b0dacee8 parents ee53543 de78657 8b9ad48 b11deb2 cae8d1f 0d647b3 42bb5aa fa7e9ec787 files · +9031 −4685Browse filesUnified · Split
| @@ -45,6 +45,7 @@ Andrey Konovalov <andreyknvl@gmail.com> <andreyknvl@google.com> · 44 unmodified lines | ||
| 45 | 45 | Andrey Ryabinin <ryabinin.a.a@gmail.com> <a.ryabinin@samsung.com> |
| 46 | 46 | Andrey Ryabinin <ryabinin.a.a@gmail.com> <aryabinin@virtuozzo.com> |
| 47 | 47 | Andrzej Hajda <andrzej.hajda@intel.com> <a.hajda@samsung.com> |
| 48 | +André Almeida <andrealmeid@igalia.com> <andrealmeid@collabora.com> | |
| 48 | 49 | Andy Adamson <andros@citi.umich.edu> |
| 49 | 50 | Antoine Tenart <atenart@kernel.org> <antoine.tenart@bootlin.com> |
| 50 | 51 | Antoine Tenart <atenart@kernel.org> <antoine.tenart@free-electrons.com> |
| @@ -204,6 +205,7 @@ Juha Yrjola <at solidboot.com> · 153 unmodified lines | ||
| 204 | 205 | Juha Yrjola <juha.yrjola@nokia.com> |
| 205 | 206 | Juha Yrjola <juha.yrjola@solidboot.com> |
| 206 | 207 | Julien Thierry <julien.thierry.kdev@gmail.com> <julien.thierry@arm.com> |
| 208 | +Kalle Valo <kvalo@kernel.org> <kvalo@codeaurora.org> | |
| 207 | 209 | Kalyan Thota <quic_kalyant@quicinc.com> <kalyan_t@codeaurora.org> |
| 208 | 210 | Kay Sievers <kay.sievers@vrfy.org> |
| 209 | 211 | Kees Cook <keescook@chromium.org> <kees.cook@canonical.com> |
| @@ -249,6 +251,7 @@ Mark Yao <markyao0591@gmail.com> <mark.yao@rock-chips.com> · 39 unmodified lines | ||
| 249 | 251 | Martin Kepplinger <martink@posteo.de> <martin.kepplinger@ginzinger.com> |
| 250 | 252 | Martin Kepplinger <martink@posteo.de> <martin.kepplinger@puri.sm> |
| 251 | 253 | Martin Kepplinger <martink@posteo.de> <martin.kepplinger@theobroma-systems.com> |
| 254 | +Martyna Szapar-Mudlaw <martyna.szapar-mudlaw@linux.intel.com> <martyna.szapar-mudlaw@intel.com> | |
| 252 | 255 | Mathieu Othacehe <m.othacehe@gmail.com> |
| 253 | 256 | Matthew Wilcox <willy@infradead.org> <matthew.r.wilcox@intel.com> |
| 254 | 257 | Matthew Wilcox <willy@infradead.org> <matthew@wil.cx> |
| @@ -228,10 +228,10 @@ Core dump support · 227 unmodified lines | ||
| 228 | 228 | ----------------- |
| 229 | 229 | |
| 230 | 230 | The allocation tags for user memory mapped with ``PROT_MTE`` are dumped |
| 231 | −in the core file as additional ``PT_ARM_MEMTAG_MTE`` segments. The | |
| 231 | +in the core file as additional ``PT_AARCH64_MEMTAG_MTE`` segments. The | |
| 232 | 232 | program header for such segment is defined as: |
| 233 | 233 | |
| 234 | −:``p_type``: ``PT_ARM_MEMTAG_MTE`` | |
| 234 | +:``p_type``: ``PT_AARCH64_MEMTAG_MTE`` | |
| 235 | 235 | :``p_flags``: 0 |
| 236 | 236 | :``p_offset``: segment file offset |
| 237 | 237 | :``p_vaddr``: segment virtual address, same as the corresponding |
| @@ -189,6 +189,9 @@ stable kernels. · 188 unmodified lines | ||
| 189 | 189 | +----------------+-----------------+-----------------+-----------------------------+ |
| 190 | 190 | | Qualcomm Tech. | Kryo4xx Silver | N/A | ARM64_ERRATUM_1024718 | |
| 191 | 191 | +----------------+-----------------+-----------------+-----------------------------+ |
| 192 | +| Qualcomm Tech. | Kryo4xx Gold | N/A | ARM64_ERRATUM_1286807 | | |
| 193 | ++----------------+-----------------+-----------------+-----------------------------+ | |
| 194 | + | |
| 192 | 195 | +----------------+-----------------+-----------------+-----------------------------+ |
| 193 | 196 | | Fujitsu | A64FX | E#010001 | FUJITSU_ERRATUM_010001 | |
| 194 | 197 | +----------------+-----------------+-----------------+-----------------------------+ |
| @@ -55,8 +55,6 @@ allOf: · 54 unmodified lines | ||
| 55 | 55 | then: |
| 56 | 56 | properties: |
| 57 | 57 | clocks: |
| 58 | − minItems: 7 | |
| 59 | − maxItems: 7 | |
| 60 | 58 | items: |
| 61 | 59 | - description: 32k osc |
| 62 | 60 | - description: 25m osc |
| @@ -66,8 +64,6 @@ allOf: · 3 unmodified lines | ||
| 66 | 64 | - description: ext3 clock input |
| 67 | 65 | - description: ext4 clock input |
| 68 | 66 | clock-names: |
| 69 | − minItems: 7 | |
| 70 | − maxItems: 7 | |
| 71 | 67 | items: |
| 72 | 68 | - const: ckil |
| 73 | 69 | - const: osc_25m |
| @@ -22,7 +22,16 @@ properties: · 21 unmodified lines | ||
| 22 | 22 | const: microchip,mpfs-clkcfg |
| 23 | 23 | |
| 24 | 24 | reg: |
| 25 | − maxItems: 1 | |
| 25 | + items: | |
| 26 | + - description: | | |
| 27 | + clock config registers: | |
| 28 | + These registers contain enable, reset & divider tables for the, cpu, | |
| 29 | + axi, ahb and rtc/mtimer reference clocks as well as enable and reset | |
| 30 | + for the peripheral clocks. | |
| 31 | + - description: | | |
| 32 | + mss pll dri registers: | |
| 33 | + Block of registers responsible for dynamic reconfiguration of the mss | |
| 34 | + pll | |
| 26 | 35 | |
| 27 | 36 | clocks: |
| 28 | 37 | maxItems: 1 |
| @@ -51,7 +60,7 @@ examples: · 22 unmodified lines | ||
| 51 | 60 | #size-cells = <2>; |
| 52 | 61 | clkcfg: clock-controller@20002000 { |
| 53 | 62 | compatible = "microchip,mpfs-clkcfg"; |
| 54 | − reg = <0x0 0x20002000 0x0 0x1000>; | |
| 63 | + reg = <0x0 0x20002000 0x0 0x1000>, <0x0 0x3E001000 0x0 0x1000>; | |
| 55 | 64 | clocks = <&ref>; |
| 56 | 65 | #clock-cells = <1>; |
| 57 | 66 | }; |
| @@ -95,7 +95,6 @@ then: · 94 unmodified lines | ||
| 95 | 95 | properties: |
| 96 | 96 | clocks: |
| 97 | 97 | minItems: 1 |
| 98 | − maxItems: 4 | |
| 99 | 98 | items: |
| 100 | 99 | - description: Functional clock |
| 101 | 100 | - description: EXTAL input clock |
| @@ -104,7 +103,6 @@ then: · 2 unmodified lines | ||
| 104 | 103 | |
| 105 | 104 | clock-names: |
| 106 | 105 | minItems: 1 |
| 107 | − maxItems: 4 | |
| 108 | 106 | items: |
| 109 | 107 | - const: fck |
| 110 | 108 | # The LVDS encoder can use the EXTAL or DU_DOTCLKINx clocks. |
| @@ -128,12 +126,10 @@ then: · 17 unmodified lines | ||
| 128 | 126 | else: |
| 129 | 127 | properties: |
| 130 | 128 | clocks: |
| 131 | − maxItems: 1 | |
| 132 | 129 | items: |
| 133 | 130 | - description: Functional clock |
| 134 | 131 | |
| 135 | 132 | clock-names: |
| 136 | − maxItems: 1 | |
| 137 | 133 | items: |
| 138 | 134 | - const: fck |
| 139 | 135 | |
| @@ -109,7 +109,6 @@ allOf: · 108 unmodified lines | ||
| 109 | 109 | properties: |
| 110 | 110 | clocks: |
| 111 | 111 | minItems: 1 |
| 112 | − maxItems: 3 | |
| 113 | 112 | items: |
| 114 | 113 | - description: Functional clock |
| 115 | 114 | - description: DU_DOTCLKIN0 input clock |
| @@ -117,7 +116,6 @@ allOf: · 1 unmodified line | ||
| 117 | 116 | |
| 118 | 117 | clock-names: |
| 119 | 118 | minItems: 1 |
| 120 | − maxItems: 3 | |
| 121 | 119 | items: |
| 122 | 120 | - const: du.0 |
| 123 | 121 | - pattern: '^dclkin\.[01]$' |
| @@ -159,7 +157,6 @@ allOf: · 35 unmodified lines | ||
| 159 | 157 | properties: |
| 160 | 158 | clocks: |
| 161 | 159 | minItems: 2 |
| 162 | − maxItems: 4 | |
| 163 | 160 | items: |
| 164 | 161 | - description: Functional clock for DU0 |
| 165 | 162 | - description: Functional clock for DU1 |
| @@ -168,7 +165,6 @@ allOf: · 2 unmodified lines | ||
| 168 | 165 | |
| 169 | 166 | clock-names: |
| 170 | 167 | minItems: 2 |
| 171 | − maxItems: 4 | |
| 172 | 168 | items: |
| 173 | 169 | - const: du.0 |
| 174 | 170 | - const: du.1 |
| @@ -216,7 +212,6 @@ allOf: · 41 unmodified lines | ||
| 216 | 212 | properties: |
| 217 | 213 | clocks: |
| 218 | 214 | minItems: 2 |
| 219 | − maxItems: 4 | |
| 220 | 215 | items: |
| 221 | 216 | - description: Functional clock for DU0 |
| 222 | 217 | - description: Functional clock for DU1 |
| @@ -225,7 +220,6 @@ allOf: · 2 unmodified lines | ||
| 225 | 220 | |
| 226 | 221 | clock-names: |
| 227 | 222 | minItems: 2 |
| 228 | − maxItems: 4 | |
| 229 | 223 | items: |
| 230 | 224 | - const: du.0 |
| 231 | 225 | - const: du.1 |
| @@ -271,7 +265,6 @@ allOf: · 39 unmodified lines | ||
| 271 | 265 | properties: |
| 272 | 266 | clocks: |
| 273 | 267 | minItems: 2 |
| 274 | − maxItems: 4 | |
| 275 | 268 | items: |
| 276 | 269 | - description: Functional clock for DU0 |
| 277 | 270 | - description: Functional clock for DU1 |
| @@ -280,7 +273,6 @@ allOf: · 2 unmodified lines | ||
| 280 | 273 | |
| 281 | 274 | clock-names: |
| 282 | 275 | minItems: 2 |
| 283 | − maxItems: 4 | |
| 284 | 276 | items: |
| 285 | 277 | - const: du.0 |
| 286 | 278 | - const: du.1 |
| @@ -327,7 +319,6 @@ allOf: · 40 unmodified lines | ||
| 327 | 319 | properties: |
| 328 | 320 | clocks: |
| 329 | 321 | minItems: 2 |
| 330 | − maxItems: 4 | |
| 331 | 322 | items: |
| 332 | 323 | - description: Functional clock for DU0 |
| 333 | 324 | - description: Functional clock for DU1 |
| @@ -336,7 +327,6 @@ allOf: · 2 unmodified lines | ||
| 336 | 327 | |
| 337 | 328 | clock-names: |
| 338 | 329 | minItems: 2 |
| 339 | − maxItems: 4 | |
| 340 | 330 | items: |
| 341 | 331 | - const: du.0 |
| 342 | 332 | - const: du.1 |
| @@ -386,7 +376,6 @@ allOf: · 43 unmodified lines | ||
| 386 | 376 | properties: |
| 387 | 377 | clocks: |
| 388 | 378 | minItems: 3 |
| 389 | − maxItems: 6 | |
| 390 | 379 | items: |
| 391 | 380 | - description: Functional clock for DU0 |
| 392 | 381 | - description: Functional clock for DU1 |
| @@ -397,7 +386,6 @@ allOf: · 4 unmodified lines | ||
| 397 | 386 | |
| 398 | 387 | clock-names: |
| 399 | 388 | minItems: 3 |
| 400 | − maxItems: 6 | |
| 401 | 389 | items: |
| 402 | 390 | - const: du.0 |
| 403 | 391 | - const: du.1 |
| @@ -448,7 +436,6 @@ allOf: · 44 unmodified lines | ||
| 448 | 436 | properties: |
| 449 | 437 | clocks: |
| 450 | 438 | minItems: 4 |
| 451 | − maxItems: 8 | |
| 452 | 439 | items: |
| 453 | 440 | - description: Functional clock for DU0 |
| 454 | 441 | - description: Functional clock for DU1 |
| @@ -461,7 +448,6 @@ allOf: · 6 unmodified lines | ||
| 461 | 448 | |
| 462 | 449 | clock-names: |
| 463 | 450 | minItems: 4 |
| 464 | − maxItems: 8 | |
| 465 | 451 | items: |
| 466 | 452 | - const: du.0 |
| 467 | 453 | - const: du.1 |
| @@ -525,7 +511,6 @@ allOf: · 57 unmodified lines | ||
| 525 | 511 | properties: |
| 526 | 512 | clocks: |
| 527 | 513 | minItems: 3 |
| 528 | − maxItems: 6 | |
| 529 | 514 | items: |
| 530 | 515 | - description: Functional clock for DU0 |
| 531 | 516 | - description: Functional clock for DU1 |
| @@ -536,7 +521,6 @@ allOf: · 4 unmodified lines | ||
| 536 | 521 | |
| 537 | 522 | clock-names: |
| 538 | 523 | minItems: 3 |
| 539 | − maxItems: 6 | |
| 540 | 524 | items: |
| 541 | 525 | - const: du.0 |
| 542 | 526 | - const: du.1 |
| @@ -596,7 +580,6 @@ allOf: · 53 unmodified lines | ||
| 596 | 580 | properties: |
| 597 | 581 | clocks: |
| 598 | 582 | minItems: 3 |
| 599 | − maxItems: 6 | |
| 600 | 583 | items: |
| 601 | 584 | - description: Functional clock for DU0 |
| 602 | 585 | - description: Functional clock for DU1 |
| @@ -607,7 +590,6 @@ allOf: · 4 unmodified lines | ||
| 607 | 590 | |
| 608 | 591 | clock-names: |
| 609 | 592 | minItems: 3 |
| 610 | − maxItems: 6 | |
| 611 | 593 | items: |
| 612 | 594 | - const: du.0 |
| 613 | 595 | - const: du.1 |
| @@ -666,14 +648,12 @@ allOf: · 52 unmodified lines | ||
| 666 | 648 | properties: |
| 667 | 649 | clocks: |
| 668 | 650 | minItems: 1 |
| 669 | − maxItems: 2 | |
| 670 | 651 | items: |
| 671 | 652 | - description: Functional clock for DU0 |
| 672 | 653 | - description: DU_DOTCLKIN0 input clock |
| 673 | 654 | |
| 674 | 655 | clock-names: |
| 675 | 656 | minItems: 1 |
| 676 | − maxItems: 2 | |
| 677 | 657 | items: |
| 678 | 658 | - const: du.0 |
| 679 | 659 | - const: dclkin.0 |
| @@ -723,7 +703,6 @@ allOf: · 43 unmodified lines | ||
| 723 | 703 | properties: |
| 724 | 704 | clocks: |
| 725 | 705 | minItems: 2 |
| 726 | − maxItems: 4 | |
| 727 | 706 | items: |
| 728 | 707 | - description: Functional clock for DU0 |
| 729 | 708 | - description: Functional clock for DU1 |
| @@ -732,7 +711,6 @@ allOf: · 2 unmodified lines | ||
| 732 | 711 | |
| 733 | 712 | clock-names: |
| 734 | 713 | minItems: 2 |
| 735 | − maxItems: 4 | |
| 736 | 714 | items: |
| 737 | 715 | - const: du.0 |
| 738 | 716 | - const: du.1 |
| @@ -791,7 +769,6 @@ allOf: · 52 unmodified lines | ||
| 791 | 769 | - description: Functional clock |
| 792 | 770 | |
| 793 | 771 | clock-names: |
| 794 | − maxItems: 1 | |
| 795 | 772 | items: |
| 796 | 773 | - const: du.0 |
| 797 | 774 | |
| @@ -58,10 +58,9 @@ patternProperties: · 57 unmodified lines | ||
| 58 | 58 | description: | |
| 59 | 59 | The value (two's complement) to be programmed in the channel specific N correction register. |
| 60 | 60 | For remote channels only. |
| 61 | − $ref: /schemas/types.yaml#/definitions/uint32 | |
| 62 | − items: | |
| 63 | − minimum: 0 | |
| 64 | − maximum: 255 | |
| 61 | + $ref: /schemas/types.yaml#/definitions/int32 | |
| 62 | + minimum: -128 | |
| 63 | + maximum: 127 | |
| 65 | 64 | |
| 66 | 65 | required: |
| 67 | 66 | - reg |
| @@ -138,7 +138,6 @@ allOf: · 137 unmodified lines | ||
| 138 | 138 | - const: bus |
| 139 | 139 | - const: adc |
| 140 | 140 | minItems: 1 |
| 141 | − maxItems: 2 | |
| 142 | 141 | |
| 143 | 142 | interrupts: |
| 144 | 143 | items: |
| @@ -170,7 +169,6 @@ allOf: · 25 unmodified lines | ||
| 170 | 169 | - const: bus |
| 171 | 170 | - const: adc |
| 172 | 171 | minItems: 1 |
| 173 | − maxItems: 2 | |
| 174 | 172 | |
| 175 | 173 | interrupts: |
| 176 | 174 | items: |
| @@ -37,8 +37,10 @@ properties: · 36 unmodified lines | ||
| 37 | 37 | - qcom,sc7180-smmu-500 |
| 38 | 38 | - qcom,sc7280-smmu-500 |
| 39 | 39 | - qcom,sc8180x-smmu-500 |
| 40 | + - qcom,sc8280xp-smmu-500 | |
| 40 | 41 | - qcom,sdm845-smmu-500 |
| 41 | 42 | - qcom,sdx55-smmu-500 |
| 43 | + - qcom,sdx65-smmu-500 | |
| 42 | 44 | - qcom,sm6350-smmu-500 |
| 43 | 45 | - qcom,sm8150-smmu-500 |
| 44 | 46 | - qcom,sm8250-smmu-500 |
| @@ -62,8 +64,9 @@ properties: · 17 unmodified lines | ||
| 62 | 64 | for improved performance. |
| 63 | 65 | items: |
| 64 | 66 | - enum: |
| 65 | − - nvidia,tegra194-smmu | |
| 66 | 67 | - nvidia,tegra186-smmu |
| 68 | + - nvidia,tegra194-smmu | |
| 69 | + - nvidia,tegra234-smmu | |
| 67 | 70 | - const: nvidia,smmu-500 |
| 68 | 71 | - items: |
| 69 | 72 | - const: arm,mmu-500 |
| @@ -157,6 +160,17 @@ properties: · 87 unmodified lines | ||
| 157 | 160 | power-domains: |
| 158 | 161 | maxItems: 1 |
| 159 | 162 | |
| 163 | + nvidia,memory-controller: | |
| 164 | + description: | | |
| 165 | + A phandle to the memory controller on NVIDIA Tegra186 and later SoCs. | |
| 166 | + The memory controller needs to be programmed with a mapping of memory | |
| 167 | + client IDs to ARM SMMU stream IDs. | |
| 168 | + | |
| 169 | + If this property is absent, the mapping programmed by early firmware | |
| 170 | + will be used and it is not guaranteed that IOMMU translations will be | |
| 171 | + enabled for any given device. | |
| 172 | + $ref: /schemas/types.yaml#/definitions/phandle | |
| 173 | + | |
| 160 | 174 | required: |
| 161 | 175 | - compatible |
| 162 | 176 | - reg |
| @@ -172,13 +186,20 @@ allOf: · 9 unmodified lines | ||
| 172 | 186 | compatible: |
| 173 | 187 | contains: |
| 174 | 188 | enum: |
| 175 | − - nvidia,tegra194-smmu | |
| 176 | 189 | - nvidia,tegra186-smmu |
| 190 | + - nvidia,tegra194-smmu | |
| 191 | + - nvidia,tegra234-smmu | |
| 177 | 192 | then: |
| 178 | 193 | properties: |
| 179 | 194 | reg: |
| 180 | 195 | minItems: 1 |
| 181 | 196 | maxItems: 2 |
| 197 | + | |
| 198 | + # The reference to the memory controller is required to ensure that the | |
| 199 | + # memory client to stream ID mapping can be done synchronously with the | |
| 200 | + # IOMMU attachment. | |
| 201 | + required: | |
| 202 | + - nvidia,memory-controller | |
| 182 | 203 | else: |
| 183 | 204 | properties: |
| 184 | 205 | reg: |
| @@ -76,7 +76,11 @@ properties: · 75 unmodified lines | ||
| 76 | 76 | - mediatek,mt8167-m4u # generation two |
| 77 | 77 | - mediatek,mt8173-m4u # generation two |
| 78 | 78 | - mediatek,mt8183-m4u # generation two |
| 79 | + - mediatek,mt8186-iommu-mm # generation two | |
| 79 | 80 | - mediatek,mt8192-m4u # generation two |
| 81 | + - mediatek,mt8195-iommu-vdo # generation two | |
| 82 | + - mediatek,mt8195-iommu-vpp # generation two | |
| 83 | + - mediatek,mt8195-iommu-infra # generation two | |
| 80 | 84 | |
| 81 | 85 | - description: mt7623 generation one |
| 82 | 86 | items: |
| @@ -119,7 +123,9 @@ properties: · 36 unmodified lines | ||
| 119 | 123 | dt-binding/memory/mt8167-larb-port.h for mt8167, |
| 120 | 124 | dt-binding/memory/mt8173-larb-port.h for mt8173, |
| 121 | 125 | dt-binding/memory/mt8183-larb-port.h for mt8183, |
| 126 | + dt-binding/memory/mt8186-memory-port.h for mt8186, | |
| 122 | 127 | dt-binding/memory/mt8192-larb-port.h for mt8192. |
| 128 | + dt-binding/memory/mt8195-memory-port.h for mt8195. | |
| 123 | 129 | |
| 124 | 130 | power-domains: |
| 125 | 131 | maxItems: 1 |
| @@ -128,7 +134,6 @@ required: · 2 unmodified lines | ||
| 128 | 134 | - compatible |
| 129 | 135 | - reg |
| 130 | 136 | - interrupts |
| 131 | − - mediatek,larbs | |
| 132 | 137 | - '#iommu-cells' |
| 133 | 138 | |
| 134 | 139 | allOf: |
| @@ -140,7 +145,10 @@ allOf: · 5 unmodified lines | ||
| 140 | 145 | - mediatek,mt2701-m4u |
| 141 | 146 | - mediatek,mt2712-m4u |
| 142 | 147 | - mediatek,mt8173-m4u |
| 148 | + - mediatek,mt8186-iommu-mm | |
| 143 | 149 | - mediatek,mt8192-m4u |
| 150 | + - mediatek,mt8195-iommu-vdo | |
| 151 | + - mediatek,mt8195-iommu-vpp | |
| 144 | 152 | |
| 145 | 153 | then: |
| 146 | 154 | required: |
| @@ -150,12 +158,26 @@ allOf: · 3 unmodified lines | ||
| 150 | 158 | properties: |
| 151 | 159 | compatible: |
| 152 | 160 | enum: |
| 161 | + - mediatek,mt8186-iommu-mm | |
| 153 | 162 | - mediatek,mt8192-m4u |
| 163 | + - mediatek,mt8195-iommu-vdo | |
| 164 | + - mediatek,mt8195-iommu-vpp | |
| 154 | 165 | |
| 155 | 166 | then: |
| 156 | 167 | required: |
| 157 | 168 | - power-domains |
| 158 | 169 | |
| 170 | + - if: # The IOMMUs don't have larbs. | |
| 171 | + not: | |
| 172 | + properties: | |
| 173 | + compatible: | |
| 174 | + contains: | |
| 175 | + const: mediatek,mt8195-iommu-infra | |
| 176 | + | |
| 177 | + then: | |
| 178 | + required: | |
| 179 | + - mediatek,larbs | |
| 180 | + | |
| 159 | 181 | additionalProperties: false |
| 160 | 182 | |
| 161 | 183 | examples: |
| @@ -173,13 +195,3 @@ examples: · 11 unmodified lines | ||
| 173 | 195 | <&larb3>, <&larb4>, <&larb5>; |
| 174 | 196 | #iommu-cells = <1>; |
| 175 | 197 | }; |
| 176 | − | |
| 177 | − - | | |
| 178 | − #include <dt-bindings/memory/mt8173-larb-port.h> | |
| 179 | − | |
| 180 | − /* Example for a client device */ | |
| 181 | − display { | |
| 182 | − compatible = "mediatek,mt8173-disp"; | |
| 183 | − iommus = <&iommu M4U_PORT_DISP_OVL0>, | |
| 184 | − <&iommu M4U_PORT_DISP_RDMA0>; | |
| 185 | − }; | |
| @@ -86,16 +86,6 @@ examples: · 85 unmodified lines | ||
| 86 | 86 | - | |
| 87 | 87 | #include <dt-bindings/clock/exynos5250.h> |
| 88 | 88 | |
| 89 | − gsc_0: scaler@13e00000 { | |
| 90 | − compatible = "samsung,exynos5-gsc"; | |
| 91 | − reg = <0x13e00000 0x1000>; | |
| 92 | − interrupts = <0 85 0>; | |
| 93 | − power-domains = <&pd_gsc>; | |
| 94 | − clocks = <&clock CLK_GSCL0>; | |
| 95 | − clock-names = "gscl"; | |
| 96 | − iommus = <&sysmmu_gsc0>; | |
| 97 | − }; | |
| 98 | − | |
| 99 | 89 | sysmmu_gsc0: iommu@13e80000 { |
| 100 | 90 | compatible = "samsung,exynos-sysmmu"; |
| 101 | 91 | reg = <0x13E80000 0x1000>; |
| @@ -43,8 +43,6 @@ patternProperties: · 42 unmodified lines | ||
| 43 | 43 | - 4 # LED output FLASH1 |
| 44 | 44 | - 5 # LED output FLASH2 |
| 45 | 45 | |
| 46 | −unevaluatedProperties: false | |
| 47 | − | |
| 48 | 46 | required: |
| 49 | 47 | - compatible |
| 50 | 48 | - "#address-cells" |
| @@ -54,7 +54,7 @@ flexcom@f8034000 { · 53 unmodified lines | ||
| 54 | 54 | clock-names = "spi_clk"; |
| 55 | 55 | atmel,fifo-size = <32>; |
| 56 | 56 | |
| 57 | − mtd_dataflash@0 { | |
| 57 | + flash@0 { | |
| 58 | 58 | compatible = "atmel,at25f512b"; |
| 59 | 59 | reg = <0>; |
| 60 | 60 | spi-max-frequency = <20000000>; |
| @@ -202,22 +202,17 @@ allOf: · 201 unmodified lines | ||
| 202 | 202 | clocks: |
| 203 | 203 | items: |
| 204 | 204 | - description: module clock |
| 205 | − minItems: 1 | |
| 206 | − maxItems: 1 | |
| 207 | 205 | else: |
| 208 | 206 | properties: |
| 209 | 207 | clocks: |
| 210 | 208 | items: |
| 211 | 209 | - description: module clock |
| 212 | 210 | - description: timeout clock |
| 213 | − minItems: 2 | |
| 214 | − maxItems: 2 | |
| 211 | + | |
| 215 | 212 | clock-names: |
| 216 | 213 | items: |
| 217 | 214 | - const: sdhci |
| 218 | 215 | - const: tmclk |
| 219 | − minItems: 2 | |
| 220 | − maxItems: 2 | |
| 221 | 216 | required: |
| 222 | 217 | - clock-names |
| 223 | 218 | |
| @@ -147,8 +147,6 @@ allOf: · 146 unmodified lines | ||
| 147 | 147 | - description: SoC gpmi io clock |
| 148 | 148 | - description: SoC gpmi bch apb clock |
| 149 | 149 | clock-names: |
| 150 | − minItems: 2 | |
| 151 | − maxItems: 2 | |
| 152 | 150 | items: |
| 153 | 151 | - const: gpmi_io |
| 154 | 152 | - const: gpmi_bch_apb |
| @@ -80,8 +80,6 @@ if: · 79 unmodified lines | ||
| 80 | 80 | then: |
| 81 | 81 | properties: |
| 82 | 82 | interrupts: |
| 83 | − minItems: 4 | |
| 84 | − maxItems: 4 | |
| 85 | 83 | items: |
| 86 | 84 | - description: Error and status IRQ |
| 87 | 85 | - description: Message object IRQ |
| @@ -91,7 +89,6 @@ then: · 3 unmodified lines | ||
| 91 | 89 | else: |
| 92 | 90 | properties: |
| 93 | 91 | interrupts: |
| 94 | − maxItems: 1 | |
| 95 | 92 | items: |
| 96 | 93 | - description: Error and status IRQ |
| 97 | 94 | |
| @@ -27,32 +27,25 @@ description: · 26 unmodified lines | ||
| 27 | 27 | The realtek-mdio driver is an MDIO driver and it must be inserted inside |
| 28 | 28 | an MDIO node. |
| 29 | 29 | |
| 30 | + The compatible string is only used to identify which (silicon) family the | |
| 31 | + switch belongs to. Roughly speaking, a family is any set of Realtek switches | |
| 32 | + whose chip identification register(s) have a common location and semantics. | |
| 33 | + The different models in a given family can be automatically disambiguated by | |
| 34 | + parsing the chip identification register(s) according to the given family, | |
| 35 | + avoiding the need for a unique compatible string for each model. | |
| 36 | + | |
| 30 | 37 | properties: |
| 31 | 38 | compatible: |
| 32 | 39 | enum: |
| 33 | 40 | - realtek,rtl8365mb |
| 34 | − - realtek,rtl8366 | |
| 35 | 41 | - realtek,rtl8366rb |
| 36 | − - realtek,rtl8366s | |
| 37 | − - realtek,rtl8367 | |
| 38 | − - realtek,rtl8367b | |
| 39 | − - realtek,rtl8367rb | |
| 40 | − - realtek,rtl8367s | |
| 41 | − - realtek,rtl8368s | |
| 42 | − - realtek,rtl8369 | |
| 43 | − - realtek,rtl8370 | |
| 44 | 42 | description: | |
| 45 | − realtek,rtl8365mb: 4+1 ports | |
| 46 | − realtek,rtl8366: 5+1 ports | |
| 47 | − realtek,rtl8366rb: 5+1 ports | |
| 48 | − realtek,rtl8366s: 5+1 ports | |
| 49 | − realtek,rtl8367: | |
| 50 | − realtek,rtl8367b: | |
| 51 | − realtek,rtl8367rb: 5+2 ports | |
| 52 | − realtek,rtl8367s: 5+2 ports | |
| 53 | − realtek,rtl8368s: 8 ports | |
| 54 | − realtek,rtl8369: 8+1 ports | |
| 55 | − realtek,rtl8370: 8+2 ports | |
| 43 | + realtek,rtl8365mb: | |
| 44 | + Use with models RTL8363NB, RTL8363NB-VB, RTL8363SC, RTL8363SC-VB, | |
| 45 | + RTL8364NB, RTL8364NB-VB, RTL8365MB, RTL8366SC, RTL8367RB-VB, RTL8367S, | |
| 46 | + RTL8367SB, RTL8370MB, RTL8310SR | |
| 47 | + realtek,rtl8366rb: | |
| 48 | + Use with models RTL8366RB, RTL8366S | |
| 56 | 49 | |
| 57 | 50 | mdc-gpios: |
| 58 | 51 | description: GPIO line for the MDC clock line. |
| @@ -335,7 +328,7 @@ examples: · 276 unmodified lines | ||
| 335 | 328 | #size-cells = <0>; |
| 336 | 329 | |
| 337 | 330 | switch@29 { |
| 338 | − compatible = "realtek,rtl8367s"; | |
| 331 | + compatible = "realtek,rtl8365mb"; | |
| 339 | 332 | reg = <29>; |
| 340 | 333 | |
| 341 | 334 | reset-gpios = <&gpio2 20 GPIO_ACTIVE_LOW>; |
| @@ -142,7 +142,6 @@ examples: · 141 unmodified lines | ||
| 142 | 142 | device_type = "pci"; |
| 143 | 143 | reg = <0x0 0x0 0x0 0x0 0x0>; |
| 144 | 144 | reset-gpios = <&pinctrl_ap 152 0>; |
| 145 | − max-link-speed = <2>; | |
| 146 | 145 | |
| 147 | 146 | #address-cells = <3>; |
| 148 | 147 | #size-cells = <2>; |
| @@ -153,7 +152,6 @@ examples: · 4 unmodified lines | ||
| 153 | 152 | device_type = "pci"; |
| 154 | 153 | reg = <0x800 0x0 0x0 0x0 0x0>; |
| 155 | 154 | reset-gpios = <&pinctrl_ap 153 0>; |
| 156 | − max-link-speed = <2>; | |
| 157 | 155 | |
| 158 | 156 | #address-cells = <3>; |
| 159 | 157 | #size-cells = <2>; |
| @@ -164,7 +162,6 @@ examples: · 4 unmodified lines | ||
| 164 | 162 | device_type = "pci"; |
| 165 | 163 | reg = <0x1000 0x0 0x0 0x0 0x0>; |
| 166 | 164 | reset-gpios = <&pinctrl_ap 33 0>; |
| 167 | − max-link-speed = <1>; | |
| 168 | 165 | |
| 169 | 166 | #address-cells = <3>; |
| 170 | 167 | #size-cells = <2>; |
| @@ -102,19 +102,17 @@ if: · 101 unmodified lines | ||
| 102 | 102 | then: |
| 103 | 103 | properties: |
| 104 | 104 | reg: |
| 105 | − maxItems: 2 | |
| 105 | + minItems: 2 | |
| 106 | + | |
| 106 | 107 | reg-names: |
| 107 | − items: | |
| 108 | − - const: "phy" | |
| 109 | − - const: "phy-ctrl" | |
| 108 | + minItems: 2 | |
| 110 | 109 | else: |
| 111 | 110 | properties: |
| 112 | 111 | reg: |
| 113 | 112 | maxItems: 1 |
| 113 | + | |
| 114 | 114 | reg-names: |
| 115 | 115 | maxItems: 1 |
| 116 | − items: | |
| 117 | − - const: "phy" | |
| 118 | 116 | |
| 119 | 117 | required: |
| 120 | 118 | - compatible |
| @@ -52,11 +52,19 @@ properties: · 51 unmodified lines | ||
| 52 | 52 | hardware supporting it the pull strength in Ohm. |
| 53 | 53 | |
| 54 | 54 | drive-push-pull: |
| 55 | − type: boolean | |
| 55 | + oneOf: | |
| 56 | + - type: boolean | |
| 57 | + - $ref: /schemas/types.yaml#/definitions/uint32 | |
| 58 | + enum: [ 0, 1 ] | |
| 59 | + deprecated: true | |
| 56 | 60 | description: drive actively high and low |
| 57 | 61 | |
| 58 | 62 | drive-open-drain: |
| 59 | − type: boolean | |
| 63 | + oneOf: | |
| 64 | + - type: boolean | |
| 65 | + - $ref: /schemas/types.yaml#/definitions/uint32 | |
| 66 | + const: 1 # No known cases of 0 | |
| 67 | + deprecated: true | |
| 60 | 68 | description: drive with open drain |
| 61 | 69 | |
| 62 | 70 | drive-open-source: |
| @@ -58,7 +58,7 @@ properties: · 57 unmodified lines | ||
| 58 | 58 | type: object |
| 59 | 59 | $ref: regulator.yaml# |
| 60 | 60 | description: | |
| 61 | − regulator description for buck1 and buck4. | |
| 61 | + regulator description for buck1 to buck4, and ldo. | |
| 62 | 62 | |
| 63 | 63 | properties: |
| 64 | 64 | regulator-allowed-modes: |
| @@ -71,7 +71,6 @@ allOf: · 70 unmodified lines | ||
| 71 | 71 | then: |
| 72 | 72 | properties: |
| 73 | 73 | clock-output-names: |
| 74 | − minItems: 1 | |
| 75 | 74 | maxItems: 1 |
| 76 | 75 | |
| 77 | 76 | - if: |
| @@ -102,7 +101,6 @@ allOf: · 24 unmodified lines | ||
| 102 | 101 | properties: |
| 103 | 102 | clock-output-names: |
| 104 | 103 | minItems: 3 |
| 105 | − maxItems: 3 | |
| 106 | 104 | |
| 107 | 105 | - if: |
| 108 | 106 | properties: |
| @@ -113,16 +111,12 @@ allOf: · 4 unmodified lines | ||
| 113 | 111 | then: |
| 114 | 112 | properties: |
| 115 | 113 | clocks: |
| 116 | − minItems: 3 | |
| 117 | − maxItems: 3 | |
| 118 | 114 | items: |
| 119 | 115 | - description: Bus clock for register access |
| 120 | 116 | - description: 24 MHz oscillator |
| 121 | 117 | - description: 32 kHz clock from the CCU |
| 122 | 118 | |
| 123 | 119 | clock-names: |
| 124 | − minItems: 3 | |
| 125 | − maxItems: 3 | |
| 126 | 120 | items: |
| 127 | 121 | - const: bus |
| 128 | 122 | - const: hosc |
| @@ -142,7 +136,6 @@ allOf: · 13 unmodified lines | ||
| 142 | 136 | properties: |
| 143 | 137 | clocks: |
| 144 | 138 | minItems: 3 |
| 145 | − maxItems: 4 | |
| 146 | 139 | items: |
| 147 | 140 | - description: Bus clock for register access |
| 148 | 141 | - description: 24 MHz oscillator |
| @@ -151,7 +144,6 @@ allOf: · 2 unmodified lines | ||
| 151 | 144 | |
| 152 | 145 | clock-names: |
| 153 | 146 | minItems: 3 |
| 154 | − maxItems: 4 | |
| 155 | 147 | items: |
| 156 | 148 | - const: bus |
| 157 | 149 | - const: hosc |
| @@ -174,14 +166,12 @@ allOf: · 16 unmodified lines | ||
| 174 | 166 | then: |
| 175 | 167 | properties: |
| 176 | 168 | interrupts: |
| 177 | − minItems: 1 | |
| 178 | 169 | maxItems: 1 |
| 179 | 170 | |
| 180 | 171 | else: |
| 181 | 172 | properties: |
| 182 | 173 | interrupts: |
| 183 | 174 | minItems: 2 |
| 184 | − maxItems: 2 | |
| 185 | 175 | |
| 186 | 176 | required: |
| 187 | 177 | - "#clock-cells" |
| @@ -31,11 +31,19 @@ properties: · 30 unmodified lines | ||
| 31 | 31 | to that of the RTC's count register. |
| 32 | 32 | |
| 33 | 33 | clocks: |
| 34 | − maxItems: 1 | |
| 34 | + items: | |
| 35 | + - description: | | |
| 36 | + AHB clock | |
| 37 | + - description: | | |
| 38 | + Reference clock: divided by the prescaler to create a time-based | |
| 39 | + strobe (typically 1 Hz) for the calendar counter. By default, the rtc | |
| 40 | + on the PolarFire SoC shares it's reference with MTIMER so this will | |
| 41 | + be a 1 MHz clock. | |
| 35 | 42 | |
| 36 | 43 | clock-names: |
| 37 | 44 | items: |
| 38 | 45 | - const: rtc |
| 46 | + - const: rtcref | |
| 39 | 47 | |
| 40 | 48 | required: |
| 41 | 49 | - compatible |
| @@ -48,11 +56,12 @@ additionalProperties: false · 6 unmodified lines | ||
| 48 | 56 | |
| 49 | 57 | examples: |
| 50 | 58 | - | |
| 59 | + #include "dt-bindings/clock/microchip,mpfs-clock.h" | |
| 51 | 60 | rtc@20124000 { |
| 52 | 61 | compatible = "microchip,mpfs-rtc"; |
| 53 | 62 | reg = <0x20124000 0x1000>; |
| 54 | − clocks = <&clkcfg 21>; | |
| 55 | − clock-names = "rtc"; | |
| 63 | + clocks = <&clkcfg CLK_RTC>, <&clkcfg CLK_RTCREF>; | |
| 64 | + clock-names = "rtc", "rtcref"; | |
| 56 | 65 | interrupts = <80>, <81>; |
| 57 | 66 | }; |
| 58 | 67 | ... |
| @@ -100,7 +100,6 @@ allOf: · 99 unmodified lines | ||
| 100 | 100 | maxItems: 3 |
| 101 | 101 | clock-names: |
| 102 | 102 | minItems: 2 |
| 103 | − maxItems: 3 | |
| 104 | 103 | items: |
| 105 | 104 | - const: uart |
| 106 | 105 | - pattern: '^clk_uart_baud[0-1]$' |
| @@ -118,11 +117,8 @@ allOf: · 11 unmodified lines | ||
| 118 | 117 | then: |
| 119 | 118 | properties: |
| 120 | 119 | clocks: |
| 121 | − minItems: 2 | |
| 122 | 120 | maxItems: 2 |
| 123 | 121 | clock-names: |
| 124 | − minItems: 2 | |
| 125 | − maxItems: 2 | |
| 126 | 122 | items: |
| 127 | 123 | - const: uart |
| 128 | 124 | - const: clk_uart_baud0 |
| @@ -89,7 +89,6 @@ allOf: · 88 unmodified lines | ||
| 89 | 89 | properties: |
| 90 | 90 | dmas: |
| 91 | 91 | minItems: 1 |
| 92 | − maxItems: 2 | |
| 93 | 92 | items: |
| 94 | 93 | - description: RX DMA Channel |
| 95 | 94 | - description: TX DMA Channel |
| @@ -80,7 +80,6 @@ allOf: · 79 unmodified lines | ||
| 80 | 80 | then: |
| 81 | 81 | properties: |
| 82 | 82 | clocks: |
| 83 | − minItems: 6 | |
| 84 | 83 | items: |
| 85 | 84 | - description: AUXCLK clock for McASP used by CPB audio |
| 86 | 85 | - description: Parent for CPB_McASP auxclk (for 48KHz) |
| @@ -107,7 +106,6 @@ allOf: · 20 unmodified lines | ||
| 107 | 106 | then: |
| 108 | 107 | properties: |
| 109 | 108 | clocks: |
| 110 | − maxItems: 4 | |
| 111 | 109 | items: |
| 112 | 110 | - description: AUXCLK clock for McASP used by CPB audio |
| 113 | 111 | - description: Parent for CPB_McASP auxclk (for 48KHz) |
| @@ -67,7 +67,6 @@ then: · 66 unmodified lines | ||
| 67 | 67 | properties: |
| 68 | 68 | reg: |
| 69 | 69 | minItems: 2 |
| 70 | − maxItems: 3 | |
| 71 | 70 | items: |
| 72 | 71 | - description: TSC1 registers |
| 73 | 72 | - description: TSC2 registers |
| @@ -43,6 +43,9 @@ properties: · 42 unmodified lines | ||
| 43 | 43 | - const: phy_clk |
| 44 | 44 | - const: ref_clk |
| 45 | 45 | |
| 46 | + power-domains: | |
| 47 | + maxItems: 1 | |
| 48 | + | |
| 46 | 49 | reg: |
| 47 | 50 | maxItems: 1 |
| 48 | 51 | |
| @@ -62,6 +62,7 @@ required: · 61 unmodified lines | ||
| 62 | 62 | - interrupts |
| 63 | 63 | - phys |
| 64 | 64 | - phy-names |
| 65 | + - reg | |
| 65 | 66 | |
| 66 | 67 | allOf: |
| 67 | 68 | - if: |
| @@ -235,12 +235,6 @@ offgrpjquota Turn off group journalled quota. · 234 unmodified lines | ||
| 235 | 235 | offprjjquota Turn off project journalled quota. |
| 236 | 236 | quota Enable plain user disk quota accounting. |
| 237 | 237 | noquota Disable all plain disk quota option. |
| 238 | −whint_mode=%s Control which write hints are passed down to block | |
| 239 | − layer. This supports "off", "user-based", and | |
| 240 | − "fs-based". In "off" mode (default), f2fs does not pass | |
| 241 | − down hints. In "user-based" mode, f2fs tries to pass | |
| 242 | − down hints given by users. And in "fs-based" mode, f2fs | |
| 243 | − passes down hints with its policy. | |
| 244 | 238 | alloc_mode=%s Adjust block allocation policy, which supports "reuse" |
| 245 | 239 | and "default". |
| 246 | 240 | fsync_mode=%s Control the policy of fsync. Currently supports "posix", |
| @@ -751,70 +745,6 @@ In order to identify whether the data in the victim segment are valid or not, · 504 unmodified lines | ||
| 751 | 745 | F2FS manages a bitmap. Each bit represents the validity of a block, and the |
| 752 | 746 | bitmap is composed of a bit stream covering whole blocks in main area. |
| 753 | 747 | |
| 754 | −Write-hint Policy | |
| 755 | −----------------- | |
| 756 | − | |
| 757 | −1) whint_mode=off. F2FS only passes down WRITE_LIFE_NOT_SET. | |
| 758 | − | |
| 759 | −2) whint_mode=user-based. F2FS tries to pass down hints given by | |
| 760 | −users. | |
| 761 | − | |
| 762 | −===================== ======================== =================== | |
| 763 | −User F2FS Block | |
| 764 | −===================== ======================== =================== | |
| 765 | −N/A META WRITE_LIFE_NOT_SET | |
| 766 | −N/A HOT_NODE " | |
| 767 | −N/A WARM_NODE " | |
| 768 | −N/A COLD_NODE " | |
| 769 | −ioctl(COLD) COLD_DATA WRITE_LIFE_EXTREME | |
| 770 | −extension list " " | |
| 771 | − | |
| 772 | −-- buffered io | |
| 773 | −WRITE_LIFE_EXTREME COLD_DATA WRITE_LIFE_EXTREME | |
| 774 | −WRITE_LIFE_SHORT HOT_DATA WRITE_LIFE_SHORT | |
| 775 | −WRITE_LIFE_NOT_SET WARM_DATA WRITE_LIFE_NOT_SET | |
| 776 | −WRITE_LIFE_NONE " " | |
| 777 | −WRITE_LIFE_MEDIUM " " | |
| 778 | −WRITE_LIFE_LONG " " | |
| 779 | − | |
| 780 | −-- direct io | |
| 781 | −WRITE_LIFE_EXTREME COLD_DATA WRITE_LIFE_EXTREME | |
| 782 | −WRITE_LIFE_SHORT HOT_DATA WRITE_LIFE_SHORT | |
| 783 | −WRITE_LIFE_NOT_SET WARM_DATA WRITE_LIFE_NOT_SET | |
| 784 | −WRITE_LIFE_NONE " WRITE_LIFE_NONE | |
| 785 | −WRITE_LIFE_MEDIUM " WRITE_LIFE_MEDIUM | |
| 786 | −WRITE_LIFE_LONG " WRITE_LIFE_LONG | |
| 787 | −===================== ======================== =================== | |
| 788 | − | |
| 789 | −3) whint_mode=fs-based. F2FS passes down hints with its policy. | |
| 790 | − | |
| 791 | −===================== ======================== =================== | |
| 792 | −User F2FS Block | |
| 793 | −===================== ======================== =================== | |
| 794 | −N/A META WRITE_LIFE_MEDIUM; | |
| 795 | −N/A HOT_NODE WRITE_LIFE_NOT_SET | |
| 796 | −N/A WARM_NODE " | |
| 797 | −N/A COLD_NODE WRITE_LIFE_NONE | |
| 798 | −ioctl(COLD) COLD_DATA WRITE_LIFE_EXTREME | |
| 799 | −extension list " " | |
| 800 | − | |
| 801 | −-- buffered io | |
| 802 | −WRITE_LIFE_EXTREME COLD_DATA WRITE_LIFE_EXTREME | |
| 803 | −WRITE_LIFE_SHORT HOT_DATA WRITE_LIFE_SHORT | |
| 804 | −WRITE_LIFE_NOT_SET WARM_DATA WRITE_LIFE_LONG | |
| 805 | −WRITE_LIFE_NONE " " | |
| 806 | −WRITE_LIFE_MEDIUM " " | |
| 807 | −WRITE_LIFE_LONG " " | |
| 808 | − | |
| 809 | −-- direct io | |
| 810 | −WRITE_LIFE_EXTREME COLD_DATA WRITE_LIFE_EXTREME | |
| 811 | −WRITE_LIFE_SHORT HOT_DATA WRITE_LIFE_SHORT | |
| 812 | −WRITE_LIFE_NOT_SET WARM_DATA WRITE_LIFE_NOT_SET | |
| 813 | −WRITE_LIFE_NONE " WRITE_LIFE_NONE | |
| 814 | −WRITE_LIFE_MEDIUM " WRITE_LIFE_MEDIUM | |
| 815 | −WRITE_LIFE_LONG " WRITE_LIFE_LONG | |
| 816 | −===================== ======================== =================== | |
| 817 | − | |
| 818 | 748 | Fallocate(2) Policy |
| 819 | 749 | ------------------- |
| 820 | 750 | |
| @@ -244,10 +244,11 @@ disclosure of a particular issue, unless requested by a response team or by · 243 unmodified lines | ||
| 244 | 244 | an involved disclosed party. The current ambassadors list: |
| 245 | 245 | |
| 246 | 246 | ============= ======================================================== |
| 247 | − ARM Grant Likely <grant.likely@arm.com> | |
| 248 | 247 | AMD Tom Lendacky <tom.lendacky@amd.com> |
| 249 | − IBM Z Christian Borntraeger <borntraeger@de.ibm.com> | |
| 250 | − IBM Power Anton Blanchard <anton@linux.ibm.com> | |
| 248 | + Ampere Darren Hart <darren@os.amperecomputing.com> | |
| 249 | + ARM Catalin Marinas <catalin.marinas@arm.com> | |
| 250 | + IBM Power Anton Blanchard <anton@linux.ibm.com> | |
| 251 | + IBM Z Christian Borntraeger <borntraeger@de.ibm.com> | |
| 251 | 252 | Intel Tony Luck <tony.luck@intel.com> |
| 252 | 253 | Qualcomm Trilok Soni <tsoni@codeaurora.org> |
| 253 | 254 | |
| @@ -121,26 +121,36 @@ even scarier, uses an easily brute-forcable 64-bit key (with a 32-bit output) · 120 unmodified lines | ||
| 121 | 121 | instead of SipHash's 128-bit key. However, this may appeal to some |
| 122 | 122 | high-performance `jhash` users. |
| 123 | 123 | |
| 124 | −Danger! | |
| 125 | − | |
| 126 | −Do not ever use HalfSipHash except for as a hashtable key function, and only | |
| 127 | −then when you can be absolutely certain that the outputs will never be | |
| 128 | −transmitted out of the kernel. This is only remotely useful over `jhash` as a | |
| 129 | −means of mitigating hashtable flooding denial of service attacks. | |
| 130 | − | |
| 131 | −Generating a HalfSipHash key | |
| 132 | −============================ | |
| 124 | +HalfSipHash support is provided through the "hsiphash" family of functions. | |
| 125 | + | |
| 126 | +.. warning:: | |
| 127 | + Do not ever use the hsiphash functions except for as a hashtable key | |
| 128 | + function, and only then when you can be absolutely certain that the outputs | |
| 129 | + will never be transmitted out of the kernel. This is only remotely useful | |
| 130 | + over `jhash` as a means of mitigating hashtable flooding denial of service | |
| 131 | + attacks. | |
| 132 | + | |
| 133 | +On 64-bit kernels, the hsiphash functions actually implement SipHash-1-3, a | |
| 134 | +reduced-round variant of SipHash, instead of HalfSipHash-1-3. This is because in | |
| 135 | +64-bit code, SipHash-1-3 is no slower than HalfSipHash-1-3, and can be faster. | |
| 136 | +Note, this does *not* mean that in 64-bit kernels the hsiphash functions are the | |
| 137 | +same as the siphash ones, or that they are secure; the hsiphash functions still | |
| 138 | +use a less secure reduced-round algorithm and truncate their outputs to 32 | |
| 139 | +bits. | |
| 140 | + | |
| 141 | +Generating a hsiphash key | |
| 142 | +========================= | |
| 133 | 143 | |
| 134 | 144 | Keys should always be generated from a cryptographically secure source of |
| 135 | −random numbers, either using get_random_bytes or get_random_once: | |
| 145 | +random numbers, either using get_random_bytes or get_random_once:: | |
| 136 | 146 | |
| 137 | −hsiphash_key_t key; | |
| 138 | −get_random_bytes(&key, sizeof(key)); | |
| 147 | + hsiphash_key_t key; | |
| 148 | + get_random_bytes(&key, sizeof(key)); | |
| 139 | 149 | |
| 140 | 150 | If you're not deriving your key from here, you're doing it wrong. |
| 141 | 151 | |
| 142 | −Using the HalfSipHash functions | |
| 143 | −=============================== | |
| 152 | +Using the hsiphash functions | |
| 153 | +============================ | |
| 144 | 154 | |
| 145 | 155 | There are two variants of the function, one that takes a list of integers, and |
| 146 | 156 | one that takes a buffer:: |
| @@ -183,7 +193,7 @@ You may then iterate like usual over the returned hash bucket. · 36 unmodified lines | ||
| 183 | 193 | Performance |
| 184 | 194 | =========== |
| 185 | 195 | |
| 186 | −HalfSipHash is roughly 3 times slower than JenkinsHash. For many replacements, | |
| 187 | −this will not be a problem, as the hashtable lookup isn't the bottleneck. And | |
| 188 | −in general, this is probably a good sacrifice to make for the security and DoS | |
| 189 | −resistance of HalfSipHash. | |
| 196 | +hsiphash() is roughly 3 times slower than jhash(). For many replacements, this | |
| 197 | +will not be a problem, as the hashtable lookup isn't the bottleneck. And in | |
| 198 | +general, this is probably a good sacrifice to make for the security and DoS | |
| 199 | +resistance of hsiphash(). | |
| @@ -5986,16 +5986,16 @@ should put the acknowledged interrupt vector into the 'epr' field. · 5985 unmodified lines | ||
| 5986 | 5986 | #define KVM_SYSTEM_EVENT_RESET 2 |
| 5987 | 5987 | #define KVM_SYSTEM_EVENT_CRASH 3 |
| 5988 | 5988 | __u32 type; |
| 5989 | − __u64 flags; | |
| 5989 | + __u32 ndata; | |
| 5990 | + __u64 data[16]; | |
| 5990 | 5991 | } system_event; |
| 5991 | 5992 | |
| 5992 | 5993 | If exit_reason is KVM_EXIT_SYSTEM_EVENT then the vcpu has triggered |
| 5993 | 5994 | a system-level event using some architecture specific mechanism (hypercall |
| 5994 | 5995 | or some special instruction). In case of ARM64, this is triggered using |
| 5995 | −HVC instruction based PSCI call from the vcpu. The 'type' field describes | |
| 5996 | −the system-level event type. The 'flags' field describes architecture | |
| 5997 | −specific flags for the system-level event. | |
| 5996 | +HVC instruction based PSCI call from the vcpu. | |
| 5998 | 5997 | |
| 5998 | +The 'type' field describes the system-level event type. | |
| 5999 | 5999 | Valid values for 'type' are: |
| 6000 | 6000 | |
| 6001 | 6001 | - KVM_SYSTEM_EVENT_SHUTDOWN -- the guest has requested a shutdown of the |
| @@ -6010,10 +6010,20 @@ Valid values for 'type' are: · 8 unmodified lines | ||
| 6010 | 6010 | to ignore the request, or to gather VM memory core dump and/or |
| 6011 | 6011 | reset/shutdown of the VM. |
| 6012 | 6012 | |
| 6013 | −Valid flags are: | |
| 6013 | +If KVM_CAP_SYSTEM_EVENT_DATA is present, the 'data' field can contain | |
| 6014 | +architecture specific information for the system-level event. Only | |
| 6015 | +the first `ndata` items (possibly zero) of the data array are valid. | |
| 6014 | 6016 | |
| 6015 | − - KVM_SYSTEM_EVENT_RESET_FLAG_PSCI_RESET2 (arm64 only) -- the guest issued | |
| 6016 | − a SYSTEM_RESET2 call according to v1.1 of the PSCI specification. | |
| 6017 | + - for arm64, data[0] is set to KVM_SYSTEM_EVENT_RESET_FLAG_PSCI_RESET2 if | |
| 6018 | + the guest issued a SYSTEM_RESET2 call according to v1.1 of the PSCI | |
| 6019 | + specification. | |
| 6020 | + | |
| 6021 | + - for RISC-V, data[0] is set to the value of the second argument of the | |
| 6022 | + ``sbi_system_reset`` call. | |
| 6023 | + | |
| 6024 | +Previous versions of Linux defined a `flags` member in this struct. The | |
| 6025 | +field is now aliased to `data[0]`. Userspace can assume that it is only | |
| 6026 | +written if ndata is greater than 0. | |
| 6017 | 6027 | |
| 6018 | 6028 | :: |
| 6019 | 6029 | |
| @@ -110,7 +110,7 @@ Usage · 109 unmodified lines | ||
| 110 | 110 | If you want to sort by the page nums of buf, use the ``-m`` parameter. |
| 111 | 111 | The detailed parameters are: |
| 112 | 112 | |
| 113 | − fundamental function: | |
| 113 | + fundamental function:: | |
| 114 | 114 | |
| 115 | 115 | Sort: |
| 116 | 116 | -a Sort by memory allocation time. |
| @@ -122,7 +122,7 @@ Usage · 5 unmodified lines | ||
| 122 | 122 | -s Sort by stack trace. |
| 123 | 123 | -t Sort by times (default). |
| 124 | 124 | |
| 125 | − additional function: | |
| 125 | + additional function:: | |
| 126 | 126 | |
| 127 | 127 | Cull: |
| 128 | 128 | --cull <rules> |
| @@ -153,6 +153,7 @@ Usage · 24 unmodified lines | ||
| 153 | 153 | |
| 154 | 154 | STANDARD FORMAT SPECIFIERS |
| 155 | 155 | ========================== |
| 156 | +:: | |
| 156 | 157 | |
| 157 | 158 | KEY LONG DESCRIPTION |
| 158 | 159 | p pid process ID |
| @@ -2638,6 +2638,7 @@ L: linux-samsung-soc@vger.kernel.org · 2637 unmodified lines | ||
| 2638 | 2638 | S: Maintained |
| 2639 | 2639 | C: irc://irc.libera.chat/linux-exynos |
| 2640 | 2640 | Q: https://patchwork.kernel.org/project/linux-samsung-soc/list/ |
| 2641 | +B: mailto:linux-samsung-soc@vger.kernel.org | |
| 2641 | 2642 | T: git git://git.kernel.org/pub/scm/linux/kernel/git/krzk/linux.git |
| 2642 | 2643 | F: Documentation/arm/samsung/ |
| 2643 | 2644 | F: Documentation/devicetree/bindings/arm/samsung/ |
| @@ -3564,8 +3565,9 @@ M: Andy Gospodarek <andy@greyhouse.net> · 920 unmodified lines | ||
| 3564 | 3565 | L: netdev@vger.kernel.org |
| 3565 | 3566 | S: Supported |
| 3566 | 3567 | W: http://sourceforge.net/projects/bonding/ |
| 3568 | +F: Documentation/networking/bonding.rst | |
| 3567 | 3569 | F: drivers/net/bonding/ |
| 3568 | −F: include/net/bonding.h | |
| 3570 | +F: include/net/bond* | |
| 3569 | 3571 | F: include/uapi/linux/if_bonding.h |
| 3570 | 3572 | |
| 3571 | 3573 | BOSCH SENSORTEC BMA400 ACCELEROMETER IIO DRIVER |
| @@ -3907,7 +3909,9 @@ BROADCOM BNXT_EN 50 GIGABIT ETHERNET DRIVER · 335 unmodified lines | ||
| 3907 | 3909 | M: Michael Chan <michael.chan@broadcom.com> |
| 3908 | 3910 | L: netdev@vger.kernel.org |
| 3909 | 3911 | S: Supported |
| 3912 | +F: drivers/firmware/broadcom/tee_bnxt_fw.c | |
| 3910 | 3913 | F: drivers/net/ethernet/broadcom/bnxt/ |
| 3914 | +F: include/linux/firmware/broadcom/tee_bnxt_fw.h | |
| 3911 | 3915 | |
| 3912 | 3916 | BROADCOM BRCM80211 IEEE802.11n WIRELESS DRIVER |
| 3913 | 3917 | M: Arend van Spriel <aspriel@gmail.com> |
| @@ -5430,6 +5434,7 @@ F: net/ax25/sysctl_net_ax25.c · 1516 unmodified lines | ||
| 5430 | 5434 | |
| 5431 | 5435 | DATA ACCESS MONITOR |
| 5432 | 5436 | M: SeongJae Park <sj@kernel.org> |
| 5437 | +L: damon@lists.linux.dev | |
| 5433 | 5438 | L: linux-mm@kvack.org |
| 5434 | 5439 | S: Maintained |
| 5435 | 5440 | F: Documentation/ABI/testing/sysfs-kernel-mm-damon |
| @@ -5908,7 +5913,7 @@ R: Benjamin Gaignard <benjamin.gaignard@collabora.com> · 472 unmodified lines | ||
| 5908 | 5913 | R: Liam Mark <lmark@codeaurora.org> |
| 5909 | 5914 | R: Laura Abbott <labbott@redhat.com> |
| 5910 | 5915 | R: Brian Starkey <Brian.Starkey@arm.com> |
| 5911 | −R: John Stultz <john.stultz@linaro.org> | |
| 5916 | +R: John Stultz <jstultz@google.com> | |
| 5912 | 5917 | L: linux-media@vger.kernel.org |
| 5913 | 5918 | L: dri-devel@lists.freedesktop.org |
| 5914 | 5919 | L: linaro-mm-sig@lists.linaro.org (moderated for non-subscribers) |
| @@ -6578,7 +6583,7 @@ F: drivers/gpu/drm/gma500/ · 663 unmodified lines | ||
| 6578 | 6583 | DRM DRIVERS FOR HISILICON |
| 6579 | 6584 | M: Xinliang Liu <xinliang.liu@linaro.org> |
| 6580 | 6585 | M: Tian Tao <tiantao6@hisilicon.com> |
| 6581 | −R: John Stultz <john.stultz@linaro.org> | |
| 6586 | +R: John Stultz <jstultz@google.com> | |
| 6582 | 6587 | R: Xinwei Kong <kong.kongxinwei@hisilicon.com> |
| 6583 | 6588 | R: Chen Feng <puck.chen@hisilicon.com> |
| 6584 | 6589 | L: dri-devel@lists.freedesktop.org |
| @@ -7490,7 +7495,7 @@ F: Documentation/hwmon/f71805f.rst · 905 unmodified lines | ||
| 7490 | 7495 | F: drivers/hwmon/f71805f.c |
| 7491 | 7496 | |
| 7492 | 7497 | FADDR2LINE |
| 7493 | −M: Josh Poimboeuf <jpoimboe@redhat.com> | |
| 7498 | +M: Josh Poimboeuf <jpoimboe@kernel.org> | |
| 7494 | 7499 | S: Maintained |
| 7495 | 7500 | F: scripts/faddr2line |
| 7496 | 7501 | |
| @@ -8103,7 +8108,7 @@ M: Ingo Molnar <mingo@redhat.com> · 606 unmodified lines | ||
| 8103 | 8108 | R: Peter Zijlstra <peterz@infradead.org> |
| 8104 | 8109 | R: Darren Hart <dvhart@infradead.org> |
| 8105 | 8110 | R: Davidlohr Bueso <dave@stgolabs.net> |
| 8106 | −R: André Almeida <andrealmeid@collabora.com> | |
| 8111 | +R: André Almeida <andrealmeid@igalia.com> | |
| 8107 | 8112 | L: linux-kernel@vger.kernel.org |
| 8108 | 8113 | S: Maintained |
| 8109 | 8114 | T: git git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip.git locking/core |
| @@ -8376,7 +8381,7 @@ M: Linus Walleij <linus.walleij@linaro.org> · 266 unmodified lines | ||
| 8376 | 8381 | M: Bartosz Golaszewski <brgl@bgdev.pl> |
| 8377 | 8382 | L: linux-gpio@vger.kernel.org |
| 8378 | 8383 | S: Maintained |
| 8379 | −T: git git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-gpio.git | |
| 8384 | +T: git git://git.kernel.org/pub/scm/linux/kernel/git/brgl/linux.git | |
| 8380 | 8385 | F: Documentation/ABI/obsolete/sysfs-gpio |
| 8381 | 8386 | F: Documentation/ABI/testing/gpio-cdev |
| 8382 | 8387 | F: Documentation/admin-guide/gpio/ |
| @@ -8839,7 +8844,7 @@ F: Documentation/devicetree/bindings/net/hisilicon*.txt · 456 unmodified lines | ||
| 8839 | 8844 | F: drivers/net/ethernet/hisilicon/ |
| 8840 | 8845 | |
| 8841 | 8846 | HIKEY960 ONBOARD USB GPIO HUB DRIVER |
| 8842 | −M: John Stultz <john.stultz@linaro.org> | |
| 8847 | +M: John Stultz <jstultz@google.com> | |
| 8843 | 8848 | L: linux-kernel@vger.kernel.org |
| 8844 | 8849 | S: Maintained |
| 8845 | 8850 | F: drivers/misc/hisi_hikey_usb.c |
| @@ -10122,7 +10127,7 @@ S: Supported · 1276 unmodified lines | ||
| 10122 | 10127 | F: drivers/net/wireless/intel/iwlegacy/ |
| 10123 | 10128 | |
| 10124 | 10129 | INTEL WIRELESS WIFI LINK (iwlwifi) |
| 10125 | −M: Luca Coelho <luciano.coelho@intel.com> | |
| 10130 | +M: Gregory Greenman <gregory.greenman@intel.com> | |
| 10126 | 10131 | L: linux-wireless@vger.kernel.org |
| 10127 | 10132 | S: Supported |
| 10128 | 10133 | W: https://wireless.wiki.kernel.org/en/users/drivers/iwlwifi |
| @@ -10231,8 +10236,6 @@ F: drivers/net/ethernet/sgi/ioc3-eth.c · 102 unmodified lines | ||
| 10231 | 10236 | IOMAP FILESYSTEM LIBRARY |
| 10232 | 10237 | M: Christoph Hellwig <hch@infradead.org> |
| 10233 | 10238 | M: Darrick J. Wong <djwong@kernel.org> |
| 10234 | −M: linux-xfs@vger.kernel.org | |
| 10235 | −M: linux-fsdevel@vger.kernel.org | |
| 10236 | 10239 | L: linux-xfs@vger.kernel.org |
| 10237 | 10240 | L: linux-fsdevel@vger.kernel.org |
| 10238 | 10241 | S: Supported |
| @@ -11341,7 +11344,7 @@ F: drivers/mmc/host/litex_mmc.c · 1102 unmodified lines | ||
| 11341 | 11344 | N: litex |
| 11342 | 11345 | |
| 11343 | 11346 | LIVE PATCHING |
| 11344 | −M: Josh Poimboeuf <jpoimboe@redhat.com> | |
| 11347 | +M: Josh Poimboeuf <jpoimboe@kernel.org> | |
| 11345 | 11348 | M: Jiri Kosina <jikos@kernel.org> |
| 11346 | 11349 | M: Miroslav Benes <mbenes@suse.cz> |
| 11347 | 11350 | M: Petr Mladek <pmladek@suse.com> |
| @@ -11967,6 +11970,7 @@ M: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org> · 619 unmodified lines | ||
| 11967 | 11970 | M: Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com> |
| 11968 | 11971 | L: linux-pm@vger.kernel.org |
| 11969 | 11972 | S: Supported |
| 11973 | +B: mailto:linux-samsung-soc@vger.kernel.org | |
| 11970 | 11974 | F: Documentation/devicetree/bindings/power/supply/maxim,max14577.yaml |
| 11971 | 11975 | F: Documentation/devicetree/bindings/power/supply/maxim,max77693.yaml |
| 11972 | 11976 | F: drivers/power/supply/max14577_charger.c |
| @@ -11978,6 +11982,7 @@ M: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org> · 5 unmodified lines | ||
| 11978 | 11982 | M: Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com> |
| 11979 | 11983 | L: linux-kernel@vger.kernel.org |
| 11980 | 11984 | S: Supported |
| 11985 | +B: mailto:linux-samsung-soc@vger.kernel.org | |
| 11981 | 11986 | F: Documentation/devicetree/bindings/*/maxim,max14577.yaml |
| 11982 | 11987 | F: Documentation/devicetree/bindings/*/maxim,max77686.yaml |
| 11983 | 11988 | F: Documentation/devicetree/bindings/*/maxim,max77693.yaml |
| @@ -12671,6 +12676,7 @@ MEMORY CONTROLLER DRIVERS · 687 unmodified lines | ||
| 12671 | 12676 | M: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org> |
| 12672 | 12677 | L: linux-kernel@vger.kernel.org |
| 12673 | 12678 | S: Maintained |
| 12679 | +B: mailto:krzysztof.kozlowski@linaro.org | |
| 12674 | 12680 | T: git git://git.kernel.org/pub/scm/linux/kernel/git/krzk/linux-mem-ctrl.git |
| 12675 | 12681 | F: Documentation/devicetree/bindings/memory-controllers/ |
| 12676 | 12682 | F: drivers/memory/ |
| @@ -13619,6 +13625,7 @@ F: net/core/drop_monitor.c · 942 unmodified lines | ||
| 13619 | 13625 | |
| 13620 | 13626 | NETWORKING DRIVERS |
| 13621 | 13627 | M: "David S. Miller" <davem@davemloft.net> |
| 13628 | +M: Eric Dumazet <edumazet@google.com> | |
| 13622 | 13629 | M: Jakub Kicinski <kuba@kernel.org> |
| 13623 | 13630 | M: Paolo Abeni <pabeni@redhat.com> |
| 13624 | 13631 | L: netdev@vger.kernel.org |
| @@ -13666,6 +13673,7 @@ F: tools/testing/selftests/drivers/net/dsa/ · 41 unmodified lines | ||
| 13666 | 13673 | |
| 13667 | 13674 | NETWORKING [GENERAL] |
| 13668 | 13675 | M: "David S. Miller" <davem@davemloft.net> |
| 13676 | +M: Eric Dumazet <edumazet@google.com> | |
| 13669 | 13677 | M: Jakub Kicinski <kuba@kernel.org> |
| 13670 | 13678 | M: Paolo Abeni <pabeni@redhat.com> |
| 13671 | 13679 | L: netdev@vger.kernel.org |
| @@ -14212,7 +14220,7 @@ F: lib/objagg.c · 540 unmodified lines | ||
| 14212 | 14220 | F: lib/test_objagg.c |
| 14213 | 14221 | |
| 14214 | 14222 | OBJTOOL |
| 14215 | −M: Josh Poimboeuf <jpoimboe@redhat.com> | |
| 14223 | +M: Josh Poimboeuf <jpoimboe@kernel.org> | |
| 14216 | 14224 | M: Peter Zijlstra <peterz@infradead.org> |
| 14217 | 14225 | S: Supported |
| 14218 | 14226 | F: tools/objtool/ |
| @@ -15463,7 +15471,8 @@ F: tools/perf/ · 1244 unmodified lines | ||
| 15463 | 15471 | PERFORMANCE EVENTS TOOLING ARM64 |
| 15464 | 15472 | R: John Garry <john.garry@huawei.com> |
| 15465 | 15473 | R: Will Deacon <will@kernel.org> |
| 15466 | −R: Mathieu Poirier <mathieu.poirier@linaro.org> | |
| 15474 | +R: James Clark <james.clark@arm.com> | |
| 15475 | +R: Mike Leach <mike.leach@linaro.org> | |
| 15467 | 15476 | R: Leo Yan <leo.yan@linaro.org> |
| 15468 | 15477 | L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) |
| 15469 | 15478 | S: Supported |
| @@ -15603,6 +15612,7 @@ L: linux-samsung-soc@vger.kernel.org · 133 unmodified lines | ||
| 15603 | 15612 | S: Maintained |
| 15604 | 15613 | C: irc://irc.libera.chat/linux-exynos |
| 15605 | 15614 | Q: https://patchwork.kernel.org/project/linux-samsung-soc/list/ |
| 15615 | +B: mailto:linux-samsung-soc@vger.kernel.org | |
| 15606 | 15616 | T: git git://git.kernel.org/pub/scm/linux/kernel/git/pinctrl/samsung.git |
| 15607 | 15617 | F: Documentation/devicetree/bindings/pinctrl/samsung,pinctrl*yaml |
| 15608 | 15618 | F: drivers/pinctrl/samsung/ |
| @@ -17319,6 +17329,7 @@ M: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org> · 1710 unmodified lines | ||
| 17319 | 17329 | M: Sylwester Nawrocki <s.nawrocki@samsung.com> |
| 17320 | 17330 | L: alsa-devel@alsa-project.org (moderated for non-subscribers) |
| 17321 | 17331 | S: Supported |
| 17332 | +B: mailto:linux-samsung-soc@vger.kernel.org | |
| 17322 | 17333 | F: Documentation/devicetree/bindings/sound/samsung* |
| 17323 | 17334 | F: sound/soc/samsung/ |
| 17324 | 17335 | |
| @@ -17363,6 +17374,7 @@ M: Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com> · 38 unmodified lines | ||
| 17363 | 17374 | L: linux-kernel@vger.kernel.org |
| 17364 | 17375 | L: linux-samsung-soc@vger.kernel.org |
| 17365 | 17376 | S: Supported |
| 17377 | +B: mailto:linux-samsung-soc@vger.kernel.org | |
| 17366 | 17378 | F: Documentation/devicetree/bindings/clock/samsung,s2mps11.yaml |
| 17367 | 17379 | F: Documentation/devicetree/bindings/mfd/samsung,s2m*.yaml |
| 17368 | 17380 | F: Documentation/devicetree/bindings/mfd/samsung,s5m*.yaml |
| @@ -18777,7 +18789,7 @@ F: include/dt-bindings/reset/starfive-jh7100.h · 1408 unmodified lines | ||
| 18777 | 18789 | |
| 18778 | 18790 | STATIC BRANCH/CALL |
| 18779 | 18791 | M: Peter Zijlstra <peterz@infradead.org> |
| 18780 | −M: Josh Poimboeuf <jpoimboe@redhat.com> | |
| 18792 | +M: Josh Poimboeuf <jpoimboe@kernel.org> | |
| 18781 | 18793 | M: Jason Baron <jbaron@akamai.com> |
| 18782 | 18794 | R: Steven Rostedt <rostedt@goodmis.org> |
| 18783 | 18795 | R: Ard Biesheuvel <ardb@kernel.org> |
| @@ -19778,7 +19790,7 @@ F: drivers/net/wireless/ti/ · 994 unmodified lines | ||
| 19778 | 19790 | F: include/linux/wl12xx.h |
| 19779 | 19791 | |
| 19780 | 19792 | TIMEKEEPING, CLOCKSOURCE CORE, NTP, ALARMTIMER |
| 19781 | −M: John Stultz <john.stultz@linaro.org> | |
| 19793 | +M: John Stultz <jstultz@google.com> | |
| 19782 | 19794 | M: Thomas Gleixner <tglx@linutronix.de> |
| 19783 | 19795 | R: Stephen Boyd <sboyd@kernel.org> |
| 19784 | 19796 | L: linux-kernel@vger.kernel.org |
| @@ -21428,6 +21440,15 @@ F: arch/x86/include/asm/uv/ · 1643 unmodified lines | ||
| 21428 | 21440 | F: arch/x86/kernel/apic/x2apic_uv_x.c |
| 21429 | 21441 | F: arch/x86/platform/uv/ |
| 21430 | 21442 | |
| 21443 | +X86 STACK UNWINDING | |
| 21444 | +M: Josh Poimboeuf <jpoimboe@kernel.org> | |
| 21445 | +M: Peter Zijlstra <peterz@infradead.org> | |
| 21446 | +S: Supported | |
| 21447 | +F: arch/x86/include/asm/unwind*.h | |
| 21448 | +F: arch/x86/kernel/dumpstack.c | |
| 21449 | +F: arch/x86/kernel/stacktrace.c | |
| 21450 | +F: arch/x86/kernel/unwind_*.c | |
| 21451 | + | |
| 21431 | 21452 | X86 VDSO |
| 21432 | 21453 | M: Andy Lutomirski <luto@kernel.org> |
| 21433 | 21454 | L: linux-kernel@vger.kernel.org |
| @@ -21590,7 +21611,6 @@ F: drivers/xen/*swiotlb* · 156 unmodified lines | ||
| 21590 | 21611 | XFS FILESYSTEM |
| 21591 | 21612 | C: irc://irc.oftc.net/xfs |
| 21592 | 21613 | M: Darrick J. Wong <djwong@kernel.org> |
| 21593 | −M: linux-xfs@vger.kernel.org | |
| 21594 | 21614 | L: linux-xfs@vger.kernel.org |
| 21595 | 21615 | S: Supported |
| 21596 | 21616 | W: http://xfs.org/ |
| @@ -2,7 +2,7 @@ · 1 unmodified line | ||
| 2 | 2 | VERSION = 5 |
| 3 | 3 | PATCHLEVEL = 18 |
| 4 | 4 | SUBLEVEL = 0 |
| 5 | −EXTRAVERSION = -rc4 | |
| 5 | +EXTRAVERSION = -rc7 | |
| 6 | 6 | NAME = Superb Owl |
| 7 | 7 | |
| 8 | 8 | # *DOCUMENTATION* |
| @@ -263,6 +263,8 @@ · 262 unmodified lines | ||
| 263 | 263 | compatible = "ti,am3359-tscadc"; |
| 264 | 264 | reg = <0x0 0x1000>; |
| 265 | 265 | interrupts = <16>; |
| 266 | + clocks = <&adc_tsc_fck>; | |
| 267 | + clock-names = "fck"; | |
| 266 | 268 | status = "disabled"; |
| 267 | 269 | dmas = <&edma 53 0>, <&edma 57 0>; |
| 268 | 270 | dma-names = "fifo0", "fifo1"; |
| @@ -161,6 +161,8 @@ · 160 unmodified lines | ||
| 161 | 161 | |
| 162 | 162 | /* HS USB Host PHY on PORT 1 */ |
| 163 | 163 | hsusb1_phy: hsusb1_phy { |
| 164 | + pinctrl-names = "default"; | |
| 165 | + pinctrl-0 = <&hsusb1_rst_pins>; | |
| 164 | 166 | compatible = "usb-nop-xceiv"; |
| 165 | 167 | reset-gpios = <&gpio2 25 GPIO_ACTIVE_LOW>; /* gpio_57 */ |
| 166 | 168 | #phy-cells = <0>; |
| @@ -168,7 +170,9 @@ · 1 unmodified line | ||
| 168 | 170 | }; |
| 169 | 171 | |
| 170 | 172 | &davinci_emac { |
| 171 | − status = "okay"; | |
| 173 | + pinctrl-names = "default"; | |
| 174 | + pinctrl-0 = <ðernet_pins>; | |
| 175 | + status = "okay"; | |
| 172 | 176 | }; |
| 173 | 177 | |
| 174 | 178 | &davinci_mdio { |
| @@ -193,6 +197,8 @@ · 18 unmodified lines | ||
| 193 | 197 | }; |
| 194 | 198 | |
| 195 | 199 | &i2c2 { |
| 200 | + pinctrl-names = "default"; | |
| 201 | + pinctrl-0 = <&i2c2_pins>; | |
| 196 | 202 | clock-frequency = <400000>; |
| 197 | 203 | /* User DIP swithes [1:8] / User LEDS [1:2] */ |
| 198 | 204 | tca6416: gpio@21 { |
| @@ -205,6 +211,8 @@ · 6 unmodified lines | ||
| 205 | 211 | }; |
| 206 | 212 | |
| 207 | 213 | &i2c3 { |
| 214 | + pinctrl-names = "default"; | |
| 215 | + pinctrl-0 = <&i2c3_pins>; | |
| 208 | 216 | clock-frequency = <400000>; |
| 209 | 217 | }; |
| 210 | 218 | |
| @@ -223,6 +231,8 @@ · 12 unmodified lines | ||
| 223 | 231 | }; |
| 224 | 232 | |
| 225 | 233 | &usbhshost { |
| 234 | + pinctrl-names = "default"; | |
| 235 | + pinctrl-0 = <&hsusb1_pins>; | |
| 226 | 236 | port1-mode = "ehci-phy"; |
| 227 | 237 | }; |
| 228 | 238 | |
| @@ -231,8 +241,35 @@ · 2 unmodified lines | ||
| 231 | 241 | }; |
| 232 | 242 | |
| 233 | 243 | &omap3_pmx_core { |
| 234 | − pinctrl-names = "default"; | |
| 235 | − pinctrl-0 = <&hsusb1_rst_pins>; | |
| 244 | + | |
| 245 | + ethernet_pins: pinmux_ethernet_pins { | |
| 246 | + pinctrl-single,pins = < | |
| 247 | + OMAP3_CORE1_IOPAD(0x21fe, PIN_INPUT | MUX_MODE0) /* rmii_mdio_data */ | |
| 248 | + OMAP3_CORE1_IOPAD(0x2200, MUX_MODE0) /* rmii_mdio_clk */ | |
| 249 | + OMAP3_CORE1_IOPAD(0x2202, PIN_INPUT_PULLDOWN | MUX_MODE0) /* rmii_rxd0 */ | |
| 250 | + OMAP3_CORE1_IOPAD(0x2204, PIN_INPUT_PULLDOWN | MUX_MODE0) /* rmii_rxd1 */ | |
| 251 | + OMAP3_CORE1_IOPAD(0x2206, PIN_INPUT_PULLDOWN | MUX_MODE0) /* rmii_crs_dv */ | |
| 252 | + OMAP3_CORE1_IOPAD(0x2208, PIN_OUTPUT_PULLDOWN | MUX_MODE0) /* rmii_rxer */ | |
| 253 | + OMAP3_CORE1_IOPAD(0x220a, PIN_OUTPUT_PULLDOWN | MUX_MODE0) /* rmii_txd0 */ | |
| 254 | + OMAP3_CORE1_IOPAD(0x220c, PIN_OUTPUT_PULLDOWN | MUX_MODE0) /* rmii_txd1 */ | |
| 255 | + OMAP3_CORE1_IOPAD(0x220e, PIN_OUTPUT_PULLDOWN |MUX_MODE0) /* rmii_txen */ | |
| 256 | + OMAP3_CORE1_IOPAD(0x2210, PIN_INPUT_PULLDOWN | MUX_MODE0) /* rmii_50mhz_clk */ | |
| 257 | + >; | |
| 258 | + }; | |
| 259 | + | |
| 260 | + i2c2_pins: pinmux_i2c2_pins { | |
| 261 | + pinctrl-single,pins = < | |
| 262 | + OMAP3_CORE1_IOPAD(0x21be, PIN_INPUT_PULLUP | MUX_MODE0) /* i2c2_scl */ | |
| 263 | + OMAP3_CORE1_IOPAD(0x21c0, PIN_INPUT_PULLUP | MUX_MODE0) /* i2c2_sda */ | |
| 264 | + >; | |
| 265 | + }; | |
| 266 | + | |
| 267 | + i2c3_pins: pinmux_i2c3_pins { | |
| 268 | + pinctrl-single,pins = < | |
| 269 | + OMAP3_CORE1_IOPAD(0x21c2, PIN_INPUT_PULLUP | MUX_MODE0) /* i2c3_scl */ | |
| 270 | + OMAP3_CORE1_IOPAD(0x21c4, PIN_INPUT_PULLUP | MUX_MODE0) /* i2c3_sda */ | |
| 271 | + >; | |
| 272 | + }; | |
| 236 | 273 | |
| 237 | 274 | leds_pins: pinmux_leds_pins { |
| 238 | 275 | pinctrl-single,pins = < |
| @@ -300,8 +337,6 @@ · 61 unmodified lines | ||
| 300 | 337 | }; |
| 301 | 338 | |
| 302 | 339 | &omap3_pmx_core2 { |
| 303 | − pinctrl-names = "default"; | |
| 304 | − pinctrl-0 = <&hsusb1_pins>; | |
| 305 | 340 | |
| 306 | 341 | hsusb1_pins: pinmux_hsusb1_pins { |
| 307 | 342 | pinctrl-single,pins = < |
| @@ -69,6 +69,8 @@ · 68 unmodified lines | ||
| 69 | 69 | }; |
| 70 | 70 | |
| 71 | 71 | &i2c1 { |
| 72 | + pinctrl-names = "default"; | |
| 73 | + pinctrl-0 = <&i2c1_pins>; | |
| 72 | 74 | clock-frequency = <400000>; |
| 73 | 75 | |
| 74 | 76 | s35390a: s35390a@30 { |
| @@ -179,6 +181,13 @@ · 104 unmodified lines | ||
| 179 | 181 | |
| 180 | 182 | &omap3_pmx_core { |
| 181 | 183 | |
| 184 | + i2c1_pins: pinmux_i2c1_pins { | |
| 185 | + pinctrl-single,pins = < | |
| 186 | + OMAP3_CORE1_IOPAD(0x21ba, PIN_INPUT_PULLUP | MUX_MODE0) /* i2c1_scl */ | |
| 187 | + OMAP3_CORE1_IOPAD(0x21bc, PIN_INPUT_PULLUP | MUX_MODE0) /* i2c1_sda */ | |
| 188 | + >; | |
| 189 | + }; | |
| 190 | + | |
| 182 | 191 | wl12xx_buffer_pins: pinmux_wl12xx_buffer_pins { |
| 183 | 192 | pinctrl-single,pins = < |
| 184 | 193 | OMAP3_CORE1_IOPAD(0x2156, PIN_OUTPUT | MUX_MODE4) /* mmc1_dat7.gpio_129 */ |
| @@ -44,7 +44,7 @@ · 43 unmodified lines | ||
| 44 | 44 | status = "okay"; |
| 45 | 45 | |
| 46 | 46 | /* spi0.0: 4M Flash Macronix MX25R4035FM1IL0 */ |
| 47 | − spi-flash@0 { | |
| 47 | + flash@0 { | |
| 48 | 48 | compatible = "mxicy,mx25u4035", "jedec,spi-nor"; |
| 49 | 49 | spi-max-frequency = <33000000>; |
| 50 | 50 | reg = <0>; |
| @@ -225,7 +225,7 @@ · 224 unmodified lines | ||
| 225 | 225 | pinctrl_pio_io_reset: gpio_io_reset { |
| 226 | 226 | pinmux = <PIN_PB30__GPIO>; |
| 227 | 227 | bias-disable; |
| 228 | − drive-open-drain; | |
| 228 | + drive-open-drain = <1>; | |
| 229 | 229 | output-low; |
| 230 | 230 | }; |
| 231 | 231 | pinctrl_pio_input: gpio_input { |
| @@ -211,7 +211,7 @@ · 210 unmodified lines | ||
| 211 | 211 | pinmux = <PIN_PD12__FLEXCOM4_IO0>, //DATA |
| 212 | 212 | <PIN_PD13__FLEXCOM4_IO1>; //CLK |
| 213 | 213 | bias-disable; |
| 214 | − drive-open-drain; | |
| 214 | + drive-open-drain = <1>; | |
| 215 | 215 | }; |
| 216 | 216 | |
| 217 | 217 | pinctrl_pwm0 { |
| @@ -125,7 +125,7 @@ · 124 unmodified lines | ||
| 125 | 125 | cs-gpios = <&pioA 3 GPIO_ACTIVE_HIGH>, <&pioC 11 GPIO_ACTIVE_LOW>, <0>, <0>; |
| 126 | 126 | status = "okay"; |
| 127 | 127 | |
| 128 | − m25p80@0 { | |
| 128 | + flash@0 { | |
| 129 | 129 | compatible = "jedec,spi-nor"; |
| 130 | 130 | spi-max-frequency = <20000000>; |
| 131 | 131 | reg = <0>; |
| @@ -214,7 +214,7 @@ · 213 unmodified lines | ||
| 214 | 214 | pinctrl-0 = <&pinctrl_qspi1_default>; |
| 215 | 215 | status = "disabled"; |
| 216 | 216 | |
| 217 | − qspi1_flash: spi_flash@0 { | |
| 217 | + qspi1_flash: flash@0 { | |
| 218 | 218 | #address-cells = <1>; |
| 219 | 219 | #size-cells = <1>; |
| 220 | 220 | compatible = "jedec,spi-nor"; |
| @@ -191,7 +191,7 @@ · 190 unmodified lines | ||
| 191 | 191 | &qspi1 { |
| 192 | 192 | status = "okay"; |
| 193 | 193 | |
| 194 | − qspi1_flash: spi_flash@0 { | |
| 194 | + qspi1_flash: flash@0 { | |
| 195 | 195 | status = "okay"; |
| 196 | 196 | }; |
| 197 | 197 | }; |
| @@ -137,7 +137,7 @@ · 136 unmodified lines | ||
| 137 | 137 | pinctrl-0 = <&pinctrl_spi0_default>; |
| 138 | 138 | status = "okay"; |
| 139 | 139 | |
| 140 | − m25p80@0 { | |
| 140 | + flash@0 { | |
| 141 | 141 | compatible = "atmel,at25df321a"; |
| 142 | 142 | reg = <0>; |
| 143 | 143 | spi-max-frequency = <50000000>; |
| @@ -57,8 +57,8 @@ · 56 unmodified lines | ||
| 57 | 57 | }; |
| 58 | 58 | |
| 59 | 59 | spi0: spi@f0004000 { |
| 60 | − pinctrl-names = "default"; | |
| 61 | − pinctrl-0 = <&pinctrl_spi0_cs>; | |
| 60 | + pinctrl-names = "default", "cs"; | |
| 61 | + pinctrl-1 = <&pinctrl_spi0_cs>; | |
| 62 | 62 | cs-gpios = <&pioD 13 0>, <0>, <0>, <&pioD 16 0>; |
| 63 | 63 | status = "okay"; |
| 64 | 64 | }; |
| @@ -171,8 +171,8 @@ · 106 unmodified lines | ||
| 171 | 171 | }; |
| 172 | 172 | |
| 173 | 173 | spi1: spi@f8008000 { |
| 174 | − pinctrl-names = "default"; | |
| 175 | − pinctrl-0 = <&pinctrl_spi1_cs>; | |
| 174 | + pinctrl-names = "default", "cs"; | |
| 175 | + pinctrl-1 = <&pinctrl_spi1_cs>; | |
| 176 | 176 | cs-gpios = <&pioC 25 0>; |
| 177 | 177 | status = "okay"; |
| 178 | 178 | }; |
| @@ -49,7 +49,7 @@ · 48 unmodified lines | ||
| 49 | 49 | cs-gpios = <&pioC 3 0>, <0>, <0>, <0>; |
| 50 | 50 | status = "okay"; |
| 51 | 51 | |
| 52 | − m25p80@0 { | |
| 52 | + flash@0 { | |
| 53 | 53 | compatible = "atmel,at25df321a"; |
| 54 | 54 | spi-max-frequency = <50000000>; |
| 55 | 55 | reg = <0>; |
| @@ -81,8 +81,8 @@ · 80 unmodified lines | ||
| 81 | 81 | }; |
| 82 | 82 | |
| 83 | 83 | spi1: spi@fc018000 { |
| 84 | − pinctrl-names = "default"; | |
| 85 | − pinctrl-0 = <&pinctrl_spi0_cs>; | |
| 84 | + pinctrl-names = "default", "cs"; | |
| 85 | + pinctrl-1 = <&pinctrl_spi1_cs>; | |
| 86 | 86 | cs-gpios = <&pioB 21 0>; |
| 87 | 87 | status = "okay"; |
| 88 | 88 | }; |
| @@ -140,7 +140,7 @@ · 51 unmodified lines | ||
| 140 | 140 | atmel,pins = |
| 141 | 141 | <AT91_PIOE 1 AT91_PERIPH_GPIO AT91_PINCTRL_PULL_UP_DEGLITCH>; |
| 142 | 142 | }; |
| 143 | − pinctrl_spi0_cs: spi0_cs_default { | |
| 143 | + pinctrl_spi1_cs: spi1_cs_default { | |
| 144 | 144 | atmel,pins = |
| 145 | 145 | <AT91_PIOB 21 AT91_PERIPH_GPIO AT91_PINCTRL_NONE>; |
| 146 | 146 | }; |
| @@ -65,7 +65,7 @@ · 64 unmodified lines | ||
| 65 | 65 | spi0: spi@f8010000 { |
| 66 | 66 | cs-gpios = <&pioC 3 0>, <0>, <0>, <0>; |
| 67 | 67 | status = "okay"; |
| 68 | − m25p80@0 { | |
| 68 | + flash@0 { | |
| 69 | 69 | compatible = "atmel,at25df321a"; |
| 70 | 70 | spi-max-frequency = <50000000>; |
| 71 | 71 | reg = <0>; |
| @@ -495,7 +495,7 @@ · 494 unmodified lines | ||
| 495 | 495 | pinctrl_flx3_default: flx3_default { |
| 496 | 496 | pinmux = <PIN_PD16__FLEXCOM3_IO0>, |
| 497 | 497 | <PIN_PD17__FLEXCOM3_IO1>; |
| 498 | − bias-disable; | |
| 498 | + bias-pull-up; | |
| 499 | 499 | }; |
| 500 | 500 | |
| 501 | 501 | pinctrl_flx4_default: flx4_default { |
| @@ -655,7 +655,7 @@ · 153 unmodified lines | ||
| 655 | 655 | <PIN_PB21__QSPI0_INT>; |
| 656 | 656 | bias-disable; |
| 657 | 657 | slew-rate = <0>; |
| 658 | − atmel,drive-strength = <ATMEL_PIO_DRVSTR_HI>; | |
| 658 | + atmel,drive-strength = <ATMEL_PIO_DRVSTR_ME>; | |
| 659 | 659 | }; |
| 660 | 660 | |
| 661 | 661 | pinctrl_sdmmc0_default: sdmmc0_default { |
| @@ -59,7 +59,7 @@ · 58 unmodified lines | ||
| 59 | 59 | spi0: spi@f8010000 { |
| 60 | 60 | cs-gpios = <&pioC 3 0>, <0>, <0>, <0>; |
| 61 | 61 | status = "okay"; |
| 62 | − m25p80@0 { | |
| 62 | + flash@0 { | |
| 63 | 63 | compatible = "n25q32b", "jedec,spi-nor"; |
| 64 | 64 | spi-max-frequency = <50000000>; |
| 65 | 65 | reg = <0>; |
| @@ -73,7 +73,7 @@ · 72 unmodified lines | ||
| 73 | 73 | spi0: spi@fffe0000 { |
| 74 | 74 | status = "okay"; |
| 75 | 75 | cs-gpios = <&pioA 3 0>, <0>, <0>, <0>; |
| 76 | − mtd_dataflash@0 { | |
| 76 | + flash@0 { | |
| 77 | 77 | compatible = "atmel,at45", "atmel,dataflash"; |
| 78 | 78 | spi-max-frequency = <15000000>; |
| 79 | 79 | reg = <0>; |
| @@ -94,7 +94,7 @@ · 14 unmodified lines | ||
| 94 | 94 | status = "okay"; |
| 95 | 95 | }; |
| 96 | 96 | |
| 97 | − nor_flash@10000000 { | |
| 97 | + flash@10000000 { | |
| 98 | 98 | compatible = "cfi-flash"; |
| 99 | 99 | reg = <0x10000000 0x800000>; |
| 100 | 100 | linux,mtd-name = "physmap-flash.0"; |
| @@ -92,7 +92,7 @@ · 91 unmodified lines | ||
| 92 | 92 | |
| 93 | 93 | spi0: spi@fffc8000 { |
| 94 | 94 | cs-gpios = <0>, <&pioC 11 0>, <0>, <0>; |
| 95 | − mtd_dataflash@1 { | |
| 95 | + flash@1 { | |
| 96 | 96 | compatible = "atmel,at45", "atmel,dataflash"; |
| 97 | 97 | spi-max-frequency = <50000000>; |
| 98 | 98 | reg = <1>; |
| @@ -145,7 +145,7 @@ · 144 unmodified lines | ||
| 145 | 145 | cs-gpios = <&pioA 3 0>, <0>, <&pioA 28 0>, <0>; |
| 146 | 146 | status = "okay"; |
| 147 | 147 | |
| 148 | − mtd_dataflash@0 { | |
| 148 | + flash@0 { | |
| 149 | 149 | compatible = "atmel,at45", "atmel,dataflash"; |
| 150 | 150 | reg = <0>; |
| 151 | 151 | spi-max-frequency = <15000000>; |
| @@ -95,7 +95,7 @@ · 94 unmodified lines | ||
| 95 | 95 | spi0: spi@fffa4000 { |
| 96 | 96 | status = "okay"; |
| 97 | 97 | cs-gpios = <&pioA 5 0>, <0>, <0>, <0>; |
| 98 | − mtd_dataflash@0 { | |
| 98 | + flash@0 { | |
| 99 | 99 | compatible = "atmel,at45", "atmel,dataflash"; |
| 100 | 100 | spi-max-frequency = <50000000>; |
| 101 | 101 | reg = <0>; |
| @@ -110,7 +110,7 @@ · 109 unmodified lines | ||
| 110 | 110 | |
| 111 | 111 | spi0: spi@fffc8000 { |
| 112 | 112 | cs-gpios = <0>, <&pioC 11 0>, <0>, <0>; |
| 113 | − mtd_dataflash@1 { | |
| 113 | + flash@1 { | |
| 114 | 114 | compatible = "atmel,at45", "atmel,dataflash"; |
| 115 | 115 | spi-max-frequency = <50000000>; |
| 116 | 116 | reg = <1>; |
| @@ -214,11 +214,23 @@ · 97 unmodified lines | ||
| 214 | 214 | 24c512@50 { |
| 215 | 215 | compatible = "atmel,24c512"; |
| 216 | 216 | reg = <0x50>; |
| 217 | + vcc-supply = <®_3v3>; | |
| 217 | 218 | }; |
| 218 | 219 | |
| 219 | 220 | wm8731: wm8731@1b { |
| 220 | 221 | compatible = "wm8731"; |
| 221 | 222 | reg = <0x1b>; |
| 223 | + | |
| 224 | + /* PCK0 at 12MHz */ | |
| 225 | + clocks = <&pmc PMC_TYPE_SYSTEM 8>; | |
| 226 | + clock-names = "mclk"; | |
| 227 | + assigned-clocks = <&pmc PMC_TYPE_SYSTEM 8>; | |
| 228 | + assigned-clock-rates = <12000000>; | |
| 229 | + | |
| 230 | + HPVDD-supply = <&vcc_dac>; | |
| 231 | + AVDD-supply = <&vcc_dac>; | |
| 232 | + DCVDD-supply = <®_3v3>; | |
| 233 | + DBVDD-supply = <®_3v3>; | |
| 222 | 234 | }; |
| 223 | 235 | }; |
| 224 | 236 | |
| @@ -254,4 +266,35 @@ · 29 unmodified lines | ||
| 254 | 266 | atmel,ssc-controller = <&ssc0>; |
| 255 | 267 | atmel,audio-codec = <&wm8731>; |
| 256 | 268 | }; |
| 269 | + | |
| 270 | + reg_5v: fixedregulator0 { | |
| 271 | + compatible = "regulator-fixed"; | |
| 272 | + regulator-name = "5V"; | |
| 273 | + regulator-min-microvolt = <5000000>; | |
| 274 | + regulator-max-microvolt = <5000000>; | |
| 275 | + }; | |
| 276 | + | |
| 277 | + reg_3v3: fixedregulator1 { | |
| 278 | + compatible = "regulator-fixed"; | |
| 279 | + regulator-name = "3V3"; | |
| 280 | + vin-supply = <®_5v>; | |
| 281 | + regulator-min-microvolt = <3300000>; | |
| 282 | + regulator-max-microvolt = <3300000>; | |
| 283 | + }; | |
| 284 | + | |
| 285 | + reg_1v: fixedregulator2 { | |
| 286 | + compatible = "regulator-fixed"; | |
| 287 | + regulator-name = "1V"; | |
| 288 | + vin-supply = <®_5v>; | |
| 289 | + regulator-min-microvolt = <1000000>; | |
| 290 | + regulator-max-microvolt = <1000000>; | |
| 291 | + }; | |
| 292 | + | |
| 293 | + vcc_dac: fixedregulator3 { | |
| 294 | + compatible = "regulator-fixed"; | |
| 295 | + regulator-name = "VCC_DAC"; | |
| 296 | + vin-supply = <®_3v3>; | |
| 297 | + regulator-min-microvolt = <3300000>; | |
| 298 | + regulator-max-microvolt = <3300000>; | |
| 299 | + }; | |
| 257 | 300 | }; |
| @@ -167,7 +167,7 @@ · 166 unmodified lines | ||
| 167 | 167 | spi0: spi@fffa4000{ |
| 168 | 168 | status = "okay"; |
| 169 | 169 | cs-gpios = <&pioB 3 0>, <0>, <0>, <0>; |
| 170 | − mtd_dataflash@0 { | |
| 170 | + flash@0 { | |
| 171 | 171 | compatible = "atmel,at45", "atmel,dataflash"; |
| 172 | 172 | spi-max-frequency = <13000000>; |
| 173 | 173 | reg = <0>; |
| @@ -119,7 +119,7 @@ · 118 unmodified lines | ||
| 119 | 119 | spi0: spi@f0000000 { |
| 120 | 120 | status = "okay"; |
| 121 | 121 | cs-gpios = <&pioA 14 0>, <0>, <0>, <0>; |
| 122 | − m25p80@0 { | |
| 122 | + flash@0 { | |
| 123 | 123 | compatible = "atmel,at25df321a"; |
| 124 | 124 | spi-max-frequency = <50000000>; |
| 125 | 125 | reg = <0>; |
| @@ -180,7 +180,7 @@ · 179 unmodified lines | ||
| 180 | 180 | spi0: spi@fffcc000 { |
| 181 | 181 | status = "okay"; |
| 182 | 182 | cs-gpios = <&pioA 28 0>, <0>, <0>, <0>; |
| 183 | − mtd_dataflash@0 { | |
| 183 | + flash@0 { | |
| 184 | 184 | compatible = "atmel,at45", "atmel,dataflash"; |
| 185 | 185 | spi-max-frequency = <15000000>; |
| 186 | 186 | reg = <0>; |
| @@ -125,7 +125,7 @@ · 124 unmodified lines | ||
| 125 | 125 | cs-gpios = <&pioA 14 0>, <0>, <0>, <0>; |
| 126 | 126 | status = "disabled"; /* conflicts with mmc1 */ |
| 127 | 127 | |
| 128 | − m25p80@0 { | |
| 128 | + flash@0 { | |
| 129 | 129 | compatible = "atmel,at25df321a"; |
| 130 | 130 | spi-max-frequency = <50000000>; |
| 131 | 131 | reg = <0>; |
| @@ -4188,11 +4188,11 @@ · 4187 unmodified lines | ||
| 4188 | 4188 | reg = <0x1d0010 0x4>; |
| 4189 | 4189 | reg-names = "sysc"; |
| 4190 | 4190 | ti,sysc-midle = <SYSC_IDLE_FORCE>, |
| 4191 | − <SYSC_IDLE_NO>, | |
| 4192 | − <SYSC_IDLE_SMART>; | |
| 4191 | + <SYSC_IDLE_NO>; | |
| 4193 | 4192 | ti,sysc-sidle = <SYSC_IDLE_FORCE>, |
| 4194 | 4193 | <SYSC_IDLE_NO>, |
| 4195 | 4194 | <SYSC_IDLE_SMART>; |
| 4195 | + power-domains = <&prm_vpe>; | |
| 4196 | 4196 | clocks = <&vpe_clkctrl DRA7_VPE_VPE_CLKCTRL 0>; |
| 4197 | 4197 | clock-names = "fck"; |
| 4198 | 4198 | #address-cells = <1>; |
| @@ -286,6 +286,8 @@ · 285 unmodified lines | ||
| 286 | 286 | codec: sgtl5000@a { |
| 287 | 287 | compatible = "fsl,sgtl5000"; |
| 288 | 288 | reg = <0x0a>; |
| 289 | + pinctrl-names = "default"; | |
| 290 | + pinctrl-0 = <&pinctrl_sgtl5000>; | |
| 289 | 291 | clocks = <&clks IMX6QDL_CLK_CKO>; |
| 290 | 292 | VDDA-supply = <®_module_3v3_audio>; |
| 291 | 293 | VDDIO-supply = <®_module_3v3>; |
| @@ -517,8 +519,6 @@ · 225 unmodified lines | ||
| 517 | 519 | MX6QDL_PAD_DISP0_DAT21__AUD4_TXD 0x130b0 |
| 518 | 520 | MX6QDL_PAD_DISP0_DAT22__AUD4_TXFS 0x130b0 |
| 519 | 521 | MX6QDL_PAD_DISP0_DAT23__AUD4_RXD 0x130b0 |
| 520 | − /* SGTL5000 sys_mclk */ | |
| 521 | − MX6QDL_PAD_GPIO_5__CCM_CLKO1 0x130b0 | |
| 522 | 522 | >; |
| 523 | 523 | }; |
| 524 | 524 | |
| @@ -811,6 +811,12 @@ · 286 unmodified lines | ||
| 811 | 811 | >; |
| 812 | 812 | }; |
| 813 | 813 | |
| 814 | + pinctrl_sgtl5000: sgtl5000grp { | |
| 815 | + fsl,pins = < | |
| 816 | + MX6QDL_PAD_GPIO_5__CCM_CLKO1 0x130b0 | |
| 817 | + >; | |
| 818 | + }; | |
| 819 | + | |
| 814 | 820 | pinctrl_spdif: spdifgrp { |
| 815 | 821 | fsl,pins = < |
| 816 | 822 | MX6QDL_PAD_GPIO_16__SPDIF_IN 0x1b0b0 |
| @@ -37,7 +37,7 @@ · 36 unmodified lines | ||
| 37 | 37 | |
| 38 | 38 | reg_sd1_vmmc: regulator-sd1-vmmc { |
| 39 | 39 | compatible = "regulator-gpio"; |
| 40 | − gpio = <&gpio5 9 GPIO_ACTIVE_HIGH>; | |
| 40 | + gpios = <&gpio5 9 GPIO_ACTIVE_HIGH>; | |
| 41 | 41 | pinctrl-names = "default"; |
| 42 | 42 | pinctrl-0 = <&pinctrl_snvs_reg_sd>; |
| 43 | 43 | regulator-always-on; |
| @@ -11,3 +11,18 @@ · 10 unmodified lines | ||
| 11 | 11 | model = "LogicPD Zoom OMAP35xx SOM-LV Development Kit"; |
| 12 | 12 | compatible = "logicpd,dm3730-som-lv-devkit", "ti,omap3430", "ti,omap3"; |
| 13 | 13 | }; |
| 14 | + | |
| 15 | +&omap3_pmx_core2 { | |
| 16 | + pinctrl-names = "default"; | |
| 17 | + pinctrl-0 = <&hsusb2_2_pins>; | |
| 18 | + hsusb2_2_pins: pinmux_hsusb2_2_pins { | |
| 19 | + pinctrl-single,pins = < | |
| 20 | + OMAP3430_CORE2_IOPAD(0x25f0, PIN_OUTPUT | MUX_MODE3) /* etk_d10.hsusb2_clk */ | |
| 21 | + OMAP3430_CORE2_IOPAD(0x25f2, PIN_OUTPUT | MUX_MODE3) /* etk_d11.hsusb2_stp */ | |
| 22 | + OMAP3430_CORE2_IOPAD(0x25f4, PIN_INPUT_PULLDOWN | MUX_MODE3) /* etk_d12.hsusb2_dir */ | |
| 23 | + OMAP3430_CORE2_IOPAD(0x25f6, PIN_INPUT_PULLDOWN | MUX_MODE3) /* etk_d13.hsusb2_nxt */ | |
| 24 | + OMAP3430_CORE2_IOPAD(0x25f8, PIN_INPUT_PULLDOWN | MUX_MODE3) /* etk_d14.hsusb2_data0 */ | |
| 25 | + OMAP3430_CORE2_IOPAD(0x25fa, PIN_INPUT_PULLDOWN | MUX_MODE3) /* etk_d15.hsusb2_data1 */ | |
| 26 | + >; | |
| 27 | + }; | |
| 28 | +}; | |
| @@ -11,3 +11,18 @@ · 10 unmodified lines | ||
| 11 | 11 | model = "LogicPD Zoom DM3730 SOM-LV Development Kit"; |
| 12 | 12 | compatible = "logicpd,dm3730-som-lv-devkit", "ti,omap3630", "ti,omap3"; |
| 13 | 13 | }; |
| 14 | + | |
| 15 | +&omap3_pmx_core2 { | |
| 16 | + pinctrl-names = "default"; | |
| 17 | + pinctrl-0 = <&hsusb2_2_pins>; | |
| 18 | + hsusb2_2_pins: pinmux_hsusb2_2_pins { | |
| 19 | + pinctrl-single,pins = < | |
| 20 | + OMAP3630_CORE2_IOPAD(0x25f0, PIN_OUTPUT | MUX_MODE3) /* etk_d10.hsusb2_clk */ | |
| 21 | + OMAP3630_CORE2_IOPAD(0x25f2, PIN_OUTPUT | MUX_MODE3) /* etk_d11.hsusb2_stp */ | |
| 22 | + OMAP3630_CORE2_IOPAD(0x25f4, PIN_INPUT_PULLDOWN | MUX_MODE3) /* etk_d12.hsusb2_dir */ | |
| 23 | + OMAP3630_CORE2_IOPAD(0x25f6, PIN_INPUT_PULLDOWN | MUX_MODE3) /* etk_d13.hsusb2_nxt */ | |
| 24 | + OMAP3630_CORE2_IOPAD(0x25f8, PIN_INPUT_PULLDOWN | MUX_MODE3) /* etk_d14.hsusb2_data0 */ | |
| 25 | + OMAP3630_CORE2_IOPAD(0x25fa, PIN_INPUT_PULLDOWN | MUX_MODE3) /* etk_d15.hsusb2_data1 */ | |
| 26 | + >; | |
| 27 | + }; | |
| 28 | +}; | |
| @@ -265,21 +265,6 @@ · 264 unmodified lines | ||
| 265 | 265 | }; |
| 266 | 266 | }; |
| 267 | 267 | |
| 268 | −&omap3_pmx_core2 { | |
| 269 | − pinctrl-names = "default"; | |
| 270 | − pinctrl-0 = <&hsusb2_2_pins>; | |
| 271 | − hsusb2_2_pins: pinmux_hsusb2_2_pins { | |
| 272 | − pinctrl-single,pins = < | |
| 273 | − OMAP3630_CORE2_IOPAD(0x25f0, PIN_OUTPUT | MUX_MODE3) /* etk_d10.hsusb2_clk */ | |
| 274 | − OMAP3630_CORE2_IOPAD(0x25f2, PIN_OUTPUT | MUX_MODE3) /* etk_d11.hsusb2_stp */ | |
| 275 | − OMAP3630_CORE2_IOPAD(0x25f4, PIN_INPUT_PULLDOWN | MUX_MODE3) /* etk_d12.hsusb2_dir */ | |
| 276 | − OMAP3630_CORE2_IOPAD(0x25f6, PIN_INPUT_PULLDOWN | MUX_MODE3) /* etk_d13.hsusb2_nxt */ | |
| 277 | − OMAP3630_CORE2_IOPAD(0x25f8, PIN_INPUT_PULLDOWN | MUX_MODE3) /* etk_d14.hsusb2_data0 */ | |
| 278 | − OMAP3630_CORE2_IOPAD(0x25fa, PIN_INPUT_PULLDOWN | MUX_MODE3) /* etk_d15.hsusb2_data1 */ | |
| 279 | − >; | |
| 280 | − }; | |
| 281 | −}; | |
| 282 | − | |
| 283 | 268 | &uart2 { |
| 284 | 269 | interrupts-extended = <&intc 73 &omap3_pmx_core OMAP3_UART2_RX>; |
| 285 | 270 | pinctrl-names = "default"; |
| @@ -31,6 +31,8 @@ · 30 unmodified lines | ||
| 31 | 31 | aliases { |
| 32 | 32 | display0 = &lcd; |
| 33 | 33 | display1 = &tv0; |
| 34 | + /delete-property/ mmc2; | |
| 35 | + /delete-property/ mmc3; | |
| 34 | 36 | }; |
| 35 | 37 | |
| 36 | 38 | ldo_3v3: fixedregulator { |
| @@ -26,7 +26,7 @@ · 25 unmodified lines | ||
| 26 | 26 | spi0: spi@f0004000 { |
| 27 | 27 | dmas = <0>, <0>; /* Do not use DMA for spi0 */ |
| 28 | 28 | |
| 29 | − m25p80@0 { | |
| 29 | + flash@0 { | |
| 30 | 30 | compatible = "atmel,at25df321a"; |
| 31 | 31 | spi-max-frequency = <50000000>; |
| 32 | 32 | reg = <0>; |
| @@ -25,7 +25,7 @@ · 24 unmodified lines | ||
| 25 | 25 | spi0: spi@f0004000 { |
| 26 | 26 | dmas = <0>, <0>; /* Do not use DMA for spi0 */ |
| 27 | 27 | |
| 28 | − m25p80@0 { | |
| 28 | + flash@0 { | |
| 29 | 29 | compatible = "atmel,at25df321a"; |
| 30 | 30 | spi-max-frequency = <50000000>; |
| 31 | 31 | reg = <0>; |
| @@ -601,9 +601,9 @@ · 600 unmodified lines | ||
| 601 | 601 | #size-cells = <0>; |
| 602 | 602 | clocks = <&pmc PMC_TYPE_PERIPHERAL 39>; |
| 603 | 603 | atmel,fifo-size = <32>; |
| 604 | − dmas = <&dma0 AT91_XDMAC_DT_PERID(7)>, | |
| 605 | − <&dma0 AT91_XDMAC_DT_PERID(8)>; | |
| 606 | − dma-names = "rx", "tx"; | |
| 604 | + dmas = <&dma0 AT91_XDMAC_DT_PERID(8)>, | |
| 605 | + <&dma0 AT91_XDMAC_DT_PERID(7)>; | |
| 606 | + dma-names = "tx", "rx"; | |
| 607 | 607 | status = "disabled"; |
| 608 | 608 | }; |
| 609 | 609 | }; |
| @@ -786,9 +786,9 @@ · 176 unmodified lines | ||
| 786 | 786 | #size-cells = <0>; |
| 787 | 787 | clocks = <&pmc PMC_TYPE_PERIPHERAL 46>; |
| 788 | 788 | atmel,fifo-size = <32>; |
| 789 | − dmas = <&dma0 AT91_XDMAC_DT_PERID(21)>, | |
| 790 | − <&dma0 AT91_XDMAC_DT_PERID(22)>; | |
| 791 | − dma-names = "rx", "tx"; | |
| 789 | + dmas = <&dma0 AT91_XDMAC_DT_PERID(22)>, | |
| 790 | + <&dma0 AT91_XDMAC_DT_PERID(21)>; | |
| 791 | + dma-names = "tx", "rx"; | |
| 792 | 792 | status = "disabled"; |
| 793 | 793 | }; |
| 794 | 794 | }; |
| @@ -810,9 +810,9 @@ · 15 unmodified lines | ||
| 810 | 810 | #size-cells = <0>; |
| 811 | 811 | clocks = <&pmc PMC_TYPE_PERIPHERAL 47>; |
| 812 | 812 | atmel,fifo-size = <32>; |
| 813 | − dmas = <&dma0 AT91_XDMAC_DT_PERID(23)>, | |
| 814 | − <&dma0 AT91_XDMAC_DT_PERID(24)>; | |
| 815 | − dma-names = "rx", "tx"; | |
| 813 | + dmas = <&dma0 AT91_XDMAC_DT_PERID(24)>, | |
| 814 | + <&dma0 AT91_XDMAC_DT_PERID(23)>; | |
| 815 | + dma-names = "tx", "rx"; | |
| 816 | 816 | status = "disabled"; |
| 817 | 817 | }; |
| 818 | 818 | }; |
| @@ -60,7 +60,7 @@ · 59 unmodified lines | ||
| 60 | 60 | spi0: spi@fffa4000 { |
| 61 | 61 | cs-gpios = <&pioB 15 GPIO_ACTIVE_HIGH>; |
| 62 | 62 | status = "okay"; |
| 63 | − mtd_dataflash@0 { | |
| 63 | + flash@0 { | |
| 64 | 64 | compatible = "atmel,at45", "atmel,dataflash"; |
| 65 | 65 | reg = <0>; |
| 66 | 66 | spi-max-frequency = <15000000>; |
| @@ -673,6 +673,7 @@ CONFIG_VIDEO_STI_DELTA=m · 672 unmodified lines | ||
| 673 | 673 | CONFIG_VIDEO_RENESAS_FDP1=m |
| 674 | 674 | CONFIG_VIDEO_RENESAS_JPU=m |
| 675 | 675 | CONFIG_VIDEO_RENESAS_VSP1=m |
| 676 | +CONFIG_VIDEO_TEGRA_VDE=m | |
| 676 | 677 | CONFIG_V4L_TEST_DRIVERS=y |
| 677 | 678 | CONFIG_VIDEO_VIVID=m |
| 678 | 679 | CONFIG_VIDEO_ADV7180=m |
| @@ -286,7 +286,8 @@ CONFIG_SERIO_NVEC_PS2=y · 285 unmodified lines | ||
| 286 | 286 | CONFIG_NVEC_POWER=y |
| 287 | 287 | CONFIG_NVEC_PAZ00=y |
| 288 | 288 | CONFIG_STAGING_MEDIA=y |
| 289 | −CONFIG_TEGRA_VDE=y | |
| 289 | +CONFIG_V4L_MEM2MEM_DRIVERS=y | |
| 290 | +CONFIG_VIDEO_TEGRA_VDE=y | |
| 290 | 291 | CONFIG_CHROME_PLATFORMS=y |
| 291 | 292 | CONFIG_CROS_EC=y |
| 292 | 293 | CONFIG_CROS_EC_I2C=m |
| @@ -440,6 +440,9 @@ extern void pci_iounmap(struct pci_dev *dev, void __iomem *addr); · 439 unmodified lines | ||
| 440 | 440 | #define ARCH_HAS_VALID_PHYS_ADDR_RANGE |
| 441 | 441 | extern int valid_phys_addr_range(phys_addr_t addr, size_t size); |
| 442 | 442 | extern int valid_mmap_phys_addr_range(unsigned long pfn, size_t size); |
| 443 | +extern bool arch_memremap_can_ram_remap(resource_size_t offset, size_t size, | |
| 444 | + unsigned long flags); | |
| 445 | +#define arch_memremap_can_ram_remap arch_memremap_can_ram_remap | |
| 443 | 446 | #endif |
| 444 | 447 | |
| 445 | 448 | /* |
| @@ -17,7 +17,6 @@ menuconfig ARCH_EXYNOS · 16 unmodified lines | ||
| 17 | 17 | select EXYNOS_PMU |
| 18 | 18 | select EXYNOS_SROM |
| 19 | 19 | select EXYNOS_PM_DOMAINS if PM_GENERIC_DOMAINS |
| 20 | − select GPIOLIB | |
| 21 | 20 | select HAVE_ARM_ARCH_TIMER if ARCH_EXYNOS5 |
| 22 | 21 | select HAVE_ARM_SCU if SMP |
| 23 | 22 | select PINCTRL |
| @@ -314,10 +314,12 @@ void __init omap_gic_of_init(void) · 313 unmodified lines | ||
| 314 | 314 | |
| 315 | 315 | np = of_find_compatible_node(NULL, NULL, "arm,cortex-a9-gic"); |
| 316 | 316 | gic_dist_base_addr = of_iomap(np, 0); |
| 317 | + of_node_put(np); | |
| 317 | 318 | WARN_ON(!gic_dist_base_addr); |
| 318 | 319 | |
| 319 | 320 | np = of_find_compatible_node(NULL, NULL, "arm,cortex-a9-twd-timer"); |
| 320 | 321 | twd_base = of_iomap(np, 0); |
| 322 | + of_node_put(np); | |
| 321 | 323 | WARN_ON(!twd_base); |
| 322 | 324 | |
| 323 | 325 | skip_errata_init: |
| @@ -493,3 +493,11 @@ void __init early_ioremap_init(void) · 492 unmodified lines | ||
| 493 | 493 | { |
| 494 | 494 | early_ioremap_setup(); |
| 495 | 495 | } |
| 496 | + | |
| 497 | +bool arch_memremap_can_ram_remap(resource_size_t offset, size_t size, | |
| 498 | + unsigned long flags) | |
| 499 | +{ | |
| 500 | + unsigned long pfn = PHYS_PFN(offset); | |
| 501 | + | |
| 502 | + return memblock_is_map_memory(pfn); | |
| 503 | +} | |
| @@ -11,26 +11,6 @@ · 10 unmodified lines | ||
| 11 | 11 | compatible = "operating-points-v2"; |
| 12 | 12 | opp-shared; |
| 13 | 13 | |
| 14 | − opp-100000000 { | |
| 15 | − opp-hz = /bits/ 64 <100000000>; | |
| 16 | − opp-microvolt = <731000>; | |
| 17 | − }; | |
| 18 | − | |
| 19 | − opp-250000000 { | |
| 20 | − opp-hz = /bits/ 64 <250000000>; | |
| 21 | − opp-microvolt = <731000>; | |
| 22 | − }; | |
| 23 | − | |
| 24 | − opp-500000000 { | |
| 25 | − opp-hz = /bits/ 64 <500000000>; | |
| 26 | − opp-microvolt = <731000>; | |
| 27 | − }; | |
| 28 | − | |
| 29 | − opp-667000000 { | |
| 30 | − opp-hz = /bits/ 64 <667000000>; | |
| 31 | − opp-microvolt = <731000>; | |
| 32 | − }; | |
| 33 | − | |
| 34 | 14 | opp-1000000000 { |
| 35 | 15 | opp-hz = /bits/ 64 <1000000000>; |
| 36 | 16 | opp-microvolt = <761000>; |
| @@ -71,26 +51,6 @@ · 34 unmodified lines | ||
| 71 | 51 | compatible = "operating-points-v2"; |
| 72 | 52 | opp-shared; |
| 73 | 53 | |
| 74 | − opp-100000000 { | |
| 75 | − opp-hz = /bits/ 64 <100000000>; | |
| 76 | − opp-microvolt = <731000>; | |
| 77 | − }; | |
| 78 | − | |
| 79 | − opp-250000000 { | |
| 80 | − opp-hz = /bits/ 64 <250000000>; | |
| 81 | − opp-microvolt = <731000>; | |
| 82 | − }; | |
| 83 | − | |
| 84 | − opp-500000000 { | |
| 85 | − opp-hz = /bits/ 64 <500000000>; | |
| 86 | − opp-microvolt = <731000>; | |
| 87 | − }; | |
| 88 | − | |
| 89 | − opp-667000000 { | |
| 90 | − opp-hz = /bits/ 64 <667000000>; | |
| 91 | − opp-microvolt = <731000>; | |
| 92 | − }; | |
| 93 | − | |
| 94 | 54 | opp-1000000000 { |
| 95 | 55 | opp-hz = /bits/ 64 <1000000000>; |
| 96 | 56 | opp-microvolt = <731000>; |
| @@ -11,26 +11,6 @@ · 10 unmodified lines | ||
| 11 | 11 | compatible = "operating-points-v2"; |
| 12 | 12 | opp-shared; |
| 13 | 13 | |
| 14 | − opp-100000000 { | |
| 15 | − opp-hz = /bits/ 64 <100000000>; | |
| 16 | − opp-microvolt = <731000>; | |
| 17 | − }; | |
| 18 | − | |
| 19 | − opp-250000000 { | |
| 20 | − opp-hz = /bits/ 64 <250000000>; | |
| 21 | − opp-microvolt = <731000>; | |
| 22 | − }; | |
| 23 | − | |
| 24 | − opp-500000000 { | |
| 25 | − opp-hz = /bits/ 64 <500000000>; | |
| 26 | − opp-microvolt = <731000>; | |
| 27 | − }; | |
| 28 | − | |
| 29 | − opp-667000000 { | |
| 30 | − opp-hz = /bits/ 64 <667000000>; | |
| 31 | − opp-microvolt = <731000>; | |
| 32 | − }; | |
| 33 | − | |
| 34 | 14 | opp-1000000000 { |
| 35 | 15 | opp-hz = /bits/ 64 <1000000000>; |
| 36 | 16 | opp-microvolt = <731000>; |
| @@ -76,26 +56,6 @@ · 39 unmodified lines | ||
| 76 | 56 | compatible = "operating-points-v2"; |
| 77 | 57 | opp-shared; |
| 78 | 58 | |
| 79 | − opp-100000000 { | |
| 80 | − opp-hz = /bits/ 64 <100000000>; | |
| 81 | − opp-microvolt = <751000>; | |
| 82 | − }; | |
| 83 | − | |
| 84 | − opp-250000000 { | |
| 85 | − opp-hz = /bits/ 64 <250000000>; | |
| 86 | − opp-microvolt = <751000>; | |
| 87 | − }; | |
| 88 | − | |
| 89 | − opp-500000000 { | |
| 90 | − opp-hz = /bits/ 64 <500000000>; | |
| 91 | − opp-microvolt = <751000>; | |
| 92 | − }; | |
| 93 | − | |
| 94 | − opp-667000000 { | |
| 95 | − opp-hz = /bits/ 64 <667000000>; | |
| 96 | − opp-microvolt = <751000>; | |
| 97 | − }; | |
| 98 | − | |
| 99 | 59 | opp-1000000000 { |
| 100 | 60 | opp-hz = /bits/ 64 <1000000000>; |
| 101 | 61 | opp-microvolt = <771000>; |
| @@ -13,28 +13,28 @@ · 12 unmodified lines | ||
| 13 | 13 | |
| 14 | 14 | cpu0: cpu@0 { |
| 15 | 15 | device_type = "cpu"; |
| 16 | − compatible = "arm,cortex-a35","arm,armv8"; | |
| 16 | + compatible = "arm,cortex-a35"; | |
| 17 | 17 | reg = <0x0 0x0>; |
| 18 | 18 | enable-method = "psci"; |
| 19 | 19 | }; |
| 20 | 20 | |
| 21 | 21 | cpu1: cpu@1 { |
| 22 | 22 | device_type = "cpu"; |
| 23 | − compatible = "arm,cortex-a35","arm,armv8"; | |
| 23 | + compatible = "arm,cortex-a35"; | |
| 24 | 24 | reg = <0x0 0x1>; |
| 25 | 25 | enable-method = "psci"; |
| 26 | 26 | }; |
| 27 | 27 | |
| 28 | 28 | cpu2: cpu@2 { |
| 29 | 29 | device_type = "cpu"; |
| 30 | − compatible = "arm,cortex-a35","arm,armv8"; | |
| 30 | + compatible = "arm,cortex-a35"; | |
| 31 | 31 | reg = <0x0 0x2>; |
| 32 | 32 | enable-method = "psci"; |
| 33 | 33 | }; |
| 34 | 34 | |
| 35 | 35 | cpu3: cpu@3 { |
| 36 | 36 | device_type = "cpu"; |
| 37 | − compatible = "arm,cortex-a35","arm,armv8"; | |
| 37 | + compatible = "arm,cortex-a35"; | |
| 38 | 38 | reg = <0x0 0x3>; |
| 39 | 39 | enable-method = "psci"; |
| 40 | 40 | }; |
| @@ -437,6 +437,7 @@ · 436 unmodified lines | ||
| 437 | 437 | "", |
| 438 | 438 | "eMMC_RST#", /* BOOT_12 */ |
| 439 | 439 | "eMMC_DS", /* BOOT_13 */ |
| 440 | + "", "", | |
| 440 | 441 | /* GPIOC */ |
| 441 | 442 | "SD_D0_B", /* GPIOC_0 */ |
| 442 | 443 | "SD_D1_B", /* GPIOC_1 */ |
| @@ -95,26 +95,6 @@ · 94 unmodified lines | ||
| 95 | 95 | compatible = "operating-points-v2"; |
| 96 | 96 | opp-shared; |
| 97 | 97 | |
| 98 | − opp-100000000 { | |
| 99 | − opp-hz = /bits/ 64 <100000000>; | |
| 100 | − opp-microvolt = <730000>; | |
| 101 | − }; | |
| 102 | − | |
| 103 | − opp-250000000 { | |
| 104 | − opp-hz = /bits/ 64 <250000000>; | |
| 105 | − opp-microvolt = <730000>; | |
| 106 | − }; | |
| 107 | − | |
| 108 | − opp-500000000 { | |
| 109 | − opp-hz = /bits/ 64 <500000000>; | |
| 110 | − opp-microvolt = <730000>; | |
| 111 | − }; | |
| 112 | − | |
| 113 | − opp-667000000 { | |
| 114 | − opp-hz = /bits/ 64 <666666666>; | |
| 115 | − opp-microvolt = <750000>; | |
| 116 | − }; | |
| 117 | − | |
| 118 | 98 | opp-1000000000 { |
| 119 | 99 | opp-hz = /bits/ 64 <1000000000>; |
| 120 | 100 | opp-microvolt = <770000>; |
| @@ -146,12 +146,14 @@ · 145 unmodified lines | ||
| 146 | 146 | |
| 147 | 147 | &usbotg1 { |
| 148 | 148 | dr_mode = "otg"; |
| 149 | + over-current-active-low; | |
| 149 | 150 | vbus-supply = <®_usb_otg1_vbus>; |
| 150 | 151 | status = "okay"; |
| 151 | 152 | }; |
| 152 | 153 | |
| 153 | 154 | &usbotg2 { |
| 154 | 155 | dr_mode = "host"; |
| 156 | + disable-over-current; | |
| 155 | 157 | status = "okay"; |
| 156 | 158 | }; |
| 157 | 159 | |
| @@ -215,7 +217,7 @@ · 57 unmodified lines | ||
| 215 | 217 | fsl,pins = < |
| 216 | 218 | MX8MM_IOMUXC_ECSPI2_SCLK_ECSPI2_SCLK 0xd6 |
| 217 | 219 | MX8MM_IOMUXC_ECSPI2_MOSI_ECSPI2_MOSI 0xd6 |
| 218 | − MX8MM_IOMUXC_ECSPI2_SCLK_ECSPI2_SCLK 0xd6 | |
| 220 | + MX8MM_IOMUXC_ECSPI2_MISO_ECSPI2_MISO 0xd6 | |
| 219 | 221 | MX8MM_IOMUXC_ECSPI2_SS0_GPIO5_IO13 0xd6 |
| 220 | 222 | >; |
| 221 | 223 | }; |
| @@ -211,12 +211,14 @@ · 210 unmodified lines | ||
| 211 | 211 | |
| 212 | 212 | &usbotg1 { |
| 213 | 213 | dr_mode = "otg"; |
| 214 | + over-current-active-low; | |
| 214 | 215 | vbus-supply = <®_usb_otg1_vbus>; |
| 215 | 216 | status = "okay"; |
| 216 | 217 | }; |
| 217 | 218 | |
| 218 | 219 | &usbotg2 { |
| 219 | 220 | dr_mode = "host"; |
| 221 | + disable-over-current; | |
| 220 | 222 | vbus-supply = <®_usb_otg2_vbus>; |
| 221 | 223 | status = "okay"; |
| 222 | 224 | }; |
| @@ -309,7 +311,7 @@ · 86 unmodified lines | ||
| 309 | 311 | fsl,pins = < |
| 310 | 312 | MX8MM_IOMUXC_ECSPI2_SCLK_ECSPI2_SCLK 0xd6 |
| 311 | 313 | MX8MM_IOMUXC_ECSPI2_MOSI_ECSPI2_MOSI 0xd6 |
| 312 | − MX8MM_IOMUXC_ECSPI2_SCLK_ECSPI2_SCLK 0xd6 | |
| 314 | + MX8MM_IOMUXC_ECSPI2_MISO_ECSPI2_MISO 0xd6 | |
| 313 | 315 | MX8MM_IOMUXC_ECSPI2_SS0_GPIO5_IO13 0xd6 |
| 314 | 316 | >; |
| 315 | 317 | }; |
| @@ -238,12 +238,14 @@ · 237 unmodified lines | ||
| 238 | 238 | |
| 239 | 239 | &usbotg1 { |
| 240 | 240 | dr_mode = "otg"; |
| 241 | + over-current-active-low; | |
| 241 | 242 | vbus-supply = <®_usb_otg1_vbus>; |
| 242 | 243 | status = "okay"; |
| 243 | 244 | }; |
| 244 | 245 | |
| 245 | 246 | &usbotg2 { |
| 246 | 247 | dr_mode = "host"; |
| 248 | + disable-over-current; | |
| 247 | 249 | vbus-supply = <®_usb_otg2_vbus>; |
| 248 | 250 | status = "okay"; |
| 249 | 251 | }; |
| @@ -358,7 +360,7 @@ · 108 unmodified lines | ||
| 358 | 360 | fsl,pins = < |
| 359 | 361 | MX8MM_IOMUXC_ECSPI2_SCLK_ECSPI2_SCLK 0xd6 |
| 360 | 362 | MX8MM_IOMUXC_ECSPI2_MOSI_ECSPI2_MOSI 0xd6 |
| 361 | − MX8MM_IOMUXC_ECSPI2_SCLK_ECSPI2_SCLK 0xd6 | |
| 363 | + MX8MM_IOMUXC_ECSPI2_MISO_ECSPI2_MISO 0xd6 | |
| 362 | 364 | MX8MM_IOMUXC_ECSPI2_SS0_GPIO5_IO13 0xd6 |
| 363 | 365 | >; |
| 364 | 366 | }; |
| @@ -59,6 +59,10 @@ · 58 unmodified lines | ||
| 59 | 59 | interrupts = <3 IRQ_TYPE_LEVEL_LOW>; |
| 60 | 60 | rohm,reset-snvs-powered; |
| 61 | 61 | |
| 62 | + #clock-cells = <0>; | |
| 63 | + clocks = <&osc_32k 0>; | |
| 64 | + clock-output-names = "clk-32k-out"; | |
| 65 | + | |
| 62 | 66 | regulators { |
| 63 | 67 | buck1_reg: BUCK1 { |
| 64 | 68 | regulator-name = "buck1"; |
| @@ -293,7 +293,7 @@ · 292 unmodified lines | ||
| 293 | 293 | ranges; |
| 294 | 294 | |
| 295 | 295 | sai2: sai@30020000 { |
| 296 | − compatible = "fsl,imx8mm-sai", "fsl,imx8mq-sai"; | |
| 296 | + compatible = "fsl,imx8mn-sai", "fsl,imx8mq-sai"; | |
| 297 | 297 | reg = <0x30020000 0x10000>; |
| 298 | 298 | interrupts = <GIC_SPI 96 IRQ_TYPE_LEVEL_HIGH>; |
| 299 | 299 | clocks = <&clk IMX8MN_CLK_SAI2_IPG>, |
| @@ -307,7 +307,7 @@ · 7 unmodified lines | ||
| 307 | 307 | }; |
| 308 | 308 | |
| 309 | 309 | sai3: sai@30030000 { |
| 310 | − compatible = "fsl,imx8mm-sai", "fsl,imx8mq-sai"; | |
| 310 | + compatible = "fsl,imx8mn-sai", "fsl,imx8mq-sai"; | |
| 311 | 311 | reg = <0x30030000 0x10000>; |
| 312 | 312 | interrupts = <GIC_SPI 50 IRQ_TYPE_LEVEL_HIGH>; |
| 313 | 313 | clocks = <&clk IMX8MN_CLK_SAI3_IPG>, |
| @@ -321,7 +321,7 @@ · 7 unmodified lines | ||
| 321 | 321 | }; |
| 322 | 322 | |
| 323 | 323 | sai5: sai@30050000 { |
| 324 | − compatible = "fsl,imx8mm-sai", "fsl,imx8mq-sai"; | |
| 324 | + compatible = "fsl,imx8mn-sai", "fsl,imx8mq-sai"; | |
| 325 | 325 | reg = <0x30050000 0x10000>; |
| 326 | 326 | interrupts = <GIC_SPI 90 IRQ_TYPE_LEVEL_HIGH>; |
| 327 | 327 | clocks = <&clk IMX8MN_CLK_SAI5_IPG>, |
| @@ -337,7 +337,7 @@ · 9 unmodified lines | ||
| 337 | 337 | }; |
| 338 | 338 | |
| 339 | 339 | sai6: sai@30060000 { |
| 340 | − compatible = "fsl,imx8mm-sai", "fsl,imx8mq-sai"; | |
| 340 | + compatible = "fsl,imx8mn-sai", "fsl,imx8mq-sai"; | |
| 341 | 341 | reg = <0x30060000 0x10000>; |
| 342 | 342 | interrupts = <GIC_SPI 90 IRQ_TYPE_LEVEL_HIGH>; |
| 343 | 343 | clocks = <&clk IMX8MN_CLK_SAI6_IPG>, |
| @@ -394,7 +394,7 @@ · 50 unmodified lines | ||
| 394 | 394 | }; |
| 395 | 395 | |
| 396 | 396 | sai7: sai@300b0000 { |
| 397 | − compatible = "fsl,imx8mm-sai", "fsl,imx8mq-sai"; | |
| 397 | + compatible = "fsl,imx8mn-sai", "fsl,imx8mq-sai"; | |
| 398 | 398 | reg = <0x300b0000 0x10000>; |
| 399 | 399 | interrupts = <GIC_SPI 111 IRQ_TYPE_LEVEL_HIGH>; |
| 400 | 400 | clocks = <&clk IMX8MN_CLK_SAI7_IPG>, |
| @@ -253,7 +253,7 @@ · 252 unmodified lines | ||
| 253 | 253 | #address-cells = <1>; |
| 254 | 254 | #size-cells = <1>; |
| 255 | 255 | spi-max-frequency = <84000000>; |
| 256 | − spi-tx-bus-width = <4>; | |
| 256 | + spi-tx-bus-width = <1>; | |
| 257 | 257 | spi-rx-bus-width = <4>; |
| 258 | 258 | }; |
| 259 | 259 | }; |
| @@ -196,7 +196,7 @@ · 195 unmodified lines | ||
| 196 | 196 | }; |
| 197 | 197 | |
| 198 | 198 | clk: clock-controller { |
| 199 | − compatible = "fsl,imx8qxp-clk", "fsl,scu-clk"; | |
| 199 | + compatible = "fsl,imx8qm-clk", "fsl,scu-clk"; | |
| 200 | 200 | #clock-cells = <2>; |
| 201 | 201 | }; |
| 202 | 202 | |
| @@ -262,25 +262,25 @@ · 261 unmodified lines | ||
| 262 | 262 | gpio4 { |
| 263 | 263 | pins = "gpio4"; |
| 264 | 264 | function = "32k-out1"; |
| 265 | − drive-push-pull; | |
| 265 | + drive-push-pull = <1>; | |
| 266 | 266 | }; |
| 267 | 267 | |
| 268 | 268 | gpio5 { |
| 269 | 269 | pins = "gpio5"; |
| 270 | 270 | function = "gpio"; |
| 271 | − drive-push-pull; | |
| 271 | + drive-push-pull = <0>; | |
| 272 | 272 | }; |
| 273 | 273 | |
| 274 | 274 | gpio6 { |
| 275 | 275 | pins = "gpio6"; |
| 276 | 276 | function = "gpio"; |
| 277 | − drive-push-pull; | |
| 277 | + drive-push-pull = <1>; | |
| 278 | 278 | }; |
| 279 | 279 | |
| 280 | 280 | gpio7 { |
| 281 | 281 | pins = "gpio7"; |
| 282 | 282 | function = "gpio"; |
| 283 | − drive-push-pull; | |
| 283 | + drive-push-pull = <0>; | |
| 284 | 284 | }; |
| 285 | 285 | }; |
| 286 | 286 | |
| @@ -462,25 +462,25 @@ · 461 unmodified lines | ||
| 462 | 462 | gpio4 { |
| 463 | 463 | pins = "gpio4"; |
| 464 | 464 | function = "32k-out1"; |
| 465 | − drive-push-pull; | |
| 465 | + drive-push-pull = <1>; | |
| 466 | 466 | }; |
| 467 | 467 | |
| 468 | 468 | gpio5 { |
| 469 | 469 | pins = "gpio5"; |
| 470 | 470 | function = "gpio"; |
| 471 | − drive-push-pull; | |
| 471 | + drive-push-pull = <0>; | |
| 472 | 472 | }; |
| 473 | 473 | |
| 474 | 474 | gpio6 { |
| 475 | 475 | pins = "gpio6"; |
| 476 | 476 | function = "gpio"; |
| 477 | − drive-push-pull; | |
| 477 | + drive-push-pull = <1>; | |
| 478 | 478 | }; |
| 479 | 479 | |
| 480 | 480 | gpio7 { |
| 481 | 481 | pins = "gpio7"; |
| 482 | 482 | function = "gpio"; |
| 483 | − drive-push-pull; | |
| 483 | + drive-push-pull = <1>; | |
| 484 | 484 | }; |
| 485 | 485 | }; |
| 486 | 486 | |
| @@ -174,19 +174,19 @@ · 173 unmodified lines | ||
| 174 | 174 | gpio4 { |
| 175 | 175 | pins = "gpio4"; |
| 176 | 176 | function = "32k-out1"; |
| 177 | − drive-push-pull; | |
| 177 | + drive-push-pull = <1>; | |
| 178 | 178 | }; |
| 179 | 179 | |
| 180 | 180 | gpio6 { |
| 181 | 181 | pins = "gpio6"; |
| 182 | 182 | function = "gpio"; |
| 183 | − drive-push-pull; | |
| 183 | + drive-push-pull = <1>; | |
| 184 | 184 | }; |
| 185 | 185 | |
| 186 | 186 | gpio7 { |
| 187 | 187 | pins = "gpio7"; |
| 188 | 188 | function = "gpio"; |
| 189 | − drive-push-pull; | |
| 189 | + drive-push-pull = <0>; | |
| 190 | 190 | }; |
| 191 | 191 | }; |
| 192 | 192 | |
| @@ -148,19 +148,19 @@ · 147 unmodified lines | ||
| 148 | 148 | gpio4 { |
| 149 | 149 | pins = "gpio4"; |
| 150 | 150 | function = "32k-out1"; |
| 151 | − drive-push-pull; | |
| 151 | + drive-push-pull = <1>; | |
| 152 | 152 | }; |
| 153 | 153 | |
| 154 | 154 | gpio6 { |
| 155 | 155 | pins = "gpio6"; |
| 156 | 156 | function = "gpio"; |
| 157 | − drive-push-pull; | |
| 157 | + drive-push-pull = <1>; | |
| 158 | 158 | }; |
| 159 | 159 | |
| 160 | 160 | gpio7 { |
| 161 | 161 | pins = "gpio7"; |
| 162 | 162 | function = "gpio"; |
| 163 | − drive-push-pull; | |
| 163 | + drive-push-pull = <0>; | |
| 164 | 164 | }; |
| 165 | 165 | }; |
| 166 | 166 | |
| @@ -59,7 +59,7 @@ · 58 unmodified lines | ||
| 59 | 59 | gpio1 { |
| 60 | 60 | pins = "gpio1"; |
| 61 | 61 | function = "fps-out"; |
| 62 | − drive-push-pull; | |
| 62 | + drive-push-pull = <1>; | |
| 63 | 63 | maxim,active-fps-source = <MAX77620_FPS_SRC_0>; |
| 64 | 64 | maxim,active-fps-power-up-slot = <7>; |
| 65 | 65 | maxim,active-fps-power-down-slot = <0>; |
| @@ -68,7 +68,7 @@ · 2 unmodified lines | ||
| 68 | 68 | gpio2_3 { |
| 69 | 69 | pins = "gpio2", "gpio3"; |
| 70 | 70 | function = "fps-out"; |
| 71 | − drive-open-drain; | |
| 71 | + drive-open-drain = <1>; | |
| 72 | 72 | maxim,active-fps-source = <MAX77620_FPS_SRC_0>; |
| 73 | 73 | }; |
| 74 | 74 | |
| @@ -80,7 +80,7 @@ · 5 unmodified lines | ||
| 80 | 80 | gpio5_6_7 { |
| 81 | 81 | pins = "gpio5", "gpio6", "gpio7"; |
| 82 | 82 | function = "gpio"; |
| 83 | − drive-push-pull; | |
| 83 | + drive-push-pull = <1>; | |
| 84 | 84 | }; |
| 85 | 85 | }; |
| 86 | 86 | |
| @@ -1351,7 +1351,7 @@ · 1350 unmodified lines | ||
| 1351 | 1351 | gpio1 { |
| 1352 | 1352 | pins = "gpio1"; |
| 1353 | 1353 | function = "fps-out"; |
| 1354 | − drive-push-pull; | |
| 1354 | + drive-push-pull = <1>; | |
| 1355 | 1355 | maxim,active-fps-source = <MAX77620_FPS_SRC_0>; |
| 1356 | 1356 | maxim,active-fps-power-up-slot = <7>; |
| 1357 | 1357 | maxim,active-fps-power-down-slot = <0>; |
| @@ -1360,14 +1360,14 @@ · 2 unmodified lines | ||
| 1360 | 1360 | gpio2 { |
| 1361 | 1361 | pins = "gpio2"; |
| 1362 | 1362 | function = "fps-out"; |
| 1363 | − drive-open-drain; | |
| 1363 | + drive-open-drain = <1>; | |
| 1364 | 1364 | maxim,active-fps-source = <MAX77620_FPS_SRC_0>; |
| 1365 | 1365 | }; |
| 1366 | 1366 | |
| 1367 | 1367 | gpio3 { |
| 1368 | 1368 | pins = "gpio3"; |
| 1369 | 1369 | function = "fps-out"; |
| 1370 | − drive-open-drain; | |
| 1370 | + drive-open-drain = <1>; | |
| 1371 | 1371 | maxim,active-fps-source = <MAX77620_FPS_SRC_0>; |
| 1372 | 1372 | }; |
| 1373 | 1373 | |
| @@ -1379,7 +1379,7 @@ · 5 unmodified lines | ||
| 1379 | 1379 | gpio5_6_7 { |
| 1380 | 1380 | pins = "gpio5", "gpio6", "gpio7"; |
| 1381 | 1381 | function = "gpio"; |
| 1382 | − drive-push-pull; | |
| 1382 | + drive-push-pull = <1>; | |
| 1383 | 1383 | }; |
| 1384 | 1384 | }; |
| 1385 | 1385 | |
| @@ -195,7 +195,7 @@ · 194 unmodified lines | ||
| 195 | 195 | gpio1 { |
| 196 | 196 | pins = "gpio1"; |
| 197 | 197 | function = "fps-out"; |
| 198 | − drive-push-pull; | |
| 198 | + drive-push-pull = <1>; | |
| 199 | 199 | maxim,active-fps-source = <MAX77620_FPS_SRC_NONE>; |
| 200 | 200 | maxim,active-fps-power-up-slot = <0>; |
| 201 | 201 | maxim,active-fps-power-down-slot = <7>; |
| @@ -204,7 +204,7 @@ · 2 unmodified lines | ||
| 204 | 204 | gpio2 { |
| 205 | 205 | pins = "gpio2"; |
| 206 | 206 | function = "fps-out"; |
| 207 | − drive-open-drain; | |
| 207 | + drive-open-drain = <1>; | |
| 208 | 208 | maxim,active-fps-source = <MAX77620_FPS_SRC_0>; |
| 209 | 209 | maxim,active-fps-power-up-slot = <0>; |
| 210 | 210 | maxim,active-fps-power-down-slot = <7>; |
| @@ -213,7 +213,7 @@ · 2 unmodified lines | ||
| 213 | 213 | gpio3 { |
| 214 | 214 | pins = "gpio3"; |
| 215 | 215 | function = "fps-out"; |
| 216 | − drive-open-drain; | |
| 216 | + drive-open-drain = <1>; | |
| 217 | 217 | maxim,active-fps-source = <MAX77620_FPS_SRC_0>; |
| 218 | 218 | maxim,active-fps-power-up-slot = <4>; |
| 219 | 219 | maxim,active-fps-power-down-slot = <3>; |
| @@ -227,7 +227,7 @@ · 7 unmodified lines | ||
| 227 | 227 | gpio5_6_7 { |
| 228 | 228 | pins = "gpio5", "gpio6", "gpio7"; |
| 229 | 229 | function = "gpio"; |
| 230 | − drive-push-pull; | |
| 230 | + drive-push-pull = <1>; | |
| 231 | 231 | }; |
| 232 | 232 | }; |
| 233 | 233 | |
| @@ -1386,7 +1386,7 @@ · 1385 unmodified lines | ||
| 1386 | 1386 | gpio3 { |
| 1387 | 1387 | pins = "gpio3"; |
| 1388 | 1388 | function = "fps-out"; |
| 1389 | − drive-open-drain; | |
| 1389 | + drive-open-drain = <1>; | |
| 1390 | 1390 | maxim,active-fps-source = <MAX77620_FPS_SRC_0>; |
| 1391 | 1391 | maxim,active-fps-power-up-slot = <4>; |
| 1392 | 1392 | maxim,active-fps-power-down-slot = <2>; |
| @@ -1395,7 +1395,7 @@ · 2 unmodified lines | ||
| 1395 | 1395 | gpio5_6 { |
| 1396 | 1396 | pins = "gpio5", "gpio6"; |
| 1397 | 1397 | function = "gpio"; |
| 1398 | − drive-push-pull; | |
| 1398 | + drive-push-pull = <1>; | |
| 1399 | 1399 | }; |
| 1400 | 1400 | |
| 1401 | 1401 | gpio4 { |
| @@ -192,4 +192,8 @@ extern void __iomem *ioremap_cache(phys_addr_t phys_addr, size_t size); · 191 unmodified lines | ||
| 192 | 192 | extern int valid_phys_addr_range(phys_addr_t addr, size_t size); |
| 193 | 193 | extern int valid_mmap_phys_addr_range(unsigned long pfn, size_t size); |
| 194 | 194 | |
| 195 | +extern bool arch_memremap_can_ram_remap(resource_size_t offset, size_t size, | |
| 196 | + unsigned long flags); | |
| 197 | +#define arch_memremap_can_ram_remap arch_memremap_can_ram_remap | |
| 198 | + | |
| 195 | 199 | #endif /* __ASM_IO_H */ |
| @@ -40,6 +40,7 @@ void kvm_inject_undefined(struct kvm_vcpu *vcpu); · 39 unmodified lines | ||
| 40 | 40 | void kvm_inject_vabt(struct kvm_vcpu *vcpu); |
| 41 | 41 | void kvm_inject_dabt(struct kvm_vcpu *vcpu, unsigned long addr); |
| 42 | 42 | void kvm_inject_pabt(struct kvm_vcpu *vcpu, unsigned long addr); |
| 43 | +void kvm_inject_size_fault(struct kvm_vcpu *vcpu); | |
| 43 | 44 | |
| 44 | 45 | void kvm_vcpu_wfi(struct kvm_vcpu *vcpu); |
| 45 | 46 | |
| @@ -75,6 +75,10 @@ obj-$(CONFIG_ARM64_MTE) += mte.o · 74 unmodified lines | ||
| 75 | 75 | obj-y += vdso-wrap.o |
| 76 | 76 | obj-$(CONFIG_COMPAT_VDSO) += vdso32-wrap.o |
| 77 | 77 | |
| 78 | +# Force dependency (vdso*-wrap.S includes vdso.so through incbin) | |
| 79 | +$(obj)/vdso-wrap.o: $(obj)/vdso/vdso.so | |
| 80 | +$(obj)/vdso32-wrap.o: $(obj)/vdso32/vdso.so | |
| 81 | + | |
| 78 | 82 | obj-y += probes/ |
| 79 | 83 | head-y := head.o |
| 80 | 84 | extra-y += $(head-y) vmlinux.lds |
| @@ -208,6 +208,8 @@ static const struct arm64_cpu_capabilities arm64_repeat_tlbi_list[] = { · 207 unmodified lines | ||
| 208 | 208 | #ifdef CONFIG_ARM64_ERRATUM_1286807 |
| 209 | 209 | { |
| 210 | 210 | ERRATA_MIDR_RANGE(MIDR_CORTEX_A76, 0, 0, 3, 0), |
| 211 | + /* Kryo4xx Gold (rcpe to rfpe) => (r0p0 to r3p0) */ | |
| 212 | + ERRATA_MIDR_RANGE(MIDR_QCOM_KRYO_4XX_GOLD, 0xc, 0xe, 0xf, 0xe), | |
| 211 | 213 | }, |
| 212 | 214 | #endif |
| 213 | 215 | {}, |
| @@ -654,7 +654,6 @@ static const struct __ftr_reg_entry { · 653 unmodified lines | ||
| 654 | 654 | ARM64_FTR_REG(SYS_ID_AA64ISAR0_EL1, ftr_id_aa64isar0), |
| 655 | 655 | ARM64_FTR_REG_OVERRIDE(SYS_ID_AA64ISAR1_EL1, ftr_id_aa64isar1, |
| 656 | 656 | &id_aa64isar1_override), |
| 657 | − ARM64_FTR_REG(SYS_ID_AA64ISAR2_EL1, ftr_id_aa64isar2), | |
| 658 | 657 | ARM64_FTR_REG_OVERRIDE(SYS_ID_AA64ISAR2_EL1, ftr_id_aa64isar2, |
| 659 | 658 | &id_aa64isar2_override), |
| 660 | 659 | |
| @@ -810,7 +809,7 @@ static void __init sort_ftr_regs(void) · 149 unmodified lines | ||
| 810 | 809 | * to sys_id for subsequent binary search in get_arm64_ftr_reg() |
| 811 | 810 | * to work correctly. |
| 812 | 811 | */ |
| 813 | − BUG_ON(arm64_ftr_regs[i].sys_id < arm64_ftr_regs[i - 1].sys_id); | |
| 812 | + BUG_ON(arm64_ftr_regs[i].sys_id <= arm64_ftr_regs[i - 1].sys_id); | |
| 814 | 813 | } |
| 815 | 814 | } |
| 816 | 815 | |
| @@ -95,7 +95,7 @@ int elf_core_write_extra_phdrs(struct coredump_params *cprm, loff_t offset) · 94 unmodified lines | ||
| 95 | 95 | for_each_mte_vma(current, vma) { |
| 96 | 96 | struct elf_phdr phdr; |
| 97 | 97 | |
| 98 | − phdr.p_type = PT_ARM_MEMTAG_MTE; | |
| 98 | + phdr.p_type = PT_AARCH64_MEMTAG_MTE; | |
| 99 | 99 | phdr.p_offset = offset; |
| 100 | 100 | phdr.p_vaddr = vma->vm_start; |
| 101 | 101 | phdr.p_paddr = 0; |
| @@ -52,9 +52,6 @@ GCOV_PROFILE := n · 51 unmodified lines | ||
| 52 | 52 | targets += vdso.lds |
| 53 | 53 | CPPFLAGS_vdso.lds += -P -C -U$(ARCH) |
| 54 | 54 | |
| 55 | −# Force dependency (incbin is bad) | |
| 56 | −$(obj)/vdso.o : $(obj)/vdso.so | |
| 57 | − | |
| 58 | 55 | # Link rule for the .so file, .lds has to be first |
| 59 | 56 | $(obj)/vdso.so.dbg: $(obj)/vdso.lds $(obj-vdso) FORCE |
| 60 | 57 | $(call if_changed,vdsold_and_vdso_check) |
| @@ -131,9 +131,6 @@ obj-vdso := $(c-obj-vdso) $(c-obj-vdso-gettimeofday) $(asm-obj-vdso) · 130 unmodified lines | ||
| 131 | 131 | targets += vdso.lds |
| 132 | 132 | CPPFLAGS_vdso.lds += -P -C -U$(ARCH) |
| 133 | 133 | |
| 134 | −# Force dependency (vdso.s includes vdso.so through incbin) | |
| 135 | −$(obj)/vdso.o: $(obj)/vdso.so | |
| 136 | − | |
| 137 | 134 | include/generated/vdso32-offsets.h: $(obj)/vdso.so.dbg FORCE |
| 138 | 135 | $(call if_changed,vdsosym) |
| 139 | 136 | |
| @@ -198,15 +198,15 @@ SYM_CODE_START(__kvm_hyp_host_vector) · 197 unmodified lines | ||
| 198 | 198 | invalid_host_el2_vect // FIQ EL2h |
| 199 | 199 | invalid_host_el2_vect // Error EL2h |
| 200 | 200 | |
| 201 | − host_el1_sync_vect // Synchronous 64-bit EL1 | |
| 202 | − invalid_host_el1_vect // IRQ 64-bit EL1 | |
| 203 | − invalid_host_el1_vect // FIQ 64-bit EL1 | |
| 204 | − invalid_host_el1_vect // Error 64-bit EL1 | |
| 205 | − | |
| 206 | − invalid_host_el1_vect // Synchronous 32-bit EL1 | |
| 207 | − invalid_host_el1_vect // IRQ 32-bit EL1 | |
| 208 | − invalid_host_el1_vect // FIQ 32-bit EL1 | |
| 209 | − invalid_host_el1_vect // Error 32-bit EL1 | |
| 201 | + host_el1_sync_vect // Synchronous 64-bit EL1/EL0 | |
| 202 | + invalid_host_el1_vect // IRQ 64-bit EL1/EL0 | |
| 203 | + invalid_host_el1_vect // FIQ 64-bit EL1/EL0 | |
| 204 | + invalid_host_el1_vect // Error 64-bit EL1/EL0 | |
| 205 | + | |
| 206 | + host_el1_sync_vect // Synchronous 32-bit EL1/EL0 | |
| 207 | + invalid_host_el1_vect // IRQ 32-bit EL1/EL0 | |
| 208 | + invalid_host_el1_vect // FIQ 32-bit EL1/EL0 | |
| 209 | + invalid_host_el1_vect // Error 32-bit EL1/EL0 | |
| 210 | 210 | SYM_CODE_END(__kvm_hyp_host_vector) |
| 211 | 211 | |
| 212 | 212 | /* |
| @@ -145,6 +145,34 @@ void kvm_inject_pabt(struct kvm_vcpu *vcpu, unsigned long addr) · 144 unmodified lines | ||
| 145 | 145 | inject_abt64(vcpu, true, addr); |
| 146 | 146 | } |
| 147 | 147 | |
| 148 | +void kvm_inject_size_fault(struct kvm_vcpu *vcpu) | |
| 149 | +{ | |
| 150 | + unsigned long addr, esr; | |
| 151 | + | |
| 152 | + addr = kvm_vcpu_get_fault_ipa(vcpu); | |
| 153 | + addr |= kvm_vcpu_get_hfar(vcpu) & GENMASK(11, 0); | |
| 154 | + | |
| 155 | + if (kvm_vcpu_trap_is_iabt(vcpu)) | |
| 156 | + kvm_inject_pabt(vcpu, addr); | |
| 157 | + else | |
| 158 | + kvm_inject_dabt(vcpu, addr); | |
| 159 | + | |
| 160 | + /* | |
| 161 | + * If AArch64 or LPAE, set FSC to 0 to indicate an Address | |
| 162 | + * Size Fault at level 0, as if exceeding PARange. | |
| 163 | + * | |
| 164 | + * Non-LPAE guests will only get the external abort, as there | |
| 165 | + * is no way to to describe the ASF. | |
| 166 | + */ | |
| 167 | + if (vcpu_el1_is_32bit(vcpu) && | |
| 168 | + !(vcpu_read_sys_reg(vcpu, TCR_EL1) & TTBCR_EAE)) | |
| 169 | + return; | |
| 170 | + | |
| 171 | + esr = vcpu_read_sys_reg(vcpu, ESR_EL1); | |
| 172 | + esr &= ~GENMASK_ULL(5, 0); | |
| 173 | + vcpu_write_sys_reg(vcpu, esr, ESR_EL1); | |
| 174 | +} | |
| 175 | + | |
| 148 | 176 | /** |
| 149 | 177 | * kvm_inject_undefined - inject an undefined instruction into the guest |
| 150 | 178 | * @vcpu: The vCPU in which to inject the exception |
| @@ -1337,6 +1337,25 @@ int kvm_handle_guest_abort(struct kvm_vcpu *vcpu) · 1336 unmodified lines | ||
| 1337 | 1337 | fault_ipa = kvm_vcpu_get_fault_ipa(vcpu); |
| 1338 | 1338 | is_iabt = kvm_vcpu_trap_is_iabt(vcpu); |
| 1339 | 1339 | |
| 1340 | + if (fault_status == FSC_FAULT) { | |
| 1341 | + /* Beyond sanitised PARange (which is the IPA limit) */ | |
| 1342 | + if (fault_ipa >= BIT_ULL(get_kvm_ipa_limit())) { | |
| 1343 | + kvm_inject_size_fault(vcpu); | |
| 1344 | + return 1; | |
| 1345 | + } | |
| 1346 | + | |
| 1347 | + /* Falls between the IPA range and the PARange? */ | |
| 1348 | + if (fault_ipa >= BIT_ULL(vcpu->arch.hw_mmu->pgt->ia_bits)) { | |
| 1349 | + fault_ipa |= kvm_vcpu_get_hfar(vcpu) & GENMASK(11, 0); | |
| 1350 | + | |
| 1351 | + if (is_iabt) | |
| 1352 | + kvm_inject_pabt(vcpu, fault_ipa); | |
| 1353 | + else | |
| 1354 | + kvm_inject_dabt(vcpu, fault_ipa); | |
| 1355 | + return 1; | |
| 1356 | + } | |
| 1357 | + } | |
| 1358 | + | |
| 1340 | 1359 | /* Synchronous External Abort? */ |
| 1341 | 1360 | if (kvm_vcpu_abt_issea(vcpu)) { |
| 1342 | 1361 | /* |
| @@ -177,6 +177,9 @@ u64 kvm_pmu_get_counter_value(struct kvm_vcpu *vcpu, u64 select_idx) · 176 unmodified lines | ||
| 177 | 177 | struct kvm_pmu *pmu = &vcpu->arch.pmu; |
| 178 | 178 | struct kvm_pmc *pmc = &pmu->pmc[select_idx]; |
| 179 | 179 | |
| 180 | + if (!kvm_vcpu_has_pmu(vcpu)) | |
| 181 | + return 0; | |
| 182 | + | |
| 180 | 183 | counter = kvm_pmu_get_pair_counter_value(vcpu, pmc); |
| 181 | 184 | |
| 182 | 185 | if (kvm_pmu_pmc_is_chained(pmc) && |
| @@ -198,6 +201,9 @@ void kvm_pmu_set_counter_value(struct kvm_vcpu *vcpu, u64 select_idx, u64 val) · 15 unmodified lines | ||
| 198 | 201 | { |
| 199 | 202 | u64 reg; |
| 200 | 203 | |
| 204 | + if (!kvm_vcpu_has_pmu(vcpu)) | |
| 205 | + return; | |
| 206 | + | |
| 201 | 207 | reg = (select_idx == ARMV8_PMU_CYCLE_IDX) |
| 202 | 208 | ? PMCCNTR_EL0 : PMEVCNTR0_EL0 + select_idx; |
| 203 | 209 | __vcpu_sys_reg(vcpu, reg) += (s64)val - kvm_pmu_get_counter_value(vcpu, select_idx); |
| @@ -322,6 +328,9 @@ void kvm_pmu_enable_counter_mask(struct kvm_vcpu *vcpu, u64 val) · 118 unmodified lines | ||
| 322 | 328 | struct kvm_pmu *pmu = &vcpu->arch.pmu; |
| 323 | 329 | struct kvm_pmc *pmc; |
| 324 | 330 | |
| 331 | + if (!kvm_vcpu_has_pmu(vcpu)) | |
| 332 | + return; | |
| 333 | + | |
| 325 | 334 | if (!(__vcpu_sys_reg(vcpu, PMCR_EL0) & ARMV8_PMU_PMCR_E) || !val) |
| 326 | 335 | return; |
| 327 | 336 | |
| @@ -357,7 +366,7 @@ void kvm_pmu_disable_counter_mask(struct kvm_vcpu *vcpu, u64 val) · 29 unmodified lines | ||
| 357 | 366 | struct kvm_pmu *pmu = &vcpu->arch.pmu; |
| 358 | 367 | struct kvm_pmc *pmc; |
| 359 | 368 | |
| 360 | − if (!val) | |
| 369 | + if (!kvm_vcpu_has_pmu(vcpu) || !val) | |
| 361 | 370 | return; |
| 362 | 371 | |
| 363 | 372 | for (i = 0; i < ARMV8_PMU_MAX_COUNTERS; i++) { |
| @@ -527,6 +536,9 @@ void kvm_pmu_software_increment(struct kvm_vcpu *vcpu, u64 val) · 163 unmodified lines | ||
| 527 | 536 | struct kvm_pmu *pmu = &vcpu->arch.pmu; |
| 528 | 537 | int i; |
| 529 | 538 | |
| 539 | + if (!kvm_vcpu_has_pmu(vcpu)) | |
| 540 | + return; | |
| 541 | + | |
| 530 | 542 | if (!(__vcpu_sys_reg(vcpu, PMCR_EL0) & ARMV8_PMU_PMCR_E)) |
| 531 | 543 | return; |
| 532 | 544 | |
| @@ -576,6 +588,9 @@ void kvm_pmu_handle_pmcr(struct kvm_vcpu *vcpu, u64 val) · 43 unmodified lines | ||
| 576 | 588 | { |
| 577 | 589 | int i; |
| 578 | 590 | |
| 591 | + if (!kvm_vcpu_has_pmu(vcpu)) | |
| 592 | + return; | |
| 593 | + | |
| 579 | 594 | if (val & ARMV8_PMU_PMCR_E) { |
| 580 | 595 | kvm_pmu_enable_counter_mask(vcpu, |
| 581 | 596 | __vcpu_sys_reg(vcpu, PMCNTENSET_EL0)); |
| @@ -739,6 +754,9 @@ void kvm_pmu_set_counter_event_type(struct kvm_vcpu *vcpu, u64 data, · 157 unmodified lines | ||
| 739 | 754 | { |
| 740 | 755 | u64 reg, mask; |
| 741 | 756 | |
| 757 | + if (!kvm_vcpu_has_pmu(vcpu)) | |
| 758 | + return; | |
| 759 | + | |
| 742 | 760 | mask = ARMV8_PMU_EVTYPE_MASK; |
| 743 | 761 | mask &= ~ARMV8_PMU_EVTYPE_EVENT; |
| 744 | 762 | mask |= kvm_pmu_event_mask(vcpu->kvm); |
| @@ -827,6 +845,9 @@ u64 kvm_pmu_get_pmceid(struct kvm_vcpu *vcpu, bool pmceid1) · 82 unmodified lines | ||
| 827 | 845 | u64 val, mask = 0; |
| 828 | 846 | int base, i, nr_events; |
| 829 | 847 | |
| 848 | + if (!kvm_vcpu_has_pmu(vcpu)) | |
| 849 | + return 0; | |
| 850 | + | |
| 830 | 851 | if (!pmceid1) { |
| 831 | 852 | val = read_sysreg(pmceid0_el0); |
| 832 | 853 | base = 0; |
| @@ -181,7 +181,8 @@ static void kvm_prepare_system_event(struct kvm_vcpu *vcpu, u32 type, u64 flags) · 180 unmodified lines | ||
| 181 | 181 | |
| 182 | 182 | memset(&vcpu->run->system_event, 0, sizeof(vcpu->run->system_event)); |
| 183 | 183 | vcpu->run->system_event.type = type; |
| 184 | − vcpu->run->system_event.flags = flags; | |
| 184 | + vcpu->run->system_event.ndata = 1; | |
| 185 | + vcpu->run->system_event.data[0] = flags; | |
| 185 | 186 | vcpu->run->exit_reason = KVM_EXIT_SYSTEM_EVENT; |
| 186 | 187 | } |
| 187 | 188 | |
| @@ -99,3 +99,11 @@ void __init early_ioremap_init(void) · 98 unmodified lines | ||
| 99 | 99 | { |
| 100 | 100 | early_ioremap_setup(); |
| 101 | 101 | } |
| 102 | + | |
| 103 | +bool arch_memremap_can_ram_remap(resource_size_t offset, size_t size, | |
| 104 | + unsigned long flags) | |
| 105 | +{ | |
| 106 | + unsigned long pfn = PHYS_PFN(offset); | |
| 107 | + | |
| 108 | + return pfn_is_map_memory(pfn); | |
| 109 | +} | |
| @@ -40,9 +40,9 @@ · 39 unmodified lines | ||
| 40 | 40 | typedef unsigned int cycles_t; |
| 41 | 41 | |
| 42 | 42 | /* |
| 43 | − * On R4000/R4400 before version 5.0 an erratum exists such that if the | |
| 44 | − * cycle counter is read in the exact moment that it is matching the | |
| 45 | − * compare register, no interrupt will be generated. | |
| 43 | + * On R4000/R4400 an erratum exists such that if the cycle counter is | |
| 44 | + * read in the exact moment that it is matching the compare register, | |
| 45 | + * no interrupt will be generated. | |
| 46 | 46 | * |
| 47 | 47 | * There is a suggested workaround and also the erratum can't strike if |
| 48 | 48 | * the compare interrupt isn't being used as the clock source device. |
| @@ -63,7 +63,7 @@ static inline int can_use_mips_counter(unsigned int prid) · 14 unmodified lines | ||
| 63 | 63 | if (!__builtin_constant_p(cpu_has_counter)) |
| 64 | 64 | asm volatile("" : "=m" (cpu_data[0].options)); |
| 65 | 65 | if (likely(cpu_has_counter && |
| 66 | − prid >= (PRID_IMP_R4000 | PRID_REV_ENCODE_44(5, 0)))) | |
| 66 | + prid > (PRID_IMP_R4000 | PRID_REV_ENCODE_44(15, 15)))) | |
| 67 | 67 | return 1; |
| 68 | 68 | else |
| 69 | 69 | return 0; |
| @@ -141,15 +141,10 @@ static __init int cpu_has_mfc0_count_bug(void) · 140 unmodified lines | ||
| 141 | 141 | case CPU_R4400MC: |
| 142 | 142 | /* |
| 143 | 143 | * The published errata for the R4400 up to 3.0 say the CPU |
| 144 | − * has the mfc0 from count bug. | |
| 144 | + * has the mfc0 from count bug. This seems the last version | |
| 145 | + * produced. | |
| 145 | 146 | */ |
| 146 | − if ((current_cpu_data.processor_id & 0xff) <= 0x30) | |
| 147 | − return 1; | |
| 148 | − | |
| 149 | − /* | |
| 150 | − * we assume newer revisions are ok | |
| 151 | − */ | |
| 152 | − return 0; | |
| 147 | + return 1; | |
| 153 | 148 | } |
| 154 | 149 | |
| 155 | 150 | return 0; |
| @@ -38,6 +38,7 @@ config PARISC · 37 unmodified lines | ||
| 38 | 38 | select ARCH_HAVE_NMI_SAFE_CMPXCHG |
| 39 | 39 | select GENERIC_SMP_IDLE_THREAD |
| 40 | 40 | select GENERIC_ARCH_TOPOLOGY if SMP |
| 41 | + select GENERIC_CPU_DEVICES if !SMP | |
| 41 | 42 | select GENERIC_LIB_DEVMEM_IS_ALLOWED |
| 42 | 43 | select SYSCTL_ARCH_UNALIGN_ALLOW |
| 43 | 44 | select SYSCTL_EXCEPTION_TRACE |
| @@ -6,6 +6,9 @@ CONFIG_BSD_PROCESS_ACCT=y · 5 unmodified lines | ||
| 6 | 6 | CONFIG_IKCONFIG=y |
| 7 | 7 | CONFIG_IKCONFIG_PROC=y |
| 8 | 8 | CONFIG_LOG_BUF_SHIFT=16 |
| 9 | +CONFIG_CGROUPS=y | |
| 10 | +CONFIG_NAMESPACES=y | |
| 11 | +CONFIG_USER_NS=y | |
| 9 | 12 | CONFIG_BLK_DEV_INITRD=y |
| 10 | 13 | CONFIG_EXPERT=y |
| 11 | 14 | CONFIG_PERF_EVENTS=y |
| @@ -47,7 +50,6 @@ CONFIG_PARPORT=y · 35 unmodified lines | ||
| 47 | 50 | CONFIG_PARPORT_PC=m |
| 48 | 51 | CONFIG_PARPORT_1284=y |
| 49 | 52 | CONFIG_BLK_DEV_LOOP=y |
| 50 | −CONFIG_BLK_DEV_CRYPTOLOOP=y | |
| 51 | 53 | CONFIG_BLK_DEV_RAM=y |
| 52 | 54 | CONFIG_BLK_DEV_RAM_SIZE=6144 |
| 53 | 55 | CONFIG_BLK_DEV_SD=y |
| @@ -16,6 +16,7 @@ CONFIG_CGROUPS=y · 15 unmodified lines | ||
| 16 | 16 | CONFIG_MEMCG=y |
| 17 | 17 | CONFIG_CGROUP_PIDS=y |
| 18 | 18 | CONFIG_CPUSETS=y |
| 19 | +CONFIG_USER_NS=y | |
| 19 | 20 | CONFIG_RELAY=y |
| 20 | 21 | CONFIG_BLK_DEV_INITRD=y |
| 21 | 22 | CONFIG_CC_OPTIMIZE_FOR_SIZE=y |
| @@ -267,9 +268,9 @@ CONFIG_CRYPTO_DEFLATE=m · 245 unmodified lines | ||
| 267 | 268 | CONFIG_CRC_CCITT=m |
| 268 | 269 | CONFIG_LIBCRC32C=y |
| 269 | 270 | CONFIG_PRINTK_TIME=y |
| 271 | +CONFIG_DEBUG_KERNEL=y | |
| 270 | 272 | CONFIG_STRIP_ASM_SYMS=y |
| 271 | 273 | CONFIG_MAGIC_SYSRQ=y |
| 272 | 274 | CONFIG_DEBUG_FS=y |
| 273 | −CONFIG_DEBUG_KERNEL=y | |
| 274 | 275 | CONFIG_DEBUG_STACKOVERFLOW=y |
| 275 | 276 | # CONFIG_SCHED_DEBUG is not set |
| @@ -160,7 +160,7 @@ extern void __update_cache(pte_t pte); · 159 unmodified lines | ||
| 160 | 160 | #define SPACEID_SHIFT (MAX_ADDRBITS - 32) |
| 161 | 161 | #else |
| 162 | 162 | #define MAX_ADDRBITS (BITS_PER_LONG) |
| 163 | −#define MAX_ADDRESS (1UL << MAX_ADDRBITS) | |
| 163 | +#define MAX_ADDRESS (1ULL << MAX_ADDRBITS) | |
| 164 | 164 | #define SPACEID_SHIFT 0 |
| 165 | 165 | #endif |
| 166 | 166 | |
| @@ -403,7 +403,7 @@ void __init parisc_setup_cache_timing(void) · 402 unmodified lines | ||
| 403 | 403 | { |
| 404 | 404 | unsigned long rangetime, alltime; |
| 405 | 405 | unsigned long size; |
| 406 | − unsigned long threshold, threshold2; | |
| 406 | + unsigned long threshold; | |
| 407 | 407 | |
| 408 | 408 | alltime = mfctl(16); |
| 409 | 409 | flush_data_cache(); |
| @@ -418,20 +418,8 @@ void __init parisc_setup_cache_timing(void) · 8 unmodified lines | ||
| 418 | 418 | alltime, size, rangetime); |
| 419 | 419 | |
| 420 | 420 | threshold = L1_CACHE_ALIGN(size * alltime / rangetime); |
| 421 | − | |
| 422 | − /* | |
| 423 | − * The threshold computed above isn't very reliable since the | |
| 424 | − * flush times depend greatly on the percentage of dirty lines | |
| 425 | − * in the flush range. Further, the whole cache time doesn't | |
| 426 | − * include the time to refill lines that aren't in the mm/vma | |
| 427 | − * being flushed. By timing glibc build and checks on mako cpus, | |
| 428 | − * the following formula seems to work reasonably well. The | |
| 429 | − * value from the timing calculation is too small, and increases | |
| 430 | − * build and check times by almost a factor two. | |
| 431 | − */ | |
| 432 | − threshold2 = cache_info.dc_size * num_online_cpus(); | |
| 433 | − if (threshold2 > threshold) | |
| 434 | − threshold = threshold2; | |
| 421 | + if (threshold > cache_info.dc_size) | |
| 422 | + threshold = cache_info.dc_size; | |
| 435 | 423 | if (threshold) |
| 436 | 424 | parisc_cache_flush_threshold = threshold; |
| 437 | 425 | printk(KERN_INFO "Cache flush threshold set to %lu KiB\n", |
| @@ -152,7 +152,7 @@ int __kprobes parisc_kprobe_ss_handler(struct pt_regs *regs) · 151 unmodified lines | ||
| 152 | 152 | /* for absolute branch instructions we can copy iaoq_b. for relative |
| 153 | 153 | * branch instructions we need to calculate the new address based on the |
| 154 | 154 | * difference between iaoq_f and iaoq_b. We cannot use iaoq_b without |
| 155 | − * modificationt because it's based on our ainsn.insn address. | |
| 155 | + * modifications because it's based on our ainsn.insn address. | |
| 156 | 156 | */ |
| 157 | 157 | |
| 158 | 158 | if (p->post_handler) |
| @@ -40,7 +40,10 @@ static void __kprobes *patch_map(void *addr, int fixmap, unsigned long *flags, · 39 unmodified lines | ||
| 40 | 40 | |
| 41 | 41 | *need_unmap = 1; |
| 42 | 42 | set_fixmap(fixmap, page_to_phys(page)); |
| 43 | − raw_spin_lock_irqsave(&patch_lock, *flags); | |
| 43 | + if (flags) | |
| 44 | + raw_spin_lock_irqsave(&patch_lock, *flags); | |
| 45 | + else | |
| 46 | + __acquire(&patch_lock); | |
| 44 | 47 | |
| 45 | 48 | return (void *) (__fix_to_virt(fixmap) + (uintaddr & ~PAGE_MASK)); |
| 46 | 49 | } |
| @@ -49,7 +52,10 @@ static void __kprobes patch_unmap(int fixmap, unsigned long *flags) · 2 unmodified lines | ||
| 49 | 52 | { |
| 50 | 53 | clear_fixmap(fixmap); |
| 51 | 54 | |
| 52 | − raw_spin_unlock_irqrestore(&patch_lock, *flags); | |
| 55 | + if (flags) | |
| 56 | + raw_spin_unlock_irqrestore(&patch_lock, *flags); | |
| 57 | + else | |
| 58 | + __release(&patch_lock); | |
| 53 | 59 | } |
| 54 | 60 | |
| 55 | 61 | void __kprobes __patch_text_multiple(void *addr, u32 *insn, unsigned int len) |
| @@ -61,9 +67,8 @@ void __kprobes __patch_text_multiple(void *addr, u32 *insn, unsigned int len) · 5 unmodified lines | ||
| 61 | 67 | int mapped; |
| 62 | 68 | |
| 63 | 69 | /* Make sure we don't have any aliases in cache */ |
| 64 | − flush_kernel_dcache_range_asm(start, end); | |
| 65 | − flush_kernel_icache_range_asm(start, end); | |
| 66 | − flush_tlb_kernel_range(start, end); | |
| 70 | + flush_kernel_vmap_range(addr, len); | |
| 71 | + flush_icache_range(start, end); | |
| 67 | 72 | |
| 68 | 73 | p = fixmap = patch_map(addr, FIX_TEXT_POKE0, &flags, &mapped); |
| 69 | 74 | |
| @@ -76,10 +81,8 @@ void __kprobes __patch_text_multiple(void *addr, u32 *insn, unsigned int len) · 6 unmodified lines | ||
| 76 | 81 | * We're crossing a page boundary, so |
| 77 | 82 | * need to remap |
| 78 | 83 | */ |
| 79 | − flush_kernel_dcache_range_asm((unsigned long)fixmap, | |
| 80 | − (unsigned long)p); | |
| 81 | − flush_tlb_kernel_range((unsigned long)fixmap, | |
| 82 | − (unsigned long)p); | |
| 84 | + flush_kernel_vmap_range((void *)fixmap, | |
| 85 | + (p-fixmap) * sizeof(*p)); | |
| 83 | 86 | if (mapped) |
| 84 | 87 | patch_unmap(FIX_TEXT_POKE0, &flags); |
| 85 | 88 | p = fixmap = patch_map(addr, FIX_TEXT_POKE0, &flags, |
| @@ -87,10 +90,10 @@ void __kprobes __patch_text_multiple(void *addr, u32 *insn, unsigned int len) · 1 unmodified line | ||
| 87 | 90 | } |
| 88 | 91 | } |
| 89 | 92 | |
| 90 | − flush_kernel_dcache_range_asm((unsigned long)fixmap, (unsigned long)p); | |
| 91 | − flush_tlb_kernel_range((unsigned long)fixmap, (unsigned long)p); | |
| 93 | + flush_kernel_vmap_range((void *)fixmap, (p-fixmap) * sizeof(*p)); | |
| 92 | 94 | if (mapped) |
| 93 | 95 | patch_unmap(FIX_TEXT_POKE0, &flags); |
| 96 | + flush_icache_range(start, end); | |
| 94 | 97 | } |
| 95 | 98 | |
| 96 | 99 | void __kprobes __patch_text(void *addr, u32 insn) |
| @@ -171,6 +171,7 @@ static int __init processor_probe(struct parisc_device *dev) · 170 unmodified lines | ||
| 171 | 171 | p->cpu_num = cpu_info.cpu_num; |
| 172 | 172 | p->cpu_loc = cpu_info.cpu_loc; |
| 173 | 173 | |
| 174 | + set_cpu_possible(cpuid, true); | |
| 174 | 175 | store_cpu_topology(cpuid); |
| 175 | 176 | |
| 176 | 177 | #ifdef CONFIG_SMP |
| @@ -419,8 +420,7 @@ show_cpuinfo (struct seq_file *m, void *v) · 242 unmodified lines | ||
| 419 | 420 | } |
| 420 | 421 | seq_printf(m, " (0x%02lx)\n", boot_cpu_data.pdc.capabilities); |
| 421 | 422 | |
| 422 | − seq_printf(m, "model\t\t: %s\n" | |
| 423 | − "model name\t: %s\n", | |
| 423 | + seq_printf(m, "model\t\t: %s - %s\n", | |
| 424 | 424 | boot_cpu_data.pdc.sys_model_name, |
| 425 | 425 | cpuinfo->dev ? |
| 426 | 426 | cpuinfo->dev->name : "Unknown"); |
| @@ -461,6 +461,13 @@ static struct parisc_driver cpu_driver __refdata = { · 34 unmodified lines | ||
| 461 | 461 | */ |
| 462 | 462 | void __init processor_init(void) |
| 463 | 463 | { |
| 464 | + unsigned int cpu; | |
| 465 | + | |
| 464 | 466 | reset_cpu_topology(); |
| 467 | + | |
| 468 | + /* reset possible mask. We will mark those which are possible. */ | |
| 469 | + for_each_possible_cpu(cpu) | |
| 470 | + set_cpu_possible(cpu, false); | |
| 471 | + | |
| 465 | 472 | register_parisc_driver(&cpu_driver); |
| 466 | 473 | } |
| @@ -161,6 +161,8 @@ void __init setup_arch(char **cmdline_p) · 160 unmodified lines | ||
| 161 | 161 | #ifdef CONFIG_PA11 |
| 162 | 162 | dma_ops_init(); |
| 163 | 163 | #endif |
| 164 | + | |
| 165 | + clear_sched_clock_stable(); | |
| 164 | 166 | } |
| 165 | 167 | |
| 166 | 168 | /* |
| @@ -251,13 +251,9 @@ void __init time_init(void) · 250 unmodified lines | ||
| 251 | 251 | static int __init init_cr16_clocksource(void) |
| 252 | 252 | { |
| 253 | 253 | /* |
| 254 | − * The cr16 interval timers are not syncronized across CPUs, even if | |
| 255 | − * they share the same socket. | |
| 254 | + * The cr16 interval timers are not synchronized across CPUs. | |
| 256 | 255 | */ |
| 257 | 256 | if (num_online_cpus() > 1 && !running_on_qemu) { |
| 258 | − /* mark sched_clock unstable */ | |
| 259 | − clear_sched_clock_stable(); | |
| 260 | − | |
| 261 | 257 | clocksource_cr16.name = "cr16_unstable"; |
| 262 | 258 | clocksource_cr16.flags = CLOCK_SOURCE_UNSTABLE; |
| 263 | 259 | clocksource_cr16.rating = 0; |
| @@ -469,7 +469,7 @@ void parisc_terminate(char *msg, struct pt_regs *regs, int code, unsigned long o · 468 unmodified lines | ||
| 469 | 469 | * panic notifiers, and we should call panic |
| 470 | 470 | * directly from the location that we wish. |
| 471 | 471 | * e.g. We should not call panic from |
| 472 | − * parisc_terminate, but rather the oter way around. | |
| 472 | + * parisc_terminate, but rather the other way around. | |
| 473 | 473 | * This hack works, prints the panic message twice, |
| 474 | 474 | * and it enables reboot timers! |
| 475 | 475 | */ |
| @@ -253,7 +253,7 @@ dbl_fadd( · 252 unmodified lines | ||
| 253 | 253 | return(NOEXCEPTION); |
| 254 | 254 | } |
| 255 | 255 | right_exponent = 1; /* Set exponent to reflect different bias |
| 256 | − * with denomalized numbers. */ | |
| 256 | + * with denormalized numbers. */ | |
| 257 | 257 | } |
| 258 | 258 | else |
| 259 | 259 | { |
| @@ -256,7 +256,7 @@ dbl_fsub( · 255 unmodified lines | ||
| 256 | 256 | return(NOEXCEPTION); |
| 257 | 257 | } |
| 258 | 258 | right_exponent = 1; /* Set exponent to reflect different bias |
| 259 | − * with denomalized numbers. */ | |
| 259 | + * with denormalized numbers. */ | |
| 260 | 260 | } |
| 261 | 261 | else |
| 262 | 262 | { |
| @@ -249,7 +249,7 @@ sgl_fadd( · 248 unmodified lines | ||
| 249 | 249 | return(NOEXCEPTION); |
| 250 | 250 | } |
| 251 | 251 | right_exponent = 1; /* Set exponent to reflect different bias |
| 252 | − * with denomalized numbers. */ | |
| 252 | + * with denormalized numbers. */ | |
| 253 | 253 | } |
| 254 | 254 | else |
| 255 | 255 | { |
| @@ -252,7 +252,7 @@ sgl_fsub( · 251 unmodified lines | ||
| 252 | 252 | return(NOEXCEPTION); |
| 253 | 253 | } |
| 254 | 254 | right_exponent = 1; /* Set exponent to reflect different bias |
| 255 | − * with denomalized numbers. */ | |
| 255 | + * with denormalized numbers. */ | |
| 256 | 256 | } |
| 257 | 257 | else |
| 258 | 258 | { |
| @@ -22,12 +22,15 @@ · 21 unmodified lines | ||
| 22 | 22 | .macro cvdso_call funct call_time=0 |
| 23 | 23 | .cfi_startproc |
| 24 | 24 | PPC_STLU r1, -PPC_MIN_STKFRM(r1) |
| 25 | + .cfi_adjust_cfa_offset PPC_MIN_STKFRM | |
| 25 | 26 | mflr r0 |
| 26 | − .cfi_register lr, r0 | |
| 27 | 27 | PPC_STLU r1, -PPC_MIN_STKFRM(r1) |
| 28 | + .cfi_adjust_cfa_offset PPC_MIN_STKFRM | |
| 28 | 29 | PPC_STL r0, PPC_MIN_STKFRM + PPC_LR_STKOFF(r1) |
| 30 | + .cfi_rel_offset lr, PPC_MIN_STKFRM + PPC_LR_STKOFF | |
| 29 | 31 | #ifdef __powerpc64__ |
| 30 | 32 | PPC_STL r2, PPC_MIN_STKFRM + STK_GOT(r1) |
| 33 | + .cfi_rel_offset r2, PPC_MIN_STKFRM + STK_GOT | |
| 31 | 34 | #endif |
| 32 | 35 | get_datapage r5 |
| 33 | 36 | .ifeq \call_time |
| @@ -39,13 +42,15 @@ · 5 unmodified lines | ||
| 39 | 42 | PPC_LL r0, PPC_MIN_STKFRM + PPC_LR_STKOFF(r1) |
| 40 | 43 | #ifdef __powerpc64__ |
| 41 | 44 | PPC_LL r2, PPC_MIN_STKFRM + STK_GOT(r1) |
| 45 | + .cfi_restore r2 | |
| 42 | 46 | #endif |
| 43 | 47 | .ifeq \call_time |
| 44 | 48 | cmpwi r3, 0 |
| 45 | 49 | .endif |
| 46 | 50 | mtlr r0 |
| 47 | − .cfi_restore lr | |
| 48 | 51 | addi r1, r1, 2 * PPC_MIN_STKFRM |
| 52 | + .cfi_restore lr | |
| 53 | + .cfi_def_cfa_offset 0 | |
| 49 | 54 | crclr so |
| 50 | 55 | .ifeq \call_time |
| 51 | 56 | beqlr+ |
| @@ -122,11 +122,27 @@ · 121 unmodified lines | ||
| 122 | 122 | |
| 123 | 123 | /* 0x0 - 0xb */ |
| 124 | 124 | |
| 125 | − /* 'current->mm' needs to be in r4 */ | |
| 126 | − tophys(r4, r2) | |
| 127 | − lwz r4, MM(r4) | |
| 128 | − tophys(r4, r4) | |
| 129 | − /* This only clobbers r0, r3, r4 and r5 */ | |
| 125 | + /* switch_mmu_context() needs paging, let's enable it */ | |
| 126 | + mfmsr r9 | |
| 127 | + ori r11, r9, MSR_DR | |
| 128 | + mtmsr r11 | |
| 129 | + sync | |
| 130 | + | |
| 131 | + /* switch_mmu_context() clobbers r12, rescue it */ | |
| 132 | + SAVE_GPR(12, r1) | |
| 133 | + | |
| 134 | + /* Calling switch_mmu_context(<inv>, current->mm, <inv>); */ | |
| 135 | + lwz r4, MM(r2) | |
| 130 | 136 | bl switch_mmu_context |
| 131 | 137 | |
| 138 | + /* restore r12 */ | |
| 139 | + REST_GPR(12, r1) | |
| 140 | + | |
| 141 | + /* Disable paging again */ | |
| 142 | + mfmsr r9 | |
| 143 | + li r6, MSR_DR | |
| 144 | + andc r9, r9, r6 | |
| 145 | + mtmsr r9 | |
| 146 | + sync | |
| 147 | + | |
| 132 | 148 | .endm |
| @@ -462,7 +462,6 @@ static int papr_scm_pmu_check_events(struct papr_scm_priv *p, struct nvdimm_pmu · 461 unmodified lines | ||
| 462 | 462 | { |
| 463 | 463 | struct papr_scm_perf_stat *stat; |
| 464 | 464 | struct papr_scm_perf_stats *stats; |
| 465 | − char *statid; | |
| 466 | 465 | int index, rc, count; |
| 467 | 466 | u32 available_events; |
| 468 | 467 | |
| @@ -493,14 +492,12 @@ static int papr_scm_pmu_check_events(struct papr_scm_priv *p, struct nvdimm_pmu · 24 unmodified lines | ||
| 493 | 492 | |
| 494 | 493 | for (index = 0, stat = stats->scm_statistic, count = 0; |
| 495 | 494 | index < available_events; index++, ++stat) { |
| 496 | − statid = kzalloc(strlen(stat->stat_id) + 1, GFP_KERNEL); | |
| 497 | − if (!statid) { | |
| 495 | + p->nvdimm_events_map[count] = kmemdup_nul(stat->stat_id, 8, GFP_KERNEL); | |
| 496 | + if (!p->nvdimm_events_map[count]) { | |
| 498 | 497 | rc = -ENOMEM; |
| 499 | 498 | goto out_nvdimm_events_map; |
| 500 | 499 | } |
| 501 | 500 | |
| 502 | − strcpy(statid, stat->stat_id); | |
| 503 | − p->nvdimm_events_map[count] = statid; | |
| 504 | 501 | count++; |
| 505 | 502 | } |
| 506 | 503 | p->nvdimm_events_map[count] = NULL; |
| @@ -27,22 +27,31 @@ struct vas_caps_entry { · 26 unmodified lines | ||
| 27 | 27 | |
| 28 | 28 | /* |
| 29 | 29 | * This function is used to get the notification from the drmgr when |
| 30 | − * QoS credits are changed. Though receiving the target total QoS | |
| 31 | − * credits here, get the official QoS capabilities from the hypervisor. | |
| 30 | + * QoS credits are changed. | |
| 32 | 31 | */ |
| 33 | −static ssize_t update_total_credits_trigger(struct vas_cop_feat_caps *caps, | |
| 32 | +static ssize_t update_total_credits_store(struct vas_cop_feat_caps *caps, | |
| 34 | 33 | const char *buf, size_t count) |
| 35 | 34 | { |
| 36 | 35 | int err; |
| 37 | 36 | u16 creds; |
| 38 | 37 | |
| 39 | 38 | err = kstrtou16(buf, 0, &creds); |
| 39 | + /* | |
| 40 | + * The user space interface from the management console | |
| 41 | + * notifies OS with the new QoS credits and then the | |
| 42 | + * hypervisor. So OS has to use this new credits value | |
| 43 | + * and reconfigure VAS windows (close or reopen depends | |
| 44 | + * on the credits available) instead of depending on VAS | |
| 45 | + * QoS capabilities from the hypervisor. | |
| 46 | + */ | |
| 40 | 47 | if (!err) |
| 41 | − err = vas_reconfig_capabilties(caps->win_type); | |
| 48 | + err = vas_reconfig_capabilties(caps->win_type, creds); | |
| 42 | 49 | |
| 43 | 50 | if (err) |
| 44 | 51 | return -EINVAL; |
| 45 | 52 | |
| 53 | + pr_info("Set QoS total credits %u\n", creds); | |
| 54 | + | |
| 46 | 55 | return count; |
| 47 | 56 | } |
| 48 | 57 | |
| @@ -92,7 +101,7 @@ VAS_ATTR_RO(nr_total_credits); · 43 unmodified lines | ||
| 92 | 101 | VAS_ATTR_RO(nr_used_credits); |
| 93 | 102 | |
| 94 | 103 | static struct vas_sysfs_entry update_total_credits_attribute = |
| 95 | − __ATTR(update_total_credits, 0200, NULL, update_total_credits_trigger); | |
| 104 | + __ATTR(update_total_credits, 0200, NULL, update_total_credits_store); | |
| 96 | 105 | |
| 97 | 106 | static struct attribute *vas_def_capab_attrs[] = { |
| 98 | 107 | &nr_total_credits_attribute.attr, |
| @@ -779,10 +779,10 @@ static int reconfig_close_windows(struct vas_caps *vcap, int excess_creds, · 778 unmodified lines | ||
| 779 | 779 | * changes. Reconfig window configurations based on the credits |
| 780 | 780 | * availability from this new capabilities. |
| 781 | 781 | */ |
| 782 | −int vas_reconfig_capabilties(u8 type) | |
| 782 | +int vas_reconfig_capabilties(u8 type, int new_nr_creds) | |
| 783 | 783 | { |
| 784 | 784 | struct vas_cop_feat_caps *caps; |
| 785 | − int old_nr_creds, new_nr_creds; | |
| 785 | + int old_nr_creds; | |
| 786 | 786 | struct vas_caps *vcaps; |
| 787 | 787 | int rc = 0, nr_active_wins; |
| 788 | 788 | |
| @@ -795,12 +795,6 @@ int vas_reconfig_capabilties(u8 type) · 6 unmodified lines | ||
| 795 | 795 | caps = &vcaps->caps; |
| 796 | 796 | |
| 797 | 797 | mutex_lock(&vas_pseries_mutex); |
| 798 | − rc = h_query_vas_capabilities(H_QUERY_VAS_CAPABILITIES, vcaps->feat, | |
| 799 | − (u64)virt_to_phys(&hv_cop_caps)); | |
| 800 | − if (rc) | |
| 801 | − goto out; | |
| 802 | − | |
| 803 | − new_nr_creds = be16_to_cpu(hv_cop_caps.target_lpar_creds); | |
| 804 | 798 | |
| 805 | 799 | old_nr_creds = atomic_read(&caps->nr_total_credits); |
| 806 | 800 | |
| @@ -832,7 +826,6 @@ int vas_reconfig_capabilties(u8 type) · 25 unmodified lines | ||
| 832 | 826 | false); |
| 833 | 827 | } |
| 834 | 828 | |
| 835 | −out: | |
| 836 | 829 | mutex_unlock(&vas_pseries_mutex); |
| 837 | 830 | return rc; |
| 838 | 831 | } |
| @@ -850,7 +843,7 @@ static int pseries_vas_notifier(struct notifier_block *nb, · 11 unmodified lines | ||
| 850 | 843 | struct of_reconfig_data *rd = data; |
| 851 | 844 | struct device_node *dn = rd->dn; |
| 852 | 845 | const __be32 *intserv = NULL; |
| 853 | − int len, rc = 0; | |
| 846 | + int new_nr_creds, len, rc = 0; | |
| 854 | 847 | |
| 855 | 848 | if ((action == OF_RECONFIG_ATTACH_NODE) || |
| 856 | 849 | (action == OF_RECONFIG_DETACH_NODE)) |
| @@ -862,7 +855,15 @@ static int pseries_vas_notifier(struct notifier_block *nb, · 5 unmodified lines | ||
| 862 | 855 | if (!intserv) |
| 863 | 856 | return NOTIFY_OK; |
| 864 | 857 | |
| 865 | − rc = vas_reconfig_capabilties(VAS_GZIP_DEF_FEAT_TYPE); | |
| 858 | + rc = h_query_vas_capabilities(H_QUERY_VAS_CAPABILITIES, | |
| 859 | + vascaps[VAS_GZIP_DEF_FEAT_TYPE].feat, | |
| 860 | + (u64)virt_to_phys(&hv_cop_caps)); | |
| 861 | + if (!rc) { | |
| 862 | + new_nr_creds = be16_to_cpu(hv_cop_caps.target_lpar_creds); | |
| 863 | + rc = vas_reconfig_capabilties(VAS_GZIP_DEF_FEAT_TYPE, | |
| 864 | + new_nr_creds); | |
| 865 | + } | |
| 866 | + | |
| 866 | 867 | if (rc) |
| 867 | 868 | pr_err("Failed reconfig VAS capabilities with DLPAR\n"); |
| 868 | 869 | |
| @@ -135,7 +135,7 @@ struct pseries_vas_window { · 134 unmodified lines | ||
| 135 | 135 | }; |
| 136 | 136 | |
| 137 | 137 | int sysfs_add_vas_caps(struct vas_cop_feat_caps *caps); |
| 138 | −int vas_reconfig_capabilties(u8 type); | |
| 138 | +int vas_reconfig_capabilties(u8 type, int new_nr_creds); | |
| 139 | 139 | int __init sysfs_pseries_vas_init(struct vas_all_caps *vas_caps); |
| 140 | 140 | |
| 141 | 141 | #ifdef CONFIG_PPC_VAS |
| @@ -7,7 +7,7 @@ · 6 unmodified lines | ||
| 7 | 7 | reg = <0x0 0x41000000 0x0 0xF0>; |
| 8 | 8 | microchip,sync-update-mask = /bits/ 32 <0>; |
| 9 | 9 | #pwm-cells = <2>; |
| 10 | − clocks = <&clkcfg CLK_FIC3>; | |
| 10 | + clocks = <&fabric_clk3>; | |
| 11 | 11 | status = "disabled"; |
| 12 | 12 | }; |
| 13 | 13 | |
| @@ -16,10 +16,22 @@ · 2 unmodified lines | ||
| 16 | 16 | reg = <0x0 0x44000000 0x0 0x1000>; |
| 17 | 17 | #address-cells = <1>; |
| 18 | 18 | #size-cells = <0>; |
| 19 | − clocks = <&clkcfg CLK_FIC3>; | |
| 19 | + clocks = <&fabric_clk3>; | |
| 20 | 20 | interrupt-parent = <&plic>; |
| 21 | 21 | interrupts = <122>; |
| 22 | 22 | clock-frequency = <100000>; |
| 23 | 23 | status = "disabled"; |
| 24 | 24 | }; |
| 25 | + | |
| 26 | + fabric_clk3: fabric-clk3 { | |
| 27 | + compatible = "fixed-clock"; | |
| 28 | + #clock-cells = <0>; | |
| 29 | + clock-frequency = <62500000>; | |
| 30 | + }; | |
| 31 | + | |
| 32 | + fabric_clk1: fabric-clk1 { | |
| 33 | + compatible = "fixed-clock"; | |
| 34 | + #clock-cells = <0>; | |
| 35 | + clock-frequency = <125000000>; | |
| 36 | + }; | |
| 25 | 37 | }; |
| @@ -45,7 +45,7 @@ · 44 unmodified lines | ||
| 45 | 45 | }; |
| 46 | 46 | |
| 47 | 47 | &refclk { |
| 48 | − clock-frequency = <600000000>; | |
| 48 | + clock-frequency = <125000000>; | |
| 49 | 49 | }; |
| 50 | 50 | |
| 51 | 51 | &mmuart1 { |
| @@ -141,7 +141,7 @@ · 140 unmodified lines | ||
| 141 | 141 | }; |
| 142 | 142 | }; |
| 143 | 143 | |
| 144 | − refclk: msspllclk { | |
| 144 | + refclk: mssrefclk { | |
| 145 | 145 | compatible = "fixed-clock"; |
| 146 | 146 | #clock-cells = <0>; |
| 147 | 147 | }; |
| @@ -190,7 +190,7 @@ · 42 unmodified lines | ||
| 190 | 190 | |
| 191 | 191 | clkcfg: clkcfg@20002000 { |
| 192 | 192 | compatible = "microchip,mpfs-clkcfg"; |
| 193 | − reg = <0x0 0x20002000 0x0 0x1000>; | |
| 193 | + reg = <0x0 0x20002000 0x0 0x1000>, <0x0 0x3E001000 0x0 0x1000>; | |
| 194 | 194 | clocks = <&refclk>; |
| 195 | 195 | #clock-cells = <1>; |
| 196 | 196 | }; |
| @@ -393,8 +393,8 @@ · 196 unmodified lines | ||
| 393 | 393 | reg = <0x0 0x20124000 0x0 0x1000>; |
| 394 | 394 | interrupt-parent = <&plic>; |
| 395 | 395 | interrupts = <80>, <81>; |
| 396 | − clocks = <&clkcfg CLK_RTC>; | |
| 397 | − clock-names = "rtc"; | |
| 396 | + clocks = <&clkcfg CLK_RTC>, <&clkcfg CLK_RTCREF>; | |
| 397 | + clock-names = "rtc", "rtcref"; | |
| 398 | 398 | status = "disabled"; |
| 399 | 399 | }; |
| 400 | 400 | |
| @@ -424,7 +424,7 @@ · 23 unmodified lines | ||
| 424 | 424 | <0 0 0 3 &pcie_intc 2>, |
| 425 | 425 | <0 0 0 4 &pcie_intc 3>; |
| 426 | 426 | interrupt-map-mask = <0 0 0 7>; |
| 427 | − clocks = <&clkcfg CLK_FIC0>, <&clkcfg CLK_FIC1>, <&clkcfg CLK_FIC3>; | |
| 427 | + clocks = <&fabric_clk1>, <&fabric_clk1>, <&fabric_clk3>; | |
| 428 | 428 | clock-names = "fic0", "fic1", "fic3"; |
| 429 | 429 | ranges = <0x3000000 0x0 0x8000000 0x20 0x8000000 0x0 0x80000000>; |
| 430 | 430 | msi-parent = <&pcie>; |
| @@ -101,6 +101,7 @@ CONFIG_VIRTIO_BALLOON=y · 100 unmodified lines | ||
| 101 | 101 | CONFIG_VIRTIO_INPUT=y |
| 102 | 102 | CONFIG_VIRTIO_MMIO=y |
| 103 | 103 | CONFIG_RPMSG_CHAR=y |
| 104 | +CONFIG_RPMSG_CTRL=y | |
| 104 | 105 | CONFIG_RPMSG_VIRTIO=y |
| 105 | 106 | CONFIG_EXT4_FS=y |
| 106 | 107 | CONFIG_EXT4_FS_POSIX_ACL=y |
| @@ -93,6 +93,7 @@ CONFIG_VIRTIO_BALLOON=y · 92 unmodified lines | ||
| 93 | 93 | CONFIG_VIRTIO_INPUT=y |
| 94 | 94 | CONFIG_VIRTIO_MMIO=y |
| 95 | 95 | CONFIG_RPMSG_CHAR=y |
| 96 | +CONFIG_RPMSG_CTRL=y | |
| 96 | 97 | CONFIG_RPMSG_VIRTIO=y |
| 97 | 98 | CONFIG_EXT4_FS=y |
| 98 | 99 | CONFIG_EXT4_FS_POSIX_ACL=y |
| @@ -104,7 +104,7 @@ static int patch_text_cb(void *data) · 103 unmodified lines | ||
| 104 | 104 | struct patch_insn *patch = data; |
| 105 | 105 | int ret = 0; |
| 106 | 106 | |
| 107 | − if (atomic_inc_return(&patch->cpu_count) == 1) { | |
| 107 | + if (atomic_inc_return(&patch->cpu_count) == num_online_cpus()) { | |
| 108 | 108 | ret = |
| 109 | 109 | patch_text_nosync(patch->addr, &patch->insn, |
| 110 | 110 | GET_INSN_LENGTH(patch->insn)); |
| @@ -83,7 +83,7 @@ void kvm_riscv_vcpu_sbi_forward(struct kvm_vcpu *vcpu, struct kvm_run *run) · 82 unmodified lines | ||
| 83 | 83 | |
| 84 | 84 | void kvm_riscv_vcpu_sbi_system_reset(struct kvm_vcpu *vcpu, |
| 85 | 85 | struct kvm_run *run, |
| 86 | − u32 type, u64 flags) | |
| 86 | + u32 type, u64 reason) | |
| 87 | 87 | { |
| 88 | 88 | unsigned long i; |
| 89 | 89 | struct kvm_vcpu *tmp; |
| @@ -94,7 +94,8 @@ void kvm_riscv_vcpu_sbi_system_reset(struct kvm_vcpu *vcpu, · 4 unmodified lines | ||
| 94 | 94 | |
| 95 | 95 | memset(&run->system_event, 0, sizeof(run->system_event)); |
| 96 | 96 | run->system_event.type = type; |
| 97 | − run->system_event.flags = flags; | |
| 97 | + run->system_event.ndata = 1; | |
| 98 | + run->system_event.data[0] = reason; | |
| 98 | 99 | run->exit_reason = KVM_EXIT_SYSTEM_EVENT; |
| 99 | 100 | } |
| 100 | 101 | |
| @@ -208,8 +208,25 @@ static void __init setup_bootmem(void) · 207 unmodified lines | ||
| 208 | 208 | * early_init_fdt_reserve_self() since __pa() does |
| 209 | 209 | * not work for DTB pointers that are fixmap addresses |
| 210 | 210 | */ |
| 211 | − if (!IS_ENABLED(CONFIG_BUILTIN_DTB)) | |
| 212 | − memblock_reserve(dtb_early_pa, fdt_totalsize(dtb_early_va)); | |
| 211 | + if (!IS_ENABLED(CONFIG_BUILTIN_DTB)) { | |
| 212 | + /* | |
| 213 | + * In case the DTB is not located in a memory region we won't | |
| 214 | + * be able to locate it later on via the linear mapping and | |
| 215 | + * get a segfault when accessing it via __va(dtb_early_pa). | |
| 216 | + * To avoid this situation copy DTB to a memory region. | |
| 217 | + * Note that memblock_phys_alloc will also reserve DTB region. | |
| 218 | + */ | |
| 219 | + if (!memblock_is_memory(dtb_early_pa)) { | |
| 220 | + size_t fdt_size = fdt_totalsize(dtb_early_va); | |
| 221 | + phys_addr_t new_dtb_early_pa = memblock_phys_alloc(fdt_size, PAGE_SIZE); | |
| 222 | + void *new_dtb_early_va = early_memremap(new_dtb_early_pa, fdt_size); | |
| 223 | + | |
| 224 | + memcpy(new_dtb_early_va, dtb_early_va, fdt_size); | |
| 225 | + early_memunmap(new_dtb_early_va, fdt_size); | |
| 226 | + _dtb_early_pa = new_dtb_early_pa; | |
| 227 | + } else | |
| 228 | + memblock_reserve(dtb_early_pa, fdt_totalsize(dtb_early_va)); | |
| 229 | + } | |
| 213 | 230 | |
| 214 | 231 | early_init_fdt_scan_reserved_mem(); |
| 215 | 232 | dma_contiguous_reserve(dma32_phys_limit); |
| @@ -30,6 +30,16 @@ KBUILD_CFLAGS_DECOMPRESSOR += -fno-stack-protector · 29 unmodified lines | ||
| 30 | 30 | KBUILD_CFLAGS_DECOMPRESSOR += $(call cc-disable-warning, address-of-packed-member) |
| 31 | 31 | KBUILD_CFLAGS_DECOMPRESSOR += $(if $(CONFIG_DEBUG_INFO),-g) |
| 32 | 32 | KBUILD_CFLAGS_DECOMPRESSOR += $(if $(CONFIG_DEBUG_INFO_DWARF4), $(call cc-option, -gdwarf-4,)) |
| 33 | + | |
| 34 | +ifdef CONFIG_CC_IS_GCC | |
| 35 | + ifeq ($(call cc-ifversion, -ge, 1200, y), y) | |
| 36 | + ifeq ($(call cc-ifversion, -lt, 1300, y), y) | |
| 37 | + KBUILD_CFLAGS += $(call cc-disable-warning, array-bounds) | |
| 38 | + KBUILD_CFLAGS_DECOMPRESSOR += $(call cc-disable-warning, array-bounds) | |
| 39 | + endif | |
| 40 | + endif | |
| 41 | +endif | |
| 42 | + | |
| 33 | 43 | UTS_MACHINE := s390x |
| 34 | 44 | STACK_SIZE := $(if $(CONFIG_KASAN),65536,16384) |
| 35 | 45 | CHECKFLAGS += -D__s390__ -D__s390x__ |
| @@ -2384,7 +2384,16 @@ static int kvm_s390_vm_mem_op(struct kvm *kvm, struct kvm_s390_mem_op *mop) · 2383 unmodified lines | ||
| 2384 | 2384 | return -EINVAL; |
| 2385 | 2385 | if (mop->size > MEM_OP_MAX_SIZE) |
| 2386 | 2386 | return -E2BIG; |
| 2387 | − if (kvm_s390_pv_is_protected(kvm)) | |
| 2387 | + /* | |
| 2388 | + * This is technically a heuristic only, if the kvm->lock is not | |
| 2389 | + * taken, it is not guaranteed that the vm is/remains non-protected. | |
| 2390 | + * This is ok from a kernel perspective, wrongdoing is detected | |
| 2391 | + * on the access, -EFAULT is returned and the vm may crash the | |
| 2392 | + * next time it accesses the memory in question. | |
| 2393 | + * There is no sane usecase to do switching and a memop on two | |
| 2394 | + * different CPUs at the same time. | |
| 2395 | + */ | |
| 2396 | + if (kvm_s390_pv_get_handle(kvm)) | |
| 2388 | 2397 | return -EINVAL; |
| 2389 | 2398 | if (mop->flags & KVM_S390_MEMOP_F_SKEY_PROTECTION) { |
| 2390 | 2399 | if (access_key_invalid(mop->key)) |
| @@ -1183,6 +1183,7 @@ EXPORT_SYMBOL_GPL(gmap_read_table); · 1182 unmodified lines | ||
| 1183 | 1183 | static inline void gmap_insert_rmap(struct gmap *sg, unsigned long vmaddr, |
| 1184 | 1184 | struct gmap_rmap *rmap) |
| 1185 | 1185 | { |
| 1186 | + struct gmap_rmap *temp; | |
| 1186 | 1187 | void __rcu **slot; |
| 1187 | 1188 | |
| 1188 | 1189 | BUG_ON(!gmap_is_shadow(sg)); |
| @@ -1190,6 +1191,12 @@ static inline void gmap_insert_rmap(struct gmap *sg, unsigned long vmaddr, · 1 unmodified line | ||
| 1190 | 1191 | if (slot) { |
| 1191 | 1192 | rmap->next = radix_tree_deref_slot_protected(slot, |
| 1192 | 1193 | &sg->guest_table_lock); |
| 1194 | + for (temp = rmap->next; temp; temp = temp->next) { | |
| 1195 | + if (temp->raddr == rmap->raddr) { | |
| 1196 | + kfree(rmap); | |
| 1197 | + return; | |
| 1198 | + } | |
| 1199 | + } | |
| 1193 | 1200 | radix_tree_replace_slot(&sg->host_to_rmap, slot, rmap); |
| 1194 | 1201 | } else { |
| 1195 | 1202 | rmap->next = NULL; |
| @@ -1866,7 +1866,7 @@ config X86_KERNEL_IBT · 1865 unmodified lines | ||
| 1866 | 1866 | code with them to make this happen. |
| 1867 | 1867 | |
| 1868 | 1868 | In addition to building the kernel with IBT, seal all functions that |
| 1869 | − are not indirect call targets, avoiding them ever becomming one. | |
| 1869 | + are not indirect call targets, avoiding them ever becoming one. | |
| 1870 | 1870 | |
| 1871 | 1871 | This requires LTO like objtool runs and will slow down the build. It |
| 1872 | 1872 | does significantly reduce the number of ENDBR instructions in the |
| @@ -337,6 +337,9 @@ SYM_CODE_END(ret_from_fork) · 336 unmodified lines | ||
| 337 | 337 | |
| 338 | 338 | call \cfunc |
| 339 | 339 | |
| 340 | + /* For some configurations \cfunc ends up being a noreturn. */ | |
| 341 | + REACHABLE | |
| 342 | + | |
| 340 | 343 | jmp error_return |
| 341 | 344 | .endm |
| 342 | 345 | |
| @@ -26,6 +26,7 @@ · 25 unmodified lines | ||
| 26 | 26 | * _G - parts with extra graphics on |
| 27 | 27 | * _X - regular server parts |
| 28 | 28 | * _D - micro server parts |
| 29 | + * _N,_P - other mobile parts | |
| 29 | 30 | * |
| 30 | 31 | * Historical OPTDIFFs: |
| 31 | 32 | * |
| @@ -107,8 +108,10 @@ · 75 unmodified lines | ||
| 107 | 108 | |
| 108 | 109 | #define INTEL_FAM6_ALDERLAKE 0x97 /* Golden Cove / Gracemont */ |
| 109 | 110 | #define INTEL_FAM6_ALDERLAKE_L 0x9A /* Golden Cove / Gracemont */ |
| 111 | +#define INTEL_FAM6_ALDERLAKE_N 0xBE | |
| 110 | 112 | |
| 111 | 113 | #define INTEL_FAM6_RAPTORLAKE 0xB7 |
| 114 | +#define INTEL_FAM6_RAPTORLAKE_P 0xBA | |
| 112 | 115 | |
| 113 | 116 | /* "Small Core" Processors (Atom) */ |
| 114 | 117 | |
| @@ -131,10 +131,12 @@ extern void __init load_ucode_bsp(void); · 130 unmodified lines | ||
| 131 | 131 | extern void load_ucode_ap(void); |
| 132 | 132 | void reload_early_microcode(void); |
| 133 | 133 | extern bool initrd_gone; |
| 134 | +void microcode_bsp_resume(void); | |
| 134 | 135 | #else |
| 135 | 136 | static inline void __init load_ucode_bsp(void) { } |
| 136 | 137 | static inline void load_ucode_ap(void) { } |
| 137 | 138 | static inline void reload_early_microcode(void) { } |
| 139 | +static inline void microcode_bsp_resume(void) { } | |
| 138 | 140 | #endif |
| 139 | 141 | |
| 140 | 142 | #endif /* _ASM_X86_MICROCODE_H */ |
| @@ -559,10 +559,6 @@ static inline void update_page_count(int level, unsigned long pages) { } · 558 unmodified lines | ||
| 559 | 559 | extern pte_t *lookup_address(unsigned long address, unsigned int *level); |
| 560 | 560 | extern pte_t *lookup_address_in_pgd(pgd_t *pgd, unsigned long address, |
| 561 | 561 | unsigned int *level); |
| 562 | − | |
| 563 | −struct mm_struct; | |
| 564 | −extern pte_t *lookup_address_in_mm(struct mm_struct *mm, unsigned long address, | |
| 565 | − unsigned int *level); | |
| 566 | 562 | extern pmd_t *lookup_pmd_address(unsigned long address); |
| 567 | 563 | extern phys_addr_t slow_virt_to_phys(void *__address); |
| 568 | 564 | extern int __init kernel_map_pages_in_pgd(pgd_t *pgd, u64 pfn, |
| @@ -26,6 +26,7 @@ · 25 unmodified lines | ||
| 26 | 26 | ".align 4 \n" \ |
| 27 | 27 | ".globl " STATIC_CALL_TRAMP_STR(name) " \n" \ |
| 28 | 28 | STATIC_CALL_TRAMP_STR(name) ": \n" \ |
| 29 | + ANNOTATE_NOENDBR \ | |
| 29 | 30 | insns " \n" \ |
| 30 | 31 | ".byte 0x53, 0x43, 0x54 \n" \ |
| 31 | 32 | ".type " STATIC_CALL_TRAMP_STR(name) ", @function \n" \ |
| @@ -758,9 +758,9 @@ static struct subsys_interface mc_cpu_interface = { · 757 unmodified lines | ||
| 758 | 758 | }; |
| 759 | 759 | |
| 760 | 760 | /** |
| 761 | − * mc_bp_resume - Update boot CPU microcode during resume. | |
| 761 | + * microcode_bsp_resume - Update boot CPU microcode during resume. | |
| 762 | 762 | */ |
| 763 | −static void mc_bp_resume(void) | |
| 763 | +void microcode_bsp_resume(void) | |
| 764 | 764 | { |
| 765 | 765 | int cpu = smp_processor_id(); |
| 766 | 766 | struct ucode_cpu_info *uci = ucode_cpu_info + cpu; |
| @@ -772,7 +772,7 @@ static void mc_bp_resume(void) · 5 unmodified lines | ||
| 772 | 772 | } |
| 773 | 773 | |
| 774 | 774 | static struct syscore_ops mc_syscore_ops = { |
| 775 | − .resume = mc_bp_resume, | |
| 775 | + .resume = microcode_bsp_resume, | |
| 776 | 776 | }; |
| 777 | 777 | |
| 778 | 778 | static int mc_cpu_starting(unsigned int cpu) |
| @@ -41,17 +41,7 @@ struct fpu_state_config fpu_user_cfg __ro_after_init; · 40 unmodified lines | ||
| 41 | 41 | */ |
| 42 | 42 | struct fpstate init_fpstate __ro_after_init; |
| 43 | 43 | |
| 44 | −/* | |
| 45 | − * Track whether the kernel is using the FPU state | |
| 46 | − * currently. | |
| 47 | − * | |
| 48 | − * This flag is used: | |
| 49 | − * | |
| 50 | − * - by IRQ context code to potentially use the FPU | |
| 51 | − * if it's unused. | |
| 52 | − * | |
| 53 | − * - to debug kernel_fpu_begin()/end() correctness | |
| 54 | − */ | |
| 44 | +/* Track in-kernel FPU usage */ | |
| 55 | 45 | static DEFINE_PER_CPU(bool, in_kernel_fpu); |
| 56 | 46 | |
| 57 | 47 | /* |
| @@ -59,42 +49,37 @@ static DEFINE_PER_CPU(bool, in_kernel_fpu); · 1 unmodified line | ||
| 59 | 49 | */ |
| 60 | 50 | DEFINE_PER_CPU(struct fpu *, fpu_fpregs_owner_ctx); |
| 61 | 51 | |
| 62 | −static bool kernel_fpu_disabled(void) | |
| 63 | −{ | |
| 64 | − return this_cpu_read(in_kernel_fpu); | |
| 65 | −} | |
| 66 | − | |
| 67 | −static bool interrupted_kernel_fpu_idle(void) | |
| 68 | −{ | |
| 69 | − return !kernel_fpu_disabled(); | |
| 70 | −} | |
| 71 | − | |
| 72 | −/* | |
| 73 | − * Were we in user mode (or vm86 mode) when we were | |
| 74 | − * interrupted? | |
| 75 | − * | |
| 76 | − * Doing kernel_fpu_begin/end() is ok if we are running | |
| 77 | − * in an interrupt context from user mode - we'll just | |
| 78 | − * save the FPU state as required. | |
| 79 | − */ | |
| 80 | −static bool interrupted_user_mode(void) | |
| 81 | −{ | |
| 82 | − struct pt_regs *regs = get_irq_regs(); | |
| 83 | − return regs && user_mode(regs); | |
| 84 | −} | |
| 85 | − | |
| 86 | 52 | /* |
| 87 | 53 | * Can we use the FPU in kernel mode with the |
| 88 | 54 | * whole "kernel_fpu_begin/end()" sequence? |
| 89 | − * | |
| 90 | − * It's always ok in process context (ie "not interrupt") | |
| 91 | − * but it is sometimes ok even from an irq. | |
| 92 | 55 | */ |
| 93 | 56 | bool irq_fpu_usable(void) |
| 94 | 57 | { |
| 95 | − return !in_interrupt() || | |
| 96 | − interrupted_user_mode() || | |
| 97 | − interrupted_kernel_fpu_idle(); | |
| 58 | + if (WARN_ON_ONCE(in_nmi())) | |
| 59 | + return false; | |
| 60 | + | |
| 61 | + /* In kernel FPU usage already active? */ | |
| 62 | + if (this_cpu_read(in_kernel_fpu)) | |
| 63 | + return false; | |
| 64 | + | |
| 65 | + /* | |
| 66 | + * When not in NMI or hard interrupt context, FPU can be used in: | |
| 67 | + * | |
| 68 | + * - Task context except from within fpregs_lock()'ed critical | |
| 69 | + * regions. | |
| 70 | + * | |
| 71 | + * - Soft interrupt processing context which cannot happen | |
| 72 | + * while in a fpregs_lock()'ed critical region. | |
| 73 | + */ | |
| 74 | + if (!in_hardirq()) | |
| 75 | + return true; | |
| 76 | + | |
| 77 | + /* | |
| 78 | + * In hard interrupt context it's safe when soft interrupts | |
| 79 | + * are enabled, which means the interrupt did not hit in | |
| 80 | + * a fpregs_lock()'ed critical region. | |
| 81 | + */ | |
| 82 | + return !softirq_count(); | |
| 98 | 83 | } |
| 99 | 84 | EXPORT_SYMBOL(irq_fpu_usable); |
| 100 | 85 | |
| @@ -339,11 +339,11 @@ static bool stack_access_ok(struct unwind_state *state, unsigned long _addr, · 338 unmodified lines | ||
| 339 | 339 | struct stack_info *info = &state->stack_info; |
| 340 | 340 | void *addr = (void *)_addr; |
| 341 | 341 | |
| 342 | − if (!on_stack(info, addr, len) && | |
| 343 | − (get_stack_info(addr, state->task, info, &state->stack_mask))) | |
| 344 | − return false; | |
| 342 | + if (on_stack(info, addr, len)) | |
| 343 | + return true; | |
| 345 | 344 | |
| 346 | − return true; | |
| 345 | + return !get_stack_info(addr, state->task, info, &state->stack_mask) && | |
| 346 | + on_stack(info, addr, len); | |
| 347 | 347 | } |
| 348 | 348 | |
| 349 | 349 | static bool deref_stack_reg(struct unwind_state *state, unsigned long addr, |
| @@ -887,6 +887,11 @@ static inline int __do_cpuid_func(struct kvm_cpuid_array *array, u32 function) · 886 unmodified lines | ||
| 887 | 887 | union cpuid10_eax eax; |
| 888 | 888 | union cpuid10_edx edx; |
| 889 | 889 | |
| 890 | + if (!static_cpu_has(X86_FEATURE_ARCH_PERFMON)) { | |
| 891 | + entry->eax = entry->ebx = entry->ecx = entry->edx = 0; | |
| 892 | + break; | |
| 893 | + } | |
| 894 | + | |
| 890 | 895 | perf_get_x86_pmu_capability(&cap); |
| 891 | 896 | |
| 892 | 897 | /* |
| @@ -1085,12 +1090,21 @@ static inline int __do_cpuid_func(struct kvm_cpuid_array *array, u32 function) · 192 unmodified lines | ||
| 1085 | 1090 | case 0x80000000: |
| 1086 | 1091 | entry->eax = min(entry->eax, 0x80000021); |
| 1087 | 1092 | /* |
| 1088 | − * Serializing LFENCE is reported in a multitude of ways, | |
| 1089 | − * and NullSegClearsBase is not reported in CPUID on Zen2; | |
| 1090 | − * help userspace by providing the CPUID leaf ourselves. | |
| 1093 | + * Serializing LFENCE is reported in a multitude of ways, and | |
| 1094 | + * NullSegClearsBase is not reported in CPUID on Zen2; help | |
| 1095 | + * userspace by providing the CPUID leaf ourselves. | |
| 1096 | + * | |
| 1097 | + * However, only do it if the host has CPUID leaf 0x8000001d. | |
| 1098 | + * QEMU thinks that it can query the host blindly for that | |
| 1099 | + * CPUID leaf if KVM reports that it supports 0x8000001d or | |
| 1100 | + * above. The processor merrily returns values from the | |
| 1101 | + * highest Intel leaf which QEMU tries to use as the guest's | |
| 1102 | + * 0x8000001d. Even worse, this can result in an infinite | |
| 1103 | + * loop if said highest leaf has no subleaves indexed by ECX. | |
| 1091 | 1104 | */ |
| 1092 | − if (static_cpu_has(X86_FEATURE_LFENCE_RDTSC) | |
| 1093 | − || !static_cpu_has_bug(X86_BUG_NULL_SEG)) | |
| 1105 | + if (entry->eax >= 0x8000001d && | |
| 1106 | + (static_cpu_has(X86_FEATURE_LFENCE_RDTSC) | |
| 1107 | + || !static_cpu_has_bug(X86_BUG_NULL_SEG))) | |
| 1094 | 1108 | entry->eax = max(entry->eax, 0x80000021); |
| 1095 | 1109 | break; |
| 1096 | 1110 | case 0x80000001: |
| @@ -65,6 +65,30 @@ static __always_inline u64 rsvd_bits(int s, int e) · 64 unmodified lines | ||
| 65 | 65 | return ((2ULL << (e - s)) - 1) << s; |
| 66 | 66 | } |
| 67 | 67 | |
| 68 | +/* | |
| 69 | + * The number of non-reserved physical address bits irrespective of features | |
| 70 | + * that repurpose legal bits, e.g. MKTME. | |
| 71 | + */ | |
| 72 | +extern u8 __read_mostly shadow_phys_bits; | |
| 73 | + | |
| 74 | +static inline gfn_t kvm_mmu_max_gfn(void) | |
| 75 | +{ | |
| 76 | + /* | |
| 77 | + * Note that this uses the host MAXPHYADDR, not the guest's. | |
| 78 | + * EPT/NPT cannot support GPAs that would exceed host.MAXPHYADDR; | |
| 79 | + * assuming KVM is running on bare metal, guest accesses beyond | |
| 80 | + * host.MAXPHYADDR will hit a #PF(RSVD) and never cause a vmexit | |
| 81 | + * (either EPT Violation/Misconfig or #NPF), and so KVM will never | |
| 82 | + * install a SPTE for such addresses. If KVM is running as a VM | |
| 83 | + * itself, on the other hand, it might see a MAXPHYADDR that is less | |
| 84 | + * than hardware's real MAXPHYADDR. Using the host MAXPHYADDR | |
| 85 | + * disallows such SPTEs entirely and simplifies the TDP MMU. | |
| 86 | + */ | |
| 87 | + int max_gpa_bits = likely(tdp_enabled) ? shadow_phys_bits : 52; | |
| 88 | + | |
| 89 | + return (1ULL << (max_gpa_bits - PAGE_SHIFT)) - 1; | |
| 90 | +} | |
| 91 | + | |
| 68 | 92 | void kvm_mmu_set_mmio_spte_mask(u64 mmio_value, u64 mmio_mask, u64 access_mask); |
| 69 | 93 | void kvm_mmu_set_ept_masks(bool has_ad_bits, bool has_exec_only); |
| 70 | 94 | |
| @@ -473,30 +473,6 @@ retry: · 472 unmodified lines | ||
| 473 | 473 | } |
| 474 | 474 | #endif |
| 475 | 475 | |
| 476 | −static bool spte_has_volatile_bits(u64 spte) | |
| 477 | −{ | |
| 478 | − if (!is_shadow_present_pte(spte)) | |
| 479 | − return false; | |
| 480 | − | |
| 481 | − /* | |
| 482 | − * Always atomically update spte if it can be updated | |
| 483 | − * out of mmu-lock, it can ensure dirty bit is not lost, | |
| 484 | − * also, it can help us to get a stable is_writable_pte() | |
| 485 | − * to ensure tlb flush is not missed. | |
| 486 | − */ | |
| 487 | − if (spte_can_locklessly_be_made_writable(spte) || | |
| 488 | − is_access_track_spte(spte)) | |
| 489 | − return true; | |
| 490 | − | |
| 491 | − if (spte_ad_enabled(spte)) { | |
| 492 | − if ((spte & shadow_accessed_mask) == 0 || | |
| 493 | − (is_writable_pte(spte) && (spte & shadow_dirty_mask) == 0)) | |
| 494 | − return true; | |
| 495 | − } | |
| 496 | − | |
| 497 | − return false; | |
| 498 | −} | |
| 499 | − | |
| 500 | 476 | /* Rules for using mmu_spte_set: |
| 501 | 477 | * Set the sptep from nonpresent to present. |
| 502 | 478 | * Note: the sptep being assigned *must* be either not present |
| @@ -557,7 +533,7 @@ static bool mmu_spte_update(u64 *sptep, u64 new_spte) · 54 unmodified lines | ||
| 557 | 533 | * we always atomically update it, see the comments in |
| 558 | 534 | * spte_has_volatile_bits(). |
| 559 | 535 | */ |
| 560 | − if (spte_can_locklessly_be_made_writable(old_spte) && | |
| 536 | + if (is_mmu_writable_spte(old_spte) && | |
| 561 | 537 | !is_writable_pte(new_spte)) |
| 562 | 538 | flush = true; |
| 563 | 539 | |
| @@ -591,7 +567,8 @@ static int mmu_spte_clear_track_bits(struct kvm *kvm, u64 *sptep) · 27 unmodified lines | ||
| 591 | 567 | u64 old_spte = *sptep; |
| 592 | 568 | int level = sptep_to_sp(sptep)->role.level; |
| 593 | 569 | |
| 594 | − if (!spte_has_volatile_bits(old_spte)) | |
| 570 | + if (!is_shadow_present_pte(old_spte) || | |
| 571 | + !spte_has_volatile_bits(old_spte)) | |
| 595 | 572 | __update_clear_spte_fast(sptep, 0ull); |
| 596 | 573 | else |
| 597 | 574 | old_spte = __update_clear_spte_slow(sptep, 0ull); |
| @@ -1187,7 +1164,7 @@ static bool spte_write_protect(u64 *sptep, bool pt_protect) · 589 unmodified lines | ||
| 1187 | 1164 | u64 spte = *sptep; |
| 1188 | 1165 | |
| 1189 | 1166 | if (!is_writable_pte(spte) && |
| 1190 | − !(pt_protect && spte_can_locklessly_be_made_writable(spte))) | |
| 1167 | + !(pt_protect && is_mmu_writable_spte(spte))) | |
| 1191 | 1168 | return false; |
| 1192 | 1169 | |
| 1193 | 1170 | rmap_printk("spte %p %llx\n", sptep, *sptep); |
| @@ -2804,8 +2781,12 @@ static int host_pfn_mapping_level(struct kvm *kvm, gfn_t gfn, kvm_pfn_t pfn, · 1610 unmodified lines | ||
| 2804 | 2781 | const struct kvm_memory_slot *slot) |
| 2805 | 2782 | { |
| 2806 | 2783 | unsigned long hva; |
| 2807 | − pte_t *pte; | |
| 2808 | − int level; | |
| 2784 | + unsigned long flags; | |
| 2785 | + int level = PG_LEVEL_4K; | |
| 2786 | + pgd_t pgd; | |
| 2787 | + p4d_t p4d; | |
| 2788 | + pud_t pud; | |
| 2789 | + pmd_t pmd; | |
| 2809 | 2790 | |
| 2810 | 2791 | if (!PageCompound(pfn_to_page(pfn)) && !kvm_is_zone_device_pfn(pfn)) |
| 2811 | 2792 | return PG_LEVEL_4K; |
| @@ -2820,10 +2801,43 @@ static int host_pfn_mapping_level(struct kvm *kvm, gfn_t gfn, kvm_pfn_t pfn, · 8 unmodified lines | ||
| 2820 | 2801 | */ |
| 2821 | 2802 | hva = __gfn_to_hva_memslot(slot, gfn); |
| 2822 | 2803 | |
| 2823 | − pte = lookup_address_in_mm(kvm->mm, hva, &level); | |
| 2824 | − if (unlikely(!pte)) | |
| 2825 | − return PG_LEVEL_4K; | |
| 2804 | + /* | |
| 2805 | + * Lookup the mapping level in the current mm. The information | |
| 2806 | + * may become stale soon, but it is safe to use as long as | |
| 2807 | + * 1) mmu_notifier_retry was checked after taking mmu_lock, and | |
| 2808 | + * 2) mmu_lock is taken now. | |
| 2809 | + * | |
| 2810 | + * We still need to disable IRQs to prevent concurrent tear down | |
| 2811 | + * of page tables. | |
| 2812 | + */ | |
| 2813 | + local_irq_save(flags); | |
| 2814 | + | |
| 2815 | + pgd = READ_ONCE(*pgd_offset(kvm->mm, hva)); | |
| 2816 | + if (pgd_none(pgd)) | |
| 2817 | + goto out; | |
| 2818 | + | |
| 2819 | + p4d = READ_ONCE(*p4d_offset(&pgd, hva)); | |
| 2820 | + if (p4d_none(p4d) || !p4d_present(p4d)) | |
| 2821 | + goto out; | |
| 2822 | + | |
| 2823 | + pud = READ_ONCE(*pud_offset(&p4d, hva)); | |
| 2824 | + if (pud_none(pud) || !pud_present(pud)) | |
| 2825 | + goto out; | |
| 2826 | + | |
| 2827 | + if (pud_large(pud)) { | |
| 2828 | + level = PG_LEVEL_1G; | |
| 2829 | + goto out; | |
| 2830 | + } | |
| 2826 | 2831 | |
| 2832 | + pmd = READ_ONCE(*pmd_offset(&pud, hva)); | |
| 2833 | + if (pmd_none(pmd) || !pmd_present(pmd)) | |
| 2834 | + goto out; | |
| 2835 | + | |
| 2836 | + if (pmd_large(pmd)) | |
| 2837 | + level = PG_LEVEL_2M; | |
| 2838 | + | |
| 2839 | +out: | |
| 2840 | + local_irq_restore(flags); | |
| 2827 | 2841 | return level; |
| 2828 | 2842 | } |
| 2829 | 2843 | |
| @@ -2992,9 +3006,15 @@ static bool handle_abnormal_pfn(struct kvm_vcpu *vcpu, struct kvm_page_fault *fa · 162 unmodified lines | ||
| 2992 | 3006 | /* |
| 2993 | 3007 | * If MMIO caching is disabled, emulate immediately without |
| 2994 | 3008 | * touching the shadow page tables as attempting to install an |
| 2995 | − * MMIO SPTE will just be an expensive nop. | |
| 3009 | + * MMIO SPTE will just be an expensive nop. Do not cache MMIO | |
| 3010 | + * whose gfn is greater than host.MAXPHYADDR, any guest that | |
| 3011 | + * generates such gfns is running nested and is being tricked | |
| 3012 | + * by L0 userspace (you can observe gfn > L1.MAXPHYADDR if | |
| 3013 | + * and only if L1's MAXPHYADDR is inaccurate with respect to | |
| 3014 | + * the hardware's). | |
| 2996 | 3015 | */ |
| 2997 | − if (unlikely(!shadow_mmio_value)) { | |
| 3016 | + if (unlikely(!shadow_mmio_value) || | |
| 3017 | + unlikely(fault->gfn > kvm_mmu_max_gfn())) { | |
| 2998 | 3018 | *ret_val = RET_PF_EMULATE; |
| 2999 | 3019 | return true; |
| 3000 | 3020 | } |
| @@ -3153,8 +3173,7 @@ static int fast_page_fault(struct kvm_vcpu *vcpu, struct kvm_page_fault *fault) · 152 unmodified lines | ||
| 3153 | 3173 | * be removed in the fast path only if the SPTE was |
| 3154 | 3174 | * write-protected for dirty-logging or access tracking. |
| 3155 | 3175 | */ |
| 3156 | − if (fault->write && | |
| 3157 | − spte_can_locklessly_be_made_writable(spte)) { | |
| 3176 | + if (fault->write && is_mmu_writable_spte(spte)) { | |
| 3158 | 3177 | new_spte |= PT_WRITABLE_MASK; |
| 3159 | 3178 | |
| 3160 | 3179 | /* |
| @@ -90,6 +90,34 @@ static bool kvm_is_mmio_pfn(kvm_pfn_t pfn) · 89 unmodified lines | ||
| 90 | 90 | E820_TYPE_RAM); |
| 91 | 91 | } |
| 92 | 92 | |
| 93 | +/* | |
| 94 | + * Returns true if the SPTE has bits that may be set without holding mmu_lock. | |
| 95 | + * The caller is responsible for checking if the SPTE is shadow-present, and | |
| 96 | + * for determining whether or not the caller cares about non-leaf SPTEs. | |
| 97 | + */ | |
| 98 | +bool spte_has_volatile_bits(u64 spte) | |
| 99 | +{ | |
| 100 | + /* | |
| 101 | + * Always atomically update spte if it can be updated | |
| 102 | + * out of mmu-lock, it can ensure dirty bit is not lost, | |
| 103 | + * also, it can help us to get a stable is_writable_pte() | |
| 104 | + * to ensure tlb flush is not missed. | |
| 105 | + */ | |
| 106 | + if (!is_writable_pte(spte) && is_mmu_writable_spte(spte)) | |
| 107 | + return true; | |
| 108 | + | |
| 109 | + if (is_access_track_spte(spte)) | |
| 110 | + return true; | |
| 111 | + | |
| 112 | + if (spte_ad_enabled(spte)) { | |
| 113 | + if (!(spte & shadow_accessed_mask) || | |
| 114 | + (is_writable_pte(spte) && !(spte & shadow_dirty_mask))) | |
| 115 | + return true; | |
| 116 | + } | |
| 117 | + | |
| 118 | + return false; | |
| 119 | +} | |
| 120 | + | |
| 93 | 121 | bool make_spte(struct kvm_vcpu *vcpu, struct kvm_mmu_page *sp, |
| 94 | 122 | const struct kvm_memory_slot *slot, |
| 95 | 123 | unsigned int pte_access, gfn_t gfn, kvm_pfn_t pfn, |
| @@ -201,12 +201,6 @@ static inline bool is_removed_spte(u64 spte) · 200 unmodified lines | ||
| 201 | 201 | */ |
| 202 | 202 | extern u64 __read_mostly shadow_nonpresent_or_rsvd_lower_gfn_mask; |
| 203 | 203 | |
| 204 | −/* | |
| 205 | − * The number of non-reserved physical address bits irrespective of features | |
| 206 | − * that repurpose legal bits, e.g. MKTME. | |
| 207 | − */ | |
| 208 | −extern u8 __read_mostly shadow_phys_bits; | |
| 209 | − | |
| 210 | 204 | static inline bool is_mmio_spte(u64 spte) |
| 211 | 205 | { |
| 212 | 206 | return (spte & shadow_mmio_mask) == shadow_mmio_value && |
| @@ -396,7 +390,7 @@ static inline void check_spte_writable_invariants(u64 spte) · 183 unmodified lines | ||
| 396 | 390 | "kvm: Writable SPTE is not MMU-writable: %llx", spte); |
| 397 | 391 | } |
| 398 | 392 | |
| 399 | −static inline bool spte_can_locklessly_be_made_writable(u64 spte) | |
| 393 | +static inline bool is_mmu_writable_spte(u64 spte) | |
| 400 | 394 | { |
| 401 | 395 | return spte & shadow_mmu_writable_mask; |
| 402 | 396 | } |
| @@ -410,6 +404,8 @@ static inline u64 get_mmio_spte_generation(u64 spte) · 7 unmodified lines | ||
| 410 | 404 | return gen; |
| 411 | 405 | } |
| 412 | 406 | |
| 407 | +bool spte_has_volatile_bits(u64 spte); | |
| 408 | + | |
| 413 | 409 | bool make_spte(struct kvm_vcpu *vcpu, struct kvm_mmu_page *sp, |
| 414 | 410 | const struct kvm_memory_slot *slot, |
| 415 | 411 | unsigned int pte_access, gfn_t gfn, kvm_pfn_t pfn, |
| @@ -6,6 +6,7 @@ · 5 unmodified lines | ||
| 6 | 6 | #include <linux/kvm_host.h> |
| 7 | 7 | |
| 8 | 8 | #include "mmu.h" |
| 9 | +#include "spte.h" | |
| 9 | 10 | |
| 10 | 11 | /* |
| 11 | 12 | * TDP MMU SPTEs are RCU protected to allow paging structures (non-leaf SPTEs) |
| @@ -17,9 +18,38 @@ static inline u64 kvm_tdp_mmu_read_spte(tdp_ptep_t sptep) · 5 unmodified lines | ||
| 17 | 18 | { |
| 18 | 19 | return READ_ONCE(*rcu_dereference(sptep)); |
| 19 | 20 | } |
| 20 | −static inline void kvm_tdp_mmu_write_spte(tdp_ptep_t sptep, u64 val) | |
| 21 | + | |
| 22 | +static inline u64 kvm_tdp_mmu_write_spte_atomic(tdp_ptep_t sptep, u64 new_spte) | |
| 23 | +{ | |
| 24 | + return xchg(rcu_dereference(sptep), new_spte); | |
| 25 | +} | |
| 26 | + | |
| 27 | +static inline void __kvm_tdp_mmu_write_spte(tdp_ptep_t sptep, u64 new_spte) | |
| 28 | +{ | |
| 29 | + WRITE_ONCE(*rcu_dereference(sptep), new_spte); | |
| 30 | +} | |
| 31 | + | |
| 32 | +static inline u64 kvm_tdp_mmu_write_spte(tdp_ptep_t sptep, u64 old_spte, | |
| 33 | + u64 new_spte, int level) | |
| 21 | 34 | { |
| 22 | − WRITE_ONCE(*rcu_dereference(sptep), val); | |
| 35 | + /* | |
| 36 | + * Atomically write the SPTE if it is a shadow-present, leaf SPTE with | |
| 37 | + * volatile bits, i.e. has bits that can be set outside of mmu_lock. | |
| 38 | + * The Writable bit can be set by KVM's fast page fault handler, and | |
| 39 | + * Accessed and Dirty bits can be set by the CPU. | |
| 40 | + * | |
| 41 | + * Note, non-leaf SPTEs do have Accessed bits and those bits are | |
| 42 | + * technically volatile, but KVM doesn't consume the Accessed bit of | |
| 43 | + * non-leaf SPTEs, i.e. KVM doesn't care if it clobbers the bit. This | |
| 44 | + * logic needs to be reassessed if KVM were to use non-leaf Accessed | |
| 45 | + * bits, e.g. to skip stepping down into child SPTEs when aging SPTEs. | |
| 46 | + */ | |
| 47 | + if (is_shadow_present_pte(old_spte) && is_last_spte(old_spte, level) && | |
| 48 | + spte_has_volatile_bits(old_spte)) | |
| 49 | + return kvm_tdp_mmu_write_spte_atomic(sptep, new_spte); | |
| 50 | + | |
| 51 | + __kvm_tdp_mmu_write_spte(sptep, new_spte); | |
| 52 | + return old_spte; | |
| 23 | 53 | } |
| 24 | 54 | |
| 25 | 55 | /* |
| @@ -426,9 +426,9 @@ static void handle_removed_pt(struct kvm *kvm, tdp_ptep_t pt, bool shared) · 425 unmodified lines | ||
| 426 | 426 | tdp_mmu_unlink_sp(kvm, sp, shared); |
| 427 | 427 | |
| 428 | 428 | for (i = 0; i < PT64_ENT_PER_PAGE; i++) { |
| 429 | − u64 *sptep = rcu_dereference(pt) + i; | |
| 429 | + tdp_ptep_t sptep = pt + i; | |
| 430 | 430 | gfn_t gfn = base_gfn + i * KVM_PAGES_PER_HPAGE(level); |
| 431 | − u64 old_child_spte; | |
| 431 | + u64 old_spte; | |
| 432 | 432 | |
| 433 | 433 | if (shared) { |
| 434 | 434 | /* |
| @@ -440,8 +440,8 @@ static void handle_removed_pt(struct kvm *kvm, tdp_ptep_t pt, bool shared) · 5 unmodified lines | ||
| 440 | 440 | * value to the removed SPTE value. |
| 441 | 441 | */ |
| 442 | 442 | for (;;) { |
| 443 | − old_child_spte = xchg(sptep, REMOVED_SPTE); | |
| 444 | − if (!is_removed_spte(old_child_spte)) | |
| 443 | + old_spte = kvm_tdp_mmu_write_spte_atomic(sptep, REMOVED_SPTE); | |
| 444 | + if (!is_removed_spte(old_spte)) | |
| 445 | 445 | break; |
| 446 | 446 | cpu_relax(); |
| 447 | 447 | } |
| @@ -455,23 +455,43 @@ static void handle_removed_pt(struct kvm *kvm, tdp_ptep_t pt, bool shared) · 7 unmodified lines | ||
| 455 | 455 | * are guarded by the memslots generation, not by being |
| 456 | 456 | * unreachable. |
| 457 | 457 | */ |
| 458 | − old_child_spte = READ_ONCE(*sptep); | |
| 459 | − if (!is_shadow_present_pte(old_child_spte)) | |
| 458 | + old_spte = kvm_tdp_mmu_read_spte(sptep); | |
| 459 | + if (!is_shadow_present_pte(old_spte)) | |
| 460 | 460 | continue; |
| 461 | 461 | |
| 462 | 462 | /* |
| 463 | − * Marking the SPTE as a removed SPTE is not | |
| 464 | − * strictly necessary here as the MMU lock will | |
| 465 | − * stop other threads from concurrently modifying | |
| 466 | − * this SPTE. Using the removed SPTE value keeps | |
| 467 | − * the two branches consistent and simplifies | |
| 468 | − * the function. | |
| 463 | + * Use the common helper instead of a raw WRITE_ONCE as | |
| 464 | + * the SPTE needs to be updated atomically if it can be | |
| 465 | + * modified by a different vCPU outside of mmu_lock. | |
| 466 | + * Even though the parent SPTE is !PRESENT, the TLB | |
| 467 | + * hasn't yet been flushed, and both Intel and AMD | |
| 468 | + * document that A/D assists can use upper-level PxE | |
| 469 | + * entries that are cached in the TLB, i.e. the CPU can | |
| 470 | + * still access the page and mark it dirty. | |
| 471 | + * | |
| 472 | + * No retry is needed in the atomic update path as the | |
| 473 | + * sole concern is dropping a Dirty bit, i.e. no other | |
| 474 | + * task can zap/remove the SPTE as mmu_lock is held for | |
| 475 | + * write. Marking the SPTE as a removed SPTE is not | |
| 476 | + * strictly necessary for the same reason, but using | |
| 477 | + * the remove SPTE value keeps the shared/exclusive | |
| 478 | + * paths consistent and allows the handle_changed_spte() | |
| 479 | + * call below to hardcode the new value to REMOVED_SPTE. | |
| 480 | + * | |
| 481 | + * Note, even though dropping a Dirty bit is the only | |
| 482 | + * scenario where a non-atomic update could result in a | |
| 483 | + * functional bug, simply checking the Dirty bit isn't | |
| 484 | + * sufficient as a fast page fault could read the upper | |
| 485 | + * level SPTE before it is zapped, and then make this | |
| 486 | + * target SPTE writable, resume the guest, and set the | |
| 487 | + * Dirty bit between reading the SPTE above and writing | |
| 488 | + * it here. | |
| 469 | 489 | */ |
| 470 | − WRITE_ONCE(*sptep, REMOVED_SPTE); | |
| 490 | + old_spte = kvm_tdp_mmu_write_spte(sptep, old_spte, | |
| 491 | + REMOVED_SPTE, level); | |
| 471 | 492 | } |
| 472 | 493 | handle_changed_spte(kvm, kvm_mmu_page_as_id(sp), gfn, |
| 473 | − old_child_spte, REMOVED_SPTE, level, | |
| 474 | − shared); | |
| 494 | + old_spte, REMOVED_SPTE, level, shared); | |
| 475 | 495 | } |
| 476 | 496 | |
| 477 | 497 | call_rcu(&sp->rcu_head, tdp_mmu_free_sp_rcu_callback); |
| @@ -667,14 +687,13 @@ static inline int tdp_mmu_zap_spte_atomic(struct kvm *kvm, · 189 unmodified lines | ||
| 667 | 687 | KVM_PAGES_PER_HPAGE(iter->level)); |
| 668 | 688 | |
| 669 | 689 | /* |
| 670 | − * No other thread can overwrite the removed SPTE as they | |
| 671 | − * must either wait on the MMU lock or use | |
| 672 | − * tdp_mmu_set_spte_atomic which will not overwrite the | |
| 673 | − * special removed SPTE value. No bookkeeping is needed | |
| 674 | − * here since the SPTE is going from non-present | |
| 675 | − * to non-present. | |
| 690 | + * No other thread can overwrite the removed SPTE as they must either | |
| 691 | + * wait on the MMU lock or use tdp_mmu_set_spte_atomic() which will not | |
| 692 | + * overwrite the special removed SPTE value. No bookkeeping is needed | |
| 693 | + * here since the SPTE is going from non-present to non-present. Use | |
| 694 | + * the raw write helper to avoid an unnecessary check on volatile bits. | |
| 676 | 695 | */ |
| 677 | − kvm_tdp_mmu_write_spte(iter->sptep, 0); | |
| 696 | + __kvm_tdp_mmu_write_spte(iter->sptep, 0); | |
| 678 | 697 | |
| 679 | 698 | return 0; |
| 680 | 699 | } |
| @@ -699,10 +718,13 @@ static inline int tdp_mmu_zap_spte_atomic(struct kvm *kvm, · 18 unmodified lines | ||
| 699 | 718 | * unless performing certain dirty logging operations. |
| 700 | 719 | * Leaving record_dirty_log unset in that case prevents page |
| 701 | 720 | * writes from being double counted. |
| 721 | + * | |
| 722 | + * Returns the old SPTE value, which _may_ be different than @old_spte if the | |
| 723 | + * SPTE had voldatile bits. | |
| 702 | 724 | */ |
| 703 | −static void __tdp_mmu_set_spte(struct kvm *kvm, int as_id, tdp_ptep_t sptep, | |
| 704 | − u64 old_spte, u64 new_spte, gfn_t gfn, int level, | |
| 705 | − bool record_acc_track, bool record_dirty_log) | |
| 725 | +static u64 __tdp_mmu_set_spte(struct kvm *kvm, int as_id, tdp_ptep_t sptep, | |
| 726 | + u64 old_spte, u64 new_spte, gfn_t gfn, int level, | |
| 727 | + bool record_acc_track, bool record_dirty_log) | |
| 706 | 728 | { |
| 707 | 729 | lockdep_assert_held_write(&kvm->mmu_lock); |
| 708 | 730 | |
| @@ -715,7 +737,7 @@ static void __tdp_mmu_set_spte(struct kvm *kvm, int as_id, tdp_ptep_t sptep, · 6 unmodified lines | ||
| 715 | 737 | */ |
| 716 | 738 | WARN_ON(is_removed_spte(old_spte) || is_removed_spte(new_spte)); |
| 717 | 739 | |
| 718 | − kvm_tdp_mmu_write_spte(sptep, new_spte); | |
| 740 | + old_spte = kvm_tdp_mmu_write_spte(sptep, old_spte, new_spte, level); | |
| 719 | 741 | |
| 720 | 742 | __handle_changed_spte(kvm, as_id, gfn, old_spte, new_spte, level, false); |
| 721 | 743 | |
| @@ -724,6 +746,7 @@ static void __tdp_mmu_set_spte(struct kvm *kvm, int as_id, tdp_ptep_t sptep, · 2 unmodified lines | ||
| 724 | 746 | if (record_dirty_log) |
| 725 | 747 | handle_changed_spte_dirty_log(kvm, as_id, gfn, old_spte, |
| 726 | 748 | new_spte, level); |
| 749 | + return old_spte; | |
| 727 | 750 | } |
| 728 | 751 | |
| 729 | 752 | static inline void _tdp_mmu_set_spte(struct kvm *kvm, struct tdp_iter *iter, |
| @@ -732,9 +755,10 @@ static inline void _tdp_mmu_set_spte(struct kvm *kvm, struct tdp_iter *iter, · 2 unmodified lines | ||
| 732 | 755 | { |
| 733 | 756 | WARN_ON_ONCE(iter->yielded); |
| 734 | 757 | |
| 735 | − __tdp_mmu_set_spte(kvm, iter->as_id, iter->sptep, iter->old_spte, | |
| 736 | − new_spte, iter->gfn, iter->level, | |
| 737 | − record_acc_track, record_dirty_log); | |
| 758 | + iter->old_spte = __tdp_mmu_set_spte(kvm, iter->as_id, iter->sptep, | |
| 759 | + iter->old_spte, new_spte, | |
| 760 | + iter->gfn, iter->level, | |
| 761 | + record_acc_track, record_dirty_log); | |
| 738 | 762 | } |
| 739 | 763 | |
| 740 | 764 | static inline void tdp_mmu_set_spte(struct kvm *kvm, struct tdp_iter *iter, |
| @@ -815,14 +839,15 @@ static inline bool __must_check tdp_mmu_iter_cond_resched(struct kvm *kvm, · 74 unmodified lines | ||
| 815 | 839 | return iter->yielded; |
| 816 | 840 | } |
| 817 | 841 | |
| 818 | −static inline gfn_t tdp_mmu_max_gfn_host(void) | |
| 842 | +static inline gfn_t tdp_mmu_max_gfn_exclusive(void) | |
| 819 | 843 | { |
| 820 | 844 | /* |
| 821 | − * Bound TDP MMU walks at host.MAXPHYADDR, guest accesses beyond that | |
| 822 | − * will hit a #PF(RSVD) and never hit an EPT Violation/Misconfig / #NPF, | |
| 823 | − * and so KVM will never install a SPTE for such addresses. | |
| 845 | + * Bound TDP MMU walks at host.MAXPHYADDR. KVM disallows memslots with | |
| 846 | + * a gpa range that would exceed the max gfn, and KVM does not create | |
| 847 | + * MMIO SPTEs for "impossible" gfns, instead sending such accesses down | |
| 848 | + * the slow emulation path every time. | |
| 824 | 849 | */ |
| 825 | − return 1ULL << (shadow_phys_bits - PAGE_SHIFT); | |
| 850 | + return kvm_mmu_max_gfn() + 1; | |
| 826 | 851 | } |
| 827 | 852 | |
| 828 | 853 | static void __tdp_mmu_zap_root(struct kvm *kvm, struct kvm_mmu_page *root, |
| @@ -830,7 +855,7 @@ static void __tdp_mmu_zap_root(struct kvm *kvm, struct kvm_mmu_page *root, · 1 unmodified line | ||
| 830 | 855 | { |
| 831 | 856 | struct tdp_iter iter; |
| 832 | 857 | |
| 833 | − gfn_t end = tdp_mmu_max_gfn_host(); | |
| 858 | + gfn_t end = tdp_mmu_max_gfn_exclusive(); | |
| 834 | 859 | gfn_t start = 0; |
| 835 | 860 | |
| 836 | 861 | for_each_tdp_pte_min_level(iter, root, zap_level, start, end) { |
| @@ -923,7 +948,7 @@ static bool tdp_mmu_zap_leafs(struct kvm *kvm, struct kvm_mmu_page *root, · 86 unmodified lines | ||
| 923 | 948 | { |
| 924 | 949 | struct tdp_iter iter; |
| 925 | 950 | |
| 926 | − end = min(end, tdp_mmu_max_gfn_host()); | |
| 951 | + end = min(end, tdp_mmu_max_gfn_exclusive()); | |
| 927 | 952 | |
| 928 | 953 | lockdep_assert_held_write(&kvm->mmu_lock); |
| 929 | 954 | |
| @@ -45,6 +45,22 @@ static struct kvm_event_hw_type_mapping amd_event_mapping[] = { · 44 unmodified lines | ||
| 45 | 45 | [7] = { 0xd1, 0x00, PERF_COUNT_HW_STALLED_CYCLES_BACKEND }, |
| 46 | 46 | }; |
| 47 | 47 | |
| 48 | +/* duplicated from amd_f17h_perfmon_event_map. */ | |
| 49 | +static struct kvm_event_hw_type_mapping amd_f17h_event_mapping[] = { | |
| 50 | + [0] = { 0x76, 0x00, PERF_COUNT_HW_CPU_CYCLES }, | |
| 51 | + [1] = { 0xc0, 0x00, PERF_COUNT_HW_INSTRUCTIONS }, | |
| 52 | + [2] = { 0x60, 0xff, PERF_COUNT_HW_CACHE_REFERENCES }, | |
| 53 | + [3] = { 0x64, 0x09, PERF_COUNT_HW_CACHE_MISSES }, | |
| 54 | + [4] = { 0xc2, 0x00, PERF_COUNT_HW_BRANCH_INSTRUCTIONS }, | |
| 55 | + [5] = { 0xc3, 0x00, PERF_COUNT_HW_BRANCH_MISSES }, | |
| 56 | + [6] = { 0x87, 0x02, PERF_COUNT_HW_STALLED_CYCLES_FRONTEND }, | |
| 57 | + [7] = { 0x87, 0x01, PERF_COUNT_HW_STALLED_CYCLES_BACKEND }, | |
| 58 | +}; | |
| 59 | + | |
| 60 | +/* amd_pmc_perf_hw_id depends on these being the same size */ | |
| 61 | +static_assert(ARRAY_SIZE(amd_event_mapping) == | |
| 62 | + ARRAY_SIZE(amd_f17h_event_mapping)); | |
| 63 | + | |
| 48 | 64 | static unsigned int get_msr_base(struct kvm_pmu *pmu, enum pmu_type type) |
| 49 | 65 | { |
| 50 | 66 | struct kvm_vcpu *vcpu = pmu_to_vcpu(pmu); |
| @@ -140,6 +156,7 @@ static inline struct kvm_pmc *get_gp_pmc_amd(struct kvm_pmu *pmu, u32 msr, · 89 unmodified lines | ||
| 140 | 156 | |
| 141 | 157 | static unsigned int amd_pmc_perf_hw_id(struct kvm_pmc *pmc) |
| 142 | 158 | { |
| 159 | + struct kvm_event_hw_type_mapping *event_mapping; | |
| 143 | 160 | u8 event_select = pmc->eventsel & ARCH_PERFMON_EVENTSEL_EVENT; |
| 144 | 161 | u8 unit_mask = (pmc->eventsel & ARCH_PERFMON_EVENTSEL_UMASK) >> 8; |
| 145 | 162 | int i; |
| @@ -148,15 +165,20 @@ static unsigned int amd_pmc_perf_hw_id(struct kvm_pmc *pmc) · 2 unmodified lines | ||
| 148 | 165 | if (WARN_ON(pmc_is_fixed(pmc))) |
| 149 | 166 | return PERF_COUNT_HW_MAX; |
| 150 | 167 | |
| 168 | + if (guest_cpuid_family(pmc->vcpu) >= 0x17) | |
| 169 | + event_mapping = amd_f17h_event_mapping; | |
| 170 | + else | |
| 171 | + event_mapping = amd_event_mapping; | |
| 172 | + | |
| 151 | 173 | for (i = 0; i < ARRAY_SIZE(amd_event_mapping); i++) |
| 152 | − if (amd_event_mapping[i].eventsel == event_select | |
| 153 | − && amd_event_mapping[i].unit_mask == unit_mask) | |
| 174 | + if (event_mapping[i].eventsel == event_select | |
| 175 | + && event_mapping[i].unit_mask == unit_mask) | |
| 154 | 176 | break; |
| 155 | 177 | |
| 156 | 178 | if (i == ARRAY_SIZE(amd_event_mapping)) |
| 157 | 179 | return PERF_COUNT_HW_MAX; |
| 158 | 180 | |
| 159 | − return amd_event_mapping[i].event_type; | |
| 181 | + return event_mapping[i].event_type; | |
| 160 | 182 | } |
| 161 | 183 | |
| 162 | 184 | /* check if a PMC is enabled by comparing it against global_ctrl bits. Because |
| @@ -1594,24 +1594,51 @@ static void sev_unlock_two_vms(struct kvm *dst_kvm, struct kvm *src_kvm) · 1593 unmodified lines | ||
| 1594 | 1594 | atomic_set_release(&src_sev->migration_in_progress, 0); |
| 1595 | 1595 | } |
| 1596 | 1596 | |
| 1597 | +/* vCPU mutex subclasses. */ | |
| 1598 | +enum sev_migration_role { | |
| 1599 | + SEV_MIGRATION_SOURCE = 0, | |
| 1600 | + SEV_MIGRATION_TARGET, | |
| 1601 | + SEV_NR_MIGRATION_ROLES, | |
| 1602 | +}; | |
| 1597 | 1603 | |
| 1598 | −static int sev_lock_vcpus_for_migration(struct kvm *kvm) | |
| 1604 | +static int sev_lock_vcpus_for_migration(struct kvm *kvm, | |
| 1605 | + enum sev_migration_role role) | |
| 1599 | 1606 | { |
| 1600 | 1607 | struct kvm_vcpu *vcpu; |
| 1601 | 1608 | unsigned long i, j; |
| 1609 | + bool first = true; | |
| 1602 | 1610 | |
| 1603 | 1611 | kvm_for_each_vcpu(i, vcpu, kvm) { |
| 1604 | − if (mutex_lock_killable(&vcpu->mutex)) | |
| 1612 | + if (mutex_lock_killable_nested(&vcpu->mutex, role)) | |
| 1605 | 1613 | goto out_unlock; |
| 1614 | + | |
| 1615 | + if (first) { | |
| 1616 | + /* | |
| 1617 | + * Reset the role to one that avoids colliding with | |
| 1618 | + * the role used for the first vcpu mutex. | |
| 1619 | + */ | |
| 1620 | + role = SEV_NR_MIGRATION_ROLES; | |
| 1621 | + first = false; | |
| 1622 | + } else { | |
| 1623 | + mutex_release(&vcpu->mutex.dep_map, _THIS_IP_); | |
| 1624 | + } | |
| 1606 | 1625 | } |
| 1607 | 1626 | |
| 1608 | 1627 | return 0; |
| 1609 | 1628 | |
| 1610 | 1629 | out_unlock: |
| 1630 | + | |
| 1631 | + first = true; | |
| 1611 | 1632 | kvm_for_each_vcpu(j, vcpu, kvm) { |
| 1612 | 1633 | if (i == j) |
| 1613 | 1634 | break; |
| 1614 | 1635 | |
| 1636 | + if (first) | |
| 1637 | + first = false; | |
| 1638 | + else | |
| 1639 | + mutex_acquire(&vcpu->mutex.dep_map, role, 0, _THIS_IP_); | |
| 1640 | + | |
| 1641 | + | |
| 1615 | 1642 | mutex_unlock(&vcpu->mutex); |
| 1616 | 1643 | } |
| 1617 | 1644 | return -EINTR; |
| @@ -1621,8 +1648,15 @@ static void sev_unlock_vcpus_for_migration(struct kvm *kvm) · 3 unmodified lines | ||
| 1621 | 1648 | { |
| 1622 | 1649 | struct kvm_vcpu *vcpu; |
| 1623 | 1650 | unsigned long i; |
| 1651 | + bool first = true; | |
| 1624 | 1652 | |
| 1625 | 1653 | kvm_for_each_vcpu(i, vcpu, kvm) { |
| 1654 | + if (first) | |
| 1655 | + first = false; | |
| 1656 | + else | |
| 1657 | + mutex_acquire(&vcpu->mutex.dep_map, | |
| 1658 | + SEV_NR_MIGRATION_ROLES, 0, _THIS_IP_); | |
| 1659 | + | |
| 1626 | 1660 | mutex_unlock(&vcpu->mutex); |
| 1627 | 1661 | } |
| 1628 | 1662 | } |
| @@ -1748,10 +1782,10 @@ int sev_vm_move_enc_context_from(struct kvm *kvm, unsigned int source_fd) · 119 unmodified lines | ||
| 1748 | 1782 | charged = true; |
| 1749 | 1783 | } |
| 1750 | 1784 | |
| 1751 | − ret = sev_lock_vcpus_for_migration(kvm); | |
| 1785 | + ret = sev_lock_vcpus_for_migration(kvm, SEV_MIGRATION_SOURCE); | |
| 1752 | 1786 | if (ret) |
| 1753 | 1787 | goto out_dst_cgroup; |
| 1754 | − ret = sev_lock_vcpus_for_migration(source_kvm); | |
| 1788 | + ret = sev_lock_vcpus_for_migration(source_kvm, SEV_MIGRATION_TARGET); | |
| 1755 | 1789 | if (ret) |
| 1756 | 1790 | goto out_dst_vcpu; |
| 1757 | 1791 | |
| @@ -5472,7 +5472,7 @@ static bool vmx_emulation_required_with_pending_exception(struct kvm_vcpu *vcpu) · 5471 unmodified lines | ||
| 5472 | 5472 | struct vcpu_vmx *vmx = to_vmx(vcpu); |
| 5473 | 5473 | |
| 5474 | 5474 | return vmx->emulation_required && !vmx->rmode.vm86_active && |
| 5475 | − vcpu->arch.exception.pending; | |
| 5475 | + (vcpu->arch.exception.pending || vcpu->arch.exception.injected); | |
| 5476 | 5476 | } |
| 5477 | 5477 | |
| 5478 | 5478 | static int handle_invalid_guest_state(struct kvm_vcpu *vcpu) |
| @@ -10020,12 +10020,14 @@ static int vcpu_enter_guest(struct kvm_vcpu *vcpu) · 10019 unmodified lines | ||
| 10020 | 10020 | if (kvm_check_request(KVM_REQ_HV_CRASH, vcpu)) { |
| 10021 | 10021 | vcpu->run->exit_reason = KVM_EXIT_SYSTEM_EVENT; |
| 10022 | 10022 | vcpu->run->system_event.type = KVM_SYSTEM_EVENT_CRASH; |
| 10023 | + vcpu->run->system_event.ndata = 0; | |
| 10023 | 10024 | r = 0; |
| 10024 | 10025 | goto out; |
| 10025 | 10026 | } |
| 10026 | 10027 | if (kvm_check_request(KVM_REQ_HV_RESET, vcpu)) { |
| 10027 | 10028 | vcpu->run->exit_reason = KVM_EXIT_SYSTEM_EVENT; |
| 10028 | 10029 | vcpu->run->system_event.type = KVM_SYSTEM_EVENT_RESET; |
| 10030 | + vcpu->run->system_event.ndata = 0; | |
| 10029 | 10031 | r = 0; |
| 10030 | 10032 | goto out; |
| 10031 | 10033 | } |
| @@ -12009,8 +12011,12 @@ int kvm_arch_prepare_memory_region(struct kvm *kvm, · 1977 unmodified lines | ||
| 12009 | 12011 | struct kvm_memory_slot *new, |
| 12010 | 12012 | enum kvm_mr_change change) |
| 12011 | 12013 | { |
| 12012 | − if (change == KVM_MR_CREATE || change == KVM_MR_MOVE) | |
| 12014 | + if (change == KVM_MR_CREATE || change == KVM_MR_MOVE) { | |
| 12015 | + if ((new->base_gfn + new->npages - 1) > kvm_mmu_max_gfn()) | |
| 12016 | + return -EINVAL; | |
| 12017 | + | |
| 12013 | 12018 | return kvm_alloc_memslot_metadata(kvm, new); |
| 12019 | + } | |
| 12014 | 12020 | |
| 12015 | 12021 | if (change == KVM_MR_FLAGS_ONLY) |
| 12016 | 12022 | memcpy(&new->arch, &old->arch, sizeof(old->arch)); |
| @@ -53,12 +53,12 @@ · 52 unmodified lines | ||
| 53 | 53 | SYM_FUNC_START(copy_user_generic_unrolled) |
| 54 | 54 | ASM_STAC |
| 55 | 55 | cmpl $8,%edx |
| 56 | − jb 20f /* less then 8 bytes, go to byte copy loop */ | |
| 56 | + jb .Lcopy_user_short_string_bytes | |
| 57 | 57 | ALIGN_DESTINATION |
| 58 | 58 | movl %edx,%ecx |
| 59 | 59 | andl $63,%edx |
| 60 | 60 | shrl $6,%ecx |
| 61 | − jz .L_copy_short_string | |
| 61 | + jz copy_user_short_string | |
| 62 | 62 | 1: movq (%rsi),%r8 |
| 63 | 63 | 2: movq 1*8(%rsi),%r9 |
| 64 | 64 | 3: movq 2*8(%rsi),%r10 |
| @@ -79,37 +79,11 @@ SYM_FUNC_START(copy_user_generic_unrolled) · 14 unmodified lines | ||
| 79 | 79 | leaq 64(%rdi),%rdi |
| 80 | 80 | decl %ecx |
| 81 | 81 | jnz 1b |
| 82 | −.L_copy_short_string: | |
| 83 | − movl %edx,%ecx | |
| 84 | − andl $7,%edx | |
| 85 | − shrl $3,%ecx | |
| 86 | − jz 20f | |
| 87 | −18: movq (%rsi),%r8 | |
| 88 | −19: movq %r8,(%rdi) | |
| 89 | − leaq 8(%rsi),%rsi | |
| 90 | − leaq 8(%rdi),%rdi | |
| 91 | − decl %ecx | |
| 92 | − jnz 18b | |
| 93 | −20: andl %edx,%edx | |
| 94 | − jz 23f | |
| 95 | − movl %edx,%ecx | |
| 96 | −21: movb (%rsi),%al | |
| 97 | −22: movb %al,(%rdi) | |
| 98 | − incq %rsi | |
| 99 | − incq %rdi | |
| 100 | − decl %ecx | |
| 101 | − jnz 21b | |
| 102 | −23: xor %eax,%eax | |
| 103 | − ASM_CLAC | |
| 104 | − RET | |
| 82 | + jmp copy_user_short_string | |
| 105 | 83 | |
| 106 | 84 | 30: shll $6,%ecx |
| 107 | 85 | addl %ecx,%edx |
| 108 | − jmp 60f | |
| 109 | −40: leal (%rdx,%rcx,8),%edx | |
| 110 | − jmp 60f | |
| 111 | −50: movl %ecx,%edx | |
| 112 | −60: jmp .Lcopy_user_handle_tail /* ecx is zerorest also */ | |
| 86 | + jmp .Lcopy_user_handle_tail | |
| 113 | 87 | |
| 114 | 88 | _ASM_EXTABLE_CPY(1b, 30b) |
| 115 | 89 | _ASM_EXTABLE_CPY(2b, 30b) |
| @@ -127,10 +101,6 @@ SYM_FUNC_START(copy_user_generic_unrolled) · 11 unmodified lines | ||
| 127 | 101 | _ASM_EXTABLE_CPY(14b, 30b) |
| 128 | 102 | _ASM_EXTABLE_CPY(15b, 30b) |
| 129 | 103 | _ASM_EXTABLE_CPY(16b, 30b) |
| 130 | − _ASM_EXTABLE_CPY(18b, 40b) | |
| 131 | − _ASM_EXTABLE_CPY(19b, 40b) | |
| 132 | − _ASM_EXTABLE_CPY(21b, 50b) | |
| 133 | − _ASM_EXTABLE_CPY(22b, 50b) | |
| 134 | 104 | SYM_FUNC_END(copy_user_generic_unrolled) |
| 135 | 105 | EXPORT_SYMBOL(copy_user_generic_unrolled) |
| 136 | 106 | |
| @@ -191,7 +161,7 @@ EXPORT_SYMBOL(copy_user_generic_string) · 54 unmodified lines | ||
| 191 | 161 | SYM_FUNC_START(copy_user_enhanced_fast_string) |
| 192 | 162 | ASM_STAC |
| 193 | 163 | /* CPUs without FSRM should avoid rep movsb for short copies */ |
| 194 | − ALTERNATIVE "cmpl $64, %edx; jb .L_copy_short_string", "", X86_FEATURE_FSRM | |
| 164 | + ALTERNATIVE "cmpl $64, %edx; jb copy_user_short_string", "", X86_FEATURE_FSRM | |
| 195 | 165 | movl %edx,%ecx |
| 196 | 166 | 1: rep movsb |
| 197 | 167 | xorl %eax,%eax |
| @@ -243,6 +213,53 @@ SYM_CODE_START_LOCAL(.Lcopy_user_handle_tail) · 45 unmodified lines | ||
| 243 | 213 | |
| 244 | 214 | SYM_CODE_END(.Lcopy_user_handle_tail) |
| 245 | 215 | |
| 216 | +/* | |
| 217 | + * Finish memcpy of less than 64 bytes. #AC should already be set. | |
| 218 | + * | |
| 219 | + * Input: | |
| 220 | + * rdi destination | |
| 221 | + * rsi source | |
| 222 | + * rdx count (< 64) | |
| 223 | + * | |
| 224 | + * Output: | |
| 225 | + * eax uncopied bytes or 0 if successful. | |
| 226 | + */ | |
| 227 | +SYM_CODE_START_LOCAL(copy_user_short_string) | |
| 228 | + movl %edx,%ecx | |
| 229 | + andl $7,%edx | |
| 230 | + shrl $3,%ecx | |
| 231 | + jz .Lcopy_user_short_string_bytes | |
| 232 | +18: movq (%rsi),%r8 | |
| 233 | +19: movq %r8,(%rdi) | |
| 234 | + leaq 8(%rsi),%rsi | |
| 235 | + leaq 8(%rdi),%rdi | |
| 236 | + decl %ecx | |
| 237 | + jnz 18b | |
| 238 | +.Lcopy_user_short_string_bytes: | |
| 239 | + andl %edx,%edx | |
| 240 | + jz 23f | |
| 241 | + movl %edx,%ecx | |
| 242 | +21: movb (%rsi),%al | |
| 243 | +22: movb %al,(%rdi) | |
| 244 | + incq %rsi | |
| 245 | + incq %rdi | |
| 246 | + decl %ecx | |
| 247 | + jnz 21b | |
| 248 | +23: xor %eax,%eax | |
| 249 | + ASM_CLAC | |
| 250 | + RET | |
| 251 | + | |
| 252 | +40: leal (%rdx,%rcx,8),%edx | |
| 253 | + jmp 60f | |
| 254 | +50: movl %ecx,%edx /* ecx is zerorest also */ | |
| 255 | +60: jmp .Lcopy_user_handle_tail | |
| 256 | + | |
| 257 | + _ASM_EXTABLE_CPY(18b, 40b) | |
| 258 | + _ASM_EXTABLE_CPY(19b, 40b) | |
| 259 | + _ASM_EXTABLE_CPY(21b, 50b) | |
| 260 | + _ASM_EXTABLE_CPY(22b, 50b) | |
| 261 | +SYM_CODE_END(copy_user_short_string) | |
| 262 | + | |
| 246 | 263 | /* |
| 247 | 264 | * copy_user_nocache - Uncached memory copy with exception handling |
| 248 | 265 | * This will force destination out of cache for more performance. |
| @@ -48,6 +48,7 @@ SYM_FUNC_START(__put_user_1) · 47 unmodified lines | ||
| 48 | 48 | cmp %_ASM_BX,%_ASM_CX |
| 49 | 49 | jae .Lbad_put_user |
| 50 | 50 | SYM_INNER_LABEL(__put_user_nocheck_1, SYM_L_GLOBAL) |
| 51 | + ENDBR | |
| 51 | 52 | ASM_STAC |
| 52 | 53 | 1: movb %al,(%_ASM_CX) |
| 53 | 54 | xor %ecx,%ecx |
| @@ -62,6 +63,7 @@ SYM_FUNC_START(__put_user_2) · 8 unmodified lines | ||
| 62 | 63 | cmp %_ASM_BX,%_ASM_CX |
| 63 | 64 | jae .Lbad_put_user |
| 64 | 65 | SYM_INNER_LABEL(__put_user_nocheck_2, SYM_L_GLOBAL) |
| 66 | + ENDBR | |
| 65 | 67 | ASM_STAC |
| 66 | 68 | 2: movw %ax,(%_ASM_CX) |
| 67 | 69 | xor %ecx,%ecx |
| @@ -76,6 +78,7 @@ SYM_FUNC_START(__put_user_4) · 8 unmodified lines | ||
| 76 | 78 | cmp %_ASM_BX,%_ASM_CX |
| 77 | 79 | jae .Lbad_put_user |
| 78 | 80 | SYM_INNER_LABEL(__put_user_nocheck_4, SYM_L_GLOBAL) |
| 81 | + ENDBR | |
| 79 | 82 | ASM_STAC |
| 80 | 83 | 3: movl %eax,(%_ASM_CX) |
| 81 | 84 | xor %ecx,%ecx |
| @@ -90,6 +93,7 @@ SYM_FUNC_START(__put_user_8) · 8 unmodified lines | ||
| 90 | 93 | cmp %_ASM_BX,%_ASM_CX |
| 91 | 94 | jae .Lbad_put_user |
| 92 | 95 | SYM_INNER_LABEL(__put_user_nocheck_8, SYM_L_GLOBAL) |
| 96 | + ENDBR | |
| 93 | 97 | ASM_STAC |
| 94 | 98 | 4: mov %_ASM_AX,(%_ASM_CX) |
| 95 | 99 | #ifdef CONFIG_X86_32 |
| @@ -31,6 +31,7 @@ · 30 unmodified lines | ||
| 31 | 31 | .align RETPOLINE_THUNK_SIZE |
| 32 | 32 | SYM_INNER_LABEL(__x86_indirect_thunk_\reg, SYM_L_GLOBAL) |
| 33 | 33 | UNWIND_HINT_EMPTY |
| 34 | + ANNOTATE_NOENDBR | |
| 34 | 35 | |
| 35 | 36 | ALTERNATIVE_2 __stringify(ANNOTATE_RETPOLINE_SAFE; jmp *%\reg), \ |
| 36 | 37 | __stringify(RETPOLINE \reg), X86_FEATURE_RETPOLINE, \ |
| @@ -55,7 +56,6 @@ SYM_INNER_LABEL(__x86_indirect_thunk_\reg, SYM_L_GLOBAL) · 18 unmodified lines | ||
| 55 | 56 | |
| 56 | 57 | .align RETPOLINE_THUNK_SIZE |
| 57 | 58 | SYM_CODE_START(__x86_indirect_thunk_array) |
| 58 | − ANNOTATE_NOENDBR // apply_retpolines | |
| 59 | 59 | |
| 60 | 60 | #define GEN(reg) THUNK reg |
| 61 | 61 | #include <asm/GEN-for-each-reg.h> |
| @@ -902,6 +902,8 @@ static void __meminit vmemmap_use_sub_pmd(unsigned long start, unsigned long end · 901 unmodified lines | ||
| 902 | 902 | |
| 903 | 903 | static void __meminit vmemmap_use_new_sub_pmd(unsigned long start, unsigned long end) |
| 904 | 904 | { |
| 905 | + const unsigned long page = ALIGN_DOWN(start, PMD_SIZE); | |
| 906 | + | |
| 905 | 907 | vmemmap_flush_unused_pmd(); |
| 906 | 908 | |
| 907 | 909 | /* |
| @@ -914,8 +916,7 @@ static void __meminit vmemmap_use_new_sub_pmd(unsigned long start, unsigned long · 6 unmodified lines | ||
| 914 | 916 | * Mark with PAGE_UNUSED the unused parts of the new memmap range |
| 915 | 917 | */ |
| 916 | 918 | if (!IS_ALIGNED(start, PMD_SIZE)) |
| 917 | − memset((void *)start, PAGE_UNUSED, | |
| 918 | − start - ALIGN_DOWN(start, PMD_SIZE)); | |
| 919 | + memset((void *)page, PAGE_UNUSED, start - page); | |
| 919 | 920 | |
| 920 | 921 | /* |
| 921 | 922 | * We want to avoid memset(PAGE_UNUSED) when populating the vmemmap of |
| @@ -638,17 +638,6 @@ pte_t *lookup_address(unsigned long address, unsigned int *level) · 637 unmodified lines | ||
| 638 | 638 | } |
| 639 | 639 | EXPORT_SYMBOL_GPL(lookup_address); |
| 640 | 640 | |
| 641 | −/* | |
| 642 | − * Lookup the page table entry for a virtual address in a given mm. Return a | |
| 643 | − * pointer to the entry and the level of the mapping. | |
| 644 | − */ | |
| 645 | −pte_t *lookup_address_in_mm(struct mm_struct *mm, unsigned long address, | |
| 646 | − unsigned int *level) | |
| 647 | −{ | |
| 648 | − return lookup_address_in_pgd(pgd_offset(mm, address), address, level); | |
| 649 | −} | |
| 650 | −EXPORT_SYMBOL_GPL(lookup_address_in_mm); | |
| 651 | − | |
| 652 | 641 | static pte_t *_lookup_address_cpa(struct cpa_data *cpa, unsigned long address, |
| 653 | 642 | unsigned int *level) |
| 654 | 643 | { |
| @@ -467,7 +467,6 @@ static __init void xen_setup_pci_msi(void) · 466 unmodified lines | ||
| 467 | 467 | else |
| 468 | 468 | xen_msi_ops.setup_msi_irqs = xen_setup_msi_irqs; |
| 469 | 469 | xen_msi_ops.teardown_msi_irqs = xen_pv_teardown_msi_irqs; |
| 470 | − pci_msi_ignore_mask = 1; | |
| 471 | 470 | } else if (xen_hvm_domain()) { |
| 472 | 471 | xen_msi_ops.setup_msi_irqs = xen_hvm_setup_msi_irqs; |
| 473 | 472 | xen_msi_ops.teardown_msi_irqs = xen_teardown_msi_irqs; |
| @@ -481,6 +480,11 @@ static __init void xen_setup_pci_msi(void) · 7 unmodified lines | ||
| 481 | 480 | * in allocating the native domain and never use it. |
| 482 | 481 | */ |
| 483 | 482 | x86_init.irqs.create_pci_msi_domain = xen_create_pci_msi_domain; |
| 483 | + /* | |
| 484 | + * With XEN PIRQ/Eventchannels in use PCI/MSI[-X] masking is solely | |
| 485 | + * controlled by the hypervisor. | |
| 486 | + */ | |
| 487 | + pci_msi_ignore_mask = 1; | |
| 484 | 488 | } |
| 485 | 489 | |
| 486 | 490 | #else /* CONFIG_PCI_MSI */ |
| @@ -50,6 +50,7 @@ · 49 unmodified lines | ||
| 50 | 50 | #define PVH_DS_SEL (PVH_GDT_ENTRY_DS * 8) |
| 51 | 51 | |
| 52 | 52 | SYM_CODE_START_LOCAL(pvh_start_xen) |
| 53 | + UNWIND_HINT_EMPTY | |
| 53 | 54 | cld |
| 54 | 55 | |
| 55 | 56 | lgdt (_pa(gdt)) |
| @@ -25,6 +25,7 @@ · 24 unmodified lines | ||
| 25 | 25 | #include <asm/cpu.h> |
| 26 | 26 | #include <asm/mmu_context.h> |
| 27 | 27 | #include <asm/cpu_device_id.h> |
| 28 | +#include <asm/microcode.h> | |
| 28 | 29 | |
| 29 | 30 | #ifdef CONFIG_X86_32 |
| 30 | 31 | __visible unsigned long saved_context_ebx; |
| @@ -262,11 +263,18 @@ static void notrace __restore_processor_state(struct saved_context *ctxt) · 231 unmodified lines | ||
| 262 | 263 | x86_platform.restore_sched_clock_state(); |
| 263 | 264 | mtrr_bp_restore(); |
| 264 | 265 | perf_restore_debug_store(); |
| 265 | − msr_restore_context(ctxt); | |
| 266 | 266 | |
| 267 | 267 | c = &cpu_data(smp_processor_id()); |
| 268 | 268 | if (cpu_has(c, X86_FEATURE_MSR_IA32_FEAT_CTL)) |
| 269 | 269 | init_ia32_feat_ctl(c); |
| 270 | + | |
| 271 | + microcode_bsp_resume(); | |
| 272 | + | |
| 273 | + /* | |
| 274 | + * This needs to happen after the microcode has been updated upon resume | |
| 275 | + * because some of the MSRs are "emulated" in microcode. | |
| 276 | + */ | |
| 277 | + msr_restore_context(ctxt); | |
| 270 | 278 | } |
| 271 | 279 | |
| 272 | 280 | /* Needed by apm.c */ |
| @@ -45,6 +45,7 @@ SYM_CODE_END(hypercall_page) · 44 unmodified lines | ||
| 45 | 45 | __INIT |
| 46 | 46 | SYM_CODE_START(startup_xen) |
| 47 | 47 | UNWIND_HINT_EMPTY |
| 48 | + ANNOTATE_NOENDBR | |
| 48 | 49 | cld |
| 49 | 50 | |
| 50 | 51 | /* Clear .bss */ |
| @@ -569,7 +569,7 @@ static bool bfqq_request_over_limit(struct bfq_queue *bfqq, int limit) · 568 unmodified lines | ||
| 569 | 569 | struct bfq_entity *entity = &bfqq->entity; |
| 570 | 570 | struct bfq_entity *inline_entities[BFQ_LIMIT_INLINE_DEPTH]; |
| 571 | 571 | struct bfq_entity **entities = inline_entities; |
| 572 | − int depth, level; | |
| 572 | + int depth, level, alloc_depth = BFQ_LIMIT_INLINE_DEPTH; | |
| 573 | 573 | int class_idx = bfqq->ioprio_class - 1; |
| 574 | 574 | struct bfq_sched_data *sched_data; |
| 575 | 575 | unsigned long wsum; |
| @@ -578,15 +578,21 @@ static bool bfqq_request_over_limit(struct bfq_queue *bfqq, int limit) · 2 unmodified lines | ||
| 578 | 578 | if (!entity->on_st_or_in_serv) |
| 579 | 579 | return false; |
| 580 | 580 | |
| 581 | +retry: | |
| 582 | + spin_lock_irq(&bfqd->lock); | |
| 581 | 583 | /* +1 for bfqq entity, root cgroup not included */ |
| 582 | 584 | depth = bfqg_to_blkg(bfqq_group(bfqq))->blkcg->css.cgroup->level + 1; |
| 583 | − if (depth > BFQ_LIMIT_INLINE_DEPTH) { | |
| 585 | + if (depth > alloc_depth) { | |
| 586 | + spin_unlock_irq(&bfqd->lock); | |
| 587 | + if (entities != inline_entities) | |
| 588 | + kfree(entities); | |
| 584 | 589 | entities = kmalloc_array(depth, sizeof(*entities), GFP_NOIO); |
| 585 | 590 | if (!entities) |
| 586 | 591 | return false; |
| 592 | + alloc_depth = depth; | |
| 593 | + goto retry; | |
| 587 | 594 | } |
| 588 | 595 | |
| 589 | − spin_lock_irq(&bfqd->lock); | |
| 590 | 596 | sched_data = entity->sched_data; |
| 591 | 597 | /* Gather our ancestors as we need to traverse them in reverse order */ |
| 592 | 598 | level = 0; |
| @@ -50,7 +50,6 @@ · 49 unmodified lines | ||
| 50 | 50 | #include "blk-pm.h" |
| 51 | 51 | #include "blk-cgroup.h" |
| 52 | 52 | #include "blk-throttle.h" |
| 53 | −#include "blk-rq-qos.h" | |
| 54 | 53 | |
| 55 | 54 | struct dentry *blk_debugfs_root; |
| 56 | 55 | |
| @@ -315,9 +314,6 @@ void blk_cleanup_queue(struct request_queue *q) · 258 unmodified lines | ||
| 315 | 314 | */ |
| 316 | 315 | blk_freeze_queue(q); |
| 317 | 316 | |
| 318 | − /* cleanup rq qos structures for queue without disk */ | |
| 319 | − rq_qos_exit(q); | |
| 320 | − | |
| 321 | 317 | blk_queue_flag_set(QUEUE_FLAG_DEAD, q); |
| 322 | 318 | |
| 323 | 319 | blk_sync_queue(q); |
| @@ -2322,7 +2322,17 @@ static void ioc_timer_fn(struct timer_list *timer) · 2321 unmodified lines | ||
| 2322 | 2322 | iocg->hweight_donating = hwa; |
| 2323 | 2323 | iocg->hweight_after_donation = new_hwi; |
| 2324 | 2324 | list_add(&iocg->surplus_list, &surpluses); |
| 2325 | − } else { | |
| 2325 | + } else if (!iocg->abs_vdebt) { | |
| 2326 | + /* | |
| 2327 | + * @iocg doesn't have enough to donate. Reset | |
| 2328 | + * its inuse to active. | |
| 2329 | + * | |
| 2330 | + * Don't reset debtors as their inuse's are | |
| 2331 | + * owned by debt handling. This shouldn't affect | |
| 2332 | + * donation calculuation in any meaningful way | |
| 2333 | + * as @iocg doesn't have a meaningful amount of | |
| 2334 | + * share anyway. | |
| 2335 | + */ | |
| 2326 | 2336 | TRACE_IOCG_PATH(inuse_shortage, iocg, &now, |
| 2327 | 2337 | iocg->inuse, iocg->active, |
| 2328 | 2338 | iocg->hweight_inuse, new_hwi); |
| @@ -1131,14 +1131,7 @@ void blk_mq_start_request(struct request *rq) · 1130 unmodified lines | ||
| 1131 | 1131 | trace_block_rq_issue(rq); |
| 1132 | 1132 | |
| 1133 | 1133 | if (test_bit(QUEUE_FLAG_STATS, &q->queue_flags)) { |
| 1134 | − u64 start_time; | |
| 1135 | −#ifdef CONFIG_BLK_CGROUP | |
| 1136 | − if (rq->bio) | |
| 1137 | − start_time = bio_issue_time(&rq->bio->bi_issue); | |
| 1138 | − else | |
| 1139 | −#endif | |
| 1140 | − start_time = ktime_get_ns(); | |
| 1141 | − rq->io_start_time_ns = start_time; | |
| 1134 | + rq->io_start_time_ns = ktime_get_ns(); | |
| 1142 | 1135 | rq->stats_sectors = blk_rq_sectors(rq); |
| 1143 | 1136 | rq->rq_flags |= RQF_STATS; |
| 1144 | 1137 | rq_qos_issue(q, rq); |
| @@ -96,11 +96,6 @@ static const struct dmi_system_id processor_power_dmi_table[] = { · 95 unmodified lines | ||
| 96 | 96 | DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK Computer Inc."), |
| 97 | 97 | DMI_MATCH(DMI_PRODUCT_NAME,"L8400B series Notebook PC")}, |
| 98 | 98 | (void *)1}, |
| 99 | − /* T40 can not handle C3 idle state */ | |
| 100 | − { set_max_cstate, "IBM ThinkPad T40", { | |
| 101 | − DMI_MATCH(DMI_SYS_VENDOR, "IBM"), | |
| 102 | − DMI_MATCH(DMI_PRODUCT_NAME, "23737CU")}, | |
| 103 | − (void *)2}, | |
| 104 | 99 | {}, |
| 105 | 100 | }; |
| 106 | 101 | |
| @@ -795,7 +790,8 @@ static int acpi_processor_setup_cstates(struct acpi_processor *pr) · 688 unmodified lines | ||
| 795 | 790 | if (cx->type == ACPI_STATE_C1 || cx->type == ACPI_STATE_C2 || |
| 796 | 791 | cx->type == ACPI_STATE_C3) { |
| 797 | 792 | state->enter_dead = acpi_idle_play_dead; |
| 798 | − drv->safe_state_index = count; | |
| 793 | + if (cx->type != ACPI_STATE_C3) | |
| 794 | + drv->safe_state_index = count; | |
| 799 | 795 | } |
| 800 | 796 | /* |
| 801 | 797 | * Halt-induced C1 is not good for ->enter_s2idle, because it |
| @@ -20,6 +20,10 @@ · 19 unmodified lines | ||
| 20 | 20 | #include <linux/platform_device.h> |
| 21 | 21 | #include <linux/reset.h> |
| 22 | 22 | #include <linux/of_irq.h> |
| 23 | +#include <linux/of_device.h> | |
| 24 | +#include <linux/acpi.h> | |
| 25 | +#include <linux/iommu.h> | |
| 26 | +#include <linux/dma-map-ops.h> | |
| 23 | 27 | |
| 24 | 28 | #define to_amba_driver(d) container_of(d, struct amba_driver, drv) |
| 25 | 29 | |
| @@ -273,6 +277,36 @@ static void amba_shutdown(struct device *dev) · 247 unmodified lines | ||
| 273 | 277 | drv->shutdown(to_amba_device(dev)); |
| 274 | 278 | } |
| 275 | 279 | |
| 280 | +static int amba_dma_configure(struct device *dev) | |
| 281 | +{ | |
| 282 | + struct amba_driver *drv = to_amba_driver(dev->driver); | |
| 283 | + enum dev_dma_attr attr; | |
| 284 | + int ret = 0; | |
| 285 | + | |
| 286 | + if (dev->of_node) { | |
| 287 | + ret = of_dma_configure(dev, dev->of_node, true); | |
| 288 | + } else if (has_acpi_companion(dev)) { | |
| 289 | + attr = acpi_get_dma_attr(to_acpi_device_node(dev->fwnode)); | |
| 290 | + ret = acpi_dma_configure(dev, attr); | |
| 291 | + } | |
| 292 | + | |
| 293 | + if (!ret && !drv->driver_managed_dma) { | |
| 294 | + ret = iommu_device_use_default_domain(dev); | |
| 295 | + if (ret) | |
| 296 | + arch_teardown_dma_ops(dev); | |
| 297 | + } | |
| 298 | + | |
| 299 | + return ret; | |
| 300 | +} | |
| 301 | + | |
| 302 | +static void amba_dma_cleanup(struct device *dev) | |
| 303 | +{ | |
| 304 | + struct amba_driver *drv = to_amba_driver(dev->driver); | |
| 305 | + | |
| 306 | + if (!drv->driver_managed_dma) | |
| 307 | + iommu_device_unuse_default_domain(dev); | |
| 308 | +} | |
| 309 | + | |
| 276 | 310 | #ifdef CONFIG_PM |
| 277 | 311 | /* |
| 278 | 312 | * Hooks to provide runtime PM of the pclk (bus clock). It is safe to |
| @@ -341,7 +375,8 @@ struct bus_type amba_bustype = { · 62 unmodified lines | ||
| 341 | 375 | .probe = amba_probe, |
| 342 | 376 | .remove = amba_remove, |
| 343 | 377 | .shutdown = amba_shutdown, |
| 344 | − .dma_configure = platform_dma_configure, | |
| 378 | + .dma_configure = amba_dma_configure, | |
| 379 | + .dma_cleanup = amba_dma_cleanup, | |
| 345 | 380 | .pm = &amba_pm, |
| 346 | 381 | }; |
| 347 | 382 | EXPORT_SYMBOL_GPL(amba_bustype); |
| @@ -2295,6 +2295,7 @@ static int binder_do_deferred_txn_copies(struct binder_alloc *alloc, · 2294 unmodified lines | ||
| 2295 | 2295 | { |
| 2296 | 2296 | int ret = 0; |
| 2297 | 2297 | struct binder_sg_copy *sgc, *tmpsgc; |
| 2298 | + struct binder_ptr_fixup *tmppf; | |
| 2298 | 2299 | struct binder_ptr_fixup *pf = |
| 2299 | 2300 | list_first_entry_or_null(pf_head, struct binder_ptr_fixup, |
| 2300 | 2301 | node); |
| @@ -2349,7 +2350,11 @@ static int binder_do_deferred_txn_copies(struct binder_alloc *alloc, · 48 unmodified lines | ||
| 2349 | 2350 | list_del(&sgc->node); |
| 2350 | 2351 | kfree(sgc); |
| 2351 | 2352 | } |
| 2352 | − BUG_ON(!list_empty(pf_head)); | |
| 2353 | + list_for_each_entry_safe(pf, tmppf, pf_head, node) { | |
| 2354 | + BUG_ON(pf->skip_size == 0); | |
| 2355 | + list_del(&pf->node); | |
| 2356 | + kfree(pf); | |
| 2357 | + } | |
| 2353 | 2358 | BUG_ON(!list_empty(sgc_head)); |
| 2354 | 2359 | |
| 2355 | 2360 | return ret > 0 ? -EINVAL : ret; |
| @@ -2486,6 +2491,9 @@ static int binder_translate_fd_array(struct list_head *pf_head, · 130 unmodified lines | ||
| 2486 | 2491 | struct binder_proc *proc = thread->proc; |
| 2487 | 2492 | int ret; |
| 2488 | 2493 | |
| 2494 | + if (fda->num_fds == 0) | |
| 2495 | + return 0; | |
| 2496 | + | |
| 2489 | 2497 | fd_buf_size = sizeof(u32) * fda->num_fds; |
| 2490 | 2498 | if (fda->num_fds >= SIZE_MAX / sizeof(u32)) { |
| 2491 | 2499 | binder_user_error("%d:%d got transaction with invalid number of fds (%lld)\n", |
| @@ -667,6 +667,15 @@ const struct cpumask *cpu_coregroup_mask(int cpu) · 666 unmodified lines | ||
| 667 | 667 | core_mask = &cpu_topology[cpu].llc_sibling; |
| 668 | 668 | } |
| 669 | 669 | |
| 670 | + /* | |
| 671 | + * For systems with no shared cpu-side LLC but with clusters defined, | |
| 672 | + * extend core_mask to cluster_siblings. The sched domain builder will | |
| 673 | + * then remove MC as redundant with CLS if SCHED_CLUSTER is enabled. | |
| 674 | + */ | |
| 675 | + if (IS_ENABLED(CONFIG_SCHED_CLUSTER) && | |
| 676 | + cpumask_subset(core_mask, &cpu_topology[cpu].cluster_sibling)) | |
| 677 | + core_mask = &cpu_topology[cpu].cluster_sibling; | |
| 678 | + | |
| 670 | 679 | return core_mask; |
| 671 | 680 | } |
| 672 | 681 | |
| @@ -684,7 +693,7 @@ void update_siblings_masks(unsigned int cpuid) · 11 unmodified lines | ||
| 684 | 693 | for_each_online_cpu(cpu) { |
| 685 | 694 | cpu_topo = &cpu_topology[cpu]; |
| 686 | 695 | |
| 687 | − if (cpuid_topo->llc_id == cpu_topo->llc_id) { | |
| 696 | + if (cpu_topo->llc_id != -1 && cpuid_topo->llc_id == cpu_topo->llc_id) { | |
| 688 | 697 | cpumask_set_cpu(cpu, &cpuid_topo->llc_sibling); |
| 689 | 698 | cpumask_set_cpu(cpuid, &cpu_topo->llc_sibling); |
| 690 | 699 | } |
| @@ -671,6 +671,8 @@ sysfs_failed: · 670 unmodified lines | ||
| 671 | 671 | if (dev->bus) |
| 672 | 672 | blocking_notifier_call_chain(&dev->bus->p->bus_notifier, |
| 673 | 673 | BUS_NOTIFY_DRIVER_NOT_BOUND, dev); |
| 674 | + if (dev->bus && dev->bus->dma_cleanup) | |
| 675 | + dev->bus->dma_cleanup(dev); | |
| 674 | 676 | pinctrl_bind_failed: |
| 675 | 677 | device_links_no_driver(dev); |
| 676 | 678 | device_unbind_cleanup(dev); |
| @@ -1199,6 +1201,9 @@ static void __device_release_driver(struct device *dev, struct device *parent) · 522 unmodified lines | ||
| 1199 | 1201 | |
| 1200 | 1202 | device_remove(dev); |
| 1201 | 1203 | |
| 1204 | + if (dev->bus && dev->bus->dma_cleanup) | |
| 1205 | + dev->bus->dma_cleanup(dev); | |
| 1206 | + | |
| 1202 | 1207 | device_links_driver_cleanup(dev); |
| 1203 | 1208 | device_unbind_cleanup(dev); |
| 1204 | 1209 | |
| @@ -735,6 +735,8 @@ _request_firmware(const struct firmware **firmware_p, const char *name, · 734 unmodified lines | ||
| 735 | 735 | size_t offset, u32 opt_flags) |
| 736 | 736 | { |
| 737 | 737 | struct firmware *fw = NULL; |
| 738 | + struct cred *kern_cred = NULL; | |
| 739 | + const struct cred *old_cred; | |
| 738 | 740 | bool nondirect = false; |
| 739 | 741 | int ret; |
| 740 | 742 | |
| @@ -751,6 +753,18 @@ _request_firmware(const struct firmware **firmware_p, const char *name, · 10 unmodified lines | ||
| 751 | 753 | if (ret <= 0) /* error or already assigned */ |
| 752 | 754 | goto out; |
| 753 | 755 | |
| 756 | + /* | |
| 757 | + * We are about to try to access the firmware file. Because we may have been | |
| 758 | + * called by a driver when serving an unrelated request from userland, we use | |
| 759 | + * the kernel credentials to read the file. | |
| 760 | + */ | |
| 761 | + kern_cred = prepare_kernel_cred(NULL); | |
| 762 | + if (!kern_cred) { | |
| 763 | + ret = -ENOMEM; | |
| 764 | + goto out; | |
| 765 | + } | |
| 766 | + old_cred = override_creds(kern_cred); | |
| 767 | + | |
| 754 | 768 | ret = fw_get_filesystem_firmware(device, fw->priv, "", NULL); |
| 755 | 769 | |
| 756 | 770 | /* Only full reads can support decompression, platform, and sysfs. */ |
| @@ -776,6 +790,9 @@ _request_firmware(const struct firmware **firmware_p, const char *name, · 19 unmodified lines | ||
| 776 | 790 | } else |
| 777 | 791 | ret = assign_fw(fw, device); |
| 778 | 792 | |
| 793 | + revert_creds(old_cred); | |
| 794 | + put_cred(kern_cred); | |
| 795 | + | |
| 779 | 796 | out: |
| 780 | 797 | if (ret < 0) { |
| 781 | 798 | fw_abort_batch_reqs(fw); |
| @@ -30,6 +30,8 @@ · 29 unmodified lines | ||
| 30 | 30 | #include <linux/property.h> |
| 31 | 31 | #include <linux/kmemleak.h> |
| 32 | 32 | #include <linux/types.h> |
| 33 | +#include <linux/iommu.h> | |
| 34 | +#include <linux/dma-map-ops.h> | |
| 33 | 35 | |
| 34 | 36 | #include "base.h" |
| 35 | 37 | #include "power/power.h" |
| @@ -1454,9 +1456,9 @@ static void platform_shutdown(struct device *_dev) · 1418 unmodified lines | ||
| 1454 | 1456 | drv->shutdown(dev); |
| 1455 | 1457 | } |
| 1456 | 1458 | |
| 1457 | − | |
| 1458 | −int platform_dma_configure(struct device *dev) | |
| 1459 | +static int platform_dma_configure(struct device *dev) | |
| 1459 | 1460 | { |
| 1461 | + struct platform_driver *drv = to_platform_driver(dev->driver); | |
| 1460 | 1462 | enum dev_dma_attr attr; |
| 1461 | 1463 | int ret = 0; |
| 1462 | 1464 | |
| @@ -1467,9 +1469,23 @@ int platform_dma_configure(struct device *dev) · 4 unmodified lines | ||
| 1467 | 1469 | ret = acpi_dma_configure(dev, attr); |
| 1468 | 1470 | } |
| 1469 | 1471 | |
| 1472 | + if (!ret && !drv->driver_managed_dma) { | |
| 1473 | + ret = iommu_device_use_default_domain(dev); | |
| 1474 | + if (ret) | |
| 1475 | + arch_teardown_dma_ops(dev); | |
| 1476 | + } | |
| 1477 | + | |
| 1470 | 1478 | return ret; |
| 1471 | 1479 | } |
| 1472 | 1480 | |
| 1481 | +static void platform_dma_cleanup(struct device *dev) | |
| 1482 | +{ | |
| 1483 | + struct platform_driver *drv = to_platform_driver(dev->driver); | |
| 1484 | + | |
| 1485 | + if (!drv->driver_managed_dma) | |
| 1486 | + iommu_device_unuse_default_domain(dev); | |
| 1487 | +} | |
| 1488 | + | |
| 1473 | 1489 | static const struct dev_pm_ops platform_dev_pm_ops = { |
| 1474 | 1490 | SET_RUNTIME_PM_OPS(pm_generic_runtime_suspend, pm_generic_runtime_resume, NULL) |
| 1475 | 1491 | USE_PLATFORM_PM_SLEEP_OPS |
| @@ -1484,6 +1500,7 @@ struct bus_type platform_bus_type = { · 8 unmodified lines | ||
| 1484 | 1500 | .remove = platform_remove, |
| 1485 | 1501 | .shutdown = platform_shutdown, |
| 1486 | 1502 | .dma_configure = platform_dma_configure, |
| 1503 | + .dma_cleanup = platform_dma_cleanup, | |
| 1487 | 1504 | .pm = &platform_dev_pm_ops, |
| 1488 | 1505 | }; |
| 1489 | 1506 | EXPORT_SYMBOL_GPL(platform_bus_type); |
| @@ -152,9 +152,19 @@ static struct attribute *default_attrs[] = { · 151 unmodified lines | ||
| 152 | 152 | NULL |
| 153 | 153 | }; |
| 154 | 154 | |
| 155 | +static umode_t topology_is_visible(struct kobject *kobj, | |
| 156 | + struct attribute *attr, int unused) | |
| 157 | +{ | |
| 158 | + if (attr == &dev_attr_ppin.attr && !topology_ppin(kobj_to_dev(kobj)->id)) | |
| 159 | + return 0; | |
| 160 | + | |
| 161 | + return attr->mode; | |
| 162 | +} | |
| 163 | + | |
| 155 | 164 | static const struct attribute_group topology_attr_group = { |
| 156 | 165 | .attrs = default_attrs, |
| 157 | 166 | .bin_attrs = bin_attrs, |
| 167 | + .is_visible = topology_is_visible, | |
| 158 | 168 | .name = "topology" |
| 159 | 169 | }; |
| 160 | 170 | |
| @@ -33,6 +33,22 @@ config BLK_DEV_FD · 32 unmodified lines | ||
| 33 | 33 | To compile this driver as a module, choose M here: the |
| 34 | 34 | module will be called floppy. |
| 35 | 35 | |
| 36 | +config BLK_DEV_FD_RAWCMD | |
| 37 | + bool "Support for raw floppy disk commands (DEPRECATED)" | |
| 38 | + depends on BLK_DEV_FD | |
| 39 | + help | |
| 40 | + If you want to use actual physical floppies and expect to do | |
| 41 | + special low-level hardware accesses to them (access and use | |
| 42 | + non-standard formats, for example), then enable this. | |
| 43 | + | |
| 44 | + Note that the code enabled by this option is rarely used and | |
| 45 | + might be unstable or insecure, and distros should not enable it. | |
| 46 | + | |
| 47 | + Note: FDRAWCMD is deprecated and will be removed from the kernel | |
| 48 | + in the near future. | |
| 49 | + | |
| 50 | + If unsure, say N. | |
| 51 | + | |
| 36 | 52 | config AMIGA_FLOPPY |
| 37 | 53 | tristate "Amiga floppy support" |
| 38 | 54 | depends on AMIGA |
| @@ -303,6 +303,7 @@ static struct atari_floppy_struct { · 302 unmodified lines | ||
| 303 | 303 | int ref; |
| 304 | 304 | int type; |
| 305 | 305 | struct blk_mq_tag_set tag_set; |
| 306 | + int error_count; | |
| 306 | 307 | } unit[FD_MAX_UNITS]; |
| 307 | 308 | |
| 308 | 309 | #define UD unit[drive] |
| @@ -705,14 +706,14 @@ static void fd_error( void ) · 396 unmodified lines | ||
| 705 | 706 | if (!fd_request) |
| 706 | 707 | return; |
| 707 | 708 | |
| 708 | − fd_request->error_count++; | |
| 709 | − if (fd_request->error_count >= MAX_ERRORS) { | |
| 709 | + unit[SelectedDrive].error_count++; | |
| 710 | + if (unit[SelectedDrive].error_count >= MAX_ERRORS) { | |
| 710 | 711 | printk(KERN_ERR "fd%d: too many errors.\n", SelectedDrive ); |
| 711 | 712 | fd_end_request_cur(BLK_STS_IOERR); |
| 712 | 713 | finish_fdc(); |
| 713 | 714 | return; |
| 714 | 715 | } |
| 715 | − else if (fd_request->error_count == RECALIBRATE_ERRORS) { | |
| 716 | + else if (unit[SelectedDrive].error_count == RECALIBRATE_ERRORS) { | |
| 716 | 717 | printk(KERN_WARNING "fd%d: recalibrating\n", SelectedDrive ); |
| 717 | 718 | if (SelectedDrive != -1) |
| 718 | 719 | SUD.track = -1; |
| @@ -1491,7 +1492,7 @@ static void setup_req_params( int drive ) · 772 unmodified lines | ||
| 1491 | 1492 | ReqData = ReqBuffer + 512 * ReqCnt; |
| 1492 | 1493 | |
| 1493 | 1494 | if (UseTrackbuffer) |
| 1494 | − read_track = (ReqCmd == READ && fd_request->error_count == 0); | |
| 1495 | + read_track = (ReqCmd == READ && unit[drive].error_count == 0); | |
| 1495 | 1496 | else |
| 1496 | 1497 | read_track = 0; |
| 1497 | 1498 | |
| @@ -1520,6 +1521,7 @@ static blk_status_t ataflop_queue_rq(struct blk_mq_hw_ctx *hctx, · 22 unmodified lines | ||
| 1520 | 1521 | return BLK_STS_RESOURCE; |
| 1521 | 1522 | } |
| 1522 | 1523 | fd_request = bd->rq; |
| 1524 | + unit[drive].error_count = 0; | |
| 1523 | 1525 | blk_mq_start_request(fd_request); |
| 1524 | 1526 | |
| 1525 | 1527 | atari_disable_irq( IRQ_MFP_FDC ); |
| @@ -509,8 +509,8 @@ static unsigned long fdc_busy; · 508 unmodified lines | ||
| 509 | 509 | static DECLARE_WAIT_QUEUE_HEAD(fdc_wait); |
| 510 | 510 | static DECLARE_WAIT_QUEUE_HEAD(command_done); |
| 511 | 511 | |
| 512 | −/* Errors during formatting are counted here. */ | |
| 513 | −static int format_errors; | |
| 512 | +/* errors encountered on the current (or last) request */ | |
| 513 | +static int floppy_errors; | |
| 514 | 514 | |
| 515 | 515 | /* Format request descriptor. */ |
| 516 | 516 | static struct format_descr format_req; |
| @@ -530,7 +530,6 @@ static struct format_descr format_req; · 13 unmodified lines | ||
| 530 | 530 | static char *floppy_track_buffer; |
| 531 | 531 | static int max_buffer_sectors; |
| 532 | 532 | |
| 533 | −static int *errors; | |
| 534 | 533 | typedef void (*done_f)(int); |
| 535 | 534 | static const struct cont_t { |
| 536 | 535 | void (*interrupt)(void); |
| @@ -1455,7 +1454,7 @@ static int interpret_errors(void) · 918 unmodified lines | ||
| 1455 | 1454 | if (drive_params[current_drive].flags & FTD_MSG) |
| 1456 | 1455 | DPRINT("Over/Underrun - retrying\n"); |
| 1457 | 1456 | bad = 0; |
| 1458 | − } else if (*errors >= drive_params[current_drive].max_errors.reporting) { | |
| 1457 | + } else if (floppy_errors >= drive_params[current_drive].max_errors.reporting) { | |
| 1459 | 1458 | print_errors(); |
| 1460 | 1459 | } |
| 1461 | 1460 | if (reply_buffer[ST2] & ST2_WC || reply_buffer[ST2] & ST2_BC) |
| @@ -2095,7 +2094,7 @@ static void bad_flp_intr(void) · 633 unmodified lines | ||
| 2095 | 2094 | if (!next_valid_format(current_drive)) |
| 2096 | 2095 | return; |
| 2097 | 2096 | } |
| 2098 | − err_count = ++(*errors); | |
| 2097 | + err_count = ++floppy_errors; | |
| 2099 | 2098 | INFBOUND(write_errors[current_drive].badness, err_count); |
| 2100 | 2099 | if (err_count > drive_params[current_drive].max_errors.abort) |
| 2101 | 2100 | cont->done(0); |
| @@ -2241,9 +2240,8 @@ static int do_format(int drive, struct format_descr *tmp_format_req) · 139 unmodified lines | ||
| 2241 | 2240 | return -EINVAL; |
| 2242 | 2241 | } |
| 2243 | 2242 | format_req = *tmp_format_req; |
| 2244 | − format_errors = 0; | |
| 2245 | 2243 | cont = &format_cont; |
| 2246 | − errors = &format_errors; | |
| 2244 | + floppy_errors = 0; | |
| 2247 | 2245 | ret = wait_til_done(redo_format, true); |
| 2248 | 2246 | if (ret == -EINTR) |
| 2249 | 2247 | return -EINTR; |
| @@ -2759,10 +2757,11 @@ static int set_next_request(void) · 509 unmodified lines | ||
| 2759 | 2757 | current_req = list_first_entry_or_null(&floppy_reqs, struct request, |
| 2760 | 2758 | queuelist); |
| 2761 | 2759 | if (current_req) { |
| 2762 | − current_req->error_count = 0; | |
| 2760 | + floppy_errors = 0; | |
| 2763 | 2761 | list_del_init(¤t_req->queuelist); |
| 2762 | + return 1; | |
| 2764 | 2763 | } |
| 2765 | − return current_req != NULL; | |
| 2764 | + return 0; | |
| 2766 | 2765 | } |
| 2767 | 2766 | |
| 2768 | 2767 | /* Starts or continues processing request. Will automatically unlock the |
| @@ -2821,7 +2820,6 @@ do_request: · 52 unmodified lines | ||
| 2821 | 2820 | _floppy = floppy_type + drive_params[current_drive].autodetect[drive_state[current_drive].probed_format]; |
| 2822 | 2821 | } else |
| 2823 | 2822 | probing = 0; |
| 2824 | − errors = &(current_req->error_count); | |
| 2825 | 2823 | tmp = make_raw_rw_request(); |
| 2826 | 2824 | if (tmp < 2) { |
| 2827 | 2825 | request_done(tmp); |
| @@ -2982,6 +2980,8 @@ static const char *drive_name(int type, int drive) · 154 unmodified lines | ||
| 2982 | 2980 | return "(null)"; |
| 2983 | 2981 | } |
| 2984 | 2982 | |
| 2983 | +#ifdef CONFIG_BLK_DEV_FD_RAWCMD | |
| 2984 | + | |
| 2985 | 2985 | /* raw commands */ |
| 2986 | 2986 | static void raw_cmd_done(int flag) |
| 2987 | 2987 | { |
| @@ -3181,6 +3181,35 @@ static int raw_cmd_ioctl(int cmd, void __user *param) · 193 unmodified lines | ||
| 3181 | 3181 | return ret; |
| 3182 | 3182 | } |
| 3183 | 3183 | |
| 3184 | +static int floppy_raw_cmd_ioctl(int type, int drive, int cmd, | |
| 3185 | + void __user *param) | |
| 3186 | +{ | |
| 3187 | + int ret; | |
| 3188 | + | |
| 3189 | + pr_warn_once("Note: FDRAWCMD is deprecated and will be removed from the kernel in the near future.\n"); | |
| 3190 | + | |
| 3191 | + if (type) | |
| 3192 | + return -EINVAL; | |
| 3193 | + if (lock_fdc(drive)) | |
| 3194 | + return -EINTR; | |
| 3195 | + set_floppy(drive); | |
| 3196 | + ret = raw_cmd_ioctl(cmd, param); | |
| 3197 | + if (ret == -EINTR) | |
| 3198 | + return -EINTR; | |
| 3199 | + process_fd_request(); | |
| 3200 | + return ret; | |
| 3201 | +} | |
| 3202 | + | |
| 3203 | +#else /* CONFIG_BLK_DEV_FD_RAWCMD */ | |
| 3204 | + | |
| 3205 | +static int floppy_raw_cmd_ioctl(int type, int drive, int cmd, | |
| 3206 | + void __user *param) | |
| 3207 | +{ | |
| 3208 | + return -EOPNOTSUPP; | |
| 3209 | +} | |
| 3210 | + | |
| 3211 | +#endif | |
| 3212 | + | |
| 3184 | 3213 | static int invalidate_drive(struct block_device *bdev) |
| 3185 | 3214 | { |
| 3186 | 3215 | /* invalidate the buffer track to force a reread */ |
| @@ -3369,7 +3398,6 @@ static int fd_locked_ioctl(struct block_device *bdev, fmode_t mode, unsigned int · 182 unmodified lines | ||
| 3369 | 3398 | { |
| 3370 | 3399 | int drive = (long)bdev->bd_disk->private_data; |
| 3371 | 3400 | int type = ITYPE(drive_state[drive].fd_device); |
| 3372 | − int i; | |
| 3373 | 3401 | int ret; |
| 3374 | 3402 | int size; |
| 3375 | 3403 | union inparam { |
| @@ -3520,16 +3548,7 @@ static int fd_locked_ioctl(struct block_device *bdev, fmode_t mode, unsigned int · 144 unmodified lines | ||
| 3520 | 3548 | outparam = &write_errors[drive]; |
| 3521 | 3549 | break; |
| 3522 | 3550 | case FDRAWCMD: |
| 3523 | − if (type) | |
| 3524 | − return -EINVAL; | |
| 3525 | − if (lock_fdc(drive)) | |
| 3526 | − return -EINTR; | |
| 3527 | − set_floppy(drive); | |
| 3528 | − i = raw_cmd_ioctl(cmd, (void __user *)param); | |
| 3529 | − if (i == -EINTR) | |
| 3530 | − return -EINTR; | |
| 3531 | − process_fd_request(); | |
| 3532 | − return i; | |
| 3551 | + return floppy_raw_cmd_ioctl(type, drive, cmd, (void __user *)param); | |
| 3533 | 3552 | case FDTWADDLE: |
| 3534 | 3553 | if (lock_fdc(drive)) |
| 3535 | 3554 | return -EINTR; |
| @@ -21,6 +21,7 @@ · 20 unmodified lines | ||
| 21 | 21 | #include <linux/dma-mapping.h> |
| 22 | 22 | #include <linux/acpi.h> |
| 23 | 23 | #include <linux/iommu.h> |
| 24 | +#include <linux/dma-map-ops.h> | |
| 24 | 25 | |
| 25 | 26 | #include "fsl-mc-private.h" |
| 26 | 27 | |
| @@ -140,15 +141,33 @@ static int fsl_mc_dma_configure(struct device *dev) · 113 unmodified lines | ||
| 140 | 141 | { |
| 141 | 142 | struct device *dma_dev = dev; |
| 142 | 143 | struct fsl_mc_device *mc_dev = to_fsl_mc_device(dev); |
| 144 | + struct fsl_mc_driver *mc_drv = to_fsl_mc_driver(dev->driver); | |
| 143 | 145 | u32 input_id = mc_dev->icid; |
| 146 | + int ret; | |
| 144 | 147 | |
| 145 | 148 | while (dev_is_fsl_mc(dma_dev)) |
| 146 | 149 | dma_dev = dma_dev->parent; |
| 147 | 150 | |
| 148 | 151 | if (dev_of_node(dma_dev)) |
| 149 | − return of_dma_configure_id(dev, dma_dev->of_node, 0, &input_id); | |
| 152 | + ret = of_dma_configure_id(dev, dma_dev->of_node, 0, &input_id); | |
| 153 | + else | |
| 154 | + ret = acpi_dma_configure_id(dev, DEV_DMA_COHERENT, &input_id); | |
| 155 | + | |
| 156 | + if (!ret && !mc_drv->driver_managed_dma) { | |
| 157 | + ret = iommu_device_use_default_domain(dev); | |
| 158 | + if (ret) | |
| 159 | + arch_teardown_dma_ops(dev); | |
| 160 | + } | |
| 161 | + | |
| 162 | + return ret; | |
| 163 | +} | |
| 164 | + | |
| 165 | +static void fsl_mc_dma_cleanup(struct device *dev) | |
| 166 | +{ | |
| 167 | + struct fsl_mc_driver *mc_drv = to_fsl_mc_driver(dev->driver); | |
| 150 | 168 | |
| 151 | − return acpi_dma_configure_id(dev, DEV_DMA_COHERENT, &input_id); | |
| 169 | + if (!mc_drv->driver_managed_dma) | |
| 170 | + iommu_device_unuse_default_domain(dev); | |
| 152 | 171 | } |
| 153 | 172 | |
| 154 | 173 | static ssize_t modalias_show(struct device *dev, struct device_attribute *attr, |
| @@ -312,6 +331,7 @@ struct bus_type fsl_mc_bus_type = { · 157 unmodified lines | ||
| 312 | 331 | .match = fsl_mc_bus_match, |
| 313 | 332 | .uevent = fsl_mc_bus_uevent, |
| 314 | 333 | .dma_configure = fsl_mc_dma_configure, |
| 334 | + .dma_cleanup = fsl_mc_dma_cleanup, | |
| 315 | 335 | .dev_groups = fsl_mc_dev_groups, |
| 316 | 336 | .bus_groups = fsl_mc_bus_groups, |
| 317 | 337 | }; |
| @@ -224,8 +224,12 @@ int fsl_mc_msi_domain_alloc_irqs(struct device *dev, unsigned int irq_count) · 223 unmodified lines | ||
| 224 | 224 | if (error) |
| 225 | 225 | return error; |
| 226 | 226 | |
| 227 | + msi_lock_descs(dev); | |
| 227 | 228 | if (msi_first_desc(dev, MSI_DESC_ALL)) |
| 228 | − return -EINVAL; | |
| 229 | + error = -EINVAL; | |
| 230 | + msi_unlock_descs(dev); | |
| 231 | + if (error) | |
| 232 | + return error; | |
| 229 | 233 | |
| 230 | 234 | /* |
| 231 | 235 | * NOTE: Calling this function will trigger the invocation of the |
| @@ -352,8 +352,7 @@ static int of_weim_notify(struct notifier_block *nb, unsigned long action, · 351 unmodified lines | ||
| 352 | 352 | |
| 353 | 353 | pdev = of_find_device_by_node(rd->dn); |
| 354 | 354 | if (!pdev) { |
| 355 | − dev_err(&pdev->dev, | |
| 356 | − "Could not find platform device for '%pOF'\n", | |
| 355 | + pr_err("Could not find platform device for '%pOF'\n", | |
| 357 | 356 | rd->dn); |
| 358 | 357 | |
| 359 | 358 | ret = notifier_from_errno(-EINVAL); |
| @@ -370,7 +369,7 @@ static int of_weim_notify(struct notifier_block *nb, unsigned long action, · 10 unmodified lines | ||
| 370 | 369 | return ret; |
| 371 | 370 | } |
| 372 | 371 | |
| 373 | −struct notifier_block weim_of_notifier = { | |
| 372 | +static struct notifier_block weim_of_notifier = { | |
| 374 | 373 | .notifier_call = of_weim_notify, |
| 375 | 374 | }; |
| 376 | 375 | #endif /* IS_ENABLED(CONFIG_OF_DYNAMIC) */ |
| @@ -1060,6 +1060,7 @@ static int __maybe_unused mhi_pci_freeze(struct device *dev) · 1059 unmodified lines | ||
| 1060 | 1060 | * the intermediate restore kernel reinitializes MHI device with new |
| 1061 | 1061 | * context. |
| 1062 | 1062 | */ |
| 1063 | + flush_work(&mhi_pdev->recovery_work); | |
| 1063 | 1064 | if (test_and_clear_bit(MHI_PCI_DEV_STARTED, &mhi_pdev->status)) { |
| 1064 | 1065 | mhi_power_down(mhi_cntrl, true); |
| 1065 | 1066 | mhi_unprepare_after_power_down(mhi_cntrl); |
| @@ -1085,6 +1086,7 @@ static const struct dev_pm_ops mhi_pci_pm_ops = { · 19 unmodified lines | ||
| 1085 | 1086 | .resume = mhi_pci_resume, |
| 1086 | 1087 | .freeze = mhi_pci_freeze, |
| 1087 | 1088 | .thaw = mhi_pci_restore, |
| 1089 | + .poweroff = mhi_pci_freeze, | |
| 1088 | 1090 | .restore = mhi_pci_restore, |
| 1089 | 1091 | #endif |
| 1090 | 1092 | }; |
| @@ -227,6 +227,8 @@ static struct sunxi_rsb_device *sunxi_rsb_device_create(struct sunxi_rsb *rsb, · 226 unmodified lines | ||
| 227 | 227 | |
| 228 | 228 | dev_dbg(&rdev->dev, "device %s registered\n", dev_name(&rdev->dev)); |
| 229 | 229 | |
| 230 | + return rdev; | |
| 231 | + | |
| 230 | 232 | err_device_add: |
| 231 | 233 | put_device(&rdev->dev); |
| 232 | 234 | |
| @@ -3232,13 +3232,27 @@ static int sysc_check_disabled_devices(struct sysc *ddata) · 3231 unmodified lines | ||
| 3232 | 3232 | */ |
| 3233 | 3233 | static int sysc_check_active_timer(struct sysc *ddata) |
| 3234 | 3234 | { |
| 3235 | + int error; | |
| 3236 | + | |
| 3235 | 3237 | if (ddata->cap->type != TI_SYSC_OMAP2_TIMER && |
| 3236 | 3238 | ddata->cap->type != TI_SYSC_OMAP4_TIMER) |
| 3237 | 3239 | return 0; |
| 3238 | 3240 | |
| 3241 | + /* | |
| 3242 | + * Quirk for omap3 beagleboard revision A to B4 to use gpt12. | |
| 3243 | + * Revision C and later are fixed with commit 23885389dbbb ("ARM: | |
| 3244 | + * dts: Fix timer regression for beagleboard revision c"). This all | |
| 3245 | + * can be dropped if we stop supporting old beagleboard revisions | |
| 3246 | + * A to B4 at some point. | |
| 3247 | + */ | |
| 3248 | + if (sysc_soc->soc == SOC_3430) | |
| 3249 | + error = -ENXIO; | |
| 3250 | + else | |
| 3251 | + error = -EBUSY; | |
| 3252 | + | |
| 3239 | 3253 | if ((ddata->cfg.quirks & SYSC_QUIRK_NO_RESET_ON_INIT) && |
| 3240 | 3254 | (ddata->cfg.quirks & SYSC_QUIRK_NO_IDLE)) |
| 3241 | − return -ENXIO; | |
| 3255 | + return error; | |
| 3242 | 3256 | |
| 3243 | 3257 | return 0; |
| 3244 | 3258 | } |
| @@ -3677,8 +3677,11 @@ static void cleanup_smi_msgs(struct ipmi_smi *intf) · 3676 unmodified lines | ||
| 3677 | 3677 | void ipmi_unregister_smi(struct ipmi_smi *intf) |
| 3678 | 3678 | { |
| 3679 | 3679 | struct ipmi_smi_watcher *w; |
| 3680 | − int intf_num = intf->intf_num, index; | |
| 3680 | + int intf_num, index; | |
| 3681 | 3681 | |
| 3682 | + if (!intf) | |
| 3683 | + return; | |
| 3684 | + intf_num = intf->intf_num; | |
| 3682 | 3685 | mutex_lock(&ipmi_interfaces_mutex); |
| 3683 | 3686 | intf->intf_num = -1; |
| 3684 | 3687 | intf->in_shutdown = true; |
| @@ -4518,6 +4521,8 @@ return_unspecified: · 833 unmodified lines | ||
| 4518 | 4521 | } else |
| 4519 | 4522 | /* The message was sent, start the timer. */ |
| 4520 | 4523 | intf_start_seq_timer(intf, msg->msgid); |
| 4524 | + requeue = 0; | |
| 4525 | + goto out; | |
| 4521 | 4526 | } else if (((msg->rsp[0] >> 2) != ((msg->data[0] >> 2) | 1)) |
| 4522 | 4527 | || (msg->rsp[1] != msg->data[1])) { |
| 4523 | 4528 | /* |
| @@ -2220,10 +2220,7 @@ static void cleanup_one_si(struct smi_info *smi_info) · 2219 unmodified lines | ||
| 2220 | 2220 | return; |
| 2221 | 2221 | |
| 2222 | 2222 | list_del(&smi_info->link); |
| 2223 | − | |
| 2224 | − if (smi_info->intf) | |
| 2225 | − ipmi_unregister_smi(smi_info->intf); | |
| 2226 | − | |
| 2223 | + ipmi_unregister_smi(smi_info->intf); | |
| 2227 | 2224 | kfree(smi_info); |
| 2228 | 2225 | } |
| 2229 | 2226 | |
| @@ -318,6 +318,13 @@ static void crng_reseed(bool force) · 317 unmodified lines | ||
| 318 | 318 | * the resultant ChaCha state to the user, along with the second |
| 319 | 319 | * half of the block containing 32 bytes of random data that may |
| 320 | 320 | * be used; random_data_len may not be greater than 32. |
| 321 | + * | |
| 322 | + * The returned ChaCha state contains within it a copy of the old | |
| 323 | + * key value, at index 4, so the state should always be zeroed out | |
| 324 | + * immediately after using in order to maintain forward secrecy. | |
| 325 | + * If the state cannot be erased in a timely manner, then it is | |
| 326 | + * safer to set the random_data parameter to &chacha_state[4] so | |
| 327 | + * that this function overwrites it before returning. | |
| 321 | 328 | */ |
| 322 | 329 | static void crng_fast_key_erasure(u8 key[CHACHA_KEY_SIZE], |
| 323 | 330 | u32 chacha_state[CHACHA_STATE_WORDS], |
| @@ -333,7 +340,7 @@ static void crng_fast_key_erasure(u8 key[CHACHA_KEY_SIZE], · 9 unmodified lines | ||
| 333 | 340 | chacha20_block(chacha_state, first_block); |
| 334 | 341 | |
| 335 | 342 | memcpy(key, first_block, CHACHA_KEY_SIZE); |
| 336 | − memmove(random_data, first_block + CHACHA_KEY_SIZE, random_data_len); | |
| 343 | + memcpy(random_data, first_block + CHACHA_KEY_SIZE, random_data_len); | |
| 337 | 344 | memzero_explicit(first_block, sizeof(first_block)); |
| 338 | 345 | } |
| 339 | 346 | |
| @@ -11,20 +11,48 @@ · 10 unmodified lines | ||
| 11 | 11 | #include <dt-bindings/clock/microchip,mpfs-clock.h> |
| 12 | 12 | |
| 13 | 13 | /* address offset of control registers */ |
| 14 | +#define REG_MSSPLL_REF_CR 0x08u | |
| 15 | +#define REG_MSSPLL_POSTDIV_CR 0x10u | |
| 16 | +#define REG_MSSPLL_SSCG_2_CR 0x2Cu | |
| 14 | 17 | #define REG_CLOCK_CONFIG_CR 0x08u |
| 18 | +#define REG_RTC_CLOCK_CR 0x0Cu | |
| 15 | 19 | #define REG_SUBBLK_CLOCK_CR 0x84u |
| 16 | 20 | #define REG_SUBBLK_RESET_CR 0x88u |
| 17 | 21 | |
| 22 | +#define MSSPLL_FBDIV_SHIFT 0x00u | |
| 23 | +#define MSSPLL_FBDIV_WIDTH 0x0Cu | |
| 24 | +#define MSSPLL_REFDIV_SHIFT 0x08u | |
| 25 | +#define MSSPLL_REFDIV_WIDTH 0x06u | |
| 26 | +#define MSSPLL_POSTDIV_SHIFT 0x08u | |
| 27 | +#define MSSPLL_POSTDIV_WIDTH 0x07u | |
| 28 | +#define MSSPLL_FIXED_DIV 4u | |
| 29 | + | |
| 18 | 30 | struct mpfs_clock_data { |
| 19 | 31 | void __iomem *base; |
| 32 | + void __iomem *msspll_base; | |
| 20 | 33 | struct clk_hw_onecell_data hw_data; |
| 21 | 34 | }; |
| 22 | 35 | |
| 36 | +struct mpfs_msspll_hw_clock { | |
| 37 | + void __iomem *base; | |
| 38 | + unsigned int id; | |
| 39 | + u32 reg_offset; | |
| 40 | + u32 shift; | |
| 41 | + u32 width; | |
| 42 | + u32 flags; | |
| 43 | + struct clk_hw hw; | |
| 44 | + struct clk_init_data init; | |
| 45 | +}; | |
| 46 | + | |
| 47 | +#define to_mpfs_msspll_clk(_hw) container_of(_hw, struct mpfs_msspll_hw_clock, hw) | |
| 48 | + | |
| 23 | 49 | struct mpfs_cfg_clock { |
| 24 | 50 | const struct clk_div_table *table; |
| 25 | 51 | unsigned int id; |
| 52 | + u32 reg_offset; | |
| 26 | 53 | u8 shift; |
| 27 | 54 | u8 width; |
| 55 | + u8 flags; | |
| 28 | 56 | }; |
| 29 | 57 | |
| 30 | 58 | struct mpfs_cfg_hw_clock { |
| @@ -55,7 +83,7 @@ struct mpfs_periph_hw_clock { · 24 unmodified lines | ||
| 55 | 83 | */ |
| 56 | 84 | static DEFINE_SPINLOCK(mpfs_clk_lock); |
| 57 | 85 | |
| 58 | −static const struct clk_parent_data mpfs_cfg_parent[] = { | |
| 86 | +static const struct clk_parent_data mpfs_ext_ref[] = { | |
| 59 | 87 | { .index = 0 }, |
| 60 | 88 | }; |
| 61 | 89 | |
| @@ -69,6 +97,86 @@ static const struct clk_div_table mpfs_div_ahb_table[] = { · 7 unmodified lines | ||
| 69 | 97 | { 0, 0 } |
| 70 | 98 | }; |
| 71 | 99 | |
| 100 | +/* | |
| 101 | + * The only two supported reference clock frequencies for the PolarFire SoC are | |
| 102 | + * 100 and 125 MHz, as the rtc reference is required to be 1 MHz. | |
| 103 | + * It therefore only needs to have divider table entries corresponding to | |
| 104 | + * divide by 100 and 125. | |
| 105 | + */ | |
| 106 | +static const struct clk_div_table mpfs_div_rtcref_table[] = { | |
| 107 | + { 100, 100 }, { 125, 125 }, | |
| 108 | + { 0, 0 } | |
| 109 | +}; | |
| 110 | + | |
| 111 | +static unsigned long mpfs_clk_msspll_recalc_rate(struct clk_hw *hw, unsigned long prate) | |
| 112 | +{ | |
| 113 | + struct mpfs_msspll_hw_clock *msspll_hw = to_mpfs_msspll_clk(hw); | |
| 114 | + void __iomem *mult_addr = msspll_hw->base + msspll_hw->reg_offset; | |
| 115 | + void __iomem *ref_div_addr = msspll_hw->base + REG_MSSPLL_REF_CR; | |
| 116 | + void __iomem *postdiv_addr = msspll_hw->base + REG_MSSPLL_POSTDIV_CR; | |
| 117 | + u32 mult, ref_div, postdiv; | |
| 118 | + | |
| 119 | + mult = readl_relaxed(mult_addr) >> MSSPLL_FBDIV_SHIFT; | |
| 120 | + mult &= clk_div_mask(MSSPLL_FBDIV_WIDTH); | |
| 121 | + ref_div = readl_relaxed(ref_div_addr) >> MSSPLL_REFDIV_SHIFT; | |
| 122 | + ref_div &= clk_div_mask(MSSPLL_REFDIV_WIDTH); | |
| 123 | + postdiv = readl_relaxed(postdiv_addr) >> MSSPLL_POSTDIV_SHIFT; | |
| 124 | + postdiv &= clk_div_mask(MSSPLL_POSTDIV_WIDTH); | |
| 125 | + | |
| 126 | + return prate * mult / (ref_div * MSSPLL_FIXED_DIV * postdiv); | |
| 127 | +} | |
| 128 | + | |
| 129 | +static const struct clk_ops mpfs_clk_msspll_ops = { | |
| 130 | + .recalc_rate = mpfs_clk_msspll_recalc_rate, | |
| 131 | +}; | |
| 132 | + | |
| 133 | +#define CLK_PLL(_id, _name, _parent, _shift, _width, _flags, _offset) { \ | |
| 134 | + .id = _id, \ | |
| 135 | + .shift = _shift, \ | |
| 136 | + .width = _width, \ | |
| 137 | + .reg_offset = _offset, \ | |
| 138 | + .flags = _flags, \ | |
| 139 | + .hw.init = CLK_HW_INIT_PARENTS_DATA(_name, _parent, &mpfs_clk_msspll_ops, 0), \ | |
| 140 | +} | |
| 141 | + | |
| 142 | +static struct mpfs_msspll_hw_clock mpfs_msspll_clks[] = { | |
| 143 | + CLK_PLL(CLK_MSSPLL, "clk_msspll", mpfs_ext_ref, MSSPLL_FBDIV_SHIFT, | |
| 144 | + MSSPLL_FBDIV_WIDTH, 0, REG_MSSPLL_SSCG_2_CR), | |
| 145 | +}; | |
| 146 | + | |
| 147 | +static int mpfs_clk_register_msspll(struct device *dev, struct mpfs_msspll_hw_clock *msspll_hw, | |
| 148 | + void __iomem *base) | |
| 149 | +{ | |
| 150 | + msspll_hw->base = base; | |
| 151 | + | |
| 152 | + return devm_clk_hw_register(dev, &msspll_hw->hw); | |
| 153 | +} | |
| 154 | + | |
| 155 | +static int mpfs_clk_register_mssplls(struct device *dev, struct mpfs_msspll_hw_clock *msspll_hws, | |
| 156 | + unsigned int num_clks, struct mpfs_clock_data *data) | |
| 157 | +{ | |
| 158 | + void __iomem *base = data->msspll_base; | |
| 159 | + unsigned int i; | |
| 160 | + int ret; | |
| 161 | + | |
| 162 | + for (i = 0; i < num_clks; i++) { | |
| 163 | + struct mpfs_msspll_hw_clock *msspll_hw = &msspll_hws[i]; | |
| 164 | + | |
| 165 | + ret = mpfs_clk_register_msspll(dev, msspll_hw, base); | |
| 166 | + if (ret) | |
| 167 | + return dev_err_probe(dev, ret, "failed to register msspll id: %d\n", | |
| 168 | + CLK_MSSPLL); | |
| 169 | + | |
| 170 | + data->hw_data.hws[msspll_hw->id] = &msspll_hw->hw; | |
| 171 | + } | |
| 172 | + | |
| 173 | + return 0; | |
| 174 | +} | |
| 175 | + | |
| 176 | +/* | |
| 177 | + * "CFG" clocks | |
| 178 | + */ | |
| 179 | + | |
| 72 | 180 | static unsigned long mpfs_cfg_clk_recalc_rate(struct clk_hw *hw, unsigned long prate) |
| 73 | 181 | { |
| 74 | 182 | struct mpfs_cfg_hw_clock *cfg_hw = to_mpfs_cfg_clk(hw); |
| @@ -76,10 +184,10 @@ static unsigned long mpfs_cfg_clk_recalc_rate(struct clk_hw *hw, unsigned long p · 1 unmodified line | ||
| 76 | 184 | void __iomem *base_addr = cfg_hw->sys_base; |
| 77 | 185 | u32 val; |
| 78 | 186 | |
| 79 | − val = readl_relaxed(base_addr + REG_CLOCK_CONFIG_CR) >> cfg->shift; | |
| 187 | + val = readl_relaxed(base_addr + cfg->reg_offset) >> cfg->shift; | |
| 80 | 188 | val &= clk_div_mask(cfg->width); |
| 81 | 189 | |
| 82 | − return prate / (1u << val); | |
| 190 | + return divider_recalc_rate(hw, prate, val, cfg->table, cfg->flags, cfg->width); | |
| 83 | 191 | } |
| 84 | 192 | |
| 85 | 193 | static long mpfs_cfg_clk_round_rate(struct clk_hw *hw, unsigned long rate, unsigned long *prate) |
| @@ -105,11 +213,10 @@ static int mpfs_cfg_clk_set_rate(struct clk_hw *hw, unsigned long rate, unsigned · 19 unmodified lines | ||
| 105 | 213 | return divider_setting; |
| 106 | 214 | |
| 107 | 215 | spin_lock_irqsave(&mpfs_clk_lock, flags); |
| 108 | − | |
| 109 | − val = readl_relaxed(base_addr + REG_CLOCK_CONFIG_CR); | |
| 216 | + val = readl_relaxed(base_addr + cfg->reg_offset); | |
| 110 | 217 | val &= ~(clk_div_mask(cfg->width) << cfg_hw->cfg.shift); |
| 111 | 218 | val |= divider_setting << cfg->shift; |
| 112 | − writel_relaxed(val, base_addr + REG_CLOCK_CONFIG_CR); | |
| 219 | + writel_relaxed(val, base_addr + cfg->reg_offset); | |
| 113 | 220 | |
| 114 | 221 | spin_unlock_irqrestore(&mpfs_clk_lock, flags); |
| 115 | 222 | |
| @@ -122,19 +229,33 @@ static const struct clk_ops mpfs_clk_cfg_ops = { · 6 unmodified lines | ||
| 122 | 229 | .set_rate = mpfs_cfg_clk_set_rate, |
| 123 | 230 | }; |
| 124 | 231 | |
| 125 | −#define CLK_CFG(_id, _name, _parent, _shift, _width, _table, _flags) { \ | |
| 126 | − .cfg.id = _id, \ | |
| 127 | − .cfg.shift = _shift, \ | |
| 128 | − .cfg.width = _width, \ | |
| 129 | − .cfg.table = _table, \ | |
| 130 | − .hw.init = CLK_HW_INIT_PARENTS_DATA(_name, _parent, &mpfs_clk_cfg_ops, \ | |
| 131 | − _flags), \ | |
| 232 | +#define CLK_CFG(_id, _name, _parent, _shift, _width, _table, _flags, _offset) { \ | |
| 233 | + .cfg.id = _id, \ | |
| 234 | + .cfg.shift = _shift, \ | |
| 235 | + .cfg.width = _width, \ | |
| 236 | + .cfg.table = _table, \ | |
| 237 | + .cfg.reg_offset = _offset, \ | |
| 238 | + .cfg.flags = _flags, \ | |
| 239 | + .hw.init = CLK_HW_INIT(_name, _parent, &mpfs_clk_cfg_ops, 0), \ | |
| 132 | 240 | } |
| 133 | 241 | |
| 134 | 242 | static struct mpfs_cfg_hw_clock mpfs_cfg_clks[] = { |
| 135 | − CLK_CFG(CLK_CPU, "clk_cpu", mpfs_cfg_parent, 0, 2, mpfs_div_cpu_axi_table, 0), | |
| 136 | − CLK_CFG(CLK_AXI, "clk_axi", mpfs_cfg_parent, 2, 2, mpfs_div_cpu_axi_table, 0), | |
| 137 | − CLK_CFG(CLK_AHB, "clk_ahb", mpfs_cfg_parent, 4, 2, mpfs_div_ahb_table, 0), | |
| 243 | + CLK_CFG(CLK_CPU, "clk_cpu", "clk_msspll", 0, 2, mpfs_div_cpu_axi_table, 0, | |
| 244 | + REG_CLOCK_CONFIG_CR), | |
| 245 | + CLK_CFG(CLK_AXI, "clk_axi", "clk_msspll", 2, 2, mpfs_div_cpu_axi_table, 0, | |
| 246 | + REG_CLOCK_CONFIG_CR), | |
| 247 | + CLK_CFG(CLK_AHB, "clk_ahb", "clk_msspll", 4, 2, mpfs_div_ahb_table, 0, | |
| 248 | + REG_CLOCK_CONFIG_CR), | |
| 249 | + { | |
| 250 | + .cfg.id = CLK_RTCREF, | |
| 251 | + .cfg.shift = 0, | |
| 252 | + .cfg.width = 12, | |
| 253 | + .cfg.table = mpfs_div_rtcref_table, | |
| 254 | + .cfg.reg_offset = REG_RTC_CLOCK_CR, | |
| 255 | + .cfg.flags = CLK_DIVIDER_ONE_BASED, | |
| 256 | + .hw.init = | |
| 257 | + CLK_HW_INIT_PARENTS_DATA("clk_rtcref", mpfs_ext_ref, &mpfs_clk_cfg_ops, 0), | |
| 258 | + } | |
| 138 | 259 | }; |
| 139 | 260 | |
| 140 | 261 | static int mpfs_clk_register_cfg(struct device *dev, struct mpfs_cfg_hw_clock *cfg_hw, |
| @@ -160,13 +281,17 @@ static int mpfs_clk_register_cfgs(struct device *dev, struct mpfs_cfg_hw_clock * · 19 unmodified lines | ||
| 160 | 281 | return dev_err_probe(dev, ret, "failed to register clock id: %d\n", |
| 161 | 282 | cfg_hw->cfg.id); |
| 162 | 283 | |
| 163 | − id = cfg_hws[i].cfg.id; | |
| 284 | + id = cfg_hw->cfg.id; | |
| 164 | 285 | data->hw_data.hws[id] = &cfg_hw->hw; |
| 165 | 286 | } |
| 166 | 287 | |
| 167 | 288 | return 0; |
| 168 | 289 | } |
| 169 | 290 | |
| 291 | +/* | |
| 292 | + * peripheral clocks - devices connected to axi or ahb buses. | |
| 293 | + */ | |
| 294 | + | |
| 170 | 295 | static int mpfs_periph_clk_enable(struct clk_hw *hw) |
| 171 | 296 | { |
| 172 | 297 | struct mpfs_periph_hw_clock *periph_hw = to_mpfs_periph_clk(hw); |
| @@ -200,10 +325,6 @@ static void mpfs_periph_clk_disable(struct clk_hw *hw) · 27 unmodified lines | ||
| 200 | 325 | |
| 201 | 326 | spin_lock_irqsave(&mpfs_clk_lock, flags); |
| 202 | 327 | |
| 203 | − reg = readl_relaxed(base_addr + REG_SUBBLK_RESET_CR); | |
| 204 | − val = reg | (1u << periph->shift); | |
| 205 | − writel_relaxed(val, base_addr + REG_SUBBLK_RESET_CR); | |
| 206 | − | |
| 207 | 328 | reg = readl_relaxed(base_addr + REG_SUBBLK_CLOCK_CR); |
| 208 | 329 | val = reg & ~(1u << periph->shift); |
| 209 | 330 | writel_relaxed(val, base_addr + REG_SUBBLK_CLOCK_CR); |
| @@ -249,8 +370,10 @@ static const struct clk_ops mpfs_periph_clk_ops = { · 39 unmodified lines | ||
| 249 | 370 | * trap handler |
| 250 | 371 | * - CLK_MMUART0: reserved by the hss |
| 251 | 372 | * - CLK_DDRC: provides clock to the ddr subsystem |
| 252 | − * - CLK_FICx: these provide clocks for sections of the fpga fabric, disabling them would | |
| 253 | − * cause the fabric to go into reset | |
| 373 | + * - CLK_FICx: these provide the processor side clocks to the "FIC" (Fabric InterConnect) | |
| 374 | + * clock domain crossers which provide the interface to the FPGA fabric. Disabling them | |
| 375 | + * causes the FPGA fabric to go into reset. | |
| 376 | + * - CLK_ATHENA: The athena clock is FIC4, which is reserved for the Athena TeraFire. | |
| 254 | 377 | */ |
| 255 | 378 | |
| 256 | 379 | static struct mpfs_periph_hw_clock mpfs_periph_clks[] = { |
| @@ -258,7 +381,7 @@ static struct mpfs_periph_hw_clock mpfs_periph_clks[] = { · 1 unmodified line | ||
| 258 | 381 | CLK_PERIPH(CLK_MAC0, "clk_periph_mac0", PARENT_CLK(AHB), 1, 0), |
| 259 | 382 | CLK_PERIPH(CLK_MAC1, "clk_periph_mac1", PARENT_CLK(AHB), 2, 0), |
| 260 | 383 | CLK_PERIPH(CLK_MMC, "clk_periph_mmc", PARENT_CLK(AHB), 3, 0), |
| 261 | − CLK_PERIPH(CLK_TIMER, "clk_periph_timer", PARENT_CLK(AHB), 4, 0), | |
| 384 | + CLK_PERIPH(CLK_TIMER, "clk_periph_timer", PARENT_CLK(RTCREF), 4, 0), | |
| 262 | 385 | CLK_PERIPH(CLK_MMUART0, "clk_periph_mmuart0", PARENT_CLK(AHB), 5, CLK_IS_CRITICAL), |
| 263 | 386 | CLK_PERIPH(CLK_MMUART1, "clk_periph_mmuart1", PARENT_CLK(AHB), 6, 0), |
| 264 | 387 | CLK_PERIPH(CLK_MMUART2, "clk_periph_mmuart2", PARENT_CLK(AHB), 7, 0), |
| @@ -277,11 +400,11 @@ static struct mpfs_periph_hw_clock mpfs_periph_clks[] = { · 12 unmodified lines | ||
| 277 | 400 | CLK_PERIPH(CLK_GPIO1, "clk_periph_gpio1", PARENT_CLK(AHB), 21, 0), |
| 278 | 401 | CLK_PERIPH(CLK_GPIO2, "clk_periph_gpio2", PARENT_CLK(AHB), 22, 0), |
| 279 | 402 | CLK_PERIPH(CLK_DDRC, "clk_periph_ddrc", PARENT_CLK(AHB), 23, CLK_IS_CRITICAL), |
| 280 | − CLK_PERIPH(CLK_FIC0, "clk_periph_fic0", PARENT_CLK(AHB), 24, CLK_IS_CRITICAL), | |
| 281 | − CLK_PERIPH(CLK_FIC1, "clk_periph_fic1", PARENT_CLK(AHB), 25, CLK_IS_CRITICAL), | |
| 282 | − CLK_PERIPH(CLK_FIC2, "clk_periph_fic2", PARENT_CLK(AHB), 26, CLK_IS_CRITICAL), | |
| 283 | − CLK_PERIPH(CLK_FIC3, "clk_periph_fic3", PARENT_CLK(AHB), 27, CLK_IS_CRITICAL), | |
| 284 | − CLK_PERIPH(CLK_ATHENA, "clk_periph_athena", PARENT_CLK(AHB), 28, 0), | |
| 403 | + CLK_PERIPH(CLK_FIC0, "clk_periph_fic0", PARENT_CLK(AXI), 24, CLK_IS_CRITICAL), | |
| 404 | + CLK_PERIPH(CLK_FIC1, "clk_periph_fic1", PARENT_CLK(AXI), 25, CLK_IS_CRITICAL), | |
| 405 | + CLK_PERIPH(CLK_FIC2, "clk_periph_fic2", PARENT_CLK(AXI), 26, CLK_IS_CRITICAL), | |
| 406 | + CLK_PERIPH(CLK_FIC3, "clk_periph_fic3", PARENT_CLK(AXI), 27, CLK_IS_CRITICAL), | |
| 407 | + CLK_PERIPH(CLK_ATHENA, "clk_periph_athena", PARENT_CLK(AXI), 28, CLK_IS_CRITICAL), | |
| 285 | 408 | CLK_PERIPH(CLK_CFM, "clk_periph_cfm", PARENT_CLK(AHB), 29, 0), |
| 286 | 409 | }; |
| 287 | 410 | |
| @@ -322,8 +445,9 @@ static int mpfs_clk_probe(struct platform_device *pdev) · 34 unmodified lines | ||
| 322 | 445 | unsigned int num_clks; |
| 323 | 446 | int ret; |
| 324 | 447 | |
| 325 | − /* CLK_RESERVED is not part of cfg_clks nor periph_clks, so add 1 */ | |
| 326 | − num_clks = ARRAY_SIZE(mpfs_cfg_clks) + ARRAY_SIZE(mpfs_periph_clks) + 1; | |
| 448 | + /* CLK_RESERVED is not part of clock arrays, so add 1 */ | |
| 449 | + num_clks = ARRAY_SIZE(mpfs_msspll_clks) + ARRAY_SIZE(mpfs_cfg_clks) | |
| 450 | + + ARRAY_SIZE(mpfs_periph_clks) + 1; | |
| 327 | 451 | |
| 328 | 452 | clk_data = devm_kzalloc(dev, struct_size(clk_data, hw_data.hws, num_clks), GFP_KERNEL); |
| 329 | 453 | if (!clk_data) |
| @@ -333,8 +457,17 @@ static int mpfs_clk_probe(struct platform_device *pdev) · 3 unmodified lines | ||
| 333 | 457 | if (IS_ERR(clk_data->base)) |
| 334 | 458 | return PTR_ERR(clk_data->base); |
| 335 | 459 | |
| 460 | + clk_data->msspll_base = devm_platform_ioremap_resource(pdev, 1); | |
| 461 | + if (IS_ERR(clk_data->msspll_base)) | |
| 462 | + return PTR_ERR(clk_data->msspll_base); | |
| 463 | + | |
| 336 | 464 | clk_data->hw_data.num = num_clks; |
| 337 | 465 | |
| 466 | + ret = mpfs_clk_register_mssplls(dev, mpfs_msspll_clks, ARRAY_SIZE(mpfs_msspll_clks), | |
| 467 | + clk_data); | |
| 468 | + if (ret) | |
| 469 | + return ret; | |
| 470 | + | |
| 338 | 471 | ret = mpfs_clk_register_cfgs(dev, mpfs_cfg_clks, ARRAY_SIZE(mpfs_cfg_clks), clk_data); |
| 339 | 472 | if (ret) |
| 340 | 473 | return ret; |
| @@ -818,7 +818,7 @@ EXPORT_SYMBOL_GPL(clk_pixel_ops); · 817 unmodified lines | ||
| 818 | 818 | static int clk_gfx3d_determine_rate(struct clk_hw *hw, |
| 819 | 819 | struct clk_rate_request *req) |
| 820 | 820 | { |
| 821 | − struct clk_rate_request parent_req = { }; | |
| 821 | + struct clk_rate_request parent_req = { .min_rate = 0, .max_rate = ULONG_MAX }; | |
| 822 | 822 | struct clk_rcg2_gfx3d *cgfx = to_clk_rcg2_gfx3d(hw); |
| 823 | 823 | struct clk_hw *xo, *p0, *p1, *p2; |
| 824 | 824 | unsigned long p0_rate; |
| @@ -241,6 +241,7 @@ static struct clk_init_data rtc_32k_init_data = { · 240 unmodified lines | ||
| 241 | 241 | .ops = &ccu_mux_ops, |
| 242 | 242 | .parent_hws = rtc_32k_parents, |
| 243 | 243 | .num_parents = ARRAY_SIZE(rtc_32k_parents), /* updated during probe */ |
| 244 | + .flags = CLK_IS_CRITICAL, | |
| 244 | 245 | }; |
| 245 | 246 | |
| 246 | 247 | static struct ccu_mux rtc_32k_clk = { |
| @@ -346,6 +347,7 @@ static const struct of_device_id sun6i_rtc_ccu_match[] = { · 99 unmodified lines | ||
| 346 | 347 | .compatible = "allwinner,sun50i-r329-rtc", |
| 347 | 348 | .data = &sun50i_r329_rtc_ccu_data, |
| 348 | 349 | }, |
| 350 | + {}, | |
| 349 | 351 | }; |
| 350 | 352 | |
| 351 | 353 | int sun6i_rtc_ccu_probe(struct device *dev, void __iomem *reg) |
| @@ -109,6 +109,8 @@ static int sun9i_a80_mmc_config_clk_probe(struct platform_device *pdev) · 108 unmodified lines | ||
| 109 | 109 | spin_lock_init(&data->lock); |
| 110 | 110 | |
| 111 | 111 | r = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
| 112 | + if (!r) | |
| 113 | + return -EINVAL; | |
| 112 | 114 | /* one clock/reset pair per word */ |
| 113 | 115 | count = DIV_ROUND_UP((resource_size(r)), SUN9I_MMC_WIDTH); |
| 114 | 116 | data->membase = devm_ioremap_resource(&pdev->dev, r); |
| @@ -24,13 +24,17 @@ · 23 unmodified lines | ||
| 24 | 24 | #define CLK_HW_DIV 2 |
| 25 | 25 | #define LUT_TURBO_IND 1 |
| 26 | 26 | |
| 27 | +#define GT_IRQ_STATUS BIT(2) | |
| 28 | + | |
| 27 | 29 | #define HZ_PER_KHZ 1000 |
| 28 | 30 | |
| 29 | 31 | struct qcom_cpufreq_soc_data { |
| 30 | 32 | u32 reg_enable; |
| 33 | + u32 reg_domain_state; | |
| 31 | 34 | u32 reg_dcvs_ctrl; |
| 32 | 35 | u32 reg_freq_lut; |
| 33 | 36 | u32 reg_volt_lut; |
| 37 | + u32 reg_intr_clr; | |
| 34 | 38 | u32 reg_current_vote; |
| 35 | 39 | u32 reg_perf_state; |
| 36 | 40 | u8 lut_row_size; |
| @@ -280,37 +284,46 @@ static void qcom_get_related_cpus(int index, struct cpumask *m) · 243 unmodified lines | ||
| 280 | 284 | } |
| 281 | 285 | } |
| 282 | 286 | |
| 283 | −static unsigned int qcom_lmh_get_throttle_freq(struct qcom_cpufreq_data *data) | |
| 287 | +static unsigned long qcom_lmh_get_throttle_freq(struct qcom_cpufreq_data *data) | |
| 284 | 288 | { |
| 285 | − unsigned int val = readl_relaxed(data->base + data->soc_data->reg_current_vote); | |
| 289 | + unsigned int lval; | |
| 290 | + | |
| 291 | + if (data->soc_data->reg_current_vote) | |
| 292 | + lval = readl_relaxed(data->base + data->soc_data->reg_current_vote) & 0x3ff; | |
| 293 | + else | |
| 294 | + lval = readl_relaxed(data->base + data->soc_data->reg_domain_state) & 0xff; | |
| 286 | 295 | |
| 287 | − return (val & 0x3FF) * 19200; | |
| 296 | + return lval * xo_rate; | |
| 288 | 297 | } |
| 289 | 298 | |
| 290 | 299 | static void qcom_lmh_dcvs_notify(struct qcom_cpufreq_data *data) |
| 291 | 300 | { |
| 292 | 301 | struct cpufreq_policy *policy = data->policy; |
| 293 | − int cpu = cpumask_first(policy->cpus); | |
| 302 | + int cpu = cpumask_first(policy->related_cpus); | |
| 294 | 303 | struct device *dev = get_cpu_device(cpu); |
| 295 | 304 | unsigned long freq_hz, throttled_freq; |
| 296 | 305 | struct dev_pm_opp *opp; |
| 297 | − unsigned int freq; | |
| 298 | 306 | |
| 299 | 307 | /* |
| 300 | 308 | * Get the h/w throttled frequency, normalize it using the |
| 301 | 309 | * registered opp table and use it to calculate thermal pressure. |
| 302 | 310 | */ |
| 303 | − freq = qcom_lmh_get_throttle_freq(data); | |
| 304 | − freq_hz = freq * HZ_PER_KHZ; | |
| 311 | + freq_hz = qcom_lmh_get_throttle_freq(data); | |
| 305 | 312 | |
| 306 | 313 | opp = dev_pm_opp_find_freq_floor(dev, &freq_hz); |
| 307 | 314 | if (IS_ERR(opp) && PTR_ERR(opp) == -ERANGE) |
| 308 | − dev_pm_opp_find_freq_ceil(dev, &freq_hz); | |
| 315 | + opp = dev_pm_opp_find_freq_ceil(dev, &freq_hz); | |
| 316 | + | |
| 317 | + if (IS_ERR(opp)) { | |
| 318 | + dev_warn(dev, "Can't find the OPP for throttling: %pe!\n", opp); | |
| 319 | + } else { | |
| 320 | + throttled_freq = freq_hz / HZ_PER_KHZ; | |
| 309 | 321 | |
| 310 | − throttled_freq = freq_hz / HZ_PER_KHZ; | |
| 322 | + /* Update thermal pressure (the boost frequencies are accepted) */ | |
| 323 | + arch_update_thermal_pressure(policy->related_cpus, throttled_freq); | |
| 311 | 324 | |
| 312 | − /* Update thermal pressure (the boost frequencies are accepted) */ | |
| 313 | − arch_update_thermal_pressure(policy->related_cpus, throttled_freq); | |
| 325 | + dev_pm_opp_put(opp); | |
| 326 | + } | |
| 314 | 327 | |
| 315 | 328 | /* |
| 316 | 329 | * In the unlikely case policy is unregistered do not enable |
| @@ -350,6 +363,10 @@ static irqreturn_t qcom_lmh_dcvs_handle_irq(int irq, void *data) · 33 unmodified lines | ||
| 350 | 363 | disable_irq_nosync(c_data->throttle_irq); |
| 351 | 364 | schedule_delayed_work(&c_data->throttle_work, 0); |
| 352 | 365 | |
| 366 | + if (c_data->soc_data->reg_intr_clr) | |
| 367 | + writel_relaxed(GT_IRQ_STATUS, | |
| 368 | + c_data->base + c_data->soc_data->reg_intr_clr); | |
| 369 | + | |
| 353 | 370 | return IRQ_HANDLED; |
| 354 | 371 | } |
| 355 | 372 | |
| @@ -365,9 +382,11 @@ static const struct qcom_cpufreq_soc_data qcom_soc_data = { · 9 unmodified lines | ||
| 365 | 382 | |
| 366 | 383 | static const struct qcom_cpufreq_soc_data epss_soc_data = { |
| 367 | 384 | .reg_enable = 0x0, |
| 385 | + .reg_domain_state = 0x20, | |
| 368 | 386 | .reg_dcvs_ctrl = 0xb0, |
| 369 | 387 | .reg_freq_lut = 0x100, |
| 370 | 388 | .reg_volt_lut = 0x200, |
| 389 | + .reg_intr_clr = 0x308, | |
| 371 | 390 | .reg_perf_state = 0x320, |
| 372 | 391 | .lut_row_size = 4, |
| 373 | 392 | }; |
| @@ -417,16 +436,39 @@ static int qcom_cpufreq_hw_lmh_init(struct cpufreq_policy *policy, int index) · 43 unmodified lines | ||
| 417 | 436 | return 0; |
| 418 | 437 | } |
| 419 | 438 | |
| 420 | −static void qcom_cpufreq_hw_lmh_exit(struct qcom_cpufreq_data *data) | |
| 439 | +static int qcom_cpufreq_hw_cpu_online(struct cpufreq_policy *policy) | |
| 440 | +{ | |
| 441 | + struct qcom_cpufreq_data *data = policy->driver_data; | |
| 442 | + struct platform_device *pdev = cpufreq_get_driver_data(); | |
| 443 | + int ret; | |
| 444 | + | |
| 445 | + ret = irq_set_affinity_hint(data->throttle_irq, policy->cpus); | |
| 446 | + if (ret) | |
| 447 | + dev_err(&pdev->dev, "Failed to set CPU affinity of %s[%d]\n", | |
| 448 | + data->irq_name, data->throttle_irq); | |
| 449 | + | |
| 450 | + return ret; | |
| 451 | +} | |
| 452 | + | |
| 453 | +static int qcom_cpufreq_hw_cpu_offline(struct cpufreq_policy *policy) | |
| 421 | 454 | { |
| 455 | + struct qcom_cpufreq_data *data = policy->driver_data; | |
| 456 | + | |
| 422 | 457 | if (data->throttle_irq <= 0) |
| 423 | − return; | |
| 458 | + return 0; | |
| 424 | 459 | |
| 425 | 460 | mutex_lock(&data->throttle_lock); |
| 426 | 461 | data->cancel_throttle = true; |
| 427 | 462 | mutex_unlock(&data->throttle_lock); |
| 428 | 463 | |
| 429 | 464 | cancel_delayed_work_sync(&data->throttle_work); |
| 465 | + irq_set_affinity_hint(data->throttle_irq, NULL); | |
| 466 | + | |
| 467 | + return 0; | |
| 468 | +} | |
| 469 | + | |
| 470 | +static void qcom_cpufreq_hw_lmh_exit(struct qcom_cpufreq_data *data) | |
| 471 | +{ | |
| 430 | 472 | free_irq(data->throttle_irq, data); |
| 431 | 473 | } |
| 432 | 474 | |
| @@ -583,6 +625,8 @@ static struct cpufreq_driver cpufreq_qcom_hw_driver = { · 150 unmodified lines | ||
| 583 | 625 | .get = qcom_cpufreq_hw_get, |
| 584 | 626 | .init = qcom_cpufreq_hw_cpu_init, |
| 585 | 627 | .exit = qcom_cpufreq_hw_cpu_exit, |
| 628 | + .online = qcom_cpufreq_hw_cpu_online, | |
| 629 | + .offline = qcom_cpufreq_hw_cpu_offline, | |
| 586 | 630 | .register_em = cpufreq_register_em_with_opp, |
| 587 | 631 | .fast_switch = qcom_cpufreq_hw_fast_switch, |
| 588 | 632 | .name = "qcom-cpufreq-hw", |
| @@ -98,8 +98,10 @@ static int sun50i_cpufreq_nvmem_probe(struct platform_device *pdev) · 97 unmodified lines | ||
| 98 | 98 | return -ENOMEM; |
| 99 | 99 | |
| 100 | 100 | ret = sun50i_cpufreq_get_efuse(&speed); |
| 101 | − if (ret) | |
| 101 | + if (ret) { | |
| 102 | + kfree(opp_tables); | |
| 102 | 103 | return ret; |
| 104 | + } | |
| 103 | 105 | |
| 104 | 106 | snprintf(name, MAX_NAME_LEN, "speed%d", speed); |
| 105 | 107 | |
| @@ -543,10 +543,6 @@ struct dma_buf *dma_buf_export(const struct dma_buf_export_info *exp_info) · 542 unmodified lines | ||
| 543 | 543 | file->f_mode |= FMODE_LSEEK; |
| 544 | 544 | dmabuf->file = file; |
| 545 | 545 | |
| 546 | − ret = dma_buf_stats_setup(dmabuf); | |
| 547 | − if (ret) | |
| 548 | − goto err_sysfs; | |
| 549 | − | |
| 550 | 546 | mutex_init(&dmabuf->lock); |
| 551 | 547 | INIT_LIST_HEAD(&dmabuf->attachments); |
| 552 | 548 | |
| @@ -554,6 +550,10 @@ struct dma_buf *dma_buf_export(const struct dma_buf_export_info *exp_info) · 1 unmodified line | ||
| 554 | 550 | list_add(&dmabuf->list_node, &db_list.head); |
| 555 | 551 | mutex_unlock(&db_list.lock); |
| 556 | 552 | |
| 553 | + ret = dma_buf_stats_setup(dmabuf); | |
| 554 | + if (ret) | |
| 555 | + goto err_sysfs; | |
| 556 | + | |
| 557 | 557 | return dmabuf; |
| 558 | 558 | |
| 559 | 559 | err_sysfs: |
| @@ -668,6 +668,7 @@ EXPORT_SYMBOL_GPL(fw_card_release); · 667 unmodified lines | ||
| 668 | 668 | void fw_core_remove_card(struct fw_card *card) |
| 669 | 669 | { |
| 670 | 670 | struct fw_card_driver dummy_driver = dummy_driver_template; |
| 671 | + unsigned long flags; | |
| 671 | 672 | |
| 672 | 673 | card->driver->update_phy_reg(card, 4, |
| 673 | 674 | PHY_LINK_ACTIVE | PHY_CONTENDER, 0); |
| @@ -682,7 +683,9 @@ void fw_core_remove_card(struct fw_card *card) · 8 unmodified lines | ||
| 682 | 683 | dummy_driver.stop_iso = card->driver->stop_iso; |
| 683 | 684 | card->driver = &dummy_driver; |
| 684 | 685 | |
| 686 | + spin_lock_irqsave(&card->lock, flags); | |
| 685 | 687 | fw_destroy_nodes(card); |
| 688 | + spin_unlock_irqrestore(&card->lock, flags); | |
| 686 | 689 | |
| 687 | 690 | /* Wait for all users, especially device workqueue jobs, to finish. */ |
| 688 | 691 | fw_card_put(card); |
| @@ -1500,6 +1500,7 @@ static void outbound_phy_packet_callback(struct fw_packet *packet, · 1499 unmodified lines | ||
| 1500 | 1500 | { |
| 1501 | 1501 | struct outbound_phy_packet_event *e = |
| 1502 | 1502 | container_of(packet, struct outbound_phy_packet_event, p); |
| 1503 | + struct client *e_client; | |
| 1503 | 1504 | |
| 1504 | 1505 | switch (status) { |
| 1505 | 1506 | /* expected: */ |
| @@ -1516,9 +1517,10 @@ static void outbound_phy_packet_callback(struct fw_packet *packet, · 10 unmodified lines | ||
| 1516 | 1517 | } |
| 1517 | 1518 | e->phy_packet.data[0] = packet->timestamp; |
| 1518 | 1519 | |
| 1520 | + e_client = e->client; | |
| 1519 | 1521 | queue_event(e->client, &e->event, &e->phy_packet, |
| 1520 | 1522 | sizeof(e->phy_packet) + e->phy_packet.length, NULL, 0); |
| 1521 | − client_put(e->client); | |
| 1523 | + client_put(e_client); | |
| 1522 | 1524 | } |
| 1523 | 1525 | |
| 1524 | 1526 | static int ioctl_send_phy_packet(struct client *client, union ioctl_arg *arg) |
| @@ -375,16 +375,13 @@ static void report_found_node(struct fw_card *card, · 374 unmodified lines | ||
| 375 | 375 | card->bm_retries = 0; |
| 376 | 376 | } |
| 377 | 377 | |
| 378 | +/* Must be called with card->lock held */ | |
| 378 | 379 | void fw_destroy_nodes(struct fw_card *card) |
| 379 | 380 | { |
| 380 | − unsigned long flags; | |
| 381 | − | |
| 382 | − spin_lock_irqsave(&card->lock, flags); | |
| 383 | 381 | card->color++; |
| 384 | 382 | if (card->local_node != NULL) |
| 385 | 383 | for_each_fw_node(card, card->local_node, report_lost_node); |
| 386 | 384 | card->local_node = NULL; |
| 387 | − spin_unlock_irqrestore(&card->lock, flags); | |
| 388 | 385 | } |
| 389 | 386 | |
| 390 | 387 | static void move_tree(struct fw_node *node0, struct fw_node *node1, int port) |
| @@ -510,6 +507,8 @@ void fw_core_handle_bus_reset(struct fw_card *card, int node_id, int generation, · 119 unmodified lines | ||
| 510 | 507 | struct fw_node *local_node; |
| 511 | 508 | unsigned long flags; |
| 512 | 509 | |
| 510 | + spin_lock_irqsave(&card->lock, flags); | |
| 511 | + | |
| 513 | 512 | /* |
| 514 | 513 | * If the selfID buffer is not the immediate successor of the |
| 515 | 514 | * previously processed one, we cannot reliably compare the |
| @@ -521,8 +520,6 @@ void fw_core_handle_bus_reset(struct fw_card *card, int node_id, int generation, · 5 unmodified lines | ||
| 521 | 520 | card->bm_retries = 0; |
| 522 | 521 | } |
| 523 | 522 | |
| 524 | − spin_lock_irqsave(&card->lock, flags); | |
| 525 | − | |
| 526 | 523 | card->broadcast_channel_allocated = card->broadcast_channel_auto_allocated; |
| 527 | 524 | card->node_id = node_id; |
| 528 | 525 | /* |
| @@ -73,24 +73,25 @@ static int try_cancel_split_timeout(struct fw_transaction *t) · 72 unmodified lines | ||
| 73 | 73 | static int close_transaction(struct fw_transaction *transaction, |
| 74 | 74 | struct fw_card *card, int rcode) |
| 75 | 75 | { |
| 76 | − struct fw_transaction *t; | |
| 76 | + struct fw_transaction *t = NULL, *iter; | |
| 77 | 77 | unsigned long flags; |
| 78 | 78 | |
| 79 | 79 | spin_lock_irqsave(&card->lock, flags); |
| 80 | − list_for_each_entry(t, &card->transaction_list, link) { | |
| 81 | − if (t == transaction) { | |
| 82 | − if (!try_cancel_split_timeout(t)) { | |
| 80 | + list_for_each_entry(iter, &card->transaction_list, link) { | |
| 81 | + if (iter == transaction) { | |
| 82 | + if (!try_cancel_split_timeout(iter)) { | |
| 83 | 83 | spin_unlock_irqrestore(&card->lock, flags); |
| 84 | 84 | goto timed_out; |
| 85 | 85 | } |
| 86 | − list_del_init(&t->link); | |
| 87 | − card->tlabel_mask &= ~(1ULL << t->tlabel); | |
| 86 | + list_del_init(&iter->link); | |
| 87 | + card->tlabel_mask &= ~(1ULL << iter->tlabel); | |
| 88 | + t = iter; | |
| 88 | 89 | break; |
| 89 | 90 | } |
| 90 | 91 | } |
| 91 | 92 | spin_unlock_irqrestore(&card->lock, flags); |
| 92 | 93 | |
| 93 | − if (&t->link != &card->transaction_list) { | |
| 94 | + if (t) { | |
| 94 | 95 | t->callback(card, rcode, NULL, 0, t->callback_data); |
| 95 | 96 | return 0; |
| 96 | 97 | } |
| @@ -935,7 +936,7 @@ EXPORT_SYMBOL(fw_core_handle_request); · 838 unmodified lines | ||
| 935 | 936 | |
| 936 | 937 | void fw_core_handle_response(struct fw_card *card, struct fw_packet *p) |
| 937 | 938 | { |
| 938 | − struct fw_transaction *t; | |
| 939 | + struct fw_transaction *t = NULL, *iter; | |
| 939 | 940 | unsigned long flags; |
| 940 | 941 | u32 *data; |
| 941 | 942 | size_t data_length; |
| @@ -947,20 +948,21 @@ void fw_core_handle_response(struct fw_card *card, struct fw_packet *p) · 5 unmodified lines | ||
| 947 | 948 | rcode = HEADER_GET_RCODE(p->header[1]); |
| 948 | 949 | |
| 949 | 950 | spin_lock_irqsave(&card->lock, flags); |
| 950 | − list_for_each_entry(t, &card->transaction_list, link) { | |
| 951 | − if (t->node_id == source && t->tlabel == tlabel) { | |
| 952 | − if (!try_cancel_split_timeout(t)) { | |
| 951 | + list_for_each_entry(iter, &card->transaction_list, link) { | |
| 952 | + if (iter->node_id == source && iter->tlabel == tlabel) { | |
| 953 | + if (!try_cancel_split_timeout(iter)) { | |
| 953 | 954 | spin_unlock_irqrestore(&card->lock, flags); |
| 954 | 955 | goto timed_out; |
| 955 | 956 | } |
| 956 | − list_del_init(&t->link); | |
| 957 | − card->tlabel_mask &= ~(1ULL << t->tlabel); | |
| 957 | + list_del_init(&iter->link); | |
| 958 | + card->tlabel_mask &= ~(1ULL << iter->tlabel); | |
| 959 | + t = iter; | |
| 958 | 960 | break; |
| 959 | 961 | } |
| 960 | 962 | } |
| 961 | 963 | spin_unlock_irqrestore(&card->lock, flags); |
| 962 | 964 | |
| 963 | − if (&t->link == &card->transaction_list) { | |
| 965 | + if (!t) { | |
| 964 | 966 | timed_out: |
| 965 | 967 | fw_notice(card, "unsolicited response (source %x, tlabel %x)\n", |
| 966 | 968 | source, tlabel); |
| @@ -408,7 +408,7 @@ static void sbp2_status_write(struct fw_card *card, struct fw_request *request, · 407 unmodified lines | ||
| 408 | 408 | void *payload, size_t length, void *callback_data) |
| 409 | 409 | { |
| 410 | 410 | struct sbp2_logical_unit *lu = callback_data; |
| 411 | − struct sbp2_orb *orb; | |
| 411 | + struct sbp2_orb *orb = NULL, *iter; | |
| 412 | 412 | struct sbp2_status status; |
| 413 | 413 | unsigned long flags; |
| 414 | 414 | |
| @@ -433,17 +433,18 @@ static void sbp2_status_write(struct fw_card *card, struct fw_request *request, · 18 unmodified lines | ||
| 433 | 433 | |
| 434 | 434 | /* Lookup the orb corresponding to this status write. */ |
| 435 | 435 | spin_lock_irqsave(&lu->tgt->lock, flags); |
| 436 | − list_for_each_entry(orb, &lu->orb_list, link) { | |
| 436 | + list_for_each_entry(iter, &lu->orb_list, link) { | |
| 437 | 437 | if (STATUS_GET_ORB_HIGH(status) == 0 && |
| 438 | − STATUS_GET_ORB_LOW(status) == orb->request_bus) { | |
| 439 | − orb->rcode = RCODE_COMPLETE; | |
| 440 | − list_del(&orb->link); | |
| 438 | + STATUS_GET_ORB_LOW(status) == iter->request_bus) { | |
| 439 | + iter->rcode = RCODE_COMPLETE; | |
| 440 | + list_del(&iter->link); | |
| 441 | + orb = iter; | |
| 441 | 442 | break; |
| 442 | 443 | } |
| 443 | 444 | } |
| 444 | 445 | spin_unlock_irqrestore(&lu->tgt->lock, flags); |
| 445 | 446 | |
| 446 | − if (&orb->link != &lu->orb_list) { | |
| 447 | + if (orb) { | |
| 447 | 448 | orb->callback(orb, &status); |
| 448 | 449 | kref_put(&orb->kref, free_orb); /* orb callback reference */ |
| 449 | 450 | } else { |
| @@ -871,13 +871,6 @@ static int mvebu_pwm_probe(struct platform_device *pdev, · 870 unmodified lines | ||
| 871 | 871 | mvpwm->chip.dev = dev; |
| 872 | 872 | mvpwm->chip.ops = &mvebu_pwm_ops; |
| 873 | 873 | mvpwm->chip.npwm = mvchip->chip.ngpio; |
| 874 | − /* | |
| 875 | − * There may already be some PWM allocated, so we can't force | |
| 876 | − * mvpwm->chip.base to a fixed point like mvchip->chip.base. | |
| 877 | − * So, we let pwmchip_add() do the numbering and take the next free | |
| 878 | − * region. | |
| 879 | − */ | |
| 880 | − mvpwm->chip.base = -1; | |
| 881 | 874 | |
| 882 | 875 | spin_lock_init(&mvpwm->lock); |
| 883 | 876 | |
| @@ -762,11 +762,11 @@ static bool pca953x_irq_pending(struct pca953x_chip *chip, unsigned long *pendin · 761 unmodified lines | ||
| 762 | 762 | bitmap_xor(cur_stat, new_stat, old_stat, gc->ngpio); |
| 763 | 763 | bitmap_and(trigger, cur_stat, chip->irq_mask, gc->ngpio); |
| 764 | 764 | |
| 765 | + bitmap_copy(chip->irq_stat, new_stat, gc->ngpio); | |
| 766 | + | |
| 765 | 767 | if (bitmap_empty(trigger, gc->ngpio)) |
| 766 | 768 | return false; |
| 767 | 769 | |
| 768 | − bitmap_copy(chip->irq_stat, new_stat, gc->ngpio); | |
| 769 | − | |
| 770 | 770 | bitmap_and(cur_stat, chip->irq_trig_fall, old_stat, gc->ngpio); |
| 771 | 771 | bitmap_and(old_stat, chip->irq_trig_raise, new_stat, gc->ngpio); |
| 772 | 772 | bitmap_or(new_stat, old_stat, cur_stat, gc->ngpio); |
| @@ -130,7 +130,6 @@ static int visconti_gpio_probe(struct platform_device *pdev) · 129 unmodified lines | ||
| 130 | 130 | struct gpio_irq_chip *girq; |
| 131 | 131 | struct irq_domain *parent; |
| 132 | 132 | struct device_node *irq_parent; |
| 133 | − struct fwnode_handle *fwnode; | |
| 134 | 133 | int ret; |
| 135 | 134 | |
| 136 | 135 | priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); |
| @@ -150,14 +149,12 @@ static int visconti_gpio_probe(struct platform_device *pdev) · 13 unmodified lines | ||
| 150 | 149 | } |
| 151 | 150 | |
| 152 | 151 | parent = irq_find_host(irq_parent); |
| 152 | + of_node_put(irq_parent); | |
| 153 | 153 | if (!parent) { |
| 154 | 154 | dev_err(dev, "No IRQ parent domain\n"); |
| 155 | 155 | return -ENODEV; |
| 156 | 156 | } |
| 157 | 157 | |
| 158 | − fwnode = of_node_to_fwnode(irq_parent); | |
| 159 | − of_node_put(irq_parent); | |
| 160 | − | |
| 161 | 158 | ret = bgpio_init(&priv->gpio_chip, dev, 4, |
| 162 | 159 | priv->base + GPIO_IDATA, |
| 163 | 160 | priv->base + GPIO_OSET, |
| @@ -180,7 +177,7 @@ static int visconti_gpio_probe(struct platform_device *pdev) · 16 unmodified lines | ||
| 180 | 177 | |
| 181 | 178 | girq = &priv->gpio_chip.irq; |
| 182 | 179 | girq->chip = irq_chip; |
| 183 | − girq->fwnode = fwnode; | |
| 180 | + girq->fwnode = of_node_to_fwnode(dev->of_node); | |
| 184 | 181 | girq->parent_domain = parent; |
| 185 | 182 | girq->child_to_parent_hwirq = visconti_gpio_child_to_parent_hwirq; |
| 186 | 183 | girq->populate_parent_alloc_arg = visconti_gpio_populate_parent_fwspec; |
| @@ -910,7 +910,7 @@ static void of_gpiochip_init_valid_mask(struct gpio_chip *chip) · 909 unmodified lines | ||
| 910 | 910 | i, &start); |
| 911 | 911 | of_property_read_u32_index(np, "gpio-reserved-ranges", |
| 912 | 912 | i + 1, &count); |
| 913 | − if (start >= chip->ngpio || start + count >= chip->ngpio) | |
| 913 | + if (start >= chip->ngpio || start + count > chip->ngpio) | |
| 914 | 914 | continue; |
| 915 | 915 | |
| 916 | 916 | bitmap_clear(chip->valid_mask, start, count); |
| @@ -296,6 +296,7 @@ static int amdgpu_ctx_set_stable_pstate(struct amdgpu_ctx *ctx, · 295 unmodified lines | ||
| 296 | 296 | { |
| 297 | 297 | struct amdgpu_device *adev = ctx->adev; |
| 298 | 298 | enum amd_dpm_forced_level level; |
| 299 | + u32 current_stable_pstate; | |
| 299 | 300 | int r; |
| 300 | 301 | |
| 301 | 302 | mutex_lock(&adev->pm.stable_pstate_ctx_lock); |
| @@ -304,6 +305,10 @@ static int amdgpu_ctx_set_stable_pstate(struct amdgpu_ctx *ctx, · 2 unmodified lines | ||
| 304 | 305 | goto done; |
| 305 | 306 | } |
| 306 | 307 | |
| 308 | + r = amdgpu_ctx_get_stable_pstate(ctx, ¤t_stable_pstate); | |
| 309 | + if (r || (stable_pstate == current_stable_pstate)) | |
| 310 | + goto done; | |
| 311 | + | |
| 307 | 312 | switch (stable_pstate) { |
| 308 | 313 | case AMDGPU_CTX_STABLE_PSTATE_NONE: |
| 309 | 314 | level = AMD_DPM_FORCED_LEVEL_AUTO; |
| @@ -2395,6 +2395,71 @@ static int amdgpu_pmops_restore(struct device *dev) · 2394 unmodified lines | ||
| 2395 | 2395 | return amdgpu_device_resume(drm_dev, true); |
| 2396 | 2396 | } |
| 2397 | 2397 | |
| 2398 | +static int amdgpu_runtime_idle_check_display(struct device *dev) | |
| 2399 | +{ | |
| 2400 | + struct pci_dev *pdev = to_pci_dev(dev); | |
| 2401 | + struct drm_device *drm_dev = pci_get_drvdata(pdev); | |
| 2402 | + struct amdgpu_device *adev = drm_to_adev(drm_dev); | |
| 2403 | + | |
| 2404 | + if (adev->mode_info.num_crtc) { | |
| 2405 | + struct drm_connector *list_connector; | |
| 2406 | + struct drm_connector_list_iter iter; | |
| 2407 | + int ret = 0; | |
| 2408 | + | |
| 2409 | + /* XXX: Return busy if any displays are connected to avoid | |
| 2410 | + * possible display wakeups after runtime resume due to | |
| 2411 | + * hotplug events in case any displays were connected while | |
| 2412 | + * the GPU was in suspend. Remove this once that is fixed. | |
| 2413 | + */ | |
| 2414 | + mutex_lock(&drm_dev->mode_config.mutex); | |
| 2415 | + drm_connector_list_iter_begin(drm_dev, &iter); | |
| 2416 | + drm_for_each_connector_iter(list_connector, &iter) { | |
| 2417 | + if (list_connector->status == connector_status_connected) { | |
| 2418 | + ret = -EBUSY; | |
| 2419 | + break; | |
| 2420 | + } | |
| 2421 | + } | |
| 2422 | + drm_connector_list_iter_end(&iter); | |
| 2423 | + mutex_unlock(&drm_dev->mode_config.mutex); | |
| 2424 | + | |
| 2425 | + if (ret) | |
| 2426 | + return ret; | |
| 2427 | + | |
| 2428 | + if (amdgpu_device_has_dc_support(adev)) { | |
| 2429 | + struct drm_crtc *crtc; | |
| 2430 | + | |
| 2431 | + drm_for_each_crtc(crtc, drm_dev) { | |
| 2432 | + drm_modeset_lock(&crtc->mutex, NULL); | |
| 2433 | + if (crtc->state->active) | |
| 2434 | + ret = -EBUSY; | |
| 2435 | + drm_modeset_unlock(&crtc->mutex); | |
| 2436 | + if (ret < 0) | |
| 2437 | + break; | |
| 2438 | + } | |
| 2439 | + } else { | |
| 2440 | + mutex_lock(&drm_dev->mode_config.mutex); | |
| 2441 | + drm_modeset_lock(&drm_dev->mode_config.connection_mutex, NULL); | |
| 2442 | + | |
| 2443 | + drm_connector_list_iter_begin(drm_dev, &iter); | |
| 2444 | + drm_for_each_connector_iter(list_connector, &iter) { | |
| 2445 | + if (list_connector->dpms == DRM_MODE_DPMS_ON) { | |
| 2446 | + ret = -EBUSY; | |
| 2447 | + break; | |
| 2448 | + } | |
| 2449 | + } | |
| 2450 | + | |
| 2451 | + drm_connector_list_iter_end(&iter); | |
| 2452 | + | |
| 2453 | + drm_modeset_unlock(&drm_dev->mode_config.connection_mutex); | |
| 2454 | + mutex_unlock(&drm_dev->mode_config.mutex); | |
| 2455 | + } | |
| 2456 | + if (ret) | |
| 2457 | + return ret; | |
| 2458 | + } | |
| 2459 | + | |
| 2460 | + return 0; | |
| 2461 | +} | |
| 2462 | + | |
| 2398 | 2463 | static int amdgpu_pmops_runtime_suspend(struct device *dev) |
| 2399 | 2464 | { |
| 2400 | 2465 | struct pci_dev *pdev = to_pci_dev(dev); |
| @@ -2407,6 +2472,10 @@ static int amdgpu_pmops_runtime_suspend(struct device *dev) · 6 unmodified lines | ||
| 2407 | 2472 | return -EBUSY; |
| 2408 | 2473 | } |
| 2409 | 2474 | |
| 2475 | + ret = amdgpu_runtime_idle_check_display(dev); | |
| 2476 | + if (ret) | |
| 2477 | + return ret; | |
| 2478 | + | |
| 2410 | 2479 | /* wait for all rings to drain before suspending */ |
| 2411 | 2480 | for (i = 0; i < AMDGPU_MAX_RINGS; i++) { |
| 2412 | 2481 | struct amdgpu_ring *ring = adev->rings[i]; |
| @@ -2516,41 +2585,7 @@ static int amdgpu_pmops_runtime_idle(struct device *dev) · 103 unmodified lines | ||
| 2516 | 2585 | return -EBUSY; |
| 2517 | 2586 | } |
| 2518 | 2587 | |
| 2519 | − if (amdgpu_device_has_dc_support(adev)) { | |
| 2520 | − struct drm_crtc *crtc; | |
| 2521 | − | |
| 2522 | − drm_for_each_crtc(crtc, drm_dev) { | |
| 2523 | − drm_modeset_lock(&crtc->mutex, NULL); | |
| 2524 | − if (crtc->state->active) | |
| 2525 | − ret = -EBUSY; | |
| 2526 | − drm_modeset_unlock(&crtc->mutex); | |
| 2527 | − if (ret < 0) | |
| 2528 | − break; | |
| 2529 | − } | |
| 2530 | − | |
| 2531 | − } else { | |
| 2532 | − struct drm_connector *list_connector; | |
| 2533 | − struct drm_connector_list_iter iter; | |
| 2534 | − | |
| 2535 | − mutex_lock(&drm_dev->mode_config.mutex); | |
| 2536 | − drm_modeset_lock(&drm_dev->mode_config.connection_mutex, NULL); | |
| 2537 | − | |
| 2538 | − drm_connector_list_iter_begin(drm_dev, &iter); | |
| 2539 | − drm_for_each_connector_iter(list_connector, &iter) { | |
| 2540 | − if (list_connector->dpms == DRM_MODE_DPMS_ON) { | |
| 2541 | − ret = -EBUSY; | |
| 2542 | − break; | |
| 2543 | − } | |
| 2544 | − } | |
| 2545 | − | |
| 2546 | − drm_connector_list_iter_end(&iter); | |
| 2547 | − | |
| 2548 | − drm_modeset_unlock(&drm_dev->mode_config.connection_mutex); | |
| 2549 | − mutex_unlock(&drm_dev->mode_config.mutex); | |
| 2550 | − } | |
| 2551 | − | |
| 2552 | − if (ret == -EBUSY) | |
| 2553 | − DRM_DEBUG_DRIVER("failing to power off - crtc active\n"); | |
| 2588 | + ret = amdgpu_runtime_idle_check_display(dev); | |
| 2554 | 2589 | |
| 2555 | 2590 | pm_runtime_mark_last_busy(dev); |
| 2556 | 2591 | pm_runtime_autosuspend(dev); |
| @@ -24,6 +24,7 @@ · 23 unmodified lines | ||
| 24 | 24 | #include <linux/module.h> |
| 25 | 25 | |
| 26 | 26 | #include <drm/drm_drv.h> |
| 27 | +#include <xen/xen.h> | |
| 27 | 28 | |
| 28 | 29 | #include "amdgpu.h" |
| 29 | 30 | #include "amdgpu_ras.h" |
| @@ -710,7 +711,8 @@ void amdgpu_detect_virtualization(struct amdgpu_device *adev) · 680 unmodified lines | ||
| 710 | 711 | adev->virt.caps |= AMDGPU_SRIOV_CAPS_ENABLE_IOV; |
| 711 | 712 | |
| 712 | 713 | if (!reg) { |
| 713 | − if (is_virtual_machine()) /* passthrough mode exclus sriov mod */ | |
| 714 | + /* passthrough mode exclus sriov mod */ | |
| 715 | + if (is_virtual_machine() && !xen_initial_domain()) | |
| 714 | 716 | adev->virt.caps |= AMDGPU_PASSTHROUGH_MODE; |
| 715 | 717 | } |
| 716 | 718 | |
| @@ -1151,6 +1151,16 @@ static int gmc_v10_0_set_clockgating_state(void *handle, · 1150 unmodified lines | ||
| 1151 | 1151 | int r; |
| 1152 | 1152 | struct amdgpu_device *adev = (struct amdgpu_device *)handle; |
| 1153 | 1153 | |
| 1154 | + /* | |
| 1155 | + * The issue mmhub can't disconnect from DF with MMHUB clock gating being disabled | |
| 1156 | + * is a new problem observed at DF 3.0.3, however with the same suspend sequence not | |
| 1157 | + * seen any issue on the DF 3.0.2 series platform. | |
| 1158 | + */ | |
| 1159 | + if (adev->in_s0ix && adev->ip_versions[DF_HWIP][0] > IP_VERSION(3, 0, 2)) { | |
| 1160 | + dev_dbg(adev->dev, "keep mmhub clock gating being enabled for s0ix\n"); | |
| 1161 | + return 0; | |
| 1162 | + } | |
| 1163 | + | |
| 1154 | 1164 | r = adev->mmhub.funcs->set_clockgating(adev, state); |
| 1155 | 1165 | if (r) |
| 1156 | 1166 | return r; |
| @@ -81,6 +81,10 @@ · 80 unmodified lines | ||
| 81 | 81 | #include "mxgpu_vi.h" |
| 82 | 82 | #include "amdgpu_dm.h" |
| 83 | 83 | |
| 84 | +#if IS_ENABLED(CONFIG_X86) | |
| 85 | +#include <asm/intel-family.h> | |
| 86 | +#endif | |
| 87 | + | |
| 84 | 88 | #define ixPCIE_LC_L1_PM_SUBSTATE 0x100100C6 |
| 85 | 89 | #define PCIE_LC_L1_PM_SUBSTATE__LC_L1_SUBSTATES_OVERRIDE_EN_MASK 0x00000001L |
| 86 | 90 | #define PCIE_LC_L1_PM_SUBSTATE__LC_PCI_PM_L1_2_OVERRIDE_MASK 0x00000002L |
| @@ -1134,13 +1138,24 @@ static void vi_enable_aspm(struct amdgpu_device *adev) · 1047 unmodified lines | ||
| 1134 | 1138 | WREG32_PCIE(ixPCIE_LC_CNTL, data); |
| 1135 | 1139 | } |
| 1136 | 1140 | |
| 1141 | +static bool aspm_support_quirk_check(void) | |
| 1142 | +{ | |
| 1143 | +#if IS_ENABLED(CONFIG_X86) | |
| 1144 | + struct cpuinfo_x86 *c = &cpu_data(0); | |
| 1145 | + | |
| 1146 | + return !(c->x86 == 6 && c->x86_model == INTEL_FAM6_ALDERLAKE); | |
| 1147 | +#else | |
| 1148 | + return true; | |
| 1149 | +#endif | |
| 1150 | +} | |
| 1151 | + | |
| 1137 | 1152 | static void vi_program_aspm(struct amdgpu_device *adev) |
| 1138 | 1153 | { |
| 1139 | 1154 | u32 data, data1, orig; |
| 1140 | 1155 | bool bL1SS = false; |
| 1141 | 1156 | bool bClkReqSupport = true; |
| 1142 | 1157 | |
| 1143 | − if (!amdgpu_device_should_use_aspm(adev)) | |
| 1158 | + if (!amdgpu_device_should_use_aspm(adev) || !aspm_support_quirk_check()) | |
| 1144 | 1159 | return; |
| 1145 | 1160 | |
| 1146 | 1161 | if (adev->flags & AMD_IS_APU || |
| @@ -130,19 +130,33 @@ void program_sh_mem_settings(struct device_queue_manager *dqm, · 129 unmodified lines | ||
| 130 | 130 | } |
| 131 | 131 | |
| 132 | 132 | static void increment_queue_count(struct device_queue_manager *dqm, |
| 133 | − enum kfd_queue_type type) | |
| 133 | + struct qcm_process_device *qpd, | |
| 134 | + struct queue *q) | |
| 134 | 135 | { |
| 135 | 136 | dqm->active_queue_count++; |
| 136 | − if (type == KFD_QUEUE_TYPE_COMPUTE || type == KFD_QUEUE_TYPE_DIQ) | |
| 137 | + if (q->properties.type == KFD_QUEUE_TYPE_COMPUTE || | |
| 138 | + q->properties.type == KFD_QUEUE_TYPE_DIQ) | |
| 137 | 139 | dqm->active_cp_queue_count++; |
| 140 | + | |
| 141 | + if (q->properties.is_gws) { | |
| 142 | + dqm->gws_queue_count++; | |
| 143 | + qpd->mapped_gws_queue = true; | |
| 144 | + } | |
| 138 | 145 | } |
| 139 | 146 | |
| 140 | 147 | static void decrement_queue_count(struct device_queue_manager *dqm, |
| 141 | − enum kfd_queue_type type) | |
| 148 | + struct qcm_process_device *qpd, | |
| 149 | + struct queue *q) | |
| 142 | 150 | { |
| 143 | 151 | dqm->active_queue_count--; |
| 144 | − if (type == KFD_QUEUE_TYPE_COMPUTE || type == KFD_QUEUE_TYPE_DIQ) | |
| 152 | + if (q->properties.type == KFD_QUEUE_TYPE_COMPUTE || | |
| 153 | + q->properties.type == KFD_QUEUE_TYPE_DIQ) | |
| 145 | 154 | dqm->active_cp_queue_count--; |
| 155 | + | |
| 156 | + if (q->properties.is_gws) { | |
| 157 | + dqm->gws_queue_count--; | |
| 158 | + qpd->mapped_gws_queue = false; | |
| 159 | + } | |
| 146 | 160 | } |
| 147 | 161 | |
| 148 | 162 | /* |
| @@ -412,7 +426,7 @@ add_queue_to_list: · 263 unmodified lines | ||
| 412 | 426 | list_add(&q->list, &qpd->queues_list); |
| 413 | 427 | qpd->queue_count++; |
| 414 | 428 | if (q->properties.is_active) |
| 415 | − increment_queue_count(dqm, q->properties.type); | |
| 429 | + increment_queue_count(dqm, qpd, q); | |
| 416 | 430 | |
| 417 | 431 | /* |
| 418 | 432 | * Unconditionally increment this counter, regardless of the queue's |
| @@ -601,13 +615,8 @@ static int destroy_queue_nocpsch_locked(struct device_queue_manager *dqm, · 182 unmodified lines | ||
| 601 | 615 | deallocate_vmid(dqm, qpd, q); |
| 602 | 616 | } |
| 603 | 617 | qpd->queue_count--; |
| 604 | − if (q->properties.is_active) { | |
| 605 | − decrement_queue_count(dqm, q->properties.type); | |
| 606 | − if (q->properties.is_gws) { | |
| 607 | − dqm->gws_queue_count--; | |
| 608 | − qpd->mapped_gws_queue = false; | |
| 609 | − } | |
| 610 | − } | |
| 618 | + if (q->properties.is_active) | |
| 619 | + decrement_queue_count(dqm, qpd, q); | |
| 611 | 620 | |
| 612 | 621 | return retval; |
| 613 | 622 | } |
| @@ -700,12 +709,11 @@ static int update_queue(struct device_queue_manager *dqm, struct queue *q, · 86 unmodified lines | ||
| 700 | 709 | * dqm->active_queue_count to determine whether a new runlist must be |
| 701 | 710 | * uploaded. |
| 702 | 711 | */ |
| 703 | − if (q->properties.is_active && !prev_active) | |
| 704 | − increment_queue_count(dqm, q->properties.type); | |
| 705 | − else if (!q->properties.is_active && prev_active) | |
| 706 | − decrement_queue_count(dqm, q->properties.type); | |
| 707 | − | |
| 708 | − if (q->gws && !q->properties.is_gws) { | |
| 712 | + if (q->properties.is_active && !prev_active) { | |
| 713 | + increment_queue_count(dqm, &pdd->qpd, q); | |
| 714 | + } else if (!q->properties.is_active && prev_active) { | |
| 715 | + decrement_queue_count(dqm, &pdd->qpd, q); | |
| 716 | + } else if (q->gws && !q->properties.is_gws) { | |
| 709 | 717 | if (q->properties.is_active) { |
| 710 | 718 | dqm->gws_queue_count++; |
| 711 | 719 | pdd->qpd.mapped_gws_queue = true; |
| @@ -767,11 +775,7 @@ static int evict_process_queues_nocpsch(struct device_queue_manager *dqm, · 55 unmodified lines | ||
| 767 | 775 | mqd_mgr = dqm->mqd_mgrs[get_mqd_type_from_queue_type( |
| 768 | 776 | q->properties.type)]; |
| 769 | 777 | q->properties.is_active = false; |
| 770 | − decrement_queue_count(dqm, q->properties.type); | |
| 771 | − if (q->properties.is_gws) { | |
| 772 | − dqm->gws_queue_count--; | |
| 773 | − qpd->mapped_gws_queue = false; | |
| 774 | − } | |
| 778 | + decrement_queue_count(dqm, qpd, q); | |
| 775 | 779 | |
| 776 | 780 | if (WARN_ONCE(!dqm->sched_running, "Evict when stopped\n")) |
| 777 | 781 | continue; |
| @@ -817,7 +821,7 @@ static int evict_process_queues_cpsch(struct device_queue_manager *dqm, · 39 unmodified lines | ||
| 817 | 821 | continue; |
| 818 | 822 | |
| 819 | 823 | q->properties.is_active = false; |
| 820 | − decrement_queue_count(dqm, q->properties.type); | |
| 824 | + decrement_queue_count(dqm, qpd, q); | |
| 821 | 825 | } |
| 822 | 826 | pdd->last_evict_timestamp = get_jiffies_64(); |
| 823 | 827 | retval = execute_queues_cpsch(dqm, |
| @@ -888,11 +892,7 @@ static int restore_process_queues_nocpsch(struct device_queue_manager *dqm, · 64 unmodified lines | ||
| 888 | 892 | mqd_mgr = dqm->mqd_mgrs[get_mqd_type_from_queue_type( |
| 889 | 893 | q->properties.type)]; |
| 890 | 894 | q->properties.is_active = true; |
| 891 | − increment_queue_count(dqm, q->properties.type); | |
| 892 | − if (q->properties.is_gws) { | |
| 893 | − dqm->gws_queue_count++; | |
| 894 | − qpd->mapped_gws_queue = true; | |
| 895 | − } | |
| 895 | + increment_queue_count(dqm, qpd, q); | |
| 896 | 896 | |
| 897 | 897 | if (WARN_ONCE(!dqm->sched_running, "Restore when stopped\n")) |
| 898 | 898 | continue; |
| @@ -950,7 +950,7 @@ static int restore_process_queues_cpsch(struct device_queue_manager *dqm, · 51 unmodified lines | ||
| 950 | 950 | continue; |
| 951 | 951 | |
| 952 | 952 | q->properties.is_active = true; |
| 953 | − increment_queue_count(dqm, q->properties.type); | |
| 953 | + increment_queue_count(dqm, &pdd->qpd, q); | |
| 954 | 954 | } |
| 955 | 955 | retval = execute_queues_cpsch(dqm, |
| 956 | 956 | KFD_UNMAP_QUEUES_FILTER_DYNAMIC_QUEUES, 0); |
| @@ -1378,7 +1378,7 @@ static int create_kernel_queue_cpsch(struct device_queue_manager *dqm, · 421 unmodified lines | ||
| 1378 | 1378 | dqm->total_queue_count); |
| 1379 | 1379 | |
| 1380 | 1380 | list_add(&kq->list, &qpd->priv_queue_list); |
| 1381 | − increment_queue_count(dqm, kq->queue->properties.type); | |
| 1381 | + increment_queue_count(dqm, qpd, kq->queue); | |
| 1382 | 1382 | qpd->is_debug = true; |
| 1383 | 1383 | execute_queues_cpsch(dqm, KFD_UNMAP_QUEUES_FILTER_DYNAMIC_QUEUES, 0); |
| 1384 | 1384 | dqm_unlock(dqm); |
| @@ -1392,7 +1392,7 @@ static void destroy_kernel_queue_cpsch(struct device_queue_manager *dqm, · 7 unmodified lines | ||
| 1392 | 1392 | { |
| 1393 | 1393 | dqm_lock(dqm); |
| 1394 | 1394 | list_del(&kq->list); |
| 1395 | − decrement_queue_count(dqm, kq->queue->properties.type); | |
| 1395 | + decrement_queue_count(dqm, qpd, kq->queue); | |
| 1396 | 1396 | qpd->is_debug = false; |
| 1397 | 1397 | execute_queues_cpsch(dqm, KFD_UNMAP_QUEUES_FILTER_ALL_QUEUES, 0); |
| 1398 | 1398 | /* |
| @@ -1467,7 +1467,7 @@ static int create_queue_cpsch(struct device_queue_manager *dqm, struct queue *q, · 68 unmodified lines | ||
| 1467 | 1467 | qpd->queue_count++; |
| 1468 | 1468 | |
| 1469 | 1469 | if (q->properties.is_active) { |
| 1470 | − increment_queue_count(dqm, q->properties.type); | |
| 1470 | + increment_queue_count(dqm, qpd, q); | |
| 1471 | 1471 | |
| 1472 | 1472 | execute_queues_cpsch(dqm, |
| 1473 | 1473 | KFD_UNMAP_QUEUES_FILTER_DYNAMIC_QUEUES, 0); |
| @@ -1683,15 +1683,11 @@ static int destroy_queue_cpsch(struct device_queue_manager *dqm, · 209 unmodified lines | ||
| 1683 | 1683 | list_del(&q->list); |
| 1684 | 1684 | qpd->queue_count--; |
| 1685 | 1685 | if (q->properties.is_active) { |
| 1686 | − decrement_queue_count(dqm, q->properties.type); | |
| 1686 | + decrement_queue_count(dqm, qpd, q); | |
| 1687 | 1687 | retval = execute_queues_cpsch(dqm, |
| 1688 | 1688 | KFD_UNMAP_QUEUES_FILTER_DYNAMIC_QUEUES, 0); |
| 1689 | 1689 | if (retval == -ETIME) |
| 1690 | 1690 | qpd->reset_wavefronts = true; |
| 1691 | − if (q->properties.is_gws) { | |
| 1692 | − dqm->gws_queue_count--; | |
| 1693 | − qpd->mapped_gws_queue = false; | |
| 1694 | − } | |
| 1695 | 1691 | } |
| 1696 | 1692 | |
| 1697 | 1693 | /* |
| @@ -1932,7 +1928,7 @@ static int process_termination_cpsch(struct device_queue_manager *dqm, · 234 unmodified lines | ||
| 1932 | 1928 | /* Clean all kernel queues */ |
| 1933 | 1929 | list_for_each_entry_safe(kq, kq_next, &qpd->priv_queue_list, list) { |
| 1934 | 1930 | list_del(&kq->list); |
| 1935 | − decrement_queue_count(dqm, kq->queue->properties.type); | |
| 1931 | + decrement_queue_count(dqm, qpd, kq->queue); | |
| 1936 | 1932 | qpd->is_debug = false; |
| 1937 | 1933 | dqm->total_queue_count--; |
| 1938 | 1934 | filter = KFD_UNMAP_QUEUES_FILTER_ALL_QUEUES; |
| @@ -1945,13 +1941,8 @@ static int process_termination_cpsch(struct device_queue_manager *dqm, · 6 unmodified lines | ||
| 1945 | 1941 | else if (q->properties.type == KFD_QUEUE_TYPE_SDMA_XGMI) |
| 1946 | 1942 | deallocate_sdma_queue(dqm, q); |
| 1947 | 1943 | |
| 1948 | − if (q->properties.is_active) { | |
| 1949 | − decrement_queue_count(dqm, q->properties.type); | |
| 1950 | − if (q->properties.is_gws) { | |
| 1951 | − dqm->gws_queue_count--; | |
| 1952 | − qpd->mapped_gws_queue = false; | |
| 1953 | − } | |
| 1954 | − } | |
| 1944 | + if (q->properties.is_active) | |
| 1945 | + decrement_queue_count(dqm, qpd, q); | |
| 1955 | 1946 | |
| 1956 | 1947 | dqm->total_queue_count--; |
| 1957 | 1948 | } |
| @@ -1103,7 +1103,7 @@ struct kfd_criu_queue_priv_data { · 1102 unmodified lines | ||
| 1103 | 1103 | uint32_t priority; |
| 1104 | 1104 | uint32_t q_percent; |
| 1105 | 1105 | uint32_t doorbell_id; |
| 1106 | − uint32_t is_gws; | |
| 1106 | + uint32_t gws; | |
| 1107 | 1107 | uint32_t sdma_id; |
| 1108 | 1108 | uint32_t eop_ring_buffer_size; |
| 1109 | 1109 | uint32_t ctx_save_restore_area_size; |
| @@ -636,6 +636,8 @@ static int criu_checkpoint_queue(struct kfd_process_device *pdd, · 635 unmodified lines | ||
| 636 | 636 | q_data->ctx_save_restore_area_size = |
| 637 | 637 | q->properties.ctx_save_restore_area_size; |
| 638 | 638 | |
| 639 | + q_data->gws = !!q->gws; | |
| 640 | + | |
| 639 | 641 | ret = pqm_checkpoint_mqd(&pdd->process->pqm, q->properties.queue_id, mqd, ctl_stack); |
| 640 | 642 | if (ret) { |
| 641 | 643 | pr_err("Failed checkpoint queue_mqd (%d)\n", ret); |
| @@ -743,7 +745,6 @@ static void set_queue_properties_from_criu(struct queue_properties *qp, · 101 unmodified lines | ||
| 743 | 745 | struct kfd_criu_queue_priv_data *q_data) |
| 744 | 746 | { |
| 745 | 747 | qp->is_interop = false; |
| 746 | − qp->is_gws = q_data->is_gws; | |
| 747 | 748 | qp->queue_percent = q_data->q_percent; |
| 748 | 749 | qp->priority = q_data->priority; |
| 749 | 750 | qp->queue_address = q_data->q_address; |
| @@ -826,12 +827,15 @@ int kfd_criu_restore_queue(struct kfd_process *p, · 76 unmodified lines | ||
| 826 | 827 | NULL); |
| 827 | 828 | if (ret) { |
| 828 | 829 | pr_err("Failed to create new queue err:%d\n", ret); |
| 829 | − ret = -EINVAL; | |
| 830 | + goto exit; | |
| 830 | 831 | } |
| 831 | 832 | |
| 833 | + if (q_data->gws) | |
| 834 | + ret = pqm_set_gws(&p->pqm, q_data->q_id, pdd->dev->gws); | |
| 835 | + | |
| 832 | 836 | exit: |
| 833 | 837 | if (ret) |
| 834 | − pr_err("Failed to create queue (%d)\n", ret); | |
| 838 | + pr_err("Failed to restore queue (%d)\n", ret); | |
| 835 | 839 | else |
| 836 | 840 | pr_debug("Queue id %d was restored successfully\n", queue_id); |
| 837 | 841 | |
| @@ -4440,7 +4440,7 @@ static void dp_test_get_audio_test_data(struct dc_link *link, bool disable_video · 4439 unmodified lines | ||
| 4440 | 4440 | &dpcd_pattern_type.value, |
| 4441 | 4441 | sizeof(dpcd_pattern_type)); |
| 4442 | 4442 | |
| 4443 | − channel_count = dpcd_test_mode.bits.channel_count + 1; | |
| 4443 | + channel_count = min(dpcd_test_mode.bits.channel_count + 1, AUDIO_CHANNELS_COUNT); | |
| 4444 | 4444 | |
| 4445 | 4445 | // read pattern periods for requested channels when sawTooth pattern is requested |
| 4446 | 4446 | if (dpcd_pattern_type.value == AUDIO_TEST_PATTERN_SAWTOOTH || |
| @@ -997,6 +997,7 @@ static struct clock_source *dcn21_clock_source_create( · 996 unmodified lines | ||
| 997 | 997 | return &clk_src->base; |
| 998 | 998 | } |
| 999 | 999 | |
| 1000 | + kfree(clk_src); | |
| 1000 | 1001 | BREAK_TO_DEBUGGER(); |
| 1001 | 1002 | return NULL; |
| 1002 | 1003 | } |
| @@ -153,9 +153,4 @@ void dcn31_hw_sequencer_construct(struct dc *dc) · 152 unmodified lines | ||
| 153 | 153 | dc->hwss.init_hw = dcn20_fpga_init_hw; |
| 154 | 154 | dc->hwseq->funcs.init_pipes = NULL; |
| 155 | 155 | } |
| 156 | − if (dc->debug.disable_z10) { | |
| 157 | − /*hw not support z10 or sw disable it*/ | |
| 158 | − dc->hwss.z10_restore = NULL; | |
| 159 | − dc->hwss.z10_save_init = NULL; | |
| 160 | − } | |
| 161 | 156 | } |
| @@ -427,6 +427,7 @@ int amdgpu_dpm_read_sensor(struct amdgpu_device *adev, enum amd_pp_sensors senso · 426 unmodified lines | ||
| 427 | 427 | void amdgpu_dpm_compute_clocks(struct amdgpu_device *adev) |
| 428 | 428 | { |
| 429 | 429 | const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; |
| 430 | + int i; | |
| 430 | 431 | |
| 431 | 432 | if (!adev->pm.dpm_enabled) |
| 432 | 433 | return; |
| @@ -434,6 +435,15 @@ void amdgpu_dpm_compute_clocks(struct amdgpu_device *adev) · 1 unmodified line | ||
| 434 | 435 | if (!pp_funcs->pm_compute_clocks) |
| 435 | 436 | return; |
| 436 | 437 | |
| 438 | + if (adev->mode_info.num_crtc) | |
| 439 | + amdgpu_display_bandwidth_update(adev); | |
| 440 | + | |
| 441 | + for (i = 0; i < AMDGPU_MAX_RINGS; i++) { | |
| 442 | + struct amdgpu_ring *ring = adev->rings[i]; | |
| 443 | + if (ring && ring->sched.ready) | |
| 444 | + amdgpu_fence_wait_empty(ring); | |
| 445 | + } | |
| 446 | + | |
| 437 | 447 | mutex_lock(&adev->pm.mutex); |
| 438 | 448 | pp_funcs->pm_compute_clocks(adev->powerplay.pp_handle); |
| 439 | 449 | mutex_unlock(&adev->pm.mutex); |
| @@ -443,6 +453,20 @@ void amdgpu_dpm_enable_uvd(struct amdgpu_device *adev, bool enable) · 3 unmodified lines | ||
| 443 | 453 | { |
| 444 | 454 | int ret = 0; |
| 445 | 455 | |
| 456 | + if (adev->family == AMDGPU_FAMILY_SI) { | |
| 457 | + mutex_lock(&adev->pm.mutex); | |
| 458 | + if (enable) { | |
| 459 | + adev->pm.dpm.uvd_active = true; | |
| 460 | + adev->pm.dpm.state = POWER_STATE_TYPE_INTERNAL_UVD; | |
| 461 | + } else { | |
| 462 | + adev->pm.dpm.uvd_active = false; | |
| 463 | + } | |
| 464 | + mutex_unlock(&adev->pm.mutex); | |
| 465 | + | |
| 466 | + amdgpu_dpm_compute_clocks(adev); | |
| 467 | + return; | |
| 468 | + } | |
| 469 | + | |
| 446 | 470 | ret = amdgpu_dpm_set_powergating_by_smu(adev, AMD_IP_BLOCK_TYPE_UVD, !enable); |
| 447 | 471 | if (ret) |
| 448 | 472 | DRM_ERROR("Dpm %s uvd failed, ret = %d. \n", |
| @@ -453,6 +477,21 @@ void amdgpu_dpm_enable_vce(struct amdgpu_device *adev, bool enable) · 4 unmodified lines | ||
| 453 | 477 | { |
| 454 | 478 | int ret = 0; |
| 455 | 479 | |
| 480 | + if (adev->family == AMDGPU_FAMILY_SI) { | |
| 481 | + mutex_lock(&adev->pm.mutex); | |
| 482 | + if (enable) { | |
| 483 | + adev->pm.dpm.vce_active = true; | |
| 484 | + /* XXX select vce level based on ring/task */ | |
| 485 | + adev->pm.dpm.vce_level = AMD_VCE_LEVEL_AC_ALL; | |
| 486 | + } else { | |
| 487 | + adev->pm.dpm.vce_active = false; | |
| 488 | + } | |
| 489 | + mutex_unlock(&adev->pm.mutex); | |
| 490 | + | |
| 491 | + amdgpu_dpm_compute_clocks(adev); | |
| 492 | + return; | |
| 493 | + } | |
| 494 | + | |
| 456 | 495 | ret = amdgpu_dpm_set_powergating_by_smu(adev, AMD_IP_BLOCK_TYPE_VCE, !enable); |
| 457 | 496 | if (ret) |
| 458 | 497 | DRM_ERROR("Dpm %s vce failed, ret = %d. \n", |
| @@ -1028,16 +1028,6 @@ static int amdgpu_dpm_change_power_state_locked(struct amdgpu_device *adev) · 1027 unmodified lines | ||
| 1028 | 1028 | void amdgpu_legacy_dpm_compute_clocks(void *handle) |
| 1029 | 1029 | { |
| 1030 | 1030 | struct amdgpu_device *adev = (struct amdgpu_device *)handle; |
| 1031 | − int i = 0; | |
| 1032 | − | |
| 1033 | − if (adev->mode_info.num_crtc) | |
| 1034 | − amdgpu_display_bandwidth_update(adev); | |
| 1035 | − | |
| 1036 | − for (i = 0; i < AMDGPU_MAX_RINGS; i++) { | |
| 1037 | − struct amdgpu_ring *ring = adev->rings[i]; | |
| 1038 | − if (ring && ring->sched.ready) | |
| 1039 | − amdgpu_fence_wait_empty(ring); | |
| 1040 | − } | |
| 1041 | 1031 | |
| 1042 | 1032 | amdgpu_dpm_get_active_displays(adev); |
| 1043 | 1033 | |
| @@ -3892,40 +3892,6 @@ static int si_set_boot_state(struct amdgpu_device *adev) · 3891 unmodified lines | ||
| 3892 | 3892 | } |
| 3893 | 3893 | #endif |
| 3894 | 3894 | |
| 3895 | −static int si_set_powergating_by_smu(void *handle, | |
| 3896 | − uint32_t block_type, | |
| 3897 | − bool gate) | |
| 3898 | −{ | |
| 3899 | − struct amdgpu_device *adev = (struct amdgpu_device *)handle; | |
| 3900 | − | |
| 3901 | − switch (block_type) { | |
| 3902 | − case AMD_IP_BLOCK_TYPE_UVD: | |
| 3903 | − if (!gate) { | |
| 3904 | − adev->pm.dpm.uvd_active = true; | |
| 3905 | − adev->pm.dpm.state = POWER_STATE_TYPE_INTERNAL_UVD; | |
| 3906 | − } else { | |
| 3907 | − adev->pm.dpm.uvd_active = false; | |
| 3908 | − } | |
| 3909 | − | |
| 3910 | − amdgpu_legacy_dpm_compute_clocks(handle); | |
| 3911 | − break; | |
| 3912 | − case AMD_IP_BLOCK_TYPE_VCE: | |
| 3913 | − if (!gate) { | |
| 3914 | − adev->pm.dpm.vce_active = true; | |
| 3915 | − /* XXX select vce level based on ring/task */ | |
| 3916 | − adev->pm.dpm.vce_level = AMD_VCE_LEVEL_AC_ALL; | |
| 3917 | − } else { | |
| 3918 | − adev->pm.dpm.vce_active = false; | |
| 3919 | − } | |
| 3920 | − | |
| 3921 | − amdgpu_legacy_dpm_compute_clocks(handle); | |
| 3922 | − break; | |
| 3923 | − default: | |
| 3924 | − break; | |
| 3925 | − } | |
| 3926 | − return 0; | |
| 3927 | −} | |
| 3928 | − | |
| 3929 | 3895 | static int si_set_sw_state(struct amdgpu_device *adev) |
| 3930 | 3896 | { |
| 3931 | 3897 | return (amdgpu_si_send_msg_to_smc(adev, PPSMC_MSG_SwitchToSwState) == PPSMC_Result_OK) ? |
| @@ -8125,7 +8091,6 @@ static const struct amd_pm_funcs si_dpm_funcs = { · 4193 unmodified lines | ||
| 8125 | 8091 | .print_power_state = &si_dpm_print_power_state, |
| 8126 | 8092 | .debugfs_print_current_performance_level = &si_dpm_debugfs_print_current_performance_level, |
| 8127 | 8093 | .force_performance_level = &si_dpm_force_performance_level, |
| 8128 | − .set_powergating_by_smu = &si_set_powergating_by_smu, | |
| 8129 | 8094 | .vblank_too_short = &si_dpm_vblank_too_short, |
| 8130 | 8095 | .set_fan_control_mode = &si_dpm_set_fan_control_mode, |
| 8131 | 8096 | .get_fan_control_mode = &si_dpm_get_fan_control_mode, |
| @@ -1487,16 +1487,6 @@ static void pp_pm_compute_clocks(void *handle) · 1486 unmodified lines | ||
| 1487 | 1487 | { |
| 1488 | 1488 | struct pp_hwmgr *hwmgr = handle; |
| 1489 | 1489 | struct amdgpu_device *adev = hwmgr->adev; |
| 1490 | − int i = 0; | |
| 1491 | − | |
| 1492 | − if (adev->mode_info.num_crtc) | |
| 1493 | − amdgpu_display_bandwidth_update(adev); | |
| 1494 | − | |
| 1495 | − for (i = 0; i < AMDGPU_MAX_RINGS; i++) { | |
| 1496 | − struct amdgpu_ring *ring = adev->rings[i]; | |
| 1497 | − if (ring && ring->sched.ready) | |
| 1498 | − amdgpu_fence_wait_empty(ring); | |
| 1499 | − } | |
| 1500 | 1490 | |
| 1501 | 1491 | if (!amdgpu_device_has_dc_support(adev)) { |
| 1502 | 1492 | amdgpu_dpm_get_active_displays(adev); |
| @@ -1351,14 +1351,8 @@ static int smu_disable_dpms(struct smu_context *smu) · 1350 unmodified lines | ||
| 1351 | 1351 | { |
| 1352 | 1352 | struct amdgpu_device *adev = smu->adev; |
| 1353 | 1353 | int ret = 0; |
| 1354 | − /* | |
| 1355 | − * TODO: (adev->in_suspend && !adev->in_s0ix) is added to pair | |
| 1356 | − * the workaround which always reset the asic in suspend. | |
| 1357 | − * It's likely that workaround will be dropped in the future. | |
| 1358 | − * Then the change here should be dropped together. | |
| 1359 | − */ | |
| 1360 | 1354 | bool use_baco = !smu->is_apu && |
| 1361 | − (((amdgpu_in_reset(adev) || (adev->in_suspend && !adev->in_s0ix)) && | |
| 1355 | + ((amdgpu_in_reset(adev) && | |
| 1362 | 1356 | (amdgpu_asic_reset_method(adev) == AMD_RESET_METHOD_BACO)) || |
| 1363 | 1357 | ((adev->in_runpm || adev->in_s4) && amdgpu_asic_supports_baco(adev))); |
| 1364 | 1358 | |
| @@ -78,6 +78,7 @@ config DRM_ITE_IT6505 · 77 unmodified lines | ||
| 78 | 78 | tristate "ITE IT6505 DisplayPort bridge" |
| 79 | 79 | depends on OF |
| 80 | 80 | select DRM_KMS_HELPER |
| 81 | + select DRM_DP_HELPER | |
| 81 | 82 | select EXTCON |
| 82 | 83 | help |
| 83 | 84 | ITE IT6505 DisplayPort bridge chip driver. |
| @@ -97,6 +97,14 @@ · 96 unmodified lines | ||
| 97 | 97 | |
| 98 | 98 | #define INTEL_EDP_BRIGHTNESS_OPTIMIZATION_1 0x359 |
| 99 | 99 | |
| 100 | +enum intel_dp_aux_backlight_modparam { | |
| 101 | + INTEL_DP_AUX_BACKLIGHT_AUTO = -1, | |
| 102 | + INTEL_DP_AUX_BACKLIGHT_OFF = 0, | |
| 103 | + INTEL_DP_AUX_BACKLIGHT_ON = 1, | |
| 104 | + INTEL_DP_AUX_BACKLIGHT_FORCE_VESA = 2, | |
| 105 | + INTEL_DP_AUX_BACKLIGHT_FORCE_INTEL = 3, | |
| 106 | +}; | |
| 107 | + | |
| 100 | 108 | /* Intel EDP backlight callbacks */ |
| 101 | 109 | static bool |
| 102 | 110 | intel_dp_aux_supports_hdr_backlight(struct intel_connector *connector) |
| @@ -126,6 +134,24 @@ intel_dp_aux_supports_hdr_backlight(struct intel_connector *connector) · 23 unmodified lines | ||
| 126 | 134 | return false; |
| 127 | 135 | } |
| 128 | 136 | |
| 137 | + /* | |
| 138 | + * If we don't have HDR static metadata there is no way to | |
| 139 | + * runtime detect used range for nits based control. For now | |
| 140 | + * do not use Intel proprietary eDP backlight control if we | |
| 141 | + * don't have this data in panel EDID. In case we find panel | |
| 142 | + * which supports only nits based control, but doesn't provide | |
| 143 | + * HDR static metadata we need to start maintaining table of | |
| 144 | + * ranges for such panels. | |
| 145 | + */ | |
| 146 | + if (i915->params.enable_dpcd_backlight != INTEL_DP_AUX_BACKLIGHT_FORCE_INTEL && | |
| 147 | + !(connector->base.hdr_sink_metadata.hdmi_type1.metadata_type & | |
| 148 | + BIT(HDMI_STATIC_METADATA_TYPE1))) { | |
| 149 | + drm_info(&i915->drm, | |
| 150 | + "Panel is missing HDR static metadata. Possible support for Intel HDR backlight interface is not used. If your backlight controls don't work try booting with i915.enable_dpcd_backlight=%d. needs this, please file a _new_ bug report on drm/i915, see " FDO_BUG_URL " for details.\n", | |
| 151 | + INTEL_DP_AUX_BACKLIGHT_FORCE_INTEL); | |
| 152 | + return false; | |
| 153 | + } | |
| 154 | + | |
| 129 | 155 | panel->backlight.edp.intel.sdr_uses_aux = |
| 130 | 156 | tcon_cap[2] & INTEL_EDP_SDR_TCON_BRIGHTNESS_AUX_CAP; |
| 131 | 157 | |
| @@ -413,14 +439,6 @@ static const struct intel_panel_bl_funcs intel_dp_vesa_bl_funcs = { · 281 unmodified lines | ||
| 413 | 439 | .get = intel_dp_aux_vesa_get_backlight, |
| 414 | 440 | }; |
| 415 | 441 | |
| 416 | −enum intel_dp_aux_backlight_modparam { | |
| 417 | − INTEL_DP_AUX_BACKLIGHT_AUTO = -1, | |
| 418 | − INTEL_DP_AUX_BACKLIGHT_OFF = 0, | |
| 419 | − INTEL_DP_AUX_BACKLIGHT_ON = 1, | |
| 420 | − INTEL_DP_AUX_BACKLIGHT_FORCE_VESA = 2, | |
| 421 | − INTEL_DP_AUX_BACKLIGHT_FORCE_INTEL = 3, | |
| 422 | −}; | |
| 423 | − | |
| 424 | 442 | int intel_dp_aux_init_backlight_funcs(struct intel_connector *connector) |
| 425 | 443 | { |
| 426 | 444 | struct drm_device *dev = connector->base.dev; |
| @@ -1037,7 +1037,7 @@ static int intel_fbc_check_plane(struct intel_atomic_state *state, · 1036 unmodified lines | ||
| 1037 | 1037 | struct intel_plane_state *plane_state = |
| 1038 | 1038 | intel_atomic_get_new_plane_state(state, plane); |
| 1039 | 1039 | const struct drm_framebuffer *fb = plane_state->hw.fb; |
| 1040 | − struct intel_crtc *crtc = to_intel_crtc(plane_state->uapi.crtc); | |
| 1040 | + struct intel_crtc *crtc = to_intel_crtc(plane_state->hw.crtc); | |
| 1041 | 1041 | const struct intel_crtc_state *crtc_state; |
| 1042 | 1042 | struct intel_fbc *fbc = plane->fbc; |
| 1043 | 1043 | |
| @@ -4345,12 +4345,12 @@ · 4344 unmodified lines | ||
| 4345 | 4345 | #define _DSPAADDR 0x70184 |
| 4346 | 4346 | #define _DSPASTRIDE 0x70188 |
| 4347 | 4347 | #define _DSPAPOS 0x7018C /* reserved */ |
| 4348 | −#define DISP_POS_Y_MASK REG_GENMASK(31, 0) | |
| 4348 | +#define DISP_POS_Y_MASK REG_GENMASK(31, 16) | |
| 4349 | 4349 | #define DISP_POS_Y(y) REG_FIELD_PREP(DISP_POS_Y_MASK, (y)) |
| 4350 | 4350 | #define DISP_POS_X_MASK REG_GENMASK(15, 0) |
| 4351 | 4351 | #define DISP_POS_X(x) REG_FIELD_PREP(DISP_POS_X_MASK, (x)) |
| 4352 | 4352 | #define _DSPASIZE 0x70190 |
| 4353 | −#define DISP_HEIGHT_MASK REG_GENMASK(31, 0) | |
| 4353 | +#define DISP_HEIGHT_MASK REG_GENMASK(31, 16) | |
| 4354 | 4354 | #define DISP_HEIGHT(h) REG_FIELD_PREP(DISP_HEIGHT_MASK, (h)) |
| 4355 | 4355 | #define DISP_WIDTH_MASK REG_GENMASK(15, 0) |
| 4356 | 4356 | #define DISP_WIDTH(w) REG_FIELD_PREP(DISP_WIDTH_MASK, (w)) |
| @@ -5152,7 +5152,7 @@ · 795 unmodified lines | ||
| 5152 | 5152 | #define _SEL_FETCH_PLANE_BASE_6_A 0x70940 |
| 5153 | 5153 | #define _SEL_FETCH_PLANE_BASE_7_A 0x70960 |
| 5154 | 5154 | #define _SEL_FETCH_PLANE_BASE_CUR_A 0x70880 |
| 5155 | −#define _SEL_FETCH_PLANE_BASE_1_B 0x70990 | |
| 5155 | +#define _SEL_FETCH_PLANE_BASE_1_B 0x71890 | |
| 5156 | 5156 | |
| 5157 | 5157 | #define _SEL_FETCH_PLANE_BASE_A(plane) _PICK(plane, \ |
| 5158 | 5158 | _SEL_FETCH_PLANE_BASE_1_A, \ |
| @@ -1605,17 +1605,17 @@ void i915_vma_close(struct i915_vma *vma) · 1604 unmodified lines | ||
| 1605 | 1605 | |
| 1606 | 1606 | static void __i915_vma_remove_closed(struct i915_vma *vma) |
| 1607 | 1607 | { |
| 1608 | − struct intel_gt *gt = vma->vm->gt; | |
| 1609 | − | |
| 1610 | − spin_lock_irq(>->closed_lock); | |
| 1611 | 1608 | list_del_init(&vma->closed_link); |
| 1612 | − spin_unlock_irq(>->closed_lock); | |
| 1613 | 1609 | } |
| 1614 | 1610 | |
| 1615 | 1611 | void i915_vma_reopen(struct i915_vma *vma) |
| 1616 | 1612 | { |
| 1613 | + struct intel_gt *gt = vma->vm->gt; | |
| 1614 | + | |
| 1615 | + spin_lock_irq(>->closed_lock); | |
| 1617 | 1616 | if (i915_vma_is_closed(vma)) |
| 1618 | 1617 | __i915_vma_remove_closed(vma); |
| 1618 | + spin_unlock_irq(>->closed_lock); | |
| 1619 | 1619 | } |
| 1620 | 1620 | |
| 1621 | 1621 | void i915_vma_release(struct kref *ref) |
| @@ -1641,6 +1641,7 @@ static void force_unbind(struct i915_vma *vma) · 19 unmodified lines | ||
| 1641 | 1641 | static void release_references(struct i915_vma *vma) |
| 1642 | 1642 | { |
| 1643 | 1643 | struct drm_i915_gem_object *obj = vma->obj; |
| 1644 | + struct intel_gt *gt = vma->vm->gt; | |
| 1644 | 1645 | |
| 1645 | 1646 | GEM_BUG_ON(i915_vma_is_active(vma)); |
| 1646 | 1647 | |
| @@ -1650,7 +1651,9 @@ static void release_references(struct i915_vma *vma) · 3 unmodified lines | ||
| 1650 | 1651 | rb_erase(&vma->obj_node, &obj->vma.tree); |
| 1651 | 1652 | spin_unlock(&obj->vma.lock); |
| 1652 | 1653 | |
| 1654 | + spin_lock_irq(>->closed_lock); | |
| 1653 | 1655 | __i915_vma_remove_closed(vma); |
| 1656 | + spin_unlock_irq(>->closed_lock); | |
| 1654 | 1657 | |
| 1655 | 1658 | __i915_vma_put(vma); |
| 1656 | 1659 | } |
| @@ -580,12 +580,6 @@ static int dp_hpd_plug_handle(struct dp_display_private *dp, u32 data) · 579 unmodified lines | ||
| 580 | 580 | dp->dp_display.connector_type, state); |
| 581 | 581 | mutex_unlock(&dp->event_mutex); |
| 582 | 582 | |
| 583 | − /* | |
| 584 | − * add fail safe mode outside event_mutex scope | |
| 585 | − * to avoid potiential circular lock with drm thread | |
| 586 | − */ | |
| 587 | − dp_panel_add_fail_safe_mode(dp->dp_display.connector); | |
| 588 | − | |
| 589 | 583 | /* uevent will complete connection part */ |
| 590 | 584 | return 0; |
| 591 | 585 | }; |
| @@ -151,15 +151,6 @@ static int dp_panel_update_modes(struct drm_connector *connector, · 150 unmodified lines | ||
| 151 | 151 | return rc; |
| 152 | 152 | } |
| 153 | 153 | |
| 154 | −void dp_panel_add_fail_safe_mode(struct drm_connector *connector) | |
| 155 | −{ | |
| 156 | − /* fail safe edid */ | |
| 157 | − mutex_lock(&connector->dev->mode_config.mutex); | |
| 158 | − if (drm_add_modes_noedid(connector, 640, 480)) | |
| 159 | − drm_set_preferred_mode(connector, 640, 480); | |
| 160 | − mutex_unlock(&connector->dev->mode_config.mutex); | |
| 161 | −} | |
| 162 | − | |
| 163 | 154 | int dp_panel_read_sink_caps(struct dp_panel *dp_panel, |
| 164 | 155 | struct drm_connector *connector) |
| 165 | 156 | { |
| @@ -215,8 +206,6 @@ int dp_panel_read_sink_caps(struct dp_panel *dp_panel, · 49 unmodified lines | ||
| 215 | 206 | rc = -ETIMEDOUT; |
| 216 | 207 | goto end; |
| 217 | 208 | } |
| 218 | − | |
| 219 | − dp_panel_add_fail_safe_mode(connector); | |
| 220 | 209 | } |
| 221 | 210 | |
| 222 | 211 | if (panel->aux_cfg_update_done) { |
| @@ -59,7 +59,6 @@ int dp_panel_init_panel_info(struct dp_panel *dp_panel); · 58 unmodified lines | ||
| 59 | 59 | int dp_panel_deinit(struct dp_panel *dp_panel); |
| 60 | 60 | int dp_panel_timing_cfg(struct dp_panel *dp_panel); |
| 61 | 61 | void dp_panel_dump_regs(struct dp_panel *dp_panel); |
| 62 | −void dp_panel_add_fail_safe_mode(struct drm_connector *connector); | |
| 63 | 62 | int dp_panel_read_sink_caps(struct dp_panel *dp_panel, |
| 64 | 63 | struct drm_connector *connector); |
| 65 | 64 | u32 dp_panel_get_mode_bpp(struct dp_panel *dp_panel, u32 mode_max_bpp, |
| @@ -46,8 +46,9 @@ static bool · 45 unmodified lines | ||
| 46 | 46 | nouveau_get_backlight_name(char backlight_name[BL_NAME_SIZE], |
| 47 | 47 | struct nouveau_backlight *bl) |
| 48 | 48 | { |
| 49 | − const int nb = ida_simple_get(&bl_ida, 0, 0, GFP_KERNEL); | |
| 50 | − if (nb < 0 || nb >= 100) | |
| 49 | + const int nb = ida_alloc_max(&bl_ida, 99, GFP_KERNEL); | |
| 50 | + | |
| 51 | + if (nb < 0) | |
| 51 | 52 | return false; |
| 52 | 53 | if (nb > 0) |
| 53 | 54 | snprintf(backlight_name, BL_NAME_SIZE, "nv_backlight%d", nb); |
| @@ -414,7 +415,7 @@ nouveau_backlight_init(struct drm_connector *connector) · 360 unmodified lines | ||
| 414 | 415 | nv_encoder, ops, &props); |
| 415 | 416 | if (IS_ERR(bl->dev)) { |
| 416 | 417 | if (bl->id >= 0) |
| 417 | − ida_simple_remove(&bl_ida, bl->id); | |
| 418 | + ida_free(&bl_ida, bl->id); | |
| 418 | 419 | ret = PTR_ERR(bl->dev); |
| 419 | 420 | goto fail_alloc; |
| 420 | 421 | } |
| @@ -442,7 +443,7 @@ nouveau_backlight_fini(struct drm_connector *connector) · 21 unmodified lines | ||
| 442 | 443 | return; |
| 443 | 444 | |
| 444 | 445 | if (bl->id >= 0) |
| 445 | − ida_simple_remove(&bl_ida, bl->id); | |
| 446 | + ida_free(&bl_ida, bl->id); | |
| 446 | 447 | |
| 447 | 448 | backlight_device_unregister(bl->dev); |
| 448 | 449 | nv_conn->backlight = NULL; |
| @@ -123,7 +123,7 @@ nvkm_device_tegra_probe_iommu(struct nvkm_device_tegra *tdev) · 122 unmodified lines | ||
| 123 | 123 | |
| 124 | 124 | mutex_init(&tdev->iommu.mutex); |
| 125 | 125 | |
| 126 | − if (iommu_present(&platform_bus_type)) { | |
| 126 | + if (device_iommu_mapped(dev)) { | |
| 127 | 127 | tdev->iommu.domain = iommu_domain_alloc(&platform_bus_type); |
| 128 | 128 | if (!tdev->iommu.domain) |
| 129 | 129 | goto error; |
| @@ -222,13 +222,11 @@ void sun4i_frontend_update_buffer(struct sun4i_frontend *frontend, · 221 unmodified lines | ||
| 222 | 222 | |
| 223 | 223 | /* Set the physical address of the buffer in memory */ |
| 224 | 224 | paddr = drm_fb_cma_get_gem_addr(fb, state, 0); |
| 225 | − paddr -= PHYS_OFFSET; | |
| 226 | 225 | DRM_DEBUG_DRIVER("Setting buffer #0 address to %pad\n", &paddr); |
| 227 | 226 | regmap_write(frontend->regs, SUN4I_FRONTEND_BUF_ADDR0_REG, paddr); |
| 228 | 227 | |
| 229 | 228 | if (fb->format->num_planes > 1) { |
| 230 | 229 | paddr = drm_fb_cma_get_gem_addr(fb, state, swap ? 2 : 1); |
| 231 | − paddr -= PHYS_OFFSET; | |
| 232 | 230 | DRM_DEBUG_DRIVER("Setting buffer #1 address to %pad\n", &paddr); |
| 233 | 231 | regmap_write(frontend->regs, SUN4I_FRONTEND_BUF_ADDR1_REG, |
| 234 | 232 | paddr); |
| @@ -236,7 +234,6 @@ void sun4i_frontend_update_buffer(struct sun4i_frontend *frontend, · 1 unmodified line | ||
| 236 | 234 | |
| 237 | 235 | if (fb->format->num_planes > 2) { |
| 238 | 236 | paddr = drm_fb_cma_get_gem_addr(fb, state, swap ? 1 : 2); |
| 239 | − paddr -= PHYS_OFFSET; | |
| 240 | 237 | DRM_DEBUG_DRIVER("Setting buffer #2 address to %pad\n", &paddr); |
| 241 | 238 | regmap_write(frontend->regs, SUN4I_FRONTEND_BUF_ADDR2_REG, |
| 242 | 239 | paddr); |
| @@ -38,6 +38,7 @@ · 37 unmodified lines | ||
| 38 | 38 | #include <drm/drm_scdc_helper.h> |
| 39 | 39 | #include <linux/clk.h> |
| 40 | 40 | #include <linux/component.h> |
| 41 | +#include <linux/gpio/consumer.h> | |
| 41 | 42 | #include <linux/i2c.h> |
| 42 | 43 | #include <linux/of_address.h> |
| 43 | 44 | #include <linux/of_gpio.h> |
| @@ -528,7 +528,7 @@ int vmw_cmd_send_fence(struct vmw_private *dev_priv, uint32_t *seqno) · 527 unmodified lines | ||
| 528 | 528 | *seqno = atomic_add_return(1, &dev_priv->marker_seq); |
| 529 | 529 | } while (*seqno == 0); |
| 530 | 530 | |
| 531 | − if (!(vmw_fifo_caps(dev_priv) & SVGA_FIFO_CAP_FENCE)) { | |
| 531 | + if (!vmw_has_fences(dev_priv)) { | |
| 532 | 532 | |
| 533 | 533 | /* |
| 534 | 534 | * Don't request hardware to send a fence. The |
| @@ -675,11 +675,14 @@ int vmw_cmd_emit_dummy_query(struct vmw_private *dev_priv, · 140 unmodified lines | ||
| 675 | 675 | */ |
| 676 | 676 | bool vmw_cmd_supported(struct vmw_private *vmw) |
| 677 | 677 | { |
| 678 | − if ((vmw->capabilities & (SVGA_CAP_COMMAND_BUFFERS | | |
| 679 | − SVGA_CAP_CMD_BUFFERS_2)) != 0) | |
| 680 | − return true; | |
| 678 | + bool has_cmdbufs = | |
| 679 | + (vmw->capabilities & (SVGA_CAP_COMMAND_BUFFERS | | |
| 680 | + SVGA_CAP_CMD_BUFFERS_2)) != 0; | |
| 681 | + if (vmw_is_svga_v3(vmw)) | |
| 682 | + return (has_cmdbufs && | |
| 683 | + (vmw->capabilities & SVGA_CAP_GBOBJECTS) != 0); | |
| 681 | 684 | /* |
| 682 | 685 | * We have FIFO cmd's |
| 683 | 686 | */ |
| 684 | − return vmw->fifo_mem != NULL; | |
| 687 | + return has_cmdbufs || vmw->fifo_mem != NULL; | |
| 685 | 688 | } |
| @@ -1679,4 +1679,12 @@ static inline void vmw_irq_status_write(struct vmw_private *vmw, · 1678 unmodified lines | ||
| 1679 | 1679 | outl(status, vmw->io_start + SVGA_IRQSTATUS_PORT); |
| 1680 | 1680 | } |
| 1681 | 1681 | |
| 1682 | +static inline bool vmw_has_fences(struct vmw_private *vmw) | |
| 1683 | +{ | |
| 1684 | + if ((vmw->capabilities & (SVGA_CAP_COMMAND_BUFFERS | | |
| 1685 | + SVGA_CAP_CMD_BUFFERS_2)) != 0) | |
| 1686 | + return true; | |
| 1687 | + return (vmw_fifo_caps(vmw) & SVGA_FIFO_CAP_FENCE) != 0; | |
| 1688 | +} | |
| 1689 | + | |
| 1682 | 1690 | #endif |
| @@ -483,7 +483,7 @@ static int vmw_fb_kms_detach(struct vmw_fb_par *par, · 482 unmodified lines | ||
| 483 | 483 | |
| 484 | 484 | static int vmw_fb_kms_framebuffer(struct fb_info *info) |
| 485 | 485 | { |
| 486 | − struct drm_mode_fb_cmd2 mode_cmd; | |
| 486 | + struct drm_mode_fb_cmd2 mode_cmd = {0}; | |
| 487 | 487 | struct vmw_fb_par *par = info->par; |
| 488 | 488 | struct fb_var_screeninfo *var = &info->var; |
| 489 | 489 | struct drm_framebuffer *cur_fb; |
| @@ -82,6 +82,22 @@ fman_from_fence(struct vmw_fence_obj *fence) · 81 unmodified lines | ||
| 82 | 82 | return container_of(fence->base.lock, struct vmw_fence_manager, lock); |
| 83 | 83 | } |
| 84 | 84 | |
| 85 | +static u32 vmw_fence_goal_read(struct vmw_private *vmw) | |
| 86 | +{ | |
| 87 | + if ((vmw->capabilities2 & SVGA_CAP2_EXTRA_REGS) != 0) | |
| 88 | + return vmw_read(vmw, SVGA_REG_FENCE_GOAL); | |
| 89 | + else | |
| 90 | + return vmw_fifo_mem_read(vmw, SVGA_FIFO_FENCE_GOAL); | |
| 91 | +} | |
| 92 | + | |
| 93 | +static void vmw_fence_goal_write(struct vmw_private *vmw, u32 value) | |
| 94 | +{ | |
| 95 | + if ((vmw->capabilities2 & SVGA_CAP2_EXTRA_REGS) != 0) | |
| 96 | + vmw_write(vmw, SVGA_REG_FENCE_GOAL, value); | |
| 97 | + else | |
| 98 | + vmw_fifo_mem_write(vmw, SVGA_FIFO_FENCE_GOAL, value); | |
| 99 | +} | |
| 100 | + | |
| 85 | 101 | /* |
| 86 | 102 | * Note on fencing subsystem usage of irqs: |
| 87 | 103 | * Typically the vmw_fences_update function is called |
| @@ -392,7 +408,7 @@ static bool vmw_fence_goal_new_locked(struct vmw_fence_manager *fman, · 304 unmodified lines | ||
| 392 | 408 | if (likely(!fman->seqno_valid)) |
| 393 | 409 | return false; |
| 394 | 410 | |
| 395 | − goal_seqno = vmw_fifo_mem_read(fman->dev_priv, SVGA_FIFO_FENCE_GOAL); | |
| 411 | + goal_seqno = vmw_fence_goal_read(fman->dev_priv); | |
| 396 | 412 | if (likely(passed_seqno - goal_seqno >= VMW_FENCE_WRAP)) |
| 397 | 413 | return false; |
| 398 | 414 | |
| @@ -400,9 +416,8 @@ static bool vmw_fence_goal_new_locked(struct vmw_fence_manager *fman, · 1 unmodified line | ||
| 400 | 416 | list_for_each_entry(fence, &fman->fence_list, head) { |
| 401 | 417 | if (!list_empty(&fence->seq_passed_actions)) { |
| 402 | 418 | fman->seqno_valid = true; |
| 403 | − vmw_fifo_mem_write(fman->dev_priv, | |
| 404 | − SVGA_FIFO_FENCE_GOAL, | |
| 405 | − fence->base.seqno); | |
| 419 | + vmw_fence_goal_write(fman->dev_priv, | |
| 420 | + fence->base.seqno); | |
| 406 | 421 | break; |
| 407 | 422 | } |
| 408 | 423 | } |
| @@ -434,13 +449,12 @@ static bool vmw_fence_goal_check_locked(struct vmw_fence_obj *fence) · 25 unmodified lines | ||
| 434 | 449 | if (dma_fence_is_signaled_locked(&fence->base)) |
| 435 | 450 | return false; |
| 436 | 451 | |
| 437 | − goal_seqno = vmw_fifo_mem_read(fman->dev_priv, SVGA_FIFO_FENCE_GOAL); | |
| 452 | + goal_seqno = vmw_fence_goal_read(fman->dev_priv); | |
| 438 | 453 | if (likely(fman->seqno_valid && |
| 439 | 454 | goal_seqno - fence->base.seqno < VMW_FENCE_WRAP)) |
| 440 | 455 | return false; |
| 441 | 456 | |
| 442 | − vmw_fifo_mem_write(fman->dev_priv, SVGA_FIFO_FENCE_GOAL, | |
| 443 | − fence->base.seqno); | |
| 457 | + vmw_fence_goal_write(fman->dev_priv, fence->base.seqno); | |
| 444 | 458 | fman->seqno_valid = true; |
| 445 | 459 | |
| 446 | 460 | return true; |
| @@ -32,6 +32,14 @@ · 31 unmodified lines | ||
| 32 | 32 | |
| 33 | 33 | #define VMW_FENCE_WRAP (1 << 24) |
| 34 | 34 | |
| 35 | +static u32 vmw_irqflag_fence_goal(struct vmw_private *vmw) | |
| 36 | +{ | |
| 37 | + if ((vmw->capabilities2 & SVGA_CAP2_EXTRA_REGS) != 0) | |
| 38 | + return SVGA_IRQFLAG_REG_FENCE_GOAL; | |
| 39 | + else | |
| 40 | + return SVGA_IRQFLAG_FENCE_GOAL; | |
| 41 | +} | |
| 42 | + | |
| 35 | 43 | /** |
| 36 | 44 | * vmw_thread_fn - Deferred (process context) irq handler |
| 37 | 45 | * |
| @@ -96,7 +104,7 @@ static irqreturn_t vmw_irq_handler(int irq, void *arg) · 58 unmodified lines | ||
| 96 | 104 | wake_up_all(&dev_priv->fifo_queue); |
| 97 | 105 | |
| 98 | 106 | if ((masked_status & (SVGA_IRQFLAG_ANY_FENCE | |
| 99 | − SVGA_IRQFLAG_FENCE_GOAL)) && | |
| 107 | + vmw_irqflag_fence_goal(dev_priv))) && | |
| 100 | 108 | !test_and_set_bit(VMW_IRQTHREAD_FENCE, dev_priv->irqthread_pending)) |
| 101 | 109 | ret = IRQ_WAKE_THREAD; |
| 102 | 110 | |
| @@ -137,8 +145,7 @@ bool vmw_seqno_passed(struct vmw_private *dev_priv, · 34 unmodified lines | ||
| 137 | 145 | if (likely(dev_priv->last_read_seqno - seqno < VMW_FENCE_WRAP)) |
| 138 | 146 | return true; |
| 139 | 147 | |
| 140 | − if (!(vmw_fifo_caps(dev_priv) & SVGA_FIFO_CAP_FENCE) && | |
| 141 | − vmw_fifo_idle(dev_priv, seqno)) | |
| 148 | + if (!vmw_has_fences(dev_priv) && vmw_fifo_idle(dev_priv, seqno)) | |
| 142 | 149 | return true; |
| 143 | 150 | |
| 144 | 151 | /** |
| @@ -160,6 +167,7 @@ int vmw_fallback_wait(struct vmw_private *dev_priv, · 15 unmodified lines | ||
| 160 | 167 | unsigned long timeout) |
| 161 | 168 | { |
| 162 | 169 | struct vmw_fifo_state *fifo_state = dev_priv->fifo; |
| 170 | + bool fifo_down = false; | |
| 163 | 171 | |
| 164 | 172 | uint32_t count = 0; |
| 165 | 173 | uint32_t signal_seq; |
| @@ -176,12 +184,14 @@ int vmw_fallback_wait(struct vmw_private *dev_priv, · 10 unmodified lines | ||
| 176 | 184 | */ |
| 177 | 185 | |
| 178 | 186 | if (fifo_idle) { |
| 179 | − down_read(&fifo_state->rwsem); | |
| 180 | 187 | if (dev_priv->cman) { |
| 181 | 188 | ret = vmw_cmdbuf_idle(dev_priv->cman, interruptible, |
| 182 | 189 | 10*HZ); |
| 183 | 190 | if (ret) |
| 184 | 191 | goto out_err; |
| 192 | + } else if (fifo_state) { | |
| 193 | + down_read(&fifo_state->rwsem); | |
| 194 | + fifo_down = true; | |
| 185 | 195 | } |
| 186 | 196 | } |
| 187 | 197 | |
| @@ -218,12 +228,12 @@ int vmw_fallback_wait(struct vmw_private *dev_priv, · 30 unmodified lines | ||
| 218 | 228 | } |
| 219 | 229 | } |
| 220 | 230 | finish_wait(&dev_priv->fence_queue, &__wait); |
| 221 | − if (ret == 0 && fifo_idle) | |
| 231 | + if (ret == 0 && fifo_idle && fifo_state) | |
| 222 | 232 | vmw_fence_write(dev_priv, signal_seq); |
| 223 | 233 | |
| 224 | 234 | wake_up_all(&dev_priv->fence_queue); |
| 225 | 235 | out_err: |
| 226 | − if (fifo_idle) | |
| 236 | + if (fifo_down) | |
| 227 | 237 | up_read(&fifo_state->rwsem); |
| 228 | 238 | |
| 229 | 239 | return ret; |
| @@ -266,13 +276,13 @@ void vmw_seqno_waiter_remove(struct vmw_private *dev_priv) · 36 unmodified lines | ||
| 266 | 276 | |
| 267 | 277 | void vmw_goal_waiter_add(struct vmw_private *dev_priv) |
| 268 | 278 | { |
| 269 | − vmw_generic_waiter_add(dev_priv, SVGA_IRQFLAG_FENCE_GOAL, | |
| 279 | + vmw_generic_waiter_add(dev_priv, vmw_irqflag_fence_goal(dev_priv), | |
| 270 | 280 | &dev_priv->goal_queue_waiters); |
| 271 | 281 | } |
| 272 | 282 | |
| 273 | 283 | void vmw_goal_waiter_remove(struct vmw_private *dev_priv) |
| 274 | 284 | { |
| 275 | − vmw_generic_waiter_remove(dev_priv, SVGA_IRQFLAG_FENCE_GOAL, | |
| 285 | + vmw_generic_waiter_remove(dev_priv, vmw_irqflag_fence_goal(dev_priv), | |
| 276 | 286 | &dev_priv->goal_queue_waiters); |
| 277 | 287 | } |
| 278 | 288 | |
| @@ -1344,7 +1344,6 @@ vmw_kms_new_framebuffer(struct vmw_private *dev_priv, · 1343 unmodified lines | ||
| 1344 | 1344 | ret = vmw_kms_new_framebuffer_surface(dev_priv, surface, &vfb, |
| 1345 | 1345 | mode_cmd, |
| 1346 | 1346 | is_bo_proxy); |
| 1347 | − | |
| 1348 | 1347 | /* |
| 1349 | 1348 | * vmw_create_bo_proxy() adds a reference that is no longer |
| 1350 | 1349 | * needed |
| @@ -1385,13 +1384,16 @@ static struct drm_framebuffer *vmw_kms_fb_create(struct drm_device *dev, · 34 unmodified lines | ||
| 1385 | 1384 | ret = vmw_user_lookup_handle(dev_priv, file_priv, |
| 1386 | 1385 | mode_cmd->handles[0], |
| 1387 | 1386 | &surface, &bo); |
| 1388 | − if (ret) | |
| 1387 | + if (ret) { | |
| 1388 | + DRM_ERROR("Invalid buffer object handle %u (0x%x).\n", | |
| 1389 | + mode_cmd->handles[0], mode_cmd->handles[0]); | |
| 1389 | 1390 | goto err_out; |
| 1391 | + } | |
| 1390 | 1392 | |
| 1391 | 1393 | |
| 1392 | 1394 | if (!bo && |
| 1393 | 1395 | !vmw_kms_srf_ok(dev_priv, mode_cmd->width, mode_cmd->height)) { |
| 1394 | − DRM_ERROR("Surface size cannot exceed %dx%d", | |
| 1396 | + DRM_ERROR("Surface size cannot exceed %dx%d\n", | |
| 1395 | 1397 | dev_priv->texture_max_width, |
| 1396 | 1398 | dev_priv->texture_max_height); |
| 1397 | 1399 | goto err_out; |
| @@ -960,7 +960,7 @@ config SENSORS_LTC4261 · 959 unmodified lines | ||
| 960 | 960 | |
| 961 | 961 | config SENSORS_LTQ_CPUTEMP |
| 962 | 962 | bool "Lantiq cpu temperature sensor driver" |
| 963 | − depends on LANTIQ | |
| 963 | + depends on SOC_XWAY | |
| 964 | 964 | help |
| 965 | 965 | If you say yes here you get support for the temperature |
| 966 | 966 | sensor inside your CPU. |
| @@ -19,6 +19,7 @@ · 18 unmodified lines | ||
| 19 | 19 | #include <linux/log2.h> |
| 20 | 20 | #include <linux/kthread.h> |
| 21 | 21 | #include <linux/regmap.h> |
| 22 | +#include <linux/sched.h> | |
| 22 | 23 | #include <linux/slab.h> |
| 23 | 24 | #include <linux/util_macros.h> |
| 24 | 25 | |
| @@ -294,11 +295,10 @@ static int adt7470_update_thread(void *p) · 269 unmodified lines | ||
| 294 | 295 | adt7470_read_temperatures(data); |
| 295 | 296 | mutex_unlock(&data->lock); |
| 296 | 297 | |
| 297 | − set_current_state(TASK_INTERRUPTIBLE); | |
| 298 | 298 | if (kthread_should_stop()) |
| 299 | 299 | break; |
| 300 | 300 | |
| 301 | − schedule_timeout(msecs_to_jiffies(data->auto_update_interval)); | |
| 301 | + schedule_timeout_interruptible(msecs_to_jiffies(data->auto_update_interval)); | |
| 302 | 302 | } |
| 303 | 303 | |
| 304 | 304 | return 0; |
| @@ -71,7 +71,7 @@ static const struct dmi_system_id asus_wmi_dmi_table[] = { · 70 unmodified lines | ||
| 71 | 71 | DMI_EXACT_MATCH_ASUS_BOARD_NAME("PRIME X399-A"), |
| 72 | 72 | DMI_EXACT_MATCH_ASUS_BOARD_NAME("PRIME X470-PRO"), |
| 73 | 73 | DMI_EXACT_MATCH_ASUS_BOARD_NAME("ROG CROSSHAIR VI EXTREME"), |
| 74 | − DMI_EXACT_MATCH_ASUS_BOARD_NAME("ROG CROSSHAIR VI HERO"), | |
| 74 | + DMI_EXACT_MATCH_ASUS_BOARD_NAME("CROSSHAIR VI HERO"), | |
| 75 | 75 | DMI_EXACT_MATCH_ASUS_BOARD_NAME("ROG CROSSHAIR VI HERO (WI-FI AC)"), |
| 76 | 76 | DMI_EXACT_MATCH_ASUS_BOARD_NAME("ROG CROSSHAIR VII HERO"), |
| 77 | 77 | DMI_EXACT_MATCH_ASUS_BOARD_NAME("ROG CROSSHAIR VII HERO (WI-FI)"), |
| @@ -1578,8 +1578,9 @@ static ssize_t show_temp(struct device *dev, struct device_attribute *devattr, · 1577 unmodified lines | ||
| 1578 | 1578 | temp *= 125; |
| 1579 | 1579 | if (sign) |
| 1580 | 1580 | temp -= 128000; |
| 1581 | − } else | |
| 1582 | − temp = data->temp[nr] * 1000; | |
| 1581 | + } else { | |
| 1582 | + temp = ((s8)data->temp[nr]) * 1000; | |
| 1583 | + } | |
| 1583 | 1584 | |
| 1584 | 1585 | return sprintf(buf, "%d\n", temp); |
| 1585 | 1586 | } |
| @@ -14,6 +14,21 @@ · 13 unmodified lines | ||
| 14 | 14 | |
| 15 | 15 | #define AHE50DC_PMBUS_READ_TEMP4 0xd0 |
| 16 | 16 | |
| 17 | +static int ahe50dc_fan_write_byte(struct i2c_client *client, int page, u8 value) | |
| 18 | +{ | |
| 19 | + /* | |
| 20 | + * The CLEAR_FAULTS operation seems to sometimes (unpredictably, perhaps | |
| 21 | + * 5% of the time or so) trigger a problematic phenomenon in which the | |
| 22 | + * fan speeds surge momentarily and at least some (perhaps all?) of the | |
| 23 | + * system's power outputs experience a glitch. | |
| 24 | + * | |
| 25 | + * However, according to Delta it should be OK to simply not send any | |
| 26 | + * CLEAR_FAULTS commands (the device doesn't seem to be capable of | |
| 27 | + * reporting any faults anyway), so just blackhole them unconditionally. | |
| 28 | + */ | |
| 29 | + return value == PMBUS_CLEAR_FAULTS ? -EOPNOTSUPP : -ENODATA; | |
| 30 | +} | |
| 31 | + | |
| 17 | 32 | static int ahe50dc_fan_read_word_data(struct i2c_client *client, int page, int phase, int reg) |
| 18 | 33 | { |
| 19 | 34 | /* temp1 in (virtual) page 1 is remapped to mfr-specific temp4 */ |
| @@ -68,6 +83,7 @@ static struct pmbus_driver_info ahe50dc_fan_info = { · 48 unmodified lines | ||
| 68 | 83 | PMBUS_HAVE_VIN | PMBUS_HAVE_FAN12 | PMBUS_HAVE_FAN34 | |
| 69 | 84 | PMBUS_HAVE_STATUS_FAN12 | PMBUS_HAVE_STATUS_FAN34 | PMBUS_PAGE_VIRTUAL, |
| 70 | 85 | .func[1] = PMBUS_HAVE_TEMP | PMBUS_PAGE_VIRTUAL, |
| 86 | + .write_byte = ahe50dc_fan_write_byte, | |
| 71 | 87 | .read_word_data = ahe50dc_fan_read_word_data, |
| 72 | 88 | }; |
| 73 | 89 | |
| @@ -2326,6 +2326,9 @@ static int pmbus_init_common(struct i2c_client *client, struct pmbus_data *data, · 2325 unmodified lines | ||
| 2326 | 2326 | data->has_status_word = true; |
| 2327 | 2327 | } |
| 2328 | 2328 | |
| 2329 | + /* Make sure PEC is disabled, will be enabled later if needed */ | |
| 2330 | + client->flags &= ~I2C_CLIENT_PEC; | |
| 2331 | + | |
| 2329 | 2332 | /* Enable PEC if the controller and bus supports it */ |
| 2330 | 2333 | if (!(data->flags & PMBUS_NO_CAPABILITY)) { |
| 2331 | 2334 | ret = i2c_smbus_read_byte_data(client, PMBUS_CAPABILITY); |
| @@ -124,7 +124,7 @@ static int xdpe122_identify(struct i2c_client *client, · 123 unmodified lines | ||
| 124 | 124 | return 0; |
| 125 | 125 | } |
| 126 | 126 | |
| 127 | −static const struct regulator_desc xdpe122_reg_desc[] = { | |
| 127 | +static const struct regulator_desc __maybe_unused xdpe122_reg_desc[] = { | |
| 128 | 128 | PMBUS_REGULATOR("vout", 0), |
| 129 | 129 | PMBUS_REGULATOR("vout", 1), |
| 130 | 130 | }; |
| @@ -708,10 +708,21 @@ static int tmp401_probe(struct i2c_client *client) · 707 unmodified lines | ||
| 708 | 708 | return 0; |
| 709 | 709 | } |
| 710 | 710 | |
| 711 | +static const struct of_device_id __maybe_unused tmp4xx_of_match[] = { | |
| 712 | + { .compatible = "ti,tmp401", }, | |
| 713 | + { .compatible = "ti,tmp411", }, | |
| 714 | + { .compatible = "ti,tmp431", }, | |
| 715 | + { .compatible = "ti,tmp432", }, | |
| 716 | + { .compatible = "ti,tmp435", }, | |
| 717 | + { }, | |
| 718 | +}; | |
| 719 | +MODULE_DEVICE_TABLE(of, tmp4xx_of_match); | |
| 720 | + | |
| 711 | 721 | static struct i2c_driver tmp401_driver = { |
| 712 | 722 | .class = I2C_CLASS_HWMON, |
| 713 | 723 | .driver = { |
| 714 | 724 | .name = "tmp401", |
| 725 | + .of_match_table = of_match_ptr(tmp4xx_of_match), | |
| 715 | 726 | }, |
| 716 | 727 | .probe_new = tmp401_probe, |
| 717 | 728 | .id_table = tmp401_id, |
| @@ -69,7 +69,12 @@ static unsigned int preferred_states_mask; · 68 unmodified lines | ||
| 69 | 69 | static struct cpuidle_device __percpu *intel_idle_cpuidle_devices; |
| 70 | 70 | |
| 71 | 71 | static unsigned long auto_demotion_disable_flags; |
| 72 | −static bool disable_promotion_to_c1e; | |
| 72 | + | |
| 73 | +static enum { | |
| 74 | + C1E_PROMOTION_PRESERVE, | |
| 75 | + C1E_PROMOTION_ENABLE, | |
| 76 | + C1E_PROMOTION_DISABLE | |
| 77 | +} c1e_promotion = C1E_PROMOTION_PRESERVE; | |
| 73 | 78 | |
| 74 | 79 | struct idle_cpu { |
| 75 | 80 | struct cpuidle_state *state_table; |
| @@ -1398,8 +1403,6 @@ static inline void intel_idle_init_cstates_acpi(struct cpuidle_driver *drv) { } · 1322 unmodified lines | ||
| 1398 | 1403 | static inline bool intel_idle_off_by_default(u32 mwait_hint) { return false; } |
| 1399 | 1404 | #endif /* !CONFIG_ACPI_PROCESSOR_CSTATE */ |
| 1400 | 1405 | |
| 1401 | −static void c1e_promotion_enable(void); | |
| 1402 | − | |
| 1403 | 1406 | /** |
| 1404 | 1407 | * ivt_idle_state_table_update - Tune the idle states table for Ivy Town. |
| 1405 | 1408 | * |
| @@ -1578,17 +1581,14 @@ static void __init spr_idle_state_table_update(void) · 172 unmodified lines | ||
| 1578 | 1581 | unsigned long long msr; |
| 1579 | 1582 | |
| 1580 | 1583 | /* Check if user prefers C1E over C1. */ |
| 1581 | − if (preferred_states_mask & BIT(2)) { | |
| 1582 | − if (preferred_states_mask & BIT(1)) | |
| 1583 | − /* Both can't be enabled, stick to the defaults. */ | |
| 1584 | − return; | |
| 1585 | − | |
| 1584 | + if ((preferred_states_mask & BIT(2)) && | |
| 1585 | + !(preferred_states_mask & BIT(1))) { | |
| 1586 | + /* Disable C1 and enable C1E. */ | |
| 1586 | 1587 | spr_cstates[0].flags |= CPUIDLE_FLAG_UNUSABLE; |
| 1587 | 1588 | spr_cstates[1].flags &= ~CPUIDLE_FLAG_UNUSABLE; |
| 1588 | 1589 | |
| 1589 | 1590 | /* Enable C1E using the "C1E promotion" bit. */ |
| 1590 | − c1e_promotion_enable(); | |
| 1591 | − disable_promotion_to_c1e = false; | |
| 1591 | + c1e_promotion = C1E_PROMOTION_ENABLE; | |
| 1592 | 1592 | } |
| 1593 | 1593 | |
| 1594 | 1594 | /* |
| @@ -1754,7 +1754,9 @@ static int intel_idle_cpu_init(unsigned int cpu) · 159 unmodified lines | ||
| 1754 | 1754 | if (auto_demotion_disable_flags) |
| 1755 | 1755 | auto_demotion_disable(); |
| 1756 | 1756 | |
| 1757 | − if (disable_promotion_to_c1e) | |
| 1757 | + if (c1e_promotion == C1E_PROMOTION_ENABLE) | |
| 1758 | + c1e_promotion_enable(); | |
| 1759 | + else if (c1e_promotion == C1E_PROMOTION_DISABLE) | |
| 1758 | 1760 | c1e_promotion_disable(); |
| 1759 | 1761 | |
| 1760 | 1762 | return 0; |
| @@ -1833,7 +1835,8 @@ static int __init intel_idle_init(void) · 72 unmodified lines | ||
| 1833 | 1835 | if (icpu) { |
| 1834 | 1836 | cpuidle_state_table = icpu->state_table; |
| 1835 | 1837 | auto_demotion_disable_flags = icpu->auto_demotion_disable_flags; |
| 1836 | − disable_promotion_to_c1e = icpu->disable_promotion_to_c1e; | |
| 1838 | + if (icpu->disable_promotion_to_c1e) | |
| 1839 | + c1e_promotion = C1E_PROMOTION_DISABLE; | |
| 1837 | 1840 | if (icpu->use_acpi || force_use_acpi) |
| 1838 | 1841 | intel_idle_acpi_cst_extract(); |
| 1839 | 1842 | } else if (!intel_idle_acpi_cst_extract()) { |
| @@ -745,7 +745,7 @@ static int ad7280a_write_thresh(struct iio_dev *indio_dev, · 744 unmodified lines | ||
| 745 | 745 | case IIO_EV_DIR_RISING: |
| 746 | 746 | addr = AD7280A_CELL_OVERVOLTAGE_REG; |
| 747 | 747 | ret = ad7280_write(st, AD7280A_DEVADDR_MASTER, addr, |
| 748 | − 1, val); | |
| 748 | + 1, value); | |
| 749 | 749 | if (ret) |
| 750 | 750 | break; |
| 751 | 751 | st->cell_threshhigh = value; |
| @@ -753,7 +753,7 @@ static int ad7280a_write_thresh(struct iio_dev *indio_dev, · 1 unmodified line | ||
| 753 | 753 | case IIO_EV_DIR_FALLING: |
| 754 | 754 | addr = AD7280A_CELL_UNDERVOLTAGE_REG; |
| 755 | 755 | ret = ad7280_write(st, AD7280A_DEVADDR_MASTER, addr, |
| 756 | − 1, val); | |
| 756 | + 1, value); | |
| 757 | 757 | if (ret) |
| 758 | 758 | break; |
| 759 | 759 | st->cell_threshlow = value; |
| @@ -770,18 +770,18 @@ static int ad7280a_write_thresh(struct iio_dev *indio_dev, · 10 unmodified lines | ||
| 770 | 770 | case IIO_EV_DIR_RISING: |
| 771 | 771 | addr = AD7280A_AUX_ADC_OVERVOLTAGE_REG; |
| 772 | 772 | ret = ad7280_write(st, AD7280A_DEVADDR_MASTER, addr, |
| 773 | − 1, val); | |
| 773 | + 1, value); | |
| 774 | 774 | if (ret) |
| 775 | 775 | break; |
| 776 | − st->aux_threshhigh = val; | |
| 776 | + st->aux_threshhigh = value; | |
| 777 | 777 | break; |
| 778 | 778 | case IIO_EV_DIR_FALLING: |
| 779 | 779 | addr = AD7280A_AUX_ADC_UNDERVOLTAGE_REG; |
| 780 | 780 | ret = ad7280_write(st, AD7280A_DEVADDR_MASTER, addr, |
| 781 | − 1, val); | |
| 781 | + 1, value); | |
| 782 | 782 | if (ret) |
| 783 | 783 | break; |
| 784 | − st->aux_threshlow = val; | |
| 784 | + st->aux_threshlow = value; | |
| 785 | 785 | break; |
| 786 | 786 | default: |
| 787 | 787 | ret = -EINVAL; |
| @@ -471,12 +471,15 @@ static ssize_t calibration_forced_value_store(struct device *dev, · 470 unmodified lines | ||
| 471 | 471 | ret = scd4x_write_and_fetch(state, CMD_FRC, arg, &val, sizeof(val)); |
| 472 | 472 | mutex_unlock(&state->lock); |
| 473 | 473 | |
| 474 | + if (ret) | |
| 475 | + return ret; | |
| 476 | + | |
| 474 | 477 | if (val == 0xff) { |
| 475 | 478 | dev_err(dev, "forced calibration has failed"); |
| 476 | 479 | return -EINVAL; |
| 477 | 480 | } |
| 478 | 481 | |
| 479 | − return ret ?: len; | |
| 482 | + return len; | |
| 480 | 483 | } |
| 481 | 484 | |
| 482 | 485 | static IIO_DEVICE_ATTR_RW(calibration_auto_enable, 0); |
| @@ -656,7 +656,7 @@ static int ad3552r_reset(struct ad3552r_desc *dac) · 655 unmodified lines | ||
| 656 | 656 | { |
| 657 | 657 | struct reg_addr_pool addr; |
| 658 | 658 | int ret; |
| 659 | − u16 val; | |
| 659 | + int val; | |
| 660 | 660 | |
| 661 | 661 | dac->gpio_reset = devm_gpiod_get_optional(&dac->spi->dev, "reset", |
| 662 | 662 | GPIOD_OUT_LOW); |
| @@ -809,10 +809,10 @@ static int ad3552r_configure_custom_gain(struct ad3552r_desc *dac, · 146 unmodified lines | ||
| 809 | 809 | |
| 810 | 810 | gain_child = fwnode_get_named_child_node(child, |
| 811 | 811 | "custom-output-range-config"); |
| 812 | − if (IS_ERR(gain_child)) { | |
| 812 | + if (!gain_child) { | |
| 813 | 813 | dev_err(dev, |
| 814 | 814 | "mandatory custom-output-range-config property missing\n"); |
| 815 | − return PTR_ERR(gain_child); | |
| 815 | + return -EINVAL; | |
| 816 | 816 | } |
| 817 | 817 | |
| 818 | 818 | dac->ch_data[ch].range_override = 1; |
| @@ -178,7 +178,7 @@ static int ad5446_read_raw(struct iio_dev *indio_dev, · 177 unmodified lines | ||
| 178 | 178 | |
| 179 | 179 | switch (m) { |
| 180 | 180 | case IIO_CHAN_INFO_RAW: |
| 181 | − *val = st->cached_val; | |
| 181 | + *val = st->cached_val >> chan->scan_type.shift; | |
| 182 | 182 | return IIO_VAL_INT; |
| 183 | 183 | case IIO_CHAN_INFO_SCALE: |
| 184 | 184 | *val = st->vref_mv; |
| @@ -522,7 +522,7 @@ static int ad5592r_alloc_channels(struct iio_dev *iio_dev) · 521 unmodified lines | ||
| 522 | 522 | if (!ret) |
| 523 | 523 | st->channel_modes[reg] = tmp; |
| 524 | 524 | |
| 525 | − fwnode_property_read_u32(child, "adi,off-state", &tmp); | |
| 525 | + ret = fwnode_property_read_u32(child, "adi,off-state", &tmp); | |
| 526 | 526 | if (!ret) |
| 527 | 527 | st->channel_offstate[reg] = tmp; |
| 528 | 528 | } |
| @@ -298,7 +298,7 @@ static int ltc2688_read_raw(struct iio_dev *indio_dev, · 297 unmodified lines | ||
| 298 | 298 | if (ret) |
| 299 | 299 | return ret; |
| 300 | 300 | |
| 301 | − *val = 16; | |
| 301 | + *val2 = 16; | |
| 302 | 302 | return IIO_VAL_FRACTIONAL_LOG2; |
| 303 | 303 | case IIO_CHAN_INFO_CALIBBIAS: |
| 304 | 304 | ret = regmap_read(st->regmap, |
| @@ -19,6 +19,7 @@ · 18 unmodified lines | ||
| 19 | 19 | #include <linux/i2c.h> |
| 20 | 20 | #include <linux/module.h> |
| 21 | 21 | #include <linux/mod_devicetable.h> |
| 22 | +#include <linux/property.h> | |
| 22 | 23 | #include <linux/regulator/consumer.h> |
| 23 | 24 | |
| 24 | 25 | enum chip_id { |
| @@ -311,6 +312,7 @@ static int dac5571_probe(struct i2c_client *client, · 286 unmodified lines | ||
| 311 | 312 | const struct dac5571_spec *spec; |
| 312 | 313 | struct dac5571_data *data; |
| 313 | 314 | struct iio_dev *indio_dev; |
| 315 | + enum chip_id chip_id; | |
| 314 | 316 | int ret, i; |
| 315 | 317 | |
| 316 | 318 | indio_dev = devm_iio_device_alloc(dev, sizeof(*data)); |
| @@ -326,7 +328,13 @@ static int dac5571_probe(struct i2c_client *client, · 9 unmodified lines | ||
| 326 | 328 | indio_dev->modes = INDIO_DIRECT_MODE; |
| 327 | 329 | indio_dev->channels = dac5571_channels; |
| 328 | 330 | |
| 329 | − spec = &dac5571_spec[id->driver_data]; | |
| 331 | + if (dev_fwnode(dev)) | |
| 332 | + chip_id = (uintptr_t)device_get_match_data(dev); | |
| 333 | + else | |
| 334 | + chip_id = id->driver_data; | |
| 335 | + | |
| 336 | + spec = &dac5571_spec[chip_id]; | |
| 337 | + | |
| 330 | 338 | indio_dev->num_channels = spec->num_channels; |
| 331 | 339 | data->spec = spec; |
| 332 | 340 | |
| @@ -385,15 +393,15 @@ static int dac5571_remove(struct i2c_client *i2c) · 52 unmodified lines | ||
| 385 | 393 | } |
| 386 | 394 | |
| 387 | 395 | static const struct of_device_id dac5571_of_id[] = { |
| 388 | − {.compatible = "ti,dac5571"}, | |
| 389 | − {.compatible = "ti,dac6571"}, | |
| 390 | − {.compatible = "ti,dac7571"}, | |
| 391 | − {.compatible = "ti,dac5574"}, | |
| 392 | − {.compatible = "ti,dac6574"}, | |
| 393 | − {.compatible = "ti,dac7574"}, | |
| 394 | − {.compatible = "ti,dac5573"}, | |
| 395 | − {.compatible = "ti,dac6573"}, | |
| 396 | − {.compatible = "ti,dac7573"}, | |
| 396 | + {.compatible = "ti,dac5571", .data = (void *)single_8bit}, | |
| 397 | + {.compatible = "ti,dac6571", .data = (void *)single_10bit}, | |
| 398 | + {.compatible = "ti,dac7571", .data = (void *)single_12bit}, | |
| 399 | + {.compatible = "ti,dac5574", .data = (void *)quad_8bit}, | |
| 400 | + {.compatible = "ti,dac6574", .data = (void *)quad_10bit}, | |
| 401 | + {.compatible = "ti,dac7574", .data = (void *)quad_12bit}, | |
| 402 | + {.compatible = "ti,dac5573", .data = (void *)quad_8bit}, | |
| 403 | + {.compatible = "ti,dac6573", .data = (void *)quad_10bit}, | |
| 404 | + {.compatible = "ti,dac7573", .data = (void *)quad_12bit}, | |
| 397 | 405 | {} |
| 398 | 406 | }; |
| 399 | 407 | MODULE_DEVICE_TABLE(of, dac5571_of_id); |
| @@ -8,6 +8,7 @@ menu "Filters" · 7 unmodified lines | ||
| 8 | 8 | config ADMV8818 |
| 9 | 9 | tristate "Analog Devices ADMV8818 High-Pass and Low-Pass Filter" |
| 10 | 10 | depends on SPI && COMMON_CLK && 64BIT |
| 11 | + select REGMAP_SPI | |
| 11 | 12 | help |
| 12 | 13 | Say yes here to build support for Analog Devices ADMV8818 |
| 13 | 14 | 2 GHz to 18 GHz, Digitally Tunable, High-Pass and Low-Pass Filter. |
| @@ -730,7 +730,7 @@ static int bmi160_chip_init(struct bmi160_data *data, bool use_spi) · 729 unmodified lines | ||
| 730 | 730 | |
| 731 | 731 | ret = regmap_write(data->regmap, BMI160_REG_CMD, BMI160_CMD_SOFTRESET); |
| 732 | 732 | if (ret) |
| 733 | − return ret; | |
| 733 | + goto disable_regulator; | |
| 734 | 734 | |
| 735 | 735 | usleep_range(BMI160_SOFTRESET_USLEEP, BMI160_SOFTRESET_USLEEP + 1); |
| 736 | 736 | |
| @@ -741,29 +741,37 @@ static int bmi160_chip_init(struct bmi160_data *data, bool use_spi) · 4 unmodified lines | ||
| 741 | 741 | if (use_spi) { |
| 742 | 742 | ret = regmap_read(data->regmap, BMI160_REG_DUMMY, &val); |
| 743 | 743 | if (ret) |
| 744 | − return ret; | |
| 744 | + goto disable_regulator; | |
| 745 | 745 | } |
| 746 | 746 | |
| 747 | 747 | ret = regmap_read(data->regmap, BMI160_REG_CHIP_ID, &val); |
| 748 | 748 | if (ret) { |
| 749 | 749 | dev_err(dev, "Error reading chip id\n"); |
| 750 | − return ret; | |
| 750 | + goto disable_regulator; | |
| 751 | 751 | } |
| 752 | 752 | if (val != BMI160_CHIP_ID_VAL) { |
| 753 | 753 | dev_err(dev, "Wrong chip id, got %x expected %x\n", |
| 754 | 754 | val, BMI160_CHIP_ID_VAL); |
| 755 | − return -ENODEV; | |
| 755 | + ret = -ENODEV; | |
| 756 | + goto disable_regulator; | |
| 756 | 757 | } |
| 757 | 758 | |
| 758 | 759 | ret = bmi160_set_mode(data, BMI160_ACCEL, true); |
| 759 | 760 | if (ret) |
| 760 | − return ret; | |
| 761 | + goto disable_regulator; | |
| 761 | 762 | |
| 762 | 763 | ret = bmi160_set_mode(data, BMI160_GYRO, true); |
| 763 | 764 | if (ret) |
| 764 | − return ret; | |
| 765 | + goto disable_accel; | |
| 765 | 766 | |
| 766 | 767 | return 0; |
| 768 | + | |
| 769 | +disable_accel: | |
| 770 | + bmi160_set_mode(data, BMI160_ACCEL, false); | |
| 771 | + | |
| 772 | +disable_regulator: | |
| 773 | + regulator_bulk_disable(ARRAY_SIZE(data->supplies), data->supplies); | |
| 774 | + return ret; | |
| 767 | 775 | } |
| 768 | 776 | |
| 769 | 777 | static int bmi160_data_rdy_trigger_set_state(struct iio_trigger *trig, |
| @@ -18,12 +18,15 @@ static int inv_icm42600_i2c_bus_setup(struct inv_icm42600_state *st) · 17 unmodified lines | ||
| 18 | 18 | unsigned int mask, val; |
| 19 | 19 | int ret; |
| 20 | 20 | |
| 21 | − /* setup interface registers */ | |
| 22 | − ret = regmap_update_bits(st->map, INV_ICM42600_REG_INTF_CONFIG6, | |
| 23 | − INV_ICM42600_INTF_CONFIG6_MASK, | |
| 24 | − INV_ICM42600_INTF_CONFIG6_I3C_EN); | |
| 25 | − if (ret) | |
| 26 | − return ret; | |
| 21 | + /* | |
| 22 | + * setup interface registers | |
| 23 | + * This register write to REG_INTF_CONFIG6 enables a spike filter that | |
| 24 | + * is impacting the line and can prevent the I2C ACK to be seen by the | |
| 25 | + * controller. So we don't test the return value. | |
| 26 | + */ | |
| 27 | + regmap_update_bits(st->map, INV_ICM42600_REG_INTF_CONFIG6, | |
| 28 | + INV_ICM42600_INTF_CONFIG6_MASK, | |
| 29 | + INV_ICM42600_INTF_CONFIG6_I3C_EN); | |
| 27 | 30 | |
| 28 | 31 | ret = regmap_update_bits(st->map, INV_ICM42600_REG_INTF_CONFIG4, |
| 29 | 32 | INV_ICM42600_INTF_CONFIG4_I3C_BUS_ONLY, 0); |
| @@ -416,6 +416,7 @@ static int ak8975_power_on(const struct ak8975_data *data) · 415 unmodified lines | ||
| 416 | 416 | if (ret) { |
| 417 | 417 | dev_warn(&data->client->dev, |
| 418 | 418 | "Failed to enable specified Vid supply\n"); |
| 419 | + regulator_disable(data->vdd); | |
| 419 | 420 | return ret; |
| 420 | 421 | } |
| 421 | 422 | |
| @@ -70,13 +70,17 @@ · 69 unmodified lines | ||
| 70 | 70 | #define SX9324_REG_AFE_PH2 0x2a |
| 71 | 71 | #define SX9324_REG_AFE_PH3 0x2b |
| 72 | 72 | #define SX9324_REG_AFE_CTRL8 0x2c |
| 73 | −#define SX9324_REG_AFE_CTRL8_RESFILTN_4KOHM 0x02 | |
| 73 | +#define SX9324_REG_AFE_CTRL8_RESERVED 0x10 | |
| 74 | +#define SX9324_REG_AFE_CTRL8_RESFILTIN_4KOHM 0x02 | |
| 74 | 75 | #define SX9324_REG_AFE_CTRL9 0x2d |
| 75 | 76 | #define SX9324_REG_AFE_CTRL9_AGAIN_1 0x08 |
| 76 | 77 | |
| 77 | 78 | #define SX9324_REG_PROX_CTRL0 0x30 |
| 78 | 79 | #define SX9324_REG_PROX_CTRL0_GAIN_MASK GENMASK(5, 3) |
| 79 | −#define SX9324_REG_PROX_CTRL0_GAIN_1 0x80 | |
| 80 | +#define SX9324_REG_PROX_CTRL0_GAIN_SHIFT 3 | |
| 81 | +#define SX9324_REG_PROX_CTRL0_GAIN_RSVD 0x0 | |
| 82 | +#define SX9324_REG_PROX_CTRL0_GAIN_1 0x1 | |
| 83 | +#define SX9324_REG_PROX_CTRL0_GAIN_8 0x4 | |
| 80 | 84 | #define SX9324_REG_PROX_CTRL0_RAWFILT_MASK GENMASK(2, 0) |
| 81 | 85 | #define SX9324_REG_PROX_CTRL0_RAWFILT_1P50 0x01 |
| 82 | 86 | #define SX9324_REG_PROX_CTRL1 0x31 |
| @@ -379,7 +383,14 @@ static int sx9324_read_gain(struct sx_common_data *data, · 296 unmodified lines | ||
| 379 | 383 | if (ret) |
| 380 | 384 | return ret; |
| 381 | 385 | |
| 382 | − *val = 1 << FIELD_GET(SX9324_REG_PROX_CTRL0_GAIN_MASK, regval); | |
| 386 | + regval = FIELD_GET(SX9324_REG_PROX_CTRL0_GAIN_MASK, regval); | |
| 387 | + if (regval) | |
| 388 | + regval--; | |
| 389 | + else if (regval == SX9324_REG_PROX_CTRL0_GAIN_RSVD || | |
| 390 | + regval > SX9324_REG_PROX_CTRL0_GAIN_8) | |
| 391 | + return -EINVAL; | |
| 392 | + | |
| 393 | + *val = 1 << regval; | |
| 383 | 394 | |
| 384 | 395 | return IIO_VAL_INT; |
| 385 | 396 | } |
| @@ -725,8 +736,12 @@ static int sx9324_write_gain(struct sx_common_data *data, · 339 unmodified lines | ||
| 725 | 736 | unsigned int gain, reg; |
| 726 | 737 | int ret; |
| 727 | 738 | |
| 728 | − gain = ilog2(val); | |
| 729 | 739 | reg = SX9324_REG_PROX_CTRL0 + chan->channel / 2; |
| 740 | + | |
| 741 | + gain = ilog2(val) + 1; | |
| 742 | + if (val <= 0 || gain > SX9324_REG_PROX_CTRL0_GAIN_8) | |
| 743 | + return -EINVAL; | |
| 744 | + | |
| 730 | 745 | gain = FIELD_PREP(SX9324_REG_PROX_CTRL0_GAIN_MASK, gain); |
| 731 | 746 | |
| 732 | 747 | mutex_lock(&data->mutex); |
| @@ -781,12 +796,15 @@ static const struct sx_common_reg_default sx9324_default_regs[] = { · 48 unmodified lines | ||
| 781 | 796 | { SX9324_REG_AFE_PH2, 0x1a }, |
| 782 | 797 | { SX9324_REG_AFE_PH3, 0x16 }, |
| 783 | 798 | |
| 784 | − { SX9324_REG_AFE_CTRL8, SX9324_REG_AFE_CTRL8_RESFILTN_4KOHM }, | |
| 799 | + { SX9324_REG_AFE_CTRL8, SX9324_REG_AFE_CTRL8_RESERVED | | |
| 800 | + SX9324_REG_AFE_CTRL8_RESFILTIN_4KOHM }, | |
| 785 | 801 | { SX9324_REG_AFE_CTRL9, SX9324_REG_AFE_CTRL9_AGAIN_1 }, |
| 786 | 802 | |
| 787 | − { SX9324_REG_PROX_CTRL0, SX9324_REG_PROX_CTRL0_GAIN_1 | | |
| 803 | + { SX9324_REG_PROX_CTRL0, | |
| 804 | + SX9324_REG_PROX_CTRL0_GAIN_1 << SX9324_REG_PROX_CTRL0_GAIN_SHIFT | | |
| 788 | 805 | SX9324_REG_PROX_CTRL0_RAWFILT_1P50 }, |
| 789 | − { SX9324_REG_PROX_CTRL1, SX9324_REG_PROX_CTRL0_GAIN_1 | | |
| 806 | + { SX9324_REG_PROX_CTRL1, | |
| 807 | + SX9324_REG_PROX_CTRL0_GAIN_1 << SX9324_REG_PROX_CTRL0_GAIN_SHIFT | | |
| 790 | 808 | SX9324_REG_PROX_CTRL0_RAWFILT_1P50 }, |
| 791 | 809 | { SX9324_REG_PROX_CTRL2, SX9324_REG_PROX_CTRL2_AVGNEG_THRESH_16K }, |
| 792 | 810 | { SX9324_REG_PROX_CTRL3, SX9324_REG_PROX_CTRL3_AVGDEB_2SAMPLES | |
| @@ -521,6 +521,7 @@ int sx_common_probe(struct i2c_client *client, · 520 unmodified lines | ||
| 521 | 521 | return dev_err_probe(dev, ret, "error reading WHOAMI\n"); |
| 522 | 522 | |
| 523 | 523 | ACPI_COMPANION_SET(&indio_dev->dev, ACPI_COMPANION(dev)); |
| 524 | + indio_dev->dev.of_node = client->dev.of_node; | |
| 524 | 525 | indio_dev->modes = INDIO_DIRECT_MODE; |
| 525 | 526 | |
| 526 | 527 | indio_dev->channels = data->chip_info->iio_channels; |
| @@ -2308,10 +2308,8 @@ err: · 2307 unmodified lines | ||
| 2308 | 2308 | return NULL; |
| 2309 | 2309 | } |
| 2310 | 2310 | |
| 2311 | −static void irdma_cm_node_free_cb(struct rcu_head *rcu_head) | |
| 2311 | +static void irdma_destroy_connection(struct irdma_cm_node *cm_node) | |
| 2312 | 2312 | { |
| 2313 | − struct irdma_cm_node *cm_node = | |
| 2314 | − container_of(rcu_head, struct irdma_cm_node, rcu_head); | |
| 2315 | 2313 | struct irdma_cm_core *cm_core = cm_node->cm_core; |
| 2316 | 2314 | struct irdma_qp *iwqp; |
| 2317 | 2315 | struct irdma_cm_info nfo; |
| @@ -2359,7 +2357,6 @@ static void irdma_cm_node_free_cb(struct rcu_head *rcu_head) · 41 unmodified lines | ||
| 2359 | 2357 | } |
| 2360 | 2358 | |
| 2361 | 2359 | cm_core->cm_free_ah(cm_node); |
| 2362 | − kfree(cm_node); | |
| 2363 | 2360 | } |
| 2364 | 2361 | |
| 2365 | 2362 | /** |
| @@ -2387,8 +2384,9 @@ void irdma_rem_ref_cm_node(struct irdma_cm_node *cm_node) · 21 unmodified lines | ||
| 2387 | 2384 | |
| 2388 | 2385 | spin_unlock_irqrestore(&cm_core->ht_lock, flags); |
| 2389 | 2386 | |
| 2390 | − /* wait for all list walkers to exit their grace period */ | |
| 2391 | − call_rcu(&cm_node->rcu_head, irdma_cm_node_free_cb); | |
| 2387 | + irdma_destroy_connection(cm_node); | |
| 2388 | + | |
| 2389 | + kfree_rcu(cm_node, rcu_head); | |
| 2392 | 2390 | } |
| 2393 | 2391 | |
| 2394 | 2392 | /** |
| @@ -3246,15 +3244,10 @@ int irdma_setup_cm_core(struct irdma_device *iwdev, u8 rdma_ver) · 851 unmodified lines | ||
| 3246 | 3244 | */ |
| 3247 | 3245 | void irdma_cleanup_cm_core(struct irdma_cm_core *cm_core) |
| 3248 | 3246 | { |
| 3249 | − unsigned long flags; | |
| 3250 | − | |
| 3251 | 3247 | if (!cm_core) |
| 3252 | 3248 | return; |
| 3253 | 3249 | |
| 3254 | − spin_lock_irqsave(&cm_core->ht_lock, flags); | |
| 3255 | − if (timer_pending(&cm_core->tcp_timer)) | |
| 3256 | − del_timer_sync(&cm_core->tcp_timer); | |
| 3257 | − spin_unlock_irqrestore(&cm_core->ht_lock, flags); | |
| 3250 | + del_timer_sync(&cm_core->tcp_timer); | |
| 3258 | 3251 | |
| 3259 | 3252 | destroy_workqueue(cm_core->event_wq); |
| 3260 | 3253 | cm_core->dev->ws_reset(&cm_core->iwdev->vsi); |
| @@ -3467,12 +3460,6 @@ static void irdma_cm_disconn_true(struct irdma_qp *iwqp) · 206 unmodified lines | ||
| 3467 | 3460 | } |
| 3468 | 3461 | |
| 3469 | 3462 | cm_id = iwqp->cm_id; |
| 3470 | − /* make sure we havent already closed this connection */ | |
| 3471 | − if (!cm_id) { | |
| 3472 | − spin_unlock_irqrestore(&iwqp->lock, flags); | |
| 3473 | − return; | |
| 3474 | − } | |
| 3475 | − | |
| 3476 | 3463 | original_hw_tcp_state = iwqp->hw_tcp_state; |
| 3477 | 3464 | original_ibqp_state = iwqp->ibqp_state; |
| 3478 | 3465 | last_ae = iwqp->last_aeq; |
| @@ -3494,11 +3481,11 @@ static void irdma_cm_disconn_true(struct irdma_qp *iwqp) · 15 unmodified lines | ||
| 3494 | 3481 | disconn_status = -ECONNRESET; |
| 3495 | 3482 | } |
| 3496 | 3483 | |
| 3497 | − if ((original_hw_tcp_state == IRDMA_TCP_STATE_CLOSED || | |
| 3498 | − original_hw_tcp_state == IRDMA_TCP_STATE_TIME_WAIT || | |
| 3499 | − last_ae == IRDMA_AE_RDMAP_ROE_BAD_LLP_CLOSE || | |
| 3500 | − last_ae == IRDMA_AE_BAD_CLOSE || | |
| 3501 | − last_ae == IRDMA_AE_LLP_CONNECTION_RESET || iwdev->rf->reset)) { | |
| 3484 | + if (original_hw_tcp_state == IRDMA_TCP_STATE_CLOSED || | |
| 3485 | + original_hw_tcp_state == IRDMA_TCP_STATE_TIME_WAIT || | |
| 3486 | + last_ae == IRDMA_AE_RDMAP_ROE_BAD_LLP_CLOSE || | |
| 3487 | + last_ae == IRDMA_AE_BAD_CLOSE || | |
| 3488 | + last_ae == IRDMA_AE_LLP_CONNECTION_RESET || iwdev->rf->reset || !cm_id) { | |
| 3502 | 3489 | issue_close = 1; |
| 3503 | 3490 | iwqp->cm_id = NULL; |
| 3504 | 3491 | qp->term_flags = 0; |
| @@ -258,18 +258,16 @@ int irdma_net_event(struct notifier_block *notifier, unsigned long event, · 257 unmodified lines | ||
| 258 | 258 | u32 local_ipaddr[4] = {}; |
| 259 | 259 | bool ipv4 = true; |
| 260 | 260 | |
| 261 | − real_dev = rdma_vlan_dev_real_dev(netdev); | |
| 262 | − if (!real_dev) | |
| 263 | − real_dev = netdev; | |
| 264 | − | |
| 265 | − ibdev = ib_device_get_by_netdev(real_dev, RDMA_DRIVER_IRDMA); | |
| 266 | − if (!ibdev) | |
| 267 | − return NOTIFY_DONE; | |
| 268 | − | |
| 269 | − iwdev = to_iwdev(ibdev); | |
| 270 | − | |
| 271 | 261 | switch (event) { |
| 272 | 262 | case NETEVENT_NEIGH_UPDATE: |
| 263 | + real_dev = rdma_vlan_dev_real_dev(netdev); | |
| 264 | + if (!real_dev) | |
| 265 | + real_dev = netdev; | |
| 266 | + ibdev = ib_device_get_by_netdev(real_dev, RDMA_DRIVER_IRDMA); | |
| 267 | + if (!ibdev) | |
| 268 | + return NOTIFY_DONE; | |
| 269 | + | |
| 270 | + iwdev = to_iwdev(ibdev); | |
| 273 | 271 | p = (__be32 *)neigh->primary_key; |
| 274 | 272 | if (neigh->tbl->family == AF_INET6) { |
| 275 | 273 | ipv4 = false; |
| @@ -290,13 +288,12 @@ int irdma_net_event(struct notifier_block *notifier, unsigned long event, · 14 unmodified lines | ||
| 290 | 288 | irdma_manage_arp_cache(iwdev->rf, neigh->ha, |
| 291 | 289 | local_ipaddr, ipv4, |
| 292 | 290 | IRDMA_ARP_DELETE); |
| 291 | + ib_device_put(ibdev); | |
| 293 | 292 | break; |
| 294 | 293 | default: |
| 295 | 294 | break; |
| 296 | 295 | } |
| 297 | 296 | |
| 298 | − ib_device_put(ibdev); | |
| 299 | − | |
| 300 | 297 | return NOTIFY_DONE; |
| 301 | 298 | } |
| 302 | 299 | |
| @@ -1618,13 +1618,13 @@ int irdma_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, int attr_mask, · 1617 unmodified lines | ||
| 1618 | 1618 | |
| 1619 | 1619 | if (issue_modify_qp && iwqp->ibqp_state > IB_QPS_RTS) { |
| 1620 | 1620 | if (dont_wait) { |
| 1621 | − if (iwqp->cm_id && iwqp->hw_tcp_state) { | |
| 1621 | + if (iwqp->hw_tcp_state) { | |
| 1622 | 1622 | spin_lock_irqsave(&iwqp->lock, flags); |
| 1623 | 1623 | iwqp->hw_tcp_state = IRDMA_TCP_STATE_CLOSED; |
| 1624 | 1624 | iwqp->last_aeq = IRDMA_AE_RESET_SENT; |
| 1625 | 1625 | spin_unlock_irqrestore(&iwqp->lock, flags); |
| 1626 | − irdma_cm_disconn(iwqp); | |
| 1627 | 1626 | } |
| 1627 | + irdma_cm_disconn(iwqp); | |
| 1628 | 1628 | } else { |
| 1629 | 1629 | int close_timer_started; |
| 1630 | 1630 | |
| @@ -38,13 +38,13 @@ static int rxe_mcast_add(struct rxe_dev *rxe, union ib_gid *mgid) · 37 unmodified lines | ||
| 38 | 38 | } |
| 39 | 39 | |
| 40 | 40 | /** |
| 41 | − * rxe_mcast_delete - delete multicast address from rxe device | |
| 41 | + * rxe_mcast_del - delete multicast address from rxe device | |
| 42 | 42 | * @rxe: rxe device object |
| 43 | 43 | * @mgid: multicast address as a gid |
| 44 | 44 | * |
| 45 | 45 | * Returns 0 on success else an error |
| 46 | 46 | */ |
| 47 | −static int rxe_mcast_delete(struct rxe_dev *rxe, union ib_gid *mgid) | |
| 47 | +static int rxe_mcast_del(struct rxe_dev *rxe, union ib_gid *mgid) | |
| 48 | 48 | { |
| 49 | 49 | unsigned char ll_addr[ETH_ALEN]; |
| 50 | 50 | |
| @@ -143,11 +143,10 @@ static struct rxe_mcg *__rxe_lookup_mcg(struct rxe_dev *rxe, · 92 unmodified lines | ||
| 143 | 143 | struct rxe_mcg *rxe_lookup_mcg(struct rxe_dev *rxe, union ib_gid *mgid) |
| 144 | 144 | { |
| 145 | 145 | struct rxe_mcg *mcg; |
| 146 | − unsigned long flags; | |
| 147 | 146 | |
| 148 | − spin_lock_irqsave(&rxe->mcg_lock, flags); | |
| 147 | + spin_lock_bh(&rxe->mcg_lock); | |
| 149 | 148 | mcg = __rxe_lookup_mcg(rxe, mgid); |
| 150 | − spin_unlock_irqrestore(&rxe->mcg_lock, flags); | |
| 149 | + spin_unlock_bh(&rxe->mcg_lock); | |
| 151 | 150 | |
| 152 | 151 | return mcg; |
| 153 | 152 | } |
| @@ -159,17 +158,10 @@ struct rxe_mcg *rxe_lookup_mcg(struct rxe_dev *rxe, union ib_gid *mgid) · 5 unmodified lines | ||
| 159 | 158 | * @mcg: new mcg object |
| 160 | 159 | * |
| 161 | 160 | * Context: caller should hold rxe->mcg lock |
| 162 | − * Returns: 0 on success else an error | |
| 163 | 161 | */ |
| 164 | −static int __rxe_init_mcg(struct rxe_dev *rxe, union ib_gid *mgid, | |
| 165 | − struct rxe_mcg *mcg) | |
| 162 | +static void __rxe_init_mcg(struct rxe_dev *rxe, union ib_gid *mgid, | |
| 163 | + struct rxe_mcg *mcg) | |
| 166 | 164 | { |
| 167 | − int err; | |
| 168 | − | |
| 169 | − err = rxe_mcast_add(rxe, mgid); | |
| 170 | − if (unlikely(err)) | |
| 171 | − return err; | |
| 172 | − | |
| 173 | 165 | kref_init(&mcg->ref_cnt); |
| 174 | 166 | memcpy(&mcg->mgid, mgid, sizeof(mcg->mgid)); |
| 175 | 167 | INIT_LIST_HEAD(&mcg->qp_list); |
| @@ -184,8 +176,6 @@ static int __rxe_init_mcg(struct rxe_dev *rxe, union ib_gid *mgid, · 8 unmodified lines | ||
| 184 | 176 | */ |
| 185 | 177 | kref_get(&mcg->ref_cnt); |
| 186 | 178 | __rxe_insert_mcg(mcg); |
| 187 | − | |
| 188 | − return 0; | |
| 189 | 179 | } |
| 190 | 180 | |
| 191 | 181 | /** |
| @@ -198,7 +188,6 @@ static int __rxe_init_mcg(struct rxe_dev *rxe, union ib_gid *mgid, · 6 unmodified lines | ||
| 198 | 188 | static struct rxe_mcg *rxe_get_mcg(struct rxe_dev *rxe, union ib_gid *mgid) |
| 199 | 189 | { |
| 200 | 190 | struct rxe_mcg *mcg, *tmp; |
| 201 | − unsigned long flags; | |
| 202 | 191 | int err; |
| 203 | 192 | |
| 204 | 193 | if (rxe->attr.max_mcast_grp == 0) |
| @@ -209,36 +198,38 @@ static struct rxe_mcg *rxe_get_mcg(struct rxe_dev *rxe, union ib_gid *mgid) · 4 unmodified lines | ||
| 209 | 198 | if (mcg) |
| 210 | 199 | return mcg; |
| 211 | 200 | |
| 201 | + /* check to see if we have reached limit */ | |
| 202 | + if (atomic_inc_return(&rxe->mcg_num) > rxe->attr.max_mcast_grp) { | |
| 203 | + err = -ENOMEM; | |
| 204 | + goto err_dec; | |
| 205 | + } | |
| 206 | + | |
| 212 | 207 | /* speculative alloc of new mcg */ |
| 213 | 208 | mcg = kzalloc(sizeof(*mcg), GFP_KERNEL); |
| 214 | 209 | if (!mcg) |
| 215 | 210 | return ERR_PTR(-ENOMEM); |
| 216 | 211 | |
| 217 | − spin_lock_irqsave(&rxe->mcg_lock, flags); | |
| 212 | + spin_lock_bh(&rxe->mcg_lock); | |
| 218 | 213 | /* re-check to see if someone else just added it */ |
| 219 | 214 | tmp = __rxe_lookup_mcg(rxe, mgid); |
| 220 | 215 | if (tmp) { |
| 216 | + spin_unlock_bh(&rxe->mcg_lock); | |
| 217 | + atomic_dec(&rxe->mcg_num); | |
| 221 | 218 | kfree(mcg); |
| 222 | − mcg = tmp; | |
| 223 | − goto out; | |
| 219 | + return tmp; | |
| 224 | 220 | } |
| 225 | 221 | |
| 226 | − if (atomic_inc_return(&rxe->mcg_num) > rxe->attr.max_mcast_grp) { | |
| 227 | − err = -ENOMEM; | |
| 228 | − goto err_dec; | |
| 229 | − } | |
| 222 | + __rxe_init_mcg(rxe, mgid, mcg); | |
| 223 | + spin_unlock_bh(&rxe->mcg_lock); | |
| 230 | 224 | |
| 231 | − err = __rxe_init_mcg(rxe, mgid, mcg); | |
| 232 | − if (err) | |
| 233 | − goto err_dec; | |
| 234 | −out: | |
| 235 | − spin_unlock_irqrestore(&rxe->mcg_lock, flags); | |
| 236 | − return mcg; | |
| 225 | + /* add mcast address outside of lock */ | |
| 226 | + err = rxe_mcast_add(rxe, mgid); | |
| 227 | + if (!err) | |
| 228 | + return mcg; | |
| 237 | 229 | |
| 230 | + kfree(mcg); | |
| 238 | 231 | err_dec: |
| 239 | 232 | atomic_dec(&rxe->mcg_num); |
| 240 | − spin_unlock_irqrestore(&rxe->mcg_lock, flags); | |
| 241 | − kfree(mcg); | |
| 242 | 233 | return ERR_PTR(err); |
| 243 | 234 | } |
| 244 | 235 | |
| @@ -268,7 +259,6 @@ static void __rxe_destroy_mcg(struct rxe_mcg *mcg) · 23 unmodified lines | ||
| 268 | 259 | __rxe_remove_mcg(mcg); |
| 269 | 260 | kref_put(&mcg->ref_cnt, rxe_cleanup_mcg); |
| 270 | 261 | |
| 271 | − rxe_mcast_delete(mcg->rxe, &mcg->mgid); | |
| 272 | 262 | atomic_dec(&rxe->mcg_num); |
| 273 | 263 | } |
| 274 | 264 | |
| @@ -280,11 +270,12 @@ static void __rxe_destroy_mcg(struct rxe_mcg *mcg) · 5 unmodified lines | ||
| 280 | 270 | */ |
| 281 | 271 | static void rxe_destroy_mcg(struct rxe_mcg *mcg) |
| 282 | 272 | { |
| 283 | − unsigned long flags; | |
| 273 | + /* delete mcast address outside of lock */ | |
| 274 | + rxe_mcast_del(mcg->rxe, &mcg->mgid); | |
| 284 | 275 | |
| 285 | − spin_lock_irqsave(&mcg->rxe->mcg_lock, flags); | |
| 276 | + spin_lock_bh(&mcg->rxe->mcg_lock); | |
| 286 | 277 | __rxe_destroy_mcg(mcg); |
| 287 | − spin_unlock_irqrestore(&mcg->rxe->mcg_lock, flags); | |
| 278 | + spin_unlock_bh(&mcg->rxe->mcg_lock); | |
| 288 | 279 | } |
| 289 | 280 | |
| 290 | 281 | /** |
| @@ -339,25 +330,24 @@ static int rxe_attach_mcg(struct rxe_mcg *mcg, struct rxe_qp *qp) · 48 unmodified lines | ||
| 339 | 330 | { |
| 340 | 331 | struct rxe_dev *rxe = mcg->rxe; |
| 341 | 332 | struct rxe_mca *mca, *tmp; |
| 342 | − unsigned long flags; | |
| 343 | 333 | int err; |
| 344 | 334 | |
| 345 | 335 | /* check to see if the qp is already a member of the group */ |
| 346 | − spin_lock_irqsave(&rxe->mcg_lock, flags); | |
| 336 | + spin_lock_bh(&rxe->mcg_lock); | |
| 347 | 337 | list_for_each_entry(mca, &mcg->qp_list, qp_list) { |
| 348 | 338 | if (mca->qp == qp) { |
| 349 | − spin_unlock_irqrestore(&rxe->mcg_lock, flags); | |
| 339 | + spin_unlock_bh(&rxe->mcg_lock); | |
| 350 | 340 | return 0; |
| 351 | 341 | } |
| 352 | 342 | } |
| 353 | − spin_unlock_irqrestore(&rxe->mcg_lock, flags); | |
| 343 | + spin_unlock_bh(&rxe->mcg_lock); | |
| 354 | 344 | |
| 355 | 345 | /* speculative alloc new mca without using GFP_ATOMIC */ |
| 356 | 346 | mca = kzalloc(sizeof(*mca), GFP_KERNEL); |
| 357 | 347 | if (!mca) |
| 358 | 348 | return -ENOMEM; |
| 359 | 349 | |
| 360 | − spin_lock_irqsave(&rxe->mcg_lock, flags); | |
| 350 | + spin_lock_bh(&rxe->mcg_lock); | |
| 361 | 351 | /* re-check to see if someone else just attached qp */ |
| 362 | 352 | list_for_each_entry(tmp, &mcg->qp_list, qp_list) { |
| 363 | 353 | if (tmp->qp == qp) { |
| @@ -371,7 +361,7 @@ static int rxe_attach_mcg(struct rxe_mcg *mcg, struct rxe_qp *qp) · 7 unmodified lines | ||
| 371 | 361 | if (err) |
| 372 | 362 | kfree(mca); |
| 373 | 363 | out: |
| 374 | − spin_unlock_irqrestore(&rxe->mcg_lock, flags); | |
| 364 | + spin_unlock_bh(&rxe->mcg_lock); | |
| 375 | 365 | return err; |
| 376 | 366 | } |
| 377 | 367 | |
| @@ -405,9 +395,8 @@ static int rxe_detach_mcg(struct rxe_mcg *mcg, struct rxe_qp *qp) · 27 unmodified lines | ||
| 405 | 395 | { |
| 406 | 396 | struct rxe_dev *rxe = mcg->rxe; |
| 407 | 397 | struct rxe_mca *mca, *tmp; |
| 408 | − unsigned long flags; | |
| 409 | 398 | |
| 410 | − spin_lock_irqsave(&rxe->mcg_lock, flags); | |
| 399 | + spin_lock_bh(&rxe->mcg_lock); | |
| 411 | 400 | list_for_each_entry_safe(mca, tmp, &mcg->qp_list, qp_list) { |
| 412 | 401 | if (mca->qp == qp) { |
| 413 | 402 | __rxe_cleanup_mca(mca, mcg); |
| @@ -421,13 +410,13 @@ static int rxe_detach_mcg(struct rxe_mcg *mcg, struct rxe_qp *qp) · 7 unmodified lines | ||
| 421 | 410 | if (atomic_read(&mcg->qp_num) <= 0) |
| 422 | 411 | __rxe_destroy_mcg(mcg); |
| 423 | 412 | |
| 424 | − spin_unlock_irqrestore(&rxe->mcg_lock, flags); | |
| 413 | + spin_unlock_bh(&rxe->mcg_lock); | |
| 425 | 414 | return 0; |
| 426 | 415 | } |
| 427 | 416 | } |
| 428 | 417 | |
| 429 | 418 | /* we didn't find the qp on the list */ |
| 430 | − spin_unlock_irqrestore(&rxe->mcg_lock, flags); | |
| 419 | + spin_unlock_bh(&rxe->mcg_lock); | |
| 431 | 420 | return -EINVAL; |
| 432 | 421 | } |
| 433 | 422 | |
| @@ -680,6 +680,11 @@ static struct resp_res *rxe_prepare_read_res(struct rxe_qp *qp, · 679 unmodified lines | ||
| 680 | 680 | * It is assumed that the access permissions if originally good |
| 681 | 681 | * are OK and the mappings to be unchanged. |
| 682 | 682 | * |
| 683 | + * TODO: If someone reregisters an MR to change its size or | |
| 684 | + * access permissions during the processing of an RDMA read | |
| 685 | + * we should kill the responder resource and complete the | |
| 686 | + * operation with an error. | |
| 687 | + * | |
| 683 | 688 | * Return: mr on success else NULL |
| 684 | 689 | */ |
| 685 | 690 | static struct rxe_mr *rxe_recheck_mr(struct rxe_qp *qp, u32 rkey) |
| @@ -690,23 +695,27 @@ static struct rxe_mr *rxe_recheck_mr(struct rxe_qp *qp, u32 rkey) · 4 unmodified lines | ||
| 690 | 695 | |
| 691 | 696 | if (rkey_is_mw(rkey)) { |
| 692 | 697 | mw = rxe_pool_get_index(&rxe->mw_pool, rkey >> 8); |
| 693 | − if (!mw || mw->rkey != rkey) | |
| 698 | + if (!mw) | |
| 694 | 699 | return NULL; |
| 695 | 700 | |
| 696 | − if (mw->state != RXE_MW_STATE_VALID) { | |
| 701 | + mr = mw->mr; | |
| 702 | + if (mw->rkey != rkey || mw->state != RXE_MW_STATE_VALID || | |
| 703 | + !mr || mr->state != RXE_MR_STATE_VALID) { | |
| 697 | 704 | rxe_put(mw); |
| 698 | 705 | return NULL; |
| 699 | 706 | } |
| 700 | 707 | |
| 701 | − mr = mw->mr; | |
| 708 | + rxe_get(mr); | |
| 702 | 709 | rxe_put(mw); |
| 703 | − } else { | |
| 704 | − mr = rxe_pool_get_index(&rxe->mr_pool, rkey >> 8); | |
| 705 | − if (!mr || mr->rkey != rkey) | |
| 706 | − return NULL; | |
| 710 | + | |
| 711 | + return mr; | |
| 707 | 712 | } |
| 708 | 713 | |
| 709 | − if (mr->state != RXE_MR_STATE_VALID) { | |
| 714 | + mr = rxe_pool_get_index(&rxe->mr_pool, rkey >> 8); | |
| 715 | + if (!mr) | |
| 716 | + return NULL; | |
| 717 | + | |
| 718 | + if (mr->rkey != rkey || mr->state != RXE_MR_STATE_VALID) { | |
| 710 | 719 | rxe_put(mr); |
| 711 | 720 | return NULL; |
| 712 | 721 | } |
| @@ -736,8 +745,14 @@ static enum resp_states read_reply(struct rxe_qp *qp, · 23 unmodified lines | ||
| 736 | 745 | } |
| 737 | 746 | |
| 738 | 747 | if (res->state == rdatm_res_state_new) { |
| 739 | − mr = qp->resp.mr; | |
| 740 | − qp->resp.mr = NULL; | |
| 748 | + if (!res->replay) { | |
| 749 | + mr = qp->resp.mr; | |
| 750 | + qp->resp.mr = NULL; | |
| 751 | + } else { | |
| 752 | + mr = rxe_recheck_mr(qp, res->read.rkey); | |
| 753 | + if (!mr) | |
| 754 | + return RESPST_ERR_RKEY_VIOLATION; | |
| 755 | + } | |
| 741 | 756 | |
| 742 | 757 | if (res->read.resid <= mtu) |
| 743 | 758 | opcode = IB_OPCODE_RC_RDMA_READ_RESPONSE_ONLY; |
| @@ -968,14 +968,15 @@ static void siw_accept_newconn(struct siw_cep *cep) · 967 unmodified lines | ||
| 968 | 968 | |
| 969 | 969 | siw_cep_set_inuse(new_cep); |
| 970 | 970 | rv = siw_proc_mpareq(new_cep); |
| 971 | − siw_cep_set_free(new_cep); | |
| 972 | − | |
| 973 | 971 | if (rv != -EAGAIN) { |
| 974 | 972 | siw_cep_put(cep); |
| 975 | 973 | new_cep->listen_cep = NULL; |
| 976 | − if (rv) | |
| 974 | + if (rv) { | |
| 975 | + siw_cep_set_free(new_cep); | |
| 977 | 976 | goto error; |
| 977 | + } | |
| 978 | 978 | } |
| 979 | + siw_cep_set_free(new_cep); | |
| 979 | 980 | } |
| 980 | 981 | return; |
| 981 | 982 | |
| @@ -1087,9 +1087,15 @@ static int of_count_icc_providers(struct device_node *np) · 1086 unmodified lines | ||
| 1087 | 1087 | { |
| 1088 | 1088 | struct device_node *child; |
| 1089 | 1089 | int count = 0; |
| 1090 | + const struct of_device_id __maybe_unused ignore_list[] = { | |
| 1091 | + { .compatible = "qcom,sc7180-ipa-virt" }, | |
| 1092 | + { .compatible = "qcom,sdx55-ipa-virt" }, | |
| 1093 | + {} | |
| 1094 | + }; | |
| 1090 | 1095 | |
| 1091 | 1096 | for_each_available_child_of_node(np, child) { |
| 1092 | − if (of_property_read_bool(child, "#interconnect-cells")) | |
| 1097 | + if (of_property_read_bool(child, "#interconnect-cells") && | |
| 1098 | + likely(!of_match_node(ignore_list, child))) | |
| 1093 | 1099 | count++; |
| 1094 | 1100 | count += of_count_icc_providers(child); |
| 1095 | 1101 | } |
| @@ -47,7 +47,6 @@ DEFINE_QNODE(qnm_mnoc_sf, SC7180_MASTER_MNOC_SF_MEM_NOC, 1, 32, SC7180_SLAVE_GEM · 46 unmodified lines | ||
| 47 | 47 | DEFINE_QNODE(qnm_snoc_gc, SC7180_MASTER_SNOC_GC_MEM_NOC, 1, 8, SC7180_SLAVE_LLCC); |
| 48 | 48 | DEFINE_QNODE(qnm_snoc_sf, SC7180_MASTER_SNOC_SF_MEM_NOC, 1, 16, SC7180_SLAVE_LLCC); |
| 49 | 49 | DEFINE_QNODE(qxm_gpu, SC7180_MASTER_GFX3D, 2, 32, SC7180_SLAVE_GEM_NOC_SNOC, SC7180_SLAVE_LLCC); |
| 50 | −DEFINE_QNODE(ipa_core_master, SC7180_MASTER_IPA_CORE, 1, 8, SC7180_SLAVE_IPA_CORE); | |
| 51 | 50 | DEFINE_QNODE(llcc_mc, SC7180_MASTER_LLCC, 2, 4, SC7180_SLAVE_EBI1); |
| 52 | 51 | DEFINE_QNODE(qhm_mnoc_cfg, SC7180_MASTER_CNOC_MNOC_CFG, 1, 4, SC7180_SLAVE_SERVICE_MNOC); |
| 53 | 52 | DEFINE_QNODE(qxm_camnoc_hf0, SC7180_MASTER_CAMNOC_HF0, 2, 32, SC7180_SLAVE_MNOC_HF_MEM_NOC); |
| @@ -129,7 +128,6 @@ DEFINE_QNODE(qhs_mdsp_ms_mpu_cfg, SC7180_SLAVE_MSS_PROC_MS_MPU_CFG, 1, 4); · 75 unmodified lines | ||
| 129 | 128 | DEFINE_QNODE(qns_gem_noc_snoc, SC7180_SLAVE_GEM_NOC_SNOC, 1, 8, SC7180_MASTER_GEM_NOC_SNOC); |
| 130 | 129 | DEFINE_QNODE(qns_llcc, SC7180_SLAVE_LLCC, 1, 16, SC7180_MASTER_LLCC); |
| 131 | 130 | DEFINE_QNODE(srvc_gemnoc, SC7180_SLAVE_SERVICE_GEM_NOC, 1, 4); |
| 132 | −DEFINE_QNODE(ipa_core_slave, SC7180_SLAVE_IPA_CORE, 1, 8); | |
| 133 | 131 | DEFINE_QNODE(ebi, SC7180_SLAVE_EBI1, 2, 4); |
| 134 | 132 | DEFINE_QNODE(qns_mem_noc_hf, SC7180_SLAVE_MNOC_HF_MEM_NOC, 1, 32, SC7180_MASTER_MNOC_HF_MEM_NOC); |
| 135 | 133 | DEFINE_QNODE(qns_mem_noc_sf, SC7180_SLAVE_MNOC_SF_MEM_NOC, 1, 32, SC7180_MASTER_MNOC_SF_MEM_NOC); |
| @@ -160,7 +158,6 @@ DEFINE_QBCM(bcm_mc0, "MC0", true, &ebi); · 24 unmodified lines | ||
| 160 | 158 | DEFINE_QBCM(bcm_sh0, "SH0", true, &qns_llcc); |
| 161 | 159 | DEFINE_QBCM(bcm_mm0, "MM0", false, &qns_mem_noc_hf); |
| 162 | 160 | DEFINE_QBCM(bcm_ce0, "CE0", false, &qxm_crypto); |
| 163 | −DEFINE_QBCM(bcm_ip0, "IP0", false, &ipa_core_slave); | |
| 164 | 161 | DEFINE_QBCM(bcm_cn0, "CN0", true, &qnm_snoc, &xm_qdss_dap, &qhs_a1_noc_cfg, &qhs_a2_noc_cfg, &qhs_ahb2phy0, &qhs_aop, &qhs_aoss, &qhs_boot_rom, &qhs_camera_cfg, &qhs_camera_nrt_throttle_cfg, &qhs_camera_rt_throttle_cfg, &qhs_clk_ctl, &qhs_cpr_cx, &qhs_cpr_mx, &qhs_crypto0_cfg, &qhs_dcc_cfg, &qhs_ddrss_cfg, &qhs_display_cfg, &qhs_display_rt_throttle_cfg, &qhs_display_throttle_cfg, &qhs_glm, &qhs_gpuss_cfg, &qhs_imem_cfg, &qhs_ipa, &qhs_mnoc_cfg, &qhs_mss_cfg, &qhs_npu_cfg, &qhs_npu_dma_throttle_cfg, &qhs_npu_dsp_throttle_cfg, &qhs_pimem_cfg, &qhs_prng, &qhs_qdss_cfg, &qhs_qm_cfg, &qhs_qm_mpu_cfg, &qhs_qup0, &qhs_qup1, &qhs_security, &qhs_snoc_cfg, &qhs_tcsr, &qhs_tlmm_1, &qhs_tlmm_2, &qhs_tlmm_3, &qhs_ufs_mem_cfg, &qhs_usb3, &qhs_venus_cfg, &qhs_venus_throttle_cfg, &qhs_vsense_ctrl_cfg, &srvc_cnoc); |
| 165 | 162 | DEFINE_QBCM(bcm_mm1, "MM1", false, &qxm_camnoc_hf0_uncomp, &qxm_camnoc_hf1_uncomp, &qxm_camnoc_sf_uncomp, &qhm_mnoc_cfg, &qxm_mdp0, &qxm_rot, &qxm_venus0, &qxm_venus_arm9); |
| 166 | 163 | DEFINE_QBCM(bcm_sh2, "SH2", false, &acm_sys_tcu); |
| @@ -372,22 +369,6 @@ static struct qcom_icc_desc sc7180_gem_noc = { · 205 unmodified lines | ||
| 372 | 369 | .num_bcms = ARRAY_SIZE(gem_noc_bcms), |
| 373 | 370 | }; |
| 374 | 371 | |
| 375 | −static struct qcom_icc_bcm *ipa_virt_bcms[] = { | |
| 376 | − &bcm_ip0, | |
| 377 | −}; | |
| 378 | − | |
| 379 | −static struct qcom_icc_node *ipa_virt_nodes[] = { | |
| 380 | − [MASTER_IPA_CORE] = &ipa_core_master, | |
| 381 | − [SLAVE_IPA_CORE] = &ipa_core_slave, | |
| 382 | −}; | |
| 383 | − | |
| 384 | −static struct qcom_icc_desc sc7180_ipa_virt = { | |
| 385 | − .nodes = ipa_virt_nodes, | |
| 386 | − .num_nodes = ARRAY_SIZE(ipa_virt_nodes), | |
| 387 | − .bcms = ipa_virt_bcms, | |
| 388 | − .num_bcms = ARRAY_SIZE(ipa_virt_bcms), | |
| 389 | −}; | |
| 390 | − | |
| 391 | 372 | static struct qcom_icc_bcm *mc_virt_bcms[] = { |
| 392 | 373 | &bcm_acv, |
| 393 | 374 | &bcm_mc0, |
| @@ -519,8 +500,6 @@ static const struct of_device_id qnoc_of_match[] = { · 125 unmodified lines | ||
| 519 | 500 | .data = &sc7180_dc_noc}, |
| 520 | 501 | { .compatible = "qcom,sc7180-gem-noc", |
| 521 | 502 | .data = &sc7180_gem_noc}, |
| 522 | − { .compatible = "qcom,sc7180-ipa-virt", | |
| 523 | − .data = &sc7180_ipa_virt}, | |
| 524 | 503 | { .compatible = "qcom,sc7180-mc-virt", |
| 525 | 504 | .data = &sc7180_mc_virt}, |
| 526 | 505 | { .compatible = "qcom,sc7180-mmss-noc", |
| @@ -18,7 +18,6 @@ · 17 unmodified lines | ||
| 18 | 18 | #include "icc-rpmh.h" |
| 19 | 19 | #include "sdx55.h" |
| 20 | 20 | |
| 21 | −DEFINE_QNODE(ipa_core_master, SDX55_MASTER_IPA_CORE, 1, 8, SDX55_SLAVE_IPA_CORE); | |
| 22 | 21 | DEFINE_QNODE(llcc_mc, SDX55_MASTER_LLCC, 4, 4, SDX55_SLAVE_EBI_CH0); |
| 23 | 22 | DEFINE_QNODE(acm_tcu, SDX55_MASTER_TCU_0, 1, 8, SDX55_SLAVE_LLCC, SDX55_SLAVE_MEM_NOC_SNOC, SDX55_SLAVE_MEM_NOC_PCIE_SNOC); |
| 24 | 23 | DEFINE_QNODE(qnm_snoc_gc, SDX55_MASTER_SNOC_GC_MEM_NOC, 1, 8, SDX55_SLAVE_LLCC); |
| @@ -40,7 +39,6 @@ DEFINE_QNODE(xm_pcie, SDX55_MASTER_PCIE, 1, 8, SDX55_SLAVE_ANOC_SNOC); · 15 unmodified lines | ||
| 40 | 39 | DEFINE_QNODE(xm_qdss_etr, SDX55_MASTER_QDSS_ETR, 1, 8, SDX55_SLAVE_SNOC_CFG, SDX55_SLAVE_EMAC_CFG, SDX55_SLAVE_USB3, SDX55_SLAVE_AOSS, SDX55_SLAVE_SPMI_FETCHER, SDX55_SLAVE_QDSS_CFG, SDX55_SLAVE_PDM, SDX55_SLAVE_SNOC_MEM_NOC_GC, SDX55_SLAVE_TCSR, SDX55_SLAVE_CNOC_DDRSS, SDX55_SLAVE_SPMI_VGI_COEX, SDX55_SLAVE_QPIC, SDX55_SLAVE_OCIMEM, SDX55_SLAVE_IPA_CFG, SDX55_SLAVE_USB3_PHY_CFG, SDX55_SLAVE_AOP, SDX55_SLAVE_BLSP_1, SDX55_SLAVE_SDCC_1, SDX55_SLAVE_CNOC_MSS, SDX55_SLAVE_PCIE_PARF, SDX55_SLAVE_ECC_CFG, SDX55_SLAVE_AUDIO, SDX55_SLAVE_AOSS, SDX55_SLAVE_PRNG, SDX55_SLAVE_CRYPTO_0_CFG, SDX55_SLAVE_TCU, SDX55_SLAVE_CLK_CTL, SDX55_SLAVE_IMEM_CFG); |
| 41 | 40 | DEFINE_QNODE(xm_sdc1, SDX55_MASTER_SDCC_1, 1, 8, SDX55_SLAVE_AOSS, SDX55_SLAVE_IPA_CFG, SDX55_SLAVE_ANOC_SNOC, SDX55_SLAVE_AOP, SDX55_SLAVE_AUDIO); |
| 42 | 41 | DEFINE_QNODE(xm_usb3, SDX55_MASTER_USB3, 1, 8, SDX55_SLAVE_ANOC_SNOC); |
| 43 | −DEFINE_QNODE(ipa_core_slave, SDX55_SLAVE_IPA_CORE, 1, 8); | |
| 44 | 42 | DEFINE_QNODE(ebi, SDX55_SLAVE_EBI_CH0, 1, 4); |
| 45 | 43 | DEFINE_QNODE(qns_llcc, SDX55_SLAVE_LLCC, 1, 16, SDX55_SLAVE_EBI_CH0); |
| 46 | 44 | DEFINE_QNODE(qns_memnoc_snoc, SDX55_SLAVE_MEM_NOC_SNOC, 1, 8, SDX55_MASTER_MEM_NOC_SNOC); |
| @@ -82,7 +80,6 @@ DEFINE_QNODE(xs_sys_tcu_cfg, SDX55_SLAVE_TCU, 1, 8); · 35 unmodified lines | ||
| 82 | 80 | DEFINE_QBCM(bcm_mc0, "MC0", true, &ebi); |
| 83 | 81 | DEFINE_QBCM(bcm_sh0, "SH0", true, &qns_llcc); |
| 84 | 82 | DEFINE_QBCM(bcm_ce0, "CE0", false, &qxm_crypto); |
| 85 | −DEFINE_QBCM(bcm_ip0, "IP0", false, &ipa_core_slave); | |
| 86 | 83 | DEFINE_QBCM(bcm_pn0, "PN0", false, &qhm_snoc_cfg); |
| 87 | 84 | DEFINE_QBCM(bcm_sh3, "SH3", false, &xm_apps_rdwr); |
| 88 | 85 | DEFINE_QBCM(bcm_sh4, "SH4", false, &qns_memnoc_snoc, &qns_sys_pcie); |
| @@ -219,22 +216,6 @@ static const struct qcom_icc_desc sdx55_system_noc = { · 130 unmodified lines | ||
| 219 | 216 | .num_bcms = ARRAY_SIZE(system_noc_bcms), |
| 220 | 217 | }; |
| 221 | 218 | |
| 222 | −static struct qcom_icc_bcm *ipa_virt_bcms[] = { | |
| 223 | − &bcm_ip0, | |
| 224 | −}; | |
| 225 | − | |
| 226 | −static struct qcom_icc_node *ipa_virt_nodes[] = { | |
| 227 | − [MASTER_IPA_CORE] = &ipa_core_master, | |
| 228 | − [SLAVE_IPA_CORE] = &ipa_core_slave, | |
| 229 | −}; | |
| 230 | − | |
| 231 | −static const struct qcom_icc_desc sdx55_ipa_virt = { | |
| 232 | − .nodes = ipa_virt_nodes, | |
| 233 | − .num_nodes = ARRAY_SIZE(ipa_virt_nodes), | |
| 234 | − .bcms = ipa_virt_bcms, | |
| 235 | − .num_bcms = ARRAY_SIZE(ipa_virt_bcms), | |
| 236 | −}; | |
| 237 | − | |
| 238 | 219 | static const struct of_device_id qnoc_of_match[] = { |
| 239 | 220 | { .compatible = "qcom,sdx55-mc-virt", |
| 240 | 221 | .data = &sdx55_mc_virt}, |
| @@ -242,8 +223,6 @@ static const struct of_device_id qnoc_of_match[] = { · 1 unmodified line | ||
| 242 | 223 | .data = &sdx55_mem_noc}, |
| 243 | 224 | { .compatible = "qcom,sdx55-system-noc", |
| 244 | 225 | .data = &sdx55_system_noc}, |
| 245 | − { .compatible = "qcom,sdx55-ipa-virt", | |
| 246 | − .data = &sdx55_ipa_virt}, | |
| 247 | 226 | { } |
| 248 | 227 | }; |
| 249 | 228 | MODULE_DEVICE_TABLE(of, qnoc_of_match); |
| @@ -407,6 +407,7 @@ · 406 unmodified lines | ||
| 407 | 407 | /* IOMMU IVINFO */ |
| 408 | 408 | #define IOMMU_IVINFO_OFFSET 36 |
| 409 | 409 | #define IOMMU_IVINFO_EFRSUP BIT(0) |
| 410 | +#define IOMMU_IVINFO_DMA_REMAP BIT(1) | |
| 410 | 411 | |
| 411 | 412 | /* IOMMU Feature Reporting Field (for IVHD type 10h */ |
| 412 | 413 | #define IOMMU_FEAT_GASUP_SHIFT 6 |
| @@ -449,6 +450,9 @@ extern struct irq_remap_table **irq_lookup_table; · 36 unmodified lines | ||
| 449 | 450 | /* Interrupt remapping feature used? */ |
| 450 | 451 | extern bool amd_iommu_irq_remap; |
| 451 | 452 | |
| 453 | +/* IVRS indicates that pre-boot remapping was enabled */ | |
| 454 | +extern bool amdr_ivrs_remap_support; | |
| 455 | + | |
| 452 | 456 | /* kmem_cache to get tables with 128 byte alignement */ |
| 453 | 457 | extern struct kmem_cache *amd_iommu_irq_cache; |
| 454 | 458 | |
| @@ -84,7 +84,7 @@ · 83 unmodified lines | ||
| 84 | 84 | #define ACPI_DEVFLAG_LINT1 0x80 |
| 85 | 85 | #define ACPI_DEVFLAG_ATSDIS 0x10000000 |
| 86 | 86 | |
| 87 | −#define LOOP_TIMEOUT 100000 | |
| 87 | +#define LOOP_TIMEOUT 2000000 | |
| 88 | 88 | /* |
| 89 | 89 | * ACPI table definitions |
| 90 | 90 | * |
| @@ -182,6 +182,7 @@ u32 amd_iommu_max_pasid __read_mostly = ~0; · 91 unmodified lines | ||
| 182 | 182 | |
| 183 | 183 | bool amd_iommu_v2_present __read_mostly; |
| 184 | 184 | static bool amd_iommu_pc_present __read_mostly; |
| 185 | +bool amdr_ivrs_remap_support __read_mostly; | |
| 185 | 186 | |
| 186 | 187 | bool amd_iommu_force_isolation __read_mostly; |
| 187 | 188 | |
| @@ -326,6 +327,8 @@ static void __init early_iommu_features_init(struct amd_iommu *iommu, · 138 unmodified lines | ||
| 326 | 327 | { |
| 327 | 328 | if (amd_iommu_ivinfo & IOMMU_IVINFO_EFRSUP) |
| 328 | 329 | iommu->features = h->efr_reg; |
| 330 | + if (amd_iommu_ivinfo & IOMMU_IVINFO_DMA_REMAP) | |
| 331 | + amdr_ivrs_remap_support = true; | |
| 329 | 332 | } |
| 330 | 333 | |
| 331 | 334 | /* Access to l1 and l2 indexed register spaces */ |
| @@ -1986,8 +1989,7 @@ static int __init amd_iommu_init_pci(void) · 1654 unmodified lines | ||
| 1986 | 1989 | for_each_iommu(iommu) |
| 1987 | 1990 | iommu_flush_all_caches(iommu); |
| 1988 | 1991 | |
| 1989 | − if (!ret) | |
| 1990 | − print_iommu_info(); | |
| 1992 | + print_iommu_info(); | |
| 1991 | 1993 | |
| 1992 | 1994 | out: |
| 1993 | 1995 | return ret; |
| @@ -1838,17 +1838,10 @@ void amd_iommu_domain_update(struct protection_domain *domain) · 1837 unmodified lines | ||
| 1838 | 1838 | amd_iommu_domain_flush_complete(domain); |
| 1839 | 1839 | } |
| 1840 | 1840 | |
| 1841 | −static void __init amd_iommu_init_dma_ops(void) | |
| 1842 | −{ | |
| 1843 | − swiotlb = (iommu_default_passthrough() || sme_me_mask) ? 1 : 0; | |
| 1844 | −} | |
| 1845 | − | |
| 1846 | 1841 | int __init amd_iommu_init_api(void) |
| 1847 | 1842 | { |
| 1848 | 1843 | int err; |
| 1849 | 1844 | |
| 1850 | − amd_iommu_init_dma_ops(); | |
| 1851 | − | |
| 1852 | 1845 | err = bus_set_iommu(&pci_bus_type, &amd_iommu_ops); |
| 1853 | 1846 | if (err) |
| 1854 | 1847 | return err; |
| @@ -2162,6 +2155,8 @@ static bool amd_iommu_capable(enum iommu_cap cap) · 307 unmodified lines | ||
| 2162 | 2155 | return (irq_remapping_enabled == 1); |
| 2163 | 2156 | case IOMMU_CAP_NOEXEC: |
| 2164 | 2157 | return false; |
| 2158 | + case IOMMU_CAP_PRE_BOOT_PROTECTION: | |
| 2159 | + return amdr_ivrs_remap_support; | |
| 2165 | 2160 | default: |
| 2166 | 2161 | break; |
| 2167 | 2162 | } |
| @@ -2271,6 +2266,12 @@ static int amd_iommu_def_domain_type(struct device *dev) · 103 unmodified lines | ||
| 2271 | 2266 | return 0; |
| 2272 | 2267 | } |
| 2273 | 2268 | |
| 2269 | +static bool amd_iommu_enforce_cache_coherency(struct iommu_domain *domain) | |
| 2270 | +{ | |
| 2271 | + /* IOMMU_PTE_FC is always set */ | |
| 2272 | + return true; | |
| 2273 | +} | |
| 2274 | + | |
| 2274 | 2275 | const struct iommu_ops amd_iommu_ops = { |
| 2275 | 2276 | .capable = amd_iommu_capable, |
| 2276 | 2277 | .domain_alloc = amd_iommu_domain_alloc, |
| @@ -2293,6 +2294,7 @@ const struct iommu_ops amd_iommu_ops = { · 16 unmodified lines | ||
| 2293 | 2294 | .flush_iotlb_all = amd_iommu_flush_iotlb_all, |
| 2294 | 2295 | .iotlb_sync = amd_iommu_iotlb_sync, |
| 2295 | 2296 | .free = amd_iommu_domain_free, |
| 2297 | + .enforce_cache_coherency = amd_iommu_enforce_cache_coherency, | |
| 2296 | 2298 | } |
| 2297 | 2299 | }; |
| 2298 | 2300 | |
| @@ -956,6 +956,7 @@ static void __exit amd_iommu_v2_exit(void) · 955 unmodified lines | ||
| 956 | 956 | { |
| 957 | 957 | struct device_state *dev_state, *next; |
| 958 | 958 | unsigned long flags; |
| 959 | + LIST_HEAD(freelist); | |
| 959 | 960 | |
| 960 | 961 | if (!amd_iommu_v2_supported()) |
| 961 | 962 | return; |
| @@ -975,11 +976,20 @@ static void __exit amd_iommu_v2_exit(void) · 13 unmodified lines | ||
| 975 | 976 | |
| 976 | 977 | put_device_state(dev_state); |
| 977 | 978 | list_del(&dev_state->list); |
| 978 | − free_device_state(dev_state); | |
| 979 | + list_add_tail(&dev_state->list, &freelist); | |
| 979 | 980 | } |
| 980 | 981 | |
| 981 | 982 | spin_unlock_irqrestore(&state_lock, flags); |
| 982 | 983 | |
| 984 | + /* | |
| 985 | + * Since free_device_state waits on the count to be zero, | |
| 986 | + * we need to free dev_state outside the spinlock. | |
| 987 | + */ | |
| 988 | + list_for_each_entry_safe(dev_state, next, &freelist, list) { | |
| 989 | + list_del(&dev_state->list); | |
| 990 | + free_device_state(dev_state); | |
| 991 | + } | |
| 992 | + | |
| 983 | 993 | destroy_workqueue(iommu_wq); |
| 984 | 994 | } |
| 985 | 995 | |
| @@ -773,6 +773,7 @@ static const struct iommu_ops apple_dart_iommu_ops = { · 772 unmodified lines | ||
| 773 | 773 | .get_resv_regions = apple_dart_get_resv_regions, |
| 774 | 774 | .put_resv_regions = generic_iommu_put_resv_regions, |
| 775 | 775 | .pgsize_bitmap = -1UL, /* Restricted during dart probe */ |
| 776 | + .owner = THIS_MODULE, | |
| 776 | 777 | .default_domain_ops = &(const struct iommu_domain_ops) { |
| 777 | 778 | .attach_dev = apple_dart_attach_dev, |
| 778 | 779 | .detach_dev = apple_dart_detach_dev, |
| @@ -859,16 +860,15 @@ static int apple_dart_probe(struct platform_device *pdev) · 80 unmodified lines | ||
| 859 | 860 | dart->dev = dev; |
| 860 | 861 | spin_lock_init(&dart->lock); |
| 861 | 862 | |
| 862 | − res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | |
| 863 | + dart->regs = devm_platform_get_and_ioremap_resource(pdev, 0, &res); | |
| 864 | + if (IS_ERR(dart->regs)) | |
| 865 | + return PTR_ERR(dart->regs); | |
| 866 | + | |
| 863 | 867 | if (resource_size(res) < 0x4000) { |
| 864 | 868 | dev_err(dev, "MMIO region too small (%pr)\n", res); |
| 865 | 869 | return -EINVAL; |
| 866 | 870 | } |
| 867 | 871 | |
| 868 | − dart->regs = devm_ioremap_resource(dev, res); | |
| 869 | − if (IS_ERR(dart->regs)) | |
| 870 | − return PTR_ERR(dart->regs); | |
| 871 | − | |
| 872 | 872 | dart->irq = platform_get_irq(pdev, 0); |
| 873 | 873 | if (dart->irq < 0) |
| 874 | 874 | return -ENODEV; |
| @@ -6,6 +6,7 @@ · 5 unmodified lines | ||
| 6 | 6 | #include <linux/mm.h> |
| 7 | 7 | #include <linux/mmu_context.h> |
| 8 | 8 | #include <linux/mmu_notifier.h> |
| 9 | +#include <linux/sched/mm.h> | |
| 9 | 10 | #include <linux/slab.h> |
| 10 | 11 | |
| 11 | 12 | #include "arm-smmu-v3.h" |
| @@ -96,9 +97,14 @@ static struct arm_smmu_ctx_desc *arm_smmu_alloc_shared_cd(struct mm_struct *mm) · 84 unmodified lines | ||
| 96 | 97 | struct arm_smmu_ctx_desc *cd; |
| 97 | 98 | struct arm_smmu_ctx_desc *ret = NULL; |
| 98 | 99 | |
| 100 | + /* Don't free the mm until we release the ASID */ | |
| 101 | + mmgrab(mm); | |
| 102 | + | |
| 99 | 103 | asid = arm64_mm_context_get(mm); |
| 100 | − if (!asid) | |
| 101 | − return ERR_PTR(-ESRCH); | |
| 104 | + if (!asid) { | |
| 105 | + err = -ESRCH; | |
| 106 | + goto out_drop_mm; | |
| 107 | + } | |
| 102 | 108 | |
| 103 | 109 | cd = kzalloc(sizeof(*cd), GFP_KERNEL); |
| 104 | 110 | if (!cd) { |
| @@ -165,6 +171,8 @@ out_free_cd: · 60 unmodified lines | ||
| 165 | 171 | kfree(cd); |
| 166 | 172 | out_put_context: |
| 167 | 173 | arm64_mm_context_put(mm); |
| 174 | +out_drop_mm: | |
| 175 | + mmdrop(mm); | |
| 168 | 176 | return err < 0 ? ERR_PTR(err) : ret; |
| 169 | 177 | } |
| 170 | 178 | |
| @@ -173,6 +181,7 @@ static void arm_smmu_free_shared_cd(struct arm_smmu_ctx_desc *cd) · 2 unmodified lines | ||
| 173 | 181 | if (arm_smmu_free_asid(cd)) { |
| 174 | 182 | /* Unpin ASID */ |
| 175 | 183 | arm64_mm_context_put(cd->mm); |
| 184 | + mmdrop(cd->mm); | |
| 176 | 185 | kfree(cd); |
| 177 | 186 | } |
| 178 | 187 | } |
| @@ -183,7 +192,14 @@ static void arm_smmu_mm_invalidate_range(struct mmu_notifier *mn, · 4 unmodified lines | ||
| 183 | 192 | { |
| 184 | 193 | struct arm_smmu_mmu_notifier *smmu_mn = mn_to_smmu(mn); |
| 185 | 194 | struct arm_smmu_domain *smmu_domain = smmu_mn->domain; |
| 186 | − size_t size = end - start + 1; | |
| 195 | + size_t size; | |
| 196 | + | |
| 197 | + /* | |
| 198 | + * The mm_types defines vm_end as the first byte after the end address, | |
| 199 | + * different from IOMMU subsystem using the last address of an address | |
| 200 | + * range. So do a simple translation here by calculating size correctly. | |
| 201 | + */ | |
| 202 | + size = end - start; | |
| 187 | 203 | |
| 188 | 204 | if (!(smmu_domain->smmu->features & ARM_SMMU_FEAT_BTM)) |
| 189 | 205 | arm_smmu_tlb_inv_range_asid(start, size, smmu_mn->cd->asid, |
| @@ -3770,6 +3770,8 @@ static int arm_smmu_device_probe(struct platform_device *pdev) · 3769 unmodified lines | ||
| 3770 | 3770 | |
| 3771 | 3771 | /* Base address */ |
| 3772 | 3772 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
| 3773 | + if (!res) | |
| 3774 | + return -EINVAL; | |
| 3773 | 3775 | if (resource_size(res) < arm_smmu_resource_size(smmu)) { |
| 3774 | 3776 | dev_err(dev, "MMIO region too small (%pr)\n", res); |
| 3775 | 3777 | return -EINVAL; |
| @@ -211,7 +211,8 @@ struct arm_smmu_device *arm_smmu_impl_init(struct arm_smmu_device *smmu) · 210 unmodified lines | ||
| 211 | 211 | if (of_property_read_bool(np, "calxeda,smmu-secure-config-access")) |
| 212 | 212 | smmu->impl = &calxeda_impl; |
| 213 | 213 | |
| 214 | − if (of_device_is_compatible(np, "nvidia,tegra194-smmu") || | |
| 214 | + if (of_device_is_compatible(np, "nvidia,tegra234-smmu") || | |
| 215 | + of_device_is_compatible(np, "nvidia,tegra194-smmu") || | |
| 215 | 216 | of_device_is_compatible(np, "nvidia,tegra186-smmu")) |
| 216 | 217 | return nvidia_smmu_impl_init(smmu); |
| 217 | 218 | |
| @@ -258,6 +258,34 @@ static void nvidia_smmu_probe_finalize(struct arm_smmu_device *smmu, struct devi · 257 unmodified lines | ||
| 258 | 258 | dev_name(dev), err); |
| 259 | 259 | } |
| 260 | 260 | |
| 261 | +static int nvidia_smmu_init_context(struct arm_smmu_domain *smmu_domain, | |
| 262 | + struct io_pgtable_cfg *pgtbl_cfg, | |
| 263 | + struct device *dev) | |
| 264 | +{ | |
| 265 | + struct arm_smmu_device *smmu = smmu_domain->smmu; | |
| 266 | + const struct device_node *np = smmu->dev->of_node; | |
| 267 | + | |
| 268 | + /* | |
| 269 | + * Tegra194 and Tegra234 SoCs have the erratum that causes walk cache | |
| 270 | + * entries to not be invalidated correctly. The problem is that the walk | |
| 271 | + * cache index generated for IOVA is not same across translation and | |
| 272 | + * invalidation requests. This is leading to page faults when PMD entry | |
| 273 | + * is released during unmap and populated with new PTE table during | |
| 274 | + * subsequent map request. Disabling large page mappings avoids the | |
| 275 | + * release of PMD entry and avoid translations seeing stale PMD entry in | |
| 276 | + * walk cache. | |
| 277 | + * Fix this by limiting the page mappings to PAGE_SIZE on Tegra194 and | |
| 278 | + * Tegra234. | |
| 279 | + */ | |
| 280 | + if (of_device_is_compatible(np, "nvidia,tegra234-smmu") || | |
| 281 | + of_device_is_compatible(np, "nvidia,tegra194-smmu")) { | |
| 282 | + smmu->pgsize_bitmap = PAGE_SIZE; | |
| 283 | + pgtbl_cfg->pgsize_bitmap = smmu->pgsize_bitmap; | |
| 284 | + } | |
| 285 | + | |
| 286 | + return 0; | |
| 287 | +} | |
| 288 | + | |
| 261 | 289 | static const struct arm_smmu_impl nvidia_smmu_impl = { |
| 262 | 290 | .read_reg = nvidia_smmu_read_reg, |
| 263 | 291 | .write_reg = nvidia_smmu_write_reg, |
| @@ -268,10 +296,12 @@ static const struct arm_smmu_impl nvidia_smmu_impl = { · 4 unmodified lines | ||
| 268 | 296 | .global_fault = nvidia_smmu_global_fault, |
| 269 | 297 | .context_fault = nvidia_smmu_context_fault, |
| 270 | 298 | .probe_finalize = nvidia_smmu_probe_finalize, |
| 299 | + .init_context = nvidia_smmu_init_context, | |
| 271 | 300 | }; |
| 272 | 301 | |
| 273 | 302 | static const struct arm_smmu_impl nvidia_smmu_single_impl = { |
| 274 | 303 | .probe_finalize = nvidia_smmu_probe_finalize, |
| 304 | + .init_context = nvidia_smmu_init_context, | |
| 275 | 305 | }; |
| 276 | 306 | |
| 277 | 307 | struct arm_smmu_device *nvidia_smmu_impl_init(struct arm_smmu_device *smmu) |
| @@ -408,6 +408,7 @@ static const struct of_device_id __maybe_unused qcom_smmu_impl_of_match[] = { · 407 unmodified lines | ||
| 408 | 408 | { .compatible = "qcom,sc7180-smmu-500" }, |
| 409 | 409 | { .compatible = "qcom,sc7280-smmu-500" }, |
| 410 | 410 | { .compatible = "qcom,sc8180x-smmu-500" }, |
| 411 | + { .compatible = "qcom,sc8280xp-smmu-500" }, | |
| 411 | 412 | { .compatible = "qcom,sdm630-smmu-v2" }, |
| 412 | 413 | { .compatible = "qcom,sdm845-smmu-500" }, |
| 413 | 414 | { .compatible = "qcom,sm6125-smmu-500" }, |
| @@ -1574,6 +1574,9 @@ static int arm_smmu_def_domain_type(struct device *dev) · 1573 unmodified lines | ||
| 1574 | 1574 | struct arm_smmu_master_cfg *cfg = dev_iommu_priv_get(dev); |
| 1575 | 1575 | const struct arm_smmu_impl *impl = cfg->smmu->impl; |
| 1576 | 1576 | |
| 1577 | + if (using_legacy_binding) | |
| 1578 | + return IOMMU_DOMAIN_IDENTITY; | |
| 1579 | + | |
| 1577 | 1580 | if (impl && impl->def_domain_type) |
| 1578 | 1581 | return impl->def_domain_type(dev); |
| 1579 | 1582 | |
| @@ -2092,11 +2095,10 @@ static int arm_smmu_device_probe(struct platform_device *pdev) · 512 unmodified lines | ||
| 2092 | 2095 | if (err) |
| 2093 | 2096 | return err; |
| 2094 | 2097 | |
| 2095 | − res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | |
| 2096 | − ioaddr = res->start; | |
| 2097 | − smmu->base = devm_ioremap_resource(dev, res); | |
| 2098 | + smmu->base = devm_platform_get_and_ioremap_resource(pdev, 0, &res); | |
| 2098 | 2099 | if (IS_ERR(smmu->base)) |
| 2099 | 2100 | return PTR_ERR(smmu->base); |
| 2101 | + ioaddr = res->start; | |
| 2100 | 2102 | /* |
| 2101 | 2103 | * The resource size should effectively match the value of SMMU_TOP; |
| 2102 | 2104 | * stash that temporarily until we know PAGESIZE to validate it with. |
| @@ -20,6 +20,7 @@ · 19 unmodified lines | ||
| 20 | 20 | #include <linux/iommu.h> |
| 21 | 21 | #include <linux/iova.h> |
| 22 | 22 | #include <linux/irq.h> |
| 23 | +#include <linux/list_sort.h> | |
| 23 | 24 | #include <linux/mm.h> |
| 24 | 25 | #include <linux/mutex.h> |
| 25 | 26 | #include <linux/pci.h> |
| @@ -414,6 +415,15 @@ static int cookie_init_hw_msi_region(struct iommu_dma_cookie *cookie, · 388 unmodified lines | ||
| 414 | 415 | return 0; |
| 415 | 416 | } |
| 416 | 417 | |
| 418 | +static int iommu_dma_ranges_sort(void *priv, const struct list_head *a, | |
| 419 | + const struct list_head *b) | |
| 420 | +{ | |
| 421 | + struct resource_entry *res_a = list_entry(a, typeof(*res_a), node); | |
| 422 | + struct resource_entry *res_b = list_entry(b, typeof(*res_b), node); | |
| 423 | + | |
| 424 | + return res_a->res->start > res_b->res->start; | |
| 425 | +} | |
| 426 | + | |
| 417 | 427 | static int iova_reserve_pci_windows(struct pci_dev *dev, |
| 418 | 428 | struct iova_domain *iovad) |
| 419 | 429 | { |
| @@ -432,6 +442,7 @@ static int iova_reserve_pci_windows(struct pci_dev *dev, · 12 unmodified lines | ||
| 432 | 442 | } |
| 433 | 443 | |
| 434 | 444 | /* Get reserved DMA windows from host bridge */ |
| 445 | + list_sort(NULL, &bridge->dma_ranges, iommu_dma_ranges_sort); | |
| 435 | 446 | resource_list_for_each_entry(window, &bridge->dma_ranges) { |
| 436 | 447 | end = window->res->start - window->offset; |
| 437 | 448 | resv_iova: |
| @@ -440,7 +451,7 @@ resv_iova: · 2 unmodified lines | ||
| 440 | 451 | hi = iova_pfn(iovad, end); |
| 441 | 452 | reserve_iova(iovad, lo, hi); |
| 442 | 453 | } else if (end < start) { |
| 443 | − /* dma_ranges list should be sorted */ | |
| 454 | + /* DMA ranges should be non-overlapping */ | |
| 444 | 455 | dev_err(&dev->dev, |
| 445 | 456 | "Failed to reserve IOVA [%pa-%pa]\n", |
| 446 | 457 | &start, &end); |
| @@ -776,6 +787,7 @@ static struct page **__iommu_dma_alloc_noncontiguous(struct device *dev, · 329 unmodified lines | ||
| 776 | 787 | unsigned int count, min_size, alloc_sizes = domain->pgsize_bitmap; |
| 777 | 788 | struct page **pages; |
| 778 | 789 | dma_addr_t iova; |
| 790 | + ssize_t ret; | |
| 779 | 791 | |
| 780 | 792 | if (static_branch_unlikely(&iommu_deferred_attach_enabled) && |
| 781 | 793 | iommu_deferred_attach(dev, domain)) |
| @@ -813,8 +825,8 @@ static struct page **__iommu_dma_alloc_noncontiguous(struct device *dev, · 31 unmodified lines | ||
| 813 | 825 | arch_dma_prep_coherent(sg_page(sg), sg->length); |
| 814 | 826 | } |
| 815 | 827 | |
| 816 | − if (iommu_map_sg_atomic(domain, iova, sgt->sgl, sgt->orig_nents, ioprot) | |
| 817 | − < size) | |
| 828 | + ret = iommu_map_sg_atomic(domain, iova, sgt->sgl, sgt->orig_nents, ioprot); | |
| 829 | + if (ret < 0 || ret < size) | |
| 818 | 830 | goto out_free_sg; |
| 819 | 831 | |
| 820 | 832 | sgt->sgl->dma_address = iova; |
| @@ -971,6 +983,11 @@ static dma_addr_t iommu_dma_map_page(struct device *dev, struct page *page, · 150 unmodified lines | ||
| 971 | 983 | void *padding_start; |
| 972 | 984 | size_t padding_size, aligned_size; |
| 973 | 985 | |
| 986 | + if (!is_swiotlb_active(dev)) { | |
| 987 | + dev_warn_once(dev, "DMA bounce buffers are inactive, unable to map unaligned transaction.\n"); | |
| 988 | + return DMA_MAPPING_ERROR; | |
| 989 | + } | |
| 990 | + | |
| 974 | 991 | aligned_size = iova_align(iovad, size); |
| 975 | 992 | phys = swiotlb_tbl_map_single(dev, phys, size, aligned_size, |
| 976 | 993 | iova_mask(iovad), dir, attrs); |
| @@ -1209,7 +1226,7 @@ static int iommu_dma_map_sg(struct device *dev, struct scatterlist *sg, · 232 unmodified lines | ||
| 1209 | 1226 | * implementation - it knows better than we do. |
| 1210 | 1227 | */ |
| 1211 | 1228 | ret = iommu_map_sg_atomic(domain, iova, sg, nents, prot); |
| 1212 | − if (ret < iova_len) | |
| 1229 | + if (ret < 0 || ret < iova_len) | |
| 1213 | 1230 | goto out_free_iova; |
| 1214 | 1231 | |
| 1215 | 1232 | return __finalise_sg(dev, sg, nents, iova); |
| @@ -11,6 +11,9 @@ · 10 unmodified lines | ||
| 11 | 11 | #include <linux/fsl/guts.h> |
| 12 | 12 | #include <linux/interrupt.h> |
| 13 | 13 | #include <linux/genalloc.h> |
| 14 | +#include <linux/of_address.h> | |
| 15 | +#include <linux/of_irq.h> | |
| 16 | +#include <linux/platform_device.h> | |
| 14 | 17 | |
| 15 | 18 | #include <asm/mpc85xx.h> |
| 16 | 19 | |
| @@ -9,6 +9,7 @@ · 8 unmodified lines | ||
| 9 | 9 | |
| 10 | 10 | #include "fsl_pamu_domain.h" |
| 11 | 11 | |
| 12 | +#include <linux/platform_device.h> | |
| 12 | 13 | #include <sysdev/fsl_pci.h> |
| 13 | 14 | |
| 14 | 15 | /* |
| @@ -533,33 +533,6 @@ static void domain_update_iommu_coherency(struct dmar_domain *domain) · 532 unmodified lines | ||
| 533 | 533 | rcu_read_unlock(); |
| 534 | 534 | } |
| 535 | 535 | |
| 536 | −static bool domain_update_iommu_snooping(struct intel_iommu *skip) | |
| 537 | −{ | |
| 538 | − struct dmar_drhd_unit *drhd; | |
| 539 | − struct intel_iommu *iommu; | |
| 540 | − bool ret = true; | |
| 541 | − | |
| 542 | − rcu_read_lock(); | |
| 543 | − for_each_active_iommu(iommu, drhd) { | |
| 544 | − if (iommu != skip) { | |
| 545 | − /* | |
| 546 | − * If the hardware is operating in the scalable mode, | |
| 547 | − * the snooping control is always supported since we | |
| 548 | − * always set PASID-table-entry.PGSNP bit if the domain | |
| 549 | − * is managed outside (UNMANAGED). | |
| 550 | − */ | |
| 551 | − if (!sm_supported(iommu) && | |
| 552 | − !ecap_sc_support(iommu->ecap)) { | |
| 553 | − ret = false; | |
| 554 | − break; | |
| 555 | − } | |
| 556 | − } | |
| 557 | − } | |
| 558 | − rcu_read_unlock(); | |
| 559 | − | |
| 560 | − return ret; | |
| 561 | −} | |
| 562 | − | |
| 563 | 536 | static int domain_update_iommu_superpage(struct dmar_domain *domain, |
| 564 | 537 | struct intel_iommu *skip) |
| 565 | 538 | { |
| @@ -641,7 +614,6 @@ static unsigned long domain_super_pgsize_bitmap(struct dmar_domain *domain) · 75 unmodified lines | ||
| 641 | 614 | static void domain_update_iommu_cap(struct dmar_domain *domain) |
| 642 | 615 | { |
| 643 | 616 | domain_update_iommu_coherency(domain); |
| 644 | − domain->iommu_snooping = domain_update_iommu_snooping(NULL); | |
| 645 | 617 | domain->iommu_superpage = domain_update_iommu_superpage(domain, NULL); |
| 646 | 618 | |
| 647 | 619 | /* |
| @@ -1588,7 +1560,8 @@ static void iommu_flush_iotlb_psi(struct intel_iommu *iommu, · 940 unmodified lines | ||
| 1588 | 1560 | unsigned long pfn, unsigned int pages, |
| 1589 | 1561 | int ih, int map) |
| 1590 | 1562 | { |
| 1591 | − unsigned int mask = ilog2(__roundup_pow_of_two(pages)); | |
| 1563 | + unsigned int aligned_pages = __roundup_pow_of_two(pages); | |
| 1564 | + unsigned int mask = ilog2(aligned_pages); | |
| 1592 | 1565 | uint64_t addr = (uint64_t)pfn << VTD_PAGE_SHIFT; |
| 1593 | 1566 | u16 did = domain->iommu_did[iommu->seq_id]; |
| 1594 | 1567 | |
| @@ -1600,10 +1573,30 @@ static void iommu_flush_iotlb_psi(struct intel_iommu *iommu, · 5 unmodified lines | ||
| 1600 | 1573 | if (domain_use_first_level(domain)) { |
| 1601 | 1574 | qi_flush_piotlb(iommu, did, PASID_RID2PASID, addr, pages, ih); |
| 1602 | 1575 | } else { |
| 1576 | + unsigned long bitmask = aligned_pages - 1; | |
| 1577 | + | |
| 1578 | + /* | |
| 1579 | + * PSI masks the low order bits of the base address. If the | |
| 1580 | + * address isn't aligned to the mask, then compute a mask value | |
| 1581 | + * needed to ensure the target range is flushed. | |
| 1582 | + */ | |
| 1583 | + if (unlikely(bitmask & pfn)) { | |
| 1584 | + unsigned long end_pfn = pfn + pages - 1, shared_bits; | |
| 1585 | + | |
| 1586 | + /* | |
| 1587 | + * Since end_pfn <= pfn + bitmask, the only way bits | |
| 1588 | + * higher than bitmask can differ in pfn and end_pfn is | |
| 1589 | + * by carrying. This means after masking out bitmask, | |
| 1590 | + * high bits starting with the first set bit in | |
| 1591 | + * shared_bits are all equal in both pfn and end_pfn. | |
| 1592 | + */ | |
| 1593 | + shared_bits = ~(pfn ^ end_pfn) & ~bitmask; | |
| 1594 | + mask = shared_bits ? __ffs(shared_bits) : BITS_PER_LONG; | |
| 1595 | + } | |
| 1596 | + | |
| 1603 | 1597 | /* |
| 1604 | 1598 | * Fallback to domain selective flush if no PSI support or |
| 1605 | − * the size is too big. PSI requires page size to be 2 ^ x, | |
| 1606 | − * and the base address is naturally aligned to the size. | |
| 1599 | + * the size is too big. | |
| 1607 | 1600 | */ |
| 1608 | 1601 | if (!cap_pgsel_inv(iommu->cap) || |
| 1609 | 1602 | mask > cap_max_amask_val(iommu->cap)) |
| @@ -2439,7 +2432,7 @@ static int domain_setup_first_level(struct intel_iommu *iommu, · 829 unmodified lines | ||
| 2439 | 2432 | if (level == 5) |
| 2440 | 2433 | flags |= PASID_FLAG_FL5LP; |
| 2441 | 2434 | |
| 2442 | − if (domain->domain.type == IOMMU_DOMAIN_UNMANAGED) | |
| 2435 | + if (domain->force_snooping) | |
| 2443 | 2436 | flags |= PASID_FLAG_PAGE_SNOOP; |
| 2444 | 2437 | |
| 2445 | 2438 | return intel_pasid_setup_first_level(iommu, dev, (pgd_t *)pgd, pasid, |
| @@ -2453,64 +2446,6 @@ static bool dev_is_real_dma_subdevice(struct device *dev) · 7 unmodified lines | ||
| 2453 | 2446 | pci_real_dma_dev(to_pci_dev(dev)) != to_pci_dev(dev); |
| 2454 | 2447 | } |
| 2455 | 2448 | |
| 2456 | −static struct dmar_domain *dmar_insert_one_dev_info(struct intel_iommu *iommu, | |
| 2457 | − int bus, int devfn, | |
| 2458 | − struct device *dev, | |
| 2459 | − struct dmar_domain *domain) | |
| 2460 | −{ | |
| 2461 | − struct device_domain_info *info = dev_iommu_priv_get(dev); | |
| 2462 | − unsigned long flags; | |
| 2463 | − int ret; | |
| 2464 | − | |
| 2465 | − spin_lock_irqsave(&device_domain_lock, flags); | |
| 2466 | − info->domain = domain; | |
| 2467 | − spin_lock(&iommu->lock); | |
| 2468 | − ret = domain_attach_iommu(domain, iommu); | |
| 2469 | − spin_unlock(&iommu->lock); | |
| 2470 | − if (ret) { | |
| 2471 | − spin_unlock_irqrestore(&device_domain_lock, flags); | |
| 2472 | − return NULL; | |
| 2473 | − } | |
| 2474 | − list_add(&info->link, &domain->devices); | |
| 2475 | − spin_unlock_irqrestore(&device_domain_lock, flags); | |
| 2476 | − | |
| 2477 | − /* PASID table is mandatory for a PCI device in scalable mode. */ | |
| 2478 | − if (sm_supported(iommu) && !dev_is_real_dma_subdevice(dev)) { | |
| 2479 | − ret = intel_pasid_alloc_table(dev); | |
| 2480 | − if (ret) { | |
| 2481 | − dev_err(dev, "PASID table allocation failed\n"); | |
| 2482 | − dmar_remove_one_dev_info(dev); | |
| 2483 | − return NULL; | |
| 2484 | − } | |
| 2485 | − | |
| 2486 | − /* Setup the PASID entry for requests without PASID: */ | |
| 2487 | − spin_lock_irqsave(&iommu->lock, flags); | |
| 2488 | − if (hw_pass_through && domain_type_is_si(domain)) | |
| 2489 | − ret = intel_pasid_setup_pass_through(iommu, domain, | |
| 2490 | − dev, PASID_RID2PASID); | |
| 2491 | − else if (domain_use_first_level(domain)) | |
| 2492 | − ret = domain_setup_first_level(iommu, domain, dev, | |
| 2493 | − PASID_RID2PASID); | |
| 2494 | − else | |
| 2495 | − ret = intel_pasid_setup_second_level(iommu, domain, | |
| 2496 | − dev, PASID_RID2PASID); | |
| 2497 | − spin_unlock_irqrestore(&iommu->lock, flags); | |
| 2498 | − if (ret) { | |
| 2499 | − dev_err(dev, "Setup RID2PASID failed\n"); | |
| 2500 | − dmar_remove_one_dev_info(dev); | |
| 2501 | − return NULL; | |
| 2502 | − } | |
| 2503 | − } | |
| 2504 | − | |
| 2505 | − if (dev && domain_context_mapping(domain, dev)) { | |
| 2506 | − dev_err(dev, "Domain context map failed\n"); | |
| 2507 | − dmar_remove_one_dev_info(dev); | |
| 2508 | − return NULL; | |
| 2509 | − } | |
| 2510 | − | |
| 2511 | − return domain; | |
| 2512 | −} | |
| 2513 | − | |
| 2514 | 2449 | static int iommu_domain_identity_map(struct dmar_domain *domain, |
| 2515 | 2450 | unsigned long first_vpfn, |
| 2516 | 2451 | unsigned long last_vpfn) |
| @@ -2586,17 +2521,62 @@ static int __init si_domain_init(int hw) · 69 unmodified lines | ||
| 2586 | 2521 | |
| 2587 | 2522 | static int domain_add_dev_info(struct dmar_domain *domain, struct device *dev) |
| 2588 | 2523 | { |
| 2589 | − struct dmar_domain *ndomain; | |
| 2524 | + struct device_domain_info *info = dev_iommu_priv_get(dev); | |
| 2590 | 2525 | struct intel_iommu *iommu; |
| 2526 | + unsigned long flags; | |
| 2591 | 2527 | u8 bus, devfn; |
| 2528 | + int ret; | |
| 2592 | 2529 | |
| 2593 | 2530 | iommu = device_to_iommu(dev, &bus, &devfn); |
| 2594 | 2531 | if (!iommu) |
| 2595 | 2532 | return -ENODEV; |
| 2596 | 2533 | |
| 2597 | − ndomain = dmar_insert_one_dev_info(iommu, bus, devfn, dev, domain); | |
| 2598 | − if (ndomain != domain) | |
| 2599 | − return -EBUSY; | |
| 2534 | + spin_lock_irqsave(&device_domain_lock, flags); | |
| 2535 | + info->domain = domain; | |
| 2536 | + spin_lock(&iommu->lock); | |
| 2537 | + ret = domain_attach_iommu(domain, iommu); | |
| 2538 | + spin_unlock(&iommu->lock); | |
| 2539 | + if (ret) { | |
| 2540 | + spin_unlock_irqrestore(&device_domain_lock, flags); | |
| 2541 | + return ret; | |
| 2542 | + } | |
| 2543 | + list_add(&info->link, &domain->devices); | |
| 2544 | + spin_unlock_irqrestore(&device_domain_lock, flags); | |
| 2545 | + | |
| 2546 | + /* PASID table is mandatory for a PCI device in scalable mode. */ | |
| 2547 | + if (sm_supported(iommu) && !dev_is_real_dma_subdevice(dev)) { | |
| 2548 | + ret = intel_pasid_alloc_table(dev); | |
| 2549 | + if (ret) { | |
| 2550 | + dev_err(dev, "PASID table allocation failed\n"); | |
| 2551 | + dmar_remove_one_dev_info(dev); | |
| 2552 | + return ret; | |
| 2553 | + } | |
| 2554 | + | |
| 2555 | + /* Setup the PASID entry for requests without PASID: */ | |
| 2556 | + spin_lock_irqsave(&iommu->lock, flags); | |
| 2557 | + if (hw_pass_through && domain_type_is_si(domain)) | |
| 2558 | + ret = intel_pasid_setup_pass_through(iommu, domain, | |
| 2559 | + dev, PASID_RID2PASID); | |
| 2560 | + else if (domain_use_first_level(domain)) | |
| 2561 | + ret = domain_setup_first_level(iommu, domain, dev, | |
| 2562 | + PASID_RID2PASID); | |
| 2563 | + else | |
| 2564 | + ret = intel_pasid_setup_second_level(iommu, domain, | |
| 2565 | + dev, PASID_RID2PASID); | |
| 2566 | + spin_unlock_irqrestore(&iommu->lock, flags); | |
| 2567 | + if (ret) { | |
| 2568 | + dev_err(dev, "Setup RID2PASID failed\n"); | |
| 2569 | + dmar_remove_one_dev_info(dev); | |
| 2570 | + return ret; | |
| 2571 | + } | |
| 2572 | + } | |
| 2573 | + | |
| 2574 | + ret = domain_context_mapping(domain, dev); | |
| 2575 | + if (ret) { | |
| 2576 | + dev_err(dev, "Domain context map failed\n"); | |
| 2577 | + dmar_remove_one_dev_info(dev); | |
| 2578 | + return ret; | |
| 2579 | + } | |
| 2600 | 2580 | |
| 2601 | 2581 | return 0; |
| 2602 | 2582 | } |
| @@ -3586,12 +3566,7 @@ static int intel_iommu_add(struct dmar_drhd_unit *dmaru) · 983 unmodified lines | ||
| 3586 | 3566 | iommu->name); |
| 3587 | 3567 | return -ENXIO; |
| 3588 | 3568 | } |
| 3589 | − if (!ecap_sc_support(iommu->ecap) && | |
| 3590 | − domain_update_iommu_snooping(iommu)) { | |
| 3591 | − pr_warn("%s: Doesn't support snooping.\n", | |
| 3592 | − iommu->name); | |
| 3593 | − return -ENXIO; | |
| 3594 | − } | |
| 3569 | + | |
| 3595 | 3570 | sp = domain_update_iommu_superpage(NULL, iommu) - 1; |
| 3596 | 3571 | if (sp >= 0 && !(cap_super_page_val(iommu->cap) & (1 << sp))) { |
| 3597 | 3572 | pr_warn("%s: Doesn't support large page.\n", |
| @@ -4283,7 +4258,6 @@ static int md_domain_init(struct dmar_domain *domain, int guest_width) · 685 unmodified lines | ||
| 4283 | 4258 | domain->agaw = width_to_agaw(adjust_width); |
| 4284 | 4259 | |
| 4285 | 4260 | domain->iommu_coherency = false; |
| 4286 | − domain->iommu_snooping = false; | |
| 4287 | 4261 | domain->iommu_superpage = 0; |
| 4288 | 4262 | domain->max_addr = 0; |
| 4289 | 4263 | |
| @@ -4348,6 +4322,9 @@ static int prepare_domain_attach_device(struct iommu_domain *domain, · 58 unmodified lines | ||
| 4348 | 4322 | if (!iommu) |
| 4349 | 4323 | return -ENODEV; |
| 4350 | 4324 | |
| 4325 | + if (dmar_domain->force_snooping && !ecap_sc_support(iommu->ecap)) | |
| 4326 | + return -EOPNOTSUPP; | |
| 4327 | + | |
| 4351 | 4328 | /* check if this iommu agaw is sufficient for max mapped address */ |
| 4352 | 4329 | addr_width = agaw_to_width(iommu->agaw); |
| 4353 | 4330 | if (addr_width > cap_mgaw(iommu->cap)) |
| @@ -4422,7 +4399,7 @@ static int intel_iommu_map(struct iommu_domain *domain, · 68 unmodified lines | ||
| 4422 | 4399 | prot |= DMA_PTE_READ; |
| 4423 | 4400 | if (iommu_prot & IOMMU_WRITE) |
| 4424 | 4401 | prot |= DMA_PTE_WRITE; |
| 4425 | − if ((iommu_prot & IOMMU_CACHE) && dmar_domain->iommu_snooping) | |
| 4402 | + if (dmar_domain->set_pte_snp) | |
| 4426 | 4403 | prot |= DMA_PTE_SNP; |
| 4427 | 4404 | |
| 4428 | 4405 | max_addr = iova + size; |
| @@ -4545,12 +4522,71 @@ static phys_addr_t intel_iommu_iova_to_phys(struct iommu_domain *domain, · 116 unmodified lines | ||
| 4545 | 4522 | return phys; |
| 4546 | 4523 | } |
| 4547 | 4524 | |
| 4525 | +static bool domain_support_force_snooping(struct dmar_domain *domain) | |
| 4526 | +{ | |
| 4527 | + struct device_domain_info *info; | |
| 4528 | + bool support = true; | |
| 4529 | + | |
| 4530 | + assert_spin_locked(&device_domain_lock); | |
| 4531 | + list_for_each_entry(info, &domain->devices, link) { | |
| 4532 | + if (!ecap_sc_support(info->iommu->ecap)) { | |
| 4533 | + support = false; | |
| 4534 | + break; | |
| 4535 | + } | |
| 4536 | + } | |
| 4537 | + | |
| 4538 | + return support; | |
| 4539 | +} | |
| 4540 | + | |
| 4541 | +static void domain_set_force_snooping(struct dmar_domain *domain) | |
| 4542 | +{ | |
| 4543 | + struct device_domain_info *info; | |
| 4544 | + | |
| 4545 | + assert_spin_locked(&device_domain_lock); | |
| 4546 | + | |
| 4547 | + /* | |
| 4548 | + * Second level page table supports per-PTE snoop control. The | |
| 4549 | + * iommu_map() interface will handle this by setting SNP bit. | |
| 4550 | + */ | |
| 4551 | + if (!domain_use_first_level(domain)) { | |
| 4552 | + domain->set_pte_snp = true; | |
| 4553 | + return; | |
| 4554 | + } | |
| 4555 | + | |
| 4556 | + list_for_each_entry(info, &domain->devices, link) | |
| 4557 | + intel_pasid_setup_page_snoop_control(info->iommu, info->dev, | |
| 4558 | + PASID_RID2PASID); | |
| 4559 | +} | |
| 4560 | + | |
| 4561 | +static bool intel_iommu_enforce_cache_coherency(struct iommu_domain *domain) | |
| 4562 | +{ | |
| 4563 | + struct dmar_domain *dmar_domain = to_dmar_domain(domain); | |
| 4564 | + unsigned long flags; | |
| 4565 | + | |
| 4566 | + if (dmar_domain->force_snooping) | |
| 4567 | + return true; | |
| 4568 | + | |
| 4569 | + spin_lock_irqsave(&device_domain_lock, flags); | |
| 4570 | + if (!domain_support_force_snooping(dmar_domain)) { | |
| 4571 | + spin_unlock_irqrestore(&device_domain_lock, flags); | |
| 4572 | + return false; | |
| 4573 | + } | |
| 4574 | + | |
| 4575 | + domain_set_force_snooping(dmar_domain); | |
| 4576 | + dmar_domain->force_snooping = true; | |
| 4577 | + spin_unlock_irqrestore(&device_domain_lock, flags); | |
| 4578 | + | |
| 4579 | + return true; | |
| 4580 | +} | |
| 4581 | + | |
| 4548 | 4582 | static bool intel_iommu_capable(enum iommu_cap cap) |
| 4549 | 4583 | { |
| 4550 | 4584 | if (cap == IOMMU_CAP_CACHE_COHERENCY) |
| 4551 | − return domain_update_iommu_snooping(NULL); | |
| 4585 | + return true; | |
| 4552 | 4586 | if (cap == IOMMU_CAP_INTR_REMAP) |
| 4553 | 4587 | return irq_remapping_enabled == 1; |
| 4588 | + if (cap == IOMMU_CAP_PRE_BOOT_PROTECTION) | |
| 4589 | + return dmar_platform_optin(); | |
| 4554 | 4590 | |
| 4555 | 4591 | return false; |
| 4556 | 4592 | } |
| @@ -4898,6 +4934,7 @@ const struct iommu_ops intel_iommu_ops = { · 341 unmodified lines | ||
| 4898 | 4934 | .iotlb_sync = intel_iommu_tlb_sync, |
| 4899 | 4935 | .iova_to_phys = intel_iommu_iova_to_phys, |
| 4900 | 4936 | .free = intel_iommu_domain_free, |
| 4937 | + .enforce_cache_coherency = intel_iommu_enforce_cache_coherency, | |
| 4901 | 4938 | } |
| 4902 | 4939 | }; |
| 4903 | 4940 | |
| @@ -710,9 +710,6 @@ int intel_pasid_setup_second_level(struct intel_iommu *iommu, · 709 unmodified lines | ||
| 710 | 710 | pasid_set_fault_enable(pte); |
| 711 | 711 | pasid_set_page_snoop(pte, !!ecap_smpwc(iommu->ecap)); |
| 712 | 712 | |
| 713 | − if (domain->domain.type == IOMMU_DOMAIN_UNMANAGED) | |
| 714 | − pasid_set_pgsnp(pte); | |
| 715 | − | |
| 716 | 713 | /* |
| 717 | 714 | * Since it is a second level only translation setup, we should |
| 718 | 715 | * set SRE bit as well (addresses are expected to be GPAs). |
| @@ -762,3 +759,45 @@ int intel_pasid_setup_pass_through(struct intel_iommu *iommu, · 43 unmodified lines | ||
| 762 | 759 | |
| 763 | 760 | return 0; |
| 764 | 761 | } |
| 762 | + | |
| 763 | +/* | |
| 764 | + * Set the page snoop control for a pasid entry which has been set up. | |
| 765 | + */ | |
| 766 | +void intel_pasid_setup_page_snoop_control(struct intel_iommu *iommu, | |
| 767 | + struct device *dev, u32 pasid) | |
| 768 | +{ | |
| 769 | + struct pasid_entry *pte; | |
| 770 | + u16 did; | |
| 771 | + | |
| 772 | + spin_lock(&iommu->lock); | |
| 773 | + pte = intel_pasid_get_entry(dev, pasid); | |
| 774 | + if (WARN_ON(!pte || !pasid_pte_is_present(pte))) { | |
| 775 | + spin_unlock(&iommu->lock); | |
| 776 | + return; | |
| 777 | + } | |
| 778 | + | |
| 779 | + pasid_set_pgsnp(pte); | |
| 780 | + did = pasid_get_domain_id(pte); | |
| 781 | + spin_unlock(&iommu->lock); | |
| 782 | + | |
| 783 | + if (!ecap_coherent(iommu->ecap)) | |
| 784 | + clflush_cache_range(pte, sizeof(*pte)); | |
| 785 | + | |
| 786 | + /* | |
| 787 | + * VT-d spec 3.4 table23 states guides for cache invalidation: | |
| 788 | + * | |
| 789 | + * - PASID-selective-within-Domain PASID-cache invalidation | |
| 790 | + * - PASID-selective PASID-based IOTLB invalidation | |
| 791 | + * - If (pasid is RID_PASID) | |
| 792 | + * - Global Device-TLB invalidation to affected functions | |
| 793 | + * Else | |
| 794 | + * - PASID-based Device-TLB invalidation (with S=1 and | |
| 795 | + * Addr[63:12]=0x7FFFFFFF_FFFFF) to affected functions | |
| 796 | + */ | |
| 797 | + pasid_cache_invalidation_with_pasid(iommu, did, pasid); | |
| 798 | + qi_flush_piotlb(iommu, did, pasid, 0, -1, 0); | |
| 799 | + | |
| 800 | + /* Device IOTLB doesn't need to be flushed in caching mode. */ | |
| 801 | + if (!cap_caching_mode(iommu->cap)) | |
| 802 | + devtlb_invalidation_with_pasid(iommu, dev, pasid); | |
| 803 | +} | |
| @@ -123,4 +123,6 @@ void intel_pasid_tear_down_entry(struct intel_iommu *iommu, · 122 unmodified lines | ||
| 123 | 123 | bool fault_ignore); |
| 124 | 124 | int vcmd_alloc_pasid(struct intel_iommu *iommu, u32 *pasid); |
| 125 | 125 | void vcmd_free_pasid(struct intel_iommu *iommu, u32 pasid); |
| 126 | +void intel_pasid_setup_page_snoop_control(struct intel_iommu *iommu, | |
| 127 | + struct device *dev, u32 pasid); | |
| 126 | 128 | #endif /* __INTEL_PASID_H */ |
| @@ -757,6 +757,10 @@ bad_req: · 756 unmodified lines | ||
| 757 | 757 | goto bad_req; |
| 758 | 758 | } |
| 759 | 759 | |
| 760 | + /* Drop Stop Marker message. No need for a response. */ | |
| 761 | + if (unlikely(req->lpig && !req->rd_req && !req->wr_req)) | |
| 762 | + goto prq_advance; | |
| 763 | + | |
| 760 | 764 | if (!svm || svm->pasid != req->pasid) { |
| 761 | 765 | /* |
| 762 | 766 | * It can't go away, because the driver is not permitted |
| @@ -18,7 +18,6 @@ · 17 unmodified lines | ||
| 18 | 18 | #include <linux/errno.h> |
| 19 | 19 | #include <linux/iommu.h> |
| 20 | 20 | #include <linux/idr.h> |
| 21 | −#include <linux/notifier.h> | |
| 22 | 21 | #include <linux/err.h> |
| 23 | 22 | #include <linux/pci.h> |
| 24 | 23 | #include <linux/bitops.h> |
| @@ -40,14 +39,16 @@ struct iommu_group { · 15 unmodified lines | ||
| 40 | 39 | struct kobject *devices_kobj; |
| 41 | 40 | struct list_head devices; |
| 42 | 41 | struct mutex mutex; |
| 43 | − struct blocking_notifier_head notifier; | |
| 44 | 42 | void *iommu_data; |
| 45 | 43 | void (*iommu_data_release)(void *iommu_data); |
| 46 | 44 | char *name; |
| 47 | 45 | int id; |
| 48 | 46 | struct iommu_domain *default_domain; |
| 47 | + struct iommu_domain *blocking_domain; | |
| 49 | 48 | struct iommu_domain *domain; |
| 50 | 49 | struct list_head entry; |
| 50 | + unsigned int owner_cnt; | |
| 51 | + void *owner; | |
| 51 | 52 | }; |
| 52 | 53 | |
| 53 | 54 | struct group_device { |
| @@ -82,8 +83,8 @@ static int __iommu_attach_device(struct iommu_domain *domain, · 28 unmodified lines | ||
| 82 | 83 | struct device *dev); |
| 83 | 84 | static int __iommu_attach_group(struct iommu_domain *domain, |
| 84 | 85 | struct iommu_group *group); |
| 85 | −static void __iommu_detach_group(struct iommu_domain *domain, | |
| 86 | − struct iommu_group *group); | |
| 86 | +static int __iommu_group_set_domain(struct iommu_group *group, | |
| 87 | + struct iommu_domain *new_domain); | |
| 87 | 88 | static int iommu_create_device_direct_mappings(struct iommu_group *group, |
| 88 | 89 | struct device *dev); |
| 89 | 90 | static struct iommu_group *iommu_group_get_for_dev(struct device *dev); |
| @@ -294,7 +295,11 @@ int iommu_probe_device(struct device *dev) · 204 unmodified lines | ||
| 294 | 295 | mutex_lock(&group->mutex); |
| 295 | 296 | iommu_alloc_default_domain(group, dev); |
| 296 | 297 | |
| 297 | − if (group->default_domain) { | |
| 298 | + /* | |
| 299 | + * If device joined an existing group which has been claimed, don't | |
| 300 | + * attach the default domain. | |
| 301 | + */ | |
| 302 | + if (group->default_domain && !group->owner) { | |
| 298 | 303 | ret = __iommu_attach_device(group->default_domain, dev); |
| 299 | 304 | if (ret) { |
| 300 | 305 | mutex_unlock(&group->mutex); |
| @@ -506,6 +511,13 @@ int iommu_get_group_resv_regions(struct iommu_group *group, · 205 unmodified lines | ||
| 506 | 511 | list_for_each_entry(device, &group->devices, list) { |
| 507 | 512 | struct list_head dev_resv_regions; |
| 508 | 513 | |
| 514 | + /* | |
| 515 | + * Non-API groups still expose reserved_regions in sysfs, | |
| 516 | + * so filter out calls that get here that way. | |
| 517 | + */ | |
| 518 | + if (!device->dev->iommu) | |
| 519 | + break; | |
| 520 | + | |
| 509 | 521 | INIT_LIST_HEAD(&dev_resv_regions); |
| 510 | 522 | iommu_get_resv_regions(device->dev, &dev_resv_regions); |
| 511 | 523 | ret = iommu_insert_device_resv_regions(&dev_resv_regions, head); |
| @@ -592,6 +604,8 @@ static void iommu_group_release(struct kobject *kobj) · 80 unmodified lines | ||
| 592 | 604 | |
| 593 | 605 | if (group->default_domain) |
| 594 | 606 | iommu_domain_free(group->default_domain); |
| 607 | + if (group->blocking_domain) | |
| 608 | + iommu_domain_free(group->blocking_domain); | |
| 595 | 609 | |
| 596 | 610 | kfree(group->name); |
| 597 | 611 | kfree(group); |
| @@ -626,7 +640,6 @@ struct iommu_group *iommu_group_alloc(void) · 28 unmodified lines | ||
| 626 | 640 | mutex_init(&group->mutex); |
| 627 | 641 | INIT_LIST_HEAD(&group->devices); |
| 628 | 642 | INIT_LIST_HEAD(&group->entry); |
| 629 | − BLOCKING_INIT_NOTIFIER_HEAD(&group->notifier); | |
| 630 | 643 | |
| 631 | 644 | ret = ida_simple_get(&iommu_group_ida, 0, 0, GFP_KERNEL); |
| 632 | 645 | if (ret < 0) { |
| @@ -899,10 +912,6 @@ rename: · 266 unmodified lines | ||
| 899 | 912 | if (ret) |
| 900 | 913 | goto err_put_group; |
| 901 | 914 | |
| 902 | − /* Notify any listeners about change to group. */ | |
| 903 | − blocking_notifier_call_chain(&group->notifier, | |
| 904 | − IOMMU_GROUP_NOTIFY_ADD_DEVICE, dev); | |
| 905 | − | |
| 906 | 915 | trace_add_device_to_group(group->id, dev); |
| 907 | 916 | |
| 908 | 917 | dev_info(dev, "Adding to iommu group %d\n", group->id); |
| @@ -944,10 +953,6 @@ void iommu_group_remove_device(struct device *dev) · 35 unmodified lines | ||
| 944 | 953 | |
| 945 | 954 | dev_info(dev, "Removing from iommu group %d\n", group->id); |
| 946 | 955 | |
| 947 | − /* Pre-notify listeners that a device is being removed. */ | |
| 948 | − blocking_notifier_call_chain(&group->notifier, | |
| 949 | − IOMMU_GROUP_NOTIFY_DEL_DEVICE, dev); | |
| 950 | − | |
| 951 | 956 | mutex_lock(&group->mutex); |
| 952 | 957 | list_for_each_entry(tmp_device, &group->devices, list) { |
| 953 | 958 | if (tmp_device->dev == dev) { |
| @@ -1069,36 +1074,6 @@ void iommu_group_put(struct iommu_group *group) · 115 unmodified lines | ||
| 1069 | 1074 | } |
| 1070 | 1075 | EXPORT_SYMBOL_GPL(iommu_group_put); |
| 1071 | 1076 | |
| 1072 | −/** | |
| 1073 | − * iommu_group_register_notifier - Register a notifier for group changes | |
| 1074 | − * @group: the group to watch | |
| 1075 | − * @nb: notifier block to signal | |
| 1076 | − * | |
| 1077 | − * This function allows iommu group users to track changes in a group. | |
| 1078 | − * See include/linux/iommu.h for actions sent via this notifier. Caller | |
| 1079 | − * should hold a reference to the group throughout notifier registration. | |
| 1080 | − */ | |
| 1081 | −int iommu_group_register_notifier(struct iommu_group *group, | |
| 1082 | − struct notifier_block *nb) | |
| 1083 | −{ | |
| 1084 | − return blocking_notifier_chain_register(&group->notifier, nb); | |
| 1085 | −} | |
| 1086 | −EXPORT_SYMBOL_GPL(iommu_group_register_notifier); | |
| 1087 | − | |
| 1088 | −/** | |
| 1089 | − * iommu_group_unregister_notifier - Unregister a notifier | |
| 1090 | − * @group: the group to watch | |
| 1091 | − * @nb: notifier block to signal | |
| 1092 | − * | |
| 1093 | − * Unregister a previously registered group notifier block. | |
| 1094 | − */ | |
| 1095 | −int iommu_group_unregister_notifier(struct iommu_group *group, | |
| 1096 | − struct notifier_block *nb) | |
| 1097 | −{ | |
| 1098 | − return blocking_notifier_chain_unregister(&group->notifier, nb); | |
| 1099 | −} | |
| 1100 | −EXPORT_SYMBOL_GPL(iommu_group_unregister_notifier); | |
| 1101 | − | |
| 1102 | 1077 | /** |
| 1103 | 1078 | * iommu_register_device_fault_handler() - Register a device fault handler |
| 1104 | 1079 | * @dev: the device |
| @@ -1644,14 +1619,8 @@ static int remove_iommu_group(struct device *dev, void *data) · 539 unmodified lines | ||
| 1644 | 1619 | static int iommu_bus_notifier(struct notifier_block *nb, |
| 1645 | 1620 | unsigned long action, void *data) |
| 1646 | 1621 | { |
| 1647 | − unsigned long group_action = 0; | |
| 1648 | 1622 | struct device *dev = data; |
| 1649 | − struct iommu_group *group; | |
| 1650 | 1623 | |
| 1651 | − /* | |
| 1652 | − * ADD/DEL call into iommu driver ops if provided, which may | |
| 1653 | − * result in ADD/DEL notifiers to group->notifier | |
| 1654 | − */ | |
| 1655 | 1624 | if (action == BUS_NOTIFY_ADD_DEVICE) { |
| 1656 | 1625 | int ret; |
| 1657 | 1626 | |
| @@ -1662,34 +1631,6 @@ static int iommu_bus_notifier(struct notifier_block *nb, · 4 unmodified lines | ||
| 1662 | 1631 | return NOTIFY_OK; |
| 1663 | 1632 | } |
| 1664 | 1633 | |
| 1665 | − /* | |
| 1666 | − * Remaining BUS_NOTIFYs get filtered and republished to the | |
| 1667 | − * group, if anyone is listening | |
| 1668 | − */ | |
| 1669 | − group = iommu_group_get(dev); | |
| 1670 | − if (!group) | |
| 1671 | − return 0; | |
| 1672 | − | |
| 1673 | − switch (action) { | |
| 1674 | − case BUS_NOTIFY_BIND_DRIVER: | |
| 1675 | − group_action = IOMMU_GROUP_NOTIFY_BIND_DRIVER; | |
| 1676 | − break; | |
| 1677 | − case BUS_NOTIFY_BOUND_DRIVER: | |
| 1678 | − group_action = IOMMU_GROUP_NOTIFY_BOUND_DRIVER; | |
| 1679 | − break; | |
| 1680 | − case BUS_NOTIFY_UNBIND_DRIVER: | |
| 1681 | − group_action = IOMMU_GROUP_NOTIFY_UNBIND_DRIVER; | |
| 1682 | − break; | |
| 1683 | − case BUS_NOTIFY_UNBOUND_DRIVER: | |
| 1684 | − group_action = IOMMU_GROUP_NOTIFY_UNBOUND_DRIVER; | |
| 1685 | − break; | |
| 1686 | − } | |
| 1687 | − | |
| 1688 | − if (group_action) | |
| 1689 | − blocking_notifier_call_chain(&group->notifier, | |
| 1690 | − group_action, dev); | |
| 1691 | − | |
| 1692 | − iommu_group_put(group); | |
| 1693 | 1634 | return 0; |
| 1694 | 1635 | } |
| 1695 | 1636 | |
| @@ -1906,6 +1847,29 @@ bool iommu_present(struct bus_type *bus) · 210 unmodified lines | ||
| 1906 | 1847 | } |
| 1907 | 1848 | EXPORT_SYMBOL_GPL(iommu_present); |
| 1908 | 1849 | |
| 1850 | +/** | |
| 1851 | + * device_iommu_capable() - check for a general IOMMU capability | |
| 1852 | + * @dev: device to which the capability would be relevant, if available | |
| 1853 | + * @cap: IOMMU capability | |
| 1854 | + * | |
| 1855 | + * Return: true if an IOMMU is present and supports the given capability | |
| 1856 | + * for the given device, otherwise false. | |
| 1857 | + */ | |
| 1858 | +bool device_iommu_capable(struct device *dev, enum iommu_cap cap) | |
| 1859 | +{ | |
| 1860 | + const struct iommu_ops *ops; | |
| 1861 | + | |
| 1862 | + if (!dev->iommu || !dev->iommu->iommu_dev) | |
| 1863 | + return false; | |
| 1864 | + | |
| 1865 | + ops = dev_iommu_ops(dev); | |
| 1866 | + if (!ops->capable) | |
| 1867 | + return false; | |
| 1868 | + | |
| 1869 | + return ops->capable(cap); | |
| 1870 | +} | |
| 1871 | +EXPORT_SYMBOL_GPL(device_iommu_capable); | |
| 1872 | + | |
| 1909 | 1873 | bool iommu_capable(struct bus_type *bus, enum iommu_cap cap) |
| 1910 | 1874 | { |
| 1911 | 1875 | if (!bus->iommu_ops || !bus->iommu_ops->capable) |
| @@ -1976,6 +1940,24 @@ void iommu_domain_free(struct iommu_domain *domain) · 64 unmodified lines | ||
| 1976 | 1940 | } |
| 1977 | 1941 | EXPORT_SYMBOL_GPL(iommu_domain_free); |
| 1978 | 1942 | |
| 1943 | +/* | |
| 1944 | + * Put the group's domain back to the appropriate core-owned domain - either the | |
| 1945 | + * standard kernel-mode DMA configuration or an all-DMA-blocked domain. | |
| 1946 | + */ | |
| 1947 | +static void __iommu_group_set_core_domain(struct iommu_group *group) | |
| 1948 | +{ | |
| 1949 | + struct iommu_domain *new_domain; | |
| 1950 | + int ret; | |
| 1951 | + | |
| 1952 | + if (group->owner) | |
| 1953 | + new_domain = group->blocking_domain; | |
| 1954 | + else | |
| 1955 | + new_domain = group->default_domain; | |
| 1956 | + | |
| 1957 | + ret = __iommu_group_set_domain(group, new_domain); | |
| 1958 | + WARN(ret, "iommu driver failed to attach the default/blocking domain"); | |
| 1959 | +} | |
| 1960 | + | |
| 1979 | 1961 | static int __iommu_attach_device(struct iommu_domain *domain, |
| 1980 | 1962 | struct device *dev) |
| 1981 | 1963 | { |
| @@ -2032,9 +2014,6 @@ static void __iommu_detach_device(struct iommu_domain *domain, · 50 unmodified lines | ||
| 2032 | 2014 | if (iommu_is_attach_deferred(dev)) |
| 2033 | 2015 | return; |
| 2034 | 2016 | |
| 2035 | − if (unlikely(domain->ops->detach_dev == NULL)) | |
| 2036 | − return; | |
| 2037 | − | |
| 2038 | 2017 | domain->ops->detach_dev(domain, dev); |
| 2039 | 2018 | trace_detach_device_from_domain(dev); |
| 2040 | 2019 | } |
| @@ -2048,12 +2027,10 @@ void iommu_detach_device(struct iommu_domain *domain, struct device *dev) · 7 unmodified lines | ||
| 2048 | 2027 | return; |
| 2049 | 2028 | |
| 2050 | 2029 | mutex_lock(&group->mutex); |
| 2051 | − if (iommu_group_device_count(group) != 1) { | |
| 2052 | − WARN_ON(1); | |
| 2030 | + if (WARN_ON(domain != group->domain) || | |
| 2031 | + WARN_ON(iommu_group_device_count(group) != 1)) | |
| 2053 | 2032 | goto out_unlock; |
| 2054 | − } | |
| 2055 | − | |
| 2056 | − __iommu_detach_group(domain, group); | |
| 2033 | + __iommu_group_set_core_domain(group); | |
| 2057 | 2034 | |
| 2058 | 2035 | out_unlock: |
| 2059 | 2036 | mutex_unlock(&group->mutex); |
| @@ -2109,7 +2086,8 @@ static int __iommu_attach_group(struct iommu_domain *domain, · 49 unmodified lines | ||
| 2109 | 2086 | { |
| 2110 | 2087 | int ret; |
| 2111 | 2088 | |
| 2112 | − if (group->default_domain && group->domain != group->default_domain) | |
| 2089 | + if (group->domain && group->domain != group->default_domain && | |
| 2090 | + group->domain != group->blocking_domain) | |
| 2113 | 2091 | return -EBUSY; |
| 2114 | 2092 | |
| 2115 | 2093 | ret = __iommu_group_for_each_dev(group, domain, |
| @@ -2141,34 +2119,49 @@ static int iommu_group_do_detach_device(struct device *dev, void *data) · 25 unmodified lines | ||
| 2141 | 2119 | return 0; |
| 2142 | 2120 | } |
| 2143 | 2121 | |
| 2144 | −static void __iommu_detach_group(struct iommu_domain *domain, | |
| 2145 | − struct iommu_group *group) | |
| 2122 | +static int __iommu_group_set_domain(struct iommu_group *group, | |
| 2123 | + struct iommu_domain *new_domain) | |
| 2146 | 2124 | { |
| 2147 | 2125 | int ret; |
| 2148 | 2126 | |
| 2149 | − if (!group->default_domain) { | |
| 2150 | − __iommu_group_for_each_dev(group, domain, | |
| 2127 | + if (group->domain == new_domain) | |
| 2128 | + return 0; | |
| 2129 | + | |
| 2130 | + /* | |
| 2131 | + * New drivers should support default domains and so the detach_dev() op | |
| 2132 | + * will never be called. Otherwise the NULL domain represents some | |
| 2133 | + * platform specific behavior. | |
| 2134 | + */ | |
| 2135 | + if (!new_domain) { | |
| 2136 | + if (WARN_ON(!group->domain->ops->detach_dev)) | |
| 2137 | + return -EINVAL; | |
| 2138 | + __iommu_group_for_each_dev(group, group->domain, | |
| 2151 | 2139 | iommu_group_do_detach_device); |
| 2152 | 2140 | group->domain = NULL; |
| 2153 | − return; | |
| 2141 | + return 0; | |
| 2154 | 2142 | } |
| 2155 | 2143 | |
| 2156 | − if (group->domain == group->default_domain) | |
| 2157 | − return; | |
| 2158 | − | |
| 2159 | − /* Detach by re-attaching to the default domain */ | |
| 2160 | − ret = __iommu_group_for_each_dev(group, group->default_domain, | |
| 2144 | + /* | |
| 2145 | + * Changing the domain is done by calling attach_dev() on the new | |
| 2146 | + * domain. This switch does not have to be atomic and DMA can be | |
| 2147 | + * discarded during the transition. DMA must only be able to access | |
| 2148 | + * either new_domain or group->domain, never something else. | |
| 2149 | + * | |
| 2150 | + * Note that this is called in error unwind paths, attaching to a | |
| 2151 | + * domain that has already been attached cannot fail. | |
| 2152 | + */ | |
| 2153 | + ret = __iommu_group_for_each_dev(group, new_domain, | |
| 2161 | 2154 | iommu_group_do_attach_device); |
| 2162 | − if (ret != 0) | |
| 2163 | − WARN_ON(1); | |
| 2164 | − else | |
| 2165 | − group->domain = group->default_domain; | |
| 2155 | + if (ret) | |
| 2156 | + return ret; | |
| 2157 | + group->domain = new_domain; | |
| 2158 | + return 0; | |
| 2166 | 2159 | } |
| 2167 | 2160 | |
| 2168 | 2161 | void iommu_detach_group(struct iommu_domain *domain, struct iommu_group *group) |
| 2169 | 2162 | { |
| 2170 | 2163 | mutex_lock(&group->mutex); |
| 2171 | − __iommu_detach_group(domain, group); | |
| 2164 | + __iommu_group_set_core_domain(group); | |
| 2172 | 2165 | mutex_unlock(&group->mutex); |
| 2173 | 2166 | } |
| 2174 | 2167 | EXPORT_SYMBOL_GPL(iommu_detach_group); |
| @@ -3019,7 +3012,7 @@ static ssize_t iommu_group_store_type(struct iommu_group *group, · 844 unmodified lines | ||
| 3019 | 3012 | if (!capable(CAP_SYS_ADMIN) || !capable(CAP_SYS_RAWIO)) |
| 3020 | 3013 | return -EACCES; |
| 3021 | 3014 | |
| 3022 | − if (WARN_ON(!group)) | |
| 3015 | + if (WARN_ON(!group) || !group->default_domain) | |
| 3023 | 3016 | return -EINVAL; |
| 3024 | 3017 | |
| 3025 | 3018 | if (sysfs_streq(buf, "identity")) |
| @@ -3095,3 +3088,167 @@ out: · 69 unmodified lines | ||
| 3095 | 3088 | |
| 3096 | 3089 | return ret; |
| 3097 | 3090 | } |
| 3091 | + | |
| 3092 | +/** | |
| 3093 | + * iommu_device_use_default_domain() - Device driver wants to handle device | |
| 3094 | + * DMA through the kernel DMA API. | |
| 3095 | + * @dev: The device. | |
| 3096 | + * | |
| 3097 | + * The device driver about to bind @dev wants to do DMA through the kernel | |
| 3098 | + * DMA API. Return 0 if it is allowed, otherwise an error. | |
| 3099 | + */ | |
| 3100 | +int iommu_device_use_default_domain(struct device *dev) | |
| 3101 | +{ | |
| 3102 | + struct iommu_group *group = iommu_group_get(dev); | |
| 3103 | + int ret = 0; | |
| 3104 | + | |
| 3105 | + if (!group) | |
| 3106 | + return 0; | |
| 3107 | + | |
| 3108 | + mutex_lock(&group->mutex); | |
| 3109 | + if (group->owner_cnt) { | |
| 3110 | + if (group->domain != group->default_domain || | |
| 3111 | + group->owner) { | |
| 3112 | + ret = -EBUSY; | |
| 3113 | + goto unlock_out; | |
| 3114 | + } | |
| 3115 | + } | |
| 3116 | + | |
| 3117 | + group->owner_cnt++; | |
| 3118 | + | |
| 3119 | +unlock_out: | |
| 3120 | + mutex_unlock(&group->mutex); | |
| 3121 | + iommu_group_put(group); | |
| 3122 | + | |
| 3123 | + return ret; | |
| 3124 | +} | |
| 3125 | + | |
| 3126 | +/** | |
| 3127 | + * iommu_device_unuse_default_domain() - Device driver stops handling device | |
| 3128 | + * DMA through the kernel DMA API. | |
| 3129 | + * @dev: The device. | |
| 3130 | + * | |
| 3131 | + * The device driver doesn't want to do DMA through kernel DMA API anymore. | |
| 3132 | + * It must be called after iommu_device_use_default_domain(). | |
| 3133 | + */ | |
| 3134 | +void iommu_device_unuse_default_domain(struct device *dev) | |
| 3135 | +{ | |
| 3136 | + struct iommu_group *group = iommu_group_get(dev); | |
| 3137 | + | |
| 3138 | + if (!group) | |
| 3139 | + return; | |
| 3140 | + | |
| 3141 | + mutex_lock(&group->mutex); | |
| 3142 | + if (!WARN_ON(!group->owner_cnt)) | |
| 3143 | + group->owner_cnt--; | |
| 3144 | + | |
| 3145 | + mutex_unlock(&group->mutex); | |
| 3146 | + iommu_group_put(group); | |
| 3147 | +} | |
| 3148 | + | |
| 3149 | +static int __iommu_group_alloc_blocking_domain(struct iommu_group *group) | |
| 3150 | +{ | |
| 3151 | + struct group_device *dev = | |
| 3152 | + list_first_entry(&group->devices, struct group_device, list); | |
| 3153 | + | |
| 3154 | + if (group->blocking_domain) | |
| 3155 | + return 0; | |
| 3156 | + | |
| 3157 | + group->blocking_domain = | |
| 3158 | + __iommu_domain_alloc(dev->dev->bus, IOMMU_DOMAIN_BLOCKED); | |
| 3159 | + if (!group->blocking_domain) { | |
| 3160 | + /* | |
| 3161 | + * For drivers that do not yet understand IOMMU_DOMAIN_BLOCKED | |
| 3162 | + * create an empty domain instead. | |
| 3163 | + */ | |
| 3164 | + group->blocking_domain = __iommu_domain_alloc( | |
| 3165 | + dev->dev->bus, IOMMU_DOMAIN_UNMANAGED); | |
| 3166 | + if (!group->blocking_domain) | |
| 3167 | + return -EINVAL; | |
| 3168 | + } | |
| 3169 | + return 0; | |
| 3170 | +} | |
| 3171 | + | |
| 3172 | +/** | |
| 3173 | + * iommu_group_claim_dma_owner() - Set DMA ownership of a group | |
| 3174 | + * @group: The group. | |
| 3175 | + * @owner: Caller specified pointer. Used for exclusive ownership. | |
| 3176 | + * | |
| 3177 | + * This is to support backward compatibility for vfio which manages | |
| 3178 | + * the dma ownership in iommu_group level. New invocations on this | |
| 3179 | + * interface should be prohibited. | |
| 3180 | + */ | |
| 3181 | +int iommu_group_claim_dma_owner(struct iommu_group *group, void *owner) | |
| 3182 | +{ | |
| 3183 | + int ret = 0; | |
| 3184 | + | |
| 3185 | + mutex_lock(&group->mutex); | |
| 3186 | + if (group->owner_cnt) { | |
| 3187 | + ret = -EPERM; | |
| 3188 | + goto unlock_out; | |
| 3189 | + } else { | |
| 3190 | + if (group->domain && group->domain != group->default_domain) { | |
| 3191 | + ret = -EBUSY; | |
| 3192 | + goto unlock_out; | |
| 3193 | + } | |
| 3194 | + | |
| 3195 | + ret = __iommu_group_alloc_blocking_domain(group); | |
| 3196 | + if (ret) | |
| 3197 | + goto unlock_out; | |
| 3198 | + | |
| 3199 | + ret = __iommu_group_set_domain(group, group->blocking_domain); | |
| 3200 | + if (ret) | |
| 3201 | + goto unlock_out; | |
| 3202 | + group->owner = owner; | |
| 3203 | + } | |
| 3204 | + | |
| 3205 | + group->owner_cnt++; | |
| 3206 | +unlock_out: | |
| 3207 | + mutex_unlock(&group->mutex); | |
| 3208 | + | |
| 3209 | + return ret; | |
| 3210 | +} | |
| 3211 | +EXPORT_SYMBOL_GPL(iommu_group_claim_dma_owner); | |
| 3212 | + | |
| 3213 | +/** | |
| 3214 | + * iommu_group_release_dma_owner() - Release DMA ownership of a group | |
| 3215 | + * @group: The group. | |
| 3216 | + * | |
| 3217 | + * Release the DMA ownership claimed by iommu_group_claim_dma_owner(). | |
| 3218 | + */ | |
| 3219 | +void iommu_group_release_dma_owner(struct iommu_group *group) | |
| 3220 | +{ | |
| 3221 | + int ret; | |
| 3222 | + | |
| 3223 | + mutex_lock(&group->mutex); | |
| 3224 | + if (WARN_ON(!group->owner_cnt || !group->owner)) | |
| 3225 | + goto unlock_out; | |
| 3226 | + | |
| 3227 | + group->owner_cnt = 0; | |
| 3228 | + group->owner = NULL; | |
| 3229 | + ret = __iommu_group_set_domain(group, group->default_domain); | |
| 3230 | + WARN(ret, "iommu driver failed to attach the default domain"); | |
| 3231 | + | |
| 3232 | +unlock_out: | |
| 3233 | + mutex_unlock(&group->mutex); | |
| 3234 | +} | |
| 3235 | +EXPORT_SYMBOL_GPL(iommu_group_release_dma_owner); | |
| 3236 | + | |
| 3237 | +/** | |
| 3238 | + * iommu_group_dma_owner_claimed() - Query group dma ownership status | |
| 3239 | + * @group: The group. | |
| 3240 | + * | |
| 3241 | + * This provides status query on a given group. It is racy and only for | |
| 3242 | + * non-binding status reporting. | |
| 3243 | + */ | |
| 3244 | +bool iommu_group_dma_owner_claimed(struct iommu_group *group) | |
| 3245 | +{ | |
| 3246 | + unsigned int user; | |
| 3247 | + | |
| 3248 | + mutex_lock(&group->mutex); | |
| 3249 | + user = group->owner_cnt; | |
| 3250 | + mutex_unlock(&group->mutex); | |
| 3251 | + | |
| 3252 | + return user; | |
| 3253 | +} | |
| 3254 | +EXPORT_SYMBOL_GPL(iommu_group_dma_owner_claimed); | |
| @@ -583,7 +583,7 @@ static void print_ctx_regs(void __iomem *base, int ctx) · 582 unmodified lines | ||
| 583 | 583 | GET_SCTLR(base, ctx), GET_ACTLR(base, ctx)); |
| 584 | 584 | } |
| 585 | 585 | |
| 586 | −static void insert_iommu_master(struct device *dev, | |
| 586 | +static int insert_iommu_master(struct device *dev, | |
| 587 | 587 | struct msm_iommu_dev **iommu, |
| 588 | 588 | struct of_phandle_args *spec) |
| 589 | 589 | { |
| @@ -592,6 +592,10 @@ static void insert_iommu_master(struct device *dev, · 2 unmodified lines | ||
| 592 | 592 | |
| 593 | 593 | if (list_empty(&(*iommu)->ctx_list)) { |
| 594 | 594 | master = kzalloc(sizeof(*master), GFP_ATOMIC); |
| 595 | + if (!master) { | |
| 596 | + dev_err(dev, "Failed to allocate iommu_master\n"); | |
| 597 | + return -ENOMEM; | |
| 598 | + } | |
| 595 | 599 | master->of_node = dev->of_node; |
| 596 | 600 | list_add(&master->list, &(*iommu)->ctx_list); |
| 597 | 601 | dev_iommu_priv_set(dev, master); |
| @@ -601,30 +605,34 @@ static void insert_iommu_master(struct device *dev, · 3 unmodified lines | ||
| 601 | 605 | if (master->mids[sid] == spec->args[0]) { |
| 602 | 606 | dev_warn(dev, "Stream ID 0x%hx repeated; ignoring\n", |
| 603 | 607 | sid); |
| 604 | − return; | |
| 608 | + return 0; | |
| 605 | 609 | } |
| 606 | 610 | |
| 607 | 611 | master->mids[master->num_mids++] = spec->args[0]; |
| 612 | + return 0; | |
| 608 | 613 | } |
| 609 | 614 | |
| 610 | 615 | static int qcom_iommu_of_xlate(struct device *dev, |
| 611 | 616 | struct of_phandle_args *spec) |
| 612 | 617 | { |
| 613 | − struct msm_iommu_dev *iommu; | |
| 618 | + struct msm_iommu_dev *iommu = NULL, *iter; | |
| 614 | 619 | unsigned long flags; |
| 615 | 620 | int ret = 0; |
| 616 | 621 | |
| 617 | 622 | spin_lock_irqsave(&msm_iommu_lock, flags); |
| 618 | − list_for_each_entry(iommu, &qcom_iommu_devices, dev_node) | |
| 619 | − if (iommu->dev->of_node == spec->np) | |
| 623 | + list_for_each_entry(iter, &qcom_iommu_devices, dev_node) { | |
| 624 | + if (iter->dev->of_node == spec->np) { | |
| 625 | + iommu = iter; | |
| 620 | 626 | break; |
| 627 | + } | |
| 628 | + } | |
| 621 | 629 | |
| 622 | − if (!iommu || iommu->dev->of_node != spec->np) { | |
| 630 | + if (!iommu) { | |
| 623 | 631 | ret = -ENODEV; |
| 624 | 632 | goto fail; |
| 625 | 633 | } |
| 626 | 634 | |
| 627 | − insert_iommu_master(dev, &iommu, spec); | |
| 635 | + ret = insert_iommu_master(dev, &iommu, spec); | |
| 628 | 636 | fail: |
| 629 | 637 | spin_unlock_irqrestore(&msm_iommu_lock, flags); |
| 630 | 638 | |
| @@ -14,12 +14,14 @@ · 13 unmodified lines | ||
| 14 | 14 | #include <linux/io.h> |
| 15 | 15 | #include <linux/iommu.h> |
| 16 | 16 | #include <linux/iopoll.h> |
| 17 | +#include <linux/io-pgtable.h> | |
| 17 | 18 | #include <linux/list.h> |
| 18 | 19 | #include <linux/mfd/syscon.h> |
| 19 | 20 | #include <linux/module.h> |
| 20 | 21 | #include <linux/of_address.h> |
| 21 | 22 | #include <linux/of_irq.h> |
| 22 | 23 | #include <linux/of_platform.h> |
| 24 | +#include <linux/pci.h> | |
| 23 | 25 | #include <linux/platform_device.h> |
| 24 | 26 | #include <linux/pm_runtime.h> |
| 25 | 27 | #include <linux/regmap.h> |
| @@ -29,7 +31,7 @@ · 3 unmodified lines | ||
| 29 | 31 | #include <asm/barrier.h> |
| 30 | 32 | #include <soc/mediatek/smi.h> |
| 31 | 33 | |
| 32 | −#include "mtk_iommu.h" | |
| 34 | +#include <dt-bindings/memory/mtk-memory-port.h> | |
| 33 | 35 | |
| 34 | 36 | #define REG_MMU_PT_BASE_ADDR 0x000 |
| 35 | 37 | #define MMU_PT_ADDR_MASK GENMASK(31, 7) |
| @@ -51,6 +53,8 @@ · 15 unmodified lines | ||
| 51 | 53 | #define F_MMU_STANDARD_AXI_MODE_MASK (BIT(3) | BIT(19)) |
| 52 | 54 | |
| 53 | 55 | #define REG_MMU_DCM_DIS 0x050 |
| 56 | +#define F_MMU_DCM BIT(8) | |
| 57 | + | |
| 54 | 58 | #define REG_MMU_WR_LEN_CTRL 0x054 |
| 55 | 59 | #define F_MMU_WR_THROT_DIS_MASK (BIT(5) | BIT(21)) |
| 56 | 60 | |
| @@ -103,10 +107,15 @@ · 46 unmodified lines | ||
| 103 | 107 | #define REG_MMU1_INT_ID 0x154 |
| 104 | 108 | #define F_MMU_INT_ID_COMM_ID(a) (((a) >> 9) & 0x7) |
| 105 | 109 | #define F_MMU_INT_ID_SUB_COMM_ID(a) (((a) >> 7) & 0x3) |
| 110 | +#define F_MMU_INT_ID_COMM_ID_EXT(a) (((a) >> 10) & 0x7) | |
| 111 | +#define F_MMU_INT_ID_SUB_COMM_ID_EXT(a) (((a) >> 7) & 0x7) | |
| 106 | 112 | #define F_MMU_INT_ID_LARB_ID(a) (((a) >> 7) & 0x7) |
| 107 | 113 | #define F_MMU_INT_ID_PORT_ID(a) (((a) >> 2) & 0x1f) |
| 108 | 114 | |
| 109 | 115 | #define MTK_PROTECT_PA_ALIGN 256 |
| 116 | +#define MTK_IOMMU_BANK_SZ 0x1000 | |
| 117 | + | |
| 118 | +#define PERICFG_IOMMU_1 0x714 | |
| 110 | 119 | |
| 111 | 120 | #define HAS_4GB_MODE BIT(0) |
| 112 | 121 | /* HW will use the EMI clock if there isn't the "bclk". */ |
| @@ -114,25 +123,147 @@ · 1 unmodified line | ||
| 114 | 123 | #define HAS_VLD_PA_RNG BIT(2) |
| 115 | 124 | #define RESET_AXI BIT(3) |
| 116 | 125 | #define OUT_ORDER_WR_EN BIT(4) |
| 117 | −#define HAS_SUB_COMM BIT(5) | |
| 118 | −#define WR_THROT_EN BIT(6) | |
| 119 | −#define HAS_LEGACY_IVRP_PADDR BIT(7) | |
| 120 | −#define IOVA_34_EN BIT(8) | |
| 126 | +#define HAS_SUB_COMM_2BITS BIT(5) | |
| 127 | +#define HAS_SUB_COMM_3BITS BIT(6) | |
| 128 | +#define WR_THROT_EN BIT(7) | |
| 129 | +#define HAS_LEGACY_IVRP_PADDR BIT(8) | |
| 130 | +#define IOVA_34_EN BIT(9) | |
| 131 | +#define SHARE_PGTABLE BIT(10) /* 2 HW share pgtable */ | |
| 132 | +#define DCM_DISABLE BIT(11) | |
| 133 | +#define STD_AXI_MODE BIT(12) /* For non MM iommu */ | |
| 134 | +/* 2 bits: iommu type */ | |
| 135 | +#define MTK_IOMMU_TYPE_MM (0x0 << 13) | |
| 136 | +#define MTK_IOMMU_TYPE_INFRA (0x1 << 13) | |
| 137 | +#define MTK_IOMMU_TYPE_MASK (0x3 << 13) | |
| 138 | +/* PM and clock always on. e.g. infra iommu */ | |
| 139 | +#define PM_CLK_AO BIT(15) | |
| 140 | +#define IFA_IOMMU_PCIE_SUPPORT BIT(16) | |
| 141 | + | |
| 142 | +#define MTK_IOMMU_HAS_FLAG_MASK(pdata, _x, mask) \ | |
| 143 | + ((((pdata)->flags) & (mask)) == (_x)) | |
| 144 | + | |
| 145 | +#define MTK_IOMMU_HAS_FLAG(pdata, _x) MTK_IOMMU_HAS_FLAG_MASK(pdata, _x, _x) | |
| 146 | +#define MTK_IOMMU_IS_TYPE(pdata, _x) MTK_IOMMU_HAS_FLAG_MASK(pdata, _x,\ | |
| 147 | + MTK_IOMMU_TYPE_MASK) | |
| 148 | + | |
| 149 | +#define MTK_INVALID_LARBID MTK_LARB_NR_MAX | |
| 150 | + | |
| 151 | +#define MTK_LARB_COM_MAX 8 | |
| 152 | +#define MTK_LARB_SUBCOM_MAX 8 | |
| 153 | + | |
| 154 | +#define MTK_IOMMU_GROUP_MAX 8 | |
| 155 | +#define MTK_IOMMU_BANK_MAX 5 | |
| 156 | + | |
| 157 | +enum mtk_iommu_plat { | |
| 158 | + M4U_MT2712, | |
| 159 | + M4U_MT6779, | |
| 160 | + M4U_MT8167, | |
| 161 | + M4U_MT8173, | |
| 162 | + M4U_MT8183, | |
| 163 | + M4U_MT8186, | |
| 164 | + M4U_MT8192, | |
| 165 | + M4U_MT8195, | |
| 166 | +}; | |
| 167 | + | |
| 168 | +struct mtk_iommu_iova_region { | |
| 169 | + dma_addr_t iova_base; | |
| 170 | + unsigned long long size; | |
| 171 | +}; | |
| 172 | + | |
| 173 | +struct mtk_iommu_suspend_reg { | |
| 174 | + u32 misc_ctrl; | |
| 175 | + u32 dcm_dis; | |
| 176 | + u32 ctrl_reg; | |
| 177 | + u32 vld_pa_rng; | |
| 178 | + u32 wr_len_ctrl; | |
| 179 | + | |
| 180 | + u32 int_control[MTK_IOMMU_BANK_MAX]; | |
| 181 | + u32 int_main_control[MTK_IOMMU_BANK_MAX]; | |
| 182 | + u32 ivrp_paddr[MTK_IOMMU_BANK_MAX]; | |
| 183 | +}; | |
| 184 | + | |
| 185 | +struct mtk_iommu_plat_data { | |
| 186 | + enum mtk_iommu_plat m4u_plat; | |
| 187 | + u32 flags; | |
| 188 | + u32 inv_sel_reg; | |
| 189 | + | |
| 190 | + char *pericfg_comp_str; | |
| 191 | + struct list_head *hw_list; | |
| 192 | + unsigned int iova_region_nr; | |
| 193 | + const struct mtk_iommu_iova_region *iova_region; | |
| 194 | + | |
| 195 | + u8 banks_num; | |
| 196 | + bool banks_enable[MTK_IOMMU_BANK_MAX]; | |
| 197 | + unsigned int banks_portmsk[MTK_IOMMU_BANK_MAX]; | |
| 198 | + unsigned char larbid_remap[MTK_LARB_COM_MAX][MTK_LARB_SUBCOM_MAX]; | |
| 199 | +}; | |
| 200 | + | |
| 201 | +struct mtk_iommu_bank_data { | |
| 202 | + void __iomem *base; | |
| 203 | + int irq; | |
| 204 | + u8 id; | |
| 205 | + struct device *parent_dev; | |
| 206 | + struct mtk_iommu_data *parent_data; | |
| 207 | + spinlock_t tlb_lock; /* lock for tlb range flush */ | |
| 208 | + struct mtk_iommu_domain *m4u_dom; /* Each bank has a domain */ | |
| 209 | +}; | |
| 210 | + | |
| 211 | +struct mtk_iommu_data { | |
| 212 | + struct device *dev; | |
| 213 | + struct clk *bclk; | |
| 214 | + phys_addr_t protect_base; /* protect memory base */ | |
| 215 | + struct mtk_iommu_suspend_reg reg; | |
| 216 | + struct iommu_group *m4u_group[MTK_IOMMU_GROUP_MAX]; | |
| 217 | + bool enable_4GB; | |
| 121 | 218 | |
| 122 | −#define MTK_IOMMU_HAS_FLAG(pdata, _x) \ | |
| 123 | − ((((pdata)->flags) & (_x)) == (_x)) | |
| 219 | + struct iommu_device iommu; | |
| 220 | + const struct mtk_iommu_plat_data *plat_data; | |
| 221 | + struct device *smicomm_dev; | |
| 222 | + | |
| 223 | + struct mtk_iommu_bank_data *bank; | |
| 224 | + | |
| 225 | + struct dma_iommu_mapping *mapping; /* For mtk_iommu_v1.c */ | |
| 226 | + struct regmap *pericfg; | |
| 227 | + | |
| 228 | + struct mutex mutex; /* Protect m4u_group/m4u_dom above */ | |
| 229 | + | |
| 230 | + /* | |
| 231 | + * In the sharing pgtable case, list data->list to the global list like m4ulist. | |
| 232 | + * In the non-sharing pgtable case, list data->list to the itself hw_list_head. | |
| 233 | + */ | |
| 234 | + struct list_head *hw_list; | |
| 235 | + struct list_head hw_list_head; | |
| 236 | + struct list_head list; | |
| 237 | + struct mtk_smi_larb_iommu larb_imu[MTK_LARB_NR_MAX]; | |
| 238 | +}; | |
| 124 | 239 | |
| 125 | 240 | struct mtk_iommu_domain { |
| 126 | 241 | struct io_pgtable_cfg cfg; |
| 127 | 242 | struct io_pgtable_ops *iop; |
| 128 | 243 | |
| 129 | − struct mtk_iommu_data *data; | |
| 244 | + struct mtk_iommu_bank_data *bank; | |
| 130 | 245 | struct iommu_domain domain; |
| 246 | + | |
| 247 | + struct mutex mutex; /* Protect "data" in this structure */ | |
| 131 | 248 | }; |
| 132 | 249 | |
| 250 | +static int mtk_iommu_bind(struct device *dev) | |
| 251 | +{ | |
| 252 | + struct mtk_iommu_data *data = dev_get_drvdata(dev); | |
| 253 | + | |
| 254 | + return component_bind_all(dev, &data->larb_imu); | |
| 255 | +} | |
| 256 | + | |
| 257 | +static void mtk_iommu_unbind(struct device *dev) | |
| 258 | +{ | |
| 259 | + struct mtk_iommu_data *data = dev_get_drvdata(dev); | |
| 260 | + | |
| 261 | + component_unbind_all(dev, &data->larb_imu); | |
| 262 | +} | |
| 263 | + | |
| 133 | 264 | static const struct iommu_ops mtk_iommu_ops; |
| 134 | 265 | |
| 135 | −static int mtk_iommu_hw_init(const struct mtk_iommu_data *data); | |
| 266 | +static int mtk_iommu_hw_init(const struct mtk_iommu_data *data, unsigned int bankid); | |
| 136 | 267 | |
| 137 | 268 | #define MTK_IOMMU_TLB_ADDR(iova) ({ \ |
| 138 | 269 | dma_addr_t _addr = iova; \ |
| @@ -165,42 +296,28 @@ static int mtk_iommu_hw_init(const struct mtk_iommu_data *data); · 26 unmodified lines | ||
| 165 | 296 | |
| 166 | 297 | static LIST_HEAD(m4ulist); /* List all the M4U HWs */ |
| 167 | 298 | |
| 168 | −#define for_each_m4u(data) list_for_each_entry(data, &m4ulist, list) | |
| 169 | − | |
| 170 | −struct mtk_iommu_iova_region { | |
| 171 | − dma_addr_t iova_base; | |
| 172 | − unsigned long long size; | |
| 173 | −}; | |
| 299 | +#define for_each_m4u(data, head) list_for_each_entry(data, head, list) | |
| 174 | 300 | |
| 175 | 301 | static const struct mtk_iommu_iova_region single_domain[] = { |
| 176 | 302 | {.iova_base = 0, .size = SZ_4G}, |
| 177 | 303 | }; |
| 178 | 304 | |
| 179 | 305 | static const struct mtk_iommu_iova_region mt8192_multi_dom[] = { |
| 180 | − { .iova_base = 0x0, .size = SZ_4G}, /* disp: 0 ~ 4G */ | |
| 306 | + { .iova_base = 0x0, .size = SZ_4G}, /* 0 ~ 4G */ | |
| 181 | 307 | #if IS_ENABLED(CONFIG_ARCH_DMA_ADDR_T_64BIT) |
| 182 | − { .iova_base = SZ_4G, .size = SZ_4G}, /* vdec: 4G ~ 8G */ | |
| 183 | − { .iova_base = SZ_4G * 2, .size = SZ_4G}, /* CAM/MDP: 8G ~ 12G */ | |
| 308 | + { .iova_base = SZ_4G, .size = SZ_4G}, /* 4G ~ 8G */ | |
| 309 | + { .iova_base = SZ_4G * 2, .size = SZ_4G}, /* 8G ~ 12G */ | |
| 310 | + { .iova_base = SZ_4G * 3, .size = SZ_4G}, /* 12G ~ 16G */ | |
| 311 | + | |
| 184 | 312 | { .iova_base = 0x240000000ULL, .size = 0x4000000}, /* CCU0 */ |
| 185 | 313 | { .iova_base = 0x244000000ULL, .size = 0x4000000}, /* CCU1 */ |
| 186 | 314 | #endif |
| 187 | 315 | }; |
| 188 | 316 | |
| 189 | −/* | |
| 190 | − * There may be 1 or 2 M4U HWs, But we always expect they are in the same domain | |
| 191 | − * for the performance. | |
| 192 | − * | |
| 193 | − * Here always return the mtk_iommu_data of the first probed M4U where the | |
| 194 | − * iommu domain information is recorded. | |
| 195 | − */ | |
| 196 | −static struct mtk_iommu_data *mtk_iommu_get_m4u_data(void) | |
| 317 | +/* If 2 M4U share a domain(use the same hwlist), Put the corresponding info in first data.*/ | |
| 318 | +static struct mtk_iommu_data *mtk_iommu_get_frst_data(struct list_head *hwlist) | |
| 197 | 319 | { |
| 198 | − struct mtk_iommu_data *data; | |
| 199 | − | |
| 200 | − for_each_m4u(data) | |
| 201 | − return data; | |
| 202 | − | |
| 203 | − return NULL; | |
| 320 | + return list_first_entry(hwlist, struct mtk_iommu_data, list); | |
| 204 | 321 | } |
| 205 | 322 | |
| 206 | 323 | static struct mtk_iommu_domain *to_mtk_domain(struct iommu_domain *dom) |
| @@ -210,46 +327,72 @@ static struct mtk_iommu_domain *to_mtk_domain(struct iommu_domain *dom) · 3 unmodified lines | ||
| 210 | 327 | |
| 211 | 328 | static void mtk_iommu_tlb_flush_all(struct mtk_iommu_data *data) |
| 212 | 329 | { |
| 330 | + /* Tlb flush all always is in bank0. */ | |
| 331 | + struct mtk_iommu_bank_data *bank = &data->bank[0]; | |
| 332 | + void __iomem *base = bank->base; | |
| 213 | 333 | unsigned long flags; |
| 214 | 334 | |
| 215 | − spin_lock_irqsave(&data->tlb_lock, flags); | |
| 216 | − writel_relaxed(F_INVLD_EN1 | F_INVLD_EN0, | |
| 217 | − data->base + data->plat_data->inv_sel_reg); | |
| 218 | − writel_relaxed(F_ALL_INVLD, data->base + REG_MMU_INVALIDATE); | |
| 335 | + spin_lock_irqsave(&bank->tlb_lock, flags); | |
| 336 | + writel_relaxed(F_INVLD_EN1 | F_INVLD_EN0, base + data->plat_data->inv_sel_reg); | |
| 337 | + writel_relaxed(F_ALL_INVLD, base + REG_MMU_INVALIDATE); | |
| 219 | 338 | wmb(); /* Make sure the tlb flush all done */ |
| 220 | − spin_unlock_irqrestore(&data->tlb_lock, flags); | |
| 339 | + spin_unlock_irqrestore(&bank->tlb_lock, flags); | |
| 221 | 340 | } |
| 222 | 341 | |
| 223 | 342 | static void mtk_iommu_tlb_flush_range_sync(unsigned long iova, size_t size, |
| 224 | − size_t granule, | |
| 225 | − struct mtk_iommu_data *data) | |
| 343 | + struct mtk_iommu_bank_data *bank) | |
| 226 | 344 | { |
| 345 | + struct list_head *head = bank->parent_data->hw_list; | |
| 346 | + struct mtk_iommu_bank_data *curbank; | |
| 347 | + struct mtk_iommu_data *data; | |
| 348 | + bool check_pm_status; | |
| 227 | 349 | unsigned long flags; |
| 350 | + void __iomem *base; | |
| 228 | 351 | int ret; |
| 229 | 352 | u32 tmp; |
| 230 | 353 | |
| 231 | − for_each_m4u(data) { | |
| 232 | − if (pm_runtime_get_if_in_use(data->dev) <= 0) | |
| 233 | − continue; | |
| 354 | + for_each_m4u(data, head) { | |
| 355 | + /* | |
| 356 | + * To avoid resume the iommu device frequently when the iommu device | |
| 357 | + * is not active, it doesn't always call pm_runtime_get here, then tlb | |
| 358 | + * flush depends on the tlb flush all in the runtime resume. | |
| 359 | + * | |
| 360 | + * There are 2 special cases: | |
| 361 | + * | |
| 362 | + * Case1: The iommu dev doesn't have power domain but has bclk. This case | |
| 363 | + * should also avoid the tlb flush while the dev is not active to mute | |
| 364 | + * the tlb timeout log. like mt8173. | |
| 365 | + * | |
| 366 | + * Case2: The power/clock of infra iommu is always on, and it doesn't | |
| 367 | + * have the device link with the master devices. This case should avoid | |
| 368 | + * the PM status check. | |
| 369 | + */ | |
| 370 | + check_pm_status = !MTK_IOMMU_HAS_FLAG(data->plat_data, PM_CLK_AO); | |
| 234 | 371 | |
| 235 | − spin_lock_irqsave(&data->tlb_lock, flags); | |
| 372 | + if (check_pm_status) { | |
| 373 | + if (pm_runtime_get_if_in_use(data->dev) <= 0) | |
| 374 | + continue; | |
| 375 | + } | |
| 376 | + | |
| 377 | + curbank = &data->bank[bank->id]; | |
| 378 | + base = curbank->base; | |
| 379 | + | |
| 380 | + spin_lock_irqsave(&curbank->tlb_lock, flags); | |
| 236 | 381 | writel_relaxed(F_INVLD_EN1 | F_INVLD_EN0, |
| 237 | − data->base + data->plat_data->inv_sel_reg); | |
| 382 | + base + data->plat_data->inv_sel_reg); | |
| 238 | 383 | |
| 239 | − writel_relaxed(MTK_IOMMU_TLB_ADDR(iova), | |
| 240 | − data->base + REG_MMU_INVLD_START_A); | |
| 384 | + writel_relaxed(MTK_IOMMU_TLB_ADDR(iova), base + REG_MMU_INVLD_START_A); | |
| 241 | 385 | writel_relaxed(MTK_IOMMU_TLB_ADDR(iova + size - 1), |
| 242 | − data->base + REG_MMU_INVLD_END_A); | |
| 243 | − writel_relaxed(F_MMU_INV_RANGE, | |
| 244 | − data->base + REG_MMU_INVALIDATE); | |
| 386 | + base + REG_MMU_INVLD_END_A); | |
| 387 | + writel_relaxed(F_MMU_INV_RANGE, base + REG_MMU_INVALIDATE); | |
| 245 | 388 | |
| 246 | 389 | /* tlb sync */ |
| 247 | − ret = readl_poll_timeout_atomic(data->base + REG_MMU_CPE_DONE, | |
| 390 | + ret = readl_poll_timeout_atomic(base + REG_MMU_CPE_DONE, | |
| 248 | 391 | tmp, tmp != 0, 10, 1000); |
| 249 | 392 | |
| 250 | 393 | /* Clear the CPE status */ |
| 251 | − writel_relaxed(0, data->base + REG_MMU_CPE_DONE); | |
| 252 | − spin_unlock_irqrestore(&data->tlb_lock, flags); | |
| 394 | + writel_relaxed(0, base + REG_MMU_CPE_DONE); | |
| 395 | + spin_unlock_irqrestore(&curbank->tlb_lock, flags); | |
| 253 | 396 | |
| 254 | 397 | if (ret) { |
| 255 | 398 | dev_warn(data->dev, |
| @@ -257,70 +400,103 @@ static void mtk_iommu_tlb_flush_range_sync(unsigned long iova, size_t size, · 1 unmodified line | ||
| 257 | 400 | mtk_iommu_tlb_flush_all(data); |
| 258 | 401 | } |
| 259 | 402 | |
| 260 | − pm_runtime_put(data->dev); | |
| 403 | + if (check_pm_status) | |
| 404 | + pm_runtime_put(data->dev); | |
| 261 | 405 | } |
| 262 | 406 | } |
| 263 | 407 | |
| 264 | 408 | static irqreturn_t mtk_iommu_isr(int irq, void *dev_id) |
| 265 | 409 | { |
| 266 | − struct mtk_iommu_data *data = dev_id; | |
| 267 | − struct mtk_iommu_domain *dom = data->m4u_dom; | |
| 268 | − unsigned int fault_larb, fault_port, sub_comm = 0; | |
| 410 | + struct mtk_iommu_bank_data *bank = dev_id; | |
| 411 | + struct mtk_iommu_data *data = bank->parent_data; | |
| 412 | + struct mtk_iommu_domain *dom = bank->m4u_dom; | |
| 413 | + unsigned int fault_larb = MTK_INVALID_LARBID, fault_port = 0, sub_comm = 0; | |
| 269 | 414 | u32 int_state, regval, va34_32, pa34_32; |
| 415 | + const struct mtk_iommu_plat_data *plat_data = data->plat_data; | |
| 416 | + void __iomem *base = bank->base; | |
| 270 | 417 | u64 fault_iova, fault_pa; |
| 271 | 418 | bool layer, write; |
| 272 | 419 | |
| 273 | 420 | /* Read error info from registers */ |
| 274 | − int_state = readl_relaxed(data->base + REG_MMU_FAULT_ST1); | |
| 421 | + int_state = readl_relaxed(base + REG_MMU_FAULT_ST1); | |
| 275 | 422 | if (int_state & F_REG_MMU0_FAULT_MASK) { |
| 276 | − regval = readl_relaxed(data->base + REG_MMU0_INT_ID); | |
| 277 | − fault_iova = readl_relaxed(data->base + REG_MMU0_FAULT_VA); | |
| 278 | − fault_pa = readl_relaxed(data->base + REG_MMU0_INVLD_PA); | |
| 423 | + regval = readl_relaxed(base + REG_MMU0_INT_ID); | |
| 424 | + fault_iova = readl_relaxed(base + REG_MMU0_FAULT_VA); | |
| 425 | + fault_pa = readl_relaxed(base + REG_MMU0_INVLD_PA); | |
| 279 | 426 | } else { |
| 280 | − regval = readl_relaxed(data->base + REG_MMU1_INT_ID); | |
| 281 | − fault_iova = readl_relaxed(data->base + REG_MMU1_FAULT_VA); | |
| 282 | − fault_pa = readl_relaxed(data->base + REG_MMU1_INVLD_PA); | |
| 427 | + regval = readl_relaxed(base + REG_MMU1_INT_ID); | |
| 428 | + fault_iova = readl_relaxed(base + REG_MMU1_FAULT_VA); | |
| 429 | + fault_pa = readl_relaxed(base + REG_MMU1_INVLD_PA); | |
| 283 | 430 | } |
| 284 | 431 | layer = fault_iova & F_MMU_FAULT_VA_LAYER_BIT; |
| 285 | 432 | write = fault_iova & F_MMU_FAULT_VA_WRITE_BIT; |
| 286 | − if (MTK_IOMMU_HAS_FLAG(data->plat_data, IOVA_34_EN)) { | |
| 433 | + if (MTK_IOMMU_HAS_FLAG(plat_data, IOVA_34_EN)) { | |
| 287 | 434 | va34_32 = FIELD_GET(F_MMU_INVAL_VA_34_32_MASK, fault_iova); |
| 288 | − pa34_32 = FIELD_GET(F_MMU_INVAL_PA_34_32_MASK, fault_iova); | |
| 289 | 435 | fault_iova = fault_iova & F_MMU_INVAL_VA_31_12_MASK; |
| 290 | 436 | fault_iova |= (u64)va34_32 << 32; |
| 291 | − fault_pa |= (u64)pa34_32 << 32; | |
| 292 | 437 | } |
| 293 | − | |
| 294 | − fault_port = F_MMU_INT_ID_PORT_ID(regval); | |
| 295 | − if (MTK_IOMMU_HAS_FLAG(data->plat_data, HAS_SUB_COMM)) { | |
| 296 | − fault_larb = F_MMU_INT_ID_COMM_ID(regval); | |
| 297 | − sub_comm = F_MMU_INT_ID_SUB_COMM_ID(regval); | |
| 298 | − } else { | |
| 299 | − fault_larb = F_MMU_INT_ID_LARB_ID(regval); | |
| 438 | + pa34_32 = FIELD_GET(F_MMU_INVAL_PA_34_32_MASK, fault_iova); | |
| 439 | + fault_pa |= (u64)pa34_32 << 32; | |
| 440 | + | |
| 441 | + if (MTK_IOMMU_IS_TYPE(plat_data, MTK_IOMMU_TYPE_MM)) { | |
| 442 | + fault_port = F_MMU_INT_ID_PORT_ID(regval); | |
| 443 | + if (MTK_IOMMU_HAS_FLAG(plat_data, HAS_SUB_COMM_2BITS)) { | |
| 444 | + fault_larb = F_MMU_INT_ID_COMM_ID(regval); | |
| 445 | + sub_comm = F_MMU_INT_ID_SUB_COMM_ID(regval); | |
| 446 | + } else if (MTK_IOMMU_HAS_FLAG(plat_data, HAS_SUB_COMM_3BITS)) { | |
| 447 | + fault_larb = F_MMU_INT_ID_COMM_ID_EXT(regval); | |
| 448 | + sub_comm = F_MMU_INT_ID_SUB_COMM_ID_EXT(regval); | |
| 449 | + } else { | |
| 450 | + fault_larb = F_MMU_INT_ID_LARB_ID(regval); | |
| 451 | + } | |
| 452 | + fault_larb = data->plat_data->larbid_remap[fault_larb][sub_comm]; | |
| 300 | 453 | } |
| 301 | − fault_larb = data->plat_data->larbid_remap[fault_larb][sub_comm]; | |
| 302 | 454 | |
| 303 | − if (report_iommu_fault(&dom->domain, data->dev, fault_iova, | |
| 455 | + if (report_iommu_fault(&dom->domain, bank->parent_dev, fault_iova, | |
| 304 | 456 | write ? IOMMU_FAULT_WRITE : IOMMU_FAULT_READ)) { |
| 305 | 457 | dev_err_ratelimited( |
| 306 | − data->dev, | |
| 307 | − "fault type=0x%x iova=0x%llx pa=0x%llx larb=%d port=%d layer=%d %s\n", | |
| 308 | − int_state, fault_iova, fault_pa, fault_larb, fault_port, | |
| 458 | + bank->parent_dev, | |
| 459 | + "fault type=0x%x iova=0x%llx pa=0x%llx master=0x%x(larb=%d port=%d) layer=%d %s\n", | |
| 460 | + int_state, fault_iova, fault_pa, regval, fault_larb, fault_port, | |
| 309 | 461 | layer, write ? "write" : "read"); |
| 310 | 462 | } |
| 311 | 463 | |
| 312 | 464 | /* Interrupt clear */ |
| 313 | − regval = readl_relaxed(data->base + REG_MMU_INT_CONTROL0); | |
| 465 | + regval = readl_relaxed(base + REG_MMU_INT_CONTROL0); | |
| 314 | 466 | regval |= F_INT_CLR_BIT; |
| 315 | − writel_relaxed(regval, data->base + REG_MMU_INT_CONTROL0); | |
| 467 | + writel_relaxed(regval, base + REG_MMU_INT_CONTROL0); | |
| 316 | 468 | |
| 317 | 469 | mtk_iommu_tlb_flush_all(data); |
| 318 | 470 | |
| 319 | 471 | return IRQ_HANDLED; |
| 320 | 472 | } |
| 321 | 473 | |
| 322 | −static int mtk_iommu_get_domain_id(struct device *dev, | |
| 323 | − const struct mtk_iommu_plat_data *plat_data) | |
| 474 | +static unsigned int mtk_iommu_get_bank_id(struct device *dev, | |
| 475 | + const struct mtk_iommu_plat_data *plat_data) | |
| 476 | +{ | |
| 477 | + struct iommu_fwspec *fwspec = dev_iommu_fwspec_get(dev); | |
| 478 | + unsigned int i, portmsk = 0, bankid = 0; | |
| 479 | + | |
| 480 | + if (plat_data->banks_num == 1) | |
| 481 | + return bankid; | |
| 482 | + | |
| 483 | + for (i = 0; i < fwspec->num_ids; i++) | |
| 484 | + portmsk |= BIT(MTK_M4U_TO_PORT(fwspec->ids[i])); | |
| 485 | + | |
| 486 | + for (i = 0; i < plat_data->banks_num && i < MTK_IOMMU_BANK_MAX; i++) { | |
| 487 | + if (!plat_data->banks_enable[i]) | |
| 488 | + continue; | |
| 489 | + | |
| 490 | + if (portmsk & plat_data->banks_portmsk[i]) { | |
| 491 | + bankid = i; | |
| 492 | + break; | |
| 493 | + } | |
| 494 | + } | |
| 495 | + return bankid; /* default is 0 */ | |
| 496 | +} | |
| 497 | + | |
| 498 | +static int mtk_iommu_get_iova_region_id(struct device *dev, | |
| 499 | + const struct mtk_iommu_plat_data *plat_data) | |
| 324 | 500 | { |
| 325 | 501 | const struct mtk_iommu_iova_region *rgn = plat_data->iova_region; |
| 326 | 502 | const struct bus_dma_region *dma_rgn = dev->dma_range_map; |
| @@ -349,46 +525,65 @@ static int mtk_iommu_get_domain_id(struct device *dev, · 22 unmodified lines | ||
| 349 | 525 | return -EINVAL; |
| 350 | 526 | } |
| 351 | 527 | |
| 352 | −static void mtk_iommu_config(struct mtk_iommu_data *data, struct device *dev, | |
| 353 | − bool enable, unsigned int domid) | |
| 528 | +static int mtk_iommu_config(struct mtk_iommu_data *data, struct device *dev, | |
| 529 | + bool enable, unsigned int regionid) | |
| 354 | 530 | { |
| 355 | 531 | struct mtk_smi_larb_iommu *larb_mmu; |
| 356 | 532 | unsigned int larbid, portid; |
| 357 | 533 | struct iommu_fwspec *fwspec = dev_iommu_fwspec_get(dev); |
| 358 | 534 | const struct mtk_iommu_iova_region *region; |
| 359 | − int i; | |
| 535 | + u32 peri_mmuen, peri_mmuen_msk; | |
| 536 | + int i, ret = 0; | |
| 360 | 537 | |
| 361 | 538 | for (i = 0; i < fwspec->num_ids; ++i) { |
| 362 | 539 | larbid = MTK_M4U_TO_LARB(fwspec->ids[i]); |
| 363 | 540 | portid = MTK_M4U_TO_PORT(fwspec->ids[i]); |
| 364 | 541 | |
| 365 | − larb_mmu = &data->larb_imu[larbid]; | |
| 366 | − | |
| 367 | − region = data->plat_data->iova_region + domid; | |
| 368 | − larb_mmu->bank[portid] = upper_32_bits(region->iova_base); | |
| 369 | − | |
| 370 | − dev_dbg(dev, "%s iommu for larb(%s) port %d dom %d bank %d.\n", | |
| 371 | − enable ? "enable" : "disable", dev_name(larb_mmu->dev), | |
| 372 | − portid, domid, larb_mmu->bank[portid]); | |
| 373 | − | |
| 374 | − if (enable) | |
| 375 | − larb_mmu->mmu |= MTK_SMI_MMU_EN(portid); | |
| 376 | − else | |
| 377 | − larb_mmu->mmu &= ~MTK_SMI_MMU_EN(portid); | |
| 542 | + if (MTK_IOMMU_IS_TYPE(data->plat_data, MTK_IOMMU_TYPE_MM)) { | |
| 543 | + larb_mmu = &data->larb_imu[larbid]; | |
| 544 | + | |
| 545 | + region = data->plat_data->iova_region + regionid; | |
| 546 | + larb_mmu->bank[portid] = upper_32_bits(region->iova_base); | |
| 547 | + | |
| 548 | + dev_dbg(dev, "%s iommu for larb(%s) port %d region %d rgn-bank %d.\n", | |
| 549 | + enable ? "enable" : "disable", dev_name(larb_mmu->dev), | |
| 550 | + portid, regionid, larb_mmu->bank[portid]); | |
| 551 | + | |
| 552 | + if (enable) | |
| 553 | + larb_mmu->mmu |= MTK_SMI_MMU_EN(portid); | |
| 554 | + else | |
| 555 | + larb_mmu->mmu &= ~MTK_SMI_MMU_EN(portid); | |
| 556 | + } else if (MTK_IOMMU_IS_TYPE(data->plat_data, MTK_IOMMU_TYPE_INFRA)) { | |
| 557 | + peri_mmuen_msk = BIT(portid); | |
| 558 | + /* PCI dev has only one output id, enable the next writing bit for PCIe */ | |
| 559 | + if (dev_is_pci(dev)) | |
| 560 | + peri_mmuen_msk |= BIT(portid + 1); | |
| 561 | + | |
| 562 | + peri_mmuen = enable ? peri_mmuen_msk : 0; | |
| 563 | + ret = regmap_update_bits(data->pericfg, PERICFG_IOMMU_1, | |
| 564 | + peri_mmuen_msk, peri_mmuen); | |
| 565 | + if (ret) | |
| 566 | + dev_err(dev, "%s iommu(%s) inframaster 0x%x fail(%d).\n", | |
| 567 | + enable ? "enable" : "disable", | |
| 568 | + dev_name(data->dev), peri_mmuen_msk, ret); | |
| 569 | + } | |
| 378 | 570 | } |
| 571 | + return ret; | |
| 379 | 572 | } |
| 380 | 573 | |
| 381 | 574 | static int mtk_iommu_domain_finalise(struct mtk_iommu_domain *dom, |
| 382 | 575 | struct mtk_iommu_data *data, |
| 383 | − unsigned int domid) | |
| 576 | + unsigned int region_id) | |
| 384 | 577 | { |
| 385 | 578 | const struct mtk_iommu_iova_region *region; |
| 386 | − | |
| 387 | − /* Use the exist domain as there is only one pgtable here. */ | |
| 388 | − if (data->m4u_dom) { | |
| 389 | − dom->iop = data->m4u_dom->iop; | |
| 390 | − dom->cfg = data->m4u_dom->cfg; | |
| 391 | − dom->domain.pgsize_bitmap = data->m4u_dom->cfg.pgsize_bitmap; | |
| 579 | + struct mtk_iommu_domain *m4u_dom; | |
| 580 | + | |
| 581 | + /* Always use bank0 in sharing pgtable case */ | |
| 582 | + m4u_dom = data->bank[0].m4u_dom; | |
| 583 | + if (m4u_dom) { | |
| 584 | + dom->iop = m4u_dom->iop; | |
| 585 | + dom->cfg = m4u_dom->cfg; | |
| 586 | + dom->domain.pgsize_bitmap = m4u_dom->cfg.pgsize_bitmap; | |
| 392 | 587 | goto update_iova_region; |
| 393 | 588 | } |
| 394 | 589 | |
| @@ -417,7 +612,7 @@ static int mtk_iommu_domain_finalise(struct mtk_iommu_domain *dom, · 22 unmodified lines | ||
| 417 | 612 | |
| 418 | 613 | update_iova_region: |
| 419 | 614 | /* Update the iova region for this domain */ |
| 420 | − region = data->plat_data->iova_region + domid; | |
| 615 | + region = data->plat_data->iova_region + region_id; | |
| 421 | 616 | dom->domain.geometry.aperture_start = region->iova_base; |
| 422 | 617 | dom->domain.geometry.aperture_end = region->iova_base + region->size - 1; |
| 423 | 618 | dom->domain.geometry.force_aperture = true; |
| @@ -428,12 +623,13 @@ static struct iommu_domain *mtk_iommu_domain_alloc(unsigned type) · 4 unmodified lines | ||
| 428 | 623 | { |
| 429 | 624 | struct mtk_iommu_domain *dom; |
| 430 | 625 | |
| 431 | − if (type != IOMMU_DOMAIN_DMA) | |
| 626 | + if (type != IOMMU_DOMAIN_DMA && type != IOMMU_DOMAIN_UNMANAGED) | |
| 432 | 627 | return NULL; |
| 433 | 628 | |
| 434 | 629 | dom = kzalloc(sizeof(*dom), GFP_KERNEL); |
| 435 | 630 | if (!dom) |
| 436 | 631 | return NULL; |
| 632 | + mutex_init(&dom->mutex); | |
| 437 | 633 | |
| 438 | 634 | return &dom->domain; |
| 439 | 635 | } |
| @@ -446,40 +642,60 @@ static void mtk_iommu_domain_free(struct iommu_domain *domain) · 6 unmodified lines | ||
| 446 | 642 | static int mtk_iommu_attach_device(struct iommu_domain *domain, |
| 447 | 643 | struct device *dev) |
| 448 | 644 | { |
| 449 | − struct mtk_iommu_data *data = dev_iommu_priv_get(dev); | |
| 645 | + struct mtk_iommu_data *data = dev_iommu_priv_get(dev), *frstdata; | |
| 450 | 646 | struct mtk_iommu_domain *dom = to_mtk_domain(domain); |
| 647 | + struct list_head *hw_list = data->hw_list; | |
| 451 | 648 | struct device *m4udev = data->dev; |
| 452 | − int ret, domid; | |
| 649 | + struct mtk_iommu_bank_data *bank; | |
| 650 | + unsigned int bankid; | |
| 651 | + int ret, region_id; | |
| 453 | 652 | |
| 454 | − domid = mtk_iommu_get_domain_id(dev, data->plat_data); | |
| 455 | − if (domid < 0) | |
| 456 | − return domid; | |
| 653 | + region_id = mtk_iommu_get_iova_region_id(dev, data->plat_data); | |
| 654 | + if (region_id < 0) | |
| 655 | + return region_id; | |
| 457 | 656 | |
| 458 | − if (!dom->data) { | |
| 459 | − if (mtk_iommu_domain_finalise(dom, data, domid)) | |
| 657 | + bankid = mtk_iommu_get_bank_id(dev, data->plat_data); | |
| 658 | + mutex_lock(&dom->mutex); | |
| 659 | + if (!dom->bank) { | |
| 660 | + /* Data is in the frstdata in sharing pgtable case. */ | |
| 661 | + frstdata = mtk_iommu_get_frst_data(hw_list); | |
| 662 | + | |
| 663 | + ret = mtk_iommu_domain_finalise(dom, frstdata, region_id); | |
| 664 | + if (ret) { | |
| 665 | + mutex_unlock(&dom->mutex); | |
| 460 | 666 | return -ENODEV; |
| 461 | − dom->data = data; | |
| 667 | + } | |
| 668 | + dom->bank = &data->bank[bankid]; | |
| 462 | 669 | } |
| 670 | + mutex_unlock(&dom->mutex); | |
| 463 | 671 | |
| 464 | − if (!data->m4u_dom) { /* Initialize the M4U HW */ | |
| 672 | + mutex_lock(&data->mutex); | |
| 673 | + bank = &data->bank[bankid]; | |
| 674 | + if (!bank->m4u_dom) { /* Initialize the M4U HW for each a BANK */ | |
| 465 | 675 | ret = pm_runtime_resume_and_get(m4udev); |
| 466 | − if (ret < 0) | |
| 467 | − return ret; | |
| 676 | + if (ret < 0) { | |
| 677 | + dev_err(m4udev, "pm get fail(%d) in attach.\n", ret); | |
| 678 | + goto err_unlock; | |
| 679 | + } | |
| 468 | 680 | |
| 469 | − ret = mtk_iommu_hw_init(data); | |
| 681 | + ret = mtk_iommu_hw_init(data, bankid); | |
| 470 | 682 | if (ret) { |
| 471 | 683 | pm_runtime_put(m4udev); |
| 472 | − return ret; | |
| 684 | + goto err_unlock; | |
| 473 | 685 | } |
| 474 | − data->m4u_dom = dom; | |
| 686 | + bank->m4u_dom = dom; | |
| 475 | 687 | writel(dom->cfg.arm_v7s_cfg.ttbr & MMU_PT_ADDR_MASK, |
| 476 | − data->base + REG_MMU_PT_BASE_ADDR); | |
| 688 | + bank->base + REG_MMU_PT_BASE_ADDR); | |
| 477 | 689 | |
| 478 | 690 | pm_runtime_put(m4udev); |
| 479 | 691 | } |
| 692 | + mutex_unlock(&data->mutex); | |
| 480 | 693 | |
| 481 | − mtk_iommu_config(data, dev, true, domid); | |
| 482 | − return 0; | |
| 694 | + return mtk_iommu_config(data, dev, true, region_id); | |
| 695 | + | |
| 696 | +err_unlock: | |
| 697 | + mutex_unlock(&data->mutex); | |
| 698 | + return ret; | |
| 483 | 699 | } |
| 484 | 700 | |
| 485 | 701 | static void mtk_iommu_detach_device(struct iommu_domain *domain, |
| @@ -496,7 +712,7 @@ static int mtk_iommu_map(struct iommu_domain *domain, unsigned long iova, · 10 unmodified lines | ||
| 496 | 712 | struct mtk_iommu_domain *dom = to_mtk_domain(domain); |
| 497 | 713 | |
| 498 | 714 | /* The "4GB mode" M4U physically can not use the lower remap of Dram. */ |
| 499 | − if (dom->data->enable_4GB) | |
| 715 | + if (dom->bank->parent_data->enable_4GB) | |
| 500 | 716 | paddr |= BIT_ULL(32); |
| 501 | 717 | |
| 502 | 718 | /* Synchronize with the tlb_lock */ |
| @@ -517,7 +733,7 @@ static void mtk_iommu_flush_iotlb_all(struct iommu_domain *domain) · 14 unmodified lines | ||
| 517 | 733 | { |
| 518 | 734 | struct mtk_iommu_domain *dom = to_mtk_domain(domain); |
| 519 | 735 | |
| 520 | − mtk_iommu_tlb_flush_all(dom->data); | |
| 736 | + mtk_iommu_tlb_flush_all(dom->bank->parent_data); | |
| 521 | 737 | } |
| 522 | 738 | |
| 523 | 739 | static void mtk_iommu_iotlb_sync(struct iommu_domain *domain, |
| @@ -526,8 +742,7 @@ static void mtk_iommu_iotlb_sync(struct iommu_domain *domain, · 2 unmodified lines | ||
| 526 | 742 | struct mtk_iommu_domain *dom = to_mtk_domain(domain); |
| 527 | 743 | size_t length = gather->end - gather->start + 1; |
| 528 | 744 | |
| 529 | − mtk_iommu_tlb_flush_range_sync(gather->start, length, gather->pgsize, | |
| 530 | − dom->data); | |
| 745 | + mtk_iommu_tlb_flush_range_sync(gather->start, length, dom->bank); | |
| 531 | 746 | } |
| 532 | 747 | |
| 533 | 748 | static void mtk_iommu_sync_map(struct iommu_domain *domain, unsigned long iova, |
| @@ -535,7 +750,7 @@ static void mtk_iommu_sync_map(struct iommu_domain *domain, unsigned long iova, · 1 unmodified line | ||
| 535 | 750 | { |
| 536 | 751 | struct mtk_iommu_domain *dom = to_mtk_domain(domain); |
| 537 | 752 | |
| 538 | − mtk_iommu_tlb_flush_range_sync(iova, size, size, dom->data); | |
| 753 | + mtk_iommu_tlb_flush_range_sync(iova, size, dom->bank); | |
| 539 | 754 | } |
| 540 | 755 | |
| 541 | 756 | static phys_addr_t mtk_iommu_iova_to_phys(struct iommu_domain *domain, |
| @@ -546,7 +761,7 @@ static phys_addr_t mtk_iommu_iova_to_phys(struct iommu_domain *domain, · 4 unmodified lines | ||
| 546 | 761 | |
| 547 | 762 | pa = dom->iop->iova_to_phys(dom->iop, iova); |
| 548 | 763 | if (IS_ENABLED(CONFIG_PHYS_ADDR_T_64BIT) && |
| 549 | − dom->data->enable_4GB && | |
| 764 | + dom->bank->parent_data->enable_4GB && | |
| 550 | 765 | pa >= MTK_IOMMU_4GB_MODE_REMAP_BASE) |
| 551 | 766 | pa &= ~BIT_ULL(32); |
| 552 | 767 | |
| @@ -566,12 +781,18 @@ static struct iommu_device *mtk_iommu_probe_device(struct device *dev) · 13 unmodified lines | ||
| 566 | 781 | |
| 567 | 782 | data = dev_iommu_priv_get(dev); |
| 568 | 783 | |
| 784 | + if (!MTK_IOMMU_IS_TYPE(data->plat_data, MTK_IOMMU_TYPE_MM)) | |
| 785 | + return &data->iommu; | |
| 786 | + | |
| 569 | 787 | /* |
| 570 | 788 | * Link the consumer device with the smi-larb device(supplier). |
| 571 | 789 | * The device that connects with each a larb is a independent HW. |
| 572 | 790 | * All the ports in each a device should be in the same larbs. |
| 573 | 791 | */ |
| 574 | 792 | larbid = MTK_M4U_TO_LARB(fwspec->ids[0]); |
| 793 | + if (larbid >= MTK_LARB_NR_MAX) | |
| 794 | + return ERR_PTR(-EINVAL); | |
| 795 | + | |
| 575 | 796 | for (i = 1; i < fwspec->num_ids; i++) { |
| 576 | 797 | larbidx = MTK_M4U_TO_LARB(fwspec->ids[i]); |
| 577 | 798 | if (larbid != larbidx) { |
| @@ -581,6 +802,9 @@ static struct iommu_device *mtk_iommu_probe_device(struct device *dev) · 3 unmodified lines | ||
| 581 | 802 | } |
| 582 | 803 | } |
| 583 | 804 | larbdev = data->larb_imu[larbid].dev; |
| 805 | + if (!larbdev) | |
| 806 | + return ERR_PTR(-EINVAL); | |
| 807 | + | |
| 584 | 808 | link = device_link_add(dev, larbdev, |
| 585 | 809 | DL_FLAG_PM_RUNTIME | DL_FLAG_STATELESS); |
| 586 | 810 | if (!link) |
| @@ -599,34 +823,55 @@ static void mtk_iommu_release_device(struct device *dev) · 12 unmodified lines | ||
| 599 | 823 | return; |
| 600 | 824 | |
| 601 | 825 | data = dev_iommu_priv_get(dev); |
| 602 | − larbid = MTK_M4U_TO_LARB(fwspec->ids[0]); | |
| 603 | − larbdev = data->larb_imu[larbid].dev; | |
| 604 | − device_link_remove(dev, larbdev); | |
| 826 | + if (MTK_IOMMU_IS_TYPE(data->plat_data, MTK_IOMMU_TYPE_MM)) { | |
| 827 | + larbid = MTK_M4U_TO_LARB(fwspec->ids[0]); | |
| 828 | + larbdev = data->larb_imu[larbid].dev; | |
| 829 | + device_link_remove(dev, larbdev); | |
| 830 | + } | |
| 605 | 831 | |
| 606 | 832 | iommu_fwspec_free(dev); |
| 607 | 833 | } |
| 608 | 834 | |
| 835 | +static int mtk_iommu_get_group_id(struct device *dev, const struct mtk_iommu_plat_data *plat_data) | |
| 836 | +{ | |
| 837 | + unsigned int bankid; | |
| 838 | + | |
| 839 | + /* | |
| 840 | + * If the bank function is enabled, each bank is a iommu group/domain. | |
| 841 | + * Otherwise, each iova region is a iommu group/domain. | |
| 842 | + */ | |
| 843 | + bankid = mtk_iommu_get_bank_id(dev, plat_data); | |
| 844 | + if (bankid) | |
| 845 | + return bankid; | |
| 846 | + | |
| 847 | + return mtk_iommu_get_iova_region_id(dev, plat_data); | |
| 848 | +} | |
| 849 | + | |
| 609 | 850 | static struct iommu_group *mtk_iommu_device_group(struct device *dev) |
| 610 | 851 | { |
| 611 | − struct mtk_iommu_data *data = mtk_iommu_get_m4u_data(); | |
| 852 | + struct mtk_iommu_data *c_data = dev_iommu_priv_get(dev), *data; | |
| 853 | + struct list_head *hw_list = c_data->hw_list; | |
| 612 | 854 | struct iommu_group *group; |
| 613 | − int domid; | |
| 855 | + int groupid; | |
| 614 | 856 | |
| 857 | + data = mtk_iommu_get_frst_data(hw_list); | |
| 615 | 858 | if (!data) |
| 616 | 859 | return ERR_PTR(-ENODEV); |
| 617 | 860 | |
| 618 | − domid = mtk_iommu_get_domain_id(dev, data->plat_data); | |
| 619 | − if (domid < 0) | |
| 620 | − return ERR_PTR(domid); | |
| 861 | + groupid = mtk_iommu_get_group_id(dev, data->plat_data); | |
| 862 | + if (groupid < 0) | |
| 863 | + return ERR_PTR(groupid); | |
| 621 | 864 | |
| 622 | − group = data->m4u_group[domid]; | |
| 865 | + mutex_lock(&data->mutex); | |
| 866 | + group = data->m4u_group[groupid]; | |
| 623 | 867 | if (!group) { |
| 624 | 868 | group = iommu_group_alloc(); |
| 625 | 869 | if (!IS_ERR(group)) |
| 626 | − data->m4u_group[domid] = group; | |
| 870 | + data->m4u_group[groupid] = group; | |
| 627 | 871 | } else { |
| 628 | 872 | iommu_group_ref_get(group); |
| 629 | 873 | } |
| 874 | + mutex_unlock(&data->mutex); | |
| 630 | 875 | return group; |
| 631 | 876 | } |
| 632 | 877 | |
| @@ -656,14 +901,14 @@ static void mtk_iommu_get_resv_regions(struct device *dev, · 23 unmodified lines | ||
| 656 | 901 | struct list_head *head) |
| 657 | 902 | { |
| 658 | 903 | struct mtk_iommu_data *data = dev_iommu_priv_get(dev); |
| 659 | − unsigned int domid = mtk_iommu_get_domain_id(dev, data->plat_data), i; | |
| 904 | + unsigned int regionid = mtk_iommu_get_iova_region_id(dev, data->plat_data), i; | |
| 660 | 905 | const struct mtk_iommu_iova_region *resv, *curdom; |
| 661 | 906 | struct iommu_resv_region *region; |
| 662 | 907 | int prot = IOMMU_WRITE | IOMMU_READ; |
| 663 | 908 | |
| 664 | − if ((int)domid < 0) | |
| 909 | + if ((int)regionid < 0) | |
| 665 | 910 | return; |
| 666 | − curdom = data->plat_data->iova_region + domid; | |
| 911 | + curdom = data->plat_data->iova_region + regionid; | |
| 667 | 912 | for (i = 0; i < data->plat_data->iova_region_nr; i++) { |
| 668 | 913 | resv = data->plat_data->iova_region + i; |
| 669 | 914 | |
| @@ -704,42 +949,24 @@ static const struct iommu_ops mtk_iommu_ops = { · 34 unmodified lines | ||
| 704 | 949 | } |
| 705 | 950 | }; |
| 706 | 951 | |
| 707 | −static int mtk_iommu_hw_init(const struct mtk_iommu_data *data) | |
| 952 | +static int mtk_iommu_hw_init(const struct mtk_iommu_data *data, unsigned int bankid) | |
| 708 | 953 | { |
| 954 | + const struct mtk_iommu_bank_data *bankx = &data->bank[bankid]; | |
| 955 | + const struct mtk_iommu_bank_data *bank0 = &data->bank[0]; | |
| 709 | 956 | u32 regval; |
| 710 | 957 | |
| 958 | + /* | |
| 959 | + * Global control settings are in bank0. May re-init these global registers | |
| 960 | + * since no sure if there is bank0 consumers. | |
| 961 | + */ | |
| 711 | 962 | if (data->plat_data->m4u_plat == M4U_MT8173) { |
| 712 | 963 | regval = F_MMU_PREFETCH_RT_REPLACE_MOD | |
| 713 | 964 | F_MMU_TF_PROT_TO_PROGRAM_ADDR_MT8173; |
| 714 | 965 | } else { |
| 715 | − regval = readl_relaxed(data->base + REG_MMU_CTRL_REG); | |
| 966 | + regval = readl_relaxed(bank0->base + REG_MMU_CTRL_REG); | |
| 716 | 967 | regval |= F_MMU_TF_PROT_TO_PROGRAM_ADDR; |
| 717 | 968 | } |
| 718 | − writel_relaxed(regval, data->base + REG_MMU_CTRL_REG); | |
| 719 | − | |
| 720 | − regval = F_L2_MULIT_HIT_EN | | |
| 721 | − F_TABLE_WALK_FAULT_INT_EN | | |
| 722 | − F_PREETCH_FIFO_OVERFLOW_INT_EN | | |
| 723 | − F_MISS_FIFO_OVERFLOW_INT_EN | | |
| 724 | − F_PREFETCH_FIFO_ERR_INT_EN | | |
| 725 | − F_MISS_FIFO_ERR_INT_EN; | |
| 726 | − writel_relaxed(regval, data->base + REG_MMU_INT_CONTROL0); | |
| 727 | − | |
| 728 | − regval = F_INT_TRANSLATION_FAULT | | |
| 729 | − F_INT_MAIN_MULTI_HIT_FAULT | | |
| 730 | − F_INT_INVALID_PA_FAULT | | |
| 731 | − F_INT_ENTRY_REPLACEMENT_FAULT | | |
| 732 | − F_INT_TLB_MISS_FAULT | | |
| 733 | − F_INT_MISS_TRANSACTION_FIFO_FAULT | | |
| 734 | − F_INT_PRETETCH_TRANSATION_FIFO_FAULT; | |
| 735 | − writel_relaxed(regval, data->base + REG_MMU_INT_MAIN_CONTROL); | |
| 736 | − | |
| 737 | − if (MTK_IOMMU_HAS_FLAG(data->plat_data, HAS_LEGACY_IVRP_PADDR)) | |
| 738 | − regval = (data->protect_base >> 1) | (data->enable_4GB << 31); | |
| 739 | − else | |
| 740 | − regval = lower_32_bits(data->protect_base) | | |
| 741 | − upper_32_bits(data->protect_base); | |
| 742 | − writel_relaxed(regval, data->base + REG_MMU_IVRP_PADDR); | |
| 969 | + writel_relaxed(regval, bank0->base + REG_MMU_CTRL_REG); | |
| 743 | 970 | |
| 744 | 971 | if (data->enable_4GB && |
| 745 | 972 | MTK_IOMMU_HAS_FLAG(data->plat_data, HAS_VLD_PA_RNG)) { |
| @@ -748,31 +975,61 @@ static int mtk_iommu_hw_init(const struct mtk_iommu_data *data) · 2 unmodified lines | ||
| 748 | 975 | * 0x1_0000_0000 to 0x1_ffff_ffff. here record bit[32:30]. |
| 749 | 976 | */ |
| 750 | 977 | regval = F_MMU_VLD_PA_RNG(7, 4); |
| 751 | − writel_relaxed(regval, data->base + REG_MMU_VLD_PA_RNG); | |
| 978 | + writel_relaxed(regval, bank0->base + REG_MMU_VLD_PA_RNG); | |
| 752 | 979 | } |
| 753 | − writel_relaxed(0, data->base + REG_MMU_DCM_DIS); | |
| 980 | + if (MTK_IOMMU_HAS_FLAG(data->plat_data, DCM_DISABLE)) | |
| 981 | + writel_relaxed(F_MMU_DCM, bank0->base + REG_MMU_DCM_DIS); | |
| 982 | + else | |
| 983 | + writel_relaxed(0, bank0->base + REG_MMU_DCM_DIS); | |
| 984 | + | |
| 754 | 985 | if (MTK_IOMMU_HAS_FLAG(data->plat_data, WR_THROT_EN)) { |
| 755 | 986 | /* write command throttling mode */ |
| 756 | − regval = readl_relaxed(data->base + REG_MMU_WR_LEN_CTRL); | |
| 987 | + regval = readl_relaxed(bank0->base + REG_MMU_WR_LEN_CTRL); | |
| 757 | 988 | regval &= ~F_MMU_WR_THROT_DIS_MASK; |
| 758 | − writel_relaxed(regval, data->base + REG_MMU_WR_LEN_CTRL); | |
| 989 | + writel_relaxed(regval, bank0->base + REG_MMU_WR_LEN_CTRL); | |
| 759 | 990 | } |
| 760 | 991 | |
| 761 | 992 | if (MTK_IOMMU_HAS_FLAG(data->plat_data, RESET_AXI)) { |
| 762 | 993 | /* The register is called STANDARD_AXI_MODE in this case */ |
| 763 | 994 | regval = 0; |
| 764 | 995 | } else { |
| 765 | − regval = readl_relaxed(data->base + REG_MMU_MISC_CTRL); | |
| 766 | − regval &= ~F_MMU_STANDARD_AXI_MODE_MASK; | |
| 996 | + regval = readl_relaxed(bank0->base + REG_MMU_MISC_CTRL); | |
| 997 | + if (!MTK_IOMMU_HAS_FLAG(data->plat_data, STD_AXI_MODE)) | |
| 998 | + regval &= ~F_MMU_STANDARD_AXI_MODE_MASK; | |
| 767 | 999 | if (MTK_IOMMU_HAS_FLAG(data->plat_data, OUT_ORDER_WR_EN)) |
| 768 | 1000 | regval &= ~F_MMU_IN_ORDER_WR_EN_MASK; |
| 769 | 1001 | } |
| 770 | − writel_relaxed(regval, data->base + REG_MMU_MISC_CTRL); | |
| 1002 | + writel_relaxed(regval, bank0->base + REG_MMU_MISC_CTRL); | |
| 771 | 1003 | |
| 772 | − if (devm_request_irq(data->dev, data->irq, mtk_iommu_isr, 0, | |
| 773 | − dev_name(data->dev), (void *)data)) { | |
| 774 | − writel_relaxed(0, data->base + REG_MMU_PT_BASE_ADDR); | |
| 775 | − dev_err(data->dev, "Failed @ IRQ-%d Request\n", data->irq); | |
| 1004 | + /* Independent settings for each bank */ | |
| 1005 | + regval = F_L2_MULIT_HIT_EN | | |
| 1006 | + F_TABLE_WALK_FAULT_INT_EN | | |
| 1007 | + F_PREETCH_FIFO_OVERFLOW_INT_EN | | |
| 1008 | + F_MISS_FIFO_OVERFLOW_INT_EN | | |
| 1009 | + F_PREFETCH_FIFO_ERR_INT_EN | | |
| 1010 | + F_MISS_FIFO_ERR_INT_EN; | |
| 1011 | + writel_relaxed(regval, bankx->base + REG_MMU_INT_CONTROL0); | |
| 1012 | + | |
| 1013 | + regval = F_INT_TRANSLATION_FAULT | | |
| 1014 | + F_INT_MAIN_MULTI_HIT_FAULT | | |
| 1015 | + F_INT_INVALID_PA_FAULT | | |
| 1016 | + F_INT_ENTRY_REPLACEMENT_FAULT | | |
| 1017 | + F_INT_TLB_MISS_FAULT | | |
| 1018 | + F_INT_MISS_TRANSACTION_FIFO_FAULT | | |
| 1019 | + F_INT_PRETETCH_TRANSATION_FIFO_FAULT; | |
| 1020 | + writel_relaxed(regval, bankx->base + REG_MMU_INT_MAIN_CONTROL); | |
| 1021 | + | |
| 1022 | + if (MTK_IOMMU_HAS_FLAG(data->plat_data, HAS_LEGACY_IVRP_PADDR)) | |
| 1023 | + regval = (data->protect_base >> 1) | (data->enable_4GB << 31); | |
| 1024 | + else | |
| 1025 | + regval = lower_32_bits(data->protect_base) | | |
| 1026 | + upper_32_bits(data->protect_base); | |
| 1027 | + writel_relaxed(regval, bankx->base + REG_MMU_IVRP_PADDR); | |
| 1028 | + | |
| 1029 | + if (devm_request_irq(bankx->parent_dev, bankx->irq, mtk_iommu_isr, 0, | |
| 1030 | + dev_name(bankx->parent_dev), (void *)bankx)) { | |
| 1031 | + writel_relaxed(0, bankx->base + REG_MMU_PT_BASE_ADDR); | |
| 1032 | + dev_err(bankx->parent_dev, "Failed @ IRQ-%d Request\n", bankx->irq); | |
| 776 | 1033 | return -ENODEV; |
| 777 | 1034 | } |
| 778 | 1035 | |
| @@ -784,21 +1041,91 @@ static const struct component_master_ops mtk_iommu_com_ops = { · 5 unmodified lines | ||
| 784 | 1041 | .unbind = mtk_iommu_unbind, |
| 785 | 1042 | }; |
| 786 | 1043 | |
| 1044 | +static int mtk_iommu_mm_dts_parse(struct device *dev, struct component_match **match, | |
| 1045 | + struct mtk_iommu_data *data) | |
| 1046 | +{ | |
| 1047 | + struct device_node *larbnode, *smicomm_node, *smi_subcomm_node; | |
| 1048 | + struct platform_device *plarbdev; | |
| 1049 | + struct device_link *link; | |
| 1050 | + int i, larb_nr, ret; | |
| 1051 | + | |
| 1052 | + larb_nr = of_count_phandle_with_args(dev->of_node, "mediatek,larbs", NULL); | |
| 1053 | + if (larb_nr < 0) | |
| 1054 | + return larb_nr; | |
| 1055 | + | |
| 1056 | + for (i = 0; i < larb_nr; i++) { | |
| 1057 | + u32 id; | |
| 1058 | + | |
| 1059 | + larbnode = of_parse_phandle(dev->of_node, "mediatek,larbs", i); | |
| 1060 | + if (!larbnode) | |
| 1061 | + return -EINVAL; | |
| 1062 | + | |
| 1063 | + if (!of_device_is_available(larbnode)) { | |
| 1064 | + of_node_put(larbnode); | |
| 1065 | + continue; | |
| 1066 | + } | |
| 1067 | + | |
| 1068 | + ret = of_property_read_u32(larbnode, "mediatek,larb-id", &id); | |
| 1069 | + if (ret)/* The id is consecutive if there is no this property */ | |
| 1070 | + id = i; | |
| 1071 | + | |
| 1072 | + plarbdev = of_find_device_by_node(larbnode); | |
| 1073 | + if (!plarbdev) { | |
| 1074 | + of_node_put(larbnode); | |
| 1075 | + return -ENODEV; | |
| 1076 | + } | |
| 1077 | + if (!plarbdev->dev.driver) { | |
| 1078 | + of_node_put(larbnode); | |
| 1079 | + return -EPROBE_DEFER; | |
| 1080 | + } | |
| 1081 | + data->larb_imu[id].dev = &plarbdev->dev; | |
| 1082 | + | |
| 1083 | + component_match_add_release(dev, match, component_release_of, | |
| 1084 | + component_compare_of, larbnode); | |
| 1085 | + } | |
| 1086 | + | |
| 1087 | + /* Get smi-(sub)-common dev from the last larb. */ | |
| 1088 | + smi_subcomm_node = of_parse_phandle(larbnode, "mediatek,smi", 0); | |
| 1089 | + if (!smi_subcomm_node) | |
| 1090 | + return -EINVAL; | |
| 1091 | + | |
| 1092 | + /* | |
| 1093 | + * It may have two level smi-common. the node is smi-sub-common if it | |
| 1094 | + * has a new mediatek,smi property. otherwise it is smi-commmon. | |
| 1095 | + */ | |
| 1096 | + smicomm_node = of_parse_phandle(smi_subcomm_node, "mediatek,smi", 0); | |
| 1097 | + if (smicomm_node) | |
| 1098 | + of_node_put(smi_subcomm_node); | |
| 1099 | + else | |
| 1100 | + smicomm_node = smi_subcomm_node; | |
| 1101 | + | |
| 1102 | + plarbdev = of_find_device_by_node(smicomm_node); | |
| 1103 | + of_node_put(smicomm_node); | |
| 1104 | + data->smicomm_dev = &plarbdev->dev; | |
| 1105 | + | |
| 1106 | + link = device_link_add(data->smicomm_dev, dev, | |
| 1107 | + DL_FLAG_STATELESS | DL_FLAG_PM_RUNTIME); | |
| 1108 | + if (!link) { | |
| 1109 | + dev_err(dev, "Unable to link %s.\n", dev_name(data->smicomm_dev)); | |
| 1110 | + return -EINVAL; | |
| 1111 | + } | |
| 1112 | + return 0; | |
| 1113 | +} | |
| 1114 | + | |
| 787 | 1115 | static int mtk_iommu_probe(struct platform_device *pdev) |
| 788 | 1116 | { |
| 789 | 1117 | struct mtk_iommu_data *data; |
| 790 | 1118 | struct device *dev = &pdev->dev; |
| 791 | − struct device_node *larbnode, *smicomm_node; | |
| 792 | − struct platform_device *plarbdev; | |
| 793 | − struct device_link *link; | |
| 794 | 1119 | struct resource *res; |
| 795 | 1120 | resource_size_t ioaddr; |
| 796 | 1121 | struct component_match *match = NULL; |
| 797 | 1122 | struct regmap *infracfg; |
| 798 | 1123 | void *protect; |
| 799 | − int i, larb_nr, ret; | |
| 1124 | + int ret, banks_num, i = 0; | |
| 800 | 1125 | u32 val; |
| 801 | 1126 | char *p; |
| 1127 | + struct mtk_iommu_bank_data *bank; | |
| 1128 | + void __iomem *base; | |
| 802 | 1129 | |
| 803 | 1130 | data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL); |
| 804 | 1131 | if (!data) |
| @@ -835,15 +1162,36 @@ static int mtk_iommu_probe(struct platform_device *pdev) · 30 unmodified lines | ||
| 835 | 1162 | data->enable_4GB = !!(val & F_DDR_4GB_SUPPORT_EN); |
| 836 | 1163 | } |
| 837 | 1164 | |
| 1165 | + banks_num = data->plat_data->banks_num; | |
| 838 | 1166 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
| 839 | − data->base = devm_ioremap_resource(dev, res); | |
| 840 | − if (IS_ERR(data->base)) | |
| 841 | − return PTR_ERR(data->base); | |
| 1167 | + if (resource_size(res) < banks_num * MTK_IOMMU_BANK_SZ) { | |
| 1168 | + dev_err(dev, "banknr %d. res %pR is not enough.\n", banks_num, res); | |
| 1169 | + return -EINVAL; | |
| 1170 | + } | |
| 1171 | + base = devm_ioremap_resource(dev, res); | |
| 1172 | + if (IS_ERR(base)) | |
| 1173 | + return PTR_ERR(base); | |
| 842 | 1174 | ioaddr = res->start; |
| 843 | 1175 | |
| 844 | − data->irq = platform_get_irq(pdev, 0); | |
| 845 | − if (data->irq < 0) | |
| 846 | − return data->irq; | |
| 1176 | + data->bank = devm_kmalloc(dev, banks_num * sizeof(*data->bank), GFP_KERNEL); | |
| 1177 | + if (!data->bank) | |
| 1178 | + return -ENOMEM; | |
| 1179 | + | |
| 1180 | + do { | |
| 1181 | + if (!data->plat_data->banks_enable[i]) | |
| 1182 | + continue; | |
| 1183 | + bank = &data->bank[i]; | |
| 1184 | + bank->id = i; | |
| 1185 | + bank->base = base + i * MTK_IOMMU_BANK_SZ; | |
| 1186 | + bank->m4u_dom = NULL; | |
| 1187 | + | |
| 1188 | + bank->irq = platform_get_irq(pdev, i); | |
| 1189 | + if (bank->irq < 0) | |
| 1190 | + return bank->irq; | |
| 1191 | + bank->parent_dev = dev; | |
| 1192 | + bank->parent_data = data; | |
| 1193 | + spin_lock_init(&bank->tlb_lock); | |
| 1194 | + } while (++i < banks_num); | |
| 847 | 1195 | |
| 848 | 1196 | if (MTK_IOMMU_HAS_FLAG(data->plat_data, HAS_BCLK)) { |
| 849 | 1197 | data->bclk = devm_clk_get(dev, "bclk"); |
| @@ -851,62 +1199,27 @@ static int mtk_iommu_probe(struct platform_device *pdev) · 1 unmodified line | ||
| 851 | 1199 | return PTR_ERR(data->bclk); |
| 852 | 1200 | } |
| 853 | 1201 | |
| 854 | − larb_nr = of_count_phandle_with_args(dev->of_node, | |
| 855 | − "mediatek,larbs", NULL); | |
| 856 | − if (larb_nr < 0) | |
| 857 | − return larb_nr; | |
| 858 | − | |
| 859 | − for (i = 0; i < larb_nr; i++) { | |
| 860 | − u32 id; | |
| 861 | − | |
| 862 | − larbnode = of_parse_phandle(dev->of_node, "mediatek,larbs", i); | |
| 863 | − if (!larbnode) | |
| 864 | − return -EINVAL; | |
| 865 | − | |
| 866 | − if (!of_device_is_available(larbnode)) { | |
| 867 | − of_node_put(larbnode); | |
| 868 | − continue; | |
| 869 | − } | |
| 870 | − | |
| 871 | − ret = of_property_read_u32(larbnode, "mediatek,larb-id", &id); | |
| 872 | − if (ret)/* The id is consecutive if there is no this property */ | |
| 873 | − id = i; | |
| 1202 | + pm_runtime_enable(dev); | |
| 874 | 1203 | |
| 875 | − plarbdev = of_find_device_by_node(larbnode); | |
| 876 | − if (!plarbdev) { | |
| 877 | − of_node_put(larbnode); | |
| 878 | − return -ENODEV; | |
| 1204 | + if (MTK_IOMMU_IS_TYPE(data->plat_data, MTK_IOMMU_TYPE_MM)) { | |
| 1205 | + ret = mtk_iommu_mm_dts_parse(dev, &match, data); | |
| 1206 | + if (ret) { | |
| 1207 | + dev_err(dev, "mm dts parse fail(%d).", ret); | |
| 1208 | + goto out_runtime_disable; | |
| 879 | 1209 | } |
| 880 | − if (!plarbdev->dev.driver) { | |
| 881 | − of_node_put(larbnode); | |
| 882 | − return -EPROBE_DEFER; | |
| 1210 | + } else if (MTK_IOMMU_IS_TYPE(data->plat_data, MTK_IOMMU_TYPE_INFRA) && | |
| 1211 | + data->plat_data->pericfg_comp_str) { | |
| 1212 | + infracfg = syscon_regmap_lookup_by_compatible(data->plat_data->pericfg_comp_str); | |
| 1213 | + if (IS_ERR(infracfg)) { | |
| 1214 | + ret = PTR_ERR(infracfg); | |
| 1215 | + goto out_runtime_disable; | |
| 883 | 1216 | } |
| 884 | − data->larb_imu[id].dev = &plarbdev->dev; | |
| 885 | − | |
| 886 | − component_match_add_release(dev, &match, component_release_of, | |
| 887 | − component_compare_of, larbnode); | |
| 888 | − } | |
| 889 | − | |
| 890 | − /* Get smi-common dev from the last larb. */ | |
| 891 | − smicomm_node = of_parse_phandle(larbnode, "mediatek,smi", 0); | |
| 892 | − if (!smicomm_node) | |
| 893 | − return -EINVAL; | |
| 894 | − | |
| 895 | − plarbdev = of_find_device_by_node(smicomm_node); | |
| 896 | − of_node_put(smicomm_node); | |
| 897 | − data->smicomm_dev = &plarbdev->dev; | |
| 898 | − | |
| 899 | − pm_runtime_enable(dev); | |
| 900 | 1217 | |
| 901 | − link = device_link_add(data->smicomm_dev, dev, | |
| 902 | − DL_FLAG_STATELESS | DL_FLAG_PM_RUNTIME); | |
| 903 | − if (!link) { | |
| 904 | − dev_err(dev, "Unable to link %s.\n", dev_name(data->smicomm_dev)); | |
| 905 | − ret = -EINVAL; | |
| 906 | − goto out_runtime_disable; | |
| 1218 | + data->pericfg = infracfg; | |
| 907 | 1219 | } |
| 908 | 1220 | |
| 909 | 1221 | platform_set_drvdata(pdev, data); |
| 1222 | + mutex_init(&data->mutex); | |
| 910 | 1223 | |
| 911 | 1224 | ret = iommu_device_sysfs_add(&data->iommu, dev, NULL, |
| 912 | 1225 | "mtk-iommu.%pa", &ioaddr); |
| @@ -917,8 +1230,14 @@ static int mtk_iommu_probe(struct platform_device *pdev) · 4 unmodified lines | ||
| 917 | 1230 | if (ret) |
| 918 | 1231 | goto out_sysfs_remove; |
| 919 | 1232 | |
| 920 | − spin_lock_init(&data->tlb_lock); | |
| 921 | − list_add_tail(&data->list, &m4ulist); | |
| 1233 | + if (MTK_IOMMU_HAS_FLAG(data->plat_data, SHARE_PGTABLE)) { | |
| 1234 | + list_add_tail(&data->list, data->plat_data->hw_list); | |
| 1235 | + data->hw_list = data->plat_data->hw_list; | |
| 1236 | + } else { | |
| 1237 | + INIT_LIST_HEAD(&data->hw_list_head); | |
| 1238 | + list_add_tail(&data->list, &data->hw_list_head); | |
| 1239 | + data->hw_list = &data->hw_list_head; | |
| 1240 | + } | |
| 922 | 1241 | |
| 923 | 1242 | if (!iommu_present(&platform_bus_type)) { |
| 924 | 1243 | ret = bus_set_iommu(&platform_bus_type, &mtk_iommu_ops); |
| @@ -926,9 +1245,20 @@ static int mtk_iommu_probe(struct platform_device *pdev) · 1 unmodified line | ||
| 926 | 1245 | goto out_list_del; |
| 927 | 1246 | } |
| 928 | 1247 | |
| 929 | − ret = component_master_add_with_match(dev, &mtk_iommu_com_ops, match); | |
| 930 | − if (ret) | |
| 931 | − goto out_bus_set_null; | |
| 1248 | + if (MTK_IOMMU_IS_TYPE(data->plat_data, MTK_IOMMU_TYPE_MM)) { | |
| 1249 | + ret = component_master_add_with_match(dev, &mtk_iommu_com_ops, match); | |
| 1250 | + if (ret) | |
| 1251 | + goto out_bus_set_null; | |
| 1252 | + } else if (MTK_IOMMU_IS_TYPE(data->plat_data, MTK_IOMMU_TYPE_INFRA) && | |
| 1253 | + MTK_IOMMU_HAS_FLAG(data->plat_data, IFA_IOMMU_PCIE_SUPPORT)) { | |
| 1254 | +#ifdef CONFIG_PCI | |
| 1255 | + if (!iommu_present(&pci_bus_type)) { | |
| 1256 | + ret = bus_set_iommu(&pci_bus_type, &mtk_iommu_ops); | |
| 1257 | + if (ret) /* PCIe fail don't affect platform_bus. */ | |
| 1258 | + goto out_list_del; | |
| 1259 | + } | |
| 1260 | +#endif | |
| 1261 | + } | |
| 932 | 1262 | return ret; |
| 933 | 1263 | |
| 934 | 1264 | out_bus_set_null: |
| @@ -939,7 +1269,8 @@ out_list_del: · 4 unmodified lines | ||
| 939 | 1269 | out_sysfs_remove: |
| 940 | 1270 | iommu_device_sysfs_remove(&data->iommu); |
| 941 | 1271 | out_link_remove: |
| 942 | − device_link_remove(data->smicomm_dev, dev); | |
| 1272 | + if (MTK_IOMMU_IS_TYPE(data->plat_data, MTK_IOMMU_TYPE_MM)) | |
| 1273 | + device_link_remove(data->smicomm_dev, dev); | |
| 943 | 1274 | out_runtime_disable: |
| 944 | 1275 | pm_runtime_disable(dev); |
| 945 | 1276 | return ret; |
| @@ -948,18 +1279,30 @@ out_runtime_disable: · 2 unmodified lines | ||
| 948 | 1279 | static int mtk_iommu_remove(struct platform_device *pdev) |
| 949 | 1280 | { |
| 950 | 1281 | struct mtk_iommu_data *data = platform_get_drvdata(pdev); |
| 1282 | + struct mtk_iommu_bank_data *bank; | |
| 1283 | + int i; | |
| 951 | 1284 | |
| 952 | 1285 | iommu_device_sysfs_remove(&data->iommu); |
| 953 | 1286 | iommu_device_unregister(&data->iommu); |
| 954 | 1287 | |
| 955 | − if (iommu_present(&platform_bus_type)) | |
| 956 | − bus_set_iommu(&platform_bus_type, NULL); | |
| 1288 | + list_del(&data->list); | |
| 957 | 1289 | |
| 958 | − clk_disable_unprepare(data->bclk); | |
| 959 | − device_link_remove(data->smicomm_dev, &pdev->dev); | |
| 1290 | + if (MTK_IOMMU_IS_TYPE(data->plat_data, MTK_IOMMU_TYPE_MM)) { | |
| 1291 | + device_link_remove(data->smicomm_dev, &pdev->dev); | |
| 1292 | + component_master_del(&pdev->dev, &mtk_iommu_com_ops); | |
| 1293 | + } else if (MTK_IOMMU_IS_TYPE(data->plat_data, MTK_IOMMU_TYPE_INFRA) && | |
| 1294 | + MTK_IOMMU_HAS_FLAG(data->plat_data, IFA_IOMMU_PCIE_SUPPORT)) { | |
| 1295 | +#ifdef CONFIG_PCI | |
| 1296 | + bus_set_iommu(&pci_bus_type, NULL); | |
| 1297 | +#endif | |
| 1298 | + } | |
| 960 | 1299 | pm_runtime_disable(&pdev->dev); |
| 961 | − devm_free_irq(&pdev->dev, data->irq, data); | |
| 962 | − component_master_del(&pdev->dev, &mtk_iommu_com_ops); | |
| 1300 | + for (i = 0; i < data->plat_data->banks_num; i++) { | |
| 1301 | + bank = &data->bank[i]; | |
| 1302 | + if (!bank->m4u_dom) | |
| 1303 | + continue; | |
| 1304 | + devm_free_irq(&pdev->dev, bank->irq, bank); | |
| 1305 | + } | |
| 963 | 1306 | return 0; |
| 964 | 1307 | } |
| 965 | 1308 | |
| @@ -967,16 +1310,23 @@ static int __maybe_unused mtk_iommu_runtime_suspend(struct device *dev) · 1 unmodified line | ||
| 967 | 1310 | { |
| 968 | 1311 | struct mtk_iommu_data *data = dev_get_drvdata(dev); |
| 969 | 1312 | struct mtk_iommu_suspend_reg *reg = &data->reg; |
| 970 | − void __iomem *base = data->base; | |
| 1313 | + void __iomem *base; | |
| 1314 | + int i = 0; | |
| 971 | 1315 | |
| 1316 | + base = data->bank[i].base; | |
| 972 | 1317 | reg->wr_len_ctrl = readl_relaxed(base + REG_MMU_WR_LEN_CTRL); |
| 973 | 1318 | reg->misc_ctrl = readl_relaxed(base + REG_MMU_MISC_CTRL); |
| 974 | 1319 | reg->dcm_dis = readl_relaxed(base + REG_MMU_DCM_DIS); |
| 975 | 1320 | reg->ctrl_reg = readl_relaxed(base + REG_MMU_CTRL_REG); |
| 976 | − reg->int_control0 = readl_relaxed(base + REG_MMU_INT_CONTROL0); | |
| 977 | − reg->int_main_control = readl_relaxed(base + REG_MMU_INT_MAIN_CONTROL); | |
| 978 | − reg->ivrp_paddr = readl_relaxed(base + REG_MMU_IVRP_PADDR); | |
| 979 | 1321 | reg->vld_pa_rng = readl_relaxed(base + REG_MMU_VLD_PA_RNG); |
| 1322 | + do { | |
| 1323 | + if (!data->plat_data->banks_enable[i]) | |
| 1324 | + continue; | |
| 1325 | + base = data->bank[i].base; | |
| 1326 | + reg->int_control[i] = readl_relaxed(base + REG_MMU_INT_CONTROL0); | |
| 1327 | + reg->int_main_control[i] = readl_relaxed(base + REG_MMU_INT_MAIN_CONTROL); | |
| 1328 | + reg->ivrp_paddr[i] = readl_relaxed(base + REG_MMU_IVRP_PADDR); | |
| 1329 | + } while (++i < data->plat_data->banks_num); | |
| 980 | 1330 | clk_disable_unprepare(data->bclk); |
| 981 | 1331 | return 0; |
| 982 | 1332 | } |
| @@ -985,9 +1335,9 @@ static int __maybe_unused mtk_iommu_runtime_resume(struct device *dev) · 2 unmodified lines | ||
| 985 | 1335 | { |
| 986 | 1336 | struct mtk_iommu_data *data = dev_get_drvdata(dev); |
| 987 | 1337 | struct mtk_iommu_suspend_reg *reg = &data->reg; |
| 988 | − struct mtk_iommu_domain *m4u_dom = data->m4u_dom; | |
| 989 | − void __iomem *base = data->base; | |
| 990 | − int ret; | |
| 1338 | + struct mtk_iommu_domain *m4u_dom; | |
| 1339 | + void __iomem *base; | |
| 1340 | + int ret, i = 0; | |
| 991 | 1341 | |
| 992 | 1342 | ret = clk_prepare_enable(data->bclk); |
| 993 | 1343 | if (ret) { |
| @@ -999,18 +1349,26 @@ static int __maybe_unused mtk_iommu_runtime_resume(struct device *dev) · 5 unmodified lines | ||
| 999 | 1349 | * Uppon first resume, only enable the clk and return, since the values of the |
| 1000 | 1350 | * registers are not yet set. |
| 1001 | 1351 | */ |
| 1002 | − if (!m4u_dom) | |
| 1352 | + if (!reg->wr_len_ctrl) | |
| 1003 | 1353 | return 0; |
| 1004 | 1354 | |
| 1355 | + base = data->bank[i].base; | |
| 1005 | 1356 | writel_relaxed(reg->wr_len_ctrl, base + REG_MMU_WR_LEN_CTRL); |
| 1006 | 1357 | writel_relaxed(reg->misc_ctrl, base + REG_MMU_MISC_CTRL); |
| 1007 | 1358 | writel_relaxed(reg->dcm_dis, base + REG_MMU_DCM_DIS); |
| 1008 | 1359 | writel_relaxed(reg->ctrl_reg, base + REG_MMU_CTRL_REG); |
| 1009 | − writel_relaxed(reg->int_control0, base + REG_MMU_INT_CONTROL0); | |
| 1010 | − writel_relaxed(reg->int_main_control, base + REG_MMU_INT_MAIN_CONTROL); | |
| 1011 | − writel_relaxed(reg->ivrp_paddr, base + REG_MMU_IVRP_PADDR); | |
| 1012 | 1360 | writel_relaxed(reg->vld_pa_rng, base + REG_MMU_VLD_PA_RNG); |
| 1013 | − writel(m4u_dom->cfg.arm_v7s_cfg.ttbr & MMU_PT_ADDR_MASK, base + REG_MMU_PT_BASE_ADDR); | |
| 1361 | + do { | |
| 1362 | + m4u_dom = data->bank[i].m4u_dom; | |
| 1363 | + if (!data->plat_data->banks_enable[i] || !m4u_dom) | |
| 1364 | + continue; | |
| 1365 | + base = data->bank[i].base; | |
| 1366 | + writel_relaxed(reg->int_control[i], base + REG_MMU_INT_CONTROL0); | |
| 1367 | + writel_relaxed(reg->int_main_control[i], base + REG_MMU_INT_MAIN_CONTROL); | |
| 1368 | + writel_relaxed(reg->ivrp_paddr[i], base + REG_MMU_IVRP_PADDR); | |
| 1369 | + writel(m4u_dom->cfg.arm_v7s_cfg.ttbr & MMU_PT_ADDR_MASK, | |
| 1370 | + base + REG_MMU_PT_BASE_ADDR); | |
| 1371 | + } while (++i < data->plat_data->banks_num); | |
| 1014 | 1372 | |
| 1015 | 1373 | /* |
| 1016 | 1374 | * Users may allocate dma buffer before they call pm_runtime_get, |
| @@ -1029,17 +1387,24 @@ static const struct dev_pm_ops mtk_iommu_pm_ops = { · 12 unmodified lines | ||
| 1029 | 1387 | |
| 1030 | 1388 | static const struct mtk_iommu_plat_data mt2712_data = { |
| 1031 | 1389 | .m4u_plat = M4U_MT2712, |
| 1032 | − .flags = HAS_4GB_MODE | HAS_BCLK | HAS_VLD_PA_RNG, | |
| 1390 | + .flags = HAS_4GB_MODE | HAS_BCLK | HAS_VLD_PA_RNG | SHARE_PGTABLE | | |
| 1391 | + MTK_IOMMU_TYPE_MM, | |
| 1392 | + .hw_list = &m4ulist, | |
| 1033 | 1393 | .inv_sel_reg = REG_MMU_INV_SEL_GEN1, |
| 1034 | 1394 | .iova_region = single_domain, |
| 1395 | + .banks_num = 1, | |
| 1396 | + .banks_enable = {true}, | |
| 1035 | 1397 | .iova_region_nr = ARRAY_SIZE(single_domain), |
| 1036 | 1398 | .larbid_remap = {{0}, {1}, {2}, {3}, {4}, {5}, {6}, {7}}, |
| 1037 | 1399 | }; |
| 1038 | 1400 | |
| 1039 | 1401 | static const struct mtk_iommu_plat_data mt6779_data = { |
| 1040 | 1402 | .m4u_plat = M4U_MT6779, |
| 1041 | − .flags = HAS_SUB_COMM | OUT_ORDER_WR_EN | WR_THROT_EN, | |
| 1403 | + .flags = HAS_SUB_COMM_2BITS | OUT_ORDER_WR_EN | WR_THROT_EN | | |
| 1404 | + MTK_IOMMU_TYPE_MM, | |
| 1042 | 1405 | .inv_sel_reg = REG_MMU_INV_SEL_GEN2, |
| 1406 | + .banks_num = 1, | |
| 1407 | + .banks_enable = {true}, | |
| 1043 | 1408 | .iova_region = single_domain, |
| 1044 | 1409 | .iova_region_nr = ARRAY_SIZE(single_domain), |
| 1045 | 1410 | .larbid_remap = {{0}, {1}, {2}, {3}, {5}, {7, 8}, {10}, {9}}, |
| @@ -1047,8 +1412,10 @@ static const struct mtk_iommu_plat_data mt6779_data = { · 1 unmodified line | ||
| 1047 | 1412 | |
| 1048 | 1413 | static const struct mtk_iommu_plat_data mt8167_data = { |
| 1049 | 1414 | .m4u_plat = M4U_MT8167, |
| 1050 | − .flags = RESET_AXI | HAS_LEGACY_IVRP_PADDR, | |
| 1415 | + .flags = RESET_AXI | HAS_LEGACY_IVRP_PADDR | MTK_IOMMU_TYPE_MM, | |
| 1051 | 1416 | .inv_sel_reg = REG_MMU_INV_SEL_GEN1, |
| 1417 | + .banks_num = 1, | |
| 1418 | + .banks_enable = {true}, | |
| 1052 | 1419 | .iova_region = single_domain, |
| 1053 | 1420 | .iova_region_nr = ARRAY_SIZE(single_domain), |
| 1054 | 1421 | .larbid_remap = {{0}, {1}, {2}}, /* Linear mapping. */ |
| @@ -1057,8 +1424,10 @@ static const struct mtk_iommu_plat_data mt8167_data = { · 2 unmodified lines | ||
| 1057 | 1424 | static const struct mtk_iommu_plat_data mt8173_data = { |
| 1058 | 1425 | .m4u_plat = M4U_MT8173, |
| 1059 | 1426 | .flags = HAS_4GB_MODE | HAS_BCLK | RESET_AXI | |
| 1060 | − HAS_LEGACY_IVRP_PADDR, | |
| 1427 | + HAS_LEGACY_IVRP_PADDR | MTK_IOMMU_TYPE_MM, | |
| 1061 | 1428 | .inv_sel_reg = REG_MMU_INV_SEL_GEN1, |
| 1429 | + .banks_num = 1, | |
| 1430 | + .banks_enable = {true}, | |
| 1062 | 1431 | .iova_region = single_domain, |
| 1063 | 1432 | .iova_region_nr = ARRAY_SIZE(single_domain), |
| 1064 | 1433 | .larbid_remap = {{0}, {1}, {2}, {3}, {4}, {5}}, /* Linear mapping. */ |
| @@ -1066,31 +1435,100 @@ static const struct mtk_iommu_plat_data mt8173_data = { · 1 unmodified line | ||
| 1066 | 1435 | |
| 1067 | 1436 | static const struct mtk_iommu_plat_data mt8183_data = { |
| 1068 | 1437 | .m4u_plat = M4U_MT8183, |
| 1069 | − .flags = RESET_AXI, | |
| 1438 | + .flags = RESET_AXI | MTK_IOMMU_TYPE_MM, | |
| 1070 | 1439 | .inv_sel_reg = REG_MMU_INV_SEL_GEN1, |
| 1440 | + .banks_num = 1, | |
| 1441 | + .banks_enable = {true}, | |
| 1071 | 1442 | .iova_region = single_domain, |
| 1072 | 1443 | .iova_region_nr = ARRAY_SIZE(single_domain), |
| 1073 | 1444 | .larbid_remap = {{0}, {4}, {5}, {6}, {7}, {2}, {3}, {1}}, |
| 1074 | 1445 | }; |
| 1075 | 1446 | |
| 1447 | +static const struct mtk_iommu_plat_data mt8186_data_mm = { | |
| 1448 | + .m4u_plat = M4U_MT8186, | |
| 1449 | + .flags = HAS_BCLK | HAS_SUB_COMM_2BITS | OUT_ORDER_WR_EN | | |
| 1450 | + WR_THROT_EN | IOVA_34_EN | MTK_IOMMU_TYPE_MM, | |
| 1451 | + .larbid_remap = {{0}, {1, MTK_INVALID_LARBID, 8}, {4}, {7}, {2}, {9, 11, 19, 20}, | |
| 1452 | + {MTK_INVALID_LARBID, 14, 16}, | |
| 1453 | + {MTK_INVALID_LARBID, 13, MTK_INVALID_LARBID, 17}}, | |
| 1454 | + .inv_sel_reg = REG_MMU_INV_SEL_GEN2, | |
| 1455 | + .banks_num = 1, | |
| 1456 | + .banks_enable = {true}, | |
| 1457 | + .iova_region = mt8192_multi_dom, | |
| 1458 | + .iova_region_nr = ARRAY_SIZE(mt8192_multi_dom), | |
| 1459 | +}; | |
| 1460 | + | |
| 1076 | 1461 | static const struct mtk_iommu_plat_data mt8192_data = { |
| 1077 | 1462 | .m4u_plat = M4U_MT8192, |
| 1078 | − .flags = HAS_BCLK | HAS_SUB_COMM | OUT_ORDER_WR_EN | | |
| 1079 | − WR_THROT_EN | IOVA_34_EN, | |
| 1463 | + .flags = HAS_BCLK | HAS_SUB_COMM_2BITS | OUT_ORDER_WR_EN | | |
| 1464 | + WR_THROT_EN | IOVA_34_EN | MTK_IOMMU_TYPE_MM, | |
| 1080 | 1465 | .inv_sel_reg = REG_MMU_INV_SEL_GEN2, |
| 1466 | + .banks_num = 1, | |
| 1467 | + .banks_enable = {true}, | |
| 1081 | 1468 | .iova_region = mt8192_multi_dom, |
| 1082 | 1469 | .iova_region_nr = ARRAY_SIZE(mt8192_multi_dom), |
| 1083 | 1470 | .larbid_remap = {{0}, {1}, {4, 5}, {7}, {2}, {9, 11, 19, 20}, |
| 1084 | 1471 | {0, 14, 16}, {0, 13, 18, 17}}, |
| 1085 | 1472 | }; |
| 1086 | 1473 | |
| 1474 | +static const struct mtk_iommu_plat_data mt8195_data_infra = { | |
| 1475 | + .m4u_plat = M4U_MT8195, | |
| 1476 | + .flags = WR_THROT_EN | DCM_DISABLE | STD_AXI_MODE | PM_CLK_AO | | |
| 1477 | + MTK_IOMMU_TYPE_INFRA | IFA_IOMMU_PCIE_SUPPORT, | |
| 1478 | + .pericfg_comp_str = "mediatek,mt8195-pericfg_ao", | |
| 1479 | + .inv_sel_reg = REG_MMU_INV_SEL_GEN2, | |
| 1480 | + .banks_num = 5, | |
| 1481 | + .banks_enable = {true, false, false, false, true}, | |
| 1482 | + .banks_portmsk = {[0] = GENMASK(19, 16), /* PCIe */ | |
| 1483 | + [4] = GENMASK(31, 20), /* USB */ | |
| 1484 | + }, | |
| 1485 | + .iova_region = single_domain, | |
| 1486 | + .iova_region_nr = ARRAY_SIZE(single_domain), | |
| 1487 | +}; | |
| 1488 | + | |
| 1489 | +static const struct mtk_iommu_plat_data mt8195_data_vdo = { | |
| 1490 | + .m4u_plat = M4U_MT8195, | |
| 1491 | + .flags = HAS_BCLK | HAS_SUB_COMM_2BITS | OUT_ORDER_WR_EN | | |
| 1492 | + WR_THROT_EN | IOVA_34_EN | SHARE_PGTABLE | MTK_IOMMU_TYPE_MM, | |
| 1493 | + .hw_list = &m4ulist, | |
| 1494 | + .inv_sel_reg = REG_MMU_INV_SEL_GEN2, | |
| 1495 | + .banks_num = 1, | |
| 1496 | + .banks_enable = {true}, | |
| 1497 | + .iova_region = mt8192_multi_dom, | |
| 1498 | + .iova_region_nr = ARRAY_SIZE(mt8192_multi_dom), | |
| 1499 | + .larbid_remap = {{2, 0}, {21}, {24}, {7}, {19}, {9, 10, 11}, | |
| 1500 | + {13, 17, 15/* 17b */, 25}, {5}}, | |
| 1501 | +}; | |
| 1502 | + | |
| 1503 | +static const struct mtk_iommu_plat_data mt8195_data_vpp = { | |
| 1504 | + .m4u_plat = M4U_MT8195, | |
| 1505 | + .flags = HAS_BCLK | HAS_SUB_COMM_3BITS | OUT_ORDER_WR_EN | | |
| 1506 | + WR_THROT_EN | IOVA_34_EN | SHARE_PGTABLE | MTK_IOMMU_TYPE_MM, | |
| 1507 | + .hw_list = &m4ulist, | |
| 1508 | + .inv_sel_reg = REG_MMU_INV_SEL_GEN2, | |
| 1509 | + .banks_num = 1, | |
| 1510 | + .banks_enable = {true}, | |
| 1511 | + .iova_region = mt8192_multi_dom, | |
| 1512 | + .iova_region_nr = ARRAY_SIZE(mt8192_multi_dom), | |
| 1513 | + .larbid_remap = {{1}, {3}, | |
| 1514 | + {22, MTK_INVALID_LARBID, MTK_INVALID_LARBID, MTK_INVALID_LARBID, 23}, | |
| 1515 | + {8}, {20}, {12}, | |
| 1516 | + /* 16: 16a; 29: 16b; 30: CCUtop0; 31: CCUtop1 */ | |
| 1517 | + {14, 16, 29, 26, 30, 31, 18}, | |
| 1518 | + {4, MTK_INVALID_LARBID, MTK_INVALID_LARBID, MTK_INVALID_LARBID, 6}}, | |
| 1519 | +}; | |
| 1520 | + | |
| 1087 | 1521 | static const struct of_device_id mtk_iommu_of_ids[] = { |
| 1088 | 1522 | { .compatible = "mediatek,mt2712-m4u", .data = &mt2712_data}, |
| 1089 | 1523 | { .compatible = "mediatek,mt6779-m4u", .data = &mt6779_data}, |
| 1090 | 1524 | { .compatible = "mediatek,mt8167-m4u", .data = &mt8167_data}, |
| 1091 | 1525 | { .compatible = "mediatek,mt8173-m4u", .data = &mt8173_data}, |
| 1092 | 1526 | { .compatible = "mediatek,mt8183-m4u", .data = &mt8183_data}, |
| 1527 | + { .compatible = "mediatek,mt8186-iommu-mm", .data = &mt8186_data_mm}, /* mm: m4u */ | |
| 1093 | 1528 | { .compatible = "mediatek,mt8192-m4u", .data = &mt8192_data}, |
| 1529 | + { .compatible = "mediatek,mt8195-iommu-infra", .data = &mt8195_data_infra}, | |
| 1530 | + { .compatible = "mediatek,mt8195-iommu-vdo", .data = &mt8195_data_vdo}, | |
| 1531 | + { .compatible = "mediatek,mt8195-iommu-vpp", .data = &mt8195_data_vpp}, | |
| 1094 | 1532 | {} |
| 1095 | 1533 | }; |
| 1096 | 1534 | |
| @@ -1,101 +0,0 @@ | ||
| 1 | −/* SPDX-License-Identifier: GPL-2.0-only */ | |
| 2 | −/* | |
| 3 | − * Copyright (c) 2015-2016 MediaTek Inc. | |
| 4 | − * Author: Honghui Zhang <honghui.zhang@mediatek.com> | |
| 5 | − */ | |
| 6 | − | |
| 7 | −#ifndef _MTK_IOMMU_H_ | |
| 8 | −#define _MTK_IOMMU_H_ | |
| 9 | − | |
| 10 | −#include <linux/clk.h> | |
| 11 | −#include <linux/component.h> | |
| 12 | −#include <linux/device.h> | |
| 13 | −#include <linux/io.h> | |
| 14 | −#include <linux/io-pgtable.h> | |
| 15 | −#include <linux/iommu.h> | |
| 16 | −#include <linux/list.h> | |
| 17 | −#include <linux/spinlock.h> | |
| 18 | −#include <linux/dma-mapping.h> | |
| 19 | −#include <soc/mediatek/smi.h> | |
| 20 | −#include <dt-bindings/memory/mtk-memory-port.h> | |
| 21 | − | |
| 22 | −#define MTK_LARB_COM_MAX 8 | |
| 23 | −#define MTK_LARB_SUBCOM_MAX 4 | |
| 24 | − | |
| 25 | −#define MTK_IOMMU_GROUP_MAX 8 | |
| 26 | − | |
| 27 | −struct mtk_iommu_suspend_reg { | |
| 28 | − union { | |
| 29 | − u32 standard_axi_mode;/* v1 */ | |
| 30 | − u32 misc_ctrl;/* v2 */ | |
| 31 | − }; | |
| 32 | − u32 dcm_dis; | |
| 33 | − u32 ctrl_reg; | |
| 34 | − u32 int_control0; | |
| 35 | − u32 int_main_control; | |
| 36 | − u32 ivrp_paddr; | |
| 37 | − u32 vld_pa_rng; | |
| 38 | − u32 wr_len_ctrl; | |
| 39 | −}; | |
| 40 | − | |
| 41 | −enum mtk_iommu_plat { | |
| 42 | − M4U_MT2701, | |
| 43 | − M4U_MT2712, | |
| 44 | − M4U_MT6779, | |
| 45 | − M4U_MT8167, | |
| 46 | − M4U_MT8173, | |
| 47 | − M4U_MT8183, | |
| 48 | − M4U_MT8192, | |
| 49 | −}; | |
| 50 | − | |
| 51 | −struct mtk_iommu_iova_region; | |
| 52 | − | |
| 53 | −struct mtk_iommu_plat_data { | |
| 54 | − enum mtk_iommu_plat m4u_plat; | |
| 55 | − u32 flags; | |
| 56 | − u32 inv_sel_reg; | |
| 57 | − | |
| 58 | − unsigned int iova_region_nr; | |
| 59 | − const struct mtk_iommu_iova_region *iova_region; | |
| 60 | − unsigned char larbid_remap[MTK_LARB_COM_MAX][MTK_LARB_SUBCOM_MAX]; | |
| 61 | −}; | |
| 62 | − | |
| 63 | −struct mtk_iommu_domain; | |
| 64 | − | |
| 65 | −struct mtk_iommu_data { | |
| 66 | − void __iomem *base; | |
| 67 | − int irq; | |
| 68 | − struct device *dev; | |
| 69 | − struct clk *bclk; | |
| 70 | − phys_addr_t protect_base; /* protect memory base */ | |
| 71 | − struct mtk_iommu_suspend_reg reg; | |
| 72 | − struct mtk_iommu_domain *m4u_dom; | |
| 73 | − struct iommu_group *m4u_group[MTK_IOMMU_GROUP_MAX]; | |
| 74 | − bool enable_4GB; | |
| 75 | − spinlock_t tlb_lock; /* lock for tlb range flush */ | |
| 76 | − | |
| 77 | − struct iommu_device iommu; | |
| 78 | − const struct mtk_iommu_plat_data *plat_data; | |
| 79 | − struct device *smicomm_dev; | |
| 80 | − | |
| 81 | − struct dma_iommu_mapping *mapping; /* For mtk_iommu_v1.c */ | |
| 82 | − | |
| 83 | − struct list_head list; | |
| 84 | − struct mtk_smi_larb_iommu larb_imu[MTK_LARB_NR_MAX]; | |
| 85 | −}; | |
| 86 | − | |
| 87 | −static inline int mtk_iommu_bind(struct device *dev) | |
| 88 | −{ | |
| 89 | − struct mtk_iommu_data *data = dev_get_drvdata(dev); | |
| 90 | − | |
| 91 | − return component_bind_all(dev, &data->larb_imu); | |
| 92 | −} | |
| 93 | − | |
| 94 | −static inline void mtk_iommu_unbind(struct device *dev) | |
| 95 | −{ | |
| 96 | − struct mtk_iommu_data *data = dev_get_drvdata(dev); | |
| 97 | − | |
| 98 | − component_unbind_all(dev, &data->larb_imu); | |
| 99 | −} | |
| 100 | − | |
| 101 | −#endif | |
| @@ -7,7 +7,6 @@ · 6 unmodified lines | ||
| 7 | 7 | * |
| 8 | 8 | * Based on driver/iommu/mtk_iommu.c |
| 9 | 9 | */ |
| 10 | −#include <linux/memblock.h> | |
| 11 | 10 | #include <linux/bug.h> |
| 12 | 11 | #include <linux/clk.h> |
| 13 | 12 | #include <linux/component.h> |
| @@ -28,10 +27,9 @@ · 14 unmodified lines | ||
| 28 | 27 | #include <linux/spinlock.h> |
| 29 | 28 | #include <asm/barrier.h> |
| 30 | 29 | #include <asm/dma-iommu.h> |
| 31 | −#include <linux/init.h> | |
| 30 | +#include <dt-bindings/memory/mtk-memory-port.h> | |
| 32 | 31 | #include <dt-bindings/memory/mt2701-larb-port.h> |
| 33 | 32 | #include <soc/mediatek/smi.h> |
| 34 | −#include "mtk_iommu.h" | |
| 35 | 33 | |
| 36 | 34 | #define REG_MMU_PT_BASE_ADDR 0x000 |
| 37 | 35 | |
| @@ -80,6 +78,7 @@ · 42 unmodified lines | ||
| 80 | 78 | /* MTK generation one iommu HW only support 4K size mapping */ |
| 81 | 79 | #define MT2701_IOMMU_PAGE_SHIFT 12 |
| 82 | 80 | #define MT2701_IOMMU_PAGE_SIZE (1UL << MT2701_IOMMU_PAGE_SHIFT) |
| 81 | +#define MT2701_LARB_NR_MAX 3 | |
| 83 | 82 | |
| 84 | 83 | /* |
| 85 | 84 | * MTK m4u support 4GB iova address space, and only support 4K page |
| @@ -87,17 +86,53 @@ · 1 unmodified line | ||
| 87 | 86 | */ |
| 88 | 87 | #define M2701_IOMMU_PGT_SIZE SZ_4M |
| 89 | 88 | |
| 90 | −struct mtk_iommu_domain { | |
| 89 | +struct mtk_iommu_v1_suspend_reg { | |
| 90 | + u32 standard_axi_mode; | |
| 91 | + u32 dcm_dis; | |
| 92 | + u32 ctrl_reg; | |
| 93 | + u32 int_control0; | |
| 94 | +}; | |
| 95 | + | |
| 96 | +struct mtk_iommu_v1_data { | |
| 97 | + void __iomem *base; | |
| 98 | + int irq; | |
| 99 | + struct device *dev; | |
| 100 | + struct clk *bclk; | |
| 101 | + phys_addr_t protect_base; /* protect memory base */ | |
| 102 | + struct mtk_iommu_v1_domain *m4u_dom; | |
| 103 | + | |
| 104 | + struct iommu_device iommu; | |
| 105 | + struct dma_iommu_mapping *mapping; | |
| 106 | + struct mtk_smi_larb_iommu larb_imu[MTK_LARB_NR_MAX]; | |
| 107 | + | |
| 108 | + struct mtk_iommu_v1_suspend_reg reg; | |
| 109 | +}; | |
| 110 | + | |
| 111 | +struct mtk_iommu_v1_domain { | |
| 91 | 112 | spinlock_t pgtlock; /* lock for page table */ |
| 92 | 113 | struct iommu_domain domain; |
| 93 | 114 | u32 *pgt_va; |
| 94 | 115 | dma_addr_t pgt_pa; |
| 95 | − struct mtk_iommu_data *data; | |
| 116 | + struct mtk_iommu_v1_data *data; | |
| 96 | 117 | }; |
| 97 | 118 | |
| 98 | −static struct mtk_iommu_domain *to_mtk_domain(struct iommu_domain *dom) | |
| 119 | +static int mtk_iommu_v1_bind(struct device *dev) | |
| 120 | +{ | |
| 121 | + struct mtk_iommu_v1_data *data = dev_get_drvdata(dev); | |
| 122 | + | |
| 123 | + return component_bind_all(dev, &data->larb_imu); | |
| 124 | +} | |
| 125 | + | |
| 126 | +static void mtk_iommu_v1_unbind(struct device *dev) | |
| 127 | +{ | |
| 128 | + struct mtk_iommu_v1_data *data = dev_get_drvdata(dev); | |
| 129 | + | |
| 130 | + component_unbind_all(dev, &data->larb_imu); | |
| 131 | +} | |
| 132 | + | |
| 133 | +static struct mtk_iommu_v1_domain *to_mtk_domain(struct iommu_domain *dom) | |
| 99 | 134 | { |
| 100 | − return container_of(dom, struct mtk_iommu_domain, domain); | |
| 135 | + return container_of(dom, struct mtk_iommu_v1_domain, domain); | |
| 101 | 136 | } |
| 102 | 137 | |
| 103 | 138 | static const int mt2701_m4u_in_larb[] = { |
| @@ -123,7 +158,7 @@ static inline int mt2701_m4u_to_port(int id) · 19 unmodified lines | ||
| 123 | 158 | return id - mt2701_m4u_in_larb[larb]; |
| 124 | 159 | } |
| 125 | 160 | |
| 126 | −static void mtk_iommu_tlb_flush_all(struct mtk_iommu_data *data) | |
| 161 | +static void mtk_iommu_v1_tlb_flush_all(struct mtk_iommu_v1_data *data) | |
| 127 | 162 | { |
| 128 | 163 | writel_relaxed(F_INVLD_EN1 | F_INVLD_EN0, |
| 129 | 164 | data->base + REG_MMU_INV_SEL); |
| @@ -131,8 +166,8 @@ static void mtk_iommu_tlb_flush_all(struct mtk_iommu_data *data) · 1 unmodified line | ||
| 131 | 166 | wmb(); /* Make sure the tlb flush all done */ |
| 132 | 167 | } |
| 133 | 168 | |
| 134 | −static void mtk_iommu_tlb_flush_range(struct mtk_iommu_data *data, | |
| 135 | − unsigned long iova, size_t size) | |
| 169 | +static void mtk_iommu_v1_tlb_flush_range(struct mtk_iommu_v1_data *data, | |
| 170 | + unsigned long iova, size_t size) | |
| 136 | 171 | { |
| 137 | 172 | int ret; |
| 138 | 173 | u32 tmp; |
| @@ -150,16 +185,16 @@ static void mtk_iommu_tlb_flush_range(struct mtk_iommu_data *data, · 11 unmodified lines | ||
| 150 | 185 | if (ret) { |
| 151 | 186 | dev_warn(data->dev, |
| 152 | 187 | "Partial TLB flush timed out, falling back to full flush\n"); |
| 153 | − mtk_iommu_tlb_flush_all(data); | |
| 188 | + mtk_iommu_v1_tlb_flush_all(data); | |
| 154 | 189 | } |
| 155 | 190 | /* Clear the CPE status */ |
| 156 | 191 | writel_relaxed(0, data->base + REG_MMU_CPE_DONE); |
| 157 | 192 | } |
| 158 | 193 | |
| 159 | −static irqreturn_t mtk_iommu_isr(int irq, void *dev_id) | |
| 194 | +static irqreturn_t mtk_iommu_v1_isr(int irq, void *dev_id) | |
| 160 | 195 | { |
| 161 | − struct mtk_iommu_data *data = dev_id; | |
| 162 | − struct mtk_iommu_domain *dom = data->m4u_dom; | |
| 196 | + struct mtk_iommu_v1_data *data = dev_id; | |
| 197 | + struct mtk_iommu_v1_domain *dom = data->m4u_dom; | |
| 163 | 198 | u32 int_state, regval, fault_iova, fault_pa; |
| 164 | 199 | unsigned int fault_larb, fault_port; |
| 165 | 200 | |
| @@ -189,13 +224,13 @@ static irqreturn_t mtk_iommu_isr(int irq, void *dev_id) · 23 unmodified lines | ||
| 189 | 224 | regval |= F_INT_CLR_BIT; |
| 190 | 225 | writel_relaxed(regval, data->base + REG_MMU_INT_CONTROL); |
| 191 | 226 | |
| 192 | − mtk_iommu_tlb_flush_all(data); | |
| 227 | + mtk_iommu_v1_tlb_flush_all(data); | |
| 193 | 228 | |
| 194 | 229 | return IRQ_HANDLED; |
| 195 | 230 | } |
| 196 | 231 | |
| 197 | −static void mtk_iommu_config(struct mtk_iommu_data *data, | |
| 198 | − struct device *dev, bool enable) | |
| 232 | +static void mtk_iommu_v1_config(struct mtk_iommu_v1_data *data, | |
| 233 | + struct device *dev, bool enable) | |
| 199 | 234 | { |
| 200 | 235 | struct mtk_smi_larb_iommu *larb_mmu; |
| 201 | 236 | unsigned int larbid, portid; |
| @@ -217,9 +252,9 @@ static void mtk_iommu_config(struct mtk_iommu_data *data, · 15 unmodified lines | ||
| 217 | 252 | } |
| 218 | 253 | } |
| 219 | 254 | |
| 220 | −static int mtk_iommu_domain_finalise(struct mtk_iommu_data *data) | |
| 255 | +static int mtk_iommu_v1_domain_finalise(struct mtk_iommu_v1_data *data) | |
| 221 | 256 | { |
| 222 | − struct mtk_iommu_domain *dom = data->m4u_dom; | |
| 257 | + struct mtk_iommu_v1_domain *dom = data->m4u_dom; | |
| 223 | 258 | |
| 224 | 259 | spin_lock_init(&dom->pgtlock); |
| 225 | 260 | |
| @@ -235,9 +270,9 @@ static int mtk_iommu_domain_finalise(struct mtk_iommu_data *data) · 9 unmodified lines | ||
| 235 | 270 | return 0; |
| 236 | 271 | } |
| 237 | 272 | |
| 238 | −static struct iommu_domain *mtk_iommu_domain_alloc(unsigned type) | |
| 273 | +static struct iommu_domain *mtk_iommu_v1_domain_alloc(unsigned type) | |
| 239 | 274 | { |
| 240 | − struct mtk_iommu_domain *dom; | |
| 275 | + struct mtk_iommu_v1_domain *dom; | |
| 241 | 276 | |
| 242 | 277 | if (type != IOMMU_DOMAIN_UNMANAGED) |
| 243 | 278 | return NULL; |
| @@ -249,21 +284,20 @@ static struct iommu_domain *mtk_iommu_domain_alloc(unsigned type) · 5 unmodified lines | ||
| 249 | 284 | return &dom->domain; |
| 250 | 285 | } |
| 251 | 286 | |
| 252 | −static void mtk_iommu_domain_free(struct iommu_domain *domain) | |
| 287 | +static void mtk_iommu_v1_domain_free(struct iommu_domain *domain) | |
| 253 | 288 | { |
| 254 | − struct mtk_iommu_domain *dom = to_mtk_domain(domain); | |
| 255 | − struct mtk_iommu_data *data = dom->data; | |
| 289 | + struct mtk_iommu_v1_domain *dom = to_mtk_domain(domain); | |
| 290 | + struct mtk_iommu_v1_data *data = dom->data; | |
| 256 | 291 | |
| 257 | 292 | dma_free_coherent(data->dev, M2701_IOMMU_PGT_SIZE, |
| 258 | 293 | dom->pgt_va, dom->pgt_pa); |
| 259 | 294 | kfree(to_mtk_domain(domain)); |
| 260 | 295 | } |
| 261 | 296 | |
| 262 | −static int mtk_iommu_attach_device(struct iommu_domain *domain, | |
| 263 | − struct device *dev) | |
| 297 | +static int mtk_iommu_v1_attach_device(struct iommu_domain *domain, struct device *dev) | |
| 264 | 298 | { |
| 265 | − struct mtk_iommu_data *data = dev_iommu_priv_get(dev); | |
| 266 | − struct mtk_iommu_domain *dom = to_mtk_domain(domain); | |
| 299 | + struct mtk_iommu_v1_data *data = dev_iommu_priv_get(dev); | |
| 300 | + struct mtk_iommu_v1_domain *dom = to_mtk_domain(domain); | |
| 267 | 301 | struct dma_iommu_mapping *mtk_mapping; |
| 268 | 302 | int ret; |
| 269 | 303 | |
| @@ -274,29 +308,28 @@ static int mtk_iommu_attach_device(struct iommu_domain *domain, · 4 unmodified lines | ||
| 274 | 308 | |
| 275 | 309 | if (!data->m4u_dom) { |
| 276 | 310 | data->m4u_dom = dom; |
| 277 | − ret = mtk_iommu_domain_finalise(data); | |
| 311 | + ret = mtk_iommu_v1_domain_finalise(data); | |
| 278 | 312 | if (ret) { |
| 279 | 313 | data->m4u_dom = NULL; |
| 280 | 314 | return ret; |
| 281 | 315 | } |
| 282 | 316 | } |
| 283 | 317 | |
| 284 | − mtk_iommu_config(data, dev, true); | |
| 318 | + mtk_iommu_v1_config(data, dev, true); | |
| 285 | 319 | return 0; |
| 286 | 320 | } |
| 287 | 321 | |
| 288 | −static void mtk_iommu_detach_device(struct iommu_domain *domain, | |
| 289 | − struct device *dev) | |
| 322 | +static void mtk_iommu_v1_detach_device(struct iommu_domain *domain, struct device *dev) | |
| 290 | 323 | { |
| 291 | − struct mtk_iommu_data *data = dev_iommu_priv_get(dev); | |
| 324 | + struct mtk_iommu_v1_data *data = dev_iommu_priv_get(dev); | |
| 292 | 325 | |
| 293 | − mtk_iommu_config(data, dev, false); | |
| 326 | + mtk_iommu_v1_config(data, dev, false); | |
| 294 | 327 | } |
| 295 | 328 | |
| 296 | −static int mtk_iommu_map(struct iommu_domain *domain, unsigned long iova, | |
| 297 | − phys_addr_t paddr, size_t size, int prot, gfp_t gfp) | |
| 329 | +static int mtk_iommu_v1_map(struct iommu_domain *domain, unsigned long iova, | |
| 330 | + phys_addr_t paddr, size_t size, int prot, gfp_t gfp) | |
| 298 | 331 | { |
| 299 | − struct mtk_iommu_domain *dom = to_mtk_domain(domain); | |
| 332 | + struct mtk_iommu_v1_domain *dom = to_mtk_domain(domain); | |
| 300 | 333 | unsigned int page_num = size >> MT2701_IOMMU_PAGE_SHIFT; |
| 301 | 334 | unsigned long flags; |
| 302 | 335 | unsigned int i; |
| @@ -317,16 +350,15 @@ static int mtk_iommu_map(struct iommu_domain *domain, unsigned long iova, · 14 unmodified lines | ||
| 317 | 350 | |
| 318 | 351 | spin_unlock_irqrestore(&dom->pgtlock, flags); |
| 319 | 352 | |
| 320 | − mtk_iommu_tlb_flush_range(dom->data, iova, size); | |
| 353 | + mtk_iommu_v1_tlb_flush_range(dom->data, iova, size); | |
| 321 | 354 | |
| 322 | 355 | return map_size == size ? 0 : -EEXIST; |
| 323 | 356 | } |
| 324 | 357 | |
| 325 | −static size_t mtk_iommu_unmap(struct iommu_domain *domain, | |
| 326 | − unsigned long iova, size_t size, | |
| 327 | − struct iommu_iotlb_gather *gather) | |
| 358 | +static size_t mtk_iommu_v1_unmap(struct iommu_domain *domain, unsigned long iova, | |
| 359 | + size_t size, struct iommu_iotlb_gather *gather) | |
| 328 | 360 | { |
| 329 | − struct mtk_iommu_domain *dom = to_mtk_domain(domain); | |
| 361 | + struct mtk_iommu_v1_domain *dom = to_mtk_domain(domain); | |
| 330 | 362 | unsigned long flags; |
| 331 | 363 | u32 *pgt_base_iova = dom->pgt_va + (iova >> MT2701_IOMMU_PAGE_SHIFT); |
| 332 | 364 | unsigned int page_num = size >> MT2701_IOMMU_PAGE_SHIFT; |
| @@ -335,15 +367,14 @@ static size_t mtk_iommu_unmap(struct iommu_domain *domain, · 2 unmodified lines | ||
| 335 | 367 | memset(pgt_base_iova, 0, page_num * sizeof(u32)); |
| 336 | 368 | spin_unlock_irqrestore(&dom->pgtlock, flags); |
| 337 | 369 | |
| 338 | − mtk_iommu_tlb_flush_range(dom->data, iova, size); | |
| 370 | + mtk_iommu_v1_tlb_flush_range(dom->data, iova, size); | |
| 339 | 371 | |
| 340 | 372 | return size; |
| 341 | 373 | } |
| 342 | 374 | |
| 343 | −static phys_addr_t mtk_iommu_iova_to_phys(struct iommu_domain *domain, | |
| 344 | − dma_addr_t iova) | |
| 375 | +static phys_addr_t mtk_iommu_v1_iova_to_phys(struct iommu_domain *domain, dma_addr_t iova) | |
| 345 | 376 | { |
| 346 | − struct mtk_iommu_domain *dom = to_mtk_domain(domain); | |
| 377 | + struct mtk_iommu_v1_domain *dom = to_mtk_domain(domain); | |
| 347 | 378 | unsigned long flags; |
| 348 | 379 | phys_addr_t pa; |
| 349 | 380 | |
| @@ -355,17 +386,16 @@ static phys_addr_t mtk_iommu_iova_to_phys(struct iommu_domain *domain, · 5 unmodified lines | ||
| 355 | 386 | return pa; |
| 356 | 387 | } |
| 357 | 388 | |
| 358 | −static const struct iommu_ops mtk_iommu_ops; | |
| 389 | +static const struct iommu_ops mtk_iommu_v1_ops; | |
| 359 | 390 | |
| 360 | 391 | /* |
| 361 | 392 | * MTK generation one iommu HW only support one iommu domain, and all the client |
| 362 | 393 | * sharing the same iova address space. |
| 363 | 394 | */ |
| 364 | −static int mtk_iommu_create_mapping(struct device *dev, | |
| 365 | − struct of_phandle_args *args) | |
| 395 | +static int mtk_iommu_v1_create_mapping(struct device *dev, struct of_phandle_args *args) | |
| 366 | 396 | { |
| 367 | 397 | struct iommu_fwspec *fwspec = dev_iommu_fwspec_get(dev); |
| 368 | − struct mtk_iommu_data *data; | |
| 398 | + struct mtk_iommu_v1_data *data; | |
| 369 | 399 | struct platform_device *m4updev; |
| 370 | 400 | struct dma_iommu_mapping *mtk_mapping; |
| 371 | 401 | int ret; |
| @@ -377,11 +407,11 @@ static int mtk_iommu_create_mapping(struct device *dev, · 5 unmodified lines | ||
| 377 | 407 | } |
| 378 | 408 | |
| 379 | 409 | if (!fwspec) { |
| 380 | − ret = iommu_fwspec_init(dev, &args->np->fwnode, &mtk_iommu_ops); | |
| 410 | + ret = iommu_fwspec_init(dev, &args->np->fwnode, &mtk_iommu_v1_ops); | |
| 381 | 411 | if (ret) |
| 382 | 412 | return ret; |
| 383 | 413 | fwspec = dev_iommu_fwspec_get(dev); |
| 384 | − } else if (dev_iommu_fwspec_get(dev)->ops != &mtk_iommu_ops) { | |
| 414 | + } else if (dev_iommu_fwspec_get(dev)->ops != &mtk_iommu_v1_ops) { | |
| 385 | 415 | return -EINVAL; |
| 386 | 416 | } |
| 387 | 417 | |
| @@ -413,16 +443,16 @@ static int mtk_iommu_create_mapping(struct device *dev, · 25 unmodified lines | ||
| 413 | 443 | return 0; |
| 414 | 444 | } |
| 415 | 445 | |
| 416 | −static int mtk_iommu_def_domain_type(struct device *dev) | |
| 446 | +static int mtk_iommu_v1_def_domain_type(struct device *dev) | |
| 417 | 447 | { |
| 418 | 448 | return IOMMU_DOMAIN_UNMANAGED; |
| 419 | 449 | } |
| 420 | 450 | |
| 421 | −static struct iommu_device *mtk_iommu_probe_device(struct device *dev) | |
| 451 | +static struct iommu_device *mtk_iommu_v1_probe_device(struct device *dev) | |
| 422 | 452 | { |
| 423 | 453 | struct iommu_fwspec *fwspec = dev_iommu_fwspec_get(dev); |
| 424 | 454 | struct of_phandle_args iommu_spec; |
| 425 | − struct mtk_iommu_data *data; | |
| 455 | + struct mtk_iommu_v1_data *data; | |
| 426 | 456 | int err, idx = 0, larbid, larbidx; |
| 427 | 457 | struct device_link *link; |
| 428 | 458 | struct device *larbdev; |
| @@ -440,7 +470,7 @@ static struct iommu_device *mtk_iommu_probe_device(struct device *dev) · 11 unmodified lines | ||
| 440 | 470 | "#iommu-cells", |
| 441 | 471 | idx, &iommu_spec)) { |
| 442 | 472 | |
| 443 | − err = mtk_iommu_create_mapping(dev, &iommu_spec); | |
| 473 | + err = mtk_iommu_v1_create_mapping(dev, &iommu_spec); | |
| 444 | 474 | of_node_put(iommu_spec.np); |
| 445 | 475 | if (err) |
| 446 | 476 | return ERR_PTR(err); |
| @@ -450,13 +480,16 @@ static struct iommu_device *mtk_iommu_probe_device(struct device *dev) · 3 unmodified lines | ||
| 450 | 480 | idx++; |
| 451 | 481 | } |
| 452 | 482 | |
| 453 | − if (!fwspec || fwspec->ops != &mtk_iommu_ops) | |
| 483 | + if (!fwspec || fwspec->ops != &mtk_iommu_v1_ops) | |
| 454 | 484 | return ERR_PTR(-ENODEV); /* Not a iommu client device */ |
| 455 | 485 | |
| 456 | 486 | data = dev_iommu_priv_get(dev); |
| 457 | 487 | |
| 458 | 488 | /* Link the consumer device with the smi-larb device(supplier) */ |
| 459 | 489 | larbid = mt2701_m4u_to_larb(fwspec->ids[0]); |
| 490 | + if (larbid >= MT2701_LARB_NR_MAX) | |
| 491 | + return ERR_PTR(-EINVAL); | |
| 492 | + | |
| 460 | 493 | for (idx = 1; idx < fwspec->num_ids; idx++) { |
| 461 | 494 | larbidx = mt2701_m4u_to_larb(fwspec->ids[idx]); |
| 462 | 495 | if (larbid != larbidx) { |
| @@ -467,6 +500,9 @@ static struct iommu_device *mtk_iommu_probe_device(struct device *dev) · 4 unmodified lines | ||
| 467 | 500 | } |
| 468 | 501 | |
| 469 | 502 | larbdev = data->larb_imu[larbid].dev; |
| 503 | + if (!larbdev) | |
| 504 | + return ERR_PTR(-EINVAL); | |
| 505 | + | |
| 470 | 506 | link = device_link_add(dev, larbdev, |
| 471 | 507 | DL_FLAG_PM_RUNTIME | DL_FLAG_STATELESS); |
| 472 | 508 | if (!link) |
| @@ -475,10 +511,10 @@ static struct iommu_device *mtk_iommu_probe_device(struct device *dev) · 2 unmodified lines | ||
| 475 | 511 | return &data->iommu; |
| 476 | 512 | } |
| 477 | 513 | |
| 478 | −static void mtk_iommu_probe_finalize(struct device *dev) | |
| 514 | +static void mtk_iommu_v1_probe_finalize(struct device *dev) | |
| 479 | 515 | { |
| 480 | 516 | struct dma_iommu_mapping *mtk_mapping; |
| 481 | − struct mtk_iommu_data *data; | |
| 517 | + struct mtk_iommu_v1_data *data; | |
| 482 | 518 | int err; |
| 483 | 519 | |
| 484 | 520 | data = dev_iommu_priv_get(dev); |
| @@ -489,14 +525,14 @@ static void mtk_iommu_probe_finalize(struct device *dev) · 4 unmodified lines | ||
| 489 | 525 | dev_err(dev, "Can't create IOMMU mapping - DMA-OPS will not work\n"); |
| 490 | 526 | } |
| 491 | 527 | |
| 492 | −static void mtk_iommu_release_device(struct device *dev) | |
| 528 | +static void mtk_iommu_v1_release_device(struct device *dev) | |
| 493 | 529 | { |
| 494 | 530 | struct iommu_fwspec *fwspec = dev_iommu_fwspec_get(dev); |
| 495 | − struct mtk_iommu_data *data; | |
| 531 | + struct mtk_iommu_v1_data *data; | |
| 496 | 532 | struct device *larbdev; |
| 497 | 533 | unsigned int larbid; |
| 498 | 534 | |
| 499 | − if (!fwspec || fwspec->ops != &mtk_iommu_ops) | |
| 535 | + if (!fwspec || fwspec->ops != &mtk_iommu_v1_ops) | |
| 500 | 536 | return; |
| 501 | 537 | |
| 502 | 538 | data = dev_iommu_priv_get(dev); |
| @@ -507,7 +543,7 @@ static void mtk_iommu_release_device(struct device *dev) · 4 unmodified lines | ||
| 507 | 543 | iommu_fwspec_free(dev); |
| 508 | 544 | } |
| 509 | 545 | |
| 510 | −static int mtk_iommu_hw_init(const struct mtk_iommu_data *data) | |
| 546 | +static int mtk_iommu_v1_hw_init(const struct mtk_iommu_v1_data *data) | |
| 511 | 547 | { |
| 512 | 548 | u32 regval; |
| 513 | 549 | int ret; |
| @@ -537,7 +573,7 @@ static int mtk_iommu_hw_init(const struct mtk_iommu_data *data) · 23 unmodified lines | ||
| 537 | 573 | |
| 538 | 574 | writel_relaxed(F_MMU_DCM_ON, data->base + REG_MMU_DCM); |
| 539 | 575 | |
| 540 | − if (devm_request_irq(data->dev, data->irq, mtk_iommu_isr, 0, | |
| 576 | + if (devm_request_irq(data->dev, data->irq, mtk_iommu_v1_isr, 0, | |
| 541 | 577 | dev_name(data->dev), (void *)data)) { |
| 542 | 578 | writel_relaxed(0, data->base + REG_MMU_PT_BASE_ADDR); |
| 543 | 579 | clk_disable_unprepare(data->bclk); |
| @@ -548,39 +584,39 @@ static int mtk_iommu_hw_init(const struct mtk_iommu_data *data) · 4 unmodified lines | ||
| 548 | 584 | return 0; |
| 549 | 585 | } |
| 550 | 586 | |
| 551 | −static const struct iommu_ops mtk_iommu_ops = { | |
| 552 | − .domain_alloc = mtk_iommu_domain_alloc, | |
| 553 | − .probe_device = mtk_iommu_probe_device, | |
| 554 | − .probe_finalize = mtk_iommu_probe_finalize, | |
| 555 | − .release_device = mtk_iommu_release_device, | |
| 556 | − .def_domain_type = mtk_iommu_def_domain_type, | |
| 587 | +static const struct iommu_ops mtk_iommu_v1_ops = { | |
| 588 | + .domain_alloc = mtk_iommu_v1_domain_alloc, | |
| 589 | + .probe_device = mtk_iommu_v1_probe_device, | |
| 590 | + .probe_finalize = mtk_iommu_v1_probe_finalize, | |
| 591 | + .release_device = mtk_iommu_v1_release_device, | |
| 592 | + .def_domain_type = mtk_iommu_v1_def_domain_type, | |
| 557 | 593 | .device_group = generic_device_group, |
| 558 | 594 | .pgsize_bitmap = ~0UL << MT2701_IOMMU_PAGE_SHIFT, |
| 559 | 595 | .owner = THIS_MODULE, |
| 560 | 596 | .default_domain_ops = &(const struct iommu_domain_ops) { |
| 561 | − .attach_dev = mtk_iommu_attach_device, | |
| 562 | − .detach_dev = mtk_iommu_detach_device, | |
| 563 | − .map = mtk_iommu_map, | |
| 564 | − .unmap = mtk_iommu_unmap, | |
| 565 | − .iova_to_phys = mtk_iommu_iova_to_phys, | |
| 566 | − .free = mtk_iommu_domain_free, | |
| 597 | + .attach_dev = mtk_iommu_v1_attach_device, | |
| 598 | + .detach_dev = mtk_iommu_v1_detach_device, | |
| 599 | + .map = mtk_iommu_v1_map, | |
| 600 | + .unmap = mtk_iommu_v1_unmap, | |
| 601 | + .iova_to_phys = mtk_iommu_v1_iova_to_phys, | |
| 602 | + .free = mtk_iommu_v1_domain_free, | |
| 567 | 603 | } |
| 568 | 604 | }; |
| 569 | 605 | |
| 570 | −static const struct of_device_id mtk_iommu_of_ids[] = { | |
| 606 | +static const struct of_device_id mtk_iommu_v1_of_ids[] = { | |
| 571 | 607 | { .compatible = "mediatek,mt2701-m4u", }, |
| 572 | 608 | {} |
| 573 | 609 | }; |
| 574 | 610 | |
| 575 | −static const struct component_master_ops mtk_iommu_com_ops = { | |
| 576 | − .bind = mtk_iommu_bind, | |
| 577 | − .unbind = mtk_iommu_unbind, | |
| 611 | +static const struct component_master_ops mtk_iommu_v1_com_ops = { | |
| 612 | + .bind = mtk_iommu_v1_bind, | |
| 613 | + .unbind = mtk_iommu_v1_unbind, | |
| 578 | 614 | }; |
| 579 | 615 | |
| 580 | −static int mtk_iommu_probe(struct platform_device *pdev) | |
| 616 | +static int mtk_iommu_v1_probe(struct platform_device *pdev) | |
| 581 | 617 | { |
| 582 | − struct mtk_iommu_data *data; | |
| 583 | 618 | struct device *dev = &pdev->dev; |
| 619 | + struct mtk_iommu_v1_data *data; | |
| 584 | 620 | struct resource *res; |
| 585 | 621 | struct component_match *match = NULL; |
| 586 | 622 | void *protect; |
| @@ -647,7 +683,7 @@ static int mtk_iommu_probe(struct platform_device *pdev) · 60 unmodified lines | ||
| 647 | 683 | |
| 648 | 684 | platform_set_drvdata(pdev, data); |
| 649 | 685 | |
| 650 | − ret = mtk_iommu_hw_init(data); | |
| 686 | + ret = mtk_iommu_v1_hw_init(data); | |
| 651 | 687 | if (ret) |
| 652 | 688 | return ret; |
| 653 | 689 | |
| @@ -656,17 +692,17 @@ static int mtk_iommu_probe(struct platform_device *pdev) · 2 unmodified lines | ||
| 656 | 692 | if (ret) |
| 657 | 693 | return ret; |
| 658 | 694 | |
| 659 | − ret = iommu_device_register(&data->iommu, &mtk_iommu_ops, dev); | |
| 695 | + ret = iommu_device_register(&data->iommu, &mtk_iommu_v1_ops, dev); | |
| 660 | 696 | if (ret) |
| 661 | 697 | goto out_sysfs_remove; |
| 662 | 698 | |
| 663 | 699 | if (!iommu_present(&platform_bus_type)) { |
| 664 | − ret = bus_set_iommu(&platform_bus_type, &mtk_iommu_ops); | |
| 700 | + ret = bus_set_iommu(&platform_bus_type, &mtk_iommu_v1_ops); | |
| 665 | 701 | if (ret) |
| 666 | 702 | goto out_dev_unreg; |
| 667 | 703 | } |
| 668 | 704 | |
| 669 | − ret = component_master_add_with_match(dev, &mtk_iommu_com_ops, match); | |
| 705 | + ret = component_master_add_with_match(dev, &mtk_iommu_v1_com_ops, match); | |
| 670 | 706 | if (ret) |
| 671 | 707 | goto out_bus_set_null; |
| 672 | 708 | return ret; |
| @@ -680,9 +716,9 @@ out_sysfs_remove: · 7 unmodified lines | ||
| 680 | 716 | return ret; |
| 681 | 717 | } |
| 682 | 718 | |
| 683 | −static int mtk_iommu_remove(struct platform_device *pdev) | |
| 719 | +static int mtk_iommu_v1_remove(struct platform_device *pdev) | |
| 684 | 720 | { |
| 685 | − struct mtk_iommu_data *data = platform_get_drvdata(pdev); | |
| 721 | + struct mtk_iommu_v1_data *data = platform_get_drvdata(pdev); | |
| 686 | 722 | |
| 687 | 723 | iommu_device_sysfs_remove(&data->iommu); |
| 688 | 724 | iommu_device_unregister(&data->iommu); |
| @@ -692,14 +728,14 @@ static int mtk_iommu_remove(struct platform_device *pdev) · 3 unmodified lines | ||
| 692 | 728 | |
| 693 | 729 | clk_disable_unprepare(data->bclk); |
| 694 | 730 | devm_free_irq(&pdev->dev, data->irq, data); |
| 695 | − component_master_del(&pdev->dev, &mtk_iommu_com_ops); | |
| 731 | + component_master_del(&pdev->dev, &mtk_iommu_v1_com_ops); | |
| 696 | 732 | return 0; |
| 697 | 733 | } |
| 698 | 734 | |
| 699 | −static int __maybe_unused mtk_iommu_suspend(struct device *dev) | |
| 735 | +static int __maybe_unused mtk_iommu_v1_suspend(struct device *dev) | |
| 700 | 736 | { |
| 701 | − struct mtk_iommu_data *data = dev_get_drvdata(dev); | |
| 702 | − struct mtk_iommu_suspend_reg *reg = &data->reg; | |
| 737 | + struct mtk_iommu_v1_data *data = dev_get_drvdata(dev); | |
| 738 | + struct mtk_iommu_v1_suspend_reg *reg = &data->reg; | |
| 703 | 739 | void __iomem *base = data->base; |
| 704 | 740 | |
| 705 | 741 | reg->standard_axi_mode = readl_relaxed(base + |
| @@ -710,10 +746,10 @@ static int __maybe_unused mtk_iommu_suspend(struct device *dev) · 4 unmodified lines | ||
| 710 | 746 | return 0; |
| 711 | 747 | } |
| 712 | 748 | |
| 713 | −static int __maybe_unused mtk_iommu_resume(struct device *dev) | |
| 749 | +static int __maybe_unused mtk_iommu_v1_resume(struct device *dev) | |
| 714 | 750 | { |
| 715 | − struct mtk_iommu_data *data = dev_get_drvdata(dev); | |
| 716 | − struct mtk_iommu_suspend_reg *reg = &data->reg; | |
| 751 | + struct mtk_iommu_v1_data *data = dev_get_drvdata(dev); | |
| 752 | + struct mtk_iommu_v1_suspend_reg *reg = &data->reg; | |
| 717 | 753 | void __iomem *base = data->base; |
| 718 | 754 | |
| 719 | 755 | writel_relaxed(data->m4u_dom->pgt_pa, base + REG_MMU_PT_BASE_ADDR); |
| @@ -726,20 +762,20 @@ static int __maybe_unused mtk_iommu_resume(struct device *dev) · 6 unmodified lines | ||
| 726 | 762 | return 0; |
| 727 | 763 | } |
| 728 | 764 | |
| 729 | −static const struct dev_pm_ops mtk_iommu_pm_ops = { | |
| 730 | − SET_SYSTEM_SLEEP_PM_OPS(mtk_iommu_suspend, mtk_iommu_resume) | |
| 765 | +static const struct dev_pm_ops mtk_iommu_v1_pm_ops = { | |
| 766 | + SET_SYSTEM_SLEEP_PM_OPS(mtk_iommu_v1_suspend, mtk_iommu_v1_resume) | |
| 731 | 767 | }; |
| 732 | 768 | |
| 733 | −static struct platform_driver mtk_iommu_driver = { | |
| 734 | − .probe = mtk_iommu_probe, | |
| 735 | − .remove = mtk_iommu_remove, | |
| 769 | +static struct platform_driver mtk_iommu_v1_driver = { | |
| 770 | + .probe = mtk_iommu_v1_probe, | |
| 771 | + .remove = mtk_iommu_v1_remove, | |
| 736 | 772 | .driver = { |
| 737 | 773 | .name = "mtk-iommu-v1", |
| 738 | − .of_match_table = mtk_iommu_of_ids, | |
| 739 | − .pm = &mtk_iommu_pm_ops, | |
| 774 | + .of_match_table = mtk_iommu_v1_of_ids, | |
| 775 | + .pm = &mtk_iommu_v1_pm_ops, | |
| 740 | 776 | } |
| 741 | 777 | }; |
| 742 | −module_platform_driver(mtk_iommu_driver); | |
| 778 | +module_platform_driver(mtk_iommu_v1_driver); | |
| 743 | 779 | |
| 744 | 780 | MODULE_DESCRIPTION("IOMMU API for MediaTek M4U v1 implementations"); |
| 745 | 781 | MODULE_LICENSE("GPL v2"); |
| @@ -99,7 +99,7 @@ static int s390_iommu_attach_device(struct iommu_domain *domain, · 98 unmodified lines | ||
| 99 | 99 | if (!domain_device) |
| 100 | 100 | return -ENOMEM; |
| 101 | 101 | |
| 102 | − if (zdev->dma_table) { | |
| 102 | + if (zdev->dma_table && !zdev->s390_domain) { | |
| 103 | 103 | cc = zpci_dma_exit_device(zdev); |
| 104 | 104 | if (cc) { |
| 105 | 105 | rc = -EIO; |
| @@ -107,6 +107,9 @@ static int s390_iommu_attach_device(struct iommu_domain *domain, · 1 unmodified line | ||
| 107 | 107 | } |
| 108 | 108 | } |
| 109 | 109 | |
| 110 | + if (zdev->s390_domain) | |
| 111 | + zpci_unregister_ioat(zdev, 0); | |
| 112 | + | |
| 110 | 113 | zdev->dma_table = s390_domain->dma_table; |
| 111 | 114 | cc = zpci_register_ioat(zdev, 0, zdev->start_dma, zdev->end_dma, |
| 112 | 115 | virt_to_phys(zdev->dma_table)); |
| @@ -136,7 +139,13 @@ static int s390_iommu_attach_device(struct iommu_domain *domain, · 23 unmodified lines | ||
| 136 | 139 | return 0; |
| 137 | 140 | |
| 138 | 141 | out_restore: |
| 139 | − zpci_dma_init_device(zdev); | |
| 142 | + if (!zdev->s390_domain) { | |
| 143 | + zpci_dma_init_device(zdev); | |
| 144 | + } else { | |
| 145 | + zdev->dma_table = zdev->s390_domain->dma_table; | |
| 146 | + zpci_register_ioat(zdev, 0, zdev->start_dma, zdev->end_dma, | |
| 147 | + virt_to_phys(zdev->dma_table)); | |
| 148 | + } | |
| 140 | 149 | out_free: |
| 141 | 150 | kfree(domain_device); |
| 142 | 151 | |
| @@ -167,7 +176,7 @@ static void s390_iommu_detach_device(struct iommu_domain *domain, · 24 unmodified lines | ||
| 167 | 176 | } |
| 168 | 177 | spin_unlock_irqrestore(&s390_domain->list_lock, flags); |
| 169 | 178 | |
| 170 | − if (found) { | |
| 179 | + if (found && (zdev->s390_domain == s390_domain)) { | |
| 171 | 180 | zdev->s390_domain = NULL; |
| 172 | 181 | zpci_unregister_ioat(zdev, 0); |
| 173 | 182 | zpci_dma_init_device(zdev); |
| @@ -164,25 +164,39 @@ static const struct regmap_access_table rpcif_volatile_table = { · 163 unmodified lines | ||
| 164 | 164 | |
| 165 | 165 | |
| 166 | 166 | /* |
| 167 | − * Custom accessor functions to ensure SMRDR0 and SMWDR0 are always accessed | |
| 168 | − * with proper width. Requires SMENR_SPIDE to be correctly set before! | |
| 167 | + * Custom accessor functions to ensure SM[RW]DR[01] are always accessed with | |
| 168 | + * proper width. Requires rpcif.xfer_size to be correctly set before! | |
| 169 | 169 | */ |
| 170 | 170 | static int rpcif_reg_read(void *context, unsigned int reg, unsigned int *val) |
| 171 | 171 | { |
| 172 | 172 | struct rpcif *rpc = context; |
| 173 | 173 | |
| 174 | − if (reg == RPCIF_SMRDR0 || reg == RPCIF_SMWDR0) { | |
| 175 | − u32 spide = readl(rpc->base + RPCIF_SMENR) & RPCIF_SMENR_SPIDE(0xF); | |
| 176 | − | |
| 177 | − if (spide == 0x8) { | |
| 174 | + switch (reg) { | |
| 175 | + case RPCIF_SMRDR0: | |
| 176 | + case RPCIF_SMWDR0: | |
| 177 | + switch (rpc->xfer_size) { | |
| 178 | + case 1: | |
| 178 | 179 | *val = readb(rpc->base + reg); |
| 179 | 180 | return 0; |
| 180 | − } else if (spide == 0xC) { | |
| 181 | + | |
| 182 | + case 2: | |
| 181 | 183 | *val = readw(rpc->base + reg); |
| 182 | 184 | return 0; |
| 183 | − } else if (spide != 0xF) { | |
| 185 | + | |
| 186 | + case 4: | |
| 187 | + case 8: | |
| 188 | + *val = readl(rpc->base + reg); | |
| 189 | + return 0; | |
| 190 | + | |
| 191 | + default: | |
| 184 | 192 | return -EILSEQ; |
| 185 | 193 | } |
| 194 | + | |
| 195 | + case RPCIF_SMRDR1: | |
| 196 | + case RPCIF_SMWDR1: | |
| 197 | + if (rpc->xfer_size != 8) | |
| 198 | + return -EILSEQ; | |
| 199 | + break; | |
| 186 | 200 | } |
| 187 | 201 | |
| 188 | 202 | *val = readl(rpc->base + reg); |
| @@ -193,18 +207,34 @@ static int rpcif_reg_write(void *context, unsigned int reg, unsigned int val) · 4 unmodified lines | ||
| 193 | 207 | { |
| 194 | 208 | struct rpcif *rpc = context; |
| 195 | 209 | |
| 196 | − if (reg == RPCIF_SMRDR0 || reg == RPCIF_SMWDR0) { | |
| 197 | − u32 spide = readl(rpc->base + RPCIF_SMENR) & RPCIF_SMENR_SPIDE(0xF); | |
| 198 | − | |
| 199 | − if (spide == 0x8) { | |
| 210 | + switch (reg) { | |
| 211 | + case RPCIF_SMWDR0: | |
| 212 | + switch (rpc->xfer_size) { | |
| 213 | + case 1: | |
| 200 | 214 | writeb(val, rpc->base + reg); |
| 201 | 215 | return 0; |
| 202 | − } else if (spide == 0xC) { | |
| 216 | + | |
| 217 | + case 2: | |
| 203 | 218 | writew(val, rpc->base + reg); |
| 204 | 219 | return 0; |
| 205 | − } else if (spide != 0xF) { | |
| 220 | + | |
| 221 | + case 4: | |
| 222 | + case 8: | |
| 223 | + writel(val, rpc->base + reg); | |
| 224 | + return 0; | |
| 225 | + | |
| 226 | + default: | |
| 206 | 227 | return -EILSEQ; |
| 207 | 228 | } |
| 229 | + | |
| 230 | + case RPCIF_SMWDR1: | |
| 231 | + if (rpc->xfer_size != 8) | |
| 232 | + return -EILSEQ; | |
| 233 | + break; | |
| 234 | + | |
| 235 | + case RPCIF_SMRDR0: | |
| 236 | + case RPCIF_SMRDR1: | |
| 237 | + return -EPERM; | |
| 208 | 238 | } |
| 209 | 239 | |
| 210 | 240 | writel(val, rpc->base + reg); |
| @@ -469,6 +499,7 @@ int rpcif_manual_xfer(struct rpcif *rpc) · 258 unmodified lines | ||
| 469 | 499 | |
| 470 | 500 | smenr |= RPCIF_SMENR_SPIDE(rpcif_bits_set(rpc, nbytes)); |
| 471 | 501 | regmap_write(rpc->regmap, RPCIF_SMENR, smenr); |
| 502 | + rpc->xfer_size = nbytes; | |
| 472 | 503 | |
| 473 | 504 | memcpy(data, rpc->buffer + pos, nbytes); |
| 474 | 505 | if (nbytes == 8) { |
| @@ -533,6 +564,7 @@ int rpcif_manual_xfer(struct rpcif *rpc) · 58 unmodified lines | ||
| 533 | 564 | regmap_write(rpc->regmap, RPCIF_SMENR, smenr); |
| 534 | 565 | regmap_write(rpc->regmap, RPCIF_SMCR, |
| 535 | 566 | rpc->smcr | RPCIF_SMCR_SPIE); |
| 567 | + rpc->xfer_size = nbytes; | |
| 536 | 568 | ret = wait_msg_xfer_end(rpc); |
| 537 | 569 | if (ret) |
| 538 | 570 | goto err_out; |
| @@ -31,6 +31,8 @@ · 30 unmodified lines | ||
| 31 | 31 | */ |
| 32 | 32 | |
| 33 | 33 | #define FM25_SN_LEN 8 /* serial number length */ |
| 34 | +#define EE_MAXADDRLEN 3 /* 24 bit addresses, up to 2 MBytes */ | |
| 35 | + | |
| 34 | 36 | struct at25_data { |
| 35 | 37 | struct spi_eeprom chip; |
| 36 | 38 | struct spi_device *spi; |
| @@ -39,6 +41,7 @@ struct at25_data { · 2 unmodified lines | ||
| 39 | 41 | struct nvmem_config nvmem_config; |
| 40 | 42 | struct nvmem_device *nvmem; |
| 41 | 43 | u8 sernum[FM25_SN_LEN]; |
| 44 | + u8 command[EE_MAXADDRLEN + 1]; | |
| 42 | 45 | }; |
| 43 | 46 | |
| 44 | 47 | #define AT25_WREN 0x06 /* latch the write enable */ |
| @@ -61,8 +64,6 @@ struct at25_data { · 16 unmodified lines | ||
| 61 | 64 | |
| 62 | 65 | #define FM25_ID_LEN 9 /* ID length */ |
| 63 | 66 | |
| 64 | −#define EE_MAXADDRLEN 3 /* 24 bit addresses, up to 2 MBytes */ | |
| 65 | − | |
| 66 | 67 | /* |
| 67 | 68 | * Specs often allow 5ms for a page write, sometimes 20ms; |
| 68 | 69 | * it's important to recover from write timeouts. |
| @@ -78,7 +79,6 @@ static int at25_ee_read(void *priv, unsigned int offset, · 9 unmodified lines | ||
| 78 | 79 | { |
| 79 | 80 | struct at25_data *at25 = priv; |
| 80 | 81 | char *buf = val; |
| 81 | − u8 command[EE_MAXADDRLEN + 1]; | |
| 82 | 82 | u8 *cp; |
| 83 | 83 | ssize_t status; |
| 84 | 84 | struct spi_transfer t[2]; |
| @@ -92,12 +92,15 @@ static int at25_ee_read(void *priv, unsigned int offset, · 7 unmodified lines | ||
| 92 | 92 | if (unlikely(!count)) |
| 93 | 93 | return -EINVAL; |
| 94 | 94 | |
| 95 | − cp = command; | |
| 95 | + cp = at25->command; | |
| 96 | 96 | |
| 97 | 97 | instr = AT25_READ; |
| 98 | 98 | if (at25->chip.flags & EE_INSTR_BIT3_IS_ADDR) |
| 99 | 99 | if (offset >= BIT(at25->addrlen * 8)) |
| 100 | 100 | instr |= AT25_INSTR_BIT3; |
| 101 | + | |
| 102 | + mutex_lock(&at25->lock); | |
| 103 | + | |
| 101 | 104 | *cp++ = instr; |
| 102 | 105 | |
| 103 | 106 | /* 8/16/24-bit address is written MSB first */ |
| @@ -116,7 +119,7 @@ static int at25_ee_read(void *priv, unsigned int offset, · 12 unmodified lines | ||
| 116 | 119 | spi_message_init(&m); |
| 117 | 120 | memset(t, 0, sizeof(t)); |
| 118 | 121 | |
| 119 | − t[0].tx_buf = command; | |
| 122 | + t[0].tx_buf = at25->command; | |
| 120 | 123 | t[0].len = at25->addrlen + 1; |
| 121 | 124 | spi_message_add_tail(&t[0], &m); |
| 122 | 125 | |
| @@ -124,8 +127,6 @@ static int at25_ee_read(void *priv, unsigned int offset, · 1 unmodified line | ||
| 124 | 127 | t[1].len = count; |
| 125 | 128 | spi_message_add_tail(&t[1], &m); |
| 126 | 129 | |
| 127 | − mutex_lock(&at25->lock); | |
| 128 | − | |
| 129 | 130 | /* |
| 130 | 131 | * Read it all at once. |
| 131 | 132 | * |
| @@ -152,7 +153,7 @@ static int fm25_aux_read(struct at25_data *at25, u8 *buf, uint8_t command, · 20 unmodified lines | ||
| 152 | 153 | spi_message_init(&m); |
| 153 | 154 | memset(t, 0, sizeof(t)); |
| 154 | 155 | |
| 155 | − t[0].tx_buf = &command; | |
| 156 | + t[0].tx_buf = at25->command; | |
| 156 | 157 | t[0].len = 1; |
| 157 | 158 | spi_message_add_tail(&t[0], &m); |
| 158 | 159 | |
| @@ -162,6 +163,8 @@ static int fm25_aux_read(struct at25_data *at25, u8 *buf, uint8_t command, · 3 unmodified lines | ||
| 162 | 163 | |
| 163 | 164 | mutex_lock(&at25->lock); |
| 164 | 165 | |
| 166 | + at25->command[0] = command; | |
| 167 | + | |
| 165 | 168 | status = spi_sync(at25->spi, &m); |
| 166 | 169 | dev_dbg(&at25->spi->dev, "read %d aux bytes --> %d\n", len, status); |
| 167 | 170 | |
| @@ -1384,13 +1384,17 @@ static int mmc_select_hs400es(struct mmc_card *card) · 1383 unmodified lines | ||
| 1384 | 1384 | goto out_err; |
| 1385 | 1385 | } |
| 1386 | 1386 | |
| 1387 | + /* | |
| 1388 | + * Bump to HS timing and frequency. Some cards don't handle | |
| 1389 | + * SEND_STATUS reliably at the initial frequency. | |
| 1390 | + */ | |
| 1387 | 1391 | mmc_set_timing(host, MMC_TIMING_MMC_HS); |
| 1392 | + mmc_set_bus_speed(card); | |
| 1393 | + | |
| 1388 | 1394 | err = mmc_switch_status(card, true); |
| 1389 | 1395 | if (err) |
| 1390 | 1396 | goto out_err; |
| 1391 | 1397 | |
| 1392 | − mmc_set_clock(host, card->ext_csd.hs_max_dtr); | |
| 1393 | − | |
| 1394 | 1398 | /* Switch card to DDR with strobe bit */ |
| 1395 | 1399 | val = EXT_CSD_DDR_BUS_WIDTH_8 | EXT_CSD_BUS_WIDTH_STROBE; |
| 1396 | 1400 | err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, |
| @@ -1448,7 +1452,7 @@ out_err: · 51 unmodified lines | ||
| 1448 | 1452 | static int mmc_select_hs200(struct mmc_card *card) |
| 1449 | 1453 | { |
| 1450 | 1454 | struct mmc_host *host = card->host; |
| 1451 | − unsigned int old_timing, old_signal_voltage; | |
| 1455 | + unsigned int old_timing, old_signal_voltage, old_clock; | |
| 1452 | 1456 | int err = -EINVAL; |
| 1453 | 1457 | u8 val; |
| 1454 | 1458 | |
| @@ -1479,8 +1483,17 @@ static int mmc_select_hs200(struct mmc_card *card) · 24 unmodified lines | ||
| 1479 | 1483 | false, true, MMC_CMD_RETRIES); |
| 1480 | 1484 | if (err) |
| 1481 | 1485 | goto err; |
| 1486 | + | |
| 1487 | + /* | |
| 1488 | + * Bump to HS timing and frequency. Some cards don't handle | |
| 1489 | + * SEND_STATUS reliably at the initial frequency. | |
| 1490 | + * NB: We can't move to full (HS200) speeds until after we've | |
| 1491 | + * successfully switched over. | |
| 1492 | + */ | |
| 1482 | 1493 | old_timing = host->ios.timing; |
| 1494 | + old_clock = host->ios.clock; | |
| 1483 | 1495 | mmc_set_timing(host, MMC_TIMING_MMC_HS200); |
| 1496 | + mmc_set_clock(card->host, card->ext_csd.hs_max_dtr); | |
| 1484 | 1497 | |
| 1485 | 1498 | /* |
| 1486 | 1499 | * For HS200, CRC errors are not a reliable way to know the |
| @@ -1493,8 +1506,10 @@ static int mmc_select_hs200(struct mmc_card *card) · 6 unmodified lines | ||
| 1493 | 1506 | * mmc_select_timing() assumes timing has not changed if |
| 1494 | 1507 | * it is a switch error. |
| 1495 | 1508 | */ |
| 1496 | − if (err == -EBADMSG) | |
| 1509 | + if (err == -EBADMSG) { | |
| 1510 | + mmc_set_clock(host, old_clock); | |
| 1497 | 1511 | mmc_set_timing(host, old_timing); |
| 1512 | + } | |
| 1498 | 1513 | } |
| 1499 | 1514 | err: |
| 1500 | 1515 | if (err) { |
| @@ -17,6 +17,7 @@ · 16 unmodified lines | ||
| 17 | 17 | #include <linux/regulator/consumer.h> |
| 18 | 18 | #include <linux/interconnect.h> |
| 19 | 19 | #include <linux/pinctrl/consumer.h> |
| 20 | +#include <linux/reset.h> | |
| 20 | 21 | |
| 21 | 22 | #include "sdhci-pltfm.h" |
| 22 | 23 | #include "cqhci.h" |
| @@ -2482,6 +2483,43 @@ static inline void sdhci_msm_get_of_property(struct platform_device *pdev, · 2459 unmodified lines | ||
| 2482 | 2483 | of_property_read_u32(node, "qcom,dll-config", &msm_host->dll_config); |
| 2483 | 2484 | } |
| 2484 | 2485 | |
| 2486 | +static int sdhci_msm_gcc_reset(struct device *dev, struct sdhci_host *host) | |
| 2487 | +{ | |
| 2488 | + struct reset_control *reset; | |
| 2489 | + int ret = 0; | |
| 2490 | + | |
| 2491 | + reset = reset_control_get_optional_exclusive(dev, NULL); | |
| 2492 | + if (IS_ERR(reset)) | |
| 2493 | + return dev_err_probe(dev, PTR_ERR(reset), | |
| 2494 | + "unable to acquire core_reset\n"); | |
| 2495 | + | |
| 2496 | + if (!reset) | |
| 2497 | + return ret; | |
| 2498 | + | |
| 2499 | + ret = reset_control_assert(reset); | |
| 2500 | + if (ret) { | |
| 2501 | + reset_control_put(reset); | |
| 2502 | + return dev_err_probe(dev, ret, "core_reset assert failed\n"); | |
| 2503 | + } | |
| 2504 | + | |
| 2505 | + /* | |
| 2506 | + * The hardware requirement for delay between assert/deassert | |
| 2507 | + * is at least 3-4 sleep clock (32.7KHz) cycles, which comes to | |
| 2508 | + * ~125us (4/32768). To be on the safe side add 200us delay. | |
| 2509 | + */ | |
| 2510 | + usleep_range(200, 210); | |
| 2511 | + | |
| 2512 | + ret = reset_control_deassert(reset); | |
| 2513 | + if (ret) { | |
| 2514 | + reset_control_put(reset); | |
| 2515 | + return dev_err_probe(dev, ret, "core_reset deassert failed\n"); | |
| 2516 | + } | |
| 2517 | + | |
| 2518 | + usleep_range(200, 210); | |
| 2519 | + reset_control_put(reset); | |
| 2520 | + | |
| 2521 | + return ret; | |
| 2522 | +} | |
| 2485 | 2523 | |
| 2486 | 2524 | static int sdhci_msm_probe(struct platform_device *pdev) |
| 2487 | 2525 | { |
| @@ -2529,6 +2567,10 @@ static int sdhci_msm_probe(struct platform_device *pdev) · 41 unmodified lines | ||
| 2529 | 2567 | |
| 2530 | 2568 | msm_host->saved_tuning_phase = INVALID_TUNING_PHASE; |
| 2531 | 2569 | |
| 2570 | + ret = sdhci_msm_gcc_reset(&pdev->dev, host); | |
| 2571 | + if (ret) | |
| 2572 | + goto pltfm_free; | |
| 2573 | + | |
| 2532 | 2574 | /* Setup SDCC bus voter clock. */ |
| 2533 | 2575 | msm_host->bus_clk = devm_clk_get(&pdev->dev, "bus"); |
| 2534 | 2576 | if (!IS_ERR(msm_host->bus_clk)) { |
| @@ -377,8 +377,9 @@ static void sunxi_mmc_init_idma_des(struct sunxi_mmc_host *host, · 376 unmodified lines | ||
| 377 | 377 | pdes[i].buf_addr_ptr1 = |
| 378 | 378 | cpu_to_le32(sg_dma_address(&data->sg[i]) >> |
| 379 | 379 | host->cfg->idma_des_shift); |
| 380 | − pdes[i].buf_addr_ptr2 = cpu_to_le32((u32)next_desc >> | |
| 381 | − host->cfg->idma_des_shift); | |
| 380 | + pdes[i].buf_addr_ptr2 = | |
| 381 | + cpu_to_le32(next_desc >> | |
| 382 | + host->cfg->idma_des_shift); | |
| 382 | 383 | } |
| 383 | 384 | |
| 384 | 385 | pdes[0].config |= cpu_to_le32(SDXC_IDMAC_DES0_FD); |
| @@ -43,6 +43,7 @@ · 42 unmodified lines | ||
| 43 | 43 | |
| 44 | 44 | struct mtk_ecc_caps { |
| 45 | 45 | u32 err_mask; |
| 46 | + u32 err_shift; | |
| 46 | 47 | const u8 *ecc_strength; |
| 47 | 48 | const u32 *ecc_regs; |
| 48 | 49 | u8 num_ecc_strength; |
| @@ -76,7 +77,7 @@ static const u8 ecc_strength_mt2712[] = { · 27 unmodified lines | ||
| 76 | 77 | }; |
| 77 | 78 | |
| 78 | 79 | static const u8 ecc_strength_mt7622[] = { |
| 79 | − 4, 6, 8, 10, 12, 14, 16 | |
| 80 | + 4, 6, 8, 10, 12 | |
| 80 | 81 | }; |
| 81 | 82 | |
| 82 | 83 | enum mtk_ecc_regs { |
| @@ -221,7 +222,7 @@ void mtk_ecc_get_stats(struct mtk_ecc *ecc, struct mtk_ecc_stats *stats, · 138 unmodified lines | ||
| 221 | 222 | for (i = 0; i < sectors; i++) { |
| 222 | 223 | offset = (i >> 2) << 2; |
| 223 | 224 | err = readl(ecc->regs + ECC_DECENUM0 + offset); |
| 224 | − err = err >> ((i % 4) * 8); | |
| 225 | + err = err >> ((i % 4) * ecc->caps->err_shift); | |
| 225 | 226 | err &= ecc->caps->err_mask; |
| 226 | 227 | if (err == ecc->caps->err_mask) { |
| 227 | 228 | /* uncorrectable errors */ |
| @@ -449,6 +450,7 @@ EXPORT_SYMBOL(mtk_ecc_get_parity_bits); · 221 unmodified lines | ||
| 449 | 450 | |
| 450 | 451 | static const struct mtk_ecc_caps mtk_ecc_caps_mt2701 = { |
| 451 | 452 | .err_mask = 0x3f, |
| 453 | + .err_shift = 8, | |
| 452 | 454 | .ecc_strength = ecc_strength_mt2701, |
| 453 | 455 | .ecc_regs = mt2701_ecc_regs, |
| 454 | 456 | .num_ecc_strength = 20, |
| @@ -459,6 +461,7 @@ static const struct mtk_ecc_caps mtk_ecc_caps_mt2701 = { · 4 unmodified lines | ||
| 459 | 461 | |
| 460 | 462 | static const struct mtk_ecc_caps mtk_ecc_caps_mt2712 = { |
| 461 | 463 | .err_mask = 0x7f, |
| 464 | + .err_shift = 8, | |
| 462 | 465 | .ecc_strength = ecc_strength_mt2712, |
| 463 | 466 | .ecc_regs = mt2712_ecc_regs, |
| 464 | 467 | .num_ecc_strength = 23, |
| @@ -468,10 +471,11 @@ static const struct mtk_ecc_caps mtk_ecc_caps_mt2712 = { · 3 unmodified lines | ||
| 468 | 471 | }; |
| 469 | 472 | |
| 470 | 473 | static const struct mtk_ecc_caps mtk_ecc_caps_mt7622 = { |
| 471 | − .err_mask = 0x3f, | |
| 474 | + .err_mask = 0x1f, | |
| 475 | + .err_shift = 5, | |
| 472 | 476 | .ecc_strength = ecc_strength_mt7622, |
| 473 | 477 | .ecc_regs = mt7622_ecc_regs, |
| 474 | − .num_ecc_strength = 7, | |
| 478 | + .num_ecc_strength = 5, | |
| 475 | 479 | .ecc_mode_shift = 4, |
| 476 | 480 | .parity_bits = 13, |
| 477 | 481 | .pg_irq_sel = 0, |
| @@ -2651,10 +2651,23 @@ static int qcom_nand_attach_chip(struct nand_chip *chip) · 2650 unmodified lines | ||
| 2651 | 2651 | ecc->engine_type = NAND_ECC_ENGINE_TYPE_ON_HOST; |
| 2652 | 2652 | |
| 2653 | 2653 | mtd_set_ooblayout(mtd, &qcom_nand_ooblayout_ops); |
| 2654 | + /* Free the initially allocated BAM transaction for reading the ONFI params */ | |
| 2655 | + if (nandc->props->is_bam) | |
| 2656 | + free_bam_transaction(nandc); | |
| 2654 | 2657 | |
| 2655 | 2658 | nandc->max_cwperpage = max_t(unsigned int, nandc->max_cwperpage, |
| 2656 | 2659 | cwperpage); |
| 2657 | 2660 | |
| 2661 | + /* Now allocate the BAM transaction based on updated max_cwperpage */ | |
| 2662 | + if (nandc->props->is_bam) { | |
| 2663 | + nandc->bam_txn = alloc_bam_transaction(nandc); | |
| 2664 | + if (!nandc->bam_txn) { | |
| 2665 | + dev_err(nandc->dev, | |
| 2666 | + "failed to allocate bam transaction\n"); | |
| 2667 | + return -ENOMEM; | |
| 2668 | + } | |
| 2669 | + } | |
| 2670 | + | |
| 2658 | 2671 | /* |
| 2659 | 2672 | * DATA_UD_BYTES varies based on whether the read/write command protects |
| 2660 | 2673 | * spare data with ECC too. We protect spare data by default, so we set |
| @@ -2955,17 +2968,6 @@ static int qcom_nand_host_init_and_register(struct qcom_nand_controller *nandc, · 294 unmodified lines | ||
| 2955 | 2968 | if (ret) |
| 2956 | 2969 | return ret; |
| 2957 | 2970 | |
| 2958 | − if (nandc->props->is_bam) { | |
| 2959 | − free_bam_transaction(nandc); | |
| 2960 | − nandc->bam_txn = alloc_bam_transaction(nandc); | |
| 2961 | − if (!nandc->bam_txn) { | |
| 2962 | − dev_err(nandc->dev, | |
| 2963 | − "failed to allocate bam transaction\n"); | |
| 2964 | − nand_cleanup(chip); | |
| 2965 | − return -ENOMEM; | |
| 2966 | − } | |
| 2967 | − } | |
| 2968 | − | |
| 2969 | 2971 | ret = mtd_device_parse_register(mtd, probes, NULL, NULL, 0); |
| 2970 | 2972 | if (ret) |
| 2971 | 2973 | nand_cleanup(chip); |
| @@ -384,7 +384,8 @@ static int flctl_dma_fifo0_transfer(struct sh_flctl *flctl, unsigned long *buf, · 383 unmodified lines | ||
| 384 | 384 | dma_addr_t dma_addr; |
| 385 | 385 | dma_cookie_t cookie; |
| 386 | 386 | uint32_t reg; |
| 387 | − int ret; | |
| 387 | + int ret = 0; | |
| 388 | + unsigned long time_left; | |
| 388 | 389 | |
| 389 | 390 | if (dir == DMA_FROM_DEVICE) { |
| 390 | 391 | chan = flctl->chan_fifo0_rx; |
| @@ -425,13 +426,14 @@ static int flctl_dma_fifo0_transfer(struct sh_flctl *flctl, unsigned long *buf, · 34 unmodified lines | ||
| 425 | 426 | goto out; |
| 426 | 427 | } |
| 427 | 428 | |
| 428 | − ret = | |
| 429 | + time_left = | |
| 429 | 430 | wait_for_completion_timeout(&flctl->dma_complete, |
| 430 | 431 | msecs_to_jiffies(3000)); |
| 431 | 432 | |
| 432 | − if (ret <= 0) { | |
| 433 | + if (time_left == 0) { | |
| 433 | 434 | dmaengine_terminate_all(chan); |
| 434 | 435 | dev_err(&flctl->pdev->dev, "wait_for_completion_timeout\n"); |
| 436 | + ret = -ETIMEDOUT; | |
| 435 | 437 | } |
| 436 | 438 | |
| 437 | 439 | out: |
| @@ -441,7 +443,7 @@ out: · 3 unmodified lines | ||
| 441 | 443 | |
| 442 | 444 | dma_unmap_single(chan->device->dev, dma_addr, len, dir); |
| 443 | 445 | |
| 444 | − /* ret > 0 is success */ | |
| 446 | + /* ret == 0 is success */ | |
| 445 | 447 | return ret; |
| 446 | 448 | } |
| 447 | 449 | |
| @@ -465,7 +467,7 @@ static void read_fiforeg(struct sh_flctl *flctl, int rlen, int offset) · 17 unmodified lines | ||
| 465 | 467 | |
| 466 | 468 | /* initiate DMA transfer */ |
| 467 | 469 | if (flctl->chan_fifo0_rx && rlen >= 32 && |
| 468 | − flctl_dma_fifo0_transfer(flctl, buf, rlen, DMA_FROM_DEVICE) > 0) | |
| 470 | + !flctl_dma_fifo0_transfer(flctl, buf, rlen, DMA_FROM_DEVICE)) | |
| 469 | 471 | goto convert; /* DMA success */ |
| 470 | 472 | |
| 471 | 473 | /* do polling transfer */ |
| @@ -524,7 +526,7 @@ static void write_ec_fiforeg(struct sh_flctl *flctl, int rlen, · 52 unmodified lines | ||
| 524 | 526 | |
| 525 | 527 | /* initiate DMA transfer */ |
| 526 | 528 | if (flctl->chan_fifo0_tx && rlen >= 32 && |
| 527 | − flctl_dma_fifo0_transfer(flctl, buf, rlen, DMA_TO_DEVICE) > 0) | |
| 529 | + !flctl_dma_fifo0_transfer(flctl, buf, rlen, DMA_TO_DEVICE)) | |
| 528 | 530 | return; /* DMA success */ |
| 529 | 531 | |
| 530 | 532 | /* do polling transfer */ |
| @@ -241,13 +241,14 @@ struct grcan_device_config { · 240 unmodified lines | ||
| 241 | 241 | .rxsize = GRCAN_DEFAULT_BUFFER_SIZE, \ |
| 242 | 242 | } |
| 243 | 243 | |
| 244 | −#define GRCAN_TXBUG_SAFE_GRLIB_VERSION 0x4100 | |
| 244 | +#define GRCAN_TXBUG_SAFE_GRLIB_VERSION 4100 | |
| 245 | 245 | #define GRLIB_VERSION_MASK 0xffff |
| 246 | 246 | |
| 247 | 247 | /* GRCAN private data structure */ |
| 248 | 248 | struct grcan_priv { |
| 249 | 249 | struct can_priv can; /* must be the first member */ |
| 250 | 250 | struct net_device *dev; |
| 251 | + struct device *ofdev_dev; | |
| 251 | 252 | struct napi_struct napi; |
| 252 | 253 | |
| 253 | 254 | struct grcan_registers __iomem *regs; /* ioremap'ed registers */ |
| @@ -921,7 +922,7 @@ static void grcan_free_dma_buffers(struct net_device *dev) · 667 unmodified lines | ||
| 921 | 922 | struct grcan_priv *priv = netdev_priv(dev); |
| 922 | 923 | struct grcan_dma *dma = &priv->dma; |
| 923 | 924 | |
| 924 | − dma_free_coherent(&dev->dev, dma->base_size, dma->base_buf, | |
| 925 | + dma_free_coherent(priv->ofdev_dev, dma->base_size, dma->base_buf, | |
| 925 | 926 | dma->base_handle); |
| 926 | 927 | memset(dma, 0, sizeof(*dma)); |
| 927 | 928 | } |
| @@ -946,7 +947,7 @@ static int grcan_allocate_dma_buffers(struct net_device *dev, · 18 unmodified lines | ||
| 946 | 947 | |
| 947 | 948 | /* Extra GRCAN_BUFFER_ALIGNMENT to allow for alignment */ |
| 948 | 949 | dma->base_size = lsize + ssize + GRCAN_BUFFER_ALIGNMENT; |
| 949 | − dma->base_buf = dma_alloc_coherent(&dev->dev, | |
| 950 | + dma->base_buf = dma_alloc_coherent(priv->ofdev_dev, | |
| 950 | 951 | dma->base_size, |
| 951 | 952 | &dma->base_handle, |
| 952 | 953 | GFP_KERNEL); |
| @@ -1102,8 +1103,10 @@ static int grcan_close(struct net_device *dev) · 149 unmodified lines | ||
| 1102 | 1103 | |
| 1103 | 1104 | priv->closing = true; |
| 1104 | 1105 | if (priv->need_txbug_workaround) { |
| 1106 | + spin_unlock_irqrestore(&priv->lock, flags); | |
| 1105 | 1107 | del_timer_sync(&priv->hang_timer); |
| 1106 | 1108 | del_timer_sync(&priv->rr_timer); |
| 1109 | + spin_lock_irqsave(&priv->lock, flags); | |
| 1107 | 1110 | } |
| 1108 | 1111 | netif_stop_queue(dev); |
| 1109 | 1112 | grcan_stop_hardware(dev); |
| @@ -1122,7 +1125,7 @@ static int grcan_close(struct net_device *dev) · 12 unmodified lines | ||
| 1122 | 1125 | return 0; |
| 1123 | 1126 | } |
| 1124 | 1127 | |
| 1125 | −static int grcan_transmit_catch_up(struct net_device *dev, int budget) | |
| 1128 | +static void grcan_transmit_catch_up(struct net_device *dev) | |
| 1126 | 1129 | { |
| 1127 | 1130 | struct grcan_priv *priv = netdev_priv(dev); |
| 1128 | 1131 | unsigned long flags; |
| @@ -1130,7 +1133,7 @@ static int grcan_transmit_catch_up(struct net_device *dev, int budget) · 1 unmodified line | ||
| 1130 | 1133 | |
| 1131 | 1134 | spin_lock_irqsave(&priv->lock, flags); |
| 1132 | 1135 | |
| 1133 | − work_done = catch_up_echo_skb(dev, budget, true); | |
| 1136 | + work_done = catch_up_echo_skb(dev, -1, true); | |
| 1134 | 1137 | if (work_done) { |
| 1135 | 1138 | if (!priv->resetting && !priv->closing && |
| 1136 | 1139 | !(priv->can.ctrlmode & CAN_CTRLMODE_LISTENONLY)) |
| @@ -1144,8 +1147,6 @@ static int grcan_transmit_catch_up(struct net_device *dev, int budget) · 7 unmodified lines | ||
| 1144 | 1147 | } |
| 1145 | 1148 | |
| 1146 | 1149 | spin_unlock_irqrestore(&priv->lock, flags); |
| 1147 | − | |
| 1148 | − return work_done; | |
| 1149 | 1150 | } |
| 1150 | 1151 | |
| 1151 | 1152 | static int grcan_receive(struct net_device *dev, int budget) |
| @@ -1227,19 +1228,13 @@ static int grcan_poll(struct napi_struct *napi, int budget) · 75 unmodified lines | ||
| 1227 | 1228 | struct net_device *dev = priv->dev; |
| 1228 | 1229 | struct grcan_registers __iomem *regs = priv->regs; |
| 1229 | 1230 | unsigned long flags; |
| 1230 | − int tx_work_done, rx_work_done; | |
| 1231 | − int rx_budget = budget / 2; | |
| 1232 | − int tx_budget = budget - rx_budget; | |
| 1231 | + int work_done; | |
| 1233 | 1232 | |
| 1234 | − /* Half of the budget for receiving messages */ | |
| 1235 | − rx_work_done = grcan_receive(dev, rx_budget); | |
| 1233 | + work_done = grcan_receive(dev, budget); | |
| 1236 | 1234 | |
| 1237 | − /* Half of the budget for transmitting messages as that can trigger echo | |
| 1238 | − * frames being received | |
| 1239 | − */ | |
| 1240 | − tx_work_done = grcan_transmit_catch_up(dev, tx_budget); | |
| 1235 | + grcan_transmit_catch_up(dev); | |
| 1241 | 1236 | |
| 1242 | − if (rx_work_done < rx_budget && tx_work_done < tx_budget) { | |
| 1237 | + if (work_done < budget) { | |
| 1243 | 1238 | napi_complete(napi); |
| 1244 | 1239 | |
| 1245 | 1240 | /* Guarantee no interference with a running reset that otherwise |
| @@ -1256,7 +1251,7 @@ static int grcan_poll(struct napi_struct *napi, int budget) · 10 unmodified lines | ||
| 1256 | 1251 | spin_unlock_irqrestore(&priv->lock, flags); |
| 1257 | 1252 | } |
| 1258 | 1253 | |
| 1259 | − return rx_work_done + tx_work_done; | |
| 1254 | + return work_done; | |
| 1260 | 1255 | } |
| 1261 | 1256 | |
| 1262 | 1257 | /* Work tx bug by waiting while for the risky situation to clear. If that fails, |
| @@ -1587,6 +1582,7 @@ static int grcan_setup_netdev(struct platform_device *ofdev, · 324 unmodified lines | ||
| 1587 | 1582 | memcpy(&priv->config, &grcan_module_config, |
| 1588 | 1583 | sizeof(struct grcan_device_config)); |
| 1589 | 1584 | priv->dev = dev; |
| 1585 | + priv->ofdev_dev = &ofdev->dev; | |
| 1590 | 1586 | priv->regs = base; |
| 1591 | 1587 | priv->can.bittiming_const = &grcan_bittiming_const; |
| 1592 | 1588 | priv->can.do_set_bittiming = grcan_set_bittiming; |
| @@ -1639,6 +1635,7 @@ exit_free_candev: · 46 unmodified lines | ||
| 1639 | 1635 | static int grcan_probe(struct platform_device *ofdev) |
| 1640 | 1636 | { |
| 1641 | 1637 | struct device_node *np = ofdev->dev.of_node; |
| 1638 | + struct device_node *sysid_parent; | |
| 1642 | 1639 | u32 sysid, ambafreq; |
| 1643 | 1640 | int irq, err; |
| 1644 | 1641 | void __iomem *base; |
| @@ -1647,10 +1644,15 @@ static int grcan_probe(struct platform_device *ofdev) · 2 unmodified lines | ||
| 1647 | 1644 | /* Compare GRLIB version number with the first that does not |
| 1648 | 1645 | * have the tx bug (see start_xmit) |
| 1649 | 1646 | */ |
| 1650 | − err = of_property_read_u32(np, "systemid", &sysid); | |
| 1651 | − if (!err && ((sysid & GRLIB_VERSION_MASK) | |
| 1652 | − >= GRCAN_TXBUG_SAFE_GRLIB_VERSION)) | |
| 1653 | − txbug = false; | |
| 1647 | + sysid_parent = of_find_node_by_path("/ambapp0"); | |
| 1648 | + if (sysid_parent) { | |
| 1649 | + of_node_get(sysid_parent); | |
| 1650 | + err = of_property_read_u32(sysid_parent, "systemid", &sysid); | |
| 1651 | + if (!err && ((sysid & GRLIB_VERSION_MASK) >= | |
| 1652 | + GRCAN_TXBUG_SAFE_GRLIB_VERSION)) | |
| 1653 | + txbug = false; | |
| 1654 | + of_node_put(sysid_parent); | |
| 1655 | + } | |
| 1654 | 1656 | |
| 1655 | 1657 | err = of_property_read_u32(np, "freq", &ambafreq); |
| 1656 | 1658 | if (err) { |
| @@ -1354,46 +1354,25 @@ static void b53_phylink_get_caps(struct dsa_switch *ds, int port, · 1353 unmodified lines | ||
| 1354 | 1354 | config->legacy_pre_march2020 = false; |
| 1355 | 1355 | } |
| 1356 | 1356 | |
| 1357 | −int b53_phylink_mac_link_state(struct dsa_switch *ds, int port, | |
| 1358 | − struct phylink_link_state *state) | |
| 1357 | +static struct phylink_pcs *b53_phylink_mac_select_pcs(struct dsa_switch *ds, | |
| 1358 | + int port, | |
| 1359 | + phy_interface_t interface) | |
| 1359 | 1360 | { |
| 1360 | 1361 | struct b53_device *dev = ds->priv; |
| 1361 | − int ret = -EOPNOTSUPP; | |
| 1362 | 1362 | |
| 1363 | − if ((phy_interface_mode_is_8023z(state->interface) || | |
| 1364 | − state->interface == PHY_INTERFACE_MODE_SGMII) && | |
| 1365 | − dev->ops->serdes_link_state) | |
| 1366 | − ret = dev->ops->serdes_link_state(dev, port, state); | |
| 1363 | + if (!dev->ops->phylink_mac_select_pcs) | |
| 1364 | + return NULL; | |
| 1367 | 1365 | |
| 1368 | − return ret; | |
| 1366 | + return dev->ops->phylink_mac_select_pcs(dev, port, interface); | |
| 1369 | 1367 | } |
| 1370 | −EXPORT_SYMBOL(b53_phylink_mac_link_state); | |
| 1371 | 1368 | |
| 1372 | 1369 | void b53_phylink_mac_config(struct dsa_switch *ds, int port, |
| 1373 | 1370 | unsigned int mode, |
| 1374 | 1371 | const struct phylink_link_state *state) |
| 1375 | 1372 | { |
| 1376 | − struct b53_device *dev = ds->priv; | |
| 1377 | − | |
| 1378 | − if (mode == MLO_AN_PHY || mode == MLO_AN_FIXED) | |
| 1379 | − return; | |
| 1380 | − | |
| 1381 | − if ((phy_interface_mode_is_8023z(state->interface) || | |
| 1382 | − state->interface == PHY_INTERFACE_MODE_SGMII) && | |
| 1383 | − dev->ops->serdes_config) | |
| 1384 | − dev->ops->serdes_config(dev, port, mode, state); | |
| 1385 | 1373 | } |
| 1386 | 1374 | EXPORT_SYMBOL(b53_phylink_mac_config); |
| 1387 | 1375 | |
| 1388 | −void b53_phylink_mac_an_restart(struct dsa_switch *ds, int port) | |
| 1389 | −{ | |
| 1390 | − struct b53_device *dev = ds->priv; | |
| 1391 | − | |
| 1392 | − if (dev->ops->serdes_an_restart) | |
| 1393 | − dev->ops->serdes_an_restart(dev, port); | |
| 1394 | −} | |
| 1395 | −EXPORT_SYMBOL(b53_phylink_mac_an_restart); | |
| 1396 | − | |
| 1397 | 1376 | void b53_phylink_mac_link_down(struct dsa_switch *ds, int port, |
| 1398 | 1377 | unsigned int mode, |
| 1399 | 1378 | phy_interface_t interface) |
| @@ -2269,9 +2248,8 @@ static const struct dsa_switch_ops b53_switch_ops = { · 869 unmodified lines | ||
| 2269 | 2248 | .phy_write = b53_phy_write16, |
| 2270 | 2249 | .adjust_link = b53_adjust_link, |
| 2271 | 2250 | .phylink_get_caps = b53_phylink_get_caps, |
| 2272 | − .phylink_mac_link_state = b53_phylink_mac_link_state, | |
| 2251 | + .phylink_mac_select_pcs = b53_phylink_mac_select_pcs, | |
| 2273 | 2252 | .phylink_mac_config = b53_phylink_mac_config, |
| 2274 | − .phylink_mac_an_restart = b53_phylink_mac_an_restart, | |
| 2275 | 2253 | .phylink_mac_link_down = b53_phylink_mac_link_down, |
| 2276 | 2254 | .phylink_mac_link_up = b53_phylink_mac_link_up, |
| 2277 | 2255 | .port_enable = b53_enable_port, |
| @@ -21,7 +21,7 @@ · 20 unmodified lines | ||
| 21 | 21 | |
| 22 | 22 | #include <linux/kernel.h> |
| 23 | 23 | #include <linux/mutex.h> |
| 24 | −#include <linux/phy.h> | |
| 24 | +#include <linux/phylink.h> | |
| 25 | 25 | #include <linux/etherdevice.h> |
| 26 | 26 | #include <net/dsa.h> |
| 27 | 27 | |
| @@ -29,7 +29,6 @@ · 1 unmodified line | ||
| 29 | 29 | |
| 30 | 30 | struct b53_device; |
| 31 | 31 | struct net_device; |
| 32 | −struct phylink_link_state; | |
| 33 | 32 | |
| 34 | 33 | struct b53_io_ops { |
| 35 | 34 | int (*read8)(struct b53_device *dev, u8 page, u8 reg, u8 *value); |
| @@ -48,13 +47,10 @@ struct b53_io_ops { · 12 unmodified lines | ||
| 48 | 47 | void (*irq_disable)(struct b53_device *dev, int port); |
| 49 | 48 | void (*phylink_get_caps)(struct b53_device *dev, int port, |
| 50 | 49 | struct phylink_config *config); |
| 50 | + struct phylink_pcs *(*phylink_mac_select_pcs)(struct b53_device *dev, | |
| 51 | + int port, | |
| 52 | + phy_interface_t interface); | |
| 51 | 53 | u8 (*serdes_map_lane)(struct b53_device *dev, int port); |
| 52 | − int (*serdes_link_state)(struct b53_device *dev, int port, | |
| 53 | − struct phylink_link_state *state); | |
| 54 | − void (*serdes_config)(struct b53_device *dev, int port, | |
| 55 | − unsigned int mode, | |
| 56 | − const struct phylink_link_state *state); | |
| 57 | − void (*serdes_an_restart)(struct b53_device *dev, int port); | |
| 58 | 54 | void (*serdes_link_set)(struct b53_device *dev, int port, |
| 59 | 55 | unsigned int mode, phy_interface_t interface, |
| 60 | 56 | bool link_up); |
| @@ -85,8 +81,15 @@ enum { · 24 unmodified lines | ||
| 85 | 81 | BCM7278_DEVICE_ID = 0x7278, |
| 86 | 82 | }; |
| 87 | 83 | |
| 84 | +struct b53_pcs { | |
| 85 | + struct phylink_pcs pcs; | |
| 86 | + struct b53_device *dev; | |
| 87 | + u8 lane; | |
| 88 | +}; | |
| 89 | + | |
| 88 | 90 | #define B53_N_PORTS 9 |
| 89 | 91 | #define B53_N_PORTS_25 6 |
| 92 | +#define B53_N_PCS 2 | |
| 90 | 93 | |
| 91 | 94 | struct b53_port { |
| 92 | 95 | u16 vlan_ctl_mask; |
| @@ -143,6 +146,8 @@ struct b53_device { · 50 unmodified lines | ||
| 143 | 146 | bool vlan_enabled; |
| 144 | 147 | unsigned int num_ports; |
| 145 | 148 | struct b53_port *ports; |
| 149 | + | |
| 150 | + struct b53_pcs pcs[B53_N_PCS]; | |
| 146 | 151 | }; |
| 147 | 152 | |
| 148 | 153 | #define b53_for_each_port(dev, i) \ |
| @@ -336,12 +341,9 @@ int b53_br_flags(struct dsa_switch *ds, int port, · 187 unmodified lines | ||
| 336 | 341 | struct netlink_ext_ack *extack); |
| 337 | 342 | int b53_setup_devlink_resources(struct dsa_switch *ds); |
| 338 | 343 | void b53_port_event(struct dsa_switch *ds, int port); |
| 339 | −int b53_phylink_mac_link_state(struct dsa_switch *ds, int port, | |
| 340 | − struct phylink_link_state *state); | |
| 341 | 344 | void b53_phylink_mac_config(struct dsa_switch *ds, int port, |
| 342 | 345 | unsigned int mode, |
| 343 | 346 | const struct phylink_link_state *state); |
| 344 | −void b53_phylink_mac_an_restart(struct dsa_switch *ds, int port); | |
| 345 | 347 | void b53_phylink_mac_link_down(struct dsa_switch *ds, int port, |
| 346 | 348 | unsigned int mode, |
| 347 | 349 | phy_interface_t interface); |
| @@ -17,6 +17,11 @@ · 16 unmodified lines | ||
| 17 | 17 | #include "b53_serdes.h" |
| 18 | 18 | #include "b53_regs.h" |
| 19 | 19 | |
| 20 | +static inline struct b53_pcs *pcs_to_b53_pcs(struct phylink_pcs *pcs) | |
| 21 | +{ | |
| 22 | + return container_of(pcs, struct b53_pcs, pcs); | |
| 23 | +} | |
| 24 | + | |
| 20 | 25 | static void b53_serdes_write_blk(struct b53_device *dev, u8 offset, u16 block, |
| 21 | 26 | u16 value) |
| 22 | 27 | { |
| @@ -60,51 +65,47 @@ static u16 b53_serdes_read(struct b53_device *dev, u8 lane, · 37 unmodified lines | ||
| 60 | 65 | return b53_serdes_read_blk(dev, offset, block); |
| 61 | 66 | } |
| 62 | 67 | |
| 63 | −void b53_serdes_config(struct b53_device *dev, int port, unsigned int mode, | |
| 64 | − const struct phylink_link_state *state) | |
| 68 | +static int b53_serdes_config(struct phylink_pcs *pcs, unsigned int mode, | |
| 69 | + phy_interface_t interface, | |
| 70 | + const unsigned long *advertising, | |
| 71 | + bool permit_pause_to_mac) | |
| 65 | 72 | { |
| 66 | − u8 lane = b53_serdes_map_lane(dev, port); | |
| 73 | + struct b53_device *dev = pcs_to_b53_pcs(pcs)->dev; | |
| 74 | + u8 lane = pcs_to_b53_pcs(pcs)->lane; | |
| 67 | 75 | u16 reg; |
| 68 | 76 | |
| 69 | − if (lane == B53_INVALID_LANE) | |
| 70 | − return; | |
| 71 | − | |
| 72 | 77 | reg = b53_serdes_read(dev, lane, B53_SERDES_DIGITAL_CONTROL(1), |
| 73 | 78 | SERDES_DIGITAL_BLK); |
| 74 | − if (state->interface == PHY_INTERFACE_MODE_1000BASEX) | |
| 79 | + if (interface == PHY_INTERFACE_MODE_1000BASEX) | |
| 75 | 80 | reg |= FIBER_MODE_1000X; |
| 76 | 81 | else |
| 77 | 82 | reg &= ~FIBER_MODE_1000X; |
| 78 | 83 | b53_serdes_write(dev, lane, B53_SERDES_DIGITAL_CONTROL(1), |
| 79 | 84 | SERDES_DIGITAL_BLK, reg); |
| 85 | + | |
| 86 | + return 0; | |
| 80 | 87 | } |
| 81 | −EXPORT_SYMBOL(b53_serdes_config); | |
| 82 | 88 | |
| 83 | −void b53_serdes_an_restart(struct b53_device *dev, int port) | |
| 89 | +static void b53_serdes_an_restart(struct phylink_pcs *pcs) | |
| 84 | 90 | { |
| 85 | − u8 lane = b53_serdes_map_lane(dev, port); | |
| 91 | + struct b53_device *dev = pcs_to_b53_pcs(pcs)->dev; | |
| 92 | + u8 lane = pcs_to_b53_pcs(pcs)->lane; | |
| 86 | 93 | u16 reg; |
| 87 | 94 | |
| 88 | − if (lane == B53_INVALID_LANE) | |
| 89 | − return; | |
| 90 | − | |
| 91 | 95 | reg = b53_serdes_read(dev, lane, B53_SERDES_MII_REG(MII_BMCR), |
| 92 | 96 | SERDES_MII_BLK); |
| 93 | 97 | reg |= BMCR_ANRESTART; |
| 94 | 98 | b53_serdes_write(dev, lane, B53_SERDES_MII_REG(MII_BMCR), |
| 95 | 99 | SERDES_MII_BLK, reg); |
| 96 | 100 | } |
| 97 | −EXPORT_SYMBOL(b53_serdes_an_restart); | |
| 98 | 101 | |
| 99 | −int b53_serdes_link_state(struct b53_device *dev, int port, | |
| 100 | − struct phylink_link_state *state) | |
| 102 | +static void b53_serdes_get_state(struct phylink_pcs *pcs, | |
| 103 | + struct phylink_link_state *state) | |
| 101 | 104 | { |
| 102 | − u8 lane = b53_serdes_map_lane(dev, port); | |
| 105 | + struct b53_device *dev = pcs_to_b53_pcs(pcs)->dev; | |
| 106 | + u8 lane = pcs_to_b53_pcs(pcs)->lane; | |
| 103 | 107 | u16 dig, bmsr; |
| 104 | 108 | |
| 105 | − if (lane == B53_INVALID_LANE) | |
| 106 | − return 1; | |
| 107 | − | |
| 108 | 109 | dig = b53_serdes_read(dev, lane, B53_SERDES_DIGITAL_STATUS, |
| 109 | 110 | SERDES_DIGITAL_BLK); |
| 110 | 111 | bmsr = b53_serdes_read(dev, lane, B53_SERDES_MII_REG(MII_BMSR), |
| @@ -133,10 +134,7 @@ int b53_serdes_link_state(struct b53_device *dev, int port, · 22 unmodified lines | ||
| 133 | 134 | state->pause |= MLO_PAUSE_RX; |
| 134 | 135 | if (dig & PAUSE_RESOLUTION_TX_SIDE) |
| 135 | 136 | state->pause |= MLO_PAUSE_TX; |
| 136 | − | |
| 137 | − return 0; | |
| 138 | 137 | } |
| 139 | −EXPORT_SYMBOL(b53_serdes_link_state); | |
| 140 | 138 | |
| 141 | 139 | void b53_serdes_link_set(struct b53_device *dev, int port, unsigned int mode, |
| 142 | 140 | phy_interface_t interface, bool link_up) |
| @@ -158,6 +156,12 @@ void b53_serdes_link_set(struct b53_device *dev, int port, unsigned int mode, · 15 unmodified lines | ||
| 158 | 156 | } |
| 159 | 157 | EXPORT_SYMBOL(b53_serdes_link_set); |
| 160 | 158 | |
| 159 | +static const struct phylink_pcs_ops b53_pcs_ops = { | |
| 160 | + .pcs_get_state = b53_serdes_get_state, | |
| 161 | + .pcs_config = b53_serdes_config, | |
| 162 | + .pcs_an_restart = b53_serdes_an_restart, | |
| 163 | +}; | |
| 164 | + | |
| 161 | 165 | void b53_serdes_phylink_get_caps(struct b53_device *dev, int port, |
| 162 | 166 | struct phylink_config *config) |
| 163 | 167 | { |
| @@ -187,9 +191,28 @@ void b53_serdes_phylink_get_caps(struct b53_device *dev, int port, · 23 unmodified lines | ||
| 187 | 191 | } |
| 188 | 192 | EXPORT_SYMBOL(b53_serdes_phylink_get_caps); |
| 189 | 193 | |
| 194 | +struct phylink_pcs *b53_serdes_phylink_mac_select_pcs(struct b53_device *dev, | |
| 195 | + int port, | |
| 196 | + phy_interface_t interface) | |
| 197 | +{ | |
| 198 | + u8 lane = b53_serdes_map_lane(dev, port); | |
| 199 | + | |
| 200 | + if (lane == B53_INVALID_LANE || lane >= B53_N_PCS || | |
| 201 | + !dev->pcs[lane].dev) | |
| 202 | + return NULL; | |
| 203 | + | |
| 204 | + if (!phy_interface_mode_is_8023z(interface) && | |
| 205 | + interface != PHY_INTERFACE_MODE_SGMII) | |
| 206 | + return NULL; | |
| 207 | + | |
| 208 | + return &dev->pcs[lane].pcs; | |
| 209 | +} | |
| 210 | +EXPORT_SYMBOL(b53_serdes_phylink_mac_select_pcs); | |
| 211 | + | |
| 190 | 212 | int b53_serdes_init(struct b53_device *dev, int port) |
| 191 | 213 | { |
| 192 | 214 | u8 lane = b53_serdes_map_lane(dev, port); |
| 215 | + struct b53_pcs *pcs; | |
| 193 | 216 | u16 id0, msb, lsb; |
| 194 | 217 | |
| 195 | 218 | if (lane == B53_INVALID_LANE) |
| @@ -212,6 +235,11 @@ int b53_serdes_init(struct b53_device *dev, int port) · 16 unmodified lines | ||
| 212 | 235 | (id0 >> SERDES_ID0_REV_NUM_SHIFT) & SERDES_ID0_REV_NUM_MASK, |
| 213 | 236 | (u32)msb << 16 | lsb); |
| 214 | 237 | |
| 238 | + pcs = &dev->pcs[lane]; | |
| 239 | + pcs->dev = dev; | |
| 240 | + pcs->lane = lane; | |
| 241 | + pcs->pcs.ops = &b53_pcs_ops; | |
| 242 | + | |
| 215 | 243 | return 0; |
| 216 | 244 | } |
| 217 | 245 | EXPORT_SYMBOL(b53_serdes_init); |
| @@ -107,14 +107,11 @@ static inline u8 b53_serdes_map_lane(struct b53_device *dev, int port) · 106 unmodified lines | ||
| 107 | 107 | return dev->ops->serdes_map_lane(dev, port); |
| 108 | 108 | } |
| 109 | 109 | |
| 110 | −int b53_serdes_get_link(struct b53_device *dev, int port); | |
| 111 | −int b53_serdes_link_state(struct b53_device *dev, int port, | |
| 112 | − struct phylink_link_state *state); | |
| 113 | −void b53_serdes_config(struct b53_device *dev, int port, unsigned int mode, | |
| 114 | − const struct phylink_link_state *state); | |
| 115 | −void b53_serdes_an_restart(struct b53_device *dev, int port); | |
| 116 | 110 | void b53_serdes_link_set(struct b53_device *dev, int port, unsigned int mode, |
| 117 | 111 | phy_interface_t interface, bool link_up); |
| 112 | +struct phylink_pcs *b53_serdes_phylink_mac_select_pcs(struct b53_device *dev, | |
| 113 | + int port, | |
| 114 | + phy_interface_t interface); | |
| 118 | 115 | void b53_serdes_phylink_get_caps(struct b53_device *dev, int port, |
| 119 | 116 | struct phylink_config *config); |
| 120 | 117 | #if IS_ENABLED(CONFIG_B53_SERDES) |
| @@ -491,10 +491,8 @@ static const struct b53_io_ops b53_srab_ops = { · 490 unmodified lines | ||
| 491 | 491 | .irq_disable = b53_srab_irq_disable, |
| 492 | 492 | .phylink_get_caps = b53_srab_phylink_get_caps, |
| 493 | 493 | #if IS_ENABLED(CONFIG_B53_SERDES) |
| 494 | + .phylink_mac_select_pcs = b53_serdes_phylink_mac_select_pcs, | |
| 494 | 495 | .serdes_map_lane = b53_srab_serdes_map_lane, |
| 495 | − .serdes_link_state = b53_serdes_link_state, | |
| 496 | − .serdes_config = b53_serdes_config, | |
| 497 | − .serdes_an_restart = b53_serdes_an_restart, | |
| 498 | 496 | .serdes_link_set = b53_serdes_link_set, |
| 499 | 497 | #endif |
| 500 | 498 | }; |
| @@ -809,6 +809,9 @@ static void bcm_sf2_sw_mac_link_down(struct dsa_switch *ds, int port, · 808 unmodified lines | ||
| 809 | 809 | struct bcm_sf2_priv *priv = bcm_sf2_to_priv(ds); |
| 810 | 810 | u32 reg, offset; |
| 811 | 811 | |
| 812 | + if (priv->wol_ports_mask & BIT(port)) | |
| 813 | + return; | |
| 814 | + | |
| 812 | 815 | if (port != core_readl(priv, CORE_IMP0_PRT_ID)) { |
| 813 | 816 | if (priv->type == BCM4908_DEVICE_ID || |
| 814 | 817 | priv->type == BCM7445_DEVICE_ID) |
| @@ -1681,9 +1681,6 @@ static void gswip_phylink_mac_config(struct dsa_switch *ds, int port, · 1680 unmodified lines | ||
| 1681 | 1681 | break; |
| 1682 | 1682 | case PHY_INTERFACE_MODE_RMII: |
| 1683 | 1683 | miicfg |= GSWIP_MII_CFG_MODE_RMIIM; |
| 1684 | − | |
| 1685 | − /* Configure the RMII clock as output: */ | |
| 1686 | − miicfg |= GSWIP_MII_CFG_RMII_CLK; | |
| 1687 | 1684 | break; |
| 1688 | 1685 | case PHY_INTERFACE_MODE_RGMII: |
| 1689 | 1686 | case PHY_INTERFACE_MODE_RGMII_ID: |
| @@ -1021,14 +1021,32 @@ static int ksz9477_port_mirror_add(struct dsa_switch *ds, int port, · 1020 unmodified lines | ||
| 1021 | 1021 | bool ingress, struct netlink_ext_ack *extack) |
| 1022 | 1022 | { |
| 1023 | 1023 | struct ksz_device *dev = ds->priv; |
| 1024 | + u8 data; | |
| 1025 | + int p; | |
| 1026 | + | |
| 1027 | + /* Limit to one sniffer port | |
| 1028 | + * Check if any of the port is already set for sniffing | |
| 1029 | + * If yes, instruct the user to remove the previous entry & exit | |
| 1030 | + */ | |
| 1031 | + for (p = 0; p < dev->port_cnt; p++) { | |
| 1032 | + /* Skip the current sniffing port */ | |
| 1033 | + if (p == mirror->to_local_port) | |
| 1034 | + continue; | |
| 1035 | + | |
| 1036 | + ksz_pread8(dev, p, P_MIRROR_CTRL, &data); | |
| 1037 | + | |
| 1038 | + if (data & PORT_MIRROR_SNIFFER) { | |
| 1039 | + NL_SET_ERR_MSG_MOD(extack, | |
| 1040 | + "Sniffer port is already configured, delete existing rules & retry"); | |
| 1041 | + return -EBUSY; | |
| 1042 | + } | |
| 1043 | + } | |
| 1024 | 1044 | |
| 1025 | 1045 | if (ingress) |
| 1026 | 1046 | ksz_port_cfg(dev, port, P_MIRROR_CTRL, PORT_MIRROR_RX, true); |
| 1027 | 1047 | else |
| 1028 | 1048 | ksz_port_cfg(dev, port, P_MIRROR_CTRL, PORT_MIRROR_TX, true); |
| 1029 | 1049 | |
| 1030 | − ksz_port_cfg(dev, port, P_MIRROR_CTRL, PORT_MIRROR_SNIFFER, false); | |
| 1031 | − | |
| 1032 | 1050 | /* configure mirror port */ |
| 1033 | 1051 | ksz_port_cfg(dev, mirror->to_local_port, P_MIRROR_CTRL, |
| 1034 | 1052 | PORT_MIRROR_SNIFFER, true); |
| @@ -1042,16 +1060,28 @@ static void ksz9477_port_mirror_del(struct dsa_switch *ds, int port, · 7 unmodified lines | ||
| 1042 | 1060 | struct dsa_mall_mirror_tc_entry *mirror) |
| 1043 | 1061 | { |
| 1044 | 1062 | struct ksz_device *dev = ds->priv; |
| 1063 | + bool in_use = false; | |
| 1045 | 1064 | u8 data; |
| 1065 | + int p; | |
| 1046 | 1066 | |
| 1047 | 1067 | if (mirror->ingress) |
| 1048 | 1068 | ksz_port_cfg(dev, port, P_MIRROR_CTRL, PORT_MIRROR_RX, false); |
| 1049 | 1069 | else |
| 1050 | 1070 | ksz_port_cfg(dev, port, P_MIRROR_CTRL, PORT_MIRROR_TX, false); |
| 1051 | 1071 | |
| 1052 | − ksz_pread8(dev, port, P_MIRROR_CTRL, &data); | |
| 1053 | 1072 | |
| 1054 | − if (!(data & (PORT_MIRROR_RX | PORT_MIRROR_TX))) | |
| 1073 | + /* Check if any of the port is still referring to sniffer port */ | |
| 1074 | + for (p = 0; p < dev->port_cnt; p++) { | |
| 1075 | + ksz_pread8(dev, p, P_MIRROR_CTRL, &data); | |
| 1076 | + | |
| 1077 | + if ((data & (PORT_MIRROR_RX | PORT_MIRROR_TX))) { | |
| 1078 | + in_use = true; | |
| 1079 | + break; | |
| 1080 | + } | |
| 1081 | + } | |
| 1082 | + | |
| 1083 | + /* delete sniffing if there are no other mirroring rules */ | |
| 1084 | + if (!in_use) | |
| 1055 | 1085 | ksz_port_cfg(dev, mirror->to_local_port, P_MIRROR_CTRL, |
| 1056 | 1086 | PORT_MIRROR_SNIFFER, false); |
| 1057 | 1087 | } |
| @@ -2229,6 +2229,7 @@ mt7530_setup(struct dsa_switch *ds) · 2228 unmodified lines | ||
| 2229 | 2229 | ret = of_get_phy_mode(mac_np, &interface); |
| 2230 | 2230 | if (ret && ret != -ENODEV) { |
| 2231 | 2231 | of_node_put(mac_np); |
| 2232 | + of_node_put(phy_node); | |
| 2232 | 2233 | return ret; |
| 2233 | 2234 | } |
| 2234 | 2235 | id = of_mdio_parse_addr(ds->dev, phy_node); |
| @@ -40,8 +40,9 @@ int mv88e6xxx_port_hidden_wait(struct mv88e6xxx_chip *chip) · 39 unmodified lines | ||
| 40 | 40 | { |
| 41 | 41 | int bit = __bf_shf(MV88E6XXX_PORT_RESERVED_1A_BUSY); |
| 42 | 42 | |
| 43 | − return mv88e6xxx_wait_bit(chip, MV88E6XXX_PORT_RESERVED_1A_CTRL_PORT, | |
| 44 | − MV88E6XXX_PORT_RESERVED_1A, bit, 0); | |
| 43 | + return mv88e6xxx_port_wait_bit(chip, | |
| 44 | + MV88E6XXX_PORT_RESERVED_1A_CTRL_PORT, | |
| 45 | + MV88E6XXX_PORT_RESERVED_1A, bit, 0); | |
| 45 | 46 | } |
| 46 | 47 | |
| 47 | 48 | int mv88e6xxx_port_hidden_read(struct mv88e6xxx_chip *chip, int block, int port, |
| @@ -403,6 +403,7 @@ static int felix_update_trapping_destinations(struct dsa_switch *ds, · 402 unmodified lines | ||
| 403 | 403 | { |
| 404 | 404 | struct ocelot *ocelot = ds->priv; |
| 405 | 405 | struct felix *felix = ocelot_to_felix(ocelot); |
| 406 | + struct ocelot_vcap_block *block_vcap_is2; | |
| 406 | 407 | struct ocelot_vcap_filter *trap; |
| 407 | 408 | enum ocelot_mask_mode mask_mode; |
| 408 | 409 | unsigned long port_mask; |
| @@ -422,9 +423,13 @@ static int felix_update_trapping_destinations(struct dsa_switch *ds, · 13 unmodified lines | ||
| 422 | 423 | /* We are sure that "cpu" was found, otherwise |
| 423 | 424 | * dsa_tree_setup_default_cpu() would have failed earlier. |
| 424 | 425 | */ |
| 426 | + block_vcap_is2 = &ocelot->block[VCAP_IS2]; | |
| 425 | 427 | |
| 426 | 428 | /* Make sure all traps are set up for that destination */ |
| 427 | − list_for_each_entry(trap, &ocelot->traps, trap_list) { | |
| 429 | + list_for_each_entry(trap, &block_vcap_is2->rules, list) { | |
| 430 | + if (!trap->is_trap) | |
| 431 | + continue; | |
| 432 | + | |
| 428 | 433 | /* Figure out the current trapping destination */ |
| 429 | 434 | if (using_tag_8021q) { |
| 430 | 435 | /* Redirect to the tag_8021q CPU port. If timestamps |
| @@ -267,7 +267,6 @@ static const struct of_device_id realtek_mdio_of_match[] = { · 266 unmodified lines | ||
| 267 | 267 | #endif |
| 268 | 268 | #if IS_ENABLED(CONFIG_NET_DSA_REALTEK_RTL8365MB) |
| 269 | 269 | { .compatible = "realtek,rtl8365mb", .data = &rtl8365mb_variant, }, |
| 270 | − { .compatible = "realtek,rtl8367s", .data = &rtl8365mb_variant, }, | |
| 271 | 270 | #endif |
| 272 | 271 | { /* sentinel */ }, |
| 273 | 272 | }; |
| @@ -551,10 +551,6 @@ static const struct of_device_id realtek_smi_of_match[] = { · 550 unmodified lines | ||
| 551 | 551 | .compatible = "realtek,rtl8365mb", |
| 552 | 552 | .data = &rtl8365mb_variant, |
| 553 | 553 | }, |
| 554 | − { | |
| 555 | − .compatible = "realtek,rtl8367s", | |
| 556 | − .data = &rtl8365mb_variant, | |
| 557 | − }, | |
| 558 | 554 | #endif |
| 559 | 555 | { /* sentinel */ }, |
| 560 | 556 | }; |
| @@ -449,7 +449,7 @@ static int aq_pm_freeze(struct device *dev) · 448 unmodified lines | ||
| 449 | 449 | |
| 450 | 450 | static int aq_pm_suspend_poweroff(struct device *dev) |
| 451 | 451 | { |
| 452 | − return aq_suspend_common(dev, false); | |
| 452 | + return aq_suspend_common(dev, true); | |
| 453 | 453 | } |
| 454 | 454 | |
| 455 | 455 | static int aq_pm_thaw(struct device *dev) |
| @@ -459,7 +459,7 @@ static int aq_pm_thaw(struct device *dev) · 3 unmodified lines | ||
| 459 | 459 | |
| 460 | 460 | static int aq_pm_resume_restore(struct device *dev) |
| 461 | 461 | { |
| 462 | − return atl_resume_common(dev, false); | |
| 462 | + return atl_resume_common(dev, true); | |
| 463 | 463 | } |
| 464 | 464 | |
| 465 | 465 | static const struct dev_pm_ops aq_pm_ops = { |
| @@ -346,7 +346,6 @@ int aq_ring_rx_clean(struct aq_ring_s *self, · 345 unmodified lines | ||
| 346 | 346 | int budget) |
| 347 | 347 | { |
| 348 | 348 | struct net_device *ndev = aq_nic_get_ndev(self->aq_nic); |
| 349 | − bool is_rsc_completed = true; | |
| 350 | 349 | int err = 0; |
| 351 | 350 | |
| 352 | 351 | for (; (self->sw_head != self->hw_head) && budget; |
| @@ -364,12 +363,17 @@ int aq_ring_rx_clean(struct aq_ring_s *self, · 11 unmodified lines | ||
| 364 | 363 | continue; |
| 365 | 364 | |
| 366 | 365 | if (!buff->is_eop) { |
| 366 | + unsigned int frag_cnt = 0U; | |
| 367 | 367 | buff_ = buff; |
| 368 | 368 | do { |
| 369 | + bool is_rsc_completed = true; | |
| 370 | + | |
| 369 | 371 | if (buff_->next >= self->size) { |
| 370 | 372 | err = -EIO; |
| 371 | 373 | goto err_exit; |
| 372 | 374 | } |
| 375 | + | |
| 376 | + frag_cnt++; | |
| 373 | 377 | next_ = buff_->next, |
| 374 | 378 | buff_ = &self->buff_ring[next_]; |
| 375 | 379 | is_rsc_completed = |
| @@ -377,18 +381,17 @@ int aq_ring_rx_clean(struct aq_ring_s *self, · 1 unmodified line | ||
| 377 | 381 | next_, |
| 378 | 382 | self->hw_head); |
| 379 | 383 | |
| 380 | − if (unlikely(!is_rsc_completed)) | |
| 381 | − break; | |
| 384 | + if (unlikely(!is_rsc_completed) || | |
| 385 | + frag_cnt > MAX_SKB_FRAGS) { | |
| 386 | + err = 0; | |
| 387 | + goto err_exit; | |
| 388 | + } | |
| 382 | 389 | |
| 383 | 390 | buff->is_error |= buff_->is_error; |
| 384 | 391 | buff->is_cso_err |= buff_->is_cso_err; |
| 385 | 392 | |
| 386 | 393 | } while (!buff_->is_eop); |
| 387 | 394 | |
| 388 | − if (!is_rsc_completed) { | |
| 389 | − err = 0; | |
| 390 | − goto err_exit; | |
| 391 | − } | |
| 392 | 395 | if (buff->is_error || |
| 393 | 396 | (buff->is_lro && buff->is_cso_err)) { |
| 394 | 397 | buff_ = buff; |
| @@ -446,7 +449,7 @@ int aq_ring_rx_clean(struct aq_ring_s *self, · 51 unmodified lines | ||
| 446 | 449 | ALIGN(hdr_len, sizeof(long))); |
| 447 | 450 | |
| 448 | 451 | if (buff->len - hdr_len > 0) { |
| 449 | − skb_add_rx_frag(skb, 0, buff->rxdata.page, | |
| 452 | + skb_add_rx_frag(skb, i++, buff->rxdata.page, | |
| 450 | 453 | buff->rxdata.pg_off + hdr_len, |
| 451 | 454 | buff->len - hdr_len, |
| 452 | 455 | AQ_CFG_RX_FRAME_MAX); |
| @@ -455,7 +458,6 @@ int aq_ring_rx_clean(struct aq_ring_s *self, · 2 unmodified lines | ||
| 455 | 458 | |
| 456 | 459 | if (!buff->is_eop) { |
| 457 | 460 | buff_ = buff; |
| 458 | − i = 1U; | |
| 459 | 461 | do { |
| 460 | 462 | next_ = buff_->next; |
| 461 | 463 | buff_ = &self->buff_ring[next_]; |
| @@ -889,6 +889,13 @@ int hw_atl_b0_hw_ring_tx_head_update(struct aq_hw_s *self, · 888 unmodified lines | ||
| 889 | 889 | err = -ENXIO; |
| 890 | 890 | goto err_exit; |
| 891 | 891 | } |
| 892 | + | |
| 893 | + /* Validate that the new hw_head_ is reasonable. */ | |
| 894 | + if (hw_head_ >= ring->size) { | |
| 895 | + err = -ENXIO; | |
| 896 | + goto err_exit; | |
| 897 | + } | |
| 898 | + | |
| 892 | 899 | ring->hw_head = hw_head_; |
| 893 | 900 | err = aq_hw_err_from_flags(self); |
| 894 | 901 | |
| @@ -14153,10 +14153,6 @@ static int bnx2x_eeh_nic_unload(struct bnx2x *bp) · 14152 unmodified lines | ||
| 14153 | 14153 | |
| 14154 | 14154 | /* Stop Tx */ |
| 14155 | 14155 | bnx2x_tx_disable(bp); |
| 14156 | − /* Delete all NAPI objects */ | |
| 14157 | − bnx2x_del_all_napi(bp); | |
| 14158 | − if (CNIC_LOADED(bp)) | |
| 14159 | − bnx2x_del_all_napi_cnic(bp); | |
| 14160 | 14156 | netdev_reset_tc(bp->dev); |
| 14161 | 14157 | |
| 14162 | 14158 | del_timer_sync(&bp->timer); |
| @@ -14261,6 +14257,11 @@ static pci_ers_result_t bnx2x_io_slot_reset(struct pci_dev *pdev) · 98 unmodified lines | ||
| 14261 | 14257 | bnx2x_drain_tx_queues(bp); |
| 14262 | 14258 | bnx2x_send_unload_req(bp, UNLOAD_RECOVERY); |
| 14263 | 14259 | bnx2x_netif_stop(bp, 1); |
| 14260 | + bnx2x_del_all_napi(bp); | |
| 14261 | + | |
| 14262 | + if (CNIC_LOADED(bp)) | |
| 14263 | + bnx2x_del_all_napi_cnic(bp); | |
| 14264 | + | |
| 14264 | 14265 | bnx2x_free_irq(bp); |
| 14265 | 14266 | |
| 14266 | 14267 | /* Report UNLOAD_DONE to MCP */ |
| @@ -2707,6 +2707,10 @@ static int bnxt_poll_p5(struct napi_struct *napi, int budget) · 2706 unmodified lines | ||
| 2707 | 2707 | u32 idx = le32_to_cpu(nqcmp->cq_handle_low); |
| 2708 | 2708 | struct bnxt_cp_ring_info *cpr2; |
| 2709 | 2709 | |
| 2710 | + /* No more budget for RX work */ | |
| 2711 | + if (budget && work_done >= budget && idx == BNXT_RX_HDL) | |
| 2712 | + break; | |
| 2713 | + | |
| 2710 | 2714 | cpr2 = cpr->cp_ring_arr[idx]; |
| 2711 | 2715 | work_done += __bnxt_poll_work(bp, cpr2, |
| 2712 | 2716 | budget - work_done); |
| @@ -10983,7 +10987,7 @@ static bool bnxt_rfs_capable(struct bnxt *bp) · 8270 unmodified lines | ||
| 10983 | 10987 | |
| 10984 | 10988 | if (bp->flags & BNXT_FLAG_CHIP_P5) |
| 10985 | 10989 | return bnxt_rfs_supported(bp); |
| 10986 | − if (!(bp->flags & BNXT_FLAG_MSIX_CAP) || !bnxt_can_reserve_rings(bp)) | |
| 10990 | + if (!(bp->flags & BNXT_FLAG_MSIX_CAP) || !bnxt_can_reserve_rings(bp) || !bp->rx_nr_rings) | |
| 10987 | 10991 | return false; |
| 10988 | 10992 | |
| 10989 | 10993 | vnics = 1 + bp->rx_nr_rings; |
| @@ -13234,10 +13238,9 @@ static int bnxt_init_dflt_ring_mode(struct bnxt *bp) · 2244 unmodified lines | ||
| 13234 | 13238 | goto init_dflt_ring_err; |
| 13235 | 13239 | |
| 13236 | 13240 | bp->tx_nr_rings_per_tc = bp->tx_nr_rings; |
| 13237 | − if (bnxt_rfs_supported(bp) && bnxt_rfs_capable(bp)) { | |
| 13238 | − bp->flags |= BNXT_FLAG_RFS; | |
| 13239 | − bp->dev->features |= NETIF_F_NTUPLE; | |
| 13240 | − } | |
| 13241 | + | |
| 13242 | + bnxt_set_dflt_rfs(bp); | |
| 13243 | + | |
| 13241 | 13244 | init_dflt_ring_err: |
| 13242 | 13245 | bnxt_ulp_irq_restart(bp, rc); |
| 13243 | 13246 | return rc; |
| @@ -846,13 +846,6 @@ int bnxt_ptp_init(struct bnxt *bp, bool phc_cfg) · 845 unmodified lines | ||
| 846 | 846 | if (rc) |
| 847 | 847 | return rc; |
| 848 | 848 | |
| 849 | − if (bp->fw_cap & BNXT_FW_CAP_PTP_RTC) { | |
| 850 | − bnxt_ptp_timecounter_init(bp, false); | |
| 851 | − rc = bnxt_ptp_init_rtc(bp, phc_cfg); | |
| 852 | − if (rc) | |
| 853 | − goto out; | |
| 854 | − } | |
| 855 | − | |
| 856 | 849 | if (ptp->ptp_clock && bnxt_pps_config_ok(bp)) |
| 857 | 850 | return 0; |
| 858 | 851 | |
| @@ -861,8 +854,14 @@ int bnxt_ptp_init(struct bnxt *bp, bool phc_cfg) · 2 unmodified lines | ||
| 861 | 854 | atomic_set(&ptp->tx_avail, BNXT_MAX_TX_TS); |
| 862 | 855 | spin_lock_init(&ptp->ptp_lock); |
| 863 | 856 | |
| 864 | − if (!(bp->fw_cap & BNXT_FW_CAP_PTP_RTC)) | |
| 857 | + if (bp->fw_cap & BNXT_FW_CAP_PTP_RTC) { | |
| 858 | + bnxt_ptp_timecounter_init(bp, false); | |
| 859 | + rc = bnxt_ptp_init_rtc(bp, phc_cfg); | |
| 860 | + if (rc) | |
| 861 | + goto out; | |
| 862 | + } else { | |
| 865 | 863 | bnxt_ptp_timecounter_init(bp, true); |
| 864 | + } | |
| 866 | 865 | |
| 867 | 866 | ptp->ptp_info = bnxt_ptp_caps; |
| 868 | 867 | if ((bp->fw_cap & BNXT_FW_CAP_PTP_PPS)) { |
| @@ -2035,6 +2035,11 @@ static struct sk_buff *bcmgenet_add_tsb(struct net_device *dev, · 2034 unmodified lines | ||
| 2035 | 2035 | return skb; |
| 2036 | 2036 | } |
| 2037 | 2037 | |
| 2038 | +static void bcmgenet_hide_tsb(struct sk_buff *skb) | |
| 2039 | +{ | |
| 2040 | + __skb_pull(skb, sizeof(struct status_64)); | |
| 2041 | +} | |
| 2042 | + | |
| 2038 | 2043 | static netdev_tx_t bcmgenet_xmit(struct sk_buff *skb, struct net_device *dev) |
| 2039 | 2044 | { |
| 2040 | 2045 | struct bcmgenet_priv *priv = netdev_priv(dev); |
| @@ -2141,6 +2146,8 @@ static netdev_tx_t bcmgenet_xmit(struct sk_buff *skb, struct net_device *dev) · 100 unmodified lines | ||
| 2141 | 2146 | } |
| 2142 | 2147 | |
| 2143 | 2148 | GENET_CB(skb)->last_cb = tx_cb_ptr; |
| 2149 | + | |
| 2150 | + bcmgenet_hide_tsb(skb); | |
| 2144 | 2151 | skb_tx_timestamp(skb); |
| 2145 | 2152 | |
| 2146 | 2153 | /* Decrement total BD count and advance our write pointer */ |
| @@ -3992,6 +3999,10 @@ static int bcmgenet_probe(struct platform_device *pdev) · 1845 unmodified lines | ||
| 3992 | 3999 | goto err; |
| 3993 | 4000 | } |
| 3994 | 4001 | priv->wol_irq = platform_get_irq_optional(pdev, 2); |
| 4002 | + if (priv->wol_irq == -EPROBE_DEFER) { | |
| 4003 | + err = priv->wol_irq; | |
| 4004 | + goto err; | |
| 4005 | + } | |
| 3995 | 4006 | |
| 3996 | 4007 | priv->base = devm_platform_ioremap_resource(pdev, 0); |
| 3997 | 4008 | if (IS_ERR(priv->base)) { |
| @@ -59,7 +59,7 @@ struct nicpf { · 58 unmodified lines | ||
| 59 | 59 | |
| 60 | 60 | /* MSI-X */ |
| 61 | 61 | u8 num_vec; |
| 62 | − bool irq_allocated[NIC_PF_MSIX_VECTORS]; | |
| 62 | + unsigned int irq_allocated[NIC_PF_MSIX_VECTORS]; | |
| 63 | 63 | char irq_name[NIC_PF_MSIX_VECTORS][20]; |
| 64 | 64 | }; |
| 65 | 65 | |
| @@ -1150,7 +1150,7 @@ static irqreturn_t nic_mbx_intr_handler(int irq, void *nic_irq) · 1084 unmodified lines | ||
| 1150 | 1150 | u64 intr; |
| 1151 | 1151 | u8 vf; |
| 1152 | 1152 | |
| 1153 | − if (irq == pci_irq_vector(nic->pdev, NIC_PF_INTR_ID_MBOX0)) | |
| 1153 | + if (irq == nic->irq_allocated[NIC_PF_INTR_ID_MBOX0]) | |
| 1154 | 1154 | mbx = 0; |
| 1155 | 1155 | else |
| 1156 | 1156 | mbx = 1; |
| @@ -1176,14 +1176,14 @@ static void nic_free_all_interrupts(struct nicpf *nic) · 19 unmodified lines | ||
| 1176 | 1176 | |
| 1177 | 1177 | for (irq = 0; irq < nic->num_vec; irq++) { |
| 1178 | 1178 | if (nic->irq_allocated[irq]) |
| 1179 | − free_irq(pci_irq_vector(nic->pdev, irq), nic); | |
| 1180 | − nic->irq_allocated[irq] = false; | |
| 1179 | + free_irq(nic->irq_allocated[irq], nic); | |
| 1180 | + nic->irq_allocated[irq] = 0; | |
| 1181 | 1181 | } |
| 1182 | 1182 | } |
| 1183 | 1183 | |
| 1184 | 1184 | static int nic_register_interrupts(struct nicpf *nic) |
| 1185 | 1185 | { |
| 1186 | − int i, ret; | |
| 1186 | + int i, ret, irq; | |
| 1187 | 1187 | nic->num_vec = pci_msix_vec_count(nic->pdev); |
| 1188 | 1188 | |
| 1189 | 1189 | /* Enable MSI-X */ |
| @@ -1201,13 +1201,13 @@ static int nic_register_interrupts(struct nicpf *nic) · 11 unmodified lines | ||
| 1201 | 1201 | sprintf(nic->irq_name[i], |
| 1202 | 1202 | "NICPF Mbox%d", (i - NIC_PF_INTR_ID_MBOX0)); |
| 1203 | 1203 | |
| 1204 | − ret = request_irq(pci_irq_vector(nic->pdev, i), | |
| 1205 | − nic_mbx_intr_handler, 0, | |
| 1204 | + irq = pci_irq_vector(nic->pdev, i); | |
| 1205 | + ret = request_irq(irq, nic_mbx_intr_handler, 0, | |
| 1206 | 1206 | nic->irq_name[i], nic); |
| 1207 | 1207 | if (ret) |
| 1208 | 1208 | goto fail; |
| 1209 | 1209 | |
| 1210 | − nic->irq_allocated[i] = true; | |
| 1210 | + nic->irq_allocated[i] = irq; | |
| 1211 | 1211 | } |
| 1212 | 1212 | |
| 1213 | 1213 | /* Enable mailbox interrupt */ |
| @@ -2793,14 +2793,14 @@ int t4_get_raw_vpd_params(struct adapter *adapter, struct vpd_params *p) · 2792 unmodified lines | ||
| 2793 | 2793 | goto out; |
| 2794 | 2794 | na = ret; |
| 2795 | 2795 | |
| 2796 | − memcpy(p->id, vpd + id, min_t(int, id_len, ID_LEN)); | |
| 2796 | + memcpy(p->id, vpd + id, min_t(unsigned int, id_len, ID_LEN)); | |
| 2797 | 2797 | strim(p->id); |
| 2798 | − memcpy(p->sn, vpd + sn, min_t(int, sn_len, SERNUM_LEN)); | |
| 2798 | + memcpy(p->sn, vpd + sn, min_t(unsigned int, sn_len, SERNUM_LEN)); | |
| 2799 | 2799 | strim(p->sn); |
| 2800 | − memcpy(p->pn, vpd + pn, min_t(int, pn_len, PN_LEN)); | |
| 2800 | + memcpy(p->pn, vpd + pn, min_t(unsigned int, pn_len, PN_LEN)); | |
| 2801 | 2801 | strim(p->pn); |
| 2802 | − memcpy(p->na, vpd + na, min_t(int, na_len, MACADDR_LEN)); | |
| 2803 | − strim((char *)p->na); | |
| 2802 | + memcpy(p->na, vpd + na, min_t(unsigned int, na_len, MACADDR_LEN)); | |
| 2803 | + strim(p->na); | |
| 2804 | 2804 | |
| 2805 | 2805 | out: |
| 2806 | 2806 | vfree(vpd); |
| @@ -1399,8 +1399,10 @@ static int tulip_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) · 1398 unmodified lines | ||
| 1399 | 1399 | |
| 1400 | 1400 | /* alloc_etherdev ensures aligned and zeroed private structures */ |
| 1401 | 1401 | dev = alloc_etherdev (sizeof (*tp)); |
| 1402 | − if (!dev) | |
| 1402 | + if (!dev) { | |
| 1403 | + pci_disable_device(pdev); | |
| 1403 | 1404 | return -ENOMEM; |
| 1405 | + } | |
| 1404 | 1406 | |
| 1405 | 1407 | SET_NETDEV_DEV(dev, &pdev->dev); |
| 1406 | 1408 | if (pci_resource_len (pdev, 0) < tulip_tbl[chip_idx].io_size) { |
| @@ -1785,6 +1787,7 @@ err_out_free_res: · 378 unmodified lines | ||
| 1785 | 1787 | |
| 1786 | 1788 | err_out_free_netdev: |
| 1787 | 1789 | free_netdev (dev); |
| 1790 | + pci_disable_device(pdev); | |
| 1788 | 1791 | return -ENODEV; |
| 1789 | 1792 | } |
| 1790 | 1793 | |
| @@ -297,10 +297,6 @@ int enetc_setup_tc_txtime(struct net_device *ndev, void *type_data) · 296 unmodified lines | ||
| 297 | 297 | if (tc < 0 || tc >= priv->num_tx_rings) |
| 298 | 298 | return -EINVAL; |
| 299 | 299 | |
| 300 | − /* Do not support TXSTART and TX CSUM offload simutaniously */ | |
| 301 | − if (ndev->features & NETIF_F_CSUM_MASK) | |
| 302 | − return -EBUSY; | |
| 303 | − | |
| 304 | 300 | /* TSD and Qbv are mutually exclusive in hardware */ |
| 305 | 301 | if (enetc_rd(&priv->si->hw, ENETC_QBV_PTGCR_OFFSET) & ENETC_QBV_TGE) |
| 306 | 302 | return -EBUSY; |
| @@ -3731,7 +3731,7 @@ static int fec_enet_init_stop_mode(struct fec_enet_private *fep, · 3730 unmodified lines | ||
| 3731 | 3731 | ARRAY_SIZE(out_val)); |
| 3732 | 3732 | if (ret) { |
| 3733 | 3733 | dev_dbg(&fep->pdev->dev, "no stop mode property\n"); |
| 3734 | − return ret; | |
| 3734 | + goto out; | |
| 3735 | 3735 | } |
| 3736 | 3736 | |
| 3737 | 3737 | fep->stop_gpr.gpr = syscon_node_to_regmap(gpr_np); |
| @@ -1065,19 +1065,23 @@ int hns_mac_init(struct dsaf_device *dsaf_dev) · 1064 unmodified lines | ||
| 1065 | 1065 | device_for_each_child_node(dsaf_dev->dev, child) { |
| 1066 | 1066 | ret = fwnode_property_read_u32(child, "reg", &port_id); |
| 1067 | 1067 | if (ret) { |
| 1068 | + fwnode_handle_put(child); | |
| 1068 | 1069 | dev_err(dsaf_dev->dev, |
| 1069 | 1070 | "get reg fail, ret=%d!\n", ret); |
| 1070 | 1071 | return ret; |
| 1071 | 1072 | } |
| 1072 | 1073 | if (port_id >= max_port_num) { |
| 1074 | + fwnode_handle_put(child); | |
| 1073 | 1075 | dev_err(dsaf_dev->dev, |
| 1074 | 1076 | "reg(%u) out of range!\n", port_id); |
| 1075 | 1077 | return -EINVAL; |
| 1076 | 1078 | } |
| 1077 | 1079 | mac_cb = devm_kzalloc(dsaf_dev->dev, sizeof(*mac_cb), |
| 1078 | 1080 | GFP_KERNEL); |
| 1079 | − if (!mac_cb) | |
| 1081 | + if (!mac_cb) { | |
| 1082 | + fwnode_handle_put(child); | |
| 1080 | 1083 | return -ENOMEM; |
| 1084 | + } | |
| 1081 | 1085 | mac_cb->fw_port = child; |
| 1082 | 1086 | mac_cb->mac_id = (u8)port_id; |
| 1083 | 1087 | dsaf_dev->mac_cb[port_id] = mac_cb; |
| @@ -75,7 +75,7 @@ int hclge_comm_tqps_update_stats(struct hnae3_handle *handle, · 74 unmodified lines | ||
| 75 | 75 | ret = hclge_comm_cmd_send(hw, &desc, 1); |
| 76 | 76 | if (ret) { |
| 77 | 77 | dev_err(&hw->cmq.csq.pdev->dev, |
| 78 | − "failed to get tqp stat, ret = %d, tx = %u.\n", | |
| 78 | + "failed to get tqp stat, ret = %d, rx = %u.\n", | |
| 79 | 79 | ret, i); |
| 80 | 80 | return ret; |
| 81 | 81 | } |
| @@ -89,7 +89,7 @@ int hclge_comm_tqps_update_stats(struct hnae3_handle *handle, · 7 unmodified lines | ||
| 89 | 89 | ret = hclge_comm_cmd_send(hw, &desc, 1); |
| 90 | 90 | if (ret) { |
| 91 | 91 | dev_err(&hw->cmq.csq.pdev->dev, |
| 92 | − "failed to get tqp stat, ret = %d, rx = %u.\n", | |
| 92 | + "failed to get tqp stat, ret = %d, tx = %u.\n", | |
| 93 | 93 | ret, i); |
| 94 | 94 | return ret; |
| 95 | 95 | } |
| @@ -562,12 +562,12 @@ static void hns3_dbg_tx_spare_info(struct hns3_enet_ring *ring, char *buf, · 561 unmodified lines | ||
| 562 | 562 | |
| 563 | 563 | for (i = 0; i < ring_num; i++) { |
| 564 | 564 | j = 0; |
| 565 | − sprintf(result[j++], "%8u", i); | |
| 566 | − sprintf(result[j++], "%9u", ring->tx_copybreak); | |
| 567 | − sprintf(result[j++], "%3u", tx_spare->len); | |
| 568 | − sprintf(result[j++], "%3u", tx_spare->next_to_use); | |
| 569 | − sprintf(result[j++], "%3u", tx_spare->next_to_clean); | |
| 570 | − sprintf(result[j++], "%3u", tx_spare->last_to_clean); | |
| 565 | + sprintf(result[j++], "%u", i); | |
| 566 | + sprintf(result[j++], "%u", ring->tx_copybreak); | |
| 567 | + sprintf(result[j++], "%u", tx_spare->len); | |
| 568 | + sprintf(result[j++], "%u", tx_spare->next_to_use); | |
| 569 | + sprintf(result[j++], "%u", tx_spare->next_to_clean); | |
| 570 | + sprintf(result[j++], "%u", tx_spare->last_to_clean); | |
| 571 | 571 | sprintf(result[j++], "%pad", &tx_spare->dma); |
| 572 | 572 | hns3_dbg_fill_content(content, sizeof(content), |
| 573 | 573 | tx_spare_info_items, |
| @@ -598,35 +598,35 @@ static void hns3_dump_rx_queue_info(struct hns3_enet_ring *ring, · 24 unmodified lines | ||
| 598 | 598 | u32 base_add_l, base_add_h; |
| 599 | 599 | u32 j = 0; |
| 600 | 600 | |
| 601 | − sprintf(result[j++], "%8u", index); | |
| 601 | + sprintf(result[j++], "%u", index); | |
| 602 | 602 | |
| 603 | − sprintf(result[j++], "%6u", readl_relaxed(ring->tqp->io_base + | |
| 603 | + sprintf(result[j++], "%u", readl_relaxed(ring->tqp->io_base + | |
| 604 | 604 | HNS3_RING_RX_RING_BD_NUM_REG)); |
| 605 | 605 | |
| 606 | − sprintf(result[j++], "%6u", readl_relaxed(ring->tqp->io_base + | |
| 606 | + sprintf(result[j++], "%u", readl_relaxed(ring->tqp->io_base + | |
| 607 | 607 | HNS3_RING_RX_RING_BD_LEN_REG)); |
| 608 | 608 | |
| 609 | − sprintf(result[j++], "%4u", readl_relaxed(ring->tqp->io_base + | |
| 609 | + sprintf(result[j++], "%u", readl_relaxed(ring->tqp->io_base + | |
| 610 | 610 | HNS3_RING_RX_RING_TAIL_REG)); |
| 611 | 611 | |
| 612 | − sprintf(result[j++], "%4u", readl_relaxed(ring->tqp->io_base + | |
| 612 | + sprintf(result[j++], "%u", readl_relaxed(ring->tqp->io_base + | |
| 613 | 613 | HNS3_RING_RX_RING_HEAD_REG)); |
| 614 | 614 | |
| 615 | − sprintf(result[j++], "%6u", readl_relaxed(ring->tqp->io_base + | |
| 615 | + sprintf(result[j++], "%u", readl_relaxed(ring->tqp->io_base + | |
| 616 | 616 | HNS3_RING_RX_RING_FBDNUM_REG)); |
| 617 | 617 | |
| 618 | − sprintf(result[j++], "%6u", readl_relaxed(ring->tqp->io_base + | |
| 618 | + sprintf(result[j++], "%u", readl_relaxed(ring->tqp->io_base + | |
| 619 | 619 | HNS3_RING_RX_RING_PKTNUM_RECORD_REG)); |
| 620 | − sprintf(result[j++], "%9u", ring->rx_copybreak); | |
| 620 | + sprintf(result[j++], "%u", ring->rx_copybreak); | |
| 621 | 621 | |
| 622 | − sprintf(result[j++], "%7s", readl_relaxed(ring->tqp->io_base + | |
| 622 | + sprintf(result[j++], "%s", readl_relaxed(ring->tqp->io_base + | |
| 623 | 623 | HNS3_RING_EN_REG) ? "on" : "off"); |
| 624 | 624 | |
| 625 | 625 | if (hnae3_ae_dev_tqp_txrx_indep_supported(ae_dev)) |
| 626 | − sprintf(result[j++], "%10s", readl_relaxed(ring->tqp->io_base + | |
| 626 | + sprintf(result[j++], "%s", readl_relaxed(ring->tqp->io_base + | |
| 627 | 627 | HNS3_RING_RX_EN_REG) ? "on" : "off"); |
| 628 | 628 | else |
| 629 | − sprintf(result[j++], "%10s", "NA"); | |
| 629 | + sprintf(result[j++], "%s", "NA"); | |
| 630 | 630 | |
| 631 | 631 | base_add_h = readl_relaxed(ring->tqp->io_base + |
| 632 | 632 | HNS3_RING_RX_RING_BASEADDR_H_REG); |
| @@ -700,36 +700,36 @@ static void hns3_dump_tx_queue_info(struct hns3_enet_ring *ring, · 67 unmodified lines | ||
| 700 | 700 | u32 base_add_l, base_add_h; |
| 701 | 701 | u32 j = 0; |
| 702 | 702 | |
| 703 | − sprintf(result[j++], "%8u", index); | |
| 704 | − sprintf(result[j++], "%6u", readl_relaxed(ring->tqp->io_base + | |
| 703 | + sprintf(result[j++], "%u", index); | |
| 704 | + sprintf(result[j++], "%u", readl_relaxed(ring->tqp->io_base + | |
| 705 | 705 | HNS3_RING_TX_RING_BD_NUM_REG)); |
| 706 | 706 | |
| 707 | − sprintf(result[j++], "%2u", readl_relaxed(ring->tqp->io_base + | |
| 707 | + sprintf(result[j++], "%u", readl_relaxed(ring->tqp->io_base + | |
| 708 | 708 | HNS3_RING_TX_RING_TC_REG)); |
| 709 | 709 | |
| 710 | − sprintf(result[j++], "%4u", readl_relaxed(ring->tqp->io_base + | |
| 710 | + sprintf(result[j++], "%u", readl_relaxed(ring->tqp->io_base + | |
| 711 | 711 | HNS3_RING_TX_RING_TAIL_REG)); |
| 712 | 712 | |
| 713 | − sprintf(result[j++], "%4u", readl_relaxed(ring->tqp->io_base + | |
| 713 | + sprintf(result[j++], "%u", readl_relaxed(ring->tqp->io_base + | |
| 714 | 714 | HNS3_RING_TX_RING_HEAD_REG)); |
| 715 | 715 | |
| 716 | − sprintf(result[j++], "%6u", readl_relaxed(ring->tqp->io_base + | |
| 716 | + sprintf(result[j++], "%u", readl_relaxed(ring->tqp->io_base + | |
| 717 | 717 | HNS3_RING_TX_RING_FBDNUM_REG)); |
| 718 | 718 | |
| 719 | − sprintf(result[j++], "%6u", readl_relaxed(ring->tqp->io_base + | |
| 719 | + sprintf(result[j++], "%u", readl_relaxed(ring->tqp->io_base + | |
| 720 | 720 | HNS3_RING_TX_RING_OFFSET_REG)); |
| 721 | 721 | |
| 722 | − sprintf(result[j++], "%6u", readl_relaxed(ring->tqp->io_base + | |
| 722 | + sprintf(result[j++], "%u", readl_relaxed(ring->tqp->io_base + | |
| 723 | 723 | HNS3_RING_TX_RING_PKTNUM_RECORD_REG)); |
| 724 | 724 | |
| 725 | − sprintf(result[j++], "%7s", readl_relaxed(ring->tqp->io_base + | |
| 725 | + sprintf(result[j++], "%s", readl_relaxed(ring->tqp->io_base + | |
| 726 | 726 | HNS3_RING_EN_REG) ? "on" : "off"); |
| 727 | 727 | |
| 728 | 728 | if (hnae3_ae_dev_tqp_txrx_indep_supported(ae_dev)) |
| 729 | − sprintf(result[j++], "%10s", readl_relaxed(ring->tqp->io_base + | |
| 729 | + sprintf(result[j++], "%s", readl_relaxed(ring->tqp->io_base + | |
| 730 | 730 | HNS3_RING_TX_EN_REG) ? "on" : "off"); |
| 731 | 731 | else |
| 732 | − sprintf(result[j++], "%10s", "NA"); | |
| 732 | + sprintf(result[j++], "%s", "NA"); | |
| 733 | 733 | |
| 734 | 734 | base_add_h = readl_relaxed(ring->tqp->io_base + |
| 735 | 735 | HNS3_RING_TX_RING_BASEADDR_H_REG); |
| @@ -848,15 +848,15 @@ static void hns3_dump_rx_bd_info(struct hns3_nic_priv *priv, · 112 unmodified lines | ||
| 848 | 848 | { |
| 849 | 849 | unsigned int j = 0; |
| 850 | 850 | |
| 851 | − sprintf(result[j++], "%5d", idx); | |
| 851 | + sprintf(result[j++], "%d", idx); | |
| 852 | 852 | sprintf(result[j++], "%#x", le32_to_cpu(desc->rx.l234_info)); |
| 853 | − sprintf(result[j++], "%7u", le16_to_cpu(desc->rx.pkt_len)); | |
| 854 | − sprintf(result[j++], "%4u", le16_to_cpu(desc->rx.size)); | |
| 853 | + sprintf(result[j++], "%u", le16_to_cpu(desc->rx.pkt_len)); | |
| 854 | + sprintf(result[j++], "%u", le16_to_cpu(desc->rx.size)); | |
| 855 | 855 | sprintf(result[j++], "%#x", le32_to_cpu(desc->rx.rss_hash)); |
| 856 | − sprintf(result[j++], "%5u", le16_to_cpu(desc->rx.fd_id)); | |
| 857 | − sprintf(result[j++], "%8u", le16_to_cpu(desc->rx.vlan_tag)); | |
| 858 | − sprintf(result[j++], "%15u", le16_to_cpu(desc->rx.o_dm_vlan_id_fb)); | |
| 859 | − sprintf(result[j++], "%11u", le16_to_cpu(desc->rx.ot_vlan_tag)); | |
| 856 | + sprintf(result[j++], "%u", le16_to_cpu(desc->rx.fd_id)); | |
| 857 | + sprintf(result[j++], "%u", le16_to_cpu(desc->rx.vlan_tag)); | |
| 858 | + sprintf(result[j++], "%u", le16_to_cpu(desc->rx.o_dm_vlan_id_fb)); | |
| 859 | + sprintf(result[j++], "%u", le16_to_cpu(desc->rx.ot_vlan_tag)); | |
| 860 | 860 | sprintf(result[j++], "%#x", le32_to_cpu(desc->rx.bd_base_info)); |
| 861 | 861 | if (test_bit(HNS3_NIC_STATE_RXD_ADV_LAYOUT_ENABLE, &priv->state)) { |
| 862 | 862 | u32 ol_info = le32_to_cpu(desc->rx.ol_info); |
| @@ -930,19 +930,19 @@ static void hns3_dump_tx_bd_info(struct hns3_nic_priv *priv, · 67 unmodified lines | ||
| 930 | 930 | { |
| 931 | 931 | unsigned int j = 0; |
| 932 | 932 | |
| 933 | − sprintf(result[j++], "%6d", idx); | |
| 933 | + sprintf(result[j++], "%d", idx); | |
| 934 | 934 | sprintf(result[j++], "%#llx", le64_to_cpu(desc->addr)); |
| 935 | − sprintf(result[j++], "%5u", le16_to_cpu(desc->tx.vlan_tag)); | |
| 936 | − sprintf(result[j++], "%5u", le16_to_cpu(desc->tx.send_size)); | |
| 935 | + sprintf(result[j++], "%u", le16_to_cpu(desc->tx.vlan_tag)); | |
| 936 | + sprintf(result[j++], "%u", le16_to_cpu(desc->tx.send_size)); | |
| 937 | 937 | sprintf(result[j++], "%#x", |
| 938 | 938 | le32_to_cpu(desc->tx.type_cs_vlan_tso_len)); |
| 939 | − sprintf(result[j++], "%5u", le16_to_cpu(desc->tx.outer_vlan_tag)); | |
| 940 | − sprintf(result[j++], "%5u", le16_to_cpu(desc->tx.tv)); | |
| 941 | − sprintf(result[j++], "%10u", | |
| 939 | + sprintf(result[j++], "%u", le16_to_cpu(desc->tx.outer_vlan_tag)); | |
| 940 | + sprintf(result[j++], "%u", le16_to_cpu(desc->tx.tv)); | |
| 941 | + sprintf(result[j++], "%u", | |
| 942 | 942 | le32_to_cpu(desc->tx.ol_type_vlan_len_msec)); |
| 943 | 943 | sprintf(result[j++], "%#x", le32_to_cpu(desc->tx.paylen_ol4cs)); |
| 944 | 944 | sprintf(result[j++], "%#x", le16_to_cpu(desc->tx.bdtp_fe_sc_vld_ra_ri)); |
| 945 | − sprintf(result[j++], "%5u", le16_to_cpu(desc->tx.mss_hw_csum)); | |
| 945 | + sprintf(result[j++], "%u", le16_to_cpu(desc->tx.mss_hw_csum)); | |
| 946 | 946 | } |
| 947 | 947 | |
| 948 | 948 | static int hns3_dbg_tx_bd_info(struct hns3_dbg_data *d, char *buf, int len) |
| @@ -5203,6 +5203,13 @@ static void hns3_state_init(struct hnae3_handle *handle) · 5202 unmodified lines | ||
| 5203 | 5203 | set_bit(HNS3_NIC_STATE_RXD_ADV_LAYOUT_ENABLE, &priv->state); |
| 5204 | 5204 | } |
| 5205 | 5205 | |
| 5206 | +static void hns3_state_uninit(struct hnae3_handle *handle) | |
| 5207 | +{ | |
| 5208 | + struct hns3_nic_priv *priv = handle->priv; | |
| 5209 | + | |
| 5210 | + clear_bit(HNS3_NIC_STATE_INITED, &priv->state); | |
| 5211 | +} | |
| 5212 | + | |
| 5206 | 5213 | static int hns3_client_init(struct hnae3_handle *handle) |
| 5207 | 5214 | { |
| 5208 | 5215 | struct pci_dev *pdev = handle->pdev; |
| @@ -5320,7 +5327,9 @@ static int hns3_client_init(struct hnae3_handle *handle) · 111 unmodified lines | ||
| 5320 | 5327 | return ret; |
| 5321 | 5328 | |
| 5322 | 5329 | out_reg_netdev_fail: |
| 5330 | + hns3_state_uninit(handle); | |
| 5323 | 5331 | hns3_dbg_uninit(handle); |
| 5332 | + hns3_client_stop(handle); | |
| 5324 | 5333 | out_client_start: |
| 5325 | 5334 | hns3_free_rx_cpu_rmap(netdev); |
| 5326 | 5335 | hns3_nic_uninit_irq(priv); |
| @@ -94,6 +94,13 @@ static int hclge_send_mbx_msg(struct hclge_vport *vport, u8 *msg, u16 msg_len, · 93 unmodified lines | ||
| 94 | 94 | enum hclge_comm_cmd_status status; |
| 95 | 95 | struct hclge_desc desc; |
| 96 | 96 | |
| 97 | + if (msg_len > HCLGE_MBX_MAX_MSG_SIZE) { | |
| 98 | + dev_err(&hdev->pdev->dev, | |
| 99 | + "msg data length(=%u) exceeds maximum(=%u)\n", | |
| 100 | + msg_len, HCLGE_MBX_MAX_MSG_SIZE); | |
| 101 | + return -EMSGSIZE; | |
| 102 | + } | |
| 103 | + | |
| 97 | 104 | resp_pf_to_vf = (struct hclge_mbx_pf_to_vf_cmd *)desc.data; |
| 98 | 105 | |
| 99 | 106 | hclge_cmd_setup_basic_desc(&desc, HCLGEVF_OPC_MBX_PF_TO_VF, false); |
| @@ -176,7 +183,7 @@ static int hclge_get_ring_chain_from_mbx( · 76 unmodified lines | ||
| 176 | 183 | ring_num = req->msg.ring_num; |
| 177 | 184 | |
| 178 | 185 | if (ring_num > HCLGE_MBX_MAX_RING_CHAIN_PARAM_NUM) |
| 179 | − return -ENOMEM; | |
| 186 | + return -EINVAL; | |
| 180 | 187 | |
| 181 | 188 | for (i = 0; i < ring_num; i++) { |
| 182 | 189 | if (req->msg.param[i].tqp_index >= vport->nic.kinfo.rss_size) { |
| @@ -587,9 +594,9 @@ static int hclge_set_vf_mtu(struct hclge_vport *vport, · 404 unmodified lines | ||
| 587 | 594 | return hclge_set_vport_mtu(vport, mtu); |
| 588 | 595 | } |
| 589 | 596 | |
| 590 | −static void hclge_get_queue_id_in_pf(struct hclge_vport *vport, | |
| 591 | − struct hclge_mbx_vf_to_pf_cmd *mbx_req, | |
| 592 | − struct hclge_respond_to_vf_msg *resp_msg) | |
| 597 | +static int hclge_get_queue_id_in_pf(struct hclge_vport *vport, | |
| 598 | + struct hclge_mbx_vf_to_pf_cmd *mbx_req, | |
| 599 | + struct hclge_respond_to_vf_msg *resp_msg) | |
| 593 | 600 | { |
| 594 | 601 | struct hnae3_handle *handle = &vport->nic; |
| 595 | 602 | struct hclge_dev *hdev = vport->back; |
| @@ -599,17 +606,18 @@ static void hclge_get_queue_id_in_pf(struct hclge_vport *vport, · 3 unmodified lines | ||
| 599 | 606 | if (queue_id >= handle->kinfo.num_tqps) { |
| 600 | 607 | dev_err(&hdev->pdev->dev, "Invalid queue id(%u) from VF %u\n", |
| 601 | 608 | queue_id, mbx_req->mbx_src_vfid); |
| 602 | − return; | |
| 609 | + return -EINVAL; | |
| 603 | 610 | } |
| 604 | 611 | |
| 605 | 612 | qid_in_pf = hclge_covert_handle_qid_global(&vport->nic, queue_id); |
| 606 | 613 | memcpy(resp_msg->data, &qid_in_pf, sizeof(qid_in_pf)); |
| 607 | 614 | resp_msg->len = sizeof(qid_in_pf); |
| 615 | + return 0; | |
| 608 | 616 | } |
| 609 | 617 | |
| 610 | −static void hclge_get_rss_key(struct hclge_vport *vport, | |
| 611 | − struct hclge_mbx_vf_to_pf_cmd *mbx_req, | |
| 612 | − struct hclge_respond_to_vf_msg *resp_msg) | |
| 618 | +static int hclge_get_rss_key(struct hclge_vport *vport, | |
| 619 | + struct hclge_mbx_vf_to_pf_cmd *mbx_req, | |
| 620 | + struct hclge_respond_to_vf_msg *resp_msg) | |
| 613 | 621 | { |
| 614 | 622 | #define HCLGE_RSS_MBX_RESP_LEN 8 |
| 615 | 623 | struct hclge_dev *hdev = vport->back; |
| @@ -627,13 +635,14 @@ static void hclge_get_rss_key(struct hclge_vport *vport, · 11 unmodified lines | ||
| 627 | 635 | dev_warn(&hdev->pdev->dev, |
| 628 | 636 | "failed to get the rss hash key, the index(%u) invalid !\n", |
| 629 | 637 | index); |
| 630 | − return; | |
| 638 | + return -EINVAL; | |
| 631 | 639 | } |
| 632 | 640 | |
| 633 | 641 | memcpy(resp_msg->data, |
| 634 | 642 | &rss_cfg->rss_hash_key[index * HCLGE_RSS_MBX_RESP_LEN], |
| 635 | 643 | HCLGE_RSS_MBX_RESP_LEN); |
| 636 | 644 | resp_msg->len = HCLGE_RSS_MBX_RESP_LEN; |
| 645 | + return 0; | |
| 637 | 646 | } |
| 638 | 647 | |
| 639 | 648 | static void hclge_link_fail_parse(struct hclge_dev *hdev, u8 link_fail_code) |
| @@ -809,10 +818,10 @@ void hclge_mbx_handler(struct hclge_dev *hdev) · 169 unmodified lines | ||
| 809 | 818 | "VF fail(%d) to set mtu\n", ret); |
| 810 | 819 | break; |
| 811 | 820 | case HCLGE_MBX_GET_QID_IN_PF: |
| 812 | − hclge_get_queue_id_in_pf(vport, req, &resp_msg); | |
| 821 | + ret = hclge_get_queue_id_in_pf(vport, req, &resp_msg); | |
| 813 | 822 | break; |
| 814 | 823 | case HCLGE_MBX_GET_RSS_KEY: |
| 815 | − hclge_get_rss_key(vport, req, &resp_msg); | |
| 824 | + ret = hclge_get_rss_key(vport, req, &resp_msg); | |
| 816 | 825 | break; |
| 817 | 826 | case HCLGE_MBX_GET_LINK_MODE: |
| 818 | 827 | hclge_get_link_mode(vport, req); |
| @@ -771,7 +771,7 @@ struct hinic_hw_wqe *hinic_get_wqe(struct hinic_wq *wq, unsigned int wqe_size, · 770 unmodified lines | ||
| 771 | 771 | /* If we only have one page, still need to get shadown wqe when |
| 772 | 772 | * wqe rolling-over page |
| 773 | 773 | */ |
| 774 | − if (curr_pg != end_pg || MASKED_WQE_IDX(wq, end_prod_idx) < *prod_idx) { | |
| 774 | + if (curr_pg != end_pg || end_prod_idx < *prod_idx) { | |
| 775 | 775 | void *shadow_addr = &wq->shadow_wqe[curr_pg * wq->max_wqe_size]; |
| 776 | 776 | |
| 777 | 777 | copy_wqe_to_shadow(wq, shadow_addr, num_wqebbs, *prod_idx); |
| @@ -841,7 +841,10 @@ struct hinic_hw_wqe *hinic_read_wqe(struct hinic_wq *wq, unsigned int wqe_size, · 63 unmodified lines | ||
| 841 | 841 | |
| 842 | 842 | *cons_idx = curr_cons_idx; |
| 843 | 843 | |
| 844 | − if (curr_pg != end_pg) { | |
| 844 | + /* If we only have one page, still need to get shadown wqe when | |
| 845 | + * wqe rolling-over page | |
| 846 | + */ | |
| 847 | + if (curr_pg != end_pg || end_cons_idx < curr_cons_idx) { | |
| 845 | 848 | void *shadow_addr = &wq->shadow_wqe[curr_pg * wq->max_wqe_size]; |
| 846 | 849 | |
| 847 | 850 | copy_wqe_to_shadow(wq, shadow_addr, num_wqebbs, *cons_idx); |
| @@ -3210,13 +3210,8 @@ static void ibmvnic_get_ringparam(struct net_device *netdev, · 3209 unmodified lines | ||
| 3210 | 3210 | { |
| 3211 | 3211 | struct ibmvnic_adapter *adapter = netdev_priv(netdev); |
| 3212 | 3212 | |
| 3213 | − if (adapter->priv_flags & IBMVNIC_USE_SERVER_MAXES) { | |
| 3214 | − ring->rx_max_pending = adapter->max_rx_add_entries_per_subcrq; | |
| 3215 | − ring->tx_max_pending = adapter->max_tx_entries_per_subcrq; | |
| 3216 | − } else { | |
| 3217 | − ring->rx_max_pending = IBMVNIC_MAX_QUEUE_SZ; | |
| 3218 | − ring->tx_max_pending = IBMVNIC_MAX_QUEUE_SZ; | |
| 3219 | − } | |
| 3213 | + ring->rx_max_pending = adapter->max_rx_add_entries_per_subcrq; | |
| 3214 | + ring->tx_max_pending = adapter->max_tx_entries_per_subcrq; | |
| 3220 | 3215 | ring->rx_mini_max_pending = 0; |
| 3221 | 3216 | ring->rx_jumbo_max_pending = 0; |
| 3222 | 3217 | ring->rx_pending = adapter->req_rx_add_entries_per_subcrq; |
| @@ -3231,23 +3226,21 @@ static int ibmvnic_set_ringparam(struct net_device *netdev, · 8 unmodified lines | ||
| 3231 | 3226 | struct netlink_ext_ack *extack) |
| 3232 | 3227 | { |
| 3233 | 3228 | struct ibmvnic_adapter *adapter = netdev_priv(netdev); |
| 3234 | − int ret; | |
| 3235 | 3229 | |
| 3236 | − ret = 0; | |
| 3230 | + if (ring->rx_pending > adapter->max_rx_add_entries_per_subcrq || | |
| 3231 | + ring->tx_pending > adapter->max_tx_entries_per_subcrq) { | |
| 3232 | + netdev_err(netdev, "Invalid request.\n"); | |
| 3233 | + netdev_err(netdev, "Max tx buffers = %llu\n", | |
| 3234 | + adapter->max_rx_add_entries_per_subcrq); | |
| 3235 | + netdev_err(netdev, "Max rx buffers = %llu\n", | |
| 3236 | + adapter->max_tx_entries_per_subcrq); | |
| 3237 | + return -EINVAL; | |
| 3238 | + } | |
| 3239 | + | |
| 3237 | 3240 | adapter->desired.rx_entries = ring->rx_pending; |
| 3238 | 3241 | adapter->desired.tx_entries = ring->tx_pending; |
| 3239 | 3242 | |
| 3240 | − ret = wait_for_reset(adapter); | |
| 3241 | − | |
| 3242 | − if (!ret && | |
| 3243 | − (adapter->req_rx_add_entries_per_subcrq != ring->rx_pending || | |
| 3244 | − adapter->req_tx_entries_per_subcrq != ring->tx_pending)) | |
| 3245 | − netdev_info(netdev, | |
| 3246 | − "Could not match full ringsize request. Requested: RX %d, TX %d; Allowed: RX %llu, TX %llu\n", | |
| 3247 | − ring->rx_pending, ring->tx_pending, | |
| 3248 | − adapter->req_rx_add_entries_per_subcrq, | |
| 3249 | − adapter->req_tx_entries_per_subcrq); | |
| 3250 | − return ret; | |
| 3243 | + return wait_for_reset(adapter); | |
| 3251 | 3244 | } |
| 3252 | 3245 | |
| 3253 | 3246 | static void ibmvnic_get_channels(struct net_device *netdev, |
| @@ -3255,14 +3248,8 @@ static void ibmvnic_get_channels(struct net_device *netdev, · 1 unmodified line | ||
| 3255 | 3248 | { |
| 3256 | 3249 | struct ibmvnic_adapter *adapter = netdev_priv(netdev); |
| 3257 | 3250 | |
| 3258 | − if (adapter->priv_flags & IBMVNIC_USE_SERVER_MAXES) { | |
| 3259 | − channels->max_rx = adapter->max_rx_queues; | |
| 3260 | − channels->max_tx = adapter->max_tx_queues; | |
| 3261 | − } else { | |
| 3262 | − channels->max_rx = IBMVNIC_MAX_QUEUES; | |
| 3263 | − channels->max_tx = IBMVNIC_MAX_QUEUES; | |
| 3264 | − } | |
| 3265 | − | |
| 3251 | + channels->max_rx = adapter->max_rx_queues; | |
| 3252 | + channels->max_tx = adapter->max_tx_queues; | |
| 3266 | 3253 | channels->max_other = 0; |
| 3267 | 3254 | channels->max_combined = 0; |
| 3268 | 3255 | channels->rx_count = adapter->req_rx_queues; |
| @@ -3275,22 +3262,11 @@ static int ibmvnic_set_channels(struct net_device *netdev, · 6 unmodified lines | ||
| 3275 | 3262 | struct ethtool_channels *channels) |
| 3276 | 3263 | { |
| 3277 | 3264 | struct ibmvnic_adapter *adapter = netdev_priv(netdev); |
| 3278 | − int ret; | |
| 3279 | 3265 | |
| 3280 | − ret = 0; | |
| 3281 | 3266 | adapter->desired.rx_queues = channels->rx_count; |
| 3282 | 3267 | adapter->desired.tx_queues = channels->tx_count; |
| 3283 | 3268 | |
| 3284 | − ret = wait_for_reset(adapter); | |
| 3285 | − | |
| 3286 | − if (!ret && | |
| 3287 | − (adapter->req_rx_queues != channels->rx_count || | |
| 3288 | − adapter->req_tx_queues != channels->tx_count)) | |
| 3289 | − netdev_info(netdev, | |
| 3290 | − "Could not match full channels request. Requested: RX %d, TX %d; Allowed: RX %llu, TX %llu\n", | |
| 3291 | − channels->rx_count, channels->tx_count, | |
| 3292 | − adapter->req_rx_queues, adapter->req_tx_queues); | |
| 3293 | − return ret; | |
| 3269 | + return wait_for_reset(adapter); | |
| 3294 | 3270 | } |
| 3295 | 3271 | |
| 3296 | 3272 | static void ibmvnic_get_strings(struct net_device *dev, u32 stringset, u8 *data) |
| @@ -3298,43 +3274,32 @@ static void ibmvnic_get_strings(struct net_device *dev, u32 stringset, u8 *data) · 1 unmodified line | ||
| 3298 | 3274 | struct ibmvnic_adapter *adapter = netdev_priv(dev); |
| 3299 | 3275 | int i; |
| 3300 | 3276 | |
| 3301 | − switch (stringset) { | |
| 3302 | − case ETH_SS_STATS: | |
| 3303 | − for (i = 0; i < ARRAY_SIZE(ibmvnic_stats); | |
| 3304 | − i++, data += ETH_GSTRING_LEN) | |
| 3305 | − memcpy(data, ibmvnic_stats[i].name, ETH_GSTRING_LEN); | |
| 3277 | + if (stringset != ETH_SS_STATS) | |
| 3278 | + return; | |
| 3306 | 3279 | |
| 3307 | − for (i = 0; i < adapter->req_tx_queues; i++) { | |
| 3308 | − snprintf(data, ETH_GSTRING_LEN, "tx%d_packets", i); | |
| 3309 | − data += ETH_GSTRING_LEN; | |
| 3280 | + for (i = 0; i < ARRAY_SIZE(ibmvnic_stats); i++, data += ETH_GSTRING_LEN) | |
| 3281 | + memcpy(data, ibmvnic_stats[i].name, ETH_GSTRING_LEN); | |
| 3310 | 3282 | |
| 3311 | − snprintf(data, ETH_GSTRING_LEN, "tx%d_bytes", i); | |
| 3312 | − data += ETH_GSTRING_LEN; | |
| 3283 | + for (i = 0; i < adapter->req_tx_queues; i++) { | |
| 3284 | + snprintf(data, ETH_GSTRING_LEN, "tx%d_packets", i); | |
| 3285 | + data += ETH_GSTRING_LEN; | |
| 3313 | 3286 | |
| 3314 | − snprintf(data, ETH_GSTRING_LEN, | |
| 3315 | − "tx%d_dropped_packets", i); | |
| 3316 | − data += ETH_GSTRING_LEN; | |
| 3317 | − } | |
| 3287 | + snprintf(data, ETH_GSTRING_LEN, "tx%d_bytes", i); | |
| 3288 | + data += ETH_GSTRING_LEN; | |
| 3318 | 3289 | |
| 3319 | − for (i = 0; i < adapter->req_rx_queues; i++) { | |
| 3320 | − snprintf(data, ETH_GSTRING_LEN, "rx%d_packets", i); | |
| 3321 | − data += ETH_GSTRING_LEN; | |
| 3290 | + snprintf(data, ETH_GSTRING_LEN, "tx%d_dropped_packets", i); | |
| 3291 | + data += ETH_GSTRING_LEN; | |
| 3292 | + } | |
| 3322 | 3293 | |
| 3323 | − snprintf(data, ETH_GSTRING_LEN, "rx%d_bytes", i); | |
| 3324 | − data += ETH_GSTRING_LEN; | |
| 3294 | + for (i = 0; i < adapter->req_rx_queues; i++) { | |
| 3295 | + snprintf(data, ETH_GSTRING_LEN, "rx%d_packets", i); | |
| 3296 | + data += ETH_GSTRING_LEN; | |
| 3325 | 3297 | |
| 3326 | − snprintf(data, ETH_GSTRING_LEN, "rx%d_interrupts", i); | |
| 3327 | − data += ETH_GSTRING_LEN; | |
| 3328 | − } | |
| 3329 | − break; | |
| 3298 | + snprintf(data, ETH_GSTRING_LEN, "rx%d_bytes", i); | |
| 3299 | + data += ETH_GSTRING_LEN; | |
| 3330 | 3300 | |
| 3331 | − case ETH_SS_PRIV_FLAGS: | |
| 3332 | − for (i = 0; i < ARRAY_SIZE(ibmvnic_priv_flags); i++) | |
| 3333 | − strcpy(data + i * ETH_GSTRING_LEN, | |
| 3334 | − ibmvnic_priv_flags[i]); | |
| 3335 | − break; | |
| 3336 | − default: | |
| 3337 | − return; | |
| 3301 | + snprintf(data, ETH_GSTRING_LEN, "rx%d_interrupts", i); | |
| 3302 | + data += ETH_GSTRING_LEN; | |
| 3338 | 3303 | } |
| 3339 | 3304 | } |
| 3340 | 3305 | |
| @@ -3347,8 +3312,6 @@ static int ibmvnic_get_sset_count(struct net_device *dev, int sset) · 6 unmodified lines | ||
| 3347 | 3312 | return ARRAY_SIZE(ibmvnic_stats) + |
| 3348 | 3313 | adapter->req_tx_queues * NUM_TX_STATS + |
| 3349 | 3314 | adapter->req_rx_queues * NUM_RX_STATS; |
| 3350 | − case ETH_SS_PRIV_FLAGS: | |
| 3351 | − return ARRAY_SIZE(ibmvnic_priv_flags); | |
| 3352 | 3315 | default: |
| 3353 | 3316 | return -EOPNOTSUPP; |
| 3354 | 3317 | } |
| @@ -3401,26 +3364,6 @@ static void ibmvnic_get_ethtool_stats(struct net_device *dev, · 46 unmodified lines | ||
| 3401 | 3364 | } |
| 3402 | 3365 | } |
| 3403 | 3366 | |
| 3404 | −static u32 ibmvnic_get_priv_flags(struct net_device *netdev) | |
| 3405 | −{ | |
| 3406 | − struct ibmvnic_adapter *adapter = netdev_priv(netdev); | |
| 3407 | − | |
| 3408 | − return adapter->priv_flags; | |
| 3409 | −} | |
| 3410 | − | |
| 3411 | −static int ibmvnic_set_priv_flags(struct net_device *netdev, u32 flags) | |
| 3412 | −{ | |
| 3413 | − struct ibmvnic_adapter *adapter = netdev_priv(netdev); | |
| 3414 | − bool which_maxes = !!(flags & IBMVNIC_USE_SERVER_MAXES); | |
| 3415 | − | |
| 3416 | − if (which_maxes) | |
| 3417 | − adapter->priv_flags |= IBMVNIC_USE_SERVER_MAXES; | |
| 3418 | − else | |
| 3419 | − adapter->priv_flags &= ~IBMVNIC_USE_SERVER_MAXES; | |
| 3420 | − | |
| 3421 | − return 0; | |
| 3422 | −} | |
| 3423 | − | |
| 3424 | 3367 | static const struct ethtool_ops ibmvnic_ethtool_ops = { |
| 3425 | 3368 | .get_drvinfo = ibmvnic_get_drvinfo, |
| 3426 | 3369 | .get_msglevel = ibmvnic_get_msglevel, |
| @@ -3434,8 +3377,6 @@ static const struct ethtool_ops ibmvnic_ethtool_ops = { · 7 unmodified lines | ||
| 3434 | 3377 | .get_sset_count = ibmvnic_get_sset_count, |
| 3435 | 3378 | .get_ethtool_stats = ibmvnic_get_ethtool_stats, |
| 3436 | 3379 | .get_link_ksettings = ibmvnic_get_link_ksettings, |
| 3437 | − .get_priv_flags = ibmvnic_get_priv_flags, | |
| 3438 | − .set_priv_flags = ibmvnic_set_priv_flags, | |
| 3439 | 3380 | }; |
| 3440 | 3381 | |
| 3441 | 3382 | /* Routines for managing CRQs/sCRQs */ |
| @@ -41,11 +41,6 @@ · 40 unmodified lines | ||
| 41 | 41 | |
| 42 | 42 | #define IBMVNIC_RESET_DELAY 100 |
| 43 | 43 | |
| 44 | −static const char ibmvnic_priv_flags[][ETH_GSTRING_LEN] = { | |
| 45 | −#define IBMVNIC_USE_SERVER_MAXES 0x1 | |
| 46 | − "use-server-maxes" | |
| 47 | −}; | |
| 48 | − | |
| 49 | 44 | struct ibmvnic_login_buffer { |
| 50 | 45 | __be32 len; |
| 51 | 46 | __be32 version; |
| @@ -883,7 +878,6 @@ struct ibmvnic_adapter { · 831 unmodified lines | ||
| 883 | 878 | struct ibmvnic_control_ip_offload_buffer ip_offload_ctrl; |
| 884 | 879 | dma_addr_t ip_offload_ctrl_tok; |
| 885 | 880 | u32 msg_enable; |
| 886 | − u32 priv_flags; | |
| 887 | 881 | |
| 888 | 882 | /* Vital Product Data (VPD) */ |
| 889 | 883 | struct ibmvnic_vpd *vpd; |
| @@ -7549,42 +7549,43 @@ static void i40e_free_macvlan_channels(struct i40e_vsi *vsi) · 7548 unmodified lines | ||
| 7549 | 7549 | static int i40e_fwd_ring_up(struct i40e_vsi *vsi, struct net_device *vdev, |
| 7550 | 7550 | struct i40e_fwd_adapter *fwd) |
| 7551 | 7551 | { |
| 7552 | + struct i40e_channel *ch = NULL, *ch_tmp, *iter; | |
| 7552 | 7553 | int ret = 0, num_tc = 1, i, aq_err; |
| 7553 | − struct i40e_channel *ch, *ch_tmp; | |
| 7554 | 7554 | struct i40e_pf *pf = vsi->back; |
| 7555 | 7555 | struct i40e_hw *hw = &pf->hw; |
| 7556 | 7556 | |
| 7557 | − if (list_empty(&vsi->macvlan_list)) | |
| 7558 | − return -EINVAL; | |
| 7559 | − | |
| 7560 | 7557 | /* Go through the list and find an available channel */ |
| 7561 | − list_for_each_entry_safe(ch, ch_tmp, &vsi->macvlan_list, list) { | |
| 7562 | − if (!i40e_is_channel_macvlan(ch)) { | |
| 7563 | − ch->fwd = fwd; | |
| 7558 | + list_for_each_entry_safe(iter, ch_tmp, &vsi->macvlan_list, list) { | |
| 7559 | + if (!i40e_is_channel_macvlan(iter)) { | |
| 7560 | + iter->fwd = fwd; | |
| 7564 | 7561 | /* record configuration for macvlan interface in vdev */ |
| 7565 | 7562 | for (i = 0; i < num_tc; i++) |
| 7566 | 7563 | netdev_bind_sb_channel_queue(vsi->netdev, vdev, |
| 7567 | 7564 | i, |
| 7568 | − ch->num_queue_pairs, | |
| 7569 | − ch->base_queue); | |
| 7570 | − for (i = 0; i < ch->num_queue_pairs; i++) { | |
| 7565 | + iter->num_queue_pairs, | |
| 7566 | + iter->base_queue); | |
| 7567 | + for (i = 0; i < iter->num_queue_pairs; i++) { | |
| 7571 | 7568 | struct i40e_ring *tx_ring, *rx_ring; |
| 7572 | 7569 | u16 pf_q; |
| 7573 | 7570 | |
| 7574 | − pf_q = ch->base_queue + i; | |
| 7571 | + pf_q = iter->base_queue + i; | |
| 7575 | 7572 | |
| 7576 | 7573 | /* Get to TX ring ptr */ |
| 7577 | 7574 | tx_ring = vsi->tx_rings[pf_q]; |
| 7578 | − tx_ring->ch = ch; | |
| 7575 | + tx_ring->ch = iter; | |
| 7579 | 7576 | |
| 7580 | 7577 | /* Get the RX ring ptr */ |
| 7581 | 7578 | rx_ring = vsi->rx_rings[pf_q]; |
| 7582 | − rx_ring->ch = ch; | |
| 7579 | + rx_ring->ch = iter; | |
| 7583 | 7580 | } |
| 7581 | + ch = iter; | |
| 7584 | 7582 | break; |
| 7585 | 7583 | } |
| 7586 | 7584 | } |
| 7587 | 7585 | |
| 7586 | + if (!ch) | |
| 7587 | + return -EINVAL; | |
| 7588 | + | |
| 7588 | 7589 | /* Guarantee all rings are updated before we update the |
| 7589 | 7590 | * MAC address filter. |
| 7590 | 7591 | */ |
| @@ -540,6 +540,7 @@ struct ice_pf { · 539 unmodified lines | ||
| 540 | 540 | struct mutex avail_q_mutex; /* protects access to avail_[rx|tx]qs */ |
| 541 | 541 | struct mutex sw_mutex; /* lock for protecting VSI alloc flow */ |
| 542 | 542 | struct mutex tc_mutex; /* lock to protect TC changes */ |
| 543 | + struct mutex adev_mutex; /* lock to protect aux device access */ | |
| 543 | 544 | u32 msg_enable; |
| 544 | 545 | struct ice_ptp ptp; |
| 545 | 546 | struct tty_driver *ice_gnss_tty_driver; |
| @@ -37,14 +37,17 @@ void ice_send_event_to_aux(struct ice_pf *pf, struct iidc_event *event) · 36 unmodified lines | ||
| 37 | 37 | if (WARN_ON_ONCE(!in_task())) |
| 38 | 38 | return; |
| 39 | 39 | |
| 40 | + mutex_lock(&pf->adev_mutex); | |
| 40 | 41 | if (!pf->adev) |
| 41 | − return; | |
| 42 | + goto finish; | |
| 42 | 43 | |
| 43 | 44 | device_lock(&pf->adev->dev); |
| 44 | 45 | iadrv = ice_get_auxiliary_drv(pf); |
| 45 | 46 | if (iadrv && iadrv->event_handler) |
| 46 | 47 | iadrv->event_handler(pf, event); |
| 47 | 48 | device_unlock(&pf->adev->dev); |
| 49 | +finish: | |
| 50 | + mutex_unlock(&pf->adev_mutex); | |
| 48 | 51 | } |
| 49 | 52 | |
| 50 | 53 | /** |
| @@ -290,7 +293,6 @@ int ice_plug_aux_dev(struct ice_pf *pf) · 239 unmodified lines | ||
| 290 | 293 | return -ENOMEM; |
| 291 | 294 | |
| 292 | 295 | adev = &iadev->adev; |
| 293 | − pf->adev = adev; | |
| 294 | 296 | iadev->pf = pf; |
| 295 | 297 | |
| 296 | 298 | adev->id = pf->aux_idx; |
| @@ -300,18 +302,20 @@ int ice_plug_aux_dev(struct ice_pf *pf) · 3 unmodified lines | ||
| 300 | 302 | |
| 301 | 303 | ret = auxiliary_device_init(adev); |
| 302 | 304 | if (ret) { |
| 303 | − pf->adev = NULL; | |
| 304 | 305 | kfree(iadev); |
| 305 | 306 | return ret; |
| 306 | 307 | } |
| 307 | 308 | |
| 308 | 309 | ret = auxiliary_device_add(adev); |
| 309 | 310 | if (ret) { |
| 310 | − pf->adev = NULL; | |
| 311 | 311 | auxiliary_device_uninit(adev); |
| 312 | 312 | return ret; |
| 313 | 313 | } |
| 314 | 314 | |
| 315 | + mutex_lock(&pf->adev_mutex); | |
| 316 | + pf->adev = adev; | |
| 317 | + mutex_unlock(&pf->adev_mutex); | |
| 318 | + | |
| 315 | 319 | return 0; |
| 316 | 320 | } |
| 317 | 321 | |
| @@ -320,12 +324,17 @@ int ice_plug_aux_dev(struct ice_pf *pf) · 2 unmodified lines | ||
| 320 | 324 | */ |
| 321 | 325 | void ice_unplug_aux_dev(struct ice_pf *pf) |
| 322 | 326 | { |
| 323 | − if (!pf->adev) | |
| 324 | − return; | |
| 327 | + struct auxiliary_device *adev; | |
| 325 | 328 | |
| 326 | − auxiliary_device_delete(pf->adev); | |
| 327 | − auxiliary_device_uninit(pf->adev); | |
| 329 | + mutex_lock(&pf->adev_mutex); | |
| 330 | + adev = pf->adev; | |
| 328 | 331 | pf->adev = NULL; |
| 332 | + mutex_unlock(&pf->adev_mutex); | |
| 333 | + | |
| 334 | + if (adev) { | |
| 335 | + auxiliary_device_delete(adev); | |
| 336 | + auxiliary_device_uninit(adev); | |
| 337 | + } | |
| 329 | 338 | } |
| 330 | 339 | |
| 331 | 340 | /** |
| @@ -3769,6 +3769,7 @@ u16 ice_get_avail_rxq_count(struct ice_pf *pf) · 3768 unmodified lines | ||
| 3769 | 3769 | static void ice_deinit_pf(struct ice_pf *pf) |
| 3770 | 3770 | { |
| 3771 | 3771 | ice_service_task_stop(pf); |
| 3772 | + mutex_destroy(&pf->adev_mutex); | |
| 3772 | 3773 | mutex_destroy(&pf->sw_mutex); |
| 3773 | 3774 | mutex_destroy(&pf->tc_mutex); |
| 3774 | 3775 | mutex_destroy(&pf->avail_q_mutex); |
| @@ -3847,6 +3848,7 @@ static int ice_init_pf(struct ice_pf *pf) · 72 unmodified lines | ||
| 3847 | 3848 | |
| 3848 | 3849 | mutex_init(&pf->sw_mutex); |
| 3849 | 3850 | mutex_init(&pf->tc_mutex); |
| 3851 | + mutex_init(&pf->adev_mutex); | |
| 3850 | 3852 | |
| 3851 | 3853 | INIT_HLIST_HEAD(&pf->aq_wait_list); |
| 3852 | 3854 | spin_lock_init(&pf->aq_wait_lock); |
| @@ -6929,12 +6931,15 @@ static void ice_rebuild(struct ice_pf *pf, enum ice_reset_req reset_type) · 3076 unmodified lines | ||
| 6929 | 6931 | |
| 6930 | 6932 | dev_dbg(dev, "rebuilding PF after reset_type=%d\n", reset_type); |
| 6931 | 6933 | |
| 6934 | +#define ICE_EMP_RESET_SLEEP_MS 5000 | |
| 6932 | 6935 | if (reset_type == ICE_RESET_EMPR) { |
| 6933 | 6936 | /* If an EMP reset has occurred, any previously pending flash |
| 6934 | 6937 | * update will have completed. We no longer know whether or |
| 6935 | 6938 | * not the NVM update EMP reset is restricted. |
| 6936 | 6939 | */ |
| 6937 | 6940 | pf->fw_emp_reset_disabled = false; |
| 6941 | + | |
| 6942 | + msleep(ICE_EMP_RESET_SLEEP_MS); | |
| 6938 | 6943 | } |
| 6939 | 6944 | |
| 6940 | 6945 | err = ice_init_all_ctrlq(hw); |
| @@ -2287,6 +2287,7 @@ ice_ptp_init_tx_e810(struct ice_pf *pf, struct ice_ptp_tx *tx) · 2286 unmodified lines | ||
| 2287 | 2287 | |
| 2288 | 2288 | /** |
| 2289 | 2289 | * ice_ptp_tx_tstamp_cleanup - Cleanup old timestamp requests that got dropped |
| 2290 | + * @hw: pointer to the hw struct | |
| 2290 | 2291 | * @tx: PTP Tx tracker to clean up |
| 2291 | 2292 | * |
| 2292 | 2293 | * Loop through the Tx timestamp requests and see if any of them have been |
| @@ -2295,7 +2296,7 @@ ice_ptp_init_tx_e810(struct ice_pf *pf, struct ice_ptp_tx *tx) · 2 unmodified lines | ||
| 2295 | 2296 | * timestamp will never be captured. This might happen if the packet gets |
| 2296 | 2297 | * discarded before it reaches the PHY timestamping block. |
| 2297 | 2298 | */ |
| 2298 | −static void ice_ptp_tx_tstamp_cleanup(struct ice_ptp_tx *tx) | |
| 2299 | +static void ice_ptp_tx_tstamp_cleanup(struct ice_hw *hw, struct ice_ptp_tx *tx) | |
| 2299 | 2300 | { |
| 2300 | 2301 | u8 idx; |
| 2301 | 2302 | |
| @@ -2304,11 +2305,16 @@ static void ice_ptp_tx_tstamp_cleanup(struct ice_ptp_tx *tx) · 2 unmodified lines | ||
| 2304 | 2305 | |
| 2305 | 2306 | for_each_set_bit(idx, tx->in_use, tx->len) { |
| 2306 | 2307 | struct sk_buff *skb; |
| 2308 | + u64 raw_tstamp; | |
| 2307 | 2309 | |
| 2308 | 2310 | /* Check if this SKB has been waiting for too long */ |
| 2309 | 2311 | if (time_is_after_jiffies(tx->tstamps[idx].start + 2 * HZ)) |
| 2310 | 2312 | continue; |
| 2311 | 2313 | |
| 2314 | + /* Read tstamp to be able to use this register again */ | |
| 2315 | + ice_read_phy_tstamp(hw, tx->quad, idx + tx->quad_offset, | |
| 2316 | + &raw_tstamp); | |
| 2317 | + | |
| 2312 | 2318 | spin_lock(&tx->lock); |
| 2313 | 2319 | skb = tx->tstamps[idx].skb; |
| 2314 | 2320 | tx->tstamps[idx].skb = NULL; |
| @@ -2330,7 +2336,7 @@ static void ice_ptp_periodic_work(struct kthread_work *work) · 15 unmodified lines | ||
| 2330 | 2336 | |
| 2331 | 2337 | ice_ptp_update_cached_phctime(pf); |
| 2332 | 2338 | |
| 2333 | − ice_ptp_tx_tstamp_cleanup(&pf->ptp.port.tx); | |
| 2339 | + ice_ptp_tx_tstamp_cleanup(&pf->hw, &pf->ptp.port.tx); | |
| 2334 | 2340 | |
| 2335 | 2341 | /* Run twice a second */ |
| 2336 | 2342 | kthread_queue_delayed_work(ptp->kworker, &ptp->work, |
| @@ -1046,8 +1046,8 @@ int ice_sriov_configure(struct pci_dev *pdev, int num_vfs) · 1045 unmodified lines | ||
| 1046 | 1046 | |
| 1047 | 1047 | if (!num_vfs) { |
| 1048 | 1048 | if (!pci_vfs_assigned(pdev)) { |
| 1049 | − ice_mbx_deinit_snapshot(&pf->hw); | |
| 1050 | 1049 | ice_free_vfs(pf); |
| 1050 | + ice_mbx_deinit_snapshot(&pf->hw); | |
| 1051 | 1051 | if (pf->lag) |
| 1052 | 1052 | ice_enable_lag(pf->lag); |
| 1053 | 1053 | return 0; |
| @@ -1307,13 +1307,52 @@ error_param: · 1306 unmodified lines | ||
| 1307 | 1307 | NULL, 0); |
| 1308 | 1308 | } |
| 1309 | 1309 | |
| 1310 | +/** | |
| 1311 | + * ice_vf_vsi_dis_single_txq - disable a single Tx queue | |
| 1312 | + * @vf: VF to disable queue for | |
| 1313 | + * @vsi: VSI for the VF | |
| 1314 | + * @q_id: VF relative (0-based) queue ID | |
| 1315 | + * | |
| 1316 | + * Attempt to disable the Tx queue passed in. If the Tx queue was successfully | |
| 1317 | + * disabled then clear q_id bit in the enabled queues bitmap and return | |
| 1318 | + * success. Otherwise return error. | |
| 1319 | + */ | |
| 1320 | +static int | |
| 1321 | +ice_vf_vsi_dis_single_txq(struct ice_vf *vf, struct ice_vsi *vsi, u16 q_id) | |
| 1322 | +{ | |
| 1323 | + struct ice_txq_meta txq_meta = { 0 }; | |
| 1324 | + struct ice_tx_ring *ring; | |
| 1325 | + int err; | |
| 1326 | + | |
| 1327 | + if (!test_bit(q_id, vf->txq_ena)) | |
| 1328 | + dev_dbg(ice_pf_to_dev(vsi->back), "Queue %u on VSI %u is not enabled, but stopping it anyway\n", | |
| 1329 | + q_id, vsi->vsi_num); | |
| 1330 | + | |
| 1331 | + ring = vsi->tx_rings[q_id]; | |
| 1332 | + if (!ring) | |
| 1333 | + return -EINVAL; | |
| 1334 | + | |
| 1335 | + ice_fill_txq_meta(vsi, ring, &txq_meta); | |
| 1336 | + | |
| 1337 | + err = ice_vsi_stop_tx_ring(vsi, ICE_NO_RESET, vf->vf_id, ring, &txq_meta); | |
| 1338 | + if (err) { | |
| 1339 | + dev_err(ice_pf_to_dev(vsi->back), "Failed to stop Tx ring %d on VSI %d\n", | |
| 1340 | + q_id, vsi->vsi_num); | |
| 1341 | + return err; | |
| 1342 | + } | |
| 1343 | + | |
| 1344 | + /* Clear enabled queues flag */ | |
| 1345 | + clear_bit(q_id, vf->txq_ena); | |
| 1346 | + | |
| 1347 | + return 0; | |
| 1348 | +} | |
| 1349 | + | |
| 1310 | 1350 | /** |
| 1311 | 1351 | * ice_vc_dis_qs_msg |
| 1312 | 1352 | * @vf: pointer to the VF info |
| 1313 | 1353 | * @msg: pointer to the msg buffer |
| 1314 | 1354 | * |
| 1315 | − * called from the VF to disable all or specific | |
| 1316 | − * queue(s) | |
| 1355 | + * called from the VF to disable all or specific queue(s) | |
| 1317 | 1356 | */ |
| 1318 | 1357 | static int ice_vc_dis_qs_msg(struct ice_vf *vf, u8 *msg) |
| 1319 | 1358 | { |
| @@ -1350,30 +1389,15 @@ static int ice_vc_dis_qs_msg(struct ice_vf *vf, u8 *msg) · 30 unmodified lines | ||
| 1350 | 1389 | q_map = vqs->tx_queues; |
| 1351 | 1390 | |
| 1352 | 1391 | for_each_set_bit(vf_q_id, &q_map, ICE_MAX_RSS_QS_PER_VF) { |
| 1353 | − struct ice_tx_ring *ring = vsi->tx_rings[vf_q_id]; | |
| 1354 | − struct ice_txq_meta txq_meta = { 0 }; | |
| 1355 | − | |
| 1356 | 1392 | if (!ice_vc_isvalid_q_id(vf, vqs->vsi_id, vf_q_id)) { |
| 1357 | 1393 | v_ret = VIRTCHNL_STATUS_ERR_PARAM; |
| 1358 | 1394 | goto error_param; |
| 1359 | 1395 | } |
| 1360 | 1396 | |
| 1361 | − if (!test_bit(vf_q_id, vf->txq_ena)) | |
| 1362 | − dev_dbg(ice_pf_to_dev(vsi->back), "Queue %u on VSI %u is not enabled, but stopping it anyway\n", | |
| 1363 | − vf_q_id, vsi->vsi_num); | |
| 1364 | − | |
| 1365 | − ice_fill_txq_meta(vsi, ring, &txq_meta); | |
| 1366 | − | |
| 1367 | − if (ice_vsi_stop_tx_ring(vsi, ICE_NO_RESET, vf->vf_id, | |
| 1368 | − ring, &txq_meta)) { | |
| 1369 | − dev_err(ice_pf_to_dev(vsi->back), "Failed to stop Tx ring %d on VSI %d\n", | |
| 1370 | − vf_q_id, vsi->vsi_num); | |
| 1397 | + if (ice_vf_vsi_dis_single_txq(vf, vsi, vf_q_id)) { | |
| 1371 | 1398 | v_ret = VIRTCHNL_STATUS_ERR_PARAM; |
| 1372 | 1399 | goto error_param; |
| 1373 | 1400 | } |
| 1374 | − | |
| 1375 | − /* Clear enabled queues flag */ | |
| 1376 | − clear_bit(vf_q_id, vf->txq_ena); | |
| 1377 | 1401 | } |
| 1378 | 1402 | } |
| 1379 | 1403 | |
| @@ -1622,6 +1646,14 @@ static int ice_vc_cfg_qs_msg(struct ice_vf *vf, u8 *msg) · 242 unmodified lines | ||
| 1622 | 1646 | if (qpi->txq.ring_len > 0) { |
| 1623 | 1647 | vsi->tx_rings[i]->dma = qpi->txq.dma_ring_addr; |
| 1624 | 1648 | vsi->tx_rings[i]->count = qpi->txq.ring_len; |
| 1649 | + | |
| 1650 | + /* Disable any existing queue first */ | |
| 1651 | + if (ice_vf_vsi_dis_single_txq(vf, vsi, q_idx)) { | |
| 1652 | + v_ret = VIRTCHNL_STATUS_ERR_PARAM; | |
| 1653 | + goto error_param; | |
| 1654 | + } | |
| 1655 | + | |
| 1656 | + /* Configure a queue with the requested settings */ | |
| 1625 | 1657 | if (ice_vsi_cfg_single_txq(vsi, vsi->tx_rings, q_idx)) { |
| 1626 | 1658 | v_ret = VIRTCHNL_STATUS_ERR_PARAM; |
| 1627 | 1659 | goto error_param; |
| @@ -3625,6 +3657,8 @@ void ice_vc_process_vf_msg(struct ice_pf *pf, struct ice_rq_event_info *event) · 1997 unmodified lines | ||
| 3625 | 3657 | return; |
| 3626 | 3658 | } |
| 3627 | 3659 | |
| 3660 | + mutex_lock(&vf->cfg_lock); | |
| 3661 | + | |
| 3628 | 3662 | /* Check if VF is disabled. */ |
| 3629 | 3663 | if (test_bit(ICE_VF_STATE_DIS, vf->vf_states)) { |
| 3630 | 3664 | err = -EPERM; |
| @@ -3642,32 +3676,20 @@ void ice_vc_process_vf_msg(struct ice_pf *pf, struct ice_rq_event_info *event) · 11 unmodified lines | ||
| 3642 | 3676 | err = -EINVAL; |
| 3643 | 3677 | } |
| 3644 | 3678 | |
| 3645 | − if (!ice_vc_is_opcode_allowed(vf, v_opcode)) { | |
| 3646 | − ice_vc_send_msg_to_vf(vf, v_opcode, | |
| 3647 | − VIRTCHNL_STATUS_ERR_NOT_SUPPORTED, NULL, | |
| 3648 | − 0); | |
| 3649 | − ice_put_vf(vf); | |
| 3650 | − return; | |
| 3651 | − } | |
| 3652 | − | |
| 3653 | 3679 | error_handler: |
| 3654 | 3680 | if (err) { |
| 3655 | 3681 | ice_vc_send_msg_to_vf(vf, v_opcode, VIRTCHNL_STATUS_ERR_PARAM, |
| 3656 | 3682 | NULL, 0); |
| 3657 | 3683 | dev_err(dev, "Invalid message from VF %d, opcode %d, len %d, error %d\n", |
| 3658 | 3684 | vf_id, v_opcode, msglen, err); |
| 3659 | − ice_put_vf(vf); | |
| 3660 | − return; | |
| 3685 | + goto finish; | |
| 3661 | 3686 | } |
| 3662 | 3687 | |
| 3663 | − /* VF is being configured in another context that triggers a VFR, so no | |
| 3664 | − * need to process this message | |
| 3665 | − */ | |
| 3666 | − if (!mutex_trylock(&vf->cfg_lock)) { | |
| 3667 | − dev_info(dev, "VF %u is being configured in another context that will trigger a VFR, so there is no need to handle this message\n", | |
| 3668 | − vf->vf_id); | |
| 3669 | − ice_put_vf(vf); | |
| 3670 | − return; | |
| 3688 | + if (!ice_vc_is_opcode_allowed(vf, v_opcode)) { | |
| 3689 | + ice_vc_send_msg_to_vf(vf, v_opcode, | |
| 3690 | + VIRTCHNL_STATUS_ERR_NOT_SUPPORTED, NULL, | |
| 3691 | + 0); | |
| 3692 | + goto finish; | |
| 3671 | 3693 | } |
| 3672 | 3694 | |
| 3673 | 3695 | switch (v_opcode) { |
| @@ -3780,6 +3802,7 @@ error_handler: · 106 unmodified lines | ||
| 3780 | 3802 | vf_id, v_opcode, err); |
| 3781 | 3803 | } |
| 3782 | 3804 | |
| 3805 | +finish: | |
| 3783 | 3806 | mutex_unlock(&vf->cfg_lock); |
| 3784 | 3807 | ice_put_vf(vf); |
| 3785 | 3808 | } |
| @@ -903,7 +903,8 @@ int ixgbe_ipsec_vf_add_sa(struct ixgbe_adapter *adapter, u32 *msgbuf, u32 vf) · 902 unmodified lines | ||
| 903 | 903 | /* Tx IPsec offload doesn't seem to work on this |
| 904 | 904 | * device, so block these requests for now. |
| 905 | 905 | */ |
| 906 | − if (!(sam->flags & XFRM_OFFLOAD_INBOUND)) { | |
| 906 | + sam->flags = sam->flags & ~XFRM_OFFLOAD_IPV6; | |
| 907 | + if (sam->flags != XFRM_OFFLOAD_INBOUND) { | |
| 907 | 908 | err = -EOPNOTSUPP; |
| 908 | 909 | goto err_out; |
| 909 | 910 | } |
| @@ -395,7 +395,7 @@ static void mtk_ppe_init_foe_table(struct mtk_ppe *ppe) · 394 unmodified lines | ||
| 395 | 395 | static const u8 skip[] = { 12, 25, 38, 51, 76, 89, 102 }; |
| 396 | 396 | int i, k; |
| 397 | 397 | |
| 398 | − memset(ppe->foe_table, 0, MTK_PPE_ENTRIES * sizeof(ppe->foe_table)); | |
| 398 | + memset(ppe->foe_table, 0, MTK_PPE_ENTRIES * sizeof(*ppe->foe_table)); | |
| 399 | 399 | |
| 400 | 400 | if (!IS_ENABLED(CONFIG_SOC_MT7621)) |
| 401 | 401 | return; |
| @@ -26,6 +26,7 @@ int mtk_sgmii_init(struct mtk_sgmii *ss, struct device_node *r, u32 ana_rgc3) · 25 unmodified lines | ||
| 26 | 26 | break; |
| 27 | 27 | |
| 28 | 28 | ss->regmap[i] = syscon_node_to_regmap(np); |
| 29 | + of_node_put(np); | |
| 29 | 30 | if (IS_ERR(ss->regmap[i])) |
| 30 | 31 | return PTR_ERR(ss->regmap[i]); |
| 31 | 32 | } |
| @@ -31,6 +31,7 @@ static const char *const mlx5_rsc_sgmt_name[] = { · 30 unmodified lines | ||
| 31 | 31 | struct mlx5_rsc_dump { |
| 32 | 32 | u32 pdn; |
| 33 | 33 | u32 mkey; |
| 34 | + u32 number_of_menu_items; | |
| 34 | 35 | u16 fw_segment_type[MLX5_SGMT_TYPE_NUM]; |
| 35 | 36 | }; |
| 36 | 37 | |
| @@ -50,21 +51,37 @@ static int mlx5_rsc_dump_sgmt_get_by_name(char *name) · 13 unmodified lines | ||
| 50 | 51 | return -EINVAL; |
| 51 | 52 | } |
| 52 | 53 | |
| 53 | −static void mlx5_rsc_dump_read_menu_sgmt(struct mlx5_rsc_dump *rsc_dump, struct page *page) | |
| 54 | +#define MLX5_RSC_DUMP_MENU_HEADER_SIZE (MLX5_ST_SZ_BYTES(resource_dump_info_segment) + \ | |
| 55 | + MLX5_ST_SZ_BYTES(resource_dump_command_segment) + \ | |
| 56 | + MLX5_ST_SZ_BYTES(resource_dump_menu_segment)) | |
| 57 | + | |
| 58 | +static int mlx5_rsc_dump_read_menu_sgmt(struct mlx5_rsc_dump *rsc_dump, struct page *page, | |
| 59 | + int read_size, int start_idx) | |
| 54 | 60 | { |
| 55 | 61 | void *data = page_address(page); |
| 56 | 62 | enum mlx5_sgmt_type sgmt_idx; |
| 57 | 63 | int num_of_items; |
| 58 | 64 | char *sgmt_name; |
| 59 | 65 | void *member; |
| 66 | + int size = 0; | |
| 60 | 67 | void *menu; |
| 61 | 68 | int i; |
| 62 | 69 | |
| 63 | − menu = MLX5_ADDR_OF(menu_resource_dump_response, data, menu); | |
| 64 | − num_of_items = MLX5_GET(resource_dump_menu_segment, menu, num_of_records); | |
| 70 | + if (!start_idx) { | |
| 71 | + menu = MLX5_ADDR_OF(menu_resource_dump_response, data, menu); | |
| 72 | + rsc_dump->number_of_menu_items = MLX5_GET(resource_dump_menu_segment, menu, | |
| 73 | + num_of_records); | |
| 74 | + size = MLX5_RSC_DUMP_MENU_HEADER_SIZE; | |
| 75 | + data += size; | |
| 76 | + } | |
| 77 | + num_of_items = rsc_dump->number_of_menu_items; | |
| 78 | + | |
| 79 | + for (i = 0; start_idx + i < num_of_items; i++) { | |
| 80 | + size += MLX5_ST_SZ_BYTES(resource_dump_menu_record); | |
| 81 | + if (size >= read_size) | |
| 82 | + return start_idx + i; | |
| 65 | 83 | |
| 66 | − for (i = 0; i < num_of_items; i++) { | |
| 67 | − member = MLX5_ADDR_OF(resource_dump_menu_segment, menu, record[i]); | |
| 84 | + member = data + MLX5_ST_SZ_BYTES(resource_dump_menu_record) * i; | |
| 68 | 85 | sgmt_name = MLX5_ADDR_OF(resource_dump_menu_record, member, segment_name); |
| 69 | 86 | sgmt_idx = mlx5_rsc_dump_sgmt_get_by_name(sgmt_name); |
| 70 | 87 | if (sgmt_idx == -EINVAL) |
| @@ -72,6 +89,7 @@ static void mlx5_rsc_dump_read_menu_sgmt(struct mlx5_rsc_dump *rsc_dump, struct · 1 unmodified line | ||
| 72 | 89 | rsc_dump->fw_segment_type[sgmt_idx] = MLX5_GET(resource_dump_menu_record, |
| 73 | 90 | member, segment_type); |
| 74 | 91 | } |
| 92 | + return 0; | |
| 75 | 93 | } |
| 76 | 94 | |
| 77 | 95 | static int mlx5_rsc_dump_trigger(struct mlx5_core_dev *dev, struct mlx5_rsc_dump_cmd *cmd, |
| @@ -168,6 +186,7 @@ static int mlx5_rsc_dump_menu(struct mlx5_core_dev *dev) · 90 unmodified lines | ||
| 168 | 186 | struct mlx5_rsc_dump_cmd *cmd = NULL; |
| 169 | 187 | struct mlx5_rsc_key key = {}; |
| 170 | 188 | struct page *page; |
| 189 | + int start_idx = 0; | |
| 171 | 190 | int size; |
| 172 | 191 | int err; |
| 173 | 192 | |
| @@ -189,7 +208,7 @@ static int mlx5_rsc_dump_menu(struct mlx5_core_dev *dev) · 15 unmodified lines | ||
| 189 | 208 | if (err < 0) |
| 190 | 209 | goto destroy_cmd; |
| 191 | 210 | |
| 192 | − mlx5_rsc_dump_read_menu_sgmt(dev->rsc_dump, page); | |
| 211 | + start_idx = mlx5_rsc_dump_read_menu_sgmt(dev->rsc_dump, page, size, start_idx); | |
| 193 | 212 | |
| 194 | 213 | } while (err > 0); |
| 195 | 214 | |
| @@ -309,8 +309,8 @@ int mlx5e_port_manual_buffer_config(struct mlx5e_priv *priv, · 308 unmodified lines | ||
| 309 | 309 | if (err) |
| 310 | 310 | return err; |
| 311 | 311 | |
| 312 | − err = update_buffer_lossy(max_mtu, curr_pfc_en, prio2buffer, port_buff_cell_sz, | |
| 313 | − xoff, &port_buffer, &update_buffer); | |
| 312 | + err = update_buffer_lossy(max_mtu, curr_pfc_en, prio2buffer, xoff, | |
| 313 | + port_buff_cell_sz, &port_buffer, &update_buffer); | |
| 314 | 314 | if (err) |
| 315 | 315 | return err; |
| 316 | 316 | } |
| @@ -145,8 +145,7 @@ mlx5e_tc_act_post_parse(struct mlx5e_tc_act_parse_state *parse_state, · 144 unmodified lines | ||
| 145 | 145 | |
| 146 | 146 | flow_action_for_each(i, act, flow_action) { |
| 147 | 147 | tc_act = mlx5e_tc_act_get(act->id, ns_type); |
| 148 | − if (!tc_act || !tc_act->post_parse || | |
| 149 | − !tc_act->can_offload(parse_state, act, i, attr)) | |
| 148 | + if (!tc_act || !tc_act->post_parse) | |
| 150 | 149 | continue; |
| 151 | 150 | |
| 152 | 151 | err = tc_act->post_parse(parse_state, priv, attr); |
| @@ -45,12 +45,41 @@ tc_act_parse_ct(struct mlx5e_tc_act_parse_state *parse_state, · 44 unmodified lines | ||
| 45 | 45 | if (mlx5e_is_eswitch_flow(parse_state->flow)) |
| 46 | 46 | attr->esw_attr->split_count = attr->esw_attr->out_count; |
| 47 | 47 | |
| 48 | − if (!clear_action) { | |
| 48 | + if (clear_action) { | |
| 49 | + parse_state->ct_clear = true; | |
| 50 | + } else { | |
| 49 | 51 | attr->flags |= MLX5_ATTR_FLAG_CT; |
| 50 | 52 | flow_flag_set(parse_state->flow, CT); |
| 51 | 53 | parse_state->ct = true; |
| 52 | 54 | } |
| 53 | − parse_state->ct_clear = clear_action; | |
| 55 | + | |
| 56 | + return 0; | |
| 57 | +} | |
| 58 | + | |
| 59 | +static int | |
| 60 | +tc_act_post_parse_ct(struct mlx5e_tc_act_parse_state *parse_state, | |
| 61 | + struct mlx5e_priv *priv, | |
| 62 | + struct mlx5_flow_attr *attr) | |
| 63 | +{ | |
| 64 | + struct mlx5e_tc_mod_hdr_acts *mod_acts = &attr->parse_attr->mod_hdr_acts; | |
| 65 | + int err; | |
| 66 | + | |
| 67 | + /* If ct action exist, we can ignore previous ct_clear actions */ | |
| 68 | + if (parse_state->ct) | |
| 69 | + return 0; | |
| 70 | + | |
| 71 | + if (parse_state->ct_clear) { | |
| 72 | + err = mlx5_tc_ct_set_ct_clear_regs(parse_state->ct_priv, mod_acts); | |
| 73 | + if (err) { | |
| 74 | + NL_SET_ERR_MSG_MOD(parse_state->extack, | |
| 75 | + "Failed to set registers for ct clear"); | |
| 76 | + return err; | |
| 77 | + } | |
| 78 | + attr->action |= MLX5_FLOW_CONTEXT_ACTION_MOD_HDR; | |
| 79 | + | |
| 80 | + /* Prevent handling of additional, redundant clear actions */ | |
| 81 | + parse_state->ct_clear = false; | |
| 82 | + } | |
| 54 | 83 | |
| 55 | 84 | return 0; |
| 56 | 85 | } |
| @@ -70,5 +99,6 @@ struct mlx5e_tc_act mlx5e_tc_act_ct = { · 13 unmodified lines | ||
| 70 | 99 | .can_offload = tc_act_can_offload_ct, |
| 71 | 100 | .parse_action = tc_act_parse_ct, |
| 72 | 101 | .is_multi_table_act = tc_act_is_multi_table_act_ct, |
| 102 | + .post_parse = tc_act_post_parse_ct, | |
| 73 | 103 | }; |
| 74 | 104 | |
| @@ -582,6 +582,12 @@ mlx5_tc_ct_entry_set_registers(struct mlx5_tc_ct_priv *ct_priv, · 581 unmodified lines | ||
| 582 | 582 | return 0; |
| 583 | 583 | } |
| 584 | 584 | |
| 585 | +int mlx5_tc_ct_set_ct_clear_regs(struct mlx5_tc_ct_priv *priv, | |
| 586 | + struct mlx5e_tc_mod_hdr_acts *mod_acts) | |
| 587 | +{ | |
| 588 | + return mlx5_tc_ct_entry_set_registers(priv, mod_acts, 0, 0, 0, 0); | |
| 589 | +} | |
| 590 | + | |
| 585 | 591 | static int |
| 586 | 592 | mlx5_tc_ct_parse_mangle_to_mod_act(struct flow_action_entry *act, |
| 587 | 593 | char *modact) |
| @@ -1410,9 +1416,6 @@ mlx5_tc_ct_parse_action(struct mlx5_tc_ct_priv *priv, · 822 unmodified lines | ||
| 1410 | 1416 | const struct flow_action_entry *act, |
| 1411 | 1417 | struct netlink_ext_ack *extack) |
| 1412 | 1418 | { |
| 1413 | − bool clear_action = act->ct.action & TCA_CT_ACT_CLEAR; | |
| 1414 | − int err; | |
| 1415 | − | |
| 1416 | 1419 | if (!priv) { |
| 1417 | 1420 | NL_SET_ERR_MSG_MOD(extack, |
| 1418 | 1421 | "offload of ct action isn't available"); |
| @@ -1423,17 +1426,6 @@ mlx5_tc_ct_parse_action(struct mlx5_tc_ct_priv *priv, · 4 unmodified lines | ||
| 1423 | 1426 | attr->ct_attr.ct_action = act->ct.action; |
| 1424 | 1427 | attr->ct_attr.nf_ft = act->ct.flow_table; |
| 1425 | 1428 | |
| 1426 | − if (!clear_action) | |
| 1427 | − goto out; | |
| 1428 | − | |
| 1429 | − err = mlx5_tc_ct_entry_set_registers(priv, mod_acts, 0, 0, 0, 0); | |
| 1430 | − if (err) { | |
| 1431 | − NL_SET_ERR_MSG_MOD(extack, "Failed to set registers for ct clear"); | |
| 1432 | − return err; | |
| 1433 | − } | |
| 1434 | − attr->action |= MLX5_FLOW_CONTEXT_ACTION_MOD_HDR; | |
| 1435 | − | |
| 1436 | −out: | |
| 1437 | 1429 | return 0; |
| 1438 | 1430 | } |
| 1439 | 1431 | |
| @@ -1749,6 +1741,8 @@ mlx5_tc_ct_flush_ft_entry(void *ptr, void *arg) · 309 unmodified lines | ||
| 1749 | 1741 | static void |
| 1750 | 1742 | mlx5_tc_ct_del_ft_cb(struct mlx5_tc_ct_priv *ct_priv, struct mlx5_ct_ft *ft) |
| 1751 | 1743 | { |
| 1744 | + struct mlx5e_priv *priv; | |
| 1745 | + | |
| 1752 | 1746 | if (!refcount_dec_and_test(&ft->refcount)) |
| 1753 | 1747 | return; |
| 1754 | 1748 | |
| @@ -1758,6 +1752,8 @@ mlx5_tc_ct_del_ft_cb(struct mlx5_tc_ct_priv *ct_priv, struct mlx5_ct_ft *ft) · 3 unmodified lines | ||
| 1758 | 1752 | rhashtable_free_and_destroy(&ft->ct_entries_ht, |
| 1759 | 1753 | mlx5_tc_ct_flush_ft_entry, |
| 1760 | 1754 | ct_priv); |
| 1755 | + priv = netdev_priv(ct_priv->netdev); | |
| 1756 | + flush_workqueue(priv->wq); | |
| 1761 | 1757 | mlx5_tc_ct_free_pre_ct_tables(ft); |
| 1762 | 1758 | mapping_remove(ct_priv->zone_mapping, ft->zone_restore_id); |
| 1763 | 1759 | kfree(ft); |
| @@ -129,6 +129,10 @@ bool · 128 unmodified lines | ||
| 129 | 129 | mlx5e_tc_ct_restore_flow(struct mlx5_tc_ct_priv *ct_priv, |
| 130 | 130 | struct sk_buff *skb, u8 zone_restore_id); |
| 131 | 131 | |
| 132 | +int | |
| 133 | +mlx5_tc_ct_set_ct_clear_regs(struct mlx5_tc_ct_priv *priv, | |
| 134 | + struct mlx5e_tc_mod_hdr_acts *mod_acts); | |
| 135 | + | |
| 132 | 136 | #else /* CONFIG_MLX5_TC_CT */ |
| 133 | 137 | |
| 134 | 138 | static inline struct mlx5_tc_ct_priv * |
| @@ -170,6 +174,13 @@ mlx5_tc_ct_add_no_trk_match(struct mlx5_flow_spec *spec) · 35 unmodified lines | ||
| 170 | 174 | return 0; |
| 171 | 175 | } |
| 172 | 176 | |
| 177 | +static inline int | |
| 178 | +mlx5_tc_ct_set_ct_clear_regs(struct mlx5_tc_ct_priv *priv, | |
| 179 | + struct mlx5e_tc_mod_hdr_acts *mod_acts) | |
| 180 | +{ | |
| 181 | + return -EOPNOTSUPP; | |
| 182 | +} | |
| 183 | + | |
| 173 | 184 | static inline int |
| 174 | 185 | mlx5_tc_ct_parse_action(struct mlx5_tc_ct_priv *priv, |
| 175 | 186 | struct mlx5_flow_attr *attr, |
| @@ -713,6 +713,7 @@ int mlx5e_tc_tun_route_lookup(struct mlx5e_priv *priv, · 712 unmodified lines | ||
| 713 | 713 | struct net_device *filter_dev) |
| 714 | 714 | { |
| 715 | 715 | struct mlx5_esw_flow_attr *esw_attr = flow_attr->esw_attr; |
| 716 | + struct mlx5_eswitch *esw = priv->mdev->priv.eswitch; | |
| 716 | 717 | struct mlx5e_tc_int_port *int_port; |
| 717 | 718 | TC_TUN_ROUTE_ATTR_INIT(attr); |
| 718 | 719 | u16 vport_num; |
| @@ -747,7 +748,7 @@ int mlx5e_tc_tun_route_lookup(struct mlx5e_priv *priv, · 28 unmodified lines | ||
| 747 | 748 | esw_attr->rx_tun_attr->vni = MLX5_GET(fte_match_param, spec->match_value, |
| 748 | 749 | misc_parameters.vxlan_vni); |
| 749 | 750 | esw_attr->rx_tun_attr->decap_vport = vport_num; |
| 750 | − } else if (netif_is_ovs_master(attr.route_dev)) { | |
| 751 | + } else if (netif_is_ovs_master(attr.route_dev) && mlx5e_tc_int_port_supported(esw)) { | |
| 751 | 752 | int_port = mlx5e_tc_int_port_get(mlx5e_get_int_port_priv(priv), |
| 752 | 753 | attr.route_dev->ifindex, |
| 753 | 754 | MLX5E_TC_INT_PORT_INGRESS); |
| @@ -1200,6 +1200,16 @@ static int mlx5e_trust_initialize(struct mlx5e_priv *priv) · 1199 unmodified lines | ||
| 1200 | 1200 | return err; |
| 1201 | 1201 | WRITE_ONCE(priv->dcbx_dp.trust_state, trust_state); |
| 1202 | 1202 | |
| 1203 | + if (priv->dcbx_dp.trust_state == MLX5_QPTS_TRUST_PCP && priv->dcbx.dscp_app_cnt) { | |
| 1204 | + /* | |
| 1205 | + * Align the driver state with the register state. | |
| 1206 | + * Temporary state change is required to enable the app list reset. | |
| 1207 | + */ | |
| 1208 | + priv->dcbx_dp.trust_state = MLX5_QPTS_TRUST_DSCP; | |
| 1209 | + mlx5e_dcbnl_delete_app(priv); | |
| 1210 | + priv->dcbx_dp.trust_state = MLX5_QPTS_TRUST_PCP; | |
| 1211 | + } | |
| 1212 | + | |
| 1203 | 1213 | mlx5e_params_calc_trust_tx_min_inline_mode(priv->mdev, &priv->channels.params, |
| 1204 | 1214 | priv->dcbx_dp.trust_state); |
| 1205 | 1215 | |
| @@ -2459,6 +2459,17 @@ static int __parse_cls_flower(struct mlx5e_priv *priv, · 2458 unmodified lines | ||
| 2459 | 2459 | match.key->vlan_priority); |
| 2460 | 2460 | |
| 2461 | 2461 | *match_level = MLX5_MATCH_L2; |
| 2462 | + | |
| 2463 | + if (!flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_CVLAN) && | |
| 2464 | + match.mask->vlan_eth_type && | |
| 2465 | + MLX5_CAP_FLOWTABLE_TYPE(priv->mdev, | |
| 2466 | + ft_field_support.outer_second_vid, | |
| 2467 | + fs_type)) { | |
| 2468 | + MLX5_SET(fte_match_set_misc, misc_c, | |
| 2469 | + outer_second_cvlan_tag, 1); | |
| 2470 | + spec->match_criteria_enable |= | |
| 2471 | + MLX5_MATCH_MISC_PARAMETERS; | |
| 2472 | + } | |
| 2462 | 2473 | } |
| 2463 | 2474 | } else if (*match_level != MLX5_MATCH_NONE) { |
| 2464 | 2475 | /* cvlan_tag enabled in match criteria and |
| @@ -139,7 +139,7 @@ mlx5_eswitch_set_rule_source_port(struct mlx5_eswitch *esw, · 138 unmodified lines | ||
| 139 | 139 | if (mlx5_esw_indir_table_decap_vport(attr)) |
| 140 | 140 | vport = mlx5_esw_indir_table_decap_vport(attr); |
| 141 | 141 | |
| 142 | − if (esw_attr->int_port) | |
| 142 | + if (attr && !attr->chain && esw_attr->int_port) | |
| 143 | 143 | metadata = |
| 144 | 144 | mlx5e_tc_int_port_get_metadata_for_match(esw_attr->int_port); |
| 145 | 145 | else |
| @@ -155,6 +155,28 @@ static void mlx5_fw_reset_complete_reload(struct mlx5_core_dev *dev) · 154 unmodified lines | ||
| 155 | 155 | } |
| 156 | 156 | } |
| 157 | 157 | |
| 158 | +static void mlx5_stop_sync_reset_poll(struct mlx5_core_dev *dev) | |
| 159 | +{ | |
| 160 | + struct mlx5_fw_reset *fw_reset = dev->priv.fw_reset; | |
| 161 | + | |
| 162 | + del_timer_sync(&fw_reset->timer); | |
| 163 | +} | |
| 164 | + | |
| 165 | +static int mlx5_sync_reset_clear_reset_requested(struct mlx5_core_dev *dev, bool poll_health) | |
| 166 | +{ | |
| 167 | + struct mlx5_fw_reset *fw_reset = dev->priv.fw_reset; | |
| 168 | + | |
| 169 | + if (!test_and_clear_bit(MLX5_FW_RESET_FLAGS_RESET_REQUESTED, &fw_reset->reset_flags)) { | |
| 170 | + mlx5_core_warn(dev, "Reset request was already cleared\n"); | |
| 171 | + return -EALREADY; | |
| 172 | + } | |
| 173 | + | |
| 174 | + mlx5_stop_sync_reset_poll(dev); | |
| 175 | + if (poll_health) | |
| 176 | + mlx5_start_health_poll(dev); | |
| 177 | + return 0; | |
| 178 | +} | |
| 179 | + | |
| 158 | 180 | static void mlx5_sync_reset_reload_work(struct work_struct *work) |
| 159 | 181 | { |
| 160 | 182 | struct mlx5_fw_reset *fw_reset = container_of(work, struct mlx5_fw_reset, |
| @@ -162,6 +184,7 @@ static void mlx5_sync_reset_reload_work(struct work_struct *work) · 1 unmodified line | ||
| 162 | 184 | struct mlx5_core_dev *dev = fw_reset->dev; |
| 163 | 185 | int err; |
| 164 | 186 | |
| 187 | + mlx5_sync_reset_clear_reset_requested(dev, false); | |
| 165 | 188 | mlx5_enter_error_state(dev, true); |
| 166 | 189 | mlx5_unload_one(dev); |
| 167 | 190 | err = mlx5_health_wait_pci_up(dev); |
| @@ -171,23 +194,6 @@ static void mlx5_sync_reset_reload_work(struct work_struct *work) · 3 unmodified lines | ||
| 171 | 194 | mlx5_fw_reset_complete_reload(dev); |
| 172 | 195 | } |
| 173 | 196 | |
| 174 | −static void mlx5_stop_sync_reset_poll(struct mlx5_core_dev *dev) | |
| 175 | −{ | |
| 176 | − struct mlx5_fw_reset *fw_reset = dev->priv.fw_reset; | |
| 177 | − | |
| 178 | − del_timer_sync(&fw_reset->timer); | |
| 179 | −} | |
| 180 | − | |
| 181 | −static void mlx5_sync_reset_clear_reset_requested(struct mlx5_core_dev *dev, bool poll_health) | |
| 182 | −{ | |
| 183 | − struct mlx5_fw_reset *fw_reset = dev->priv.fw_reset; | |
| 184 | − | |
| 185 | − mlx5_stop_sync_reset_poll(dev); | |
| 186 | − clear_bit(MLX5_FW_RESET_FLAGS_RESET_REQUESTED, &fw_reset->reset_flags); | |
| 187 | − if (poll_health) | |
| 188 | − mlx5_start_health_poll(dev); | |
| 189 | −} | |
| 190 | − | |
| 191 | 197 | #define MLX5_RESET_POLL_INTERVAL (HZ / 10) |
| 192 | 198 | static void poll_sync_reset(struct timer_list *t) |
| 193 | 199 | { |
| @@ -202,7 +208,6 @@ static void poll_sync_reset(struct timer_list *t) · 8 unmodified lines | ||
| 202 | 208 | |
| 203 | 209 | if (fatal_error) { |
| 204 | 210 | mlx5_core_warn(dev, "Got Device Reset\n"); |
| 205 | − mlx5_sync_reset_clear_reset_requested(dev, false); | |
| 206 | 211 | queue_work(fw_reset->wq, &fw_reset->reset_reload_work); |
| 207 | 212 | return; |
| 208 | 213 | } |
| @@ -229,13 +234,17 @@ static int mlx5_fw_reset_set_reset_sync_nack(struct mlx5_core_dev *dev) · 20 unmodified lines | ||
| 229 | 234 | return mlx5_reg_mfrl_set(dev, MLX5_MFRL_REG_RESET_LEVEL3, 0, 2, false); |
| 230 | 235 | } |
| 231 | 236 | |
| 232 | −static void mlx5_sync_reset_set_reset_requested(struct mlx5_core_dev *dev) | |
| 237 | +static int mlx5_sync_reset_set_reset_requested(struct mlx5_core_dev *dev) | |
| 233 | 238 | { |
| 234 | 239 | struct mlx5_fw_reset *fw_reset = dev->priv.fw_reset; |
| 235 | 240 | |
| 241 | + if (test_and_set_bit(MLX5_FW_RESET_FLAGS_RESET_REQUESTED, &fw_reset->reset_flags)) { | |
| 242 | + mlx5_core_warn(dev, "Reset request was already set\n"); | |
| 243 | + return -EALREADY; | |
| 244 | + } | |
| 236 | 245 | mlx5_stop_health_poll(dev, true); |
| 237 | − set_bit(MLX5_FW_RESET_FLAGS_RESET_REQUESTED, &fw_reset->reset_flags); | |
| 238 | 246 | mlx5_start_sync_reset_poll(dev); |
| 247 | + return 0; | |
| 239 | 248 | } |
| 240 | 249 | |
| 241 | 250 | static void mlx5_fw_live_patch_event(struct work_struct *work) |
| @@ -264,7 +273,9 @@ static void mlx5_sync_reset_request_event(struct work_struct *work) · 22 unmodified lines | ||
| 264 | 273 | err ? "Failed" : "Sent"); |
| 265 | 274 | return; |
| 266 | 275 | } |
| 267 | − mlx5_sync_reset_set_reset_requested(dev); | |
| 276 | + if (mlx5_sync_reset_set_reset_requested(dev)) | |
| 277 | + return; | |
| 278 | + | |
| 268 | 279 | err = mlx5_fw_reset_set_reset_sync_ack(dev); |
| 269 | 280 | if (err) |
| 270 | 281 | mlx5_core_warn(dev, "PCI Sync FW Update Reset Ack Failed. Error code: %d\n", err); |
| @@ -362,7 +373,8 @@ static void mlx5_sync_reset_now_event(struct work_struct *work) · 91 unmodified lines | ||
| 362 | 373 | struct mlx5_core_dev *dev = fw_reset->dev; |
| 363 | 374 | int err; |
| 364 | 375 | |
| 365 | − mlx5_sync_reset_clear_reset_requested(dev, false); | |
| 376 | + if (mlx5_sync_reset_clear_reset_requested(dev, false)) | |
| 377 | + return; | |
| 366 | 378 | |
| 367 | 379 | mlx5_core_warn(dev, "Sync Reset now. Device is going to reset.\n"); |
| 368 | 380 | |
| @@ -391,10 +403,8 @@ static void mlx5_sync_reset_abort_event(struct work_struct *work) · 22 unmodified lines | ||
| 391 | 403 | reset_abort_work); |
| 392 | 404 | struct mlx5_core_dev *dev = fw_reset->dev; |
| 393 | 405 | |
| 394 | − if (!test_bit(MLX5_FW_RESET_FLAGS_RESET_REQUESTED, &fw_reset->reset_flags)) | |
| 406 | + if (mlx5_sync_reset_clear_reset_requested(dev, true)) | |
| 395 | 407 | return; |
| 396 | − | |
| 397 | − mlx5_sync_reset_clear_reset_requested(dev, true); | |
| 398 | 408 | mlx5_core_warn(dev, "PCI Sync FW Update Reset Aborted.\n"); |
| 399 | 409 | } |
| 400 | 410 | |
| @@ -100,6 +100,14 @@ static void mlx5_lag_fib_event_flush(struct notifier_block *nb) · 99 unmodified lines | ||
| 100 | 100 | flush_workqueue(mp->wq); |
| 101 | 101 | } |
| 102 | 102 | |
| 103 | +static void mlx5_lag_fib_set(struct lag_mp *mp, struct fib_info *fi, u32 dst, int dst_len) | |
| 104 | +{ | |
| 105 | + mp->fib.mfi = fi; | |
| 106 | + mp->fib.priority = fi->fib_priority; | |
| 107 | + mp->fib.dst = dst; | |
| 108 | + mp->fib.dst_len = dst_len; | |
| 109 | +} | |
| 110 | + | |
| 103 | 111 | struct mlx5_fib_event_work { |
| 104 | 112 | struct work_struct work; |
| 105 | 113 | struct mlx5_lag *ldev; |
| @@ -110,10 +118,10 @@ struct mlx5_fib_event_work { · 4 unmodified lines | ||
| 110 | 118 | }; |
| 111 | 119 | }; |
| 112 | 120 | |
| 113 | −static void mlx5_lag_fib_route_event(struct mlx5_lag *ldev, | |
| 114 | − unsigned long event, | |
| 115 | − struct fib_info *fi) | |
| 121 | +static void mlx5_lag_fib_route_event(struct mlx5_lag *ldev, unsigned long event, | |
| 122 | + struct fib_entry_notifier_info *fen_info) | |
| 116 | 123 | { |
| 124 | + struct fib_info *fi = fen_info->fi; | |
| 117 | 125 | struct lag_mp *mp = &ldev->lag_mp; |
| 118 | 126 | struct fib_nh *fib_nh0, *fib_nh1; |
| 119 | 127 | unsigned int nhs; |
| @@ -121,13 +129,15 @@ static void mlx5_lag_fib_route_event(struct mlx5_lag *ldev, · 1 unmodified line | ||
| 121 | 129 | /* Handle delete event */ |
| 122 | 130 | if (event == FIB_EVENT_ENTRY_DEL) { |
| 123 | 131 | /* stop track */ |
| 124 | − if (mp->mfi == fi) | |
| 125 | − mp->mfi = NULL; | |
| 132 | + if (mp->fib.mfi == fi) | |
| 133 | + mp->fib.mfi = NULL; | |
| 126 | 134 | return; |
| 127 | 135 | } |
| 128 | 136 | |
| 129 | 137 | /* Handle multipath entry with lower priority value */ |
| 130 | − if (mp->mfi && mp->mfi != fi && fi->fib_priority >= mp->mfi->fib_priority) | |
| 138 | + if (mp->fib.mfi && mp->fib.mfi != fi && | |
| 139 | + (mp->fib.dst != fen_info->dst || mp->fib.dst_len != fen_info->dst_len) && | |
| 140 | + fi->fib_priority >= mp->fib.priority) | |
| 131 | 141 | return; |
| 132 | 142 | |
| 133 | 143 | /* Handle add/replace event */ |
| @@ -143,9 +153,9 @@ static void mlx5_lag_fib_route_event(struct mlx5_lag *ldev, · 9 unmodified lines | ||
| 143 | 153 | |
| 144 | 154 | i++; |
| 145 | 155 | mlx5_lag_set_port_affinity(ldev, i); |
| 156 | + mlx5_lag_fib_set(mp, fi, fen_info->dst, fen_info->dst_len); | |
| 146 | 157 | } |
| 147 | 158 | |
| 148 | − mp->mfi = fi; | |
| 149 | 159 | return; |
| 150 | 160 | } |
| 151 | 161 | |
| @@ -165,7 +175,7 @@ static void mlx5_lag_fib_route_event(struct mlx5_lag *ldev, · 13 unmodified lines | ||
| 165 | 175 | } |
| 166 | 176 | |
| 167 | 177 | /* First time we see multipath route */ |
| 168 | − if (!mp->mfi && !__mlx5_lag_is_active(ldev)) { | |
| 178 | + if (!mp->fib.mfi && !__mlx5_lag_is_active(ldev)) { | |
| 169 | 179 | struct lag_tracker tracker; |
| 170 | 180 | |
| 171 | 181 | tracker = ldev->tracker; |
| @@ -173,7 +183,7 @@ static void mlx5_lag_fib_route_event(struct mlx5_lag *ldev, · 1 unmodified line | ||
| 173 | 183 | } |
| 174 | 184 | |
| 175 | 185 | mlx5_lag_set_port_affinity(ldev, MLX5_LAG_NORMAL_AFFINITY); |
| 176 | − mp->mfi = fi; | |
| 186 | + mlx5_lag_fib_set(mp, fi, fen_info->dst, fen_info->dst_len); | |
| 177 | 187 | } |
| 178 | 188 | |
| 179 | 189 | static void mlx5_lag_fib_nexthop_event(struct mlx5_lag *ldev, |
| @@ -184,7 +194,7 @@ static void mlx5_lag_fib_nexthop_event(struct mlx5_lag *ldev, · 4 unmodified lines | ||
| 184 | 194 | struct lag_mp *mp = &ldev->lag_mp; |
| 185 | 195 | |
| 186 | 196 | /* Check the nh event is related to the route */ |
| 187 | − if (!mp->mfi || mp->mfi != fi) | |
| 197 | + if (!mp->fib.mfi || mp->fib.mfi != fi) | |
| 188 | 198 | return; |
| 189 | 199 | |
| 190 | 200 | /* nh added/removed */ |
| @@ -214,7 +224,7 @@ static void mlx5_lag_fib_update(struct work_struct *work) · 23 unmodified lines | ||
| 214 | 224 | case FIB_EVENT_ENTRY_REPLACE: |
| 215 | 225 | case FIB_EVENT_ENTRY_DEL: |
| 216 | 226 | mlx5_lag_fib_route_event(ldev, fib_work->event, |
| 217 | − fib_work->fen_info.fi); | |
| 227 | + &fib_work->fen_info); | |
| 218 | 228 | fib_info_put(fib_work->fen_info.fi); |
| 219 | 229 | break; |
| 220 | 230 | case FIB_EVENT_NH_ADD: |
| @@ -313,7 +323,7 @@ void mlx5_lag_mp_reset(struct mlx5_lag *ldev) · 92 unmodified lines | ||
| 313 | 323 | /* Clear mfi, as it might become stale when a route delete event |
| 314 | 324 | * has been missed, see mlx5_lag_fib_route_event(). |
| 315 | 325 | */ |
| 316 | − ldev->lag_mp.mfi = NULL; | |
| 326 | + ldev->lag_mp.fib.mfi = NULL; | |
| 317 | 327 | } |
| 318 | 328 | |
| 319 | 329 | int mlx5_lag_mp_init(struct mlx5_lag *ldev) |
| @@ -324,7 +334,7 @@ int mlx5_lag_mp_init(struct mlx5_lag *ldev) · 4 unmodified lines | ||
| 324 | 334 | /* always clear mfi, as it might become stale when a route delete event |
| 325 | 335 | * has been missed |
| 326 | 336 | */ |
| 327 | − mp->mfi = NULL; | |
| 337 | + mp->fib.mfi = NULL; | |
| 328 | 338 | |
| 329 | 339 | if (mp->fib_nb.notifier_call) |
| 330 | 340 | return 0; |
| @@ -354,5 +364,5 @@ void mlx5_lag_mp_cleanup(struct mlx5_lag *ldev) · 23 unmodified lines | ||
| 354 | 364 | unregister_fib_notifier(&init_net, &mp->fib_nb); |
| 355 | 365 | destroy_workqueue(mp->wq); |
| 356 | 366 | mp->fib_nb.notifier_call = NULL; |
| 357 | − mp->mfi = NULL; | |
| 367 | + mp->fib.mfi = NULL; | |
| 358 | 368 | } |
| @@ -15,7 +15,12 @@ enum mlx5_lag_port_affinity { · 14 unmodified lines | ||
| 15 | 15 | |
| 16 | 16 | struct lag_mp { |
| 17 | 17 | struct notifier_block fib_nb; |
| 18 | − struct fib_info *mfi; /* used in tracking fib events */ | |
| 18 | + struct { | |
| 19 | + const void *mfi; /* used in tracking fib events */ | |
| 20 | + u32 priority; | |
| 21 | + u32 dst; | |
| 22 | + int dst_len; | |
| 23 | + } fib; | |
| 19 | 24 | struct workqueue_struct *wq; |
| 20 | 25 | }; |
| 21 | 26 | |
| @@ -505,7 +505,7 @@ static int mlx5_lag_create_inner_ttc_table(struct mlx5_lag *ldev) · 504 unmodified lines | ||
| 505 | 505 | struct ttc_params ttc_params = {}; |
| 506 | 506 | |
| 507 | 507 | mlx5_lag_set_inner_ttc_params(ldev, &ttc_params); |
| 508 | − port_sel->inner.ttc = mlx5_create_ttc_table(dev, &ttc_params); | |
| 508 | + port_sel->inner.ttc = mlx5_create_inner_ttc_table(dev, &ttc_params); | |
| 509 | 509 | if (IS_ERR(port_sel->inner.ttc)) |
| 510 | 510 | return PTR_ERR(port_sel->inner.ttc); |
| 511 | 511 | |
| @@ -408,6 +408,8 @@ static int mlx5_generate_inner_ttc_table_rules(struct mlx5_core_dev *dev, · 407 unmodified lines | ||
| 408 | 408 | for (tt = 0; tt < MLX5_NUM_TT; tt++) { |
| 409 | 409 | struct mlx5_ttc_rule *rule = &rules[tt]; |
| 410 | 410 | |
| 411 | + if (test_bit(tt, params->ignore_dests)) | |
| 412 | + continue; | |
| 411 | 413 | rule->rule = mlx5_generate_inner_ttc_rule(dev, ft, |
| 412 | 414 | ¶ms->dests[tt], |
| 413 | 415 | ttc_rules[tt].etype, |
| @@ -568,10 +568,8 @@ static int · 567 unmodified lines | ||
| 568 | 568 | mlxsw_sp2_ipip_rem_addr_set_gre6(struct mlxsw_sp *mlxsw_sp, |
| 569 | 569 | struct mlxsw_sp_ipip_entry *ipip_entry) |
| 570 | 570 | { |
| 571 | − struct __ip6_tnl_parm parms6; | |
| 572 | − | |
| 573 | − parms6 = mlxsw_sp_ipip_netdev_parms6(ipip_entry->ol_dev); | |
| 574 | − return mlxsw_sp_ipv6_addr_kvdl_index_get(mlxsw_sp, &parms6.raddr, | |
| 571 | + return mlxsw_sp_ipv6_addr_kvdl_index_get(mlxsw_sp, | |
| 572 | + &ipip_entry->parms.daddr.addr6, | |
| 575 | 573 | &ipip_entry->dip_kvdl_index); |
| 576 | 574 | } |
| 577 | 575 | |
| @@ -579,10 +577,7 @@ static void · 1 unmodified line | ||
| 579 | 577 | mlxsw_sp2_ipip_rem_addr_unset_gre6(struct mlxsw_sp *mlxsw_sp, |
| 580 | 578 | const struct mlxsw_sp_ipip_entry *ipip_entry) |
| 581 | 579 | { |
| 582 | − struct __ip6_tnl_parm parms6; | |
| 583 | − | |
| 584 | − parms6 = mlxsw_sp_ipip_netdev_parms6(ipip_entry->ol_dev); | |
| 585 | − mlxsw_sp_ipv6_addr_put(mlxsw_sp, &parms6.raddr); | |
| 580 | + mlxsw_sp_ipv6_addr_put(mlxsw_sp, &ipip_entry->parms.daddr.addr6); | |
| 586 | 581 | } |
| 587 | 582 | |
| 588 | 583 | static const struct mlxsw_sp_ipip_ops mlxsw_sp2_ipip_gre6_ops = { |
| @@ -346,7 +346,7 @@ static void lan966x_mac_irq_process(struct lan966x *lan966x, u32 row, · 345 unmodified lines | ||
| 346 | 346 | |
| 347 | 347 | lan966x_mac_process_raw_entry(&raw_entries[column], |
| 348 | 348 | mac, &vid, &dest_idx); |
| 349 | − if (WARN_ON(dest_idx > lan966x->num_phys_ports)) | |
| 349 | + if (WARN_ON(dest_idx >= lan966x->num_phys_ports)) | |
| 350 | 350 | continue; |
| 351 | 351 | |
| 352 | 352 | /* If the entry in SW is found, then there is nothing |
| @@ -393,7 +393,7 @@ static void lan966x_mac_irq_process(struct lan966x *lan966x, u32 row, · 40 unmodified lines | ||
| 393 | 393 | |
| 394 | 394 | lan966x_mac_process_raw_entry(&raw_entries[column], |
| 395 | 395 | mac, &vid, &dest_idx); |
| 396 | − if (WARN_ON(dest_idx > lan966x->num_phys_ports)) | |
| 396 | + if (WARN_ON(dest_idx >= lan966x->num_phys_ports)) | |
| 397 | 397 | continue; |
| 398 | 398 | |
| 399 | 399 | mac_entry = lan966x_mac_alloc_entry(mac, vid, dest_idx); |
| @@ -551,7 +551,7 @@ int ocelot_port_vlan_filtering(struct ocelot *ocelot, int port, · 550 unmodified lines | ||
| 551 | 551 | struct ocelot_vcap_block *block = &ocelot->block[VCAP_IS1]; |
| 552 | 552 | struct ocelot_port *ocelot_port = ocelot->ports[port]; |
| 553 | 553 | struct ocelot_vcap_filter *filter; |
| 554 | − int err; | |
| 554 | + int err = 0; | |
| 555 | 555 | u32 val; |
| 556 | 556 | |
| 557 | 557 | list_for_each_entry(filter, &block->rules, list) { |
| @@ -570,7 +570,7 @@ int ocelot_port_vlan_filtering(struct ocelot *ocelot, int port, · 12 unmodified lines | ||
| 570 | 570 | if (vlan_aware) |
| 571 | 571 | err = ocelot_del_vlan_unaware_pvid(ocelot, port, |
| 572 | 572 | ocelot_port->bridge); |
| 573 | − else | |
| 573 | + else if (ocelot_port->bridge) | |
| 574 | 574 | err = ocelot_add_vlan_unaware_pvid(ocelot, port, |
| 575 | 575 | ocelot_port->bridge); |
| 576 | 576 | if (err) |
| @@ -629,6 +629,13 @@ int ocelot_vlan_add(struct ocelot *ocelot, int port, u16 vid, bool pvid, · 52 unmodified lines | ||
| 629 | 629 | { |
| 630 | 630 | int err; |
| 631 | 631 | |
| 632 | + /* Ignore VID 0 added to our RX filter by the 8021q module, since | |
| 633 | + * that collides with OCELOT_STANDALONE_PVID and changes it from | |
| 634 | + * egress-untagged to egress-tagged. | |
| 635 | + */ | |
| 636 | + if (!vid) | |
| 637 | + return 0; | |
| 638 | + | |
| 632 | 639 | err = ocelot_vlan_member_add(ocelot, port, vid, untagged); |
| 633 | 640 | if (err) |
| 634 | 641 | return err; |
| @@ -651,6 +658,9 @@ int ocelot_vlan_del(struct ocelot *ocelot, int port, u16 vid) · 16 unmodified lines | ||
| 651 | 658 | bool del_pvid = false; |
| 652 | 659 | int err; |
| 653 | 660 | |
| 661 | + if (!vid) | |
| 662 | + return 0; | |
| 663 | + | |
| 654 | 664 | if (ocelot_port->pvid_vlan && ocelot_port->pvid_vlan->vid == vid) |
| 655 | 665 | del_pvid = true; |
| 656 | 666 | |
| @@ -1612,7 +1622,7 @@ int ocelot_trap_add(struct ocelot *ocelot, int port, · 955 unmodified lines | ||
| 1612 | 1622 | trap->action.mask_mode = OCELOT_MASK_MODE_PERMIT_DENY; |
| 1613 | 1623 | trap->action.port_mask = 0; |
| 1614 | 1624 | trap->take_ts = take_ts; |
| 1615 | − list_add_tail(&trap->trap_list, &ocelot->traps); | |
| 1625 | + trap->is_trap = true; | |
| 1616 | 1626 | new = true; |
| 1617 | 1627 | } |
| 1618 | 1628 | |
| @@ -1624,10 +1634,8 @@ int ocelot_trap_add(struct ocelot *ocelot, int port, · 5 unmodified lines | ||
| 1624 | 1634 | err = ocelot_vcap_filter_replace(ocelot, trap); |
| 1625 | 1635 | if (err) { |
| 1626 | 1636 | trap->ingress_port_mask &= ~BIT(port); |
| 1627 | − if (!trap->ingress_port_mask) { | |
| 1628 | − list_del(&trap->trap_list); | |
| 1637 | + if (!trap->ingress_port_mask) | |
| 1629 | 1638 | kfree(trap); |
| 1630 | − } | |
| 1631 | 1639 | return err; |
| 1632 | 1640 | } |
| 1633 | 1641 | |
| @@ -1647,11 +1655,8 @@ int ocelot_trap_del(struct ocelot *ocelot, int port, unsigned long cookie) · 13 unmodified lines | ||
| 1647 | 1655 | return 0; |
| 1648 | 1656 | |
| 1649 | 1657 | trap->ingress_port_mask &= ~BIT(port); |
| 1650 | − if (!trap->ingress_port_mask) { | |
| 1651 | − list_del(&trap->trap_list); | |
| 1652 | − | |
| 1658 | + if (!trap->ingress_port_mask) | |
| 1653 | 1659 | return ocelot_vcap_filter_del(ocelot, trap); |
| 1654 | − } | |
| 1655 | 1660 | |
| 1656 | 1661 | return ocelot_vcap_filter_replace(ocelot, trap); |
| 1657 | 1662 | } |
| @@ -280,9 +280,10 @@ static int ocelot_flower_parse_action(struct ocelot *ocelot, int port, · 279 unmodified lines | ||
| 280 | 280 | filter->type = OCELOT_VCAP_FILTER_OFFLOAD; |
| 281 | 281 | break; |
| 282 | 282 | case FLOW_ACTION_TRAP: |
| 283 | − if (filter->block_id != VCAP_IS2) { | |
| 283 | + if (filter->block_id != VCAP_IS2 || | |
| 284 | + filter->lookup != 0) { | |
| 284 | 285 | NL_SET_ERR_MSG_MOD(extack, |
| 285 | − "Trap action can only be offloaded to VCAP IS2"); | |
| 286 | + "Trap action can only be offloaded to VCAP IS2 lookup 0"); | |
| 286 | 287 | return -EOPNOTSUPP; |
| 287 | 288 | } |
| 288 | 289 | if (filter->goto_target != -1) { |
| @@ -295,7 +296,7 @@ static int ocelot_flower_parse_action(struct ocelot *ocelot, int port, · 6 unmodified lines | ||
| 295 | 296 | filter->action.cpu_copy_ena = true; |
| 296 | 297 | filter->action.cpu_qu_num = 0; |
| 297 | 298 | filter->type = OCELOT_VCAP_FILTER_OFFLOAD; |
| 298 | − list_add_tail(&filter->trap_list, &ocelot->traps); | |
| 299 | + filter->is_trap = true; | |
| 299 | 300 | break; |
| 300 | 301 | case FLOW_ACTION_POLICE: |
| 301 | 302 | if (filter->block_id == PSFP_BLOCK_ID) { |
| @@ -878,8 +879,6 @@ int ocelot_cls_flower_replace(struct ocelot *ocelot, int port, · 576 unmodified lines | ||
| 878 | 879 | |
| 879 | 880 | ret = ocelot_flower_parse(ocelot, port, ingress, f, filter); |
| 880 | 881 | if (ret) { |
| 881 | − if (!list_empty(&filter->trap_list)) | |
| 882 | − list_del(&filter->trap_list); | |
| 883 | 882 | kfree(filter); |
| 884 | 883 | return ret; |
| 885 | 884 | } |
| @@ -374,7 +374,6 @@ static void is2_entry_set(struct ocelot *ocelot, int ix, · 373 unmodified lines | ||
| 374 | 374 | OCELOT_VCAP_BIT_0); |
| 375 | 375 | vcap_key_set(vcap, &data, VCAP_IS2_HK_IGR_PORT_MASK, 0, |
| 376 | 376 | ~filter->ingress_port_mask); |
| 377 | − vcap_key_bit_set(vcap, &data, VCAP_IS2_HK_FIRST, OCELOT_VCAP_BIT_ANY); | |
| 378 | 377 | vcap_key_bit_set(vcap, &data, VCAP_IS2_HK_HOST_MATCH, |
| 379 | 378 | OCELOT_VCAP_BIT_ANY); |
| 380 | 379 | vcap_key_bit_set(vcap, &data, VCAP_IS2_HK_L2_MC, filter->dmac_mc); |
| @@ -1217,6 +1216,8 @@ int ocelot_vcap_filter_add(struct ocelot *ocelot, · 836 unmodified lines | ||
| 1217 | 1216 | struct ocelot_vcap_filter *tmp; |
| 1218 | 1217 | |
| 1219 | 1218 | tmp = ocelot_vcap_block_find_filter_by_index(block, i); |
| 1219 | + /* Read back the filter's counters before moving it */ | |
| 1220 | + vcap_entry_get(ocelot, i - 1, tmp); | |
| 1220 | 1221 | vcap_entry_set(ocelot, i, tmp); |
| 1221 | 1222 | } |
| 1222 | 1223 | |
| @@ -1250,7 +1251,11 @@ int ocelot_vcap_filter_del(struct ocelot *ocelot, · 27 unmodified lines | ||
| 1250 | 1251 | struct ocelot_vcap_filter del_filter; |
| 1251 | 1252 | int i, index; |
| 1252 | 1253 | |
| 1254 | + /* Need to inherit the block_id so that vcap_entry_set() | |
| 1255 | + * does not get confused and knows where to install it. | |
| 1256 | + */ | |
| 1253 | 1257 | memset(&del_filter, 0, sizeof(del_filter)); |
| 1258 | + del_filter.block_id = filter->block_id; | |
| 1254 | 1259 | |
| 1255 | 1260 | /* Gets index of the filter */ |
| 1256 | 1261 | index = ocelot_vcap_block_get_filter_index(block, filter); |
| @@ -1265,6 +1270,8 @@ int ocelot_vcap_filter_del(struct ocelot *ocelot, · 8 unmodified lines | ||
| 1265 | 1270 | struct ocelot_vcap_filter *tmp; |
| 1266 | 1271 | |
| 1267 | 1272 | tmp = ocelot_vcap_block_find_filter_by_index(block, i); |
| 1273 | + /* Read back the filter's counters before moving it */ | |
| 1274 | + vcap_entry_get(ocelot, i + 1, tmp); | |
| 1268 | 1275 | vcap_entry_set(ocelot, i, tmp); |
| 1269 | 1276 | } |
| 1270 | 1277 | |
| @@ -256,7 +256,7 @@ static int ionic_probe(struct pci_dev *pdev, const struct pci_device_id *ent) · 255 unmodified lines | ||
| 256 | 256 | |
| 257 | 257 | err = ionic_map_bars(ionic); |
| 258 | 258 | if (err) |
| 259 | − goto err_out_pci_disable_device; | |
| 259 | + goto err_out_pci_release_regions; | |
| 260 | 260 | |
| 261 | 261 | /* Configure the device */ |
| 262 | 262 | err = ionic_setup(ionic); |
| @@ -360,6 +360,7 @@ err_out_teardown: · 97 unmodified lines | ||
| 360 | 360 | |
| 361 | 361 | err_out_unmap_bars: |
| 362 | 362 | ionic_unmap_bars(ionic); |
| 363 | +err_out_pci_release_regions: | |
| 363 | 364 | pci_release_regions(pdev); |
| 364 | 365 | err_out_pci_disable_device: |
| 365 | 366 | pci_disable_device(pdev); |
| @@ -3579,6 +3579,11 @@ static int efx_ef10_mtd_probe(struct efx_nic *efx) · 3578 unmodified lines | ||
| 3579 | 3579 | n_parts++; |
| 3580 | 3580 | } |
| 3581 | 3581 | |
| 3582 | + if (!n_parts) { | |
| 3583 | + kfree(parts); | |
| 3584 | + return 0; | |
| 3585 | + } | |
| 3586 | + | |
| 3582 | 3587 | rc = efx_mtd_add(efx, &parts[0].common, n_parts, sizeof(*parts)); |
| 3583 | 3588 | fail: |
| 3584 | 3589 | if (rc) |
| @@ -867,7 +867,9 @@ static void efx_set_xdp_channels(struct efx_nic *efx) · 866 unmodified lines | ||
| 867 | 867 | |
| 868 | 868 | int efx_realloc_channels(struct efx_nic *efx, u32 rxq_entries, u32 txq_entries) |
| 869 | 869 | { |
| 870 | − struct efx_channel *other_channel[EFX_MAX_CHANNELS], *channel; | |
| 870 | + struct efx_channel *other_channel[EFX_MAX_CHANNELS], *channel, | |
| 871 | + *ptp_channel = efx_ptp_channel(efx); | |
| 872 | + struct efx_ptp_data *ptp_data = efx->ptp_data; | |
| 871 | 873 | unsigned int i, next_buffer_table = 0; |
| 872 | 874 | u32 old_rxq_entries, old_txq_entries; |
| 873 | 875 | int rc, rc2; |
| @@ -938,6 +940,7 @@ int efx_realloc_channels(struct efx_nic *efx, u32 rxq_entries, u32 txq_entries) · 64 unmodified lines | ||
| 938 | 940 | |
| 939 | 941 | efx_set_xdp_channels(efx); |
| 940 | 942 | out: |
| 943 | + efx->ptp_data = NULL; | |
| 941 | 944 | /* Destroy unused channel structures */ |
| 942 | 945 | for (i = 0; i < efx->n_channels; i++) { |
| 943 | 946 | channel = other_channel[i]; |
| @@ -948,6 +951,7 @@ out: · 4 unmodified lines | ||
| 948 | 951 | } |
| 949 | 952 | } |
| 950 | 953 | |
| 954 | + efx->ptp_data = ptp_data; | |
| 951 | 955 | rc2 = efx_soft_enable_interrupts(efx); |
| 952 | 956 | if (rc2) { |
| 953 | 957 | rc = rc ? rc : rc2; |
| @@ -966,6 +970,7 @@ rollback: · 12 unmodified lines | ||
| 966 | 970 | efx->txq_entries = old_txq_entries; |
| 967 | 971 | for (i = 0; i < efx->n_channels; i++) |
| 968 | 972 | swap(efx->channel[i], other_channel[i]); |
| 973 | + efx_ptp_update_channel(efx, ptp_channel); | |
| 969 | 974 | goto out; |
| 970 | 975 | } |
| 971 | 976 | |
| @@ -45,6 +45,7 @@ · 44 unmodified lines | ||
| 45 | 45 | #include "farch_regs.h" |
| 46 | 46 | #include "tx.h" |
| 47 | 47 | #include "nic.h" /* indirectly includes ptp.h */ |
| 48 | +#include "efx_channels.h" | |
| 48 | 49 | |
| 49 | 50 | /* Maximum number of events expected to make up a PTP event */ |
| 50 | 51 | #define MAX_EVENT_FRAGS 3 |
| @@ -541,6 +542,12 @@ struct efx_channel *efx_ptp_channel(struct efx_nic *efx) · 490 unmodified lines | ||
| 541 | 542 | return efx->ptp_data ? efx->ptp_data->channel : NULL; |
| 542 | 543 | } |
| 543 | 544 | |
| 545 | +void efx_ptp_update_channel(struct efx_nic *efx, struct efx_channel *channel) | |
| 546 | +{ | |
| 547 | + if (efx->ptp_data) | |
| 548 | + efx->ptp_data->channel = channel; | |
| 549 | +} | |
| 550 | + | |
| 544 | 551 | static u32 last_sync_timestamp_major(struct efx_nic *efx) |
| 545 | 552 | { |
| 546 | 553 | struct efx_channel *channel = efx_ptp_channel(efx); |
| @@ -1443,6 +1450,11 @@ int efx_ptp_probe(struct efx_nic *efx, struct efx_channel *channel) · 896 unmodified lines | ||
| 1443 | 1450 | int rc = 0; |
| 1444 | 1451 | unsigned int pos; |
| 1445 | 1452 | |
| 1453 | + if (efx->ptp_data) { | |
| 1454 | + efx->ptp_data->channel = channel; | |
| 1455 | + return 0; | |
| 1456 | + } | |
| 1457 | + | |
| 1446 | 1458 | ptp = kzalloc(sizeof(struct efx_ptp_data), GFP_KERNEL); |
| 1447 | 1459 | efx->ptp_data = ptp; |
| 1448 | 1460 | if (!efx->ptp_data) |
| @@ -2176,7 +2188,7 @@ static const struct efx_channel_type efx_ptp_channel_type = { · 727 unmodified lines | ||
| 2176 | 2188 | .pre_probe = efx_ptp_probe_channel, |
| 2177 | 2189 | .post_remove = efx_ptp_remove_channel, |
| 2178 | 2190 | .get_name = efx_ptp_get_channel_name, |
| 2179 | − /* no copy operation; there is no need to reallocate this channel */ | |
| 2191 | + .copy = efx_copy_channel, | |
| 2180 | 2192 | .receive_skb = efx_ptp_rx, |
| 2181 | 2193 | .want_txqs = efx_ptp_want_txqs, |
| 2182 | 2194 | .keep_eventq = false, |
| @@ -16,6 +16,7 @@ struct ethtool_ts_info; · 15 unmodified lines | ||
| 16 | 16 | int efx_ptp_probe(struct efx_nic *efx, struct efx_channel *channel); |
| 17 | 17 | void efx_ptp_defer_probe_with_channel(struct efx_nic *efx); |
| 18 | 18 | struct efx_channel *efx_ptp_channel(struct efx_nic *efx); |
| 19 | +void efx_ptp_update_channel(struct efx_nic *efx, struct efx_channel *channel); | |
| 19 | 20 | void efx_ptp_remove(struct efx_nic *efx); |
| 20 | 21 | int efx_ptp_set_ts_config(struct efx_nic *efx, struct ifreq *ifr); |
| 21 | 22 | int efx_ptp_get_ts_config(struct efx_nic *efx, struct ifreq *ifr); |
| @@ -2431,7 +2431,7 @@ static int smsc911x_drv_probe(struct platform_device *pdev) · 2430 unmodified lines | ||
| 2431 | 2431 | if (irq == -EPROBE_DEFER) { |
| 2432 | 2432 | retval = -EPROBE_DEFER; |
| 2433 | 2433 | goto out_0; |
| 2434 | − } else if (irq <= 0) { | |
| 2434 | + } else if (irq < 0) { | |
| 2435 | 2435 | pr_warn("Could not allocate irq resource\n"); |
| 2436 | 2436 | retval = -ENODEV; |
| 2437 | 2437 | goto out_0; |
| @@ -454,6 +454,7 @@ static int intel_mgbe_common_data(struct pci_dev *pdev, · 453 unmodified lines | ||
| 454 | 454 | plat->has_gmac4 = 1; |
| 455 | 455 | plat->force_sf_dma_mode = 0; |
| 456 | 456 | plat->tso_en = 1; |
| 457 | + plat->sph_disable = 1; | |
| 457 | 458 | |
| 458 | 459 | /* Multiplying factor to the clk_eee_i clock time |
| 459 | 460 | * period to make it closer to 100 ns. This value |
| @@ -65,8 +65,9 @@ static void socfpga_dwmac_fix_mac_speed(void *priv, unsigned int speed) · 64 unmodified lines | ||
| 65 | 65 | struct phy_device *phy_dev = ndev->phydev; |
| 66 | 66 | u32 val; |
| 67 | 67 | |
| 68 | − writew(SGMII_ADAPTER_DISABLE, | |
| 69 | − sgmii_adapter_base + SGMII_ADAPTER_CTRL_REG); | |
| 68 | + if (sgmii_adapter_base) | |
| 69 | + writew(SGMII_ADAPTER_DISABLE, | |
| 70 | + sgmii_adapter_base + SGMII_ADAPTER_CTRL_REG); | |
| 70 | 71 | |
| 71 | 72 | if (splitter_base) { |
| 72 | 73 | val = readl(splitter_base + EMAC_SPLITTER_CTRL_REG); |
| @@ -88,10 +89,11 @@ static void socfpga_dwmac_fix_mac_speed(void *priv, unsigned int speed) · 15 unmodified lines | ||
| 88 | 89 | writel(val, splitter_base + EMAC_SPLITTER_CTRL_REG); |
| 89 | 90 | } |
| 90 | 91 | |
| 91 | − writew(SGMII_ADAPTER_ENABLE, | |
| 92 | − sgmii_adapter_base + SGMII_ADAPTER_CTRL_REG); | |
| 93 | − if (phy_dev) | |
| 92 | + if (phy_dev && sgmii_adapter_base) { | |
| 93 | + writew(SGMII_ADAPTER_ENABLE, | |
| 94 | + sgmii_adapter_base + SGMII_ADAPTER_CTRL_REG); | |
| 94 | 95 | tse_pcs_fix_mac_speed(&dwmac->pcs, phy_dev, speed); |
| 96 | + } | |
| 95 | 97 | } |
| 96 | 98 | |
| 97 | 99 | static int socfpga_dwmac_parse_data(struct socfpga_dwmac *dwmac, struct device *dev) |
| @@ -907,6 +907,7 @@ static int sun8i_dwmac_register_mdio_mux(struct stmmac_priv *priv) · 906 unmodified lines | ||
| 907 | 907 | |
| 908 | 908 | ret = mdio_mux_init(priv->device, mdio_mux, mdio_mux_syscon_switch_fn, |
| 909 | 909 | &gmac->mux_handle, priv, priv->mii); |
| 910 | + of_node_put(mdio_mux); | |
| 910 | 911 | return ret; |
| 911 | 912 | } |
| 912 | 913 | |
| @@ -7021,7 +7021,7 @@ int stmmac_dvr_probe(struct device *device, · 7020 unmodified lines | ||
| 7021 | 7021 | dev_info(priv->device, "TSO feature enabled\n"); |
| 7022 | 7022 | } |
| 7023 | 7023 | |
| 7024 | − if (priv->dma_cap.sphen) { | |
| 7024 | + if (priv->dma_cap.sphen && !priv->plat->sph_disable) { | |
| 7025 | 7025 | ndev->hw_features |= NETIF_F_GRO; |
| 7026 | 7026 | priv->sph_cap = true; |
| 7027 | 7027 | priv->sph = priv->sph_cap; |
| @@ -181,7 +181,7 @@ static int stmmac_pci_probe(struct pci_dev *pdev, · 180 unmodified lines | ||
| 181 | 181 | return -ENOMEM; |
| 182 | 182 | |
| 183 | 183 | /* Enable pci device */ |
| 184 | − ret = pci_enable_device(pdev); | |
| 184 | + ret = pcim_enable_device(pdev); | |
| 185 | 185 | if (ret) { |
| 186 | 186 | dev_err(&pdev->dev, "%s: ERROR: failed to enable device\n", |
| 187 | 187 | __func__); |
| @@ -241,8 +241,6 @@ static void stmmac_pci_remove(struct pci_dev *pdev) · 53 unmodified lines | ||
| 241 | 241 | pcim_iounmap_regions(pdev, BIT(i)); |
| 242 | 242 | break; |
| 243 | 243 | } |
| 244 | − | |
| 245 | − pci_disable_device(pdev); | |
| 246 | 244 | } |
| 247 | 245 | |
| 248 | 246 | static int __maybe_unused stmmac_pci_suspend(struct device *dev) |
| @@ -1246,8 +1246,10 @@ static int cpsw_probe_dt(struct cpsw_common *cpsw) · 1245 unmodified lines | ||
| 1246 | 1246 | data->slave_data = devm_kcalloc(dev, CPSW_SLAVE_PORTS_NUM, |
| 1247 | 1247 | sizeof(struct cpsw_slave_data), |
| 1248 | 1248 | GFP_KERNEL); |
| 1249 | − if (!data->slave_data) | |
| 1249 | + if (!data->slave_data) { | |
| 1250 | + of_node_put(tmp_node); | |
| 1250 | 1251 | return -ENOMEM; |
| 1252 | + } | |
| 1251 | 1253 | |
| 1252 | 1254 | /* Populate all the child nodes here... |
| 1253 | 1255 | */ |
| @@ -1341,6 +1343,7 @@ static int cpsw_probe_dt(struct cpsw_common *cpsw) · 87 unmodified lines | ||
| 1341 | 1343 | |
| 1342 | 1344 | err_node_put: |
| 1343 | 1345 | of_node_put(port_np); |
| 1346 | + of_node_put(tmp_node); | |
| 1344 | 1347 | return ret; |
| 1345 | 1348 | } |
| 1346 | 1349 | |
| @@ -823,10 +823,10 @@ static int xemaclite_mdio_write(struct mii_bus *bus, int phy_id, int reg, · 822 unmodified lines | ||
| 823 | 823 | static int xemaclite_mdio_setup(struct net_local *lp, struct device *dev) |
| 824 | 824 | { |
| 825 | 825 | struct mii_bus *bus; |
| 826 | − int rc; | |
| 827 | 826 | struct resource res; |
| 828 | 827 | struct device_node *np = of_get_parent(lp->phy_node); |
| 829 | 828 | struct device_node *npp; |
| 829 | + int rc, ret; | |
| 830 | 830 | |
| 831 | 831 | /* Don't register the MDIO bus if the phy_node or its parent node |
| 832 | 832 | * can't be found. |
| @@ -836,8 +836,14 @@ static int xemaclite_mdio_setup(struct net_local *lp, struct device *dev) · 3 unmodified lines | ||
| 836 | 836 | return -ENODEV; |
| 837 | 837 | } |
| 838 | 838 | npp = of_get_parent(np); |
| 839 | − | |
| 840 | − of_address_to_resource(npp, 0, &res); | |
| 839 | + ret = of_address_to_resource(npp, 0, &res); | |
| 840 | + of_node_put(npp); | |
| 841 | + if (ret) { | |
| 842 | + dev_err(dev, "%s resource error!\n", | |
| 843 | + dev->of_node->full_name); | |
| 844 | + of_node_put(np); | |
| 845 | + return ret; | |
| 846 | + } | |
| 841 | 847 | if (lp->ndev->mem_start != res.start) { |
| 842 | 848 | struct phy_device *phydev; |
| 843 | 849 | phydev = of_phy_find_device(lp->phy_node); |
| @@ -846,6 +852,7 @@ static int xemaclite_mdio_setup(struct net_local *lp, struct device *dev) · 2 unmodified lines | ||
| 846 | 852 | "MDIO of the phy is not registered yet\n"); |
| 847 | 853 | else |
| 848 | 854 | put_device(&phydev->mdio.dev); |
| 855 | + of_node_put(np); | |
| 849 | 856 | return 0; |
| 850 | 857 | } |
| 851 | 858 | |
| @@ -858,6 +865,7 @@ static int xemaclite_mdio_setup(struct net_local *lp, struct device *dev) · 6 unmodified lines | ||
| 858 | 865 | bus = mdiobus_alloc(); |
| 859 | 866 | if (!bus) { |
| 860 | 867 | dev_err(dev, "Failed to allocate mdiobus\n"); |
| 868 | + of_node_put(np); | |
| 861 | 869 | return -ENOMEM; |
| 862 | 870 | } |
| 863 | 871 | |
| @@ -870,6 +878,7 @@ static int xemaclite_mdio_setup(struct net_local *lp, struct device *dev) · 6 unmodified lines | ||
| 870 | 878 | bus->parent = dev; |
| 871 | 879 | |
| 872 | 880 | rc = of_mdiobus_register(bus, np); |
| 881 | + of_node_put(np); | |
| 873 | 882 | if (rc) { |
| 874 | 883 | dev_err(dev, "Failed to register mdio bus.\n"); |
| 875 | 884 | goto err_register; |
| @@ -926,8 +935,6 @@ static int xemaclite_open(struct net_device *dev) · 50 unmodified lines | ||
| 926 | 935 | xemaclite_disable_interrupts(lp); |
| 927 | 936 | |
| 928 | 937 | if (lp->phy_node) { |
| 929 | − u32 bmcr; | |
| 930 | − | |
| 931 | 938 | lp->phy_dev = of_phy_connect(lp->ndev, lp->phy_node, |
| 932 | 939 | xemaclite_adjust_link, 0, |
| 933 | 940 | PHY_INTERFACE_MODE_MII); |
| @@ -938,19 +945,6 @@ static int xemaclite_open(struct net_device *dev) · 4 unmodified lines | ||
| 938 | 945 | |
| 939 | 946 | /* EmacLite doesn't support giga-bit speeds */ |
| 940 | 947 | phy_set_max_speed(lp->phy_dev, SPEED_100); |
| 941 | − | |
| 942 | − /* Don't advertise 1000BASE-T Full/Half duplex speeds */ | |
| 943 | − phy_write(lp->phy_dev, MII_CTRL1000, 0); | |
| 944 | − | |
| 945 | − /* Advertise only 10 and 100mbps full/half duplex speeds */ | |
| 946 | − phy_write(lp->phy_dev, MII_ADVERTISE, ADVERTISE_ALL | | |
| 947 | − ADVERTISE_CSMA); | |
| 948 | − | |
| 949 | − /* Restart auto negotiation */ | |
| 950 | − bmcr = phy_read(lp->phy_dev, MII_BMCR); | |
| 951 | − bmcr |= (BMCR_ANENABLE | BMCR_ANRESTART); | |
| 952 | − phy_write(lp->phy_dev, MII_BMCR, bmcr); | |
| 953 | − | |
| 954 | 948 | phy_start(lp->phy_dev); |
| 955 | 949 | } |
| 956 | 950 | |
| @@ -115,7 +115,7 @@ static int bcm6368_mdiomux_probe(struct platform_device *pdev) · 114 unmodified lines | ||
| 115 | 115 | md->mii_bus = devm_mdiobus_alloc(&pdev->dev); |
| 116 | 116 | if (!md->mii_bus) { |
| 117 | 117 | dev_err(&pdev->dev, "mdiomux bus alloc failed\n"); |
| 118 | − return ENOMEM; | |
| 118 | + return -ENOMEM; | |
| 119 | 119 | } |
| 120 | 120 | |
| 121 | 121 | bus = md->mii_bus; |
| @@ -880,7 +880,7 @@ static int mv3310_read_status_copper(struct phy_device *phydev) · 879 unmodified lines | ||
| 880 | 880 | |
| 881 | 881 | cssr1 = phy_read_mmd(phydev, MDIO_MMD_PCS, MV_PCS_CSSR1); |
| 882 | 882 | if (cssr1 < 0) |
| 883 | − return val; | |
| 883 | + return cssr1; | |
| 884 | 884 | |
| 885 | 885 | /* If the link settings are not resolved, mark the link down */ |
| 886 | 886 | if (!(cssr1 & MV_PCS_CSSR1_RESOLVED)) { |
| @@ -1743,7 +1743,7 @@ static int ksz886x_cable_test_get_status(struct phy_device *phydev, · 1742 unmodified lines | ||
| 1743 | 1743 | |
| 1744 | 1744 | static int lanphy_read_page_reg(struct phy_device *phydev, int page, u32 addr) |
| 1745 | 1745 | { |
| 1746 | − u32 data; | |
| 1746 | + int data; | |
| 1747 | 1747 | |
| 1748 | 1748 | phy_lock_mdio_bus(phydev); |
| 1749 | 1749 | __phy_write(phydev, LAN_EXT_PAGE_ACCESS_CONTROL, page); |
| @@ -2444,8 +2444,7 @@ static int lan8804_config_init(struct phy_device *phydev) · 694 unmodified lines | ||
| 2444 | 2444 | |
| 2445 | 2445 | static irqreturn_t lan8814_handle_interrupt(struct phy_device *phydev) |
| 2446 | 2446 | { |
| 2447 | − u16 tsu_irq_status; | |
| 2448 | − int irq_status; | |
| 2447 | + int irq_status, tsu_irq_status; | |
| 2449 | 2448 | |
| 2450 | 2449 | irq_status = phy_read(phydev, LAN8814_INTS); |
| 2451 | 2450 | if (irq_status > 0 && (irq_status & LAN8814_INT_LINK)) |
| @@ -2657,6 +2656,7 @@ static struct phy_driver ksphy_driver[] = { · 205 unmodified lines | ||
| 2657 | 2656 | .name = "Micrel KS8737", |
| 2658 | 2657 | /* PHY_BASIC_FEATURES */ |
| 2659 | 2658 | .driver_data = &ks8737_type, |
| 2659 | + .probe = kszphy_probe, | |
| 2660 | 2660 | .config_init = kszphy_config_init, |
| 2661 | 2661 | .config_intr = kszphy_config_intr, |
| 2662 | 2662 | .handle_interrupt = kszphy_handle_interrupt, |
| @@ -2782,8 +2782,8 @@ static struct phy_driver ksphy_driver[] = { · 119 unmodified lines | ||
| 2782 | 2782 | .config_init = ksz8061_config_init, |
| 2783 | 2783 | .config_intr = kszphy_config_intr, |
| 2784 | 2784 | .handle_interrupt = kszphy_handle_interrupt, |
| 2785 | − .suspend = kszphy_suspend, | |
| 2786 | − .resume = kszphy_resume, | |
| 2785 | + .suspend = genphy_suspend, | |
| 2786 | + .resume = genphy_resume, | |
| 2787 | 2787 | }, { |
| 2788 | 2788 | .phy_id = PHY_ID_KSZ9021, |
| 2789 | 2789 | .phy_id_mask = 0x000ffffe, |
| @@ -970,8 +970,13 @@ static irqreturn_t phy_interrupt(int irq, void *phy_dat) · 969 unmodified lines | ||
| 970 | 970 | { |
| 971 | 971 | struct phy_device *phydev = phy_dat; |
| 972 | 972 | struct phy_driver *drv = phydev->drv; |
| 973 | + irqreturn_t ret; | |
| 973 | 974 | |
| 974 | − return drv->handle_interrupt(phydev); | |
| 975 | + mutex_lock(&phydev->lock); | |
| 976 | + ret = drv->handle_interrupt(phydev); | |
| 977 | + mutex_unlock(&phydev->lock); | |
| 978 | + | |
| 979 | + return ret; | |
| 975 | 980 | } |
| 976 | 981 | |
| 977 | 982 | /** |
| @@ -250,6 +250,7 @@ struct sfp { · 249 unmodified lines | ||
| 250 | 250 | struct sfp_eeprom_id id; |
| 251 | 251 | unsigned int module_power_mW; |
| 252 | 252 | unsigned int module_t_start_up; |
| 253 | + bool tx_fault_ignore; | |
| 253 | 254 | |
| 254 | 255 | #if IS_ENABLED(CONFIG_HWMON) |
| 255 | 256 | struct sfp_diag diag; |
| @@ -1956,6 +1957,12 @@ static int sfp_sm_mod_probe(struct sfp *sfp, bool report) · 1700 unmodified lines | ||
| 1956 | 1957 | else |
| 1957 | 1958 | sfp->module_t_start_up = T_START_UP; |
| 1958 | 1959 | |
| 1960 | + if (!memcmp(id.base.vendor_name, "HUAWEI ", 16) && | |
| 1961 | + !memcmp(id.base.vendor_pn, "MA5671A ", 16)) | |
| 1962 | + sfp->tx_fault_ignore = true; | |
| 1963 | + else | |
| 1964 | + sfp->tx_fault_ignore = false; | |
| 1965 | + | |
| 1959 | 1966 | return 0; |
| 1960 | 1967 | } |
| 1961 | 1968 | |
| @@ -2409,7 +2416,10 @@ static void sfp_check_state(struct sfp *sfp) · 447 unmodified lines | ||
| 2409 | 2416 | mutex_lock(&sfp->st_mutex); |
| 2410 | 2417 | state = sfp_get_state(sfp); |
| 2411 | 2418 | changed = state ^ sfp->state; |
| 2412 | − changed &= SFP_F_PRESENT | SFP_F_LOS | SFP_F_TX_FAULT; | |
| 2419 | + if (sfp->tx_fault_ignore) | |
| 2420 | + changed &= SFP_F_PRESENT | SFP_F_LOS; | |
| 2421 | + else | |
| 2422 | + changed &= SFP_F_PRESENT | SFP_F_LOS | SFP_F_TX_FAULT; | |
| 2413 | 2423 | |
| 2414 | 2424 | for (i = 0; i < GPIO_MAX; i++) |
| 2415 | 2425 | if (changed & BIT(i)) |
| @@ -1005,6 +1005,24 @@ static struct sk_buff *receive_mergeable(struct net_device *dev, · 1004 unmodified lines | ||
| 1005 | 1005 | * xdp.data_meta were adjusted |
| 1006 | 1006 | */ |
| 1007 | 1007 | len = xdp.data_end - xdp.data + vi->hdr_len + metasize; |
| 1008 | + | |
| 1009 | + /* recalculate headroom if xdp.data or xdp_data_meta | |
| 1010 | + * were adjusted, note that offset should always point | |
| 1011 | + * to the start of the reserved bytes for virtio_net | |
| 1012 | + * header which are followed by xdp.data, that means | |
| 1013 | + * that offset is equal to the headroom (when buf is | |
| 1014 | + * starting at the beginning of the page, otherwise | |
| 1015 | + * there is a base offset inside the page) but it's used | |
| 1016 | + * with a different starting point (buf start) than | |
| 1017 | + * xdp.data (buf start + vnet hdr size). If xdp.data or | |
| 1018 | + * data_meta were adjusted by the xdp prog then the | |
| 1019 | + * headroom size has changed and so has the offset, we | |
| 1020 | + * can use data_hard_start, which points at buf start + | |
| 1021 | + * vnet hdr size, to calculate the new headroom and use | |
| 1022 | + * it later to compute buf start in page_to_skb() | |
| 1023 | + */ | |
| 1024 | + headroom = xdp.data - xdp.data_hard_start - metasize; | |
| 1025 | + | |
| 1008 | 1026 | /* We can only create skb based on xdp_page. */ |
| 1009 | 1027 | if (unlikely(xdp_page != page)) { |
| 1010 | 1028 | rcu_read_unlock(); |
| @@ -1012,7 +1030,7 @@ static struct sk_buff *receive_mergeable(struct net_device *dev, · 1 unmodified line | ||
| 1012 | 1030 | head_skb = page_to_skb(vi, rq, xdp_page, offset, |
| 1013 | 1031 | len, PAGE_SIZE, false, |
| 1014 | 1032 | metasize, |
| 1015 | − VIRTIO_XDP_HEADROOM); | |
| 1033 | + headroom); | |
| 1016 | 1034 | return head_skb; |
| 1017 | 1035 | } |
| 1018 | 1036 | break; |
| @@ -349,7 +349,7 @@ static int __init cosa_init(void) · 348 unmodified lines | ||
| 349 | 349 | } |
| 350 | 350 | } else { |
| 351 | 351 | cosa_major = register_chrdev(0, "cosa", &cosa_fops); |
| 352 | − if (!cosa_major) { | |
| 352 | + if (cosa_major < 0) { | |
| 353 | 353 | pr_warn("unable to register chardev\n"); |
| 354 | 354 | err = -EIO; |
| 355 | 355 | goto out; |
| @@ -19,6 +19,7 @@ · 18 unmodified lines | ||
| 19 | 19 | #include <linux/if_arp.h> |
| 20 | 20 | #include <linux/icmp.h> |
| 21 | 21 | #include <linux/suspend.h> |
| 22 | +#include <net/dst_metadata.h> | |
| 22 | 23 | #include <net/icmp.h> |
| 23 | 24 | #include <net/rtnetlink.h> |
| 24 | 25 | #include <net/ip_tunnels.h> |
| @@ -167,7 +168,7 @@ static netdev_tx_t wg_xmit(struct sk_buff *skb, struct net_device *dev) · 142 unmodified lines | ||
| 167 | 168 | goto err_peer; |
| 168 | 169 | } |
| 169 | 170 | |
| 170 | − mtu = skb_dst(skb) ? dst_mtu(skb_dst(skb)) : dev->mtu; | |
| 171 | + mtu = skb_valid_dst(skb) ? dst_mtu(skb_dst(skb)) : dev->mtu; | |
| 171 | 172 | |
| 172 | 173 | __skb_queue_head_init(&packets); |
| 173 | 174 | if (!skb_is_gso(skb)) { |
| @@ -1288,6 +1288,7 @@ static void ath11k_core_restart(struct work_struct *work) · 1287 unmodified lines | ||
| 1288 | 1288 | |
| 1289 | 1289 | ieee80211_stop_queues(ar->hw); |
| 1290 | 1290 | ath11k_mac_drain_tx(ar); |
| 1291 | + complete(&ar->completed_11d_scan); | |
| 1291 | 1292 | complete(&ar->scan.started); |
| 1292 | 1293 | complete(&ar->scan.completed); |
| 1293 | 1294 | complete(&ar->peer_assoc_done); |
| @@ -38,6 +38,8 @@ · 37 unmodified lines | ||
| 38 | 38 | |
| 39 | 39 | extern unsigned int ath11k_frame_mode; |
| 40 | 40 | |
| 41 | +#define ATH11K_SCAN_TIMEOUT_HZ (20 * HZ) | |
| 42 | + | |
| 41 | 43 | #define ATH11K_MON_TIMER_INTERVAL 10 |
| 42 | 44 | |
| 43 | 45 | enum ath11k_supported_bw { |
| @@ -189,6 +191,12 @@ enum ath11k_scan_state { · 145 unmodified lines | ||
| 189 | 191 | ATH11K_SCAN_ABORTING, |
| 190 | 192 | }; |
| 191 | 193 | |
| 194 | +enum ath11k_11d_state { | |
| 195 | + ATH11K_11D_IDLE, | |
| 196 | + ATH11K_11D_PREPARING, | |
| 197 | + ATH11K_11D_RUNNING, | |
| 198 | +}; | |
| 199 | + | |
| 192 | 200 | enum ath11k_dev_flags { |
| 193 | 201 | ATH11K_CAC_RUNNING, |
| 194 | 202 | ATH11K_FLAG_CORE_REGISTERED, |
| @@ -607,9 +615,8 @@ struct ath11k { · 412 unmodified lines | ||
| 607 | 615 | bool dfs_block_radar_events; |
| 608 | 616 | struct ath11k_thermal thermal; |
| 609 | 617 | u32 vdev_id_11d_scan; |
| 610 | − struct completion finish_11d_scan; | |
| 611 | − struct completion finish_11d_ch_list; | |
| 612 | − bool pending_11d; | |
| 618 | + struct completion completed_11d_scan; | |
| 619 | + enum ath11k_11d_state state_11d; | |
| 613 | 620 | bool regdom_set_by_user; |
| 614 | 621 | int hw_rate_code; |
| 615 | 622 | u8 twt_enabled; |
| @@ -3601,26 +3601,6 @@ static int ath11k_mac_op_hw_scan(struct ieee80211_hw *hw, · 3600 unmodified lines | ||
| 3601 | 3601 | if (ret) |
| 3602 | 3602 | goto exit; |
| 3603 | 3603 | |
| 3604 | − /* Currently the pending_11d=true only happened 1 time while | |
| 3605 | − * wlan interface up in ath11k_mac_11d_scan_start(), it is called by | |
| 3606 | − * ath11k_mac_op_add_interface(), after wlan interface up, | |
| 3607 | − * pending_11d=false always. | |
| 3608 | − * If remove below wait, it always happened scan fail and lead connect | |
| 3609 | − * fail while wlan interface up, because it has a 11d scan which is running | |
| 3610 | − * in firmware, and lead this scan failed. | |
| 3611 | − */ | |
| 3612 | − if (ar->pending_11d) { | |
| 3613 | − long time_left; | |
| 3614 | − unsigned long timeout = 5 * HZ; | |
| 3615 | − | |
| 3616 | − if (ar->supports_6ghz) | |
| 3617 | − timeout += 5 * HZ; | |
| 3618 | − | |
| 3619 | − time_left = wait_for_completion_timeout(&ar->finish_11d_ch_list, timeout); | |
| 3620 | − ath11k_dbg(ar->ab, ATH11K_DBG_MAC, | |
| 3621 | − "mac wait 11d channel list time left %ld\n", time_left); | |
| 3622 | − } | |
| 3623 | − | |
| 3624 | 3604 | memset(&arg, 0, sizeof(arg)); |
| 3625 | 3605 | ath11k_wmi_start_scan_init(ar, &arg); |
| 3626 | 3606 | arg.vdev_id = arvif->vdev_id; |
| @@ -3686,6 +3666,10 @@ exit: · 59 unmodified lines | ||
| 3686 | 3666 | kfree(arg.extraie.ptr); |
| 3687 | 3667 | |
| 3688 | 3668 | mutex_unlock(&ar->conf_mutex); |
| 3669 | + | |
| 3670 | + if (ar->state_11d == ATH11K_11D_PREPARING) | |
| 3671 | + ath11k_mac_11d_scan_start(ar, arvif->vdev_id); | |
| 3672 | + | |
| 3689 | 3673 | return ret; |
| 3690 | 3674 | } |
| 3691 | 3675 | |
| @@ -5814,7 +5798,7 @@ static int ath11k_mac_op_start(struct ieee80211_hw *hw) · 2122 unmodified lines | ||
| 5814 | 5798 | |
| 5815 | 5799 | /* TODO: Do we need to enable ANI? */ |
| 5816 | 5800 | |
| 5817 | − ath11k_reg_update_chan_list(ar); | |
| 5801 | + ath11k_reg_update_chan_list(ar, false); | |
| 5818 | 5802 | |
| 5819 | 5803 | ar->num_started_vdevs = 0; |
| 5820 | 5804 | ar->num_created_vdevs = 0; |
| @@ -5881,6 +5865,11 @@ static void ath11k_mac_op_stop(struct ieee80211_hw *hw) · 60 unmodified lines | ||
| 5881 | 5865 | cancel_work_sync(&ar->ab->update_11d_work); |
| 5882 | 5866 | cancel_work_sync(&ar->ab->rfkill_work); |
| 5883 | 5867 | |
| 5868 | + if (ar->state_11d == ATH11K_11D_PREPARING) { | |
| 5869 | + ar->state_11d = ATH11K_11D_IDLE; | |
| 5870 | + complete(&ar->completed_11d_scan); | |
| 5871 | + } | |
| 5872 | + | |
| 5884 | 5873 | spin_lock_bh(&ar->data_lock); |
| 5885 | 5874 | list_for_each_entry_safe(ppdu_stats, tmp, &ar->ppdu_stats_info, list) { |
| 5886 | 5875 | list_del(&ppdu_stats->list); |
| @@ -6051,7 +6040,7 @@ static bool ath11k_mac_vif_ap_active_any(struct ath11k_base *ab) · 164 unmodified lines | ||
| 6051 | 6040 | return false; |
| 6052 | 6041 | } |
| 6053 | 6042 | |
| 6054 | −void ath11k_mac_11d_scan_start(struct ath11k *ar, u32 vdev_id, bool wait) | |
| 6043 | +void ath11k_mac_11d_scan_start(struct ath11k *ar, u32 vdev_id) | |
| 6055 | 6044 | { |
| 6056 | 6045 | struct wmi_11d_scan_start_params param; |
| 6057 | 6046 | int ret; |
| @@ -6079,28 +6068,22 @@ void ath11k_mac_11d_scan_start(struct ath11k *ar, u32 vdev_id, bool wait) · 21 unmodified lines | ||
| 6079 | 6068 | |
| 6080 | 6069 | ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "mac start 11d scan\n"); |
| 6081 | 6070 | |
| 6082 | − if (wait) | |
| 6083 | − reinit_completion(&ar->finish_11d_scan); | |
| 6084 | − | |
| 6085 | 6071 | ret = ath11k_wmi_send_11d_scan_start_cmd(ar, ¶m); |
| 6086 | 6072 | if (ret) { |
| 6087 | 6073 | ath11k_warn(ar->ab, "failed to start 11d scan vdev %d ret: %d\n", |
| 6088 | 6074 | vdev_id, ret); |
| 6089 | 6075 | } else { |
| 6090 | 6076 | ar->vdev_id_11d_scan = vdev_id; |
| 6091 | − if (wait) { | |
| 6092 | − ar->pending_11d = true; | |
| 6093 | − ret = wait_for_completion_timeout(&ar->finish_11d_scan, | |
| 6094 | − 5 * HZ); | |
| 6095 | − ath11k_dbg(ar->ab, ATH11K_DBG_MAC, | |
| 6096 | − "mac 11d scan left time %d\n", ret); | |
| 6097 | − | |
| 6098 | − if (!ret) | |
| 6099 | − ar->pending_11d = false; | |
| 6100 | − } | |
| 6077 | + if (ar->state_11d == ATH11K_11D_PREPARING) | |
| 6078 | + ar->state_11d = ATH11K_11D_RUNNING; | |
| 6101 | 6079 | } |
| 6102 | 6080 | |
| 6103 | 6081 | fin: |
| 6082 | + if (ar->state_11d == ATH11K_11D_PREPARING) { | |
| 6083 | + ar->state_11d = ATH11K_11D_IDLE; | |
| 6084 | + complete(&ar->completed_11d_scan); | |
| 6085 | + } | |
| 6086 | + | |
| 6104 | 6087 | mutex_unlock(&ar->ab->vdev_id_11d_lock); |
| 6105 | 6088 | } |
| 6106 | 6089 | |
| @@ -6123,12 +6106,15 @@ void ath11k_mac_11d_scan_stop(struct ath11k *ar) · 16 unmodified lines | ||
| 6123 | 6106 | vdev_id = ar->vdev_id_11d_scan; |
| 6124 | 6107 | |
| 6125 | 6108 | ret = ath11k_wmi_send_11d_scan_stop_cmd(ar, vdev_id); |
| 6126 | − if (ret) | |
| 6109 | + if (ret) { | |
| 6127 | 6110 | ath11k_warn(ar->ab, |
| 6128 | 6111 | "failed to stopt 11d scan vdev %d ret: %d\n", |
| 6129 | 6112 | vdev_id, ret); |
| 6130 | − else | |
| 6113 | + } else { | |
| 6131 | 6114 | ar->vdev_id_11d_scan = ATH11K_11D_INVALID_VDEV_ID; |
| 6115 | + ar->state_11d = ATH11K_11D_IDLE; | |
| 6116 | + complete(&ar->completed_11d_scan); | |
| 6117 | + } | |
| 6132 | 6118 | } |
| 6133 | 6119 | mutex_unlock(&ar->ab->vdev_id_11d_lock); |
| 6134 | 6120 | } |
| @@ -6324,8 +6310,10 @@ static int ath11k_mac_op_add_interface(struct ieee80211_hw *hw, · 189 unmodified lines | ||
| 6324 | 6310 | goto err_peer_del; |
| 6325 | 6311 | } |
| 6326 | 6312 | |
| 6327 | − ath11k_mac_11d_scan_start(ar, arvif->vdev_id, true); | |
| 6328 | − | |
| 6313 | + if (test_bit(WMI_TLV_SERVICE_11D_OFFLOAD, ab->wmi_ab.svc_map)) { | |
| 6314 | + reinit_completion(&ar->completed_11d_scan); | |
| 6315 | + ar->state_11d = ATH11K_11D_PREPARING; | |
| 6316 | + } | |
| 6329 | 6317 | break; |
| 6330 | 6318 | case WMI_VDEV_TYPE_MONITOR: |
| 6331 | 6319 | set_bit(ATH11K_FLAG_MONITOR_VDEV_CREATED, &ar->monitor_flags); |
| @@ -7190,7 +7178,7 @@ ath11k_mac_op_unassign_vif_chanctx(struct ieee80211_hw *hw, · 858 unmodified lines | ||
| 7190 | 7178 | } |
| 7191 | 7179 | |
| 7192 | 7180 | if (arvif->vdev_type == WMI_VDEV_TYPE_STA) |
| 7193 | − ath11k_mac_11d_scan_start(ar, arvif->vdev_id, false); | |
| 7181 | + ath11k_mac_11d_scan_start(ar, arvif->vdev_id); | |
| 7194 | 7182 | |
| 7195 | 7183 | mutex_unlock(&ar->conf_mutex); |
| 7196 | 7184 | } |
| @@ -8671,8 +8659,7 @@ int ath11k_mac_allocate(struct ath11k_base *ab) · 1474 unmodified lines | ||
| 8671 | 8659 | ar->monitor_vdev_id = -1; |
| 8672 | 8660 | clear_bit(ATH11K_FLAG_MONITOR_VDEV_CREATED, &ar->monitor_flags); |
| 8673 | 8661 | ar->vdev_id_11d_scan = ATH11K_11D_INVALID_VDEV_ID; |
| 8674 | − init_completion(&ar->finish_11d_scan); | |
| 8675 | − init_completion(&ar->finish_11d_ch_list); | |
| 8662 | + init_completion(&ar->completed_11d_scan); | |
| 8676 | 8663 | } |
| 8677 | 8664 | |
| 8678 | 8665 | return 0; |
| @@ -130,7 +130,7 @@ extern const struct htt_rx_ring_tlv_filter ath11k_mac_mon_status_filter_default; · 129 unmodified lines | ||
| 130 | 130 | #define ATH11K_SCAN_11D_INTERVAL 600000 |
| 131 | 131 | #define ATH11K_11D_INVALID_VDEV_ID 0xFFFF |
| 132 | 132 | |
| 133 | −void ath11k_mac_11d_scan_start(struct ath11k *ar, u32 vdev_id, bool wait); | |
| 133 | +void ath11k_mac_11d_scan_start(struct ath11k *ar, u32 vdev_id); | |
| 134 | 134 | void ath11k_mac_11d_scan_stop(struct ath11k *ar); |
| 135 | 135 | void ath11k_mac_11d_scan_stop_all(struct ath11k_base *ab); |
| 136 | 136 | |
| @@ -102,7 +102,7 @@ ath11k_reg_notifier(struct wiphy *wiphy, struct regulatory_request *request) · 101 unmodified lines | ||
| 102 | 102 | ar->regdom_set_by_user = true; |
| 103 | 103 | } |
| 104 | 104 | |
| 105 | −int ath11k_reg_update_chan_list(struct ath11k *ar) | |
| 105 | +int ath11k_reg_update_chan_list(struct ath11k *ar, bool wait) | |
| 106 | 106 | { |
| 107 | 107 | struct ieee80211_supported_band **bands; |
| 108 | 108 | struct scan_chan_list_params *params; |
| @@ -111,7 +111,32 @@ int ath11k_reg_update_chan_list(struct ath11k *ar) · 2 unmodified lines | ||
| 111 | 111 | struct channel_param *ch; |
| 112 | 112 | enum nl80211_band band; |
| 113 | 113 | int num_channels = 0; |
| 114 | − int i, ret; | |
| 114 | + int i, ret, left; | |
| 115 | + | |
| 116 | + if (wait && ar->state_11d != ATH11K_11D_IDLE) { | |
| 117 | + left = wait_for_completion_timeout(&ar->completed_11d_scan, | |
| 118 | + ATH11K_SCAN_TIMEOUT_HZ); | |
| 119 | + if (!left) { | |
| 120 | + ath11k_dbg(ar->ab, ATH11K_DBG_REG, | |
| 121 | + "failed to receive 11d scan complete: timed out\n"); | |
| 122 | + ar->state_11d = ATH11K_11D_IDLE; | |
| 123 | + } | |
| 124 | + ath11k_dbg(ar->ab, ATH11K_DBG_REG, | |
| 125 | + "reg 11d scan wait left time %d\n", left); | |
| 126 | + } | |
| 127 | + | |
| 128 | + if (wait && | |
| 129 | + (ar->scan.state == ATH11K_SCAN_STARTING || | |
| 130 | + ar->scan.state == ATH11K_SCAN_RUNNING)) { | |
| 131 | + left = wait_for_completion_timeout(&ar->scan.completed, | |
| 132 | + ATH11K_SCAN_TIMEOUT_HZ); | |
| 133 | + if (!left) | |
| 134 | + ath11k_dbg(ar->ab, ATH11K_DBG_REG, | |
| 135 | + "failed to receive hw scan complete: timed out\n"); | |
| 136 | + | |
| 137 | + ath11k_dbg(ar->ab, ATH11K_DBG_REG, | |
| 138 | + "reg hw scan wait left time %d\n", left); | |
| 139 | + } | |
| 115 | 140 | |
| 116 | 141 | bands = hw->wiphy->bands; |
| 117 | 142 | for (band = 0; band < NUM_NL80211_BANDS; band++) { |
| @@ -193,11 +218,6 @@ int ath11k_reg_update_chan_list(struct ath11k *ar) · 75 unmodified lines | ||
| 193 | 218 | ret = ath11k_wmi_send_scan_chan_list_cmd(ar, params); |
| 194 | 219 | kfree(params); |
| 195 | 220 | |
| 196 | − if (ar->pending_11d) { | |
| 197 | − complete(&ar->finish_11d_ch_list); | |
| 198 | − ar->pending_11d = false; | |
| 199 | − } | |
| 200 | − | |
| 201 | 221 | return ret; |
| 202 | 222 | } |
| 203 | 223 | |
| @@ -263,15 +283,8 @@ int ath11k_regd_update(struct ath11k *ar) · 59 unmodified lines | ||
| 263 | 283 | goto err; |
| 264 | 284 | } |
| 265 | 285 | |
| 266 | − if (ar->pending_11d) | |
| 267 | − complete(&ar->finish_11d_scan); | |
| 268 | − | |
| 269 | 286 | rtnl_lock(); |
| 270 | 287 | wiphy_lock(ar->hw->wiphy); |
| 271 | − | |
| 272 | − if (ar->pending_11d) | |
| 273 | − reinit_completion(&ar->finish_11d_ch_list); | |
| 274 | − | |
| 275 | 288 | ret = regulatory_set_wiphy_regd_sync(ar->hw->wiphy, regd_copy); |
| 276 | 289 | wiphy_unlock(ar->hw->wiphy); |
| 277 | 290 | rtnl_unlock(); |
| @@ -282,7 +295,7 @@ int ath11k_regd_update(struct ath11k *ar) · 4 unmodified lines | ||
| 282 | 295 | goto err; |
| 283 | 296 | |
| 284 | 297 | if (ar->state == ATH11K_STATE_ON) { |
| 285 | − ret = ath11k_reg_update_chan_list(ar); | |
| 298 | + ret = ath11k_reg_update_chan_list(ar, true); | |
| 286 | 299 | if (ret) |
| 287 | 300 | goto err; |
| 288 | 301 | } |
| @@ -32,5 +32,5 @@ struct ieee80211_regdomain * · 31 unmodified lines | ||
| 32 | 32 | ath11k_reg_build_regd(struct ath11k_base *ab, |
| 33 | 33 | struct cur_regulatory_info *reg_info, bool intersect); |
| 34 | 34 | int ath11k_regd_update(struct ath11k *ar); |
| 35 | −int ath11k_reg_update_chan_list(struct ath11k *ar); | |
| 35 | +int ath11k_reg_update_chan_list(struct ath11k *ar, bool wait); | |
| 36 | 36 | #endif |
| @@ -2015,7 +2015,10 @@ void ath11k_wmi_start_scan_init(struct ath11k *ar, · 2014 unmodified lines | ||
| 2015 | 2015 | { |
| 2016 | 2016 | /* setup commonly used values */ |
| 2017 | 2017 | arg->scan_req_id = 1; |
| 2018 | − arg->scan_priority = WMI_SCAN_PRIORITY_LOW; | |
| 2018 | + if (ar->state_11d == ATH11K_11D_PREPARING) | |
| 2019 | + arg->scan_priority = WMI_SCAN_PRIORITY_MEDIUM; | |
| 2020 | + else | |
| 2021 | + arg->scan_priority = WMI_SCAN_PRIORITY_LOW; | |
| 2019 | 2022 | arg->dwell_time_active = 50; |
| 2020 | 2023 | arg->dwell_time_active_2g = 0; |
| 2021 | 2024 | arg->dwell_time_passive = 150; |
| @@ -6350,8 +6353,10 @@ static void ath11k_wmi_op_ep_tx_credits(struct ath11k_base *ab) · 4328 unmodified lines | ||
| 6350 | 6353 | static int ath11k_reg_11d_new_cc_event(struct ath11k_base *ab, struct sk_buff *skb) |
| 6351 | 6354 | { |
| 6352 | 6355 | const struct wmi_11d_new_cc_ev *ev; |
| 6356 | + struct ath11k *ar; | |
| 6357 | + struct ath11k_pdev *pdev; | |
| 6353 | 6358 | const void **tb; |
| 6354 | − int ret; | |
| 6359 | + int ret, i; | |
| 6355 | 6360 | |
| 6356 | 6361 | tb = ath11k_wmi_tlv_parse_alloc(ab, skb->data, skb->len, GFP_ATOMIC); |
| 6357 | 6362 | if (IS_ERR(tb)) { |
| @@ -6377,6 +6382,13 @@ static int ath11k_reg_11d_new_cc_event(struct ath11k_base *ab, struct sk_buff *s · 19 unmodified lines | ||
| 6377 | 6382 | |
| 6378 | 6383 | kfree(tb); |
| 6379 | 6384 | |
| 6385 | + for (i = 0; i < ab->num_radios; i++) { | |
| 6386 | + pdev = &ab->pdevs[i]; | |
| 6387 | + ar = pdev->ar; | |
| 6388 | + ar->state_11d = ATH11K_11D_IDLE; | |
| 6389 | + complete(&ar->completed_11d_scan); | |
| 6390 | + } | |
| 6391 | + | |
| 6380 | 6392 | queue_work(ab->workqueue, &ab->update_11d_work); |
| 6381 | 6393 | |
| 6382 | 6394 | return 0; |
| @@ -371,7 +371,7 @@ void iwl_dbg_tlv_del_timers(struct iwl_trans *trans) · 370 unmodified lines | ||
| 371 | 371 | struct iwl_dbg_tlv_timer_node *node, *tmp; |
| 372 | 372 | |
| 373 | 373 | list_for_each_entry_safe(node, tmp, timer_list, list) { |
| 374 | − del_timer(&node->timer); | |
| 374 | + del_timer_sync(&node->timer); | |
| 375 | 375 | list_del(&node->list); |
| 376 | 376 | kfree(node); |
| 377 | 377 | } |
| @@ -2202,11 +2202,14 @@ mac80211_hwsim_sta_rc_update(struct ieee80211_hw *hw, · 2201 unmodified lines | ||
| 2202 | 2202 | if (!data->use_chanctx) { |
| 2203 | 2203 | confbw = data->bw; |
| 2204 | 2204 | } else { |
| 2205 | − struct ieee80211_chanctx_conf *chanctx_conf = | |
| 2206 | − rcu_dereference(vif->chanctx_conf); | |
| 2205 | + struct ieee80211_chanctx_conf *chanctx_conf; | |
| 2206 | + | |
| 2207 | + rcu_read_lock(); | |
| 2208 | + chanctx_conf = rcu_dereference(vif->chanctx_conf); | |
| 2207 | 2209 | |
| 2208 | 2210 | if (!WARN_ON(!chanctx_conf)) |
| 2209 | 2211 | confbw = chanctx_conf->def.width; |
| 2212 | + rcu_read_unlock(); | |
| 2210 | 2213 | } |
| 2211 | 2214 | |
| 2212 | 2215 | WARN(bw > hwsim_get_chanwidth(confbw), |
| @@ -2475,11 +2478,13 @@ static void hw_scan_work(struct work_struct *work) · 262 unmodified lines | ||
| 2475 | 2478 | if (req->ie_len) |
| 2476 | 2479 | skb_put_data(probe, req->ie, req->ie_len); |
| 2477 | 2480 | |
| 2481 | + rcu_read_lock(); | |
| 2478 | 2482 | if (!ieee80211_tx_prepare_skb(hwsim->hw, |
| 2479 | 2483 | hwsim->hw_scan_vif, |
| 2480 | 2484 | probe, |
| 2481 | 2485 | hwsim->tmp_chan->band, |
| 2482 | 2486 | NULL)) { |
| 2487 | + rcu_read_unlock(); | |
| 2483 | 2488 | kfree_skb(probe); |
| 2484 | 2489 | continue; |
| 2485 | 2490 | } |
| @@ -2487,6 +2492,7 @@ static void hw_scan_work(struct work_struct *work) · 1 unmodified line | ||
| 2487 | 2492 | local_bh_disable(); |
| 2488 | 2493 | mac80211_hwsim_tx_frame(hwsim->hw, probe, |
| 2489 | 2494 | hwsim->tmp_chan); |
| 2495 | + rcu_read_unlock(); | |
| 2490 | 2496 | local_bh_enable(); |
| 2491 | 2497 | } |
| 2492 | 2498 | } |
| @@ -183,6 +183,7 @@ void nfcmrvl_nci_unregister_dev(struct nfcmrvl_private *priv) · 182 unmodified lines | ||
| 183 | 183 | { |
| 184 | 184 | struct nci_dev *ndev = priv->ndev; |
| 185 | 185 | |
| 186 | + nci_unregister_device(ndev); | |
| 186 | 187 | if (priv->ndev->nfc_dev->fw_download_in_progress) |
| 187 | 188 | nfcmrvl_fw_dnld_abort(priv); |
| 188 | 189 | |
| @@ -191,7 +192,6 @@ void nfcmrvl_nci_unregister_dev(struct nfcmrvl_private *priv) · 2 unmodified lines | ||
| 191 | 192 | if (gpio_is_valid(priv->config.reset_n_io)) |
| 192 | 193 | gpio_free(priv->config.reset_n_io); |
| 193 | 194 | |
| 194 | − nci_unregister_device(ndev); | |
| 195 | 195 | nci_free_device(ndev); |
| 196 | 196 | kfree(priv); |
| 197 | 197 | } |
| @@ -369,7 +369,6 @@ static int devm_of_pci_get_host_bridge_resources(struct device *dev, · 368 unmodified lines | ||
| 369 | 369 | |
| 370 | 370 | dev_dbg(dev, "Parsing dma-ranges property...\n"); |
| 371 | 371 | for_each_of_pci_range(&parser, &range) { |
| 372 | − struct resource_entry *entry; | |
| 373 | 372 | /* |
| 374 | 373 | * If we failed translation or got a zero-sized region |
| 375 | 374 | * then skip this range |
| @@ -393,12 +392,7 @@ static int devm_of_pci_get_host_bridge_resources(struct device *dev, · 17 unmodified lines | ||
| 393 | 392 | goto failed; |
| 394 | 393 | } |
| 395 | 394 | |
| 396 | − /* Keep the resource list sorted */ | |
| 397 | − resource_list_for_each_entry(entry, ib_resources) | |
| 398 | − if (entry->res->start > res->start) | |
| 399 | − break; | |
| 400 | − | |
| 401 | − pci_add_resource_offset(&entry->node, res, | |
| 395 | + pci_add_resource_offset(ib_resources, res, | |
| 402 | 396 | res->start - range.pci_addr); |
| 403 | 397 | } |
| 404 | 398 | |
| @@ -20,6 +20,7 @@ · 19 unmodified lines | ||
| 20 | 20 | #include <linux/of_device.h> |
| 21 | 21 | #include <linux/acpi.h> |
| 22 | 22 | #include <linux/dma-map-ops.h> |
| 23 | +#include <linux/iommu.h> | |
| 23 | 24 | #include "pci.h" |
| 24 | 25 | #include "pcie/portdrv.h" |
| 25 | 26 | |
| @@ -1601,6 +1602,7 @@ static int pci_bus_num_vf(struct device *dev) · 1575 unmodified lines | ||
| 1601 | 1602 | */ |
| 1602 | 1603 | static int pci_dma_configure(struct device *dev) |
| 1603 | 1604 | { |
| 1605 | + struct pci_driver *driver = to_pci_driver(dev->driver); | |
| 1604 | 1606 | struct device *bridge; |
| 1605 | 1607 | int ret = 0; |
| 1606 | 1608 | |
| @@ -1616,9 +1618,24 @@ static int pci_dma_configure(struct device *dev) · 9 unmodified lines | ||
| 1616 | 1618 | } |
| 1617 | 1619 | |
| 1618 | 1620 | pci_put_host_bridge_device(bridge); |
| 1621 | + | |
| 1622 | + if (!ret && !driver->driver_managed_dma) { | |
| 1623 | + ret = iommu_device_use_default_domain(dev); | |
| 1624 | + if (ret) | |
| 1625 | + arch_teardown_dma_ops(dev); | |
| 1626 | + } | |
| 1627 | + | |
| 1619 | 1628 | return ret; |
| 1620 | 1629 | } |
| 1621 | 1630 | |
| 1631 | +static void pci_dma_cleanup(struct device *dev) | |
| 1632 | +{ | |
| 1633 | + struct pci_driver *driver = to_pci_driver(dev->driver); | |
| 1634 | + | |
| 1635 | + if (!driver->driver_managed_dma) | |
| 1636 | + iommu_device_unuse_default_domain(dev); | |
| 1637 | +} | |
| 1638 | + | |
| 1622 | 1639 | struct bus_type pci_bus_type = { |
| 1623 | 1640 | .name = "pci", |
| 1624 | 1641 | .match = pci_bus_match, |
| @@ -1632,6 +1649,7 @@ struct bus_type pci_bus_type = { · 7 unmodified lines | ||
| 1632 | 1649 | .pm = PCI_PM_OPS_PTR, |
| 1633 | 1650 | .num_vf = pci_bus_num_vf, |
| 1634 | 1651 | .dma_configure = pci_dma_configure, |
| 1652 | + .dma_cleanup = pci_dma_cleanup, | |
| 1635 | 1653 | }; |
| 1636 | 1654 | EXPORT_SYMBOL(pci_bus_type); |
| 1637 | 1655 | |
| @@ -36,6 +36,7 @@ static struct pci_driver stub_driver = { · 35 unmodified lines | ||
| 36 | 36 | .name = "pci-stub", |
| 37 | 37 | .id_table = NULL, /* only dynamic id's */ |
| 38 | 38 | .probe = pci_stub_probe, |
| 39 | + .driver_managed_dma = true, | |
| 39 | 40 | }; |
| 40 | 41 | |
| 41 | 42 | static int __init pci_stub_init(void) |
| @@ -202,6 +202,8 @@ static struct pci_driver pcie_portdriver = { · 201 unmodified lines | ||
| 202 | 202 | |
| 203 | 203 | .err_handler = &pcie_portdrv_err_handler, |
| 204 | 204 | |
| 205 | + .driver_managed_dma = true, | |
| 206 | + | |
| 205 | 207 | .driver.pm = PCIE_PORTDRV_PM_OPS, |
| 206 | 208 | }; |
| 207 | 209 | |
| @@ -414,19 +414,19 @@ static int phy_g12a_usb3_pcie_probe(struct platform_device *pdev) · 413 unmodified lines | ||
| 414 | 414 | |
| 415 | 415 | ret = clk_prepare_enable(priv->clk_ref); |
| 416 | 416 | if (ret) |
| 417 | − goto err_disable_clk_ref; | |
| 417 | + return ret; | |
| 418 | 418 | |
| 419 | 419 | priv->reset = devm_reset_control_array_get_exclusive(dev); |
| 420 | − if (IS_ERR(priv->reset)) | |
| 421 | − return PTR_ERR(priv->reset); | |
| 420 | + if (IS_ERR(priv->reset)) { | |
| 421 | + ret = PTR_ERR(priv->reset); | |
| 422 | + goto err_disable_clk_ref; | |
| 423 | + } | |
| 422 | 424 | |
| 423 | 425 | priv->phy = devm_phy_create(dev, np, &phy_g12a_usb3_pcie_ops); |
| 424 | 426 | if (IS_ERR(priv->phy)) { |
| 425 | 427 | ret = PTR_ERR(priv->phy); |
| 426 | − if (ret != -EPROBE_DEFER) | |
| 427 | − dev_err(dev, "failed to create PHY\n"); | |
| 428 | − | |
| 429 | − return ret; | |
| 428 | + dev_err_probe(dev, ret, "failed to create PHY\n"); | |
| 429 | + goto err_disable_clk_ref; | |
| 430 | 430 | } |
| 431 | 431 | |
| 432 | 432 | phy_set_drvdata(priv->phy, priv); |
| @@ -434,8 +434,12 @@ static int phy_g12a_usb3_pcie_probe(struct platform_device *pdev) · 1 unmodified line | ||
| 434 | 434 | |
| 435 | 435 | phy_provider = devm_of_phy_provider_register(dev, |
| 436 | 436 | phy_g12a_usb3_pcie_xlate); |
| 437 | + if (IS_ERR(phy_provider)) { | |
| 438 | + ret = PTR_ERR(phy_provider); | |
| 439 | + goto err_disable_clk_ref; | |
| 440 | + } | |
| 437 | 441 | |
| 438 | − return PTR_ERR_OR_ZERO(phy_provider); | |
| 442 | + return 0; | |
| 439 | 443 | |
| 440 | 444 | err_disable_clk_ref: |
| 441 | 445 | clk_disable_unprepare(priv->clk_ref); |
| @@ -629,7 +629,8 @@ idle: · 628 unmodified lines | ||
| 629 | 629 | cleanup: |
| 630 | 630 | if (error < 0) |
| 631 | 631 | phy_mdm6600_device_power_off(ddata); |
| 632 | − | |
| 632 | + pm_runtime_disable(ddata->dev); | |
| 633 | + pm_runtime_dont_use_autosuspend(ddata->dev); | |
| 633 | 634 | return error; |
| 634 | 635 | } |
| 635 | 636 | |
| @@ -187,6 +187,7 @@ static int exynos_sata_phy_probe(struct platform_device *pdev) · 186 unmodified lines | ||
| 187 | 187 | return -EINVAL; |
| 188 | 188 | |
| 189 | 189 | sata_phy->client = of_find_i2c_device_by_node(node); |
| 190 | + of_node_put(node); | |
| 190 | 191 | if (!sata_phy->client) |
| 191 | 192 | return -EPROBE_DEFER; |
| 192 | 193 | |
| @@ -195,20 +196,21 @@ static int exynos_sata_phy_probe(struct platform_device *pdev) · 2 unmodified lines | ||
| 195 | 196 | sata_phy->phyclk = devm_clk_get(dev, "sata_phyctrl"); |
| 196 | 197 | if (IS_ERR(sata_phy->phyclk)) { |
| 197 | 198 | dev_err(dev, "failed to get clk for PHY\n"); |
| 198 | − return PTR_ERR(sata_phy->phyclk); | |
| 199 | + ret = PTR_ERR(sata_phy->phyclk); | |
| 200 | + goto put_dev; | |
| 199 | 201 | } |
| 200 | 202 | |
| 201 | 203 | ret = clk_prepare_enable(sata_phy->phyclk); |
| 202 | 204 | if (ret < 0) { |
| 203 | 205 | dev_err(dev, "failed to enable source clk\n"); |
| 204 | − return ret; | |
| 206 | + goto put_dev; | |
| 205 | 207 | } |
| 206 | 208 | |
| 207 | 209 | sata_phy->phy = devm_phy_create(dev, NULL, &exynos_sata_phy_ops); |
| 208 | 210 | if (IS_ERR(sata_phy->phy)) { |
| 209 | − clk_disable_unprepare(sata_phy->phyclk); | |
| 210 | 211 | dev_err(dev, "failed to create PHY\n"); |
| 211 | − return PTR_ERR(sata_phy->phy); | |
| 212 | + ret = PTR_ERR(sata_phy->phy); | |
| 213 | + goto clk_disable; | |
| 212 | 214 | } |
| 213 | 215 | |
| 214 | 216 | phy_set_drvdata(sata_phy->phy, sata_phy); |
| @@ -216,11 +218,18 @@ static int exynos_sata_phy_probe(struct platform_device *pdev) · 1 unmodified line | ||
| 216 | 218 | phy_provider = devm_of_phy_provider_register(dev, |
| 217 | 219 | of_phy_simple_xlate); |
| 218 | 220 | if (IS_ERR(phy_provider)) { |
| 219 | − clk_disable_unprepare(sata_phy->phyclk); | |
| 220 | − return PTR_ERR(phy_provider); | |
| 221 | + ret = PTR_ERR(phy_provider); | |
| 222 | + goto clk_disable; | |
| 221 | 223 | } |
| 222 | 224 | |
| 223 | 225 | return 0; |
| 226 | + | |
| 227 | +clk_disable: | |
| 228 | + clk_disable_unprepare(sata_phy->phyclk); | |
| 229 | +put_dev: | |
| 230 | + put_device(&sata_phy->client->dev); | |
| 231 | + | |
| 232 | + return ret; | |
| 224 | 233 | } |
| 225 | 234 | |
| 226 | 235 | static const struct of_device_id exynos_sata_phy_of_match[] = { |
| @@ -838,7 +838,7 @@ static int serdes_am654_probe(struct platform_device *pdev) · 837 unmodified lines | ||
| 838 | 838 | |
| 839 | 839 | clk_err: |
| 840 | 840 | of_clk_del_provider(node); |
| 841 | − | |
| 841 | + pm_runtime_disable(dev); | |
| 842 | 842 | return ret; |
| 843 | 843 | } |
| 844 | 844 | |
| @@ -215,7 +215,7 @@ static int omap_usb2_enable_clocks(struct omap_usb *phy) · 214 unmodified lines | ||
| 215 | 215 | return 0; |
| 216 | 216 | |
| 217 | 217 | err1: |
| 218 | − clk_disable(phy->wkupclk); | |
| 218 | + clk_disable_unprepare(phy->wkupclk); | |
| 219 | 219 | |
| 220 | 220 | err0: |
| 221 | 221 | return ret; |
| @@ -696,6 +696,7 @@ static int ti_pipe3_get_sysctrl(struct ti_pipe3 *phy) · 695 unmodified lines | ||
| 696 | 696 | } |
| 697 | 697 | |
| 698 | 698 | control_pdev = of_find_device_by_node(control_node); |
| 699 | + of_node_put(control_node); | |
| 699 | 700 | if (!control_pdev) { |
| 700 | 701 | dev_err(dev, "Failed to get control device\n"); |
| 701 | 702 | return -EINVAL; |
| @@ -155,7 +155,7 @@ static int tusb1210_set_mode(struct phy *phy, enum phy_mode mode, int submode) · 154 unmodified lines | ||
| 155 | 155 | } |
| 156 | 156 | |
| 157 | 157 | #ifdef CONFIG_POWER_SUPPLY |
| 158 | −const char * const tusb1210_chg_det_states[] = { | |
| 158 | +static const char * const tusb1210_chg_det_states[] = { | |
| 159 | 159 | "CHG_DET_CONNECTING", |
| 160 | 160 | "CHG_DET_START_DET", |
| 161 | 161 | "CHG_DET_READ_DET", |
| @@ -537,12 +537,18 @@ static int tusb1210_probe(struct ulpi *ulpi) · 375 unmodified lines | ||
| 537 | 537 | tusb1210_probe_charger_detect(tusb); |
| 538 | 538 | |
| 539 | 539 | tusb->phy = ulpi_phy_create(ulpi, &phy_ops); |
| 540 | − if (IS_ERR(tusb->phy)) | |
| 541 | − return PTR_ERR(tusb->phy); | |
| 540 | + if (IS_ERR(tusb->phy)) { | |
| 541 | + ret = PTR_ERR(tusb->phy); | |
| 542 | + goto err_remove_charger; | |
| 543 | + } | |
| 542 | 544 | |
| 543 | 545 | phy_set_drvdata(tusb->phy, tusb); |
| 544 | 546 | ulpi_set_drvdata(ulpi, tusb); |
| 545 | 547 | return 0; |
| 548 | + | |
| 549 | +err_remove_charger: | |
| 550 | + tusb1210_remove_charger_detect(tusb); | |
| 551 | + return ret; | |
| 546 | 552 | } |
| 547 | 553 | |
| 548 | 554 | static void tusb1210_remove(struct ulpi *ulpi) |
| @@ -14,11 +14,17 @@ · 13 unmodified lines | ||
| 14 | 14 | |
| 15 | 15 | #include "pinctrl-intel.h" |
| 16 | 16 | |
| 17 | −#define ADL_PAD_OWN 0x0a0 | |
| 18 | −#define ADL_PADCFGLOCK 0x110 | |
| 19 | −#define ADL_HOSTSW_OWN 0x150 | |
| 20 | −#define ADL_GPI_IS 0x200 | |
| 21 | −#define ADL_GPI_IE 0x220 | |
| 17 | +#define ADL_N_PAD_OWN 0x020 | |
| 18 | +#define ADL_N_PADCFGLOCK 0x080 | |
| 19 | +#define ADL_N_HOSTSW_OWN 0x0b0 | |
| 20 | +#define ADL_N_GPI_IS 0x100 | |
| 21 | +#define ADL_N_GPI_IE 0x120 | |
| 22 | + | |
| 23 | +#define ADL_S_PAD_OWN 0x0a0 | |
| 24 | +#define ADL_S_PADCFGLOCK 0x110 | |
| 25 | +#define ADL_S_HOSTSW_OWN 0x150 | |
| 26 | +#define ADL_S_GPI_IS 0x200 | |
| 27 | +#define ADL_S_GPI_IE 0x220 | |
| 22 | 28 | |
| 23 | 29 | #define ADL_GPP(r, s, e, g) \ |
| 24 | 30 | { \ |
| @@ -28,14 +34,28 @@ · 3 unmodified lines | ||
| 28 | 34 | .gpio_base = (g), \ |
| 29 | 35 | } |
| 30 | 36 | |
| 31 | −#define ADL_COMMUNITY(b, s, e, g) \ | |
| 37 | +#define ADL_N_COMMUNITY(b, s, e, g) \ | |
| 38 | + { \ | |
| 39 | + .barno = (b), \ | |
| 40 | + .padown_offset = ADL_N_PAD_OWN, \ | |
| 41 | + .padcfglock_offset = ADL_N_PADCFGLOCK, \ | |
| 42 | + .hostown_offset = ADL_N_HOSTSW_OWN, \ | |
| 43 | + .is_offset = ADL_N_GPI_IS, \ | |
| 44 | + .ie_offset = ADL_N_GPI_IE, \ | |
| 45 | + .pin_base = (s), \ | |
| 46 | + .npins = ((e) - (s) + 1), \ | |
| 47 | + .gpps = (g), \ | |
| 48 | + .ngpps = ARRAY_SIZE(g), \ | |
| 49 | + } | |
| 50 | + | |
| 51 | +#define ADL_S_COMMUNITY(b, s, e, g) \ | |
| 32 | 52 | { \ |
| 33 | 53 | .barno = (b), \ |
| 34 | − .padown_offset = ADL_PAD_OWN, \ | |
| 35 | − .padcfglock_offset = ADL_PADCFGLOCK, \ | |
| 36 | − .hostown_offset = ADL_HOSTSW_OWN, \ | |
| 37 | − .is_offset = ADL_GPI_IS, \ | |
| 38 | − .ie_offset = ADL_GPI_IE, \ | |
| 54 | + .padown_offset = ADL_S_PAD_OWN, \ | |
| 55 | + .padcfglock_offset = ADL_S_PADCFGLOCK, \ | |
| 56 | + .hostown_offset = ADL_S_HOSTSW_OWN, \ | |
| 57 | + .is_offset = ADL_S_GPI_IS, \ | |
| 58 | + .ie_offset = ADL_S_GPI_IE, \ | |
| 39 | 59 | .pin_base = (s), \ |
| 40 | 60 | .npins = ((e) - (s) + 1), \ |
| 41 | 61 | .gpps = (g), \ |
| @@ -342,10 +362,10 @@ static const struct intel_padgroup adln_community5_gpps[] = { · 300 unmodified lines | ||
| 342 | 362 | }; |
| 343 | 363 | |
| 344 | 364 | static const struct intel_community adln_communities[] = { |
| 345 | − ADL_COMMUNITY(0, 0, 66, adln_community0_gpps), | |
| 346 | − ADL_COMMUNITY(1, 67, 168, adln_community1_gpps), | |
| 347 | − ADL_COMMUNITY(2, 169, 248, adln_community4_gpps), | |
| 348 | − ADL_COMMUNITY(3, 249, 256, adln_community5_gpps), | |
| 365 | + ADL_N_COMMUNITY(0, 0, 66, adln_community0_gpps), | |
| 366 | + ADL_N_COMMUNITY(1, 67, 168, adln_community1_gpps), | |
| 367 | + ADL_N_COMMUNITY(2, 169, 248, adln_community4_gpps), | |
| 368 | + ADL_N_COMMUNITY(3, 249, 256, adln_community5_gpps), | |
| 349 | 369 | }; |
| 350 | 370 | |
| 351 | 371 | static const struct intel_pinctrl_soc_data adln_soc_data = { |
| @@ -713,11 +733,11 @@ static const struct intel_padgroup adls_community5_gpps[] = { · 361 unmodified lines | ||
| 713 | 733 | }; |
| 714 | 734 | |
| 715 | 735 | static const struct intel_community adls_communities[] = { |
| 716 | − ADL_COMMUNITY(0, 0, 94, adls_community0_gpps), | |
| 717 | − ADL_COMMUNITY(1, 95, 150, adls_community1_gpps), | |
| 718 | − ADL_COMMUNITY(2, 151, 199, adls_community3_gpps), | |
| 719 | − ADL_COMMUNITY(3, 200, 269, adls_community4_gpps), | |
| 720 | − ADL_COMMUNITY(4, 270, 303, adls_community5_gpps), | |
| 736 | + ADL_S_COMMUNITY(0, 0, 94, adls_community0_gpps), | |
| 737 | + ADL_S_COMMUNITY(1, 95, 150, adls_community1_gpps), | |
| 738 | + ADL_S_COMMUNITY(2, 151, 199, adls_community3_gpps), | |
| 739 | + ADL_S_COMMUNITY(3, 200, 269, adls_community4_gpps), | |
| 740 | + ADL_S_COMMUNITY(4, 270, 303, adls_community5_gpps), | |
| 721 | 741 | }; |
| 722 | 742 | |
| 723 | 743 | static const struct intel_pinctrl_soc_data adls_soc_data = { |
| @@ -30,6 +30,7 @@ config PINCTRL_MTK_MOORE · 29 unmodified lines | ||
| 30 | 30 | select GENERIC_PINMUX_FUNCTIONS |
| 31 | 31 | select GPIOLIB |
| 32 | 32 | select OF_GPIO |
| 33 | + select EINT_MTK | |
| 33 | 34 | select PINCTRL_MTK_V2 |
| 34 | 35 | |
| 35 | 36 | config PINCTRL_MTK_PARIS |
| @@ -1374,10 +1374,10 @@ static int pistachio_gpio_register(struct pistachio_pinctrl *pctl) · 1373 unmodified lines | ||
| 1374 | 1374 | } |
| 1375 | 1375 | |
| 1376 | 1376 | irq = irq_of_parse_and_map(child, 0); |
| 1377 | − if (irq < 0) { | |
| 1378 | − dev_err(pctl->dev, "No IRQ for bank %u: %d\n", i, irq); | |
| 1377 | + if (!irq) { | |
| 1378 | + dev_err(pctl->dev, "No IRQ for bank %u\n", i); | |
| 1379 | 1379 | of_node_put(child); |
| 1380 | − ret = irq; | |
| 1380 | + ret = -EINVAL; | |
| 1381 | 1381 | goto err; |
| 1382 | 1382 | } |
| 1383 | 1383 | |
| @@ -457,95 +457,110 @@ static struct rockchip_mux_recalced_data rk3128_mux_recalced_data[] = { · 456 unmodified lines | ||
| 457 | 457 | |
| 458 | 458 | static struct rockchip_mux_recalced_data rk3308_mux_recalced_data[] = { |
| 459 | 459 | { |
| 460 | + /* gpio1b6_sel */ | |
| 460 | 461 | .num = 1, |
| 461 | 462 | .pin = 14, |
| 462 | 463 | .reg = 0x28, |
| 463 | 464 | .bit = 12, |
| 464 | 465 | .mask = 0xf |
| 465 | 466 | }, { |
| 467 | + /* gpio1b7_sel */ | |
| 466 | 468 | .num = 1, |
| 467 | 469 | .pin = 15, |
| 468 | 470 | .reg = 0x2c, |
| 469 | 471 | .bit = 0, |
| 470 | 472 | .mask = 0x3 |
| 471 | 473 | }, { |
| 474 | + /* gpio1c2_sel */ | |
| 472 | 475 | .num = 1, |
| 473 | 476 | .pin = 18, |
| 474 | 477 | .reg = 0x30, |
| 475 | 478 | .bit = 4, |
| 476 | 479 | .mask = 0xf |
| 477 | 480 | }, { |
| 481 | + /* gpio1c3_sel */ | |
| 478 | 482 | .num = 1, |
| 479 | 483 | .pin = 19, |
| 480 | 484 | .reg = 0x30, |
| 481 | 485 | .bit = 8, |
| 482 | 486 | .mask = 0xf |
| 483 | 487 | }, { |
| 488 | + /* gpio1c4_sel */ | |
| 484 | 489 | .num = 1, |
| 485 | 490 | .pin = 20, |
| 486 | 491 | .reg = 0x30, |
| 487 | 492 | .bit = 12, |
| 488 | 493 | .mask = 0xf |
| 489 | 494 | }, { |
| 495 | + /* gpio1c5_sel */ | |
| 490 | 496 | .num = 1, |
| 491 | 497 | .pin = 21, |
| 492 | 498 | .reg = 0x34, |
| 493 | 499 | .bit = 0, |
| 494 | 500 | .mask = 0xf |
| 495 | 501 | }, { |
| 502 | + /* gpio1c6_sel */ | |
| 496 | 503 | .num = 1, |
| 497 | 504 | .pin = 22, |
| 498 | 505 | .reg = 0x34, |
| 499 | 506 | .bit = 4, |
| 500 | 507 | .mask = 0xf |
| 501 | 508 | }, { |
| 509 | + /* gpio1c7_sel */ | |
| 502 | 510 | .num = 1, |
| 503 | 511 | .pin = 23, |
| 504 | 512 | .reg = 0x34, |
| 505 | 513 | .bit = 8, |
| 506 | 514 | .mask = 0xf |
| 507 | 515 | }, { |
| 508 | − .num = 3, | |
| 509 | − .pin = 12, | |
| 510 | − .reg = 0x68, | |
| 511 | − .bit = 8, | |
| 512 | − .mask = 0xf | |
| 513 | − }, { | |
| 514 | − .num = 3, | |
| 515 | − .pin = 13, | |
| 516 | − .reg = 0x68, | |
| 517 | − .bit = 12, | |
| 518 | − .mask = 0xf | |
| 519 | − }, { | |
| 516 | + /* gpio2a2_sel */ | |
| 520 | 517 | .num = 2, |
| 521 | 518 | .pin = 2, |
| 522 | − .reg = 0x608, | |
| 523 | − .bit = 0, | |
| 524 | − .mask = 0x7 | |
| 519 | + .reg = 0x40, | |
| 520 | + .bit = 4, | |
| 521 | + .mask = 0x3 | |
| 525 | 522 | }, { |
| 523 | + /* gpio2a3_sel */ | |
| 526 | 524 | .num = 2, |
| 527 | 525 | .pin = 3, |
| 528 | − .reg = 0x608, | |
| 529 | − .bit = 4, | |
| 530 | − .mask = 0x7 | |
| 526 | + .reg = 0x40, | |
| 527 | + .bit = 6, | |
| 528 | + .mask = 0x3 | |
| 531 | 529 | }, { |
| 530 | + /* gpio2c0_sel */ | |
| 532 | 531 | .num = 2, |
| 533 | 532 | .pin = 16, |
| 534 | − .reg = 0x610, | |
| 535 | − .bit = 8, | |
| 536 | − .mask = 0x7 | |
| 533 | + .reg = 0x50, | |
| 534 | + .bit = 0, | |
| 535 | + .mask = 0x3 | |
| 537 | 536 | }, { |
| 537 | + /* gpio3b2_sel */ | |
| 538 | 538 | .num = 3, |
| 539 | 539 | .pin = 10, |
| 540 | − .reg = 0x610, | |
| 541 | − .bit = 0, | |
| 542 | − .mask = 0x7 | |
| 540 | + .reg = 0x68, | |
| 541 | + .bit = 4, | |
| 542 | + .mask = 0x3 | |
| 543 | 543 | }, { |
| 544 | + /* gpio3b3_sel */ | |
| 544 | 545 | .num = 3, |
| 545 | 546 | .pin = 11, |
| 546 | − .reg = 0x610, | |
| 547 | − .bit = 4, | |
| 548 | − .mask = 0x7 | |
| 547 | + .reg = 0x68, | |
| 548 | + .bit = 6, | |
| 549 | + .mask = 0x3 | |
| 550 | + }, { | |
| 551 | + /* gpio3b4_sel */ | |
| 552 | + .num = 3, | |
| 553 | + .pin = 12, | |
| 554 | + .reg = 0x68, | |
| 555 | + .bit = 8, | |
| 556 | + .mask = 0xf | |
| 557 | + }, { | |
| 558 | + /* gpio3b5_sel */ | |
| 559 | + .num = 3, | |
| 560 | + .pin = 13, | |
| 561 | + .reg = 0x68, | |
| 562 | + .bit = 12, | |
| 563 | + .mask = 0xf | |
| 549 | 564 | }, |
| 550 | 565 | }; |
| 551 | 566 | |
| @@ -264,14 +264,14 @@ static const struct pinctrl_pin_desc sm6350_pins[] = { · 263 unmodified lines | ||
| 264 | 264 | PINCTRL_PIN(153, "GPIO_153"), |
| 265 | 265 | PINCTRL_PIN(154, "GPIO_154"), |
| 266 | 266 | PINCTRL_PIN(155, "GPIO_155"), |
| 267 | − PINCTRL_PIN(156, "SDC1_RCLK"), | |
| 268 | − PINCTRL_PIN(157, "SDC1_CLK"), | |
| 269 | − PINCTRL_PIN(158, "SDC1_CMD"), | |
| 270 | − PINCTRL_PIN(159, "SDC1_DATA"), | |
| 271 | − PINCTRL_PIN(160, "SDC2_CLK"), | |
| 272 | − PINCTRL_PIN(161, "SDC2_CMD"), | |
| 273 | − PINCTRL_PIN(162, "SDC2_DATA"), | |
| 274 | − PINCTRL_PIN(163, "UFS_RESET"), | |
| 267 | + PINCTRL_PIN(156, "UFS_RESET"), | |
| 268 | + PINCTRL_PIN(157, "SDC1_RCLK"), | |
| 269 | + PINCTRL_PIN(158, "SDC1_CLK"), | |
| 270 | + PINCTRL_PIN(159, "SDC1_CMD"), | |
| 271 | + PINCTRL_PIN(160, "SDC1_DATA"), | |
| 272 | + PINCTRL_PIN(161, "SDC2_CLK"), | |
| 273 | + PINCTRL_PIN(162, "SDC2_CMD"), | |
| 274 | + PINCTRL_PIN(163, "SDC2_DATA"), | |
| 275 | 275 | }; |
| 276 | 276 | |
| 277 | 277 | #define DECLARE_MSM_GPIO_PINS(pin) \ |
| @@ -4,14 +4,13 @@ · 3 unmodified lines | ||
| 4 | 4 | # |
| 5 | 5 | config PINCTRL_SAMSUNG |
| 6 | 6 | bool |
| 7 | − depends on OF_GPIO | |
| 7 | + select GPIOLIB | |
| 8 | 8 | select PINMUX |
| 9 | 9 | select PINCONF |
| 10 | 10 | |
| 11 | 11 | config PINCTRL_EXYNOS |
| 12 | 12 | bool "Pinctrl common driver part for Samsung Exynos SoCs" |
| 13 | − depends on OF_GPIO | |
| 14 | − depends on ARCH_EXYNOS || ARCH_S5PV210 || COMPILE_TEST | |
| 13 | + depends on ARCH_EXYNOS || ARCH_S5PV210 || (COMPILE_TEST && OF) | |
| 15 | 14 | select PINCTRL_SAMSUNG |
| 16 | 15 | select PINCTRL_EXYNOS_ARM if ARM && (ARCH_EXYNOS || ARCH_S5PV210) |
| 17 | 16 | select PINCTRL_EXYNOS_ARM64 if ARM64 && ARCH_EXYNOS |
| @@ -26,12 +25,10 @@ config PINCTRL_EXYNOS_ARM64 · 8 unmodified lines | ||
| 26 | 25 | |
| 27 | 26 | config PINCTRL_S3C24XX |
| 28 | 27 | bool "Samsung S3C24XX SoC pinctrl driver" |
| 29 | − depends on OF_GPIO | |
| 30 | − depends on ARCH_S3C24XX || COMPILE_TEST | |
| 28 | + depends on ARCH_S3C24XX || (COMPILE_TEST && OF) | |
| 31 | 29 | select PINCTRL_SAMSUNG |
| 32 | 30 | |
| 33 | 31 | config PINCTRL_S3C64XX |
| 34 | 32 | bool "Samsung S3C64XX SoC pinctrl driver" |
| 35 | − depends on OF_GPIO | |
| 36 | − depends on ARCH_S3C64XX || COMPILE_TEST | |
| 33 | + depends on ARCH_S3C64XX || (COMPILE_TEST && OF) | |
| 37 | 34 | select PINCTRL_SAMSUNG |
| @@ -770,7 +770,7 @@ static const struct samsung_pin_bank_data fsd_pin_banks2[] __initconst = { · 769 unmodified lines | ||
| 770 | 770 | EXYNOS850_PIN_BANK_EINTN(3, 0x00, "gpq0"), |
| 771 | 771 | }; |
| 772 | 772 | |
| 773 | −const struct samsung_pin_ctrl fsd_pin_ctrl[] __initconst = { | |
| 773 | +static const struct samsung_pin_ctrl fsd_pin_ctrl[] __initconst = { | |
| 774 | 774 | { |
| 775 | 775 | /* pin-controller instance 0 FSYS0 data */ |
| 776 | 776 | .pin_banks = fsd_pin_banks0, |
| @@ -225,6 +225,13 @@ static void stm32_gpio_free(struct gpio_chip *chip, unsigned offset) · 224 unmodified lines | ||
| 225 | 225 | pinctrl_gpio_free(chip->base + offset); |
| 226 | 226 | } |
| 227 | 227 | |
| 228 | +static int stm32_gpio_get_noclk(struct gpio_chip *chip, unsigned int offset) | |
| 229 | +{ | |
| 230 | + struct stm32_gpio_bank *bank = gpiochip_get_data(chip); | |
| 231 | + | |
| 232 | + return !!(readl_relaxed(bank->base + STM32_GPIO_IDR) & BIT(offset)); | |
| 233 | +} | |
| 234 | + | |
| 228 | 235 | static int stm32_gpio_get(struct gpio_chip *chip, unsigned offset) |
| 229 | 236 | { |
| 230 | 237 | struct stm32_gpio_bank *bank = gpiochip_get_data(chip); |
| @@ -232,7 +239,7 @@ static int stm32_gpio_get(struct gpio_chip *chip, unsigned offset) · 1 unmodified line | ||
| 232 | 239 | |
| 233 | 240 | clk_enable(bank->clk); |
| 234 | 241 | |
| 235 | − ret = !!(readl_relaxed(bank->base + STM32_GPIO_IDR) & BIT(offset)); | |
| 242 | + ret = stm32_gpio_get_noclk(chip, offset); | |
| 236 | 243 | |
| 237 | 244 | clk_disable(bank->clk); |
| 238 | 245 | |
| @@ -311,8 +318,12 @@ static void stm32_gpio_irq_trigger(struct irq_data *d) · 72 unmodified lines | ||
| 311 | 318 | struct stm32_gpio_bank *bank = d->domain->host_data; |
| 312 | 319 | int level; |
| 313 | 320 | |
| 321 | + /* Do not access the GPIO if this is not LEVEL triggered IRQ. */ | |
| 322 | + if (!(bank->irq_type[d->hwirq] & IRQ_TYPE_LEVEL_MASK)) | |
| 323 | + return; | |
| 324 | + | |
| 314 | 325 | /* If level interrupt type then retrig */ |
| 315 | − level = stm32_gpio_get(&bank->gpio_chip, d->hwirq); | |
| 326 | + level = stm32_gpio_get_noclk(&bank->gpio_chip, d->hwirq); | |
| 316 | 327 | if ((level == 0 && bank->irq_type[d->hwirq] == IRQ_TYPE_LEVEL_LOW) || |
| 317 | 328 | (level == 1 && bank->irq_type[d->hwirq] == IRQ_TYPE_LEVEL_HIGH)) |
| 318 | 329 | irq_chip_retrigger_hierarchy(d); |
| @@ -354,6 +365,7 @@ static int stm32_gpio_irq_request_resources(struct irq_data *irq_data) · 35 unmodified lines | ||
| 354 | 365 | { |
| 355 | 366 | struct stm32_gpio_bank *bank = irq_data->domain->host_data; |
| 356 | 367 | struct stm32_pinctrl *pctl = dev_get_drvdata(bank->gpio_chip.parent); |
| 368 | + unsigned long flags; | |
| 357 | 369 | int ret; |
| 358 | 370 | |
| 359 | 371 | ret = stm32_gpio_direction_input(&bank->gpio_chip, irq_data->hwirq); |
| @@ -367,6 +379,10 @@ static int stm32_gpio_irq_request_resources(struct irq_data *irq_data) · 7 unmodified lines | ||
| 367 | 379 | return ret; |
| 368 | 380 | } |
| 369 | 381 | |
| 382 | + flags = irqd_get_trigger_type(irq_data); | |
| 383 | + if (flags & IRQ_TYPE_LEVEL_MASK) | |
| 384 | + clk_enable(bank->clk); | |
| 385 | + | |
| 370 | 386 | return 0; |
| 371 | 387 | } |
| 372 | 388 | |
| @@ -374,6 +390,9 @@ static void stm32_gpio_irq_release_resources(struct irq_data *irq_data) · 1 unmodified line | ||
| 374 | 390 | { |
| 375 | 391 | struct stm32_gpio_bank *bank = irq_data->domain->host_data; |
| 376 | 392 | |
| 393 | + if (bank->irq_type[irq_data->hwirq] & IRQ_TYPE_LEVEL_MASK) | |
| 394 | + clk_disable(bank->clk); | |
| 395 | + | |
| 377 | 396 | gpiochip_unlock_as_irq(&bank->gpio_chip, irq_data->hwirq); |
| 378 | 397 | } |
| 379 | 398 | |
| @@ -419,7 +419,15 @@ static const struct sppctl_grp sp7021grps_prbp[] = { · 418 unmodified lines | ||
| 419 | 419 | EGRP("PROBE_PORT2", 2, pins_prp2), |
| 420 | 420 | }; |
| 421 | 421 | |
| 422 | +/* | |
| 423 | + * Due to compatible reason, the first valid item should start at the third | |
| 424 | + * position of the array. Please keep the first two items of the table | |
| 425 | + * no use (dummy). | |
| 426 | + */ | |
| 422 | 427 | const struct sppctl_func sppctl_list_funcs[] = { |
| 428 | + FNCN("", pinmux_type_fpmx, 0x00, 0, 0), | |
| 429 | + FNCN("", pinmux_type_fpmx, 0x00, 0, 0), | |
| 430 | + | |
| 423 | 431 | FNCN("L2SW_CLK_OUT", pinmux_type_fpmx, 0x00, 0, 7), |
| 424 | 432 | FNCN("L2SW_MAC_SMI_MDC", pinmux_type_fpmx, 0x00, 8, 7), |
| 425 | 433 | FNCN("L2SW_LED_FLASH0", pinmux_type_fpmx, 0x01, 0, 7), |
| @@ -817,7 +817,7 @@ err_cpkg: · 816 unmodified lines | ||
| 817 | 817 | err_bus: |
| 818 | 818 | return status; |
| 819 | 819 | } |
| 820 | −module_init(ssam_core_init); | |
| 820 | +subsys_initcall(ssam_core_init); | |
| 821 | 821 | |
| 822 | 822 | static void __exit ssam_core_exit(void) |
| 823 | 823 | { |
| @@ -99,6 +99,14 @@ static const struct dmi_system_id dmi_lid_device_table[] = { · 98 unmodified lines | ||
| 99 | 99 | }, |
| 100 | 100 | .driver_data = (void *)lid_device_props_l4D, |
| 101 | 101 | }, |
| 102 | + { | |
| 103 | + .ident = "Surface Pro 8", | |
| 104 | + .matches = { | |
| 105 | + DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Microsoft Corporation"), | |
| 106 | + DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "Surface Pro 8"), | |
| 107 | + }, | |
| 108 | + .driver_data = (void *)lid_device_props_l4B, | |
| 109 | + }, | |
| 102 | 110 | { |
| 103 | 111 | .ident = "Surface Book 1", |
| 104 | 112 | .matches = { |
| @@ -371,10 +371,14 @@ static int asus_wmi_evaluate_method_buf(u32 method_id, · 370 unmodified lines | ||
| 371 | 371 | |
| 372 | 372 | switch (obj->type) { |
| 373 | 373 | case ACPI_TYPE_BUFFER: |
| 374 | − if (obj->buffer.length > size) | |
| 374 | + if (obj->buffer.length > size) { | |
| 375 | 375 | err = -ENOSPC; |
| 376 | − if (obj->buffer.length == 0) | |
| 376 | + break; | |
| 377 | + } | |
| 378 | + if (obj->buffer.length == 0) { | |
| 377 | 379 | err = -ENODATA; |
| 380 | + break; | |
| 381 | + } | |
| 378 | 382 | |
| 379 | 383 | memcpy(ret_buffer, obj->buffer.pointer, obj->buffer.length); |
| 380 | 384 | break; |
| @@ -2223,9 +2227,10 @@ static int fan_curve_check_present(struct asus_wmi *asus, bool *available, · 1842 unmodified lines | ||
| 2223 | 2227 | |
| 2224 | 2228 | err = fan_curve_get_factory_default(asus, fan_dev); |
| 2225 | 2229 | if (err) { |
| 2226 | − if (err == -ENODEV || err == -ENODATA) | |
| 2227 | − return 0; | |
| 2228 | − return err; | |
| 2230 | + pr_debug("fan_curve_get_factory_default(0x%08x) failed: %d\n", | |
| 2231 | + fan_dev, err); | |
| 2232 | + /* Don't cause probe to fail on devices without fan-curves */ | |
| 2233 | + return 0; | |
| 2229 | 2234 | } |
| 2230 | 2235 | |
| 2231 | 2236 | *available = true; |
| @@ -80,6 +80,10 @@ static struct quirk_entry quirk_dell_inspiron_1012 = { · 79 unmodified lines | ||
| 80 | 80 | .kbd_led_not_present = true, |
| 81 | 81 | }; |
| 82 | 82 | |
| 83 | +static struct quirk_entry quirk_dell_latitude_7520 = { | |
| 84 | + .kbd_missing_ac_tag = true, | |
| 85 | +}; | |
| 86 | + | |
| 83 | 87 | static struct platform_driver platform_driver = { |
| 84 | 88 | .driver = { |
| 85 | 89 | .name = "dell-laptop", |
| @@ -336,6 +340,15 @@ static const struct dmi_system_id dell_quirks[] __initconst = { · 250 unmodified lines | ||
| 336 | 340 | }, |
| 337 | 341 | .driver_data = &quirk_dell_inspiron_1012, |
| 338 | 342 | }, |
| 343 | + { | |
| 344 | + .callback = dmi_matched, | |
| 345 | + .ident = "Dell Latitude 7520", | |
| 346 | + .matches = { | |
| 347 | + DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), | |
| 348 | + DMI_MATCH(DMI_PRODUCT_NAME, "Latitude 7520"), | |
| 349 | + }, | |
| 350 | + .driver_data = &quirk_dell_latitude_7520, | |
| 351 | + }, | |
| 339 | 352 | { } |
| 340 | 353 | }; |
| 341 | 354 | |
| @@ -148,6 +148,7 @@ static const struct dmi_system_id gigabyte_wmi_known_working_platforms[] = { · 147 unmodified lines | ||
| 148 | 148 | DMI_EXACT_MATCH_GIGABYTE_BOARD_NAME("B550I AORUS PRO AX"), |
| 149 | 149 | DMI_EXACT_MATCH_GIGABYTE_BOARD_NAME("B550M AORUS PRO-P"), |
| 150 | 150 | DMI_EXACT_MATCH_GIGABYTE_BOARD_NAME("B550M DS3H"), |
| 151 | + DMI_EXACT_MATCH_GIGABYTE_BOARD_NAME("B660 GAMING X DDR4"), | |
| 151 | 152 | DMI_EXACT_MATCH_GIGABYTE_BOARD_NAME("Z390 I AORUS PRO WIFI-CF"), |
| 152 | 153 | DMI_EXACT_MATCH_GIGABYTE_BOARD_NAME("X570 AORUS ELITE"), |
| 153 | 154 | DMI_EXACT_MATCH_GIGABYTE_BOARD_NAME("X570 GAMING X"), |
| @@ -236,7 +236,7 @@ enum ppfear_regs { · 235 unmodified lines | ||
| 236 | 236 | #define ADL_LPM_STATUS_LATCH_EN_OFFSET 0x1704 |
| 237 | 237 | #define ADL_LPM_LIVE_STATUS_OFFSET 0x1764 |
| 238 | 238 | |
| 239 | −const char *pmc_lpm_modes[] = { | |
| 239 | +static const char *pmc_lpm_modes[] = { | |
| 240 | 240 | "S0i2.0", |
| 241 | 241 | "S0i2.1", |
| 242 | 242 | "S0i2.2", |
| @@ -103,7 +103,7 @@ static int pmt_telem_probe(struct auxiliary_device *auxdev, const struct auxilia · 102 unmodified lines | ||
| 103 | 103 | auxiliary_set_drvdata(auxdev, priv); |
| 104 | 104 | |
| 105 | 105 | for (i = 0; i < intel_vsec_dev->num_resources; i++) { |
| 106 | − struct intel_pmt_entry *entry = &priv->entry[i]; | |
| 106 | + struct intel_pmt_entry *entry = &priv->entry[priv->num_entries]; | |
| 107 | 107 | |
| 108 | 108 | ret = intel_pmt_dev_create(entry, &pmt_telem_ns, intel_vsec_dev, i); |
| 109 | 109 | if (ret < 0) |
| @@ -51,6 +51,8 @@ · 50 unmodified lines | ||
| 51 | 51 | #define MBOX_TIMEOUT_US 2000 |
| 52 | 52 | #define MBOX_TIMEOUT_ACQUIRE_US 1000 |
| 53 | 53 | #define MBOX_POLLING_PERIOD_US 100 |
| 54 | +#define MBOX_ACQUIRE_NUM_RETRIES 5 | |
| 55 | +#define MBOX_ACQUIRE_RETRY_DELAY_MS 500 | |
| 54 | 56 | #define MBOX_MAX_PACKETS 4 |
| 55 | 57 | |
| 56 | 58 | #define MBOX_OWNER_NONE 0x00 |
| @@ -81,7 +83,7 @@ enum sdsi_command { · 24 unmodified lines | ||
| 81 | 83 | |
| 82 | 84 | struct sdsi_mbox_info { |
| 83 | 85 | u64 *payload; |
| 84 | − u64 *buffer; | |
| 86 | + void *buffer; | |
| 85 | 87 | int size; |
| 86 | 88 | }; |
| 87 | 89 | |
| @@ -163,9 +165,7 @@ static int sdsi_mbox_cmd_read(struct sdsi_priv *priv, struct sdsi_mbox_info *inf · 75 unmodified lines | ||
| 163 | 165 | total = 0; |
| 164 | 166 | loop = 0; |
| 165 | 167 | do { |
| 166 | − int offset = SDSI_SIZE_MAILBOX * loop; | |
| 167 | − void __iomem *addr = priv->mbox_addr + offset; | |
| 168 | − u64 *buf = info->buffer + offset / SDSI_SIZE_CMD; | |
| 168 | + void *buf = info->buffer + (SDSI_SIZE_MAILBOX * loop); | |
| 169 | 169 | u32 packet_size; |
| 170 | 170 | |
| 171 | 171 | /* Poll on ready bit */ |
| @@ -196,7 +196,7 @@ static int sdsi_mbox_cmd_read(struct sdsi_priv *priv, struct sdsi_mbox_info *inf · 24 unmodified lines | ||
| 196 | 196 | break; |
| 197 | 197 | } |
| 198 | 198 | |
| 199 | − sdsi_memcpy64_fromio(buf, addr, round_up(packet_size, SDSI_SIZE_CMD)); | |
| 199 | + sdsi_memcpy64_fromio(buf, priv->mbox_addr, round_up(packet_size, SDSI_SIZE_CMD)); | |
| 200 | 200 | |
| 201 | 201 | total += packet_size; |
| 202 | 202 | |
| @@ -243,8 +243,8 @@ static int sdsi_mbox_cmd_write(struct sdsi_priv *priv, struct sdsi_mbox_info *in · 40 unmodified lines | ||
| 243 | 243 | FIELD_PREP(CTRL_PACKET_SIZE, info->size); |
| 244 | 244 | writeq(control, priv->control_addr); |
| 245 | 245 | |
| 246 | − /* Poll on run_busy bit */ | |
| 247 | − ret = readq_poll_timeout(priv->control_addr, control, !(control & CTRL_RUN_BUSY), | |
| 246 | + /* Poll on ready bit */ | |
| 247 | + ret = readq_poll_timeout(priv->control_addr, control, control & CTRL_READY, | |
| 248 | 248 | MBOX_POLLING_PERIOD_US, MBOX_TIMEOUT_US); |
| 249 | 249 | |
| 250 | 250 | if (ret) |
| @@ -263,7 +263,7 @@ static int sdsi_mbox_acquire(struct sdsi_priv *priv, struct sdsi_mbox_info *info · 12 unmodified lines | ||
| 263 | 263 | { |
| 264 | 264 | u64 control; |
| 265 | 265 | u32 owner; |
| 266 | − int ret; | |
| 266 | + int ret, retries = 0; | |
| 267 | 267 | |
| 268 | 268 | lockdep_assert_held(&priv->mb_lock); |
| 269 | 269 | |
| @@ -273,13 +273,29 @@ static int sdsi_mbox_acquire(struct sdsi_priv *priv, struct sdsi_mbox_info *info · 3 unmodified lines | ||
| 273 | 273 | if (owner != MBOX_OWNER_NONE) |
| 274 | 274 | return -EBUSY; |
| 275 | 275 | |
| 276 | − /* Write first qword of payload */ | |
| 277 | − writeq(info->payload[0], priv->mbox_addr); | |
| 276 | + /* | |
| 277 | + * If there has been no recent transaction and no one owns the mailbox, | |
| 278 | + * we should acquire it in under 1ms. However, if we've accessed it | |
| 279 | + * recently it may take up to 2.1 seconds to acquire it again. | |
| 280 | + */ | |
| 281 | + do { | |
| 282 | + /* Write first qword of payload */ | |
| 283 | + writeq(info->payload[0], priv->mbox_addr); | |
| 284 | + | |
| 285 | + /* Check for ownership */ | |
| 286 | + ret = readq_poll_timeout(priv->control_addr, control, | |
| 287 | + FIELD_GET(CTRL_OWNER, control) == MBOX_OWNER_INBAND, | |
| 288 | + MBOX_POLLING_PERIOD_US, MBOX_TIMEOUT_ACQUIRE_US); | |
| 289 | + | |
| 290 | + if (FIELD_GET(CTRL_OWNER, control) == MBOX_OWNER_NONE && | |
| 291 | + retries++ < MBOX_ACQUIRE_NUM_RETRIES) { | |
| 292 | + msleep(MBOX_ACQUIRE_RETRY_DELAY_MS); | |
| 293 | + continue; | |
| 294 | + } | |
| 278 | 295 | |
| 279 | − /* Check for ownership */ | |
| 280 | − ret = readq_poll_timeout(priv->control_addr, control, | |
| 281 | − FIELD_GET(CTRL_OWNER, control) & MBOX_OWNER_INBAND, | |
| 282 | − MBOX_POLLING_PERIOD_US, MBOX_TIMEOUT_ACQUIRE_US); | |
| 296 | + /* Either we got it or someone else did. */ | |
| 297 | + break; | |
| 298 | + } while (true); | |
| 283 | 299 | |
| 284 | 300 | return ret; |
| 285 | 301 | } |
| @@ -212,6 +212,9 @@ static int __init intel_uncore_init(void) · 211 unmodified lines | ||
| 212 | 212 | const struct x86_cpu_id *id; |
| 213 | 213 | int ret; |
| 214 | 214 | |
| 215 | + if (cpu_feature_enabled(X86_FEATURE_HYPERVISOR)) | |
| 216 | + return -ENODEV; | |
| 217 | + | |
| 215 | 218 | id = x86_match_cpu(intel_uncore_cpu_ids); |
| 216 | 219 | if (!id) |
| 217 | 220 | return -ENODEV; |
| @@ -309,6 +309,20 @@ struct ibm_init_struct { · 308 unmodified lines | ||
| 309 | 309 | struct ibm_struct *data; |
| 310 | 310 | }; |
| 311 | 311 | |
| 312 | +/* DMI Quirks */ | |
| 313 | +struct quirk_entry { | |
| 314 | + bool btusb_bug; | |
| 315 | + u32 s2idle_bug_mmio; | |
| 316 | +}; | |
| 317 | + | |
| 318 | +static struct quirk_entry quirk_btusb_bug = { | |
| 319 | + .btusb_bug = true, | |
| 320 | +}; | |
| 321 | + | |
| 322 | +static struct quirk_entry quirk_s2idle_bug = { | |
| 323 | + .s2idle_bug_mmio = 0xfed80380, | |
| 324 | +}; | |
| 325 | + | |
| 312 | 326 | static struct { |
| 313 | 327 | u32 bluetooth:1; |
| 314 | 328 | u32 hotkey:1; |
| @@ -338,6 +352,7 @@ static struct { · 23 unmodified lines | ||
| 338 | 352 | u32 hotkey_poll_active:1; |
| 339 | 353 | u32 has_adaptive_kbd:1; |
| 340 | 354 | u32 kbd_lang:1; |
| 355 | + struct quirk_entry *quirks; | |
| 341 | 356 | } tp_features; |
| 342 | 357 | |
| 343 | 358 | static struct { |
| @@ -4359,9 +4374,10 @@ static void bluetooth_exit(void) · 4015 unmodified lines | ||
| 4359 | 4374 | bluetooth_shutdown(); |
| 4360 | 4375 | } |
| 4361 | 4376 | |
| 4362 | −static const struct dmi_system_id bt_fwbug_list[] __initconst = { | |
| 4377 | +static const struct dmi_system_id fwbug_list[] __initconst = { | |
| 4363 | 4378 | { |
| 4364 | 4379 | .ident = "ThinkPad E485", |
| 4380 | + .driver_data = &quirk_btusb_bug, | |
| 4365 | 4381 | .matches = { |
| 4366 | 4382 | DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), |
| 4367 | 4383 | DMI_MATCH(DMI_BOARD_NAME, "20KU"), |
| @@ -4369,6 +4385,7 @@ static const struct dmi_system_id bt_fwbug_list[] __initconst = { · 1 unmodified line | ||
| 4369 | 4385 | }, |
| 4370 | 4386 | { |
| 4371 | 4387 | .ident = "ThinkPad E585", |
| 4388 | + .driver_data = &quirk_btusb_bug, | |
| 4372 | 4389 | .matches = { |
| 4373 | 4390 | DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), |
| 4374 | 4391 | DMI_MATCH(DMI_BOARD_NAME, "20KV"), |
| @@ -4376,6 +4393,7 @@ static const struct dmi_system_id bt_fwbug_list[] __initconst = { · 1 unmodified line | ||
| 4376 | 4393 | }, |
| 4377 | 4394 | { |
| 4378 | 4395 | .ident = "ThinkPad A285 - 20MW", |
| 4396 | + .driver_data = &quirk_btusb_bug, | |
| 4379 | 4397 | .matches = { |
| 4380 | 4398 | DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), |
| 4381 | 4399 | DMI_MATCH(DMI_BOARD_NAME, "20MW"), |
| @@ -4383,6 +4401,7 @@ static const struct dmi_system_id bt_fwbug_list[] __initconst = { · 1 unmodified line | ||
| 4383 | 4401 | }, |
| 4384 | 4402 | { |
| 4385 | 4403 | .ident = "ThinkPad A285 - 20MX", |
| 4404 | + .driver_data = &quirk_btusb_bug, | |
| 4386 | 4405 | .matches = { |
| 4387 | 4406 | DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), |
| 4388 | 4407 | DMI_MATCH(DMI_BOARD_NAME, "20MX"), |
| @@ -4390,6 +4409,7 @@ static const struct dmi_system_id bt_fwbug_list[] __initconst = { · 1 unmodified line | ||
| 4390 | 4409 | }, |
| 4391 | 4410 | { |
| 4392 | 4411 | .ident = "ThinkPad A485 - 20MU", |
| 4412 | + .driver_data = &quirk_btusb_bug, | |
| 4393 | 4413 | .matches = { |
| 4394 | 4414 | DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), |
| 4395 | 4415 | DMI_MATCH(DMI_BOARD_NAME, "20MU"), |
| @@ -4397,14 +4417,125 @@ static const struct dmi_system_id bt_fwbug_list[] __initconst = { · 1 unmodified line | ||
| 4397 | 4417 | }, |
| 4398 | 4418 | { |
| 4399 | 4419 | .ident = "ThinkPad A485 - 20MV", |
| 4420 | + .driver_data = &quirk_btusb_bug, | |
| 4400 | 4421 | .matches = { |
| 4401 | 4422 | DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), |
| 4402 | 4423 | DMI_MATCH(DMI_BOARD_NAME, "20MV"), |
| 4403 | 4424 | }, |
| 4404 | 4425 | }, |
| 4426 | + { | |
| 4427 | + .ident = "L14 Gen2 AMD", | |
| 4428 | + .driver_data = &quirk_s2idle_bug, | |
| 4429 | + .matches = { | |
| 4430 | + DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"), | |
| 4431 | + DMI_MATCH(DMI_PRODUCT_NAME, "20X5"), | |
| 4432 | + } | |
| 4433 | + }, | |
| 4434 | + { | |
| 4435 | + .ident = "T14s Gen2 AMD", | |
| 4436 | + .driver_data = &quirk_s2idle_bug, | |
| 4437 | + .matches = { | |
| 4438 | + DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"), | |
| 4439 | + DMI_MATCH(DMI_PRODUCT_NAME, "20XF"), | |
| 4440 | + } | |
| 4441 | + }, | |
| 4442 | + { | |
| 4443 | + .ident = "X13 Gen2 AMD", | |
| 4444 | + .driver_data = &quirk_s2idle_bug, | |
| 4445 | + .matches = { | |
| 4446 | + DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"), | |
| 4447 | + DMI_MATCH(DMI_PRODUCT_NAME, "20XH"), | |
| 4448 | + } | |
| 4449 | + }, | |
| 4450 | + { | |
| 4451 | + .ident = "T14 Gen2 AMD", | |
| 4452 | + .driver_data = &quirk_s2idle_bug, | |
| 4453 | + .matches = { | |
| 4454 | + DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"), | |
| 4455 | + DMI_MATCH(DMI_PRODUCT_NAME, "20XK"), | |
| 4456 | + } | |
| 4457 | + }, | |
| 4458 | + { | |
| 4459 | + .ident = "T14 Gen1 AMD", | |
| 4460 | + .driver_data = &quirk_s2idle_bug, | |
| 4461 | + .matches = { | |
| 4462 | + DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"), | |
| 4463 | + DMI_MATCH(DMI_PRODUCT_NAME, "20UD"), | |
| 4464 | + } | |
| 4465 | + }, | |
| 4466 | + { | |
| 4467 | + .ident = "T14 Gen1 AMD", | |
| 4468 | + .driver_data = &quirk_s2idle_bug, | |
| 4469 | + .matches = { | |
| 4470 | + DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"), | |
| 4471 | + DMI_MATCH(DMI_PRODUCT_NAME, "20UE"), | |
| 4472 | + } | |
| 4473 | + }, | |
| 4474 | + { | |
| 4475 | + .ident = "T14s Gen1 AMD", | |
| 4476 | + .driver_data = &quirk_s2idle_bug, | |
| 4477 | + .matches = { | |
| 4478 | + DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"), | |
| 4479 | + DMI_MATCH(DMI_PRODUCT_NAME, "20UH"), | |
| 4480 | + } | |
| 4481 | + }, | |
| 4482 | + { | |
| 4483 | + .ident = "P14s Gen1 AMD", | |
| 4484 | + .driver_data = &quirk_s2idle_bug, | |
| 4485 | + .matches = { | |
| 4486 | + DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"), | |
| 4487 | + DMI_MATCH(DMI_PRODUCT_NAME, "20Y1"), | |
| 4488 | + } | |
| 4489 | + }, | |
| 4490 | + { | |
| 4491 | + .ident = "P14s Gen2 AMD", | |
| 4492 | + .driver_data = &quirk_s2idle_bug, | |
| 4493 | + .matches = { | |
| 4494 | + DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"), | |
| 4495 | + DMI_MATCH(DMI_PRODUCT_NAME, "21A0"), | |
| 4496 | + } | |
| 4497 | + }, | |
| 4405 | 4498 | {} |
| 4406 | 4499 | }; |
| 4407 | 4500 | |
| 4501 | +#ifdef CONFIG_SUSPEND | |
| 4502 | +/* | |
| 4503 | + * Lenovo laptops from a variety of generations run a SMI handler during the D3->D0 | |
| 4504 | + * transition that occurs specifically when exiting suspend to idle which can cause | |
| 4505 | + * large delays during resume when the IOMMU translation layer is enabled (the default | |
| 4506 | + * behavior) for NVME devices: | |
| 4507 | + * | |
| 4508 | + * To avoid this firmware problem, skip the SMI handler on these machines before the | |
| 4509 | + * D0 transition occurs. | |
| 4510 | + */ | |
| 4511 | +static void thinkpad_acpi_amd_s2idle_restore(void) | |
| 4512 | +{ | |
| 4513 | + struct resource *res; | |
| 4514 | + void __iomem *addr; | |
| 4515 | + u8 val; | |
| 4516 | + | |
| 4517 | + res = request_mem_region_muxed(tp_features.quirks->s2idle_bug_mmio, 1, | |
| 4518 | + "thinkpad_acpi_pm80"); | |
| 4519 | + if (!res) | |
| 4520 | + return; | |
| 4521 | + | |
| 4522 | + addr = ioremap(tp_features.quirks->s2idle_bug_mmio, 1); | |
| 4523 | + if (!addr) | |
| 4524 | + goto cleanup_resource; | |
| 4525 | + | |
| 4526 | + val = ioread8(addr); | |
| 4527 | + iowrite8(val & ~BIT(0), addr); | |
| 4528 | + | |
| 4529 | + iounmap(addr); | |
| 4530 | +cleanup_resource: | |
| 4531 | + release_resource(res); | |
| 4532 | +} | |
| 4533 | + | |
| 4534 | +static struct acpi_s2idle_dev_ops thinkpad_acpi_s2idle_dev_ops = { | |
| 4535 | + .restore = thinkpad_acpi_amd_s2idle_restore, | |
| 4536 | +}; | |
| 4537 | +#endif | |
| 4538 | + | |
| 4408 | 4539 | static const struct pci_device_id fwbug_cards_ids[] __initconst = { |
| 4409 | 4540 | { PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x24F3) }, |
| 4410 | 4541 | { PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x24FD) }, |
| @@ -4419,7 +4550,8 @@ static int __init have_bt_fwbug(void) · 8 unmodified lines | ||
| 4419 | 4550 | * Some AMD based ThinkPads have a firmware bug that calling |
| 4420 | 4551 | * "GBDC" will cause bluetooth on Intel wireless cards blocked |
| 4421 | 4552 | */ |
| 4422 | − if (dmi_check_system(bt_fwbug_list) && pci_dev_present(fwbug_cards_ids)) { | |
| 4553 | + if (tp_features.quirks && tp_features.quirks->btusb_bug && | |
| 4554 | + pci_dev_present(fwbug_cards_ids)) { | |
| 4423 | 4555 | vdbg_printk(TPACPI_DBG_INIT | TPACPI_DBG_RFKILL, |
| 4424 | 4556 | FW_BUG "disable bluetooth subdriver for Intel cards\n"); |
| 4425 | 4557 | return 1; |
| @@ -8748,24 +8880,27 @@ static int __init fan_init(struct ibm_init_struct *iibm) · 4322 unmodified lines | ||
| 8748 | 8880 | fan_status_access_mode = TPACPI_FAN_RD_TPEC; |
| 8749 | 8881 | if (quirks & TPACPI_FAN_Q1) |
| 8750 | 8882 | fan_quirk1_setup(); |
| 8751 | − if (quirks & TPACPI_FAN_2FAN) { | |
| 8752 | − tp_features.second_fan = 1; | |
| 8753 | − pr_info("secondary fan support enabled\n"); | |
| 8754 | − } | |
| 8755 | − if (quirks & TPACPI_FAN_2CTL) { | |
| 8756 | − tp_features.second_fan = 1; | |
| 8757 | − tp_features.second_fan_ctl = 1; | |
| 8758 | − pr_info("secondary fan control enabled\n"); | |
| 8759 | − } | |
| 8760 | 8883 | /* Try and probe the 2nd fan */ |
| 8884 | + tp_features.second_fan = 1; /* needed for get_speed to work */ | |
| 8761 | 8885 | res = fan2_get_speed(&speed); |
| 8762 | 8886 | if (res >= 0) { |
| 8763 | 8887 | /* It responded - so let's assume it's there */ |
| 8764 | 8888 | tp_features.second_fan = 1; |
| 8765 | 8889 | tp_features.second_fan_ctl = 1; |
| 8766 | 8890 | pr_info("secondary fan control detected & enabled\n"); |
| 8891 | + } else { | |
| 8892 | + /* Fan not auto-detected */ | |
| 8893 | + tp_features.second_fan = 0; | |
| 8894 | + if (quirks & TPACPI_FAN_2FAN) { | |
| 8895 | + tp_features.second_fan = 1; | |
| 8896 | + pr_info("secondary fan support enabled\n"); | |
| 8897 | + } | |
| 8898 | + if (quirks & TPACPI_FAN_2CTL) { | |
| 8899 | + tp_features.second_fan = 1; | |
| 8900 | + tp_features.second_fan_ctl = 1; | |
| 8901 | + pr_info("secondary fan control enabled\n"); | |
| 8902 | + } | |
| 8767 | 8903 | } |
| 8768 | − | |
| 8769 | 8904 | } else { |
| 8770 | 8905 | pr_err("ThinkPad ACPI EC access misbehaving, fan status and control unavailable\n"); |
| 8771 | 8906 | return -ENODEV; |
| @@ -11455,6 +11590,10 @@ static void thinkpad_acpi_module_exit(void) · 2683 unmodified lines | ||
| 11455 | 11590 | |
| 11456 | 11591 | tpacpi_lifecycle = TPACPI_LIFE_EXITING; |
| 11457 | 11592 | |
| 11593 | +#ifdef CONFIG_SUSPEND | |
| 11594 | + if (tp_features.quirks && tp_features.quirks->s2idle_bug_mmio) | |
| 11595 | + acpi_unregister_lps0_dev(&thinkpad_acpi_s2idle_dev_ops); | |
| 11596 | +#endif | |
| 11458 | 11597 | if (tpacpi_hwmon) |
| 11459 | 11598 | hwmon_device_unregister(tpacpi_hwmon); |
| 11460 | 11599 | if (tp_features.sensors_pdrv_registered) |
| @@ -11496,6 +11635,7 @@ static void thinkpad_acpi_module_exit(void) · 35 unmodified lines | ||
| 11496 | 11635 | |
| 11497 | 11636 | static int __init thinkpad_acpi_module_init(void) |
| 11498 | 11637 | { |
| 11638 | + const struct dmi_system_id *dmi_id; | |
| 11499 | 11639 | int ret, i; |
| 11500 | 11640 | |
| 11501 | 11641 | tpacpi_lifecycle = TPACPI_LIFE_INIT; |
| @@ -11535,6 +11675,10 @@ static int __init thinkpad_acpi_module_init(void) · 33 unmodified lines | ||
| 11535 | 11675 | return -ENODEV; |
| 11536 | 11676 | } |
| 11537 | 11677 | |
| 11678 | + dmi_id = dmi_first_match(fwbug_list); | |
| 11679 | + if (dmi_id) | |
| 11680 | + tp_features.quirks = dmi_id->driver_data; | |
| 11681 | + | |
| 11538 | 11682 | /* Device initialization */ |
| 11539 | 11683 | tpacpi_pdev = platform_device_register_simple(TPACPI_DRVR_NAME, -1, |
| 11540 | 11684 | NULL, 0); |
| @@ -11623,6 +11767,13 @@ static int __init thinkpad_acpi_module_init(void) · 82 unmodified lines | ||
| 11623 | 11767 | tp_features.input_device_registered = 1; |
| 11624 | 11768 | } |
| 11625 | 11769 | |
| 11770 | +#ifdef CONFIG_SUSPEND | |
| 11771 | + if (tp_features.quirks && tp_features.quirks->s2idle_bug_mmio) { | |
| 11772 | + if (!acpi_register_lps0_dev(&thinkpad_acpi_s2idle_dev_ops)) | |
| 11773 | + pr_info("Using s2idle quirk to avoid %s platform firmware bug\n", | |
| 11774 | + (dmi_id && dmi_id->ident) ? dmi_id->ident : ""); | |
| 11775 | + } | |
| 11776 | +#endif | |
| 11626 | 11777 | return 0; |
| 11627 | 11778 | } |
| 11628 | 11779 | |
| @@ -1557,7 +1557,7 @@ ptp_ocp_signal_set(struct ptp_ocp *bp, int gen, struct ptp_ocp_signal *s) · 1556 unmodified lines | ||
| 1557 | 1557 | start_ns = ktime_set(ts.tv_sec, ts.tv_nsec) + NSEC_PER_MSEC; |
| 1558 | 1558 | if (!s->start) { |
| 1559 | 1559 | /* roundup() does not work on 32-bit systems */ |
| 1560 | − s->start = DIV_ROUND_UP_ULL(start_ns, s->period); | |
| 1560 | + s->start = DIV64_U64_ROUND_UP(start_ns, s->period); | |
| 1561 | 1561 | s->start = ktime_add(s->start, s->phase); |
| 1562 | 1562 | } |
| 1563 | 1563 | |
| @@ -1422,6 +1422,13 @@ int dasd_start_IO(struct dasd_ccw_req *cqr) · 1421 unmodified lines | ||
| 1422 | 1422 | if (!cqr->lpm) |
| 1423 | 1423 | cqr->lpm = dasd_path_get_opm(device); |
| 1424 | 1424 | } |
| 1425 | + /* | |
| 1426 | + * remember the amount of formatted tracks to prevent double format on | |
| 1427 | + * ESE devices | |
| 1428 | + */ | |
| 1429 | + if (cqr->block) | |
| 1430 | + cqr->trkcount = atomic_read(&cqr->block->trkcount); | |
| 1431 | + | |
| 1425 | 1432 | if (cqr->cpmode == 1) { |
| 1426 | 1433 | rc = ccw_device_tm_start(device->cdev, cqr->cpaddr, |
| 1427 | 1434 | (long) cqr, cqr->lpm); |
| @@ -1639,6 +1646,7 @@ void dasd_int_handler(struct ccw_device *cdev, unsigned long intparm, · 211 unmodified lines | ||
| 1639 | 1646 | unsigned long now; |
| 1640 | 1647 | int nrf_suppressed = 0; |
| 1641 | 1648 | int fp_suppressed = 0; |
| 1649 | + struct request *req; | |
| 1642 | 1650 | u8 *sense = NULL; |
| 1643 | 1651 | int expires; |
| 1644 | 1652 | |
| @@ -1739,7 +1747,12 @@ void dasd_int_handler(struct ccw_device *cdev, unsigned long intparm, · 94 unmodified lines | ||
| 1739 | 1747 | } |
| 1740 | 1748 | |
| 1741 | 1749 | if (dasd_ese_needs_format(cqr->block, irb)) { |
| 1742 | − if (rq_data_dir((struct request *)cqr->callback_data) == READ) { | |
| 1750 | + req = dasd_get_callback_data(cqr); | |
| 1751 | + if (!req) { | |
| 1752 | + cqr->status = DASD_CQR_ERROR; | |
| 1753 | + return; | |
| 1754 | + } | |
| 1755 | + if (rq_data_dir(req) == READ) { | |
| 1743 | 1756 | device->discipline->ese_read(cqr, irb); |
| 1744 | 1757 | cqr->status = DASD_CQR_SUCCESS; |
| 1745 | 1758 | cqr->stopclk = now; |
| @@ -2765,8 +2778,7 @@ static void __dasd_cleanup_cqr(struct dasd_ccw_req *cqr) · 1019 unmodified lines | ||
| 2765 | 2778 | * complete a request partially. |
| 2766 | 2779 | */ |
| 2767 | 2780 | if (proc_bytes) { |
| 2768 | − blk_update_request(req, BLK_STS_OK, | |
| 2769 | − blk_rq_bytes(req) - proc_bytes); | |
| 2781 | + blk_update_request(req, BLK_STS_OK, proc_bytes); | |
| 2770 | 2782 | blk_mq_requeue_request(req, true); |
| 2771 | 2783 | } else if (likely(!blk_should_fake_timeout(req->q))) { |
| 2772 | 2784 | blk_mq_complete_request(req); |
| @@ -1480,7 +1480,7 @@ static int dasd_eckd_pe_handler(struct dasd_device *device, · 1479 unmodified lines | ||
| 1480 | 1480 | { |
| 1481 | 1481 | struct pe_handler_work_data *data; |
| 1482 | 1482 | |
| 1483 | − data = kmalloc(sizeof(*data), GFP_ATOMIC | GFP_DMA); | |
| 1483 | + data = kzalloc(sizeof(*data), GFP_ATOMIC | GFP_DMA); | |
| 1484 | 1484 | if (!data) { |
| 1485 | 1485 | if (mutex_trylock(&dasd_pe_handler_mutex)) { |
| 1486 | 1486 | data = pe_handler_worker; |
| @@ -1488,9 +1488,6 @@ static int dasd_eckd_pe_handler(struct dasd_device *device, · 1 unmodified line | ||
| 1488 | 1488 | } else { |
| 1489 | 1489 | return -ENOMEM; |
| 1490 | 1490 | } |
| 1491 | − } else { | |
| 1492 | − memset(data, 0, sizeof(*data)); | |
| 1493 | − data->isglobal = 0; | |
| 1494 | 1491 | } |
| 1495 | 1492 | INIT_WORK(&data->worker, do_pe_handler_work); |
| 1496 | 1493 | dasd_get_device(device); |
| @@ -3083,13 +3080,24 @@ static int dasd_eckd_format_device(struct dasd_device *base, · 1586 unmodified lines | ||
| 3083 | 3080 | } |
| 3084 | 3081 | |
| 3085 | 3082 | static bool test_and_set_format_track(struct dasd_format_entry *to_format, |
| 3086 | − struct dasd_block *block) | |
| 3083 | + struct dasd_ccw_req *cqr) | |
| 3087 | 3084 | { |
| 3085 | + struct dasd_block *block = cqr->block; | |
| 3088 | 3086 | struct dasd_format_entry *format; |
| 3089 | 3087 | unsigned long flags; |
| 3090 | 3088 | bool rc = false; |
| 3091 | 3089 | |
| 3092 | 3090 | spin_lock_irqsave(&block->format_lock, flags); |
| 3091 | + if (cqr->trkcount != atomic_read(&block->trkcount)) { | |
| 3092 | + /* | |
| 3093 | + * The number of formatted tracks has changed after request | |
| 3094 | + * start and we can not tell if the current track was involved. | |
| 3095 | + * To avoid data corruption treat it as if the current track is | |
| 3096 | + * involved | |
| 3097 | + */ | |
| 3098 | + rc = true; | |
| 3099 | + goto out; | |
| 3100 | + } | |
| 3093 | 3101 | list_for_each_entry(format, &block->format_list, list) { |
| 3094 | 3102 | if (format->track == to_format->track) { |
| 3095 | 3103 | rc = true; |
| @@ -3109,6 +3117,7 @@ static void clear_format_track(struct dasd_format_entry *format, · 13 unmodified lines | ||
| 3109 | 3117 | unsigned long flags; |
| 3110 | 3118 | |
| 3111 | 3119 | spin_lock_irqsave(&block->format_lock, flags); |
| 3120 | + atomic_inc(&block->trkcount); | |
| 3112 | 3121 | list_del_init(&format->list); |
| 3113 | 3122 | spin_unlock_irqrestore(&block->format_lock, flags); |
| 3114 | 3123 | } |
| @@ -3145,7 +3154,7 @@ dasd_eckd_ese_format(struct dasd_device *startdev, struct dasd_ccw_req *cqr, · 30 unmodified lines | ||
| 3145 | 3154 | sector_t curr_trk; |
| 3146 | 3155 | int rc; |
| 3147 | 3156 | |
| 3148 | − req = cqr->callback_data; | |
| 3157 | + req = dasd_get_callback_data(cqr); | |
| 3149 | 3158 | block = cqr->block; |
| 3150 | 3159 | base = block->base; |
| 3151 | 3160 | private = base->private; |
| @@ -3170,8 +3179,11 @@ dasd_eckd_ese_format(struct dasd_device *startdev, struct dasd_ccw_req *cqr, · 18 unmodified lines | ||
| 3170 | 3179 | } |
| 3171 | 3180 | format->track = curr_trk; |
| 3172 | 3181 | /* test if track is already in formatting by another thread */ |
| 3173 | − if (test_and_set_format_track(format, block)) | |
| 3182 | + if (test_and_set_format_track(format, cqr)) { | |
| 3183 | + /* this is no real error so do not count down retries */ | |
| 3184 | + cqr->retries++; | |
| 3174 | 3185 | return ERR_PTR(-EEXIST); |
| 3186 | + } | |
| 3175 | 3187 | |
| 3176 | 3188 | fdata.start_unit = curr_trk; |
| 3177 | 3189 | fdata.stop_unit = curr_trk; |
| @@ -3270,12 +3282,11 @@ static int dasd_eckd_ese_read(struct dasd_ccw_req *cqr, struct irb *irb) · 92 unmodified lines | ||
| 3270 | 3282 | cqr->proc_bytes = blk_count * blksize; |
| 3271 | 3283 | return 0; |
| 3272 | 3284 | } |
| 3273 | − if (dst && !skip_block) { | |
| 3274 | − dst += off; | |
| 3285 | + if (dst && !skip_block) | |
| 3275 | 3286 | memset(dst, 0, blksize); |
| 3276 | − } else { | |
| 3287 | + else | |
| 3277 | 3288 | skip_block--; |
| 3278 | − } | |
| 3289 | + dst += blksize; | |
| 3279 | 3290 | blk_count++; |
| 3280 | 3291 | } |
| 3281 | 3292 | } |
| @@ -187,6 +187,7 @@ struct dasd_ccw_req { · 186 unmodified lines | ||
| 187 | 187 | void (*callback)(struct dasd_ccw_req *, void *data); |
| 188 | 188 | void *callback_data; |
| 189 | 189 | unsigned int proc_bytes; /* bytes for partial completion */ |
| 190 | + unsigned int trkcount; /* count formatted tracks */ | |
| 190 | 191 | }; |
| 191 | 192 | |
| 192 | 193 | /* |
| @@ -610,6 +611,7 @@ struct dasd_block { · 417 unmodified lines | ||
| 610 | 611 | |
| 611 | 612 | struct list_head format_list; |
| 612 | 613 | spinlock_t format_lock; |
| 614 | + atomic_t trkcount; | |
| 613 | 615 | }; |
| 614 | 616 | |
| 615 | 617 | struct dasd_attention_data { |
| @@ -756,6 +758,18 @@ dasd_check_blocksize(int bsize) · 140 unmodified lines | ||
| 756 | 758 | return 0; |
| 757 | 759 | } |
| 758 | 760 | |
| 761 | +/* | |
| 762 | + * return the callback data of the original request in case there are | |
| 763 | + * ERP requests build on top of it | |
| 764 | + */ | |
| 765 | +static inline void *dasd_get_callback_data(struct dasd_ccw_req *cqr) | |
| 766 | +{ | |
| 767 | + while (cqr->refers) | |
| 768 | + cqr = cqr->refers; | |
| 769 | + | |
| 770 | + return cqr->callback_data; | |
| 771 | +} | |
| 772 | + | |
| 759 | 773 | /* externals in dasd.c */ |
| 760 | 774 | #define DASD_PROFILE_OFF 0 |
| 761 | 775 | #define DASD_PROFILE_ON 1 |
| @@ -626,8 +626,6 @@ static void mpc_rcvd_sweep_resp(struct mpcg_info *mpcginfo) · 625 unmodified lines | ||
| 626 | 626 | ctcm_clear_busy_do(dev); |
| 627 | 627 | } |
| 628 | 628 | |
| 629 | − kfree(mpcginfo); | |
| 630 | − | |
| 631 | 629 | return; |
| 632 | 630 | |
| 633 | 631 | } |
| @@ -1192,10 +1190,10 @@ static void ctcmpc_unpack_skb(struct channel *ch, struct sk_buff *pskb) · 558 unmodified lines | ||
| 1192 | 1190 | CTCM_FUNTAIL, dev->name); |
| 1193 | 1191 | priv->stats.rx_dropped++; |
| 1194 | 1192 | /* mpcginfo only used for non-data transfers */ |
| 1195 | − kfree(mpcginfo); | |
| 1196 | 1193 | if (do_debug_data) |
| 1197 | 1194 | ctcmpc_dump_skb(pskb, -8); |
| 1198 | 1195 | } |
| 1196 | + kfree(mpcginfo); | |
| 1199 | 1197 | } |
| 1200 | 1198 | done: |
| 1201 | 1199 | |
| @@ -1977,7 +1975,6 @@ static void mpc_action_rcvd_xid0(fsm_instance *fsm, int event, void *arg) · 775 unmodified lines | ||
| 1977 | 1975 | } |
| 1978 | 1976 | break; |
| 1979 | 1977 | } |
| 1980 | − kfree(mpcginfo); | |
| 1981 | 1978 | |
| 1982 | 1979 | CTCM_PR_DEBUG("ctcmpc:%s() %s xid2:%i xid7:%i xidt_p2:%i \n", |
| 1983 | 1980 | __func__, ch->id, grp->outstanding_xid2, |
| @@ -2038,7 +2035,6 @@ static void mpc_action_rcvd_xid7(fsm_instance *fsm, int event, void *arg) · 54 unmodified lines | ||
| 2038 | 2035 | mpc_validate_xid(mpcginfo); |
| 2039 | 2036 | break; |
| 2040 | 2037 | } |
| 2041 | − kfree(mpcginfo); | |
| 2042 | 2038 | return; |
| 2043 | 2039 | } |
| 2044 | 2040 | |
| @@ -39,11 +39,12 @@ static ssize_t ctcm_buffer_write(struct device *dev, · 38 unmodified lines | ||
| 39 | 39 | struct ctcm_priv *priv = dev_get_drvdata(dev); |
| 40 | 40 | int rc; |
| 41 | 41 | |
| 42 | − ndev = priv->channel[CTCM_READ]->netdev; | |
| 43 | − if (!(priv && priv->channel[CTCM_READ] && ndev)) { | |
| 42 | + if (!(priv && priv->channel[CTCM_READ] && | |
| 43 | + priv->channel[CTCM_READ]->netdev)) { | |
| 44 | 44 | CTCM_DBF_TEXT(SETUP, CTC_DBF_ERROR, "bfnondev"); |
| 45 | 45 | return -ENODEV; |
| 46 | 46 | } |
| 47 | + ndev = priv->channel[CTCM_READ]->netdev; | |
| 47 | 48 | |
| 48 | 49 | rc = kstrtouint(buf, 0, &bs1); |
| 49 | 50 | if (rc) |
| @@ -1736,10 +1736,11 @@ lcs_get_control(struct lcs_card *card, struct lcs_cmd *cmd) · 1735 unmodified lines | ||
| 1736 | 1736 | lcs_schedule_recovery(card); |
| 1737 | 1737 | break; |
| 1738 | 1738 | case LCS_CMD_STOPLAN: |
| 1739 | − pr_warn("Stoplan for %s initiated by LGW\n", | |
| 1740 | − card->dev->name); | |
| 1741 | − if (card->dev) | |
| 1739 | + if (card->dev) { | |
| 1740 | + pr_warn("Stoplan for %s initiated by LGW\n", | |
| 1741 | + card->dev->name); | |
| 1742 | 1742 | netif_carrier_off(card->dev); |
| 1743 | + } | |
| 1743 | 1744 | break; |
| 1744 | 1745 | default: |
| 1745 | 1746 | LCS_DBF_TEXT(5, trace, "noLGWcmd"); |
| @@ -1172,9 +1172,8 @@ static blk_status_t alua_prep_fn(struct scsi_device *sdev, struct request *req) · 1171 unmodified lines | ||
| 1172 | 1172 | case SCSI_ACCESS_STATE_OPTIMAL: |
| 1173 | 1173 | case SCSI_ACCESS_STATE_ACTIVE: |
| 1174 | 1174 | case SCSI_ACCESS_STATE_LBA: |
| 1175 | − return BLK_STS_OK; | |
| 1176 | 1175 | case SCSI_ACCESS_STATE_TRANSITIONING: |
| 1177 | − return BLK_STS_AGAIN; | |
| 1176 | + return BLK_STS_OK; | |
| 1178 | 1177 | default: |
| 1179 | 1178 | req->rq_flags |= RQF_QUIET; |
| 1180 | 1179 | return BLK_STS_IOERR; |
| @@ -1330,7 +1330,7 @@ lpfc_issue_els_flogi(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, · 1329 unmodified lines | ||
| 1330 | 1330 | if (bf_get(lpfc_sli_intf_if_type, &phba->sli4_hba.sli_intf) == |
| 1331 | 1331 | LPFC_SLI_INTF_IF_TYPE_0) { |
| 1332 | 1332 | /* FLOGI needs to be 3 for WQE FCFI */ |
| 1333 | − ct = ((SLI4_CT_FCFI >> 1) & 1) | (SLI4_CT_FCFI & 1); | |
| 1333 | + ct = SLI4_CT_FCFI; | |
| 1334 | 1334 | bf_set(wqe_ct, &wqe->els_req.wqe_com, ct); |
| 1335 | 1335 | |
| 1336 | 1336 | /* Set the fcfi to the fcfi we registered with */ |
| @@ -10720,10 +10720,10 @@ __lpfc_sli_prep_gen_req_s4(struct lpfc_iocbq *cmdiocbq, struct lpfc_dmabuf *bmp, · 10719 unmodified lines | ||
| 10720 | 10720 | |
| 10721 | 10721 | /* Words 0 - 2 */ |
| 10722 | 10722 | bde = (struct ulp_bde64_le *)&cmdwqe->generic.bde; |
| 10723 | − bde->addr_low = cpu_to_le32(putPaddrLow(bmp->phys)); | |
| 10724 | − bde->addr_high = cpu_to_le32(putPaddrHigh(bmp->phys)); | |
| 10723 | + bde->addr_low = bpl->addr_low; | |
| 10724 | + bde->addr_high = bpl->addr_high; | |
| 10725 | 10725 | bde->type_size = cpu_to_le32(xmit_len); |
| 10726 | − bde->type_size |= cpu_to_le32(ULP_BDE64_TYPE_BLP_64); | |
| 10726 | + bde->type_size |= cpu_to_le32(ULP_BDE64_TYPE_BDE_64); | |
| 10727 | 10727 | |
| 10728 | 10728 | /* Word 3 */ |
| 10729 | 10729 | cmdwqe->gen_req.request_payload_len = xmit_len; |
| @@ -3826,6 +3826,9 @@ int qlt_abort_cmd(struct qla_tgt_cmd *cmd) · 3825 unmodified lines | ||
| 3826 | 3826 | |
| 3827 | 3827 | spin_lock_irqsave(&cmd->cmd_lock, flags); |
| 3828 | 3828 | if (cmd->aborted) { |
| 3829 | + if (cmd->sg_mapped) | |
| 3830 | + qlt_unmap_sg(vha, cmd); | |
| 3831 | + | |
| 3829 | 3832 | spin_unlock_irqrestore(&cmd->cmd_lock, flags); |
| 3830 | 3833 | /* |
| 3831 | 3834 | * It's normal to see 2 calls in this path: |
| @@ -510,9 +510,9 @@ static int qcom_slim_probe(struct platform_device *pdev) · 509 unmodified lines | ||
| 510 | 510 | } |
| 511 | 511 | |
| 512 | 512 | ctrl->irq = platform_get_irq(pdev, 0); |
| 513 | − if (!ctrl->irq) { | |
| 513 | + if (ctrl->irq < 0) { | |
| 514 | 514 | dev_err(&pdev->dev, "no slimbus IRQ\n"); |
| 515 | − return -ENODEV; | |
| 515 | + return ctrl->irq; | |
| 516 | 516 | } |
| 517 | 517 | |
| 518 | 518 | sctrl = &ctrl->ctrl; |
| @@ -50,7 +50,7 @@ struct imx8m_blk_ctrl_domain_data { · 49 unmodified lines | ||
| 50 | 50 | u32 mipi_phy_rst_mask; |
| 51 | 51 | }; |
| 52 | 52 | |
| 53 | −#define DOMAIN_MAX_CLKS 3 | |
| 53 | +#define DOMAIN_MAX_CLKS 4 | |
| 54 | 54 | |
| 55 | 55 | struct imx8m_blk_ctrl_domain { |
| 56 | 56 | struct generic_pm_domain genpd; |
| @@ -588,7 +588,7 @@ static void pscsi_destroy_device(struct se_device *dev) · 587 unmodified lines | ||
| 588 | 588 | } |
| 589 | 589 | |
| 590 | 590 | static void pscsi_complete_cmd(struct se_cmd *cmd, u8 scsi_status, |
| 591 | − unsigned char *req_sense) | |
| 591 | + unsigned char *req_sense, int valid_data) | |
| 592 | 592 | { |
| 593 | 593 | struct pscsi_dev_virt *pdv = PSCSI_DEV(cmd->se_dev); |
| 594 | 594 | struct scsi_device *sd = pdv->pdv_sd; |
| @@ -681,7 +681,7 @@ after_mode_select: · 86 unmodified lines | ||
| 681 | 681 | * back despite framework assumption that a |
| 682 | 682 | * check condition means there is no data |
| 683 | 683 | */ |
| 684 | − if (sd->type == TYPE_TAPE && | |
| 684 | + if (sd->type == TYPE_TAPE && valid_data && | |
| 685 | 685 | cmd->data_direction == DMA_FROM_DEVICE) { |
| 686 | 686 | /* |
| 687 | 687 | * is sense data valid, fixed format, |
| @@ -1032,6 +1032,7 @@ static void pscsi_req_done(struct request *req, blk_status_t status) · 344 unmodified lines | ||
| 1032 | 1032 | struct se_cmd *cmd = req->end_io_data; |
| 1033 | 1033 | struct scsi_cmnd *scmd = blk_mq_rq_to_pdu(req); |
| 1034 | 1034 | enum sam_status scsi_status = scmd->result & 0xff; |
| 1035 | + int valid_data = cmd->data_length - scmd->resid_len; | |
| 1035 | 1036 | u8 *cdb = cmd->priv; |
| 1036 | 1037 | |
| 1037 | 1038 | if (scsi_status != SAM_STAT_GOOD) { |
| @@ -1039,12 +1040,11 @@ static void pscsi_req_done(struct request *req, blk_status_t status) · 1 unmodified line | ||
| 1039 | 1040 | " 0x%02x Result: 0x%08x\n", cmd, cdb[0], scmd->result); |
| 1040 | 1041 | } |
| 1041 | 1042 | |
| 1042 | − pscsi_complete_cmd(cmd, scsi_status, scmd->sense_buffer); | |
| 1043 | + pscsi_complete_cmd(cmd, scsi_status, scmd->sense_buffer, valid_data); | |
| 1043 | 1044 | |
| 1044 | 1045 | switch (host_byte(scmd->result)) { |
| 1045 | 1046 | case DID_OK: |
| 1046 | − target_complete_cmd_with_length(cmd, scsi_status, | |
| 1047 | − cmd->data_length - scmd->resid_len); | |
| 1047 | + target_complete_cmd_with_length(cmd, scsi_status, valid_data); | |
| 1048 | 1048 | break; |
| 1049 | 1049 | default: |
| 1050 | 1050 | pr_debug("PSCSI Host Byte exception at cmd: %p CDB:" |
| @@ -865,6 +865,7 @@ err_rhashtable_free: · 864 unmodified lines | ||
| 865 | 865 | rhashtable_free_and_destroy(&optee->ffa.global_ids, rh_free_fn, NULL); |
| 866 | 866 | optee_supp_uninit(&optee->supp); |
| 867 | 867 | mutex_destroy(&optee->call_queue.mutex); |
| 868 | + mutex_destroy(&optee->ffa.mutex); | |
| 868 | 869 | err_unreg_supp_teedev: |
| 869 | 870 | tee_device_unregister(optee->supp_teedev); |
| 870 | 871 | err_unreg_teedev: |
| @@ -113,8 +113,10 @@ config THERMAL_DEFAULT_GOV_USER_SPACE · 112 unmodified lines | ||
| 113 | 113 | bool "user_space" |
| 114 | 114 | select THERMAL_GOV_USER_SPACE |
| 115 | 115 | help |
| 116 | − Select this if you want to let the user space manage the | |
| 117 | − platform thermals. | |
| 116 | + The Userspace governor allows to get trip point crossed | |
| 117 | + notification from the kernel via uevents. It is recommended | |
| 118 | + to use the netlink interface instead which gives richer | |
| 119 | + information about the thermal framework events. | |
| 118 | 120 | |
| 119 | 121 | config THERMAL_DEFAULT_GOV_POWER_ALLOCATOR |
| 120 | 122 | bool "power_allocator" |
| @@ -17,8 +17,7 @@ · 16 unmodified lines | ||
| 17 | 17 | |
| 18 | 18 | static int user_space_bind(struct thermal_zone_device *tz) |
| 19 | 19 | { |
| 20 | − pr_warn_once("Userspace governor deprecated: use thermal netlink " \ | |
| 21 | − "notification instead\n"); | |
| 20 | + pr_info_once("Consider using thermal netlink events interface\n"); | |
| 22 | 21 | |
| 23 | 22 | return 0; |
| 24 | 23 | } |
| @@ -68,7 +68,7 @@ static int evaluate_odvp(struct int3400_thermal_priv *priv); · 67 unmodified lines | ||
| 68 | 68 | struct odvp_attr { |
| 69 | 69 | int odvp; |
| 70 | 70 | struct int3400_thermal_priv *priv; |
| 71 | − struct kobj_attribute attr; | |
| 71 | + struct device_attribute attr; | |
| 72 | 72 | }; |
| 73 | 73 | |
| 74 | 74 | static ssize_t data_vault_read(struct file *file, struct kobject *kobj, |
| @@ -311,7 +311,7 @@ end: · 236 unmodified lines | ||
| 311 | 311 | return result; |
| 312 | 312 | } |
| 313 | 313 | |
| 314 | −static ssize_t odvp_show(struct kobject *kobj, struct kobj_attribute *attr, | |
| 314 | +static ssize_t odvp_show(struct device *dev, struct device_attribute *attr, | |
| 315 | 315 | char *buf) |
| 316 | 316 | { |
| 317 | 317 | struct odvp_attr *odvp_attr; |
| @@ -610,9 +610,6 @@ cur_state_store(struct device *dev, struct device_attribute *attr, · 609 unmodified lines | ||
| 610 | 610 | unsigned long state; |
| 611 | 611 | int result; |
| 612 | 612 | |
| 613 | − dev_warn_once(&cdev->device, | |
| 614 | − "Setting cooling device state is deprecated\n"); | |
| 615 | − | |
| 616 | 613 | if (sscanf(buf, "%ld\n", &state) != 1) |
| 617 | 614 | return -EINVAL; |
| 618 | 615 | |
| @@ -7,9 +7,7 @@ · 6 unmodified lines | ||
| 7 | 7 | */ |
| 8 | 8 | |
| 9 | 9 | #include <linux/device.h> |
| 10 | −#include <linux/dmar.h> | |
| 11 | 10 | #include <linux/idr.h> |
| 12 | −#include <linux/iommu.h> | |
| 13 | 11 | #include <linux/module.h> |
| 14 | 12 | #include <linux/pm_runtime.h> |
| 15 | 13 | #include <linux/slab.h> |
| @@ -257,13 +255,9 @@ static ssize_t iommu_dma_protection_show(struct device *dev, · 241 unmodified lines | ||
| 257 | 255 | struct device_attribute *attr, |
| 258 | 256 | char *buf) |
| 259 | 257 | { |
| 260 | − /* | |
| 261 | − * Kernel DMA protection is a feature where Thunderbolt security is | |
| 262 | − * handled natively using IOMMU. It is enabled when IOMMU is | |
| 263 | − * enabled and ACPI DMAR table has DMAR_PLATFORM_OPT_IN set. | |
| 264 | − */ | |
| 265 | − return sprintf(buf, "%d\n", | |
| 266 | − iommu_present(&pci_bus_type) && dmar_platform_optin()); | |
| 258 | + struct tb *tb = container_of(dev, struct tb, dev); | |
| 259 | + | |
| 260 | + return sysfs_emit(buf, "%d\n", tb->nhi->iommu_dma_protection); | |
| 267 | 261 | } |
| 268 | 262 | static DEVICE_ATTR_RO(iommu_dma_protection); |
| 269 | 263 | |
| @@ -15,9 +15,11 @@ · 14 unmodified lines | ||
| 15 | 15 | #include <linux/pci.h> |
| 16 | 16 | #include <linux/dma-mapping.h> |
| 17 | 17 | #include <linux/interrupt.h> |
| 18 | +#include <linux/iommu.h> | |
| 18 | 19 | #include <linux/module.h> |
| 19 | 20 | #include <linux/delay.h> |
| 20 | 21 | #include <linux/property.h> |
| 22 | +#include <linux/string_helpers.h> | |
| 21 | 23 | |
| 22 | 24 | #include "nhi.h" |
| 23 | 25 | #include "nhi_regs.h" |
| @@ -1103,6 +1105,47 @@ static void nhi_check_quirks(struct tb_nhi *nhi) · 1079 unmodified lines | ||
| 1103 | 1105 | nhi->quirks |= QUIRK_AUTO_CLEAR_INT; |
| 1104 | 1106 | } |
| 1105 | 1107 | |
| 1108 | +static int nhi_check_iommu_pdev(struct pci_dev *pdev, void *data) | |
| 1109 | +{ | |
| 1110 | + if (!pdev->external_facing || | |
| 1111 | + !device_iommu_capable(&pdev->dev, IOMMU_CAP_PRE_BOOT_PROTECTION)) | |
| 1112 | + return 0; | |
| 1113 | + *(bool *)data = true; | |
| 1114 | + return 1; /* Stop walking */ | |
| 1115 | +} | |
| 1116 | + | |
| 1117 | +static void nhi_check_iommu(struct tb_nhi *nhi) | |
| 1118 | +{ | |
| 1119 | + struct pci_bus *bus = nhi->pdev->bus; | |
| 1120 | + bool port_ok = false; | |
| 1121 | + | |
| 1122 | + /* | |
| 1123 | + * Ideally what we'd do here is grab every PCI device that | |
| 1124 | + * represents a tunnelling adapter for this NHI and check their | |
| 1125 | + * status directly, but unfortunately USB4 seems to make it | |
| 1126 | + * obnoxiously difficult to reliably make any correlation. | |
| 1127 | + * | |
| 1128 | + * So for now we'll have to bodge it... Hoping that the system | |
| 1129 | + * is at least sane enough that an adapter is in the same PCI | |
| 1130 | + * segment as its NHI, if we can find *something* on that segment | |
| 1131 | + * which meets the requirements for Kernel DMA Protection, we'll | |
| 1132 | + * take that to imply that firmware is aware and has (hopefully) | |
| 1133 | + * done the right thing in general. We need to know that the PCI | |
| 1134 | + * layer has seen the ExternalFacingPort property which will then | |
| 1135 | + * inform the IOMMU layer to enforce the complete "untrusted DMA" | |
| 1136 | + * flow, but also that the IOMMU driver itself can be trusted not | |
| 1137 | + * to have been subverted by a pre-boot DMA attack. | |
| 1138 | + */ | |
| 1139 | + while (bus->parent) | |
| 1140 | + bus = bus->parent; | |
| 1141 | + | |
| 1142 | + pci_walk_bus(bus, nhi_check_iommu_pdev, &port_ok); | |
| 1143 | + | |
| 1144 | + nhi->iommu_dma_protection = port_ok; | |
| 1145 | + dev_dbg(&nhi->pdev->dev, "IOMMU DMA protection is %s\n", | |
| 1146 | + str_enabled_disabled(port_ok)); | |
| 1147 | +} | |
| 1148 | + | |
| 1106 | 1149 | static int nhi_init_msi(struct tb_nhi *nhi) |
| 1107 | 1150 | { |
| 1108 | 1151 | struct pci_dev *pdev = nhi->pdev; |
| @@ -1220,6 +1263,7 @@ static int nhi_probe(struct pci_dev *pdev, const struct pci_device_id *id) · 111 unmodified lines | ||
| 1220 | 1263 | return -ENOMEM; |
| 1221 | 1264 | |
| 1222 | 1265 | nhi_check_quirks(nhi); |
| 1266 | + nhi_check_iommu(nhi); | |
| 1223 | 1267 | |
| 1224 | 1268 | res = nhi_init_msi(nhi); |
| 1225 | 1269 | if (res) { |
| @@ -73,6 +73,8 @@ module_param(debug, int, 0600); · 72 unmodified lines | ||
| 73 | 73 | */ |
| 74 | 74 | #define MAX_MRU 1500 |
| 75 | 75 | #define MAX_MTU 1500 |
| 76 | +/* SOF, ADDR, CTRL, LEN1, LEN2, ..., FCS, EOF */ | |
| 77 | +#define PROT_OVERHEAD 7 | |
| 76 | 78 | #define GSM_NET_TX_TIMEOUT (HZ*10) |
| 77 | 79 | |
| 78 | 80 | /* |
| @@ -135,6 +137,7 @@ struct gsm_dlci { · 56 unmodified lines | ||
| 135 | 137 | int retries; |
| 136 | 138 | /* Uplink tty if active */ |
| 137 | 139 | struct tty_port port; /* The tty bound to this DLCI if there is one */ |
| 140 | +#define TX_SIZE 4096 /* Must be power of 2. */ | |
| 138 | 141 | struct kfifo fifo; /* Queue fifo for the DLCI */ |
| 139 | 142 | int adaption; /* Adaption layer in use */ |
| 140 | 143 | int prev_adaption; |
| @@ -219,7 +222,6 @@ struct gsm_mux { · 78 unmodified lines | ||
| 219 | 222 | int encoding; |
| 220 | 223 | u8 control; |
| 221 | 224 | u8 fcs; |
| 222 | − u8 received_fcs; | |
| 223 | 225 | u8 *txframe; /* TX framing buffer */ |
| 224 | 226 | |
| 225 | 227 | /* Method for the receiver side */ |
| @@ -231,6 +233,7 @@ struct gsm_mux { · 5 unmodified lines | ||
| 231 | 233 | int initiator; /* Did we initiate connection */ |
| 232 | 234 | bool dead; /* Has the mux been shut down */ |
| 233 | 235 | struct gsm_dlci *dlci[NUM_DLCI]; |
| 236 | + int old_c_iflag; /* termios c_iflag value before attach */ | |
| 234 | 237 | bool constipated; /* Asked by remote to shut up */ |
| 235 | 238 | |
| 236 | 239 | spinlock_t tx_lock; |
| @@ -271,10 +274,6 @@ static DEFINE_SPINLOCK(gsm_mux_lock); · 34 unmodified lines | ||
| 271 | 274 | |
| 272 | 275 | static struct tty_driver *gsm_tty_driver; |
| 273 | 276 | |
| 274 | −/* Save dlci open address */ | |
| 275 | −static int addr_open[256] = { 0 }; | |
| 276 | −/* Save dlci open count */ | |
| 277 | −static int addr_cnt; | |
| 278 | 277 | /* |
| 279 | 278 | * This section of the driver logic implements the GSM encodings |
| 280 | 279 | * both the basic and the 'advanced'. Reliable transport is not |
| @@ -369,6 +368,7 @@ static const u8 gsm_fcs8[256] = { · 88 unmodified lines | ||
| 369 | 368 | #define GOOD_FCS 0xCF |
| 370 | 369 | |
| 371 | 370 | static int gsmld_output(struct gsm_mux *gsm, u8 *data, int len); |
| 371 | +static int gsm_modem_update(struct gsm_dlci *dlci, u8 brk); | |
| 372 | 372 | |
| 373 | 373 | /** |
| 374 | 374 | * gsm_fcs_add - update FCS |
| @@ -832,7 +832,7 @@ static int gsm_dlci_data_output(struct gsm_mux *gsm, struct gsm_dlci *dlci) · 457 unmodified lines | ||
| 832 | 832 | break; |
| 833 | 833 | case 2: /* Unstructed with modem bits. |
| 834 | 834 | Always one byte as we never send inline break data */ |
| 835 | − *dp++ = gsm_encode_modem(dlci); | |
| 835 | + *dp++ = (gsm_encode_modem(dlci) << 1) | EA; | |
| 836 | 836 | break; |
| 837 | 837 | } |
| 838 | 838 | WARN_ON(kfifo_out_locked(&dlci->fifo, dp , len, &dlci->lock) != len); |
| @@ -916,6 +916,66 @@ static int gsm_dlci_data_output_framed(struct gsm_mux *gsm, · 77 unmodified lines | ||
| 916 | 916 | return size; |
| 917 | 917 | } |
| 918 | 918 | |
| 919 | +/** | |
| 920 | + * gsm_dlci_modem_output - try and push modem status out of a DLCI | |
| 921 | + * @gsm: mux | |
| 922 | + * @dlci: the DLCI to pull modem status from | |
| 923 | + * @brk: break signal | |
| 924 | + * | |
| 925 | + * Push an empty frame in to the transmit queue to update the modem status | |
| 926 | + * bits and to transmit an optional break. | |
| 927 | + * | |
| 928 | + * Caller must hold the tx_lock of the mux. | |
| 929 | + */ | |
| 930 | + | |
| 931 | +static int gsm_dlci_modem_output(struct gsm_mux *gsm, struct gsm_dlci *dlci, | |
| 932 | + u8 brk) | |
| 933 | +{ | |
| 934 | + u8 *dp = NULL; | |
| 935 | + struct gsm_msg *msg; | |
| 936 | + int size = 0; | |
| 937 | + | |
| 938 | + /* for modem bits without break data */ | |
| 939 | + switch (dlci->adaption) { | |
| 940 | + case 1: /* Unstructured */ | |
| 941 | + break; | |
| 942 | + case 2: /* Unstructured with modem bits. */ | |
| 943 | + size++; | |
| 944 | + if (brk > 0) | |
| 945 | + size++; | |
| 946 | + break; | |
| 947 | + default: | |
| 948 | + pr_err("%s: unsupported adaption %d\n", __func__, | |
| 949 | + dlci->adaption); | |
| 950 | + return -EINVAL; | |
| 951 | + } | |
| 952 | + | |
| 953 | + msg = gsm_data_alloc(gsm, dlci->addr, size, gsm->ftype); | |
| 954 | + if (!msg) { | |
| 955 | + pr_err("%s: gsm_data_alloc error", __func__); | |
| 956 | + return -ENOMEM; | |
| 957 | + } | |
| 958 | + dp = msg->data; | |
| 959 | + switch (dlci->adaption) { | |
| 960 | + case 1: /* Unstructured */ | |
| 961 | + break; | |
| 962 | + case 2: /* Unstructured with modem bits. */ | |
| 963 | + if (brk == 0) { | |
| 964 | + *dp++ = (gsm_encode_modem(dlci) << 1) | EA; | |
| 965 | + } else { | |
| 966 | + *dp++ = gsm_encode_modem(dlci) << 1; | |
| 967 | + *dp++ = (brk << 4) | 2 | EA; /* Length, Break, EA */ | |
| 968 | + } | |
| 969 | + break; | |
| 970 | + default: | |
| 971 | + /* Handled above */ | |
| 972 | + break; | |
| 973 | + } | |
| 974 | + | |
| 975 | + __gsm_data_queue(dlci, msg); | |
| 976 | + return size; | |
| 977 | +} | |
| 978 | + | |
| 919 | 979 | /** |
| 920 | 980 | * gsm_dlci_data_sweep - look for data to send |
| 921 | 981 | * @gsm: the GSM mux |
| @@ -1093,7 +1153,6 @@ static void gsm_control_modem(struct gsm_mux *gsm, const u8 *data, int clen) · 171 unmodified lines | ||
| 1093 | 1153 | { |
| 1094 | 1154 | unsigned int addr = 0; |
| 1095 | 1155 | unsigned int modem = 0; |
| 1096 | − unsigned int brk = 0; | |
| 1097 | 1156 | struct gsm_dlci *dlci; |
| 1098 | 1157 | int len = clen; |
| 1099 | 1158 | int slen; |
| @@ -1123,17 +1182,8 @@ static void gsm_control_modem(struct gsm_mux *gsm, const u8 *data, int clen) · 23 unmodified lines | ||
| 1123 | 1182 | return; |
| 1124 | 1183 | } |
| 1125 | 1184 | len--; |
| 1126 | − if (len > 0) { | |
| 1127 | − while (gsm_read_ea(&brk, *dp++) == 0) { | |
| 1128 | − len--; | |
| 1129 | − if (len == 0) | |
| 1130 | − return; | |
| 1131 | − } | |
| 1132 | − modem <<= 7; | |
| 1133 | − modem |= (brk & 0x7f); | |
| 1134 | − } | |
| 1135 | 1185 | tty = tty_port_tty_get(&dlci->port); |
| 1136 | − gsm_process_modem(tty, dlci, modem, slen); | |
| 1186 | + gsm_process_modem(tty, dlci, modem, slen - len); | |
| 1137 | 1187 | if (tty) { |
| 1138 | 1188 | tty_wakeup(tty); |
| 1139 | 1189 | tty_kref_put(tty); |
| @@ -1193,7 +1243,6 @@ static void gsm_control_rls(struct gsm_mux *gsm, const u8 *data, int clen) · 53 unmodified lines | ||
| 1193 | 1243 | } |
| 1194 | 1244 | |
| 1195 | 1245 | static void gsm_dlci_begin_close(struct gsm_dlci *dlci); |
| 1196 | −static void gsm_dlci_close(struct gsm_dlci *dlci); | |
| 1197 | 1246 | |
| 1198 | 1247 | /** |
| 1199 | 1248 | * gsm_control_message - DLCI 0 control processing |
| @@ -1212,28 +1261,15 @@ static void gsm_control_message(struct gsm_mux *gsm, unsigned int command, · 12 unmodified lines | ||
| 1212 | 1261 | { |
| 1213 | 1262 | u8 buf[1]; |
| 1214 | 1263 | unsigned long flags; |
| 1215 | − struct gsm_dlci *dlci; | |
| 1216 | − int i; | |
| 1217 | − int address; | |
| 1218 | 1264 | |
| 1219 | 1265 | switch (command) { |
| 1220 | 1266 | case CMD_CLD: { |
| 1221 | − if (addr_cnt > 0) { | |
| 1222 | − for (i = 0; i < addr_cnt; i++) { | |
| 1223 | − address = addr_open[i]; | |
| 1224 | − dlci = gsm->dlci[address]; | |
| 1225 | − gsm_dlci_close(dlci); | |
| 1226 | − addr_open[i] = 0; | |
| 1227 | − } | |
| 1228 | − } | |
| 1267 | + struct gsm_dlci *dlci = gsm->dlci[0]; | |
| 1229 | 1268 | /* Modem wishes to close down */ |
| 1230 | − dlci = gsm->dlci[0]; | |
| 1231 | 1269 | if (dlci) { |
| 1232 | 1270 | dlci->dead = true; |
| 1233 | 1271 | gsm->dead = true; |
| 1234 | − gsm_dlci_close(dlci); | |
| 1235 | − addr_cnt = 0; | |
| 1236 | − gsm_response(gsm, 0, UA|PF); | |
| 1272 | + gsm_dlci_begin_close(dlci); | |
| 1237 | 1273 | } |
| 1238 | 1274 | } |
| 1239 | 1275 | break; |
| @@ -1326,11 +1362,12 @@ static void gsm_control_response(struct gsm_mux *gsm, unsigned int command, · 86 unmodified lines | ||
| 1326 | 1362 | |
| 1327 | 1363 | static void gsm_control_transmit(struct gsm_mux *gsm, struct gsm_control *ctrl) |
| 1328 | 1364 | { |
| 1329 | − struct gsm_msg *msg = gsm_data_alloc(gsm, 0, ctrl->len + 1, gsm->ftype); | |
| 1365 | + struct gsm_msg *msg = gsm_data_alloc(gsm, 0, ctrl->len + 2, gsm->ftype); | |
| 1330 | 1366 | if (msg == NULL) |
| 1331 | 1367 | return; |
| 1332 | − msg->data[0] = (ctrl->cmd << 1) | 2 | EA; /* command */ | |
| 1333 | − memcpy(msg->data + 1, ctrl->data, ctrl->len); | |
| 1368 | + msg->data[0] = (ctrl->cmd << 1) | CR | EA; /* command */ | |
| 1369 | + msg->data[1] = (ctrl->len << 1) | EA; | |
| 1370 | + memcpy(msg->data + 2, ctrl->data, ctrl->len); | |
| 1334 | 1371 | gsm_data_queue(gsm->dlci[0], msg); |
| 1335 | 1372 | } |
| 1336 | 1373 | |
| @@ -1353,7 +1390,6 @@ static void gsm_control_retransmit(struct timer_list *t) · 16 unmodified lines | ||
| 1353 | 1390 | spin_lock_irqsave(&gsm->control_lock, flags); |
| 1354 | 1391 | ctrl = gsm->pending_cmd; |
| 1355 | 1392 | if (ctrl) { |
| 1356 | − gsm->cretries--; | |
| 1357 | 1393 | if (gsm->cretries == 0) { |
| 1358 | 1394 | gsm->pending_cmd = NULL; |
| 1359 | 1395 | ctrl->error = -ETIMEDOUT; |
| @@ -1362,6 +1398,7 @@ static void gsm_control_retransmit(struct timer_list *t) · 2 unmodified lines | ||
| 1362 | 1398 | wake_up(&gsm->event); |
| 1363 | 1399 | return; |
| 1364 | 1400 | } |
| 1401 | + gsm->cretries--; | |
| 1365 | 1402 | gsm_control_transmit(gsm, ctrl); |
| 1366 | 1403 | mod_timer(&gsm->t2_timer, jiffies + gsm->t2 * HZ / 100); |
| 1367 | 1404 | } |
| @@ -1402,7 +1439,7 @@ retry: · 34 unmodified lines | ||
| 1402 | 1439 | |
| 1403 | 1440 | /* If DLCI0 is in ADM mode skip retries, it won't respond */ |
| 1404 | 1441 | if (gsm->dlci[0]->mode == DLCI_MODE_ADM) |
| 1405 | − gsm->cretries = 1; | |
| 1442 | + gsm->cretries = 0; | |
| 1406 | 1443 | else |
| 1407 | 1444 | gsm->cretries = gsm->n2; |
| 1408 | 1445 | |
| @@ -1450,20 +1487,22 @@ static int gsm_control_wait(struct gsm_mux *gsm, struct gsm_control *control) · 41 unmodified lines | ||
| 1450 | 1487 | |
| 1451 | 1488 | static void gsm_dlci_close(struct gsm_dlci *dlci) |
| 1452 | 1489 | { |
| 1490 | + unsigned long flags; | |
| 1491 | + | |
| 1453 | 1492 | del_timer(&dlci->t1); |
| 1454 | 1493 | if (debug & 8) |
| 1455 | 1494 | pr_debug("DLCI %d goes closed.\n", dlci->addr); |
| 1456 | 1495 | dlci->state = DLCI_CLOSED; |
| 1457 | 1496 | if (dlci->addr != 0) { |
| 1458 | 1497 | tty_port_tty_hangup(&dlci->port, false); |
| 1498 | + spin_lock_irqsave(&dlci->lock, flags); | |
| 1459 | 1499 | kfifo_reset(&dlci->fifo); |
| 1500 | + spin_unlock_irqrestore(&dlci->lock, flags); | |
| 1460 | 1501 | /* Ensure that gsmtty_open() can return. */ |
| 1461 | 1502 | tty_port_set_initialized(&dlci->port, 0); |
| 1462 | 1503 | wake_up_interruptible(&dlci->port.open_wait); |
| 1463 | 1504 | } else |
| 1464 | 1505 | dlci->gsm->dead = true; |
| 1465 | − /* Unregister gsmtty driver,report gsmtty dev remove uevent for user */ | |
| 1466 | − tty_unregister_device(gsm_tty_driver, dlci->addr); | |
| 1467 | 1506 | wake_up(&dlci->gsm->event); |
| 1468 | 1507 | /* A DLCI 0 close is a MUX termination so we need to kick that |
| 1469 | 1508 | back to userspace somehow */ |
| @@ -1485,8 +1524,9 @@ static void gsm_dlci_open(struct gsm_dlci *dlci) · 15 unmodified lines | ||
| 1485 | 1524 | dlci->state = DLCI_OPEN; |
| 1486 | 1525 | if (debug & 8) |
| 1487 | 1526 | pr_debug("DLCI %d goes open.\n", dlci->addr); |
| 1488 | − /* Register gsmtty driver,report gsmtty dev add uevent for user */ | |
| 1489 | − tty_register_device(gsm_tty_driver, dlci->addr, NULL); | |
| 1527 | + /* Send current modem state */ | |
| 1528 | + if (dlci->addr) | |
| 1529 | + gsm_modem_update(dlci, 0); | |
| 1490 | 1530 | wake_up(&dlci->gsm->event); |
| 1491 | 1531 | } |
| 1492 | 1532 | |
| @@ -1619,10 +1659,12 @@ static void gsm_dlci_data(struct gsm_dlci *dlci, const u8 *data, int clen) · 126 unmodified lines | ||
| 1619 | 1659 | if (len == 0) |
| 1620 | 1660 | return; |
| 1621 | 1661 | } |
| 1662 | + len--; | |
| 1622 | 1663 | slen++; |
| 1623 | 1664 | tty = tty_port_tty_get(port); |
| 1624 | 1665 | if (tty) { |
| 1625 | 1666 | gsm_process_modem(tty, dlci, modem, slen); |
| 1667 | + tty_wakeup(tty); | |
| 1626 | 1668 | tty_kref_put(tty); |
| 1627 | 1669 | } |
| 1628 | 1670 | fallthrough; |
| @@ -1690,7 +1732,7 @@ static struct gsm_dlci *gsm_dlci_alloc(struct gsm_mux *gsm, int addr) · 61 unmodified lines | ||
| 1690 | 1732 | return NULL; |
| 1691 | 1733 | spin_lock_init(&dlci->lock); |
| 1692 | 1734 | mutex_init(&dlci->mutex); |
| 1693 | − if (kfifo_alloc(&dlci->fifo, 4096, GFP_KERNEL) < 0) { | |
| 1735 | + if (kfifo_alloc(&dlci->fifo, TX_SIZE, GFP_KERNEL) < 0) { | |
| 1694 | 1736 | kfree(dlci); |
| 1695 | 1737 | return NULL; |
| 1696 | 1738 | } |
| @@ -1793,19 +1835,7 @@ static void gsm_queue(struct gsm_mux *gsm) · 96 unmodified lines | ||
| 1793 | 1835 | struct gsm_dlci *dlci; |
| 1794 | 1836 | u8 cr; |
| 1795 | 1837 | int address; |
| 1796 | − int i, j, k, address_tmp; | |
| 1797 | − /* We have to sneak a look at the packet body to do the FCS. | |
| 1798 | − A somewhat layering violation in the spec */ | |
| 1799 | 1838 | |
| 1800 | − if ((gsm->control & ~PF) == UI) | |
| 1801 | − gsm->fcs = gsm_fcs_add_block(gsm->fcs, gsm->buf, gsm->len); | |
| 1802 | − if (gsm->encoding == 0) { | |
| 1803 | − /* WARNING: gsm->received_fcs is used for | |
| 1804 | − gsm->encoding = 0 only. | |
| 1805 | − In this case it contain the last piece of data | |
| 1806 | − required to generate final CRC */ | |
| 1807 | − gsm->fcs = gsm_fcs_add(gsm->fcs, gsm->received_fcs); | |
| 1808 | − } | |
| 1809 | 1839 | if (gsm->fcs != GOOD_FCS) { |
| 1810 | 1840 | gsm->bad_fcs++; |
| 1811 | 1841 | if (debug & 4) |
| @@ -1836,11 +1866,6 @@ static void gsm_queue(struct gsm_mux *gsm) · 24 unmodified lines | ||
| 1836 | 1866 | else { |
| 1837 | 1867 | gsm_response(gsm, address, UA|PF); |
| 1838 | 1868 | gsm_dlci_open(dlci); |
| 1839 | − /* Save dlci open address */ | |
| 1840 | − if (address) { | |
| 1841 | − addr_open[addr_cnt] = address; | |
| 1842 | − addr_cnt++; | |
| 1843 | − } | |
| 1844 | 1869 | } |
| 1845 | 1870 | break; |
| 1846 | 1871 | case DISC|PF: |
| @@ -1851,35 +1876,9 @@ static void gsm_queue(struct gsm_mux *gsm) · 4 unmodified lines | ||
| 1851 | 1876 | return; |
| 1852 | 1877 | } |
| 1853 | 1878 | /* Real close complete */ |
| 1854 | − if (!address) { | |
| 1855 | − if (addr_cnt > 0) { | |
| 1856 | − for (i = 0; i < addr_cnt; i++) { | |
| 1857 | − address = addr_open[i]; | |
| 1858 | − dlci = gsm->dlci[address]; | |
| 1859 | − gsm_dlci_close(dlci); | |
| 1860 | − addr_open[i] = 0; | |
| 1861 | − } | |
| 1862 | − } | |
| 1863 | − dlci = gsm->dlci[0]; | |
| 1864 | − gsm_dlci_close(dlci); | |
| 1865 | − addr_cnt = 0; | |
| 1866 | − gsm_response(gsm, 0, UA|PF); | |
| 1867 | − } else { | |
| 1868 | − gsm_response(gsm, address, UA|PF); | |
| 1869 | − gsm_dlci_close(dlci); | |
| 1870 | − /* clear dlci address */ | |
| 1871 | − for (j = 0; j < addr_cnt; j++) { | |
| 1872 | − address_tmp = addr_open[j]; | |
| 1873 | − if (address_tmp == address) { | |
| 1874 | − for (k = j; k < addr_cnt; k++) | |
| 1875 | − addr_open[k] = addr_open[k+1]; | |
| 1876 | − addr_cnt--; | |
| 1877 | − break; | |
| 1878 | − } | |
| 1879 | − } | |
| 1880 | − } | |
| 1879 | + gsm_response(gsm, address, UA|PF); | |
| 1880 | + gsm_dlci_close(dlci); | |
| 1881 | 1881 | break; |
| 1882 | − case UA: | |
| 1883 | 1882 | case UA|PF: |
| 1884 | 1883 | if (cr == 0 || dlci == NULL) |
| 1885 | 1884 | break; |
| @@ -1993,19 +1992,25 @@ static void gsm0_receive(struct gsm_mux *gsm, unsigned char c) · 107 unmodified lines | ||
| 1993 | 1992 | break; |
| 1994 | 1993 | case GSM_DATA: /* Data */ |
| 1995 | 1994 | gsm->buf[gsm->count++] = c; |
| 1996 | − if (gsm->count == gsm->len) | |
| 1995 | + if (gsm->count == gsm->len) { | |
| 1996 | + /* Calculate final FCS for UI frames over all data */ | |
| 1997 | + if ((gsm->control & ~PF) != UIH) { | |
| 1998 | + gsm->fcs = gsm_fcs_add_block(gsm->fcs, gsm->buf, | |
| 1999 | + gsm->count); | |
| 2000 | + } | |
| 1997 | 2001 | gsm->state = GSM_FCS; |
| 2002 | + } | |
| 1998 | 2003 | break; |
| 1999 | 2004 | case GSM_FCS: /* FCS follows the packet */ |
| 2000 | − gsm->received_fcs = c; | |
| 2001 | − gsm_queue(gsm); | |
| 2005 | + gsm->fcs = gsm_fcs_add(gsm->fcs, c); | |
| 2002 | 2006 | gsm->state = GSM_SSOF; |
| 2003 | 2007 | break; |
| 2004 | 2008 | case GSM_SSOF: |
| 2005 | − if (c == GSM0_SOF) { | |
| 2006 | − gsm->state = GSM_SEARCH; | |
| 2007 | − break; | |
| 2008 | − } | |
| 2009 | + gsm->state = GSM_SEARCH; | |
| 2010 | + if (c == GSM0_SOF) | |
| 2011 | + gsm_queue(gsm); | |
| 2012 | + else | |
| 2013 | + gsm->bad_size++; | |
| 2009 | 2014 | break; |
| 2010 | 2015 | default: |
| 2011 | 2016 | pr_debug("%s: unhandled state: %d\n", __func__, gsm->state); |
| @@ -2023,12 +2028,35 @@ static void gsm0_receive(struct gsm_mux *gsm, unsigned char c) · 11 unmodified lines | ||
| 2023 | 2028 | |
| 2024 | 2029 | static void gsm1_receive(struct gsm_mux *gsm, unsigned char c) |
| 2025 | 2030 | { |
| 2031 | + /* handle XON/XOFF */ | |
| 2032 | + if ((c & ISO_IEC_646_MASK) == XON) { | |
| 2033 | + gsm->constipated = true; | |
| 2034 | + return; | |
| 2035 | + } else if ((c & ISO_IEC_646_MASK) == XOFF) { | |
| 2036 | + gsm->constipated = false; | |
| 2037 | + /* Kick the link in case it is idling */ | |
| 2038 | + gsm_data_kick(gsm, NULL); | |
| 2039 | + return; | |
| 2040 | + } | |
| 2026 | 2041 | if (c == GSM1_SOF) { |
| 2027 | − /* EOF is only valid in frame if we have got to the data state | |
| 2028 | − and received at least one byte (the FCS) */ | |
| 2029 | − if (gsm->state == GSM_DATA && gsm->count) { | |
| 2030 | − /* Extract the FCS */ | |
| 2042 | + /* EOF is only valid in frame if we have got to the data state */ | |
| 2043 | + if (gsm->state == GSM_DATA) { | |
| 2044 | + if (gsm->count < 1) { | |
| 2045 | + /* Missing FSC */ | |
| 2046 | + gsm->malformed++; | |
| 2047 | + gsm->state = GSM_START; | |
| 2048 | + return; | |
| 2049 | + } | |
| 2050 | + /* Remove the FCS from data */ | |
| 2031 | 2051 | gsm->count--; |
| 2052 | + if ((gsm->control & ~PF) != UIH) { | |
| 2053 | + /* Calculate final FCS for UI frames over all | |
| 2054 | + * data but FCS | |
| 2055 | + */ | |
| 2056 | + gsm->fcs = gsm_fcs_add_block(gsm->fcs, gsm->buf, | |
| 2057 | + gsm->count); | |
| 2058 | + } | |
| 2059 | + /* Add the FCS itself to test against GOOD_FCS */ | |
| 2032 | 2060 | gsm->fcs = gsm_fcs_add(gsm->fcs, gsm->buf[gsm->count]); |
| 2033 | 2061 | gsm->len = gsm->count; |
| 2034 | 2062 | gsm_queue(gsm); |
| @@ -2037,7 +2065,8 @@ static void gsm1_receive(struct gsm_mux *gsm, unsigned char c) · 2 unmodified lines | ||
| 2037 | 2065 | } |
| 2038 | 2066 | /* Any partial frame was a runt so go back to start */ |
| 2039 | 2067 | if (gsm->state != GSM_START) { |
| 2040 | − gsm->malformed++; | |
| 2068 | + if (gsm->state != GSM_SEARCH) | |
| 2069 | + gsm->malformed++; | |
| 2041 | 2070 | gsm->state = GSM_START; |
| 2042 | 2071 | } |
| 2043 | 2072 | /* A SOF in GSM_START means we are still reading idling or |
| @@ -2106,74 +2135,43 @@ static void gsm_error(struct gsm_mux *gsm) · 62 unmodified lines | ||
| 2106 | 2135 | gsm->io_error++; |
| 2107 | 2136 | } |
| 2108 | 2137 | |
| 2109 | −static int gsm_disconnect(struct gsm_mux *gsm) | |
| 2110 | −{ | |
| 2111 | − struct gsm_dlci *dlci = gsm->dlci[0]; | |
| 2112 | − struct gsm_control *gc; | |
| 2113 | − | |
| 2114 | − if (!dlci) | |
| 2115 | − return 0; | |
| 2116 | − | |
| 2117 | − /* In theory disconnecting DLCI 0 is sufficient but for some | |
| 2118 | − modems this is apparently not the case. */ | |
| 2119 | − gc = gsm_control_send(gsm, CMD_CLD, NULL, 0); | |
| 2120 | − if (gc) | |
| 2121 | − gsm_control_wait(gsm, gc); | |
| 2122 | − | |
| 2123 | − del_timer_sync(&gsm->t2_timer); | |
| 2124 | − /* Now we are sure T2 has stopped */ | |
| 2125 | − | |
| 2126 | − gsm_dlci_begin_close(dlci); | |
| 2127 | − wait_event_interruptible(gsm->event, | |
| 2128 | − dlci->state == DLCI_CLOSED); | |
| 2129 | − | |
| 2130 | − if (signal_pending(current)) | |
| 2131 | − return -EINTR; | |
| 2132 | − | |
| 2133 | − return 0; | |
| 2134 | −} | |
| 2135 | − | |
| 2136 | 2138 | /** |
| 2137 | 2139 | * gsm_cleanup_mux - generic GSM protocol cleanup |
| 2138 | 2140 | * @gsm: our mux |
| 2141 | + * @disc: disconnect link? | |
| 2139 | 2142 | * |
| 2140 | 2143 | * Clean up the bits of the mux which are the same for all framing |
| 2141 | 2144 | * protocols. Remove the mux from the mux table, stop all the timers |
| 2142 | 2145 | * and then shut down each device hanging up the channels as we go. |
| 2143 | 2146 | */ |
| 2144 | 2147 | |
| 2145 | −static void gsm_cleanup_mux(struct gsm_mux *gsm) | |
| 2148 | +static void gsm_cleanup_mux(struct gsm_mux *gsm, bool disc) | |
| 2146 | 2149 | { |
| 2147 | 2150 | int i; |
| 2148 | 2151 | struct gsm_dlci *dlci = gsm->dlci[0]; |
| 2149 | 2152 | struct gsm_msg *txq, *ntxq; |
| 2150 | 2153 | |
| 2151 | 2154 | gsm->dead = true; |
| 2155 | + mutex_lock(&gsm->mutex); | |
| 2152 | 2156 | |
| 2153 | − spin_lock(&gsm_mux_lock); | |
| 2154 | − for (i = 0; i < MAX_MUX; i++) { | |
| 2155 | − if (gsm_mux[i] == gsm) { | |
| 2156 | − gsm_mux[i] = NULL; | |
| 2157 | − break; | |
| 2157 | + if (dlci) { | |
| 2158 | + if (disc && dlci->state != DLCI_CLOSED) { | |
| 2159 | + gsm_dlci_begin_close(dlci); | |
| 2160 | + wait_event(gsm->event, dlci->state == DLCI_CLOSED); | |
| 2158 | 2161 | } |
| 2162 | + dlci->dead = true; | |
| 2159 | 2163 | } |
| 2160 | − spin_unlock(&gsm_mux_lock); | |
| 2161 | − /* open failed before registering => nothing to do */ | |
| 2162 | − if (i == MAX_MUX) | |
| 2163 | − return; | |
| 2164 | 2164 | |
| 2165 | + /* Finish outstanding timers, making sure they are done */ | |
| 2165 | 2166 | del_timer_sync(&gsm->t2_timer); |
| 2166 | − /* Now we are sure T2 has stopped */ | |
| 2167 | − if (dlci) | |
| 2168 | − dlci->dead = true; | |
| 2169 | 2167 | |
| 2170 | − /* Free up any link layer users */ | |
| 2171 | − mutex_lock(&gsm->mutex); | |
| 2172 | − for (i = 0; i < NUM_DLCI; i++) | |
| 2168 | + /* Free up any link layer users and finally the control channel */ | |
| 2169 | + for (i = NUM_DLCI - 1; i >= 0; i--) | |
| 2173 | 2170 | if (gsm->dlci[i]) |
| 2174 | 2171 | gsm_dlci_release(gsm->dlci[i]); |
| 2175 | 2172 | mutex_unlock(&gsm->mutex); |
| 2176 | 2173 | /* Now wipe the queues */ |
| 2174 | + tty_ldisc_flush(gsm->tty); | |
| 2177 | 2175 | list_for_each_entry_safe(txq, ntxq, &gsm->tx_list, list) |
| 2178 | 2176 | kfree(txq); |
| 2179 | 2177 | INIT_LIST_HEAD(&gsm->tx_list); |
| @@ -2191,7 +2189,6 @@ static void gsm_cleanup_mux(struct gsm_mux *gsm) · 11 unmodified lines | ||
| 2191 | 2189 | static int gsm_activate_mux(struct gsm_mux *gsm) |
| 2192 | 2190 | { |
| 2193 | 2191 | struct gsm_dlci *dlci; |
| 2194 | − int i = 0; | |
| 2195 | 2192 | |
| 2196 | 2193 | timer_setup(&gsm->t2_timer, gsm_control_retransmit, 0); |
| 2197 | 2194 | init_waitqueue_head(&gsm->event); |
| @@ -2203,18 +2200,6 @@ static int gsm_activate_mux(struct gsm_mux *gsm) · 5 unmodified lines | ||
| 2203 | 2200 | else |
| 2204 | 2201 | gsm->receive = gsm1_receive; |
| 2205 | 2202 | |
| 2206 | − spin_lock(&gsm_mux_lock); | |
| 2207 | − for (i = 0; i < MAX_MUX; i++) { | |
| 2208 | − if (gsm_mux[i] == NULL) { | |
| 2209 | − gsm->num = i; | |
| 2210 | − gsm_mux[i] = gsm; | |
| 2211 | − break; | |
| 2212 | − } | |
| 2213 | − } | |
| 2214 | − spin_unlock(&gsm_mux_lock); | |
| 2215 | − if (i == MAX_MUX) | |
| 2216 | − return -EBUSY; | |
| 2217 | − | |
| 2218 | 2203 | dlci = gsm_dlci_alloc(gsm, 0); |
| 2219 | 2204 | if (dlci == NULL) |
| 2220 | 2205 | return -ENOMEM; |
| @@ -2230,6 +2215,15 @@ static int gsm_activate_mux(struct gsm_mux *gsm) · 9 unmodified lines | ||
| 2230 | 2215 | */ |
| 2231 | 2216 | static void gsm_free_mux(struct gsm_mux *gsm) |
| 2232 | 2217 | { |
| 2218 | + int i; | |
| 2219 | + | |
| 2220 | + for (i = 0; i < MAX_MUX; i++) { | |
| 2221 | + if (gsm == gsm_mux[i]) { | |
| 2222 | + gsm_mux[i] = NULL; | |
| 2223 | + break; | |
| 2224 | + } | |
| 2225 | + } | |
| 2226 | + mutex_destroy(&gsm->mutex); | |
| 2233 | 2227 | kfree(gsm->txframe); |
| 2234 | 2228 | kfree(gsm->buf); |
| 2235 | 2229 | kfree(gsm); |
| @@ -2249,12 +2243,20 @@ static void gsm_free_muxr(struct kref *ref) · 13 unmodified lines | ||
| 2249 | 2243 | |
| 2250 | 2244 | static inline void mux_get(struct gsm_mux *gsm) |
| 2251 | 2245 | { |
| 2246 | + unsigned long flags; | |
| 2247 | + | |
| 2248 | + spin_lock_irqsave(&gsm_mux_lock, flags); | |
| 2252 | 2249 | kref_get(&gsm->ref); |
| 2250 | + spin_unlock_irqrestore(&gsm_mux_lock, flags); | |
| 2253 | 2251 | } |
| 2254 | 2252 | |
| 2255 | 2253 | static inline void mux_put(struct gsm_mux *gsm) |
| 2256 | 2254 | { |
| 2255 | + unsigned long flags; | |
| 2256 | + | |
| 2257 | + spin_lock_irqsave(&gsm_mux_lock, flags); | |
| 2257 | 2258 | kref_put(&gsm->ref, gsm_free_muxr); |
| 2259 | + spin_unlock_irqrestore(&gsm_mux_lock, flags); | |
| 2258 | 2260 | } |
| 2259 | 2261 | |
| 2260 | 2262 | static inline unsigned int mux_num_to_base(struct gsm_mux *gsm) |
| @@ -2275,6 +2277,7 @@ static inline unsigned int mux_line_to_num(unsigned int line) · 14 unmodified lines | ||
| 2275 | 2277 | |
| 2276 | 2278 | static struct gsm_mux *gsm_alloc_mux(void) |
| 2277 | 2279 | { |
| 2280 | + int i; | |
| 2278 | 2281 | struct gsm_mux *gsm = kzalloc(sizeof(struct gsm_mux), GFP_KERNEL); |
| 2279 | 2282 | if (gsm == NULL) |
| 2280 | 2283 | return NULL; |
| @@ -2283,7 +2286,7 @@ static struct gsm_mux *gsm_alloc_mux(void) · 2 unmodified lines | ||
| 2283 | 2286 | kfree(gsm); |
| 2284 | 2287 | return NULL; |
| 2285 | 2288 | } |
| 2286 | − gsm->txframe = kmalloc(2 * MAX_MRU + 2, GFP_KERNEL); | |
| 2289 | + gsm->txframe = kmalloc(2 * (MAX_MTU + PROT_OVERHEAD - 1), GFP_KERNEL); | |
| 2287 | 2290 | if (gsm->txframe == NULL) { |
| 2288 | 2291 | kfree(gsm->buf); |
| 2289 | 2292 | kfree(gsm); |
| @@ -2304,6 +2307,26 @@ static struct gsm_mux *gsm_alloc_mux(void) · 14 unmodified lines | ||
| 2304 | 2307 | gsm->mtu = 64; |
| 2305 | 2308 | gsm->dead = true; /* Avoid early tty opens */ |
| 2306 | 2309 | |
| 2310 | + /* Store the instance to the mux array or abort if no space is | |
| 2311 | + * available. | |
| 2312 | + */ | |
| 2313 | + spin_lock(&gsm_mux_lock); | |
| 2314 | + for (i = 0; i < MAX_MUX; i++) { | |
| 2315 | + if (!gsm_mux[i]) { | |
| 2316 | + gsm_mux[i] = gsm; | |
| 2317 | + gsm->num = i; | |
| 2318 | + break; | |
| 2319 | + } | |
| 2320 | + } | |
| 2321 | + spin_unlock(&gsm_mux_lock); | |
| 2322 | + if (i == MAX_MUX) { | |
| 2323 | + mutex_destroy(&gsm->mutex); | |
| 2324 | + kfree(gsm->txframe); | |
| 2325 | + kfree(gsm->buf); | |
| 2326 | + kfree(gsm); | |
| 2327 | + return NULL; | |
| 2328 | + } | |
| 2329 | + | |
| 2307 | 2330 | return gsm; |
| 2308 | 2331 | } |
| 2309 | 2332 | |
| @@ -2330,6 +2353,7 @@ static void gsm_copy_config_values(struct gsm_mux *gsm, · 20 unmodified lines | ||
| 2330 | 2353 | |
| 2331 | 2354 | static int gsm_config(struct gsm_mux *gsm, struct gsm_config *c) |
| 2332 | 2355 | { |
| 2356 | + int ret = 0; | |
| 2333 | 2357 | int need_close = 0; |
| 2334 | 2358 | int need_restart = 0; |
| 2335 | 2359 | |
| @@ -2339,7 +2363,7 @@ static int gsm_config(struct gsm_mux *gsm, struct gsm_config *c) · 3 unmodified lines | ||
| 2339 | 2363 | /* Check the MRU/MTU range looks sane */ |
| 2340 | 2364 | if (c->mru > MAX_MRU || c->mtu > MAX_MTU || c->mru < 8 || c->mtu < 8) |
| 2341 | 2365 | return -EINVAL; |
| 2342 | − if (c->n2 < 3) | |
| 2366 | + if (c->n2 > 255) | |
| 2343 | 2367 | return -EINVAL; |
| 2344 | 2368 | if (c->encapsulation > 1) /* Basic, advanced, no I */ |
| 2345 | 2369 | return -EINVAL; |
| @@ -2370,19 +2394,11 @@ static int gsm_config(struct gsm_mux *gsm, struct gsm_config *c) · 24 unmodified lines | ||
| 2370 | 2394 | |
| 2371 | 2395 | /* |
| 2372 | 2396 | * Close down what is needed, restart and initiate the new |
| 2373 | − * configuration | |
| 2397 | + * configuration. On the first time there is no DLCI[0] | |
| 2398 | + * and closing or cleaning up is not necessary. | |
| 2374 | 2399 | */ |
| 2375 | − | |
| 2376 | − if (gsm->initiator && (need_close || need_restart)) { | |
| 2377 | − int ret; | |
| 2378 | − | |
| 2379 | − ret = gsm_disconnect(gsm); | |
| 2380 | − | |
| 2381 | − if (ret) | |
| 2382 | − return ret; | |
| 2383 | − } | |
| 2384 | − if (need_restart) | |
| 2385 | − gsm_cleanup_mux(gsm); | |
| 2400 | + if (need_close || need_restart) | |
| 2401 | + gsm_cleanup_mux(gsm, true); | |
| 2386 | 2402 | |
| 2387 | 2403 | gsm->initiator = c->initiator; |
| 2388 | 2404 | gsm->mru = c->mru; |
| @@ -2405,10 +2421,13 @@ static int gsm_config(struct gsm_mux *gsm, struct gsm_config *c) · 16 unmodified lines | ||
| 2405 | 2421 | * FIXME: We need to separate activation/deactivation from adding |
| 2406 | 2422 | * and removing from the mux array |
| 2407 | 2423 | */ |
| 2408 | − if (need_restart) | |
| 2409 | − gsm_activate_mux(gsm); | |
| 2410 | − if (gsm->initiator && need_close) | |
| 2411 | − gsm_dlci_begin_open(gsm->dlci[0]); | |
| 2424 | + if (gsm->dead) { | |
| 2425 | + ret = gsm_activate_mux(gsm); | |
| 2426 | + if (ret) | |
| 2427 | + return ret; | |
| 2428 | + if (gsm->initiator) | |
| 2429 | + gsm_dlci_begin_open(gsm->dlci[0]); | |
| 2430 | + } | |
| 2412 | 2431 | return 0; |
| 2413 | 2432 | } |
| 2414 | 2433 | |
| @@ -2450,25 +2469,26 @@ static int gsmld_attach_gsm(struct tty_struct *tty, struct gsm_mux *gsm) · 35 unmodified lines | ||
| 2450 | 2469 | int ret, i; |
| 2451 | 2470 | |
| 2452 | 2471 | gsm->tty = tty_kref_get(tty); |
| 2472 | + /* Turn off tty XON/XOFF handling to handle it explicitly. */ | |
| 2473 | + gsm->old_c_iflag = tty->termios.c_iflag; | |
| 2474 | + tty->termios.c_iflag &= (IXON | IXOFF); | |
| 2453 | 2475 | ret = gsm_activate_mux(gsm); |
| 2454 | 2476 | if (ret != 0) |
| 2455 | 2477 | tty_kref_put(gsm->tty); |
| 2456 | 2478 | else { |
| 2457 | 2479 | /* Don't register device 0 - this is the control channel and not |
| 2458 | 2480 | a usable tty interface */ |
| 2459 | − if (gsm->initiator) { | |
| 2460 | − base = mux_num_to_base(gsm); /* Base for this MUX */ | |
| 2461 | − for (i = 1; i < NUM_DLCI; i++) { | |
| 2462 | − struct device *dev; | |
| 2481 | + base = mux_num_to_base(gsm); /* Base for this MUX */ | |
| 2482 | + for (i = 1; i < NUM_DLCI; i++) { | |
| 2483 | + struct device *dev; | |
| 2463 | 2484 | |
| 2464 | − dev = tty_register_device(gsm_tty_driver, | |
| 2485 | + dev = tty_register_device(gsm_tty_driver, | |
| 2465 | 2486 | base + i, NULL); |
| 2466 | − if (IS_ERR(dev)) { | |
| 2467 | − for (i--; i >= 1; i--) | |
| 2468 | − tty_unregister_device(gsm_tty_driver, | |
| 2469 | − base + i); | |
| 2470 | − return PTR_ERR(dev); | |
| 2471 | − } | |
| 2487 | + if (IS_ERR(dev)) { | |
| 2488 | + for (i--; i >= 1; i--) | |
| 2489 | + tty_unregister_device(gsm_tty_driver, | |
| 2490 | + base + i); | |
| 2491 | + return PTR_ERR(dev); | |
| 2472 | 2492 | } |
| 2473 | 2493 | } |
| 2474 | 2494 | } |
| @@ -2490,11 +2510,10 @@ static void gsmld_detach_gsm(struct tty_struct *tty, struct gsm_mux *gsm) · 15 unmodified lines | ||
| 2490 | 2510 | int i; |
| 2491 | 2511 | |
| 2492 | 2512 | WARN_ON(tty != gsm->tty); |
| 2493 | − if (gsm->initiator) { | |
| 2494 | − for (i = 1; i < NUM_DLCI; i++) | |
| 2495 | − tty_unregister_device(gsm_tty_driver, base + i); | |
| 2496 | − } | |
| 2497 | − gsm_cleanup_mux(gsm); | |
| 2513 | + for (i = 1; i < NUM_DLCI; i++) | |
| 2514 | + tty_unregister_device(gsm_tty_driver, base + i); | |
| 2515 | + /* Restore tty XON/XOFF handling. */ | |
| 2516 | + gsm->tty->termios.c_iflag = gsm->old_c_iflag; | |
| 2498 | 2517 | tty_kref_put(gsm->tty); |
| 2499 | 2518 | gsm->tty = NULL; |
| 2500 | 2519 | } |
| @@ -2559,6 +2578,12 @@ static void gsmld_close(struct tty_struct *tty) · 58 unmodified lines | ||
| 2559 | 2578 | { |
| 2560 | 2579 | struct gsm_mux *gsm = tty->disc_data; |
| 2561 | 2580 | |
| 2581 | + /* The ldisc locks and closes the port before calling our close. This | |
| 2582 | + * means we have no way to do a proper disconnect. We will not bother | |
| 2583 | + * to do one. | |
| 2584 | + */ | |
| 2585 | + gsm_cleanup_mux(gsm, false); | |
| 2586 | + | |
| 2562 | 2587 | gsmld_detach_gsm(tty, gsm); |
| 2563 | 2588 | |
| 2564 | 2589 | gsmld_flush_buffer(tty); |
| @@ -2597,7 +2622,7 @@ static int gsmld_open(struct tty_struct *tty) · 32 unmodified lines | ||
| 2597 | 2622 | |
| 2598 | 2623 | ret = gsmld_attach_gsm(tty, gsm); |
| 2599 | 2624 | if (ret != 0) { |
| 2600 | − gsm_cleanup_mux(gsm); | |
| 2625 | + gsm_cleanup_mux(gsm, false); | |
| 2601 | 2626 | mux_put(gsm); |
| 2602 | 2627 | } |
| 2603 | 2628 | return ret; |
| @@ -2952,28 +2977,78 @@ static struct tty_ldisc_ops tty_ldisc_packet = { · 348 unmodified lines | ||
| 2952 | 2977 | * Virtual tty side |
| 2953 | 2978 | */ |
| 2954 | 2979 | |
| 2955 | −#define TX_SIZE 512 | |
| 2980 | +/** | |
| 2981 | + * gsm_modem_upd_via_data - send modem bits via convergence layer | |
| 2982 | + * @dlci: channel | |
| 2983 | + * @brk: break signal | |
| 2984 | + * | |
| 2985 | + * Send an empty frame to signal mobile state changes and to transmit the | |
| 2986 | + * break signal for adaption 2. | |
| 2987 | + */ | |
| 2988 | + | |
| 2989 | +static void gsm_modem_upd_via_data(struct gsm_dlci *dlci, u8 brk) | |
| 2990 | +{ | |
| 2991 | + struct gsm_mux *gsm = dlci->gsm; | |
| 2992 | + unsigned long flags; | |
| 2993 | + | |
| 2994 | + if (dlci->state != DLCI_OPEN || dlci->adaption != 2) | |
| 2995 | + return; | |
| 2996 | + | |
| 2997 | + spin_lock_irqsave(&gsm->tx_lock, flags); | |
| 2998 | + gsm_dlci_modem_output(gsm, dlci, brk); | |
| 2999 | + spin_unlock_irqrestore(&gsm->tx_lock, flags); | |
| 3000 | +} | |
| 3001 | + | |
| 3002 | +/** | |
| 3003 | + * gsm_modem_upd_via_msc - send modem bits via control frame | |
| 3004 | + * @dlci: channel | |
| 3005 | + * @brk: break signal | |
| 3006 | + */ | |
| 2956 | 3007 | |
| 2957 | −static int gsmtty_modem_update(struct gsm_dlci *dlci, u8 brk) | |
| 3008 | +static int gsm_modem_upd_via_msc(struct gsm_dlci *dlci, u8 brk) | |
| 2958 | 3009 | { |
| 2959 | − u8 modembits[5]; | |
| 3010 | + u8 modembits[3]; | |
| 2960 | 3011 | struct gsm_control *ctrl; |
| 2961 | 3012 | int len = 2; |
| 2962 | 3013 | |
| 2963 | − if (brk) | |
| 2964 | − len++; | |
| 3014 | + if (dlci->gsm->encoding != 0) | |
| 3015 | + return 0; | |
| 2965 | 3016 | |
| 2966 | − modembits[0] = len << 1 | EA; /* Data bytes */ | |
| 2967 | − modembits[1] = dlci->addr << 2 | 3; /* DLCI, EA, 1 */ | |
| 2968 | − modembits[2] = gsm_encode_modem(dlci) << 1 | EA; | |
| 2969 | − if (brk) | |
| 2970 | − modembits[3] = brk << 4 | 2 | EA; /* Valid, EA */ | |
| 2971 | − ctrl = gsm_control_send(dlci->gsm, CMD_MSC, modembits, len + 1); | |
| 3017 | + modembits[0] = (dlci->addr << 2) | 2 | EA; /* DLCI, Valid, EA */ | |
| 3018 | + if (!brk) { | |
| 3019 | + modembits[1] = (gsm_encode_modem(dlci) << 1) | EA; | |
| 3020 | + } else { | |
| 3021 | + modembits[1] = gsm_encode_modem(dlci) << 1; | |
| 3022 | + modembits[2] = (brk << 4) | 2 | EA; /* Length, Break, EA */ | |
| 3023 | + len++; | |
| 3024 | + } | |
| 3025 | + ctrl = gsm_control_send(dlci->gsm, CMD_MSC, modembits, len); | |
| 2972 | 3026 | if (ctrl == NULL) |
| 2973 | 3027 | return -ENOMEM; |
| 2974 | 3028 | return gsm_control_wait(dlci->gsm, ctrl); |
| 2975 | 3029 | } |
| 2976 | 3030 | |
| 3031 | +/** | |
| 3032 | + * gsm_modem_update - send modem status line state | |
| 3033 | + * @dlci: channel | |
| 3034 | + * @brk: break signal | |
| 3035 | + */ | |
| 3036 | + | |
| 3037 | +static int gsm_modem_update(struct gsm_dlci *dlci, u8 brk) | |
| 3038 | +{ | |
| 3039 | + if (dlci->adaption == 2) { | |
| 3040 | + /* Send convergence layer type 2 empty data frame. */ | |
| 3041 | + gsm_modem_upd_via_data(dlci, brk); | |
| 3042 | + return 0; | |
| 3043 | + } else if (dlci->gsm->encoding == 0) { | |
| 3044 | + /* Send as MSC control message. */ | |
| 3045 | + return gsm_modem_upd_via_msc(dlci, brk); | |
| 3046 | + } | |
| 3047 | + | |
| 3048 | + /* Modem status lines are not supported. */ | |
| 3049 | + return -EPROTONOSUPPORT; | |
| 3050 | +} | |
| 3051 | + | |
| 2977 | 3052 | static int gsm_carrier_raised(struct tty_port *port) |
| 2978 | 3053 | { |
| 2979 | 3054 | struct gsm_dlci *dlci = container_of(port, struct gsm_dlci, port); |
| @@ -3006,7 +3081,7 @@ static void gsm_dtr_rts(struct tty_port *port, int onoff) · 26 unmodified lines | ||
| 3006 | 3081 | modem_tx &= ~(TIOCM_DTR | TIOCM_RTS); |
| 3007 | 3082 | if (modem_tx != dlci->modem_tx) { |
| 3008 | 3083 | dlci->modem_tx = modem_tx; |
| 3009 | − gsmtty_modem_update(dlci, 0); | |
| 3084 | + gsm_modem_update(dlci, 0); | |
| 3010 | 3085 | } |
| 3011 | 3086 | } |
| 3012 | 3087 | |
| @@ -3141,7 +3216,7 @@ static unsigned int gsmtty_write_room(struct tty_struct *tty) · 128 unmodified lines | ||
| 3141 | 3216 | struct gsm_dlci *dlci = tty->driver_data; |
| 3142 | 3217 | if (dlci->state == DLCI_CLOSED) |
| 3143 | 3218 | return 0; |
| 3144 | − return TX_SIZE - kfifo_len(&dlci->fifo); | |
| 3219 | + return kfifo_avail(&dlci->fifo); | |
| 3145 | 3220 | } |
| 3146 | 3221 | |
| 3147 | 3222 | static unsigned int gsmtty_chars_in_buffer(struct tty_struct *tty) |
| @@ -3155,13 +3230,17 @@ static unsigned int gsmtty_chars_in_buffer(struct tty_struct *tty) · 7 unmodified lines | ||
| 3155 | 3230 | static void gsmtty_flush_buffer(struct tty_struct *tty) |
| 3156 | 3231 | { |
| 3157 | 3232 | struct gsm_dlci *dlci = tty->driver_data; |
| 3233 | + unsigned long flags; | |
| 3234 | + | |
| 3158 | 3235 | if (dlci->state == DLCI_CLOSED) |
| 3159 | 3236 | return; |
| 3160 | 3237 | /* Caution needed: If we implement reliable transport classes |
| 3161 | 3238 | then the data being transmitted can't simply be junked once |
| 3162 | 3239 | it has first hit the stack. Until then we can just blow it |
| 3163 | 3240 | away */ |
| 3241 | + spin_lock_irqsave(&dlci->lock, flags); | |
| 3164 | 3242 | kfifo_reset(&dlci->fifo); |
| 3243 | + spin_unlock_irqrestore(&dlci->lock, flags); | |
| 3165 | 3244 | /* Need to unhook this DLCI from the transmit queue logic */ |
| 3166 | 3245 | } |
| 3167 | 3246 | |
| @@ -3193,7 +3272,7 @@ static int gsmtty_tiocmset(struct tty_struct *tty, · 25 unmodified lines | ||
| 3193 | 3272 | |
| 3194 | 3273 | if (modem_tx != dlci->modem_tx) { |
| 3195 | 3274 | dlci->modem_tx = modem_tx; |
| 3196 | − return gsmtty_modem_update(dlci, 0); | |
| 3275 | + return gsm_modem_update(dlci, 0); | |
| 3197 | 3276 | } |
| 3198 | 3277 | return 0; |
| 3199 | 3278 | } |
| @@ -3254,7 +3333,7 @@ static void gsmtty_throttle(struct tty_struct *tty) · 54 unmodified lines | ||
| 3254 | 3333 | dlci->modem_tx &= ~TIOCM_RTS; |
| 3255 | 3334 | dlci->throttled = true; |
| 3256 | 3335 | /* Send an MSC with RTS cleared */ |
| 3257 | − gsmtty_modem_update(dlci, 0); | |
| 3336 | + gsm_modem_update(dlci, 0); | |
| 3258 | 3337 | } |
| 3259 | 3338 | |
| 3260 | 3339 | static void gsmtty_unthrottle(struct tty_struct *tty) |
| @@ -3266,7 +3345,7 @@ static void gsmtty_unthrottle(struct tty_struct *tty) · 5 unmodified lines | ||
| 3266 | 3345 | dlci->modem_tx |= TIOCM_RTS; |
| 3267 | 3346 | dlci->throttled = false; |
| 3268 | 3347 | /* Send an MSC with RTS set */ |
| 3269 | − gsmtty_modem_update(dlci, 0); | |
| 3348 | + gsm_modem_update(dlci, 0); | |
| 3270 | 3349 | } |
| 3271 | 3350 | |
| 3272 | 3351 | static int gsmtty_break_ctl(struct tty_struct *tty, int state) |
| @@ -3284,7 +3363,7 @@ static int gsmtty_break_ctl(struct tty_struct *tty, int state) · 11 unmodified lines | ||
| 3284 | 3363 | if (encode > 0x0F) |
| 3285 | 3364 | encode = 0x0F; /* Best effort */ |
| 3286 | 3365 | } |
| 3287 | − return gsmtty_modem_update(dlci, encode); | |
| 3366 | + return gsm_modem_update(dlci, encode); | |
| 3288 | 3367 | } |
| 3289 | 3368 | |
| 3290 | 3369 | static void gsmtty_cleanup(struct tty_struct *tty) |
| @@ -37,6 +37,7 @@ · 36 unmodified lines | ||
| 37 | 37 | #define MTK_UART_IER_RTSI 0x40 /* Enable RTS Modem status interrupt */ |
| 38 | 38 | #define MTK_UART_IER_CTSI 0x80 /* Enable CTS Modem status interrupt */ |
| 39 | 39 | |
| 40 | +#define MTK_UART_EFR 38 /* I/O: Extended Features Register */ | |
| 40 | 41 | #define MTK_UART_EFR_EN 0x10 /* Enable enhancement feature */ |
| 41 | 42 | #define MTK_UART_EFR_RTS 0x40 /* Enable hardware rx flow control */ |
| 42 | 43 | #define MTK_UART_EFR_CTS 0x80 /* Enable hardware tx flow control */ |
| @@ -53,6 +54,12 @@ · 10 unmodified lines | ||
| 53 | 54 | #define MTK_UART_TX_TRIGGER 1 |
| 54 | 55 | #define MTK_UART_RX_TRIGGER MTK_UART_RX_SIZE |
| 55 | 56 | |
| 57 | +#define MTK_UART_FEATURE_SEL 39 /* Feature Selection register */ | |
| 58 | +#define MTK_UART_FEAT_NEWRMAP BIT(0) /* Use new register map */ | |
| 59 | + | |
| 60 | +#define MTK_UART_XON1 40 /* I/O: Xon character 1 */ | |
| 61 | +#define MTK_UART_XOFF1 42 /* I/O: Xoff character 1 */ | |
| 62 | + | |
| 56 | 63 | #ifdef CONFIG_SERIAL_8250_DMA |
| 57 | 64 | enum dma_rx_status { |
| 58 | 65 | DMA_RX_START = 0, |
| @@ -169,7 +176,7 @@ static void mtk8250_dma_enable(struct uart_8250_port *up) · 110 unmodified lines | ||
| 169 | 176 | MTK_UART_DMA_EN_RX | MTK_UART_DMA_EN_TX); |
| 170 | 177 | |
| 171 | 178 | serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B); |
| 172 | − serial_out(up, UART_EFR, UART_EFR_ECB); | |
| 179 | + serial_out(up, MTK_UART_EFR, UART_EFR_ECB); | |
| 173 | 180 | serial_out(up, UART_LCR, lcr); |
| 174 | 181 | |
| 175 | 182 | if (dmaengine_slave_config(dma->rxchan, &dma->rxconf) != 0) |
| @@ -232,7 +239,7 @@ static void mtk8250_set_flow_ctrl(struct uart_8250_port *up, int mode) · 56 unmodified lines | ||
| 232 | 239 | int lcr = serial_in(up, UART_LCR); |
| 233 | 240 | |
| 234 | 241 | serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B); |
| 235 | − serial_out(up, UART_EFR, UART_EFR_ECB); | |
| 242 | + serial_out(up, MTK_UART_EFR, UART_EFR_ECB); | |
| 236 | 243 | serial_out(up, UART_LCR, lcr); |
| 237 | 244 | lcr = serial_in(up, UART_LCR); |
| 238 | 245 | |
| @@ -241,7 +248,7 @@ static void mtk8250_set_flow_ctrl(struct uart_8250_port *up, int mode) · 2 unmodified lines | ||
| 241 | 248 | serial_out(up, MTK_UART_ESCAPE_DAT, MTK_UART_ESCAPE_CHAR); |
| 242 | 249 | serial_out(up, MTK_UART_ESCAPE_EN, 0x00); |
| 243 | 250 | serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B); |
| 244 | − serial_out(up, UART_EFR, serial_in(up, UART_EFR) & | |
| 251 | + serial_out(up, MTK_UART_EFR, serial_in(up, MTK_UART_EFR) & | |
| 245 | 252 | (~(MTK_UART_EFR_HW_FC | MTK_UART_EFR_SW_FC_MASK))); |
| 246 | 253 | serial_out(up, UART_LCR, lcr); |
| 247 | 254 | mtk8250_disable_intrs(up, MTK_UART_IER_XOFFI | |
| @@ -255,8 +262,8 @@ static void mtk8250_set_flow_ctrl(struct uart_8250_port *up, int mode) · 7 unmodified lines | ||
| 255 | 262 | serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B); |
| 256 | 263 | |
| 257 | 264 | /*enable hw flow control*/ |
| 258 | − serial_out(up, UART_EFR, MTK_UART_EFR_HW_FC | | |
| 259 | − (serial_in(up, UART_EFR) & | |
| 265 | + serial_out(up, MTK_UART_EFR, MTK_UART_EFR_HW_FC | | |
| 266 | + (serial_in(up, MTK_UART_EFR) & | |
| 260 | 267 | (~(MTK_UART_EFR_HW_FC | MTK_UART_EFR_SW_FC_MASK)))); |
| 261 | 268 | |
| 262 | 269 | serial_out(up, UART_LCR, lcr); |
| @@ -270,12 +277,12 @@ static void mtk8250_set_flow_ctrl(struct uart_8250_port *up, int mode) · 7 unmodified lines | ||
| 270 | 277 | serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B); |
| 271 | 278 | |
| 272 | 279 | /*enable sw flow control */ |
| 273 | − serial_out(up, UART_EFR, MTK_UART_EFR_XON1_XOFF1 | | |
| 274 | − (serial_in(up, UART_EFR) & | |
| 280 | + serial_out(up, MTK_UART_EFR, MTK_UART_EFR_XON1_XOFF1 | | |
| 281 | + (serial_in(up, MTK_UART_EFR) & | |
| 275 | 282 | (~(MTK_UART_EFR_HW_FC | MTK_UART_EFR_SW_FC_MASK)))); |
| 276 | 283 | |
| 277 | − serial_out(up, UART_XON1, START_CHAR(port->state->port.tty)); | |
| 278 | − serial_out(up, UART_XOFF1, STOP_CHAR(port->state->port.tty)); | |
| 284 | + serial_out(up, MTK_UART_XON1, START_CHAR(port->state->port.tty)); | |
| 285 | + serial_out(up, MTK_UART_XOFF1, STOP_CHAR(port->state->port.tty)); | |
| 279 | 286 | serial_out(up, UART_LCR, lcr); |
| 280 | 287 | mtk8250_disable_intrs(up, MTK_UART_IER_CTSI|MTK_UART_IER_RTSI); |
| 281 | 288 | mtk8250_enable_intrs(up, MTK_UART_IER_XOFFI); |
| @@ -568,6 +575,10 @@ static int mtk8250_probe(struct platform_device *pdev) · 286 unmodified lines | ||
| 568 | 575 | uart.dma = data->dma; |
| 569 | 576 | #endif |
| 570 | 577 | |
| 578 | + /* Set AP UART new register map */ | |
| 579 | + writel(MTK_UART_FEAT_NEWRMAP, uart.port.membase + | |
| 580 | + (MTK_UART_FEATURE_SEL << uart.port.regshift)); | |
| 581 | + | |
| 571 | 582 | /* Disable Rate Fix function */ |
| 572 | 583 | writel(0x0, uart.port.membase + |
| 573 | 584 | (MTK_UART_RATE_FIX << uart.port.regshift)); |
| @@ -2667,7 +2667,7 @@ enum pci_board_num_t { · 2666 unmodified lines | ||
| 2667 | 2667 | pbn_panacom2, |
| 2668 | 2668 | pbn_panacom4, |
| 2669 | 2669 | pbn_plx_romulus, |
| 2670 | − pbn_endrun_2_4000000, | |
| 2670 | + pbn_endrun_2_3906250, | |
| 2671 | 2671 | pbn_oxsemi, |
| 2672 | 2672 | pbn_oxsemi_1_3906250, |
| 2673 | 2673 | pbn_oxsemi_2_3906250, |
| @@ -3195,10 +3195,10 @@ static struct pciserial_board pci_boards[] = { · 521 unmodified lines | ||
| 3195 | 3195 | * signal now many ports are available |
| 3196 | 3196 | * 2 port 952 Uart support |
| 3197 | 3197 | */ |
| 3198 | − [pbn_endrun_2_4000000] = { | |
| 3198 | + [pbn_endrun_2_3906250] = { | |
| 3199 | 3199 | .flags = FL_BASE0, |
| 3200 | 3200 | .num_ports = 2, |
| 3201 | − .base_baud = 4000000, | |
| 3201 | + .base_baud = 3906250, | |
| 3202 | 3202 | .uart_offset = 0x200, |
| 3203 | 3203 | .first_offset = 0x1000, |
| 3204 | 3204 | }, |
| @@ -4115,7 +4115,7 @@ static const struct pci_device_id serial_pci_tbl[] = { · 910 unmodified lines | ||
| 4115 | 4115 | */ |
| 4116 | 4116 | { PCI_VENDOR_ID_ENDRUN, PCI_DEVICE_ID_ENDRUN_1588, |
| 4117 | 4117 | PCI_ANY_ID, PCI_ANY_ID, 0, 0, |
| 4118 | − pbn_endrun_2_4000000 }, | |
| 4118 | + pbn_endrun_2_3906250 }, | |
| 4119 | 4119 | /* |
| 4120 | 4120 | * Quatech cards. These actually have configurable clocks but for |
| 4121 | 4121 | * now we just use the default. |
| @@ -1675,11 +1675,11 @@ static void serial8250_start_tx(struct uart_port *port) · 1674 unmodified lines | ||
| 1675 | 1675 | struct uart_8250_port *up = up_to_u8250p(port); |
| 1676 | 1676 | struct uart_8250_em485 *em485 = up->em485; |
| 1677 | 1677 | |
| 1678 | − serial8250_rpm_get_tx(up); | |
| 1679 | − | |
| 1680 | 1678 | if (!port->x_char && uart_circ_empty(&port->state->xmit)) |
| 1681 | 1679 | return; |
| 1682 | 1680 | |
| 1681 | + serial8250_rpm_get_tx(up); | |
| 1682 | + | |
| 1683 | 1683 | if (em485 && |
| 1684 | 1684 | em485->active_timer == &em485->start_tx_timer) |
| 1685 | 1685 | return; |
| @@ -3329,7 +3329,7 @@ static void serial8250_console_restore(struct uart_8250_port *up) · 1643 unmodified lines | ||
| 3329 | 3329 | |
| 3330 | 3330 | serial8250_set_divisor(port, baud, quot, frac); |
| 3331 | 3331 | serial_port_out(port, UART_LCR, up->lcr); |
| 3332 | − serial8250_out_MCR(up, UART_MCR_DTR | UART_MCR_RTS); | |
| 3332 | + serial8250_out_MCR(up, up->mcr | UART_MCR_DTR | UART_MCR_RTS); | |
| 3333 | 3333 | } |
| 3334 | 3334 | |
| 3335 | 3335 | /* |
| @@ -1255,13 +1255,18 @@ static inline bool pl011_dma_rx_running(struct uart_amba_port *uap) · 1254 unmodified lines | ||
| 1255 | 1255 | |
| 1256 | 1256 | static void pl011_rs485_tx_stop(struct uart_amba_port *uap) |
| 1257 | 1257 | { |
| 1258 | + /* | |
| 1259 | + * To be on the safe side only time out after twice as many iterations | |
| 1260 | + * as fifo size. | |
| 1261 | + */ | |
| 1262 | + const int MAX_TX_DRAIN_ITERS = uap->port.fifosize * 2; | |
| 1258 | 1263 | struct uart_port *port = &uap->port; |
| 1259 | 1264 | int i = 0; |
| 1260 | 1265 | u32 cr; |
| 1261 | 1266 | |
| 1262 | 1267 | /* Wait until hardware tx queue is empty */ |
| 1263 | 1268 | while (!pl011_tx_empty(port)) { |
| 1264 | − if (i == port->fifosize) { | |
| 1269 | + if (i > MAX_TX_DRAIN_ITERS) { | |
| 1265 | 1270 | dev_warn(port->dev, |
| 1266 | 1271 | "timeout while draining hardware tx queue\n"); |
| 1267 | 1272 | break; |
| @@ -2052,7 +2057,7 @@ pl011_set_termios(struct uart_port *port, struct ktermios *termios, · 784 unmodified lines | ||
| 2052 | 2057 | * with the given baud rate. We use this as the poll interval when we |
| 2053 | 2058 | * wait for the tx queue to empty. |
| 2054 | 2059 | */ |
| 2055 | − uap->rs485_tx_drain_interval = (bits * 1000 * 1000) / baud; | |
| 2060 | + uap->rs485_tx_drain_interval = DIV_ROUND_UP(bits * 1000 * 1000, baud); | |
| 2056 | 2061 | |
| 2057 | 2062 | pl011_setup_status_masks(port, termios); |
| 2058 | 2063 | |
| @@ -471,11 +471,10 @@ static int digicolor_uart_probe(struct platform_device *pdev) · 470 unmodified lines | ||
| 471 | 471 | if (IS_ERR(uart_clk)) |
| 472 | 472 | return PTR_ERR(uart_clk); |
| 473 | 473 | |
| 474 | − res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | |
| 475 | − dp->port.mapbase = res->start; | |
| 476 | − dp->port.membase = devm_ioremap_resource(&pdev->dev, res); | |
| 474 | + dp->port.membase = devm_platform_get_and_ioremap_resource(pdev, 0, &res); | |
| 477 | 475 | if (IS_ERR(dp->port.membase)) |
| 478 | 476 | return PTR_ERR(dp->port.membase); |
| 477 | + dp->port.mapbase = res->start; | |
| 479 | 478 | |
| 480 | 479 | irq = platform_get_irq(pdev, 0); |
| 481 | 480 | if (irq < 0) |
| @@ -2664,6 +2664,7 @@ static int lpuart_probe(struct platform_device *pdev) · 2663 unmodified lines | ||
| 2664 | 2664 | struct device_node *np = pdev->dev.of_node; |
| 2665 | 2665 | struct lpuart_port *sport; |
| 2666 | 2666 | struct resource *res; |
| 2667 | + irq_handler_t handler; | |
| 2667 | 2668 | int ret; |
| 2668 | 2669 | |
| 2669 | 2670 | sport = devm_kzalloc(&pdev->dev, sizeof(*sport), GFP_KERNEL); |
| @@ -2741,17 +2742,11 @@ static int lpuart_probe(struct platform_device *pdev) · 71 unmodified lines | ||
| 2741 | 2742 | |
| 2742 | 2743 | if (lpuart_is_32(sport)) { |
| 2743 | 2744 | lpuart_reg.cons = LPUART32_CONSOLE; |
| 2744 | − ret = devm_request_irq(&pdev->dev, sport->port.irq, lpuart32_int, 0, | |
| 2745 | − DRIVER_NAME, sport); | |
| 2745 | + handler = lpuart32_int; | |
| 2746 | 2746 | } else { |
| 2747 | 2747 | lpuart_reg.cons = LPUART_CONSOLE; |
| 2748 | − ret = devm_request_irq(&pdev->dev, sport->port.irq, lpuart_int, 0, | |
| 2749 | − DRIVER_NAME, sport); | |
| 2748 | + handler = lpuart_int; | |
| 2750 | 2749 | } |
| 2751 | − | |
| 2752 | − if (ret) | |
| 2753 | − goto failed_irq_request; | |
| 2754 | − | |
| 2755 | 2750 | ret = uart_add_one_port(&lpuart_reg, &sport->port); |
| 2756 | 2751 | if (ret) |
| 2757 | 2752 | goto failed_attach_port; |
| @@ -2773,13 +2768,18 @@ static int lpuart_probe(struct platform_device *pdev) · 15 unmodified lines | ||
| 2773 | 2768 | |
| 2774 | 2769 | sport->port.rs485_config(&sport->port, &sport->port.rs485); |
| 2775 | 2770 | |
| 2771 | + ret = devm_request_irq(&pdev->dev, sport->port.irq, handler, 0, | |
| 2772 | + DRIVER_NAME, sport); | |
| 2773 | + if (ret) | |
| 2774 | + goto failed_irq_request; | |
| 2775 | + | |
| 2776 | 2776 | return 0; |
| 2777 | 2777 | |
| 2778 | +failed_irq_request: | |
| 2778 | 2779 | failed_get_rs485: |
| 2779 | 2780 | failed_reset: |
| 2780 | 2781 | uart_remove_one_port(&lpuart_reg, &sport->port); |
| 2781 | 2782 | failed_attach_port: |
| 2782 | −failed_irq_request: | |
| 2783 | 2783 | lpuart_disable_clks(sport); |
| 2784 | 2784 | failed_clock_enable: |
| 2785 | 2785 | failed_out_of_range: |
| @@ -1448,7 +1448,7 @@ static int imx_uart_startup(struct uart_port *port) · 1447 unmodified lines | ||
| 1448 | 1448 | imx_uart_writel(sport, ucr1, UCR1); |
| 1449 | 1449 | |
| 1450 | 1450 | ucr4 = imx_uart_readl(sport, UCR4) & ~(UCR4_OREN | UCR4_INVR); |
| 1451 | − if (!sport->dma_is_enabled) | |
| 1451 | + if (!dma_is_inited) | |
| 1452 | 1452 | ucr4 |= UCR4_OREN; |
| 1453 | 1453 | if (sport->inverted_rx) |
| 1454 | 1454 | ucr4 |= UCR4_INVR; |
| @@ -1238,12 +1238,10 @@ static void sc16is7xx_shutdown(struct uart_port *port) · 1237 unmodified lines | ||
| 1238 | 1238 | |
| 1239 | 1239 | /* Disable all interrupts */ |
| 1240 | 1240 | sc16is7xx_port_write(port, SC16IS7XX_IER_REG, 0); |
| 1241 | − /* Disable TX/RX, clear auto RS485 and RTS invert */ | |
| 1241 | + /* Disable TX/RX */ | |
| 1242 | 1242 | sc16is7xx_port_update(port, SC16IS7XX_EFCR_REG, |
| 1243 | 1243 | SC16IS7XX_EFCR_RXDISABLE_BIT | |
| 1244 | − SC16IS7XX_EFCR_TXDISABLE_BIT | | |
| 1245 | − SC16IS7XX_EFCR_AUTO_RS485_BIT | | |
| 1246 | − SC16IS7XX_EFCR_RTS_INVERT_BIT, | |
| 1244 | + SC16IS7XX_EFCR_TXDISABLE_BIT, | |
| 1247 | 1245 | SC16IS7XX_EFCR_RXDISABLE_BIT | |
| 1248 | 1246 | SC16IS7XX_EFCR_TXDISABLE_BIT); |
| 1249 | 1247 | |
| @@ -2684,6 +2684,7 @@ int __cdns3_gadget_ep_clear_halt(struct cdns3_endpoint *priv_ep) · 2683 unmodified lines | ||
| 2684 | 2684 | struct usb_request *request; |
| 2685 | 2685 | struct cdns3_request *priv_req; |
| 2686 | 2686 | struct cdns3_trb *trb = NULL; |
| 2687 | + struct cdns3_trb trb_tmp; | |
| 2687 | 2688 | int ret; |
| 2688 | 2689 | int val; |
| 2689 | 2690 | |
| @@ -2693,8 +2694,10 @@ int __cdns3_gadget_ep_clear_halt(struct cdns3_endpoint *priv_ep) · 3 unmodified lines | ||
| 2693 | 2694 | if (request) { |
| 2694 | 2695 | priv_req = to_cdns3_request(request); |
| 2695 | 2696 | trb = priv_req->trb; |
| 2696 | − if (trb) | |
| 2697 | + if (trb) { | |
| 2698 | + trb_tmp = *trb; | |
| 2697 | 2699 | trb->control = trb->control ^ cpu_to_le32(TRB_CYCLE); |
| 2700 | + } | |
| 2698 | 2701 | } |
| 2699 | 2702 | |
| 2700 | 2703 | writel(EP_CMD_CSTALL | EP_CMD_EPRST, &priv_dev->regs->ep_cmd); |
| @@ -2709,7 +2712,7 @@ int __cdns3_gadget_ep_clear_halt(struct cdns3_endpoint *priv_ep) · 8 unmodified lines | ||
| 2709 | 2712 | |
| 2710 | 2713 | if (request) { |
| 2711 | 2714 | if (trb) |
| 2712 | − trb->control = trb->control ^ cpu_to_le32(TRB_CYCLE); | |
| 2715 | + *trb = trb_tmp; | |
| 2713 | 2716 | |
| 2714 | 2717 | cdns3_rearm_transfer(priv_ep, 1); |
| 2715 | 2718 | } |
| @@ -774,6 +774,7 @@ static int wdm_release(struct inode *inode, struct file *file) · 773 unmodified lines | ||
| 774 | 774 | poison_urbs(desc); |
| 775 | 775 | spin_lock_irq(&desc->iuspin); |
| 776 | 776 | desc->resp_count = 0; |
| 777 | + clear_bit(WDM_RESPONDING, &desc->flags); | |
| 777 | 778 | spin_unlock_irq(&desc->iuspin); |
| 778 | 779 | desc->manage_power(desc->intf, 0); |
| 779 | 780 | unpoison_urbs(desc); |
| @@ -1209,12 +1209,16 @@ static int do_proc_control(struct usb_dev_state *ps, · 1208 unmodified lines | ||
| 1209 | 1209 | |
| 1210 | 1210 | usb_unlock_device(dev); |
| 1211 | 1211 | i = usbfs_start_wait_urb(urb, tmo, &actlen); |
| 1212 | + | |
| 1213 | + /* Linger a bit, prior to the next control message. */ | |
| 1214 | + if (dev->quirks & USB_QUIRK_DELAY_CTRL_MSG) | |
| 1215 | + msleep(200); | |
| 1212 | 1216 | usb_lock_device(dev); |
| 1213 | 1217 | snoop_urb(dev, NULL, pipe, actlen, i, COMPLETE, tbuf, actlen); |
| 1214 | 1218 | if (!i && actlen) { |
| 1215 | 1219 | if (copy_to_user(ctrl->data, tbuf, actlen)) { |
| 1216 | 1220 | ret = -EFAULT; |
| 1217 | − goto recv_fault; | |
| 1221 | + goto done; | |
| 1218 | 1222 | } |
| 1219 | 1223 | } |
| 1220 | 1224 | } else { |
| @@ -1231,6 +1235,10 @@ static int do_proc_control(struct usb_dev_state *ps, · 10 unmodified lines | ||
| 1231 | 1235 | |
| 1232 | 1236 | usb_unlock_device(dev); |
| 1233 | 1237 | i = usbfs_start_wait_urb(urb, tmo, &actlen); |
| 1238 | + | |
| 1239 | + /* Linger a bit, prior to the next control message. */ | |
| 1240 | + if (dev->quirks & USB_QUIRK_DELAY_CTRL_MSG) | |
| 1241 | + msleep(200); | |
| 1234 | 1242 | usb_lock_device(dev); |
| 1235 | 1243 | snoop_urb(dev, NULL, pipe, actlen, i, COMPLETE, NULL, 0); |
| 1236 | 1244 | } |
| @@ -1242,10 +1250,6 @@ static int do_proc_control(struct usb_dev_state *ps, · 5 unmodified lines | ||
| 1242 | 1250 | } |
| 1243 | 1251 | ret = (i < 0 ? i : actlen); |
| 1244 | 1252 | |
| 1245 | − recv_fault: | |
| 1246 | − /* Linger a bit, prior to the next control message. */ | |
| 1247 | − if (dev->quirks & USB_QUIRK_DELAY_CTRL_MSG) | |
| 1248 | − msleep(200); | |
| 1249 | 1253 | done: |
| 1250 | 1254 | kfree(dr); |
| 1251 | 1255 | usb_free_urb(urb); |
| @@ -404,6 +404,9 @@ static const struct usb_device_id usb_quirk_list[] = { · 403 unmodified lines | ||
| 404 | 404 | { USB_DEVICE(0x0b05, 0x17e0), .driver_info = |
| 405 | 405 | USB_QUIRK_IGNORE_REMOTE_WAKEUP }, |
| 406 | 406 | |
| 407 | + /* Realtek Semiconductor Corp. Mass Storage Device (Multicard Reader)*/ | |
| 408 | + { USB_DEVICE(0x0bda, 0x0151), .driver_info = USB_QUIRK_CONFIG_INTF_STRINGS }, | |
| 409 | + | |
| 407 | 410 | /* Realtek hub in Dell WD19 (Type-C) */ |
| 408 | 411 | { USB_DEVICE(0x0bda, 0x0487), .driver_info = USB_QUIRK_NO_LPM }, |
| 409 | 412 | |
| @@ -507,6 +510,9 @@ static const struct usb_device_id usb_quirk_list[] = { · 97 unmodified lines | ||
| 507 | 510 | /* DJI CineSSD */ |
| 508 | 511 | { USB_DEVICE(0x2ca3, 0x0031), .driver_info = USB_QUIRK_NO_LPM }, |
| 509 | 512 | |
| 513 | + /* VCOM device */ | |
| 514 | + { USB_DEVICE(0x4296, 0x7570), .driver_info = USB_QUIRK_CONFIG_INTF_STRINGS }, | |
| 515 | + | |
| 510 | 516 | /* INTEL VALUE SSD */ |
| 511 | 517 | { USB_DEVICE(0x8086, 0xf1a5), .driver_info = USB_QUIRK_RESET_RESUME }, |
| 512 | 518 | |
| @@ -274,7 +274,8 @@ int dwc3_core_soft_reset(struct dwc3 *dwc) · 273 unmodified lines | ||
| 274 | 274 | |
| 275 | 275 | reg = dwc3_readl(dwc->regs, DWC3_DCTL); |
| 276 | 276 | reg |= DWC3_DCTL_CSFTRST; |
| 277 | − dwc3_writel(dwc->regs, DWC3_DCTL, reg); | |
| 277 | + reg &= ~DWC3_DCTL_RUN_STOP; | |
| 278 | + dwc3_gadget_dctl_write_safe(dwc, reg); | |
| 278 | 279 | |
| 279 | 280 | /* |
| 280 | 281 | * For DWC_usb31 controller 1.90a and later, the DCTL.CSFRST bit |
| @@ -1377,10 +1378,10 @@ static void dwc3_get_properties(struct dwc3 *dwc) · 1096 unmodified lines | ||
| 1377 | 1378 | u8 lpm_nyet_threshold; |
| 1378 | 1379 | u8 tx_de_emphasis; |
| 1379 | 1380 | u8 hird_threshold; |
| 1380 | − u8 rx_thr_num_pkt_prd; | |
| 1381 | − u8 rx_max_burst_prd; | |
| 1382 | − u8 tx_thr_num_pkt_prd; | |
| 1383 | − u8 tx_max_burst_prd; | |
| 1381 | + u8 rx_thr_num_pkt_prd = 0; | |
| 1382 | + u8 rx_max_burst_prd = 0; | |
| 1383 | + u8 tx_thr_num_pkt_prd = 0; | |
| 1384 | + u8 tx_max_burst_prd = 0; | |
| 1384 | 1385 | u8 tx_fifo_resize_max_num; |
| 1385 | 1386 | const char *usb_psy_name; |
| 1386 | 1387 | int ret; |
| @@ -1690,21 +1691,44 @@ static int dwc3_probe(struct platform_device *pdev) · 303 unmodified lines | ||
| 1690 | 1691 | /* |
| 1691 | 1692 | * Clocks are optional, but new DT platforms should support all |
| 1692 | 1693 | * clocks as required by the DT-binding. |
| 1694 | + * Some devices have different clock names in legacy device trees, | |
| 1695 | + * check for them to retain backwards compatibility. | |
| 1693 | 1696 | */ |
| 1694 | 1697 | dwc->bus_clk = devm_clk_get_optional(dev, "bus_early"); |
| 1695 | 1698 | if (IS_ERR(dwc->bus_clk)) |
| 1696 | 1699 | return dev_err_probe(dev, PTR_ERR(dwc->bus_clk), |
| 1697 | 1700 | "could not get bus clock\n"); |
| 1698 | 1701 | |
| 1702 | + if (dwc->bus_clk == NULL) { | |
| 1703 | + dwc->bus_clk = devm_clk_get_optional(dev, "bus_clk"); | |
| 1704 | + if (IS_ERR(dwc->bus_clk)) | |
| 1705 | + return dev_err_probe(dev, PTR_ERR(dwc->bus_clk), | |
| 1706 | + "could not get bus clock\n"); | |
| 1707 | + } | |
| 1708 | + | |
| 1699 | 1709 | dwc->ref_clk = devm_clk_get_optional(dev, "ref"); |
| 1700 | 1710 | if (IS_ERR(dwc->ref_clk)) |
| 1701 | 1711 | return dev_err_probe(dev, PTR_ERR(dwc->ref_clk), |
| 1702 | 1712 | "could not get ref clock\n"); |
| 1703 | 1713 | |
| 1714 | + if (dwc->ref_clk == NULL) { | |
| 1715 | + dwc->ref_clk = devm_clk_get_optional(dev, "ref_clk"); | |
| 1716 | + if (IS_ERR(dwc->ref_clk)) | |
| 1717 | + return dev_err_probe(dev, PTR_ERR(dwc->ref_clk), | |
| 1718 | + "could not get ref clock\n"); | |
| 1719 | + } | |
| 1720 | + | |
| 1704 | 1721 | dwc->susp_clk = devm_clk_get_optional(dev, "suspend"); |
| 1705 | 1722 | if (IS_ERR(dwc->susp_clk)) |
| 1706 | 1723 | return dev_err_probe(dev, PTR_ERR(dwc->susp_clk), |
| 1707 | 1724 | "could not get suspend clock\n"); |
| 1725 | + | |
| 1726 | + if (dwc->susp_clk == NULL) { | |
| 1727 | + dwc->susp_clk = devm_clk_get_optional(dev, "suspend_clk"); | |
| 1728 | + if (IS_ERR(dwc->susp_clk)) | |
| 1729 | + return dev_err_probe(dev, PTR_ERR(dwc->susp_clk), | |
| 1730 | + "could not get suspend clock\n"); | |
| 1731 | + } | |
| 1708 | 1732 | } |
| 1709 | 1733 | |
| 1710 | 1734 | ret = reset_control_deassert(dwc->reset); |
| @@ -584,16 +584,15 @@ int dwc3_drd_init(struct dwc3 *dwc) · 583 unmodified lines | ||
| 584 | 584 | { |
| 585 | 585 | int ret, irq; |
| 586 | 586 | |
| 587 | + if (ROLE_SWITCH && | |
| 588 | + device_property_read_bool(dwc->dev, "usb-role-switch")) | |
| 589 | + return dwc3_setup_role_switch(dwc); | |
| 590 | + | |
| 587 | 591 | dwc->edev = dwc3_get_extcon(dwc); |
| 588 | 592 | if (IS_ERR(dwc->edev)) |
| 589 | 593 | return PTR_ERR(dwc->edev); |
| 590 | 594 | |
| 591 | − if (ROLE_SWITCH && | |
| 592 | − device_property_read_bool(dwc->dev, "usb-role-switch")) { | |
| 593 | − ret = dwc3_setup_role_switch(dwc); | |
| 594 | − if (ret < 0) | |
| 595 | − return ret; | |
| 596 | − } else if (dwc->edev) { | |
| 595 | + if (dwc->edev) { | |
| 597 | 596 | dwc->edev_nb.notifier_call = dwc3_drd_notifier; |
| 598 | 597 | ret = extcon_register_notifier(dwc->edev, EXTCON_USB_HOST, |
| 599 | 598 | &dwc->edev_nb); |
| @@ -45,6 +45,8 @@ · 44 unmodified lines | ||
| 45 | 45 | #define PCI_DEVICE_ID_INTEL_ADLM 0x54ee |
| 46 | 46 | #define PCI_DEVICE_ID_INTEL_ADLS 0x7ae1 |
| 47 | 47 | #define PCI_DEVICE_ID_INTEL_RPLS 0x7a61 |
| 48 | +#define PCI_DEVICE_ID_INTEL_MTLP 0x7ec1 | |
| 49 | +#define PCI_DEVICE_ID_INTEL_MTL 0x7e7e | |
| 48 | 50 | #define PCI_DEVICE_ID_INTEL_TGL 0x9a15 |
| 49 | 51 | #define PCI_DEVICE_ID_AMD_MR 0x163a |
| 50 | 52 | |
| @@ -456,6 +458,12 @@ static const struct pci_device_id dwc3_pci_id_table[] = { · 405 unmodified lines | ||
| 456 | 458 | { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_RPLS), |
| 457 | 459 | (kernel_ulong_t) &dwc3_pci_intel_swnode, }, |
| 458 | 460 | |
| 461 | + { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_MTLP), | |
| 462 | + (kernel_ulong_t) &dwc3_pci_intel_swnode, }, | |
| 463 | + | |
| 464 | + { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_MTL), | |
| 465 | + (kernel_ulong_t) &dwc3_pci_intel_swnode, }, | |
| 466 | + | |
| 459 | 467 | { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_TGL), |
| 460 | 468 | (kernel_ulong_t) &dwc3_pci_intel_swnode, }, |
| 461 | 469 | |
| @@ -3274,6 +3274,7 @@ static int dwc3_gadget_ep_cleanup_completed_request(struct dwc3_ep *dep, · 3273 unmodified lines | ||
| 3274 | 3274 | const struct dwc3_event_depevt *event, |
| 3275 | 3275 | struct dwc3_request *req, int status) |
| 3276 | 3276 | { |
| 3277 | + int request_status; | |
| 3277 | 3278 | int ret; |
| 3278 | 3279 | |
| 3279 | 3280 | if (req->request.num_mapped_sgs) |
| @@ -3294,7 +3295,35 @@ static int dwc3_gadget_ep_cleanup_completed_request(struct dwc3_ep *dep, · 14 unmodified lines | ||
| 3294 | 3295 | req->needs_extra_trb = false; |
| 3295 | 3296 | } |
| 3296 | 3297 | |
| 3297 | − dwc3_gadget_giveback(dep, req, status); | |
| 3298 | + /* | |
| 3299 | + * The event status only reflects the status of the TRB with IOC set. | |
| 3300 | + * For the requests that don't set interrupt on completion, the driver | |
| 3301 | + * needs to check and return the status of the completed TRBs associated | |
| 3302 | + * with the request. Use the status of the last TRB of the request. | |
| 3303 | + */ | |
| 3304 | + if (req->request.no_interrupt) { | |
| 3305 | + struct dwc3_trb *trb; | |
| 3306 | + | |
| 3307 | + trb = dwc3_ep_prev_trb(dep, dep->trb_dequeue); | |
| 3308 | + switch (DWC3_TRB_SIZE_TRBSTS(trb->size)) { | |
| 3309 | + case DWC3_TRBSTS_MISSED_ISOC: | |
| 3310 | + /* Isoc endpoint only */ | |
| 3311 | + request_status = -EXDEV; | |
| 3312 | + break; | |
| 3313 | + case DWC3_TRB_STS_XFER_IN_PROG: | |
| 3314 | + /* Applicable when End Transfer with ForceRM=0 */ | |
| 3315 | + case DWC3_TRBSTS_SETUP_PENDING: | |
| 3316 | + /* Control endpoint only */ | |
| 3317 | + case DWC3_TRBSTS_OK: | |
| 3318 | + default: | |
| 3319 | + request_status = 0; | |
| 3320 | + break; | |
| 3321 | + } | |
| 3322 | + } else { | |
| 3323 | + request_status = status; | |
| 3324 | + } | |
| 3325 | + | |
| 3326 | + dwc3_gadget_giveback(dep, req, request_status); | |
| 3298 | 3327 | |
| 3299 | 3328 | out: |
| 3300 | 3329 | return ret; |
| @@ -1438,6 +1438,8 @@ static void configfs_composite_unbind(struct usb_gadget *gadget) · 1437 unmodified lines | ||
| 1438 | 1438 | usb_ep_autoconfig_reset(cdev->gadget); |
| 1439 | 1439 | spin_lock_irqsave(&gi->spinlock, flags); |
| 1440 | 1440 | cdev->gadget = NULL; |
| 1441 | + cdev->deactivations = 0; | |
| 1442 | + gadget->deactivated = false; | |
| 1441 | 1443 | set_gadget_data(gadget, NULL); |
| 1442 | 1444 | spin_unlock_irqrestore(&gi->spinlock, flags); |
| 1443 | 1445 | } |
| @@ -890,13 +890,37 @@ static void uvc_function_unbind(struct usb_configuration *c, · 889 unmodified lines | ||
| 890 | 890 | { |
| 891 | 891 | struct usb_composite_dev *cdev = c->cdev; |
| 892 | 892 | struct uvc_device *uvc = to_uvc(f); |
| 893 | + long wait_ret = 1; | |
| 893 | 894 | |
| 894 | 895 | uvcg_info(f, "%s()\n", __func__); |
| 895 | 896 | |
| 897 | + /* If we know we're connected via v4l2, then there should be a cleanup | |
| 898 | + * of the device from userspace either via UVC_EVENT_DISCONNECT or | |
| 899 | + * though the video device removal uevent. Allow some time for the | |
| 900 | + * application to close out before things get deleted. | |
| 901 | + */ | |
| 902 | + if (uvc->func_connected) { | |
| 903 | + uvcg_dbg(f, "waiting for clean disconnect\n"); | |
| 904 | + wait_ret = wait_event_interruptible_timeout(uvc->func_connected_queue, | |
| 905 | + uvc->func_connected == false, msecs_to_jiffies(500)); | |
| 906 | + uvcg_dbg(f, "done waiting with ret: %ld\n", wait_ret); | |
| 907 | + } | |
| 908 | + | |
| 896 | 909 | device_remove_file(&uvc->vdev.dev, &dev_attr_function_name); |
| 897 | 910 | video_unregister_device(&uvc->vdev); |
| 898 | 911 | v4l2_device_unregister(&uvc->v4l2_dev); |
| 899 | 912 | |
| 913 | + if (uvc->func_connected) { | |
| 914 | + /* Wait for the release to occur to ensure there are no longer any | |
| 915 | + * pending operations that may cause panics when resources are cleaned | |
| 916 | + * up. | |
| 917 | + */ | |
| 918 | + uvcg_warn(f, "%s no clean disconnect, wait for release\n", __func__); | |
| 919 | + wait_ret = wait_event_interruptible_timeout(uvc->func_connected_queue, | |
| 920 | + uvc->func_connected == false, msecs_to_jiffies(1000)); | |
| 921 | + uvcg_dbg(f, "done waiting for release with ret: %ld\n", wait_ret); | |
| 922 | + } | |
| 923 | + | |
| 900 | 924 | usb_ep_free_request(cdev->gadget->ep0, uvc->control_req); |
| 901 | 925 | kfree(uvc->control_buf); |
| 902 | 926 | |
| @@ -915,6 +939,7 @@ static struct usb_function *uvc_alloc(struct usb_function_instance *fi) · 12 unmodified lines | ||
| 915 | 939 | |
| 916 | 940 | mutex_init(&uvc->video.mutex); |
| 917 | 941 | uvc->state = UVC_STATE_DISCONNECTED; |
| 942 | + init_waitqueue_head(&uvc->func_connected_queue); | |
| 918 | 943 | opts = fi_to_f_uvc_opts(fi); |
| 919 | 944 | |
| 920 | 945 | mutex_lock(&opts->lock); |
| @@ -14,6 +14,7 @@ · 13 unmodified lines | ||
| 14 | 14 | #include <linux/spinlock.h> |
| 15 | 15 | #include <linux/usb/composite.h> |
| 16 | 16 | #include <linux/videodev2.h> |
| 17 | +#include <linux/wait.h> | |
| 17 | 18 | |
| 18 | 19 | #include <media/v4l2-device.h> |
| 19 | 20 | #include <media/v4l2-dev.h> |
| @@ -129,6 +130,7 @@ struct uvc_device { · 109 unmodified lines | ||
| 129 | 130 | struct usb_function func; |
| 130 | 131 | struct uvc_video video; |
| 131 | 132 | bool func_connected; |
| 133 | + wait_queue_head_t func_connected_queue; | |
| 132 | 134 | |
| 133 | 135 | /* Descriptors */ |
| 134 | 136 | struct { |
| @@ -264,6 +264,8 @@ void uvcg_queue_cancel(struct uvc_video_queue *queue, int disconnect) · 263 unmodified lines | ||
| 264 | 264 | buf->state = UVC_BUF_STATE_ERROR; |
| 265 | 265 | vb2_buffer_done(&buf->buf.vb2_buf, VB2_BUF_STATE_ERROR); |
| 266 | 266 | } |
| 267 | + queue->buf_used = 0; | |
| 268 | + | |
| 267 | 269 | /* This must be protected by the irqlock spinlock to avoid race |
| 268 | 270 | * conditions between uvc_queue_buffer and the disconnection event that |
| 269 | 271 | * could result in an interruptible wait in uvc_dequeue_buffer. Do not |
| @@ -253,10 +253,11 @@ uvc_v4l2_subscribe_event(struct v4l2_fh *fh, · 252 unmodified lines | ||
| 253 | 253 | |
| 254 | 254 | static void uvc_v4l2_disable(struct uvc_device *uvc) |
| 255 | 255 | { |
| 256 | − uvc->func_connected = false; | |
| 257 | 256 | uvc_function_disconnect(uvc); |
| 258 | 257 | uvcg_video_enable(&uvc->video, 0); |
| 259 | 258 | uvcg_free_buffers(&uvc->video.queue); |
| 259 | + uvc->func_connected = false; | |
| 260 | + wake_up_interruptible(&uvc->func_connected_queue); | |
| 260 | 261 | } |
| 261 | 262 | |
| 262 | 263 | static int |
| @@ -145,6 +145,7 @@ enum dev_state { · 144 unmodified lines | ||
| 145 | 145 | STATE_DEV_INVALID = 0, |
| 146 | 146 | STATE_DEV_OPENED, |
| 147 | 147 | STATE_DEV_INITIALIZED, |
| 148 | + STATE_DEV_REGISTERING, | |
| 148 | 149 | STATE_DEV_RUNNING, |
| 149 | 150 | STATE_DEV_CLOSED, |
| 150 | 151 | STATE_DEV_FAILED |
| @@ -508,6 +509,7 @@ static int raw_ioctl_run(struct raw_dev *dev, unsigned long value) · 357 unmodified lines | ||
| 508 | 509 | ret = -EINVAL; |
| 509 | 510 | goto out_unlock; |
| 510 | 511 | } |
| 512 | + dev->state = STATE_DEV_REGISTERING; | |
| 511 | 513 | spin_unlock_irqrestore(&dev->lock, flags); |
| 512 | 514 | |
| 513 | 515 | ret = usb_gadget_probe_driver(&dev->driver); |
| @@ -1103,6 +1103,26 @@ static void ehci_remove_device(struct usb_hcd *hcd, struct usb_device *udev) · 1102 unmodified lines | ||
| 1103 | 1103 | |
| 1104 | 1104 | #ifdef CONFIG_PM |
| 1105 | 1105 | |
| 1106 | +/* Clear wakeup signal locked in zhaoxin platform when device plug in. */ | |
| 1107 | +static void ehci_zx_wakeup_clear(struct ehci_hcd *ehci) | |
| 1108 | +{ | |
| 1109 | + u32 __iomem *reg = &ehci->regs->port_status[4]; | |
| 1110 | + u32 t1 = ehci_readl(ehci, reg); | |
| 1111 | + | |
| 1112 | + t1 &= (u32)~0xf0000; | |
| 1113 | + t1 |= PORT_TEST_FORCE; | |
| 1114 | + ehci_writel(ehci, t1, reg); | |
| 1115 | + t1 = ehci_readl(ehci, reg); | |
| 1116 | + msleep(1); | |
| 1117 | + t1 &= (u32)~0xf0000; | |
| 1118 | + ehci_writel(ehci, t1, reg); | |
| 1119 | + ehci_readl(ehci, reg); | |
| 1120 | + msleep(1); | |
| 1121 | + t1 = ehci_readl(ehci, reg); | |
| 1122 | + ehci_writel(ehci, t1 | PORT_CSC, reg); | |
| 1123 | + ehci_readl(ehci, reg); | |
| 1124 | +} | |
| 1125 | + | |
| 1106 | 1126 | /* suspend/resume, section 4.3 */ |
| 1107 | 1127 | |
| 1108 | 1128 | /* These routines handle the generic parts of controller suspend/resume */ |
| @@ -1154,6 +1174,9 @@ int ehci_resume(struct usb_hcd *hcd, bool force_reset) · 45 unmodified lines | ||
| 1154 | 1174 | if (ehci->shutdown) |
| 1155 | 1175 | return 0; /* Controller is dead */ |
| 1156 | 1176 | |
| 1177 | + if (ehci->zx_wakeup_clear_needed) | |
| 1178 | + ehci_zx_wakeup_clear(ehci); | |
| 1179 | + | |
| 1157 | 1180 | /* |
| 1158 | 1181 | * If CF is still set and reset isn't forced |
| 1159 | 1182 | * then we maintained suspend power. |
| @@ -231,6 +231,10 @@ static int ehci_pci_setup(struct usb_hcd *hcd) · 230 unmodified lines | ||
| 231 | 231 | ehci->is_aspeed = 1; |
| 232 | 232 | } |
| 233 | 233 | break; |
| 234 | + case PCI_VENDOR_ID_ZHAOXIN: | |
| 235 | + if (pdev->device == 0x3104 && (pdev->revision & 0xf0) == 0x90) | |
| 236 | + ehci->zx_wakeup_clear_needed = 1; | |
| 237 | + break; | |
| 234 | 238 | } |
| 235 | 239 | |
| 236 | 240 | /* optional debug port, normally in the first BAR */ |
| @@ -220,6 +220,7 @@ struct ehci_hcd { /* one per controller */ · 219 unmodified lines | ||
| 220 | 220 | unsigned imx28_write_fix:1; /* For Freescale i.MX28 */ |
| 221 | 221 | unsigned spurious_oc:1; |
| 222 | 222 | unsigned is_aspeed:1; |
| 223 | + unsigned zx_wakeup_clear_needed:1; | |
| 223 | 224 | |
| 224 | 225 | /* required for usb32 quirk */ |
| 225 | 226 | #define OHCI_CTRL_HCFS (3 << 6) |
| @@ -1434,7 +1434,7 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, · 1433 unmodified lines | ||
| 1434 | 1434 | } |
| 1435 | 1435 | spin_unlock_irqrestore(&xhci->lock, flags); |
| 1436 | 1436 | if (!wait_for_completion_timeout(&bus_state->u3exit_done[wIndex], |
| 1437 | − msecs_to_jiffies(100))) | |
| 1437 | + msecs_to_jiffies(500))) | |
| 1438 | 1438 | xhci_dbg(xhci, "missing U0 port change event for port %d-%d\n", |
| 1439 | 1439 | hcd->self.busnum, wIndex + 1); |
| 1440 | 1440 | spin_lock_irqsave(&xhci->lock, flags); |
| @@ -19,11 +19,6 @@ · 18 unmodified lines | ||
| 19 | 19 | #define HS_BW_BOUNDARY 6144 |
| 20 | 20 | /* usb2 spec section11.18.1: at most 188 FS bytes per microframe */ |
| 21 | 21 | #define FS_PAYLOAD_MAX 188 |
| 22 | −/* | |
| 23 | − * max number of microframes for split transfer, | |
| 24 | − * for fs isoc in : 1 ss + 1 idle + 7 cs | |
| 25 | − */ | |
| 26 | −#define TT_MICROFRAMES_MAX 9 | |
| 27 | 22 | |
| 28 | 23 | #define DBG_BUF_EN 64 |
| 29 | 24 | |
| @@ -242,28 +237,17 @@ static void drop_tt(struct usb_device *udev) · 212 unmodified lines | ||
| 242 | 237 | |
| 243 | 238 | static struct mu3h_sch_ep_info * |
| 244 | 239 | create_sch_ep(struct xhci_hcd_mtk *mtk, struct usb_device *udev, |
| 245 | − struct usb_host_endpoint *ep, struct xhci_ep_ctx *ep_ctx) | |
| 240 | + struct usb_host_endpoint *ep) | |
| 246 | 241 | { |
| 247 | 242 | struct mu3h_sch_ep_info *sch_ep; |
| 248 | 243 | struct mu3h_sch_bw_info *bw_info; |
| 249 | 244 | struct mu3h_sch_tt *tt = NULL; |
| 250 | − u32 len_bw_budget_table; | |
| 251 | 245 | |
| 252 | 246 | bw_info = get_bw_info(mtk, udev, ep); |
| 253 | 247 | if (!bw_info) |
| 254 | 248 | return ERR_PTR(-ENODEV); |
| 255 | 249 | |
| 256 | − if (is_fs_or_ls(udev->speed)) | |
| 257 | − len_bw_budget_table = TT_MICROFRAMES_MAX; | |
| 258 | − else if ((udev->speed >= USB_SPEED_SUPER) | |
| 259 | − && usb_endpoint_xfer_isoc(&ep->desc)) | |
| 260 | − len_bw_budget_table = get_esit(ep_ctx); | |
| 261 | − else | |
| 262 | − len_bw_budget_table = 1; | |
| 263 | − | |
| 264 | − sch_ep = kzalloc(struct_size(sch_ep, bw_budget_table, | |
| 265 | − len_bw_budget_table), | |
| 266 | − GFP_KERNEL); | |
| 250 | + sch_ep = kzalloc(sizeof(*sch_ep), GFP_KERNEL); | |
| 267 | 251 | if (!sch_ep) |
| 268 | 252 | return ERR_PTR(-ENOMEM); |
| 269 | 253 | |
| @@ -295,8 +279,6 @@ static void setup_sch_info(struct xhci_ep_ctx *ep_ctx, · 25 unmodified lines | ||
| 295 | 279 | u32 mult; |
| 296 | 280 | u32 esit_pkts; |
| 297 | 281 | u32 max_esit_payload; |
| 298 | − u32 *bwb_table = sch_ep->bw_budget_table; | |
| 299 | − int i; | |
| 300 | 282 | |
| 301 | 283 | ep_type = CTX_TO_EP_TYPE(le32_to_cpu(ep_ctx->ep_info2)); |
| 302 | 284 | maxpkt = MAX_PACKET_DECODED(le32_to_cpu(ep_ctx->ep_info2)); |
| @@ -332,7 +314,6 @@ static void setup_sch_info(struct xhci_ep_ctx *ep_ctx, · 29 unmodified lines | ||
| 332 | 314 | */ |
| 333 | 315 | sch_ep->pkts = max_burst + 1; |
| 334 | 316 | sch_ep->bw_cost_per_microframe = maxpkt * sch_ep->pkts; |
| 335 | − bwb_table[0] = sch_ep->bw_cost_per_microframe; | |
| 336 | 317 | } else if (sch_ep->speed >= USB_SPEED_SUPER) { |
| 337 | 318 | /* usb3_r1 spec section4.4.7 & 4.4.8 */ |
| 338 | 319 | sch_ep->cs_count = 0; |
| @@ -349,7 +330,6 @@ static void setup_sch_info(struct xhci_ep_ctx *ep_ctx, · 10 unmodified lines | ||
| 349 | 330 | if (ep_type == INT_IN_EP || ep_type == INT_OUT_EP) { |
| 350 | 331 | sch_ep->pkts = esit_pkts; |
| 351 | 332 | sch_ep->num_budget_microframes = 1; |
| 352 | − bwb_table[0] = maxpkt * sch_ep->pkts; | |
| 353 | 333 | } |
| 354 | 334 | |
| 355 | 335 | if (ep_type == ISOC_IN_EP || ep_type == ISOC_OUT_EP) { |
| @@ -366,15 +346,8 @@ static void setup_sch_info(struct xhci_ep_ctx *ep_ctx, · 10 unmodified lines | ||
| 366 | 346 | DIV_ROUND_UP(esit_pkts, sch_ep->pkts); |
| 367 | 347 | |
| 368 | 348 | sch_ep->repeat = !!(sch_ep->num_budget_microframes > 1); |
| 369 | − sch_ep->bw_cost_per_microframe = maxpkt * sch_ep->pkts; | |
| 370 | − | |
| 371 | − for (i = 0; i < sch_ep->num_budget_microframes - 1; i++) | |
| 372 | − bwb_table[i] = sch_ep->bw_cost_per_microframe; | |
| 373 | − | |
| 374 | − /* last one <= bw_cost_per_microframe */ | |
| 375 | − bwb_table[i] = maxpkt * esit_pkts | |
| 376 | − - i * sch_ep->bw_cost_per_microframe; | |
| 377 | 349 | } |
| 350 | + sch_ep->bw_cost_per_microframe = maxpkt * sch_ep->pkts; | |
| 378 | 351 | } else if (is_fs_or_ls(sch_ep->speed)) { |
| 379 | 352 | sch_ep->pkts = 1; /* at most one packet for each microframe */ |
| 380 | 353 | |
| @@ -384,28 +357,7 @@ static void setup_sch_info(struct xhci_ep_ctx *ep_ctx, · 3 unmodified lines | ||
| 384 | 357 | */ |
| 385 | 358 | sch_ep->cs_count = DIV_ROUND_UP(maxpkt, FS_PAYLOAD_MAX); |
| 386 | 359 | sch_ep->num_budget_microframes = sch_ep->cs_count; |
| 387 | − sch_ep->bw_cost_per_microframe = | |
| 388 | − (maxpkt < FS_PAYLOAD_MAX) ? maxpkt : FS_PAYLOAD_MAX; | |
| 389 | − | |
| 390 | − /* init budget table */ | |
| 391 | − if (ep_type == ISOC_OUT_EP) { | |
| 392 | − for (i = 0; i < sch_ep->num_budget_microframes; i++) | |
| 393 | − bwb_table[i] = sch_ep->bw_cost_per_microframe; | |
| 394 | − } else if (ep_type == INT_OUT_EP) { | |
| 395 | − /* only first one consumes bandwidth, others as zero */ | |
| 396 | − bwb_table[0] = sch_ep->bw_cost_per_microframe; | |
| 397 | − } else { /* INT_IN_EP or ISOC_IN_EP */ | |
| 398 | − bwb_table[0] = 0; /* start split */ | |
| 399 | − bwb_table[1] = 0; /* idle */ | |
| 400 | − /* | |
| 401 | − * due to cs_count will be updated according to cs | |
| 402 | − * position, assign all remainder budget array | |
| 403 | − * elements as @bw_cost_per_microframe, but only first | |
| 404 | − * @num_budget_microframes elements will be used later | |
| 405 | − */ | |
| 406 | − for (i = 2; i < TT_MICROFRAMES_MAX; i++) | |
| 407 | − bwb_table[i] = sch_ep->bw_cost_per_microframe; | |
| 408 | − } | |
| 360 | + sch_ep->bw_cost_per_microframe = min_t(u32, maxpkt, FS_PAYLOAD_MAX); | |
| 409 | 361 | } |
| 410 | 362 | } |
| 411 | 363 | |
| @@ -422,7 +374,7 @@ static u32 get_max_bw(struct mu3h_sch_bw_info *sch_bw, · 10 unmodified lines | ||
| 422 | 374 | |
| 423 | 375 | for (j = 0; j < sch_ep->num_budget_microframes; j++) { |
| 424 | 376 | k = XHCI_MTK_BW_INDEX(base + j); |
| 425 | − bw = sch_bw->bus_bw[k] + sch_ep->bw_budget_table[j]; | |
| 377 | + bw = sch_bw->bus_bw[k] + sch_ep->bw_cost_per_microframe; | |
| 426 | 378 | if (bw > max_bw) |
| 427 | 379 | max_bw = bw; |
| 428 | 380 | } |
| @@ -433,18 +385,16 @@ static u32 get_max_bw(struct mu3h_sch_bw_info *sch_bw, · 4 unmodified lines | ||
| 433 | 385 | static void update_bus_bw(struct mu3h_sch_bw_info *sch_bw, |
| 434 | 386 | struct mu3h_sch_ep_info *sch_ep, bool used) |
| 435 | 387 | { |
| 388 | + int bw_updated; | |
| 436 | 389 | u32 base; |
| 437 | − int i, j, k; | |
| 390 | + int i, j; | |
| 391 | + | |
| 392 | + bw_updated = sch_ep->bw_cost_per_microframe * (used ? 1 : -1); | |
| 438 | 393 | |
| 439 | 394 | for (i = 0; i < sch_ep->num_esit; i++) { |
| 440 | 395 | base = sch_ep->offset + i * sch_ep->esit; |
| 441 | − for (j = 0; j < sch_ep->num_budget_microframes; j++) { | |
| 442 | − k = XHCI_MTK_BW_INDEX(base + j); | |
| 443 | − if (used) | |
| 444 | − sch_bw->bus_bw[k] += sch_ep->bw_budget_table[j]; | |
| 445 | − else | |
| 446 | − sch_bw->bus_bw[k] -= sch_ep->bw_budget_table[j]; | |
| 447 | − } | |
| 396 | + for (j = 0; j < sch_ep->num_budget_microframes; j++) | |
| 397 | + sch_bw->bus_bw[XHCI_MTK_BW_INDEX(base + j)] += bw_updated; | |
| 448 | 398 | } |
| 449 | 399 | } |
| 450 | 400 | |
| @@ -464,7 +414,7 @@ static int check_fs_bus_bw(struct mu3h_sch_ep_info *sch_ep, int offset) · 13 unmodified lines | ||
| 464 | 414 | */ |
| 465 | 415 | for (j = 0; j < sch_ep->num_budget_microframes; j++) { |
| 466 | 416 | k = XHCI_MTK_BW_INDEX(base + j); |
| 467 | − tmp = tt->fs_bus_bw[k] + sch_ep->bw_budget_table[j]; | |
| 417 | + tmp = tt->fs_bus_bw[k] + sch_ep->bw_cost_per_microframe; | |
| 468 | 418 | if (tmp > FS_PAYLOAD_MAX) |
| 469 | 419 | return -ESCH_BW_OVERFLOW; |
| 470 | 420 | } |
| @@ -538,19 +488,17 @@ static int check_sch_tt(struct mu3h_sch_ep_info *sch_ep, u32 offset) · 67 unmodified lines | ||
| 538 | 488 | static void update_sch_tt(struct mu3h_sch_ep_info *sch_ep, bool used) |
| 539 | 489 | { |
| 540 | 490 | struct mu3h_sch_tt *tt = sch_ep->sch_tt; |
| 491 | + int bw_updated; | |
| 541 | 492 | u32 base; |
| 542 | − int i, j, k; | |
| 493 | + int i, j; | |
| 494 | + | |
| 495 | + bw_updated = sch_ep->bw_cost_per_microframe * (used ? 1 : -1); | |
| 543 | 496 | |
| 544 | 497 | for (i = 0; i < sch_ep->num_esit; i++) { |
| 545 | 498 | base = sch_ep->offset + i * sch_ep->esit; |
| 546 | 499 | |
| 547 | − for (j = 0; j < sch_ep->num_budget_microframes; j++) { | |
| 548 | − k = XHCI_MTK_BW_INDEX(base + j); | |
| 549 | − if (used) | |
| 550 | − tt->fs_bus_bw[k] += sch_ep->bw_budget_table[j]; | |
| 551 | − else | |
| 552 | − tt->fs_bus_bw[k] -= sch_ep->bw_budget_table[j]; | |
| 553 | − } | |
| 500 | + for (j = 0; j < sch_ep->num_budget_microframes; j++) | |
| 501 | + tt->fs_bus_bw[XHCI_MTK_BW_INDEX(base + j)] += bw_updated; | |
| 554 | 502 | } |
| 555 | 503 | |
| 556 | 504 | if (used) |
| @@ -710,7 +658,7 @@ static int add_ep_quirk(struct usb_hcd *hcd, struct usb_device *udev, · 153 unmodified lines | ||
| 710 | 658 | |
| 711 | 659 | xhci_dbg(xhci, "%s %s\n", __func__, decode_ep(ep, udev->speed)); |
| 712 | 660 | |
| 713 | − sch_ep = create_sch_ep(mtk, udev, ep, ep_ctx); | |
| 661 | + sch_ep = create_sch_ep(mtk, udev, ep); | |
| 714 | 662 | if (IS_ERR_OR_NULL(sch_ep)) |
| 715 | 663 | return -ENOMEM; |
| 716 | 664 | |
| @@ -83,7 +83,6 @@ struct mu3h_sch_bw_info { · 82 unmodified lines | ||
| 83 | 83 | * times; 1: distribute the (bMaxBurst+1)*(Mult+1) packets |
| 84 | 84 | * according to @pkts and @repeat. normal mode is used by |
| 85 | 85 | * default |
| 86 | − * @bw_budget_table: table to record bandwidth budget per microframe | |
| 87 | 86 | */ |
| 88 | 87 | struct mu3h_sch_ep_info { |
| 89 | 88 | u32 esit; |
| @@ -109,7 +108,6 @@ struct mu3h_sch_ep_info { · 19 unmodified lines | ||
| 109 | 108 | u32 pkts; |
| 110 | 109 | u32 cs_count; |
| 111 | 110 | u32 burst_mode; |
| 112 | − u32 bw_budget_table[]; | |
| 113 | 111 | }; |
| 114 | 112 | |
| 115 | 113 | #define MU3C_U3_PORT_MAX 4 |
| @@ -59,6 +59,7 @@ · 58 unmodified lines | ||
| 59 | 59 | #define PCI_DEVICE_ID_INTEL_TIGER_LAKE_XHCI 0x9a13 |
| 60 | 60 | #define PCI_DEVICE_ID_INTEL_MAPLE_RIDGE_XHCI 0x1138 |
| 61 | 61 | #define PCI_DEVICE_ID_INTEL_ALDER_LAKE_XHCI 0x461e |
| 62 | +#define PCI_DEVICE_ID_INTEL_ALDER_LAKE_PCH_XHCI 0x51ed | |
| 62 | 63 | |
| 63 | 64 | #define PCI_DEVICE_ID_AMD_RENOIR_XHCI 0x1639 |
| 64 | 65 | #define PCI_DEVICE_ID_AMD_PROMONTORYA_4 0x43b9 |
| @@ -266,7 +267,8 @@ static void xhci_pci_quirks(struct device *dev, struct xhci_hcd *xhci) · 201 unmodified lines | ||
| 266 | 267 | pdev->device == PCI_DEVICE_ID_INTEL_ICE_LAKE_XHCI || |
| 267 | 268 | pdev->device == PCI_DEVICE_ID_INTEL_TIGER_LAKE_XHCI || |
| 268 | 269 | pdev->device == PCI_DEVICE_ID_INTEL_MAPLE_RIDGE_XHCI || |
| 269 | − pdev->device == PCI_DEVICE_ID_INTEL_ALDER_LAKE_XHCI)) | |
| 270 | + pdev->device == PCI_DEVICE_ID_INTEL_ALDER_LAKE_XHCI || | |
| 271 | + pdev->device == PCI_DEVICE_ID_INTEL_ALDER_LAKE_PCH_XHCI)) | |
| 270 | 272 | xhci->quirks |= XHCI_DEFAULT_PM_RUNTIME_ALLOW; |
| 271 | 273 | |
| 272 | 274 | if (pdev->vendor == PCI_VENDOR_ID_ETRON && |
| @@ -3141,6 +3141,7 @@ irqreturn_t xhci_irq(struct usb_hcd *hcd) · 3140 unmodified lines | ||
| 3141 | 3141 | if (event_loop++ < TRBS_PER_SEGMENT / 2) |
| 3142 | 3142 | continue; |
| 3143 | 3143 | xhci_update_erst_dequeue(xhci, event_ring_deq); |
| 3144 | + event_ring_deq = xhci->event_ring->dequeue; | |
| 3144 | 3145 | |
| 3145 | 3146 | /* ring is half-full, force isoc trbs to interrupt more often */ |
| 3146 | 3147 | if (xhci->isoc_bei_interval > AVOID_BEI_INTERVAL_MIN) |
| @@ -1034,13 +1034,13 @@ static int tegra_xusb_unpowergate_partitions(struct tegra_xusb *tegra) · 1033 unmodified lines | ||
| 1034 | 1034 | int rc; |
| 1035 | 1035 | |
| 1036 | 1036 | if (tegra->use_genpd) { |
| 1037 | − rc = pm_runtime_get_sync(tegra->genpd_dev_ss); | |
| 1037 | + rc = pm_runtime_resume_and_get(tegra->genpd_dev_ss); | |
| 1038 | 1038 | if (rc < 0) { |
| 1039 | 1039 | dev_err(dev, "failed to enable XUSB SS partition\n"); |
| 1040 | 1040 | return rc; |
| 1041 | 1041 | } |
| 1042 | 1042 | |
| 1043 | − rc = pm_runtime_get_sync(tegra->genpd_dev_host); | |
| 1043 | + rc = pm_runtime_resume_and_get(tegra->genpd_dev_host); | |
| 1044 | 1044 | if (rc < 0) { |
| 1045 | 1045 | dev_err(dev, "failed to enable XUSB Host partition\n"); |
| 1046 | 1046 | pm_runtime_put_sync(tegra->genpd_dev_ss); |
| @@ -781,6 +781,17 @@ void xhci_shutdown(struct usb_hcd *hcd) · 780 unmodified lines | ||
| 781 | 781 | if (xhci->quirks & XHCI_SPURIOUS_REBOOT) |
| 782 | 782 | usb_disable_xhci_ports(to_pci_dev(hcd->self.sysdev)); |
| 783 | 783 | |
| 784 | + /* Don't poll the roothubs after shutdown. */ | |
| 785 | + xhci_dbg(xhci, "%s: stopping usb%d port polling.\n", | |
| 786 | + __func__, hcd->self.busnum); | |
| 787 | + clear_bit(HCD_FLAG_POLL_RH, &hcd->flags); | |
| 788 | + del_timer_sync(&hcd->rh_timer); | |
| 789 | + | |
| 790 | + if (xhci->shared_hcd) { | |
| 791 | + clear_bit(HCD_FLAG_POLL_RH, &xhci->shared_hcd->flags); | |
| 792 | + del_timer_sync(&xhci->shared_hcd->rh_timer); | |
| 793 | + } | |
| 794 | + | |
| 784 | 795 | spin_lock_irq(&xhci->lock); |
| 785 | 796 | xhci_halt(xhci); |
| 786 | 797 | /* Workaround for spurious wakeups at shutdown with HSW */ |
| @@ -186,16 +186,16 @@ static int eud_probe(struct platform_device *pdev) · 185 unmodified lines | ||
| 186 | 186 | |
| 187 | 187 | chip->dev = &pdev->dev; |
| 188 | 188 | |
| 189 | − ret = devm_add_action_or_reset(chip->dev, eud_role_switch_release, chip); | |
| 190 | − if (ret) | |
| 191 | − return dev_err_probe(chip->dev, ret, | |
| 192 | − "failed to add role switch release action\n"); | |
| 193 | − | |
| 194 | 189 | chip->role_sw = usb_role_switch_get(&pdev->dev); |
| 195 | 190 | if (IS_ERR(chip->role_sw)) |
| 196 | 191 | return dev_err_probe(chip->dev, PTR_ERR(chip->role_sw), |
| 197 | 192 | "failed to get role switch\n"); |
| 198 | 193 | |
| 194 | + ret = devm_add_action_or_reset(chip->dev, eud_role_switch_release, chip); | |
| 195 | + if (ret) | |
| 196 | + return dev_err_probe(chip->dev, ret, | |
| 197 | + "failed to add role switch release action\n"); | |
| 198 | + | |
| 199 | 199 | chip->base = devm_platform_ioremap_resource(pdev, 0); |
| 200 | 200 | if (IS_ERR(chip->base)) |
| 201 | 201 | return PTR_ERR(chip->base); |
| @@ -71,6 +71,7 @@ static void destroy_priv(struct kref *kref) · 70 unmodified lines | ||
| 71 | 71 | |
| 72 | 72 | dev_dbg(&priv->usbdev->dev, "destroying priv datastructure\n"); |
| 73 | 73 | usb_put_dev(priv->usbdev); |
| 74 | + priv->usbdev = NULL; | |
| 74 | 75 | kfree(priv); |
| 75 | 76 | } |
| 76 | 77 | |
| @@ -736,7 +737,6 @@ static int uss720_probe(struct usb_interface *intf, · 659 unmodified lines | ||
| 736 | 737 | parport_announce_port(pp); |
| 737 | 738 | |
| 738 | 739 | usb_set_intfdata(intf, pp); |
| 739 | − usb_put_dev(usbdev); | |
| 740 | 740 | return 0; |
| 741 | 741 | |
| 742 | 742 | probe_abort: |
| @@ -754,7 +754,6 @@ static void uss720_disconnect(struct usb_interface *intf) · 11 unmodified lines | ||
| 754 | 754 | usb_set_intfdata(intf, NULL); |
| 755 | 755 | if (pp) { |
| 756 | 756 | priv = pp->private_data; |
| 757 | − priv->usbdev = NULL; | |
| 758 | 757 | priv->pp = NULL; |
| 759 | 758 | dev_dbg(&intf->dev, "parport_remove_port\n"); |
| 760 | 759 | parport_remove_port(pp); |
| @@ -21,10 +21,8 @@ static inline struct ssusb_mtk *otg_sx_to_ssusb(struct otg_switch_mtk *otg_sx) · 20 unmodified lines | ||
| 21 | 21 | |
| 22 | 22 | static void toggle_opstate(struct ssusb_mtk *ssusb) |
| 23 | 23 | { |
| 24 | − if (!ssusb->otg_switch.is_u3_drd) { | |
| 25 | − mtu3_setbits(ssusb->mac_base, U3D_DEVICE_CONTROL, DC_SESSION); | |
| 26 | − mtu3_setbits(ssusb->mac_base, U3D_POWER_MANAGEMENT, SOFT_CONN); | |
| 27 | − } | |
| 24 | + mtu3_setbits(ssusb->mac_base, U3D_DEVICE_CONTROL, DC_SESSION); | |
| 25 | + mtu3_setbits(ssusb->mac_base, U3D_POWER_MANAGEMENT, SOFT_CONN); | |
| 28 | 26 | } |
| 29 | 27 | |
| 30 | 28 | /* only port0 supports dual-role mode */ |
| @@ -268,6 +268,13 @@ int usb_phy_gen_create_phy(struct device *dev, struct usb_phy_generic *nop) · 267 unmodified lines | ||
| 268 | 268 | return -EPROBE_DEFER; |
| 269 | 269 | } |
| 270 | 270 | |
| 271 | + nop->vbus_draw = devm_regulator_get_exclusive(dev, "vbus"); | |
| 272 | + if (PTR_ERR(nop->vbus_draw) == -ENODEV) | |
| 273 | + nop->vbus_draw = NULL; | |
| 274 | + if (IS_ERR(nop->vbus_draw)) | |
| 275 | + return dev_err_probe(dev, PTR_ERR(nop->vbus_draw), | |
| 276 | + "could not get vbus regulator\n"); | |
| 277 | + | |
| 271 | 278 | nop->dev = dev; |
| 272 | 279 | nop->phy.dev = nop->dev; |
| 273 | 280 | nop->phy.label = "nop-xceiv"; |
| @@ -194,6 +194,8 @@ static const struct usb_device_id id_table[] = { · 193 unmodified lines | ||
| 194 | 194 | { USB_DEVICE(0x16DC, 0x0015) }, /* W-IE-NE-R Plein & Baus GmbH CML Control, Monitoring and Data Logger */ |
| 195 | 195 | { USB_DEVICE(0x17A8, 0x0001) }, /* Kamstrup Optical Eye/3-wire */ |
| 196 | 196 | { USB_DEVICE(0x17A8, 0x0005) }, /* Kamstrup M-Bus Master MultiPort 250D */ |
| 197 | + { USB_DEVICE(0x17A8, 0x0101) }, /* Kamstrup 868 MHz wM-Bus C-Mode Meter Reader (Int Ant) */ | |
| 198 | + { USB_DEVICE(0x17A8, 0x0102) }, /* Kamstrup 868 MHz wM-Bus C-Mode Meter Reader (Ext Ant) */ | |
| 197 | 199 | { USB_DEVICE(0x17F4, 0xAAAA) }, /* Wavesense Jazz blood glucose meter */ |
| 198 | 200 | { USB_DEVICE(0x1843, 0x0200) }, /* Vaisala USB Instrument Cable */ |
| 199 | 201 | { USB_DEVICE(0x18EF, 0xE00F) }, /* ELV USB-I2C-Interface */ |
| @@ -432,6 +432,8 @@ static void option_instat_callback(struct urb *urb); · 431 unmodified lines | ||
| 432 | 432 | #define CINTERION_PRODUCT_CLS8 0x00b0 |
| 433 | 433 | #define CINTERION_PRODUCT_MV31_MBIM 0x00b3 |
| 434 | 434 | #define CINTERION_PRODUCT_MV31_RMNET 0x00b7 |
| 435 | +#define CINTERION_PRODUCT_MV32_WA 0x00f1 | |
| 436 | +#define CINTERION_PRODUCT_MV32_WB 0x00f2 | |
| 435 | 437 | |
| 436 | 438 | /* Olivetti products */ |
| 437 | 439 | #define OLIVETTI_VENDOR_ID 0x0b3c |
| @@ -1217,6 +1219,10 @@ static const struct usb_device_id option_ids[] = { · 779 unmodified lines | ||
| 1217 | 1219 | .driver_info = NCTRL(0) | RSVD(1) }, |
| 1218 | 1220 | { USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x1056, 0xff), /* Telit FD980 */ |
| 1219 | 1221 | .driver_info = NCTRL(2) | RSVD(3) }, |
| 1222 | + { USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x1057, 0xff), /* Telit FN980 */ | |
| 1223 | + .driver_info = NCTRL(0) | RSVD(1) | RSVD(2) }, | |
| 1224 | + { USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x1058, 0xff), /* Telit FN980 (PCIe) */ | |
| 1225 | + .driver_info = NCTRL(0) | RSVD(1) }, | |
| 1220 | 1226 | { USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x1060, 0xff), /* Telit LN920 (rmnet) */ |
| 1221 | 1227 | .driver_info = NCTRL(0) | RSVD(1) | RSVD(2) }, |
| 1222 | 1228 | { USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x1061, 0xff), /* Telit LN920 (MBIM) */ |
| @@ -1233,6 +1239,8 @@ static const struct usb_device_id option_ids[] = { · 10 unmodified lines | ||
| 1233 | 1239 | .driver_info = NCTRL(2) | RSVD(3) }, |
| 1234 | 1240 | { USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x1073, 0xff), /* Telit FN990 (ECM) */ |
| 1235 | 1241 | .driver_info = NCTRL(0) | RSVD(1) }, |
| 1242 | + { USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x1075, 0xff), /* Telit FN990 (PCIe) */ | |
| 1243 | + .driver_info = RSVD(0) }, | |
| 1236 | 1244 | { USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_ME910), |
| 1237 | 1245 | .driver_info = NCTRL(0) | RSVD(1) | RSVD(3) }, |
| 1238 | 1246 | { USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_ME910_DUAL_MODEM), |
| @@ -1969,6 +1977,10 @@ static const struct usb_device_id option_ids[] = { · 730 unmodified lines | ||
| 1969 | 1977 | .driver_info = RSVD(3)}, |
| 1970 | 1978 | { USB_DEVICE_INTERFACE_CLASS(CINTERION_VENDOR_ID, CINTERION_PRODUCT_MV31_RMNET, 0xff), |
| 1971 | 1979 | .driver_info = RSVD(0)}, |
| 1980 | + { USB_DEVICE_INTERFACE_CLASS(CINTERION_VENDOR_ID, CINTERION_PRODUCT_MV32_WA, 0xff), | |
| 1981 | + .driver_info = RSVD(3)}, | |
| 1982 | + { USB_DEVICE_INTERFACE_CLASS(CINTERION_VENDOR_ID, CINTERION_PRODUCT_MV32_WB, 0xff), | |
| 1983 | + .driver_info = RSVD(3)}, | |
| 1972 | 1984 | { USB_DEVICE(OLIVETTI_VENDOR_ID, OLIVETTI_PRODUCT_OLICARD100), |
| 1973 | 1985 | .driver_info = RSVD(4) }, |
| 1974 | 1986 | { USB_DEVICE(OLIVETTI_VENDOR_ID, OLIVETTI_PRODUCT_OLICARD120), |
| @@ -2111,10 +2123,14 @@ static const struct usb_device_id option_ids[] = { · 136 unmodified lines | ||
| 2111 | 2123 | .driver_info = RSVD(3) }, |
| 2112 | 2124 | { USB_DEVICE(0x1508, 0x1001), /* Fibocom NL668 (IOT version) */ |
| 2113 | 2125 | .driver_info = RSVD(4) | RSVD(5) | RSVD(6) }, |
| 2126 | + { USB_DEVICE(0x1782, 0x4d10) }, /* Fibocom L610 (AT mode) */ | |
| 2127 | + { USB_DEVICE_INTERFACE_CLASS(0x1782, 0x4d11, 0xff) }, /* Fibocom L610 (ECM/RNDIS mode) */ | |
| 2114 | 2128 | { USB_DEVICE(0x2cb7, 0x0104), /* Fibocom NL678 series */ |
| 2115 | 2129 | .driver_info = RSVD(4) | RSVD(5) }, |
| 2116 | 2130 | { USB_DEVICE_INTERFACE_CLASS(0x2cb7, 0x0105, 0xff), /* Fibocom NL678 series */ |
| 2117 | 2131 | .driver_info = RSVD(6) }, |
| 2132 | + { USB_DEVICE_INTERFACE_CLASS(0x2cb7, 0x0106, 0xff) }, /* Fibocom MA510 (ECM mode w/ diag intf.) */ | |
| 2133 | + { USB_DEVICE_INTERFACE_CLASS(0x2cb7, 0x010a, 0xff) }, /* Fibocom MA510 (ECM mode) */ | |
| 2118 | 2134 | { USB_DEVICE_AND_INTERFACE_INFO(0x2cb7, 0x010b, 0xff, 0xff, 0x30) }, /* Fibocom FG150 Diag */ |
| 2119 | 2135 | { USB_DEVICE_AND_INTERFACE_INFO(0x2cb7, 0x010b, 0xff, 0, 0) }, /* Fibocom FG150 AT */ |
| 2120 | 2136 | { USB_DEVICE_INTERFACE_CLASS(0x2cb7, 0x01a0, 0xff) }, /* Fibocom NL668-AM/NL652-EU (laptop MBIM) */ |
| @@ -106,6 +106,7 @@ static const struct usb_device_id id_table[] = { · 105 unmodified lines | ||
| 106 | 106 | { USB_DEVICE(HP_VENDOR_ID, HP_LCM220_PRODUCT_ID) }, |
| 107 | 107 | { USB_DEVICE(HP_VENDOR_ID, HP_LCM960_PRODUCT_ID) }, |
| 108 | 108 | { USB_DEVICE(HP_VENDOR_ID, HP_LM920_PRODUCT_ID) }, |
| 109 | + { USB_DEVICE(HP_VENDOR_ID, HP_LM930_PRODUCT_ID) }, | |
| 109 | 110 | { USB_DEVICE(HP_VENDOR_ID, HP_LM940_PRODUCT_ID) }, |
| 110 | 111 | { USB_DEVICE(HP_VENDOR_ID, HP_TD620_PRODUCT_ID) }, |
| 111 | 112 | { USB_DEVICE(CRESSI_VENDOR_ID, CRESSI_EDY_PRODUCT_ID) }, |
| @@ -135,6 +135,7 @@ · 134 unmodified lines | ||
| 135 | 135 | #define HP_TD620_PRODUCT_ID 0x0956 |
| 136 | 136 | #define HP_LD960_PRODUCT_ID 0x0b39 |
| 137 | 137 | #define HP_LD381_PRODUCT_ID 0x0f7f |
| 138 | +#define HP_LM930_PRODUCT_ID 0x0f9b | |
| 138 | 139 | #define HP_LCM220_PRODUCT_ID 0x3139 |
| 139 | 140 | #define HP_LCM960_PRODUCT_ID 0x3239 |
| 140 | 141 | #define HP_LD220_PRODUCT_ID 0x3524 |
| @@ -166,6 +166,8 @@ static const struct usb_device_id id_table[] = { · 165 unmodified lines | ||
| 166 | 166 | {DEVICE_SWI(0x1199, 0x9090)}, /* Sierra Wireless EM7565 QDL */ |
| 167 | 167 | {DEVICE_SWI(0x1199, 0x9091)}, /* Sierra Wireless EM7565 */ |
| 168 | 168 | {DEVICE_SWI(0x1199, 0x90d2)}, /* Sierra Wireless EM9191 QDL */ |
| 169 | + {DEVICE_SWI(0x1199, 0xc080)}, /* Sierra Wireless EM7590 QDL */ | |
| 170 | + {DEVICE_SWI(0x1199, 0xc081)}, /* Sierra Wireless EM7590 */ | |
| 169 | 171 | {DEVICE_SWI(0x413c, 0x81a2)}, /* Dell Wireless 5806 Gobi(TM) 4G LTE Mobile Broadband Card */ |
| 170 | 172 | {DEVICE_SWI(0x413c, 0x81a3)}, /* Dell Wireless 5570 HSPA+ (42Mbps) Mobile Broadband Card */ |
| 171 | 173 | {DEVICE_SWI(0x413c, 0x81a4)}, /* Dell Wireless 5570e HSPA+ (42Mbps) Mobile Broadband Card */ |
| @@ -584,9 +584,8 @@ static int firm_send_command(struct usb_serial_port *port, __u8 command, · 583 unmodified lines | ||
| 584 | 584 | switch (command) { |
| 585 | 585 | case WHITEHEAT_GET_DTR_RTS: |
| 586 | 586 | info = usb_get_serial_port_data(port); |
| 587 | − memcpy(&info->mcr, command_info->result_buffer, | |
| 588 | − sizeof(struct whiteheat_dr_info)); | |
| 589 | − break; | |
| 587 | + info->mcr = command_info->result_buffer[0]; | |
| 588 | + break; | |
| 590 | 589 | } |
| 591 | 590 | } |
| 592 | 591 | exit: |
| @@ -56,6 +56,7 @@ config TYPEC_RT1719 · 55 unmodified lines | ||
| 56 | 56 | tristate "Richtek RT1719 Sink Only Type-C controller driver" |
| 57 | 57 | depends on USB_ROLE_SWITCH || !USB_ROLE_SWITCH |
| 58 | 58 | depends on I2C |
| 59 | + depends on POWER_SUPPLY | |
| 59 | 60 | select REGMAP_I2C |
| 60 | 61 | help |
| 61 | 62 | Say Y or M here if your system has Richtek RT1719 sink only |
| @@ -877,7 +877,7 @@ static int tcpci_remove(struct i2c_client *client) · 876 unmodified lines | ||
| 877 | 877 | /* Disable chip interrupts before unregistering port */ |
| 878 | 878 | err = tcpci_write16(chip->tcpci, TCPC_ALERT_MASK, 0); |
| 879 | 879 | if (err < 0) |
| 880 | − return err; | |
| 880 | + dev_warn(&client->dev, "Failed to disable irqs (%pe)\n", ERR_PTR(err)); | |
| 881 | 881 | |
| 882 | 882 | tcpci_unregister_port(chip->tcpci); |
| 883 | 883 | |
| @@ -15,6 +15,9 @@ · 14 unmodified lines | ||
| 15 | 15 | |
| 16 | 16 | #include "tcpci.h" |
| 17 | 17 | |
| 18 | +#define MT6360_REG_PHYCTRL1 0x80 | |
| 19 | +#define MT6360_REG_PHYCTRL3 0x82 | |
| 20 | +#define MT6360_REG_PHYCTRL7 0x86 | |
| 18 | 21 | #define MT6360_REG_VCONNCTRL1 0x8C |
| 19 | 22 | #define MT6360_REG_MODECTRL2 0x8F |
| 20 | 23 | #define MT6360_REG_SWRESET 0xA0 |
| @@ -22,6 +25,8 @@ · 1 unmodified line | ||
| 22 | 25 | #define MT6360_REG_DRPCTRL1 0xA2 |
| 23 | 26 | #define MT6360_REG_DRPCTRL2 0xA3 |
| 24 | 27 | #define MT6360_REG_I2CTORST 0xBF |
| 28 | +#define MT6360_REG_PHYCTRL11 0xCA | |
| 29 | +#define MT6360_REG_RXCTRL1 0xCE | |
| 25 | 30 | #define MT6360_REG_RXCTRL2 0xCF |
| 26 | 31 | #define MT6360_REG_CTDCTRL2 0xEC |
| 27 | 32 | |
| @@ -106,6 +111,27 @@ static int mt6360_tcpc_init(struct tcpci *tcpci, struct tcpci_data *tdata) · 78 unmodified lines | ||
| 106 | 111 | if (ret) |
| 107 | 112 | return ret; |
| 108 | 113 | |
| 114 | + /* BMC PHY */ | |
| 115 | + ret = mt6360_tcpc_write16(regmap, MT6360_REG_PHYCTRL1, 0x3A70); | |
| 116 | + if (ret) | |
| 117 | + return ret; | |
| 118 | + | |
| 119 | + ret = regmap_write(regmap, MT6360_REG_PHYCTRL3, 0x82); | |
| 120 | + if (ret) | |
| 121 | + return ret; | |
| 122 | + | |
| 123 | + ret = regmap_write(regmap, MT6360_REG_PHYCTRL7, 0x36); | |
| 124 | + if (ret) | |
| 125 | + return ret; | |
| 126 | + | |
| 127 | + ret = mt6360_tcpc_write16(regmap, MT6360_REG_PHYCTRL11, 0x3C60); | |
| 128 | + if (ret) | |
| 129 | + return ret; | |
| 130 | + | |
| 131 | + ret = regmap_write(regmap, MT6360_REG_RXCTRL1, 0xE8); | |
| 132 | + if (ret) | |
| 133 | + return ret; | |
| 134 | + | |
| 109 | 135 | /* Set shipping mode off, AUTOIDLE on */ |
| 110 | 136 | return regmap_write(regmap, MT6360_REG_MODECTRL2, 0x7A); |
| 111 | 137 | } |
| @@ -949,6 +949,8 @@ static int ucsi_dr_swap(struct typec_port *port, enum typec_data_role role) · 948 unmodified lines | ||
| 949 | 949 | role == TYPEC_HOST)) |
| 950 | 950 | goto out_unlock; |
| 951 | 951 | |
| 952 | + reinit_completion(&con->complete); | |
| 953 | + | |
| 952 | 954 | command = UCSI_SET_UOR | UCSI_CONNECTOR_NUMBER(con->num); |
| 953 | 955 | command |= UCSI_SET_UOR_ROLE(role); |
| 954 | 956 | command |= UCSI_SET_UOR_ACCEPT_ROLE_SWAPS; |
| @@ -956,14 +958,18 @@ static int ucsi_dr_swap(struct typec_port *port, enum typec_data_role role) · 1 unmodified line | ||
| 956 | 958 | if (ret < 0) |
| 957 | 959 | goto out_unlock; |
| 958 | 960 | |
| 961 | + mutex_unlock(&con->lock); | |
| 962 | + | |
| 959 | 963 | if (!wait_for_completion_timeout(&con->complete, |
| 960 | − msecs_to_jiffies(UCSI_SWAP_TIMEOUT_MS))) | |
| 961 | − ret = -ETIMEDOUT; | |
| 964 | + msecs_to_jiffies(UCSI_SWAP_TIMEOUT_MS))) | |
| 965 | + return -ETIMEDOUT; | |
| 966 | + | |
| 967 | + return 0; | |
| 962 | 968 | |
| 963 | 969 | out_unlock: |
| 964 | 970 | mutex_unlock(&con->lock); |
| 965 | 971 | |
| 966 | − return ret < 0 ? ret : 0; | |
| 972 | + return ret; | |
| 967 | 973 | } |
| 968 | 974 | |
| 969 | 975 | static int ucsi_pr_swap(struct typec_port *port, enum typec_role role) |
| @@ -985,6 +991,8 @@ static int ucsi_pr_swap(struct typec_port *port, enum typec_role role) · 15 unmodified lines | ||
| 985 | 991 | if (cur_role == role) |
| 986 | 992 | goto out_unlock; |
| 987 | 993 | |
| 994 | + reinit_completion(&con->complete); | |
| 995 | + | |
| 988 | 996 | command = UCSI_SET_PDR | UCSI_CONNECTOR_NUMBER(con->num); |
| 989 | 997 | command |= UCSI_SET_PDR_ROLE(role); |
| 990 | 998 | command |= UCSI_SET_PDR_ACCEPT_ROLE_SWAPS; |
| @@ -992,11 +1000,13 @@ static int ucsi_pr_swap(struct typec_port *port, enum typec_role role) · 1 unmodified line | ||
| 992 | 1000 | if (ret < 0) |
| 993 | 1001 | goto out_unlock; |
| 994 | 1002 | |
| 1003 | + mutex_unlock(&con->lock); | |
| 1004 | + | |
| 995 | 1005 | if (!wait_for_completion_timeout(&con->complete, |
| 996 | − msecs_to_jiffies(UCSI_SWAP_TIMEOUT_MS))) { | |
| 997 | − ret = -ETIMEDOUT; | |
| 998 | − goto out_unlock; | |
| 999 | − } | |
| 1006 | + msecs_to_jiffies(UCSI_SWAP_TIMEOUT_MS))) | |
| 1007 | + return -ETIMEDOUT; | |
| 1008 | + | |
| 1009 | + mutex_lock(&con->lock); | |
| 1000 | 1010 | |
| 1001 | 1011 | /* Something has gone wrong while swapping the role */ |
| 1002 | 1012 | if (UCSI_CONSTAT_PWR_OPMODE(con->status.flags) != |
| @@ -588,6 +588,7 @@ static struct fsl_mc_driver vfio_fsl_mc_driver = { · 587 unmodified lines | ||
| 588 | 588 | .name = "vfio-fsl-mc", |
| 589 | 589 | .owner = THIS_MODULE, |
| 590 | 590 | }, |
| 591 | + .driver_managed_dma = true, | |
| 591 | 592 | }; |
| 592 | 593 | |
| 593 | 594 | static int __init vfio_fsl_mc_driver_init(void) |
| @@ -194,6 +194,7 @@ static struct pci_driver vfio_pci_driver = { · 193 unmodified lines | ||
| 194 | 194 | .remove = vfio_pci_remove, |
| 195 | 195 | .sriov_configure = vfio_pci_sriov_configure, |
| 196 | 196 | .err_handler = &vfio_pci_core_err_handlers, |
| 197 | + .driver_managed_dma = true, | |
| 197 | 198 | }; |
| 198 | 199 | |
| 199 | 200 | static void __init vfio_pci_fill_ids(void) |
| @@ -95,6 +95,7 @@ static struct amba_driver vfio_amba_driver = { · 94 unmodified lines | ||
| 95 | 95 | .name = "vfio-amba", |
| 96 | 96 | .owner = THIS_MODULE, |
| 97 | 97 | }, |
| 98 | + .driver_managed_dma = true, | |
| 98 | 99 | }; |
| 99 | 100 | |
| 100 | 101 | module_amba_driver(vfio_amba_driver); |
| @@ -76,6 +76,7 @@ static struct platform_driver vfio_platform_driver = { · 75 unmodified lines | ||
| 76 | 76 | .driver = { |
| 77 | 77 | .name = "vfio-platform", |
| 78 | 78 | }, |
| 79 | + .driver_managed_dma = true, | |
| 79 | 80 | }; |
| 80 | 81 | |
| 81 | 82 | module_platform_driver(vfio_platform_driver); |
| @@ -62,11 +62,6 @@ struct vfio_container { · 61 unmodified lines | ||
| 62 | 62 | bool noiommu; |
| 63 | 63 | }; |
| 64 | 64 | |
| 65 | −struct vfio_unbound_dev { | |
| 66 | − struct device *dev; | |
| 67 | − struct list_head unbound_next; | |
| 68 | −}; | |
| 69 | − | |
| 70 | 65 | struct vfio_group { |
| 71 | 66 | struct device dev; |
| 72 | 67 | struct cdev cdev; |
| @@ -76,11 +71,8 @@ struct vfio_group { · 3 unmodified lines | ||
| 76 | 71 | struct vfio_container *container; |
| 77 | 72 | struct list_head device_list; |
| 78 | 73 | struct mutex device_lock; |
| 79 | − struct notifier_block nb; | |
| 80 | 74 | struct list_head vfio_next; |
| 81 | 75 | struct list_head container_next; |
| 82 | − struct list_head unbound_list; | |
| 83 | − struct mutex unbound_lock; | |
| 84 | 76 | atomic_t opened; |
| 85 | 77 | wait_queue_head_t container_q; |
| 86 | 78 | enum vfio_group_type type; |
| @@ -281,8 +273,6 @@ void vfio_unregister_iommu_driver(const struct vfio_iommu_driver_ops *ops) · 194 unmodified lines | ||
| 281 | 273 | } |
| 282 | 274 | EXPORT_SYMBOL_GPL(vfio_unregister_iommu_driver); |
| 283 | 275 | |
| 284 | −static int vfio_iommu_group_notifier(struct notifier_block *nb, | |
| 285 | − unsigned long action, void *data); | |
| 286 | 276 | static void vfio_group_get(struct vfio_group *group); |
| 287 | 277 | |
| 288 | 278 | /* |
| @@ -340,16 +330,8 @@ vfio_group_get_from_iommu(struct iommu_group *iommu_group) · 51 unmodified lines | ||
| 340 | 330 | static void vfio_group_release(struct device *dev) |
| 341 | 331 | { |
| 342 | 332 | struct vfio_group *group = container_of(dev, struct vfio_group, dev); |
| 343 | − struct vfio_unbound_dev *unbound, *tmp; | |
| 344 | − | |
347 more lines aren’t shown here.
This diff is large: its 92 lines aren’t shown here.
This diff is large: its 10 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 10 lines aren’t shown here.
This diff is large: its 10 lines aren’t shown here.
This diff is large: its 11 lines aren’t shown here.
This diff is large: its 36 lines aren’t shown here.
This diff is large: its 19 lines aren’t shown here.
This diff is large: its 13 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 25 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 27 lines aren’t shown here.
This diff is large: its 27 lines aren’t shown here.
This diff is large: its 26 lines aren’t shown here.
This diff is large: its 11 lines aren’t shown here.
This diff is large: its 22 lines aren’t shown here.
This diff is large: its 13 lines aren’t shown here.
This diff is large: its 10 lines aren’t shown here.
This diff is large: its 10 lines aren’t shown here.
This diff is large: its 30 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 10 lines aren’t shown here.
This diff is large: its 44 lines aren’t shown here.
This diff is large: its 12 lines aren’t shown here.
This diff is large: its 32 lines aren’t shown here.
This diff is large: its 10 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 18 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 14 lines aren’t shown here.
This diff is large: its 26 lines aren’t shown here.
This diff is large: its 61 lines aren’t shown here.
This diff is large: its 105 lines aren’t shown here.
This diff is large: its 118 lines aren’t shown here.
This diff is large: its 11 lines aren’t shown here.
This diff is large: its 40 lines aren’t shown here.
This diff is large: its 10 lines aren’t shown here.
This diff is large: its 100 lines aren’t shown here.
This diff is large: its 10 lines aren’t shown here.
This diff is large: its 35 lines aren’t shown here.
This diff is large: its 57 lines aren’t shown here.
This diff is large: its 18 lines aren’t shown here.
This diff is large: its 40 lines aren’t shown here.
This diff is large: its 42 lines aren’t shown here.
This diff is large: its 30 lines aren’t shown here.
This diff is large: its 20 lines aren’t shown here.
This diff is large: its 13 lines aren’t shown here.
This diff is large: its 58 lines aren’t shown here.
This diff is large: its 30 lines aren’t shown here.
This diff is large: its 10 lines aren’t shown here.
This diff is large: its 102 lines aren’t shown here.
This diff is large: its 81 lines aren’t shown here.
This diff is large: its 11 lines aren’t shown here.
This diff is large: its 19 lines aren’t shown here.
This diff is large: its 293 lines aren’t shown here.
This diff is large: its 49 lines aren’t shown here.
This diff is large: its 14 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 26 lines aren’t shown here.
This diff is large: its 20 lines aren’t shown here.
This diff is large: its 50 lines aren’t shown here.
This diff is large: its 28 lines aren’t shown here.
This diff is large: its 27 lines aren’t shown here.
This diff is large: its 70 lines aren’t shown here.
This diff is large: its 42 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 93 lines aren’t shown here.
This diff is large: its 25 lines aren’t shown here.
This diff is large: its 17 lines aren’t shown here.
This diff is large: its 218 lines aren’t shown here.
This diff is large: its 409 lines aren’t shown here.
This diff is large: its 7 lines aren’t shown here.
This diff is large: its 15 lines aren’t shown here.
This diff is large: its 28 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 17 lines aren’t shown here.
This diff is large: its 22 lines aren’t shown here.
This diff is large: its 10 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 137 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 13 lines aren’t shown here.
This diff is large: its 18 lines aren’t shown here.
This diff is large: its 51 lines aren’t shown here.
This diff is large: its 22 lines aren’t shown here.
This diff is large: its 24 lines aren’t shown here.
This diff is large: its 7 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 16 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 19 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 11 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 36 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 16 lines aren’t shown here.
This diff is large: its 15 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 24 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 20 lines aren’t shown here.
This diff is large: its 14 lines aren’t shown here.
This diff is large: its 16 lines aren’t shown here.
This diff is large: its 15 lines aren’t shown here.
This diff is large: its 24 lines aren’t shown here.
This diff is large: its 67 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 18 lines aren’t shown here.
This diff is large: its 12 lines aren’t shown here.
This diff is large: its 12 lines aren’t shown here.
This diff is large: its 24 lines aren’t shown here.
This diff is large: its 12 lines aren’t shown here.
This diff is large: its 11 lines aren’t shown here.
This diff is large: its 11 lines aren’t shown here.
This diff is large: its 64 lines aren’t shown here.
This diff is large: its 58 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 18 lines aren’t shown here.
This diff is large: its 14 lines aren’t shown here.
This diff is large: its 17 lines aren’t shown here.
This diff is large: its 29 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 43 lines aren’t shown here.
This diff is large: its 18 lines aren’t shown here.
This diff is large: its 67 lines aren’t shown here.
This diff is large: its 22 lines aren’t shown here.
This diff is large: its 186 lines aren’t shown here.
This diff is large: its 23 lines aren’t shown here.
This diff is large: its 33 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 46 lines aren’t shown here.
This diff is large: its 13 lines aren’t shown here.
This diff is large: its 35 lines aren’t shown here.
This diff is large: its 29 lines aren’t shown here.
This diff is large: its 48 lines aren’t shown here.
This diff is large: its 21 lines aren’t shown here.
This diff is large: its 18 lines aren’t shown here.
This diff is large: its 10 lines aren’t shown here.
This diff is large: its 18 lines aren’t shown here.
This diff is large: its 19 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 28 lines aren’t shown here.
This diff is large: its 89 lines aren’t shown here.
This diff is large: its 36 lines aren’t shown here.
Empty file deleted.
This diff is large: its 33 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 29 lines aren’t shown here.
This diff is large: its 29 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 36 lines aren’t shown here.
This diff is large: its 18 lines aren’t shown here.
This diff is large: its 51 lines aren’t shown here.
This diff is large: its 28 lines aren’t shown here.
This diff is large: its 30 lines aren’t shown here.
This diff is large: its 10 lines aren’t shown here.
This diff is large: its 13 lines aren’t shown here.
This diff is large: its 10 lines aren’t shown here.
This diff is large: its 16 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 39 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 13 lines aren’t shown here.
This diff is large: its 80 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 130 lines aren’t shown here.
This diff is large: its 18 lines aren’t shown here.
This diff is large: its 38 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 12 lines aren’t shown here.
This diff is large: its 12 lines aren’t shown here.
This diff is large: its 17 lines aren’t shown here.
This diff is large: its 58 lines aren’t shown here.
This diff is large: its 11 lines aren’t shown here.
This diff is large: its 243 lines aren’t shown here.
This diff is large: its 42 lines aren’t shown here.
This diff is large: its 13 lines aren’t shown here.
This diff is large: its 15 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 79 lines aren’t shown here.
This diff is large: its 74 lines aren’t shown here.
This diff is large: its 30 lines aren’t shown here.
This diff is large: its 42 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 29 lines aren’t shown here.
This diff is large: its 31 lines aren’t shown here.
This diff is large: its 15 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 36 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 32 lines aren’t shown here.
This diff is large: its 19 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 36 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 44 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 14 lines aren’t shown here.
This diff is large: its 41 lines aren’t shown here.
This diff is large: its 12 lines aren’t shown here.
This diff is large: its 24 lines aren’t shown here.
This diff is large: its 206 lines aren’t shown here.
This diff is large: its 212 lines aren’t shown here.
This diff is large: its 18 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 24 lines aren’t shown here.
This diff is large: its 28 lines aren’t shown here.
This diff is large: its 6 lines aren’t shown here.
This diff is large: its 26 lines aren’t shown here.
This diff is large: its 20 lines aren’t shown here.
This diff is large: its 16 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 13 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 14 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 72 lines aren’t shown here.
This diff is large: its 17 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 31 lines aren’t shown here.
This diff is large: its 15 lines aren’t shown here.
This diff is large: its 286 lines aren’t shown here.
This diff is large: its 34 lines aren’t shown here.
This diff is large: its 86 lines aren’t shown here.
This diff is large: its 13 lines aren’t shown here.
This diff is large: its 18 lines aren’t shown here.
This diff is large: its 102 lines aren’t shown here.
This diff is large: its 45 lines aren’t shown here.
This diff is large: its 31 lines aren’t shown here.
This diff is large: its 60 lines aren’t shown here.
This diff is large: its 5 lines aren’t shown here.
This diff is large: its 417 lines aren’t shown here.
This diff is large: its 10 lines aren’t shown here.
This diff is large: its 11 lines aren’t shown here.
This diff is large: its 11 lines aren’t shown here.
This diff is large: its 12 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 7 lines aren’t shown here.
This diff is large: its 7 lines aren’t shown here.
This diff is large: its 7 lines aren’t shown here.
This diff is large: its 7 lines aren’t shown here.
This diff is large: its 7 lines aren’t shown here.
This diff is large: its 7 lines aren’t shown here.
This diff is large: its 14 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 13 lines aren’t shown here.
This diff is large: its 13 lines aren’t shown here.
This diff is large: its 7 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 13 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.