Cross-merge networking fixes after downstream PR. No conflicts (or adjacent changes of note).
Unified · Split
| @@ -377,6 +377,7 @@ Matthew Wilcox <willy@infradead.org> <willy@debian.org> · 376 unmodified lines | ||
| 377 | 377 | Matthew Wilcox <willy@infradead.org> <willy@linux.intel.com> |
| 378 | 378 | Matthew Wilcox <willy@infradead.org> <willy@parisc-linux.org> |
| 379 | 379 | Matthias Fuchs <socketcan@esd.eu> <matthias.fuchs@esd.eu> |
| 380 | +Matthieu Baerts <matttbe@kernel.org> <matthieu.baerts@tessares.net> | |
| 380 | 381 | Matthieu CASTET <castet.matthieu@free.fr> |
| 381 | 382 | Matti Vaittinen <mazziesaccount@gmail.com> <matti.vaittinen@fi.rohmeurope.com> |
| 382 | 383 | Matt Ranostay <matt.ranostay@konsulko.com> <matt@ranostay.consulting> |
| @@ -92,6 +92,13 @@ Brief summary of control files. · 91 unmodified lines | ||
| 92 | 92 | memory.oom_control set/show oom controls. |
| 93 | 93 | memory.numa_stat show the number of memory usage per numa |
| 94 | 94 | node |
| 95 | + memory.kmem.limit_in_bytes Deprecated knob to set and read the kernel | |
| 96 | + memory hard limit. Kernel hard limit is not | |
| 97 | + supported since 5.16. Writing any value to | |
| 98 | + do file will not have any effect same as if | |
| 99 | + nokmem kernel parameter was specified. | |
| 100 | + Kernel memory is still charged and reported | |
| 101 | + by memory.kmem.usage_in_bytes. | |
| 95 | 102 | memory.kmem.usage_in_bytes show current kernel memory allocation |
| 96 | 103 | memory.kmem.failcnt show the number of kernel memory usage |
| 97 | 104 | hits limits |
| @@ -175,6 +175,8 @@ infrastructure: · 174 unmodified lines | ||
| 175 | 175 | +------------------------------+---------+---------+ |
| 176 | 176 | | Name | bits | visible | |
| 177 | 177 | +------------------------------+---------+---------+ |
| 178 | + | SME | [27-24] | y | | |
| 179 | + +------------------------------+---------+---------+ | |
| 178 | 180 | | MTE | [11-8] | y | |
| 179 | 181 | +------------------------------+---------+---------+ |
| 180 | 182 | | SSBS | [7-4] | y | |
| @@ -288,8 +290,18 @@ infrastructure: · 107 unmodified lines | ||
| 288 | 290 | +------------------------------+---------+---------+ |
| 289 | 291 | | Name | bits | visible | |
| 290 | 292 | +------------------------------+---------+---------+ |
| 293 | + | CSSC | [55-52] | y | | |
| 294 | + +------------------------------+---------+---------+ | |
| 295 | + | RPRFM | [51-48] | y | | |
| 296 | + +------------------------------+---------+---------+ | |
| 297 | + | BC | [23-20] | y | | |
| 298 | + +------------------------------+---------+---------+ | |
| 291 | 299 | | MOPS | [19-16] | y | |
| 292 | 300 | +------------------------------+---------+---------+ |
| 301 | + | APA3 | [15-12] | y | | |
| 302 | + +------------------------------+---------+---------+ | |
| 303 | + | GPA3 | [11-8] | y | | |
| 304 | + +------------------------------+---------+---------+ | |
| 293 | 305 | | RPRES | [7-4] | y | |
| 294 | 306 | +------------------------------+---------+---------+ |
| 295 | 307 | | WFXT | [3-0] | y | |
| @@ -305,6 +305,9 @@ HWCAP2_SMEF16F16 · 304 unmodified lines | ||
| 305 | 305 | HWCAP2_MOPS |
| 306 | 306 | Functionality implied by ID_AA64ISAR2_EL1.MOPS == 0b0001. |
| 307 | 307 | |
| 308 | +HWCAP2_HBC | |
| 309 | + Functionality implied by ID_AA64ISAR2_EL1.BC == 0b0001. | |
| 310 | + | |
| 308 | 311 | 4. Unused AT_HWCAP bits |
| 309 | 312 | ----------------------- |
| 310 | 313 | |
| @@ -381,9 +381,9 @@ Documentation of LoongArch ISA: · 380 unmodified lines | ||
| 381 | 381 | |
| 382 | 382 | Documentation of LoongArch ELF psABI: |
| 383 | 383 | |
| 384 | − https://github.com/loongson/LoongArch-Documentation/releases/latest/download/LoongArch-ELF-ABI-v2.00-CN.pdf (in Chinese) | |
| 384 | + https://github.com/loongson/LoongArch-Documentation/releases/latest/download/LoongArch-ELF-ABI-v2.01-CN.pdf (in Chinese) | |
| 385 | 385 | |
| 386 | − https://github.com/loongson/LoongArch-Documentation/releases/latest/download/LoongArch-ELF-ABI-v2.00-EN.pdf (in English) | |
| 386 | + https://github.com/loongson/LoongArch-Documentation/releases/latest/download/LoongArch-ELF-ABI-v2.01-EN.pdf (in English) | |
| 387 | 387 | |
| 388 | 388 | Linux kernel repository of Loongson and LoongArch: |
| 389 | 389 | |
| @@ -38,6 +38,7 @@ patternProperties: · 37 unmodified lines | ||
| 38 | 38 | ID number 0 and the slave drive will have ID number 1. The PATA port |
| 39 | 39 | nodes will be named "ide-port". |
| 40 | 40 | type: object |
| 41 | + additionalProperties: false | |
| 41 | 42 | |
| 42 | 43 | properties: |
| 43 | 44 | reg: |
| @@ -37,6 +37,9 @@ properties: · 36 unmodified lines | ||
| 37 | 37 | maxItems: 1 |
| 38 | 38 | |
| 39 | 39 | '#clock-cells': |
| 40 | + description: | |
| 41 | + The index in the assigned-clocks is mapped to the output clock as below | |
| 42 | + 0 - REF, 1 - SE1, 2 - SE2, 3 - SE3, 4 - DIFF1, 5 - DIFF2. | |
| 40 | 43 | const: 1 |
| 41 | 44 | |
| 42 | 45 | clocks: |
| @@ -68,7 +71,7 @@ examples: · 25 unmodified lines | ||
| 68 | 71 | reg = <0x68>; |
| 69 | 72 | #clock-cells = <1>; |
| 70 | 73 | |
| 71 | − clocks = <&x1_x2>; | |
| 74 | + clocks = <&x1>; | |
| 72 | 75 | |
| 73 | 76 | renesas,settings = [ |
| 74 | 77 | 80 00 11 19 4c 02 23 7f 83 19 08 a9 5f 25 24 bf |
| @@ -79,8 +82,8 @@ examples: · 4 unmodified lines | ||
| 79 | 82 | assigned-clocks = <&versa3 0>, <&versa3 1>, |
| 80 | 83 | <&versa3 2>, <&versa3 3>, |
| 81 | 84 | <&versa3 4>, <&versa3 5>; |
| 82 | − assigned-clock-rates = <12288000>, <25000000>, | |
| 83 | − <12000000>, <11289600>, | |
| 84 | − <11289600>, <24000000>; | |
| 85 | + assigned-clock-rates = <24000000>, <11289600>, | |
| 86 | + <11289600>, <12000000>, | |
| 87 | + <25000000>, <12288000>; | |
| 85 | 88 | }; |
| 86 | 89 | }; |
| @@ -9,6 +9,9 @@ title: Freescale MXS Inter IC (I2C) Controller · 8 unmodified lines | ||
| 9 | 9 | maintainers: |
| 10 | 10 | - Shawn Guo <shawnguo@kernel.org> |
| 11 | 11 | |
| 12 | +allOf: | |
| 13 | + - $ref: /schemas/i2c/i2c-controller.yaml# | |
| 14 | + | |
| 12 | 15 | properties: |
| 13 | 16 | compatible: |
| 14 | 17 | enum: |
| @@ -37,7 +40,7 @@ required: · 22 unmodified lines | ||
| 37 | 40 | - dmas |
| 38 | 41 | - dma-names |
| 39 | 42 | |
| 40 | −additionalProperties: false | |
| 43 | +unevaluatedProperties: false | |
| 41 | 44 | |
| 42 | 45 | examples: |
| 43 | 46 | - | |
| @@ -270,6 +270,7 @@ allOf: · 269 unmodified lines | ||
| 270 | 270 | contains: |
| 271 | 271 | enum: |
| 272 | 272 | - qcom,msm8998-smmu-v2 |
| 273 | + - qcom,sdm630-smmu-v2 | |
| 273 | 274 | then: |
| 274 | 275 | anyOf: |
| 275 | 276 | - properties: |
| @@ -311,7 +312,6 @@ allOf: · 35 unmodified lines | ||
| 311 | 312 | compatible: |
| 312 | 313 | contains: |
| 313 | 314 | enum: |
| 314 | − - qcom,sdm630-smmu-v2 | |
| 315 | 315 | - qcom,sm6375-smmu-v2 |
| 316 | 316 | then: |
| 317 | 317 | anyOf: |
| @@ -31,10 +31,6 @@ properties: · 30 unmodified lines | ||
| 31 | 31 | charger: |
| 32 | 32 | $ref: /schemas/power/supply/maxim,max77693.yaml |
| 33 | 33 | |
| 34 | − connector: | |
| 35 | − $ref: /schemas/connector/usb-connector.yaml# | |
| 36 | − unevaluatedProperties: false | |
| 37 | − | |
| 38 | 34 | led: |
| 39 | 35 | $ref: /schemas/leds/maxim,max77693.yaml |
| 40 | 36 | |
| @@ -11,11 +11,16 @@ maintainers: · 10 unmodified lines | ||
| 11 | 11 | |
| 12 | 12 | properties: |
| 13 | 13 | compatible: |
| 14 | − items: | |
| 15 | − - enum: | |
| 16 | − - loongson,ls2k0500-pmc | |
| 17 | − - loongson,ls2k1000-pmc | |
| 18 | − - const: syscon | |
| 14 | + oneOf: | |
| 15 | + - items: | |
| 16 | + - const: loongson,ls2k0500-pmc | |
| 17 | + - const: syscon | |
| 18 | + - items: | |
| 19 | + - enum: | |
| 20 | + - loongson,ls2k1000-pmc | |
| 21 | + - loongson,ls2k2000-pmc | |
| 22 | + - const: loongson,ls2k0500-pmc | |
| 23 | + - const: syscon | |
| 19 | 24 | |
| 20 | 25 | reg: |
| 21 | 26 | maxItems: 1 |
| @@ -32,6 +37,18 @@ properties: · 10 unmodified lines | ||
| 32 | 37 | addition, the PM need according to it to indicate that current |
| 33 | 38 | SoC whether support Suspend To RAM. |
| 34 | 39 | |
| 40 | + syscon-poweroff: | |
| 41 | + $ref: /schemas/power/reset/syscon-poweroff.yaml# | |
| 42 | + type: object | |
| 43 | + description: | |
| 44 | + Node for power off method | |
| 45 | + | |
| 46 | + syscon-reboot: | |
| 47 | + $ref: /schemas/power/reset/syscon-reboot.yaml# | |
| 48 | + type: object | |
| 49 | + description: | |
| 50 | + Node for reboot method | |
| 51 | + | |
| 35 | 52 | required: |
| 36 | 53 | - compatible |
| 37 | 54 | - reg |
| @@ -44,9 +61,23 @@ examples: · 6 unmodified lines | ||
| 44 | 61 | #include <dt-bindings/interrupt-controller/irq.h> |
| 45 | 62 | |
| 46 | 63 | power-management@1fe27000 { |
| 47 | − compatible = "loongson,ls2k1000-pmc", "syscon"; | |
| 64 | + compatible = "loongson,ls2k1000-pmc", "loongson,ls2k0500-pmc", "syscon"; | |
| 48 | 65 | reg = <0x1fe27000 0x58>; |
| 49 | 66 | interrupt-parent = <&liointc1>; |
| 50 | 67 | interrupts = <11 IRQ_TYPE_LEVEL_LOW>; |
| 51 | 68 | loongson,suspend-address = <0x0 0x1c000500>; |
| 69 | + | |
| 70 | + syscon-reboot { | |
| 71 | + compatible = "syscon-reboot"; | |
| 72 | + offset = <0x30>; | |
| 73 | + mask = <0x1>; | |
| 74 | + }; | |
| 75 | + | |
| 76 | + syscon-poweroff { | |
| 77 | + compatible = "syscon-poweroff"; | |
| 78 | + regmap = <&pmc>; | |
| 79 | + offset = <0x14>; | |
| 80 | + mask = <0x3c00>; | |
| 81 | + value = <0x3c00>; | |
| 82 | + }; | |
| 52 | 83 | }; |
| @@ -22,6 +22,13 @@ properties: · 21 unmodified lines | ||
| 22 | 22 | - const: fsl,imx35-cspi |
| 23 | 23 | - const: fsl,imx51-ecspi |
| 24 | 24 | - const: fsl,imx53-ecspi |
| 25 | + - items: | |
| 26 | + - enum: | |
| 27 | + - fsl,imx25-cspi | |
| 28 | + - fsl,imx50-cspi | |
| 29 | + - fsl,imx51-cspi | |
| 30 | + - fsl,imx53-cspi | |
| 31 | + - const: fsl,imx35-cspi | |
| 25 | 32 | - items: |
| 26 | 33 | - const: fsl,imx8mp-ecspi |
| 27 | 34 | - const: fsl,imx6ul-ecspi |
| @@ -949,3 +949,99 @@ mmap_lock held. All in-tree users have been audited and do not seem to · 948 unmodified lines | ||
| 949 | 949 | depend on the mmap_lock being held, but out of tree users should verify |
| 950 | 950 | for themselves. If they do need it, they can return VM_FAULT_RETRY to |
| 951 | 951 | be called with the mmap_lock held. |
| 952 | + | |
| 953 | +--- | |
| 954 | + | |
| 955 | +**mandatory** | |
| 956 | + | |
| 957 | +The order of opening block devices and matching or creating superblocks has | |
| 958 | +changed. | |
| 959 | + | |
| 960 | +The old logic opened block devices first and then tried to find a | |
| 961 | +suitable superblock to reuse based on the block device pointer. | |
| 962 | + | |
| 963 | +The new logic tries to find a suitable superblock first based on the device | |
| 964 | +number, and opening the block device afterwards. | |
| 965 | + | |
| 966 | +Since opening block devices cannot happen under s_umount because of lock | |
| 967 | +ordering requirements s_umount is now dropped while opening block devices and | |
| 968 | +reacquired before calling fill_super(). | |
| 969 | + | |
| 970 | +In the old logic concurrent mounters would find the superblock on the list of | |
| 971 | +superblocks for the filesystem type. Since the first opener of the block device | |
| 972 | +would hold s_umount they would wait until the superblock became either born or | |
| 973 | +was discarded due to initialization failure. | |
| 974 | + | |
| 975 | +Since the new logic drops s_umount concurrent mounters could grab s_umount and | |
| 976 | +would spin. Instead they are now made to wait using an explicit wait-wake | |
| 977 | +mechanism without having to hold s_umount. | |
| 978 | + | |
| 979 | +--- | |
| 980 | + | |
| 981 | +**mandatory** | |
| 982 | + | |
| 983 | +The holder of a block device is now the superblock. | |
| 984 | + | |
| 985 | +The holder of a block device used to be the file_system_type which wasn't | |
| 986 | +particularly useful. It wasn't possible to go from block device to owning | |
| 987 | +superblock without matching on the device pointer stored in the superblock. | |
| 988 | +This mechanism would only work for a single device so the block layer couldn't | |
| 989 | +find the owning superblock of any additional devices. | |
| 990 | + | |
| 991 | +In the old mechanism reusing or creating a superblock for a racing mount(2) and | |
| 992 | +umount(2) relied on the file_system_type as the holder. This was severly | |
| 993 | +underdocumented however: | |
| 994 | + | |
| 995 | +(1) Any concurrent mounter that managed to grab an active reference on an | |
| 996 | + existing superblock was made to wait until the superblock either became | |
| 997 | + ready or until the superblock was removed from the list of superblocks of | |
| 998 | + the filesystem type. If the superblock is ready the caller would simple | |
| 999 | + reuse it. | |
| 1000 | + | |
| 1001 | +(2) If the mounter came after deactivate_locked_super() but before | |
| 1002 | + the superblock had been removed from the list of superblocks of the | |
| 1003 | + filesystem type the mounter would wait until the superblock was shutdown, | |
| 1004 | + reuse the block device and allocate a new superblock. | |
| 1005 | + | |
| 1006 | +(3) If the mounter came after deactivate_locked_super() and after | |
| 1007 | + the superblock had been removed from the list of superblocks of the | |
| 1008 | + filesystem type the mounter would reuse the block device and allocate a new | |
| 1009 | + superblock (the bd_holder point may still be set to the filesystem type). | |
| 1010 | + | |
| 1011 | +Because the holder of the block device was the file_system_type any concurrent | |
| 1012 | +mounter could open the block devices of any superblock of the same | |
| 1013 | +file_system_type without risking seeing EBUSY because the block device was | |
| 1014 | +still in use by another superblock. | |
| 1015 | + | |
| 1016 | +Making the superblock the owner of the block device changes this as the holder | |
| 1017 | +is now a unique superblock and thus block devices associated with it cannot be | |
| 1018 | +reused by concurrent mounters. So a concurrent mounter in (2) could suddenly | |
| 1019 | +see EBUSY when trying to open a block device whose holder was a different | |
| 1020 | +superblock. | |
| 1021 | + | |
| 1022 | +The new logic thus waits until the superblock and the devices are shutdown in | |
| 1023 | +->kill_sb(). Removal of the superblock from the list of superblocks of the | |
| 1024 | +filesystem type is now moved to a later point when the devices are closed: | |
| 1025 | + | |
| 1026 | +(1) Any concurrent mounter managing to grab an active reference on an existing | |
| 1027 | + superblock is made to wait until the superblock is either ready or until | |
| 1028 | + the superblock and all devices are shutdown in ->kill_sb(). If the | |
| 1029 | + superblock is ready the caller will simply reuse it. | |
| 1030 | + | |
| 1031 | +(2) If the mounter comes after deactivate_locked_super() but before | |
| 1032 | + the superblock has been removed from the list of superblocks of the | |
| 1033 | + filesystem type the mounter is made to wait until the superblock and the | |
| 1034 | + devices are shut down in ->kill_sb() and the superblock is removed from the | |
| 1035 | + list of superblocks of the filesystem type. The mounter will allocate a new | |
| 1036 | + superblock and grab ownership of the block device (the bd_holder pointer of | |
| 1037 | + the block device will be set to the newly allocated superblock). | |
| 1038 | + | |
| 1039 | +(3) This case is now collapsed into (2) as the superblock is left on the list | |
| 1040 | + of superblocks of the filesystem type until all devices are shutdown in | |
| 1041 | + ->kill_sb(). In other words, if the superblock isn't on the list of | |
| 1042 | + superblock of the filesystem type anymore then it has given up ownership of | |
| 1043 | + all associated block devices (the bd_holder pointer is NULL). | |
| 1044 | + | |
| 1045 | +As this is a VFS level change it has no practical consequences for filesystems | |
| 1046 | +other than that all of them must use one of the provided kill_litter_super(), | |
| 1047 | +kill_anon_super(), or kill_block_super() helpers. | |
| @@ -573,6 +573,32 @@ above, leading to: · 572 unmodified lines | ||
| 573 | 573 | bool "Support for foo hardware" |
| 574 | 574 | depends on ARCH_FOO_VENDOR || COMPILE_TEST |
| 575 | 575 | |
| 576 | +Optional dependencies | |
| 577 | +~~~~~~~~~~~~~~~~~~~~~ | |
| 578 | + | |
| 579 | +Some drivers are able to optionally use a feature from another module | |
| 580 | +or build cleanly with that module disabled, but cause a link failure | |
| 581 | +when trying to use that loadable module from a built-in driver. | |
| 582 | + | |
| 583 | +The most common way to express this optional dependency in Kconfig logic | |
| 584 | +uses the slightly counterintuitive:: | |
| 585 | + | |
| 586 | + config FOO | |
| 587 | + tristate "Support for foo hardware" | |
| 588 | + depends on BAR || !BAR | |
| 589 | + | |
| 590 | +This means that there is either a dependency on BAR that disallows | |
| 591 | +the combination of FOO=y with BAR=m, or BAR is completely disabled. | |
| 592 | +For a more formalized approach if there are multiple drivers that have | |
| 593 | +the same dependency, a helper symbol can be used, like:: | |
| 594 | + | |
| 595 | + config FOO | |
| 596 | + tristate "Support for foo hardware" | |
| 597 | + depends on BAR_OPTIONAL | |
| 598 | + | |
| 599 | + config BAR_OPTIONAL | |
| 600 | + def_tristate BAR || !BAR | |
| 601 | + | |
| 576 | 602 | Kconfig recursive dependency limitations |
| 577 | 603 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| 578 | 604 | |
| @@ -36,11 +36,11 @@ EXAMPLE · 35 unmodified lines | ||
| 36 | 36 | In the example below, **rtla timerlat hist** is set to run for *10* minutes, |
| 37 | 37 | in the cpus *0-4*, *skipping zero* only lines. Moreover, **rtla timerlat |
| 38 | 38 | hist** will change the priority of the *timerlat* threads to run under |
| 39 | −*SCHED_DEADLINE* priority, with a *10us* runtime every *1ms* period. The | |
| 39 | +*SCHED_DEADLINE* priority, with a *100us* runtime every *1ms* period. The | |
| 40 | 40 | *1ms* period is also passed to the *timerlat* tracer. Auto-analysis is disabled |
| 41 | 41 | to reduce overhead :: |
| 42 | 42 | |
| 43 | − [root@alien ~]# timerlat hist -d 10m -c 0-4 -P d:100us:1ms -p 1ms --no-aa | |
| 43 | + [root@alien ~]# timerlat hist -d 10m -c 0-4 -P d:100us:1ms -p 1000 --no-aa | |
| 44 | 44 | # RTLA timerlat histogram |
| 45 | 45 | # Time unit is microseconds (us) |
| 46 | 46 | # Duration: 0 00:10:00 |
| @@ -344,9 +344,9 @@ LoongArch指令集架构的文档: · 343 unmodified lines | ||
| 344 | 344 | |
| 345 | 345 | LoongArch的ELF psABI文档: |
| 346 | 346 | |
| 347 | − https://github.com/loongson/LoongArch-Documentation/releases/latest/download/LoongArch-ELF-ABI-v2.00-CN.pdf (中文版) | |
| 347 | + https://github.com/loongson/LoongArch-Documentation/releases/latest/download/LoongArch-ELF-ABI-v2.01-CN.pdf (中文版) | |
| 348 | 348 | |
| 349 | − https://github.com/loongson/LoongArch-Documentation/releases/latest/download/LoongArch-ELF-ABI-v2.00-EN.pdf (英文版) | |
| 349 | + https://github.com/loongson/LoongArch-Documentation/releases/latest/download/LoongArch-ELF-ABI-v2.01-EN.pdf (英文版) | |
| 350 | 350 | |
| 351 | 351 | Loongson与LoongArch的Linux内核源码仓库: |
| 352 | 352 | |
| @@ -470,7 +470,6 @@ F: drivers/hwmon/adm1029.c · 469 unmodified lines | ||
| 470 | 470 | ADM8211 WIRELESS DRIVER |
| 471 | 471 | L: linux-wireless@vger.kernel.org |
| 472 | 472 | S: Orphan |
| 473 | −W: https://wireless.wiki.kernel.org/ | |
| 474 | 473 | F: drivers/net/wireless/admtek/adm8211.* |
| 475 | 474 | |
| 476 | 475 | ADP1653 FLASH CONTROLLER DRIVER |
| @@ -1662,7 +1661,7 @@ F: arch/arm*/include/asm/perf_event.h · 1185 unmodified lines | ||
| 1662 | 1661 | F: arch/arm*/kernel/hw_breakpoint.c |
| 1663 | 1662 | F: arch/arm*/kernel/perf_* |
| 1664 | 1663 | F: drivers/perf/ |
| 1665 | −F: include/linux/perf/arm_pmu.h | |
| 1664 | +F: include/linux/perf/arm_pmu*.h | |
| 1666 | 1665 | |
| 1667 | 1666 | ARM PORT |
| 1668 | 1667 | M: Russell King <linux@armlinux.org.uk> |
| @@ -1963,12 +1962,12 @@ F: drivers/irqchip/irq-aspeed-i2c-ic.c · 294 unmodified lines | ||
| 1963 | 1962 | |
| 1964 | 1963 | ARM/ASPEED MACHINE SUPPORT |
| 1965 | 1964 | M: Joel Stanley <joel@jms.id.au> |
| 1966 | −R: Andrew Jeffery <andrew@aj.id.au> | |
| 1965 | +R: Andrew Jeffery <andrew@codeconstruct.com.au> | |
| 1967 | 1966 | L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) |
| 1968 | 1967 | L: linux-aspeed@lists.ozlabs.org (moderated for non-subscribers) |
| 1969 | 1968 | S: Supported |
| 1970 | 1969 | Q: https://patchwork.ozlabs.org/project/linux-aspeed/list/ |
| 1971 | −T: git git://git.kernel.org/pub/scm/linux/kernel/git/joel/aspeed.git | |
| 1970 | +T: git git://git.kernel.org/pub/scm/linux/kernel/git/joel/bmc.git | |
| 1972 | 1971 | F: Documentation/devicetree/bindings/arm/aspeed/ |
| 1973 | 1972 | F: arch/arm/boot/dts/aspeed/ |
| 1974 | 1973 | F: arch/arm/mach-aspeed/ |
| @@ -3058,7 +3057,7 @@ F: Documentation/devicetree/bindings/peci/peci-aspeed.yaml · 1083 unmodified lines | ||
| 3058 | 3057 | F: drivers/peci/controller/peci-aspeed.c |
| 3059 | 3058 | |
| 3060 | 3059 | ASPEED PINCTRL DRIVERS |
| 3061 | −M: Andrew Jeffery <andrew@aj.id.au> | |
| 3060 | +M: Andrew Jeffery <andrew@codeconstruct.com.au> | |
| 3062 | 3061 | L: linux-aspeed@lists.ozlabs.org (moderated for non-subscribers) |
| 3063 | 3062 | L: openbmc@lists.ozlabs.org (moderated for non-subscribers) |
| 3064 | 3063 | L: linux-gpio@vger.kernel.org |
| @@ -3075,7 +3074,7 @@ F: drivers/irqchip/irq-aspeed-scu-ic.c · 10 unmodified lines | ||
| 3075 | 3074 | F: include/dt-bindings/interrupt-controller/aspeed-scu-ic.h |
| 3076 | 3075 | |
| 3077 | 3076 | ASPEED SD/MMC DRIVER |
| 3078 | −M: Andrew Jeffery <andrew@aj.id.au> | |
| 3077 | +M: Andrew Jeffery <andrew@codeconstruct.com.au> | |
| 3079 | 3078 | L: linux-aspeed@lists.ozlabs.org (moderated for non-subscribers) |
| 3080 | 3079 | L: openbmc@lists.ozlabs.org (moderated for non-subscribers) |
| 3081 | 3080 | L: linux-mmc@vger.kernel.org |
| @@ -4083,7 +4082,7 @@ F: drivers/net/wireless/broadcom/brcm80211/ · 1001 unmodified lines | ||
| 4083 | 4082 | |
| 4084 | 4083 | BROADCOM BRCMSTB GPIO DRIVER |
| 4085 | 4084 | M: Doug Berger <opendmb@gmail.com> |
| 4086 | −M: Florian Fainelli <florian.fainelli@broadcom> | |
| 4085 | +M: Florian Fainelli <florian.fainelli@broadcom.com> | |
| 4087 | 4086 | R: Broadcom internal kernel review list <bcm-kernel-feedback-list@broadcom.com> |
| 4088 | 4087 | S: Supported |
| 4089 | 4088 | F: Documentation/devicetree/bindings/gpio/brcm,brcmstb-gpio.yaml |
| @@ -6656,9 +6655,9 @@ F: Documentation/devicetree/bindings/display/panel/novatek,nt36672a.yaml · 2566 unmodified lines | ||
| 6656 | 6655 | F: drivers/gpu/drm/panel/panel-novatek-nt36672a.c |
| 6657 | 6656 | |
| 6658 | 6657 | DRM DRIVER FOR NVIDIA GEFORCE/QUADRO GPUS |
| 6659 | −M: Ben Skeggs <bskeggs@redhat.com> | |
| 6660 | 6658 | M: Karol Herbst <kherbst@redhat.com> |
| 6661 | 6659 | M: Lyude Paul <lyude@redhat.com> |
| 6660 | +M: Danilo Krummrich <dakr@redhat.com> | |
| 6662 | 6661 | L: dri-devel@lists.freedesktop.org |
| 6663 | 6662 | L: nouveau@lists.freedesktop.org |
| 6664 | 6663 | S: Supported |
| @@ -8885,7 +8884,7 @@ F: drivers/gpio/gpio-mockup.c · 2220 unmodified lines | ||
| 8885 | 8884 | F: tools/testing/selftests/gpio/ |
| 8886 | 8885 | |
| 8887 | 8886 | GPIO REGMAP |
| 8888 | −R: Michael Walle <michael@walle.cc> | |
| 8887 | +M: Michael Walle <michael@walle.cc> | |
| 8889 | 8888 | S: Maintained |
| 8890 | 8889 | F: drivers/gpio/gpio-regmap.c |
| 8891 | 8890 | F: include/linux/gpio/regmap.h |
| @@ -9542,10 +9541,8 @@ F: Documentation/devicetree/bindings/iio/pressure/honeywell,mprls0025pa.yaml · 650 unmodified lines | ||
| 9542 | 9541 | F: drivers/iio/pressure/mprls0025pa.c |
| 9543 | 9542 | |
| 9544 | 9543 | HOST AP DRIVER |
| 9545 | −M: Jouni Malinen <j@w1.fi> | |
| 9546 | 9544 | L: linux-wireless@vger.kernel.org |
| 9547 | 9545 | S: Obsolete |
| 9548 | −W: http://w1.fi/hostap-driver.html | |
| 9549 | 9546 | F: drivers/net/wireless/intersil/hostap/ |
| 9550 | 9547 | |
| 9551 | 9548 | HP BIOSCFG DRIVER |
| @@ -13627,6 +13624,7 @@ F: drivers/net/ethernet/mellanox/mlxfw/ · 4075 unmodified lines | ||
| 13627 | 13624 | |
| 13628 | 13625 | MELLANOX HARDWARE PLATFORM SUPPORT |
| 13629 | 13626 | M: Hans de Goede <hdegoede@redhat.com> |
| 13627 | +M: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com> | |
| 13630 | 13628 | M: Mark Gross <markgross@kernel.org> |
| 13631 | 13629 | M: Vadim Pasternak <vadimp@nvidia.com> |
| 13632 | 13630 | L: platform-driver-x86@vger.kernel.org |
| @@ -14221,6 +14219,7 @@ F: drivers/platform/surface/surface_gpe.c · 588 unmodified lines | ||
| 14221 | 14219 | |
| 14222 | 14220 | MICROSOFT SURFACE HARDWARE PLATFORM SUPPORT |
| 14223 | 14221 | M: Hans de Goede <hdegoede@redhat.com> |
| 14222 | +M: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com> | |
| 14224 | 14223 | M: Mark Gross <markgross@kernel.org> |
| 14225 | 14224 | M: Maximilian Luz <luzmaximilian@gmail.com> |
| 14226 | 14225 | L: platform-driver-x86@vger.kernel.org |
| @@ -14958,7 +14957,7 @@ K: macsec · 731 unmodified lines | ||
| 14958 | 14957 | K: \bmdo_ |
| 14959 | 14958 | |
| 14960 | 14959 | NETWORKING [MPTCP] |
| 14961 | −M: Matthieu Baerts <matthieu.baerts@tessares.net> | |
| 14960 | +M: Matthieu Baerts <matttbe@kernel.org> | |
| 14962 | 14961 | M: Mat Martineau <martineau@kernel.org> |
| 14963 | 14962 | L: netdev@vger.kernel.org |
| 14964 | 14963 | L: mptcp@lists.linux.dev |
| @@ -17613,6 +17612,7 @@ M: Kalle Valo <kvalo@kernel.org> · 2648 unmodified lines | ||
| 17613 | 17612 | M: Jeff Johnson <quic_jjohnson@quicinc.com> |
| 17614 | 17613 | L: ath12k@lists.infradead.org |
| 17615 | 17614 | S: Supported |
| 17615 | +W: https://wireless.wiki.kernel.org/en/users/Drivers/ath12k | |
| 17616 | 17616 | T: git git://git.kernel.org/pub/scm/linux/kernel/git/kvalo/ath.git |
| 17617 | 17617 | F: drivers/net/wireless/ath/ath12k/ |
| 17618 | 17618 | |
| @@ -18143,8 +18143,6 @@ REALTEK WIRELESS DRIVER (rtlwifi family) · 524 unmodified lines | ||
| 18143 | 18143 | M: Ping-Ke Shih <pkshih@realtek.com> |
| 18144 | 18144 | L: linux-wireless@vger.kernel.org |
| 18145 | 18145 | S: Maintained |
| 18146 | −W: https://wireless.wiki.kernel.org/ | |
| 18147 | −T: git git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-testing.git | |
| 18148 | 18146 | F: drivers/net/wireless/realtek/rtlwifi/ |
| 18149 | 18147 | |
| 18150 | 18148 | REALTEK WIRELESS DRIVER (rtw88) |
| @@ -18672,7 +18670,6 @@ F: drivers/media/dvb-frontends/rtl2832_sdr* · 521 unmodified lines | ||
| 18672 | 18670 | RTL8180 WIRELESS DRIVER |
| 18673 | 18671 | L: linux-wireless@vger.kernel.org |
| 18674 | 18672 | S: Orphan |
| 18675 | −W: https://wireless.wiki.kernel.org/ | |
| 18676 | 18673 | F: drivers/net/wireless/realtek/rtl818x/rtl8180/ |
| 18677 | 18674 | |
| 18678 | 18675 | RTL8187 WIRELESS DRIVER |
| @@ -18680,14 +18677,12 @@ M: Hin-Tak Leung <hintak.leung@gmail.com> · 1 unmodified line | ||
| 18680 | 18677 | M: Larry Finger <Larry.Finger@lwfinger.net> |
| 18681 | 18678 | L: linux-wireless@vger.kernel.org |
| 18682 | 18679 | S: Maintained |
| 18683 | −W: https://wireless.wiki.kernel.org/ | |
| 18684 | 18680 | F: drivers/net/wireless/realtek/rtl818x/rtl8187/ |
| 18685 | 18681 | |
| 18686 | 18682 | RTL8XXXU WIRELESS DRIVER (rtl8xxxu) |
| 18687 | 18683 | M: Jes Sorensen <Jes.Sorensen@gmail.com> |
| 18688 | 18684 | L: linux-wireless@vger.kernel.org |
| 18689 | 18685 | S: Maintained |
| 18690 | −T: git git://git.kernel.org/pub/scm/linux/kernel/git/jes/linux.git rtl8xxxu-devel | |
| 18691 | 18686 | F: drivers/net/wireless/realtek/rtl8xxxu/ |
| 18692 | 18687 | |
| 18693 | 18688 | RTRS TRANSPORT DRIVERS |
| @@ -21669,7 +21664,6 @@ L: linux-wireless@vger.kernel.org · 2975 unmodified lines | ||
| 21669 | 21664 | S: Orphan |
| 21670 | 21665 | W: https://wireless.wiki.kernel.org/en/users/Drivers/wl12xx |
| 21671 | 21666 | W: https://wireless.wiki.kernel.org/en/users/Drivers/wl1251 |
| 21672 | −T: git git://git.kernel.org/pub/scm/linux/kernel/git/luca/wl12xx.git | |
| 21673 | 21667 | F: drivers/net/wireless/ti/ |
| 21674 | 21668 | |
| 21675 | 21669 | TIMEKEEPING, CLOCKSOURCE CORE, NTP, ALARMTIMER |
| @@ -23436,9 +23430,11 @@ F: drivers/platform/x86/x86-android-tablets/ · 1760 unmodified lines | ||
| 23436 | 23430 | |
| 23437 | 23431 | X86 PLATFORM DRIVERS |
| 23438 | 23432 | M: Hans de Goede <hdegoede@redhat.com> |
| 23433 | +M: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com> | |
| 23439 | 23434 | M: Mark Gross <markgross@kernel.org> |
| 23440 | 23435 | L: platform-driver-x86@vger.kernel.org |
| 23441 | 23436 | S: Maintained |
| 23437 | +Q: https://patchwork.kernel.org/project/platform-driver-x86/list/ | |
| 23442 | 23438 | T: git git://git.kernel.org/pub/scm/linux/kernel/git/pdx86/platform-drivers-x86.git |
| 23443 | 23439 | F: drivers/platform/olpc/ |
| 23444 | 23440 | F: drivers/platform/x86/ |
| @@ -2,7 +2,7 @@ · 1 unmodified line | ||
| 2 | 2 | VERSION = 6 |
| 3 | 3 | PATCHLEVEL = 6 |
| 4 | 4 | SUBLEVEL = 0 |
| 5 | −EXTRAVERSION = -rc2 | |
| 5 | +EXTRAVERSION = -rc4 | |
| 6 | 6 | NAME = Hurr durr I'ma ninja sloth |
| 7 | 7 | |
| 8 | 8 | # *DOCUMENTATION* |
| @@ -614,12 +614,12 @@ · 613 unmodified lines | ||
| 614 | 614 | /* Configure pwm clock source for timers 8 & 9 */ |
| 615 | 615 | &timer8 { |
| 616 | 616 | assigned-clocks = <&abe_clkctrl OMAP4_TIMER8_CLKCTRL 24>; |
| 617 | − assigned-clock-parents = <&sys_clkin_ck>; | |
| 617 | + assigned-clock-parents = <&sys_32k_ck>; | |
| 618 | 618 | }; |
| 619 | 619 | |
| 620 | 620 | &timer9 { |
| 621 | 621 | assigned-clocks = <&l4_per_clkctrl OMAP4_TIMER9_CLKCTRL 24>; |
| 622 | − assigned-clock-parents = <&sys_clkin_ck>; | |
| 622 | + assigned-clock-parents = <&sys_32k_ck>; | |
| 623 | 623 | }; |
| 624 | 624 | |
| 625 | 625 | /* |
| @@ -640,6 +640,7 @@ · 14 unmodified lines | ||
| 640 | 640 | &uart3 { |
| 641 | 641 | interrupts-extended = <&wakeupgen GIC_SPI 74 IRQ_TYPE_LEVEL_HIGH |
| 642 | 642 | &omap4_pmx_core 0x17c>; |
| 643 | + overrun-throttle-ms = <500>; | |
| 643 | 644 | }; |
| 644 | 645 | |
| 645 | 646 | &uart4 { |
| @@ -12,8 +12,7 @@ cpu_thermal: cpu-thermal { · 11 unmodified lines | ||
| 12 | 12 | polling-delay = <1000>; /* milliseconds */ |
| 13 | 13 | coefficients = <0 20000>; |
| 14 | 14 | |
| 15 | − /* sensor ID */ | |
| 16 | − thermal-sensors = <&bandgap 0>; | |
| 15 | + thermal-sensors = <&bandgap>; | |
| 17 | 16 | |
| 18 | 17 | cpu_trips: trips { |
| 19 | 18 | cpu_alert0: cpu_alert { |
| @@ -12,7 +12,10 @@ cpu_thermal: cpu_thermal { · 11 unmodified lines | ||
| 12 | 12 | polling-delay-passive = <250>; /* milliseconds */ |
| 13 | 13 | polling-delay = <1000>; /* milliseconds */ |
| 14 | 14 | |
| 15 | − /* sensor ID */ | |
| 15 | + /* | |
| 16 | + * See 44xx files for single sensor addressing, omap5 and dra7 need | |
| 17 | + * also sensor ID for addressing. | |
| 18 | + */ | |
| 16 | 19 | thermal-sensors = <&bandgap 0>; |
| 17 | 20 | |
| 18 | 21 | cpu_trips: trips { |
| @@ -69,6 +69,7 @@ · 68 unmodified lines | ||
| 69 | 69 | }; |
| 70 | 70 | |
| 71 | 71 | &cpu_thermal { |
| 72 | + thermal-sensors = <&bandgap>; | |
| 72 | 73 | coefficients = <0 20000>; |
| 73 | 74 | }; |
| 74 | 75 | |
| @@ -79,6 +79,7 @@ · 78 unmodified lines | ||
| 79 | 79 | }; |
| 80 | 80 | |
| 81 | 81 | &cpu_thermal { |
| 82 | + thermal-sensors = <&bandgap>; | |
| 82 | 83 | coefficients = <348 (-9301)>; |
| 83 | 84 | }; |
| 84 | 85 | |
| @@ -195,7 +195,7 @@ struct locomo_driver { · 194 unmodified lines | ||
| 195 | 195 | |
| 196 | 196 | #define LOCOMO_DRIVER_NAME(_ldev) ((_ldev)->dev.driver->name) |
| 197 | 197 | |
| 198 | −void locomo_lcd_power(struct locomo_dev *, int, unsigned int); | |
| 198 | +extern void locomolcd_power(int on); | |
| 199 | 199 | |
| 200 | 200 | int locomo_driver_register(struct locomo_driver *); |
| 201 | 201 | void locomo_driver_unregister(struct locomo_driver *); |
| @@ -99,7 +99,7 @@ static int omap4_pm_suspend(void) · 98 unmodified lines | ||
| 99 | 99 | * possible causes. |
| 100 | 100 | * http://www.spinics.net/lists/arm-kernel/msg218641.html |
| 101 | 101 | */ |
| 102 | − pr_warn("A possible cause could be an old bootloader - try u-boot >= v2012.07\n"); | |
| 102 | + pr_debug("A possible cause could be an old bootloader - try u-boot >= v2012.07\n"); | |
| 103 | 103 | } else { |
| 104 | 104 | pr_info("Successfully put all powerdomains to target state\n"); |
| 105 | 105 | } |
| @@ -257,7 +257,7 @@ int __init omap4_pm_init(void) · 151 unmodified lines | ||
| 257 | 257 | * http://www.spinics.net/lists/arm-kernel/msg218641.html |
| 258 | 258 | */ |
| 259 | 259 | if (cpu_is_omap44xx()) |
| 260 | − pr_warn("OMAP4 PM: u-boot >= v2012.07 is required for full PM support\n"); | |
| 260 | + pr_debug("OMAP4 PM: u-boot >= v2012.07 is required for full PM support\n"); | |
| 261 | 261 | |
| 262 | 262 | ret = pwrdm_for_each(pwrdms_setup, NULL); |
| 263 | 263 | if (ret) { |
| @@ -16,8 +16,6 @@ · 15 unmodified lines | ||
| 16 | 16 | |
| 17 | 17 | #include "hardware.h" /* Gives GPIO_MAX */ |
| 18 | 18 | |
| 19 | −extern void locomolcd_power(int on); | |
| 20 | − | |
| 21 | 19 | #define COLLIE_SCOOP_GPIO_BASE (GPIO_MAX + 1) |
| 22 | 20 | #define COLLIE_GPIO_CHARGE_ON (COLLIE_SCOOP_GPIO_BASE + 0) |
| 23 | 21 | #define COLLIE_SCP_DIAG_BOOT1 SCOOP_GPCR_PA12 |
| @@ -58,11 +58,13 @@ · 57 unmodified lines | ||
| 58 | 58 | ((op & UNIPHIER_SSCOQM_S_MASK) == UNIPHIER_SSCOQM_S_RANGE) |
| 59 | 59 | |
| 60 | 60 | /** |
| 61 | − * uniphier_cache_data - UniPhier outer cache specific data | |
| 61 | + * struct uniphier_cache_data - UniPhier outer cache specific data | |
| 62 | 62 | * |
| 63 | 63 | * @ctrl_base: virtual base address of control registers |
| 64 | 64 | * @rev_base: virtual base address of revision registers |
| 65 | 65 | * @op_base: virtual base address of operation registers |
| 66 | + * @way_ctrl_base: virtual address of the way control registers for this | |
| 67 | + * SoC revision | |
| 66 | 68 | * @way_mask: each bit specifies if the way is present |
| 67 | 69 | * @nsets: number of associativity sets |
| 68 | 70 | * @line_size: line size in bytes |
| @@ -66,6 +66,7 @@ dtb-$(CONFIG_ARCH_MXC) += imx8mm-mx8menlo.dtb · 65 unmodified lines | ||
| 66 | 66 | dtb-$(CONFIG_ARCH_MXC) += imx8mm-nitrogen-r2.dtb |
| 67 | 67 | dtb-$(CONFIG_ARCH_MXC) += imx8mm-phg.dtb |
| 68 | 68 | dtb-$(CONFIG_ARCH_MXC) += imx8mm-phyboard-polis-rdk.dtb |
| 69 | +dtb-$(CONFIG_ARCH_MXC) += imx8mm-prt8mm.dtb | |
| 69 | 70 | dtb-$(CONFIG_ARCH_MXC) += imx8mm-tqma8mqml-mba8mx.dtb |
| 70 | 71 | dtb-$(CONFIG_ARCH_MXC) += imx8mm-var-som-symphony.dtb |
| 71 | 72 | dtb-$(CONFIG_ARCH_MXC) += imx8mm-venice-gw71xx-0x.dtb |
| @@ -26,7 +26,7 @@ · 25 unmodified lines | ||
| 26 | 26 | |
| 27 | 27 | port { |
| 28 | 28 | hdmi_connector_in: endpoint { |
| 29 | − remote-endpoint = <&adv7533_out>; | |
| 29 | + remote-endpoint = <&adv7535_out>; | |
| 30 | 30 | }; |
| 31 | 31 | }; |
| 32 | 32 | }; |
| @@ -72,6 +72,13 @@ · 39 unmodified lines | ||
| 72 | 72 | enable-active-high; |
| 73 | 73 | }; |
| 74 | 74 | |
| 75 | + reg_vddext_3v3: regulator-vddext-3v3 { | |
| 76 | + compatible = "regulator-fixed"; | |
| 77 | + regulator-name = "VDDEXT_3V3"; | |
| 78 | + regulator-min-microvolt = <3300000>; | |
| 79 | + regulator-max-microvolt = <3300000>; | |
| 80 | + }; | |
| 81 | + | |
| 75 | 82 | backlight: backlight { |
| 76 | 83 | compatible = "pwm-backlight"; |
| 77 | 84 | pwms = <&pwm1 0 5000000 0>; |
| @@ -317,15 +324,16 @@ · 239 unmodified lines | ||
| 317 | 324 | |
| 318 | 325 | hdmi@3d { |
| 319 | 326 | compatible = "adi,adv7535"; |
| 320 | − reg = <0x3d>, <0x3c>, <0x3e>, <0x3f>; | |
| 321 | − reg-names = "main", "cec", "edid", "packet"; | |
| 327 | + reg = <0x3d>; | |
| 328 | + interrupt-parent = <&gpio1>; | |
| 329 | + interrupts = <9 IRQ_TYPE_EDGE_FALLING>; | |
| 322 | 330 | adi,dsi-lanes = <4>; |
| 323 | − | |
| 324 | − adi,input-depth = <8>; | |
| 325 | − adi,input-colorspace = "rgb"; | |
| 326 | − adi,input-clock = "1x"; | |
| 327 | − adi,input-style = <1>; | |
| 328 | − adi,input-justification = "evenly"; | |
| 331 | + avdd-supply = <&buck5_reg>; | |
| 332 | + dvdd-supply = <&buck5_reg>; | |
| 333 | + pvdd-supply = <&buck5_reg>; | |
| 334 | + a2vdd-supply = <&buck5_reg>; | |
| 335 | + v3p3-supply = <®_vddext_3v3>; | |
| 336 | + v1p2-supply = <&buck5_reg>; | |
| 329 | 337 | |
| 330 | 338 | ports { |
| 331 | 339 | #address-cells = <1>; |
| @@ -334,7 +342,7 @@ · 2 unmodified lines | ||
| 334 | 342 | port@0 { |
| 335 | 343 | reg = <0>; |
| 336 | 344 | |
| 337 | − adv7533_in: endpoint { | |
| 345 | + adv7535_in: endpoint { | |
| 338 | 346 | remote-endpoint = <&dsi_out>; |
| 339 | 347 | }; |
| 340 | 348 | }; |
| @@ -342,7 +350,7 @@ · 1 unmodified line | ||
| 342 | 350 | port@1 { |
| 343 | 351 | reg = <1>; |
| 344 | 352 | |
| 345 | − adv7533_out: endpoint { | |
| 353 | + adv7535_out: endpoint { | |
| 346 | 354 | remote-endpoint = <&hdmi_connector_in>; |
| 347 | 355 | }; |
| 348 | 356 | }; |
| @@ -448,7 +456,7 @@ · 99 unmodified lines | ||
| 448 | 456 | reg = <1>; |
| 449 | 457 | |
| 450 | 458 | dsi_out: endpoint { |
| 451 | − remote-endpoint = <&adv7533_in>; | |
| 459 | + remote-endpoint = <&adv7535_in>; | |
| 452 | 460 | data-lanes = <1 2 3 4>; |
| 453 | 461 | }; |
| 454 | 462 | }; |
| @@ -381,9 +381,10 @@ · 380 unmodified lines | ||
| 381 | 381 | &sai3 { |
| 382 | 382 | pinctrl-names = "default"; |
| 383 | 383 | pinctrl-0 = <&pinctrl_sai3>; |
| 384 | − assigned-clocks = <&clk IMX8MP_CLK_SAI3>; | |
| 384 | + assigned-clocks = <&clk IMX8MP_CLK_SAI3>, | |
| 385 | + <&clk IMX8MP_AUDIO_PLL2> ; | |
| 385 | 386 | assigned-clock-parents = <&clk IMX8MP_AUDIO_PLL2_OUT>; |
| 386 | − assigned-clock-rates = <12288000>; | |
| 387 | + assigned-clock-rates = <12288000>, <361267200>; | |
| 387 | 388 | fsl,sai-mclk-direction-output; |
| 388 | 389 | status = "okay"; |
| 389 | 390 | }; |
| @@ -790,6 +790,12 @@ · 789 unmodified lines | ||
| 790 | 790 | reg = <IMX8MP_POWER_DOMAIN_AUDIOMIX>; |
| 791 | 791 | clocks = <&clk IMX8MP_CLK_AUDIO_ROOT>, |
| 792 | 792 | <&clk IMX8MP_CLK_AUDIO_AXI>; |
| 793 | + assigned-clocks = <&clk IMX8MP_CLK_AUDIO_AHB>, | |
| 794 | + <&clk IMX8MP_CLK_AUDIO_AXI_SRC>; | |
| 795 | + assigned-clock-parents = <&clk IMX8MP_SYS_PLL1_800M>, | |
| 796 | + <&clk IMX8MP_SYS_PLL1_800M>; | |
| 797 | + assigned-clock-rates = <400000000>, | |
| 798 | + <600000000>; | |
| 793 | 799 | }; |
| 794 | 800 | |
| 795 | 801 | pgc_gpu2d: power-domain@6 { |
| @@ -81,7 +81,7 @@ · 80 unmodified lines | ||
| 81 | 81 | &gpio1 { |
| 82 | 82 | pmic-irq-hog { |
| 83 | 83 | gpio-hog; |
| 84 | − gpios = <2 GPIO_ACTIVE_LOW>; | |
| 84 | + gpios = <3 GPIO_ACTIVE_LOW>; | |
| 85 | 85 | input; |
| 86 | 86 | line-name = "PMIC_IRQ#"; |
| 87 | 87 | }; |
| @@ -2957,7 +2957,7 @@ · 2956 unmodified lines | ||
| 2957 | 2957 | clock-names = "merge","merge_async"; |
| 2958 | 2958 | power-domains = <&spm MT8195_POWER_DOMAIN_VDOSYS1>; |
| 2959 | 2959 | mediatek,gce-client-reg = <&gce0 SUBSYS_1c10XXXX 0xc000 0x1000>; |
| 2960 | − mediatek,merge-mute = <1>; | |
| 2960 | + mediatek,merge-mute; | |
| 2961 | 2961 | resets = <&vdosys1 MT8195_VDOSYS1_SW0_RST_B_MERGE0_DL_ASYNC>; |
| 2962 | 2962 | }; |
| 2963 | 2963 | |
| @@ -2970,7 +2970,7 @@ · 6 unmodified lines | ||
| 2970 | 2970 | clock-names = "merge","merge_async"; |
| 2971 | 2971 | power-domains = <&spm MT8195_POWER_DOMAIN_VDOSYS1>; |
| 2972 | 2972 | mediatek,gce-client-reg = <&gce0 SUBSYS_1c10XXXX 0xd000 0x1000>; |
| 2973 | − mediatek,merge-mute = <1>; | |
| 2973 | + mediatek,merge-mute; | |
| 2974 | 2974 | resets = <&vdosys1 MT8195_VDOSYS1_SW0_RST_B_MERGE1_DL_ASYNC>; |
| 2975 | 2975 | }; |
| 2976 | 2976 | |
| @@ -2983,7 +2983,7 @@ · 6 unmodified lines | ||
| 2983 | 2983 | clock-names = "merge","merge_async"; |
| 2984 | 2984 | power-domains = <&spm MT8195_POWER_DOMAIN_VDOSYS1>; |
| 2985 | 2985 | mediatek,gce-client-reg = <&gce0 SUBSYS_1c10XXXX 0xe000 0x1000>; |
| 2986 | − mediatek,merge-mute = <1>; | |
| 2986 | + mediatek,merge-mute; | |
| 2987 | 2987 | resets = <&vdosys1 MT8195_VDOSYS1_SW0_RST_B_MERGE2_DL_ASYNC>; |
| 2988 | 2988 | }; |
| 2989 | 2989 | |
| @@ -2996,7 +2996,7 @@ · 6 unmodified lines | ||
| 2996 | 2996 | clock-names = "merge","merge_async"; |
| 2997 | 2997 | power-domains = <&spm MT8195_POWER_DOMAIN_VDOSYS1>; |
| 2998 | 2998 | mediatek,gce-client-reg = <&gce0 SUBSYS_1c10XXXX 0xf000 0x1000>; |
| 2999 | − mediatek,merge-mute = <1>; | |
| 2999 | + mediatek,merge-mute; | |
| 3000 | 3000 | resets = <&vdosys1 MT8195_VDOSYS1_SW0_RST_B_MERGE3_DL_ASYNC>; |
| 3001 | 3001 | }; |
| 3002 | 3002 | |
| @@ -3009,7 +3009,7 @@ · 6 unmodified lines | ||
| 3009 | 3009 | clock-names = "merge","merge_async"; |
| 3010 | 3010 | power-domains = <&spm MT8195_POWER_DOMAIN_VDOSYS1>; |
| 3011 | 3011 | mediatek,gce-client-reg = <&gce0 SUBSYS_1c11XXXX 0x0000 0x1000>; |
| 3012 | − mediatek,merge-fifo-en = <1>; | |
| 3012 | + mediatek,merge-fifo-en; | |
| 3013 | 3013 | resets = <&vdosys1 MT8195_VDOSYS1_SW0_RST_B_MERGE4_DL_ASYNC>; |
| 3014 | 3014 | }; |
| 3015 | 3015 | |
| @@ -636,6 +636,7 @@ CONFIG_POWER_RESET_MSM=y · 635 unmodified lines | ||
| 636 | 636 | CONFIG_POWER_RESET_QCOM_PON=m |
| 637 | 637 | CONFIG_POWER_RESET_XGENE=y |
| 638 | 638 | CONFIG_POWER_RESET_SYSCON=y |
| 639 | +CONFIG_POWER_RESET_SYSCON_POWEROFF=y | |
| 639 | 640 | CONFIG_SYSCON_REBOOT_MODE=y |
| 640 | 641 | CONFIG_NVMEM_REBOOT_MODE=m |
| 641 | 642 | CONFIG_BATTERY_SBS=m |
| @@ -1175,7 +1176,6 @@ CONFIG_COMMON_CLK_S2MPS11=y · 533 unmodified lines | ||
| 1175 | 1176 | CONFIG_COMMON_CLK_PWM=y |
| 1176 | 1177 | CONFIG_COMMON_CLK_RS9_PCIE=y |
| 1177 | 1178 | CONFIG_COMMON_CLK_VC5=y |
| 1178 | −CONFIG_COMMON_CLK_NPCM8XX=y | |
| 1179 | 1179 | CONFIG_COMMON_CLK_BD718XX=m |
| 1180 | 1180 | CONFIG_CLK_RASPBERRYPI=m |
| 1181 | 1181 | CONFIG_CLK_IMX8MM=y |
| @@ -663,7 +663,7 @@ static inline bool supports_clearbhb(int scope) · 662 unmodified lines | ||
| 663 | 663 | isar2 = read_sanitised_ftr_reg(SYS_ID_AA64ISAR2_EL1); |
| 664 | 664 | |
| 665 | 665 | return cpuid_feature_extract_unsigned_field(isar2, |
| 666 | − ID_AA64ISAR2_EL1_BC_SHIFT); | |
| 666 | + ID_AA64ISAR2_EL1_CLRBHB_SHIFT); | |
| 667 | 667 | } |
| 668 | 668 | |
| 669 | 669 | const struct cpumask *system_32bit_el0_cpumask(void); |
| @@ -28,7 +28,7 @@ pte_t arch_make_huge_pte(pte_t entry, unsigned int shift, vm_flags_t flags); · 27 unmodified lines | ||
| 28 | 28 | #define arch_make_huge_pte arch_make_huge_pte |
| 29 | 29 | #define __HAVE_ARCH_HUGE_SET_HUGE_PTE_AT |
| 30 | 30 | extern void set_huge_pte_at(struct mm_struct *mm, unsigned long addr, |
| 31 | − pte_t *ptep, pte_t pte); | |
| 31 | + pte_t *ptep, pte_t pte, unsigned long sz); | |
| 32 | 32 | #define __HAVE_ARCH_HUGE_PTEP_SET_ACCESS_FLAGS |
| 33 | 33 | extern int huge_ptep_set_access_flags(struct vm_area_struct *vma, |
| 34 | 34 | unsigned long addr, pte_t *ptep, |
| @@ -118,7 +118,7 @@ void deactivate_traps_vhe_put(struct kvm_vcpu *vcpu); · 117 unmodified lines | ||
| 118 | 118 | |
| 119 | 119 | u64 __guest_enter(struct kvm_vcpu *vcpu); |
| 120 | 120 | |
| 121 | −bool kvm_host_psci_handler(struct kvm_cpu_context *host_ctxt); | |
| 121 | +bool kvm_host_psci_handler(struct kvm_cpu_context *host_ctxt, u32 func_id); | |
| 122 | 122 | |
| 123 | 123 | #ifdef __KVM_NVHE_HYPERVISOR__ |
| 124 | 124 | void __noreturn __hyp_do_panic(struct kvm_cpu_context *host_ctxt, u64 spsr, |
| @@ -222,7 +222,8 @@ static const struct arm64_ftr_bits ftr_id_aa64isar1[] = { · 221 unmodified lines | ||
| 222 | 222 | static const struct arm64_ftr_bits ftr_id_aa64isar2[] = { |
| 223 | 223 | ARM64_FTR_BITS(FTR_VISIBLE, FTR_NONSTRICT, FTR_LOWER_SAFE, ID_AA64ISAR2_EL1_CSSC_SHIFT, 4, 0), |
| 224 | 224 | ARM64_FTR_BITS(FTR_VISIBLE, FTR_NONSTRICT, FTR_LOWER_SAFE, ID_AA64ISAR2_EL1_RPRFM_SHIFT, 4, 0), |
| 225 | − ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_HIGHER_SAFE, ID_AA64ISAR2_EL1_BC_SHIFT, 4, 0), | |
| 225 | + ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_AA64ISAR2_EL1_CLRBHB_SHIFT, 4, 0), | |
| 226 | + ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_LOWER_SAFE, ID_AA64ISAR2_EL1_BC_SHIFT, 4, 0), | |
| 226 | 227 | ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_LOWER_SAFE, ID_AA64ISAR2_EL1_MOPS_SHIFT, 4, 0), |
| 227 | 228 | ARM64_FTR_BITS(FTR_VISIBLE_IF_IS_ENABLED(CONFIG_ARM64_PTR_AUTH), |
| 228 | 229 | FTR_STRICT, FTR_EXACT, ID_AA64ISAR2_EL1_APA3_SHIFT, 4, 0), |
| @@ -12,6 +12,6 @@ · 11 unmodified lines | ||
| 12 | 12 | #define FFA_MAX_FUNC_NUM 0x7F |
| 13 | 13 | |
| 14 | 14 | int hyp_ffa_init(void *pages); |
| 15 | −bool kvm_host_ffa_handler(struct kvm_cpu_context *host_ctxt); | |
| 15 | +bool kvm_host_ffa_handler(struct kvm_cpu_context *host_ctxt, u32 func_id); | |
| 16 | 16 | |
| 17 | 17 | #endif /* __KVM_HYP_FFA_H */ |
| @@ -634,9 +634,8 @@ out_handled: · 633 unmodified lines | ||
| 634 | 634 | return true; |
| 635 | 635 | } |
| 636 | 636 | |
| 637 | −bool kvm_host_ffa_handler(struct kvm_cpu_context *host_ctxt) | |
| 637 | +bool kvm_host_ffa_handler(struct kvm_cpu_context *host_ctxt, u32 func_id) | |
| 638 | 638 | { |
| 639 | − DECLARE_REG(u64, func_id, host_ctxt, 0); | |
| 640 | 639 | struct arm_smccc_res res; |
| 641 | 640 | |
| 642 | 641 | /* |
| @@ -57,6 +57,7 @@ __do_hyp_init: · 56 unmodified lines | ||
| 57 | 57 | cmp x0, #HVC_STUB_HCALL_NR |
| 58 | 58 | b.lo __kvm_handle_stub_hvc |
| 59 | 59 | |
| 60 | + bic x0, x0, #ARM_SMCCC_CALL_HINTS | |
| 60 | 61 | mov x3, #KVM_HOST_SMCCC_FUNC(__kvm_hyp_init) |
| 61 | 62 | cmp x0, x3 |
| 62 | 63 | b.eq 1f |
| @@ -368,6 +368,7 @@ static void handle_host_hcall(struct kvm_cpu_context *host_ctxt) · 367 unmodified lines | ||
| 368 | 368 | if (static_branch_unlikely(&kvm_protected_mode_initialized)) |
| 369 | 369 | hcall_min = __KVM_HOST_SMCCC_FUNC___pkvm_prot_finalize; |
| 370 | 370 | |
| 371 | + id &= ~ARM_SMCCC_CALL_HINTS; | |
| 371 | 372 | id -= KVM_HOST_SMCCC_ID(0); |
| 372 | 373 | |
| 373 | 374 | if (unlikely(id < hcall_min || id >= ARRAY_SIZE(host_hcall))) |
| @@ -392,11 +393,14 @@ static void default_host_smc_handler(struct kvm_cpu_context *host_ctxt) · 18 unmodified lines | ||
| 392 | 393 | |
| 393 | 394 | static void handle_host_smc(struct kvm_cpu_context *host_ctxt) |
| 394 | 395 | { |
| 396 | + DECLARE_REG(u64, func_id, host_ctxt, 0); | |
| 395 | 397 | bool handled; |
| 396 | 398 | |
| 397 | − handled = kvm_host_psci_handler(host_ctxt); | |
| 399 | + func_id &= ~ARM_SMCCC_CALL_HINTS; | |
| 400 | + | |
| 401 | + handled = kvm_host_psci_handler(host_ctxt, func_id); | |
| 398 | 402 | if (!handled) |
| 399 | − handled = kvm_host_ffa_handler(host_ctxt); | |
| 403 | + handled = kvm_host_ffa_handler(host_ctxt, func_id); | |
| 400 | 404 | if (!handled) |
| 401 | 405 | default_host_smc_handler(host_ctxt); |
| 402 | 406 | |
| @@ -273,9 +273,8 @@ static unsigned long psci_1_0_handler(u64 func_id, struct kvm_cpu_context *host_ · 272 unmodified lines | ||
| 273 | 273 | } |
| 274 | 274 | } |
| 275 | 275 | |
| 276 | −bool kvm_host_psci_handler(struct kvm_cpu_context *host_ctxt) | |
| 276 | +bool kvm_host_psci_handler(struct kvm_cpu_context *host_ctxt, u32 func_id) | |
| 277 | 277 | { |
| 278 | − DECLARE_REG(u64, func_id, host_ctxt, 0); | |
| 279 | 278 | unsigned long ret; |
| 280 | 279 | |
| 281 | 280 | switch (kvm_host_psci_config.version) { |
| @@ -652,6 +652,9 @@ int hyp_alloc_private_va_range(size_t size, unsigned long *haddr) · 651 unmodified lines | ||
| 652 | 652 | |
| 653 | 653 | mutex_unlock(&kvm_hyp_pgd_mutex); |
| 654 | 654 | |
| 655 | + if (!ret) | |
| 656 | + *haddr = base; | |
| 657 | + | |
| 655 | 658 | return ret; |
| 656 | 659 | } |
| 657 | 660 | |
| @@ -241,15 +241,8 @@ static void clear_flush(struct mm_struct *mm, · 240 unmodified lines | ||
| 241 | 241 | flush_tlb_range(&vma, saddr, addr); |
| 242 | 242 | } |
| 243 | 243 | |
| 244 | −static inline struct folio *hugetlb_swap_entry_to_folio(swp_entry_t entry) | |
| 245 | −{ | |
| 246 | − VM_BUG_ON(!is_migration_entry(entry) && !is_hwpoison_entry(entry)); | |
| 247 | − | |
| 248 | − return page_folio(pfn_to_page(swp_offset_pfn(entry))); | |
| 249 | −} | |
| 250 | − | |
| 251 | 244 | void set_huge_pte_at(struct mm_struct *mm, unsigned long addr, |
| 252 | − pte_t *ptep, pte_t pte) | |
| 245 | + pte_t *ptep, pte_t pte, unsigned long sz) | |
| 253 | 246 | { |
| 254 | 247 | size_t pgsize; |
| 255 | 248 | int i; |
| @@ -257,13 +250,10 @@ void set_huge_pte_at(struct mm_struct *mm, unsigned long addr, · 1 unmodified line | ||
| 257 | 250 | unsigned long pfn, dpfn; |
| 258 | 251 | pgprot_t hugeprot; |
| 259 | 252 | |
| 260 | − if (!pte_present(pte)) { | |
| 261 | − struct folio *folio; | |
| 262 | − | |
| 263 | − folio = hugetlb_swap_entry_to_folio(pte_to_swp_entry(pte)); | |
| 264 | − ncontig = num_contig_ptes(folio_size(folio), &pgsize); | |
| 253 | + ncontig = num_contig_ptes(sz, &pgsize); | |
| 265 | 254 | |
| 266 | − for (i = 0; i < ncontig; i++, ptep++) | |
| 255 | + if (!pte_present(pte)) { | |
| 256 | + for (i = 0; i < ncontig; i++, ptep++, addr += pgsize) | |
| 267 | 257 | set_pte_at(mm, addr, ptep, pte); |
| 268 | 258 | return; |
| 269 | 259 | } |
| @@ -273,7 +263,6 @@ void set_huge_pte_at(struct mm_struct *mm, unsigned long addr, · 3 unmodified lines | ||
| 273 | 263 | return; |
| 274 | 264 | } |
| 275 | 265 | |
| 276 | − ncontig = find_num_contig(mm, addr, ptep, &pgsize); | |
| 277 | 266 | pfn = pte_pfn(pte); |
| 278 | 267 | dpfn = pgsize >> PAGE_SHIFT; |
| 279 | 268 | hugeprot = pte_pgprot(pte); |
| @@ -571,5 +560,7 @@ pte_t huge_ptep_modify_prot_start(struct vm_area_struct *vma, unsigned long addr · 291 unmodified lines | ||
| 571 | 560 | void huge_ptep_modify_prot_commit(struct vm_area_struct *vma, unsigned long addr, pte_t *ptep, |
| 572 | 561 | pte_t old_pte, pte_t pte) |
| 573 | 562 | { |
| 574 | − set_huge_pte_at(vma->vm_mm, addr, ptep, pte); | |
| 563 | + unsigned long psize = huge_page_size(hstate_vma(vma)); | |
| 564 | + | |
| 565 | + set_huge_pte_at(vma->vm_mm, addr, ptep, pte, psize); | |
| 575 | 566 | } |
| @@ -1347,7 +1347,11 @@ UnsignedEnum 51:48 RPRFM · 1346 unmodified lines | ||
| 1347 | 1347 | 0b0000 NI |
| 1348 | 1348 | 0b0001 IMP |
| 1349 | 1349 | EndEnum |
| 1350 | −Res0 47:28 | |
| 1350 | +Res0 47:32 | |
| 1351 | +UnsignedEnum 31:28 CLRBHB | |
| 1352 | + 0b0000 NI | |
| 1353 | + 0b0001 IMP | |
| 1354 | +EndEnum | |
| 1351 | 1355 | UnsignedEnum 27:24 PAC_frac |
| 1352 | 1356 | 0b0000 NI |
| 1353 | 1357 | 0b0001 IMP |
| @@ -907,3 +907,7 @@ EXPORT_SYMBOL(acpi_unregister_ioapic); · 906 unmodified lines | ||
| 907 | 907 | * TBD when IA64 starts to support suspend... |
| 908 | 908 | */ |
| 909 | 909 | int acpi_suspend_lowlevel(void) { return 0; } |
| 910 | + | |
| 911 | +void acpi_proc_quirk_mwait_check(void) | |
| 912 | +{ | |
| 913 | +} | |
| @@ -19,7 +19,7 @@ · 18 unmodified lines | ||
| 19 | 19 | */ |
| 20 | 20 | #ifndef __ASSEMBLY__ |
| 21 | 21 | #ifndef PHYS_OFFSET |
| 22 | −#define PHYS_OFFSET _AC(0, UL) | |
| 22 | +#define PHYS_OFFSET _UL(0) | |
| 23 | 23 | #endif |
| 24 | 24 | extern unsigned long vm_map_base; |
| 25 | 25 | #endif /* __ASSEMBLY__ */ |
| @@ -43,7 +43,7 @@ extern unsigned long vm_map_base; · 17 unmodified lines | ||
| 43 | 43 | * Memory above this physical address will be considered highmem. |
| 44 | 44 | */ |
| 45 | 45 | #ifndef HIGHMEM_START |
| 46 | −#define HIGHMEM_START (_AC(1, UL) << _AC(DMW_PABITS, UL)) | |
| 46 | +#define HIGHMEM_START (_UL(1) << _UL(DMW_PABITS)) | |
| 47 | 47 | #endif |
| 48 | 48 | |
| 49 | 49 | #define TO_PHYS(x) ( ((x) & TO_PHYS_MASK)) |
| @@ -65,16 +65,16 @@ extern unsigned long vm_map_base; · 15 unmodified lines | ||
| 65 | 65 | #define _ATYPE_ |
| 66 | 66 | #define _ATYPE32_ |
| 67 | 67 | #define _ATYPE64_ |
| 68 | −#define _CONST64_(x) x | |
| 69 | 68 | #else |
| 70 | 69 | #define _ATYPE_ __PTRDIFF_TYPE__ |
| 71 | 70 | #define _ATYPE32_ int |
| 72 | 71 | #define _ATYPE64_ __s64 |
| 72 | +#endif | |
| 73 | + | |
| 73 | 74 | #ifdef CONFIG_64BIT |
| 74 | −#define _CONST64_(x) x ## UL | |
| 75 | +#define _CONST64_(x) _UL(x) | |
| 75 | 76 | #else |
| 76 | −#define _CONST64_(x) x ## ULL | |
| 77 | −#endif | |
| 77 | +#define _CONST64_(x) _ULL(x) | |
| 78 | 78 | #endif |
| 79 | 79 | |
| 80 | 80 | /* |
| @@ -111,6 +111,15 @@ · 110 unmodified lines | ||
| 111 | 111 | #define R_LARCH_TLS_GD_HI20 98 |
| 112 | 112 | #define R_LARCH_32_PCREL 99 |
| 113 | 113 | #define R_LARCH_RELAX 100 |
| 114 | +#define R_LARCH_DELETE 101 | |
| 115 | +#define R_LARCH_ALIGN 102 | |
| 116 | +#define R_LARCH_PCREL20_S2 103 | |
| 117 | +#define R_LARCH_CFA 104 | |
| 118 | +#define R_LARCH_ADD6 105 | |
| 119 | +#define R_LARCH_SUB6 106 | |
| 120 | +#define R_LARCH_ADD_ULEB128 107 | |
| 121 | +#define R_LARCH_SUB_ULEB128 108 | |
| 122 | +#define R_LARCH_64_PCREL 109 | |
| 114 | 123 | |
| 115 | 124 | #ifndef ELF_ARCH |
| 116 | 125 | |
| @@ -0,0 +1,45 @@ | ||
| 1 | +/* SPDX-License-Identifier: GPL-2.0-only */ | |
| 2 | + | |
| 3 | +#ifndef __ASM_EXCEPTION_H | |
| 4 | +#define __ASM_EXCEPTION_H | |
| 5 | + | |
| 6 | +#include <asm/ptrace.h> | |
| 7 | +#include <linux/kprobes.h> | |
| 8 | + | |
| 9 | +void show_registers(struct pt_regs *regs); | |
| 10 | + | |
| 11 | +asmlinkage void cache_parity_error(void); | |
| 12 | +asmlinkage void noinstr do_ade(struct pt_regs *regs); | |
| 13 | +asmlinkage void noinstr do_ale(struct pt_regs *regs); | |
| 14 | +asmlinkage void noinstr do_bce(struct pt_regs *regs); | |
| 15 | +asmlinkage void noinstr do_bp(struct pt_regs *regs); | |
| 16 | +asmlinkage void noinstr do_ri(struct pt_regs *regs); | |
| 17 | +asmlinkage void noinstr do_fpu(struct pt_regs *regs); | |
| 18 | +asmlinkage void noinstr do_fpe(struct pt_regs *regs, unsigned long fcsr); | |
| 19 | +asmlinkage void noinstr do_lsx(struct pt_regs *regs); | |
| 20 | +asmlinkage void noinstr do_lasx(struct pt_regs *regs); | |
| 21 | +asmlinkage void noinstr do_lbt(struct pt_regs *regs); | |
| 22 | +asmlinkage void noinstr do_watch(struct pt_regs *regs); | |
| 23 | +asmlinkage void noinstr do_syscall(struct pt_regs *regs); | |
| 24 | +asmlinkage void noinstr do_reserved(struct pt_regs *regs); | |
| 25 | +asmlinkage void noinstr do_vint(struct pt_regs *regs, unsigned long sp); | |
| 26 | +asmlinkage void __kprobes do_page_fault(struct pt_regs *regs, | |
| 27 | + unsigned long write, unsigned long address); | |
| 28 | + | |
| 29 | +asmlinkage void handle_ade(void); | |
| 30 | +asmlinkage void handle_ale(void); | |
| 31 | +asmlinkage void handle_bce(void); | |
| 32 | +asmlinkage void handle_sys(void); | |
| 33 | +asmlinkage void handle_bp(void); | |
| 34 | +asmlinkage void handle_ri(void); | |
| 35 | +asmlinkage void handle_fpu(void); | |
| 36 | +asmlinkage void handle_fpe(void); | |
| 37 | +asmlinkage void handle_lsx(void); | |
| 38 | +asmlinkage void handle_lasx(void); | |
| 39 | +asmlinkage void handle_lbt(void); | |
| 40 | +asmlinkage void handle_watch(void); | |
| 41 | +asmlinkage void handle_reserved(void); | |
| 42 | +asmlinkage void handle_vint(void); | |
| 43 | +asmlinkage void noinstr handle_loongarch_irq(struct pt_regs *regs); | |
| 44 | + | |
| 45 | +#endif /* __ASM_EXCEPTION_H */ | |
| @@ -10,8 +10,6 @@ · 9 unmodified lines | ||
| 10 | 10 | #include <asm/io.h> |
| 11 | 11 | #include <asm/pgtable.h> |
| 12 | 12 | |
| 13 | −#define __HAVE_ARCH_SHADOW_MAP | |
| 14 | − | |
| 15 | 13 | #define KASAN_SHADOW_SCALE_SHIFT 3 |
| 16 | 14 | #define KASAN_SHADOW_OFFSET _AC(CONFIG_KASAN_SHADOW_OFFSET, UL) |
| 17 | 15 | |
| @@ -62,61 +60,22 @@ · 44 unmodified lines | ||
| 62 | 60 | extern bool kasan_early_stage; |
| 63 | 61 | extern unsigned char kasan_early_shadow_page[PAGE_SIZE]; |
| 64 | 62 | |
| 63 | +#define kasan_mem_to_shadow kasan_mem_to_shadow | |
| 64 | +void *kasan_mem_to_shadow(const void *addr); | |
| 65 | + | |
| 66 | +#define kasan_shadow_to_mem kasan_shadow_to_mem | |
| 67 | +const void *kasan_shadow_to_mem(const void *shadow_addr); | |
| 68 | + | |
| 65 | 69 | #define kasan_arch_is_ready kasan_arch_is_ready |
| 66 | 70 | static __always_inline bool kasan_arch_is_ready(void) |
| 67 | 71 | { |
| 68 | 72 | return !kasan_early_stage; |
| 69 | 73 | } |
| 70 | 74 | |
| 71 | −static inline void *kasan_mem_to_shadow(const void *addr) | |
| 72 | −{ | |
| 73 | − if (!kasan_arch_is_ready()) { | |
| 74 | − return (void *)(kasan_early_shadow_page); | |
| 75 | − } else { | |
| 76 | − unsigned long maddr = (unsigned long)addr; | |
| 77 | − unsigned long xrange = (maddr >> XRANGE_SHIFT) & 0xffff; | |
| 78 | − unsigned long offset = 0; | |
| 79 | − | |
| 80 | − maddr &= XRANGE_SHADOW_MASK; | |
| 81 | − switch (xrange) { | |
| 82 | − case XKPRANGE_CC_SEG: | |
| 83 | − offset = XKPRANGE_CC_SHADOW_OFFSET; | |
| 84 | − break; | |
| 85 | − case XKPRANGE_UC_SEG: | |
| 86 | − offset = XKPRANGE_UC_SHADOW_OFFSET; | |
| 87 | − break; | |
| 88 | − case XKVRANGE_VC_SEG: | |
| 89 | − offset = XKVRANGE_VC_SHADOW_OFFSET; | |
| 90 | − break; | |
| 91 | − default: | |
| 92 | − WARN_ON(1); | |
| 93 | − return NULL; | |
| 94 | − } | |
| 95 | − | |
| 96 | − return (void *)((maddr >> KASAN_SHADOW_SCALE_SHIFT) + offset); | |
| 97 | − } | |
| 98 | −} | |
| 99 | − | |
| 100 | −static inline const void *kasan_shadow_to_mem(const void *shadow_addr) | |
| 75 | +#define addr_has_metadata addr_has_metadata | |
| 76 | +static __always_inline bool addr_has_metadata(const void *addr) | |
| 101 | 77 | { |
| 102 | − unsigned long addr = (unsigned long)shadow_addr; | |
| 103 | − | |
| 104 | − if (unlikely(addr > KASAN_SHADOW_END) || | |
| 105 | − unlikely(addr < KASAN_SHADOW_START)) { | |
| 106 | − WARN_ON(1); | |
| 107 | − return NULL; | |
| 108 | − } | |
| 109 | − | |
| 110 | − if (addr >= XKVRANGE_VC_SHADOW_OFFSET) | |
| 111 | − return (void *)(((addr - XKVRANGE_VC_SHADOW_OFFSET) << KASAN_SHADOW_SCALE_SHIFT) + XKVRANGE_VC_START); | |
| 112 | − else if (addr >= XKPRANGE_UC_SHADOW_OFFSET) | |
| 113 | − return (void *)(((addr - XKPRANGE_UC_SHADOW_OFFSET) << KASAN_SHADOW_SCALE_SHIFT) + XKPRANGE_UC_START); | |
| 114 | − else if (addr >= XKPRANGE_CC_SHADOW_OFFSET) | |
| 115 | − return (void *)(((addr - XKPRANGE_CC_SHADOW_OFFSET) << KASAN_SHADOW_SCALE_SHIFT) + XKPRANGE_CC_START); | |
| 116 | − else { | |
| 117 | − WARN_ON(1); | |
| 118 | − return NULL; | |
| 119 | − } | |
| 78 | + return (kasan_mem_to_shadow((void *)addr) != NULL); | |
| 120 | 79 | } |
| 121 | 80 | |
| 122 | 81 | void kasan_init(void); |
| @@ -70,6 +70,7 @@ struct secondary_data { · 69 unmodified lines | ||
| 70 | 70 | extern struct secondary_data cpuboot_data; |
| 71 | 71 | |
| 72 | 72 | extern asmlinkage void smpboot_entry(void); |
| 73 | +extern asmlinkage void start_secondary(void); | |
| 73 | 74 | |
| 74 | 75 | extern void calculate_cpu_foreign_map(void); |
| 75 | 76 | |
| @@ -19,6 +19,10 @@ obj-$(CONFIG_CPU_HAS_LBT) += lbt.o · 18 unmodified lines | ||
| 19 | 19 | |
| 20 | 20 | obj-$(CONFIG_ARCH_STRICT_ALIGN) += unaligned.o |
| 21 | 21 | |
| 22 | +CFLAGS_module.o += $(call cc-option,-Wno-override-init,) | |
| 23 | +CFLAGS_syscall.o += $(call cc-option,-Wno-override-init,) | |
| 24 | +CFLAGS_perf_event.o += $(call cc-option,-Wno-override-init,) | |
| 25 | + | |
| 22 | 26 | ifdef CONFIG_FUNCTION_TRACER |
| 23 | 27 | ifndef CONFIG_DYNAMIC_FTRACE |
| 24 | 28 | obj-y += mcount.o ftrace.o |
| @@ -281,7 +281,6 @@ acpi_numa_processor_affinity_init(struct acpi_srat_cpu_affinity *pa) · 280 unmodified lines | ||
| 281 | 281 | pr_info("SRAT: PXM %u -> CPU 0x%02x -> Node %u\n", pxm, pa->apic_id, node); |
| 282 | 282 | } |
| 283 | 283 | |
| 284 | −void __init acpi_numa_arch_fixup(void) {} | |
| 285 | 284 | #endif |
| 286 | 285 | |
| 287 | 286 | void __init arch_reserve_mem_area(acpi_physical_address addr, size_t size) |
| @@ -50,7 +50,6 @@ void __init memblock_init(void) · 49 unmodified lines | ||
| 50 | 50 | } |
| 51 | 51 | |
| 52 | 52 | memblock_set_current_limit(PFN_PHYS(max_low_pfn)); |
| 53 | − memblock_set_node(0, PHYS_ADDR_MAX, &memblock.memory, 0); | |
| 54 | 53 | |
| 55 | 54 | /* Reserve the first 2MB */ |
| 56 | 55 | memblock_reserve(PHYS_OFFSET, 0x200000); |
| @@ -58,4 +57,7 @@ void __init memblock_init(void) · 1 unmodified line | ||
| 58 | 57 | /* Reserve the kernel text/data/bss */ |
| 59 | 58 | memblock_reserve(__pa_symbol(&_text), |
| 60 | 59 | __pa_symbol(&_end) - __pa_symbol(&_text)); |
| 60 | + | |
| 61 | + memblock_set_node(0, PHYS_ADDR_MAX, &memblock.memory, 0); | |
| 62 | + memblock_set_node(0, PHYS_ADDR_MAX, &memblock.reserved, 0); | |
| 61 | 63 | } |
| @@ -6,6 +6,7 @@ · 5 unmodified lines | ||
| 6 | 6 | #include <linux/elf.h> |
| 7 | 7 | #include <linux/kernel.h> |
| 8 | 8 | #include <linux/module.h> |
| 9 | +#include <linux/moduleloader.h> | |
| 9 | 10 | #include <linux/ftrace.h> |
| 10 | 11 | |
| 11 | 12 | Elf_Addr module_emit_got_entry(struct module *mod, Elf_Shdr *sechdrs, Elf_Addr val) |
| @@ -367,6 +367,24 @@ static int apply_r_larch_got_pc(struct module *mod, · 366 unmodified lines | ||
| 367 | 367 | return apply_r_larch_pcala(mod, location, got, rela_stack, rela_stack_top, type); |
| 368 | 368 | } |
| 369 | 369 | |
| 370 | +static int apply_r_larch_32_pcrel(struct module *mod, u32 *location, Elf_Addr v, | |
| 371 | + s64 *rela_stack, size_t *rela_stack_top, unsigned int type) | |
| 372 | +{ | |
| 373 | + ptrdiff_t offset = (void *)v - (void *)location; | |
| 374 | + | |
| 375 | + *(u32 *)location = offset; | |
| 376 | + return 0; | |
| 377 | +} | |
| 378 | + | |
| 379 | +static int apply_r_larch_64_pcrel(struct module *mod, u32 *location, Elf_Addr v, | |
| 380 | + s64 *rela_stack, size_t *rela_stack_top, unsigned int type) | |
| 381 | +{ | |
| 382 | + ptrdiff_t offset = (void *)v - (void *)location; | |
| 383 | + | |
| 384 | + *(u64 *)location = offset; | |
| 385 | + return 0; | |
| 386 | +} | |
| 387 | + | |
| 370 | 388 | /* |
| 371 | 389 | * reloc_handlers_rela() - Apply a particular relocation to a module |
| 372 | 390 | * @mod: the module to apply the reloc to |
| @@ -382,7 +400,7 @@ typedef int (*reloc_rela_handler)(struct module *mod, u32 *location, Elf_Addr v, · 9 unmodified lines | ||
| 382 | 400 | |
| 383 | 401 | /* The handlers for known reloc types */ |
| 384 | 402 | static reloc_rela_handler reloc_rela_handlers[] = { |
| 385 | − [R_LARCH_NONE ... R_LARCH_RELAX] = apply_r_larch_error, | |
| 403 | + [R_LARCH_NONE ... R_LARCH_64_PCREL] = apply_r_larch_error, | |
| 386 | 404 | |
| 387 | 405 | [R_LARCH_NONE] = apply_r_larch_none, |
| 388 | 406 | [R_LARCH_32] = apply_r_larch_32, |
| @@ -396,6 +414,8 @@ static reloc_rela_handler reloc_rela_handlers[] = { · 7 unmodified lines | ||
| 396 | 414 | [R_LARCH_SOP_POP_32_S_10_5 ... R_LARCH_SOP_POP_32_U] = apply_r_larch_sop_imm_field, |
| 397 | 415 | [R_LARCH_ADD32 ... R_LARCH_SUB64] = apply_r_larch_add_sub, |
| 398 | 416 | [R_LARCH_PCALA_HI20...R_LARCH_PCALA64_HI12] = apply_r_larch_pcala, |
| 417 | + [R_LARCH_32_PCREL] = apply_r_larch_32_pcrel, | |
| 418 | + [R_LARCH_64_PCREL] = apply_r_larch_64_pcrel, | |
| 399 | 419 | }; |
| 400 | 420 | |
| 401 | 421 | int apply_relocate_add(Elf_Shdr *sechdrs, const char *strtab, |
| @@ -436,7 +436,7 @@ void __init paging_init(void) · 435 unmodified lines | ||
| 436 | 436 | |
| 437 | 437 | void __init mem_init(void) |
| 438 | 438 | { |
| 439 | − high_memory = (void *) __va(get_num_physpages() << PAGE_SHIFT); | |
| 439 | + high_memory = (void *) __va(max_low_pfn << PAGE_SHIFT); | |
| 440 | 440 | memblock_free_all(); |
| 441 | 441 | } |
| 442 | 442 | |
| @@ -37,6 +37,7 @@ · 36 unmodified lines | ||
| 37 | 37 | #include <asm/bootinfo.h> |
| 38 | 38 | #include <asm/cpu.h> |
| 39 | 39 | #include <asm/elf.h> |
| 40 | +#include <asm/exec.h> | |
| 40 | 41 | #include <asm/fpu.h> |
| 41 | 42 | #include <asm/lbt.h> |
| 42 | 43 | #include <asm/io.h> |
| @@ -72,7 +72,6 @@ copy_word: · 71 unmodified lines | ||
| 72 | 72 | LONG_ADDI s5, s5, -1 |
| 73 | 73 | beqz s5, process_entry |
| 74 | 74 | b copy_word |
| 75 | − b process_entry | |
| 76 | 75 | |
| 77 | 76 | done: |
| 78 | 77 | ibar 0 |
| @@ -13,6 +13,7 @@ · 12 unmodified lines | ||
| 13 | 13 | #include <linux/audit.h> |
| 14 | 14 | #include <linux/cache.h> |
| 15 | 15 | #include <linux/context_tracking.h> |
| 16 | +#include <linux/entry-common.h> | |
| 16 | 17 | #include <linux/irqflags.h> |
| 17 | 18 | #include <linux/sched.h> |
| 18 | 19 | #include <linux/mm.h> |
| @@ -891,8 +892,8 @@ static unsigned long setup_extcontext(struct extctx_layout *extctx, unsigned lon · 872 unmodified lines | ||
| 891 | 892 | return new_sp; |
| 892 | 893 | } |
| 893 | 894 | |
| 894 | −void __user *get_sigframe(struct ksignal *ksig, struct pt_regs *regs, | |
| 895 | − struct extctx_layout *extctx) | |
| 895 | +static void __user *get_sigframe(struct ksignal *ksig, struct pt_regs *regs, | |
| 896 | + struct extctx_layout *extctx) | |
| 896 | 897 | { |
| 897 | 898 | unsigned long sp; |
| 898 | 899 | |
| @@ -922,7 +923,7 @@ void __user *get_sigframe(struct ksignal *ksig, struct pt_regs *regs, · 23 unmodified lines | ||
| 922 | 923 | * Atomically swap in the new signal mask, and wait for a signal. |
| 923 | 924 | */ |
| 924 | 925 | |
| 925 | −asmlinkage long sys_rt_sigreturn(void) | |
| 926 | +SYSCALL_DEFINE0(rt_sigreturn) | |
| 926 | 927 | { |
| 927 | 928 | int sig; |
| 928 | 929 | sigset_t set; |
| @@ -13,6 +13,7 @@ · 12 unmodified lines | ||
| 13 | 13 | #include <linux/cpumask.h> |
| 14 | 14 | #include <linux/init.h> |
| 15 | 15 | #include <linux/interrupt.h> |
| 16 | +#include <linux/profile.h> | |
| 16 | 17 | #include <linux/seq_file.h> |
| 17 | 18 | #include <linux/smp.h> |
| 18 | 19 | #include <linux/threads.h> |
| @@ -556,10 +557,12 @@ void smp_send_stop(void) · 537 unmodified lines | ||
| 556 | 557 | smp_call_function(stop_this_cpu, NULL, 0); |
| 557 | 558 | } |
| 558 | 559 | |
| 560 | +#ifdef CONFIG_PROFILING | |
| 559 | 561 | int setup_profiling_timer(unsigned int multiplier) |
| 560 | 562 | { |
| 561 | 563 | return 0; |
| 562 | 564 | } |
| 565 | +#endif | |
| 563 | 566 | |
| 564 | 567 | static void flush_tlb_all_ipi(void *info) |
| 565 | 568 | { |
| @@ -13,6 +13,7 @@ · 12 unmodified lines | ||
| 13 | 13 | #include <linux/unistd.h> |
| 14 | 14 | |
| 15 | 15 | #include <asm/asm.h> |
| 16 | +#include <asm/exception.h> | |
| 16 | 17 | #include <asm/signal.h> |
| 17 | 18 | #include <asm/switch_to.h> |
| 18 | 19 | #include <asm-generic/syscalls.h> |
| @@ -29,7 +29,7 @@ static void constant_event_handler(struct clock_event_device *dev) · 28 unmodified lines | ||
| 29 | 29 | { |
| 30 | 30 | } |
| 31 | 31 | |
| 32 | −irqreturn_t constant_timer_interrupt(int irq, void *data) | |
| 32 | +static irqreturn_t constant_timer_interrupt(int irq, void *data) | |
| 33 | 33 | { |
| 34 | 34 | int cpu = smp_processor_id(); |
| 35 | 35 | struct clock_event_device *cd; |
| @@ -1,4 +1,5 @@ | ||
| 1 | 1 | // SPDX-License-Identifier: GPL-2.0 |
| 2 | +#include <linux/acpi.h> | |
| 2 | 3 | #include <linux/cpu.h> |
| 3 | 4 | #include <linux/cpumask.h> |
| 4 | 5 | #include <linux/init.h> |
| @@ -7,6 +8,8 @@ · 2 unmodified lines | ||
| 7 | 8 | #include <linux/percpu.h> |
| 8 | 9 | #include <asm/bootinfo.h> |
| 9 | 10 | |
| 11 | +#include <acpi/processor.h> | |
| 12 | + | |
| 10 | 13 | static DEFINE_PER_CPU(struct cpu, cpu_devices); |
| 11 | 14 | |
| 12 | 15 | #ifdef CONFIG_HOTPLUG_CPU |
| @@ -25,7 +25,6 @@ · 24 unmodified lines | ||
| 25 | 25 | #include <linux/ptrace.h> |
| 26 | 26 | #include <linux/kgdb.h> |
| 27 | 27 | #include <linux/kdebug.h> |
| 28 | −#include <linux/kprobes.h> | |
| 29 | 28 | #include <linux/notifier.h> |
| 30 | 29 | #include <linux/irq.h> |
| 31 | 30 | #include <linux/perf_event.h> |
| @@ -35,6 +34,7 @@ · 3 unmodified lines | ||
| 35 | 34 | #include <asm/branch.h> |
| 36 | 35 | #include <asm/break.h> |
| 37 | 36 | #include <asm/cpu.h> |
| 37 | +#include <asm/exception.h> | |
| 38 | 38 | #include <asm/fpu.h> |
| 39 | 39 | #include <asm/lbt.h> |
| 40 | 40 | #include <asm/inst.h> |
| @@ -53,21 +53,6 @@ · 12 unmodified lines | ||
| 53 | 53 | |
| 54 | 54 | #include "access-helper.h" |
| 55 | 55 | |
| 56 | −extern asmlinkage void handle_ade(void); | |
| 57 | −extern asmlinkage void handle_ale(void); | |
| 58 | −extern asmlinkage void handle_bce(void); | |
| 59 | −extern asmlinkage void handle_sys(void); | |
| 60 | −extern asmlinkage void handle_bp(void); | |
| 61 | −extern asmlinkage void handle_ri(void); | |
| 62 | −extern asmlinkage void handle_fpu(void); | |
| 63 | −extern asmlinkage void handle_fpe(void); | |
| 64 | −extern asmlinkage void handle_lbt(void); | |
| 65 | −extern asmlinkage void handle_lsx(void); | |
| 66 | −extern asmlinkage void handle_lasx(void); | |
| 67 | −extern asmlinkage void handle_reserved(void); | |
| 68 | −extern asmlinkage void handle_watch(void); | |
| 69 | −extern asmlinkage void handle_vint(void); | |
| 70 | − | |
| 71 | 56 | static void show_backtrace(struct task_struct *task, const struct pt_regs *regs, |
| 72 | 57 | const char *loglvl, bool user) |
| 73 | 58 | { |
| @@ -439,8 +424,8 @@ static inline void setup_vint_size(unsigned int size) · 365 unmodified lines | ||
| 439 | 424 | * happen together with Overflow or Underflow, and `ptrace' can set |
| 440 | 425 | * any bits. |
| 441 | 426 | */ |
| 442 | −void force_fcsr_sig(unsigned long fcsr, void __user *fault_addr, | |
| 443 | − struct task_struct *tsk) | |
| 427 | +static void force_fcsr_sig(unsigned long fcsr, | |
| 428 | + void __user *fault_addr, struct task_struct *tsk) | |
| 444 | 429 | { |
| 445 | 430 | int si_code = FPE_FLTUNK; |
| 446 | 431 | |
| @@ -458,7 +443,7 @@ void force_fcsr_sig(unsigned long fcsr, void __user *fault_addr, · 11 unmodified lines | ||
| 458 | 443 | force_sig_fault(SIGFPE, si_code, fault_addr); |
| 459 | 444 | } |
| 460 | 445 | |
| 461 | −int process_fpemu_return(int sig, void __user *fault_addr, unsigned long fcsr) | |
| 446 | +static int process_fpemu_return(int sig, void __user *fault_addr, unsigned long fcsr) | |
| 462 | 447 | { |
| 463 | 448 | int si_code; |
| 464 | 449 | |
| @@ -824,7 +809,7 @@ out: · 359 unmodified lines | ||
| 824 | 809 | asmlinkage void noinstr do_ri(struct pt_regs *regs) |
| 825 | 810 | { |
| 826 | 811 | int status = SIGILL; |
| 827 | − unsigned int opcode = 0; | |
| 812 | + unsigned int __maybe_unused opcode; | |
| 828 | 813 | unsigned int __user *era = (unsigned int __user *)exception_era(regs); |
| 829 | 814 | irqentry_state_t state = irqentry_enter(regs); |
| 830 | 815 | |
| @@ -53,33 +53,6 @@ SECTIONS · 52 unmodified lines | ||
| 53 | 53 | . = ALIGN(PECOFF_SEGMENT_ALIGN); |
| 54 | 54 | _etext = .; |
| 55 | 55 | |
| 56 | − /* | |
| 57 | − * struct alt_inst entries. From the header (alternative.h): | |
| 58 | − * "Alternative instructions for different CPU types or capabilities" | |
| 59 | − * Think locking instructions on spinlocks. | |
| 60 | − */ | |
| 61 | − . = ALIGN(4); | |
| 62 | − .altinstructions : AT(ADDR(.altinstructions) - LOAD_OFFSET) { | |
| 63 | − __alt_instructions = .; | |
| 64 | − *(.altinstructions) | |
| 65 | − __alt_instructions_end = .; | |
| 66 | − } | |
| 67 | − | |
| 68 | −#ifdef CONFIG_RELOCATABLE | |
| 69 | − . = ALIGN(8); | |
| 70 | − .la_abs : AT(ADDR(.la_abs) - LOAD_OFFSET) { | |
| 71 | − __la_abs_begin = .; | |
| 72 | − *(.la_abs) | |
| 73 | − __la_abs_end = .; | |
| 74 | − } | |
| 75 | −#endif | |
| 76 | − | |
| 77 | − .got : ALIGN(16) { *(.got) } | |
| 78 | − .plt : ALIGN(16) { *(.plt) } | |
| 79 | − .got.plt : ALIGN(16) { *(.got.plt) } | |
| 80 | − | |
| 81 | − .data.rel : { *(.data.rel*) } | |
| 82 | − | |
| 83 | 56 | . = ALIGN(PECOFF_SEGMENT_ALIGN); |
| 84 | 57 | __init_begin = .; |
| 85 | 58 | __inittext_begin = .; |
| @@ -94,6 +67,18 @@ SECTIONS · 8 unmodified lines | ||
| 94 | 67 | |
| 95 | 68 | __initdata_begin = .; |
| 96 | 69 | |
| 70 | + /* | |
| 71 | + * struct alt_inst entries. From the header (alternative.h): | |
| 72 | + * "Alternative instructions for different CPU types or capabilities" | |
| 73 | + * Think locking instructions on spinlocks. | |
| 74 | + */ | |
| 75 | + . = ALIGN(4); | |
| 76 | + .altinstructions : AT(ADDR(.altinstructions) - LOAD_OFFSET) { | |
| 77 | + __alt_instructions = .; | |
| 78 | + *(.altinstructions) | |
| 79 | + __alt_instructions_end = .; | |
| 80 | + } | |
| 81 | + | |
| 97 | 82 | INIT_DATA_SECTION(16) |
| 98 | 83 | .exit.data : { |
| 99 | 84 | EXIT_DATA |
| @@ -113,6 +98,11 @@ SECTIONS · 13 unmodified lines | ||
| 113 | 98 | |
| 114 | 99 | _sdata = .; |
| 115 | 100 | RO_DATA(4096) |
| 101 | + | |
| 102 | + .got : ALIGN(16) { *(.got) } | |
| 103 | + .plt : ALIGN(16) { *(.plt) } | |
| 104 | + .got.plt : ALIGN(16) { *(.got.plt) } | |
| 105 | + | |
| 116 | 106 | RW_DATA(1 << CONFIG_L1_CACHE_SHIFT, PAGE_SIZE, THREAD_SIZE) |
| 117 | 107 | |
| 118 | 108 | .rela.dyn : ALIGN(8) { |
| @@ -121,6 +111,17 @@ SECTIONS · 2 unmodified lines | ||
| 121 | 111 | __rela_dyn_end = .; |
| 122 | 112 | } |
| 123 | 113 | |
| 114 | + .data.rel : { *(.data.rel*) } | |
| 115 | + | |
| 116 | +#ifdef CONFIG_RELOCATABLE | |
| 117 | + . = ALIGN(8); | |
| 118 | + .la_abs : AT(ADDR(.la_abs) - LOAD_OFFSET) { | |
| 119 | + __la_abs_begin = .; | |
| 120 | + *(.la_abs) | |
| 121 | + __la_abs_end = .; | |
| 122 | + } | |
| 123 | +#endif | |
| 124 | + | |
| 124 | 125 | .sdata : { |
| 125 | 126 | *(.sdata) |
| 126 | 127 | } |
| @@ -20,12 +20,12 @@ · 19 unmodified lines | ||
| 20 | 20 | #include <linux/mm.h> |
| 21 | 21 | #include <linux/smp.h> |
| 22 | 22 | #include <linux/kdebug.h> |
| 23 | −#include <linux/kprobes.h> | |
| 24 | 23 | #include <linux/perf_event.h> |
| 25 | 24 | #include <linux/uaccess.h> |
| 26 | 25 | #include <linux/kfence.h> |
| 27 | 26 | |
| 28 | 27 | #include <asm/branch.h> |
| 28 | +#include <asm/exception.h> | |
| 29 | 29 | #include <asm/mmu_context.h> |
| 30 | 30 | #include <asm/ptrace.h> |
| 31 | 31 | |
| @@ -50,18 +50,6 @@ pte_t *huge_pte_offset(struct mm_struct *mm, unsigned long addr, · 49 unmodified lines | ||
| 50 | 50 | return (pte_t *) pmd; |
| 51 | 51 | } |
| 52 | 52 | |
| 53 | −/* | |
| 54 | − * This function checks for proper alignment of input addr and len parameters. | |
| 55 | − */ | |
| 56 | −int is_aligned_hugepage_range(unsigned long addr, unsigned long len) | |
| 57 | −{ | |
| 58 | − if (len & ~HPAGE_MASK) | |
| 59 | − return -EINVAL; | |
| 60 | − if (addr & ~HPAGE_MASK) | |
| 61 | − return -EINVAL; | |
| 62 | − return 0; | |
| 63 | −} | |
| 64 | − | |
| 65 | 53 | int pmd_huge(pmd_t pmd) |
| 66 | 54 | { |
| 67 | 55 | return (pmd_val(pmd) & _PAGE_HUGE) != 0; |
| @@ -4,6 +4,7 @@ · 3 unmodified lines | ||
| 4 | 4 | */ |
| 5 | 5 | |
| 6 | 6 | #include <asm/io.h> |
| 7 | +#include <asm-generic/early_ioremap.h> | |
| 7 | 8 | |
| 8 | 9 | void __init __iomem *early_ioremap(u64 phys_addr, unsigned long size) |
| 9 | 10 | { |
| @@ -35,6 +35,57 @@ static pgd_t kasan_pg_dir[PTRS_PER_PGD] __initdata __aligned(PAGE_SIZE); · 34 unmodified lines | ||
| 35 | 35 | |
| 36 | 36 | bool kasan_early_stage = true; |
| 37 | 37 | |
| 38 | +void *kasan_mem_to_shadow(const void *addr) | |
| 39 | +{ | |
| 40 | + if (!kasan_arch_is_ready()) { | |
| 41 | + return (void *)(kasan_early_shadow_page); | |
| 42 | + } else { | |
| 43 | + unsigned long maddr = (unsigned long)addr; | |
| 44 | + unsigned long xrange = (maddr >> XRANGE_SHIFT) & 0xffff; | |
| 45 | + unsigned long offset = 0; | |
| 46 | + | |
| 47 | + maddr &= XRANGE_SHADOW_MASK; | |
| 48 | + switch (xrange) { | |
| 49 | + case XKPRANGE_CC_SEG: | |
| 50 | + offset = XKPRANGE_CC_SHADOW_OFFSET; | |
| 51 | + break; | |
| 52 | + case XKPRANGE_UC_SEG: | |
| 53 | + offset = XKPRANGE_UC_SHADOW_OFFSET; | |
| 54 | + break; | |
| 55 | + case XKVRANGE_VC_SEG: | |
| 56 | + offset = XKVRANGE_VC_SHADOW_OFFSET; | |
| 57 | + break; | |
| 58 | + default: | |
| 59 | + WARN_ON(1); | |
| 60 | + return NULL; | |
| 61 | + } | |
| 62 | + | |
| 63 | + return (void *)((maddr >> KASAN_SHADOW_SCALE_SHIFT) + offset); | |
| 64 | + } | |
| 65 | +} | |
| 66 | + | |
| 67 | +const void *kasan_shadow_to_mem(const void *shadow_addr) | |
| 68 | +{ | |
| 69 | + unsigned long addr = (unsigned long)shadow_addr; | |
| 70 | + | |
| 71 | + if (unlikely(addr > KASAN_SHADOW_END) || | |
| 72 | + unlikely(addr < KASAN_SHADOW_START)) { | |
| 73 | + WARN_ON(1); | |
| 74 | + return NULL; | |
| 75 | + } | |
| 76 | + | |
| 77 | + if (addr >= XKVRANGE_VC_SHADOW_OFFSET) | |
| 78 | + return (void *)(((addr - XKVRANGE_VC_SHADOW_OFFSET) << KASAN_SHADOW_SCALE_SHIFT) + XKVRANGE_VC_START); | |
| 79 | + else if (addr >= XKPRANGE_UC_SHADOW_OFFSET) | |
| 80 | + return (void *)(((addr - XKPRANGE_UC_SHADOW_OFFSET) << KASAN_SHADOW_SCALE_SHIFT) + XKPRANGE_UC_START); | |
| 81 | + else if (addr >= XKPRANGE_CC_SHADOW_OFFSET) | |
| 82 | + return (void *)(((addr - XKPRANGE_CC_SHADOW_OFFSET) << KASAN_SHADOW_SCALE_SHIFT) + XKPRANGE_CC_START); | |
| 83 | + else { | |
| 84 | + WARN_ON(1); | |
| 85 | + return NULL; | |
| 86 | + } | |
| 87 | +} | |
| 88 | + | |
| 38 | 89 | /* |
| 39 | 90 | * Alloc memory for shadow memory page table. |
| 40 | 91 | */ |
| @@ -261,7 +261,7 @@ unsigned long pcpu_handlers[NR_CPUS]; · 260 unmodified lines | ||
| 261 | 261 | #endif |
| 262 | 262 | extern long exception_handlers[VECSIZE * 128 / sizeof(long)]; |
| 263 | 263 | |
| 264 | −void setup_tlb_handler(int cpu) | |
| 264 | +static void setup_tlb_handler(int cpu) | |
| 265 | 265 | { |
| 266 | 266 | setup_ptwalker(); |
| 267 | 267 | local_flush_tlb_all(); |
| @@ -164,6 +164,7 @@ static struct platform_device db1x00_audio_dev = { · 163 unmodified lines | ||
| 164 | 164 | |
| 165 | 165 | /******************************************************************************/ |
| 166 | 166 | |
| 167 | +#ifdef CONFIG_MMC_AU1X | |
| 167 | 168 | static irqreturn_t db1100_mmc_cd(int irq, void *ptr) |
| 168 | 169 | { |
| 169 | 170 | mmc_detect_change(ptr, msecs_to_jiffies(500)); |
| @@ -369,6 +370,7 @@ static struct platform_device db1100_mmc1_dev = { · 199 unmodified lines | ||
| 369 | 370 | .num_resources = ARRAY_SIZE(au1100_mmc1_res), |
| 370 | 371 | .resource = au1100_mmc1_res, |
| 371 | 372 | }; |
| 373 | +#endif /* CONFIG_MMC_AU1X */ | |
| 372 | 374 | |
| 373 | 375 | /******************************************************************************/ |
| 374 | 376 | |
| @@ -440,8 +442,10 @@ static struct platform_device *db1x00_devs[] = { · 65 unmodified lines | ||
| 440 | 442 | |
| 441 | 443 | static struct platform_device *db1100_devs[] = { |
| 442 | 444 | &au1100_lcd_device, |
| 445 | +#ifdef CONFIG_MMC_AU1X | |
| 443 | 446 | &db1100_mmc0_dev, |
| 444 | 447 | &db1100_mmc1_dev, |
| 448 | +#endif | |
| 445 | 449 | }; |
| 446 | 450 | |
| 447 | 451 | int __init db1000_dev_setup(void) |
| @@ -326,6 +326,7 @@ static struct platform_device db1200_ide_dev = { · 325 unmodified lines | ||
| 326 | 326 | |
| 327 | 327 | /**********************************************************************/ |
| 328 | 328 | |
| 329 | +#ifdef CONFIG_MMC_AU1X | |
| 329 | 330 | /* SD carddetects: they're supposed to be edge-triggered, but ack |
| 330 | 331 | * doesn't seem to work (CPLD Rev 2). Instead, the screaming one |
| 331 | 332 | * is disabled and its counterpart enabled. The 200ms timeout is |
| @@ -584,6 +585,7 @@ static struct platform_device pb1200_mmc1_dev = { · 252 unmodified lines | ||
| 584 | 585 | .num_resources = ARRAY_SIZE(au1200_mmc1_res), |
| 585 | 586 | .resource = au1200_mmc1_res, |
| 586 | 587 | }; |
| 588 | +#endif /* CONFIG_MMC_AU1X */ | |
| 587 | 589 | |
| 588 | 590 | /**********************************************************************/ |
| 589 | 591 | |
| @@ -751,7 +753,9 @@ static struct platform_device db1200_audiodma_dev = { · 161 unmodified lines | ||
| 751 | 753 | static struct platform_device *db1200_devs[] __initdata = { |
| 752 | 754 | NULL, /* PSC0, selected by S6.8 */ |
| 753 | 755 | &db1200_ide_dev, |
| 756 | +#ifdef CONFIG_MMC_AU1X | |
| 754 | 757 | &db1200_mmc0_dev, |
| 758 | +#endif | |
| 755 | 759 | &au1200_lcd_dev, |
| 756 | 760 | &db1200_eth_dev, |
| 757 | 761 | &db1200_nand_dev, |
| @@ -762,7 +766,9 @@ static struct platform_device *db1200_devs[] __initdata = { · 4 unmodified lines | ||
| 762 | 766 | }; |
| 763 | 767 | |
| 764 | 768 | static struct platform_device *pb1200_devs[] __initdata = { |
| 769 | +#ifdef CONFIG_MMC_AU1X | |
| 765 | 770 | &pb1200_mmc1_dev, |
| 771 | +#endif | |
| 766 | 772 | }; |
| 767 | 773 | |
| 768 | 774 | /* Some peripheral base addresses differ on the PB1200 */ |
| @@ -450,6 +450,7 @@ static struct platform_device db1300_ide_dev = { · 449 unmodified lines | ||
| 450 | 450 | |
| 451 | 451 | /**********************************************************************/ |
| 452 | 452 | |
| 453 | +#ifdef CONFIG_MMC_AU1X | |
| 453 | 454 | static irqreturn_t db1300_mmc_cd(int irq, void *ptr) |
| 454 | 455 | { |
| 455 | 456 | disable_irq_nosync(irq); |
| @@ -632,6 +633,7 @@ static struct platform_device db1300_sd0_dev = { · 176 unmodified lines | ||
| 632 | 633 | .resource = au1300_sd0_res, |
| 633 | 634 | .num_resources = ARRAY_SIZE(au1300_sd0_res), |
| 634 | 635 | }; |
| 636 | +#endif /* CONFIG_MMC_AU1X */ | |
| 635 | 637 | |
| 636 | 638 | /**********************************************************************/ |
| 637 | 639 | |
| @@ -767,8 +769,10 @@ static struct platform_device *db1300_dev[] __initdata = { · 129 unmodified lines | ||
| 767 | 769 | &db1300_5waysw_dev, |
| 768 | 770 | &db1300_nand_dev, |
| 769 | 771 | &db1300_ide_dev, |
| 772 | +#ifdef CONFIG_MMC_AU1X | |
| 770 | 773 | &db1300_sd0_dev, |
| 771 | 774 | &db1300_sd1_dev, |
| 775 | +#endif | |
| 772 | 776 | &db1300_lcd_dev, |
| 773 | 777 | &db1300_ac97_dev, |
| 774 | 778 | &db1300_i2s_dev, |
| @@ -6,7 +6,7 @@ · 5 unmodified lines | ||
| 6 | 6 | |
| 7 | 7 | #define __HAVE_ARCH_HUGE_SET_HUGE_PTE_AT |
| 8 | 8 | void set_huge_pte_at(struct mm_struct *mm, unsigned long addr, |
| 9 | − pte_t *ptep, pte_t pte); | |
| 9 | + pte_t *ptep, pte_t pte, unsigned long sz); | |
| 10 | 10 | |
| 11 | 11 | #define __HAVE_ARCH_HUGE_PTEP_GET_AND_CLEAR |
| 12 | 12 | pte_t huge_ptep_get_and_clear(struct mm_struct *mm, unsigned long addr, |
| @@ -140,7 +140,7 @@ static void __set_huge_pte_at(struct mm_struct *mm, unsigned long addr, · 139 unmodified lines | ||
| 140 | 140 | } |
| 141 | 141 | |
| 142 | 142 | void set_huge_pte_at(struct mm_struct *mm, unsigned long addr, |
| 143 | − pte_t *ptep, pte_t entry) | |
| 143 | + pte_t *ptep, pte_t entry, unsigned long sz) | |
| 144 | 144 | { |
| 145 | 145 | __set_huge_pte_at(mm, addr, ptep, entry); |
| 146 | 146 | } |
| @@ -46,7 +46,8 @@ static inline int check_and_get_huge_psize(int shift) · 45 unmodified lines | ||
| 46 | 46 | } |
| 47 | 47 | |
| 48 | 48 | #define __HAVE_ARCH_HUGE_SET_HUGE_PTE_AT |
| 49 | −void set_huge_pte_at(struct mm_struct *mm, unsigned long addr, pte_t *ptep, pte_t pte); | |
| 49 | +void set_huge_pte_at(struct mm_struct *mm, unsigned long addr, pte_t *ptep, | |
| 50 | + pte_t pte, unsigned long sz); | |
| 50 | 51 | |
| 51 | 52 | #define __HAVE_ARCH_HUGE_PTE_CLEAR |
| 52 | 53 | static inline void huge_pte_clear(struct mm_struct *mm, unsigned long addr, |
| @@ -73,29 +73,12 @@ int __no_sanitize_address arch_stack_walk_reliable(stack_trace_consume_fn consum · 72 unmodified lines | ||
| 73 | 73 | bool firstframe; |
| 74 | 74 | |
| 75 | 75 | stack_end = stack_page + THREAD_SIZE; |
| 76 | − if (!is_idle_task(task)) { | |
| 77 | − /* | |
| 78 | − * For user tasks, this is the SP value loaded on | |
| 79 | − * kernel entry, see "PACAKSAVE(r13)" in _switch() and | |
| 80 | − * system_call_common(). | |
| 81 | − * | |
| 82 | − * Likewise for non-swapper kernel threads, | |
| 83 | − * this also happens to be the top of the stack | |
| 84 | − * as setup by copy_thread(). | |
| 85 | − * | |
| 86 | − * Note that stack backlinks are not properly setup by | |
| 87 | − * copy_thread() and thus, a forked task() will have | |
| 88 | − * an unreliable stack trace until it's been | |
| 89 | − * _switch()'ed to for the first time. | |
| 90 | − */ | |
| 91 | − stack_end -= STACK_USER_INT_FRAME_SIZE; | |
| 92 | − } else { | |
| 93 | − /* | |
| 94 | − * idle tasks have a custom stack layout, | |
| 95 | − * c.f. cpu_idle_thread_init(). | |
| 96 | − */ | |
| 76 | + | |
| 77 | + // See copy_thread() for details. | |
| 78 | + if (task->flags & PF_KTHREAD) | |
| 97 | 79 | stack_end -= STACK_FRAME_MIN_SIZE; |
| 98 | − } | |
| 80 | + else | |
| 81 | + stack_end -= STACK_USER_INT_FRAME_SIZE; | |
| 99 | 82 | |
| 100 | 83 | if (task == current) |
| 101 | 84 | sp = current_stack_frame(); |
| @@ -143,11 +143,14 @@ pte_t huge_ptep_modify_prot_start(struct vm_area_struct *vma, · 142 unmodified lines | ||
| 143 | 143 | void huge_ptep_modify_prot_commit(struct vm_area_struct *vma, unsigned long addr, |
| 144 | 144 | pte_t *ptep, pte_t old_pte, pte_t pte) |
| 145 | 145 | { |
| 146 | + unsigned long psize; | |
| 146 | 147 | |
| 147 | 148 | if (radix_enabled()) |
| 148 | 149 | return radix__huge_ptep_modify_prot_commit(vma, addr, ptep, |
| 149 | 150 | old_pte, pte); |
| 150 | − set_huge_pte_at(vma->vm_mm, addr, ptep, pte); | |
| 151 | + | |
| 152 | + psize = huge_page_size(hstate_vma(vma)); | |
| 153 | + set_huge_pte_at(vma->vm_mm, addr, ptep, pte, psize); | |
| 151 | 154 | } |
| 152 | 155 | |
| 153 | 156 | void __init hugetlbpage_init_defaultsize(void) |
| @@ -47,6 +47,7 @@ void radix__huge_ptep_modify_prot_commit(struct vm_area_struct *vma, · 46 unmodified lines | ||
| 47 | 47 | pte_t old_pte, pte_t pte) |
| 48 | 48 | { |
| 49 | 49 | struct mm_struct *mm = vma->vm_mm; |
| 50 | + unsigned long psize = huge_page_size(hstate_vma(vma)); | |
| 50 | 51 | |
| 51 | 52 | /* |
| 52 | 53 | * POWER9 NMMU must flush the TLB after clearing the PTE before |
| @@ -58,5 +59,5 @@ void radix__huge_ptep_modify_prot_commit(struct vm_area_struct *vma, · 5 unmodified lines | ||
| 58 | 59 | atomic_read(&mm->context.copros) > 0) |
| 59 | 60 | radix__flush_hugetlb_page(vma, addr); |
| 60 | 61 | |
| 61 | − set_huge_pte_at(vma->vm_mm, addr, ptep, pte); | |
| 62 | + set_huge_pte_at(vma->vm_mm, addr, ptep, pte, psize); | |
| 62 | 63 | } |
| @@ -91,7 +91,8 @@ static int __ref __early_map_kernel_hugepage(unsigned long va, phys_addr_t pa, · 90 unmodified lines | ||
| 91 | 91 | if (new && WARN_ON(pte_present(*ptep) && pgprot_val(prot))) |
| 92 | 92 | return -EINVAL; |
| 93 | 93 | |
| 94 | − set_huge_pte_at(&init_mm, va, ptep, pte_mkhuge(pfn_pte(pa >> PAGE_SHIFT, prot))); | |
| 94 | + set_huge_pte_at(&init_mm, va, ptep, | |
| 95 | + pte_mkhuge(pfn_pte(pa >> PAGE_SHIFT, prot)), psize); | |
| 95 | 96 | |
| 96 | 97 | return 0; |
| 97 | 98 | } |
| @@ -288,7 +288,8 @@ int huge_ptep_set_access_flags(struct vm_area_struct *vma, · 287 unmodified lines | ||
| 288 | 288 | } |
| 289 | 289 | |
| 290 | 290 | #if defined(CONFIG_PPC_8xx) |
| 291 | −void set_huge_pte_at(struct mm_struct *mm, unsigned long addr, pte_t *ptep, pte_t pte) | |
| 291 | +void set_huge_pte_at(struct mm_struct *mm, unsigned long addr, pte_t *ptep, | |
| 292 | + pte_t pte, unsigned long sz) | |
| 292 | 293 | { |
| 293 | 294 | pmd_t *pmd = pmd_off(mm, addr); |
| 294 | 295 | pte_basic_t val; |
| @@ -262,7 +262,7 @@ · 261 unmodified lines | ||
| 262 | 262 | reg = <0x100000 0x400000>; |
| 263 | 263 | }; |
| 264 | 264 | reserved-data@600000 { |
| 265 | − reg = <0x600000 0x1000000>; | |
| 265 | + reg = <0x600000 0xa00000>; | |
| 266 | 266 | }; |
| 267 | 267 | }; |
| 268 | 268 | }; |
| @@ -440,30 +440,6 @@ · 171 unmodified lines | ||
| 440 | 440 | }; |
| 441 | 441 | }; |
| 442 | 442 | |
| 443 | − uart0_pins: uart0-0 { | |
| 444 | − tx-pins { | |
| 445 | − pinmux = <GPIOMUX(5, GPOUT_SYS_UART0_TX, | |
| 446 | − GPOEN_ENABLE, | |
| 447 | − GPI_NONE)>; | |
| 448 | − bias-disable; | |
| 449 | − drive-strength = <12>; | |
| 450 | − input-disable; | |
| 451 | − input-schmitt-disable; | |
| 452 | − slew-rate = <0>; | |
| 453 | − }; | |
| 454 | − | |
| 455 | − rx-pins { | |
| 456 | − pinmux = <GPIOMUX(6, GPOUT_LOW, | |
| 457 | − GPOEN_DISABLE, | |
| 458 | − GPI_SYS_UART0_RX)>; | |
| 459 | − bias-disable; /* external pull-up */ | |
| 460 | − drive-strength = <2>; | |
| 461 | − input-enable; | |
| 462 | − input-schmitt-enable; | |
| 463 | − slew-rate = <0>; | |
| 464 | − }; | |
| 465 | − }; | |
| 466 | − | |
| 467 | 443 | tdm_pins: tdm-0 { |
| 468 | 444 | tx-pins { |
| 469 | 445 | pinmux = <GPIOMUX(44, GPOUT_SYS_TDM_TXD, |
| @@ -497,6 +473,30 @@ · 27 unmodified lines | ||
| 497 | 473 | input-enable; |
| 498 | 474 | }; |
| 499 | 475 | }; |
| 476 | + | |
| 477 | + uart0_pins: uart0-0 { | |
| 478 | + tx-pins { | |
| 479 | + pinmux = <GPIOMUX(5, GPOUT_SYS_UART0_TX, | |
| 480 | + GPOEN_ENABLE, | |
| 481 | + GPI_NONE)>; | |
| 482 | + bias-disable; | |
| 483 | + drive-strength = <12>; | |
| 484 | + input-disable; | |
| 485 | + input-schmitt-disable; | |
| 486 | + slew-rate = <0>; | |
| 487 | + }; | |
| 488 | + | |
| 489 | + rx-pins { | |
| 490 | + pinmux = <GPIOMUX(6, GPOUT_LOW, | |
| 491 | + GPOEN_DISABLE, | |
| 492 | + GPI_SYS_UART0_RX)>; | |
| 493 | + bias-disable; /* external pull-up */ | |
| 494 | + drive-strength = <2>; | |
| 495 | + input-enable; | |
| 496 | + input-schmitt-enable; | |
| 497 | + slew-rate = <0>; | |
| 498 | + }; | |
| 499 | + }; | |
| 500 | 500 | }; |
| 501 | 501 | |
| 502 | 502 | &tdm { |
| @@ -513,6 +513,7 @@ · 10 unmodified lines | ||
| 513 | 513 | |
| 514 | 514 | &usb0 { |
| 515 | 515 | dr_mode = "peripheral"; |
| 516 | + status = "okay"; | |
| 516 | 517 | }; |
| 517 | 518 | |
| 518 | 519 | &U74_1 { |
| @@ -18,7 +18,8 @@ void huge_pte_clear(struct mm_struct *mm, unsigned long addr, · 17 unmodified lines | ||
| 18 | 18 | |
| 19 | 19 | #define __HAVE_ARCH_HUGE_SET_HUGE_PTE_AT |
| 20 | 20 | void set_huge_pte_at(struct mm_struct *mm, |
| 21 | − unsigned long addr, pte_t *ptep, pte_t pte); | |
| 21 | + unsigned long addr, pte_t *ptep, pte_t pte, | |
| 22 | + unsigned long sz); | |
| 22 | 23 | |
| 23 | 24 | #define __HAVE_ARCH_HUGE_PTEP_GET_AND_CLEAR |
| 24 | 25 | pte_t huge_ptep_get_and_clear(struct mm_struct *mm, |
| @@ -460,8 +460,11 @@ static int riscv_vcpu_get_isa_ext_single(struct kvm_vcpu *vcpu, · 459 unmodified lines | ||
| 460 | 460 | reg_num >= ARRAY_SIZE(kvm_isa_ext_arr)) |
| 461 | 461 | return -ENOENT; |
| 462 | 462 | |
| 463 | − *reg_val = 0; | |
| 464 | 463 | host_isa_ext = kvm_isa_ext_arr[reg_num]; |
| 464 | + if (!__riscv_isa_extension_available(NULL, host_isa_ext)) | |
| 465 | + return -ENOENT; | |
| 466 | + | |
| 467 | + *reg_val = 0; | |
| 465 | 468 | if (__riscv_isa_extension_available(vcpu->arch.isa, host_isa_ext)) |
| 466 | 469 | *reg_val = 1; /* Mark the given extension as available */ |
| 467 | 470 | |
| @@ -842,7 +845,7 @@ static int copy_isa_ext_reg_indices(const struct kvm_vcpu *vcpu, · 374 unmodified lines | ||
| 842 | 845 | u64 reg = KVM_REG_RISCV | size | KVM_REG_RISCV_ISA_EXT | i; |
| 843 | 846 | |
| 844 | 847 | isa_ext = kvm_isa_ext_arr[i]; |
| 845 | − if (!__riscv_isa_extension_available(vcpu->arch.isa, isa_ext)) | |
| 848 | + if (!__riscv_isa_extension_available(NULL, isa_ext)) | |
| 846 | 849 | continue; |
| 847 | 850 | |
| 848 | 851 | if (uindices) { |
| @@ -180,7 +180,8 @@ pte_t arch_make_huge_pte(pte_t entry, unsigned int shift, vm_flags_t flags) · 179 unmodified lines | ||
| 180 | 180 | void set_huge_pte_at(struct mm_struct *mm, |
| 181 | 181 | unsigned long addr, |
| 182 | 182 | pte_t *ptep, |
| 183 | − pte_t pte) | |
| 183 | + pte_t pte, | |
| 184 | + unsigned long sz) | |
| 184 | 185 | { |
| 185 | 186 | int i, pte_num; |
| 186 | 187 | |
| @@ -40,23 +40,25 @@ CONFIG_SCHED_AUTOGROUP=y · 39 unmodified lines | ||
| 40 | 40 | CONFIG_EXPERT=y |
| 41 | 41 | # CONFIG_SYSFS_SYSCALL is not set |
| 42 | 42 | CONFIG_PROFILING=y |
| 43 | +CONFIG_KEXEC_FILE=y | |
| 44 | +CONFIG_KEXEC_SIG=y | |
| 45 | +CONFIG_CRASH_DUMP=y | |
| 43 | 46 | CONFIG_LIVEPATCH=y |
| 44 | 47 | CONFIG_MARCH_ZEC12=y |
| 45 | 48 | CONFIG_TUNE_ZEC12=y |
| 46 | 49 | CONFIG_NR_CPUS=512 |
| 47 | 50 | CONFIG_NUMA=y |
| 48 | 51 | CONFIG_HZ_100=y |
| 49 | −CONFIG_KEXEC_FILE=y | |
| 50 | −CONFIG_KEXEC_SIG=y | |
| 52 | +CONFIG_CERT_STORE=y | |
| 51 | 53 | CONFIG_EXPOLINE=y |
| 52 | 54 | CONFIG_EXPOLINE_AUTO=y |
| 53 | 55 | CONFIG_CHSC_SCH=y |
| 54 | 56 | CONFIG_VFIO_CCW=m |
| 55 | 57 | CONFIG_VFIO_AP=m |
| 56 | −CONFIG_CRASH_DUMP=y | |
| 57 | 58 | CONFIG_PROTECTED_VIRTUALIZATION_GUEST=y |
| 58 | 59 | CONFIG_CMM=m |
| 59 | 60 | CONFIG_APPLDATA_BASE=y |
| 61 | +CONFIG_S390_HYPFS_FS=y | |
| 60 | 62 | CONFIG_KVM=m |
| 61 | 63 | CONFIG_S390_UNWIND_SELFTEST=m |
| 62 | 64 | CONFIG_S390_KPROBES_SANITY_TEST=m |
| @@ -434,6 +436,7 @@ CONFIG_SCSI_DH_EMC=m · 371 unmodified lines | ||
| 434 | 436 | CONFIG_SCSI_DH_ALUA=m |
| 435 | 437 | CONFIG_MD=y |
| 436 | 438 | CONFIG_BLK_DEV_MD=y |
| 439 | +# CONFIG_MD_BITMAP_FILE is not set | |
| 437 | 440 | CONFIG_MD_LINEAR=m |
| 438 | 441 | CONFIG_MD_MULTIPATH=m |
| 439 | 442 | CONFIG_MD_FAULTY=m |
| @@ -577,6 +580,7 @@ CONFIG_SOFT_WATCHDOG=m · 137 unmodified lines | ||
| 577 | 580 | CONFIG_DIAG288_WATCHDOG=m |
| 578 | 581 | # CONFIG_DRM_DEBUG_MODESET_LOCK is not set |
| 579 | 582 | CONFIG_FB=y |
| 583 | +# CONFIG_FB_DEVICE is not set | |
| 580 | 584 | CONFIG_FRAMEBUFFER_CONSOLE=y |
| 581 | 585 | CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY=y |
| 582 | 586 | # CONFIG_HID_SUPPORT is not set |
| @@ -647,6 +651,7 @@ CONFIG_PROC_KCORE=y · 64 unmodified lines | ||
| 647 | 651 | CONFIG_TMPFS=y |
| 648 | 652 | CONFIG_TMPFS_POSIX_ACL=y |
| 649 | 653 | CONFIG_TMPFS_INODE64=y |
| 654 | +CONFIG_TMPFS_QUOTA=y | |
| 650 | 655 | CONFIG_HUGETLBFS=y |
| 651 | 656 | CONFIG_ECRYPT_FS=m |
| 652 | 657 | CONFIG_CRAMFS=m |
| @@ -703,6 +708,7 @@ CONFIG_IMA_WRITE_POLICY=y · 50 unmodified lines | ||
| 703 | 708 | CONFIG_IMA_APPRAISE=y |
| 704 | 709 | CONFIG_LSM="yama,loadpin,safesetid,integrity,selinux,smack,tomoyo,apparmor" |
| 705 | 710 | CONFIG_INIT_STACK_NONE=y |
| 711 | +CONFIG_BUG_ON_DATA_CORRUPTION=y | |
| 706 | 712 | CONFIG_CRYPTO_USER=m |
| 707 | 713 | # CONFIG_CRYPTO_MANAGER_DISABLE_TESTS is not set |
| 708 | 714 | CONFIG_CRYPTO_PCRYPT=m |
| @@ -825,9 +831,9 @@ CONFIG_LOCK_STAT=y · 116 unmodified lines | ||
| 825 | 831 | CONFIG_DEBUG_ATOMIC_SLEEP=y |
| 826 | 832 | CONFIG_DEBUG_LOCKING_API_SELFTESTS=y |
| 827 | 833 | CONFIG_DEBUG_IRQFLAGS=y |
| 834 | +CONFIG_DEBUG_LIST=y | |
| 828 | 835 | CONFIG_DEBUG_SG=y |
| 829 | 836 | CONFIG_DEBUG_NOTIFIERS=y |
| 830 | −CONFIG_BUG_ON_DATA_CORRUPTION=y | |
| 831 | 837 | CONFIG_DEBUG_CREDENTIALS=y |
| 832 | 838 | CONFIG_RCU_TORTURE_TEST=m |
| 833 | 839 | CONFIG_RCU_REF_SCALE_TEST=m |
| @@ -38,23 +38,25 @@ CONFIG_SCHED_AUTOGROUP=y · 37 unmodified lines | ||
| 38 | 38 | CONFIG_EXPERT=y |
| 39 | 39 | # CONFIG_SYSFS_SYSCALL is not set |
| 40 | 40 | CONFIG_PROFILING=y |
| 41 | +CONFIG_KEXEC_FILE=y | |
| 42 | +CONFIG_KEXEC_SIG=y | |
| 43 | +CONFIG_CRASH_DUMP=y | |
| 41 | 44 | CONFIG_LIVEPATCH=y |
| 42 | 45 | CONFIG_MARCH_ZEC12=y |
| 43 | 46 | CONFIG_TUNE_ZEC12=y |
| 44 | 47 | CONFIG_NR_CPUS=512 |
| 45 | 48 | CONFIG_NUMA=y |
| 46 | 49 | CONFIG_HZ_100=y |
| 47 | −CONFIG_KEXEC_FILE=y | |
| 48 | −CONFIG_KEXEC_SIG=y | |
| 50 | +CONFIG_CERT_STORE=y | |
| 49 | 51 | CONFIG_EXPOLINE=y |
| 50 | 52 | CONFIG_EXPOLINE_AUTO=y |
| 51 | 53 | CONFIG_CHSC_SCH=y |
| 52 | 54 | CONFIG_VFIO_CCW=m |
| 53 | 55 | CONFIG_VFIO_AP=m |
| 54 | −CONFIG_CRASH_DUMP=y | |
| 55 | 56 | CONFIG_PROTECTED_VIRTUALIZATION_GUEST=y |
| 56 | 57 | CONFIG_CMM=m |
| 57 | 58 | CONFIG_APPLDATA_BASE=y |
| 59 | +CONFIG_S390_HYPFS_FS=y | |
| 58 | 60 | CONFIG_KVM=m |
| 59 | 61 | CONFIG_S390_UNWIND_SELFTEST=m |
| 60 | 62 | CONFIG_S390_KPROBES_SANITY_TEST=m |
| @@ -424,6 +426,7 @@ CONFIG_SCSI_DH_EMC=m · 363 unmodified lines | ||
| 424 | 426 | CONFIG_SCSI_DH_ALUA=m |
| 425 | 427 | CONFIG_MD=y |
| 426 | 428 | CONFIG_BLK_DEV_MD=y |
| 429 | +# CONFIG_MD_BITMAP_FILE is not set | |
| 427 | 430 | CONFIG_MD_LINEAR=m |
| 428 | 431 | CONFIG_MD_MULTIPATH=m |
| 429 | 432 | CONFIG_MD_FAULTY=m |
| @@ -566,6 +569,7 @@ CONFIG_WATCHDOG_NOWAYOUT=y · 136 unmodified lines | ||
| 566 | 569 | CONFIG_SOFT_WATCHDOG=m |
| 567 | 570 | CONFIG_DIAG288_WATCHDOG=m |
| 568 | 571 | CONFIG_FB=y |
| 572 | +# CONFIG_FB_DEVICE is not set | |
| 569 | 573 | CONFIG_FRAMEBUFFER_CONSOLE=y |
| 570 | 574 | CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY=y |
| 571 | 575 | # CONFIG_HID_SUPPORT is not set |
| @@ -632,6 +636,7 @@ CONFIG_PROC_KCORE=y · 60 unmodified lines | ||
| 632 | 636 | CONFIG_TMPFS=y |
| 633 | 637 | CONFIG_TMPFS_POSIX_ACL=y |
| 634 | 638 | CONFIG_TMPFS_INODE64=y |
| 639 | +CONFIG_TMPFS_QUOTA=y | |
| 635 | 640 | CONFIG_HUGETLBFS=y |
| 636 | 641 | CONFIG_CONFIGFS_FS=m |
| 637 | 642 | CONFIG_ECRYPT_FS=m |
| @@ -687,6 +692,7 @@ CONFIG_IMA_WRITE_POLICY=y · 49 unmodified lines | ||
| 687 | 692 | CONFIG_IMA_APPRAISE=y |
| 688 | 693 | CONFIG_LSM="yama,loadpin,safesetid,integrity,selinux,smack,tomoyo,apparmor" |
| 689 | 694 | CONFIG_INIT_STACK_NONE=y |
| 695 | +CONFIG_BUG_ON_DATA_CORRUPTION=y | |
| 690 | 696 | CONFIG_CRYPTO_FIPS=y |
| 691 | 697 | CONFIG_CRYPTO_USER=m |
| 692 | 698 | # CONFIG_CRYPTO_MANAGER_DISABLE_TESTS is not set |
| @@ -781,7 +787,6 @@ CONFIG_PTDUMP_DEBUGFS=y · 88 unmodified lines | ||
| 781 | 787 | CONFIG_DEBUG_MEMORY_INIT=y |
| 782 | 788 | CONFIG_PANIC_ON_OOPS=y |
| 783 | 789 | CONFIG_TEST_LOCKUP=m |
| 784 | −CONFIG_BUG_ON_DATA_CORRUPTION=y | |
| 785 | 790 | CONFIG_RCU_TORTURE_TEST=m |
| 786 | 791 | CONFIG_RCU_REF_SCALE_TEST=m |
| 787 | 792 | CONFIG_RCU_CPU_STALL_TIMEOUT=60 |
| @@ -8,6 +8,7 @@ CONFIG_BPF_SYSCALL=y · 7 unmodified lines | ||
| 8 | 8 | # CONFIG_NET_NS is not set |
| 9 | 9 | CONFIG_BLK_DEV_INITRD=y |
| 10 | 10 | CONFIG_CC_OPTIMIZE_FOR_SIZE=y |
| 11 | +CONFIG_CRASH_DUMP=y | |
| 11 | 12 | CONFIG_MARCH_ZEC12=y |
| 12 | 13 | CONFIG_TUNE_ZEC12=y |
| 13 | 14 | # CONFIG_COMPAT is not set |
| @@ -15,9 +16,8 @@ CONFIG_NR_CPUS=2 · 1 unmodified line | ||
| 15 | 16 | CONFIG_HZ_100=y |
| 16 | 17 | # CONFIG_CHSC_SCH is not set |
| 17 | 18 | # CONFIG_SCM_BUS is not set |
| 18 | −CONFIG_CRASH_DUMP=y | |
| 19 | 19 | # CONFIG_PFAULT is not set |
| 20 | −# CONFIG_S390_HYPFS_FS is not set | |
| 20 | +# CONFIG_S390_HYPFS is not set | |
| 21 | 21 | # CONFIG_VIRTUALIZATION is not set |
| 22 | 22 | # CONFIG_S390_GUEST is not set |
| 23 | 23 | # CONFIG_SECCOMP is not set |
| @@ -16,6 +16,8 @@ · 15 unmodified lines | ||
| 16 | 16 | #define hugepages_supported() (MACHINE_HAS_EDAT1) |
| 17 | 17 | |
| 18 | 18 | void set_huge_pte_at(struct mm_struct *mm, unsigned long addr, |
| 19 | + pte_t *ptep, pte_t pte, unsigned long sz); | |
| 20 | +void __set_huge_pte_at(struct mm_struct *mm, unsigned long addr, | |
| 19 | 21 | pte_t *ptep, pte_t pte); |
| 20 | 22 | pte_t huge_ptep_get(pte_t *ptep); |
| 21 | 23 | pte_t huge_ptep_get_and_clear(struct mm_struct *mm, |
| @@ -65,7 +67,7 @@ static inline int huge_ptep_set_access_flags(struct vm_area_struct *vma, · 43 unmodified lines | ||
| 65 | 67 | int changed = !pte_same(huge_ptep_get(ptep), pte); |
| 66 | 68 | if (changed) { |
| 67 | 69 | huge_ptep_get_and_clear(vma->vm_mm, addr, ptep); |
| 68 | − set_huge_pte_at(vma->vm_mm, addr, ptep, pte); | |
| 70 | + __set_huge_pte_at(vma->vm_mm, addr, ptep, pte); | |
| 69 | 71 | } |
| 70 | 72 | return changed; |
| 71 | 73 | } |
| @@ -74,7 +76,7 @@ static inline void huge_ptep_set_wrprotect(struct mm_struct *mm, · 2 unmodified lines | ||
| 74 | 76 | unsigned long addr, pte_t *ptep) |
| 75 | 77 | { |
| 76 | 78 | pte_t pte = huge_ptep_get_and_clear(mm, addr, ptep); |
| 77 | − set_huge_pte_at(mm, addr, ptep, pte_wrprotect(pte)); | |
| 79 | + __set_huge_pte_at(mm, addr, ptep, pte_wrprotect(pte)); | |
| 78 | 80 | } |
| 79 | 81 | |
| 80 | 82 | static inline pte_t mk_huge_pte(struct page *page, pgprot_t pgprot) |
| @@ -432,15 +432,16 @@ static char *get_key_description(struct vcssb *vcssb, const struct vce *vce) · 431 unmodified lines | ||
| 432 | 432 | char *desc; |
| 433 | 433 | |
| 434 | 434 | cs_token = vcssb->cs_token; |
| 435 | − /* Description string contains "%64s:%04u:%08u\0". */ | |
| 435 | + /* Description string contains "%64s:%05u:%010u\0". */ | |
| 436 | 436 | name_len = sizeof(vce->vce_hdr.vc_name); |
| 437 | − len = name_len + 1 + 4 + 1 + 8 + 1; | |
| 437 | + len = name_len + 1 + 5 + 1 + 10 + 1; | |
| 438 | 438 | desc = kmalloc(len, GFP_KERNEL); |
| 439 | 439 | if (!desc) |
| 440 | 440 | return NULL; |
| 441 | 441 | |
| 442 | 442 | memcpy(desc, vce->vce_hdr.vc_name, name_len); |
| 443 | − sprintf(desc + name_len, ":%04u:%08u", vce->vce_hdr.vc_index, cs_token); | |
| 443 | + snprintf(desc + name_len, len - name_len, ":%05u:%010u", | |
| 444 | + vce->vce_hdr.vc_index, cs_token); | |
| 444 | 445 | |
| 445 | 446 | return desc; |
| 446 | 447 | } |
| @@ -142,7 +142,7 @@ static void clear_huge_pte_skeys(struct mm_struct *mm, unsigned long rste) · 141 unmodified lines | ||
| 142 | 142 | __storage_key_init_range(paddr, paddr + size - 1); |
| 143 | 143 | } |
| 144 | 144 | |
| 145 | −void set_huge_pte_at(struct mm_struct *mm, unsigned long addr, | |
| 145 | +void __set_huge_pte_at(struct mm_struct *mm, unsigned long addr, | |
| 146 | 146 | pte_t *ptep, pte_t pte) |
| 147 | 147 | { |
| 148 | 148 | unsigned long rste; |
| @@ -163,6 +163,12 @@ void set_huge_pte_at(struct mm_struct *mm, unsigned long addr, · 14 unmodified lines | ||
| 163 | 163 | set_pte(ptep, __pte(rste)); |
| 164 | 164 | } |
| 165 | 165 | |
| 166 | +void set_huge_pte_at(struct mm_struct *mm, unsigned long addr, | |
| 167 | + pte_t *ptep, pte_t pte, unsigned long sz) | |
| 168 | +{ | |
| 169 | + __set_huge_pte_at(mm, addr, ptep, pte); | |
| 170 | +} | |
| 171 | + | |
| 166 | 172 | pte_t huge_ptep_get(pte_t *ptep) |
| 167 | 173 | { |
| 168 | 174 | return __rste_to_pte(pte_val(*ptep)); |
| @@ -2513,7 +2513,7 @@ int arch_prepare_bpf_trampoline(struct bpf_tramp_image *im, void *image, · 2512 unmodified lines | ||
| 2513 | 2513 | return -E2BIG; |
| 2514 | 2514 | } |
| 2515 | 2515 | |
| 2516 | − return ret; | |
| 2516 | + return tjit.common.prg; | |
| 2517 | 2517 | } |
| 2518 | 2518 | |
| 2519 | 2519 | bool bpf_jit_supports_subprog_tailcalls(void) |
| @@ -72,8 +72,8 @@ __ioremap_29bit(phys_addr_t offset, unsigned long size, pgprot_t prot) · 71 unmodified lines | ||
| 72 | 72 | #define __ioremap_29bit(offset, size, prot) NULL |
| 73 | 73 | #endif /* CONFIG_29BIT */ |
| 74 | 74 | |
| 75 | −void __iomem *ioremap_prot(phys_addr_t phys_addr, size_t size, | |
| 76 | − unsigned long prot) | |
| 75 | +void __iomem __ref *ioremap_prot(phys_addr_t phys_addr, size_t size, | |
| 76 | + unsigned long prot) | |
| 77 | 77 | { |
| 78 | 78 | void __iomem *mapped; |
| 79 | 79 | pgprot_t pgprot = __pgprot(prot); |
| @@ -14,6 +14,8 @@ extern struct pud_huge_patch_entry __pud_huge_patch, __pud_huge_patch_end; · 13 unmodified lines | ||
| 14 | 14 | |
| 15 | 15 | #define __HAVE_ARCH_HUGE_SET_HUGE_PTE_AT |
| 16 | 16 | void set_huge_pte_at(struct mm_struct *mm, unsigned long addr, |
| 17 | + pte_t *ptep, pte_t pte, unsigned long sz); | |
| 18 | +void __set_huge_pte_at(struct mm_struct *mm, unsigned long addr, | |
| 17 | 19 | pte_t *ptep, pte_t pte); |
| 18 | 20 | |
| 19 | 21 | #define __HAVE_ARCH_HUGE_PTEP_GET_AND_CLEAR |
| @@ -32,7 +34,7 @@ static inline void huge_ptep_set_wrprotect(struct mm_struct *mm, · 12 unmodified lines | ||
| 32 | 34 | unsigned long addr, pte_t *ptep) |
| 33 | 35 | { |
| 34 | 36 | pte_t old_pte = *ptep; |
| 35 | − set_huge_pte_at(mm, addr, ptep, pte_wrprotect(old_pte)); | |
| 37 | + __set_huge_pte_at(mm, addr, ptep, pte_wrprotect(old_pte)); | |
| 36 | 38 | } |
| 37 | 39 | |
| 38 | 40 | #define __HAVE_ARCH_HUGE_PTEP_SET_ACCESS_FLAGS |
| @@ -42,7 +44,7 @@ static inline int huge_ptep_set_access_flags(struct vm_area_struct *vma, · 3 unmodified lines | ||
| 42 | 44 | { |
| 43 | 45 | int changed = !pte_same(*ptep, pte); |
| 44 | 46 | if (changed) { |
| 45 | − set_huge_pte_at(vma->vm_mm, addr, ptep, pte); | |
| 47 | + __set_huge_pte_at(vma->vm_mm, addr, ptep, pte); | |
| 46 | 48 | flush_tlb_page(vma, addr); |
| 47 | 49 | } |
| 48 | 50 | return changed; |
| @@ -328,7 +328,7 @@ pte_t *huge_pte_offset(struct mm_struct *mm, · 327 unmodified lines | ||
| 328 | 328 | return pte_offset_huge(pmd, addr); |
| 329 | 329 | } |
| 330 | 330 | |
| 331 | −void set_huge_pte_at(struct mm_struct *mm, unsigned long addr, | |
| 331 | +void __set_huge_pte_at(struct mm_struct *mm, unsigned long addr, | |
| 332 | 332 | pte_t *ptep, pte_t entry) |
| 333 | 333 | { |
| 334 | 334 | unsigned int nptes, orig_shift, shift; |
| @@ -364,6 +364,12 @@ void set_huge_pte_at(struct mm_struct *mm, unsigned long addr, · 29 unmodified lines | ||
| 364 | 364 | orig_shift); |
| 365 | 365 | } |
| 366 | 366 | |
| 367 | +void set_huge_pte_at(struct mm_struct *mm, unsigned long addr, | |
| 368 | + pte_t *ptep, pte_t entry, unsigned long sz) | |
| 369 | +{ | |
| 370 | + __set_huge_pte_at(mm, addr, ptep, entry); | |
| 371 | +} | |
| 372 | + | |
| 367 | 373 | pte_t huge_ptep_get_and_clear(struct mm_struct *mm, unsigned long addr, |
| 368 | 374 | pte_t *ptep) |
| 369 | 375 | { |
| @@ -534,8 +534,12 @@ static void amd_pmu_cpu_reset(int cpu) · 533 unmodified lines | ||
| 534 | 534 | /* Clear enable bits i.e. PerfCntrGlobalCtl.PerfCntrEn */ |
| 535 | 535 | wrmsrl(MSR_AMD64_PERF_CNTR_GLOBAL_CTL, 0); |
| 536 | 536 | |
| 537 | − /* Clear overflow bits i.e. PerfCntrGLobalStatus.PerfCntrOvfl */ | |
| 538 | − wrmsrl(MSR_AMD64_PERF_CNTR_GLOBAL_STATUS_CLR, amd_pmu_global_cntr_mask); | |
| 537 | + /* | |
| 538 | + * Clear freeze and overflow bits i.e. PerfCntrGLobalStatus.LbrFreeze | |
| 539 | + * and PerfCntrGLobalStatus.PerfCntrOvfl | |
| 540 | + */ | |
| 541 | + wrmsrl(MSR_AMD64_PERF_CNTR_GLOBAL_STATUS_CLR, | |
| 542 | + GLOBAL_STATUS_LBRS_FROZEN | amd_pmu_global_cntr_mask); | |
| 539 | 543 | } |
| 540 | 544 | |
| 541 | 545 | static int amd_pmu_cpu_prepare(int cpu) |
| @@ -570,6 +574,7 @@ static void amd_pmu_cpu_starting(int cpu) · 28 unmodified lines | ||
| 570 | 574 | int i, nb_id; |
| 571 | 575 | |
| 572 | 576 | cpuc->perf_ctr_virt_mask = AMD64_EVENTSEL_HOSTONLY; |
| 577 | + amd_pmu_cpu_reset(cpu); | |
| 573 | 578 | |
| 574 | 579 | if (!x86_pmu.amd_nb_constraints) |
| 575 | 580 | return; |
| @@ -591,8 +596,6 @@ static void amd_pmu_cpu_starting(int cpu) · 15 unmodified lines | ||
| 591 | 596 | |
| 592 | 597 | cpuc->amd_nb->nb_id = nb_id; |
| 593 | 598 | cpuc->amd_nb->refcnt++; |
| 594 | − | |
| 595 | − amd_pmu_cpu_reset(cpu); | |
| 596 | 599 | } |
| 597 | 600 | |
| 598 | 601 | static void amd_pmu_cpu_dead(int cpu) |
| @@ -601,6 +604,7 @@ static void amd_pmu_cpu_dead(int cpu) · 2 unmodified lines | ||
| 601 | 604 | |
| 602 | 605 | kfree(cpuhw->lbr_sel); |
| 603 | 606 | cpuhw->lbr_sel = NULL; |
| 607 | + amd_pmu_cpu_reset(cpu); | |
| 604 | 608 | |
| 605 | 609 | if (!x86_pmu.amd_nb_constraints) |
| 606 | 610 | return; |
| @@ -613,8 +617,6 @@ static void amd_pmu_cpu_dead(int cpu) · 6 unmodified lines | ||
| 613 | 617 | |
| 614 | 618 | cpuhw->amd_nb = NULL; |
| 615 | 619 | } |
| 616 | − | |
| 617 | − amd_pmu_cpu_reset(cpu); | |
| 618 | 620 | } |
| 619 | 621 | |
| 620 | 622 | static inline void amd_pmu_set_global_ctl(u64 ctl) |
| @@ -884,7 +886,7 @@ static int amd_pmu_v2_handle_irq(struct pt_regs *regs) · 263 unmodified lines | ||
| 884 | 886 | struct hw_perf_event *hwc; |
| 885 | 887 | struct perf_event *event; |
| 886 | 888 | int handled = 0, idx; |
| 887 | − u64 status, mask; | |
| 889 | + u64 reserved, status, mask; | |
| 888 | 890 | bool pmu_enabled; |
| 889 | 891 | |
| 890 | 892 | /* |
| @@ -909,6 +911,14 @@ static int amd_pmu_v2_handle_irq(struct pt_regs *regs) · 18 unmodified lines | ||
| 909 | 911 | status &= ~GLOBAL_STATUS_LBRS_FROZEN; |
| 910 | 912 | } |
| 911 | 913 | |
| 914 | + reserved = status & ~amd_pmu_global_cntr_mask; | |
| 915 | + if (reserved) | |
| 916 | + pr_warn_once("Reserved PerfCntrGlobalStatus bits are set (0x%llx), please consider updating microcode\n", | |
| 917 | + reserved); | |
| 918 | + | |
| 919 | + /* Clear any reserved bits set by buggy microcode */ | |
| 920 | + status &= amd_pmu_global_cntr_mask; | |
| 921 | + | |
| 912 | 922 | for (idx = 0; idx < x86_pmu.num_counters; idx++) { |
| 913 | 923 | if (!test_bit(idx, cpuc->active_mask)) |
| 914 | 924 | continue; |
| @@ -1419,7 +1419,6 @@ struct kvm_arch { · 1418 unmodified lines | ||
| 1419 | 1419 | * the thread holds the MMU lock in write mode. |
| 1420 | 1420 | */ |
| 1421 | 1421 | spinlock_t tdp_mmu_pages_lock; |
| 1422 | − struct workqueue_struct *tdp_mmu_zap_wq; | |
| 1423 | 1422 | #endif /* CONFIG_X86_64 */ |
| 1424 | 1423 | |
| 1425 | 1424 | /* |
| @@ -1835,7 +1834,7 @@ void kvm_mmu_vendor_module_exit(void); · 409 unmodified lines | ||
| 1835 | 1834 | |
| 1836 | 1835 | void kvm_mmu_destroy(struct kvm_vcpu *vcpu); |
| 1837 | 1836 | int kvm_mmu_create(struct kvm_vcpu *vcpu); |
| 1838 | −int kvm_mmu_init_vm(struct kvm *kvm); | |
| 1837 | +void kvm_mmu_init_vm(struct kvm *kvm); | |
| 1839 | 1838 | void kvm_mmu_uninit_vm(struct kvm *kvm); |
| 1840 | 1839 | |
| 1841 | 1840 | void kvm_mmu_after_set_cpuid(struct kvm_vcpu *vcpu); |
| @@ -105,6 +105,13 @@ · 104 unmodified lines | ||
| 105 | 105 | CFI_POST_PADDING \ |
| 106 | 106 | SYM_FUNC_END(__cfi_##name) |
| 107 | 107 | |
| 108 | +/* UML needs to be able to override memcpy() and friends for KASAN. */ | |
| 109 | +#ifdef CONFIG_UML | |
| 110 | +# define SYM_FUNC_ALIAS_MEMFUNC SYM_FUNC_ALIAS_WEAK | |
| 111 | +#else | |
| 112 | +# define SYM_FUNC_ALIAS_MEMFUNC SYM_FUNC_ALIAS | |
| 113 | +#endif | |
| 114 | + | |
| 108 | 115 | /* SYM_TYPED_FUNC_START -- use for indirectly called globals, w/ CFI type */ |
| 109 | 116 | #define SYM_TYPED_FUNC_START(name) \ |
| 110 | 117 | SYM_TYPED_START(name, SYM_L_GLOBAL, SYM_F_ALIGN) \ |
| @@ -186,8 +186,7 @@ do { \ · 185 unmodified lines | ||
| 186 | 186 | #else |
| 187 | 187 | #define deactivate_mm(tsk, mm) \ |
| 188 | 188 | do { \ |
| 189 | − if (!tsk->vfork_done) \ | |
| 190 | − shstk_free(tsk); \ | |
| 189 | + shstk_free(tsk); \ | |
| 191 | 190 | load_gs_index(0); \ |
| 192 | 191 | loadsegment(fs, 0); \ |
| 193 | 192 | } while (0) |
| @@ -955,6 +955,14 @@ static inline int pte_same(pte_t a, pte_t b) · 954 unmodified lines | ||
| 955 | 955 | return a.pte == b.pte; |
| 956 | 956 | } |
| 957 | 957 | |
| 958 | +static inline pte_t pte_next_pfn(pte_t pte) | |
| 959 | +{ | |
| 960 | + if (__pte_needs_invert(pte_val(pte))) | |
| 961 | + return __pte(pte_val(pte) - (1UL << PFN_PTE_SHIFT)); | |
| 962 | + return __pte(pte_val(pte) + (1UL << PFN_PTE_SHIFT)); | |
| 963 | +} | |
| 964 | +#define pte_next_pfn pte_next_pfn | |
| 965 | + | |
| 958 | 966 | static inline int pte_present(pte_t a) |
| 959 | 967 | { |
| 960 | 968 | return pte_flags(a) & (_PAGE_PRESENT | _PAGE_PROTNONE); |
| @@ -683,13 +683,11 @@ extern u16 get_llc_id(unsigned int cpu); · 682 unmodified lines | ||
| 683 | 683 | #ifdef CONFIG_CPU_SUP_AMD |
| 684 | 684 | extern u32 amd_get_nodes_per_socket(void); |
| 685 | 685 | extern u32 amd_get_highest_perf(void); |
| 686 | −extern bool cpu_has_ibpb_brtype_microcode(void); | |
| 687 | 686 | extern void amd_clear_divider(void); |
| 688 | 687 | extern void amd_check_microcode(void); |
| 689 | 688 | #else |
| 690 | 689 | static inline u32 amd_get_nodes_per_socket(void) { return 0; } |
| 691 | 690 | static inline u32 amd_get_highest_perf(void) { return 0; } |
| 692 | −static inline bool cpu_has_ibpb_brtype_microcode(void) { return false; } | |
| 693 | 691 | static inline void amd_clear_divider(void) { } |
| 694 | 692 | static inline void amd_check_microcode(void) { } |
| 695 | 693 | #endif |
| @@ -720,13 +720,8 @@ void __init_or_module noinline apply_returns(s32 *start, s32 *end) · 719 unmodified lines | ||
| 720 | 720 | { |
| 721 | 721 | s32 *s; |
| 722 | 722 | |
| 723 | − /* | |
| 724 | − * Do not patch out the default return thunks if those needed are the | |
| 725 | − * ones generated by the compiler. | |
| 726 | − */ | |
| 727 | − if (cpu_feature_enabled(X86_FEATURE_RETHUNK) && | |
| 728 | − (x86_return_thunk == __x86_return_thunk)) | |
| 729 | − return; | |
| 723 | + if (cpu_feature_enabled(X86_FEATURE_RETHUNK)) | |
| 724 | + static_call_force_reinit(); | |
| 730 | 725 | |
| 731 | 726 | for (s = start; s < end; s++) { |
| 732 | 727 | void *dest = NULL, *addr = (void *)s + *s; |
| @@ -272,7 +272,6 @@ void __init callthunks_patch_builtin_calls(void) · 271 unmodified lines | ||
| 272 | 272 | pr_info("Setting up call depth tracking\n"); |
| 273 | 273 | mutex_lock(&text_mutex); |
| 274 | 274 | callthunks_setup(&cs, &builtin_coretext); |
| 275 | − static_call_force_reinit(); | |
| 276 | 275 | thunks_initialized = true; |
| 277 | 276 | mutex_unlock(&text_mutex); |
| 278 | 277 | } |
| @@ -766,6 +766,15 @@ static void early_init_amd(struct cpuinfo_x86 *c) · 765 unmodified lines | ||
| 766 | 766 | |
| 767 | 767 | if (cpu_has(c, X86_FEATURE_TOPOEXT)) |
| 768 | 768 | smp_num_siblings = ((cpuid_ebx(0x8000001e) >> 8) & 0xff) + 1; |
| 769 | + | |
| 770 | + if (!cpu_has(c, X86_FEATURE_HYPERVISOR) && !cpu_has(c, X86_FEATURE_IBPB_BRTYPE)) { | |
| 771 | + if (c->x86 == 0x17 && boot_cpu_has(X86_FEATURE_AMD_IBPB)) | |
| 772 | + setup_force_cpu_cap(X86_FEATURE_IBPB_BRTYPE); | |
| 773 | + else if (c->x86 >= 0x19 && !wrmsrl_safe(MSR_IA32_PRED_CMD, PRED_CMD_SBPB)) { | |
| 774 | + setup_force_cpu_cap(X86_FEATURE_IBPB_BRTYPE); | |
| 775 | + setup_force_cpu_cap(X86_FEATURE_SBPB); | |
| 776 | + } | |
| 777 | + } | |
| 769 | 778 | } |
| 770 | 779 | |
| 771 | 780 | static void init_amd_k8(struct cpuinfo_x86 *c) |
| @@ -1301,25 +1310,6 @@ void amd_check_microcode(void) · 529 unmodified lines | ||
| 1301 | 1310 | on_each_cpu(zenbleed_check_cpu, NULL, 1); |
| 1302 | 1311 | } |
| 1303 | 1312 | |
| 1304 | −bool cpu_has_ibpb_brtype_microcode(void) | |
| 1305 | −{ | |
| 1306 | − switch (boot_cpu_data.x86) { | |
| 1307 | − /* Zen1/2 IBPB flushes branch type predictions too. */ | |
| 1308 | − case 0x17: | |
| 1309 | − return boot_cpu_has(X86_FEATURE_AMD_IBPB); | |
| 1310 | − case 0x19: | |
| 1311 | − /* Poke the MSR bit on Zen3/4 to check its presence. */ | |
| 1312 | − if (!wrmsrl_safe(MSR_IA32_PRED_CMD, PRED_CMD_SBPB)) { | |
| 1313 | − setup_force_cpu_cap(X86_FEATURE_SBPB); | |
| 1314 | − return true; | |
| 1315 | − } else { | |
| 1316 | − return false; | |
| 1317 | − } | |
| 1318 | − default: | |
| 1319 | − return false; | |
| 1320 | − } | |
| 1321 | −} | |
| 1322 | − | |
| 1323 | 1313 | /* |
| 1324 | 1314 | * Issue a DIV 0/1 insn to clear any division data from previous DIV |
| 1325 | 1315 | * operations. |
| @@ -2404,26 +2404,15 @@ early_param("spec_rstack_overflow", srso_parse_cmdline); · 2403 unmodified lines | ||
| 2404 | 2404 | |
| 2405 | 2405 | static void __init srso_select_mitigation(void) |
| 2406 | 2406 | { |
| 2407 | − bool has_microcode; | |
| 2407 | + bool has_microcode = boot_cpu_has(X86_FEATURE_IBPB_BRTYPE); | |
| 2408 | 2408 | |
| 2409 | 2409 | if (!boot_cpu_has_bug(X86_BUG_SRSO) || cpu_mitigations_off()) |
| 2410 | 2410 | goto pred_cmd; |
| 2411 | 2411 | |
| 2412 | − /* | |
| 2413 | − * The first check is for the kernel running as a guest in order | |
| 2414 | − * for guests to verify whether IBPB is a viable mitigation. | |
| 2415 | − */ | |
| 2416 | − has_microcode = boot_cpu_has(X86_FEATURE_IBPB_BRTYPE) || cpu_has_ibpb_brtype_microcode(); | |
| 2417 | 2412 | if (!has_microcode) { |
| 2418 | 2413 | pr_warn("IBPB-extending microcode not applied!\n"); |
| 2419 | 2414 | pr_warn(SRSO_NOTICE); |
| 2420 | 2415 | } else { |
| 2421 | − /* | |
| 2422 | − * Enable the synthetic (even if in a real CPUID leaf) | |
| 2423 | − * flags for guests. | |
| 2424 | − */ | |
| 2425 | − setup_force_cpu_cap(X86_FEATURE_IBPB_BRTYPE); | |
| 2426 | − | |
| 2427 | 2416 | /* |
| 2428 | 2417 | * Zen1/2 with SMT off aren't vulnerable after the right |
| 2429 | 2418 | * IBPB microcode has been applied. |
| @@ -2444,7 +2433,7 @@ static void __init srso_select_mitigation(void) · 14 unmodified lines | ||
| 2444 | 2433 | |
| 2445 | 2434 | switch (srso_cmd) { |
| 2446 | 2435 | case SRSO_CMD_OFF: |
| 2447 | − return; | |
| 2436 | + goto pred_cmd; | |
| 2448 | 2437 | |
| 2449 | 2438 | case SRSO_CMD_MICROCODE: |
| 2450 | 2439 | if (has_microcode) { |
| @@ -2717,7 +2706,7 @@ static ssize_t srso_show_state(char *buf) · 266 unmodified lines | ||
| 2717 | 2706 | |
| 2718 | 2707 | return sysfs_emit(buf, "%s%s\n", |
| 2719 | 2708 | srso_strings[srso_mitigation], |
| 2720 | − (cpu_has_ibpb_brtype_microcode() ? "" : ", no microcode")); | |
| 2709 | + boot_cpu_has(X86_FEATURE_IBPB_BRTYPE) ? "" : ", no microcode"); | |
| 2721 | 2710 | } |
| 2722 | 2711 | |
| 2723 | 2712 | static ssize_t gds_show_state(char *buf) |
| @@ -1303,7 +1303,7 @@ static const struct x86_cpu_id cpu_vuln_blacklist[] __initconst = { · 1302 unmodified lines | ||
| 1303 | 1303 | VULNBL_AMD(0x15, RETBLEED), |
| 1304 | 1304 | VULNBL_AMD(0x16, RETBLEED), |
| 1305 | 1305 | VULNBL_AMD(0x17, RETBLEED | SMT_RSB | SRSO), |
| 1306 | − VULNBL_HYGON(0x18, RETBLEED | SMT_RSB), | |
| 1306 | + VULNBL_HYGON(0x18, RETBLEED | SMT_RSB | SRSO), | |
| 1307 | 1307 | VULNBL_AMD(0x19, SRSO), |
| 1308 | 1308 | {} |
| 1309 | 1309 | }; |
| @@ -235,6 +235,21 @@ static struct sgx_epc_page *sgx_encl_eldu(struct sgx_encl_page *encl_page, · 234 unmodified lines | ||
| 235 | 235 | return epc_page; |
| 236 | 236 | } |
| 237 | 237 | |
| 238 | +/* | |
| 239 | + * Ensure the SECS page is not swapped out. Must be called with encl->lock | |
| 240 | + * to protect the enclave states including SECS and ensure the SECS page is | |
| 241 | + * not swapped out again while being used. | |
| 242 | + */ | |
| 243 | +static struct sgx_epc_page *sgx_encl_load_secs(struct sgx_encl *encl) | |
| 244 | +{ | |
| 245 | + struct sgx_epc_page *epc_page = encl->secs.epc_page; | |
| 246 | + | |
| 247 | + if (!epc_page) | |
| 248 | + epc_page = sgx_encl_eldu(&encl->secs, NULL); | |
| 249 | + | |
| 250 | + return epc_page; | |
| 251 | +} | |
| 252 | + | |
| 238 | 253 | static struct sgx_encl_page *__sgx_encl_load_page(struct sgx_encl *encl, |
| 239 | 254 | struct sgx_encl_page *entry) |
| 240 | 255 | { |
| @@ -248,11 +263,9 @@ static struct sgx_encl_page *__sgx_encl_load_page(struct sgx_encl *encl, · 7 unmodified lines | ||
| 248 | 263 | return entry; |
| 249 | 264 | } |
| 250 | 265 | |
| 251 | − if (!(encl->secs.epc_page)) { | |
| 252 | − epc_page = sgx_encl_eldu(&encl->secs, NULL); | |
| 253 | − if (IS_ERR(epc_page)) | |
| 254 | − return ERR_CAST(epc_page); | |
| 255 | − } | |
| 266 | + epc_page = sgx_encl_load_secs(encl); | |
| 267 | + if (IS_ERR(epc_page)) | |
| 268 | + return ERR_CAST(epc_page); | |
| 256 | 269 | |
| 257 | 270 | epc_page = sgx_encl_eldu(entry, encl->secs.epc_page); |
| 258 | 271 | if (IS_ERR(epc_page)) |
| @@ -339,6 +352,13 @@ static vm_fault_t sgx_encl_eaug_page(struct vm_area_struct *vma, · 80 unmodified lines | ||
| 339 | 352 | |
| 340 | 353 | mutex_lock(&encl->lock); |
| 341 | 354 | |
| 355 | + epc_page = sgx_encl_load_secs(encl); | |
| 356 | + if (IS_ERR(epc_page)) { | |
| 357 | + if (PTR_ERR(epc_page) == -EBUSY) | |
| 358 | + vmret = VM_FAULT_NOPAGE; | |
| 359 | + goto err_out_unlock; | |
| 360 | + } | |
| 361 | + | |
| 342 | 362 | epc_page = sgx_alloc_epc_page(encl_page, false); |
| 343 | 363 | if (IS_ERR(epc_page)) { |
| 344 | 364 | if (PTR_ERR(epc_page) == -EBUSY) |
| @@ -695,7 +695,6 @@ void kgdb_arch_exit(void) · 694 unmodified lines | ||
| 695 | 695 | } |
| 696 | 696 | |
| 697 | 697 | /** |
| 698 | − * | |
| 699 | 698 | * kgdb_skipexception - Bail out of KGDB when we've been triggered. |
| 700 | 699 | * @exception: Exception vector number |
| 701 | 700 | * @regs: Current &struct pt_regs. |
| @@ -257,13 +257,6 @@ int copy_thread(struct task_struct *p, const struct kernel_clone_args *args) · 256 unmodified lines | ||
| 257 | 257 | if (!ret && unlikely(test_tsk_thread_flag(current, TIF_IO_BITMAP))) |
| 258 | 258 | io_bitmap_share(p); |
| 259 | 259 | |
| 260 | − /* | |
| 261 | − * If copy_thread() if failing, don't leak the shadow stack possibly | |
| 262 | − * allocated in shstk_alloc_thread_stack() above. | |
| 263 | − */ | |
| 264 | − if (ret) | |
| 265 | − shstk_free(p); | |
| 266 | − | |
| 267 | 260 | return ret; |
| 268 | 261 | } |
| 269 | 262 | |
| @@ -358,15 +358,11 @@ static void __init add_early_ima_buffer(u64 phys_addr) · 357 unmodified lines | ||
| 358 | 358 | #if defined(CONFIG_HAVE_IMA_KEXEC) && !defined(CONFIG_OF_FLATTREE) |
| 359 | 359 | int __init ima_free_kexec_buffer(void) |
| 360 | 360 | { |
| 361 | − int rc; | |
| 362 | − | |
| 363 | 361 | if (!ima_kexec_buffer_size) |
| 364 | 362 | return -ENOENT; |
| 365 | 363 | |
| 366 | − rc = memblock_phys_free(ima_kexec_buffer_phys, | |
| 367 | − ima_kexec_buffer_size); | |
| 368 | − if (rc) | |
| 369 | − return rc; | |
| 364 | + memblock_free_late(ima_kexec_buffer_phys, | |
| 365 | + ima_kexec_buffer_size); | |
| 370 | 366 | |
| 371 | 367 | ima_kexec_buffer_phys = 0; |
| 372 | 368 | ima_kexec_buffer_size = 0; |
| @@ -205,10 +205,21 @@ unsigned long shstk_alloc_thread_stack(struct task_struct *tsk, unsigned long cl · 204 unmodified lines | ||
| 205 | 205 | return 0; |
| 206 | 206 | |
| 207 | 207 | /* |
| 208 | − * For CLONE_VM, except vfork, the child needs a separate shadow | |
| 208 | + * For CLONE_VFORK the child will share the parents shadow stack. | |
| 209 | + * Make sure to clear the internal tracking of the thread shadow | |
| 210 | + * stack so the freeing logic run for child knows to leave it alone. | |
| 211 | + */ | |
| 212 | + if (clone_flags & CLONE_VFORK) { | |
| 213 | + shstk->base = 0; | |
| 214 | + shstk->size = 0; | |
| 215 | + return 0; | |
| 216 | + } | |
| 217 | + | |
| 218 | + /* | |
| 219 | + * For !CLONE_VM the child will use a copy of the parents shadow | |
| 209 | 220 | * stack. |
| 210 | 221 | */ |
| 211 | − if ((clone_flags & (CLONE_VFORK | CLONE_VM)) != CLONE_VM) | |
| 222 | + if (!(clone_flags & CLONE_VM)) | |
| 212 | 223 | return 0; |
| 213 | 224 | |
| 214 | 225 | size = adjust_shstk_size(stack_size); |
| @@ -408,7 +419,25 @@ void shstk_free(struct task_struct *tsk) · 193 unmodified lines | ||
| 408 | 419 | if (!tsk->mm || tsk->mm != current->mm) |
| 409 | 420 | return; |
| 410 | 421 | |
| 422 | + /* | |
| 423 | + * If shstk->base is NULL, then this task is not managing its | |
| 424 | + * own shadow stack (CLONE_VFORK). So skip freeing it. | |
| 425 | + */ | |
| 426 | + if (!shstk->base) | |
| 427 | + return; | |
| 428 | + | |
| 429 | + /* | |
| 430 | + * shstk->base is NULL for CLONE_VFORK child tasks, and so is | |
| 431 | + * normal. But size = 0 on a shstk->base is not normal and | |
| 432 | + * indicated an attempt to free the thread shadow stack twice. | |
| 433 | + * Warn about it. | |
| 434 | + */ | |
| 435 | + if (WARN_ON(!shstk->size)) | |
| 436 | + return; | |
| 437 | + | |
| 411 | 438 | unmap_shadow_stack(shstk->base, shstk->size); |
| 439 | + | |
| 440 | + shstk->size = 0; | |
| 412 | 441 | } |
| 413 | 442 | |
| 414 | 443 | static int wrss_control(bool enable) |
| @@ -6167,20 +6167,15 @@ static bool kvm_has_zapped_obsolete_pages(struct kvm *kvm) · 6166 unmodified lines | ||
| 6167 | 6167 | return unlikely(!list_empty_careful(&kvm->arch.zapped_obsolete_pages)); |
| 6168 | 6168 | } |
| 6169 | 6169 | |
| 6170 | −int kvm_mmu_init_vm(struct kvm *kvm) | |
| 6170 | +void kvm_mmu_init_vm(struct kvm *kvm) | |
| 6171 | 6171 | { |
| 6172 | − int r; | |
| 6173 | − | |
| 6174 | 6172 | INIT_LIST_HEAD(&kvm->arch.active_mmu_pages); |
| 6175 | 6173 | INIT_LIST_HEAD(&kvm->arch.zapped_obsolete_pages); |
| 6176 | 6174 | INIT_LIST_HEAD(&kvm->arch.possible_nx_huge_pages); |
| 6177 | 6175 | spin_lock_init(&kvm->arch.mmu_unsync_pages_lock); |
| 6178 | 6176 | |
| 6179 | − if (tdp_mmu_enabled) { | |
| 6180 | − r = kvm_mmu_init_tdp_mmu(kvm); | |
| 6181 | − if (r < 0) | |
| 6182 | − return r; | |
| 6183 | − } | |
| 6177 | + if (tdp_mmu_enabled) | |
| 6178 | + kvm_mmu_init_tdp_mmu(kvm); | |
| 6184 | 6179 | |
| 6185 | 6180 | kvm->arch.split_page_header_cache.kmem_cache = mmu_page_header_cache; |
| 6186 | 6181 | kvm->arch.split_page_header_cache.gfp_zero = __GFP_ZERO; |
| @@ -6189,8 +6184,6 @@ int kvm_mmu_init_vm(struct kvm *kvm) · 2 unmodified lines | ||
| 6189 | 6184 | |
| 6190 | 6185 | kvm->arch.split_desc_cache.kmem_cache = pte_list_desc_cache; |
| 6191 | 6186 | kvm->arch.split_desc_cache.gfp_zero = __GFP_ZERO; |
| 6192 | − | |
| 6193 | − return 0; | |
| 6194 | 6187 | } |
| 6195 | 6188 | |
| 6196 | 6189 | static void mmu_free_vm_memory_caches(struct kvm *kvm) |
| @@ -6246,7 +6239,6 @@ static bool kvm_rmap_zap_gfn_range(struct kvm *kvm, gfn_t gfn_start, gfn_t gfn_e · 49 unmodified lines | ||
| 6246 | 6239 | void kvm_zap_gfn_range(struct kvm *kvm, gfn_t gfn_start, gfn_t gfn_end) |
| 6247 | 6240 | { |
| 6248 | 6241 | bool flush; |
| 6249 | − int i; | |
| 6250 | 6242 | |
| 6251 | 6243 | if (WARN_ON_ONCE(gfn_end <= gfn_start)) |
| 6252 | 6244 | return; |
| @@ -6257,11 +6249,8 @@ void kvm_zap_gfn_range(struct kvm *kvm, gfn_t gfn_start, gfn_t gfn_end) · 4 unmodified lines | ||
| 6257 | 6249 | |
| 6258 | 6250 | flush = kvm_rmap_zap_gfn_range(kvm, gfn_start, gfn_end); |
| 6259 | 6251 | |
| 6260 | − if (tdp_mmu_enabled) { | |
| 6261 | − for (i = 0; i < KVM_ADDRESS_SPACE_NUM; i++) | |
| 6262 | − flush = kvm_tdp_mmu_zap_leafs(kvm, i, gfn_start, | |
| 6263 | − gfn_end, true, flush); | |
| 6264 | − } | |
| 6252 | + if (tdp_mmu_enabled) | |
| 6253 | + flush = kvm_tdp_mmu_zap_leafs(kvm, gfn_start, gfn_end, flush); | |
| 6265 | 6254 | |
| 6266 | 6255 | if (flush) |
| 6267 | 6256 | kvm_flush_remote_tlbs_range(kvm, gfn_start, gfn_end - gfn_start); |
| @@ -58,7 +58,12 @@ struct kvm_mmu_page { · 57 unmodified lines | ||
| 58 | 58 | |
| 59 | 59 | bool tdp_mmu_page; |
| 60 | 60 | bool unsync; |
| 61 | − u8 mmu_valid_gen; | |
| 61 | + union { | |
| 62 | + u8 mmu_valid_gen; | |
| 63 | + | |
| 64 | + /* Only accessed under slots_lock. */ | |
| 65 | + bool tdp_mmu_scheduled_root_to_zap; | |
| 66 | + }; | |
| 62 | 67 | |
| 63 | 68 | /* |
| 64 | 69 | * The shadow page can't be replaced by an equivalent huge page |
| @@ -100,13 +105,7 @@ struct kvm_mmu_page { · 35 unmodified lines | ||
| 100 | 105 | struct kvm_rmap_head parent_ptes; /* rmap pointers to parent sptes */ |
| 101 | 106 | tdp_ptep_t ptep; |
| 102 | 107 | }; |
| 103 | − union { | |
| 104 | − DECLARE_BITMAP(unsync_child_bitmap, 512); | |
| 105 | − struct { | |
| 106 | − struct work_struct tdp_mmu_async_work; | |
| 107 | − void *tdp_mmu_async_data; | |
| 108 | − }; | |
| 109 | − }; | |
| 108 | + DECLARE_BITMAP(unsync_child_bitmap, 512); | |
| 110 | 109 | |
| 111 | 110 | /* |
| 112 | 111 | * Tracks shadow pages that, if zapped, would allow KVM to create an NX |
| @@ -12,18 +12,10 @@ · 11 unmodified lines | ||
| 12 | 12 | #include <trace/events/kvm.h> |
| 13 | 13 | |
| 14 | 14 | /* Initializes the TDP MMU for the VM, if enabled. */ |
| 15 | −int kvm_mmu_init_tdp_mmu(struct kvm *kvm) | |
| 15 | +void kvm_mmu_init_tdp_mmu(struct kvm *kvm) | |
| 16 | 16 | { |
| 17 | − struct workqueue_struct *wq; | |
| 18 | − | |
| 19 | − wq = alloc_workqueue("kvm", WQ_UNBOUND|WQ_MEM_RECLAIM|WQ_CPU_INTENSIVE, 0); | |
| 20 | − if (!wq) | |
| 21 | − return -ENOMEM; | |
| 22 | − | |
| 23 | 17 | INIT_LIST_HEAD(&kvm->arch.tdp_mmu_roots); |
| 24 | 18 | spin_lock_init(&kvm->arch.tdp_mmu_pages_lock); |
| 25 | − kvm->arch.tdp_mmu_zap_wq = wq; | |
| 26 | − return 1; | |
| 27 | 19 | } |
| 28 | 20 | |
| 29 | 21 | /* Arbitrarily returns true so that this may be used in if statements. */ |
| @@ -46,20 +38,15 @@ void kvm_mmu_uninit_tdp_mmu(struct kvm *kvm) · 16 unmodified lines | ||
| 46 | 38 | * ultimately frees all roots. |
| 47 | 39 | */ |
| 48 | 40 | kvm_tdp_mmu_invalidate_all_roots(kvm); |
| 49 | − | |
| 50 | − /* | |
| 51 | − * Destroying a workqueue also first flushes the workqueue, i.e. no | |
| 52 | − * need to invoke kvm_tdp_mmu_zap_invalidated_roots(). | |
| 53 | − */ | |
| 54 | − destroy_workqueue(kvm->arch.tdp_mmu_zap_wq); | |
| 41 | + kvm_tdp_mmu_zap_invalidated_roots(kvm); | |
| 55 | 42 | |
| 56 | 43 | WARN_ON(atomic64_read(&kvm->arch.tdp_mmu_pages)); |
| 57 | 44 | WARN_ON(!list_empty(&kvm->arch.tdp_mmu_roots)); |
| 58 | 45 | |
| 59 | 46 | /* |
| 60 | 47 | * Ensure that all the outstanding RCU callbacks to free shadow pages |
| 61 | − * can run before the VM is torn down. Work items on tdp_mmu_zap_wq | |
| 62 | − * can call kvm_tdp_mmu_put_root and create new callbacks. | |
| 48 | + * can run before the VM is torn down. Putting the last reference to | |
| 49 | + * zapped roots will create new callbacks. | |
| 63 | 50 | */ |
| 64 | 51 | rcu_barrier(); |
| 65 | 52 | } |
| @@ -86,46 +73,6 @@ static void tdp_mmu_free_sp_rcu_callback(struct rcu_head *head) · 20 unmodified lines | ||
| 86 | 73 | tdp_mmu_free_sp(sp); |
| 87 | 74 | } |
| 88 | 75 | |
| 89 | −static void tdp_mmu_zap_root(struct kvm *kvm, struct kvm_mmu_page *root, | |
| 90 | − bool shared); | |
| 91 | − | |
| 92 | −static void tdp_mmu_zap_root_work(struct work_struct *work) | |
| 93 | −{ | |
| 94 | − struct kvm_mmu_page *root = container_of(work, struct kvm_mmu_page, | |
| 95 | − tdp_mmu_async_work); | |
| 96 | − struct kvm *kvm = root->tdp_mmu_async_data; | |
| 97 | − | |
| 98 | − read_lock(&kvm->mmu_lock); | |
| 99 | − | |
| 100 | − /* | |
| 101 | − * A TLB flush is not necessary as KVM performs a local TLB flush when | |
| 102 | − * allocating a new root (see kvm_mmu_load()), and when migrating vCPU | |
| 103 | − * to a different pCPU. Note, the local TLB flush on reuse also | |
| 104 | − * invalidates any paging-structure-cache entries, i.e. TLB entries for | |
| 105 | − * intermediate paging structures, that may be zapped, as such entries | |
| 106 | − * are associated with the ASID on both VMX and SVM. | |
| 107 | − */ | |
| 108 | − tdp_mmu_zap_root(kvm, root, true); | |
| 109 | − | |
| 110 | − /* | |
| 111 | − * Drop the refcount using kvm_tdp_mmu_put_root() to test its logic for | |
| 112 | − * avoiding an infinite loop. By design, the root is reachable while | |
| 113 | − * it's being asynchronously zapped, thus a different task can put its | |
| 114 | − * last reference, i.e. flowing through kvm_tdp_mmu_put_root() for an | |
| 115 | − * asynchronously zapped root is unavoidable. | |
| 116 | − */ | |
| 117 | − kvm_tdp_mmu_put_root(kvm, root, true); | |
| 118 | − | |
| 119 | − read_unlock(&kvm->mmu_lock); | |
| 120 | −} | |
| 121 | − | |
| 122 | −static void tdp_mmu_schedule_zap_root(struct kvm *kvm, struct kvm_mmu_page *root) | |
| 123 | −{ | |
| 124 | − root->tdp_mmu_async_data = kvm; | |
| 125 | − INIT_WORK(&root->tdp_mmu_async_work, tdp_mmu_zap_root_work); | |
| 126 | − queue_work(kvm->arch.tdp_mmu_zap_wq, &root->tdp_mmu_async_work); | |
| 127 | −} | |
| 128 | − | |
| 129 | 76 | void kvm_tdp_mmu_put_root(struct kvm *kvm, struct kvm_mmu_page *root, |
| 130 | 77 | bool shared) |
| 131 | 78 | { |
| @@ -211,8 +158,12 @@ static struct kvm_mmu_page *tdp_mmu_next_root(struct kvm *kvm, · 79 unmodified lines | ||
| 211 | 158 | #define for_each_valid_tdp_mmu_root_yield_safe(_kvm, _root, _as_id, _shared) \ |
| 212 | 159 | __for_each_tdp_mmu_root_yield_safe(_kvm, _root, _as_id, _shared, true) |
| 213 | 160 | |
| 214 | −#define for_each_tdp_mmu_root_yield_safe(_kvm, _root, _as_id) \ | |
| 215 | − __for_each_tdp_mmu_root_yield_safe(_kvm, _root, _as_id, false, false) | |
| 161 | +#define for_each_tdp_mmu_root_yield_safe(_kvm, _root, _shared) \ | |
| 162 | + for (_root = tdp_mmu_next_root(_kvm, NULL, _shared, false); \ | |
| 163 | + _root; \ | |
| 164 | + _root = tdp_mmu_next_root(_kvm, _root, _shared, false)) \ | |
| 165 | + if (!kvm_lockdep_assert_mmu_lock_held(_kvm, _shared)) { \ | |
| 166 | + } else | |
| 216 | 167 | |
| 217 | 168 | /* |
| 218 | 169 | * Iterate over all TDP MMU roots. Requires that mmu_lock be held for write, |
| @@ -292,7 +243,7 @@ hpa_t kvm_tdp_mmu_get_vcpu_root_hpa(struct kvm_vcpu *vcpu) · 73 unmodified lines | ||
| 292 | 243 | * by a memslot update or by the destruction of the VM. Initialize the |
| 293 | 244 | * refcount to two; one reference for the vCPU, and one reference for |
| 294 | 245 | * the TDP MMU itself, which is held until the root is invalidated and |
| 295 | − * is ultimately put by tdp_mmu_zap_root_work(). | |
| 246 | + * is ultimately put by kvm_tdp_mmu_zap_invalidated_roots(). | |
| 296 | 247 | */ |
| 297 | 248 | refcount_set(&root->tdp_mmu_root_count, 2); |
| 298 | 249 | |
| @@ -877,13 +828,12 @@ static bool tdp_mmu_zap_leafs(struct kvm *kvm, struct kvm_mmu_page *root, · 578 unmodified lines | ||
| 877 | 828 | * true if a TLB flush is needed before releasing the MMU lock, i.e. if one or |
| 878 | 829 | * more SPTEs were zapped since the MMU lock was last acquired. |
| 879 | 830 | */ |
| 880 | −bool kvm_tdp_mmu_zap_leafs(struct kvm *kvm, int as_id, gfn_t start, gfn_t end, | |
| 881 | − bool can_yield, bool flush) | |
| 831 | +bool kvm_tdp_mmu_zap_leafs(struct kvm *kvm, gfn_t start, gfn_t end, bool flush) | |
| 882 | 832 | { |
| 883 | 833 | struct kvm_mmu_page *root; |
| 884 | 834 | |
| 885 | − for_each_tdp_mmu_root_yield_safe(kvm, root, as_id) | |
| 886 | − flush = tdp_mmu_zap_leafs(kvm, root, start, end, can_yield, flush); | |
| 835 | + for_each_tdp_mmu_root_yield_safe(kvm, root, false) | |
| 836 | + flush = tdp_mmu_zap_leafs(kvm, root, start, end, true, flush); | |
| 887 | 837 | |
| 888 | 838 | return flush; |
| 889 | 839 | } |
| @@ -891,7 +841,6 @@ bool kvm_tdp_mmu_zap_leafs(struct kvm *kvm, int as_id, gfn_t start, gfn_t end, · 1 unmodified line | ||
| 891 | 841 | void kvm_tdp_mmu_zap_all(struct kvm *kvm) |
| 892 | 842 | { |
| 893 | 843 | struct kvm_mmu_page *root; |
| 894 | − int i; | |
| 895 | 844 | |
| 896 | 845 | /* |
| 897 | 846 | * Zap all roots, including invalid roots, as all SPTEs must be dropped |
| @@ -905,10 +854,8 @@ void kvm_tdp_mmu_zap_all(struct kvm *kvm) · 7 unmodified lines | ||
| 905 | 854 | * is being destroyed or the userspace VMM has exited. In both cases, |
| 906 | 855 | * KVM_RUN is unreachable, i.e. no vCPUs will ever service the request. |
| 907 | 856 | */ |
| 908 | − for (i = 0; i < KVM_ADDRESS_SPACE_NUM; i++) { | |
| 909 | − for_each_tdp_mmu_root_yield_safe(kvm, root, i) | |
| 910 | − tdp_mmu_zap_root(kvm, root, false); | |
| 911 | − } | |
| 857 | + for_each_tdp_mmu_root_yield_safe(kvm, root, false) | |
| 858 | + tdp_mmu_zap_root(kvm, root, false); | |
| 912 | 859 | } |
| 913 | 860 | |
| 914 | 861 | /* |
| @@ -917,18 +864,47 @@ void kvm_tdp_mmu_zap_all(struct kvm *kvm) · 2 unmodified lines | ||
| 917 | 864 | */ |
| 918 | 865 | void kvm_tdp_mmu_zap_invalidated_roots(struct kvm *kvm) |
| 919 | 866 | { |
| 920 | − flush_workqueue(kvm->arch.tdp_mmu_zap_wq); | |
| 867 | + struct kvm_mmu_page *root; | |
| 868 | + | |
| 869 | + read_lock(&kvm->mmu_lock); | |
| 870 | + | |
| 871 | + for_each_tdp_mmu_root_yield_safe(kvm, root, true) { | |
| 872 | + if (!root->tdp_mmu_scheduled_root_to_zap) | |
| 873 | + continue; | |
| 874 | + | |
| 875 | + root->tdp_mmu_scheduled_root_to_zap = false; | |
| 876 | + KVM_BUG_ON(!root->role.invalid, kvm); | |
| 877 | + | |
| 878 | + /* | |
| 879 | + * A TLB flush is not necessary as KVM performs a local TLB | |
| 880 | + * flush when allocating a new root (see kvm_mmu_load()), and | |
| 881 | + * when migrating a vCPU to a different pCPU. Note, the local | |
| 882 | + * TLB flush on reuse also invalidates paging-structure-cache | |
| 883 | + * entries, i.e. TLB entries for intermediate paging structures, | |
| 884 | + * that may be zapped, as such entries are associated with the | |
| 885 | + * ASID on both VMX and SVM. | |
| 886 | + */ | |
| 887 | + tdp_mmu_zap_root(kvm, root, true); | |
| 888 | + | |
| 889 | + /* | |
| 890 | + * The referenced needs to be put *after* zapping the root, as | |
| 891 | + * the root must be reachable by mmu_notifiers while it's being | |
| 892 | + * zapped | |
| 893 | + */ | |
| 894 | + kvm_tdp_mmu_put_root(kvm, root, true); | |
| 895 | + } | |
| 896 | + | |
| 897 | + read_unlock(&kvm->mmu_lock); | |
| 921 | 898 | } |
| 922 | 899 | |
| 923 | 900 | /* |
| 924 | 901 | * Mark each TDP MMU root as invalid to prevent vCPUs from reusing a root that |
| 925 | 902 | * is about to be zapped, e.g. in response to a memslots update. The actual |
| 926 | − * zapping is performed asynchronously. Using a separate workqueue makes it | |
| 927 | − * easy to ensure that the destruction is performed before the "fast zap" | |
| 928 | − * completes, without keeping a separate list of invalidated roots; the list is | |
| 929 | − * effectively the list of work items in the workqueue. | |
| 903 | + * zapping is done separately so that it happens with mmu_lock with read, | |
| 904 | + * whereas invalidating roots must be done with mmu_lock held for write (unless | |
| 905 | + * the VM is being destroyed). | |
| 930 | 906 | * |
| 931 | − * Note, the asynchronous worker is gifted the TDP MMU's reference. | |
| 907 | + * Note, kvm_tdp_mmu_zap_invalidated_roots() is gifted the TDP MMU's reference. | |
| 932 | 908 | * See kvm_tdp_mmu_get_vcpu_root_hpa(). |
| 933 | 909 | */ |
| 934 | 910 | void kvm_tdp_mmu_invalidate_all_roots(struct kvm *kvm) |
| @@ -953,19 +929,20 @@ void kvm_tdp_mmu_invalidate_all_roots(struct kvm *kvm) · 18 unmodified lines | ||
| 953 | 929 | /* |
| 954 | 930 | * As above, mmu_lock isn't held when destroying the VM! There can't |
| 955 | 931 | * be other references to @kvm, i.e. nothing else can invalidate roots |
| 956 | − * or be consuming roots, but walking the list of roots does need to be | |
| 957 | − * guarded against roots being deleted by the asynchronous zap worker. | |
| 932 | + * or get/put references to roots. | |
| 958 | 933 | */ |
| 959 | − rcu_read_lock(); | |
| 960 | − | |
| 961 | − list_for_each_entry_rcu(root, &kvm->arch.tdp_mmu_roots, link) { | |
| 934 | + list_for_each_entry(root, &kvm->arch.tdp_mmu_roots, link) { | |
| 935 | + /* | |
| 936 | + * Note, invalid roots can outlive a memslot update! Invalid | |
| 937 | + * roots must be *zapped* before the memslot update completes, | |
| 938 | + * but a different task can acquire a reference and keep the | |
| 939 | + * root alive after its been zapped. | |
| 940 | + */ | |
| 962 | 941 | if (!root->role.invalid) { |
| 942 | + root->tdp_mmu_scheduled_root_to_zap = true; | |
| 963 | 943 | root->role.invalid = true; |
| 964 | − tdp_mmu_schedule_zap_root(kvm, root); | |
| 965 | 944 | } |
| 966 | 945 | } |
| 967 | − | |
| 968 | − rcu_read_unlock(); | |
| 969 | 946 | } |
| 970 | 947 | |
| 971 | 948 | /* |
| @@ -1146,8 +1123,13 @@ retry: · 174 unmodified lines | ||
| 1146 | 1123 | bool kvm_tdp_mmu_unmap_gfn_range(struct kvm *kvm, struct kvm_gfn_range *range, |
| 1147 | 1124 | bool flush) |
| 1148 | 1125 | { |
| 1149 | − return kvm_tdp_mmu_zap_leafs(kvm, range->slot->as_id, range->start, | |
| 1150 | − range->end, range->may_block, flush); | |
| 1126 | + struct kvm_mmu_page *root; | |
| 1127 | + | |
| 1128 | + __for_each_tdp_mmu_root_yield_safe(kvm, root, range->slot->as_id, false, false) | |
| 1129 | + flush = tdp_mmu_zap_leafs(kvm, root, range->start, range->end, | |
| 1130 | + range->may_block, flush); | |
| 1131 | + | |
| 1132 | + return flush; | |
| 1151 | 1133 | } |
| 1152 | 1134 | |
| 1153 | 1135 | typedef bool (*tdp_handler_t)(struct kvm *kvm, struct tdp_iter *iter, |
| @@ -7,7 +7,7 @@ · 6 unmodified lines | ||
| 7 | 7 | |
| 8 | 8 | #include "spte.h" |
| 9 | 9 | |
| 10 | −int kvm_mmu_init_tdp_mmu(struct kvm *kvm); | |
| 10 | +void kvm_mmu_init_tdp_mmu(struct kvm *kvm); | |
| 11 | 11 | void kvm_mmu_uninit_tdp_mmu(struct kvm *kvm); |
| 12 | 12 | |
| 13 | 13 | hpa_t kvm_tdp_mmu_get_vcpu_root_hpa(struct kvm_vcpu *vcpu); |
| @@ -20,8 +20,7 @@ __must_check static inline bool kvm_tdp_mmu_get_root(struct kvm_mmu_page *root) · 6 unmodified lines | ||
| 20 | 20 | void kvm_tdp_mmu_put_root(struct kvm *kvm, struct kvm_mmu_page *root, |
| 21 | 21 | bool shared); |
| 22 | 22 | |
| 23 | −bool kvm_tdp_mmu_zap_leafs(struct kvm *kvm, int as_id, gfn_t start, | |
| 24 | − gfn_t end, bool can_yield, bool flush); | |
| 23 | +bool kvm_tdp_mmu_zap_leafs(struct kvm *kvm, gfn_t start, gfn_t end, bool flush); | |
| 25 | 24 | bool kvm_tdp_mmu_zap_sp(struct kvm *kvm, struct kvm_mmu_page *sp); |
| 26 | 25 | void kvm_tdp_mmu_zap_all(struct kvm *kvm); |
| 27 | 26 | void kvm_tdp_mmu_invalidate_all_roots(struct kvm *kvm); |
| @@ -2962,6 +2962,32 @@ int sev_es_string_io(struct vcpu_svm *svm, int size, unsigned int port, int in) · 2961 unmodified lines | ||
| 2962 | 2962 | count, in); |
| 2963 | 2963 | } |
| 2964 | 2964 | |
| 2965 | +static void sev_es_vcpu_after_set_cpuid(struct vcpu_svm *svm) | |
| 2966 | +{ | |
| 2967 | + struct kvm_vcpu *vcpu = &svm->vcpu; | |
| 2968 | + | |
| 2969 | + if (boot_cpu_has(X86_FEATURE_V_TSC_AUX)) { | |
| 2970 | + bool v_tsc_aux = guest_cpuid_has(vcpu, X86_FEATURE_RDTSCP) || | |
| 2971 | + guest_cpuid_has(vcpu, X86_FEATURE_RDPID); | |
| 2972 | + | |
| 2973 | + set_msr_interception(vcpu, svm->msrpm, MSR_TSC_AUX, v_tsc_aux, v_tsc_aux); | |
| 2974 | + } | |
| 2975 | +} | |
| 2976 | + | |
| 2977 | +void sev_vcpu_after_set_cpuid(struct vcpu_svm *svm) | |
| 2978 | +{ | |
| 2979 | + struct kvm_vcpu *vcpu = &svm->vcpu; | |
| 2980 | + struct kvm_cpuid_entry2 *best; | |
| 2981 | + | |
| 2982 | + /* For sev guests, the memory encryption bit is not reserved in CR3. */ | |
| 2983 | + best = kvm_find_cpuid_entry(vcpu, 0x8000001F); | |
| 2984 | + if (best) | |
| 2985 | + vcpu->arch.reserved_gpa_bits &= ~(1UL << (best->ebx & 0x3f)); | |
| 2986 | + | |
| 2987 | + if (sev_es_guest(svm->vcpu.kvm)) | |
| 2988 | + sev_es_vcpu_after_set_cpuid(svm); | |
| 2989 | +} | |
| 2990 | + | |
| 2965 | 2991 | static void sev_es_init_vmcb(struct vcpu_svm *svm) |
| 2966 | 2992 | { |
| 2967 | 2993 | struct vmcb *vmcb = svm->vmcb01.ptr; |
| @@ -3024,14 +3050,6 @@ static void sev_es_init_vmcb(struct vcpu_svm *svm) · 56 unmodified lines | ||
| 3024 | 3050 | set_msr_interception(vcpu, svm->msrpm, MSR_IA32_LASTBRANCHTOIP, 1, 1); |
| 3025 | 3051 | set_msr_interception(vcpu, svm->msrpm, MSR_IA32_LASTINTFROMIP, 1, 1); |
| 3026 | 3052 | set_msr_interception(vcpu, svm->msrpm, MSR_IA32_LASTINTTOIP, 1, 1); |
| 3027 | − | |
| 3028 | − if (boot_cpu_has(X86_FEATURE_V_TSC_AUX) && | |
| 3029 | − (guest_cpuid_has(&svm->vcpu, X86_FEATURE_RDTSCP) || | |
| 3030 | − guest_cpuid_has(&svm->vcpu, X86_FEATURE_RDPID))) { | |
| 3031 | − set_msr_interception(vcpu, svm->msrpm, MSR_TSC_AUX, 1, 1); | |
| 3032 | − if (guest_cpuid_has(&svm->vcpu, X86_FEATURE_RDTSCP)) | |
| 3033 | − svm_clr_intercept(svm, INTERCEPT_RDTSCP); | |
| 3034 | − } | |
| 3035 | 3053 | } |
| 3036 | 3054 | |
| 3037 | 3055 | void sev_init_vmcb(struct vcpu_svm *svm) |
| @@ -683,6 +683,21 @@ static int svm_hardware_enable(void) · 682 unmodified lines | ||
| 683 | 683 | |
| 684 | 684 | amd_pmu_enable_virt(); |
| 685 | 685 | |
| 686 | + /* | |
| 687 | + * If TSC_AUX virtualization is supported, TSC_AUX becomes a swap type | |
| 688 | + * "B" field (see sev_es_prepare_switch_to_guest()) for SEV-ES guests. | |
| 689 | + * Since Linux does not change the value of TSC_AUX once set, prime the | |
| 690 | + * TSC_AUX field now to avoid a RDMSR on every vCPU run. | |
| 691 | + */ | |
| 692 | + if (boot_cpu_has(X86_FEATURE_V_TSC_AUX)) { | |
| 693 | + struct sev_es_save_area *hostsa; | |
| 694 | + u32 msr_hi; | |
| 695 | + | |
| 696 | + hostsa = (struct sev_es_save_area *)(page_address(sd->save_area) + 0x400); | |
| 697 | + | |
| 698 | + rdmsr(MSR_TSC_AUX, hostsa->tsc_aux, msr_hi); | |
| 699 | + } | |
| 700 | + | |
| 686 | 701 | return 0; |
| 687 | 702 | } |
| 688 | 703 | |
| @@ -1532,7 +1547,14 @@ static void svm_prepare_switch_to_guest(struct kvm_vcpu *vcpu) · 843 unmodified lines | ||
| 1532 | 1547 | if (tsc_scaling) |
| 1533 | 1548 | __svm_write_tsc_multiplier(vcpu->arch.tsc_scaling_ratio); |
| 1534 | 1549 | |
| 1535 | − if (likely(tsc_aux_uret_slot >= 0)) | |
| 1550 | + /* | |
| 1551 | + * TSC_AUX is always virtualized for SEV-ES guests when the feature is | |
| 1552 | + * available. The user return MSR support is not required in this case | |
| 1553 | + * because TSC_AUX is restored on #VMEXIT from the host save area | |
| 1554 | + * (which has been initialized in svm_hardware_enable()). | |
| 1555 | + */ | |
| 1556 | + if (likely(tsc_aux_uret_slot >= 0) && | |
| 1557 | + (!boot_cpu_has(X86_FEATURE_V_TSC_AUX) || !sev_es_guest(vcpu->kvm))) | |
| 1536 | 1558 | kvm_set_user_return_msr(tsc_aux_uret_slot, svm->tsc_aux, -1ull); |
| 1537 | 1559 | |
| 1538 | 1560 | svm->guest_state_loaded = true; |
| @@ -3086,6 +3108,16 @@ static int svm_set_msr(struct kvm_vcpu *vcpu, struct msr_data *msr) · 1547 unmodified lines | ||
| 3086 | 3108 | svm->sysenter_esp_hi = guest_cpuid_is_intel(vcpu) ? (data >> 32) : 0; |
| 3087 | 3109 | break; |
| 3088 | 3110 | case MSR_TSC_AUX: |
| 3111 | + /* | |
| 3112 | + * TSC_AUX is always virtualized for SEV-ES guests when the | |
| 3113 | + * feature is available. The user return MSR support is not | |
| 3114 | + * required in this case because TSC_AUX is restored on #VMEXIT | |
| 3115 | + * from the host save area (which has been initialized in | |
| 3116 | + * svm_hardware_enable()). | |
| 3117 | + */ | |
| 3118 | + if (boot_cpu_has(X86_FEATURE_V_TSC_AUX) && sev_es_guest(vcpu->kvm)) | |
| 3119 | + break; | |
| 3120 | + | |
| 3089 | 3121 | /* |
| 3090 | 3122 | * TSC_AUX is usually changed only during boot and never read |
| 3091 | 3123 | * directly. Intercept TSC_AUX instead of exposing it to the |
| @@ -4284,7 +4316,6 @@ static bool svm_has_emulated_msr(struct kvm *kvm, u32 index) · 1192 unmodified lines | ||
| 4284 | 4316 | static void svm_vcpu_after_set_cpuid(struct kvm_vcpu *vcpu) |
| 4285 | 4317 | { |
| 4286 | 4318 | struct vcpu_svm *svm = to_svm(vcpu); |
| 4287 | − struct kvm_cpuid_entry2 *best; | |
| 4288 | 4319 | |
| 4289 | 4320 | /* |
| 4290 | 4321 | * SVM doesn't provide a way to disable just XSAVES in the guest, KVM |
| @@ -4328,12 +4359,8 @@ static void svm_vcpu_after_set_cpuid(struct kvm_vcpu *vcpu) · 37 unmodified lines | ||
| 4328 | 4359 | set_msr_interception(vcpu, svm->msrpm, MSR_IA32_FLUSH_CMD, 0, |
| 4329 | 4360 | !!guest_cpuid_has(vcpu, X86_FEATURE_FLUSH_L1D)); |
| 4330 | 4361 | |
| 4331 | − /* For sev guests, the memory encryption bit is not reserved in CR3. */ | |
| 4332 | − if (sev_guest(vcpu->kvm)) { | |
| 4333 | − best = kvm_find_cpuid_entry(vcpu, 0x8000001F); | |
| 4334 | − if (best) | |
| 4335 | − vcpu->arch.reserved_gpa_bits &= ~(1UL << (best->ebx & 0x3f)); | |
| 4336 | − } | |
| 4362 | + if (sev_guest(vcpu->kvm)) | |
| 4363 | + sev_vcpu_after_set_cpuid(svm); | |
| 4337 | 4364 | |
| 4338 | 4365 | init_vmcb_after_set_cpuid(vcpu); |
| 4339 | 4366 | } |
| @@ -684,6 +684,7 @@ void __init sev_hardware_setup(void); · 683 unmodified lines | ||
| 684 | 684 | void sev_hardware_unsetup(void); |
| 685 | 685 | int sev_cpu_init(struct svm_cpu_data *sd); |
| 686 | 686 | void sev_init_vmcb(struct vcpu_svm *svm); |
| 687 | +void sev_vcpu_after_set_cpuid(struct vcpu_svm *svm); | |
| 687 | 688 | void sev_free_vcpu(struct kvm_vcpu *vcpu); |
| 688 | 689 | int sev_handle_vmgexit(struct kvm_vcpu *vcpu); |
| 689 | 690 | int sev_es_string_io(struct vcpu_svm *svm, int size, unsigned int port, int in); |
| @@ -12308,9 +12308,7 @@ int kvm_arch_init_vm(struct kvm *kvm, unsigned long type) · 12307 unmodified lines | ||
| 12308 | 12308 | if (ret) |
| 12309 | 12309 | goto out; |
| 12310 | 12310 | |
| 12311 | − ret = kvm_mmu_init_vm(kvm); | |
| 12312 | − if (ret) | |
| 12313 | − goto out_page_track; | |
| 12311 | + kvm_mmu_init_vm(kvm); | |
| 12314 | 12312 | |
| 12315 | 12313 | ret = static_call(kvm_x86_vm_init)(kvm); |
| 12316 | 12314 | if (ret) |
| @@ -12355,7 +12353,6 @@ int kvm_arch_init_vm(struct kvm *kvm, unsigned long type) · 38 unmodified lines | ||
| 12355 | 12353 | |
| 12356 | 12354 | out_uninit_mmu: |
| 12357 | 12355 | kvm_mmu_uninit_vm(kvm); |
| 12358 | −out_page_track: | |
| 12359 | 12356 | kvm_page_track_cleanup(kvm); |
| 12360 | 12357 | out: |
| 12361 | 12358 | return ret; |
| @@ -40,7 +40,7 @@ SYM_TYPED_FUNC_START(__memcpy) · 39 unmodified lines | ||
| 40 | 40 | SYM_FUNC_END(__memcpy) |
| 41 | 41 | EXPORT_SYMBOL(__memcpy) |
| 42 | 42 | |
| 43 | −SYM_FUNC_ALIAS(memcpy, __memcpy) | |
| 43 | +SYM_FUNC_ALIAS_MEMFUNC(memcpy, __memcpy) | |
| 44 | 44 | EXPORT_SYMBOL(memcpy) |
| 45 | 45 | |
| 46 | 46 | SYM_FUNC_START_LOCAL(memcpy_orig) |
| @@ -212,5 +212,5 @@ SYM_FUNC_START(__memmove) · 211 unmodified lines | ||
| 212 | 212 | SYM_FUNC_END(__memmove) |
| 213 | 213 | EXPORT_SYMBOL(__memmove) |
| 214 | 214 | |
| 215 | −SYM_FUNC_ALIAS(memmove, __memmove) | |
| 215 | +SYM_FUNC_ALIAS_MEMFUNC(memmove, __memmove) | |
| 216 | 216 | EXPORT_SYMBOL(memmove) |
| @@ -40,7 +40,7 @@ SYM_FUNC_START(__memset) · 39 unmodified lines | ||
| 40 | 40 | SYM_FUNC_END(__memset) |
| 41 | 41 | EXPORT_SYMBOL(__memset) |
| 42 | 42 | |
| 43 | −SYM_FUNC_ALIAS(memset, __memset) | |
| 43 | +SYM_FUNC_ALIAS_MEMFUNC(memset, __memset) | |
| 44 | 44 | EXPORT_SYMBOL(memset) |
| 45 | 45 | |
| 46 | 46 | SYM_FUNC_START_LOCAL(memset_orig) |
| @@ -9,8 +9,7 @@ · 8 unmodified lines | ||
| 9 | 9 | |
| 10 | 10 | |
| 11 | 11 | # KBUILD_CFLAGS used when building rest of boot (takes effect recursively) |
| 12 | −KBUILD_CFLAGS += -fno-builtin -Iarch/$(ARCH)/boot/include | |
| 13 | −HOSTFLAGS += -Iarch/$(ARCH)/boot/include | |
| 12 | +KBUILD_CFLAGS += -fno-builtin | |
| 14 | 13 | |
| 15 | 14 | subdir-y := lib |
| 16 | 15 | targets += vmlinux.bin vmlinux.bin.gz |
| @@ -4,13 +4,14 @@ · 3 unmodified lines | ||
| 4 | 4 | /* bits taken from ppc */ |
| 5 | 5 | |
| 6 | 6 | extern void *avail_ram, *end_avail; |
| 7 | +void gunzip(void *dst, int dstlen, unsigned char *src, int *lenp); | |
| 7 | 8 | |
| 8 | −void exit (void) | |
| 9 | +static void exit(void) | |
| 9 | 10 | { |
| 10 | 11 | for (;;); |
| 11 | 12 | } |
| 12 | 13 | |
| 13 | −void *zalloc(unsigned size) | |
| 14 | +static void *zalloc(unsigned int size) | |
| 14 | 15 | { |
| 15 | 16 | void *p = avail_ram; |
| 16 | 17 | |
| @@ -6,6 +6,10 @@ · 5 unmodified lines | ||
| 6 | 6 | |
| 7 | 7 | #include <variant/core.h> |
| 8 | 8 | |
| 9 | +#ifndef XCHAL_HAVE_DIV32 | |
| 10 | +#define XCHAL_HAVE_DIV32 0 | |
| 11 | +#endif | |
| 12 | + | |
| 9 | 13 | #ifndef XCHAL_HAVE_EXCLUSIVE |
| 10 | 14 | #define XCHAL_HAVE_EXCLUSIVE 0 |
| 11 | 15 | #endif |
| @@ -48,6 +48,7 @@ void arch_uninstall_hw_breakpoint(struct perf_event *bp); · 47 unmodified lines | ||
| 48 | 48 | void hw_breakpoint_pmu_read(struct perf_event *bp); |
| 49 | 49 | int check_hw_breakpoint(struct pt_regs *regs); |
| 50 | 50 | void clear_ptrace_hw_breakpoint(struct task_struct *tsk); |
| 51 | +void restore_dbreak(void); | |
| 51 | 52 | |
| 52 | 53 | #else |
| 53 | 54 | |
| @@ -14,6 +14,8 @@ · 13 unmodified lines | ||
| 14 | 14 | |
| 15 | 15 | #include <linux/compiler.h> |
| 16 | 16 | #include <linux/stringify.h> |
| 17 | + | |
| 18 | +#include <asm/bootparam.h> | |
| 17 | 19 | #include <asm/ptrace.h> |
| 18 | 20 | #include <asm/types.h> |
| 19 | 21 | #include <asm/regs.h> |
| @@ -217,6 +219,9 @@ struct mm_struct; · 197 unmodified lines | ||
| 217 | 219 | |
| 218 | 220 | extern unsigned long __get_wchan(struct task_struct *p); |
| 219 | 221 | |
| 222 | +void init_arch(bp_tag_t *bp_start); | |
| 223 | +void do_notify_resume(struct pt_regs *regs); | |
| 224 | + | |
| 220 | 225 | #define KSTK_EIP(tsk) (task_pt_regs(tsk)->pc) |
| 221 | 226 | #define KSTK_ESP(tsk) (task_pt_regs(tsk)->areg[1]) |
| 222 | 227 | |
| @@ -106,6 +106,9 @@ static inline unsigned long regs_return_value(struct pt_regs *regs) · 105 unmodified lines | ||
| 106 | 106 | return regs->areg[2]; |
| 107 | 107 | } |
| 108 | 108 | |
| 109 | +int do_syscall_trace_enter(struct pt_regs *regs); | |
| 110 | +void do_syscall_trace_leave(struct pt_regs *regs); | |
| 111 | + | |
| 109 | 112 | #else /* __ASSEMBLY__ */ |
| 110 | 113 | |
| 111 | 114 | # include <asm/asm-offsets.h> |
| @@ -23,6 +23,7 @@ struct cpumask; · 22 unmodified lines | ||
| 23 | 23 | void arch_send_call_function_ipi_mask(const struct cpumask *mask); |
| 24 | 24 | void arch_send_call_function_single_ipi(int cpu); |
| 25 | 25 | |
| 26 | +void secondary_start_kernel(void); | |
| 26 | 27 | void smp_init_cpus(void); |
| 27 | 28 | void secondary_init_irq(void); |
| 28 | 29 | void ipi_init(void); |
| @@ -18,4 +18,6 @@ · 17 unmodified lines | ||
| 18 | 18 | |
| 19 | 19 | #define __pte_free_tlb(tlb, pte, address) pte_free((tlb)->mm, pte) |
| 20 | 20 | |
| 21 | +void check_tlb_sanity(void); | |
| 22 | + | |
| 21 | 23 | #endif /* _XTENSA_TLB_H */ |
| @@ -13,6 +13,7 @@ · 12 unmodified lines | ||
| 13 | 13 | #include <linux/percpu.h> |
| 14 | 14 | #include <linux/perf_event.h> |
| 15 | 15 | #include <asm/core.h> |
| 16 | +#include <asm/hw_breakpoint.h> | |
| 16 | 17 | |
| 17 | 18 | /* Breakpoint currently in use for each IBREAKA. */ |
| 18 | 19 | static DEFINE_PER_CPU(struct perf_event *, bp_on_reg[XCHAL_NUM_IBREAK]); |
| @@ -28,6 +28,7 @@ · 27 unmodified lines | ||
| 28 | 28 | #include <asm/mxregs.h> |
| 29 | 29 | #include <linux/uaccess.h> |
| 30 | 30 | #include <asm/platform.h> |
| 31 | +#include <asm/traps.h> | |
| 31 | 32 | |
| 32 | 33 | DECLARE_PER_CPU(unsigned long, nmi_count); |
| 33 | 34 | |
| @@ -541,7 +541,6 @@ long arch_ptrace(struct task_struct *child, long request, · 540 unmodified lines | ||
| 541 | 541 | return ret; |
| 542 | 542 | } |
| 543 | 543 | |
| 544 | −void do_syscall_trace_leave(struct pt_regs *regs); | |
| 545 | 544 | int do_syscall_trace_enter(struct pt_regs *regs) |
| 546 | 545 | { |
| 547 | 546 | if (regs->syscall == NO_SYSCALL) |
| @@ -26,6 +26,8 @@ · 25 unmodified lines | ||
| 26 | 26 | #include <linux/uaccess.h> |
| 27 | 27 | #include <asm/cacheflush.h> |
| 28 | 28 | #include <asm/coprocessor.h> |
| 29 | +#include <asm/processor.h> | |
| 30 | +#include <asm/syscall.h> | |
| 29 | 31 | #include <asm/unistd.h> |
| 30 | 32 | |
| 31 | 33 | extern struct task_struct *coproc_owners[]; |
| @@ -21,6 +21,7 @@ · 20 unmodified lines | ||
| 21 | 21 | #include <linux/irq.h> |
| 22 | 22 | #include <linux/kdebug.h> |
| 23 | 23 | #include <linux/module.h> |
| 24 | +#include <linux/profile.h> | |
| 24 | 25 | #include <linux/sched/mm.h> |
| 25 | 26 | #include <linux/sched/hotplug.h> |
| 26 | 27 | #include <linux/sched/task_stack.h> |
| @@ -12,6 +12,7 @@ · 11 unmodified lines | ||
| 12 | 12 | #include <linux/sched.h> |
| 13 | 13 | #include <linux/stacktrace.h> |
| 14 | 14 | |
| 15 | +#include <asm/ftrace.h> | |
| 15 | 16 | #include <asm/stacktrace.h> |
| 16 | 17 | #include <asm/traps.h> |
| 17 | 18 | #include <linux/uaccess.h> |
| @@ -23,6 +23,7 @@ · 22 unmodified lines | ||
| 23 | 23 | * for more details. |
| 24 | 24 | */ |
| 25 | 25 | |
| 26 | +#include <linux/cpu.h> | |
| 26 | 27 | #include <linux/kernel.h> |
| 27 | 28 | #include <linux/sched/signal.h> |
| 28 | 29 | #include <linux/sched/debug.h> |
| @@ -3,7 +3,9 @@ · 2 unmodified lines | ||
| 3 | 3 | #include <asm/asmmacro.h> |
| 4 | 4 | #include <asm/core.h> |
| 5 | 5 | |
| 6 | −#if !XCHAL_HAVE_MUL16 && !XCHAL_HAVE_MUL32 && !XCHAL_HAVE_MAC16 | |
| 6 | +#if XCHAL_HAVE_MUL16 || XCHAL_HAVE_MUL32 || XCHAL_HAVE_MAC16 | |
| 7 | +#define XCHAL_NO_MUL 0 | |
| 8 | +#else | |
| 7 | 9 | #define XCHAL_NO_MUL 1 |
| 8 | 10 | #endif |
| 9 | 11 | |
| @@ -20,6 +20,7 @@ · 19 unmodified lines | ||
| 20 | 20 | #include <asm/mmu_context.h> |
| 21 | 21 | #include <asm/cacheflush.h> |
| 22 | 22 | #include <asm/hardirq.h> |
| 23 | +#include <asm/traps.h> | |
| 23 | 24 | |
| 24 | 25 | void bad_page_fault(struct pt_regs*, unsigned long, int); |
| 25 | 26 | |
| @@ -17,6 +17,7 @@ · 16 unmodified lines | ||
| 17 | 17 | #include <linux/mm.h> |
| 18 | 18 | #include <asm/processor.h> |
| 19 | 19 | #include <asm/mmu_context.h> |
| 20 | +#include <asm/tlb.h> | |
| 20 | 21 | #include <asm/tlbflush.h> |
| 21 | 22 | #include <asm/cacheflush.h> |
| 22 | 23 | |
| @@ -201,7 +201,7 @@ static int tuntap_write(struct iss_net_private *lp, struct sk_buff **skb) · 200 unmodified lines | ||
| 201 | 201 | return simc_write(lp->tp.info.tuntap.fd, (*skb)->data, (*skb)->len); |
| 202 | 202 | } |
| 203 | 203 | |
| 204 | −unsigned short tuntap_protocol(struct sk_buff *skb) | |
| 204 | +static unsigned short tuntap_protocol(struct sk_buff *skb) | |
| 205 | 205 | { |
| 206 | 206 | return eth_type_trans(skb, skb->dev); |
| 207 | 207 | } |
| @@ -441,7 +441,7 @@ static int iss_net_change_mtu(struct net_device *dev, int new_mtu) · 233 unmodified lines | ||
| 441 | 441 | return -EINVAL; |
| 442 | 442 | } |
| 443 | 443 | |
| 444 | −void iss_net_user_timer_expire(struct timer_list *unused) | |
| 444 | +static void iss_net_user_timer_expire(struct timer_list *unused) | |
| 445 | 445 | { |
| 446 | 446 | } |
| 447 | 447 | |
| @@ -270,7 +270,7 @@ void rq_qos_wait(struct rq_wait *rqw, void *private_data, · 269 unmodified lines | ||
| 270 | 270 | finish_wait(&rqw->wait, &data.wq); |
| 271 | 271 | |
| 272 | 272 | /* |
| 273 | − * We raced with wbt_wake_function() getting a token, | |
| 273 | + * We raced with rq_qos_wake_function() getting a token, | |
| 274 | 274 | * which means we now have two. Put our local token |
| 275 | 275 | * and wake anyone else potentially waiting for one. |
| 276 | 276 | */ |
| @@ -290,7 +290,6 @@ EXPORT_SYMBOL(disk_check_media_change); · 289 unmodified lines | ||
| 290 | 290 | /** |
| 291 | 291 | * disk_force_media_change - force a media change event |
| 292 | 292 | * @disk: the disk which will raise the event |
| 293 | − * @events: the events to raise | |
| 294 | 293 | * |
| 295 | 294 | * Should be called when the media changes for @disk. Generates a uevent |
| 296 | 295 | * and attempts to free all dentries and inodes and invalidates all block |
| @@ -278,10 +278,14 @@ int sm2_compute_z_digest(struct shash_desc *desc, · 277 unmodified lines | ||
| 278 | 278 | if (!ec) |
| 279 | 279 | return -ENOMEM; |
| 280 | 280 | |
| 281 | − err = __sm2_set_pub_key(ec, key, keylen); | |
| 281 | + err = sm2_ec_ctx_init(ec); | |
| 282 | 282 | if (err) |
| 283 | 283 | goto out_free_ec; |
| 284 | 284 | |
| 285 | + err = __sm2_set_pub_key(ec, key, keylen); | |
| 286 | + if (err) | |
| 287 | + goto out_deinit_ec; | |
| 288 | + | |
| 285 | 289 | bits_len = SM2_DEFAULT_USERID_LEN * 8; |
| 286 | 290 | entl[0] = bits_len >> 8; |
| 287 | 291 | entl[1] = bits_len & 0xff; |
| @@ -327,7 +327,7 @@ static int ivpu_wait_for_ready(struct ivpu_device *vdev) · 326 unmodified lines | ||
| 327 | 327 | } |
| 328 | 328 | |
| 329 | 329 | if (!ret) |
| 330 | − ivpu_info(vdev, "VPU ready message received successfully\n"); | |
| 330 | + ivpu_dbg(vdev, PM, "VPU ready message received successfully\n"); | |
| 331 | 331 | else |
| 332 | 332 | ivpu_hw_diagnose_failure(vdev); |
| 333 | 333 | |
| @@ -634,6 +634,7 @@ static void ivpu_dev_fini(struct ivpu_device *vdev) · 300 unmodified lines | ||
| 634 | 634 | |
| 635 | 635 | static struct pci_device_id ivpu_pci_ids[] = { |
| 636 | 636 | { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_MTL) }, |
| 637 | + { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_ARL) }, | |
| 637 | 638 | { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_LNL) }, |
| 638 | 639 | { } |
| 639 | 640 | }; |
| @@ -23,6 +23,7 @@ · 22 unmodified lines | ||
| 23 | 23 | #define DRIVER_DATE "20230117" |
| 24 | 24 | |
| 25 | 25 | #define PCI_DEVICE_ID_MTL 0x7d1d |
| 26 | +#define PCI_DEVICE_ID_ARL 0xad1d | |
| 26 | 27 | #define PCI_DEVICE_ID_LNL 0x643e |
| 27 | 28 | |
| 28 | 29 | #define IVPU_HW_37XX 37 |
| @@ -165,6 +166,7 @@ static inline int ivpu_hw_gen(struct ivpu_device *vdev) · 136 unmodified lines | ||
| 165 | 166 | { |
| 166 | 167 | switch (ivpu_device_id(vdev)) { |
| 167 | 168 | case PCI_DEVICE_ID_MTL: |
| 169 | + case PCI_DEVICE_ID_ARL: | |
| 168 | 170 | return IVPU_HW_37XX; |
| 169 | 171 | case PCI_DEVICE_ID_LNL: |
| 170 | 172 | return IVPU_HW_40XX; |
| @@ -220,7 +220,8 @@ static int ivpu_fw_mem_init(struct ivpu_device *vdev) · 219 unmodified lines | ||
| 220 | 220 | if (ret) |
| 221 | 221 | return ret; |
| 222 | 222 | |
| 223 | − fw->mem = ivpu_bo_alloc_internal(vdev, fw->runtime_addr, fw->runtime_size, DRM_IVPU_BO_WC); | |
| 223 | + fw->mem = ivpu_bo_alloc_internal(vdev, fw->runtime_addr, fw->runtime_size, | |
| 224 | + DRM_IVPU_BO_CACHED | DRM_IVPU_BO_NOSNOOP); | |
| 224 | 225 | if (!fw->mem) { |
| 225 | 226 | ivpu_err(vdev, "Failed to allocate firmware runtime memory\n"); |
| 226 | 227 | return -ENOMEM; |
| @@ -330,7 +331,7 @@ int ivpu_fw_load(struct ivpu_device *vdev) · 103 unmodified lines | ||
| 330 | 331 | memset(start, 0, size); |
| 331 | 332 | } |
| 332 | 333 | |
| 333 | − wmb(); /* Flush WC buffers after writing fw->mem */ | |
| 334 | + clflush_cache_range(fw->mem->kvaddr, fw->mem->base.size); | |
| 334 | 335 | |
| 335 | 336 | return 0; |
| 336 | 337 | } |
| @@ -432,6 +433,7 @@ void ivpu_fw_boot_params_setup(struct ivpu_device *vdev, struct vpu_boot_params · 95 unmodified lines | ||
| 432 | 433 | if (!ivpu_fw_is_cold_boot(vdev)) { |
| 433 | 434 | boot_params->save_restore_ret_address = 0; |
| 434 | 435 | vdev->pm->is_warmboot = true; |
| 436 | + clflush_cache_range(vdev->fw->mem->kvaddr, SZ_4K); | |
| 435 | 437 | return; |
| 436 | 438 | } |
| 437 | 439 | |
| @@ -493,7 +495,7 @@ void ivpu_fw_boot_params_setup(struct ivpu_device *vdev, struct vpu_boot_params · 55 unmodified lines | ||
| 493 | 495 | boot_params->punit_telemetry_sram_size = ivpu_hw_reg_telemetry_size_get(vdev); |
| 494 | 496 | boot_params->vpu_telemetry_enable = ivpu_hw_reg_telemetry_enable_get(vdev); |
| 495 | 497 | |
| 496 | − wmb(); /* Flush WC buffers after writing bootparams */ | |
| 498 | + clflush_cache_range(vdev->fw->mem->kvaddr, SZ_4K); | |
| 497 | 499 | |
| 498 | 500 | ivpu_fw_boot_params_print(vdev, boot_params); |
| 499 | 501 | } |
| @@ -8,6 +8,8 @@ · 7 unmodified lines | ||
| 8 | 8 | #include <drm/drm_gem.h> |
| 9 | 9 | #include <drm/drm_mm.h> |
| 10 | 10 | |
| 11 | +#define DRM_IVPU_BO_NOSNOOP 0x10000000 | |
| 12 | + | |
| 11 | 13 | struct dma_buf; |
| 12 | 14 | struct ivpu_bo_ops; |
| 13 | 15 | struct ivpu_file_priv; |
| @@ -83,6 +85,9 @@ static inline u32 ivpu_bo_cache_mode(struct ivpu_bo *bo) · 69 unmodified lines | ||
| 83 | 85 | |
| 84 | 86 | static inline bool ivpu_bo_is_snooped(struct ivpu_bo *bo) |
| 85 | 87 | { |
| 88 | + if (bo->flags & DRM_IVPU_BO_NOSNOOP) | |
| 89 | + return false; | |
| 90 | + | |
| 86 | 91 | return ivpu_bo_cache_mode(bo) == DRM_IVPU_BO_CACHED; |
| 87 | 92 | } |
| 88 | 93 | |
| @@ -57,8 +57,7 @@ · 56 unmodified lines | ||
| 57 | 57 | |
| 58 | 58 | #define ICB_0_1_IRQ_MASK ((((u64)ICB_1_IRQ_MASK) << 32) | ICB_0_IRQ_MASK) |
| 59 | 59 | |
| 60 | −#define BUTTRESS_IRQ_MASK ((REG_FLD(VPU_40XX_BUTTRESS_INTERRUPT_STAT, FREQ_CHANGE)) | \ | |
| 61 | − (REG_FLD(VPU_40XX_BUTTRESS_INTERRUPT_STAT, ATS_ERR)) | \ | |
| 60 | +#define BUTTRESS_IRQ_MASK ((REG_FLD(VPU_40XX_BUTTRESS_INTERRUPT_STAT, ATS_ERR)) | \ | |
| 62 | 61 | (REG_FLD(VPU_40XX_BUTTRESS_INTERRUPT_STAT, CFI0_ERR)) | \ |
| 63 | 62 | (REG_FLD(VPU_40XX_BUTTRESS_INTERRUPT_STAT, CFI1_ERR)) | \ |
| 64 | 63 | (REG_FLD(VPU_40XX_BUTTRESS_INTERRUPT_STAT, IMR0_ERR)) | \ |
| @@ -196,6 +195,14 @@ static int ivpu_pll_wait_for_status_ready(struct ivpu_device *vdev) · 131 unmodified lines | ||
| 196 | 195 | return REGB_POLL_FLD(VPU_40XX_BUTTRESS_VPU_STATUS, READY, 1, PLL_TIMEOUT_US); |
| 197 | 196 | } |
| 198 | 197 | |
| 198 | +static int ivpu_wait_for_clock_own_resource_ack(struct ivpu_device *vdev) | |
| 199 | +{ | |
| 200 | + if (ivpu_is_simics(vdev)) | |
| 201 | + return 0; | |
| 202 | + | |
| 203 | + return REGB_POLL_FLD(VPU_40XX_BUTTRESS_VPU_STATUS, CLOCK_RESOURCE_OWN_ACK, 1, TIMEOUT_US); | |
| 204 | +} | |
| 205 | + | |
| 199 | 206 | static void ivpu_pll_init_frequency_ratios(struct ivpu_device *vdev) |
| 200 | 207 | { |
| 201 | 208 | struct ivpu_hw_info *hw = vdev->hw; |
| @@ -556,6 +563,12 @@ static int ivpu_boot_pwr_domain_enable(struct ivpu_device *vdev) · 354 unmodified lines | ||
| 556 | 563 | { |
| 557 | 564 | int ret; |
| 558 | 565 | |
| 566 | + ret = ivpu_wait_for_clock_own_resource_ack(vdev); | |
| 567 | + if (ret) { | |
| 568 | + ivpu_err(vdev, "Timed out waiting for clock own resource ACK\n"); | |
| 569 | + return ret; | |
| 570 | + } | |
| 571 | + | |
| 559 | 572 | ivpu_boot_pwr_island_trickle_drive(vdev, true); |
| 560 | 573 | ivpu_boot_pwr_island_drive(vdev, true); |
| 561 | 574 | |
| @@ -1046,8 +1059,6 @@ static irqreturn_t ivpu_hw_40xx_irqb_handler(struct ivpu_device *vdev, int irq) · 484 unmodified lines | ||
| 1046 | 1059 | if (status == 0) |
| 1047 | 1060 | return IRQ_NONE; |
| 1048 | 1061 | |
| 1049 | − REGB_WR32(VPU_40XX_BUTTRESS_INTERRUPT_STAT, status); | |
| 1050 | − | |
| 1051 | 1062 | if (REG_TEST_FLD(VPU_40XX_BUTTRESS_INTERRUPT_STAT, FREQ_CHANGE, status)) |
| 1052 | 1063 | ivpu_dbg(vdev, IRQ, "FREQ_CHANGE"); |
| 1053 | 1064 | |
| @@ -1092,6 +1103,9 @@ static irqreturn_t ivpu_hw_40xx_irqb_handler(struct ivpu_device *vdev, int irq) · 38 unmodified lines | ||
| 1092 | 1103 | schedule_recovery = true; |
| 1093 | 1104 | } |
| 1094 | 1105 | |
| 1106 | + /* This must be done after interrupts are cleared at the source. */ | |
| 1107 | + REGB_WR32(VPU_40XX_BUTTRESS_INTERRUPT_STAT, status); | |
| 1108 | + | |
| 1095 | 1109 | if (schedule_recovery) |
| 1096 | 1110 | ivpu_pm_schedule_recovery(vdev); |
| 1097 | 1111 | |
| @@ -1103,9 +1117,14 @@ static irqreturn_t ivpu_hw_40xx_irq_handler(int irq, void *ptr) · 5 unmodified lines | ||
| 1103 | 1117 | struct ivpu_device *vdev = ptr; |
| 1104 | 1118 | irqreturn_t ret = IRQ_NONE; |
| 1105 | 1119 | |
| 1120 | + REGB_WR32(VPU_40XX_BUTTRESS_GLOBAL_INT_MASK, 0x1); | |
| 1121 | + | |
| 1106 | 1122 | ret |= ivpu_hw_40xx_irqv_handler(vdev, irq); |
| 1107 | 1123 | ret |= ivpu_hw_40xx_irqb_handler(vdev, irq); |
| 1108 | 1124 | |
| 1125 | + /* Re-enable global interrupts to re-trigger MSI for pending interrupts */ | |
| 1126 | + REGB_WR32(VPU_40XX_BUTTRESS_GLOBAL_INT_MASK, 0x0); | |
| 1127 | + | |
| 1109 | 1128 | if (ret & IRQ_WAKE_THREAD) |
| 1110 | 1129 | return IRQ_WAKE_THREAD; |
| 1111 | 1130 | |
| @@ -70,6 +70,8 @@ · 69 unmodified lines | ||
| 70 | 70 | #define VPU_40XX_BUTTRESS_VPU_STATUS_READY_MASK BIT_MASK(0) |
| 71 | 71 | #define VPU_40XX_BUTTRESS_VPU_STATUS_IDLE_MASK BIT_MASK(1) |
| 72 | 72 | #define VPU_40XX_BUTTRESS_VPU_STATUS_DUP_IDLE_MASK BIT_MASK(2) |
| 73 | +#define VPU_40XX_BUTTRESS_VPU_STATUS_CLOCK_RESOURCE_OWN_ACK_MASK BIT_MASK(6) | |
| 74 | +#define VPU_40XX_BUTTRESS_VPU_STATUS_POWER_RESOURCE_OWN_ACK_MASK BIT_MASK(7) | |
| 73 | 75 | #define VPU_40XX_BUTTRESS_VPU_STATUS_PERF_CLK_MASK BIT_MASK(11) |
| 74 | 76 | #define VPU_40XX_BUTTRESS_VPU_STATUS_DISABLE_CLK_RELINQUISH_MASK BIT_MASK(12) |
| 75 | 77 | |
| @@ -209,10 +209,10 @@ int ivpu_ipc_receive(struct ivpu_device *vdev, struct ivpu_ipc_consumer *cons, · 208 unmodified lines | ||
| 209 | 209 | struct ivpu_ipc_rx_msg *rx_msg; |
| 210 | 210 | int wait_ret, ret = 0; |
| 211 | 211 | |
| 212 | − wait_ret = wait_event_interruptible_timeout(cons->rx_msg_wq, | |
| 213 | − (IS_KTHREAD() && kthread_should_stop()) || | |
| 214 | − !list_empty(&cons->rx_msg_list), | |
| 215 | − msecs_to_jiffies(timeout_ms)); | |
| 212 | + wait_ret = wait_event_timeout(cons->rx_msg_wq, | |
| 213 | + (IS_KTHREAD() && kthread_should_stop()) || | |
| 214 | + !list_empty(&cons->rx_msg_list), | |
| 215 | + msecs_to_jiffies(timeout_ms)); | |
| 216 | 216 | |
| 217 | 217 | if (IS_KTHREAD() && kthread_should_stop()) |
| 218 | 218 | return -EINTR; |
| @@ -220,9 +220,6 @@ int ivpu_ipc_receive(struct ivpu_device *vdev, struct ivpu_ipc_consumer *cons, · 1 unmodified line | ||
| 220 | 220 | if (wait_ret == 0) |
| 221 | 221 | return -ETIMEDOUT; |
| 222 | 222 | |
| 223 | − if (wait_ret < 0) | |
| 224 | − return -ERESTARTSYS; | |
| 225 | − | |
| 226 | 223 | spin_lock_irq(&cons->rx_msg_lock); |
| 227 | 224 | rx_msg = list_first_entry_or_null(&cons->rx_msg_list, struct ivpu_ipc_rx_msg, link); |
| 228 | 225 | if (!rx_msg) { |
| @@ -2057,7 +2057,9 @@ static int acpi_video_bus_add(struct acpi_device *device) · 2056 unmodified lines | ||
| 2057 | 2057 | !auto_detect) |
| 2058 | 2058 | acpi_video_bus_register_backlight(video); |
| 2059 | 2059 | |
| 2060 | − acpi_video_bus_add_notify_handler(video); | |
| 2060 | + error = acpi_video_bus_add_notify_handler(video); | |
| 2061 | + if (error) | |
| 2062 | + goto err_del; | |
| 2061 | 2063 | |
| 2062 | 2064 | error = acpi_dev_install_notify_handler(device, ACPI_DEVICE_NOTIFY, |
| 2063 | 2065 | acpi_video_bus_notify); |
| @@ -2067,10 +2069,11 @@ static int acpi_video_bus_add(struct acpi_device *device) · 3 unmodified lines | ||
| 2067 | 2069 | return 0; |
| 2068 | 2070 | |
| 2069 | 2071 | err_remove: |
| 2072 | + acpi_video_bus_remove_notify_handler(video); | |
| 2073 | +err_del: | |
| 2070 | 2074 | mutex_lock(&video_list_lock); |
| 2071 | 2075 | list_del(&video->entry); |
| 2072 | 2076 | mutex_unlock(&video_list_lock); |
| 2073 | − acpi_video_bus_remove_notify_handler(video); | |
| 2074 | 2077 | acpi_video_bus_unregister_backlight(video); |
| 2075 | 2078 | err_put_video: |
| 2076 | 2079 | acpi_video_bus_put_devices(video); |
| @@ -855,7 +855,7 @@ static size_t sizeof_idt(struct acpi_nfit_interleave *idt) · 854 unmodified lines | ||
| 855 | 855 | { |
| 856 | 856 | if (idt->header.length < sizeof(*idt)) |
| 857 | 857 | return 0; |
| 858 | − return sizeof(*idt) + sizeof(u32) * (idt->line_count - 1); | |
| 858 | + return sizeof(*idt) + sizeof(u32) * idt->line_count; | |
| 859 | 859 | } |
| 860 | 860 | |
| 861 | 861 | static bool add_idt(struct acpi_nfit_desc *acpi_desc, |
| @@ -19,6 +19,7 @@ static void acpi_set_pdc_bits(u32 *buf) · 18 unmodified lines | ||
| 19 | 19 | { |
| 20 | 20 | buf[0] = ACPI_PDC_REVISION_ID; |
| 21 | 21 | buf[1] = 1; |
| 22 | + buf[2] = 0; | |
| 22 | 23 | |
| 23 | 24 | /* Twiddle arch-specific bits needed for _PDC */ |
| 24 | 25 | arch_acpi_set_proc_cap_bits(&buf[2]); |
| @@ -1972,6 +1972,96 @@ retry: · 1971 unmodified lines | ||
| 1972 | 1972 | return rc; |
| 1973 | 1973 | } |
| 1974 | 1974 | |
| 1975 | +/** | |
| 1976 | + * ata_dev_power_set_standby - Set a device power mode to standby | |
| 1977 | + * @dev: target device | |
| 1978 | + * | |
| 1979 | + * Issue a STANDBY IMMEDIATE command to set a device power mode to standby. | |
| 1980 | + * For an HDD device, this spins down the disks. | |
| 1981 | + * | |
| 1982 | + * LOCKING: | |
| 1983 | + * Kernel thread context (may sleep). | |
| 1984 | + */ | |
| 1985 | +void ata_dev_power_set_standby(struct ata_device *dev) | |
| 1986 | +{ | |
| 1987 | + unsigned long ap_flags = dev->link->ap->flags; | |
| 1988 | + struct ata_taskfile tf; | |
| 1989 | + unsigned int err_mask; | |
| 1990 | + | |
| 1991 | + /* Issue STANDBY IMMEDIATE command only if supported by the device */ | |
| 1992 | + if (dev->class != ATA_DEV_ATA && dev->class != ATA_DEV_ZAC) | |
| 1993 | + return; | |
| 1994 | + | |
| 1995 | + /* | |
| 1996 | + * Some odd clown BIOSes issue spindown on power off (ACPI S4 or S5) | |
| 1997 | + * causing some drives to spin up and down again. For these, do nothing | |
| 1998 | + * if we are being called on shutdown. | |
| 1999 | + */ | |
| 2000 | + if ((ap_flags & ATA_FLAG_NO_POWEROFF_SPINDOWN) && | |
| 2001 | + system_state == SYSTEM_POWER_OFF) | |
| 2002 | + return; | |
| 2003 | + | |
| 2004 | + if ((ap_flags & ATA_FLAG_NO_HIBERNATE_SPINDOWN) && | |
| 2005 | + system_entering_hibernation()) | |
| 2006 | + return; | |
| 2007 | + | |
| 2008 | + ata_tf_init(dev, &tf); | |
| 2009 | + tf.flags |= ATA_TFLAG_DEVICE | ATA_TFLAG_ISADDR; | |
| 2010 | + tf.protocol = ATA_PROT_NODATA; | |
| 2011 | + tf.command = ATA_CMD_STANDBYNOW1; | |
| 2012 | + | |
| 2013 | + ata_dev_notice(dev, "Entering standby power mode\n"); | |
| 2014 | + | |
| 2015 | + err_mask = ata_exec_internal(dev, &tf, NULL, DMA_NONE, NULL, 0, 0); | |
| 2016 | + if (err_mask) | |
| 2017 | + ata_dev_err(dev, "STANDBY IMMEDIATE failed (err_mask=0x%x)\n", | |
| 2018 | + err_mask); | |
| 2019 | +} | |
| 2020 | + | |
| 2021 | +/** | |
| 2022 | + * ata_dev_power_set_active - Set a device power mode to active | |
| 2023 | + * @dev: target device | |
| 2024 | + * | |
| 2025 | + * Issue a VERIFY command to enter to ensure that the device is in the | |
| 2026 | + * active power mode. For a spun-down HDD (standby or idle power mode), | |
| 2027 | + * the VERIFY command will complete after the disk spins up. | |
| 2028 | + * | |
| 2029 | + * LOCKING: | |
| 2030 | + * Kernel thread context (may sleep). | |
| 2031 | + */ | |
| 2032 | +void ata_dev_power_set_active(struct ata_device *dev) | |
| 2033 | +{ | |
| 2034 | + struct ata_taskfile tf; | |
| 2035 | + unsigned int err_mask; | |
| 2036 | + | |
| 2037 | + /* | |
| 2038 | + * Issue READ VERIFY SECTORS command for 1 sector at lba=0 only | |
| 2039 | + * if supported by the device. | |
| 2040 | + */ | |
| 2041 | + if (dev->class != ATA_DEV_ATA && dev->class != ATA_DEV_ZAC) | |
| 2042 | + return; | |
| 2043 | + | |
| 2044 | + ata_tf_init(dev, &tf); | |
| 2045 | + tf.flags |= ATA_TFLAG_DEVICE | ATA_TFLAG_ISADDR; | |
| 2046 | + tf.protocol = ATA_PROT_NODATA; | |
| 2047 | + tf.command = ATA_CMD_VERIFY; | |
| 2048 | + tf.nsect = 1; | |
| 2049 | + if (dev->flags & ATA_DFLAG_LBA) { | |
| 2050 | + tf.flags |= ATA_TFLAG_LBA; | |
| 2051 | + tf.device |= ATA_LBA; | |
| 2052 | + } else { | |
| 2053 | + /* CHS */ | |
| 2054 | + tf.lbal = 0x1; /* sect */ | |
| 2055 | + } | |
| 2056 | + | |
| 2057 | + ata_dev_notice(dev, "Entering active power mode\n"); | |
| 2058 | + | |
| 2059 | + err_mask = ata_exec_internal(dev, &tf, NULL, DMA_NONE, NULL, 0, 0); | |
| 2060 | + if (err_mask) | |
| 2061 | + ata_dev_err(dev, "VERIFY failed (err_mask=0x%x)\n", | |
| 2062 | + err_mask); | |
| 2063 | +} | |
| 2064 | + | |
| 1975 | 2065 | /** |
| 1976 | 2066 | * ata_read_log_page - read a specific log page |
| 1977 | 2067 | * @dev: target device |
| @@ -2529,7 +2619,7 @@ static int ata_dev_config_lba(struct ata_device *dev) · 551 unmodified lines | ||
| 2529 | 2619 | { |
| 2530 | 2620 | const u16 *id = dev->id; |
| 2531 | 2621 | const char *lba_desc; |
| 2532 | − char ncq_desc[24]; | |
| 2622 | + char ncq_desc[32]; | |
| 2533 | 2623 | int ret; |
| 2534 | 2624 | |
| 2535 | 2625 | dev->flags |= ATA_DFLAG_LBA; |
| @@ -5037,17 +5127,19 @@ static void ata_port_request_pm(struct ata_port *ap, pm_message_t mesg, · 2501 unmodified lines | ||
| 5037 | 5127 | struct ata_link *link; |
| 5038 | 5128 | unsigned long flags; |
| 5039 | 5129 | |
| 5040 | − /* Previous resume operation might still be in | |
| 5041 | − * progress. Wait for PM_PENDING to clear. | |
| 5130 | + spin_lock_irqsave(ap->lock, flags); | |
| 5131 | + | |
| 5132 | + /* | |
| 5133 | + * A previous PM operation might still be in progress. Wait for | |
| 5134 | + * ATA_PFLAG_PM_PENDING to clear. | |
| 5042 | 5135 | */ |
| 5043 | 5136 | if (ap->pflags & ATA_PFLAG_PM_PENDING) { |
| 5137 | + spin_unlock_irqrestore(ap->lock, flags); | |
| 5044 | 5138 | ata_port_wait_eh(ap); |
| 5045 | − WARN_ON(ap->pflags & ATA_PFLAG_PM_PENDING); | |
| 5139 | + spin_lock_irqsave(ap->lock, flags); | |
| 5046 | 5140 | } |
| 5047 | 5141 | |
| 5048 | − /* request PM ops to EH */ | |
| 5049 | − spin_lock_irqsave(ap->lock, flags); | |
| 5050 | − | |
| 5142 | + /* Request PM operation to EH */ | |
| 5051 | 5143 | ap->pm_mesg = mesg; |
| 5052 | 5144 | ap->pflags |= ATA_PFLAG_PM_PENDING; |
| 5053 | 5145 | ata_for_each_link(link, ap, HOST_FIRST) { |
| @@ -5059,10 +5151,8 @@ static void ata_port_request_pm(struct ata_port *ap, pm_message_t mesg, · 5 unmodified lines | ||
| 5059 | 5151 | |
| 5060 | 5152 | spin_unlock_irqrestore(ap->lock, flags); |
| 5061 | 5153 | |
| 5062 | − if (!async) { | |
| 5154 | + if (!async) | |
| 5063 | 5155 | ata_port_wait_eh(ap); |
| 5064 | − WARN_ON(ap->pflags & ATA_PFLAG_PM_PENDING); | |
| 5065 | − } | |
| 5066 | 5156 | } |
| 5067 | 5157 | |
| 5068 | 5158 | /* |
| @@ -5078,11 +5168,27 @@ static const unsigned int ata_port_suspend_ehi = ATA_EHI_QUIET · 9 unmodified lines | ||
| 5078 | 5168 | |
| 5079 | 5169 | static void ata_port_suspend(struct ata_port *ap, pm_message_t mesg) |
| 5080 | 5170 | { |
| 5171 | + /* | |
| 5172 | + * We are about to suspend the port, so we do not care about | |
| 5173 | + * scsi_rescan_device() calls scheduled by previous resume operations. | |
| 5174 | + * The next resume will schedule the rescan again. So cancel any rescan | |
| 5175 | + * that is not done yet. | |
| 5176 | + */ | |
| 5177 | + cancel_delayed_work_sync(&ap->scsi_rescan_task); | |
| 5178 | + | |
| 5081 | 5179 | ata_port_request_pm(ap, mesg, 0, ata_port_suspend_ehi, false); |
| 5082 | 5180 | } |
| 5083 | 5181 | |
| 5084 | 5182 | static void ata_port_suspend_async(struct ata_port *ap, pm_message_t mesg) |
| 5085 | 5183 | { |
| 5184 | + /* | |
| 5185 | + * We are about to suspend the port, so we do not care about | |
| 5186 | + * scsi_rescan_device() calls scheduled by previous resume operations. | |
| 5187 | + * The next resume will schedule the rescan again. So cancel any rescan | |
| 5188 | + * that is not done yet. | |
| 5189 | + */ | |
| 5190 | + cancel_delayed_work_sync(&ap->scsi_rescan_task); | |
| 5191 | + | |
| 5086 | 5192 | ata_port_request_pm(ap, mesg, 0, ata_port_suspend_ehi, true); |
| 5087 | 5193 | } |
| 5088 | 5194 | |
| @@ -5229,7 +5335,7 @@ EXPORT_SYMBOL_GPL(ata_host_resume); · 140 unmodified lines | ||
| 5229 | 5335 | #endif |
| 5230 | 5336 | |
| 5231 | 5337 | const struct device_type ata_port_type = { |
| 5232 | − .name = "ata_port", | |
| 5338 | + .name = ATA_PORT_TYPE_NAME, | |
| 5233 | 5339 | #ifdef CONFIG_PM |
| 5234 | 5340 | .pm = &ata_port_pm_ops, |
| 5235 | 5341 | #endif |
| @@ -5948,11 +6054,30 @@ static void ata_port_detach(struct ata_port *ap) · 712 unmodified lines | ||
| 5948 | 6054 | struct ata_link *link; |
| 5949 | 6055 | struct ata_device *dev; |
| 5950 | 6056 | |
| 5951 | − /* tell EH we're leaving & flush EH */ | |
| 6057 | + /* Wait for any ongoing EH */ | |
| 6058 | + ata_port_wait_eh(ap); | |
| 6059 | + | |
| 6060 | + mutex_lock(&ap->scsi_scan_mutex); | |
| 5952 | 6061 | spin_lock_irqsave(ap->lock, flags); |
| 6062 | + | |
| 6063 | + /* Remove scsi devices */ | |
| 6064 | + ata_for_each_link(link, ap, HOST_FIRST) { | |
| 6065 | + ata_for_each_dev(dev, link, ALL) { | |
| 6066 | + if (dev->sdev) { | |
| 6067 | + spin_unlock_irqrestore(ap->lock, flags); | |
| 6068 | + scsi_remove_device(dev->sdev); | |
| 6069 | + spin_lock_irqsave(ap->lock, flags); | |
| 6070 | + dev->sdev = NULL; | |
| 6071 | + } | |
| 6072 | + } | |
| 6073 | + } | |
| 6074 | + | |
| 6075 | + /* Tell EH to disable all devices */ | |
| 5953 | 6076 | ap->pflags |= ATA_PFLAG_UNLOADING; |
| 5954 | 6077 | ata_port_schedule_eh(ap); |
| 6078 | + | |
| 5955 | 6079 | spin_unlock_irqrestore(ap->lock, flags); |
| 6080 | + mutex_unlock(&ap->scsi_scan_mutex); | |
| 5956 | 6081 | |
| 5957 | 6082 | /* wait till EH commits suicide */ |
| 5958 | 6083 | ata_port_wait_eh(ap); |
| @@ -147,6 +147,8 @@ ata_eh_cmd_timeout_table[ATA_EH_CMD_TIMEOUT_TABLE_SIZE] = { · 146 unmodified lines | ||
| 147 | 147 | .timeouts = ata_eh_other_timeouts, }, |
| 148 | 148 | { .commands = CMDS(ATA_CMD_FLUSH, ATA_CMD_FLUSH_EXT), |
| 149 | 149 | .timeouts = ata_eh_flush_timeouts }, |
| 150 | + { .commands = CMDS(ATA_CMD_VERIFY), | |
| 151 | + .timeouts = ata_eh_reset_timeouts }, | |
| 150 | 152 | }; |
| 151 | 153 | #undef CMDS |
| 152 | 154 | |
| @@ -498,7 +500,19 @@ static void ata_eh_unload(struct ata_port *ap) · 345 unmodified lines | ||
| 498 | 500 | struct ata_device *dev; |
| 499 | 501 | unsigned long flags; |
| 500 | 502 | |
| 501 | − /* Restore SControl IPM and SPD for the next driver and | |
| 503 | + /* | |
| 504 | + * Unless we are restarting, transition all enabled devices to | |
| 505 | + * standby power mode. | |
| 506 | + */ | |
| 507 | + if (system_state != SYSTEM_RESTART) { | |
| 508 | + ata_for_each_link(link, ap, PMP_FIRST) { | |
| 509 | + ata_for_each_dev(dev, link, ENABLED) | |
| 510 | + ata_dev_power_set_standby(dev); | |
| 511 | + } | |
| 512 | + } | |
| 513 | + | |
| 514 | + /* | |
| 515 | + * Restore SControl IPM and SPD for the next driver and | |
| 502 | 516 | * disable attached devices. |
| 503 | 517 | */ |
| 504 | 518 | ata_for_each_link(link, ap, PMP_FIRST) { |
| @@ -684,6 +698,10 @@ void ata_scsi_port_error_handler(struct Scsi_Host *host, struct ata_port *ap) · 179 unmodified lines | ||
| 684 | 698 | ehc->saved_xfer_mode[devno] = dev->xfer_mode; |
| 685 | 699 | if (ata_ncq_enabled(dev)) |
| 686 | 700 | ehc->saved_ncq_enabled |= 1 << devno; |
| 701 | + | |
| 702 | + /* If we are resuming, wake up the device */ | |
| 703 | + if (ap->pflags & ATA_PFLAG_RESUMING) | |
| 704 | + ehc->i.dev_action[devno] |= ATA_EH_SET_ACTIVE; | |
| 687 | 705 | } |
| 688 | 706 | } |
| 689 | 707 | |
| @@ -743,6 +761,8 @@ void ata_scsi_port_error_handler(struct Scsi_Host *host, struct ata_port *ap) · 53 unmodified lines | ||
| 743 | 761 | /* clean up */ |
| 744 | 762 | spin_lock_irqsave(ap->lock, flags); |
| 745 | 763 | |
| 764 | + ap->pflags &= ~ATA_PFLAG_RESUMING; | |
| 765 | + | |
| 746 | 766 | if (ap->pflags & ATA_PFLAG_LOADING) |
| 747 | 767 | ap->pflags &= ~ATA_PFLAG_LOADING; |
| 748 | 768 | else if ((ap->pflags & ATA_PFLAG_SCSI_HOTPLUG) && |
| @@ -1218,6 +1238,13 @@ void ata_eh_detach_dev(struct ata_device *dev) · 469 unmodified lines | ||
| 1218 | 1238 | struct ata_eh_context *ehc = &link->eh_context; |
| 1219 | 1239 | unsigned long flags; |
| 1220 | 1240 | |
| 1241 | + /* | |
| 1242 | + * If the device is still enabled, transition it to standby power mode | |
| 1243 | + * (i.e. spin down HDDs). | |
| 1244 | + */ | |
| 1245 | + if (ata_dev_enabled(dev)) | |
| 1246 | + ata_dev_power_set_standby(dev); | |
| 1247 | + | |
| 1221 | 1248 | ata_dev_disable(dev); |
| 1222 | 1249 | |
| 1223 | 1250 | spin_lock_irqsave(ap->lock, flags); |
| @@ -2305,7 +2332,7 @@ static void ata_eh_link_report(struct ata_link *link) · 1081 unmodified lines | ||
| 2305 | 2332 | struct ata_eh_context *ehc = &link->eh_context; |
| 2306 | 2333 | struct ata_queued_cmd *qc; |
| 2307 | 2334 | const char *frozen, *desc; |
| 2308 | − char tries_buf[6] = ""; | |
| 2335 | + char tries_buf[16] = ""; | |
| 2309 | 2336 | int tag, nr_failed = 0; |
| 2310 | 2337 | |
| 2311 | 2338 | if (ehc->i.flags & ATA_EHI_QUIET) |
| @@ -3016,6 +3043,15 @@ static int ata_eh_revalidate_and_attach(struct ata_link *link, · 704 unmodified lines | ||
| 3016 | 3043 | if (ehc->i.flags & ATA_EHI_DID_RESET) |
| 3017 | 3044 | readid_flags |= ATA_READID_POSTRESET; |
| 3018 | 3045 | |
| 3046 | + /* | |
| 3047 | + * When resuming, before executing any command, make sure to | |
| 3048 | + * transition the device to the active power mode. | |
| 3049 | + */ | |
| 3050 | + if ((action & ATA_EH_SET_ACTIVE) && ata_dev_enabled(dev)) { | |
| 3051 | + ata_dev_power_set_active(dev); | |
| 3052 | + ata_eh_done(link, dev, ATA_EH_SET_ACTIVE); | |
| 3053 | + } | |
| 3054 | + | |
| 3019 | 3055 | if ((action & ATA_EH_REVALIDATE) && ata_dev_enabled(dev)) { |
| 3020 | 3056 | WARN_ON(dev->class == ATA_DEV_PMP); |
| 3021 | 3057 | |
| @@ -3989,6 +4025,7 @@ static void ata_eh_handle_port_suspend(struct ata_port *ap) · 967 unmodified lines | ||
| 3989 | 4025 | unsigned long flags; |
| 3990 | 4026 | int rc = 0; |
| 3991 | 4027 | struct ata_device *dev; |
| 4028 | + struct ata_link *link; | |
| 3992 | 4029 | |
| 3993 | 4030 | /* are we suspending? */ |
| 3994 | 4031 | spin_lock_irqsave(ap->lock, flags); |
| @@ -4001,6 +4038,12 @@ static void ata_eh_handle_port_suspend(struct ata_port *ap) · 6 unmodified lines | ||
| 4001 | 4038 | |
| 4002 | 4039 | WARN_ON(ap->pflags & ATA_PFLAG_SUSPENDED); |
| 4003 | 4040 | |
| 4041 | + /* Set all devices attached to the port in standby mode */ | |
| 4042 | + ata_for_each_link(link, ap, HOST_FIRST) { | |
| 4043 | + ata_for_each_dev(dev, link, ENABLED) | |
| 4044 | + ata_dev_power_set_standby(dev); | |
| 4045 | + } | |
| 4046 | + | |
| 4004 | 4047 | /* |
| 4005 | 4048 | * If we have a ZPODD attached, check its zero |
| 4006 | 4049 | * power ready status before the port is frozen. |
| @@ -4083,6 +4126,7 @@ static void ata_eh_handle_port_resume(struct ata_port *ap) · 76 unmodified lines | ||
| 4083 | 4126 | /* update the flags */ |
| 4084 | 4127 | spin_lock_irqsave(ap->lock, flags); |
| 4085 | 4128 | ap->pflags &= ~(ATA_PFLAG_PM_PENDING | ATA_PFLAG_SUSPENDED); |
| 4129 | + ap->pflags |= ATA_PFLAG_RESUMING; | |
| 4086 | 4130 | spin_unlock_irqrestore(ap->lock, flags); |
| 4087 | 4131 | } |
| 4088 | 4132 | #endif /* CONFIG_PM */ |
| @@ -1050,14 +1050,13 @@ int ata_scsi_dev_config(struct scsi_device *sdev, struct ata_device *dev) · 1049 unmodified lines | ||
| 1050 | 1050 | } |
| 1051 | 1051 | } else { |
| 1052 | 1052 | sdev->sector_size = ata_id_logical_sector_size(dev->id); |
| 1053 | + | |
| 1053 | 1054 | /* |
| 1054 | − * Stop the drive on suspend but do not issue START STOP UNIT | |
| 1055 | − * on resume as this is not necessary and may fail: the device | |
| 1056 | − * will be woken up by ata_port_pm_resume() with a port reset | |
| 1057 | − * and device revalidation. | |
| 1055 | + * Ask the sd driver to issue START STOP UNIT on runtime suspend | |
| 1056 | + * and resume only. For system level suspend/resume, devices | |
| 1057 | + * power state is handled directly by libata EH. | |
| 1058 | 1058 | */ |
| 1059 | − sdev->manage_start_stop = 1; | |
| 1060 | − sdev->no_start_on_resume = 1; | |
| 1059 | + sdev->manage_runtime_start_stop = true; | |
| 1061 | 1060 | } |
| 1062 | 1061 | |
| 1063 | 1062 | /* |
| @@ -1089,6 +1088,42 @@ int ata_scsi_dev_config(struct scsi_device *sdev, struct ata_device *dev) · 25 unmodified lines | ||
| 1089 | 1088 | return 0; |
| 1090 | 1089 | } |
| 1091 | 1090 | |
| 1091 | +/** | |
| 1092 | + * ata_scsi_slave_alloc - Early setup of SCSI device | |
| 1093 | + * @sdev: SCSI device to examine | |
| 1094 | + * | |
| 1095 | + * This is called from scsi_alloc_sdev() when the scsi device | |
| 1096 | + * associated with an ATA device is scanned on a port. | |
| 1097 | + * | |
| 1098 | + * LOCKING: | |
| 1099 | + * Defined by SCSI layer. We don't really care. | |
| 1100 | + */ | |
| 1101 | + | |
| 1102 | +int ata_scsi_slave_alloc(struct scsi_device *sdev) | |
| 1103 | +{ | |
| 1104 | + struct ata_port *ap = ata_shost_to_port(sdev->host); | |
| 1105 | + struct device_link *link; | |
| 1106 | + | |
| 1107 | + ata_scsi_sdev_config(sdev); | |
| 1108 | + | |
| 1109 | + /* | |
| 1110 | + * Create a link from the ata_port device to the scsi device to ensure | |
| 1111 | + * that PM does suspend/resume in the correct order: the scsi device is | |
| 1112 | + * consumer (child) and the ata port the supplier (parent). | |
| 1113 | + */ | |
| 1114 | + link = device_link_add(&sdev->sdev_gendev, &ap->tdev, | |
| 1115 | + DL_FLAG_STATELESS | | |
| 1116 | + DL_FLAG_PM_RUNTIME | DL_FLAG_RPM_ACTIVE); | |
| 1117 | + if (!link) { | |
| 1118 | + ata_port_err(ap, "Failed to create link to scsi device %s\n", | |
| 1119 | + dev_name(&sdev->sdev_gendev)); | |
| 1120 | + return -ENODEV; | |
| 1121 | + } | |
| 1122 | + | |
| 1123 | + return 0; | |
| 1124 | +} | |
| 1125 | +EXPORT_SYMBOL_GPL(ata_scsi_slave_alloc); | |
| 1126 | + | |
| 1092 | 1127 | /** |
| 1093 | 1128 | * ata_scsi_slave_config - Set SCSI device attributes |
| 1094 | 1129 | * @sdev: SCSI device to examine |
| @@ -1105,14 +1140,11 @@ int ata_scsi_slave_config(struct scsi_device *sdev) · 10 unmodified lines | ||
| 1105 | 1140 | { |
| 1106 | 1141 | struct ata_port *ap = ata_shost_to_port(sdev->host); |
| 1107 | 1142 | struct ata_device *dev = __ata_scsi_find_dev(ap, sdev); |
| 1108 | − int rc = 0; | |
| 1109 | − | |
| 1110 | − ata_scsi_sdev_config(sdev); | |
| 1111 | 1143 | |
| 1112 | 1144 | if (dev) |
| 1113 | − rc = ata_scsi_dev_config(sdev, dev); | |
| 1145 | + return ata_scsi_dev_config(sdev, dev); | |
| 1114 | 1146 | |
| 1115 | − return rc; | |
| 1147 | + return 0; | |
| 1116 | 1148 | } |
| 1117 | 1149 | EXPORT_SYMBOL_GPL(ata_scsi_slave_config); |
| 1118 | 1150 | |
| @@ -1136,6 +1168,8 @@ void ata_scsi_slave_destroy(struct scsi_device *sdev) · 17 unmodified lines | ||
| 1136 | 1168 | unsigned long flags; |
| 1137 | 1169 | struct ata_device *dev; |
| 1138 | 1170 | |
| 1171 | + device_link_remove(&sdev->sdev_gendev, &ap->tdev); | |
| 1172 | + | |
| 1139 | 1173 | spin_lock_irqsave(ap->lock, flags); |
| 1140 | 1174 | dev = __ata_scsi_find_dev(ap, sdev); |
| 1141 | 1175 | if (dev && dev->sdev) { |
| @@ -1195,7 +1229,7 @@ static unsigned int ata_scsi_start_stop_xlat(struct ata_queued_cmd *qc) · 53 unmodified lines | ||
| 1195 | 1229 | } |
| 1196 | 1230 | |
| 1197 | 1231 | if (cdb[4] & 0x1) { |
| 1198 | − tf->nsect = 1; /* 1 sector, lba=0 */ | |
| 1232 | + tf->nsect = 1; /* 1 sector, lba=0 */ | |
| 1199 | 1233 | |
| 1200 | 1234 | if (qc->dev->flags & ATA_DFLAG_LBA) { |
| 1201 | 1235 | tf->flags |= ATA_TFLAG_LBA; |
| @@ -1211,7 +1245,7 @@ static unsigned int ata_scsi_start_stop_xlat(struct ata_queued_cmd *qc) · 9 unmodified lines | ||
| 1211 | 1245 | tf->lbah = 0x0; /* cyl high */ |
| 1212 | 1246 | } |
| 1213 | 1247 | |
| 1214 | − tf->command = ATA_CMD_VERIFY; /* READ VERIFY */ | |
| 1248 | + tf->command = ATA_CMD_VERIFY; /* READ VERIFY */ | |
| 1215 | 1249 | } else { |
| 1216 | 1250 | /* Some odd clown BIOSen issue spindown on power off (ACPI S4 |
| 1217 | 1251 | * or S5) causing some drives to spin up and down again. |
| @@ -1221,7 +1255,7 @@ static unsigned int ata_scsi_start_stop_xlat(struct ata_queued_cmd *qc) · 3 unmodified lines | ||
| 1221 | 1255 | goto skip; |
| 1222 | 1256 | |
| 1223 | 1257 | if ((qc->ap->flags & ATA_FLAG_NO_HIBERNATE_SPINDOWN) && |
| 1224 | − system_entering_hibernation()) | |
| 1258 | + system_entering_hibernation()) | |
| 1225 | 1259 | goto skip; |
| 1226 | 1260 | |
| 1227 | 1261 | /* Issue ATA STANDBY IMMEDIATE command */ |
| @@ -1835,6 +1869,9 @@ static unsigned int ata_scsiop_inq_std(struct ata_scsi_args *args, u8 *rbuf) · 607 unmodified lines | ||
| 1835 | 1869 | hdr[2] = 0x7; /* claim SPC-5 version compatibility */ |
| 1836 | 1870 | } |
| 1837 | 1871 | |
| 1872 | + if (args->dev->flags & ATA_DFLAG_CDL) | |
| 1873 | + hdr[2] = 0xd; /* claim SPC-6 version compatibility */ | |
| 1874 | + | |
| 1838 | 1875 | memcpy(rbuf, hdr, sizeof(hdr)); |
| 1839 | 1876 | memcpy(&rbuf[8], "ATA ", 8); |
| 1840 | 1877 | ata_id_string(args->id, &rbuf[16], ATA_ID_PROD, 16); |
| @@ -4312,7 +4349,7 @@ void ata_scsi_simulate(struct ata_device *dev, struct scsi_cmnd *cmd) · 2471 unmodified lines | ||
| 4312 | 4349 | break; |
| 4313 | 4350 | |
| 4314 | 4351 | case MAINTENANCE_IN: |
| 4315 | − if (scsicmd[1] == MI_REPORT_SUPPORTED_OPERATION_CODES) | |
| 4352 | + if ((scsicmd[1] & 0x1f) == MI_REPORT_SUPPORTED_OPERATION_CODES) | |
| 4316 | 4353 | ata_scsi_rbuf_fill(&args, ata_scsiop_maint_in); |
| 4317 | 4354 | else |
| 4318 | 4355 | ata_scsi_set_invalid_field(dev, cmd, 1, 0xff); |
| @@ -4722,7 +4759,7 @@ void ata_scsi_dev_rescan(struct work_struct *work) · 403 unmodified lines | ||
| 4722 | 4759 | struct ata_link *link; |
| 4723 | 4760 | struct ata_device *dev; |
| 4724 | 4761 | unsigned long flags; |
| 4725 | − bool delay_rescan = false; | |
| 4762 | + int ret = 0; | |
| 4726 | 4763 | |
| 4727 | 4764 | mutex_lock(&ap->scsi_scan_mutex); |
| 4728 | 4765 | spin_lock_irqsave(ap->lock, flags); |
| @@ -4731,37 +4768,34 @@ void ata_scsi_dev_rescan(struct work_struct *work) · 2 unmodified lines | ||
| 4731 | 4768 | ata_for_each_dev(dev, link, ENABLED) { |
| 4732 | 4769 | struct scsi_device *sdev = dev->sdev; |
| 4733 | 4770 | |
| 4771 | + /* | |
| 4772 | + * If the port was suspended before this was scheduled, | |
| 4773 | + * bail out. | |
| 4774 | + */ | |
| 4775 | + if (ap->pflags & ATA_PFLAG_SUSPENDED) | |
| 4776 | + goto unlock; | |
| 4777 | + | |
| 4734 | 4778 | if (!sdev) |
| 4735 | 4779 | continue; |
| 4736 | 4780 | if (scsi_device_get(sdev)) |
| 4737 | 4781 | continue; |
| 4738 | 4782 | |
| 4739 | − /* | |
| 4740 | − * If the rescan work was scheduled because of a resume | |
| 4741 | − * event, the port is already fully resumed, but the | |
| 4742 | − * SCSI device may not yet be fully resumed. In such | |
| 4743 | − * case, executing scsi_rescan_device() may cause a | |
| 4744 | − * deadlock with the PM code on device_lock(). Prevent | |
| 4745 | − * this by giving up and retrying rescan after a short | |
| 4746 | − * delay. | |
| 4747 | − */ | |
| 4748 | − delay_rescan = sdev->sdev_gendev.power.is_suspended; | |
| 4749 | − if (delay_rescan) { | |
| 4750 | − scsi_device_put(sdev); | |
| 4751 | − break; | |
| 4752 | − } | |
| 4753 | − | |
| 4754 | 4783 | spin_unlock_irqrestore(ap->lock, flags); |
| 4755 | − scsi_rescan_device(sdev); | |
| 4784 | + ret = scsi_rescan_device(sdev); | |
| 4756 | 4785 | scsi_device_put(sdev); |
| 4757 | 4786 | spin_lock_irqsave(ap->lock, flags); |
| 4787 | + | |
| 4788 | + if (ret) | |
| 4789 | + goto unlock; | |
| 4758 | 4790 | } |
| 4759 | 4791 | } |
| 4760 | 4792 | |
| 4793 | +unlock: | |
| 4761 | 4794 | spin_unlock_irqrestore(ap->lock, flags); |
| 4762 | 4795 | mutex_unlock(&ap->scsi_scan_mutex); |
| 4763 | 4796 | |
| 4764 | − if (delay_rescan) | |
| 4797 | + /* Reschedule with a delay if scsi_rescan_device() returned an error */ | |
| 4798 | + if (ret) | |
| 4765 | 4799 | schedule_delayed_work(&ap->scsi_rescan_task, |
| 4766 | 4800 | msecs_to_jiffies(5)); |
| 4767 | 4801 | } |
| @@ -266,6 +266,10 @@ void ata_tport_delete(struct ata_port *ap) · 265 unmodified lines | ||
| 266 | 266 | put_device(dev); |
| 267 | 267 | } |
| 268 | 268 | |
| 269 | +static const struct device_type ata_port_sas_type = { | |
| 270 | + .name = ATA_PORT_TYPE_NAME, | |
| 271 | +}; | |
| 272 | + | |
| 269 | 273 | /** ata_tport_add - initialize a transport ATA port structure |
| 270 | 274 | * |
| 271 | 275 | * @parent: parent device |
| @@ -283,7 +287,10 @@ int ata_tport_add(struct device *parent, · 11 unmodified lines | ||
| 283 | 287 | struct device *dev = &ap->tdev; |
| 284 | 288 | |
| 285 | 289 | device_initialize(dev); |
| 286 | − dev->type = &ata_port_type; | |
| 290 | + if (ap->flags & ATA_FLAG_SAS_HOST) | |
| 291 | + dev->type = &ata_port_sas_type; | |
| 292 | + else | |
| 293 | + dev->type = &ata_port_type; | |
| 287 | 294 | |
| 288 | 295 | dev->parent = parent; |
| 289 | 296 | ata_host_get(ap->host); |
| @@ -30,6 +30,8 @@ enum { · 29 unmodified lines | ||
| 30 | 30 | ATA_DNXFER_QUIET = (1 << 31), |
| 31 | 31 | }; |
| 32 | 32 | |
| 33 | +#define ATA_PORT_TYPE_NAME "ata_port" | |
| 34 | + | |
| 33 | 35 | extern atomic_t ata_print_id; |
| 34 | 36 | extern int atapi_passthru16; |
| 35 | 37 | extern int libata_fua; |
| @@ -60,6 +62,8 @@ extern int ata_dev_reread_id(struct ata_device *dev, unsigned int readid_flags); · 24 unmodified lines | ||
| 60 | 62 | extern int ata_dev_revalidate(struct ata_device *dev, unsigned int new_class, |
| 61 | 63 | unsigned int readid_flags); |
| 62 | 64 | extern int ata_dev_configure(struct ata_device *dev); |
| 65 | +extern void ata_dev_power_set_standby(struct ata_device *dev); | |
| 66 | +extern void ata_dev_power_set_active(struct ata_device *dev); | |
| 63 | 67 | extern int sata_down_spd_limit(struct ata_link *link, u32 spd_limit); |
| 64 | 68 | extern int ata_down_xfermask_limit(struct ata_device *dev, unsigned int sel); |
| 65 | 69 | extern unsigned int ata_dev_set_feature(struct ata_device *dev, |
| @@ -453,7 +453,8 @@ static int regcache_rbtree_write(struct regmap *map, unsigned int reg, · 452 unmodified lines | ||
| 453 | 453 | if (!rbnode) |
| 454 | 454 | return -ENOMEM; |
| 455 | 455 | regcache_rbtree_set_register(map, rbnode, |
| 456 | − reg - rbnode->base_reg, value); | |
| 456 | + (reg - rbnode->base_reg) / map->reg_stride, | |
| 457 | + value); | |
| 457 | 458 | regcache_rbtree_insert(map, &rbtree_ctx->root, rbnode); |
| 458 | 459 | rbtree_ctx->cached_rbnode = rbnode; |
| 459 | 460 | } |
| @@ -632,9 +632,8 @@ void rbd_warn(struct rbd_device *rbd_dev, const char *fmt, ...) · 631 unmodified lines | ||
| 632 | 632 | static void rbd_dev_remove_parent(struct rbd_device *rbd_dev); |
| 633 | 633 | |
| 634 | 634 | static int rbd_dev_refresh(struct rbd_device *rbd_dev); |
| 635 | −static int rbd_dev_v2_header_onetime(struct rbd_device *rbd_dev); | |
| 636 | −static int rbd_dev_header_info(struct rbd_device *rbd_dev); | |
| 637 | −static int rbd_dev_v2_parent_info(struct rbd_device *rbd_dev); | |
| 635 | +static int rbd_dev_v2_header_onetime(struct rbd_device *rbd_dev, | |
| 636 | + struct rbd_image_header *header); | |
| 638 | 637 | static const char *rbd_dev_v2_snap_name(struct rbd_device *rbd_dev, |
| 639 | 638 | u64 snap_id); |
| 640 | 639 | static int _rbd_dev_v2_snap_size(struct rbd_device *rbd_dev, u64 snap_id, |
| @@ -995,15 +994,24 @@ static void rbd_init_layout(struct rbd_device *rbd_dev) · 354 unmodified lines | ||
| 995 | 994 | RCU_INIT_POINTER(rbd_dev->layout.pool_ns, NULL); |
| 996 | 995 | } |
| 997 | 996 | |
| 997 | +static void rbd_image_header_cleanup(struct rbd_image_header *header) | |
| 998 | +{ | |
| 999 | + kfree(header->object_prefix); | |
| 1000 | + ceph_put_snap_context(header->snapc); | |
| 1001 | + kfree(header->snap_sizes); | |
| 1002 | + kfree(header->snap_names); | |
| 1003 | + | |
| 1004 | + memset(header, 0, sizeof(*header)); | |
| 1005 | +} | |
| 1006 | + | |
| 998 | 1007 | /* |
| 999 | 1008 | * Fill an rbd image header with information from the given format 1 |
| 1000 | 1009 | * on-disk header. |
| 1001 | 1010 | */ |
| 1002 | −static int rbd_header_from_disk(struct rbd_device *rbd_dev, | |
| 1003 | − struct rbd_image_header_ondisk *ondisk) | |
| 1011 | +static int rbd_header_from_disk(struct rbd_image_header *header, | |
| 1012 | + struct rbd_image_header_ondisk *ondisk, | |
| 1013 | + bool first_time) | |
| 1004 | 1014 | { |
| 1005 | − struct rbd_image_header *header = &rbd_dev->header; | |
| 1006 | − bool first_time = header->object_prefix == NULL; | |
| 1007 | 1015 | struct ceph_snap_context *snapc; |
| 1008 | 1016 | char *object_prefix = NULL; |
| 1009 | 1017 | char *snap_names = NULL; |
| @@ -1070,11 +1078,6 @@ static int rbd_header_from_disk(struct rbd_device *rbd_dev, · 60 unmodified lines | ||
| 1070 | 1078 | if (first_time) { |
| 1071 | 1079 | header->object_prefix = object_prefix; |
| 1072 | 1080 | header->obj_order = ondisk->options.order; |
| 1073 | − rbd_init_layout(rbd_dev); | |
| 1074 | − } else { | |
| 1075 | − ceph_put_snap_context(header->snapc); | |
| 1076 | − kfree(header->snap_names); | |
| 1077 | − kfree(header->snap_sizes); | |
| 1078 | 1081 | } |
| 1079 | 1082 | |
| 1080 | 1083 | /* The remaining fields always get updated (when we refresh) */ |
| @@ -4859,7 +4862,9 @@ out_req: · 3778 unmodified lines | ||
| 4859 | 4862 | * return, the rbd_dev->header field will contain up-to-date |
| 4860 | 4863 | * information about the image. |
| 4861 | 4864 | */ |
| 4862 | −static int rbd_dev_v1_header_info(struct rbd_device *rbd_dev) | |
| 4865 | +static int rbd_dev_v1_header_info(struct rbd_device *rbd_dev, | |
| 4866 | + struct rbd_image_header *header, | |
| 4867 | + bool first_time) | |
| 4863 | 4868 | { |
| 4864 | 4869 | struct rbd_image_header_ondisk *ondisk = NULL; |
| 4865 | 4870 | u32 snap_count = 0; |
| @@ -4907,7 +4912,7 @@ static int rbd_dev_v1_header_info(struct rbd_device *rbd_dev) · 41 unmodified lines | ||
| 4907 | 4912 | snap_count = le32_to_cpu(ondisk->snap_count); |
| 4908 | 4913 | } while (snap_count != want_count); |
| 4909 | 4914 | |
| 4910 | − ret = rbd_header_from_disk(rbd_dev, ondisk); | |
| 4915 | + ret = rbd_header_from_disk(header, ondisk, first_time); | |
| 4911 | 4916 | out: |
| 4912 | 4917 | kfree(ondisk); |
| 4913 | 4918 | |
| @@ -4931,39 +4936,6 @@ static void rbd_dev_update_size(struct rbd_device *rbd_dev) · 17 unmodified lines | ||
| 4931 | 4936 | } |
| 4932 | 4937 | } |
| 4933 | 4938 | |
| 4934 | −static int rbd_dev_refresh(struct rbd_device *rbd_dev) | |
| 4935 | −{ | |
| 4936 | − u64 mapping_size; | |
| 4937 | − int ret; | |
| 4938 | − | |
| 4939 | − down_write(&rbd_dev->header_rwsem); | |
| 4940 | − mapping_size = rbd_dev->mapping.size; | |
| 4941 | − | |
| 4942 | − ret = rbd_dev_header_info(rbd_dev); | |
| 4943 | − if (ret) | |
| 4944 | − goto out; | |
| 4945 | − | |
| 4946 | − /* | |
| 4947 | − * If there is a parent, see if it has disappeared due to the | |
| 4948 | − * mapped image getting flattened. | |
| 4949 | − */ | |
| 4950 | − if (rbd_dev->parent) { | |
| 4951 | − ret = rbd_dev_v2_parent_info(rbd_dev); | |
| 4952 | − if (ret) | |
| 4953 | − goto out; | |
| 4954 | − } | |
| 4955 | − | |
| 4956 | − rbd_assert(!rbd_is_snap(rbd_dev)); | |
| 4957 | − rbd_dev->mapping.size = rbd_dev->header.image_size; | |
| 4958 | − | |
| 4959 | −out: | |
| 4960 | − up_write(&rbd_dev->header_rwsem); | |
| 4961 | − if (!ret && mapping_size != rbd_dev->mapping.size) | |
| 4962 | − rbd_dev_update_size(rbd_dev); | |
| 4963 | − | |
| 4964 | − return ret; | |
| 4965 | −} | |
| 4966 | − | |
| 4967 | 4939 | static const struct blk_mq_ops rbd_mq_ops = { |
| 4968 | 4940 | .queue_rq = rbd_queue_rq, |
| 4969 | 4941 | }; |
| @@ -5503,17 +5475,12 @@ static int _rbd_dev_v2_snap_size(struct rbd_device *rbd_dev, u64 snap_id, · 533 unmodified lines | ||
| 5503 | 5475 | return 0; |
| 5504 | 5476 | } |
| 5505 | 5477 | |
| 5506 | −static int rbd_dev_v2_image_size(struct rbd_device *rbd_dev) | |
| 5507 | −{ | |
| 5508 | − return _rbd_dev_v2_snap_size(rbd_dev, CEPH_NOSNAP, | |
| 5509 | − &rbd_dev->header.obj_order, | |
| 5510 | − &rbd_dev->header.image_size); | |
| 5511 | −} | |
| 5512 | − | |
| 5513 | −static int rbd_dev_v2_object_prefix(struct rbd_device *rbd_dev) | |
| 5478 | +static int rbd_dev_v2_object_prefix(struct rbd_device *rbd_dev, | |
| 5479 | + char **pobject_prefix) | |
| 5514 | 5480 | { |
| 5515 | 5481 | size_t size; |
| 5516 | 5482 | void *reply_buf; |
| 5483 | + char *object_prefix; | |
| 5517 | 5484 | int ret; |
| 5518 | 5485 | void *p; |
| 5519 | 5486 | |
| @@ -5531,16 +5498,16 @@ static int rbd_dev_v2_object_prefix(struct rbd_device *rbd_dev) · 11 unmodified lines | ||
| 5531 | 5498 | goto out; |
| 5532 | 5499 | |
| 5533 | 5500 | p = reply_buf; |
| 5534 | − rbd_dev->header.object_prefix = ceph_extract_encoded_string(&p, | |
| 5535 | − p + ret, NULL, GFP_NOIO); | |
| 5501 | + object_prefix = ceph_extract_encoded_string(&p, p + ret, NULL, | |
| 5502 | + GFP_NOIO); | |
| 5503 | + if (IS_ERR(object_prefix)) { | |
| 5504 | + ret = PTR_ERR(object_prefix); | |
| 5505 | + goto out; | |
| 5506 | + } | |
| 5536 | 5507 | ret = 0; |
| 5537 | 5508 | |
| 5538 | − if (IS_ERR(rbd_dev->header.object_prefix)) { | |
| 5539 | − ret = PTR_ERR(rbd_dev->header.object_prefix); | |
| 5540 | − rbd_dev->header.object_prefix = NULL; | |
| 5541 | − } else { | |
| 5542 | − dout(" object_prefix = %s\n", rbd_dev->header.object_prefix); | |
| 5543 | − } | |
| 5509 | + *pobject_prefix = object_prefix; | |
| 5510 | + dout(" object_prefix = %s\n", object_prefix); | |
| 5544 | 5511 | out: |
| 5545 | 5512 | kfree(reply_buf); |
| 5546 | 5513 | |
| @@ -5591,13 +5558,6 @@ static int _rbd_dev_v2_snap_features(struct rbd_device *rbd_dev, u64 snap_id, · 44 unmodified lines | ||
| 5591 | 5558 | return 0; |
| 5592 | 5559 | } |
| 5593 | 5560 | |
| 5594 | −static int rbd_dev_v2_features(struct rbd_device *rbd_dev) | |
| 5595 | −{ | |
| 5596 | − return _rbd_dev_v2_snap_features(rbd_dev, CEPH_NOSNAP, | |
| 5597 | − rbd_is_ro(rbd_dev), | |
| 5598 | − &rbd_dev->header.features); | |
| 5599 | −} | |
| 5600 | − | |
| 5601 | 5561 | /* |
| 5602 | 5562 | * These are generic image flags, but since they are used only for |
| 5603 | 5563 | * object map, store them in rbd_dev->object_map_flags. |
| @@ -5634,6 +5594,14 @@ struct parent_image_info { · 30 unmodified lines | ||
| 5634 | 5594 | u64 overlap; |
| 5635 | 5595 | }; |
| 5636 | 5596 | |
| 5597 | +static void rbd_parent_info_cleanup(struct parent_image_info *pii) | |
| 5598 | +{ | |
| 5599 | + kfree(pii->pool_ns); | |
| 5600 | + kfree(pii->image_id); | |
| 5601 | + | |
| 5602 | + memset(pii, 0, sizeof(*pii)); | |
| 5603 | +} | |
| 5604 | + | |
| 5637 | 5605 | /* |
| 5638 | 5606 | * The caller is responsible for @pii. |
| 5639 | 5607 | */ |
| @@ -5703,6 +5671,9 @@ static int __get_parent_info(struct rbd_device *rbd_dev, · 63 unmodified lines | ||
| 5703 | 5671 | if (pii->has_overlap) |
| 5704 | 5672 | ceph_decode_64_safe(&p, end, pii->overlap, e_inval); |
| 5705 | 5673 | |
| 5674 | + dout("%s pool_id %llu pool_ns %s image_id %s snap_id %llu has_overlap %d overlap %llu\n", | |
| 5675 | + __func__, pii->pool_id, pii->pool_ns, pii->image_id, pii->snap_id, | |
| 5676 | + pii->has_overlap, pii->overlap); | |
| 5706 | 5677 | return 0; |
| 5707 | 5678 | |
| 5708 | 5679 | e_inval: |
| @@ -5741,14 +5712,17 @@ static int __get_parent_info_legacy(struct rbd_device *rbd_dev, · 32 unmodified lines | ||
| 5741 | 5712 | pii->has_overlap = true; |
| 5742 | 5713 | ceph_decode_64_safe(&p, end, pii->overlap, e_inval); |
| 5743 | 5714 | |
| 5715 | + dout("%s pool_id %llu pool_ns %s image_id %s snap_id %llu has_overlap %d overlap %llu\n", | |
| 5716 | + __func__, pii->pool_id, pii->pool_ns, pii->image_id, pii->snap_id, | |
| 5717 | + pii->has_overlap, pii->overlap); | |
| 5744 | 5718 | return 0; |
| 5745 | 5719 | |
| 5746 | 5720 | e_inval: |
| 5747 | 5721 | return -EINVAL; |
| 5748 | 5722 | } |
| 5749 | 5723 | |
| 5750 | −static int get_parent_info(struct rbd_device *rbd_dev, | |
| 5751 | − struct parent_image_info *pii) | |
| 5724 | +static int rbd_dev_v2_parent_info(struct rbd_device *rbd_dev, | |
| 5725 | + struct parent_image_info *pii) | |
| 5752 | 5726 | { |
| 5753 | 5727 | struct page *req_page, *reply_page; |
| 5754 | 5728 | void *p; |
| @@ -5776,7 +5750,7 @@ static int get_parent_info(struct rbd_device *rbd_dev, · 21 unmodified lines | ||
| 5776 | 5750 | return ret; |
| 5777 | 5751 | } |
| 5778 | 5752 | |
| 5779 | −static int rbd_dev_v2_parent_info(struct rbd_device *rbd_dev) | |
| 5753 | +static int rbd_dev_setup_parent(struct rbd_device *rbd_dev) | |
| 5780 | 5754 | { |
| 5781 | 5755 | struct rbd_spec *parent_spec; |
| 5782 | 5756 | struct parent_image_info pii = { 0 }; |
| @@ -5786,37 +5760,12 @@ static int rbd_dev_v2_parent_info(struct rbd_device *rbd_dev) · 3 unmodified lines | ||
| 5786 | 5760 | if (!parent_spec) |
| 5787 | 5761 | return -ENOMEM; |
| 5788 | 5762 | |
| 5789 | − ret = get_parent_info(rbd_dev, &pii); | |
| 5763 | + ret = rbd_dev_v2_parent_info(rbd_dev, &pii); | |
| 5790 | 5764 | if (ret) |
| 5791 | 5765 | goto out_err; |
| 5792 | 5766 | |
| 5793 | − dout("%s pool_id %llu pool_ns %s image_id %s snap_id %llu has_overlap %d overlap %llu\n", | |
| 5794 | − __func__, pii.pool_id, pii.pool_ns, pii.image_id, pii.snap_id, | |
| 5795 | − pii.has_overlap, pii.overlap); | |
| 5796 | − | |
| 5797 | − if (pii.pool_id == CEPH_NOPOOL || !pii.has_overlap) { | |
| 5798 | − /* | |
| 5799 | − * Either the parent never existed, or we have | |
| 5800 | − * record of it but the image got flattened so it no | |
| 5801 | − * longer has a parent. When the parent of a | |
| 5802 | − * layered image disappears we immediately set the | |
| 5803 | − * overlap to 0. The effect of this is that all new | |
| 5804 | − * requests will be treated as if the image had no | |
| 5805 | − * parent. | |
| 5806 | − * | |
| 5807 | − * If !pii.has_overlap, the parent image spec is not | |
| 5808 | − * applicable. It's there to avoid duplication in each | |
| 5809 | − * snapshot record. | |
| 5810 | − */ | |
| 5811 | − if (rbd_dev->parent_overlap) { | |
| 5812 | − rbd_dev->parent_overlap = 0; | |
| 5813 | − rbd_dev_parent_put(rbd_dev); | |
| 5814 | − pr_info("%s: clone image has been flattened\n", | |
| 5815 | − rbd_dev->disk->disk_name); | |
| 5816 | − } | |
| 5817 | − | |
| 5767 | + if (pii.pool_id == CEPH_NOPOOL || !pii.has_overlap) | |
| 5818 | 5768 | goto out; /* No parent? No problem. */ |
| 5819 | − } | |
| 5820 | 5769 | |
| 5821 | 5770 | /* The ceph file layout needs to fit pool id in 32 bits */ |
| 5822 | 5771 | |
| @@ -5828,58 +5777,46 @@ static int rbd_dev_v2_parent_info(struct rbd_device *rbd_dev) · 5 unmodified lines | ||
| 5828 | 5777 | } |
| 5829 | 5778 | |
| 5830 | 5779 | /* |
| 5831 | − * The parent won't change (except when the clone is | |
| 5832 | − * flattened, already handled that). So we only need to | |
| 5833 | − * record the parent spec we have not already done so. | |
| 5780 | + * The parent won't change except when the clone is flattened, | |
| 5781 | + * so we only need to record the parent image spec once. | |
| 5834 | 5782 | */ |
| 5835 | − if (!rbd_dev->parent_spec) { | |
| 5836 | − parent_spec->pool_id = pii.pool_id; | |
| 5837 | − if (pii.pool_ns && *pii.pool_ns) { | |
| 5838 | − parent_spec->pool_ns = pii.pool_ns; | |
| 5839 | − pii.pool_ns = NULL; | |
| 5840 | − } | |
| 5841 | − parent_spec->image_id = pii.image_id; | |
| 5842 | − pii.image_id = NULL; | |
| 5843 | − parent_spec->snap_id = pii.snap_id; | |
| 5844 | − | |
| 5845 | − rbd_dev->parent_spec = parent_spec; | |
| 5846 | − parent_spec = NULL; /* rbd_dev now owns this */ | |
| 5783 | + parent_spec->pool_id = pii.pool_id; | |
| 5784 | + if (pii.pool_ns && *pii.pool_ns) { | |
| 5785 | + parent_spec->pool_ns = pii.pool_ns; | |
| 5786 | + pii.pool_ns = NULL; | |
| 5847 | 5787 | } |
| 5788 | + parent_spec->image_id = pii.image_id; | |
| 5789 | + pii.image_id = NULL; | |
| 5790 | + parent_spec->snap_id = pii.snap_id; | |
| 5791 | + | |
| 5792 | + rbd_assert(!rbd_dev->parent_spec); | |
| 5793 | + rbd_dev->parent_spec = parent_spec; | |
| 5794 | + parent_spec = NULL; /* rbd_dev now owns this */ | |
| 5848 | 5795 | |
| 5849 | 5796 | /* |
| 5850 | − * We always update the parent overlap. If it's zero we issue | |
| 5851 | − * a warning, as we will proceed as if there was no parent. | |
| 5797 | + * Record the parent overlap. If it's zero, issue a warning as | |
| 5798 | + * we will proceed as if there is no parent. | |
| 5852 | 5799 | */ |
| 5853 | − if (!pii.overlap) { | |
| 5854 | − if (parent_spec) { | |
| 5855 | − /* refresh, careful to warn just once */ | |
| 5856 | − if (rbd_dev->parent_overlap) | |
| 5857 | − rbd_warn(rbd_dev, | |
| 5858 | − "clone now standalone (overlap became 0)"); | |
| 5859 | − } else { | |
| 5860 | − /* initial probe */ | |
| 5861 | − rbd_warn(rbd_dev, "clone is standalone (overlap 0)"); | |
| 5862 | − } | |
| 5863 | − } | |
| 5800 | + if (!pii.overlap) | |
| 5801 | + rbd_warn(rbd_dev, "clone is standalone (overlap 0)"); | |
| 5864 | 5802 | rbd_dev->parent_overlap = pii.overlap; |
| 5865 | 5803 | |
| 5866 | 5804 | out: |
| 5867 | 5805 | ret = 0; |
| 5868 | 5806 | out_err: |
| 5869 | − kfree(pii.pool_ns); | |
| 5870 | − kfree(pii.image_id); | |
| 5807 | + rbd_parent_info_cleanup(&pii); | |
| 5871 | 5808 | rbd_spec_put(parent_spec); |
| 5872 | 5809 | return ret; |
| 5873 | 5810 | } |
| 5874 | 5811 | |
| 5875 | −static int rbd_dev_v2_striping_info(struct rbd_device *rbd_dev) | |
| 5812 | +static int rbd_dev_v2_striping_info(struct rbd_device *rbd_dev, | |
| 5813 | + u64 *stripe_unit, u64 *stripe_count) | |
| 5876 | 5814 | { |
| 5877 | 5815 | struct { |
| 5878 | 5816 | __le64 stripe_unit; |
| 5879 | 5817 | __le64 stripe_count; |
| 5880 | 5818 | } __attribute__ ((packed)) striping_info_buf = { 0 }; |
| 5881 | 5819 | size_t size = sizeof (striping_info_buf); |
| 5882 | − void *p; | |
| 5883 | 5820 | int ret; |
| 5884 | 5821 | |
| 5885 | 5822 | ret = rbd_obj_method_sync(rbd_dev, &rbd_dev->header_oid, |
| @@ -5891,27 +5828,33 @@ static int rbd_dev_v2_striping_info(struct rbd_device *rbd_dev) · 5 unmodified lines | ||
| 5891 | 5828 | if (ret < size) |
| 5892 | 5829 | return -ERANGE; |
| 5893 | 5830 | |
| 5894 | − p = &striping_info_buf; | |
| 5895 | − rbd_dev->header.stripe_unit = ceph_decode_64(&p); | |
| 5896 | − rbd_dev->header.stripe_count = ceph_decode_64(&p); | |
| 5831 | + *stripe_unit = le64_to_cpu(striping_info_buf.stripe_unit); | |
| 5832 | + *stripe_count = le64_to_cpu(striping_info_buf.stripe_count); | |
| 5833 | + dout(" stripe_unit = %llu stripe_count = %llu\n", *stripe_unit, | |
| 5834 | + *stripe_count); | |
| 5835 | + | |
| 5897 | 5836 | return 0; |
| 5898 | 5837 | } |
| 5899 | 5838 | |
| 5900 | −static int rbd_dev_v2_data_pool(struct rbd_device *rbd_dev) | |
| 5839 | +static int rbd_dev_v2_data_pool(struct rbd_device *rbd_dev, s64 *data_pool_id) | |
| 5901 | 5840 | { |
| 5902 | − __le64 data_pool_id; | |
| 5841 | + __le64 data_pool_buf; | |
| 5903 | 5842 | int ret; |
| 5904 | 5843 | |
| 5905 | 5844 | ret = rbd_obj_method_sync(rbd_dev, &rbd_dev->header_oid, |
| 5906 | 5845 | &rbd_dev->header_oloc, "get_data_pool", |
| 5907 | − NULL, 0, &data_pool_id, sizeof(data_pool_id)); | |
| 5846 | + NULL, 0, &data_pool_buf, | |
| 5847 | + sizeof(data_pool_buf)); | |
| 5848 | + dout("%s: rbd_obj_method_sync returned %d\n", __func__, ret); | |
| 5908 | 5849 | if (ret < 0) |
| 5909 | 5850 | return ret; |
| 5910 | − if (ret < sizeof(data_pool_id)) | |
| 5851 | + if (ret < sizeof(data_pool_buf)) | |
| 5911 | 5852 | return -EBADMSG; |
| 5912 | 5853 | |
| 5913 | − rbd_dev->header.data_pool_id = le64_to_cpu(data_pool_id); | |
| 5914 | − WARN_ON(rbd_dev->header.data_pool_id == CEPH_NOPOOL); | |
| 5854 | + *data_pool_id = le64_to_cpu(data_pool_buf); | |
| 5855 | + dout(" data_pool_id = %lld\n", *data_pool_id); | |
| 5856 | + WARN_ON(*data_pool_id == CEPH_NOPOOL); | |
| 5857 | + | |
| 5915 | 5858 | return 0; |
| 5916 | 5859 | } |
| 5917 | 5860 | |
| @@ -6103,7 +6046,8 @@ out_err: · 185 unmodified lines | ||
| 6103 | 6046 | return ret; |
| 6104 | 6047 | } |
| 6105 | 6048 | |
| 6106 | −static int rbd_dev_v2_snap_context(struct rbd_device *rbd_dev) | |
| 6049 | +static int rbd_dev_v2_snap_context(struct rbd_device *rbd_dev, | |
| 6050 | + struct ceph_snap_context **psnapc) | |
| 6107 | 6051 | { |
| 6108 | 6052 | size_t size; |
| 6109 | 6053 | int ret; |
| @@ -6164,9 +6108,7 @@ static int rbd_dev_v2_snap_context(struct rbd_device *rbd_dev) · 54 unmodified lines | ||
| 6164 | 6108 | for (i = 0; i < snap_count; i++) |
| 6165 | 6109 | snapc->snaps[i] = ceph_decode_64(&p); |
| 6166 | 6110 | |
| 6167 | − ceph_put_snap_context(rbd_dev->header.snapc); | |
| 6168 | − rbd_dev->header.snapc = snapc; | |
| 6169 | − | |
| 6111 | + *psnapc = snapc; | |
| 6170 | 6112 | dout(" snap context seq = %llu, snap_count = %u\n", |
| 6171 | 6113 | (unsigned long long)seq, (unsigned int)snap_count); |
| 6172 | 6114 | out: |
| @@ -6215,38 +6157,42 @@ out: · 42 unmodified lines | ||
| 6215 | 6157 | return snap_name; |
| 6216 | 6158 | } |
| 6217 | 6159 | |
| 6218 | −static int rbd_dev_v2_header_info(struct rbd_device *rbd_dev) | |
| 6160 | +static int rbd_dev_v2_header_info(struct rbd_device *rbd_dev, | |
| 6161 | + struct rbd_image_header *header, | |
| 6162 | + bool first_time) | |
| 6219 | 6163 | { |
| 6220 | − bool first_time = rbd_dev->header.object_prefix == NULL; | |
| 6221 | 6164 | int ret; |
| 6222 | 6165 | |
| 6223 | − ret = rbd_dev_v2_image_size(rbd_dev); | |
| 6166 | + ret = _rbd_dev_v2_snap_size(rbd_dev, CEPH_NOSNAP, | |
| 6167 | + first_time ? &header->obj_order : NULL, | |
| 6168 | + &header->image_size); | |
| 6224 | 6169 | if (ret) |
| 6225 | 6170 | return ret; |
| 6226 | 6171 | |
| 6227 | 6172 | if (first_time) { |
| 6228 | − ret = rbd_dev_v2_header_onetime(rbd_dev); | |
| 6173 | + ret = rbd_dev_v2_header_onetime(rbd_dev, header); | |
| 6229 | 6174 | if (ret) |
| 6230 | 6175 | return ret; |
| 6231 | 6176 | } |
| 6232 | 6177 | |
| 6233 | − ret = rbd_dev_v2_snap_context(rbd_dev); | |
| 6234 | − if (ret && first_time) { | |
| 6235 | − kfree(rbd_dev->header.object_prefix); | |
| 6236 | − rbd_dev->header.object_prefix = NULL; | |
| 6237 | − } | |
| 6178 | + ret = rbd_dev_v2_snap_context(rbd_dev, &header->snapc); | |
| 6179 | + if (ret) | |
| 6180 | + return ret; | |
| 6238 | 6181 | |
| 6239 | − return ret; | |
| 6182 | + return 0; | |
| 6240 | 6183 | } |
| 6241 | 6184 | |
| 6242 | −static int rbd_dev_header_info(struct rbd_device *rbd_dev) | |
| 6185 | +static int rbd_dev_header_info(struct rbd_device *rbd_dev, | |
| 6186 | + struct rbd_image_header *header, | |
| 6187 | + bool first_time) | |
| 6243 | 6188 | { |
| 6244 | 6189 | rbd_assert(rbd_image_format_valid(rbd_dev->image_format)); |
| 6190 | + rbd_assert(!header->object_prefix && !header->snapc); | |
| 6245 | 6191 | |
| 6246 | 6192 | if (rbd_dev->image_format == 1) |
| 6247 | − return rbd_dev_v1_header_info(rbd_dev); | |
| 6193 | + return rbd_dev_v1_header_info(rbd_dev, header, first_time); | |
| 6248 | 6194 | |
| 6249 | − return rbd_dev_v2_header_info(rbd_dev); | |
| 6195 | + return rbd_dev_v2_header_info(rbd_dev, header, first_time); | |
| 6250 | 6196 | } |
| 6251 | 6197 | |
| 6252 | 6198 | /* |
| @@ -6734,60 +6680,49 @@ out: · 481 unmodified lines | ||
| 6734 | 6680 | */ |
| 6735 | 6681 | static void rbd_dev_unprobe(struct rbd_device *rbd_dev) |
| 6736 | 6682 | { |
| 6737 | − struct rbd_image_header *header; | |
| 6738 | − | |
| 6739 | 6683 | rbd_dev_parent_put(rbd_dev); |
| 6740 | 6684 | rbd_object_map_free(rbd_dev); |
| 6741 | 6685 | rbd_dev_mapping_clear(rbd_dev); |
| 6742 | 6686 | |
| 6743 | 6687 | /* Free dynamic fields from the header, then zero it out */ |
| 6744 | 6688 | |
| 6745 | − header = &rbd_dev->header; | |
| 6746 | − ceph_put_snap_context(header->snapc); | |
| 6747 | − kfree(header->snap_sizes); | |
| 6748 | − kfree(header->snap_names); | |
| 6749 | − kfree(header->object_prefix); | |
| 6750 | − memset(header, 0, sizeof (*header)); | |
| 6689 | + rbd_image_header_cleanup(&rbd_dev->header); | |
| 6751 | 6690 | } |
| 6752 | 6691 | |
| 6753 | −static int rbd_dev_v2_header_onetime(struct rbd_device *rbd_dev) | |
| 6692 | +static int rbd_dev_v2_header_onetime(struct rbd_device *rbd_dev, | |
| 6693 | + struct rbd_image_header *header) | |
| 6754 | 6694 | { |
| 6755 | 6695 | int ret; |
| 6756 | 6696 | |
| 6757 | − ret = rbd_dev_v2_object_prefix(rbd_dev); | |
| 6697 | + ret = rbd_dev_v2_object_prefix(rbd_dev, &header->object_prefix); | |
| 6758 | 6698 | if (ret) |
| 6759 | − goto out_err; | |
| 6699 | + return ret; | |
| 6760 | 6700 | |
| 6761 | 6701 | /* |
| 6762 | 6702 | * Get the and check features for the image. Currently the |
| 6763 | 6703 | * features are assumed to never change. |
| 6764 | 6704 | */ |
| 6765 | − ret = rbd_dev_v2_features(rbd_dev); | |
| 6705 | + ret = _rbd_dev_v2_snap_features(rbd_dev, CEPH_NOSNAP, | |
| 6706 | + rbd_is_ro(rbd_dev), &header->features); | |
| 6766 | 6707 | if (ret) |
| 6767 | − goto out_err; | |
| 6708 | + return ret; | |
| 6768 | 6709 | |
| 6769 | 6710 | /* If the image supports fancy striping, get its parameters */ |
| 6770 | 6711 | |
| 6771 | − if (rbd_dev->header.features & RBD_FEATURE_STRIPINGV2) { | |
| 6772 | − ret = rbd_dev_v2_striping_info(rbd_dev); | |
| 6773 | − if (ret < 0) | |
| 6774 | − goto out_err; | |
| 6712 | + if (header->features & RBD_FEATURE_STRIPINGV2) { | |
| 6713 | + ret = rbd_dev_v2_striping_info(rbd_dev, &header->stripe_unit, | |
| 6714 | + &header->stripe_count); | |
| 6715 | + if (ret) | |
| 6716 | + return ret; | |
| 6775 | 6717 | } |
| 6776 | 6718 | |
| 6777 | − if (rbd_dev->header.features & RBD_FEATURE_DATA_POOL) { | |
| 6778 | − ret = rbd_dev_v2_data_pool(rbd_dev); | |
| 6719 | + if (header->features & RBD_FEATURE_DATA_POOL) { | |
| 6720 | + ret = rbd_dev_v2_data_pool(rbd_dev, &header->data_pool_id); | |
| 6779 | 6721 | if (ret) |
| 6780 | − goto out_err; | |
| 6722 | + return ret; | |
| 6781 | 6723 | } |
| 6782 | 6724 | |
| 6783 | − rbd_init_layout(rbd_dev); | |
| 6784 | 6725 | return 0; |
| 6785 | − | |
| 6786 | −out_err: | |
| 6787 | − rbd_dev->header.features = 0; | |
| 6788 | − kfree(rbd_dev->header.object_prefix); | |
| 6789 | − rbd_dev->header.object_prefix = NULL; | |
| 6790 | − return ret; | |
| 6791 | 6726 | } |
| 6792 | 6727 | |
| 6793 | 6728 | /* |
| @@ -6982,13 +6917,15 @@ static int rbd_dev_image_probe(struct rbd_device *rbd_dev, int depth) · 188 unmodified lines | ||
| 6982 | 6917 | if (!depth) |
| 6983 | 6918 | down_write(&rbd_dev->header_rwsem); |
| 6984 | 6919 | |
| 6985 | − ret = rbd_dev_header_info(rbd_dev); | |
| 6920 | + ret = rbd_dev_header_info(rbd_dev, &rbd_dev->header, true); | |
| 6986 | 6921 | if (ret) { |
| 6987 | 6922 | if (ret == -ENOENT && !need_watch) |
| 6988 | 6923 | rbd_print_dne(rbd_dev, false); |
| 6989 | 6924 | goto err_out_probe; |
| 6990 | 6925 | } |
| 6991 | 6926 | |
| 6927 | + rbd_init_layout(rbd_dev); | |
| 6928 | + | |
| 6992 | 6929 | /* |
| 6993 | 6930 | * If this image is the one being mapped, we have pool name and |
| 6994 | 6931 | * id, image name and id, and snap name - need to fill snap id. |
| @@ -7017,7 +6954,7 @@ static int rbd_dev_image_probe(struct rbd_device *rbd_dev, int depth) · 22 unmodified lines | ||
| 7017 | 6954 | } |
| 7018 | 6955 | |
| 7019 | 6956 | if (rbd_dev->header.features & RBD_FEATURE_LAYERING) { |
| 7020 | − ret = rbd_dev_v2_parent_info(rbd_dev); | |
| 6957 | + ret = rbd_dev_setup_parent(rbd_dev); | |
| 7021 | 6958 | if (ret) |
| 7022 | 6959 | goto err_out_probe; |
| 7023 | 6960 | } |
| @@ -7043,6 +6980,107 @@ err_out_format: · 19 unmodified lines | ||
| 7043 | 6980 | return ret; |
| 7044 | 6981 | } |
| 7045 | 6982 | |
| 6983 | +static void rbd_dev_update_header(struct rbd_device *rbd_dev, | |
| 6984 | + struct rbd_image_header *header) | |
| 6985 | +{ | |
| 6986 | + rbd_assert(rbd_image_format_valid(rbd_dev->image_format)); | |
| 6987 | + rbd_assert(rbd_dev->header.object_prefix); /* !first_time */ | |
| 6988 | + | |
| 6989 | + if (rbd_dev->header.image_size != header->image_size) { | |
| 6990 | + rbd_dev->header.image_size = header->image_size; | |
| 6991 | + | |
| 6992 | + if (!rbd_is_snap(rbd_dev)) { | |
| 6993 | + rbd_dev->mapping.size = header->image_size; | |
| 6994 | + rbd_dev_update_size(rbd_dev); | |
| 6995 | + } | |
| 6996 | + } | |
| 6997 | + | |
| 6998 | + ceph_put_snap_context(rbd_dev->header.snapc); | |
| 6999 | + rbd_dev->header.snapc = header->snapc; | |
| 7000 | + header->snapc = NULL; | |
| 7001 | + | |
| 7002 | + if (rbd_dev->image_format == 1) { | |
| 7003 | + kfree(rbd_dev->header.snap_names); | |
| 7004 | + rbd_dev->header.snap_names = header->snap_names; | |
| 7005 | + header->snap_names = NULL; | |
| 7006 | + | |
| 7007 | + kfree(rbd_dev->header.snap_sizes); | |
| 7008 | + rbd_dev->header.snap_sizes = header->snap_sizes; | |
| 7009 | + header->snap_sizes = NULL; | |
| 7010 | + } | |
| 7011 | +} | |
| 7012 | + | |
| 7013 | +static void rbd_dev_update_parent(struct rbd_device *rbd_dev, | |
| 7014 | + struct parent_image_info *pii) | |
| 7015 | +{ | |
| 7016 | + if (pii->pool_id == CEPH_NOPOOL || !pii->has_overlap) { | |
| 7017 | + /* | |
| 7018 | + * Either the parent never existed, or we have | |
| 7019 | + * record of it but the image got flattened so it no | |
| 7020 | + * longer has a parent. When the parent of a | |
| 7021 | + * layered image disappears we immediately set the | |
| 7022 | + * overlap to 0. The effect of this is that all new | |
| 7023 | + * requests will be treated as if the image had no | |
| 7024 | + * parent. | |
| 7025 | + * | |
| 7026 | + * If !pii.has_overlap, the parent image spec is not | |
| 7027 | + * applicable. It's there to avoid duplication in each | |
| 7028 | + * snapshot record. | |
| 7029 | + */ | |
| 7030 | + if (rbd_dev->parent_overlap) { | |
| 7031 | + rbd_dev->parent_overlap = 0; | |
| 7032 | + rbd_dev_parent_put(rbd_dev); | |
| 7033 | + pr_info("%s: clone has been flattened\n", | |
| 7034 | + rbd_dev->disk->disk_name); | |
| 7035 | + } | |
| 7036 | + } else { | |
| 7037 | + rbd_assert(rbd_dev->parent_spec); | |
| 7038 | + | |
| 7039 | + /* | |
| 7040 | + * Update the parent overlap. If it became zero, issue | |
| 7041 | + * a warning as we will proceed as if there is no parent. | |
| 7042 | + */ | |
| 7043 | + if (!pii->overlap && rbd_dev->parent_overlap) | |
| 7044 | + rbd_warn(rbd_dev, | |
| 7045 | + "clone has become standalone (overlap 0)"); | |
| 7046 | + rbd_dev->parent_overlap = pii->overlap; | |
| 7047 | + } | |
| 7048 | +} | |
| 7049 | + | |
| 7050 | +static int rbd_dev_refresh(struct rbd_device *rbd_dev) | |
| 7051 | +{ | |
| 7052 | + struct rbd_image_header header = { 0 }; | |
| 7053 | + struct parent_image_info pii = { 0 }; | |
| 7054 | + int ret; | |
| 7055 | + | |
| 7056 | + dout("%s rbd_dev %p\n", __func__, rbd_dev); | |
| 7057 | + | |
| 7058 | + ret = rbd_dev_header_info(rbd_dev, &header, false); | |
| 7059 | + if (ret) | |
| 7060 | + goto out; | |
| 7061 | + | |
| 7062 | + /* | |
| 7063 | + * If there is a parent, see if it has disappeared due to the | |
| 7064 | + * mapped image getting flattened. | |
| 7065 | + */ | |
| 7066 | + if (rbd_dev->parent) { | |
| 7067 | + ret = rbd_dev_v2_parent_info(rbd_dev, &pii); | |
| 7068 | + if (ret) | |
| 7069 | + goto out; | |
| 7070 | + } | |
| 7071 | + | |
| 7072 | + down_write(&rbd_dev->header_rwsem); | |
| 7073 | + rbd_dev_update_header(rbd_dev, &header); | |
| 7074 | + if (rbd_dev->parent) | |
| 7075 | + rbd_dev_update_parent(rbd_dev, &pii); | |
| 7076 | + up_write(&rbd_dev->header_rwsem); | |
| 7077 | + | |
| 7078 | +out: | |
| 7079 | + rbd_parent_info_cleanup(&pii); | |
| 7080 | + rbd_image_header_cleanup(&header); | |
| 7081 | + return ret; | |
| 7082 | +} | |
| 7083 | + | |
| 7046 | 7084 | static ssize_t do_rbd_add(const char *buf, size_t count) |
| 7047 | 7085 | { |
| 7048 | 7086 | struct rbd_device *rbd_dev = NULL; |
| @@ -4419,6 +4419,7 @@ static int btusb_probe(struct usb_interface *intf, · 4418 unmodified lines | ||
| 4419 | 4419 | |
| 4420 | 4420 | if (id->driver_info & BTUSB_QCA_ROME) { |
| 4421 | 4421 | data->setup_on_usb = btusb_setup_qca; |
| 4422 | + hdev->shutdown = btusb_shutdown_qca; | |
| 4422 | 4423 | hdev->set_bdaddr = btusb_set_bdaddr_ath3012; |
| 4423 | 4424 | hdev->cmd_timeout = btusb_qca_cmd_timeout; |
| 4424 | 4425 | set_bit(HCI_QUIRK_SIMULTANEOUS_DISCOVERY, &hdev->quirks); |
| @@ -38,6 +38,7 @@ enum sysc_soc { · 37 unmodified lines | ||
| 38 | 38 | SOC_2420, |
| 39 | 39 | SOC_2430, |
| 40 | 40 | SOC_3430, |
| 41 | + SOC_AM35, | |
| 41 | 42 | SOC_3630, |
| 42 | 43 | SOC_4430, |
| 43 | 44 | SOC_4460, |
| @@ -1097,6 +1098,11 @@ static int sysc_enable_module(struct device *dev) · 1053 unmodified lines | ||
| 1097 | 1098 | if (ddata->cfg.quirks & (SYSC_QUIRK_SWSUP_SIDLE | |
| 1098 | 1099 | SYSC_QUIRK_SWSUP_SIDLE_ACT)) { |
| 1099 | 1100 | best_mode = SYSC_IDLE_NO; |
| 1101 | + | |
| 1102 | + /* Clear WAKEUP */ | |
| 1103 | + if (regbits->enwkup_shift >= 0 && | |
| 1104 | + ddata->cfg.sysc_val & BIT(regbits->enwkup_shift)) | |
| 1105 | + reg &= ~BIT(regbits->enwkup_shift); | |
| 1100 | 1106 | } else { |
| 1101 | 1107 | best_mode = fls(ddata->cfg.sidlemodes) - 1; |
| 1102 | 1108 | if (best_mode > SYSC_IDLE_MASK) { |
| @@ -1224,6 +1230,13 @@ set_sidle: · 121 unmodified lines | ||
| 1224 | 1230 | } |
| 1225 | 1231 | } |
| 1226 | 1232 | |
| 1233 | + if (ddata->cfg.quirks & SYSC_QUIRK_SWSUP_SIDLE_ACT) { | |
| 1234 | + /* Set WAKEUP */ | |
| 1235 | + if (regbits->enwkup_shift >= 0 && | |
| 1236 | + ddata->cfg.sysc_val & BIT(regbits->enwkup_shift)) | |
| 1237 | + reg |= BIT(regbits->enwkup_shift); | |
| 1238 | + } | |
| 1239 | + | |
| 1227 | 1240 | reg &= ~(SYSC_IDLE_MASK << regbits->sidle_shift); |
| 1228 | 1241 | reg |= best_mode << regbits->sidle_shift; |
| 1229 | 1242 | if (regbits->autoidle_shift >= 0 && |
| @@ -1518,16 +1531,16 @@ struct sysc_revision_quirk { · 288 unmodified lines | ||
| 1518 | 1531 | static const struct sysc_revision_quirk sysc_revision_quirks[] = { |
| 1519 | 1532 | /* These drivers need to be fixed to not use pm_runtime_irq_safe() */ |
| 1520 | 1533 | SYSC_QUIRK("uart", 0, 0x50, 0x54, 0x58, 0x00000046, 0xffffffff, |
| 1521 | − SYSC_QUIRK_SWSUP_SIDLE | SYSC_QUIRK_LEGACY_IDLE), | |
| 1534 | + SYSC_QUIRK_SWSUP_SIDLE_ACT | SYSC_QUIRK_LEGACY_IDLE), | |
| 1522 | 1535 | SYSC_QUIRK("uart", 0, 0x50, 0x54, 0x58, 0x00000052, 0xffffffff, |
| 1523 | − SYSC_QUIRK_SWSUP_SIDLE | SYSC_QUIRK_LEGACY_IDLE), | |
| 1536 | + SYSC_QUIRK_SWSUP_SIDLE_ACT | SYSC_QUIRK_LEGACY_IDLE), | |
| 1524 | 1537 | /* Uarts on omap4 and later */ |
| 1525 | 1538 | SYSC_QUIRK("uart", 0, 0x50, 0x54, 0x58, 0x50411e03, 0xffff00ff, |
| 1526 | − SYSC_QUIRK_SWSUP_SIDLE | SYSC_QUIRK_LEGACY_IDLE), | |
| 1539 | + SYSC_QUIRK_SWSUP_SIDLE_ACT | SYSC_QUIRK_LEGACY_IDLE), | |
| 1527 | 1540 | SYSC_QUIRK("uart", 0, 0x50, 0x54, 0x58, 0x47422e03, 0xffffffff, |
| 1528 | − SYSC_QUIRK_SWSUP_SIDLE | SYSC_QUIRK_LEGACY_IDLE), | |
| 1541 | + SYSC_QUIRK_SWSUP_SIDLE_ACT | SYSC_QUIRK_LEGACY_IDLE), | |
| 1529 | 1542 | SYSC_QUIRK("uart", 0, 0x50, 0x54, 0x58, 0x47424e03, 0xffffffff, |
| 1530 | − SYSC_QUIRK_SWSUP_SIDLE | SYSC_QUIRK_LEGACY_IDLE), | |
| 1543 | + SYSC_QUIRK_SWSUP_SIDLE_ACT | SYSC_QUIRK_LEGACY_IDLE), | |
| 1531 | 1544 | |
| 1532 | 1545 | /* Quirks that need to be set based on the module address */ |
| 1533 | 1546 | SYSC_QUIRK("mcpdm", 0x40132000, 0, 0x10, -ENODEV, 0x50000800, 0xffffffff, |
| @@ -1862,7 +1875,7 @@ static void sysc_pre_reset_quirk_dss(struct sysc *ddata) · 328 unmodified lines | ||
| 1862 | 1875 | dev_warn(ddata->dev, "%s: timed out %08x !+ %08x\n", |
| 1863 | 1876 | __func__, val, irq_mask); |
| 1864 | 1877 | |
| 1865 | − if (sysc_soc->soc == SOC_3430) { | |
| 1878 | + if (sysc_soc->soc == SOC_3430 || sysc_soc->soc == SOC_AM35) { | |
| 1866 | 1879 | /* Clear DSS_SDI_CONTROL */ |
| 1867 | 1880 | sysc_write(ddata, 0x44, 0); |
| 1868 | 1881 | |
| @@ -2150,8 +2163,7 @@ static int sysc_reset(struct sysc *ddata) · 281 unmodified lines | ||
| 2150 | 2163 | } |
| 2151 | 2164 | |
| 2152 | 2165 | if (ddata->cfg.srst_udelay) |
| 2153 | − usleep_range(ddata->cfg.srst_udelay, | |
| 2154 | − ddata->cfg.srst_udelay * 2); | |
| 2166 | + fsleep(ddata->cfg.srst_udelay); | |
| 2155 | 2167 | |
| 2156 | 2168 | if (ddata->post_reset_quirk) |
| 2157 | 2169 | ddata->post_reset_quirk(ddata); |
| @@ -3025,6 +3037,7 @@ static void ti_sysc_idle(struct work_struct *work) · 867 unmodified lines | ||
| 3025 | 3037 | static const struct soc_device_attribute sysc_soc_match[] = { |
| 3026 | 3038 | SOC_FLAG("OMAP242*", SOC_2420), |
| 3027 | 3039 | SOC_FLAG("OMAP243*", SOC_2430), |
| 3040 | + SOC_FLAG("AM35*", SOC_AM35), | |
| 3028 | 3041 | SOC_FLAG("OMAP3[45]*", SOC_3430), |
| 3029 | 3042 | SOC_FLAG("OMAP3[67]*", SOC_3630), |
| 3030 | 3043 | SOC_FLAG("OMAP443*", SOC_4430), |
| @@ -3229,7 +3242,7 @@ static int sysc_check_active_timer(struct sysc *ddata) · 198 unmodified lines | ||
| 3229 | 3242 | * can be dropped if we stop supporting old beagleboard revisions |
| 3230 | 3243 | * A to B4 at some point. |
| 3231 | 3244 | */ |
| 3232 | − if (sysc_soc->soc == SOC_3430) | |
| 3245 | + if (sysc_soc->soc == SOC_3430 || sysc_soc->soc == SOC_AM35) | |
| 3233 | 3246 | error = -ENXIO; |
| 3234 | 3247 | else |
| 3235 | 3248 | error = -EBUSY; |
| @@ -96,7 +96,7 @@ static int si521xx_regmap_i2c_write(void *context, unsigned int reg, · 95 unmodified lines | ||
| 96 | 96 | unsigned int val) |
| 97 | 97 | { |
| 98 | 98 | struct i2c_client *i2c = context; |
| 99 | − const u8 data[3] = { reg, 1, val }; | |
| 99 | + const u8 data[2] = { reg, val }; | |
| 100 | 100 | const int count = ARRAY_SIZE(data); |
| 101 | 101 | int ret; |
| 102 | 102 | |
| @@ -146,7 +146,7 @@ static int si521xx_regmap_i2c_read(void *context, unsigned int reg, · 43 unmodified lines | ||
| 146 | 146 | static const struct regmap_config si521xx_regmap_config = { |
| 147 | 147 | .reg_bits = 8, |
| 148 | 148 | .val_bits = 8, |
| 149 | − .cache_type = REGCACHE_NONE, | |
| 149 | + .cache_type = REGCACHE_FLAT, | |
| 150 | 150 | .max_register = SI521XX_REG_DA, |
| 151 | 151 | .rd_table = &si521xx_readable_table, |
| 152 | 152 | .wr_table = &si521xx_writeable_table, |
| @@ -281,9 +281,10 @@ static int si521xx_probe(struct i2c_client *client) · 128 unmodified lines | ||
| 281 | 281 | { |
| 282 | 282 | const u16 chip_info = (u16)(uintptr_t)device_get_match_data(&client->dev); |
| 283 | 283 | const struct clk_parent_data clk_parent_data = { .index = 0 }; |
| 284 | − struct si521xx *si; | |
| 284 | + const u8 data[3] = { SI521XX_REG_BC, 1, 1 }; | |
| 285 | 285 | unsigned char name[6] = "DIFF0"; |
| 286 | 286 | struct clk_init_data init = {}; |
| 287 | + struct si521xx *si; | |
| 287 | 288 | int i, ret; |
| 288 | 289 | |
| 289 | 290 | if (!chip_info) |
| @@ -308,7 +309,7 @@ static int si521xx_probe(struct i2c_client *client) · 18 unmodified lines | ||
| 308 | 309 | "Failed to allocate register map\n"); |
| 309 | 310 | |
| 310 | 311 | /* Always read back 1 Byte via I2C */ |
| 311 | − ret = regmap_write(si->regmap, SI521XX_REG_BC, 1); | |
| 312 | + ret = i2c_master_send(client, data, ARRAY_SIZE(data)); | |
| 312 | 313 | if (ret < 0) |
| 313 | 314 | return ret; |
| 314 | 315 | |
| @@ -118,21 +118,21 @@ enum vc3_div { · 117 unmodified lines | ||
| 118 | 118 | VC3_DIV5, |
| 119 | 119 | }; |
| 120 | 120 | |
| 121 | −enum vc3_clk_mux { | |
| 122 | − VC3_DIFF2_MUX, | |
| 123 | − VC3_DIFF1_MUX, | |
| 124 | − VC3_SE3_MUX, | |
| 125 | − VC3_SE2_MUX, | |
| 126 | − VC3_SE1_MUX, | |
| 127 | −}; | |
| 128 | − | |
| 129 | 121 | enum vc3_clk { |
| 130 | − VC3_DIFF2, | |
| 131 | − VC3_DIFF1, | |
| 132 | − VC3_SE3, | |
| 133 | − VC3_SE2, | |
| 134 | − VC3_SE1, | |
| 135 | 122 | VC3_REF, |
| 123 | + VC3_SE1, | |
| 124 | + VC3_SE2, | |
| 125 | + VC3_SE3, | |
| 126 | + VC3_DIFF1, | |
| 127 | + VC3_DIFF2, | |
| 128 | +}; | |
| 129 | + | |
| 130 | +enum vc3_clk_mux { | |
| 131 | + VC3_SE1_MUX = VC3_SE1 - 1, | |
| 132 | + VC3_SE2_MUX = VC3_SE2 - 1, | |
| 133 | + VC3_SE3_MUX = VC3_SE3 - 1, | |
| 134 | + VC3_DIFF1_MUX = VC3_DIFF1 - 1, | |
| 135 | + VC3_DIFF2_MUX = VC3_DIFF2 - 1, | |
| 136 | 136 | }; |
| 137 | 137 | |
| 138 | 138 | struct vc3_clk_data { |
| @@ -401,11 +401,10 @@ static long vc3_pll_round_rate(struct clk_hw *hw, unsigned long rate, · 262 unmodified lines | ||
| 401 | 401 | /* Determine best fractional part, which is 16 bit wide */ |
| 402 | 402 | div_frc = rate % *parent_rate; |
| 403 | 403 | div_frc *= BIT(16) - 1; |
| 404 | − do_div(div_frc, *parent_rate); | |
| 405 | 404 | |
| 406 | − vc3->div_frc = (u32)div_frc; | |
| 405 | + vc3->div_frc = min_t(u64, div64_ul(div_frc, *parent_rate), U16_MAX); | |
| 407 | 406 | rate = (*parent_rate * |
| 408 | − (vc3->div_int * VC3_2_POW_16 + div_frc) / VC3_2_POW_16); | |
| 407 | + (vc3->div_int * VC3_2_POW_16 + vc3->div_frc) / VC3_2_POW_16); | |
| 409 | 408 | } else { |
| 410 | 409 | rate = *parent_rate * vc3->div_int; |
| 411 | 410 | } |
| @@ -897,33 +896,33 @@ static struct vc3_hw_data clk_div[] = { · 485 unmodified lines | ||
| 897 | 896 | }; |
| 898 | 897 | |
| 899 | 898 | static struct vc3_hw_data clk_mux[] = { |
| 900 | − [VC3_DIFF2_MUX] = { | |
| 899 | + [VC3_SE1_MUX] = { | |
| 901 | 900 | .data = &(struct vc3_clk_data) { |
| 902 | − .offs = VC3_DIFF2_CTRL_REG, | |
| 903 | − .bitmsk = VC3_DIFF2_CTRL_REG_DIFF2_CLK_SEL | |
| 901 | + .offs = VC3_SE1_DIV4_CTRL, | |
| 902 | + .bitmsk = VC3_SE1_DIV4_CTRL_SE1_CLK_SEL | |
| 904 | 903 | }, |
| 905 | 904 | .hw.init = &(struct clk_init_data){ |
| 906 | − .name = "diff2_mux", | |
| 905 | + .name = "se1_mux", | |
| 907 | 906 | .ops = &vc3_clk_mux_ops, |
| 908 | 907 | .parent_hws = (const struct clk_hw *[]) { |
| 909 | − &clk_div[VC3_DIV1].hw, | |
| 910 | − &clk_div[VC3_DIV3].hw | |
| 908 | + &clk_div[VC3_DIV5].hw, | |
| 909 | + &clk_div[VC3_DIV4].hw | |
| 911 | 910 | }, |
| 912 | 911 | .num_parents = 2, |
| 913 | 912 | .flags = CLK_SET_RATE_PARENT |
| 914 | 913 | } |
| 915 | 914 | }, |
| 916 | − [VC3_DIFF1_MUX] = { | |
| 915 | + [VC3_SE2_MUX] = { | |
| 917 | 916 | .data = &(struct vc3_clk_data) { |
| 918 | − .offs = VC3_DIFF1_CTRL_REG, | |
| 919 | − .bitmsk = VC3_DIFF1_CTRL_REG_DIFF1_CLK_SEL | |
| 917 | + .offs = VC3_SE2_CTRL_REG0, | |
| 918 | + .bitmsk = VC3_SE2_CTRL_REG0_SE2_CLK_SEL | |
| 920 | 919 | }, |
| 921 | 920 | .hw.init = &(struct clk_init_data){ |
| 922 | − .name = "diff1_mux", | |
| 921 | + .name = "se2_mux", | |
| 923 | 922 | .ops = &vc3_clk_mux_ops, |
| 924 | 923 | .parent_hws = (const struct clk_hw *[]) { |
| 925 | − &clk_div[VC3_DIV1].hw, | |
| 926 | − &clk_div[VC3_DIV3].hw | |
| 924 | + &clk_div[VC3_DIV5].hw, | |
| 925 | + &clk_div[VC3_DIV4].hw | |
| 927 | 926 | }, |
| 928 | 927 | .num_parents = 2, |
| 929 | 928 | .flags = CLK_SET_RATE_PARENT |
| @@ -945,33 +944,33 @@ static struct vc3_hw_data clk_mux[] = { · 15 unmodified lines | ||
| 945 | 944 | .flags = CLK_SET_RATE_PARENT |
| 946 | 945 | } |
| 947 | 946 | }, |
| 948 | − [VC3_SE2_MUX] = { | |
| 947 | + [VC3_DIFF1_MUX] = { | |
| 949 | 948 | .data = &(struct vc3_clk_data) { |
| 950 | − .offs = VC3_SE2_CTRL_REG0, | |
| 951 | − .bitmsk = VC3_SE2_CTRL_REG0_SE2_CLK_SEL | |
| 949 | + .offs = VC3_DIFF1_CTRL_REG, | |
| 950 | + .bitmsk = VC3_DIFF1_CTRL_REG_DIFF1_CLK_SEL | |
| 952 | 951 | }, |
| 953 | 952 | .hw.init = &(struct clk_init_data){ |
| 954 | − .name = "se2_mux", | |
| 953 | + .name = "diff1_mux", | |
| 955 | 954 | .ops = &vc3_clk_mux_ops, |
| 956 | 955 | .parent_hws = (const struct clk_hw *[]) { |
| 957 | − &clk_div[VC3_DIV5].hw, | |
| 958 | − &clk_div[VC3_DIV4].hw | |
| 956 | + &clk_div[VC3_DIV1].hw, | |
| 957 | + &clk_div[VC3_DIV3].hw | |
| 959 | 958 | }, |
| 960 | 959 | .num_parents = 2, |
| 961 | 960 | .flags = CLK_SET_RATE_PARENT |
| 962 | 961 | } |
| 963 | 962 | }, |
| 964 | − [VC3_SE1_MUX] = { | |
| 963 | + [VC3_DIFF2_MUX] = { | |
| 965 | 964 | .data = &(struct vc3_clk_data) { |
| 966 | − .offs = VC3_SE1_DIV4_CTRL, | |
| 967 | − .bitmsk = VC3_SE1_DIV4_CTRL_SE1_CLK_SEL | |
| 965 | + .offs = VC3_DIFF2_CTRL_REG, | |
| 966 | + .bitmsk = VC3_DIFF2_CTRL_REG_DIFF2_CLK_SEL | |
| 968 | 967 | }, |
| 969 | 968 | .hw.init = &(struct clk_init_data){ |
| 970 | − .name = "se1_mux", | |
| 969 | + .name = "diff2_mux", | |
| 971 | 970 | .ops = &vc3_clk_mux_ops, |
| 972 | 971 | .parent_hws = (const struct clk_hw *[]) { |
| 973 | − &clk_div[VC3_DIV5].hw, | |
| 974 | − &clk_div[VC3_DIV4].hw | |
| 972 | + &clk_div[VC3_DIV1].hw, | |
| 973 | + &clk_div[VC3_DIV3].hw | |
| 975 | 974 | }, |
| 976 | 975 | .num_parents = 2, |
| 977 | 976 | .flags = CLK_SET_RATE_PARENT |
| @@ -1110,7 +1109,7 @@ static int vc3_probe(struct i2c_client *client) · 132 unmodified lines | ||
| 1110 | 1109 | name, 0, CLK_SET_RATE_PARENT, 1, 1); |
| 1111 | 1110 | else |
| 1112 | 1111 | clk_out[i] = devm_clk_hw_register_fixed_factor_parent_hw(dev, |
| 1113 | − name, &clk_mux[i].hw, CLK_SET_RATE_PARENT, 1, 1); | |
| 1112 | + name, &clk_mux[i - 1].hw, CLK_SET_RATE_PARENT, 1, 1); | |
| 1114 | 1113 | |
| 1115 | 1114 | if (IS_ERR(clk_out[i])) |
| 1116 | 1115 | return PTR_ERR(clk_out[i]); |
| @@ -800,7 +800,7 @@ static SPRD_MUX_CLK_DATA(uart1_clk, "uart1-clk", uart_parents, · 799 unmodified lines | ||
| 800 | 800 | 0x250, 0, 3, UMS512_MUX_FLAG); |
| 801 | 801 | |
| 802 | 802 | static const struct clk_parent_data thm_parents[] = { |
| 803 | − { .fw_name = "ext-32m" }, | |
| 803 | + { .fw_name = "ext-32k" }, | |
| 804 | 804 | { .hw = &clk_250k.hw }, |
| 805 | 805 | }; |
| 806 | 806 | static SPRD_MUX_CLK_DATA(thm0_clk, "thm0-clk", thm_parents, |
| @@ -159,7 +159,7 @@ static unsigned long tegra_bpmp_clk_recalc_rate(struct clk_hw *hw, · 158 unmodified lines | ||
| 159 | 159 | |
| 160 | 160 | err = tegra_bpmp_clk_transfer(clk->bpmp, &msg); |
| 161 | 161 | if (err < 0) |
| 162 | − return err; | |
| 162 | + return 0; | |
| 163 | 163 | |
| 164 | 164 | return response.rate; |
| 165 | 165 | } |
| @@ -14,7 +14,7 @@ · 13 unmodified lines | ||
| 14 | 14 | |
| 15 | 15 | struct cxl_cxims_data { |
| 16 | 16 | int nr_maps; |
| 17 | − u64 xormaps[]; | |
| 17 | + u64 xormaps[] __counted_by(nr_maps); | |
| 18 | 18 | }; |
| 19 | 19 | |
| 20 | 20 | /* |
| @@ -112,9 +112,9 @@ static int cxl_parse_cxims(union acpi_subtable_headers *header, void *arg, · 91 unmodified lines | ||
| 112 | 112 | GFP_KERNEL); |
| 113 | 113 | if (!cximsd) |
| 114 | 114 | return -ENOMEM; |
| 115 | + cximsd->nr_maps = nr_maps; | |
| 115 | 116 | memcpy(cximsd->xormaps, cxims->xormap_list, |
| 116 | 117 | nr_maps * sizeof(*cximsd->xormaps)); |
| 117 | − cximsd->nr_maps = nr_maps; | |
| 118 | 118 | cxlrd->platform_data = cximsd; |
| 119 | 119 | |
| 120 | 120 | return 0; |
| @@ -715,24 +715,25 @@ static void cxl_walk_cel(struct cxl_memdev_state *mds, size_t size, u8 *cel) · 714 unmodified lines | ||
| 715 | 715 | for (i = 0; i < cel_entries; i++) { |
| 716 | 716 | u16 opcode = le16_to_cpu(cel_entry[i].opcode); |
| 717 | 717 | struct cxl_mem_command *cmd = cxl_mem_find_command(opcode); |
| 718 | + int enabled = 0; | |
| 718 | 719 | |
| 719 | − if (!cmd && (!cxl_is_poison_command(opcode) || | |
| 720 | − !cxl_is_security_command(opcode))) { | |
| 721 | − dev_dbg(dev, | |
| 722 | − "Opcode 0x%04x unsupported by driver\n", opcode); | |
| 723 | − continue; | |
| 724 | − } | |
| 725 | − | |
| 726 | − if (cmd) | |
| 720 | + if (cmd) { | |
| 727 | 721 | set_bit(cmd->info.id, mds->enabled_cmds); |
| 722 | + enabled++; | |
| 723 | + } | |
| 728 | 724 | |
| 729 | − if (cxl_is_poison_command(opcode)) | |
| 725 | + if (cxl_is_poison_command(opcode)) { | |
| 730 | 726 | cxl_set_poison_cmd_enabled(&mds->poison, opcode); |
| 727 | + enabled++; | |
| 728 | + } | |
| 731 | 729 | |
| 732 | − if (cxl_is_security_command(opcode)) | |
| 730 | + if (cxl_is_security_command(opcode)) { | |
| 733 | 731 | cxl_set_security_cmd_enabled(&mds->security, opcode); |
| 732 | + enabled++; | |
| 733 | + } | |
| 734 | 734 | |
| 735 | − dev_dbg(dev, "Opcode 0x%04x enabled\n", opcode); | |
| 735 | + dev_dbg(dev, "Opcode 0x%04x %s\n", opcode, | |
| 736 | + enabled ? "enabled" : "unsupported by driver"); | |
| 736 | 737 | } |
| 737 | 738 | } |
| 738 | 739 | |
| @@ -1,5 +1,6 @@ | ||
| 1 | 1 | // SPDX-License-Identifier: GPL-2.0-only |
| 2 | 2 | /* Copyright(c) 2020 Intel Corporation. All rights reserved. */ |
| 3 | +#include <linux/platform_device.h> | |
| 3 | 4 | #include <linux/memregion.h> |
| 4 | 5 | #include <linux/workqueue.h> |
| 5 | 6 | #include <linux/debugfs.h> |
| @@ -706,16 +707,20 @@ static int cxl_setup_comp_regs(struct device *dev, struct cxl_register_map *map, · 700 unmodified lines | ||
| 706 | 707 | return cxl_setup_regs(map); |
| 707 | 708 | } |
| 708 | 709 | |
| 709 | −static inline int cxl_port_setup_regs(struct cxl_port *port, | |
| 710 | − resource_size_t component_reg_phys) | |
| 710 | +static int cxl_port_setup_regs(struct cxl_port *port, | |
| 711 | + resource_size_t component_reg_phys) | |
| 711 | 712 | { |
| 713 | + if (dev_is_platform(port->uport_dev)) | |
| 714 | + return 0; | |
| 712 | 715 | return cxl_setup_comp_regs(&port->dev, &port->comp_map, |
| 713 | 716 | component_reg_phys); |
| 714 | 717 | } |
| 715 | 718 | |
| 716 | −static inline int cxl_dport_setup_regs(struct cxl_dport *dport, | |
| 717 | − resource_size_t component_reg_phys) | |
| 719 | +static int cxl_dport_setup_regs(struct cxl_dport *dport, | |
| 720 | + resource_size_t component_reg_phys) | |
| 718 | 721 | { |
| 722 | + if (dev_is_platform(dport->dport_dev)) | |
| 723 | + return 0; | |
| 719 | 724 | return cxl_setup_comp_regs(dport->dport_dev, &dport->comp_map, |
| 720 | 725 | component_reg_phys); |
| 721 | 726 | } |
| @@ -717,13 +717,35 @@ static int match_free_decoder(struct device *dev, void *data) · 716 unmodified lines | ||
| 717 | 717 | return 0; |
| 718 | 718 | } |
| 719 | 719 | |
| 720 | +static int match_auto_decoder(struct device *dev, void *data) | |
| 721 | +{ | |
| 722 | + struct cxl_region_params *p = data; | |
| 723 | + struct cxl_decoder *cxld; | |
| 724 | + struct range *r; | |
| 725 | + | |
| 726 | + if (!is_switch_decoder(dev)) | |
| 727 | + return 0; | |
| 728 | + | |
| 729 | + cxld = to_cxl_decoder(dev); | |
| 730 | + r = &cxld->hpa_range; | |
| 731 | + | |
| 732 | + if (p->res && p->res->start == r->start && p->res->end == r->end) | |
| 733 | + return 1; | |
| 734 | + | |
| 735 | + return 0; | |
| 736 | +} | |
| 737 | + | |
| 720 | 738 | static struct cxl_decoder *cxl_region_find_decoder(struct cxl_port *port, |
| 721 | 739 | struct cxl_region *cxlr) |
| 722 | 740 | { |
| 723 | 741 | struct device *dev; |
| 724 | 742 | int id = 0; |
| 725 | 743 | |
| 726 | − dev = device_find_child(&port->dev, &id, match_free_decoder); | |
| 744 | + if (test_bit(CXL_REGION_F_AUTO, &cxlr->flags)) | |
| 745 | + dev = device_find_child(&port->dev, &cxlr->params, | |
| 746 | + match_auto_decoder); | |
| 747 | + else | |
| 748 | + dev = device_find_child(&port->dev, &id, match_free_decoder); | |
| 727 | 749 | if (!dev) |
| 728 | 750 | return NULL; |
| 729 | 751 | /* |
| @@ -1154,16 +1176,15 @@ static int cxl_port_setup_targets(struct cxl_port *port, · 424 unmodified lines | ||
| 1154 | 1176 | } |
| 1155 | 1177 | |
| 1156 | 1178 | /* |
| 1157 | − * If @parent_port is masking address bits, pick the next unused address | |
| 1158 | − * bit to route @port's targets. | |
| 1179 | + * Interleave granularity is a multiple of @parent_port granularity. | |
| 1180 | + * Multiplier is the parent port interleave ways. | |
| 1159 | 1181 | */ |
| 1160 | − if (parent_iw > 1 && cxl_rr->nr_targets > 1) { | |
| 1161 | − u32 address_bit = max(peig + peiw, eiw + peig); | |
| 1162 | − | |
| 1163 | − eig = address_bit - eiw + 1; | |
| 1164 | − } else { | |
| 1165 | − eiw = peiw; | |
| 1166 | − eig = peig; | |
| 1182 | + rc = granularity_to_eig(parent_ig * parent_iw, &eig); | |
| 1183 | + if (rc) { | |
| 1184 | + dev_dbg(&cxlr->dev, | |
| 1185 | + "%s: invalid granularity calculation (%d * %d)\n", | |
| 1186 | + dev_name(&parent_port->dev), parent_ig, parent_iw); | |
| 1187 | + return rc; | |
| 1167 | 1188 | } |
| 1168 | 1189 | |
| 1169 | 1190 | rc = eig_to_granularity(eig, &ig); |
| @@ -529,7 +529,6 @@ static int cxl_pci_setup_regs(struct pci_dev *pdev, enum cxl_regloc_type type, · 528 unmodified lines | ||
| 529 | 529 | |
| 530 | 530 | static int cxl_pci_ras_unmask(struct pci_dev *pdev) |
| 531 | 531 | { |
| 532 | − struct pci_host_bridge *host_bridge = pci_find_host_bridge(pdev->bus); | |
| 533 | 532 | struct cxl_dev_state *cxlds = pci_get_drvdata(pdev); |
| 534 | 533 | void __iomem *addr; |
| 535 | 534 | u32 orig_val, val, mask; |
| @@ -541,9 +540,9 @@ static int cxl_pci_ras_unmask(struct pci_dev *pdev) · 5 unmodified lines | ||
| 541 | 540 | return 0; |
| 542 | 541 | } |
| 543 | 542 | |
| 544 | − /* BIOS has CXL error control */ | |
| 545 | − if (!host_bridge->native_cxl_error) | |
| 546 | − return -ENXIO; | |
| 543 | + /* BIOS has PCIe AER error control */ | |
| 544 | + if (!pcie_aer_is_native(pdev)) | |
| 545 | + return 0; | |
| 547 | 546 | |
| 548 | 547 | rc = pcie_capability_read_word(pdev, PCI_EXP_DEVCTL, &cap); |
| 549 | 548 | if (rc) |
| @@ -558,6 +558,9 @@ int k3_udma_glue_tx_get_irq(struct k3_udma_glue_tx_channel *tx_chn) · 557 unmodified lines | ||
| 558 | 558 | tx_chn->virq = k3_ringacc_get_ring_irq_num(tx_chn->ringtxcq); |
| 559 | 559 | } |
| 560 | 560 | |
| 561 | + if (!tx_chn->virq) | |
| 562 | + return -ENXIO; | |
| 563 | + | |
| 561 | 564 | return tx_chn->virq; |
| 562 | 565 | } |
| 563 | 566 | EXPORT_SYMBOL_GPL(k3_udma_glue_tx_get_irq); |
| @@ -81,7 +81,8 @@ MODULE_PARM_DESC(exclusive_login, "Exclusive login to sbp2 device " · 80 unmodified lines | ||
| 81 | 81 | * |
| 82 | 82 | * - power condition |
| 83 | 83 | * Set the power condition field in the START STOP UNIT commands sent by |
| 84 | − * sd_mod on suspend, resume, and shutdown (if manage_start_stop is on). | |
| 84 | + * sd_mod on suspend, resume, and shutdown (if manage_system_start_stop or | |
| 85 | + * manage_runtime_start_stop is on). | |
| 85 | 86 | * Some disks need this to spin down or to resume properly. |
| 86 | 87 | * |
| 87 | 88 | * - override internal blacklist |
| @@ -1517,8 +1518,10 @@ static int sbp2_scsi_slave_configure(struct scsi_device *sdev) · 1429 unmodified lines | ||
| 1517 | 1518 | |
| 1518 | 1519 | sdev->use_10_for_rw = 1; |
| 1519 | 1520 | |
| 1520 | − if (sbp2_param_exclusive_login) | |
| 1521 | − sdev->manage_start_stop = 1; | |
| 1521 | + if (sbp2_param_exclusive_login) { | |
| 1522 | + sdev->manage_system_start_stop = true; | |
| 1523 | + sdev->manage_runtime_start_stop = true; | |
| 1524 | + } | |
| 1522 | 1525 | |
| 1523 | 1526 | if (sdev->type == TYPE_ROM) |
| 1524 | 1527 | sdev->use_10_for_ms = 1; |
| @@ -397,6 +397,19 @@ static u32 ffa_get_num_pages_sg(struct scatterlist *sg) · 396 unmodified lines | ||
| 397 | 397 | return num_pages; |
| 398 | 398 | } |
| 399 | 399 | |
| 400 | +static u8 ffa_memory_attributes_get(u32 func_id) | |
| 401 | +{ | |
| 402 | + /* | |
| 403 | + * For the memory lend or donate operation, if the receiver is a PE or | |
| 404 | + * a proxy endpoint, the owner/sender must not specify the attributes | |
| 405 | + */ | |
| 406 | + if (func_id == FFA_FN_NATIVE(MEM_LEND) || | |
| 407 | + func_id == FFA_MEM_LEND) | |
| 408 | + return 0; | |
| 409 | + | |
| 410 | + return FFA_MEM_NORMAL | FFA_MEM_WRITE_BACK | FFA_MEM_INNER_SHAREABLE; | |
| 411 | +} | |
| 412 | + | |
| 400 | 413 | static int |
| 401 | 414 | ffa_setup_and_transmit(u32 func_id, void *buffer, u32 max_fragsize, |
| 402 | 415 | struct ffa_mem_ops_args *args) |
| @@ -413,8 +426,7 @@ ffa_setup_and_transmit(u32 func_id, void *buffer, u32 max_fragsize, · 10 unmodified lines | ||
| 413 | 426 | mem_region->tag = args->tag; |
| 414 | 427 | mem_region->flags = args->flags; |
| 415 | 428 | mem_region->sender_id = drv_info->vm_id; |
| 416 | − mem_region->attributes = FFA_MEM_NORMAL | FFA_MEM_WRITE_BACK | | |
| 417 | − FFA_MEM_INNER_SHAREABLE; | |
| 429 | + mem_region->attributes = ffa_memory_attributes_get(func_id); | |
| 418 | 430 | ep_mem_access = &mem_region->ep_mem_access[0]; |
| 419 | 431 | |
| 420 | 432 | for (idx = 0; idx < args->nattrs; idx++, ep_mem_access++) { |
| @@ -1080,6 +1080,8 @@ static int scmi_perf_protocol_init(const struct scmi_protocol_handle *ph) · 1079 unmodified lines | ||
| 1080 | 1080 | if (!pinfo) |
| 1081 | 1081 | return -ENOMEM; |
| 1082 | 1082 | |
| 1083 | + pinfo->version = version; | |
| 1084 | + | |
| 1083 | 1085 | ret = scmi_perf_attributes_get(ph, pinfo); |
| 1084 | 1086 | if (ret) |
| 1085 | 1087 | return ret; |
| @@ -1104,8 +1106,6 @@ static int scmi_perf_protocol_init(const struct scmi_protocol_handle *ph) · 18 unmodified lines | ||
| 1104 | 1106 | if (ret) |
| 1105 | 1107 | return ret; |
| 1106 | 1108 | |
| 1107 | − pinfo->version = version; | |
| 1108 | − | |
| 1109 | 1109 | return ph->set_priv(ph, pinfo); |
| 1110 | 1110 | } |
| 1111 | 1111 | |
| @@ -623,6 +623,34 @@ static __init int match_config_table(const efi_guid_t *guid, · 622 unmodified lines | ||
| 623 | 623 | return 0; |
| 624 | 624 | } |
| 625 | 625 | |
| 626 | +/** | |
| 627 | + * reserve_unaccepted - Map and reserve unaccepted configuration table | |
| 628 | + * @unaccepted: Pointer to unaccepted memory table | |
| 629 | + * | |
| 630 | + * memblock_add() makes sure that the table is mapped in direct mapping. During | |
| 631 | + * normal boot it happens automatically because the table is allocated from | |
| 632 | + * usable memory. But during crashkernel boot only memory specifically reserved | |
| 633 | + * for crash scenario is mapped. memblock_add() forces the table to be mapped | |
| 634 | + * in crashkernel case. | |
| 635 | + * | |
| 636 | + * Align the range to the nearest page borders. Ranges smaller than page size | |
| 637 | + * are not going to be mapped. | |
| 638 | + * | |
| 639 | + * memblock_reserve() makes sure that future allocations will not touch the | |
| 640 | + * table. | |
| 641 | + */ | |
| 642 | + | |
| 643 | +static __init void reserve_unaccepted(struct efi_unaccepted_memory *unaccepted) | |
| 644 | +{ | |
| 645 | + phys_addr_t start, size; | |
| 646 | + | |
| 647 | + start = PAGE_ALIGN_DOWN(efi.unaccepted); | |
| 648 | + size = PAGE_ALIGN(sizeof(*unaccepted) + unaccepted->size); | |
| 649 | + | |
| 650 | + memblock_add(start, size); | |
| 651 | + memblock_reserve(start, size); | |
| 652 | +} | |
| 653 | + | |
| 626 | 654 | int __init efi_config_parse_tables(const efi_config_table_t *config_tables, |
| 627 | 655 | int count, |
| 628 | 656 | const efi_config_table_type_t *arch_tables) |
| @@ -751,11 +779,9 @@ int __init efi_config_parse_tables(const efi_config_table_t *config_tables, · 122 unmodified lines | ||
| 751 | 779 | |
| 752 | 780 | unaccepted = early_memremap(efi.unaccepted, sizeof(*unaccepted)); |
| 753 | 781 | if (unaccepted) { |
| 754 | − unsigned long size; | |
| 755 | 782 | |
| 756 | 783 | if (unaccepted->version == 1) { |
| 757 | − size = sizeof(*unaccepted) + unaccepted->size; | |
| 758 | − memblock_reserve(efi.unaccepted, size); | |
| 784 | + reserve_unaccepted(unaccepted); | |
| 759 | 785 | } else { |
| 760 | 786 | efi.unaccepted = EFI_INVALID_TABLE_ADDR; |
| 761 | 787 | } |
| @@ -114,6 +114,7 @@ static int imx_dsp_setup_channels(struct imx_dsp_ipc *dsp_ipc) · 113 unmodified lines | ||
| 114 | 114 | dsp_chan->idx = i % 2; |
| 115 | 115 | dsp_chan->ch = mbox_request_channel_byname(cl, chan_name); |
| 116 | 116 | if (IS_ERR(dsp_chan->ch)) { |
| 117 | + kfree(dsp_chan->name); | |
| 117 | 118 | ret = PTR_ERR(dsp_chan->ch); |
| 118 | 119 | if (ret != -EPROBE_DEFER) |
| 119 | 120 | dev_err(dev, "Failed to request mbox chan %s ret %d\n", |
| @@ -352,6 +352,7 @@ static int sprd_pmic_eic_probe(struct platform_device *pdev) · 351 unmodified lines | ||
| 352 | 352 | pmic_eic->chip.set_config = sprd_pmic_eic_set_config; |
| 353 | 353 | pmic_eic->chip.set = sprd_pmic_eic_set; |
| 354 | 354 | pmic_eic->chip.get = sprd_pmic_eic_get; |
| 355 | + pmic_eic->chip.can_sleep = true; | |
| 355 | 356 | |
| 356 | 357 | irq = &pmic_eic->chip.irq; |
| 357 | 358 | gpio_irq_chip_set_chip(irq, &pmic_eic_irq_chip); |
| @@ -19,6 +19,7 @@ · 18 unmodified lines | ||
| 19 | 19 | #include <linux/irq.h> |
| 20 | 20 | #include <linux/irq_sim.h> |
| 21 | 21 | #include <linux/list.h> |
| 22 | +#include <linux/minmax.h> | |
| 22 | 23 | #include <linux/mod_devicetable.h> |
| 23 | 24 | #include <linux/module.h> |
| 24 | 25 | #include <linux/mutex.h> |
| @@ -685,52 +686,32 @@ gpio_sim_device_config_live_show(struct config_item *item, char *page) · 660 unmodified lines | ||
| 685 | 686 | return sprintf(page, "%c\n", live ? '1' : '0'); |
| 686 | 687 | } |
| 687 | 688 | |
| 688 | −static char **gpio_sim_make_line_names(struct gpio_sim_bank *bank, | |
| 689 | − unsigned int *line_names_size) | |
| 689 | +static unsigned int gpio_sim_get_line_names_size(struct gpio_sim_bank *bank) | |
| 690 | 690 | { |
| 691 | − unsigned int max_offset = 0; | |
| 692 | − bool has_line_names = false; | |
| 693 | 691 | struct gpio_sim_line *line; |
| 694 | − char **line_names; | |
| 692 | + unsigned int size = 0; | |
| 695 | 693 | |
| 696 | 694 | list_for_each_entry(line, &bank->line_list, siblings) { |
| 697 | − if (line->offset >= bank->num_lines) | |
| 695 | + if (!line->name || (line->offset >= bank->num_lines)) | |
| 698 | 696 | continue; |
| 699 | 697 | |
| 700 | − if (line->name) { | |
| 701 | − if (line->offset > max_offset) | |
| 702 | − max_offset = line->offset; | |
| 703 | − | |
| 704 | − /* | |
| 705 | − * max_offset can stay at 0 so it's not an indicator | |
| 706 | − * of whether line names were configured at all. | |
| 707 | − */ | |
| 708 | − has_line_names = true; | |
| 709 | − } | |
| 698 | + size = max(size, line->offset + 1); | |
| 710 | 699 | } |
| 711 | 700 | |
| 712 | − if (!has_line_names) | |
| 713 | − /* | |
| 714 | − * This is not an error - NULL means, there are no line | |
| 715 | − * names configured. | |
| 716 | − */ | |
| 717 | − return NULL; | |
| 718 | − | |
| 719 | − *line_names_size = max_offset + 1; | |
| 701 | + return size; | |
| 702 | +} | |
| 720 | 703 | |
| 721 | − line_names = kcalloc(*line_names_size, sizeof(*line_names), GFP_KERNEL); | |
| 722 | − if (!line_names) | |
| 723 | − return ERR_PTR(-ENOMEM); | |
| 704 | +static void | |
| 705 | +gpio_sim_set_line_names(struct gpio_sim_bank *bank, char **line_names) | |
| 706 | +{ | |
| 707 | + struct gpio_sim_line *line; | |
| 724 | 708 | |
| 725 | 709 | list_for_each_entry(line, &bank->line_list, siblings) { |
| 726 | − if (line->offset >= bank->num_lines) | |
| 710 | + if (!line->name || (line->offset >= bank->num_lines)) | |
| 727 | 711 | continue; |
| 728 | 712 | |
| 729 | − if (line->name && (line->offset <= max_offset)) | |
| 730 | − line_names[line->offset] = line->name; | |
| 713 | + line_names[line->offset] = line->name; | |
| 731 | 714 | } |
| 732 | − | |
| 733 | − return line_names; | |
| 734 | 715 | } |
| 735 | 716 | |
| 736 | 717 | static void gpio_sim_remove_hogs(struct gpio_sim_device *dev) |
| @@ -834,7 +815,7 @@ gpio_sim_make_bank_swnode(struct gpio_sim_bank *bank, · 97 unmodified lines | ||
| 834 | 815 | struct fwnode_handle *parent) |
| 835 | 816 | { |
| 836 | 817 | struct property_entry properties[GPIO_SIM_PROP_MAX]; |
| 837 | − unsigned int prop_idx = 0, line_names_size = 0; | |
| 818 | + unsigned int prop_idx = 0, line_names_size; | |
| 838 | 819 | char **line_names __free(kfree) = NULL; |
| 839 | 820 | |
| 840 | 821 | memset(properties, 0, sizeof(properties)); |
| @@ -845,14 +826,19 @@ gpio_sim_make_bank_swnode(struct gpio_sim_bank *bank, · 4 unmodified lines | ||
| 845 | 826 | properties[prop_idx++] = PROPERTY_ENTRY_STRING("gpio-sim,label", |
| 846 | 827 | bank->label); |
| 847 | 828 | |
| 848 | − line_names = gpio_sim_make_line_names(bank, &line_names_size); | |
| 849 | − if (IS_ERR(line_names)) | |
| 850 | − return ERR_CAST(line_names); | |
| 829 | + line_names_size = gpio_sim_get_line_names_size(bank); | |
| 830 | + if (line_names_size) { | |
| 831 | + line_names = kcalloc(line_names_size, sizeof(*line_names), | |
| 832 | + GFP_KERNEL); | |
| 833 | + if (!line_names) | |
| 834 | + return ERR_PTR(-ENOMEM); | |
| 835 | + | |
| 836 | + gpio_sim_set_line_names(bank, line_names); | |
| 851 | 837 | |
| 852 | − if (line_names) | |
| 853 | 838 | properties[prop_idx++] = PROPERTY_ENTRY_STRING_ARRAY_LEN( |
| 854 | 839 | "gpio-line-names", |
| 855 | 840 | line_names, line_names_size); |
| 841 | + } | |
| 856 | 842 | |
| 857 | 843 | return fwnode_create_software_node(properties, parent); |
| 858 | 844 | } |
| @@ -195,7 +195,7 @@ static int tb10x_gpio_probe(struct platform_device *pdev) · 194 unmodified lines | ||
| 195 | 195 | handle_edge_irq, IRQ_NOREQUEST, IRQ_NOPROBE, |
| 196 | 196 | IRQ_GC_INIT_MASK_CACHE); |
| 197 | 197 | if (ret) |
| 198 | − return ret; | |
| 198 | + goto err_remove_domain; | |
| 199 | 199 | |
| 200 | 200 | gc = tb10x_gpio->domain->gc->gc[0]; |
| 201 | 201 | gc->reg_base = tb10x_gpio->base; |
| @@ -209,6 +209,10 @@ static int tb10x_gpio_probe(struct platform_device *pdev) · 7 unmodified lines | ||
| 209 | 209 | } |
| 210 | 210 | |
| 211 | 211 | return 0; |
| 212 | + | |
| 213 | +err_remove_domain: | |
| 214 | + irq_domain_remove(tb10x_gpio->domain); | |
| 215 | + return ret; | |
| 212 | 216 | } |
| 213 | 217 | |
| 214 | 218 | static int tb10x_gpio_remove(struct platform_device *pdev) |
| @@ -43,9 +43,10 @@ static int timbgpio_update_bit(struct gpio_chip *gpio, unsigned index, · 42 unmodified lines | ||
| 43 | 43 | unsigned offset, bool enabled) |
| 44 | 44 | { |
| 45 | 45 | struct timbgpio *tgpio = gpiochip_get_data(gpio); |
| 46 | + unsigned long flags; | |
| 46 | 47 | u32 reg; |
| 47 | 48 | |
| 48 | − spin_lock(&tgpio->lock); | |
| 49 | + spin_lock_irqsave(&tgpio->lock, flags); | |
| 49 | 50 | reg = ioread32(tgpio->membase + offset); |
| 50 | 51 | |
| 51 | 52 | if (enabled) |
| @@ -54,7 +55,7 @@ static int timbgpio_update_bit(struct gpio_chip *gpio, unsigned index, · 2 unmodified lines | ||
| 54 | 55 | reg &= ~(1 << index); |
| 55 | 56 | |
| 56 | 57 | iowrite32(reg, tgpio->membase + offset); |
| 57 | − spin_unlock(&tgpio->lock); | |
| 58 | + spin_unlock_irqrestore(&tgpio->lock, flags); | |
| 58 | 59 | |
| 59 | 60 | return 0; |
| 60 | 61 | } |
| @@ -136,7 +136,7 @@ config DRM_FBDEV_EMULATION · 135 unmodified lines | ||
| 136 | 136 | bool "Enable legacy fbdev support for your modesetting driver" |
| 137 | 137 | depends on DRM |
| 138 | 138 | select FRAMEBUFFER_CONSOLE_DETECT_PRIMARY if FRAMEBUFFER_CONSOLE |
| 139 | − default y | |
| 139 | + default FB | |
| 140 | 140 | help |
| 141 | 141 | Choose this option if you have a need for the legacy fbdev |
| 142 | 142 | support. Note that this support also provides the linux console |
| @@ -1776,7 +1776,7 @@ static ssize_t amdgpu_atombios_get_vbios_version(struct device *dev, · 1775 unmodified lines | ||
| 1776 | 1776 | struct amdgpu_device *adev = drm_to_adev(ddev); |
| 1777 | 1777 | struct atom_context *ctx = adev->mode_info.atom_context; |
| 1778 | 1778 | |
| 1779 | − return sysfs_emit(buf, "%s\n", ctx->vbios_ver_str); | |
| 1779 | + return sysfs_emit(buf, "%s\n", ctx->vbios_pn); | |
| 1780 | 1780 | } |
| 1781 | 1781 | |
| 1782 | 1782 | static DEVICE_ATTR(vbios_version, 0444, amdgpu_atombios_get_vbios_version, |
| @@ -801,6 +801,7 @@ int amdgpu_ras_feature_enable(struct amdgpu_device *adev, · 800 unmodified lines | ||
| 801 | 801 | enable ? "enable":"disable", |
| 802 | 802 | get_ras_block_str(head), |
| 803 | 803 | amdgpu_ras_is_poison_mode_supported(adev), ret); |
| 804 | + kfree(info); | |
| 804 | 805 | return ret; |
| 805 | 806 | } |
| 806 | 807 | |
| @@ -216,7 +216,7 @@ static int add_queue_mes(struct device_queue_manager *dqm, struct queue *q, · 215 unmodified lines | ||
| 216 | 216 | |
| 217 | 217 | if (q->wptr_bo) { |
| 218 | 218 | wptr_addr_off = (uint64_t)q->properties.write_ptr & (PAGE_SIZE - 1); |
| 219 | − queue_input.wptr_mc_addr = ((uint64_t)q->wptr_bo->tbo.resource->start << PAGE_SHIFT) + wptr_addr_off; | |
| 219 | + queue_input.wptr_mc_addr = amdgpu_bo_gpu_offset(q->wptr_bo) + wptr_addr_off; | |
| 220 | 220 | } |
| 221 | 221 | |
| 222 | 222 | queue_input.is_kfd_process = 1; |
| @@ -6098,8 +6098,6 @@ create_stream_for_sink(struct amdgpu_dm_connector *aconnector, · 6097 unmodified lines | ||
| 6098 | 6098 | |
| 6099 | 6099 | if (recalculate_timing) |
| 6100 | 6100 | drm_mode_set_crtcinfo(&saved_mode, 0); |
| 6101 | − else if (!old_stream) | |
| 6102 | − drm_mode_set_crtcinfo(&mode, 0); | |
| 6103 | 6101 | |
| 6104 | 6102 | /* |
| 6105 | 6103 | * If scaling is enabled and refresh rate didn't change |
| @@ -6661,6 +6659,8 @@ enum drm_mode_status amdgpu_dm_connector_mode_valid(struct drm_connector *connec · 555 unmodified lines | ||
| 6661 | 6659 | goto fail; |
| 6662 | 6660 | } |
| 6663 | 6661 | |
| 6662 | + drm_mode_set_crtcinfo(mode, 0); | |
| 6663 | + | |
| 6664 | 6664 | stream = create_validate_stream_for_sink(aconnector, mode, |
| 6665 | 6665 | to_dm_connector_state(connector->state), |
| 6666 | 6666 | NULL); |
| @@ -1178,12 +1178,15 @@ void dce110_disable_stream(struct pipe_ctx *pipe_ctx) · 1177 unmodified lines | ||
| 1178 | 1178 | dto_params.otg_inst = tg->inst; |
| 1179 | 1179 | dto_params.timing = &pipe_ctx->stream->timing; |
| 1180 | 1180 | dp_hpo_inst = pipe_ctx->stream_res.hpo_dp_stream_enc->inst; |
| 1181 | − dccg->funcs->set_dtbclk_dto(dccg, &dto_params); | |
| 1182 | − dccg->funcs->disable_symclk32_se(dccg, dp_hpo_inst); | |
| 1183 | − dccg->funcs->set_dpstreamclk(dccg, REFCLK, tg->inst, dp_hpo_inst); | |
| 1184 | − } else if (pipe_ctx->stream->signal == SIGNAL_TYPE_DISPLAY_PORT_MST && dccg->funcs->disable_symclk_se) | |
| 1181 | + if (dccg) { | |
| 1182 | + dccg->funcs->set_dtbclk_dto(dccg, &dto_params); | |
| 1183 | + dccg->funcs->disable_symclk32_se(dccg, dp_hpo_inst); | |
| 1184 | + dccg->funcs->set_dpstreamclk(dccg, REFCLK, tg->inst, dp_hpo_inst); | |
| 1185 | + } | |
| 1186 | + } else if (dccg && dccg->funcs->disable_symclk_se) { | |
| 1185 | 1187 | dccg->funcs->disable_symclk_se(dccg, stream_enc->stream_enc_inst, |
| 1186 | 1188 | link_enc->transmitter - TRANSMITTER_UNIPHY_A); |
| 1189 | + } | |
| 1187 | 1190 | |
| 1188 | 1191 | if (dc->link_srv->dp_is_128b_132b_signal(pipe_ctx)) { |
| 1189 | 1192 | /* TODO: This looks like a bug to me as we are disabling HPO IO when |
| @@ -2658,11 +2661,11 @@ void dce110_prepare_bandwidth( · 1468 unmodified lines | ||
| 2658 | 2661 | struct clk_mgr *dccg = dc->clk_mgr; |
| 2659 | 2662 | |
| 2660 | 2663 | dce110_set_safe_displaymarks(&context->res_ctx, dc->res_pool); |
| 2661 | − | |
| 2662 | − dccg->funcs->update_clocks( | |
| 2663 | − dccg, | |
| 2664 | − context, | |
| 2665 | − false); | |
| 2664 | + if (dccg) | |
| 2665 | + dccg->funcs->update_clocks( | |
| 2666 | + dccg, | |
| 2667 | + context, | |
| 2668 | + false); | |
| 2666 | 2669 | } |
| 2667 | 2670 | |
| 2668 | 2671 | void dce110_optimize_bandwidth( |
| @@ -2673,10 +2676,11 @@ void dce110_optimize_bandwidth( · 4 unmodified lines | ||
| 2673 | 2676 | |
| 2674 | 2677 | dce110_set_displaymarks(dc, context); |
| 2675 | 2678 | |
| 2676 | − dccg->funcs->update_clocks( | |
| 2677 | − dccg, | |
| 2678 | − context, | |
| 2679 | − true); | |
| 2679 | + if (dccg) | |
| 2680 | + dccg->funcs->update_clocks( | |
| 2681 | + dccg, | |
| 2682 | + context, | |
| 2683 | + true); | |
| 2680 | 2684 | } |
| 2681 | 2685 | |
| 2682 | 2686 | static void dce110_program_front_end_for_pipe( |
| @@ -2692,8 +2692,6 @@ void dcn20_enable_stream(struct pipe_ctx *pipe_ctx) · 2691 unmodified lines | ||
| 2692 | 2692 | struct dce_hwseq *hws = dc->hwseq; |
| 2693 | 2693 | unsigned int k1_div = PIXEL_RATE_DIV_NA; |
| 2694 | 2694 | unsigned int k2_div = PIXEL_RATE_DIV_NA; |
| 2695 | − struct link_encoder *link_enc = link_enc_cfg_get_link_enc(pipe_ctx->stream->link); | |
| 2696 | − struct stream_encoder *stream_enc = pipe_ctx->stream_res.stream_enc; | |
| 2697 | 2695 | |
| 2698 | 2696 | if (dc->link_srv->dp_is_128b_132b_signal(pipe_ctx)) { |
| 2699 | 2697 | if (dc->hwseq->funcs.setup_hpo_hw_control) |
| @@ -2713,10 +2711,8 @@ void dcn20_enable_stream(struct pipe_ctx *pipe_ctx) · 13 unmodified lines | ||
| 2713 | 2711 | dto_params.timing = &pipe_ctx->stream->timing; |
| 2714 | 2712 | dto_params.ref_dtbclk_khz = dc->clk_mgr->funcs->get_dtb_ref_clk_frequency(dc->clk_mgr); |
| 2715 | 2713 | dccg->funcs->set_dtbclk_dto(dccg, &dto_params); |
| 2716 | − } else if (pipe_ctx->stream->signal == SIGNAL_TYPE_DISPLAY_PORT_MST && dccg->funcs->enable_symclk_se) | |
| 2717 | − dccg->funcs->enable_symclk_se(dccg, | |
| 2718 | − stream_enc->stream_enc_inst, link_enc->transmitter - TRANSMITTER_UNIPHY_A); | |
| 2719 | − | |
| 2714 | + } else { | |
| 2715 | + } | |
| 2720 | 2716 | if (hws->funcs.calculate_dccg_k1_k2_values && dc->res_pool->dccg->funcs->set_pixel_rate_div) { |
| 2721 | 2717 | hws->funcs.calculate_dccg_k1_k2_values(pipe_ctx, &k1_div, &k2_div); |
| 2722 | 2718 | |
| @@ -75,7 +75,7 @@ void mpc32_power_on_blnd_lut( · 74 unmodified lines | ||
| 75 | 75 | if (power_on) { |
| 76 | 76 | REG_UPDATE(MPCC_MCM_MEM_PWR_CTRL[mpcc_id], MPCC_MCM_1DLUT_MEM_PWR_FORCE, 0); |
| 77 | 77 | REG_WAIT(MPCC_MCM_MEM_PWR_CTRL[mpcc_id], MPCC_MCM_1DLUT_MEM_PWR_STATE, 0, 1, 5); |
| 78 | − } else { | |
| 78 | + } else if (!mpc->ctx->dc->debug.disable_mem_low_power) { | |
| 79 | 79 | ASSERT(false); |
| 80 | 80 | /* TODO: change to mpc |
| 81 | 81 | * dpp_base->ctx->dc->optimized_required = true; |
| @@ -100,6 +100,7 @@ int shmem_sg_alloc_table(struct drm_i915_private *i915, struct sg_table *st, · 99 unmodified lines | ||
| 100 | 100 | st->nents = 0; |
| 101 | 101 | for (i = 0; i < page_count; i++) { |
| 102 | 102 | struct folio *folio; |
| 103 | + unsigned long nr_pages; | |
| 103 | 104 | const unsigned int shrink[] = { |
| 104 | 105 | I915_SHRINK_BOUND | I915_SHRINK_UNBOUND, |
| 105 | 106 | 0, |
| @@ -150,6 +151,8 @@ int shmem_sg_alloc_table(struct drm_i915_private *i915, struct sg_table *st, · 44 unmodified lines | ||
| 150 | 151 | } |
| 151 | 152 | } while (1); |
| 152 | 153 | |
| 154 | + nr_pages = min_t(unsigned long, | |
| 155 | + folio_nr_pages(folio), page_count - i); | |
| 153 | 156 | if (!i || |
| 154 | 157 | sg->length >= max_segment || |
| 155 | 158 | folio_pfn(folio) != next_pfn) { |
| @@ -157,13 +160,13 @@ int shmem_sg_alloc_table(struct drm_i915_private *i915, struct sg_table *st, · 1 unmodified line | ||
| 157 | 160 | sg = sg_next(sg); |
| 158 | 161 | |
| 159 | 162 | st->nents++; |
| 160 | − sg_set_folio(sg, folio, folio_size(folio), 0); | |
| 163 | + sg_set_folio(sg, folio, nr_pages * PAGE_SIZE, 0); | |
| 161 | 164 | } else { |
| 162 | 165 | /* XXX: could overflow? */ |
| 163 | − sg->length += folio_size(folio); | |
| 166 | + sg->length += nr_pages * PAGE_SIZE; | |
| 164 | 167 | } |
| 165 | − next_pfn = folio_pfn(folio) + folio_nr_pages(folio); | |
| 166 | − i += folio_nr_pages(folio) - 1; | |
| 168 | + next_pfn = folio_pfn(folio) + nr_pages; | |
| 169 | + i += nr_pages - 1; | |
| 167 | 170 | |
| 168 | 171 | /* Check that the i965g/gm workaround works. */ |
| 169 | 172 | GEM_BUG_ON(gfp & __GFP_DMA32 && next_pfn >= 0x00100000UL); |
| @@ -558,7 +558,6 @@ static int intel_engine_setup(struct intel_gt *gt, enum intel_engine_id id, · 557 unmodified lines | ||
| 558 | 558 | DRIVER_CAPS(i915)->has_logical_contexts = true; |
| 559 | 559 | |
| 560 | 560 | ewma__engine_latency_init(&engine->latency); |
| 561 | − seqcount_init(&engine->stats.execlists.lock); | |
| 562 | 561 | |
| 563 | 562 | ATOMIC_INIT_NOTIFIER_HEAD(&engine->context_status_notifier); |
| 564 | 563 | |
| @@ -3550,6 +3550,8 @@ int intel_execlists_submission_setup(struct intel_engine_cs *engine) · 3549 unmodified lines | ||
| 3550 | 3550 | logical_ring_default_vfuncs(engine); |
| 3551 | 3551 | logical_ring_default_irqs(engine); |
| 3552 | 3552 | |
| 3553 | + seqcount_init(&engine->stats.execlists.lock); | |
| 3554 | + | |
| 3553 | 3555 | if (engine->flags & I915_ENGINE_HAS_RCS_REG_STATE) |
| 3554 | 3556 | rcs_submission_override(engine); |
| 3555 | 3557 | |
| @@ -511,20 +511,31 @@ void intel_ggtt_unbind_vma(struct i915_address_space *vm, · 510 unmodified lines | ||
| 511 | 511 | vm->clear_range(vm, vma_res->start, vma_res->vma_size); |
| 512 | 512 | } |
| 513 | 513 | |
| 514 | +/* | |
| 515 | + * Reserve the top of the GuC address space for firmware images. Addresses | |
| 516 | + * beyond GUC_GGTT_TOP in the GuC address space are inaccessible by GuC, | |
| 517 | + * which makes for a suitable range to hold GuC/HuC firmware images if the | |
| 518 | + * size of the GGTT is 4G. However, on a 32-bit platform the size of the GGTT | |
| 519 | + * is limited to 2G, which is less than GUC_GGTT_TOP, but we reserve a chunk | |
| 520 | + * of the same size anyway, which is far more than needed, to keep the logic | |
| 521 | + * in uc_fw_ggtt_offset() simple. | |
| 522 | + */ | |
| 523 | +#define GUC_TOP_RESERVE_SIZE (SZ_4G - GUC_GGTT_TOP) | |
| 524 | + | |
| 514 | 525 | static int ggtt_reserve_guc_top(struct i915_ggtt *ggtt) |
| 515 | 526 | { |
| 516 | − u64 size; | |
| 527 | + u64 offset; | |
| 517 | 528 | int ret; |
| 518 | 529 | |
| 519 | 530 | if (!intel_uc_uses_guc(&ggtt->vm.gt->uc)) |
| 520 | 531 | return 0; |
| 521 | 532 | |
| 522 | − GEM_BUG_ON(ggtt->vm.total <= GUC_GGTT_TOP); | |
| 523 | − size = ggtt->vm.total - GUC_GGTT_TOP; | |
| 533 | + GEM_BUG_ON(ggtt->vm.total <= GUC_TOP_RESERVE_SIZE); | |
| 534 | + offset = ggtt->vm.total - GUC_TOP_RESERVE_SIZE; | |
| 524 | 535 | |
| 525 | − ret = i915_gem_gtt_reserve(&ggtt->vm, NULL, &ggtt->uc_fw, size, | |
| 526 | − GUC_GGTT_TOP, I915_COLOR_UNEVICTABLE, | |
| 527 | − PIN_NOEVICT); | |
| 536 | + ret = i915_gem_gtt_reserve(&ggtt->vm, NULL, &ggtt->uc_fw, | |
| 537 | + GUC_TOP_RESERVE_SIZE, offset, | |
| 538 | + I915_COLOR_UNEVICTABLE, PIN_NOEVICT); | |
| 528 | 539 | if (ret) |
| 529 | 540 | drm_dbg(&ggtt->vm.i915->drm, |
| 530 | 541 | "Failed to reserve top of GGTT for GuC\n"); |
| @@ -1094,6 +1094,9 @@ __lrc_alloc_state(struct intel_context *ce, struct intel_engine_cs *engine) · 1093 unmodified lines | ||
| 1094 | 1094 | I915_BO_ALLOC_PM_VOLATILE); |
| 1095 | 1095 | if (IS_ERR(obj)) { |
| 1096 | 1096 | obj = i915_gem_object_create_shmem(engine->i915, context_size); |
| 1097 | + if (IS_ERR(obj)) | |
| 1098 | + return ERR_CAST(obj); | |
| 1099 | + | |
| 1097 | 1100 | /* |
| 1098 | 1101 | * Wa_22016122933: For Media version 13.0, all Media GT shared |
| 1099 | 1102 | * memory needs to be mapped as WC on CPU side and UC (PAT |
| @@ -1102,8 +1105,6 @@ __lrc_alloc_state(struct intel_context *ce, struct intel_engine_cs *engine) · 2 unmodified lines | ||
| 1102 | 1105 | if (intel_gt_needs_wa_22016122933(engine->gt)) |
| 1103 | 1106 | i915_gem_object_set_cache_coherency(obj, I915_CACHE_NONE); |
| 1104 | 1107 | } |
| 1105 | − if (IS_ERR(obj)) | |
| 1106 | − return ERR_CAST(obj); | |
| 1107 | 1108 | |
| 1108 | 1109 | vma = i915_vma_instance(obj, &engine->gt->ggtt->vm, NULL); |
| 1109 | 1110 | if (IS_ERR(vma)) { |
| @@ -1432,6 +1432,36 @@ static void guc_timestamp_ping(struct work_struct *wrk) · 1431 unmodified lines | ||
| 1432 | 1432 | unsigned long index; |
| 1433 | 1433 | int srcu, ret; |
| 1434 | 1434 | |
| 1435 | + /* | |
| 1436 | + * Ideally the busyness worker should take a gt pm wakeref because the | |
| 1437 | + * worker only needs to be active while gt is awake. However, the | |
| 1438 | + * gt_park path cancels the worker synchronously and this complicates | |
| 1439 | + * the flow if the worker is also running at the same time. The cancel | |
| 1440 | + * waits for the worker and when the worker releases the wakeref, that | |
| 1441 | + * would call gt_park and would lead to a deadlock. | |
| 1442 | + * | |
| 1443 | + * The resolution is to take the global pm wakeref if runtime pm is | |
| 1444 | + * already active. If not, we don't need to update the busyness stats as | |
| 1445 | + * the stats would already be updated when the gt was parked. | |
| 1446 | + * | |
| 1447 | + * Note: | |
| 1448 | + * - We do not requeue the worker if we cannot take a reference to runtime | |
| 1449 | + * pm since intel_guc_busyness_unpark would requeue the worker in the | |
| 1450 | + * resume path. | |
| 1451 | + * | |
| 1452 | + * - If the gt was parked longer than time taken for GT timestamp to roll | |
| 1453 | + * over, we ignore those rollovers since we don't care about tracking | |
| 1454 | + * the exact GT time. We only care about roll overs when the gt is | |
| 1455 | + * active and running workloads. | |
| 1456 | + * | |
| 1457 | + * - There is a window of time between gt_park and runtime suspend, | |
| 1458 | + * where the worker may run. This is acceptable since the worker will | |
| 1459 | + * not find any new data to update busyness. | |
| 1460 | + */ | |
| 1461 | + wakeref = intel_runtime_pm_get_if_active(>->i915->runtime_pm); | |
| 1462 | + if (!wakeref) | |
| 1463 | + return; | |
| 1464 | + | |
| 1435 | 1465 | /* |
| 1436 | 1466 | * Synchronize with gt reset to make sure the worker does not |
| 1437 | 1467 | * corrupt the engine/guc stats. NB: can't actually block waiting |
| @@ -1440,10 +1470,9 @@ static void guc_timestamp_ping(struct work_struct *wrk) · 2 unmodified lines | ||
| 1440 | 1470 | */ |
| 1441 | 1471 | ret = intel_gt_reset_trylock(gt, &srcu); |
| 1442 | 1472 | if (ret) |
| 1443 | − return; | |
| 1473 | + goto err_trylock; | |
| 1444 | 1474 | |
| 1445 | − with_intel_runtime_pm(>->i915->runtime_pm, wakeref) | |
| 1446 | − __update_guc_busyness_stats(guc); | |
| 1475 | + __update_guc_busyness_stats(guc); | |
| 1447 | 1476 | |
| 1448 | 1477 | /* adjust context stats for overflow */ |
| 1449 | 1478 | xa_for_each(&guc->context_lookup, index, ce) |
| @@ -1452,6 +1481,9 @@ static void guc_timestamp_ping(struct work_struct *wrk) · 2 unmodified lines | ||
| 1452 | 1481 | intel_gt_reset_unlock(gt, srcu); |
| 1453 | 1482 | |
| 1454 | 1483 | guc_enable_busyness_worker(guc); |
| 1484 | + | |
| 1485 | +err_trylock: | |
| 1486 | + intel_runtime_pm_put(>->i915->runtime_pm, wakeref); | |
| 1455 | 1487 | } |
| 1456 | 1488 | |
| 1457 | 1489 | static int guc_action_enable_usage_stats(struct intel_guc *guc) |
| @@ -334,6 +334,8 @@ static void meson_encoder_hdmi_hpd_notify(struct drm_bridge *bridge, · 333 unmodified lines | ||
| 334 | 334 | return; |
| 335 | 335 | |
| 336 | 336 | cec_notifier_set_phys_addr_from_edid(encoder_hdmi->cec_notifier, edid); |
| 337 | + | |
| 338 | + kfree(edid); | |
| 337 | 339 | } else |
| 338 | 340 | cec_notifier_phys_addr_invalidate(encoder_hdmi->cec_notifier); |
| 339 | 341 | } |
| @@ -189,21 +189,12 @@ u_free(void *addr) · 188 unmodified lines | ||
| 189 | 189 | static inline void * |
| 190 | 190 | u_memcpya(uint64_t user, unsigned int nmemb, unsigned int size) |
| 191 | 191 | { |
| 192 | − void *mem; | |
| 193 | − void __user *userptr = (void __force __user *)(uintptr_t)user; | |
| 192 | + void __user *userptr = u64_to_user_ptr(user); | |
| 193 | + size_t bytes; | |
| 194 | 194 | |
| 195 | − size *= nmemb; | |
| 196 | − | |
| 197 | − mem = kvmalloc(size, GFP_KERNEL); | |
| 198 | − if (!mem) | |
| 199 | − return ERR_PTR(-ENOMEM); | |
| 200 | − | |
| 201 | − if (copy_from_user(mem, userptr, size)) { | |
| 202 | − u_free(mem); | |
| 203 | − return ERR_PTR(-EFAULT); | |
| 204 | − } | |
| 205 | − | |
| 206 | − return mem; | |
| 195 | + if (unlikely(check_mul_overflow(nmemb, size, &bytes))) | |
| 196 | + return ERR_PTR(-EOVERFLOW); | |
| 197 | + return vmemdup_user(userptr, bytes); | |
| 207 | 198 | } |
| 208 | 199 | |
| 209 | 200 | #include <nvif/object.h> |
| @@ -213,7 +213,7 @@ nouveau_exec_job_timeout(struct nouveau_job *job) · 212 unmodified lines | ||
| 213 | 213 | |
| 214 | 214 | nouveau_sched_entity_fini(job->entity); |
| 215 | 215 | |
| 216 | − return DRM_GPU_SCHED_STAT_ENODEV; | |
| 216 | + return DRM_GPU_SCHED_STAT_NOMINAL; | |
| 217 | 217 | } |
| 218 | 218 | |
| 219 | 219 | static struct nouveau_job_ops nouveau_exec_job_ops = { |
| @@ -207,7 +207,7 @@ nouveau_fence_context_new(struct nouveau_channel *chan, struct nouveau_fence_cha · 206 unmodified lines | ||
| 207 | 207 | int |
| 208 | 208 | nouveau_fence_emit(struct nouveau_fence *fence) |
| 209 | 209 | { |
| 210 | − struct nouveau_channel *chan = fence->channel; | |
| 210 | + struct nouveau_channel *chan = unrcu_pointer(fence->channel); | |
| 211 | 211 | struct nouveau_fence_chan *fctx = chan->fence; |
| 212 | 212 | struct nouveau_fence_priv *priv = (void*)chan->drm->fence; |
| 213 | 213 | int ret; |
| @@ -375,14 +375,20 @@ nouveau_sched_run_job(struct drm_sched_job *sched_job) · 374 unmodified lines | ||
| 375 | 375 | static enum drm_gpu_sched_stat |
| 376 | 376 | nouveau_sched_timedout_job(struct drm_sched_job *sched_job) |
| 377 | 377 | { |
| 378 | + struct drm_gpu_scheduler *sched = sched_job->sched; | |
| 378 | 379 | struct nouveau_job *job = to_nouveau_job(sched_job); |
| 380 | + enum drm_gpu_sched_stat stat = DRM_GPU_SCHED_STAT_NOMINAL; | |
| 379 | 381 | |
| 380 | − NV_PRINTK(warn, job->cli, "Job timed out.\n"); | |
| 382 | + drm_sched_stop(sched, sched_job); | |
| 381 | 383 | |
| 382 | 384 | if (job->ops->timeout) |
| 383 | − return job->ops->timeout(job); | |
| 385 | + stat = job->ops->timeout(job); | |
| 386 | + else | |
| 387 | + NV_PRINTK(warn, job->cli, "Generic job timeout.\n"); | |
| 388 | + | |
| 389 | + drm_sched_start(sched, true); | |
| 384 | 390 | |
| 385 | − return DRM_GPU_SCHED_STAT_ENODEV; | |
| 391 | + return stat; | |
| 386 | 392 | } |
| 387 | 393 | |
| 388 | 394 | static void |
| @@ -939,7 +939,7 @@ static void drm_test_mm_insert_range(struct kunit *test) · 938 unmodified lines | ||
| 939 | 939 | KUNIT_ASSERT_FALSE(test, __drm_test_mm_insert_range(test, count, size, 0, max - 1)); |
| 940 | 940 | KUNIT_ASSERT_FALSE(test, __drm_test_mm_insert_range(test, count, size, 0, max / 2)); |
| 941 | 941 | KUNIT_ASSERT_FALSE(test, __drm_test_mm_insert_range(test, count, size, |
| 942 | − max / 2, max / 2)); | |
| 942 | + max / 2, max)); | |
| 943 | 943 | KUNIT_ASSERT_FALSE(test, __drm_test_mm_insert_range(test, count, size, |
| 944 | 944 | max / 4 + 1, 3 * max / 4 - 1)); |
| 945 | 945 | |
| @@ -361,7 +361,6 @@ static void virtio_gpu_complete_submit(struct virtio_gpu_submit *submit) · 360 unmodified lines | ||
| 361 | 361 | submit->buf = NULL; |
| 362 | 362 | submit->buflist = NULL; |
| 363 | 363 | submit->sync_file = NULL; |
| 364 | − submit->out_fence = NULL; | |
| 365 | 364 | submit->out_fence_fd = -1; |
| 366 | 365 | } |
| 367 | 366 | |
| @@ -441,8 +441,25 @@ err_release_lock: · 440 unmodified lines | ||
| 441 | 441 | |
| 442 | 442 | void __i2c_dw_disable(struct dw_i2c_dev *dev) |
| 443 | 443 | { |
| 444 | + unsigned int raw_intr_stats; | |
| 445 | + unsigned int enable; | |
| 444 | 446 | int timeout = 100; |
| 447 | + bool abort_needed; | |
| 445 | 448 | unsigned int status; |
| 449 | + int ret; | |
| 450 | + | |
| 451 | + regmap_read(dev->map, DW_IC_RAW_INTR_STAT, &raw_intr_stats); | |
| 452 | + regmap_read(dev->map, DW_IC_ENABLE, &enable); | |
| 453 | + | |
| 454 | + abort_needed = raw_intr_stats & DW_IC_INTR_MST_ON_HOLD; | |
| 455 | + if (abort_needed) { | |
| 456 | + regmap_write(dev->map, DW_IC_ENABLE, enable | DW_IC_ENABLE_ABORT); | |
| 457 | + ret = regmap_read_poll_timeout(dev->map, DW_IC_ENABLE, enable, | |
| 458 | + !(enable & DW_IC_ENABLE_ABORT), 10, | |
| 459 | + 100); | |
| 460 | + if (ret) | |
| 461 | + dev_err(dev->dev, "timeout while trying to abort current transfer\n"); | |
| 462 | + } | |
| 446 | 463 | |
| 447 | 464 | do { |
| 448 | 465 | __i2c_dw_disable_nowait(dev); |
| @@ -98,6 +98,7 @@ · 97 unmodified lines | ||
| 98 | 98 | #define DW_IC_INTR_START_DET BIT(10) |
| 99 | 99 | #define DW_IC_INTR_GEN_CALL BIT(11) |
| 100 | 100 | #define DW_IC_INTR_RESTART_DET BIT(12) |
| 101 | +#define DW_IC_INTR_MST_ON_HOLD BIT(13) | |
| 101 | 102 | |
| 102 | 103 | #define DW_IC_INTR_DEFAULT_MASK (DW_IC_INTR_RX_FULL | \ |
| 103 | 104 | DW_IC_INTR_TX_ABRT | \ |
| @@ -108,6 +109,8 @@ · 4 unmodified lines | ||
| 108 | 109 | DW_IC_INTR_RX_UNDER | \ |
| 109 | 110 | DW_IC_INTR_RD_REQ) |
| 110 | 111 | |
| 112 | +#define DW_IC_ENABLE_ABORT BIT(1) | |
| 113 | + | |
| 111 | 114 | #define DW_IC_STATUS_ACTIVITY BIT(0) |
| 112 | 115 | #define DW_IC_STATUS_TFE BIT(2) |
| 113 | 116 | #define DW_IC_STATUS_RFNE BIT(3) |
| @@ -1754,6 +1754,7 @@ static int i801_probe(struct pci_dev *dev, const struct pci_device_id *id) · 1753 unmodified lines | ||
| 1754 | 1754 | "SMBus I801 adapter at %04lx", priv->smba); |
| 1755 | 1755 | err = i2c_add_adapter(&priv->adapter); |
| 1756 | 1756 | if (err) { |
| 1757 | + platform_device_unregister(priv->tco_pdev); | |
| 1757 | 1758 | i801_acpi_remove(priv); |
| 1758 | 1759 | return err; |
| 1759 | 1760 | } |
| @@ -694,6 +694,7 @@ static void npcm_i2c_callback(struct npcm_i2c *bus, · 693 unmodified lines | ||
| 694 | 694 | { |
| 695 | 695 | struct i2c_msg *msgs; |
| 696 | 696 | int msgs_num; |
| 697 | + bool do_complete = false; | |
| 697 | 698 | |
| 698 | 699 | msgs = bus->msgs; |
| 699 | 700 | msgs_num = bus->msgs_num; |
| @@ -722,23 +723,17 @@ static void npcm_i2c_callback(struct npcm_i2c *bus, · 22 unmodified lines | ||
| 722 | 723 | msgs[1].flags & I2C_M_RD) |
| 723 | 724 | msgs[1].len = info; |
| 724 | 725 | } |
| 725 | − if (completion_done(&bus->cmd_complete) == false) | |
| 726 | − complete(&bus->cmd_complete); | |
| 727 | − break; | |
| 728 | − | |
| 726 | + do_complete = true; | |
| 727 | + break; | |
| 729 | 728 | case I2C_NACK_IND: |
| 730 | 729 | /* MASTER transmit got a NACK before tx all bytes */ |
| 731 | 730 | bus->cmd_err = -ENXIO; |
| 732 | − if (bus->master_or_slave == I2C_MASTER) | |
| 733 | − complete(&bus->cmd_complete); | |
| 734 | − | |
| 731 | + do_complete = true; | |
| 735 | 732 | break; |
| 736 | 733 | case I2C_BUS_ERR_IND: |
| 737 | 734 | /* Bus error */ |
| 738 | 735 | bus->cmd_err = -EAGAIN; |
| 739 | − if (bus->master_or_slave == I2C_MASTER) | |
| 740 | − complete(&bus->cmd_complete); | |
| 741 | − | |
| 736 | + do_complete = true; | |
| 742 | 737 | break; |
| 743 | 738 | case I2C_WAKE_UP_IND: |
| 744 | 739 | /* I2C wake up */ |
| @@ -752,6 +747,8 @@ static void npcm_i2c_callback(struct npcm_i2c *bus, · 7 unmodified lines | ||
| 752 | 747 | if (bus->slave) |
| 753 | 748 | bus->master_or_slave = I2C_SLAVE; |
| 754 | 749 | #endif |
| 750 | + if (do_complete) | |
| 751 | + complete(&bus->cmd_complete); | |
| 755 | 752 | } |
| 756 | 753 | |
| 757 | 754 | static u8 npcm_i2c_fifo_usage(struct npcm_i2c *bus) |
| @@ -710,7 +710,7 @@ static irqreturn_t xiic_process(int irq, void *dev_id) · 709 unmodified lines | ||
| 710 | 710 | * reset the IP instead of just flush fifos |
| 711 | 711 | */ |
| 712 | 712 | ret = xiic_reinit(i2c); |
| 713 | − if (!ret) | |
| 713 | + if (ret < 0) | |
| 714 | 714 | dev_dbg(i2c->adap.dev.parent, "reinit failed\n"); |
| 715 | 715 | |
| 716 | 716 | if (i2c->rx_msg) { |
| @@ -341,7 +341,7 @@ int i2c_mux_add_adapter(struct i2c_mux_core *muxc, · 340 unmodified lines | ||
| 341 | 341 | priv->adap.lock_ops = &i2c_parent_lock_ops; |
| 342 | 342 | |
| 343 | 343 | /* Sanity check on class */ |
| 344 | − if (i2c_mux_parent_classes(parent) & class) | |
| 344 | + if (i2c_mux_parent_classes(parent) & class & ~I2C_CLASS_DEPRECATED) | |
| 345 | 345 | dev_err(&parent->dev, |
| 346 | 346 | "Segment %d behind mux can't share classes with ancestors\n", |
| 347 | 347 | chan_id); |
| @@ -243,6 +243,10 @@ static int i2c_demux_pinctrl_probe(struct platform_device *pdev) · 242 unmodified lines | ||
| 243 | 243 | |
| 244 | 244 | props[i].name = devm_kstrdup(&pdev->dev, "status", GFP_KERNEL); |
| 245 | 245 | props[i].value = devm_kstrdup(&pdev->dev, "ok", GFP_KERNEL); |
| 246 | + if (!props[i].name || !props[i].value) { | |
| 247 | + err = -ENOMEM; | |
| 248 | + goto err_rollback; | |
| 249 | + } | |
| 246 | 250 | props[i].length = 3; |
| 247 | 251 | |
| 248 | 252 | of_changeset_init(&priv->chan[i].chgset); |
| @@ -105,8 +105,10 @@ static int i2c_mux_gpio_probe_fw(struct gpiomux *mux, · 104 unmodified lines | ||
| 105 | 105 | |
| 106 | 106 | } else if (is_acpi_node(child)) { |
| 107 | 107 | rc = acpi_get_local_address(ACPI_HANDLE_FWNODE(child), values + i); |
| 108 | − if (rc) | |
| 108 | + if (rc) { | |
| 109 | + fwnode_handle_put(child); | |
| 109 | 110 | return dev_err_probe(dev, rc, "Cannot get address\n"); |
| 111 | + } | |
| 110 | 112 | } |
| 111 | 113 | |
| 112 | 114 | i++; |
| @@ -671,8 +671,7 @@ static int apple_dart_attach_dev(struct iommu_domain *domain, · 670 unmodified lines | ||
| 671 | 671 | return ret; |
| 672 | 672 | |
| 673 | 673 | switch (domain->type) { |
| 674 | − case IOMMU_DOMAIN_DMA: | |
| 675 | − case IOMMU_DOMAIN_UNMANAGED: | |
| 674 | + default: | |
| 676 | 675 | ret = apple_dart_domain_add_streams(dart_domain, cfg); |
| 677 | 676 | if (ret) |
| 678 | 677 | return ret; |
| @@ -186,6 +186,15 @@ static void arm_smmu_free_shared_cd(struct arm_smmu_ctx_desc *cd) · 185 unmodified lines | ||
| 186 | 186 | } |
| 187 | 187 | } |
| 188 | 188 | |
| 189 | +/* | |
| 190 | + * Cloned from the MAX_TLBI_OPS in arch/arm64/include/asm/tlbflush.h, this | |
| 191 | + * is used as a threshold to replace per-page TLBI commands to issue in the | |
| 192 | + * command queue with an address-space TLBI command, when SMMU w/o a range | |
| 193 | + * invalidation feature handles too many per-page TLBI commands, which will | |
| 194 | + * otherwise result in a soft lockup. | |
| 195 | + */ | |
| 196 | +#define CMDQ_MAX_TLBI_OPS (1 << (PAGE_SHIFT - 3)) | |
| 197 | + | |
| 189 | 198 | static void arm_smmu_mm_arch_invalidate_secondary_tlbs(struct mmu_notifier *mn, |
| 190 | 199 | struct mm_struct *mm, |
| 191 | 200 | unsigned long start, |
| @@ -201,8 +210,13 @@ static void arm_smmu_mm_arch_invalidate_secondary_tlbs(struct mmu_notifier *mn, · 9 unmodified lines | ||
| 201 | 210 | * range. So do a simple translation here by calculating size correctly. |
| 202 | 211 | */ |
| 203 | 212 | size = end - start; |
| 204 | − if (size == ULONG_MAX) | |
| 205 | − size = 0; | |
| 213 | + if (!(smmu_domain->smmu->features & ARM_SMMU_FEAT_RANGE_INV)) { | |
| 214 | + if (size >= CMDQ_MAX_TLBI_OPS * PAGE_SIZE) | |
| 215 | + size = 0; | |
| 216 | + } else { | |
| 217 | + if (size == ULONG_MAX) | |
| 218 | + size = 0; | |
| 219 | + } | |
| 206 | 220 | |
| 207 | 221 | if (!(smmu_domain->smmu->features & ARM_SMMU_FEAT_BTM)) { |
| 208 | 222 | if (!size) |
| @@ -1895,18 +1895,23 @@ static void __arm_smmu_tlb_inv_range(struct arm_smmu_cmdq_ent *cmd, · 1894 unmodified lines | ||
| 1895 | 1895 | /* Get the leaf page size */ |
| 1896 | 1896 | tg = __ffs(smmu_domain->domain.pgsize_bitmap); |
| 1897 | 1897 | |
| 1898 | + num_pages = size >> tg; | |
| 1899 | + | |
| 1898 | 1900 | /* Convert page size of 12,14,16 (log2) to 1,2,3 */ |
| 1899 | 1901 | cmd->tlbi.tg = (tg - 10) / 2; |
| 1900 | 1902 | |
| 1901 | 1903 | /* |
| 1902 | − * Determine what level the granule is at. For non-leaf, io-pgtable | |
| 1903 | − * assumes .tlb_flush_walk can invalidate multiple levels at once, | |
| 1904 | − * so ignore the nominal last-level granule and leave TTL=0. | |
| 1904 | + * Determine what level the granule is at. For non-leaf, both | |
| 1905 | + * io-pgtable and SVA pass a nominal last-level granule because | |
| 1906 | + * they don't know what level(s) actually apply, so ignore that | |
| 1907 | + * and leave TTL=0. However for various errata reasons we still | |
| 1908 | + * want to use a range command, so avoid the SVA corner case | |
| 1909 | + * where both scale and num could be 0 as well. | |
| 1905 | 1910 | */ |
| 1906 | 1911 | if (cmd->tlbi.leaf) |
| 1907 | 1912 | cmd->tlbi.ttl = 4 - ((ilog2(granule) - 3) / (tg - 3)); |
| 1908 | − | |
| 1909 | − num_pages = size >> tg; | |
| 1913 | + else if ((num_pages & CMDQ_TLBI_RANGE_NUM_MAX) == 1) | |
| 1914 | + num_pages++; | |
| 1910 | 1915 | } |
| 1911 | 1916 | |
| 1912 | 1917 | cmds.num = 0; |
| @@ -2998,13 +2998,6 @@ static int iommu_suspend(void) · 2997 unmodified lines | ||
| 2998 | 2998 | struct intel_iommu *iommu = NULL; |
| 2999 | 2999 | unsigned long flag; |
| 3000 | 3000 | |
| 3001 | − for_each_active_iommu(iommu, drhd) { | |
| 3002 | − iommu->iommu_state = kcalloc(MAX_SR_DMAR_REGS, sizeof(u32), | |
| 3003 | − GFP_KERNEL); | |
| 3004 | − if (!iommu->iommu_state) | |
| 3005 | − goto nomem; | |
| 3006 | − } | |
| 3007 | − | |
| 3008 | 3001 | iommu_flush_all(); |
| 3009 | 3002 | |
| 3010 | 3003 | for_each_active_iommu(iommu, drhd) { |
| @@ -3024,12 +3017,6 @@ static int iommu_suspend(void) · 13 unmodified lines | ||
| 3024 | 3017 | raw_spin_unlock_irqrestore(&iommu->register_lock, flag); |
| 3025 | 3018 | } |
| 3026 | 3019 | return 0; |
| 3027 | − | |
| 3028 | −nomem: | |
| 3029 | − for_each_active_iommu(iommu, drhd) | |
| 3030 | − kfree(iommu->iommu_state); | |
| 3031 | − | |
| 3032 | − return -ENOMEM; | |
| 3033 | 3020 | } |
| 3034 | 3021 | |
| 3035 | 3022 | static void iommu_resume(void) |
| @@ -3061,9 +3048,6 @@ static void iommu_resume(void) · 25 unmodified lines | ||
| 3061 | 3048 | |
| 3062 | 3049 | raw_spin_unlock_irqrestore(&iommu->register_lock, flag); |
| 3063 | 3050 | } |
| 3064 | − | |
| 3065 | − for_each_active_iommu(iommu, drhd) | |
| 3066 | − kfree(iommu->iommu_state); | |
| 3067 | 3051 | } |
| 3068 | 3052 | |
| 3069 | 3053 | static struct syscore_ops iommu_syscore_ops = { |
| @@ -681,7 +681,7 @@ struct intel_iommu { · 680 unmodified lines | ||
| 681 | 681 | struct iopf_queue *iopf_queue; |
| 682 | 682 | unsigned char iopfq_name[16]; |
| 683 | 683 | struct q_inval *qi; /* Queued invalidation info */ |
| 684 | − u32 *iommu_state; /* Store iommu states between suspend and resume.*/ | |
| 684 | + u32 iommu_state[MAX_SR_DMAR_REGS]; /* Store iommu states between suspend and resume.*/ | |
| 685 | 685 | |
| 686 | 686 | #ifdef CONFIG_IRQ_REMAP |
| 687 | 687 | struct ir_table *ir_table; /* Interrupt remapping info */ |
| @@ -262,7 +262,7 @@ struct mtk_iommu_data { · 261 unmodified lines | ||
| 262 | 262 | struct device *smicomm_dev; |
| 263 | 263 | |
| 264 | 264 | struct mtk_iommu_bank_data *bank; |
| 265 | − struct mtk_iommu_domain *share_dom; /* For 2 HWs share pgtable */ | |
| 265 | + struct mtk_iommu_domain *share_dom; | |
| 266 | 266 | |
| 267 | 267 | struct regmap *pericfg; |
| 268 | 268 | struct mutex mutex; /* Protect m4u_group/m4u_dom above */ |
| @@ -643,8 +643,8 @@ static int mtk_iommu_domain_finalise(struct mtk_iommu_domain *dom, · 374 unmodified lines | ||
| 643 | 643 | struct mtk_iommu_domain *share_dom = data->share_dom; |
| 644 | 644 | const struct mtk_iommu_iova_region *region; |
| 645 | 645 | |
| 646 | − /* Always use share domain in sharing pgtable case */ | |
| 647 | − if (MTK_IOMMU_HAS_FLAG(data->plat_data, SHARE_PGTABLE) && share_dom) { | |
| 646 | + /* Share pgtable when 2 MM IOMMU share the pgtable or one IOMMU use multiple iova ranges */ | |
| 647 | + if (share_dom) { | |
| 648 | 648 | dom->iop = share_dom->iop; |
| 649 | 649 | dom->cfg = share_dom->cfg; |
| 650 | 650 | dom->domain.pgsize_bitmap = share_dom->cfg.pgsize_bitmap; |
| @@ -677,8 +677,7 @@ static int mtk_iommu_domain_finalise(struct mtk_iommu_domain *dom, · 26 unmodified lines | ||
| 677 | 677 | /* Update our support page sizes bitmap */ |
| 678 | 678 | dom->domain.pgsize_bitmap = dom->cfg.pgsize_bitmap; |
| 679 | 679 | |
| 680 | − if (MTK_IOMMU_HAS_FLAG(data->plat_data, SHARE_PGTABLE)) | |
| 681 | − data->share_dom = dom; | |
| 680 | + data->share_dom = dom; | |
| 682 | 681 | |
| 683 | 682 | update_iova_region: |
| 684 | 683 | /* Update the iova region for this domain */ |
| @@ -12,6 +12,7 @@ · 11 unmodified lines | ||
| 12 | 12 | #include <linux/irqdomain.h> |
| 13 | 13 | #include <linux/irq.h> |
| 14 | 14 | #include <linux/irqchip.h> |
| 15 | +#include <linux/irqchip/xtensa-mx.h> | |
| 15 | 16 | #include <linux/of.h> |
| 16 | 17 | |
| 17 | 18 | #include <asm/mxregs.h> |
| @@ -479,10 +479,6 @@ int led_compose_name(struct device *dev, struct led_init_data *init_data, · 478 unmodified lines | ||
| 479 | 479 | |
| 480 | 480 | led_parse_fwnode_props(dev, fwnode, &props); |
| 481 | 481 | |
| 482 | − /* We want to label LEDs that can produce full range of colors | |
| 483 | − * as RGB, not multicolor */ | |
| 484 | − BUG_ON(props.color == LED_COLOR_ID_MULTI); | |
| 485 | − | |
| 486 | 482 | if (props.label) { |
| 487 | 483 | /* |
| 488 | 484 | * If init_data.devicename is NULL, then it indicates that |
| @@ -241,6 +241,7 @@ config MFD_CS42L43 · 240 unmodified lines | ||
| 241 | 241 | tristate |
| 242 | 242 | select MFD_CORE |
| 243 | 243 | select REGMAP |
| 244 | + select REGMAP_IRQ | |
| 244 | 245 | |
| 245 | 246 | config MFD_CS42L43_I2C |
| 246 | 247 | tristate "Cirrus Logic CS42L43 (I2C)" |
| @@ -1178,8 +1178,8 @@ err: · 1177 unmodified lines | ||
| 1178 | 1178 | } |
| 1179 | 1179 | |
| 1180 | 1180 | EXPORT_NS_GPL_DEV_PM_OPS(cs42l43_pm_ops, MFD_CS42L43) = { |
| 1181 | − SET_SYSTEM_SLEEP_PM_OPS(cs42l43_suspend, cs42l43_resume) | |
| 1182 | − SET_RUNTIME_PM_OPS(cs42l43_runtime_suspend, cs42l43_runtime_resume, NULL) | |
| 1181 | + SYSTEM_SLEEP_PM_OPS(cs42l43_suspend, cs42l43_resume) | |
| 1182 | + RUNTIME_PM_OPS(cs42l43_runtime_suspend, cs42l43_runtime_resume, NULL) | |
| 1183 | 1183 | }; |
| 1184 | 1184 | |
| 1185 | 1185 | MODULE_DESCRIPTION("CS42L43 Core Driver"); |
| @@ -83,63 +83,20 @@ static void rts5227_fetch_vendor_settings(struct rtsx_pcr *pcr) · 82 unmodified lines | ||
| 83 | 83 | |
| 84 | 84 | static void rts5227_init_from_cfg(struct rtsx_pcr *pcr) |
| 85 | 85 | { |
| 86 | − struct pci_dev *pdev = pcr->pci; | |
| 87 | − int l1ss; | |
| 88 | − u32 lval; | |
| 89 | 86 | struct rtsx_cr_option *option = &pcr->option; |
| 90 | 87 | |
| 91 | − l1ss = pci_find_ext_capability(pdev, PCI_EXT_CAP_ID_L1SS); | |
| 92 | − if (!l1ss) | |
| 93 | − return; | |
| 94 | − | |
| 95 | − pci_read_config_dword(pdev, l1ss + PCI_L1SS_CTL1, &lval); | |
| 96 | − | |
| 97 | 88 | if (CHK_PCI_PID(pcr, 0x522A)) { |
| 98 | − if (0 == (lval & 0x0F)) | |
| 99 | − rtsx_pci_enable_oobs_polling(pcr); | |
| 100 | − else | |
| 89 | + if (rtsx_check_dev_flag(pcr, ASPM_L1_1_EN | ASPM_L1_2_EN | |
| 90 | + | PM_L1_1_EN | PM_L1_2_EN)) | |
| 101 | 91 | rtsx_pci_disable_oobs_polling(pcr); |
| 92 | + else | |
| 93 | + rtsx_pci_enable_oobs_polling(pcr); | |
| 102 | 94 | } |
| 103 | 95 | |
| 104 | − if (lval & PCI_L1SS_CTL1_ASPM_L1_1) | |
| 105 | − rtsx_set_dev_flag(pcr, ASPM_L1_1_EN); | |
| 106 | − else | |
| 107 | − rtsx_clear_dev_flag(pcr, ASPM_L1_1_EN); | |
| 108 | − | |
| 109 | − if (lval & PCI_L1SS_CTL1_ASPM_L1_2) | |
| 110 | − rtsx_set_dev_flag(pcr, ASPM_L1_2_EN); | |
| 111 | − else | |
| 112 | − rtsx_clear_dev_flag(pcr, ASPM_L1_2_EN); | |
| 113 | − | |
| 114 | − if (lval & PCI_L1SS_CTL1_PCIPM_L1_1) | |
| 115 | − rtsx_set_dev_flag(pcr, PM_L1_1_EN); | |
| 116 | − else | |
| 117 | − rtsx_clear_dev_flag(pcr, PM_L1_1_EN); | |
| 118 | − | |
| 119 | − if (lval & PCI_L1SS_CTL1_PCIPM_L1_2) | |
| 120 | − rtsx_set_dev_flag(pcr, PM_L1_2_EN); | |
| 121 | − else | |
| 122 | − rtsx_clear_dev_flag(pcr, PM_L1_2_EN); | |
| 123 | − | |
| 124 | 96 | if (option->ltr_en) { |
| 125 | − u16 val; | |
| 126 | − | |
| 127 | − pcie_capability_read_word(pcr->pci, PCI_EXP_DEVCTL2, &val); | |
| 128 | − if (val & PCI_EXP_DEVCTL2_LTR_EN) { | |
| 129 | − option->ltr_enabled = true; | |
| 130 | − option->ltr_active = true; | |
| 97 | + if (option->ltr_enabled) | |
| 131 | 98 | rtsx_set_ltr_latency(pcr, option->ltr_active_latency); |
| 132 | − } else { | |
| 133 | − option->ltr_enabled = false; | |
| 134 | − } | |
| 135 | 99 | } |
| 136 | − | |
| 137 | − if (rtsx_check_dev_flag(pcr, ASPM_L1_1_EN | ASPM_L1_2_EN | |
| 138 | − | PM_L1_1_EN | PM_L1_2_EN)) | |
| 139 | − option->force_clkreq_0 = false; | |
| 140 | − else | |
| 141 | − option->force_clkreq_0 = true; | |
| 142 | − | |
| 143 | 100 | } |
| 144 | 101 | |
| 145 | 102 | static int rts5227_extra_init_hw(struct rtsx_pcr *pcr) |
| @@ -195,7 +152,7 @@ static int rts5227_extra_init_hw(struct rtsx_pcr *pcr) · 49 unmodified lines | ||
| 195 | 152 | } |
| 196 | 153 | } |
| 197 | 154 | |
| 198 | − if (option->force_clkreq_0 && pcr->aspm_mode == ASPM_MODE_CFG) | |
| 155 | + if (option->force_clkreq_0) | |
| 199 | 156 | rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, PETXCFG, |
| 200 | 157 | FORCE_CLKREQ_DELINK_MASK, FORCE_CLKREQ_LOW); |
| 201 | 158 | else |
| @@ -386,59 +386,25 @@ static void rts5228_process_ocp(struct rtsx_pcr *pcr) · 385 unmodified lines | ||
| 386 | 386 | |
| 387 | 387 | static void rts5228_init_from_cfg(struct rtsx_pcr *pcr) |
| 388 | 388 | { |
| 389 | − struct pci_dev *pdev = pcr->pci; | |
| 390 | − int l1ss; | |
| 391 | − u32 lval; | |
| 392 | 389 | struct rtsx_cr_option *option = &pcr->option; |
| 393 | 390 | |
| 394 | − l1ss = pci_find_ext_capability(pdev, PCI_EXT_CAP_ID_L1SS); | |
| 395 | − if (!l1ss) | |
| 396 | − return; | |
| 397 | − | |
| 398 | − pci_read_config_dword(pdev, l1ss + PCI_L1SS_CTL1, &lval); | |
| 399 | − | |
| 400 | − if (0 == (lval & 0x0F)) | |
| 401 | − rtsx_pci_enable_oobs_polling(pcr); | |
| 402 | − else | |
| 391 | + if (rtsx_check_dev_flag(pcr, ASPM_L1_1_EN | ASPM_L1_2_EN | |
| 392 | + | PM_L1_1_EN | PM_L1_2_EN)) | |
| 403 | 393 | rtsx_pci_disable_oobs_polling(pcr); |
| 404 | − | |
| 405 | − if (lval & PCI_L1SS_CTL1_ASPM_L1_1) | |
| 406 | − rtsx_set_dev_flag(pcr, ASPM_L1_1_EN); | |
| 407 | − else | |
| 408 | − rtsx_clear_dev_flag(pcr, ASPM_L1_1_EN); | |
| 409 | − | |
| 410 | − if (lval & PCI_L1SS_CTL1_ASPM_L1_2) | |
| 411 | − rtsx_set_dev_flag(pcr, ASPM_L1_2_EN); | |
| 412 | − else | |
| 413 | − rtsx_clear_dev_flag(pcr, ASPM_L1_2_EN); | |
| 414 | − | |
| 415 | − if (lval & PCI_L1SS_CTL1_PCIPM_L1_1) | |
| 416 | − rtsx_set_dev_flag(pcr, PM_L1_1_EN); | |
| 417 | 394 | else |
| 418 | − rtsx_clear_dev_flag(pcr, PM_L1_1_EN); | |
| 419 | − | |
| 420 | − if (lval & PCI_L1SS_CTL1_PCIPM_L1_2) | |
| 421 | − rtsx_set_dev_flag(pcr, PM_L1_2_EN); | |
| 422 | − else | |
| 423 | − rtsx_clear_dev_flag(pcr, PM_L1_2_EN); | |
| 395 | + rtsx_pci_enable_oobs_polling(pcr); | |
| 424 | 396 | |
| 425 | 397 | rtsx_pci_write_register(pcr, ASPM_FORCE_CTL, 0xFF, 0); |
| 426 | − if (option->ltr_en) { | |
| 427 | − u16 val; | |
| 428 | 398 | |
| 429 | − pcie_capability_read_word(pcr->pci, PCI_EXP_DEVCTL2, &val); | |
| 430 | − if (val & PCI_EXP_DEVCTL2_LTR_EN) { | |
| 431 | − option->ltr_enabled = true; | |
| 432 | − option->ltr_active = true; | |
| 399 | + if (option->ltr_en) { | |
| 400 | + if (option->ltr_enabled) | |
| 433 | 401 | rtsx_set_ltr_latency(pcr, option->ltr_active_latency); |
| 434 | − } else { | |
| 435 | − option->ltr_enabled = false; | |
| 436 | − } | |
| 437 | 402 | } |
| 438 | 403 | } |
| 439 | 404 | |
| 440 | 405 | static int rts5228_extra_init_hw(struct rtsx_pcr *pcr) |
| 441 | 406 | { |
| 407 | + struct rtsx_cr_option *option = &pcr->option; | |
| 442 | 408 | |
| 443 | 409 | rtsx_pci_write_register(pcr, RTS5228_AUTOLOAD_CFG1, |
| 444 | 410 | CD_RESUME_EN_MASK, CD_RESUME_EN_MASK); |
| @@ -469,6 +435,17 @@ static int rts5228_extra_init_hw(struct rtsx_pcr *pcr) · 24 unmodified lines | ||
| 469 | 435 | else |
| 470 | 436 | rtsx_pci_write_register(pcr, PETXCFG, 0x30, 0x00); |
| 471 | 437 | |
| 438 | + /* | |
| 439 | + * If u_force_clkreq_0 is enabled, CLKREQ# PIN will be forced | |
| 440 | + * to drive low, and we forcibly request clock. | |
| 441 | + */ | |
| 442 | + if (option->force_clkreq_0) | |
| 443 | + rtsx_pci_write_register(pcr, PETXCFG, | |
| 444 | + FORCE_CLKREQ_DELINK_MASK, FORCE_CLKREQ_LOW); | |
| 445 | + else | |
| 446 | + rtsx_pci_write_register(pcr, PETXCFG, | |
| 447 | + FORCE_CLKREQ_DELINK_MASK, FORCE_CLKREQ_HIGH); | |
| 448 | + | |
| 472 | 449 | rtsx_pci_write_register(pcr, PWD_SUSPEND_EN, 0xFF, 0xFB); |
| 473 | 450 | |
| 474 | 451 | if (pcr->rtd3_en) { |
| @@ -86,64 +86,22 @@ static void rtsx_base_fetch_vendor_settings(struct rtsx_pcr *pcr) · 85 unmodified lines | ||
| 86 | 86 | |
| 87 | 87 | static void rts5249_init_from_cfg(struct rtsx_pcr *pcr) |
| 88 | 88 | { |
| 89 | − struct pci_dev *pdev = pcr->pci; | |
| 90 | − int l1ss; | |
| 91 | 89 | struct rtsx_cr_option *option = &(pcr->option); |
| 92 | − u32 lval; | |
| 93 | − | |
| 94 | − l1ss = pci_find_ext_capability(pdev, PCI_EXT_CAP_ID_L1SS); | |
| 95 | − if (!l1ss) | |
| 96 | − return; | |
| 97 | − | |
| 98 | − pci_read_config_dword(pdev, l1ss + PCI_L1SS_CTL1, &lval); | |
| 99 | 90 | |
| 100 | 91 | if (CHK_PCI_PID(pcr, PID_524A) || CHK_PCI_PID(pcr, PID_525A)) { |
| 101 | − if (0 == (lval & 0x0F)) | |
| 102 | − rtsx_pci_enable_oobs_polling(pcr); | |
| 103 | − else | |
| 92 | + if (rtsx_check_dev_flag(pcr, ASPM_L1_1_EN | ASPM_L1_2_EN | |
| 93 | + | PM_L1_1_EN | PM_L1_2_EN)) | |
| 104 | 94 | rtsx_pci_disable_oobs_polling(pcr); |
| 95 | + else | |
| 96 | + rtsx_pci_enable_oobs_polling(pcr); | |
| 105 | 97 | } |
| 106 | 98 | |
| 107 | − | |
| 108 | − if (lval & PCI_L1SS_CTL1_ASPM_L1_1) | |
| 109 | − rtsx_set_dev_flag(pcr, ASPM_L1_1_EN); | |
| 110 | − | |
| 111 | − if (lval & PCI_L1SS_CTL1_ASPM_L1_2) | |
| 112 | − rtsx_set_dev_flag(pcr, ASPM_L1_2_EN); | |
| 113 | − | |
| 114 | − if (lval & PCI_L1SS_CTL1_PCIPM_L1_1) | |
| 115 | − rtsx_set_dev_flag(pcr, PM_L1_1_EN); | |
| 116 | − | |
| 117 | − if (lval & PCI_L1SS_CTL1_PCIPM_L1_2) | |
| 118 | − rtsx_set_dev_flag(pcr, PM_L1_2_EN); | |
| 119 | − | |
| 120 | 99 | if (option->ltr_en) { |
| 121 | − u16 val; | |
| 122 | − | |
| 123 | − pcie_capability_read_word(pdev, PCI_EXP_DEVCTL2, &val); | |
| 124 | − if (val & PCI_EXP_DEVCTL2_LTR_EN) { | |
| 125 | − option->ltr_enabled = true; | |
| 126 | − option->ltr_active = true; | |
| 100 | + if (option->ltr_enabled) | |
| 127 | 101 | rtsx_set_ltr_latency(pcr, option->ltr_active_latency); |
| 128 | − } else { | |
| 129 | − option->ltr_enabled = false; | |
| 130 | − } | |
| 131 | 102 | } |
| 132 | 103 | } |
| 133 | 104 | |
| 134 | −static int rts5249_init_from_hw(struct rtsx_pcr *pcr) | |
| 135 | −{ | |
| 136 | − struct rtsx_cr_option *option = &(pcr->option); | |
| 137 | − | |
| 138 | − if (rtsx_check_dev_flag(pcr, ASPM_L1_1_EN | ASPM_L1_2_EN | |
| 139 | − | PM_L1_1_EN | PM_L1_2_EN)) | |
| 140 | − option->force_clkreq_0 = false; | |
| 141 | − else | |
| 142 | − option->force_clkreq_0 = true; | |
| 143 | − | |
| 144 | − return 0; | |
| 145 | −} | |
| 146 | − | |
| 147 | 105 | static void rts52xa_force_power_down(struct rtsx_pcr *pcr, u8 pm_state, bool runtime) |
| 148 | 106 | { |
| 149 | 107 | /* Set relink_time to 0 */ |
| @@ -276,7 +234,6 @@ static int rts5249_extra_init_hw(struct rtsx_pcr *pcr) · 126 unmodified lines | ||
| 276 | 234 | struct rtsx_cr_option *option = &(pcr->option); |
| 277 | 235 | |
| 278 | 236 | rts5249_init_from_cfg(pcr); |
| 279 | − rts5249_init_from_hw(pcr); | |
| 280 | 237 | |
| 281 | 238 | rtsx_pci_init_cmd(pcr); |
| 282 | 239 | |
| @@ -327,11 +284,12 @@ static int rts5249_extra_init_hw(struct rtsx_pcr *pcr) · 44 unmodified lines | ||
| 327 | 284 | } |
| 328 | 285 | } |
| 329 | 286 | |
| 287 | + | |
| 330 | 288 | /* |
| 331 | 289 | * If u_force_clkreq_0 is enabled, CLKREQ# PIN will be forced |
| 332 | 290 | * to drive low, and we forcibly request clock. |
| 333 | 291 | */ |
| 334 | − if (option->force_clkreq_0 && pcr->aspm_mode == ASPM_MODE_CFG) | |
| 292 | + if (option->force_clkreq_0) | |
| 335 | 293 | rtsx_pci_write_register(pcr, PETXCFG, |
| 336 | 294 | FORCE_CLKREQ_DELINK_MASK, FORCE_CLKREQ_LOW); |
| 337 | 295 | else |
| @@ -480,47 +480,19 @@ static void rts5260_pwr_saving_setting(struct rtsx_pcr *pcr) · 479 unmodified lines | ||
| 480 | 480 | |
| 481 | 481 | static void rts5260_init_from_cfg(struct rtsx_pcr *pcr) |
| 482 | 482 | { |
| 483 | − struct pci_dev *pdev = pcr->pci; | |
| 484 | − int l1ss; | |
| 485 | 483 | struct rtsx_cr_option *option = &pcr->option; |
| 486 | − u32 lval; | |
| 487 | − | |
| 488 | − l1ss = pci_find_ext_capability(pdev, PCI_EXT_CAP_ID_L1SS); | |
| 489 | − if (!l1ss) | |
| 490 | − return; | |
| 491 | − | |
| 492 | − pci_read_config_dword(pdev, l1ss + PCI_L1SS_CTL1, &lval); | |
| 493 | − | |
| 494 | − if (lval & PCI_L1SS_CTL1_ASPM_L1_1) | |
| 495 | − rtsx_set_dev_flag(pcr, ASPM_L1_1_EN); | |
| 496 | − | |
| 497 | − if (lval & PCI_L1SS_CTL1_ASPM_L1_2) | |
| 498 | − rtsx_set_dev_flag(pcr, ASPM_L1_2_EN); | |
| 499 | − | |
| 500 | − if (lval & PCI_L1SS_CTL1_PCIPM_L1_1) | |
| 501 | − rtsx_set_dev_flag(pcr, PM_L1_1_EN); | |
| 502 | − | |
| 503 | − if (lval & PCI_L1SS_CTL1_PCIPM_L1_2) | |
| 504 | − rtsx_set_dev_flag(pcr, PM_L1_2_EN); | |
| 505 | 484 | |
| 506 | 485 | rts5260_pwr_saving_setting(pcr); |
| 507 | 486 | |
| 508 | 487 | if (option->ltr_en) { |
| 509 | − u16 val; | |
| 510 | − | |
| 511 | − pcie_capability_read_word(pdev, PCI_EXP_DEVCTL2, &val); | |
| 512 | − if (val & PCI_EXP_DEVCTL2_LTR_EN) { | |
| 513 | − option->ltr_enabled = true; | |
| 514 | − option->ltr_active = true; | |
| 488 | + if (option->ltr_enabled) | |
| 515 | 489 | rtsx_set_ltr_latency(pcr, option->ltr_active_latency); |
| 516 | − } else { | |
| 517 | − option->ltr_enabled = false; | |
| 518 | − } | |
| 519 | 490 | } |
| 520 | 491 | } |
| 521 | 492 | |
| 522 | 493 | static int rts5260_extra_init_hw(struct rtsx_pcr *pcr) |
| 523 | 494 | { |
| 495 | + struct rtsx_cr_option *option = &pcr->option; | |
| 524 | 496 | |
| 525 | 497 | /* Set mcu_cnt to 7 to ensure data can be sampled properly */ |
| 526 | 498 | rtsx_pci_write_register(pcr, 0xFC03, 0x7F, 0x07); |
| @@ -539,6 +511,17 @@ static int rts5260_extra_init_hw(struct rtsx_pcr *pcr) · 12 unmodified lines | ||
| 539 | 511 | |
| 540 | 512 | rts5260_init_hw(pcr); |
| 541 | 513 | |
| 514 | + /* | |
| 515 | + * If u_force_clkreq_0 is enabled, CLKREQ# PIN will be forced | |
| 516 | + * to drive low, and we forcibly request clock. | |
| 517 | + */ | |
| 518 | + if (option->force_clkreq_0) | |
| 519 | + rtsx_pci_write_register(pcr, PETXCFG, | |
| 520 | + FORCE_CLKREQ_DELINK_MASK, FORCE_CLKREQ_LOW); | |
| 521 | + else | |
| 522 | + rtsx_pci_write_register(pcr, PETXCFG, | |
| 523 | + FORCE_CLKREQ_DELINK_MASK, FORCE_CLKREQ_HIGH); | |
| 524 | + | |
| 542 | 525 | rtsx_pci_write_register(pcr, pcr->reg_pm_ctrl3, 0x10, 0x00); |
| 543 | 526 | |
| 544 | 527 | return 0; |
| @@ -454,54 +454,17 @@ static void rts5261_init_from_hw(struct rtsx_pcr *pcr) · 453 unmodified lines | ||
| 454 | 454 | |
| 455 | 455 | static void rts5261_init_from_cfg(struct rtsx_pcr *pcr) |
| 456 | 456 | { |
| 457 | − struct pci_dev *pdev = pcr->pci; | |
| 458 | − int l1ss; | |
| 459 | − u32 lval; | |
| 460 | 457 | struct rtsx_cr_option *option = &pcr->option; |
| 461 | 458 | |
| 462 | − l1ss = pci_find_ext_capability(pdev, PCI_EXT_CAP_ID_L1SS); | |
| 463 | − if (!l1ss) | |
| 464 | − return; | |
| 465 | − | |
| 466 | − pci_read_config_dword(pdev, l1ss + PCI_L1SS_CTL1, &lval); | |
| 467 | − | |
| 468 | − if (lval & PCI_L1SS_CTL1_ASPM_L1_1) | |
| 469 | − rtsx_set_dev_flag(pcr, ASPM_L1_1_EN); | |
| 470 | − else | |
| 471 | − rtsx_clear_dev_flag(pcr, ASPM_L1_1_EN); | |
| 472 | − | |
| 473 | − if (lval & PCI_L1SS_CTL1_ASPM_L1_2) | |
| 474 | − rtsx_set_dev_flag(pcr, ASPM_L1_2_EN); | |
| 475 | − else | |
| 476 | − rtsx_clear_dev_flag(pcr, ASPM_L1_2_EN); | |
| 477 | − | |
| 478 | − if (lval & PCI_L1SS_CTL1_PCIPM_L1_1) | |
| 479 | − rtsx_set_dev_flag(pcr, PM_L1_1_EN); | |
| 480 | − else | |
| 481 | − rtsx_clear_dev_flag(pcr, PM_L1_1_EN); | |
| 482 | − | |
| 483 | − if (lval & PCI_L1SS_CTL1_PCIPM_L1_2) | |
| 484 | − rtsx_set_dev_flag(pcr, PM_L1_2_EN); | |
| 485 | − else | |
| 486 | − rtsx_clear_dev_flag(pcr, PM_L1_2_EN); | |
| 487 | − | |
| 488 | − rtsx_pci_write_register(pcr, ASPM_FORCE_CTL, 0xFF, 0); | |
| 489 | 459 | if (option->ltr_en) { |
| 490 | − u16 val; | |
| 491 | − | |
| 492 | − pcie_capability_read_word(pdev, PCI_EXP_DEVCTL2, &val); | |
| 493 | − if (val & PCI_EXP_DEVCTL2_LTR_EN) { | |
| 494 | − option->ltr_enabled = true; | |
| 495 | − option->ltr_active = true; | |
| 460 | + if (option->ltr_enabled) | |
| 496 | 461 | rtsx_set_ltr_latency(pcr, option->ltr_active_latency); |
| 497 | − } else { | |
| 498 | − option->ltr_enabled = false; | |
| 499 | − } | |
| 500 | 462 | } |
| 501 | 463 | } |
| 502 | 464 | |
| 503 | 465 | static int rts5261_extra_init_hw(struct rtsx_pcr *pcr) |
| 504 | 466 | { |
| 467 | + struct rtsx_cr_option *option = &pcr->option; | |
| 505 | 468 | u32 val; |
| 506 | 469 | |
| 507 | 470 | rtsx_pci_write_register(pcr, RTS5261_AUTOLOAD_CFG1, |
| @@ -547,6 +510,17 @@ static int rts5261_extra_init_hw(struct rtsx_pcr *pcr) · 39 unmodified lines | ||
| 547 | 510 | else |
| 548 | 511 | rtsx_pci_write_register(pcr, PETXCFG, 0x30, 0x00); |
| 549 | 512 | |
| 513 | + /* | |
| 514 | + * If u_force_clkreq_0 is enabled, CLKREQ# PIN will be forced | |
| 515 | + * to drive low, and we forcibly request clock. | |
| 516 | + */ | |
| 517 | + if (option->force_clkreq_0) | |
| 518 | + rtsx_pci_write_register(pcr, PETXCFG, | |
| 519 | + FORCE_CLKREQ_DELINK_MASK, FORCE_CLKREQ_LOW); | |
| 520 | + else | |
| 521 | + rtsx_pci_write_register(pcr, PETXCFG, | |
| 522 | + FORCE_CLKREQ_DELINK_MASK, FORCE_CLKREQ_HIGH); | |
| 523 | + | |
| 550 | 524 | rtsx_pci_write_register(pcr, PWD_SUSPEND_EN, 0xFF, 0xFB); |
| 551 | 525 | |
| 552 | 526 | if (pcr->rtd3_en) { |
| @@ -1326,11 +1326,8 @@ static int rtsx_pci_init_hw(struct rtsx_pcr *pcr) · 1325 unmodified lines | ||
| 1326 | 1326 | return err; |
| 1327 | 1327 | } |
| 1328 | 1328 | |
| 1329 | − if (pcr->aspm_mode == ASPM_MODE_REG) { | |
| 1329 | + if (pcr->aspm_mode == ASPM_MODE_REG) | |
| 1330 | 1330 | rtsx_pci_write_register(pcr, ASPM_FORCE_CTL, 0x30, 0x30); |
| 1331 | − rtsx_pci_write_register(pcr, PETXCFG, | |
| 1332 | − FORCE_CLKREQ_DELINK_MASK, FORCE_CLKREQ_HIGH); | |
| 1333 | − } | |
| 1334 | 1331 | |
| 1335 | 1332 | /* No CD interrupt if probing driver with card inserted. |
| 1336 | 1333 | * So we need to initialize pcr->card_exist here. |
| @@ -1345,7 +1342,9 @@ static int rtsx_pci_init_hw(struct rtsx_pcr *pcr) · 8 unmodified lines | ||
| 1345 | 1342 | |
| 1346 | 1343 | static int rtsx_pci_init_chip(struct rtsx_pcr *pcr) |
| 1347 | 1344 | { |
| 1348 | − int err; | |
| 1345 | + struct rtsx_cr_option *option = &(pcr->option); | |
| 1346 | + int err, l1ss; | |
| 1347 | + u32 lval; | |
| 1349 | 1348 | u16 cfg_val; |
| 1350 | 1349 | u8 val; |
| 1351 | 1350 | |
| @@ -1430,6 +1429,48 @@ static int rtsx_pci_init_chip(struct rtsx_pcr *pcr) · 78 unmodified lines | ||
| 1430 | 1429 | pcr->aspm_enabled = true; |
| 1431 | 1430 | } |
| 1432 | 1431 | |
| 1432 | + l1ss = pci_find_ext_capability(pcr->pci, PCI_EXT_CAP_ID_L1SS); | |
| 1433 | + if (l1ss) { | |
| 1434 | + pci_read_config_dword(pcr->pci, l1ss + PCI_L1SS_CTL1, &lval); | |
| 1435 | + | |
| 1436 | + if (lval & PCI_L1SS_CTL1_ASPM_L1_1) | |
| 1437 | + rtsx_set_dev_flag(pcr, ASPM_L1_1_EN); | |
| 1438 | + else | |
| 1439 | + rtsx_clear_dev_flag(pcr, ASPM_L1_1_EN); | |
| 1440 | + | |
| 1441 | + if (lval & PCI_L1SS_CTL1_ASPM_L1_2) | |
| 1442 | + rtsx_set_dev_flag(pcr, ASPM_L1_2_EN); | |
| 1443 | + else | |
| 1444 | + rtsx_clear_dev_flag(pcr, ASPM_L1_2_EN); | |
| 1445 | + | |
| 1446 | + if (lval & PCI_L1SS_CTL1_PCIPM_L1_1) | |
| 1447 | + rtsx_set_dev_flag(pcr, PM_L1_1_EN); | |
| 1448 | + else | |
| 1449 | + rtsx_clear_dev_flag(pcr, PM_L1_1_EN); | |
| 1450 | + | |
| 1451 | + if (lval & PCI_L1SS_CTL1_PCIPM_L1_2) | |
| 1452 | + rtsx_set_dev_flag(pcr, PM_L1_2_EN); | |
| 1453 | + else | |
| 1454 | + rtsx_clear_dev_flag(pcr, PM_L1_2_EN); | |
| 1455 | + | |
| 1456 | + pcie_capability_read_word(pcr->pci, PCI_EXP_DEVCTL2, &cfg_val); | |
| 1457 | + if (cfg_val & PCI_EXP_DEVCTL2_LTR_EN) { | |
| 1458 | + option->ltr_enabled = true; | |
| 1459 | + option->ltr_active = true; | |
| 1460 | + } else { | |
| 1461 | + option->ltr_enabled = false; | |
| 1462 | + } | |
| 1463 | + | |
| 1464 | + if (rtsx_check_dev_flag(pcr, ASPM_L1_1_EN | ASPM_L1_2_EN | |
| 1465 | + | PM_L1_1_EN | PM_L1_2_EN)) | |
| 1466 | + option->force_clkreq_0 = false; | |
| 1467 | + else | |
| 1468 | + option->force_clkreq_0 = true; | |
| 1469 | + } else { | |
| 1470 | + option->ltr_enabled = false; | |
| 1471 | + option->force_clkreq_0 = true; | |
| 1472 | + } | |
| 1473 | + | |
| 1433 | 1474 | if (pcr->ops->fetch_vendor_settings) |
| 1434 | 1475 | pcr->ops->fetch_vendor_settings(pcr); |
| 1435 | 1476 | |
| @@ -894,6 +894,13 @@ int ubi_attach_mtd_dev(struct mtd_info *mtd, int ubi_num, · 893 unmodified lines | ||
| 894 | 894 | return -EINVAL; |
| 895 | 895 | } |
| 896 | 896 | |
| 897 | + /* UBI cannot work on flashes with zero erasesize. */ | |
| 898 | + if (!mtd->erasesize) { | |
| 899 | + pr_err("ubi: refuse attaching mtd%d - zero erasesize flash is not supported\n", | |
| 900 | + mtd->index); | |
| 901 | + return -EINVAL; | |
| 902 | + } | |
| 903 | + | |
| 897 | 904 | if (ubi_num == UBI_DEV_NUM_AUTO) { |
| 898 | 905 | /* Search for an empty slot in the @ubi_devices array */ |
| 899 | 906 | for (ubi_num = 0; ubi_num < UBI_MAX_DEVICES; ubi_num++) |
| @@ -2958,14 +2958,16 @@ static void mv88e6xxx_hardware_reset(struct mv88e6xxx_chip *chip) · 2957 unmodified lines | ||
| 2958 | 2958 | * from the wrong location resulting in the switch booting |
| 2959 | 2959 | * to wrong mode and inoperable. |
| 2960 | 2960 | */ |
| 2961 | − mv88e6xxx_g1_wait_eeprom_done(chip); | |
| 2961 | + if (chip->info->ops->get_eeprom) | |
| 2962 | + mv88e6xxx_g2_eeprom_wait(chip); | |
| 2962 | 2963 | |
| 2963 | 2964 | gpiod_set_value_cansleep(gpiod, 1); |
| 2964 | 2965 | usleep_range(10000, 20000); |
| 2965 | 2966 | gpiod_set_value_cansleep(gpiod, 0); |
| 2966 | 2967 | usleep_range(10000, 20000); |
| 2967 | 2968 | |
| 2968 | − mv88e6xxx_g1_wait_eeprom_done(chip); | |
| 2969 | + if (chip->info->ops->get_eeprom) | |
| 2970 | + mv88e6xxx_g2_eeprom_wait(chip); | |
| 2969 | 2971 | } |
| 2970 | 2972 | } |
| 2971 | 2973 | |
| @@ -75,37 +75,6 @@ static int mv88e6xxx_g1_wait_init_ready(struct mv88e6xxx_chip *chip) · 74 unmodified lines | ||
| 75 | 75 | return mv88e6xxx_g1_wait_bit(chip, MV88E6XXX_G1_STS, bit, 1); |
| 76 | 76 | } |
| 77 | 77 | |
| 78 | −void mv88e6xxx_g1_wait_eeprom_done(struct mv88e6xxx_chip *chip) | |
| 79 | −{ | |
| 80 | − const unsigned long timeout = jiffies + 1 * HZ; | |
| 81 | − u16 val; | |
| 82 | − int err; | |
| 83 | − | |
| 84 | − /* Wait up to 1 second for the switch to finish reading the | |
| 85 | − * EEPROM. | |
| 86 | − */ | |
| 87 | − while (time_before(jiffies, timeout)) { | |
| 88 | − err = mv88e6xxx_g1_read(chip, MV88E6XXX_G1_STS, &val); | |
| 89 | − if (err) { | |
| 90 | − dev_err(chip->dev, "Error reading status"); | |
| 91 | − return; | |
| 92 | − } | |
| 93 | − | |
| 94 | − /* If the switch is still resetting, it may not | |
| 95 | − * respond on the bus, and so MDIO read returns | |
| 96 | − * 0xffff. Differentiate between that, and waiting for | |
| 97 | − * the EEPROM to be done by bit 0 being set. | |
| 98 | − */ | |
| 99 | − if (val != 0xffff && | |
| 100 | − val & BIT(MV88E6XXX_G1_STS_IRQ_EEPROM_DONE)) | |
| 101 | − return; | |
| 102 | − | |
| 103 | − usleep_range(1000, 2000); | |
| 104 | − } | |
| 105 | − | |
| 106 | − dev_err(chip->dev, "Timeout waiting for EEPROM done"); | |
| 107 | −} | |
| 108 | − | |
| 109 | 78 | /* Offset 0x01: Switch MAC Address Register Bytes 0 & 1 |
| 110 | 79 | * Offset 0x02: Switch MAC Address Register Bytes 2 & 3 |
| 111 | 80 | * Offset 0x03: Switch MAC Address Register Bytes 4 & 5 |
| @@ -282,7 +282,6 @@ int mv88e6xxx_g1_set_switch_mac(struct mv88e6xxx_chip *chip, u8 *addr); · 281 unmodified lines | ||
| 282 | 282 | int mv88e6185_g1_reset(struct mv88e6xxx_chip *chip); |
| 283 | 283 | int mv88e6352_g1_reset(struct mv88e6xxx_chip *chip); |
| 284 | 284 | int mv88e6250_g1_reset(struct mv88e6xxx_chip *chip); |
| 285 | −void mv88e6xxx_g1_wait_eeprom_done(struct mv88e6xxx_chip *chip); | |
| 286 | 285 | |
| 287 | 286 | int mv88e6185_g1_ppu_enable(struct mv88e6xxx_chip *chip); |
| 288 | 287 | int mv88e6185_g1_ppu_disable(struct mv88e6xxx_chip *chip); |
| @@ -340,7 +340,7 @@ int mv88e6xxx_g2_pot_clear(struct mv88e6xxx_chip *chip) · 339 unmodified lines | ||
| 340 | 340 | * Offset 0x15: EEPROM Addr (for 8-bit data access) |
| 341 | 341 | */ |
| 342 | 342 | |
| 343 | −static int mv88e6xxx_g2_eeprom_wait(struct mv88e6xxx_chip *chip) | |
| 343 | +int mv88e6xxx_g2_eeprom_wait(struct mv88e6xxx_chip *chip) | |
| 344 | 344 | { |
| 345 | 345 | int bit = __bf_shf(MV88E6XXX_G2_EEPROM_CMD_BUSY); |
| 346 | 346 | int err; |
| @@ -365,6 +365,7 @@ int mv88e6xxx_g2_trunk_clear(struct mv88e6xxx_chip *chip); · 364 unmodified lines | ||
| 365 | 365 | |
| 366 | 366 | int mv88e6xxx_g2_device_mapping_write(struct mv88e6xxx_chip *chip, int target, |
| 367 | 367 | int port); |
| 368 | +int mv88e6xxx_g2_eeprom_wait(struct mv88e6xxx_chip *chip); | |
| 368 | 369 | |
| 369 | 370 | extern const struct mv88e6xxx_irq_ops mv88e6097_watchdog_ops; |
| 370 | 371 | extern const struct mv88e6xxx_irq_ops mv88e6250_watchdog_ops; |
| @@ -1303,24 +1303,23 @@ static void ibmveth_rx_csum_helper(struct sk_buff *skb, · 1302 unmodified lines | ||
| 1303 | 1303 | * the user space for finding a flow. During this process, OVS computes |
| 1304 | 1304 | * checksum on the first packet when CHECKSUM_PARTIAL flag is set. |
| 1305 | 1305 | * |
| 1306 | − * So, re-compute TCP pseudo header checksum when configured for | |
| 1307 | − * trunk mode. | |
| 1306 | + * So, re-compute TCP pseudo header checksum. | |
| 1308 | 1307 | */ |
| 1308 | + | |
| 1309 | 1309 | if (iph_proto == IPPROTO_TCP) { |
| 1310 | 1310 | struct tcphdr *tcph = (struct tcphdr *)(skb->data + iphlen); |
| 1311 | + | |
| 1311 | 1312 | if (tcph->check == 0x0000) { |
| 1312 | 1313 | /* Recompute TCP pseudo header checksum */ |
| 1313 | − if (adapter->is_active_trunk) { | |
| 1314 | − tcphdrlen = skb->len - iphlen; | |
| 1315 | − if (skb_proto == ETH_P_IP) | |
| 1316 | − tcph->check = | |
| 1317 | − ~csum_tcpudp_magic(iph->saddr, | |
| 1318 | − iph->daddr, tcphdrlen, iph_proto, 0); | |
| 1319 | − else if (skb_proto == ETH_P_IPV6) | |
| 1320 | − tcph->check = | |
| 1321 | − ~csum_ipv6_magic(&iph6->saddr, | |
| 1322 | − &iph6->daddr, tcphdrlen, iph_proto, 0); | |
| 1323 | − } | |
| 1314 | + tcphdrlen = skb->len - iphlen; | |
| 1315 | + if (skb_proto == ETH_P_IP) | |
| 1316 | + tcph->check = | |
| 1317 | + ~csum_tcpudp_magic(iph->saddr, | |
| 1318 | + iph->daddr, tcphdrlen, iph_proto, 0); | |
| 1319 | + else if (skb_proto == ETH_P_IPV6) | |
| 1320 | + tcph->check = | |
| 1321 | + ~csum_ipv6_magic(&iph6->saddr, | |
| 1322 | + &iph6->daddr, tcphdrlen, iph_proto, 0); | |
| 1324 | 1323 | /* Setup SKB fields for checksum offload */ |
| 1325 | 1324 | skb_partial_csum_set(skb, iphlen, |
| 1326 | 1325 | offsetof(struct tcphdr, check)); |
| @@ -2655,12 +2655,14 @@ static int ice_vc_query_rxdid(struct ice_vf *vf) · 2654 unmodified lines | ||
| 2655 | 2655 | goto err; |
| 2656 | 2656 | } |
| 2657 | 2657 | |
| 2658 | − /* Read flexiflag registers to determine whether the | |
| 2659 | − * corresponding RXDID is configured and supported or not. | |
| 2660 | − * Since Legacy 16byte descriptor format is not supported, | |
| 2661 | − * start from Legacy 32byte descriptor. | |
| 2658 | + /* RXDIDs supported by DDP package can be read from the register | |
| 2659 | + * to get the supported RXDID bitmap. But the legacy 32byte RXDID | |
| 2660 | + * is not listed in DDP package, add it in the bitmap manually. | |
| 2661 | + * Legacy 16byte descriptor is not supported. | |
| 2662 | 2662 | */ |
| 2663 | − for (i = ICE_RXDID_LEGACY_1; i < ICE_FLEX_DESC_RXDID_MAX_NUM; i++) { | |
| 2663 | + rxdid->supported_rxdids |= BIT(ICE_RXDID_LEGACY_1); | |
| 2664 | + | |
| 2665 | + for (i = ICE_RXDID_FLEX_NIC; i < ICE_FLEX_DESC_RXDID_MAX_NUM; i++) { | |
| 2664 | 2666 | regval = rd32(hw, GLFLXP_RXDID_FLAGS(i, 0)); |
| 2665 | 2667 | if ((regval >> GLFLXP_RXDID_FLAGS_FLEXIFLAG_4N_S) |
| 2666 | 2668 | & GLFLXP_RXDID_FLAGS_FLEXIFLAG_4N_M) |
| @@ -2195,7 +2195,7 @@ struct rx_ring_info { · 2194 unmodified lines | ||
| 2195 | 2195 | struct sk_buff *skb; |
| 2196 | 2196 | dma_addr_t data_addr; |
| 2197 | 2197 | DEFINE_DMA_UNMAP_LEN(data_size); |
| 2198 | − dma_addr_t frag_addr[ETH_JUMBO_MTU >> PAGE_SHIFT]; | |
| 2198 | + dma_addr_t frag_addr[ETH_JUMBO_MTU >> PAGE_SHIFT ?: 1]; | |
| 2199 | 2199 | }; |
| 2200 | 2200 | |
| 2201 | 2201 | enum flow_control { |
| @@ -3172,8 +3172,8 @@ static irqreturn_t mtk_handle_irq_rx(int irq, void *_eth) · 3171 unmodified lines | ||
| 3172 | 3172 | |
| 3173 | 3173 | eth->rx_events++; |
| 3174 | 3174 | if (likely(napi_schedule_prep(ð->rx_napi))) { |
| 3175 | − __napi_schedule(ð->rx_napi); | |
| 3176 | 3175 | mtk_rx_irq_disable(eth, eth->soc->txrx.rx_irq_done_mask); |
| 3176 | + __napi_schedule(ð->rx_napi); | |
| 3177 | 3177 | } |
| 3178 | 3178 | |
| 3179 | 3179 | return IRQ_HANDLED; |
| @@ -3185,8 +3185,8 @@ static irqreturn_t mtk_handle_irq_tx(int irq, void *_eth) · 5 unmodified lines | ||
| 3185 | 3185 | |
| 3186 | 3186 | eth->tx_events++; |
| 3187 | 3187 | if (likely(napi_schedule_prep(ð->tx_napi))) { |
| 3188 | − __napi_schedule(ð->tx_napi); | |
| 3189 | 3188 | mtk_tx_irq_disable(eth, MTK_TX_DONE_INT); |
| 3189 | + __napi_schedule(ð->tx_napi); | |
| 3190 | 3190 | } |
| 3191 | 3191 | |
| 3192 | 3192 | return IRQ_HANDLED; |
| @@ -46,6 +46,7 @@ config LAN743X · 45 unmodified lines | ||
| 46 | 46 | tristate "LAN743x support" |
| 47 | 47 | depends on PCI |
| 48 | 48 | depends on PTP_1588_CLOCK_OPTIONAL |
| 49 | + select PHYLIB | |
| 49 | 50 | select FIXED_PHY |
| 50 | 51 | select CRC16 |
| 51 | 52 | select CRC32 |
| @@ -91,63 +91,137 @@ static unsigned int mana_checksum_info(struct sk_buff *skb) · 90 unmodified lines | ||
| 91 | 91 | return 0; |
| 92 | 92 | } |
| 93 | 93 | |
| 94 | +static void mana_add_sge(struct mana_tx_package *tp, struct mana_skb_head *ash, | |
| 95 | + int sg_i, dma_addr_t da, int sge_len, u32 gpa_mkey) | |
| 96 | +{ | |
| 97 | + ash->dma_handle[sg_i] = da; | |
| 98 | + ash->size[sg_i] = sge_len; | |
| 99 | + | |
| 100 | + tp->wqe_req.sgl[sg_i].address = da; | |
| 101 | + tp->wqe_req.sgl[sg_i].mem_key = gpa_mkey; | |
| 102 | + tp->wqe_req.sgl[sg_i].size = sge_len; | |
| 103 | +} | |
| 104 | + | |
| 94 | 105 | static int mana_map_skb(struct sk_buff *skb, struct mana_port_context *apc, |
| 95 | − struct mana_tx_package *tp) | |
| 106 | + struct mana_tx_package *tp, int gso_hs) | |
| 96 | 107 | { |
| 97 | 108 | struct mana_skb_head *ash = (struct mana_skb_head *)skb->head; |
| 109 | + int hsg = 1; /* num of SGEs of linear part */ | |
| 98 | 110 | struct gdma_dev *gd = apc->ac->gdma_dev; |
| 111 | + int skb_hlen = skb_headlen(skb); | |
| 112 | + int sge0_len, sge1_len = 0; | |
| 99 | 113 | struct gdma_context *gc; |
| 100 | 114 | struct device *dev; |
| 101 | 115 | skb_frag_t *frag; |
| 102 | 116 | dma_addr_t da; |
| 117 | + int sg_i; | |
| 103 | 118 | int i; |
| 104 | 119 | |
| 105 | 120 | gc = gd->gdma_context; |
| 106 | 121 | dev = gc->dev; |
| 107 | − da = dma_map_single(dev, skb->data, skb_headlen(skb), DMA_TO_DEVICE); | |
| 108 | 122 | |
| 123 | + if (gso_hs && gso_hs < skb_hlen) { | |
| 124 | + sge0_len = gso_hs; | |
| 125 | + sge1_len = skb_hlen - gso_hs; | |
| 126 | + } else { | |
| 127 | + sge0_len = skb_hlen; | |
| 128 | + } | |
| 129 | + | |
| 130 | + da = dma_map_single(dev, skb->data, sge0_len, DMA_TO_DEVICE); | |
| 109 | 131 | if (dma_mapping_error(dev, da)) |
| 110 | 132 | return -ENOMEM; |
| 111 | 133 | |
| 112 | − ash->dma_handle[0] = da; | |
| 113 | − ash->size[0] = skb_headlen(skb); | |
| 134 | + mana_add_sge(tp, ash, 0, da, sge0_len, gd->gpa_mkey); | |
| 114 | 135 | |
| 115 | − tp->wqe_req.sgl[0].address = ash->dma_handle[0]; | |
| 116 | − tp->wqe_req.sgl[0].mem_key = gd->gpa_mkey; | |
| 117 | − tp->wqe_req.sgl[0].size = ash->size[0]; | |
| 136 | + if (sge1_len) { | |
| 137 | + sg_i = 1; | |
| 138 | + da = dma_map_single(dev, skb->data + sge0_len, sge1_len, | |
| 139 | + DMA_TO_DEVICE); | |
| 140 | + if (dma_mapping_error(dev, da)) | |
| 141 | + goto frag_err; | |
| 142 | + | |
| 143 | + mana_add_sge(tp, ash, sg_i, da, sge1_len, gd->gpa_mkey); | |
| 144 | + hsg = 2; | |
| 145 | + } | |
| 118 | 146 | |
| 119 | 147 | for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) { |
| 148 | + sg_i = hsg + i; | |
| 149 | + | |
| 120 | 150 | frag = &skb_shinfo(skb)->frags[i]; |
| 121 | 151 | da = skb_frag_dma_map(dev, frag, 0, skb_frag_size(frag), |
| 122 | 152 | DMA_TO_DEVICE); |
| 123 | − | |
| 124 | 153 | if (dma_mapping_error(dev, da)) |
| 125 | 154 | goto frag_err; |
| 126 | 155 | |
| 127 | − ash->dma_handle[i + 1] = da; | |
| 128 | − ash->size[i + 1] = skb_frag_size(frag); | |
| 129 | − | |
| 130 | − tp->wqe_req.sgl[i + 1].address = ash->dma_handle[i + 1]; | |
| 131 | − tp->wqe_req.sgl[i + 1].mem_key = gd->gpa_mkey; | |
| 132 | − tp->wqe_req.sgl[i + 1].size = ash->size[i + 1]; | |
| 156 | + mana_add_sge(tp, ash, sg_i, da, skb_frag_size(frag), | |
| 157 | + gd->gpa_mkey); | |
| 133 | 158 | } |
| 134 | 159 | |
| 135 | 160 | return 0; |
| 136 | 161 | |
| 137 | 162 | frag_err: |
| 138 | − for (i = i - 1; i >= 0; i--) | |
| 139 | − dma_unmap_page(dev, ash->dma_handle[i + 1], ash->size[i + 1], | |
| 163 | + for (i = sg_i - 1; i >= hsg; i--) | |
| 164 | + dma_unmap_page(dev, ash->dma_handle[i], ash->size[i], | |
| 140 | 165 | DMA_TO_DEVICE); |
| 141 | 166 | |
| 142 | − dma_unmap_single(dev, ash->dma_handle[0], ash->size[0], DMA_TO_DEVICE); | |
| 167 | + for (i = hsg - 1; i >= 0; i--) | |
| 168 | + dma_unmap_single(dev, ash->dma_handle[i], ash->size[i], | |
| 169 | + DMA_TO_DEVICE); | |
| 143 | 170 | |
| 144 | 171 | return -ENOMEM; |
| 145 | 172 | } |
| 146 | 173 | |
| 174 | +/* Handle the case when GSO SKB linear length is too large. | |
| 175 | + * MANA NIC requires GSO packets to put only the packet header to SGE0. | |
| 176 | + * So, we need 2 SGEs for the skb linear part which contains more than the | |
| 177 | + * header. | |
| 178 | + * Return a positive value for the number of SGEs, or a negative value | |
| 179 | + * for an error. | |
| 180 | + */ | |
| 181 | +static int mana_fix_skb_head(struct net_device *ndev, struct sk_buff *skb, | |
| 182 | + int gso_hs) | |
| 183 | +{ | |
| 184 | + int num_sge = 1 + skb_shinfo(skb)->nr_frags; | |
| 185 | + int skb_hlen = skb_headlen(skb); | |
| 186 | + | |
| 187 | + if (gso_hs < skb_hlen) { | |
| 188 | + num_sge++; | |
| 189 | + } else if (gso_hs > skb_hlen) { | |
| 190 | + if (net_ratelimit()) | |
| 191 | + netdev_err(ndev, | |
| 192 | + "TX nonlinear head: hs:%d, skb_hlen:%d\n", | |
| 193 | + gso_hs, skb_hlen); | |
| 194 | + | |
| 195 | + return -EINVAL; | |
| 196 | + } | |
| 197 | + | |
| 198 | + return num_sge; | |
| 199 | +} | |
| 200 | + | |
| 201 | +/* Get the GSO packet's header size */ | |
| 202 | +static int mana_get_gso_hs(struct sk_buff *skb) | |
| 203 | +{ | |
| 204 | + int gso_hs; | |
| 205 | + | |
| 206 | + if (skb->encapsulation) { | |
| 207 | + gso_hs = skb_inner_tcp_all_headers(skb); | |
| 208 | + } else { | |
| 209 | + if (skb_shinfo(skb)->gso_type & SKB_GSO_UDP_L4) { | |
| 210 | + gso_hs = skb_transport_offset(skb) + | |
| 211 | + sizeof(struct udphdr); | |
| 212 | + } else { | |
| 213 | + gso_hs = skb_tcp_all_headers(skb); | |
| 214 | + } | |
| 215 | + } | |
| 216 | + | |
| 217 | + return gso_hs; | |
| 218 | +} | |
| 219 | + | |
| 147 | 220 | netdev_tx_t mana_start_xmit(struct sk_buff *skb, struct net_device *ndev) |
| 148 | 221 | { |
| 149 | 222 | enum mana_tx_pkt_format pkt_fmt = MANA_SHORT_PKT_FMT; |
| 150 | 223 | struct mana_port_context *apc = netdev_priv(ndev); |
| 224 | + int gso_hs = 0; /* zero for non-GSO pkts */ | |
| 151 | 225 | u16 txq_idx = skb_get_queue_mapping(skb); |
| 152 | 226 | struct gdma_dev *gd = apc->ac->gdma_dev; |
| 153 | 227 | bool ipv4 = false, ipv6 = false; |
| @@ -159,7 +233,6 @@ netdev_tx_t mana_start_xmit(struct sk_buff *skb, struct net_device *ndev) · 5 unmodified lines | ||
| 159 | 233 | struct mana_txq *txq; |
| 160 | 234 | struct mana_cq *cq; |
| 161 | 235 | int err, len; |
| 162 | − u16 ihs; | |
| 163 | 236 | |
| 164 | 237 | if (unlikely(!apc->port_is_up)) |
| 165 | 238 | goto tx_drop; |
| @@ -209,19 +282,6 @@ netdev_tx_t mana_start_xmit(struct sk_buff *skb, struct net_device *ndev) · 43 unmodified lines | ||
| 209 | 282 | pkg.wqe_req.client_data_unit = 0; |
| 210 | 283 | |
| 211 | 284 | pkg.wqe_req.num_sge = 1 + skb_shinfo(skb)->nr_frags; |
| 212 | − WARN_ON_ONCE(pkg.wqe_req.num_sge > MAX_TX_WQE_SGL_ENTRIES); | |
| 213 | − | |
| 214 | − if (pkg.wqe_req.num_sge <= ARRAY_SIZE(pkg.sgl_array)) { | |
| 215 | − pkg.wqe_req.sgl = pkg.sgl_array; | |
| 216 | − } else { | |
| 217 | − pkg.sgl_ptr = kmalloc_array(pkg.wqe_req.num_sge, | |
| 218 | − sizeof(struct gdma_sge), | |
| 219 | − GFP_ATOMIC); | |
| 220 | − if (!pkg.sgl_ptr) | |
| 221 | − goto tx_drop_count; | |
| 222 | − | |
| 223 | − pkg.wqe_req.sgl = pkg.sgl_ptr; | |
| 224 | − } | |
| 225 | 285 | |
| 226 | 286 | if (skb->protocol == htons(ETH_P_IP)) |
| 227 | 287 | ipv4 = true; |
| @@ -229,6 +289,26 @@ netdev_tx_t mana_start_xmit(struct sk_buff *skb, struct net_device *ndev) · 1 unmodified line | ||
| 229 | 289 | ipv6 = true; |
| 230 | 290 | |
| 231 | 291 | if (skb_is_gso(skb)) { |
| 292 | + int num_sge; | |
| 293 | + | |
| 294 | + gso_hs = mana_get_gso_hs(skb); | |
| 295 | + | |
| 296 | + num_sge = mana_fix_skb_head(ndev, skb, gso_hs); | |
| 297 | + if (num_sge > 0) | |
| 298 | + pkg.wqe_req.num_sge = num_sge; | |
| 299 | + else | |
| 300 | + goto tx_drop_count; | |
| 301 | + | |
| 302 | + u64_stats_update_begin(&tx_stats->syncp); | |
| 303 | + if (skb->encapsulation) { | |
| 304 | + tx_stats->tso_inner_packets++; | |
| 305 | + tx_stats->tso_inner_bytes += skb->len - gso_hs; | |
| 306 | + } else { | |
| 307 | + tx_stats->tso_packets++; | |
| 308 | + tx_stats->tso_bytes += skb->len - gso_hs; | |
| 309 | + } | |
| 310 | + u64_stats_update_end(&tx_stats->syncp); | |
| 311 | + | |
| 232 | 312 | pkg.tx_oob.s_oob.is_outer_ipv4 = ipv4; |
| 233 | 313 | pkg.tx_oob.s_oob.is_outer_ipv6 = ipv6; |
| 234 | 314 | |
| @@ -252,28 +332,6 @@ netdev_tx_t mana_start_xmit(struct sk_buff *skb, struct net_device *ndev) · 17 unmodified lines | ||
| 252 | 332 | &ipv6_hdr(skb)->daddr, 0, |
| 253 | 333 | IPPROTO_TCP, 0); |
| 254 | 334 | } |
| 255 | − | |
| 256 | − if (skb->encapsulation) { | |
| 257 | − ihs = skb_inner_tcp_all_headers(skb); | |
| 258 | − u64_stats_update_begin(&tx_stats->syncp); | |
| 259 | − tx_stats->tso_inner_packets++; | |
| 260 | − tx_stats->tso_inner_bytes += skb->len - ihs; | |
| 261 | − u64_stats_update_end(&tx_stats->syncp); | |
| 262 | − } else { | |
| 263 | − if (skb_shinfo(skb)->gso_type & SKB_GSO_UDP_L4) { | |
| 264 | − ihs = skb_transport_offset(skb) + sizeof(struct udphdr); | |
| 265 | − } else { | |
| 266 | − ihs = skb_tcp_all_headers(skb); | |
| 267 | − if (ipv6_has_hopopt_jumbo(skb)) | |
| 268 | − ihs -= sizeof(struct hop_jumbo_hdr); | |
| 269 | − } | |
| 270 | − | |
| 271 | − u64_stats_update_begin(&tx_stats->syncp); | |
| 272 | − tx_stats->tso_packets++; | |
| 273 | − tx_stats->tso_bytes += skb->len - ihs; | |
| 274 | − u64_stats_update_end(&tx_stats->syncp); | |
| 275 | − } | |
| 276 | − | |
| 277 | 335 | } else if (skb->ip_summed == CHECKSUM_PARTIAL) { |
| 278 | 336 | csum_type = mana_checksum_info(skb); |
| 279 | 337 | |
| @@ -296,11 +354,25 @@ netdev_tx_t mana_start_xmit(struct sk_buff *skb, struct net_device *ndev) · 16 unmodified lines | ||
| 296 | 354 | } else { |
| 297 | 355 | /* Can't do offload of this type of checksum */ |
| 298 | 356 | if (skb_checksum_help(skb)) |
| 299 | − goto free_sgl_ptr; | |
| 357 | + goto tx_drop_count; | |
| 300 | 358 | } |
| 301 | 359 | } |
| 302 | 360 | |
| 303 | − if (mana_map_skb(skb, apc, &pkg)) { | |
| 361 | + WARN_ON_ONCE(pkg.wqe_req.num_sge > MAX_TX_WQE_SGL_ENTRIES); | |
| 362 | + | |
| 363 | + if (pkg.wqe_req.num_sge <= ARRAY_SIZE(pkg.sgl_array)) { | |
| 364 | + pkg.wqe_req.sgl = pkg.sgl_array; | |
| 365 | + } else { | |
| 366 | + pkg.sgl_ptr = kmalloc_array(pkg.wqe_req.num_sge, | |
| 367 | + sizeof(struct gdma_sge), | |
| 368 | + GFP_ATOMIC); | |
| 369 | + if (!pkg.sgl_ptr) | |
| 370 | + goto tx_drop_count; | |
| 371 | + | |
| 372 | + pkg.wqe_req.sgl = pkg.sgl_ptr; | |
| 373 | + } | |
| 374 | + | |
| 375 | + if (mana_map_skb(skb, apc, &pkg, gso_hs)) { | |
| 304 | 376 | u64_stats_update_begin(&tx_stats->syncp); |
| 305 | 377 | tx_stats->mana_map_err++; |
| 306 | 378 | u64_stats_update_end(&tx_stats->syncp); |
| @@ -1258,11 +1330,16 @@ static void mana_unmap_skb(struct sk_buff *skb, struct mana_port_context *apc) · 951 unmodified lines | ||
| 1258 | 1330 | struct mana_skb_head *ash = (struct mana_skb_head *)skb->head; |
| 1259 | 1331 | struct gdma_context *gc = apc->ac->gdma_dev->gdma_context; |
| 1260 | 1332 | struct device *dev = gc->dev; |
| 1261 | − int i; | |
| 1333 | + int hsg, i; | |
| 1262 | 1334 | |
| 1263 | − dma_unmap_single(dev, ash->dma_handle[0], ash->size[0], DMA_TO_DEVICE); | |
| 1335 | + /* Number of SGEs of linear part */ | |
| 1336 | + hsg = (skb_is_gso(skb) && skb_headlen(skb) > ash->size[0]) ? 2 : 1; | |
| 1264 | 1337 | |
| 1265 | − for (i = 1; i < skb_shinfo(skb)->nr_frags + 1; i++) | |
| 1338 | + for (i = 0; i < hsg; i++) | |
| 1339 | + dma_unmap_single(dev, ash->dma_handle[i], ash->size[i], | |
| 1340 | + DMA_TO_DEVICE); | |
| 1341 | + | |
| 1342 | + for (i = hsg; i < skb_shinfo(skb)->nr_frags + hsg; i++) | |
| 1266 | 1343 | dma_unmap_page(dev, ash->dma_handle[i], ash->size[i], |
| 1267 | 1344 | DMA_TO_DEVICE); |
| 1268 | 1345 | } |
| @@ -1317,19 +1394,23 @@ static void mana_poll_tx_cq(struct mana_cq *cq) · 48 unmodified lines | ||
| 1317 | 1394 | case CQE_TX_VPORT_IDX_OUT_OF_RANGE: |
| 1318 | 1395 | case CQE_TX_VPORT_DISABLED: |
| 1319 | 1396 | case CQE_TX_VLAN_TAGGING_VIOLATION: |
| 1320 | − WARN_ONCE(1, "TX: CQE error %d: ignored.\n", | |
| 1321 | − cqe_oob->cqe_hdr.cqe_type); | |
| 1397 | + if (net_ratelimit()) | |
| 1398 | + netdev_err(ndev, "TX: CQE error %d\n", | |
| 1399 | + cqe_oob->cqe_hdr.cqe_type); | |
| 1400 | + | |
| 1322 | 1401 | apc->eth_stats.tx_cqe_err++; |
| 1323 | 1402 | break; |
| 1324 | 1403 | |
| 1325 | 1404 | default: |
| 1326 | − /* If the CQE type is unexpected, log an error, assert, | |
| 1327 | − * and go through the error path. | |
| 1405 | + /* If the CQE type is unknown, log an error, | |
| 1406 | + * and still free the SKB, update tail, etc. | |
| 1328 | 1407 | */ |
| 1329 | − WARN_ONCE(1, "TX: Unexpected CQE type %d: HW BUG?\n", | |
| 1330 | − cqe_oob->cqe_hdr.cqe_type); | |
| 1408 | + if (net_ratelimit()) | |
| 1409 | + netdev_err(ndev, "TX: unknown CQE type %d\n", | |
| 1410 | + cqe_oob->cqe_hdr.cqe_type); | |
| 1411 | + | |
| 1331 | 1412 | apc->eth_stats.tx_cqe_unknown_type++; |
| 1332 | − return; | |
| 1413 | + break; | |
| 1333 | 1414 | } |
| 1334 | 1415 | |
| 1335 | 1416 | if (WARN_ON_ONCE(txq->gdma_txq_id != completions[i].wq_num)) |
| @@ -110,9 +110,9 @@ struct qed_ll2_info { · 109 unmodified lines | ||
| 110 | 110 | enum core_tx_dest tx_dest; |
| 111 | 111 | u8 tx_stats_en; |
| 112 | 112 | bool main_func_queue; |
| 113 | + struct qed_ll2_cbs cbs; | |
| 113 | 114 | struct qed_ll2_rx_queue rx_queue; |
| 114 | 115 | struct qed_ll2_tx_queue tx_queue; |
| 115 | − struct qed_ll2_cbs cbs; | |
| 116 | 116 | }; |
| 117 | 117 | |
| 118 | 118 | extern const struct qed_ll2_ops qed_ll2_ops_pass; |
| @@ -4,6 +4,7 @@ · 3 unmodified lines | ||
| 4 | 4 | * Copyright (C) 2022 Renesas Electronics Corporation |
| 5 | 5 | */ |
| 6 | 6 | |
| 7 | +#include <linux/clk.h> | |
| 7 | 8 | #include <linux/dma-mapping.h> |
| 8 | 9 | #include <linux/err.h> |
| 9 | 10 | #include <linux/etherdevice.h> |
| @@ -1049,7 +1050,7 @@ static void rswitch_rmac_setting(struct rswitch_etha *etha, const u8 *mac) · 1039 unmodified lines | ||
| 1049 | 1050 | static void rswitch_etha_enable_mii(struct rswitch_etha *etha) |
| 1050 | 1051 | { |
| 1051 | 1052 | rswitch_modify(etha->addr, MPIC, MPIC_PSMCS_MASK | MPIC_PSMHT_MASK, |
| 1052 | − MPIC_PSMCS(0x05) | MPIC_PSMHT(0x06)); | |
| 1053 | + MPIC_PSMCS(etha->psmcs) | MPIC_PSMHT(0x06)); | |
| 1053 | 1054 | rswitch_modify(etha->addr, MPSM, 0, MPSM_MFF_C45); |
| 1054 | 1055 | } |
| 1055 | 1056 | |
| @@ -1693,6 +1694,12 @@ static void rswitch_etha_init(struct rswitch_private *priv, int index) · 637 unmodified lines | ||
| 1693 | 1694 | etha->index = index; |
| 1694 | 1695 | etha->addr = priv->addr + RSWITCH_ETHA_OFFSET + index * RSWITCH_ETHA_SIZE; |
| 1695 | 1696 | etha->coma_addr = priv->addr; |
| 1697 | + | |
| 1698 | + /* MPIC.PSMCS = (clk [MHz] / (MDC frequency [MHz] * 2) - 1. | |
| 1699 | + * Calculating PSMCS value as MDC frequency = 2.5MHz. So, multiply | |
| 1700 | + * both the numerator and the denominator by 10. | |
| 1701 | + */ | |
| 1702 | + etha->psmcs = clk_get_rate(priv->clk) / 100000 / (25 * 2) - 1; | |
| 1696 | 1703 | } |
| 1697 | 1704 | |
| 1698 | 1705 | static int rswitch_device_alloc(struct rswitch_private *priv, int index) |
| @@ -1900,6 +1907,10 @@ static int renesas_eth_sw_probe(struct platform_device *pdev) · 201 unmodified lines | ||
| 1900 | 1907 | return -ENOMEM; |
| 1901 | 1908 | spin_lock_init(&priv->lock); |
| 1902 | 1909 | |
| 1910 | + priv->clk = devm_clk_get(&pdev->dev, NULL); | |
| 1911 | + if (IS_ERR(priv->clk)) | |
| 1912 | + return PTR_ERR(priv->clk); | |
| 1913 | + | |
| 1903 | 1914 | attr = soc_device_match(rswitch_soc_no_speed_change); |
| 1904 | 1915 | if (attr) |
| 1905 | 1916 | priv->etha_no_runtime_change = true; |
| @@ -915,6 +915,7 @@ struct rswitch_etha { · 914 unmodified lines | ||
| 915 | 915 | bool external_phy; |
| 916 | 916 | struct mii_bus *mii; |
| 917 | 917 | phy_interface_t phy_interface; |
| 918 | + u32 psmcs; | |
| 918 | 919 | u8 mac_addr[MAX_ADDR_LEN]; |
| 919 | 920 | int link; |
| 920 | 921 | int speed; |
| @@ -1012,6 +1013,7 @@ struct rswitch_private { · 91 unmodified lines | ||
| 1012 | 1013 | struct rswitch_mfwd mfwd; |
| 1013 | 1014 | |
| 1014 | 1015 | spinlock_t lock; /* lock interrupt registers' control */ |
| 1016 | + struct clk *clk; | |
| 1015 | 1017 | |
| 1016 | 1018 | bool etha_no_runtime_change; |
| 1017 | 1019 | bool gwca_halt; |
| @@ -104,6 +104,7 @@ struct stm32_ops { · 103 unmodified lines | ||
| 104 | 104 | int (*parse_data)(struct stm32_dwmac *dwmac, |
| 105 | 105 | struct device *dev); |
| 106 | 106 | u32 syscfg_eth_mask; |
| 107 | + bool clk_rx_enable_in_suspend; | |
| 107 | 108 | }; |
| 108 | 109 | |
| 109 | 110 | static int stm32_dwmac_init(struct plat_stmmacenet_data *plat_dat) |
| @@ -121,7 +122,8 @@ static int stm32_dwmac_init(struct plat_stmmacenet_data *plat_dat) · 11 unmodified lines | ||
| 121 | 122 | if (ret) |
| 122 | 123 | return ret; |
| 123 | 124 | |
| 124 | − if (!dwmac->dev->power.is_suspended) { | |
| 125 | + if (!dwmac->ops->clk_rx_enable_in_suspend || | |
| 126 | + !dwmac->dev->power.is_suspended) { | |
| 125 | 127 | ret = clk_prepare_enable(dwmac->clk_rx); |
| 126 | 128 | if (ret) { |
| 127 | 129 | clk_disable_unprepare(dwmac->clk_tx); |
| @@ -508,7 +510,8 @@ static struct stm32_ops stm32mp1_dwmac_data = { · 380 unmodified lines | ||
| 508 | 510 | .suspend = stm32mp1_suspend, |
| 509 | 511 | .resume = stm32mp1_resume, |
| 510 | 512 | .parse_data = stm32mp1_parse_data, |
| 511 | − .syscfg_eth_mask = SYSCFG_MP1_ETH_MASK | |
| 513 | + .syscfg_eth_mask = SYSCFG_MP1_ETH_MASK, | |
| 514 | + .clk_rx_enable_in_suspend = true | |
| 512 | 515 | }; |
| 513 | 516 | |
| 514 | 517 | static const struct of_device_id stm32_dwmac_match[] = { |
| @@ -6012,33 +6012,6 @@ static irqreturn_t stmmac_msi_intr_rx(int irq, void *data) · 6011 unmodified lines | ||
| 6012 | 6012 | return IRQ_HANDLED; |
| 6013 | 6013 | } |
| 6014 | 6014 | |
| 6015 | −#ifdef CONFIG_NET_POLL_CONTROLLER | |
| 6016 | −/* Polling receive - used by NETCONSOLE and other diagnostic tools | |
| 6017 | − * to allow network I/O with interrupts disabled. | |
| 6018 | − */ | |
| 6019 | −static void stmmac_poll_controller(struct net_device *dev) | |
| 6020 | −{ | |
| 6021 | − struct stmmac_priv *priv = netdev_priv(dev); | |
| 6022 | − int i; | |
| 6023 | − | |
| 6024 | − /* If adapter is down, do nothing */ | |
| 6025 | − if (test_bit(STMMAC_DOWN, &priv->state)) | |
| 6026 | − return; | |
| 6027 | − | |
| 6028 | − if (priv->plat->flags & STMMAC_FLAG_MULTI_MSI_EN) { | |
| 6029 | − for (i = 0; i < priv->plat->rx_queues_to_use; i++) | |
| 6030 | − stmmac_msi_intr_rx(0, &priv->dma_conf.rx_queue[i]); | |
| 6031 | − | |
| 6032 | − for (i = 0; i < priv->plat->tx_queues_to_use; i++) | |
| 6033 | − stmmac_msi_intr_tx(0, &priv->dma_conf.tx_queue[i]); | |
| 6034 | − } else { | |
| 6035 | − disable_irq(dev->irq); | |
| 6036 | − stmmac_interrupt(dev->irq, dev); | |
| 6037 | − enable_irq(dev->irq); | |
| 6038 | − } | |
| 6039 | −} | |
| 6040 | −#endif | |
| 6041 | − | |
| 6042 | 6015 | /** |
| 6043 | 6016 | * stmmac_ioctl - Entry point for the Ioctl |
| 6044 | 6017 | * @dev: Device pointer. |
| @@ -6999,9 +6972,6 @@ static const struct net_device_ops stmmac_netdev_ops = { · 954 unmodified lines | ||
| 6999 | 6972 | .ndo_get_stats64 = stmmac_get_stats64, |
| 7000 | 6973 | .ndo_setup_tc = stmmac_setup_tc, |
| 7001 | 6974 | .ndo_select_queue = stmmac_select_queue, |
| 7002 | −#ifdef CONFIG_NET_POLL_CONTROLLER | |
| 7003 | − .ndo_poll_controller = stmmac_poll_controller, | |
| 7004 | −#endif | |
| 7005 | 6975 | .ndo_set_mac_address = stmmac_set_mac_address, |
| 7006 | 6976 | .ndo_vlan_rx_add_vid = stmmac_vlan_rx_add_vid, |
| 7007 | 6977 | .ndo_vlan_rx_kill_vid = stmmac_vlan_rx_kill_vid, |
| @@ -874,7 +874,7 @@ static int __maybe_unused stmmac_pltfr_resume(struct device *dev) · 873 unmodified lines | ||
| 874 | 874 | struct platform_device *pdev = to_platform_device(dev); |
| 875 | 875 | int ret; |
| 876 | 876 | |
| 877 | − ret = stmmac_pltfr_init(pdev, priv->plat->bsp_priv); | |
| 877 | + ret = stmmac_pltfr_init(pdev, priv->plat); | |
| 878 | 878 | if (ret) |
| 879 | 879 | return ret; |
| 880 | 880 | |
| @@ -1747,9 +1747,10 @@ static int am65_cpsw_nuss_init_tx_chns(struct am65_cpsw_common *common) · 1746 unmodified lines | ||
| 1747 | 1747 | } |
| 1748 | 1748 | |
| 1749 | 1749 | tx_chn->irq = k3_udma_glue_tx_get_irq(tx_chn->tx_chn); |
| 1750 | − if (tx_chn->irq <= 0) { | |
| 1750 | + if (tx_chn->irq < 0) { | |
| 1751 | 1751 | dev_err(dev, "Failed to get tx dma irq %d\n", |
| 1752 | 1752 | tx_chn->irq); |
| 1753 | + ret = tx_chn->irq; | |
| 1753 | 1754 | goto err; |
| 1754 | 1755 | } |
| 1755 | 1756 | |
| @@ -316,12 +316,12 @@ static int prueth_init_tx_chns(struct prueth_emac *emac) · 315 unmodified lines | ||
| 316 | 316 | goto fail; |
| 317 | 317 | } |
| 318 | 318 | |
| 319 | − tx_chn->irq = k3_udma_glue_tx_get_irq(tx_chn->tx_chn); | |
| 320 | − if (tx_chn->irq <= 0) { | |
| 321 | − ret = -EINVAL; | |
| 319 | + ret = k3_udma_glue_tx_get_irq(tx_chn->tx_chn); | |
| 320 | + if (ret < 0) { | |
| 322 | 321 | netdev_err(ndev, "failed to get tx irq\n"); |
| 323 | 322 | goto fail; |
| 324 | 323 | } |
| 324 | + tx_chn->irq = ret; | |
| 325 | 325 | |
| 326 | 326 | snprintf(tx_chn->name, sizeof(tx_chn->name), "%s-tx%d", |
| 327 | 327 | dev_name(dev), tx_chn->id); |
| @@ -90,7 +90,9 @@ static int __must_check __smsc75xx_read_reg(struct usbnet *dev, u32 index, · 89 unmodified lines | ||
| 90 | 90 | ret = fn(dev, USB_VENDOR_REQUEST_READ_REGISTER, USB_DIR_IN |
| 91 | 91 | | USB_TYPE_VENDOR | USB_RECIP_DEVICE, |
| 92 | 92 | 0, index, &buf, 4); |
| 93 | − if (unlikely(ret < 0)) { | |
| 93 | + if (unlikely(ret < 4)) { | |
| 94 | + ret = ret < 0 ? ret : -ENODATA; | |
| 95 | + | |
| 94 | 96 | netdev_warn(dev->net, "Failed to read reg index 0x%08x: %d\n", |
| 95 | 97 | index, ret); |
| 96 | 98 | return ret; |
| @@ -34,6 +34,8 @@ · 33 unmodified lines | ||
| 34 | 34 | #define TDM_PPPOHT_SLIC_MAXIN |
| 35 | 35 | #define RX_BD_ERRORS (R_CD_S | R_OV_S | R_CR_S | R_AB_S | R_NO_S | R_LG_S) |
| 36 | 36 | |
| 37 | +static int uhdlc_close(struct net_device *dev); | |
| 38 | + | |
| 37 | 39 | static struct ucc_tdm_info utdm_primary_info = { |
| 38 | 40 | .uf_info = { |
| 39 | 41 | .tsa = 0, |
| @@ -708,6 +710,7 @@ static int uhdlc_open(struct net_device *dev) · 668 unmodified lines | ||
| 708 | 710 | hdlc_device *hdlc = dev_to_hdlc(dev); |
| 709 | 711 | struct ucc_hdlc_private *priv = hdlc->priv; |
| 710 | 712 | struct ucc_tdm *utdm = priv->utdm; |
| 713 | + int rc = 0; | |
| 711 | 714 | |
| 712 | 715 | if (priv->hdlc_busy != 1) { |
| 713 | 716 | if (request_irq(priv->ut_info->uf_info.irq, |
| @@ -731,10 +734,13 @@ static int uhdlc_open(struct net_device *dev) · 17 unmodified lines | ||
| 731 | 734 | napi_enable(&priv->napi); |
| 732 | 735 | netdev_reset_queue(dev); |
| 733 | 736 | netif_start_queue(dev); |
| 734 | − hdlc_open(dev); | |
| 737 | + | |
| 738 | + rc = hdlc_open(dev); | |
| 739 | + if (rc) | |
| 740 | + uhdlc_close(dev); | |
| 735 | 741 | } |
| 736 | 742 | |
| 737 | − return 0; | |
| 743 | + return rc; | |
| 738 | 744 | } |
| 739 | 745 | |
| 740 | 746 | static void uhdlc_memclean(struct ucc_hdlc_private *priv) |
| @@ -824,6 +830,8 @@ static int uhdlc_close(struct net_device *dev) · 83 unmodified lines | ||
| 824 | 830 | netdev_reset_queue(dev); |
| 825 | 831 | priv->hdlc_busy = 0; |
| 826 | 832 | |
| 833 | + hdlc_close(dev); | |
| 834 | + | |
| 827 | 835 | return 0; |
| 828 | 836 | } |
| 829 | 837 | |
| @@ -442,7 +442,12 @@ struct brcmf_scan_params_v2_le { · 441 unmodified lines | ||
| 442 | 442 | * fixed parameter portion is assumed, otherwise |
| 443 | 443 | * ssid in the fixed portion is ignored |
| 444 | 444 | */ |
| 445 | − __le16 channel_list[1]; /* list of chanspecs */ | |
| 445 | + union { | |
| 446 | + __le16 padding; /* Reserve space for at least 1 entry for abort | |
| 447 | + * which uses an on stack brcmf_scan_params_v2_le | |
| 448 | + */ | |
| 449 | + DECLARE_FLEX_ARRAY(__le16, channel_list); /* chanspecs */ | |
| 450 | + }; | |
| 446 | 451 | }; |
| 447 | 452 | |
| 448 | 453 | struct brcmf_scan_results { |
| @@ -702,7 +707,7 @@ struct brcmf_sta_info_le { · 253 unmodified lines | ||
| 702 | 707 | |
| 703 | 708 | struct brcmf_chanspec_list { |
| 704 | 709 | __le32 count; /* # of entries */ |
| 705 | − __le32 element[1]; /* variable length uint32 list */ | |
| 710 | + __le32 element[]; /* variable length uint32 list */ | |
| 706 | 711 | }; |
| 707 | 712 | |
| 708 | 713 | /* |
| @@ -310,9 +310,9 @@ struct iwl_fw_ini_fifo_hdr { · 309 unmodified lines | ||
| 310 | 310 | struct iwl_fw_ini_error_dump_range { |
| 311 | 311 | __le32 range_data_size; |
| 312 | 312 | union { |
| 313 | − __le32 internal_base_addr; | |
| 314 | − __le64 dram_base_addr; | |
| 315 | − __le32 page_num; | |
| 313 | + __le32 internal_base_addr __packed; | |
| 314 | + __le64 dram_base_addr __packed; | |
| 315 | + __le32 page_num __packed; | |
| 316 | 316 | struct iwl_fw_ini_fifo_hdr fifo_hdr; |
| 317 | 317 | struct iwl_cmd_header fw_pkt_hdr; |
| 318 | 318 | }; |
| @@ -802,7 +802,7 @@ out: · 801 unmodified lines | ||
| 802 | 802 | mvm->nvm_data->bands[0].n_channels = 1; |
| 803 | 803 | mvm->nvm_data->bands[0].n_bitrates = 1; |
| 804 | 804 | mvm->nvm_data->bands[0].bitrates = |
| 805 | − (void *)((u8 *)mvm->nvm_data->channels + 1); | |
| 805 | + (void *)(mvm->nvm_data->channels + 1); | |
| 806 | 806 | mvm->nvm_data->bands[0].bitrates->hw_value = 10; |
| 807 | 807 | } |
| 808 | 808 | |
| @@ -731,73 +731,78 @@ static void iwl_mvm_mld_vif_cfg_changed_station(struct iwl_mvm *mvm, · 730 unmodified lines | ||
| 731 | 731 | |
| 732 | 732 | mvmvif->associated = vif->cfg.assoc; |
| 733 | 733 | |
| 734 | − if (!(changes & BSS_CHANGED_ASSOC)) | |
| 735 | − return; | |
| 736 | − | |
| 737 | − if (vif->cfg.assoc) { | |
| 738 | − /* clear statistics to get clean beacon counter */ | |
| 739 | − iwl_mvm_request_statistics(mvm, true); | |
| 740 | − iwl_mvm_sf_update(mvm, vif, false); | |
| 741 | − iwl_mvm_power_vif_assoc(mvm, vif); | |
| 742 | − | |
| 743 | − for_each_mvm_vif_valid_link(mvmvif, i) { | |
| 744 | − memset(&mvmvif->link[i]->beacon_stats, 0, | |
| 745 | − sizeof(mvmvif->link[i]->beacon_stats)); | |
| 734 | + if (changes & BSS_CHANGED_ASSOC) { | |
| 735 | + if (vif->cfg.assoc) { | |
| 736 | + /* clear statistics to get clean beacon counter */ | |
| 737 | + iwl_mvm_request_statistics(mvm, true); | |
| 738 | + iwl_mvm_sf_update(mvm, vif, false); | |
| 739 | + iwl_mvm_power_vif_assoc(mvm, vif); | |
| 740 | + | |
| 741 | + for_each_mvm_vif_valid_link(mvmvif, i) { | |
| 742 | + memset(&mvmvif->link[i]->beacon_stats, 0, | |
| 743 | + sizeof(mvmvif->link[i]->beacon_stats)); | |
| 744 | + | |
| 745 | + if (vif->p2p) { | |
| 746 | + iwl_mvm_update_smps(mvm, vif, | |
| 747 | + IWL_MVM_SMPS_REQ_PROT, | |
| 748 | + IEEE80211_SMPS_DYNAMIC, i); | |
| 749 | + } | |
| 750 | + | |
| 751 | + rcu_read_lock(); | |
| 752 | + link_conf = rcu_dereference(vif->link_conf[i]); | |
| 753 | + if (link_conf && !link_conf->dtim_period) | |
| 754 | + protect = true; | |
| 755 | + rcu_read_unlock(); | |
| 756 | + } | |
| 746 | 757 | |
| 747 | − if (vif->p2p) { | |
| 748 | − iwl_mvm_update_smps(mvm, vif, | |
| 749 | − IWL_MVM_SMPS_REQ_PROT, | |
| 750 | − IEEE80211_SMPS_DYNAMIC, i); | |
| 758 | + if (!test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status) && | |
| 759 | + protect) { | |
| 760 | + /* If we're not restarting and still haven't | |
| 761 | + * heard a beacon (dtim period unknown) then | |
| 762 | + * make sure we still have enough minimum time | |
| 763 | + * remaining in the time event, since the auth | |
| 764 | + * might actually have taken quite a while | |
| 765 | + * (especially for SAE) and so the remaining | |
| 766 | + * time could be small without us having heard | |
| 767 | + * a beacon yet. | |
| 768 | + */ | |
| 769 | + iwl_mvm_protect_assoc(mvm, vif, 0); | |
| 751 | 770 | } |
| 752 | 771 | |
| 753 | − rcu_read_lock(); | |
| 754 | − link_conf = rcu_dereference(vif->link_conf[i]); | |
| 755 | − if (link_conf && !link_conf->dtim_period) | |
| 756 | − protect = true; | |
| 757 | − rcu_read_unlock(); | |
| 758 | − } | |
| 772 | + iwl_mvm_sf_update(mvm, vif, false); | |
| 773 | + | |
| 774 | + /* FIXME: need to decide about misbehaving AP handling */ | |
| 775 | + iwl_mvm_power_vif_assoc(mvm, vif); | |
| 776 | + } else if (iwl_mvm_mld_vif_have_valid_ap_sta(mvmvif)) { | |
| 777 | + iwl_mvm_mei_host_disassociated(mvm); | |
| 759 | 778 | |
| 760 | − if (!test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status) && | |
| 761 | − protect) { | |
| 762 | − /* If we're not restarting and still haven't | |
| 763 | − * heard a beacon (dtim period unknown) then | |
| 764 | − * make sure we still have enough minimum time | |
| 765 | − * remaining in the time event, since the auth | |
| 766 | − * might actually have taken quite a while | |
| 767 | − * (especially for SAE) and so the remaining | |
| 768 | − * time could be small without us having heard | |
| 769 | − * a beacon yet. | |
| 779 | + /* If update fails - SF might be running in associated | |
| 780 | + * mode while disassociated - which is forbidden. | |
| 770 | 781 | */ |
| 771 | − iwl_mvm_protect_assoc(mvm, vif, 0); | |
| 782 | + ret = iwl_mvm_sf_update(mvm, vif, false); | |
| 783 | + WARN_ONCE(ret && | |
| 784 | + !test_bit(IWL_MVM_STATUS_HW_RESTART_REQUESTED, | |
| 785 | + &mvm->status), | |
| 786 | + "Failed to update SF upon disassociation\n"); | |
| 787 | + | |
| 788 | + /* If we get an assert during the connection (after the | |
| 789 | + * station has been added, but before the vif is set | |
| 790 | + * to associated), mac80211 will re-add the station and | |
| 791 | + * then configure the vif. Since the vif is not | |
| 792 | + * associated, we would remove the station here and | |
| 793 | + * this would fail the recovery. | |
| 794 | + */ | |
| 795 | + iwl_mvm_mld_vif_delete_all_stas(mvm, vif); | |
| 772 | 796 | } |
| 773 | 797 | |
| 774 | − iwl_mvm_sf_update(mvm, vif, false); | |
| 775 | − | |
| 776 | − /* FIXME: need to decide about misbehaving AP handling */ | |
| 777 | − iwl_mvm_power_vif_assoc(mvm, vif); | |
| 778 | − } else if (iwl_mvm_mld_vif_have_valid_ap_sta(mvmvif)) { | |
| 779 | − iwl_mvm_mei_host_disassociated(mvm); | |
| 780 | − | |
| 781 | − /* If update fails - SF might be running in associated | |
| 782 | − * mode while disassociated - which is forbidden. | |
| 783 | − */ | |
| 784 | − ret = iwl_mvm_sf_update(mvm, vif, false); | |
| 785 | − WARN_ONCE(ret && | |
| 786 | − !test_bit(IWL_MVM_STATUS_HW_RESTART_REQUESTED, | |
| 787 | − &mvm->status), | |
| 788 | − "Failed to update SF upon disassociation\n"); | |
| 789 | − | |
| 790 | − /* If we get an assert during the connection (after the | |
| 791 | − * station has been added, but before the vif is set | |
| 792 | − * to associated), mac80211 will re-add the station and | |
| 793 | − * then configure the vif. Since the vif is not | |
| 794 | − * associated, we would remove the station here and | |
| 795 | − * this would fail the recovery. | |
| 796 | − */ | |
| 797 | − iwl_mvm_mld_vif_delete_all_stas(mvm, vif); | |
| 798 | + iwl_mvm_bss_info_changed_station_assoc(mvm, vif, changes); | |
| 798 | 799 | } |
| 799 | 800 | |
| 800 | − iwl_mvm_bss_info_changed_station_assoc(mvm, vif, changes); | |
| 801 | + if (changes & BSS_CHANGED_PS) { | |
| 802 | + ret = iwl_mvm_power_update_mac(mvm); | |
| 803 | + if (ret) | |
| 804 | + IWL_ERR(mvm, "failed to update power mode\n"); | |
| 805 | + } | |
| 801 | 806 | } |
| 802 | 807 | |
| 803 | 808 | static void |
| @@ -2342,7 +2342,7 @@ iwl_mvm_scan_umac_fill_general_p_v12(struct iwl_mvm *mvm, · 2341 unmodified lines | ||
| 2342 | 2342 | if (gen_flags & IWL_UMAC_SCAN_GEN_FLAGS_V2_FRAGMENTED_LMAC2) |
| 2343 | 2343 | gp->num_of_fragments[SCAN_HB_LMAC_IDX] = IWL_SCAN_NUM_OF_FRAGS; |
| 2344 | 2344 | |
| 2345 | − if (version < 12) { | |
| 2345 | + if (version < 16) { | |
| 2346 | 2346 | gp->scan_start_mac_or_link_id = scan_vif->id; |
| 2347 | 2347 | } else { |
| 2348 | 2348 | struct iwl_mvm_vif_link_info *link_info; |
| @@ -1612,6 +1612,7 @@ static void iwl_mvm_rx_tx_cmd_single(struct iwl_mvm *mvm, · 1611 unmodified lines | ||
| 1612 | 1612 | iwl_trans_free_tx_cmd(mvm->trans, info->driver_data[1]); |
| 1613 | 1613 | |
| 1614 | 1614 | memset(&info->status, 0, sizeof(info->status)); |
| 1615 | + info->flags &= ~(IEEE80211_TX_STAT_ACK | IEEE80211_TX_STAT_TX_FILTERED); | |
| 1615 | 1616 | |
| 1616 | 1617 | /* inform mac80211 about what happened with the frame */ |
| 1617 | 1618 | switch (status & TX_STATUS_MSK) { |
| @@ -1964,6 +1965,8 @@ static void iwl_mvm_tx_reclaim(struct iwl_mvm *mvm, int sta_id, int tid, · 346 unmodified lines | ||
| 1964 | 1965 | */ |
| 1965 | 1966 | if (!is_flush) |
| 1966 | 1967 | info->flags |= IEEE80211_TX_STAT_ACK; |
| 1968 | + else | |
| 1969 | + info->flags &= ~IEEE80211_TX_STAT_ACK; | |
| 1967 | 1970 | } |
| 1968 | 1971 | |
| 1969 | 1972 | /* |
| @@ -918,9 +918,17 @@ void mwifiex_11n_rxba_sync_event(struct mwifiex_private *priv, · 917 unmodified lines | ||
| 918 | 918 | |
| 919 | 919 | mwifiex_dbg_dump(priv->adapter, EVT_D, "RXBA_SYNC event:", |
| 920 | 920 | event_buf, len); |
| 921 | − while (tlv_buf_left >= sizeof(*tlv_rxba)) { | |
| 921 | + while (tlv_buf_left > sizeof(*tlv_rxba)) { | |
| 922 | 922 | tlv_type = le16_to_cpu(tlv_rxba->header.type); |
| 923 | 923 | tlv_len = le16_to_cpu(tlv_rxba->header.len); |
| 924 | + if (size_add(sizeof(tlv_rxba->header), tlv_len) > tlv_buf_left) { | |
| 925 | + mwifiex_dbg(priv->adapter, WARN, | |
| 926 | + "TLV size (%zu) overflows event_buf buf_left=%d\n", | |
| 927 | + size_add(sizeof(tlv_rxba->header), tlv_len), | |
| 928 | + tlv_buf_left); | |
| 929 | + return; | |
| 930 | + } | |
| 931 | + | |
| 924 | 932 | if (tlv_type != TLV_TYPE_RXBA_SYNC) { |
| 925 | 933 | mwifiex_dbg(priv->adapter, ERROR, |
| 926 | 934 | "Wrong TLV id=0x%x\n", tlv_type); |
| @@ -929,6 +937,14 @@ void mwifiex_11n_rxba_sync_event(struct mwifiex_private *priv, · 2 unmodified lines | ||
| 929 | 937 | |
| 930 | 938 | tlv_seq_num = le16_to_cpu(tlv_rxba->seq_num); |
| 931 | 939 | tlv_bitmap_len = le16_to_cpu(tlv_rxba->bitmap_len); |
| 940 | + if (size_add(sizeof(*tlv_rxba), tlv_bitmap_len) > tlv_buf_left) { | |
| 941 | + mwifiex_dbg(priv->adapter, WARN, | |
| 942 | + "TLV size (%zu) overflows event_buf buf_left=%d\n", | |
| 943 | + size_add(sizeof(*tlv_rxba), tlv_bitmap_len), | |
| 944 | + tlv_buf_left); | |
| 945 | + return; | |
| 946 | + } | |
| 947 | + | |
| 932 | 948 | mwifiex_dbg(priv->adapter, INFO, |
| 933 | 949 | "%pM tid=%d seq_num=%d bitmap_len=%d\n", |
| 934 | 950 | tlv_rxba->mac, tlv_rxba->tid, tlv_seq_num, |
| @@ -965,8 +981,8 @@ void mwifiex_11n_rxba_sync_event(struct mwifiex_private *priv, · 30 unmodified lines | ||
| 965 | 981 | } |
| 966 | 982 | } |
| 967 | 983 | |
| 968 | − tlv_buf_left -= (sizeof(*tlv_rxba) + tlv_len); | |
| 969 | − tmp = (u8 *)tlv_rxba + tlv_len + sizeof(*tlv_rxba); | |
| 984 | + tlv_buf_left -= (sizeof(tlv_rxba->header) + tlv_len); | |
| 985 | + tmp = (u8 *)tlv_rxba + sizeof(tlv_rxba->header) + tlv_len; | |
| 970 | 986 | tlv_rxba = (struct mwifiex_ie_types_rxba_sync *)tmp; |
| 971 | 987 | } |
| 972 | 988 | } |
| @@ -779,7 +779,7 @@ struct mwifiex_ie_types_rxba_sync { · 778 unmodified lines | ||
| 779 | 779 | u8 reserved; |
| 780 | 780 | __le16 seq_num; |
| 781 | 781 | __le16 bitmap_len; |
| 782 | − u8 bitmap[1]; | |
| 782 | + u8 bitmap[]; | |
| 783 | 783 | } __packed; |
| 784 | 784 | |
| 785 | 785 | struct chan_band_param_set { |
| @@ -86,7 +86,8 @@ int mwifiex_process_rx_packet(struct mwifiex_private *priv, · 85 unmodified lines | ||
| 86 | 86 | rx_pkt_len = le16_to_cpu(local_rx_pd->rx_pkt_length); |
| 87 | 87 | rx_pkt_hdr = (void *)local_rx_pd + rx_pkt_off; |
| 88 | 88 | |
| 89 | − if (sizeof(*rx_pkt_hdr) + rx_pkt_off > skb->len) { | |
| 89 | + if (sizeof(rx_pkt_hdr->eth803_hdr) + sizeof(rfc1042_header) + | |
| 90 | + rx_pkt_off > skb->len) { | |
| 90 | 91 | mwifiex_dbg(priv->adapter, ERROR, |
| 91 | 92 | "wrong rx packet offset: len=%d, rx_pkt_off=%d\n", |
| 92 | 93 | skb->len, rx_pkt_off); |
| @@ -95,12 +96,13 @@ int mwifiex_process_rx_packet(struct mwifiex_private *priv, · 2 unmodified lines | ||
| 95 | 96 | return -1; |
| 96 | 97 | } |
| 97 | 98 | |
| 98 | − if ((!memcmp(&rx_pkt_hdr->rfc1042_hdr, bridge_tunnel_header, | |
| 99 | − sizeof(bridge_tunnel_header))) || | |
| 100 | − (!memcmp(&rx_pkt_hdr->rfc1042_hdr, rfc1042_header, | |
| 101 | − sizeof(rfc1042_header)) && | |
| 102 | − ntohs(rx_pkt_hdr->rfc1042_hdr.snap_type) != ETH_P_AARP && | |
| 103 | − ntohs(rx_pkt_hdr->rfc1042_hdr.snap_type) != ETH_P_IPX)) { | |
| 99 | + if (sizeof(*rx_pkt_hdr) + rx_pkt_off <= skb->len && | |
| 100 | + ((!memcmp(&rx_pkt_hdr->rfc1042_hdr, bridge_tunnel_header, | |
| 101 | + sizeof(bridge_tunnel_header))) || | |
| 102 | + (!memcmp(&rx_pkt_hdr->rfc1042_hdr, rfc1042_header, | |
| 103 | + sizeof(rfc1042_header)) && | |
| 104 | + ntohs(rx_pkt_hdr->rfc1042_hdr.snap_type) != ETH_P_AARP && | |
| 105 | + ntohs(rx_pkt_hdr->rfc1042_hdr.snap_type) != ETH_P_IPX))) { | |
| 104 | 106 | /* |
| 105 | 107 | * Replace the 803 header and rfc1042 header (llc/snap) with an |
| 106 | 108 | * EthernetII header, keep the src/dst and snap_type |
| @@ -93,13 +93,13 @@ __mt76_get_rxwi(struct mt76_dev *dev) · 92 unmodified lines | ||
| 93 | 93 | { |
| 94 | 94 | struct mt76_txwi_cache *t = NULL; |
| 95 | 95 | |
| 96 | − spin_lock(&dev->wed_lock); | |
| 96 | + spin_lock_bh(&dev->wed_lock); | |
| 97 | 97 | if (!list_empty(&dev->rxwi_cache)) { |
| 98 | 98 | t = list_first_entry(&dev->rxwi_cache, struct mt76_txwi_cache, |
| 99 | 99 | list); |
| 100 | 100 | list_del(&t->list); |
| 101 | 101 | } |
| 102 | − spin_unlock(&dev->wed_lock); | |
| 102 | + spin_unlock_bh(&dev->wed_lock); | |
| 103 | 103 | |
| 104 | 104 | return t; |
| 105 | 105 | } |
| @@ -145,9 +145,9 @@ mt76_put_rxwi(struct mt76_dev *dev, struct mt76_txwi_cache *t) · 39 unmodified lines | ||
| 145 | 145 | if (!t) |
| 146 | 146 | return; |
| 147 | 147 | |
| 148 | − spin_lock(&dev->wed_lock); | |
| 148 | + spin_lock_bh(&dev->wed_lock); | |
| 149 | 149 | list_add(&t->list, &dev->rxwi_cache); |
| 150 | − spin_unlock(&dev->wed_lock); | |
| 150 | + spin_unlock_bh(&dev->wed_lock); | |
| 151 | 151 | } |
| 152 | 152 | EXPORT_SYMBOL_GPL(mt76_put_rxwi); |
| 153 | 153 | |
| @@ -131,15 +131,8 @@ u8 mt76x02_get_lna_gain(struct mt76x02_dev *dev, · 130 unmodified lines | ||
| 131 | 131 | s8 *lna_2g, s8 *lna_5g, |
| 132 | 132 | struct ieee80211_channel *chan) |
| 133 | 133 | { |
| 134 | − u16 val; | |
| 135 | 134 | u8 lna; |
| 136 | 135 | |
| 137 | − val = mt76x02_eeprom_get(dev, MT_EE_NIC_CONF_1); | |
| 138 | − if (val & MT_EE_NIC_CONF_1_LNA_EXT_2G) | |
| 139 | − *lna_2g = 0; | |
| 140 | − if (val & MT_EE_NIC_CONF_1_LNA_EXT_5G) | |
| 141 | − memset(lna_5g, 0, sizeof(s8) * 3); | |
| 142 | − | |
| 143 | 136 | if (chan->band == NL80211_BAND_2GHZ) |
| 144 | 137 | lna = *lna_2g; |
| 145 | 138 | else if (chan->hw_value <= 64) |
| @@ -256,7 +256,8 @@ void mt76x2_read_rx_gain(struct mt76x02_dev *dev) · 255 unmodified lines | ||
| 256 | 256 | struct ieee80211_channel *chan = dev->mphy.chandef.chan; |
| 257 | 257 | int channel = chan->hw_value; |
| 258 | 258 | s8 lna_5g[3], lna_2g; |
| 259 | − u8 lna; | |
| 259 | + bool use_lna; | |
| 260 | + u8 lna = 0; | |
| 260 | 261 | u16 val; |
| 261 | 262 | |
| 262 | 263 | if (chan->band == NL80211_BAND_2GHZ) |
| @@ -275,7 +276,15 @@ void mt76x2_read_rx_gain(struct mt76x02_dev *dev) · 12 unmodified lines | ||
| 275 | 276 | dev->cal.rx.mcu_gain |= (lna_5g[1] & 0xff) << 16; |
| 276 | 277 | dev->cal.rx.mcu_gain |= (lna_5g[2] & 0xff) << 24; |
| 277 | 278 | |
| 278 | − lna = mt76x02_get_lna_gain(dev, &lna_2g, lna_5g, chan); | |
| 279 | + val = mt76x02_eeprom_get(dev, MT_EE_NIC_CONF_1); | |
| 280 | + if (chan->band == NL80211_BAND_2GHZ) | |
| 281 | + use_lna = !(val & MT_EE_NIC_CONF_1_LNA_EXT_2G); | |
| 282 | + else | |
| 283 | + use_lna = !(val & MT_EE_NIC_CONF_1_LNA_EXT_5G); | |
| 284 | + | |
| 285 | + if (use_lna) | |
| 286 | + lna = mt76x02_get_lna_gain(dev, &lna_2g, lna_5g, chan); | |
| 287 | + | |
| 279 | 288 | dev->cal.rx.lna_gain = mt76x02_sign_extend(lna, 8); |
| 280 | 289 | } |
| 281 | 290 | EXPORT_SYMBOL_GPL(mt76x2_read_rx_gain); |
| @@ -46,6 +46,7 @@ struct rtw8723du_efuse { · 45 unmodified lines | ||
| 46 | 46 | u8 vender_id[2]; /* 0x100 */ |
| 47 | 47 | u8 product_id[2]; /* 0x102 */ |
| 48 | 48 | u8 usb_option; /* 0x104 */ |
| 49 | + u8 res5[2]; /* 0x105 */ | |
| 49 | 50 | u8 mac_addr[ETH_ALEN]; /* 0x107 */ |
| 50 | 51 | }; |
| 51 | 52 | |
| @@ -229,6 +229,7 @@ int pcie_aer_is_native(struct pci_dev *dev) · 228 unmodified lines | ||
| 229 | 229 | |
| 230 | 230 | return pcie_ports_native || host->native_aer; |
| 231 | 231 | } |
| 232 | +EXPORT_SYMBOL_NS_GPL(pcie_aer_is_native, CXL); | |
| 232 | 233 | |
| 233 | 234 | static int pci_enable_pcie_error_reporting(struct pci_dev *dev) |
| 234 | 235 | { |
| @@ -29,10 +29,8 @@ extern bool pcie_ports_dpc_native; · 28 unmodified lines | ||
| 29 | 29 | |
| 30 | 30 | #ifdef CONFIG_PCIEAER |
| 31 | 31 | int pcie_aer_init(void); |
| 32 | −int pcie_aer_is_native(struct pci_dev *dev); | |
| 33 | 32 | #else |
| 34 | 33 | static inline int pcie_aer_init(void) { return 0; } |
| 35 | −static inline int pcie_aer_is_native(struct pci_dev *dev) { return 0; } | |
| 36 | 34 | #endif |
| 37 | 35 | |
| 38 | 36 | #ifdef CONFIG_HOTPLUG_PCI_PCIE |
| @@ -19,6 +19,7 @@ · 18 unmodified lines | ||
| 19 | 19 | #include <linux/init.h> |
| 20 | 20 | #include <linux/interrupt.h> |
| 21 | 21 | #include <linux/io.h> |
| 22 | +#include <linux/iopoll.h> | |
| 22 | 23 | #include <linux/module.h> |
| 23 | 24 | #include <linux/slab.h> |
| 24 | 25 | |
| @@ -231,19 +232,15 @@ static inline u32 ipc_data_readl(struct intel_scu_ipc_dev *scu, u32 offset) · 206 unmodified lines | ||
| 231 | 232 | /* Wait till scu status is busy */ |
| 232 | 233 | static inline int busy_loop(struct intel_scu_ipc_dev *scu) |
| 233 | 234 | { |
| 234 | − unsigned long end = jiffies + IPC_TIMEOUT; | |
| 235 | − | |
| 236 | − do { | |
| 237 | − u32 status; | |
| 238 | − | |
| 239 | − status = ipc_read_status(scu); | |
| 240 | − if (!(status & IPC_STATUS_BUSY)) | |
| 241 | − return (status & IPC_STATUS_ERR) ? -EIO : 0; | |
| 235 | + u8 status; | |
| 236 | + int err; | |
| 242 | 237 | |
| 243 | − usleep_range(50, 100); | |
| 244 | − } while (time_before(jiffies, end)); | |
| 238 | + err = readx_poll_timeout(ipc_read_status, scu, status, !(status & IPC_STATUS_BUSY), | |
| 239 | + 100, jiffies_to_usecs(IPC_TIMEOUT)); | |
| 240 | + if (err) | |
| 241 | + return err; | |
| 245 | 242 | |
| 246 | − return -ETIMEDOUT; | |
| 243 | + return (status & IPC_STATUS_ERR) ? -EIO : 0; | |
| 247 | 244 | } |
| 248 | 245 | |
| 249 | 246 | /* Wait till ipc ioc interrupt is received or timeout in 10 HZ */ |
| @@ -251,10 +248,12 @@ static inline int ipc_wait_for_interrupt(struct intel_scu_ipc_dev *scu) · 1 unmodified line | ||
| 251 | 248 | { |
| 252 | 249 | int status; |
| 253 | 250 | |
| 254 | − if (!wait_for_completion_timeout(&scu->cmd_complete, IPC_TIMEOUT)) | |
| 255 | − return -ETIMEDOUT; | |
| 251 | + wait_for_completion_timeout(&scu->cmd_complete, IPC_TIMEOUT); | |
| 256 | 252 | |
| 257 | 253 | status = ipc_read_status(scu); |
| 254 | + if (status & IPC_STATUS_BUSY) | |
| 255 | + return -ETIMEDOUT; | |
| 256 | + | |
| 258 | 257 | if (status & IPC_STATUS_ERR) |
| 259 | 258 | return -EIO; |
| 260 | 259 | |
| @@ -266,6 +265,24 @@ static int intel_scu_ipc_check_status(struct intel_scu_ipc_dev *scu) · 5 unmodified lines | ||
| 266 | 265 | return scu->irq > 0 ? ipc_wait_for_interrupt(scu) : busy_loop(scu); |
| 267 | 266 | } |
| 268 | 267 | |
| 268 | +static struct intel_scu_ipc_dev *intel_scu_ipc_get(struct intel_scu_ipc_dev *scu) | |
| 269 | +{ | |
| 270 | + u8 status; | |
| 271 | + | |
| 272 | + if (!scu) | |
| 273 | + scu = ipcdev; | |
| 274 | + if (!scu) | |
| 275 | + return ERR_PTR(-ENODEV); | |
| 276 | + | |
| 277 | + status = ipc_read_status(scu); | |
| 278 | + if (status & IPC_STATUS_BUSY) { | |
| 279 | + dev_dbg(&scu->dev, "device is busy\n"); | |
| 280 | + return ERR_PTR(-EBUSY); | |
| 281 | + } | |
| 282 | + | |
| 283 | + return scu; | |
| 284 | +} | |
| 285 | + | |
| 269 | 286 | /* Read/Write power control(PMIC in Langwell, MSIC in PenWell) registers */ |
| 270 | 287 | static int pwr_reg_rdwr(struct intel_scu_ipc_dev *scu, u16 *addr, u8 *data, |
| 271 | 288 | u32 count, u32 op, u32 id) |
| @@ -279,11 +296,10 @@ static int pwr_reg_rdwr(struct intel_scu_ipc_dev *scu, u16 *addr, u8 *data, · 7 unmodified lines | ||
| 279 | 296 | memset(cbuf, 0, sizeof(cbuf)); |
| 280 | 297 | |
| 281 | 298 | mutex_lock(&ipclock); |
| 282 | − if (!scu) | |
| 283 | − scu = ipcdev; | |
| 284 | − if (!scu) { | |
| 299 | + scu = intel_scu_ipc_get(scu); | |
| 300 | + if (IS_ERR(scu)) { | |
| 285 | 301 | mutex_unlock(&ipclock); |
| 286 | − return -ENODEV; | |
| 302 | + return PTR_ERR(scu); | |
| 287 | 303 | } |
| 288 | 304 | |
| 289 | 305 | for (nc = 0; nc < count; nc++, offset += 2) { |
| @@ -438,13 +454,12 @@ int intel_scu_ipc_dev_simple_command(struct intel_scu_ipc_dev *scu, int cmd, · 148 unmodified lines | ||
| 438 | 454 | int err; |
| 439 | 455 | |
| 440 | 456 | mutex_lock(&ipclock); |
| 441 | − if (!scu) | |
| 442 | − scu = ipcdev; | |
| 443 | − if (!scu) { | |
| 457 | + scu = intel_scu_ipc_get(scu); | |
| 458 | + if (IS_ERR(scu)) { | |
| 444 | 459 | mutex_unlock(&ipclock); |
| 445 | − return -ENODEV; | |
| 460 | + return PTR_ERR(scu); | |
| 446 | 461 | } |
| 447 | − scu = ipcdev; | |
| 462 | + | |
| 448 | 463 | cmdval = sub << 12 | cmd; |
| 449 | 464 | ipc_command(scu, cmdval); |
| 450 | 465 | err = intel_scu_ipc_check_status(scu); |
| @@ -484,11 +499,10 @@ int intel_scu_ipc_dev_command_with_size(struct intel_scu_ipc_dev *scu, int cmd, · 33 unmodified lines | ||
| 484 | 499 | return -EINVAL; |
| 485 | 500 | |
| 486 | 501 | mutex_lock(&ipclock); |
| 487 | − if (!scu) | |
| 488 | − scu = ipcdev; | |
| 489 | − if (!scu) { | |
| 502 | + scu = intel_scu_ipc_get(scu); | |
| 503 | + if (IS_ERR(scu)) { | |
| 490 | 504 | mutex_unlock(&ipclock); |
| 491 | − return -ENODEV; | |
| 505 | + return PTR_ERR(scu); | |
| 492 | 506 | } |
| 493 | 507 | |
| 494 | 508 | memcpy(inbuf, in, inlen); |
| @@ -4116,9 +4116,11 @@ static void hotkey_resume(void) · 4115 unmodified lines | ||
| 4116 | 4116 | { |
| 4117 | 4117 | tpacpi_disable_brightness_delay(); |
| 4118 | 4118 | |
| 4119 | + mutex_lock(&hotkey_mutex); | |
| 4119 | 4120 | if (hotkey_status_set(true) < 0 || |
| 4120 | 4121 | hotkey_mask_set(hotkey_acpi_mask) < 0) |
| 4121 | 4122 | pr_err("error while attempting to reset the event firmware interface\n"); |
| 4123 | + mutex_unlock(&hotkey_mutex); | |
| 4122 | 4124 | |
| 4123 | 4125 | tpacpi_send_radiosw_update(); |
| 4124 | 4126 | tpacpi_input_send_tabletsw(); |
| @@ -300,7 +300,7 @@ config NVMEM_REBOOT_MODE · 299 unmodified lines | ||
| 300 | 300 | |
| 301 | 301 | config POWER_MLXBF |
| 302 | 302 | tristate "Mellanox BlueField power handling driver" |
| 303 | − depends on (GPIO_MLXBF2 && ACPI) | |
| 303 | + depends on (GPIO_MLXBF2 || GPIO_MLXBF3) && ACPI | |
| 304 | 304 | help |
| 305 | 305 | This driver supports reset or low power mode handling for Mellanox BlueField. |
| 306 | 306 | |
| @@ -1,4 +1,4 @@ | ||
| 1 | −// SPDX-License-Identifier: GPL-2.0-only or BSD-3-Clause | |
| 1 | +// SPDX-License-Identifier: GPL-2.0-only OR BSD-3-Clause | |
| 2 | 2 | |
| 3 | 3 | /* |
| 4 | 4 | * Copyright (c) 2022 NVIDIA CORPORATION & AFFILIATES. |
| @@ -121,7 +121,7 @@ static int vexpress_reset_probe(struct platform_device *pdev) · 120 unmodified lines | ||
| 121 | 121 | return PTR_ERR(regmap); |
| 122 | 122 | dev_set_drvdata(&pdev->dev, regmap); |
| 123 | 123 | |
| 124 | − switch ((enum vexpress_reset_func)match->data) { | |
| 124 | + switch ((uintptr_t)match->data) { | |
| 125 | 125 | case FUNC_SHUTDOWN: |
| 126 | 126 | vexpress_power_off_device = &pdev->dev; |
| 127 | 127 | pm_power_off = vexpress_power_off; |
| @@ -769,6 +769,7 @@ config BATTERY_RT5033 · 768 unmodified lines | ||
| 769 | 769 | config CHARGER_RT5033 |
| 770 | 770 | tristate "RT5033 battery charger support" |
| 771 | 771 | depends on MFD_RT5033 |
| 772 | + depends on EXTCON || !EXTCON | |
| 772 | 773 | help |
| 773 | 774 | This adds support for battery charger in Richtek RT5033 PMIC. |
| 774 | 775 | The device supports pre-charge mode, fast charge mode and |
| @@ -115,7 +115,6 @@ struct ab8500_btemp { · 114 unmodified lines | ||
| 115 | 115 | static enum power_supply_property ab8500_btemp_props[] = { |
| 116 | 116 | POWER_SUPPLY_PROP_PRESENT, |
| 117 | 117 | POWER_SUPPLY_PROP_ONLINE, |
| 118 | − POWER_SUPPLY_PROP_TECHNOLOGY, | |
| 119 | 118 | POWER_SUPPLY_PROP_TEMP, |
| 120 | 119 | }; |
| 121 | 120 | |
| @@ -532,12 +531,6 @@ static int ab8500_btemp_get_property(struct power_supply *psy, · 410 unmodified lines | ||
| 532 | 531 | else |
| 533 | 532 | val->intval = 1; |
| 534 | 533 | break; |
| 535 | − case POWER_SUPPLY_PROP_TECHNOLOGY: | |
| 536 | − if (di->bm->bi) | |
| 537 | − val->intval = di->bm->bi->technology; | |
| 538 | − else | |
| 539 | − val->intval = POWER_SUPPLY_TECHNOLOGY_UNKNOWN; | |
| 540 | − break; | |
| 541 | 534 | case POWER_SUPPLY_PROP_TEMP: |
| 542 | 535 | val->intval = ab8500_btemp_get_temp(di); |
| 543 | 536 | break; |
| @@ -662,7 +655,7 @@ static char *supply_interface[] = { · 118 unmodified lines | ||
| 662 | 655 | |
| 663 | 656 | static const struct power_supply_desc ab8500_btemp_desc = { |
| 664 | 657 | .name = "ab8500_btemp", |
| 665 | − .type = POWER_SUPPLY_TYPE_BATTERY, | |
| 658 | + .type = POWER_SUPPLY_TYPE_UNKNOWN, | |
| 666 | 659 | .properties = ab8500_btemp_props, |
| 667 | 660 | .num_properties = ARRAY_SIZE(ab8500_btemp_props), |
| 668 | 661 | .get_property = ab8500_btemp_get_property, |
| @@ -1720,7 +1720,7 @@ static char *supply_interface[] = { · 1719 unmodified lines | ||
| 1720 | 1720 | |
| 1721 | 1721 | static const struct power_supply_desc ab8500_chargalg_desc = { |
| 1722 | 1722 | .name = "ab8500_chargalg", |
| 1723 | − .type = POWER_SUPPLY_TYPE_BATTERY, | |
| 1723 | + .type = POWER_SUPPLY_TYPE_UNKNOWN, | |
| 1724 | 1724 | .properties = ab8500_chargalg_props, |
| 1725 | 1725 | .num_properties = ARRAY_SIZE(ab8500_chargalg_props), |
| 1726 | 1726 | .get_property = ab8500_chargalg_get_property, |
| @@ -324,7 +324,7 @@ static int mt6370_chg_toggle_cfo(struct mt6370_priv *priv) · 323 unmodified lines | ||
| 324 | 324 | |
| 325 | 325 | if (fl_strobe) { |
| 326 | 326 | dev_err(priv->dev, "Flash led is still in strobe mode\n"); |
| 327 | − return ret; | |
| 327 | + return -EINVAL; | |
| 328 | 328 | } |
| 329 | 329 | |
| 330 | 330 | /* cfo off */ |
| @@ -482,6 +482,13 @@ int power_supply_uevent(const struct device *dev, struct kobj_uevent_env *env) · 481 unmodified lines | ||
| 482 | 482 | if (ret) |
| 483 | 483 | return ret; |
| 484 | 484 | |
| 485 | + /* | |
| 486 | + * Kernel generates KOBJ_REMOVE uevent in device removal path, after | |
| 487 | + * resources have been freed. Exit early to avoid use-after-free. | |
| 488 | + */ | |
| 489 | + if (psy->removing) | |
| 490 | + return 0; | |
| 491 | + | |
| 485 | 492 | prop_buf = (char *)get_zeroed_page(GFP_KERNEL); |
| 486 | 493 | if (!prop_buf) |
| 487 | 494 | return -ENOMEM; |
| @@ -1045,6 +1045,13 @@ static void rk817_charging_monitor(struct work_struct *work) · 1044 unmodified lines | ||
| 1045 | 1045 | queue_delayed_work(system_wq, &charger->work, msecs_to_jiffies(8000)); |
| 1046 | 1046 | } |
| 1047 | 1047 | |
| 1048 | +static void rk817_cleanup_node(void *data) | |
| 1049 | +{ | |
| 1050 | + struct device_node *node = data; | |
| 1051 | + | |
| 1052 | + of_node_put(node); | |
| 1053 | +} | |
| 1054 | + | |
| 1048 | 1055 | static int rk817_charger_probe(struct platform_device *pdev) |
| 1049 | 1056 | { |
| 1050 | 1057 | struct rk808 *rk808 = dev_get_drvdata(pdev->dev.parent); |
| @@ -1061,11 +1068,13 @@ static int rk817_charger_probe(struct platform_device *pdev) · 10 unmodified lines | ||
| 1061 | 1068 | if (!node) |
| 1062 | 1069 | return -ENODEV; |
| 1063 | 1070 | |
| 1071 | + ret = devm_add_action_or_reset(&pdev->dev, rk817_cleanup_node, node); | |
| 1072 | + if (ret) | |
| 1073 | + return ret; | |
| 1074 | + | |
| 1064 | 1075 | charger = devm_kzalloc(&pdev->dev, sizeof(*charger), GFP_KERNEL); |
| 1065 | − if (!charger) { | |
| 1066 | − of_node_put(node); | |
| 1076 | + if (!charger) | |
| 1067 | 1077 | return -ENOMEM; |
| 1068 | − } | |
| 1069 | 1078 | |
| 1070 | 1079 | charger->rk808 = rk808; |
| 1071 | 1080 | |
| @@ -1211,3 +1220,4 @@ MODULE_DESCRIPTION("Battery power supply driver for RK817 PMIC"); · 139 unmodified lines | ||
| 1211 | 1220 | MODULE_AUTHOR("Maya Matuszczyk <maccraft123mc@gmail.com>"); |
| 1212 | 1221 | MODULE_AUTHOR("Chris Morgan <macromorgan@hotmail.com>"); |
| 1213 | 1222 | MODULE_LICENSE("GPL"); |
| 1223 | +MODULE_ALIAS("platform:rk817-charger"); | |
| @@ -598,8 +598,8 @@ static int rt9467_run_aicl(struct rt9467_chg_data *data) · 597 unmodified lines | ||
| 598 | 598 | |
| 599 | 599 | reinit_completion(&data->aicl_done); |
| 600 | 600 | ret = wait_for_completion_timeout(&data->aicl_done, msecs_to_jiffies(3500)); |
| 601 | − if (ret) | |
| 602 | − return ret; | |
| 601 | + if (ret == 0) | |
| 602 | + return -ETIMEDOUT; | |
| 603 | 603 | |
| 604 | 604 | ret = rt9467_get_value_from_ranges(data, F_IAICR, RT9467_RANGE_IAICR, &aicr_get); |
| 605 | 605 | if (ret) { |
| @@ -384,7 +384,8 @@ static int ucs1002_get_property(struct power_supply *psy, · 383 unmodified lines | ||
| 384 | 384 | case POWER_SUPPLY_PROP_USB_TYPE: |
| 385 | 385 | return ucs1002_get_usb_type(info, val); |
| 386 | 386 | case POWER_SUPPLY_PROP_HEALTH: |
| 387 | − return val->intval = info->health; | |
| 387 | + val->intval = info->health; | |
| 388 | + return 0; | |
| 388 | 389 | case POWER_SUPPLY_PROP_PRESENT: |
| 389 | 390 | val->intval = info->present; |
| 390 | 391 | return 0; |
| @@ -4046,7 +4046,6 @@ ptp_ocp_device_init(struct ptp_ocp *bp, struct pci_dev *pdev) · 4045 unmodified lines | ||
| 4046 | 4046 | return 0; |
| 4047 | 4047 | |
| 4048 | 4048 | out: |
| 4049 | − ptp_ocp_dev_release(&bp->dev); | |
| 4050 | 4049 | put_device(&bp->dev); |
| 4051 | 4050 | return err; |
| 4052 | 4051 | } |
| @@ -5542,6 +5542,8 @@ regulator_register(struct device *dev, · 5541 unmodified lines | ||
| 5542 | 5542 | goto rinse; |
| 5543 | 5543 | } |
| 5544 | 5544 | device_initialize(&rdev->dev); |
| 5545 | + dev_set_drvdata(&rdev->dev, rdev); | |
| 5546 | + rdev->dev.class = ®ulator_class; | |
| 5545 | 5547 | spin_lock_init(&rdev->err_lock); |
| 5546 | 5548 | |
| 5547 | 5549 | /* |
| @@ -5603,11 +5605,9 @@ regulator_register(struct device *dev, · 55 unmodified lines | ||
| 5603 | 5605 | rdev->supply_name = regulator_desc->supply_name; |
| 5604 | 5606 | |
| 5605 | 5607 | /* register with sysfs */ |
| 5606 | − rdev->dev.class = ®ulator_class; | |
| 5607 | 5608 | rdev->dev.parent = config->dev; |
| 5608 | 5609 | dev_set_name(&rdev->dev, "regulator.%lu", |
| 5609 | 5610 | (unsigned long) atomic_inc_return(®ulator_no)); |
| 5610 | − dev_set_drvdata(&rdev->dev, rdev); | |
| 5611 | 5611 | |
| 5612 | 5612 | /* set regulator constraints */ |
| 5613 | 5613 | if (init_data) |
| @@ -5724,15 +5724,11 @@ wash: · 110 unmodified lines | ||
| 5724 | 5724 | mutex_lock(®ulator_list_mutex); |
| 5725 | 5725 | regulator_ena_gpio_free(rdev); |
| 5726 | 5726 | mutex_unlock(®ulator_list_mutex); |
| 5727 | − put_device(&rdev->dev); | |
| 5728 | − rdev = NULL; | |
| 5729 | 5727 | clean: |
| 5730 | 5728 | if (dangling_of_gpiod) |
| 5731 | 5729 | gpiod_put(config->ena_gpiod); |
| 5732 | − if (rdev && rdev->dev.of_node) | |
| 5733 | − of_node_put(rdev->dev.of_node); | |
| 5734 | − kfree(rdev); | |
| 5735 | 5730 | kfree(config); |
| 5731 | + put_device(&rdev->dev); | |
| 5736 | 5732 | rinse: |
| 5737 | 5733 | if (dangling_cfg_gpiod) |
| 5738 | 5734 | gpiod_put(cfg->ena_gpiod); |
| @@ -43,7 +43,7 @@ struct mt6358_regulator_info { · 42 unmodified lines | ||
| 43 | 43 | .desc = { \ |
| 44 | 44 | .name = #vreg, \ |
| 45 | 45 | .of_match = of_match_ptr(match), \ |
| 46 | − .ops = &mt6358_volt_range_ops, \ | |
| 46 | + .ops = &mt6358_buck_ops, \ | |
| 47 | 47 | .type = REGULATOR_VOLTAGE, \ |
| 48 | 48 | .id = MT6358_ID_##vreg, \ |
| 49 | 49 | .owner = THIS_MODULE, \ |
| @@ -139,7 +139,7 @@ struct mt6358_regulator_info { · 89 unmodified lines | ||
| 139 | 139 | .desc = { \ |
| 140 | 140 | .name = #vreg, \ |
| 141 | 141 | .of_match = of_match_ptr(match), \ |
| 142 | − .ops = &mt6358_volt_range_ops, \ | |
| 142 | + .ops = &mt6358_buck_ops, \ | |
| 143 | 143 | .type = REGULATOR_VOLTAGE, \ |
| 144 | 144 | .id = MT6366_ID_##vreg, \ |
| 145 | 145 | .owner = THIS_MODULE, \ |
| @@ -450,7 +450,7 @@ static unsigned int mt6358_regulator_get_mode(struct regulator_dev *rdev) · 304 unmodified lines | ||
| 450 | 450 | } |
| 451 | 451 | } |
| 452 | 452 | |
| 453 | −static const struct regulator_ops mt6358_volt_range_ops = { | |
| 453 | +static const struct regulator_ops mt6358_buck_ops = { | |
| 454 | 454 | .list_voltage = regulator_list_voltage_linear, |
| 455 | 455 | .map_voltage = regulator_map_voltage_linear, |
| 456 | 456 | .set_voltage_sel = regulator_set_voltage_sel_regmap, |
| @@ -464,6 +464,18 @@ static const struct regulator_ops mt6358_volt_range_ops = { · 7 unmodified lines | ||
| 464 | 464 | .get_mode = mt6358_regulator_get_mode, |
| 465 | 465 | }; |
| 466 | 466 | |
| 467 | +static const struct regulator_ops mt6358_volt_range_ops = { | |
| 468 | + .list_voltage = regulator_list_voltage_linear, | |
| 469 | + .map_voltage = regulator_map_voltage_linear, | |
| 470 | + .set_voltage_sel = regulator_set_voltage_sel_regmap, | |
| 471 | + .get_voltage_sel = mt6358_get_buck_voltage_sel, | |
| 472 | + .set_voltage_time_sel = regulator_set_voltage_time_sel, | |
| 473 | + .enable = regulator_enable_regmap, | |
| 474 | + .disable = regulator_disable_regmap, | |
| 475 | + .is_enabled = regulator_is_enabled_regmap, | |
| 476 | + .get_status = mt6358_get_status, | |
| 477 | +}; | |
| 478 | + | |
| 467 | 479 | static const struct regulator_ops mt6358_volt_table_ops = { |
| 468 | 480 | .list_voltage = regulator_list_voltage_table, |
| 469 | 481 | .map_voltage = regulator_map_voltage_iterate, |
| @@ -518,12 +518,12 @@ struct zfcp_port *zfcp_port_enqueue(struct zfcp_adapter *adapter, u64 wwpn, · 517 unmodified lines | ||
| 518 | 518 | if (port) { |
| 519 | 519 | put_device(&port->dev); |
| 520 | 520 | retval = -EEXIST; |
| 521 | − goto err_out; | |
| 521 | + goto err_put; | |
| 522 | 522 | } |
| 523 | 523 | |
| 524 | 524 | port = kzalloc(sizeof(struct zfcp_port), GFP_KERNEL); |
| 525 | 525 | if (!port) |
| 526 | − goto err_out; | |
| 526 | + goto err_put; | |
| 527 | 527 | |
| 528 | 528 | rwlock_init(&port->unit_list_lock); |
| 529 | 529 | INIT_LIST_HEAD(&port->unit_list); |
| @@ -546,7 +546,7 @@ struct zfcp_port *zfcp_port_enqueue(struct zfcp_adapter *adapter, u64 wwpn, · 16 unmodified lines | ||
| 546 | 546 | |
| 547 | 547 | if (dev_set_name(&port->dev, "0x%016llx", (unsigned long long)wwpn)) { |
| 548 | 548 | kfree(port); |
| 549 | − goto err_out; | |
| 549 | + goto err_put; | |
| 550 | 550 | } |
| 551 | 551 | retval = -EINVAL; |
| 552 | 552 | |
| @@ -563,7 +563,8 @@ struct zfcp_port *zfcp_port_enqueue(struct zfcp_adapter *adapter, u64 wwpn, · 10 unmodified lines | ||
| 563 | 563 | |
| 564 | 564 | return port; |
| 565 | 565 | |
| 566 | −err_out: | |
| 566 | +err_put: | |
| 567 | 567 | zfcp_ccw_adapter_put(adapter); |
| 568 | +err_out: | |
| 568 | 569 | return ERR_PTR(retval); |
| 569 | 570 | } |
| @@ -27,7 +27,7 @@ · 26 unmodified lines | ||
| 27 | 27 | |
| 28 | 28 | #define DRV_NAME "fnic" |
| 29 | 29 | #define DRV_DESCRIPTION "Cisco FCoE HBA Driver" |
| 30 | −#define DRV_VERSION "1.6.0.56" | |
| 30 | +#define DRV_VERSION "1.6.0.57" | |
| 31 | 31 | #define PFX DRV_NAME ": " |
| 32 | 32 | #define DFX DRV_NAME "%d: " |
| 33 | 33 | |
| @@ -237,6 +237,8 @@ struct fnic { · 203 unmodified lines | ||
| 237 | 237 | unsigned int cq_count; |
| 238 | 238 | |
| 239 | 239 | struct mutex sgreset_mutex; |
| 240 | + spinlock_t sgreset_lock; /* lock for sgreset */ | |
| 241 | + struct scsi_cmnd *sgreset_sc; | |
| 240 | 242 | struct dentry *fnic_stats_debugfs_host; |
| 241 | 243 | struct dentry *fnic_stats_debugfs_file; |
| 242 | 244 | struct dentry *fnic_reset_debugfs_file; |
| @@ -52,6 +52,8 @@ struct fnic_io_req { · 51 unmodified lines | ||
| 52 | 52 | unsigned long start_time; /* in jiffies */ |
| 53 | 53 | struct completion *abts_done; /* completion for abts */ |
| 54 | 54 | struct completion *dr_done; /* completion for device reset */ |
| 55 | + unsigned int tag; | |
| 56 | + struct scsi_cmnd *sc; /* midlayer's cmd pointer */ | |
| 55 | 57 | }; |
| 56 | 58 | |
| 57 | 59 | enum fnic_port_speeds { |
| @@ -754,6 +754,8 @@ static int fnic_probe(struct pci_dev *pdev, const struct pci_device_id *ent) · 753 unmodified lines | ||
| 754 | 754 | for (i = 0; i < FNIC_IO_LOCKS; i++) |
| 755 | 755 | spin_lock_init(&fnic->io_req_lock[i]); |
| 756 | 756 | |
| 757 | + spin_lock_init(&fnic->sgreset_lock); | |
| 758 | + | |
| 757 | 759 | err = -ENOMEM; |
| 758 | 760 | fnic->io_req_pool = mempool_create_slab_pool(2, fnic_io_req_cache); |
| 759 | 761 | if (!fnic->io_req_pool) |
| @@ -1047,9 +1047,9 @@ static void fnic_fcpio_itmf_cmpl_handler(struct fnic *fnic, · 1046 unmodified lines | ||
| 1047 | 1047 | { |
| 1048 | 1048 | u8 type; |
| 1049 | 1049 | u8 hdr_status; |
| 1050 | − struct fcpio_tag tag; | |
| 1050 | + struct fcpio_tag ftag; | |
| 1051 | 1051 | u32 id; |
| 1052 | − struct scsi_cmnd *sc; | |
| 1052 | + struct scsi_cmnd *sc = NULL; | |
| 1053 | 1053 | struct fnic_io_req *io_req; |
| 1054 | 1054 | struct fnic_stats *fnic_stats = &fnic->fnic_stats; |
| 1055 | 1055 | struct abort_stats *abts_stats = &fnic->fnic_stats.abts_stats; |
| @@ -1058,27 +1058,43 @@ static void fnic_fcpio_itmf_cmpl_handler(struct fnic *fnic, · 2 unmodified lines | ||
| 1058 | 1058 | unsigned long flags; |
| 1059 | 1059 | spinlock_t *io_lock; |
| 1060 | 1060 | unsigned long start_time; |
| 1061 | + unsigned int tag; | |
| 1061 | 1062 | |
| 1062 | − fcpio_header_dec(&desc->hdr, &type, &hdr_status, &tag); | |
| 1063 | − fcpio_tag_id_dec(&tag, &id); | |
| 1063 | + fcpio_header_dec(&desc->hdr, &type, &hdr_status, &ftag); | |
| 1064 | + fcpio_tag_id_dec(&ftag, &id); | |
| 1064 | 1065 | |
| 1065 | − if ((id & FNIC_TAG_MASK) >= fnic->fnic_max_tag_id) { | |
| 1066 | + tag = id & FNIC_TAG_MASK; | |
| 1067 | + if (tag == fnic->fnic_max_tag_id) { | |
| 1068 | + if (!(id & FNIC_TAG_DEV_RST)) { | |
| 1069 | + shost_printk(KERN_ERR, fnic->lport->host, | |
| 1070 | + "Tag out of range id 0x%x hdr status = %s\n", | |
| 1071 | + id, fnic_fcpio_status_to_str(hdr_status)); | |
| 1072 | + return; | |
| 1073 | + } | |
| 1074 | + } else if (tag > fnic->fnic_max_tag_id) { | |
| 1066 | 1075 | shost_printk(KERN_ERR, fnic->lport->host, |
| 1067 | − "Tag out of range tag %x hdr status = %s\n", | |
| 1068 | − id, fnic_fcpio_status_to_str(hdr_status)); | |
| 1076 | + "Tag out of range tag 0x%x hdr status = %s\n", | |
| 1077 | + tag, fnic_fcpio_status_to_str(hdr_status)); | |
| 1069 | 1078 | return; |
| 1070 | 1079 | } |
| 1071 | 1080 | |
| 1072 | − sc = scsi_host_find_tag(fnic->lport->host, id & FNIC_TAG_MASK); | |
| 1081 | + if ((tag == fnic->fnic_max_tag_id) && (id & FNIC_TAG_DEV_RST)) { | |
| 1082 | + sc = fnic->sgreset_sc; | |
| 1083 | + io_lock = &fnic->sgreset_lock; | |
| 1084 | + } else { | |
| 1085 | + sc = scsi_host_find_tag(fnic->lport->host, id & FNIC_TAG_MASK); | |
| 1086 | + io_lock = fnic_io_lock_hash(fnic, sc); | |
| 1087 | + } | |
| 1088 | + | |
| 1073 | 1089 | WARN_ON_ONCE(!sc); |
| 1074 | 1090 | if (!sc) { |
| 1075 | 1091 | atomic64_inc(&fnic_stats->io_stats.sc_null); |
| 1076 | 1092 | shost_printk(KERN_ERR, fnic->lport->host, |
| 1077 | 1093 | "itmf_cmpl sc is null - hdr status = %s tag = 0x%x\n", |
| 1078 | − fnic_fcpio_status_to_str(hdr_status), id); | |
| 1094 | + fnic_fcpio_status_to_str(hdr_status), tag); | |
| 1079 | 1095 | return; |
| 1080 | 1096 | } |
| 1081 | − io_lock = fnic_io_lock_hash(fnic, sc); | |
| 1097 | + | |
| 1082 | 1098 | spin_lock_irqsave(io_lock, flags); |
| 1083 | 1099 | io_req = fnic_priv(sc)->io_req; |
| 1084 | 1100 | WARN_ON_ONCE(!io_req); |
| @@ -1089,7 +1105,7 @@ static void fnic_fcpio_itmf_cmpl_handler(struct fnic *fnic, · 4 unmodified lines | ||
| 1089 | 1105 | shost_printk(KERN_ERR, fnic->lport->host, |
| 1090 | 1106 | "itmf_cmpl io_req is null - " |
| 1091 | 1107 | "hdr status = %s tag = 0x%x sc 0x%p\n", |
| 1092 | − fnic_fcpio_status_to_str(hdr_status), id, sc); | |
| 1108 | + fnic_fcpio_status_to_str(hdr_status), tag, sc); | |
| 1093 | 1109 | return; |
| 1094 | 1110 | } |
| 1095 | 1111 | start_time = io_req->start_time; |
| @@ -1938,6 +1954,10 @@ static inline int fnic_queue_dr_io_req(struct fnic *fnic, · 842 unmodified lines | ||
| 1938 | 1954 | struct scsi_lun fc_lun; |
| 1939 | 1955 | int ret = 0; |
| 1940 | 1956 | unsigned long intr_flags; |
| 1957 | + unsigned int tag = scsi_cmd_to_rq(sc)->tag; | |
| 1958 | + | |
| 1959 | + if (tag == SCSI_NO_TAG) | |
| 1960 | + tag = io_req->tag; | |
| 1941 | 1961 | |
| 1942 | 1962 | spin_lock_irqsave(host->host_lock, intr_flags); |
| 1943 | 1963 | if (unlikely(fnic_chk_state_flags_locked(fnic, |
| @@ -1964,7 +1984,8 @@ static inline int fnic_queue_dr_io_req(struct fnic *fnic, · 20 unmodified lines | ||
| 1964 | 1984 | /* fill in the lun info */ |
| 1965 | 1985 | int_to_scsilun(sc->device->lun, &fc_lun); |
| 1966 | 1986 | |
| 1967 | − fnic_queue_wq_copy_desc_itmf(wq, scsi_cmd_to_rq(sc)->tag | FNIC_TAG_DEV_RST, | |
| 1987 | + tag |= FNIC_TAG_DEV_RST; | |
| 1988 | + fnic_queue_wq_copy_desc_itmf(wq, tag, | |
| 1968 | 1989 | 0, FCPIO_ITMF_LUN_RESET, SCSI_NO_TAG, |
| 1969 | 1990 | fc_lun.scsi_lun, io_req->port_id, |
| 1970 | 1991 | fnic->config.ra_tov, fnic->config.ed_tov); |
| @@ -2146,8 +2167,7 @@ static int fnic_clean_pending_aborts(struct fnic *fnic, · 175 unmodified lines | ||
| 2146 | 2167 | .ret = SUCCESS, |
| 2147 | 2168 | }; |
| 2148 | 2169 | |
| 2149 | − if (new_sc) | |
| 2150 | − iter_data.lr_sc = lr_sc; | |
| 2170 | + iter_data.lr_sc = lr_sc; | |
| 2151 | 2171 | |
| 2152 | 2172 | scsi_host_busy_iter(fnic->lport->host, |
| 2153 | 2173 | fnic_pending_aborts_iter, &iter_data); |
| @@ -2230,8 +2250,14 @@ int fnic_device_reset(struct scsi_cmnd *sc) · 76 unmodified lines | ||
| 2230 | 2250 | mutex_lock(&fnic->sgreset_mutex); |
| 2231 | 2251 | tag = fnic->fnic_max_tag_id; |
| 2232 | 2252 | new_sc = 1; |
| 2233 | − } | |
| 2234 | − io_lock = fnic_io_lock_hash(fnic, sc); | |
| 2253 | + fnic->sgreset_sc = sc; | |
| 2254 | + io_lock = &fnic->sgreset_lock; | |
| 2255 | + FNIC_SCSI_DBG(KERN_INFO, fnic->lport->host, | |
| 2256 | + "fcid: 0x%x lun: 0x%llx flags: 0x%x tag: 0x%x Issuing sgreset\n", | |
| 2257 | + rport->port_id, sc->device->lun, fnic_priv(sc)->flags, tag); | |
| 2258 | + } else | |
| 2259 | + io_lock = fnic_io_lock_hash(fnic, sc); | |
| 2260 | + | |
| 2235 | 2261 | spin_lock_irqsave(io_lock, flags); |
| 2236 | 2262 | io_req = fnic_priv(sc)->io_req; |
| 2237 | 2263 | |
| @@ -2247,6 +2273,8 @@ int fnic_device_reset(struct scsi_cmnd *sc) · 9 unmodified lines | ||
| 2247 | 2273 | } |
| 2248 | 2274 | memset(io_req, 0, sizeof(*io_req)); |
| 2249 | 2275 | io_req->port_id = rport->port_id; |
| 2276 | + io_req->tag = tag; | |
| 2277 | + io_req->sc = sc; | |
| 2250 | 2278 | fnic_priv(sc)->io_req = io_req; |
| 2251 | 2279 | } |
| 2252 | 2280 | io_req->dr_done = &tm_done; |
| @@ -2400,8 +2428,10 @@ fnic_device_reset_end: · 147 unmodified lines | ||
| 2400 | 2428 | (u64)sc->cmnd[4] << 8 | sc->cmnd[5]), |
| 2401 | 2429 | fnic_flags_and_state(sc)); |
| 2402 | 2430 | |
| 2403 | − if (new_sc) | |
| 2431 | + if (new_sc) { | |
| 2432 | + fnic->sgreset_sc = NULL; | |
| 2404 | 2433 | mutex_unlock(&fnic->sgreset_mutex); |
| 2434 | + } | |
| 2405 | 2435 | |
| 2406 | 2436 | FNIC_SCSI_DBG(KERN_DEBUG, fnic->lport->host, |
| 2407 | 2437 | "Returning from device reset %s\n", |
| @@ -613,6 +613,17 @@ void scsi_cdl_check(struct scsi_device *sdev) · 612 unmodified lines | ||
| 613 | 613 | bool cdl_supported; |
| 614 | 614 | unsigned char *buf; |
| 615 | 615 | |
| 616 | + /* | |
| 617 | + * Support for CDL was defined in SPC-5. Ignore devices reporting an | |
| 618 | + * lower SPC version. This also avoids problems with old drives choking | |
| 619 | + * on MAINTENANCE_IN / MI_REPORT_SUPPORTED_OPERATION_CODES with a | |
| 620 | + * service action specified, as done in scsi_cdl_check_cmd(). | |
| 621 | + */ | |
| 622 | + if (sdev->scsi_level < SCSI_SPC_5) { | |
| 623 | + sdev->cdl_supported = 0; | |
| 624 | + return; | |
| 625 | + } | |
| 626 | + | |
| 616 | 627 | buf = kmalloc(SCSI_CDL_CHECK_BUF_LEN, GFP_KERNEL); |
| 617 | 628 | if (!buf) { |
| 618 | 629 | sdev->cdl_supported = 0; |
| @@ -822,7 +822,7 @@ static int scsi_probe_lun(struct scsi_device *sdev, unsigned char *inq_result, · 821 unmodified lines | ||
| 822 | 822 | * device is attached at LUN 0 (SCSI_SCAN_TARGET_PRESENT) so |
| 823 | 823 | * non-zero LUNs can be scanned. |
| 824 | 824 | */ |
| 825 | − sdev->scsi_level = inq_result[2] & 0x07; | |
| 825 | + sdev->scsi_level = inq_result[2] & 0x0f; | |
| 826 | 826 | if (sdev->scsi_level >= 2 || |
| 827 | 827 | (sdev->scsi_level == 1 && (inq_result[3] & 0x0f) == 1)) |
| 828 | 828 | sdev->scsi_level++; |
| @@ -1619,12 +1619,24 @@ int scsi_add_device(struct Scsi_Host *host, uint channel, · 790 unmodified lines | ||
| 1619 | 1619 | } |
| 1620 | 1620 | EXPORT_SYMBOL(scsi_add_device); |
| 1621 | 1621 | |
| 1622 | −void scsi_rescan_device(struct scsi_device *sdev) | |
| 1622 | +int scsi_rescan_device(struct scsi_device *sdev) | |
| 1623 | 1623 | { |
| 1624 | 1624 | struct device *dev = &sdev->sdev_gendev; |
| 1625 | + int ret = 0; | |
| 1625 | 1626 | |
| 1626 | 1627 | device_lock(dev); |
| 1627 | 1628 | |
| 1629 | + /* | |
| 1630 | + * Bail out if the device is not running. Otherwise, the rescan may | |
| 1631 | + * block waiting for commands to be executed, with us holding the | |
| 1632 | + * device lock. This can result in a potential deadlock in the power | |
| 1633 | + * management core code when system resume is on-going. | |
| 1634 | + */ | |
| 1635 | + if (sdev->sdev_state != SDEV_RUNNING) { | |
| 1636 | + ret = -EWOULDBLOCK; | |
| 1637 | + goto unlock; | |
| 1638 | + } | |
| 1639 | + | |
| 1628 | 1640 | scsi_attach_vpd(sdev); |
| 1629 | 1641 | scsi_cdl_check(sdev); |
| 1630 | 1642 | |
| @@ -1638,7 +1650,11 @@ void scsi_rescan_device(struct scsi_device *sdev) · 7 unmodified lines | ||
| 1638 | 1650 | drv->rescan(dev); |
| 1639 | 1651 | module_put(dev->driver->owner); |
| 1640 | 1652 | } |
| 1653 | + | |
| 1654 | +unlock: | |
| 1641 | 1655 | device_unlock(dev); |
| 1656 | + | |
| 1657 | + return ret; | |
| 1642 | 1658 | } |
| 1643 | 1659 | EXPORT_SYMBOL(scsi_rescan_device); |
| 1644 | 1660 | |
| @@ -201,18 +201,32 @@ cache_type_store(struct device *dev, struct device_attribute *attr, · 200 unmodified lines | ||
| 201 | 201 | } |
| 202 | 202 | |
| 203 | 203 | static ssize_t |
| 204 | −manage_start_stop_show(struct device *dev, struct device_attribute *attr, | |
| 205 | − char *buf) | |
| 204 | +manage_start_stop_show(struct device *dev, | |
| 205 | + struct device_attribute *attr, char *buf) | |
| 206 | 206 | { |
| 207 | 207 | struct scsi_disk *sdkp = to_scsi_disk(dev); |
| 208 | 208 | struct scsi_device *sdp = sdkp->device; |
| 209 | 209 | |
| 210 | − return sprintf(buf, "%u\n", sdp->manage_start_stop); | |
| 210 | + return sysfs_emit(buf, "%u\n", | |
| 211 | + sdp->manage_system_start_stop && | |
| 212 | + sdp->manage_runtime_start_stop); | |
| 211 | 213 | } |
| 214 | +static DEVICE_ATTR_RO(manage_start_stop); | |
| 212 | 215 | |
| 213 | 216 | static ssize_t |
| 214 | −manage_start_stop_store(struct device *dev, struct device_attribute *attr, | |
| 215 | − const char *buf, size_t count) | |
| 217 | +manage_system_start_stop_show(struct device *dev, | |
| 218 | + struct device_attribute *attr, char *buf) | |
| 219 | +{ | |
| 220 | + struct scsi_disk *sdkp = to_scsi_disk(dev); | |
| 221 | + struct scsi_device *sdp = sdkp->device; | |
| 222 | + | |
| 223 | + return sysfs_emit(buf, "%u\n", sdp->manage_system_start_stop); | |
| 224 | +} | |
| 225 | + | |
| 226 | +static ssize_t | |
| 227 | +manage_system_start_stop_store(struct device *dev, | |
| 228 | + struct device_attribute *attr, | |
| 229 | + const char *buf, size_t count) | |
| 216 | 230 | { |
| 217 | 231 | struct scsi_disk *sdkp = to_scsi_disk(dev); |
| 218 | 232 | struct scsi_device *sdp = sdkp->device; |
| @@ -224,11 +238,42 @@ manage_start_stop_store(struct device *dev, struct device_attribute *attr, · 5 unmodified lines | ||
| 224 | 238 | if (kstrtobool(buf, &v)) |
| 225 | 239 | return -EINVAL; |
| 226 | 240 | |
| 227 | − sdp->manage_start_stop = v; | |
| 241 | + sdp->manage_system_start_stop = v; | |
| 228 | 242 | |
| 229 | 243 | return count; |
| 230 | 244 | } |
| 231 | −static DEVICE_ATTR_RW(manage_start_stop); | |
| 245 | +static DEVICE_ATTR_RW(manage_system_start_stop); | |
| 246 | + | |
| 247 | +static ssize_t | |
| 248 | +manage_runtime_start_stop_show(struct device *dev, | |
| 249 | + struct device_attribute *attr, char *buf) | |
| 250 | +{ | |
| 251 | + struct scsi_disk *sdkp = to_scsi_disk(dev); | |
| 252 | + struct scsi_device *sdp = sdkp->device; | |
| 253 | + | |
| 254 | + return sysfs_emit(buf, "%u\n", sdp->manage_runtime_start_stop); | |
| 255 | +} | |
| 256 | + | |
| 257 | +static ssize_t | |
| 258 | +manage_runtime_start_stop_store(struct device *dev, | |
| 259 | + struct device_attribute *attr, | |
| 260 | + const char *buf, size_t count) | |
| 261 | +{ | |
| 262 | + struct scsi_disk *sdkp = to_scsi_disk(dev); | |
| 263 | + struct scsi_device *sdp = sdkp->device; | |
| 264 | + bool v; | |
| 265 | + | |
| 266 | + if (!capable(CAP_SYS_ADMIN)) | |
| 267 | + return -EACCES; | |
| 268 | + | |
| 269 | + if (kstrtobool(buf, &v)) | |
| 270 | + return -EINVAL; | |
| 271 | + | |
| 272 | + sdp->manage_runtime_start_stop = v; | |
| 273 | + | |
| 274 | + return count; | |
| 275 | +} | |
| 276 | +static DEVICE_ATTR_RW(manage_runtime_start_stop); | |
| 232 | 277 | |
| 233 | 278 | static ssize_t |
| 234 | 279 | allow_restart_show(struct device *dev, struct device_attribute *attr, char *buf) |
| @@ -560,6 +605,8 @@ static struct attribute *sd_disk_attrs[] = { · 325 unmodified lines | ||
| 560 | 605 | &dev_attr_FUA.attr, |
| 561 | 606 | &dev_attr_allow_restart.attr, |
| 562 | 607 | &dev_attr_manage_start_stop.attr, |
| 608 | + &dev_attr_manage_system_start_stop.attr, | |
| 609 | + &dev_attr_manage_runtime_start_stop.attr, | |
| 563 | 610 | &dev_attr_protection_type.attr, |
| 564 | 611 | &dev_attr_protection_mode.attr, |
| 565 | 612 | &dev_attr_app_tag_own.attr, |
| @@ -3694,7 +3741,8 @@ static int sd_remove(struct device *dev) · 3128 unmodified lines | ||
| 3694 | 3741 | |
| 3695 | 3742 | device_del(&sdkp->disk_dev); |
| 3696 | 3743 | del_gendisk(sdkp->disk); |
| 3697 | − sd_shutdown(dev); | |
| 3744 | + if (!sdkp->suspended) | |
| 3745 | + sd_shutdown(dev); | |
| 3698 | 3746 | |
| 3699 | 3747 | put_disk(sdkp->disk); |
| 3700 | 3748 | return 0; |
| @@ -3771,13 +3819,20 @@ static void sd_shutdown(struct device *dev) · 70 unmodified lines | ||
| 3771 | 3819 | sd_sync_cache(sdkp, NULL); |
| 3772 | 3820 | } |
| 3773 | 3821 | |
| 3774 | − if (system_state != SYSTEM_RESTART && sdkp->device->manage_start_stop) { | |
| 3822 | + if (system_state != SYSTEM_RESTART && | |
| 3823 | + sdkp->device->manage_system_start_stop) { | |
| 3775 | 3824 | sd_printk(KERN_NOTICE, sdkp, "Stopping disk\n"); |
| 3776 | 3825 | sd_start_stop_device(sdkp, 0); |
| 3777 | 3826 | } |
| 3778 | 3827 | } |
| 3779 | 3828 | |
| 3780 | −static int sd_suspend_common(struct device *dev, bool ignore_stop_errors) | |
| 3829 | +static inline bool sd_do_start_stop(struct scsi_device *sdev, bool runtime) | |
| 3830 | +{ | |
| 3831 | + return (sdev->manage_system_start_stop && !runtime) || | |
| 3832 | + (sdev->manage_runtime_start_stop && runtime); | |
| 3833 | +} | |
| 3834 | + | |
| 3835 | +static int sd_suspend_common(struct device *dev, bool runtime) | |
| 3781 | 3836 | { |
| 3782 | 3837 | struct scsi_disk *sdkp = dev_get_drvdata(dev); |
| 3783 | 3838 | struct scsi_sense_hdr sshdr; |
| @@ -3809,15 +3864,18 @@ static int sd_suspend_common(struct device *dev, bool ignore_stop_errors) · 25 unmodified lines | ||
| 3809 | 3864 | } |
| 3810 | 3865 | } |
| 3811 | 3866 | |
| 3812 | − if (sdkp->device->manage_start_stop) { | |
| 3867 | + if (sd_do_start_stop(sdkp->device, runtime)) { | |
| 3813 | 3868 | if (!sdkp->device->silence_suspend) |
| 3814 | 3869 | sd_printk(KERN_NOTICE, sdkp, "Stopping disk\n"); |
| 3815 | 3870 | /* an error is not worth aborting a system sleep */ |
| 3816 | 3871 | ret = sd_start_stop_device(sdkp, 0); |
| 3817 | − if (ignore_stop_errors) | |
| 3872 | + if (!runtime) | |
| 3818 | 3873 | ret = 0; |
| 3819 | 3874 | } |
| 3820 | 3875 | |
| 3876 | + if (!ret) | |
| 3877 | + sdkp->suspended = true; | |
| 3878 | + | |
| 3821 | 3879 | return ret; |
| 3822 | 3880 | } |
| 3823 | 3881 | |
| @@ -3826,15 +3884,15 @@ static int sd_suspend_system(struct device *dev) · 2 unmodified lines | ||
| 3826 | 3884 | if (pm_runtime_suspended(dev)) |
| 3827 | 3885 | return 0; |
| 3828 | 3886 | |
| 3829 | − return sd_suspend_common(dev, true); | |
| 3887 | + return sd_suspend_common(dev, false); | |
| 3830 | 3888 | } |
| 3831 | 3889 | |
| 3832 | 3890 | static int sd_suspend_runtime(struct device *dev) |
| 3833 | 3891 | { |
| 3834 | − return sd_suspend_common(dev, false); | |
| 3892 | + return sd_suspend_common(dev, true); | |
| 3835 | 3893 | } |
| 3836 | 3894 | |
| 3837 | −static int sd_resume(struct device *dev) | |
| 3895 | +static int sd_resume(struct device *dev, bool runtime) | |
| 3838 | 3896 | { |
| 3839 | 3897 | struct scsi_disk *sdkp = dev_get_drvdata(dev); |
| 3840 | 3898 | int ret = 0; |
| @@ -3842,16 +3900,21 @@ static int sd_resume(struct device *dev) · 1 unmodified line | ||
| 3842 | 3900 | if (!sdkp) /* E.g.: runtime resume at the start of sd_probe() */ |
| 3843 | 3901 | return 0; |
| 3844 | 3902 | |
| 3845 | − if (!sdkp->device->manage_start_stop) | |
| 3903 | + if (!sd_do_start_stop(sdkp->device, runtime)) { | |
| 3904 | + sdkp->suspended = false; | |
| 3846 | 3905 | return 0; |
| 3906 | + } | |
| 3847 | 3907 | |
| 3848 | 3908 | if (!sdkp->device->no_start_on_resume) { |
| 3849 | 3909 | sd_printk(KERN_NOTICE, sdkp, "Starting disk\n"); |
| 3850 | 3910 | ret = sd_start_stop_device(sdkp, 1); |
| 3851 | 3911 | } |
| 3852 | 3912 | |
| 3853 | − if (!ret) | |
| 3913 | + if (!ret) { | |
| 3854 | 3914 | opal_unlock_from_suspend(sdkp->opal_dev); |
| 3915 | + sdkp->suspended = false; | |
| 3916 | + } | |
| 3917 | + | |
| 3855 | 3918 | return ret; |
| 3856 | 3919 | } |
| 3857 | 3920 | |
| @@ -3860,7 +3923,7 @@ static int sd_resume_system(struct device *dev) · 2 unmodified lines | ||
| 3860 | 3923 | if (pm_runtime_suspended(dev)) |
| 3861 | 3924 | return 0; |
| 3862 | 3925 | |
| 3863 | − return sd_resume(dev); | |
| 3926 | + return sd_resume(dev, false); | |
| 3864 | 3927 | } |
| 3865 | 3928 | |
| 3866 | 3929 | static int sd_resume_runtime(struct device *dev) |
| @@ -3887,7 +3950,7 @@ static int sd_resume_runtime(struct device *dev) · 20 unmodified lines | ||
| 3887 | 3950 | "Failed to clear sense data\n"); |
| 3888 | 3951 | } |
| 3889 | 3952 | |
| 3890 | − return sd_resume(dev); | |
| 3953 | + return sd_resume(dev, true); | |
| 3891 | 3954 | } |
| 3892 | 3955 | |
| 3893 | 3956 | static const struct dev_pm_ops sd_pm_ops = { |
| @@ -131,6 +131,7 @@ struct scsi_disk { · 130 unmodified lines | ||
| 131 | 131 | u8 provisioning_mode; |
| 132 | 132 | u8 zeroing_mode; |
| 133 | 133 | u8 nr_actuators; /* Number of actuators */ |
| 134 | + bool suspended; /* Disk is suspended (stopped) */ | |
| 134 | 135 | unsigned ATO : 1; /* state of disk ATO bit */ |
| 135 | 136 | unsigned cache_override : 1; /* temp override of WCE,RCD */ |
| 136 | 137 | unsigned WCE : 1; /* state of disk WCE bit */ |
| @@ -100,6 +100,7 @@ static void __init imx8mm_soc_uid(void) · 99 unmodified lines | ||
| 100 | 100 | { |
| 101 | 101 | void __iomem *ocotp_base; |
| 102 | 102 | struct device_node *np; |
| 103 | + struct clk *clk; | |
| 103 | 104 | u32 offset = of_machine_is_compatible("fsl,imx8mp") ? |
| 104 | 105 | IMX8MP_OCOTP_UID_OFFSET : 0; |
| 105 | 106 | |
| @@ -109,11 +110,20 @@ static void __init imx8mm_soc_uid(void) · 3 unmodified lines | ||
| 109 | 110 | |
| 110 | 111 | ocotp_base = of_iomap(np, 0); |
| 111 | 112 | WARN_ON(!ocotp_base); |
| 113 | + clk = of_clk_get_by_name(np, NULL); | |
| 114 | + if (IS_ERR(clk)) { | |
| 115 | + WARN_ON(IS_ERR(clk)); | |
| 116 | + return; | |
| 117 | + } | |
| 118 | + | |
| 119 | + clk_prepare_enable(clk); | |
| 112 | 120 | |
| 113 | 121 | soc_uid = readl_relaxed(ocotp_base + OCOTP_UID_HIGH + offset); |
| 114 | 122 | soc_uid <<= 32; |
| 115 | 123 | soc_uid |= readl_relaxed(ocotp_base + OCOTP_UID_LOW + offset); |
| 116 | 124 | |
| 125 | + clk_disable_unprepare(clk); | |
| 126 | + clk_put(clk); | |
| 117 | 127 | iounmap(ocotp_base); |
| 118 | 128 | of_node_put(np); |
| 119 | 129 | } |
| @@ -20,6 +20,7 @@ config LOONGSON2_GUTS · 19 unmodified lines | ||
| 20 | 20 | config LOONGSON2_PM |
| 21 | 21 | bool "Loongson-2 SoC Power Management Controller Driver" |
| 22 | 22 | depends on LOONGARCH && OF |
| 23 | + depends on INPUT=y | |
| 23 | 24 | help |
| 24 | 25 | The Loongson-2's power management controller was ACPI, supports ACPI |
| 25 | 26 | S2Idle (Suspend To Idle), ACPI S3 (Suspend To RAM), ACPI S4 (Suspend To |
| @@ -70,7 +70,7 @@ static const struct loongson2_soc_die_attr *loongson2_soc_die_match( · 69 unmodified lines | ||
| 70 | 70 | if (matches->svr == (svr & matches->mask)) |
| 71 | 71 | return matches; |
| 72 | 72 | matches++; |
| 73 | − }; | |
| 73 | + } | |
| 74 | 74 | |
| 75 | 75 | return NULL; |
| 76 | 76 | } |
| @@ -94,7 +94,6 @@ static int loongson2_guts_probe(struct platform_device *pdev) · 17 unmodified lines | ||
| 94 | 94 | { |
| 95 | 95 | struct device_node *root, *np = pdev->dev.of_node; |
| 96 | 96 | struct device *dev = &pdev->dev; |
| 97 | − struct resource *res; | |
| 98 | 97 | const struct loongson2_soc_die_attr *soc_die; |
| 99 | 98 | const char *machine; |
| 100 | 99 | u32 svr; |
| @@ -106,8 +105,7 @@ static int loongson2_guts_probe(struct platform_device *pdev) · 5 unmodified lines | ||
| 106 | 105 | |
| 107 | 106 | guts->little_endian = of_property_read_bool(np, "little-endian"); |
| 108 | 107 | |
| 109 | − res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | |
| 110 | − guts->regs = ioremap(res->start, res->end - res->start + 1); | |
| 108 | + guts->regs = devm_platform_ioremap_resource(pdev, 0); | |
| 111 | 109 | if (IS_ERR(guts->regs)) |
| 112 | 110 | return PTR_ERR(guts->regs); |
| 113 | 111 | |
| @@ -11,6 +11,7 @@ · 10 unmodified lines | ||
| 11 | 11 | #include <linux/input.h> |
| 12 | 12 | #include <linux/suspend.h> |
| 13 | 13 | #include <linux/interrupt.h> |
| 14 | +#include <linux/of_platform.h> | |
| 14 | 15 | #include <linux/pm_wakeirq.h> |
| 15 | 16 | #include <linux/platform_device.h> |
| 16 | 17 | #include <asm/bootinfo.h> |
| @@ -192,12 +193,16 @@ static int loongson2_pm_probe(struct platform_device *pdev) · 175 unmodified lines | ||
| 192 | 193 | if (loongson_sysconf.suspend_addr) |
| 193 | 194 | suspend_set_ops(&loongson2_suspend_ops); |
| 194 | 195 | |
| 196 | + /* Populate children */ | |
| 197 | + retval = devm_of_platform_populate(dev); | |
| 198 | + if (retval) | |
| 199 | + dev_err(dev, "Error populating children, reboot and poweroff might not work properly\n"); | |
| 200 | + | |
| 195 | 201 | return 0; |
| 196 | 202 | } |
| 197 | 203 | |
| 198 | 204 | static const struct of_device_id loongson2_pm_match[] = { |
| 199 | 205 | { .compatible = "loongson,ls2k0500-pmc", }, |
| 200 | − { .compatible = "loongson,ls2k1000-pmc", }, | |
| 201 | 206 | {}, |
| 202 | 207 | }; |
| 203 | 208 | |
| @@ -256,7 +256,6 @@ static int cs42l43_spi_probe(struct platform_device *pdev) · 255 unmodified lines | ||
| 256 | 256 | |
| 257 | 257 | ret = devm_spi_register_controller(priv->dev, priv->ctlr); |
| 258 | 258 | if (ret) { |
| 259 | − pm_runtime_disable(priv->dev); | |
| 260 | 259 | dev_err(priv->dev, "Failed to register SPI controller: %d\n", ret); |
| 261 | 260 | } |
| 262 | 261 | |
| @@ -194,7 +194,7 @@ static ssize_t gxp_spi_write(struct gxp_spi_chip *chip, const struct spi_mem_op · 193 unmodified lines | ||
| 194 | 194 | return ret; |
| 195 | 195 | } |
| 196 | 196 | |
| 197 | − return write_len; | |
| 197 | + return 0; | |
| 198 | 198 | } |
| 199 | 199 | |
| 200 | 200 | static int do_gxp_exec_mem_op(struct spi_mem *mem, const struct spi_mem_op *op) |
| @@ -843,7 +843,6 @@ sector_t target_to_linux_sector(struct se_device *dev, sector_t lb) · 842 unmodified lines | ||
| 843 | 843 | EXPORT_SYMBOL(target_to_linux_sector); |
| 844 | 844 | |
| 845 | 845 | struct devices_idr_iter { |
| 846 | − struct config_item *prev_item; | |
| 847 | 846 | int (*fn)(struct se_device *dev, void *data); |
| 848 | 847 | void *data; |
| 849 | 848 | }; |
| @@ -853,11 +852,9 @@ static int target_devices_idr_iter(int id, void *p, void *data) · 3 unmodified lines | ||
| 853 | 852 | { |
| 854 | 853 | struct devices_idr_iter *iter = data; |
| 855 | 854 | struct se_device *dev = p; |
| 855 | + struct config_item *item; | |
| 856 | 856 | int ret; |
| 857 | 857 | |
| 858 | − config_item_put(iter->prev_item); | |
| 859 | − iter->prev_item = NULL; | |
| 860 | − | |
| 861 | 858 | /* |
| 862 | 859 | * We add the device early to the idr, so it can be used |
| 863 | 860 | * by backend modules during configuration. We do not want |
| @@ -867,12 +864,13 @@ static int target_devices_idr_iter(int id, void *p, void *data) · 3 unmodified lines | ||
| 867 | 864 | if (!target_dev_configured(dev)) |
| 868 | 865 | return 0; |
| 869 | 866 | |
| 870 | − iter->prev_item = config_item_get_unless_zero(&dev->dev_group.cg_item); | |
| 871 | − if (!iter->prev_item) | |
| 867 | + item = config_item_get_unless_zero(&dev->dev_group.cg_item); | |
| 868 | + if (!item) | |
| 872 | 869 | return 0; |
| 873 | 870 | mutex_unlock(&device_mutex); |
| 874 | 871 | |
| 875 | 872 | ret = iter->fn(dev, iter->data); |
| 873 | + config_item_put(item); | |
| 876 | 874 | |
| 877 | 875 | mutex_lock(&device_mutex); |
| 878 | 876 | return ret; |
| @@ -895,7 +893,6 @@ int target_for_each_device(int (*fn)(struct se_device *dev, void *data), · 16 unmodified lines | ||
| 895 | 893 | mutex_lock(&device_mutex); |
| 896 | 894 | ret = idr_for_each(&devices_idr, target_devices_idr_iter, &iter); |
| 897 | 895 | mutex_unlock(&device_mutex); |
| 898 | − config_item_put(iter.prev_item); | |
| 899 | 896 | return ret; |
| 900 | 897 | } |
| 901 | 898 | |
| @@ -238,8 +238,6 @@ int optee_notif_send(struct optee *optee, u_int key); · 237 unmodified lines | ||
| 238 | 238 | u32 optee_supp_thrd_req(struct tee_context *ctx, u32 func, size_t num_params, |
| 239 | 239 | struct tee_param *param); |
| 240 | 240 | |
| 241 | −int optee_supp_read(struct tee_context *ctx, void __user *buf, size_t len); | |
| 242 | −int optee_supp_write(struct tee_context *ctx, void __user *buf, size_t len); | |
| 243 | 241 | void optee_supp_init(struct optee_supp *supp); |
| 244 | 242 | void optee_supp_uninit(struct optee_supp *supp); |
| 245 | 243 | void optee_supp_release(struct optee_supp *supp); |
| @@ -47,8 +47,6 @@ struct tee_device { · 46 unmodified lines | ||
| 47 | 47 | struct tee_shm_pool *pool; |
| 48 | 48 | }; |
| 49 | 49 | |
| 50 | −int tee_shm_init(void); | |
| 51 | − | |
| 52 | 50 | int tee_shm_get_fd(struct tee_shm *shm); |
| 53 | 51 | |
| 54 | 52 | bool tee_device_get(struct tee_device *teedev); |
| @@ -185,9 +185,6 @@ trip_point_hyst_store(struct device *dev, struct device_attribute *attr, · 184 unmodified lines | ||
| 185 | 185 | if (sscanf(attr->attr.name, "trip_point_%d_hyst", &trip_id) != 1) |
| 186 | 186 | return -EINVAL; |
| 187 | 187 | |
| 188 | − if (kstrtoint(buf, 10, &trip.hysteresis)) | |
| 189 | − return -EINVAL; | |
| 190 | − | |
| 191 | 188 | mutex_lock(&tz->lock); |
| 192 | 189 | |
| 193 | 190 | if (!device_is_registered(dev)) { |
| @@ -198,7 +195,11 @@ trip_point_hyst_store(struct device *dev, struct device_attribute *attr, · 4 unmodified lines | ||
| 198 | 195 | ret = __thermal_zone_get_trip(tz, trip_id, &trip); |
| 199 | 196 | if (ret) |
| 200 | 197 | goto unlock; |
| 201 | − | |
| 198 | + | |
| 199 | + ret = kstrtoint(buf, 10, &trip.hysteresis); | |
| 200 | + if (ret) | |
| 201 | + goto unlock; | |
| 202 | + | |
| 202 | 203 | ret = thermal_zone_set_trip(tz, trip_id, &trip); |
| 203 | 204 | unlock: |
| 204 | 205 | mutex_unlock(&tz->lock); |
| @@ -3097,10 +3097,8 @@ static void gsm_cleanup_mux(struct gsm_mux *gsm, bool disc) · 3096 unmodified lines | ||
| 3097 | 3097 | gsm->has_devices = false; |
| 3098 | 3098 | } |
| 3099 | 3099 | for (i = NUM_DLCI - 1; i >= 0; i--) |
| 3100 | − if (gsm->dlci[i]) { | |
| 3100 | + if (gsm->dlci[i]) | |
| 3101 | 3101 | gsm_dlci_release(gsm->dlci[i]); |
| 3102 | − gsm->dlci[i] = NULL; | |
| 3103 | − } | |
| 3104 | 3102 | mutex_unlock(&gsm->mutex); |
| 3105 | 3103 | /* Now wipe the queues */ |
| 3106 | 3104 | tty_ldisc_flush(gsm->tty); |
| @@ -1936,7 +1936,10 @@ int serial8250_handle_irq(struct uart_port *port, unsigned int iir) · 1935 unmodified lines | ||
| 1936 | 1936 | skip_rx = true; |
| 1937 | 1937 | |
| 1938 | 1938 | if (status & (UART_LSR_DR | UART_LSR_BI) && !skip_rx) { |
| 1939 | − if (irqd_is_wakeup_set(irq_get_irq_data(port->irq))) | |
| 1939 | + struct irq_data *d; | |
| 1940 | + | |
| 1941 | + d = irq_get_irq_data(port->irq); | |
| 1942 | + if (d && irqd_is_wakeup_set(d)) | |
| 1940 | 1943 | pm_wakeup_event(tport->tty->dev, 0); |
| 1941 | 1944 | if (!up->dma || handle_rx_dma(up, iir)) |
| 1942 | 1945 | status = serial8250_rx_chars(up, status); |
| @@ -233,7 +233,8 @@ int parent_create_sysfs_files(struct mdev_parent *parent) · 232 unmodified lines | ||
| 233 | 233 | out_err: |
| 234 | 234 | while (--i >= 0) |
| 235 | 235 | mdev_type_remove(parent->types[i]); |
| 236 | − return 0; | |
| 236 | + kset_unregister(parent->mdev_types_kset); | |
| 237 | + return ret; | |
| 237 | 238 | } |
| 238 | 239 | |
| 239 | 240 | static ssize_t remove_store(struct device *dev, struct device_attribute *attr, |
| @@ -3,7 +3,7 @@ · 2 unmodified lines | ||
| 3 | 3 | |
| 4 | 4 | config PDS_VFIO_PCI |
| 5 | 5 | tristate "VFIO support for PDS PCI devices" |
| 6 | − depends on PDS_CORE | |
| 6 | + depends on PDS_CORE && PCI_IOV | |
| 7 | 7 | select VFIO_PCI_CORE |
| 8 | 8 | help |
| 9 | 9 | This provides generic PCI support for PDS devices using the VFIO |
| @@ -162,7 +162,7 @@ static int pds_vfio_init_device(struct vfio_device *vdev) · 161 unmodified lines | ||
| 162 | 162 | pci_id = PCI_DEVID(pdev->bus->number, pdev->devfn); |
| 163 | 163 | dev_dbg(&pdev->dev, |
| 164 | 164 | "%s: PF %#04x VF %#04x vf_id %d domain %d pds_vfio %p\n", |
| 165 | − __func__, pci_dev_id(pdev->physfn), pci_id, vf_id, | |
| 165 | + __func__, pci_dev_id(pci_physfn(pdev)), pci_id, vf_id, | |
| 166 | 166 | pci_domain_nr(pdev->bus), pds_vfio); |
| 167 | 167 | |
| 168 | 168 | return 0; |
| @@ -123,8 +123,18 @@ static inline ssize_t vringh_iov_xfer(struct vringh *vrh, · 122 unmodified lines | ||
| 123 | 123 | done += partlen; |
| 124 | 124 | len -= partlen; |
| 125 | 125 | ptr += partlen; |
| 126 | + iov->consumed += partlen; | |
| 127 | + iov->iov[iov->i].iov_len -= partlen; | |
| 128 | + iov->iov[iov->i].iov_base += partlen; | |
| 126 | 129 | |
| 127 | − vringh_kiov_advance(iov, partlen); | |
| 130 | + if (!iov->iov[iov->i].iov_len) { | |
| 131 | + /* Fix up old iov element then increment. */ | |
| 132 | + iov->iov[iov->i].iov_len = iov->consumed; | |
| 133 | + iov->iov[iov->i].iov_base -= iov->consumed; | |
| 134 | + | |
| 135 | + iov->consumed = 0; | |
| 136 | + iov->i++; | |
| 137 | + } | |
| 128 | 138 | } |
| 129 | 139 | return done; |
| 130 | 140 | } |
| @@ -73,6 +73,7 @@ config DUMMY_CONSOLE_ROWS · 72 unmodified lines | ||
| 73 | 73 | config FRAMEBUFFER_CONSOLE |
| 74 | 74 | bool "Framebuffer Console support" |
| 75 | 75 | depends on FB_CORE && !UML |
| 76 | + default DRM_FBDEV_EMULATION | |
| 76 | 77 | select VT_HW_CONSOLE_BINDING |
| 77 | 78 | select CRC32 |
| 78 | 79 | select FONT_SUPPORT |
| @@ -1762,7 +1762,7 @@ config FB_COBALT · 1761 unmodified lines | ||
| 1762 | 1762 | |
| 1763 | 1763 | config FB_SH7760 |
| 1764 | 1764 | bool "SH7760/SH7763/SH7720/SH7721 LCDC support" |
| 1765 | − depends on FB && (CPU_SUBTYPE_SH7760 || CPU_SUBTYPE_SH7763 \ | |
| 1765 | + depends on FB=y && (CPU_SUBTYPE_SH7760 || CPU_SUBTYPE_SH7763 \ | |
| 1766 | 1766 | || CPU_SUBTYPE_SH7720 || CPU_SUBTYPE_SH7721) |
| 1767 | 1767 | select FB_IOMEM_HELPERS |
| 1768 | 1768 | help |
| @@ -28,7 +28,7 @@ config FIRMWARE_EDID · 27 unmodified lines | ||
| 28 | 28 | config FB_DEVICE |
| 29 | 29 | bool "Provide legacy /dev/fb* device" |
| 30 | 30 | depends on FB_CORE |
| 31 | − default y | |
| 31 | + default FB | |
| 32 | 32 | help |
| 33 | 33 | Say Y here if you want the legacy /dev/fb* device file and |
| 34 | 34 | interfaces within sysfs anc procfs. It is only required if you |
| @@ -80,7 +80,7 @@ struct aio_ring { · 79 unmodified lines | ||
| 80 | 80 | struct kioctx_table { |
| 81 | 81 | struct rcu_head rcu; |
| 82 | 82 | unsigned nr; |
| 83 | − struct kioctx __rcu *table[]; | |
| 83 | + struct kioctx __rcu *table[] __counted_by(nr); | |
| 84 | 84 | }; |
| 85 | 85 | |
| 86 | 86 | struct kioctx_cpu { |
| @@ -345,10 +345,9 @@ static int load_elf_fdpic_binary(struct linux_binprm *bprm) · 344 unmodified lines | ||
| 345 | 345 | /* there's now no turning back... the old userspace image is dead, |
| 346 | 346 | * defunct, deceased, etc. |
| 347 | 347 | */ |
| 348 | + SET_PERSONALITY(exec_params.hdr); | |
| 348 | 349 | if (elf_check_fdpic(&exec_params.hdr)) |
| 349 | − set_personality(PER_LINUX_FDPIC); | |
| 350 | − else | |
| 351 | − set_personality(PER_LINUX); | |
| 350 | + current->personality |= PER_LINUX_FDPIC; | |
| 352 | 351 | if (elf_read_implies_exec(&exec_params.hdr, executable_stack)) |
| 353 | 352 | current->personality |= READ_IMPLIES_EXEC; |
| 354 | 353 | |
| @@ -103,24 +103,17 @@ void btrfs_update_delayed_refs_rsv(struct btrfs_trans_handle *trans) · 102 unmodified lines | ||
| 103 | 103 | * Transfer bytes to our delayed refs rsv. |
| 104 | 104 | * |
| 105 | 105 | * @fs_info: the filesystem |
| 106 | − * @src: source block rsv to transfer from | |
| 107 | 106 | * @num_bytes: number of bytes to transfer |
| 108 | 107 | * |
| 109 | − * This transfers up to the num_bytes amount from the src rsv to the | |
| 108 | + * This transfers up to the num_bytes amount, previously reserved, to the | |
| 110 | 109 | * delayed_refs_rsv. Any extra bytes are returned to the space info. |
| 111 | 110 | */ |
| 112 | 111 | void btrfs_migrate_to_delayed_refs_rsv(struct btrfs_fs_info *fs_info, |
| 113 | − struct btrfs_block_rsv *src, | |
| 114 | 112 | u64 num_bytes) |
| 115 | 113 | { |
| 116 | 114 | struct btrfs_block_rsv *delayed_refs_rsv = &fs_info->delayed_refs_rsv; |
| 117 | 115 | u64 to_free = 0; |
| 118 | 116 | |
| 119 | − spin_lock(&src->lock); | |
| 120 | − src->reserved -= num_bytes; | |
| 121 | − src->size -= num_bytes; | |
| 122 | − spin_unlock(&src->lock); | |
| 123 | − | |
| 124 | 117 | spin_lock(&delayed_refs_rsv->lock); |
| 125 | 118 | if (delayed_refs_rsv->size > delayed_refs_rsv->reserved) { |
| 126 | 119 | u64 delta = delayed_refs_rsv->size - |
| @@ -163,6 +156,8 @@ int btrfs_delayed_refs_rsv_refill(struct btrfs_fs_info *fs_info, · 36 unmodified lines | ||
| 163 | 156 | struct btrfs_block_rsv *block_rsv = &fs_info->delayed_refs_rsv; |
| 164 | 157 | u64 limit = btrfs_calc_delayed_ref_bytes(fs_info, 1); |
| 165 | 158 | u64 num_bytes = 0; |
| 159 | + u64 refilled_bytes; | |
| 160 | + u64 to_free; | |
| 166 | 161 | int ret = -ENOSPC; |
| 167 | 162 | |
| 168 | 163 | spin_lock(&block_rsv->lock); |
| @@ -178,9 +173,38 @@ int btrfs_delayed_refs_rsv_refill(struct btrfs_fs_info *fs_info, · 9 unmodified lines | ||
| 178 | 173 | ret = btrfs_reserve_metadata_bytes(fs_info, block_rsv, num_bytes, flush); |
| 179 | 174 | if (ret) |
| 180 | 175 | return ret; |
| 181 | − btrfs_block_rsv_add_bytes(block_rsv, num_bytes, false); | |
| 182 | − trace_btrfs_space_reservation(fs_info, "delayed_refs_rsv", | |
| 183 | − 0, num_bytes, 1); | |
| 176 | + | |
| 177 | + /* | |
| 178 | + * We may have raced with someone else, so check again if we the block | |
| 179 | + * reserve is still not full and release any excess space. | |
| 180 | + */ | |
| 181 | + spin_lock(&block_rsv->lock); | |
| 182 | + if (block_rsv->reserved < block_rsv->size) { | |
| 183 | + u64 needed = block_rsv->size - block_rsv->reserved; | |
| 184 | + | |
| 185 | + if (num_bytes >= needed) { | |
| 186 | + block_rsv->reserved += needed; | |
| 187 | + block_rsv->full = true; | |
| 188 | + to_free = num_bytes - needed; | |
| 189 | + refilled_bytes = needed; | |
| 190 | + } else { | |
| 191 | + block_rsv->reserved += num_bytes; | |
| 192 | + to_free = 0; | |
| 193 | + refilled_bytes = num_bytes; | |
| 194 | + } | |
| 195 | + } else { | |
| 196 | + to_free = num_bytes; | |
| 197 | + refilled_bytes = 0; | |
| 198 | + } | |
| 199 | + spin_unlock(&block_rsv->lock); | |
| 200 | + | |
| 201 | + if (to_free > 0) | |
| 202 | + btrfs_space_info_free_bytes_may_use(fs_info, block_rsv->space_info, | |
| 203 | + to_free); | |
| 204 | + | |
| 205 | + if (refilled_bytes > 0) | |
| 206 | + trace_btrfs_space_reservation(fs_info, "delayed_refs_rsv", 0, | |
| 207 | + refilled_bytes, 1); | |
| 184 | 208 | return 0; |
| 185 | 209 | } |
| 186 | 210 | |
| @@ -407,7 +407,6 @@ void btrfs_update_delayed_refs_rsv(struct btrfs_trans_handle *trans); · 406 unmodified lines | ||
| 407 | 407 | int btrfs_delayed_refs_rsv_refill(struct btrfs_fs_info *fs_info, |
| 408 | 408 | enum btrfs_reserve_flush_enum flush); |
| 409 | 409 | void btrfs_migrate_to_delayed_refs_rsv(struct btrfs_fs_info *fs_info, |
| 410 | − struct btrfs_block_rsv *src, | |
| 411 | 410 | u64 num_bytes); |
| 412 | 411 | bool btrfs_check_space_for_delayed_refs(struct btrfs_fs_info *fs_info); |
| 413 | 412 | |
| @@ -1514,15 +1514,14 @@ static int __btrfs_inc_extent_ref(struct btrfs_trans_handle *trans, · 1513 unmodified lines | ||
| 1514 | 1514 | btrfs_release_path(path); |
| 1515 | 1515 | |
| 1516 | 1516 | /* now insert the actual backref */ |
| 1517 | − if (owner < BTRFS_FIRST_FREE_OBJECTID) { | |
| 1518 | − BUG_ON(refs_to_add != 1); | |
| 1517 | + if (owner < BTRFS_FIRST_FREE_OBJECTID) | |
| 1519 | 1518 | ret = insert_tree_block_ref(trans, path, bytenr, parent, |
| 1520 | 1519 | root_objectid); |
| 1521 | − } else { | |
| 1520 | + else | |
| 1522 | 1521 | ret = insert_extent_data_ref(trans, path, bytenr, parent, |
| 1523 | 1522 | root_objectid, owner, offset, |
| 1524 | 1523 | refs_to_add); |
| 1525 | − } | |
| 1524 | + | |
| 1526 | 1525 | if (ret) |
| 1527 | 1526 | btrfs_abort_transaction(trans, ret); |
| 1528 | 1527 | out: |
| @@ -1656,7 +1655,10 @@ again: · 127 unmodified lines | ||
| 1656 | 1655 | goto again; |
| 1657 | 1656 | } |
| 1658 | 1657 | } else { |
| 1659 | − err = -EIO; | |
| 1658 | + err = -EUCLEAN; | |
| 1659 | + btrfs_err(fs_info, | |
| 1660 | + "missing extent item for extent %llu num_bytes %llu level %d", | |
| 1661 | + head->bytenr, head->num_bytes, extent_op->level); | |
| 1660 | 1662 | goto out; |
| 1661 | 1663 | } |
| 1662 | 1664 | } |
| @@ -1699,12 +1701,12 @@ static int run_delayed_tree_ref(struct btrfs_trans_handle *trans, · 36 unmodified lines | ||
| 1699 | 1701 | parent = ref->parent; |
| 1700 | 1702 | ref_root = ref->root; |
| 1701 | 1703 | |
| 1702 | − if (node->ref_mod != 1) { | |
| 1704 | + if (unlikely(node->ref_mod != 1)) { | |
| 1703 | 1705 | btrfs_err(trans->fs_info, |
| 1704 | − "btree block(%llu) has %d references rather than 1: action %d ref_root %llu parent %llu", | |
| 1706 | + "btree block %llu has %d references rather than 1: action %d ref_root %llu parent %llu", | |
| 1705 | 1707 | node->bytenr, node->ref_mod, node->action, ref_root, |
| 1706 | 1708 | parent); |
| 1707 | − return -EIO; | |
| 1709 | + return -EUCLEAN; | |
| 1708 | 1710 | } |
| 1709 | 1711 | if (node->action == BTRFS_ADD_DELAYED_REF && insert_reserved) { |
| 1710 | 1712 | BUG_ON(!extent_op || !extent_op->update_flags); |
| @@ -3995,8 +3995,14 @@ void read_extent_buffer(const struct extent_buffer *eb, void *dstv, · 3994 unmodified lines | ||
| 3995 | 3995 | char *dst = (char *)dstv; |
| 3996 | 3996 | unsigned long i = get_eb_page_index(start); |
| 3997 | 3997 | |
| 3998 | − if (check_eb_range(eb, start, len)) | |
| 3998 | + if (check_eb_range(eb, start, len)) { | |
| 3999 | + /* | |
| 4000 | + * Invalid range hit, reset the memory, so callers won't get | |
| 4001 | + * some random garbage for their uninitialzed memory. | |
| 4002 | + */ | |
| 4003 | + memset(dstv, 0, len); | |
| 3999 | 4004 | return; |
| 4005 | + } | |
| 4000 | 4006 | |
| 4001 | 4007 | offset = get_eb_offset_in_page(eb, start); |
| 4002 | 4008 | |
| @@ -2117,7 +2117,7 @@ static int btrfs_statfs(struct dentry *dentry, struct kstatfs *buf) · 2116 unmodified lines | ||
| 2117 | 2117 | * calculated f_bavail. |
| 2118 | 2118 | */ |
| 2119 | 2119 | if (!mixed && block_rsv->space_info->full && |
| 2120 | − total_free_meta - thresh < block_rsv->size) | |
| 2120 | + (total_free_meta < thresh || total_free_meta - thresh < block_rsv->size)) | |
| 2121 | 2121 | buf->f_bavail = 0; |
| 2122 | 2122 | |
| 2123 | 2123 | buf->f_type = BTRFS_SUPER_MAGIC; |
| @@ -631,14 +631,14 @@ start_transaction(struct btrfs_root *root, unsigned int num_items, · 630 unmodified lines | ||
| 631 | 631 | reloc_reserved = true; |
| 632 | 632 | } |
| 633 | 633 | |
| 634 | − ret = btrfs_block_rsv_add(fs_info, rsv, num_bytes, flush); | |
| 634 | + ret = btrfs_reserve_metadata_bytes(fs_info, rsv, num_bytes, flush); | |
| 635 | 635 | if (ret) |
| 636 | 636 | goto reserve_fail; |
| 637 | 637 | if (delayed_refs_bytes) { |
| 638 | − btrfs_migrate_to_delayed_refs_rsv(fs_info, rsv, | |
| 639 | − delayed_refs_bytes); | |
| 638 | + btrfs_migrate_to_delayed_refs_rsv(fs_info, delayed_refs_bytes); | |
| 640 | 639 | num_bytes -= delayed_refs_bytes; |
| 641 | 640 | } |
| 641 | + btrfs_block_rsv_add_bytes(rsv, num_bytes, true); | |
| 642 | 642 | |
| 643 | 643 | if (rsv->space_info->force_alloc) |
| 644 | 644 | do_chunk_alloc = true; |
| @@ -4722,7 +4722,7 @@ static int btrfs_log_prealloc_extents(struct btrfs_trans_handle *trans, · 4721 unmodified lines | ||
| 4722 | 4722 | struct extent_buffer *leaf; |
| 4723 | 4723 | int slot; |
| 4724 | 4724 | int ins_nr = 0; |
| 4725 | − int start_slot; | |
| 4725 | + int start_slot = 0; | |
| 4726 | 4726 | int ret; |
| 4727 | 4727 | |
| 4728 | 4728 | if (!(inode->flags & BTRFS_INODE_PREALLOC)) |
| @@ -1594,7 +1594,7 @@ static int find_free_dev_extent(struct btrfs_device *device, u64 num_bytes, · 1593 unmodified lines | ||
| 1594 | 1594 | u64 search_start; |
| 1595 | 1595 | u64 hole_size; |
| 1596 | 1596 | u64 max_hole_start; |
| 1597 | − u64 max_hole_size; | |
| 1597 | + u64 max_hole_size = 0; | |
| 1598 | 1598 | u64 extent_end; |
| 1599 | 1599 | u64 search_end = device->total_bytes; |
| 1600 | 1600 | int ret; |
| @@ -1602,17 +1602,16 @@ static int find_free_dev_extent(struct btrfs_device *device, u64 num_bytes, · 1 unmodified line | ||
| 1602 | 1602 | struct extent_buffer *l; |
| 1603 | 1603 | |
| 1604 | 1604 | search_start = dev_extent_search_start(device); |
| 1605 | + max_hole_start = search_start; | |
| 1605 | 1606 | |
| 1606 | 1607 | WARN_ON(device->zone_info && |
| 1607 | 1608 | !IS_ALIGNED(num_bytes, device->zone_info->zone_size)); |
| 1608 | 1609 | |
| 1609 | 1610 | path = btrfs_alloc_path(); |
| 1610 | − if (!path) | |
| 1611 | − return -ENOMEM; | |
| 1612 | − | |
| 1613 | − max_hole_start = search_start; | |
| 1614 | − max_hole_size = 0; | |
| 1615 | − | |
| 1611 | + if (!path) { | |
| 1612 | + ret = -ENOMEM; | |
| 1613 | + goto out; | |
| 1614 | + } | |
| 1616 | 1615 | again: |
| 1617 | 1616 | if (search_start >= search_end || |
| 1618 | 1617 | test_bit(BTRFS_DEV_STATE_REPLACE_TGT, &device->dev_state)) { |
| @@ -2011,7 +2011,7 @@ void folio_zero_new_buffers(struct folio *folio, size_t from, size_t to) · 2010 unmodified lines | ||
| 2011 | 2011 | } |
| 2012 | 2012 | EXPORT_SYMBOL(folio_zero_new_buffers); |
| 2013 | 2013 | |
| 2014 | −static void | |
| 2014 | +static int | |
| 2015 | 2015 | iomap_to_bh(struct inode *inode, sector_t block, struct buffer_head *bh, |
| 2016 | 2016 | const struct iomap *iomap) |
| 2017 | 2017 | { |
| @@ -2025,7 +2025,8 @@ iomap_to_bh(struct inode *inode, sector_t block, struct buffer_head *bh, · 7 unmodified lines | ||
| 2025 | 2025 | * current block, then do not map the buffer and let the caller |
| 2026 | 2026 | * handle it. |
| 2027 | 2027 | */ |
| 2028 | − BUG_ON(offset >= iomap->offset + iomap->length); | |
| 2028 | + if (offset >= iomap->offset + iomap->length) | |
| 2029 | + return -EIO; | |
| 2029 | 2030 | |
| 2030 | 2031 | switch (iomap->type) { |
| 2031 | 2032 | case IOMAP_HOLE: |
| @@ -2037,7 +2038,7 @@ iomap_to_bh(struct inode *inode, sector_t block, struct buffer_head *bh, · 5 unmodified lines | ||
| 2037 | 2038 | if (!buffer_uptodate(bh) || |
| 2038 | 2039 | (offset >= i_size_read(inode))) |
| 2039 | 2040 | set_buffer_new(bh); |
| 2040 | − break; | |
| 2041 | + return 0; | |
| 2041 | 2042 | case IOMAP_DELALLOC: |
| 2042 | 2043 | if (!buffer_uptodate(bh) || |
| 2043 | 2044 | (offset >= i_size_read(inode))) |
| @@ -2045,7 +2046,7 @@ iomap_to_bh(struct inode *inode, sector_t block, struct buffer_head *bh, · 1 unmodified line | ||
| 2045 | 2046 | set_buffer_uptodate(bh); |
| 2046 | 2047 | set_buffer_mapped(bh); |
| 2047 | 2048 | set_buffer_delay(bh); |
| 2048 | − break; | |
| 2049 | + return 0; | |
| 2049 | 2050 | case IOMAP_UNWRITTEN: |
| 2050 | 2051 | /* |
| 2051 | 2052 | * For unwritten regions, we always need to ensure that regions |
| @@ -2057,12 +2058,24 @@ iomap_to_bh(struct inode *inode, sector_t block, struct buffer_head *bh, · 5 unmodified lines | ||
| 2057 | 2058 | fallthrough; |
| 2058 | 2059 | case IOMAP_MAPPED: |
| 2059 | 2060 | if ((iomap->flags & IOMAP_F_NEW) || |
| 2060 | − offset >= i_size_read(inode)) | |
| 2061 | + offset >= i_size_read(inode)) { | |
| 2062 | + /* | |
| 2063 | + * This can happen if truncating the block device races | |
| 2064 | + * with the check in the caller as i_size updates on | |
| 2065 | + * block devices aren't synchronized by i_rwsem for | |
| 2066 | + * block devices. | |
| 2067 | + */ | |
| 2068 | + if (S_ISBLK(inode->i_mode)) | |
| 2069 | + return -EIO; | |
| 2061 | 2070 | set_buffer_new(bh); |
| 2071 | + } | |
| 2062 | 2072 | bh->b_blocknr = (iomap->addr + offset - iomap->offset) >> |
| 2063 | 2073 | inode->i_blkbits; |
| 2064 | 2074 | set_buffer_mapped(bh); |
| 2065 | − break; | |
| 2075 | + return 0; | |
| 2076 | + default: | |
| 2077 | + WARN_ON_ONCE(1); | |
| 2078 | + return -EIO; | |
| 2066 | 2079 | } |
| 2067 | 2080 | } |
| 2068 | 2081 | |
| @@ -2103,13 +2116,12 @@ int __block_write_begin_int(struct folio *folio, loff_t pos, unsigned len, · 34 unmodified lines | ||
| 2103 | 2116 | clear_buffer_new(bh); |
| 2104 | 2117 | if (!buffer_mapped(bh)) { |
| 2105 | 2118 | WARN_ON(bh->b_size != blocksize); |
| 2106 | − if (get_block) { | |
| 2119 | + if (get_block) | |
| 2107 | 2120 | err = get_block(inode, block, bh, 1); |
| 2108 | − if (err) | |
| 2109 | − break; | |
| 2110 | − } else { | |
| 2111 | − iomap_to_bh(inode, block, bh, iomap); | |
| 2112 | − } | |
| 2121 | + else | |
| 2122 | + err = iomap_to_bh(inode, block, bh, iomap); | |
| 2123 | + if (err) | |
| 2124 | + break; | |
| 2113 | 2125 | |
| 2114 | 2126 | if (buffer_new(bh)) { |
| 2115 | 2127 | clean_bdev_bh_alias(bh); |
| @@ -249,11 +249,9 @@ static struct inode *parse_longname(const struct inode *parent, · 248 unmodified lines | ||
| 249 | 249 | if (!dir) { |
| 250 | 250 | /* This can happen if we're not mounting cephfs on the root */ |
| 251 | 251 | dir = ceph_get_inode(parent->i_sb, vino, NULL); |
| 252 | − if (!dir) | |
| 253 | − dir = ERR_PTR(-ENOENT); | |
| 252 | + if (IS_ERR(dir)) | |
| 253 | + dout("Can't find inode %s (%s)\n", inode_number, name); | |
| 254 | 254 | } |
| 255 | − if (IS_ERR(dir)) | |
| 256 | − dout("Can't find inode %s (%s)\n", inode_number, name); | |
| 257 | 255 | |
| 258 | 256 | out: |
| 259 | 257 | kfree(inode_number); |
| @@ -1535,10 +1535,15 @@ static void requeue_inode(struct inode *inode, struct bdi_writeback *wb, · 1534 unmodified lines | ||
| 1535 | 1535 | |
| 1536 | 1536 | if (wbc->pages_skipped) { |
| 1537 | 1537 | /* |
| 1538 | − * writeback is not making progress due to locked | |
| 1539 | − * buffers. Skip this inode for now. | |
| 1538 | + * Writeback is not making progress due to locked buffers. | |
| 1539 | + * Skip this inode for now. Although having skipped pages | |
| 1540 | + * is odd for clean inodes, it can happen for some | |
| 1541 | + * filesystems so handle that gracefully. | |
| 1540 | 1542 | */ |
| 1541 | − redirty_tail_locked(inode, wb); | |
| 1543 | + if (inode->i_state & I_DIRTY_ALL) | |
| 1544 | + redirty_tail_locked(inode, wb); | |
| 1545 | + else | |
| 1546 | + inode_cgwb_move_to_attached(inode, wb); | |
| 1542 | 1547 | return; |
| 1543 | 1548 | } |
| 1544 | 1549 | |
| @@ -640,11 +640,13 @@ static int __iomap_write_begin(const struct iomap_iter *iter, loff_t pos, · 639 unmodified lines | ||
| 640 | 640 | size_t poff, plen; |
| 641 | 641 | |
| 642 | 642 | /* |
| 643 | − * If the write completely overlaps the current folio, then | |
| 643 | + * If the write or zeroing completely overlaps the current folio, then | |
| 644 | 644 | * entire folio will be dirtied so there is no need for |
| 645 | 645 | * per-block state tracking structures to be attached to this folio. |
| 646 | + * For the unshare case, we must read in the ondisk contents because we | |
| 647 | + * are not changing pagecache contents. | |
| 646 | 648 | */ |
| 647 | − if (pos <= folio_pos(folio) && | |
| 649 | + if (!(iter->flags & IOMAP_UNSHARE) && pos <= folio_pos(folio) && | |
| 648 | 650 | pos + len >= folio_pos(folio) + folio_size(folio)) |
| 649 | 651 | return 0; |
| 650 | 652 | |
| @@ -1047,7 +1049,7 @@ static int iomap_write_delalloc_punch(struct inode *inode, struct folio *folio, · 396 unmodified lines | ||
| 1047 | 1049 | |
| 1048 | 1050 | /* |
| 1049 | 1051 | * Scan the data range passed to us for dirty page cache folios. If we find a |
| 1050 | − * dirty folio, punch out the preceeding range and update the offset from which | |
| 1052 | + * dirty folio, punch out the preceding range and update the offset from which | |
| 1051 | 1053 | * the next punch will start from. |
| 1052 | 1054 | * |
| 1053 | 1055 | * We can punch out storage reservations under clean pages because they either |
| @@ -1261,7 +1263,6 @@ static loff_t iomap_unshare_iter(struct iomap_iter *iter) · 207 unmodified lines | ||
| 1261 | 1263 | const struct iomap *srcmap = iomap_iter_srcmap(iter); |
| 1262 | 1264 | loff_t pos = iter->pos; |
| 1263 | 1265 | loff_t length = iomap_length(iter); |
| 1264 | − long status = 0; | |
| 1265 | 1266 | loff_t written = 0; |
| 1266 | 1267 | |
| 1267 | 1268 | /* don't bother with blocks that are not shared to start with */ |
| @@ -1272,28 +1273,33 @@ static loff_t iomap_unshare_iter(struct iomap_iter *iter) · 4 unmodified lines | ||
| 1272 | 1273 | return length; |
| 1273 | 1274 | |
| 1274 | 1275 | do { |
| 1275 | − unsigned long offset = offset_in_page(pos); | |
| 1276 | − unsigned long bytes = min_t(loff_t, PAGE_SIZE - offset, length); | |
| 1277 | 1276 | struct folio *folio; |
| 1277 | + int status; | |
| 1278 | + size_t offset; | |
| 1279 | + size_t bytes = min_t(u64, SIZE_MAX, length); | |
| 1278 | 1280 | |
| 1279 | 1281 | status = iomap_write_begin(iter, pos, bytes, &folio); |
| 1280 | 1282 | if (unlikely(status)) |
| 1281 | 1283 | return status; |
| 1282 | − if (iter->iomap.flags & IOMAP_F_STALE) | |
| 1284 | + if (iomap->flags & IOMAP_F_STALE) | |
| 1283 | 1285 | break; |
| 1284 | 1286 | |
| 1285 | − status = iomap_write_end(iter, pos, bytes, bytes, folio); | |
| 1286 | − if (WARN_ON_ONCE(status == 0)) | |
| 1287 | + offset = offset_in_folio(folio, pos); | |
| 1288 | + if (bytes > folio_size(folio) - offset) | |
| 1289 | + bytes = folio_size(folio) - offset; | |
| 1290 | + | |
| 1291 | + bytes = iomap_write_end(iter, pos, bytes, bytes, folio); | |
| 1292 | + if (WARN_ON_ONCE(bytes == 0)) | |
| 1287 | 1293 | return -EIO; |
| 1288 | 1294 | |
| 1289 | 1295 | cond_resched(); |
| 1290 | 1296 | |
| 1291 | − pos += status; | |
| 1292 | − written += status; | |
| 1293 | − length -= status; | |
| 1297 | + pos += bytes; | |
| 1298 | + written += bytes; | |
| 1299 | + length -= bytes; | |
| 1294 | 1300 | |
| 1295 | 1301 | balance_dirty_pages_ratelimited(iter->inode->i_mapping); |
| 1296 | − } while (length); | |
| 1302 | + } while (length > 0); | |
| 1297 | 1303 | |
| 1298 | 1304 | return written; |
| 1299 | 1305 | } |
| @@ -1903,6 +1903,7 @@ ssize_t direct_write_fallback(struct kiocb *iocb, struct iov_iter *iter, · 1902 unmodified lines | ||
| 1903 | 1903 | * We don't know how much we wrote, so just return the number of |
| 1904 | 1904 | * bytes which were direct-written |
| 1905 | 1905 | */ |
| 1906 | + iocb->ki_pos -= buffered_written; | |
| 1906 | 1907 | if (direct_written) |
| 1907 | 1908 | return direct_written; |
| 1908 | 1909 | return err; |
| @@ -10622,7 +10622,9 @@ static void nfs4_disable_swap(struct inode *inode) · 10621 unmodified lines | ||
| 10622 | 10622 | */ |
| 10623 | 10623 | struct nfs_client *clp = NFS_SERVER(inode)->nfs_client; |
| 10624 | 10624 | |
| 10625 | − nfs4_schedule_state_manager(clp); | |
| 10625 | + set_bit(NFS4CLNT_RUN_MANAGER, &clp->cl_state); | |
| 10626 | + clear_bit(NFS4CLNT_MANAGER_AVAILABLE, &clp->cl_state); | |
| 10627 | + wake_up_var(&clp->cl_state); | |
| 10626 | 10628 | } |
| 10627 | 10629 | |
| 10628 | 10630 | static const struct inode_operations nfs4_dir_inode_operations = { |
| @@ -1209,16 +1209,26 @@ void nfs4_schedule_state_manager(struct nfs_client *clp) · 1208 unmodified lines | ||
| 1209 | 1209 | { |
| 1210 | 1210 | struct task_struct *task; |
| 1211 | 1211 | char buf[INET6_ADDRSTRLEN + sizeof("-manager") + 1]; |
| 1212 | + struct rpc_clnt *clnt = clp->cl_rpcclient; | |
| 1213 | + bool swapon = false; | |
| 1212 | 1214 | |
| 1213 | − if (clp->cl_rpcclient->cl_shutdown) | |
| 1215 | + if (clnt->cl_shutdown) | |
| 1214 | 1216 | return; |
| 1215 | 1217 | |
| 1216 | 1218 | set_bit(NFS4CLNT_RUN_MANAGER, &clp->cl_state); |
| 1217 | − if (test_and_set_bit(NFS4CLNT_MANAGER_AVAILABLE, &clp->cl_state) != 0) { | |
| 1218 | − wake_up_var(&clp->cl_state); | |
| 1219 | − return; | |
| 1219 | + | |
| 1220 | + if (atomic_read(&clnt->cl_swapper)) { | |
| 1221 | + swapon = !test_and_set_bit(NFS4CLNT_MANAGER_AVAILABLE, | |
| 1222 | + &clp->cl_state); | |
| 1223 | + if (!swapon) { | |
| 1224 | + wake_up_var(&clp->cl_state); | |
| 1225 | + return; | |
| 1226 | + } | |
| 1220 | 1227 | } |
| 1221 | − set_bit(NFS4CLNT_MANAGER_RUNNING, &clp->cl_state); | |
| 1228 | + | |
| 1229 | + if (test_and_set_bit(NFS4CLNT_MANAGER_RUNNING, &clp->cl_state) != 0) | |
| 1230 | + return; | |
| 1231 | + | |
| 1222 | 1232 | __module_get(THIS_MODULE); |
| 1223 | 1233 | refcount_inc(&clp->cl_count); |
| 1224 | 1234 | |
| @@ -1235,8 +1245,9 @@ void nfs4_schedule_state_manager(struct nfs_client *clp) · 10 unmodified lines | ||
| 1235 | 1245 | __func__, PTR_ERR(task)); |
| 1236 | 1246 | if (!nfs_client_init_is_complete(clp)) |
| 1237 | 1247 | nfs_mark_client_ready(clp, PTR_ERR(task)); |
| 1248 | + if (swapon) | |
| 1249 | + clear_bit(NFS4CLNT_MANAGER_AVAILABLE, &clp->cl_state); | |
| 1238 | 1250 | nfs4_clear_state_manager_bit(clp); |
| 1239 | − clear_bit(NFS4CLNT_MANAGER_AVAILABLE, &clp->cl_state); | |
| 1240 | 1251 | nfs_put_client(clp); |
| 1241 | 1252 | module_put(THIS_MODULE); |
| 1242 | 1253 | } |
| @@ -2703,6 +2714,13 @@ static void nfs4_state_manager(struct nfs_client *clp) · 1460 unmodified lines | ||
| 2703 | 2714 | nfs4_end_drain_session(clp); |
| 2704 | 2715 | nfs4_clear_state_manager_bit(clp); |
| 2705 | 2716 | |
| 2717 | + if (test_bit(NFS4CLNT_RUN_MANAGER, &clp->cl_state) && | |
| 2718 | + !test_and_set_bit(NFS4CLNT_MANAGER_RUNNING, | |
| 2719 | + &clp->cl_state)) { | |
| 2720 | + memflags = memalloc_nofs_save(); | |
| 2721 | + continue; | |
| 2722 | + } | |
| 2723 | + | |
| 2706 | 2724 | if (!test_and_set_bit(NFS4CLNT_RECALL_RUNNING, &clp->cl_state)) { |
| 2707 | 2725 | if (test_and_clear_bit(NFS4CLNT_DELEGRETURN, &clp->cl_state)) { |
| 2708 | 2726 | nfs_client_return_marked_delegations(clp); |
| @@ -2741,22 +2759,25 @@ static int nfs4_run_state_manager(void *ptr) · 32 unmodified lines | ||
| 2741 | 2759 | |
| 2742 | 2760 | allow_signal(SIGKILL); |
| 2743 | 2761 | again: |
| 2744 | − set_bit(NFS4CLNT_MANAGER_RUNNING, &clp->cl_state); | |
| 2745 | 2762 | nfs4_state_manager(clp); |
| 2746 | − if (atomic_read(&cl->cl_swapper)) { | |
| 2763 | + | |
| 2764 | + if (test_bit(NFS4CLNT_MANAGER_AVAILABLE, &clp->cl_state) && | |
| 2765 | + !test_bit(NFS4CLNT_MANAGER_RUNNING, &clp->cl_state)) { | |
| 2747 | 2766 | wait_var_event_interruptible(&clp->cl_state, |
| 2748 | 2767 | test_bit(NFS4CLNT_RUN_MANAGER, |
| 2749 | 2768 | &clp->cl_state)); |
| 2750 | − if (atomic_read(&cl->cl_swapper) && | |
| 2751 | − test_bit(NFS4CLNT_RUN_MANAGER, &clp->cl_state)) | |
| 2769 | + if (!atomic_read(&cl->cl_swapper)) | |
| 2770 | + clear_bit(NFS4CLNT_MANAGER_AVAILABLE, &clp->cl_state); | |
| 2771 | + if (refcount_read(&clp->cl_count) > 1 && !signalled() && | |
| 2772 | + !test_and_set_bit(NFS4CLNT_MANAGER_RUNNING, &clp->cl_state)) | |
| 2752 | 2773 | goto again; |
| 2753 | 2774 | /* Either no longer a swapper, or were signalled */ |
| 2775 | + clear_bit(NFS4CLNT_MANAGER_AVAILABLE, &clp->cl_state); | |
| 2754 | 2776 | } |
| 2755 | − clear_bit(NFS4CLNT_MANAGER_AVAILABLE, &clp->cl_state); | |
| 2756 | 2777 | |
| 2757 | 2778 | if (refcount_read(&clp->cl_count) > 1 && !signalled() && |
| 2758 | 2779 | test_bit(NFS4CLNT_RUN_MANAGER, &clp->cl_state) && |
| 2759 | − !test_and_set_bit(NFS4CLNT_MANAGER_AVAILABLE, &clp->cl_state)) | |
| 2780 | + !test_and_set_bit(NFS4CLNT_MANAGER_RUNNING, &clp->cl_state)) | |
| 2760 | 2781 | goto again; |
| 2761 | 2782 | |
| 2762 | 2783 | nfs_put_client(clp); |
| @@ -802,8 +802,8 @@ static void nfs_inode_remove_request(struct nfs_page *req) · 801 unmodified lines | ||
| 802 | 802 | } |
| 803 | 803 | |
| 804 | 804 | if (test_and_clear_bit(PG_INODE_REF, &req->wb_flags)) { |
| 805 | − nfs_release_request(req); | |
| 806 | 805 | atomic_long_dec(&NFS_I(nfs_page_to_inode(req))->nrequests); |
| 806 | + nfs_release_request(req); | |
| 807 | 807 | } |
| 808 | 808 | } |
| 809 | 809 | |
| @@ -4113,6 +4113,7 @@ static __be32 nfsd4_encode_readv(struct nfsd4_compoundres *resp, · 4112 unmodified lines | ||
| 4113 | 4113 | struct file *file, unsigned long maxcount) |
| 4114 | 4114 | { |
| 4115 | 4115 | struct xdr_stream *xdr = resp->xdr; |
| 4116 | + unsigned int base = xdr->buf->page_len & ~PAGE_MASK; | |
| 4116 | 4117 | unsigned int starting_len = xdr->buf->len; |
| 4117 | 4118 | __be32 zero = xdr_zero; |
| 4118 | 4119 | __be32 nfserr; |
| @@ -4121,8 +4122,7 @@ static __be32 nfsd4_encode_readv(struct nfsd4_compoundres *resp, · 2 unmodified lines | ||
| 4121 | 4122 | return nfserr_resource; |
| 4122 | 4123 | |
| 4123 | 4124 | nfserr = nfsd_iter_read(resp->rqstp, read->rd_fhp, file, |
| 4124 | − read->rd_offset, &maxcount, | |
| 4125 | − xdr->buf->page_len & ~PAGE_MASK, | |
| 4125 | + read->rd_offset, &maxcount, base, | |
| 4126 | 4126 | &read->rd_eof); |
| 4127 | 4127 | read->rd_length = maxcount; |
| 4128 | 4128 | if (nfserr) |
| @@ -73,10 +73,8 @@ int nilfs_gccache_submit_read_data(struct inode *inode, sector_t blkoff, · 72 unmodified lines | ||
| 73 | 73 | struct the_nilfs *nilfs = inode->i_sb->s_fs_info; |
| 74 | 74 | |
| 75 | 75 | err = nilfs_dat_translate(nilfs->ns_dat, vbn, &pbn); |
| 76 | − if (unlikely(err)) { /* -EIO, -ENOMEM, -ENOENT */ | |
| 77 | − brelse(bh); | |
| 76 | + if (unlikely(err)) /* -EIO, -ENOMEM, -ENOENT */ | |
| 78 | 77 | goto failed; |
| 79 | − } | |
| 80 | 78 | } |
| 81 | 79 | |
| 82 | 80 | lock_buffer(bh); |
| @@ -102,6 +100,8 @@ int nilfs_gccache_submit_read_data(struct inode *inode, sector_t blkoff, · 19 unmodified lines | ||
| 102 | 100 | failed: |
| 103 | 101 | unlock_page(bh->b_page); |
| 104 | 102 | put_page(bh->b_page); |
| 103 | + if (unlikely(err)) | |
| 104 | + brelse(bh); | |
| 105 | 105 | return err; |
| 106 | 106 | } |
| 107 | 107 | |
| @@ -1562,6 +1562,7 @@ load_root: · 1561 unmodified lines | ||
| 1562 | 1562 | put_inode_out: |
| 1563 | 1563 | iput(inode); |
| 1564 | 1564 | out: |
| 1565 | + ntfs3_put_sbi(sbi); | |
| 1565 | 1566 | kfree(boot2); |
| 1566 | 1567 | return err; |
| 1567 | 1568 | } |
| @@ -337,7 +337,7 @@ static int ovl_set_timestamps(struct ovl_fs *ofs, struct dentry *upperdentry, · 336 unmodified lines | ||
| 337 | 337 | { |
| 338 | 338 | struct iattr attr = { |
| 339 | 339 | .ia_valid = |
| 340 | − ATTR_ATIME | ATTR_MTIME | ATTR_ATIME_SET | ATTR_MTIME_SET, | |
| 340 | + ATTR_ATIME | ATTR_MTIME | ATTR_ATIME_SET | ATTR_MTIME_SET | ATTR_CTIME, | |
| 341 | 341 | .ia_atime = stat->atime, |
| 342 | 342 | .ia_mtime = stat->mtime, |
| 343 | 343 | }; |
| @@ -188,7 +188,7 @@ static int ovl_check_encode_origin(struct dentry *dentry) · 187 unmodified lines | ||
| 188 | 188 | |
| 189 | 189 | /* Lower file handle for non-upper non-decodable */ |
| 190 | 190 | if (!ovl_dentry_upper(dentry) && !decodable) |
| 191 | − return 0; | |
| 191 | + return 1; | |
| 192 | 192 | |
| 193 | 193 | /* Upper file handle for pure upper */ |
| 194 | 194 | if (!ovl_dentry_lower(dentry)) |
| @@ -341,7 +341,6 @@ static ssize_t ovl_read_iter(struct kiocb *iocb, struct iov_iter *iter) · 340 unmodified lines | ||
| 341 | 341 | if (!aio_req) |
| 342 | 342 | goto out; |
| 343 | 343 | |
| 344 | − real.flags = 0; | |
| 345 | 344 | aio_req->orig_iocb = iocb; |
| 346 | 345 | kiocb_clone(&aio_req->iocb, iocb, get_file(real.file)); |
| 347 | 346 | aio_req->iocb.ki_complete = ovl_aio_rw_complete; |
| @@ -391,6 +390,12 @@ static ssize_t ovl_write_iter(struct kiocb *iocb, struct iov_iter *iter) · 43 unmodified lines | ||
| 391 | 390 | if (!ovl_should_sync(OVL_FS(inode->i_sb))) |
| 392 | 391 | ifl &= ~(IOCB_DSYNC | IOCB_SYNC); |
| 393 | 392 | |
| 393 | + /* | |
| 394 | + * Overlayfs doesn't support deferred completions, don't copy | |
| 395 | + * this property in case it is set by the issuer. | |
| 396 | + */ | |
| 397 | + ifl &= ~IOCB_DIO_CALLER_COMP; | |
| 398 | + | |
| 394 | 399 | old_cred = ovl_override_creds(file_inode(file)->i_sb); |
| 395 | 400 | if (is_sync_kiocb(iocb)) { |
| 396 | 401 | file_start_write(real.file); |
| @@ -407,7 +412,6 @@ static ssize_t ovl_write_iter(struct kiocb *iocb, struct iov_iter *iter) · 10 unmodified lines | ||
| 407 | 412 | if (!aio_req) |
| 408 | 413 | goto out; |
| 409 | 414 | |
| 410 | − real.flags = 0; | |
| 411 | 415 | aio_req->orig_iocb = iocb; |
| 412 | 416 | kiocb_clone(&aio_req->iocb, iocb, get_file(real.file)); |
| 413 | 417 | aio_req->iocb.ki_flags = ifl; |
| @@ -8,6 +8,7 @@ · 7 unmodified lines | ||
| 8 | 8 | struct ovl_config { |
| 9 | 9 | char *upperdir; |
| 10 | 10 | char *workdir; |
| 11 | + char **lowerdirs; | |
| 11 | 12 | bool default_permissions; |
| 12 | 13 | int redirect_mode; |
| 13 | 14 | int verity_mode; |
| @@ -39,17 +40,8 @@ struct ovl_layer { · 25 unmodified lines | ||
| 39 | 40 | int idx; |
| 40 | 41 | /* One fsid per unique underlying sb (upper fsid == 0) */ |
| 41 | 42 | int fsid; |
| 42 | − char *name; | |
| 43 | 43 | }; |
| 44 | 44 | |
| 45 | −/* | |
| 46 | − * ovl_free_fs() relies on @mnt being the first member when unmounting | |
| 47 | − * the private mounts created for each layer. Let's check both the | |
| 48 | − * offset and type. | |
| 49 | − */ | |
| 50 | −static_assert(offsetof(struct ovl_layer, mnt) == 0); | |
| 51 | −static_assert(__same_type(typeof_member(struct ovl_layer, mnt), struct vfsmount *)); | |
| 52 | − | |
| 53 | 45 | struct ovl_path { |
| 54 | 46 | const struct ovl_layer *layer; |
| 55 | 47 | struct dentry *dentry; |
| @@ -752,12 +752,12 @@ void ovl_free_fs(struct ovl_fs *ofs) · 751 unmodified lines | ||
| 752 | 752 | if (ofs->upperdir_locked) |
| 753 | 753 | ovl_inuse_unlock(ovl_upper_mnt(ofs)->mnt_root); |
| 754 | 754 | |
| 755 | − /* Hack! Reuse ofs->layers as a vfsmount array before freeing it */ | |
| 756 | − mounts = (struct vfsmount **) ofs->layers; | |
| 755 | + /* Reuse ofs->config.lowerdirs as a vfsmount array before freeing it */ | |
| 756 | + mounts = (struct vfsmount **) ofs->config.lowerdirs; | |
| 757 | 757 | for (i = 0; i < ofs->numlayer; i++) { |
| 758 | 758 | iput(ofs->layers[i].trap); |
| 759 | + kfree(ofs->config.lowerdirs[i]); | |
| 759 | 760 | mounts[i] = ofs->layers[i].mnt; |
| 760 | − kfree(ofs->layers[i].name); | |
| 761 | 761 | } |
| 762 | 762 | kern_unmount_array(mounts, ofs->numlayer); |
| 763 | 763 | kfree(ofs->layers); |
| @@ -765,6 +765,7 @@ void ovl_free_fs(struct ovl_fs *ofs) · 1 unmodified line | ||
| 765 | 765 | free_anon_bdev(ofs->fs[i].pseudo_dev); |
| 766 | 766 | kfree(ofs->fs); |
| 767 | 767 | |
| 768 | + kfree(ofs->config.lowerdirs); | |
| 768 | 769 | kfree(ofs->config.upperdir); |
| 769 | 770 | kfree(ofs->config.workdir); |
| 770 | 771 | if (ofs->creator_cred) |
| @@ -949,16 +950,16 @@ int ovl_show_options(struct seq_file *m, struct dentry *dentry) · 178 unmodified lines | ||
| 949 | 950 | struct super_block *sb = dentry->d_sb; |
| 950 | 951 | struct ovl_fs *ofs = OVL_FS(sb); |
| 951 | 952 | size_t nr, nr_merged_lower = ofs->numlayer - ofs->numdatalayer; |
| 952 | − const struct ovl_layer *data_layers = &ofs->layers[nr_merged_lower]; | |
| 953 | + char **lowerdatadirs = &ofs->config.lowerdirs[nr_merged_lower]; | |
| 953 | 954 | |
| 954 | − /* ofs->layers[0] is the upper layer */ | |
| 955 | − seq_printf(m, ",lowerdir=%s", ofs->layers[1].name); | |
| 955 | + /* lowerdirs[] starts from offset 1 */ | |
| 956 | + seq_printf(m, ",lowerdir=%s", ofs->config.lowerdirs[1]); | |
| 956 | 957 | /* dump regular lower layers */ |
| 957 | 958 | for (nr = 2; nr < nr_merged_lower; nr++) |
| 958 | − seq_printf(m, ":%s", ofs->layers[nr].name); | |
| 959 | + seq_printf(m, ":%s", ofs->config.lowerdirs[nr]); | |
| 959 | 960 | /* dump data lower layers */ |
| 960 | 961 | for (nr = 0; nr < ofs->numdatalayer; nr++) |
| 961 | − seq_printf(m, "::%s", data_layers[nr].name); | |
| 962 | + seq_printf(m, "::%s", lowerdatadirs[nr]); | |
| 962 | 963 | if (ofs->config.upperdir) { |
| 963 | 964 | seq_show_option(m, "upperdir", ofs->config.upperdir); |
| 964 | 965 | seq_show_option(m, "workdir", ofs->config.workdir); |
| @@ -104,8 +104,8 @@ static int ovl_revalidate_real(struct dentry *d, unsigned int flags, bool weak) · 103 unmodified lines | ||
| 104 | 104 | static int ovl_dentry_revalidate_common(struct dentry *dentry, |
| 105 | 105 | unsigned int flags, bool weak) |
| 106 | 106 | { |
| 107 | − struct ovl_entry *oe = OVL_E(dentry); | |
| 108 | − struct ovl_path *lowerstack = ovl_lowerstack(oe); | |
| 107 | + struct ovl_entry *oe; | |
| 108 | + struct ovl_path *lowerstack; | |
| 109 | 109 | struct inode *inode = d_inode_rcu(dentry); |
| 110 | 110 | struct dentry *upper; |
| 111 | 111 | unsigned int i; |
| @@ -115,6 +115,8 @@ static int ovl_dentry_revalidate_common(struct dentry *dentry, · 3 unmodified lines | ||
| 115 | 115 | if (!inode) |
| 116 | 116 | return -ECHILD; |
| 117 | 117 | |
| 118 | + oe = OVL_I_E(inode); | |
| 119 | + lowerstack = ovl_lowerstack(oe); | |
| 118 | 120 | upper = ovl_i_dentry_upper(inode); |
| 119 | 121 | if (upper) |
| 120 | 122 | ret = ovl_revalidate_real(upper, flags, weak); |
| @@ -167,6 +169,7 @@ static void ovl_free_inode(struct inode *inode) · 46 unmodified lines | ||
| 167 | 169 | struct ovl_inode *oi = OVL_I(inode); |
| 168 | 170 | |
| 169 | 171 | kfree(oi->redirect); |
| 172 | + kfree(oi->oe); | |
| 170 | 173 | mutex_destroy(&oi->lock); |
| 171 | 174 | kmem_cache_free(ovl_inode_cachep, oi); |
| 172 | 175 | } |
| @@ -176,7 +179,7 @@ static void ovl_destroy_inode(struct inode *inode) · 3 unmodified lines | ||
| 176 | 179 | struct ovl_inode *oi = OVL_I(inode); |
| 177 | 180 | |
| 178 | 181 | dput(oi->__upperdentry); |
| 179 | − ovl_free_entry(oi->oe); | |
| 182 | + ovl_stack_put(ovl_lowerstack(oi->oe), ovl_numlower(oi->oe)); | |
| 180 | 183 | if (S_ISDIR(inode->i_mode)) |
| 181 | 184 | ovl_dir_cache_free(inode); |
| 182 | 185 | else |
| @@ -569,11 +572,6 @@ static int ovl_get_upper(struct super_block *sb, struct ovl_fs *ofs, · 386 unmodified lines | ||
| 569 | 572 | upper_layer->idx = 0; |
| 570 | 573 | upper_layer->fsid = 0; |
| 571 | 574 | |
| 572 | − err = -ENOMEM; | |
| 573 | − upper_layer->name = kstrdup(ofs->config.upperdir, GFP_KERNEL); | |
| 574 | − if (!upper_layer->name) | |
| 575 | − goto out; | |
| 576 | − | |
| 577 | 575 | /* |
| 578 | 576 | * Inherit SB_NOSEC flag from upperdir. |
| 579 | 577 | * |
| @@ -1122,7 +1120,8 @@ static int ovl_get_layers(struct super_block *sb, struct ovl_fs *ofs, · 542 unmodified lines | ||
| 1122 | 1120 | layers[ofs->numlayer].idx = ofs->numlayer; |
| 1123 | 1121 | layers[ofs->numlayer].fsid = fsid; |
| 1124 | 1122 | layers[ofs->numlayer].fs = &ofs->fs[fsid]; |
| 1125 | − layers[ofs->numlayer].name = l->name; | |
| 1123 | + /* Store for printing lowerdir=... in ovl_show_options() */ | |
| 1124 | + ofs->config.lowerdirs[ofs->numlayer] = l->name; | |
| 1126 | 1125 | l->name = NULL; |
| 1127 | 1126 | ofs->numlayer++; |
| 1128 | 1127 | ofs->fs[fsid].is_lower = true; |
| @@ -1367,8 +1366,16 @@ int ovl_fill_super(struct super_block *sb, struct fs_context *fc) · 238 unmodified lines | ||
| 1367 | 1366 | if (!layers) |
| 1368 | 1367 | goto out_err; |
| 1369 | 1368 | |
| 1369 | + ofs->config.lowerdirs = kcalloc(ctx->nr + 1, sizeof(char *), GFP_KERNEL); | |
| 1370 | + if (!ofs->config.lowerdirs) { | |
| 1371 | + kfree(layers); | |
| 1372 | + goto out_err; | |
| 1373 | + } | |
| 1370 | 1374 | ofs->layers = layers; |
| 1371 | − /* Layer 0 is reserved for upper even if there's no upper */ | |
| 1375 | + /* | |
| 1376 | + * Layer 0 is reserved for upper even if there's no upper. | |
| 1377 | + * For consistency, config.lowerdirs[0] is NULL. | |
| 1378 | + */ | |
| 1372 | 1379 | ofs->numlayer = 1; |
| 1373 | 1380 | |
| 1374 | 1381 | sb->s_stack_depth = 0; |
| @@ -537,7 +537,6 @@ pipe_write(struct kiocb *iocb, struct iov_iter *from) · 536 unmodified lines | ||
| 537 | 537 | break; |
| 538 | 538 | } |
| 539 | 539 | ret += copied; |
| 540 | − buf->offset = 0; | |
| 541 | 540 | buf->len = copied; |
| 542 | 541 | |
| 543 | 542 | if (!iov_iter_count(from)) |
| @@ -289,9 +289,7 @@ struct proc_maps_private { · 288 unmodified lines | ||
| 289 | 289 | struct inode *inode; |
| 290 | 290 | struct task_struct *task; |
| 291 | 291 | struct mm_struct *mm; |
| 292 | −#ifdef CONFIG_MMU | |
| 293 | 292 | struct vma_iterator iter; |
| 294 | −#endif | |
| 295 | 293 | #ifdef CONFIG_NUMA |
| 296 | 294 | struct mempolicy *task_mempolicy; |
| 297 | 295 | #endif |
| @@ -175,15 +175,28 @@ static int show_map(struct seq_file *m, void *_p) · 174 unmodified lines | ||
| 175 | 175 | return nommu_vma_show(m, _p); |
| 176 | 176 | } |
| 177 | 177 | |
| 178 | −static void *m_start(struct seq_file *m, loff_t *pos) | |
| 178 | +static struct vm_area_struct *proc_get_vma(struct proc_maps_private *priv, | |
| 179 | + loff_t *ppos) | |
| 180 | +{ | |
| 181 | + struct vm_area_struct *vma = vma_next(&priv->iter); | |
| 182 | + | |
| 183 | + if (vma) { | |
| 184 | + *ppos = vma->vm_start; | |
| 185 | + } else { | |
| 186 | + *ppos = -1UL; | |
| 187 | + } | |
| 188 | + | |
| 189 | + return vma; | |
| 190 | +} | |
| 191 | + | |
| 192 | +static void *m_start(struct seq_file *m, loff_t *ppos) | |
| 179 | 193 | { |
| 180 | 194 | struct proc_maps_private *priv = m->private; |
| 195 | + unsigned long last_addr = *ppos; | |
| 181 | 196 | struct mm_struct *mm; |
| 182 | − struct vm_area_struct *vma; | |
| 183 | − unsigned long addr = *pos; | |
| 184 | 197 | |
| 185 | − /* See m_next(). Zero at the start or after lseek. */ | |
| 186 | − if (addr == -1UL) | |
| 198 | + /* See proc_get_vma(). Zero at the start or after lseek. */ | |
| 199 | + if (last_addr == -1UL) | |
| 187 | 200 | return NULL; |
| 188 | 201 | |
| 189 | 202 | /* pin the task and mm whilst we play with them */ |
| @@ -192,44 +205,41 @@ static void *m_start(struct seq_file *m, loff_t *pos) · 2 unmodified lines | ||
| 192 | 205 | return ERR_PTR(-ESRCH); |
| 193 | 206 | |
| 194 | 207 | mm = priv->mm; |
| 195 | − if (!mm || !mmget_not_zero(mm)) | |
| 208 | + if (!mm || !mmget_not_zero(mm)) { | |
| 209 | + put_task_struct(priv->task); | |
| 210 | + priv->task = NULL; | |
| 196 | 211 | return NULL; |
| 212 | + } | |
| 197 | 213 | |
| 198 | 214 | if (mmap_read_lock_killable(mm)) { |
| 199 | 215 | mmput(mm); |
| 216 | + put_task_struct(priv->task); | |
| 217 | + priv->task = NULL; | |
| 200 | 218 | return ERR_PTR(-EINTR); |
| 201 | 219 | } |
| 202 | 220 | |
| 203 | − /* start the next element from addr */ | |
| 204 | − vma = find_vma(mm, addr); | |
| 205 | − if (vma) | |
| 206 | − return vma; | |
| 221 | + vma_iter_init(&priv->iter, mm, last_addr); | |
| 207 | 222 | |
| 208 | − mmap_read_unlock(mm); | |
| 209 | − mmput(mm); | |
| 210 | − return NULL; | |
| 223 | + return proc_get_vma(priv, ppos); | |
| 211 | 224 | } |
| 212 | 225 | |
| 213 | −static void m_stop(struct seq_file *m, void *_vml) | |
| 226 | +static void m_stop(struct seq_file *m, void *v) | |
| 214 | 227 | { |
| 215 | 228 | struct proc_maps_private *priv = m->private; |
| 229 | + struct mm_struct *mm = priv->mm; | |
| 216 | 230 | |
| 217 | − if (!IS_ERR_OR_NULL(_vml)) { | |
| 218 | − mmap_read_unlock(priv->mm); | |
| 219 | − mmput(priv->mm); | |
| 220 | − } | |
| 221 | − if (priv->task) { | |
| 222 | − put_task_struct(priv->task); | |
| 223 | − priv->task = NULL; | |
| 224 | − } | |
| 231 | + if (!priv->task) | |
| 232 | + return; | |
| 233 | + | |
| 234 | + mmap_read_unlock(mm); | |
| 235 | + mmput(mm); | |
| 236 | + put_task_struct(priv->task); | |
| 237 | + priv->task = NULL; | |
| 225 | 238 | } |
| 226 | 239 | |
| 227 | −static void *m_next(struct seq_file *m, void *_p, loff_t *pos) | |
| 240 | +static void *m_next(struct seq_file *m, void *_p, loff_t *ppos) | |
| 228 | 241 | { |
| 229 | − struct vm_area_struct *vma = _p; | |
| 230 | − | |
| 231 | − *pos = vma->vm_end; | |
| 232 | − return find_vma(vma->vm_mm, vma->vm_end); | |
| 242 | + return proc_get_vma(m->private, ppos); | |
| 233 | 243 | } |
| 234 | 244 | |
| 235 | 245 | static const struct seq_operations proc_pid_maps_ops = { |
| @@ -2699,7 +2699,7 @@ struct reiserfs_iget_args { · 2698 unmodified lines | ||
| 2699 | 2699 | #define get_journal_desc_magic(bh) (bh->b_data + bh->b_size - 12) |
| 2700 | 2700 | |
| 2701 | 2701 | #define journal_trans_half(blocksize) \ |
| 2702 | − ((blocksize - sizeof (struct reiserfs_journal_desc) + sizeof (__u32) - 12) / sizeof (__u32)) | |
| 2702 | + ((blocksize - sizeof(struct reiserfs_journal_desc) - 12) / sizeof(__u32)) | |
| 2703 | 2703 | |
| 2704 | 2704 | /* journal.c see journal.c for all the comments here */ |
| 2705 | 2705 | |
| @@ -2711,7 +2711,7 @@ struct reiserfs_journal_desc { · 5 unmodified lines | ||
| 2711 | 2711 | __le32 j_len; |
| 2712 | 2712 | |
| 2713 | 2713 | __le32 j_mount_id; /* mount id of this trans */ |
| 2714 | − __le32 j_realblock[1]; /* real locations for each block */ | |
| 2714 | + __le32 j_realblock[]; /* real locations for each block */ | |
| 2715 | 2715 | }; |
| 2716 | 2716 | |
| 2717 | 2717 | #define get_desc_trans_id(d) le32_to_cpu((d)->j_trans_id) |
| @@ -2726,7 +2726,7 @@ struct reiserfs_journal_desc { · 8 unmodified lines | ||
| 2726 | 2726 | struct reiserfs_journal_commit { |
| 2727 | 2727 | __le32 j_trans_id; /* must match j_trans_id from the desc block */ |
| 2728 | 2728 | __le32 j_len; /* ditto */ |
| 2729 | − __le32 j_realblock[1]; /* real locations for each block */ | |
| 2729 | + __le32 j_realblock[]; /* real locations for each block */ | |
| 2730 | 2730 | }; |
| 2731 | 2731 | |
| 2732 | 2732 | #define get_commit_trans_id(c) le32_to_cpu((c)->j_trans_id) |
| @@ -452,6 +452,9 @@ void invalidate_all_cached_dirs(struct cifs_tcon *tcon) · 451 unmodified lines | ||
| 452 | 452 | struct cached_fid *cfid, *q; |
| 453 | 453 | LIST_HEAD(entry); |
| 454 | 454 | |
| 455 | + if (cfids == NULL) | |
| 456 | + return; | |
| 457 | + | |
| 455 | 458 | spin_lock(&cfids->cfid_list_lock); |
| 456 | 459 | list_for_each_entry_safe(cfid, q, &cfids->entries, entry) { |
| 457 | 460 | list_move(&cfid->entry, &entry); |
| @@ -651,6 +654,9 @@ void free_cached_dirs(struct cached_fids *cfids) · 193 unmodified lines | ||
| 651 | 654 | struct cached_fid *cfid, *q; |
| 652 | 655 | LIST_HEAD(entry); |
| 653 | 656 | |
| 657 | + if (cfids == NULL) | |
| 658 | + return; | |
| 659 | + | |
| 654 | 660 | if (cfids->laundromat) { |
| 655 | 661 | kthread_stop(cfids->laundromat); |
| 656 | 662 | cfids->laundromat = NULL; |
| @@ -1807,6 +1807,7 @@ static inline bool is_retryable_error(int error) · 1806 unmodified lines | ||
| 1807 | 1807 | #define MID_RETRY_NEEDED 8 /* session closed while this request out */ |
| 1808 | 1808 | #define MID_RESPONSE_MALFORMED 0x10 |
| 1809 | 1809 | #define MID_SHUTDOWN 0x20 |
| 1810 | +#define MID_RESPONSE_READY 0x40 /* ready for other process handle the rsp */ | |
| 1810 | 1811 | |
| 1811 | 1812 | /* Flags */ |
| 1812 | 1813 | #define MID_WAIT_CANCELLED 1 /* Cancelled while waiting for response */ |
| @@ -1943,7 +1944,7 @@ require use of the stronger protocol */ · 130 unmodified lines | ||
| 1943 | 1944 | * cifsInodeInfo->lock_sem cifsInodeInfo->llist cifs_init_once |
| 1944 | 1945 | * ->can_cache_brlcks |
| 1945 | 1946 | * cifsInodeInfo->deferred_lock cifsInodeInfo->deferred_closes cifsInodeInfo_alloc |
| 1946 | − * cached_fid->fid_mutex cifs_tcon->crfid tconInfoAlloc | |
| 1947 | + * cached_fid->fid_mutex cifs_tcon->crfid tcon_info_alloc | |
| 1947 | 1948 | * cifsFileInfo->fh_mutex cifsFileInfo cifs_new_fileinfo |
| 1948 | 1949 | * cifsFileInfo->file_info_lock cifsFileInfo->count cifs_new_fileinfo |
| 1949 | 1950 | * ->invalidHandle initiate_cifs_search |
| @@ -512,7 +512,7 @@ extern int CIFSSMBLogoff(const unsigned int xid, struct cifs_ses *ses); · 511 unmodified lines | ||
| 512 | 512 | |
| 513 | 513 | extern struct cifs_ses *sesInfoAlloc(void); |
| 514 | 514 | extern void sesInfoFree(struct cifs_ses *); |
| 515 | −extern struct cifs_tcon *tconInfoAlloc(void); | |
| 515 | +extern struct cifs_tcon *tcon_info_alloc(bool dir_leases_enabled); | |
| 516 | 516 | extern void tconInfoFree(struct cifs_tcon *); |
| 517 | 517 | |
| 518 | 518 | extern int cifs_sign_rqst(struct smb_rqst *rqst, struct TCP_Server_Info *server, |
| @@ -1882,7 +1882,8 @@ cifs_setup_ipc(struct cifs_ses *ses, struct smb3_fs_context *ctx) · 1881 unmodified lines | ||
| 1882 | 1882 | } |
| 1883 | 1883 | } |
| 1884 | 1884 | |
| 1885 | − tcon = tconInfoAlloc(); | |
| 1885 | + /* no need to setup directory caching on IPC share, so pass in false */ | |
| 1886 | + tcon = tcon_info_alloc(false); | |
| 1886 | 1887 | if (tcon == NULL) |
| 1887 | 1888 | return -ENOMEM; |
| 1888 | 1889 | |
| @@ -2492,7 +2493,10 @@ cifs_get_tcon(struct cifs_ses *ses, struct smb3_fs_context *ctx) · 603 unmodified lines | ||
| 2492 | 2493 | goto out_fail; |
| 2493 | 2494 | } |
| 2494 | 2495 | |
| 2495 | − tcon = tconInfoAlloc(); | |
| 2496 | + if (ses->server->capabilities & SMB2_GLOBAL_CAP_DIRECTORY_LEASING) | |
| 2497 | + tcon = tcon_info_alloc(true); | |
| 2498 | + else | |
| 2499 | + tcon = tcon_info_alloc(false); | |
| 2496 | 2500 | if (tcon == NULL) { |
| 2497 | 2501 | rc = -ENOMEM; |
| 2498 | 2502 | goto out_fail; |
| @@ -1541,6 +1541,7 @@ static int smb3_fs_context_parse_param(struct fs_context *fc, · 1540 unmodified lines | ||
| 1541 | 1541 | |
| 1542 | 1542 | cifs_parse_mount_err: |
| 1543 | 1543 | kfree_sensitive(ctx->password); |
| 1544 | + ctx->password = NULL; | |
| 1544 | 1545 | return -EINVAL; |
| 1545 | 1546 | } |
| 1546 | 1547 | |
| @@ -113,18 +113,22 @@ sesInfoFree(struct cifs_ses *buf_to_free) · 112 unmodified lines | ||
| 113 | 113 | } |
| 114 | 114 | |
| 115 | 115 | struct cifs_tcon * |
| 116 | −tconInfoAlloc(void) | |
| 116 | +tcon_info_alloc(bool dir_leases_enabled) | |
| 117 | 117 | { |
| 118 | 118 | struct cifs_tcon *ret_buf; |
| 119 | 119 | |
| 120 | 120 | ret_buf = kzalloc(sizeof(*ret_buf), GFP_KERNEL); |
| 121 | 121 | if (!ret_buf) |
| 122 | 122 | return NULL; |
| 123 | − ret_buf->cfids = init_cached_dirs(); | |
| 124 | − if (!ret_buf->cfids) { | |
| 125 | − kfree(ret_buf); | |
| 126 | − return NULL; | |
| 123 | + | |
| 124 | + if (dir_leases_enabled == true) { | |
| 125 | + ret_buf->cfids = init_cached_dirs(); | |
| 126 | + if (!ret_buf->cfids) { | |
| 127 | + kfree(ret_buf); | |
| 128 | + return NULL; | |
| 129 | + } | |
| 127 | 130 | } |
| 131 | + /* else ret_buf->cfids is already set to NULL above */ | |
| 128 | 132 | |
| 129 | 133 | atomic_inc(&tconInfoAllocCount); |
| 130 | 134 | ret_buf->status = TID_NEW; |
| @@ -539,6 +539,9 @@ static int parse_create_response(struct cifs_open_info_data *data, · 538 unmodified lines | ||
| 539 | 539 | int rc = 0; |
| 540 | 540 | |
| 541 | 541 | switch (rsp->hdr.Status) { |
| 542 | + case STATUS_IO_REPARSE_TAG_NOT_HANDLED: | |
| 543 | + reparse_point = true; | |
| 544 | + break; | |
| 542 | 545 | case STATUS_STOPPED_ON_SYMLINK: |
| 543 | 546 | rc = smb2_parse_symlink_response(cifs_sb, iov, |
| 544 | 547 | &data->symlink_target); |
| @@ -877,8 +877,6 @@ static const struct status_to_posix_error smb2_error_map_table[] = { · 876 unmodified lines | ||
| 877 | 877 | "STATUS_IO_REPARSE_TAG_MISMATCH"}, |
| 878 | 878 | {STATUS_IO_REPARSE_DATA_INVALID, -EIO, |
| 879 | 879 | "STATUS_IO_REPARSE_DATA_INVALID"}, |
| 880 | − {STATUS_IO_REPARSE_TAG_NOT_HANDLED, -EIO, | |
| 881 | − "STATUS_IO_REPARSE_TAG_NOT_HANDLED"}, | |
| 882 | 880 | {STATUS_REPARSE_POINT_NOT_RESOLVED, -EIO, |
| 883 | 881 | "STATUS_REPARSE_POINT_NOT_RESOLVED"}, |
| 884 | 882 | {STATUS_DIRECTORY_IS_A_REPARSE_POINT, -EIO, |
| @@ -848,7 +848,7 @@ add_posix_context(struct kvec *iov, unsigned int *num_iovec, umode_t mode) · 847 unmodified lines | ||
| 848 | 848 | |
| 849 | 849 | iov[num].iov_base = create_posix_buf(mode); |
| 850 | 850 | if (mode == ACL_NO_MODE) |
| 851 | − cifs_dbg(FYI, "Invalid mode\n"); | |
| 851 | + cifs_dbg(FYI, "%s: no mode\n", __func__); | |
| 852 | 852 | if (iov[num].iov_base == NULL) |
| 853 | 853 | return -ENOMEM; |
| 854 | 854 | iov[num].iov_len = sizeof(struct create_posix); |
| @@ -3878,7 +3878,7 @@ void smb2_reconnect_server(struct work_struct *work) · 3023 unmodified lines | ||
| 3878 | 3878 | goto done; |
| 3879 | 3879 | |
| 3880 | 3880 | /* allocate a dummy tcon struct used for reconnect */ |
| 3881 | − tcon = tconInfoAlloc(); | |
| 3881 | + tcon = tcon_info_alloc(false); | |
| 3882 | 3882 | if (!tcon) { |
| 3883 | 3883 | resched = true; |
| 3884 | 3884 | list_for_each_entry_safe(ses, ses2, &tmp_ses_list, rlist) { |
| @@ -1401,10 +1401,13 @@ create_conn: · 1400 unmodified lines | ||
| 1401 | 1401 | server->smbd_conn = smbd_get_connection( |
| 1402 | 1402 | server, (struct sockaddr *) &server->dstaddr); |
| 1403 | 1403 | |
| 1404 | − if (server->smbd_conn) | |
| 1404 | + if (server->smbd_conn) { | |
| 1405 | 1405 | cifs_dbg(VFS, "RDMA transport re-established\n"); |
| 1406 | − | |
| 1407 | − return server->smbd_conn ? 0 : -ENOENT; | |
| 1406 | + trace_smb3_smbd_connect_done(server->hostname, server->conn_id, &server->dstaddr); | |
| 1407 | + return 0; | |
| 1408 | + } | |
| 1409 | + trace_smb3_smbd_connect_err(server->hostname, server->conn_id, &server->dstaddr); | |
| 1410 | + return -ENOENT; | |
| 1408 | 1411 | } |
| 1409 | 1412 | |
| 1410 | 1413 | static void destroy_caches_and_workqueue(struct smbd_connection *info) |
| @@ -935,6 +935,8 @@ DEFINE_EVENT(smb3_connect_class, smb3_##name, \ · 934 unmodified lines | ||
| 935 | 935 | TP_ARGS(hostname, conn_id, addr)) |
| 936 | 936 | |
| 937 | 937 | DEFINE_SMB3_CONNECT_EVENT(connect_done); |
| 938 | +DEFINE_SMB3_CONNECT_EVENT(smbd_connect_done); | |
| 939 | +DEFINE_SMB3_CONNECT_EVENT(smbd_connect_err); | |
| 938 | 940 | |
| 939 | 941 | DECLARE_EVENT_CLASS(smb3_connect_err_class, |
| 940 | 942 | TP_PROTO(char *hostname, __u64 conn_id, |
| @@ -35,6 +35,8 @@ · 34 unmodified lines | ||
| 35 | 35 | void |
| 36 | 36 | cifs_wake_up_task(struct mid_q_entry *mid) |
| 37 | 37 | { |
| 38 | + if (mid->mid_state == MID_RESPONSE_RECEIVED) | |
| 39 | + mid->mid_state = MID_RESPONSE_READY; | |
| 38 | 40 | wake_up_process(mid->callback_data); |
| 39 | 41 | } |
| 40 | 42 | |
| @@ -87,7 +89,8 @@ static void __release_mid(struct kref *refcount) · 46 unmodified lines | ||
| 87 | 89 | struct TCP_Server_Info *server = midEntry->server; |
| 88 | 90 | |
| 89 | 91 | if (midEntry->resp_buf && (midEntry->mid_flags & MID_WAIT_CANCELLED) && |
| 90 | − midEntry->mid_state == MID_RESPONSE_RECEIVED && | |
| 92 | + (midEntry->mid_state == MID_RESPONSE_RECEIVED || | |
| 93 | + midEntry->mid_state == MID_RESPONSE_READY) && | |
| 91 | 94 | server->ops->handle_cancelled_mid) |
| 92 | 95 | server->ops->handle_cancelled_mid(midEntry, server); |
| 93 | 96 | |
| @@ -737,7 +740,8 @@ wait_for_response(struct TCP_Server_Info *server, struct mid_q_entry *midQ) · 643 unmodified lines | ||
| 737 | 740 | int error; |
| 738 | 741 | |
| 739 | 742 | error = wait_event_state(server->response_q, |
| 740 | − midQ->mid_state != MID_REQUEST_SUBMITTED, | |
| 743 | + midQ->mid_state != MID_REQUEST_SUBMITTED && | |
| 744 | + midQ->mid_state != MID_RESPONSE_RECEIVED, | |
| 741 | 745 | (TASK_KILLABLE|TASK_FREEZABLE_UNSAFE)); |
| 742 | 746 | if (error < 0) |
| 743 | 747 | return -ERESTARTSYS; |
| @@ -890,7 +894,7 @@ cifs_sync_mid_result(struct mid_q_entry *mid, struct TCP_Server_Info *server) · 146 unmodified lines | ||
| 890 | 894 | |
| 891 | 895 | spin_lock(&server->mid_lock); |
| 892 | 896 | switch (mid->mid_state) { |
| 893 | − case MID_RESPONSE_RECEIVED: | |
| 897 | + case MID_RESPONSE_READY: | |
| 894 | 898 | spin_unlock(&server->mid_lock); |
| 895 | 899 | return rc; |
| 896 | 900 | case MID_RETRY_NEEDED: |
| @@ -989,6 +993,9 @@ cifs_compound_callback(struct mid_q_entry *mid) · 92 unmodified lines | ||
| 989 | 993 | credits.instance = server->reconnect_instance; |
| 990 | 994 | |
| 991 | 995 | add_credits(server, &credits, mid->optype); |
| 996 | + | |
| 997 | + if (mid->mid_state == MID_RESPONSE_RECEIVED) | |
| 998 | + mid->mid_state = MID_RESPONSE_READY; | |
| 992 | 999 | } |
| 993 | 1000 | |
| 994 | 1001 | static void |
| @@ -1209,7 +1216,8 @@ compound_send_recv(const unsigned int xid, struct cifs_ses *ses, · 214 unmodified lines | ||
| 1209 | 1216 | send_cancel(server, &rqst[i], midQ[i]); |
| 1210 | 1217 | spin_lock(&server->mid_lock); |
| 1211 | 1218 | midQ[i]->mid_flags |= MID_WAIT_CANCELLED; |
| 1212 | − if (midQ[i]->mid_state == MID_REQUEST_SUBMITTED) { | |
| 1219 | + if (midQ[i]->mid_state == MID_REQUEST_SUBMITTED || | |
| 1220 | + midQ[i]->mid_state == MID_RESPONSE_RECEIVED) { | |
| 1213 | 1221 | midQ[i]->callback = cifs_cancelled_callback; |
| 1214 | 1222 | cancelled_mid[i] = true; |
| 1215 | 1223 | credits[i].value = 0; |
| @@ -1230,7 +1238,7 @@ compound_send_recv(const unsigned int xid, struct cifs_ses *ses, · 14 unmodified lines | ||
| 1230 | 1238 | } |
| 1231 | 1239 | |
| 1232 | 1240 | if (!midQ[i]->resp_buf || |
| 1233 | − midQ[i]->mid_state != MID_RESPONSE_RECEIVED) { | |
| 1241 | + midQ[i]->mid_state != MID_RESPONSE_READY) { | |
| 1234 | 1242 | rc = -EIO; |
| 1235 | 1243 | cifs_dbg(FYI, "Bad MID state?\n"); |
| 1236 | 1244 | goto out; |
| @@ -1417,7 +1425,8 @@ SendReceive(const unsigned int xid, struct cifs_ses *ses, · 180 unmodified lines | ||
| 1417 | 1425 | if (rc != 0) { |
| 1418 | 1426 | send_cancel(server, &rqst, midQ); |
| 1419 | 1427 | spin_lock(&server->mid_lock); |
| 1420 | − if (midQ->mid_state == MID_REQUEST_SUBMITTED) { | |
| 1428 | + if (midQ->mid_state == MID_REQUEST_SUBMITTED || | |
| 1429 | + midQ->mid_state == MID_RESPONSE_RECEIVED) { | |
| 1421 | 1430 | /* no longer considered to be "in-flight" */ |
| 1422 | 1431 | midQ->callback = release_mid; |
| 1423 | 1432 | spin_unlock(&server->mid_lock); |
| @@ -1434,7 +1443,7 @@ SendReceive(const unsigned int xid, struct cifs_ses *ses, · 10 unmodified lines | ||
| 1434 | 1443 | } |
| 1435 | 1444 | |
| 1436 | 1445 | if (!midQ->resp_buf || !out_buf || |
| 1437 | − midQ->mid_state != MID_RESPONSE_RECEIVED) { | |
| 1446 | + midQ->mid_state != MID_RESPONSE_READY) { | |
| 1438 | 1447 | rc = -EIO; |
| 1439 | 1448 | cifs_server_dbg(VFS, "Bad MID state?\n"); |
| 1440 | 1449 | goto out; |
| @@ -1558,14 +1567,16 @@ SendReceiveBlockingLock(const unsigned int xid, struct cifs_tcon *tcon, · 117 unmodified lines | ||
| 1558 | 1567 | |
| 1559 | 1568 | /* Wait for a reply - allow signals to interrupt. */ |
| 1560 | 1569 | rc = wait_event_interruptible(server->response_q, |
| 1561 | − (!(midQ->mid_state == MID_REQUEST_SUBMITTED)) || | |
| 1570 | + (!(midQ->mid_state == MID_REQUEST_SUBMITTED || | |
| 1571 | + midQ->mid_state == MID_RESPONSE_RECEIVED)) || | |
| 1562 | 1572 | ((server->tcpStatus != CifsGood) && |
| 1563 | 1573 | (server->tcpStatus != CifsNew))); |
| 1564 | 1574 | |
| 1565 | 1575 | /* Were we interrupted by a signal ? */ |
| 1566 | 1576 | spin_lock(&server->srv_lock); |
| 1567 | 1577 | if ((rc == -ERESTARTSYS) && |
| 1568 | − (midQ->mid_state == MID_REQUEST_SUBMITTED) && | |
| 1578 | + (midQ->mid_state == MID_REQUEST_SUBMITTED || | |
| 1579 | + midQ->mid_state == MID_RESPONSE_RECEIVED) && | |
| 1569 | 1580 | ((server->tcpStatus == CifsGood) || |
| 1570 | 1581 | (server->tcpStatus == CifsNew))) { |
| 1571 | 1582 | spin_unlock(&server->srv_lock); |
| @@ -1596,7 +1607,8 @@ SendReceiveBlockingLock(const unsigned int xid, struct cifs_tcon *tcon, · 24 unmodified lines | ||
| 1596 | 1607 | if (rc) { |
| 1597 | 1608 | send_cancel(server, &rqst, midQ); |
| 1598 | 1609 | spin_lock(&server->mid_lock); |
| 1599 | − if (midQ->mid_state == MID_REQUEST_SUBMITTED) { | |
| 1610 | + if (midQ->mid_state == MID_REQUEST_SUBMITTED || | |
| 1611 | + midQ->mid_state == MID_RESPONSE_RECEIVED) { | |
| 1600 | 1612 | /* no longer considered to be "in-flight" */ |
| 1601 | 1613 | midQ->callback = release_mid; |
| 1602 | 1614 | spin_unlock(&server->mid_lock); |
| @@ -1616,7 +1628,7 @@ SendReceiveBlockingLock(const unsigned int xid, struct cifs_tcon *tcon, · 13 unmodified lines | ||
| 1616 | 1628 | return rc; |
| 1617 | 1629 | |
| 1618 | 1630 | /* rcvd frame is ok */ |
| 1619 | − if (out_buf == NULL || midQ->mid_state != MID_RESPONSE_RECEIVED) { | |
| 1631 | + if (out_buf == NULL || midQ->mid_state != MID_RESPONSE_READY) { | |
| 1620 | 1632 | rc = -EIO; |
| 1621 | 1633 | cifs_tcon_dbg(VFS, "Bad MID state?\n"); |
| 1622 | 1634 | goto out; |
| @@ -197,6 +197,9 @@ int ksmbd_conn_write(struct ksmbd_work *work) · 196 unmodified lines | ||
| 197 | 197 | if (work->send_no_response) |
| 198 | 198 | return 0; |
| 199 | 199 | |
| 200 | + if (!work->iov_idx) | |
| 201 | + return -EINVAL; | |
| 202 | + | |
| 200 | 203 | ksmbd_conn_lock(conn); |
| 201 | 204 | sent = conn->transport->ops->writev(conn->transport, work->iov, |
| 202 | 205 | work->iov_cnt, |
| @@ -115,8 +115,10 @@ static int __process_request(struct ksmbd_work *work, struct ksmbd_conn *conn, · 114 unmodified lines | ||
| 115 | 115 | if (check_conn_state(work)) |
| 116 | 116 | return SERVER_HANDLER_CONTINUE; |
| 117 | 117 | |
| 118 | − if (ksmbd_verify_smb_message(work)) | |
| 118 | + if (ksmbd_verify_smb_message(work)) { | |
| 119 | + conn->ops->set_rsp_status(work, STATUS_INVALID_PARAMETER); | |
| 119 | 120 | return SERVER_HANDLER_ABORT; |
| 121 | + } | |
| 120 | 122 | |
| 121 | 123 | command = conn->ops->get_cmd_val(work); |
| 122 | 124 | *cmd = command; |
| @@ -440,10 +440,8 @@ int ksmbd_smb2_check_message(struct ksmbd_work *work) · 439 unmodified lines | ||
| 440 | 440 | |
| 441 | 441 | validate_credit: |
| 442 | 442 | if ((work->conn->vals->capabilities & SMB2_GLOBAL_CAP_LARGE_MTU) && |
| 443 | − smb2_validate_credit_charge(work->conn, hdr)) { | |
| 444 | − work->conn->ops->set_rsp_status(work, STATUS_INVALID_PARAMETER); | |
| 443 | + smb2_validate_credit_charge(work->conn, hdr)) | |
| 445 | 444 | return 1; |
| 446 | − } | |
| 447 | 445 | |
| 448 | 446 | return 0; |
| 449 | 447 | } |
| @@ -70,6 +70,7 @@ static struct dentry *eventfs_root_lookup(struct inode *dir, · 69 unmodified lines | ||
| 70 | 70 | struct dentry *dentry, |
| 71 | 71 | unsigned int flags); |
| 72 | 72 | static int dcache_dir_open_wrapper(struct inode *inode, struct file *file); |
| 73 | +static int dcache_readdir_wrapper(struct file *file, struct dir_context *ctx); | |
| 73 | 74 | static int eventfs_release(struct inode *inode, struct file *file); |
| 74 | 75 | |
| 75 | 76 | static const struct inode_operations eventfs_root_dir_inode_operations = { |
| @@ -79,7 +80,7 @@ static const struct inode_operations eventfs_root_dir_inode_operations = { · 3 unmodified lines | ||
| 79 | 80 | static const struct file_operations eventfs_file_operations = { |
| 80 | 81 | .open = dcache_dir_open_wrapper, |
| 81 | 82 | .read = generic_read_dir, |
| 82 | − .iterate_shared = dcache_readdir, | |
| 83 | + .iterate_shared = dcache_readdir_wrapper, | |
| 83 | 84 | .llseek = generic_file_llseek, |
| 84 | 85 | .release = eventfs_release, |
| 85 | 86 | }; |
| @@ -396,6 +397,11 @@ static struct dentry *eventfs_root_lookup(struct inode *dir, · 310 unmodified lines | ||
| 396 | 397 | return ret; |
| 397 | 398 | } |
| 398 | 399 | |
| 400 | +struct dentry_list { | |
| 401 | + void *cursor; | |
| 402 | + struct dentry **dentries; | |
| 403 | +}; | |
| 404 | + | |
| 399 | 405 | /** |
| 400 | 406 | * eventfs_release - called to release eventfs file/dir |
| 401 | 407 | * @inode: inode to be released |
| @@ -404,26 +410,25 @@ static struct dentry *eventfs_root_lookup(struct inode *dir, · 2 unmodified lines | ||
| 404 | 410 | static int eventfs_release(struct inode *inode, struct file *file) |
| 405 | 411 | { |
| 406 | 412 | struct tracefs_inode *ti; |
| 407 | − struct eventfs_inode *ei; | |
| 408 | − struct eventfs_file *ef; | |
| 409 | − struct dentry *dentry; | |
| 410 | − int idx; | |
| 413 | + struct dentry_list *dlist = file->private_data; | |
| 414 | + void *cursor; | |
| 415 | + int i; | |
| 411 | 416 | |
| 412 | 417 | ti = get_tracefs(inode); |
| 413 | 418 | if (!(ti->flags & TRACEFS_EVENT_INODE)) |
| 414 | 419 | return -EINVAL; |
| 415 | 420 | |
| 416 | − ei = ti->private; | |
| 417 | − idx = srcu_read_lock(&eventfs_srcu); | |
| 418 | − list_for_each_entry_srcu(ef, &ei->e_top_files, list, | |
| 419 | − srcu_read_lock_held(&eventfs_srcu)) { | |
| 420 | − mutex_lock(&eventfs_mutex); | |
| 421 | − dentry = ef->dentry; | |
| 422 | − mutex_unlock(&eventfs_mutex); | |
| 423 | − if (dentry) | |
| 424 | − dput(dentry); | |
| 421 | + if (WARN_ON_ONCE(!dlist)) | |
| 422 | + return -EINVAL; | |
| 423 | + | |
| 424 | + for (i = 0; dlist->dentries && dlist->dentries[i]; i++) { | |
| 425 | + dput(dlist->dentries[i]); | |
| 425 | 426 | } |
| 426 | − srcu_read_unlock(&eventfs_srcu, idx); | |
| 427 | + | |
| 428 | + cursor = dlist->cursor; | |
| 429 | + kfree(dlist->dentries); | |
| 430 | + kfree(dlist); | |
| 431 | + file->private_data = cursor; | |
| 427 | 432 | return dcache_dir_close(inode, file); |
| 428 | 433 | } |
| 429 | 434 | |
| @@ -442,22 +447,70 @@ static int dcache_dir_open_wrapper(struct inode *inode, struct file *file) · 12 unmodified lines | ||
| 442 | 447 | struct tracefs_inode *ti; |
| 443 | 448 | struct eventfs_inode *ei; |
| 444 | 449 | struct eventfs_file *ef; |
| 450 | + struct dentry_list *dlist; | |
| 451 | + struct dentry **dentries = NULL; | |
| 445 | 452 | struct dentry *dentry = file_dentry(file); |
| 453 | + struct dentry *d; | |
| 446 | 454 | struct inode *f_inode = file_inode(file); |
| 455 | + int cnt = 0; | |
| 447 | 456 | int idx; |
| 457 | + int ret; | |
| 448 | 458 | |
| 449 | 459 | ti = get_tracefs(f_inode); |
| 450 | 460 | if (!(ti->flags & TRACEFS_EVENT_INODE)) |
| 451 | 461 | return -EINVAL; |
| 452 | 462 | |
| 463 | + if (WARN_ON_ONCE(file->private_data)) | |
| 464 | + return -EINVAL; | |
| 465 | + | |
| 466 | + dlist = kmalloc(sizeof(*dlist), GFP_KERNEL); | |
| 467 | + if (!dlist) | |
| 468 | + return -ENOMEM; | |
| 469 | + | |
| 453 | 470 | ei = ti->private; |
| 454 | 471 | idx = srcu_read_lock(&eventfs_srcu); |
| 455 | 472 | list_for_each_entry_srcu(ef, &ei->e_top_files, list, |
| 456 | 473 | srcu_read_lock_held(&eventfs_srcu)) { |
| 457 | − create_dentry(ef, dentry, false); | |
| 474 | + d = create_dentry(ef, dentry, false); | |
| 475 | + if (d) { | |
| 476 | + struct dentry **tmp; | |
| 477 | + | |
| 478 | + tmp = krealloc(dentries, sizeof(d) * (cnt + 2), GFP_KERNEL); | |
| 479 | + if (!tmp) | |
| 480 | + break; | |
| 481 | + tmp[cnt] = d; | |
| 482 | + tmp[cnt + 1] = NULL; | |
| 483 | + cnt++; | |
| 484 | + dentries = tmp; | |
| 485 | + } | |
| 458 | 486 | } |
| 459 | 487 | srcu_read_unlock(&eventfs_srcu, idx); |
| 460 | − return dcache_dir_open(inode, file); | |
| 488 | + ret = dcache_dir_open(inode, file); | |
| 489 | + | |
| 490 | + /* | |
| 491 | + * dcache_dir_open() sets file->private_data to a dentry cursor. | |
| 492 | + * Need to save that but also save all the dentries that were | |
| 493 | + * opened by this function. | |
| 494 | + */ | |
| 495 | + dlist->cursor = file->private_data; | |
| 496 | + dlist->dentries = dentries; | |
| 497 | + file->private_data = dlist; | |
| 498 | + return ret; | |
| 499 | +} | |
| 500 | + | |
| 501 | +/* | |
| 502 | + * This just sets the file->private_data back to the cursor and back. | |
| 503 | + */ | |
| 504 | +static int dcache_readdir_wrapper(struct file *file, struct dir_context *ctx) | |
| 505 | +{ | |
| 506 | + struct dentry_list *dlist = file->private_data; | |
| 507 | + int ret; | |
| 508 | + | |
| 509 | + file->private_data = dlist->cursor; | |
| 510 | + ret = dcache_readdir(file, ctx); | |
| 511 | + dlist->cursor = file->private_data; | |
| 512 | + file->private_data = dlist; | |
| 513 | + return ret; | |
| 461 | 514 | } |
| 462 | 515 | |
| 463 | 516 | /** |
| @@ -147,7 +147,7 @@ config XFS_ONLINE_SCRUB_STATS · 146 unmodified lines | ||
| 147 | 147 | bool "XFS online metadata check usage data collection" |
| 148 | 148 | default y |
| 149 | 149 | depends on XFS_ONLINE_SCRUB |
| 150 | − select FS_DEBUG | |
| 150 | + select XFS_DEBUG | |
| 151 | 151 | help |
| 152 | 152 | If you say Y here, the kernel will gather usage data about |
| 153 | 153 | the online metadata check subsystem. This includes the number |
| @@ -131,4 +131,26 @@ void xlog_check_buf_cancel_table(struct xlog *log); · 130 unmodified lines | ||
| 131 | 131 | #define xlog_check_buf_cancel_table(log) do { } while (0) |
| 132 | 132 | #endif |
| 133 | 133 | |
| 134 | +/* | |
| 135 | + * Transform a regular reservation into one suitable for recovery of a log | |
| 136 | + * intent item. | |
| 137 | + * | |
| 138 | + * Intent recovery only runs a single step of the transaction chain and defers | |
| 139 | + * the rest to a separate transaction. Therefore, we reduce logcount to 1 here | |
| 140 | + * to avoid livelocks if the log grant space is nearly exhausted due to the | |
| 141 | + * recovered intent pinning the tail. Keep the same logflags to avoid tripping | |
| 142 | + * asserts elsewhere. Struct copies abound below. | |
| 143 | + */ | |
| 144 | +static inline struct xfs_trans_res | |
| 145 | +xlog_recover_resv(const struct xfs_trans_res *r) | |
| 146 | +{ | |
| 147 | + struct xfs_trans_res ret = { | |
| 148 | + .tr_logres = r->tr_logres, | |
| 149 | + .tr_logcount = 1, | |
| 150 | + .tr_logflags = r->tr_logflags, | |
| 151 | + }; | |
| 152 | + | |
| 153 | + return ret; | |
| 154 | +} | |
| 155 | + | |
| 134 | 156 | #endif /* __XFS_LOG_RECOVER_H__ */ |
| @@ -266,7 +266,8 @@ xfs_validate_sb_write( · 265 unmodified lines | ||
| 266 | 266 | return -EFSCORRUPTED; |
| 267 | 267 | } |
| 268 | 268 | |
| 269 | − if (xfs_sb_has_ro_compat_feature(sbp, XFS_SB_FEAT_RO_COMPAT_UNKNOWN)) { | |
| 269 | + if (!xfs_is_readonly(mp) && | |
| 270 | + xfs_sb_has_ro_compat_feature(sbp, XFS_SB_FEAT_RO_COMPAT_UNKNOWN)) { | |
| 270 | 271 | xfs_alert(mp, |
| 271 | 272 | "Corruption detected in superblock read-only compatible features (0x%x)!", |
| 272 | 273 | (sbp->sb_features_ro_compat & |
| @@ -588,6 +588,8 @@ out_nofix: · 587 unmodified lines | ||
| 588 | 588 | out_teardown: |
| 589 | 589 | error = xchk_teardown(sc, error); |
| 590 | 590 | out_sc: |
| 591 | + if (error != -ENOENT) | |
| 592 | + xchk_stats_merge(mp, sm, &run); | |
| 591 | 593 | kfree(sc); |
| 592 | 594 | out: |
| 593 | 595 | trace_xchk_done(XFS_I(file_inode(file)), sm, error); |
| @@ -595,8 +597,6 @@ out: · 1 unmodified line | ||
| 595 | 597 | sm->sm_flags |= XFS_SCRUB_OFLAG_CORRUPT; |
| 596 | 598 | error = 0; |
| 597 | 599 | } |
| 598 | − if (error != -ENOENT) | |
| 599 | − xchk_stats_merge(mp, sm, &run); | |
| 600 | 600 | return error; |
| 601 | 601 | need_drain: |
| 602 | 602 | error = xchk_teardown(sc, 0); |
| @@ -185,7 +185,10 @@ xchk_stats_merge_one( · 184 unmodified lines | ||
| 185 | 185 | { |
| 186 | 186 | struct xchk_scrub_stats *css; |
| 187 | 187 | |
| 188 | − ASSERT(sm->sm_type < XFS_SCRUB_TYPE_NR); | |
| 188 | + if (sm->sm_type >= XFS_SCRUB_TYPE_NR) { | |
| 189 | + ASSERT(sm->sm_type < XFS_SCRUB_TYPE_NR); | |
| 190 | + return; | |
| 191 | + } | |
| 189 | 192 | |
| 190 | 193 | css = &cs->cs_stats[sm->sm_type]; |
| 191 | 194 | spin_lock(&css->css_lock); |
| @@ -333,7 +333,6 @@ xfs_attr_inactive( · 332 unmodified lines | ||
| 333 | 333 | int error = 0; |
| 334 | 334 | |
| 335 | 335 | mp = dp->i_mount; |
| 336 | − ASSERT(! XFS_NOT_DQATTACHED(mp, dp)); | |
| 337 | 336 | |
| 338 | 337 | xfs_ilock(dp, lock_mode); |
| 339 | 338 | if (!xfs_inode_has_attr_fork(dp)) |
| @@ -547,7 +547,7 @@ xfs_attri_item_recover( · 546 unmodified lines | ||
| 547 | 547 | struct xfs_inode *ip; |
| 548 | 548 | struct xfs_da_args *args; |
| 549 | 549 | struct xfs_trans *tp; |
| 550 | − struct xfs_trans_res tres; | |
| 550 | + struct xfs_trans_res resv; | |
| 551 | 551 | struct xfs_attri_log_format *attrp; |
| 552 | 552 | struct xfs_attri_log_nameval *nv = attrip->attri_nameval; |
| 553 | 553 | int error; |
| @@ -618,8 +618,9 @@ xfs_attri_item_recover( · 64 unmodified lines | ||
| 618 | 618 | goto out; |
| 619 | 619 | } |
| 620 | 620 | |
| 621 | − xfs_init_attr_trans(args, &tres, &total); | |
| 622 | − error = xfs_trans_alloc(mp, &tres, total, 0, XFS_TRANS_RESERVE, &tp); | |
| 621 | + xfs_init_attr_trans(args, &resv, &total); | |
| 622 | + resv = xlog_recover_resv(&resv); | |
| 623 | + error = xfs_trans_alloc(mp, &resv, total, 0, XFS_TRANS_RESERVE, &tp); | |
| 623 | 624 | if (error) |
| 624 | 625 | goto out; |
| 625 | 626 | |
| @@ -490,6 +490,7 @@ xfs_bui_item_recover( · 489 unmodified lines | ||
| 490 | 490 | struct list_head *capture_list) |
| 491 | 491 | { |
| 492 | 492 | struct xfs_bmap_intent fake = { }; |
| 493 | + struct xfs_trans_res resv; | |
| 493 | 494 | struct xfs_bui_log_item *buip = BUI_ITEM(lip); |
| 494 | 495 | struct xfs_trans *tp; |
| 495 | 496 | struct xfs_inode *ip = NULL; |
| @@ -515,7 +516,8 @@ xfs_bui_item_recover( · 19 unmodified lines | ||
| 515 | 516 | return error; |
| 516 | 517 | |
| 517 | 518 | /* Allocate transaction and do the work. */ |
| 518 | − error = xfs_trans_alloc(mp, &M_RES(mp)->tr_itruncate, | |
| 519 | + resv = xlog_recover_resv(&M_RES(mp)->tr_itruncate); | |
| 520 | + error = xfs_trans_alloc(mp, &resv, | |
| 519 | 521 | XFS_EXTENTADD_SPACE_RES(mp, XFS_DATA_FORK), 0, 0, &tp); |
| 520 | 522 | if (error) |
| 521 | 523 | goto err_rele; |
| @@ -146,6 +146,20 @@ xfs_nfs_get_inode( · 145 unmodified lines | ||
| 146 | 146 | return ERR_PTR(error); |
| 147 | 147 | } |
| 148 | 148 | |
| 149 | + /* | |
| 150 | + * Reload the incore unlinked list to avoid failure in inodegc. | |
| 151 | + * Use an unlocked check here because unrecovered unlinked inodes | |
| 152 | + * should be somewhat rare. | |
| 153 | + */ | |
| 154 | + if (xfs_inode_unlinked_incomplete(ip)) { | |
| 155 | + error = xfs_inode_reload_unlinked(ip); | |
| 156 | + if (error) { | |
| 157 | + xfs_force_shutdown(mp, SHUTDOWN_CORRUPT_INCORE); | |
| 158 | + xfs_irele(ip); | |
| 159 | + return ERR_PTR(error); | |
| 160 | + } | |
| 161 | + } | |
| 162 | + | |
| 149 | 163 | if (VFS_I(ip)->i_generation != generation) { |
| 150 | 164 | xfs_irele(ip); |
| 151 | 165 | return ERR_PTR(-ESTALE); |
| @@ -660,6 +660,7 @@ xfs_efi_item_recover( · 659 unmodified lines | ||
| 660 | 660 | struct xfs_log_item *lip, |
| 661 | 661 | struct list_head *capture_list) |
| 662 | 662 | { |
| 663 | + struct xfs_trans_res resv; | |
| 663 | 664 | struct xfs_efi_log_item *efip = EFI_ITEM(lip); |
| 664 | 665 | struct xfs_mount *mp = lip->li_log->l_mp; |
| 665 | 666 | struct xfs_efd_log_item *efdp; |
| @@ -683,7 +684,8 @@ xfs_efi_item_recover( · 17 unmodified lines | ||
| 683 | 684 | } |
| 684 | 685 | } |
| 685 | 686 | |
| 686 | − error = xfs_trans_alloc(mp, &M_RES(mp)->tr_itruncate, 0, 0, 0, &tp); | |
| 687 | + resv = xlog_recover_resv(&M_RES(mp)->tr_itruncate); | |
| 688 | + error = xfs_trans_alloc(mp, &resv, 0, 0, 0, &tp); | |
| 687 | 689 | if (error) |
| 688 | 690 | return error; |
| 689 | 691 | efdp = xfs_trans_get_efd(tp, efip, efip->efi_format.efi_nextents); |
| @@ -565,6 +565,19 @@ err: · 564 unmodified lines | ||
| 565 | 565 | } |
| 566 | 566 | #endif /* CONFIG_XFS_RT */ |
| 567 | 567 | |
| 568 | +static inline bool | |
| 569 | +rmap_not_shareable(struct xfs_mount *mp, const struct xfs_rmap_irec *r) | |
| 570 | +{ | |
| 571 | + if (!xfs_has_reflink(mp)) | |
| 572 | + return true; | |
| 573 | + if (XFS_RMAP_NON_INODE_OWNER(r->rm_owner)) | |
| 574 | + return true; | |
| 575 | + if (r->rm_flags & (XFS_RMAP_ATTR_FORK | XFS_RMAP_BMBT_BLOCK | | |
| 576 | + XFS_RMAP_UNWRITTEN)) | |
| 577 | + return true; | |
| 578 | + return false; | |
| 579 | +} | |
| 580 | + | |
| 568 | 581 | /* Execute a getfsmap query against the regular data device. */ |
| 569 | 582 | STATIC int |
| 570 | 583 | __xfs_getfsmap_datadev( |
| @@ -598,7 +611,6 @@ __xfs_getfsmap_datadev( · 27 unmodified lines | ||
| 598 | 611 | * low to the fsmap low key and max out the high key to the end |
| 599 | 612 | * of the AG. |
| 600 | 613 | */ |
| 601 | − info->low.rm_startblock = XFS_FSB_TO_AGBNO(mp, start_fsb); | |
| 602 | 614 | info->low.rm_offset = XFS_BB_TO_FSBT(mp, keys[0].fmr_offset); |
| 603 | 615 | error = xfs_fsmap_owner_to_rmap(&info->low, &keys[0]); |
| 604 | 616 | if (error) |
| @@ -608,12 +620,9 @@ __xfs_getfsmap_datadev( · 3 unmodified lines | ||
| 608 | 620 | |
| 609 | 621 | /* Adjust the low key if we are continuing from where we left off. */ |
| 610 | 622 | if (info->low.rm_blockcount == 0) { |
| 611 | − /* empty */ | |
| 612 | − } else if (XFS_RMAP_NON_INODE_OWNER(info->low.rm_owner) || | |
| 613 | − (info->low.rm_flags & (XFS_RMAP_ATTR_FORK | | |
| 614 | − XFS_RMAP_BMBT_BLOCK | | |
| 615 | − XFS_RMAP_UNWRITTEN))) { | |
| 616 | − info->low.rm_startblock += info->low.rm_blockcount; | |
| 623 | + /* No previous record from which to continue */ | |
| 624 | + } else if (rmap_not_shareable(mp, &info->low)) { | |
| 625 | + /* Last record seen was an unshareable extent */ | |
| 617 | 626 | info->low.rm_owner = 0; |
| 618 | 627 | info->low.rm_offset = 0; |
| 619 | 628 | |
| @@ -621,8 +630,10 @@ __xfs_getfsmap_datadev( · 1 unmodified line | ||
| 621 | 630 | if (XFS_FSB_TO_DADDR(mp, start_fsb) >= eofs) |
| 622 | 631 | return 0; |
| 623 | 632 | } else { |
| 633 | + /* Last record seen was a shareable file data extent */ | |
| 624 | 634 | info->low.rm_offset += info->low.rm_blockcount; |
| 625 | 635 | } |
| 636 | + info->low.rm_startblock = XFS_FSB_TO_AGBNO(mp, start_fsb); | |
| 626 | 637 | |
| 627 | 638 | info->high.rm_startblock = -1U; |
| 628 | 639 | info->high.rm_owner = ULLONG_MAX; |
| @@ -113,7 +113,7 @@ xfs_inode_alloc( · 112 unmodified lines | ||
| 113 | 113 | INIT_LIST_HEAD(&ip->i_ioend_list); |
| 114 | 114 | spin_lock_init(&ip->i_ioend_lock); |
| 115 | 115 | ip->i_next_unlinked = NULLAGINO; |
| 116 | − ip->i_prev_unlinked = NULLAGINO; | |
| 116 | + ip->i_prev_unlinked = 0; | |
| 117 | 117 | |
| 118 | 118 | return ip; |
| 119 | 119 | } |
| @@ -443,7 +443,7 @@ xfs_inodegc_queue_all( · 323 unmodified lines | ||
| 443 | 443 | int cpu; |
| 444 | 444 | bool ret = false; |
| 445 | 445 | |
| 446 | − for_each_online_cpu(cpu) { | |
| 446 | + for_each_cpu(cpu, &mp->m_inodegc_cpumask) { | |
| 447 | 447 | gc = per_cpu_ptr(mp->m_inodegc, cpu); |
| 448 | 448 | if (!llist_empty(&gc->list)) { |
| 449 | 449 | mod_delayed_work_on(cpu, mp->m_inodegc_wq, &gc->work, 0); |
| @@ -463,7 +463,7 @@ xfs_inodegc_wait_all( · 13 unmodified lines | ||
| 463 | 463 | int error = 0; |
| 464 | 464 | |
| 465 | 465 | flush_workqueue(mp->m_inodegc_wq); |
| 466 | − for_each_online_cpu(cpu) { | |
| 466 | + for_each_cpu(cpu, &mp->m_inodegc_cpumask) { | |
| 467 | 467 | struct xfs_inodegc *gc; |
| 468 | 468 | |
| 469 | 469 | gc = per_cpu_ptr(mp->m_inodegc, cpu); |
| @@ -1845,9 +1845,17 @@ xfs_inodegc_worker( · 1375 unmodified lines | ||
| 1845 | 1845 | struct xfs_inodegc, work); |
| 1846 | 1846 | struct llist_node *node = llist_del_all(&gc->list); |
| 1847 | 1847 | struct xfs_inode *ip, *n; |
| 1848 | + struct xfs_mount *mp = gc->mp; | |
| 1848 | 1849 | unsigned int nofs_flag; |
| 1849 | 1850 | |
| 1850 | − ASSERT(gc->cpu == smp_processor_id()); | |
| 1851 | + /* | |
| 1852 | + * Clear the cpu mask bit and ensure that we have seen the latest | |
| 1853 | + * update of the gc structure associated with this CPU. This matches | |
| 1854 | + * with the release semantics used when setting the cpumask bit in | |
| 1855 | + * xfs_inodegc_queue. | |
| 1856 | + */ | |
| 1857 | + cpumask_clear_cpu(gc->cpu, &mp->m_inodegc_cpumask); | |
| 1858 | + smp_mb__after_atomic(); | |
| 1851 | 1859 | |
| 1852 | 1860 | WRITE_ONCE(gc->items, 0); |
| 1853 | 1861 | |
| @@ -1862,7 +1870,7 @@ xfs_inodegc_worker( · 8 unmodified lines | ||
| 1862 | 1870 | nofs_flag = memalloc_nofs_save(); |
| 1863 | 1871 | |
| 1864 | 1872 | ip = llist_entry(node, struct xfs_inode, i_gclist); |
| 1865 | − trace_xfs_inodegc_worker(ip->i_mount, READ_ONCE(gc->shrinker_hits)); | |
| 1873 | + trace_xfs_inodegc_worker(mp, READ_ONCE(gc->shrinker_hits)); | |
| 1866 | 1874 | |
| 1867 | 1875 | WRITE_ONCE(gc->shrinker_hits, 0); |
| 1868 | 1876 | llist_for_each_entry_safe(ip, n, node, i_gclist) { |
| @@ -2057,6 +2065,7 @@ xfs_inodegc_queue( · 188 unmodified lines | ||
| 2057 | 2065 | struct xfs_inodegc *gc; |
| 2058 | 2066 | int items; |
| 2059 | 2067 | unsigned int shrinker_hits; |
| 2068 | + unsigned int cpu_nr; | |
| 2060 | 2069 | unsigned long queue_delay = 1; |
| 2061 | 2070 | |
| 2062 | 2071 | trace_xfs_inode_set_need_inactive(ip); |
| @@ -2064,18 +2073,28 @@ xfs_inodegc_queue( · 1 unmodified line | ||
| 2064 | 2073 | ip->i_flags |= XFS_NEED_INACTIVE; |
| 2065 | 2074 | spin_unlock(&ip->i_flags_lock); |
| 2066 | 2075 | |
| 2067 | − gc = get_cpu_ptr(mp->m_inodegc); | |
| 2076 | + cpu_nr = get_cpu(); | |
| 2077 | + gc = this_cpu_ptr(mp->m_inodegc); | |
| 2068 | 2078 | llist_add(&ip->i_gclist, &gc->list); |
| 2069 | 2079 | items = READ_ONCE(gc->items); |
| 2070 | 2080 | WRITE_ONCE(gc->items, items + 1); |
| 2071 | 2081 | shrinker_hits = READ_ONCE(gc->shrinker_hits); |
| 2072 | 2082 | |
| 2083 | + /* | |
| 2084 | + * Ensure the list add is always seen by anyone who finds the cpumask | |
| 2085 | + * bit set. This effectively gives the cpumask bit set operation | |
| 2086 | + * release ordering semantics. | |
| 2087 | + */ | |
| 2088 | + smp_mb__before_atomic(); | |
| 2089 | + if (!cpumask_test_cpu(cpu_nr, &mp->m_inodegc_cpumask)) | |
| 2090 | + cpumask_test_and_set_cpu(cpu_nr, &mp->m_inodegc_cpumask); | |
| 2091 | + | |
| 2073 | 2092 | /* |
| 2074 | 2093 | * We queue the work while holding the current CPU so that the work |
| 2075 | 2094 | * is scheduled to run on this CPU. |
| 2076 | 2095 | */ |
| 2077 | 2096 | if (!xfs_is_inodegc_enabled(mp)) { |
| 2078 | − put_cpu_ptr(gc); | |
| 2097 | + put_cpu(); | |
| 2079 | 2098 | return; |
| 2080 | 2099 | } |
| 2081 | 2100 | |
| @@ -2085,7 +2104,7 @@ xfs_inodegc_queue( · 3 unmodified lines | ||
| 2085 | 2104 | trace_xfs_inodegc_queue(mp, __return_address); |
| 2086 | 2105 | mod_delayed_work_on(current_cpu(), mp->m_inodegc_wq, &gc->work, |
| 2087 | 2106 | queue_delay); |
| 2088 | − put_cpu_ptr(gc); | |
| 2107 | + put_cpu(); | |
| 2089 | 2108 | |
| 2090 | 2109 | if (xfs_inodegc_want_flush_work(ip, items, shrinker_hits)) { |
| 2091 | 2110 | trace_xfs_inodegc_throttle(mp, __return_address); |
| @@ -2093,47 +2112,6 @@ xfs_inodegc_queue( · 1 unmodified line | ||
| 2093 | 2112 | } |
| 2094 | 2113 | } |
| 2095 | 2114 | |
| 2096 | −/* | |
| 2097 | − * Fold the dead CPU inodegc queue into the current CPUs queue. | |
| 2098 | − */ | |
| 2099 | −void | |
| 2100 | −xfs_inodegc_cpu_dead( | |
| 2101 | − struct xfs_mount *mp, | |
| 2102 | − unsigned int dead_cpu) | |
| 2103 | −{ | |
| 2104 | − struct xfs_inodegc *dead_gc, *gc; | |
| 2105 | − struct llist_node *first, *last; | |
| 2106 | − unsigned int count = 0; | |
| 2107 | − | |
| 2108 | − dead_gc = per_cpu_ptr(mp->m_inodegc, dead_cpu); | |
| 2109 | − cancel_delayed_work_sync(&dead_gc->work); | |
| 2110 | − | |
| 2111 | − if (llist_empty(&dead_gc->list)) | |
| 2112 | − return; | |
| 2113 | − | |
| 2114 | − first = dead_gc->list.first; | |
| 2115 | − last = first; | |
| 2116 | − while (last->next) { | |
| 2117 | − last = last->next; | |
| 2118 | − count++; | |
| 2119 | − } | |
| 2120 | − dead_gc->list.first = NULL; | |
| 2121 | − dead_gc->items = 0; | |
| 2122 | − | |
| 2123 | − /* Add pending work to current CPU */ | |
| 2124 | − gc = get_cpu_ptr(mp->m_inodegc); | |
| 2125 | − llist_add_batch(first, last, &gc->list); | |
| 2126 | − count += READ_ONCE(gc->items); | |
| 2127 | − WRITE_ONCE(gc->items, count); | |
| 2128 | − | |
| 2129 | − if (xfs_is_inodegc_enabled(mp)) { | |
| 2130 | − trace_xfs_inodegc_queue(mp, __return_address); | |
| 2131 | − mod_delayed_work_on(current_cpu(), mp->m_inodegc_wq, &gc->work, | |
| 2132 | − 0); | |
| 2133 | − } | |
| 2134 | − put_cpu_ptr(gc); | |
| 2135 | −} | |
| 2136 | − | |
| 2137 | 2115 | /* |
| 2138 | 2116 | * We set the inode flag atomically with the radix tree tag. Once we get tag |
| 2139 | 2117 | * lookups on the radix tree, this inode flag can go away. |
| @@ -2195,7 +2173,7 @@ xfs_inodegc_shrinker_count( · 55 unmodified lines | ||
| 2195 | 2173 | if (!xfs_is_inodegc_enabled(mp)) |
| 2196 | 2174 | return 0; |
| 2197 | 2175 | |
| 2198 | − for_each_online_cpu(cpu) { | |
| 2176 | + for_each_cpu(cpu, &mp->m_inodegc_cpumask) { | |
| 2199 | 2177 | gc = per_cpu_ptr(mp->m_inodegc, cpu); |
| 2200 | 2178 | if (!llist_empty(&gc->list)) |
| 2201 | 2179 | return XFS_INODEGC_SHRINKER_COUNT; |
| @@ -2220,7 +2198,7 @@ xfs_inodegc_shrinker_scan( · 18 unmodified lines | ||
| 2220 | 2198 | |
| 2221 | 2199 | trace_xfs_inodegc_shrinker_scan(mp, sc, __return_address); |
| 2222 | 2200 | |
| 2223 | − for_each_online_cpu(cpu) { | |
| 2201 | + for_each_cpu(cpu, &mp->m_inodegc_cpumask) { | |
| 2224 | 2202 | gc = per_cpu_ptr(mp->m_inodegc, cpu); |
| 2225 | 2203 | if (!llist_empty(&gc->list)) { |
| 2226 | 2204 | unsigned int h = READ_ONCE(gc->shrinker_hits); |
| @@ -79,7 +79,6 @@ void xfs_inodegc_push(struct xfs_mount *mp); · 78 unmodified lines | ||
| 79 | 79 | int xfs_inodegc_flush(struct xfs_mount *mp); |
| 80 | 80 | void xfs_inodegc_stop(struct xfs_mount *mp); |
| 81 | 81 | void xfs_inodegc_start(struct xfs_mount *mp); |
| 82 | −void xfs_inodegc_cpu_dead(struct xfs_mount *mp, unsigned int cpu); | |
| 83 | 82 | int xfs_inodegc_register_shrinker(struct xfs_mount *mp); |
| 84 | 83 | |
| 85 | 84 | #endif |
| @@ -1642,8 +1642,11 @@ xfs_inode_needs_inactive( · 1641 unmodified lines | ||
| 1642 | 1642 | if (VFS_I(ip)->i_mode == 0) |
| 1643 | 1643 | return false; |
| 1644 | 1644 | |
| 1645 | − /* If this is a read-only mount, don't do this (would generate I/O) */ | |
| 1646 | − if (xfs_is_readonly(mp)) | |
| 1645 | + /* | |
| 1646 | + * If this is a read-only mount, don't do this (would generate I/O) | |
| 1647 | + * unless we're in log recovery and cleaning the iunlinked list. | |
| 1648 | + */ | |
| 1649 | + if (xfs_is_readonly(mp) && !xlog_recovery_needed(mp->m_log)) | |
| 1647 | 1650 | return false; |
| 1648 | 1651 | |
| 1649 | 1652 | /* If the log isn't running, push inodes straight to reclaim. */ |
| @@ -1703,8 +1706,11 @@ xfs_inactive( · 53 unmodified lines | ||
| 1703 | 1706 | mp = ip->i_mount; |
| 1704 | 1707 | ASSERT(!xfs_iflags_test(ip, XFS_IRECOVERY)); |
| 1705 | 1708 | |
| 1706 | − /* If this is a read-only mount, don't do this (would generate I/O) */ | |
| 1707 | − if (xfs_is_readonly(mp)) | |
| 1709 | + /* | |
| 1710 | + * If this is a read-only mount, don't do this (would generate I/O) | |
| 1711 | + * unless we're in log recovery and cleaning the iunlinked list. | |
| 1712 | + */ | |
| 1713 | + if (xfs_is_readonly(mp) && !xlog_recovery_needed(mp->m_log)) | |
| 1708 | 1714 | goto out; |
| 1709 | 1715 | |
| 1710 | 1716 | /* Metadata inodes require explicit resource cleanup. */ |
| @@ -1736,9 +1742,21 @@ xfs_inactive( · 25 unmodified lines | ||
| 1736 | 1742 | ip->i_df.if_nextents > 0 || ip->i_delayed_blks > 0)) |
| 1737 | 1743 | truncate = 1; |
| 1738 | 1744 | |
| 1739 | − error = xfs_qm_dqattach(ip); | |
| 1740 | − if (error) | |
| 1741 | − goto out; | |
| 1745 | + if (xfs_iflags_test(ip, XFS_IQUOTAUNCHECKED)) { | |
| 1746 | + /* | |
| 1747 | + * If this inode is being inactivated during a quotacheck and | |
| 1748 | + * has not yet been scanned by quotacheck, we /must/ remove | |
| 1749 | + * the dquots from the inode before inactivation changes the | |
| 1750 | + * block and inode counts. Most probably this is a result of | |
| 1751 | + * reloading the incore iunlinked list to purge unrecovered | |
| 1752 | + * unlinked inodes. | |
| 1753 | + */ | |
| 1754 | + xfs_qm_dqdetach(ip); | |
| 1755 | + } else { | |
| 1756 | + error = xfs_qm_dqattach(ip); | |
| 1757 | + if (error) | |
| 1758 | + goto out; | |
| 1759 | + } | |
| 1742 | 1760 | |
| 1743 | 1761 | if (S_ISLNK(VFS_I(ip)->i_mode)) |
| 1744 | 1762 | error = xfs_inactive_symlink(ip); |
| @@ -1822,12 +1840,17 @@ xfs_iunlink_lookup( · 77 unmodified lines | ||
| 1822 | 1840 | |
| 1823 | 1841 | rcu_read_lock(); |
| 1824 | 1842 | ip = radix_tree_lookup(&pag->pag_ici_root, agino); |
| 1843 | + if (!ip) { | |
| 1844 | + /* Caller can handle inode not being in memory. */ | |
| 1845 | + rcu_read_unlock(); | |
| 1846 | + return NULL; | |
| 1847 | + } | |
| 1825 | 1848 | |
| 1826 | 1849 | /* |
| 1827 | − * Inode not in memory or in RCU freeing limbo should not happen. | |
| 1828 | − * Warn about this and let the caller handle the failure. | |
| 1850 | + * Inode in RCU freeing limbo should not happen. Warn about this and | |
| 1851 | + * let the caller handle the failure. | |
| 1829 | 1852 | */ |
| 1830 | − if (WARN_ON_ONCE(!ip || !ip->i_ino)) { | |
| 1853 | + if (WARN_ON_ONCE(!ip->i_ino)) { | |
| 1831 | 1854 | rcu_read_unlock(); |
| 1832 | 1855 | return NULL; |
| 1833 | 1856 | } |
| @@ -1836,7 +1859,10 @@ xfs_iunlink_lookup( · 2 unmodified lines | ||
| 1836 | 1859 | return ip; |
| 1837 | 1860 | } |
| 1838 | 1861 | |
| 1839 | −/* Update the prev pointer of the next agino. */ | |
| 1862 | +/* | |
| 1863 | + * Update the prev pointer of the next agino. Returns -ENOLINK if the inode | |
| 1864 | + * is not in cache. | |
| 1865 | + */ | |
| 1840 | 1866 | static int |
| 1841 | 1867 | xfs_iunlink_update_backref( |
| 1842 | 1868 | struct xfs_perag *pag, |
| @@ -1851,7 +1877,8 @@ xfs_iunlink_update_backref( · 8 unmodified lines | ||
| 1851 | 1877 | |
| 1852 | 1878 | ip = xfs_iunlink_lookup(pag, next_agino); |
| 1853 | 1879 | if (!ip) |
| 1854 | − return -EFSCORRUPTED; | |
| 1880 | + return -ENOLINK; | |
| 1881 | + | |
| 1855 | 1882 | ip->i_prev_unlinked = prev_agino; |
| 1856 | 1883 | return 0; |
| 1857 | 1884 | } |
| @@ -1895,6 +1922,64 @@ xfs_iunlink_update_bucket( · 37 unmodified lines | ||
| 1895 | 1922 | return 0; |
| 1896 | 1923 | } |
| 1897 | 1924 | |
| 1925 | +/* | |
| 1926 | + * Load the inode @next_agino into the cache and set its prev_unlinked pointer | |
| 1927 | + * to @prev_agino. Caller must hold the AGI to synchronize with other changes | |
| 1928 | + * to the unlinked list. | |
| 1929 | + */ | |
| 1930 | +STATIC int | |
| 1931 | +xfs_iunlink_reload_next( | |
| 1932 | + struct xfs_trans *tp, | |
| 1933 | + struct xfs_buf *agibp, | |
| 1934 | + xfs_agino_t prev_agino, | |
| 1935 | + xfs_agino_t next_agino) | |
| 1936 | +{ | |
| 1937 | + struct xfs_perag *pag = agibp->b_pag; | |
| 1938 | + struct xfs_mount *mp = pag->pag_mount; | |
| 1939 | + struct xfs_inode *next_ip = NULL; | |
| 1940 | + xfs_ino_t ino; | |
| 1941 | + int error; | |
| 1942 | + | |
| 1943 | + ASSERT(next_agino != NULLAGINO); | |
| 1944 | + | |
| 1945 | +#ifdef DEBUG | |
| 1946 | + rcu_read_lock(); | |
| 1947 | + next_ip = radix_tree_lookup(&pag->pag_ici_root, next_agino); | |
| 1948 | + ASSERT(next_ip == NULL); | |
| 1949 | + rcu_read_unlock(); | |
| 1950 | +#endif | |
| 1951 | + | |
| 1952 | + xfs_info_ratelimited(mp, | |
| 1953 | + "Found unrecovered unlinked inode 0x%x in AG 0x%x. Initiating recovery.", | |
| 1954 | + next_agino, pag->pag_agno); | |
| 1955 | + | |
| 1956 | + /* | |
| 1957 | + * Use an untrusted lookup just to be cautious in case the AGI has been | |
| 1958 | + * corrupted and now points at a free inode. That shouldn't happen, | |
| 1959 | + * but we'd rather shut down now since we're already running in a weird | |
| 1960 | + * situation. | |
| 1961 | + */ | |
| 1962 | + ino = XFS_AGINO_TO_INO(mp, pag->pag_agno, next_agino); | |
| 1963 | + error = xfs_iget(mp, tp, ino, XFS_IGET_UNTRUSTED, 0, &next_ip); | |
| 1964 | + if (error) | |
| 1965 | + return error; | |
| 1966 | + | |
| 1967 | + /* If this is not an unlinked inode, something is very wrong. */ | |
| 1968 | + if (VFS_I(next_ip)->i_nlink != 0) { | |
| 1969 | + error = -EFSCORRUPTED; | |
| 1970 | + goto rele; | |
| 1971 | + } | |
| 1972 | + | |
| 1973 | + next_ip->i_prev_unlinked = prev_agino; | |
| 1974 | + trace_xfs_iunlink_reload_next(next_ip); | |
| 1975 | +rele: | |
| 1976 | + ASSERT(!(VFS_I(next_ip)->i_state & I_DONTCACHE)); | |
| 1977 | + if (xfs_is_quotacheck_running(mp) && next_ip) | |
| 1978 | + xfs_iflags_set(next_ip, XFS_IQUOTAUNCHECKED); | |
| 1979 | + xfs_irele(next_ip); | |
| 1980 | + return error; | |
| 1981 | +} | |
| 1982 | + | |
| 1898 | 1983 | static int |
| 1899 | 1984 | xfs_iunlink_insert_inode( |
| 1900 | 1985 | struct xfs_trans *tp, |
| @@ -1926,6 +2011,8 @@ xfs_iunlink_insert_inode( · 25 unmodified lines | ||
| 1926 | 2011 | * inode. |
| 1927 | 2012 | */ |
| 1928 | 2013 | error = xfs_iunlink_update_backref(pag, agino, next_agino); |
| 2014 | + if (error == -ENOLINK) | |
| 2015 | + error = xfs_iunlink_reload_next(tp, agibp, agino, next_agino); | |
| 1929 | 2016 | if (error) |
| 1930 | 2017 | return error; |
| 1931 | 2018 | |
| @@ -1941,6 +2028,7 @@ xfs_iunlink_insert_inode( · 9 unmodified lines | ||
| 1941 | 2028 | } |
| 1942 | 2029 | |
| 1943 | 2030 | /* Point the head of the list to point to this inode. */ |
| 2031 | + ip->i_prev_unlinked = NULLAGINO; | |
| 1944 | 2032 | return xfs_iunlink_update_bucket(tp, pag, agibp, bucket_index, agino); |
| 1945 | 2033 | } |
| 1946 | 2034 | |
| @@ -2020,6 +2108,9 @@ xfs_iunlink_remove_inode( · 73 unmodified lines | ||
| 2020 | 2108 | */ |
| 2021 | 2109 | error = xfs_iunlink_update_backref(pag, ip->i_prev_unlinked, |
| 2022 | 2110 | ip->i_next_unlinked); |
| 2111 | + if (error == -ENOLINK) | |
| 2112 | + error = xfs_iunlink_reload_next(tp, agibp, ip->i_prev_unlinked, | |
| 2113 | + ip->i_next_unlinked); | |
| 2023 | 2114 | if (error) |
| 2024 | 2115 | return error; |
| 2025 | 2116 | |
| @@ -2040,7 +2131,7 @@ xfs_iunlink_remove_inode( · 14 unmodified lines | ||
| 2040 | 2131 | } |
| 2041 | 2132 | |
| 2042 | 2133 | ip->i_next_unlinked = NULLAGINO; |
| 2043 | − ip->i_prev_unlinked = NULLAGINO; | |
| 2134 | + ip->i_prev_unlinked = 0; | |
| 2044 | 2135 | return error; |
| 2045 | 2136 | } |
| 2046 | 2137 | |
| @@ -3529,3 +3620,117 @@ xfs_iunlock2_io_mmap( · 1482 unmodified lines | ||
| 3529 | 3620 | if (ip1 != ip2) |
| 3530 | 3621 | inode_unlock(VFS_I(ip1)); |
| 3531 | 3622 | } |
| 3623 | + | |
| 3624 | +/* | |
| 3625 | + * Reload the incore inode list for this inode. Caller should ensure that | |
| 3626 | + * the link count cannot change, either by taking ILOCK_SHARED or otherwise | |
| 3627 | + * preventing other threads from executing. | |
| 3628 | + */ | |
| 3629 | +int | |
| 3630 | +xfs_inode_reload_unlinked_bucket( | |
| 3631 | + struct xfs_trans *tp, | |
| 3632 | + struct xfs_inode *ip) | |
| 3633 | +{ | |
| 3634 | + struct xfs_mount *mp = tp->t_mountp; | |
| 3635 | + struct xfs_buf *agibp; | |
| 3636 | + struct xfs_agi *agi; | |
| 3637 | + struct xfs_perag *pag; | |
| 3638 | + xfs_agnumber_t agno = XFS_INO_TO_AGNO(mp, ip->i_ino); | |
| 3639 | + xfs_agino_t agino = XFS_INO_TO_AGINO(mp, ip->i_ino); | |
| 3640 | + xfs_agino_t prev_agino, next_agino; | |
| 3641 | + unsigned int bucket; | |
| 3642 | + bool foundit = false; | |
| 3643 | + int error; | |
| 3644 | + | |
| 3645 | + /* Grab the first inode in the list */ | |
| 3646 | + pag = xfs_perag_get(mp, agno); | |
| 3647 | + error = xfs_ialloc_read_agi(pag, tp, &agibp); | |
| 3648 | + xfs_perag_put(pag); | |
| 3649 | + if (error) | |
| 3650 | + return error; | |
| 3651 | + | |
| 3652 | + /* | |
| 3653 | + * We've taken ILOCK_SHARED and the AGI buffer lock to stabilize the | |
| 3654 | + * incore unlinked list pointers for this inode. Check once more to | |
| 3655 | + * see if we raced with anyone else to reload the unlinked list. | |
| 3656 | + */ | |
| 3657 | + if (!xfs_inode_unlinked_incomplete(ip)) { | |
| 3658 | + foundit = true; | |
| 3659 | + goto out_agibp; | |
| 3660 | + } | |
| 3661 | + | |
| 3662 | + bucket = agino % XFS_AGI_UNLINKED_BUCKETS; | |
| 3663 | + agi = agibp->b_addr; | |
| 3664 | + | |
| 3665 | + trace_xfs_inode_reload_unlinked_bucket(ip); | |
| 3666 | + | |
| 3667 | + xfs_info_ratelimited(mp, | |
| 3668 | + "Found unrecovered unlinked inode 0x%x in AG 0x%x. Initiating list recovery.", | |
| 3669 | + agino, agno); | |
| 3670 | + | |
| 3671 | + prev_agino = NULLAGINO; | |
| 3672 | + next_agino = be32_to_cpu(agi->agi_unlinked[bucket]); | |
| 3673 | + while (next_agino != NULLAGINO) { | |
| 3674 | + struct xfs_inode *next_ip = NULL; | |
| 3675 | + | |
| 3676 | + /* Found this caller's inode, set its backlink. */ | |
| 3677 | + if (next_agino == agino) { | |
| 3678 | + next_ip = ip; | |
| 3679 | + next_ip->i_prev_unlinked = prev_agino; | |
| 3680 | + foundit = true; | |
| 3681 | + goto next_inode; | |
| 3682 | + } | |
| 3683 | + | |
| 3684 | + /* Try in-memory lookup first. */ | |
| 3685 | + next_ip = xfs_iunlink_lookup(pag, next_agino); | |
| 3686 | + if (next_ip) | |
| 3687 | + goto next_inode; | |
| 3688 | + | |
| 3689 | + /* Inode not in memory, try reloading it. */ | |
| 3690 | + error = xfs_iunlink_reload_next(tp, agibp, prev_agino, | |
| 3691 | + next_agino); | |
| 3692 | + if (error) | |
| 3693 | + break; | |
| 3694 | + | |
| 3695 | + /* Grab the reloaded inode. */ | |
| 3696 | + next_ip = xfs_iunlink_lookup(pag, next_agino); | |
| 3697 | + if (!next_ip) { | |
| 3698 | + /* No incore inode at all? We reloaded it... */ | |
| 3699 | + ASSERT(next_ip != NULL); | |
| 3700 | + error = -EFSCORRUPTED; | |
| 3701 | + break; | |
| 3702 | + } | |
| 3703 | + | |
| 3704 | +next_inode: | |
| 3705 | + prev_agino = next_agino; | |
| 3706 | + next_agino = next_ip->i_next_unlinked; | |
| 3707 | + } | |
| 3708 | + | |
| 3709 | +out_agibp: | |
| 3710 | + xfs_trans_brelse(tp, agibp); | |
| 3711 | + /* Should have found this inode somewhere in the iunlinked bucket. */ | |
| 3712 | + if (!error && !foundit) | |
| 3713 | + error = -EFSCORRUPTED; | |
| 3714 | + return error; | |
| 3715 | +} | |
| 3716 | + | |
| 3717 | +/* Decide if this inode is missing its unlinked list and reload it. */ | |
| 3718 | +int | |
| 3719 | +xfs_inode_reload_unlinked( | |
| 3720 | + struct xfs_inode *ip) | |
| 3721 | +{ | |
| 3722 | + struct xfs_trans *tp; | |
| 3723 | + int error; | |
| 3724 | + | |
| 3725 | + error = xfs_trans_alloc_empty(ip->i_mount, &tp); | |
| 3726 | + if (error) | |
| 3727 | + return error; | |
| 3728 | + | |
| 3729 | + xfs_ilock(ip, XFS_ILOCK_SHARED); | |
| 3730 | + if (xfs_inode_unlinked_incomplete(ip)) | |
| 3731 | + error = xfs_inode_reload_unlinked_bucket(tp, ip); | |
| 3732 | + xfs_iunlock(ip, XFS_ILOCK_SHARED); | |
| 3733 | + xfs_trans_cancel(tp); | |
| 3734 | + | |
| 3735 | + return error; | |
| 3736 | +} | |
| @@ -68,8 +68,21 @@ typedef struct xfs_inode { · 67 unmodified lines | ||
| 68 | 68 | uint64_t i_diflags2; /* XFS_DIFLAG2_... */ |
| 69 | 69 | struct timespec64 i_crtime; /* time created */ |
| 70 | 70 | |
| 71 | − /* unlinked list pointers */ | |
| 71 | + /* | |
| 72 | + * Unlinked list pointers. These point to the next and previous inodes | |
| 73 | + * in the AGI unlinked bucket list, respectively. These fields can | |
| 74 | + * only be updated with the AGI locked. | |
| 75 | + * | |
| 76 | + * i_next_unlinked caches di_next_unlinked. | |
| 77 | + */ | |
| 72 | 78 | xfs_agino_t i_next_unlinked; |
| 79 | + | |
| 80 | + /* | |
| 81 | + * If the inode is not on an unlinked list, this field is zero. If the | |
| 82 | + * inode is the first element in an unlinked list, this field is | |
| 83 | + * NULLAGINO. Otherwise, i_prev_unlinked points to the previous inode | |
| 84 | + * in the unlinked list. | |
| 85 | + */ | |
| 73 | 86 | xfs_agino_t i_prev_unlinked; |
| 74 | 87 | |
| 75 | 88 | /* VFS inode */ |
| @@ -81,6 +94,11 @@ typedef struct xfs_inode { · 5 unmodified lines | ||
| 81 | 94 | struct list_head i_ioend_list; |
| 82 | 95 | } xfs_inode_t; |
| 83 | 96 | |
| 97 | +static inline bool xfs_inode_on_unlinked_list(const struct xfs_inode *ip) | |
| 98 | +{ | |
| 99 | + return ip->i_prev_unlinked != 0; | |
| 100 | +} | |
| 101 | + | |
| 84 | 102 | static inline bool xfs_inode_has_attr_fork(struct xfs_inode *ip) |
| 85 | 103 | { |
| 86 | 104 | return ip->i_forkoff > 0; |
| @@ -326,6 +344,9 @@ static inline bool xfs_inode_has_large_extent_counts(struct xfs_inode *ip) · 239 unmodified lines | ||
| 326 | 344 | */ |
| 327 | 345 | #define XFS_INACTIVATING (1 << 13) |
| 328 | 346 | |
| 347 | +/* Quotacheck is running but inode has not been added to quota counts. */ | |
| 348 | +#define XFS_IQUOTAUNCHECKED (1 << 14) | |
| 349 | + | |
| 329 | 350 | /* All inode state flags related to inode reclaim. */ |
| 330 | 351 | #define XFS_ALL_IRECLAIM_FLAGS (XFS_IRECLAIMABLE | \ |
| 331 | 352 | XFS_IRECLAIM | \ |
| @@ -340,7 +361,7 @@ static inline bool xfs_inode_has_large_extent_counts(struct xfs_inode *ip) · 8 unmodified lines | ||
| 340 | 361 | #define XFS_IRECLAIM_RESET_FLAGS \ |
| 341 | 362 | (XFS_IRECLAIMABLE | XFS_IRECLAIM | \ |
| 342 | 363 | XFS_IDIRTY_RELEASE | XFS_ITRUNCATED | XFS_NEED_INACTIVE | \ |
| 343 | − XFS_INACTIVATING) | |
| 364 | + XFS_INACTIVATING | XFS_IQUOTAUNCHECKED) | |
| 344 | 365 | |
| 345 | 366 | /* |
| 346 | 367 | * Flags for inode locking. |
| @@ -575,4 +596,13 @@ void xfs_end_io(struct work_struct *work); · 228 unmodified lines | ||
| 575 | 596 | int xfs_ilock2_io_mmap(struct xfs_inode *ip1, struct xfs_inode *ip2); |
| 576 | 597 | void xfs_iunlock2_io_mmap(struct xfs_inode *ip1, struct xfs_inode *ip2); |
| 577 | 598 | |
| 599 | +static inline bool | |
| 600 | +xfs_inode_unlinked_incomplete( | |
| 601 | + struct xfs_inode *ip) | |
| 602 | +{ | |
| 603 | + return VFS_I(ip)->i_nlink == 0 && !xfs_inode_on_unlinked_list(ip); | |
| 604 | +} | |
| 605 | +int xfs_inode_reload_unlinked_bucket(struct xfs_trans *tp, struct xfs_inode *ip); | |
| 606 | +int xfs_inode_reload_unlinked(struct xfs_inode *ip); | |
| 607 | + | |
| 578 | 608 | #endif /* __XFS_INODE_H__ */ |
| @@ -80,6 +80,17 @@ xfs_bulkstat_one_int( · 79 unmodified lines | ||
| 80 | 80 | if (error) |
| 81 | 81 | goto out; |
| 82 | 82 | |
| 83 | + /* Reload the incore unlinked list to avoid failure in inodegc. */ | |
| 84 | + if (xfs_inode_unlinked_incomplete(ip)) { | |
| 85 | + error = xfs_inode_reload_unlinked_bucket(tp, ip); | |
| 86 | + if (error) { | |
| 87 | + xfs_iunlock(ip, XFS_ILOCK_SHARED); | |
| 88 | + xfs_force_shutdown(mp, SHUTDOWN_CORRUPT_INCORE); | |
| 89 | + xfs_irele(ip); | |
| 90 | + return error; | |
| 91 | + } | |
| 92 | + } | |
| 93 | + | |
| 83 | 94 | ASSERT(ip != NULL); |
| 84 | 95 | ASSERT(ip->i_imap.im_blkno != 0); |
| 85 | 96 | inode = VFS_I(ip); |
| @@ -715,15 +715,7 @@ xfs_log_mount( · 714 unmodified lines | ||
| 715 | 715 | * just worked. |
| 716 | 716 | */ |
| 717 | 717 | if (!xfs_has_norecovery(mp)) { |
| 718 | − /* | |
| 719 | − * log recovery ignores readonly state and so we need to clear | |
| 720 | − * mount-based read only state so it can write to disk. | |
| 721 | − */ | |
| 722 | − bool readonly = test_and_clear_bit(XFS_OPSTATE_READONLY, | |
| 723 | − &mp->m_opstate); | |
| 724 | 718 | error = xlog_recover(log); |
| 725 | − if (readonly) | |
| 726 | − set_bit(XFS_OPSTATE_READONLY, &mp->m_opstate); | |
| 727 | 719 | if (error) { |
| 728 | 720 | xfs_warn(mp, "log mount/recovery failed: error %d", |
| 729 | 721 | error); |
| @@ -772,7 +764,6 @@ xfs_log_mount_finish( · 42 unmodified lines | ||
| 772 | 764 | struct xfs_mount *mp) |
| 773 | 765 | { |
| 774 | 766 | struct xlog *log = mp->m_log; |
| 775 | − bool readonly; | |
| 776 | 767 | int error = 0; |
| 777 | 768 | |
| 778 | 769 | if (xfs_has_norecovery(mp)) { |
| @@ -780,12 +771,6 @@ xfs_log_mount_finish( · 1 unmodified line | ||
| 780 | 771 | return 0; |
| 781 | 772 | } |
| 782 | 773 | |
| 783 | − /* | |
| 784 | − * log recovery ignores readonly state and so we need to clear | |
| 785 | − * mount-based read only state so it can write to disk. | |
| 786 | − */ | |
| 787 | − readonly = test_and_clear_bit(XFS_OPSTATE_READONLY, &mp->m_opstate); | |
| 788 | − | |
| 789 | 774 | /* |
| 790 | 775 | * During the second phase of log recovery, we need iget and |
| 791 | 776 | * iput to behave like they do for an active filesystem. |
| @@ -835,8 +820,6 @@ xfs_log_mount_finish( · 43 unmodified lines | ||
| 835 | 820 | xfs_buftarg_drain(mp->m_ddev_targp); |
| 836 | 821 | |
| 837 | 822 | clear_bit(XLOG_RECOVERY_NEEDED, &log->l_opstate); |
| 838 | − if (readonly) | |
| 839 | − set_bit(XFS_OPSTATE_READONLY, &mp->m_opstate); | |
| 840 | 823 | |
| 841 | 824 | /* Make sure the log is dead if we're returning failure. */ |
| 842 | 825 | ASSERT(!error || xlog_is_shutdown(log)); |
| @@ -124,7 +124,7 @@ xlog_cil_push_pcp_aggregate( · 123 unmodified lines | ||
| 124 | 124 | struct xlog_cil_pcp *cilpcp; |
| 125 | 125 | int cpu; |
| 126 | 126 | |
| 127 | − for_each_online_cpu(cpu) { | |
| 127 | + for_each_cpu(cpu, &ctx->cil_pcpmask) { | |
| 128 | 128 | cilpcp = per_cpu_ptr(cil->xc_pcp, cpu); |
| 129 | 129 | |
| 130 | 130 | ctx->ticket->t_curr_res += cilpcp->space_reserved; |
| @@ -165,7 +165,13 @@ xlog_cil_insert_pcp_aggregate( · 34 unmodified lines | ||
| 165 | 165 | if (!test_and_clear_bit(XLOG_CIL_PCP_SPACE, &cil->xc_flags)) |
| 166 | 166 | return; |
| 167 | 167 | |
| 168 | − for_each_online_cpu(cpu) { | |
| 168 | + /* | |
| 169 | + * We can race with other cpus setting cil_pcpmask. However, we've | |
| 170 | + * atomically cleared PCP_SPACE which forces other threads to add to | |
| 171 | + * the global space used count. cil_pcpmask is a superset of cilpcp | |
| 172 | + * structures that could have a nonzero space_used. | |
| 173 | + */ | |
| 174 | + for_each_cpu(cpu, &ctx->cil_pcpmask) { | |
| 169 | 175 | int old, prev; |
| 170 | 176 | |
| 171 | 177 | cilpcp = per_cpu_ptr(cil->xc_pcp, cpu); |
| @@ -554,6 +560,7 @@ xlog_cil_insert_items( · 382 unmodified lines | ||
| 554 | 560 | int iovhdr_res = 0, split_res = 0, ctx_res = 0; |
| 555 | 561 | int space_used; |
| 556 | 562 | int order; |
| 563 | + unsigned int cpu_nr; | |
| 557 | 564 | struct xlog_cil_pcp *cilpcp; |
| 558 | 565 | |
| 559 | 566 | ASSERT(tp); |
| @@ -577,7 +584,12 @@ xlog_cil_insert_items( · 17 unmodified lines | ||
| 577 | 584 | * can't be scheduled away between split sample/update operations that |
| 578 | 585 | * are done without outside locking to serialise them. |
| 579 | 586 | */ |
| 580 | − cilpcp = get_cpu_ptr(cil->xc_pcp); | |
| 587 | + cpu_nr = get_cpu(); | |
| 588 | + cilpcp = this_cpu_ptr(cil->xc_pcp); | |
| 589 | + | |
| 590 | + /* Tell the future push that there was work added by this CPU. */ | |
| 591 | + if (!cpumask_test_cpu(cpu_nr, &ctx->cil_pcpmask)) | |
| 592 | + cpumask_test_and_set_cpu(cpu_nr, &ctx->cil_pcpmask); | |
| 581 | 593 | |
| 582 | 594 | /* |
| 583 | 595 | * We need to take the CIL checkpoint unit reservation on the first |
| @@ -663,7 +675,7 @@ xlog_cil_insert_items( · 79 unmodified lines | ||
| 663 | 675 | continue; |
| 664 | 676 | list_add_tail(&lip->li_cil, &cilpcp->log_items); |
| 665 | 677 | } |
| 666 | − put_cpu_ptr(cilpcp); | |
| 678 | + put_cpu(); | |
| 667 | 679 | |
| 668 | 680 | /* |
| 669 | 681 | * If we've overrun the reservation, dump the tx details before we move |
| @@ -1790,38 +1802,6 @@ out_shutdown: · 1120 unmodified lines | ||
| 1790 | 1802 | return 0; |
| 1791 | 1803 | } |
| 1792 | 1804 | |
| 1793 | −/* | |
| 1794 | − * Move dead percpu state to the relevant CIL context structures. | |
| 1795 | − * | |
| 1796 | − * We have to lock the CIL context here to ensure that nothing is modifying | |
| 1797 | − * the percpu state, either addition or removal. Both of these are done under | |
| 1798 | − * the CIL context lock, so grabbing that exclusively here will ensure we can | |
| 1799 | − * safely drain the cilpcp for the CPU that is dying. | |
| 1800 | − */ | |
| 1801 | −void | |
| 1802 | −xlog_cil_pcp_dead( | |
| 1803 | − struct xlog *log, | |
| 1804 | − unsigned int cpu) | |
| 1805 | −{ | |
| 1806 | − struct xfs_cil *cil = log->l_cilp; | |
| 1807 | − struct xlog_cil_pcp *cilpcp = per_cpu_ptr(cil->xc_pcp, cpu); | |
| 1808 | − struct xfs_cil_ctx *ctx; | |
| 1809 | − | |
| 1810 | − down_write(&cil->xc_ctx_lock); | |
| 1811 | − ctx = cil->xc_ctx; | |
| 1812 | − if (ctx->ticket) | |
| 1813 | − ctx->ticket->t_curr_res += cilpcp->space_reserved; | |
| 1814 | − cilpcp->space_reserved = 0; | |
| 1815 | − | |
| 1816 | − if (!list_empty(&cilpcp->log_items)) | |
| 1817 | − list_splice_init(&cilpcp->log_items, &ctx->log_items); | |
| 1818 | − if (!list_empty(&cilpcp->busy_extents)) | |
| 1819 | − list_splice_init(&cilpcp->busy_extents, &ctx->busy_extents); | |
| 1820 | − atomic_add(cilpcp->space_used, &ctx->space_used); | |
| 1821 | − cilpcp->space_used = 0; | |
| 1822 | − up_write(&cil->xc_ctx_lock); | |
| 1823 | −} | |
| 1824 | − | |
| 1825 | 1805 | /* |
| 1826 | 1806 | * Perform initial CIL structure initialisation. |
| 1827 | 1807 | */ |
| @@ -231,6 +231,12 @@ struct xfs_cil_ctx { · 230 unmodified lines | ||
| 231 | 231 | struct work_struct discard_endio_work; |
| 232 | 232 | struct work_struct push_work; |
| 233 | 233 | atomic_t order_id; |
| 234 | + | |
| 235 | + /* | |
| 236 | + * CPUs that could have added items to the percpu CIL data. Access is | |
| 237 | + * coordinated with xc_ctx_lock. | |
| 238 | + */ | |
| 239 | + struct cpumask cil_pcpmask; | |
| 234 | 240 | }; |
| 235 | 241 | |
| 236 | 242 | /* |
| @@ -278,9 +284,6 @@ struct xfs_cil { · 41 unmodified lines | ||
| 278 | 284 | wait_queue_head_t xc_push_wait; /* background push throttle */ |
| 279 | 285 | |
| 280 | 286 | void __percpu *xc_pcp; /* percpu CIL structures */ |
| 281 | −#ifdef CONFIG_HOTPLUG_CPU | |
| 282 | − struct list_head xc_pcp_list; | |
| 283 | −#endif | |
| 284 | 287 | } ____cacheline_aligned_in_smp; |
| 285 | 288 | |
| 286 | 289 | /* xc_flags bit values */ |
| @@ -705,9 +708,4 @@ xlog_kvmalloc( · 418 unmodified lines | ||
| 705 | 708 | return p; |
| 706 | 709 | } |
| 707 | 710 | |
| 708 | −/* | |
| 709 | − * CIL CPU dead notifier | |
| 710 | − */ | |
| 711 | −void xlog_cil_pcp_dead(struct xlog *log, unsigned int cpu); | |
| 712 | − | |
| 713 | 711 | #endif /* __XFS_LOG_PRIV_H__ */ |
| @@ -329,7 +329,7 @@ xlog_find_verify_cycle( · 328 unmodified lines | ||
| 329 | 329 | * try a smaller size. We need to be able to read at least |
| 330 | 330 | * a log sector, or we're out of luck. |
| 331 | 331 | */ |
| 332 | − bufblks = 1 << ffs(nbblks); | |
| 332 | + bufblks = roundup_pow_of_two(nbblks); | |
| 333 | 333 | while (bufblks > log->l_logBBsize) |
| 334 | 334 | bufblks >>= 1; |
| 335 | 335 | while (!(buffer = xlog_alloc_buffer(log, bufblks))) { |
| @@ -1528,7 +1528,7 @@ xlog_write_log_records( · 1192 unmodified lines | ||
| 1528 | 1528 | * a smaller size. We need to be able to write at least a |
| 1529 | 1529 | * log sector, or we're out of luck. |
| 1530 | 1530 | */ |
| 1531 | − bufblks = 1 << ffs(blocks); | |
| 1531 | + bufblks = roundup_pow_of_two(blocks); | |
| 1532 | 1532 | while (bufblks > log->l_logBBsize) |
| 1533 | 1533 | bufblks >>= 1; |
| 1534 | 1534 | while (!(buffer = xlog_alloc_buffer(log, bufblks))) { |
| @@ -60,6 +60,7 @@ struct xfs_error_cfg { · 59 unmodified lines | ||
| 60 | 60 | * Per-cpu deferred inode inactivation GC lists. |
| 61 | 61 | */ |
| 62 | 62 | struct xfs_inodegc { |
| 63 | + struct xfs_mount *mp; | |
| 63 | 64 | struct llist_head list; |
| 64 | 65 | struct delayed_work work; |
| 65 | 66 | int error; |
| @@ -67,9 +68,7 @@ struct xfs_inodegc { · 1 unmodified line | ||
| 67 | 68 | /* approximate count of inodes in the list */ |
| 68 | 69 | unsigned int items; |
| 69 | 70 | unsigned int shrinker_hits; |
| 70 | −#if defined(DEBUG) || defined(XFS_WARN) | |
| 71 | 71 | unsigned int cpu; |
| 72 | −#endif | |
| 73 | 72 | }; |
| 74 | 73 | |
| 75 | 74 | /* |
| @@ -98,7 +97,6 @@ typedef struct xfs_mount { · 22 unmodified lines | ||
| 98 | 97 | xfs_buftarg_t *m_ddev_targp; /* saves taking the address */ |
| 99 | 98 | xfs_buftarg_t *m_logdev_targp;/* ptr to log device */ |
| 100 | 99 | xfs_buftarg_t *m_rtdev_targp; /* ptr to rt device */ |
| 101 | − struct list_head m_mount_list; /* global mount list */ | |
| 102 | 100 | void __percpu *m_inodegc; /* percpu inodegc structures */ |
| 103 | 101 | |
| 104 | 102 | /* |
| @@ -249,6 +247,9 @@ typedef struct xfs_mount { · 144 unmodified lines | ||
| 249 | 247 | unsigned int *m_errortag; |
| 250 | 248 | struct xfs_kobj m_errortag_kobj; |
| 251 | 249 | #endif |
| 250 | + | |
| 251 | + /* cpus that have inodes queued for inactivation */ | |
| 252 | + struct cpumask m_inodegc_cpumask; | |
| 252 | 253 | } xfs_mount_t; |
| 253 | 254 | |
| 254 | 255 | #define M_IGEO(mp) (&(mp)->m_ino_geo) |
| @@ -404,6 +405,8 @@ __XFS_HAS_FEAT(nouuid, NOUUID) · 149 unmodified lines | ||
| 404 | 405 | #define XFS_OPSTATE_WARNED_SHRINK 8 |
| 405 | 406 | /* Kernel has logged a warning about logged xattr updates being used. */ |
| 406 | 407 | #define XFS_OPSTATE_WARNED_LARP 9 |
| 408 | +/* Mount time quotacheck is running */ | |
| 409 | +#define XFS_OPSTATE_QUOTACHECK_RUNNING 10 | |
| 407 | 410 | |
| 408 | 411 | #define __XFS_IS_OPSTATE(name, NAME) \ |
| 409 | 412 | static inline bool xfs_is_ ## name (struct xfs_mount *mp) \ |
| @@ -426,6 +429,11 @@ __XFS_IS_OPSTATE(inode32, INODE32) · 16 unmodified lines | ||
| 426 | 429 | __XFS_IS_OPSTATE(readonly, READONLY) |
| 427 | 430 | __XFS_IS_OPSTATE(inodegc_enabled, INODEGC_ENABLED) |
| 428 | 431 | __XFS_IS_OPSTATE(blockgc_enabled, BLOCKGC_ENABLED) |
| 432 | +#ifdef CONFIG_XFS_QUOTA | |
| 433 | +__XFS_IS_OPSTATE(quotacheck_running, QUOTACHECK_RUNNING) | |
| 434 | +#else | |
| 435 | +# define xfs_is_quotacheck_running(mp) (false) | |
| 436 | +#endif | |
| 429 | 437 | |
| 430 | 438 | static inline bool |
| 431 | 439 | xfs_should_warn(struct xfs_mount *mp, long nr) |
| @@ -443,7 +451,8 @@ xfs_should_warn(struct xfs_mount *mp, long nr) · 11 unmodified lines | ||
| 443 | 451 | { (1UL << XFS_OPSTATE_BLOCKGC_ENABLED), "blockgc" }, \ |
| 444 | 452 | { (1UL << XFS_OPSTATE_WARNED_SCRUB), "wscrub" }, \ |
| 445 | 453 | { (1UL << XFS_OPSTATE_WARNED_SHRINK), "wshrink" }, \ |
| 446 | − { (1UL << XFS_OPSTATE_WARNED_LARP), "wlarp" } | |
| 454 | + { (1UL << XFS_OPSTATE_WARNED_LARP), "wlarp" }, \ | |
| 455 | + { (1UL << XFS_OPSTATE_QUOTACHECK_RUNNING), "quotacheck" } | |
| 447 | 456 | |
| 448 | 457 | /* |
| 449 | 458 | * Max and min values for mount-option defined I/O |
| @@ -1160,6 +1160,19 @@ xfs_qm_dqusage_adjust( · 1159 unmodified lines | ||
| 1160 | 1160 | if (error) |
| 1161 | 1161 | return error; |
| 1162 | 1162 | |
| 1163 | + /* | |
| 1164 | + * Reload the incore unlinked list to avoid failure in inodegc. | |
| 1165 | + * Use an unlocked check here because unrecovered unlinked inodes | |
| 1166 | + * should be somewhat rare. | |
| 1167 | + */ | |
| 1168 | + if (xfs_inode_unlinked_incomplete(ip)) { | |
| 1169 | + error = xfs_inode_reload_unlinked(ip); | |
| 1170 | + if (error) { | |
| 1171 | + xfs_force_shutdown(mp, SHUTDOWN_CORRUPT_INCORE); | |
| 1172 | + goto error0; | |
| 1173 | + } | |
| 1174 | + } | |
| 1175 | + | |
| 1163 | 1176 | ASSERT(ip->i_delayed_blks == 0); |
| 1164 | 1177 | |
| 1165 | 1178 | if (XFS_IS_REALTIME_INODE(ip)) { |
| @@ -1173,6 +1186,7 @@ xfs_qm_dqusage_adjust( · 7 unmodified lines | ||
| 1173 | 1186 | } |
| 1174 | 1187 | |
| 1175 | 1188 | nblks = (xfs_qcnt_t)ip->i_nblocks - rtblks; |
| 1189 | + xfs_iflags_clear(ip, XFS_IQUOTAUNCHECKED); | |
| 1176 | 1190 | |
| 1177 | 1191 | /* |
| 1178 | 1192 | * Add the (disk blocks and inode) resources occupied by this |
| @@ -1319,8 +1333,10 @@ xfs_qm_quotacheck( · 140 unmodified lines | ||
| 1319 | 1333 | flags |= XFS_PQUOTA_CHKD; |
| 1320 | 1334 | } |
| 1321 | 1335 | |
| 1336 | + xfs_set_quotacheck_running(mp); | |
| 1322 | 1337 | error = xfs_iwalk_threaded(mp, 0, 0, xfs_qm_dqusage_adjust, 0, true, |
| 1323 | 1338 | NULL); |
| 1339 | + xfs_clear_quotacheck_running(mp); | |
| 1324 | 1340 | |
| 1325 | 1341 | /* |
| 1326 | 1342 | * On error, the inode walk may have partially populated the dquot |
| @@ -477,6 +477,7 @@ xfs_cui_item_recover( · 476 unmodified lines | ||
| 477 | 477 | struct xfs_log_item *lip, |
| 478 | 478 | struct list_head *capture_list) |
| 479 | 479 | { |
| 480 | + struct xfs_trans_res resv; | |
| 480 | 481 | struct xfs_cui_log_item *cuip = CUI_ITEM(lip); |
| 481 | 482 | struct xfs_cud_log_item *cudp; |
| 482 | 483 | struct xfs_trans *tp; |
| @@ -514,8 +515,9 @@ xfs_cui_item_recover( · 31 unmodified lines | ||
| 514 | 515 | * doesn't fit. We need to reserve enough blocks to handle a |
| 515 | 516 | * full btree split on either end of the refcount range. |
| 516 | 517 | */ |
| 517 | − error = xfs_trans_alloc(mp, &M_RES(mp)->tr_itruncate, | |
| 518 | − mp->m_refc_maxlevels * 2, 0, XFS_TRANS_RESERVE, &tp); | |
| 518 | + resv = xlog_recover_resv(&M_RES(mp)->tr_itruncate); | |
| 519 | + error = xfs_trans_alloc(mp, &resv, mp->m_refc_maxlevels * 2, 0, | |
| 520 | + XFS_TRANS_RESERVE, &tp); | |
| 519 | 521 | if (error) |
| 520 | 522 | return error; |
| 521 | 523 | |
| @@ -507,6 +507,7 @@ xfs_rui_item_recover( · 506 unmodified lines | ||
| 507 | 507 | struct xfs_log_item *lip, |
| 508 | 508 | struct list_head *capture_list) |
| 509 | 509 | { |
| 510 | + struct xfs_trans_res resv; | |
| 510 | 511 | struct xfs_rui_log_item *ruip = RUI_ITEM(lip); |
| 511 | 512 | struct xfs_rud_log_item *rudp; |
| 512 | 513 | struct xfs_trans *tp; |
| @@ -530,8 +531,9 @@ xfs_rui_item_recover( · 17 unmodified lines | ||
| 530 | 531 | } |
| 531 | 532 | } |
| 532 | 533 | |
| 533 | − error = xfs_trans_alloc(mp, &M_RES(mp)->tr_itruncate, | |
| 534 | − mp->m_rmap_maxlevels, 0, XFS_TRANS_RESERVE, &tp); | |
| 534 | + resv = xlog_recover_resv(&M_RES(mp)->tr_itruncate); | |
| 535 | + error = xfs_trans_alloc(mp, &resv, mp->m_rmap_maxlevels, 0, | |
| 536 | + XFS_TRANS_RESERVE, &tp); | |
| 535 | 537 | if (error) |
| 536 | 538 | return error; |
| 537 | 539 | rudp = xfs_trans_get_rud(tp, ruip); |
| @@ -56,28 +56,6 @@ static struct kset *xfs_kset; /* top-level xfs sysfs dir */ · 55 unmodified lines | ||
| 56 | 56 | static struct xfs_kobj xfs_dbg_kobj; /* global debug sysfs attrs */ |
| 57 | 57 | #endif |
| 58 | 58 | |
| 59 | −#ifdef CONFIG_HOTPLUG_CPU | |
| 60 | −static LIST_HEAD(xfs_mount_list); | |
| 61 | −static DEFINE_SPINLOCK(xfs_mount_list_lock); | |
| 62 | − | |
| 63 | −static inline void xfs_mount_list_add(struct xfs_mount *mp) | |
| 64 | −{ | |
| 65 | − spin_lock(&xfs_mount_list_lock); | |
| 66 | − list_add(&mp->m_mount_list, &xfs_mount_list); | |
| 67 | − spin_unlock(&xfs_mount_list_lock); | |
| 68 | −} | |
| 69 | − | |
| 70 | −static inline void xfs_mount_list_del(struct xfs_mount *mp) | |
| 71 | −{ | |
| 72 | − spin_lock(&xfs_mount_list_lock); | |
| 73 | − list_del(&mp->m_mount_list); | |
| 74 | − spin_unlock(&xfs_mount_list_lock); | |
| 75 | −} | |
| 76 | −#else /* !CONFIG_HOTPLUG_CPU */ | |
| 77 | −static inline void xfs_mount_list_add(struct xfs_mount *mp) {} | |
| 78 | −static inline void xfs_mount_list_del(struct xfs_mount *mp) {} | |
| 79 | −#endif | |
| 80 | − | |
| 81 | 59 | enum xfs_dax_mode { |
| 82 | 60 | XFS_DAX_INODE = 0, |
| 83 | 61 | XFS_DAX_ALWAYS = 1, |
| @@ -1135,9 +1113,8 @@ xfs_inodegc_init_percpu( · 1051 unmodified lines | ||
| 1135 | 1113 | |
| 1136 | 1114 | for_each_possible_cpu(cpu) { |
| 1137 | 1115 | gc = per_cpu_ptr(mp->m_inodegc, cpu); |
| 1138 | −#if defined(DEBUG) || defined(XFS_WARN) | |
| 1139 | 1116 | gc->cpu = cpu; |
| 1140 | −#endif | |
| 1117 | + gc->mp = mp; | |
| 1141 | 1118 | init_llist_head(&gc->list); |
| 1142 | 1119 | gc->items = 0; |
| 1143 | 1120 | gc->error = 0; |
| @@ -1168,7 +1145,6 @@ xfs_fs_put_super( · 24 unmodified lines | ||
| 1168 | 1145 | xfs_freesb(mp); |
| 1169 | 1146 | xchk_mount_stats_free(mp); |
| 1170 | 1147 | free_percpu(mp->m_stats.xs_stats); |
| 1171 | − xfs_mount_list_del(mp); | |
| 1172 | 1148 | xfs_inodegc_free_percpu(mp); |
| 1173 | 1149 | xfs_destroy_percpu_counters(mp); |
| 1174 | 1150 | xfs_destroy_mount_workqueues(mp); |
| @@ -1577,13 +1553,6 @@ xfs_fs_fill_super( · 402 unmodified lines | ||
| 1577 | 1553 | if (error) |
| 1578 | 1554 | goto out_destroy_counters; |
| 1579 | 1555 | |
| 1580 | − /* | |
| 1581 | − * All percpu data structures requiring cleanup when a cpu goes offline | |
| 1582 | − * must be allocated before adding this @mp to the cpu-dead handler's | |
| 1583 | − * mount list. | |
| 1584 | − */ | |
| 1585 | − xfs_mount_list_add(mp); | |
| 1586 | − | |
| 1587 | 1556 | /* Allocate stats memory before we do operations that might use it */ |
| 1588 | 1557 | mp->m_stats.xs_stats = alloc_percpu(struct xfsstats); |
| 1589 | 1558 | if (!mp->m_stats.xs_stats) { |
| @@ -1781,7 +1750,6 @@ xfs_fs_fill_super( · 191 unmodified lines | ||
| 1781 | 1750 | out_free_stats: |
| 1782 | 1751 | free_percpu(mp->m_stats.xs_stats); |
| 1783 | 1752 | out_destroy_inodegc: |
| 1784 | − xfs_mount_list_del(mp); | |
| 1785 | 1753 | xfs_inodegc_free_percpu(mp); |
| 1786 | 1754 | out_destroy_counters: |
| 1787 | 1755 | xfs_destroy_percpu_counters(mp); |
| @@ -2326,49 +2294,6 @@ xfs_destroy_workqueues(void) · 538 unmodified lines | ||
| 2326 | 2294 | destroy_workqueue(xfs_alloc_wq); |
| 2327 | 2295 | } |
| 2328 | 2296 | |
| 2329 | −#ifdef CONFIG_HOTPLUG_CPU | |
| 2330 | −static int | |
| 2331 | −xfs_cpu_dead( | |
| 2332 | − unsigned int cpu) | |
| 2333 | −{ | |
| 2334 | − struct xfs_mount *mp, *n; | |
| 2335 | − | |
| 2336 | − spin_lock(&xfs_mount_list_lock); | |
| 2337 | − list_for_each_entry_safe(mp, n, &xfs_mount_list, m_mount_list) { | |
| 2338 | − spin_unlock(&xfs_mount_list_lock); | |
| 2339 | − xfs_inodegc_cpu_dead(mp, cpu); | |
| 2340 | − xlog_cil_pcp_dead(mp->m_log, cpu); | |
| 2341 | − spin_lock(&xfs_mount_list_lock); | |
| 2342 | − } | |
| 2343 | − spin_unlock(&xfs_mount_list_lock); | |
| 2344 | − return 0; | |
| 2345 | −} | |
| 2346 | − | |
| 2347 | −static int __init | |
| 2348 | −xfs_cpu_hotplug_init(void) | |
| 2349 | −{ | |
| 2350 | − int error; | |
| 2351 | − | |
| 2352 | − error = cpuhp_setup_state_nocalls(CPUHP_XFS_DEAD, "xfs:dead", NULL, | |
| 2353 | − xfs_cpu_dead); | |
| 2354 | − if (error < 0) | |
| 2355 | − xfs_alert(NULL, | |
| 2356 | −"Failed to initialise CPU hotplug, error %d. XFS is non-functional.", | |
| 2357 | − error); | |
| 2358 | − return error; | |
| 2359 | −} | |
| 2360 | − | |
| 2361 | −static void | |
| 2362 | −xfs_cpu_hotplug_destroy(void) | |
| 2363 | −{ | |
| 2364 | − cpuhp_remove_state_nocalls(CPUHP_XFS_DEAD); | |
| 2365 | −} | |
| 2366 | − | |
| 2367 | −#else /* !CONFIG_HOTPLUG_CPU */ | |
| 2368 | −static inline int xfs_cpu_hotplug_init(void) { return 0; } | |
| 2369 | −static inline void xfs_cpu_hotplug_destroy(void) {} | |
| 2370 | −#endif | |
| 2371 | − | |
| 2372 | 2297 | STATIC int __init |
| 2373 | 2298 | init_xfs_fs(void) |
| 2374 | 2299 | { |
| @@ -2385,13 +2310,9 @@ init_xfs_fs(void) · 10 unmodified lines | ||
| 2385 | 2310 | |
| 2386 | 2311 | xfs_dir_startup(); |
| 2387 | 2312 | |
| 2388 | − error = xfs_cpu_hotplug_init(); | |
| 2389 | − if (error) | |
| 2390 | − goto out; | |
| 2391 | − | |
| 2392 | 2313 | error = xfs_init_caches(); |
| 2393 | 2314 | if (error) |
| 2394 | − goto out_destroy_hp; | |
| 2315 | + goto out; | |
| 2395 | 2316 | |
| 2396 | 2317 | error = xfs_init_workqueues(); |
| 2397 | 2318 | if (error) |
| @@ -2475,8 +2396,6 @@ init_xfs_fs(void) · 77 unmodified lines | ||
| 2475 | 2396 | xfs_destroy_workqueues(); |
| 2476 | 2397 | out_destroy_caches: |
| 2477 | 2398 | xfs_destroy_caches(); |
| 2478 | − out_destroy_hp: | |
| 2479 | − xfs_cpu_hotplug_destroy(); | |
| 2480 | 2399 | out: |
| 2481 | 2400 | return error; |
| 2482 | 2401 | } |
| @@ -2500,7 +2419,6 @@ exit_xfs_fs(void) · 17 unmodified lines | ||
| 2500 | 2419 | xfs_destroy_workqueues(); |
| 2501 | 2420 | xfs_destroy_caches(); |
| 2502 | 2421 | xfs_uuid_table_free(); |
| 2503 | − xfs_cpu_hotplug_destroy(); | |
| 2504 | 2422 | } |
| 2505 | 2423 | |
| 2506 | 2424 | module_init(init_xfs_fs); |
| @@ -3824,6 +3824,51 @@ TRACE_EVENT(xfs_iunlink_update_dinode, · 3823 unmodified lines | ||
| 3824 | 3824 | __entry->new_ptr) |
| 3825 | 3825 | ); |
| 3826 | 3826 | |
| 3827 | +TRACE_EVENT(xfs_iunlink_reload_next, | |
| 3828 | + TP_PROTO(struct xfs_inode *ip), | |
| 3829 | + TP_ARGS(ip), | |
| 3830 | + TP_STRUCT__entry( | |
| 3831 | + __field(dev_t, dev) | |
| 3832 | + __field(xfs_agnumber_t, agno) | |
| 3833 | + __field(xfs_agino_t, agino) | |
| 3834 | + __field(xfs_agino_t, prev_agino) | |
| 3835 | + __field(xfs_agino_t, next_agino) | |
| 3836 | + ), | |
| 3837 | + TP_fast_assign( | |
| 3838 | + __entry->dev = ip->i_mount->m_super->s_dev; | |
| 3839 | + __entry->agno = XFS_INO_TO_AGNO(ip->i_mount, ip->i_ino); | |
| 3840 | + __entry->agino = XFS_INO_TO_AGINO(ip->i_mount, ip->i_ino); | |
| 3841 | + __entry->prev_agino = ip->i_prev_unlinked; | |
| 3842 | + __entry->next_agino = ip->i_next_unlinked; | |
| 3843 | + ), | |
| 3844 | + TP_printk("dev %d:%d agno 0x%x agino 0x%x prev_unlinked 0x%x next_unlinked 0x%x", | |
| 3845 | + MAJOR(__entry->dev), MINOR(__entry->dev), | |
| 3846 | + __entry->agno, | |
| 3847 | + __entry->agino, | |
| 3848 | + __entry->prev_agino, | |
| 3849 | + __entry->next_agino) | |
| 3850 | +); | |
| 3851 | + | |
| 3852 | +TRACE_EVENT(xfs_inode_reload_unlinked_bucket, | |
| 3853 | + TP_PROTO(struct xfs_inode *ip), | |
| 3854 | + TP_ARGS(ip), | |
| 3855 | + TP_STRUCT__entry( | |
| 3856 | + __field(dev_t, dev) | |
| 3857 | + __field(xfs_agnumber_t, agno) | |
| 3858 | + __field(xfs_agino_t, agino) | |
| 3859 | + ), | |
| 3860 | + TP_fast_assign( | |
| 3861 | + __entry->dev = ip->i_mount->m_super->s_dev; | |
| 3862 | + __entry->agno = XFS_INO_TO_AGNO(ip->i_mount, ip->i_ino); | |
| 3863 | + __entry->agino = XFS_INO_TO_AGINO(ip->i_mount, ip->i_ino); | |
| 3864 | + ), | |
| 3865 | + TP_printk("dev %d:%d agno 0x%x agino 0x%x bucket %u", | |
| 3866 | + MAJOR(__entry->dev), MINOR(__entry->dev), | |
| 3867 | + __entry->agno, | |
| 3868 | + __entry->agino, | |
| 3869 | + __entry->agino % XFS_AGI_UNLINKED_BUCKETS) | |
| 3870 | +); | |
| 3871 | + | |
| 3827 | 3872 | DECLARE_EVENT_CLASS(xfs_ag_inode_class, |
| 3828 | 3873 | TP_PROTO(struct xfs_inode *ip), |
| 3829 | 3874 | TP_ARGS(ip), |
| @@ -46,6 +46,17 @@ xfs_attr_grab_log_assist( · 45 unmodified lines | ||
| 46 | 46 | if (xfs_sb_version_haslogxattrs(&mp->m_sb)) |
| 47 | 47 | return 0; |
| 48 | 48 | |
| 49 | + /* | |
| 50 | + * Check if the filesystem featureset is new enough to set this log | |
| 51 | + * incompat feature bit. Strictly speaking, the minimum requirement is | |
| 52 | + * a V5 filesystem for the superblock field, but we'll require rmap | |
| 53 | + * or reflink to avoid having to deal with really old kernels. | |
| 54 | + */ | |
| 55 | + if (!xfs_has_reflink(mp) && !xfs_has_rmapbt(mp)) { | |
| 56 | + error = -EOPNOTSUPP; | |
| 57 | + goto drop_incompat; | |
| 58 | + } | |
| 59 | + | |
| 49 | 60 | /* Enable log-assisted xattrs. */ |
| 50 | 61 | error = xfs_add_incompat_log_feature(mp, |
| 51 | 62 | XFS_SB_FEAT_INCOMPAT_LOG_XATTRS); |
| @@ -76,7 +76,7 @@ static inline void hugetlb_free_pgd_range(struct mmu_gather *tlb, · 75 unmodified lines | ||
| 76 | 76 | |
| 77 | 77 | #ifndef __HAVE_ARCH_HUGE_SET_HUGE_PTE_AT |
| 78 | 78 | static inline void set_huge_pte_at(struct mm_struct *mm, unsigned long addr, |
| 79 | − pte_t *ptep, pte_t pte) | |
| 79 | + pte_t *ptep, pte_t pte, unsigned long sz) | |
| 80 | 80 | { |
| 81 | 81 | set_pte_at(mm, addr, ptep, pte); |
| 82 | 82 | } |
| @@ -138,13 +138,6 @@ · 137 unmodified lines | ||
| 138 | 138 | * are handled as text/data or they can be discarded (which |
| 139 | 139 | * often happens at runtime) |
| 140 | 140 | */ |
| 141 | −#ifdef CONFIG_HOTPLUG_CPU | |
| 142 | −#define CPU_KEEP(sec) *(.cpu##sec) | |
| 143 | −#define CPU_DISCARD(sec) | |
| 144 | −#else | |
| 145 | −#define CPU_KEEP(sec) | |
| 146 | −#define CPU_DISCARD(sec) *(.cpu##sec) | |
| 147 | −#endif | |
| 148 | 141 | |
| 149 | 142 | #if defined(CONFIG_MEMORY_HOTPLUG) |
| 150 | 143 | #define MEM_KEEP(sec) *(.mem##sec) |
| @@ -42,11 +42,13 @@ struct aer_capability_regs { · 41 unmodified lines | ||
| 42 | 42 | |
| 43 | 43 | #if defined(CONFIG_PCIEAER) |
| 44 | 44 | int pci_aer_clear_nonfatal_status(struct pci_dev *dev); |
| 45 | +int pcie_aer_is_native(struct pci_dev *dev); | |
| 45 | 46 | #else |
| 46 | 47 | static inline int pci_aer_clear_nonfatal_status(struct pci_dev *dev) |
| 47 | 48 | { |
| 48 | 49 | return -EINVAL; |
| 49 | 50 | } |
| 51 | +static inline int pcie_aer_is_native(struct pci_dev *dev) { return 0; } | |
| 50 | 52 | #endif |
| 51 | 53 | |
| 52 | 54 | void cper_print_aer(struct pci_dev *dev, int aer_severity, |
| @@ -67,6 +67,8 @@ · 66 unmodified lines | ||
| 67 | 67 | #define ARM_SMCCC_VERSION_1_3 0x10003 |
| 68 | 68 | |
| 69 | 69 | #define ARM_SMCCC_1_3_SVE_HINT 0x10000 |
| 70 | +#define ARM_SMCCC_CALL_HINTS ARM_SMCCC_1_3_SVE_HINT | |
| 71 | + | |
| 70 | 72 | |
| 71 | 73 | #define ARM_SMCCC_VERSION_FUNC_ID \ |
| 72 | 74 | ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL, \ |
| @@ -459,8 +459,6 @@ raw_atomic_read_acquire(const atomic_t *v) · 458 unmodified lines | ||
| 459 | 459 | { |
| 460 | 460 | #if defined(arch_atomic_read_acquire) |
| 461 | 461 | return arch_atomic_read_acquire(v); |
| 462 | −#elif defined(arch_atomic_read) | |
| 463 | − return arch_atomic_read(v); | |
| 464 | 462 | #else |
| 465 | 463 | int ret; |
| 466 | 464 | |
| @@ -508,8 +506,6 @@ raw_atomic_set_release(atomic_t *v, int i) · 41 unmodified lines | ||
| 508 | 506 | { |
| 509 | 507 | #if defined(arch_atomic_set_release) |
| 510 | 508 | arch_atomic_set_release(v, i); |
| 511 | −#elif defined(arch_atomic_set) | |
| 512 | − arch_atomic_set(v, i); | |
| 513 | 509 | #else |
| 514 | 510 | if (__native_word(atomic_t)) { |
| 515 | 511 | smp_store_release(&(v)->counter, i); |
| @@ -2575,8 +2571,6 @@ raw_atomic64_read_acquire(const atomic64_t *v) · 2059 unmodified lines | ||
| 2575 | 2571 | { |
| 2576 | 2572 | #if defined(arch_atomic64_read_acquire) |
| 2577 | 2573 | return arch_atomic64_read_acquire(v); |
| 2578 | −#elif defined(arch_atomic64_read) | |
| 2579 | − return arch_atomic64_read(v); | |
| 2580 | 2574 | #else |
| 2581 | 2575 | s64 ret; |
| 2582 | 2576 | |
| @@ -2624,8 +2618,6 @@ raw_atomic64_set_release(atomic64_t *v, s64 i) · 41 unmodified lines | ||
| 2624 | 2618 | { |
| 2625 | 2619 | #if defined(arch_atomic64_set_release) |
| 2626 | 2620 | arch_atomic64_set_release(v, i); |
| 2627 | −#elif defined(arch_atomic64_set) | |
| 2628 | − arch_atomic64_set(v, i); | |
| 2629 | 2621 | #else |
| 2630 | 2622 | if (__native_word(atomic64_t)) { |
| 2631 | 2623 | smp_store_release(&(v)->counter, i); |
| @@ -4657,4 +4649,4 @@ raw_atomic64_dec_if_positive(atomic64_t *v) · 2025 unmodified lines | ||
| 4657 | 4649 | } |
| 4658 | 4650 | |
| 4659 | 4651 | #endif /* _LINUX_ATOMIC_FALLBACK_H */ |
| 4660 | −// 202b45c7db600ce36198eb1f1fc2c2d5268ace2d | |
| 4652 | +// 2fdd6702823fa842f9cea57a002e6e4476ae780c | |
| @@ -1318,7 +1318,7 @@ static inline int bpf_trampoline_unlink_prog(struct bpf_tramp_link *link, · 1317 unmodified lines | ||
| 1318 | 1318 | static inline struct bpf_trampoline *bpf_trampoline_get(u64 key, |
| 1319 | 1319 | struct bpf_attach_target_info *tgt_info) |
| 1320 | 1320 | { |
| 1321 | − return ERR_PTR(-EOPNOTSUPP); | |
| 1321 | + return NULL; | |
| 1322 | 1322 | } |
| 1323 | 1323 | static inline void bpf_trampoline_put(struct bpf_trampoline *tr) {} |
| 1324 | 1324 | #define DEFINE_BPF_DISPATCHER(name) |
| @@ -467,19 +467,17 @@ union ceph_mds_request_args { · 466 unmodified lines | ||
| 467 | 467 | } __attribute__ ((packed)); |
| 468 | 468 | |
| 469 | 469 | union ceph_mds_request_args_ext { |
| 470 | − union { | |
| 471 | − union ceph_mds_request_args old; | |
| 472 | − struct { | |
| 473 | − __le32 mode; | |
| 474 | − __le32 uid; | |
| 475 | − __le32 gid; | |
| 476 | − struct ceph_timespec mtime; | |
| 477 | − struct ceph_timespec atime; | |
| 478 | − __le64 size, old_size; /* old_size needed by truncate */ | |
| 479 | − __le32 mask; /* CEPH_SETATTR_* */ | |
| 480 | − struct ceph_timespec btime; | |
| 481 | − } __attribute__ ((packed)) setattr_ext; | |
| 482 | − }; | |
| 470 | + union ceph_mds_request_args old; | |
| 471 | + struct { | |
| 472 | + __le32 mode; | |
| 473 | + __le32 uid; | |
| 474 | + __le32 gid; | |
| 475 | + struct ceph_timespec mtime; | |
| 476 | + struct ceph_timespec atime; | |
| 477 | + __le64 size, old_size; /* old_size needed by truncate */ | |
| 478 | + __le32 mask; /* CEPH_SETATTR_* */ | |
| 479 | + struct ceph_timespec btime; | |
| 480 | + } __attribute__ ((packed)) setattr_ext; | |
| 483 | 481 | }; |
| 484 | 482 | |
| 485 | 483 | #define CEPH_MDS_FLAG_REPLAY 1 /* this is a replayed op */ |
| @@ -90,7 +90,6 @@ enum cpuhp_state { · 89 unmodified lines | ||
| 90 | 90 | CPUHP_FS_BUFF_DEAD, |
| 91 | 91 | CPUHP_PRINTK_DEAD, |
| 92 | 92 | CPUHP_MM_MEMCQ_DEAD, |
| 93 | − CPUHP_XFS_DEAD, | |
| 94 | 93 | CPUHP_PERCPU_CNT_DEAD, |
| 95 | 94 | CPUHP_RADIX_DEAD, |
| 96 | 95 | CPUHP_PAGE_ALLOC, |
| @@ -984,7 +984,9 @@ static inline void huge_ptep_modify_prot_commit(struct vm_area_struct *vma, · 983 unmodified lines | ||
| 984 | 984 | unsigned long addr, pte_t *ptep, |
| 985 | 985 | pte_t old_pte, pte_t pte) |
| 986 | 986 | { |
| 987 | − set_huge_pte_at(vma->vm_mm, addr, ptep, pte); | |
| 987 | + unsigned long psize = huge_page_size(hstate_vma(vma)); | |
| 988 | + | |
| 989 | + set_huge_pte_at(vma->vm_mm, addr, ptep, pte, psize); | |
| 988 | 990 | } |
| 989 | 991 | #endif |
| 990 | 992 | |
| @@ -1173,7 +1175,7 @@ static inline pte_t huge_ptep_clear_flush(struct vm_area_struct *vma, · 182 unmodified lines | ||
| 1173 | 1175 | } |
| 1174 | 1176 | |
| 1175 | 1177 | static inline void set_huge_pte_at(struct mm_struct *mm, unsigned long addr, |
| 1176 | − pte_t *ptep, pte_t pte) | |
| 1178 | + pte_t *ptep, pte_t pte, unsigned long sz) | |
| 1177 | 1179 | { |
| 1178 | 1180 | } |
| 1179 | 1181 | |
| @@ -569,8 +569,12 @@ enum · 568 unmodified lines | ||
| 569 | 569 | * 2) rcu_report_dead() reports the final quiescent states. |
| 570 | 570 | * |
| 571 | 571 | * _ IRQ_POLL: irq_poll_cpu_dead() migrates the queue |
| 572 | + * | |
| 573 | + * _ (HR)TIMER_SOFTIRQ: (hr)timers_dead_cpu() migrates the queue | |
| 572 | 574 | */ |
| 573 | −#define SOFTIRQ_HOTPLUG_SAFE_MASK (BIT(RCU_SOFTIRQ) | BIT(IRQ_POLL_SOFTIRQ)) | |
| 575 | +#define SOFTIRQ_HOTPLUG_SAFE_MASK (BIT(TIMER_SOFTIRQ) | BIT(IRQ_POLL_SOFTIRQ) |\ | |
| 576 | + BIT(HRTIMER_SOFTIRQ) | BIT(RCU_SOFTIRQ)) | |
| 577 | + | |
| 574 | 578 | |
| 575 | 579 | /* map softirq index to softirq name. update 'softirq_to_name' in |
| 576 | 580 | * kernel/softirq.c when adding a new softirq. |
| @@ -54,7 +54,7 @@ extern p4d_t kasan_early_shadow_p4d[MAX_PTRS_PER_P4D]; · 53 unmodified lines | ||
| 54 | 54 | int kasan_populate_early_shadow(const void *shadow_start, |
| 55 | 55 | const void *shadow_end); |
| 56 | 56 | |
| 57 | −#ifndef __HAVE_ARCH_SHADOW_MAP | |
| 57 | +#ifndef kasan_mem_to_shadow | |
| 58 | 58 | static inline void *kasan_mem_to_shadow(const void *addr) |
| 59 | 59 | { |
| 60 | 60 | return (void *)((unsigned long)addr >> KASAN_SHADOW_SCALE_SHIFT) |
| @@ -192,6 +192,7 @@ enum { · 191 unmodified lines | ||
| 192 | 192 | ATA_PFLAG_UNLOADING = (1 << 9), /* driver is being unloaded */ |
| 193 | 193 | ATA_PFLAG_UNLOADED = (1 << 10), /* driver is unloaded */ |
| 194 | 194 | |
| 195 | + ATA_PFLAG_RESUMING = (1 << 16), /* port is being resumed */ | |
| 195 | 196 | ATA_PFLAG_SUSPENDED = (1 << 17), /* port is suspended (power) */ |
| 196 | 197 | ATA_PFLAG_PM_PENDING = (1 << 18), /* PM operation pending */ |
| 197 | 198 | ATA_PFLAG_INIT_GTM_VALID = (1 << 19), /* initial gtm data valid */ |
| @@ -259,7 +260,7 @@ enum { · 61 unmodified lines | ||
| 259 | 260 | * advised to wait only for the following duration before |
| 260 | 261 | * doing SRST. |
| 261 | 262 | */ |
| 262 | − ATA_TMOUT_PMP_SRST_WAIT = 5000, | |
| 263 | + ATA_TMOUT_PMP_SRST_WAIT = 10000, | |
| 263 | 264 | |
| 264 | 265 | /* When the LPM policy is set to ATA_LPM_MAX_POWER, there might |
| 265 | 266 | * be a spurious PHY event, so ignore the first PHY event that |
| @@ -318,9 +319,10 @@ enum { · 52 unmodified lines | ||
| 318 | 319 | ATA_EH_ENABLE_LINK = (1 << 3), |
| 319 | 320 | ATA_EH_PARK = (1 << 5), /* unload heads and stop I/O */ |
| 320 | 321 | ATA_EH_GET_SUCCESS_SENSE = (1 << 6), /* Get sense data for successful cmd */ |
| 322 | + ATA_EH_SET_ACTIVE = (1 << 7), /* Set a device to active power mode */ | |
| 321 | 323 | |
| 322 | 324 | ATA_EH_PERDEV_MASK = ATA_EH_REVALIDATE | ATA_EH_PARK | |
| 323 | − ATA_EH_GET_SUCCESS_SENSE, | |
| 325 | + ATA_EH_GET_SUCCESS_SENSE | ATA_EH_SET_ACTIVE, | |
| 324 | 326 | ATA_EH_ALL_ACTIONS = ATA_EH_REVALIDATE | ATA_EH_RESET | |
| 325 | 327 | ATA_EH_ENABLE_LINK, |
| 326 | 328 | |
| @@ -357,7 +359,7 @@ enum { · 30 unmodified lines | ||
| 357 | 359 | /* This should match the actual table size of |
| 358 | 360 | * ata_eh_cmd_timeout_table in libata-eh.c. |
| 359 | 361 | */ |
| 360 | − ATA_EH_CMD_TIMEOUT_TABLE_SIZE = 7, | |
| 362 | + ATA_EH_CMD_TIMEOUT_TABLE_SIZE = 8, | |
| 361 | 363 | |
| 362 | 364 | /* Horkage types. May be set by libata or controller on drives |
| 363 | 365 | (some horkage may be drive/controller pair dependent */ |
| @@ -1148,6 +1150,7 @@ extern int ata_std_bios_param(struct scsi_device *sdev, · 784 unmodified lines | ||
| 1148 | 1150 | struct block_device *bdev, |
| 1149 | 1151 | sector_t capacity, int geom[]); |
| 1150 | 1152 | extern void ata_scsi_unlock_native_capacity(struct scsi_device *sdev); |
| 1153 | +extern int ata_scsi_slave_alloc(struct scsi_device *sdev); | |
| 1151 | 1154 | extern int ata_scsi_slave_config(struct scsi_device *sdev); |
| 1152 | 1155 | extern void ata_scsi_slave_destroy(struct scsi_device *sdev); |
| 1153 | 1156 | extern int ata_scsi_change_queue_depth(struct scsi_device *sdev, |
| @@ -1396,6 +1399,7 @@ extern const struct attribute_group *ata_common_sdev_groups[]; · 242 unmodified lines | ||
| 1396 | 1399 | .this_id = ATA_SHT_THIS_ID, \ |
| 1397 | 1400 | .emulated = ATA_SHT_EMULATED, \ |
| 1398 | 1401 | .proc_name = drv_name, \ |
| 1402 | + .slave_alloc = ata_scsi_slave_alloc, \ | |
| 1399 | 1403 | .slave_destroy = ata_scsi_slave_destroy, \ |
| 1400 | 1404 | .bios_param = ata_std_bios_param, \ |
| 1401 | 1405 | .unlock_native_capacity = ata_scsi_unlock_native_capacity,\ |
| @@ -428,6 +428,8 @@ struct ma_wr_state { · 427 unmodified lines | ||
| 428 | 428 | #define MAS_ROOT ((struct maple_enode *)5UL) |
| 429 | 429 | #define MAS_NONE ((struct maple_enode *)9UL) |
| 430 | 430 | #define MAS_PAUSE ((struct maple_enode *)17UL) |
| 431 | +#define MAS_OVERFLOW ((struct maple_enode *)33UL) | |
| 432 | +#define MAS_UNDERFLOW ((struct maple_enode *)65UL) | |
| 431 | 433 | #define MA_ERROR(err) \ |
| 432 | 434 | ((struct maple_enode *)(((unsigned long)err << 2) | 2UL)) |
| 433 | 435 | |
| @@ -511,6 +513,15 @@ static inline bool mas_is_paused(const struct ma_state *mas) · 77 unmodified lines | ||
| 511 | 513 | return mas->node == MAS_PAUSE; |
| 512 | 514 | } |
| 513 | 515 | |
| 516 | +/* Check if the mas is pointing to a node or not */ | |
| 517 | +static inline bool mas_is_active(struct ma_state *mas) | |
| 518 | +{ | |
| 519 | + if ((unsigned long)mas->node >= MAPLE_RESERVED_RANGE) | |
| 520 | + return true; | |
| 521 | + | |
| 522 | + return false; | |
| 523 | +} | |
| 524 | + | |
| 514 | 525 | /** |
| 515 | 526 | * mas_reset() - Reset a Maple Tree operation state. |
| 516 | 527 | * @mas: Maple Tree operation state. |
| @@ -920,7 +920,7 @@ unsigned long mem_cgroup_get_zone_lru_size(struct lruvec *lruvec, · 919 unmodified lines | ||
| 920 | 920 | return READ_ONCE(mz->lru_zone_size[zone_idx][lru]); |
| 921 | 921 | } |
| 922 | 922 | |
| 923 | −void mem_cgroup_handle_over_high(void); | |
| 923 | +void mem_cgroup_handle_over_high(gfp_t gfp_mask); | |
| 924 | 924 | |
| 925 | 925 | unsigned long mem_cgroup_get_max(struct mem_cgroup *memcg); |
| 926 | 926 | |
| @@ -1458,7 +1458,7 @@ static inline void mem_cgroup_unlock_pages(void) · 531 unmodified lines | ||
| 1458 | 1458 | rcu_read_unlock(); |
| 1459 | 1459 | } |
| 1460 | 1460 | |
| 1461 | −static inline void mem_cgroup_handle_over_high(void) | |
| 1461 | +static inline void mem_cgroup_handle_over_high(gfp_t gfp_mask) | |
| 1462 | 1462 | { |
| 1463 | 1463 | } |
| 1464 | 1464 | |
| @@ -9,6 +9,7 @@ struct ip_ct_sctp { · 8 unmodified lines | ||
| 9 | 9 | enum sctp_conntrack state; |
| 10 | 10 | |
| 11 | 11 | __be32 vtag[IP_CT_DIR_MAX]; |
| 12 | + u8 init[IP_CT_DIR_MAX]; | |
| 12 | 13 | u8 last_dir; |
| 13 | 14 | u8 flags; |
| 14 | 15 | }; |
| @@ -206,6 +206,14 @@ static inline int pmd_young(pmd_t pmd) · 205 unmodified lines | ||
| 206 | 206 | #endif |
| 207 | 207 | |
| 208 | 208 | #ifndef set_ptes |
| 209 | + | |
| 210 | +#ifndef pte_next_pfn | |
| 211 | +static inline pte_t pte_next_pfn(pte_t pte) | |
| 212 | +{ | |
| 213 | + return __pte(pte_val(pte) + (1UL << PFN_PTE_SHIFT)); | |
| 214 | +} | |
| 215 | +#endif | |
| 216 | + | |
| 209 | 217 | /** |
| 210 | 218 | * set_ptes - Map consecutive pages to a contiguous range of addresses. |
| 211 | 219 | * @mm: Address space to map the pages into. |
| @@ -231,7 +239,7 @@ static inline void set_ptes(struct mm_struct *mm, unsigned long addr, · 19 unmodified lines | ||
| 231 | 239 | if (--nr == 0) |
| 232 | 240 | break; |
| 233 | 241 | ptep++; |
| 234 | − pte = __pte(pte_val(pte) + (1UL << PFN_PTE_SHIFT)); | |
| 242 | + pte = pte_next_pfn(pte); | |
| 235 | 243 | } |
| 236 | 244 | arch_leave_lazy_mmu_mode(); |
| 237 | 245 | } |
| @@ -55,7 +55,7 @@ static inline void resume_user_mode_work(struct pt_regs *regs) · 54 unmodified lines | ||
| 55 | 55 | } |
| 56 | 56 | #endif |
| 57 | 57 | |
| 58 | − mem_cgroup_handle_over_high(); | |
| 58 | + mem_cgroup_handle_over_high(GFP_KERNEL); | |
| 59 | 59 | blkcg_maybe_throttle_current(); |
| 60 | 60 | |
| 61 | 61 | rseq_handle_notify_resume(NULL, regs); |
| @@ -512,8 +512,8 @@ do { \ · 511 unmodified lines | ||
| 512 | 512 | |
| 513 | 513 | static inline void do_write_seqcount_begin_nested(seqcount_t *s, int subclass) |
| 514 | 514 | { |
| 515 | − do_raw_write_seqcount_begin(s); | |
| 516 | 515 | seqcount_acquire(&s->dep_map, subclass, 0, _RET_IP_); |
| 516 | + do_raw_write_seqcount_begin(s); | |
| 517 | 517 | } |
| 518 | 518 | |
| 519 | 519 | /** |
| @@ -172,14 +172,23 @@ static inline bool is_swiotlb_buffer(struct device *dev, phys_addr_t paddr) · 171 unmodified lines | ||
| 172 | 172 | if (!mem) |
| 173 | 173 | return false; |
| 174 | 174 | |
| 175 | − if (IS_ENABLED(CONFIG_SWIOTLB_DYNAMIC)) { | |
| 176 | − /* Pairs with smp_wmb() in swiotlb_find_slots() and | |
| 177 | − * swiotlb_dyn_alloc(), which modify the RCU lists. | |
| 178 | − */ | |
| 179 | − smp_rmb(); | |
| 180 | − return swiotlb_find_pool(dev, paddr); | |
| 181 | − } | |
| 175 | +#ifdef CONFIG_SWIOTLB_DYNAMIC | |
| 176 | + /* | |
| 177 | + * All SWIOTLB buffer addresses must have been returned by | |
| 178 | + * swiotlb_tbl_map_single() and passed to a device driver. | |
| 179 | + * If a SWIOTLB address is checked on another CPU, then it was | |
| 180 | + * presumably loaded by the device driver from an unspecified private | |
| 181 | + * data structure. Make sure that this load is ordered before reading | |
| 182 | + * dev->dma_uses_io_tlb here and mem->pools in swiotlb_find_pool(). | |
| 183 | + * | |
| 184 | + * This barrier pairs with smp_mb() in swiotlb_find_slots(). | |
| 185 | + */ | |
| 186 | + smp_rmb(); | |
| 187 | + return READ_ONCE(dev->dma_uses_io_tlb) && | |
| 188 | + swiotlb_find_pool(dev, paddr); | |
| 189 | +#else | |
| 182 | 190 | return paddr >= mem->defpool.start && paddr < mem->defpool.end; |
| 191 | +#endif | |
| 183 | 192 | } |
| 184 | 193 | |
| 185 | 194 | static inline bool is_swiotlb_force_bounce(struct device *dev) |
| @@ -350,7 +350,7 @@ struct hci_dev { · 349 unmodified lines | ||
| 350 | 350 | struct list_head list; |
| 351 | 351 | struct mutex lock; |
| 352 | 352 | |
| 353 | − char name[8]; | |
| 353 | + const char *name; | |
| 354 | 354 | unsigned long flags; |
| 355 | 355 | __u16 id; |
| 356 | 356 | __u8 bus; |
| @@ -5941,6 +5941,7 @@ void wiphy_delayed_work_cancel(struct wiphy *wiphy, · 5940 unmodified lines | ||
| 5941 | 5941 | * @event_lock: (private) lock for event list |
| 5942 | 5942 | * @owner_nlportid: (private) owner socket port ID |
| 5943 | 5943 | * @nl_owner_dead: (private) owner socket went away |
| 5944 | + * @cqm_rssi_work: (private) CQM RSSI reporting work | |
| 5944 | 5945 | * @cqm_config: (private) nl80211 RSSI monitor state |
| 5945 | 5946 | * @pmsr_list: (private) peer measurement requests |
| 5946 | 5947 | * @pmsr_lock: (private) peer measurements requests/results lock |
| @@ -6013,7 +6014,8 @@ struct wireless_dev { · 66 unmodified lines | ||
| 6013 | 6014 | } wext; |
| 6014 | 6015 | #endif |
| 6015 | 6016 | |
| 6016 | − struct cfg80211_cqm_config *cqm_config; | |
| 6017 | + struct wiphy_work cqm_rssi_work; | |
| 6018 | + struct cfg80211_cqm_config __rcu *cqm_config; | |
| 6017 | 6019 | |
| 6018 | 6020 | struct list_head pmsr_list; |
| 6019 | 6021 | spinlock_t pmsr_lock; |
| @@ -7231,7 +7233,7 @@ struct cfg80211_rx_assoc_resp { · 1211 unmodified lines | ||
| 7231 | 7233 | int uapsd_queues; |
| 7232 | 7234 | const u8 *ap_mld_addr; |
| 7233 | 7235 | struct { |
| 7234 | − const u8 *addr; | |
| 7236 | + u8 addr[ETH_ALEN] __aligned(2); | |
| 7235 | 7237 | struct cfg80211_bss *bss; |
| 7236 | 7238 | u16 status; |
| 7237 | 7239 | } links[IEEE80211_MLD_MAX_NUM_LINKS]; |
| @@ -154,6 +154,7 @@ struct fib_info { · 153 unmodified lines | ||
| 154 | 154 | int fib_nhs; |
| 155 | 155 | bool fib_nh_is_v6; |
| 156 | 156 | bool nh_updated; |
| 157 | + bool pfsrc_removed; | |
| 157 | 158 | struct nexthop *nh; |
| 158 | 159 | struct rcu_head rcu; |
| 159 | 160 | struct fib_nh fib_nh[] __counted_by(fib_nhs); |
| @@ -103,9 +103,10 @@ struct mana_txq { · 102 unmodified lines | ||
| 103 | 103 | |
| 104 | 104 | /* skb data and frags dma mappings */ |
| 105 | 105 | struct mana_skb_head { |
| 106 | − dma_addr_t dma_handle[MAX_SKB_FRAGS + 1]; | |
| 106 | + /* GSO pkts may have 2 SGEs for the linear part*/ | |
| 107 | + dma_addr_t dma_handle[MAX_SKB_FRAGS + 2]; | |
| 107 | 108 | |
| 108 | − u32 size[MAX_SKB_FRAGS + 1]; | |
| 109 | + u32 size[MAX_SKB_FRAGS + 2]; | |
| 109 | 110 | }; |
| 110 | 111 | |
| 111 | 112 | #define MANA_HEADROOM sizeof(struct mana_skb_head) |
| @@ -539,7 +539,7 @@ static inline int neigh_output(struct neighbour *n, struct sk_buff *skb, · 538 unmodified lines | ||
| 539 | 539 | READ_ONCE(hh->hh_len)) |
| 540 | 540 | return neigh_hh_output(hh, skb); |
| 541 | 541 | |
| 542 | − return n->output(n, skb); | |
| 542 | + return READ_ONCE(n->output)(n, skb); | |
| 543 | 543 | } |
| 544 | 544 | |
| 545 | 545 | static inline struct neighbour * |
| @@ -16,13 +16,13 @@ · 15 unmodified lines | ||
| 16 | 16 | * page_pool_alloc_pages() call. Drivers should use |
| 17 | 17 | * page_pool_dev_alloc_pages() replacing dev_alloc_pages(). |
| 18 | 18 | * |
| 19 | − * API keeps track of in-flight pages, in order to let API user know | |
| 19 | + * The API keeps track of in-flight pages, in order to let API users know | |
| 20 | 20 | * when it is safe to free a page_pool object. Thus, API users |
| 21 | 21 | * must call page_pool_put_page() to free the page, or attach |
| 22 | − * the page to a page_pool-aware objects like skbs marked with | |
| 22 | + * the page to a page_pool-aware object like skbs marked with | |
| 23 | 23 | * skb_mark_for_recycle(). |
| 24 | 24 | * |
| 25 | − * API user must call page_pool_put_page() once on a page, as it | |
| 25 | + * API users must call page_pool_put_page() once on a page, as it | |
| 26 | 26 | * will either recycle the page, or in case of refcnt > 1, it will |
| 27 | 27 | * release the DMA mapping and in-flight state accounting. |
| 28 | 28 | */ |
| @@ -348,12 +348,14 @@ ssize_t tcp_splice_read(struct socket *sk, loff_t *ppos, · 347 unmodified lines | ||
| 348 | 348 | struct sk_buff *tcp_stream_alloc_skb(struct sock *sk, gfp_t gfp, |
| 349 | 349 | bool force_schedule); |
| 350 | 350 | |
| 351 | −static inline void tcp_dec_quickack_mode(struct sock *sk, | |
| 352 | − const unsigned int pkts) | |
| 351 | +static inline void tcp_dec_quickack_mode(struct sock *sk) | |
| 353 | 352 | { |
| 354 | 353 | struct inet_connection_sock *icsk = inet_csk(sk); |
| 355 | 354 | |
| 356 | 355 | if (icsk->icsk_ack.quick) { |
| 356 | + /* How many ACKs S/ACKing new data have we sent? */ | |
| 357 | + const unsigned int pkts = inet_csk_ack_scheduled(sk) ? 1 : 0; | |
| 358 | + | |
| 357 | 359 | if (pkts >= icsk->icsk_ack.quick) { |
| 358 | 360 | icsk->icsk_ack.quick = 0; |
| 359 | 361 | /* Leaving quickack mode we deflate ATO. */ |
| @@ -157,6 +157,9 @@ enum scsi_disposition { · 156 unmodified lines | ||
| 157 | 157 | #define SCSI_3 4 /* SPC */ |
| 158 | 158 | #define SCSI_SPC_2 5 |
| 159 | 159 | #define SCSI_SPC_3 6 |
| 160 | +#define SCSI_SPC_4 7 | |
| 161 | +#define SCSI_SPC_5 8 | |
| 162 | +#define SCSI_SPC_6 14 | |
| 160 | 163 | |
| 161 | 164 | /* |
| 162 | 165 | * INQ PERIPHERAL QUALIFIERS |
| @@ -161,6 +161,10 @@ struct scsi_device { · 160 unmodified lines | ||
| 161 | 161 | * pass settings from slave_alloc to scsi |
| 162 | 162 | * core. */ |
| 163 | 163 | unsigned int eh_timeout; /* Error handling timeout */ |
| 164 | + | |
| 165 | + bool manage_system_start_stop; /* Let HLD (sd) manage system start/stop */ | |
| 166 | + bool manage_runtime_start_stop; /* Let HLD (sd) manage runtime start/stop */ | |
| 167 | + | |
| 164 | 168 | unsigned removable:1; |
| 165 | 169 | unsigned changed:1; /* Data invalid due to media change */ |
| 166 | 170 | unsigned busy:1; /* Used to prevent races */ |
| @@ -193,7 +197,6 @@ struct scsi_device { · 26 unmodified lines | ||
| 193 | 197 | unsigned use_192_bytes_for_3f:1; /* ask for 192 bytes from page 0x3f */ |
| 194 | 198 | unsigned no_start_on_add:1; /* do not issue start on add */ |
| 195 | 199 | unsigned allow_restart:1; /* issue START_UNIT in error handler */ |
| 196 | − unsigned manage_start_stop:1; /* Let HLD (sd) manage start/stop */ | |
| 197 | 200 | unsigned no_start_on_resume:1; /* Do not issue START_STOP_UNIT on resume */ |
| 198 | 201 | unsigned start_stop_pwr_cond:1; /* Set power cond. in START_STOP_UNIT */ |
| 199 | 202 | unsigned no_uld_attach:1; /* disable connecting to upper level drivers */ |
| @@ -764,7 +764,7 @@ scsi_template_proc_dir(const struct scsi_host_template *sht); · 763 unmodified lines | ||
| 764 | 764 | #define scsi_template_proc_dir(sht) NULL |
| 765 | 765 | #endif |
| 766 | 766 | extern void scsi_scan_host(struct Scsi_Host *); |
| 767 | −extern void scsi_rescan_device(struct scsi_device *); | |
| 767 | +extern int scsi_rescan_device(struct scsi_device *sdev); | |
| 768 | 768 | extern void scsi_remove_host(struct Scsi_Host *); |
| 769 | 769 | extern struct Scsi_Host *scsi_host_get(struct Scsi_Host *); |
| 770 | 770 | extern int scsi_host_busy(struct Scsi_Host *shost); |
| @@ -29,6 +29,11 @@ · 28 unmodified lines | ||
| 29 | 29 | struct TAG { MEMBERS } ATTRS NAME; \ |
| 30 | 30 | } |
| 31 | 31 | |
| 32 | +#ifdef __cplusplus | |
| 33 | +/* sizeof(struct{}) is 1 in C++, not 0, can't use C version of the macro. */ | |
| 34 | +#define __DECLARE_FLEX_ARRAY(T, member) \ | |
| 35 | + T member[0] | |
| 36 | +#else | |
| 32 | 37 | /** |
| 33 | 38 | * __DECLARE_FLEX_ARRAY() - Declare a flexible array usable in a union |
| 34 | 39 | * |
| @@ -49,3 +54,5 @@ · 14 unmodified lines | ||
| 49 | 54 | #ifndef __counted_by |
| 50 | 55 | #define __counted_by(m) |
| 51 | 56 | #endif |
| 57 | + | |
| 58 | +#endif /* _UAPI_LINUX_STDDEF_H */ | |
| @@ -243,7 +243,7 @@ int io_linkat_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe) · 242 unmodified lines | ||
| 243 | 243 | struct io_link *lnk = io_kiocb_to_cmd(req, struct io_link); |
| 244 | 244 | const char __user *oldf, *newf; |
| 245 | 245 | |
| 246 | − if (sqe->rw_flags || sqe->buf_index || sqe->splice_fd_in) | |
| 246 | + if (sqe->buf_index || sqe->splice_fd_in) | |
| 247 | 247 | return -EINVAL; |
| 248 | 248 | if (unlikely(req->flags & REQ_F_FIXED_FILE)) |
| 249 | 249 | return -EBADF; |
| @@ -973,37 +973,31 @@ void notrace *bpf_mem_cache_alloc_flags(struct bpf_mem_alloc *ma, gfp_t flags) · 972 unmodified lines | ||
| 973 | 973 | return !ret ? NULL : ret + LLIST_NODE_SZ; |
| 974 | 974 | } |
| 975 | 975 | |
| 976 | −/* Most of the logic is taken from setup_kmalloc_cache_index_table() */ | |
| 977 | 976 | static __init int bpf_mem_cache_adjust_size(void) |
| 978 | 977 | { |
| 979 | − unsigned int size, index; | |
| 978 | + unsigned int size; | |
| 980 | 979 | |
| 981 | − /* Normally KMALLOC_MIN_SIZE is 8-bytes, but it can be | |
| 982 | − * up-to 256-bytes. | |
| 980 | + /* Adjusting the indexes in size_index() according to the object_size | |
| 981 | + * of underlying slab cache, so bpf_mem_alloc() will select a | |
| 982 | + * bpf_mem_cache with unit_size equal to the object_size of | |
| 983 | + * the underlying slab cache. | |
| 984 | + * | |
| 985 | + * The maximal value of KMALLOC_MIN_SIZE and __kmalloc_minalign() is | |
| 986 | + * 256-bytes, so only do adjustment for [8-bytes, 192-bytes]. | |
| 983 | 987 | */ |
| 984 | − size = KMALLOC_MIN_SIZE; | |
| 985 | − if (size <= 192) | |
| 986 | − index = size_index[(size - 1) / 8]; | |
| 987 | − else | |
| 988 | − index = fls(size - 1) - 1; | |
| 989 | − for (size = 8; size < KMALLOC_MIN_SIZE && size <= 192; size += 8) | |
| 990 | − size_index[(size - 1) / 8] = index; | |
| 988 | + for (size = 192; size >= 8; size -= 8) { | |
| 989 | + unsigned int kmalloc_size, index; | |
| 991 | 990 | |
| 992 | − /* The minimal alignment is 64-bytes, so disable 96-bytes cache and | |
| 993 | − * use 128-bytes cache instead. | |
| 994 | − */ | |
| 995 | − if (KMALLOC_MIN_SIZE >= 64) { | |
| 996 | − index = size_index[(128 - 1) / 8]; | |
| 997 | − for (size = 64 + 8; size <= 96; size += 8) | |
| 998 | − size_index[(size - 1) / 8] = index; | |
| 999 | − } | |
| 991 | + kmalloc_size = kmalloc_size_roundup(size); | |
| 992 | + if (kmalloc_size == size) | |
| 993 | + continue; | |
| 1000 | 994 | |
| 1001 | − /* The minimal alignment is 128-bytes, so disable 192-bytes cache and | |
| 1002 | − * use 256-bytes cache instead. | |
| 1003 | − */ | |
| 1004 | − if (KMALLOC_MIN_SIZE >= 128) { | |
| 1005 | − index = fls(256 - 1) - 1; | |
| 1006 | − for (size = 128 + 8; size <= 192; size += 8) | |
| 995 | + if (kmalloc_size <= 192) | |
| 996 | + index = size_index[(kmalloc_size - 1) / 8]; | |
| 997 | + else | |
| 998 | + index = fls(kmalloc_size - 1) - 1; | |
| 999 | + /* Only overwrite if necessary */ | |
| 1000 | + if (size_index[(size - 1) / 8] != index) | |
| 1007 | 1001 | size_index[(size - 1) / 8] = index; |
| 1008 | 1002 | } |
| 1009 | 1003 | |
| @@ -253,6 +253,9 @@ int bpf_mprog_attach(struct bpf_mprog_entry *entry, · 252 unmodified lines | ||
| 253 | 253 | goto out; |
| 254 | 254 | } |
| 255 | 255 | idx = tidx; |
| 256 | + } else if (bpf_mprog_total(entry) == bpf_mprog_max()) { | |
| 257 | + ret = -ERANGE; | |
| 258 | + goto out; | |
| 256 | 259 | } |
| 257 | 260 | if (flags & BPF_F_BEFORE) { |
| 258 | 261 | tidx = bpf_mprog_pos_before(entry, &rtuple); |
| @@ -4132,11 +4132,9 @@ static int __mark_chain_precision(struct bpf_verifier_env *env, int regno) · 4131 unmodified lines | ||
| 4132 | 4132 | bitmap_from_u64(mask, bt_reg_mask(bt)); |
| 4133 | 4133 | for_each_set_bit(i, mask, 32) { |
| 4134 | 4134 | reg = &st->frame[0]->regs[i]; |
| 4135 | − if (reg->type != SCALAR_VALUE) { | |
| 4136 | − bt_clear_reg(bt, i); | |
| 4137 | − continue; | |
| 4138 | − } | |
| 4139 | − reg->precise = true; | |
| 4135 | + bt_clear_reg(bt, i); | |
| 4136 | + if (reg->type == SCALAR_VALUE) | |
| 4137 | + reg->precise = true; | |
| 4140 | 4138 | } |
| 4141 | 4139 | return 0; |
| 4142 | 4140 | } |
| @@ -739,6 +739,17 @@ subsys_initcall(crash_notes_memory_init); · 738 unmodified lines | ||
| 739 | 739 | #undef pr_fmt |
| 740 | 740 | #define pr_fmt(fmt) "crash hp: " fmt |
| 741 | 741 | |
| 742 | +/* | |
| 743 | + * Different than kexec/kdump loading/unloading/jumping/shrinking which | |
| 744 | + * usually rarely happen, there will be many crash hotplug events notified | |
| 745 | + * during one short period, e.g one memory board is hot added and memory | |
| 746 | + * regions are online. So mutex lock __crash_hotplug_lock is used to | |
| 747 | + * serialize the crash hotplug handling specifically. | |
| 748 | + */ | |
| 749 | +DEFINE_MUTEX(__crash_hotplug_lock); | |
| 750 | +#define crash_hotplug_lock() mutex_lock(&__crash_hotplug_lock) | |
| 751 | +#define crash_hotplug_unlock() mutex_unlock(&__crash_hotplug_lock) | |
| 752 | + | |
| 742 | 753 | /* |
| 743 | 754 | * This routine utilized when the crash_hotplug sysfs node is read. |
| 744 | 755 | * It reflects the kernel's ability/permission to update the crash |
| @@ -748,9 +759,11 @@ int crash_check_update_elfcorehdr(void) · 3 unmodified lines | ||
| 748 | 759 | { |
| 749 | 760 | int rc = 0; |
| 750 | 761 | |
| 762 | + crash_hotplug_lock(); | |
| 751 | 763 | /* Obtain lock while reading crash information */ |
| 752 | 764 | if (!kexec_trylock()) { |
| 753 | 765 | pr_info("kexec_trylock() failed, elfcorehdr may be inaccurate\n"); |
| 766 | + crash_hotplug_unlock(); | |
| 754 | 767 | return 0; |
| 755 | 768 | } |
| 756 | 769 | if (kexec_crash_image) { |
| @@ -761,6 +774,7 @@ int crash_check_update_elfcorehdr(void) · 4 unmodified lines | ||
| 761 | 774 | } |
| 762 | 775 | /* Release lock now that update complete */ |
| 763 | 776 | kexec_unlock(); |
| 777 | + crash_hotplug_unlock(); | |
| 764 | 778 | |
| 765 | 779 | return rc; |
| 766 | 780 | } |
| @@ -783,9 +797,11 @@ static void crash_handle_hotplug_event(unsigned int hp_action, unsigned int cpu) · 16 unmodified lines | ||
| 783 | 797 | { |
| 784 | 798 | struct kimage *image; |
| 785 | 799 | |
| 800 | + crash_hotplug_lock(); | |
| 786 | 801 | /* Obtain lock while changing crash information */ |
| 787 | 802 | if (!kexec_trylock()) { |
| 788 | 803 | pr_info("kexec_trylock() failed, elfcorehdr may be inaccurate\n"); |
| 804 | + crash_hotplug_unlock(); | |
| 789 | 805 | return; |
| 790 | 806 | } |
| 791 | 807 | |
| @@ -852,6 +868,7 @@ static void crash_handle_hotplug_event(unsigned int hp_action, unsigned int cpu) · 60 unmodified lines | ||
| 852 | 868 | out: |
| 853 | 869 | /* Release lock now that update complete */ |
| 854 | 870 | kexec_unlock(); |
| 871 | + crash_hotplug_unlock(); | |
| 855 | 872 | } |
| 856 | 873 | |
| 857 | 874 | static int crash_memhp_notifier(struct notifier_block *nb, unsigned long val, void *v) |
| @@ -399,14 +399,13 @@ void __init swiotlb_init_remap(bool addressing_limit, unsigned int flags, · 398 unmodified lines | ||
| 399 | 399 | } |
| 400 | 400 | |
| 401 | 401 | mem->areas = memblock_alloc(array_size(sizeof(struct io_tlb_area), |
| 402 | − default_nareas), SMP_CACHE_BYTES); | |
| 402 | + nareas), SMP_CACHE_BYTES); | |
| 403 | 403 | if (!mem->areas) { |
| 404 | 404 | pr_warn("%s: Failed to allocate mem->areas.\n", __func__); |
| 405 | 405 | return; |
| 406 | 406 | } |
| 407 | 407 | |
| 408 | − swiotlb_init_io_tlb_pool(mem, __pa(tlb), nslabs, false, | |
| 409 | − default_nareas); | |
| 408 | + swiotlb_init_io_tlb_pool(mem, __pa(tlb), nslabs, false, nareas); | |
| 410 | 409 | add_mem_pool(&io_tlb_default_mem, mem); |
| 411 | 410 | |
| 412 | 411 | if (flags & SWIOTLB_VERBOSE) |
| @@ -729,9 +728,6 @@ static void swiotlb_dyn_alloc(struct work_struct *work) · 316 unmodified lines | ||
| 729 | 728 | } |
| 730 | 729 | |
| 731 | 730 | add_mem_pool(mem, pool); |
| 732 | − | |
| 733 | − /* Pairs with smp_rmb() in is_swiotlb_buffer(). */ | |
| 734 | − smp_wmb(); | |
| 735 | 731 | } |
| 736 | 732 | |
| 737 | 733 | /** |
| @@ -1152,9 +1148,26 @@ static int swiotlb_find_slots(struct device *dev, phys_addr_t orig_addr, · 414 unmodified lines | ||
| 1152 | 1148 | spin_unlock_irqrestore(&dev->dma_io_tlb_lock, flags); |
| 1153 | 1149 | |
| 1154 | 1150 | found: |
| 1155 | − dev->dma_uses_io_tlb = true; | |
| 1156 | − /* Pairs with smp_rmb() in is_swiotlb_buffer() */ | |
| 1157 | − smp_wmb(); | |
| 1151 | + WRITE_ONCE(dev->dma_uses_io_tlb, true); | |
| 1152 | + | |
| 1153 | + /* | |
| 1154 | + * The general barrier orders reads and writes against a presumed store | |
| 1155 | + * of the SWIOTLB buffer address by a device driver (to a driver private | |
| 1156 | + * data structure). It serves two purposes. | |
| 1157 | + * | |
| 1158 | + * First, the store to dev->dma_uses_io_tlb must be ordered before the | |
| 1159 | + * presumed store. This guarantees that the returned buffer address | |
| 1160 | + * cannot be passed to another CPU before updating dev->dma_uses_io_tlb. | |
| 1161 | + * | |
| 1162 | + * Second, the load from mem->pools must be ordered before the same | |
| 1163 | + * presumed store. This guarantees that the returned buffer address | |
| 1164 | + * cannot be observed by another CPU before an update of the RCU list | |
| 1165 | + * that was made by swiotlb_dyn_alloc() on a third CPU (cf. multicopy | |
| 1166 | + * atomicity). | |
| 1167 | + * | |
| 1168 | + * See also the comment in is_swiotlb_buffer(). | |
| 1169 | + */ | |
| 1170 | + smp_mb(); | |
| 1158 | 1171 | |
| 1159 | 1172 | *retpool = pool; |
| 1160 | 1173 | return index; |
| @@ -609,7 +609,7 @@ int pidfd_create(struct pid *pid, unsigned int flags) · 608 unmodified lines | ||
| 609 | 609 | } |
| 610 | 610 | |
| 611 | 611 | /** |
| 612 | − * pidfd_open() - Open new pid file descriptor. | |
| 612 | + * sys_pidfd_open() - Open new pid file descriptor. | |
| 613 | 613 | * |
| 614 | 614 | * @pid: pid for which to retrieve a pidfd |
| 615 | 615 | * @flags: flags to pass |
| @@ -9269,7 +9269,7 @@ void __init init_idle(struct task_struct *idle, int cpu) · 9268 unmodified lines | ||
| 9269 | 9269 | * PF_KTHREAD should already be set at this point; regardless, make it |
| 9270 | 9270 | * look like a proper per-CPU kthread. |
| 9271 | 9271 | */ |
| 9272 | − idle->flags |= PF_IDLE | PF_KTHREAD | PF_NO_SETAFFINITY; | |
| 9272 | + idle->flags |= PF_KTHREAD | PF_NO_SETAFFINITY; | |
| 9273 | 9273 | kthread_set_per_cpu(idle, cpu); |
| 9274 | 9274 | |
| 9275 | 9275 | #ifdef CONFIG_SMP |
| @@ -101,6 +101,7 @@ static inline int __cpupri_find(struct cpupri *cp, struct task_struct *p, · 100 unmodified lines | ||
| 101 | 101 | |
| 102 | 102 | if (lowest_mask) { |
| 103 | 103 | cpumask_and(lowest_mask, &p->cpus_mask, vec->mask); |
| 104 | + cpumask_and(lowest_mask, lowest_mask, cpu_active_mask); | |
| 104 | 105 | |
| 105 | 106 | /* |
| 106 | 107 | * We have to ensure that we have at least one bit |
| @@ -373,6 +373,7 @@ EXPORT_SYMBOL_GPL(play_idle_precise); · 372 unmodified lines | ||
| 373 | 373 | |
| 374 | 374 | void cpu_startup_entry(enum cpuhp_state state) |
| 375 | 375 | { |
| 376 | + current->flags |= PF_IDLE; | |
| 376 | 377 | arch_cpu_idle_prepare(); |
| 377 | 378 | cpuhp_online_idle(state); |
| 378 | 379 | while (1) |
| @@ -78,6 +78,7 @@ int task_work_add(struct task_struct *task, struct callback_head *work, · 77 unmodified lines | ||
| 78 | 78 | * task_work_cancel_match - cancel a pending work added by task_work_add() |
| 79 | 79 | * @task: the task which should execute the work |
| 80 | 80 | * @match: match function to call |
| 81 | + * @data: data to be passed in to match function | |
| 81 | 82 | * |
| 82 | 83 | * RETURNS: |
| 83 | 84 | * The found work or NULL if not found. |
| @@ -354,6 +354,11 @@ static void rb_init_page(struct buffer_data_page *bpage) · 353 unmodified lines | ||
| 354 | 354 | local_set(&bpage->commit, 0); |
| 355 | 355 | } |
| 356 | 356 | |
| 357 | +static __always_inline unsigned int rb_page_commit(struct buffer_page *bpage) | |
| 358 | +{ | |
| 359 | + return local_read(&bpage->page->commit); | |
| 360 | +} | |
| 361 | + | |
| 357 | 362 | static void free_buffer_page(struct buffer_page *bpage) |
| 358 | 363 | { |
| 359 | 364 | free_page((unsigned long)bpage->page); |
| @@ -1132,6 +1137,9 @@ __poll_t ring_buffer_poll_wait(struct trace_buffer *buffer, int cpu, · 772 unmodified lines | ||
| 1132 | 1137 | if (full) { |
| 1133 | 1138 | poll_wait(filp, &work->full_waiters, poll_table); |
| 1134 | 1139 | work->full_waiters_pending = true; |
| 1140 | + if (!cpu_buffer->shortest_full || | |
| 1141 | + cpu_buffer->shortest_full > full) | |
| 1142 | + cpu_buffer->shortest_full = full; | |
| 1135 | 1143 | } else { |
| 1136 | 1144 | poll_wait(filp, &work->waiters, poll_table); |
| 1137 | 1145 | work->waiters_pending = true; |
| @@ -2003,7 +2011,7 @@ rb_remove_pages(struct ring_buffer_per_cpu *cpu_buffer, unsigned long nr_pages) · 865 unmodified lines | ||
| 2003 | 2011 | * Increment overrun to account for the lost events. |
| 2004 | 2012 | */ |
| 2005 | 2013 | local_add(page_entries, &cpu_buffer->overrun); |
| 2006 | − local_sub(BUF_PAGE_SIZE, &cpu_buffer->entries_bytes); | |
| 2014 | + local_sub(rb_page_commit(to_remove_page), &cpu_buffer->entries_bytes); | |
| 2007 | 2015 | local_inc(&cpu_buffer->pages_lost); |
| 2008 | 2016 | } |
| 2009 | 2017 | |
| @@ -2367,11 +2375,6 @@ rb_reader_event(struct ring_buffer_per_cpu *cpu_buffer) · 357 unmodified lines | ||
| 2367 | 2375 | cpu_buffer->reader_page->read); |
| 2368 | 2376 | } |
| 2369 | 2377 | |
| 2370 | −static __always_inline unsigned rb_page_commit(struct buffer_page *bpage) | |
| 2371 | −{ | |
| 2372 | − return local_read(&bpage->page->commit); | |
| 2373 | −} | |
| 2374 | − | |
| 2375 | 2378 | static struct ring_buffer_event * |
| 2376 | 2379 | rb_iter_head_event(struct ring_buffer_iter *iter) |
| 2377 | 2380 | { |
| @@ -2517,7 +2520,7 @@ rb_handle_head_page(struct ring_buffer_per_cpu *cpu_buffer, · 139 unmodified lines | ||
| 2517 | 2520 | * the counters. |
| 2518 | 2521 | */ |
| 2519 | 2522 | local_add(entries, &cpu_buffer->overrun); |
| 2520 | − local_sub(BUF_PAGE_SIZE, &cpu_buffer->entries_bytes); | |
| 2523 | + local_sub(rb_page_commit(next_page), &cpu_buffer->entries_bytes); | |
| 2521 | 2524 | local_inc(&cpu_buffer->pages_lost); |
| 2522 | 2525 | |
| 2523 | 2526 | /* |
| @@ -2660,9 +2663,6 @@ rb_reset_tail(struct ring_buffer_per_cpu *cpu_buffer, · 136 unmodified lines | ||
| 2660 | 2663 | |
| 2661 | 2664 | event = __rb_page_index(tail_page, tail); |
| 2662 | 2665 | |
| 2663 | − /* account for padding bytes */ | |
| 2664 | − local_add(BUF_PAGE_SIZE - tail, &cpu_buffer->entries_bytes); | |
| 2665 | − | |
| 2666 | 2666 | /* |
| 2667 | 2667 | * Save the original length to the meta data. |
| 2668 | 2668 | * This will be used by the reader to add lost event |
| @@ -2676,7 +2676,8 @@ rb_reset_tail(struct ring_buffer_per_cpu *cpu_buffer, · 7 unmodified lines | ||
| 2676 | 2676 | * write counter enough to allow another writer to slip |
| 2677 | 2677 | * in on this page. |
| 2678 | 2678 | * We put in a discarded commit instead, to make sure |
| 2679 | − * that this space is not used again. | |
| 2679 | + * that this space is not used again, and this space will | |
| 2680 | + * not be accounted into 'entries_bytes'. | |
| 2680 | 2681 | * |
| 2681 | 2682 | * If we are less than the minimum size, we don't need to |
| 2682 | 2683 | * worry about it. |
| @@ -2701,6 +2702,9 @@ rb_reset_tail(struct ring_buffer_per_cpu *cpu_buffer, · 18 unmodified lines | ||
| 2701 | 2702 | /* time delta must be non zero */ |
| 2702 | 2703 | event->time_delta = 1; |
| 2703 | 2704 | |
| 2705 | + /* account for padding bytes */ | |
| 2706 | + local_add(BUF_PAGE_SIZE - tail, &cpu_buffer->entries_bytes); | |
| 2707 | + | |
| 2704 | 2708 | /* Make sure the padding is visible before the tail_page->write update */ |
| 2705 | 2709 | smp_wmb(); |
| 2706 | 2710 | |
| @@ -4215,7 +4219,7 @@ u64 ring_buffer_oldest_event_ts(struct trace_buffer *buffer, int cpu) · 1508 unmodified lines | ||
| 4215 | 4219 | EXPORT_SYMBOL_GPL(ring_buffer_oldest_event_ts); |
| 4216 | 4220 | |
| 4217 | 4221 | /** |
| 4218 | − * ring_buffer_bytes_cpu - get the number of bytes consumed in a cpu buffer | |
| 4222 | + * ring_buffer_bytes_cpu - get the number of bytes unconsumed in a cpu buffer | |
| 4219 | 4223 | * @buffer: The ring buffer |
| 4220 | 4224 | * @cpu: The per CPU buffer to read from. |
| 4221 | 4225 | */ |
| @@ -4723,6 +4727,7 @@ static void rb_advance_reader(struct ring_buffer_per_cpu *cpu_buffer) · 501 unmodified lines | ||
| 4723 | 4727 | |
| 4724 | 4728 | length = rb_event_length(event); |
| 4725 | 4729 | cpu_buffer->reader_page->read += length; |
| 4730 | + cpu_buffer->read_bytes += length; | |
| 4726 | 4731 | } |
| 4727 | 4732 | |
| 4728 | 4733 | static void rb_advance_iter(struct ring_buffer_iter *iter) |
| @@ -5816,7 +5821,7 @@ int ring_buffer_read_page(struct trace_buffer *buffer, · 1087 unmodified lines | ||
| 5816 | 5821 | } else { |
| 5817 | 5822 | /* update the entry counter */ |
| 5818 | 5823 | cpu_buffer->read += rb_page_entries(reader); |
| 5819 | − cpu_buffer->read_bytes += BUF_PAGE_SIZE; | |
| 5824 | + cpu_buffer->read_bytes += rb_page_commit(reader); | |
| 5820 | 5825 | |
| 5821 | 5826 | /* swap the pages */ |
| 5822 | 5827 | rb_init_page(bpage); |
| @@ -2770,6 +2770,7 @@ void trace_event_eval_update(struct trace_eval_map **map, int len) · 2769 unmodified lines | ||
| 2770 | 2770 | update_event_fields(call, map[i]); |
| 2771 | 2771 | } |
| 2772 | 2772 | } |
| 2773 | + cond_resched(); | |
| 2773 | 2774 | } |
| 2774 | 2775 | up_write(&trace_event_sem); |
| 2775 | 2776 | } |
| @@ -127,8 +127,13 @@ struct user_event_enabler { · 126 unmodified lines | ||
| 127 | 127 | /* Bit 7 is for freeing status of enablement */ |
| 128 | 128 | #define ENABLE_VAL_FREEING_BIT 7 |
| 129 | 129 | |
| 130 | −/* Only duplicate the bit value */ | |
| 131 | −#define ENABLE_VAL_DUP_MASK ENABLE_VAL_BIT_MASK | |
| 130 | +/* Bit 8 is for marking 32-bit on 64-bit */ | |
| 131 | +#define ENABLE_VAL_32_ON_64_BIT 8 | |
| 132 | + | |
| 133 | +#define ENABLE_VAL_COMPAT_MASK (1 << ENABLE_VAL_32_ON_64_BIT) | |
| 134 | + | |
| 135 | +/* Only duplicate the bit and compat values */ | |
| 136 | +#define ENABLE_VAL_DUP_MASK (ENABLE_VAL_BIT_MASK | ENABLE_VAL_COMPAT_MASK) | |
| 132 | 137 | |
| 133 | 138 | #define ENABLE_BITOPS(e) (&(e)->values) |
| 134 | 139 | |
| @@ -174,6 +179,30 @@ struct user_event_validator { · 39 unmodified lines | ||
| 174 | 179 | int flags; |
| 175 | 180 | }; |
| 176 | 181 | |
| 182 | +static inline void align_addr_bit(unsigned long *addr, int *bit, | |
| 183 | + unsigned long *flags) | |
| 184 | +{ | |
| 185 | + if (IS_ALIGNED(*addr, sizeof(long))) { | |
| 186 | +#ifdef __BIG_ENDIAN | |
| 187 | + /* 32 bit on BE 64 bit requires a 32 bit offset when aligned. */ | |
| 188 | + if (test_bit(ENABLE_VAL_32_ON_64_BIT, flags)) | |
| 189 | + *bit += 32; | |
| 190 | +#endif | |
| 191 | + return; | |
| 192 | + } | |
| 193 | + | |
| 194 | + *addr = ALIGN_DOWN(*addr, sizeof(long)); | |
| 195 | + | |
| 196 | + /* | |
| 197 | + * We only support 32 and 64 bit values. The only time we need | |
| 198 | + * to align is a 32 bit value on a 64 bit kernel, which on LE | |
| 199 | + * is always 32 bits, and on BE requires no change when unaligned. | |
| 200 | + */ | |
| 201 | +#ifdef __LITTLE_ENDIAN | |
| 202 | + *bit += 32; | |
| 203 | +#endif | |
| 204 | +} | |
| 205 | + | |
| 177 | 206 | typedef void (*user_event_func_t) (struct user_event *user, struct iov_iter *i, |
| 178 | 207 | void *tpdata, bool *faulted); |
| 179 | 208 | |
| @@ -482,6 +511,7 @@ static int user_event_enabler_write(struct user_event_mm *mm, · 302 unmodified lines | ||
| 482 | 511 | unsigned long *ptr; |
| 483 | 512 | struct page *page; |
| 484 | 513 | void *kaddr; |
| 514 | + int bit = ENABLE_BIT(enabler); | |
| 485 | 515 | int ret; |
| 486 | 516 | |
| 487 | 517 | lockdep_assert_held(&event_mutex); |
| @@ -497,6 +527,8 @@ static int user_event_enabler_write(struct user_event_mm *mm, · 9 unmodified lines | ||
| 497 | 527 | test_bit(ENABLE_VAL_FREEING_BIT, ENABLE_BITOPS(enabler)))) |
| 498 | 528 | return -EBUSY; |
| 499 | 529 | |
| 530 | + align_addr_bit(&uaddr, &bit, ENABLE_BITOPS(enabler)); | |
| 531 | + | |
| 500 | 532 | ret = pin_user_pages_remote(mm->mm, uaddr, 1, FOLL_WRITE | FOLL_NOFAULT, |
| 501 | 533 | &page, NULL); |
| 502 | 534 | |
| @@ -515,9 +547,9 @@ static int user_event_enabler_write(struct user_event_mm *mm, · 12 unmodified lines | ||
| 515 | 547 | |
| 516 | 548 | /* Update bit atomically, user tracers must be atomic as well */ |
| 517 | 549 | if (enabler->event && enabler->event->status) |
| 518 | − set_bit(ENABLE_BIT(enabler), ptr); | |
| 550 | + set_bit(bit, ptr); | |
| 519 | 551 | else |
| 520 | − clear_bit(ENABLE_BIT(enabler), ptr); | |
| 552 | + clear_bit(bit, ptr); | |
| 521 | 553 | |
| 522 | 554 | kunmap_local(kaddr); |
| 523 | 555 | unpin_user_pages_dirty_lock(&page, 1, true); |
| @@ -849,6 +881,12 @@ static struct user_event_enabler · 325 unmodified lines | ||
| 849 | 881 | enabler->event = user; |
| 850 | 882 | enabler->addr = uaddr; |
| 851 | 883 | enabler->values = reg->enable_bit; |
| 884 | + | |
| 885 | +#if BITS_PER_LONG >= 64 | |
| 886 | + if (reg->enable_size == 4) | |
| 887 | + set_bit(ENABLE_VAL_32_ON_64_BIT, ENABLE_BITOPS(enabler)); | |
| 888 | +#endif | |
| 889 | + | |
| 852 | 890 | retry: |
| 853 | 891 | /* Prevents state changes from racing with new enablers */ |
| 854 | 892 | mutex_lock(&event_mutex); |
| @@ -2377,7 +2415,8 @@ static long user_unreg_get(struct user_unreg __user *ureg, · 1522 unmodified lines | ||
| 2377 | 2415 | } |
| 2378 | 2416 | |
| 2379 | 2417 | static int user_event_mm_clear_bit(struct user_event_mm *user_mm, |
| 2380 | − unsigned long uaddr, unsigned char bit) | |
| 2418 | + unsigned long uaddr, unsigned char bit, | |
| 2419 | + unsigned long flags) | |
| 2381 | 2420 | { |
| 2382 | 2421 | struct user_event_enabler enabler; |
| 2383 | 2422 | int result; |
| @@ -2385,7 +2424,7 @@ static int user_event_mm_clear_bit(struct user_event_mm *user_mm, · 1 unmodified line | ||
| 2385 | 2424 | |
| 2386 | 2425 | memset(&enabler, 0, sizeof(enabler)); |
| 2387 | 2426 | enabler.addr = uaddr; |
| 2388 | − enabler.values = bit; | |
| 2427 | + enabler.values = bit | flags; | |
| 2389 | 2428 | retry: |
| 2390 | 2429 | /* Prevents state changes from racing with new enablers */ |
| 2391 | 2430 | mutex_lock(&event_mutex); |
| @@ -2415,6 +2454,7 @@ static long user_events_ioctl_unreg(unsigned long uarg) · 23 unmodified lines | ||
| 2415 | 2454 | struct user_event_mm *mm = current->user_event_mm; |
| 2416 | 2455 | struct user_event_enabler *enabler, *next; |
| 2417 | 2456 | struct user_unreg reg; |
| 2457 | + unsigned long flags; | |
| 2418 | 2458 | long ret; |
| 2419 | 2459 | |
| 2420 | 2460 | ret = user_unreg_get(ureg, ®); |
| @@ -2425,6 +2465,7 @@ static long user_events_ioctl_unreg(unsigned long uarg) · 4 unmodified lines | ||
| 2425 | 2465 | if (!mm) |
| 2426 | 2466 | return -ENOENT; |
| 2427 | 2467 | |
| 2468 | + flags = 0; | |
| 2428 | 2469 | ret = -ENOENT; |
| 2429 | 2470 | |
| 2430 | 2471 | /* |
| @@ -2441,6 +2482,9 @@ static long user_events_ioctl_unreg(unsigned long uarg) · 10 unmodified lines | ||
| 2441 | 2482 | ENABLE_BIT(enabler) == reg.disable_bit) { |
| 2442 | 2483 | set_bit(ENABLE_VAL_FREEING_BIT, ENABLE_BITOPS(enabler)); |
| 2443 | 2484 | |
| 2485 | + /* We must keep compat flags for the clear */ | |
| 2486 | + flags |= enabler->values & ENABLE_VAL_COMPAT_MASK; | |
| 2487 | + | |
| 2444 | 2488 | if (!test_bit(ENABLE_VAL_FAULTING_BIT, ENABLE_BITOPS(enabler))) |
| 2445 | 2489 | user_event_enabler_destroy(enabler, true); |
| 2446 | 2490 | |
| @@ -2454,7 +2498,7 @@ static long user_events_ioctl_unreg(unsigned long uarg) · 7 unmodified lines | ||
| 2454 | 2498 | /* Ensure bit is now cleared for user, regardless of event status */ |
| 2455 | 2499 | if (!ret) |
| 2456 | 2500 | ret = user_event_mm_clear_bit(mm, reg.disable_addr, |
| 2457 | − reg.disable_bit); | |
| 2501 | + reg.disable_bit, flags); | |
| 2458 | 2502 | |
| 2459 | 2503 | return ret; |
| 2460 | 2504 | } |
| @@ -6535,9 +6535,6 @@ void __init workqueue_init_early(void) · 6534 unmodified lines | ||
| 6535 | 6535 | |
| 6536 | 6536 | BUG_ON(!zalloc_cpumask_var_node(&pt->pod_cpus[0], GFP_KERNEL, NUMA_NO_NODE)); |
| 6537 | 6537 | |
| 6538 | − wq_update_pod_attrs_buf = alloc_workqueue_attrs(); | |
| 6539 | − BUG_ON(!wq_update_pod_attrs_buf); | |
| 6540 | − | |
| 6541 | 6538 | pt->nr_pods = 1; |
| 6542 | 6539 | cpumask_copy(pt->pod_cpus[0], cpu_possible_mask); |
| 6543 | 6540 | pt->pod_node[0] = NUMA_NO_NODE; |
| @@ -6605,13 +6602,13 @@ static void __init wq_cpu_intensive_thresh_init(void) · 61 unmodified lines | ||
| 6605 | 6602 | unsigned long thresh; |
| 6606 | 6603 | unsigned long bogo; |
| 6607 | 6604 | |
| 6605 | + pwq_release_worker = kthread_create_worker(0, "pool_workqueue_release"); | |
| 6606 | + BUG_ON(IS_ERR(pwq_release_worker)); | |
| 6607 | + | |
| 6608 | 6608 | /* if the user set it to a specific value, keep it */ |
| 6609 | 6609 | if (wq_cpu_intensive_thresh_us != ULONG_MAX) |
| 6610 | 6610 | return; |
| 6611 | 6611 | |
| 6612 | − pwq_release_worker = kthread_create_worker(0, "pool_workqueue_release"); | |
| 6613 | − BUG_ON(IS_ERR(pwq_release_worker)); | |
| 6614 | − | |
| 6615 | 6612 | /* |
| 6616 | 6613 | * The default of 10ms is derived from the fact that most modern (as of |
| 6617 | 6614 | * 2023) processors can do a lot in 10ms and that it's just below what |
| @@ -28,7 +28,7 @@ static int count_argc(const char *str) · 27 unmodified lines | ||
| 28 | 28 | |
| 29 | 29 | /** |
| 30 | 30 | * argv_free - free an argv |
| 31 | − * @argv - the argument vector to be freed | |
| 31 | + * @argv: the argument vector to be freed | |
| 32 | 32 | * |
| 33 | 33 | * Frees an argv and the strings it points to. |
| 34 | 34 | */ |
| @@ -46,7 +46,7 @@ EXPORT_SYMBOL(argv_free); · 11 unmodified lines | ||
| 46 | 46 | * @str: the string to be split |
| 47 | 47 | * @argcp: returned argument count |
| 48 | 48 | * |
| 49 | − * Returns an array of pointers to strings which are split out from | |
| 49 | + * Returns: an array of pointers to strings which are split out from | |
| 50 | 50 | * @str. This is performed by strictly splitting on white-space; no |
| 51 | 51 | * quote processing is performed. Multiple whitespace characters are |
| 52 | 52 | * considered to be a single argument separator. The returned array |
| @@ -256,6 +256,22 @@ bool mas_is_err(struct ma_state *mas) · 255 unmodified lines | ||
| 256 | 256 | return xa_is_err(mas->node); |
| 257 | 257 | } |
| 258 | 258 | |
| 259 | +static __always_inline bool mas_is_overflow(struct ma_state *mas) | |
| 260 | +{ | |
| 261 | + if (unlikely(mas->node == MAS_OVERFLOW)) | |
| 262 | + return true; | |
| 263 | + | |
| 264 | + return false; | |
| 265 | +} | |
| 266 | + | |
| 267 | +static __always_inline bool mas_is_underflow(struct ma_state *mas) | |
| 268 | +{ | |
| 269 | + if (unlikely(mas->node == MAS_UNDERFLOW)) | |
| 270 | + return true; | |
| 271 | + | |
| 272 | + return false; | |
| 273 | +} | |
| 274 | + | |
| 259 | 275 | static inline bool mas_searchable(struct ma_state *mas) |
| 260 | 276 | { |
| 261 | 277 | if (mas_is_none(mas)) |
| @@ -4415,10 +4431,13 @@ no_entry: · 4153 unmodified lines | ||
| 4415 | 4431 | * |
| 4416 | 4432 | * @mas: The maple state |
| 4417 | 4433 | * @max: The minimum starting range |
| 4434 | + * @empty: Can be empty | |
| 4435 | + * @set_underflow: Set the @mas->node to underflow state on limit. | |
| 4418 | 4436 | * |
| 4419 | 4437 | * Return: The entry in the previous slot which is possibly NULL |
| 4420 | 4438 | */ |
| 4421 | −static void *mas_prev_slot(struct ma_state *mas, unsigned long min, bool empty) | |
| 4439 | +static void *mas_prev_slot(struct ma_state *mas, unsigned long min, bool empty, | |
| 4440 | + bool set_underflow) | |
| 4422 | 4441 | { |
| 4423 | 4442 | void *entry; |
| 4424 | 4443 | void __rcu **slots; |
| @@ -4435,7 +4454,6 @@ retry: · 10 unmodified lines | ||
| 4435 | 4454 | if (unlikely(mas_rewalk_if_dead(mas, node, save_point))) |
| 4436 | 4455 | goto retry; |
| 4437 | 4456 | |
| 4438 | −again: | |
| 4439 | 4457 | if (mas->min <= min) { |
| 4440 | 4458 | pivot = mas_safe_min(mas, pivots, mas->offset); |
| 4441 | 4459 | |
| @@ -4443,9 +4461,10 @@ again: · 1 unmodified line | ||
| 4443 | 4461 | goto retry; |
| 4444 | 4462 | |
| 4445 | 4463 | if (pivot <= min) |
| 4446 | − return NULL; | |
| 4464 | + goto underflow; | |
| 4447 | 4465 | } |
| 4448 | 4466 | |
| 4467 | +again: | |
| 4449 | 4468 | if (likely(mas->offset)) { |
| 4450 | 4469 | mas->offset--; |
| 4451 | 4470 | mas->last = mas->index - 1; |
| @@ -4457,7 +4476,7 @@ again: · 5 unmodified lines | ||
| 4457 | 4476 | } |
| 4458 | 4477 | |
| 4459 | 4478 | if (mas_is_none(mas)) |
| 4460 | − return NULL; | |
| 4479 | + goto underflow; | |
| 4461 | 4480 | |
| 4462 | 4481 | mas->last = mas->max; |
| 4463 | 4482 | node = mas_mn(mas); |
| @@ -4474,10 +4493,19 @@ again: · 10 unmodified lines | ||
| 4474 | 4493 | if (likely(entry)) |
| 4475 | 4494 | return entry; |
| 4476 | 4495 | |
| 4477 | − if (!empty) | |
| 4496 | + if (!empty) { | |
| 4497 | + if (mas->index <= min) | |
| 4498 | + goto underflow; | |
| 4499 | + | |
| 4478 | 4500 | goto again; |
| 4501 | + } | |
| 4479 | 4502 | |
| 4480 | 4503 | return entry; |
| 4504 | + | |
| 4505 | +underflow: | |
| 4506 | + if (set_underflow) | |
| 4507 | + mas->node = MAS_UNDERFLOW; | |
| 4508 | + return NULL; | |
| 4481 | 4509 | } |
| 4482 | 4510 | |
| 4483 | 4511 | /* |
| @@ -4567,10 +4595,13 @@ no_entry: · 83 unmodified lines | ||
| 4567 | 4595 | * @mas: The maple state |
| 4568 | 4596 | * @max: The maximum starting range |
| 4569 | 4597 | * @empty: Can be empty |
| 4598 | + * @set_overflow: Should @mas->node be set to overflow when the limit is | |
| 4599 | + * reached. | |
| 4570 | 4600 | * |
| 4571 | 4601 | * Return: The entry in the next slot which is possibly NULL |
| 4572 | 4602 | */ |
| 4573 | −static void *mas_next_slot(struct ma_state *mas, unsigned long max, bool empty) | |
| 4603 | +static void *mas_next_slot(struct ma_state *mas, unsigned long max, bool empty, | |
| 4604 | + bool set_overflow) | |
| 4574 | 4605 | { |
| 4575 | 4606 | void __rcu **slots; |
| 4576 | 4607 | unsigned long *pivots; |
| @@ -4589,22 +4620,22 @@ retry: · 12 unmodified lines | ||
| 4589 | 4620 | if (unlikely(mas_rewalk_if_dead(mas, node, save_point))) |
| 4590 | 4621 | goto retry; |
| 4591 | 4622 | |
| 4592 | −again: | |
| 4593 | 4623 | if (mas->max >= max) { |
| 4594 | 4624 | if (likely(mas->offset < data_end)) |
| 4595 | 4625 | pivot = pivots[mas->offset]; |
| 4596 | 4626 | else |
| 4597 | − return NULL; /* must be mas->max */ | |
| 4627 | + goto overflow; | |
| 4598 | 4628 | |
| 4599 | 4629 | if (unlikely(mas_rewalk_if_dead(mas, node, save_point))) |
| 4600 | 4630 | goto retry; |
| 4601 | 4631 | |
| 4602 | 4632 | if (pivot >= max) |
| 4603 | − return NULL; | |
| 4633 | + goto overflow; | |
| 4604 | 4634 | } |
| 4605 | 4635 | |
| 4606 | 4636 | if (likely(mas->offset < data_end)) { |
| 4607 | 4637 | mas->index = pivots[mas->offset] + 1; |
| 4638 | +again: | |
| 4608 | 4639 | mas->offset++; |
| 4609 | 4640 | if (likely(mas->offset < data_end)) |
| 4610 | 4641 | mas->last = pivots[mas->offset]; |
| @@ -4616,8 +4647,11 @@ again: · 5 unmodified lines | ||
| 4616 | 4647 | goto retry; |
| 4617 | 4648 | } |
| 4618 | 4649 | |
| 4619 | − if (mas_is_none(mas)) | |
| 4650 | + if (WARN_ON_ONCE(mas_is_none(mas))) { | |
| 4651 | + mas->node = MAS_OVERFLOW; | |
| 4620 | 4652 | return NULL; |
| 4653 | + goto overflow; | |
| 4654 | + } | |
| 4621 | 4655 | |
| 4622 | 4656 | mas->offset = 0; |
| 4623 | 4657 | mas->index = mas->min; |
| @@ -4636,12 +4670,20 @@ again: · 12 unmodified lines | ||
| 4636 | 4670 | return entry; |
| 4637 | 4671 | |
| 4638 | 4672 | if (!empty) { |
| 4639 | − if (!mas->offset) | |
| 4640 | − data_end = 2; | |
| 4673 | + if (mas->last >= max) | |
| 4674 | + goto overflow; | |
| 4675 | + | |
| 4676 | + mas->index = mas->last + 1; | |
| 4677 | + /* Node cannot end on NULL, so it's safe to short-cut here */ | |
| 4641 | 4678 | goto again; |
| 4642 | 4679 | } |
| 4643 | 4680 | |
| 4644 | 4681 | return entry; |
| 4682 | + | |
| 4683 | +overflow: | |
| 4684 | + if (set_overflow) | |
| 4685 | + mas->node = MAS_OVERFLOW; | |
| 4686 | + return NULL; | |
| 4645 | 4687 | } |
| 4646 | 4688 | |
| 4647 | 4689 | /* |
| @@ -4651,17 +4693,20 @@ again: · 3 unmodified lines | ||
| 4651 | 4693 | * |
| 4652 | 4694 | * Set the @mas->node to the next entry and the range_start to |
| 4653 | 4695 | * the beginning value for the entry. Does not check beyond @limit. |
| 4654 | − * Sets @mas->index and @mas->last to the limit if it is hit. | |
| 4696 | + * Sets @mas->index and @mas->last to the range, Does not update @mas->index and | |
| 4697 | + * @mas->last on overflow. | |
| 4655 | 4698 | * Restarts on dead nodes. |
| 4656 | 4699 | * |
| 4657 | 4700 | * Return: the next entry or %NULL. |
| 4658 | 4701 | */ |
| 4659 | 4702 | static inline void *mas_next_entry(struct ma_state *mas, unsigned long limit) |
| 4660 | 4703 | { |
| 4661 | − if (mas->last >= limit) | |
| 4704 | + if (mas->last >= limit) { | |
| 4705 | + mas->node = MAS_OVERFLOW; | |
| 4662 | 4706 | return NULL; |
| 4707 | + } | |
| 4663 | 4708 | |
| 4664 | − return mas_next_slot(mas, limit, false); | |
| 4709 | + return mas_next_slot(mas, limit, false, true); | |
| 4665 | 4710 | } |
| 4666 | 4711 | |
| 4667 | 4712 | /* |
| @@ -4837,7 +4882,7 @@ void *mas_walk(struct ma_state *mas) · 169 unmodified lines | ||
| 4837 | 4882 | { |
| 4838 | 4883 | void *entry; |
| 4839 | 4884 | |
| 4840 | − if (mas_is_none(mas) || mas_is_paused(mas) || mas_is_ptr(mas)) | |
| 4885 | + if (!mas_is_active(mas) || !mas_is_start(mas)) | |
| 4841 | 4886 | mas->node = MAS_START; |
| 4842 | 4887 | retry: |
| 4843 | 4888 | entry = mas_state_walk(mas); |
| @@ -5294,14 +5339,22 @@ static inline void mte_destroy_walk(struct maple_enode *enode, · 450 unmodified lines | ||
| 5294 | 5339 | |
| 5295 | 5340 | static void mas_wr_store_setup(struct ma_wr_state *wr_mas) |
| 5296 | 5341 | { |
| 5297 | − if (mas_is_start(wr_mas->mas)) | |
| 5298 | − return; | |
| 5342 | + if (!mas_is_active(wr_mas->mas)) { | |
| 5343 | + if (mas_is_start(wr_mas->mas)) | |
| 5344 | + return; | |
| 5299 | 5345 | |
| 5300 | − if (unlikely(mas_is_paused(wr_mas->mas))) | |
| 5301 | − goto reset; | |
| 5346 | + if (unlikely(mas_is_paused(wr_mas->mas))) | |
| 5347 | + goto reset; | |
| 5302 | 5348 | |
| 5303 | − if (unlikely(mas_is_none(wr_mas->mas))) | |
| 5304 | − goto reset; | |
| 5349 | + if (unlikely(mas_is_none(wr_mas->mas))) | |
| 5350 | + goto reset; | |
| 5351 | + | |
| 5352 | + if (unlikely(mas_is_overflow(wr_mas->mas))) | |
| 5353 | + goto reset; | |
| 5354 | + | |
| 5355 | + if (unlikely(mas_is_underflow(wr_mas->mas))) | |
| 5356 | + goto reset; | |
| 5357 | + } | |
| 5305 | 5358 | |
| 5306 | 5359 | /* |
| 5307 | 5360 | * A less strict version of mas_is_span_wr() where we allow spanning |
| @@ -5595,8 +5648,25 @@ static inline bool mas_next_setup(struct ma_state *mas, unsigned long max, · 287 unmodified lines | ||
| 5595 | 5648 | { |
| 5596 | 5649 | bool was_none = mas_is_none(mas); |
| 5597 | 5650 | |
| 5598 | − if (mas_is_none(mas) || mas_is_paused(mas)) | |
| 5651 | + if (unlikely(mas->last >= max)) { | |
| 5652 | + mas->node = MAS_OVERFLOW; | |
| 5653 | + return true; | |
| 5654 | + } | |
| 5655 | + | |
| 5656 | + if (mas_is_active(mas)) | |
| 5657 | + return false; | |
| 5658 | + | |
| 5659 | + if (mas_is_none(mas) || mas_is_paused(mas)) { | |
| 5660 | + mas->node = MAS_START; | |
| 5661 | + } else if (mas_is_overflow(mas)) { | |
| 5662 | + /* Overflowed before, but the max changed */ | |
| 5599 | 5663 | mas->node = MAS_START; |
| 5664 | + } else if (mas_is_underflow(mas)) { | |
| 5665 | + mas->node = MAS_START; | |
| 5666 | + *entry = mas_walk(mas); | |
| 5667 | + if (*entry) | |
| 5668 | + return true; | |
| 5669 | + } | |
| 5600 | 5670 | |
| 5601 | 5671 | if (mas_is_start(mas)) |
| 5602 | 5672 | *entry = mas_walk(mas); /* Retries on dead nodes handled by mas_walk */ |
| @@ -5615,6 +5685,7 @@ static inline bool mas_next_setup(struct ma_state *mas, unsigned long max, · 12 unmodified lines | ||
| 5615 | 5685 | |
| 5616 | 5686 | if (mas_is_none(mas)) |
| 5617 | 5687 | return true; |
| 5688 | + | |
| 5618 | 5689 | return false; |
| 5619 | 5690 | } |
| 5620 | 5691 | |
| @@ -5637,7 +5708,7 @@ void *mas_next(struct ma_state *mas, unsigned long max) · 16 unmodified lines | ||
| 5637 | 5708 | return entry; |
| 5638 | 5709 | |
| 5639 | 5710 | /* Retries on dead nodes handled by mas_next_slot */ |
| 5640 | − return mas_next_slot(mas, max, false); | |
| 5711 | + return mas_next_slot(mas, max, false, true); | |
| 5641 | 5712 | } |
| 5642 | 5713 | EXPORT_SYMBOL_GPL(mas_next); |
| 5643 | 5714 | |
| @@ -5660,7 +5731,7 @@ void *mas_next_range(struct ma_state *mas, unsigned long max) · 16 unmodified lines | ||
| 5660 | 5731 | return entry; |
| 5661 | 5732 | |
| 5662 | 5733 | /* Retries on dead nodes handled by mas_next_slot */ |
| 5663 | − return mas_next_slot(mas, max, true); | |
| 5734 | + return mas_next_slot(mas, max, true, true); | |
| 5664 | 5735 | } |
| 5665 | 5736 | EXPORT_SYMBOL_GPL(mas_next_range); |
| 5666 | 5737 | |
| @@ -5691,18 +5762,31 @@ EXPORT_SYMBOL_GPL(mt_next); · 24 unmodified lines | ||
| 5691 | 5762 | static inline bool mas_prev_setup(struct ma_state *mas, unsigned long min, |
| 5692 | 5763 | void **entry) |
| 5693 | 5764 | { |
| 5694 | − if (mas->index <= min) | |
| 5695 | − goto none; | |
| 5765 | + if (unlikely(mas->index <= min)) { | |
| 5766 | + mas->node = MAS_UNDERFLOW; | |
| 5767 | + return true; | |
| 5768 | + } | |
| 5696 | 5769 | |
| 5697 | − if (mas_is_none(mas) || mas_is_paused(mas)) | |
| 5770 | + if (mas_is_active(mas)) | |
| 5771 | + return false; | |
| 5772 | + | |
| 5773 | + if (mas_is_overflow(mas)) { | |
| 5698 | 5774 | mas->node = MAS_START; |
| 5775 | + *entry = mas_walk(mas); | |
| 5776 | + if (*entry) | |
| 5777 | + return true; | |
| 5778 | + } | |
| 5699 | 5779 | |
| 5700 | − if (mas_is_start(mas)) { | |
| 5701 | − mas_walk(mas); | |
| 5702 | − if (!mas->index) | |
| 5703 | − goto none; | |
| 5780 | + if (mas_is_none(mas) || mas_is_paused(mas)) { | |
| 5781 | + mas->node = MAS_START; | |
| 5782 | + } else if (mas_is_underflow(mas)) { | |
| 5783 | + /* underflowed before but the min changed */ | |
| 5784 | + mas->node = MAS_START; | |
| 5704 | 5785 | } |
| 5705 | 5786 | |
| 5787 | + if (mas_is_start(mas)) | |
| 5788 | + mas_walk(mas); | |
| 5789 | + | |
| 5706 | 5790 | if (unlikely(mas_is_ptr(mas))) { |
| 5707 | 5791 | if (!mas->index) |
| 5708 | 5792 | goto none; |
| @@ -5747,7 +5831,7 @@ void *mas_prev(struct ma_state *mas, unsigned long min) · 38 unmodified lines | ||
| 5747 | 5831 | if (mas_prev_setup(mas, min, &entry)) |
| 5748 | 5832 | return entry; |
| 5749 | 5833 | |
| 5750 | − return mas_prev_slot(mas, min, false); | |
| 5834 | + return mas_prev_slot(mas, min, false, true); | |
| 5751 | 5835 | } |
| 5752 | 5836 | EXPORT_SYMBOL_GPL(mas_prev); |
| 5753 | 5837 | |
| @@ -5770,7 +5854,7 @@ void *mas_prev_range(struct ma_state *mas, unsigned long min) · 16 unmodified lines | ||
| 5770 | 5854 | if (mas_prev_setup(mas, min, &entry)) |
| 5771 | 5855 | return entry; |
| 5772 | 5856 | |
| 5773 | − return mas_prev_slot(mas, min, true); | |
| 5857 | + return mas_prev_slot(mas, min, true, true); | |
| 5774 | 5858 | } |
| 5775 | 5859 | EXPORT_SYMBOL_GPL(mas_prev_range); |
| 5776 | 5860 | |
| @@ -5828,24 +5912,35 @@ EXPORT_SYMBOL_GPL(mas_pause); · 51 unmodified lines | ||
| 5828 | 5912 | static inline bool mas_find_setup(struct ma_state *mas, unsigned long max, |
| 5829 | 5913 | void **entry) |
| 5830 | 5914 | { |
| 5831 | − *entry = NULL; | |
| 5915 | + if (mas_is_active(mas)) { | |
| 5916 | + if (mas->last < max) | |
| 5917 | + return false; | |
| 5832 | 5918 | |
| 5833 | − if (unlikely(mas_is_none(mas))) { | |
| 5919 | + return true; | |
| 5920 | + } | |
| 5921 | + | |
| 5922 | + if (mas_is_paused(mas)) { | |
| 5834 | 5923 | if (unlikely(mas->last >= max)) |
| 5835 | 5924 | return true; |
| 5836 | 5925 | |
| 5837 | − mas->index = mas->last; | |
| 5926 | + mas->index = ++mas->last; | |
| 5838 | 5927 | mas->node = MAS_START; |
| 5839 | − } else if (unlikely(mas_is_paused(mas))) { | |
| 5928 | + } else if (mas_is_none(mas)) { | |
| 5840 | 5929 | if (unlikely(mas->last >= max)) |
| 5841 | 5930 | return true; |
| 5842 | 5931 | |
| 5932 | + mas->index = mas->last; | |
| 5843 | 5933 | mas->node = MAS_START; |
| 5844 | − mas->index = ++mas->last; | |
| 5845 | − } else if (unlikely(mas_is_ptr(mas))) | |
| 5846 | − goto ptr_out_of_range; | |
| 5934 | + } else if (mas_is_overflow(mas) || mas_is_underflow(mas)) { | |
| 5935 | + if (mas->index > max) { | |
| 5936 | + mas->node = MAS_OVERFLOW; | |
| 5937 | + return true; | |
| 5938 | + } | |
| 5939 | + | |
| 5940 | + mas->node = MAS_START; | |
| 5941 | + } | |
| 5847 | 5942 | |
| 5848 | − if (unlikely(mas_is_start(mas))) { | |
| 5943 | + if (mas_is_start(mas)) { | |
| 5849 | 5944 | /* First run or continue */ |
| 5850 | 5945 | if (mas->index > max) |
| 5851 | 5946 | return true; |
| @@ -5895,7 +5990,7 @@ void *mas_find(struct ma_state *mas, unsigned long max) · 43 unmodified lines | ||
| 5895 | 5990 | return entry; |
| 5896 | 5991 | |
| 5897 | 5992 | /* Retries on dead nodes handled by mas_next_slot */ |
| 5898 | − return mas_next_slot(mas, max, false); | |
| 5993 | + return mas_next_slot(mas, max, false, false); | |
| 5899 | 5994 | } |
| 5900 | 5995 | EXPORT_SYMBOL_GPL(mas_find); |
| 5901 | 5996 | |
| @@ -5913,13 +6008,13 @@ EXPORT_SYMBOL_GPL(mas_find); · 11 unmodified lines | ||
| 5913 | 6008 | */ |
| 5914 | 6009 | void *mas_find_range(struct ma_state *mas, unsigned long max) |
| 5915 | 6010 | { |
| 5916 | − void *entry; | |
| 6011 | + void *entry = NULL; | |
| 5917 | 6012 | |
| 5918 | 6013 | if (mas_find_setup(mas, max, &entry)) |
| 5919 | 6014 | return entry; |
| 5920 | 6015 | |
| 5921 | 6016 | /* Retries on dead nodes handled by mas_next_slot */ |
| 5922 | − return mas_next_slot(mas, max, true); | |
| 6017 | + return mas_next_slot(mas, max, true, false); | |
| 5923 | 6018 | } |
| 5924 | 6019 | EXPORT_SYMBOL_GPL(mas_find_range); |
| 5925 | 6020 | |
| @@ -5934,26 +6029,36 @@ EXPORT_SYMBOL_GPL(mas_find_range); · 8 unmodified lines | ||
| 5934 | 6029 | static inline bool mas_find_rev_setup(struct ma_state *mas, unsigned long min, |
| 5935 | 6030 | void **entry) |
| 5936 | 6031 | { |
| 5937 | − *entry = NULL; | |
| 5938 | − | |
| 5939 | − if (unlikely(mas_is_none(mas))) { | |
| 5940 | − if (mas->index <= min) | |
| 5941 | − goto none; | |
| 6032 | + if (mas_is_active(mas)) { | |
| 6033 | + if (mas->index > min) | |
| 6034 | + return false; | |
| 5942 | 6035 | |
| 5943 | − mas->last = mas->index; | |
| 5944 | − mas->node = MAS_START; | |
| 6036 | + return true; | |
| 5945 | 6037 | } |
| 5946 | 6038 | |
| 5947 | − if (unlikely(mas_is_paused(mas))) { | |
| 6039 | + if (mas_is_paused(mas)) { | |
| 5948 | 6040 | if (unlikely(mas->index <= min)) { |
| 5949 | 6041 | mas->node = MAS_NONE; |
| 5950 | 6042 | return true; |
| 5951 | 6043 | } |
| 5952 | 6044 | mas->node = MAS_START; |
| 5953 | 6045 | mas->last = --mas->index; |
| 6046 | + } else if (mas_is_none(mas)) { | |
| 6047 | + if (mas->index <= min) | |
| 6048 | + goto none; | |
| 6049 | + | |
| 6050 | + mas->last = mas->index; | |
| 6051 | + mas->node = MAS_START; | |
| 6052 | + } else if (mas_is_underflow(mas) || mas_is_overflow(mas)) { | |
| 6053 | + if (mas->last <= min) { | |
| 6054 | + mas->node = MAS_UNDERFLOW; | |
| 6055 | + return true; | |
| 6056 | + } | |
| 6057 | + | |
| 6058 | + mas->node = MAS_START; | |
| 5954 | 6059 | } |
| 5955 | 6060 | |
| 5956 | − if (unlikely(mas_is_start(mas))) { | |
| 6061 | + if (mas_is_start(mas)) { | |
| 5957 | 6062 | /* First run or continue */ |
| 5958 | 6063 | if (mas->index < min) |
| 5959 | 6064 | return true; |
| @@ -6004,13 +6109,13 @@ none: · 44 unmodified lines | ||
| 6004 | 6109 | */ |
| 6005 | 6110 | void *mas_find_rev(struct ma_state *mas, unsigned long min) |
| 6006 | 6111 | { |
| 6007 | − void *entry; | |
| 6112 | + void *entry = NULL; | |
| 6008 | 6113 | |
| 6009 | 6114 | if (mas_find_rev_setup(mas, min, &entry)) |
| 6010 | 6115 | return entry; |
| 6011 | 6116 | |
| 6012 | 6117 | /* Retries on dead nodes handled by mas_prev_slot */ |
| 6013 | − return mas_prev_slot(mas, min, false); | |
| 6118 | + return mas_prev_slot(mas, min, false, false); | |
| 6014 | 6119 | |
| 6015 | 6120 | } |
| 6016 | 6121 | EXPORT_SYMBOL_GPL(mas_find_rev); |
| @@ -6030,13 +6135,13 @@ EXPORT_SYMBOL_GPL(mas_find_rev); · 13 unmodified lines | ||
| 6030 | 6135 | */ |
| 6031 | 6136 | void *mas_find_range_rev(struct ma_state *mas, unsigned long min) |
| 6032 | 6137 | { |
| 6033 | − void *entry; | |
| 6138 | + void *entry = NULL; | |
| 6034 | 6139 | |
| 6035 | 6140 | if (mas_find_rev_setup(mas, min, &entry)) |
| 6036 | 6141 | return entry; |
| 6037 | 6142 | |
| 6038 | 6143 | /* Retries on dead nodes handled by mas_prev_slot */ |
| 6039 | − return mas_prev_slot(mas, min, true); | |
| 6144 | + return mas_prev_slot(mas, min, true, false); | |
| 6040 | 6145 | } |
| 6041 | 6146 | EXPORT_SYMBOL_GPL(mas_find_range_rev); |
| 6042 | 6147 | |
| @@ -265,7 +265,8 @@ EXPORT_SYMBOL(sg_free_table); · 264 unmodified lines | ||
| 265 | 265 | * @table: The sg table header to use |
| 266 | 266 | * @nents: Number of entries in sg list |
| 267 | 267 | * @max_ents: The maximum number of entries the allocator returns per call |
| 268 | − * @nents_first_chunk: Number of entries int the (preallocated) first | |
| 268 | + * @first_chunk: first SGL if preallocated (may be %NULL) | |
| 269 | + * @nents_first_chunk: Number of entries in the (preallocated) first | |
| 269 | 270 | * scatterlist chunk, 0 means no such preallocated chunk provided by user |
| 270 | 271 | * @gfp_mask: GFP allocation mask |
| 271 | 272 | * @alloc_fn: Allocator to use |
| @@ -788,6 +789,7 @@ EXPORT_SYMBOL(__sg_page_iter_dma_next); · 516 unmodified lines | ||
| 788 | 789 | * @miter: sg mapping iter to be started |
| 789 | 790 | * @sgl: sg list to iterate over |
| 790 | 791 | * @nents: number of sg entries |
| 792 | + * @flags: sg iterator flags | |
| 791 | 793 | * |
| 792 | 794 | * Description: |
| 793 | 795 | * Starts mapping iterator @miter. |
| @@ -2166,7 +2166,7 @@ static noinline void __init next_prev_test(struct maple_tree *mt) · 2165 unmodified lines | ||
| 2166 | 2166 | MT_BUG_ON(mt, val != NULL); |
| 2167 | 2167 | MT_BUG_ON(mt, mas.index != 0); |
| 2168 | 2168 | MT_BUG_ON(mt, mas.last != 5); |
| 2169 | − MT_BUG_ON(mt, mas.node != MAS_NONE); | |
| 2169 | + MT_BUG_ON(mt, mas.node != MAS_UNDERFLOW); | |
| 2170 | 2170 | |
| 2171 | 2171 | mas.index = 0; |
| 2172 | 2172 | mas.last = 5; |
| @@ -2917,6 +2917,7 @@ static noinline void __init check_empty_area_fill(struct maple_tree *mt) · 744 unmodified lines | ||
| 2917 | 2917 | * exists MAS_NONE active range |
| 2918 | 2918 | * exists active active range |
| 2919 | 2919 | * DNE active active set to last range |
| 2920 | + * ERANGE active MAS_OVERFLOW last range | |
| 2920 | 2921 | * |
| 2921 | 2922 | * Function ENTRY Start Result index & last |
| 2922 | 2923 | * mas_prev() |
| @@ -2945,6 +2946,7 @@ static noinline void __init check_empty_area_fill(struct maple_tree *mt) · 22 unmodified lines | ||
| 2945 | 2946 | * any MAS_ROOT MAS_NONE 0 |
| 2946 | 2947 | * exists active active range |
| 2947 | 2948 | * DNE active active last range |
| 2949 | + * ERANGE active MAS_UNDERFLOW last range | |
| 2948 | 2950 | * |
| 2949 | 2951 | * Function ENTRY Start Result index & last |
| 2950 | 2952 | * mas_find() |
| @@ -2955,7 +2957,7 @@ static noinline void __init check_empty_area_fill(struct maple_tree *mt) · 4 unmodified lines | ||
| 2955 | 2957 | * DNE MAS_START MAS_NONE 0 |
| 2956 | 2958 | * DNE MAS_PAUSE MAS_NONE 0 |
| 2957 | 2959 | * DNE MAS_ROOT MAS_NONE 0 |
| 2958 | − * DNE MAS_NONE MAS_NONE 0 | |
| 2960 | + * DNE MAS_NONE MAS_NONE 1 | |
| 2959 | 2961 | * if index == 0 |
| 2960 | 2962 | * exists MAS_START MAS_ROOT 0 |
| 2961 | 2963 | * exists MAS_PAUSE MAS_ROOT 0 |
| @@ -2967,7 +2969,7 @@ static noinline void __init check_empty_area_fill(struct maple_tree *mt) · 5 unmodified lines | ||
| 2967 | 2969 | * DNE MAS_START active set to max |
| 2968 | 2970 | * exists MAS_PAUSE active range |
| 2969 | 2971 | * DNE MAS_PAUSE active set to max |
| 2970 | − * exists MAS_NONE active range | |
| 2972 | + * exists MAS_NONE active range (start at last) | |
| 2971 | 2973 | * exists active active range |
| 2972 | 2974 | * DNE active active last range (max < last) |
| 2973 | 2975 | * |
| @@ -2992,7 +2994,7 @@ static noinline void __init check_empty_area_fill(struct maple_tree *mt) · 18 unmodified lines | ||
| 2992 | 2994 | * DNE MAS_START active set to min |
| 2993 | 2995 | * exists MAS_PAUSE active range |
| 2994 | 2996 | * DNE MAS_PAUSE active set to min |
| 2995 | − * exists MAS_NONE active range | |
| 2997 | + * exists MAS_NONE active range (start at index) | |
| 2996 | 2998 | * exists active active range |
| 2997 | 2999 | * DNE active active last range (min > index) |
| 2998 | 3000 | * |
| @@ -3039,10 +3041,10 @@ static noinline void __init check_state_handling(struct maple_tree *mt) · 40 unmodified lines | ||
| 3039 | 3041 | mtree_store_range(mt, 0, 0, ptr, GFP_KERNEL); |
| 3040 | 3042 | |
| 3041 | 3043 | mas_lock(&mas); |
| 3042 | − /* prev: Start -> none */ | |
| 3044 | + /* prev: Start -> underflow*/ | |
| 3043 | 3045 | entry = mas_prev(&mas, 0); |
| 3044 | 3046 | MT_BUG_ON(mt, entry != NULL); |
| 3045 | − MT_BUG_ON(mt, mas.node != MAS_NONE); | |
| 3047 | + MT_BUG_ON(mt, mas.node != MAS_UNDERFLOW); | |
| 3046 | 3048 | |
| 3047 | 3049 | /* prev: Start -> root */ |
| 3048 | 3050 | mas_set(&mas, 10); |
| @@ -3069,7 +3071,7 @@ static noinline void __init check_state_handling(struct maple_tree *mt) · 20 unmodified lines | ||
| 3069 | 3071 | MT_BUG_ON(mt, entry != NULL); |
| 3070 | 3072 | MT_BUG_ON(mt, mas.node != MAS_NONE); |
| 3071 | 3073 | |
| 3072 | − /* next: start -> none */ | |
| 3074 | + /* next: start -> none*/ | |
| 3073 | 3075 | mas_set(&mas, 10); |
| 3074 | 3076 | entry = mas_next(&mas, ULONG_MAX); |
| 3075 | 3077 | MT_BUG_ON(mt, mas.index != 1); |
| @@ -3268,25 +3270,46 @@ static noinline void __init check_state_handling(struct maple_tree *mt) · 192 unmodified lines | ||
| 3268 | 3270 | MT_BUG_ON(mt, mas.last != 0x2500); |
| 3269 | 3271 | MT_BUG_ON(mt, !mas_active(mas)); |
| 3270 | 3272 | |
| 3271 | − /* next:active -> active out of range*/ | |
| 3273 | + /* next:active -> active beyond data */ | |
| 3272 | 3274 | entry = mas_next(&mas, 0x2999); |
| 3273 | 3275 | MT_BUG_ON(mt, entry != NULL); |
| 3274 | 3276 | MT_BUG_ON(mt, mas.index != 0x2501); |
| 3275 | 3277 | MT_BUG_ON(mt, mas.last != 0x2fff); |
| 3276 | 3278 | MT_BUG_ON(mt, !mas_active(mas)); |
| 3277 | 3279 | |
| 3278 | − /* Continue after out of range*/ | |
| 3280 | + /* Continue after last range ends after max */ | |
| 3279 | 3281 | entry = mas_next(&mas, ULONG_MAX); |
| 3280 | 3282 | MT_BUG_ON(mt, entry != ptr3); |
| 3281 | 3283 | MT_BUG_ON(mt, mas.index != 0x3000); |
| 3282 | 3284 | MT_BUG_ON(mt, mas.last != 0x3500); |
| 3283 | 3285 | MT_BUG_ON(mt, !mas_active(mas)); |
| 3284 | 3286 | |
| 3285 | − /* next:active -> active out of range*/ | |
| 3287 | + /* next:active -> active continued */ | |
| 3288 | + entry = mas_next(&mas, ULONG_MAX); | |
| 3289 | + MT_BUG_ON(mt, entry != NULL); | |
| 3290 | + MT_BUG_ON(mt, mas.index != 0x3501); | |
| 3291 | + MT_BUG_ON(mt, mas.last != ULONG_MAX); | |
| 3292 | + MT_BUG_ON(mt, !mas_active(mas)); | |
| 3293 | + | |
| 3294 | + /* next:active -> overflow */ | |
| 3286 | 3295 | entry = mas_next(&mas, ULONG_MAX); |
| 3287 | 3296 | MT_BUG_ON(mt, entry != NULL); |
| 3288 | 3297 | MT_BUG_ON(mt, mas.index != 0x3501); |
| 3289 | 3298 | MT_BUG_ON(mt, mas.last != ULONG_MAX); |
| 3299 | + MT_BUG_ON(mt, mas.node != MAS_OVERFLOW); | |
| 3300 | + | |
| 3301 | + /* next:overflow -> overflow */ | |
| 3302 | + entry = mas_next(&mas, ULONG_MAX); | |
| 3303 | + MT_BUG_ON(mt, entry != NULL); | |
| 3304 | + MT_BUG_ON(mt, mas.index != 0x3501); | |
| 3305 | + MT_BUG_ON(mt, mas.last != ULONG_MAX); | |
| 3306 | + MT_BUG_ON(mt, mas.node != MAS_OVERFLOW); | |
| 3307 | + | |
| 3308 | + /* prev:overflow -> active */ | |
| 3309 | + entry = mas_prev(&mas, 0); | |
| 3310 | + MT_BUG_ON(mt, entry != ptr3); | |
| 3311 | + MT_BUG_ON(mt, mas.index != 0x3000); | |
| 3312 | + MT_BUG_ON(mt, mas.last != 0x3500); | |
| 3290 | 3313 | MT_BUG_ON(mt, !mas_active(mas)); |
| 3291 | 3314 | |
| 3292 | 3315 | /* next: none -> active, skip value at location */ |
| @@ -3307,11 +3330,46 @@ static noinline void __init check_state_handling(struct maple_tree *mt) · 14 unmodified lines | ||
| 3307 | 3330 | MT_BUG_ON(mt, mas.last != 0x1500); |
| 3308 | 3331 | MT_BUG_ON(mt, !mas_active(mas)); |
| 3309 | 3332 | |
| 3310 | − /* prev:active -> active out of range*/ | |
| 3333 | + /* prev:active -> active spanning end range */ | |
| 3334 | + entry = mas_prev(&mas, 0x0100); | |
| 3335 | + MT_BUG_ON(mt, entry != NULL); | |
| 3336 | + MT_BUG_ON(mt, mas.index != 0); | |
| 3337 | + MT_BUG_ON(mt, mas.last != 0x0FFF); | |
| 3338 | + MT_BUG_ON(mt, !mas_active(mas)); | |
| 3339 | + | |
| 3340 | + /* prev:active -> underflow */ | |
| 3341 | + entry = mas_prev(&mas, 0); | |
| 3342 | + MT_BUG_ON(mt, entry != NULL); | |
| 3343 | + MT_BUG_ON(mt, mas.index != 0); | |
| 3344 | + MT_BUG_ON(mt, mas.last != 0x0FFF); | |
| 3345 | + MT_BUG_ON(mt, mas.node != MAS_UNDERFLOW); | |
| 3346 | + | |
| 3347 | + /* prev:underflow -> underflow */ | |
| 3311 | 3348 | entry = mas_prev(&mas, 0); |
| 3312 | 3349 | MT_BUG_ON(mt, entry != NULL); |
| 3313 | 3350 | MT_BUG_ON(mt, mas.index != 0); |
| 3314 | 3351 | MT_BUG_ON(mt, mas.last != 0x0FFF); |
| 3352 | + MT_BUG_ON(mt, mas.node != MAS_UNDERFLOW); | |
| 3353 | + | |
| 3354 | + /* next:underflow -> active */ | |
| 3355 | + entry = mas_next(&mas, ULONG_MAX); | |
| 3356 | + MT_BUG_ON(mt, entry != ptr); | |
| 3357 | + MT_BUG_ON(mt, mas.index != 0x1000); | |
| 3358 | + MT_BUG_ON(mt, mas.last != 0x1500); | |
| 3359 | + MT_BUG_ON(mt, !mas_active(mas)); | |
| 3360 | + | |
| 3361 | + /* prev:first value -> underflow */ | |
| 3362 | + entry = mas_prev(&mas, 0x1000); | |
| 3363 | + MT_BUG_ON(mt, entry != NULL); | |
| 3364 | + MT_BUG_ON(mt, mas.index != 0x1000); | |
| 3365 | + MT_BUG_ON(mt, mas.last != 0x1500); | |
| 3366 | + MT_BUG_ON(mt, mas.node != MAS_UNDERFLOW); | |
| 3367 | + | |
| 3368 | + /* find:underflow -> first value */ | |
| 3369 | + entry = mas_find(&mas, ULONG_MAX); | |
| 3370 | + MT_BUG_ON(mt, entry != ptr); | |
| 3371 | + MT_BUG_ON(mt, mas.index != 0x1000); | |
| 3372 | + MT_BUG_ON(mt, mas.last != 0x1500); | |
| 3315 | 3373 | MT_BUG_ON(mt, !mas_active(mas)); |
| 3316 | 3374 | |
| 3317 | 3375 | /* prev: pause ->active */ |
| @@ -3325,14 +3383,14 @@ static noinline void __init check_state_handling(struct maple_tree *mt) · 7 unmodified lines | ||
| 3325 | 3383 | MT_BUG_ON(mt, mas.last != 0x2500); |
| 3326 | 3384 | MT_BUG_ON(mt, !mas_active(mas)); |
| 3327 | 3385 | |
| 3328 | − /* prev:active -> active out of range*/ | |
| 3386 | + /* prev:active -> active spanning min */ | |
| 3329 | 3387 | entry = mas_prev(&mas, 0x1600); |
| 3330 | 3388 | MT_BUG_ON(mt, entry != NULL); |
| 3331 | 3389 | MT_BUG_ON(mt, mas.index != 0x1501); |
| 3332 | 3390 | MT_BUG_ON(mt, mas.last != 0x1FFF); |
| 3333 | 3391 | MT_BUG_ON(mt, !mas_active(mas)); |
| 3334 | 3392 | |
| 3335 | − /* prev: active ->active, continue*/ | |
| 3393 | + /* prev: active ->active, continue */ | |
| 3336 | 3394 | entry = mas_prev(&mas, 0); |
| 3337 | 3395 | MT_BUG_ON(mt, entry != ptr); |
| 3338 | 3396 | MT_BUG_ON(mt, mas.index != 0x1000); |
| @@ -3379,7 +3437,7 @@ static noinline void __init check_state_handling(struct maple_tree *mt) · 40 unmodified lines | ||
| 3379 | 3437 | MT_BUG_ON(mt, mas.last != 0x2FFF); |
| 3380 | 3438 | MT_BUG_ON(mt, !mas_active(mas)); |
| 3381 | 3439 | |
| 3382 | − /* find: none ->active */ | |
| 3440 | + /* find: overflow ->active */ | |
| 3383 | 3441 | entry = mas_find(&mas, 0x5000); |
| 3384 | 3442 | MT_BUG_ON(mt, entry != ptr3); |
| 3385 | 3443 | MT_BUG_ON(mt, mas.index != 0x3000); |
| @@ -3778,7 +3836,6 @@ static int __init maple_tree_seed(void) · 392 unmodified lines | ||
| 3778 | 3836 | check_empty_area_fill(&tree); |
| 3779 | 3837 | mtree_destroy(&tree); |
| 3780 | 3838 | |
| 3781 | − | |
| 3782 | 3839 | mt_init_flags(&tree, MT_FLAGS_ALLOC_RANGE); |
| 3783 | 3840 | check_state_handling(&tree); |
| 3784 | 3841 | mtree_destroy(&tree); |
| @@ -148,6 +148,8 @@ static void damon_do_test_apply_three_regions(struct kunit *test, · 147 unmodified lines | ||
| 148 | 148 | KUNIT_EXPECT_EQ(test, r->ar.start, expected[i * 2]); |
| 149 | 149 | KUNIT_EXPECT_EQ(test, r->ar.end, expected[i * 2 + 1]); |
| 150 | 150 | } |
| 151 | + | |
| 152 | + damon_destroy_target(t); | |
| 151 | 153 | } |
| 152 | 154 | |
| 153 | 155 | /* |
| @@ -341,13 +341,14 @@ static void damon_hugetlb_mkold(pte_t *pte, struct mm_struct *mm, · 340 unmodified lines | ||
| 341 | 341 | bool referenced = false; |
| 342 | 342 | pte_t entry = huge_ptep_get(pte); |
| 343 | 343 | struct folio *folio = pfn_folio(pte_pfn(entry)); |
| 344 | + unsigned long psize = huge_page_size(hstate_vma(vma)); | |
| 344 | 345 | |
| 345 | 346 | folio_get(folio); |
| 346 | 347 | |
| 347 | 348 | if (pte_young(entry)) { |
| 348 | 349 | referenced = true; |
| 349 | 350 | entry = pte_mkold(entry); |
| 350 | − set_huge_pte_at(mm, addr, pte, entry); | |
| 351 | + set_huge_pte_at(mm, addr, pte, entry, psize); | |
| 351 | 352 | } |
| 352 | 353 | |
| 353 | 354 | #ifdef CONFIG_MMU_NOTIFIER |
| @@ -3475,13 +3475,11 @@ skip: · 3474 unmodified lines | ||
| 3475 | 3475 | */ |
| 3476 | 3476 | static vm_fault_t filemap_map_folio_range(struct vm_fault *vmf, |
| 3477 | 3477 | struct folio *folio, unsigned long start, |
| 3478 | − unsigned long addr, unsigned int nr_pages) | |
| 3478 | + unsigned long addr, unsigned int nr_pages, | |
| 3479 | + unsigned int *mmap_miss) | |
| 3479 | 3480 | { |
| 3480 | 3481 | vm_fault_t ret = 0; |
| 3481 | − struct vm_area_struct *vma = vmf->vma; | |
| 3482 | − struct file *file = vma->vm_file; | |
| 3483 | 3482 | struct page *page = folio_page(folio, start); |
| 3484 | − unsigned int mmap_miss = READ_ONCE(file->f_ra.mmap_miss); | |
| 3485 | 3483 | unsigned int count = 0; |
| 3486 | 3484 | pte_t *old_ptep = vmf->pte; |
| 3487 | 3485 | |
| @@ -3489,8 +3487,7 @@ static vm_fault_t filemap_map_folio_range(struct vm_fault *vmf, · 1 unmodified line | ||
| 3489 | 3487 | if (PageHWPoison(page + count)) |
| 3490 | 3488 | goto skip; |
| 3491 | 3489 | |
| 3492 | − if (mmap_miss > 0) | |
| 3493 | − mmap_miss--; | |
| 3490 | + (*mmap_miss)++; | |
| 3494 | 3491 | |
| 3495 | 3492 | /* |
| 3496 | 3493 | * NOTE: If there're PTE markers, we'll leave them to be |
| @@ -3506,7 +3503,7 @@ skip: · 9 unmodified lines | ||
| 3506 | 3503 | if (count) { |
| 3507 | 3504 | set_pte_range(vmf, folio, page, count, addr); |
| 3508 | 3505 | folio_ref_add(folio, count); |
| 3509 | − if (in_range(vmf->address, addr, count)) | |
| 3506 | + if (in_range(vmf->address, addr, count * PAGE_SIZE)) | |
| 3510 | 3507 | ret = VM_FAULT_NOPAGE; |
| 3511 | 3508 | } |
| 3512 | 3509 | |
| @@ -3520,12 +3517,40 @@ skip: · 7 unmodified lines | ||
| 3520 | 3517 | if (count) { |
| 3521 | 3518 | set_pte_range(vmf, folio, page, count, addr); |
| 3522 | 3519 | folio_ref_add(folio, count); |
| 3523 | − if (in_range(vmf->address, addr, count)) | |
| 3520 | + if (in_range(vmf->address, addr, count * PAGE_SIZE)) | |
| 3524 | 3521 | ret = VM_FAULT_NOPAGE; |
| 3525 | 3522 | } |
| 3526 | 3523 | |
| 3527 | 3524 | vmf->pte = old_ptep; |
| 3528 | − WRITE_ONCE(file->f_ra.mmap_miss, mmap_miss); | |
| 3525 | + | |
| 3526 | + return ret; | |
| 3527 | +} | |
| 3528 | + | |
| 3529 | +static vm_fault_t filemap_map_order0_folio(struct vm_fault *vmf, | |
| 3530 | + struct folio *folio, unsigned long addr, | |
| 3531 | + unsigned int *mmap_miss) | |
| 3532 | +{ | |
| 3533 | + vm_fault_t ret = 0; | |
| 3534 | + struct page *page = &folio->page; | |
| 3535 | + | |
| 3536 | + if (PageHWPoison(page)) | |
| 3537 | + return ret; | |
| 3538 | + | |
| 3539 | + (*mmap_miss)++; | |
| 3540 | + | |
| 3541 | + /* | |
| 3542 | + * NOTE: If there're PTE markers, we'll leave them to be | |
| 3543 | + * handled in the specific fault path, and it'll prohibit | |
| 3544 | + * the fault-around logic. | |
| 3545 | + */ | |
| 3546 | + if (!pte_none(ptep_get(vmf->pte))) | |
| 3547 | + return ret; | |
| 3548 | + | |
| 3549 | + if (vmf->address == addr) | |
| 3550 | + ret = VM_FAULT_NOPAGE; | |
| 3551 | + | |
| 3552 | + set_pte_range(vmf, folio, page, 1, addr); | |
| 3553 | + folio_ref_inc(folio); | |
| 3529 | 3554 | |
| 3530 | 3555 | return ret; |
| 3531 | 3556 | } |
| @@ -3541,7 +3566,7 @@ vm_fault_t filemap_map_pages(struct vm_fault *vmf, · 9 unmodified lines | ||
| 3541 | 3566 | XA_STATE(xas, &mapping->i_pages, start_pgoff); |
| 3542 | 3567 | struct folio *folio; |
| 3543 | 3568 | vm_fault_t ret = 0; |
| 3544 | − int nr_pages = 0; | |
| 3569 | + unsigned int nr_pages = 0, mmap_miss = 0, mmap_miss_saved; | |
| 3545 | 3570 | |
| 3546 | 3571 | rcu_read_lock(); |
| 3547 | 3572 | folio = next_uptodate_folio(&xas, mapping, end_pgoff); |
| @@ -3569,25 +3594,27 @@ vm_fault_t filemap_map_pages(struct vm_fault *vmf, · 21 unmodified lines | ||
| 3569 | 3594 | end = folio->index + folio_nr_pages(folio) - 1; |
| 3570 | 3595 | nr_pages = min(end, end_pgoff) - xas.xa_index + 1; |
| 3571 | 3596 | |
| 3572 | − /* | |
| 3573 | − * NOTE: If there're PTE markers, we'll leave them to be | |
| 3574 | − * handled in the specific fault path, and it'll prohibit the | |
| 3575 | − * fault-around logic. | |
| 3576 | − */ | |
| 3577 | − if (!pte_none(ptep_get(vmf->pte))) | |
| 3578 | − goto unlock; | |
| 3579 | − | |
| 3580 | − ret |= filemap_map_folio_range(vmf, folio, | |
| 3581 | − xas.xa_index - folio->index, addr, nr_pages); | |
| 3597 | + if (!folio_test_large(folio)) | |
| 3598 | + ret |= filemap_map_order0_folio(vmf, | |
| 3599 | + folio, addr, &mmap_miss); | |
| 3600 | + else | |
| 3601 | + ret |= filemap_map_folio_range(vmf, folio, | |
| 3602 | + xas.xa_index - folio->index, addr, | |
| 3603 | + nr_pages, &mmap_miss); | |
| 3582 | 3604 | |
| 3583 | −unlock: | |
| 3584 | 3605 | folio_unlock(folio); |
| 3585 | 3606 | folio_put(folio); |
| 3586 | − folio = next_uptodate_folio(&xas, mapping, end_pgoff); | |
| 3587 | − } while (folio); | |
| 3607 | + } while ((folio = next_uptodate_folio(&xas, mapping, end_pgoff)) != NULL); | |
| 3588 | 3608 | pte_unmap_unlock(vmf->pte, vmf->ptl); |
| 3589 | 3609 | out: |
| 3590 | 3610 | rcu_read_unlock(); |
| 3611 | + | |
| 3612 | + mmap_miss_saved = READ_ONCE(file->f_ra.mmap_miss); | |
| 3613 | + if (mmap_miss >= mmap_miss_saved) | |
| 3614 | + WRITE_ONCE(file->f_ra.mmap_miss, 0); | |
| 3615 | + else | |
| 3616 | + WRITE_ONCE(file->f_ra.mmap_miss, mmap_miss_saved - mmap_miss); | |
| 3617 | + | |
| 3591 | 3618 | return ret; |
| 3592 | 3619 | } |
| 3593 | 3620 | EXPORT_SYMBOL(filemap_map_pages); |
| @@ -4980,7 +4980,7 @@ static bool is_hugetlb_entry_hwpoisoned(pte_t pte) · 4979 unmodified lines | ||
| 4980 | 4980 | |
| 4981 | 4981 | static void |
| 4982 | 4982 | hugetlb_install_folio(struct vm_area_struct *vma, pte_t *ptep, unsigned long addr, |
| 4983 | − struct folio *new_folio, pte_t old) | |
| 4983 | + struct folio *new_folio, pte_t old, unsigned long sz) | |
| 4984 | 4984 | { |
| 4985 | 4985 | pte_t newpte = make_huge_pte(vma, &new_folio->page, 1); |
| 4986 | 4986 | |
| @@ -4988,7 +4988,7 @@ hugetlb_install_folio(struct vm_area_struct *vma, pte_t *ptep, unsigned long add · 1 unmodified line | ||
| 4988 | 4988 | hugepage_add_new_anon_rmap(new_folio, vma, addr); |
| 4989 | 4989 | if (userfaultfd_wp(vma) && huge_pte_uffd_wp(old)) |
| 4990 | 4990 | newpte = huge_pte_mkuffd_wp(newpte); |
| 4991 | − set_huge_pte_at(vma->vm_mm, addr, ptep, newpte); | |
| 4991 | + set_huge_pte_at(vma->vm_mm, addr, ptep, newpte, sz); | |
| 4992 | 4992 | hugetlb_count_add(pages_per_huge_page(hstate_vma(vma)), vma->vm_mm); |
| 4993 | 4993 | folio_set_hugetlb_migratable(new_folio); |
| 4994 | 4994 | } |
| @@ -5065,7 +5065,7 @@ again: · 70 unmodified lines | ||
| 5065 | 5065 | } else if (unlikely(is_hugetlb_entry_hwpoisoned(entry))) { |
| 5066 | 5066 | if (!userfaultfd_wp(dst_vma)) |
| 5067 | 5067 | entry = huge_pte_clear_uffd_wp(entry); |
| 5068 | − set_huge_pte_at(dst, addr, dst_pte, entry); | |
| 5068 | + set_huge_pte_at(dst, addr, dst_pte, entry, sz); | |
| 5069 | 5069 | } else if (unlikely(is_hugetlb_entry_migration(entry))) { |
| 5070 | 5070 | swp_entry_t swp_entry = pte_to_swp_entry(entry); |
| 5071 | 5071 | bool uffd_wp = pte_swp_uffd_wp(entry); |
| @@ -5080,18 +5080,18 @@ again: · 8 unmodified lines | ||
| 5080 | 5080 | entry = swp_entry_to_pte(swp_entry); |
| 5081 | 5081 | if (userfaultfd_wp(src_vma) && uffd_wp) |
| 5082 | 5082 | entry = pte_swp_mkuffd_wp(entry); |
| 5083 | − set_huge_pte_at(src, addr, src_pte, entry); | |
| 5083 | + set_huge_pte_at(src, addr, src_pte, entry, sz); | |
| 5084 | 5084 | } |
| 5085 | 5085 | if (!userfaultfd_wp(dst_vma)) |
| 5086 | 5086 | entry = huge_pte_clear_uffd_wp(entry); |
| 5087 | − set_huge_pte_at(dst, addr, dst_pte, entry); | |
| 5087 | + set_huge_pte_at(dst, addr, dst_pte, entry, sz); | |
| 5088 | 5088 | } else if (unlikely(is_pte_marker(entry))) { |
| 5089 | 5089 | pte_marker marker = copy_pte_marker( |
| 5090 | 5090 | pte_to_swp_entry(entry), dst_vma); |
| 5091 | 5091 | |
| 5092 | 5092 | if (marker) |
| 5093 | 5093 | set_huge_pte_at(dst, addr, dst_pte, |
| 5094 | − make_pte_marker(marker)); | |
| 5094 | + make_pte_marker(marker), sz); | |
| 5095 | 5095 | } else { |
| 5096 | 5096 | entry = huge_ptep_get(src_pte); |
| 5097 | 5097 | pte_folio = page_folio(pte_page(entry)); |
| @@ -5145,7 +5145,7 @@ again: · 47 unmodified lines | ||
| 5145 | 5145 | goto again; |
| 5146 | 5146 | } |
| 5147 | 5147 | hugetlb_install_folio(dst_vma, dst_pte, addr, |
| 5148 | − new_folio, src_pte_old); | |
| 5148 | + new_folio, src_pte_old, sz); | |
| 5149 | 5149 | spin_unlock(src_ptl); |
| 5150 | 5150 | spin_unlock(dst_ptl); |
| 5151 | 5151 | continue; |
| @@ -5166,7 +5166,7 @@ again: · 14 unmodified lines | ||
| 5166 | 5166 | if (!userfaultfd_wp(dst_vma)) |
| 5167 | 5167 | entry = huge_pte_clear_uffd_wp(entry); |
| 5168 | 5168 | |
| 5169 | − set_huge_pte_at(dst, addr, dst_pte, entry); | |
| 5169 | + set_huge_pte_at(dst, addr, dst_pte, entry, sz); | |
| 5170 | 5170 | hugetlb_count_add(npages, dst); |
| 5171 | 5171 | } |
| 5172 | 5172 | spin_unlock(src_ptl); |
| @@ -5184,7 +5184,8 @@ again: · 11 unmodified lines | ||
| 5184 | 5184 | } |
| 5185 | 5185 | |
| 5186 | 5186 | static void move_huge_pte(struct vm_area_struct *vma, unsigned long old_addr, |
| 5187 | − unsigned long new_addr, pte_t *src_pte, pte_t *dst_pte) | |
| 5187 | + unsigned long new_addr, pte_t *src_pte, pte_t *dst_pte, | |
| 5188 | + unsigned long sz) | |
| 5188 | 5189 | { |
| 5189 | 5190 | struct hstate *h = hstate_vma(vma); |
| 5190 | 5191 | struct mm_struct *mm = vma->vm_mm; |
| @@ -5202,7 +5203,7 @@ static void move_huge_pte(struct vm_area_struct *vma, unsigned long old_addr, · 11 unmodified lines | ||
| 5202 | 5203 | spin_lock_nested(src_ptl, SINGLE_DEPTH_NESTING); |
| 5203 | 5204 | |
| 5204 | 5205 | pte = huge_ptep_get_and_clear(mm, old_addr, src_pte); |
| 5205 | − set_huge_pte_at(mm, new_addr, dst_pte, pte); | |
| 5206 | + set_huge_pte_at(mm, new_addr, dst_pte, pte, sz); | |
| 5206 | 5207 | |
| 5207 | 5208 | if (src_ptl != dst_ptl) |
| 5208 | 5209 | spin_unlock(src_ptl); |
| @@ -5259,7 +5260,7 @@ int move_hugetlb_page_tables(struct vm_area_struct *vma, · 50 unmodified lines | ||
| 5259 | 5260 | if (!dst_pte) |
| 5260 | 5261 | break; |
| 5261 | 5262 | |
| 5262 | − move_huge_pte(vma, old_addr, new_addr, src_pte, dst_pte); | |
| 5263 | + move_huge_pte(vma, old_addr, new_addr, src_pte, dst_pte, sz); | |
| 5263 | 5264 | } |
| 5264 | 5265 | |
| 5265 | 5266 | if (shared_pmd) |
| @@ -5337,7 +5338,8 @@ static void __unmap_hugepage_range(struct mmu_gather *tlb, struct vm_area_struct · 71 unmodified lines | ||
| 5337 | 5338 | if (pte_swp_uffd_wp_any(pte) && |
| 5338 | 5339 | !(zap_flags & ZAP_FLAG_DROP_MARKER)) |
| 5339 | 5340 | set_huge_pte_at(mm, address, ptep, |
| 5340 | − make_pte_marker(PTE_MARKER_UFFD_WP)); | |
| 5341 | + make_pte_marker(PTE_MARKER_UFFD_WP), | |
| 5342 | + sz); | |
| 5341 | 5343 | else |
| 5342 | 5344 | huge_pte_clear(mm, address, ptep, sz); |
| 5343 | 5345 | spin_unlock(ptl); |
| @@ -5371,7 +5373,8 @@ static void __unmap_hugepage_range(struct mmu_gather *tlb, struct vm_area_struct · 27 unmodified lines | ||
| 5371 | 5373 | if (huge_pte_uffd_wp(pte) && |
| 5372 | 5374 | !(zap_flags & ZAP_FLAG_DROP_MARKER)) |
| 5373 | 5375 | set_huge_pte_at(mm, address, ptep, |
| 5374 | − make_pte_marker(PTE_MARKER_UFFD_WP)); | |
| 5376 | + make_pte_marker(PTE_MARKER_UFFD_WP), | |
| 5377 | + sz); | |
| 5375 | 5378 | hugetlb_count_sub(pages_per_huge_page(h), mm); |
| 5376 | 5379 | page_remove_rmap(page, vma, true); |
| 5377 | 5380 | |
| @@ -5676,7 +5679,7 @@ retry_avoidcopy: · 298 unmodified lines | ||
| 5676 | 5679 | hugepage_add_new_anon_rmap(new_folio, vma, haddr); |
| 5677 | 5680 | if (huge_pte_uffd_wp(pte)) |
| 5678 | 5681 | newpte = huge_pte_mkuffd_wp(newpte); |
| 5679 | − set_huge_pte_at(mm, haddr, ptep, newpte); | |
| 5682 | + set_huge_pte_at(mm, haddr, ptep, newpte, huge_page_size(h)); | |
| 5680 | 5683 | folio_set_hugetlb_migratable(new_folio); |
| 5681 | 5684 | /* Make the old page be freed below */ |
| 5682 | 5685 | new_folio = old_folio; |
| @@ -5972,7 +5975,7 @@ static vm_fault_t hugetlb_no_page(struct mm_struct *mm, · 289 unmodified lines | ||
| 5972 | 5975 | */ |
| 5973 | 5976 | if (unlikely(pte_marker_uffd_wp(old_pte))) |
| 5974 | 5977 | new_pte = huge_pte_mkuffd_wp(new_pte); |
| 5975 | − set_huge_pte_at(mm, haddr, ptep, new_pte); | |
| 5978 | + set_huge_pte_at(mm, haddr, ptep, new_pte, huge_page_size(h)); | |
| 5976 | 5979 | |
| 5977 | 5980 | hugetlb_count_add(pages_per_huge_page(h), mm); |
| 5978 | 5981 | if ((flags & FAULT_FLAG_WRITE) && !(vma->vm_flags & VM_SHARED)) { |
| @@ -6261,7 +6264,8 @@ int hugetlb_mfill_atomic_pte(pte_t *dst_pte, · 282 unmodified lines | ||
| 6261 | 6264 | } |
| 6262 | 6265 | |
| 6263 | 6266 | _dst_pte = make_pte_marker(PTE_MARKER_POISONED); |
| 6264 | − set_huge_pte_at(dst_mm, dst_addr, dst_pte, _dst_pte); | |
| 6267 | + set_huge_pte_at(dst_mm, dst_addr, dst_pte, _dst_pte, | |
| 6268 | + huge_page_size(h)); | |
| 6265 | 6269 | |
| 6266 | 6270 | /* No need to invalidate - it was non-present before */ |
| 6267 | 6271 | update_mmu_cache(dst_vma, dst_addr, dst_pte); |
| @@ -6412,7 +6416,7 @@ int hugetlb_mfill_atomic_pte(pte_t *dst_pte, · 144 unmodified lines | ||
| 6412 | 6416 | if (wp_enabled) |
| 6413 | 6417 | _dst_pte = huge_pte_mkuffd_wp(_dst_pte); |
| 6414 | 6418 | |
| 6415 | − set_huge_pte_at(dst_mm, dst_addr, dst_pte, _dst_pte); | |
| 6419 | + set_huge_pte_at(dst_mm, dst_addr, dst_pte, _dst_pte, huge_page_size(h)); | |
| 6416 | 6420 | |
| 6417 | 6421 | hugetlb_count_add(pages_per_huge_page(h), dst_mm); |
| 6418 | 6422 | |
| @@ -6598,7 +6602,7 @@ long hugetlb_change_protection(struct vm_area_struct *vma, · 179 unmodified lines | ||
| 6598 | 6602 | else if (uffd_wp_resolve) |
| 6599 | 6603 | newpte = pte_swp_clear_uffd_wp(newpte); |
| 6600 | 6604 | if (!pte_same(pte, newpte)) |
| 6601 | − set_huge_pte_at(mm, address, ptep, newpte); | |
| 6605 | + set_huge_pte_at(mm, address, ptep, newpte, psize); | |
| 6602 | 6606 | } else if (unlikely(is_pte_marker(pte))) { |
| 6603 | 6607 | /* No other markers apply for now. */ |
| 6604 | 6608 | WARN_ON_ONCE(!pte_marker_uffd_wp(pte)); |
| @@ -6623,7 +6627,8 @@ long hugetlb_change_protection(struct vm_area_struct *vma, · 18 unmodified lines | ||
| 6623 | 6627 | if (unlikely(uffd_wp)) |
| 6624 | 6628 | /* Safe to modify directly (none->non-present). */ |
| 6625 | 6629 | set_huge_pte_at(mm, address, ptep, |
| 6626 | − make_pte_marker(PTE_MARKER_UFFD_WP)); | |
| 6630 | + make_pte_marker(PTE_MARKER_UFFD_WP), | |
| 6631 | + psize); | |
| 6627 | 6632 | } |
| 6628 | 6633 | spin_unlock(ptl); |
| 6629 | 6634 | } |
| @@ -291,7 +291,7 @@ struct kasan_stack_ring { · 290 unmodified lines | ||
| 291 | 291 | |
| 292 | 292 | #if defined(CONFIG_KASAN_GENERIC) || defined(CONFIG_KASAN_SW_TAGS) |
| 293 | 293 | |
| 294 | −#ifndef __HAVE_ARCH_SHADOW_MAP | |
| 294 | +#ifndef kasan_shadow_to_mem | |
| 295 | 295 | static inline const void *kasan_shadow_to_mem(const void *shadow_addr) |
| 296 | 296 | { |
| 297 | 297 | return (void *)(((unsigned long)shadow_addr - KASAN_SHADOW_OFFSET) |
| @@ -299,15 +299,13 @@ static inline const void *kasan_shadow_to_mem(const void *shadow_addr) · 1 unmodified line | ||
| 299 | 299 | } |
| 300 | 300 | #endif |
| 301 | 301 | |
| 302 | +#ifndef addr_has_metadata | |
| 302 | 303 | static __always_inline bool addr_has_metadata(const void *addr) |
| 303 | 304 | { |
| 304 | −#ifdef __HAVE_ARCH_SHADOW_MAP | |
| 305 | − return (kasan_mem_to_shadow((void *)addr) != NULL); | |
| 306 | −#else | |
| 307 | 305 | return (kasan_reset_tag(addr) >= |
| 308 | 306 | kasan_shadow_to_mem((void *)KASAN_SHADOW_START)); |
| 309 | −#endif | |
| 310 | 307 | } |
| 308 | +#endif | |
| 311 | 309 | |
| 312 | 310 | /** |
| 313 | 311 | * kasan_check_range - Check memory region, and report if invalid access. |
| @@ -2555,7 +2555,7 @@ static unsigned long calculate_high_delay(struct mem_cgroup *memcg, · 2554 unmodified lines | ||
| 2555 | 2555 | * Scheduled by try_charge() to be executed from the userland return path |
| 2556 | 2556 | * and reclaims memory over the high limit. |
| 2557 | 2557 | */ |
| 2558 | −void mem_cgroup_handle_over_high(void) | |
| 2558 | +void mem_cgroup_handle_over_high(gfp_t gfp_mask) | |
| 2559 | 2559 | { |
| 2560 | 2560 | unsigned long penalty_jiffies; |
| 2561 | 2561 | unsigned long pflags; |
| @@ -2583,7 +2583,7 @@ retry_reclaim: · 21 unmodified lines | ||
| 2583 | 2583 | */ |
| 2584 | 2584 | nr_reclaimed = reclaim_high(memcg, |
| 2585 | 2585 | in_retry ? SWAP_CLUSTER_MAX : nr_pages, |
| 2586 | − GFP_KERNEL); | |
| 2586 | + gfp_mask); | |
| 2587 | 2587 | |
| 2588 | 2588 | /* |
| 2589 | 2589 | * memory.high is breached and reclaim is unable to keep up. Throttle |
| @@ -2819,7 +2819,7 @@ done_restock: · 229 unmodified lines | ||
| 2819 | 2819 | if (current->memcg_nr_pages_over_high > MEMCG_CHARGE_BATCH && |
| 2820 | 2820 | !(current->flags & PF_MEMALLOC) && |
| 2821 | 2821 | gfpflags_allow_blocking(gfp_mask)) { |
| 2822 | − mem_cgroup_handle_over_high(); | |
| 2822 | + mem_cgroup_handle_over_high(gfp_mask); | |
| 2823 | 2823 | } |
| 2824 | 2824 | return 0; |
| 2825 | 2825 | } |
| @@ -3867,6 +3867,13 @@ static ssize_t mem_cgroup_write(struct kernfs_open_file *of, · 1041 unmodified lines | ||
| 3867 | 3867 | case _MEMSWAP: |
| 3868 | 3868 | ret = mem_cgroup_resize_max(memcg, nr_pages, true); |
| 3869 | 3869 | break; |
| 3870 | + case _KMEM: | |
| 3871 | + pr_warn_once("kmem.limit_in_bytes is deprecated and will be removed. " | |
| 3872 | + "Writing any value to this file has no effect. " | |
| 3873 | + "Please report your usecase to linux-mm@kvack.org if you " | |
| 3874 | + "depend on this functionality.\n"); | |
| 3875 | + ret = 0; | |
| 3876 | + break; | |
| 3870 | 3877 | case _TCP: |
| 3871 | 3878 | ret = memcg_update_tcp_max(memcg, nr_pages); |
| 3872 | 3879 | break; |
| @@ -5077,6 +5084,12 @@ static struct cftype mem_cgroup_legacy_files[] = { · 1204 unmodified lines | ||
| 5077 | 5084 | .seq_show = memcg_numa_stat_show, |
| 5078 | 5085 | }, |
| 5079 | 5086 | #endif |
| 5087 | + { | |
| 5088 | + .name = "kmem.limit_in_bytes", | |
| 5089 | + .private = MEMFILE_PRIVATE(_KMEM, RES_LIMIT), | |
| 5090 | + .write = mem_cgroup_write, | |
| 5091 | + .read_u64 = mem_cgroup_read_u64, | |
| 5092 | + }, | |
| 5080 | 5093 | { |
| 5081 | 5094 | .name = "kmem.usage_in_bytes", |
| 5082 | 5095 | .private = MEMFILE_PRIVATE(_KMEM, RES_USAGE), |
| @@ -426,6 +426,7 @@ struct queue_pages { · 425 unmodified lines | ||
| 426 | 426 | unsigned long start; |
| 427 | 427 | unsigned long end; |
| 428 | 428 | struct vm_area_struct *first; |
| 429 | + bool has_unmovable; | |
| 429 | 430 | }; |
| 430 | 431 | |
| 431 | 432 | /* |
| @@ -446,9 +447,8 @@ static inline bool queue_folio_required(struct folio *folio, · 14 unmodified lines | ||
| 446 | 447 | /* |
| 447 | 448 | * queue_folios_pmd() has three possible return values: |
| 448 | 449 | * 0 - folios are placed on the right node or queued successfully, or |
| 449 | − * special page is met, i.e. huge zero page. | |
| 450 | − * 1 - there is unmovable folio, and MPOL_MF_MOVE* & MPOL_MF_STRICT were | |
| 451 | − * specified. | |
| 450 | + * special page is met, i.e. zero page, or unmovable page is found | |
| 451 | + * but continue walking (indicated by queue_pages.has_unmovable). | |
| 452 | 452 | * -EIO - is migration entry or only MPOL_MF_STRICT was specified and an |
| 453 | 453 | * existing folio was already on a node that does not follow the |
| 454 | 454 | * policy. |
| @@ -479,7 +479,7 @@ static int queue_folios_pmd(pmd_t *pmd, spinlock_t *ptl, unsigned long addr, · 24 unmodified lines | ||
| 479 | 479 | if (flags & (MPOL_MF_MOVE | MPOL_MF_MOVE_ALL)) { |
| 480 | 480 | if (!vma_migratable(walk->vma) || |
| 481 | 481 | migrate_folio_add(folio, qp->pagelist, flags)) { |
| 482 | − ret = 1; | |
| 482 | + qp->has_unmovable = true; | |
| 483 | 483 | goto unlock; |
| 484 | 484 | } |
| 485 | 485 | } else |
| @@ -495,9 +495,8 @@ unlock: · 9 unmodified lines | ||
| 495 | 495 | * |
| 496 | 496 | * queue_folios_pte_range() has three possible return values: |
| 497 | 497 | * 0 - folios are placed on the right node or queued successfully, or |
| 498 | − * special page is met, i.e. zero page. | |
| 499 | − * 1 - there is unmovable folio, and MPOL_MF_MOVE* & MPOL_MF_STRICT were | |
| 500 | − * specified. | |
| 498 | + * special page is met, i.e. zero page, or unmovable page is found | |
| 499 | + * but continue walking (indicated by queue_pages.has_unmovable). | |
| 501 | 500 | * -EIO - only MPOL_MF_STRICT was specified and an existing folio was already |
| 502 | 501 | * on a node that does not follow the policy. |
| 503 | 502 | */ |
| @@ -508,7 +507,6 @@ static int queue_folios_pte_range(pmd_t *pmd, unsigned long addr, · 4 unmodified lines | ||
| 508 | 507 | struct folio *folio; |
| 509 | 508 | struct queue_pages *qp = walk->private; |
| 510 | 509 | unsigned long flags = qp->flags; |
| 511 | − bool has_unmovable = false; | |
| 512 | 510 | pte_t *pte, *mapped_pte; |
| 513 | 511 | pte_t ptent; |
| 514 | 512 | spinlock_t *ptl; |
| @@ -538,11 +536,12 @@ static int queue_folios_pte_range(pmd_t *pmd, unsigned long addr, · 23 unmodified lines | ||
| 538 | 536 | if (!queue_folio_required(folio, qp)) |
| 539 | 537 | continue; |
| 540 | 538 | if (flags & (MPOL_MF_MOVE | MPOL_MF_MOVE_ALL)) { |
| 541 | − /* MPOL_MF_STRICT must be specified if we get here */ | |
| 542 | − if (!vma_migratable(vma)) { | |
| 543 | − has_unmovable = true; | |
| 544 | − break; | |
| 545 | − } | |
| 539 | + /* | |
| 540 | + * MPOL_MF_STRICT must be specified if we get here. | |
| 541 | + * Continue walking vmas due to MPOL_MF_MOVE* flags. | |
| 542 | + */ | |
| 543 | + if (!vma_migratable(vma)) | |
| 544 | + qp->has_unmovable = true; | |
| 546 | 545 | |
| 547 | 546 | /* |
| 548 | 547 | * Do not abort immediately since there may be |
| @@ -550,16 +549,13 @@ static int queue_folios_pte_range(pmd_t *pmd, unsigned long addr, · 1 unmodified line | ||
| 550 | 549 | * need migrate other LRU pages. |
| 551 | 550 | */ |
| 552 | 551 | if (migrate_folio_add(folio, qp->pagelist, flags)) |
| 553 | − has_unmovable = true; | |
| 552 | + qp->has_unmovable = true; | |
| 554 | 553 | } else |
| 555 | 554 | break; |
| 556 | 555 | } |
| 557 | 556 | pte_unmap_unlock(mapped_pte, ptl); |
| 558 | 557 | cond_resched(); |
| 559 | 558 | |
| 560 | − if (has_unmovable) | |
| 561 | − return 1; | |
| 562 | − | |
| 563 | 559 | return addr != end ? -EIO : 0; |
| 564 | 560 | } |
| 565 | 561 | |
| @@ -599,7 +595,7 @@ static int queue_folios_hugetlb(pte_t *pte, unsigned long hmask, · 33 unmodified lines | ||
| 599 | 595 | * Detecting misplaced folio but allow migrating folios which |
| 600 | 596 | * have been queued. |
| 601 | 597 | */ |
| 602 | − ret = 1; | |
| 598 | + qp->has_unmovable = true; | |
| 603 | 599 | goto unlock; |
| 604 | 600 | } |
| 605 | 601 | |
| @@ -620,7 +616,7 @@ static int queue_folios_hugetlb(pte_t *pte, unsigned long hmask, · 14 unmodified lines | ||
| 620 | 616 | * Failed to isolate folio but allow migrating pages |
| 621 | 617 | * which have been queued. |
| 622 | 618 | */ |
| 623 | − ret = 1; | |
| 619 | + qp->has_unmovable = true; | |
| 624 | 620 | } |
| 625 | 621 | unlock: |
| 626 | 622 | spin_unlock(ptl); |
| @@ -756,12 +752,15 @@ queue_pages_range(struct mm_struct *mm, unsigned long start, unsigned long end, · 129 unmodified lines | ||
| 756 | 752 | .start = start, |
| 757 | 753 | .end = end, |
| 758 | 754 | .first = NULL, |
| 755 | + .has_unmovable = false, | |
| 759 | 756 | }; |
| 760 | 757 | const struct mm_walk_ops *ops = lock_vma ? |
| 761 | 758 | &queue_pages_lock_vma_walk_ops : &queue_pages_walk_ops; |
| 762 | 759 | |
| 763 | 760 | err = walk_page_range(mm, start, end, ops, &qp); |
| 764 | 761 | |
| 762 | + if (qp.has_unmovable) | |
| 763 | + err = 1; | |
| 765 | 764 | if (!qp.first) |
| 766 | 765 | /* whole range in hole */ |
| 767 | 766 | err = -EFAULT; |
| @@ -1358,7 +1357,7 @@ static long do_mbind(unsigned long start, unsigned long len, · 590 unmodified lines | ||
| 1358 | 1357 | putback_movable_pages(&pagelist); |
| 1359 | 1358 | } |
| 1360 | 1359 | |
| 1361 | − if ((ret > 0) || (nr_failed && (flags & MPOL_MF_STRICT))) | |
| 1360 | + if (((ret > 0) || nr_failed) && (flags & MPOL_MF_STRICT)) | |
| 1362 | 1361 | err = -EIO; |
| 1363 | 1362 | } else { |
| 1364 | 1363 | up_out: |
| @@ -243,7 +243,9 @@ static bool remove_migration_pte(struct folio *folio, · 242 unmodified lines | ||
| 243 | 243 | |
| 244 | 244 | #ifdef CONFIG_HUGETLB_PAGE |
| 245 | 245 | if (folio_test_hugetlb(folio)) { |
| 246 | − unsigned int shift = huge_page_shift(hstate_vma(vma)); | |
| 246 | + struct hstate *h = hstate_vma(vma); | |
| 247 | + unsigned int shift = huge_page_shift(h); | |
| 248 | + unsigned long psize = huge_page_size(h); | |
| 247 | 249 | |
| 248 | 250 | pte = arch_make_huge_pte(pte, shift, vma->vm_flags); |
| 249 | 251 | if (folio_test_anon(folio)) |
| @@ -251,7 +253,8 @@ static bool remove_migration_pte(struct folio *folio, · 1 unmodified line | ||
| 251 | 253 | rmap_flags); |
| 252 | 254 | else |
| 253 | 255 | page_dup_file_rmap(new, true); |
| 254 | − set_huge_pte_at(vma->vm_mm, pvmw.address, pvmw.pte, pte); | |
| 256 | + set_huge_pte_at(vma->vm_mm, pvmw.address, pvmw.pte, pte, | |
| 257 | + psize); | |
| 255 | 258 | } else |
| 256 | 259 | #endif |
| 257 | 260 | { |
| @@ -2400,7 +2400,7 @@ void free_unref_page(struct page *page, unsigned int order) · 2399 unmodified lines | ||
| 2400 | 2400 | struct per_cpu_pages *pcp; |
| 2401 | 2401 | struct zone *zone; |
| 2402 | 2402 | unsigned long pfn = page_to_pfn(page); |
| 2403 | − int migratetype; | |
| 2403 | + int migratetype, pcpmigratetype; | |
| 2404 | 2404 | |
| 2405 | 2405 | if (!free_unref_page_prepare(page, pfn, order)) |
| 2406 | 2406 | return; |
| @@ -2408,24 +2408,24 @@ void free_unref_page(struct page *page, unsigned int order) · 1 unmodified line | ||
| 2408 | 2408 | /* |
| 2409 | 2409 | * We only track unmovable, reclaimable and movable on pcp lists. |
| 2410 | 2410 | * Place ISOLATE pages on the isolated list because they are being |
| 2411 | − * offlined but treat HIGHATOMIC as movable pages so we can get those | |
| 2412 | − * areas back if necessary. Otherwise, we may have to free | |
| 2411 | + * offlined but treat HIGHATOMIC and CMA as movable pages so we can | |
| 2412 | + * get those areas back if necessary. Otherwise, we may have to free | |
| 2413 | 2413 | * excessively into the page allocator |
| 2414 | 2414 | */ |
| 2415 | − migratetype = get_pcppage_migratetype(page); | |
| 2415 | + migratetype = pcpmigratetype = get_pcppage_migratetype(page); | |
| 2416 | 2416 | if (unlikely(migratetype >= MIGRATE_PCPTYPES)) { |
| 2417 | 2417 | if (unlikely(is_migrate_isolate(migratetype))) { |
| 2418 | 2418 | free_one_page(page_zone(page), page, pfn, order, migratetype, FPI_NONE); |
| 2419 | 2419 | return; |
| 2420 | 2420 | } |
| 2421 | − migratetype = MIGRATE_MOVABLE; | |
| 2421 | + pcpmigratetype = MIGRATE_MOVABLE; | |
| 2422 | 2422 | } |
| 2423 | 2423 | |
| 2424 | 2424 | zone = page_zone(page); |
| 2425 | 2425 | pcp_trylock_prepare(UP_flags); |
| 2426 | 2426 | pcp = pcp_spin_trylock(zone->per_cpu_pageset); |
| 2427 | 2427 | if (pcp) { |
| 2428 | − free_unref_page_commit(zone, pcp, page, migratetype, order); | |
| 2428 | + free_unref_page_commit(zone, pcp, page, pcpmigratetype, order); | |
| 2429 | 2429 | pcp_spin_unlock(pcp); |
| 2430 | 2430 | } else { |
| 2431 | 2431 | free_one_page(zone, page, pfn, order, migratetype, FPI_NONE); |
| @@ -1480,6 +1480,7 @@ static bool try_to_unmap_one(struct folio *folio, struct vm_area_struct *vma, · 1479 unmodified lines | ||
| 1480 | 1480 | struct mmu_notifier_range range; |
| 1481 | 1481 | enum ttu_flags flags = (enum ttu_flags)(long)arg; |
| 1482 | 1482 | unsigned long pfn; |
| 1483 | + unsigned long hsz = 0; | |
| 1483 | 1484 | |
| 1484 | 1485 | /* |
| 1485 | 1486 | * When racing against e.g. zap_pte_range() on another cpu, |
| @@ -1511,6 +1512,9 @@ static bool try_to_unmap_one(struct folio *folio, struct vm_area_struct *vma, · 25 unmodified lines | ||
| 1511 | 1512 | */ |
| 1512 | 1513 | adjust_range_if_pmd_sharing_possible(vma, &range.start, |
| 1513 | 1514 | &range.end); |
| 1515 | + | |
| 1516 | + /* We need the huge page size for set_huge_pte_at() */ | |
| 1517 | + hsz = huge_page_size(hstate_vma(vma)); | |
| 1514 | 1518 | } |
| 1515 | 1519 | mmu_notifier_invalidate_range_start(&range); |
| 1516 | 1520 | |
| @@ -1628,7 +1632,8 @@ static bool try_to_unmap_one(struct folio *folio, struct vm_area_struct *vma, · 111 unmodified lines | ||
| 1628 | 1632 | pteval = swp_entry_to_pte(make_hwpoison_entry(subpage)); |
| 1629 | 1633 | if (folio_test_hugetlb(folio)) { |
| 1630 | 1634 | hugetlb_count_sub(folio_nr_pages(folio), mm); |
| 1631 | − set_huge_pte_at(mm, address, pvmw.pte, pteval); | |
| 1635 | + set_huge_pte_at(mm, address, pvmw.pte, pteval, | |
| 1636 | + hsz); | |
| 1632 | 1637 | } else { |
| 1633 | 1638 | dec_mm_counter(mm, mm_counter(&folio->page)); |
| 1634 | 1639 | set_pte_at(mm, address, pvmw.pte, pteval); |
| @@ -1820,6 +1825,7 @@ static bool try_to_migrate_one(struct folio *folio, struct vm_area_struct *vma, · 185 unmodified lines | ||
| 1820 | 1825 | struct mmu_notifier_range range; |
| 1821 | 1826 | enum ttu_flags flags = (enum ttu_flags)(long)arg; |
| 1822 | 1827 | unsigned long pfn; |
| 1828 | + unsigned long hsz = 0; | |
| 1823 | 1829 | |
| 1824 | 1830 | /* |
| 1825 | 1831 | * When racing against e.g. zap_pte_range() on another cpu, |
| @@ -1855,6 +1861,9 @@ static bool try_to_migrate_one(struct folio *folio, struct vm_area_struct *vma, · 29 unmodified lines | ||
| 1855 | 1861 | */ |
| 1856 | 1862 | adjust_range_if_pmd_sharing_possible(vma, &range.start, |
| 1857 | 1863 | &range.end); |
| 1864 | + | |
| 1865 | + /* We need the huge page size for set_huge_pte_at() */ | |
| 1866 | + hsz = huge_page_size(hstate_vma(vma)); | |
| 1858 | 1867 | } |
| 1859 | 1868 | mmu_notifier_invalidate_range_start(&range); |
| 1860 | 1869 | |
| @@ -2020,7 +2029,8 @@ static bool try_to_migrate_one(struct folio *folio, struct vm_area_struct *vma, · 159 unmodified lines | ||
| 2020 | 2029 | pteval = swp_entry_to_pte(make_hwpoison_entry(subpage)); |
| 2021 | 2030 | if (folio_test_hugetlb(folio)) { |
| 2022 | 2031 | hugetlb_count_sub(folio_nr_pages(folio), mm); |
| 2023 | − set_huge_pte_at(mm, address, pvmw.pte, pteval); | |
| 2032 | + set_huge_pte_at(mm, address, pvmw.pte, pteval, | |
| 2033 | + hsz); | |
| 2024 | 2034 | } else { |
| 2025 | 2035 | dec_mm_counter(mm, mm_counter(&folio->page)); |
| 2026 | 2036 | set_pte_at(mm, address, pvmw.pte, pteval); |
| @@ -2044,7 +2054,8 @@ static bool try_to_migrate_one(struct folio *folio, struct vm_area_struct *vma, · 17 unmodified lines | ||
| 2044 | 2054 | |
| 2045 | 2055 | if (arch_unmap_one(mm, vma, address, pteval) < 0) { |
| 2046 | 2056 | if (folio_test_hugetlb(folio)) |
| 2047 | − set_huge_pte_at(mm, address, pvmw.pte, pteval); | |
| 2057 | + set_huge_pte_at(mm, address, pvmw.pte, | |
| 2058 | + pteval, hsz); | |
| 2048 | 2059 | else |
| 2049 | 2060 | set_pte_at(mm, address, pvmw.pte, pteval); |
| 2050 | 2061 | ret = false; |
| @@ -2058,7 +2069,8 @@ static bool try_to_migrate_one(struct folio *folio, struct vm_area_struct *vma, · 7 unmodified lines | ||
| 2058 | 2069 | if (anon_exclusive && |
| 2059 | 2070 | page_try_share_anon_rmap(subpage)) { |
| 2060 | 2071 | if (folio_test_hugetlb(folio)) |
| 2061 | − set_huge_pte_at(mm, address, pvmw.pte, pteval); | |
| 2072 | + set_huge_pte_at(mm, address, pvmw.pte, | |
| 2073 | + pteval, hsz); | |
| 2062 | 2074 | else |
| 2063 | 2075 | set_pte_at(mm, address, pvmw.pte, pteval); |
| 2064 | 2076 | ret = false; |
| @@ -2090,7 +2102,8 @@ static bool try_to_migrate_one(struct folio *folio, struct vm_area_struct *vma, · 25 unmodified lines | ||
| 2090 | 2102 | if (pte_uffd_wp(pteval)) |
| 2091 | 2103 | swp_pte = pte_swp_mkuffd_wp(swp_pte); |
| 2092 | 2104 | if (folio_test_hugetlb(folio)) |
| 2093 | − set_huge_pte_at(mm, address, pvmw.pte, swp_pte); | |
| 2105 | + set_huge_pte_at(mm, address, pvmw.pte, swp_pte, | |
| 2106 | + hsz); | |
| 2094 | 2107 | else |
| 2095 | 2108 | set_pte_at(mm, address, pvmw.pte, swp_pte); |
| 2096 | 2109 | trace_set_migration_pte(address, pte_val(swp_pte), |
| @@ -479,7 +479,7 @@ void slab_kmem_cache_release(struct kmem_cache *s) · 478 unmodified lines | ||
| 479 | 479 | |
| 480 | 480 | void kmem_cache_destroy(struct kmem_cache *s) |
| 481 | 481 | { |
| 482 | − int refcnt; | |
| 482 | + int err = -EBUSY; | |
| 483 | 483 | bool rcu_set; |
| 484 | 484 | |
| 485 | 485 | if (unlikely(!s) || !kasan_check_byte(s)) |
| @@ -490,17 +490,17 @@ void kmem_cache_destroy(struct kmem_cache *s) · 4 unmodified lines | ||
| 490 | 490 | |
| 491 | 491 | rcu_set = s->flags & SLAB_TYPESAFE_BY_RCU; |
| 492 | 492 | |
| 493 | − refcnt = --s->refcount; | |
| 494 | − if (refcnt) | |
| 493 | + s->refcount--; | |
| 494 | + if (s->refcount) | |
| 495 | 495 | goto out_unlock; |
| 496 | 496 | |
| 497 | − WARN(shutdown_cache(s), | |
| 498 | − "%s %s: Slab cache still has objects when called from %pS", | |
| 497 | + err = shutdown_cache(s); | |
| 498 | + WARN(err, "%s %s: Slab cache still has objects when called from %pS", | |
| 499 | 499 | __func__, s->name, (void *)_RET_IP_); |
| 500 | 500 | out_unlock: |
| 501 | 501 | mutex_unlock(&slab_mutex); |
| 502 | 502 | cpus_read_unlock(); |
| 503 | − if (!refcnt && !rcu_set) | |
| 503 | + if (!err && !rcu_set) | |
| 504 | 504 | kmem_cache_release(s); |
| 505 | 505 | } |
| 506 | 506 | EXPORT_SYMBOL(kmem_cache_destroy); |
| @@ -745,24 +745,24 @@ struct kmem_cache *kmalloc_slab(size_t size, gfp_t flags, unsigned long caller) · 238 unmodified lines | ||
| 745 | 745 | |
| 746 | 746 | size_t kmalloc_size_roundup(size_t size) |
| 747 | 747 | { |
| 748 | − struct kmem_cache *c; | |
| 748 | + if (size && size <= KMALLOC_MAX_CACHE_SIZE) { | |
| 749 | + /* | |
| 750 | + * The flags don't matter since size_index is common to all. | |
| 751 | + * Neither does the caller for just getting ->object_size. | |
| 752 | + */ | |
| 753 | + return kmalloc_slab(size, GFP_KERNEL, 0)->object_size; | |
| 754 | + } | |
| 749 | 755 | |
| 750 | − /* Short-circuit the 0 size case. */ | |
| 751 | − if (unlikely(size == 0)) | |
| 752 | − return 0; | |
| 753 | − /* Short-circuit saturated "too-large" case. */ | |
| 754 | − if (unlikely(size == SIZE_MAX)) | |
| 755 | − return SIZE_MAX; | |
| 756 | 756 | /* Above the smaller buckets, size is a multiple of page size. */ |
| 757 | − if (size > KMALLOC_MAX_CACHE_SIZE) | |
| 757 | + if (size && size <= KMALLOC_MAX_SIZE) | |
| 758 | 758 | return PAGE_SIZE << get_order(size); |
| 759 | 759 | |
| 760 | 760 | /* |
| 761 | − * The flags don't matter since size_index is common to all. | |
| 762 | − * Neither does the caller for just getting ->object_size. | |
| 761 | + * Return 'size' for 0 - kmalloc() returns ZERO_SIZE_PTR | |
| 762 | + * and very large size - kmalloc() may fail. | |
| 763 | 763 | */ |
| 764 | − c = kmalloc_slab(size, GFP_KERNEL, 0); | |
| 765 | − return c ? c->object_size : 0; | |
| 764 | + return size; | |
| 765 | + | |
| 766 | 766 | } |
| 767 | 767 | EXPORT_SYMBOL(kmalloc_size_roundup); |
| 768 | 768 | |
| @@ -111,7 +111,7 @@ static int vmap_pte_range(pmd_t *pmd, unsigned long addr, unsigned long end, · 110 unmodified lines | ||
| 111 | 111 | pte_t entry = pfn_pte(pfn, prot); |
| 112 | 112 | |
| 113 | 113 | entry = arch_make_huge_pte(entry, ilog2(size), 0); |
| 114 | − set_huge_pte_at(&init_mm, addr, pte, entry); | |
| 114 | + set_huge_pte_at(&init_mm, addr, pte, entry, size); | |
| 115 | 115 | pfn += PFN_DOWN(size); |
| 116 | 116 | continue; |
| 117 | 117 | } |
| @@ -1218,6 +1218,19 @@ bool zswap_store(struct folio *folio) · 1217 unmodified lines | ||
| 1218 | 1218 | if (!zswap_enabled || !tree) |
| 1219 | 1219 | return false; |
| 1220 | 1220 | |
| 1221 | + /* | |
| 1222 | + * If this is a duplicate, it must be removed before attempting to store | |
| 1223 | + * it, otherwise, if the store fails the old page won't be removed from | |
| 1224 | + * the tree, and it might be written back overriding the new data. | |
| 1225 | + */ | |
| 1226 | + spin_lock(&tree->lock); | |
| 1227 | + dupentry = zswap_rb_search(&tree->rbroot, offset); | |
| 1228 | + if (dupentry) { | |
| 1229 | + zswap_duplicate_entry++; | |
| 1230 | + zswap_invalidate_entry(tree, dupentry); | |
| 1231 | + } | |
| 1232 | + spin_unlock(&tree->lock); | |
| 1233 | + | |
| 1221 | 1234 | /* |
| 1222 | 1235 | * XXX: zswap reclaim does not work with cgroups yet. Without a |
| 1223 | 1236 | * cgroup-aware entry LRU, we will push out entries system-wide based on |
| @@ -1333,7 +1346,14 @@ insert_entry: · 109 unmodified lines | ||
| 1333 | 1346 | |
| 1334 | 1347 | /* map */ |
| 1335 | 1348 | spin_lock(&tree->lock); |
| 1349 | + /* | |
| 1350 | + * A duplicate entry should have been removed at the beginning of this | |
| 1351 | + * function. Since the swap entry should be pinned, if a duplicate is | |
| 1352 | + * found again here it means that something went wrong in the swap | |
| 1353 | + * cache. | |
| 1354 | + */ | |
| 1336 | 1355 | while (zswap_rb_insert(&tree->rbroot, entry, &dupentry) == -EEXIST) { |
| 1356 | + WARN_ON(1); | |
| 1337 | 1357 | zswap_duplicate_entry++; |
| 1338 | 1358 | zswap_invalidate_entry(tree, dupentry); |
| 1339 | 1359 | } |
| @@ -2413,34 +2413,41 @@ int hci_conn_security(struct hci_conn *conn, __u8 sec_level, __u8 auth_type, · 2412 unmodified lines | ||
| 2413 | 2413 | if (!test_bit(HCI_CONN_AUTH, &conn->flags)) |
| 2414 | 2414 | goto auth; |
| 2415 | 2415 | |
| 2416 | − /* An authenticated FIPS approved combination key has sufficient | |
| 2417 | − * security for security level 4. */ | |
| 2418 | − if (conn->key_type == HCI_LK_AUTH_COMBINATION_P256 && | |
| 2419 | − sec_level == BT_SECURITY_FIPS) | |
| 2420 | − goto encrypt; | |
| 2421 | − | |
| 2422 | − /* An authenticated combination key has sufficient security for | |
| 2423 | − security level 3. */ | |
| 2424 | − if ((conn->key_type == HCI_LK_AUTH_COMBINATION_P192 || | |
| 2425 | − conn->key_type == HCI_LK_AUTH_COMBINATION_P256) && | |
| 2426 | − sec_level == BT_SECURITY_HIGH) | |
| 2427 | − goto encrypt; | |
| 2428 | − | |
| 2429 | − /* An unauthenticated combination key has sufficient security for | |
| 2430 | − security level 1 and 2. */ | |
| 2431 | − if ((conn->key_type == HCI_LK_UNAUTH_COMBINATION_P192 || | |
| 2432 | − conn->key_type == HCI_LK_UNAUTH_COMBINATION_P256) && | |
| 2433 | − (sec_level == BT_SECURITY_MEDIUM || sec_level == BT_SECURITY_LOW)) | |
| 2434 | − goto encrypt; | |
| 2435 | − | |
| 2436 | − /* A combination key has always sufficient security for the security | |
| 2437 | − levels 1 or 2. High security level requires the combination key | |
| 2438 | − is generated using maximum PIN code length (16). | |
| 2439 | − For pre 2.1 units. */ | |
| 2440 | − if (conn->key_type == HCI_LK_COMBINATION && | |
| 2441 | − (sec_level == BT_SECURITY_MEDIUM || sec_level == BT_SECURITY_LOW || | |
| 2442 | − conn->pin_length == 16)) | |
| 2443 | − goto encrypt; | |
| 2416 | + switch (conn->key_type) { | |
| 2417 | + case HCI_LK_AUTH_COMBINATION_P256: | |
| 2418 | + /* An authenticated FIPS approved combination key has | |
| 2419 | + * sufficient security for security level 4 or lower. | |
| 2420 | + */ | |
| 2421 | + if (sec_level <= BT_SECURITY_FIPS) | |
| 2422 | + goto encrypt; | |
| 2423 | + break; | |
| 2424 | + case HCI_LK_AUTH_COMBINATION_P192: | |
| 2425 | + /* An authenticated combination key has sufficient security for | |
| 2426 | + * security level 3 or lower. | |
| 2427 | + */ | |
| 2428 | + if (sec_level <= BT_SECURITY_HIGH) | |
| 2429 | + goto encrypt; | |
| 2430 | + break; | |
| 2431 | + case HCI_LK_UNAUTH_COMBINATION_P192: | |
| 2432 | + case HCI_LK_UNAUTH_COMBINATION_P256: | |
| 2433 | + /* An unauthenticated combination key has sufficient security | |
| 2434 | + * for security level 2 or lower. | |
| 2435 | + */ | |
| 2436 | + if (sec_level <= BT_SECURITY_MEDIUM) | |
| 2437 | + goto encrypt; | |
| 2438 | + break; | |
| 2439 | + case HCI_LK_COMBINATION: | |
| 2440 | + /* A combination key has always sufficient security for the | |
| 2441 | + * security levels 2 or lower. High security level requires the | |
| 2442 | + * combination key is generated using maximum PIN code length | |
| 2443 | + * (16). For pre 2.1 units. | |
| 2444 | + */ | |
| 2445 | + if (sec_level <= BT_SECURITY_MEDIUM || conn->pin_length == 16) | |
| 2446 | + goto encrypt; | |
| 2447 | + break; | |
| 2448 | + default: | |
| 2449 | + break; | |
| 2450 | + } | |
| 2444 | 2451 | |
| 2445 | 2452 | auth: |
| 2446 | 2453 | if (test_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags)) |
| @@ -2617,7 +2617,11 @@ int hci_register_dev(struct hci_dev *hdev) · 2616 unmodified lines | ||
| 2617 | 2617 | if (id < 0) |
| 2618 | 2618 | return id; |
| 2619 | 2619 | |
| 2620 | − snprintf(hdev->name, sizeof(hdev->name), "hci%d", id); | |
| 2620 | + error = dev_set_name(&hdev->dev, "hci%u", id); | |
| 2621 | + if (error) | |
| 2622 | + return error; | |
| 2623 | + | |
| 2624 | + hdev->name = dev_name(&hdev->dev); | |
| 2621 | 2625 | hdev->id = id; |
| 2622 | 2626 | |
| 2623 | 2627 | BT_DBG("%p name %s bus %d", hdev, hdev->name, hdev->bus); |
| @@ -2639,8 +2643,6 @@ int hci_register_dev(struct hci_dev *hdev) · 15 unmodified lines | ||
| 2639 | 2643 | if (!IS_ERR_OR_NULL(bt_debugfs)) |
| 2640 | 2644 | hdev->debugfs = debugfs_create_dir(hdev->name, bt_debugfs); |
| 2641 | 2645 | |
| 2642 | − dev_set_name(&hdev->dev, "%s", hdev->name); | |
| 2643 | − | |
| 2644 | 2646 | error = device_add(&hdev->dev); |
| 2645 | 2647 | if (error < 0) |
| 2646 | 2648 | goto err_wqueue; |
| @@ -2784,6 +2786,7 @@ void hci_release_dev(struct hci_dev *hdev) · 137 unmodified lines | ||
| 2784 | 2786 | hci_conn_params_clear_all(hdev); |
| 2785 | 2787 | hci_discovery_filter_clear(hdev); |
| 2786 | 2788 | hci_blocked_keys_clear(hdev); |
| 2789 | + hci_codec_list_clear(&hdev->local_codecs); | |
| 2787 | 2790 | hci_dev_unlock(hdev); |
| 2788 | 2791 | |
| 2789 | 2792 | ida_simple_remove(&hci_index_ida, hdev->id); |
| @@ -3418,7 +3421,12 @@ static void hci_link_tx_to(struct hci_dev *hdev, __u8 type) · 628 unmodified lines | ||
| 3418 | 3421 | if (c->type == type && c->sent) { |
| 3419 | 3422 | bt_dev_err(hdev, "killing stalled connection %pMR", |
| 3420 | 3423 | &c->dst); |
| 3424 | + /* hci_disconnect might sleep, so, we have to release | |
| 3425 | + * the RCU read lock before calling it. | |
| 3426 | + */ | |
| 3427 | + rcu_read_unlock(); | |
| 3421 | 3428 | hci_disconnect(c, HCI_ERROR_REMOTE_USER_TERM); |
| 3429 | + rcu_read_lock(); | |
| 3422 | 3430 | } |
| 3423 | 3431 | } |
| 3424 | 3432 | |
| @@ -33,6 +33,7 @@ · 32 unmodified lines | ||
| 33 | 33 | |
| 34 | 34 | #include "hci_request.h" |
| 35 | 35 | #include "hci_debugfs.h" |
| 36 | +#include "hci_codec.h" | |
| 36 | 37 | #include "a2mp.h" |
| 37 | 38 | #include "amp.h" |
| 38 | 39 | #include "smp.h" |
| @@ -71,7 +71,5 @@ struct sk_buff *hci_prepare_cmd(struct hci_dev *hdev, u16 opcode, u32 plen, · 70 unmodified lines | ||
| 71 | 71 | void hci_req_add_le_scan_disable(struct hci_request *req, bool rpa_le_conn); |
| 72 | 72 | void hci_req_add_le_passive_scan(struct hci_request *req); |
| 73 | 73 | |
| 74 | −void hci_req_prepare_suspend(struct hci_dev *hdev, enum suspended_state next); | |
| 75 | − | |
| 76 | 74 | void hci_request_setup(struct hci_dev *hdev); |
| 77 | 75 | void hci_request_cancel_all(struct hci_dev *hdev); |
| @@ -413,11 +413,6 @@ static int hci_le_scan_restart_sync(struct hci_dev *hdev) · 412 unmodified lines | ||
| 413 | 413 | LE_SCAN_FILTER_DUP_ENABLE); |
| 414 | 414 | } |
| 415 | 415 | |
| 416 | −static int le_scan_restart_sync(struct hci_dev *hdev, void *data) | |
| 417 | −{ | |
| 418 | − return hci_le_scan_restart_sync(hdev); | |
| 419 | −} | |
| 420 | − | |
| 421 | 416 | static void le_scan_restart(struct work_struct *work) |
| 422 | 417 | { |
| 423 | 418 | struct hci_dev *hdev = container_of(work, struct hci_dev, |
| @@ -427,15 +422,15 @@ static void le_scan_restart(struct work_struct *work) · 3 unmodified lines | ||
| 427 | 422 | |
| 428 | 423 | bt_dev_dbg(hdev, ""); |
| 429 | 424 | |
| 430 | − hci_dev_lock(hdev); | |
| 431 | − | |
| 432 | − status = hci_cmd_sync_queue(hdev, le_scan_restart_sync, NULL, NULL); | |
| 425 | + status = hci_le_scan_restart_sync(hdev); | |
| 433 | 426 | if (status) { |
| 434 | 427 | bt_dev_err(hdev, "failed to restart LE scan: status %d", |
| 435 | 428 | status); |
| 436 | − goto unlock; | |
| 429 | + return; | |
| 437 | 430 | } |
| 438 | 431 | |
| 432 | + hci_dev_lock(hdev); | |
| 433 | + | |
| 439 | 434 | if (!test_bit(HCI_QUIRK_STRICT_DUPLICATE_FILTER, &hdev->quirks) || |
| 440 | 435 | !hdev->discovery.scan_start) |
| 441 | 436 | goto unlock; |
| @@ -5079,6 +5074,7 @@ int hci_dev_close_sync(struct hci_dev *hdev) · 4637 unmodified lines | ||
| 5079 | 5074 | memset(hdev->eir, 0, sizeof(hdev->eir)); |
| 5080 | 5075 | memset(hdev->dev_class, 0, sizeof(hdev->dev_class)); |
| 5081 | 5076 | bacpy(&hdev->random_addr, BDADDR_ANY); |
| 5077 | + hci_codec_list_clear(&hdev->local_codecs); | |
| 5082 | 5078 | |
| 5083 | 5079 | hci_dev_put(hdev); |
| 5084 | 5080 | return err; |
| @@ -502,7 +502,7 @@ drop: · 501 unmodified lines | ||
| 502 | 502 | } |
| 503 | 503 | |
| 504 | 504 | /* -------- Socket interface ---------- */ |
| 505 | −static struct sock *__iso_get_sock_listen_by_addr(bdaddr_t *ba) | |
| 505 | +static struct sock *__iso_get_sock_listen_by_addr(bdaddr_t *src, bdaddr_t *dst) | |
| 506 | 506 | { |
| 507 | 507 | struct sock *sk; |
| 508 | 508 | |
| @@ -510,7 +510,10 @@ static struct sock *__iso_get_sock_listen_by_addr(bdaddr_t *ba) · 1 unmodified line | ||
| 510 | 510 | if (sk->sk_state != BT_LISTEN) |
| 511 | 511 | continue; |
| 512 | 512 | |
| 513 | − if (!bacmp(&iso_pi(sk)->src, ba)) | |
| 513 | + if (bacmp(&iso_pi(sk)->dst, dst)) | |
| 514 | + continue; | |
| 515 | + | |
| 516 | + if (!bacmp(&iso_pi(sk)->src, src)) | |
| 514 | 517 | return sk; |
| 515 | 518 | } |
| 516 | 519 | |
| @@ -952,7 +955,7 @@ static int iso_listen_cis(struct sock *sk) · 435 unmodified lines | ||
| 952 | 955 | |
| 953 | 956 | write_lock(&iso_sk_list.lock); |
| 954 | 957 | |
| 955 | − if (__iso_get_sock_listen_by_addr(&iso_pi(sk)->src)) | |
| 958 | + if (__iso_get_sock_listen_by_addr(&iso_pi(sk)->src, &iso_pi(sk)->dst)) | |
| 956 | 959 | err = -EADDRINUSE; |
| 957 | 960 | |
| 958 | 961 | write_unlock(&iso_sk_list.lock); |
| @@ -294,7 +294,7 @@ int br_nf_pre_routing_finish_bridge(struct net *net, struct sock *sk, struct sk_ · 293 unmodified lines | ||
| 294 | 294 | /* tell br_dev_xmit to continue with forwarding */ |
| 295 | 295 | nf_bridge->bridged_dnat = 1; |
| 296 | 296 | /* FIXME Need to refragment */ |
| 297 | − ret = neigh->output(neigh, skb); | |
| 297 | + ret = READ_ONCE(neigh->output)(neigh, skb); | |
| 298 | 298 | } |
| 299 | 299 | neigh_release(neigh); |
| 300 | 300 | return ret; |
| @@ -410,7 +410,7 @@ static void neigh_flush_dev(struct neigh_table *tbl, struct net_device *dev, · 409 unmodified lines | ||
| 410 | 410 | */ |
| 411 | 411 | __skb_queue_purge(&n->arp_queue); |
| 412 | 412 | n->arp_queue_len_bytes = 0; |
| 413 | − n->output = neigh_blackhole; | |
| 413 | + WRITE_ONCE(n->output, neigh_blackhole); | |
| 414 | 414 | if (n->nud_state & NUD_VALID) |
| 415 | 415 | n->nud_state = NUD_NOARP; |
| 416 | 416 | else |
| @@ -920,7 +920,7 @@ static void neigh_suspect(struct neighbour *neigh) · 503 unmodified lines | ||
| 920 | 920 | { |
| 921 | 921 | neigh_dbg(2, "neigh %p is suspected\n", neigh); |
| 922 | 922 | |
| 923 | − neigh->output = neigh->ops->output; | |
| 923 | + WRITE_ONCE(neigh->output, neigh->ops->output); | |
| 924 | 924 | } |
| 925 | 925 | |
| 926 | 926 | /* Neighbour state is OK; |
| @@ -932,7 +932,7 @@ static void neigh_connect(struct neighbour *neigh) · 5 unmodified lines | ||
| 932 | 932 | { |
| 933 | 933 | neigh_dbg(2, "neigh %p is connected\n", neigh); |
| 934 | 934 | |
| 935 | − neigh->output = neigh->ops->connected_output; | |
| 935 | + WRITE_ONCE(neigh->output, neigh->ops->connected_output); | |
| 936 | 936 | } |
| 937 | 937 | |
| 938 | 938 | static void neigh_periodic_work(struct work_struct *work) |
| @@ -988,7 +988,9 @@ static void neigh_periodic_work(struct work_struct *work) · 49 unmodified lines | ||
| 988 | 988 | (state == NUD_FAILED || |
| 989 | 989 | !time_in_range_open(jiffies, n->used, |
| 990 | 990 | n->used + NEIGH_VAR(n->parms, GC_STALETIME)))) { |
| 991 | − *np = n->next; | |
| 991 | + rcu_assign_pointer(*np, | |
| 992 | + rcu_dereference_protected(n->next, | |
| 993 | + lockdep_is_held(&tbl->lock))); | |
| 992 | 994 | neigh_mark_dead(n); |
| 993 | 995 | write_unlock(&n->lock); |
| 994 | 996 | neigh_cleanup_and_release(n); |
| @@ -1447,7 +1449,7 @@ static int __neigh_update(struct neighbour *neigh, const u8 *lladdr, · 452 unmodified lines | ||
| 1447 | 1449 | if (n2) |
| 1448 | 1450 | n1 = n2; |
| 1449 | 1451 | } |
| 1450 | − n1->output(n1, skb); | |
| 1452 | + READ_ONCE(n1->output)(n1, skb); | |
| 1451 | 1453 | if (n2) |
| 1452 | 1454 | neigh_release(n2); |
| 1453 | 1455 | rcu_read_unlock(); |
| @@ -3153,7 +3155,7 @@ int neigh_xmit(int index, struct net_device *dev, · 1699 unmodified lines | ||
| 3153 | 3155 | rcu_read_unlock(); |
| 3154 | 3156 | goto out_kfree_skb; |
| 3155 | 3157 | } |
| 3156 | − err = neigh->output(neigh, skb); | |
| 3158 | + err = READ_ONCE(neigh->output)(neigh, skb); | |
| 3157 | 3159 | rcu_read_unlock(); |
| 3158 | 3160 | } |
| 3159 | 3161 | else if (index == NEIGH_LINK_TABLE) { |
| @@ -668,6 +668,8 @@ BPF_CALL_4(bpf_msg_redirect_map, struct sk_msg *, msg, · 667 unmodified lines | ||
| 668 | 668 | sk = __sock_map_lookup_elem(map, key); |
| 669 | 669 | if (unlikely(!sk || !sock_map_redirect_allowed(sk))) |
| 670 | 670 | return SK_DROP; |
| 671 | + if (!(flags & BPF_F_INGRESS) && !sk_is_tcp(sk)) | |
| 672 | + return SK_DROP; | |
| 671 | 673 | |
| 672 | 674 | msg->flags = flags; |
| 673 | 675 | msg->sk_redir = sk; |
| @@ -1267,6 +1269,8 @@ BPF_CALL_4(bpf_msg_redirect_hash, struct sk_msg *, msg, · 593 unmodified lines | ||
| 1267 | 1269 | sk = __sock_hash_lookup_elem(map, key); |
| 1268 | 1270 | if (unlikely(!sk || !sock_map_redirect_allowed(sk))) |
| 1269 | 1271 | return SK_DROP; |
| 1272 | + if (!(flags & BPF_F_INGRESS) && !sk_is_tcp(sk)) | |
| 1273 | + return SK_DROP; | |
| 1270 | 1274 | |
| 1271 | 1275 | msg->flags = flags; |
| 1272 | 1276 | msg->sk_redir = sk; |
| @@ -21,16 +21,6 @@ struct plca_reply_data { · 20 unmodified lines | ||
| 21 | 21 | #define PLCA_REPDATA(__reply_base) \ |
| 22 | 22 | container_of(__reply_base, struct plca_reply_data, base) |
| 23 | 23 | |
| 24 | −static void plca_update_sint(int *dst, const struct nlattr *attr, | |
| 25 | − bool *mod) | |
| 26 | −{ | |
| 27 | − if (!attr) | |
| 28 | − return; | |
| 29 | − | |
| 30 | − *dst = nla_get_u32(attr); | |
| 31 | − *mod = true; | |
| 32 | −} | |
| 33 | − | |
| 34 | 24 | // PLCA get configuration message ------------------------------------------- // |
| 35 | 25 | |
| 36 | 26 | const struct nla_policy ethnl_plca_get_cfg_policy[] = { |
| @@ -38,6 +28,29 @@ const struct nla_policy ethnl_plca_get_cfg_policy[] = { · 1 unmodified line | ||
| 38 | 28 | NLA_POLICY_NESTED(ethnl_header_policy), |
| 39 | 29 | }; |
| 40 | 30 | |
| 31 | +static void plca_update_sint(int *dst, struct nlattr **tb, u32 attrid, | |
| 32 | + bool *mod) | |
| 33 | +{ | |
| 34 | + const struct nlattr *attr = tb[attrid]; | |
| 35 | + | |
| 36 | + if (!attr || | |
| 37 | + WARN_ON_ONCE(attrid >= ARRAY_SIZE(ethnl_plca_set_cfg_policy))) | |
| 38 | + return; | |
| 39 | + | |
| 40 | + switch (ethnl_plca_set_cfg_policy[attrid].type) { | |
| 41 | + case NLA_U8: | |
| 42 | + *dst = nla_get_u8(attr); | |
| 43 | + break; | |
| 44 | + case NLA_U32: | |
| 45 | + *dst = nla_get_u32(attr); | |
| 46 | + break; | |
| 47 | + default: | |
| 48 | + WARN_ON_ONCE(1); | |
| 49 | + } | |
| 50 | + | |
| 51 | + *mod = true; | |
| 52 | +} | |
| 53 | + | |
| 41 | 54 | static int plca_get_cfg_prepare_data(const struct ethnl_req_info *req_base, |
| 42 | 55 | struct ethnl_reply_data *reply_base, |
| 43 | 56 | const struct genl_info *info) |
| @@ -144,13 +157,13 @@ ethnl_set_plca(struct ethnl_req_info *req_info, struct genl_info *info) · 100 unmodified lines | ||
| 144 | 157 | return -EOPNOTSUPP; |
| 145 | 158 | |
| 146 | 159 | memset(&plca_cfg, 0xff, sizeof(plca_cfg)); |
| 147 | − plca_update_sint(&plca_cfg.enabled, tb[ETHTOOL_A_PLCA_ENABLED], &mod); | |
| 148 | − plca_update_sint(&plca_cfg.node_id, tb[ETHTOOL_A_PLCA_NODE_ID], &mod); | |
| 149 | − plca_update_sint(&plca_cfg.node_cnt, tb[ETHTOOL_A_PLCA_NODE_CNT], &mod); | |
| 150 | − plca_update_sint(&plca_cfg.to_tmr, tb[ETHTOOL_A_PLCA_TO_TMR], &mod); | |
| 151 | − plca_update_sint(&plca_cfg.burst_cnt, tb[ETHTOOL_A_PLCA_BURST_CNT], | |
| 160 | + plca_update_sint(&plca_cfg.enabled, tb, ETHTOOL_A_PLCA_ENABLED, &mod); | |
| 161 | + plca_update_sint(&plca_cfg.node_id, tb, ETHTOOL_A_PLCA_NODE_ID, &mod); | |
| 162 | + plca_update_sint(&plca_cfg.node_cnt, tb, ETHTOOL_A_PLCA_NODE_CNT, &mod); | |
| 163 | + plca_update_sint(&plca_cfg.to_tmr, tb, ETHTOOL_A_PLCA_TO_TMR, &mod); | |
| 164 | + plca_update_sint(&plca_cfg.burst_cnt, tb, ETHTOOL_A_PLCA_BURST_CNT, | |
| 152 | 165 | &mod); |
| 153 | − plca_update_sint(&plca_cfg.burst_tmr, tb[ETHTOOL_A_PLCA_BURST_TMR], | |
| 166 | + plca_update_sint(&plca_cfg.burst_tmr, tb, ETHTOOL_A_PLCA_BURST_TMR, | |
| 154 | 167 | &mod); |
| 155 | 168 | if (!mod) |
| 156 | 169 | return 0; |
| @@ -1887,6 +1887,7 @@ int fib_sync_down_addr(struct net_device *dev, __be32 local) · 1886 unmodified lines | ||
| 1887 | 1887 | continue; |
| 1888 | 1888 | if (fi->fib_prefsrc == local) { |
| 1889 | 1889 | fi->fib_flags |= RTNH_F_DEAD; |
| 1890 | + fi->pfsrc_removed = true; | |
| 1890 | 1891 | ret++; |
| 1891 | 1892 | } |
| 1892 | 1893 | } |
| @@ -2027,6 +2027,7 @@ void fib_table_flush_external(struct fib_table *tb) · 2026 unmodified lines | ||
| 2027 | 2027 | int fib_table_flush(struct net *net, struct fib_table *tb, bool flush_all) |
| 2028 | 2028 | { |
| 2029 | 2029 | struct trie *t = (struct trie *)tb->tb_data; |
| 2030 | + struct nl_info info = { .nl_net = net }; | |
| 2030 | 2031 | struct key_vector *pn = t->kv; |
| 2031 | 2032 | unsigned long cindex = 1; |
| 2032 | 2033 | struct hlist_node *tmp; |
| @@ -2089,6 +2090,9 @@ int fib_table_flush(struct net *net, struct fib_table *tb, bool flush_all) · 56 unmodified lines | ||
| 2089 | 2090 | |
| 2090 | 2091 | fib_notify_alias_delete(net, n->key, &n->leaf, fa, |
| 2091 | 2092 | NULL); |
| 2093 | + if (fi->pfsrc_removed) | |
| 2094 | + rtmsg_fib(RTM_DELROUTE, htonl(n->key), fa, | |
| 2095 | + KEYLENGTH - fa->fa_slen, tb->tb_id, &info, 0); | |
| 2092 | 2096 | hlist_del_rcu(&fa->fa_list); |
| 2093 | 2097 | fib_release_info(fa->fa_info); |
| 2094 | 2098 | alias_free_mem_rcu(fa); |
| @@ -3417,6 +3417,8 @@ static int inet_rtm_getroute(struct sk_buff *in_skb, struct nlmsghdr *nlh, · 3416 unmodified lines | ||
| 3417 | 3417 | fa->fa_type == fri.type) { |
| 3418 | 3418 | fri.offload = READ_ONCE(fa->offload); |
| 3419 | 3419 | fri.trap = READ_ONCE(fa->trap); |
| 3420 | + fri.offload_failed = | |
| 3421 | + READ_ONCE(fa->offload_failed); | |
| 3420 | 3422 | break; |
| 3421 | 3423 | } |
| 3422 | 3424 | } |
| @@ -1621,16 +1621,13 @@ EXPORT_SYMBOL(tcp_read_sock); · 1620 unmodified lines | ||
| 1621 | 1621 | |
| 1622 | 1622 | int tcp_read_skb(struct sock *sk, skb_read_actor_t recv_actor) |
| 1623 | 1623 | { |
| 1624 | − struct tcp_sock *tp = tcp_sk(sk); | |
| 1625 | − u32 seq = tp->copied_seq; | |
| 1626 | 1624 | struct sk_buff *skb; |
| 1627 | 1625 | int copied = 0; |
| 1628 | − u32 offset; | |
| 1629 | 1626 | |
| 1630 | 1627 | if (sk->sk_state == TCP_LISTEN) |
| 1631 | 1628 | return -ENOTCONN; |
| 1632 | 1629 | |
| 1633 | − while ((skb = tcp_recv_skb(sk, seq, &offset)) != NULL) { | |
| 1630 | + while ((skb = skb_peek(&sk->sk_receive_queue)) != NULL) { | |
| 1634 | 1631 | u8 tcp_flags; |
| 1635 | 1632 | int used; |
| 1636 | 1633 | |
| @@ -1643,13 +1640,10 @@ int tcp_read_skb(struct sock *sk, skb_read_actor_t recv_actor) · 6 unmodified lines | ||
| 1643 | 1640 | copied = used; |
| 1644 | 1641 | break; |
| 1645 | 1642 | } |
| 1646 | − seq += used; | |
| 1647 | 1643 | copied += used; |
| 1648 | 1644 | |
| 1649 | − if (tcp_flags & TCPHDR_FIN) { | |
| 1650 | − ++seq; | |
| 1645 | + if (tcp_flags & TCPHDR_FIN) | |
| 1651 | 1646 | break; |
| 1652 | − } | |
| 1653 | 1647 | } |
| 1654 | 1648 | return copied; |
| 1655 | 1649 | } |
| @@ -222,6 +222,7 @@ static int tcp_bpf_recvmsg_parser(struct sock *sk, · 221 unmodified lines | ||
| 222 | 222 | int *addr_len) |
| 223 | 223 | { |
| 224 | 224 | struct tcp_sock *tcp = tcp_sk(sk); |
| 225 | + int peek = flags & MSG_PEEK; | |
| 225 | 226 | u32 seq = tcp->copied_seq; |
| 226 | 227 | struct sk_psock *psock; |
| 227 | 228 | int copied = 0; |
| @@ -311,7 +312,8 @@ msg_bytes_ready: · 83 unmodified lines | ||
| 311 | 312 | copied = -EAGAIN; |
| 312 | 313 | } |
| 313 | 314 | out: |
| 314 | − WRITE_ONCE(tcp->copied_seq, seq); | |
| 315 | + if (!peek) | |
| 316 | + WRITE_ONCE(tcp->copied_seq, seq); | |
| 315 | 317 | tcp_rcv_space_adjust(sk); |
| 316 | 318 | if (copied > 0) |
| 317 | 319 | __tcp_cleanup_rbuf(sk, copied); |
| @@ -253,6 +253,19 @@ static void tcp_measure_rcv_mss(struct sock *sk, const struct sk_buff *skb) · 252 unmodified lines | ||
| 253 | 253 | if (unlikely(len > icsk->icsk_ack.rcv_mss + |
| 254 | 254 | MAX_TCP_OPTION_SPACE)) |
| 255 | 255 | tcp_gro_dev_warn(sk, skb, len); |
| 256 | + /* If the skb has a len of exactly 1*MSS and has the PSH bit | |
| 257 | + * set then it is likely the end of an application write. So | |
| 258 | + * more data may not be arriving soon, and yet the data sender | |
| 259 | + * may be waiting for an ACK if cwnd-bound or using TX zero | |
| 260 | + * copy. So we set ICSK_ACK_PUSHED here so that | |
| 261 | + * tcp_cleanup_rbuf() will send an ACK immediately if the app | |
| 262 | + * reads all of the data and is not ping-pong. If len > MSS | |
| 263 | + * then this logic does not matter (and does not hurt) because | |
| 264 | + * tcp_cleanup_rbuf() will always ACK immediately if the app | |
| 265 | + * reads data and there is more than an MSS of unACKed data. | |
| 266 | + */ | |
| 267 | + if (TCP_SKB_CB(skb)->tcp_flags & TCPHDR_PSH) | |
| 268 | + icsk->icsk_ack.pending |= ICSK_ACK_PUSHED; | |
| 256 | 269 | } else { |
| 257 | 270 | /* Otherwise, we make more careful check taking into account, |
| 258 | 271 | * that SACKs block is variable. |
| @@ -177,8 +177,7 @@ static void tcp_event_data_sent(struct tcp_sock *tp, · 176 unmodified lines | ||
| 177 | 177 | } |
| 178 | 178 | |
| 179 | 179 | /* Account for an ACK we sent. */ |
| 180 | −static inline void tcp_event_ack_sent(struct sock *sk, unsigned int pkts, | |
| 181 | − u32 rcv_nxt) | |
| 180 | +static inline void tcp_event_ack_sent(struct sock *sk, u32 rcv_nxt) | |
| 182 | 181 | { |
| 183 | 182 | struct tcp_sock *tp = tcp_sk(sk); |
| 184 | 183 | |
| @@ -192,7 +191,7 @@ static inline void tcp_event_ack_sent(struct sock *sk, unsigned int pkts, · 7 unmodified lines | ||
| 192 | 191 | |
| 193 | 192 | if (unlikely(rcv_nxt != tp->rcv_nxt)) |
| 194 | 193 | return; /* Special ACK sent by DCTCP to reflect ECN */ |
| 195 | − tcp_dec_quickack_mode(sk, pkts); | |
| 194 | + tcp_dec_quickack_mode(sk); | |
| 196 | 195 | inet_csk_clear_xmit_timer(sk, ICSK_TIME_DACK); |
| 197 | 196 | } |
| 198 | 197 | |
| @@ -1380,7 +1379,7 @@ static int __tcp_transmit_skb(struct sock *sk, struct sk_buff *skb, · 1181 unmodified lines | ||
| 1380 | 1379 | sk, skb); |
| 1381 | 1380 | |
| 1382 | 1381 | if (likely(tcb->tcp_flags & TCPHDR_ACK)) |
| 1383 | − tcp_event_ack_sent(sk, tcp_skb_pcount(skb), rcv_nxt); | |
| 1382 | + tcp_event_ack_sent(sk, rcv_nxt); | |
| 1384 | 1383 | |
| 1385 | 1384 | if (skb->len != tcp_header_size) { |
| 1386 | 1385 | tcp_event_data_sent(tp, sk); |
| @@ -1639,9 +1639,12 @@ process: · 1638 unmodified lines | ||
| 1639 | 1639 | struct sock *nsk; |
| 1640 | 1640 | |
| 1641 | 1641 | sk = req->rsk_listener; |
| 1642 | − drop_reason = tcp_inbound_md5_hash(sk, skb, | |
| 1643 | − &hdr->saddr, &hdr->daddr, | |
| 1644 | − AF_INET6, dif, sdif); | |
| 1642 | + if (!xfrm6_policy_check(sk, XFRM_POLICY_IN, skb)) | |
| 1643 | + drop_reason = SKB_DROP_REASON_XFRM_POLICY; | |
| 1644 | + else | |
| 1645 | + drop_reason = tcp_inbound_md5_hash(sk, skb, | |
| 1646 | + &hdr->saddr, &hdr->daddr, | |
| 1647 | + AF_INET6, dif, sdif); | |
| 1645 | 1648 | if (drop_reason) { |
| 1646 | 1649 | sk_drops_add(sk, skb); |
| 1647 | 1650 | reqsk_put(req); |
| @@ -1688,6 +1691,7 @@ process: · 40 unmodified lines | ||
| 1688 | 1691 | } |
| 1689 | 1692 | goto discard_and_relse; |
| 1690 | 1693 | } |
| 1694 | + nf_reset_ct(skb); | |
| 1691 | 1695 | if (nsk == sk) { |
| 1692 | 1696 | reqsk_put(req); |
| 1693 | 1697 | tcp_v6_restore_cb(skb); |
| @@ -507,7 +507,6 @@ static int l2tp_ip6_sendmsg(struct sock *sk, struct msghdr *msg, size_t len) · 506 unmodified lines | ||
| 507 | 507 | */ |
| 508 | 508 | if (len > INT_MAX - transhdrlen) |
| 509 | 509 | return -EMSGSIZE; |
| 510 | − ulen = len + transhdrlen; | |
| 511 | 510 | |
| 512 | 511 | /* Mirror BSD error message compatibility */ |
| 513 | 512 | if (msg->msg_flags & MSG_OOB) |
| @@ -628,6 +627,7 @@ static int l2tp_ip6_sendmsg(struct sock *sk, struct msghdr *msg, size_t len) · 114 unmodified lines | ||
| 628 | 627 | |
| 629 | 628 | back_from_confirm: |
| 630 | 629 | lock_sock(sk); |
| 630 | + ulen = len + skb_queue_empty(&sk->sk_write_queue) ? transhdrlen : 0; | |
| 631 | 631 | err = ip6_append_data(sk, ip_generic_getfrag, msg, |
| 632 | 632 | ulen, transhdrlen, &ipc6, |
| 633 | 633 | &fl6, (struct rt6_info *)dst, |
| @@ -566,6 +566,9 @@ static int ieee80211_add_key(struct wiphy *wiphy, struct net_device *dev, · 565 unmodified lines | ||
| 566 | 566 | } |
| 567 | 567 | |
| 568 | 568 | err = ieee80211_key_link(key, link, sta); |
| 569 | + /* KRACK protection, shouldn't happen but just silently accept key */ | |
| 570 | + if (err == -EALREADY) | |
| 571 | + err = 0; | |
| 569 | 572 | |
| 570 | 573 | out_unlock: |
| 571 | 574 | mutex_unlock(&local->sta_mtx); |
| @@ -1857,7 +1860,8 @@ static int sta_link_apply_parameters(struct ieee80211_local *local, · 1285 unmodified lines | ||
| 1857 | 1860 | /* VHT can override some HT caps such as the A-MSDU max length */ |
| 1858 | 1861 | if (params->vht_capa) |
| 1859 | 1862 | ieee80211_vht_cap_ie_to_sta_vht_cap(sdata, sband, |
| 1860 | − params->vht_capa, link_sta); | |
| 1863 | + params->vht_capa, NULL, | |
| 1864 | + link_sta); | |
| 1861 | 1865 | |
| 1862 | 1866 | if (params->he_capa) |
| 1863 | 1867 | ieee80211_he_cap_ie_to_sta_he_cap(sdata, sband, |
| @@ -1072,7 +1072,7 @@ static void ieee80211_update_sta_info(struct ieee80211_sub_if_data *sdata, · 1071 unmodified lines | ||
| 1072 | 1072 | &chandef); |
| 1073 | 1073 | memcpy(&cap_ie, elems->vht_cap_elem, sizeof(cap_ie)); |
| 1074 | 1074 | ieee80211_vht_cap_ie_to_sta_vht_cap(sdata, sband, |
| 1075 | − &cap_ie, | |
| 1075 | + &cap_ie, NULL, | |
| 1076 | 1076 | &sta->deflink); |
| 1077 | 1077 | if (memcmp(&cap, &sta->sta.deflink.vht_cap, sizeof(cap))) |
| 1078 | 1078 | rates_updated |= true; |
| @@ -676,7 +676,7 @@ struct ieee80211_if_mesh { · 675 unmodified lines | ||
| 676 | 676 | struct timer_list mesh_path_root_timer; |
| 677 | 677 | |
| 678 | 678 | unsigned long wrkq_flags; |
| 679 | − unsigned long mbss_changed; | |
| 679 | + unsigned long mbss_changed[64 / BITS_PER_LONG]; | |
| 680 | 680 | |
| 681 | 681 | bool userspace_handles_dfs; |
| 682 | 682 | |
| @@ -2141,6 +2141,7 @@ void · 1458 unmodified lines | ||
| 2141 | 2141 | ieee80211_vht_cap_ie_to_sta_vht_cap(struct ieee80211_sub_if_data *sdata, |
| 2142 | 2142 | struct ieee80211_supported_band *sband, |
| 2143 | 2143 | const struct ieee80211_vht_cap *vht_cap_ie, |
| 2144 | + const struct ieee80211_vht_cap *vht_cap_ie2, | |
| 2144 | 2145 | struct link_sta_info *link_sta); |
| 2145 | 2146 | enum ieee80211_sta_rx_bandwidth |
| 2146 | 2147 | ieee80211_sta_cap_rx_bw(struct link_sta_info *link_sta); |
| @@ -802,6 +802,9 @@ static void ieee80211_key_destroy(struct ieee80211_key *key, · 801 unmodified lines | ||
| 802 | 802 | |
| 803 | 803 | void ieee80211_key_free_unused(struct ieee80211_key *key) |
| 804 | 804 | { |
| 805 | + if (!key) | |
| 806 | + return; | |
| 807 | + | |
| 805 | 808 | WARN_ON(key->sdata || key->local); |
| 806 | 809 | ieee80211_key_free_common(key); |
| 807 | 810 | } |
| @@ -854,7 +857,7 @@ int ieee80211_key_link(struct ieee80211_key *key, · 46 unmodified lines | ||
| 854 | 857 | * can cause warnings to appear. |
| 855 | 858 | */ |
| 856 | 859 | bool delay_tailroom = sdata->vif.type == NL80211_IFTYPE_STATION; |
| 857 | − int ret = -EOPNOTSUPP; | |
| 860 | + int ret; | |
| 858 | 861 | |
| 859 | 862 | mutex_lock(&sdata->local->key_mtx); |
| 860 | 863 | |
| @@ -868,8 +871,10 @@ int ieee80211_key_link(struct ieee80211_key *key, · 7 unmodified lines | ||
| 868 | 871 | * the same cipher. Enforce the assumption for pairwise keys. |
| 869 | 872 | */ |
| 870 | 873 | if ((alt_key && alt_key->conf.cipher != key->conf.cipher) || |
| 871 | − (old_key && old_key->conf.cipher != key->conf.cipher)) | |
| 874 | + (old_key && old_key->conf.cipher != key->conf.cipher)) { | |
| 875 | + ret = -EOPNOTSUPP; | |
| 872 | 876 | goto out; |
| 877 | + } | |
| 873 | 878 | } else if (sta) { |
| 874 | 879 | struct link_sta_info *link_sta = &sta->deflink; |
| 875 | 880 | int link_id = key->conf.link_id; |
| @@ -895,8 +900,10 @@ int ieee80211_key_link(struct ieee80211_key *key, · 19 unmodified lines | ||
| 895 | 900 | |
| 896 | 901 | /* Non-pairwise keys must also not switch the cipher on rekey */ |
| 897 | 902 | if (!pairwise) { |
| 898 | − if (old_key && old_key->conf.cipher != key->conf.cipher) | |
| 903 | + if (old_key && old_key->conf.cipher != key->conf.cipher) { | |
| 904 | + ret = -EOPNOTSUPP; | |
| 899 | 905 | goto out; |
| 906 | + } | |
| 900 | 907 | } |
| 901 | 908 | |
| 902 | 909 | /* |
| @@ -904,9 +911,8 @@ int ieee80211_key_link(struct ieee80211_key *key, · 1 unmodified line | ||
| 904 | 911 | * new version of the key to avoid nonce reuse or replay issues. |
| 905 | 912 | */ |
| 906 | 913 | if (ieee80211_key_identical(sdata, old_key, key)) { |
| 907 | − ieee80211_key_free_unused(key); | |
| 908 | − ret = 0; | |
| 909 | − goto out; | |
| 914 | + ret = -EALREADY; | |
| 915 | + goto unlock; | |
| 910 | 916 | } |
| 911 | 917 | |
| 912 | 918 | key->local = sdata->local; |
| @@ -930,7 +936,11 @@ int ieee80211_key_link(struct ieee80211_key *key, · 17 unmodified lines | ||
| 930 | 936 | ieee80211_key_free(key, delay_tailroom); |
| 931 | 937 | } |
| 932 | 938 | |
| 939 | + key = NULL; | |
| 940 | + | |
| 933 | 941 | out: |
| 942 | + ieee80211_key_free_unused(key); | |
| 943 | + unlock: | |
| 934 | 944 | mutex_unlock(&sdata->local->key_mtx); |
| 935 | 945 | |
| 936 | 946 | return ret; |
| @@ -1175,7 +1175,7 @@ void ieee80211_mbss_info_change_notify(struct ieee80211_sub_if_data *sdata, · 1174 unmodified lines | ||
| 1175 | 1175 | |
| 1176 | 1176 | /* if we race with running work, worst case this work becomes a noop */ |
| 1177 | 1177 | for_each_set_bit(bit, &bits, sizeof(changed) * BITS_PER_BYTE) |
| 1178 | − set_bit(bit, &ifmsh->mbss_changed); | |
| 1178 | + set_bit(bit, ifmsh->mbss_changed); | |
| 1179 | 1179 | set_bit(MESH_WORK_MBSS_CHANGED, &ifmsh->wrkq_flags); |
| 1180 | 1180 | wiphy_work_queue(sdata->local->hw.wiphy, &sdata->work); |
| 1181 | 1181 | } |
| @@ -1257,7 +1257,7 @@ void ieee80211_stop_mesh(struct ieee80211_sub_if_data *sdata) · 75 unmodified lines | ||
| 1257 | 1257 | |
| 1258 | 1258 | /* clear any mesh work (for next join) we may have accrued */ |
| 1259 | 1259 | ifmsh->wrkq_flags = 0; |
| 1260 | − ifmsh->mbss_changed = 0; | |
| 1260 | + memset(ifmsh->mbss_changed, 0, sizeof(ifmsh->mbss_changed)); | |
| 1261 | 1261 | |
| 1262 | 1262 | local->fif_other_bss--; |
| 1263 | 1263 | atomic_dec(&local->iff_allmultis); |
| @@ -1724,9 +1724,9 @@ static void mesh_bss_info_changed(struct ieee80211_sub_if_data *sdata) · 460 unmodified lines | ||
| 1724 | 1724 | u32 bit; |
| 1725 | 1725 | u64 changed = 0; |
| 1726 | 1726 | |
| 1727 | − for_each_set_bit(bit, &ifmsh->mbss_changed, | |
| 1727 | + for_each_set_bit(bit, ifmsh->mbss_changed, | |
| 1728 | 1728 | sizeof(changed) * BITS_PER_BYTE) { |
| 1729 | − clear_bit(bit, &ifmsh->mbss_changed); | |
| 1729 | + clear_bit(bit, ifmsh->mbss_changed); | |
| 1730 | 1730 | changed |= BIT(bit); |
| 1731 | 1731 | } |
| 1732 | 1732 | |
| @@ -451,7 +451,7 @@ static void mesh_sta_info_init(struct ieee80211_sub_if_data *sdata, · 450 unmodified lines | ||
| 451 | 451 | changed |= IEEE80211_RC_BW_CHANGED; |
| 452 | 452 | |
| 453 | 453 | ieee80211_vht_cap_ie_to_sta_vht_cap(sdata, sband, |
| 454 | − elems->vht_cap_elem, | |
| 454 | + elems->vht_cap_elem, NULL, | |
| 455 | 455 | &sta->deflink); |
| 456 | 456 | |
| 457 | 457 | ieee80211_he_cap_ie_to_sta_he_cap(sdata, sband, elems->he_cap, |
| @@ -4202,10 +4202,33 @@ static bool ieee80211_assoc_config_link(struct ieee80211_link_data *link, · 4201 unmodified lines | ||
| 4202 | 4202 | elems->ht_cap_elem, |
| 4203 | 4203 | link_sta); |
| 4204 | 4204 | |
| 4205 | − if (elems->vht_cap_elem && !(link->u.mgd.conn_flags & IEEE80211_CONN_DISABLE_VHT)) | |
| 4205 | + if (elems->vht_cap_elem && | |
| 4206 | + !(link->u.mgd.conn_flags & IEEE80211_CONN_DISABLE_VHT)) { | |
| 4207 | + const struct ieee80211_vht_cap *bss_vht_cap = NULL; | |
| 4208 | + const struct cfg80211_bss_ies *ies; | |
| 4209 | + | |
| 4210 | + /* | |
| 4211 | + * Cisco AP module 9115 with FW 17.3 has a bug and sends a | |
| 4212 | + * too large maximum MPDU length in the association response | |
| 4213 | + * (indicating 12k) that it cannot actually process ... | |
| 4214 | + * Work around that. | |
| 4215 | + */ | |
| 4216 | + rcu_read_lock(); | |
| 4217 | + ies = rcu_dereference(cbss->ies); | |
| 4218 | + if (ies) { | |
| 4219 | + const struct element *elem; | |
| 4220 | + | |
| 4221 | + elem = cfg80211_find_elem(WLAN_EID_VHT_CAPABILITY, | |
| 4222 | + ies->data, ies->len); | |
| 4223 | + if (elem && elem->datalen >= sizeof(*bss_vht_cap)) | |
| 4224 | + bss_vht_cap = (const void *)elem->data; | |
| 4225 | + } | |
| 4226 | + | |
| 4206 | 4227 | ieee80211_vht_cap_ie_to_sta_vht_cap(sdata, sband, |
| 4207 | 4228 | elems->vht_cap_elem, |
| 4208 | − link_sta); | |
| 4229 | + bss_vht_cap, link_sta); | |
| 4230 | + rcu_read_unlock(); | |
| 4231 | + } | |
| 4209 | 4232 | |
| 4210 | 4233 | if (elems->he_operation && !(link->u.mgd.conn_flags & IEEE80211_CONN_DISABLE_HE) && |
| 4211 | 4234 | elems->he_cap) { |
| @@ -5107,9 +5130,10 @@ static bool ieee80211_assoc_success(struct ieee80211_sub_if_data *sdata, · 895 unmodified lines | ||
| 5107 | 5130 | continue; |
| 5108 | 5131 | |
| 5109 | 5132 | valid_links |= BIT(link_id); |
| 5110 | − if (assoc_data->link[link_id].disabled) { | |
| 5133 | + if (assoc_data->link[link_id].disabled) | |
| 5111 | 5134 | dormant_links |= BIT(link_id); |
| 5112 | − } else if (link_id != assoc_data->assoc_link_id) { | |
| 5135 | + | |
| 5136 | + if (link_id != assoc_data->assoc_link_id) { | |
| 5113 | 5137 | err = ieee80211_sta_allocate_link(sta, link_id); |
| 5114 | 5138 | if (err) |
| 5115 | 5139 | goto out_err; |
| @@ -5124,7 +5148,7 @@ static bool ieee80211_assoc_success(struct ieee80211_sub_if_data *sdata, · 8 unmodified lines | ||
| 5124 | 5148 | struct ieee80211_link_data *link; |
| 5125 | 5149 | struct link_sta_info *link_sta; |
| 5126 | 5150 | |
| 5127 | − if (!cbss || assoc_data->link[link_id].disabled) | |
| 5151 | + if (!cbss) | |
| 5128 | 5152 | continue; |
| 5129 | 5153 | |
| 5130 | 5154 | link = sdata_dereference(sdata->link[link_id], sdata); |
| @@ -5429,17 +5453,18 @@ static void ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata, · 298 unmodified lines | ||
| 5429 | 5453 | for (link_id = 0; link_id < IEEE80211_MLD_MAX_NUM_LINKS; link_id++) { |
| 5430 | 5454 | struct ieee80211_link_data *link; |
| 5431 | 5455 | |
| 5432 | − link = sdata_dereference(sdata->link[link_id], sdata); | |
| 5433 | − if (!link) | |
| 5434 | − continue; | |
| 5435 | − | |
| 5436 | 5456 | if (!assoc_data->link[link_id].bss) |
| 5437 | 5457 | continue; |
| 5438 | 5458 | |
| 5439 | 5459 | resp.links[link_id].bss = assoc_data->link[link_id].bss; |
| 5440 | − resp.links[link_id].addr = link->conf->addr; | |
| 5460 | + ether_addr_copy(resp.links[link_id].addr, | |
| 5461 | + assoc_data->link[link_id].addr); | |
| 5441 | 5462 | resp.links[link_id].status = assoc_data->link[link_id].status; |
| 5442 | 5463 | |
| 5464 | + link = sdata_dereference(sdata->link[link_id], sdata); | |
| 5465 | + if (!link) | |
| 5466 | + continue; | |
| 5467 | + | |
| 5443 | 5468 | /* get uapsd queues configuration - same for all links */ |
| 5444 | 5469 | resp.uapsd_queues = 0; |
| 5445 | 5470 | for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) |
| @@ -665,7 +665,8 @@ ieee80211_tx_h_select_key(struct ieee80211_tx_data *tx) · 664 unmodified lines | ||
| 665 | 665 | } |
| 666 | 666 | |
| 667 | 667 | if (unlikely(tx->key && tx->key->flags & KEY_FLAG_TAINTED && |
| 668 | − !ieee80211_is_deauth(hdr->frame_control))) | |
| 668 | + !ieee80211_is_deauth(hdr->frame_control)) && | |
| 669 | + tx->skb->protocol != tx->sdata->control_port_protocol) | |
| 669 | 670 | return TX_DROP; |
| 670 | 671 | |
| 671 | 672 | if (!skip_hw && tx->key && |
| @@ -4,7 +4,7 @@ · 3 unmodified lines | ||
| 4 | 4 | * |
| 5 | 5 | * Portions of this file |
| 6 | 6 | * Copyright(c) 2015 - 2016 Intel Deutschland GmbH |
| 7 | − * Copyright (C) 2018 - 2022 Intel Corporation | |
| 7 | + * Copyright (C) 2018 - 2023 Intel Corporation | |
| 8 | 8 | */ |
| 9 | 9 | |
| 10 | 10 | #include <linux/ieee80211.h> |
| @@ -116,12 +116,14 @@ void · 105 unmodified lines | ||
| 116 | 116 | ieee80211_vht_cap_ie_to_sta_vht_cap(struct ieee80211_sub_if_data *sdata, |
| 117 | 117 | struct ieee80211_supported_band *sband, |
| 118 | 118 | const struct ieee80211_vht_cap *vht_cap_ie, |
| 119 | + const struct ieee80211_vht_cap *vht_cap_ie2, | |
| 119 | 120 | struct link_sta_info *link_sta) |
| 120 | 121 | { |
| 121 | 122 | struct ieee80211_sta_vht_cap *vht_cap = &link_sta->pub->vht_cap; |
| 122 | 123 | struct ieee80211_sta_vht_cap own_cap; |
| 123 | 124 | u32 cap_info, i; |
| 124 | 125 | bool have_80mhz; |
| 126 | + u32 mpdu_len; | |
| 125 | 127 | |
| 126 | 128 | memset(vht_cap, 0, sizeof(*vht_cap)); |
| 127 | 129 | |
| @@ -317,11 +319,21 @@ ieee80211_vht_cap_ie_to_sta_vht_cap(struct ieee80211_sub_if_data *sdata, · 189 unmodified lines | ||
| 317 | 319 | |
| 318 | 320 | link_sta->pub->bandwidth = ieee80211_sta_cur_vht_bw(link_sta); |
| 319 | 321 | |
| 322 | + /* | |
| 323 | + * Work around the Cisco 9115 FW 17.3 bug by taking the min of | |
| 324 | + * both reported MPDU lengths. | |
| 325 | + */ | |
| 326 | + mpdu_len = vht_cap->cap & IEEE80211_VHT_CAP_MAX_MPDU_MASK; | |
| 327 | + if (vht_cap_ie2) | |
| 328 | + mpdu_len = min_t(u32, mpdu_len, | |
| 329 | + le32_get_bits(vht_cap_ie2->vht_cap_info, | |
| 330 | + IEEE80211_VHT_CAP_MAX_MPDU_MASK)); | |
| 331 | + | |
| 320 | 332 | /* |
| 321 | 333 | * FIXME - should the amsdu len be per link? store per link |
| 322 | 334 | * and maintain a minimum? |
| 323 | 335 | */ |
| 324 | − switch (vht_cap->cap & IEEE80211_VHT_CAP_MAX_MPDU_MASK) { | |
| 336 | + switch (mpdu_len) { | |
| 325 | 337 | case IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_11454: |
| 326 | 338 | link_sta->pub->agg.max_amsdu_len = IEEE80211_MAX_MPDU_LEN_VHT_11454; |
| 327 | 339 | break; |
| @@ -307,12 +307,6 @@ int mptcp_nl_cmd_sf_create(struct sk_buff *skb, struct genl_info *info) · 306 unmodified lines | ||
| 307 | 307 | goto create_err; |
| 308 | 308 | } |
| 309 | 309 | |
| 310 | − if (addr_l.id == 0) { | |
| 311 | − NL_SET_ERR_MSG_ATTR(info->extack, laddr, "missing local addr id"); | |
| 312 | − err = -EINVAL; | |
| 313 | − goto create_err; | |
| 314 | − } | |
| 315 | − | |
| 316 | 310 | err = mptcp_pm_parse_addr(raddr, info, &addr_r); |
| 317 | 311 | if (err < 0) { |
| 318 | 312 | NL_SET_ERR_MSG_ATTR(info->extack, raddr, "error parsing remote addr"); |
| @@ -3425,24 +3425,21 @@ static void schedule_3rdack_retransmission(struct sock *ssk) · 3424 unmodified lines | ||
| 3425 | 3425 | sk_reset_timer(ssk, &icsk->icsk_delack_timer, timeout); |
| 3426 | 3426 | } |
| 3427 | 3427 | |
| 3428 | −void mptcp_subflow_process_delegated(struct sock *ssk) | |
| 3428 | +void mptcp_subflow_process_delegated(struct sock *ssk, long status) | |
| 3429 | 3429 | { |
| 3430 | 3430 | struct mptcp_subflow_context *subflow = mptcp_subflow_ctx(ssk); |
| 3431 | 3431 | struct sock *sk = subflow->conn; |
| 3432 | 3432 | |
| 3433 | − if (test_bit(MPTCP_DELEGATE_SEND, &subflow->delegated_status)) { | |
| 3433 | + if (status & BIT(MPTCP_DELEGATE_SEND)) { | |
| 3434 | 3434 | mptcp_data_lock(sk); |
| 3435 | 3435 | if (!sock_owned_by_user(sk)) |
| 3436 | 3436 | __mptcp_subflow_push_pending(sk, ssk, true); |
| 3437 | 3437 | else |
| 3438 | 3438 | __set_bit(MPTCP_PUSH_PENDING, &mptcp_sk(sk)->cb_flags); |
| 3439 | 3439 | mptcp_data_unlock(sk); |
| 3440 | − mptcp_subflow_delegated_done(subflow, MPTCP_DELEGATE_SEND); | |
| 3441 | 3440 | } |
| 3442 | − if (test_bit(MPTCP_DELEGATE_ACK, &subflow->delegated_status)) { | |
| 3441 | + if (status & BIT(MPTCP_DELEGATE_ACK)) | |
| 3443 | 3442 | schedule_3rdack_retransmission(ssk); |
| 3444 | − mptcp_subflow_delegated_done(subflow, MPTCP_DELEGATE_ACK); | |
| 3445 | − } | |
| 3446 | 3443 | } |
| 3447 | 3444 | |
| 3448 | 3445 | static int mptcp_hash(struct sock *sk) |
| @@ -3968,14 +3965,17 @@ static int mptcp_napi_poll(struct napi_struct *napi, int budget) · 519 unmodified lines | ||
| 3968 | 3965 | struct sock *ssk = mptcp_subflow_tcp_sock(subflow); |
| 3969 | 3966 | |
| 3970 | 3967 | bh_lock_sock_nested(ssk); |
| 3971 | − if (!sock_owned_by_user(ssk) && | |
| 3972 | − mptcp_subflow_has_delegated_action(subflow)) | |
| 3973 | − mptcp_subflow_process_delegated(ssk); | |
| 3974 | − /* ... elsewhere tcp_release_cb_override already processed | |
| 3975 | − * the action or will do at next release_sock(). | |
| 3976 | − * In both case must dequeue the subflow here - on the same | |
| 3977 | − * CPU that scheduled it. | |
| 3978 | − */ | |
| 3968 | + if (!sock_owned_by_user(ssk)) { | |
| 3969 | + mptcp_subflow_process_delegated(ssk, xchg(&subflow->delegated_status, 0)); | |
| 3970 | + } else { | |
| 3971 | + /* tcp_release_cb_override already processed | |
| 3972 | + * the action or will do at next release_sock(). | |
| 3973 | + * In both case must dequeue the subflow here - on the same | |
| 3974 | + * CPU that scheduled it. | |
| 3975 | + */ | |
| 3976 | + smp_wmb(); | |
| 3977 | + clear_bit(MPTCP_DELEGATE_SCHEDULED, &subflow->delegated_status); | |
| 3978 | + } | |
| 3979 | 3979 | bh_unlock_sock(ssk); |
| 3980 | 3980 | sock_put(ssk); |
| 3981 | 3981 | |
| @@ -444,9 +444,11 @@ struct mptcp_delegated_action { · 443 unmodified lines | ||
| 444 | 444 | |
| 445 | 445 | DECLARE_PER_CPU(struct mptcp_delegated_action, mptcp_delegated_actions); |
| 446 | 446 | |
| 447 | −#define MPTCP_DELEGATE_SEND 0 | |
| 448 | −#define MPTCP_DELEGATE_ACK 1 | |
| 447 | +#define MPTCP_DELEGATE_SCHEDULED 0 | |
| 448 | +#define MPTCP_DELEGATE_SEND 1 | |
| 449 | +#define MPTCP_DELEGATE_ACK 2 | |
| 449 | 450 | |
| 451 | +#define MPTCP_DELEGATE_ACTIONS_MASK (~BIT(MPTCP_DELEGATE_SCHEDULED)) | |
| 450 | 452 | /* MPTCP subflow context */ |
| 451 | 453 | struct mptcp_subflow_context { |
| 452 | 454 | struct list_head node;/* conn_list of subflows */ |
| @@ -564,23 +566,24 @@ mptcp_subflow_get_mapped_dsn(const struct mptcp_subflow_context *subflow) · 111 unmodified lines | ||
| 564 | 566 | return subflow->map_seq + mptcp_subflow_get_map_offset(subflow); |
| 565 | 567 | } |
| 566 | 568 | |
| 567 | −void mptcp_subflow_process_delegated(struct sock *ssk); | |
| 569 | +void mptcp_subflow_process_delegated(struct sock *ssk, long actions); | |
| 568 | 570 | |
| 569 | 571 | static inline void mptcp_subflow_delegate(struct mptcp_subflow_context *subflow, int action) |
| 570 | 572 | { |
| 573 | + long old, set_bits = BIT(MPTCP_DELEGATE_SCHEDULED) | BIT(action); | |
| 571 | 574 | struct mptcp_delegated_action *delegated; |
| 572 | 575 | bool schedule; |
| 573 | 576 | |
| 574 | 577 | /* the caller held the subflow bh socket lock */ |
| 575 | 578 | lockdep_assert_in_softirq(); |
| 576 | 579 | |
| 577 | − /* The implied barrier pairs with mptcp_subflow_delegated_done(), and | |
| 578 | − * ensures the below list check sees list updates done prior to status | |
| 579 | − * bit changes | |
| 580 | + /* The implied barrier pairs with tcp_release_cb_override() | |
| 581 | + * mptcp_napi_poll(), and ensures the below list check sees list | |
| 582 | + * updates done prior to delegated status bits changes | |
| 580 | 583 | */ |
| 581 | − if (!test_and_set_bit(action, &subflow->delegated_status)) { | |
| 582 | − /* still on delegated list from previous scheduling */ | |
| 583 | − if (!list_empty(&subflow->delegated_node)) | |
| 584 | + old = set_mask_bits(&subflow->delegated_status, 0, set_bits); | |
| 585 | + if (!(old & BIT(MPTCP_DELEGATE_SCHEDULED))) { | |
| 586 | + if (WARN_ON_ONCE(!list_empty(&subflow->delegated_node))) | |
| 584 | 587 | return; |
| 585 | 588 | |
| 586 | 589 | delegated = this_cpu_ptr(&mptcp_delegated_actions); |
| @@ -605,20 +608,6 @@ mptcp_subflow_delegated_next(struct mptcp_delegated_action *delegated) · 18 unmodified lines | ||
| 605 | 608 | return ret; |
| 606 | 609 | } |
| 607 | 610 | |
| 608 | −static inline bool mptcp_subflow_has_delegated_action(const struct mptcp_subflow_context *subflow) | |
| 609 | −{ | |
| 610 | − return !!READ_ONCE(subflow->delegated_status); | |
| 611 | −} | |
| 612 | − | |
| 613 | −static inline void mptcp_subflow_delegated_done(struct mptcp_subflow_context *subflow, int action) | |
| 614 | −{ | |
| 615 | − /* pairs with mptcp_subflow_delegate, ensures delegate_node is updated before | |
| 616 | − * touching the status bit | |
| 617 | − */ | |
| 618 | − smp_wmb(); | |
| 619 | − clear_bit(action, &subflow->delegated_status); | |
| 620 | −} | |
| 621 | − | |
| 622 | 611 | int mptcp_is_enabled(const struct net *net); |
| 623 | 612 | unsigned int mptcp_get_add_addr_timeout(const struct net *net); |
| 624 | 613 | int mptcp_is_checksum_enabled(const struct net *net); |
| @@ -1956,9 +1956,15 @@ static void subflow_ulp_clone(const struct request_sock *req, · 1955 unmodified lines | ||
| 1956 | 1956 | static void tcp_release_cb_override(struct sock *ssk) |
| 1957 | 1957 | { |
| 1958 | 1958 | struct mptcp_subflow_context *subflow = mptcp_subflow_ctx(ssk); |
| 1959 | + long status; | |
| 1959 | 1960 | |
| 1960 | − if (mptcp_subflow_has_delegated_action(subflow)) | |
| 1961 | − mptcp_subflow_process_delegated(ssk); | |
| 1961 | + /* process and clear all the pending actions, but leave the subflow into | |
| 1962 | + * the napi queue. To respect locking, only the same CPU that originated | |
| 1963 | + * the action can touch the list. mptcp_napi_poll will take care of it. | |
| 1964 | + */ | |
| 1965 | + status = set_mask_bits(&subflow->delegated_status, MPTCP_DELEGATE_ACTIONS_MASK, 0); | |
| 1966 | + if (status) | |
| 1967 | + mptcp_subflow_process_delegated(ssk, status); | |
| 1962 | 1968 | |
| 1963 | 1969 | tcp_release_cb(ssk); |
| 1964 | 1970 | } |
| @@ -1435,7 +1435,7 @@ static int bind_mcastif_addr(struct socket *sock, struct net_device *dev) · 1434 unmodified lines | ||
| 1435 | 1435 | sin.sin_addr.s_addr = addr; |
| 1436 | 1436 | sin.sin_port = 0; |
| 1437 | 1437 | |
| 1438 | − return sock->ops->bind(sock, (struct sockaddr*)&sin, sizeof(sin)); | |
| 1438 | + return kernel_bind(sock, (struct sockaddr *)&sin, sizeof(sin)); | |
| 1439 | 1439 | } |
| 1440 | 1440 | |
| 1441 | 1441 | static void get_mcast_sockaddr(union ipvs_sockaddr *sa, int *salen, |
| @@ -1501,8 +1501,8 @@ static int make_send_sock(struct netns_ipvs *ipvs, int id, · 59 unmodified lines | ||
| 1501 | 1501 | } |
| 1502 | 1502 | |
| 1503 | 1503 | get_mcast_sockaddr(&mcast_addr, &salen, &ipvs->mcfg, id); |
| 1504 | − result = sock->ops->connect(sock, (struct sockaddr *) &mcast_addr, | |
| 1505 | − salen, 0); | |
| 1504 | + result = kernel_connect(sock, (struct sockaddr *)&mcast_addr, | |
| 1505 | + salen, 0); | |
| 1506 | 1506 | if (result < 0) { |
| 1507 | 1507 | pr_err("Error connecting to the multicast addr\n"); |
| 1508 | 1508 | goto error; |
| @@ -1542,7 +1542,7 @@ static int make_receive_sock(struct netns_ipvs *ipvs, int id, · 33 unmodified lines | ||
| 1542 | 1542 | |
| 1543 | 1543 | get_mcast_sockaddr(&mcast_addr, &salen, &ipvs->bcfg, id); |
| 1544 | 1544 | sock->sk->sk_bound_dev_if = dev->ifindex; |
| 1545 | − result = sock->ops->bind(sock, (struct sockaddr *)&mcast_addr, salen); | |
| 1545 | + result = kernel_bind(sock, (struct sockaddr *)&mcast_addr, salen); | |
| 1546 | 1546 | if (result < 0) { |
| 1547 | 1547 | pr_err("Error binding to the multicast addr\n"); |
| 1548 | 1548 | goto error; |
| @@ -112,7 +112,7 @@ static const u8 sctp_conntracks[2][11][SCTP_CONNTRACK_MAX] = { · 111 unmodified lines | ||
| 112 | 112 | /* shutdown_ack */ {sSA, sCL, sCW, sCE, sES, sSA, sSA, sSA, sSA}, |
| 113 | 113 | /* error */ {sCL, sCL, sCW, sCE, sES, sSS, sSR, sSA, sCL},/* Can't have Stale cookie*/ |
| 114 | 114 | /* cookie_echo */ {sCL, sCL, sCE, sCE, sES, sSS, sSR, sSA, sCL},/* 5.2.4 - Big TODO */ |
| 115 | −/* cookie_ack */ {sCL, sCL, sCW, sCE, sES, sSS, sSR, sSA, sCL},/* Can't come in orig dir */ | |
| 115 | +/* cookie_ack */ {sCL, sCL, sCW, sES, sES, sSS, sSR, sSA, sCL},/* Can't come in orig dir */ | |
| 116 | 116 | /* shutdown_comp*/ {sCL, sCL, sCW, sCE, sES, sSS, sSR, sCL, sCL}, |
| 117 | 117 | /* heartbeat */ {sHS, sCL, sCW, sCE, sES, sSS, sSR, sSA, sHS}, |
| 118 | 118 | /* heartbeat_ack*/ {sCL, sCL, sCW, sCE, sES, sSS, sSR, sSA, sHS}, |
| @@ -126,7 +126,7 @@ static const u8 sctp_conntracks[2][11][SCTP_CONNTRACK_MAX] = { · 7 unmodified lines | ||
| 126 | 126 | /* shutdown */ {sIV, sCL, sCW, sCE, sSR, sSS, sSR, sSA, sIV}, |
| 127 | 127 | /* shutdown_ack */ {sIV, sCL, sCW, sCE, sES, sSA, sSA, sSA, sIV}, |
| 128 | 128 | /* error */ {sIV, sCL, sCW, sCL, sES, sSS, sSR, sSA, sIV}, |
| 129 | −/* cookie_echo */ {sIV, sCL, sCW, sCE, sES, sSS, sSR, sSA, sIV},/* Can't come in reply dir */ | |
| 129 | +/* cookie_echo */ {sIV, sCL, sCE, sCE, sES, sSS, sSR, sSA, sIV},/* Can't come in reply dir */ | |
| 130 | 130 | /* cookie_ack */ {sIV, sCL, sCW, sES, sES, sSS, sSR, sSA, sIV}, |
| 131 | 131 | /* shutdown_comp*/ {sIV, sCL, sCW, sCE, sES, sSS, sSR, sCL, sIV}, |
| 132 | 132 | /* heartbeat */ {sIV, sCL, sCW, sCE, sES, sSS, sSR, sSA, sHS}, |
| @@ -412,6 +412,9 @@ int nf_conntrack_sctp_packet(struct nf_conn *ct, · 279 unmodified lines | ||
| 412 | 412 | /* (D) vtag must be same as init_vtag as found in INIT_ACK */ |
| 413 | 413 | if (sh->vtag != ct->proto.sctp.vtag[dir]) |
| 414 | 414 | goto out_unlock; |
| 415 | + } else if (sch->type == SCTP_CID_COOKIE_ACK) { | |
| 416 | + ct->proto.sctp.init[dir] = 0; | |
| 417 | + ct->proto.sctp.init[!dir] = 0; | |
| 415 | 418 | } else if (sch->type == SCTP_CID_HEARTBEAT) { |
| 416 | 419 | if (ct->proto.sctp.vtag[dir] == 0) { |
| 417 | 420 | pr_debug("Setting %d vtag %x for dir %d\n", sch->type, sh->vtag, dir); |
| @@ -461,16 +464,18 @@ int nf_conntrack_sctp_packet(struct nf_conn *ct, · 43 unmodified lines | ||
| 461 | 464 | } |
| 462 | 465 | |
| 463 | 466 | /* If it is an INIT or an INIT ACK note down the vtag */ |
| 464 | − if (sch->type == SCTP_CID_INIT || | |
| 465 | − sch->type == SCTP_CID_INIT_ACK) { | |
| 466 | − struct sctp_inithdr _inithdr, *ih; | |
| 467 | + if (sch->type == SCTP_CID_INIT) { | |
| 468 | + struct sctp_inithdr _ih, *ih; | |
| 467 | 469 | |
| 468 | − ih = skb_header_pointer(skb, offset + sizeof(_sch), | |
| 469 | − sizeof(_inithdr), &_inithdr); | |
| 470 | − if (ih == NULL) | |
| 470 | + ih = skb_header_pointer(skb, offset + sizeof(_sch), sizeof(*ih), &_ih); | |
| 471 | + if (!ih) | |
| 471 | 472 | goto out_unlock; |
| 472 | − pr_debug("Setting vtag %x for dir %d\n", | |
| 473 | − ih->init_tag, !dir); | |
| 473 | + | |
| 474 | + if (ct->proto.sctp.init[dir] && ct->proto.sctp.init[!dir]) | |
| 475 | + ct->proto.sctp.init[!dir] = 0; | |
| 476 | + ct->proto.sctp.init[dir] = 1; | |
| 477 | + | |
| 478 | + pr_debug("Setting vtag %x for dir %d\n", ih->init_tag, !dir); | |
| 474 | 479 | ct->proto.sctp.vtag[!dir] = ih->init_tag; |
| 475 | 480 | |
| 476 | 481 | /* don't renew timeout on init retransmit so |
| @@ -481,6 +486,24 @@ int nf_conntrack_sctp_packet(struct nf_conn *ct, · 4 unmodified lines | ||
| 481 | 486 | old_state == SCTP_CONNTRACK_CLOSED && |
| 482 | 487 | nf_ct_is_confirmed(ct)) |
| 483 | 488 | ignore = true; |
| 489 | + } else if (sch->type == SCTP_CID_INIT_ACK) { | |
| 490 | + struct sctp_inithdr _ih, *ih; | |
| 491 | + __be32 vtag; | |
| 492 | + | |
| 493 | + ih = skb_header_pointer(skb, offset + sizeof(_sch), sizeof(*ih), &_ih); | |
| 494 | + if (!ih) | |
| 495 | + goto out_unlock; | |
| 496 | + | |
| 497 | + vtag = ct->proto.sctp.vtag[!dir]; | |
| 498 | + if (!ct->proto.sctp.init[!dir] && vtag && vtag != ih->init_tag) | |
| 499 | + goto out_unlock; | |
| 500 | + /* collision */ | |
| 501 | + if (ct->proto.sctp.init[dir] && ct->proto.sctp.init[!dir] && | |
| 502 | + vtag != ih->init_tag) | |
| 503 | + goto out_unlock; | |
| 504 | + | |
| 505 | + pr_debug("Setting vtag %x for dir %d\n", ih->init_tag, !dir); | |
| 506 | + ct->proto.sctp.vtag[!dir] = ih->init_tag; | |
| 484 | 507 | } |
| 485 | 508 | |
| 486 | 509 | ct->proto.sctp.state = new_state; |
| @@ -7879,24 +7879,14 @@ static int nf_tables_delobj(struct sk_buff *skb, const struct nfnl_info *info, · 7878 unmodified lines | ||
| 7879 | 7879 | return nft_delobj(&ctx, obj); |
| 7880 | 7880 | } |
| 7881 | 7881 | |
| 7882 | −void nft_obj_notify(struct net *net, const struct nft_table *table, | |
| 7883 | − struct nft_object *obj, u32 portid, u32 seq, int event, | |
| 7884 | − u16 flags, int family, int report, gfp_t gfp) | |
| 7882 | +static void | |
| 7883 | +__nft_obj_notify(struct net *net, const struct nft_table *table, | |
| 7884 | + struct nft_object *obj, u32 portid, u32 seq, int event, | |
| 7885 | + u16 flags, int family, int report, gfp_t gfp) | |
| 7885 | 7886 | { |
| 7886 | 7887 | struct nftables_pernet *nft_net = nft_pernet(net); |
| 7887 | 7888 | struct sk_buff *skb; |
| 7888 | 7889 | int err; |
| 7889 | − char *buf = kasprintf(gfp, "%s:%u", | |
| 7890 | − table->name, nft_net->base_seq); | |
| 7891 | − | |
| 7892 | − audit_log_nfcfg(buf, | |
| 7893 | − family, | |
| 7894 | − obj->handle, | |
| 7895 | − event == NFT_MSG_NEWOBJ ? | |
| 7896 | − AUDIT_NFT_OP_OBJ_REGISTER : | |
| 7897 | − AUDIT_NFT_OP_OBJ_UNREGISTER, | |
| 7898 | − gfp); | |
| 7899 | − kfree(buf); | |
| 7900 | 7890 | |
| 7901 | 7891 | if (!report && |
| 7902 | 7892 | !nfnetlink_has_listeners(net, NFNLGRP_NFTABLES)) |
| @@ -7919,13 +7909,35 @@ void nft_obj_notify(struct net *net, const struct nft_table *table, · 16 unmodified lines | ||
| 7919 | 7909 | err: |
| 7920 | 7910 | nfnetlink_set_err(net, portid, NFNLGRP_NFTABLES, -ENOBUFS); |
| 7921 | 7911 | } |
| 7912 | + | |
| 7913 | +void nft_obj_notify(struct net *net, const struct nft_table *table, | |
| 7914 | + struct nft_object *obj, u32 portid, u32 seq, int event, | |
| 7915 | + u16 flags, int family, int report, gfp_t gfp) | |
| 7916 | +{ | |
| 7917 | + struct nftables_pernet *nft_net = nft_pernet(net); | |
| 7918 | + char *buf = kasprintf(gfp, "%s:%u", | |
| 7919 | + table->name, nft_net->base_seq); | |
| 7920 | + | |
| 7921 | + audit_log_nfcfg(buf, | |
| 7922 | + family, | |
| 7923 | + obj->handle, | |
| 7924 | + event == NFT_MSG_NEWOBJ ? | |
| 7925 | + AUDIT_NFT_OP_OBJ_REGISTER : | |
| 7926 | + AUDIT_NFT_OP_OBJ_UNREGISTER, | |
| 7927 | + gfp); | |
| 7928 | + kfree(buf); | |
| 7929 | + | |
| 7930 | + __nft_obj_notify(net, table, obj, portid, seq, event, | |
| 7931 | + flags, family, report, gfp); | |
| 7932 | +} | |
| 7922 | 7933 | EXPORT_SYMBOL_GPL(nft_obj_notify); |
| 7923 | 7934 | |
| 7924 | 7935 | static void nf_tables_obj_notify(const struct nft_ctx *ctx, |
| 7925 | 7936 | struct nft_object *obj, int event) |
| 7926 | 7937 | { |
| 7927 | − nft_obj_notify(ctx->net, ctx->table, obj, ctx->portid, ctx->seq, event, | |
| 7928 | − ctx->flags, ctx->family, ctx->report, GFP_KERNEL); | |
| 7938 | + __nft_obj_notify(ctx->net, ctx->table, obj, ctx->portid, | |
| 7939 | + ctx->seq, event, ctx->flags, ctx->family, | |
| 7940 | + ctx->report, GFP_KERNEL); | |
| 7929 | 7941 | } |
| 7930 | 7942 | |
| 7931 | 7943 | /* |
| @@ -154,6 +154,17 @@ int nft_payload_inner_offset(const struct nft_pktinfo *pkt) · 153 unmodified lines | ||
| 154 | 154 | return pkt->inneroff; |
| 155 | 155 | } |
| 156 | 156 | |
| 157 | +static bool nft_payload_need_vlan_copy(const struct nft_payload *priv) | |
| 158 | +{ | |
| 159 | + unsigned int len = priv->offset + priv->len; | |
| 160 | + | |
| 161 | + /* data past ether src/dst requested, copy needed */ | |
| 162 | + if (len > offsetof(struct ethhdr, h_proto)) | |
| 163 | + return true; | |
| 164 | + | |
| 165 | + return false; | |
| 166 | +} | |
| 167 | + | |
| 157 | 168 | void nft_payload_eval(const struct nft_expr *expr, |
| 158 | 169 | struct nft_regs *regs, |
| 159 | 170 | const struct nft_pktinfo *pkt) |
| @@ -172,7 +183,7 @@ void nft_payload_eval(const struct nft_expr *expr, · 12 unmodified lines | ||
| 172 | 183 | goto err; |
| 173 | 184 | |
| 174 | 185 | if (skb_vlan_tag_present(skb) && |
| 175 | − priv->offset >= offsetof(struct ethhdr, h_proto)) { | |
| 186 | + nft_payload_need_vlan_copy(priv)) { | |
| 176 | 187 | if (!nft_payload_copy_vlan(dest, skb, |
| 177 | 188 | priv->offset, priv->len)) |
| 178 | 189 | goto err; |
| @@ -233,10 +233,9 @@ static void nft_rbtree_gc_remove(struct net *net, struct nft_set *set, · 232 unmodified lines | ||
| 233 | 233 | rb_erase(&rbe->node, &priv->root); |
| 234 | 234 | } |
| 235 | 235 | |
| 236 | −static int nft_rbtree_gc_elem(const struct nft_set *__set, | |
| 237 | − struct nft_rbtree *priv, | |
| 238 | − struct nft_rbtree_elem *rbe, | |
| 239 | − u8 genmask) | |
| 236 | +static const struct nft_rbtree_elem * | |
| 237 | +nft_rbtree_gc_elem(const struct nft_set *__set, struct nft_rbtree *priv, | |
| 238 | + struct nft_rbtree_elem *rbe, u8 genmask) | |
| 240 | 239 | { |
| 241 | 240 | struct nft_set *set = (struct nft_set *)__set; |
| 242 | 241 | struct rb_node *prev = rb_prev(&rbe->node); |
| @@ -246,7 +245,7 @@ static int nft_rbtree_gc_elem(const struct nft_set *__set, · 3 unmodified lines | ||
| 246 | 245 | |
| 247 | 246 | gc = nft_trans_gc_alloc(set, 0, GFP_ATOMIC); |
| 248 | 247 | if (!gc) |
| 249 | − return -ENOMEM; | |
| 248 | + return ERR_PTR(-ENOMEM); | |
| 250 | 249 | |
| 251 | 250 | /* search for end interval coming before this element. |
| 252 | 251 | * end intervals don't carry a timeout extension, they |
| @@ -261,6 +260,7 @@ static int nft_rbtree_gc_elem(const struct nft_set *__set, · 8 unmodified lines | ||
| 261 | 260 | prev = rb_prev(prev); |
| 262 | 261 | } |
| 263 | 262 | |
| 263 | + rbe_prev = NULL; | |
| 264 | 264 | if (prev) { |
| 265 | 265 | rbe_prev = rb_entry(prev, struct nft_rbtree_elem, node); |
| 266 | 266 | nft_rbtree_gc_remove(net, set, priv, rbe_prev); |
| @@ -272,7 +272,7 @@ static int nft_rbtree_gc_elem(const struct nft_set *__set, · 5 unmodified lines | ||
| 272 | 272 | */ |
| 273 | 273 | gc = nft_trans_gc_queue_sync(gc, GFP_ATOMIC); |
| 274 | 274 | if (WARN_ON_ONCE(!gc)) |
| 275 | − return -ENOMEM; | |
| 275 | + return ERR_PTR(-ENOMEM); | |
| 276 | 276 | |
| 277 | 277 | nft_trans_gc_elem_add(gc, rbe_prev); |
| 278 | 278 | } |
| @@ -280,13 +280,13 @@ static int nft_rbtree_gc_elem(const struct nft_set *__set, · 1 unmodified line | ||
| 280 | 280 | nft_rbtree_gc_remove(net, set, priv, rbe); |
| 281 | 281 | gc = nft_trans_gc_queue_sync(gc, GFP_ATOMIC); |
| 282 | 282 | if (WARN_ON_ONCE(!gc)) |
| 283 | − return -ENOMEM; | |
| 283 | + return ERR_PTR(-ENOMEM); | |
| 284 | 284 | |
| 285 | 285 | nft_trans_gc_elem_add(gc, rbe); |
| 286 | 286 | |
| 287 | 287 | nft_trans_gc_queue_sync_done(gc); |
| 288 | 288 | |
| 289 | − return 0; | |
| 289 | + return rbe_prev; | |
| 290 | 290 | } |
| 291 | 291 | |
| 292 | 292 | static bool nft_rbtree_update_first(const struct nft_set *set, |
| @@ -314,7 +314,7 @@ static int __nft_rbtree_insert(const struct net *net, const struct nft_set *set, · 21 unmodified lines | ||
| 314 | 314 | struct nft_rbtree *priv = nft_set_priv(set); |
| 315 | 315 | u8 cur_genmask = nft_genmask_cur(net); |
| 316 | 316 | u8 genmask = nft_genmask_next(net); |
| 317 | − int d, err; | |
| 317 | + int d; | |
| 318 | 318 | |
| 319 | 319 | /* Descend the tree to search for an existing element greater than the |
| 320 | 320 | * key value to insert that is greater than the new element. This is the |
| @@ -363,9 +363,14 @@ static int __nft_rbtree_insert(const struct net *net, const struct nft_set *set, · 42 unmodified lines | ||
| 363 | 363 | */ |
| 364 | 364 | if (nft_set_elem_expired(&rbe->ext) && |
| 365 | 365 | nft_set_elem_active(&rbe->ext, cur_genmask)) { |
| 366 | − err = nft_rbtree_gc_elem(set, priv, rbe, genmask); | |
| 367 | − if (err < 0) | |
| 368 | − return err; | |
| 366 | + const struct nft_rbtree_elem *removed_end; | |
| 367 | + | |
| 368 | + removed_end = nft_rbtree_gc_elem(set, priv, rbe, genmask); | |
| 369 | + if (IS_ERR(removed_end)) | |
| 370 | + return PTR_ERR(removed_end); | |
| 371 | + | |
| 372 | + if (removed_end == rbe_le || removed_end == rbe_ge) | |
| 373 | + return -EAGAIN; | |
| 369 | 374 | |
| 370 | 375 | continue; |
| 371 | 376 | } |
| @@ -486,11 +491,18 @@ static int nft_rbtree_insert(const struct net *net, const struct nft_set *set, · 114 unmodified lines | ||
| 486 | 491 | struct nft_rbtree_elem *rbe = elem->priv; |
| 487 | 492 | int err; |
| 488 | 493 | |
| 489 | − write_lock_bh(&priv->lock); | |
| 490 | − write_seqcount_begin(&priv->count); | |
| 491 | − err = __nft_rbtree_insert(net, set, rbe, ext); | |
| 492 | − write_seqcount_end(&priv->count); | |
| 493 | − write_unlock_bh(&priv->lock); | |
| 494 | + do { | |
| 495 | + if (fatal_signal_pending(current)) | |
| 496 | + return -EINTR; | |
| 497 | + | |
| 498 | + cond_resched(); | |
| 499 | + | |
| 500 | + write_lock_bh(&priv->lock); | |
| 501 | + write_seqcount_begin(&priv->count); | |
| 502 | + err = __nft_rbtree_insert(net, set, rbe, ext); | |
| 503 | + write_seqcount_end(&priv->count); | |
| 504 | + write_unlock_bh(&priv->lock); | |
| 505 | + } while (err == -EAGAIN); | |
| 494 | 506 | |
| 495 | 507 | return err; |
| 496 | 508 | } |
| @@ -352,7 +352,7 @@ static void netlink_overrun(struct sock *sk) · 351 unmodified lines | ||
| 352 | 352 | if (!nlk_test_bit(RECV_NO_ENOBUFS, sk)) { |
| 353 | 353 | if (!test_and_set_bit(NETLINK_S_CONGESTED, |
| 354 | 354 | &nlk_sk(sk)->state)) { |
| 355 | − sk->sk_err = ENOBUFS; | |
| 355 | + WRITE_ONCE(sk->sk_err, ENOBUFS); | |
| 356 | 356 | sk_error_report(sk); |
| 357 | 357 | } |
| 358 | 358 | } |
| @@ -1605,7 +1605,7 @@ static int do_one_set_err(struct sock *sk, struct netlink_set_err_data *p) · 1246 unmodified lines | ||
| 1605 | 1605 | goto out; |
| 1606 | 1606 | } |
| 1607 | 1607 | |
| 1608 | − sk->sk_err = p->code; | |
| 1608 | + WRITE_ONCE(sk->sk_err, p->code); | |
| 1609 | 1609 | sk_error_report(sk); |
| 1610 | 1610 | out: |
| 1611 | 1611 | return ret; |
| @@ -1991,7 +1991,7 @@ static int netlink_recvmsg(struct socket *sock, struct msghdr *msg, size_t len, · 379 unmodified lines | ||
| 1991 | 1991 | atomic_read(&sk->sk_rmem_alloc) <= sk->sk_rcvbuf / 2) { |
| 1992 | 1992 | ret = netlink_dump(sk); |
| 1993 | 1993 | if (ret) { |
| 1994 | − sk->sk_err = -ret; | |
| 1994 | + WRITE_ONCE(sk->sk_err, -ret); | |
| 1995 | 1995 | sk_error_report(sk); |
| 1996 | 1996 | } |
| 1997 | 1997 | } |
| @@ -2511,7 +2511,7 @@ void netlink_ack(struct sk_buff *in_skb, struct nlmsghdr *nlh, int err, · 513 unmodified lines | ||
| 2511 | 2511 | err_bad_put: |
| 2512 | 2512 | nlmsg_free(skb); |
| 2513 | 2513 | err_skb: |
| 2514 | − NETLINK_CB(in_skb).sk->sk_err = ENOBUFS; | |
| 2514 | + WRITE_ONCE(NETLINK_CB(in_skb).sk->sk_err, ENOBUFS); | |
| 2515 | 2515 | sk_error_report(NETLINK_CB(in_skb).sk); |
| 2516 | 2516 | } |
| 2517 | 2517 | EXPORT_SYMBOL(netlink_ack); |
| @@ -1636,7 +1636,9 @@ int nfc_llcp_register_device(struct nfc_dev *ndev) · 1635 unmodified lines | ||
| 1636 | 1636 | timer_setup(&local->sdreq_timer, nfc_llcp_sdreq_timer, 0); |
| 1637 | 1637 | INIT_WORK(&local->sdreq_timeout_work, nfc_llcp_sdreq_timeout_work); |
| 1638 | 1638 | |
| 1639 | + spin_lock(&llcp_devices_lock); | |
| 1639 | 1640 | list_add(&local->list, &llcp_devices); |
| 1641 | + spin_unlock(&llcp_devices_lock); | |
| 1640 | 1642 | |
| 1641 | 1643 | return 0; |
| 1642 | 1644 | } |
| @@ -145,7 +145,7 @@ int rds_tcp_conn_path_connect(struct rds_conn_path *cp) · 144 unmodified lines | ||
| 145 | 145 | addrlen = sizeof(sin); |
| 146 | 146 | } |
| 147 | 147 | |
| 148 | − ret = sock->ops->bind(sock, addr, addrlen); | |
| 148 | + ret = kernel_bind(sock, addr, addrlen); | |
| 149 | 149 | if (ret) { |
| 150 | 150 | rdsdebug("bind failed with %d at address %pI6c\n", |
| 151 | 151 | ret, &conn->c_laddr); |
| @@ -173,7 +173,7 @@ int rds_tcp_conn_path_connect(struct rds_conn_path *cp) · 21 unmodified lines | ||
| 173 | 173 | * own the socket |
| 174 | 174 | */ |
| 175 | 175 | rds_tcp_set_callbacks(sock, cp); |
| 176 | − ret = sock->ops->connect(sock, addr, addrlen, O_NONBLOCK); | |
| 176 | + ret = kernel_connect(sock, addr, addrlen, O_NONBLOCK); | |
| 177 | 177 | |
| 178 | 178 | rdsdebug("connect to address %pI6c returned %d\n", &conn->c_faddr, ret); |
| 179 | 179 | if (ret == -EINPROGRESS) |
| @@ -306,7 +306,7 @@ struct socket *rds_tcp_listen_init(struct net *net, bool isv6) · 305 unmodified lines | ||
| 306 | 306 | addr_len = sizeof(*sin); |
| 307 | 307 | } |
| 308 | 308 | |
| 309 | − ret = sock->ops->bind(sock, (struct sockaddr *)&ss, addr_len); | |
| 309 | + ret = kernel_bind(sock, (struct sockaddr *)&ss, addr_len); | |
| 310 | 310 | if (ret < 0) { |
| 311 | 311 | rdsdebug("could not bind %s listener socket: %d\n", |
| 312 | 312 | isv6 ? "IPv6" : "IPv4", ret); |
| @@ -48,6 +48,7 @@ struct rfkill { · 47 unmodified lines | ||
| 48 | 48 | bool persistent; |
| 49 | 49 | bool polling_paused; |
| 50 | 50 | bool suspended; |
| 51 | + bool need_sync; | |
| 51 | 52 | |
| 52 | 53 | const struct rfkill_ops *ops; |
| 53 | 54 | void *data; |
| @@ -368,6 +369,17 @@ static void rfkill_set_block(struct rfkill *rfkill, bool blocked) · 314 unmodified lines | ||
| 368 | 369 | rfkill_event(rfkill); |
| 369 | 370 | } |
| 370 | 371 | |
| 372 | +static void rfkill_sync(struct rfkill *rfkill) | |
| 373 | +{ | |
| 374 | + lockdep_assert_held(&rfkill_global_mutex); | |
| 375 | + | |
| 376 | + if (!rfkill->need_sync) | |
| 377 | + return; | |
| 378 | + | |
| 379 | + rfkill_set_block(rfkill, rfkill_global_states[rfkill->type].cur); | |
| 380 | + rfkill->need_sync = false; | |
| 381 | +} | |
| 382 | + | |
| 371 | 383 | static void rfkill_update_global_state(enum rfkill_type type, bool blocked) |
| 372 | 384 | { |
| 373 | 385 | int i; |
| @@ -730,6 +742,10 @@ static ssize_t soft_show(struct device *dev, struct device_attribute *attr, · 356 unmodified lines | ||
| 730 | 742 | { |
| 731 | 743 | struct rfkill *rfkill = to_rfkill(dev); |
| 732 | 744 | |
| 745 | + mutex_lock(&rfkill_global_mutex); | |
| 746 | + rfkill_sync(rfkill); | |
| 747 | + mutex_unlock(&rfkill_global_mutex); | |
| 748 | + | |
| 733 | 749 | return sysfs_emit(buf, "%d\n", (rfkill->state & RFKILL_BLOCK_SW) ? 1 : 0); |
| 734 | 750 | } |
| 735 | 751 | |
| @@ -751,6 +767,7 @@ static ssize_t soft_store(struct device *dev, struct device_attribute *attr, · 15 unmodified lines | ||
| 751 | 767 | return -EINVAL; |
| 752 | 768 | |
| 753 | 769 | mutex_lock(&rfkill_global_mutex); |
| 770 | + rfkill_sync(rfkill); | |
| 754 | 771 | rfkill_set_block(rfkill, state); |
| 755 | 772 | mutex_unlock(&rfkill_global_mutex); |
| 756 | 773 | |
| @@ -783,6 +800,10 @@ static ssize_t state_show(struct device *dev, struct device_attribute *attr, · 26 unmodified lines | ||
| 783 | 800 | { |
| 784 | 801 | struct rfkill *rfkill = to_rfkill(dev); |
| 785 | 802 | |
| 803 | + mutex_lock(&rfkill_global_mutex); | |
| 804 | + rfkill_sync(rfkill); | |
| 805 | + mutex_unlock(&rfkill_global_mutex); | |
| 806 | + | |
| 786 | 807 | return sysfs_emit(buf, "%d\n", user_state_from_blocked(rfkill->state)); |
| 787 | 808 | } |
| 788 | 809 | |
| @@ -805,6 +826,7 @@ static ssize_t state_store(struct device *dev, struct device_attribute *attr, · 16 unmodified lines | ||
| 805 | 826 | return -EINVAL; |
| 806 | 827 | |
| 807 | 828 | mutex_lock(&rfkill_global_mutex); |
| 829 | + rfkill_sync(rfkill); | |
| 808 | 830 | rfkill_set_block(rfkill, state == RFKILL_USER_STATE_SOFT_BLOCKED); |
| 809 | 831 | mutex_unlock(&rfkill_global_mutex); |
| 810 | 832 | |
| @@ -1032,14 +1054,10 @@ static void rfkill_uevent_work(struct work_struct *work) · 221 unmodified lines | ||
| 1032 | 1054 | |
| 1033 | 1055 | static void rfkill_sync_work(struct work_struct *work) |
| 1034 | 1056 | { |
| 1035 | − struct rfkill *rfkill; | |
| 1036 | − bool cur; | |
| 1037 | − | |
| 1038 | − rfkill = container_of(work, struct rfkill, sync_work); | |
| 1057 | + struct rfkill *rfkill = container_of(work, struct rfkill, sync_work); | |
| 1039 | 1058 | |
| 1040 | 1059 | mutex_lock(&rfkill_global_mutex); |
| 1041 | − cur = rfkill_global_states[rfkill->type].cur; | |
| 1042 | − rfkill_set_block(rfkill, cur); | |
| 1060 | + rfkill_sync(rfkill); | |
| 1043 | 1061 | mutex_unlock(&rfkill_global_mutex); |
| 1044 | 1062 | } |
| 1045 | 1063 | |
| @@ -1087,6 +1105,7 @@ int __must_check rfkill_register(struct rfkill *rfkill) · 41 unmodified lines | ||
| 1087 | 1105 | round_jiffies_relative(POLL_INTERVAL)); |
| 1088 | 1106 | |
| 1089 | 1107 | if (!rfkill->persistent || rfkill_epo_lock_active) { |
| 1108 | + rfkill->need_sync = true; | |
| 1090 | 1109 | schedule_work(&rfkill->sync_work); |
| 1091 | 1110 | } else { |
| 1092 | 1111 | #ifdef CONFIG_RFKILL_INPUT |
| @@ -1171,6 +1190,7 @@ static int rfkill_fop_open(struct inode *inode, struct file *file) · 78 unmodified lines | ||
| 1171 | 1190 | ev = kzalloc(sizeof(*ev), GFP_KERNEL); |
| 1172 | 1191 | if (!ev) |
| 1173 | 1192 | goto free; |
| 1193 | + rfkill_sync(rfkill); | |
| 1174 | 1194 | rfkill_fill_event(&ev->ev, rfkill, RFKILL_OP_ADD); |
| 1175 | 1195 | list_add_tail(&ev->list, &data->events); |
| 1176 | 1196 | } |
| @@ -1159,8 +1159,7 @@ int sctp_assoc_update(struct sctp_association *asoc, · 1158 unmodified lines | ||
| 1159 | 1159 | /* Add any peer addresses from the new association. */ |
| 1160 | 1160 | list_for_each_entry(trans, &new->peer.transport_addr_list, |
| 1161 | 1161 | transports) |
| 1162 | − if (!sctp_assoc_lookup_paddr(asoc, &trans->ipaddr) && | |
| 1163 | − !sctp_assoc_add_peer(asoc, &trans->ipaddr, | |
| 1162 | + if (!sctp_assoc_add_peer(asoc, &trans->ipaddr, | |
| 1164 | 1163 | GFP_ATOMIC, trans->state)) |
| 1165 | 1164 | return -ENOMEM; |
| 1166 | 1165 | |
| @@ -2450,6 +2450,7 @@ static int sctp_apply_peer_addr_params(struct sctp_paddrparams *params, · 2449 unmodified lines | ||
| 2450 | 2450 | if (trans) { |
| 2451 | 2451 | trans->hbinterval = |
| 2452 | 2452 | msecs_to_jiffies(params->spp_hbinterval); |
| 2453 | + sctp_transport_reset_hb_timer(trans); | |
| 2453 | 2454 | } else if (asoc) { |
| 2454 | 2455 | asoc->hbinterval = |
| 2455 | 2456 | msecs_to_jiffies(params->spp_hbinterval); |
| @@ -737,6 +737,14 @@ static inline int sock_sendmsg_nosec(struct socket *sock, struct msghdr *msg) · 736 unmodified lines | ||
| 737 | 737 | return ret; |
| 738 | 738 | } |
| 739 | 739 | |
| 740 | +static int __sock_sendmsg(struct socket *sock, struct msghdr *msg) | |
| 741 | +{ | |
| 742 | + int err = security_socket_sendmsg(sock, msg, | |
| 743 | + msg_data_left(msg)); | |
| 744 | + | |
| 745 | + return err ?: sock_sendmsg_nosec(sock, msg); | |
| 746 | +} | |
| 747 | + | |
| 740 | 748 | /** |
| 741 | 749 | * sock_sendmsg - send a message through @sock |
| 742 | 750 | * @sock: socket |
| @@ -747,10 +755,19 @@ static inline int sock_sendmsg_nosec(struct socket *sock, struct msghdr *msg) · 4 unmodified lines | ||
| 747 | 755 | */ |
| 748 | 756 | int sock_sendmsg(struct socket *sock, struct msghdr *msg) |
| 749 | 757 | { |
| 750 | − int err = security_socket_sendmsg(sock, msg, | |
| 751 | − msg_data_left(msg)); | |
| 758 | + struct sockaddr_storage *save_addr = (struct sockaddr_storage *)msg->msg_name; | |
| 759 | + struct sockaddr_storage address; | |
| 760 | + int ret; | |
| 752 | 761 | |
| 753 | − return err ?: sock_sendmsg_nosec(sock, msg); | |
| 762 | + if (msg->msg_name) { | |
| 763 | + memcpy(&address, msg->msg_name, msg->msg_namelen); | |
| 764 | + msg->msg_name = &address; | |
| 765 | + } | |
| 766 | + | |
| 767 | + ret = __sock_sendmsg(sock, msg); | |
| 768 | + msg->msg_name = save_addr; | |
| 769 | + | |
| 770 | + return ret; | |
| 754 | 771 | } |
| 755 | 772 | EXPORT_SYMBOL(sock_sendmsg); |
| 756 | 773 | |
| @@ -1138,7 +1155,7 @@ static ssize_t sock_write_iter(struct kiocb *iocb, struct iov_iter *from) · 381 unmodified lines | ||
| 1138 | 1155 | if (sock->type == SOCK_SEQPACKET) |
| 1139 | 1156 | msg.msg_flags |= MSG_EOR; |
| 1140 | 1157 | |
| 1141 | − res = sock_sendmsg(sock, &msg); | |
| 1158 | + res = __sock_sendmsg(sock, &msg); | |
| 1142 | 1159 | *from = msg.msg_iter; |
| 1143 | 1160 | return res; |
| 1144 | 1161 | } |
| @@ -2174,7 +2191,7 @@ int __sys_sendto(int fd, void __user *buff, size_t len, unsigned int flags, · 1029 unmodified lines | ||
| 2174 | 2191 | if (sock->file->f_flags & O_NONBLOCK) |
| 2175 | 2192 | flags |= MSG_DONTWAIT; |
| 2176 | 2193 | msg.msg_flags = flags; |
| 2177 | − err = sock_sendmsg(sock, &msg); | |
| 2194 | + err = __sock_sendmsg(sock, &msg); | |
| 2178 | 2195 | |
| 2179 | 2196 | out_put: |
| 2180 | 2197 | fput_light(sock->file, fput_needed); |
| @@ -2538,7 +2555,7 @@ static int ____sys_sendmsg(struct socket *sock, struct msghdr *msg_sys, · 357 unmodified lines | ||
| 2538 | 2555 | err = sock_sendmsg_nosec(sock, msg_sys); |
| 2539 | 2556 | goto out_freectl; |
| 2540 | 2557 | } |
| 2541 | − err = sock_sendmsg(sock, msg_sys); | |
| 2558 | + err = __sock_sendmsg(sock, msg_sys); | |
| 2542 | 2559 | /* |
| 2543 | 2560 | * If this is sendmmsg() and sending to current destination address was |
| 2544 | 2561 | * successful, remember it. |
| @@ -3499,7 +3516,12 @@ static long compat_sock_ioctl(struct file *file, unsigned int cmd, · 954 unmodified lines | ||
| 3499 | 3516 | |
| 3500 | 3517 | int kernel_bind(struct socket *sock, struct sockaddr *addr, int addrlen) |
| 3501 | 3518 | { |
| 3502 | − return READ_ONCE(sock->ops)->bind(sock, addr, addrlen); | |
| 3519 | + struct sockaddr_storage address; | |
| 3520 | + | |
| 3521 | + memcpy(&address, addr, addrlen); | |
| 3522 | + | |
| 3523 | + return READ_ONCE(sock->ops)->bind(sock, (struct sockaddr *)&address, | |
| 3524 | + addrlen); | |
| 3503 | 3525 | } |
| 3504 | 3526 | EXPORT_SYMBOL(kernel_bind); |
| 3505 | 3527 | |
| @@ -769,9 +769,14 @@ int rpcauth_wrap_req(struct rpc_task *task, struct xdr_stream *xdr) · 768 unmodified lines | ||
| 769 | 769 | * @task: controlling RPC task |
| 770 | 770 | * @xdr: xdr_stream containing RPC Reply header |
| 771 | 771 | * |
| 772 | − * On success, @xdr is updated to point past the verifier and | |
| 773 | − * zero is returned. Otherwise, @xdr is in an undefined state | |
| 774 | − * and a negative errno is returned. | |
| 772 | + * Return values: | |
| 773 | + * %0: Verifier is valid. @xdr now points past the verifier. | |
| 774 | + * %-EIO: Verifier is corrupted or message ended early. | |
| 775 | + * %-EACCES: Verifier is intact but not valid. | |
| 776 | + * %-EPROTONOSUPPORT: Server does not support the requested auth type. | |
| 777 | + * | |
| 778 | + * When a negative errno is returned, @xdr is left in an undefined | |
| 779 | + * state. | |
| 775 | 780 | */ |
| 776 | 781 | int |
| 777 | 782 | rpcauth_checkverf(struct rpc_task *task, struct xdr_stream *xdr) |
| @@ -129,9 +129,9 @@ static int tls_validate(struct rpc_task *task, struct xdr_stream *xdr) · 128 unmodified lines | ||
| 129 | 129 | if (*p != rpc_auth_null) |
| 130 | 130 | return -EIO; |
| 131 | 131 | if (xdr_stream_decode_opaque_inline(xdr, &str, starttls_len) != starttls_len) |
| 132 | − return -EIO; | |
| 132 | + return -EPROTONOSUPPORT; | |
| 133 | 133 | if (memcmp(str, starttls_token, starttls_len)) |
| 134 | − return -EIO; | |
| 134 | + return -EPROTONOSUPPORT; | |
| 135 | 135 | return 0; |
| 136 | 136 | } |
| 137 | 137 | |
| @@ -2476,8 +2476,7 @@ call_status(struct rpc_task *task) · 2475 unmodified lines | ||
| 2476 | 2476 | goto out_exit; |
| 2477 | 2477 | } |
| 2478 | 2478 | task->tk_action = call_encode; |
| 2479 | − if (status != -ECONNRESET && status != -ECONNABORTED) | |
| 2480 | − rpc_check_timeout(task); | |
| 2479 | + rpc_check_timeout(task); | |
| 2481 | 2480 | return; |
| 2482 | 2481 | out_exit: |
| 2483 | 2482 | rpc_call_rpcerror(task, status); |
| @@ -2725,7 +2724,15 @@ out_unparsable: · 241 unmodified lines | ||
| 2725 | 2724 | |
| 2726 | 2725 | out_verifier: |
| 2727 | 2726 | trace_rpc_bad_verifier(task); |
| 2728 | − goto out_garbage; | |
| 2727 | + switch (error) { | |
| 2728 | + case -EPROTONOSUPPORT: | |
| 2729 | + goto out_err; | |
| 2730 | + case -EACCES: | |
| 2731 | + /* Re-encode with a fresh cred */ | |
| 2732 | + fallthrough; | |
| 2733 | + default: | |
| 2734 | + goto out_garbage; | |
| 2735 | + } | |
| 2729 | 2736 | |
| 2730 | 2737 | out_msg_denied: |
| 2731 | 2738 | error = -EACCES; |
| @@ -2672,6 +2672,10 @@ static void xs_tcp_tls_setup_socket(struct work_struct *work) · 2671 unmodified lines | ||
| 2672 | 2672 | rcu_read_lock(); |
| 2673 | 2673 | lower_xprt = rcu_dereference(lower_clnt->cl_xprt); |
| 2674 | 2674 | rcu_read_unlock(); |
| 2675 | + | |
| 2676 | + if (wait_on_bit_lock(&lower_xprt->state, XPRT_LOCKED, TASK_KILLABLE)) | |
| 2677 | + goto out_unlock; | |
| 2678 | + | |
| 2675 | 2679 | status = xs_tls_handshake_sync(lower_xprt, &upper_xprt->xprtsec); |
| 2676 | 2680 | if (status) { |
| 2677 | 2681 | trace_rpc_tls_not_started(upper_clnt, upper_xprt); |
| @@ -2681,6 +2685,7 @@ static void xs_tcp_tls_setup_socket(struct work_struct *work) · 3 unmodified lines | ||
| 2681 | 2685 | status = xs_tcp_tls_finish_connecting(lower_xprt, upper_transport); |
| 2682 | 2686 | if (status) |
| 2683 | 2687 | goto out_close; |
| 2688 | + xprt_release_write(lower_xprt, NULL); | |
| 2684 | 2689 | |
| 2685 | 2690 | trace_rpc_socket_connect(upper_xprt, upper_transport->sock, 0); |
| 2686 | 2691 | if (!xprt_test_and_set_connected(upper_xprt)) { |
| @@ -2702,6 +2707,7 @@ out_unlock: · 15 unmodified lines | ||
| 2702 | 2707 | return; |
| 2703 | 2708 | |
| 2704 | 2709 | out_close: |
| 2710 | + xprt_release_write(lower_xprt, NULL); | |
| 2705 | 2711 | rpc_shutdown_client(lower_clnt); |
| 2706 | 2712 | |
| 2707 | 2713 | /* xprt_force_disconnect() wakes tasks with a fixed tk_status code. |
| @@ -1441,14 +1441,14 @@ static int tipc_crypto_key_revoke(struct net *net, u8 tx_key) · 1440 unmodified lines | ||
| 1441 | 1441 | struct tipc_crypto *tx = tipc_net(net)->crypto_tx; |
| 1442 | 1442 | struct tipc_key key; |
| 1443 | 1443 | |
| 1444 | − spin_lock(&tx->lock); | |
| 1444 | + spin_lock_bh(&tx->lock); | |
| 1445 | 1445 | key = tx->key; |
| 1446 | 1446 | WARN_ON(!key.active || tx_key != key.active); |
| 1447 | 1447 | |
| 1448 | 1448 | /* Free the active key */ |
| 1449 | 1449 | tipc_crypto_key_set_state(tx, key.passive, 0, key.pending); |
| 1450 | 1450 | tipc_crypto_key_detach(tx->aead[key.active], &tx->lock); |
| 1451 | − spin_unlock(&tx->lock); | |
| 1451 | + spin_unlock_bh(&tx->lock); | |
| 1452 | 1452 | |
| 1453 | 1453 | pr_warn("%s: key is revoked\n", tx->name); |
| 1454 | 1454 | return -EKEYREVOKED; |
| @@ -1181,16 +1181,11 @@ void wiphy_rfkill_set_hw_state_reason(struct wiphy *wiphy, bool blocked, · 1180 unmodified lines | ||
| 1181 | 1181 | } |
| 1182 | 1182 | EXPORT_SYMBOL(wiphy_rfkill_set_hw_state_reason); |
| 1183 | 1183 | |
| 1184 | −void cfg80211_cqm_config_free(struct wireless_dev *wdev) | |
| 1185 | −{ | |
| 1186 | − kfree(wdev->cqm_config); | |
| 1187 | − wdev->cqm_config = NULL; | |
| 1188 | −} | |
| 1189 | − | |
| 1190 | 1184 | static void _cfg80211_unregister_wdev(struct wireless_dev *wdev, |
| 1191 | 1185 | bool unregister_netdev) |
| 1192 | 1186 | { |
| 1193 | 1187 | struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy); |
| 1188 | + struct cfg80211_cqm_config *cqm_config; | |
| 1194 | 1189 | unsigned int link_id; |
| 1195 | 1190 | |
| 1196 | 1191 | ASSERT_RTNL(); |
| @@ -1227,7 +1222,10 @@ static void _cfg80211_unregister_wdev(struct wireless_dev *wdev, · 30 unmodified lines | ||
| 1227 | 1222 | kfree_sensitive(wdev->wext.keys); |
| 1228 | 1223 | wdev->wext.keys = NULL; |
| 1229 | 1224 | #endif |
| 1230 | − cfg80211_cqm_config_free(wdev); | |
| 1225 | + wiphy_work_cancel(wdev->wiphy, &wdev->cqm_rssi_work); | |
| 1226 | + /* deleted from the list, so can't be found from nl80211 any more */ | |
| 1227 | + cqm_config = rcu_access_pointer(wdev->cqm_config); | |
| 1228 | + kfree_rcu(cqm_config, rcu_head); | |
| 1231 | 1229 | |
| 1232 | 1230 | /* |
| 1233 | 1231 | * Ensure that all events have been processed and |
| @@ -1379,6 +1377,8 @@ void cfg80211_init_wdev(struct wireless_dev *wdev) · 145 unmodified lines | ||
| 1379 | 1377 | wdev->wext.connect.auth_type = NL80211_AUTHTYPE_AUTOMATIC; |
| 1380 | 1378 | #endif |
| 1381 | 1379 | |
| 1380 | + wiphy_work_init(&wdev->cqm_rssi_work, cfg80211_cqm_rssi_notify_work); | |
| 1381 | + | |
| 1382 | 1382 | if (wdev->wiphy->flags & WIPHY_FLAG_PS_ON_BY_DEFAULT) |
| 1383 | 1383 | wdev->ps = true; |
| 1384 | 1384 | else |
| @@ -295,12 +295,17 @@ struct cfg80211_beacon_registration { · 294 unmodified lines | ||
| 295 | 295 | }; |
| 296 | 296 | |
| 297 | 297 | struct cfg80211_cqm_config { |
| 298 | + struct rcu_head rcu_head; | |
| 298 | 299 | u32 rssi_hyst; |
| 299 | 300 | s32 last_rssi_event_value; |
| 301 | + enum nl80211_cqm_rssi_threshold_event last_rssi_event_type; | |
| 300 | 302 | int n_rssi_thresholds; |
| 301 | 303 | s32 rssi_thresholds[] __counted_by(n_rssi_thresholds); |
| 302 | 304 | }; |
| 303 | 305 | |
| 306 | +void cfg80211_cqm_rssi_notify_work(struct wiphy *wiphy, | |
| 307 | + struct wiphy_work *work); | |
| 308 | + | |
| 304 | 309 | void cfg80211_destroy_ifaces(struct cfg80211_registered_device *rdev); |
| 305 | 310 | |
| 306 | 311 | /* free object */ |
| @@ -566,8 +571,6 @@ cfg80211_bss_update(struct cfg80211_registered_device *rdev, · 259 unmodified lines | ||
| 566 | 571 | #define CFG80211_DEV_WARN_ON(cond) ({bool __r = (cond); __r; }) |
| 567 | 572 | #endif |
| 568 | 573 | |
| 569 | −void cfg80211_cqm_config_free(struct wireless_dev *wdev); | |
| 570 | − | |
| 571 | 574 | void cfg80211_release_pmsr(struct wireless_dev *wdev, u32 portid); |
| 572 | 575 | void cfg80211_pmsr_wdev_down(struct wireless_dev *wdev); |
| 573 | 576 | void cfg80211_pmsr_free_wk(struct work_struct *work); |
| @@ -52,7 +52,8 @@ void cfg80211_rx_assoc_resp(struct net_device *dev, · 51 unmodified lines | ||
| 52 | 52 | cr.links[link_id].bssid = data->links[link_id].bss->bssid; |
| 53 | 53 | cr.links[link_id].addr = data->links[link_id].addr; |
| 54 | 54 | /* need to have local link addresses for MLO connections */ |
| 55 | − WARN_ON(cr.ap_mld_addr && !cr.links[link_id].addr); | |
| 55 | + WARN_ON(cr.ap_mld_addr && | |
| 56 | + !is_valid_ether_addr(cr.links[link_id].addr)); | |
| 56 | 57 | |
| 57 | 58 | BUG_ON(!cr.links[link_id].bss->channel); |
| 58 | 59 | |
| @@ -5909,6 +5909,21 @@ out: · 5908 unmodified lines | ||
| 5909 | 5909 | nlmsg_free(msg); |
| 5910 | 5910 | } |
| 5911 | 5911 | |
| 5912 | +static int nl80211_validate_ap_phy_operation(struct cfg80211_ap_settings *params) | |
| 5913 | +{ | |
| 5914 | + struct ieee80211_channel *channel = params->chandef.chan; | |
| 5915 | + | |
| 5916 | + if ((params->he_cap || params->he_oper) && | |
| 5917 | + (channel->flags & IEEE80211_CHAN_NO_HE)) | |
| 5918 | + return -EOPNOTSUPP; | |
| 5919 | + | |
| 5920 | + if ((params->eht_cap || params->eht_oper) && | |
| 5921 | + (channel->flags & IEEE80211_CHAN_NO_EHT)) | |
| 5922 | + return -EOPNOTSUPP; | |
| 5923 | + | |
| 5924 | + return 0; | |
| 5925 | +} | |
| 5926 | + | |
| 5912 | 5927 | static int nl80211_start_ap(struct sk_buff *skb, struct genl_info *info) |
| 5913 | 5928 | { |
| 5914 | 5929 | struct cfg80211_registered_device *rdev = info->user_ptr[0]; |
| @@ -6178,6 +6193,10 @@ static int nl80211_start_ap(struct sk_buff *skb, struct genl_info *info) · 263 unmodified lines | ||
| 6178 | 6193 | if (err) |
| 6179 | 6194 | goto out_unlock; |
| 6180 | 6195 | |
| 6196 | + err = nl80211_validate_ap_phy_operation(params); | |
| 6197 | + if (err) | |
| 6198 | + goto out_unlock; | |
| 6199 | + | |
| 6181 | 6200 | if (info->attrs[NL80211_ATTR_AP_SETTINGS_FLAGS]) |
| 6182 | 6201 | params->flags = nla_get_u32( |
| 6183 | 6202 | info->attrs[NL80211_ATTR_AP_SETTINGS_FLAGS]); |
| @@ -8482,7 +8501,7 @@ static int nl80211_update_mesh_config(struct sk_buff *skb, · 2298 unmodified lines | ||
| 8482 | 8501 | struct cfg80211_registered_device *rdev = info->user_ptr[0]; |
| 8483 | 8502 | struct net_device *dev = info->user_ptr[1]; |
| 8484 | 8503 | struct wireless_dev *wdev = dev->ieee80211_ptr; |
| 8485 | − struct mesh_config cfg; | |
| 8504 | + struct mesh_config cfg = {}; | |
| 8486 | 8505 | u32 mask; |
| 8487 | 8506 | int err; |
| 8488 | 8507 | |
| @@ -12796,7 +12815,8 @@ static int nl80211_set_cqm_txe(struct genl_info *info, · 4307 unmodified lines | ||
| 12796 | 12815 | } |
| 12797 | 12816 | |
| 12798 | 12817 | static int cfg80211_cqm_rssi_update(struct cfg80211_registered_device *rdev, |
| 12799 | − struct net_device *dev) | |
| 12818 | + struct net_device *dev, | |
| 12819 | + struct cfg80211_cqm_config *cqm_config) | |
| 12800 | 12820 | { |
| 12801 | 12821 | struct wireless_dev *wdev = dev->ieee80211_ptr; |
| 12802 | 12822 | s32 last, low, high; |
| @@ -12805,7 +12825,7 @@ static int cfg80211_cqm_rssi_update(struct cfg80211_registered_device *rdev, · 2 unmodified lines | ||
| 12805 | 12825 | int err; |
| 12806 | 12826 | |
| 12807 | 12827 | /* RSSI reporting disabled? */ |
| 12808 | − if (!wdev->cqm_config) | |
| 12828 | + if (!cqm_config) | |
| 12809 | 12829 | return rdev_set_cqm_rssi_range_config(rdev, dev, 0, 0); |
| 12810 | 12830 | |
| 12811 | 12831 | /* |
| @@ -12814,7 +12834,7 @@ static int cfg80211_cqm_rssi_update(struct cfg80211_registered_device *rdev, · 2 unmodified lines | ||
| 12814 | 12834 | * connection is established and enough beacons received to calculate |
| 12815 | 12835 | * the average. |
| 12816 | 12836 | */ |
| 12817 | − if (!wdev->cqm_config->last_rssi_event_value && | |
| 12837 | + if (!cqm_config->last_rssi_event_value && | |
| 12818 | 12838 | wdev->links[0].client.current_bss && |
| 12819 | 12839 | rdev->ops->get_station) { |
| 12820 | 12840 | struct station_info sinfo = {}; |
| @@ -12828,30 +12848,30 @@ static int cfg80211_cqm_rssi_update(struct cfg80211_registered_device *rdev, · 7 unmodified lines | ||
| 12828 | 12848 | |
| 12829 | 12849 | cfg80211_sinfo_release_content(&sinfo); |
| 12830 | 12850 | if (sinfo.filled & BIT_ULL(NL80211_STA_INFO_BEACON_SIGNAL_AVG)) |
| 12831 | − wdev->cqm_config->last_rssi_event_value = | |
| 12851 | + cqm_config->last_rssi_event_value = | |
| 12832 | 12852 | (s8) sinfo.rx_beacon_signal_avg; |
| 12833 | 12853 | } |
| 12834 | 12854 | |
| 12835 | − last = wdev->cqm_config->last_rssi_event_value; | |
| 12836 | − hyst = wdev->cqm_config->rssi_hyst; | |
| 12837 | − n = wdev->cqm_config->n_rssi_thresholds; | |
| 12855 | + last = cqm_config->last_rssi_event_value; | |
| 12856 | + hyst = cqm_config->rssi_hyst; | |
| 12857 | + n = cqm_config->n_rssi_thresholds; | |
| 12838 | 12858 | |
| 12839 | 12859 | for (i = 0; i < n; i++) { |
| 12840 | 12860 | i = array_index_nospec(i, n); |
| 12841 | − if (last < wdev->cqm_config->rssi_thresholds[i]) | |
| 12861 | + if (last < cqm_config->rssi_thresholds[i]) | |
| 12842 | 12862 | break; |
| 12843 | 12863 | } |
| 12844 | 12864 | |
| 12845 | 12865 | low_index = i - 1; |
| 12846 | 12866 | if (low_index >= 0) { |
| 12847 | 12867 | low_index = array_index_nospec(low_index, n); |
| 12848 | − low = wdev->cqm_config->rssi_thresholds[low_index] - hyst; | |
| 12868 | + low = cqm_config->rssi_thresholds[low_index] - hyst; | |
| 12849 | 12869 | } else { |
| 12850 | 12870 | low = S32_MIN; |
| 12851 | 12871 | } |
| 12852 | 12872 | if (i < n) { |
| 12853 | 12873 | i = array_index_nospec(i, n); |
| 12854 | − high = wdev->cqm_config->rssi_thresholds[i] + hyst - 1; | |
| 12874 | + high = cqm_config->rssi_thresholds[i] + hyst - 1; | |
| 12855 | 12875 | } else { |
| 12856 | 12876 | high = S32_MAX; |
| 12857 | 12877 | } |
| @@ -12864,6 +12884,7 @@ static int nl80211_set_cqm_rssi(struct genl_info *info, · 6 unmodified lines | ||
| 12864 | 12884 | u32 hysteresis) |
| 12865 | 12885 | { |
| 12866 | 12886 | struct cfg80211_registered_device *rdev = info->user_ptr[0]; |
| 12887 | + struct cfg80211_cqm_config *cqm_config = NULL, *old; | |
| 12867 | 12888 | struct net_device *dev = info->user_ptr[1]; |
| 12868 | 12889 | struct wireless_dev *wdev = dev->ieee80211_ptr; |
| 12869 | 12890 | int i, err; |
| @@ -12881,10 +12902,6 @@ static int nl80211_set_cqm_rssi(struct genl_info *info, · 11 unmodified lines | ||
| 12881 | 12902 | wdev->iftype != NL80211_IFTYPE_P2P_CLIENT) |
| 12882 | 12903 | return -EOPNOTSUPP; |
| 12883 | 12904 | |
| 12884 | − wdev_lock(wdev); | |
| 12885 | − cfg80211_cqm_config_free(wdev); | |
| 12886 | − wdev_unlock(wdev); | |
| 12887 | − | |
| 12888 | 12905 | if (n_thresholds <= 1 && rdev->ops->set_cqm_rssi_config) { |
| 12889 | 12906 | if (n_thresholds == 0 || thresholds[0] == 0) /* Disabling */ |
| 12890 | 12907 | return rdev_set_cqm_rssi_config(rdev, dev, 0, 0); |
| @@ -12901,9 +12918,10 @@ static int nl80211_set_cqm_rssi(struct genl_info *info, · 10 unmodified lines | ||
| 12901 | 12918 | n_thresholds = 0; |
| 12902 | 12919 | |
| 12903 | 12920 | wdev_lock(wdev); |
| 12904 | − if (n_thresholds) { | |
| 12905 | − struct cfg80211_cqm_config *cqm_config; | |
| 12921 | + old = rcu_dereference_protected(wdev->cqm_config, | |
| 12922 | + lockdep_is_held(&wdev->mtx)); | |
| 12906 | 12923 | |
| 12924 | + if (n_thresholds) { | |
| 12907 | 12925 | cqm_config = kzalloc(struct_size(cqm_config, rssi_thresholds, |
| 12908 | 12926 | n_thresholds), |
| 12909 | 12927 | GFP_KERNEL); |
| @@ -12918,11 +12936,18 @@ static int nl80211_set_cqm_rssi(struct genl_info *info, · 8 unmodified lines | ||
| 12918 | 12936 | flex_array_size(cqm_config, rssi_thresholds, |
| 12919 | 12937 | n_thresholds)); |
| 12920 | 12938 | |
| 12921 | − wdev->cqm_config = cqm_config; | |
| 12939 | + rcu_assign_pointer(wdev->cqm_config, cqm_config); | |
| 12940 | + } else { | |
| 12941 | + RCU_INIT_POINTER(wdev->cqm_config, NULL); | |
| 12922 | 12942 | } |
| 12923 | 12943 | |
| 12924 | − err = cfg80211_cqm_rssi_update(rdev, dev); | |
| 12925 | − | |
| 12944 | + err = cfg80211_cqm_rssi_update(rdev, dev, cqm_config); | |
| 12945 | + if (err) { | |
| 12946 | + rcu_assign_pointer(wdev->cqm_config, old); | |
| 12947 | + kfree_rcu(cqm_config, rcu_head); | |
| 12948 | + } else { | |
| 12949 | + kfree_rcu(old, rcu_head); | |
| 12950 | + } | |
| 12926 | 12951 | unlock: |
| 12927 | 12952 | wdev_unlock(wdev); |
| 12928 | 12953 | |
| @@ -19073,9 +19098,8 @@ void cfg80211_cqm_rssi_notify(struct net_device *dev, · 6144 unmodified lines | ||
| 19073 | 19098 | enum nl80211_cqm_rssi_threshold_event rssi_event, |
| 19074 | 19099 | s32 rssi_level, gfp_t gfp) |
| 19075 | 19100 | { |
| 19076 | − struct sk_buff *msg; | |
| 19077 | 19101 | struct wireless_dev *wdev = dev->ieee80211_ptr; |
| 19078 | − struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy); | |
| 19102 | + struct cfg80211_cqm_config *cqm_config; | |
| 19079 | 19103 | |
| 19080 | 19104 | trace_cfg80211_cqm_rssi_notify(dev, rssi_event, rssi_level); |
| 19081 | 19105 | |
| @@ -19083,18 +19107,41 @@ void cfg80211_cqm_rssi_notify(struct net_device *dev, · 1 unmodified line | ||
| 19083 | 19107 | rssi_event != NL80211_CQM_RSSI_THRESHOLD_EVENT_HIGH)) |
| 19084 | 19108 | return; |
| 19085 | 19109 | |
| 19086 | − if (wdev->cqm_config) { | |
| 19087 | − wdev->cqm_config->last_rssi_event_value = rssi_level; | |
| 19110 | + rcu_read_lock(); | |
| 19111 | + cqm_config = rcu_dereference(wdev->cqm_config); | |
| 19112 | + if (cqm_config) { | |
| 19113 | + cqm_config->last_rssi_event_value = rssi_level; | |
| 19114 | + cqm_config->last_rssi_event_type = rssi_event; | |
| 19115 | + wiphy_work_queue(wdev->wiphy, &wdev->cqm_rssi_work); | |
| 19116 | + } | |
| 19117 | + rcu_read_unlock(); | |
| 19118 | +} | |
| 19119 | +EXPORT_SYMBOL(cfg80211_cqm_rssi_notify); | |
| 19088 | 19120 | |
| 19089 | − cfg80211_cqm_rssi_update(rdev, dev); | |
| 19121 | +void cfg80211_cqm_rssi_notify_work(struct wiphy *wiphy, struct wiphy_work *work) | |
| 19122 | +{ | |
| 19123 | + struct wireless_dev *wdev = container_of(work, struct wireless_dev, | |
| 19124 | + cqm_rssi_work); | |
| 19125 | + struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy); | |
| 19126 | + enum nl80211_cqm_rssi_threshold_event rssi_event; | |
| 19127 | + struct cfg80211_cqm_config *cqm_config; | |
| 19128 | + struct sk_buff *msg; | |
| 19129 | + s32 rssi_level; | |
| 19090 | 19130 | |
| 19091 | − if (rssi_level == 0) | |
| 19092 | − rssi_level = wdev->cqm_config->last_rssi_event_value; | |
| 19093 | − } | |
| 19131 | + wdev_lock(wdev); | |
| 19132 | + cqm_config = rcu_dereference_protected(wdev->cqm_config, | |
| 19133 | + lockdep_is_held(&wdev->mtx)); | |
| 19134 | + if (!wdev->cqm_config) | |
| 19135 | + goto unlock; | |
| 19094 | 19136 | |
| 19095 | − msg = cfg80211_prepare_cqm(dev, NULL, gfp); | |
| 19137 | + cfg80211_cqm_rssi_update(rdev, wdev->netdev, cqm_config); | |
| 19138 | + | |
| 19139 | + rssi_level = cqm_config->last_rssi_event_value; | |
| 19140 | + rssi_event = cqm_config->last_rssi_event_type; | |
| 19141 | + | |
| 19142 | + msg = cfg80211_prepare_cqm(wdev->netdev, NULL, GFP_KERNEL); | |
| 19096 | 19143 | if (!msg) |
| 19097 | − return; | |
| 19144 | + goto unlock; | |
| 19098 | 19145 | |
| 19099 | 19146 | if (nla_put_u32(msg, NL80211_ATTR_CQM_RSSI_THRESHOLD_EVENT, |
| 19100 | 19147 | rssi_event)) |
| @@ -19104,14 +19151,15 @@ void cfg80211_cqm_rssi_notify(struct net_device *dev, · 3 unmodified lines | ||
| 19104 | 19151 | rssi_level)) |
| 19105 | 19152 | goto nla_put_failure; |
| 19106 | 19153 | |
| 19107 | − cfg80211_send_cqm(msg, gfp); | |
| 19154 | + cfg80211_send_cqm(msg, GFP_KERNEL); | |
| 19108 | 19155 | |
| 19109 | − return; | |
| 19156 | + goto unlock; | |
| 19110 | 19157 | |
| 19111 | 19158 | nla_put_failure: |
| 19112 | 19159 | nlmsg_free(msg); |
| 19160 | + unlock: | |
| 19161 | + wdev_unlock(wdev); | |
| 19113 | 19162 | } |
| 19114 | −EXPORT_SYMBOL(cfg80211_cqm_rssi_notify); | |
| 19115 | 19163 | |
| 19116 | 19164 | void cfg80211_cqm_txe_notify(struct net_device *dev, |
| 19117 | 19165 | const u8 *peer, u32 num_packets, |
| @@ -908,6 +908,10 @@ static int cfg80211_scan_6ghz(struct cfg80211_registered_device *rdev) · 907 unmodified lines | ||
| 908 | 908 | !cfg80211_find_ssid_match(ap, request)) |
| 909 | 909 | continue; |
| 910 | 910 | |
| 911 | + if (!is_broadcast_ether_addr(request->bssid) && | |
| 912 | + !ether_addr_equal(request->bssid, ap->bssid)) | |
| 913 | + continue; | |
| 914 | + | |
| 911 | 915 | if (!request->n_ssids && ap->multi_bss && !ap->transmitted_bssid) |
| 912 | 916 | continue; |
| 913 | 917 | |
| @@ -144,7 +144,7 @@ endif · 143 unmodified lines | ||
| 144 | 144 | quiet_cmd_gzip = GZIP $@ |
| 145 | 145 | cmd_gzip = $(KGZIP) -n -f $< |
| 146 | 146 | quiet_cmd_xz = XZ $@ |
| 147 | − cmd_xz = $(XZ) --lzma2=dict=2MiB -f $< | |
| 147 | + cmd_xz = $(XZ) --check=crc32 --lzma2=dict=1MiB -f $< | |
| 148 | 148 | quiet_cmd_zstd = ZSTD $@ |
| 149 | 149 | cmd_zstd = $(ZSTD) -T0 --rm -f -q $< |
| 150 | 150 | |
| @@ -102,7 +102,7 @@ gen_proto_order_variant() · 101 unmodified lines | ||
| 102 | 102 | fi |
| 103 | 103 | |
| 104 | 104 | # Allow ACQUIRE/RELEASE/RELAXED ops to be defined in terms of FULL ops |
| 105 | − if [ ! -z "${order}" ]; then | |
| 105 | + if [ ! -z "${order}" ] && ! meta_is_implicitly_relaxed "${meta}"; then | |
| 106 | 106 | printf "#elif defined(arch_${basename})\n" |
| 107 | 107 | printf "\t${retstmt}arch_${basename}(${args});\n" |
| 108 | 108 | fi |
| @@ -111,12 +111,11 @@ lx-symbols command.""" · 110 unmodified lines | ||
| 111 | 111 | return "{textaddr} {sections}".format( |
| 112 | 112 | textaddr=textaddr, sections="".join(args)) |
| 113 | 113 | |
| 114 | − def load_module_symbols(self, module, module_file=None): | |
| 114 | + def load_module_symbols(self, module): | |
| 115 | 115 | module_name = module['name'].string() |
| 116 | 116 | module_addr = str(module['mem'][constants.LX_MOD_TEXT]['base']).split()[0] |
| 117 | 117 | |
| 118 | − if not module_file: | |
| 119 | − module_file = self._get_module_file(module_name) | |
| 118 | + module_file = self._get_module_file(module_name) | |
| 120 | 119 | if not module_file and not self.module_files_updated: |
| 121 | 120 | self._update_module_files() |
| 122 | 121 | module_file = self._get_module_file(module_name) |
| @@ -139,19 +138,6 @@ lx-symbols command.""" · 16 unmodified lines | ||
| 139 | 138 | else: |
| 140 | 139 | gdb.write("no module object found for '{0}'\n".format(module_name)) |
| 141 | 140 | |
| 142 | − def load_ko_symbols(self, mod_path): | |
| 143 | − self.loaded_modules = [] | |
| 144 | − module_list = modules.module_list() | |
| 145 | − | |
| 146 | − for module in module_list: | |
| 147 | − module_name = module['name'].string() | |
| 148 | − module_pattern = ".*/{0}\.ko(?:.debug)?$".format( | |
| 149 | − module_name.replace("_", r"[_\-]")) | |
| 150 | − if re.match(module_pattern, mod_path) and os.path.exists(mod_path): | |
| 151 | − self.load_module_symbols(module, mod_path) | |
| 152 | − return | |
| 153 | − raise gdb.GdbError("%s is not a valid .ko\n" % mod_path) | |
| 154 | − | |
| 155 | 141 | def load_all_symbols(self): |
| 156 | 142 | gdb.write("loading vmlinux\n") |
| 157 | 143 | |
| @@ -190,11 +176,6 @@ lx-symbols command.""" · 32 unmodified lines | ||
| 190 | 176 | self.module_files = [] |
| 191 | 177 | self.module_files_updated = False |
| 192 | 178 | |
| 193 | − argv = gdb.string_to_argv(arg) | |
| 194 | − if len(argv) == 1: | |
| 195 | − self.load_ko_symbols(argv[0]) | |
| 196 | − return | |
| 197 | − | |
| 198 | 179 | self.load_all_symbols() |
| 199 | 180 | |
| 200 | 181 | if hasattr(gdb, 'Breakpoint'): |
| @@ -1604,7 +1604,7 @@ void handle_moddevtable(struct module *mod, struct elf_info *info, · 1603 unmodified lines | ||
| 1604 | 1604 | /* First handle the "special" cases */ |
| 1605 | 1605 | if (sym_is(name, namelen, "usb")) |
| 1606 | 1606 | do_usb_table(symval, sym->st_size, mod); |
| 1607 | − if (sym_is(name, namelen, "of")) | |
| 1607 | + else if (sym_is(name, namelen, "of")) | |
| 1608 | 1608 | do_of_table(symval, sym->st_size, mod); |
| 1609 | 1609 | else if (sym_is(name, namelen, "pnp")) |
| 1610 | 1610 | do_pnp_device_entry(symval, sym->st_size, mod); |
| @@ -1015,9 +1015,20 @@ static int secref_whitelist(const char *fromsec, const char *fromsym, · 1014 unmodified lines | ||
| 1015 | 1015 | "*_console"))) |
| 1016 | 1016 | return 0; |
| 1017 | 1017 | |
| 1018 | − /* symbols in data sections that may refer to meminit/exit sections */ | |
| 1018 | + /* symbols in data sections that may refer to meminit sections */ | |
| 1019 | 1019 | if (match(fromsec, PATTERNS(DATA_SECTIONS)) && |
| 1020 | − match(tosec, PATTERNS(ALL_XXXINIT_SECTIONS, ALL_EXIT_SECTIONS)) && | |
| 1020 | + match(tosec, PATTERNS(ALL_XXXINIT_SECTIONS, ALL_XXXEXIT_SECTIONS)) && | |
| 1021 | + match(fromsym, PATTERNS("*driver"))) | |
| 1022 | + return 0; | |
| 1023 | + | |
| 1024 | + /* | |
| 1025 | + * symbols in data sections must not refer to .exit.*, but there are | |
| 1026 | + * quite a few offenders, so hide these unless for W=1 builds until | |
| 1027 | + * these are fixed. | |
| 1028 | + */ | |
| 1029 | + if (!extra_warn && | |
| 1030 | + match(fromsec, PATTERNS(DATA_SECTIONS)) && | |
| 1031 | + match(tosec, PATTERNS(EXIT_SECTIONS)) && | |
| 1021 | 1032 | match(fromsym, PATTERNS("*driver"))) |
| 1022 | 1033 | return 0; |
| 1023 | 1034 | |
| @@ -64,7 +64,6 @@ install_linux_image () { · 63 unmodified lines | ||
| 64 | 64 | |
| 65 | 65 | ${MAKE} -f ${srctree}/Makefile INSTALL_MOD_PATH="${pdir}" modules_install |
| 66 | 66 | rm -f "${pdir}/lib/modules/${KERNELRELEASE}/build" |
| 67 | − rm -f "${pdir}/lib/modules/${KERNELRELEASE}/source" | |
| 68 | 67 | |
| 69 | 68 | # Install the kernel |
| 70 | 69 | if [ "${ARCH}" = um ] ; then |
| @@ -68,7 +68,6 @@ cp $(%{make} %{makeflags} -s image_name) %{buildroot}/boot/vmlinuz-%{KERNELRELEA · 67 unmodified lines | ||
| 68 | 68 | cp System.map %{buildroot}/boot/System.map-%{KERNELRELEASE} |
| 69 | 69 | cp .config %{buildroot}/boot/config-%{KERNELRELEASE} |
| 70 | 70 | ln -fns /usr/src/kernels/%{KERNELRELEASE} %{buildroot}/lib/modules/%{KERNELRELEASE}/build |
| 71 | −ln -fns /usr/src/kernels/%{KERNELRELEASE} %{buildroot}/lib/modules/%{KERNELRELEASE}/source | |
| 72 | 71 | %if %{with_devel} |
| 73 | 72 | %{make} %{makeflags} run-command KBUILD_RUN_COMMAND='${srctree}/scripts/package/install-extmod-build %{buildroot}/usr/src/kernels/%{KERNELRELEASE}' |
| 74 | 73 | %endif |
| @@ -101,7 +100,6 @@ fi · 26 unmodified lines | ||
| 101 | 100 | %defattr (-, root, root) |
| 102 | 101 | /lib/modules/%{KERNELRELEASE} |
| 103 | 102 | %exclude /lib/modules/%{KERNELRELEASE}/build |
| 104 | −%exclude /lib/modules/%{KERNELRELEASE}/source | |
| 105 | 103 | /boot/* |
| 106 | 104 | |
| 107 | 105 | %files headers |
| @@ -113,5 +111,4 @@ fi · 5 unmodified lines | ||
| 113 | 111 | %defattr (-, root, root) |
| 114 | 112 | /usr/src/kernels/%{KERNELRELEASE} |
| 115 | 113 | /lib/modules/%{KERNELRELEASE}/build |
| 116 | −/lib/modules/%{KERNELRELEASE}/source | |
| 117 | 114 | %endif |
| @@ -29,9 +29,11 @@ config IMA · 28 unmodified lines | ||
| 29 | 29 | to learn more about IMA. |
| 30 | 30 | If unsure, say N. |
| 31 | 31 | |
| 32 | +if IMA | |
| 33 | + | |
| 32 | 34 | config IMA_KEXEC |
| 33 | 35 | bool "Enable carrying the IMA measurement list across a soft boot" |
| 34 | − depends on IMA && TCG_TPM && HAVE_IMA_KEXEC | |
| 36 | + depends on TCG_TPM && HAVE_IMA_KEXEC | |
| 35 | 37 | default n |
| 36 | 38 | help |
| 37 | 39 | TPM PCRs are only reset on a hard reboot. In order to validate |
| @@ -43,7 +45,6 @@ config IMA_KEXEC · 5 unmodified lines | ||
| 43 | 45 | |
| 44 | 46 | config IMA_MEASURE_PCR_IDX |
| 45 | 47 | int |
| 46 | − depends on IMA | |
| 47 | 48 | range 8 14 |
| 48 | 49 | default 10 |
| 49 | 50 | help |
| @@ -53,7 +54,7 @@ config IMA_MEASURE_PCR_IDX · 3 unmodified lines | ||
| 53 | 54 | |
| 54 | 55 | config IMA_LSM_RULES |
| 55 | 56 | bool |
| 56 | − depends on IMA && AUDIT && (SECURITY_SELINUX || SECURITY_SMACK || SECURITY_APPARMOR) | |
| 57 | + depends on AUDIT && (SECURITY_SELINUX || SECURITY_SMACK || SECURITY_APPARMOR) | |
| 57 | 58 | default y |
| 58 | 59 | help |
| 59 | 60 | Disabling this option will disregard LSM based policy rules. |
| @@ -61,7 +62,6 @@ config IMA_LSM_RULES · 1 unmodified line | ||
| 61 | 62 | choice |
| 62 | 63 | prompt "Default template" |
| 63 | 64 | default IMA_NG_TEMPLATE |
| 64 | − depends on IMA | |
| 65 | 65 | help |
| 66 | 66 | Select the default IMA measurement template. |
| 67 | 67 | |
| @@ -80,14 +80,12 @@ endchoice · 12 unmodified lines | ||
| 80 | 80 | |
| 81 | 81 | config IMA_DEFAULT_TEMPLATE |
| 82 | 82 | string |
| 83 | − depends on IMA | |
| 84 | 83 | default "ima-ng" if IMA_NG_TEMPLATE |
| 85 | 84 | default "ima-sig" if IMA_SIG_TEMPLATE |
| 86 | 85 | |
| 87 | 86 | choice |
| 88 | 87 | prompt "Default integrity hash algorithm" |
| 89 | 88 | default IMA_DEFAULT_HASH_SHA1 |
| 90 | − depends on IMA | |
| 91 | 89 | help |
| 92 | 90 | Select the default hash algorithm used for the measurement |
| 93 | 91 | list, integrity appraisal and audit log. The compiled default |
| @@ -117,7 +115,6 @@ endchoice · 23 unmodified lines | ||
| 117 | 115 | |
| 118 | 116 | config IMA_DEFAULT_HASH |
| 119 | 117 | string |
| 120 | − depends on IMA | |
| 121 | 118 | default "sha1" if IMA_DEFAULT_HASH_SHA1 |
| 122 | 119 | default "sha256" if IMA_DEFAULT_HASH_SHA256 |
| 123 | 120 | default "sha512" if IMA_DEFAULT_HASH_SHA512 |
| @@ -126,7 +123,6 @@ config IMA_DEFAULT_HASH · 2 unmodified lines | ||
| 126 | 123 | |
| 127 | 124 | config IMA_WRITE_POLICY |
| 128 | 125 | bool "Enable multiple writes to the IMA policy" |
| 129 | − depends on IMA | |
| 130 | 126 | default n |
| 131 | 127 | help |
| 132 | 128 | IMA policy can now be updated multiple times. The new rules get |
| @@ -137,7 +133,6 @@ config IMA_WRITE_POLICY · 4 unmodified lines | ||
| 137 | 133 | |
| 138 | 134 | config IMA_READ_POLICY |
| 139 | 135 | bool "Enable reading back the current IMA policy" |
| 140 | − depends on IMA | |
| 141 | 136 | default y if IMA_WRITE_POLICY |
| 142 | 137 | default n if !IMA_WRITE_POLICY |
| 143 | 138 | help |
| @@ -147,7 +142,6 @@ config IMA_READ_POLICY · 3 unmodified lines | ||
| 147 | 142 | |
| 148 | 143 | config IMA_APPRAISE |
| 149 | 144 | bool "Appraise integrity measurements" |
| 150 | − depends on IMA | |
| 151 | 145 | default n |
| 152 | 146 | help |
| 153 | 147 | This option enables local measurement integrity appraisal. |
| @@ -269,7 +263,7 @@ config IMA_KEYRINGS_PERMIT_SIGNED_BY_BUILTIN_OR_SECONDARY · 115 unmodified lines | ||
| 269 | 263 | config IMA_BLACKLIST_KEYRING |
| 270 | 264 | bool "Create IMA machine owner blacklist keyrings (EXPERIMENTAL)" |
| 271 | 265 | depends on SYSTEM_TRUSTED_KEYRING |
| 272 | − depends on IMA_TRUSTED_KEYRING | |
| 266 | + depends on INTEGRITY_TRUSTED_KEYRING | |
| 273 | 267 | default n |
| 274 | 268 | help |
| 275 | 269 | This option creates an IMA blacklist keyring, which contains all |
| @@ -279,7 +273,7 @@ config IMA_BLACKLIST_KEYRING · 3 unmodified lines | ||
| 279 | 273 | |
| 280 | 274 | config IMA_LOAD_X509 |
| 281 | 275 | bool "Load X509 certificate onto the '.ima' trusted keyring" |
| 282 | − depends on IMA_TRUSTED_KEYRING | |
| 276 | + depends on INTEGRITY_TRUSTED_KEYRING | |
| 283 | 277 | default n |
| 284 | 278 | help |
| 285 | 279 | File signature verification is based on the public keys |
| @@ -304,7 +298,6 @@ config IMA_APPRAISE_SIGNED_INIT · 18 unmodified lines | ||
| 304 | 298 | |
| 305 | 299 | config IMA_MEASURE_ASYMMETRIC_KEYS |
| 306 | 300 | bool |
| 307 | − depends on IMA | |
| 308 | 301 | depends on ASYMMETRIC_PUBLIC_KEY_SUBTYPE=y |
| 309 | 302 | default y |
| 310 | 303 | |
| @@ -323,7 +316,8 @@ config IMA_SECURE_AND_OR_TRUSTED_BOOT · 12 unmodified lines | ||
| 323 | 316 | |
| 324 | 317 | config IMA_DISABLE_HTABLE |
| 325 | 318 | bool "Disable htable to allow measurement of duplicate records" |
| 326 | − depends on IMA | |
| 327 | 319 | default n |
| 328 | 320 | help |
| 329 | 321 | This option disables htable to allow measurement of duplicate records. |
| 322 | + | |
| 323 | +endif | |
| @@ -57,6 +57,7 @@ · 56 unmodified lines | ||
| 57 | 57 | |
| 58 | 58 | #define MSR_IA32_PRED_CMD 0x00000049 /* Prediction Command */ |
| 59 | 59 | #define PRED_CMD_IBPB BIT(0) /* Indirect Branch Prediction Barrier */ |
| 60 | +#define PRED_CMD_SBPB BIT(7) /* Selective Branch Prediction Barrier */ | |
| 60 | 61 | |
| 61 | 62 | #define MSR_PPIN_CTL 0x0000004e |
| 62 | 63 | #define MSR_PPIN 0x0000004f |
| @@ -155,6 +156,15 @@ · 92 unmodified lines | ||
| 155 | 156 | * Not susceptible to Post-Barrier |
| 156 | 157 | * Return Stack Buffer Predictions. |
| 157 | 158 | */ |
| 159 | +#define ARCH_CAP_GDS_CTRL BIT(25) /* | |
| 160 | + * CPU is vulnerable to Gather | |
| 161 | + * Data Sampling (GDS) and | |
| 162 | + * has controls for mitigation. | |
| 163 | + */ | |
| 164 | +#define ARCH_CAP_GDS_NO BIT(26) /* | |
| 165 | + * CPU is not vulnerable to Gather | |
| 166 | + * Data Sampling (GDS). | |
| 167 | + */ | |
| 158 | 168 | |
| 159 | 169 | #define ARCH_CAP_XAPIC_DISABLE BIT(21) /* |
| 160 | 170 | * IA32_XAPIC_DISABLE_STATUS MSR |
| @@ -178,6 +188,8 @@ · 17 unmodified lines | ||
| 178 | 188 | #define RNGDS_MITG_DIS BIT(0) /* SRBDS support */ |
| 179 | 189 | #define RTM_ALLOW BIT(1) /* TSX development mode */ |
| 180 | 190 | #define FB_CLEAR_DIS BIT(3) /* CPU Fill buffer clear disable */ |
| 191 | +#define GDS_MITG_DIS BIT(4) /* Disable GDS mitigation */ | |
| 192 | +#define GDS_MITG_LOCKED BIT(5) /* GDS mitigation locked */ | |
| 181 | 193 | |
| 182 | 194 | #define MSR_IA32_SYSENTER_CS 0x00000174 |
| 183 | 195 | #define MSR_IA32_SYSENTER_ESP 0x00000175 |
| @@ -820,8 +820,11 @@ __SYSCALL(__NR_set_mempolicy_home_node, sys_set_mempolicy_home_node) · 819 unmodified lines | ||
| 820 | 820 | #define __NR_cachestat 451 |
| 821 | 821 | __SYSCALL(__NR_cachestat, sys_cachestat) |
| 822 | 822 | |
| 823 | +#define __NR_fchmodat2 452 | |
| 824 | +__SYSCALL(__NR_fchmodat2, sys_fchmodat2) | |
| 825 | + | |
| 823 | 826 | #undef __NR_syscalls |
| 824 | −#define __NR_syscalls 452 | |
| 827 | +#define __NR_syscalls 453 | |
| 825 | 828 | |
| 826 | 829 | /* |
| 827 | 830 | * 32 bit systems traditionally used different |
| @@ -673,8 +673,11 @@ struct drm_gem_open { · 672 unmodified lines | ||
| 673 | 673 | * Bitfield of supported PRIME sharing capabilities. See &DRM_PRIME_CAP_IMPORT |
| 674 | 674 | * and &DRM_PRIME_CAP_EXPORT. |
| 675 | 675 | * |
| 676 | − * PRIME buffers are exposed as dma-buf file descriptors. See | |
| 677 | − * Documentation/gpu/drm-mm.rst, section "PRIME Buffer Sharing". | |
| 676 | + * Starting from kernel version 6.6, both &DRM_PRIME_CAP_IMPORT and | |
| 677 | + * &DRM_PRIME_CAP_EXPORT are always advertised. | |
| 678 | + * | |
| 679 | + * PRIME buffers are exposed as dma-buf file descriptors. | |
| 680 | + * See :ref:`prime_buffer_sharing`. | |
| 678 | 681 | */ |
| 679 | 682 | #define DRM_CAP_PRIME 0x5 |
| 680 | 683 | /** |
| @@ -682,6 +685,8 @@ struct drm_gem_open { · 1 unmodified line | ||
| 682 | 685 | * |
| 683 | 686 | * If this bit is set in &DRM_CAP_PRIME, the driver supports importing PRIME |
| 684 | 687 | * buffers via the &DRM_IOCTL_PRIME_FD_TO_HANDLE ioctl. |
| 688 | + * | |
| 689 | + * Starting from kernel version 6.6, this bit is always set in &DRM_CAP_PRIME. | |
| 685 | 690 | */ |
| 686 | 691 | #define DRM_PRIME_CAP_IMPORT 0x1 |
| 687 | 692 | /** |
| @@ -689,6 +694,8 @@ struct drm_gem_open { · 1 unmodified line | ||
| 689 | 694 | * |
| 690 | 695 | * If this bit is set in &DRM_CAP_PRIME, the driver supports exporting PRIME |
| 691 | 696 | * buffers via the &DRM_IOCTL_PRIME_HANDLE_TO_FD ioctl. |
| 697 | + * | |
| 698 | + * Starting from kernel version 6.6, this bit is always set in &DRM_CAP_PRIME. | |
| 692 | 699 | */ |
| 693 | 700 | #define DRM_PRIME_CAP_EXPORT 0x2 |
| 694 | 701 | /** |
| @@ -756,15 +763,14 @@ struct drm_gem_open { · 61 unmodified lines | ||
| 756 | 763 | /** |
| 757 | 764 | * DRM_CAP_SYNCOBJ |
| 758 | 765 | * |
| 759 | − * If set to 1, the driver supports sync objects. See | |
| 760 | − * Documentation/gpu/drm-mm.rst, section "DRM Sync Objects". | |
| 766 | + * If set to 1, the driver supports sync objects. See :ref:`drm_sync_objects`. | |
| 761 | 767 | */ |
| 762 | 768 | #define DRM_CAP_SYNCOBJ 0x13 |
| 763 | 769 | /** |
| 764 | 770 | * DRM_CAP_SYNCOBJ_TIMELINE |
| 765 | 771 | * |
| 766 | 772 | * If set to 1, the driver supports timeline operations on sync objects. See |
| 767 | − * Documentation/gpu/drm-mm.rst, section "DRM Sync Objects". | |
| 773 | + * :ref:`drm_sync_objects`. | |
| 768 | 774 | */ |
| 769 | 775 | #define DRM_CAP_SYNCOBJ_TIMELINE 0x14 |
| 770 | 776 | |
| @@ -909,6 +915,27 @@ struct drm_syncobj_timeline_wait { · 138 unmodified lines | ||
| 909 | 915 | __u32 pad; |
| 910 | 916 | }; |
| 911 | 917 | |
| 918 | +/** | |
| 919 | + * struct drm_syncobj_eventfd | |
| 920 | + * @handle: syncobj handle. | |
| 921 | + * @flags: Zero to wait for the point to be signalled, or | |
| 922 | + * &DRM_SYNCOBJ_WAIT_FLAGS_WAIT_AVAILABLE to wait for a fence to be | |
| 923 | + * available for the point. | |
| 924 | + * @point: syncobj timeline point (set to zero for binary syncobjs). | |
| 925 | + * @fd: Existing eventfd to sent events to. | |
| 926 | + * @pad: Must be zero. | |
| 927 | + * | |
| 928 | + * Register an eventfd to be signalled by a syncobj. The eventfd counter will | |
| 929 | + * be incremented by one. | |
| 930 | + */ | |
| 931 | +struct drm_syncobj_eventfd { | |
| 932 | + __u32 handle; | |
| 933 | + __u32 flags; | |
| 934 | + __u64 point; | |
| 935 | + __s32 fd; | |
| 936 | + __u32 pad; | |
| 937 | +}; | |
| 938 | + | |
| 912 | 939 | |
| 913 | 940 | struct drm_syncobj_array { |
| 914 | 941 | __u64 handles; |
| @@ -1169,6 +1196,8 @@ extern "C" { · 254 unmodified lines | ||
| 1169 | 1196 | */ |
| 1170 | 1197 | #define DRM_IOCTL_MODE_GETFB2 DRM_IOWR(0xCE, struct drm_mode_fb_cmd2) |
| 1171 | 1198 | |
| 1199 | +#define DRM_IOCTL_SYNCOBJ_EVENTFD DRM_IOWR(0xCF, struct drm_syncobj_eventfd) | |
| 1200 | + | |
| 1172 | 1201 | /* |
| 1173 | 1202 | * Device specific ioctls should only be in their respective headers |
| 1174 | 1203 | * The device specific ioctl range is from 0x40 to 0x9f. |
| @@ -1180,25 +1209,50 @@ extern "C" { · 5 unmodified lines | ||
| 1180 | 1209 | #define DRM_COMMAND_BASE 0x40 |
| 1181 | 1210 | #define DRM_COMMAND_END 0xA0 |
| 1182 | 1211 | |
| 1183 | −/* | |
| 1184 | − * Header for events written back to userspace on the drm fd. The | |
| 1185 | − * type defines the type of event, the length specifies the total | |
| 1186 | − * length of the event (including the header), and user_data is | |
| 1187 | − * typically a 64 bit value passed with the ioctl that triggered the | |
| 1188 | − * event. A read on the drm fd will always only return complete | |
| 1189 | − * events, that is, if for example the read buffer is 100 bytes, and | |
| 1190 | − * there are two 64 byte events pending, only one will be returned. | |
| 1212 | +/** | |
| 1213 | + * struct drm_event - Header for DRM events | |
| 1214 | + * @type: event type. | |
| 1215 | + * @length: total number of payload bytes (including header). | |
| 1191 | 1216 | * |
| 1192 | − * Event types 0 - 0x7fffffff are generic drm events, 0x80000000 and | |
| 1193 | − * up are chipset specific. | |
| 1217 | + * This struct is a header for events written back to user-space on the DRM FD. | |
| 1218 | + * A read on the DRM FD will always only return complete events: e.g. if the | |
| 1219 | + * read buffer is 100 bytes large and there are two 64 byte events pending, | |
| 1220 | + * only one will be returned. | |
| 1221 | + * | |
| 1222 | + * Event types 0 - 0x7fffffff are generic DRM events, 0x80000000 and | |
| 1223 | + * up are chipset specific. Generic DRM events include &DRM_EVENT_VBLANK, | |
| 1224 | + * &DRM_EVENT_FLIP_COMPLETE and &DRM_EVENT_CRTC_SEQUENCE. | |
| 1194 | 1225 | */ |
| 1195 | 1226 | struct drm_event { |
| 1196 | 1227 | __u32 type; |
| 1197 | 1228 | __u32 length; |
| 1198 | 1229 | }; |
| 1199 | 1230 | |
| 1231 | +/** | |
| 1232 | + * DRM_EVENT_VBLANK - vertical blanking event | |
| 1233 | + * | |
| 1234 | + * This event is sent in response to &DRM_IOCTL_WAIT_VBLANK with the | |
| 1235 | + * &_DRM_VBLANK_EVENT flag set. | |
| 1236 | + * | |
| 1237 | + * The event payload is a struct drm_event_vblank. | |
| 1238 | + */ | |
| 1200 | 1239 | #define DRM_EVENT_VBLANK 0x01 |
| 1240 | +/** | |
| 1241 | + * DRM_EVENT_FLIP_COMPLETE - page-flip completion event | |
| 1242 | + * | |
| 1243 | + * This event is sent in response to an atomic commit or legacy page-flip with | |
| 1244 | + * the &DRM_MODE_PAGE_FLIP_EVENT flag set. | |
| 1245 | + * | |
| 1246 | + * The event payload is a struct drm_event_vblank. | |
| 1247 | + */ | |
| 1201 | 1248 | #define DRM_EVENT_FLIP_COMPLETE 0x02 |
| 1249 | +/** | |
| 1250 | + * DRM_EVENT_CRTC_SEQUENCE - CRTC sequence event | |
| 1251 | + * | |
| 1252 | + * This event is sent in response to &DRM_IOCTL_CRTC_QUEUE_SEQUENCE. | |
| 1253 | + * | |
| 1254 | + * The event payload is a struct drm_event_crtc_sequence. | |
| 1255 | + */ | |
| 1202 | 1256 | #define DRM_EVENT_CRTC_SEQUENCE 0x03 |
| 1203 | 1257 | |
| 1204 | 1258 | struct drm_event_vblank { |
| @@ -0,0 +1,157 @@ | ||
| 1 | +/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ | |
| 2 | +#ifndef _UAPI_LINUX_SECCOMP_H | |
| 3 | +#define _UAPI_LINUX_SECCOMP_H | |
| 4 | + | |
| 5 | +#include <linux/compiler.h> | |
| 6 | +#include <linux/types.h> | |
| 7 | + | |
| 8 | + | |
| 9 | +/* Valid values for seccomp.mode and prctl(PR_SET_SECCOMP, <mode>) */ | |
| 10 | +#define SECCOMP_MODE_DISABLED 0 /* seccomp is not in use. */ | |
| 11 | +#define SECCOMP_MODE_STRICT 1 /* uses hard-coded filter. */ | |
| 12 | +#define SECCOMP_MODE_FILTER 2 /* uses user-supplied filter. */ | |
| 13 | + | |
| 14 | +/* Valid operations for seccomp syscall. */ | |
| 15 | +#define SECCOMP_SET_MODE_STRICT 0 | |
| 16 | +#define SECCOMP_SET_MODE_FILTER 1 | |
| 17 | +#define SECCOMP_GET_ACTION_AVAIL 2 | |
| 18 | +#define SECCOMP_GET_NOTIF_SIZES 3 | |
| 19 | + | |
| 20 | +/* Valid flags for SECCOMP_SET_MODE_FILTER */ | |
| 21 | +#define SECCOMP_FILTER_FLAG_TSYNC (1UL << 0) | |
| 22 | +#define SECCOMP_FILTER_FLAG_LOG (1UL << 1) | |
| 23 | +#define SECCOMP_FILTER_FLAG_SPEC_ALLOW (1UL << 2) | |
| 24 | +#define SECCOMP_FILTER_FLAG_NEW_LISTENER (1UL << 3) | |
| 25 | +#define SECCOMP_FILTER_FLAG_TSYNC_ESRCH (1UL << 4) | |
| 26 | +/* Received notifications wait in killable state (only respond to fatal signals) */ | |
| 27 | +#define SECCOMP_FILTER_FLAG_WAIT_KILLABLE_RECV (1UL << 5) | |
| 28 | + | |
| 29 | +/* | |
| 30 | + * All BPF programs must return a 32-bit value. | |
| 31 | + * The bottom 16-bits are for optional return data. | |
| 32 | + * The upper 16-bits are ordered from least permissive values to most, | |
| 33 | + * as a signed value (so 0x8000000 is negative). | |
| 34 | + * | |
| 35 | + * The ordering ensures that a min_t() over composed return values always | |
| 36 | + * selects the least permissive choice. | |
| 37 | + */ | |
| 38 | +#define SECCOMP_RET_KILL_PROCESS 0x80000000U /* kill the process */ | |
| 39 | +#define SECCOMP_RET_KILL_THREAD 0x00000000U /* kill the thread */ | |
| 40 | +#define SECCOMP_RET_KILL SECCOMP_RET_KILL_THREAD | |
| 41 | +#define SECCOMP_RET_TRAP 0x00030000U /* disallow and force a SIGSYS */ | |
| 42 | +#define SECCOMP_RET_ERRNO 0x00050000U /* returns an errno */ | |
| 43 | +#define SECCOMP_RET_USER_NOTIF 0x7fc00000U /* notifies userspace */ | |
| 44 | +#define SECCOMP_RET_TRACE 0x7ff00000U /* pass to a tracer or disallow */ | |
| 45 | +#define SECCOMP_RET_LOG 0x7ffc0000U /* allow after logging */ | |
| 46 | +#define SECCOMP_RET_ALLOW 0x7fff0000U /* allow */ | |
| 47 | + | |
| 48 | +/* Masks for the return value sections. */ | |
| 49 | +#define SECCOMP_RET_ACTION_FULL 0xffff0000U | |
| 50 | +#define SECCOMP_RET_ACTION 0x7fff0000U | |
| 51 | +#define SECCOMP_RET_DATA 0x0000ffffU | |
| 52 | + | |
| 53 | +/** | |
| 54 | + * struct seccomp_data - the format the BPF program executes over. | |
| 55 | + * @nr: the system call number | |
| 56 | + * @arch: indicates system call convention as an AUDIT_ARCH_* value | |
| 57 | + * as defined in <linux/audit.h>. | |
| 58 | + * @instruction_pointer: at the time of the system call. | |
| 59 | + * @args: up to 6 system call arguments always stored as 64-bit values | |
| 60 | + * regardless of the architecture. | |
| 61 | + */ | |
| 62 | +struct seccomp_data { | |
| 63 | + int nr; | |
| 64 | + __u32 arch; | |
| 65 | + __u64 instruction_pointer; | |
| 66 | + __u64 args[6]; | |
| 67 | +}; | |
| 68 | + | |
| 69 | +struct seccomp_notif_sizes { | |
| 70 | + __u16 seccomp_notif; | |
| 71 | + __u16 seccomp_notif_resp; | |
| 72 | + __u16 seccomp_data; | |
| 73 | +}; | |
| 74 | + | |
| 75 | +struct seccomp_notif { | |
| 76 | + __u64 id; | |
| 77 | + __u32 pid; | |
| 78 | + __u32 flags; | |
| 79 | + struct seccomp_data data; | |
| 80 | +}; | |
| 81 | + | |
| 82 | +/* | |
| 83 | + * Valid flags for struct seccomp_notif_resp | |
| 84 | + * | |
| 85 | + * Note, the SECCOMP_USER_NOTIF_FLAG_CONTINUE flag must be used with caution! | |
| 86 | + * If set by the process supervising the syscalls of another process the | |
| 87 | + * syscall will continue. This is problematic because of an inherent TOCTOU. | |
| 88 | + * An attacker can exploit the time while the supervised process is waiting on | |
| 89 | + * a response from the supervising process to rewrite syscall arguments which | |
| 90 | + * are passed as pointers of the intercepted syscall. | |
| 91 | + * It should be absolutely clear that this means that the seccomp notifier | |
| 92 | + * _cannot_ be used to implement a security policy! It should only ever be used | |
| 93 | + * in scenarios where a more privileged process supervises the syscalls of a | |
| 94 | + * lesser privileged process to get around kernel-enforced security | |
| 95 | + * restrictions when the privileged process deems this safe. In other words, | |
| 96 | + * in order to continue a syscall the supervising process should be sure that | |
| 97 | + * another security mechanism or the kernel itself will sufficiently block | |
| 98 | + * syscalls if arguments are rewritten to something unsafe. | |
| 99 | + * | |
| 100 | + * Similar precautions should be applied when stacking SECCOMP_RET_USER_NOTIF | |
| 101 | + * or SECCOMP_RET_TRACE. For SECCOMP_RET_USER_NOTIF filters acting on the | |
| 102 | + * same syscall, the most recently added filter takes precedence. This means | |
| 103 | + * that the new SECCOMP_RET_USER_NOTIF filter can override any | |
| 104 | + * SECCOMP_IOCTL_NOTIF_SEND from earlier filters, essentially allowing all | |
| 105 | + * such filtered syscalls to be executed by sending the response | |
| 106 | + * SECCOMP_USER_NOTIF_FLAG_CONTINUE. Note that SECCOMP_RET_TRACE can equally | |
| 107 | + * be overriden by SECCOMP_USER_NOTIF_FLAG_CONTINUE. | |
| 108 | + */ | |
| 109 | +#define SECCOMP_USER_NOTIF_FLAG_CONTINUE (1UL << 0) | |
| 110 | + | |
| 111 | +struct seccomp_notif_resp { | |
| 112 | + __u64 id; | |
| 113 | + __s64 val; | |
| 114 | + __s32 error; | |
| 115 | + __u32 flags; | |
| 116 | +}; | |
| 117 | + | |
| 118 | +#define SECCOMP_USER_NOTIF_FD_SYNC_WAKE_UP (1UL << 0) | |
| 119 | + | |
| 120 | +/* valid flags for seccomp_notif_addfd */ | |
| 121 | +#define SECCOMP_ADDFD_FLAG_SETFD (1UL << 0) /* Specify remote fd */ | |
| 122 | +#define SECCOMP_ADDFD_FLAG_SEND (1UL << 1) /* Addfd and return it, atomically */ | |
| 123 | + | |
| 124 | +/** | |
| 125 | + * struct seccomp_notif_addfd | |
| 126 | + * @id: The ID of the seccomp notification | |
| 127 | + * @flags: SECCOMP_ADDFD_FLAG_* | |
| 128 | + * @srcfd: The local fd number | |
| 129 | + * @newfd: Optional remote FD number if SETFD option is set, otherwise 0. | |
| 130 | + * @newfd_flags: The O_* flags the remote FD should have applied | |
| 131 | + */ | |
| 132 | +struct seccomp_notif_addfd { | |
| 133 | + __u64 id; | |
| 134 | + __u32 flags; | |
| 135 | + __u32 srcfd; | |
| 136 | + __u32 newfd; | |
| 137 | + __u32 newfd_flags; | |
| 138 | +}; | |
| 139 | + | |
| 140 | +#define SECCOMP_IOC_MAGIC '!' | |
| 141 | +#define SECCOMP_IO(nr) _IO(SECCOMP_IOC_MAGIC, nr) | |
| 142 | +#define SECCOMP_IOR(nr, type) _IOR(SECCOMP_IOC_MAGIC, nr, type) | |
| 143 | +#define SECCOMP_IOW(nr, type) _IOW(SECCOMP_IOC_MAGIC, nr, type) | |
| 144 | +#define SECCOMP_IOWR(nr, type) _IOWR(SECCOMP_IOC_MAGIC, nr, type) | |
| 145 | + | |
| 146 | +/* Flags for seccomp notification fd ioctl. */ | |
| 147 | +#define SECCOMP_IOCTL_NOTIF_RECV SECCOMP_IOWR(0, struct seccomp_notif) | |
| 148 | +#define SECCOMP_IOCTL_NOTIF_SEND SECCOMP_IOWR(1, \ | |
| 149 | + struct seccomp_notif_resp) | |
| 150 | +#define SECCOMP_IOCTL_NOTIF_ID_VALID SECCOMP_IOW(2, __u64) | |
| 151 | +/* On success, the return value is the remote process's added fd number */ | |
| 152 | +#define SECCOMP_IOCTL_NOTIF_ADDFD SECCOMP_IOW(3, \ | |
| 153 | + struct seccomp_notif_addfd) | |
| 154 | + | |
| 155 | +#define SECCOMP_IOCTL_NOTIF_SET_FLAGS SECCOMP_IOW(4, __u64) | |
| 156 | + | |
| 157 | +#endif /* _UAPI_LINUX_SECCOMP_H */ | |
| @@ -366,3 +366,4 @@ · 365 unmodified lines | ||
| 366 | 366 | 449 n64 futex_waitv sys_futex_waitv |
| 367 | 367 | 450 common set_mempolicy_home_node sys_set_mempolicy_home_node |
| 368 | 368 | 451 n64 cachestat sys_cachestat |
| 369 | +452 n64 fchmodat2 sys_fchmodat2 | |
| @@ -538,3 +538,4 @@ · 537 unmodified lines | ||
| 538 | 538 | 449 common futex_waitv sys_futex_waitv |
| 539 | 539 | 450 nospu set_mempolicy_home_node sys_set_mempolicy_home_node |
| 540 | 540 | 451 common cachestat sys_cachestat |
| 541 | +452 common fchmodat2 sys_fchmodat2 | |
| @@ -454,3 +454,4 @@ · 453 unmodified lines | ||
| 454 | 454 | 449 common futex_waitv sys_futex_waitv sys_futex_waitv |
| 455 | 455 | 450 common set_mempolicy_home_node sys_set_mempolicy_home_node sys_set_mempolicy_home_node |
| 456 | 456 | 451 common cachestat sys_cachestat sys_cachestat |
| 457 | +452 common fchmodat2 sys_fchmodat2 sys_fchmodat2 | |
| @@ -373,6 +373,8 @@ · 372 unmodified lines | ||
| 373 | 373 | 449 common futex_waitv sys_futex_waitv |
| 374 | 374 | 450 common set_mempolicy_home_node sys_set_mempolicy_home_node |
| 375 | 375 | 451 common cachestat sys_cachestat |
| 376 | +452 common fchmodat2 sys_fchmodat2 | |
| 377 | +453 64 map_shadow_stack sys_map_shadow_stack | |
| 376 | 378 | |
| 377 | 379 | # |
| 378 | 380 | # Due to a historical design error, certain syscalls are numbered differently |
| @@ -9,7 +9,7 @@ · 8 unmodified lines | ||
| 9 | 9 | #include <sys/syscall.h> |
| 10 | 10 | #include <sys/ioctl.h> |
| 11 | 11 | #include <linux/time64.h> |
| 12 | −#include <linux/seccomp.h> | |
| 12 | +#include <uapi/linux/seccomp.h> | |
| 13 | 13 | #include <sys/prctl.h> |
| 14 | 14 | |
| 15 | 15 | #include <unistd.h> |
| @@ -21,6 +21,7 @@ FILES=( · 20 unmodified lines | ||
| 21 | 21 | "include/uapi/linux/perf_event.h" |
| 22 | 22 | "include/uapi/linux/prctl.h" |
| 23 | 23 | "include/uapi/linux/sched.h" |
| 24 | + "include/uapi/linux/seccomp.h" | |
| 24 | 25 | "include/uapi/linux/stat.h" |
| 25 | 26 | "include/uapi/linux/usbdevice_fs.h" |
| 26 | 27 | "include/uapi/linux/vhost.h" |
| @@ -991,7 +991,7 @@ const struct pmu_events_table *perf_pmu__find_events_table(struct perf_pmu *pmu) · 990 unmodified lines | ||
| 991 | 991 | } |
| 992 | 992 | } |
| 993 | 993 | free(cpuid); |
| 994 | − if (!pmu) | |
| 994 | + if (!pmu || !table) | |
| 995 | 995 | return table; |
| 996 | 996 | |
| 997 | 997 | for (i = 0; i < table->num_pmus; i++) { |
| @@ -413,10 +413,10 @@ def has_event(event: Event) -> Function: · 412 unmodified lines | ||
| 413 | 413 | # pylint: disable=invalid-name |
| 414 | 414 | return Function('has_event', event) |
| 415 | 415 | |
| 416 | −def strcmp_cpuid_str(event: str) -> Function: | |
| 416 | +def strcmp_cpuid_str(cpuid: Event) -> Function: | |
| 417 | 417 | # pylint: disable=redefined-builtin |
| 418 | 418 | # pylint: disable=invalid-name |
| 419 | − return Function('strcmp_cpuid_str', event) | |
| 419 | + return Function('strcmp_cpuid_str', cpuid) | |
| 420 | 420 | |
| 421 | 421 | class Metric: |
| 422 | 422 | """An individual metric that will specifiable on the perf command line.""" |
| @@ -1,508 +0,0 @@ | ||
| 1 | −// SPDX-License-Identifier: GPL-2.0 | |
| 2 | −/* | |
| 3 | − * bpf-prologue.c | |
| 4 | − * | |
| 5 | − * Copyright (C) 2015 He Kuang <hekuang@huawei.com> | |
| 6 | − * Copyright (C) 2015 Wang Nan <wangnan0@huawei.com> | |
| 7 | − * Copyright (C) 2015 Huawei Inc. | |
| 8 | − */ | |
| 9 | − | |
| 10 | −#include <bpf/libbpf.h> | |
| 11 | −#include "debug.h" | |
| 12 | −#include "bpf-loader.h" | |
| 13 | −#include "bpf-prologue.h" | |
| 14 | −#include "probe-finder.h" | |
| 15 | −#include <errno.h> | |
| 16 | −#include <stdlib.h> | |
| 17 | −#include <dwarf-regs.h> | |
| 18 | −#include <linux/filter.h> | |
| 19 | − | |
| 20 | −#define BPF_REG_SIZE 8 | |
| 21 | − | |
| 22 | −#define JMP_TO_ERROR_CODE -1 | |
| 23 | −#define JMP_TO_SUCCESS_CODE -2 | |
| 24 | −#define JMP_TO_USER_CODE -3 | |
| 25 | − | |
| 26 | −struct bpf_insn_pos { | |
| 27 | − struct bpf_insn *begin; | |
| 28 | − struct bpf_insn *end; | |
| 29 | − struct bpf_insn *pos; | |
| 30 | −}; | |
| 31 | − | |
| 32 | −static inline int | |
| 33 | −pos_get_cnt(struct bpf_insn_pos *pos) | |
| 34 | −{ | |
| 35 | − return pos->pos - pos->begin; | |
| 36 | −} | |
| 37 | − | |
| 38 | −static int | |
| 39 | −append_insn(struct bpf_insn new_insn, struct bpf_insn_pos *pos) | |
| 40 | −{ | |
| 41 | − if (!pos->pos) | |
| 42 | − return -BPF_LOADER_ERRNO__PROLOGUE2BIG; | |
| 43 | − | |
| 44 | − if (pos->pos + 1 >= pos->end) { | |
| 45 | − pr_err("bpf prologue: prologue too long\n"); | |
| 46 | − pos->pos = NULL; | |
| 47 | − return -BPF_LOADER_ERRNO__PROLOGUE2BIG; | |
| 48 | − } | |
| 49 | − | |
| 50 | − *(pos->pos)++ = new_insn; | |
| 51 | − return 0; | |
| 52 | −} | |
| 53 | − | |
| 54 | −static int | |
| 55 | −check_pos(struct bpf_insn_pos *pos) | |
| 56 | −{ | |
| 57 | − if (!pos->pos || pos->pos >= pos->end) | |
| 58 | − return -BPF_LOADER_ERRNO__PROLOGUE2BIG; | |
| 59 | − return 0; | |
| 60 | −} | |
| 61 | − | |
| 62 | −/* | |
| 63 | − * Convert type string (u8/u16/u32/u64/s8/s16/s32/s64 ..., see | |
| 64 | − * Documentation/trace/kprobetrace.rst) to size field of BPF_LDX_MEM | |
| 65 | − * instruction (BPF_{B,H,W,DW}). | |
| 66 | − */ | |
| 67 | −static int | |
| 68 | −argtype_to_ldx_size(const char *type) | |
| 69 | −{ | |
| 70 | − int arg_size = type ? atoi(&type[1]) : 64; | |
| 71 | − | |
| 72 | − switch (arg_size) { | |
| 73 | − case 8: | |
| 74 | − return BPF_B; | |
| 75 | − case 16: | |
| 76 | − return BPF_H; | |
| 77 | − case 32: | |
| 78 | − return BPF_W; | |
| 79 | − case 64: | |
| 80 | − default: | |
| 81 | − return BPF_DW; | |
| 82 | − } | |
| 83 | −} | |
| 84 | − | |
| 85 | −static const char * | |
| 86 | −insn_sz_to_str(int insn_sz) | |
| 87 | −{ | |
| 88 | − switch (insn_sz) { | |
| 89 | − case BPF_B: | |
| 90 | − return "BPF_B"; | |
| 91 | − case BPF_H: | |
| 92 | − return "BPF_H"; | |
| 93 | − case BPF_W: | |
| 94 | − return "BPF_W"; | |
| 95 | − case BPF_DW: | |
| 96 | − return "BPF_DW"; | |
| 97 | − default: | |
| 98 | − return "UNKNOWN"; | |
| 99 | − } | |
| 100 | −} | |
| 101 | − | |
| 102 | −/* Give it a shorter name */ | |
| 103 | −#define ins(i, p) append_insn((i), (p)) | |
| 104 | − | |
| 105 | −/* | |
| 106 | − * Give a register name (in 'reg'), generate instruction to | |
| 107 | − * load register into an eBPF register rd: | |
| 108 | − * 'ldd target_reg, offset(ctx_reg)', where: | |
| 109 | − * ctx_reg is pre initialized to pointer of 'struct pt_regs'. | |
| 110 | − */ | |
| 111 | −static int | |
| 112 | −gen_ldx_reg_from_ctx(struct bpf_insn_pos *pos, int ctx_reg, | |
| 113 | − const char *reg, int target_reg) | |
| 114 | −{ | |
| 115 | − int offset = regs_query_register_offset(reg); | |
| 116 | − | |
| 117 | − if (offset < 0) { | |
| 118 | − pr_err("bpf: prologue: failed to get register %s\n", | |
| 119 | − reg); | |
| 120 | − return offset; | |
| 121 | − } | |
| 122 | − ins(BPF_LDX_MEM(BPF_DW, target_reg, ctx_reg, offset), pos); | |
| 123 | − | |
| 124 | − return check_pos(pos); | |
| 125 | −} | |
| 126 | − | |
| 127 | −/* | |
| 128 | − * Generate a BPF_FUNC_probe_read function call. | |
| 129 | − * | |
| 130 | − * src_base_addr_reg is a register holding base address, | |
| 131 | − * dst_addr_reg is a register holding dest address (on stack), | |
| 132 | − * result is: | |
| 133 | − * | |
| 134 | − * *[dst_addr_reg] = *([src_base_addr_reg] + offset) | |
| 135 | − * | |
| 136 | − * Arguments of BPF_FUNC_probe_read: | |
| 137 | − * ARG1: ptr to stack (dest) | |
| 138 | − * ARG2: size (8) | |
| 139 | − * ARG3: unsafe ptr (src) | |
| 140 | − */ | |
| 141 | −static int | |
| 142 | −gen_read_mem(struct bpf_insn_pos *pos, | |
| 143 | − int src_base_addr_reg, | |
| 144 | − int dst_addr_reg, | |
| 145 | − long offset, | |
| 146 | − int probeid) | |
| 147 | −{ | |
| 148 | − /* mov arg3, src_base_addr_reg */ | |
| 149 | − if (src_base_addr_reg != BPF_REG_ARG3) | |
| 150 | − ins(BPF_MOV64_REG(BPF_REG_ARG3, src_base_addr_reg), pos); | |
| 151 | − /* add arg3, #offset */ | |
| 152 | − if (offset) | |
| 153 | − ins(BPF_ALU64_IMM(BPF_ADD, BPF_REG_ARG3, offset), pos); | |
| 154 | − | |
| 155 | − /* mov arg2, #reg_size */ | |
| 156 | − ins(BPF_ALU64_IMM(BPF_MOV, BPF_REG_ARG2, BPF_REG_SIZE), pos); | |
| 157 | − | |
| 158 | − /* mov arg1, dst_addr_reg */ | |
| 159 | − if (dst_addr_reg != BPF_REG_ARG1) | |
| 160 | − ins(BPF_MOV64_REG(BPF_REG_ARG1, dst_addr_reg), pos); | |
| 161 | − | |
| 162 | − /* Call probe_read */ | |
| 163 | − ins(BPF_EMIT_CALL(probeid), pos); | |
| 164 | − /* | |
| 165 | − * Error processing: if read fail, goto error code, | |
| 166 | − * will be relocated. Target should be the start of | |
| 167 | − * error processing code. | |
| 168 | − */ | |
| 169 | − ins(BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 0, JMP_TO_ERROR_CODE), | |
| 170 | − pos); | |
| 171 | − | |
| 172 | − return check_pos(pos); | |
| 173 | −} | |
| 174 | − | |
| 175 | −/* | |
| 176 | − * Each arg should be bare register. Fetch and save them into argument | |
| 177 | − * registers (r3 - r5). | |
| 178 | − * | |
| 179 | − * BPF_REG_1 should have been initialized with pointer to | |
| 180 | − * 'struct pt_regs'. | |
| 181 | − */ | |
| 182 | −static int | |
| 183 | −gen_prologue_fastpath(struct bpf_insn_pos *pos, | |
| 184 | − struct probe_trace_arg *args, int nargs) | |
| 185 | −{ | |
| 186 | − int i, err = 0; | |
| 187 | − | |
| 188 | − for (i = 0; i < nargs; i++) { | |
| 189 | − err = gen_ldx_reg_from_ctx(pos, BPF_REG_1, args[i].value, | |
| 190 | − BPF_PROLOGUE_START_ARG_REG + i); | |
| 191 | − if (err) | |
| 192 | − goto errout; | |
| 193 | − } | |
| 194 | − | |
| 195 | − return check_pos(pos); | |
| 196 | −errout: | |
| 197 | − return err; | |
| 198 | −} | |
| 199 | − | |
| 200 | −/* | |
| 201 | − * Slow path: | |
| 202 | − * At least one argument has the form of 'offset($rx)'. | |
| 203 | − * | |
| 204 | − * Following code first stores them into stack, then loads all of then | |
| 205 | − * to r2 - r5. | |
| 206 | − * Before final loading, the final result should be: | |
| 207 | − * | |
| 208 | − * low address | |
| 209 | − * BPF_REG_FP - 24 ARG3 | |
| 210 | − * BPF_REG_FP - 16 ARG2 | |
| 211 | − * BPF_REG_FP - 8 ARG1 | |
| 212 | − * BPF_REG_FP | |
| 213 | − * high address | |
| 214 | − * | |
| 215 | − * For each argument (described as: offn(...off2(off1(reg)))), | |
| 216 | − * generates following code: | |
| 217 | − * | |
| 218 | − * r7 <- fp | |
| 219 | − * r7 <- r7 - stack_offset // Ideal code should initialize r7 using | |
| 220 | − * // fp before generating args. However, | |
| 221 | − * // eBPF won't regard r7 as stack pointer | |
| 222 | − * // if it is generated by minus 8 from | |
| 223 | − * // another stack pointer except fp. | |
| 224 | − * // This is why we have to set r7 | |
| 225 | − * // to fp for each variable. | |
| 226 | − * r3 <- value of 'reg'-> generated using gen_ldx_reg_from_ctx() | |
| 227 | − * (r7) <- r3 // skip following instructions for bare reg | |
| 228 | − * r3 <- r3 + off1 . // skip if off1 == 0 | |
| 229 | − * r2 <- 8 \ | |
| 230 | − * r1 <- r7 |-> generated by gen_read_mem() | |
| 231 | − * call probe_read / | |
| 232 | − * jnei r0, 0, err ./ | |
| 233 | − * r3 <- (r7) | |
| 234 | − * r3 <- r3 + off2 . // skip if off2 == 0 | |
| 235 | − * r2 <- 8 \ // r2 may be broken by probe_read, so set again | |
| 236 | − * r1 <- r7 |-> generated by gen_read_mem() | |
| 237 | − * call probe_read / | |
| 238 | − * jnei r0, 0, err ./ | |
| 239 | − * ... | |
| 240 | − */ | |
| 241 | −static int | |
| 242 | −gen_prologue_slowpath(struct bpf_insn_pos *pos, | |
| 243 | − struct probe_trace_arg *args, int nargs) | |
| 244 | −{ | |
| 245 | − int err, i, probeid; | |
| 246 | − | |
| 247 | − for (i = 0; i < nargs; i++) { | |
| 248 | − struct probe_trace_arg *arg = &args[i]; | |
| 249 | − const char *reg = arg->value; | |
| 250 | − struct probe_trace_arg_ref *ref = NULL; | |
| 251 | − int stack_offset = (i + 1) * -8; | |
| 252 | − | |
| 253 | − pr_debug("prologue: fetch arg %d, base reg is %s\n", | |
| 254 | − i, reg); | |
| 255 | − | |
| 256 | − /* value of base register is stored into ARG3 */ | |
| 257 | − err = gen_ldx_reg_from_ctx(pos, BPF_REG_CTX, reg, | |
| 258 | − BPF_REG_ARG3); | |
| 259 | − if (err) { | |
| 260 | − pr_err("prologue: failed to get offset of register %s\n", | |
| 261 | − reg); | |
| 262 | − goto errout; | |
| 263 | − } | |
| 264 | − | |
| 265 | − /* Make r7 the stack pointer. */ | |
| 266 | − ins(BPF_MOV64_REG(BPF_REG_7, BPF_REG_FP), pos); | |
| 267 | − /* r7 += -8 */ | |
| 268 | − ins(BPF_ALU64_IMM(BPF_ADD, BPF_REG_7, stack_offset), pos); | |
| 269 | − /* | |
| 270 | − * Store r3 (base register) onto stack | |
| 271 | − * Ensure fp[offset] is set. | |
| 272 | − * fp is the only valid base register when storing | |
| 273 | − * into stack. We are not allowed to use r7 as base | |
| 274 | − * register here. | |
| 275 | − */ | |
| 276 | − ins(BPF_STX_MEM(BPF_DW, BPF_REG_FP, BPF_REG_ARG3, | |
| 277 | − stack_offset), pos); | |
| 278 | − | |
| 279 | − ref = arg->ref; | |
| 280 | − probeid = BPF_FUNC_probe_read_kernel; | |
| 281 | − while (ref) { | |
| 282 | − pr_debug("prologue: arg %d: offset %ld\n", | |
| 283 | − i, ref->offset); | |
| 284 | − | |
| 285 | − if (ref->user_access) | |
| 286 | − probeid = BPF_FUNC_probe_read_user; | |
| 287 | − | |
| 288 | − err = gen_read_mem(pos, BPF_REG_3, BPF_REG_7, | |
| 289 | − ref->offset, probeid); | |
| 290 | − if (err) { | |
| 291 | − pr_err("prologue: failed to generate probe_read function call\n"); | |
| 292 | − goto errout; | |
| 293 | − } | |
| 294 | − | |
| 295 | − ref = ref->next; | |
| 296 | − /* | |
| 297 | − * Load previous result into ARG3. Use | |
| 298 | − * BPF_REG_FP instead of r7 because verifier | |
| 299 | − * allows FP based addressing only. | |
| 300 | − */ | |
| 301 | − if (ref) | |
| 302 | − ins(BPF_LDX_MEM(BPF_DW, BPF_REG_ARG3, | |
| 303 | − BPF_REG_FP, stack_offset), pos); | |
| 304 | − } | |
| 305 | − } | |
| 306 | − | |
| 307 | − /* Final pass: read to registers */ | |
| 308 | − for (i = 0; i < nargs; i++) { | |
| 309 | − int insn_sz = (args[i].ref) ? argtype_to_ldx_size(args[i].type) : BPF_DW; | |
| 310 | − | |
| 311 | − pr_debug("prologue: load arg %d, insn_sz is %s\n", | |
| 312 | − i, insn_sz_to_str(insn_sz)); | |
| 313 | − ins(BPF_LDX_MEM(insn_sz, BPF_PROLOGUE_START_ARG_REG + i, | |
| 314 | − BPF_REG_FP, -BPF_REG_SIZE * (i + 1)), pos); | |
| 315 | − } | |
| 316 | − | |
| 317 | − ins(BPF_JMP_IMM(BPF_JA, BPF_REG_0, 0, JMP_TO_SUCCESS_CODE), pos); | |
| 318 | − | |
| 319 | − return check_pos(pos); | |
| 320 | −errout: | |
| 321 | − return err; | |
| 322 | −} | |
| 323 | − | |
| 324 | −static int | |
| 325 | −prologue_relocate(struct bpf_insn_pos *pos, struct bpf_insn *error_code, | |
| 326 | − struct bpf_insn *success_code, struct bpf_insn *user_code) | |
| 327 | −{ | |
| 328 | − struct bpf_insn *insn; | |
| 329 | − | |
| 330 | − if (check_pos(pos)) | |
| 331 | − return -BPF_LOADER_ERRNO__PROLOGUE2BIG; | |
| 332 | − | |
| 333 | − for (insn = pos->begin; insn < pos->pos; insn++) { | |
| 334 | − struct bpf_insn *target; | |
| 335 | − u8 class = BPF_CLASS(insn->code); | |
| 336 | − u8 opcode; | |
| 337 | − | |
| 338 | − if (class != BPF_JMP) | |
| 339 | − continue; | |
| 340 | − opcode = BPF_OP(insn->code); | |
| 341 | − if (opcode == BPF_CALL) | |
| 342 | − continue; | |
| 343 | − | |
| 344 | − switch (insn->off) { | |
| 345 | − case JMP_TO_ERROR_CODE: | |
| 346 | − target = error_code; | |
| 347 | − break; | |
| 348 | − case JMP_TO_SUCCESS_CODE: | |
| 349 | − target = success_code; | |
| 350 | − break; | |
| 351 | − case JMP_TO_USER_CODE: | |
| 352 | − target = user_code; | |
| 353 | − break; | |
| 354 | − default: | |
| 355 | − pr_err("bpf prologue: internal error: relocation failed\n"); | |
| 356 | − return -BPF_LOADER_ERRNO__PROLOGUE; | |
| 357 | − } | |
| 358 | − | |
| 359 | − insn->off = target - (insn + 1); | |
| 360 | − } | |
| 361 | − return 0; | |
| 362 | −} | |
| 363 | − | |
| 364 | −int bpf__gen_prologue(struct probe_trace_arg *args, int nargs, | |
| 365 | − struct bpf_insn *new_prog, size_t *new_cnt, | |
| 366 | − size_t cnt_space) | |
| 367 | −{ | |
| 368 | − struct bpf_insn *success_code = NULL; | |
| 369 | − struct bpf_insn *error_code = NULL; | |
| 370 | − struct bpf_insn *user_code = NULL; | |
| 371 | − struct bpf_insn_pos pos; | |
| 372 | − bool fastpath = true; | |
| 373 | − int err = 0, i; | |
| 374 | − | |
| 375 | − if (!new_prog || !new_cnt) | |
| 376 | − return -EINVAL; | |
| 377 | − | |
| 378 | − if (cnt_space > BPF_MAXINSNS) | |
| 379 | − cnt_space = BPF_MAXINSNS; | |
| 380 | − | |
| 381 | − pos.begin = new_prog; | |
| 382 | − pos.end = new_prog + cnt_space; | |
| 383 | − pos.pos = new_prog; | |
| 384 | − | |
| 385 | − if (!nargs) { | |
| 386 | − ins(BPF_ALU64_IMM(BPF_MOV, BPF_PROLOGUE_FETCH_RESULT_REG, 0), | |
| 387 | − &pos); | |
| 388 | − | |
| 389 | − if (check_pos(&pos)) | |
| 390 | − goto errout; | |
| 391 | − | |
| 392 | − *new_cnt = pos_get_cnt(&pos); | |
| 393 | − return 0; | |
| 394 | − } | |
| 395 | − | |
| 396 | − if (nargs > BPF_PROLOGUE_MAX_ARGS) { | |
| 397 | − pr_warning("bpf: prologue: %d arguments are dropped\n", | |
| 398 | − nargs - BPF_PROLOGUE_MAX_ARGS); | |
| 399 | − nargs = BPF_PROLOGUE_MAX_ARGS; | |
| 400 | − } | |
| 401 | − | |
| 402 | − /* First pass: validation */ | |
| 403 | − for (i = 0; i < nargs; i++) { | |
| 404 | − struct probe_trace_arg_ref *ref = args[i].ref; | |
| 405 | − | |
| 406 | − if (args[i].value[0] == '@') { | |
| 407 | − /* TODO: fetch global variable */ | |
| 408 | − pr_err("bpf: prologue: global %s%+ld not support\n", | |
| 409 | − args[i].value, ref ? ref->offset : 0); | |
| 410 | − return -ENOTSUP; | |
| 411 | − } | |
| 412 | − | |
| 413 | − while (ref) { | |
| 414 | − /* fastpath is true if all args has ref == NULL */ | |
| 415 | − fastpath = false; | |
| 416 | − | |
| 417 | − /* | |
| 418 | − * Instruction encodes immediate value using | |
| 419 | − * s32, ref->offset is long. On systems which | |
| 420 | − * can't fill long in s32, refuse to process if | |
| 421 | − * ref->offset too large (or small). | |
| 422 | − */ | |
| 423 | −#ifdef __LP64__ | |
| 424 | −#define OFFSET_MAX ((1LL << 31) - 1) | |
| 425 | −#define OFFSET_MIN ((1LL << 31) * -1) | |
| 426 | − if (ref->offset > OFFSET_MAX || | |
| 427 | − ref->offset < OFFSET_MIN) { | |
| 428 | − pr_err("bpf: prologue: offset out of bound: %ld\n", | |
| 429 | − ref->offset); | |
| 430 | − return -BPF_LOADER_ERRNO__PROLOGUEOOB; | |
| 431 | − } | |
| 432 | −#endif | |
| 433 | − ref = ref->next; | |
| 434 | − } | |
| 435 | − } | |
| 436 | − pr_debug("prologue: pass validation\n"); | |
| 437 | − | |
| 438 | − if (fastpath) { | |
| 439 | − /* If all variables are registers... */ | |
| 440 | − pr_debug("prologue: fast path\n"); | |
| 441 | − err = gen_prologue_fastpath(&pos, args, nargs); | |
| 442 | − if (err) | |
| 443 | − goto errout; | |
| 444 | − } else { | |
| 445 | − pr_debug("prologue: slow path\n"); | |
| 446 | − | |
| 447 | − /* Initialization: move ctx to a callee saved register. */ | |
| 448 | − ins(BPF_MOV64_REG(BPF_REG_CTX, BPF_REG_ARG1), &pos); | |
| 449 | − | |
| 450 | − err = gen_prologue_slowpath(&pos, args, nargs); | |
| 451 | − if (err) | |
| 452 | − goto errout; | |
| 453 | − /* | |
| 454 | − * start of ERROR_CODE (only slow pass needs error code) | |
| 455 | − * mov r2 <- 1 // r2 is error number | |
| 456 | − * mov r3 <- 0 // r3, r4... should be touched or | |
| 457 | − * // verifier would complain | |
| 458 | − * mov r4 <- 0 | |
| 459 | − * ... | |
| 460 | − * goto usercode | |
| 461 | − */ | |
| 462 | − error_code = pos.pos; | |
| 463 | − ins(BPF_ALU64_IMM(BPF_MOV, BPF_PROLOGUE_FETCH_RESULT_REG, 1), | |
| 464 | − &pos); | |
| 465 | − | |
| 466 | − for (i = 0; i < nargs; i++) | |
| 467 | − ins(BPF_ALU64_IMM(BPF_MOV, | |
| 468 | − BPF_PROLOGUE_START_ARG_REG + i, | |
| 469 | − 0), | |
| 470 | − &pos); | |
| 471 | − ins(BPF_JMP_IMM(BPF_JA, BPF_REG_0, 0, JMP_TO_USER_CODE), | |
| 472 | − &pos); | |
| 473 | − } | |
| 474 | − | |
| 475 | − /* | |
| 476 | − * start of SUCCESS_CODE: | |
| 477 | − * mov r2 <- 0 | |
| 478 | − * goto usercode // skip | |
| 479 | − */ | |
| 480 | − success_code = pos.pos; | |
| 481 | − ins(BPF_ALU64_IMM(BPF_MOV, BPF_PROLOGUE_FETCH_RESULT_REG, 0), &pos); | |
| 482 | − | |
| 483 | − /* | |
| 484 | − * start of USER_CODE: | |
| 485 | − * Restore ctx to r1 | |
| 486 | − */ | |
| 487 | − user_code = pos.pos; | |
| 488 | − if (!fastpath) { | |
| 489 | − /* | |
| 490 | − * Only slow path needs restoring of ctx. In fast path, | |
| 491 | − * register are loaded directly from r1. | |
| 492 | − */ | |
| 493 | − ins(BPF_MOV64_REG(BPF_REG_ARG1, BPF_REG_CTX), &pos); | |
| 494 | − err = prologue_relocate(&pos, error_code, success_code, | |
| 495 | − user_code); | |
| 496 | − if (err) | |
| 497 | − goto errout; | |
| 498 | − } | |
| 499 | − | |
| 500 | − err = check_pos(&pos); | |
| 501 | − if (err) | |
| 502 | − goto errout; | |
| 503 | − | |
| 504 | − *new_cnt = pos_get_cnt(&pos); | |
| 505 | − return 0; | |
| 506 | −errout: | |
| 507 | − return err; | |
| 508 | −} | |
| @@ -23,7 +23,9 @@ · 22 unmodified lines | ||
| 23 | 23 | #define MAX_CPUS 4096 |
| 24 | 24 | |
| 25 | 25 | // FIXME: These should come from system headers |
| 26 | +#ifndef bool | |
| 26 | 27 | typedef char bool; |
| 28 | +#endif | |
| 27 | 29 | typedef int pid_t; |
| 28 | 30 | typedef long long int __s64; |
| 29 | 31 | typedef __s64 time64_t; |
| @@ -80,16 +80,6 @@ struct hashmap { · 79 unmodified lines | ||
| 80 | 80 | size_t sz; |
| 81 | 81 | }; |
| 82 | 82 | |
| 83 | −#define HASHMAP_INIT(hash_fn, equal_fn, ctx) { \ | |
| 84 | − .hash_fn = (hash_fn), \ | |
| 85 | − .equal_fn = (equal_fn), \ | |
| 86 | − .ctx = (ctx), \ | |
| 87 | − .buckets = NULL, \ | |
| 88 | − .cap = 0, \ | |
| 89 | − .cap_bits = 0, \ | |
| 90 | − .sz = 0, \ | |
| 91 | −} | |
| 92 | − | |
| 93 | 83 | void hashmap__init(struct hashmap *map, hashmap_hash_fn hash_fn, |
| 94 | 84 | hashmap_equal_fn equal_fn, void *ctx); |
| 95 | 85 | struct hashmap *hashmap__new(hashmap_hash_fn hash_fn, |
| @@ -520,7 +520,7 @@ static int perf_pmu__new_alias(struct perf_pmu *pmu, const char *name, · 519 unmodified lines | ||
| 520 | 520 | pmu_name = pe->pmu; |
| 521 | 521 | } |
| 522 | 522 | |
| 523 | − alias = malloc(sizeof(*alias)); | |
| 523 | + alias = zalloc(sizeof(*alias)); | |
| 524 | 524 | if (!alias) |
| 525 | 525 | return -ENOMEM; |
| 526 | 526 | |
| @@ -92,7 +92,7 @@ endif · 91 unmodified lines | ||
| 92 | 92 | TARGETS += tmpfs |
| 93 | 93 | TARGETS += tpm2 |
| 94 | 94 | TARGETS += tty |
| 95 | −TARGETS += uevents | |
| 95 | +TARGETS += uevent | |
| 96 | 96 | TARGETS += user |
| 97 | 97 | TARGETS += user_events |
| 98 | 98 | TARGETS += vDSO |
| @@ -185,6 +185,8 @@ static void test_cubic(void) · 184 unmodified lines | ||
| 185 | 185 | |
| 186 | 186 | do_test("bpf_cubic", NULL); |
| 187 | 187 | |
| 188 | + ASSERT_EQ(cubic_skel->bss->bpf_cubic_acked_called, 1, "pkts_acked called"); | |
| 189 | + | |
| 188 | 190 | bpf_link__destroy(link); |
| 189 | 191 | bpf_cubic__destroy(cubic_skel); |
| 190 | 192 | } |
| @@ -475,6 +475,55 @@ out: · 474 unmodified lines | ||
| 475 | 475 | test_sockmap_drop_prog__destroy(drop); |
| 476 | 476 | } |
| 477 | 477 | |
| 478 | +static void test_sockmap_skb_verdict_peek(void) | |
| 479 | +{ | |
| 480 | + int err, map, verdict, s, c1, p1, zero = 0, sent, recvd, avail; | |
| 481 | + struct test_sockmap_pass_prog *pass; | |
| 482 | + char snd[256] = "0123456789"; | |
| 483 | + char rcv[256] = "0"; | |
| 484 | + | |
| 485 | + pass = test_sockmap_pass_prog__open_and_load(); | |
| 486 | + if (!ASSERT_OK_PTR(pass, "open_and_load")) | |
| 487 | + return; | |
| 488 | + verdict = bpf_program__fd(pass->progs.prog_skb_verdict); | |
| 489 | + map = bpf_map__fd(pass->maps.sock_map_rx); | |
| 490 | + | |
| 491 | + err = bpf_prog_attach(verdict, map, BPF_SK_SKB_STREAM_VERDICT, 0); | |
| 492 | + if (!ASSERT_OK(err, "bpf_prog_attach")) | |
| 493 | + goto out; | |
| 494 | + | |
| 495 | + s = socket_loopback(AF_INET, SOCK_STREAM); | |
| 496 | + if (!ASSERT_GT(s, -1, "socket_loopback(s)")) | |
| 497 | + goto out; | |
| 498 | + | |
| 499 | + err = create_pair(s, AF_INET, SOCK_STREAM, &c1, &p1); | |
| 500 | + if (!ASSERT_OK(err, "create_pairs(s)")) | |
| 501 | + goto out; | |
| 502 | + | |
| 503 | + err = bpf_map_update_elem(map, &zero, &c1, BPF_NOEXIST); | |
| 504 | + if (!ASSERT_OK(err, "bpf_map_update_elem(c1)")) | |
| 505 | + goto out_close; | |
| 506 | + | |
| 507 | + sent = xsend(p1, snd, sizeof(snd), 0); | |
| 508 | + ASSERT_EQ(sent, sizeof(snd), "xsend(p1)"); | |
| 509 | + recvd = recv(c1, rcv, sizeof(rcv), MSG_PEEK); | |
| 510 | + ASSERT_EQ(recvd, sizeof(rcv), "recv(c1)"); | |
| 511 | + err = ioctl(c1, FIONREAD, &avail); | |
| 512 | + ASSERT_OK(err, "ioctl(FIONREAD) error"); | |
| 513 | + ASSERT_EQ(avail, sizeof(snd), "after peek ioctl(FIONREAD)"); | |
| 514 | + recvd = recv(c1, rcv, sizeof(rcv), 0); | |
| 515 | + ASSERT_EQ(recvd, sizeof(rcv), "recv(p0)"); | |
| 516 | + err = ioctl(c1, FIONREAD, &avail); | |
| 517 | + ASSERT_OK(err, "ioctl(FIONREAD) error"); | |
| 518 | + ASSERT_EQ(avail, 0, "after read ioctl(FIONREAD)"); | |
| 519 | + | |
| 520 | +out_close: | |
| 521 | + close(c1); | |
| 522 | + close(p1); | |
| 523 | +out: | |
| 524 | + test_sockmap_pass_prog__destroy(pass); | |
| 525 | +} | |
| 526 | + | |
| 478 | 527 | void test_sockmap_basic(void) |
| 479 | 528 | { |
| 480 | 529 | if (test__start_subtest("sockmap create_update_free")) |
| @@ -515,4 +564,6 @@ void test_sockmap_basic(void) · 34 unmodified lines | ||
| 515 | 564 | test_sockmap_skb_verdict_fionread(true); |
| 516 | 565 | if (test__start_subtest("sockmap skb_verdict fionread on drop")) |
| 517 | 566 | test_sockmap_skb_verdict_fionread(false); |
| 567 | + if (test__start_subtest("sockmap skb_verdict msg_f_peek")) | |
| 568 | + test_sockmap_skb_verdict_peek(); | |
| 518 | 569 | } |
| @@ -2378,3 +2378,87 @@ void serial_test_tc_opts_chain_mixed(void) · 2377 unmodified lines | ||
| 2378 | 2378 | test_tc_chain_mixed(BPF_TCX_INGRESS); |
| 2379 | 2379 | test_tc_chain_mixed(BPF_TCX_EGRESS); |
| 2380 | 2380 | } |
| 2381 | + | |
| 2382 | +static int generate_dummy_prog(void) | |
| 2383 | +{ | |
| 2384 | + const struct bpf_insn prog_insns[] = { | |
| 2385 | + BPF_MOV64_IMM(BPF_REG_0, 0), | |
| 2386 | + BPF_EXIT_INSN(), | |
| 2387 | + }; | |
| 2388 | + const size_t prog_insn_cnt = sizeof(prog_insns) / sizeof(struct bpf_insn); | |
| 2389 | + LIBBPF_OPTS(bpf_prog_load_opts, opts); | |
| 2390 | + const size_t log_buf_sz = 256; | |
| 2391 | + char *log_buf; | |
| 2392 | + int fd = -1; | |
| 2393 | + | |
| 2394 | + log_buf = malloc(log_buf_sz); | |
| 2395 | + if (!ASSERT_OK_PTR(log_buf, "log_buf_alloc")) | |
| 2396 | + return fd; | |
| 2397 | + opts.log_buf = log_buf; | |
| 2398 | + opts.log_size = log_buf_sz; | |
| 2399 | + | |
| 2400 | + log_buf[0] = '\0'; | |
| 2401 | + opts.log_level = 0; | |
| 2402 | + fd = bpf_prog_load(BPF_PROG_TYPE_SCHED_CLS, "tcx_prog", "GPL", | |
| 2403 | + prog_insns, prog_insn_cnt, &opts); | |
| 2404 | + ASSERT_STREQ(log_buf, "", "log_0"); | |
| 2405 | + ASSERT_GE(fd, 0, "prog_fd"); | |
| 2406 | + free(log_buf); | |
| 2407 | + return fd; | |
| 2408 | +} | |
| 2409 | + | |
| 2410 | +static void test_tc_opts_max_target(int target, int flags, bool relative) | |
| 2411 | +{ | |
| 2412 | + int err, ifindex, i, prog_fd, last_fd = -1; | |
| 2413 | + LIBBPF_OPTS(bpf_prog_attach_opts, opta); | |
| 2414 | + const int max_progs = 63; | |
| 2415 | + | |
| 2416 | + ASSERT_OK(system("ip link add dev tcx_opts1 type veth peer name tcx_opts2"), "add veth"); | |
| 2417 | + ifindex = if_nametoindex("tcx_opts1"); | |
| 2418 | + ASSERT_NEQ(ifindex, 0, "non_zero_ifindex"); | |
| 2419 | + | |
| 2420 | + assert_mprog_count_ifindex(ifindex, target, 0); | |
| 2421 | + | |
| 2422 | + for (i = 0; i < max_progs; i++) { | |
| 2423 | + prog_fd = generate_dummy_prog(); | |
| 2424 | + if (!ASSERT_GE(prog_fd, 0, "dummy_prog")) | |
| 2425 | + goto cleanup; | |
| 2426 | + err = bpf_prog_attach_opts(prog_fd, ifindex, target, &opta); | |
| 2427 | + if (!ASSERT_EQ(err, 0, "prog_attach")) | |
| 2428 | + goto cleanup; | |
| 2429 | + assert_mprog_count_ifindex(ifindex, target, i + 1); | |
| 2430 | + if (i == max_progs - 1 && relative) | |
| 2431 | + last_fd = prog_fd; | |
| 2432 | + else | |
| 2433 | + close(prog_fd); | |
| 2434 | + } | |
| 2435 | + | |
| 2436 | + prog_fd = generate_dummy_prog(); | |
| 2437 | + if (!ASSERT_GE(prog_fd, 0, "dummy_prog")) | |
| 2438 | + goto cleanup; | |
| 2439 | + opta.flags = flags; | |
| 2440 | + if (last_fd > 0) | |
| 2441 | + opta.relative_fd = last_fd; | |
| 2442 | + err = bpf_prog_attach_opts(prog_fd, ifindex, target, &opta); | |
| 2443 | + ASSERT_EQ(err, -ERANGE, "prog_64_attach"); | |
| 2444 | + assert_mprog_count_ifindex(ifindex, target, max_progs); | |
| 2445 | + close(prog_fd); | |
| 2446 | +cleanup: | |
| 2447 | + if (last_fd > 0) | |
| 2448 | + close(last_fd); | |
| 2449 | + ASSERT_OK(system("ip link del dev tcx_opts1"), "del veth"); | |
| 2450 | + ASSERT_EQ(if_nametoindex("tcx_opts1"), 0, "dev1_removed"); | |
| 2451 | + ASSERT_EQ(if_nametoindex("tcx_opts2"), 0, "dev2_removed"); | |
| 2452 | +} | |
| 2453 | + | |
| 2454 | +void serial_test_tc_opts_max(void) | |
| 2455 | +{ | |
| 2456 | + test_tc_opts_max_target(BPF_TCX_INGRESS, 0, false); | |
| 2457 | + test_tc_opts_max_target(BPF_TCX_EGRESS, 0, false); | |
| 2458 | + | |
| 2459 | + test_tc_opts_max_target(BPF_TCX_INGRESS, BPF_F_BEFORE, false); | |
| 2460 | + test_tc_opts_max_target(BPF_TCX_EGRESS, BPF_F_BEFORE, true); | |
| 2461 | + | |
| 2462 | + test_tc_opts_max_target(BPF_TCX_INGRESS, BPF_F_AFTER, true); | |
| 2463 | + test_tc_opts_max_target(BPF_TCX_EGRESS, BPF_F_AFTER, false); | |
| 2464 | +} | |
| @@ -490,6 +490,8 @@ static __always_inline void hystart_update(struct sock *sk, __u32 delay) · 489 unmodified lines | ||
| 490 | 490 | } |
| 491 | 491 | } |
| 492 | 492 | |
| 493 | +int bpf_cubic_acked_called = 0; | |
| 494 | + | |
| 493 | 495 | void BPF_STRUCT_OPS(bpf_cubic_acked, struct sock *sk, |
| 494 | 496 | const struct ack_sample *sample) |
| 495 | 497 | { |
| @@ -497,6 +499,7 @@ void BPF_STRUCT_OPS(bpf_cubic_acked, struct sock *sk, · 1 unmodified line | ||
| 497 | 499 | struct bictcp *ca = inet_csk_ca(sk); |
| 498 | 500 | __u32 delay; |
| 499 | 501 | |
| 502 | + bpf_cubic_acked_called = 1; | |
| 500 | 503 | /* Some calls are for duplicates without timetamps */ |
| 501 | 504 | if (sample->rtt_us < 0) |
| 502 | 505 | return; |
| @@ -1,6 +1,6 @@ | ||
| 1 | 1 | # SPDX-License-Identifier: GPL-2.0-or-later |
| 2 | 2 | |
| 3 | −CFLAGS += -Wall -O2 -g -fsanitize=address -fsanitize=undefined $(KHDR_INCLUDES) | |
| 3 | +CFLAGS += -Wall -O2 -g -fsanitize=address -fsanitize=undefined -static-libasan $(KHDR_INCLUDES) | |
| 4 | 4 | TEST_GEN_PROGS := fchmodat2_test |
| 5 | 5 | |
| 6 | 6 | include ../lib.mk |
| @@ -387,7 +387,7 @@ char *strdup_printf(const char *fmt, ...) · 386 unmodified lines | ||
| 387 | 387 | char *str; |
| 388 | 388 | |
| 389 | 389 | va_start(ap, fmt); |
| 390 | − vasprintf(&str, fmt, ap); | |
| 390 | + TEST_ASSERT(vasprintf(&str, fmt, ap) >= 0, "vasprintf() failed"); | |
| 391 | 391 | va_end(ap); |
| 392 | 392 | |
| 393 | 393 | return str; |
| @@ -12,19 +12,37 @@ · 11 unmodified lines | ||
| 12 | 12 | |
| 13 | 13 | #define REG_MASK (KVM_REG_ARCH_MASK | KVM_REG_SIZE_MASK) |
| 14 | 14 | |
| 15 | +static bool isa_ext_cant_disable[KVM_RISCV_ISA_EXT_MAX]; | |
| 16 | + | |
| 15 | 17 | bool filter_reg(__u64 reg) |
| 16 | 18 | { |
| 19 | + switch (reg & ~REG_MASK) { | |
| 17 | 20 | /* |
| 18 | − * Some ISA extensions are optional and not present on all host, | |
| 19 | − * but they can't be disabled through ISA_EXT registers when present. | |
| 20 | − * So, to make life easy, just filtering out these kind of registers. | |
| 21 | + * Same set of ISA_EXT registers are not present on all host because | |
| 22 | + * ISA_EXT registers are visible to the KVM user space based on the | |
| 23 | + * ISA extensions available on the host. Also, disabling an ISA | |
| 24 | + * extension using corresponding ISA_EXT register does not affect | |
| 25 | + * the visibility of the ISA_EXT register itself. | |
| 26 | + * | |
| 27 | + * Based on above, we should filter-out all ISA_EXT registers. | |
| 21 | 28 | */ |
| 22 | − switch (reg & ~REG_MASK) { | |
| 29 | + case KVM_REG_RISCV_ISA_EXT | KVM_RISCV_ISA_EXT_A: | |
| 30 | + case KVM_REG_RISCV_ISA_EXT | KVM_RISCV_ISA_EXT_C: | |
| 31 | + case KVM_REG_RISCV_ISA_EXT | KVM_RISCV_ISA_EXT_D: | |
| 32 | + case KVM_REG_RISCV_ISA_EXT | KVM_RISCV_ISA_EXT_F: | |
| 33 | + case KVM_REG_RISCV_ISA_EXT | KVM_RISCV_ISA_EXT_H: | |
| 34 | + case KVM_REG_RISCV_ISA_EXT | KVM_RISCV_ISA_EXT_I: | |
| 35 | + case KVM_REG_RISCV_ISA_EXT | KVM_RISCV_ISA_EXT_M: | |
| 36 | + case KVM_REG_RISCV_ISA_EXT | KVM_RISCV_ISA_EXT_SVPBMT: | |
| 23 | 37 | case KVM_REG_RISCV_ISA_EXT | KVM_RISCV_ISA_EXT_SSTC: |
| 24 | 38 | case KVM_REG_RISCV_ISA_EXT | KVM_RISCV_ISA_EXT_SVINVAL: |
| 25 | 39 | case KVM_REG_RISCV_ISA_EXT | KVM_RISCV_ISA_EXT_ZIHINTPAUSE: |
| 40 | + case KVM_REG_RISCV_ISA_EXT | KVM_RISCV_ISA_EXT_ZICBOM: | |
| 41 | + case KVM_REG_RISCV_ISA_EXT | KVM_RISCV_ISA_EXT_ZICBOZ: | |
| 26 | 42 | case KVM_REG_RISCV_ISA_EXT | KVM_RISCV_ISA_EXT_ZBB: |
| 27 | 43 | case KVM_REG_RISCV_ISA_EXT | KVM_RISCV_ISA_EXT_SSAIA: |
| 44 | + case KVM_REG_RISCV_ISA_EXT | KVM_RISCV_ISA_EXT_V: | |
| 45 | + case KVM_REG_RISCV_ISA_EXT | KVM_RISCV_ISA_EXT_SVNAPOT: | |
| 28 | 46 | case KVM_REG_RISCV_ISA_EXT | KVM_RISCV_ISA_EXT_ZBA: |
| 29 | 47 | case KVM_REG_RISCV_ISA_EXT | KVM_RISCV_ISA_EXT_ZBS: |
| 30 | 48 | case KVM_REG_RISCV_ISA_EXT | KVM_RISCV_ISA_EXT_ZICNTR: |
| @@ -32,6 +50,15 @@ bool filter_reg(__u64 reg) · 1 unmodified line | ||
| 32 | 50 | case KVM_REG_RISCV_ISA_EXT | KVM_RISCV_ISA_EXT_ZIFENCEI: |
| 33 | 51 | case KVM_REG_RISCV_ISA_EXT | KVM_RISCV_ISA_EXT_ZIHPM: |
| 34 | 52 | return true; |
| 53 | + /* AIA registers are always available when Ssaia can't be disabled */ | |
| 54 | + case KVM_REG_RISCV_CSR | KVM_REG_RISCV_CSR_AIA | KVM_REG_RISCV_CSR_AIA_REG(siselect): | |
| 55 | + case KVM_REG_RISCV_CSR | KVM_REG_RISCV_CSR_AIA | KVM_REG_RISCV_CSR_AIA_REG(iprio1): | |
| 56 | + case KVM_REG_RISCV_CSR | KVM_REG_RISCV_CSR_AIA | KVM_REG_RISCV_CSR_AIA_REG(iprio2): | |
| 57 | + case KVM_REG_RISCV_CSR | KVM_REG_RISCV_CSR_AIA | KVM_REG_RISCV_CSR_AIA_REG(sieh): | |
| 58 | + case KVM_REG_RISCV_CSR | KVM_REG_RISCV_CSR_AIA | KVM_REG_RISCV_CSR_AIA_REG(siph): | |
| 59 | + case KVM_REG_RISCV_CSR | KVM_REG_RISCV_CSR_AIA | KVM_REG_RISCV_CSR_AIA_REG(iprio1h): | |
| 60 | + case KVM_REG_RISCV_CSR | KVM_REG_RISCV_CSR_AIA | KVM_REG_RISCV_CSR_AIA_REG(iprio2h): | |
| 61 | + return isa_ext_cant_disable[KVM_RISCV_ISA_EXT_SSAIA]; | |
| 35 | 62 | default: |
| 36 | 63 | break; |
| 37 | 64 | } |
| @@ -50,24 +77,27 @@ static inline bool vcpu_has_ext(struct kvm_vcpu *vcpu, int ext) · 12 unmodified lines | ||
| 50 | 77 | unsigned long value; |
| 51 | 78 | |
| 52 | 79 | ret = __vcpu_get_reg(vcpu, RISCV_ISA_EXT_REG(ext), &value); |
| 53 | − if (ret) { | |
| 54 | − printf("Failed to get ext %d", ext); | |
| 55 | − return false; | |
| 56 | − } | |
| 57 | − | |
| 58 | − return !!value; | |
| 80 | + return (ret) ? false : !!value; | |
| 59 | 81 | } |
| 60 | 82 | |
| 61 | 83 | void finalize_vcpu(struct kvm_vcpu *vcpu, struct vcpu_reg_list *c) |
| 62 | 84 | { |
| 85 | + unsigned long isa_ext_state[KVM_RISCV_ISA_EXT_MAX] = { 0 }; | |
| 63 | 86 | struct vcpu_reg_sublist *s; |
| 87 | + int rc; | |
| 88 | + | |
| 89 | + for (int i = 0; i < KVM_RISCV_ISA_EXT_MAX; i++) | |
| 90 | + __vcpu_get_reg(vcpu, RISCV_ISA_EXT_REG(i), &isa_ext_state[i]); | |
| 64 | 91 | |
| 65 | 92 | /* |
| 66 | 93 | * Disable all extensions which were enabled by default |
| 67 | 94 | * if they were available in the risc-v host. |
| 68 | 95 | */ |
| 69 | − for (int i = 0; i < KVM_RISCV_ISA_EXT_MAX; i++) | |
| 70 | − __vcpu_set_reg(vcpu, RISCV_ISA_EXT_REG(i), 0); | |
| 96 | + for (int i = 0; i < KVM_RISCV_ISA_EXT_MAX; i++) { | |
| 97 | + rc = __vcpu_set_reg(vcpu, RISCV_ISA_EXT_REG(i), 0); | |
| 98 | + if (rc && isa_ext_state[i]) | |
| 99 | + isa_ext_cant_disable[i] = true; | |
| 100 | + } | |
| 71 | 101 | |
| 72 | 102 | for_each_sublist(c, s) { |
| 73 | 103 | if (!s->feature) |
| @@ -506,10 +536,6 @@ static __u64 base_regs[] = { · 432 unmodified lines | ||
| 506 | 536 | KVM_REG_RISCV | KVM_REG_SIZE_U64 | KVM_REG_RISCV_TIMER | KVM_REG_RISCV_TIMER_REG(time), |
| 507 | 537 | KVM_REG_RISCV | KVM_REG_SIZE_U64 | KVM_REG_RISCV_TIMER | KVM_REG_RISCV_TIMER_REG(compare), |
| 508 | 538 | KVM_REG_RISCV | KVM_REG_SIZE_U64 | KVM_REG_RISCV_TIMER | KVM_REG_RISCV_TIMER_REG(state), |
| 509 | − KVM_REG_RISCV | KVM_REG_SIZE_ULONG | KVM_REG_RISCV_ISA_EXT | KVM_RISCV_ISA_EXT_A, | |
| 510 | − KVM_REG_RISCV | KVM_REG_SIZE_ULONG | KVM_REG_RISCV_ISA_EXT | KVM_RISCV_ISA_EXT_C, | |
| 511 | − KVM_REG_RISCV | KVM_REG_SIZE_ULONG | KVM_REG_RISCV_ISA_EXT | KVM_RISCV_ISA_EXT_I, | |
| 512 | − KVM_REG_RISCV | KVM_REG_SIZE_ULONG | KVM_REG_RISCV_ISA_EXT | KVM_RISCV_ISA_EXT_M, | |
| 513 | 539 | KVM_REG_RISCV | KVM_REG_SIZE_ULONG | KVM_REG_RISCV_SBI_EXT | KVM_REG_RISCV_SBI_SINGLE | KVM_RISCV_SBI_EXT_V01, |
| 514 | 540 | KVM_REG_RISCV | KVM_REG_SIZE_ULONG | KVM_REG_RISCV_SBI_EXT | KVM_REG_RISCV_SBI_SINGLE | KVM_RISCV_SBI_EXT_TIME, |
| 515 | 541 | KVM_REG_RISCV | KVM_REG_SIZE_ULONG | KVM_REG_RISCV_SBI_EXT | KVM_REG_RISCV_SBI_SINGLE | KVM_RISCV_SBI_EXT_IPI, |
| @@ -25,7 +25,7 @@ if [[ "$1" == "-cgroup-v2" ]]; then · 24 unmodified lines | ||
| 25 | 25 | fi |
| 26 | 26 | |
| 27 | 27 | if [[ $cgroup2 ]]; then |
| 28 | − cgroup_path=$(mount -t cgroup2 | head -1 | awk -e '{print $3}') | |
| 28 | + cgroup_path=$(mount -t cgroup2 | head -1 | awk '{print $3}') | |
| 29 | 29 | if [[ -z "$cgroup_path" ]]; then |
| 30 | 30 | cgroup_path=/dev/cgroup/memory |
| 31 | 31 | mount -t cgroup2 none $cgroup_path |
| @@ -33,7 +33,7 @@ if [[ $cgroup2 ]]; then · 1 unmodified line | ||
| 33 | 33 | fi |
| 34 | 34 | echo "+hugetlb" >$cgroup_path/cgroup.subtree_control |
| 35 | 35 | else |
| 36 | − cgroup_path=$(mount -t cgroup | grep ",hugetlb" | awk -e '{print $3}') | |
| 36 | + cgroup_path=$(mount -t cgroup | grep ",hugetlb" | awk '{print $3}') | |
| 37 | 37 | if [[ -z "$cgroup_path" ]]; then |
| 38 | 38 | cgroup_path=/dev/cgroup/memory |
| 39 | 39 | mount -t cgroup memory,hugetlb $cgroup_path |
| @@ -20,7 +20,7 @@ fi · 19 unmodified lines | ||
| 20 | 20 | |
| 21 | 21 | |
| 22 | 22 | if [[ $cgroup2 ]]; then |
| 23 | − CGROUP_ROOT=$(mount -t cgroup2 | head -1 | awk -e '{print $3}') | |
| 23 | + CGROUP_ROOT=$(mount -t cgroup2 | head -1 | awk '{print $3}') | |
| 24 | 24 | if [[ -z "$CGROUP_ROOT" ]]; then |
| 25 | 25 | CGROUP_ROOT=/dev/cgroup/memory |
| 26 | 26 | mount -t cgroup2 none $CGROUP_ROOT |
| @@ -28,7 +28,7 @@ if [[ $cgroup2 ]]; then · 1 unmodified line | ||
| 28 | 28 | fi |
| 29 | 29 | echo "+hugetlb +memory" >$CGROUP_ROOT/cgroup.subtree_control |
| 30 | 30 | else |
| 31 | − CGROUP_ROOT=$(mount -t cgroup | grep ",hugetlb" | awk -e '{print $3}') | |
| 31 | + CGROUP_ROOT=$(mount -t cgroup | grep ",hugetlb" | awk '{print $3}') | |
| 32 | 32 | if [[ -z "$CGROUP_ROOT" ]]; then |
| 33 | 33 | CGROUP_ROOT=/dev/cgroup/memory |
| 34 | 34 | mount -t cgroup memory,hugetlb $CGROUP_ROOT |
| @@ -6,13 +6,14 @@ TEST_PROGS := nft_trans_stress.sh nft_fib.sh nft_nat.sh bridge_brouter.sh \ · 5 unmodified lines | ||
| 6 | 6 | nft_concat_range.sh nft_conntrack_helper.sh \ |
| 7 | 7 | nft_queue.sh nft_meta.sh nf_nat_edemux.sh \ |
| 8 | 8 | ipip-conntrack-mtu.sh conntrack_tcp_unreplied.sh \ |
| 9 | − conntrack_vrf.sh nft_synproxy.sh rpath.sh nft_audit.sh | |
| 9 | + conntrack_vrf.sh nft_synproxy.sh rpath.sh nft_audit.sh \ | |
| 10 | + conntrack_sctp_collision.sh | |
| 10 | 11 | |
| 11 | 12 | HOSTPKG_CONFIG := pkg-config |
| 12 | 13 | |
| 13 | 14 | CFLAGS += $(shell $(HOSTPKG_CONFIG) --cflags libmnl 2>/dev/null) |
| 14 | 15 | LDLIBS += $(shell $(HOSTPKG_CONFIG) --libs libmnl 2>/dev/null || echo -lmnl) |
| 15 | 16 | |
| 16 | −TEST_GEN_FILES = nf-queue connect_close audit_logread | |
| 17 | +TEST_GEN_FILES = nf-queue connect_close audit_logread sctp_collision | |
| 17 | 18 | |
| 18 | 19 | include ../lib.mk |
| @@ -0,0 +1,89 @@ | ||
| 1 | +#!/bin/bash | |
| 2 | +# SPDX-License-Identifier: GPL-2.0 | |
| 3 | +# | |
| 4 | +# Testing For SCTP COLLISION SCENARIO as Below: | |
| 5 | +# | |
| 6 | +# 14:35:47.655279 IP CLIENT_IP.PORT > SERVER_IP.PORT: sctp (1) [INIT] [init tag: 2017837359] | |
| 7 | +# 14:35:48.353250 IP SERVER_IP.PORT > CLIENT_IP.PORT: sctp (1) [INIT] [init tag: 1187206187] | |
| 8 | +# 14:35:48.353275 IP CLIENT_IP.PORT > SERVER_IP.PORT: sctp (1) [INIT ACK] [init tag: 2017837359] | |
| 9 | +# 14:35:48.353283 IP SERVER_IP.PORT > CLIENT_IP.PORT: sctp (1) [COOKIE ECHO] | |
| 10 | +# 14:35:48.353977 IP CLIENT_IP.PORT > SERVER_IP.PORT: sctp (1) [COOKIE ACK] | |
| 11 | +# 14:35:48.855335 IP SERVER_IP.PORT > CLIENT_IP.PORT: sctp (1) [INIT ACK] [init tag: 164579970] | |
| 12 | +# | |
| 13 | +# TOPO: SERVER_NS (link0)<--->(link1) ROUTER_NS (link2)<--->(link3) CLIENT_NS | |
| 14 | + | |
| 15 | +CLIENT_NS=$(mktemp -u client-XXXXXXXX) | |
| 16 | +CLIENT_IP="198.51.200.1" | |
| 17 | +CLIENT_PORT=1234 | |
| 18 | + | |
| 19 | +SERVER_NS=$(mktemp -u server-XXXXXXXX) | |
| 20 | +SERVER_IP="198.51.100.1" | |
| 21 | +SERVER_PORT=1234 | |
| 22 | + | |
| 23 | +ROUTER_NS=$(mktemp -u router-XXXXXXXX) | |
| 24 | +CLIENT_GW="198.51.200.2" | |
| 25 | +SERVER_GW="198.51.100.2" | |
| 26 | + | |
| 27 | +# setup the topo | |
| 28 | +setup() { | |
| 29 | + ip net add $CLIENT_NS | |
| 30 | + ip net add $SERVER_NS | |
| 31 | + ip net add $ROUTER_NS | |
| 32 | + ip -n $SERVER_NS link add link0 type veth peer name link1 netns $ROUTER_NS | |
| 33 | + ip -n $CLIENT_NS link add link3 type veth peer name link2 netns $ROUTER_NS | |
| 34 | + | |
| 35 | + ip -n $SERVER_NS link set link0 up | |
| 36 | + ip -n $SERVER_NS addr add $SERVER_IP/24 dev link0 | |
| 37 | + ip -n $SERVER_NS route add $CLIENT_IP dev link0 via $SERVER_GW | |
| 38 | + | |
| 39 | + ip -n $ROUTER_NS link set link1 up | |
| 40 | + ip -n $ROUTER_NS link set link2 up | |
| 41 | + ip -n $ROUTER_NS addr add $SERVER_GW/24 dev link1 | |
| 42 | + ip -n $ROUTER_NS addr add $CLIENT_GW/24 dev link2 | |
| 43 | + ip net exec $ROUTER_NS sysctl -wq net.ipv4.ip_forward=1 | |
| 44 | + | |
| 45 | + ip -n $CLIENT_NS link set link3 up | |
| 46 | + ip -n $CLIENT_NS addr add $CLIENT_IP/24 dev link3 | |
| 47 | + ip -n $CLIENT_NS route add $SERVER_IP dev link3 via $CLIENT_GW | |
| 48 | + | |
| 49 | + # simulate the delay on OVS upcall by setting up a delay for INIT_ACK with | |
| 50 | + # tc on $SERVER_NS side | |
| 51 | + tc -n $SERVER_NS qdisc add dev link0 root handle 1: htb | |
| 52 | + tc -n $SERVER_NS class add dev link0 parent 1: classid 1:1 htb rate 100mbit | |
| 53 | + tc -n $SERVER_NS filter add dev link0 parent 1: protocol ip u32 match ip protocol 132 \ | |
| 54 | + 0xff match u8 2 0xff at 32 flowid 1:1 | |
| 55 | + tc -n $SERVER_NS qdisc add dev link0 parent 1:1 handle 10: netem delay 1200ms | |
| 56 | + | |
| 57 | + # simulate the ctstate check on OVS nf_conntrack | |
| 58 | + ip net exec $ROUTER_NS iptables -A FORWARD -m state --state INVALID,UNTRACKED -j DROP | |
| 59 | + ip net exec $ROUTER_NS iptables -A INPUT -p sctp -j DROP | |
| 60 | + | |
| 61 | + # use a smaller number for assoc's max_retrans to reproduce the issue | |
| 62 | + modprobe sctp | |
| 63 | + ip net exec $CLIENT_NS sysctl -wq net.sctp.association_max_retrans=3 | |
| 64 | +} | |
| 65 | + | |
| 66 | +cleanup() { | |
| 67 | + ip net exec $CLIENT_NS pkill sctp_collision 2>&1 >/dev/null | |
| 68 | + ip net exec $SERVER_NS pkill sctp_collision 2>&1 >/dev/null | |
| 69 | + ip net del "$CLIENT_NS" | |
| 70 | + ip net del "$SERVER_NS" | |
| 71 | + ip net del "$ROUTER_NS" | |
| 72 | +} | |
| 73 | + | |
| 74 | +do_test() { | |
| 75 | + ip net exec $SERVER_NS ./sctp_collision server \ | |
| 76 | + $SERVER_IP $SERVER_PORT $CLIENT_IP $CLIENT_PORT & | |
| 77 | + ip net exec $CLIENT_NS ./sctp_collision client \ | |
| 78 | + $CLIENT_IP $CLIENT_PORT $SERVER_IP $SERVER_PORT | |
| 79 | +} | |
| 80 | + | |
| 81 | +# NOTE: one way to work around the issue is set a smaller hb_interval | |
| 82 | +# ip net exec $CLIENT_NS sysctl -wq net.sctp.hb_interval=3500 | |
| 83 | + | |
| 84 | +# run the test case | |
| 85 | +trap cleanup EXIT | |
| 86 | +setup && \ | |
| 87 | +echo "Test for SCTP Collision in nf_conntrack:" && \ | |
| 88 | +do_test && echo "PASS!" | |
| 89 | +exit $? | |
| @@ -12,10 +12,11 @@ nft --version >/dev/null 2>&1 || { · 11 unmodified lines | ||
| 12 | 12 | } |
| 13 | 13 | |
| 14 | 14 | logfile=$(mktemp) |
| 15 | +rulefile=$(mktemp) | |
| 15 | 16 | echo "logging into $logfile" |
| 16 | 17 | ./audit_logread >"$logfile" & |
| 17 | 18 | logread_pid=$! |
| 18 | −trap 'kill $logread_pid; rm -f $logfile' EXIT | |
| 19 | +trap 'kill $logread_pid; rm -f $logfile $rulefile' EXIT | |
| 19 | 20 | exec 3<"$logfile" |
| 20 | 21 | |
| 21 | 22 | do_test() { # (cmd, log) |
| @@ -26,12 +27,14 @@ do_test() { # (cmd, log) · 4 unmodified lines | ||
| 26 | 27 | res=$(diff -a -u <(echo "$2") - <&3) |
| 27 | 28 | [ $? -eq 0 ] && { echo "OK"; return; } |
| 28 | 29 | echo "FAIL" |
| 29 | − echo "$res" | |
| 30 | − ((RC++)) | |
| 30 | + grep -v '^\(---\|+++\|@@\)' <<< "$res" | |
| 31 | + ((RC--)) | |
| 31 | 32 | } |
| 32 | 33 | |
| 33 | 34 | nft flush ruleset |
| 34 | 35 | |
| 36 | +# adding tables, chains and rules | |
| 37 | + | |
| 35 | 38 | for table in t1 t2; do |
| 36 | 39 | do_test "nft add table $table" \ |
| 37 | 40 | "table=$table family=2 entries=1 op=nft_register_table" |
| @@ -62,6 +65,48 @@ for table in t1 t2; do · 24 unmodified lines | ||
| 62 | 65 | "table=$table family=2 entries=6 op=nft_register_rule" |
| 63 | 66 | done |
| 64 | 67 | |
| 68 | +for ((i = 0; i < 500; i++)); do | |
| 69 | + echo "add rule t2 c3 counter accept comment \"rule $i\"" | |
| 70 | +done >$rulefile | |
| 71 | +do_test "nft -f $rulefile" \ | |
| 72 | +'table=t2 family=2 entries=500 op=nft_register_rule' | |
| 73 | + | |
| 74 | +# adding sets and elements | |
| 75 | + | |
| 76 | +settype='type inet_service; counter' | |
| 77 | +setelem='{ 22, 80, 443 }' | |
| 78 | +setblock="{ $settype; elements = $setelem; }" | |
| 79 | +do_test "nft add set t1 s $setblock" \ | |
| 80 | +"table=t1 family=2 entries=4 op=nft_register_set" | |
| 81 | + | |
| 82 | +do_test "nft add set t1 s2 $setblock; add set t1 s3 { $settype; }" \ | |
| 83 | +"table=t1 family=2 entries=5 op=nft_register_set" | |
| 84 | + | |
| 85 | +do_test "nft add element t1 s3 $setelem" \ | |
| 86 | +"table=t1 family=2 entries=3 op=nft_register_setelem" | |
| 87 | + | |
| 88 | +# adding counters | |
| 89 | + | |
| 90 | +do_test 'nft add counter t1 c1' \ | |
| 91 | +'table=t1 family=2 entries=1 op=nft_register_obj' | |
| 92 | + | |
| 93 | +do_test 'nft add counter t2 c1; add counter t2 c2' \ | |
| 94 | +'table=t2 family=2 entries=2 op=nft_register_obj' | |
| 95 | + | |
| 96 | +# adding/updating quotas | |
| 97 | + | |
| 98 | +do_test 'nft add quota t1 q1 { 10 bytes }' \ | |
| 99 | +'table=t1 family=2 entries=1 op=nft_register_obj' | |
| 100 | + | |
| 101 | +do_test 'nft add quota t2 q1 { 10 bytes }; add quota t2 q2 { 10 bytes }' \ | |
| 102 | +'table=t2 family=2 entries=2 op=nft_register_obj' | |
| 103 | + | |
| 104 | +# changing the quota value triggers obj update path | |
| 105 | +do_test 'nft add quota t1 q1 { 20 bytes }' \ | |
| 106 | +'table=t1 family=2 entries=1 op=nft_register_obj' | |
| 107 | + | |
| 108 | +# resetting rules | |
| 109 | + | |
| 65 | 110 | do_test 'nft reset rules t1 c2' \ |
| 66 | 111 | 'table=t1 family=2 entries=3 op=nft_reset_rule' |
| 67 | 112 | |
| @@ -70,19 +115,6 @@ do_test 'nft reset rules table t1' \ · 2 unmodified lines | ||
| 70 | 115 | table=t1 family=2 entries=3 op=nft_reset_rule |
| 71 | 116 | table=t1 family=2 entries=3 op=nft_reset_rule' |
| 72 | 117 | |
| 73 | −do_test 'nft reset rules' \ | |
| 74 | −'table=t1 family=2 entries=3 op=nft_reset_rule | |
| 75 | −table=t1 family=2 entries=3 op=nft_reset_rule | |
| 76 | −table=t1 family=2 entries=3 op=nft_reset_rule | |
| 77 | −table=t2 family=2 entries=3 op=nft_reset_rule | |
| 78 | −table=t2 family=2 entries=3 op=nft_reset_rule | |
| 79 | −table=t2 family=2 entries=3 op=nft_reset_rule' | |
| 80 | − | |
| 81 | −for ((i = 0; i < 500; i++)); do | |
| 82 | − echo "add rule t2 c3 counter accept comment \"rule $i\"" | |
| 83 | −done | do_test 'nft -f -' \ | |
| 84 | −'table=t2 family=2 entries=500 op=nft_register_rule' | |
| 85 | − | |
| 86 | 118 | do_test 'nft reset rules t2 c3' \ |
| 87 | 119 | 'table=t2 family=2 entries=189 op=nft_reset_rule |
| 88 | 120 | table=t2 family=2 entries=188 op=nft_reset_rule |
| @@ -105,4 +137,57 @@ table=t2 family=2 entries=180 op=nft_reset_rule · 16 unmodified lines | ||
| 105 | 137 | table=t2 family=2 entries=188 op=nft_reset_rule |
| 106 | 138 | table=t2 family=2 entries=135 op=nft_reset_rule' |
| 107 | 139 | |
| 140 | +# resetting sets and elements | |
| 141 | + | |
| 142 | +elem=(22 ,80 ,443) | |
| 143 | +relem="" | |
| 144 | +for i in {1..3}; do | |
| 145 | + relem+="${elem[((i - 1))]}" | |
| 146 | + do_test "nft reset element t1 s { $relem }" \ | |
| 147 | + "table=t1 family=2 entries=$i op=nft_reset_setelem" | |
| 148 | +done | |
| 149 | + | |
| 150 | +do_test 'nft reset set t1 s' \ | |
| 151 | +'table=t1 family=2 entries=3 op=nft_reset_setelem' | |
| 152 | + | |
| 153 | +# deleting rules | |
| 154 | + | |
| 155 | +readarray -t handles < <(nft -a list chain t1 c1 | \ | |
| 156 | + sed -n 's/.*counter.* handle \(.*\)$/\1/p') | |
| 157 | + | |
| 158 | +do_test "nft delete rule t1 c1 handle ${handles[0]}" \ | |
| 159 | +'table=t1 family=2 entries=1 op=nft_unregister_rule' | |
| 160 | + | |
| 161 | +cmd='delete rule t1 c1 handle' | |
| 162 | +do_test "nft $cmd ${handles[1]}; $cmd ${handles[2]}" \ | |
| 163 | +'table=t1 family=2 entries=2 op=nft_unregister_rule' | |
| 164 | + | |
| 165 | +do_test 'nft flush chain t1 c2' \ | |
| 166 | +'table=t1 family=2 entries=3 op=nft_unregister_rule' | |
| 167 | + | |
| 168 | +do_test 'nft flush table t2' \ | |
| 169 | +'table=t2 family=2 entries=509 op=nft_unregister_rule' | |
| 170 | + | |
| 171 | +# deleting chains | |
| 172 | + | |
| 173 | +do_test 'nft delete chain t2 c2' \ | |
| 174 | +'table=t2 family=2 entries=1 op=nft_unregister_chain' | |
| 175 | + | |
| 176 | +# deleting sets and elements | |
| 177 | + | |
| 178 | +do_test 'nft delete element t1 s { 22 }' \ | |
| 179 | +'table=t1 family=2 entries=1 op=nft_unregister_setelem' | |
| 180 | + | |
| 181 | +do_test 'nft delete element t1 s { 80, 443 }' \ | |
| 182 | +'table=t1 family=2 entries=2 op=nft_unregister_setelem' | |
| 183 | + | |
| 184 | +do_test 'nft flush set t1 s2' \ | |
| 185 | +'table=t1 family=2 entries=3 op=nft_unregister_setelem' | |
| 186 | + | |
| 187 | +do_test 'nft delete set t1 s2' \ | |
| 188 | +'table=t1 family=2 entries=1 op=nft_unregister_set' | |
| 189 | + | |
| 190 | +do_test 'nft delete set t1 s3' \ | |
| 191 | +'table=t1 family=2 entries=1 op=nft_unregister_set' | |
| 192 | + | |
| 108 | 193 | exit $RC |
| @@ -0,0 +1,99 @@ | ||
| 1 | +// SPDX-License-Identifier: GPL-2.0 | |
| 2 | + | |
| 3 | +#include <stdio.h> | |
| 4 | +#include <stdlib.h> | |
| 5 | +#include <string.h> | |
| 6 | +#include <unistd.h> | |
| 7 | +#include <arpa/inet.h> | |
| 8 | + | |
| 9 | +int main(int argc, char *argv[]) | |
| 10 | +{ | |
| 11 | + struct sockaddr_in saddr = {}, daddr = {}; | |
| 12 | + int sd, ret, len = sizeof(daddr); | |
| 13 | + struct timeval tv = {25, 0}; | |
| 14 | + char buf[] = "hello"; | |
| 15 | + | |
| 16 | + if (argc != 6 || (strcmp(argv[1], "server") && strcmp(argv[1], "client"))) { | |
| 17 | + printf("%s <server|client> <LOCAL_IP> <LOCAL_PORT> <REMOTE_IP> <REMOTE_PORT>\n", | |
| 18 | + argv[0]); | |
| 19 | + return -1; | |
| 20 | + } | |
| 21 | + | |
| 22 | + sd = socket(AF_INET, SOCK_SEQPACKET, IPPROTO_SCTP); | |
| 23 | + if (sd < 0) { | |
| 24 | + printf("Failed to create sd\n"); | |
| 25 | + return -1; | |
| 26 | + } | |
| 27 | + | |
| 28 | + saddr.sin_family = AF_INET; | |
| 29 | + saddr.sin_addr.s_addr = inet_addr(argv[2]); | |
| 30 | + saddr.sin_port = htons(atoi(argv[3])); | |
| 31 | + | |
| 32 | + ret = bind(sd, (struct sockaddr *)&saddr, sizeof(saddr)); | |
| 33 | + if (ret < 0) { | |
| 34 | + printf("Failed to bind to address\n"); | |
| 35 | + goto out; | |
| 36 | + } | |
| 37 | + | |
| 38 | + ret = listen(sd, 5); | |
| 39 | + if (ret < 0) { | |
| 40 | + printf("Failed to listen on port\n"); | |
| 41 | + goto out; | |
| 42 | + } | |
| 43 | + | |
| 44 | + daddr.sin_family = AF_INET; | |
| 45 | + daddr.sin_addr.s_addr = inet_addr(argv[4]); | |
| 46 | + daddr.sin_port = htons(atoi(argv[5])); | |
| 47 | + | |
| 48 | + /* make test shorter than 25s */ | |
| 49 | + ret = setsockopt(sd, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)); | |
| 50 | + if (ret < 0) { | |
| 51 | + printf("Failed to setsockopt SO_RCVTIMEO\n"); | |
| 52 | + goto out; | |
| 53 | + } | |
| 54 | + | |
| 55 | + if (!strcmp(argv[1], "server")) { | |
| 56 | + sleep(1); /* wait a bit for client's INIT */ | |
| 57 | + ret = connect(sd, (struct sockaddr *)&daddr, len); | |
| 58 | + if (ret < 0) { | |
| 59 | + printf("Failed to connect to peer\n"); | |
| 60 | + goto out; | |
| 61 | + } | |
| 62 | + ret = recvfrom(sd, buf, sizeof(buf), 0, (struct sockaddr *)&daddr, &len); | |
| 63 | + if (ret < 0) { | |
| 64 | + printf("Failed to recv msg %d\n", ret); | |
| 65 | + goto out; | |
| 66 | + } | |
| 67 | + ret = sendto(sd, buf, strlen(buf) + 1, 0, (struct sockaddr *)&daddr, len); | |
| 68 | + if (ret < 0) { | |
| 69 | + printf("Failed to send msg %d\n", ret); | |
| 70 | + goto out; | |
| 71 | + } | |
| 72 | + printf("Server: sent! %d\n", ret); | |
| 73 | + } | |
| 74 | + | |
| 75 | + if (!strcmp(argv[1], "client")) { | |
| 76 | + usleep(300000); /* wait a bit for server's listening */ | |
| 77 | + ret = connect(sd, (struct sockaddr *)&daddr, len); | |
| 78 | + if (ret < 0) { | |
| 79 | + printf("Failed to connect to peer\n"); | |
| 80 | + goto out; | |
| 81 | + } | |
| 82 | + sleep(1); /* wait a bit for server's delayed INIT_ACK to reproduce the issue */ | |
| 83 | + ret = sendto(sd, buf, strlen(buf) + 1, 0, (struct sockaddr *)&daddr, len); | |
| 84 | + if (ret < 0) { | |
| 85 | + printf("Failed to send msg %d\n", ret); | |
| 86 | + goto out; | |
| 87 | + } | |
| 88 | + ret = recvfrom(sd, buf, sizeof(buf), 0, (struct sockaddr *)&daddr, &len); | |
| 89 | + if (ret < 0) { | |
| 90 | + printf("Failed to recv msg %d\n", ret); | |
| 91 | + goto out; | |
| 92 | + } | |
| 93 | + printf("Client: rcvd! %d\n", ret); | |
| 94 | + } | |
| 95 | + ret = 0; | |
| 96 | +out: | |
| 97 | + close(sd); | |
| 98 | + return ret; | |
| 99 | +} | |
| @@ -1,6 +1,6 @@ | ||
| 1 | 1 | # SPDX-License-Identifier: GPL-2.0-or-later |
| 2 | 2 | |
| 3 | −CFLAGS += -Wall -O2 -g -fsanitize=address -fsanitize=undefined | |
| 3 | +CFLAGS += -Wall -O2 -g -fsanitize=address -fsanitize=undefined -static-libasan | |
| 4 | 4 | TEST_GEN_PROGS := openat2_test resolve_test rename_attack_test |
| 5 | 5 | |
| 6 | 6 | include ../lib.mk |
| @@ -59,12 +59,11 @@ override define INSTALL_RULE · 58 unmodified lines | ||
| 59 | 59 | done; |
| 60 | 60 | endef |
| 61 | 61 | |
| 62 | −override define EMIT_TESTS | |
| 62 | +emit_tests: | |
| 63 | 63 | +@for TARGET in $(SUB_DIRS); do \ |
| 64 | 64 | BUILD_TARGET=$(OUTPUT)/$$TARGET; \ |
| 65 | − $(MAKE) OUTPUT=$$BUILD_TARGET -s -C $$TARGET emit_tests;\ | |
| 65 | + $(MAKE) OUTPUT=$$BUILD_TARGET -s -C $$TARGET $@;\ | |
| 66 | 66 | done; |
| 67 | −endef | |
| 68 | 67 | |
| 69 | 68 | override define CLEAN |
| 70 | 69 | +@for TARGET in $(SUB_DIRS); do \ |
| @@ -77,4 +76,4 @@ endef · 6 unmodified lines | ||
| 77 | 76 | tags: |
| 78 | 77 | find . -name '*.c' -o -name '*.h' | xargs ctags |
| 79 | 78 | |
| 80 | −.PHONY: tags $(SUB_DIRS) | |
| 79 | +.PHONY: tags $(SUB_DIRS) emit_tests | |
| @@ -30,13 +30,14 @@ override define RUN_TESTS · 29 unmodified lines | ||
| 30 | 30 | +TARGET=event_code_tests; BUILD_TARGET=$$OUTPUT/$$TARGET; $(MAKE) OUTPUT=$$BUILD_TARGET -C $$TARGET run_tests |
| 31 | 31 | endef |
| 32 | 32 | |
| 33 | −DEFAULT_EMIT_TESTS := $(EMIT_TESTS) | |
| 34 | −override define EMIT_TESTS | |
| 35 | − $(DEFAULT_EMIT_TESTS) | |
| 33 | +emit_tests: | |
| 34 | + for TEST in $(TEST_GEN_PROGS); do \ | |
| 35 | + BASENAME_TEST=`basename $$TEST`; \ | |
| 36 | + echo "$(COLLECTION):$$BASENAME_TEST"; \ | |
| 37 | + done | |
| 36 | 38 | +TARGET=ebb; BUILD_TARGET=$$OUTPUT/$$TARGET; $(MAKE) OUTPUT=$$BUILD_TARGET -s -C $$TARGET emit_tests |
| 37 | 39 | +TARGET=sampling_tests; BUILD_TARGET=$$OUTPUT/$$TARGET; $(MAKE) OUTPUT=$$BUILD_TARGET -s -C $$TARGET emit_tests |
| 38 | 40 | +TARGET=event_code_tests; BUILD_TARGET=$$OUTPUT/$$TARGET; $(MAKE) OUTPUT=$$BUILD_TARGET -s -C $$TARGET emit_tests |
| 39 | −endef | |
| 40 | 41 | |
| 41 | 42 | DEFAULT_INSTALL_RULE := $(INSTALL_RULE) |
| 42 | 43 | override define INSTALL_RULE |
| @@ -64,4 +65,4 @@ sampling_tests: · 21 unmodified lines | ||
| 64 | 65 | event_code_tests: |
| 65 | 66 | TARGET=$@; BUILD_TARGET=$$OUTPUT/$$TARGET; mkdir -p $$BUILD_TARGET; $(MAKE) OUTPUT=$$BUILD_TARGET -k -C $$TARGET all |
| 66 | 67 | |
| 67 | −.PHONY: all run_tests ebb sampling_tests event_code_tests | |
| 68 | +.PHONY: all run_tests ebb sampling_tests event_code_tests emit_tests | |
| @@ -267,6 +267,7 @@ static const char g_smaps_rollup[] = · 266 unmodified lines | ||
| 267 | 267 | "Private_Dirty: 0 kB\n" |
| 268 | 268 | "Referenced: 0 kB\n" |
| 269 | 269 | "Anonymous: 0 kB\n" |
| 270 | +"KSM: 0 kB\n" | |
| 270 | 271 | "LazyFree: 0 kB\n" |
| 271 | 272 | "AnonHugePages: 0 kB\n" |
| 272 | 273 | "ShmemPmdMapped: 0 kB\n" |
| @@ -91,16 +91,18 @@ static int reg_disable(long *enable, int bit) · 90 unmodified lines | ||
| 91 | 91 | |
| 92 | 92 | FIXTURE(user) { |
| 93 | 93 | long check; |
| 94 | + bool umount; | |
| 94 | 95 | }; |
| 95 | 96 | |
| 96 | 97 | FIXTURE_SETUP(user) { |
| 97 | − USER_EVENT_FIXTURE_SETUP(return); | |
| 98 | + USER_EVENT_FIXTURE_SETUP(return, self->umount); | |
| 98 | 99 | |
| 99 | 100 | change_event(false); |
| 100 | 101 | self->check = 0; |
| 101 | 102 | } |
| 102 | 103 | |
| 103 | 104 | FIXTURE_TEARDOWN(user) { |
| 105 | + USER_EVENT_FIXTURE_TEARDOWN(self->umount); | |
| 104 | 106 | } |
| 105 | 107 | |
| 106 | 108 | TEST_F(user, enablement) { |
| @@ -144,13 +144,16 @@ do { \ · 143 unmodified lines | ||
| 144 | 144 | |
| 145 | 145 | FIXTURE(user) { |
| 146 | 146 | int check; |
| 147 | + bool umount; | |
| 147 | 148 | }; |
| 148 | 149 | |
| 149 | 150 | FIXTURE_SETUP(user) { |
| 150 | − USER_EVENT_FIXTURE_SETUP(return); | |
| 151 | + USER_EVENT_FIXTURE_SETUP(return, self->umount); | |
| 151 | 152 | } |
| 152 | 153 | |
| 153 | 154 | FIXTURE_TEARDOWN(user) { |
| 155 | + USER_EVENT_FIXTURE_TEARDOWN(self->umount); | |
| 156 | + | |
| 154 | 157 | wait_for_delete(); |
| 155 | 158 | } |
| 156 | 159 | |
| @@ -204,10 +204,11 @@ FIXTURE(user) { · 203 unmodified lines | ||
| 204 | 204 | int data_fd; |
| 205 | 205 | int enable_fd; |
| 206 | 206 | int check; |
| 207 | + bool umount; | |
| 207 | 208 | }; |
| 208 | 209 | |
| 209 | 210 | FIXTURE_SETUP(user) { |
| 210 | − USER_EVENT_FIXTURE_SETUP(return); | |
| 211 | + USER_EVENT_FIXTURE_SETUP(return, self->umount); | |
| 211 | 212 | |
| 212 | 213 | self->status_fd = open(status_file, O_RDONLY); |
| 213 | 214 | ASSERT_NE(-1, self->status_fd); |
| @@ -219,6 +220,8 @@ FIXTURE_SETUP(user) { · 5 unmodified lines | ||
| 219 | 220 | } |
| 220 | 221 | |
| 221 | 222 | FIXTURE_TEARDOWN(user) { |
| 223 | + USER_EVENT_FIXTURE_TEARDOWN(self->umount); | |
| 224 | + | |
| 222 | 225 | close(self->status_fd); |
| 223 | 226 | close(self->data_fd); |
| 224 | 227 | |
| @@ -111,16 +111,19 @@ static int clear(int *check) · 110 unmodified lines | ||
| 111 | 111 | FIXTURE(user) { |
| 112 | 112 | int data_fd; |
| 113 | 113 | int check; |
| 114 | + bool umount; | |
| 114 | 115 | }; |
| 115 | 116 | |
| 116 | 117 | FIXTURE_SETUP(user) { |
| 117 | − USER_EVENT_FIXTURE_SETUP(return); | |
| 118 | + USER_EVENT_FIXTURE_SETUP(return, self->umount); | |
| 118 | 119 | |
| 119 | 120 | self->data_fd = open(data_file, O_RDWR); |
| 120 | 121 | ASSERT_NE(-1, self->data_fd); |
| 121 | 122 | } |
| 122 | 123 | |
| 123 | 124 | FIXTURE_TEARDOWN(user) { |
| 125 | + USER_EVENT_FIXTURE_TEARDOWN(self->umount); | |
| 126 | + | |
| 124 | 127 | close(self->data_fd); |
| 125 | 128 | |
| 126 | 129 | if (clear(&self->check) != 0) |
| @@ -11,13 +11,19 @@ · 10 unmodified lines | ||
| 11 | 11 | |
| 12 | 12 | #include "../kselftest.h" |
| 13 | 13 | |
| 14 | −static inline bool tracefs_enabled(char **message, bool *fail) | |
| 14 | +static inline void tracefs_unmount(void) | |
| 15 | +{ | |
| 16 | + umount("/sys/kernel/tracing"); | |
| 17 | +} | |
| 18 | + | |
| 19 | +static inline bool tracefs_enabled(char **message, bool *fail, bool *umount) | |
| 15 | 20 | { |
| 16 | 21 | struct stat buf; |
| 17 | 22 | int ret; |
| 18 | 23 | |
| 19 | 24 | *message = ""; |
| 20 | 25 | *fail = false; |
| 26 | + *umount = false; | |
| 21 | 27 | |
| 22 | 28 | /* Ensure tracefs is installed */ |
| 23 | 29 | ret = stat("/sys/kernel/tracing", &buf); |
| @@ -37,6 +43,8 @@ static inline bool tracefs_enabled(char **message, bool *fail) · 13 unmodified lines | ||
| 37 | 43 | return false; |
| 38 | 44 | } |
| 39 | 45 | |
| 46 | + *umount = true; | |
| 47 | + | |
| 40 | 48 | ret = stat("/sys/kernel/tracing/README", &buf); |
| 41 | 49 | } |
| 42 | 50 | |
| @@ -49,13 +57,14 @@ static inline bool tracefs_enabled(char **message, bool *fail) · 6 unmodified lines | ||
| 49 | 57 | return true; |
| 50 | 58 | } |
| 51 | 59 | |
| 52 | −static inline bool user_events_enabled(char **message, bool *fail) | |
| 60 | +static inline bool user_events_enabled(char **message, bool *fail, bool *umount) | |
| 53 | 61 | { |
| 54 | 62 | struct stat buf; |
| 55 | 63 | int ret; |
| 56 | 64 | |
| 57 | 65 | *message = ""; |
| 58 | 66 | *fail = false; |
| 67 | + *umount = false; | |
| 59 | 68 | |
| 60 | 69 | if (getuid() != 0) { |
| 61 | 70 | *message = "Must be run as root"; |
| @@ -63,7 +72,7 @@ static inline bool user_events_enabled(char **message, bool *fail) · 1 unmodified line | ||
| 63 | 72 | return false; |
| 64 | 73 | } |
| 65 | 74 | |
| 66 | − if (!tracefs_enabled(message, fail)) | |
| 75 | + if (!tracefs_enabled(message, fail, umount)) | |
| 67 | 76 | return false; |
| 68 | 77 | |
| 69 | 78 | /* Ensure user_events is installed */ |
| @@ -85,10 +94,10 @@ static inline bool user_events_enabled(char **message, bool *fail) · 15 unmodified lines | ||
| 85 | 94 | return true; |
| 86 | 95 | } |
| 87 | 96 | |
| 88 | −#define USER_EVENT_FIXTURE_SETUP(statement) do { \ | |
| 97 | +#define USER_EVENT_FIXTURE_SETUP(statement, umount) do { \ | |
| 89 | 98 | char *message; \ |
| 90 | 99 | bool fail; \ |
| 91 | − if (!user_events_enabled(&message, &fail)) { \ | |
| 100 | + if (!user_events_enabled(&message, &fail, &(umount))) { \ | |
| 92 | 101 | if (fail) { \ |
| 93 | 102 | TH_LOG("Setup failed due to: %s", message); \ |
| 94 | 103 | ASSERT_FALSE(fail); \ |
| @@ -97,4 +106,9 @@ static inline bool user_events_enabled(char **message, bool *fail) · 2 unmodified lines | ||
| 97 | 106 | } \ |
| 98 | 107 | } while (0) |
| 99 | 108 | |
| 109 | +#define USER_EVENT_FIXTURE_TEARDOWN(umount) do { \ | |
| 110 | + if ((umount)) \ | |
| 111 | + tracefs_unmount(); \ | |
| 112 | +} while (0) | |
| 113 | + | |
| 100 | 114 | #endif /* _USER_EVENTS_SELFTESTS_H */ |
| @@ -159,6 +159,7 @@ static int timerlat_aa_irq_latency(struct timerlat_aa_data *taa_data, · 158 unmodified lines | ||
| 159 | 159 | taa_data->thread_nmi_sum = 0; |
| 160 | 160 | taa_data->thread_irq_sum = 0; |
| 161 | 161 | taa_data->thread_softirq_sum = 0; |
| 162 | + taa_data->thread_thread_sum = 0; | |
| 162 | 163 | taa_data->thread_blocking_duration = 0; |
| 163 | 164 | taa_data->timer_irq_start_time = 0; |
| 164 | 165 | taa_data->timer_irq_duration = 0; |
| @@ -337,7 +338,23 @@ static int timerlat_aa_irq_handler(struct trace_seq *s, struct tep_record *recor · 172 unmodified lines | ||
| 337 | 338 | taa_data->timer_irq_start_time = start; |
| 338 | 339 | taa_data->timer_irq_duration = duration; |
| 339 | 340 | |
| 340 | − taa_data->timer_irq_start_delay = taa_data->timer_irq_start_time - expected_start; | |
| 341 | + /* | |
| 342 | + * We are dealing with two different clock sources: the | |
| 343 | + * external clock source that timerlat uses as a reference | |
| 344 | + * and the clock used by the tracer. There are also two | |
| 345 | + * moments: the time reading the clock and the timer in | |
| 346 | + * which the event is placed in the buffer (the trace | |
| 347 | + * event timestamp). If the processor is slow or there | |
| 348 | + * is some hardware noise, the difference between the | |
| 349 | + * timestamp and the external clock read can be longer | |
| 350 | + * than the IRQ handler delay, resulting in a negative | |
| 351 | + * time. If so, set IRQ start delay as 0. In the end, | |
| 352 | + * it is less relevant than the noise. | |
| 353 | + */ | |
| 354 | + if (expected_start < taa_data->timer_irq_start_time) | |
| 355 | + taa_data->timer_irq_start_delay = taa_data->timer_irq_start_time - expected_start; | |
| 356 | + else | |
| 357 | + taa_data->timer_irq_start_delay = 0; | |
| 341 | 358 | |
| 342 | 359 | /* |
| 343 | 360 | * not exit from idle. |
| @@ -528,7 +545,7 @@ static int timerlat_aa_kworker_start_handler(struct trace_seq *s, struct tep_rec · 184 unmodified lines | ||
| 528 | 545 | static void timerlat_thread_analysis(struct timerlat_aa_data *taa_data, int cpu, |
| 529 | 546 | int irq_thresh, int thread_thresh) |
| 530 | 547 | { |
| 531 | − unsigned long long exp_irq_ts; | |
| 548 | + long long exp_irq_ts; | |
| 532 | 549 | int total; |
| 533 | 550 | int irq; |
| 534 | 551 | |
| @@ -545,12 +562,15 @@ static void timerlat_thread_analysis(struct timerlat_aa_data *taa_data, int cpu, · 10 unmodified lines | ||
| 545 | 562 | |
| 546 | 563 | /* |
| 547 | 564 | * Expected IRQ arrival time using the trace clock as the base. |
| 565 | + * | |
| 566 | + * TODO: Add a list of previous IRQ, and then run the list backwards. | |
| 548 | 567 | */ |
| 549 | 568 | exp_irq_ts = taa_data->timer_irq_start_time - taa_data->timer_irq_start_delay; |
| 550 | − | |
| 551 | − if (exp_irq_ts < taa_data->prev_irq_timstamp + taa_data->prev_irq_duration) | |
| 552 | − printf(" Previous IRQ interference: \t\t up to %9.2f us\n", | |
| 553 | − ns_to_usf(taa_data->prev_irq_duration)); | |
| 569 | + if (exp_irq_ts < taa_data->prev_irq_timstamp + taa_data->prev_irq_duration) { | |
| 570 | + if (taa_data->prev_irq_timstamp < taa_data->timer_irq_start_time) | |
| 571 | + printf(" Previous IRQ interference: \t\t up to %9.2f us\n", | |
| 572 | + ns_to_usf(taa_data->prev_irq_duration)); | |
| 573 | + } | |
| 554 | 574 | |
| 555 | 575 | /* |
| 556 | 576 | * The delay that the IRQ suffered before starting. |
| @@ -45,7 +45,7 @@ static int timerlat_u_main(int cpu, struct timerlat_u_params *params) · 44 unmodified lines | ||
| 45 | 45 | |
| 46 | 46 | retval = sched_setaffinity(gettid(), sizeof(set), &set); |
| 47 | 47 | if (retval == -1) { |
| 48 | − err_msg("Error setting user thread affinity\n"); | |
| 48 | + debug_msg("Error setting user thread affinity %d, is the CPU online?\n", cpu); | |
| 49 | 49 | exit(1); |
| 50 | 50 | } |
| 51 | 51 | |
| @@ -193,7 +193,9 @@ void *timerlat_u_dispatcher(void *data) · 141 unmodified lines | ||
| 193 | 193 | procs_count--; |
| 194 | 194 | } |
| 195 | 195 | } |
| 196 | − break; | |
| 196 | + | |
| 197 | + if (!procs_count) | |
| 198 | + break; | |
| 197 | 199 | } |
| 198 | 200 | |
| 199 | 201 | sleep(1); |