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 | 377 | Matthew Wilcox <willy@infradead.org> <willy@linux.intel.com> |
| 378 | 378 | Matthew Wilcox <willy@infradead.org> <willy@parisc-linux.org> |
| 379 | 379 | Matthias Fuchs <socketcan@esd.eu> <matthias.fuchs@esd.eu> |
| 380 | +Matthieu Baerts <matttbe@kernel.org> <matthieu.baerts@tessares.net> | |
| 380 | 381 | Matthieu CASTET <castet.matthieu@free.fr> |
| 381 | 382 | Matti Vaittinen <mazziesaccount@gmail.com> <matti.vaittinen@fi.rohmeurope.com> |
| 382 | 383 | Matt Ranostay <matt.ranostay@konsulko.com> <matt@ranostay.consulting> |
| @@ -1,7 +1,7 @@ | ||
| 1 | 1 | What: /sys/class/firmware/.../data |
| 2 | 2 | Date: July 2022 |
| 3 | 3 | KernelVersion: 5.19 |
| 4 | −Contact: Russ Weight <russell.h.weight@intel.com> | |
| 4 | +Contact: Russ Weight <russ.weight@linux.dev> | |
| 5 | 5 | Description: The data sysfs file is used for firmware-fallback and for |
| 6 | 6 | firmware uploads. Cat a firmware image to this sysfs file |
| 7 | 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 | 13 | What: /sys/class/firmware/.../cancel |
| 14 | 14 | Date: July 2022 |
| 15 | 15 | KernelVersion: 5.19 |
| 16 | −Contact: Russ Weight <russell.h.weight@intel.com> | |
| 16 | +Contact: Russ Weight <russ.weight@linux.dev> | |
| 17 | 17 | Description: Write-only. For firmware uploads, write a "1" to this file to |
| 18 | 18 | request that the transfer of firmware data to the lower-level |
| 19 | 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 | 23 | What: /sys/class/firmware/.../error |
| 24 | 24 | Date: July 2022 |
| 25 | 25 | KernelVersion: 5.19 |
| 26 | −Contact: Russ Weight <russell.h.weight@intel.com> | |
| 26 | +Contact: Russ Weight <russ.weight@linux.dev> | |
| 27 | 27 | Description: Read-only. Returns a string describing a failed firmware |
| 28 | 28 | upload. This string will be in the form of <STATUS>:<ERROR>, |
| 29 | 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 | 37 | What: /sys/class/firmware/.../loading |
| 38 | 38 | Date: July 2022 |
| 39 | 39 | KernelVersion: 5.19 |
| 40 | −Contact: Russ Weight <russell.h.weight@intel.com> | |
| 40 | +Contact: Russ Weight <russ.weight@linux.dev> | |
| 41 | 41 | Description: The loading sysfs file is used for both firmware-fallback and |
| 42 | 42 | for firmware uploads. Echo 1 onto the loading file to indicate |
| 43 | 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 | 49 | What: /sys/class/firmware/.../remaining_size |
| 50 | 50 | Date: July 2022 |
| 51 | 51 | KernelVersion: 5.19 |
| 52 | −Contact: Russ Weight <russell.h.weight@intel.com> | |
| 52 | +Contact: Russ Weight <russ.weight@linux.dev> | |
| 53 | 53 | Description: Read-only. For firmware upload, this file contains the size |
| 54 | 54 | of the firmware data that remains to be transferred to the |
| 55 | 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 | 62 | What: /sys/class/firmware/.../status |
| 63 | 63 | Date: July 2022 |
| 64 | 64 | KernelVersion: 5.19 |
| 65 | −Contact: Russ Weight <russell.h.weight@intel.com> | |
| 65 | +Contact: Russ Weight <russ.weight@linux.dev> | |
| 66 | 66 | Description: Read-only. Returns a string describing the current status of |
| 67 | 67 | a firmware upload. The string will be one of the following: |
| 68 | 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 | 70 | What: /sys/class/firmware/.../timeout |
| 71 | 71 | Date: July 2022 |
| 72 | 72 | KernelVersion: 5.19 |
| 73 | −Contact: Russ Weight <russell.h.weight@intel.com> | |
| 73 | +Contact: Russ Weight <russ.weight@linux.dev> | |
| 74 | 74 | Description: This file supports the timeout mechanism for firmware |
| 75 | 75 | fallback. This file has no affect on firmware uploads. For |
| 76 | 76 | more information on timeouts please see the documentation |
| @@ -71,6 +71,8 @@ stable kernels. · 70 unmodified lines | ||
| 71 | 71 | +----------------+-----------------+-----------------+-----------------------------+ |
| 72 | 72 | | ARM | Cortex-A510 | #2658417 | ARM64_ERRATUM_2658417 | |
| 73 | 73 | +----------------+-----------------+-----------------+-----------------------------+ |
| 74 | +| ARM | Cortex-A520 | #2966298 | ARM64_ERRATUM_2966298 | | |
| 75 | ++----------------+-----------------+-----------------+-----------------------------+ | |
| 74 | 76 | | ARM | Cortex-A53 | #826319 | ARM64_ERRATUM_826319 | |
| 75 | 77 | +----------------+-----------------+-----------------+-----------------------------+ |
| 76 | 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 | 244 | time thus achieving the same ordering property as ST wq. |
| 245 | 245 | |
| 246 | 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 | 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 | 390 | scope can be changed using ``apply_workqueue_attrs()``. |
| 391 | 391 | |
| 392 | 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 | 394 | directory. |
| 395 | 395 | |
| 396 | 396 | ``affinity_scope`` |
| @@ -73,9 +73,6 @@ patternProperties: · 72 unmodified lines | ||
| 73 | 73 | "^.*@[0-9a-f]+$": |
| 74 | 74 | description: Devices attached to the bus |
| 75 | 75 | type: object |
| 76 | − properties: | |
| 77 | − reg: | |
| 78 | − maxItems: 1 | |
| 79 | 76 | |
| 80 | 77 | required: |
| 81 | 78 | - reg |
| @@ -69,7 +69,7 @@ examples: · 68 unmodified lines | ||
| 69 | 69 | - | |
| 70 | 70 | #include <dt-bindings/interrupt-controller/irq.h> |
| 71 | 71 | |
| 72 | − cache-controller@2010000 { | |
| 72 | + cache-controller@13400000 { | |
| 73 | 73 | compatible = "andestech,ax45mp-cache", "cache"; |
| 74 | 74 | reg = <0x13400000 0x100000>; |
| 75 | 75 | interrupts = <508 IRQ_TYPE_LEVEL_HIGH>; |
| @@ -87,7 +87,7 @@ required: · 86 unmodified lines | ||
| 87 | 87 | - interrupts |
| 88 | 88 | - ports |
| 89 | 89 | |
| 90 | −additionalProperties: false | |
| 90 | +unevaluatedProperties: false | |
| 91 | 91 | |
| 92 | 92 | examples: |
| 93 | 93 | - | |
| @@ -13,6 +13,8 @@ description: | · 12 unmodified lines | ||
| 13 | 13 | |
| 14 | 14 | maintainers: |
| 15 | 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 | 19 | allOf: |
| 18 | 20 | - $ref: ../dma-controller.yaml# |
| @@ -65,6 +67,7 @@ required: · 46 unmodified lines | ||
| 65 | 67 | - interrupts |
| 66 | 68 | - clocks |
| 67 | 69 | - clock-names |
| 70 | + - xlnx,bus-width | |
| 68 | 71 | |
| 69 | 72 | additionalProperties: false |
| 70 | 73 | |
| @@ -61,7 +61,7 @@ patternProperties: · 60 unmodified lines | ||
| 61 | 61 | required: |
| 62 | 62 | - reg |
| 63 | 63 | |
| 64 | − additionalProperties: true | |
| 64 | + additionalProperties: false | |
| 65 | 65 | |
| 66 | 66 | allOf: |
| 67 | 67 | - $ref: /schemas/spi/spi-peripheral-props.yaml# |
| @@ -45,5 +45,6 @@ examples: · 44 unmodified lines | ||
| 45 | 45 | light-sensor@38 { |
| 46 | 46 | compatible = "rohm,bu27010"; |
| 47 | 47 | reg = <0x38>; |
| 48 | + vdd-supply = <&vdd>; | |
| 48 | 49 | }; |
| 49 | 50 | }; |
| @@ -106,6 +106,12 @@ properties: · 105 unmodified lines | ||
| 106 | 106 | $ref: /schemas/types.yaml#/definitions/uint32 |
| 107 | 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 | 115 | msi-controller: |
| 110 | 116 | description: |
| 111 | 117 | Only present if the Message Based Interrupt functionality is |
| @@ -193,6 +199,12 @@ patternProperties: · 81 unmodified lines | ||
| 193 | 199 | compatible: |
| 194 | 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 | 208 | msi-controller: true |
| 197 | 209 | |
| 198 | 210 | "#msi-cells": |
| @@ -37,6 +37,7 @@ properties: · 36 unmodified lines | ||
| 37 | 37 | - renesas,intc-ex-r8a77990 # R-Car E3 |
| 38 | 38 | - renesas,intc-ex-r8a77995 # R-Car D3 |
| 39 | 39 | - renesas,intc-ex-r8a779a0 # R-Car V3U |
| 40 | + - renesas,intc-ex-r8a779f0 # R-Car S4-8 | |
| 40 | 41 | - renesas,intc-ex-r8a779g0 # R-Car V4H |
| 41 | 42 | - const: renesas,irqc |
| 42 | 43 | |
| @@ -19,20 +19,19 @@ description: | · 18 unmodified lines | ||
| 19 | 19 | - NMI edge select (NMI is not treated as NMI exception and supports fall edge and |
| 20 | 20 | stand-up edge detection interrupts) |
| 21 | 21 | |
| 22 | −allOf: | |
| 23 | − - $ref: /schemas/interrupt-controller.yaml# | |
| 24 | − | |
| 25 | 22 | properties: |
| 26 | 23 | compatible: |
| 27 | 24 | items: |
| 28 | 25 | - enum: |
| 26 | + - renesas,r9a07g043u-irqc # RZ/G2UL | |
| 29 | 27 | - renesas,r9a07g044-irqc # RZ/G2{L,LC} |
| 30 | 28 | - renesas,r9a07g054-irqc # RZ/V2L |
| 31 | 29 | - const: renesas,rzg2l-irqc |
| 32 | 30 | |
| 33 | 31 | '#interrupt-cells': |
| 34 | − description: The first cell should contain external interrupt number (IRQ0-7) and the | |
| 35 | − second cell is used to specify the flag. | |
| 32 | + description: The first cell should contain a macro RZG2L_{NMI,IRQX} included in the | |
| 33 | + include/dt-bindings/interrupt-controller/irqc-rzg2l.h and the second | |
| 34 | + cell is used to specify the flag. | |
| 36 | 35 | const: 2 |
| 37 | 36 | |
| 38 | 37 | '#address-cells': |
| @@ -44,7 +43,96 @@ properties: · 5 unmodified lines | ||
| 44 | 43 | maxItems: 1 |
| 45 | 44 | |
| 46 | 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 | 137 | clocks: |
| 50 | 138 | maxItems: 2 |
| @@ -72,6 +160,23 @@ required: · 21 unmodified lines | ||
| 72 | 160 | - power-domains |
| 73 | 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 | 180 | unevaluatedProperties: false |
| 76 | 181 | |
| 77 | 182 | examples: |
| @@ -80,55 +185,66 @@ examples: · 2 unmodified lines | ||
| 80 | 185 | #include <dt-bindings/clock/r9a07g044-cpg.h> |
| 81 | 186 | |
| 82 | 187 | irqc: interrupt-controller@110a0000 { |
| 83 | − compatible = "renesas,r9a07g044-irqc", "renesas,rzg2l-irqc"; | |
| 84 | − reg = <0x110a0000 0x10000>; | |
| 85 | − #interrupt-cells = <2>; | |
| 86 | − #address-cells = <0>; | |
| 87 | − interrupt-controller; | |
| 88 | − interrupts = <GIC_SPI 0 IRQ_TYPE_LEVEL_HIGH>, | |
| 89 | − <GIC_SPI 1 IRQ_TYPE_LEVEL_HIGH>, | |
| 90 | − <GIC_SPI 2 IRQ_TYPE_LEVEL_HIGH>, | |
| 91 | − <GIC_SPI 3 IRQ_TYPE_LEVEL_HIGH>, | |
| 92 | − <GIC_SPI 4 IRQ_TYPE_LEVEL_HIGH>, | |
| 93 | − <GIC_SPI 5 IRQ_TYPE_LEVEL_HIGH>, | |
| 94 | − <GIC_SPI 6 IRQ_TYPE_LEVEL_HIGH>, | |
| 95 | − <GIC_SPI 7 IRQ_TYPE_LEVEL_HIGH>, | |
| 96 | − <GIC_SPI 8 IRQ_TYPE_LEVEL_HIGH>, | |
| 97 | − <GIC_SPI 444 IRQ_TYPE_LEVEL_HIGH>, | |
| 98 | − <GIC_SPI 445 IRQ_TYPE_LEVEL_HIGH>, | |
| 99 | − <GIC_SPI 446 IRQ_TYPE_LEVEL_HIGH>, | |
| 100 | − <GIC_SPI 447 IRQ_TYPE_LEVEL_HIGH>, | |
| 101 | − <GIC_SPI 448 IRQ_TYPE_LEVEL_HIGH>, | |
| 102 | − <GIC_SPI 449 IRQ_TYPE_LEVEL_HIGH>, | |
| 103 | − <GIC_SPI 450 IRQ_TYPE_LEVEL_HIGH>, | |
| 104 | − <GIC_SPI 451 IRQ_TYPE_LEVEL_HIGH>, | |
| 105 | − <GIC_SPI 452 IRQ_TYPE_LEVEL_HIGH>, | |
| 106 | − <GIC_SPI 453 IRQ_TYPE_LEVEL_HIGH>, | |
| 107 | − <GIC_SPI 454 IRQ_TYPE_LEVEL_HIGH>, | |
| 108 | − <GIC_SPI 455 IRQ_TYPE_LEVEL_HIGH>, | |
| 109 | − <GIC_SPI 456 IRQ_TYPE_LEVEL_HIGH>, | |
| 110 | − <GIC_SPI 457 IRQ_TYPE_LEVEL_HIGH>, | |
| 111 | − <GIC_SPI 458 IRQ_TYPE_LEVEL_HIGH>, | |
| 112 | − <GIC_SPI 459 IRQ_TYPE_LEVEL_HIGH>, | |
| 113 | − <GIC_SPI 460 IRQ_TYPE_LEVEL_HIGH>, | |
| 114 | − <GIC_SPI 461 IRQ_TYPE_LEVEL_HIGH>, | |
| 115 | − <GIC_SPI 462 IRQ_TYPE_LEVEL_HIGH>, | |
| 116 | − <GIC_SPI 463 IRQ_TYPE_LEVEL_HIGH>, | |
| 117 | − <GIC_SPI 464 IRQ_TYPE_LEVEL_HIGH>, | |
| 118 | − <GIC_SPI 465 IRQ_TYPE_LEVEL_HIGH>, | |
| 119 | − <GIC_SPI 466 IRQ_TYPE_LEVEL_HIGH>, | |
| 120 | − <GIC_SPI 467 IRQ_TYPE_LEVEL_HIGH>, | |
| 121 | − <GIC_SPI 468 IRQ_TYPE_LEVEL_HIGH>, | |
| 122 | − <GIC_SPI 469 IRQ_TYPE_LEVEL_HIGH>, | |
| 123 | − <GIC_SPI 470 IRQ_TYPE_LEVEL_HIGH>, | |
| 124 | − <GIC_SPI 471 IRQ_TYPE_LEVEL_HIGH>, | |
| 125 | − <GIC_SPI 472 IRQ_TYPE_LEVEL_HIGH>, | |
| 126 | − <GIC_SPI 473 IRQ_TYPE_LEVEL_HIGH>, | |
| 127 | − <GIC_SPI 474 IRQ_TYPE_LEVEL_HIGH>, | |
| 128 | − <GIC_SPI 475 IRQ_TYPE_LEVEL_HIGH>; | |
| 129 | − clocks = <&cpg CPG_MOD R9A07G044_IA55_CLK>, | |
| 130 | − <&cpg CPG_MOD R9A07G044_IA55_PCLK>; | |
| 131 | − clock-names = "clk", "pclk"; | |
| 132 | − power-domains = <&cpg>; | |
| 133 | − resets = <&cpg R9A07G044_IA55_RESETN>; | |
| 188 | + compatible = "renesas,r9a07g044-irqc", "renesas,rzg2l-irqc"; | |
| 189 | + reg = <0x110a0000 0x10000>; | |
| 190 | + #interrupt-cells = <2>; | |
| 191 | + #address-cells = <0>; | |
| 192 | + interrupt-controller; | |
| 193 | + interrupts = <GIC_SPI 0 IRQ_TYPE_LEVEL_HIGH>, | |
| 194 | + <GIC_SPI 1 IRQ_TYPE_LEVEL_HIGH>, | |
| 195 | + <GIC_SPI 2 IRQ_TYPE_LEVEL_HIGH>, | |
| 196 | + <GIC_SPI 3 IRQ_TYPE_LEVEL_HIGH>, | |
| 197 | + <GIC_SPI 4 IRQ_TYPE_LEVEL_HIGH>, | |
| 198 | + <GIC_SPI 5 IRQ_TYPE_LEVEL_HIGH>, | |
| 199 | + <GIC_SPI 6 IRQ_TYPE_LEVEL_HIGH>, | |
| 200 | + <GIC_SPI 7 IRQ_TYPE_LEVEL_HIGH>, | |
| 201 | + <GIC_SPI 8 IRQ_TYPE_LEVEL_HIGH>, | |
| 202 | + <GIC_SPI 444 IRQ_TYPE_LEVEL_HIGH>, | |
| 203 | + <GIC_SPI 445 IRQ_TYPE_LEVEL_HIGH>, | |
| 204 | + <GIC_SPI 446 IRQ_TYPE_LEVEL_HIGH>, | |
| 205 | + <GIC_SPI 447 IRQ_TYPE_LEVEL_HIGH>, | |
| 206 | + <GIC_SPI 448 IRQ_TYPE_LEVEL_HIGH>, | |
| 207 | + <GIC_SPI 449 IRQ_TYPE_LEVEL_HIGH>, | |
| 208 | + <GIC_SPI 450 IRQ_TYPE_LEVEL_HIGH>, | |
| 209 | + <GIC_SPI 451 IRQ_TYPE_LEVEL_HIGH>, | |
| 210 | + <GIC_SPI 452 IRQ_TYPE_LEVEL_HIGH>, | |
| 211 | + <GIC_SPI 453 IRQ_TYPE_LEVEL_HIGH>, | |
| 212 | + <GIC_SPI 454 IRQ_TYPE_LEVEL_HIGH>, | |
| 213 | + <GIC_SPI 455 IRQ_TYPE_LEVEL_HIGH>, | |
| 214 | + <GIC_SPI 456 IRQ_TYPE_LEVEL_HIGH>, | |
| 215 | + <GIC_SPI 457 IRQ_TYPE_LEVEL_HIGH>, | |
| 216 | + <GIC_SPI 458 IRQ_TYPE_LEVEL_HIGH>, | |
| 217 | + <GIC_SPI 459 IRQ_TYPE_LEVEL_HIGH>, | |
| 218 | + <GIC_SPI 460 IRQ_TYPE_LEVEL_HIGH>, | |
| 219 | + <GIC_SPI 461 IRQ_TYPE_LEVEL_HIGH>, | |
| 220 | + <GIC_SPI 462 IRQ_TYPE_LEVEL_HIGH>, | |
| 221 | + <GIC_SPI 463 IRQ_TYPE_LEVEL_HIGH>, | |
| 222 | + <GIC_SPI 464 IRQ_TYPE_LEVEL_HIGH>, | |
| 223 | + <GIC_SPI 465 IRQ_TYPE_LEVEL_HIGH>, | |
| 224 | + <GIC_SPI 466 IRQ_TYPE_LEVEL_HIGH>, | |
| 225 | + <GIC_SPI 467 IRQ_TYPE_LEVEL_HIGH>, | |
| 226 | + <GIC_SPI 468 IRQ_TYPE_LEVEL_HIGH>, | |
| 227 | + <GIC_SPI 469 IRQ_TYPE_LEVEL_HIGH>, | |
| 228 | + <GIC_SPI 470 IRQ_TYPE_LEVEL_HIGH>, | |
| 229 | + <GIC_SPI 471 IRQ_TYPE_LEVEL_HIGH>, | |
| 230 | + <GIC_SPI 472 IRQ_TYPE_LEVEL_HIGH>, | |
| 231 | + <GIC_SPI 473 IRQ_TYPE_LEVEL_HIGH>, | |
| 232 | + <GIC_SPI 474 IRQ_TYPE_LEVEL_HIGH>, | |
| 233 | + <GIC_SPI 475 IRQ_TYPE_LEVEL_HIGH>; | |
| 234 | + interrupt-names = "nmi", | |
| 235 | + "irq0", "irq1", "irq2", "irq3", | |
| 236 | + "irq4", "irq5", "irq6", "irq7", | |
| 237 | + "tint0", "tint1", "tint2", "tint3", | |
| 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 | 270 | contains: |
| 271 | 271 | enum: |
| 272 | 272 | - qcom,msm8998-smmu-v2 |
| 273 | + - qcom,sdm630-smmu-v2 | |
| 273 | 274 | then: |
| 274 | 275 | anyOf: |
| 275 | 276 | - properties: |
| @@ -311,7 +312,6 @@ allOf: · 35 unmodified lines | ||
| 311 | 312 | compatible: |
| 312 | 313 | contains: |
| 313 | 314 | enum: |
| 314 | − - qcom,sdm630-smmu-v2 | |
| 315 | 315 | - qcom,sm6375-smmu-v2 |
| 316 | 316 | then: |
| 317 | 317 | anyOf: |
| @@ -54,6 +54,7 @@ properties: · 53 unmodified lines | ||
| 54 | 54 | |
| 55 | 55 | port: |
| 56 | 56 | $ref: /schemas/graph.yaml#/$defs/port-base |
| 57 | + unevaluatedProperties: false | |
| 57 | 58 | |
| 58 | 59 | properties: |
| 59 | 60 | endpoint: |
| @@ -69,6 +69,7 @@ properties: · 68 unmodified lines | ||
| 69 | 69 | properties: |
| 70 | 70 | port@0: |
| 71 | 71 | $ref: /schemas/graph.yaml#/$defs/port-base |
| 72 | + unevaluatedProperties: false | |
| 72 | 73 | description: Input port |
| 73 | 74 | |
| 74 | 75 | properties: |
| @@ -89,6 +90,7 @@ properties: · 14 unmodified lines | ||
| 89 | 90 | |
| 90 | 91 | port@1: |
| 91 | 92 | $ref: /schemas/graph.yaml#/$defs/port-base |
| 93 | + unevaluatedProperties: false | |
| 92 | 94 | description: Output port |
| 93 | 95 | |
| 94 | 96 | properties: |
| @@ -59,7 +59,6 @@ allOf: · 58 unmodified lines | ||
| 59 | 59 | compatible: |
| 60 | 60 | contains: |
| 61 | 61 | enum: |
| 62 | − - fsl,imx8mq-csi | |
| 63 | 62 | - fsl,imx8mm-csi |
| 64 | 63 | then: |
| 65 | 64 | required: |
| @@ -95,7 +95,7 @@ properties: · 94 unmodified lines | ||
| 95 | 95 | synchronization is selected. |
| 96 | 96 | default: 1 |
| 97 | 97 | |
| 98 | − field-active-even: true | |
| 98 | + field-even-active: true | |
| 99 | 99 | |
| 100 | 100 | bus-width: true |
| 101 | 101 | |
| @@ -144,7 +144,7 @@ properties: · 42 unmodified lines | ||
| 144 | 144 | synchronization is selected. |
| 145 | 145 | default: 1 |
| 146 | 146 | |
| 147 | − field-active-even: true | |
| 147 | + field-even-active: true | |
| 148 | 148 | |
| 149 | 149 | bus-width: true |
| 150 | 150 | |
| @@ -57,6 +57,7 @@ properties: · 56 unmodified lines | ||
| 57 | 57 | patternProperties: |
| 58 | 58 | "^port@[01]$": |
| 59 | 59 | $ref: /schemas/graph.yaml#/$defs/port-base |
| 60 | + unevaluatedProperties: false | |
| 60 | 61 | description: |
| 61 | 62 | Camera A and camera B inputs. |
| 62 | 63 | |
| @@ -31,10 +31,6 @@ properties: · 30 unmodified lines | ||
| 31 | 31 | charger: |
| 32 | 32 | $ref: /schemas/power/supply/maxim,max77693.yaml |
| 33 | 33 | |
| 34 | − connector: | |
| 35 | − $ref: /schemas/connector/usb-connector.yaml# | |
| 36 | − unevaluatedProperties: false | |
| 37 | − | |
| 38 | 34 | led: |
| 39 | 35 | $ref: /schemas/leds/maxim,max77693.yaml |
| 40 | 36 | |
| @@ -12,7 +12,6 @@ maintainers: · 11 unmodified lines | ||
| 12 | 12 | |
| 13 | 13 | allOf: |
| 14 | 14 | - $ref: /schemas/pci/pci-bus.yaml# |
| 15 | − - $ref: /schemas/interrupt-controller/msi-controller.yaml# | |
| 16 | 15 | |
| 17 | 16 | properties: |
| 18 | 17 | compatible: |
| @@ -34,13 +33,6 @@ properties: · 15 unmodified lines | ||
| 34 | 33 | description: > |
| 35 | 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 | 36 | ranges: |
| 45 | 37 | minItems: 1 |
| 46 | 38 | maxItems: 2 |
| @@ -54,16 +46,8 @@ properties: · 7 unmodified lines | ||
| 54 | 46 | items: |
| 55 | 47 | - const: pcie-phy |
| 56 | 48 | |
| 57 | − bus-range: true | |
| 58 | − | |
| 59 | 49 | dma-coherent: true |
| 60 | 50 | |
| 61 | − "#address-cells": true | |
| 62 | − | |
| 63 | − "#size-cells": true | |
| 64 | − | |
| 65 | − device_type: true | |
| 66 | − | |
| 67 | 51 | brcm,pcie-ob: |
| 68 | 52 | type: boolean |
| 69 | 53 | description: > |
| @@ -78,20 +62,24 @@ properties: · 8 unmodified lines | ||
| 78 | 62 | |
| 79 | 63 | msi: |
| 80 | 64 | type: object |
| 65 | + $ref: /schemas/interrupt-controller/msi-controller.yaml# | |
| 66 | + unevaluatedProperties: false | |
| 67 | + | |
| 81 | 68 | properties: |
| 82 | 69 | compatible: |
| 83 | 70 | items: |
| 84 | 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: | |
| 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 | |
| 82 | + msi-parent: true | |
| 95 | 83 | |
| 96 | 84 | dependencies: |
| 97 | 85 | brcm,pcie-ob-axi-offset: ["brcm,pcie-ob"] |
| @@ -117,68 +105,69 @@ unevaluatedProperties: false · 19 unmodified lines | ||
| 117 | 105 | |
| 118 | 106 | examples: |
| 119 | 107 | - | |
| 120 | − #include <dt-bindings/interrupt-controller/arm-gic.h> | |
| 121 | − | |
| 122 | − bus { | |
| 123 | − #address-cells = <1>; | |
| 124 | − #size-cells = <1>; | |
| 125 | − pcie0: pcie@18012000 { | |
| 126 | − compatible = "brcm,iproc-pcie"; | |
| 127 | − reg = <0x18012000 0x1000>; | |
| 128 | − | |
| 129 | − #interrupt-cells = <1>; | |
| 130 | − interrupt-map-mask = <0 0 0 0>; | |
| 131 | − interrupt-map = <0 0 0 0 &gic GIC_SPI 100 IRQ_TYPE_NONE>; | |
| 132 | − | |
| 133 | − linux,pci-domain = <0>; | |
| 134 | − | |
| 135 | − bus-range = <0x00 0xff>; | |
| 136 | − | |
| 137 | − #address-cells = <3>; | |
| 138 | − #size-cells = <2>; | |
| 139 | − device_type = "pci"; | |
| 140 | − ranges = <0x81000000 0 0 0x28000000 0 0x00010000>, | |
| 141 | − <0x82000000 0 0x20000000 0x20000000 0 0x04000000>; | |
| 142 | − | |
| 143 | − phys = <&phy 0 5>; | |
| 144 | − phy-names = "pcie-phy"; | |
| 145 | − | |
| 146 | − brcm,pcie-ob; | |
| 147 | − brcm,pcie-ob-axi-offset = <0x00000000>; | |
| 148 | − | |
| 149 | − msi-parent = <&msi0>; | |
| 150 | − | |
| 151 | − /* iProc event queue based MSI */ | |
| 152 | − msi0: msi { | |
| 153 | − compatible = "brcm,iproc-msi"; | |
| 154 | − msi-controller; | |
| 155 | − interrupt-parent = <&gic>; | |
| 156 | − interrupts = <GIC_SPI 96 IRQ_TYPE_NONE>, | |
| 157 | − <GIC_SPI 97 IRQ_TYPE_NONE>, | |
| 158 | − <GIC_SPI 98 IRQ_TYPE_NONE>, | |
| 159 | − <GIC_SPI 99 IRQ_TYPE_NONE>; | |
| 160 | − }; | |
| 161 | − }; | |
| 162 | − | |
| 163 | − pcie1: pcie@18013000 { | |
| 164 | − compatible = "brcm,iproc-pcie"; | |
| 165 | − reg = <0x18013000 0x1000>; | |
| 166 | − | |
| 167 | − #interrupt-cells = <1>; | |
| 168 | − interrupt-map-mask = <0 0 0 0>; | |
| 169 | − interrupt-map = <0 0 0 0 &gic GIC_SPI 106 IRQ_TYPE_NONE>; | |
| 170 | − | |
| 171 | − linux,pci-domain = <1>; | |
| 172 | − | |
| 173 | − bus-range = <0x00 0xff>; | |
| 174 | − | |
| 175 | − #address-cells = <3>; | |
| 176 | − #size-cells = <2>; | |
| 177 | − device_type = "pci"; | |
| 178 | − ranges = <0x81000000 0 0 0x48000000 0 0x00010000>, | |
| 179 | − <0x82000000 0 0x40000000 0x40000000 0 0x04000000>; | |
| 180 | − | |
| 181 | − phys = <&phy 1 6>; | |
| 182 | − phy-names = "pcie-phy"; | |
| 183 | − }; | |
| 108 | + #include <dt-bindings/interrupt-controller/arm-gic.h> | |
| 109 | + | |
| 110 | + gic: interrupt-controller { | |
| 111 | + interrupt-controller; | |
| 112 | + #interrupt-cells = <3>; | |
| 113 | + }; | |
| 114 | + | |
| 115 | + pcie@18012000 { | |
| 116 | + compatible = "brcm,iproc-pcie"; | |
| 117 | + reg = <0x18012000 0x1000>; | |
| 118 | + | |
| 119 | + #interrupt-cells = <1>; | |
| 120 | + interrupt-map-mask = <0 0 0 0>; | |
| 121 | + interrupt-map = <0 0 0 0 &gic GIC_SPI 100 IRQ_TYPE_NONE>; | |
| 122 | + | |
| 123 | + linux,pci-domain = <0>; | |
| 124 | + | |
| 125 | + bus-range = <0x00 0xff>; | |
| 126 | + | |
| 127 | + #address-cells = <3>; | |
| 128 | + #size-cells = <2>; | |
| 129 | + device_type = "pci"; | |
| 130 | + ranges = <0x81000000 0 0 0x28000000 0 0x00010000>, | |
| 131 | + <0x82000000 0 0x20000000 0x20000000 0 0x04000000>; | |
| 132 | + | |
| 133 | + phys = <&phy 0 5>; | |
| 134 | + phy-names = "pcie-phy"; | |
| 135 | + | |
| 136 | + brcm,pcie-ob; | |
| 137 | + brcm,pcie-ob-axi-offset = <0x00000000>; | |
| 138 | + | |
| 139 | + msi-parent = <&msi0>; | |
| 140 | + | |
| 141 | + /* iProc event queue based MSI */ | |
| 142 | + msi0: msi { | |
| 143 | + compatible = "brcm,iproc-msi"; | |
| 144 | + msi-controller; | |
| 145 | + interrupt-parent = <&gic>; | |
| 146 | + interrupts = <GIC_SPI 96 IRQ_TYPE_NONE>, | |
| 147 | + <GIC_SPI 97 IRQ_TYPE_NONE>, | |
| 148 | + <GIC_SPI 98 IRQ_TYPE_NONE>, | |
| 149 | + <GIC_SPI 99 IRQ_TYPE_NONE>; | |
| 150 | + }; | |
| 151 | + }; | |
| 152 | + - | | |
| 153 | + pcie@18013000 { | |
| 154 | + compatible = "brcm,iproc-pcie"; | |
| 155 | + reg = <0x18013000 0x1000>; | |
| 156 | + | |
| 157 | + #interrupt-cells = <1>; | |
| 158 | + interrupt-map-mask = <0 0 0 0>; | |
| 159 | + interrupt-map = <0 0 0 0 &gic GIC_SPI 106 IRQ_TYPE_NONE>; | |
| 160 | + | |
| 161 | + linux,pci-domain = <1>; | |
| 162 | + | |
| 163 | + bus-range = <0x00 0xff>; | |
| 164 | + | |
| 165 | + #address-cells = <3>; | |
| 166 | + #size-cells = <2>; | |
| 167 | + device_type = "pci"; | |
| 168 | + ranges = <0x81000000 0 0 0x48000000 0 0x00010000>, | |
| 169 | + <0x82000000 0 0x40000000 0x40000000 0 0x04000000>; | |
| 170 | + | |
| 171 | + phys = <&phy 1 6>; | |
| 172 | + phy-names = "pcie-phy"; | |
| 184 | 173 | }; |
| @@ -91,6 +91,7 @@ properties: · 90 unmodified lines | ||
| 91 | 91 | |
| 92 | 92 | interrupt-controller: |
| 93 | 93 | type: object |
| 94 | + additionalProperties: false | |
| 94 | 95 | description: Describes the CPU's local interrupt controller |
| 95 | 96 | |
| 96 | 97 | properties: |
| @@ -56,6 +56,9 @@ properties: · 55 unmodified lines | ||
| 56 | 56 | - const: clkext3 |
| 57 | 57 | minItems: 2 |
| 58 | 58 | |
| 59 | + "#sound-dai-cells": | |
| 60 | + const: 0 | |
| 61 | + | |
| 59 | 62 | required: |
| 60 | 63 | - compatible |
| 61 | 64 | - reg |
| @@ -26,6 +26,7 @@ properties: · 25 unmodified lines | ||
| 26 | 26 | - const: rockchip,rk3568-spdif |
| 27 | 27 | - items: |
| 28 | 28 | - enum: |
| 29 | + - rockchip,rk3128-spdif | |
| 29 | 30 | - rockchip,rk3188-spdif |
| 30 | 31 | - rockchip,rk3288-spdif |
| 31 | 32 | - rockchip,rk3308-spdif |
| @@ -232,7 +232,7 @@ properties: · 231 unmodified lines | ||
| 232 | 232 | # MEMSIC magnetometer |
| 233 | 233 | - memsic,mmc35240 |
| 234 | 234 | # MEMSIC 3-axis accelerometer |
| 235 | − - memsic,mx4005 | |
| 235 | + - memsic,mxc4005 | |
| 236 | 236 | # MEMSIC 2-axis 8-bit digital accelerometer |
| 237 | 237 | - memsic,mxc6225 |
| 238 | 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 | 59 | - Support extended attributes as an option; |
| 60 | 60 | |
| 61 | + - Support a bloom filter that speeds up negative extended attribute lookups; | |
| 62 | + | |
| 61 | 63 | - Support POSIX.1e ACLs by using extended attributes; |
| 62 | 64 | |
| 63 | 65 | - Support transparent data compression as an option: |
| 64 | − LZ4 and MicroLZMA algorithms can be used on a per-file basis; In addition, | |
| 65 | − inplace decompression is also supported to avoid bounce compressed buffers | |
| 66 | − and page cache thrashing. | |
| 66 | + LZ4, MicroLZMA and DEFLATE algorithms can be used on a per-file basis; In | |
| 67 | + addition, inplace decompression is also supported to avoid bounce compressed | |
| 68 | + buffers and unnecessary page cache thrashing. | |
| 67 | 69 | |
| 68 | 70 | - Support chunk-based data deduplication and rolling-hash compressed data |
| 69 | 71 | deduplication; |
| @@ -268,6 +270,38 @@ details.) · 198 unmodified lines | ||
| 268 | 270 | |
| 269 | 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 | 305 | Data compression |
| 272 | 306 | ---------------- |
| 273 | 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 | 339 | rightmost one and going left. In the above example lower1 will be the |
| 340 | 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 | 355 | Metadata only copy up |
| 344 | 356 | --------------------- |
| @@ -25,15 +25,15 @@ Contact · 24 unmodified lines | ||
| 25 | 25 | The Linux kernel hardware security team is separate from the regular Linux |
| 26 | 26 | kernel security team. |
| 27 | 27 | |
| 28 | −The team only handles the coordination of embargoed hardware security | |
| 29 | −issues. Reports of pure software security bugs in the Linux kernel are not | |
| 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 | |
| 30 | 30 | handled by this team and the reporter will be guided to contact the regular |
| 31 | 31 | Linux kernel security team (:ref:`Documentation/admin-guide/ |
| 32 | 32 | <securitybugs>`) instead. |
| 33 | 33 | |
| 34 | 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 | |
| 36 | −issue according to our documented process. | |
| 35 | +is a private list of security officers who will help you to coordinate a | |
| 36 | +fix according to our documented process. | |
| 37 | 37 | |
| 38 | 38 | The list is encrypted and email to the list can be sent by either PGP or |
| 39 | 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 | 133 | The hardware security team will provide an incident-specific encrypted |
| 134 | 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 | 137 | The hardware security team will provide the disclosing party a list of |
| 138 | 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 | 140 | Memorandum of Understanding and the documented process. These developers |
| 141 | 141 | form the initial response team and will be responsible for handling the |
| 142 | 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 | 209 | After acknowledgement or resolution of an objection the expert is disclosed |
| 210 | 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 | 217 | Coordinated release |
| 214 | 218 | """"""""""""""""""" |
| 215 | 219 | |
| 216 | 220 | The involved parties will negotiate the date and time where the embargo |
| 217 | 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 | 225 | While we understand that hardware security issues need coordinated embargo |
| 221 | 226 | time, the embargo time should be constrained to the minimum time which is |
| @@ -36,11 +36,11 @@ EXAMPLE · 35 unmodified lines | ||
| 36 | 36 | In the example below, **rtla timerlat hist** is set to run for *10* minutes, |
| 37 | 37 | in the cpus *0-4*, *skipping zero* only lines. Moreover, **rtla timerlat |
| 38 | 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 | 40 | *1ms* period is also passed to the *timerlat* tracer. Auto-analysis is disabled |
| 41 | 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 | 44 | # RTLA timerlat histogram |
| 45 | 45 | # Time unit is microseconds (us) |
| 46 | 46 | # Duration: 0 00:10:00 |
| @@ -202,7 +202,7 @@ workqueue将自动创建与属性相匹配的后备工作者池。调节并发 · 201 unmodified lines | ||
| 202 | 202 | 同的排序属性。 |
| 203 | 203 | |
| 204 | 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 | 470 | ADM8211 WIRELESS DRIVER |
| 471 | 471 | L: linux-wireless@vger.kernel.org |
| 472 | 472 | S: Orphan |
| 473 | −W: https://wireless.wiki.kernel.org/ | |
| 474 | 473 | F: drivers/net/wireless/admtek/adm8211.* |
| 475 | 474 | |
| 476 | 475 | ADP1653 FLASH CONTROLLER DRIVER |
| @@ -1585,6 +1584,17 @@ F: arch/arm/include/asm/arch_timer.h · 1108 unmodified lines | ||
| 1585 | 1584 | F: arch/arm64/include/asm/arch_timer.h |
| 1586 | 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 | 1598 | ARM HDLCD DRM DRIVER |
| 1589 | 1599 | M: Liviu Dudau <liviu.dudau@arm.com> |
| 1590 | 1600 | S: Supported |
| @@ -2211,21 +2221,28 @@ F: arch/arm/boot/dts/ti/omap/omap3-igep* · 620 unmodified lines | ||
| 2211 | 2221 | ARM/INTEL IXP4XX ARM ARCHITECTURE |
| 2212 | 2222 | M: Linus Walleij <linusw@kernel.org> |
| 2213 | 2223 | M: Imre Kaloz <kaloz@openwrt.org> |
| 2214 | −M: Krzysztof Halasa <khalasa@piap.pl> | |
| 2215 | 2224 | L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) |
| 2216 | 2225 | S: Maintained |
| 2217 | 2226 | F: Documentation/devicetree/bindings/arm/intel-ixp4xx.yaml |
| 2218 | 2227 | F: Documentation/devicetree/bindings/gpio/intel,ixp4xx-gpio.txt |
| 2219 | 2228 | F: Documentation/devicetree/bindings/interrupt-controller/intel,ixp4xx-interrupt.yaml |
| 2220 | 2229 | F: Documentation/devicetree/bindings/memory-controllers/intel,ixp4xx-expansion* |
| 2230 | +F: Documentation/devicetree/bindings/rng/intel,ixp46x-rng.yaml | |
| 2221 | 2231 | F: Documentation/devicetree/bindings/timer/intel,ixp4xx-timer.yaml |
| 2222 | 2232 | F: arch/arm/boot/dts/intel/ixp/ |
| 2223 | 2233 | F: arch/arm/mach-ixp4xx/ |
| 2224 | 2234 | F: drivers/bus/intel-ixp4xx-eb.c |
| 2235 | +F: drivers/char/hw_random/ixp4xx-rng.c | |
| 2225 | 2236 | F: drivers/clocksource/timer-ixp4xx.c |
| 2226 | 2237 | F: drivers/crypto/intel/ixp4xx/ixp4xx_crypto.c |
| 2227 | 2238 | F: drivers/gpio/gpio-ixp4xx.c |
| 2228 | 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 | 2247 | ARM/INTEL KEEMBAY ARCHITECTURE |
| 2231 | 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 | 2345 | ARM/Mediatek SoC support |
| 2329 | 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 | 2348 | L: linux-kernel@vger.kernel.org |
| 2332 | 2349 | L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) |
| 2333 | 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 | 6002 | DEVICE-MAPPER (LVM) |
| 5986 | 6003 | M: Alasdair Kergon <agk@redhat.com> |
| 5987 | 6004 | M: Mike Snitzer <snitzer@kernel.org> |
| 5988 | −M: dm-devel@redhat.com | |
| 5989 | −L: dm-devel@redhat.com | |
| 6005 | +M: dm-devel@lists.linux.dev | |
| 6006 | +L: dm-devel@lists.linux.dev | |
| 5990 | 6007 | S: Maintained |
| 5991 | 6008 | W: http://sources.redhat.com/dm |
| 5992 | 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 | 8111 | FIRMWARE LOADER (request_firmware) |
| 8095 | 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 | 8114 | L: linux-kernel@vger.kernel.org |
| 8098 | 8115 | S: Maintained |
| 8099 | 8116 | F: Documentation/firmware_class/ |
| @@ -9531,10 +9548,8 @@ F: Documentation/devicetree/bindings/iio/pressure/honeywell,mprls0025pa.yaml · 1431 unmodified lines | ||
| 9531 | 9548 | F: drivers/iio/pressure/mprls0025pa.c |
| 9532 | 9549 | |
| 9533 | 9550 | HOST AP DRIVER |
| 9534 | −M: Jouni Malinen <j@w1.fi> | |
| 9535 | 9551 | L: linux-wireless@vger.kernel.org |
| 9536 | 9552 | S: Obsolete |
| 9537 | −W: http://w1.fi/hostap-driver.html | |
| 9538 | 9553 | F: drivers/net/wireless/intersil/hostap/ |
| 9539 | 9554 | |
| 9540 | 9555 | HP BIOSCFG DRIVER |
| @@ -10622,22 +10637,6 @@ L: linux-crypto@vger.kernel.org · 1081 unmodified lines | ||
| 10622 | 10637 | S: Maintained |
| 10623 | 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 | 10640 | INTEL KEEM BAY DRM DRIVER |
| 10642 | 10641 | M: Anitha Chrisanthus <anitha.chrisanthus@intel.com> |
| 10643 | 10642 | M: Edmund Dea <edmund.j.dea@intel.com> |
| @@ -11063,7 +11062,7 @@ F: Documentation/devicetree/bindings/sound/irondevice,* · 419 unmodified lines | ||
| 11063 | 11062 | F: sound/soc/codecs/sma* |
| 11064 | 11063 | |
| 11065 | 11064 | IRQ DOMAINS (IRQ NUMBER MAPPING LIBRARY) |
| 11066 | −M: Marc Zyngier <maz@kernel.org> | |
| 11065 | +M: Thomas Gleixner <tglx@linutronix.de> | |
| 11067 | 11066 | S: Maintained |
| 11068 | 11067 | T: git git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip.git irq/core |
| 11069 | 11068 | F: Documentation/core-api/irq/irq-domain.rst |
| @@ -11082,7 +11081,6 @@ F: lib/group_cpus.c · 12 unmodified lines | ||
| 11082 | 11081 | |
| 11083 | 11082 | IRQCHIP DRIVERS |
| 11084 | 11083 | M: Thomas Gleixner <tglx@linutronix.de> |
| 11085 | −M: Marc Zyngier <maz@kernel.org> | |
| 11086 | 11084 | L: linux-kernel@vger.kernel.org |
| 11087 | 11085 | S: Maintained |
| 11088 | 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 | 14945 | K: \bmdo_ |
| 14948 | 14946 | |
| 14949 | 14947 | NETWORKING [MPTCP] |
| 14950 | −M: Matthieu Baerts <matthieu.baerts@tessares.net> | |
| 14948 | +M: Matthieu Baerts <matttbe@kernel.org> | |
| 14951 | 14949 | M: Mat Martineau <martineau@kernel.org> |
| 14952 | 14950 | L: netdev@vger.kernel.org |
| 14953 | 14951 | L: mptcp@lists.linux.dev |
| @@ -17602,6 +17600,7 @@ M: Kalle Valo <kvalo@kernel.org> · 2648 unmodified lines | ||
| 17602 | 17600 | M: Jeff Johnson <quic_jjohnson@quicinc.com> |
| 17603 | 17601 | L: ath12k@lists.infradead.org |
| 17604 | 17602 | S: Supported |
| 17603 | +W: https://wireless.wiki.kernel.org/en/users/Drivers/ath12k | |
| 17605 | 17604 | T: git git://git.kernel.org/pub/scm/linux/kernel/git/kvalo/ath.git |
| 17606 | 17605 | F: drivers/net/wireless/ath/ath12k/ |
| 17607 | 17606 | |
| @@ -18132,8 +18131,6 @@ REALTEK WIRELESS DRIVER (rtlwifi family) · 524 unmodified lines | ||
| 18132 | 18131 | M: Ping-Ke Shih <pkshih@realtek.com> |
| 18133 | 18132 | L: linux-wireless@vger.kernel.org |
| 18134 | 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 | 18134 | F: drivers/net/wireless/realtek/rtlwifi/ |
| 18138 | 18135 | |
| 18139 | 18136 | REALTEK WIRELESS DRIVER (rtw88) |
| @@ -18661,7 +18658,6 @@ F: drivers/media/dvb-frontends/rtl2832_sdr* · 521 unmodified lines | ||
| 18661 | 18658 | RTL8180 WIRELESS DRIVER |
| 18662 | 18659 | L: linux-wireless@vger.kernel.org |
| 18663 | 18660 | S: Orphan |
| 18664 | −W: https://wireless.wiki.kernel.org/ | |
| 18665 | 18661 | F: drivers/net/wireless/realtek/rtl818x/rtl8180/ |
| 18666 | 18662 | |
| 18667 | 18663 | RTL8187 WIRELESS DRIVER |
| @@ -18669,14 +18665,12 @@ M: Hin-Tak Leung <hintak.leung@gmail.com> · 1 unmodified line | ||
| 18669 | 18665 | M: Larry Finger <Larry.Finger@lwfinger.net> |
| 18670 | 18666 | L: linux-wireless@vger.kernel.org |
| 18671 | 18667 | S: Maintained |
| 18672 | −W: https://wireless.wiki.kernel.org/ | |
| 18673 | 18668 | F: drivers/net/wireless/realtek/rtl818x/rtl8187/ |
| 18674 | 18669 | |
| 18675 | 18670 | RTL8XXXU WIRELESS DRIVER (rtl8xxxu) |
| 18676 | 18671 | M: Jes Sorensen <Jes.Sorensen@gmail.com> |
| 18677 | 18672 | L: linux-wireless@vger.kernel.org |
| 18678 | 18673 | S: Maintained |
| 18679 | −T: git git://git.kernel.org/pub/scm/linux/kernel/git/jes/linux.git rtl8xxxu-devel | |
| 18680 | 18674 | F: drivers/net/wireless/realtek/rtl8xxxu/ |
| 18681 | 18675 | |
| 18682 | 18676 | RTRS TRANSPORT DRIVERS |
| @@ -20490,6 +20484,7 @@ F: include/dt-bindings/clock/starfive?jh71*.h · 1807 unmodified lines | ||
| 20490 | 20484 | STARFIVE JH71X0 PINCTRL DRIVERS |
| 20491 | 20485 | M: Emil Renner Berthing <kernel@esmil.dk> |
| 20492 | 20486 | M: Jianlong Huang <jianlong.huang@starfivetech.com> |
| 20487 | +M: Hal Feng <hal.feng@starfivetech.com> | |
| 20493 | 20488 | L: linux-gpio@vger.kernel.org |
| 20494 | 20489 | S: Maintained |
| 20495 | 20490 | F: Documentation/devicetree/bindings/pinctrl/starfive,jh71*.yaml |
| @@ -21658,7 +21653,6 @@ L: linux-wireless@vger.kernel.org · 1162 unmodified lines | ||
| 21658 | 21653 | S: Orphan |
| 21659 | 21654 | W: https://wireless.wiki.kernel.org/en/users/Drivers/wl12xx |
| 21660 | 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 | 21656 | F: drivers/net/wireless/ti/ |
| 21663 | 21657 | |
| 21664 | 21658 | TIMEKEEPING, CLOCKSOURCE CORE, NTP, ALARMTIMER |
| @@ -2,7 +2,7 @@ · 1 unmodified line | ||
| 2 | 2 | VERSION = 6 |
| 3 | 3 | PATCHLEVEL = 6 |
| 4 | 4 | SUBLEVEL = 0 |
| 5 | −EXTRAVERSION = -rc4 | |
| 5 | +EXTRAVERSION = -rc6 | |
| 6 | 6 | NAME = Hurr durr I'ma ninja sloth |
| 7 | 7 | |
| 8 | 8 | # *DOCUMENTATION* |
| @@ -1037,6 +1037,19 @@ config ARM64_ERRATUM_2645198 · 1036 unmodified lines | ||
| 1037 | 1037 | |
| 1038 | 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 | 1053 | config CAVIUM_ERRATUM_22375 |
| 1041 | 1054 | bool "Cavium erratum 22375, 24313" |
| 1042 | 1055 | default y |
| @@ -185,7 +185,7 @@ · 184 unmodified lines | ||
| 185 | 185 | #size-cells = <1>; |
| 186 | 186 | ranges; |
| 187 | 187 | |
| 188 | − anomix_ns_gpr: syscon@44210000 { | |
| 188 | + aonmix_ns_gpr: syscon@44210000 { | |
| 189 | 189 | compatible = "fsl,imx93-aonmix-ns-syscfg", "syscon"; |
| 190 | 190 | reg = <0x44210000 0x1000>; |
| 191 | 191 | }; |
| @@ -319,6 +319,7 @@ · 127 unmodified lines | ||
| 319 | 319 | assigned-clock-parents = <&clk IMX93_CLK_SYS_PLL_PFD1_DIV2>; |
| 320 | 320 | assigned-clock-rates = <40000000>; |
| 321 | 321 | fsl,clk-source = /bits/ 8 <0>; |
| 322 | + fsl,stop-mode = <&aonmix_ns_gpr 0x14 0>; | |
| 322 | 323 | status = "disabled"; |
| 323 | 324 | }; |
| 324 | 325 | |
| @@ -591,6 +592,7 @@ · 266 unmodified lines | ||
| 591 | 592 | assigned-clock-parents = <&clk IMX93_CLK_SYS_PLL_PFD1_DIV2>; |
| 592 | 593 | assigned-clock-rates = <40000000>; |
| 593 | 594 | fsl,clk-source = /bits/ 8 <0>; |
| 595 | + fsl,stop-mode = <&wakeupmix_gpr 0x0c 2>; | |
| 594 | 596 | status = "disabled"; |
| 595 | 597 | }; |
| 596 | 598 | |
| @@ -905,7 +905,7 @@ · 904 unmodified lines | ||
| 905 | 905 | status = "disabled"; |
| 906 | 906 | }; |
| 907 | 907 | |
| 908 | − sata_phy: t-phy@1a243000 { | |
| 908 | + sata_phy: t-phy { | |
| 909 | 909 | compatible = "mediatek,mt7622-tphy", |
| 910 | 910 | "mediatek,generic-tphy-v1"; |
| 911 | 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 | 438 | compatible = "mediatek,mt7986-tphy", |
| 439 | 439 | "mediatek,generic-tphy-v2"; |
| 440 | 440 | #address-cells = <2>; |
| @@ -48,7 +48,7 @@ · 47 unmodified lines | ||
| 48 | 48 | |
| 49 | 49 | memory@40000000 { |
| 50 | 50 | device_type = "memory"; |
| 51 | − reg = <0 0x40000000 0 0x80000000>; | |
| 51 | + reg = <0 0x40000000 0x2 0x00000000>; | |
| 52 | 52 | }; |
| 53 | 53 | |
| 54 | 54 | reserved-memory { |
| @@ -56,13 +56,8 @@ · 1 unmodified line | ||
| 56 | 56 | #size-cells = <2>; |
| 57 | 57 | ranges; |
| 58 | 58 | |
| 59 | − /* 2 MiB reserved for ARM Trusted Firmware (BL31) */ | |
| 60 | − bl31_secmon_reserved: secmon@54600000 { | |
| 61 | − no-map; | |
| 62 | − reg = <0 0x54600000 0x0 0x200000>; | |
| 63 | − }; | |
| 64 | − | |
| 65 | − /* 12 MiB reserved for OP-TEE (BL32) | |
| 59 | + /* | |
| 60 | + * 12 MiB reserved for OP-TEE (BL32) | |
| 66 | 61 | * +-----------------------+ 0x43e0_0000 |
| 67 | 62 | * | SHMEM 2MiB | |
| 68 | 63 | * +-----------------------+ 0x43c0_0000 |
| @@ -75,6 +70,34 @@ · 6 unmodified lines | ||
| 75 | 70 | no-map; |
| 76 | 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 | 313 | interrupts = <GIC_SPI 18 IRQ_TYPE_LEVEL_HIGH 0>; |
| 314 | 314 | cpus = <&cpu0>, <&cpu1>, <&cpu2>, <&cpu3>, |
| 315 | 315 | <&cpu4>, <&cpu5>, <&cpu6>, <&cpu7>; |
| 316 | + status = "fail"; | |
| 316 | 317 | }; |
| 317 | 318 | |
| 318 | 319 | dmic_codec: dmic-codec { |
| @@ -3958,7 +3958,7 @@ · 3957 unmodified lines | ||
| 3958 | 3958 | |
| 3959 | 3959 | pdc: interrupt-controller@b220000 { |
| 3960 | 3960 | compatible = "qcom,sm8150-pdc", "qcom,pdc"; |
| 3961 | − reg = <0 0x0b220000 0 0x400>; | |
| 3961 | + reg = <0 0x0b220000 0 0x30000>; | |
| 3962 | 3962 | qcom,pdc-ranges = <0 480 94>, <94 609 31>, |
| 3963 | 3963 | <125 63 1>; |
| 3964 | 3964 | #interrupt-cells = <2>; |
| @@ -9,6 +9,7 @@ · 8 unmodified lines | ||
| 9 | 9 | #ifndef _ASM_ACPI_H |
| 10 | 10 | #define _ASM_ACPI_H |
| 11 | 11 | |
| 12 | +#include <linux/cpuidle.h> | |
| 12 | 13 | #include <linux/efi.h> |
| 13 | 14 | #include <linux/memblock.h> |
| 14 | 15 | #include <linux/psci.h> |
| @@ -44,6 +45,24 @@ · 29 unmodified lines | ||
| 44 | 45 | |
| 45 | 46 | #define ACPI_MADT_GICC_TRBE (offsetof(struct acpi_madt_generic_interrupt, \ |
| 46 | 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 | 67 | /* Basic configuration for ACPI */ |
| 49 | 68 | #ifdef CONFIG_ACPI |
| @@ -79,6 +79,7 @@ · 78 unmodified lines | ||
| 79 | 79 | #define ARM_CPU_PART_CORTEX_A78AE 0xD42 |
| 80 | 80 | #define ARM_CPU_PART_CORTEX_X1 0xD44 |
| 81 | 81 | #define ARM_CPU_PART_CORTEX_A510 0xD46 |
| 82 | +#define ARM_CPU_PART_CORTEX_A520 0xD80 | |
| 82 | 83 | #define ARM_CPU_PART_CORTEX_A710 0xD47 |
| 83 | 84 | #define ARM_CPU_PART_CORTEX_A715 0xD4D |
| 84 | 85 | #define ARM_CPU_PART_CORTEX_X2 0xD48 |
| @@ -148,6 +149,7 @@ · 63 unmodified lines | ||
| 148 | 149 | #define MIDR_CORTEX_A78AE MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A78AE) |
| 149 | 150 | #define MIDR_CORTEX_X1 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_X1) |
| 150 | 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 | 153 | #define MIDR_CORTEX_A710 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A710) |
| 152 | 154 | #define MIDR_CORTEX_A715 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A715) |
| 153 | 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 | 730 | .cpu_enable = cpu_clear_bf16_from_user_emulation, |
| 731 | 731 | }, |
| 732 | 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 | 741 | #ifdef CONFIG_AMPERE_ERRATUM_AC03_CPU_38 |
| 734 | 742 | { |
| 735 | 743 | .desc = "AmpereOne erratum AC03_CPU_38", |
| @@ -428,6 +428,10 @@ alternative_else_nop_endif · 427 unmodified lines | ||
| 428 | 428 | ldp x28, x29, [sp, #16 * 14] |
| 429 | 429 | |
| 430 | 430 | .if \el == 0 |
| 431 | +alternative_if ARM64_WORKAROUND_2966298 | |
| 432 | + tlbi vale1, xzr | |
| 433 | + dsb nsh | |
| 434 | +alternative_else_nop_endif | |
| 431 | 435 | alternative_if_not ARM64_UNMAP_KERNEL_AT_EL0 |
| 432 | 436 | ldr lr, [sp, #S_LR] |
| 433 | 437 | add sp, sp, #PT_REGS_SIZE // restore sp |
| @@ -84,6 +84,7 @@ WORKAROUND_2077057 · 83 unmodified lines | ||
| 84 | 84 | WORKAROUND_2457168 |
| 85 | 85 | WORKAROUND_2645198 |
| 86 | 86 | WORKAROUND_2658417 |
| 87 | +WORKAROUND_2966298 | |
| 87 | 88 | WORKAROUND_AMPERE_AC03_CPU_38 |
| 88 | 89 | WORKAROUND_TRBE_OVERWRITE_FILL_MODE |
| 89 | 90 | WORKAROUND_TSB_FLUSH_FAILURE |
| @@ -15,9 +15,4 @@ DECLARE_PER_CPU(struct ia64_cpu, cpu_devices); · 14 unmodified lines | ||
| 15 | 15 | |
| 16 | 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 | 18 | #endif /* _ASM_IA64_CPU_H_ */ |
| @@ -59,7 +59,7 @@ void __ref arch_unregister_cpu(int num) · 58 unmodified lines | ||
| 59 | 59 | } |
| 60 | 60 | EXPORT_SYMBOL(arch_unregister_cpu); |
| 61 | 61 | #else |
| 62 | −static int __init arch_register_cpu(int num) | |
| 62 | +int __init arch_register_cpu(int num) | |
| 63 | 63 | { |
| 64 | 64 | return register_cpu(&sysfs_cpus[num].cpu, num); |
| 65 | 65 | } |
| @@ -2,39 +2,42 @@ · 1 unmodified line | ||
| 2 | 2 | #ifndef __PARISC_LDCW_H |
| 3 | 3 | #define __PARISC_LDCW_H |
| 4 | 4 | |
| 5 | −#ifndef CONFIG_PA20 | |
| 6 | 5 | /* Because kmalloc only guarantees 8-byte alignment for kmalloc'd data, |
| 7 | 6 | and GCC only guarantees 8-byte alignment for stack locals, we can't |
| 8 | 7 | be assured of 16-byte alignment for atomic lock data even if we |
| 9 | 8 | specify "__attribute ((aligned(16)))" in the type declaration. So, |
| 10 | 9 | we use a struct containing an array of four ints for the atomic lock |
| 11 | 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 | 28 | #define __PA_LDCW_ALIGNMENT 16 |
| 15 | −#define __PA_LDCW_ALIGN_ORDER 4 | |
| 16 | 29 | #define __ldcw_align(a) ({ \ |
| 17 | 30 | unsigned long __ret = (unsigned long) &(a)->lock[0]; \ |
| 18 | 31 | __ret = (__ret + __PA_LDCW_ALIGNMENT - 1) \ |
| 19 | 32 | & ~(__PA_LDCW_ALIGNMENT - 1); \ |
| 20 | 33 | (volatile unsigned int *) __ret; \ |
| 21 | 34 | }) |
| 22 | −#define __LDCW "ldcw" | |
| 23 | 35 | |
| 24 | −#else /*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) | |
| 36 | +#ifdef CONFIG_PA20 | |
| 35 | 37 | #define __LDCW "ldcw,co" |
| 36 | − | |
| 37 | −#endif /*!CONFIG_PA20*/ | |
| 38 | +#else | |
| 39 | +#define __LDCW "ldcw" | |
| 40 | +#endif | |
| 38 | 41 | |
| 39 | 42 | /* LDCW, the only atomic read-write operation PA-RISC has. *sigh*. |
| 40 | 43 | We don't explicitly expose that "*a" may be written as reload |
| @@ -9,15 +9,10 @@ · 8 unmodified lines | ||
| 9 | 9 | #ifndef __ASSEMBLY__ |
| 10 | 10 | |
| 11 | 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 | 12 | volatile unsigned int lock[4]; |
| 17 | 13 | # define __ARCH_SPIN_LOCK_UNLOCKED \ |
| 18 | 14 | { { __ARCH_SPIN_LOCK_UNLOCKED_VAL, __ARCH_SPIN_LOCK_UNLOCKED_VAL, \ |
| 19 | 15 | __ARCH_SPIN_LOCK_UNLOCKED_VAL, __ARCH_SPIN_LOCK_UNLOCKED_VAL } } |
| 20 | −#endif | |
| 21 | 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 | 440 | if (cpu_online(cpu)) |
| 441 | 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 | 446 | return -EIO; |
| 445 | 447 | |
| 446 | 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 | 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 | 104 | static inline int pte_write(pte_t pte) |
| 98 | 105 | { |
| 99 | 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 | 198 | unsigned long old; |
| 199 | 199 | |
| 200 | − if (pte_young(*ptep)) | |
| 200 | + if (!pte_young(*ptep)) | |
| 201 | 201 | return 0; |
| 202 | 202 | old = pte_update(mm, addr, ptep, _PAGE_ACCESSED, 0, 0); |
| 203 | 203 | return (old & _PAGE_ACCESSED) != 0; |
| @@ -25,7 +25,9 @@ static inline int pte_write(pte_t pte) · 24 unmodified lines | ||
| 25 | 25 | return pte_val(pte) & _PAGE_RW; |
| 26 | 26 | } |
| 27 | 27 | #endif |
| 28 | +#ifndef pte_read | |
| 28 | 29 | static inline int pte_read(pte_t pte) { return 1; } |
| 30 | +#endif | |
| 29 | 31 | static inline int pte_dirty(pte_t pte) { return pte_val(pte) & _PAGE_DIRTY; } |
| 30 | 32 | static inline int pte_special(pte_t pte) { return pte_val(pte) & _PAGE_SPECIAL; } |
| 31 | 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 | 137 | lis r4,icache_44x_need_flush@ha |
| 138 | 138 | lwz r5,icache_44x_need_flush@l(r4) |
| 139 | 139 | cmplwi cr0,r5,0 |
| 140 | − bne- 2f | |
| 140 | + bne- .L44x_icache_flush | |
| 141 | 141 | #endif /* CONFIG_PPC_47x */ |
| 142 | +.L44x_icache_flush_return: | |
| 142 | 143 | kuep_unlock |
| 143 | 144 | lwz r4,_LINK(r1) |
| 144 | 145 | lwz r5,_CCR(r1) |
| @@ -172,10 +173,11 @@ syscall_exit_finish: · 27 unmodified lines | ||
| 172 | 173 | b 1b |
| 173 | 174 | |
| 174 | 175 | #ifdef CONFIG_44x |
| 175 | −2: li r7,0 | |
| 176 | +.L44x_icache_flush: | |
| 177 | + li r7,0 | |
| 176 | 178 | iccci r0,r0 |
| 177 | 179 | stw r7,icache_44x_need_flush@l(r4) |
| 178 | − b 1b | |
| 180 | + b .L44x_icache_flush_return | |
| 179 | 181 | #endif /* CONFIG_44x */ |
| 180 | 182 | |
| 181 | 183 | .globl ret_from_fork |
| @@ -395,7 +395,7 @@ interrupt_base: · 394 unmodified lines | ||
| 395 | 395 | #ifdef CONFIG_PPC_FPU |
| 396 | 396 | FP_UNAVAILABLE_EXCEPTION |
| 397 | 397 | #else |
| 398 | − EXCEPTION(0x0800, FP_UNAVAIL, FloatingPointUnavailable, unknown_exception) | |
| 398 | + EXCEPTION(0x0800, FP_UNAVAIL, FloatingPointUnavailable, emulation_assist_interrupt) | |
| 399 | 399 | #endif |
| 400 | 400 | |
| 401 | 401 | /* System Call Interrupt */ |
| @@ -184,9 +184,6 @@ _GLOBAL_TOC(plpar_hcall) · 183 unmodified lines | ||
| 184 | 184 | plpar_hcall_trace: |
| 185 | 185 | HCALL_INST_PRECALL(R5) |
| 186 | 186 | |
| 187 | − std r4,STK_PARAM(R4)(r1) | |
| 188 | − mr r0,r4 | |
| 189 | − | |
| 190 | 187 | mr r4,r5 |
| 191 | 188 | mr r5,r6 |
| 192 | 189 | mr r6,r7 |
| @@ -196,7 +193,7 @@ plpar_hcall_trace: · 3 unmodified lines | ||
| 196 | 193 | |
| 197 | 194 | HVSC |
| 198 | 195 | |
| 199 | − ld r12,STK_PARAM(R4)(r1) | |
| 196 | + ld r12,STACK_FRAME_MIN_SIZE+STK_PARAM(R4)(r1) | |
| 200 | 197 | std r4,0(r12) |
| 201 | 198 | std r5,8(r12) |
| 202 | 199 | std r6,16(r12) |
| @@ -296,9 +293,6 @@ _GLOBAL_TOC(plpar_hcall9) · 93 unmodified lines | ||
| 296 | 293 | plpar_hcall9_trace: |
| 297 | 294 | HCALL_INST_PRECALL(R5) |
| 298 | 295 | |
| 299 | − std r4,STK_PARAM(R4)(r1) | |
| 300 | − mr r0,r4 | |
| 301 | − | |
| 302 | 296 | mr r4,r5 |
| 303 | 297 | mr r5,r6 |
| 304 | 298 | mr r6,r7 |
| @@ -6,7 +6,6 @@ · 5 unmodified lines | ||
| 6 | 6 | # for more details. |
| 7 | 7 | # |
| 8 | 8 | |
| 9 | −OBJCOPYFLAGS := -O binary | |
| 10 | 9 | LDFLAGS_vmlinux := -z norelro |
| 11 | 10 | ifeq ($(CONFIG_RELOCATABLE),y) |
| 12 | 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 | 5 | obj-y += errata.o |
| @@ -31,6 +31,27 @@ static inline unsigned long ftrace_call_adjust(unsigned long addr) · 30 unmodified lines | ||
| 31 | 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 | 55 | struct dyn_arch_ftrace { |
| 35 | 56 | }; |
| 36 | 57 | #endif |
| @@ -40,6 +40,15 @@ void arch_remove_kprobe(struct kprobe *p); · 39 unmodified lines | ||
| 40 | 40 | int kprobe_fault_handler(struct pt_regs *regs, unsigned int trapnr); |
| 41 | 41 | bool kprobe_breakpoint_handler(struct pt_regs *regs); |
| 42 | 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 | 53 | #endif /* CONFIG_KPROBES */ |
| 45 | 54 | #endif /* _ASM_RISCV_KPROBES_H */ |
| @@ -34,7 +34,18 @@ struct arch_uprobe { · 33 unmodified lines | ||
| 34 | 34 | bool simulate; |
| 35 | 35 | }; |
| 36 | 36 | |
| 37 | +#ifdef CONFIG_UPROBES | |
| 37 | 38 | bool uprobe_breakpoint_handler(struct pt_regs *regs); |
| 38 | 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 | 51 | #endif /* _ASM_RISCV_UPROBES_H */ |
| @@ -60,7 +60,7 @@ static void init_irq_stacks(void) · 59 unmodified lines | ||
| 60 | 60 | } |
| 61 | 61 | #endif /* CONFIG_VMAP_STACK */ |
| 62 | 62 | |
| 63 | −#ifdef CONFIG_HAVE_SOFTIRQ_ON_OWN_STACK | |
| 63 | +#ifdef CONFIG_SOFTIRQ_ON_OWN_STACK | |
| 64 | 64 | void do_softirq_own_stack(void) |
| 65 | 65 | { |
| 66 | 66 | #ifdef CONFIG_IRQ_STACKS |
| @@ -92,7 +92,7 @@ void do_softirq_own_stack(void) · 25 unmodified lines | ||
| 92 | 92 | #endif |
| 93 | 93 | __do_softirq(); |
| 94 | 94 | } |
| 95 | −#endif /* CONFIG_HAVE_SOFTIRQ_ON_OWN_STACK */ | |
| 95 | +#endif /* CONFIG_SOFTIRQ_ON_OWN_STACK */ | |
| 96 | 96 | |
| 97 | 97 | #else |
| 98 | 98 | static void init_irq_stacks(void) {} |
| @@ -173,19 +173,6 @@ static void __init init_resources(void) · 172 unmodified lines | ||
| 173 | 173 | if (ret < 0) |
| 174 | 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 | 176 | #ifdef CONFIG_CRASH_DUMP |
| 190 | 177 | if (elfcorehdr_size > 0) { |
| 191 | 178 | elfcorehdr_res.start = elfcorehdr_addr; |
| @@ -311,13 +311,6 @@ static inline void __user *get_sigframe(struct ksignal *ksig, · 310 unmodified lines | ||
| 311 | 311 | /* Align the stack frame. */ |
| 312 | 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 | 314 | return (void __user *)sp; |
| 322 | 315 | } |
| 323 | 316 | |
| @@ -13,6 +13,8 @@ · 12 unmodified lines | ||
| 13 | 13 | #include <linux/kdebug.h> |
| 14 | 14 | #include <linux/uaccess.h> |
| 15 | 15 | #include <linux/kprobes.h> |
| 16 | +#include <linux/uprobes.h> | |
| 17 | +#include <asm/uprobes.h> | |
| 16 | 18 | #include <linux/mm.h> |
| 17 | 19 | #include <linux/module.h> |
| 18 | 20 | #include <linux/irq.h> |
| @@ -247,22 +249,28 @@ static inline unsigned long get_break_insn_length(unsigned long pc) · 228 unmodified lines | ||
| 247 | 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 | 266 | void handle_break(struct pt_regs *regs) |
| 251 | 267 | { |
| 252 | −#ifdef CONFIG_KPROBES | |
| 253 | − if (kprobe_single_step_handler(regs)) | |
| 268 | + if (probe_single_step_handler(regs)) | |
| 254 | 269 | return; |
| 255 | 270 | |
| 256 | − if (kprobe_breakpoint_handler(regs)) | |
| 257 | − return; | |
| 258 | −#endif | |
| 259 | −#ifdef CONFIG_UPROBES | |
| 260 | − if (uprobe_single_step_handler(regs)) | |
| 271 | + if (probe_breakpoint_handler(regs)) | |
| 261 | 272 | return; |
| 262 | 273 | |
| 263 | − if (uprobe_breakpoint_handler(regs)) | |
| 264 | − return; | |
| 265 | −#endif | |
| 266 | 274 | current->thread.bad_cause = regs->cause; |
| 267 | 275 | |
| 268 | 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 | 245 | emit_addi(RV_REG_SP, RV_REG_SP, stack_adjust, ctx); |
| 246 | 246 | /* Set return value. */ |
| 247 | 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 | 249 | emit_jalr(RV_REG_ZERO, is_tail_call ? RV_REG_T3 : RV_REG_RA, |
| 250 | 250 | is_tail_call ? (RV_FENTRY_NINSNS + 1) * 4 : 0, /* skip reserved nops and TCC init */ |
| 251 | 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 | 759 | if (ret) |
| 760 | 760 | return ret; |
| 761 | 761 | |
| 762 | − if (save_ret) | |
| 763 | − emit_sd(RV_REG_FP, -retval_off, regmap[BPF_REG_0], ctx); | |
| 762 | + if (save_ret) { | |
| 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 | 767 | /* update branch with beqz */ |
| 766 | 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 | 856 | save_ret = flags & (BPF_TRAMP_F_CALL_ORIG | BPF_TRAMP_F_RET_FENTRY_RET); |
| 855 | 857 | if (save_ret) { |
| 856 | − stack_size += 8; | |
| 858 | + stack_size += 16; /* Save both A5 (BPF R0) and A0 */ | |
| 857 | 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 | 959 | if (ret) |
| 958 | 960 | goto out; |
| 959 | 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 | 963 | im->ip_after_call = ctx->insns + ctx->ninsns; |
| 961 | 964 | /* 2 nops reserved for auipc+jalr pair */ |
| 962 | 965 | emit(rv_nop(), ctx); |
| @@ -988,8 +991,10 @@ static int __arch_prepare_bpf_trampoline(struct bpf_tramp_image *im, · 25 unmodified lines | ||
| 988 | 991 | if (flags & BPF_TRAMP_F_RESTORE_REGS) |
| 989 | 992 | restore_args(nregs, args_off, ctx); |
| 990 | 993 | |
| 991 | − if (save_ret) | |
| 994 | + if (save_ret) { | |
| 992 | 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 | 999 | emit_ld(RV_REG_S1, -sreg_off, RV_REG_FP, ctx); |
| 995 | 1000 | |
| @@ -1515,7 +1520,8 @@ out_be: · 519 unmodified lines | ||
| 1515 | 1520 | if (ret) |
| 1516 | 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 | 1525 | break; |
| 1520 | 1526 | } |
| 1521 | 1527 | /* tail call */ |
| @@ -2066,6 +2066,7 @@ struct bpf_tramp_jit { · 2065 unmodified lines | ||
| 2066 | 2066 | * func_addr's original caller |
| 2067 | 2067 | */ |
| 2068 | 2068 | int stack_size; /* Trampoline stack size */ |
| 2069 | + int backchain_off; /* Offset of backchain */ | |
| 2069 | 2070 | int stack_args_off; /* Offset of stack arguments for calling |
| 2070 | 2071 | * func_addr, has to be at the top |
| 2071 | 2072 | */ |
| @@ -2086,9 +2087,10 @@ struct bpf_tramp_jit { · 14 unmodified lines | ||
| 2086 | 2087 | * for __bpf_prog_enter() return value and |
| 2087 | 2088 | * func_addr respectively |
| 2088 | 2089 | */ |
| 2089 | − int r14_off; /* Offset of saved %r14 */ | |
| 2090 | 2090 | int run_ctx_off; /* Offset of struct bpf_tramp_run_ctx */ |
| 2091 | 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 | 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 | 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 | 2256 | tjit->stack_size = STACK_FRAME_OVERHEAD; |
| 2257 | + tjit->backchain_off = tjit->stack_size - sizeof(u64); | |
| 2252 | 2258 | tjit->stack_args_off = alloc_stack(tjit, nr_stack_args * sizeof(u64)); |
| 2253 | 2259 | tjit->reg_args_off = alloc_stack(tjit, nr_reg_args * sizeof(u64)); |
| 2254 | 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 | 2262 | tjit->bpf_args_off = alloc_stack(tjit, nr_bpf_args * sizeof(u64)); |
| 2257 | 2263 | tjit->retval_off = alloc_stack(tjit, sizeof(u64)); |
| 2258 | 2264 | tjit->r7_r8_off = alloc_stack(tjit, 2 * sizeof(u64)); |
| 2259 | − tjit->r14_off = alloc_stack(tjit, sizeof(u64)); | |
| 2260 | 2265 | tjit->run_ctx_off = alloc_stack(tjit, |
| 2261 | 2266 | sizeof(struct bpf_tramp_run_ctx)); |
| 2262 | 2267 | tjit->tccnt_off = alloc_stack(tjit, sizeof(u64)); |
| 2263 | − /* The caller has already reserved STACK_FRAME_OVERHEAD bytes. */ | |
| 2264 | − tjit->stack_size -= STACK_FRAME_OVERHEAD; | |
| 2268 | + tjit->r14_off = alloc_stack(tjit, sizeof(u64) * 2); | |
| 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 | 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 | 2279 | /* aghi %r15,-stack_size */ |
| 2268 | 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 | 2284 | /* mvc tccnt_off(4,%r15),stack_size+STK_OFF_TCCNT(%r15) */ |
| 2270 | 2285 | _EMIT6(0xd203f000 | tjit->tccnt_off, |
| 2271 | 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 | 2528 | return -E2BIG; |
| 2514 | 2529 | } |
| 2515 | 2530 | |
| 2516 | − return ret; | |
| 2531 | + return tjit.common.prg; | |
| 2517 | 2532 | } |
| 2518 | 2533 | |
| 2519 | 2534 | bool bpf_jit_supports_subprog_tailcalls(void) |
| @@ -1,5 +1,6 @@ | ||
| 1 | 1 | // SPDX-License-Identifier: GPL-2.0 |
| 2 | 2 | #include <asm/insn.h> |
| 3 | +#include <linux/mm.h> | |
| 3 | 4 | |
| 4 | 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 | 133 | * The LBR logs any address in the IP, even if the IP just |
| 133 | 134 | * faulted. This means userspace can control the from address. |
| 134 | 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 | 139 | addr = (void *)from; |
| 139 | 140 | /* |
| 140 | 141 | * Assume we can get the maximum possible size |
| @@ -7,6 +7,8 @@ · 6 unmodified lines | ||
| 7 | 7 | * Author : K. Y. Srinivasan <kys@microsoft.com> |
| 8 | 8 | */ |
| 9 | 9 | |
| 10 | +#define pr_fmt(fmt) "Hyper-V: " fmt | |
| 11 | + | |
| 10 | 12 | #include <linux/efi.h> |
| 11 | 13 | #include <linux/types.h> |
| 12 | 14 | #include <linux/bitfield.h> |
| @@ -191,7 +193,7 @@ void set_hv_tscchange_cb(void (*cb)(void)) · 178 unmodified lines | ||
| 191 | 193 | struct hv_tsc_emulation_control emu_ctrl = {.enabled = 1}; |
| 192 | 194 | |
| 193 | 195 | if (!hv_reenlightenment_available()) { |
| 194 | − pr_warn("Hyper-V: reenlightenment support is unavailable\n"); | |
| 196 | + pr_warn("reenlightenment support is unavailable\n"); | |
| 195 | 197 | return; |
| 196 | 198 | } |
| 197 | 199 | |
| @@ -394,6 +396,7 @@ static void __init hv_get_partition_id(void) · 196 unmodified lines | ||
| 394 | 396 | local_irq_restore(flags); |
| 395 | 397 | } |
| 396 | 398 | |
| 399 | +#if IS_ENABLED(CONFIG_HYPERV_VTL_MODE) | |
| 397 | 400 | static u8 __init get_vtl(void) |
| 398 | 401 | { |
| 399 | 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 | 419 | if (hv_result_success(ret)) { |
| 417 | 420 | ret = output->as64.low & HV_X64_VTL_MASK; |
| 418 | 421 | } else { |
| 419 | − pr_err("Failed to get VTL(%lld) and set VTL to zero by default.\n", ret); | |
| 420 | − ret = 0; | |
| 422 | + pr_err("Failed to get VTL(error: %lld) exiting...\n", ret); | |
| 423 | + BUG(); | |
| 421 | 424 | } |
| 422 | 425 | |
| 423 | 426 | local_irq_restore(flags); |
| 424 | 427 | return ret; |
| 425 | 428 | } |
| 429 | +#else | |
| 430 | +static inline u8 get_vtl(void) { return 0; } | |
| 431 | +#endif | |
| 426 | 432 | |
| 427 | 433 | /* |
| 428 | 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 | 570 | if (cpu_feature_enabled(X86_FEATURE_IBT) && |
| 565 | 571 | *(u32 *)hv_hypercall_pg != gen_endbr()) { |
| 566 | 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 | 575 | #endif |
| 570 | 576 | |
| @@ -604,8 +610,10 @@ skip_hypercall_pg_init: · 33 unmodified lines | ||
| 604 | 610 | hv_query_ext_cap(0); |
| 605 | 611 | |
| 606 | 612 | /* Find the VTL */ |
| 607 | − if (!ms_hyperv.paravisor_present && hv_isolation_type_snp()) | |
| 608 | − ms_hyperv.vtl = get_vtl(); | |
| 613 | + ms_hyperv.vtl = get_vtl(); | |
| 614 | + | |
| 615 | + if (ms_hyperv.vtl > 0) /* non default VTL */ | |
| 616 | + hv_vtl_early_init(); | |
| 609 | 617 | |
| 610 | 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 | 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 | 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 | 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 | 30 | #ifdef CONFIG_HOTPLUG_CPU |
| 31 | −extern int arch_register_cpu(int num); | |
| 32 | −extern void arch_unregister_cpu(int); | |
| 33 | 31 | extern void soft_restart_cpu(void); |
| 34 | 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 | 341 | #ifdef CONFIG_HYPERV_VTL_MODE |
| 342 | 342 | void __init hv_vtl_init_platform(void); |
| 343 | +int __init hv_vtl_early_init(void); | |
| 343 | 344 | #else |
| 344 | 345 | static inline void __init hv_vtl_init_platform(void) {} |
| 346 | +static inline int __init hv_vtl_early_init(void) { return 0; } | |
| 345 | 347 | #endif |
| 346 | 348 | |
| 347 | 349 | #include <asm-generic/mshyperv.h> |
| @@ -637,12 +637,17 @@ · 636 unmodified lines | ||
| 637 | 637 | /* AMD Last Branch Record MSRs */ |
| 638 | 638 | #define MSR_AMD64_LBR_SELECT 0xc000010e |
| 639 | 639 | |
| 640 | −/* Fam 17h MSRs */ | |
| 641 | −#define MSR_F17H_IRPERF 0xc00000e9 | |
| 640 | +/* Zen4 */ | |
| 641 | +#define MSR_ZEN4_BP_CFG 0xc001102e | |
| 642 | +#define MSR_ZEN4_BP_CFG_SHARED_BTB_FIX_BIT 5 | |
| 642 | 643 | |
| 644 | +/* Zen 2 */ | |
| 643 | 645 | #define MSR_ZEN2_SPECTRAL_CHICKEN 0xc00110e3 |
| 644 | 646 | #define MSR_ZEN2_SPECTRAL_CHICKEN_BIT BIT_ULL(1) |
| 645 | 647 | |
| 648 | +/* Fam 17h MSRs */ | |
| 649 | +#define MSR_F17H_IRPERF 0xc00000e9 | |
| 650 | + | |
| 646 | 651 | /* Fam 16h MSRs */ |
| 647 | 652 | #define MSR_F16H_L2I_PERF_CTL 0xc0010230 |
| 648 | 653 | #define MSR_F16H_L2I_PERF_CTR 0xc0010231 |
| @@ -129,7 +129,6 @@ void native_smp_send_reschedule(int cpu); · 128 unmodified lines | ||
| 129 | 129 | void native_send_call_func_ipi(const struct cpumask *mask); |
| 130 | 130 | void native_send_call_func_single_ipi(int cpu); |
| 131 | 131 | |
| 132 | −bool smp_park_other_cpus_in_init(void); | |
| 133 | 132 | void smp_store_cpu_info(int id); |
| 134 | 133 | |
| 135 | 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 | 403 | u8 insn_buff[MAX_PATCH_LEN]; |
| 404 | 404 | |
| 405 | 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 | 418 | * The scan order should be from start to end. A later scanned |
| 408 | 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 | 464 | text_poke_early(instr, insn_buff, insn_buff_sz); |
| 454 | 465 | } |
| 466 | + | |
| 467 | + kasan_enable_current(); | |
| 455 | 468 | } |
| 456 | 469 | |
| 457 | 470 | static inline bool is_jcc32(struct insn *insn) |
| @@ -80,6 +80,10 @@ static const int amd_div0[] = · 79 unmodified lines | ||
| 80 | 80 | AMD_LEGACY_ERRATUM(AMD_MODEL_RANGE(0x17, 0x00, 0x0, 0x2f, 0xf), |
| 81 | 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 | 87 | static bool cpu_has_amd_erratum(struct cpuinfo_x86 *cpu, const int *erratum) |
| 84 | 88 | { |
| 85 | 89 | int osvw_id = *erratum++; |
| @@ -1149,6 +1153,10 @@ static void init_amd(struct cpuinfo_x86 *c) · 1063 unmodified lines | ||
| 1149 | 1153 | pr_notice_once("AMD Zen1 DIV0 bug detected. Disable SMT for full protection.\n"); |
| 1150 | 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 | 1162 | #ifdef CONFIG_X86_32 |
| @@ -30,15 +30,15 @@ struct rmid_entry { · 29 unmodified lines | ||
| 30 | 30 | struct list_head list; |
| 31 | 31 | }; |
| 32 | 32 | |
| 33 | −/** | |
| 34 | − * @rmid_free_lru A least recently used list of free RMIDs | |
| 33 | +/* | |
| 34 | + * @rmid_free_lru - A least recently used list of free RMIDs | |
| 35 | 35 | * These RMIDs are guaranteed to have an occupancy less than the |
| 36 | 36 | * threshold occupancy |
| 37 | 37 | */ |
| 38 | 38 | static LIST_HEAD(rmid_free_lru); |
| 39 | 39 | |
| 40 | −/** | |
| 41 | − * @rmid_limbo_count count of currently unused but (potentially) | |
| 40 | +/* | |
| 41 | + * @rmid_limbo_count - count of currently unused but (potentially) | |
| 42 | 42 | * dirty RMIDs. |
| 43 | 43 | * This counts RMIDs that no one is currently using but that |
| 44 | 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 | 47 | static unsigned int rmid_limbo_count; |
| 48 | 48 | |
| 49 | −/** | |
| 49 | +/* | |
| 50 | 50 | * @rmid_entry - The entry in the limbo and free lists. |
| 51 | 51 | */ |
| 52 | 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 | 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 | 261 | int ret; |
| 262 | 262 | |
| @@ -279,6 +279,45 @@ static int sev_cpuid_hv(struct cpuid_leaf *leaf) · 16 unmodified lines | ||
| 279 | 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 | 322 | * This may be called early while still running on the initial identity |
| 284 | 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 | 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 | 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 | 439 | struct cpuid_leaf leaf_hv = *leaf; |
| 400 | 440 | |
| 401 | 441 | switch (leaf->fn) { |
| 402 | 442 | case 0x1: |
| 403 | − snp_cpuid_hv(&leaf_hv); | |
| 443 | + snp_cpuid_hv(ghcb, ctxt, &leaf_hv); | |
| 404 | 444 | |
| 405 | 445 | /* initial APIC ID */ |
| 406 | 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 | 459 | break; |
| 420 | 460 | case 0xB: |
| 421 | 461 | leaf_hv.subfn = 0; |
| 422 | − snp_cpuid_hv(&leaf_hv); | |
| 462 | + snp_cpuid_hv(ghcb, ctxt, &leaf_hv); | |
| 423 | 463 | |
| 424 | 464 | /* extended APIC ID */ |
| 425 | 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 | 508 | break; |
| 469 | 509 | case 0x8000001E: |
| 470 | − snp_cpuid_hv(&leaf_hv); | |
| 510 | + snp_cpuid_hv(ghcb, ctxt, &leaf_hv); | |
| 471 | 511 | |
| 472 | 512 | /* extended APIC ID */ |
| 473 | 513 | leaf->eax = leaf_hv.eax; |
| @@ -488,7 +528,7 @@ static int snp_cpuid_postprocess(struct cpuid_leaf *leaf) · 14 unmodified lines | ||
| 488 | 528 | * Returns -EOPNOTSUPP if feature not enabled. Any other non-zero return value |
| 489 | 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 | 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 | 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 | 584 | leaf.fn = fn; |
| 545 | 585 | leaf.subfn = subfn; |
| 546 | 586 | |
| 547 | − ret = snp_cpuid(&leaf); | |
| 587 | + ret = snp_cpuid(NULL, NULL, &leaf); | |
| 548 | 588 | if (!ret) |
| 549 | 589 | goto cpuid_done; |
| 550 | 590 | |
| 551 | 591 | if (ret != -EOPNOTSUPP) |
| 552 | 592 | goto fail; |
| 553 | 593 | |
| 554 | − if (sev_cpuid_hv(&leaf)) | |
| 594 | + if (__sev_cpuid_hv_msr(&leaf)) | |
| 555 | 595 | goto fail; |
| 556 | 596 | |
| 557 | 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 | 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 | 894 | struct cpuid_leaf leaf; |
| 854 | 895 | int ret; |
| 855 | 896 | |
| 856 | 897 | leaf.fn = regs->ax; |
| 857 | 898 | leaf.subfn = regs->cx; |
| 858 | − ret = snp_cpuid(&leaf); | |
| 899 | + ret = snp_cpuid(ghcb, ctxt, &leaf); | |
| 859 | 900 | if (!ret) { |
| 860 | 901 | regs->ax = leaf.eax; |
| 861 | 902 | regs->bx = leaf.ebx; |
| @@ -874,7 +915,7 @@ static enum es_result vc_handle_cpuid(struct ghcb *ghcb, · 12 unmodified lines | ||
| 874 | 915 | enum es_result ret; |
| 875 | 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 | 919 | if (!snp_cpuid_ret) |
| 879 | 920 | return ES_OK; |
| 880 | 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 | 869 | void snp_accept_memory(phys_addr_t start, phys_addr_t end) |
| 870 | 870 | { |
| 871 | − unsigned long vaddr; | |
| 872 | − unsigned int npages; | |
| 871 | + unsigned long vaddr, npages; | |
| 873 | 872 | |
| 874 | 873 | if (!cc_platform_has(CC_ATTR_GUEST_SEV_SNP)) |
| 875 | 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 | 136 | DEFINE_IDTENTRY_SYSVEC(sysvec_reboot) |
| 137 | 137 | { |
| @@ -172,17 +172,13 @@ static void native_stop_other_cpus(int wait) · 34 unmodified lines | ||
| 172 | 172 | * 2) Wait for all other CPUs to report that they reached the |
| 173 | 173 | * HLT loop in stop_this_cpu() |
| 174 | 174 | * |
| 175 | − * 3) If the system uses INIT/STARTUP for CPU bringup, then | |
| 176 | − * send all present CPUs an INIT vector, which brings them | |
| 177 | − * completely out of the way. | |
| 175 | + * 3) If #2 timed out send an NMI to the CPUs which did not | |
| 176 | + * yet report | |
| 178 | 177 | * |
| 179 | − * 4) If #3 is not possible and #2 timed out send an NMI to the | |
| 180 | − * CPUs which did not yet report | |
| 181 | − * | |
| 182 | − * 5) Wait for all other CPUs to report that they reached the | |
| 178 | + * 4) Wait for all other CPUs to report that they reached the | |
| 183 | 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 | 182 | * That CPU will have reported already and the "have all CPUs |
| 187 | 183 | * reached HLT" condition will be true despite the fact that the |
| 188 | 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 | 195 | * Don't wait longer than a second for IPI completion. The |
| 200 | 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 | 198 | * CPUs reach shutdown state. |
| 203 | 199 | */ |
| 204 | 200 | timeout = USEC_PER_SEC; |
| @@ -206,27 +202,7 @@ static void native_stop_other_cpus(int wait) · 1 unmodified line | ||
| 206 | 202 | udelay(1); |
| 207 | 203 | } |
| 208 | 204 | |
| 209 | − /* | |
| 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 | − */ | |
| 205 | + /* if the REBOOT_VECTOR didn't work, try with the NMI */ | |
| 230 | 206 | if (!cpumask_empty(&cpus_stop_mask)) { |
| 231 | 207 | /* |
| 232 | 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 | 225 | udelay(1); |
| 250 | 226 | } |
| 251 | 227 | |
| 252 | −done: | |
| 253 | 228 | local_irq_save(flags); |
| 254 | 229 | disable_local_APIC(); |
| 255 | 230 | mcheck_cpu_clear(this_cpu_ptr(&cpu_info)); |
| @@ -1240,33 +1240,6 @@ void arch_thaw_secondary_cpus_end(void) · 1239 unmodified lines | ||
| 1240 | 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 | 1244 | * Early setup to make printk work. |
| 1272 | 1245 | */ |
| @@ -54,7 +54,7 @@ void arch_unregister_cpu(int num) · 53 unmodified lines | ||
| 54 | 54 | EXPORT_SYMBOL(arch_unregister_cpu); |
| 55 | 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 | 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 | 773 | filemap_invalidate_lock(inode->i_mapping); |
| 774 | 774 | |
| 775 | − /* Invalidate the page cache, including dirty pages. */ | |
| 776 | − error = truncate_bdev_range(bdev, file_to_blk_mode(file), start, end); | |
| 777 | − if (error) | |
| 778 | − goto fail; | |
| 779 | − | |
| 775 | + /* | |
| 776 | + * Invalidate the page cache, including dirty pages, for valid | |
| 777 | + * de-allocate mode calls to fallocate(). | |
| 778 | + */ | |
| 780 | 779 | switch (mode) { |
| 781 | 780 | case FALLOC_FL_ZERO_RANGE: |
| 782 | 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 | 786 | error = blkdev_issue_zeroout(bdev, start >> SECTOR_SHIFT, |
| 784 | 787 | len >> SECTOR_SHIFT, GFP_KERNEL, |
| 785 | 788 | BLKDEV_ZERO_NOUNMAP); |
| 786 | 789 | break; |
| 787 | 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 | 795 | error = blkdev_issue_zeroout(bdev, start >> SECTOR_SHIFT, |
| 789 | 796 | len >> SECTOR_SHIFT, GFP_KERNEL, |
| 790 | 797 | BLKDEV_ZERO_NOFALLBACK); |
| 791 | 798 | break; |
| 792 | 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 | 804 | error = blkdev_issue_discard(bdev, start >> SECTOR_SHIFT, |
| 794 | 805 | len >> SECTOR_SHIFT, GFP_KERNEL); |
| 795 | 806 | break; |
| @@ -12,6 +12,7 @@ · 11 unmodified lines | ||
| 12 | 12 | #define pr_fmt(fmt) "ACPI: " fmt |
| 13 | 13 | |
| 14 | 14 | #include <linux/acpi.h> |
| 15 | +#include <linux/cpu.h> | |
| 15 | 16 | #include <linux/device.h> |
| 16 | 17 | #include <linux/dmi.h> |
| 17 | 18 | #include <linux/kernel.h> |
| @@ -1913,6 +1913,17 @@ static const struct dmi_system_id ec_dmi_table[] __initconst = { · 1912 unmodified lines | ||
| 1913 | 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 | 1929 | * Samsung hardware |
| @@ -855,7 +855,7 @@ static size_t sizeof_idt(struct acpi_nfit_interleave *idt) · 854 unmodified lines | ||
| 855 | 855 | { |
| 856 | 856 | if (idt->header.length < sizeof(*idt)) |
| 857 | 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 | 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 | 1217 | strscpy(state->desc, lpi->desc, CPUIDLE_DESC_LEN); |
| 1218 | 1218 | state->exit_latency = lpi->wake_latency; |
| 1219 | 1219 | state->target_residency = lpi->min_residency; |
| 1220 | − if (lpi->arch_flags) | |
| 1221 | − state->flags |= CPUIDLE_FLAG_TIMER_STOP; | |
| 1220 | + state->flags |= arch_get_idle_state_flags(lpi->arch_flags); | |
| 1222 | 1221 | if (i != 0 && lpi->entry_method == ACPI_CSTATE_FFH) |
| 1223 | 1222 | state->flags |= CPUIDLE_FLAG_RCU_IDLE; |
| 1224 | 1223 | state->enter = acpi_idle_lpi_enter; |
| @@ -439,6 +439,13 @@ static const struct dmi_system_id asus_laptop[] = { · 438 unmodified lines | ||
| 439 | 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 | 450 | .ident = "Asus ExpertBook B1502CBA", |
| 444 | 451 | .matches = { |
| @@ -500,16 +507,23 @@ static const struct dmi_system_id maingear_laptop[] = { · 55 unmodified lines | ||
| 500 | 507 | |
| 501 | 508 | static const struct dmi_system_id pcspecialist_laptop[] = { |
| 502 | 509 | { |
| 503 | − .ident = "PCSpecialist Elimina Pro 16 M", | |
| 504 | − /* | |
| 505 | − * Some models have product-name "Elimina Pro 16 M", | |
| 506 | − * others "GM6BGEQ". Match on board-name to match both. | |
| 507 | − */ | |
| 510 | + /* TongFang GM6BGEQ / PCSpecialist Elimina Pro 16 M, RTX 3050 */ | |
| 508 | 511 | .matches = { |
| 509 | − DMI_MATCH(DMI_SYS_VENDOR, "PCSpecialist"), | |
| 510 | 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 | 4812 | "undelivered TRANSACTION_ERROR: %u\n", |
| 4813 | 4813 | e->cmd); |
| 4814 | 4814 | } break; |
| 4815 | + case BINDER_WORK_TRANSACTION_PENDING: | |
| 4816 | + case BINDER_WORK_TRANSACTION_ONEWAY_SPAM_SUSPECT: | |
| 4815 | 4817 | case BINDER_WORK_TRANSACTION_COMPLETE: { |
| 4816 | 4818 | binder_debug(BINDER_DEBUG_DEAD_TRANSACTION, |
| 4817 | 4819 | "undelivered TRANSACTION_COMPLETE\n"); |
| @@ -9,11 +9,6 @@ · 8 unmodified lines | ||
| 9 | 9 | * |
| 10 | 10 | * The TD-2000 and certain older devices use a different protocol. |
| 11 | 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 | 14 | #include <linux/module.h> |
| @@ -37,8 +32,7 @@ · 17 unmodified lines | ||
| 37 | 32 | |
| 38 | 33 | static void fit3_write_regr(struct pi_adapter *pi, int cont, int regr, int val) |
| 39 | 34 | { |
| 40 | − if (cont == 1) | |
| 41 | − return; | |
| 35 | + regr += cont << 3; | |
| 42 | 36 | |
| 43 | 37 | switch (pi->mode) { |
| 44 | 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 | 54 | int a, b; |
| 61 | 55 | |
| 62 | − if (cont) { | |
| 63 | − if (regr != 6) | |
| 64 | − return 0xff; | |
| 65 | − regr = 7; | |
| 66 | − } | |
| 56 | + regr += cont << 3; | |
| 67 | 57 | |
| 68 | 58 | switch (pi->mode) { |
| 69 | 59 | case 0: |
| @@ -51,6 +51,13 @@ static void pata_parport_dev_select(struct ata_port *ap, unsigned int device) · 50 unmodified lines | ||
| 51 | 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 | 61 | static bool pata_parport_devchk(struct ata_port *ap, unsigned int device) |
| 55 | 62 | { |
| 56 | 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 | 71 | pi->proto->write_regr(pi, 0, ATA_REG_NSECT, 0xaa); |
| 65 | 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 | 75 | pi->proto->write_regr(pi, 0, ATA_REG_LBAL, 0xaa); |
| 69 | 76 | |
| 70 | 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 | 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 | 149 | static int pata_parport_bus_softreset(struct ata_port *ap, unsigned int devmask, |
| 77 | 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 | 160 | ap->last_ctl = ap->ctl; |
| 88 | 161 | |
| 89 | 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 | 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 | 325 | .hardreset = NULL, |
| 253 | 326 | |
| 254 | 327 | .sff_dev_select = pata_parport_dev_select, |
| 328 | + .sff_set_devctl = pata_parport_set_devctl, | |
| 255 | 329 | .sff_check_status = pata_parport_check_status, |
| 256 | 330 | .sff_check_altstatus = pata_parport_check_altstatus, |
| 257 | 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 | 453 | if (!rbnode) |
| 454 | 454 | return -ENOMEM; |
| 455 | 455 | regcache_rbtree_set_register(map, rbnode, |
| 456 | − reg - rbnode->base_reg, value); | |
| 456 | + (reg - rbnode->base_reg) / map->reg_stride, | |
| 457 | + value); | |
| 457 | 458 | regcache_rbtree_insert(map, &rbtree_ctx->root, rbnode); |
| 458 | 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 | 1437 | static void nbd_clear_sock_ioctl(struct nbd_device *nbd) |
| 1438 | 1438 | { |
| 1439 | − blk_mark_disk_dead(nbd->disk); | |
| 1440 | 1439 | nbd_clear_sock(nbd); |
| 1440 | + disk_force_media_change(nbd->disk); | |
| 1441 | + nbd_bdev_reset(nbd); | |
| 1441 | 1442 | if (test_and_clear_bit(NBD_RT_HAS_CONFIG_REF, |
| 1442 | 1443 | &nbd->config->runtime_flags)) |
| 1443 | 1444 | nbd_config_put(nbd); |
| @@ -4419,6 +4419,7 @@ static int btusb_probe(struct usb_interface *intf, · 4418 unmodified lines | ||
| 4419 | 4419 | |
| 4420 | 4420 | if (id->driver_info & BTUSB_QCA_ROME) { |
| 4421 | 4421 | data->setup_on_usb = btusb_setup_qca; |
| 4422 | + hdev->shutdown = btusb_shutdown_qca; | |
| 4422 | 4423 | hdev->set_bdaddr = btusb_set_bdaddr_ath3012; |
| 4423 | 4424 | hdev->cmd_timeout = btusb_qca_cmd_timeout; |
| 4424 | 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 | 247 | if (*id == component_id) |
| 248 | 248 | return 0; |
| 249 | 249 | |
| 250 | − if (ext->type == COUNTER_COMP_ARRAY) { | |
| 251 | − element = ext->priv; | |
| 250 | + if (ext[*ext_idx].type == COUNTER_COMP_ARRAY) { | |
| 251 | + element = ext[*ext_idx].priv; | |
| 252 | 252 | |
| 253 | 253 | if (component_id - *id < element->length) |
| 254 | 254 | return 0; |
| @@ -97,7 +97,7 @@ static int mchp_tc_count_function_write(struct counter_device *counter, · 96 unmodified lines | ||
| 97 | 97 | priv->qdec_mode = 0; |
| 98 | 98 | /* Set highest rate based on whether soc has gclk or not */ |
| 99 | 99 | bmr &= ~(ATMEL_TC_QDEN | ATMEL_TC_POSEN); |
| 100 | − if (priv->tc_cfg->has_gclk) | |
| 100 | + if (!priv->tc_cfg->has_gclk) | |
| 101 | 101 | cmr |= ATMEL_TC_TIMER_CLOCK2; |
| 102 | 102 | else |
| 103 | 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 | 76 | dma_fence_unwrap_for_each(tmp, &iter[i], fences[i]) { |
| 77 | 77 | if (!dma_fence_is_signaled(tmp)) { |
| 78 | 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 | 79 | } else { |
| 84 | − /* | |
| 85 | − * Use the current time if the fence is | |
| 86 | − * currently signaling. | |
| 87 | − */ | |
| 88 | − timestamp = ktime_get(); | |
| 80 | + ktime_t t = dma_fence_timestamp(tmp); | |
| 81 | + | |
| 82 | + if (ktime_after(t, timestamp)) | |
| 83 | + timestamp = t; | |
| 89 | 84 | } |
| 90 | 85 | } |
| 91 | 86 | } |
| @@ -268,13 +268,10 @@ static int sync_fill_fence_info(struct dma_fence *fence, · 267 unmodified lines | ||
| 268 | 268 | sizeof(info->driver_name)); |
| 269 | 269 | |
| 270 | 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 | 271 | info->timestamp_ns = |
| 275 | − test_bit(DMA_FENCE_FLAG_TIMESTAMP_BIT, &fence->flags) ? | |
| 276 | − ktime_to_ns(fence->timestamp) : | |
| 277 | − ktime_set(0, 0); | |
| 272 | + dma_fence_is_signaled(fence) ? | |
| 273 | + ktime_to_ns(dma_fence_timestamp(fence)) : | |
| 274 | + ktime_set(0, 0); | |
| 278 | 275 | |
| 279 | 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 | 93 | edma_writel_chreg(fsl_chan, val, ch_sbr); |
| 94 | 94 | |
| 95 | − if (flags & FSL_EDMA_DRV_HAS_CHMUX) | |
| 96 | − edma_writel_chreg(fsl_chan, fsl_chan->srcid, ch_mux); | |
| 95 | + if (flags & FSL_EDMA_DRV_HAS_CHMUX) { | |
| 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 | 104 | val = edma_readl_chreg(fsl_chan, ch_csr); |
| 99 | 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 | 455 | edma_write_tcdreg(fsl_chan, tcd->dlast_sga, dlast_sga); |
| 450 | 456 | |
| 457 | + csr = le16_to_cpu(tcd->csr); | |
| 458 | + | |
| 451 | 459 | if (fsl_chan->is_sw) { |
| 452 | − csr = le16_to_cpu(tcd->csr); | |
| 453 | 460 | csr |= EDMA_TCD_CSR_START; |
| 454 | 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 | 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 | 183 | #define FSL_EDMA_DRV_BUS_8BYTE BIT(10) |
| 184 | 184 | #define FSL_EDMA_DRV_DEV_TO_DEV BIT(11) |
| 185 | 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 | 191 | #define FSL_EDMA_DRV_EDMA3 (FSL_EDMA_DRV_SPLIT_REG | \ |
| 188 | 192 | FSL_EDMA_DRV_BUS_8BYTE | \ |
| 189 | 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 | 204 | struct fsl_edma_drvdata { |
| 193 | 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 | 154 | fsl_chan = to_fsl_edma_chan(chan); |
| 155 | 155 | i = fsl_chan - fsl_edma->chans; |
| 156 | 156 | |
| 157 | − chan = dma_get_slave_channel(chan); | |
| 158 | − chan->device->privatecnt++; | |
| 159 | 157 | fsl_chan->priority = dma_spec->args[1]; |
| 160 | 158 | fsl_chan->is_rxchan = dma_spec->args[2] & ARGS_RX; |
| 161 | 159 | fsl_chan->is_remote = dma_spec->args[2] & ARGS_REMOTE; |
| 162 | 160 | fsl_chan->is_multi_fifo = dma_spec->args[2] & ARGS_MULTI_FIFO; |
| 163 | 161 | |
| 164 | 162 | if (!b_chmux && i == dma_spec->args[0]) { |
| 163 | + chan = dma_get_slave_channel(chan); | |
| 164 | + chan->device->privatecnt++; | |
| 165 | 165 | mutex_unlock(&fsl_edma->fsl_edma_mutex); |
| 166 | 166 | return chan; |
| 167 | 167 | } else if (b_chmux && !fsl_chan->srcid) { |
| 168 | 168 | /* if controller support channel mux, choose a free channel */ |
| 169 | + chan = dma_get_slave_channel(chan); | |
| 170 | + chan->device->privatecnt++; | |
| 169 | 171 | fsl_chan->srcid = dma_spec->args[0]; |
| 170 | 172 | mutex_unlock(&fsl_edma->fsl_edma_mutex); |
| 171 | 173 | return chan; |
| @@ -355,7 +357,7 @@ static struct fsl_edma_drvdata imx93_data3 = { · 183 unmodified lines | ||
| 355 | 357 | }; |
| 356 | 358 | |
| 357 | 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 | 361 | .chreg_space_sz = 0x8000, |
| 360 | 362 | .chreg_off = 0x10000, |
| 361 | 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 | 477 | union idxd_command_reg cmd; |
| 478 | 478 | DECLARE_COMPLETION_ONSTACK(done); |
| 479 | 479 | u32 stat; |
| 480 | + unsigned long flags; | |
| 480 | 481 | |
| 481 | 482 | if (idxd_device_is_halted(idxd)) { |
| 482 | 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 | 491 | cmd.operand = operand; |
| 491 | 492 | cmd.int_req = 1; |
| 492 | 493 | |
| 493 | − spin_lock(&idxd->cmd_lock); | |
| 494 | + spin_lock_irqsave(&idxd->cmd_lock, flags); | |
| 494 | 495 | wait_event_lock_irq(idxd->cmd_waitq, |
| 495 | 496 | !test_bit(IDXD_FLAG_CMD_RUNNING, &idxd->flags), |
| 496 | 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 | 508 | * After command submitted, release lock and go to sleep until |
| 508 | 509 | * the command completes via interrupt. |
| 509 | 510 | */ |
| 510 | − spin_unlock(&idxd->cmd_lock); | |
| 511 | + spin_unlock_irqrestore(&idxd->cmd_lock, flags); | |
| 511 | 512 | wait_for_completion(&done); |
| 512 | 513 | stat = ioread32(idxd->reg_base + IDXD_CMDSTS_OFFSET); |
| 513 | 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 | 450 | mtk_uart_apdma_write(c, VFF_EN, VFF_EN_CLR_B); |
| 451 | 451 | mtk_uart_apdma_write(c, VFF_INT_EN, VFF_INT_EN_CLR_B); |
| 452 | 452 | |
| 453 | − synchronize_irq(c->irq); | |
| 454 | − | |
| 455 | 453 | spin_unlock_irqrestore(&c->vc.lock, flags); |
| 454 | + synchronize_irq(c->irq); | |
| 456 | 455 | |
| 457 | 456 | return 0; |
| 458 | 457 | } |
| @@ -3668,6 +3668,7 @@ static int __init d40_probe(struct platform_device *pdev) · 3667 unmodified lines | ||
| 3668 | 3668 | regulator_disable(base->lcpa_regulator); |
| 3669 | 3669 | regulator_put(base->lcpa_regulator); |
| 3670 | 3670 | } |
| 3671 | + pm_runtime_disable(base->dev); | |
| 3671 | 3672 | |
| 3672 | 3673 | report_failure: |
| 3673 | 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 | 1113 | chan->chan_reg.dma_scr &= ~STM32_DMA_SCR_PFCTRL; |
| 1114 | 1114 | |
| 1115 | 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 | 1117 | chan->chan_reg.dma_scr |= STM32_DMA_SCR_DBM; |
| 1118 | + chan->chan_reg.dma_scr &= ~STM32_DMA_SCR_CT; | |
| 1119 | + } | |
| 1118 | 1120 | |
| 1119 | 1121 | for_each_sg(sgl, sg, sg_len, i) { |
| 1120 | 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 | 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 | 1393 | n_sg++; |
| 1392 | 1394 | if (n_sg == chan->desc->num_sgs) |
| 1393 | 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 | 1404 | * residue = remaining bytes from NDTR + remaining |
| 1402 | 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 | 1408 | for (i = n_sg; i < desc->num_sgs; i++) |
| 1406 | 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 | 777 | /* Enable interrupts */ |
| 778 | 778 | ccr &= ~STM32_MDMA_CCR_IRQ_MASK; |
| 779 | 779 | ccr |= STM32_MDMA_CCR_TEIE | STM32_MDMA_CCR_CTCIE; |
| 780 | − if (sg_len > 1) | |
| 781 | − ccr |= STM32_MDMA_CCR_BTIE; | |
| 782 | 780 | desc->ccr = ccr; |
| 783 | 781 | |
| 784 | 782 | return 0; |
| @@ -1236,6 +1234,10 @@ static int stm32_mdma_resume(struct dma_chan *c) · 451 unmodified lines | ||
| 1236 | 1234 | unsigned long flags; |
| 1237 | 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 | 1241 | hwdesc = chan->desc->node[chan->curr_hwdesc].hwdesc; |
| 1240 | 1242 | |
| 1241 | 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 | 1319 | static size_t stm32_mdma_desc_residue(struct stm32_mdma_chan *chan, |
| 1318 | 1320 | struct stm32_mdma_desc *desc, |
| 1319 | − u32 curr_hwdesc) | |
| 1321 | + u32 curr_hwdesc, | |
| 1322 | + struct dma_tx_state *state) | |
| 1320 | 1323 | { |
| 1321 | 1324 | struct stm32_mdma_device *dmadev = stm32_mdma_get_dev(chan); |
| 1322 | 1325 | struct stm32_mdma_hwdesc *hwdesc; |
| 1323 | − u32 cbndtr, residue, modulo, burst_size; | |
| 1326 | + u32 cisr, clar, cbndtr, residue, modulo, burst_size; | |
| 1324 | 1327 | int i; |
| 1325 | 1328 | |
| 1329 | + cisr = stm32_mdma_read(dmadev, STM32_MDMA_CISR(chan->id)); | |
| 1330 | + | |
| 1326 | 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 | 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 | 1341 | residue += STM32_MDMA_CBNDTR_BNDT(hwdesc->cbndtr); |
| 1330 | 1342 | } |
| 1331 | 1343 | cbndtr = stm32_mdma_read(dmadev, STM32_MDMA_CBNDTR(chan->id)); |
| 1332 | 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 | 1350 | if (!chan->mem_burst) |
| 1335 | 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 | 1377 | vdesc = vchan_find_desc(&chan->vchan, cookie); |
| 1362 | 1378 | if (chan->desc && cookie == chan->desc->vdesc.tx.cookie) |
| 1363 | − residue = stm32_mdma_desc_residue(chan, chan->desc, | |
| 1364 | − chan->curr_hwdesc); | |
| 1379 | + residue = stm32_mdma_desc_residue(chan, chan->desc, chan->curr_hwdesc, state); | |
| 1365 | 1380 | else if (vdesc) |
| 1366 | − residue = stm32_mdma_desc_residue(chan, | |
| 1367 | − to_stm32_mdma_desc(vdesc), 0); | |
| 1381 | + residue = stm32_mdma_desc_residue(chan, to_stm32_mdma_desc(vdesc), 0, state); | |
| 1382 | + | |
| 1368 | 1383 | dma_set_residue(state, residue); |
| 1369 | 1384 | |
| 1370 | 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 | 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 | 564 | return tx_chn->virq; |
| 562 | 565 | } |
| 563 | 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 | 973 | else if (param == PIN_CONFIG_BIAS_DISABLE || |
| 974 | 974 | param == PIN_CONFIG_BIAS_PULL_DOWN || |
| 975 | 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 | 977 | else if (param == PIN_CONFIG_DRIVE_OPEN_DRAIN || |
| 978 | 978 | param == PIN_CONFIG_DRIVE_OPEN_SOURCE) |
| 979 | 979 | /* Return -ENOTSUPP to trigger emulation, as per datasheet */ |
| @@ -237,6 +237,7 @@ static bool pxa_gpio_has_pinctrl(void) · 236 unmodified lines | ||
| 237 | 237 | switch (gpio_type) { |
| 238 | 238 | case PXA3XX_GPIO: |
| 239 | 239 | case MMP2_GPIO: |
| 240 | + case MMP_GPIO: | |
| 240 | 241 | return false; |
| 241 | 242 | |
| 242 | 243 | default: |
| @@ -2093,7 +2093,7 @@ static int amdgpu_device_ip_early_init(struct amdgpu_device *adev) · 2092 unmodified lines | ||
| 2093 | 2093 | adev->flags |= AMD_IS_PX; |
| 2094 | 2094 | |
| 2095 | 2095 | if (!(adev->flags & AMD_IS_APU)) { |
| 2096 | − parent = pci_upstream_bridge(adev->pdev); | |
| 2096 | + parent = pcie_find_root_port(adev->pdev); | |
| 2097 | 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 | 142 | int r; |
| 143 | 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 | 149 | /* Reserve first num_kernel_doorbells (page-aligned) for kernel ops */ |
| 146 | 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 | 170 | csum += pia[size - 1]; |
| 171 | 171 | if (csum) { |
| 172 | 172 | DRM_ERROR("Bad Product Info Area checksum: 0x%02x", csum); |
| 173 | + kfree(pia); | |
| 173 | 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 | 252 | struct amdgpu_device *adev = amdgpu_ttm_adev(bo->tbo.bdev); |
| 253 | 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 | 256 | return false; |
| 257 | 257 | |
| 258 | 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 | 157 | int32_t N; |
| 158 | 158 | int32_t j; |
| 159 | 159 | |
| 160 | − if (!pipe_ctx->stream) | |
| 160 | + if (!resource_is_pipe_type(pipe_ctx, OTG_MASTER)) | |
| 161 | 161 | continue; |
| 162 | 162 | /* Virtual encoders don't have this function */ |
| 163 | 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 | 188 | int32_t N; |
| 189 | 189 | int32_t j; |
| 190 | 190 | |
| 191 | − if (!pipe_ctx->stream) | |
| 191 | + if (!resource_is_pipe_type(pipe_ctx, OTG_MASTER)) | |
| 192 | 192 | continue; |
| 193 | 193 | /* Virtual encoders don't have this function */ |
| 194 | 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 | 355 | int32_t N; |
| 356 | 356 | int32_t j; |
| 357 | 357 | |
| 358 | − if (!pipe_ctx->stream) | |
| 358 | + if (!resource_is_pipe_type(pipe_ctx, OTG_MASTER)) | |
| 359 | 359 | continue; |
| 360 | 360 | /* Virtual encoders don't have this function */ |
| 361 | 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 | 401 | int32_t N; |
| 402 | 402 | int32_t j; |
| 403 | 403 | |
| 404 | − if (!pipe_ctx->stream) | |
| 404 | + if (!resource_is_pipe_type(pipe_ctx, OTG_MASTER)) | |
| 405 | 405 | continue; |
| 406 | 406 | /* Virtual encoders don't have this function */ |
| 407 | 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 | 1262 | if (stream == NULL) |
| 1263 | 1263 | continue; |
| 1264 | 1264 | |
| 1265 | + if (stream->apply_seamless_boot_optimization) | |
| 1266 | + continue; | |
| 1267 | + | |
| 1265 | 1268 | // only looking for first odm pipe |
| 1266 | 1269 | if (pipe->prev_odm_pipe) |
| 1267 | 1270 | continue; |
| @@ -2040,6 +2040,7 @@ static int default_attr_update(struct amdgpu_device *adev, struct amdgpu_device_ · 2039 unmodified lines | ||
| 2040 | 2040 | case IP_VERSION(11, 0, 0): |
| 2041 | 2041 | case IP_VERSION(11, 0, 1): |
| 2042 | 2042 | case IP_VERSION(11, 0, 2): |
| 2043 | + case IP_VERSION(11, 0, 3): | |
| 2043 | 2044 | *states = ATTR_STATE_SUPPORTED; |
| 2044 | 2045 | break; |
| 2045 | 2046 | default: |
| @@ -2082,36 +2082,41 @@ static int sienna_cichlid_display_disable_memory_clock_switch(struct smu_context · 2081 unmodified lines | ||
| 2082 | 2082 | return ret; |
| 2083 | 2083 | } |
| 2084 | 2084 | |
| 2085 | +#define MAX(a, b) ((a) > (b) ? (a) : (b)) | |
| 2086 | + | |
| 2085 | 2087 | static int sienna_cichlid_update_pcie_parameters(struct smu_context *smu, |
| 2086 | 2088 | uint32_t pcie_gen_cap, |
| 2087 | 2089 | uint32_t pcie_width_cap) |
| 2088 | 2090 | { |
| 2089 | 2091 | struct smu_11_0_dpm_context *dpm_context = smu->smu_dpm.dpm_context; |
| 2090 | 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 | 2097 | int ret, i; |
| 2093 | 2098 | |
| 2094 | − /* PCIE gen speed and lane width override */ | |
| 2095 | − if (!amdgpu_device_pcie_dynamic_switching_supported()) { | |
| 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]; | |
| 2099 | + GET_PPTABLE_MEMBER(PcieGenSpeed, &table_member1); | |
| 2100 | + GET_PPTABLE_MEMBER(PcieLaneCount, &table_member2); | |
| 2098 | 2101 | |
| 2099 | − if (pcie_table->pcie_lane[NUM_LINK_LEVELS - 1] < pcie_width_cap) | |
| 2100 | − pcie_width_cap = pcie_table->pcie_lane[NUM_LINK_LEVELS - 1]; | |
| 2102 | + min_gen_speed = MAX(0, table_member1[0]); | |
| 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 */ | |
| 2103 | − for (i = 0; i < NUM_LINK_LEVELS; i++) { | |
| 2104 | − pcie_table->pcie_gen[i] = pcie_gen_cap; | |
| 2105 | − pcie_table->pcie_lane[i] = pcie_width_cap; | |
| 2106 | − } | |
| 2111 | + if (!amdgpu_device_pcie_dynamic_switching_supported()) { | |
| 2112 | + pcie_table->pcie_gen[0] = max_gen_speed; | |
| 2113 | + pcie_table->pcie_lane[0] = max_lane_width; | |
| 2107 | 2114 | } else { |
| 2108 | − for (i = 0; i < NUM_LINK_LEVELS; i++) { | |
| 2109 | − if (pcie_table->pcie_gen[i] > pcie_gen_cap) | |
| 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 | − } | |
| 2115 | + pcie_table->pcie_gen[0] = min_gen_speed; | |
| 2116 | + pcie_table->pcie_lane[0] = min_lane_width; | |
| 2114 | 2117 | } |
| 2118 | + pcie_table->pcie_gen[1] = max_gen_speed; | |
| 2119 | + pcie_table->pcie_lane[1] = max_lane_width; | |
| 2115 | 2120 | |
| 2116 | 2121 | for (i = 0; i < NUM_LINK_LEVELS; i++) { |
| 2117 | 2122 | smu_pcie_arg = (i << 16 | |
| @@ -290,7 +290,8 @@ static int · 289 unmodified lines | ||
| 290 | 290 | update_connector_routing(struct drm_atomic_state *state, |
| 291 | 291 | struct drm_connector *connector, |
| 292 | 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 | 296 | const struct drm_connector_helper_funcs *funcs; |
| 296 | 297 | struct drm_encoder *new_encoder; |
| @@ -339,9 +340,13 @@ update_connector_routing(struct drm_atomic_state *state, · 42 unmodified lines | ||
| 339 | 340 | * there's a chance the connector may have been destroyed during the |
| 340 | 341 | * process, but it's better to ignore that then cause |
| 341 | 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 | 348 | if (!state->duplicated && drm_connector_is_unregistered(connector) && |
| 344 | − crtc_state->active) { | |
| 349 | + added_by_user && crtc_state->active) { | |
| 345 | 350 | drm_dbg_atomic(connector->dev, |
| 346 | 351 | "[CONNECTOR:%d:%s] is not registered\n", |
| 347 | 352 | connector->base.id, connector->name); |
| @@ -620,7 +625,10 @@ drm_atomic_helper_check_modeset(struct drm_device *dev, · 272 unmodified lines | ||
| 620 | 625 | struct drm_connector *connector; |
| 621 | 626 | struct drm_connector_state *old_connector_state, *new_connector_state; |
| 622 | 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 | 633 | for_each_oldnew_crtc_in_state(state, crtc, old_crtc_state, new_crtc_state, i) { |
| 626 | 634 | bool has_connectors = |
| @@ -685,7 +693,8 @@ drm_atomic_helper_check_modeset(struct drm_device *dev, · 58 unmodified lines | ||
| 685 | 693 | */ |
| 686 | 694 | ret = update_connector_routing(state, connector, |
| 687 | 695 | old_connector_state, |
| 688 | − new_connector_state); | |
| 696 | + new_connector_state, | |
| 697 | + BIT(i) & user_connectors_mask); | |
| 689 | 698 | if (ret) |
| 690 | 699 | return ret; |
| 691 | 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 | 540 | struct page **pages; |
| 541 | 541 | struct folio *folio; |
| 542 | 542 | struct folio_batch fbatch; |
| 543 | − int i, j, npages; | |
| 543 | + long i, j, npages; | |
| 544 | 544 | |
| 545 | 545 | if (WARN_ON(!obj->filp)) |
| 546 | 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 | 565 | i = 0; |
| 566 | 566 | while (i < npages) { |
| 567 | + long nr; | |
| 567 | 568 | folio = shmem_read_folio_gfp(mapping, i, |
| 568 | 569 | mapping_gfp_mask(mapping)); |
| 569 | 570 | if (IS_ERR(folio)) |
| 570 | 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 | 574 | pages[i] = folio_file_page(folio, i); |
| 573 | 575 | |
| 574 | 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 | 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 | 49 | static const struct drm_dmi_panel_orientation_data gpd_pocket = { |
| 42 | 50 | .width = 1200, |
| 43 | 51 | .height = 1920, |
| @@ -401,6 +409,14 @@ static const struct dmi_system_id orientation_data[] = { · 357 unmodified lines | ||
| 401 | 409 | DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "LTH17"), |
| 402 | 410 | }, |
| 403 | 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 | 199 | for_each_gt(gt, i915, id) { |
| 200 | 200 | if (!obj->mm.tlb[id]) |
| 201 | − return; | |
| 201 | + continue; | |
| 202 | 202 | |
| 203 | 203 | intel_gt_invalidate_tlb_full(gt, obj->mm.tlb[id]); |
| 204 | 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 | 271 | if (GRAPHICS_VER_FULL(rq->i915) >= IP_VER(12, 70)) |
| 272 | 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 | 284 | bit_group_1 |= PIPE_CONTROL_TILE_CACHE_FLUSH; |
| 275 | − bit_group_1 |= PIPE_CONTROL_FLUSH_L3; | |
| 276 | 285 | bit_group_1 |= PIPE_CONTROL_RENDER_TARGET_CACHE_FLUSH; |
| 277 | 286 | bit_group_1 |= PIPE_CONTROL_DEPTH_CACHE_FLUSH; |
| 278 | 287 | /* Wa_1409600907:tgl,adl-p */ |
| @@ -1199,6 +1199,13 @@ int i915_gem_init(struct drm_i915_private *dev_priv) · 1198 unmodified lines | ||
| 1199 | 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 | 1209 | return 0; |
| 1203 | 1210 | |
| 1204 | 1211 | /* |
| @@ -1246,8 +1253,6 @@ err_unlock: · 41 unmodified lines | ||
| 1246 | 1253 | void i915_gem_driver_register(struct drm_i915_private *i915) |
| 1247 | 1254 | { |
| 1248 | 1255 | i915_gem_driver_register__shrinker(i915); |
| 1249 | − | |
| 1250 | − intel_engines_driver_register(i915); | |
| 1251 | 1256 | } |
| 1252 | 1257 | |
| 1253 | 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 | 119 | struct dpu_sw_pipe_cfg *pipe_cfg) |
| 120 | 120 | { |
| 121 | 121 | int src_width, src_height, dst_height, fps; |
| 122 | + u64 plane_pixel_rate, plane_bit_rate; | |
| 122 | 123 | u64 plane_prefill_bw; |
| 123 | 124 | u64 plane_bw; |
| 124 | 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 | 137 | scale_factor = src_height > dst_height ? |
| 137 | 138 | mult_frac(src_height, 1, dst_height) : 1; |
| 138 | 139 | |
| 139 | − plane_bw = | |
| 140 | − src_width * mode->vtotal * fps * fmt->bpp * | |
| 141 | − scale_factor; | |
| 140 | + plane_pixel_rate = src_width * mode->vtotal * fps; | |
| 141 | + plane_bit_rate = plane_pixel_rate * fmt->bpp; | |
| 142 | 142 | |
| 143 | − plane_prefill_bw = | |
| 144 | − src_width * hw_latency_lines * fps * fmt->bpp * | |
| 145 | − scale_factor * mode->vtotal; | |
| 143 | + plane_bw = plane_bit_rate * scale_factor; | |
| 144 | + | |
| 145 | + plane_prefill_bw = plane_bw * hw_latency_lines; | |
| 146 | 146 | |
| 147 | 147 | if ((vbp+vpw) > hw_latency_lines) |
| 148 | 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 | 733 | static int dpu_plane_atomic_check_pipe(struct dpu_plane *pdpu, |
| 734 | 734 | struct dpu_sw_pipe *pipe, |
| 735 | 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 | 739 | uint32_t min_src_size; |
| 740 | + struct dpu_kms *kms = _dpu_plane_get_kms(&pdpu->base); | |
| 739 | 741 | |
| 740 | 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 | 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 | 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 | 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 | 911 | if (ret) |
| 904 | 912 | return ret; |
| 905 | 913 | |
| 906 | 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 | 917 | if (ret) |
| 909 | 918 | return ret; |
| 910 | 919 | } |
| @@ -1774,13 +1774,6 @@ int dp_ctrl_on_link(struct dp_ctrl *dp_ctrl) · 1773 unmodified lines | ||
| 1774 | 1774 | return rc; |
| 1775 | 1775 | |
| 1776 | 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 | 1777 | training_step = DP_TRAINING_NONE; |
| 1785 | 1778 | rc = dp_ctrl_setup_main_link(ctrl, &training_step); |
| 1786 | 1779 | if (rc == 0) { |
| @@ -1832,6 +1825,12 @@ int dp_ctrl_on_link(struct dp_ctrl *dp_ctrl) · 45 unmodified lines | ||
| 1832 | 1825 | /* stop link training before start re training */ |
| 1833 | 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 | 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 | 1090 | } else if (dp_link_read_psr_error_status(link)) { |
| 1091 | 1091 | DRM_ERROR("PSR IRQ_HPD received\n"); |
| 1092 | 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 | 1094 | } else { |
| 1095 | 1095 | ret = dp_link_process_link_status_update(link); |
| 1096 | 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 | 1111 | dp_link->sink_request); |
| 1112 | 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 | 1083 | static void dsi_wait4video_eng_busy(struct msm_dsi_host *msm_host) |
| 1084 | 1084 | { |
| 1085 | + u32 data; | |
| 1086 | + | |
| 1085 | 1087 | if (!(msm_host->mode_flags & MIPI_DSI_MODE_VIDEO)) |
| 1086 | 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 | 1100 | if (msm_host->power_on && msm_host->enabled) { |
| 1089 | 1101 | dsi_wait4video_done(msm_host); |
| 1090 | 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 | 1908 | msm_host->irq = irq_of_parse_and_map(pdev->dev.of_node, 0); |
| 1897 | − if (msm_host->irq < 0) { | |
| 1898 | − ret = msm_host->irq; | |
| 1899 | − dev_err(&pdev->dev, "failed to get irq: %d\n", ret); | |
| 1900 | − return ret; | |
| 1909 | + if (!msm_host->irq) { | |
| 1910 | + dev_err(&pdev->dev, "failed to get irq\n"); | |
| 1911 | + return -EINVAL; | |
| 1901 | 1912 | } |
| 1902 | 1913 | |
| 1903 | 1914 | /* do not autoenable, will be enabled later */ |
| @@ -511,7 +511,7 @@ static int mdss_remove(struct platform_device *pdev) · 510 unmodified lines | ||
| 511 | 511 | static const struct msm_mdss_data msm8998_data = { |
| 512 | 512 | .ubwc_enc_version = UBWC_1_0, |
| 513 | 513 | .ubwc_dec_version = UBWC_1_0, |
| 514 | − .highest_bank_bit = 1, | |
| 514 | + .highest_bank_bit = 2, | |
| 515 | 515 | }; |
| 516 | 516 | |
| 517 | 517 | static const struct msm_mdss_data qcm2290_data = { |
| @@ -31,6 +31,7 @@ · 30 unmodified lines | ||
| 31 | 31 | |
| 32 | 32 | #include "nouveau_drv.h" |
| 33 | 33 | #include "nouveau_dma.h" |
| 34 | +#include "nouveau_exec.h" | |
| 34 | 35 | #include "nouveau_gem.h" |
| 35 | 36 | #include "nouveau_chan.h" |
| 36 | 37 | #include "nouveau_abi16.h" |
| @@ -183,6 +184,20 @@ nouveau_abi16_fini(struct nouveau_abi16 *abi16) · 146 unmodified lines | ||
| 183 | 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 | 201 | int |
| 187 | 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 | 262 | case NOUVEAU_GETPARAM_GRAPH_UNITS: |
| 248 | 263 | getparam->value = nvkm_gr_units(gr); |
| 249 | 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 | 271 | default: |
| 251 | 272 | NV_PRINTK(dbg, cli, "unknown parameter %lld\n", getparam->param); |
| 252 | 273 | return -EINVAL; |
| @@ -257,10 +257,7 @@ static int · 256 unmodified lines | ||
| 257 | 257 | nouveau_channel_ctor(struct nouveau_drm *drm, struct nvif_device *device, bool priv, u64 runm, |
| 258 | 258 | struct nouveau_channel **pchan) |
| 259 | 259 | { |
| 260 | − static const struct { | |
| 261 | − s32 oclass; | |
| 262 | − int version; | |
| 263 | − } hosts[] = { | |
| 260 | + const struct nvif_mclass hosts[] = { | |
| 264 | 261 | { AMPERE_CHANNEL_GPFIFO_B, 0 }, |
| 265 | 262 | { AMPERE_CHANNEL_GPFIFO_A, 0 }, |
| 266 | 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 | 442 | /* initialise dma tracking parameters */ |
| 446 | − switch (chan->user.oclass & 0x00ff) { | |
| 447 | − case 0x006b: | |
| 448 | − case 0x006e: | |
| 443 | + switch (chan->user.oclass) { | |
| 444 | + case NV03_CHANNEL_DMA: | |
| 445 | + case NV10_CHANNEL_DMA: | |
| 446 | + case NV17_CHANNEL_DMA: | |
| 447 | + case NV40_CHANNEL_DMA: | |
| 449 | 448 | chan->user_put = 0x40; |
| 450 | 449 | chan->user_get = 0x44; |
| 451 | 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 | 454 | chan->user_get = 0x44; |
| 456 | 455 | chan->user_get_hi = 0x60; |
| 457 | 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 | 458 | chan->dma.ib_put = 0; |
| 460 | 459 | chan->dma.ib_free = chan->dma.ib_max - chan->dma.ib_put; |
| 461 | 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 | 49 | /* Maximum push buffer size. */ |
| 50 | 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 | 55 | /* Object handles - for stuff that's doesn't use handle == oclass. */ |
| 53 | 56 | enum { |
| 54 | 57 | NvDmaFB = 0x80000002, |
| @@ -379,7 +379,7 @@ nouveau_exec_ioctl_exec(struct drm_device *dev, · 378 unmodified lines | ||
| 379 | 379 | struct nouveau_channel *chan = NULL; |
| 380 | 380 | struct nouveau_exec_job_args args = {}; |
| 381 | 381 | struct drm_nouveau_exec *req = data; |
| 382 | − int ret = 0; | |
| 382 | + int push_max, ret = 0; | |
| 383 | 383 | |
| 384 | 384 | if (unlikely(!abi16)) |
| 385 | 385 | return -ENOMEM; |
| @@ -404,9 +404,10 @@ nouveau_exec_ioctl_exec(struct drm_device *dev, · 18 unmodified lines | ||
| 404 | 404 | if (!chan->dma.ib_max) |
| 405 | 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 | 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 | 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 | 51 | int nouveau_exec_ioctl_exec(struct drm_device *dev, void *data, |
| 52 | 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 | 64 | #endif |
| @@ -1342,9 +1342,7 @@ static const struct panel_init_cmd starry_himax83102_j02_init_cmd[] = { · 1341 unmodified lines | ||
| 1342 | 1342 | _INIT_DCS_CMD(0xB1, 0x01, 0xBF, 0x11), |
| 1343 | 1343 | _INIT_DCS_CMD(0xCB, 0x86), |
| 1344 | 1344 | _INIT_DCS_CMD(0xD2, 0x3C, 0xFA), |
| 1345 | − _INIT_DCS_CMD(0xE9, 0xC5), | |
| 1346 | − _INIT_DCS_CMD(0xD3, 0x00, 0x00, 0x00, 0x00, 0x80, 0x0C, 0x01), | |
| 1347 | − _INIT_DCS_CMD(0xE9, 0x3F), | |
| 1345 | + _INIT_DCS_CMD(0xD3, 0x00, 0x00, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x0C, 0x01), | |
| 1348 | 1346 | _INIT_DCS_CMD(0xE7, 0x02, 0x00, 0x28, 0x01, 0x7E, 0x0F, 0x7E, 0x10, 0xA0, 0x00, 0x00, 0x20, 0x40, 0x50, 0x40), |
| 1349 | 1347 | _INIT_DCS_CMD(0xBD, 0x02), |
| 1350 | 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 | 930 | if (next) { |
| 931 | 931 | next->s_fence->scheduled.timestamp = |
| 932 | − job->s_fence->finished.timestamp; | |
| 932 | + dma_fence_timestamp(&job->s_fence->finished); | |
| 933 | 933 | /* start TO timer for next job */ |
| 934 | 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 | 119 | kunit_release_action(test, |
| 120 | 120 | kunit_action_platform_driver_unregister, |
| 121 | − pdev); | |
| 121 | + &fake_platform_driver); | |
| 122 | 122 | } |
| 123 | 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 | 746 | ret = devm_aperture_acquire_from_firmware(dev, res->start, resource_size(res)); |
| 747 | 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 | 749 | return ERR_PTR(ret); |
| 750 | 750 | } |
| 751 | 751 | |
| @@ -34,6 +34,8 @@ · 33 unmodified lines | ||
| 34 | 34 | |
| 35 | 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 | 39 | vmw_bo_unmap(vbo); |
| 38 | 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 | 499 | if (!(flags & drm_vmw_synccpu_allow_cs)) { |
| 498 | 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 | 505 | return ret; |
| @@ -539,7 +541,7 @@ int vmw_user_bo_synccpu_ioctl(struct drm_device *dev, void *data, · 35 unmodified lines | ||
| 539 | 541 | return ret; |
| 540 | 542 | |
| 541 | 543 | ret = vmw_user_bo_synccpu_grab(vbo, arg->flags); |
| 542 | − vmw_user_bo_unref(vbo); | |
| 544 | + vmw_user_bo_unref(&vbo); | |
| 543 | 545 | if (unlikely(ret != 0)) { |
| 544 | 546 | if (ret == -ERESTARTSYS || ret == -EBUSY) |
| 545 | 547 | return -EBUSY; |
| @@ -612,7 +614,6 @@ int vmw_user_bo_lookup(struct drm_file *filp, · 66 unmodified lines | ||
| 612 | 614 | } |
| 613 | 615 | |
| 614 | 616 | *out = to_vmw_bo(gobj); |
| 615 | − ttm_bo_get(&(*out)->tbo); | |
| 616 | 617 | |
| 617 | 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 | 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) { | |
| 201 | − ttm_bo_put(&vbo->tbo); | |
| 202 | − drm_gem_object_put(&vbo->tbo.base); | |
| 203 | − } | |
| 200 | + drm_gem_object_get(&vbo->tbo.base); | |
| 201 | + return vbo; | |
| 202 | +} | |
| 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 | 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 | 432 | * for the new COTable. Initially pin the buffer object to make sure |
| 433 | 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 | 436 | if (ret) { |
| 437 | 437 | DRM_ERROR("Failed initializing new cotable MOB.\n"); |
| 438 | 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 | 503 | vmw_resource_mob_attach(res); |
| 504 | 504 | /* Let go of the old mob. */ |
| 505 | − vmw_bo_unreference(&old_buf); | |
| 505 | + vmw_user_bo_unref(&old_buf); | |
| 506 | 506 | res->id = vcotbl->type; |
| 507 | 507 | |
| 508 | 508 | ret = dma_resv_reserve_fences(bo->base.resv, 1); |
| @@ -521,7 +521,7 @@ out_map_new: · 12 unmodified lines | ||
| 521 | 521 | out_wait: |
| 522 | 522 | ttm_bo_unpin(bo); |
| 523 | 523 | ttm_bo_unreserve(bo); |
| 524 | − vmw_bo_unreference(&buf); | |
| 524 | + vmw_user_bo_unref(&buf); | |
| 525 | 525 | |
| 526 | 526 | out_done: |
| 527 | 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 | 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 | 860 | extern int vmw_gem_object_create_with_handle(struct vmw_private *dev_priv, |
| 857 | 861 | struct drm_file *filp, |
| 858 | 862 | uint32_t size, |
| @@ -1151,7 +1151,7 @@ static int vmw_translate_mob_ptr(struct vmw_private *dev_priv, · 1150 unmodified lines | ||
| 1151 | 1151 | SVGAMobId *id, |
| 1152 | 1152 | struct vmw_bo **vmw_bo_p) |
| 1153 | 1153 | { |
| 1154 | − struct vmw_bo *vmw_bo; | |
| 1154 | + struct vmw_bo *vmw_bo, *tmp_bo; | |
| 1155 | 1155 | uint32_t handle = *id; |
| 1156 | 1156 | struct vmw_relocation *reloc; |
| 1157 | 1157 | int ret; |
| @@ -1164,7 +1164,8 @@ static int vmw_translate_mob_ptr(struct vmw_private *dev_priv, · 6 unmodified lines | ||
| 1164 | 1164 | } |
| 1165 | 1165 | vmw_bo_placement_set(vmw_bo, VMW_BO_DOMAIN_MOB, VMW_BO_DOMAIN_MOB); |
| 1166 | 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 | 1169 | if (unlikely(ret != 0)) |
| 1169 | 1170 | return ret; |
| 1170 | 1171 | |
| @@ -1206,7 +1207,7 @@ static int vmw_translate_guest_ptr(struct vmw_private *dev_priv, · 35 unmodified lines | ||
| 1206 | 1207 | SVGAGuestPtr *ptr, |
| 1207 | 1208 | struct vmw_bo **vmw_bo_p) |
| 1208 | 1209 | { |
| 1209 | − struct vmw_bo *vmw_bo; | |
| 1210 | + struct vmw_bo *vmw_bo, *tmp_bo; | |
| 1210 | 1211 | uint32_t handle = ptr->gmrId; |
| 1211 | 1212 | struct vmw_relocation *reloc; |
| 1212 | 1213 | int ret; |
| @@ -1220,7 +1221,8 @@ static int vmw_translate_guest_ptr(struct vmw_private *dev_priv, · 7 unmodified lines | ||
| 1220 | 1221 | vmw_bo_placement_set(vmw_bo, VMW_BO_DOMAIN_GMR | VMW_BO_DOMAIN_VRAM, |
| 1221 | 1222 | VMW_BO_DOMAIN_GMR | VMW_BO_DOMAIN_VRAM); |
| 1222 | 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 | 1226 | if (unlikely(ret != 0)) |
| 1225 | 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 | 1622 | VMW_DECLARE_CMD_VAR(*cmd, SVGA3dCmdSetTextureState); |
| 1621 | 1623 | SVGA3dTextureState *last_state = (SVGA3dTextureState *) |
| 1622 | − ((unsigned long) header + header->size + sizeof(header)); | |
| 1624 | + ((unsigned long) header + header->size + sizeof(*header)); | |
| 1623 | 1625 | SVGA3dTextureState *cur_state = (SVGA3dTextureState *) |
| 1624 | 1626 | ((unsigned long) header + sizeof(*cmd)); |
| 1625 | 1627 | struct vmw_resource *ctx; |
| @@ -111,6 +111,20 @@ static const struct drm_gem_object_funcs vmw_gem_object_funcs = { · 110 unmodified lines | ||
| 111 | 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 | 128 | int vmw_gem_object_create_with_handle(struct vmw_private *dev_priv, |
| 115 | 129 | struct drm_file *filp, |
| 116 | 130 | uint32_t size, |
| @@ -126,12 +140,10 @@ int vmw_gem_object_create_with_handle(struct vmw_private *dev_priv, · 9 unmodified lines | ||
| 126 | 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 | 144 | if (ret != 0) |
| 131 | 145 | goto out_no_bo; |
| 132 | 146 | |
| 133 | − (*p_vbo)->tbo.base.funcs = &vmw_gem_object_funcs; | |
| 134 | − | |
| 135 | 147 | ret = drm_gem_handle_create(filp, &(*p_vbo)->tbo.base, handle); |
| 136 | 148 | out_no_bo: |
| 137 | 149 | return ret; |
| @@ -1471,8 +1471,8 @@ static int vmw_create_bo_proxy(struct drm_device *dev, · 1470 unmodified lines | ||
| 1471 | 1471 | /* Reserve and switch the backing mob. */ |
| 1472 | 1472 | mutex_lock(&res->dev_priv->cmdbuf_mutex); |
| 1473 | 1473 | (void) vmw_resource_reserve(res, false, true); |
| 1474 | − vmw_bo_unreference(&res->guest_memory_bo); | |
| 1475 | − res->guest_memory_bo = vmw_bo_reference(bo_mob); | |
| 1474 | + vmw_user_bo_unref(&res->guest_memory_bo); | |
| 1475 | + res->guest_memory_bo = vmw_user_bo_ref(bo_mob); | |
| 1476 | 1476 | res->guest_memory_offset = 0; |
| 1477 | 1477 | vmw_resource_unreserve(res, false, false, false, NULL, 0); |
| 1478 | 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 | 1666 | err_out: |
| 1667 | 1667 | /* vmw_user_lookup_handle takes one ref so does new_fb */ |
| 1668 | 1668 | if (bo) |
| 1669 | − vmw_user_bo_unref(bo); | |
| 1669 | + vmw_user_bo_unref(&bo); | |
| 1670 | 1670 | if (surface) |
| 1671 | 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 | 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 | 456 | out_unlock: |
| 457 | 457 | mutex_unlock(&overlay->mutex); |
| @@ -141,7 +141,7 @@ static void vmw_resource_release(struct kref *kref) · 140 unmodified lines | ||
| 141 | 141 | if (res->coherent) |
| 142 | 142 | vmw_bo_dirty_release(res->guest_memory_bo); |
| 143 | 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 | 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 | 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 | 342 | if (unlikely(ret != 0)) |
| 343 | 343 | goto out_no_bo; |
| 344 | 344 | |
| @@ -457,11 +457,11 @@ void vmw_resource_unreserve(struct vmw_resource *res, · 112 unmodified lines | ||
| 457 | 457 | vmw_resource_mob_detach(res); |
| 458 | 458 | if (res->coherent) |
| 459 | 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 | 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 | 467 | * The validation code should already have added a |
| @@ -551,7 +551,7 @@ out_no_reserve: · 83 unmodified lines | ||
| 551 | 551 | ttm_bo_put(val_buf->bo); |
| 552 | 552 | val_buf->bo = NULL; |
| 553 | 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 | 556 | return ret; |
| 557 | 557 | } |
| @@ -727,7 +727,7 @@ int vmw_resource_validate(struct vmw_resource *res, bool intr, · 169 unmodified lines | ||
| 727 | 727 | goto out_no_validate; |
| 728 | 728 | else if (!res->func->needs_guest_memory && res->guest_memory_bo) { |
| 729 | 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 | 733 | return 0; |
| @@ -180,7 +180,7 @@ static int vmw_gb_shader_init(struct vmw_private *dev_priv, · 179 unmodified lines | ||
| 180 | 180 | |
| 181 | 181 | res->guest_memory_size = size; |
| 182 | 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 | 184 | res->guest_memory_offset = offset; |
| 185 | 185 | } |
| 186 | 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 | 809 | shader_type, num_input_sig, |
| 810 | 810 | num_output_sig, tfile, shader_handle); |
| 811 | 811 | out_bad_arg: |
| 812 | − vmw_user_bo_unref(buffer); | |
| 812 | + vmw_user_bo_unref(&buffer); | |
| 813 | 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 | 686 | container_of(base, struct vmw_user_surface, prime.base); |
| 687 | 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 | 689 | *p_base = NULL; |
| 693 | 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 | 852 | * expect a backup buffer to be present. |
| 856 | 853 | */ |
| 857 | 854 | if (dev_priv->has_mob && req->shareable) { |
| 858 | − uint32_t backup_handle; | |
| 859 | − | |
| 860 | − ret = vmw_gem_object_create_with_handle(dev_priv, | |
| 861 | − file_priv, | |
| 862 | − res->guest_memory_size, | |
| 863 | − &backup_handle, | |
| 864 | − &res->guest_memory_bo); | |
| 855 | + struct vmw_bo_params params = { | |
| 856 | + .domain = VMW_BO_DOMAIN_SYS, | |
| 857 | + .busy_domain = VMW_BO_DOMAIN_SYS, | |
| 858 | + .bo_type = ttm_bo_type_device, | |
| 859 | + .size = res->guest_memory_size, | |
| 860 | + .pin = false | |
| 861 | + }; | |
| 862 | + | |
| 863 | + ret = vmw_gem_object_create(dev_priv, | |
| 864 | + ¶ms, | |
| 865 | + &res->guest_memory_bo); | |
| 865 | 866 | if (unlikely(ret != 0)) { |
| 866 | 867 | vmw_resource_unreference(&res); |
| 867 | 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 | 872 | tmp = vmw_resource_reference(&srf->res); |
| @@ -1512,7 +1507,7 @@ vmw_gb_surface_define_internal(struct drm_device *dev, · 634 unmodified lines | ||
| 1512 | 1507 | if (ret == 0) { |
| 1513 | 1508 | if (res->guest_memory_bo->tbo.base.size < res->guest_memory_size) { |
| 1514 | 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 | 1511 | ret = -EINVAL; |
| 1517 | 1512 | goto out_unlock; |
| 1518 | 1513 | } else { |
| @@ -1526,8 +1521,6 @@ vmw_gb_surface_define_internal(struct drm_device *dev, · 7 unmodified lines | ||
| 1526 | 1521 | res->guest_memory_size, |
| 1527 | 1522 | &backup_handle, |
| 1528 | 1523 | &res->guest_memory_bo); |
| 1529 | − if (ret == 0) | |
| 1530 | − vmw_bo_reference(res->guest_memory_bo); | |
| 1531 | 1524 | } |
| 1532 | 1525 | |
| 1533 | 1526 | if (unlikely(ret != 0)) { |
| @@ -799,6 +799,8 @@ config HID_NVIDIA_SHIELD · 798 unmodified lines | ||
| 799 | 799 | tristate "NVIDIA SHIELD devices" |
| 800 | 800 | depends on USB_HID |
| 801 | 801 | depends on BT_HIDP |
| 802 | + depends on LEDS_CLASS | |
| 803 | + select POWER_SUPPLY | |
| 802 | 804 | help |
| 803 | 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 | 130 | return -ENODEV; |
| 131 | 131 | |
| 132 | 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 | 137 | boot_hid_input = list_first_entry(&boot_hid->inputs, |
| 134 | 138 | struct hid_input, list); |
| 135 | 139 | |
| @@ -425,6 +425,7 @@ · 424 unmodified lines | ||
| 425 | 425 | #define I2C_DEVICE_ID_HP_SPECTRE_X360_13T_AW100 0x29F5 |
| 426 | 426 | #define I2C_DEVICE_ID_HP_SPECTRE_X360_14T_EA100_V1 0x2BED |
| 427 | 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 | 430 | #define USB_VENDOR_ID_ELECOM 0x056e |
| 430 | 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 | 409 | HID_BATTERY_QUIRK_IGNORE }, |
| 410 | 410 | { HID_I2C_DEVICE(USB_VENDOR_ID_ELAN, I2C_DEVICE_ID_HP_SPECTRE_X360_14T_EA100_V2), |
| 411 | 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 | 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 | 4521 | if (will_restart) { |
| 4521 | 4522 | /* Reset the HID node state */ |
| @@ -4677,6 +4678,8 @@ static const struct hid_device_id hidpp_devices[] = { · 155 unmodified lines | ||
| 4677 | 4678 | HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_LOGITECH, 0xb008) }, |
| 4678 | 4679 | { /* MX Master mouse over Bluetooth */ |
| 4679 | 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 | 4683 | { /* MX Ergo trackball over Bluetooth */ |
| 4681 | 4684 | HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_LOGITECH, 0xb01d) }, |
| 4682 | 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 | 2144 | USB_DEVICE_ID_MTP_STM)}, |
| 2145 | 2145 | |
| 2146 | 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 | 2151 | { .driver_data = MT_CLS_WIN_8_FORCE_MULTI_INPUT, |
| 2148 | 2152 | HID_DEVICE(BUS_I2C, HID_GROUP_MULTITOUCH_WIN_8, |
| 2149 | 2153 | USB_VENDOR_ID_SYNAPTICS, 0xce08) }, |
| @@ -2088,7 +2088,9 @@ static int joycon_read_info(struct joycon_ctlr *ctlr) · 2087 unmodified lines | ||
| 2088 | 2088 | struct joycon_input_report *report; |
| 2089 | 2089 | |
| 2090 | 2090 | req.subcmd_id = JC_SUBCMD_REQ_DEV_INFO; |
| 2091 | + mutex_lock(&ctlr->output_mutex); | |
| 2091 | 2092 | ret = joycon_send_subcmd(ctlr, &req, 0, HZ); |
| 2093 | + mutex_unlock(&ctlr->output_mutex); | |
| 2092 | 2094 | if (ret) { |
| 2093 | 2095 | hid_err(ctlr->hdev, "Failed to get joycon info; ret=%d\n", ret); |
| 2094 | 2096 | return ret; |
| @@ -2117,6 +2119,85 @@ static int joycon_read_info(struct joycon_ctlr *ctlr) · 22 unmodified lines | ||
| 2117 | 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 | 2201 | /* Common handler for parsing inputs */ |
| 2121 | 2202 | static int joycon_ctlr_read_handler(struct joycon_ctlr *ctlr, u8 *data, |
| 2122 | 2203 | int size) |
| @@ -2248,85 +2329,19 @@ static int nintendo_hid_probe(struct hid_device *hdev, · 125 unmodified lines | ||
| 2248 | 2329 | |
| 2249 | 2330 | hid_device_io_start(hdev); |
| 2250 | 2331 | |
| 2251 | − /* Initialize the controller */ | |
| 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); | |
| 2332 | + ret = joycon_init(hdev); | |
| 2282 | 2333 | if (ret) { |
| 2283 | − /* | |
| 2284 | − * We can function with default calibration, but it may be | |
| 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; | |
| 2334 | + hid_err(hdev, "Failed to initialize controller; ret=%d\n", ret); | |
| 2335 | + goto err_close; | |
| 2319 | 2336 | } |
| 2320 | 2337 | |
| 2321 | 2338 | ret = joycon_read_info(ctlr); |
| 2322 | 2339 | if (ret) { |
| 2323 | 2340 | hid_err(hdev, "Failed to retrieve controller info; ret=%d\n", |
| 2324 | 2341 | ret); |
| 2325 | − goto err_mutex; | |
| 2342 | + goto err_close; | |
| 2326 | 2343 | } |
| 2327 | 2344 | |
| 2328 | − mutex_unlock(&ctlr->output_mutex); | |
| 2329 | − | |
| 2330 | 2345 | /* Initialize the leds */ |
| 2331 | 2346 | ret = joycon_leds_create(ctlr); |
| 2332 | 2347 | if (ret) { |
| @@ -2352,8 +2367,6 @@ static int nintendo_hid_probe(struct hid_device *hdev, · 19 unmodified lines | ||
| 2352 | 2367 | hid_dbg(hdev, "probe - success\n"); |
| 2353 | 2368 | return 0; |
| 2354 | 2369 | |
| 2355 | −err_mutex: | |
| 2356 | − mutex_unlock(&ctlr->output_mutex); | |
| 2357 | 2370 | err_close: |
| 2358 | 2371 | hid_hw_close(hdev); |
| 2359 | 2372 | err_stop: |
| @@ -2383,6 +2396,20 @@ static void nintendo_hid_remove(struct hid_device *hdev) · 23 unmodified lines | ||
| 2383 | 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 | 2413 | static const struct hid_device_id nintendo_hid_devices[] = { |
| 2387 | 2414 | { HID_USB_DEVICE(USB_VENDOR_ID_NINTENDO, |
| 2388 | 2415 | USB_DEVICE_ID_NINTENDO_PROCON) }, |
| @@ -2404,6 +2431,10 @@ static struct hid_driver nintendo_hid_driver = { · 15 unmodified lines | ||
| 2404 | 2431 | .probe = nintendo_hid_probe, |
| 2405 | 2432 | .remove = nintendo_hid_remove, |
| 2406 | 2433 | .raw_event = nintendo_hid_event, |
| 2434 | + | |
| 2435 | +#ifdef CONFIG_PM | |
| 2436 | + .resume = nintendo_hid_resume, | |
| 2437 | +#endif | |
| 2407 | 2438 | }; |
| 2408 | 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 | 801 | led->name = devm_kasprintf(&ts->base.hdev->dev, GFP_KERNEL, |
| 802 | 802 | "thunderstrike%d:blue:led", ts->id); |
| 803 | 803 | led->max_brightness = 1; |
| 804 | − led->flags = LED_CORE_SUSPENDRESUME; | |
| 804 | + led->flags = LED_CORE_SUSPENDRESUME | LED_RETAIN_AT_SHUTDOWN; | |
| 805 | 805 | led->brightness_get = &thunderstrike_led_get_brightness; |
| 806 | 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 | 1058 | ret = hid_hw_start(hdev, HID_CONNECT_HIDINPUT); |
| 1059 | 1059 | if (ret) { |
| 1060 | 1060 | hid_err(hdev, "Failed to start HID device\n"); |
| 1061 | − goto err_haptics; | |
| 1061 | + goto err_ts_create; | |
| 1062 | 1062 | } |
| 1063 | 1063 | |
| 1064 | 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 | 1074 | err_stop: |
| 1075 | 1075 | hid_hw_stop(hdev); |
| 1076 | −err_haptics: | |
| 1076 | +err_ts_create: | |
| 1077 | + power_supply_unregister(ts->base.battery_dev.psy); | |
| 1077 | 1078 | if (ts->haptics_dev) |
| 1078 | 1079 | input_unregister_device(ts->haptics_dev); |
| 1080 | + led_classdev_unregister(&ts->led_dev); | |
| 1081 | + ida_free(&thunderstrike_ida, ts->id); | |
| 1079 | 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 | 2155 | return ret; |
| 2156 | 2156 | |
| 2157 | 2157 | err: |
| 2158 | + usb_free_urb(sc->ghl_urb); | |
| 2159 | + | |
| 2158 | 2160 | hid_hw_stop(hdev); |
| 2159 | 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 | 390 | ret = hid_hw_raw_request(hdev, arctis_1_battery_request[0], |
| 391 | 391 | write_buf, sizeof(arctis_1_battery_request), |
| 392 | 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 | 394 | hid_err(hdev, "hid_hw_raw_request() failed with %d\n", ret); |
| 395 | 395 | ret = -ENODATA; |
| 396 | 396 | } |
| @@ -998,45 +998,29 @@ static int i2c_hid_core_resume(struct i2c_hid *ihid) · 997 unmodified lines | ||
| 998 | 998 | return hid_driver_reset_resume(hid); |
| 999 | 999 | } |
| 1000 | 1000 | |
| 1001 | −/** | |
| 1002 | − * __do_i2c_hid_core_initial_power_up() - First time power up of the i2c-hid device. | |
| 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. | |
| 1001 | +/* | |
| 1002 | + * Check that the device exists and parse the HID descriptor. | |
| 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 | 1006 | struct i2c_client *client = ihid->client; |
| 1016 | 1007 | struct hid_device *hid = ihid->hid; |
| 1017 | 1008 | int ret; |
| 1018 | 1009 | |
| 1019 | − ret = i2c_hid_core_power_up(ihid); | |
| 1020 | − if (ret) | |
| 1021 | − return ret; | |
| 1022 | − | |
| 1023 | 1010 | /* Make sure there is something at this address */ |
| 1024 | 1011 | ret = i2c_smbus_read_byte(client); |
| 1025 | 1012 | if (ret < 0) { |
| 1026 | 1013 | i2c_hid_dbg(ihid, "nothing at this address: %d\n", ret); |
| 1027 | − ret = -ENXIO; | |
| 1028 | − goto err; | |
| 1014 | + return -ENXIO; | |
| 1029 | 1015 | } |
| 1030 | 1016 | |
| 1031 | 1017 | ret = i2c_hid_fetch_hid_descriptor(ihid); |
| 1032 | 1018 | if (ret < 0) { |
| 1033 | 1019 | dev_err(&client->dev, |
| 1034 | 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 | 1024 | hid->version = le16_to_cpu(ihid->hdesc.bcdVersion); |
| 1041 | 1025 | hid->vendor = le16_to_cpu(ihid->hdesc.wVendorID); |
| 1042 | 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 | 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 | 1048 | ret = hid_add_device(hid); |
| 1054 | 1049 | if (ret) { |
| 1055 | 1050 | if (ret != -ENODEV) |
| 1056 | 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 | 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 | 1078 | i2c_hid_core_power_down(ihid); |
| 1079 | + | |
| 1064 | 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 | 1093 | * steps. |
| 1078 | 1094 | */ |
| 1079 | 1095 | if (!hid->version) |
| 1080 | − ret = __do_i2c_hid_core_initial_power_up(ihid); | |
| 1096 | + ret = i2c_hid_core_probe_panel_follower(ihid); | |
| 1081 | 1097 | else |
| 1082 | 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 | 1152 | struct device *dev = &ihid->client->dev; |
| 1137 | 1153 | int ret; |
| 1138 | 1154 | |
| 1139 | − ihid->is_panel_follower = true; | |
| 1140 | 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 | 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 | 1174 | int i2c_hid_core_probe(struct i2c_client *client, struct i2chid_ops *ops, |
| 1184 | 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 | 1202 | ihid->ops = ops; |
| 1212 | 1203 | ihid->client = client; |
| 1213 | 1204 | ihid->wHIDDescRegister = cpu_to_le16(hid_descriptor_address); |
| 1205 | + ihid->is_panel_follower = drm_is_panel_follower(&client->dev); | |
| 1214 | 1206 | |
| 1215 | 1207 | init_waitqueue_head(&ihid->wait); |
| 1216 | 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 | 1216 | return ret; |
| 1225 | 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 | 1219 | hid = hid_allocate_device(); |
| 1232 | 1220 | if (IS_ERR(hid)) { |
| 1233 | 1221 | ret = PTR_ERR(hid); |
| 1234 | − goto err_irq; | |
| 1222 | + goto err_free_buffers; | |
| 1235 | 1223 | } |
| 1236 | 1224 | |
| 1237 | 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 | 1230 | hid->bus = BUS_I2C; |
| 1243 | 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 | 1256 | if (ret) |
| 1247 | − goto err_mem_free; | |
| 1257 | + goto err_free_irq; | |
| 1248 | 1258 | |
| 1249 | 1259 | return 0; |
| 1250 | 1260 | |
| 1251 | −err_mem_free: | |
| 1252 | − hid_destroy_device(hid); | |
| 1253 | − | |
| 1254 | −err_irq: | |
| 1261 | +err_free_irq: | |
| 1255 | 1262 | free_irq(client->irq, ihid); |
| 1256 | − | |
| 1257 | −err_buffers_allocated: | |
| 1263 | +err_power_down: | |
| 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 | 1269 | i2c_hid_free_buffers(ihid); |
| 1259 | 1270 | |
| 1260 | 1271 | return ret; |
| @@ -1266,7 +1277,14 @@ void i2c_hid_core_remove(struct i2c_client *client) · 5 unmodified lines | ||
| 1266 | 1277 | struct i2c_hid *ihid = i2c_get_clientdata(client); |
| 1267 | 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 | 1289 | hid = ihid->hid; |
| 1272 | 1290 | hid_destroy_device(hid); |
| @@ -133,6 +133,14 @@ static int enable_gpe(struct device *dev) · 132 unmodified lines | ||
| 133 | 133 | } |
| 134 | 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 | 144 | acpi_sts = acpi_enable_gpe(wakeup->gpe_device, wakeup->gpe_number); |
| 137 | 145 | if (ACPI_FAILURE(acpi_sts)) { |
| 138 | 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 | 611 | flat_buf->vaddr = dma_alloc_noncoherent(real_dev, etr_buf->size, |
| 612 | 612 | &flat_buf->daddr, |
| 613 | − DMA_FROM_DEVICE, GFP_KERNEL); | |
| 613 | + DMA_FROM_DEVICE, | |
| 614 | + GFP_KERNEL | __GFP_NOWARN); | |
| 614 | 615 | if (!flat_buf->vaddr) { |
| 615 | 616 | kfree(flat_buf); |
| 616 | 617 | return -ENOMEM; |
| @@ -1173,16 +1174,6 @@ static struct etr_buf *tmc_etr_get_sysfs_buffer(struct coresight_device *csdev) · 556 unmodified lines | ||
| 1173 | 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 | 1178 | * If we don't have a buffer or it doesn't match the requested size, |
| 1188 | 1179 | * use the buffer allocated above. Otherwise reuse the existing buffer. |
| @@ -1204,7 +1195,7 @@ out: · 15 unmodified lines | ||
| 1204 | 1195 | |
| 1205 | 1196 | static int tmc_enable_etr_sink_sysfs(struct coresight_device *csdev) |
| 1206 | 1197 | { |
| 1207 | − int ret; | |
| 1198 | + int ret = 0; | |
| 1208 | 1199 | unsigned long flags; |
| 1209 | 1200 | struct tmc_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent); |
| 1210 | 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 | 1204 | return PTR_ERR(sysfs_buf); |
| 1214 | 1205 | |
| 1215 | 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 | 1218 | ret = tmc_etr_enable_hw(drvdata, sysfs_buf); |
| 1217 | 1219 | if (!ret) { |
| 1218 | 1220 | drvdata->mode = CS_MODE_SYSFS; |
| 1219 | 1221 | atomic_inc(&csdev->refcnt); |
| 1220 | 1222 | } |
| 1221 | 1223 | |
| 1224 | +out: | |
| 1222 | 1225 | spin_unlock_irqrestore(&drvdata->spinlock, flags); |
| 1223 | 1226 | |
| 1224 | 1227 | if (!ret) |
| @@ -177,6 +177,7 @@ struct ad7192_chip_info { · 176 unmodified lines | ||
| 177 | 177 | struct ad7192_state { |
| 178 | 178 | const struct ad7192_chip_info *chip_info; |
| 179 | 179 | struct regulator *avdd; |
| 180 | + struct regulator *vref; | |
| 180 | 181 | struct clk *mclk; |
| 181 | 182 | u16 int_vref_mv; |
| 182 | 183 | u32 fclk; |
| @@ -1008,10 +1009,30 @@ static int ad7192_probe(struct spi_device *spi) · 825 unmodified lines | ||
| 1008 | 1009 | if (ret) |
| 1009 | 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 | − if (ret < 0) { | |
| 1013 | − dev_err(&spi->dev, "Device tree error, reference voltage undefined\n"); | |
| 1014 | − return ret; | |
| 1012 | + st->vref = devm_regulator_get_optional(&spi->dev, "vref"); | |
| 1013 | + if (IS_ERR(st->vref)) { | |
| 1014 | + if (PTR_ERR(st->vref) != -ENODEV) | |
| 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 | 1037 | st->int_vref_mv = ret / 1000; |
| 1017 | 1038 | |
| @@ -38,8 +38,8 @@ · 37 unmodified lines | ||
| 38 | 38 | #define IMX8QXP_ADR_ADC_FCTRL 0x30 |
| 39 | 39 | #define IMX8QXP_ADR_ADC_SWTRIG 0x34 |
| 40 | 40 | #define IMX8QXP_ADR_ADC_TCTRL(tid) (0xc0 + (tid) * 4) |
| 41 | −#define IMX8QXP_ADR_ADC_CMDH(cid) (0x100 + (cid) * 8) | |
| 42 | −#define IMX8QXP_ADR_ADC_CMDL(cid) (0x104 + (cid) * 8) | |
| 41 | +#define IMX8QXP_ADR_ADC_CMDL(cid) (0x100 + (cid) * 8) | |
| 42 | +#define IMX8QXP_ADR_ADC_CMDH(cid) (0x104 + (cid) * 8) | |
| 43 | 43 | #define IMX8QXP_ADR_ADC_RESFIFO 0x300 |
| 44 | 44 | #define IMX8QXP_ADR_ADC_TST 0xffc |
| 45 | 45 | |
| @@ -24,6 +24,8 @@ config AD74413R · 23 unmodified lines | ||
| 24 | 24 | depends on GPIOLIB && SPI |
| 25 | 25 | select REGMAP_SPI |
| 26 | 26 | select CRC8 |
| 27 | + select IIO_BUFFER | |
| 28 | + select IIO_TRIGGERED_BUFFER | |
| 27 | 29 | help |
| 28 | 30 | Say yes here to build support for Analog Devices AD74412R/AD74413R |
| 29 | 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 | 191 | * Ignore samples if the buffer is not set: it is needed if the ODR is |
| 192 | 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 | 198 | return 0; |
| 196 | 199 | |
| 197 | 200 | out = (s16 *)st->samples; |
| @@ -210,6 +213,7 @@ int cros_ec_sensors_push_data(struct iio_dev *indio_dev, · 12 unmodified lines | ||
| 210 | 213 | iio_push_to_buffers_with_timestamp(indio_dev, st->samples, |
| 211 | 214 | timestamp + delta); |
| 212 | 215 | |
| 216 | + iio_device_release_buffer_mode(indio_dev); | |
| 213 | 217 | return 0; |
| 214 | 218 | } |
| 215 | 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 | 142 | enum ad3542r_id { |
| 143 | − AD3542R_ID = 0x4008, | |
| 144 | − AD3552R_ID = 0x4009, | |
| 143 | + AD3542R_ID = 0x4009, | |
| 144 | + AD3552R_ID = 0x4008, | |
| 145 | 145 | }; |
| 146 | 146 | |
| 147 | 147 | enum ad3552r_ch_output_range { |
| @@ -351,9 +351,9 @@ static int admv1013_update_mixer_vgate(struct admv1013_state *st) · 350 unmodified lines | ||
| 351 | 351 | if (vcm < 0) |
| 352 | 352 | return vcm; |
| 353 | 353 | |
| 354 | − if (vcm < 1800000) | |
| 354 | + if (vcm <= 1800000) | |
| 355 | 355 | mixer_vgate = (2389 * vcm / 1000000 + 8100) / 100; |
| 356 | − else if (vcm > 1800000 && vcm < 2600000) | |
| 356 | + else if (vcm > 1800000 && vcm <= 2600000) | |
| 357 | 357 | mixer_vgate = (2375 * vcm / 1000000 + 125) / 100; |
| 358 | 358 | else |
| 359 | 359 | return -EINVAL; |
| @@ -2,6 +2,8 @@ · 1 unmodified line | ||
| 2 | 2 | |
| 3 | 3 | config BOSCH_BNO055 |
| 4 | 4 | tristate |
| 5 | + select IIO_BUFFER | |
| 6 | + select IIO_TRIGGERED_BUFFER | |
| 5 | 7 | |
| 6 | 8 | config BOSCH_BNO055_SERIAL |
| 7 | 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 | 1514 | out: |
| 1515 | 1515 | mutex_unlock(&data->vcnl4000_lock); |
| 1516 | − data->chip_spec->set_power_state(data, data->ps_int || data->als_int); | |
| 1517 | 1516 | |
| 1518 | 1517 | return ret; |
| 1519 | 1518 | } |
| @@ -2179,7 +2179,7 @@ int bmp280_common_probe(struct device *dev, · 2178 unmodified lines | ||
| 2179 | 2179 | * however as it happens, the BMP085 shares the chip ID of BMP180 |
| 2180 | 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 | 2183 | ret = bmp085_fetch_eoc_irq(dev, name, irq, data); |
| 2184 | 2184 | if (ret) |
| 2185 | 2185 | return ret; |
| @@ -57,8 +57,8 @@ · 56 unmodified lines | ||
| 57 | 57 | #define DPS310_RESET_MAGIC 0x09 |
| 58 | 58 | #define DPS310_COEF_BASE 0x10 |
| 59 | 59 | |
| 60 | −/* Make sure sleep time is <= 20ms for usleep_range */ | |
| 61 | −#define DPS310_POLL_SLEEP_US(t) min(20000, (t) / 8) | |
| 60 | +/* Make sure sleep time is <= 30ms for usleep_range */ | |
| 61 | +#define DPS310_POLL_SLEEP_US(t) min(30000, (t) / 8) | |
| 62 | 62 | /* Silently handle error in rate value here */ |
| 63 | 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 | 402 | if (rc) |
| 403 | 403 | return rc; |
| 404 | 404 | |
| 405 | − /* Wait for device chip access: 2.5ms in specification */ | |
| 406 | − usleep_range(2500, 12000); | |
| 405 | + /* Wait for device chip access: 15ms in specification */ | |
| 406 | + usleep_range(15000, 55000); | |
| 407 | 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 | 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 | 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 | 760 | struct iio_dev *indio_dev = ((struct iio_poll_func *)pollf)->indio_dev; |
| 761 | 761 | struct irsd200_data *data = iio_priv(indio_dev); |
| 762 | − s16 buf = 0; | |
| 762 | + s64 buf[2] = {}; | |
| 763 | 763 | int ret; |
| 764 | 764 | |
| 765 | − ret = irsd200_read_data(data, &buf); | |
| 765 | + ret = irsd200_read_data(data, (s16 *)buf); | |
| 766 | 766 | if (ret) |
| 767 | 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 | 770 | iio_get_time_ns(indio_dev)); |
| 771 | 771 | |
| 772 | 772 | end: |
| @@ -4968,7 +4968,7 @@ static int cma_iboe_join_multicast(struct rdma_id_private *id_priv, · 4967 unmodified lines | ||
| 4968 | 4968 | int err = 0; |
| 4969 | 4969 | struct sockaddr *addr = (struct sockaddr *)&mc->addr; |
| 4970 | 4970 | struct net_device *ndev = NULL; |
| 4971 | − struct ib_sa_multicast ib; | |
| 4971 | + struct ib_sa_multicast ib = {}; | |
| 4972 | 4972 | enum ib_gid_type gid_type; |
| 4973 | 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 | 217 | return -ENOMEM; |
| 218 | 218 | |
| 219 | 219 | for (i = 0; i < ports_num; i++) { |
| 220 | − char port_str[10]; | |
| 220 | + char port_str[11]; | |
| 221 | 221 | |
| 222 | 222 | ports[i].port_num = i + 1; |
| 223 | 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 | 2530 | [RDMA_NLDEV_CMD_SYS_SET] = { |
| 2531 | 2531 | .doit = nldev_set_sys_set_doit, |
| 2532 | + .flags = RDMA_NL_ADMIN_PERM, | |
| 2532 | 2533 | }, |
| 2533 | 2534 | [RDMA_NLDEV_CMD_STAT_SET] = { |
| 2534 | 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 | 546 | if (hdr->in_words * 4 != count) |
| 547 | 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 | 551 | * rdma-core v18 and v19 have a bug where they send DESTROY_CQ |
| 552 | 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 | 910 | list_del(&qp->list); |
| 911 | 911 | mutex_unlock(&rdev->qp_lock); |
| 912 | 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 | 918 | ib_umem_release(qp->rumem); |
| 915 | 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 | 665 | blocked = cookie & RCFW_CMD_IS_BLOCKING; |
| 666 | 666 | cookie &= RCFW_MAX_COOKIE_VALUE; |
| 667 | 667 | crsqe = &rcfw->crsqe_tbl[cookie]; |
| 668 | − crsqe->is_in_used = false; | |
| 669 | 668 | |
| 670 | 669 | if (WARN_ONCE(test_bit(FIRMWARE_STALL_DETECTED, |
| 671 | 670 | &rcfw->cmdq.flags), |
| @@ -681,8 +680,14 @@ static int bnxt_qplib_process_qp_event(struct bnxt_qplib_rcfw *rcfw, · 9 unmodified lines | ||
| 681 | 680 | atomic_dec(&rcfw->timeout_send); |
| 682 | 681 | |
| 683 | 682 | if (crsqe->is_waiter_alive) { |
| 684 | − if (crsqe->resp) | |
| 683 | + if (crsqe->resp) { | |
| 685 | 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 | 691 | if (!blocked) |
| 687 | 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 | 699 | if (!is_waiter_alive) |
| 695 | 700 | crsqe->resp = NULL; |
| 696 | 701 | |
| 702 | + crsqe->is_in_used = false; | |
| 703 | + | |
| 697 | 704 | hwq->cons += req_size; |
| 698 | 705 | |
| 699 | 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 | 1965 | int win; |
| 1966 | 1966 | |
| 1967 | 1967 | skb = get_skb(NULL, sizeof(*req), GFP_KERNEL); |
| 1968 | + if (!skb) | |
| 1969 | + return -ENOMEM; | |
| 1970 | + | |
| 1968 | 1971 | req = __skb_put_zero(skb, sizeof(*req)); |
| 1969 | 1972 | req->op_compl = htonl(WR_OP_V(FW_OFLD_CONNECTION_WR)); |
| 1970 | 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 | 133 | static int regmr_cmd(struct erdma_dev *dev, struct erdma_mr *mr) |
| 134 | 134 | { |
| 135 | 135 | struct erdma_pd *pd = to_epd(mr->ibmr.pd); |
| 136 | + u32 mtt_level = ERDMA_MR_MTT_0LEVEL; | |
| 136 | 137 | struct erdma_cmdq_reg_mr_req req; |
| 137 | − u32 mtt_level; | |
| 138 | 138 | |
| 139 | 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 | 147 | req.phy_addr[0] = sg_dma_address(mr->mem.mtt->sglist); |
| 148 | 148 | mtt_level = mr->mem.mtt->level; |
| 149 | 149 | } |
| 150 | − } else { | |
| 150 | + } else if (mr->type != ERDMA_MR_TYPE_DMA) { | |
| 151 | 151 | memcpy(req.phy_addr, mr->mem.mtt->buf, |
| 152 | 152 | MTT_SIZE(mr->mem.page_cnt)); |
| 153 | − mtt_level = ERDMA_MR_MTT_0LEVEL; | |
| 154 | 153 | } |
| 155 | 154 | |
| 156 | 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 | 655 | mtt = kzalloc(sizeof(*mtt), GFP_KERNEL); |
| 657 | 656 | if (!mtt) |
| 658 | − return NULL; | |
| 657 | + return ERR_PTR(-ENOMEM); | |
| 659 | 658 | |
| 660 | 659 | mtt->size = ALIGN(size, PAGE_SIZE); |
| 661 | 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 | 223 | static int add_port_entries(struct mlx4_ib_dev *device, int port_num) |
| 224 | 224 | { |
| 225 | 225 | int i; |
| 226 | − char buff[11]; | |
| 226 | + char buff[12]; | |
| 227 | 227 | struct mlx4_ib_iov_port *port = NULL; |
| 228 | 228 | int ret = 0 ; |
| 229 | 229 | struct ib_port_attr attr; |
| @@ -2470,8 +2470,8 @@ destroy_res: · 2469 unmodified lines | ||
| 2470 | 2470 | mlx5_steering_anchor_destroy_res(ft_prio); |
| 2471 | 2471 | put_flow_table: |
| 2472 | 2472 | put_flow_table(dev, ft_prio, true); |
| 2473 | − mutex_unlock(&dev->flow_db->lock); | |
| 2474 | 2473 | free_obj: |
| 2474 | + mutex_unlock(&dev->flow_db->lock); | |
| 2475 | 2475 | kfree(obj); |
| 2476 | 2476 | |
| 2477 | 2477 | return err; |
| @@ -2084,7 +2084,7 @@ static inline char *mmap_cmd2str(enum mlx5_ib_mmap_cmd cmd) · 2083 unmodified lines | ||
| 2084 | 2084 | case MLX5_IB_MMAP_DEVICE_MEM: |
| 2085 | 2085 | return "Device Memory"; |
| 2086 | 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 | 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 | 306 | MLX5_SET(mkc, mkc, free, 1); |
| 306 | 307 | MLX5_SET(mkc, mkc, umr_en, 1); |
| 307 | 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 | 1025 | if (!dev->cache.wq) |
| 1025 | 1026 | return; |
| 1026 | 1027 | |
| 1027 | − cancel_delayed_work_sync(&dev->cache.remove_ent_dwork); | |
| 1028 | 1028 | mutex_lock(&dev->cache.rb_lock); |
| 1029 | 1029 | for (node = rb_first(root); node; node = rb_next(node)) { |
| 1030 | 1030 | ent = rb_entry(node, struct mlx5_cache_ent, node); |
| 1031 | 1031 | xa_lock_irq(&ent->mkeys); |
| 1032 | 1032 | ent->disabled = true; |
| 1033 | 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 | 1043 | mlx5_mkey_cache_debugfs_cleanup(dev); |
| 1038 | 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 | 1048 | node = rb_first(root); |
| 1041 | 1049 | while (node) { |
| 1042 | 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 | 976 | siw_cep_put(cep); |
| 977 | 977 | new_cep->listen_cep = NULL; |
| 978 | 978 | if (rv) { |
| 979 | + siw_cancel_mpatimer(new_cep); | |
| 979 | 980 | siw_cep_set_free(new_cep); |
| 980 | 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 | 1102 | * Socket close before MPA request received. |
| 1102 | 1103 | */ |
| 1103 | − siw_dbg_cep(cep, "no mpareq: drop listener\n"); | |
| 1104 | − siw_cep_put(cep->listen_cep); | |
| 1105 | − cep->listen_cep = NULL; | |
| 1104 | + if (cep->listen_cep) { | |
| 1105 | + siw_dbg_cep(cep, | |
| 1106 | + "no mpareq: drop listener\n"); | |
| 1107 | + siw_cep_put(cep->listen_cep); | |
| 1108 | + cep->listen_cep = NULL; | |
| 1109 | + } | |
| 1106 | 1110 | } |
| 1107 | 1111 | } |
| 1108 | 1112 | release_cep = 1; |
| @@ -1227,7 +1231,11 @@ static void siw_cm_llp_data_ready(struct sock *sk) · 118 unmodified lines | ||
| 1227 | 1231 | if (!cep) |
| 1228 | 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 | 1240 | switch (cep->state) { |
| 1233 | 1241 | case SIW_EPSTATE_RDMA_MODE: |
| @@ -2784,7 +2784,6 @@ static int srp_abort(struct scsi_cmnd *scmnd) · 2783 unmodified lines | ||
| 2784 | 2784 | u32 tag; |
| 2785 | 2785 | u16 ch_idx; |
| 2786 | 2786 | struct srp_rdma_ch *ch; |
| 2787 | − int ret; | |
| 2788 | 2787 | |
| 2789 | 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 | 2797 | shost_printk(KERN_ERR, target->scsi_host, |
| 2799 | 2798 | "Sending SRP abort for tag %#x\n", tag); |
| 2800 | 2799 | if (srp_send_tsk_mgmt(ch, tag, scmnd->device->lun, |
| 2801 | − 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) { | |
| 2800 | + SRP_TSK_ABORT_TASK, NULL) == 0) { | |
| 2808 | 2801 | srp_free_req(ch, req, scmnd, 0); |
| 2809 | − scmnd->result = DID_ABORT << 16; | |
| 2810 | − scsi_done(scmnd); | |
| 2802 | + return SUCCESS; | |
| 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 | 2810 | static int srp_reset_device(struct scsi_cmnd *scmnd) |
| @@ -130,6 +130,7 @@ static const struct xpad_device { · 129 unmodified lines | ||
| 130 | 130 | { 0x0079, 0x18d4, "GPD Win 2 X-Box Controller", 0, XTYPE_XBOX360 }, |
| 131 | 131 | { 0x03eb, 0xff01, "Wooting One (Legacy)", 0, XTYPE_XBOX360 }, |
| 132 | 132 | { 0x03eb, 0xff02, "Wooting Two (Legacy)", 0, XTYPE_XBOX360 }, |
| 133 | + { 0x03f0, 0x0495, "HyperX Clutch Gladiate", 0, XTYPE_XBOXONE }, | |
| 133 | 134 | { 0x044f, 0x0f00, "Thrustmaster Wheel", 0, XTYPE_XBOX }, |
| 134 | 135 | { 0x044f, 0x0f03, "Thrustmaster Wheel", 0, XTYPE_XBOX }, |
| 135 | 136 | { 0x044f, 0x0f07, "Thrustmaster, Inc. Controller", 0, XTYPE_XBOX }, |
| @@ -272,6 +273,7 @@ static const struct xpad_device { · 136 unmodified lines | ||
| 272 | 273 | { 0x1038, 0x1430, "SteelSeries Stratus Duo", 0, XTYPE_XBOX360 }, |
| 273 | 274 | { 0x1038, 0x1431, "SteelSeries Stratus Duo", 0, XTYPE_XBOX360 }, |
| 274 | 275 | { 0x11c9, 0x55f0, "Nacon GC-100XF", 0, XTYPE_XBOX360 }, |
| 276 | + { 0x11ff, 0x0511, "PXN V900", 0, XTYPE_XBOX360 }, | |
| 275 | 277 | { 0x1209, 0x2882, "Ardwiino Controller", 0, XTYPE_XBOX360 }, |
| 276 | 278 | { 0x12ab, 0x0004, "Honey Bee Xbox360 dancepad", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX360 }, |
| 277 | 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 | 461 | { USB_INTERFACE_INFO('X', 'B', 0) }, /* Xbox USB-IF not-approved class */ |
| 460 | 462 | XPAD_XBOX360_VENDOR(0x0079), /* GPD Win 2 controller */ |
| 461 | 463 | XPAD_XBOX360_VENDOR(0x03eb), /* Wooting Keyboards (Legacy) */ |
| 464 | + XPAD_XBOXONE_VENDOR(0x03f0), /* HP HyperX Xbox One controllers */ | |
| 462 | 465 | XPAD_XBOX360_VENDOR(0x044f), /* Thrustmaster Xbox 360 controllers */ |
| 463 | 466 | XPAD_XBOX360_VENDOR(0x045e), /* Microsoft Xbox 360 controllers */ |
| 464 | 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 | 480 | XPAD_XBOX360_VENDOR(0x1038), /* SteelSeries controllers */ |
| 478 | 481 | XPAD_XBOXONE_VENDOR(0x10f5), /* Turtle Beach Controllers */ |
| 479 | 482 | XPAD_XBOX360_VENDOR(0x11c9), /* Nacon GC100XF */ |
| 483 | + XPAD_XBOX360_VENDOR(0x11ff), /* PXN V900 */ | |
| 480 | 484 | XPAD_XBOX360_VENDOR(0x1209), /* Ardwiino Controllers */ |
| 481 | 485 | XPAD_XBOX360_VENDOR(0x12ab), /* Xbox 360 dance pads */ |
| 482 | 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 | 425 | pm->requires_update = 0; |
| 426 | 426 | usb_kill_urb(pm->irq); |
| 427 | 427 | input_unregister_device(pm->input); |
| 428 | + usb_kill_urb(pm->config); | |
| 428 | 429 | usb_free_urb(pm->irq); |
| 429 | 430 | usb_free_urb(pm->config); |
| 430 | 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 | 2114 | psmouse->protocol_handler = elantech_process_byte; |
| 2115 | 2115 | psmouse->disconnect = elantech_disconnect; |
| 2116 | 2116 | psmouse->reconnect = elantech_reconnect; |
| 2117 | + psmouse->fast_reconnect = NULL; | |
| 2117 | 2118 | psmouse->pktsize = info->hw_version > 1 ? 6 : 4; |
| 2118 | 2119 | |
| 2119 | 2120 | return 0; |
| @@ -5,7 +5,6 @@ · 4 unmodified lines | ||
| 5 | 5 | |
| 6 | 6 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt |
| 7 | 7 | |
| 8 | −#include <linux/delay.h> | |
| 9 | 8 | #include <linux/kernel.h> |
| 10 | 9 | #include <linux/module.h> |
| 11 | 10 | #include <linux/libps2.h> |
| @@ -119,18 +118,13 @@ static psmouse_ret_t psmouse_smbus_process_byte(struct psmouse *psmouse) · 107 unmodified lines | ||
| 119 | 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 | 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 | 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 | 263 | psmouse->private = smbdev; |
| 269 | 264 | psmouse->protocol_handler = psmouse_smbus_process_byte; |
| @@ -1623,6 +1623,7 @@ static int synaptics_init_ps2(struct psmouse *psmouse, · 1622 unmodified lines | ||
| 1623 | 1623 | psmouse->set_rate = synaptics_set_rate; |
| 1624 | 1624 | psmouse->disconnect = synaptics_disconnect; |
| 1625 | 1625 | psmouse->reconnect = synaptics_reconnect; |
| 1626 | + psmouse->fast_reconnect = NULL; | |
| 1626 | 1627 | psmouse->cleanup = synaptics_reset; |
| 1627 | 1628 | /* Synaptics can usually stay in sync without extra help */ |
| 1628 | 1629 | psmouse->resync_time = 0; |
| @@ -1752,6 +1753,7 @@ static int synaptics_create_intertouch(struct psmouse *psmouse, · 123 unmodified lines | ||
| 1752 | 1753 | psmouse_matches_pnp_id(psmouse, topbuttonpad_pnp_ids) && |
| 1753 | 1754 | !SYN_CAP_EXT_BUTTONS_STICK(info->ext_cap_10); |
| 1754 | 1755 | const struct rmi_device_platform_data pdata = { |
| 1756 | + .reset_delay_ms = 30, | |
| 1755 | 1757 | .sensor_pdata = { |
| 1756 | 1758 | .sensor_type = rmi_sensor_touchpad, |
| 1757 | 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 | 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 | 248 | /* we need to get the smbus version to activate the touchpad */ |
| 241 | − retval = rmi_smb_get_version(rmi_smb); | |
| 242 | − if (retval < 0) | |
| 243 | − return retval; | |
| 249 | + smbus_version = rmi_smb_get_version(rmi_smb); | |
| 250 | + if (smbus_version < 0) | |
| 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 | 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 | 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 | |
| 257 | − * PS/2 or there will be races between PS/2 and SMBus. | |
| 258 | − * PS/2 should ensure that a psmouse_reset is called before | |
| 259 | − * intializing the device and after it has been removed to be in a known | |
| 260 | − * state. | |
| 273 | + * We do not call the actual reset command, it has to be handled in | |
| 274 | + * PS/2 or there will be races between PS/2 and SMBus. PS/2 should | |
| 275 | + * ensure that a psmouse_reset is called before initializing the | |
| 276 | + * device and after it has been removed to be in a known state. | |
| 261 | 277 | */ |
| 262 | 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 | 289 | struct rmi_device_platform_data *pdata = dev_get_platdata(&client->dev); |
| 274 | 290 | struct rmi_smb_xport *rmi_smb; |
| 275 | − int smbus_version; | |
| 276 | 291 | int error; |
| 277 | 292 | |
| 278 | 293 | if (!pdata) { |
| @@ -311,18 +326,9 @@ static int rmi_smb_probe(struct i2c_client *client) · 32 unmodified lines | ||
| 311 | 326 | rmi_smb->xport.proto_name = "smb"; |
| 312 | 327 | rmi_smb->xport.ops = &rmi_smb_ops; |
| 313 | 328 | |
| 314 | − smbus_version = rmi_smb_get_version(rmi_smb); | |
| 315 | − if (smbus_version < 0) | |
| 316 | − return smbus_version; | |
| 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 | − } | |
| 329 | + error = rmi_smb_enable_smbus_mode(rmi_smb); | |
| 330 | + if (error) | |
| 331 | + return error; | |
| 326 | 332 | |
| 327 | 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 | 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 | 630 | /* Gigabyte M912 */ |
| 623 | 631 | .matches = { |
| @@ -900,6 +900,25 @@ static int goodix_add_acpi_gpio_mappings(struct goodix_ts_data *ts) · 899 unmodified lines | ||
| 900 | 900 | dev_info(dev, "No ACPI GpioInt resource, assuming that the GPIO order is reset, int\n"); |
| 901 | 901 | ts->irq_pin_access_method = IRQ_PIN_ACCESS_ACPI_GPIO; |
| 902 | 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 | 922 | } else { |
| 904 | 923 | dev_warn(dev, "Unexpected ACPI resources: gpio_count %d, gpio_int_idx %d\n", |
| 905 | 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 | 671 | return ret; |
| 672 | 672 | |
| 673 | 673 | switch (domain->type) { |
| 674 | − case IOMMU_DOMAIN_DMA: | |
| 675 | − case IOMMU_DOMAIN_UNMANAGED: | |
| 674 | + default: | |
| 676 | 675 | ret = apple_dart_domain_add_streams(dart_domain, cfg); |
| 677 | 676 | if (ret) |
| 678 | 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 | 198 | static void arm_smmu_mm_arch_invalidate_secondary_tlbs(struct mmu_notifier *mn, |
| 190 | 199 | struct mm_struct *mm, |
| 191 | 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 | 210 | * range. So do a simple translation here by calculating size correctly. |
| 202 | 211 | */ |
| 203 | 212 | size = end - start; |
| 204 | − if (size == ULONG_MAX) | |
| 205 | − size = 0; | |
| 213 | + if (!(smmu_domain->smmu->features & ARM_SMMU_FEAT_RANGE_INV)) { | |
| 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 | 221 | if (!(smmu_domain->smmu->features & ARM_SMMU_FEAT_BTM)) { |
| 208 | 222 | if (!size) |
| @@ -1895,18 +1895,23 @@ static void __arm_smmu_tlb_inv_range(struct arm_smmu_cmdq_ent *cmd, · 1894 unmodified lines | ||
| 1895 | 1895 | /* Get the leaf page size */ |
| 1896 | 1896 | tg = __ffs(smmu_domain->domain.pgsize_bitmap); |
| 1897 | 1897 | |
| 1898 | + num_pages = size >> tg; | |
| 1899 | + | |
| 1898 | 1900 | /* Convert page size of 12,14,16 (log2) to 1,2,3 */ |
| 1899 | 1901 | cmd->tlbi.tg = (tg - 10) / 2; |
| 1900 | 1902 | |
| 1901 | 1903 | /* |
| 1902 | − * Determine what level the granule is at. For non-leaf, io-pgtable | |
| 1903 | − * assumes .tlb_flush_walk can invalidate multiple levels at once, | |
| 1904 | − * so ignore the nominal last-level granule and leave TTL=0. | |
| 1904 | + * Determine what level the granule is at. For non-leaf, both | |
| 1905 | + * io-pgtable and SVA pass a nominal last-level granule because | |
| 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 | 1911 | if (cmd->tlbi.leaf) |
| 1907 | 1912 | cmd->tlbi.ttl = 4 - ((ilog2(granule) - 3) / (tg - 3)); |
| 1908 | − | |
| 1909 | − num_pages = size >> tg; | |
| 1913 | + else if ((num_pages & CMDQ_TLBI_RANGE_NUM_MAX) == 1) | |
| 1914 | + num_pages++; | |
| 1910 | 1915 | } |
| 1911 | 1916 | |
| 1912 | 1917 | cmds.num = 0; |
| @@ -2998,13 +2998,6 @@ static int iommu_suspend(void) · 2997 unmodified lines | ||
| 2998 | 2998 | struct intel_iommu *iommu = NULL; |
| 2999 | 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 | 3001 | iommu_flush_all(); |
| 3009 | 3002 | |
| 3010 | 3003 | for_each_active_iommu(iommu, drhd) { |
| @@ -3024,12 +3017,6 @@ static int iommu_suspend(void) · 13 unmodified lines | ||
| 3024 | 3017 | raw_spin_unlock_irqrestore(&iommu->register_lock, flag); |
| 3025 | 3018 | } |
| 3026 | 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 | 3022 | static void iommu_resume(void) |
| @@ -3061,9 +3048,6 @@ static void iommu_resume(void) · 25 unmodified lines | ||
| 3061 | 3048 | |
| 3062 | 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 | 3053 | static struct syscore_ops iommu_syscore_ops = { |
| @@ -681,7 +681,7 @@ struct intel_iommu { · 680 unmodified lines | ||
| 681 | 681 | struct iopf_queue *iopf_queue; |
| 682 | 682 | unsigned char iopfq_name[16]; |
| 683 | 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 | 686 | #ifdef CONFIG_IRQ_REMAP |
| 687 | 687 | struct ir_table *ir_table; /* Interrupt remapping info */ |
| @@ -262,7 +262,7 @@ struct mtk_iommu_data { · 261 unmodified lines | ||
| 262 | 262 | struct device *smicomm_dev; |
| 263 | 263 | |
| 264 | 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 | 267 | struct regmap *pericfg; |
| 268 | 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 | 643 | struct mtk_iommu_domain *share_dom = data->share_dom; |
| 644 | 644 | const struct mtk_iommu_iova_region *region; |
| 645 | 645 | |
| 646 | − /* Always use share domain in sharing pgtable case */ | |
| 647 | − if (MTK_IOMMU_HAS_FLAG(data->plat_data, SHARE_PGTABLE) && share_dom) { | |
| 646 | + /* Share pgtable when 2 MM IOMMU share the pgtable or one IOMMU use multiple iova ranges */ | |
| 647 | + if (share_dom) { | |
| 648 | 648 | dom->iop = share_dom->iop; |
| 649 | 649 | dom->cfg = share_dom->cfg; |
| 650 | 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 | 677 | /* Update our support page sizes bitmap */ |
| 678 | 678 | dom->domain.pgsize_bitmap = dom->cfg.pgsize_bitmap; |
| 679 | 679 | |
| 680 | − if (MTK_IOMMU_HAS_FLAG(data->plat_data, SHARE_PGTABLE)) | |
| 681 | − data->share_dom = dom; | |
| 680 | + data->share_dom = dom; | |
| 682 | 681 | |
| 683 | 682 | update_iova_region: |
| 684 | 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 | 29 | void gic_enable_of_quirks(const struct device_node *np, |
| 30 | 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 | 36 | #endif /* _IRQ_GIC_COMMON_H */ |
| @@ -44,10 +44,6 @@ · 43 unmodified lines | ||
| 44 | 44 | #define ITS_FLAGS_WORKAROUND_CAVIUM_23144 (1ULL << 2) |
| 45 | 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 | 47 | #define RD_LOCAL_LPI_ENABLED BIT(0) |
| 52 | 48 | #define RD_LOCAL_PENDTABLE_PREALLOCATED BIT(1) |
| 53 | 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 | 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 | 4761 | static const struct gic_quirk its_quirks[] = { |
| 4758 | 4762 | #ifdef CONFIG_CAVIUM_ERRATUM_22375 |
| 4759 | 4763 | { |
| @@ -4808,6 +4812,11 @@ static const struct gic_quirk its_quirks[] = { · 48 unmodified lines | ||
| 4808 | 4812 | .init = its_enable_rk3588001, |
| 4809 | 4813 | }, |
| 4810 | 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 | 4826 | u32 iidr = readl_relaxed(its->base + GITS_IIDR); |
| 4818 | 4827 | |
| 4819 | 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 | 4835 | static int its_save_disable(void) |
| @@ -4952,7 +4965,7 @@ out_unmap: · 129 unmodified lines | ||
| 4952 | 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 | 4970 | struct irq_domain *inner_domain; |
| 4958 | 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 | 4980 | inner_domain = irq_domain_create_hierarchy(its_parent, |
| 4968 | 4981 | its->msi_domain_flags, 0, |
| 4969 | − handle, &its_domain_ops, | |
| 4982 | + its->fwnode_handle, &its_domain_ops, | |
| 4970 | 4983 | info); |
| 4971 | 4984 | if (!inner_domain) { |
| 4972 | 4985 | kfree(info); |
| @@ -5017,8 +5030,7 @@ static int its_init_vpe_domain(void) · 44 unmodified lines | ||
| 5017 | 5030 | return 0; |
| 5018 | 5031 | } |
| 5019 | 5032 | |
| 5020 | −static int __init its_compute_its_list_map(struct resource *res, | |
| 5021 | − void __iomem *its_base) | |
| 5033 | +static int __init its_compute_its_list_map(struct its_node *its) | |
| 5022 | 5034 | { |
| 5023 | 5035 | int its_number; |
| 5024 | 5036 | u32 ctlr; |
| @@ -5032,15 +5044,15 @@ static int __init its_compute_its_list_map(struct resource *res, · 7 unmodified lines | ||
| 5032 | 5044 | its_number = find_first_zero_bit(&its_list_map, GICv4_ITS_LIST_MAX); |
| 5033 | 5045 | if (its_number >= GICv4_ITS_LIST_MAX) { |
| 5034 | 5046 | pr_err("ITS@%pa: No ITSList entry available!\n", |
| 5035 | − &res->start); | |
| 5047 | + &its->phys_base); | |
| 5036 | 5048 | return -EINVAL; |
| 5037 | 5049 | } |
| 5038 | 5050 | |
| 5039 | − ctlr = readl_relaxed(its_base + GITS_CTLR); | |
| 5051 | + ctlr = readl_relaxed(its->base + GITS_CTLR); | |
| 5040 | 5052 | ctlr &= ~GITS_CTLR_ITS_NUMBER; |
| 5041 | 5053 | ctlr |= its_number << GITS_CTLR_ITS_NUMBER_SHIFT; |
| 5042 | − writel_relaxed(ctlr, its_base + GITS_CTLR); | |
| 5043 | − ctlr = readl_relaxed(its_base + GITS_CTLR); | |
| 5054 | + writel_relaxed(ctlr, its->base + GITS_CTLR); | |
| 5055 | + ctlr = readl_relaxed(its->base + GITS_CTLR); | |
| 5044 | 5056 | if ((ctlr & GITS_CTLR_ITS_NUMBER) != (its_number << GITS_CTLR_ITS_NUMBER_SHIFT)) { |
| 5045 | 5057 | its_number = ctlr & GITS_CTLR_ITS_NUMBER; |
| 5046 | 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 | 5061 | if (test_and_set_bit(its_number, &its_list_map)) { |
| 5050 | 5062 | pr_err("ITS@%pa: Duplicate ITSList entry %d\n", |
| 5051 | − &res->start, its_number); | |
| 5063 | + &its->phys_base, its_number); | |
| 5052 | 5064 | return -EINVAL; |
| 5053 | 5065 | } |
| 5054 | 5066 | |
| 5055 | 5067 | return its_number; |
| 5056 | 5068 | } |
| 5057 | 5069 | |
| 5058 | −static int __init its_probe_one(struct resource *res, | |
| 5059 | − struct fwnode_handle *handle, int numa_node) | |
| 5070 | +static int __init its_probe_one(struct its_node *its) | |
| 5060 | 5071 | { |
| 5061 | − struct its_node *its; | |
| 5062 | − void __iomem *its_base; | |
| 5063 | − u64 baser, tmp, typer; | |
| 5072 | + u64 baser, tmp; | |
| 5064 | 5073 | struct page *page; |
| 5065 | 5074 | u32 ctlr; |
| 5066 | 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 | 5077 | if (is_v4(its)) { |
| 5089 | − if (!(typer & GITS_TYPER_VMOVP)) { | |
| 5090 | − err = its_compute_its_list_map(res, its_base); | |
| 5078 | + if (!(its->typer & GITS_TYPER_VMOVP)) { | |
| 5079 | + err = its_compute_its_list_map(its); | |
| 5091 | 5080 | if (err < 0) |
| 5092 | − goto out_free_its; | |
| 5081 | + goto out; | |
| 5093 | 5082 | |
| 5094 | 5083 | its->list_nr = err; |
| 5095 | 5084 | |
| 5096 | 5085 | pr_info("ITS@%pa: Using ITS number %d\n", |
| 5097 | − &res->start, err); | |
| 5086 | + &its->phys_base, err); | |
| 5098 | 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 | 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 | 5095 | if (!its->sgir_base) { |
| 5107 | 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 | 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 | 5107 | page = alloc_pages_node(its->numa_node, GFP_KERNEL | __GFP_ZERO, |
| 5121 | 5108 | get_order(ITS_CMD_QUEUE_SZ)); |
| 5122 | 5109 | if (!page) { |
| @@ -5125,12 +5112,9 @@ static int __init its_probe_one(struct resource *res, · 2 unmodified lines | ||
| 5125 | 5112 | } |
| 5126 | 5113 | its->cmd_base = (void *)page_address(page); |
| 5127 | 5114 | its->cmd_write = its->cmd_base; |
| 5128 | − its->fwnode_handle = handle; | |
| 5129 | 5115 | its->get_msi_base = its_irq_get_msi_base; |
| 5130 | 5116 | its->msi_domain_flags = IRQ_DOMAIN_FLAG_ISOLATED_MSI; |
| 5131 | 5117 | |
| 5132 | − its_enable_quirks(its); | |
| 5133 | − | |
| 5134 | 5118 | err = its_alloc_tables(its); |
| 5135 | 5119 | if (err) |
| 5136 | 5120 | goto out_free_cmd; |
| @@ -5174,7 +5158,7 @@ static int __init its_probe_one(struct resource *res, · 37 unmodified lines | ||
| 5174 | 5158 | ctlr |= GITS_CTLR_ImDe; |
| 5175 | 5159 | writel_relaxed(ctlr, its->base + GITS_CTLR); |
| 5176 | 5160 | |
| 5177 | − err = its_init_domain(handle, its); | |
| 5161 | + err = its_init_domain(its); | |
| 5178 | 5162 | if (err) |
| 5179 | 5163 | goto out_free_tables; |
| 5180 | 5164 | |
| @@ -5191,11 +5175,8 @@ out_free_cmd: · 10 unmodified lines | ||
| 5191 | 5175 | out_unmap_sgir: |
| 5192 | 5176 | if (its->sgir_base) |
| 5193 | 5177 | iounmap(its->sgir_base); |
| 5194 | −out_free_its: | |
| 5195 | − kfree(its); | |
| 5196 | −out_unmap: | |
| 5197 | − iounmap(its_base); | |
| 5198 | − pr_err("ITS@%pa: failed probing (%d)\n", &res->start, err); | |
| 5178 | +out: | |
| 5179 | + pr_err("ITS@%pa: failed probing (%d)\n", &its->phys_base, err); | |
| 5199 | 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 | 5382 | static int __init its_of_probe(struct device_node *node) |
| 5360 | 5383 | { |
| 5361 | 5384 | struct device_node *np; |
| 5362 | 5385 | struct resource res; |
| 5386 | + int err; | |
| 5363 | 5387 | |
| 5364 | 5388 | /* |
| 5365 | 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 | 5394 | for (np = of_find_matching_node(node, its_device_id); np; |
| 5371 | 5395 | np = of_find_matching_node(np, its_device_id)) { |
| 5372 | − int err; | |
| 5373 | − | |
| 5374 | 5396 | if (!of_device_is_available(np) || |
| 5375 | 5397 | !of_property_read_bool(np, "msi-controller") || |
| 5376 | 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 | 5406 | for (np = of_find_matching_node(node, its_device_id); np; |
| 5385 | 5407 | np = of_find_matching_node(np, its_device_id)) { |
| 5408 | + struct its_node *its; | |
| 5409 | + | |
| 5386 | 5410 | if (!of_device_is_available(np)) |
| 5387 | 5411 | continue; |
| 5388 | 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 | 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 | 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 | 5543 | struct acpi_madt_generic_translator *its_entry; |
| 5510 | 5544 | struct fwnode_handle *dom_handle; |
| 5545 | + struct its_node *its; | |
| 5511 | 5546 | struct resource res; |
| 5512 | 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 | 5567 | goto dom_err; |
| 5533 | 5568 | } |
| 5534 | 5569 | |
| 5535 | − err = its_probe_one(&res, dom_handle, | |
| 5536 | − acpi_get_its_numa_node(its_entry->translation_id)); | |
| 5570 | + its = its_node_init(&res, dom_handle, | |
| 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 | 5578 | if (!err) |
| 5538 | 5579 | return 0; |
| 5539 | 5580 | |
| 5581 | +node_err: | |
| 5540 | 5582 | iort_deregister_domain_token(its_entry->translation_id); |
| 5541 | 5583 | dom_err: |
| 5542 | 5584 | irq_domain_free_fwnode(dom_handle); |
| @@ -1857,6 +1857,14 @@ static bool gic_enable_quirk_arm64_2941627(void *data) · 1856 unmodified lines | ||
| 1857 | 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 | 1868 | static const struct gic_quirk gic_quirks[] = { |
| 1861 | 1869 | { |
| 1862 | 1870 | .desc = "GICv3: Qualcomm MSM8996 broken firmware", |
| @@ -1923,6 +1931,11 @@ static const struct gic_quirk gic_quirks[] = { · 60 unmodified lines | ||
| 1923 | 1931 | .mask = 0xff0f0fff, |
| 1924 | 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 | 119 | raw_spin_lock(&priv->lock); |
| 120 | 120 | reg = readl_relaxed(priv->base + TSSR(tssr_index)); |
| 121 | − reg &= ~(TSSEL_MASK << tssr_offset); | |
| 121 | + reg &= ~(TSSEL_MASK << TSSEL_SHIFT(tssr_offset)); | |
| 122 | 122 | writel_relaxed(reg, priv->base + TSSR(tssr_index)); |
| 123 | 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 | 130 | unsigned int hw_irq = irqd_to_hwirq(d); |
| 131 | 131 | |
| 132 | 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 | 134 | struct rzg2l_irqc_priv *priv = irq_data_to_priv(d); |
| 134 | − unsigned long tint = (uintptr_t)d->chip_data; | |
| 135 | 135 | u32 offset = hw_irq - IRQC_TINT_START; |
| 136 | 136 | u32 tssr_offset = TSSR_OFFSET(offset); |
| 137 | 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 | 155 | * for each INTC DT node. We only need to do INTC initialization |
| 156 | 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 | 166 | return 0; |
| 167 | + } | |
| 160 | 168 | |
| 161 | 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 | 460 | .map = irq_map_generic_chip, |
| 461 | 461 | .alloc = stm32_exti_alloc, |
| 462 | 462 | .free = stm32_exti_free, |
| 463 | + .xlate = irq_domain_xlate_twocell, | |
| 463 | 464 | }; |
| 464 | 465 | |
| 465 | 466 | static void stm32_irq_ack(struct irq_data *d) |
| @@ -22,9 +22,20 @@ · 21 unmodified lines | ||
| 22 | 22 | |
| 23 | 23 | #define PDC_MAX_GPIO_IRQS 256 |
| 24 | 24 | |
| 25 | +/* Valid only on HW version < 3.2 */ | |
| 25 | 26 | #define IRQ_ENABLE_BANK 0x10 |
| 26 | 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 | 39 | struct pdc_pin_region { |
| 29 | 40 | u32 pin_base; |
| 30 | 41 | u32 parent_base; |
| @@ -37,6 +48,7 @@ static DEFINE_RAW_SPINLOCK(pdc_lock); · 6 unmodified lines | ||
| 37 | 48 | static void __iomem *pdc_base; |
| 38 | 49 | static struct pdc_pin_region *pdc_region; |
| 39 | 50 | static int pdc_region_cnt; |
| 51 | +static unsigned int pdc_version; | |
| 40 | 52 | |
| 41 | 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 | 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 | 65 | unsigned long enable; |
| 55 | − unsigned long flags; | |
| 56 | − u32 index, mask; | |
| 57 | 66 | |
| 58 | − index = pin_out / 32; | |
| 59 | − mask = pin_out % 32; | |
| 67 | + if (pdc_version < PDC_VERSION_3_2) { | |
| 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 | 87 | raw_spin_lock_irqsave(&pdc_lock, flags); |
| 62 | − enable = pdc_reg_read(IRQ_ENABLE_BANK, index); | |
| 63 | − __assign_bit(mask, &enable, on); | |
| 64 | − pdc_reg_write(IRQ_ENABLE_BANK, index, enable); | |
| 88 | + __pdc_enable_intr(d->hwirq, on); | |
| 65 | 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 | 168 | old_pdc_type = pdc_reg_read(IRQ_i_CFG, d->hwirq); |
| 169 | + pdc_type |= (old_pdc_type & ~IRQ_i_CFG_TYPE_MASK); | |
| 145 | 170 | pdc_reg_write(IRQ_i_CFG, d->hwirq, pdc_type); |
| 146 | 171 | |
| 147 | 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 | 271 | static int pdc_setup_pin_mapping(struct device_node *np) |
| 247 | 272 | { |
| 248 | 273 | int ret, n, i; |
| 249 | − u32 irq_index, reg_index, val; | |
| 250 | 274 | |
| 251 | 275 | n = of_property_count_elems_of_size(np, "qcom,pdc-ranges", sizeof(u32)); |
| 252 | 276 | if (n <= 0 || n % 3) |
| @@ -276,29 +300,38 @@ static int pdc_setup_pin_mapping(struct device_node *np) · 23 unmodified lines | ||
| 276 | 300 | if (ret) |
| 277 | 301 | return ret; |
| 278 | 302 | |
| 279 | − for (i = 0; i < pdc_region[n].cnt; i++) { | |
| 280 | − reg_index = (i + pdc_region[n].pin_base) >> 5; | |
| 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 | − } | |
| 303 | + for (i = 0; i < pdc_region[n].cnt; i++) | |
| 304 | + __pdc_enable_intr(i + pdc_region[n].pin_base, 0); | |
| 286 | 305 | } |
| 287 | 306 | |
| 288 | 307 | return 0; |
| 289 | 308 | } |
| 290 | 309 | |
| 310 | +#define QCOM_PDC_SIZE 0x30000 | |
| 311 | + | |
| 291 | 312 | static int qcom_pdc_init(struct device_node *node, struct device_node *parent) |
| 292 | 313 | { |
| 293 | 314 | struct irq_domain *parent_domain, *pdc_domain; |
| 315 | + resource_size_t res_size; | |
| 316 | + struct resource res; | |
| 294 | 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 | 328 | if (!pdc_base) { |
| 298 | 329 | pr_err("%pOF: unable to map PDC registers\n", node); |
| 299 | 330 | return -ENXIO; |
| 300 | 331 | } |
| 301 | 332 | |
| 333 | + pdc_version = pdc_reg_read(PDC_VERSION_REG, 0); | |
| 334 | + | |
| 302 | 335 | parent_domain = irq_find_host(parent); |
| 303 | 336 | if (!parent_domain) { |
| 304 | 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 | 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 | 482 | if (props.label) { |
| 487 | 483 | /* |
| 488 | 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 | 388 | static int __mcb_bus_add_devices(struct device *dev, void *data) |
| 389 | 389 | { |
| 390 | − struct mcb_device *mdev = to_mcb_device(dev); | |
| 391 | 390 | int retval; |
| 392 | 391 | |
| 393 | − if (mdev->is_added) | |
| 394 | − return 0; | |
| 395 | − | |
| 396 | 392 | retval = device_attach(dev); |
| 397 | − if (retval < 0) | |
| 393 | + if (retval < 0) { | |
| 398 | 394 | dev_err(dev, "Error adding device (%d)\n", retval); |
| 399 | − | |
| 400 | − mdev->is_added = true; | |
| 395 | + return retval; | |
| 396 | + } | |
| 401 | 397 | |
| 402 | 398 | return 0; |
| 403 | 399 | } |
| @@ -99,8 +99,6 @@ static int chameleon_parse_gdd(struct mcb_bus *bus, · 98 unmodified lines | ||
| 99 | 99 | mdev->mem.end = mdev->mem.start + size - 1; |
| 100 | 100 | mdev->mem.flags = IORESOURCE_MEM; |
| 101 | 101 | |
| 102 | − mdev->is_added = false; | |
| 103 | − | |
| 104 | 102 | ret = mcb_device_register(bus, mdev); |
| 105 | 103 | if (ret < 0) |
| 106 | 104 | goto err; |
| @@ -753,7 +753,8 @@ static int crypt_iv_eboiv_gen(struct crypt_config *cc, u8 *iv, · 752 unmodified lines | ||
| 753 | 753 | int err; |
| 754 | 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 | 759 | req = kmalloc(reqsize + cc->iv_size, GFP_NOIO); |
| 759 | 760 | if (!req) |
| @@ -748,17 +748,16 @@ err: · 747 unmodified lines | ||
| 748 | 748 | /* |
| 749 | 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 | 753 | struct dmz_target *dmz = ti->private; |
| 754 | 754 | int i; |
| 755 | 755 | |
| 756 | − for (i = 0; i < dmz->nr_ddevs; i++) { | |
| 757 | − if (dmz->ddev[i]) { | |
| 756 | + for (i = 0; i < dmz->nr_ddevs; i++) | |
| 757 | + if (dmz->ddev[i]) | |
| 758 | 758 | dm_put_device(ti, dmz->ddev[i]); |
| 759 | − dmz->ddev[i] = NULL; | |
| 760 | − } | |
| 761 | − } | |
| 759 | + | |
| 760 | + kfree(dmz->ddev); | |
| 762 | 761 | } |
| 763 | 762 | |
| 764 | 763 | static int dmz_fixup_devices(struct dm_target *ti) |
| @@ -948,7 +947,7 @@ err_bio: · 183 unmodified lines | ||
| 948 | 947 | err_meta: |
| 949 | 948 | dmz_dtr_metadata(dmz->metadata); |
| 950 | 949 | err_dev: |
| 951 | − dmz_put_zoned_device(ti); | |
| 950 | + dmz_put_zoned_devices(ti); | |
| 952 | 951 | err: |
| 953 | 952 | kfree(dmz->dev); |
| 954 | 953 | kfree(dmz); |
| @@ -978,7 +977,7 @@ static void dmz_dtr(struct dm_target *ti) · 23 unmodified lines | ||
| 978 | 977 | |
| 979 | 978 | bioset_exit(&dmz->bio_set); |
| 980 | 979 | |
| 981 | − dmz_put_zoned_device(ti); | |
| 980 | + dmz_put_zoned_devices(ti); | |
| 982 | 981 | |
| 983 | 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 | 855 | set_bit(R5_INACTIVE_BLOCKED, &conf->cache_state); |
| 856 | 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 | 864 | wait_event_lock_irq(conf->wait_for_stripe, |
| 858 | 865 | is_inactive_blocked(conf, hash), |
| 859 | 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 | 1852 | ret = v4l2_fwnode_endpoint_parse(endpoint, &vep); |
| 1853 | + fwnode_handle_put(endpoint); | |
| 1853 | 1854 | if (ret) { |
| 1854 | 1855 | dev_err(dev, "Failed to parse endpoint: %d\n", ret); |
| 1855 | − fwnode_handle_put(endpoint); | |
| 1856 | 1856 | return ret; |
| 1857 | 1857 | } |
| 1858 | 1858 | |
| @@ -1864,12 +1864,9 @@ static int ov8858_parse_of(struct ov8858 *ov8858) · 5 unmodified lines | ||
| 1864 | 1864 | default: |
| 1865 | 1865 | dev_err(dev, "Unsupported number of data lanes %u\n", |
| 1866 | 1866 | ov8858->num_lanes); |
| 1867 | − fwnode_handle_put(endpoint); | |
| 1868 | 1867 | return -EINVAL; |
| 1869 | 1868 | } |
| 1870 | 1869 | |
| 1871 | − ov8858->subdev.fwnode = endpoint; | |
| 1872 | − | |
| 1873 | 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 | 1911 | ret = ov8858_init_ctrls(ov8858); |
| 1915 | 1912 | if (ret) |
| 1916 | − goto err_put_fwnode; | |
| 1913 | + return ret; | |
| 1917 | 1914 | |
| 1918 | 1915 | sd = &ov8858->subdev; |
| 1919 | 1916 | sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE | V4L2_SUBDEV_FL_HAS_EVENTS; |
| @@ -1964,8 +1961,6 @@ err_clean_entity: · 44 unmodified lines | ||
| 1964 | 1961 | media_entity_cleanup(&sd->entity); |
| 1965 | 1962 | err_free_handler: |
| 1966 | 1963 | v4l2_ctrl_handler_free(&ov8858->ctrl_handler); |
| 1967 | −err_put_fwnode: | |
| 1968 | − fwnode_handle_put(ov8858->subdev.fwnode); | |
| 1969 | 1964 | |
| 1970 | 1965 | return ret; |
| 1971 | 1966 | } |
| @@ -1978,7 +1973,6 @@ static void ov8858_remove(struct i2c_client *client) · 6 unmodified lines | ||
| 1978 | 1973 | v4l2_async_unregister_subdev(sd); |
| 1979 | 1974 | media_entity_cleanup(&sd->entity); |
| 1980 | 1975 | v4l2_ctrl_handler_free(&ov8858->ctrl_handler); |
| 1981 | − fwnode_handle_put(ov8858->subdev.fwnode); | |
| 1982 | 1976 | |
| 1983 | 1977 | pm_runtime_disable(&client->dev); |
| 1984 | 1978 | if (!pm_runtime_status_suspended(&client->dev)) |
| @@ -1,11 +1,19 @@ | ||
| 1 | 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 | 6 | config IPU_BRIDGE |
| 3 | − tristate | |
| 7 | + tristate "Intel IPU Bridge" | |
| 4 | 8 | depends on I2C && ACPI |
| 5 | 9 | help |
| 6 | − This is a helper module for the IPU bridge, which can be | |
| 7 | − used by ipu3 and other drivers. In order to handle module | |
| 8 | − dependencies, this is selected by each driver that needs it. | |
| 10 | + The IPU bridge is a helper library for Intel IPU drivers to | |
| 11 | + function on systems shipped with Windows. | |
| 9 | 12 | |
| 10 | −source "drivers/media/pci/intel/ipu3/Kconfig" | |
| 11 | −source "drivers/media/pci/intel/ivsc/Kconfig" | |
| 13 | + Currently used by the ipu3-cio2 and atomisp drivers. | |
| 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 | 107 | for_each_acpi_dev_match(ivsc_adev, acpi_id->id, NULL, -1) |
| 108 | 108 | /* camera sensor depends on IVSC in DSDT if exist */ |
| 109 | 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 | 112 | return ivsc_adev; |
| 113 | + } | |
| 112 | 114 | } |
| 113 | 115 | |
| 114 | 116 | return NULL; |
| @@ -2,13 +2,13 @@ · 1 unmodified line | ||
| 2 | 2 | config VIDEO_IPU3_CIO2 |
| 3 | 3 | tristate "Intel ipu3-cio2 driver" |
| 4 | 4 | depends on VIDEO_DEV && PCI |
| 5 | + depends on IPU_BRIDGE || !IPU_BRIDGE | |
| 5 | 6 | depends on ACPI || COMPILE_TEST |
| 6 | 7 | depends on X86 |
| 7 | 8 | select MEDIA_CONTROLLER |
| 8 | 9 | select VIDEO_V4L2_SUBDEV_API |
| 9 | 10 | select V4L2_FWNODE |
| 10 | 11 | select VIDEOBUF2_DMA_SG |
| 11 | − select IPU_BRIDGE if CIO2_BRIDGE | |
| 12 | 12 | |
| 13 | 13 | help |
| 14 | 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 | 18 | Say Y or M here if you have a Skylake/Kaby Lake SoC with MIPI CSI-2 |
| 19 | 19 | connected camera. |
| 20 | 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 | 6 | depends on INTEL_MEI && ACPI && VIDEO_DEV |
| 7 | 7 | select MEDIA_CONTROLLER |
| 8 | 8 | select VIDEO_V4L2_SUBDEV_API |
| 9 | − select V4L2_ASYNC | |
| 9 | + select V4L2_FWNODE | |
| 10 | 10 | help |
| 11 | 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 | 2398 | PXA_CAM_DRV_NAME, pcdev); |
| 2399 | 2399 | if (err) { |
| 2400 | 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 | 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 | 138 | vpu->ctx->vpu_inst = vpu; |
| 139 | 139 | |
| 140 | 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 | 144 | if (status) { |
| 144 | 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 | 56 | struct xvip_graph_entity *entity; |
| 57 | 57 | struct v4l2_async_connection *asd; |
| 58 | − | |
| 59 | − list_for_each_entry(asd, &xdev->notifier.done_list, asc_entry) { | |
| 60 | − entity = to_xvip_entity(asd); | |
| 61 | − if (entity->asd.match.fwnode == fwnode) | |
| 62 | − return entity; | |
| 58 | + struct list_head *lists[] = { | |
| 59 | + &xdev->notifier.done_list, | |
| 60 | + &xdev->notifier.waiting_list | |
| 61 | + }; | |
| 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 | 72 | return NULL; |
| @@ -502,6 +502,13 @@ static long subdev_do_ioctl(struct file *file, unsigned int cmd, void *arg, · 501 unmodified lines | ||
| 502 | 502 | V4L2_SUBDEV_CLIENT_CAP_STREAMS; |
| 503 | 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 | 512 | switch (cmd) { |
| 506 | 513 | case VIDIOC_SUBDEV_QUERYCAP: { |
| 507 | 514 | struct v4l2_subdev_capability *cap = arg; |
| @@ -241,6 +241,7 @@ config MFD_CS42L43 · 240 unmodified lines | ||
| 241 | 241 | tristate |
| 242 | 242 | select MFD_CORE |
| 243 | 243 | select REGMAP |
| 244 | + select REGMAP_IRQ | |
| 244 | 245 | |
| 245 | 246 | config MFD_CS42L43_I2C |
| 246 | 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 | 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 | 904 | if (ubi_num == UBI_DEV_NUM_AUTO) { |
| 898 | 905 | /* Search for an empty slot in the @ubi_devices array */ |
| 899 | 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 | 191 | config CAN_SUN4I |
| 192 | 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 | 194 | help |
| 195 | 195 | Say Y here if you want to use CAN controller found on Allwinner |
| 196 | 196 | A10/A20/D1 SoCs. |
| @@ -348,7 +348,7 @@ static struct flexcan_devtype_data fsl_imx8mp_devtype_data = { · 347 unmodified lines | ||
| 348 | 348 | static struct flexcan_devtype_data fsl_imx93_devtype_data = { |
| 349 | 349 | .quirks = FLEXCAN_QUIRK_DISABLE_RXFG | FLEXCAN_QUIRK_ENABLE_EACEN_RRS | |
| 350 | 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 | 352 | FLEXCAN_QUIRK_SUPPORT_FD | FLEXCAN_QUIRK_SUPPORT_ECC | |
| 353 | 353 | FLEXCAN_QUIRK_SUPPORT_RX_MAILBOX | |
| 354 | 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 | 544 | } else if (priv->devtype_data.quirks & FLEXCAN_QUIRK_SETUP_STOP_MODE_GPR) { |
| 545 | 545 | regmap_update_bits(priv->stm.gpr, priv->stm.req_gpr, |
| 546 | 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 | 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 | 569 | reg_mcr &= ~FLEXCAN_MCR_SLF_WAK; |
| 575 | 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 | 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 | 1983 | ret = flexcan_setup_stop_mode_scfw(pdev); |
| 1995 | 1984 | else if (priv->devtype_data.quirks & FLEXCAN_QUIRK_SETUP_STOP_MODE_GPR) |
| 1996 | 1985 | ret = flexcan_setup_stop_mode_gpr(pdev); |
| 1997 | − else if (priv->devtype_data.quirks & FLEXCAN_QUIRK_AUTO_STOP_MODE) | |
| 1998 | − ret = 0; | |
| 1999 | 1986 | else |
| 2000 | 1987 | /* return 0 directly if doesn't support stop mode feature */ |
| 2001 | 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 | 1998 | return ret; |
| 2005 | 1999 | |
| 2006 | 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 | 2314 | if (netif_running(dev)) { |
| 2321 | 2315 | int err; |
| 2322 | 2316 | |
| 2323 | − if (device_may_wakeup(device)) { | |
| 2317 | + if (device_may_wakeup(device)) | |
| 2324 | 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 | 2320 | err = pm_runtime_force_suspend(device); |
| 2335 | 2321 | if (err) |
| @@ -2347,15 +2333,9 @@ static int __maybe_unused flexcan_noirq_resume(struct device *device) · 11 unmodified lines | ||
| 2347 | 2333 | if (netif_running(dev)) { |
| 2348 | 2334 | int err; |
| 2349 | 2335 | |
| 2350 | − /* For the wakeup in auto stop mode, no need to gate on the | |
| 2351 | − * clock here, hardware will do this automatically. | |
| 2352 | − */ | |
| 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 | − } | |
| 2336 | + err = pm_runtime_force_resume(device); | |
| 2337 | + if (err) | |
| 2338 | + return err; | |
| 2359 | 2339 | |
| 2360 | 2340 | if (device_may_wakeup(device)) |
| 2361 | 2341 | flexcan_enable_wakeup_irq(priv, false); |
| @@ -68,8 +68,6 @@ · 67 unmodified lines | ||
| 68 | 68 | #define FLEXCAN_QUIRK_SUPPORT_RX_MAILBOX_RTR BIT(15) |
| 69 | 69 | /* Device supports RX via FIFO */ |
| 70 | 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 | 72 | struct flexcan_devtype_data { |
| 75 | 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 | 126 | [TCAN4553] = { |
| 127 | 127 | .name = "4553", |
| 128 | − .id2_register = 0x32353534, | |
| 128 | + .id2_register = 0x33353534, | |
| 129 | 129 | }, |
| 130 | 130 | /* generic version with no id2_register at the end */ |
| 131 | 131 | [TCAN4X5X] = { |
| @@ -392,7 +392,13 @@ static irqreturn_t sja1000_reset_interrupt(int irq, void *dev_id) · 391 unmodified lines | ||
| 392 | 392 | struct net_device *dev = (struct net_device *)dev_id; |
| 393 | 393 | |
| 394 | 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 | 403 | return IRQ_HANDLED; |
| 398 | 404 | } |
| @@ -2958,14 +2958,16 @@ static void mv88e6xxx_hardware_reset(struct mv88e6xxx_chip *chip) · 2957 unmodified lines | ||
| 2958 | 2958 | * from the wrong location resulting in the switch booting |
| 2959 | 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 | 2964 | gpiod_set_value_cansleep(gpiod, 1); |
| 2964 | 2965 | usleep_range(10000, 20000); |
| 2965 | 2966 | gpiod_set_value_cansleep(gpiod, 0); |
| 2966 | 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 | 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 | 78 | /* Offset 0x01: Switch MAC Address Register Bytes 0 & 1 |
| 110 | 79 | * Offset 0x02: Switch MAC Address Register Bytes 2 & 3 |
| 111 | 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 | 282 | int mv88e6185_g1_reset(struct mv88e6xxx_chip *chip); |
| 283 | 283 | int mv88e6352_g1_reset(struct mv88e6xxx_chip *chip); |
| 284 | 284 | int mv88e6250_g1_reset(struct mv88e6xxx_chip *chip); |
| 285 | −void mv88e6xxx_g1_wait_eeprom_done(struct mv88e6xxx_chip *chip); | |
| 286 | 285 | |
| 287 | 286 | int mv88e6185_g1_ppu_enable(struct mv88e6xxx_chip *chip); |
| 288 | 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 | 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 | 345 | int bit = __bf_shf(MV88E6XXX_G2_EEPROM_CMD_BUSY); |
| 346 | 346 | int err; |
| @@ -365,6 +365,7 @@ int mv88e6xxx_g2_trunk_clear(struct mv88e6xxx_chip *chip); · 364 unmodified lines | ||
| 365 | 365 | |
| 366 | 366 | int mv88e6xxx_g2_device_mapping_write(struct mv88e6xxx_chip *chip, int target, |
| 367 | 367 | int port); |
| 368 | +int mv88e6xxx_g2_eeprom_wait(struct mv88e6xxx_chip *chip); | |
| 368 | 369 | |
| 369 | 370 | extern const struct mv88e6xxx_irq_ops mv88e6097_watchdog_ops; |
| 370 | 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 | 505 | void *val_buf, size_t val_len) |
| 506 | 506 | { |
| 507 | 507 | int i, count = val_len / sizeof(u32), ret; |
| 508 | − u32 reg = *(u32 *)reg_buf & U16_MAX; | |
| 509 | 508 | struct qca8k_priv *priv = ctx; |
| 509 | + u32 reg = *(u16 *)reg_buf; | |
| 510 | 510 | |
| 511 | 511 | if (priv->mgmt_master && |
| 512 | 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 | 527 | const void *val_buf, size_t val_len) |
| 528 | 528 | { |
| 529 | 529 | int i, count = val_len / sizeof(u32), ret; |
| 530 | − u32 reg = *(u32 *)reg_buf & U16_MAX; | |
| 531 | 530 | struct qca8k_priv *priv = ctx; |
| 531 | + u32 reg = *(u16 *)reg_buf; | |
| 532 | 532 | u32 *val = (u32 *)val_buf; |
| 533 | 533 | |
| 534 | 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 | 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 | 678 | /* Actually start the request: |
| 670 | 679 | * 1. Send mdio master packet |
| 671 | 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 | 687 | mgmt_master = priv->mgmt_master; |
| 679 | 688 | if (!mgmt_master) { |
| 680 | 689 | mutex_unlock(&mgmt_eth_data->mutex); |
| 690 | + mutex_unlock(&priv->bus->mdio_lock); | |
| 681 | 691 | ret = -EINVAL; |
| 682 | 692 | goto err_mgmt_master; |
| 683 | 693 | } |
| @@ -765,6 +775,7 @@ exit: · 81 unmodified lines | ||
| 765 | 775 | QCA8K_ETHERNET_TIMEOUT); |
| 766 | 776 | |
| 767 | 777 | mutex_unlock(&mgmt_eth_data->mutex); |
| 778 | + mutex_unlock(&priv->bus->mdio_lock); | |
| 768 | 779 | |
| 769 | 780 | return ret; |
| 770 | 781 | |
| @@ -1303,24 +1303,23 @@ static void ibmveth_rx_csum_helper(struct sk_buff *skb, · 1302 unmodified lines | ||
| 1303 | 1303 | * the user space for finding a flow. During this process, OVS computes |
| 1304 | 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 | |
| 1307 | − * trunk mode. | |
| 1306 | + * So, re-compute TCP pseudo header checksum. | |
| 1308 | 1307 | */ |
| 1308 | + | |
| 1309 | 1309 | if (iph_proto == IPPROTO_TCP) { |
| 1310 | 1310 | struct tcphdr *tcph = (struct tcphdr *)(skb->data + iphlen); |
| 1311 | + | |
| 1311 | 1312 | if (tcph->check == 0x0000) { |
| 1312 | 1313 | /* Recompute TCP pseudo header checksum */ |
| 1313 | − if (adapter->is_active_trunk) { | |
| 1314 | − tcphdrlen = skb->len - iphlen; | |
| 1315 | − if (skb_proto == ETH_P_IP) | |
| 1316 | − tcph->check = | |
| 1317 | − ~csum_tcpudp_magic(iph->saddr, | |
| 1318 | − iph->daddr, tcphdrlen, iph_proto, 0); | |
| 1319 | − else if (skb_proto == ETH_P_IPV6) | |
| 1320 | − tcph->check = | |
| 1321 | − ~csum_ipv6_magic(&iph6->saddr, | |
| 1322 | − &iph6->daddr, tcphdrlen, iph_proto, 0); | |
| 1323 | − } | |
| 1314 | + tcphdrlen = skb->len - iphlen; | |
| 1315 | + if (skb_proto == ETH_P_IP) | |
| 1316 | + tcph->check = | |
| 1317 | + ~csum_tcpudp_magic(iph->saddr, | |
| 1318 | + iph->daddr, tcphdrlen, iph_proto, 0); | |
| 1319 | + else if (skb_proto == ETH_P_IPV6) | |
| 1320 | + tcph->check = | |
| 1321 | + ~csum_ipv6_magic(&iph6->saddr, | |
| 1322 | + &iph6->daddr, tcphdrlen, iph_proto, 0); | |
| 1324 | 1323 | /* Setup SKB fields for checksum offload */ |
| 1325 | 1324 | skb_partial_csum_set(skb, iphlen, |
| 1326 | 1325 | offsetof(struct tcphdr, check)); |
| @@ -2093,3 +2093,35 @@ lag_rebuild_out: · 2092 unmodified lines | ||
| 2093 | 2093 | } |
| 2094 | 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 | 62 | int ice_init_lag(struct ice_pf *pf); |
| 63 | 63 | void ice_deinit_lag(struct ice_pf *pf); |
| 64 | 64 | void ice_lag_rebuild(struct ice_pf *pf); |
| 65 | +bool ice_lag_is_switchdev_running(struct ice_pf *pf); | |
| 65 | 66 | #endif /* _ICE_LAG_H_ */ |
| @@ -3575,6 +3575,12 @@ int ice_set_dflt_vsi(struct ice_vsi *vsi) · 3574 unmodified lines | ||
| 3575 | 3575 | |
| 3576 | 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 | 3584 | /* the VSI passed in is already the default VSI */ |
| 3579 | 3585 | if (ice_is_vsi_dflt_vsi(vsi)) { |
| 3580 | 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 | 2617 | goto err; |
| 2618 | 2618 | } |
| 2619 | 2619 | |
| 2620 | − /* Read flexiflag registers to determine whether the | |
| 2621 | − * corresponding RXDID is configured and supported or not. | |
| 2622 | − * Since Legacy 16byte descriptor format is not supported, | |
| 2623 | − * start from Legacy 32byte descriptor. | |
| 2620 | + /* RXDIDs supported by DDP package can be read from the register | |
| 2621 | + * to get the supported RXDID bitmap. But the legacy 32byte RXDID | |
| 2622 | + * is not listed in DDP package, add it in the bitmap manually. | |
| 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 | 2628 | regval = rd32(hw, GLFLXP_RXDID_FLAGS(i, 0)); |
| 2627 | 2629 | if ((regval >> GLFLXP_RXDID_FLAGS_FLEXIFLAG_4N_S) |
| 2628 | 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 | 28 | struct vf_macvlans *mv_list; |
| 29 | 29 | int num_vf_macvlans, i; |
| 30 | 30 | |
| 31 | + /* Initialize list of VF macvlans */ | |
| 32 | + INIT_LIST_HEAD(&adapter->vf_mvs.l); | |
| 33 | + | |
| 31 | 34 | num_vf_macvlans = hw->mac.num_rar_entries - |
| 32 | 35 | (IXGBE_MAX_PF_MACVLANS + 1 + num_vfs); |
| 33 | 36 | if (!num_vf_macvlans) |
| @@ -36,8 +39,6 @@ static inline void ixgbe_alloc_vf_macvlans(struct ixgbe_adapter *adapter, · 2 unmodified lines | ||
| 36 | 39 | mv_list = kcalloc(num_vf_macvlans, sizeof(struct vf_macvlans), |
| 37 | 40 | GFP_KERNEL); |
| 38 | 41 | if (mv_list) { |
| 39 | − /* Initialize list of VF macvlans */ | |
| 40 | − INIT_LIST_HEAD(&adapter->vf_mvs.l); | |
| 41 | 42 | for (i = 0; i < num_vf_macvlans; i++) { |
| 42 | 43 | mv_list[i].vf = -1; |
| 43 | 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 | 1358 | if (netif_running(secy->netdev)) { |
| 1359 | 1359 | /* Keys cannot be changed after creation */ |
| 1360 | − err = cn10k_write_tx_sa_pn(pfvf, txsc, sa_num, | |
| 1361 | − sw_tx_sa->next_pn); | |
| 1362 | − if (err) | |
| 1363 | − return err; | |
| 1360 | + if (ctx->sa.update_pn) { | |
| 1361 | + err = cn10k_write_tx_sa_pn(pfvf, txsc, sa_num, | |
| 1362 | + sw_tx_sa->next_pn); | |
| 1363 | + if (err) | |
| 1364 | + return err; | |
| 1365 | + } | |
| 1364 | 1366 | |
| 1365 | 1367 | err = cn10k_mcs_link_tx_sa2sc(pfvf, secy, txsc, |
| 1366 | 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 | 1531 | if (err) |
| 1530 | 1532 | return err; |
| 1531 | 1533 | |
| 1534 | + if (!ctx->sa.update_pn) | |
| 1535 | + return 0; | |
| 1536 | + | |
| 1532 | 1537 | err = cn10k_mcs_write_rx_sa_pn(pfvf, rxsc, sa_num, |
| 1533 | 1538 | rx_sa->next_pn); |
| 1534 | 1539 | if (err) |
| @@ -1403,6 +1403,7 @@ int otx2_pool_init(struct otx2_nic *pfvf, u16 pool_id, · 1402 unmodified lines | ||
| 1403 | 1403 | return 0; |
| 1404 | 1404 | } |
| 1405 | 1405 | |
| 1406 | + pp_params.order = get_order(buf_size); | |
| 1406 | 1407 | pp_params.flags = PP_FLAG_PAGE_FRAG | PP_FLAG_DMA_MAP; |
| 1407 | 1408 | pp_params.pool_size = min(OTX2_PAGE_POOL_SZ, numptrs); |
| 1408 | 1409 | pp_params.nid = NUMA_NO_NODE; |
| @@ -2195,7 +2195,7 @@ struct rx_ring_info { · 2194 unmodified lines | ||
| 2195 | 2195 | struct sk_buff *skb; |
| 2196 | 2196 | dma_addr_t data_addr; |
| 2197 | 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 | 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 | 3172 | eth->rx_events++; |
| 3173 | 3173 | if (likely(napi_schedule_prep(ð->rx_napi))) { |
| 3174 | − __napi_schedule(ð->rx_napi); | |
| 3175 | 3174 | mtk_rx_irq_disable(eth, eth->soc->txrx.rx_irq_done_mask); |
| 3175 | + __napi_schedule(ð->rx_napi); | |
| 3176 | 3176 | } |
| 3177 | 3177 | |
| 3178 | 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 | 3185 | eth->tx_events++; |
| 3186 | 3186 | if (likely(napi_schedule_prep(ð->tx_napi))) { |
| 3187 | − __napi_schedule(ð->tx_napi); | |
| 3188 | 3187 | mtk_tx_irq_disable(eth, MTK_TX_DONE_INT); |
| 3188 | + __napi_schedule(ð->tx_napi); | |
| 3189 | 3189 | } |
| 3190 | 3190 | |
| 3191 | 3191 | return IRQ_HANDLED; |
| @@ -580,7 +580,7 @@ static int mlx5e_macsec_upd_txsa(struct macsec_context *ctx) · 579 unmodified lines | ||
| 580 | 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 | 584 | netdev_err(netdev, "MACsec offload: update TX sa %d PN isn't supported\n", |
| 585 | 585 | assoc_num); |
| 586 | 586 | err = -EINVAL; |
| @@ -973,7 +973,7 @@ static int mlx5e_macsec_upd_rxsa(struct macsec_context *ctx) · 386 unmodified lines | ||
| 973 | 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 | 977 | netdev_err(ctx->netdev, |
| 978 | 978 | "MACsec offload update RX sa %d PN isn't supported\n", |
| 979 | 979 | assoc_num); |
| @@ -3952,13 +3952,14 @@ static int set_feature_rx_fcs(struct net_device *netdev, bool enable) · 3951 unmodified lines | ||
| 3952 | 3952 | struct mlx5e_channels *chs = &priv->channels; |
| 3953 | 3953 | struct mlx5e_params new_params; |
| 3954 | 3954 | int err; |
| 3955 | + bool rx_ts_over_crc = !enable; | |
| 3955 | 3956 | |
| 3956 | 3957 | mutex_lock(&priv->state_lock); |
| 3957 | 3958 | |
| 3958 | 3959 | new_params = chs->params; |
| 3959 | 3960 | new_params.scatter_fcs_en = enable; |
| 3960 | 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 | 3963 | mutex_unlock(&priv->state_lock); |
| 3963 | 3964 | return err; |
| 3964 | 3965 | } |
| @@ -310,8 +310,8 @@ const struct mlxsw_sp_nve_ops mlxsw_sp1_nve_vxlan_ops = { · 309 unmodified lines | ||
| 310 | 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, | |
| 314 | − bool learning_en) | |
| 313 | +static int mlxsw_sp2_nve_vxlan_learning_set(struct mlxsw_sp *mlxsw_sp, | |
| 314 | + bool learning_en) | |
| 315 | 315 | { |
| 316 | 316 | char tnpc_pl[MLXSW_REG_TNPC_LEN]; |
| 317 | 317 | |
| @@ -46,6 +46,7 @@ config LAN743X · 45 unmodified lines | ||
| 46 | 46 | tristate "LAN743x support" |
| 47 | 47 | depends on PCI |
| 48 | 48 | depends on PTP_1588_CLOCK_OPTIONAL |
| 49 | + select PHYLIB | |
| 49 | 50 | select FIXED_PHY |
| 50 | 51 | select CRC16 |
| 51 | 52 | select CRC32 |
| @@ -91,63 +91,137 @@ static unsigned int mana_checksum_info(struct sk_buff *skb) · 90 unmodified lines | ||
| 91 | 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 | 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 | 108 | struct mana_skb_head *ash = (struct mana_skb_head *)skb->head; |
| 109 | + int hsg = 1; /* num of SGEs of linear part */ | |
| 98 | 110 | struct gdma_dev *gd = apc->ac->gdma_dev; |
| 111 | + int skb_hlen = skb_headlen(skb); | |
| 112 | + int sge0_len, sge1_len = 0; | |
| 99 | 113 | struct gdma_context *gc; |
| 100 | 114 | struct device *dev; |
| 101 | 115 | skb_frag_t *frag; |
| 102 | 116 | dma_addr_t da; |
| 117 | + int sg_i; | |
| 103 | 118 | int i; |
| 104 | 119 | |
| 105 | 120 | gc = gd->gdma_context; |
| 106 | 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 | 131 | if (dma_mapping_error(dev, da)) |
| 110 | 132 | return -ENOMEM; |
| 111 | 133 | |
| 112 | − ash->dma_handle[0] = da; | |
| 113 | − ash->size[0] = skb_headlen(skb); | |
| 134 | + mana_add_sge(tp, ash, 0, da, sge0_len, gd->gpa_mkey); | |
| 114 | 135 | |
| 115 | − tp->wqe_req.sgl[0].address = ash->dma_handle[0]; | |
| 116 | − tp->wqe_req.sgl[0].mem_key = gd->gpa_mkey; | |
| 117 | − tp->wqe_req.sgl[0].size = ash->size[0]; | |
| 136 | + if (sge1_len) { | |
| 137 | + sg_i = 1; | |
| 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 | 147 | for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) { |
| 148 | + sg_i = hsg + i; | |
| 149 | + | |
| 120 | 150 | frag = &skb_shinfo(skb)->frags[i]; |
| 121 | 151 | da = skb_frag_dma_map(dev, frag, 0, skb_frag_size(frag), |
| 122 | 152 | DMA_TO_DEVICE); |
| 123 | − | |
| 124 | 153 | if (dma_mapping_error(dev, da)) |
| 125 | 154 | goto frag_err; |
| 126 | 155 | |
| 127 | − ash->dma_handle[i + 1] = da; | |
| 128 | − ash->size[i + 1] = skb_frag_size(frag); | |
| 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]; | |
| 156 | + mana_add_sge(tp, ash, sg_i, da, skb_frag_size(frag), | |
| 157 | + gd->gpa_mkey); | |
| 133 | 158 | } |
| 134 | 159 | |
| 135 | 160 | return 0; |
| 136 | 161 | |
| 137 | 162 | frag_err: |
| 138 | − for (i = i - 1; i >= 0; i--) | |
| 139 | − dma_unmap_page(dev, ash->dma_handle[i + 1], ash->size[i + 1], | |
| 163 | + for (i = sg_i - 1; i >= hsg; i--) | |
| 164 | + dma_unmap_page(dev, ash->dma_handle[i], ash->size[i], | |
| 140 | 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 | 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 | 220 | netdev_tx_t mana_start_xmit(struct sk_buff *skb, struct net_device *ndev) |
| 148 | 221 | { |
| 149 | 222 | enum mana_tx_pkt_format pkt_fmt = MANA_SHORT_PKT_FMT; |
| 150 | 223 | struct mana_port_context *apc = netdev_priv(ndev); |
| 224 | + int gso_hs = 0; /* zero for non-GSO pkts */ | |
| 151 | 225 | u16 txq_idx = skb_get_queue_mapping(skb); |
| 152 | 226 | struct gdma_dev *gd = apc->ac->gdma_dev; |
| 153 | 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 | 233 | struct mana_txq *txq; |
| 160 | 234 | struct mana_cq *cq; |
| 161 | 235 | int err, len; |
| 162 | − u16 ihs; | |
| 163 | 236 | |
| 164 | 237 | if (unlikely(!apc->port_is_up)) |
| 165 | 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 | 282 | pkg.wqe_req.client_data_unit = 0; |
| 210 | 283 | |
| 211 | 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 | 286 | if (skb->protocol == htons(ETH_P_IP)) |
| 227 | 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 | 289 | ipv6 = true; |
| 230 | 290 | |
| 231 | 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 | 312 | pkg.tx_oob.s_oob.is_outer_ipv4 = ipv4; |
| 233 | 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 | 332 | &ipv6_hdr(skb)->daddr, 0, |
| 253 | 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 | 335 | } else if (skb->ip_summed == CHECKSUM_PARTIAL) { |
| 278 | 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 | 354 | } else { |
| 297 | 355 | /* Can't do offload of this type of checksum */ |
| 298 | 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 | 376 | u64_stats_update_begin(&tx_stats->syncp); |
| 305 | 377 | tx_stats->mana_map_err++; |
| 306 | 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 | 1330 | struct mana_skb_head *ash = (struct mana_skb_head *)skb->head; |
| 1259 | 1331 | struct gdma_context *gc = apc->ac->gdma_dev->gdma_context; |
| 1260 | 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 | 1343 | dma_unmap_page(dev, ash->dma_handle[i], ash->size[i], |
| 1267 | 1344 | DMA_TO_DEVICE); |
| 1268 | 1345 | } |
| @@ -1317,19 +1394,23 @@ static void mana_poll_tx_cq(struct mana_cq *cq) · 48 unmodified lines | ||
| 1317 | 1394 | case CQE_TX_VPORT_IDX_OUT_OF_RANGE: |
| 1318 | 1395 | case CQE_TX_VPORT_DISABLED: |
| 1319 | 1396 | case CQE_TX_VLAN_TAGGING_VIOLATION: |
| 1320 | − WARN_ONCE(1, "TX: CQE error %d: ignored.\n", | |
| 1321 | − cqe_oob->cqe_hdr.cqe_type); | |
| 1397 | + if (net_ratelimit()) | |
| 1398 | + netdev_err(ndev, "TX: CQE error %d\n", | |
| 1399 | + cqe_oob->cqe_hdr.cqe_type); | |
| 1400 | + | |
| 1322 | 1401 | apc->eth_stats.tx_cqe_err++; |
| 1323 | 1402 | break; |
| 1324 | 1403 | |
| 1325 | 1404 | default: |
| 1326 | − /* If the CQE type is unexpected, log an error, assert, | |
| 1327 | − * and go through the error path. | |
| 1405 | + /* If the CQE type is unknown, log an error, | |
| 1406 | + * and still free the SKB, update tail, etc. | |
| 1328 | 1407 | */ |
| 1329 | − WARN_ONCE(1, "TX: Unexpected CQE type %d: HW BUG?\n", | |
| 1330 | − cqe_oob->cqe_hdr.cqe_type); | |
| 1408 | + if (net_ratelimit()) | |
| 1409 | + netdev_err(ndev, "TX: unknown CQE type %d\n", | |
| 1410 | + cqe_oob->cqe_hdr.cqe_type); | |
| 1411 | + | |
| 1331 | 1412 | apc->eth_stats.tx_cqe_unknown_type++; |
| 1332 | − return; | |
| 1413 | + break; | |
| 1333 | 1414 | } |
| 1334 | 1415 | |
| 1335 | 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 | 210 | unsigned int msg_len = nfp_flower_cmsg_get_data_len(skb); |
| 211 | 211 | struct nfp_flower_cmsg_merge_hint *msg; |
| 212 | 212 | struct nfp_fl_payload *sub_flows[2]; |
| 213 | + struct nfp_flower_priv *priv; | |
| 213 | 214 | int err, i, flow_cnt; |
| 214 | 215 | |
| 215 | 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 | 229 | return; |
| 229 | 230 | } |
| 230 | 231 | |
| 231 | − rtnl_lock(); | |
| 232 | + priv = app->priv; | |
| 233 | + mutex_lock(&priv->nfp_fl_lock); | |
| 232 | 234 | for (i = 0; i < flow_cnt; i++) { |
| 233 | 235 | u32 ctx = be32_to_cpu(msg->flow[i].host_ctx); |
| 234 | 236 | |
| 235 | 237 | sub_flows[i] = nfp_flower_get_fl_payload_from_ctx(app, ctx); |
| 236 | 238 | if (!sub_flows[i]) { |
| 237 | 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 | 246 | if (err == -ENOMEM) |
| 245 | 247 | nfp_flower_cmsg_warn(app, "Flow merge memory fail.\n"); |
| 246 | 248 | |
| 247 | −err_rtnl_unlock: | |
| 248 | − rtnl_unlock(); | |
| 249 | +err_mutex_unlock: | |
| 250 | + mutex_unlock(&priv->nfp_fl_lock); | |
| 249 | 251 | } |
| 250 | 252 | |
| 251 | 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 | 2131 | struct nfp_fl_ct_flow_entry *ct_entry; |
| 2132 | 2132 | struct netlink_ext_ack *extack = NULL; |
| 2133 | 2133 | |
| 2134 | − ASSERT_RTNL(); | |
| 2135 | − | |
| 2136 | 2134 | extack = flow->common.extack; |
| 2137 | 2135 | switch (flow->command) { |
| 2138 | 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 | 2177 | switch (type) { |
| 2180 | 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 | 2184 | err = nfp_fl_ct_offload_nft_flow(zt, flow); |
| 2183 | − rtnl_unlock(); | |
| 2185 | + mutex_unlock(&zt->priv->nfp_fl_lock); | |
| 2184 | 2186 | break; |
| 2185 | 2187 | default: |
| 2186 | 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 | 2210 | struct nfp_fl_ct_flow_entry *ct_entry; |
| 2209 | 2211 | struct nfp_fl_ct_zone_entry *zt; |
| 2210 | 2212 | struct rhashtable *m_table; |
| 2213 | + struct nf_flowtable *nft; | |
| 2211 | 2214 | |
| 2212 | 2215 | if (!ct_map_ent) |
| 2213 | 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 | 2229 | if (ct_map_ent->cookie > 0) |
| 2227 | 2230 | kfree(ct_map_ent); |
| 2228 | 2231 | |
| 2229 | − if (!zt->pre_ct_count) { | |
| 2230 | − zt->nft = NULL; | |
| 2232 | + if (!zt->pre_ct_count && zt->nft) { | |
| 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 | 2238 | nfp_fl_ct_clean_nft_entries(zt); |
| 2232 | 2239 | } |
| 2233 | 2240 | break; |
| @@ -297,6 +297,7 @@ struct nfp_fl_internal_ports { · 296 unmodified lines | ||
| 297 | 297 | * @predt_list: List to keep track of decap pretun flows |
| 298 | 298 | * @neigh_table: Table to keep track of neighbor entries |
| 299 | 299 | * @predt_lock: Lock to serialise predt/neigh table updates |
| 300 | + * @nfp_fl_lock: Lock to protect the flow offload operation | |
| 300 | 301 | */ |
| 301 | 302 | struct nfp_flower_priv { |
| 302 | 303 | struct nfp_app *app; |
| @@ -339,6 +340,7 @@ struct nfp_flower_priv { · 36 unmodified lines | ||
| 339 | 340 | struct list_head predt_list; |
| 340 | 341 | struct rhashtable neigh_table; |
| 341 | 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 | 528 | if (err) |
| 529 | 529 | goto err_free_stats_ctx_table; |
| 530 | 530 | |
| 531 | + mutex_init(&priv->nfp_fl_lock); | |
| 532 | + | |
| 531 | 533 | err = rhashtable_init(&priv->ct_zone_table, &nfp_zone_table_params); |
| 532 | 534 | if (err) |
| 533 | 535 | goto err_free_merge_table; |
| @@ -1009,8 +1009,6 @@ int nfp_flower_merge_offloaded_flows(struct nfp_app *app, · 1008 unmodified lines | ||
| 1009 | 1009 | u64 parent_ctx = 0; |
| 1010 | 1010 | int err; |
| 1011 | 1011 | |
| 1012 | − ASSERT_RTNL(); | |
| 1013 | − | |
| 1014 | 1012 | if (sub_flow1 == sub_flow2 || |
| 1015 | 1013 | nfp_flower_is_merge_flow(sub_flow1) || |
| 1016 | 1014 | nfp_flower_is_merge_flow(sub_flow2)) |
| @@ -1727,19 +1725,30 @@ static int · 710 unmodified lines | ||
| 1727 | 1725 | nfp_flower_repr_offload(struct nfp_app *app, struct net_device *netdev, |
| 1728 | 1726 | struct flow_cls_offload *flower) |
| 1729 | 1727 | { |
| 1728 | + struct nfp_flower_priv *priv = app->priv; | |
| 1729 | + int ret; | |
| 1730 | + | |
| 1730 | 1731 | if (!eth_proto_is_802_3(flower->common.protocol)) |
| 1731 | 1732 | return -EOPNOTSUPP; |
| 1732 | 1733 | |
| 1734 | + mutex_lock(&priv->nfp_fl_lock); | |
| 1733 | 1735 | switch (flower->command) { |
| 1734 | 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 | 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 | 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 | 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 | 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 | 1787 | repr_priv = repr->app_priv; |
| 1779 | 1788 | repr_priv->block_shared = f->block_shared; |
| 1780 | 1789 | f->driver_block_list = &nfp_block_cb_list; |
| 1790 | + f->unlocked_driver_cb = true; | |
| 1781 | 1791 | |
| 1782 | 1792 | switch (f->command) { |
| 1783 | 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 | 1886 | nfp_flower_internal_port_can_offload(app, netdev))) |
| 1877 | 1887 | return -EOPNOTSUPP; |
| 1878 | 1888 | |
| 1889 | + f->unlocked_driver_cb = true; | |
| 1890 | + | |
| 1879 | 1891 | switch (f->command) { |
| 1880 | 1892 | case FLOW_BLOCK_BIND: |
| 1881 | 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 | 524 | struct netlink_ext_ack *extack = flow->common.extack; |
| 525 | 525 | struct nfp_flower_priv *fl_priv = app->priv; |
| 526 | + int ret; | |
| 526 | 527 | |
| 527 | 528 | if (!(fl_priv->flower_ext_feats & NFP_FL_FEATS_VF_RLIM)) { |
| 528 | 529 | NL_SET_ERR_MSG_MOD(extack, "unsupported offload: loaded firmware does not support qos rate limit offload"); |
| 529 | 530 | return -EOPNOTSUPP; |
| 530 | 531 | } |
| 531 | 532 | |
| 533 | + mutex_lock(&fl_priv->nfp_fl_lock); | |
| 532 | 534 | switch (flow->command) { |
| 533 | 535 | case TC_CLSMATCHALL_REPLACE: |
| 534 | − return nfp_flower_install_rate_limiter(app, netdev, flow, | |
| 535 | − extack); | |
| 536 | + ret = nfp_flower_install_rate_limiter(app, netdev, flow, extack); | |
| 537 | + break; | |
| 536 | 538 | case TC_CLSMATCHALL_DESTROY: |
| 537 | − return nfp_flower_remove_rate_limiter(app, netdev, flow, | |
| 538 | − extack); | |
| 539 | + ret = nfp_flower_remove_rate_limiter(app, netdev, flow, extack); | |
| 540 | + break; | |
| 539 | 541 | case TC_CLSMATCHALL_STATS: |
| 540 | − return nfp_flower_stats_rate_limiter(app, netdev, flow, | |
| 541 | − extack); | |
| 542 | + ret = nfp_flower_stats_rate_limiter(app, netdev, flow, extack); | |
| 543 | + break; | |
| 542 | 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 | 553 | /* Offload tc action, currently only for tc police */ |
| @@ -110,9 +110,9 @@ struct qed_ll2_info { · 109 unmodified lines | ||
| 110 | 110 | enum core_tx_dest tx_dest; |
| 111 | 111 | u8 tx_stats_en; |
| 112 | 112 | bool main_func_queue; |
| 113 | + struct qed_ll2_cbs cbs; | |
| 113 | 114 | struct qed_ll2_rx_queue rx_queue; |
| 114 | 115 | struct qed_ll2_tx_queue tx_queue; |
| 115 | − struct qed_ll2_cbs cbs; | |
| 116 | 116 | }; |
| 117 | 117 | |
| 118 | 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 | 2167 | of_phy_deregister_fixed_link(np); |
| 2168 | 2168 | } |
| 2169 | 2169 | |
| 2170 | + cancel_work_sync(&priv->work); | |
| 2171 | + | |
| 2170 | 2172 | if (info->multi_irqs) { |
| 2171 | 2173 | free_irq(priv->tx_irqs[RAVB_NC], ndev); |
| 2172 | 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 | 2893 | clk_disable_unprepare(priv->gptp_clk); |
| 2892 | 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 | 2896 | /* Set reset mode */ |
| 2897 | 2897 | ravb_write(ndev, CCC_OPC_RESET, CCC); |
| 2898 | 2898 | unregister_netdev(ndev); |
| @@ -2900,6 +2900,8 @@ static int ravb_remove(struct platform_device *pdev) · 1 unmodified line | ||
| 2900 | 2900 | netif_napi_del(&priv->napi[RAVB_NC]); |
| 2901 | 2901 | netif_napi_del(&priv->napi[RAVB_BE]); |
| 2902 | 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 | 2905 | pm_runtime_put_sync(&pdev->dev); |
| 2904 | 2906 | pm_runtime_disable(&pdev->dev); |
| 2905 | 2907 | reset_control_assert(priv->rstc); |
| @@ -4,6 +4,7 @@ · 3 unmodified lines | ||
| 4 | 4 | * Copyright (C) 2022 Renesas Electronics Corporation |
| 5 | 5 | */ |
| 6 | 6 | |
| 7 | +#include <linux/clk.h> | |
| 7 | 8 | #include <linux/dma-mapping.h> |
| 8 | 9 | #include <linux/err.h> |
| 9 | 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 | 1050 | static void rswitch_etha_enable_mii(struct rswitch_etha *etha) |
| 1050 | 1051 | { |
| 1051 | 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 | 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 | 1254 | phy_print_status(phydev); |
| 1254 | 1255 | if (phydev->link) |
| 1255 | 1256 | phy_power_on(rdev->serdes); |
| 1256 | − else | |
| 1257 | + else if (rdev->serdes->power_count) | |
| 1257 | 1258 | phy_power_off(rdev->serdes); |
| 1258 | 1259 | |
| 1259 | 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 | 1694 | etha->index = index; |
| 1694 | 1695 | etha->addr = priv->addr + RSWITCH_ETHA_OFFSET + index * RSWITCH_ETHA_SIZE; |
| 1695 | 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 | 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 | 1907 | return -ENOMEM; |
| 1901 | 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 | 1914 | attr = soc_device_match(rswitch_soc_no_speed_change); |
| 1904 | 1915 | if (attr) |
| 1905 | 1916 | priv->etha_no_runtime_change = true; |
| @@ -1953,15 +1964,17 @@ static void rswitch_deinit(struct rswitch_private *priv) · 47 unmodified lines | ||
| 1953 | 1964 | rswitch_gwca_hw_deinit(priv); |
| 1954 | 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 | 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 | 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 | 1978 | rswitch_gwca_ts_queue_free(priv); |
| 1966 | 1979 | rswitch_gwca_linkfix_free(priv); |
| 1967 | 1980 | |
| @@ -915,6 +915,7 @@ struct rswitch_etha { · 914 unmodified lines | ||
| 915 | 915 | bool external_phy; |
| 916 | 916 | struct mii_bus *mii; |
| 917 | 917 | phy_interface_t phy_interface; |
| 918 | + u32 psmcs; | |
| 918 | 919 | u8 mac_addr[MAX_ADDR_LEN]; |
| 919 | 920 | int link; |
| 920 | 921 | int speed; |
| @@ -1012,6 +1013,7 @@ struct rswitch_private { · 91 unmodified lines | ||
| 1012 | 1013 | struct rswitch_mfwd mfwd; |
| 1013 | 1014 | |
| 1014 | 1015 | spinlock_t lock; /* lock interrupt registers' control */ |
| 1016 | + struct clk *clk; | |
| 1015 | 1017 | |
| 1016 | 1018 | bool etha_no_runtime_change; |
| 1017 | 1019 | bool gwca_halt; |
| @@ -104,6 +104,7 @@ struct stm32_ops { · 103 unmodified lines | ||
| 104 | 104 | int (*parse_data)(struct stm32_dwmac *dwmac, |
| 105 | 105 | struct device *dev); |
| 106 | 106 | u32 syscfg_eth_mask; |
| 107 | + bool clk_rx_enable_in_suspend; | |
| 107 | 108 | }; |
| 108 | 109 | |
| 109 | 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 | 122 | if (ret) |
| 122 | 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 | 127 | ret = clk_prepare_enable(dwmac->clk_rx); |
| 126 | 128 | if (ret) { |
| 127 | 129 | clk_disable_unprepare(dwmac->clk_tx); |
| @@ -513,7 +515,8 @@ static struct stm32_ops stm32mp1_dwmac_data = { · 385 unmodified lines | ||
| 513 | 515 | .suspend = stm32mp1_suspend, |
| 514 | 516 | .resume = stm32mp1_resume, |
| 515 | 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 | 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 | 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 | 6006 | * stmmac_ioctl - Entry point for the Ioctl |
| 6034 | 6007 | * @dev: Device pointer. |
| @@ -6989,9 +6962,6 @@ static const struct net_device_ops stmmac_netdev_ops = { · 954 unmodified lines | ||
| 6989 | 6962 | .ndo_get_stats64 = stmmac_get_stats64, |
| 6990 | 6963 | .ndo_setup_tc = stmmac_setup_tc, |
| 6991 | 6964 | .ndo_select_queue = stmmac_select_queue, |
| 6992 | −#ifdef CONFIG_NET_POLL_CONTROLLER | |
| 6993 | − .ndo_poll_controller = stmmac_poll_controller, | |
| 6994 | −#endif | |
| 6995 | 6965 | .ndo_set_mac_address = stmmac_set_mac_address, |
| 6996 | 6966 | .ndo_vlan_rx_add_vid = stmmac_vlan_rx_add_vid, |
| 6997 | 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 | 901 | struct platform_device *pdev = to_platform_device(dev); |
| 902 | 902 | int ret; |
| 903 | 903 | |
| 904 | − ret = stmmac_pltfr_init(pdev, priv->plat->bsp_priv); | |
| 904 | + ret = stmmac_pltfr_init(pdev, priv->plat); | |
| 905 | 905 | if (ret) |
| 906 | 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 | 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 | 1751 | dev_err(dev, "Failed to get tx dma irq %d\n", |
| 1752 | 1752 | tx_chn->irq); |
| 1753 | + ret = tx_chn->irq; | |
| 1753 | 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 | 316 | goto fail; |
| 317 | 317 | } |
| 318 | 318 | |
| 319 | − tx_chn->irq = k3_udma_glue_tx_get_irq(tx_chn->tx_chn); | |
| 320 | − if (tx_chn->irq <= 0) { | |
| 321 | − ret = -EINVAL; | |
| 319 | + ret = k3_udma_glue_tx_get_irq(tx_chn->tx_chn); | |
| 320 | + if (ret < 0) { | |
| 322 | 321 | netdev_err(ndev, "failed to get tx irq\n"); |
| 323 | 322 | goto fail; |
| 324 | 323 | } |
| 324 | + tx_chn->irq = ret; | |
| 325 | 325 | |
| 326 | 326 | snprintf(tx_chn->name, sizeof(tx_chn->name), "%s-tx%d", |
| 327 | 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 | 2740 | struct device_node *np = spi->dev.of_node; |
| 2741 | 2741 | struct ca8210_priv *priv = spi_get_drvdata(spi); |
| 2742 | 2742 | struct ca8210_platform_data *pdata = spi->dev.platform_data; |
| 2743 | − int ret = 0; | |
| 2744 | 2743 | |
| 2745 | 2744 | if (!np) |
| 2746 | 2745 | return -EFAULT; |
| @@ -2757,18 +2756,8 @@ static int ca8210_register_ext_clock(struct spi_device *spi) · 10 unmodified lines | ||
| 2757 | 2756 | dev_crit(&spi->dev, "Failed to register external clk\n"); |
| 2758 | 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 | 2770 | struct ca8210_priv *priv = spi_get_drvdata(spi); |
| 2782 | 2771 | |
| 2783 | − if (!priv->clk) | |
| 2784 | − return | |
| 2772 | + if (IS_ERR_OR_NULL(priv->clk)) | |
| 2773 | + return; | |
| 2785 | 2774 | |
| 2786 | 2775 | of_clk_del_provider(spi->dev.of_node); |
| 2787 | 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 | 2384 | ctx.sa.assoc_num = assoc_num; |
| 2385 | 2385 | ctx.sa.tx_sa = tx_sa; |
| 2386 | + ctx.sa.update_pn = !!prev_pn.full64; | |
| 2386 | 2387 | ctx.secy = secy; |
| 2387 | 2388 | |
| 2388 | 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 | 2478 | ctx.sa.assoc_num = assoc_num; |
| 2478 | 2479 | ctx.sa.rx_sa = rx_sa; |
| 2480 | + ctx.sa.update_pn = !!prev_pn.full64; | |
| 2479 | 2481 | ctx.secy = secy; |
| 2480 | 2482 | |
| 2481 | 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 | 849 | struct macsec_flow *flow; |
| 850 | 850 | int ret; |
| 851 | 851 | |
| 852 | + if (ctx->sa.update_pn) | |
| 853 | + return -EINVAL; | |
| 854 | + | |
| 852 | 855 | flow = vsc8584_macsec_find_flow(ctx, MACSEC_INGR); |
| 853 | 856 | if (IS_ERR(flow)) |
| 854 | 857 | return PTR_ERR(flow); |
| @@ -900,6 +903,9 @@ static int vsc8584_macsec_upd_txsa(struct macsec_context *ctx) · 45 unmodified lines | ||
| 900 | 903 | struct macsec_flow *flow; |
| 901 | 904 | int ret; |
| 902 | 905 | |
| 906 | + if (ctx->sa.update_pn) | |
| 907 | + return -EINVAL; | |
| 908 | + | |
| 903 | 909 | flow = vsc8584_macsec_find_flow(ctx, MACSEC_EGR); |
| 904 | 910 | if (IS_ERR(flow)) |
| 905 | 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 | 222 | struct usbnet *dev = netdev_priv(netdev); |
| 223 | 223 | |
| 224 | 224 | __le16 res; |
| 225 | + int err; | |
| 225 | 226 | |
| 226 | 227 | if (phy_id) { |
| 227 | 228 | netdev_dbg(dev->net, "Only internal phy supported\n"); |
| 228 | 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 | 238 | netdev_dbg(dev->net, |
| 234 | 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 | 90 | ret = fn(dev, USB_VENDOR_REQUEST_READ_REGISTER, USB_DIR_IN |
| 91 | 91 | | USB_TYPE_VENDOR | USB_RECIP_DEVICE, |
| 92 | 92 | 0, index, &buf, 4); |
| 93 | − if (unlikely(ret < 0)) { | |
| 93 | + if (unlikely(ret < 4)) { | |
| 94 | + ret = ret < 0 ? ret : -ENODATA; | |
| 95 | + | |
| 94 | 96 | netdev_warn(dev->net, "Failed to read reg index 0x%08x: %d\n", |
| 95 | 97 | index, ret); |
| 96 | 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 | 608 | --dma->ref; |
| 609 | 609 | |
| 610 | − if (dma->ref) { | |
| 611 | − if (dma->need_sync && len) { | |
| 612 | − offset = buf - (head + sizeof(*dma)); | |
| 610 | + if (dma->need_sync && len) { | |
| 611 | + offset = buf - (head + sizeof(*dma)); | |
| 613 | 612 | |
| 614 | − virtqueue_dma_sync_single_range_for_cpu(rq->vq, dma->addr, offset, | |
| 615 | − len, DMA_FROM_DEVICE); | |
| 616 | − } | |
| 613 | + virtqueue_dma_sync_single_range_for_cpu(rq->vq, dma->addr, | |
| 614 | + offset, len, | |
| 615 | + DMA_FROM_DEVICE); | |
| 616 | + } | |
| 617 | 617 | |
| 618 | + if (dma->ref) | |
| 618 | 619 | return; |
| 619 | − } | |
| 620 | 620 | |
| 621 | 621 | virtqueue_dma_unmap_single_attrs(rq->vq, dma->addr, dma->len, |
| 622 | 622 | DMA_FROM_DEVICE, DMA_ATTR_SKIP_CPU_SYNC); |
| @@ -34,6 +34,8 @@ · 33 unmodified lines | ||
| 34 | 34 | #define TDM_PPPOHT_SLIC_MAXIN |
| 35 | 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 | 39 | static struct ucc_tdm_info utdm_primary_info = { |
| 38 | 40 | .uf_info = { |
| 39 | 41 | .tsa = 0, |
| @@ -708,6 +710,7 @@ static int uhdlc_open(struct net_device *dev) · 668 unmodified lines | ||
| 708 | 710 | hdlc_device *hdlc = dev_to_hdlc(dev); |
| 709 | 711 | struct ucc_hdlc_private *priv = hdlc->priv; |
| 710 | 712 | struct ucc_tdm *utdm = priv->utdm; |
| 713 | + int rc = 0; | |
| 711 | 714 | |
| 712 | 715 | if (priv->hdlc_busy != 1) { |
| 713 | 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 | 734 | napi_enable(&priv->napi); |
| 732 | 735 | netdev_reset_queue(dev); |
| 733 | 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 | 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 | 830 | netdev_reset_queue(dev); |
| 825 | 831 | priv->hdlc_busy = 0; |
| 826 | 832 | |
| 833 | + hdlc_close(dev); | |
| 834 | + | |
| 827 | 835 | return 0; |
| 828 | 836 | } |
| 829 | 837 | |
| @@ -442,7 +442,12 @@ struct brcmf_scan_params_v2_le { · 441 unmodified lines | ||
| 442 | 442 | * fixed parameter portion is assumed, otherwise |
| 443 | 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 | 453 | struct brcmf_scan_results { |
| @@ -702,7 +707,7 @@ struct brcmf_sta_info_le { · 253 unmodified lines | ||
| 702 | 707 | |
| 703 | 708 | struct brcmf_chanspec_list { |
| 704 | 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 | 310 | struct iwl_fw_ini_error_dump_range { |
| 311 | 311 | __le32 range_data_size; |
| 312 | 312 | union { |
| 313 | − __le32 internal_base_addr; | |
| 314 | − __le64 dram_base_addr; | |
| 315 | − __le32 page_num; | |
| 313 | + __le32 internal_base_addr __packed; | |
| 314 | + __le64 dram_base_addr __packed; | |
| 315 | + __le32 page_num __packed; | |
| 316 | 316 | struct iwl_fw_ini_fifo_hdr fifo_hdr; |
| 317 | 317 | struct iwl_cmd_header fw_pkt_hdr; |
| 318 | 318 | }; |
| @@ -802,7 +802,7 @@ out: · 801 unmodified lines | ||
| 802 | 802 | mvm->nvm_data->bands[0].n_channels = 1; |
| 803 | 803 | mvm->nvm_data->bands[0].n_bitrates = 1; |
| 804 | 804 | mvm->nvm_data->bands[0].bitrates = |
| 805 | − (void *)((u8 *)mvm->nvm_data->channels + 1); | |
| 805 | + (void *)(mvm->nvm_data->channels + 1); | |
| 806 | 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 | 732 | mvmvif->associated = vif->cfg.assoc; |
| 733 | 733 | |
| 734 | − if (!(changes & BSS_CHANGED_ASSOC)) | |
| 735 | − return; | |
| 736 | − | |
| 737 | − if (vif->cfg.assoc) { | |
| 738 | − /* clear statistics to get clean beacon counter */ | |
| 739 | − iwl_mvm_request_statistics(mvm, true); | |
| 740 | − iwl_mvm_sf_update(mvm, vif, false); | |
| 741 | − iwl_mvm_power_vif_assoc(mvm, vif); | |
| 742 | − | |
| 743 | − for_each_mvm_vif_valid_link(mvmvif, i) { | |
| 744 | − memset(&mvmvif->link[i]->beacon_stats, 0, | |
| 745 | − sizeof(mvmvif->link[i]->beacon_stats)); | |
| 734 | + if (changes & BSS_CHANGED_ASSOC) { | |
| 735 | + if (vif->cfg.assoc) { | |
| 736 | + /* clear statistics to get clean beacon counter */ | |
| 737 | + iwl_mvm_request_statistics(mvm, true); | |
| 738 | + iwl_mvm_sf_update(mvm, vif, false); | |
| 739 | + iwl_mvm_power_vif_assoc(mvm, vif); | |
| 740 | + | |
| 741 | + for_each_mvm_vif_valid_link(mvmvif, i) { | |
| 742 | + memset(&mvmvif->link[i]->beacon_stats, 0, | |
| 743 | + sizeof(mvmvif->link[i]->beacon_stats)); | |
| 744 | + | |
| 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) { | |
| 748 | − iwl_mvm_update_smps(mvm, vif, | |
| 749 | − IWL_MVM_SMPS_REQ_PROT, | |
| 750 | − IEEE80211_SMPS_DYNAMIC, i); | |
| 758 | + if (!test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status) && | |
| 759 | + protect) { | |
| 760 | + /* If we're not restarting and still haven't | |
| 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(); | |
| 754 | − link_conf = rcu_dereference(vif->link_conf[i]); | |
| 755 | − if (link_conf && !link_conf->dtim_period) | |
| 756 | − protect = true; | |
| 757 | − rcu_read_unlock(); | |
| 758 | − } | |
| 772 | + iwl_mvm_sf_update(mvm, vif, false); | |
| 773 | + | |
| 774 | + /* FIXME: need to decide about misbehaving AP handling */ | |
| 775 | + iwl_mvm_power_vif_assoc(mvm, vif); | |
| 776 | + } else if (iwl_mvm_mld_vif_have_valid_ap_sta(mvmvif)) { | |
| 777 | + iwl_mvm_mei_host_disassociated(mvm); | |
| 759 | 778 | |
| 760 | − if (!test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status) && | |
| 761 | − protect) { | |
| 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. | |
| 779 | + /* If update fails - SF might be running in associated | |
| 780 | + * mode while disassociated - which is forbidden. | |
| 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); | |
| 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 | + iwl_mvm_bss_info_changed_station_assoc(mvm, vif, changes); | |
| 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 | 808 | static void |
| @@ -2342,7 +2342,7 @@ iwl_mvm_scan_umac_fill_general_p_v12(struct iwl_mvm *mvm, · 2341 unmodified lines | ||
| 2342 | 2342 | if (gen_flags & IWL_UMAC_SCAN_GEN_FLAGS_V2_FRAGMENTED_LMAC2) |
| 2343 | 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 | 2346 | gp->scan_start_mac_or_link_id = scan_vif->id; |
| 2347 | 2347 | } else { |
| 2348 | 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 | 1612 | iwl_trans_free_tx_cmd(mvm->trans, info->driver_data[1]); |
| 1613 | 1613 | |
| 1614 | 1614 | memset(&info->status, 0, sizeof(info->status)); |
| 1615 | + info->flags &= ~(IEEE80211_TX_STAT_ACK | IEEE80211_TX_STAT_TX_FILTERED); | |
| 1615 | 1616 | |
| 1616 | 1617 | /* inform mac80211 about what happened with the frame */ |
| 1617 | 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 | 1966 | if (!is_flush) |
| 1966 | 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 | 919 | mwifiex_dbg_dump(priv->adapter, EVT_D, "RXBA_SYNC event:", |
| 920 | 920 | event_buf, len); |
| 921 | − while (tlv_buf_left >= sizeof(*tlv_rxba)) { | |
| 921 | + while (tlv_buf_left > sizeof(*tlv_rxba)) { | |
| 922 | 922 | tlv_type = le16_to_cpu(tlv_rxba->header.type); |
| 923 | 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 | 932 | if (tlv_type != TLV_TYPE_RXBA_SYNC) { |
| 925 | 933 | mwifiex_dbg(priv->adapter, ERROR, |
| 926 | 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 | 938 | tlv_seq_num = le16_to_cpu(tlv_rxba->seq_num); |
| 931 | 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 | 948 | mwifiex_dbg(priv->adapter, INFO, |
| 933 | 949 | "%pM tid=%d seq_num=%d bitmap_len=%d\n", |
| 934 | 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); | |
| 969 | − tmp = (u8 *)tlv_rxba + tlv_len + sizeof(*tlv_rxba); | |
| 984 | + tlv_buf_left -= (sizeof(tlv_rxba->header) + tlv_len); | |
| 985 | + tmp = (u8 *)tlv_rxba + sizeof(tlv_rxba->header) + tlv_len; | |
| 970 | 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 | 779 | u8 reserved; |
| 780 | 780 | __le16 seq_num; |
| 781 | 781 | __le16 bitmap_len; |
| 782 | − u8 bitmap[1]; | |
| 782 | + u8 bitmap[]; | |
| 783 | 783 | } __packed; |
| 784 | 784 | |
| 785 | 785 | struct chan_band_param_set { |
| @@ -86,7 +86,8 @@ int mwifiex_process_rx_packet(struct mwifiex_private *priv, · 85 unmodified lines | ||
| 86 | 86 | rx_pkt_len = le16_to_cpu(local_rx_pd->rx_pkt_length); |
| 87 | 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 | 91 | mwifiex_dbg(priv->adapter, ERROR, |
| 91 | 92 | "wrong rx packet offset: len=%d, rx_pkt_off=%d\n", |
| 92 | 93 | skb->len, rx_pkt_off); |
| @@ -95,12 +96,13 @@ int mwifiex_process_rx_packet(struct mwifiex_private *priv, · 2 unmodified lines | ||
| 95 | 96 | return -1; |
| 96 | 97 | } |
| 97 | 98 | |
| 98 | − if ((!memcmp(&rx_pkt_hdr->rfc1042_hdr, bridge_tunnel_header, | |
| 99 | − sizeof(bridge_tunnel_header))) || | |
| 100 | − (!memcmp(&rx_pkt_hdr->rfc1042_hdr, rfc1042_header, | |
| 101 | − sizeof(rfc1042_header)) && | |
| 102 | − ntohs(rx_pkt_hdr->rfc1042_hdr.snap_type) != ETH_P_AARP && | |
| 103 | − ntohs(rx_pkt_hdr->rfc1042_hdr.snap_type) != ETH_P_IPX)) { | |
| 99 | + if (sizeof(*rx_pkt_hdr) + rx_pkt_off <= skb->len && | |
| 100 | + ((!memcmp(&rx_pkt_hdr->rfc1042_hdr, bridge_tunnel_header, | |
| 101 | + sizeof(bridge_tunnel_header))) || | |
| 102 | + (!memcmp(&rx_pkt_hdr->rfc1042_hdr, rfc1042_header, | |
| 103 | + sizeof(rfc1042_header)) && | |
| 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 | 107 | * Replace the 803 header and rfc1042 header (llc/snap) with an |
| 106 | 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 | 94 | struct mt76_txwi_cache *t = NULL; |
| 95 | 95 | |
| 96 | − spin_lock(&dev->wed_lock); | |
| 96 | + spin_lock_bh(&dev->wed_lock); | |
| 97 | 97 | if (!list_empty(&dev->rxwi_cache)) { |
| 98 | 98 | t = list_first_entry(&dev->rxwi_cache, struct mt76_txwi_cache, |
| 99 | 99 | list); |
| 100 | 100 | list_del(&t->list); |
| 101 | 101 | } |
| 102 | − spin_unlock(&dev->wed_lock); | |
| 102 | + spin_unlock_bh(&dev->wed_lock); | |
| 103 | 103 | |
| 104 | 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 | 145 | if (!t) |
| 146 | 146 | return; |
| 147 | 147 | |
| 148 | − spin_lock(&dev->wed_lock); | |
| 148 | + spin_lock_bh(&dev->wed_lock); | |
| 149 | 149 | list_add(&t->list, &dev->rxwi_cache); |
| 150 | − spin_unlock(&dev->wed_lock); | |
| 150 | + spin_unlock_bh(&dev->wed_lock); | |
| 151 | 151 | } |
| 152 | 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 | 131 | s8 *lna_2g, s8 *lna_5g, |
| 132 | 132 | struct ieee80211_channel *chan) |
| 133 | 133 | { |
| 134 | − u16 val; | |
| 135 | 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 | 136 | if (chan->band == NL80211_BAND_2GHZ) |
| 144 | 137 | lna = *lna_2g; |
| 145 | 138 | else if (chan->hw_value <= 64) |
| @@ -256,7 +256,8 @@ void mt76x2_read_rx_gain(struct mt76x02_dev *dev) · 255 unmodified lines | ||
| 256 | 256 | struct ieee80211_channel *chan = dev->mphy.chandef.chan; |
| 257 | 257 | int channel = chan->hw_value; |
| 258 | 258 | s8 lna_5g[3], lna_2g; |
| 259 | − u8 lna; | |
| 259 | + bool use_lna; | |
| 260 | + u8 lna = 0; | |
| 260 | 261 | u16 val; |
| 261 | 262 | |
| 262 | 263 | if (chan->band == NL80211_BAND_2GHZ) |
| @@ -275,7 +276,15 @@ void mt76x2_read_rx_gain(struct mt76x02_dev *dev) · 12 unmodified lines | ||
| 275 | 276 | dev->cal.rx.mcu_gain |= (lna_5g[1] & 0xff) << 16; |
| 276 | 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 | 288 | dev->cal.rx.lna_gain = mt76x02_sign_extend(lna, 8); |
| 280 | 289 | } |
| 281 | 290 | EXPORT_SYMBOL_GPL(mt76x2_read_rx_gain); |
| @@ -46,6 +46,7 @@ struct rtw8723du_efuse { · 45 unmodified lines | ||
| 46 | 46 | u8 vender_id[2]; /* 0x100 */ |
| 47 | 47 | u8 product_id[2]; /* 0x102 */ |
| 48 | 48 | u8 usb_option; /* 0x104 */ |
| 49 | + u8 res5[2]; /* 0x105 */ | |
| 49 | 50 | u8 mac_addr[ETH_ALEN]; /* 0x107 */ |
| 50 | 51 | }; |
| 51 | 52 | |
| @@ -41,8 +41,6 @@ · 40 unmodified lines | ||
| 41 | 41 | #include <asm/xen/hypercall.h> |
| 42 | 42 | #include <xen/balloon.h> |
| 43 | 43 | |
| 44 | −#define XENVIF_QUEUE_LENGTH 32 | |
| 45 | − | |
| 46 | 44 | /* Number of bytes allowed on the internal guest Rx queue. */ |
| 47 | 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 | 528 | dev->features = dev->hw_features | NETIF_F_RXCSUM; |
| 531 | 529 | dev->ethtool_ops = &xenvif_ethtool_ops; |
| 532 | 530 | |
| 533 | − dev->tx_queue_len = XENVIF_QUEUE_LENGTH; | |
| 534 | − | |
| 535 | 531 | dev->min_mtu = ETH_MIN_MTU; |
| 536 | 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 | 891 | struct of_changeset_entry *ce; |
| 892 | 892 | |
| 893 | + if (WARN_ON(action >= ARRAY_SIZE(action_names))) | |
| 894 | + return -EINVAL; | |
| 895 | + | |
| 893 | 896 | ce = kzalloc(sizeof(*ce), GFP_KERNEL); |
| 894 | 897 | if (!ce) |
| 895 | 898 | return -ENOMEM; |
| 896 | 899 | |
| 897 | − if (WARN_ON(action >= ARRAY_SIZE(action_names))) | |
| 898 | − return -EINVAL; | |
| 899 | − | |
| 900 | 900 | /* get a reference to the node */ |
| 901 | 901 | ce->action = action; |
| 902 | 902 | ce->np = of_node_get(np); |
| @@ -45,8 +45,8 @@ struct target { · 44 unmodified lines | ||
| 45 | 45 | |
| 46 | 46 | /** |
| 47 | 47 | * struct fragment - info about fragment nodes in overlay expanded device tree |
| 48 | − * @target: target of the overlay operation | |
| 49 | 48 | * @overlay: pointer to the __overlay__ node |
| 49 | + * @target: target of the overlay operation | |
| 50 | 50 | */ |
| 51 | 51 | struct fragment { |
| 52 | 52 | struct device_node *overlay; |
| @@ -43,7 +43,6 @@ · 42 unmodified lines | ||
| 43 | 43 | #define PARF_PHY_REFCLK 0x4c |
| 44 | 44 | #define PARF_CONFIG_BITS 0x50 |
| 45 | 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 | 46 | #define PARF_MHI_CLOCK_RESET_CTRL 0x174 |
| 48 | 47 | #define PARF_AXI_MSTR_WR_ADDR_HALT 0x178 |
| 49 | 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 | 796 | u16 offset = dw_pcie_find_capability(pci, PCI_CAP_ID_EXP); |
| 798 | 797 | u32 val; |
| 799 | 798 | |
| 800 | − writel(SLV_ADDR_SPACE_SZ, | |
| 801 | − pcie->parf + PARF_SLV_ADDR_SPACE_SIZE_2_3_3); | |
| 799 | + writel(SLV_ADDR_SPACE_SZ, pcie->parf + PARF_SLV_ADDR_SPACE_SIZE); | |
| 802 | 800 | |
| 803 | 801 | val = readl(pcie->parf + PARF_PHY_CTRL); |
| 804 | 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 | 658 | cset = kmalloc(sizeof(*cset), GFP_KERNEL); |
| 659 | 659 | if (!cset) |
| 660 | − goto failed; | |
| 660 | + goto out_free_name; | |
| 661 | 661 | of_changeset_init(cset); |
| 662 | 662 | |
| 663 | 663 | np = of_changeset_create_node(cset, ppnode, name); |
| 664 | 664 | if (!np) |
| 665 | − goto failed; | |
| 666 | − np->data = cset; | |
| 665 | + goto out_destroy_cset; | |
| 667 | 666 | |
| 668 | 667 | ret = of_pci_add_properties(pdev, cset, np); |
| 669 | 668 | if (ret) |
| 670 | − goto failed; | |
| 669 | + goto out_free_node; | |
| 671 | 670 | |
| 672 | 671 | ret = of_changeset_apply(cset); |
| 673 | 672 | if (ret) |
| 674 | − goto failed; | |
| 673 | + goto out_free_node; | |
| 675 | 674 | |
| 675 | + np->data = cset; | |
| 676 | 676 | pdev->dev.of_node = np; |
| 677 | 677 | kfree(name); |
| 678 | 678 | |
| 679 | 679 | return; |
| 680 | 680 | |
| 681 | −failed: | |
| 682 | − if (np) | |
| 683 | − of_node_put(np); | |
| 681 | +out_free_node: | |
| 682 | + of_node_put(np); | |
| 683 | +out_destroy_cset: | |
| 684 | + of_changeset_destroy(cset); | |
| 685 | + kfree(cset); | |
| 686 | +out_free_name: | |
| 684 | 687 | kfree(name); |
| 685 | 688 | } |
| 686 | 689 | #endif |
| @@ -186,8 +186,8 @@ static int of_pci_prop_interrupts(struct pci_dev *pdev, · 185 unmodified lines | ||
| 186 | 186 | static int of_pci_prop_intr_map(struct pci_dev *pdev, struct of_changeset *ocs, |
| 187 | 187 | struct device_node *np) |
| 188 | 188 | { |
| 189 | + u32 i, addr_sz[OF_PCI_MAX_INT_PIN] = { 0 }, map_sz = 0; | |
| 189 | 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 | 191 | __be32 laddr[OF_PCI_ADDRESS_CELLS] = { 0 }; |
| 192 | 192 | u32 int_map_mask[] = { 0xffff00, 0, 0, 7 }; |
| 193 | 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 | 213 | out_irq[i].args[0] = pin; |
| 214 | 214 | ret = of_irq_parse_raw(laddr, &out_irq[i]); |
| 215 | 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 | 218 | continue; |
| 218 | 219 | } |
| 219 | − ret = of_property_read_u32(out_irq[i].np, "#address-cells", | |
| 220 | − &addr_sz[i]); | |
| 221 | − if (ret) | |
| 222 | − addr_sz[i] = 0; | |
| 220 | + of_property_read_u32(out_irq[i].np, "#address-cells", | |
| 221 | + &addr_sz[i]); | |
| 223 | 222 | } |
| 224 | 223 | |
| 225 | 224 | list_for_each_entry(child, &pdev->subordinate->devices, bus_list) { |
| 226 | 225 | for (pin = 1; pin <= OF_PCI_MAX_INT_PIN; pin++) { |
| 227 | 226 | i = pci_swizzle_interrupt_pin(child, pin) - 1; |
| 227 | + if (!out_irq[i].np) | |
| 228 | + continue; | |
| 228 | 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 | 240 | int_map = kcalloc(map_sz, sizeof(u32), GFP_KERNEL); |
| 233 | 241 | mapp = int_map; |
| 234 | 242 | |
| 235 | 243 | list_for_each_entry(child, &pdev->subordinate->devices, bus_list) { |
| 236 | 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 | 249 | *mapp = (child->bus->number << 16) | |
| 238 | 250 | (child->devfn << 8); |
| 239 | 251 | mapp += OF_PCI_ADDRESS_CELLS; |
| 240 | 252 | *mapp = pin; |
| 241 | 253 | mapp++; |
| 242 | − i = pci_swizzle_interrupt_pin(child, pin) - 1; | |
| 243 | 254 | *mapp = out_irq[i].np->phandle; |
| 244 | 255 | mapp++; |
| 245 | 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 | 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 | 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 | 1972 | u64 delta; |
| 1973 | 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 | 1976 | if (status & (1U << i)) { |
| 1977 | 1977 | ret = IRQ_HANDLED; |
| 1978 | 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 | 23 | return ((event->attr.type == PERF_TYPE_HARDWARE) || |
| 24 | 24 | (event->attr.type == PERF_TYPE_HW_CACHE) || |
| 25 | 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 | 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 | 511 | struct perf_event *event = (struct perf_event *)arg; |
| 512 | 512 | |
| 513 | − csr_write(CSR_SCOUNTEREN, | |
| 514 | − csr_read(CSR_SCOUNTEREN) | (1 << pmu_sbi_csr_index(event))); | |
| 513 | + if (event->hw.idx != -1) | |
| 514 | + csr_write(CSR_SCOUNTEREN, | |
| 515 | + csr_read(CSR_SCOUNTEREN) | (1 << pmu_sbi_csr_index(event))); | |
| 515 | 516 | } |
| 516 | 517 | |
| 517 | 518 | static void pmu_sbi_reset_scounteren(void *arg) |
| 518 | 519 | { |
| 519 | 520 | struct perf_event *event = (struct perf_event *)arg; |
| 520 | 521 | |
| 521 | − csr_write(CSR_SCOUNTEREN, | |
| 522 | − csr_read(CSR_SCOUNTEREN) & ~(1 << pmu_sbi_csr_index(event))); | |
| 522 | + if (event->hw.idx != -1) | |
| 523 | + csr_write(CSR_SCOUNTEREN, | |
| 524 | + csr_read(CSR_SCOUNTEREN) & ~(1 << pmu_sbi_csr_index(event))); | |
| 523 | 525 | } |
| 524 | 526 | |
| 525 | 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 | 544 | if ((hwc->flags & PERF_EVENT_FLAG_USER_ACCESS) && |
| 543 | 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 | 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 | 555 | if ((hwc->flags & PERF_EVENT_FLAG_USER_ACCESS) && |
| 553 | 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 | 560 | ret = sbi_ecall(SBI_EXT_PMU, SBI_EXT_PMU_COUNTER_STOP, hwc->idx, 1, flag, 0, 0, 0); |
| 557 | 561 | if (ret.error && (ret.error != SBI_ERR_ALREADY_STOPPED) && |
| @@ -127,6 +127,10 @@ struct lynx_28g_lane { · 126 unmodified lines | ||
| 127 | 127 | struct lynx_28g_priv { |
| 128 | 128 | void __iomem *base; |
| 129 | 129 | struct device *dev; |
| 130 | + /* Serialize concurrent access to registers shared between lanes, | |
| 131 | + * like PCCn | |
| 132 | + */ | |
| 133 | + spinlock_t pcc_lock; | |
| 130 | 134 | struct lynx_28g_pll pll[LYNX_28G_NUM_PLL]; |
| 131 | 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 | 401 | if (powered_up) |
| 398 | 402 | lynx_28g_power_off(phy); |
| 399 | 403 | |
| 404 | + spin_lock(&priv->pcc_lock); | |
| 405 | + | |
| 400 | 406 | switch (submode) { |
| 401 | 407 | case PHY_INTERFACE_MODE_SGMII: |
| 402 | 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 | 419 | lane->interface = submode; |
| 414 | 420 | |
| 415 | 421 | out: |
| 422 | + spin_unlock(&priv->pcc_lock); | |
| 423 | + | |
| 416 | 424 | /* Power up the lane if necessary */ |
| 417 | 425 | if (powered_up) |
| 418 | 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 | 516 | for (i = 0; i < LYNX_28G_NUM_LANE; i++) { |
| 509 | 517 | lane = &priv->lane[i]; |
| 510 | 518 | |
| 511 | − if (!lane->init) | |
| 512 | − continue; | |
| 519 | + mutex_lock(&lane->phy->mutex); | |
| 513 | 520 | |
| 514 | − if (!lane->powered_up) | |
| 521 | + if (!lane->init || !lane->powered_up) { | |
| 522 | + mutex_unlock(&lane->phy->mutex); | |
| 515 | 523 | continue; |
| 524 | + } | |
| 516 | 525 | |
| 517 | 526 | rrstctl = lynx_28g_lane_read(lane, LNaRRSTCTL); |
| 518 | 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 | 530 | rrstctl = lynx_28g_lane_read(lane, LNaRRSTCTL); |
| 522 | 531 | } while (!(rrstctl & LYNX_28G_LNaRRSTCTL_RST_DONE)); |
| 523 | 532 | } |
| 533 | + | |
| 534 | + mutex_unlock(&lane->phy->mutex); | |
| 524 | 535 | } |
| 525 | 536 | queue_delayed_work(system_power_efficient_wq, &priv->cdr_check, |
| 526 | 537 | msecs_to_jiffies(1000)); |
| @@ -593,6 +604,7 @@ static int lynx_28g_probe(struct platform_device *pdev) · 66 unmodified lines | ||
| 593 | 604 | |
| 594 | 605 | dev_set_drvdata(dev, priv); |
| 595 | 606 | |
| 607 | + spin_lock_init(&priv->pcc_lock); | |
| 596 | 608 | INIT_DELAYED_WORK(&priv->cdr_check, lynx_28g_cdr_lock_check); |
| 597 | 609 | |
| 598 | 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 | 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 | 627 | static const struct of_device_id lynx_28g_of_match_table[] = { |
| 608 | 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 | 633 | static struct platform_driver lynx_28g_driver = { |
| 614 | 634 | .probe = lynx_28g_probe, |
| 635 | + .remove_new = lynx_28g_remove, | |
| 615 | 636 | .driver = { |
| 616 | 637 | .name = "lynx-28g", |
| 617 | 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 | 1023 | static struct pinctrl *find_pinctrl(struct device *dev) |
| 1024 | 1024 | { |
| 1025 | − struct pinctrl *p; | |
| 1025 | + struct pinctrl *entry, *p = NULL; | |
| 1026 | 1026 | |
| 1027 | 1027 | mutex_lock(&pinctrl_list_mutex); |
| 1028 | − list_for_each_entry(p, &pinctrl_list, node) | |
| 1029 | − if (p->dev == dev) { | |
| 1030 | − mutex_unlock(&pinctrl_list_mutex); | |
| 1031 | − return p; | |
| 1028 | + | |
| 1029 | + list_for_each_entry(entry, &pinctrl_list, node) { | |
| 1030 | + if (entry->dev == dev) { | |
| 1031 | + p = entry; | |
| 1032 | + kref_get(&p->users); | |
| 1033 | + break; | |
| 1032 | 1034 | } |
| 1035 | + } | |
| 1033 | 1036 | |
| 1034 | 1037 | mutex_unlock(&pinctrl_list_mutex); |
| 1035 | − return NULL; | |
| 1038 | + return p; | |
| 1036 | 1039 | } |
| 1037 | 1040 | |
| 1038 | 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 | 1143 | p = find_pinctrl(dev); |
| 1141 | 1144 | if (p) { |
| 1142 | 1145 | dev_dbg(dev, "obtain a copy of previously claimed pinctrl\n"); |
| 1143 | − kref_get(&p->users); | |
| 1144 | 1146 | return p; |
| 1145 | 1147 | } |
| 1146 | 1148 | |
| @@ -1062,13 +1062,13 @@ static int wpcm450_gpio_register(struct platform_device *pdev, · 1061 unmodified lines | ||
| 1062 | 1062 | if (ret < 0) |
| 1063 | 1063 | return ret; |
| 1064 | 1064 | |
| 1065 | − gpio = &pctrl->gpio_bank[reg]; | |
| 1066 | − gpio->pctrl = pctrl; | |
| 1067 | − | |
| 1068 | 1065 | if (reg >= WPCM450_NUM_BANKS) |
| 1069 | 1066 | return dev_err_probe(dev, -EINVAL, |
| 1070 | 1067 | "GPIO index %d out of range!\n", reg); |
| 1071 | 1068 | |
| 1069 | + gpio = &pctrl->gpio_bank[reg]; | |
| 1070 | + gpio->pctrl = pctrl; | |
| 1071 | + | |
| 1072 | 1072 | bank = &wpcm450_banks[reg]; |
| 1073 | 1073 | gpio->bank = bank; |
| 1074 | 1074 | |
| @@ -198,5 +198,4 @@ enum ltq_pin { · 197 unmodified lines | ||
| 198 | 198 | |
| 199 | 199 | extern int ltq_pinctrl_register(struct platform_device *pdev, |
| 200 | 200 | struct ltq_pinmux_info *info); |
| 201 | −extern int ltq_pinctrl_unregister(struct platform_device *pdev); | |
| 202 | 201 | #endif /* __PINCTRL_LANTIQ_H */ |
| @@ -235,6 +235,7 @@ config PINCTRL_RZN1 · 234 unmodified lines | ||
| 235 | 235 | depends on OF |
| 236 | 236 | depends on ARCH_RZN1 || COMPILE_TEST |
| 237 | 237 | select GENERIC_PINCONF |
| 238 | + select PINMUX | |
| 238 | 239 | help |
| 239 | 240 | This selects pinctrl driver for Renesas RZ/N1 devices. |
| 240 | 241 | |
| @@ -31,6 +31,8 @@ · 30 unmodified lines | ||
| 31 | 31 | #define JH7110_AON_NGPIO 4 |
| 32 | 32 | #define JH7110_AON_GC_BASE 64 |
| 33 | 33 | |
| 34 | +#define JH7110_AON_REGS_NUM 37 | |
| 35 | + | |
| 34 | 36 | /* registers */ |
| 35 | 37 | #define JH7110_AON_DOEN 0x0 |
| 36 | 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 | 147 | .gpi_mask = GENMASK(3, 0), |
| 146 | 148 | .gpioin_reg_base = JH7110_AON_GPIOIN, |
| 147 | 149 | .irq_reg = &jh7110_aon_irq_reg, |
| 150 | + .nsaved_regs = JH7110_AON_REGS_NUM, | |
| 148 | 151 | .jh7110_set_one_pin_mux = jh7110_aon_set_one_pin_mux, |
| 149 | 152 | .jh7110_get_padcfg_base = jh7110_aon_get_padcfg_base, |
| 150 | 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 | 168 | .driver = { |
| 166 | 169 | .name = "starfive-jh7110-aon-pinctrl", |
| 167 | 170 | .of_match_table = jh7110_aon_pinctrl_of_match, |
| 171 | + .pm = pm_sleep_ptr(&jh7110_pinctrl_pm_ops), | |
| 168 | 172 | }, |
| 169 | 173 | }; |
| 170 | 174 | module_platform_driver(jh7110_aon_pinctrl_driver); |
| @@ -31,6 +31,8 @@ · 30 unmodified lines | ||
| 31 | 31 | #define JH7110_SYS_NGPIO 64 |
| 32 | 32 | #define JH7110_SYS_GC_BASE 0 |
| 33 | 33 | |
| 34 | +#define JH7110_SYS_REGS_NUM 174 | |
| 35 | + | |
| 34 | 36 | /* registers */ |
| 35 | 37 | #define JH7110_SYS_DOEN 0x000 |
| 36 | 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 | 419 | .gpi_mask = GENMASK(6, 0), |
| 418 | 420 | .gpioin_reg_base = JH7110_SYS_GPIOIN, |
| 419 | 421 | .irq_reg = &jh7110_sys_irq_reg, |
| 422 | + .nsaved_regs = JH7110_SYS_REGS_NUM, | |
| 420 | 423 | .jh7110_set_one_pin_mux = jh7110_sys_set_one_pin_mux, |
| 421 | 424 | .jh7110_get_padcfg_base = jh7110_sys_get_padcfg_base, |
| 422 | 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 | 440 | .driver = { |
| 438 | 441 | .name = "starfive-jh7110-sys-pinctrl", |
| 439 | 442 | .of_match_table = jh7110_sys_pinctrl_of_match, |
| 443 | + .pm = pm_sleep_ptr(&jh7110_pinctrl_pm_ops), | |
| 440 | 444 | }, |
| 441 | 445 | }; |
| 442 | 446 | module_platform_driver(jh7110_sys_pinctrl_driver); |
| @@ -872,6 +872,13 @@ int jh7110_pinctrl_probe(struct platform_device *pdev) · 871 unmodified lines | ||
| 872 | 872 | if (!sfp) |
| 873 | 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 | 882 | sfp->base = devm_platform_ioremap_resource(pdev, 0); |
| 876 | 883 | if (IS_ERR(sfp->base)) |
| 877 | 884 | return PTR_ERR(sfp->base); |
| @@ -967,14 +974,45 @@ int jh7110_pinctrl_probe(struct platform_device *pdev) · 89 unmodified lines | ||
| 967 | 974 | if (ret) |
| 968 | 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 | 977 | dev_info(dev, "StarFive GPIO chip registered %d GPIOs\n", sfp->gc.ngpio); |
| 973 | 978 | |
| 974 | 979 | return pinctrl_enable(sfp->pctl); |
| 975 | 980 | } |
| 976 | 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 | 1016 | MODULE_DESCRIPTION("Pinctrl driver for the StarFive JH7110 SoC"); |
| 979 | 1017 | MODULE_AUTHOR("Emil Renner Berthing <kernel@esmil.dk>"); |
| 980 | 1018 | MODULE_AUTHOR("Jianlong Huang <jianlong.huang@starfivetech.com>"); |
| @@ -21,6 +21,7 @@ struct jh7110_pinctrl { · 20 unmodified lines | ||
| 21 | 21 | /* register read/write mutex */ |
| 22 | 22 | struct mutex mutex; |
| 23 | 23 | const struct jh7110_pinctrl_soc_info *info; |
| 24 | + u32 *saved_regs; | |
| 24 | 25 | }; |
| 25 | 26 | |
| 26 | 27 | struct jh7110_gpio_irq_reg { |
| @@ -50,6 +51,8 @@ struct jh7110_pinctrl_soc_info { · 23 unmodified lines | ||
| 50 | 51 | |
| 51 | 52 | const struct jh7110_gpio_irq_reg *irq_reg; |
| 52 | 53 | |
| 54 | + unsigned int nsaved_regs; | |
| 55 | + | |
| 53 | 56 | /* generic pinmux */ |
| 54 | 57 | int (*jh7110_set_one_pin_mux)(struct jh7110_pinctrl *sfp, |
| 55 | 58 | unsigned int pin, |
| @@ -66,5 +69,6 @@ void jh7110_set_gpiomux(struct jh7110_pinctrl *sfp, unsigned int pin, · 10 unmodified lines | ||
| 66 | 69 | unsigned int din, u32 dout, u32 doen); |
| 67 | 70 | int jh7110_pinctrl_probe(struct platform_device *pdev); |
| 68 | 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 | 74 | #endif /* __PINCTRL_STARFIVE_JH7110_H__ */ |
| @@ -96,7 +96,6 @@ static const struct cfg_param { · 95 unmodified lines | ||
| 96 | 96 | {"nvidia,slew-rate-falling", TEGRA_PINCONF_PARAM_SLEW_RATE_FALLING}, |
| 97 | 97 | {"nvidia,slew-rate-rising", TEGRA_PINCONF_PARAM_SLEW_RATE_RISING}, |
| 98 | 98 | {"nvidia,drive-type", TEGRA_PINCONF_PARAM_DRIVE_TYPE}, |
| 99 | − {"nvidia,function", TEGRA_PINCONF_PARAM_FUNCTION}, | |
| 100 | 99 | }; |
| 101 | 100 | |
| 102 | 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 | 470 | *bit = g->drvtype_bit; |
| 472 | 471 | *width = 2; |
| 473 | 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 | 473 | default: |
| 481 | 474 | dev_err(pmx->dev, "Invalid config param %04x\n", param); |
| 482 | 475 | return -ENOTSUPP; |
| @@ -640,16 +633,8 @@ static void tegra_pinconf_group_dbg_show(struct pinctrl_dev *pctldev, · 157 unmodified lines | ||
| 640 | 633 | val >>= bit; |
| 641 | 634 | val &= (1 << width) - 1; |
| 642 | 635 | |
| 643 | − if (cfg_params[i].param == TEGRA_PINCONF_PARAM_FUNCTION) { | |
| 644 | − u8 idx = pmx->soc->groups[group].funcs[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 | − } | |
| 636 | + seq_printf(s, "\n\t%s=%u", | |
| 637 | + strip_prefix(cfg_params[i].property), val); | |
| 653 | 638 | } |
| 654 | 639 | } |
| 655 | 640 | |
| @@ -54,8 +54,6 @@ enum tegra_pinconf_param { · 53 unmodified lines | ||
| 54 | 54 | TEGRA_PINCONF_PARAM_SLEW_RATE_RISING, |
| 55 | 55 | /* argument: Integer, range is HW-dependant */ |
| 56 | 56 | TEGRA_PINCONF_PARAM_DRIVE_TYPE, |
| 57 | − /* argument: pinmux settings */ | |
| 58 | − TEGRA_PINCONF_PARAM_FUNCTION, | |
| 59 | 57 | }; |
| 60 | 58 | |
| 61 | 59 | enum tegra_pinconf_pull { |
| @@ -53,7 +53,7 @@ · 52 unmodified lines | ||
| 53 | 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 | 57 | * @va: virtual address of the ring |
| 58 | 58 | * @dma: dma address of the ring |
| 59 | 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 | 117 | * @vdev: virtio device, in which the vdev.id.device field has the |
| 118 | 118 | * VIRTIO_ID_xxx id to distinguish the virtual device. |
| 119 | 119 | * @status: status of the device |
| 120 | 120 | * @features: supported features of the device |
| 121 | 121 | * @vrings: array of tmfifo vrings of this device |
| 122 | + * @config: non-anonymous union for cons and net | |
| 122 | 123 | * @config.cons: virtual console config - |
| 123 | 124 | * select if vdev.id.device is VIRTIO_ID_CONSOLE |
| 124 | 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 | 143 | * @fifo: pointer to the tmfifo structure |
| 143 | 144 | * @irq: interrupt number |
| 144 | 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 | 155 | * @ctl: control register offset (TMFIFO_RX_CTL / TMFIFO_TX_CTL) |
| 155 | 156 | * @sts: status register offset (TMFIFO_RX_STS / TMFIFO_TX_STS) |
| 156 | 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 | 167 | * @vdev: array of the virtual devices running over the TmFifo |
| 167 | 168 | * @lock: lock to protect the TmFifo access |
| 168 | 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 | 203 | * @type: message type |
| 203 | 204 | * @len: payload length in network byte order. Messages sent into the FIFO |
| 204 | 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 | 209 | struct mlxbf_tmfifo_msg_hdr { |
| 209 | 210 | u8 type; |
| 210 | 211 | __be16 len; |
| 212 | + /* private: */ | |
| 211 | 213 | u8 unused[5]; |
| 212 | 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 | 659 | const char *guid, int min_elements, |
| 660 | 660 | int instance_id) |
| 661 | 661 | { |
| 662 | − struct kobject *attr_name_kobj; | |
| 662 | + struct kobject *attr_name_kobj, *duplicate; | |
| 663 | 663 | union acpi_object *elements; |
| 664 | 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 | 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 | 709 | pr_debug("Duplicate attribute name found - %s\n", str_value); |
| 710 | + /* kset_find_obj() returns a reference */ | |
| 711 | + kobject_put(duplicate); | |
| 709 | 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 | 771 | const char *guid, int min_elements, |
| 769 | 772 | int instance_id) |
| 770 | 773 | { |
| 771 | − struct kobject *attr_name_kobj; | |
| 774 | + struct kobject *attr_name_kobj, *duplicate; | |
| 772 | 775 | struct kset *temp_kset; |
| 773 | 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 | 797 | temp_kset = bioscfg_drv.main_dir_kset; |
| 795 | 798 | |
| 796 | 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 | 802 | pr_debug("Duplicate attribute name found - %s\n", str); |
| 803 | + /* kset_find_obj() returns a reference */ | |
| 804 | + kobject_put(duplicate); | |
| 799 | 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 | 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 | 1558 | .driver = { |
| 1553 | 1559 | .name = "hp-wmi", |
| 1554 | 1560 | .pm = &hp_wmi_pm_ops, |
| @@ -331,14 +331,15 @@ int do_core_test(int cpu, struct device *dev) · 330 unmodified lines | ||
| 331 | 331 | switch (test->test_num) { |
| 332 | 332 | case IFS_TYPE_SAF: |
| 333 | 333 | if (!ifsd->loaded) |
| 334 | − return -EPERM; | |
| 335 | − ifs_test_core(cpu, dev); | |
| 334 | + ret = -EPERM; | |
| 335 | + else | |
| 336 | + ifs_test_core(cpu, dev); | |
| 336 | 337 | break; |
| 337 | 338 | case IFS_TYPE_ARRAY_BIST: |
| 338 | 339 | ifs_array_test_core(cpu, dev); |
| 339 | 340 | break; |
| 340 | 341 | default: |
| 341 | − return -EINVAL; | |
| 342 | + ret = -EINVAL; | |
| 342 | 343 | } |
| 343 | 344 | out: |
| 344 | 345 | cpus_read_unlock(); |
| @@ -1248,6 +1248,24 @@ static void tlmi_release_attr(void) · 1247 unmodified lines | ||
| 1248 | 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 | 1269 | static int tlmi_sysfs_init(void) |
| 1252 | 1270 | { |
| 1253 | 1271 | int i, ret; |
| @@ -1276,10 +1294,8 @@ static int tlmi_sysfs_init(void) · 22 unmodified lines | ||
| 1276 | 1294 | continue; |
| 1277 | 1295 | |
| 1278 | 1296 | /* check for duplicate or reserved values */ |
| 1279 | − if (kset_find_obj(tlmi_priv.attribute_kset, tlmi_priv.setting[i]->display_name) || | |
| 1280 | − !strcmp(tlmi_priv.setting[i]->display_name, "Reserved")) { | |
| 1281 | − pr_debug("duplicate or reserved attribute name found - %s\n", | |
| 1282 | − tlmi_priv.setting[i]->display_name); | |
| 1297 | + if (tlmi_validate_setting_name(tlmi_priv.attribute_kset, | |
| 1298 | + tlmi_priv.setting[i]->display_name) < 0) { | |
| 1283 | 1299 | kfree(tlmi_priv.setting[i]->possible_values); |
| 1284 | 1300 | kfree(tlmi_priv.setting[i]); |
| 1285 | 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 | 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 | 60 | static const struct property_entry chuwi_hi8_props[] = { |
| 46 | 61 | PROPERTY_ENTRY_U32("touchscreen-size-x", 1665), |
| 47 | 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 | 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 | 789 | static const struct property_entry pov_mobii_wintab_p800w_v20_props[] = { |
| 760 | 790 | PROPERTY_ENTRY_U32("touchscreen-min-x", 32), |
| 761 | 791 | PROPERTY_ENTRY_U32("touchscreen-min-y", 16), |
| @@ -1070,6 +1100,13 @@ const struct dmi_system_id touchscreen_dmi_table[] = { · 308 unmodified lines | ||
| 1070 | 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 | 1111 | /* Chuwi Hi8 */ |
| 1075 | 1112 | .driver_data = (void *)&chuwi_hi8_data, |
| @@ -1480,6 +1517,14 @@ const struct dmi_system_id touchscreen_dmi_table[] = { · 404 unmodified lines | ||
| 1480 | 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 | 1529 | /* Point of View mobii wintab p800w (v2.0) */ |
| 1485 | 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 | 150 | { "mclk-out-1", IMX_SC_R_MCLK_OUT_1, 1, false, 0 }, |
| 151 | 151 | { "dma0-ch", IMX_SC_R_DMA_0_CH0, 32, true, 0 }, |
| 152 | 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 | 155 | { "dma3-ch", IMX_SC_R_DMA_3_CH0, 32, true, 0 }, |
| 155 | 156 | { "asrc0", IMX_SC_R_ASRC_0, 1, false, 0 }, |
| 156 | 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 | 106 | struct qcom_battmgr_update_request { |
| 107 | 107 | struct pmic_glink_hdr hdr; |
| 108 | − u32 battery_id; | |
| 108 | + __le32 battery_id; | |
| 109 | 109 | }; |
| 110 | 110 | |
| 111 | 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 | 1283 | struct qcom_battmgr *battmgr = container_of(work, struct qcom_battmgr, enable_work); |
| 1284 | 1284 | struct qcom_battmgr_enable_request req = { |
| 1285 | − .hdr.owner = PMIC_GLINK_OWNER_BATTMGR, | |
| 1286 | − .hdr.type = PMIC_GLINK_NOTIFY, | |
| 1287 | − .hdr.opcode = BATTMGR_REQUEST_NOTIFICATION, | |
| 1285 | + .hdr.owner = cpu_to_le32(PMIC_GLINK_OWNER_BATTMGR), | |
| 1286 | + .hdr.type = cpu_to_le32(PMIC_GLINK_NOTIFY), | |
| 1287 | + .hdr.opcode = cpu_to_le32(BATTMGR_REQUEST_NOTIFICATION), | |
| 1288 | 1288 | }; |
| 1289 | 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 | 3998 | return 0; |
| 3999 | 3999 | |
| 4000 | 4000 | out: |
| 4001 | − ptp_ocp_dev_release(&bp->dev); | |
| 4002 | 4001 | put_device(&bp->dev); |
| 4003 | 4002 | return err; |
| 4004 | 4003 | } |
| @@ -5542,6 +5542,8 @@ regulator_register(struct device *dev, · 5541 unmodified lines | ||
| 5542 | 5542 | goto rinse; |
| 5543 | 5543 | } |
| 5544 | 5544 | device_initialize(&rdev->dev); |
| 5545 | + dev_set_drvdata(&rdev->dev, rdev); | |
| 5546 | + rdev->dev.class = ®ulator_class; | |
| 5545 | 5547 | spin_lock_init(&rdev->err_lock); |
| 5546 | 5548 | |
| 5547 | 5549 | /* |
| @@ -5603,11 +5605,9 @@ regulator_register(struct device *dev, · 55 unmodified lines | ||
| 5603 | 5605 | rdev->supply_name = regulator_desc->supply_name; |
| 5604 | 5606 | |
| 5605 | 5607 | /* register with sysfs */ |
| 5606 | − rdev->dev.class = ®ulator_class; | |
| 5607 | 5608 | rdev->dev.parent = config->dev; |
| 5608 | 5609 | dev_set_name(&rdev->dev, "regulator.%lu", |
| 5609 | 5610 | (unsigned long) atomic_inc_return(®ulator_no)); |
| 5610 | − dev_set_drvdata(&rdev->dev, rdev); | |
| 5611 | 5611 | |
| 5612 | 5612 | /* set regulator constraints */ |
| 5613 | 5613 | if (init_data) |
| @@ -5724,15 +5724,11 @@ wash: · 110 unmodified lines | ||
| 5724 | 5724 | mutex_lock(®ulator_list_mutex); |
| 5725 | 5725 | regulator_ena_gpio_free(rdev); |
| 5726 | 5726 | mutex_unlock(®ulator_list_mutex); |
| 5727 | − put_device(&rdev->dev); | |
| 5728 | − rdev = NULL; | |
| 5729 | 5727 | clean: |
| 5730 | 5728 | if (dangling_of_gpiod) |
| 5731 | 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 | 5730 | kfree(config); |
| 5731 | + put_device(&rdev->dev); | |
| 5736 | 5732 | rinse: |
| 5737 | 5733 | if (dangling_cfg_gpiod) |
| 5738 | 5734 | gpiod_put(cfg->ena_gpiod); |
| @@ -43,7 +43,7 @@ struct mt6358_regulator_info { · 42 unmodified lines | ||
| 43 | 43 | .desc = { \ |
| 44 | 44 | .name = #vreg, \ |
| 45 | 45 | .of_match = of_match_ptr(match), \ |
| 46 | − .ops = &mt6358_volt_range_ops, \ | |
| 46 | + .ops = &mt6358_buck_ops, \ | |
| 47 | 47 | .type = REGULATOR_VOLTAGE, \ |
| 48 | 48 | .id = MT6358_ID_##vreg, \ |
| 49 | 49 | .owner = THIS_MODULE, \ |
| @@ -139,7 +139,7 @@ struct mt6358_regulator_info { · 89 unmodified lines | ||
| 139 | 139 | .desc = { \ |
| 140 | 140 | .name = #vreg, \ |
| 141 | 141 | .of_match = of_match_ptr(match), \ |
| 142 | − .ops = &mt6358_volt_range_ops, \ | |
| 142 | + .ops = &mt6358_buck_ops, \ | |
| 143 | 143 | .type = REGULATOR_VOLTAGE, \ |
| 144 | 144 | .id = MT6366_ID_##vreg, \ |
| 145 | 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 | 454 | .list_voltage = regulator_list_voltage_linear, |
| 455 | 455 | .map_voltage = regulator_map_voltage_linear, |
| 456 | 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 | 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 | 479 | static const struct regulator_ops mt6358_volt_table_ops = { |
| 468 | 480 | .list_voltage = regulator_list_voltage_table, |
| 469 | 481 | .map_voltage = regulator_map_voltage_iterate, |
| @@ -102,7 +102,7 @@ config CCWGROUP · 101 unmodified lines | ||
| 102 | 102 | |
| 103 | 103 | config ISM |
| 104 | 104 | tristate "Support for ISM vPCI Adapter" |
| 105 | − depends on PCI && SMC | |
| 105 | + depends on PCI | |
| 106 | 106 | default n |
| 107 | 107 | help |
| 108 | 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 | 518 | if (port) { |
| 519 | 519 | put_device(&port->dev); |
| 520 | 520 | retval = -EEXIST; |
| 521 | − goto err_out; | |
| 521 | + goto err_put; | |
| 522 | 522 | } |
| 523 | 523 | |
| 524 | 524 | port = kzalloc(sizeof(struct zfcp_port), GFP_KERNEL); |
| 525 | 525 | if (!port) |
| 526 | − goto err_out; | |
| 526 | + goto err_put; | |
| 527 | 527 | |
| 528 | 528 | rwlock_init(&port->unit_list_lock); |
| 529 | 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 | 547 | if (dev_set_name(&port->dev, "0x%016llx", (unsigned long long)wwpn)) { |
| 548 | 548 | kfree(port); |
| 549 | − goto err_out; | |
| 549 | + goto err_put; | |
| 550 | 550 | } |
| 551 | 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 | 564 | return port; |
| 565 | 565 | |
| 566 | −err_out: | |
| 566 | +err_put: | |
| 567 | 567 | zfcp_ccw_adapter_put(adapter); |
| 568 | +err_out: | |
| 568 | 569 | return ERR_PTR(retval); |
| 569 | 570 | } |
| @@ -27,7 +27,7 @@ · 26 unmodified lines | ||
| 27 | 27 | |
| 28 | 28 | #define DRV_NAME "fnic" |
| 29 | 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 | 31 | #define PFX DRV_NAME ": " |
| 32 | 32 | #define DFX DRV_NAME "%d: " |
| 33 | 33 | |
| @@ -237,6 +237,8 @@ struct fnic { · 203 unmodified lines | ||
| 237 | 237 | unsigned int cq_count; |
| 238 | 238 | |
| 239 | 239 | struct mutex sgreset_mutex; |
| 240 | + spinlock_t sgreset_lock; /* lock for sgreset */ | |
| 241 | + struct scsi_cmnd *sgreset_sc; | |
| 240 | 242 | struct dentry *fnic_stats_debugfs_host; |
| 241 | 243 | struct dentry *fnic_stats_debugfs_file; |
| 242 | 244 | struct dentry *fnic_reset_debugfs_file; |
| @@ -52,6 +52,8 @@ struct fnic_io_req { · 51 unmodified lines | ||
| 52 | 52 | unsigned long start_time; /* in jiffies */ |
| 53 | 53 | struct completion *abts_done; /* completion for abts */ |
| 54 | 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 | 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 | 754 | for (i = 0; i < FNIC_IO_LOCKS; i++) |
| 755 | 755 | spin_lock_init(&fnic->io_req_lock[i]); |
| 756 | 756 | |
| 757 | + spin_lock_init(&fnic->sgreset_lock); | |
| 758 | + | |
| 757 | 759 | err = -ENOMEM; |
| 758 | 760 | fnic->io_req_pool = mempool_create_slab_pool(2, fnic_io_req_cache); |
| 759 | 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 | 1048 | u8 type; |
| 1049 | 1049 | u8 hdr_status; |
| 1050 | − struct fcpio_tag tag; | |
| 1050 | + struct fcpio_tag ftag; | |
| 1051 | 1051 | u32 id; |
| 1052 | − struct scsi_cmnd *sc; | |
| 1052 | + struct scsi_cmnd *sc = NULL; | |
| 1053 | 1053 | struct fnic_io_req *io_req; |
| 1054 | 1054 | struct fnic_stats *fnic_stats = &fnic->fnic_stats; |
| 1055 | 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 | 1058 | unsigned long flags; |
| 1059 | 1059 | spinlock_t *io_lock; |
| 1060 | 1060 | unsigned long start_time; |
| 1061 | + unsigned int tag; | |
| 1061 | 1062 | |
| 1062 | − fcpio_header_dec(&desc->hdr, &type, &hdr_status, &tag); | |
| 1063 | − fcpio_tag_id_dec(&tag, &id); | |
| 1063 | + fcpio_header_dec(&desc->hdr, &type, &hdr_status, &ftag); | |
| 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 | 1075 | shost_printk(KERN_ERR, fnic->lport->host, |
| 1067 | − "Tag out of range tag %x hdr status = %s\n", | |
| 1068 | − id, fnic_fcpio_status_to_str(hdr_status)); | |
| 1076 | + "Tag out of range tag 0x%x hdr status = %s\n", | |
| 1077 | + tag, fnic_fcpio_status_to_str(hdr_status)); | |
| 1069 | 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 | 1089 | WARN_ON_ONCE(!sc); |
| 1074 | 1090 | if (!sc) { |
| 1075 | 1091 | atomic64_inc(&fnic_stats->io_stats.sc_null); |
| 1076 | 1092 | shost_printk(KERN_ERR, fnic->lport->host, |
| 1077 | 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 | 1095 | return; |
| 1080 | 1096 | } |
| 1081 | − io_lock = fnic_io_lock_hash(fnic, sc); | |
| 1097 | + | |
| 1082 | 1098 | spin_lock_irqsave(io_lock, flags); |
| 1083 | 1099 | io_req = fnic_priv(sc)->io_req; |
| 1084 | 1100 | WARN_ON_ONCE(!io_req); |
| @@ -1089,7 +1105,7 @@ static void fnic_fcpio_itmf_cmpl_handler(struct fnic *fnic, · 4 unmodified lines | ||
| 1089 | 1105 | shost_printk(KERN_ERR, fnic->lport->host, |
| 1090 | 1106 | "itmf_cmpl io_req is null - " |
| 1091 | 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 | 1109 | return; |
| 1094 | 1110 | } |
| 1095 | 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 | 1954 | struct scsi_lun fc_lun; |
| 1939 | 1955 | int ret = 0; |
| 1940 | 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 | 1962 | spin_lock_irqsave(host->host_lock, intr_flags); |
| 1943 | 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 | 1984 | /* fill in the lun info */ |
| 1965 | 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 | 1989 | 0, FCPIO_ITMF_LUN_RESET, SCSI_NO_TAG, |
| 1969 | 1990 | fc_lun.scsi_lun, io_req->port_id, |
| 1970 | 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 | 2167 | .ret = SUCCESS, |
| 2147 | 2168 | }; |
| 2148 | 2169 | |
| 2149 | − if (new_sc) | |
| 2150 | − iter_data.lr_sc = lr_sc; | |
| 2170 | + iter_data.lr_sc = lr_sc; | |
| 2151 | 2171 | |
| 2152 | 2172 | scsi_host_busy_iter(fnic->lport->host, |
| 2153 | 2173 | fnic_pending_aborts_iter, &iter_data); |
| @@ -2230,8 +2250,14 @@ int fnic_device_reset(struct scsi_cmnd *sc) · 76 unmodified lines | ||
| 2230 | 2250 | mutex_lock(&fnic->sgreset_mutex); |
| 2231 | 2251 | tag = fnic->fnic_max_tag_id; |
| 2232 | 2252 | new_sc = 1; |
| 2233 | − } | |
| 2234 | − io_lock = fnic_io_lock_hash(fnic, sc); | |
| 2253 | + fnic->sgreset_sc = 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 | 2261 | spin_lock_irqsave(io_lock, flags); |
| 2236 | 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 | 2274 | memset(io_req, 0, sizeof(*io_req)); |
| 2249 | 2275 | io_req->port_id = rport->port_id; |
| 2276 | + io_req->tag = tag; | |
| 2277 | + io_req->sc = sc; | |
| 2250 | 2278 | fnic_priv(sc)->io_req = io_req; |
| 2251 | 2279 | } |
| 2252 | 2280 | io_req->dr_done = &tm_done; |
| @@ -2400,8 +2428,10 @@ fnic_device_reset_end: · 147 unmodified lines | ||
| 2400 | 2428 | (u64)sc->cmnd[4] << 8 | sc->cmnd[5]), |
| 2401 | 2429 | fnic_flags_and_state(sc)); |
| 2402 | 2430 | |
| 2403 | − if (new_sc) | |
| 2431 | + if (new_sc) { | |
| 2432 | + fnic->sgreset_sc = NULL; | |
| 2404 | 2433 | mutex_unlock(&fnic->sgreset_mutex); |
| 2434 | + } | |
| 2405 | 2435 | |
| 2406 | 2436 | FNIC_SCSI_DBG(KERN_DEBUG, fnic->lport->host, |
| 2407 | 2437 | "Returning from device reset %s\n", |
| @@ -1627,12 +1627,13 @@ int scsi_rescan_device(struct scsi_device *sdev) · 1626 unmodified lines | ||
| 1627 | 1627 | device_lock(dev); |
| 1628 | 1628 | |
| 1629 | 1629 | /* |
| 1630 | − * Bail out if the device is not running. Otherwise, the rescan may | |
| 1631 | − * block waiting for commands to be executed, with us holding the | |
| 1632 | − * device lock. This can result in a potential deadlock in the power | |
| 1633 | − * management core code when system resume is on-going. | |
| 1630 | + * Bail out if the device or its queue are not running. Otherwise, | |
| 1631 | + * the rescan may block waiting for commands to be executed, with us | |
| 1632 | + * holding the device lock. This can result in a potential deadlock | |
| 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 | 1637 | ret = -EWOULDBLOCK; |
| 1637 | 1638 | goto unlock; |
| 1638 | 1639 | } |
| @@ -333,6 +333,7 @@ if RISCV · 332 unmodified lines | ||
| 333 | 333 | |
| 334 | 334 | config ARCH_R9A07G043 |
| 335 | 335 | bool "RISC-V Platform support for RZ/Five" |
| 336 | + depends on NONPORTABLE | |
| 336 | 337 | select ARCH_RZG2L |
| 337 | 338 | select AX45MP_L2_CACHE if RISCV_DMA_NONCOHERENT |
| 338 | 339 | select DMA_GLOBAL_POOL |
| @@ -15,6 +15,10 @@ ifdef CONFIG_DEBUG_FS · 14 unmodified lines | ||
| 15 | 15 | soundwire-bus-y += debugfs.o |
| 16 | 16 | endif |
| 17 | 17 | |
| 18 | +ifdef CONFIG_IRQ_DOMAIN | |
| 19 | +soundwire-bus-y += irq.o | |
| 20 | +endif | |
| 21 | + | |
| 18 | 22 | #AMD driver |
| 19 | 23 | soundwire-amd-y := amd_manager.o |
| 20 | 24 | obj-$(CONFIG_SOUNDWIRE_AMD) += soundwire-amd.o |
| @@ -3,13 +3,13 @@ · 2 unmodified lines | ||
| 3 | 3 | |
| 4 | 4 | #include <linux/acpi.h> |
| 5 | 5 | #include <linux/delay.h> |
| 6 | −#include <linux/irq.h> | |
| 7 | 6 | #include <linux/mod_devicetable.h> |
| 8 | 7 | #include <linux/pm_runtime.h> |
| 9 | 8 | #include <linux/soundwire/sdw_registers.h> |
| 10 | 9 | #include <linux/soundwire/sdw.h> |
| 11 | 10 | #include <linux/soundwire/sdw_type.h> |
| 12 | 11 | #include "bus.h" |
| 12 | +#include "irq.h" | |
| 13 | 13 | #include "sysfs_local.h" |
| 14 | 14 | |
| 15 | 15 | static DEFINE_IDA(sdw_bus_ida); |
| @@ -25,23 +25,6 @@ static int sdw_get_id(struct sdw_bus *bus) · 9 unmodified lines | ||
| 25 | 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 | 29 | * sdw_bus_master_add() - add a bus Master instance |
| 47 | 30 | * @bus: bus instance |
| @@ -168,13 +151,9 @@ int sdw_bus_master_add(struct sdw_bus *bus, struct device *parent, · 120 unmodified lines | ||
| 168 | 151 | bus->params.curr_bank = SDW_BANK0; |
| 169 | 152 | bus->params.next_bank = SDW_BANK1; |
| 170 | 153 | |
| 171 | − bus->irq_chip.name = dev_name(bus->dev); | |
| 172 | − bus->domain = irq_domain_create_linear(fwnode, SDW_MAX_DEVICES, | |
| 173 | − &sdw_domain_ops, bus); | |
| 174 | − if (!bus->domain) { | |
| 175 | − dev_err(bus->dev, "Failed to add IRQ domain\n"); | |
| 176 | − return -EINVAL; | |
| 177 | − } | |
| 154 | + ret = sdw_irq_create(bus, fwnode); | |
| 155 | + if (ret) | |
| 156 | + return ret; | |
| 178 | 157 | |
| 179 | 158 | return 0; |
| 180 | 159 | } |
| @@ -213,7 +192,7 @@ void sdw_bus_master_delete(struct sdw_bus *bus) · 32 unmodified lines | ||
| 213 | 192 | { |
| 214 | 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 | 197 | sdw_master_device_del(bus); |
| 219 | 198 | |
| @@ -7,6 +7,7 @@ · 6 unmodified lines | ||
| 7 | 7 | #include <linux/soundwire/sdw.h> |
| 8 | 8 | #include <linux/soundwire/sdw_type.h> |
| 9 | 9 | #include "bus.h" |
| 10 | +#include "irq.h" | |
| 10 | 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 | 123 | if (drv->ops && drv->ops->read_prop) |
| 123 | 124 | drv->ops->read_prop(slave); |
| 124 | 125 | |
| 125 | − if (slave->prop.use_domain_irq) { | |
| 126 | − slave->irq = irq_create_mapping(slave->bus->domain, slave->dev_num); | |
| 127 | − if (!slave->irq) | |
| 128 | − dev_warn(dev, "Failed to map IRQ\n"); | |
| 129 | − } | |
| 126 | + if (slave->prop.use_domain_irq) | |
| 127 | + sdw_irq_create_mapping(slave); | |
| 130 | 128 | |
| 131 | 129 | /* init the sysfs as we have properties now */ |
| 132 | 130 | ret = sdw_slave_sysfs_init(slave); |
| @@ -176,8 +174,7 @@ static int sdw_drv_remove(struct device *dev) · 43 unmodified lines | ||
| 176 | 174 | slave->probed = false; |
| 177 | 175 | |
| 178 | 176 | if (slave->prop.use_domain_irq) |
| 179 | − irq_dispose_mapping(irq_find_mapping(slave->bus->domain, | |
| 180 | − slave->dev_num)); | |
| 177 | + sdw_irq_dispose_mapping(slave); | |
| 181 | 178 | |
| 182 | 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 | 12 | config VIDEO_ATOMISP |
| 13 | 13 | tristate "Intel Atom Image Signal Processor Driver" |
| 14 | 14 | depends on VIDEO_DEV && INTEL_ATOMISP |
| 15 | + depends on IPU_BRIDGE | |
| 15 | 16 | depends on MEDIA_PCI_SUPPORT |
| 16 | 17 | depends on PMIC_OPREGION |
| 17 | 18 | depends on I2C |
| 18 | 19 | select V4L2_FWNODE |
| 19 | 20 | select IOSF_MBI |
| 20 | − select IPU_BRIDGE | |
| 21 | 21 | select VIDEOBUF2_VMALLOC |
| 22 | 22 | select VIDEO_V4L2_SUBDEV_API |
| 23 | 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 | 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 | 1462 | const struct fwnode_handle *fwnode) |
| 1463 | 1463 | { |
| 1464 | 1464 | struct tegra_vi_graph_entity *entity; |
| 1465 | 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 | 1468 | entity = to_tegra_vi_graph_entity(asd); |
| 1469 | + | |
| 1469 | 1470 | if (entity->asd.match.fwnode == fwnode) |
| 1470 | 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 | 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 | 1538 | if (!ent) { |
| 1537 | 1539 | dev_err(vi->dev, "no entity found for %pOF\n", |
| 1538 | 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 | 1666 | * Locate the entity corresponding to the bound subdev and store the |
| 1665 | 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 | 1671 | if (!entity) { |
| 1669 | 1672 | dev_err(vi->dev, "no entity for subdev %s\n", subdev->name); |
| 1670 | 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 | 1717 | /* skip entities that are already processed */ |
| 1715 | 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 | 1721 | fwnode_handle_put(remote); |
| 1718 | 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 | 843 | EXPORT_SYMBOL(target_to_linux_sector); |
| 844 | 844 | |
| 845 | 845 | struct devices_idr_iter { |
| 846 | − struct config_item *prev_item; | |
| 847 | 846 | int (*fn)(struct se_device *dev, void *data); |
| 848 | 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 | 853 | struct devices_idr_iter *iter = data; |
| 855 | 854 | struct se_device *dev = p; |
| 855 | + struct config_item *item; | |
| 856 | 856 | int ret; |
| 857 | 857 | |
| 858 | − config_item_put(iter->prev_item); | |
| 859 | − iter->prev_item = NULL; | |
| 860 | − | |
| 861 | 858 | /* |
| 862 | 859 | * We add the device early to the idr, so it can be used |
| 863 | 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 | 864 | if (!target_dev_configured(dev)) |
| 868 | 865 | return 0; |
| 869 | 866 | |
| 870 | − iter->prev_item = config_item_get_unless_zero(&dev->dev_group.cg_item); | |
| 871 | − if (!iter->prev_item) | |
| 867 | + item = config_item_get_unless_zero(&dev->dev_group.cg_item); | |
| 868 | + if (!item) | |
| 872 | 869 | return 0; |
| 873 | 870 | mutex_unlock(&device_mutex); |
| 874 | 871 | |
| 875 | 872 | ret = iter->fn(dev, iter->data); |
| 873 | + config_item_put(item); | |
| 876 | 874 | |
| 877 | 875 | mutex_lock(&device_mutex); |
| 878 | 876 | return ret; |
| @@ -895,7 +893,6 @@ int target_for_each_device(int (*fn)(struct se_device *dev, void *data), · 16 unmodified lines | ||
| 895 | 893 | mutex_lock(&device_mutex); |
| 896 | 894 | ret = idr_for_each(&devices_idr, target_devices_idr_iter, &iter); |
| 897 | 895 | mutex_unlock(&device_mutex); |
| 898 | − config_item_put(iter.prev_item); | |
| 899 | 896 | return ret; |
| 900 | 897 | } |
| 901 | 898 | |
| @@ -217,12 +217,12 @@ unlock: · 216 unmodified lines | ||
| 217 | 217 | return rc; |
| 218 | 218 | } |
| 219 | 219 | |
| 220 | +/* mutex must be held by caller */ | |
| 220 | 221 | static void destroy_session(struct kref *ref) |
| 221 | 222 | { |
| 222 | 223 | struct amdtee_session *sess = container_of(ref, struct amdtee_session, |
| 223 | 224 | refcount); |
| 224 | 225 | |
| 225 | − mutex_lock(&session_list_mutex); | |
| 226 | 226 | list_del(&sess->list_node); |
| 227 | 227 | mutex_unlock(&session_list_mutex); |
| 228 | 228 | kfree(sess); |
| @@ -272,7 +272,8 @@ int amdtee_open_session(struct tee_context *ctx, · 43 unmodified lines | ||
| 272 | 272 | if (arg->ret != TEEC_SUCCESS) { |
| 273 | 273 | pr_err("open_session failed %d\n", arg->ret); |
| 274 | 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 | 277 | goto out; |
| 277 | 278 | } |
| 278 | 279 | |
| @@ -290,7 +291,8 @@ int amdtee_open_session(struct tee_context *ctx, · 11 unmodified lines | ||
| 290 | 291 | pr_err("reached maximum session count %d\n", TEE_NUM_SESSIONS); |
| 291 | 292 | handle_close_session(ta_handle, session_info); |
| 292 | 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 | 296 | rc = -ENOMEM; |
| 295 | 297 | goto out; |
| 296 | 298 | } |
| @@ -331,7 +333,7 @@ int amdtee_close_session(struct tee_context *ctx, u32 session) · 34 unmodified lines | ||
| 331 | 333 | handle_close_session(ta_handle, session_info); |
| 332 | 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 | 338 | return 0; |
| 337 | 339 | } |
| @@ -41,6 +41,7 @@ · 40 unmodified lines | ||
| 41 | 41 | #define PHY_PORT_CS1_LINK_STATE_SHIFT 26 |
| 42 | 42 | |
| 43 | 43 | #define ICM_TIMEOUT 5000 /* ms */ |
| 44 | +#define ICM_RETRIES 3 | |
| 44 | 45 | #define ICM_APPROVE_TIMEOUT 10000 /* ms */ |
| 45 | 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 | 298 | static int icm_request(struct tb *tb, const void *request, size_t request_size, |
| 298 | 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 | 302 | struct icm *icm = tb_priv(tb); |
| 302 | − int retries = 3; | |
| 303 | 303 | |
| 304 | 304 | do { |
| 305 | 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 | 410 | return -ENOMEM; |
| 411 | 411 | |
| 412 | 412 | ret = icm_request(tb, &request, sizeof(request), switches, |
| 413 | − sizeof(*switches), npackets, ICM_TIMEOUT); | |
| 413 | + sizeof(*switches), npackets, ICM_RETRIES, ICM_TIMEOUT); | |
| 414 | 414 | if (ret) |
| 415 | 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 | 464 | memset(&reply, 0, sizeof(reply)); |
| 465 | 465 | ret = icm_request(tb, &request, sizeof(request), &reply, sizeof(reply), |
| 466 | − 1, ICM_TIMEOUT); | |
| 466 | + 1, ICM_RETRIES, ICM_TIMEOUT); | |
| 467 | 467 | if (ret) |
| 468 | 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 | 488 | memset(&reply, 0, sizeof(reply)); |
| 489 | 489 | /* Use larger timeout as establishing tunnels can take some time */ |
| 490 | 490 | ret = icm_request(tb, &request, sizeof(request), &reply, sizeof(reply), |
| 491 | − 1, ICM_APPROVE_TIMEOUT); | |
| 491 | + 1, ICM_RETRIES, ICM_APPROVE_TIMEOUT); | |
| 492 | 492 | if (ret) |
| 493 | 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 | 516 | memset(&reply, 0, sizeof(reply)); |
| 517 | 517 | ret = icm_request(tb, &request, sizeof(request), &reply, sizeof(reply), |
| 518 | − 1, ICM_TIMEOUT); | |
| 518 | + 1, ICM_RETRIES, ICM_TIMEOUT); | |
| 519 | 519 | if (ret) |
| 520 | 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 | 544 | memset(&reply, 0, sizeof(reply)); |
| 545 | 545 | ret = icm_request(tb, &request, sizeof(request), &reply, sizeof(reply), |
| 546 | − 1, ICM_TIMEOUT); | |
| 546 | + 1, ICM_RETRIES, ICM_TIMEOUT); | |
| 547 | 547 | if (ret) |
| 548 | 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 | 578 | memset(&reply, 0, sizeof(reply)); |
| 579 | 579 | ret = icm_request(tb, &request, sizeof(request), &reply, sizeof(reply), |
| 580 | − 1, ICM_TIMEOUT); | |
| 580 | + 1, ICM_RETRIES, ICM_TIMEOUT); | |
| 581 | 581 | if (ret) |
| 582 | 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 | 1021 | memset(&reply, 0, sizeof(reply)); |
| 1022 | 1022 | ret = icm_request(tb, &request, sizeof(request), &reply, sizeof(reply), |
| 1023 | − 1, 20000); | |
| 1023 | + 1, 10, 2000); | |
| 1024 | 1024 | if (ret) |
| 1025 | 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 | 1054 | memset(&reply, 0, sizeof(reply)); |
| 1055 | 1055 | ret = icm_request(tb, &request, sizeof(request), &reply, sizeof(reply), |
| 1056 | − 1, ICM_APPROVE_TIMEOUT); | |
| 1056 | + 1, ICM_RETRIES, ICM_APPROVE_TIMEOUT); | |
| 1057 | 1057 | if (ret) |
| 1058 | 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 | 1082 | memset(&reply, 0, sizeof(reply)); |
| 1083 | 1083 | ret = icm_request(tb, &request, sizeof(request), &reply, sizeof(reply), |
| 1084 | − 1, ICM_TIMEOUT); | |
| 1084 | + 1, ICM_RETRIES, ICM_TIMEOUT); | |
| 1085 | 1085 | if (ret) |
| 1086 | 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 | 1111 | memset(&reply, 0, sizeof(reply)); |
| 1112 | 1112 | ret = icm_request(tb, &request, sizeof(request), &reply, sizeof(reply), |
| 1113 | − 1, ICM_TIMEOUT); | |
| 1113 | + 1, ICM_RETRIES, ICM_TIMEOUT); | |
| 1114 | 1114 | if (ret) |
| 1115 | 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 | 1145 | memset(&reply, 0, sizeof(reply)); |
| 1146 | 1146 | ret = icm_request(tb, &request, sizeof(request), &reply, sizeof(reply), |
| 1147 | − 1, ICM_TIMEOUT); | |
| 1147 | + 1, ICM_RETRIES, ICM_TIMEOUT); | |
| 1148 | 1148 | if (ret) |
| 1149 | 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 | 1171 | memset(&reply, 0, sizeof(reply)); |
| 1172 | 1172 | ret = icm_request(tb, &request, sizeof(request), &reply, sizeof(reply), |
| 1173 | − 1, ICM_TIMEOUT); | |
| 1173 | + 1, ICM_RETRIES, ICM_TIMEOUT); | |
| 1174 | 1174 | if (ret) |
| 1175 | 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 | 1497 | memset(&reply, 0, sizeof(reply)); |
| 1498 | 1498 | ret = icm_request(tb, &request, sizeof(request), &reply, sizeof(reply), |
| 1499 | − 1, ICM_TIMEOUT); | |
| 1499 | + 1, ICM_RETRIES, ICM_TIMEOUT); | |
| 1500 | 1500 | if (ret) |
| 1501 | 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 | 1523 | memset(&reply, 0, sizeof(reply)); |
| 1524 | 1524 | ret = icm_request(tb, &request, sizeof(request), &reply, sizeof(reply), |
| 1525 | − 1, ICM_TIMEOUT); | |
| 1525 | + 1, ICM_RETRIES, ICM_TIMEOUT); | |
| 1526 | 1526 | if (ret) |
| 1527 | 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 | 1544 | memset(&reply, 0, sizeof(reply)); |
| 1545 | 1545 | ret = icm_request(tb, &request, sizeof(request), &reply, sizeof(reply), |
| 1546 | − 1, ICM_TIMEOUT); | |
| 1546 | + 1, ICM_RETRIES, ICM_TIMEOUT); | |
| 1547 | 1547 | if (ret) |
| 1548 | 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 | 1605 | memset(&reply, 0, sizeof(reply)); |
| 1606 | 1606 | ret = icm_request(tb, &request, sizeof(request), &reply, sizeof(reply), |
| 1607 | − 1, ICM_TIMEOUT); | |
| 1607 | + 1, ICM_RETRIES, ICM_TIMEOUT); | |
| 1608 | 1608 | if (ret) |
| 1609 | 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 | 1627 | memset(&reply, 0, sizeof(reply)); |
| 1628 | 1628 | ret = icm_request(tb, &request, sizeof(request), &reply, sizeof(reply), |
| 1629 | − 1, 20000); | |
| 1629 | + 1, ICM_RETRIES, 20000); | |
| 1630 | 1630 | if (ret) |
| 1631 | 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 | 2299 | memset(&reply, 0, sizeof(reply)); |
| 2300 | 2300 | ret = icm_request(tb, &request, sizeof(request), &reply, sizeof(reply), |
| 2301 | − 1, ICM_TIMEOUT); | |
| 2301 | + 1, ICM_RETRIES, ICM_TIMEOUT); | |
| 2302 | 2302 | if (ret) |
| 2303 | 2303 | return ret; |
| 2304 | 2304 | |
| @@ -2725,6 +2725,13 @@ int tb_switch_lane_bonding_enable(struct tb_switch *sw) · 2724 unmodified lines | ||
| 2725 | 2725 | !tb_port_is_width_supported(down, TB_LINK_WIDTH_DUAL)) |
| 2726 | 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 | 2735 | ret = tb_port_lane_bonding_enable(up); |
| 2729 | 2736 | if (ret) { |
| 2730 | 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 | 382 | } else if (ucap && tb_port_tmu_is_unidirectional(up)) { |
| 383 | 383 | if (tmu_rates[TB_SWITCH_TMU_MODE_LOWRES] == rate) |
| 384 | 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 | 386 | sw->tmu.mode = TB_SWITCH_TMU_MODE_HIFI_UNI; |
| 387 | 387 | } else if (rate) { |
| 388 | 388 | sw->tmu.mode = TB_SWITCH_TMU_MODE_HIFI_BI; |
| @@ -703,6 +703,27 @@ out_unlock: · 702 unmodified lines | ||
| 703 | 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 | 727 | static void tb_xdp_handle_request(struct work_struct *work) |
| 707 | 728 | { |
| 708 | 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 | 786 | case UUID_REQUEST: |
| 766 | 787 | tb_dbg(tb, "%llx: received XDomain UUID request\n", route); |
| 767 | 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 | 798 | break; |
| 769 | 799 | |
| 770 | 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 | 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 | 1561 | static void tb_xdomain_state_work(struct work_struct *work) |
| 1525 | 1562 | { |
| 1526 | 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 | 1584 | if (ret) { |
| 1548 | 1585 | if (ret == -EAGAIN) |
| 1549 | 1586 | goto retry_state; |
| 1550 | − xd->state = XDOMAIN_STATE_ERROR; | |
| 1587 | + tb_xdomain_failed(xd); | |
| 1551 | 1588 | } else { |
| 1552 | 1589 | tb_xdomain_queue_properties_changed(xd); |
| 1553 | 1590 | if (xd->bonding_possible) |
| @@ -1612,7 +1649,7 @@ static void tb_xdomain_state_work(struct work_struct *work) · 58 unmodified lines | ||
| 1612 | 1649 | if (ret) { |
| 1613 | 1650 | if (ret == -EAGAIN) |
| 1614 | 1651 | goto retry_state; |
| 1615 | − xd->state = XDOMAIN_STATE_ERROR; | |
| 1652 | + tb_xdomain_failed(xd); | |
| 1616 | 1653 | } else { |
| 1617 | 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 | 1660 | break; |
| 1624 | 1661 | |
| 1625 | 1662 | case XDOMAIN_STATE_ERROR: |
| 1663 | + dev_dbg(&xd->dev, "discovery failed, stopping handshake\n"); | |
| 1664 | + __stop_handshake(xd); | |
| 1626 | 1665 | break; |
| 1627 | 1666 | |
| 1628 | 1667 | default: |
| @@ -1833,21 +1872,6 @@ static void tb_xdomain_release(struct device *dev) · 204 unmodified lines | ||
| 1833 | 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 | 1875 | static int __maybe_unused tb_xdomain_suspend(struct device *dev) |
| 1852 | 1876 | { |
| 1853 | 1877 | stop_handshake(tb_to_xdomain(dev)); |
| @@ -1623,7 +1623,7 @@ static int omap8250_suspend(struct device *dev) · 1622 unmodified lines | ||
| 1623 | 1623 | { |
| 1624 | 1624 | struct omap8250_priv *priv = dev_get_drvdata(dev); |
| 1625 | 1625 | struct uart_8250_port *up = serial8250_get_port(priv->line); |
| 1626 | − int err; | |
| 1626 | + int err = 0; | |
| 1627 | 1627 | |
| 1628 | 1628 | serial8250_suspend_port(priv->line); |
| 1629 | 1629 | |
| @@ -1633,7 +1633,8 @@ static int omap8250_suspend(struct device *dev) · 3 unmodified lines | ||
| 1633 | 1633 | if (!device_may_wakeup(dev)) |
| 1634 | 1634 | priv->wer = 0; |
| 1635 | 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 | 1638 | flush_work(&priv->qos_work); |
| 1638 | 1639 | |
| 1639 | 1640 | return err; |
| @@ -1642,11 +1643,15 @@ static int omap8250_suspend(struct device *dev) · 2 unmodified lines | ||
| 1642 | 1643 | static int omap8250_resume(struct device *dev) |
| 1643 | 1644 | { |
| 1644 | 1645 | struct omap8250_priv *priv = dev_get_drvdata(dev); |
| 1646 | + struct uart_8250_port *up = serial8250_get_port(priv->line); | |
| 1645 | 1647 | int err; |
| 1646 | 1648 | |
| 1647 | − err = pm_runtime_force_resume(dev); | |
| 1648 | − if (err) | |
| 1649 | − return err; | |
| 1649 | + if (uart_console(&up->port) && console_suspend_enabled) { | |
| 1650 | + err = pm_runtime_force_resume(dev); | |
| 1651 | + if (err) | |
| 1652 | + return err; | |
| 1653 | + } | |
| 1654 | + | |
| 1650 | 1655 | serial8250_resume_port(priv->line); |
| 1651 | 1656 | /* Paired with pm_runtime_resume_and_get() in omap8250_suspend() */ |
| 1652 | 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 | 1729 | if (priv->line >= 0) |
| 1725 | 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 | 1732 | if (priv->habit & UART_ERRATA_CLOCK_DISABLE) { |
| 1738 | 1733 | int ret; |
| @@ -156,7 +156,7 @@ static void __uart_start(struct uart_state *state) · 155 unmodified lines | ||
| 156 | 156 | * enabled, serial_port_runtime_resume() calls start_tx() again |
| 157 | 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 | 160 | port->ops->start_tx(port); |
| 161 | 161 | pm_runtime_mark_last_busy(&port_dev->dev); |
| 162 | 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 | 1407 | static int uart_rs485_config(struct uart_port *port) |
| 1408 | 1408 | { |
| 1409 | 1409 | struct serial_rs485 *rs485 = &port->rs485; |
| 1410 | + unsigned long flags; | |
| 1410 | 1411 | int ret; |
| 1411 | 1412 | |
| 1413 | + if (!(rs485->flags & SER_RS485_ENABLED)) | |
| 1414 | + return 0; | |
| 1415 | + | |
| 1412 | 1416 | uart_sanitize_serial_rs485(port, rs485); |
| 1413 | 1417 | uart_set_rs485_termination(port, rs485); |
| 1414 | 1418 | |
| 1419 | + uart_port_lock_irqsave(port, &flags); | |
| 1415 | 1420 | ret = port->rs485_config(port, NULL, rs485); |
| 1421 | + uart_port_unlock_irqrestore(port, flags); | |
| 1416 | 1422 | if (ret) |
| 1417 | 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 | 2483 | if (ret == 0) { |
| 2478 | 2484 | if (tty) |
| 2479 | 2485 | uart_change_line_settings(tty, state, NULL); |
| 2486 | + uart_rs485_config(uport); | |
| 2480 | 2487 | uart_port_lock_irq(uport); |
| 2481 | 2488 | if (!(uport->rs485.flags & SER_RS485_ENABLED)) |
| 2482 | 2489 | ops->set_mctrl(uport, uport->mctrl); |
| 2483 | − else | |
| 2484 | − uart_rs485_config(uport); | |
| 2485 | 2490 | ops->start_tx(uport); |
| 2486 | 2491 | uart_port_unlock_irq(uport); |
| 2487 | 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 | 2595 | port->mctrl &= TIOCM_DTR; |
| 2591 | 2596 | if (!(port->rs485.flags & SER_RS485_ENABLED)) |
| 2592 | 2597 | port->ops->set_mctrl(port, port->mctrl); |
| 2593 | − else | |
| 2594 | − uart_rs485_config(port); | |
| 2595 | 2598 | uart_port_unlock_irqrestore(port, flags); |
| 2596 | 2599 | |
| 2600 | + uart_rs485_config(port); | |
| 2601 | + | |
| 2597 | 2602 | /* |
| 2598 | 2603 | * If this driver supports console, and it hasn't been |
| 2599 | 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 | 6895 | mask, 0, 1000, 1000); |
| 6896 | 6896 | |
| 6897 | 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 | 6900 | out: |
| 6901 | 6901 | return err; |
| @@ -1125,6 +1125,9 @@ static int cdnsp_gadget_ep_dequeue(struct usb_ep *ep, · 1124 unmodified lines | ||
| 1125 | 1125 | unsigned long flags; |
| 1126 | 1126 | int ret; |
| 1127 | 1127 | |
| 1128 | + if (request->status != -EINPROGRESS) | |
| 1129 | + return 0; | |
| 1130 | + | |
| 1128 | 1131 | if (!pep->endpoint.desc) { |
| 1129 | 1132 | dev_err(pdev->dev, |
| 1130 | 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 | 131 | #else /* CONFIG_PM_SLEEP */ |
| 132 | 132 | static inline int cdns_resume(struct cdns *cdns) |
| 133 | 133 | { return 0; } |
| 134 | −static inline int cdns_set_active(struct cdns *cdns, u8 set_active) | |
| 135 | −{ return 0; } | |
| 134 | +static inline void cdns_set_active(struct cdns *cdns, u8 set_active) { } | |
| 136 | 135 | static inline int cdns_suspend(struct cdns *cdns) |
| 137 | 136 | { return 0; } |
| 138 | 137 | #endif /* CONFIG_PM_SLEEP */ |
| @@ -151,6 +151,10 @@ int usb_device_supports_lpm(struct usb_device *udev) · 150 unmodified lines | ||
| 151 | 151 | if (udev->quirks & USB_QUIRK_NO_LPM) |
| 152 | 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 | 158 | /* USB 2.1 (and greater) devices indicate LPM support through |
| 155 | 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 | 331 | if (!udev->lpm_capable || udev->speed < USB_SPEED_SUPER) |
| 328 | 332 | return; |
| 329 | 333 | |
| 334 | + /* Skip if the device BOS descriptor couldn't be read */ | |
| 335 | + if (!udev->bos) | |
| 336 | + return; | |
| 337 | + | |
| 330 | 338 | hub = usb_hub_to_struct_hub(udev->parent); |
| 331 | 339 | /* It doesn't take time to transition the roothub into U0, since it |
| 332 | 340 | * doesn't have an upstream link. |
| @@ -2704,13 +2712,17 @@ out_authorized: · 2371 unmodified lines | ||
| 2704 | 2712 | static enum usb_ssp_rate get_port_ssp_rate(struct usb_device *hdev, |
| 2705 | 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 | 2716 | u32 attr; |
| 2709 | 2717 | u8 speed_id; |
| 2710 | 2718 | u8 ssac; |
| 2711 | 2719 | u8 lanes; |
| 2712 | 2720 | int i; |
| 2713 | 2721 | |
| 2722 | + if (!hdev->bos) | |
| 2723 | + goto out; | |
| 2724 | + | |
| 2725 | + ssp_cap = hdev->bos->ssp_cap; | |
| 2714 | 2726 | if (!ssp_cap) |
| 2715 | 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 | 4227 | enum usb3_link_state state) |
| 4216 | 4228 | { |
| 4217 | 4229 | int timeout; |
| 4218 | − __u8 u1_mel = udev->bos->ss_cap->bU1devExitLat; | |
| 4219 | − __le16 u2_mel = udev->bos->ss_cap->bU2DevExitLat; | |
| 4230 | + __u8 u1_mel; | |
| 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 | 4240 | /* If the device says it doesn't have *any* exit latency to come out of |
| 4222 | 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 | 154 | return (hdev->descriptor.bDeviceProtocol == USB_HUB_PR_SS && |
| 155 | 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 | 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 | 279 | * XHCI driver will reset the host block. If dwc3 was configured for |
| 280 | 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 | 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 | 322 | reg = dwc3_readl(dwc->regs, DWC3_DCTL); |
| 286 | 323 | reg |= DWC3_DCTL_CSFTRST; |
| 287 | 324 | reg &= ~DWC3_DCTL_RUN_STOP; |
| @@ -1156,7 +1156,8 @@ static int ncm_unwrap_ntb(struct gether *port, · 1155 unmodified lines | ||
| 1156 | 1156 | struct sk_buff_head *list) |
| 1157 | 1157 | { |
| 1158 | 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 | 1161 | unsigned index, index2; |
| 1161 | 1162 | int ndp_index; |
| 1162 | 1163 | unsigned dg_len, dg_len2; |
| @@ -1169,6 +1170,10 @@ static int ncm_unwrap_ntb(struct gether *port, · 6 unmodified lines | ||
| 1169 | 1170 | const struct ndp_parser_opts *opts = ncm->parser_opts; |
| 1170 | 1171 | unsigned crc_len = ncm->is_crc ? sizeof(uint32_t) : 0; |
| 1171 | 1172 | int dgram_counter; |
| 1173 | + int to_process = skb->len; | |
| 1174 | + | |
| 1175 | +parse_ntb: | |
| 1176 | + tmp = (__le16 *)ntb_ptr; | |
| 1172 | 1177 | |
| 1173 | 1178 | /* dwSignature */ |
| 1174 | 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 | 1220 | * walk through NDP |
| 1216 | 1221 | * dwSignature |
| 1217 | 1222 | */ |
| 1218 | − tmp = (void *)(skb->data + ndp_index); | |
| 1223 | + tmp = (__le16 *)(ntb_ptr + ndp_index); | |
| 1219 | 1224 | if (get_unaligned_le32(tmp) != ncm->ndp_sign) { |
| 1220 | 1225 | INFO(port->func.config->cdev, "Wrong NDP SIGN\n"); |
| 1221 | 1226 | goto err; |
| @@ -1272,11 +1277,11 @@ static int ncm_unwrap_ntb(struct gether *port, · 50 unmodified lines | ||
| 1272 | 1277 | if (ncm->is_crc) { |
| 1273 | 1278 | uint32_t crc, crc2; |
| 1274 | 1279 | |
| 1275 | − crc = get_unaligned_le32(skb->data + | |
| 1280 | + crc = get_unaligned_le32(ntb_ptr + | |
| 1276 | 1281 | index + dg_len - |
| 1277 | 1282 | crc_len); |
| 1278 | 1283 | crc2 = ~crc32_le(~0, |
| 1279 | − skb->data + index, | |
| 1284 | + ntb_ptr + index, | |
| 1280 | 1285 | dg_len - crc_len); |
| 1281 | 1286 | if (crc != crc2) { |
| 1282 | 1287 | INFO(port->func.config->cdev, |
| @@ -1303,7 +1308,7 @@ static int ncm_unwrap_ntb(struct gether *port, · 20 unmodified lines | ||
| 1303 | 1308 | dg_len - crc_len); |
| 1304 | 1309 | if (skb2 == NULL) |
| 1305 | 1310 | goto err; |
| 1306 | − skb_put_data(skb2, skb->data + index, | |
| 1311 | + skb_put_data(skb2, ntb_ptr + index, | |
| 1307 | 1312 | dg_len - crc_len); |
| 1308 | 1313 | |
| 1309 | 1314 | skb_queue_tail(list, skb2); |
| @@ -1316,10 +1321,17 @@ static int ncm_unwrap_ntb(struct gether *port, · 6 unmodified lines | ||
| 1316 | 1321 | } while (ndp_len > 2 * (opts->dgram_item_len * 2)); |
| 1317 | 1322 | } while (ndp_index); |
| 1318 | 1323 | |
| 1319 | − dev_consume_skb_any(skb); | |
| 1320 | − | |
| 1321 | 1324 | VDBG(port->func.config->cdev, |
| 1322 | 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 | 1335 | return 0; |
| 1324 | 1336 | err: |
| 1325 | 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 | 497 | /* Get the Buffer address and copy the transmit data.*/ |
| 498 | 498 | eprambase = (u32 __force *)(udc->addr + ep->rambase); |
| 499 | 499 | if (ep->is_in) { |
| 500 | − memcpy(eprambase, bufferptr, bytestosend); | |
| 500 | + memcpy_toio((void __iomem *)eprambase, bufferptr, | |
| 501 | + bytestosend); | |
| 501 | 502 | udc->write_fn(udc->addr, ep->offset + |
| 502 | 503 | XUSB_EP_BUF0COUNT_OFFSET, bufferlen); |
| 503 | 504 | } else { |
| 504 | − memcpy(bufferptr, eprambase, bytestosend); | |
| 505 | + memcpy_toio((void __iomem *)bufferptr, eprambase, | |
| 506 | + bytestosend); | |
| 505 | 507 | } |
| 506 | 508 | /* |
| 507 | 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 | 517 | eprambase = (u32 __force *)(udc->addr + ep->rambase + |
| 516 | 518 | ep->ep_usb.maxpacket); |
| 517 | 519 | if (ep->is_in) { |
| 518 | − memcpy(eprambase, bufferptr, bytestosend); | |
| 520 | + memcpy_toio((void __iomem *)eprambase, bufferptr, | |
| 521 | + bytestosend); | |
| 519 | 522 | udc->write_fn(udc->addr, ep->offset + |
| 520 | 523 | XUSB_EP_BUF1COUNT_OFFSET, bufferlen); |
| 521 | 524 | } else { |
| 522 | − memcpy(bufferptr, eprambase, bytestosend); | |
| 525 | + memcpy_toio((void __iomem *)bufferptr, eprambase, | |
| 526 | + bytestosend); | |
| 523 | 527 | } |
| 524 | 528 | /* |
| 525 | 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 | 1025 | udc->addr); |
| 1022 | 1026 | length = req->usb_req.actual = min_t(u32, length, |
| 1023 | 1027 | EP0_MAX_PACKET); |
| 1024 | − memcpy(corebuf, req->usb_req.buf, length); | |
| 1028 | + memcpy_toio((void __iomem *)corebuf, req->usb_req.buf, length); | |
| 1025 | 1029 | udc->write_fn(udc->addr, XUSB_EP_BUF0COUNT_OFFSET, length); |
| 1026 | 1030 | udc->write_fn(udc->addr, XUSB_BUFFREADY_OFFSET, 1); |
| 1027 | 1031 | } else { |
| @@ -1752,7 +1756,7 @@ static void xudc_handle_setup(struct xusb_udc *udc) · 724 unmodified lines | ||
| 1752 | 1756 | |
| 1753 | 1757 | /* Load up the chapter 9 command buffer.*/ |
| 1754 | 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 | 1761 | udc->setup = setup; |
| 1758 | 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 | 1843 | (ep0->rambase << 2)); |
| 1840 | 1844 | buffer = req->usb_req.buf + req->usb_req.actual; |
| 1841 | 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 | 1848 | if (req->usb_req.length == req->usb_req.actual) { |
| 1845 | 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 | 1919 | (ep0->rambase << 2)); |
| 1916 | 1920 | buffer = req->usb_req.buf + req->usb_req.actual; |
| 1917 | 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 | 1924 | udc->write_fn(udc->addr, XUSB_EP_BUF0COUNT_OFFSET, count); |
| 1921 | 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 | 1062 | *status |= USB_PORT_STAT_C_CONFIG_ERROR << 16; |
| 1063 | 1063 | |
| 1064 | 1064 | /* USB3 specific wPortStatus bits */ |
| 1065 | − if (portsc & PORT_POWER) { | |
| 1065 | + if (portsc & PORT_POWER) | |
| 1066 | 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 */ | |
| 1073 | − if (bus_state->port_remote_wakeup & (1 << portnum) && | |
| 1068 | + /* no longer suspended or resuming */ | |
| 1069 | + if (link_state != XDEV_U3 && | |
| 1074 | 1070 | link_state != XDEV_RESUME && |
| 1075 | 1071 | link_state != XDEV_RECOVERY) { |
| 1076 | − bus_state->port_remote_wakeup &= ~(1 << portnum); | |
| 1077 | − usb_hcd_end_port_resume(&hcd->self, portnum); | |
| 1072 | + /* remote wake resume signaling complete */ | |
| 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 | 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 | 1131 | usb_hcd_end_port_resume(&port->rhub->hcd->self, portnum); |
| 1132 | 1132 | } |
| 1133 | 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 | 2285 | writel(erst_size, &ir->ir_set->erst_size); |
| 2286 | 2286 | |
| 2287 | 2287 | erst_base = xhci_read_64(xhci, &ir->ir_set->erst_base); |
| 2288 | − erst_base &= ERST_PTR_MASK; | |
| 2289 | − erst_base |= (ir->erst.erst_dma_addr & (u64) ~ERST_PTR_MASK); | |
| 2288 | + erst_base &= ERST_BASE_RSVDP; | |
| 2289 | + erst_base |= ir->erst.erst_dma_addr & ~ERST_BASE_RSVDP; | |
| 2290 | 2290 | xhci_write_64(xhci, erst_base, &ir->ir_set->erst_base); |
| 2291 | 2291 | |
| 2292 | 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 | 798 | static void xhci_unmap_td_bounce_buffer(struct xhci_hcd *xhci, |
| 799 | 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 | 802 | struct xhci_segment *seg = td->bounce_seg; |
| 803 | 803 | struct urb *urb = td->urb; |
| 804 | 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 | 2997 | static void xhci_update_erst_dequeue(struct xhci_hcd *xhci, |
| 2998 | 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 | 3002 | u64 temp_64; |
| 3002 | 3003 | dma_addr_t deq; |
| @@ -3017,12 +3018,13 @@ static void xhci_update_erst_dequeue(struct xhci_hcd *xhci, · 14 unmodified lines | ||
| 3017 | 3018 | return; |
| 3018 | 3019 | |
| 3019 | 3020 | /* Update HC event ring dequeue pointer */ |
| 3020 | − temp_64 &= ERST_PTR_MASK; | |
| 3021 | + temp_64 &= ERST_DESI_MASK; | |
| 3021 | 3022 | temp_64 |= ((u64) deq & (u64) ~ERST_PTR_MASK); |
| 3022 | 3023 | } |
| 3023 | 3024 | |
| 3024 | 3025 | /* Clear the event handler busy flag (RW1C) */ |
| 3025 | − temp_64 |= ERST_EHB; | |
| 3026 | + if (clear_ehb) | |
| 3027 | + temp_64 |= ERST_EHB; | |
| 3026 | 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 | 3105 | while (xhci_handle_event(xhci, ir) > 0) { |
| 3104 | 3106 | if (event_loop++ < TRBS_PER_SEGMENT / 2) |
| 3105 | 3107 | continue; |
| 3106 | − xhci_update_erst_dequeue(xhci, ir, event_ring_deq); | |
| 3108 | + xhci_update_erst_dequeue(xhci, ir, event_ring_deq, false); | |
| 3107 | 3109 | event_ring_deq = ir->event_ring->dequeue; |
| 3108 | 3110 | |
| 3109 | 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 | 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 | 3119 | ret = IRQ_HANDLED; |
| 3118 | 3120 | |
| 3119 | 3121 | out: |
| @@ -3469,7 +3471,7 @@ static u32 xhci_td_remainder(struct xhci_hcd *xhci, int transferred, · 349 unmodified lines | ||
| 3469 | 3471 | static int xhci_align_td(struct xhci_hcd *xhci, struct urb *urb, u32 enqd_len, |
| 3470 | 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 | 3475 | unsigned int unalign; |
| 3474 | 3476 | unsigned int max_pkt; |
| 3475 | 3477 | u32 new_buff_len; |
| @@ -514,7 +514,7 @@ struct xhci_intr_reg { · 513 unmodified lines | ||
| 514 | 514 | #define ERST_SIZE_MASK (0xffff << 16) |
| 515 | 515 | |
| 516 | 516 | /* erst_base bitmasks */ |
| 517 | −#define ERST_BASE_RSVDP (0x3f) | |
| 517 | +#define ERST_BASE_RSVDP (GENMASK_ULL(5, 0)) | |
| 518 | 518 | |
| 519 | 519 | /* erst_dequeue bitmasks */ |
| 520 | 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 | 434 | { USB_DEVICE(VENDOR_ID_GENESYS, 0x0608) }, /* Genesys Logic GL850G USB 2.0 */ |
| 435 | 435 | { USB_DEVICE(VENDOR_ID_GENESYS, 0x0610) }, /* Genesys Logic GL852G USB 2.0 */ |
| 436 | 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 | 438 | { USB_DEVICE(VENDOR_ID_MICROCHIP, 0x2514) }, /* USB2514B USB 2.0 */ |
| 438 | 439 | { USB_DEVICE(VENDOR_ID_MICROCHIP, 0x2517) }, /* USB2517 USB 2.0 */ |
| 439 | 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 | 49 | static const struct of_device_id onboard_hub_match[] = { |
| 50 | + { .compatible = "usb424,2412", .data = µchip_usb424_data, }, | |
| 50 | 51 | { .compatible = "usb424,2514", .data = µchip_usb424_data, }, |
| 51 | 52 | { .compatible = "usb424,2517", .data = µchip_usb424_data, }, |
| 52 | 53 | { .compatible = "usb451,8140", .data = &ti_tusb8041_data, }, |
| @@ -39,7 +39,7 @@ static const struct musb_register_map musb_regmap[] = { · 38 unmodified lines | ||
| 39 | 39 | { "IntrUsbE", MUSB_INTRUSBE, 8 }, |
| 40 | 40 | { "DevCtl", MUSB_DEVCTL, 8 }, |
| 41 | 41 | { "VControl", 0x68, 32 }, |
| 42 | − { "HWVers", 0x69, 16 }, | |
| 42 | + { "HWVers", MUSB_HWVERS, 16 }, | |
| 43 | 43 | { "LinkInfo", MUSB_LINKINFO, 8 }, |
| 44 | 44 | { "VPLen", MUSB_VPLEN, 8 }, |
| 45 | 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 | 321 | musb_giveback(musb, urb, status); |
| 322 | 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 | 330 | /* reclaim resources (and bandwidth) ASAP; deschedule it, and |
| 325 | 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 | 334 | struct list_head *head; |
| 329 | 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 | 2404 | * and its URB list has emptied, recycle this qh. |
| 2399 | 2405 | */ |
| 2400 | 2406 | if (ready && list_empty(&qh->hep->urb_list)) { |
| 2407 | + musb_ep_set_qh(qh->hw_ep, is_in, NULL); | |
| 2401 | 2408 | qh->hep->hcpriv = NULL; |
| 2402 | 2409 | list_del(&qh->ring); |
| 2403 | 2410 | kfree(qh); |
| @@ -304,6 +304,11 @@ static int dp_altmode_vdm(struct typec_altmode *alt, · 303 unmodified lines | ||
| 304 | 304 | typec_altmode_update_active(alt, false); |
| 305 | 305 | dp->data.status = 0; |
| 306 | 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 | 312 | break; |
| 308 | 313 | case DP_CMD_STATUS_UPDATE: |
| 309 | 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 | 381 | struct device *dev = pmic_typec_pdphy->dev; |
| 382 | 382 | int ret; |
| 383 | 383 | |
| 384 | − ret = regulator_enable(pmic_typec_pdphy->vdd_pdphy); | |
| 385 | − if (ret) | |
| 386 | − return ret; | |
| 387 | − | |
| 388 | 384 | /* PD 2.0, DR=TYPEC_DEVICE, PR=TYPEC_SINK */ |
| 389 | 385 | ret = regmap_update_bits(pmic_typec_pdphy->regmap, |
| 390 | 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 | 418 | ret = regmap_write(pmic_typec_pdphy->regmap, |
| 423 | 419 | pmic_typec_pdphy->base + USB_PDPHY_EN_CONTROL_REG, 0); |
| 424 | 420 | |
| 425 | − regulator_disable(pmic_typec_pdphy->vdd_pdphy); | |
| 426 | − | |
| 427 | 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 | 441 | int i; |
| 448 | 442 | int ret; |
| 449 | 443 | |
| 444 | + ret = regulator_enable(pmic_typec_pdphy->vdd_pdphy); | |
| 445 | + if (ret) | |
| 446 | + return ret; | |
| 447 | + | |
| 450 | 448 | pmic_typec_pdphy->tcpm_port = tcpm_port; |
| 451 | 449 | |
| 452 | 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 | 465 | disable_irq(pmic_typec_pdphy->irq_data[i].irq); |
| 468 | 466 | |
| 469 | 467 | qcom_pmic_typec_pdphy_reset_on(pmic_typec_pdphy); |
| 468 | + | |
| 469 | + regulator_disable(pmic_typec_pdphy->vdd_pdphy); | |
| 470 | 470 | } |
| 471 | 471 | |
| 472 | 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 | 37 | struct device *dev = con->ucsi->dev; |
| 38 | 38 | |
| 39 | 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 | 49 | val->intval = scope; |
| 41 | 50 | return 0; |
| 42 | 51 | } |
| @@ -787,6 +787,7 @@ static void ucsi_unregister_partner(struct ucsi_connector *con) · 786 unmodified lines | ||
| 787 | 787 | |
| 788 | 788 | typec_set_mode(con->port, TYPEC_STATE_SAFE); |
| 789 | 789 | |
| 790 | + typec_partner_set_usb_power_delivery(con->partner, NULL); | |
| 790 | 791 | ucsi_unregister_partner_pdos(con); |
| 791 | 792 | ucsi_unregister_altmodes(con, UCSI_RECIPIENT_SOP); |
| 792 | 793 | typec_unregister_partner(con->partner); |
| @@ -884,6 +885,7 @@ static void ucsi_handle_connector_change(struct work_struct *work) · 91 unmodified lines | ||
| 884 | 885 | if (ret < 0) { |
| 885 | 886 | dev_err(ucsi->dev, "%s: GET_CONNECTOR_STATUS failed (%d)\n", |
| 886 | 887 | __func__, ret); |
| 888 | + clear_bit(EVENT_PENDING, &con->ucsi->flags); | |
| 887 | 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 | 123 | done += partlen; |
| 124 | 124 | len -= partlen; |
| 125 | 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 | 139 | return done; |
| 130 | 140 | } |
| @@ -33,6 +33,7 @@ · 32 unmodified lines | ||
| 33 | 33 | #include <linux/slab.h> |
| 34 | 34 | #include <linux/irqnr.h> |
| 35 | 35 | #include <linux/pci.h> |
| 36 | +#include <linux/rcupdate.h> | |
| 36 | 37 | #include <linux/spinlock.h> |
| 37 | 38 | #include <linux/cpuhotplug.h> |
| 38 | 39 | #include <linux/atomic.h> |
| @@ -96,6 +97,7 @@ enum xen_irq_type { · 57 unmodified lines | ||
| 96 | 97 | struct irq_info { |
| 97 | 98 | struct list_head list; |
| 98 | 99 | struct list_head eoi_list; |
| 100 | + struct rcu_work rwork; | |
| 99 | 101 | short refcnt; |
| 100 | 102 | u8 spurious_cnt; |
| 101 | 103 | u8 is_accounted; |
| @@ -146,23 +148,13 @@ const struct evtchn_ops *evtchn_ops; · 44 unmodified lines | ||
| 146 | 148 | */ |
| 147 | 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 | 152 | * Lock hierarchy: |
| 160 | 153 | * |
| 161 | 154 | * irq_mapping_update_lock |
| 162 | − * evtchn_rwlock | |
| 163 | − * IRQ-desc lock | |
| 164 | − * percpu eoi_list_lock | |
| 165 | − * irq_info->lock | |
| 155 | + * IRQ-desc lock | |
| 156 | + * percpu eoi_list_lock | |
| 157 | + * irq_info->lock | |
| 166 | 158 | */ |
| 167 | 159 | |
| 168 | 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 | 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 | 317 | /* Constructors for packed IRQ information. */ |
| 310 | 318 | static int xen_irq_info_common_setup(struct irq_info *info, |
| 311 | 319 | unsigned irq, |
| @@ -668,33 +676,36 @@ static void xen_irq_lateeoi_worker(struct work_struct *work) · 356 unmodified lines | ||
| 668 | 676 | |
| 669 | 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 | 681 | while (true) { |
| 674 | − spin_lock(&eoi->eoi_list_lock); | |
| 682 | + spin_lock_irqsave(&eoi->eoi_list_lock, flags); | |
| 675 | 683 | |
| 676 | 684 | info = list_first_entry_or_null(&eoi->eoi_list, struct irq_info, |
| 677 | 685 | eoi_list); |
| 678 | 686 | |
| 679 | − if (info == NULL || now < info->eoi_time) { | |
| 680 | − spin_unlock(&eoi->eoi_list_lock); | |
| 687 | + if (info == NULL) | |
| 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 | 694 | break; |
| 682 | 695 | } |
| 683 | 696 | |
| 684 | 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 | 701 | info->eoi_time = 0; |
| 689 | 702 | |
| 690 | 703 | xen_irq_lateeoi_locked(info, false); |
| 691 | 704 | } |
| 692 | 705 | |
| 693 | − if (info) | |
| 694 | − mod_delayed_work_on(info->eoi_cpu, system_wq, | |
| 695 | − &eoi->delayed, info->eoi_time - now); | |
| 706 | + spin_unlock_irqrestore(&eoi->eoi_list_lock, flags); | |
| 696 | 707 | |
| 697 | − read_unlock_irqrestore(&evtchn_rwlock, flags); | |
| 708 | + rcu_read_unlock(); | |
| 698 | 709 | } |
| 699 | 710 | |
| 700 | 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 | 720 | void xen_irq_lateeoi(unsigned int irq, unsigned int eoi_flags) |
| 710 | 721 | { |
| 711 | 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 | 726 | info = info_for_irq(irq); |
| 717 | 727 | |
| 718 | 728 | if (info) |
| 719 | 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 | 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 | 743 | info->type = IRQT_UNBOUND; |
| 734 | 744 | info->refcnt = -1; |
| 745 | + INIT_RCU_WORK(&info->rwork, delayed_free_irq); | |
| 735 | 746 | |
| 736 | 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 | 800 | static void xen_free_irq(unsigned irq) |
| 790 | 801 | { |
| 791 | 802 | struct irq_info *info = info_for_irq(irq); |
| 792 | − unsigned long flags; | |
| 793 | 803 | |
| 794 | 804 | if (WARN_ON(!info)) |
| 795 | 805 | return; |
| 796 | 806 | |
| 797 | − write_lock_irqsave(&evtchn_rwlock, flags); | |
| 798 | − | |
| 799 | 807 | if (!list_empty(&info->eoi_list)) |
| 800 | 808 | lateeoi_list_del(info); |
| 801 | 809 | |
| 802 | 810 | list_del(&info->list); |
| 803 | 811 | |
| 804 | − set_info_for_irq(irq, NULL); | |
| 805 | − | |
| 806 | 812 | WARN_ON(info->refcnt > 0); |
| 807 | 813 | |
| 808 | − write_unlock_irqrestore(&evtchn_rwlock, flags); | |
| 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); | |
| 814 | + queue_rcu_work(system_wq, &info->rwork); | |
| 817 | 815 | } |
| 818 | 816 | |
| 819 | 817 | /* Not called for lateeoi events. */ |
| @@ -1711,7 +1709,14 @@ int xen_evtchn_do_upcall(void) · 891 unmodified lines | ||
| 1711 | 1709 | int cpu = smp_processor_id(); |
| 1712 | 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 | 1721 | do { |
| 1717 | 1722 | vcpu_info->evtchn_upcall_pending = 0; |
| @@ -1724,7 +1729,7 @@ int xen_evtchn_do_upcall(void) · 6 unmodified lines | ||
| 1724 | 1729 | |
| 1725 | 1730 | } while (vcpu_info->evtchn_upcall_pending); |
| 1726 | 1731 | |
| 1727 | − read_unlock(&evtchn_rwlock); | |
| 1732 | + rcu_read_unlock(); | |
| 1728 | 1733 | |
| 1729 | 1734 | /* |
| 1730 | 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 | 682 | u64 search_start; |
| 683 | 683 | int ret; |
| 684 | 684 | |
| 685 | − if (test_bit(BTRFS_ROOT_DELETING, &root->state)) | |
| 686 | − btrfs_err(fs_info, | |
| 687 | − "COW'ing blocks on a fs root that's being dropped"); | |
| 688 | − | |
| 689 | − if (trans->transaction != fs_info->running_transaction) | |
| 690 | − WARN(1, KERN_CRIT "trans %llu running %llu\n", | |
| 691 | − trans->transid, | |
| 692 | − fs_info->running_transaction->transid); | |
| 685 | + if (unlikely(test_bit(BTRFS_ROOT_DELETING, &root->state))) { | |
| 686 | + btrfs_abort_transaction(trans, -EUCLEAN); | |
| 687 | + btrfs_crit(fs_info, | |
| 688 | + "attempt to COW block %llu on root %llu that is being deleted", | |
| 689 | + buf->start, btrfs_root_id(root)); | |
| 690 | + return -EUCLEAN; | |
| 691 | + } | |
| 693 | 692 | |
| 694 | − if (trans->transid != fs_info->generation) | |
| 695 | − WARN(1, KERN_CRIT "trans %llu running %llu\n", | |
| 696 | − trans->transid, fs_info->generation); | |
| 693 | + /* | |
| 694 | + * COWing must happen through a running transaction, which always | |
| 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 | 710 | if (!should_cow_block(trans, root, buf)) { |
| 699 | 711 | *cow_ret = buf; |
| @@ -805,8 +817,22 @@ int btrfs_realloc_node(struct btrfs_trans_handle *trans, · 105 unmodified lines | ||
| 805 | 817 | int progress_passed = 0; |
| 806 | 818 | struct btrfs_disk_key disk_key; |
| 807 | 819 | |
| 808 | − WARN_ON(trans->transaction != fs_info->running_transaction); | |
| 809 | − WARN_ON(trans->transid != fs_info->generation); | |
| 820 | + /* | |
| 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 | 837 | parent_nritems = btrfs_header_nritems(parent); |
| 812 | 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 | 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 | 317 | if (item) { |
| 318 | 318 | item->data_len = data_len; |
| 319 | 319 | item->type = type; |
| @@ -95,7 +95,7 @@ struct btrfs_delayed_item { · 94 unmodified lines | ||
| 95 | 95 | bool logged; |
| 96 | 96 | /* The maximum leaf size is 64K, so u16 is more than enough. */ |
| 97 | 97 | u16 data_len; |
| 98 | − char data[]; | |
| 98 | + char data[] __counted_by(data_len); | |
| 99 | 99 | }; |
| 100 | 100 | |
| 101 | 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 | 2978 | static long btrfs_ioctl_space_info(struct btrfs_fs_info *fs_info, |
| 2979 | 2979 | void __user *arg) |
| 2980 | 2980 | { |
| 2981 | − struct btrfs_ioctl_space_args space_args; | |
| 2981 | + struct btrfs_ioctl_space_args space_args = { 0 }; | |
| 2982 | 2982 | struct btrfs_ioctl_space_info space; |
| 2983 | 2983 | struct btrfs_ioctl_space_info *dest; |
| 2984 | 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 | 4339 | if (compat) { |
| 4340 | 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 | 4343 | ret = copy_from_user(&args32, argp, sizeof(args32)); |
| 4344 | 4344 | if (ret) |
| @@ -219,8 +219,8 @@ do { \ · 218 unmodified lines | ||
| 219 | 219 | (errno))) { \ |
| 220 | 220 | /* Stack trace printed. */ \ |
| 221 | 221 | } else { \ |
| 222 | − btrfs_debug((trans)->fs_info, \ | |
| 223 | − "Transaction aborted (error %d)", \ | |
| 222 | + btrfs_err((trans)->fs_info, \ | |
| 223 | + "Transaction aborted (error %d)", \ | |
| 224 | 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 | 460 | out: |
| 461 | 461 | fscrypt_fname_free_buffer(&_tname); |
| 462 | 462 | out_inode: |
| 463 | − if ((dir != fname->dir) && !IS_ERR(dir)) { | |
| 463 | + if (dir != fname->dir) { | |
| 464 | 464 | if ((dir->i_state & I_NEW)) |
| 465 | 465 | discard_new_inode(dir); |
| 466 | 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 | 2969 | ret = do_splice_direct(src_file, &src_off, dst_file, |
| 2970 | 2970 | &dst_off, src_objlen, flags); |
| 2971 | 2971 | /* Abort on short copies or on error */ |
| 2972 | − if (ret < src_objlen) { | |
| 2972 | + if (ret < (long)src_objlen) { | |
| 2973 | 2973 | dout("Failed partial copy (%zd)\n", ret); |
| 2974 | 2974 | goto out; |
| 2975 | 2975 | } |
| @@ -769,9 +769,7 @@ int ceph_fill_file_size(struct inode *inode, int issued, · 768 unmodified lines | ||
| 769 | 769 | ci->i_truncate_seq = truncate_seq; |
| 770 | 770 | |
| 771 | 771 | /* the MDS should have revoked these caps */ |
| 772 | − WARN_ON_ONCE(issued & (CEPH_CAP_FILE_EXCL | | |
| 773 | − CEPH_CAP_FILE_RD | | |
| 774 | − CEPH_CAP_FILE_WR | | |
| 772 | + WARN_ON_ONCE(issued & (CEPH_CAP_FILE_RD | | |
| 775 | 773 | CEPH_CAP_FILE_LAZYIO)); |
| 776 | 774 | /* |
| 777 | 775 | * If we hold relevant caps, or in the case where we're |
| @@ -217,9 +217,12 @@ again: · 216 unmodified lines | ||
| 217 | 217 | strm->buf.out_size = min_t(u32, outlen, |
| 218 | 218 | PAGE_SIZE - pageofs); |
| 219 | 219 | outlen -= strm->buf.out_size; |
| 220 | − if (!rq->out[no] && rq->fillgaps) /* deduped */ | |
| 220 | + if (!rq->out[no] && rq->fillgaps) { /* deduped */ | |
| 221 | 221 | rq->out[no] = erofs_allocpage(pagepool, |
| 222 | 222 | GFP_KERNEL | __GFP_NOFAIL); |
| 223 | + set_page_private(rq->out[no], | |
| 224 | + Z_EROFS_SHORTLIVED_PAGE); | |
| 225 | + } | |
| 223 | 226 | if (rq->out[no]) |
| 224 | 227 | strm->buf.out = kmap(rq->out[no]) + pageofs; |
| 225 | 228 | pageofs = 0; |
| @@ -235,7 +235,7 @@ static int erofs_init_device(struct erofs_buf *buf, struct super_block *sb, · 234 unmodified lines | ||
| 235 | 235 | return PTR_ERR(ptr); |
| 236 | 236 | dis = ptr + erofs_blkoff(sb, *pos); |
| 237 | 237 | |
| 238 | − if (!dif->path) { | |
| 238 | + if (!sbi->devs->flatdev && !dif->path) { | |
| 239 | 239 | if (!dis->tag[0]) { |
| 240 | 240 | erofs_err(sb, "empty device tag @ pos %llu", *pos); |
| 241 | 241 | return -EINVAL; |
| @@ -192,17 +192,19 @@ int vfs_parse_fs_string(struct fs_context *fc, const char *key, · 191 unmodified lines | ||
| 192 | 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 | 196 | * @fc: The superblock configuration to fill in. |
| 197 | 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 | − * called from the ->monolithic_mount_data() fs_context operation. | |
| 200 | + * Parse a blob of data that's in key[=val][,key[=val]]* form with a custom | |
| 201 | + * option separator callback. | |
| 201 | 202 | * |
| 202 | 203 | * Returns 0 on success or the error returned by the ->parse_option() fs_context |
| 203 | 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 | 209 | char *options = data, *key; |
| 208 | 210 | int ret = 0; |
| @@ -214,7 +216,7 @@ int generic_parse_monolithic(struct fs_context *fc, void *data) · 5 unmodified lines | ||
| 214 | 216 | if (ret) |
| 215 | 217 | return ret; |
| 216 | 218 | |
| 217 | − while ((key = strsep(&options, ",")) != NULL) { | |
| 219 | + while ((key = sep(&options)) != NULL) { | |
| 218 | 220 | if (*key) { |
| 219 | 221 | size_t v_len = 0; |
| 220 | 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 | 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 | 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 | 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 | 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 | 1210 | struct task_struct *task; |
| 1211 | 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 | 1216 | return; |
| 1215 | 1217 | |
| 1216 | 1218 | set_bit(NFS4CLNT_RUN_MANAGER, &clp->cl_state); |
| 1217 | − if (test_and_set_bit(NFS4CLNT_MANAGER_AVAILABLE, &clp->cl_state) != 0) { | |
| 1218 | − wake_up_var(&clp->cl_state); | |
| 1219 | − return; | |
| 1219 | + | |
| 1220 | + if (atomic_read(&clnt->cl_swapper)) { | |
| 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 | 1232 | __module_get(THIS_MODULE); |
| 1223 | 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 | 1245 | __func__, PTR_ERR(task)); |
| 1236 | 1246 | if (!nfs_client_init_is_complete(clp)) |
| 1237 | 1247 | nfs_mark_client_ready(clp, PTR_ERR(task)); |
| 1248 | + if (swapon) | |
| 1249 | + clear_bit(NFS4CLNT_MANAGER_AVAILABLE, &clp->cl_state); | |
| 1238 | 1250 | nfs4_clear_state_manager_bit(clp); |
| 1239 | − clear_bit(NFS4CLNT_MANAGER_AVAILABLE, &clp->cl_state); | |
| 1240 | 1251 | nfs_put_client(clp); |
| 1241 | 1252 | module_put(THIS_MODULE); |
| 1242 | 1253 | } |
| @@ -2703,6 +2714,13 @@ static void nfs4_state_manager(struct nfs_client *clp) · 1460 unmodified lines | ||
| 2703 | 2714 | nfs4_end_drain_session(clp); |
| 2704 | 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 | 2724 | if (!test_and_set_bit(NFS4CLNT_RECALL_RUNNING, &clp->cl_state)) { |
| 2707 | 2725 | if (test_and_clear_bit(NFS4CLNT_DELEGRETURN, &clp->cl_state)) { |
| 2708 | 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 | 2760 | allow_signal(SIGKILL); |
| 2743 | 2761 | again: |
| 2744 | − set_bit(NFS4CLNT_MANAGER_RUNNING, &clp->cl_state); | |
| 2745 | 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 | 2766 | wait_var_event_interruptible(&clp->cl_state, |
| 2748 | 2767 | test_bit(NFS4CLNT_RUN_MANAGER, |
| 2749 | 2768 | &clp->cl_state)); |
| 2750 | − if (atomic_read(&cl->cl_swapper) && | |
| 2751 | − test_bit(NFS4CLNT_RUN_MANAGER, &clp->cl_state)) | |
| 2769 | + if (!atomic_read(&cl->cl_swapper)) | |
| 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 | 2773 | goto again; |
| 2753 | 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 | 2778 | if (refcount_read(&clp->cl_count) > 1 && !signalled() && |
| 2758 | 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 | 2781 | goto again; |
| 2761 | 2782 | |
| 2762 | 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 | 804 | if (test_and_clear_bit(PG_INODE_REF, &req->wb_flags)) { |
| 805 | − nfs_release_request(req); | |
| 806 | 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 | 189 | /* Lower file handle for non-upper non-decodable */ |
| 190 | 190 | if (!ovl_dentry_upper(dentry) && !decodable) |
| 191 | − return 0; | |
| 191 | + return 1; | |
| 192 | 192 | |
| 193 | 193 | /* Upper file handle for pure upper */ |
| 194 | 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 | 341 | if (!aio_req) |
| 342 | 342 | goto out; |
| 343 | 343 | |
| 344 | − real.flags = 0; | |
| 345 | 344 | aio_req->orig_iocb = iocb; |
| 346 | 345 | kiocb_clone(&aio_req->iocb, iocb, get_file(real.file)); |
| 347 | 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 | 412 | if (!aio_req) |
| 414 | 413 | goto out; |
| 415 | 414 | |
| 416 | − real.flags = 0; | |
| 417 | 415 | aio_req->orig_iocb = iocb; |
| 418 | 416 | kiocb_clone(&aio_req->iocb, iocb, get_file(real.file)); |
| 419 | 417 | aio_req->iocb.ki_flags = ifl; |
| @@ -8,6 +8,7 @@ · 7 unmodified lines | ||
| 8 | 8 | struct ovl_config { |
| 9 | 9 | char *upperdir; |
| 10 | 10 | char *workdir; |
| 11 | + char **lowerdirs; | |
| 11 | 12 | bool default_permissions; |
| 12 | 13 | int redirect_mode; |
| 13 | 14 | int verity_mode; |
| @@ -39,17 +40,8 @@ struct ovl_layer { · 25 unmodified lines | ||
| 39 | 40 | int idx; |
| 40 | 41 | /* One fsid per unique underlying sb (upper fsid == 0) */ |
| 41 | 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 | 45 | struct ovl_path { |
| 54 | 46 | const struct ovl_layer *layer; |
| 55 | 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 | 188 | static ssize_t ovl_parse_param_split_lowerdirs(char *str) |
| 161 | 189 | { |
| 162 | 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 | 193 | for (s = d = str;; s++, d++) { |
| 166 | 194 | if (*s == '\\') { |
| 167 | − s++; | |
| 195 | + /* keep esc chars in split lowerdir */ | |
| 196 | + *d++ = *s++; | |
| 168 | 197 | } else if (*s == ':') { |
| 169 | 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 | 273 | int err = -ENOMEM; |
| 245 | 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 | 277 | ovl_unescape(tmp); |
| 249 | 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 | 281 | pr_err("filesystem on '%s' not supported as upperdir\n", |
| 253 | 282 | tmp); |
| 254 | 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 | 298 | struct path path; |
| 270 | 299 | char *dup; |
| 271 | 300 | |
| 272 | − err = ovl_mount_dir(name, &path); | |
| 301 | + err = ovl_mount_dir(name, &path, true); | |
| 273 | 302 | if (err) |
| 274 | 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 | 350 | * Set "/lower1", "/lower2", and "/lower3" as lower layers and |
| 322 | 351 | * "/data1" and "/data2" as data lower layers. Any existing lower |
| 323 | 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 | 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 | 371 | return 0; |
| 349 | 372 | } |
| 350 | 373 | |
| 351 | − if (strncmp(name, "::", 2) == 0) { | |
| 352 | − /* | |
| 353 | − * This is a data layer. | |
| 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; | |
| 374 | + if (*name == ':') { | |
| 375 | + pr_err("cannot append lower layer"); | |
| 376 | + return -EINVAL; | |
| 394 | 377 | } |
| 395 | 378 | |
| 396 | 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 | 455 | l = &ctx->lower[nr]; |
| 473 | 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 | 459 | if (err) |
| 477 | 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 | 667 | static const struct fs_context_operations ovl_context_ops = { |
| 668 | + .parse_monolithic = ovl_parse_monolithic, | |
| 685 | 669 | .parse_param = ovl_parse_param, |
| 686 | 670 | .get_tree = ovl_get_tree, |
| 687 | 671 | .reconfigure = ovl_reconfigure, |
| @@ -752,12 +736,12 @@ void ovl_free_fs(struct ovl_fs *ofs) · 64 unmodified lines | ||
| 752 | 736 | if (ofs->upperdir_locked) |
| 753 | 737 | ovl_inuse_unlock(ovl_upper_mnt(ofs)->mnt_root); |
| 754 | 738 | |
| 755 | − /* Hack! Reuse ofs->layers as a vfsmount array before freeing it */ | |
| 756 | − mounts = (struct vfsmount **) ofs->layers; | |
| 739 | + /* Reuse ofs->config.lowerdirs as a vfsmount array before freeing it */ | |
| 740 | + mounts = (struct vfsmount **) ofs->config.lowerdirs; | |
| 757 | 741 | for (i = 0; i < ofs->numlayer; i++) { |
| 758 | 742 | iput(ofs->layers[i].trap); |
| 743 | + kfree(ofs->config.lowerdirs[i]); | |
| 759 | 744 | mounts[i] = ofs->layers[i].mnt; |
| 760 | − kfree(ofs->layers[i].name); | |
| 761 | 745 | } |
| 762 | 746 | kern_unmount_array(mounts, ofs->numlayer); |
| 763 | 747 | kfree(ofs->layers); |
| @@ -765,6 +749,7 @@ void ovl_free_fs(struct ovl_fs *ofs) · 1 unmodified line | ||
| 765 | 749 | free_anon_bdev(ofs->fs[i].pseudo_dev); |
| 766 | 750 | kfree(ofs->fs); |
| 767 | 751 | |
| 752 | + kfree(ofs->config.lowerdirs); | |
| 768 | 753 | kfree(ofs->config.upperdir); |
| 769 | 754 | kfree(ofs->config.workdir); |
| 770 | 755 | if (ofs->creator_cred) |
| @@ -949,16 +934,23 @@ int ovl_show_options(struct seq_file *m, struct dentry *dentry) · 178 unmodified lines | ||
| 949 | 934 | struct super_block *sb = dentry->d_sb; |
| 950 | 935 | struct ovl_fs *ofs = OVL_FS(sb); |
| 951 | 936 | size_t nr, nr_merged_lower = ofs->numlayer - ofs->numdatalayer; |
| 952 | − const struct ovl_layer *data_layers = &ofs->layers[nr_merged_lower]; | |
| 953 | − | |
| 954 | − /* ofs->layers[0] is the upper layer */ | |
| 955 | − seq_printf(m, ",lowerdir=%s", ofs->layers[1].name); | |
| 956 | − /* dump regular lower layers */ | |
| 957 | − for (nr = 2; nr < nr_merged_lower; nr++) | |
| 958 | − seq_printf(m, ":%s", ofs->layers[nr].name); | |
| 959 | − /* dump data lower layers */ | |
| 960 | − for (nr = 0; nr < ofs->numdatalayer; nr++) | |
| 961 | − seq_printf(m, "::%s", data_layers[nr].name); | |
| 937 | + | |
| 938 | + /* | |
| 939 | + * lowerdirs[] starts from offset 1, then | |
| 940 | + * >= 0 regular lower layers prefixed with : and | |
| 941 | + * >= 0 data-only lower layers prefixed with :: | |
| 942 | + * | |
| 943 | + * we need to escase comma and space like seq_show_option() does and | |
| 944 | + * we also need to escape the colon separator from lowerdir paths. | |
| 945 | + */ | |
| 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 | 954 | if (ofs->config.upperdir) { |
| 963 | 955 | seq_show_option(m, "upperdir", ofs->config.upperdir); |
| 964 | 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 | 104 | static int ovl_dentry_revalidate_common(struct dentry *dentry, |
| 105 | 105 | unsigned int flags, bool weak) |
| 106 | 106 | { |
| 107 | − struct ovl_entry *oe = OVL_E(dentry); | |
| 108 | − struct ovl_path *lowerstack = ovl_lowerstack(oe); | |
| 107 | + struct ovl_entry *oe; | |
| 108 | + struct ovl_path *lowerstack; | |
| 109 | 109 | struct inode *inode = d_inode_rcu(dentry); |
| 110 | 110 | struct dentry *upper; |
| 111 | 111 | unsigned int i; |
| @@ -115,6 +115,8 @@ static int ovl_dentry_revalidate_common(struct dentry *dentry, · 3 unmodified lines | ||
| 115 | 115 | if (!inode) |
| 116 | 116 | return -ECHILD; |
| 117 | 117 | |
| 118 | + oe = OVL_I_E(inode); | |
| 119 | + lowerstack = ovl_lowerstack(oe); | |
| 118 | 120 | upper = ovl_i_dentry_upper(inode); |
| 119 | 121 | if (upper) |
| 120 | 122 | ret = ovl_revalidate_real(upper, flags, weak); |
| @@ -167,6 +169,7 @@ static void ovl_free_inode(struct inode *inode) · 46 unmodified lines | ||
| 167 | 169 | struct ovl_inode *oi = OVL_I(inode); |
| 168 | 170 | |
| 169 | 171 | kfree(oi->redirect); |
| 172 | + kfree(oi->oe); | |
| 170 | 173 | mutex_destroy(&oi->lock); |
| 171 | 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 | 179 | struct ovl_inode *oi = OVL_I(inode); |
| 177 | 180 | |
| 178 | 181 | dput(oi->__upperdentry); |
| 179 | − ovl_free_entry(oi->oe); | |
| 182 | + ovl_stack_put(ovl_lowerstack(oi->oe), ovl_numlower(oi->oe)); | |
| 180 | 183 | if (S_ISDIR(inode->i_mode)) |
| 181 | 184 | ovl_dir_cache_free(inode); |
| 182 | 185 | else |
| @@ -569,11 +572,6 @@ static int ovl_get_upper(struct super_block *sb, struct ovl_fs *ofs, · 386 unmodified lines | ||
| 569 | 572 | upper_layer->idx = 0; |
| 570 | 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 | 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 | 1120 | layers[ofs->numlayer].idx = ofs->numlayer; |
| 1123 | 1121 | layers[ofs->numlayer].fsid = fsid; |
| 1124 | 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 | 1125 | l->name = NULL; |
| 1127 | 1126 | ofs->numlayer++; |
| 1128 | 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 | 1366 | if (!layers) |
| 1368 | 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 | 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 | 1379 | ofs->numlayer = 1; |
| 1373 | 1380 | |
| 1374 | 1381 | sb->s_stack_depth = 0; |
| @@ -233,19 +233,18 @@ static void put_quota_format(struct quota_format_type *fmt) · 232 unmodified lines | ||
| 233 | 233 | * All dquots are placed to the end of inuse_list when first created, and this |
| 234 | 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 | |
| 237 | − * added to releasing_dquots. We'd then queue work item which would call | |
| 236 | + * When the last reference of a dquot is dropped, the dquot is added to | |
| 237 | + * releasing_dquots. We'll then queue work item which will call | |
| 238 | 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 | |
| 240 | − * dq_free list_head in the dquot struct. When a dquot is removed from | |
| 241 | − * releasing_dquots, a reference count is always subtracted, and if | |
| 242 | − * dq_count == 0 at that point, the dquot will be added to the free_dquots. | |
| 239 | + * dquots on the list. Each cleaned up dquot is moved to free_dquots list. | |
| 240 | + * Both releasing_dquots and free_dquots use the dq_free list_head in the dquot | |
| 241 | + * struct. | |
| 243 | 242 | * |
| 244 | − * Unused dquots (dq_count == 0) are added to the free_dquots list when freed, | |
| 245 | − * and this list is searched whenever we need an available dquot. Dquots are | |
| 246 | − * removed from the list as soon as they are used again, and | |
| 247 | − * dqstats.free_dquots gives the number of dquots on the list. When | |
| 248 | − * dquot is invalidated it's completely released from memory. | |
| 243 | + * Unused and cleaned up dquots are in the free_dquots list and this list is | |
| 244 | + * searched whenever we need an available dquot. Dquots are removed from the | |
| 245 | + * list as soon as they are used again and dqstats.free_dquots gives the number | |
| 246 | + * of dquots on the list. When dquot is invalidated it's completely released | |
| 247 | + * from memory. | |
| 249 | 248 | * |
| 250 | 249 | * Dirty dquots are added to the dqi_dirty_list of quota_info when mark |
| 251 | 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 | 320 | static inline void put_releasing_dquots(struct dquot *dquot) |
| 322 | 321 | { |
| 323 | 322 | list_add_tail(&dquot->dq_free, &releasing_dquots); |
| 323 | + set_bit(DQ_RELEASING_B, &dquot->dq_flags); | |
| 324 | 324 | } |
| 325 | 325 | |
| 326 | 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 | 328 | if (list_empty(&dquot->dq_free)) |
| 329 | 329 | return; |
| 330 | 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 | 332 | dqstats_dec(DQST_FREE_DQUOTS); |
| 333 | + else | |
| 334 | + clear_bit(DQ_RELEASING_B, &dquot->dq_flags); | |
| 333 | 335 | } |
| 334 | 336 | |
| 335 | 337 | static inline void put_inuse(struct dquot *dquot) |
| @@ -581,12 +583,6 @@ restart: · 245 unmodified lines | ||
| 581 | 583 | continue; |
| 582 | 584 | /* Wait for dquot users */ |
| 583 | 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 | 586 | atomic_inc(&dquot->dq_count); |
| 591 | 587 | spin_unlock(&dq_list_lock); |
| 592 | 588 | /* |
| @@ -605,6 +601,15 @@ restart: · 12 unmodified lines | ||
| 605 | 601 | * restart. */ |
| 606 | 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 | 614 | * Quota now has no users and it has been written on last |
| 610 | 615 | * dqput() |
| @@ -696,6 +701,13 @@ int dquot_writeback_dquots(struct super_block *sb, int type) · 85 unmodified lines | ||
| 696 | 701 | dq_dirty); |
| 697 | 702 | |
| 698 | 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 | 712 | /* Now we have active dquot from which someone is |
| 701 | 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 | 821 | /* Exchange the list head to avoid livelock. */ |
| 810 | 822 | list_replace_init(&releasing_dquots, &rls_head); |
| 811 | 823 | spin_unlock(&dq_list_lock); |
| 824 | + synchronize_srcu(&dquot_srcu); | |
| 812 | 825 | |
| 813 | 826 | restart: |
| 814 | − synchronize_srcu(&dquot_srcu); | |
| 815 | 827 | spin_lock(&dq_list_lock); |
| 816 | 828 | while (!list_empty(&rls_head)) { |
| 817 | 829 | dquot = list_first_entry(&rls_head, struct dquot, dq_free); |
| 818 | − /* Dquot got used again? */ | |
| 819 | − if (atomic_read(&dquot->dq_count) > 1) { | |
| 820 | − remove_free_dquot(dquot); | |
| 821 | − atomic_dec(&dquot->dq_count); | |
| 822 | − continue; | |
| 823 | − } | |
| 830 | + WARN_ON_ONCE(atomic_read(&dquot->dq_count)); | |
| 831 | + /* | |
| 832 | + * Note that DQ_RELEASING_B protects us from racing with | |
| 833 | + * invalidate_dquots() calls so we are safe to work with the | |
| 834 | + * dquot even after we drop dq_list_lock. | |
| 835 | + */ | |
| 824 | 836 | if (dquot_dirty(dquot)) { |
| 825 | 837 | spin_unlock(&dq_list_lock); |
| 826 | 838 | /* Commit dquot before releasing */ |
| @@ -834,7 +846,6 @@ restart: · 7 unmodified lines | ||
| 834 | 846 | } |
| 835 | 847 | /* Dquot is inactive and clean, now move it to free list */ |
| 836 | 848 | remove_free_dquot(dquot); |
| 837 | − atomic_dec(&dquot->dq_count); | |
| 838 | 849 | put_dquot_last(dquot); |
| 839 | 850 | } |
| 840 | 851 | spin_unlock(&dq_list_lock); |
| @@ -875,6 +886,7 @@ void dqput(struct dquot *dquot) · 34 unmodified lines | ||
| 875 | 886 | BUG_ON(!list_empty(&dquot->dq_free)); |
| 876 | 887 | #endif |
| 877 | 888 | put_releasing_dquots(dquot); |
| 889 | + atomic_dec(&dquot->dq_count); | |
| 878 | 890 | spin_unlock(&dq_list_lock); |
| 879 | 891 | queue_delayed_work(system_unbound_wq, "a_release_work, 1); |
| 880 | 892 | } |
| @@ -963,7 +975,7 @@ we_slept: · 82 unmodified lines | ||
| 963 | 975 | dqstats_inc(DQST_LOOKUPS); |
| 964 | 976 | } |
| 965 | 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 | 979 | wait_on_dquot(dquot); |
| 968 | 980 | /* Read the dquot / allocate space in quota file */ |
| 969 | 981 | if (!dquot_active(dquot)) { |
| @@ -15,6 +15,7 @@ · 14 unmodified lines | ||
| 15 | 15 | static struct cached_fid *init_cached_dir(const char *path); |
| 16 | 16 | static void free_cached_dir(struct cached_fid *cfid); |
| 17 | 17 | static void smb2_close_cached_fid(struct kref *ref); |
| 18 | +static void cfids_laundromat_worker(struct work_struct *work); | |
| 18 | 19 | |
| 19 | 20 | static struct cached_fid *find_or_create_cached_dir(struct cached_fids *cfids, |
| 20 | 21 | const char *path, |
| @@ -169,15 +170,18 @@ int open_cached_dir(unsigned int xid, struct cifs_tcon *tcon, · 148 unmodified lines | ||
| 169 | 170 | return -ENOENT; |
| 170 | 171 | } |
| 171 | 172 | /* |
| 172 | − * At this point we either have a lease already and we can just | |
| 173 | − * return it. If not we are guaranteed to be the only thread accessing | |
| 174 | − * this cfid. | |
| 173 | + * Return cached fid if it has a lease. Otherwise, it is either a new | |
| 174 | + * entry or laundromat worker removed it from @cfids->entries. Caller | |
| 175 | + * will put last reference if the latter. | |
| 175 | 176 | */ |
| 177 | + spin_lock(&cfids->cfid_list_lock); | |
| 176 | 178 | if (cfid->has_lease) { |
| 179 | + spin_unlock(&cfids->cfid_list_lock); | |
| 177 | 180 | *ret_cfid = cfid; |
| 178 | 181 | kfree(utf16_path); |
| 179 | 182 | return 0; |
| 180 | 183 | } |
| 184 | + spin_unlock(&cfids->cfid_list_lock); | |
| 181 | 185 | |
| 182 | 186 | /* |
| 183 | 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 | 298 | goto oshr_free; |
| 295 | 299 | } |
| 296 | 300 | } |
| 301 | + spin_lock(&cfids->cfid_list_lock); | |
| 297 | 302 | cfid->dentry = dentry; |
| 298 | 303 | cfid->time = jiffies; |
| 299 | 304 | cfid->has_lease = true; |
| 305 | + spin_unlock(&cfids->cfid_list_lock); | |
| 300 | 306 | |
| 301 | 307 | oshr_free: |
| 302 | 308 | kfree(utf16_path); |
| @@ -305,24 +311,28 @@ oshr_free: · 2 unmodified lines | ||
| 305 | 311 | free_rsp_buf(resp_buftype[0], rsp_iov[0].iov_base); |
| 306 | 312 | free_rsp_buf(resp_buftype[1], rsp_iov[1].iov_base); |
| 307 | 313 | spin_lock(&cfids->cfid_list_lock); |
| 308 | − if (rc && !cfid->has_lease) { | |
| 309 | − if (cfid->on_list) { | |
| 310 | − list_del(&cfid->entry); | |
| 311 | − cfid->on_list = false; | |
| 312 | − cfids->num_entries--; | |
| 314 | + if (!cfid->has_lease) { | |
| 315 | + if (rc) { | |
| 316 | + if (cfid->on_list) { | |
| 317 | + list_del(&cfid->entry); | |
| 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 | 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 | 336 | if (rc) { |
| 327 | 337 | if (cfid->is_open) |
| 328 | 338 | SMB2_close(0, cfid->tcon, cfid->fid.persistent_fid, |
| @@ -330,7 +340,7 @@ oshr_free: · 1 unmodified line | ||
| 330 | 340 | free_cached_dir(cfid); |
| 331 | 341 | cfid = NULL; |
| 332 | 342 | } |
| 333 | − | |
| 343 | +out: | |
| 334 | 344 | if (rc == 0) { |
| 335 | 345 | *ret_cfid = cfid; |
| 336 | 346 | atomic_inc(&tcon->num_remote_opens); |
| @@ -572,53 +582,51 @@ static void free_cached_dir(struct cached_fid *cfid) · 235 unmodified lines | ||
| 572 | 582 | kfree(cfid); |
| 573 | 583 | } |
| 574 | 584 | |
| 575 | −static int | |
| 576 | −cifs_cfids_laundromat_thread(void *p) | |
| 585 | +static void cfids_laundromat_worker(struct work_struct *work) | |
| 577 | 586 | { |
| 578 | − struct cached_fids *cfids = p; | |
| 587 | + struct cached_fids *cfids; | |
| 579 | 588 | struct cached_fid *cfid, *q; |
| 580 | − struct list_head entry; | |
| 589 | + LIST_HEAD(entry); | |
| 581 | 590 | |
| 582 | − while (!kthread_should_stop()) { | |
| 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); | |
| 591 | + cfids = container_of(work, struct cached_fids, laundromat_work.work); | |
| 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 | 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 | |
| 602 | − * case we are racing with it. | |
| 615 | + * Our lease has not yet been cancelled from the server | |
| 616 | + * so we need to drop the reference. | |
| 603 | 617 | */ |
| 604 | − cancel_work_sync(&cfid->lease_break); | |
| 605 | − if (cfid->has_lease) { | |
| 606 | − /* | |
| 607 | − * We lease has not yet been cancelled from | |
| 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 | − } | |
| 618 | + spin_lock(&cfids->cfid_list_lock); | |
| 619 | + cfid->has_lease = false; | |
| 620 | + spin_unlock(&cfids->cfid_list_lock); | |
| 621 | + kref_put(&cfid->refcount, smb2_close_cached_fid); | |
| 615 | 622 | } |
| 623 | + /* Drop the extra reference opened above */ | |
| 624 | + kref_put(&cfid->refcount, smb2_close_cached_fid); | |
| 616 | 625 | } |
| 617 | − | |
| 618 | − return 0; | |
| 626 | + queue_delayed_work(cifsiod_wq, &cfids->laundromat_work, | |
| 627 | + dir_cache_timeout * HZ); | |
| 619 | 628 | } |
| 620 | 629 | |
| 621 | − | |
| 622 | 630 | struct cached_fids *init_cached_dirs(void) |
| 623 | 631 | { |
| 624 | 632 | struct cached_fids *cfids; |
| @@ -629,19 +637,10 @@ struct cached_fids *init_cached_dirs(void) · 4 unmodified lines | ||
| 629 | 637 | spin_lock_init(&cfids->cfid_list_lock); |
| 630 | 638 | INIT_LIST_HEAD(&cfids->entries); |
| 631 | 639 | |
| 632 | − /* | |
| 633 | − * since we're in a cifs function already, we know that | |
| 634 | − * this will succeed. No need for try_module_get(). | |
| 635 | − */ | |
| 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 | − } | |
| 640 | + INIT_DELAYED_WORK(&cfids->laundromat_work, cfids_laundromat_worker); | |
| 641 | + queue_delayed_work(cifsiod_wq, &cfids->laundromat_work, | |
| 642 | + dir_cache_timeout * HZ); | |
| 643 | + | |
| 645 | 644 | return cfids; |
| 646 | 645 | } |
| 647 | 646 | |
| @@ -657,11 +656,7 @@ void free_cached_dirs(struct cached_fids *cfids) · 9 unmodified lines | ||
| 657 | 656 | if (cfids == NULL) |
| 658 | 657 | return; |
| 659 | 658 | |
| 660 | − if (cfids->laundromat) { | |
| 661 | − kthread_stop(cfids->laundromat); | |
| 662 | − cfids->laundromat = NULL; | |
| 663 | − module_put(THIS_MODULE); | |
| 664 | − } | |
| 659 | + cancel_delayed_work_sync(&cfids->laundromat_work); | |
| 665 | 660 | |
| 666 | 661 | spin_lock(&cfids->cfid_list_lock); |
| 667 | 662 | list_for_each_entry_safe(cfid, q, &cfids->entries, entry) { |
| @@ -57,7 +57,7 @@ struct cached_fids { · 56 unmodified lines | ||
| 57 | 57 | spinlock_t cfid_list_lock; |
| 58 | 58 | int num_entries; |
| 59 | 59 | struct list_head entries; |
| 60 | − struct task_struct *laundromat; | |
| 60 | + struct delayed_work laundromat_work; | |
| 61 | 61 | }; |
| 62 | 62 | |
| 63 | 63 | extern struct cached_fids *init_cached_dirs(void); |
| @@ -2474,8 +2474,9 @@ cifs_put_tcon(struct cifs_tcon *tcon) · 2473 unmodified lines | ||
| 2474 | 2474 | static struct cifs_tcon * |
| 2475 | 2475 | cifs_get_tcon(struct cifs_ses *ses, struct smb3_fs_context *ctx) |
| 2476 | 2476 | { |
| 2477 | − int rc, xid; | |
| 2478 | 2477 | struct cifs_tcon *tcon; |
| 2478 | + bool nohandlecache; | |
| 2479 | + int rc, xid; | |
| 2479 | 2480 | |
| 2480 | 2481 | tcon = cifs_find_tcon(ses, ctx); |
| 2481 | 2482 | if (tcon) { |
| @@ -2493,14 +2494,17 @@ cifs_get_tcon(struct cifs_ses *ses, struct smb3_fs_context *ctx) · 11 unmodified lines | ||
| 2493 | 2494 | goto out_fail; |
| 2494 | 2495 | } |
| 2495 | 2496 | |
| 2496 | − if (ses->server->capabilities & SMB2_GLOBAL_CAP_DIRECTORY_LEASING) | |
| 2497 | − tcon = tcon_info_alloc(true); | |
| 2497 | + if (ses->server->dialect >= SMB20_PROT_ID && | |
| 2498 | + (ses->server->capabilities & SMB2_GLOBAL_CAP_DIRECTORY_LEASING)) | |
| 2499 | + nohandlecache = ctx->nohandlecache; | |
| 2498 | 2500 | else |
| 2499 | − tcon = tcon_info_alloc(false); | |
| 2501 | + nohandlecache = true; | |
| 2502 | + tcon = tcon_info_alloc(!nohandlecache); | |
| 2500 | 2503 | if (tcon == NULL) { |
| 2501 | 2504 | rc = -ENOMEM; |
| 2502 | 2505 | goto out_fail; |
| 2503 | 2506 | } |
| 2507 | + tcon->nohandlecache = nohandlecache; | |
| 2504 | 2508 | |
| 2505 | 2509 | if (ctx->snapshot_time) { |
| 2506 | 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 | 2666 | tcon->nocase = ctx->nocase; |
| 2663 | 2667 | tcon->broken_sparse_sup = ctx->no_sparse; |
| 2664 | 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 | 2669 | tcon->nodelete = ctx->nodelete; |
| 2670 | 2670 | tcon->local_lease = ctx->local_lease; |
| 2671 | 2671 | INIT_LIST_HEAD(&tcon->pending_opens); |
| @@ -2895,9 +2895,9 @@ bind_socket(struct TCP_Server_Info *server) · 223 unmodified lines | ||
| 2895 | 2895 | if (server->srcaddr.ss_family != AF_UNSPEC) { |
| 2896 | 2896 | /* Bind to the specified local IP address */ |
| 2897 | 2897 | struct socket *socket = server->ssocket; |
| 2898 | − rc = socket->ops->bind(socket, | |
| 2899 | − (struct sockaddr *) &server->srcaddr, | |
| 2900 | − sizeof(server->srcaddr)); | |
| 2898 | + rc = kernel_bind(socket, | |
| 2899 | + (struct sockaddr *) &server->srcaddr, | |
| 2900 | + sizeof(server->srcaddr)); | |
| 2901 | 2901 | if (rc < 0) { |
| 2902 | 2902 | struct sockaddr_in *saddr4; |
| 2903 | 2903 | struct sockaddr_in6 *saddr6; |
| @@ -3046,8 +3046,8 @@ generic_ip_connect(struct TCP_Server_Info *server) · 142 unmodified lines | ||
| 3046 | 3046 | socket->sk->sk_sndbuf, |
| 3047 | 3047 | socket->sk->sk_rcvbuf, socket->sk->sk_rcvtimeo); |
| 3048 | 3048 | |
| 3049 | − rc = socket->ops->connect(socket, saddr, slen, | |
| 3050 | − server->noblockcnt ? O_NONBLOCK : 0); | |
| 3049 | + rc = kernel_connect(socket, saddr, slen, | |
| 3050 | + server->noblockcnt ? O_NONBLOCK : 0); | |
| 3051 | 3051 | /* |
| 3052 | 3052 | * When mounting SMB root file systems, we do not want to block in |
| 3053 | 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 | 84 | spin_lock_init(&conn->llist_lock); |
| 85 | 85 | INIT_LIST_HEAD(&conn->lock_list); |
| 86 | 86 | |
| 87 | + init_rwsem(&conn->session_lock); | |
| 88 | + | |
| 87 | 89 | down_write(&conn_list_lock); |
| 88 | 90 | list_add(&conn->conns_list, &conn_list); |
| 89 | 91 | up_write(&conn_list_lock); |
| @@ -50,6 +50,7 @@ struct ksmbd_conn { · 49 unmodified lines | ||
| 50 | 50 | struct nls_table *local_nls; |
| 51 | 51 | struct unicode_map *um; |
| 52 | 52 | struct list_head conns_list; |
| 53 | + struct rw_semaphore session_lock; | |
| 53 | 54 | /* smb session 1 per user */ |
| 54 | 55 | struct xarray sessions; |
| 55 | 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 | 74 | tree_conn->user = sess->user; |
| 75 | 75 | tree_conn->share_conf = sc; |
| 76 | + tree_conn->t_state = TREE_NEW; | |
| 76 | 77 | status.tree_conn = tree_conn; |
| 78 | + atomic_set(&tree_conn->refcount, 1); | |
| 79 | + init_waitqueue_head(&tree_conn->refcount_q); | |
| 77 | 80 | |
| 78 | 81 | ret = xa_err(xa_store(&sess->tree_conns, tree_conn->id, tree_conn, |
| 79 | 82 | GFP_KERNEL)); |
| @@ -93,14 +96,33 @@ out_error: · 13 unmodified lines | ||
| 93 | 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 | 111 | int ksmbd_tree_conn_disconnect(struct ksmbd_session *sess, |
| 97 | 112 | struct ksmbd_tree_connect *tree_conn) |
| 98 | 113 | { |
| 99 | 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 | 124 | ret = ksmbd_ipc_tree_disconnect_request(sess->id, tree_conn->id); |
| 102 | 125 | ksmbd_release_tree_conn_id(sess, tree_conn->id); |
| 103 | − xa_erase(&sess->tree_conns, tree_conn->id); | |
| 104 | 126 | ksmbd_share_config_put(tree_conn->share_conf); |
| 105 | 127 | kfree(tree_conn); |
| 106 | 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 | 134 | struct ksmbd_tree_connect *tcon; |
| 113 | 135 | |
| 136 | + read_lock(&sess->tree_conns_lock); | |
| 114 | 137 | tcon = xa_load(&sess->tree_conns, id); |
| 115 | 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 | 142 | tcon = NULL; |
| 118 | 143 | } |
| 144 | + read_unlock(&sess->tree_conns_lock); | |
| 119 | 145 | |
| 120 | 146 | return tcon; |
| 121 | 147 | } |
| @@ -129,8 +155,18 @@ int ksmbd_tree_conn_session_logoff(struct ksmbd_session *sess) · 7 unmodified lines | ||
| 129 | 155 | if (!sess) |
| 130 | 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 | 168 | ret |= ksmbd_tree_conn_disconnect(sess, tc); |
| 169 | + } | |
| 134 | 170 | xa_destroy(&sess->tree_conns); |
| 135 | 171 | return ret; |
| 136 | 172 | } |
| @@ -14,7 +14,11 @@ struct ksmbd_share_config; · 13 unmodified lines | ||
| 14 | 14 | struct ksmbd_user; |
| 15 | 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 | 23 | struct ksmbd_tree_connect { |
| 20 | 24 | int id; |
| @@ -27,7 +31,9 @@ struct ksmbd_tree_connect { · 6 unmodified lines | ||
| 27 | 31 | |
| 28 | 32 | int maximal_access; |
| 29 | 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 | 39 | struct ksmbd_tree_conn_status { |
| @@ -46,6 +52,7 @@ struct ksmbd_session; · 12 unmodified lines | ||
| 46 | 52 | struct ksmbd_tree_conn_status |
| 47 | 53 | ksmbd_tree_conn_connect(struct ksmbd_conn *conn, struct ksmbd_session *sess, |
| 48 | 54 | const char *share_name); |
| 55 | +void ksmbd_tree_connect_put(struct ksmbd_tree_connect *tcon); | |
| 49 | 56 | |
| 50 | 57 | int ksmbd_tree_conn_disconnect(struct ksmbd_session *sess, |
| 51 | 58 | struct ksmbd_tree_connect *tree_conn); |
| @@ -174,7 +174,7 @@ static void ksmbd_expire_session(struct ksmbd_conn *conn) · 173 unmodified lines | ||
| 174 | 174 | unsigned long id; |
| 175 | 175 | struct ksmbd_session *sess; |
| 176 | 176 | |
| 177 | − down_write(&sessions_table_lock); | |
| 177 | + down_write(&conn->session_lock); | |
| 178 | 178 | xa_for_each(&conn->sessions, id, sess) { |
| 179 | 179 | if (sess->state != SMB2_SESSION_VALID || |
| 180 | 180 | time_after(jiffies, |
| @@ -185,7 +185,7 @@ static void ksmbd_expire_session(struct ksmbd_conn *conn) · 4 unmodified lines | ||
| 185 | 185 | continue; |
| 186 | 186 | } |
| 187 | 187 | } |
| 188 | − up_write(&sessions_table_lock); | |
| 188 | + up_write(&conn->session_lock); | |
| 189 | 189 | } |
| 190 | 190 | |
| 191 | 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 | 233 | xa_for_each(&conn->sessions, id, sess) { |
| 232 | 234 | unsigned long chann_id; |
| 233 | 235 | struct channel *chann; |
| @@ -244,7 +246,7 @@ void ksmbd_sessions_deregister(struct ksmbd_conn *conn) · 10 unmodified lines | ||
| 244 | 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 | 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 | 255 | struct ksmbd_session *sess; |
| 254 | 256 | |
| 257 | + down_read(&conn->session_lock); | |
| 255 | 258 | sess = xa_load(&conn->sessions, id); |
| 256 | 259 | if (sess) |
| 257 | 260 | sess->last_active = jiffies; |
| 261 | + up_read(&conn->session_lock); | |
| 258 | 262 | return sess; |
| 259 | 263 | } |
| 260 | 264 | |
| @@ -351,6 +355,7 @@ static struct ksmbd_session *__session_create(int protocol) · 90 unmodified lines | ||
| 351 | 355 | xa_init(&sess->ksmbd_chann_list); |
| 352 | 356 | xa_init(&sess->rpc_handle_list); |
| 353 | 357 | sess->sequence_number = 1; |
| 358 | + rwlock_init(&sess->tree_conns_lock); | |
| 354 | 359 | |
| 355 | 360 | ret = __init_smb2_session(sess); |
| 356 | 361 | if (ret) |
| @@ -60,6 +60,7 @@ struct ksmbd_session { · 59 unmodified lines | ||
| 60 | 60 | |
| 61 | 61 | struct ksmbd_file_table file_table; |
| 62 | 62 | unsigned long last_active; |
| 63 | + rwlock_t tree_conns_lock; | |
| 63 | 64 | }; |
| 64 | 65 | |
| 65 | 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 | 241 | } while (is_chained == true); |
| 242 | 242 | |
| 243 | 243 | send: |
| 244 | + if (work->tcon) | |
| 245 | + ksmbd_tree_connect_put(work->tcon); | |
| 244 | 246 | smb3_preauth_hash_rsp(work); |
| 245 | 247 | if (work->sess && work->sess->enc && work->encrypted && |
| 246 | 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 | 232 | struct smb2_hdr *rsp_hdr; |
| 233 | 233 | |
| 234 | − if (work->next_smb2_rcv_hdr_off) | |
| 235 | − rsp_hdr = ksmbd_resp_buf_next(work); | |
| 236 | − else | |
| 237 | − rsp_hdr = smb2_get_msg(work->response_buf); | |
| 234 | + rsp_hdr = smb2_get_msg(work->response_buf); | |
| 238 | 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 | 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 | 1994 | if (conn->posix_ext_supported) |
| 1994 | 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 | 2000 | rsp->StructureSize = cpu_to_le16(16); |
| 1997 | 2001 | out_err1: |
| 1998 | 2002 | rsp->Capabilities = 0; |
| @@ -2122,27 +2126,50 @@ int smb2_tree_disconnect(struct ksmbd_work *work) · 123 unmodified lines | ||
| 2122 | 2126 | |
| 2123 | 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 | 2159 | rsp->StructureSize = cpu_to_le16(4); |
| 2126 | 2160 | err = ksmbd_iov_pin_rsp(work, rsp, |
| 2127 | 2161 | sizeof(struct smb2_tree_disconnect_rsp)); |
| 2128 | 2162 | if (err) { |
| 2129 | 2163 | rsp->hdr.Status = STATUS_INSUFFICIENT_RESOURCES; |
| 2130 | − smb2_set_err_rsp(work); | |
| 2131 | − return err; | |
| 2164 | + goto err_out; | |
| 2132 | 2165 | } |
| 2133 | 2166 | |
| 2134 | − if (!tcon || test_and_set_bit(TREE_CONN_EXPIRE, &tcon->status)) { | |
| 2135 | − ksmbd_debug(SMB, "Invalid tid %d\n", req->hdr.Id.SyncId.TreeId); | |
| 2167 | + return 0; | |
| 2136 | 2168 | |
| 2137 | − rsp->hdr.Status = STATUS_NETWORK_NAME_DELETED; | |
| 2138 | − smb2_set_err_rsp(work); | |
| 2139 | − return -ENOENT; | |
| 2140 | − } | |
| 2169 | +err_out: | |
| 2170 | + smb2_set_err_rsp(work); | |
| 2171 | + return err; | |
| 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 | 2192 | ksmbd_debug(SMB, "request\n"); |
| 2166 | 2193 | |
| 2167 | − sess_id = le64_to_cpu(req->hdr.SessionId); | |
| 2168 | − | |
| 2169 | − rsp->StructureSize = cpu_to_le16(4); | |
| 2170 | − err = ksmbd_iov_pin_rsp(work, rsp, sizeof(struct smb2_logoff_rsp)); | |
| 2171 | − if (err) { | |
| 2172 | − rsp->hdr.Status = STATUS_INSUFFICIENT_RESOURCES; | |
| 2194 | + ksmbd_conn_lock(conn); | |
| 2195 | + if (!ksmbd_conn_good(conn)) { | |
| 2196 | + ksmbd_conn_unlock(conn); | |
| 2197 | + rsp->hdr.Status = STATUS_NETWORK_NAME_DELETED; | |
| 2173 | 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 | 2202 | ksmbd_all_conn_set_status(sess_id, KSMBD_SESS_NEED_RECONNECT); |
| 2203 | + ksmbd_conn_unlock(conn); | |
| 2204 | + | |
| 2178 | 2205 | ksmbd_close_session_fds(work); |
| 2179 | 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 | 2223 | ksmbd_free_user(sess->user); |
| 2197 | 2224 | sess->user = NULL; |
| 2198 | 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 | 2234 | return 0; |
| 2200 | 2235 | } |
| 2201 | 2236 | |
| @@ -3370,8 +3405,10 @@ err_out: · 1168 unmodified lines | ||
| 3370 | 3405 | } |
| 3371 | 3406 | ksmbd_revert_fsids(work); |
| 3372 | 3407 | err_out1: |
| 3373 | − if (!rc) | |
| 3408 | + if (!rc) { | |
| 3409 | + ksmbd_update_fstate(&work->sess->file_table, fp, FP_INITED); | |
| 3374 | 3410 | rc = ksmbd_iov_pin_rsp(work, (void *)rsp, iov_len); |
| 3411 | + } | |
| 3375 | 3412 | if (rc) { |
| 3376 | 3413 | if (rc == -EINVAL) |
| 3377 | 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 | 6152 | memcpy(aux_payload_buf, rpc_resp->payload, rpc_resp->payload_sz); |
| 6116 | 6153 | |
| 6117 | 6154 | nbytes = rpc_resp->payload_sz; |
| 6118 | − kvfree(rpc_resp); | |
| 6119 | 6155 | err = ksmbd_iov_pin_rsp_read(work, (void *)rsp, |
| 6120 | 6156 | offsetof(struct smb2_read_rsp, Buffer), |
| 6121 | 6157 | aux_payload_buf, nbytes); |
| 6122 | 6158 | if (err) |
| 6123 | 6159 | goto out; |
| 6160 | + kvfree(rpc_resp); | |
| 6124 | 6161 | } else { |
| 6125 | 6162 | err = ksmbd_iov_pin_rsp(work, (void *)rsp, |
| 6126 | 6163 | offsetof(struct smb2_read_rsp, Buffer)); |
| @@ -7028,10 +7065,6 @@ skip: · 901 unmodified lines | ||
| 7028 | 7065 | |
| 7029 | 7066 | ksmbd_debug(SMB, |
| 7030 | 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 | 7068 | list_add(&smb_lock->llist, &rollback_list); |
| 7036 | 7069 | |
| 7037 | 7070 | argv = kmalloc(sizeof(void *), GFP_KERNEL); |
| @@ -7062,9 +7095,6 @@ skip: · 24 unmodified lines | ||
| 7062 | 7095 | |
| 7063 | 7096 | if (work->state != KSMBD_WORK_ACTIVE) { |
| 7064 | 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 | 7098 | locks_free_lock(flock); |
| 7069 | 7099 | |
| 7070 | 7100 | if (work->state == KSMBD_WORK_CANCELLED) { |
| @@ -7084,19 +7114,16 @@ skip: · 13 unmodified lines | ||
| 7084 | 7114 | } |
| 7085 | 7115 | |
| 7086 | 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 | 7117 | release_async_work(work); |
| 7091 | 7118 | goto retry; |
| 7092 | 7119 | } else if (!rc) { |
| 7120 | + list_add(&smb_lock->llist, &rollback_list); | |
| 7093 | 7121 | spin_lock(&work->conn->llist_lock); |
| 7094 | 7122 | list_add_tail(&smb_lock->clist, |
| 7095 | 7123 | &work->conn->lock_list); |
| 7096 | 7124 | list_add_tail(&smb_lock->flist, |
| 7097 | 7125 | &fp->lock_list); |
| 7098 | 7126 | spin_unlock(&work->conn->llist_lock); |
| 7099 | − list_add(&smb_lock->llist, &rollback_list); | |
| 7100 | 7127 | ksmbd_debug(SMB, "successful in taking lock\n"); |
| 7101 | 7128 | } else { |
| 7102 | 7129 | goto out; |
| @@ -8036,10 +8063,10 @@ static void smb20_oplock_break_ack(struct ksmbd_work *work) · 933 unmodified lines | ||
| 8036 | 8063 | goto err_out; |
| 8037 | 8064 | } |
| 8038 | 8065 | |
| 8039 | − opinfo_put(opinfo); | |
| 8040 | − ksmbd_fd_put(work, fp); | |
| 8041 | 8066 | opinfo->op_state = OPLOCK_STATE_NONE; |
| 8042 | 8067 | wake_up_interruptible_all(&opinfo->oplock_q); |
| 8068 | + opinfo_put(opinfo); | |
| 8069 | + ksmbd_fd_put(work, fp); | |
| 8043 | 8070 | |
| 8044 | 8071 | rsp->StructureSize = cpu_to_le16(24); |
| 8045 | 8072 | rsp->OplockLevel = rsp_oplevel; |
| @@ -106,7 +106,7 @@ int ksmbd_query_inode_status(struct inode *inode) · 105 unmodified lines | ||
| 106 | 106 | ci = __ksmbd_inode_lookup(inode); |
| 107 | 107 | if (ci) { |
| 108 | 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 | 110 | ret = KSMBD_INODE_STATUS_PENDING_DELETE; |
| 111 | 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 | 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 | 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 | 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 | 339 | if (!atomic_inc_not_zero(&fp->refcount)) |
| 337 | 340 | return NULL; |
| 338 | 341 | return fp; |
| @@ -382,15 +385,20 @@ int ksmbd_close_fd(struct ksmbd_work *work, u64 id) · 43 unmodified lines | ||
| 382 | 385 | return 0; |
| 383 | 386 | |
| 384 | 387 | ft = &work->sess->file_table; |
| 385 | − read_lock(&ft->lock); | |
| 388 | + write_lock(&ft->lock); | |
| 386 | 389 | fp = idr_find(ft->idr, id); |
| 387 | 390 | if (fp) { |
| 388 | 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 | 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 | 403 | if (!fp) |
| 396 | 404 | return -EINVAL; |
| @@ -570,6 +578,7 @@ struct ksmbd_file *ksmbd_open_fd(struct ksmbd_work *work, struct file *filp) · 173 unmodified lines | ||
| 570 | 578 | fp->tcon = work->tcon; |
| 571 | 579 | fp->volatile_id = KSMBD_NO_FID; |
| 572 | 580 | fp->persistent_id = KSMBD_NO_FID; |
| 581 | + fp->f_state = FP_NEW; | |
| 573 | 582 | fp->f_ci = ksmbd_inode_get(fp); |
| 574 | 583 | |
| 575 | 584 | if (!fp->f_ci) { |
| @@ -591,6 +600,17 @@ err_out: · 15 unmodified lines | ||
| 591 | 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 | 614 | static int |
| 595 | 615 | __close_file_table_ids(struct ksmbd_file_table *ft, |
| 596 | 616 | struct ksmbd_tree_connect *tcon, |
| @@ -60,6 +60,12 @@ struct ksmbd_inode { · 59 unmodified lines | ||
| 60 | 60 | __le32 m_fattr; |
| 61 | 61 | }; |
| 62 | 62 | |
| 63 | +enum { | |
| 64 | + FP_NEW = 0, | |
| 65 | + FP_INITED, | |
| 66 | + FP_CLOSED | |
| 67 | +}; | |
| 68 | + | |
| 63 | 69 | struct ksmbd_file { |
| 64 | 70 | struct file *filp; |
| 65 | 71 | u64 persistent_id; |
| @@ -98,6 +104,7 @@ struct ksmbd_file { · 32 unmodified lines | ||
| 98 | 104 | /* if ls is happening on directory, below is valid*/ |
| 99 | 105 | struct ksmbd_readdir_data readdir_data; |
| 100 | 106 | int dot_dotdot[2]; |
| 107 | + unsigned int f_state; | |
| 101 | 108 | }; |
| 102 | 109 | |
| 103 | 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 | 149 | int ksmbd_init_global_file_table(void); |
| 143 | 150 | void ksmbd_free_global_file_table(void); |
| 144 | 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 | 156 | * INODE hash |
| @@ -1001,6 +1001,12 @@ xfs_ag_shrink_space( · 1000 unmodified lines | ||
| 1001 | 1001 | error = -ENOSPC; |
| 1002 | 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 | 1010 | xfs_ialloc_log_agi(*tpp, agibp, XFS_AGI_LENGTH); |
| 1005 | 1011 | xfs_alloc_log_agf(*tpp, agfbp, XFS_AGF_LENGTH); |
| 1006 | 1012 | return 0; |
| @@ -10,7 +10,6 @@ · 9 unmodified lines | ||
| 10 | 10 | #include "xfs_log_format.h" |
| 11 | 11 | #include "xfs_trans_resv.h" |
| 12 | 12 | #include "xfs_mount.h" |
| 13 | −#include "xfs_format.h" | |
| 14 | 13 | #include "scrub/xfile.h" |
| 15 | 14 | #include "scrub/xfarray.h" |
| 16 | 15 | #include "scrub/scrub.h" |
| @@ -1,6 +1,6 @@ | ||
| 1 | 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 | 4 | * All Rights Reserved. |
| 5 | 5 | */ |
| 6 | 6 | #include "xfs.h" |
| @@ -19,21 +19,147 @@ · 12 unmodified lines | ||
| 19 | 19 | #include "xfs_log.h" |
| 20 | 20 | #include "xfs_ag.h" |
| 21 | 21 | |
| 22 | −STATIC int | |
| 23 | −xfs_trim_extents( | |
| 22 | +/* | |
| 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 | 149 | struct xfs_perag *pag, |
| 25 | 150 | xfs_daddr_t start, |
| 26 | 151 | xfs_daddr_t end, |
| 27 | 152 | xfs_daddr_t minlen, |
| 153 | + struct xfs_alloc_rec_incore *tcur, | |
| 154 | + struct xfs_busy_extents *extents, | |
| 28 | 155 | uint64_t *blocks_trimmed) |
| 29 | 156 | { |
| 30 | 157 | struct xfs_mount *mp = pag->pag_mount; |
| 31 | − struct block_device *bdev = mp->m_ddev_targp->bt_bdev; | |
| 32 | 158 | struct xfs_btree_cur *cur; |
| 33 | 159 | struct xfs_buf *agbp; |
| 34 | − struct xfs_agf *agf; | |
| 35 | 160 | int error; |
| 36 | 161 | int i; |
| 162 | + int batch = 100; | |
| 37 | 163 | |
| 38 | 164 | /* |
| 39 | 165 | * Force out the log. This means any transactions that might have freed |
| @@ -45,20 +171,28 @@ xfs_trim_extents( · 5 unmodified lines | ||
| 45 | 171 | error = xfs_alloc_read_agf(pag, NULL, 0, &agbp); |
| 46 | 172 | if (error) |
| 47 | 173 | return error; |
| 48 | − agf = agbp->b_addr; | |
| 49 | 174 | |
| 50 | 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 | 185 | if (error) |
| 57 | 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 | 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 | 197 | while (i) { |
| 64 | 198 | xfs_agblock_t fbno; |
| @@ -73,7 +207,16 @@ xfs_trim_extents( · 8 unmodified lines | ||
| 73 | 207 | error = -EFSCORRUPTED; |
| 74 | 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 | 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 | 232 | if (dlen < minlen) { |
| 90 | 233 | trace_xfs_discard_toosmall(mp, pag->pag_agno, fbno, flen); |
| 234 | + tcur->ar_blockcount = 0; | |
| 91 | 235 | break; |
| 92 | 236 | } |
| 93 | 237 | |
| @@ -110,29 +254,103 @@ xfs_trim_extents( · 16 unmodified lines | ||
| 110 | 254 | goto next_extent; |
| 111 | 255 | } |
| 112 | 256 | |
| 113 | − trace_xfs_discard_extent(mp, pag->pag_agno, fbno, flen); | |
| 114 | − error = blkdev_issue_discard(bdev, dbno, dlen, GFP_NOFS); | |
| 115 | − if (error) | |
| 116 | − break; | |
| 257 | + xfs_extent_busy_insert_discard(pag, fbno, flen, | |
| 258 | + &extents->extent_list); | |
| 117 | 259 | *blocks_trimmed += flen; |
| 118 | − | |
| 119 | 260 | next_extent: |
| 120 | 261 | error = xfs_btree_decrement(cur, 0, &i); |
| 121 | 262 | if (error) |
| 122 | 263 | break; |
| 123 | 264 | |
| 124 | − if (fatal_signal_pending(current)) { | |
| 125 | − error = -ERESTARTSYS; | |
| 126 | − break; | |
| 127 | − } | |
| 265 | + /* | |
| 266 | + * If there's no more records in the tree, we are done. Set the | |
| 267 | + * cursor block count to 0 to indicate to the caller that there | |
| 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 | 280 | out_del_cursor: |
| 131 | 281 | xfs_btree_del_cursor(cur, error); |
| 132 | 282 | xfs_buf_relse(agbp); |
| 133 | 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 | 355 | * trim a range of the filesystem. |
| 138 | 356 | * |
| @@ -195,12 +413,12 @@ xfs_ioc_trim( · 56 unmodified lines | ||
| 195 | 413 | for_each_perag_range(mp, agno, xfs_daddr_to_agno(mp, end), pag) { |
| 196 | 414 | error = xfs_trim_extents(pag, start, end, minlen, |
| 197 | 415 | &blocks_trimmed); |
| 198 | − if (error) { | |
| 416 | + if (error) | |
| 199 | 417 | last_error = error; |
| 200 | − if (error == -ERESTARTSYS) { | |
| 201 | − xfs_perag_rele(pag); | |
| 202 | − break; | |
| 203 | − } | |
| 418 | + | |
| 419 | + if (xfs_trim_should_stop()) { | |
| 420 | + xfs_perag_rele(pag); | |
| 421 | + break; | |
| 204 | 422 | } |
| 205 | 423 | } |
| 206 | 424 | |
| @@ -3,8 +3,10 @@ · 2 unmodified lines | ||
| 3 | 3 | #define XFS_DISCARD_H 1 |
| 4 | 4 | |
| 5 | 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 | 12 | #endif /* XFS_DISCARD_H */ |
| @@ -19,13 +19,13 @@ · 18 unmodified lines | ||
| 19 | 19 | #include "xfs_log.h" |
| 20 | 20 | #include "xfs_ag.h" |
| 21 | 21 | |
| 22 | −void | |
| 23 | −xfs_extent_busy_insert( | |
| 24 | − struct xfs_trans *tp, | |
| 22 | +static void | |
| 23 | +xfs_extent_busy_insert_list( | |
| 25 | 24 | struct xfs_perag *pag, |
| 26 | 25 | xfs_agblock_t bno, |
| 27 | 26 | xfs_extlen_t len, |
| 28 | − unsigned int flags) | |
| 27 | + unsigned int flags, | |
| 28 | + struct list_head *busy_list) | |
| 29 | 29 | { |
| 30 | 30 | struct xfs_extent_busy *new; |
| 31 | 31 | struct xfs_extent_busy *busyp; |
| @@ -40,7 +40,7 @@ xfs_extent_busy_insert( · 8 unmodified lines | ||
| 40 | 40 | new->flags = flags; |
| 41 | 41 | |
| 42 | 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 | 45 | spin_lock(&pag->pagb_lock); |
| 46 | 46 | rbp = &pag->pagb_tree.rb_node; |
| @@ -62,10 +62,33 @@ xfs_extent_busy_insert( · 15 unmodified lines | ||
| 62 | 62 | rb_link_node(&new->rb_node, parent, rbp); |
| 63 | 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 | 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 | 93 | * Search for a busy extent within the range of the extent we are about to |
| 71 | 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 | 17 | * Busy block/extent entry. Indexed by a rbtree in perag to mark blocks that |
| 18 | 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 | 20 | struct xfs_extent_busy { |
| 24 | 21 | struct rb_node rb_node; /* ag by-bno indexed search tree */ |
| @@ -31,10 +28,31 @@ struct xfs_extent_busy { · 6 unmodified lines | ||
| 31 | 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 | 48 | void |
| 35 | 49 | xfs_extent_busy_insert(struct xfs_trans *tp, struct xfs_perag *pag, |
| 36 | 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 | 56 | void |
| 39 | 57 | xfs_extent_busy_clear(struct xfs_mount *mp, struct list_head *list, |
| 40 | 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 | 593 | * Note: If you add another clause to set an attribute flag, please |
| 589 | 594 | * update attributes_mask below. |
| @@ -16,8 +16,7 @@ · 15 unmodified lines | ||
| 16 | 16 | #include "xfs_log.h" |
| 17 | 17 | #include "xfs_log_priv.h" |
| 18 | 18 | #include "xfs_trace.h" |
| 19 | − | |
| 20 | −struct workqueue_struct *xfs_discard_wq; | |
| 19 | +#include "xfs_discard.h" | |
| 21 | 20 | |
| 22 | 21 | /* |
| 23 | 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 | 103 | ctx = kmem_zalloc(sizeof(*ctx), KM_NOFS); |
| 105 | 104 | INIT_LIST_HEAD(&ctx->committing); |
| 106 | − INIT_LIST_HEAD(&ctx->busy_extents); | |
| 105 | + INIT_LIST_HEAD(&ctx->busy_extents.extent_list); | |
| 107 | 106 | INIT_LIST_HEAD(&ctx->log_items); |
| 108 | 107 | INIT_LIST_HEAD(&ctx->lv_chain); |
| 109 | 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 | 132 | if (!list_empty(&cilpcp->busy_extents)) { |
| 134 | 133 | list_splice_init(&cilpcp->busy_extents, |
| 135 | − &ctx->busy_extents); | |
| 134 | + &ctx->busy_extents.extent_list); | |
| 136 | 135 | } |
| 137 | 136 | if (!list_empty(&cilpcp->log_items)) |
| 138 | 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 | 711 | * Mark all items committed and clear busy extents. We free the log vector |
| 783 | 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 | 736 | xfs_trans_committed_bulk(ctx->cil->xc_log->l_ailp, &ctx->lv_chain, |
| 808 | 737 | ctx->start_lsn, abort); |
| 809 | 738 | |
| 810 | − xfs_extent_busy_sort(&ctx->busy_extents); | |
| 811 | − xfs_extent_busy_clear(mp, &ctx->busy_extents, | |
| 739 | + xfs_extent_busy_sort(&ctx->busy_extents.extent_list); | |
| 740 | + xfs_extent_busy_clear(mp, &ctx->busy_extents.extent_list, | |
| 812 | 741 | xfs_has_discard(mp) && !abort); |
| 813 | 742 | |
| 814 | 743 | spin_lock(&ctx->cil->xc_push_lock); |
| @@ -817,10 +746,14 @@ xlog_cil_committed( · 2 unmodified lines | ||
| 817 | 746 | |
| 818 | 747 | xlog_cil_free_logvec(&ctx->lv_chain); |
| 819 | 748 | |
| 820 | − if (!list_empty(&ctx->busy_extents)) | |
| 821 | − xlog_discard_busy_extents(mp, ctx); | |
| 822 | − else | |
| 823 | − kmem_free(ctx); | |
| 749 | + if (!list_empty(&ctx->busy_extents.extent_list)) { | |
| 750 | + ctx->busy_extents.mount = mp; | |
| 751 | + ctx->busy_extents.owner = ctx; | |
| 752 | + xfs_discard_extents(mp, &ctx->busy_extents); | |
| 753 | + return; | |
| 754 | + } | |
| 755 | + | |
| 756 | + kmem_free(ctx); | |
| 824 | 757 | } |
| 825 | 758 | |
| 826 | 759 | void |
| @@ -6,6 +6,8 @@ · 5 unmodified lines | ||
| 6 | 6 | #ifndef __XFS_LOG_PRIV_H__ |
| 7 | 7 | #define __XFS_LOG_PRIV_H__ |
| 8 | 8 | |
| 9 | +#include "xfs_extent_busy.h" /* for struct xfs_busy_extents */ | |
| 10 | + | |
| 9 | 11 | struct xfs_buf; |
| 10 | 12 | struct xlog; |
| 11 | 13 | struct xlog_ticket; |
| @@ -223,12 +225,11 @@ struct xfs_cil_ctx { · 211 unmodified lines | ||
| 223 | 225 | struct xlog_in_core *commit_iclog; |
| 224 | 226 | struct xlog_ticket *ticket; /* chkpt ticket */ |
| 225 | 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 | 229 | struct list_head log_items; /* log items in chkpt */ |
| 228 | 230 | struct list_head lv_chain; /* logvecs being pushed */ |
| 229 | 231 | struct list_head iclog_entry; |
| 230 | 232 | struct list_head committing; /* ctx committing list */ |
| 231 | − struct work_struct discard_endio_work; | |
| 232 | 233 | struct work_struct push_work; |
| 233 | 234 | atomic_t order_id; |
| 234 | 235 | |
| @@ -126,8 +126,8 @@ xfs_dax_notify_ddev_failure( · 125 unmodified lines | ||
| 126 | 126 | struct xfs_rmap_irec ri_low = { }; |
| 127 | 127 | struct xfs_rmap_irec ri_high; |
| 128 | 128 | struct xfs_agf *agf; |
| 129 | − xfs_agblock_t agend; | |
| 130 | 129 | struct xfs_perag *pag; |
| 130 | + xfs_agblock_t range_agend; | |
| 131 | 131 | |
| 132 | 132 | pag = xfs_perag_get(mp, agno); |
| 133 | 133 | error = xfs_alloc_read_agf(pag, tp, 0, &agf_bp); |
| @@ -148,10 +148,10 @@ xfs_dax_notify_ddev_failure( · 14 unmodified lines | ||
| 148 | 148 | ri_high.rm_startblock = XFS_FSB_TO_AGBNO(mp, end_fsbno); |
| 149 | 149 | |
| 150 | 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 | 152 | ri_high.rm_startblock); |
| 153 | 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 | 156 | error = xfs_rmap_query_range(cur, &ri_low, &ri_high, |
| 157 | 157 | xfs_dax_failure_fn, ¬ify); |
| @@ -465,9 +465,4 @@ extern int acpi_processor_ffh_lpi_probe(unsigned int cpu); · 464 unmodified lines | ||
| 465 | 465 | extern int acpi_processor_ffh_lpi_enter(struct acpi_lpi_state *lpi); |
| 466 | 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 | 468 | #endif |
| @@ -36,6 +36,7 @@ struct ms_hyperv_info { · 35 unmodified lines | ||
| 36 | 36 | u32 nested_features; |
| 37 | 37 | u32 max_vp_index; |
| 38 | 38 | u32 max_lp_index; |
| 39 | + u8 vtl; | |
| 39 | 40 | union { |
| 40 | 41 | u32 isolation_config_a; |
| 41 | 42 | struct { |
| @@ -54,7 +55,6 @@ struct ms_hyperv_info { · 12 unmodified lines | ||
| 54 | 55 | }; |
| 55 | 56 | }; |
| 56 | 57 | u64 shared_gpa_boundary; |
| 57 | − u8 vtl; | |
| 58 | 58 | }; |
| 59 | 59 | extern struct ms_hyperv_info ms_hyperv; |
| 60 | 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 | 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 | 1492 | #ifdef CONFIG_ACPI_PPTT |
| 1484 | 1493 | int acpi_pptt_cpu_is_thread(unsigned int cpu); |
| 1485 | 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 | 1307 | static inline struct bpf_trampoline *bpf_trampoline_get(u64 key, |
| 1308 | 1308 | struct bpf_attach_target_info *tgt_info) |
| 1309 | 1309 | { |
| 1310 | − return ERR_PTR(-EOPNOTSUPP); | |
| 1310 | + return NULL; | |
| 1311 | 1311 | } |
| 1312 | 1312 | static inline void bpf_trampoline_put(struct bpf_trampoline *tr) {} |
| 1313 | 1313 | #define DEFINE_BPF_DISPATCHER(name) |
| @@ -238,7 +238,7 @@ struct css_set { · 237 unmodified lines | ||
| 238 | 238 | * Lists running through all tasks using this cgroup group. |
| 239 | 239 | * mg_tasks lists tasks which belong to this cset but are in the |
| 240 | 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 | 242 | * mg_tasks, it can be read safely while holding cgroup_mutex. |
| 243 | 243 | */ |
| 244 | 244 | struct list_head tasks; |
| @@ -80,6 +80,8 @@ extern __printf(4, 5) · 79 unmodified lines | ||
| 80 | 80 | struct device *cpu_device_create(struct device *parent, void *drvdata, |
| 81 | 81 | const struct attribute_group **groups, |
| 82 | 82 | const char *fmt, ...); |
| 83 | +extern int arch_register_cpu(int cpu); | |
| 84 | +extern void arch_unregister_cpu(int cpu); | |
| 83 | 85 | #ifdef CONFIG_HOTPLUG_CPU |
| 84 | 86 | extern void unregister_cpu(struct cpu *cpu); |
| 85 | 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 | 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 | 590 | signed long dma_fence_wait_timeout(struct dma_fence *, |
| 572 | 591 | bool intr, signed long timeout); |
| 573 | 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 | 136 | extern int vfs_parse_fs_param(struct fs_context *fc, struct fs_parameter *param); |
| 137 | 137 | extern int vfs_parse_fs_string(struct fs_context *fc, const char *key, |
| 138 | 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 | 141 | extern int generic_parse_monolithic(struct fs_context *fc, void *data); |
| 140 | 142 | extern int vfs_get_tree(struct fs_context *fc); |
| 141 | 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 | 63 | struct mcb_device { |
| 64 | 64 | struct device dev; |
| 65 | 65 | struct mcb_bus *bus; |
| 66 | − bool is_added; | |
| 67 | 66 | struct mcb_driver *driver; |
| 68 | 67 | u16 id; |
| 69 | 68 | int inst; |
| @@ -9,6 +9,7 @@ struct ip_ct_sctp { · 8 unmodified lines | ||
| 9 | 9 | enum sctp_conntrack state; |
| 10 | 10 | |
| 11 | 11 | __be32 vtag[IP_CT_DIR_MAX]; |
| 12 | + u8 init[IP_CT_DIR_MAX]; | |
| 12 | 13 | u8 last_dir; |
| 13 | 14 | u8 flags; |
| 14 | 15 | }; |
| @@ -285,7 +285,9 @@ static inline void dqstats_dec(unsigned int type) · 284 unmodified lines | ||
| 285 | 285 | #define DQ_FAKE_B 3 /* no limits only usage */ |
| 286 | 286 | #define DQ_READ_B 4 /* dquot was read into memory */ |
| 287 | 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 | 291 | * for the mask of entries set via SETQUOTA\ |
| 290 | 292 | * quotactl. They are set under dq_data_lock\ |
| 291 | 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 | 58 | if (test_bit(DQ_MOD_B, &dquot->dq_flags)) |
| 59 | 59 | return true; |
| 60 | − if (atomic_read(&dquot->dq_count) > 1) | |
| 60 | + if (atomic_read(&dquot->dq_count) > 0) | |
| 61 | 61 | return true; |
| 62 | 62 | return false; |
| 63 | 63 | } |
| @@ -1309,7 +1309,7 @@ struct sk_buff_fclones { · 1308 unmodified lines | ||
| 1309 | 1309 | * |
| 1310 | 1310 | * Returns true if skb is a fast clone, and its clone is not freed. |
| 1311 | 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 | 1314 | static inline bool skb_fclone_busy(const struct sock *sk, |
| 1315 | 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 | 2016 | * Copy shared buffers into a new sk_buff. We effectively do COW on |
| 2017 | 2017 | * packets to handle cases where we have a local reader and forward |
| 2018 | 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 | 350 | struct list_head list; |
| 351 | 351 | struct mutex lock; |
| 352 | 352 | |
| 353 | − char name[8]; | |
| 353 | + const char *name; | |
| 354 | 354 | unsigned long flags; |
| 355 | 355 | __u16 id; |
| 356 | 356 | __u8 bus; |
| @@ -5941,6 +5941,7 @@ void wiphy_delayed_work_cancel(struct wiphy *wiphy, · 5940 unmodified lines | ||
| 5941 | 5941 | * @event_lock: (private) lock for event list |
| 5942 | 5942 | * @owner_nlportid: (private) owner socket port ID |
| 5943 | 5943 | * @nl_owner_dead: (private) owner socket went away |
| 5944 | + * @cqm_rssi_work: (private) CQM RSSI reporting work | |
| 5944 | 5945 | * @cqm_config: (private) nl80211 RSSI monitor state |
| 5945 | 5946 | * @pmsr_list: (private) peer measurement requests |
| 5946 | 5947 | * @pmsr_lock: (private) peer measurements requests/results lock |
| @@ -6013,7 +6014,8 @@ struct wireless_dev { · 66 unmodified lines | ||
| 6013 | 6014 | } wext; |
| 6014 | 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 | 6020 | struct list_head pmsr_list; |
| 6019 | 6021 | spinlock_t pmsr_lock; |
| @@ -7231,7 +7233,7 @@ struct cfg80211_rx_assoc_resp { · 1211 unmodified lines | ||
| 7231 | 7233 | int uapsd_queues; |
| 7232 | 7234 | const u8 *ap_mld_addr; |
| 7233 | 7235 | struct { |
| 7234 | − const u8 *addr; | |
| 7236 | + u8 addr[ETH_ALEN] __aligned(2); | |
| 7235 | 7237 | struct cfg80211_bss *bss; |
| 7236 | 7238 | u16 status; |
| 7237 | 7239 | } links[IEEE80211_MLD_MAX_NUM_LINKS]; |
| @@ -154,6 +154,7 @@ struct fib_info { · 153 unmodified lines | ||
| 154 | 154 | int fib_nhs; |
| 155 | 155 | bool fib_nh_is_v6; |
| 156 | 156 | bool nh_updated; |
| 157 | + bool pfsrc_removed; | |
| 157 | 158 | struct nexthop *nh; |
| 158 | 159 | struct rcu_head rcu; |
| 159 | 160 | struct fib_nh fib_nh[]; |
| @@ -258,6 +258,7 @@ struct macsec_context { · 257 unmodified lines | ||
| 258 | 258 | struct macsec_secy *secy; |
| 259 | 259 | struct macsec_rx_sc *rx_sc; |
| 260 | 260 | struct { |
| 261 | + bool update_pn; | |
| 261 | 262 | unsigned char assoc_num; |
| 262 | 263 | u8 key[MACSEC_MAX_KEY_LEN]; |
| 263 | 264 | union { |
| @@ -103,9 +103,10 @@ struct mana_txq { · 102 unmodified lines | ||
| 103 | 103 | |
| 104 | 104 | /* skb data and frags dma mappings */ |
| 105 | 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 | 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 | 539 | READ_ONCE(hh->hh_len)) |
| 540 | 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 | 545 | static inline struct neighbour * |
| @@ -16,13 +16,13 @@ · 15 unmodified lines | ||
| 16 | 16 | * page_pool_alloc_pages() call. Drivers should use |
| 17 | 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 | 20 | * when it is safe to free a page_pool object. Thus, API users |
| 21 | 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 | 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 | 26 | * will either recycle the page, or in case of refcnt > 1, it will |
| 27 | 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 | 348 | struct sk_buff *tcp_stream_alloc_skb(struct sock *sk, gfp_t gfp, |
| 349 | 349 | bool force_schedule); |
| 350 | 350 | |
| 351 | −static inline void tcp_dec_quickack_mode(struct sock *sk, | |
| 352 | − const unsigned int pkts) | |
| 351 | +static inline void tcp_dec_quickack_mode(struct sock *sk) | |
| 353 | 352 | { |
| 354 | 353 | struct inet_connection_sock *icsk = inet_csk(sk); |
| 355 | 354 | |
| 356 | 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 | 359 | if (pkts >= icsk->icsk_ack.quick) { |
| 358 | 360 | icsk->icsk_ack.quick = 0; |
| 359 | 361 | /* Leaving quickack mode we deflate ATO. */ |
| @@ -1126,6 +1126,8 @@ struct snd_soc_pcm_runtime { · 1125 unmodified lines | ||
| 1126 | 1126 | unsigned int pop_wait:1; |
| 1127 | 1127 | unsigned int fe_compr:1; /* for Dynamic PCM */ |
| 1128 | 1128 | |
| 1129 | + bool initialized; | |
| 1130 | + | |
| 1129 | 1131 | int num_components; |
| 1130 | 1132 | struct snd_soc_component *components[]; /* CPU/Codec/Platform */ |
| 1131 | 1133 | }; |
| @@ -44,6 +44,16 @@ extern "C" { · 43 unmodified lines | ||
| 44 | 44 | #define NOUVEAU_GETPARAM_PTIMER_TIME 14 |
| 45 | 45 | #define NOUVEAU_GETPARAM_HAS_BO_USAGE 15 |
| 46 | 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 | 57 | struct drm_nouveau_getparam { |
| 48 | 58 | __u64 param; |
| 49 | 59 | __u64 value; |
| @@ -18,11 +18,7 @@ struct sockaddr_ll { · 17 unmodified lines | ||
| 18 | 18 | unsigned short sll_hatype; |
| 19 | 19 | unsigned char sll_pkttype; |
| 20 | 20 | unsigned char sll_halen; |
| 21 | − union { | |
| 22 | − unsigned char sll_addr[8]; | |
| 23 | − /* Actual length is in sll_halen. */ | |
| 24 | − __DECLARE_FLEX_ARRAY(unsigned char, sll_addr_flex); | |
| 25 | − }; | |
| 21 | + unsigned char sll_addr[8]; | |
| 26 | 22 | }; |
| 27 | 23 | |
| 28 | 24 | /* Packet types */ |
| @@ -1151,9 +1151,6 @@ struct io_wq *io_wq_create(unsigned bounded, struct io_wq_data *data) · 1150 unmodified lines | ||
| 1151 | 1151 | wq = kzalloc(sizeof(struct io_wq), GFP_KERNEL); |
| 1152 | 1152 | if (!wq) |
| 1153 | 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 | 1155 | refcount_inc(&data->hash->refs); |
| 1159 | 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 | 1183 | wq->task = get_task_struct(data->task); |
| 1187 | 1184 | atomic_set(&wq->worker_refs, 1); |
| 1188 | 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 | 1190 | return wq; |
| 1190 | 1191 | err: |
| 1191 | 1192 | io_wq_put_hash(data->hash); |
| 1192 | − cpuhp_state_remove_instance_nocalls(io_wq_online, &wq->cpuhp_node); | |
| 1193 | − | |
| 1194 | 1193 | free_cpumask_var(wq->cpu_mask); |
| 1195 | −err_wq: | |
| 1196 | 1194 | kfree(wq); |
| 1197 | 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 | 2687 | struct page **page_array; |
| 2688 | 2688 | unsigned int nr_pages; |
| 2689 | − int ret; | |
| 2689 | + int ret, i; | |
| 2690 | 2690 | |
| 2691 | 2691 | *npages = 0; |
| 2692 | 2692 | |
| @@ -2716,6 +2716,20 @@ err: · 23 unmodified lines | ||
| 2716 | 2716 | */ |
| 2717 | 2717 | if (page_array[0] != page_array[ret - 1]) |
| 2718 | 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 | 2733 | *pages = page_array; |
| 2720 | 2734 | *npages = nr_pages; |
| 2721 | 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 | 86 | bool io_match_task_safe(struct io_kiocb *head, struct task_struct *task, |
| 87 | 87 | bool cancel_all); |
| 88 | 88 | |
| 89 | −#define io_lockdep_assert_cq_locked(ctx) \ | |
| 90 | − do { \ | |
| 91 | − lockdep_assert(in_task()); \ | |
| 92 | − \ | |
| 93 | − if (ctx->flags & IORING_SETUP_IOPOLL) { \ | |
| 94 | − lockdep_assert_held(&ctx->uring_lock); \ | |
| 95 | − } else if (!ctx->task_complete) { \ | |
| 96 | − lockdep_assert_held(&ctx->completion_lock); \ | |
| 97 | − } else if (ctx->submitter_task->flags & PF_EXITING) { \ | |
| 98 | − lockdep_assert(current_work()); \ | |
| 99 | − } else { \ | |
| 100 | − lockdep_assert(current == ctx->submitter_task); \ | |
| 101 | − } \ | |
| 102 | − } while (0) | |
| 89 | +#if defined(CONFIG_PROVE_LOCKING) | |
| 90 | +static inline void io_lockdep_assert_cq_locked(struct io_ring_ctx *ctx) | |
| 91 | +{ | |
| 92 | + lockdep_assert(in_task()); | |
| 93 | + | |
| 94 | + if (ctx->flags & IORING_SETUP_IOPOLL) { | |
| 95 | + lockdep_assert_held(&ctx->uring_lock); | |
| 96 | + } else if (!ctx->task_complete) { | |
| 97 | + lockdep_assert_held(&ctx->completion_lock); | |
| 98 | + } else if (ctx->submitter_task) { | |
| 99 | + /* | |
| 100 | + * ->submitter_task may be NULL and we can still post a CQE, | |
| 101 | + * if the ring has been setup with IORING_SETUP_R_DISABLED. | |
| 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 | 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 | 478 | struct io_uring_buf_ring *br; |
| 479 | 479 | struct page **pages; |
| 480 | − int nr_pages; | |
| 480 | + int i, nr_pages; | |
| 481 | 481 | |
| 482 | 482 | pages = io_pin_pages(reg->ring_addr, |
| 483 | 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 | 485 | if (IS_ERR(pages)) |
| 486 | 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 | 499 | br = page_address(pages[0]); |
| 489 | 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 | 507 | * should use IOU_PBUF_RING_MMAP instead, and liburing will handle |
| 497 | 508 | * this transparently. |
| 498 | 509 | */ |
| 499 | − if ((reg->ring_addr | (unsigned long) br) & (SHM_COLOUR - 1)) { | |
| 500 | − int i; | |
| 501 | − | |
| 502 | − for (i = 0; i < nr_pages; i++) | |
| 503 | − unpin_user_page(pages[i]); | |
| 504 | − return -EINVAL; | |
| 505 | − } | |
| 510 | + if ((reg->ring_addr | (unsigned long) br) & (SHM_COLOUR - 1)) | |
| 511 | + goto error_unpin; | |
| 506 | 512 | #endif |
| 507 | 513 | bl->buf_pages = pages; |
| 508 | 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 | 516 | bl->is_mapped = 1; |
| 511 | 517 | bl->is_mmap = 0; |
| 512 | 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 | 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 | 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 | 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 | |
| 974 | − * up-to 256-bytes. | |
| 972 | + /* Adjusting the indexes in size_index() according to the object_size | |
| 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; | |
| 977 | − if (size <= 192) | |
| 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; | |
| 980 | + for (size = 192; size >= 8; size -= 8) { | |
| 981 | + unsigned int kmalloc_size, index; | |
| 983 | 982 | |
| 984 | − /* The minimal alignment is 64-bytes, so disable 96-bytes cache and | |
| 985 | − * use 128-bytes cache instead. | |
| 986 | − */ | |
| 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 | − } | |
| 983 | + kmalloc_size = kmalloc_size_roundup(size); | |
| 984 | + if (kmalloc_size == size) | |
| 985 | + continue; | |
| 992 | 986 | |
| 993 | − /* The minimal alignment is 128-bytes, so disable 192-bytes cache and | |
| 994 | − * use 256-bytes cache instead. | |
| 995 | − */ | |
| 996 | − if (KMALLOC_MIN_SIZE >= 128) { | |
| 997 | − index = fls(256 - 1) - 1; | |
| 998 | − for (size = 128 + 8; size <= 192; size += 8) | |
| 987 | + if (kmalloc_size <= 192) | |
| 988 | + index = size_index[(kmalloc_size - 1) / 8]; | |
| 989 | + else | |
| 990 | + index = fls(kmalloc_size - 1) - 1; | |
| 991 | + /* Only overwrite if necessary */ | |
| 992 | + if (size_index[(size - 1) / 8] != index) | |
| 999 | 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 | 253 | goto out; |
| 254 | 254 | } |
| 255 | 255 | idx = tidx; |
| 256 | + } else if (bpf_mprog_total(entry) == bpf_mprog_max()) { | |
| 257 | + ret = -ERANGE; | |
| 258 | + goto out; | |
| 256 | 259 | } |
| 257 | 260 | if (flags & BPF_F_BEFORE) { |
| 258 | 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 | 401 | struct bpf_mprog_cp *cp; |
| 399 | 402 | struct bpf_prog *prog; |
| 400 | 403 | const u32 flags = 0; |
| 404 | + u32 id, count = 0; | |
| 405 | + u64 revision = 1; | |
| 401 | 406 | int i, ret = 0; |
| 402 | − u32 id, count; | |
| 403 | − u64 revision; | |
| 404 | 407 | |
| 405 | 408 | if (attr->query.query_flags || attr->query.attach_flags) |
| 406 | 409 | return -EINVAL; |
| 407 | − revision = bpf_mprog_revision(entry); | |
| 408 | − count = bpf_mprog_total(entry); | |
| 410 | + if (entry) { | |
| 411 | + revision = bpf_mprog_revision(entry); | |
| 412 | + count = bpf_mprog_total(entry); | |
| 413 | + } | |
| 409 | 414 | if (copy_to_user(&uattr->query.attach_flags, &flags, sizeof(flags))) |
| 410 | 415 | return -EFAULT; |
| 411 | 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 | 3797 | enum bpf_prog_type ptype; |
| 3798 | 3798 | struct bpf_prog *prog; |
| 3799 | − u32 mask; | |
| 3800 | 3799 | int ret; |
| 3801 | 3800 | |
| 3802 | 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 | 3804 | ptype = attach_type_to_prog_type(attr->attach_type); |
| 3806 | 3805 | if (ptype == BPF_PROG_TYPE_UNSPEC) |
| 3807 | 3806 | return -EINVAL; |
| 3808 | − mask = bpf_mprog_supported(ptype) ? | |
| 3809 | − BPF_F_ATTACH_MASK_MPROG : BPF_F_ATTACH_MASK_BASE; | |
| 3810 | − if (attr->attach_flags & ~mask) | |
| 3811 | − return -EINVAL; | |
| 3807 | + if (bpf_mprog_supported(ptype)) { | |
| 3808 | + if (attr->attach_flags & ~BPF_F_ATTACH_MASK_MPROG) | |
| 3809 | + 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 | 3818 | prog = bpf_prog_get_type(attr->attach_bpf_fd, ptype); |
| 3814 | 3819 | if (IS_ERR(prog)) |
| @@ -3878,6 +3883,10 @@ static int bpf_prog_detach(const union bpf_attr *attr) · 63 unmodified lines | ||
| 3878 | 3883 | if (IS_ERR(prog)) |
| 3879 | 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 | 3892 | switch (ptype) { |
| @@ -3913,7 +3922,7 @@ static int bpf_prog_detach(const union bpf_attr *attr) · 29 unmodified lines | ||
| 3913 | 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 | 3927 | static int bpf_prog_query(const union bpf_attr *attr, |
| 3919 | 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 | 124 | bool ingress = attr->query.attach_type == BPF_TCX_INGRESS; |
| 125 | 125 | struct net *net = current->nsproxy->net_ns; |
| 126 | − struct bpf_mprog_entry *entry; | |
| 127 | 126 | struct net_device *dev; |
| 128 | 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 | 132 | ret = -ENODEV; |
| 134 | 133 | goto out; |
| 135 | 134 | } |
| 136 | − entry = tcx_entry_fetch(dev, ingress); | |
| 137 | − if (!entry) { | |
| 138 | − ret = -ENOENT; | |
| 139 | − goto out; | |
| 140 | − } | |
| 141 | − ret = bpf_mprog_query(attr, uattr, entry); | |
| 135 | + ret = bpf_mprog_query(attr, uattr, tcx_entry_fetch(dev, ingress)); | |
| 142 | 136 | out: |
| 143 | 137 | rtnl_unlock(); |
| 144 | 138 | return ret; |
| @@ -4047,11 +4047,9 @@ static int __mark_chain_precision(struct bpf_verifier_env *env, int regno) · 4046 unmodified lines | ||
| 4047 | 4047 | bitmap_from_u64(mask, bt_reg_mask(bt)); |
| 4048 | 4048 | for_each_set_bit(i, mask, 32) { |
| 4049 | 4049 | reg = &st->frame[0]->regs[i]; |
| 4050 | − if (reg->type != SCALAR_VALUE) { | |
| 4051 | − bt_clear_reg(bt, i); | |
| 4052 | − continue; | |
| 4053 | − } | |
| 4054 | − reg->precise = true; | |
| 4050 | + bt_clear_reg(bt, i); | |
| 4051 | + if (reg->type == SCALAR_VALUE) | |
| 4052 | + reg->precise = true; | |
| 4055 | 4053 | } |
| 4056 | 4054 | return 0; |
| 4057 | 4055 | } |
| @@ -14481,7 +14479,7 @@ static int check_return_code(struct bpf_verifier_env *env) · 10423 unmodified lines | ||
| 14481 | 14479 | struct tnum enforce_attach_type_range = tnum_unknown; |
| 14482 | 14480 | const struct bpf_prog *prog = env->prog; |
| 14483 | 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 | 14483 | enum bpf_prog_type prog_type = resolve_prog_type(env->prog); |
| 14486 | 14484 | int err; |
| 14487 | 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 | 14527 | return -EINVAL; |
| 14530 | 14528 | } |
| 14531 | 14529 | |
| 14532 | − if (!tnum_in(tnum_const(0), reg->var_off)) { | |
| 14533 | − verbose_invalid_scalar(env, reg, &range, "async callback", "R0"); | |
| 14530 | + if (!tnum_in(const_0, reg->var_off)) { | |
| 14531 | + verbose_invalid_scalar(env, reg, &const_0, "async callback", "R0"); | |
| 14534 | 14532 | return -EINVAL; |
| 14535 | 14533 | } |
| 14536 | 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 | 361 | css_task_iter_end(&it); |
| 362 | 362 | length = n; |
| 363 | − /* now sort & (if procs) strip out duplicates */ | |
| 363 | + /* now sort & strip out duplicates (tgids or recycled thread PIDs) */ | |
| 364 | 364 | sort(array, length, sizeof(pid_t), cmppid, NULL); |
| 365 | − if (type == CGROUP_FILE_PROCS) | |
| 366 | − length = pidlist_uniq(array, length); | |
| 365 | + length = pidlist_uniq(array, length); | |
| 367 | 366 | |
| 368 | 367 | l = cgroup_pidlist_find_create(cgrp, type); |
| 369 | 368 | if (!l) { |
| @@ -2647,7 +2647,7 @@ static int prepare_image(struct memory_bitmap *new_bm, struct memory_bitmap *bm, · 2646 unmodified lines | ||
| 2647 | 2647 | memory_bm_free(bm, PG_UNSAFE_KEEP); |
| 2648 | 2648 | |
| 2649 | 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 | 2651 | if (error) |
| 2652 | 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 | 2660 | goto Free; |
| 2661 | 2661 | |
| 2662 | 2662 | duplicate_memory_bitmap(zero_bm, &tmp); |
| 2663 | − memory_bm_free(&tmp, PG_UNSAFE_KEEP); | |
| 2663 | + memory_bm_free(&tmp, PG_UNSAFE_CLEAR); | |
| 2664 | 2664 | /* At this point zero_bm is in safe pages and it can be used for restoring. */ |
| 2665 | 2665 | |
| 2666 | 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 | 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 | 3747 | for (;;) { |
| 3744 | 3748 | diff = 0; |
| 3745 | 3749 | |
| 3746 | 3750 | /* |
| 3747 | 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 | 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 | 350 | * Except when the rq is capped by uclamp_max. |
| 351 | 351 | */ |
| 352 | 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 | 355 | next_f = sg_policy->next_freq; |
| 355 | 356 | |
| 356 | 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 | 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 | 671 | u64 avg_vruntime(struct cfs_rq *cfs_rq) |
| 668 | 672 | { |
| 669 | 673 | struct sched_entity *curr = cfs_rq->curr; |
| @@ -677,8 +681,12 @@ u64 avg_vruntime(struct cfs_rq *cfs_rq) · 7 unmodified lines | ||
| 677 | 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 | 688 | avg = div_s64(avg, load); |
| 689 | + } | |
| 682 | 690 | |
| 683 | 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 | 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 | 877 | struct rb_node *node = cfs_rq->tasks_timeline.rb_root.rb_node; |
| 870 | 878 | struct sched_entity *curr = cfs_rq->curr; |
| 871 | 879 | struct sched_entity *best = NULL; |
| 880 | + struct sched_entity *best_left = NULL; | |
| 872 | 881 | |
| 873 | 882 | if (curr && (!curr->on_rq || !entity_eligible(cfs_rq, curr))) |
| 874 | 883 | curr = NULL; |
| 884 | + best = curr; | |
| 875 | 885 | |
| 876 | 886 | /* |
| 877 | 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 | |
| 896 | − * best, take this one. If it also has the earliest deadline | |
| 897 | − * of its subtree, we're done. | |
| 905 | + * Now we heap search eligible trees for the best (min_)deadline | |
| 898 | 906 | */ |
| 899 | − if (!best || deadline_gt(deadline, best, se)) { | |
| 907 | + if (!best || deadline_gt(deadline, best, se)) | |
| 900 | 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 | |
| 907 | − * eligible left half of our space, go there. | |
| 911 | + * Every se in a left branch is eligible, keep track of the | |
| 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 | 957 | if (node->rb_left && |
| 910 | 958 | __node_2_se(node->rb_left)->min_deadline == se->min_deadline) { |
| 911 | 959 | node = node->rb_left; |
| 912 | 960 | continue; |
| 913 | 961 | } |
| 914 | 962 | |
| 963 | + /* else min_deadline is in the right branch */ | |
| 915 | 964 | node = node->rb_right; |
| 916 | 965 | } |
| 966 | + return NULL; | |
| 967 | +} | |
| 917 | 968 | |
| 918 | − if (!best || (curr && deadline_gt(deadline, best, curr))) | |
| 919 | − best = curr; | |
| 969 | +static struct sched_entity *pick_eevdf(struct cfs_rq *cfs_rq) | |
| 970 | +{ | |
| 971 | + struct sched_entity *se = __pick_eevdf(cfs_rq); | |
| 920 | 972 | |
| 921 | − if (unlikely(!best)) { | |
| 973 | + if (!se) { | |
| 922 | 974 | struct sched_entity *left = __pick_first_entity(cfs_rq); |
| 923 | 975 | if (left) { |
| 924 | 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 | 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 | 3658 | deadline = div_s64(deadline * old_weight, weight); |
| 3607 | 3659 | se->deadline = se->vruntime + deadline; |
| 3660 | + min_deadline_cb_propagate(&se->run_node, NULL); | |
| 3608 | 3661 | } |
| 3609 | 3662 | |
| 3610 | 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 | 4972 | static void |
| 4920 | 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); | |
| 4923 | − u64 vruntime = avg_vruntime(cfs_rq); | |
| 4975 | + u64 vslice, vruntime = avg_vruntime(cfs_rq); | |
| 4924 | 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 | 4982 | * Due to how V is constructed as the weighted average of entities, |
| 4928 | 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 | 2167 | struct worker *worker; |
| 2168 | 2168 | int id; |
| 2169 | − char id_buf[16]; | |
| 2169 | + char id_buf[23]; | |
| 2170 | 2170 | |
| 2171 | 2171 | /* ID is needed to determine kthread name */ |
| 2172 | 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 | 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 | 4609 | return ret; |
| 4604 | 4610 | |
| 4605 | 4611 | enomem: |
| 4606 | 4612 | if (wq->cpu_pwq) { |
| 4607 | − for_each_possible_cpu(cpu) | |
| 4608 | − kfree(*per_cpu_ptr(wq->cpu_pwq, cpu)); | |
| 4613 | + for_each_possible_cpu(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 | 4619 | free_percpu(wq->cpu_pwq); |
| 4610 | 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 | 5792 | list_for_each_entry(wq, &workqueues, list) { |
| 5783 | 5793 | if (!(wq->flags & WQ_UNBOUND)) |
| 5784 | 5794 | continue; |
| 5795 | + | |
| 5785 | 5796 | /* creating multiple pwqs breaks ordering guarantee */ |
| 5786 | − if (wq->flags & __WQ_ORDERED) | |
| 5787 | − continue; | |
| 5797 | + if (!list_empty(&wq->pwqs)) { | |
| 5798 | + if (wq->flags & __WQ_ORDERED_EXPLICIT) | |
| 5799 | + continue; | |
| 5800 | + wq->flags &= ~__WQ_ORDERED; | |
| 5801 | + } | |
| 5788 | 5802 | |
| 5789 | 5803 | ctx = apply_wqattrs_prepare(wq, wq->unbound_attrs, unbound_cpumask); |
| 5790 | 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 | 2413 | if (!test_bit(HCI_CONN_AUTH, &conn->flags)) |
| 2414 | 2414 | goto auth; |
| 2415 | 2415 | |
| 2416 | − /* An authenticated FIPS approved combination key has sufficient | |
| 2417 | − * security for security level 4. */ | |
| 2418 | − if (conn->key_type == HCI_LK_AUTH_COMBINATION_P256 && | |
| 2419 | − sec_level == BT_SECURITY_FIPS) | |
| 2420 | − goto encrypt; | |
| 2421 | − | |
| 2422 | − /* An authenticated combination key has sufficient security for | |
| 2423 | − security level 3. */ | |
| 2424 | − if ((conn->key_type == HCI_LK_AUTH_COMBINATION_P192 || | |
| 2425 | − conn->key_type == HCI_LK_AUTH_COMBINATION_P256) && | |
| 2426 | − sec_level == BT_SECURITY_HIGH) | |
| 2427 | − goto encrypt; | |
| 2428 | − | |
| 2429 | − /* An unauthenticated combination key has sufficient security for | |
| 2430 | − security level 1 and 2. */ | |
| 2431 | − if ((conn->key_type == HCI_LK_UNAUTH_COMBINATION_P192 || | |
| 2432 | − conn->key_type == HCI_LK_UNAUTH_COMBINATION_P256) && | |
| 2433 | − (sec_level == BT_SECURITY_MEDIUM || sec_level == BT_SECURITY_LOW)) | |
| 2434 | − goto encrypt; | |
| 2435 | − | |
| 2436 | − /* A combination key has always sufficient security for the security | |
| 2437 | − levels 1 or 2. High security level requires the combination key | |
| 2438 | − is generated using maximum PIN code length (16). | |
| 2439 | − For pre 2.1 units. */ | |
| 2440 | − if (conn->key_type == HCI_LK_COMBINATION && | |
| 2441 | − (sec_level == BT_SECURITY_MEDIUM || sec_level == BT_SECURITY_LOW || | |
| 2442 | − conn->pin_length == 16)) | |
| 2443 | − goto encrypt; | |
| 2416 | + switch (conn->key_type) { | |
| 2417 | + case HCI_LK_AUTH_COMBINATION_P256: | |
| 2418 | + /* An authenticated FIPS approved combination key has | |
| 2419 | + * sufficient security for security level 4 or lower. | |
| 2420 | + */ | |
| 2421 | + if (sec_level <= BT_SECURITY_FIPS) | |
| 2422 | + goto encrypt; | |
| 2423 | + break; | |
| 2424 | + case HCI_LK_AUTH_COMBINATION_P192: | |
| 2425 | + /* An authenticated combination key has sufficient security for | |
| 2426 | + * security level 3 or lower. | |
| 2427 | + */ | |
| 2428 | + if (sec_level <= BT_SECURITY_HIGH) | |
| 2429 | + goto encrypt; | |
| 2430 | + break; | |
| 2431 | + case HCI_LK_UNAUTH_COMBINATION_P192: | |
| 2432 | + case HCI_LK_UNAUTH_COMBINATION_P256: | |
| 2433 | + /* An unauthenticated combination key has sufficient security | |
| 2434 | + * for security level 2 or lower. | |
| 2435 | + */ | |
| 2436 | + if (sec_level <= BT_SECURITY_MEDIUM) | |
| 2437 | + goto encrypt; | |
| 2438 | + break; | |
| 2439 | + case HCI_LK_COMBINATION: | |
| 2440 | + /* A combination key has always sufficient security for the | |
| 2441 | + * security levels 2 or lower. High security level requires the | |
| 2442 | + * combination key is generated using maximum PIN code length | |
| 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 | 2452 | auth: |
| 2446 | 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 | 2617 | if (id < 0) |
| 2618 | 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 | 2625 | hdev->id = id; |
| 2622 | 2626 | |
| 2623 | 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 | 2643 | if (!IS_ERR_OR_NULL(bt_debugfs)) |
| 2640 | 2644 | hdev->debugfs = debugfs_create_dir(hdev->name, bt_debugfs); |
| 2641 | 2645 | |
| 2642 | − dev_set_name(&hdev->dev, "%s", hdev->name); | |
| 2643 | − | |
| 2644 | 2646 | error = device_add(&hdev->dev); |
| 2645 | 2647 | if (error < 0) |
| 2646 | 2648 | goto err_wqueue; |
| @@ -2784,6 +2786,7 @@ void hci_release_dev(struct hci_dev *hdev) · 137 unmodified lines | ||
| 2784 | 2786 | hci_conn_params_clear_all(hdev); |
| 2785 | 2787 | hci_discovery_filter_clear(hdev); |
| 2786 | 2788 | hci_blocked_keys_clear(hdev); |
| 2789 | + hci_codec_list_clear(&hdev->local_codecs); | |
| 2787 | 2790 | hci_dev_unlock(hdev); |
| 2788 | 2791 | |
| 2789 | 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 | 3421 | if (c->type == type && c->sent) { |
| 3419 | 3422 | bt_dev_err(hdev, "killing stalled connection %pMR", |
| 3420 | 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 | 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 | 34 | #include "hci_request.h" |
| 35 | 35 | #include "hci_debugfs.h" |
| 36 | +#include "hci_codec.h" | |
| 36 | 37 | #include "a2mp.h" |
| 37 | 38 | #include "amp.h" |
| 38 | 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 | 71 | void hci_req_add_le_scan_disable(struct hci_request *req, bool rpa_le_conn); |
| 72 | 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 | 74 | void hci_request_setup(struct hci_dev *hdev); |
| 77 | 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 | 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 | 416 | static void le_scan_restart(struct work_struct *work) |
| 422 | 417 | { |
| 423 | 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 | 423 | bt_dev_dbg(hdev, ""); |
| 429 | 424 | |
| 430 | − hci_dev_lock(hdev); | |
| 431 | − | |
| 432 | − status = hci_cmd_sync_queue(hdev, le_scan_restart_sync, NULL, NULL); | |
| 425 | + status = hci_le_scan_restart_sync(hdev); | |
| 433 | 426 | if (status) { |
| 434 | 427 | bt_dev_err(hdev, "failed to restart LE scan: status %d", |
| 435 | 428 | status); |
| 436 | − goto unlock; | |
| 429 | + return; | |
| 437 | 430 | } |
| 438 | 431 | |
| 432 | + hci_dev_lock(hdev); | |
| 433 | + | |
| 439 | 434 | if (!test_bit(HCI_QUIRK_STRICT_DUPLICATE_FILTER, &hdev->quirks) || |
| 440 | 435 | !hdev->discovery.scan_start) |
| 441 | 436 | goto unlock; |
| @@ -5079,6 +5074,7 @@ int hci_dev_close_sync(struct hci_dev *hdev) · 4637 unmodified lines | ||
| 5079 | 5074 | memset(hdev->eir, 0, sizeof(hdev->eir)); |
| 5080 | 5075 | memset(hdev->dev_class, 0, sizeof(hdev->dev_class)); |
| 5081 | 5076 | bacpy(&hdev->random_addr, BDADDR_ANY); |
| 5077 | + hci_codec_list_clear(&hdev->local_codecs); | |
| 5082 | 5078 | |
| 5083 | 5079 | hci_dev_put(hdev); |
| 5084 | 5080 | return err; |
| @@ -502,7 +502,7 @@ drop: · 501 unmodified lines | ||
| 502 | 502 | } |
| 503 | 503 | |
| 504 | 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 | 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 | 510 | if (sk->sk_state != BT_LISTEN) |
| 511 | 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 | 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 | 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 | 959 | err = -EADDRINUSE; |
| 957 | 960 | |
| 958 | 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 | 294 | /* tell br_dev_xmit to continue with forwarding */ |
| 295 | 295 | nf_bridge->bridged_dnat = 1; |
| 296 | 296 | /* FIXME Need to refragment */ |
| 297 | − ret = neigh->output(neigh, skb); | |
| 297 | + ret = READ_ONCE(neigh->output)(neigh, skb); | |
| 298 | 298 | } |
| 299 | 299 | neigh_release(neigh); |
| 300 | 300 | return ret; |
| @@ -948,21 +948,18 @@ static int isotp_sendmsg(struct socket *sock, struct msghdr *msg, size_t size) · 947 unmodified lines | ||
| 948 | 948 | if (!so->bound || so->tx.state == ISOTP_SHUTDOWN) |
| 949 | 949 | return -EADDRNOTAVAIL; |
| 950 | 950 | |
| 951 | −wait_free_buffer: | |
| 952 | − /* we do not support multiple buffers - for now */ | |
| 953 | − if (wq_has_sleeper(&so->wait) && (msg->msg_flags & MSG_DONTWAIT)) | |
| 954 | − return -EAGAIN; | |
| 951 | + while (cmpxchg(&so->tx.state, ISOTP_IDLE, ISOTP_SENDING) != ISOTP_IDLE) { | |
| 952 | + /* we do not support multiple buffers - for now */ | |
| 953 | + if (msg->msg_flags & MSG_DONTWAIT) | |
| 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 | 956 | if (so->tx.state == ISOTP_SHUTDOWN) |
| 963 | 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 | 965 | /* PDU size > default => try max_pdu_size */ |
| @@ -459,8 +459,8 @@ int ceph_tcp_connect(struct ceph_connection *con) · 458 unmodified lines | ||
| 459 | 459 | set_sock_callbacks(sock, con); |
| 460 | 460 | |
| 461 | 461 | con_sock_state_connecting(con); |
| 462 | − ret = sock->ops->connect(sock, (struct sockaddr *)&ss, sizeof(ss), | |
| 463 | − O_NONBLOCK); | |
| 462 | + ret = kernel_connect(sock, (struct sockaddr *)&ss, sizeof(ss), | |
| 463 | + O_NONBLOCK); | |
| 464 | 464 | if (ret == -EINPROGRESS) { |
| 465 | 465 | dout("connect %s EINPROGRESS sk_state = %u\n", |
| 466 | 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 | 3293 | offset = skb_checksum_start_offset(skb); |
| 3294 | 3294 | ret = -EINVAL; |
| 3295 | − if (WARN_ON_ONCE(offset >= skb_headlen(skb))) { | |
| 3295 | + if (unlikely(offset >= skb_headlen(skb))) { | |
| 3296 | 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 | 3299 | goto out; |
| 3298 | 3300 | } |
| 3299 | 3301 | csum = skb_checksum(skb, offset, skb->len - offset, 0); |
| 3300 | 3302 | |
| 3301 | 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 | 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 | 3308 | goto out; |
| 3305 | 3309 | } |
| 3306 | 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 | 411 | __skb_queue_purge(&n->arp_queue); |
| 412 | 412 | n->arp_queue_len_bytes = 0; |
| 413 | − n->output = neigh_blackhole; | |
| 413 | + WRITE_ONCE(n->output, neigh_blackhole); | |
| 414 | 414 | if (n->nud_state & NUD_VALID) |
| 415 | 415 | n->nud_state = NUD_NOARP; |
| 416 | 416 | else |
| @@ -920,7 +920,7 @@ static void neigh_suspect(struct neighbour *neigh) · 503 unmodified lines | ||
| 920 | 920 | { |
| 921 | 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 | 926 | /* Neighbour state is OK; |
| @@ -932,7 +932,7 @@ static void neigh_connect(struct neighbour *neigh) · 5 unmodified lines | ||
| 932 | 932 | { |
| 933 | 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 | 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 | 988 | (state == NUD_FAILED || |
| 989 | 989 | !time_in_range_open(jiffies, n->used, |
| 990 | 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 | 994 | neigh_mark_dead(n); |
| 993 | 995 | write_unlock(&n->lock); |
| 994 | 996 | neigh_cleanup_and_release(n); |
| @@ -1447,7 +1449,7 @@ static int __neigh_update(struct neighbour *neigh, const u8 *lladdr, · 452 unmodified lines | ||
| 1447 | 1449 | if (n2) |
| 1448 | 1450 | n1 = n2; |
| 1449 | 1451 | } |
| 1450 | − n1->output(n1, skb); | |
| 1452 | + READ_ONCE(n1->output)(n1, skb); | |
| 1451 | 1453 | if (n2) |
| 1452 | 1454 | neigh_release(n2); |
| 1453 | 1455 | rcu_read_unlock(); |
| @@ -3153,7 +3155,7 @@ int neigh_xmit(int index, struct net_device *dev, · 1699 unmodified lines | ||
| 3153 | 3155 | rcu_read_unlock(); |
| 3154 | 3156 | goto out_kfree_skb; |
| 3155 | 3157 | } |
| 3156 | − err = neigh->output(neigh, skb); | |
| 3158 | + err = READ_ONCE(neigh->output)(neigh, skb); | |
| 3157 | 3159 | rcu_read_unlock(); |
| 3158 | 3160 | } |
| 3159 | 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 | 668 | sk = __sock_map_lookup_elem(map, key); |
| 669 | 669 | if (unlikely(!sk || !sock_map_redirect_allowed(sk))) |
| 670 | 670 | return SK_DROP; |
| 671 | + if (!(flags & BPF_F_INGRESS) && !sk_is_tcp(sk)) | |
| 672 | + return SK_DROP; | |
| 671 | 673 | |
| 672 | 674 | msg->flags = flags; |
| 673 | 675 | msg->sk_redir = sk; |
| @@ -1267,6 +1269,8 @@ BPF_CALL_4(bpf_msg_redirect_hash, struct sk_msg *, msg, · 593 unmodified lines | ||
| 1267 | 1269 | sk = __sock_hash_lookup_elem(map, key); |
| 1268 | 1270 | if (unlikely(!sk || !sock_map_redirect_allowed(sk))) |
| 1269 | 1271 | return SK_DROP; |
| 1272 | + if (!(flags & BPF_F_INGRESS) && !sk_is_tcp(sk)) | |
| 1273 | + return SK_DROP; | |
| 1270 | 1274 | |
| 1271 | 1275 | msg->flags = flags; |
| 1272 | 1276 | msg->sk_redir = sk; |
| @@ -58,7 +58,6 @@ struct devlink_health_reporter { · 57 unmodified lines | ||
| 58 | 58 | struct devlink *devlink; |
| 59 | 59 | struct devlink_port *devlink_port; |
| 60 | 60 | struct devlink_fmsg *dump_fmsg; |
| 61 | − struct mutex dump_lock; /* lock parallel read/write from dump buffers */ | |
| 62 | 61 | u64 graceful_period; |
| 63 | 62 | bool auto_recover; |
| 64 | 63 | bool auto_dump; |
| @@ -125,7 +124,6 @@ __devlink_health_reporter_create(struct devlink *devlink, · 60 unmodified lines | ||
| 125 | 124 | reporter->graceful_period = graceful_period; |
| 126 | 125 | reporter->auto_recover = !!ops->recover; |
| 127 | 126 | reporter->auto_dump = !!ops->dump; |
| 128 | − mutex_init(&reporter->dump_lock); | |
| 129 | 127 | return reporter; |
| 130 | 128 | } |
| 131 | 129 | |
| @@ -226,7 +224,6 @@ EXPORT_SYMBOL_GPL(devlink_health_reporter_create); · 94 unmodified lines | ||
| 226 | 224 | static void |
| 227 | 225 | devlink_health_reporter_free(struct devlink_health_reporter *reporter) |
| 228 | 226 | { |
| 229 | − mutex_destroy(&reporter->dump_lock); | |
| 230 | 227 | if (reporter->dump_fmsg) |
| 231 | 228 | devlink_fmsg_free(reporter->dump_fmsg); |
| 232 | 229 | kfree(reporter); |
| @@ -625,10 +622,10 @@ int devlink_health_report(struct devlink_health_reporter *reporter, · 392 unmodified lines | ||
| 625 | 622 | } |
| 626 | 623 | |
| 627 | 624 | if (reporter->auto_dump) { |
| 628 | − mutex_lock(&reporter->dump_lock); | |
| 625 | + devl_lock(devlink); | |
| 629 | 626 | /* store current dump of current error, for later analysis */ |
| 630 | 627 | devlink_health_do_dump(reporter, priv_ctx, NULL); |
| 631 | − mutex_unlock(&reporter->dump_lock); | |
| 628 | + devl_unlock(devlink); | |
| 632 | 629 | } |
| 633 | 630 | |
| 634 | 631 | if (!reporter->auto_recover) |
| @@ -1262,7 +1259,7 @@ out: · 627 unmodified lines | ||
| 1262 | 1259 | } |
| 1263 | 1260 | |
| 1264 | 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 | 1264 | const struct genl_info *info = genl_info_dump(cb); |
| 1268 | 1265 | struct devlink_health_reporter *reporter; |
| @@ -1272,10 +1269,12 @@ devlink_health_reporter_get_from_cb(struct netlink_callback *cb) · 3 unmodified lines | ||
| 1272 | 1269 | devlink = devlink_get_from_attrs_lock(sock_net(cb->skb->sk), attrs); |
| 1273 | 1270 | if (IS_ERR(devlink)) |
| 1274 | 1271 | return NULL; |
| 1275 | − devl_unlock(devlink); | |
| 1276 | 1272 | |
| 1277 | 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 | 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 | 1284 | struct devlink_nl_dump_state *state = devlink_dump_state(cb); |
| 1286 | 1285 | struct devlink_health_reporter *reporter; |
| 1286 | + struct devlink *devlink; | |
| 1287 | 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 | 1290 | if (!reporter) |
| 1291 | 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 | 1297 | return -EOPNOTSUPP; |
| 1298 | + } | |
| 1295 | 1299 | |
| 1296 | − mutex_lock(&reporter->dump_lock); | |
| 1297 | 1300 | if (!state->idx) { |
| 1298 | 1301 | err = devlink_health_do_dump(reporter, NULL, cb->extack); |
| 1299 | 1302 | if (err) |
| @@ -1309,7 +1312,8 @@ int devlink_nl_cmd_health_reporter_dump_get_dumpit(struct sk_buff *skb, · 9 unmodified lines | ||
| 1309 | 1312 | err = devlink_fmsg_dumpit(reporter->dump_fmsg, skb, cb, |
| 1310 | 1313 | DEVLINK_CMD_HEALTH_REPORTER_DUMP_GET); |
| 1311 | 1314 | unlock: |
| 1312 | − mutex_unlock(&reporter->dump_lock); | |
| 1315 | + devl_unlock(devlink); | |
| 1316 | + devlink_put(devlink); | |
| 1313 | 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 | 1330 | if (!reporter->ops->dump) |
| 1327 | 1331 | return -EOPNOTSUPP; |
| 1328 | 1332 | |
| 1329 | − mutex_lock(&reporter->dump_lock); | |
| 1330 | 1333 | devlink_health_dump_clear(reporter); |
| 1331 | − mutex_unlock(&reporter->dump_lock); | |
| 1332 | 1334 | return 0; |
| 1333 | 1335 | } |
| 1334 | 1336 | |
| @@ -431,8 +431,10 @@ ethnl_update_bitset32_verbose(u32 *bitmap, unsigned int nbits, · 430 unmodified lines | ||
| 431 | 431 | ethnl_string_array_t names, |
| 432 | 432 | struct netlink_ext_ack *extack, bool *mod) |
| 433 | 433 | { |
| 434 | + u32 *orig_bitmap, *saved_bitmap = NULL; | |
| 434 | 435 | struct nlattr *bit_attr; |
| 435 | 436 | bool no_mask; |
| 437 | + bool dummy; | |
| 436 | 438 | int rem; |
| 437 | 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 | 452 | no_mask = tb[ETHTOOL_A_BITSET_NOMASK]; |
| 451 | − if (no_mask) | |
| 452 | − ethnl_bitmap32_clear(bitmap, 0, nbits, mod); | |
| 453 | + if (no_mask) { | |
| 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 | 470 | nla_for_each_nested(bit_attr, tb[ETHTOOL_A_BITSET_BITS], rem) { |
| 455 | 471 | bool old_val, new_val; |
| @@ -458,13 +474,14 @@ ethnl_update_bitset32_verbose(u32 *bitmap, unsigned int nbits, · 2 unmodified lines | ||
| 458 | 474 | if (nla_type(bit_attr) != ETHTOOL_A_BITSET_BITS_BIT) { |
| 459 | 475 | NL_SET_ERR_MSG_ATTR(extack, bit_attr, |
| 460 | 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 | 480 | ret = ethnl_parse_bit(&idx, &new_val, nbits, bit_attr, no_mask, |
| 464 | 481 | names, extack); |
| 465 | 482 | if (ret < 0) |
| 466 | − return ret; | |
| 467 | − old_val = bitmap[idx / 32] & ((u32)1 << (idx % 32)); | |
| 483 | + goto out; | |
| 484 | + old_val = orig_bitmap[idx / 32] & ((u32)1 << (idx % 32)); | |
| 468 | 485 | if (new_val != old_val) { |
| 469 | 486 | if (new_val) |
| 470 | 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 | 500 | static int ethnl_compact_sanity_checks(unsigned int nbits, |
| @@ -21,16 +21,6 @@ struct plca_reply_data { · 20 unmodified lines | ||
| 21 | 21 | #define PLCA_REPDATA(__reply_base) \ |
| 22 | 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 | 24 | // PLCA get configuration message ------------------------------------------- // |
| 35 | 25 | |
| 36 | 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 | 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 | 54 | static int plca_get_cfg_prepare_data(const struct ethnl_req_info *req_base, |
| 42 | 55 | struct ethnl_reply_data *reply_base, |
| 43 | 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 | 157 | return -EOPNOTSUPP; |
| 145 | 158 | |
| 146 | 159 | memset(&plca_cfg, 0xff, sizeof(plca_cfg)); |
| 147 | − 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); | |
| 149 | − 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); | |
| 151 | − plca_update_sint(&plca_cfg.burst_cnt, tb[ETHTOOL_A_PLCA_BURST_CNT], | |
| 160 | + plca_update_sint(&plca_cfg.enabled, tb, ETHTOOL_A_PLCA_ENABLED, &mod); | |
| 161 | + plca_update_sint(&plca_cfg.node_id, tb, ETHTOOL_A_PLCA_NODE_ID, &mod); | |
| 162 | + plca_update_sint(&plca_cfg.node_cnt, tb, ETHTOOL_A_PLCA_NODE_CNT, &mod); | |
| 163 | + plca_update_sint(&plca_cfg.to_tmr, tb, ETHTOOL_A_PLCA_TO_TMR, &mod); | |
| 164 | + plca_update_sint(&plca_cfg.burst_cnt, tb, ETHTOOL_A_PLCA_BURST_CNT, | |
| 152 | 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 | 167 | &mod); |
| 155 | 168 | if (!mod) |
| 156 | 169 | return 0; |
| @@ -1887,6 +1887,7 @@ int fib_sync_down_addr(struct net_device *dev, __be32 local) · 1886 unmodified lines | ||
| 1887 | 1887 | continue; |
| 1888 | 1888 | if (fi->fib_prefsrc == local) { |
| 1889 | 1889 | fi->fib_flags |= RTNH_F_DEAD; |
| 1890 | + fi->pfsrc_removed = true; | |
| 1890 | 1891 | ret++; |
| 1891 | 1892 | } |
| 1892 | 1893 | } |
| @@ -2027,6 +2027,7 @@ void fib_table_flush_external(struct fib_table *tb) · 2026 unmodified lines | ||
| 2027 | 2027 | int fib_table_flush(struct net *net, struct fib_table *tb, bool flush_all) |
| 2028 | 2028 | { |
| 2029 | 2029 | struct trie *t = (struct trie *)tb->tb_data; |
| 2030 | + struct nl_info info = { .nl_net = net }; | |
| 2030 | 2031 | struct key_vector *pn = t->kv; |
| 2031 | 2032 | unsigned long cindex = 1; |
| 2032 | 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 | 2091 | fib_notify_alias_delete(net, n->key, &n->leaf, fa, |
| 2091 | 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 | 2096 | hlist_del_rcu(&fa->fa_list); |
| 2093 | 2097 | fib_release_info(fa->fa_info); |
| 2094 | 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 | 3417 | fa->fa_type == fri.type) { |
| 3418 | 3418 | fri.offload = READ_ONCE(fa->offload); |
| 3419 | 3419 | fri.trap = READ_ONCE(fa->trap); |
| 3420 | + fri.offload_failed = | |
| 3421 | + READ_ONCE(fa->offload_failed); | |
| 3420 | 3422 | break; |
| 3421 | 3423 | } |
| 3422 | 3424 | } |
| @@ -1621,16 +1621,13 @@ EXPORT_SYMBOL(tcp_read_sock); · 1620 unmodified lines | ||
| 1621 | 1621 | |
| 1622 | 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 | 1624 | struct sk_buff *skb; |
| 1627 | 1625 | int copied = 0; |
| 1628 | − u32 offset; | |
| 1629 | 1626 | |
| 1630 | 1627 | if (sk->sk_state == TCP_LISTEN) |
| 1631 | 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 | 1631 | u8 tcp_flags; |
| 1635 | 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 | 1640 | copied = used; |
| 1644 | 1641 | break; |
| 1645 | 1642 | } |
| 1646 | − seq += used; | |
| 1647 | 1643 | copied += used; |
| 1648 | 1644 | |
| 1649 | − if (tcp_flags & TCPHDR_FIN) { | |
| 1650 | − ++seq; | |
| 1645 | + if (tcp_flags & TCPHDR_FIN) | |
| 1651 | 1646 | break; |
| 1652 | − } | |
| 1653 | 1647 | } |
| 1654 | 1648 | return copied; |
| 1655 | 1649 | } |
| @@ -222,6 +222,7 @@ static int tcp_bpf_recvmsg_parser(struct sock *sk, · 221 unmodified lines | ||
| 222 | 222 | int *addr_len) |
| 223 | 223 | { |
| 224 | 224 | struct tcp_sock *tcp = tcp_sk(sk); |
| 225 | + int peek = flags & MSG_PEEK; | |
| 225 | 226 | u32 seq = tcp->copied_seq; |
| 226 | 227 | struct sk_psock *psock; |
| 227 | 228 | int copied = 0; |
| @@ -311,7 +312,8 @@ msg_bytes_ready: · 83 unmodified lines | ||
| 311 | 312 | copied = -EAGAIN; |
| 312 | 313 | } |
| 313 | 314 | out: |
| 314 | − WRITE_ONCE(tcp->copied_seq, seq); | |
| 315 | + if (!peek) | |
| 316 | + WRITE_ONCE(tcp->copied_seq, seq); | |
| 315 | 317 | tcp_rcv_space_adjust(sk); |
| 316 | 318 | if (copied > 0) |
| 317 | 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 | 253 | if (unlikely(len > icsk->icsk_ack.rcv_mss + |
| 254 | 254 | MAX_TCP_OPTION_SPACE)) |
| 255 | 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 | 269 | } else { |
| 257 | 270 | /* Otherwise, we make more careful check taking into account, |
| 258 | 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 | 179 | /* Account for an ACK we sent. */ |
| 180 | −static inline void tcp_event_ack_sent(struct sock *sk, unsigned int pkts, | |
| 181 | − u32 rcv_nxt) | |
| 180 | +static inline void tcp_event_ack_sent(struct sock *sk, u32 rcv_nxt) | |
| 182 | 181 | { |
| 183 | 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 | 192 | if (unlikely(rcv_nxt != tp->rcv_nxt)) |
| 194 | 193 | return; /* Special ACK sent by DCTCP to reflect ECN */ |
| 195 | − tcp_dec_quickack_mode(sk, pkts); | |
| 194 | + tcp_dec_quickack_mode(sk); | |
| 196 | 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 | 1386 | sk, skb); |
| 1388 | 1387 | |
| 1389 | 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 | 1391 | if (skb->len != tcp_header_size) { |
| 1393 | 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 | 2457 | /* build the payload, and be prepared to abort if this fails. */ |
| 2459 | 2458 | if (tcp_clone_payload(sk, nskb, probe_size)) { |
| 2459 | + tcp_skb_tsorted_anchor_cleanup(nskb); | |
| 2460 | 2460 | consume_skb(nskb); |
| 2461 | 2461 | return -1; |
| 2462 | 2462 | } |
| @@ -1640,9 +1640,12 @@ process: · 1639 unmodified lines | ||
| 1640 | 1640 | struct sock *nsk; |
| 1641 | 1641 | |
| 1642 | 1642 | sk = req->rsk_listener; |
| 1643 | − drop_reason = tcp_inbound_md5_hash(sk, skb, | |
| 1644 | − &hdr->saddr, &hdr->daddr, | |
| 1645 | − AF_INET6, dif, sdif); | |
| 1643 | + if (!xfrm6_policy_check(sk, XFRM_POLICY_IN, skb)) | |
| 1644 | + drop_reason = SKB_DROP_REASON_XFRM_POLICY; | |
| 1645 | + else | |
| 1646 | + drop_reason = tcp_inbound_md5_hash(sk, skb, | |
| 1647 | + &hdr->saddr, &hdr->daddr, | |
| 1648 | + AF_INET6, dif, sdif); | |
| 1646 | 1649 | if (drop_reason) { |
| 1647 | 1650 | sk_drops_add(sk, skb); |
| 1648 | 1651 | reqsk_put(req); |
| @@ -1689,6 +1692,7 @@ process: · 40 unmodified lines | ||
| 1689 | 1692 | } |
| 1690 | 1693 | goto discard_and_relse; |
| 1691 | 1694 | } |
| 1695 | + nf_reset_ct(skb); | |
| 1692 | 1696 | if (nsk == sk) { |
| 1693 | 1697 | reqsk_put(req); |
| 1694 | 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 | 508 | if (len > INT_MAX - transhdrlen) |
| 509 | 509 | return -EMSGSIZE; |
| 510 | − ulen = len + transhdrlen; | |
| 511 | 510 | |
| 512 | 511 | /* Mirror BSD error message compatibility */ |
| 513 | 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 | 628 | back_from_confirm: |
| 630 | 629 | lock_sock(sk); |
| 630 | + ulen = len + skb_queue_empty(&sk->sk_write_queue) ? transhdrlen : 0; | |
| 631 | 631 | err = ip6_append_data(sk, ip_generic_getfrag, msg, |
| 632 | 632 | ulen, transhdrlen, &ipc6, |
| 633 | 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 | 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 | 573 | out_unlock: |
| 571 | 574 | mutex_unlock(&local->sta_mtx); |
| @@ -1857,7 +1860,8 @@ static int sta_link_apply_parameters(struct ieee80211_local *local, · 1285 unmodified lines | ||
| 1857 | 1860 | /* VHT can override some HT caps such as the A-MSDU max length */ |
| 1858 | 1861 | if (params->vht_capa) |
| 1859 | 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 | 1866 | if (params->he_capa) |
| 1863 | 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 | 1072 | &chandef); |
| 1073 | 1073 | memcpy(&cap_ie, elems->vht_cap_elem, sizeof(cap_ie)); |
| 1074 | 1074 | ieee80211_vht_cap_ie_to_sta_vht_cap(sdata, sband, |
| 1075 | − &cap_ie, | |
| 1075 | + &cap_ie, NULL, | |
| 1076 | 1076 | &sta->deflink); |
| 1077 | 1077 | if (memcmp(&cap, &sta->sta.deflink.vht_cap, sizeof(cap))) |
| 1078 | 1078 | rates_updated |= true; |
| @@ -676,7 +676,7 @@ struct ieee80211_if_mesh { · 675 unmodified lines | ||
| 676 | 676 | struct timer_list mesh_path_root_timer; |
| 677 | 677 | |
| 678 | 678 | unsigned long wrkq_flags; |
| 679 | − unsigned long mbss_changed; | |
| 679 | + unsigned long mbss_changed[64 / BITS_PER_LONG]; | |
| 680 | 680 | |
| 681 | 681 | bool userspace_handles_dfs; |
| 682 | 682 | |
| @@ -2141,6 +2141,7 @@ void · 1458 unmodified lines | ||
| 2141 | 2141 | ieee80211_vht_cap_ie_to_sta_vht_cap(struct ieee80211_sub_if_data *sdata, |
| 2142 | 2142 | struct ieee80211_supported_band *sband, |
| 2143 | 2143 | const struct ieee80211_vht_cap *vht_cap_ie, |
| 2144 | + const struct ieee80211_vht_cap *vht_cap_ie2, | |
| 2144 | 2145 | struct link_sta_info *link_sta); |
| 2145 | 2146 | enum ieee80211_sta_rx_bandwidth |
| 2146 | 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 | 803 | void ieee80211_key_free_unused(struct ieee80211_key *key) |
| 804 | 804 | { |
| 805 | + if (!key) | |
| 806 | + return; | |
| 807 | + | |
| 805 | 808 | WARN_ON(key->sdata || key->local); |
| 806 | 809 | ieee80211_key_free_common(key); |
| 807 | 810 | } |
| @@ -854,7 +857,7 @@ int ieee80211_key_link(struct ieee80211_key *key, · 46 unmodified lines | ||
| 854 | 857 | * can cause warnings to appear. |
| 855 | 858 | */ |
| 856 | 859 | bool delay_tailroom = sdata->vif.type == NL80211_IFTYPE_STATION; |
| 857 | − int ret = -EOPNOTSUPP; | |
| 860 | + int ret; | |
| 858 | 861 | |
| 859 | 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 | 871 | * the same cipher. Enforce the assumption for pairwise keys. |
| 869 | 872 | */ |
| 870 | 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 | 876 | goto out; |
| 877 | + } | |
| 873 | 878 | } else if (sta) { |
| 874 | 879 | struct link_sta_info *link_sta = &sta->deflink; |
| 875 | 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 | 901 | /* Non-pairwise keys must also not switch the cipher on rekey */ |
| 897 | 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 | 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 | 911 | * new version of the key to avoid nonce reuse or replay issues. |
| 905 | 912 | */ |
| 906 | 913 | if (ieee80211_key_identical(sdata, old_key, key)) { |
| 907 | − ieee80211_key_free_unused(key); | |
| 908 | − ret = 0; | |
| 909 | − goto out; | |
| 914 | + ret = -EALREADY; | |
| 915 | + goto unlock; | |
| 910 | 916 | } |
| 911 | 917 | |
| 912 | 918 | key->local = sdata->local; |
| @@ -930,7 +936,11 @@ int ieee80211_key_link(struct ieee80211_key *key, · 17 unmodified lines | ||
| 930 | 936 | ieee80211_key_free(key, delay_tailroom); |
| 931 | 937 | } |
| 932 | 938 | |
| 939 | + key = NULL; | |
| 940 | + | |
| 933 | 941 | out: |
| 942 | + ieee80211_key_free_unused(key); | |
| 943 | + unlock: | |
| 934 | 944 | mutex_unlock(&sdata->local->key_mtx); |
| 935 | 945 | |
| 936 | 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 | 1176 | /* if we race with running work, worst case this work becomes a noop */ |
| 1177 | 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 | 1179 | set_bit(MESH_WORK_MBSS_CHANGED, &ifmsh->wrkq_flags); |
| 1180 | 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 | 1258 | /* clear any mesh work (for next join) we may have accrued */ |
| 1259 | 1259 | ifmsh->wrkq_flags = 0; |
| 1260 | − ifmsh->mbss_changed = 0; | |
| 1260 | + memset(ifmsh->mbss_changed, 0, sizeof(ifmsh->mbss_changed)); | |
| 1261 | 1261 | |
| 1262 | 1262 | local->fif_other_bss--; |
| 1263 | 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 | 1724 | u32 bit; |
| 1725 | 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 | 1728 | sizeof(changed) * BITS_PER_BYTE) { |
| 1729 | − clear_bit(bit, &ifmsh->mbss_changed); | |
| 1729 | + clear_bit(bit, ifmsh->mbss_changed); | |
| 1730 | 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 | 451 | changed |= IEEE80211_RC_BW_CHANGED; |
| 452 | 452 | |
| 453 | 453 | ieee80211_vht_cap_ie_to_sta_vht_cap(sdata, sband, |
| 454 | − elems->vht_cap_elem, | |
| 454 | + elems->vht_cap_elem, NULL, | |
| 455 | 455 | &sta->deflink); |
| 456 | 456 | |
| 457 | 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 | 4202 | elems->ht_cap_elem, |
| 4203 | 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 | 4227 | ieee80211_vht_cap_ie_to_sta_vht_cap(sdata, sband, |
| 4207 | 4228 | elems->vht_cap_elem, |
| 4208 | − link_sta); | |
| 4229 | + bss_vht_cap, link_sta); | |
| 4230 | + rcu_read_unlock(); | |
| 4231 | + } | |
| 4209 | 4232 | |
| 4210 | 4233 | if (elems->he_operation && !(link->u.mgd.conn_flags & IEEE80211_CONN_DISABLE_HE) && |
| 4211 | 4234 | elems->he_cap) { |
| @@ -5107,9 +5130,10 @@ static bool ieee80211_assoc_success(struct ieee80211_sub_if_data *sdata, · 895 unmodified lines | ||
| 5107 | 5130 | continue; |
| 5108 | 5131 | |
| 5109 | 5132 | valid_links |= BIT(link_id); |
| 5110 | − if (assoc_data->link[link_id].disabled) { | |
| 5133 | + if (assoc_data->link[link_id].disabled) | |
| 5111 | 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 | 5137 | err = ieee80211_sta_allocate_link(sta, link_id); |
| 5114 | 5138 | if (err) |
| 5115 | 5139 | goto out_err; |
| @@ -5124,7 +5148,7 @@ static bool ieee80211_assoc_success(struct ieee80211_sub_if_data *sdata, · 8 unmodified lines | ||
| 5124 | 5148 | struct ieee80211_link_data *link; |
| 5125 | 5149 | struct link_sta_info *link_sta; |
| 5126 | 5150 | |
| 5127 | − if (!cbss || assoc_data->link[link_id].disabled) | |
| 5151 | + if (!cbss) | |
| 5128 | 5152 | continue; |
| 5129 | 5153 | |
| 5130 | 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 | 5453 | for (link_id = 0; link_id < IEEE80211_MLD_MAX_NUM_LINKS; link_id++) { |
| 5430 | 5454 | struct ieee80211_link_data *link; |
| 5431 | 5455 | |
| 5432 | − link = sdata_dereference(sdata->link[link_id], sdata); | |
| 5433 | − if (!link) | |
| 5434 | − continue; | |
| 5435 | − | |
| 5436 | 5456 | if (!assoc_data->link[link_id].bss) |
| 5437 | 5457 | continue; |
| 5438 | 5458 | |
| 5439 | 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 | 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 | 5468 | /* get uapsd queues configuration - same for all links */ |
| 5444 | 5469 | resp.uapsd_queues = 0; |
| 5445 | 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 | 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 | 670 | return TX_DROP; |
| 670 | 671 | |
| 671 | 672 | if (!skip_hw && tx->key && |
| @@ -4,7 +4,7 @@ · 3 unmodified lines | ||
| 4 | 4 | * |
| 5 | 5 | * Portions of this file |
| 6 | 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 | 10 | #include <linux/ieee80211.h> |
| @@ -116,12 +116,14 @@ void · 105 unmodified lines | ||
| 116 | 116 | ieee80211_vht_cap_ie_to_sta_vht_cap(struct ieee80211_sub_if_data *sdata, |
| 117 | 117 | struct ieee80211_supported_band *sband, |
| 118 | 118 | const struct ieee80211_vht_cap *vht_cap_ie, |
| 119 | + const struct ieee80211_vht_cap *vht_cap_ie2, | |
| 119 | 120 | struct link_sta_info *link_sta) |
| 120 | 121 | { |
| 121 | 122 | struct ieee80211_sta_vht_cap *vht_cap = &link_sta->pub->vht_cap; |
| 122 | 123 | struct ieee80211_sta_vht_cap own_cap; |
| 123 | 124 | u32 cap_info, i; |
| 124 | 125 | bool have_80mhz; |
| 126 | + u32 mpdu_len; | |
| 125 | 127 | |
| 126 | 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 | 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 | 333 | * FIXME - should the amsdu len be per link? store per link |
| 322 | 334 | * and maintain a minimum? |
| 323 | 335 | */ |
| 324 | − switch (vht_cap->cap & IEEE80211_VHT_CAP_MAX_MPDU_MASK) { | |
| 336 | + switch (mpdu_len) { | |
| 325 | 337 | case IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_11454: |
| 326 | 338 | link_sta->pub->agg.max_amsdu_len = IEEE80211_MAX_MPDU_LEN_VHT_11454; |
| 327 | 339 | break; |
| @@ -737,6 +737,8 @@ struct mctp_route *mctp_route_lookup(struct net *net, unsigned int dnet, · 736 unmodified lines | ||
| 737 | 737 | { |
| 738 | 738 | struct mctp_route *tmp, *rt = NULL; |
| 739 | 739 | |
| 740 | + rcu_read_lock(); | |
| 741 | + | |
| 740 | 742 | list_for_each_entry_rcu(tmp, &net->mctp.routes, list) { |
| 741 | 743 | /* TODO: add metrics */ |
| 742 | 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 | 754 | return rt; |
| 751 | 755 | } |
| 752 | 756 | |
| 753 | 757 | static struct mctp_route *mctp_route_lookup_null(struct net *net, |
| 754 | 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) { | |
| 759 | − if (rt->dev->dev == dev && rt->type == RTN_LOCAL && | |
| 760 | − refcount_inc_not_zero(&rt->refs)) | |
| 761 | − return rt; | |
| 762 | + rcu_read_lock(); | |
| 763 | + | |
| 764 | + list_for_each_entry_rcu(tmp, &net->mctp.routes, list) { | |
| 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 | 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 | 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 | 310 | err = mptcp_pm_parse_addr(raddr, info, &addr_r); |
| 317 | 311 | if (err < 0) { |
| 318 | 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 | 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 | 3430 | struct mptcp_subflow_context *subflow = mptcp_subflow_ctx(ssk); |
| 3431 | 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 | 3434 | mptcp_data_lock(sk); |
| 3435 | 3435 | if (!sock_owned_by_user(sk)) |
| 3436 | 3436 | __mptcp_subflow_push_pending(sk, ssk, true); |
| 3437 | 3437 | else |
| 3438 | 3438 | __set_bit(MPTCP_PUSH_PENDING, &mptcp_sk(sk)->cb_flags); |
| 3439 | 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 | 3442 | schedule_3rdack_retransmission(ssk); |
| 3444 | − mptcp_subflow_delegated_done(subflow, MPTCP_DELEGATE_ACK); | |
| 3445 | − } | |
| 3446 | 3443 | } |
| 3447 | 3444 | |
| 3448 | 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 | 3965 | struct sock *ssk = mptcp_subflow_tcp_sock(subflow); |
| 3969 | 3966 | |
| 3970 | 3967 | bh_lock_sock_nested(ssk); |
| 3971 | − if (!sock_owned_by_user(ssk) && | |
| 3972 | − mptcp_subflow_has_delegated_action(subflow)) | |
| 3973 | − mptcp_subflow_process_delegated(ssk); | |
| 3974 | − /* ... elsewhere tcp_release_cb_override already processed | |
| 3975 | − * the action or will do at next release_sock(). | |
| 3976 | − * In both case must dequeue the subflow here - on the same | |
| 3977 | − * CPU that scheduled it. | |
| 3978 | − */ | |
| 3968 | + if (!sock_owned_by_user(ssk)) { | |
| 3969 | + mptcp_subflow_process_delegated(ssk, xchg(&subflow->delegated_status, 0)); | |
| 3970 | + } else { | |
| 3971 | + /* tcp_release_cb_override already processed | |
| 3972 | + * the action or will do at next release_sock(). | |
| 3973 | + * In both case must dequeue the subflow here - on the same | |
| 3974 | + * CPU that scheduled it. | |
| 3975 | + */ | |
| 3976 | + smp_wmb(); | |
| 3977 | + clear_bit(MPTCP_DELEGATE_SCHEDULED, &subflow->delegated_status); | |
| 3978 | + } | |
| 3979 | 3979 | bh_unlock_sock(ssk); |
| 3980 | 3980 | sock_put(ssk); |
| 3981 | 3981 | |
| @@ -444,9 +444,11 @@ struct mptcp_delegated_action { · 443 unmodified lines | ||
| 444 | 444 | |
| 445 | 445 | DECLARE_PER_CPU(struct mptcp_delegated_action, mptcp_delegated_actions); |
| 446 | 446 | |
| 447 | −#define MPTCP_DELEGATE_SEND 0 | |
| 448 | −#define MPTCP_DELEGATE_ACK 1 | |
| 447 | +#define MPTCP_DELEGATE_SCHEDULED 0 | |
| 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 | 452 | /* MPTCP subflow context */ |
| 451 | 453 | struct mptcp_subflow_context { |
| 452 | 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 | 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 | 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 | 574 | struct mptcp_delegated_action *delegated; |
| 572 | 575 | bool schedule; |
| 573 | 576 | |
| 574 | 577 | /* the caller held the subflow bh socket lock */ |
| 575 | 578 | lockdep_assert_in_softirq(); |
| 576 | 579 | |
| 577 | − /* The implied barrier pairs with mptcp_subflow_delegated_done(), and | |
| 578 | − * ensures the below list check sees list updates done prior to status | |
| 579 | − * bit changes | |
| 580 | + /* The implied barrier pairs with tcp_release_cb_override() | |
| 581 | + * mptcp_napi_poll(), and ensures the below list check sees list | |
| 582 | + * updates done prior to delegated status bits changes | |
| 580 | 583 | */ |
| 581 | − if (!test_and_set_bit(action, &subflow->delegated_status)) { | |
| 582 | − /* still on delegated list from previous scheduling */ | |
| 583 | − if (!list_empty(&subflow->delegated_node)) | |
| 584 | + old = set_mask_bits(&subflow->delegated_status, 0, set_bits); | |
| 585 | + if (!(old & BIT(MPTCP_DELEGATE_SCHEDULED))) { | |
| 586 | + if (WARN_ON_ONCE(!list_empty(&subflow->delegated_node))) | |
| 584 | 587 | return; |
| 585 | 588 | |
| 586 | 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 | 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 | 611 | int mptcp_is_enabled(const struct net *net); |
| 623 | 612 | unsigned int mptcp_get_add_addr_timeout(const struct net *net); |
| 624 | 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 | 1956 | static void tcp_release_cb_override(struct sock *ssk) |
| 1957 | 1957 | { |
| 1958 | 1958 | struct mptcp_subflow_context *subflow = mptcp_subflow_ctx(ssk); |
| 1959 | + long status; | |
| 1959 | 1960 | |
| 1960 | − if (mptcp_subflow_has_delegated_action(subflow)) | |
| 1961 | − mptcp_subflow_process_delegated(ssk); | |
| 1961 | + /* process and clear all the pending actions, but leave the subflow into | |
| 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 | 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 | 1439 | sin.sin_addr.s_addr = addr; |
| 1440 | 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 | 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 | 1507 | get_mcast_sockaddr(&mcast_addr, &salen, &ipvs->mcfg, id); |
| 1508 | − result = sock->ops->connect(sock, (struct sockaddr *) &mcast_addr, | |
| 1509 | − salen, 0); | |
| 1508 | + result = kernel_connect(sock, (struct sockaddr *)&mcast_addr, | |
| 1509 | + salen, 0); | |
| 1510 | 1510 | if (result < 0) { |
| 1511 | 1511 | pr_err("Error connecting to the multicast addr\n"); |
| 1512 | 1512 | goto error; |
| @@ -1546,7 +1546,7 @@ static int make_receive_sock(struct netns_ipvs *ipvs, int id, · 33 unmodified lines | ||
| 1546 | 1546 | |
| 1547 | 1547 | get_mcast_sockaddr(&mcast_addr, &salen, &ipvs->bcfg, id); |
| 1548 | 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 | 1550 | if (result < 0) { |
| 1551 | 1551 | pr_err("Error binding to the multicast addr\n"); |
| 1552 | 1552 | goto error; |
| @@ -112,7 +112,7 @@ static const u8 sctp_conntracks[2][11][SCTP_CONNTRACK_MAX] = { · 111 unmodified lines | ||
| 112 | 112 | /* shutdown_ack */ {sSA, sCL, sCW, sCE, sES, sSA, sSA, sSA, sSA}, |
| 113 | 113 | /* error */ {sCL, sCL, sCW, sCE, sES, sSS, sSR, sSA, sCL},/* Can't have Stale cookie*/ |
| 114 | 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 | 116 | /* shutdown_comp*/ {sCL, sCL, sCW, sCE, sES, sSS, sSR, sCL, sCL}, |
| 117 | 117 | /* heartbeat */ {sHS, sCL, sCW, sCE, sES, sSS, sSR, sSA, sHS}, |
| 118 | 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 | 126 | /* shutdown */ {sIV, sCL, sCW, sCE, sSR, sSS, sSR, sSA, sIV}, |
| 127 | 127 | /* shutdown_ack */ {sIV, sCL, sCW, sCE, sES, sSA, sSA, sSA, sIV}, |
| 128 | 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 | 130 | /* cookie_ack */ {sIV, sCL, sCW, sES, sES, sSS, sSR, sSA, sIV}, |
| 131 | 131 | /* shutdown_comp*/ {sIV, sCL, sCW, sCE, sES, sSS, sSR, sCL, sIV}, |
| 132 | 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 | 412 | /* (D) vtag must be same as init_vtag as found in INIT_ACK */ |
| 413 | 413 | if (sh->vtag != ct->proto.sctp.vtag[dir]) |
| 414 | 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 | 418 | } else if (sch->type == SCTP_CID_HEARTBEAT) { |
| 416 | 419 | if (ct->proto.sctp.vtag[dir] == 0) { |
| 417 | 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 | 466 | /* If it is an INIT or an INIT ACK note down the vtag */ |
| 464 | − if (sch->type == SCTP_CID_INIT || | |
| 465 | − sch->type == SCTP_CID_INIT_ACK) { | |
| 466 | − struct sctp_inithdr _inithdr, *ih; | |
| 467 | + if (sch->type == SCTP_CID_INIT) { | |
| 468 | + struct sctp_inithdr _ih, *ih; | |
| 467 | 469 | |
| 468 | − ih = skb_header_pointer(skb, offset + sizeof(_sch), | |
| 469 | − sizeof(_inithdr), &_inithdr); | |
| 470 | − if (ih == NULL) | |
| 470 | + ih = skb_header_pointer(skb, offset + sizeof(_sch), sizeof(*ih), &_ih); | |
| 471 | + if (!ih) | |
| 471 | 472 | goto out_unlock; |
| 472 | − pr_debug("Setting vtag %x for dir %d\n", | |
| 473 | − ih->init_tag, !dir); | |
| 473 | + | |
| 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 | 479 | ct->proto.sctp.vtag[!dir] = ih->init_tag; |
| 475 | 480 | |
| 476 | 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 | 486 | old_state == SCTP_CONNTRACK_CLOSED && |
| 482 | 487 | nf_ct_is_confirmed(ct)) |
| 483 | 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 | 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 | 7871 | return nft_delobj(&ctx, obj); |
| 7872 | 7872 | } |
| 7873 | 7873 | |
| 7874 | −void nft_obj_notify(struct net *net, const struct nft_table *table, | |
| 7875 | − struct nft_object *obj, u32 portid, u32 seq, int event, | |
| 7876 | − u16 flags, int family, int report, gfp_t gfp) | |
| 7874 | +static void | |
| 7875 | +__nft_obj_notify(struct net *net, const struct nft_table *table, | |
| 7876 | + struct nft_object *obj, u32 portid, u32 seq, int event, | |
| 7877 | + u16 flags, int family, int report, gfp_t gfp) | |
| 7877 | 7878 | { |
| 7878 | 7879 | struct nftables_pernet *nft_net = nft_pernet(net); |
| 7879 | 7880 | struct sk_buff *skb; |
| 7880 | 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 | 7883 | if (!report && |
| 7894 | 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 | 7901 | err: |
| 7912 | 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 | 7925 | EXPORT_SYMBOL_GPL(nft_obj_notify); |
| 7915 | 7926 | |
| 7916 | 7927 | static void nf_tables_obj_notify(const struct nft_ctx *ctx, |
| 7917 | 7928 | struct nft_object *obj, int event) |
| 7918 | 7929 | { |
| 7919 | − nft_obj_notify(ctx->net, ctx->table, obj, ctx->portid, ctx->seq, event, | |
| 7920 | − ctx->flags, ctx->family, ctx->report, GFP_KERNEL); | |
| 7930 | + __nft_obj_notify(ctx->net, ctx->table, obj, ctx->portid, | |
| 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 | 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 | 168 | void nft_payload_eval(const struct nft_expr *expr, |
| 158 | 169 | struct nft_regs *regs, |
| 159 | 170 | const struct nft_pktinfo *pkt) |
| @@ -172,7 +183,7 @@ void nft_payload_eval(const struct nft_expr *expr, · 12 unmodified lines | ||
| 172 | 183 | goto err; |
| 173 | 184 | |
| 174 | 185 | if (skb_vlan_tag_present(skb) && |
| 175 | − priv->offset >= offsetof(struct ethhdr, h_proto)) { | |
| 186 | + nft_payload_need_vlan_copy(priv)) { | |
| 176 | 187 | if (!nft_payload_copy_vlan(dest, skb, |
| 177 | 188 | priv->offset, priv->len)) |
| 178 | 189 | goto err; |
| @@ -233,10 +233,9 @@ static void nft_rbtree_gc_remove(struct net *net, struct nft_set *set, · 232 unmodified lines | ||
| 233 | 233 | rb_erase(&rbe->node, &priv->root); |
| 234 | 234 | } |
| 235 | 235 | |
| 236 | −static int nft_rbtree_gc_elem(const struct nft_set *__set, | |
| 237 | − struct nft_rbtree *priv, | |
| 238 | − struct nft_rbtree_elem *rbe, | |
| 239 | − u8 genmask) | |
| 236 | +static const struct nft_rbtree_elem * | |
| 237 | +nft_rbtree_gc_elem(const struct nft_set *__set, struct nft_rbtree *priv, | |
| 238 | + struct nft_rbtree_elem *rbe, u8 genmask) | |
| 240 | 239 | { |
| 241 | 240 | struct nft_set *set = (struct nft_set *)__set; |
| 242 | 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 | 246 | gc = nft_trans_gc_alloc(set, 0, GFP_ATOMIC); |
| 248 | 247 | if (!gc) |
| 249 | − return -ENOMEM; | |
| 248 | + return ERR_PTR(-ENOMEM); | |
| 250 | 249 | |
| 251 | 250 | /* search for end interval coming before this element. |
| 252 | 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 | 260 | prev = rb_prev(prev); |
| 262 | 261 | } |
| 263 | 262 | |
| 263 | + rbe_prev = NULL; | |
| 264 | 264 | if (prev) { |
| 265 | 265 | rbe_prev = rb_entry(prev, struct nft_rbtree_elem, node); |
| 266 | 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 | 273 | gc = nft_trans_gc_queue_sync(gc, GFP_ATOMIC); |
| 274 | 274 | if (WARN_ON_ONCE(!gc)) |
| 275 | − return -ENOMEM; | |
| 275 | + return ERR_PTR(-ENOMEM); | |
| 276 | 276 | |
| 277 | 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 | 280 | nft_rbtree_gc_remove(net, set, priv, rbe); |
| 281 | 281 | gc = nft_trans_gc_queue_sync(gc, GFP_ATOMIC); |
| 282 | 282 | if (WARN_ON_ONCE(!gc)) |
| 283 | − return -ENOMEM; | |
| 283 | + return ERR_PTR(-ENOMEM); | |
| 284 | 284 | |
| 285 | 285 | nft_trans_gc_elem_add(gc, rbe); |
| 286 | 286 | |
| 287 | 287 | nft_trans_gc_queue_sync_done(gc); |
| 288 | 288 | |
| 289 | − return 0; | |
| 289 | + return rbe_prev; | |
| 290 | 290 | } |
| 291 | 291 | |
| 292 | 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 | 314 | struct nft_rbtree *priv = nft_set_priv(set); |
| 315 | 315 | u8 cur_genmask = nft_genmask_cur(net); |
| 316 | 316 | u8 genmask = nft_genmask_next(net); |
| 317 | − int d, err; | |
| 317 | + int d; | |
| 318 | 318 | |
| 319 | 319 | /* Descend the tree to search for an existing element greater than the |
| 320 | 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 | 364 | if (nft_set_elem_expired(&rbe->ext) && |
| 365 | 365 | nft_set_elem_active(&rbe->ext, cur_genmask)) { |
| 366 | − err = nft_rbtree_gc_elem(set, priv, rbe, genmask); | |
| 367 | − if (err < 0) | |
| 368 | − return err; | |
| 366 | + const struct nft_rbtree_elem *removed_end; | |
| 367 | + | |
| 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 | 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 | 491 | struct nft_rbtree_elem *rbe = elem->priv; |
| 487 | 492 | int err; |
| 488 | 493 | |
| 489 | − write_lock_bh(&priv->lock); | |
| 490 | − write_seqcount_begin(&priv->count); | |
| 491 | − err = __nft_rbtree_insert(net, set, rbe, ext); | |
| 492 | − write_seqcount_end(&priv->count); | |
| 493 | − write_unlock_bh(&priv->lock); | |
| 494 | + do { | |
| 495 | + if (fatal_signal_pending(current)) | |
| 496 | + return -EINTR; | |
| 497 | + | |
| 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 | 507 | return err; |
| 496 | 508 | } |
| @@ -352,7 +352,7 @@ static void netlink_overrun(struct sock *sk) · 351 unmodified lines | ||
| 352 | 352 | if (!nlk_test_bit(RECV_NO_ENOBUFS, sk)) { |
| 353 | 353 | if (!test_and_set_bit(NETLINK_S_CONGESTED, |
| 354 | 354 | &nlk_sk(sk)->state)) { |
| 355 | − sk->sk_err = ENOBUFS; | |
| 355 | + WRITE_ONCE(sk->sk_err, ENOBUFS); | |
| 356 | 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 | 1605 | goto out; |
| 1606 | 1606 | } |
| 1607 | 1607 | |
| 1608 | − sk->sk_err = p->code; | |
| 1608 | + WRITE_ONCE(sk->sk_err, p->code); | |
| 1609 | 1609 | sk_error_report(sk); |
| 1610 | 1610 | out: |
| 1611 | 1611 | return ret; |
| @@ -1991,7 +1991,7 @@ static int netlink_recvmsg(struct socket *sock, struct msghdr *msg, size_t len, · 379 unmodified lines | ||
| 1991 | 1991 | atomic_read(&sk->sk_rmem_alloc) <= sk->sk_rcvbuf / 2) { |
| 1992 | 1992 | ret = netlink_dump(sk); |
| 1993 | 1993 | if (ret) { |
| 1994 | − sk->sk_err = -ret; | |
| 1994 | + WRITE_ONCE(sk->sk_err, -ret); | |
| 1995 | 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 | 2511 | err_bad_put: |
| 2512 | 2512 | nlmsg_free(skb); |
| 2513 | 2513 | err_skb: |
| 2514 | − NETLINK_CB(in_skb).sk->sk_err = ENOBUFS; | |
| 2514 | + WRITE_ONCE(NETLINK_CB(in_skb).sk->sk_err, ENOBUFS); | |
| 2515 | 2515 | sk_error_report(NETLINK_CB(in_skb).sk); |
| 2516 | 2516 | } |
| 2517 | 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 | 204 | if (tmp_sock->ssap == ssap && tmp_sock->dsap == dsap) { |
| 205 | 205 | llcp_sock = tmp_sock; |
| 206 | + sock_hold(&llcp_sock->sk); | |
| 206 | 207 | break; |
| 207 | 208 | } |
| 208 | 209 | } |
| 209 | 210 | |
| 210 | 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 | 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 | 343 | static |
| 348 | 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 | 348 | struct sock *sk; |
| 352 | 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 | 380 | if (memcmp(sn, tmp_sock->service_name, sn_len) == 0) { |
| 384 | 381 | llcp_sock = tmp_sock; |
| 382 | + if (needref) | |
| 383 | + sock_hold(&llcp_sock->sk); | |
| 385 | 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 | 422 | * to this service name. |
| 424 | 423 | */ |
| 425 | 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 | 427 | mutex_unlock(&local->sdp_lock); |
| 428 | 428 | |
| 429 | 429 | return LLCP_SAP_MAX; |
| @@ -824,16 +824,7 @@ out: · 394 unmodified lines | ||
| 824 | 824 | static struct nfc_llcp_sock *nfc_llcp_sock_get_sn(struct nfc_llcp_local *local, |
| 825 | 825 | const u8 *sn, size_t sn_len) |
| 826 | 826 | { |
| 827 | − struct nfc_llcp_sock *llcp_sock; | |
| 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; | |
| 827 | + return nfc_llcp_sock_from_sn(local, sn, sn_len, true); | |
| 837 | 828 | } |
| 838 | 829 | |
| 839 | 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 | 1291 | llcp_sock = nfc_llcp_sock_from_sn(local, service_name, |
| 1301 | − service_name_len); | |
| 1292 | + service_name_len, | |
| 1293 | + true); | |
| 1302 | 1294 | if (!llcp_sock) { |
| 1303 | 1295 | sap = 0; |
| 1304 | 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 | 1311 | if (sap == LLCP_SAP_MAX) { |
| 1320 | 1312 | sap = 0; |
| 1313 | + nfc_llcp_sock_put(llcp_sock); | |
| 1321 | 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 | 1329 | pr_debug("%p %d\n", llcp_sock, sap); |
| 1337 | 1330 | |
| 1331 | + nfc_llcp_sock_put(llcp_sock); | |
| 1338 | 1332 | add_snl: |
| 1339 | 1333 | sdp = nfc_llcp_build_sdres_tlv(tid, sap); |
| 1340 | 1334 | if (sdp == NULL) |
| @@ -1636,7 +1630,9 @@ int nfc_llcp_register_device(struct nfc_dev *ndev) · 295 unmodified lines | ||
| 1636 | 1630 | timer_setup(&local->sdreq_timer, nfc_llcp_sdreq_timer, 0); |
| 1637 | 1631 | INIT_WORK(&local->sdreq_timeout_work, nfc_llcp_sdreq_timeout_work); |
| 1638 | 1632 | |
| 1633 | + spin_lock(&llcp_devices_lock); | |
| 1639 | 1634 | list_add(&local->list, &llcp_devices); |
| 1635 | + spin_unlock(&llcp_devices_lock); | |
| 1640 | 1636 | |
| 1641 | 1637 | return 0; |
| 1642 | 1638 | } |
| @@ -909,6 +909,11 @@ static int nci_activate_target(struct nfc_dev *nfc_dev, · 908 unmodified lines | ||
| 909 | 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 | 917 | if (!(nci_target->supported_protocols & (1 << protocol))) { |
| 913 | 918 | pr_err("target does not support the requested protocol 0x%x\n", |
| 914 | 919 | protocol); |
| @@ -3607,7 +3607,12 @@ static int packet_getname(struct socket *sock, struct sockaddr *uaddr, · 3606 unmodified lines | ||
| 3607 | 3607 | if (dev) { |
| 3608 | 3608 | sll->sll_hatype = dev->type; |
| 3609 | 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 | 3616 | } else { |
| 3612 | 3617 | sll->sll_hatype = 0; /* Bad: we have no ARPHRD_UNSPEC */ |
| 3613 | 3618 | sll->sll_halen = 0; |
| @@ -145,7 +145,7 @@ int rds_tcp_conn_path_connect(struct rds_conn_path *cp) · 144 unmodified lines | ||
| 145 | 145 | addrlen = sizeof(sin); |
| 146 | 146 | } |
| 147 | 147 | |
| 148 | − ret = sock->ops->bind(sock, addr, addrlen); | |
| 148 | + ret = kernel_bind(sock, addr, addrlen); | |
| 149 | 149 | if (ret) { |
| 150 | 150 | rdsdebug("bind failed with %d at address %pI6c\n", |
| 151 | 151 | ret, &conn->c_laddr); |
| @@ -173,7 +173,7 @@ int rds_tcp_conn_path_connect(struct rds_conn_path *cp) · 21 unmodified lines | ||
| 173 | 173 | * own the socket |
| 174 | 174 | */ |
| 175 | 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 | 178 | rdsdebug("connect to address %pI6c returned %d\n", &conn->c_faddr, ret); |
| 179 | 179 | if (ret == -EINPROGRESS) |
| @@ -306,7 +306,7 @@ struct socket *rds_tcp_listen_init(struct net *net, bool isv6) · 305 unmodified lines | ||
| 306 | 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 | 310 | if (ret < 0) { |
| 311 | 311 | rdsdebug("could not bind %s listener socket: %d\n", |
| 312 | 312 | isv6 ? "IPv6" : "IPv4", ret); |
| @@ -48,6 +48,7 @@ struct rfkill { · 47 unmodified lines | ||
| 48 | 48 | bool persistent; |
| 49 | 49 | bool polling_paused; |
| 50 | 50 | bool suspended; |
| 51 | + bool need_sync; | |
| 51 | 52 | |
| 52 | 53 | const struct rfkill_ops *ops; |
| 53 | 54 | void *data; |
| @@ -368,6 +369,17 @@ static void rfkill_set_block(struct rfkill *rfkill, bool blocked) · 314 unmodified lines | ||
| 368 | 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 | 383 | static void rfkill_update_global_state(enum rfkill_type type, bool blocked) |
| 372 | 384 | { |
| 373 | 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 | 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 | 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 | 767 | return -EINVAL; |
| 752 | 768 | |
| 753 | 769 | mutex_lock(&rfkill_global_mutex); |
| 770 | + rfkill_sync(rfkill); | |
| 754 | 771 | rfkill_set_block(rfkill, state); |
| 755 | 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 | 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 | 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 | 826 | return -EINVAL; |
| 806 | 827 | |
| 807 | 828 | mutex_lock(&rfkill_global_mutex); |
| 829 | + rfkill_sync(rfkill); | |
| 808 | 830 | rfkill_set_block(rfkill, state == RFKILL_USER_STATE_SOFT_BLOCKED); |
| 809 | 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 | 1055 | static void rfkill_sync_work(struct work_struct *work) |
| 1034 | 1056 | { |
| 1035 | − struct rfkill *rfkill; | |
| 1036 | − bool cur; | |
| 1037 | − | |
| 1038 | − rfkill = container_of(work, struct rfkill, sync_work); | |
| 1057 | + struct rfkill *rfkill = container_of(work, struct rfkill, sync_work); | |
| 1039 | 1058 | |
| 1040 | 1059 | mutex_lock(&rfkill_global_mutex); |
| 1041 | − cur = rfkill_global_states[rfkill->type].cur; | |
| 1042 | − rfkill_set_block(rfkill, cur); | |
| 1060 | + rfkill_sync(rfkill); | |
| 1043 | 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 | 1105 | round_jiffies_relative(POLL_INTERVAL)); |
| 1088 | 1106 | |
| 1089 | 1107 | if (!rfkill->persistent || rfkill_epo_lock_active) { |
| 1108 | + rfkill->need_sync = true; | |
| 1090 | 1109 | schedule_work(&rfkill->sync_work); |
| 1091 | 1110 | } else { |
| 1092 | 1111 | #ifdef CONFIG_RFKILL_INPUT |
| @@ -1171,6 +1190,7 @@ static int rfkill_fop_open(struct inode *inode, struct file *file) · 78 unmodified lines | ||
| 1171 | 1190 | ev = kzalloc(sizeof(*ev), GFP_KERNEL); |
| 1172 | 1191 | if (!ev) |
| 1173 | 1192 | goto free; |
| 1193 | + rfkill_sync(rfkill); | |
| 1174 | 1194 | rfkill_fill_event(&ev->ev, rfkill, RFKILL_OP_ADD); |
| 1175 | 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 | 366 | idr_init(&root_ht->handle_idr); |
| 367 | 367 | |
| 368 | 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 | 370 | if (tp_c == NULL) { |
| 371 | 371 | kfree(root_ht); |
| 372 | 372 | return -ENOBUFS; |
| @@ -1159,8 +1159,7 @@ int sctp_assoc_update(struct sctp_association *asoc, · 1158 unmodified lines | ||
| 1159 | 1159 | /* Add any peer addresses from the new association. */ |
| 1160 | 1160 | list_for_each_entry(trans, &new->peer.transport_addr_list, |
| 1161 | 1161 | transports) |
| 1162 | − if (!sctp_assoc_lookup_paddr(asoc, &trans->ipaddr) && | |
| 1163 | − !sctp_assoc_add_peer(asoc, &trans->ipaddr, | |
| 1162 | + if (!sctp_assoc_add_peer(asoc, &trans->ipaddr, | |
| 1164 | 1163 | GFP_ATOMIC, trans->state)) |
| 1165 | 1164 | return -ENOMEM; |
| 1166 | 1165 | |
| @@ -2450,6 +2450,7 @@ static int sctp_apply_peer_addr_params(struct sctp_paddrparams *params, · 2449 unmodified lines | ||
| 2450 | 2450 | if (trans) { |
| 2451 | 2451 | trans->hbinterval = |
| 2452 | 2452 | msecs_to_jiffies(params->spp_hbinterval); |
| 2453 | + sctp_transport_reset_hb_timer(trans); | |
| 2453 | 2454 | } else if (asoc) { |
| 2454 | 2455 | asoc->hbinterval = |
| 2455 | 2456 | msecs_to_jiffies(params->spp_hbinterval); |
| @@ -2,6 +2,7 @@ · 1 unmodified line | ||
| 2 | 2 | config SMC |
| 3 | 3 | tristate "SMC socket protocol family" |
| 4 | 4 | depends on INET && INFINIBAND |
| 5 | + depends on m || ISM != m | |
| 5 | 6 | help |
| 6 | 7 | SMC-R provides a "sockets over RDMA" solution making use of |
| 7 | 8 | RDMA over Converged Ethernet (RoCE) technology to upgrade |
| @@ -92,13 +92,14 @@ do { \ · 91 unmodified lines | ||
| 92 | 92 | typeof(_smc_stats) stats = (_smc_stats); \ |
| 93 | 93 | typeof(_tech) t = (_tech); \ |
| 94 | 94 | typeof(_len) l = (_len); \ |
| 95 | − int _pos = fls64((l) >> 13); \ | |
| 95 | + int _pos; \ | |
| 96 | 96 | typeof(_rc) r = (_rc); \ |
| 97 | 97 | int m = SMC_BUF_MAX - 1; \ |
| 98 | 98 | this_cpu_inc((*stats).smc[t].key ## _cnt); \ |
| 99 | − if (r <= 0) \ | |
| 99 | + if (r <= 0 || l <= 0) \ | |
| 100 | 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 | 103 | this_cpu_inc((*stats).smc[t].key ## _pd.buf[_pos]); \ |
| 103 | 104 | this_cpu_add((*stats).smc[t].key ## _bytes, r); \ |
| 104 | 105 | } \ |
| @@ -138,9 +139,12 @@ while (0) · 33 unmodified lines | ||
| 138 | 139 | do { \ |
| 139 | 140 | typeof(_len) _l = (_len); \ |
| 140 | 141 | typeof(_tech) t = (_tech); \ |
| 141 | − int _pos = fls((_l) >> 13); \ | |
| 142 | + int _pos; \ | |
| 142 | 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 | 148 | this_cpu_inc((*(_smc_stats)).smc[t].k ## _rmbsize.buf[_pos]); \ |
| 145 | 149 | } \ |
| 146 | 150 | while (0) |
| @@ -737,6 +737,14 @@ static inline int sock_sendmsg_nosec(struct socket *sock, struct msghdr *msg) · 736 unmodified lines | ||
| 737 | 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 | 749 | * sock_sendmsg - send a message through @sock |
| 742 | 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 | 756 | int sock_sendmsg(struct socket *sock, struct msghdr *msg) |
| 749 | 757 | { |
| 750 | − int err = security_socket_sendmsg(sock, msg, | |
| 751 | − msg_data_left(msg)); | |
| 758 | + struct sockaddr_storage *save_addr = (struct sockaddr_storage *)msg->msg_name; | |
| 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 | 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 | 1155 | if (sock->type == SOCK_SEQPACKET) |
| 1139 | 1156 | msg.msg_flags |= MSG_EOR; |
| 1140 | 1157 | |
| 1141 | − res = sock_sendmsg(sock, &msg); | |
| 1158 | + res = __sock_sendmsg(sock, &msg); | |
| 1142 | 1159 | *from = msg.msg_iter; |
| 1143 | 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 | 2191 | if (sock->file->f_flags & O_NONBLOCK) |
| 2175 | 2192 | flags |= MSG_DONTWAIT; |
| 2176 | 2193 | msg.msg_flags = flags; |
| 2177 | − err = sock_sendmsg(sock, &msg); | |
| 2194 | + err = __sock_sendmsg(sock, &msg); | |
| 2178 | 2195 | |
| 2179 | 2196 | out_put: |
| 2180 | 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 | 2555 | err = sock_sendmsg_nosec(sock, msg_sys); |
| 2539 | 2556 | goto out_freectl; |
| 2540 | 2557 | } |
| 2541 | − err = sock_sendmsg(sock, msg_sys); | |
| 2558 | + err = __sock_sendmsg(sock, msg_sys); | |
| 2542 | 2559 | /* |
| 2543 | 2560 | * If this is sendmmsg() and sending to current destination address was |
| 2544 | 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 | 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 | 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 | 769 | * @task: controlling RPC task |
| 770 | 770 | * @xdr: xdr_stream containing RPC Reply header |
| 771 | 771 | * |
| 772 | − * On success, @xdr is updated to point past the verifier and | |
| 773 | − * zero is returned. Otherwise, @xdr is in an undefined state | |
| 774 | − * and a negative errno is returned. | |
| 772 | + * Return values: | |
| 773 | + * %0: Verifier is valid. @xdr now points past the verifier. | |
| 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 | 781 | int |
| 777 | 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 | 129 | if (*p != rpc_auth_null) |
| 130 | 130 | return -EIO; |
| 131 | 131 | if (xdr_stream_decode_opaque_inline(xdr, &str, starttls_len) != starttls_len) |
| 132 | − return -EIO; | |
| 132 | + return -EPROTONOSUPPORT; | |
| 133 | 133 | if (memcmp(str, starttls_token, starttls_len)) |
| 134 | − return -EIO; | |
| 134 | + return -EPROTONOSUPPORT; | |
| 135 | 135 | return 0; |
| 136 | 136 | } |
| 137 | 137 | |
| @@ -2476,8 +2476,7 @@ call_status(struct rpc_task *task) · 2475 unmodified lines | ||
| 2476 | 2476 | goto out_exit; |
| 2477 | 2477 | } |
| 2478 | 2478 | task->tk_action = call_encode; |
| 2479 | − if (status != -ECONNRESET && status != -ECONNABORTED) | |
| 2480 | − rpc_check_timeout(task); | |
| 2479 | + rpc_check_timeout(task); | |
| 2481 | 2480 | return; |
| 2482 | 2481 | out_exit: |
| 2483 | 2482 | rpc_call_rpcerror(task, status); |
| @@ -2725,7 +2724,15 @@ out_unparsable: · 241 unmodified lines | ||
| 2725 | 2724 | |
| 2726 | 2725 | out_verifier: |
| 2727 | 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 | 2737 | out_msg_denied: |
| 2731 | 2738 | error = -EACCES; |
| @@ -2672,6 +2672,10 @@ static void xs_tcp_tls_setup_socket(struct work_struct *work) · 2671 unmodified lines | ||
| 2672 | 2672 | rcu_read_lock(); |
| 2673 | 2673 | lower_xprt = rcu_dereference(lower_clnt->cl_xprt); |
| 2674 | 2674 | rcu_read_unlock(); |
| 2675 | + | |
| 2676 | + if (wait_on_bit_lock(&lower_xprt->state, XPRT_LOCKED, TASK_KILLABLE)) | |
| 2677 | + goto out_unlock; | |
| 2678 | + | |
| 2675 | 2679 | status = xs_tls_handshake_sync(lower_xprt, &upper_xprt->xprtsec); |
| 2676 | 2680 | if (status) { |
| 2677 | 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 | 2685 | status = xs_tcp_tls_finish_connecting(lower_xprt, upper_transport); |
| 2682 | 2686 | if (status) |
| 2683 | 2687 | goto out_close; |
| 2688 | + xprt_release_write(lower_xprt, NULL); | |
| 2684 | 2689 | |
| 2685 | 2690 | trace_rpc_socket_connect(upper_xprt, upper_transport->sock, 0); |
| 2686 | 2691 | if (!xprt_test_and_set_connected(upper_xprt)) { |
| @@ -2702,6 +2707,7 @@ out_unlock: · 15 unmodified lines | ||
| 2702 | 2707 | return; |
| 2703 | 2708 | |
| 2704 | 2709 | out_close: |
| 2710 | + xprt_release_write(lower_xprt, NULL); | |
| 2705 | 2711 | rpc_shutdown_client(lower_clnt); |
| 2706 | 2712 | |
| 2707 | 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 | 1441 | struct tipc_crypto *tx = tipc_net(net)->crypto_tx; |
| 1442 | 1442 | struct tipc_key key; |
| 1443 | 1443 | |
| 1444 | − spin_lock(&tx->lock); | |
| 1444 | + spin_lock_bh(&tx->lock); | |
| 1445 | 1445 | key = tx->key; |
| 1446 | 1446 | WARN_ON(!key.active || tx_key != key.active); |
| 1447 | 1447 | |
| 1448 | 1448 | /* Free the active key */ |
| 1449 | 1449 | tipc_crypto_key_set_state(tx, key.passive, 0, key.pending); |
| 1450 | 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 | 1453 | pr_warn("%s: key is revoked\n", tx->name); |
| 1454 | 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 | 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 | 1184 | static void _cfg80211_unregister_wdev(struct wireless_dev *wdev, |
| 1191 | 1185 | bool unregister_netdev) |
| 1192 | 1186 | { |
| 1193 | 1187 | struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy); |
| 1188 | + struct cfg80211_cqm_config *cqm_config; | |
| 1194 | 1189 | unsigned int link_id; |
| 1195 | 1190 | |
| 1196 | 1191 | ASSERT_RTNL(); |
| @@ -1227,7 +1222,10 @@ static void _cfg80211_unregister_wdev(struct wireless_dev *wdev, · 30 unmodified lines | ||
| 1227 | 1222 | kfree_sensitive(wdev->wext.keys); |
| 1228 | 1223 | wdev->wext.keys = NULL; |
| 1229 | 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 | 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 | 1377 | wdev->wext.connect.auth_type = NL80211_AUTHTYPE_AUTOMATIC; |
| 1380 | 1378 | #endif |
| 1381 | 1379 | |
| 1380 | + wiphy_work_init(&wdev->cqm_rssi_work, cfg80211_cqm_rssi_notify_work); | |
| 1381 | + | |
| 1382 | 1382 | if (wdev->wiphy->flags & WIPHY_FLAG_PS_ON_BY_DEFAULT) |
| 1383 | 1383 | wdev->ps = true; |
| 1384 | 1384 | else |
| @@ -295,12 +295,17 @@ struct cfg80211_beacon_registration { · 294 unmodified lines | ||
| 295 | 295 | }; |
| 296 | 296 | |
| 297 | 297 | struct cfg80211_cqm_config { |
| 298 | + struct rcu_head rcu_head; | |
| 298 | 299 | u32 rssi_hyst; |
| 299 | 300 | s32 last_rssi_event_value; |
| 301 | + enum nl80211_cqm_rssi_threshold_event last_rssi_event_type; | |
| 300 | 302 | int n_rssi_thresholds; |
| 301 | 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 | 309 | void cfg80211_destroy_ifaces(struct cfg80211_registered_device *rdev); |
| 305 | 310 | |
| 306 | 311 | /* free object */ |
| @@ -566,8 +571,6 @@ cfg80211_bss_update(struct cfg80211_registered_device *rdev, · 259 unmodified lines | ||
| 566 | 571 | #define CFG80211_DEV_WARN_ON(cond) ({bool __r = (cond); __r; }) |
| 567 | 572 | #endif |
| 568 | 573 | |
| 569 | −void cfg80211_cqm_config_free(struct wireless_dev *wdev); | |
| 570 | − | |
| 571 | 574 | void cfg80211_release_pmsr(struct wireless_dev *wdev, u32 portid); |
| 572 | 575 | void cfg80211_pmsr_wdev_down(struct wireless_dev *wdev); |
| 573 | 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 | 52 | cr.links[link_id].bssid = data->links[link_id].bss->bssid; |
| 53 | 53 | cr.links[link_id].addr = data->links[link_id].addr; |
| 54 | 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 | 58 | BUG_ON(!cr.links[link_id].bss->channel); |
| 58 | 59 | |
| @@ -5909,6 +5909,21 @@ out: · 5908 unmodified lines | ||
| 5909 | 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 | 5927 | static int nl80211_start_ap(struct sk_buff *skb, struct genl_info *info) |
| 5913 | 5928 | { |
| 5914 | 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 | 6193 | if (err) |
| 6179 | 6194 | goto out_unlock; |
| 6180 | 6195 | |
| 6196 | + err = nl80211_validate_ap_phy_operation(params); | |
| 6197 | + if (err) | |
| 6198 | + goto out_unlock; | |
| 6199 | + | |
| 6181 | 6200 | if (info->attrs[NL80211_ATTR_AP_SETTINGS_FLAGS]) |
| 6182 | 6201 | params->flags = nla_get_u32( |
| 6183 | 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 | 8501 | struct cfg80211_registered_device *rdev = info->user_ptr[0]; |
| 8483 | 8502 | struct net_device *dev = info->user_ptr[1]; |
| 8484 | 8503 | struct wireless_dev *wdev = dev->ieee80211_ptr; |
| 8485 | − struct mesh_config cfg; | |
| 8504 | + struct mesh_config cfg = {}; | |
| 8486 | 8505 | u32 mask; |
| 8487 | 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 | 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 | 12821 | struct wireless_dev *wdev = dev->ieee80211_ptr; |
| 12802 | 12822 | s32 last, low, high; |
| @@ -12805,7 +12825,7 @@ static int cfg80211_cqm_rssi_update(struct cfg80211_registered_device *rdev, · 2 unmodified lines | ||
| 12805 | 12825 | int err; |
| 12806 | 12826 | |
| 12807 | 12827 | /* RSSI reporting disabled? */ |
| 12808 | − if (!wdev->cqm_config) | |
| 12828 | + if (!cqm_config) | |
| 12809 | 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 | 12834 | * connection is established and enough beacons received to calculate |
| 12815 | 12835 | * the average. |
| 12816 | 12836 | */ |
| 12817 | − if (!wdev->cqm_config->last_rssi_event_value && | |
| 12837 | + if (!cqm_config->last_rssi_event_value && | |
| 12818 | 12838 | wdev->links[0].client.current_bss && |
| 12819 | 12839 | rdev->ops->get_station) { |
| 12820 | 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 | 12849 | cfg80211_sinfo_release_content(&sinfo); |
| 12830 | 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 | 12852 | (s8) sinfo.rx_beacon_signal_avg; |
| 12833 | 12853 | } |
| 12834 | 12854 | |
| 12835 | − last = wdev->cqm_config->last_rssi_event_value; | |
| 12836 | − hyst = wdev->cqm_config->rssi_hyst; | |
| 12837 | − n = wdev->cqm_config->n_rssi_thresholds; | |
| 12855 | + last = cqm_config->last_rssi_event_value; | |
| 12856 | + hyst = cqm_config->rssi_hyst; | |
| 12857 | + n = cqm_config->n_rssi_thresholds; | |
| 12838 | 12858 | |
| 12839 | 12859 | for (i = 0; i < n; i++) { |
| 12840 | 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 | 12862 | break; |
| 12843 | 12863 | } |
| 12844 | 12864 | |
| 12845 | 12865 | low_index = i - 1; |
| 12846 | 12866 | if (low_index >= 0) { |
| 12847 | 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 | 12869 | } else { |
| 12850 | 12870 | low = S32_MIN; |
| 12851 | 12871 | } |
| 12852 | 12872 | if (i < n) { |
| 12853 | 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 | 12875 | } else { |
| 12856 | 12876 | high = S32_MAX; |
| 12857 | 12877 | } |
| @@ -12864,6 +12884,7 @@ static int nl80211_set_cqm_rssi(struct genl_info *info, · 6 unmodified lines | ||
| 12864 | 12884 | u32 hysteresis) |
| 12865 | 12885 | { |
| 12866 | 12886 | struct cfg80211_registered_device *rdev = info->user_ptr[0]; |
| 12887 | + struct cfg80211_cqm_config *cqm_config = NULL, *old; | |
| 12867 | 12888 | struct net_device *dev = info->user_ptr[1]; |
| 12868 | 12889 | struct wireless_dev *wdev = dev->ieee80211_ptr; |
| 12869 | 12890 | int i, err; |
| @@ -12881,10 +12902,6 @@ static int nl80211_set_cqm_rssi(struct genl_info *info, · 11 unmodified lines | ||
| 12881 | 12902 | wdev->iftype != NL80211_IFTYPE_P2P_CLIENT) |
| 12882 | 12903 | return -EOPNOTSUPP; |
| 12883 | 12904 | |
| 12884 | − wdev_lock(wdev); | |
| 12885 | − cfg80211_cqm_config_free(wdev); | |
| 12886 | − wdev_unlock(wdev); | |
| 12887 | − | |
| 12888 | 12905 | if (n_thresholds <= 1 && rdev->ops->set_cqm_rssi_config) { |
| 12889 | 12906 | if (n_thresholds == 0 || thresholds[0] == 0) /* Disabling */ |
| 12890 | 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 | 12918 | n_thresholds = 0; |
| 12902 | 12919 | |
| 12903 | 12920 | wdev_lock(wdev); |
| 12904 | − if (n_thresholds) { | |
| 12905 | − struct cfg80211_cqm_config *cqm_config; | |
| 12921 | + old = rcu_dereference_protected(wdev->cqm_config, | |
| 12922 | + lockdep_is_held(&wdev->mtx)); | |
| 12906 | 12923 | |
| 12924 | + if (n_thresholds) { | |
| 12907 | 12925 | cqm_config = kzalloc(struct_size(cqm_config, rssi_thresholds, |
| 12908 | 12926 | n_thresholds), |
| 12909 | 12927 | GFP_KERNEL); |
| @@ -12918,11 +12936,18 @@ static int nl80211_set_cqm_rssi(struct genl_info *info, · 8 unmodified lines | ||
| 12918 | 12936 | flex_array_size(cqm_config, rssi_thresholds, |
| 12919 | 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); | |
| 12925 | − | |
| 12944 | + err = cfg80211_cqm_rssi_update(rdev, dev, cqm_config); | |
| 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 | 12951 | unlock: |
| 12927 | 12952 | wdev_unlock(wdev); |
| 12928 | 12953 | |
| @@ -19073,9 +19098,8 @@ void cfg80211_cqm_rssi_notify(struct net_device *dev, · 6144 unmodified lines | ||
| 19073 | 19098 | enum nl80211_cqm_rssi_threshold_event rssi_event, |
| 19074 | 19099 | s32 rssi_level, gfp_t gfp) |
| 19075 | 19100 | { |
| 19076 | − struct sk_buff *msg; | |
| 19077 | 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 | 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 | 19107 | rssi_event != NL80211_CQM_RSSI_THRESHOLD_EVENT_HIGH)) |
| 19084 | 19108 | return; |
| 19085 | 19109 | |
| 19086 | − if (wdev->cqm_config) { | |
| 19087 | − wdev->cqm_config->last_rssi_event_value = rssi_level; | |
| 19110 | + rcu_read_lock(); | |
| 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) | |
| 19092 | − rssi_level = wdev->cqm_config->last_rssi_event_value; | |
| 19093 | − } | |
| 19131 | + wdev_lock(wdev); | |
| 19132 | + cqm_config = rcu_dereference_protected(wdev->cqm_config, | |
| 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 | 19143 | if (!msg) |
| 19097 | − return; | |
| 19144 | + goto unlock; | |
| 19098 | 19145 | |
| 19099 | 19146 | if (nla_put_u32(msg, NL80211_ATTR_CQM_RSSI_THRESHOLD_EVENT, |
| 19100 | 19147 | rssi_event)) |
| @@ -19104,14 +19151,15 @@ void cfg80211_cqm_rssi_notify(struct net_device *dev, · 3 unmodified lines | ||
| 19104 | 19151 | rssi_level)) |
| 19105 | 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 | 19158 | nla_put_failure: |
| 19112 | 19159 | nlmsg_free(msg); |
| 19160 | + unlock: | |
| 19161 | + wdev_unlock(wdev); | |
| 19113 | 19162 | } |
| 19114 | −EXPORT_SYMBOL(cfg80211_cqm_rssi_notify); | |
| 19115 | 19163 | |
| 19116 | 19164 | void cfg80211_cqm_txe_notify(struct net_device *dev, |
| 19117 | 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 | 908 | !cfg80211_find_ssid_match(ap, request)) |
| 909 | 909 | continue; |
| 910 | 910 | |
| 911 | + if (!is_broadcast_ether_addr(request->bssid) && | |
| 912 | + !ether_addr_equal(request->bssid, ap->bssid)) | |
| 913 | + continue; | |
| 914 | + | |
| 911 | 915 | if (!request->n_ssids && ap->multi_bss && !ap->transmitted_bssid) |
| 912 | 916 | continue; |
| 913 | 917 | |
| @@ -34,6 +34,16 @@ struct xsk_queue *xskq_create(u32 nentries, bool umem_queue) · 33 unmodified lines | ||
| 34 | 34 | q->ring_mask = nentries - 1; |
| 35 | 35 | |
| 36 | 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 | 47 | size = PAGE_ALIGN(size); |
| 38 | 48 | |
| 39 | 49 | q->ring = vmalloc_user(size); |
| @@ -29,9 +29,11 @@ config IMA · 28 unmodified lines | ||
| 29 | 29 | to learn more about IMA. |
| 30 | 30 | If unsure, say N. |
| 31 | 31 | |
| 32 | +if IMA | |
| 33 | + | |
| 32 | 34 | config IMA_KEXEC |
| 33 | 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 | 37 | default n |
| 36 | 38 | help |
| 37 | 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 | 46 | config IMA_MEASURE_PCR_IDX |
| 45 | 47 | int |
| 46 | − depends on IMA | |
| 47 | 48 | range 8 14 |
| 48 | 49 | default 10 |
| 49 | 50 | help |
| @@ -53,7 +54,7 @@ config IMA_MEASURE_PCR_IDX · 3 unmodified lines | ||
| 53 | 54 | |
| 54 | 55 | config IMA_LSM_RULES |
| 55 | 56 | bool |
| 56 | − depends on IMA && AUDIT && (SECURITY_SELINUX || SECURITY_SMACK || SECURITY_APPARMOR) | |
| 57 | + depends on AUDIT && (SECURITY_SELINUX || SECURITY_SMACK || SECURITY_APPARMOR) | |
| 57 | 58 | default y |
| 58 | 59 | help |
| 59 | 60 | Disabling this option will disregard LSM based policy rules. |
| @@ -61,7 +62,6 @@ config IMA_LSM_RULES · 1 unmodified line | ||
| 61 | 62 | choice |
| 62 | 63 | prompt "Default template" |
| 63 | 64 | default IMA_NG_TEMPLATE |
| 64 | − depends on IMA | |
| 65 | 65 | help |
| 66 | 66 | Select the default IMA measurement template. |
| 67 | 67 | |
| @@ -80,14 +80,12 @@ endchoice · 12 unmodified lines | ||
| 80 | 80 | |
| 81 | 81 | config IMA_DEFAULT_TEMPLATE |
| 82 | 82 | string |
| 83 | − depends on IMA | |
| 84 | 83 | default "ima-ng" if IMA_NG_TEMPLATE |
| 85 | 84 | default "ima-sig" if IMA_SIG_TEMPLATE |
| 86 | 85 | |
| 87 | 86 | choice |
| 88 | 87 | prompt "Default integrity hash algorithm" |
| 89 | 88 | default IMA_DEFAULT_HASH_SHA1 |
| 90 | − depends on IMA | |
| 91 | 89 | help |
| 92 | 90 | Select the default hash algorithm used for the measurement |
| 93 | 91 | list, integrity appraisal and audit log. The compiled default |
| @@ -117,7 +115,6 @@ endchoice · 23 unmodified lines | ||
| 117 | 115 | |
| 118 | 116 | config IMA_DEFAULT_HASH |
| 119 | 117 | string |
| 120 | − depends on IMA | |
| 121 | 118 | default "sha1" if IMA_DEFAULT_HASH_SHA1 |
| 122 | 119 | default "sha256" if IMA_DEFAULT_HASH_SHA256 |
| 123 | 120 | default "sha512" if IMA_DEFAULT_HASH_SHA512 |
| @@ -126,7 +123,6 @@ config IMA_DEFAULT_HASH · 2 unmodified lines | ||
| 126 | 123 | |
| 127 | 124 | config IMA_WRITE_POLICY |
| 128 | 125 | bool "Enable multiple writes to the IMA policy" |
| 129 | − depends on IMA | |
| 130 | 126 | default n |
| 131 | 127 | help |
| 132 | 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 | 134 | config IMA_READ_POLICY |
| 139 | 135 | bool "Enable reading back the current IMA policy" |
| 140 | − depends on IMA | |
| 141 | 136 | default y if IMA_WRITE_POLICY |
| 142 | 137 | default n if !IMA_WRITE_POLICY |
| 143 | 138 | help |
| @@ -147,7 +142,6 @@ config IMA_READ_POLICY · 3 unmodified lines | ||
| 147 | 142 | |
| 148 | 143 | config IMA_APPRAISE |
| 149 | 144 | bool "Appraise integrity measurements" |
| 150 | − depends on IMA | |
| 151 | 145 | default n |
| 152 | 146 | help |
| 153 | 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 | 263 | config IMA_BLACKLIST_KEYRING |
| 270 | 264 | bool "Create IMA machine owner blacklist keyrings (EXPERIMENTAL)" |
| 271 | 265 | depends on SYSTEM_TRUSTED_KEYRING |
| 272 | − depends on IMA_TRUSTED_KEYRING | |
| 266 | + depends on INTEGRITY_TRUSTED_KEYRING | |
| 273 | 267 | default n |
| 274 | 268 | help |
| 275 | 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 | 274 | config IMA_LOAD_X509 |
| 281 | 275 | bool "Load X509 certificate onto the '.ima' trusted keyring" |
| 282 | − depends on IMA_TRUSTED_KEYRING | |
| 276 | + depends on INTEGRITY_TRUSTED_KEYRING | |
| 283 | 277 | default n |
| 284 | 278 | help |
| 285 | 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 | 299 | config IMA_MEASURE_ASYMMETRIC_KEYS |
| 306 | 300 | bool |
| 307 | − depends on IMA | |
| 308 | 301 | depends on ASYMMETRIC_PUBLIC_KEY_SUBTYPE=y |
| 309 | 302 | default y |
| 310 | 303 | |
| @@ -323,7 +316,8 @@ config IMA_SECURE_AND_OR_TRUSTED_BOOT · 12 unmodified lines | ||
| 323 | 316 | |
| 324 | 317 | config IMA_DISABLE_HTABLE |
| 325 | 318 | bool "Disable htable to allow measurement of duplicate records" |
| 326 | − depends on IMA | |
| 327 | 319 | default n |
| 328 | 320 | help |
| 329 | 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 | 44 | #endif |
| 45 | 45 | }; |
| 46 | 46 | |
| 47 | −DEFINE_STATIC_CALL_NULL(trusted_key_init, *trusted_key_sources[0].ops->init); | |
| 48 | 47 | DEFINE_STATIC_CALL_NULL(trusted_key_seal, *trusted_key_sources[0].ops->seal); |
| 49 | 48 | DEFINE_STATIC_CALL_NULL(trusted_key_unseal, |
| 50 | 49 | *trusted_key_sources[0].ops->unseal); |
| 51 | 50 | DEFINE_STATIC_CALL_NULL(trusted_key_get_random, |
| 52 | 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 | 53 | static unsigned char migratable; |
| 55 | 54 | |
| 56 | 55 | enum { |
| @@ -359,19 +358,16 @@ static int __init init_trusted(void) · 302 unmodified lines | ||
| 359 | 358 | if (!get_random) |
| 360 | 359 | get_random = kernel_get_random; |
| 361 | 360 | |
| 362 | − static_call_update(trusted_key_init, | |
| 363 | − trusted_key_sources[i].ops->init); | |
| 364 | 361 | static_call_update(trusted_key_seal, |
| 365 | 362 | trusted_key_sources[i].ops->seal); |
| 366 | 363 | static_call_update(trusted_key_unseal, |
| 367 | 364 | trusted_key_sources[i].ops->unseal); |
| 368 | 365 | static_call_update(trusted_key_get_random, |
| 369 | 366 | get_random); |
| 370 | − static_call_update(trusted_key_exit, | |
| 371 | − trusted_key_sources[i].ops->exit); | |
| 367 | + trusted_key_exit = trusted_key_sources[i].ops->exit; | |
| 372 | 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 | 371 | if (!ret) |
| 376 | 372 | break; |
| 377 | 373 | } |
| @@ -388,7 +384,8 @@ static int __init init_trusted(void) · 10 unmodified lines | ||
| 388 | 384 | |
| 389 | 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 | 391 | late_initcall(init_trusted); |
| @@ -185,10 +185,14 @@ static int cs35l41_request_firmware_files_spkid(struct cs35l41_hda *cs35l41, · 184 unmodified lines | ||
| 185 | 185 | cs35l41->speaker_id, "wmfw"); |
| 186 | 186 | if (!ret) { |
| 187 | 187 | /* try cirrus/part-dspN-fwtype-sub<-spkidN><-ampname>.bin */ |
| 188 | − return cs35l41_request_firmware_file(cs35l41, coeff_firmware, coeff_filename, | |
| 189 | − CS35L41_FIRMWARE_ROOT, | |
| 190 | − cs35l41->acpi_subsystem_id, cs35l41->amp_name, | |
| 191 | − cs35l41->speaker_id, "bin"); | |
| 188 | + ret = cs35l41_request_firmware_file(cs35l41, coeff_firmware, coeff_filename, | |
| 189 | + CS35L41_FIRMWARE_ROOT, | |
| 190 | + cs35l41->acpi_subsystem_id, cs35l41->amp_name, | |
| 191 | + cs35l41->speaker_id, "bin"); | |
| 192 | + if (ret) | |
| 193 | + goto coeff_err; | |
| 194 | + | |
| 195 | + return 0; | |
| 192 | 196 | } |
| 193 | 197 | |
| 194 | 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 | 201 | cs35l41->amp_name, -1, "wmfw"); |
| 198 | 202 | if (!ret) { |
| 199 | 203 | /* try cirrus/part-dspN-fwtype-sub<-spkidN><-ampname>.bin */ |
| 200 | − return cs35l41_request_firmware_file(cs35l41, coeff_firmware, coeff_filename, | |
| 201 | − CS35L41_FIRMWARE_ROOT, | |
| 202 | − cs35l41->acpi_subsystem_id, cs35l41->amp_name, | |
| 203 | − cs35l41->speaker_id, "bin"); | |
| 204 | + ret = cs35l41_request_firmware_file(cs35l41, coeff_firmware, coeff_filename, | |
| 205 | + CS35L41_FIRMWARE_ROOT, | |
| 206 | + cs35l41->acpi_subsystem_id, cs35l41->amp_name, | |
| 207 | + cs35l41->speaker_id, "bin"); | |
| 208 | + if (ret) | |
| 209 | + goto coeff_err; | |
| 210 | + | |
| 211 | + return 0; | |
| 204 | 212 | } |
| 205 | 213 | |
| 206 | 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 | 223 | cs35l41->amp_name, cs35l41->speaker_id, "bin"); |
| 216 | 224 | if (ret) |
| 217 | 225 | /* try cirrus/part-dspN-fwtype-sub<-spkidN>.bin */ |
| 218 | − return cs35l41_request_firmware_file(cs35l41, coeff_firmware, | |
| 219 | − coeff_filename, CS35L41_FIRMWARE_ROOT, | |
| 220 | − cs35l41->acpi_subsystem_id, NULL, | |
| 221 | − cs35l41->speaker_id, "bin"); | |
| 226 | + ret = cs35l41_request_firmware_file(cs35l41, coeff_firmware, | |
| 227 | + coeff_filename, CS35L41_FIRMWARE_ROOT, | |
| 228 | + cs35l41->acpi_subsystem_id, NULL, | |
| 229 | + cs35l41->speaker_id, "bin"); | |
| 230 | + if (ret) | |
| 231 | + goto coeff_err; | |
| 232 | + | |
| 233 | + return 0; | |
| 222 | 234 | } |
| 223 | 235 | |
| 224 | 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 | 245 | cs35l41->speaker_id, "bin"); |
| 234 | 246 | if (ret) |
| 235 | 247 | /* try cirrus/part-dspN-fwtype-sub<-spkidN>.bin */ |
| 236 | − return cs35l41_request_firmware_file(cs35l41, coeff_firmware, | |
| 237 | − coeff_filename, CS35L41_FIRMWARE_ROOT, | |
| 238 | − cs35l41->acpi_subsystem_id, NULL, | |
| 239 | − cs35l41->speaker_id, "bin"); | |
| 248 | + ret = cs35l41_request_firmware_file(cs35l41, coeff_firmware, | |
| 249 | + coeff_filename, CS35L41_FIRMWARE_ROOT, | |
| 250 | + cs35l41->acpi_subsystem_id, NULL, | |
| 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 | 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 | 304 | ret = cs35l41_request_firmware_files_spkid(cs35l41, wmfw_firmware, wmfw_filename, |
| 255 | 305 | coeff_firmware, coeff_filename); |
| 256 | 306 | goto out; |
| 257 | − | |
| 258 | 307 | } |
| 259 | 308 | |
| 260 | 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 | 316 | CS35L41_FIRMWARE_ROOT, |
| 268 | 317 | cs35l41->acpi_subsystem_id, cs35l41->amp_name, |
| 269 | 318 | -1, "bin"); |
| 319 | + if (ret) | |
| 320 | + goto coeff_err; | |
| 321 | + | |
| 270 | 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 | 338 | CS35L41_FIRMWARE_ROOT, |
| 287 | 339 | cs35l41->acpi_subsystem_id, NULL, -1, |
| 288 | 340 | "bin"); |
| 341 | + if (ret) | |
| 342 | + goto coeff_err; | |
| 289 | 343 | } |
| 290 | 344 | |
| 291 | 345 | out: |
| 292 | − if (!ret) | |
| 293 | − return 0; | |
| 346 | + if (ret) | |
| 347 | + /* if all attempts at finding firmware fail, try fallback */ | |
| 348 | + goto fallback; | |
| 294 | 349 | |
| 295 | − /* Handle fallback */ | |
| 296 | − dev_warn(cs35l41->dev, "Falling back to default firmware.\n"); | |
| 350 | + return 0; | |
| 297 | 351 | |
| 352 | +coeff_err: | |
| 298 | 353 | release_firmware(*wmfw_firmware); |
| 299 | 354 | kfree(*wmfw_filename); |
| 300 | − | |
| 301 | − /* fallback try cirrus/part-dspN-fwtype.wmfw */ | |
| 302 | − ret = cs35l41_request_firmware_file(cs35l41, wmfw_firmware, wmfw_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; | |
| 355 | +fallback: | |
| 356 | + return cs35l41_fallback_firmware_file(cs35l41, wmfw_firmware, wmfw_filename, | |
| 357 | + coeff_firmware, coeff_filename); | |
| 315 | 358 | } |
| 316 | 359 | |
| 317 | 360 | #if IS_ENABLED(CONFIG_EFI) |
| @@ -7343,6 +7343,7 @@ enum { · 7342 unmodified lines | ||
| 7343 | 7343 | ALC245_FIXUP_HP_MUTE_LED_COEFBIT, |
| 7344 | 7344 | ALC245_FIXUP_HP_X360_MUTE_LEDS, |
| 7345 | 7345 | ALC287_FIXUP_THINKPAD_I2S_SPK, |
| 7346 | + ALC287_FIXUP_MG_RTKC_CSAMP_CS35L41_I2C_THINKPAD, | |
| 7346 | 7347 | }; |
| 7347 | 7348 | |
| 7348 | 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 | 9442 | .type = HDA_FIXUP_FUNC, |
| 9442 | 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 | 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 | 9861 | SND_PCI_QUIRK(0x10ec, 0x124c, "Intel Reference board", ALC295_FIXUP_CHROME_BOOK), |
| 9855 | 9862 | SND_PCI_QUIRK(0x10ec, 0x1252, "Intel Reference board", ALC295_FIXUP_CHROME_BOOK), |
| 9856 | 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 | 9865 | SND_PCI_QUIRK(0x10f7, 0x8338, "Panasonic CF-SZ6", ALC269_FIXUP_HEADSET_MODE), |
| 9859 | 9866 | SND_PCI_QUIRK(0x144d, 0xc109, "Samsung Ativ book 9 (NP900X3G)", ALC269_FIXUP_INV_DMIC), |
| 9860 | 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 | 9995 | SND_PCI_QUIRK(0x17aa, 0x22be, "Thinkpad X1 Carbon 8th", ALC285_FIXUP_THINKPAD_HEADSET_JACK), |
| 9989 | 9996 | SND_PCI_QUIRK(0x17aa, 0x22c1, "Thinkpad P1 Gen 3", ALC285_FIXUP_THINKPAD_NO_BASS_SPK_HEADSET_JACK), |
| 9990 | 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), | |
| 9992 | − SND_PCI_QUIRK(0x17aa, 0x22f2, "Thinkpad", ALC287_FIXUP_CS35L41_I2C_2_THINKPAD_ACPI), | |
| 9993 | − SND_PCI_QUIRK(0x17aa, 0x22f3, "Thinkpad", ALC287_FIXUP_CS35L41_I2C_2_THINKPAD_ACPI), | |
| 9994 | − SND_PCI_QUIRK(0x17aa, 0x2316, "Thinkpad P1 Gen 6", ALC287_FIXUP_CS35L41_I2C_2_THINKPAD_ACPI), | |
| 9995 | − SND_PCI_QUIRK(0x17aa, 0x2317, "Thinkpad P1 Gen 6", ALC287_FIXUP_CS35L41_I2C_2_THINKPAD_ACPI), | |
| 9996 | − SND_PCI_QUIRK(0x17aa, 0x2318, "Thinkpad Z13 Gen2", ALC287_FIXUP_CS35L41_I2C_2_THINKPAD_ACPI), | |
| 9997 | − SND_PCI_QUIRK(0x17aa, 0x2319, "Thinkpad Z16 Gen2", ALC287_FIXUP_CS35L41_I2C_2_THINKPAD_ACPI), | |
| 9998 | − SND_PCI_QUIRK(0x17aa, 0x231a, "Thinkpad Z16 Gen2", ALC287_FIXUP_CS35L41_I2C_2_THINKPAD_ACPI), | |
| 9998 | + SND_PCI_QUIRK(0x17aa, 0x22f1, "Thinkpad", ALC287_FIXUP_MG_RTKC_CSAMP_CS35L41_I2C_THINKPAD), | |
| 9999 | + SND_PCI_QUIRK(0x17aa, 0x22f2, "Thinkpad", ALC287_FIXUP_MG_RTKC_CSAMP_CS35L41_I2C_THINKPAD), | |
| 10000 | + SND_PCI_QUIRK(0x17aa, 0x22f3, "Thinkpad", ALC287_FIXUP_MG_RTKC_CSAMP_CS35L41_I2C_THINKPAD), | |
| 10001 | + SND_PCI_QUIRK(0x17aa, 0x2316, "Thinkpad P1 Gen 6", ALC287_FIXUP_MG_RTKC_CSAMP_CS35L41_I2C_THINKPAD), | |
| 10002 | + SND_PCI_QUIRK(0x17aa, 0x2317, "Thinkpad P1 Gen 6", ALC287_FIXUP_MG_RTKC_CSAMP_CS35L41_I2C_THINKPAD), | |
| 10003 | + SND_PCI_QUIRK(0x17aa, 0x2318, "Thinkpad Z13 Gen2", ALC287_FIXUP_MG_RTKC_CSAMP_CS35L41_I2C_THINKPAD), | |
| 10004 | + SND_PCI_QUIRK(0x17aa, 0x2319, "Thinkpad Z16 Gen2", ALC287_FIXUP_MG_RTKC_CSAMP_CS35L41_I2C_THINKPAD), | |
| 10005 | + SND_PCI_QUIRK(0x17aa, 0x231a, "Thinkpad Z16 Gen2", ALC287_FIXUP_MG_RTKC_CSAMP_CS35L41_I2C_THINKPAD), | |
| 9999 | 10006 | SND_PCI_QUIRK(0x17aa, 0x30bb, "ThinkCentre AIO", ALC233_FIXUP_LENOVO_LINE2_MIC_HOTKEY), |
| 10000 | 10007 | SND_PCI_QUIRK(0x17aa, 0x30e2, "ThinkCentre AIO", ALC233_FIXUP_LENOVO_LINE2_MIC_HOTKEY), |
| 10001 | 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 | 10098 | SND_PCI_QUIRK(0x8086, 0x2074, "Intel NUC 8", ALC233_FIXUP_INTEL_NUC8_DMIC), |
| 10092 | 10099 | SND_PCI_QUIRK(0x8086, 0x2080, "Intel NUC 8 Rugged", ALC256_FIXUP_INTEL_NUC8_RUGGED), |
| 10093 | 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 | 10102 | SND_PCI_QUIRK(0xf111, 0x0001, "Framework Laptop", ALC295_FIXUP_FRAMEWORK_LAPTOP_MIC_NO_PRESENCE), |
| 10096 | 10103 | |
| 10097 | 10104 | #if 0 |
| @@ -241,6 +241,13 @@ static const struct dmi_system_id yc_acp_quirk_table[] = { · 240 unmodified lines | ||
| 241 | 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 | 252 | .driver_data = &acp6x_card, |
| 246 | 253 | .matches = { |
| @@ -531,7 +531,10 @@ static int hdmi_codec_fill_codec_params(struct snd_soc_dai *dai, · 530 unmodified lines | ||
| 531 | 531 | hp->sample_rate = sample_rate; |
| 532 | 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 | 539 | return 0; |
| 537 | 540 | } |
| @@ -157,11 +157,6 @@ static int rt5682_i2c_probe(struct i2c_client *i2c) · 156 unmodified lines | ||
| 157 | 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 | 160 | ret = regulator_bulk_enable(ARRAY_SIZE(rt5682->supplies), |
| 166 | 161 | rt5682->supplies); |
| 167 | 162 | if (ret) { |
| @@ -169,6 +164,11 @@ static int rt5682_i2c_probe(struct i2c_client *i2c) · 1 unmodified line | ||
| 169 | 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 | 172 | ret = rt5682_get_ldo1(rt5682, &i2c->dev); |
| 173 | 173 | if (ret) |
| 174 | 174 | return ret; |
| @@ -293,7 +293,7 @@ · 292 unmodified lines | ||
| 293 | 293 | #define ADC3XXX_BYPASS_RPGA 0x80 |
| 294 | 294 | |
| 295 | 295 | /* MICBIAS control bits */ |
| 296 | −#define ADC3XXX_MICBIAS_MASK 0x2 | |
| 296 | +#define ADC3XXX_MICBIAS_MASK 0x3 | |
| 297 | 297 | #define ADC3XXX_MICBIAS1_SHIFT 5 |
| 298 | 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 | 1099 | unsigned int val; |
| 1100 | 1100 | |
| 1101 | 1101 | if (!of_property_read_u32(np, propname, &val)) { |
| 1102 | − if (val >= ADC3XXX_MICBIAS_AVDD) { | |
| 1102 | + if (val > ADC3XXX_MICBIAS_AVDD) { | |
| 1103 | 1103 | dev_err(dev, "Invalid property value for '%s'\n", propname); |
| 1104 | 1104 | return -EINVAL; |
| 1105 | 1105 | } |
| @@ -52,8 +52,8 @@ struct codec_priv { · 51 unmodified lines | ||
| 52 | 52 | unsigned long mclk_freq; |
| 53 | 53 | unsigned long free_freq; |
| 54 | 54 | u32 mclk_id; |
| 55 | − u32 fll_id; | |
| 56 | − u32 pll_id; | |
| 55 | + int fll_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 | 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 | 210 | if (priv->sample_format == SNDRV_PCM_FORMAT_S24_LE) |
| 211 | 211 | pll_out = priv->sample_rate * 384; |
| 212 | 212 | else |
| @@ -248,7 +248,7 @@ static int fsl_asoc_card_hw_free(struct snd_pcm_substream *substream) · 35 unmodified lines | ||
| 248 | 248 | |
| 249 | 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 | 252 | /* Force freq to be free_freq to avoid error message in codec */ |
| 253 | 253 | ret = snd_soc_dai_set_sysclk(asoc_rtd_to_codec(rtd, 0), |
| 254 | 254 | codec_priv->mclk_id, |
| @@ -621,6 +621,10 @@ static int fsl_asoc_card_probe(struct platform_device *pdev) · 366 unmodified lines | ||
| 621 | 621 | priv->card.dapm_routes = audio_map; |
| 622 | 622 | priv->card.num_dapm_routes = ARRAY_SIZE(audio_map); |
| 623 | 623 | priv->card.driver_name = DRIVER_NAME; |
| 624 | + | |
| 625 | + priv->codec_priv.fll_id = -1; | |
| 626 | + priv->codec_priv.pll_id = -1; | |
| 627 | + | |
| 624 | 628 | /* Diversify the card configurations */ |
| 625 | 629 | if (of_device_is_compatible(np, "fsl,imx-audio-cs42888")) { |
| 626 | 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 | 711 | unsigned int ofs = sai->soc_data->reg_offset; |
| 712 | 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 | 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 | 723 | /* TERE will remain set till the end of current frame */ |
| 719 | 724 | do { |
| @@ -310,7 +310,8 @@ int asoc_simple_startup(struct snd_pcm_substream *substream) · 309 unmodified lines | ||
| 310 | 310 | if (fixed_sysclk % props->mclk_fs) { |
| 311 | 311 | dev_err(rtd->dev, "fixed sysclk %u not divisible by mclk_fs %u\n", |
| 312 | 312 | fixed_sysclk, props->mclk_fs); |
| 313 | − return -EINVAL; | |
| 313 | + ret = -EINVAL; | |
| 314 | + goto codec_err; | |
| 314 | 315 | } |
| 315 | 316 | ret = snd_pcm_hw_constraint_minmax(substream->runtime, SNDRV_PCM_HW_PARAM_RATE, |
| 316 | 317 | fixed_rate, fixed_rate); |
| @@ -759,10 +759,12 @@ static int asoc_simple_probe(struct platform_device *pdev) · 758 unmodified lines | ||
| 759 | 759 | struct snd_soc_dai_link *dai_link = priv->dai_link; |
| 760 | 760 | struct simple_dai_props *dai_props = priv->dai_props; |
| 761 | 761 | |
| 762 | + ret = -EINVAL; | |
| 763 | + | |
| 762 | 764 | cinfo = dev->platform_data; |
| 763 | 765 | if (!cinfo) { |
| 764 | 766 | dev_err(dev, "no info for asoc-simple-card\n"); |
| 765 | − return -EINVAL; | |
| 767 | + goto err; | |
| 766 | 768 | } |
| 767 | 769 | |
| 768 | 770 | if (!cinfo->name || |
| @@ -771,7 +773,7 @@ static int asoc_simple_probe(struct platform_device *pdev) · 2 unmodified lines | ||
| 771 | 773 | !cinfo->platform || |
| 772 | 774 | !cinfo->cpu_dai.name) { |
| 773 | 775 | dev_err(dev, "insufficient asoc_simple_card_info settings\n"); |
| 774 | − return -EINVAL; | |
| 776 | + goto err; | |
| 775 | 777 | } |
| 776 | 778 | |
| 777 | 779 | cpus = dai_link->cpus; |
| @@ -808,6 +808,16 @@ static const struct platform_device_id board_ids[] = { · 807 unmodified lines | ||
| 808 | 808 | SOF_ES8336_SPEAKERS_EN_GPIO1_QUIRK | |
| 809 | 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 | 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 | 376 | /* No Jack */ |
| 377 | 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 | 390 | .callback = sof_sdw_quirk_cb, |
| 381 | 391 | .matches = { |
| @@ -655,18 +655,18 @@ struct snd_soc_acpi_mach snd_soc_acpi_intel_adl_sdw_machines[] = { · 654 unmodified lines | ||
| 655 | 655 | .drv_name = "sof_sdw", |
| 656 | 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 | 659 | .link_mask = 0x7, /* rt714 on link0 & two rt1316s on link1 and link2 */ |
| 666 | 660 | .links = adl_sdw_rt1316_link12_rt714_link0, |
| 667 | 661 | .drv_name = "sof_sdw", |
| 668 | 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 | 671 | .link_mask = 0x5, /* 2 active links required */ |
| 672 | 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 | 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 | 43 | struct snd_soc_acpi_mach snd_soc_acpi_intel_mtl_machines[] = { |
| 34 | 44 | { |
| 35 | 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 | 62 | .quirk_data = &mtl_rt1019p_amp, |
| 53 | 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 | 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 | 1347 | snd_soc_runtime_get_dai_fmt(rtd); |
| 1348 | 1348 | ret = snd_soc_runtime_set_dai_fmt(rtd, dai_link->dai_fmt); |
| 1349 | 1349 | if (ret) |
| 1350 | − return ret; | |
| 1350 | + goto err; | |
| 1351 | 1351 | |
| 1352 | 1352 | /* add DPCM sysfs entries */ |
| 1353 | 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 | 1372 | /* create compress_device if possible */ |
| 1373 | 1373 | ret = snd_soc_dai_compress_new(cpu_dai, rtd, num); |
| 1374 | 1374 | if (ret != -ENOTSUPP) |
| 1375 | − return ret; | |
| 1375 | + goto err; | |
| 1376 | 1376 | |
| 1377 | 1377 | /* create the pcm */ |
| 1378 | 1378 | ret = soc_new_pcm(rtd, num); |
| 1379 | 1379 | if (ret < 0) { |
| 1380 | 1380 | dev_err(card->dev, "ASoC: can't create pcm %s :%d\n", |
| 1381 | 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 | 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 | 1454 | if (component->card) { |
| 1446 | 1455 | if (component->card != card) { |
| 1447 | 1456 | dev_err(component->dev, |
| 1448 | − "Trying to bind component to card \"%s\" but is already bound to card \"%s\"\n", | |
| 1449 | − card->name, component->card->name); | |
| 1457 | + "Trying to bind component \"%s\" to card \"%s\" but is already bound to card \"%s\"\n", | |
| 1458 | + component->name, card->name, component->card->name); | |
| 1450 | 1459 | return -ENODEV; |
| 1451 | 1460 | } |
| 1452 | 1461 | return 0; |
| @@ -1980,7 +1989,8 @@ static void soc_cleanup_card_resources(struct snd_soc_card *card) · 527 unmodified lines | ||
| 1980 | 1989 | |
| 1981 | 1990 | /* release machine specific resources */ |
| 1982 | 1991 | for_each_card_rtds(card, rtd) |
| 1983 | − snd_soc_link_exit(rtd); | |
| 1992 | + if (rtd->initialized) | |
| 1993 | + snd_soc_link_exit(rtd); | |
| 1984 | 1994 | /* remove and free each DAI */ |
| 1985 | 1995 | soc_remove_link_dais(card); |
| 1986 | 1996 | soc_remove_link_components(card); |
| @@ -44,8 +44,8 @@ static struct device *dmaengine_dma_dev(struct dmaengine_pcm *pcm, · 43 unmodified lines | ||
| 44 | 44 | * platforms which make use of the snd_dmaengine_dai_dma_data struct for their |
| 45 | 45 | * DAI DMA data. Internally the function will first call |
| 46 | 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 | |
| 48 | − * remaining fields based on the DAI DMA data. | |
| 47 | + * hw_params, followed by snd_dmaengine_pcm_set_config_from_dai_data to fill in | |
| 48 | + * the remaining fields based on the DAI DMA data. | |
| 49 | 49 | */ |
| 50 | 50 | int snd_dmaengine_pcm_prepare_slave_config(struct snd_pcm_substream *substream, |
| 51 | 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 | 35 | .dsp_intr_base = ACP6X_DSP_SW_INTR_BASE, |
| 36 | 36 | .sram_pte_offset = ACP6X_SRAM_PTE_OFFSET, |
| 37 | 37 | .hw_semaphore_offset = ACP6X_AXI2DAGB_SEM_0, |
| 38 | − .acp_clkmux_sel = ACP6X_CLKMUX_SEL, | |
| 39 | 38 | .fusion_dsp_offset = ACP6X_DSP_FUSION_RUNSTALL, |
| 40 | 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 | 338 | /* Line discipline .receive_buf() */ |
| 339 | −static void cx81801_receive(struct tty_struct *tty, const u8 *cp, | |
| 340 | − const char *fp, int count) | |
| 339 | +static void cx81801_receive(struct tty_struct *tty, const u8 *cp, const u8 *fp, | |
| 340 | + size_t count) | |
| 341 | 341 | { |
| 342 | 342 | struct snd_soc_component *component = tty->disc_data; |
| 343 | 343 | const unsigned char *c; |
| @@ -1204,6 +1204,13 @@ static void volume_control_quirks(struct usb_mixer_elem_info *cval, · 1203 unmodified lines | ||
| 1204 | 1204 | cval->res = 16; |
| 1205 | 1205 | } |
| 1206 | 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 | 1994 | /* mic works only when ep packet size is set to wMaxPacketSize */ |
| 1995 | 1995 | fp->attributes |= UAC_EP_CS_ATTR_FILL_MAX; |
| 1996 | 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 | 2177 | QUIRK_FLAG_FIXED_RATE), |
| 2174 | 2178 | DEVICE_FLG(0x0ecb, 0x2069, /* JBL Quantum810 Wireless */ |
| 2175 | 2179 | QUIRK_FLAG_FIXED_RATE), |
| 2180 | + DEVICE_FLG(0x1bcf, 0x2283, /* NexiGo N930AF FHD Webcam */ | |
| 2181 | + QUIRK_FLAG_GET_SAMPLE_RATE), | |
| 2176 | 2182 | |
| 2177 | 2183 | /* Vendor matches */ |
| 2178 | 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 | 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 | 1239 | static int kvp_set_ip_info(char *if_name, struct hv_kvp_ipaddr_value *new_val) |
| 1175 | 1240 | { |
| 1176 | 1241 | int error = 0; |
| 1177 | − char if_file[PATH_MAX]; | |
| 1178 | − FILE *file; | |
| 1242 | + char if_filename[PATH_MAX]; | |
| 1243 | + char nm_filename[PATH_MAX]; | |
| 1244 | + FILE *ifcfg_file, *nmfile; | |
| 1179 | 1245 | char cmd[PATH_MAX]; |
| 1246 | + int is_ipv6 = 0; | |
| 1180 | 1247 | char *mac_addr; |
| 1181 | 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 | 1264 | * in a given distro to configure the interface and so are free |
| 1198 | 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 | 1269 | * HWADDR=macaddr |
| 1203 | 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 | 1287 | * tagged as IPV6_DEFAULTGW and IPV6 NETMASK will be tagged as |
| 1221 | 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 | 1316 | * The host can specify multiple ipv4 and ipv6 addresses to be |
| 1224 | 1317 | * configured for the interface. Furthermore, the configuration |
| 1225 | 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 | 1320 | * call. |
| 1228 | 1321 | */ |
| 1229 | 1322 | |
| 1230 | − snprintf(if_file, sizeof(if_file), "%s%s%s", KVP_CONFIG_LOC, | |
| 1231 | − "/ifcfg-", if_name); | |
| 1323 | + /* | |
| 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 | 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 | 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 | 1356 | goto setval_error; |
| 1249 | 1357 | } |
| 1250 | 1358 | |
| 1251 | − error = kvp_write_file(file, "HWADDR", "", mac_addr); | |
| 1252 | − free(mac_addr); | |
| 1359 | + error = kvp_write_file(ifcfg_file, "HWADDR", "", 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 | 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 | 1380 | if (error) |
| 1258 | − goto setval_error; | |
| 1381 | + goto setmac_error; | |
| 1382 | + | |
| 1383 | + free(mac_addr); | |
| 1259 | 1384 | |
| 1260 | 1385 | /* |
| 1261 | 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 | 1388 | * proceed to parse and pass the IPv6 information to the |
| 1264 | 1389 | * disto-specific script hv_set_ifconfig. |
| 1265 | 1390 | */ |
| 1391 | + | |
| 1392 | + /* | |
| 1393 | + * First populate the ifcfg file format | |
| 1394 | + */ | |
| 1266 | 1395 | if (new_val->dhcp_enabled) { |
| 1267 | − error = kvp_write_file(file, "BOOTPROTO", "", "dhcp"); | |
| 1396 | + error = kvp_write_file(ifcfg_file, "BOOTPROTO", "", "dhcp"); | |
| 1268 | 1397 | if (error) |
| 1269 | 1398 | goto setval_error; |
| 1270 | − | |
| 1271 | 1399 | } else { |
| 1272 | − error = kvp_write_file(file, "BOOTPROTO", "", "none"); | |
| 1400 | + error = kvp_write_file(ifcfg_file, "BOOTPROTO", "", "none"); | |
| 1273 | 1401 | if (error) |
| 1274 | 1402 | goto setval_error; |
| 1275 | 1403 | } |
| 1276 | 1404 | |
| 1277 | − /* | |
| 1278 | − * Write the configuration for ipaddress, netmask, gateway and | |
| 1279 | − * name servers. | |
| 1280 | − */ | |
| 1281 | − | |
| 1282 | − error = process_ip_string(file, (char *)new_val->ip_addr, IPADDR); | |
| 1405 | + error = process_ip_string(ifcfg_file, (char *)new_val->ip_addr, | |
| 1406 | + IPADDR); | |
| 1283 | 1407 | if (error) |
| 1284 | 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 | 1412 | if (error) |
| 1288 | 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 | 1417 | if (error) |
| 1292 | 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 | 1421 | if (error) |
| 1296 | 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 | 1470 | * Now that we have populated the configuration file, |
| 1302 | 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", | |
| 1306 | − "hv_set_ifconfig", if_file); | |
| 1474 | + str_len = snprintf(cmd, sizeof(cmd), KVP_SCRIPTS_PATH "%s %s %s", | |
| 1475 | + "hv_set_ifconfig", if_filename, nm_filename); | |
| 1307 | 1476 | /* |
| 1308 | 1477 | * This is a little overcautious, but it's necessary to suppress some |
| 1309 | 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 | 1486 | if (system(cmd)) { |
| 1318 | 1487 | syslog(LOG_ERR, "Failed to execute cmd '%s'; error: %d %s", |
| 1319 | − cmd, errno, strerror(errno)); | |
| 1488 | + cmd, errno, strerror(errno)); | |
| 1320 | 1489 | return HV_E_FAIL; |
| 1321 | 1490 | } |
| 1322 | 1491 | return 0; |
| 1323 | − | |
| 1492 | +setmac_error: | |
| 1493 | + free(mac_addr); | |
| 1324 | 1494 | setval_error: |
| 1325 | 1495 | syslog(LOG_ERR, "Failed to write config file"); |
| 1326 | − fclose(file); | |
| 1496 | + fclose(ifcfg_file); | |
| 1497 | + fclose(nmfile); | |
| 1327 | 1498 | return error; |
| 1328 | 1499 | } |
| 1329 | 1500 | |
| @@ -18,12 +18,12 @@ · 17 unmodified lines | ||
| 18 | 18 | # |
| 19 | 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 | 23 | # HWADDR=macaddr |
| 24 | 24 | # DEVICE=interface name |
| 25 | 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 | 28 | # IPADDR0=ipaddr1 |
| 29 | 29 | # IPADDR1=ipaddr2 |
| @@ -41,6 +41,32 @@ · 11 unmodified lines | ||
| 41 | 41 | # tagged as IPV6_DEFAULTGW and IPV6 NETMASK will be tagged as |
| 42 | 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 | 70 | # The host can specify multiple ipv4 and ipv6 addresses to be |
| 45 | 71 | # configured for the interface. Furthermore, the configuration |
| 46 | 72 | # needs to be persistent. A subsequent GET call on the interface |
| @@ -48,18 +74,19 @@ · 1 unmodified line | ||
| 48 | 74 | # call. |
| 49 | 75 | # |
| 50 | 76 | |
| 51 | − | |
| 52 | − | |
| 53 | 77 | echo "IPV6INIT=yes" >> $1 |
| 54 | 78 | echo "NM_CONTROLLED=no" >> $1 |
| 55 | 79 | echo "PEERDNS=yes" >> $1 |
| 56 | 80 | echo "ONBOOT=yes" >> $1 |
| 57 | 81 | |
| 58 | − | |
| 59 | 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 | 91 | /sbin/ifdown $interface 2>/dev/null |
| 65 | 92 | /sbin/ifup $interface 2>/dev/null |
| @@ -92,7 +92,7 @@ endif · 91 unmodified lines | ||
| 92 | 92 | TARGETS += tmpfs |
| 93 | 93 | TARGETS += tpm2 |
| 94 | 94 | TARGETS += tty |
| 95 | −TARGETS += uevents | |
| 95 | +TARGETS += uevent | |
| 96 | 96 | TARGETS += user |
| 97 | 97 | TARGETS += user_events |
| 98 | 98 | TARGETS += vDSO |
| @@ -185,6 +185,8 @@ static void test_cubic(void) · 184 unmodified lines | ||
| 185 | 185 | |
| 186 | 186 | do_test("bpf_cubic", NULL); |
| 187 | 187 | |
| 188 | + ASSERT_EQ(cubic_skel->bss->bpf_cubic_acked_called, 1, "pkts_acked called"); | |
| 189 | + | |
| 188 | 190 | bpf_link__destroy(link); |
| 189 | 191 | bpf_cubic__destroy(cubic_skel); |
| 190 | 192 | } |
| @@ -475,6 +475,55 @@ out: · 474 unmodified lines | ||
| 475 | 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 | 527 | void test_sockmap_basic(void) |
| 479 | 528 | { |
| 480 | 529 | if (test__start_subtest("sockmap create_update_free")) |
| @@ -515,4 +564,6 @@ void test_sockmap_basic(void) · 34 unmodified lines | ||
| 515 | 564 | test_sockmap_skb_verdict_fionread(true); |
| 516 | 565 | if (test__start_subtest("sockmap skb_verdict fionread on drop")) |
| 517 | 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 | 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 | 50 | __u32 count = 0, attach_flags = 0; |
| 51 | 51 | int err; |
| @@ -53,20 +53,22 @@ static inline void __assert_mprog_count(int target, int expected, bool miniq, in · 1 unmodified line | ||
| 53 | 53 | err = bpf_prog_query(ifindex, target, 0, &attach_flags, |
| 54 | 54 | NULL, &count); |
| 55 | 55 | ASSERT_EQ(count, expected, "count"); |
| 56 | − if (!expected && !miniq) | |
| 57 | − ASSERT_EQ(err, -ENOENT, "prog_query"); | |
| 58 | − else | |
| 59 | − ASSERT_EQ(err, 0, "prog_query"); | |
| 56 | + ASSERT_EQ(err, 0, "prog_query"); | |
| 60 | 57 | } |
| 61 | 58 | |
| 62 | 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 | 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 | 74 | #endif /* TC_HELPERS */ |
| @@ -65,6 +65,7 @@ void serial_test_tc_links_basic(void) · 64 unmodified lines | ||
| 65 | 65 | ASSERT_EQ(optq.prog_ids[1], 0, "prog_ids[1]"); |
| 66 | 66 | ASSERT_EQ(optq.link_ids[1], 0, "link_ids[1]"); |
| 67 | 67 | |
| 68 | + tc_skel_reset_all_seen(skel); | |
| 68 | 69 | ASSERT_OK(system(ping_cmd), ping_cmd); |
| 69 | 70 | |
| 70 | 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 | 98 | ASSERT_EQ(optq.prog_ids[1], 0, "prog_ids[1]"); |
| 98 | 99 | ASSERT_EQ(optq.link_ids[1], 0, "link_ids[1]"); |
| 99 | 100 | |
| 101 | + tc_skel_reset_all_seen(skel); | |
| 100 | 102 | ASSERT_OK(system(ping_cmd), ping_cmd); |
| 101 | 103 | |
| 102 | 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 | 189 | ASSERT_EQ(optq.prog_ids[2], 0, "prog_ids[2]"); |
| 188 | 190 | ASSERT_EQ(optq.link_ids[2], 0, "link_ids[2]"); |
| 189 | 191 | |
| 192 | + tc_skel_reset_all_seen(skel); | |
| 190 | 193 | ASSERT_OK(system(ping_cmd), ping_cmd); |
| 191 | 194 | |
| 192 | 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 | 197 | ASSERT_EQ(skel->bss->seen_tc3, false, "seen_tc3"); |
| 195 | 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 | 200 | LIBBPF_OPTS_RESET(optl, |
| 201 | 201 | .flags = BPF_F_BEFORE, |
| 202 | 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 | 246 | ASSERT_EQ(optq.prog_ids[4], 0, "prog_ids[4]"); |
| 247 | 247 | ASSERT_EQ(optq.link_ids[4], 0, "link_ids[4]"); |
| 248 | 248 | |
| 249 | + tc_skel_reset_all_seen(skel); | |
| 249 | 250 | ASSERT_OK(system(ping_cmd), ping_cmd); |
| 250 | 251 | |
| 251 | 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 | 343 | ASSERT_EQ(optq.prog_ids[2], 0, "prog_ids[2]"); |
| 343 | 344 | ASSERT_EQ(optq.link_ids[2], 0, "link_ids[2]"); |
| 344 | 345 | |
| 346 | + tc_skel_reset_all_seen(skel); | |
| 345 | 347 | ASSERT_OK(system(ping_cmd), ping_cmd); |
| 346 | 348 | |
| 347 | 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 | 351 | ASSERT_EQ(skel->bss->seen_tc3, false, "seen_tc3"); |
| 350 | 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 | 354 | LIBBPF_OPTS_RESET(optl, |
| 356 | 355 | .flags = BPF_F_AFTER, |
| 357 | 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 | 400 | ASSERT_EQ(optq.prog_ids[4], 0, "prog_ids[4]"); |
| 402 | 401 | ASSERT_EQ(optq.link_ids[4], 0, "link_ids[4]"); |
| 403 | 402 | |
| 403 | + tc_skel_reset_all_seen(skel); | |
| 404 | 404 | ASSERT_OK(system(ping_cmd), ping_cmd); |
| 405 | 405 | |
| 406 | 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 | 502 | ASSERT_EQ(optq.prog_ids[2], 0, "prog_ids[2]"); |
| 503 | 503 | ASSERT_EQ(optq.link_ids[2], 0, "prog_ids[2]"); |
| 504 | 504 | |
| 505 | + tc_skel_reset_all_seen(skel); | |
| 505 | 506 | ASSERT_OK(system(ping_cmd), ping_cmd); |
| 506 | 507 | |
| 507 | 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 | 583 | assert_mprog_count(target, 2); |
| 583 | 584 | |
| 585 | + tc_skel_reset_all_seen(skel); | |
| 584 | 586 | ASSERT_OK(system(ping_cmd), ping_cmd); |
| 585 | 587 | |
| 586 | 588 | ASSERT_EQ(skel->bss->seen_tc1, true, "seen_tc1"); |
| 587 | 589 | ASSERT_EQ(skel->bss->seen_tc2, true, "seen_tc2"); |
| 588 | 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 | 592 | err = bpf_link__detach(skel->links.tc2); |
| 595 | 593 | if (!ASSERT_OK(err, "prog_detach")) |
| 596 | 594 | goto cleanup; |
| 597 | 595 | |
| 598 | 596 | assert_mprog_count(target, 1); |
| 599 | 597 | |
| 598 | + tc_skel_reset_all_seen(skel); | |
| 600 | 599 | ASSERT_OK(system(ping_cmd), ping_cmd); |
| 601 | 600 | |
| 602 | 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 | 706 | ASSERT_EQ(optq.prog_ids[2], 0, "prog_ids[2]"); |
| 708 | 707 | ASSERT_EQ(optq.link_ids[2], 0, "link_ids[2]"); |
| 709 | 708 | |
| 709 | + tc_skel_reset_all_seen(skel); | |
| 710 | 710 | ASSERT_OK(system(ping_cmd), ping_cmd); |
| 711 | 711 | |
| 712 | 712 | ASSERT_EQ(skel->bss->seen_tc1, true, "seen_tc1"); |
| 713 | 713 | ASSERT_EQ(skel->bss->seen_tc2, true, "seen_tc2"); |
| 714 | 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 | 716 | LIBBPF_OPTS_RESET(optl, |
| 721 | 717 | .flags = BPF_F_REPLACE, |
| 722 | 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 | 777 | ASSERT_EQ(optq.prog_ids[2], 0, "prog_ids[2]"); |
| 782 | 778 | ASSERT_EQ(optq.link_ids[2], 0, "link_ids[2]"); |
| 783 | 779 | |
| 780 | + tc_skel_reset_all_seen(skel); | |
| 784 | 781 | ASSERT_OK(system(ping_cmd), ping_cmd); |
| 785 | 782 | |
| 786 | 783 | ASSERT_EQ(skel->bss->seen_tc1, true, "seen_tc1"); |
| 787 | 784 | ASSERT_EQ(skel->bss->seen_tc2, false, "seen_tc2"); |
| 788 | 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 | 787 | err = bpf_link__detach(skel->links.tc2); |
| 795 | 788 | if (!ASSERT_OK(err, "link_detach")) |
| 796 | 789 | goto cleanup; |
| @@ -812,16 +805,13 @@ static void test_tc_links_replace_target(int target) · 15 unmodified lines | ||
| 812 | 805 | ASSERT_EQ(optq.prog_ids[1], 0, "prog_ids[1]"); |
| 813 | 806 | ASSERT_EQ(optq.link_ids[1], 0, "link_ids[1]"); |
| 814 | 807 | |
| 808 | + tc_skel_reset_all_seen(skel); | |
| 815 | 809 | ASSERT_OK(system(ping_cmd), ping_cmd); |
| 816 | 810 | |
| 817 | 811 | ASSERT_EQ(skel->bss->seen_tc1, true, "seen_tc1"); |
| 818 | 812 | ASSERT_EQ(skel->bss->seen_tc2, false, "seen_tc2"); |
| 819 | 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 | 815 | err = bpf_link__update_program(skel->links.tc1, skel->progs.tc1); |
| 826 | 816 | if (!ASSERT_OK(err, "link_update_self")) |
| 827 | 817 | goto cleanup; |
| @@ -843,6 +833,7 @@ static void test_tc_links_replace_target(int target) · 15 unmodified lines | ||
| 843 | 833 | ASSERT_EQ(optq.prog_ids[1], 0, "prog_ids[1]"); |
| 844 | 834 | ASSERT_EQ(optq.link_ids[1], 0, "link_ids[1]"); |
| 845 | 835 | |
| 836 | + tc_skel_reset_all_seen(skel); | |
| 846 | 837 | ASSERT_OK(system(ping_cmd), ping_cmd); |
| 847 | 838 | |
| 848 | 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 | 1245 | ASSERT_EQ(optq.prog_ids[2], 0, "prog_ids[2]"); |
| 1255 | 1246 | ASSERT_EQ(optq.link_ids[2], 0, "link_ids[2]"); |
| 1256 | 1247 | |
| 1248 | + tc_skel_reset_all_seen(skel); | |
| 1257 | 1249 | ASSERT_OK(system(ping_cmd), ping_cmd); |
| 1258 | 1250 | |
| 1259 | 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 | 1253 | ASSERT_EQ(skel->bss->seen_tc3, false, "seen_tc3"); |
| 1262 | 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 | 1256 | LIBBPF_OPTS_RESET(optl, |
| 1268 | 1257 | .flags = BPF_F_BEFORE, |
| 1269 | 1258 | ); |
| @@ -1311,6 +1300,7 @@ static void test_tc_links_prepend_target(int target) · 41 unmodified lines | ||
| 1311 | 1300 | ASSERT_EQ(optq.prog_ids[4], 0, "prog_ids[4]"); |
| 1312 | 1301 | ASSERT_EQ(optq.link_ids[4], 0, "link_ids[4]"); |
| 1313 | 1302 | |
| 1303 | + tc_skel_reset_all_seen(skel); | |
| 1314 | 1304 | ASSERT_OK(system(ping_cmd), ping_cmd); |
| 1315 | 1305 | |
| 1316 | 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 | 1401 | ASSERT_EQ(optq.prog_ids[2], 0, "prog_ids[2]"); |
| 1412 | 1402 | ASSERT_EQ(optq.link_ids[2], 0, "link_ids[2]"); |
| 1413 | 1403 | |
| 1404 | + tc_skel_reset_all_seen(skel); | |
| 1414 | 1405 | ASSERT_OK(system(ping_cmd), ping_cmd); |
| 1415 | 1406 | |
| 1416 | 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 | 1409 | ASSERT_EQ(skel->bss->seen_tc3, false, "seen_tc3"); |
| 1419 | 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 | 1412 | LIBBPF_OPTS_RESET(optl, |
| 1425 | 1413 | .flags = BPF_F_AFTER, |
| 1426 | 1414 | ); |
| @@ -1468,6 +1456,7 @@ static void test_tc_links_append_target(int target) · 41 unmodified lines | ||
| 1468 | 1456 | ASSERT_EQ(optq.prog_ids[4], 0, "prog_ids[4]"); |
| 1469 | 1457 | ASSERT_EQ(optq.link_ids[4], 0, "link_ids[4]"); |
| 1470 | 1458 | |
| 1459 | + tc_skel_reset_all_seen(skel); | |
| 1471 | 1460 | ASSERT_OK(system(ping_cmd), ping_cmd); |
| 1472 | 1461 | |
| 1473 | 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 | 1627 | assert_mprog_count(target, 1); |
| 1639 | 1628 | |
| 1629 | + tc_skel_reset_all_seen(skel); | |
| 1640 | 1630 | ASSERT_OK(system(ping_cmd), ping_cmd); |
| 1641 | 1631 | |
| 1642 | 1632 | ASSERT_EQ(skel->bss->seen_tc4, false, "seen_tc4"); |
| 1643 | 1633 | ASSERT_EQ(skel->bss->seen_tc5, false, "seen_tc5"); |
| 1644 | 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 | 1636 | err = bpf_link__update_program(skel->links.tc6, skel->progs.tc4); |
| 1651 | 1637 | if (!ASSERT_OK(err, "link_update")) |
| 1652 | 1638 | goto cleanup; |
| 1653 | 1639 | |
| 1654 | 1640 | assert_mprog_count(target, 1); |
| 1655 | 1641 | |
| 1642 | + tc_skel_reset_all_seen(skel); | |
| 1656 | 1643 | ASSERT_OK(system(ping_cmd), ping_cmd); |
| 1657 | 1644 | |
| 1658 | 1645 | ASSERT_EQ(skel->bss->seen_tc4, true, "seen_tc4"); |
| 1659 | 1646 | ASSERT_EQ(skel->bss->seen_tc5, true, "seen_tc5"); |
| 1660 | 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 | 1649 | err = bpf_link__detach(skel->links.tc6); |
| 1667 | 1650 | if (!ASSERT_OK(err, "prog_detach")) |
| 1668 | 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 | 1656 | ASSERT_OK(system(ping_cmd), ping_cmd); |
| 1673 | 1657 | |
| 1674 | 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 | 1743 | assert_mprog_count(target, 2); |
| 1760 | 1744 | |
| 1745 | + tc_skel_reset_all_seen(skel); | |
| 1761 | 1746 | ASSERT_OK(system(ping_cmd), ping_cmd); |
| 1762 | 1747 | |
| 1763 | 1748 | ASSERT_EQ(skel->bss->seen_tc1, true, "seen_tc1"); |
| 1764 | 1749 | ASSERT_EQ(skel->bss->seen_tc2, true, "seen_tc2"); |
| 1765 | 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 | 1752 | err = bpf_link__detach(skel->links.tc2); |
| 1772 | 1753 | if (!ASSERT_OK(err, "prog_detach")) |
| 1773 | 1754 | goto cleanup; |
| 1774 | 1755 | |
| 1775 | 1756 | assert_mprog_count(target, 1); |
| 1776 | 1757 | |
| 1758 | + tc_skel_reset_all_seen(skel); | |
| 1777 | 1759 | ASSERT_OK(system(ping_cmd), ping_cmd); |
| 1778 | 1760 | |
| 1779 | 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 | 59 | ASSERT_EQ(optq.prog_ids[0], id1, "prog_ids[0]"); |
| 60 | 60 | ASSERT_EQ(optq.prog_ids[1], 0, "prog_ids[1]"); |
| 61 | 61 | |
| 62 | + tc_skel_reset_all_seen(skel); | |
| 62 | 63 | ASSERT_OK(system(ping_cmd), ping_cmd); |
| 63 | 64 | |
| 64 | 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 | 84 | ASSERT_EQ(optq.prog_ids[0], id2, "prog_ids[0]"); |
| 84 | 85 | ASSERT_EQ(optq.prog_ids[1], 0, "prog_ids[1]"); |
| 85 | 86 | |
| 87 | + tc_skel_reset_all_seen(skel); | |
| 86 | 88 | ASSERT_OK(system(ping_cmd), ping_cmd); |
| 87 | 89 | |
| 88 | 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 | 165 | ASSERT_EQ(optq.prog_ids[1], id2, "prog_ids[1]"); |
| 164 | 166 | ASSERT_EQ(optq.prog_ids[2], 0, "prog_ids[2]"); |
| 165 | 167 | |
| 168 | + tc_skel_reset_all_seen(skel); | |
| 166 | 169 | ASSERT_OK(system(ping_cmd), ping_cmd); |
| 167 | 170 | |
| 168 | 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 | 222 | ASSERT_EQ(optq.prog_ids[3], id2, "prog_ids[3]"); |
| 220 | 223 | ASSERT_EQ(optq.prog_ids[4], 0, "prog_ids[4]"); |
| 221 | 224 | |
| 225 | + tc_skel_reset_all_seen(skel); | |
| 222 | 226 | ASSERT_OK(system(ping_cmd), ping_cmd); |
| 223 | 227 | |
| 224 | 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 | 317 | ASSERT_EQ(optq.prog_ids[1], id2, "prog_ids[1]"); |
| 314 | 318 | ASSERT_EQ(optq.prog_ids[2], 0, "prog_ids[2]"); |
| 315 | 319 | |
| 320 | + tc_skel_reset_all_seen(skel); | |
| 316 | 321 | ASSERT_OK(system(ping_cmd), ping_cmd); |
| 317 | 322 | |
| 318 | 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 | 374 | ASSERT_EQ(optq.prog_ids[3], id4, "prog_ids[3]"); |
| 370 | 375 | ASSERT_EQ(optq.prog_ids[4], 0, "prog_ids[4]"); |
| 371 | 376 | |
| 377 | + tc_skel_reset_all_seen(skel); | |
| 372 | 378 | ASSERT_OK(system(ping_cmd), ping_cmd); |
| 373 | 379 | |
| 374 | 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 | 520 | ASSERT_EQ(optq.prog_ids[1], id2, "prog_ids[1]"); |
| 515 | 521 | ASSERT_EQ(optq.prog_ids[2], 0, "prog_ids[2]"); |
| 516 | 522 | |
| 523 | + tc_skel_reset_all_seen(skel); | |
| 517 | 524 | ASSERT_OK(system(ping_cmd), ping_cmd); |
| 518 | 525 | |
| 519 | 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 | 616 | assert_mprog_count(target, 2); |
| 610 | 617 | |
| 618 | + tc_skel_reset_all_seen(skel); | |
| 611 | 619 | ASSERT_OK(system(ping_cmd), ping_cmd); |
| 612 | 620 | |
| 613 | 621 | ASSERT_EQ(skel->bss->seen_tc1, true, "seen_tc1"); |
| 614 | 622 | ASSERT_EQ(skel->bss->seen_tc2, true, "seen_tc2"); |
| 615 | 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 | 625 | err = bpf_prog_detach_opts(fd2, loopback, target, &optd); |
| 622 | 626 | if (!ASSERT_OK(err, "prog_detach")) |
| 623 | 627 | goto cleanup_detach; |
| 624 | 628 | |
| 625 | 629 | assert_mprog_count(target, 1); |
| 626 | 630 | |
| 631 | + tc_skel_reset_all_seen(skel); | |
| 627 | 632 | ASSERT_OK(system(ping_cmd), ping_cmd); |
| 628 | 633 | |
| 629 | 634 | ASSERT_EQ(skel->bss->seen_tc1, true, "seen_tc1"); |
| @@ -635,7 +640,7 @@ cleanup_detach: · 5 unmodified lines | ||
| 635 | 640 | if (!ASSERT_OK(err, "prog_detach")) |
| 636 | 641 | goto cleanup; |
| 637 | 642 | |
| 638 | − __assert_mprog_count(target, 0, chain_tc_old, loopback); | |
| 643 | + assert_mprog_count(target, 0); | |
| 639 | 644 | cleanup: |
| 640 | 645 | if (tc_attached) { |
| 641 | 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 | 735 | ASSERT_EQ(optq.prog_attach_flags[1], 0, "prog_flags[1]"); |
| 731 | 736 | ASSERT_EQ(optq.prog_attach_flags[2], 0, "prog_flags[2]"); |
| 732 | 737 | |
| 738 | + tc_skel_reset_all_seen(skel); | |
| 733 | 739 | ASSERT_OK(system(ping_cmd), ping_cmd); |
| 734 | 740 | |
| 735 | 741 | ASSERT_EQ(skel->bss->seen_tc1, true, "seen_tc1"); |
| 736 | 742 | ASSERT_EQ(skel->bss->seen_tc2, true, "seen_tc2"); |
| 737 | 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 | 745 | LIBBPF_OPTS_RESET(opta, |
| 744 | 746 | .flags = BPF_F_REPLACE, |
| 745 | 747 | .replace_prog_fd = fd2, |
| @@ -767,16 +769,13 @@ static void test_tc_opts_replace_target(int target) · 21 unmodified lines | ||
| 767 | 769 | ASSERT_EQ(optq.prog_ids[1], id1, "prog_ids[1]"); |
| 768 | 770 | ASSERT_EQ(optq.prog_ids[2], 0, "prog_ids[2]"); |
| 769 | 771 | |
| 772 | + tc_skel_reset_all_seen(skel); | |
| 770 | 773 | ASSERT_OK(system(ping_cmd), ping_cmd); |
| 771 | 774 | |
| 772 | 775 | ASSERT_EQ(skel->bss->seen_tc1, true, "seen_tc1"); |
| 773 | 776 | ASSERT_EQ(skel->bss->seen_tc2, false, "seen_tc2"); |
| 774 | 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 | 779 | LIBBPF_OPTS_RESET(opta, |
| 781 | 780 | .flags = BPF_F_REPLACE | BPF_F_BEFORE, |
| 782 | 781 | .replace_prog_fd = fd3, |
| @@ -805,6 +804,7 @@ static void test_tc_opts_replace_target(int target) · 22 unmodified lines | ||
| 805 | 804 | ASSERT_EQ(optq.prog_ids[1], id1, "prog_ids[1]"); |
| 806 | 805 | ASSERT_EQ(optq.prog_ids[2], 0, "prog_ids[2]"); |
| 807 | 806 | |
| 807 | + tc_skel_reset_all_seen(skel); | |
| 808 | 808 | ASSERT_OK(system(ping_cmd), ping_cmd); |
| 809 | 809 | |
| 810 | 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 | 1084 | ASSERT_EQ(optq.prog_ids[1], id1, "prog_ids[1]"); |
| 1085 | 1085 | ASSERT_EQ(optq.prog_ids[2], 0, "prog_ids[2]"); |
| 1086 | 1086 | |
| 1087 | + tc_skel_reset_all_seen(skel); | |
| 1087 | 1088 | ASSERT_OK(system(ping_cmd), ping_cmd); |
| 1088 | 1089 | |
| 1089 | 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 | 1125 | ASSERT_EQ(optq.prog_ids[3], id1, "prog_ids[3]"); |
| 1125 | 1126 | ASSERT_EQ(optq.prog_ids[4], 0, "prog_ids[4]"); |
| 1126 | 1127 | |
| 1128 | + tc_skel_reset_all_seen(skel); | |
| 1127 | 1129 | ASSERT_OK(system(ping_cmd), ping_cmd); |
| 1128 | 1130 | |
| 1129 | 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 | 1224 | ASSERT_EQ(optq.prog_ids[1], id2, "prog_ids[1]"); |
| 1223 | 1225 | ASSERT_EQ(optq.prog_ids[2], 0, "prog_ids[2]"); |
| 1224 | 1226 | |
| 1227 | + tc_skel_reset_all_seen(skel); | |
| 1225 | 1228 | ASSERT_OK(system(ping_cmd), ping_cmd); |
| 1226 | 1229 | |
| 1227 | 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 | 1265 | ASSERT_EQ(optq.prog_ids[3], id4, "prog_ids[3]"); |
| 1263 | 1266 | ASSERT_EQ(optq.prog_ids[4], 0, "prog_ids[4]"); |
| 1264 | 1267 | |
| 1268 | + tc_skel_reset_all_seen(skel); | |
| 1265 | 1269 | ASSERT_OK(system(ping_cmd), ping_cmd); |
| 1266 | 1270 | |
| 1267 | 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 | 2254 | BPF_TC_INGRESS : BPF_TC_EGRESS; |
| 2251 | 2255 | err = bpf_tc_hook_create(&tc_hook); |
| 2252 | 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 | 2259 | err = bpf_prog_detach_opts(0, loopback, target, &optd); |
| 2256 | 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 | 2321 | assert_mprog_count(target, 1); |
| 2318 | 2322 | |
| 2323 | + tc_skel_reset_all_seen(skel); | |
| 2319 | 2324 | ASSERT_OK(system(ping_cmd), ping_cmd); |
| 2320 | 2325 | |
| 2321 | 2326 | ASSERT_EQ(skel->bss->seen_tc4, false, "seen_tc4"); |
| 2322 | 2327 | ASSERT_EQ(skel->bss->seen_tc5, false, "seen_tc5"); |
| 2323 | 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 | 2330 | LIBBPF_OPTS_RESET(opta, |
| 2330 | 2331 | .flags = BPF_F_REPLACE, |
| 2331 | 2332 | .replace_prog_fd = fd3, |
| @@ -2339,21 +2340,19 @@ static void test_tc_chain_mixed(int target) · 7 unmodified lines | ||
| 2339 | 2340 | |
| 2340 | 2341 | assert_mprog_count(target, 1); |
| 2341 | 2342 | |
| 2343 | + tc_skel_reset_all_seen(skel); | |
| 2342 | 2344 | ASSERT_OK(system(ping_cmd), ping_cmd); |
| 2343 | 2345 | |
| 2344 | 2346 | ASSERT_EQ(skel->bss->seen_tc4, true, "seen_tc4"); |
| 2345 | 2347 | ASSERT_EQ(skel->bss->seen_tc5, true, "seen_tc5"); |
| 2346 | 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 | 2350 | cleanup_opts: |
| 2353 | 2351 | err = bpf_prog_detach_opts(detach_fd, loopback, target, &optd); |
| 2354 | 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 | 2356 | ASSERT_OK(system(ping_cmd), ping_cmd); |
| 2358 | 2357 | |
| 2359 | 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 | 2377 | test_tc_chain_mixed(BPF_TCX_INGRESS); |
| 2379 | 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 | 2 | /* Copyright (c) 2021 Facebook */ |
| 3 | 3 | #include <test_progs.h> |
| 4 | 4 | #include "timer.skel.h" |
| 5 | +#include "timer_failure.skel.h" | |
| 5 | 6 | |
| 6 | 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 | 51 | timer_skel = timer__open_and_load(); |
| 51 | 52 | if (!ASSERT_OK_PTR(timer_skel, "timer_skel_load")) |
| 52 | − goto cleanup; | |
| 53 | + return; | |
| 53 | 54 | |
| 54 | 55 | err = timer(timer_skel); |
| 55 | 56 | ASSERT_OK(err, "timer"); |
| 56 | −cleanup: | |
| 57 | 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 | 495 | void BPF_STRUCT_OPS(bpf_cubic_acked, struct sock *sk, |
| 494 | 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 | 499 | struct bictcp *ca = inet_csk_ca(sk); |
| 498 | 500 | __u32 delay; |
| 499 | 501 | |
| 502 | + bpf_cubic_acked_called = 1; | |
| 500 | 503 | /* Some calls are for duplicates without timetamps */ |
| 501 | 504 | if (sample->rtt_us < 0) |
| 502 | 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 | 6 | nft_concat_range.sh nft_conntrack_helper.sh \ |
| 7 | 7 | nft_queue.sh nft_meta.sh nf_nat_edemux.sh \ |
| 8 | 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 | 12 | HOSTPKG_CONFIG := pkg-config |
| 12 | 13 | |
| 13 | 14 | CFLAGS += $(shell $(HOSTPKG_CONFIG) --cflags libmnl 2>/dev/null) |
| 14 | 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 | 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 | 14 | logfile=$(mktemp) |
| 15 | +rulefile=$(mktemp) | |
| 15 | 16 | echo "logging into $logfile" |
| 16 | 17 | ./audit_logread >"$logfile" & |
| 17 | 18 | logread_pid=$! |
| 18 | −trap 'kill $logread_pid; rm -f $logfile' EXIT | |
| 19 | +trap 'kill $logread_pid; rm -f $logfile $rulefile' EXIT | |
| 19 | 20 | exec 3<"$logfile" |
| 20 | 21 | |
| 21 | 22 | do_test() { # (cmd, log) |
| @@ -26,12 +27,14 @@ do_test() { # (cmd, log) · 4 unmodified lines | ||
| 26 | 27 | res=$(diff -a -u <(echo "$2") - <&3) |
| 27 | 28 | [ $? -eq 0 ] && { echo "OK"; return; } |
| 28 | 29 | echo "FAIL" |
| 29 | − echo "$res" | |
| 30 | − ((RC++)) | |
| 30 | + grep -v '^\(---\|+++\|@@\)' <<< "$res" | |
| 31 | + ((RC--)) | |
| 31 | 32 | } |
| 32 | 33 | |
| 33 | 34 | nft flush ruleset |
| 34 | 35 | |
| 36 | +# adding tables, chains and rules | |
| 37 | + | |
| 35 | 38 | for table in t1 t2; do |
| 36 | 39 | do_test "nft add table $table" \ |
| 37 | 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 | 65 | "table=$table family=2 entries=6 op=nft_register_rule" |
| 63 | 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 | 110 | do_test 'nft reset rules t1 c2' \ |
| 66 | 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 | 115 | table=t1 family=2 entries=3 op=nft_reset_rule |
| 71 | 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 | 118 | do_test 'nft reset rules t2 c3' \ |
| 87 | 119 | 'table=t2 family=2 entries=189 op=nft_reset_rule |
| 88 | 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 | 137 | table=t2 family=2 entries=188 op=nft_reset_rule |
| 106 | 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 | 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 | 5 | # Additional include paths needed by kselftest.h and local headers |
| 6 | 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 | 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 | 15 | $(CC) -o$@ $(CFLAGS) $(LDFLAGS) $^ |
| @@ -1,6 +1,6 @@ | ||
| 1 | 1 | // SPDX-License-Identifier: GPL-2.0-only |
| 2 | 2 | #include <sys/mman.h> |
| 3 | −#include <testcases/mmap_test.h> | |
| 3 | +#include <mmap_test.h> | |
| 4 | 4 | |
| 5 | 5 | #include "../../kselftest_harness.h" |
| 6 | 6 | |
| @@ -1,6 +1,6 @@ | ||
| 1 | 1 | // SPDX-License-Identifier: GPL-2.0-only |
| 2 | 2 | #include <sys/mman.h> |
| 3 | −#include <testcases/mmap_test.h> | |
| 3 | +#include <mmap_test.h> | |
| 4 | 4 | |
| 5 | 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 | 159 | taa_data->thread_nmi_sum = 0; |
| 160 | 160 | taa_data->thread_irq_sum = 0; |
| 161 | 161 | taa_data->thread_softirq_sum = 0; |
| 162 | + taa_data->thread_thread_sum = 0; | |
| 162 | 163 | taa_data->thread_blocking_duration = 0; |
| 163 | 164 | taa_data->timer_irq_start_time = 0; |
| 164 | 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 | 338 | taa_data->timer_irq_start_time = start; |
| 338 | 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 | 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 | 545 | static void timerlat_thread_analysis(struct timerlat_aa_data *taa_data, int cpu, |
| 529 | 546 | int irq_thresh, int thread_thresh) |
| 530 | 547 | { |
| 531 | − unsigned long long exp_irq_ts; | |
| 548 | + long long exp_irq_ts; | |
| 532 | 549 | int total; |
| 533 | 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 | 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 | 568 | exp_irq_ts = taa_data->timer_irq_start_time - taa_data->timer_irq_start_delay; |
| 550 | − | |
| 551 | − if (exp_irq_ts < taa_data->prev_irq_timstamp + taa_data->prev_irq_duration) | |
| 552 | − printf(" Previous IRQ interference: \t\t up to %9.2f us\n", | |
| 553 | − ns_to_usf(taa_data->prev_irq_duration)); | |
| 569 | + 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) | |
| 571 | + printf(" Previous IRQ interference: \t\t up to %9.2f us\n", | |
| 572 | + ns_to_usf(taa_data->prev_irq_duration)); | |
| 573 | + } | |
| 554 | 574 | |
| 555 | 575 | /* |
| 556 | 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 | 46 | retval = sched_setaffinity(gettid(), sizeof(set), &set); |
| 47 | 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 | 49 | exit(1); |
| 50 | 50 | } |
| 51 | 51 | |
| @@ -193,7 +193,9 @@ void *timerlat_u_dispatcher(void *data) · 141 unmodified lines | ||
| 193 | 193 | procs_count--; |
| 194 | 194 | } |
| 195 | 195 | } |
| 196 | − break; | |
| 196 | + | |
| 197 | + if (!procs_count) | |
| 198 | + break; | |
| 197 | 199 | } |
| 198 | 200 | |
| 199 | 201 | sleep(1); |