Pick up build fixes from upstream to make this tree more testable.
Unified · Split
| @@ -102,6 +102,7 @@ Ard Biesheuvel <ardb@kernel.org> <ard.biesheuvel@linaro.org> · 101 unmodified lines | |||
| 102 | Arnaud Patard <arnaud.patard@rtp-net.org> | 102 | Arnaud Patard <arnaud.patard@rtp-net.org> |
| 103 | Arnd Bergmann <arnd@arndb.de> | 103 | Arnd Bergmann <arnd@arndb.de> |
| 104 | Arun Kumar Neelakantam <quic_aneela@quicinc.com> <aneela@codeaurora.org> | 104 | Arun Kumar Neelakantam <quic_aneela@quicinc.com> <aneela@codeaurora.org> |
| 105 | Asahi Lina <lina+kernel@asahilina.net> <lina@asahilina.net> | ||
| 105 | Ashok Raj Nagarajan <quic_arnagara@quicinc.com> <arnagara@codeaurora.org> | 106 | Ashok Raj Nagarajan <quic_arnagara@quicinc.com> <arnagara@codeaurora.org> |
| 106 | Ashwin Chaugule <quic_ashwinc@quicinc.com> <ashwinc@codeaurora.org> | 107 | Ashwin Chaugule <quic_ashwinc@quicinc.com> <ashwinc@codeaurora.org> |
| 107 | Asutosh Das <quic_asutoshd@quicinc.com> <asutoshd@codeaurora.org> | 108 | Asutosh Das <quic_asutoshd@quicinc.com> <asutoshd@codeaurora.org> |
| @@ -1,6 +1,6 @@ | |||
| 1 | What: /sys/bus/hid/drivers/hid-appletb-kbd/<dev>/mode | 1 | What: /sys/bus/hid/drivers/hid-appletb-kbd/<dev>/mode |
| 2 | Date: September, 2023 | 2 | Date: March, 2025 |
| 3 | KernelVersion: 6.5 | 3 | KernelVersion: 6.15 |
| 4 | Contact: linux-input@vger.kernel.org | 4 | Contact: linux-input@vger.kernel.org |
| 5 | Description: | 5 | Description: |
| 6 | The set of keys displayed on the Touch Bar. | 6 | The set of keys displayed on the Touch Bar. |
| @@ -46,6 +46,21 @@ The kernel embeds the building user and host names in · 45 unmodified lines | |||
| 46 | `KBUILD_BUILD_USER and KBUILD_BUILD_HOST`_ variables. If you are | 46 | `KBUILD_BUILD_USER and KBUILD_BUILD_HOST`_ variables. If you are |
| 47 | building from a git commit, you could use its committer address. | 47 | building from a git commit, you could use its committer address. |
| 48 | 48 | ||
| 49 | Absolute filenames | ||
| 50 | ------------------ | ||
| 51 | |||
| 52 | When the kernel is built out-of-tree, debug information may include | ||
| 53 | absolute filenames for the source files. This must be overridden by | ||
| 54 | including the ``-fdebug-prefix-map`` option in the `KCFLAGS`_ variable. | ||
| 55 | |||
| 56 | Depending on the compiler used, the ``__FILE__`` macro may also expand | ||
| 57 | to an absolute filename in an out-of-tree build. Kbuild automatically | ||
| 58 | uses the ``-fmacro-prefix-map`` option to prevent this, if it is | ||
| 59 | supported. | ||
| 60 | |||
| 61 | The Reproducible Builds web site has more information about these | ||
| 62 | `prefix-map options`_. | ||
| 63 | |||
| 49 | Generated files in source packages | 64 | Generated files in source packages |
| 50 | ---------------------------------- | 65 | ---------------------------------- |
| 51 | 66 | ||
| @@ -116,5 +131,7 @@ See ``scripts/setlocalversion`` for details. · 64 unmodified lines | |||
| 116 | 131 | ||
| 117 | .. _KBUILD_BUILD_TIMESTAMP: kbuild.html#kbuild-build-timestamp | 132 | .. _KBUILD_BUILD_TIMESTAMP: kbuild.html#kbuild-build-timestamp |
| 118 | .. _KBUILD_BUILD_USER and KBUILD_BUILD_HOST: kbuild.html#kbuild-build-user-kbuild-build-host | 133 | .. _KBUILD_BUILD_USER and KBUILD_BUILD_HOST: kbuild.html#kbuild-build-user-kbuild-build-host |
| 134 | .. _KCFLAGS: kbuild.html#kcflags | ||
| 135 | .. _prefix-map options: https://reproducible-builds.org/docs/build-path/ | ||
| 119 | .. _Reproducible Builds project: https://reproducible-builds.org/ | 136 | .. _Reproducible Builds project: https://reproducible-builds.org/ |
| 120 | .. _SOURCE_DATE_EPOCH: https://reproducible-builds.org/docs/source-date-epoch/ | 137 | .. _SOURCE_DATE_EPOCH: https://reproducible-builds.org/docs/source-date-epoch/ |
| @@ -2017,7 +2017,8 @@ attribute-sets: · 2016 unmodified lines | |||
| 2017 | attributes: | 2017 | attributes: |
| 2018 | - | 2018 | - |
| 2019 | name: act | 2019 | name: act |
| 2020 | type: nest | 2020 | type: indexed-array |
| 2021 | sub-type: nest | ||
| 2021 | nested-attributes: tc-act-attrs | 2022 | nested-attributes: tc-act-attrs |
| 2022 | - | 2023 | - |
| 2023 | name: police | 2024 | name: police |
| @@ -2250,7 +2251,8 @@ attribute-sets: · 226 unmodified lines | |||
| 2250 | attributes: | 2251 | attributes: |
| 2251 | - | 2252 | - |
| 2252 | name: act | 2253 | name: act |
| 2253 | type: nest | 2254 | type: indexed-array |
| 2255 | sub-type: nest | ||
| 2254 | nested-attributes: tc-act-attrs | 2256 | nested-attributes: tc-act-attrs |
| 2255 | - | 2257 | - |
| 2256 | name: police | 2258 | name: police |
| @@ -2745,7 +2747,7 @@ attribute-sets: · 488 unmodified lines | |||
| 2745 | type: u16 | 2747 | type: u16 |
| 2746 | byte-order: big-endian | 2748 | byte-order: big-endian |
| 2747 | - | 2749 | - |
| 2748 | name: key-l2-tpv3-sid | 2750 | name: key-l2tpv3-sid |
| 2749 | type: u32 | 2751 | type: u32 |
| 2750 | byte-order: big-endian | 2752 | byte-order: big-endian |
| 2751 | - | 2753 | - |
| @@ -3504,7 +3506,7 @@ attribute-sets: · 752 unmodified lines | |||
| 3504 | name: rate64 | 3506 | name: rate64 |
| 3505 | type: u64 | 3507 | type: u64 |
| 3506 | - | 3508 | - |
| 3507 | name: prate4 | 3509 | name: prate64 |
| 3508 | type: u64 | 3510 | type: u64 |
| 3509 | - | 3511 | - |
| 3510 | name: burst | 3512 | name: burst |
| @@ -811,11 +811,9 @@ Documentation/devicetree/bindings/ptp/timestamper.txt for more details. · 810 unmodified lines | |||
| 811 | 3.2.4 Other caveats for MAC drivers | 811 | 3.2.4 Other caveats for MAC drivers |
| 812 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | 812 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ |
| 813 | 813 | ||
| 814 | Stacked PHCs, especially DSA (but not only) - since that doesn't require any | 814 | The use of stacked PHCs may uncover MAC driver bugs which were impossible to |
| 815 | modification to MAC drivers, so it is more difficult to ensure correctness of | 815 | trigger without them. One example has to do with this line of code, already |
| 816 | all possible code paths - is that they uncover bugs which were impossible to | 816 | presented earlier:: |
| 817 | trigger before the existence of stacked PTP clocks. One example has to do with | ||
| 818 | this line of code, already presented earlier:: | ||
| 819 | 817 | ||
| 820 | skb_shinfo(skb)->tx_flags |= SKBTX_IN_PROGRESS; | 818 | skb_shinfo(skb)->tx_flags |= SKBTX_IN_PROGRESS; |
| 821 | 819 | ||
| @@ -10147,6 +10147,13 @@ F: drivers/gpio/gpio-regmap.c · 10146 unmodified lines | |||
| 10147 | F: include/linux/gpio/regmap.h | 10147 | F: include/linux/gpio/regmap.h |
| 10148 | K: (devm_)?gpio_regmap_(un)?register | 10148 | K: (devm_)?gpio_regmap_(un)?register |
| 10149 | 10149 | ||
| 10150 | GPIO SLOPPY LOGIC ANALYZER | ||
| 10151 | M: Wolfram Sang <wsa+renesas@sang-engineering.com> | ||
| 10152 | S: Supported | ||
| 10153 | F: Documentation/dev-tools/gpio-sloppy-logic-analyzer.rst | ||
| 10154 | F: drivers/gpio/gpio-sloppy-logic-analyzer.c | ||
| 10155 | F: tools/gpio/gpio-sloppy-logic-analyzer.sh | ||
| 10156 | |||
| 10150 | GPIO SUBSYSTEM | 10157 | GPIO SUBSYSTEM |
| 10151 | M: Linus Walleij <linus.walleij@linaro.org> | 10158 | M: Linus Walleij <linus.walleij@linaro.org> |
| 10152 | M: Bartosz Golaszewski <brgl@bgdev.pl> | 10159 | M: Bartosz Golaszewski <brgl@bgdev.pl> |
| @@ -15542,6 +15549,18 @@ S: Maintained · 5389 unmodified lines | |||
| 15542 | F: include/linux/execmem.h | 15549 | F: include/linux/execmem.h |
| 15543 | F: mm/execmem.c | 15550 | F: mm/execmem.c |
| 15544 | 15551 | ||
| 15552 | MEMORY MANAGEMENT - GUP (GET USER PAGES) | ||
| 15553 | M: Andrew Morton <akpm@linux-foundation.org> | ||
| 15554 | M: David Hildenbrand <david@redhat.com> | ||
| 15555 | R: Jason Gunthorpe <jgg@nvidia.com> | ||
| 15556 | R: John Hubbard <jhubbard@nvidia.com> | ||
| 15557 | R: Peter Xu <peterx@redhat.com> | ||
| 15558 | L: linux-mm@kvack.org | ||
| 15559 | S: Maintained | ||
| 15560 | W: http://www.linux-mm.org | ||
| 15561 | T: git git://git.kernel.org/pub/scm/linux/kernel/git/akpm/mm | ||
| 15562 | F: mm/gup.c | ||
| 15563 | |||
| 15545 | MEMORY MANAGEMENT - NUMA MEMBLOCKS AND NUMA EMULATION | 15564 | MEMORY MANAGEMENT - NUMA MEMBLOCKS AND NUMA EMULATION |
| 15546 | M: Andrew Morton <akpm@linux-foundation.org> | 15565 | M: Andrew Morton <akpm@linux-foundation.org> |
| 15547 | M: Mike Rapoport <rppt@kernel.org> | 15566 | M: Mike Rapoport <rppt@kernel.org> |
| @@ -18432,7 +18451,7 @@ F: include/uapi/linux/ppdev.h · 2884 unmodified lines | |||
| 18432 | PARAVIRT_OPS INTERFACE | 18451 | PARAVIRT_OPS INTERFACE |
| 18433 | M: Juergen Gross <jgross@suse.com> | 18452 | M: Juergen Gross <jgross@suse.com> |
| 18434 | R: Ajay Kaher <ajay.kaher@broadcom.com> | 18453 | R: Ajay Kaher <ajay.kaher@broadcom.com> |
| 18435 | R: Alexey Makhalov <alexey.amakhalov@broadcom.com> | 18454 | R: Alexey Makhalov <alexey.makhalov@broadcom.com> |
| 18436 | R: Broadcom internal kernel review list <bcm-kernel-feedback-list@broadcom.com> | 18455 | R: Broadcom internal kernel review list <bcm-kernel-feedback-list@broadcom.com> |
| 18437 | L: virtualization@lists.linux.dev | 18456 | L: virtualization@lists.linux.dev |
| 18438 | L: x86@kernel.org | 18457 | L: x86@kernel.org |
| @@ -22916,7 +22935,6 @@ F: drivers/accessibility/speakup/ · 4477 unmodified lines | |||
| 22916 | 22935 | ||
| 22917 | SPEAR PLATFORM/CLOCK/PINCTRL SUPPORT | 22936 | SPEAR PLATFORM/CLOCK/PINCTRL SUPPORT |
| 22918 | M: Viresh Kumar <vireshk@kernel.org> | 22937 | M: Viresh Kumar <vireshk@kernel.org> |
| 22919 | M: Shiraz Hashim <shiraz.linux.kernel@gmail.com> | ||
| 22920 | L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) | 22938 | L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) |
| 22921 | L: soc@lists.linux.dev | 22939 | L: soc@lists.linux.dev |
| 22922 | S: Maintained | 22940 | S: Maintained |
| @@ -25918,7 +25936,7 @@ F: drivers/misc/vmw_balloon.c · 2995 unmodified lines | |||
| 25918 | 25936 | ||
| 25919 | VMWARE HYPERVISOR INTERFACE | 25937 | VMWARE HYPERVISOR INTERFACE |
| 25920 | M: Ajay Kaher <ajay.kaher@broadcom.com> | 25938 | M: Ajay Kaher <ajay.kaher@broadcom.com> |
| 25921 | M: Alexey Makhalov <alexey.amakhalov@broadcom.com> | 25939 | M: Alexey Makhalov <alexey.makhalov@broadcom.com> |
| 25922 | R: Broadcom internal kernel review list <bcm-kernel-feedback-list@broadcom.com> | 25940 | R: Broadcom internal kernel review list <bcm-kernel-feedback-list@broadcom.com> |
| 25923 | L: virtualization@lists.linux.dev | 25941 | L: virtualization@lists.linux.dev |
| 25924 | L: x86@kernel.org | 25942 | L: x86@kernel.org |
| @@ -25946,7 +25964,7 @@ F: drivers/scsi/vmw_pvscsi.h · 21 unmodified lines | |||
| 25946 | VMWARE VIRTUAL PTP CLOCK DRIVER | 25964 | VMWARE VIRTUAL PTP CLOCK DRIVER |
| 25947 | M: Nick Shi <nick.shi@broadcom.com> | 25965 | M: Nick Shi <nick.shi@broadcom.com> |
| 25948 | R: Ajay Kaher <ajay.kaher@broadcom.com> | 25966 | R: Ajay Kaher <ajay.kaher@broadcom.com> |
| 25949 | R: Alexey Makhalov <alexey.amakhalov@broadcom.com> | 25967 | R: Alexey Makhalov <alexey.makhalov@broadcom.com> |
| 25950 | R: Broadcom internal kernel review list <bcm-kernel-feedback-list@broadcom.com> | 25968 | R: Broadcom internal kernel review list <bcm-kernel-feedback-list@broadcom.com> |
| 25951 | L: netdev@vger.kernel.org | 25969 | L: netdev@vger.kernel.org |
| 25952 | S: Supported | 25970 | S: Supported |
| @@ -2,7 +2,7 @@ · 1 unmodified line | |||
| 2 | VERSION = 6 | 2 | VERSION = 6 |
| 3 | PATCHLEVEL = 15 | 3 | PATCHLEVEL = 15 |
| 4 | SUBLEVEL = 0 | 4 | SUBLEVEL = 0 |
| 5 | EXTRAVERSION = -rc6 | 5 | EXTRAVERSION = -rc7 |
| 6 | NAME = Baby Opossum Posse | 6 | NAME = Baby Opossum Posse |
| 7 | 7 | ||
| 8 | # *DOCUMENTATION* | 8 | # *DOCUMENTATION* |
| @@ -1068,8 +1068,7 @@ KBUILD_CFLAGS += -fno-builtin-wcslen · 1059 unmodified lines | |||
| 1068 | 1068 | ||
| 1069 | # change __FILE__ to the relative path to the source directory | 1069 | # change __FILE__ to the relative path to the source directory |
| 1070 | ifdef building_out_of_srctree | 1070 | ifdef building_out_of_srctree |
| 1071 | KBUILD_CPPFLAGS += $(call cc-option,-ffile-prefix-map=$(srcroot)/=) | 1071 | KBUILD_CPPFLAGS += $(call cc-option,-fmacro-prefix-map=$(srcroot)/=) |
| 1072 | KBUILD_RUSTFLAGS += --remap-path-prefix=$(srcroot)/= | ||
| 1073 | endif | 1072 | endif |
| 1074 | 1073 | ||
| 1075 | # include additional Makefiles when needed | 1074 | # include additional Makefiles when needed |
| @@ -451,7 +451,7 @@ · 450 unmodified lines | |||
| 451 | pwm_ef: pwm@86c0 { | 451 | pwm_ef: pwm@86c0 { |
| 452 | compatible = "amlogic,meson8-pwm-v2"; | 452 | compatible = "amlogic,meson8-pwm-v2"; |
| 453 | clocks = <&xtal>, | 453 | clocks = <&xtal>, |
| 454 | <>, /* unknown/untested, the datasheet calls it "Video PLL" */ | 454 | <0>, /* unknown/untested, the datasheet calls it "Video PLL" */ |
| 455 | <&clkc CLKID_FCLK_DIV4>, | 455 | <&clkc CLKID_FCLK_DIV4>, |
| 456 | <&clkc CLKID_FCLK_DIV3>; | 456 | <&clkc CLKID_FCLK_DIV3>; |
| 457 | reg = <0x86c0 0x10>; | 457 | reg = <0x86c0 0x10>; |
| @@ -705,7 +705,7 @@ · 247 unmodified lines | |||
| 705 | &pwm_ab { | 705 | &pwm_ab { |
| 706 | compatible = "amlogic,meson8-pwm-v2"; | 706 | compatible = "amlogic,meson8-pwm-v2"; |
| 707 | clocks = <&xtal>, | 707 | clocks = <&xtal>, |
| 708 | <>, /* unknown/untested, the datasheet calls it "Video PLL" */ | 708 | <0>, /* unknown/untested, the datasheet calls it "Video PLL" */ |
| 709 | <&clkc CLKID_FCLK_DIV4>, | 709 | <&clkc CLKID_FCLK_DIV4>, |
| 710 | <&clkc CLKID_FCLK_DIV3>; | 710 | <&clkc CLKID_FCLK_DIV3>; |
| 711 | }; | 711 | }; |
| @@ -713,7 +713,7 @@ · 1 unmodified line | |||
| 713 | &pwm_cd { | 713 | &pwm_cd { |
| 714 | compatible = "amlogic,meson8-pwm-v2"; | 714 | compatible = "amlogic,meson8-pwm-v2"; |
| 715 | clocks = <&xtal>, | 715 | clocks = <&xtal>, |
| 716 | <>, /* unknown/untested, the datasheet calls it "Video PLL" */ | 716 | <0>, /* unknown/untested, the datasheet calls it "Video PLL" */ |
| 717 | <&clkc CLKID_FCLK_DIV4>, | 717 | <&clkc CLKID_FCLK_DIV4>, |
| 718 | <&clkc CLKID_FCLK_DIV3>; | 718 | <&clkc CLKID_FCLK_DIV3>; |
| 719 | }; | 719 | }; |
| @@ -406,7 +406,7 @@ · 405 unmodified lines | |||
| 406 | compatible = "amlogic,meson8b-pwm-v2", "amlogic,meson8-pwm-v2"; | 406 | compatible = "amlogic,meson8b-pwm-v2", "amlogic,meson8-pwm-v2"; |
| 407 | reg = <0x86c0 0x10>; | 407 | reg = <0x86c0 0x10>; |
| 408 | clocks = <&xtal>, | 408 | clocks = <&xtal>, |
| 409 | <>, /* unknown/untested, the datasheet calls it "Video PLL" */ | 409 | <0>, /* unknown/untested, the datasheet calls it "Video PLL" */ |
| 410 | <&clkc CLKID_FCLK_DIV4>, | 410 | <&clkc CLKID_FCLK_DIV4>, |
| 411 | <&clkc CLKID_FCLK_DIV3>; | 411 | <&clkc CLKID_FCLK_DIV3>; |
| 412 | #pwm-cells = <3>; | 412 | #pwm-cells = <3>; |
| @@ -680,7 +680,7 @@ · 267 unmodified lines | |||
| 680 | &pwm_ab { | 680 | &pwm_ab { |
| 681 | compatible = "amlogic,meson8b-pwm-v2", "amlogic,meson8-pwm-v2"; | 681 | compatible = "amlogic,meson8b-pwm-v2", "amlogic,meson8-pwm-v2"; |
| 682 | clocks = <&xtal>, | 682 | clocks = <&xtal>, |
| 683 | <>, /* unknown/untested, the datasheet calls it "Video PLL" */ | 683 | <0>, /* unknown/untested, the datasheet calls it "Video PLL" */ |
| 684 | <&clkc CLKID_FCLK_DIV4>, | 684 | <&clkc CLKID_FCLK_DIV4>, |
| 685 | <&clkc CLKID_FCLK_DIV3>; | 685 | <&clkc CLKID_FCLK_DIV3>; |
| 686 | }; | 686 | }; |
| @@ -688,7 +688,7 @@ · 1 unmodified line | |||
| 688 | &pwm_cd { | 688 | &pwm_cd { |
| 689 | compatible = "amlogic,meson8b-pwm-v2", "amlogic,meson8-pwm-v2"; | 689 | compatible = "amlogic,meson8b-pwm-v2", "amlogic,meson8-pwm-v2"; |
| 690 | clocks = <&xtal>, | 690 | clocks = <&xtal>, |
| 691 | <>, /* unknown/untested, the datasheet calls it "Video PLL" */ | 691 | <0>, /* unknown/untested, the datasheet calls it "Video PLL" */ |
| 692 | <&clkc CLKID_FCLK_DIV4>, | 692 | <&clkc CLKID_FCLK_DIV4>, |
| 693 | <&clkc CLKID_FCLK_DIV3>; | 693 | <&clkc CLKID_FCLK_DIV3>; |
| 694 | }; | 694 | }; |
| @@ -151,7 +151,7 @@ · 150 unmodified lines | |||
| 151 | al,msi-num-spis = <160>; | 151 | al,msi-num-spis = <160>; |
| 152 | }; | 152 | }; |
| 153 | 153 | ||
| 154 | io-fabric@fc000000 { | 154 | io-bus@fc000000 { |
| 155 | compatible = "simple-bus"; | 155 | compatible = "simple-bus"; |
| 156 | #address-cells = <1>; | 156 | #address-cells = <1>; |
| 157 | #size-cells = <1>; | 157 | #size-cells = <1>; |
| @@ -361,7 +361,7 @@ · 360 unmodified lines | |||
| 361 | interrupt-parent = <&gic>; | 361 | interrupt-parent = <&gic>; |
| 362 | }; | 362 | }; |
| 363 | 363 | ||
| 364 | io-fabric@fc000000 { | 364 | io-bus@fc000000 { |
| 365 | compatible = "simple-bus"; | 365 | compatible = "simple-bus"; |
| 366 | #address-cells = <1>; | 366 | #address-cells = <1>; |
| 367 | #size-cells = <1>; | 367 | #size-cells = <1>; |
| @@ -2313,7 +2313,7 @@ · 2312 unmodified lines | |||
| 2313 | "amlogic,meson8-pwm-v2"; | 2313 | "amlogic,meson8-pwm-v2"; |
| 2314 | reg = <0x0 0x19000 0x0 0x20>; | 2314 | reg = <0x0 0x19000 0x0 0x20>; |
| 2315 | clocks = <&xtal>, | 2315 | clocks = <&xtal>, |
| 2316 | <>, /* unknown/untested, the datasheet calls it "vid_pll" */ | 2316 | <0>, /* unknown/untested, the datasheet calls it "vid_pll" */ |
| 2317 | <&clkc CLKID_FCLK_DIV4>, | 2317 | <&clkc CLKID_FCLK_DIV4>, |
| 2318 | <&clkc CLKID_FCLK_DIV3>; | 2318 | <&clkc CLKID_FCLK_DIV3>; |
| 2319 | #pwm-cells = <3>; | 2319 | #pwm-cells = <3>; |
| @@ -2325,7 +2325,7 @@ · 5 unmodified lines | |||
| 2325 | "amlogic,meson8-pwm-v2"; | 2325 | "amlogic,meson8-pwm-v2"; |
| 2326 | reg = <0x0 0x1a000 0x0 0x20>; | 2326 | reg = <0x0 0x1a000 0x0 0x20>; |
| 2327 | clocks = <&xtal>, | 2327 | clocks = <&xtal>, |
| 2328 | <>, /* unknown/untested, the datasheet calls it "vid_pll" */ | 2328 | <0>, /* unknown/untested, the datasheet calls it "vid_pll" */ |
| 2329 | <&clkc CLKID_FCLK_DIV4>, | 2329 | <&clkc CLKID_FCLK_DIV4>, |
| 2330 | <&clkc CLKID_FCLK_DIV3>; | 2330 | <&clkc CLKID_FCLK_DIV3>; |
| 2331 | #pwm-cells = <3>; | 2331 | #pwm-cells = <3>; |
| @@ -2337,7 +2337,7 @@ · 5 unmodified lines | |||
| 2337 | "amlogic,meson8-pwm-v2"; | 2337 | "amlogic,meson8-pwm-v2"; |
| 2338 | reg = <0x0 0x1b000 0x0 0x20>; | 2338 | reg = <0x0 0x1b000 0x0 0x20>; |
| 2339 | clocks = <&xtal>, | 2339 | clocks = <&xtal>, |
| 2340 | <>, /* unknown/untested, the datasheet calls it "vid_pll" */ | 2340 | <0>, /* unknown/untested, the datasheet calls it "vid_pll" */ |
| 2341 | <&clkc CLKID_FCLK_DIV4>, | 2341 | <&clkc CLKID_FCLK_DIV4>, |
| 2342 | <&clkc CLKID_FCLK_DIV3>; | 2342 | <&clkc CLKID_FCLK_DIV3>; |
| 2343 | #pwm-cells = <3>; | 2343 | #pwm-cells = <3>; |
| @@ -116,6 +116,10 @@ · 115 unmodified lines | |||
| 116 | status = "okay"; | 116 | status = "okay"; |
| 117 | }; | 117 | }; |
| 118 | 118 | ||
| 119 | &clkc_audio { | ||
| 120 | status = "okay"; | ||
| 121 | }; | ||
| 122 | |||
| 119 | &frddr_a { | 123 | &frddr_a { |
| 120 | status = "okay"; | 124 | status = "okay"; |
| 121 | }; | 125 | }; |
| @@ -741,7 +741,7 @@ · 740 unmodified lines | |||
| 741 | 741 | ||
| 742 | &pwm_ab { | 742 | &pwm_ab { |
| 743 | clocks = <&xtal>, | 743 | clocks = <&xtal>, |
| 744 | <>, /* unknown/untested, the datasheet calls it "vid_pll" */ | 744 | <0>, /* unknown/untested, the datasheet calls it "vid_pll" */ |
| 745 | <&clkc CLKID_FCLK_DIV4>, | 745 | <&clkc CLKID_FCLK_DIV4>, |
| 746 | <&clkc CLKID_FCLK_DIV3>; | 746 | <&clkc CLKID_FCLK_DIV3>; |
| 747 | }; | 747 | }; |
| @@ -752,14 +752,14 @@ · 4 unmodified lines | |||
| 752 | 752 | ||
| 753 | &pwm_cd { | 753 | &pwm_cd { |
| 754 | clocks = <&xtal>, | 754 | clocks = <&xtal>, |
| 755 | <>, /* unknown/untested, the datasheet calls it "vid_pll" */ | 755 | <0>, /* unknown/untested, the datasheet calls it "vid_pll" */ |
| 756 | <&clkc CLKID_FCLK_DIV4>, | 756 | <&clkc CLKID_FCLK_DIV4>, |
| 757 | <&clkc CLKID_FCLK_DIV3>; | 757 | <&clkc CLKID_FCLK_DIV3>; |
| 758 | }; | 758 | }; |
| 759 | 759 | ||
| 760 | &pwm_ef { | 760 | &pwm_ef { |
| 761 | clocks = <&xtal>, | 761 | clocks = <&xtal>, |
| 762 | <>, /* unknown/untested, the datasheet calls it "vid_pll" */ | 762 | <0>, /* unknown/untested, the datasheet calls it "vid_pll" */ |
| 763 | <&clkc CLKID_FCLK_DIV4>, | 763 | <&clkc CLKID_FCLK_DIV4>, |
| 764 | <&clkc CLKID_FCLK_DIV3>; | 764 | <&clkc CLKID_FCLK_DIV3>; |
| 765 | }; | 765 | }; |
| @@ -811,7 +811,7 @@ · 810 unmodified lines | |||
| 811 | 811 | ||
| 812 | &pwm_ab { | 812 | &pwm_ab { |
| 813 | clocks = <&xtal>, | 813 | clocks = <&xtal>, |
| 814 | <>, /* unknown/untested, the datasheet calls it "vid_pll" */ | 814 | <0>, /* unknown/untested, the datasheet calls it "vid_pll" */ |
| 815 | <&clkc CLKID_FCLK_DIV4>, | 815 | <&clkc CLKID_FCLK_DIV4>, |
| 816 | <&clkc CLKID_FCLK_DIV3>; | 816 | <&clkc CLKID_FCLK_DIV3>; |
| 817 | }; | 817 | }; |
| @@ -822,14 +822,14 @@ · 4 unmodified lines | |||
| 822 | 822 | ||
| 823 | &pwm_cd { | 823 | &pwm_cd { |
| 824 | clocks = <&xtal>, | 824 | clocks = <&xtal>, |
| 825 | <>, /* unknown/untested, the datasheet calls it "vid_pll" */ | 825 | <0>, /* unknown/untested, the datasheet calls it "vid_pll" */ |
| 826 | <&clkc CLKID_FCLK_DIV4>, | 826 | <&clkc CLKID_FCLK_DIV4>, |
| 827 | <&clkc CLKID_FCLK_DIV3>; | 827 | <&clkc CLKID_FCLK_DIV3>; |
| 828 | }; | 828 | }; |
| 829 | 829 | ||
| 830 | &pwm_ef { | 830 | &pwm_ef { |
| 831 | clocks = <&xtal>, | 831 | clocks = <&xtal>, |
| 832 | <>, /* unknown/untested, the datasheet calls it "vid_pll" */ | 832 | <0>, /* unknown/untested, the datasheet calls it "vid_pll" */ |
| 833 | <&clkc CLKID_FCLK_DIV4>, | 833 | <&clkc CLKID_FCLK_DIV4>, |
| 834 | <&clkc CLKID_FCLK_DIV3>; | 834 | <&clkc CLKID_FCLK_DIV3>; |
| 835 | }; | 835 | }; |
| @@ -77,6 +77,16 @@ · 76 unmodified lines | |||
| 77 | }; | 77 | }; |
| 78 | }; | 78 | }; |
| 79 | 79 | ||
| 80 | /* | ||
| 81 | * The driver depends on boot loader initialized state which resets when this | ||
| 82 | * power-domain is powered off. This happens on suspend or when the driver is | ||
| 83 | * missing during boot. Mark the domain as always on until the driver can | ||
| 84 | * handle this. | ||
| 85 | */ | ||
| 86 | &ps_dispdfr_be { | ||
| 87 | apple,always-on; | ||
| 88 | }; | ||
| 89 | |||
| 80 | &display_dfr { | 90 | &display_dfr { |
| 81 | status = "okay"; | 91 | status = "okay"; |
| 82 | }; | 92 | }; |
| @@ -40,6 +40,16 @@ · 39 unmodified lines | |||
| 40 | }; | 40 | }; |
| 41 | }; | 41 | }; |
| 42 | 42 | ||
| 43 | /* | ||
| 44 | * The driver depends on boot loader initialized state which resets when this | ||
| 45 | * power-domain is powered off. This happens on suspend or when the driver is | ||
| 46 | * missing during boot. Mark the domain as always on until the driver can | ||
| 47 | * handle this. | ||
| 48 | */ | ||
| 49 | &ps_dispdfr_be { | ||
| 50 | apple,always-on; | ||
| 51 | }; | ||
| 52 | |||
| 43 | &display_dfr { | 53 | &display_dfr { |
| 44 | status = "okay"; | 54 | status = "okay"; |
| 45 | }; | 55 | }; |
| @@ -88,3 +88,5 @@ · 87 unmodified lines | |||
| 88 | <0>, <0>, <400000000>, | 88 | <0>, <0>, <400000000>, |
| 89 | <1039500000>; | 89 | <1039500000>; |
| 90 | }; | 90 | }; |
| 91 | |||
| 92 | /delete-node/ &{noc_opp_table/opp-1000000000}; | ||
| @@ -35,7 +35,6 @@ · 34 unmodified lines | |||
| 35 | <0x1 0x00000000 0 0xc0000000>; | 35 | <0x1 0x00000000 0 0xc0000000>; |
| 36 | }; | 36 | }; |
| 37 | 37 | ||
| 38 | |||
| 39 | reg_usdhc2_vmmc: regulator-usdhc2-vmmc { | 38 | reg_usdhc2_vmmc: regulator-usdhc2-vmmc { |
| 40 | compatible = "regulator-fixed"; | 39 | compatible = "regulator-fixed"; |
| 41 | regulator-name = "VSD_3V3"; | 40 | regulator-name = "VSD_3V3"; |
| @@ -46,6 +45,16 @@ · 4 unmodified lines | |||
| 46 | startup-delay-us = <100>; | 45 | startup-delay-us = <100>; |
| 47 | off-on-delay-us = <12000>; | 46 | off-on-delay-us = <12000>; |
| 48 | }; | 47 | }; |
| 48 | |||
| 49 | reg_usdhc2_vqmmc: regulator-usdhc2-vqmmc { | ||
| 50 | compatible = "regulator-gpio"; | ||
| 51 | regulator-name = "VSD_VSEL"; | ||
| 52 | regulator-min-microvolt = <1800000>; | ||
| 53 | regulator-max-microvolt = <3300000>; | ||
| 54 | gpios = <&gpio2 12 GPIO_ACTIVE_HIGH>; | ||
| 55 | states = <3300000 0x0 1800000 0x1>; | ||
| 56 | vin-supply = <&ldo5>; | ||
| 57 | }; | ||
| 49 | }; | 58 | }; |
| 50 | 59 | ||
| 51 | &A53_0 { | 60 | &A53_0 { |
| @@ -205,6 +214,7 @@ · 153 unmodified lines | |||
| 205 | pinctrl-2 = <&pinctrl_usdhc2_200mhz>, <&pinctrl_usdhc2_gpio>; | 214 | pinctrl-2 = <&pinctrl_usdhc2_200mhz>, <&pinctrl_usdhc2_gpio>; |
| 206 | cd-gpios = <&gpio1 14 GPIO_ACTIVE_LOW>; | 215 | cd-gpios = <&gpio1 14 GPIO_ACTIVE_LOW>; |
| 207 | vmmc-supply = <®_usdhc2_vmmc>; | 216 | vmmc-supply = <®_usdhc2_vmmc>; |
| 217 | vqmmc-supply = <®_usdhc2_vqmmc>; | ||
| 208 | bus-width = <4>; | 218 | bus-width = <4>; |
| 209 | status = "okay"; | 219 | status = "okay"; |
| 210 | }; | 220 | }; |
| @@ -1645,6 +1645,12 @@ · 1644 unmodified lines | |||
| 1645 | opp-hz = /bits/ 64 <200000000>; | 1645 | opp-hz = /bits/ 64 <200000000>; |
| 1646 | }; | 1646 | }; |
| 1647 | 1647 | ||
| 1648 | /* Nominal drive mode maximum */ | ||
| 1649 | opp-800000000 { | ||
| 1650 | opp-hz = /bits/ 64 <800000000>; | ||
| 1651 | }; | ||
| 1652 | |||
| 1653 | /* Overdrive mode maximum */ | ||
| 1648 | opp-1000000000 { | 1654 | opp-1000000000 { |
| 1649 | opp-hz = /bits/ 64 <1000000000>; | 1655 | opp-hz = /bits/ 64 <1000000000>; |
| 1650 | }; | 1656 | }; |
| @@ -31,7 +31,7 @@ · 30 unmodified lines | |||
| 31 | }; | 31 | }; |
| 32 | 32 | ||
| 33 | vcc3v3_btreg: vcc3v3-btreg { | 33 | vcc3v3_btreg: vcc3v3-btreg { |
| 34 | compatible = "regulator-gpio"; | 34 | compatible = "regulator-fixed"; |
| 35 | enable-active-high; | 35 | enable-active-high; |
| 36 | pinctrl-names = "default"; | 36 | pinctrl-names = "default"; |
| 37 | pinctrl-0 = <&bt_enable_h>; | 37 | pinctrl-0 = <&bt_enable_h>; |
| @@ -39,7 +39,6 @@ · 1 unmodified line | |||
| 39 | regulator-min-microvolt = <3300000>; | 39 | regulator-min-microvolt = <3300000>; |
| 40 | regulator-max-microvolt = <3300000>; | 40 | regulator-max-microvolt = <3300000>; |
| 41 | regulator-always-on; | 41 | regulator-always-on; |
| 42 | states = <3300000 0x0>; | ||
| 43 | }; | 42 | }; |
| 44 | 43 | ||
| 45 | vcc3v3_rf_aux_mod: regulator-vcc3v3-rf-aux-mod { | 44 | vcc3v3_rf_aux_mod: regulator-vcc3v3-rf-aux-mod { |
| @@ -26,5 +26,5 @@ · 25 unmodified lines | |||
| 26 | }; | 26 | }; |
| 27 | 27 | ||
| 28 | &vcc3v3_btreg { | 28 | &vcc3v3_btreg { |
| 29 | enable-gpios = <&gpio1 RK_PC3 GPIO_ACTIVE_HIGH>; | 29 | gpios = <&gpio1 RK_PC3 GPIO_ACTIVE_HIGH>; |
| 30 | }; | 30 | }; |
| @@ -39,5 +39,5 @@ · 38 unmodified lines | |||
| 39 | }; | 39 | }; |
| 40 | 40 | ||
| 41 | &vcc3v3_btreg { | 41 | &vcc3v3_btreg { |
| 42 | enable-gpios = <&gpio1 RK_PC2 GPIO_ACTIVE_HIGH>; | 42 | gpios = <&gpio1 RK_PC2 GPIO_ACTIVE_HIGH>; |
| 43 | }; | 43 | }; |
| @@ -43,7 +43,7 @@ · 42 unmodified lines | |||
| 43 | sdio_pwrseq: sdio-pwrseq { | 43 | sdio_pwrseq: sdio-pwrseq { |
| 44 | compatible = "mmc-pwrseq-simple"; | 44 | compatible = "mmc-pwrseq-simple"; |
| 45 | clocks = <&rk808 1>; | 45 | clocks = <&rk808 1>; |
| 46 | clock-names = "lpo"; | 46 | clock-names = "ext_clock"; |
| 47 | pinctrl-names = "default"; | 47 | pinctrl-names = "default"; |
| 48 | pinctrl-0 = <&wifi_enable_h>; | 48 | pinctrl-0 = <&wifi_enable_h>; |
| 49 | reset-gpios = <&gpio0 RK_PB2 GPIO_ACTIVE_LOW>; | 49 | reset-gpios = <&gpio0 RK_PB2 GPIO_ACTIVE_LOW>; |
| @@ -775,7 +775,7 @@ · 774 unmodified lines | |||
| 775 | rockchip,default-sample-phase = <90>; | 775 | rockchip,default-sample-phase = <90>; |
| 776 | status = "okay"; | 776 | status = "okay"; |
| 777 | 777 | ||
| 778 | sdio-wifi@1 { | 778 | wifi@1 { |
| 779 | compatible = "brcm,bcm4329-fmac"; | 779 | compatible = "brcm,bcm4329-fmac"; |
| 780 | reg = <1>; | 780 | reg = <1>; |
| 781 | interrupt-parent = <&gpio2>; | 781 | interrupt-parent = <&gpio2>; |
| @@ -619,6 +619,8 @@ · 618 unmodified lines | |||
| 619 | bus-width = <8>; | 619 | bus-width = <8>; |
| 620 | max-frequency = <200000000>; | 620 | max-frequency = <200000000>; |
| 621 | non-removable; | 621 | non-removable; |
| 622 | pinctrl-names = "default"; | ||
| 623 | pinctrl-0 = <&emmc_bus8 &emmc_clk &emmc_cmd &emmc_datastrobe>; | ||
| 622 | status = "okay"; | 624 | status = "okay"; |
| 623 | }; | 625 | }; |
| 624 | 626 | ||
| @@ -610,7 +610,7 @@ · 609 unmodified lines | |||
| 610 | reg = <0x51>; | 610 | reg = <0x51>; |
| 611 | clock-output-names = "hym8563"; | 611 | clock-output-names = "hym8563"; |
| 612 | interrupt-parent = <&gpio0>; | 612 | interrupt-parent = <&gpio0>; |
| 613 | interrupts = <RK_PB0 IRQ_TYPE_LEVEL_LOW>; | 613 | interrupts = <RK_PA0 IRQ_TYPE_LEVEL_LOW>; |
| 614 | pinctrl-names = "default"; | 614 | pinctrl-names = "default"; |
| 615 | pinctrl-0 = <&hym8563_int>; | 615 | pinctrl-0 = <&hym8563_int>; |
| 616 | wakeup-source; | 616 | wakeup-source; |
| @@ -222,6 +222,10 @@ · 221 unmodified lines | |||
| 222 | compatible = "realtek,rt5616"; | 222 | compatible = "realtek,rt5616"; |
| 223 | reg = <0x1b>; | 223 | reg = <0x1b>; |
| 224 | #sound-dai-cells = <0>; | 224 | #sound-dai-cells = <0>; |
| 225 | assigned-clocks = <&cru I2S0_8CH_MCLKOUT>; | ||
| 226 | assigned-clock-rates = <12288000>; | ||
| 227 | clocks = <&cru I2S0_8CH_MCLKOUT>; | ||
| 228 | clock-names = "mclk"; | ||
| 225 | }; | 229 | }; |
| 226 | }; | 230 | }; |
| 227 | 231 | ||
| @@ -214,6 +214,8 @@ · 213 unmodified lines | |||
| 214 | }; | 214 | }; |
| 215 | 215 | ||
| 216 | &package_thermal { | 216 | &package_thermal { |
| 217 | polling-delay = <1000>; | ||
| 218 | |||
| 217 | trips { | 219 | trips { |
| 218 | package_active1: trip-active1 { | 220 | package_active1: trip-active1 { |
| 219 | temperature = <45000>; | 221 | temperature = <45000>; |
| @@ -11,20 +11,15 @@ · 10 unmodified lines | |||
| 11 | compatible = "operating-points-v2"; | 11 | compatible = "operating-points-v2"; |
| 12 | opp-shared; | 12 | opp-shared; |
| 13 | 13 | ||
| 14 | opp-1416000000 { | 14 | opp-1200000000 { |
| 15 | opp-hz = /bits/ 64 <1416000000>; | 15 | opp-hz = /bits/ 64 <1200000000>; |
| 16 | opp-microvolt = <750000 750000 950000>; | 16 | opp-microvolt = <750000 750000 950000>; |
| 17 | clock-latency-ns = <40000>; | 17 | clock-latency-ns = <40000>; |
| 18 | opp-suspend; | 18 | opp-suspend; |
| 19 | }; | 19 | }; |
| 20 | opp-1608000000 { | 20 | opp-1296000000 { |
| 21 | opp-hz = /bits/ 64 <1608000000>; | 21 | opp-hz = /bits/ 64 <1296000000>; |
| 22 | opp-microvolt = <887500 887500 950000>; | 22 | opp-microvolt = <775000 775000 950000>; |
| 23 | clock-latency-ns = <40000>; | ||
| 24 | }; | ||
| 25 | opp-1704000000 { | ||
| 26 | opp-hz = /bits/ 64 <1704000000>; | ||
| 27 | opp-microvolt = <937500 937500 950000>; | ||
| 28 | clock-latency-ns = <40000>; | 23 | clock-latency-ns = <40000>; |
| 29 | }; | 24 | }; |
| 30 | }; | 25 | }; |
| @@ -33,9 +28,14 @@ · 2 unmodified lines | |||
| 33 | compatible = "operating-points-v2"; | 28 | compatible = "operating-points-v2"; |
| 34 | opp-shared; | 29 | opp-shared; |
| 35 | 30 | ||
| 31 | opp-1200000000{ | ||
| 32 | opp-hz = /bits/ 64 <1200000000>; | ||
| 33 | opp-microvolt = <750000 750000 950000>; | ||
| 34 | clock-latency-ns = <40000>; | ||
| 35 | }; | ||
| 36 | opp-1416000000 { | 36 | opp-1416000000 { |
| 37 | opp-hz = /bits/ 64 <1416000000>; | 37 | opp-hz = /bits/ 64 <1416000000>; |
| 38 | opp-microvolt = <750000 750000 950000>; | 38 | opp-microvolt = <762500 762500 950000>; |
| 39 | clock-latency-ns = <40000>; | 39 | clock-latency-ns = <40000>; |
| 40 | }; | 40 | }; |
| 41 | opp-1608000000 { | 41 | opp-1608000000 { |
| @@ -43,25 +43,20 @@ · 1 unmodified line | |||
| 43 | opp-microvolt = <787500 787500 950000>; | 43 | opp-microvolt = <787500 787500 950000>; |
| 44 | clock-latency-ns = <40000>; | 44 | clock-latency-ns = <40000>; |
| 45 | }; | 45 | }; |
| 46 | opp-1800000000 { | ||
| 47 | opp-hz = /bits/ 64 <1800000000>; | ||
| 48 | opp-microvolt = <875000 875000 950000>; | ||
| 49 | clock-latency-ns = <40000>; | ||
| 50 | }; | ||
| 51 | opp-2016000000 { | ||
| 52 | opp-hz = /bits/ 64 <2016000000>; | ||
| 53 | opp-microvolt = <950000 950000 950000>; | ||
| 54 | clock-latency-ns = <40000>; | ||
| 55 | }; | ||
| 56 | }; | 46 | }; |
| 57 | 47 | ||
| 58 | cluster2_opp_table: opp-table-cluster2 { | 48 | cluster2_opp_table: opp-table-cluster2 { |
| 59 | compatible = "operating-points-v2"; | 49 | compatible = "operating-points-v2"; |
| 60 | opp-shared; | 50 | opp-shared; |
| 61 | 51 | ||
| 52 | opp-1200000000{ | ||
| 53 | opp-hz = /bits/ 64 <1200000000>; | ||
| 54 | opp-microvolt = <750000 750000 950000>; | ||
| 55 | clock-latency-ns = <40000>; | ||
| 56 | }; | ||
| 62 | opp-1416000000 { | 57 | opp-1416000000 { |
| 63 | opp-hz = /bits/ 64 <1416000000>; | 58 | opp-hz = /bits/ 64 <1416000000>; |
| 64 | opp-microvolt = <750000 750000 950000>; | 59 | opp-microvolt = <762500 762500 950000>; |
| 65 | clock-latency-ns = <40000>; | 60 | clock-latency-ns = <40000>; |
| 66 | }; | 61 | }; |
| 67 | opp-1608000000 { | 62 | opp-1608000000 { |
| @@ -69,16 +64,6 @@ · 1 unmodified line | |||
| 69 | opp-microvolt = <787500 787500 950000>; | 64 | opp-microvolt = <787500 787500 950000>; |
| 70 | clock-latency-ns = <40000>; | 65 | clock-latency-ns = <40000>; |
| 71 | }; | 66 | }; |
| 72 | opp-1800000000 { | ||
| 73 | opp-hz = /bits/ 64 <1800000000>; | ||
| 74 | opp-microvolt = <875000 875000 950000>; | ||
| 75 | clock-latency-ns = <40000>; | ||
| 76 | }; | ||
| 77 | opp-2016000000 { | ||
| 78 | opp-hz = /bits/ 64 <2016000000>; | ||
| 79 | opp-microvolt = <950000 950000 950000>; | ||
| 80 | clock-latency-ns = <40000>; | ||
| 81 | }; | ||
| 82 | }; | 67 | }; |
| 83 | 68 | ||
| 84 | gpu_opp_table: opp-table { | 69 | gpu_opp_table: opp-table { |
| @@ -104,10 +89,6 @@ · 19 unmodified lines | |||
| 104 | opp-hz = /bits/ 64 <700000000>; | 89 | opp-hz = /bits/ 64 <700000000>; |
| 105 | opp-microvolt = <750000 750000 850000>; | 90 | opp-microvolt = <750000 750000 850000>; |
| 106 | }; | 91 | }; |
| 107 | opp-850000000 { | ||
| 108 | opp-hz = /bits/ 64 <800000000>; | ||
| 109 | opp-microvolt = <787500 787500 850000>; | ||
| 110 | }; | ||
| 111 | }; | 92 | }; |
| 112 | }; | 93 | }; |
| 113 | 94 | ||
| @@ -81,6 +81,7 @@ · 80 unmodified lines | |||
| 81 | #define ARM_CPU_PART_CORTEX_A78AE 0xD42 | 81 | #define ARM_CPU_PART_CORTEX_A78AE 0xD42 |
| 82 | #define ARM_CPU_PART_CORTEX_X1 0xD44 | 82 | #define ARM_CPU_PART_CORTEX_X1 0xD44 |
| 83 | #define ARM_CPU_PART_CORTEX_A510 0xD46 | 83 | #define ARM_CPU_PART_CORTEX_A510 0xD46 |
| 84 | #define ARM_CPU_PART_CORTEX_X1C 0xD4C | ||
| 84 | #define ARM_CPU_PART_CORTEX_A520 0xD80 | 85 | #define ARM_CPU_PART_CORTEX_A520 0xD80 |
| 85 | #define ARM_CPU_PART_CORTEX_A710 0xD47 | 86 | #define ARM_CPU_PART_CORTEX_A710 0xD47 |
| 86 | #define ARM_CPU_PART_CORTEX_A715 0xD4D | 87 | #define ARM_CPU_PART_CORTEX_A715 0xD4D |
| @@ -168,6 +169,7 @@ · 81 unmodified lines | |||
| 168 | #define MIDR_CORTEX_A78AE MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A78AE) | 169 | #define MIDR_CORTEX_A78AE MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A78AE) |
| 169 | #define MIDR_CORTEX_X1 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_X1) | 170 | #define MIDR_CORTEX_X1 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_X1) |
| 170 | #define MIDR_CORTEX_A510 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A510) | 171 | #define MIDR_CORTEX_A510 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A510) |
| 172 | #define MIDR_CORTEX_X1C MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_X1C) | ||
| 171 | #define MIDR_CORTEX_A520 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A520) | 173 | #define MIDR_CORTEX_A520 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A520) |
| 172 | #define MIDR_CORTEX_A710 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A710) | 174 | #define MIDR_CORTEX_A710 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A710) |
| 173 | #define MIDR_CORTEX_A715 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A715) | 175 | #define MIDR_CORTEX_A715 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A715) |
| @@ -706,6 +706,7 @@ u32 aarch64_insn_gen_cas(enum aarch64_insn_register result, · 705 unmodified lines | |||
| 706 | } | 706 | } |
| 707 | #endif | 707 | #endif |
| 708 | u32 aarch64_insn_gen_dmb(enum aarch64_insn_mb_type type); | 708 | u32 aarch64_insn_gen_dmb(enum aarch64_insn_mb_type type); |
| 709 | u32 aarch64_insn_gen_dsb(enum aarch64_insn_mb_type type); | ||
| 709 | u32 aarch64_insn_gen_mrs(enum aarch64_insn_register result, | 710 | u32 aarch64_insn_gen_mrs(enum aarch64_insn_register result, |
| 710 | enum aarch64_insn_system_register sysreg); | 711 | enum aarch64_insn_system_register sysreg); |
| 711 | 712 | ||
| @@ -97,6 +97,9 @@ enum mitigation_state arm64_get_meltdown_state(void); · 96 unmodified lines | |||
| 97 | 97 | ||
| 98 | enum mitigation_state arm64_get_spectre_bhb_state(void); | 98 | enum mitigation_state arm64_get_spectre_bhb_state(void); |
| 99 | bool is_spectre_bhb_affected(const struct arm64_cpu_capabilities *entry, int scope); | 99 | bool is_spectre_bhb_affected(const struct arm64_cpu_capabilities *entry, int scope); |
| 100 | extern bool __nospectre_bhb; | ||
| 101 | u8 get_spectre_bhb_loop_value(void); | ||
| 102 | bool is_spectre_bhb_fw_mitigated(void); | ||
| 100 | void spectre_bhb_enable_mitigation(const struct arm64_cpu_capabilities *__unused); | 103 | void spectre_bhb_enable_mitigation(const struct arm64_cpu_capabilities *__unused); |
| 101 | bool try_emulate_el1_ssbs(struct pt_regs *regs, u32 instr); | 104 | bool try_emulate_el1_ssbs(struct pt_regs *regs, u32 instr); |
| 102 | 105 | ||
| @@ -891,6 +891,7 @@ static u8 spectre_bhb_loop_affected(void) · 890 unmodified lines | |||
| 891 | MIDR_ALL_VERSIONS(MIDR_CORTEX_A78AE), | 891 | MIDR_ALL_VERSIONS(MIDR_CORTEX_A78AE), |
| 892 | MIDR_ALL_VERSIONS(MIDR_CORTEX_A78C), | 892 | MIDR_ALL_VERSIONS(MIDR_CORTEX_A78C), |
| 893 | MIDR_ALL_VERSIONS(MIDR_CORTEX_X1), | 893 | MIDR_ALL_VERSIONS(MIDR_CORTEX_X1), |
| 894 | MIDR_ALL_VERSIONS(MIDR_CORTEX_X1C), | ||
| 894 | MIDR_ALL_VERSIONS(MIDR_CORTEX_A710), | 895 | MIDR_ALL_VERSIONS(MIDR_CORTEX_A710), |
| 895 | MIDR_ALL_VERSIONS(MIDR_CORTEX_X2), | 896 | MIDR_ALL_VERSIONS(MIDR_CORTEX_X2), |
| 896 | MIDR_ALL_VERSIONS(MIDR_NEOVERSE_N2), | 897 | MIDR_ALL_VERSIONS(MIDR_NEOVERSE_N2), |
| @@ -999,6 +1000,11 @@ bool is_spectre_bhb_affected(const struct arm64_cpu_capabilities *entry, · 102 unmodified lines | |||
| 999 | return true; | 1000 | return true; |
| 1000 | } | 1001 | } |
| 1001 | 1002 | ||
| 1003 | u8 get_spectre_bhb_loop_value(void) | ||
| 1004 | { | ||
| 1005 | return max_bhb_k; | ||
| 1006 | } | ||
| 1007 | |||
| 1002 | static void this_cpu_set_vectors(enum arm64_bp_harden_el1_vectors slot) | 1008 | static void this_cpu_set_vectors(enum arm64_bp_harden_el1_vectors slot) |
| 1003 | { | 1009 | { |
| 1004 | const char *v = arm64_get_bp_hardening_vector(slot); | 1010 | const char *v = arm64_get_bp_hardening_vector(slot); |
| @@ -1016,7 +1022,7 @@ static void this_cpu_set_vectors(enum arm64_bp_harden_el1_vectors slot) · 11 unmodified lines | |||
| 1016 | isb(); | 1022 | isb(); |
| 1017 | } | 1023 | } |
| 1018 | 1024 | ||
| 1019 | static bool __read_mostly __nospectre_bhb; | 1025 | bool __read_mostly __nospectre_bhb; |
| 1020 | static int __init parse_spectre_bhb_param(char *str) | 1026 | static int __init parse_spectre_bhb_param(char *str) |
| 1021 | { | 1027 | { |
| 1022 | __nospectre_bhb = true; | 1028 | __nospectre_bhb = true; |
| @@ -1094,6 +1100,11 @@ void spectre_bhb_enable_mitigation(const struct arm64_cpu_capabilities *entry) · 71 unmodified lines | |||
| 1094 | update_mitigation_state(&spectre_bhb_state, state); | 1100 | update_mitigation_state(&spectre_bhb_state, state); |
| 1095 | } | 1101 | } |
| 1096 | 1102 | ||
| 1103 | bool is_spectre_bhb_fw_mitigated(void) | ||
| 1104 | { | ||
| 1105 | return test_bit(BHB_FW, &system_bhb_mitigations); | ||
| 1106 | } | ||
| 1107 | |||
| 1097 | /* Patched to NOP when enabled */ | 1108 | /* Patched to NOP when enabled */ |
| 1098 | void noinstr spectre_bhb_patch_loop_mitigation_enable(struct alt_instr *alt, | 1109 | void noinstr spectre_bhb_patch_loop_mitigation_enable(struct alt_instr *alt, |
| 1099 | __le32 *origptr, | 1110 | __le32 *origptr, |
| @@ -5,6 +5,7 @@ · 4 unmodified lines | |||
| 5 | * | 5 | * |
| 6 | * Copyright (C) 2014-2016 Zi Shen Lim <zlim.lnx@gmail.com> | 6 | * Copyright (C) 2014-2016 Zi Shen Lim <zlim.lnx@gmail.com> |
| 7 | */ | 7 | */ |
| 8 | #include <linux/bitfield.h> | ||
| 8 | #include <linux/bitops.h> | 9 | #include <linux/bitops.h> |
| 9 | #include <linux/bug.h> | 10 | #include <linux/bug.h> |
| 10 | #include <linux/printk.h> | 11 | #include <linux/printk.h> |
| @@ -1500,43 +1501,41 @@ u32 aarch64_insn_gen_extr(enum aarch64_insn_variant variant, · 1489 unmodified lines | |||
| 1500 | return aarch64_insn_encode_register(AARCH64_INSN_REGTYPE_RM, insn, Rm); | 1501 | return aarch64_insn_encode_register(AARCH64_INSN_REGTYPE_RM, insn, Rm); |
| 1501 | } | 1502 | } |
| 1502 | 1503 | ||
| 1503 | u32 aarch64_insn_gen_dmb(enum aarch64_insn_mb_type type) | 1504 | static u32 __get_barrier_crm_val(enum aarch64_insn_mb_type type) |
| 1504 | { | 1505 | { |
| 1505 | u32 opt; | ||
| 1506 | u32 insn; | ||
| 1507 | |||
| 1508 | switch (type) { | 1506 | switch (type) { |
| 1509 | case AARCH64_INSN_MB_SY: | 1507 | case AARCH64_INSN_MB_SY: |
| 1510 | opt = 0xf; | 1508 | return 0xf; |
| 1511 | break; | ||
| 1512 | case AARCH64_INSN_MB_ST: | 1509 | case AARCH64_INSN_MB_ST: |
| 1513 | opt = 0xe; | 1510 | return 0xe; |
| 1514 | break; | ||
| 1515 | case AARCH64_INSN_MB_LD: | 1511 | case AARCH64_INSN_MB_LD: |
| 1516 | opt = 0xd; | 1512 | return 0xd; |
| 1517 | break; | ||
| 1518 | case AARCH64_INSN_MB_ISH: | 1513 | case AARCH64_INSN_MB_ISH: |
| 1519 | opt = 0xb; | 1514 | return 0xb; |
| 1520 | break; | ||
| 1521 | case AARCH64_INSN_MB_ISHST: | 1515 | case AARCH64_INSN_MB_ISHST: |
| 1522 | opt = 0xa; | 1516 | return 0xa; |
| 1523 | break; | ||
| 1524 | case AARCH64_INSN_MB_ISHLD: | 1517 | case AARCH64_INSN_MB_ISHLD: |
| 1525 | opt = 0x9; | 1518 | return 0x9; |
| 1526 | break; | ||
| 1527 | case AARCH64_INSN_MB_NSH: | 1519 | case AARCH64_INSN_MB_NSH: |
| 1528 | opt = 0x7; | 1520 | return 0x7; |
| 1529 | break; | ||
| 1530 | case AARCH64_INSN_MB_NSHST: | 1521 | case AARCH64_INSN_MB_NSHST: |
| 1531 | opt = 0x6; | 1522 | return 0x6; |
| 1532 | break; | ||
| 1533 | case AARCH64_INSN_MB_NSHLD: | 1523 | case AARCH64_INSN_MB_NSHLD: |
| 1534 | opt = 0x5; | 1524 | return 0x5; |
| 1535 | break; | ||
| 1536 | default: | 1525 | default: |
| 1537 | pr_err("%s: unknown dmb type %d\n", __func__, type); | 1526 | pr_err("%s: unknown barrier type %d\n", __func__, type); |
| 1538 | return AARCH64_BREAK_FAULT; | 1527 | return AARCH64_BREAK_FAULT; |
| 1539 | } | 1528 | } |
| 1529 | } | ||
| 1530 | |||
| 1531 | u32 aarch64_insn_gen_dmb(enum aarch64_insn_mb_type type) | ||
| 1532 | { | ||
| 1533 | u32 opt; | ||
| 1534 | u32 insn; | ||
| 1535 | |||
| 1536 | opt = __get_barrier_crm_val(type); | ||
| 1537 | if (opt == AARCH64_BREAK_FAULT) | ||
| 1538 | return AARCH64_BREAK_FAULT; | ||
| 1540 | 1539 | ||
| 1541 | insn = aarch64_insn_get_dmb_value(); | 1540 | insn = aarch64_insn_get_dmb_value(); |
| 1542 | insn &= ~GENMASK(11, 8); | 1541 | insn &= ~GENMASK(11, 8); |
| @@ -1545,6 +1544,21 @@ u32 aarch64_insn_gen_dmb(enum aarch64_insn_mb_type type) · 2 unmodified lines | |||
| 1545 | return insn; | 1544 | return insn; |
| 1546 | } | 1545 | } |
| 1547 | 1546 | ||
| 1547 | u32 aarch64_insn_gen_dsb(enum aarch64_insn_mb_type type) | ||
| 1548 | { | ||
| 1549 | u32 opt, insn; | ||
| 1550 | |||
| 1551 | opt = __get_barrier_crm_val(type); | ||
| 1552 | if (opt == AARCH64_BREAK_FAULT) | ||
| 1553 | return AARCH64_BREAK_FAULT; | ||
| 1554 | |||
| 1555 | insn = aarch64_insn_get_dsb_base_value(); | ||
| 1556 | insn &= ~GENMASK(11, 8); | ||
| 1557 | insn |= (opt << 8); | ||
| 1558 | |||
| 1559 | return insn; | ||
| 1560 | } | ||
| 1561 | |||
| 1548 | u32 aarch64_insn_gen_mrs(enum aarch64_insn_register result, | 1562 | u32 aarch64_insn_gen_mrs(enum aarch64_insn_register result, |
| 1549 | enum aarch64_insn_system_register sysreg) | 1563 | enum aarch64_insn_system_register sysreg) |
| 1550 | { | 1564 | { |
| @@ -7,6 +7,7 @@ · 6 unmodified lines | |||
| 7 | 7 | ||
| 8 | #define pr_fmt(fmt) "bpf_jit: " fmt | 8 | #define pr_fmt(fmt) "bpf_jit: " fmt |
| 9 | 9 | ||
| 10 | #include <linux/arm-smccc.h> | ||
| 10 | #include <linux/bitfield.h> | 11 | #include <linux/bitfield.h> |
| 11 | #include <linux/bpf.h> | 12 | #include <linux/bpf.h> |
| 12 | #include <linux/filter.h> | 13 | #include <linux/filter.h> |
| @@ -17,6 +18,7 @@ · 4 unmodified lines | |||
| 17 | #include <asm/asm-extable.h> | 18 | #include <asm/asm-extable.h> |
| 18 | #include <asm/byteorder.h> | 19 | #include <asm/byteorder.h> |
| 19 | #include <asm/cacheflush.h> | 20 | #include <asm/cacheflush.h> |
| 21 | #include <asm/cpufeature.h> | ||
| 20 | #include <asm/debug-monitors.h> | 22 | #include <asm/debug-monitors.h> |
| 21 | #include <asm/insn.h> | 23 | #include <asm/insn.h> |
| 22 | #include <asm/text-patching.h> | 24 | #include <asm/text-patching.h> |
| @@ -939,7 +941,51 @@ static void build_plt(struct jit_ctx *ctx) · 916 unmodified lines | |||
| 939 | plt->target = (u64)&dummy_tramp; | 941 | plt->target = (u64)&dummy_tramp; |
| 940 | } | 942 | } |
| 941 | 943 | ||
| 942 | static void build_epilogue(struct jit_ctx *ctx) | 944 | /* Clobbers BPF registers 1-4, aka x0-x3 */ |
| 945 | static void __maybe_unused build_bhb_mitigation(struct jit_ctx *ctx) | ||
| 946 | { | ||
| 947 | const u8 r1 = bpf2a64[BPF_REG_1]; /* aka x0 */ | ||
| 948 | u8 k = get_spectre_bhb_loop_value(); | ||
| 949 | |||
| 950 | if (!IS_ENABLED(CONFIG_MITIGATE_SPECTRE_BRANCH_HISTORY) || | ||
| 951 | cpu_mitigations_off() || __nospectre_bhb || | ||
| 952 | arm64_get_spectre_v2_state() == SPECTRE_VULNERABLE) | ||
| 953 | return; | ||
| 954 | |||
| 955 | if (capable(CAP_SYS_ADMIN)) | ||
| 956 | return; | ||
| 957 | |||
| 958 | if (supports_clearbhb(SCOPE_SYSTEM)) { | ||
| 959 | emit(aarch64_insn_gen_hint(AARCH64_INSN_HINT_CLEARBHB), ctx); | ||
| 960 | return; | ||
| 961 | } | ||
| 962 | |||
| 963 | if (k) { | ||
| 964 | emit_a64_mov_i64(r1, k, ctx); | ||
| 965 | emit(A64_B(1), ctx); | ||
| 966 | emit(A64_SUBS_I(true, r1, r1, 1), ctx); | ||
| 967 | emit(A64_B_(A64_COND_NE, -2), ctx); | ||
| 968 | emit(aarch64_insn_gen_dsb(AARCH64_INSN_MB_ISH), ctx); | ||
| 969 | emit(aarch64_insn_get_isb_value(), ctx); | ||
| 970 | } | ||
| 971 | |||
| 972 | if (is_spectre_bhb_fw_mitigated()) { | ||
| 973 | emit(A64_ORR_I(false, r1, AARCH64_INSN_REG_ZR, | ||
| 974 | ARM_SMCCC_ARCH_WORKAROUND_3), ctx); | ||
| 975 | switch (arm_smccc_1_1_get_conduit()) { | ||
| 976 | case SMCCC_CONDUIT_HVC: | ||
| 977 | emit(aarch64_insn_get_hvc_value(), ctx); | ||
| 978 | break; | ||
| 979 | case SMCCC_CONDUIT_SMC: | ||
| 980 | emit(aarch64_insn_get_smc_value(), ctx); | ||
| 981 | break; | ||
| 982 | default: | ||
| 983 | pr_err_once("Firmware mitigation enabled with unknown conduit\n"); | ||
| 984 | } | ||
| 985 | } | ||
| 986 | } | ||
| 987 | |||
| 988 | static void build_epilogue(struct jit_ctx *ctx, bool was_classic) | ||
| 943 | { | 989 | { |
| 944 | const u8 r0 = bpf2a64[BPF_REG_0]; | 990 | const u8 r0 = bpf2a64[BPF_REG_0]; |
| 945 | const u8 ptr = bpf2a64[TCCNT_PTR]; | 991 | const u8 ptr = bpf2a64[TCCNT_PTR]; |
| @@ -952,10 +998,13 @@ static void build_epilogue(struct jit_ctx *ctx) · 6 unmodified lines | |||
| 952 | 998 | ||
| 953 | emit(A64_POP(A64_ZR, ptr, A64_SP), ctx); | 999 | emit(A64_POP(A64_ZR, ptr, A64_SP), ctx); |
| 954 | 1000 | ||
| 1001 | if (was_classic) | ||
| 1002 | build_bhb_mitigation(ctx); | ||
| 1003 | |||
| 955 | /* Restore FP/LR registers */ | 1004 | /* Restore FP/LR registers */ |
| 956 | emit(A64_POP(A64_FP, A64_LR, A64_SP), ctx); | 1005 | emit(A64_POP(A64_FP, A64_LR, A64_SP), ctx); |
| 957 | 1006 | ||
| 958 | /* Set return value */ | 1007 | /* Move the return value from bpf:r0 (aka x7) to x0 */ |
| 959 | emit(A64_MOV(1, A64_R(0), r0), ctx); | 1008 | emit(A64_MOV(1, A64_R(0), r0), ctx); |
| 960 | 1009 | ||
| 961 | /* Authenticate lr */ | 1010 | /* Authenticate lr */ |
| @@ -1898,7 +1947,7 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog) · 936 unmodified lines | |||
| 1898 | } | 1947 | } |
| 1899 | 1948 | ||
| 1900 | ctx.epilogue_offset = ctx.idx; | 1949 | ctx.epilogue_offset = ctx.idx; |
| 1901 | build_epilogue(&ctx); | 1950 | build_epilogue(&ctx, was_classic); |
| 1902 | build_plt(&ctx); | 1951 | build_plt(&ctx); |
| 1903 | 1952 | ||
| 1904 | extable_align = __alignof__(struct exception_table_entry); | 1953 | extable_align = __alignof__(struct exception_table_entry); |
| @@ -1961,7 +2010,7 @@ skip_init_ctx: · 56 unmodified lines | |||
| 1961 | goto out_free_hdr; | 2010 | goto out_free_hdr; |
| 1962 | } | 2011 | } |
| 1963 | 2012 | ||
| 1964 | build_epilogue(&ctx); | 2013 | build_epilogue(&ctx, was_classic); |
| 1965 | build_plt(&ctx); | 2014 | build_plt(&ctx); |
| 1966 | 2015 | ||
| 1967 | /* Extra pass to validate JITed code. */ | 2016 | /* Extra pass to validate JITed code. */ |
| @@ -55,7 +55,7 @@ static inline void instruction_pointer_set(struct pt_regs *regs, unsigned long v · 54 unmodified lines | |||
| 55 | 55 | ||
| 56 | /* Query offset/name of register from its name/offset */ | 56 | /* Query offset/name of register from its name/offset */ |
| 57 | extern int regs_query_register_offset(const char *name); | 57 | extern int regs_query_register_offset(const char *name); |
| 58 | #define MAX_REG_OFFSET (offsetof(struct pt_regs, __last)) | 58 | #define MAX_REG_OFFSET (offsetof(struct pt_regs, __last) - sizeof(unsigned long)) |
| 59 | 59 | ||
| 60 | /** | 60 | /** |
| 61 | * regs_get_register() - get register value from its offset | 61 | * regs_get_register() - get register value from its offset |
| @@ -15,7 +15,6 @@ typedef u32 uprobe_opcode_t; · 14 unmodified lines | |||
| 15 | #define UPROBE_XOLBP_INSN __emit_break(BRK_UPROBE_XOLBP) | 15 | #define UPROBE_XOLBP_INSN __emit_break(BRK_UPROBE_XOLBP) |
| 16 | 16 | ||
| 17 | struct arch_uprobe { | 17 | struct arch_uprobe { |
| 18 | unsigned long resume_era; | ||
| 19 | u32 insn[2]; | 18 | u32 insn[2]; |
| 20 | u32 ixol[2]; | 19 | u32 ixol[2]; |
| 21 | bool simulate; | 20 | bool simulate; |
| @@ -16,6 +16,7 @@ · 15 unmodified lines | |||
| 16 | #include <asm/stackframe.h> | 16 | #include <asm/stackframe.h> |
| 17 | #include <asm/thread_info.h> | 17 | #include <asm/thread_info.h> |
| 18 | 18 | ||
| 19 | .section .cpuidle.text, "ax" | ||
| 19 | .align 5 | 20 | .align 5 |
| 20 | SYM_FUNC_START(__arch_cpu_idle) | 21 | SYM_FUNC_START(__arch_cpu_idle) |
| 21 | /* start of idle interrupt region */ | 22 | /* start of idle interrupt region */ |
| @@ -31,14 +32,16 @@ SYM_FUNC_START(__arch_cpu_idle) · 9 unmodified lines | |||
| 31 | */ | 32 | */ |
| 32 | idle 0 | 33 | idle 0 |
| 33 | /* end of idle interrupt region */ | 34 | /* end of idle interrupt region */ |
| 34 | 1: jr ra | 35 | idle_exit: |
| 36 | jr ra | ||
| 35 | SYM_FUNC_END(__arch_cpu_idle) | 37 | SYM_FUNC_END(__arch_cpu_idle) |
| 38 | .previous | ||
| 36 | 39 | ||
| 37 | SYM_CODE_START(handle_vint) | 40 | SYM_CODE_START(handle_vint) |
| 38 | UNWIND_HINT_UNDEFINED | 41 | UNWIND_HINT_UNDEFINED |
| 39 | BACKUP_T0T1 | 42 | BACKUP_T0T1 |
| 40 | SAVE_ALL | 43 | SAVE_ALL |
| 41 | la_abs t1, 1b | 44 | la_abs t1, idle_exit |
| 42 | LONG_L t0, sp, PT_ERA | 45 | LONG_L t0, sp, PT_ERA |
| 43 | /* 3 instructions idle interrupt region */ | 46 | /* 3 instructions idle interrupt region */ |
| 44 | ori t0, t0, 0b1100 | 47 | ori t0, t0, 0b1100 |
| @@ -18,11 +18,28 @@ static unsigned int euen_mask = CSR_EUEN_FPEN; · 17 unmodified lines | |||
| 18 | static DEFINE_PER_CPU(bool, in_kernel_fpu); | 18 | static DEFINE_PER_CPU(bool, in_kernel_fpu); |
| 19 | static DEFINE_PER_CPU(unsigned int, euen_current); | 19 | static DEFINE_PER_CPU(unsigned int, euen_current); |
| 20 | 20 | ||
| 21 | static inline void fpregs_lock(void) | ||
| 22 | { | ||
| 23 | if (IS_ENABLED(CONFIG_PREEMPT_RT)) | ||
| 24 | preempt_disable(); | ||
| 25 | else | ||
| 26 | local_bh_disable(); | ||
| 27 | } | ||
| 28 | |||
| 29 | static inline void fpregs_unlock(void) | ||
| 30 | { | ||
| 31 | if (IS_ENABLED(CONFIG_PREEMPT_RT)) | ||
| 32 | preempt_enable(); | ||
| 33 | else | ||
| 34 | local_bh_enable(); | ||
| 35 | } | ||
| 36 | |||
| 21 | void kernel_fpu_begin(void) | 37 | void kernel_fpu_begin(void) |
| 22 | { | 38 | { |
| 23 | unsigned int *euen_curr; | 39 | unsigned int *euen_curr; |
| 24 | 40 | ||
| 25 | preempt_disable(); | 41 | if (!irqs_disabled()) |
| 42 | fpregs_lock(); | ||
| 26 | 43 | ||
| 27 | WARN_ON(this_cpu_read(in_kernel_fpu)); | 44 | WARN_ON(this_cpu_read(in_kernel_fpu)); |
| 28 | 45 | ||
| @@ -73,7 +90,8 @@ void kernel_fpu_end(void) · 44 unmodified lines | |||
| 73 | 90 | ||
| 74 | this_cpu_write(in_kernel_fpu, false); | 91 | this_cpu_write(in_kernel_fpu, false); |
| 75 | 92 | ||
| 76 | preempt_enable(); | 93 | if (!irqs_disabled()) |
| 94 | fpregs_unlock(); | ||
| 77 | } | 95 | } |
| 78 | EXPORT_SYMBOL_GPL(kernel_fpu_end); | 96 | EXPORT_SYMBOL_GPL(kernel_fpu_end); |
| 79 | 97 | ||
| @@ -111,7 +111,7 @@ static unsigned long __init get_loops_per_jiffy(void) · 110 unmodified lines | |||
| 111 | return lpj; | 111 | return lpj; |
| 112 | } | 112 | } |
| 113 | 113 | ||
| 114 | static long init_offset __nosavedata; | 114 | static long init_offset; |
| 115 | 115 | ||
| 116 | void save_counter(void) | 116 | void save_counter(void) |
| 117 | { | 117 | { |
| @@ -42,7 +42,6 @@ int arch_uprobe_pre_xol(struct arch_uprobe *auprobe, struct pt_regs *regs) · 41 unmodified lines | |||
| 42 | utask->autask.saved_trap_nr = current->thread.trap_nr; | 42 | utask->autask.saved_trap_nr = current->thread.trap_nr; |
| 43 | current->thread.trap_nr = UPROBE_TRAP_NR; | 43 | current->thread.trap_nr = UPROBE_TRAP_NR; |
| 44 | instruction_pointer_set(regs, utask->xol_vaddr); | 44 | instruction_pointer_set(regs, utask->xol_vaddr); |
| 45 | user_enable_single_step(current); | ||
| 46 | 45 | ||
| 47 | return 0; | 46 | return 0; |
| 48 | } | 47 | } |
| @@ -53,13 +52,7 @@ int arch_uprobe_post_xol(struct arch_uprobe *auprobe, struct pt_regs *regs) · 4 unmodified lines | |||
| 53 | 52 | ||
| 54 | WARN_ON_ONCE(current->thread.trap_nr != UPROBE_TRAP_NR); | 53 | WARN_ON_ONCE(current->thread.trap_nr != UPROBE_TRAP_NR); |
| 55 | current->thread.trap_nr = utask->autask.saved_trap_nr; | 54 | current->thread.trap_nr = utask->autask.saved_trap_nr; |
| 56 | 55 | instruction_pointer_set(regs, utask->vaddr + LOONGARCH_INSN_SIZE); | |
| 57 | if (auprobe->simulate) | ||
| 58 | instruction_pointer_set(regs, auprobe->resume_era); | ||
| 59 | else | ||
| 60 | instruction_pointer_set(regs, utask->vaddr + LOONGARCH_INSN_SIZE); | ||
| 61 | |||
| 62 | user_disable_single_step(current); | ||
| 63 | 56 | ||
| 64 | return 0; | 57 | return 0; |
| 65 | } | 58 | } |
| @@ -70,7 +63,6 @@ void arch_uprobe_abort_xol(struct arch_uprobe *auprobe, struct pt_regs *regs) · 4 unmodified lines | |||
| 70 | 63 | ||
| 71 | current->thread.trap_nr = utask->autask.saved_trap_nr; | 64 | current->thread.trap_nr = utask->autask.saved_trap_nr; |
| 72 | instruction_pointer_set(regs, utask->vaddr); | 65 | instruction_pointer_set(regs, utask->vaddr); |
| 73 | user_disable_single_step(current); | ||
| 74 | } | 66 | } |
| 75 | 67 | ||
| 76 | bool arch_uprobe_xol_was_trapped(struct task_struct *t) | 68 | bool arch_uprobe_xol_was_trapped(struct task_struct *t) |
| @@ -90,7 +82,6 @@ bool arch_uprobe_skip_sstep(struct arch_uprobe *auprobe, struct pt_regs *regs) · 13 unmodified lines | |||
| 90 | 82 | ||
| 91 | insn.word = auprobe->insn[0]; | 83 | insn.word = auprobe->insn[0]; |
| 92 | arch_simulate_insn(insn, regs); | 84 | arch_simulate_insn(insn, regs); |
| 93 | auprobe->resume_era = regs->csr_era; | ||
| 94 | 85 | ||
| 95 | return true; | 86 | return true; |
| 96 | } | 87 | } |
| @@ -2,6 +2,7 @@ · 1 unmodified line | |||
| 2 | #include <asm/fpu.h> | 2 | #include <asm/fpu.h> |
| 3 | #include <asm/loongson.h> | 3 | #include <asm/loongson.h> |
| 4 | #include <asm/sections.h> | 4 | #include <asm/sections.h> |
| 5 | #include <asm/time.h> | ||
| 5 | #include <asm/tlbflush.h> | 6 | #include <asm/tlbflush.h> |
| 6 | #include <linux/suspend.h> | 7 | #include <linux/suspend.h> |
| 7 | 8 | ||
| @@ -14,6 +15,7 @@ struct pt_regs saved_regs; · 6 unmodified lines | |||
| 14 | 15 | ||
| 15 | void save_processor_state(void) | 16 | void save_processor_state(void) |
| 16 | { | 17 | { |
| 18 | save_counter(); | ||
| 17 | saved_crmd = csr_read32(LOONGARCH_CSR_CRMD); | 19 | saved_crmd = csr_read32(LOONGARCH_CSR_CRMD); |
| 18 | saved_prmd = csr_read32(LOONGARCH_CSR_PRMD); | 20 | saved_prmd = csr_read32(LOONGARCH_CSR_PRMD); |
| 19 | saved_euen = csr_read32(LOONGARCH_CSR_EUEN); | 21 | saved_euen = csr_read32(LOONGARCH_CSR_EUEN); |
| @@ -26,6 +28,7 @@ void save_processor_state(void) · 6 unmodified lines | |||
| 26 | 28 | ||
| 27 | void restore_processor_state(void) | 29 | void restore_processor_state(void) |
| 28 | { | 30 | { |
| 31 | sync_counter(); | ||
| 29 | csr_write32(saved_crmd, LOONGARCH_CSR_CRMD); | 32 | csr_write32(saved_crmd, LOONGARCH_CSR_CRMD); |
| 30 | csr_write32(saved_prmd, LOONGARCH_CSR_PRMD); | 33 | csr_write32(saved_prmd, LOONGARCH_CSR_PRMD); |
| 31 | csr_write32(saved_euen, LOONGARCH_CSR_EUEN); | 34 | csr_write32(saved_euen, LOONGARCH_CSR_EUEN); |
| @@ -341,7 +341,7 @@ · 340 unmodified lines | |||
| 341 | 1024 1024 1024 1024>; | 341 | 1024 1024 1024 1024>; |
| 342 | snps,priority = <0 1 2 3 4 5 6 7>; | 342 | snps,priority = <0 1 2 3 4 5 6 7>; |
| 343 | snps,dma-masters = <2>; | 343 | snps,dma-masters = <2>; |
| 344 | snps,data-width = <4>; | 344 | snps,data-width = <2>; |
| 345 | status = "disabled"; | 345 | status = "disabled"; |
| 346 | }; | 346 | }; |
| 347 | 347 | ||
| @@ -154,5 +154,6 @@ MRPROPER_FILES += $(HOST_DIR)/include/generated · 153 unmodified lines | |||
| 154 | archclean: | 154 | archclean: |
| 155 | @find . \( -name '*.bb' -o -name '*.bbg' -o -name '*.da' \ | 155 | @find . \( -name '*.bb' -o -name '*.bbg' -o -name '*.da' \ |
| 156 | -o -name '*.gcov' \) -type f -print | xargs rm -f | 156 | -o -name '*.gcov' \) -type f -print | xargs rm -f |
| 157 | $(Q)$(MAKE) -f $(srctree)/Makefile ARCH=$(HEADER_ARCH) clean | ||
| 157 | 158 | ||
| 158 | export HEADER_ARCH SUBARCH USER_CFLAGS CFLAGS_NO_HARDENING DEV_NULL_PATH | 159 | export HEADER_ARCH SUBARCH USER_CFLAGS CFLAGS_NO_HARDENING DEV_NULL_PATH |
| @@ -547,6 +547,102 @@ void snp_accept_memory(phys_addr_t start, phys_addr_t end) · 546 unmodified lines | |||
| 547 | set_pages_state(vaddr, npages, SNP_PAGE_STATE_PRIVATE); | 547 | set_pages_state(vaddr, npages, SNP_PAGE_STATE_PRIVATE); |
| 548 | } | 548 | } |
| 549 | 549 | ||
| 550 | static int vmgexit_ap_control(u64 event, struct sev_es_save_area *vmsa, u32 apic_id) | ||
| 551 | { | ||
| 552 | bool create = event != SVM_VMGEXIT_AP_DESTROY; | ||
| 553 | struct ghcb_state state; | ||
| 554 | unsigned long flags; | ||
| 555 | struct ghcb *ghcb; | ||
| 556 | int ret = 0; | ||
| 557 | |||
| 558 | local_irq_save(flags); | ||
| 559 | |||
| 560 | ghcb = __sev_get_ghcb(&state); | ||
| 561 | |||
| 562 | vc_ghcb_invalidate(ghcb); | ||
| 563 | |||
| 564 | if (create) | ||
| 565 | ghcb_set_rax(ghcb, vmsa->sev_features); | ||
| 566 | |||
| 567 | ghcb_set_sw_exit_code(ghcb, SVM_VMGEXIT_AP_CREATION); | ||
| 568 | ghcb_set_sw_exit_info_1(ghcb, | ||
| 569 | ((u64)apic_id << 32) | | ||
| 570 | ((u64)snp_vmpl << 16) | | ||
| 571 | event); | ||
| 572 | ghcb_set_sw_exit_info_2(ghcb, __pa(vmsa)); | ||
| 573 | |||
| 574 | sev_es_wr_ghcb_msr(__pa(ghcb)); | ||
| 575 | VMGEXIT(); | ||
| 576 | |||
| 577 | if (!ghcb_sw_exit_info_1_is_valid(ghcb) || | ||
| 578 | lower_32_bits(ghcb->save.sw_exit_info_1)) { | ||
| 579 | pr_err("SNP AP %s error\n", (create ? "CREATE" : "DESTROY")); | ||
| 580 | ret = -EINVAL; | ||
| 581 | } | ||
| 582 | |||
| 583 | __sev_put_ghcb(&state); | ||
| 584 | |||
| 585 | local_irq_restore(flags); | ||
| 586 | |||
| 587 | return ret; | ||
| 588 | } | ||
| 589 | |||
| 590 | static int snp_set_vmsa(void *va, void *caa, int apic_id, bool make_vmsa) | ||
| 591 | { | ||
| 592 | int ret; | ||
| 593 | |||
| 594 | if (snp_vmpl) { | ||
| 595 | struct svsm_call call = {}; | ||
| 596 | unsigned long flags; | ||
| 597 | |||
| 598 | local_irq_save(flags); | ||
| 599 | |||
| 600 | call.caa = this_cpu_read(svsm_caa); | ||
| 601 | call.rcx = __pa(va); | ||
| 602 | |||
| 603 | if (make_vmsa) { | ||
| 604 | /* Protocol 0, Call ID 2 */ | ||
| 605 | call.rax = SVSM_CORE_CALL(SVSM_CORE_CREATE_VCPU); | ||
| 606 | call.rdx = __pa(caa); | ||
| 607 | call.r8 = apic_id; | ||
| 608 | } else { | ||
| 609 | /* Protocol 0, Call ID 3 */ | ||
| 610 | call.rax = SVSM_CORE_CALL(SVSM_CORE_DELETE_VCPU); | ||
| 611 | } | ||
| 612 | |||
| 613 | ret = svsm_perform_call_protocol(&call); | ||
| 614 | |||
| 615 | local_irq_restore(flags); | ||
| 616 | } else { | ||
| 617 | /* | ||
| 618 | * If the kernel runs at VMPL0, it can change the VMSA | ||
| 619 | * bit for a page using the RMPADJUST instruction. | ||
| 620 | * However, for the instruction to succeed it must | ||
| 621 | * target the permissions of a lesser privileged (higher | ||
| 622 | * numbered) VMPL level, so use VMPL1. | ||
| 623 | */ | ||
| 624 | u64 attrs = 1; | ||
| 625 | |||
| 626 | if (make_vmsa) | ||
| 627 | attrs |= RMPADJUST_VMSA_PAGE_BIT; | ||
| 628 | |||
| 629 | ret = rmpadjust((unsigned long)va, RMP_PG_SIZE_4K, attrs); | ||
| 630 | } | ||
| 631 | |||
| 632 | return ret; | ||
| 633 | } | ||
| 634 | |||
| 635 | static void snp_cleanup_vmsa(struct sev_es_save_area *vmsa, int apic_id) | ||
| 636 | { | ||
| 637 | int err; | ||
| 638 | |||
| 639 | err = snp_set_vmsa(vmsa, NULL, apic_id, false); | ||
| 640 | if (err) | ||
| 641 | pr_err("clear VMSA page failed (%u), leaking page\n", err); | ||
| 642 | else | ||
| 643 | free_page((unsigned long)vmsa); | ||
| 644 | } | ||
| 645 | |||
| 550 | static void set_pte_enc(pte_t *kpte, int level, void *va) | 646 | static void set_pte_enc(pte_t *kpte, int level, void *va) |
| 551 | { | 647 | { |
| 552 | struct pte_enc_desc d = { | 648 | struct pte_enc_desc d = { |
| @@ -593,7 +689,8 @@ static void unshare_all_memory(void) · 40 unmodified lines | |||
| 593 | data = per_cpu(runtime_data, cpu); | 689 | data = per_cpu(runtime_data, cpu); |
| 594 | ghcb = (unsigned long)&data->ghcb_page; | 690 | ghcb = (unsigned long)&data->ghcb_page; |
| 595 | 691 | ||
| 596 | if (addr <= ghcb && ghcb <= addr + size) { | 692 | /* Handle the case of a huge page containing the GHCB page */ |
| 693 | if (addr <= ghcb && ghcb < addr + size) { | ||
| 597 | skipped_addr = true; | 694 | skipped_addr = true; |
| 598 | break; | 695 | break; |
| 599 | } | 696 | } |
| @@ -643,11 +740,70 @@ void snp_kexec_begin(void) · 43 unmodified lines | |||
| 643 | pr_warn("Failed to stop shared<->private conversions\n"); | 740 | pr_warn("Failed to stop shared<->private conversions\n"); |
| 644 | } | 741 | } |
| 645 | 742 | ||
| 743 | /* | ||
| 744 | * Shutdown all APs except the one handling kexec/kdump and clearing | ||
| 745 | * the VMSA tag on AP's VMSA pages as they are not being used as | ||
| 746 | * VMSA page anymore. | ||
| 747 | */ | ||
| 748 | static void shutdown_all_aps(void) | ||
| 749 | { | ||
| 750 | struct sev_es_save_area *vmsa; | ||
| 751 | int apic_id, this_cpu, cpu; | ||
| 752 | |||
| 753 | this_cpu = get_cpu(); | ||
| 754 | |||
| 755 | /* | ||
| 756 | * APs are already in HLT loop when enc_kexec_finish() callback | ||
| 757 | * is invoked. | ||
| 758 | */ | ||
| 759 | for_each_present_cpu(cpu) { | ||
| 760 | vmsa = per_cpu(sev_vmsa, cpu); | ||
| 761 | |||
| 762 | /* | ||
| 763 | * The BSP or offlined APs do not have guest allocated VMSA | ||
| 764 | * and there is no need to clear the VMSA tag for this page. | ||
| 765 | */ | ||
| 766 | if (!vmsa) | ||
| 767 | continue; | ||
| 768 | |||
| 769 | /* | ||
| 770 | * Cannot clear the VMSA tag for the currently running vCPU. | ||
| 771 | */ | ||
| 772 | if (this_cpu == cpu) { | ||
| 773 | unsigned long pa; | ||
| 774 | struct page *p; | ||
| 775 | |||
| 776 | pa = __pa(vmsa); | ||
| 777 | /* | ||
| 778 | * Mark the VMSA page of the running vCPU as offline | ||
| 779 | * so that is excluded and not touched by makedumpfile | ||
| 780 | * while generating vmcore during kdump. | ||
| 781 | */ | ||
| 782 | p = pfn_to_online_page(pa >> PAGE_SHIFT); | ||
| 783 | if (p) | ||
| 784 | __SetPageOffline(p); | ||
| 785 | continue; | ||
| 786 | } | ||
| 787 | |||
| 788 | apic_id = cpuid_to_apicid[cpu]; | ||
| 789 | |||
| 790 | /* | ||
| 791 | * Issue AP destroy to ensure AP gets kicked out of guest mode | ||
| 792 | * to allow using RMPADJUST to remove the VMSA tag on it's | ||
| 793 | * VMSA page. | ||
| 794 | */ | ||
| 795 | vmgexit_ap_control(SVM_VMGEXIT_AP_DESTROY, vmsa, apic_id); | ||
| 796 | snp_cleanup_vmsa(vmsa, apic_id); | ||
| 797 | } | ||
| 798 | |||
| 799 | put_cpu(); | ||
| 800 | } | ||
| 801 | |||
| 646 | void snp_kexec_finish(void) | 802 | void snp_kexec_finish(void) |
| 647 | { | 803 | { |
| 648 | struct sev_es_runtime_data *data; | 804 | struct sev_es_runtime_data *data; |
| 805 | unsigned long size, addr; | ||
| 649 | unsigned int level, cpu; | 806 | unsigned int level, cpu; |
| 650 | unsigned long size; | ||
| 651 | struct ghcb *ghcb; | 807 | struct ghcb *ghcb; |
| 652 | pte_t *pte; | 808 | pte_t *pte; |
| 653 | 809 | ||
| @@ -657,6 +813,8 @@ void snp_kexec_finish(void) · 3 unmodified lines | |||
| 657 | if (!IS_ENABLED(CONFIG_KEXEC_CORE)) | 813 | if (!IS_ENABLED(CONFIG_KEXEC_CORE)) |
| 658 | return; | 814 | return; |
| 659 | 815 | ||
| 816 | shutdown_all_aps(); | ||
| 817 | |||
| 660 | unshare_all_memory(); | 818 | unshare_all_memory(); |
| 661 | 819 | ||
| 662 | /* | 820 | /* |
| @@ -673,54 +831,11 @@ void snp_kexec_finish(void) · 10 unmodified lines | |||
| 673 | ghcb = &data->ghcb_page; | 831 | ghcb = &data->ghcb_page; |
| 674 | pte = lookup_address((unsigned long)ghcb, &level); | 832 | pte = lookup_address((unsigned long)ghcb, &level); |
| 675 | size = page_level_size(level); | 833 | size = page_level_size(level); |
| 676 | set_pte_enc(pte, level, (void *)ghcb); | 834 | /* Handle the case of a huge page containing the GHCB page */ |
| 677 | snp_set_memory_private((unsigned long)ghcb, (size / PAGE_SIZE)); | 835 | addr = (unsigned long)ghcb & page_level_mask(level); |
| 678 | } | 836 | set_pte_enc(pte, level, (void *)addr); |
| 679 | } | 837 | snp_set_memory_private(addr, (size / PAGE_SIZE)); |
| 680 | |||
| 681 | static int snp_set_vmsa(void *va, void *caa, int apic_id, bool make_vmsa) | ||
| 682 | { | ||
| 683 | int ret; | ||
| 684 | |||
| 685 | if (snp_vmpl) { | ||
| 686 | struct svsm_call call = {}; | ||
| 687 | unsigned long flags; | ||
| 688 | |||
| 689 | local_irq_save(flags); | ||
| 690 | |||
| 691 | call.caa = this_cpu_read(svsm_caa); | ||
| 692 | call.rcx = __pa(va); | ||
| 693 | |||
| 694 | if (make_vmsa) { | ||
| 695 | /* Protocol 0, Call ID 2 */ | ||
| 696 | call.rax = SVSM_CORE_CALL(SVSM_CORE_CREATE_VCPU); | ||
| 697 | call.rdx = __pa(caa); | ||
| 698 | call.r8 = apic_id; | ||
| 699 | } else { | ||
| 700 | /* Protocol 0, Call ID 3 */ | ||
| 701 | call.rax = SVSM_CORE_CALL(SVSM_CORE_DELETE_VCPU); | ||
| 702 | } | ||
| 703 | |||
| 704 | ret = svsm_perform_call_protocol(&call); | ||
| 705 | |||
| 706 | local_irq_restore(flags); | ||
| 707 | } else { | ||
| 708 | /* | ||
| 709 | * If the kernel runs at VMPL0, it can change the VMSA | ||
| 710 | * bit for a page using the RMPADJUST instruction. | ||
| 711 | * However, for the instruction to succeed it must | ||
| 712 | * target the permissions of a lesser privileged (higher | ||
| 713 | * numbered) VMPL level, so use VMPL1. | ||
| 714 | */ | ||
| 715 | u64 attrs = 1; | ||
| 716 | |||
| 717 | if (make_vmsa) | ||
| 718 | attrs |= RMPADJUST_VMSA_PAGE_BIT; | ||
| 719 | |||
| 720 | ret = rmpadjust((unsigned long)va, RMP_PG_SIZE_4K, attrs); | ||
| 721 | } | 838 | } |
| 722 | |||
| 723 | return ret; | ||
| 724 | } | 839 | } |
| 725 | 840 | ||
| 726 | #define __ATTR_BASE (SVM_SELECTOR_P_MASK | SVM_SELECTOR_S_MASK) | 841 | #define __ATTR_BASE (SVM_SELECTOR_P_MASK | SVM_SELECTOR_S_MASK) |
| @@ -754,24 +869,10 @@ static void *snp_alloc_vmsa_page(int cpu) · 27 unmodified lines | |||
| 754 | return page_address(p + 1); | 869 | return page_address(p + 1); |
| 755 | } | 870 | } |
| 756 | 871 | ||
| 757 | static void snp_cleanup_vmsa(struct sev_es_save_area *vmsa, int apic_id) | ||
| 758 | { | ||
| 759 | int err; | ||
| 760 | |||
| 761 | err = snp_set_vmsa(vmsa, NULL, apic_id, false); | ||
| 762 | if (err) | ||
| 763 | pr_err("clear VMSA page failed (%u), leaking page\n", err); | ||
| 764 | else | ||
| 765 | free_page((unsigned long)vmsa); | ||
| 766 | } | ||
| 767 | |||
| 768 | static int wakeup_cpu_via_vmgexit(u32 apic_id, unsigned long start_ip) | 872 | static int wakeup_cpu_via_vmgexit(u32 apic_id, unsigned long start_ip) |
| 769 | { | 873 | { |
| 770 | struct sev_es_save_area *cur_vmsa, *vmsa; | 874 | struct sev_es_save_area *cur_vmsa, *vmsa; |
| 771 | struct ghcb_state state; | ||
| 772 | struct svsm_ca *caa; | 875 | struct svsm_ca *caa; |
| 773 | unsigned long flags; | ||
| 774 | struct ghcb *ghcb; | ||
| 775 | u8 sipi_vector; | 876 | u8 sipi_vector; |
| 776 | int cpu, ret; | 877 | int cpu, ret; |
| 777 | u64 cr4; | 878 | u64 cr4; |
| @@ -885,33 +986,7 @@ static int wakeup_cpu_via_vmgexit(u32 apic_id, unsigned long start_ip) · 107 unmodified lines | |||
| 885 | } | 986 | } |
| 886 | 987 | ||
| 887 | /* Issue VMGEXIT AP Creation NAE event */ | 988 | /* Issue VMGEXIT AP Creation NAE event */ |
| 888 | local_irq_save(flags); | 989 | ret = vmgexit_ap_control(SVM_VMGEXIT_AP_CREATE, vmsa, apic_id); |
| 889 | |||
| 890 | ghcb = __sev_get_ghcb(&state); | ||
| 891 | |||
| 892 | vc_ghcb_invalidate(ghcb); | ||
| 893 | ghcb_set_rax(ghcb, vmsa->sev_features); | ||
| 894 | ghcb_set_sw_exit_code(ghcb, SVM_VMGEXIT_AP_CREATION); | ||
| 895 | ghcb_set_sw_exit_info_1(ghcb, | ||
| 896 | ((u64)apic_id << 32) | | ||
| 897 | ((u64)snp_vmpl << 16) | | ||
| 898 | SVM_VMGEXIT_AP_CREATE); | ||
| 899 | ghcb_set_sw_exit_info_2(ghcb, __pa(vmsa)); | ||
| 900 | |||
| 901 | sev_es_wr_ghcb_msr(__pa(ghcb)); | ||
| 902 | VMGEXIT(); | ||
| 903 | |||
| 904 | if (!ghcb_sw_exit_info_1_is_valid(ghcb) || | ||
| 905 | lower_32_bits(ghcb->save.sw_exit_info_1)) { | ||
| 906 | pr_err("SNP AP Creation error\n"); | ||
| 907 | ret = -EINVAL; | ||
| 908 | } | ||
| 909 | |||
| 910 | __sev_put_ghcb(&state); | ||
| 911 | |||
| 912 | local_irq_restore(flags); | ||
| 913 | |||
| 914 | /* Perform cleanup if there was an error */ | ||
| 915 | if (ret) { | 990 | if (ret) { |
| 916 | snp_cleanup_vmsa(vmsa, apic_id); | 991 | snp_cleanup_vmsa(vmsa, apic_id); |
| 917 | vmsa = NULL; | 992 | vmsa = NULL; |
| @@ -2466,8 +2466,9 @@ static void intel_pmu_drain_pebs_core(struct pt_regs *iregs, struct perf_sample_ · 2465 unmodified lines | |||
| 2466 | setup_pebs_fixed_sample_data); | 2466 | setup_pebs_fixed_sample_data); |
| 2467 | } | 2467 | } |
| 2468 | 2468 | ||
| 2469 | static void intel_pmu_pebs_event_update_no_drain(struct cpu_hw_events *cpuc, int size) | 2469 | static void intel_pmu_pebs_event_update_no_drain(struct cpu_hw_events *cpuc, u64 mask) |
| 2470 | { | 2470 | { |
| 2471 | u64 pebs_enabled = cpuc->pebs_enabled & mask; | ||
| 2471 | struct perf_event *event; | 2472 | struct perf_event *event; |
| 2472 | int bit; | 2473 | int bit; |
| 2473 | 2474 | ||
| @@ -2478,7 +2479,7 @@ static void intel_pmu_pebs_event_update_no_drain(struct cpu_hw_events *cpuc, int · 4 unmodified lines | |||
| 2478 | * It needs to call intel_pmu_save_and_restart_reload() to | 2479 | * It needs to call intel_pmu_save_and_restart_reload() to |
| 2479 | * update the event->count for this case. | 2480 | * update the event->count for this case. |
| 2480 | */ | 2481 | */ |
| 2481 | for_each_set_bit(bit, (unsigned long *)&cpuc->pebs_enabled, size) { | 2482 | for_each_set_bit(bit, (unsigned long *)&pebs_enabled, X86_PMC_IDX_MAX) { |
| 2482 | event = cpuc->events[bit]; | 2483 | event = cpuc->events[bit]; |
| 2483 | if (event->hw.flags & PERF_X86_EVENT_AUTO_RELOAD) | 2484 | if (event->hw.flags & PERF_X86_EVENT_AUTO_RELOAD) |
| 2484 | intel_pmu_save_and_restart_reload(event, 0); | 2485 | intel_pmu_save_and_restart_reload(event, 0); |
| @@ -2513,7 +2514,7 @@ static void intel_pmu_drain_pebs_nhm(struct pt_regs *iregs, struct perf_sample_d · 28 unmodified lines | |||
| 2513 | } | 2514 | } |
| 2514 | 2515 | ||
| 2515 | if (unlikely(base >= top)) { | 2516 | if (unlikely(base >= top)) { |
| 2516 | intel_pmu_pebs_event_update_no_drain(cpuc, size); | 2517 | intel_pmu_pebs_event_update_no_drain(cpuc, mask); |
| 2517 | return; | 2518 | return; |
| 2518 | } | 2519 | } |
| 2519 | 2520 | ||
| @@ -2627,7 +2628,7 @@ static void intel_pmu_drain_pebs_icl(struct pt_regs *iregs, struct perf_sample_d · 107 unmodified lines | |||
| 2627 | (hybrid(cpuc->pmu, fixed_cntr_mask64) << INTEL_PMC_IDX_FIXED); | 2628 | (hybrid(cpuc->pmu, fixed_cntr_mask64) << INTEL_PMC_IDX_FIXED); |
| 2628 | 2629 | ||
| 2629 | if (unlikely(base >= top)) { | 2630 | if (unlikely(base >= top)) { |
| 2630 | intel_pmu_pebs_event_update_no_drain(cpuc, X86_PMC_IDX_MAX); | 2631 | intel_pmu_pebs_event_update_no_drain(cpuc, mask); |
| 2631 | return; | 2632 | return; |
| 2632 | } | 2633 | } |
| 2633 | 2634 | ||
| @@ -75,7 +75,7 @@ · 74 unmodified lines | |||
| 75 | #define X86_FEATURE_CENTAUR_MCR ( 3*32+ 3) /* "centaur_mcr" Centaur MCRs (= MTRRs) */ | 75 | #define X86_FEATURE_CENTAUR_MCR ( 3*32+ 3) /* "centaur_mcr" Centaur MCRs (= MTRRs) */ |
| 76 | #define X86_FEATURE_K8 ( 3*32+ 4) /* Opteron, Athlon64 */ | 76 | #define X86_FEATURE_K8 ( 3*32+ 4) /* Opteron, Athlon64 */ |
| 77 | #define X86_FEATURE_ZEN5 ( 3*32+ 5) /* CPU based on Zen5 microarchitecture */ | 77 | #define X86_FEATURE_ZEN5 ( 3*32+ 5) /* CPU based on Zen5 microarchitecture */ |
| 78 | /* Free ( 3*32+ 6) */ | 78 | #define X86_FEATURE_ZEN6 ( 3*32+ 6) /* CPU based on Zen6 microarchitecture */ |
| 79 | /* Free ( 3*32+ 7) */ | 79 | /* Free ( 3*32+ 7) */ |
| 80 | #define X86_FEATURE_CONSTANT_TSC ( 3*32+ 8) /* "constant_tsc" TSC ticks at a constant rate */ | 80 | #define X86_FEATURE_CONSTANT_TSC ( 3*32+ 8) /* "constant_tsc" TSC ticks at a constant rate */ |
| 81 | #define X86_FEATURE_UP ( 3*32+ 9) /* "up" SMP kernel running on UP */ | 81 | #define X86_FEATURE_UP ( 3*32+ 9) /* "up" SMP kernel running on UP */ |
| @@ -116,7 +116,7 @@ enum psc_op { · 115 unmodified lines | |||
| 116 | #define GHCB_MSR_VMPL_REQ 0x016 | 116 | #define GHCB_MSR_VMPL_REQ 0x016 |
| 117 | #define GHCB_MSR_VMPL_REQ_LEVEL(v) \ | 117 | #define GHCB_MSR_VMPL_REQ_LEVEL(v) \ |
| 118 | /* GHCBData[39:32] */ \ | 118 | /* GHCBData[39:32] */ \ |
| 119 | (((u64)(v) & GENMASK_ULL(7, 0) << 32) | \ | 119 | ((((u64)(v) & GENMASK_ULL(7, 0)) << 32) | \ |
| 120 | /* GHCBDdata[11:0] */ \ | 120 | /* GHCBDdata[11:0] */ \ |
| 121 | GHCB_MSR_VMPL_REQ) | 121 | GHCB_MSR_VMPL_REQ) |
| 122 | 122 | ||
| @@ -111,7 +111,9 @@ static bool cfi_paranoid __ro_after_init; · 110 unmodified lines | |||
| 111 | 111 | ||
| 112 | #ifdef CONFIG_MITIGATION_ITS | 112 | #ifdef CONFIG_MITIGATION_ITS |
| 113 | 113 | ||
| 114 | #ifdef CONFIG_MODULES | ||
| 114 | static struct module *its_mod; | 115 | static struct module *its_mod; |
| 116 | #endif | ||
| 115 | static void *its_page; | 117 | static void *its_page; |
| 116 | static unsigned int its_offset; | 118 | static unsigned int its_offset; |
| 117 | 119 | ||
| @@ -149,6 +151,7 @@ static void *its_init_thunk(void *thunk, int reg) · 31 unmodified lines | |||
| 149 | return thunk + offset; | 151 | return thunk + offset; |
| 150 | } | 152 | } |
| 151 | 153 | ||
| 154 | #ifdef CONFIG_MODULES | ||
| 152 | void its_init_mod(struct module *mod) | 155 | void its_init_mod(struct module *mod) |
| 153 | { | 156 | { |
| 154 | if (!cpu_feature_enabled(X86_FEATURE_INDIRECT_THUNK_ITS)) | 157 | if (!cpu_feature_enabled(X86_FEATURE_INDIRECT_THUNK_ITS)) |
| @@ -187,6 +190,7 @@ void its_free_mod(struct module *mod) · 32 unmodified lines | |||
| 187 | } | 190 | } |
| 188 | kfree(mod->its_page_array); | 191 | kfree(mod->its_page_array); |
| 189 | } | 192 | } |
| 193 | #endif /* CONFIG_MODULES */ | ||
| 190 | 194 | ||
| 191 | static void *its_alloc(void) | 195 | static void *its_alloc(void) |
| 192 | { | 196 | { |
| @@ -195,6 +199,7 @@ static void *its_alloc(void) · 2 unmodified lines | |||
| 195 | if (!page) | 199 | if (!page) |
| 196 | return NULL; | 200 | return NULL; |
| 197 | 201 | ||
| 202 | #ifdef CONFIG_MODULES | ||
| 198 | if (its_mod) { | 203 | if (its_mod) { |
| 199 | void *tmp = krealloc(its_mod->its_page_array, | 204 | void *tmp = krealloc(its_mod->its_page_array, |
| 200 | (its_mod->its_num_pages+1) * sizeof(void *), | 205 | (its_mod->its_num_pages+1) * sizeof(void *), |
| @@ -207,6 +212,7 @@ static void *its_alloc(void) · 6 unmodified lines | |||
| 207 | 212 | ||
| 208 | execmem_make_temp_rw(page, PAGE_SIZE); | 213 | execmem_make_temp_rw(page, PAGE_SIZE); |
| 209 | } | 214 | } |
| 215 | #endif /* CONFIG_MODULES */ | ||
| 210 | 216 | ||
| 211 | return no_free_ptr(page); | 217 | return no_free_ptr(page); |
| 212 | } | 218 | } |
| @@ -474,6 +474,11 @@ static void bsp_init_amd(struct cpuinfo_x86 *c) · 473 unmodified lines | |||
| 474 | case 0x60 ... 0x7f: | 474 | case 0x60 ... 0x7f: |
| 475 | setup_force_cpu_cap(X86_FEATURE_ZEN5); | 475 | setup_force_cpu_cap(X86_FEATURE_ZEN5); |
| 476 | break; | 476 | break; |
| 477 | case 0x50 ... 0x5f: | ||
| 478 | case 0x90 ... 0xaf: | ||
| 479 | case 0xc0 ... 0xcf: | ||
| 480 | setup_force_cpu_cap(X86_FEATURE_ZEN6); | ||
| 481 | break; | ||
| 477 | default: | 482 | default: |
| 478 | goto warn; | 483 | goto warn; |
| 479 | } | 484 | } |
| @@ -566,7 +566,7 @@ static void __init lowmem_pfn_init(void) · 565 unmodified lines | |||
| 566 | "only %luMB highmem pages available, ignoring highmem size of %luMB!\n" | 566 | "only %luMB highmem pages available, ignoring highmem size of %luMB!\n" |
| 567 | 567 | ||
| 568 | #define MSG_HIGHMEM_TRIMMED \ | 568 | #define MSG_HIGHMEM_TRIMMED \ |
| 569 | "Warning: only 4GB will be used. Support for for CONFIG_HIGHMEM64G was removed!\n" | 569 | "Warning: only 4GB will be used. Support for CONFIG_HIGHMEM64G was removed!\n" |
| 570 | /* | 570 | /* |
| 571 | * We have more RAM than fits into lowmem - we try to put it into | 571 | * We have more RAM than fits into lowmem - we try to put it into |
| 572 | * highmem, also taking the highmem=x boot parameter into account: | 572 | * highmem, also taking the highmem=x boot parameter into account: |
| @@ -9,6 +9,7 @@ · 8 unmodified lines | |||
| 9 | * not aware of PI. | 9 | * not aware of PI. |
| 10 | */ | 10 | */ |
| 11 | #include <linux/blk-integrity.h> | 11 | #include <linux/blk-integrity.h> |
| 12 | #include <linux/t10-pi.h> | ||
| 12 | #include <linux/workqueue.h> | 13 | #include <linux/workqueue.h> |
| 13 | #include "blk.h" | 14 | #include "blk.h" |
| 14 | 15 | ||
| @@ -43,6 +44,29 @@ static void bio_integrity_verify_fn(struct work_struct *work) · 28 unmodified lines | |||
| 43 | bio_endio(bio); | 44 | bio_endio(bio); |
| 44 | } | 45 | } |
| 45 | 46 | ||
| 47 | #define BIP_CHECK_FLAGS (BIP_CHECK_GUARD | BIP_CHECK_REFTAG | BIP_CHECK_APPTAG) | ||
| 48 | static bool bip_should_check(struct bio_integrity_payload *bip) | ||
| 49 | { | ||
| 50 | return bip->bip_flags & BIP_CHECK_FLAGS; | ||
| 51 | } | ||
| 52 | |||
| 53 | static bool bi_offload_capable(struct blk_integrity *bi) | ||
| 54 | { | ||
| 55 | switch (bi->csum_type) { | ||
| 56 | case BLK_INTEGRITY_CSUM_CRC64: | ||
| 57 | return bi->tuple_size == sizeof(struct crc64_pi_tuple); | ||
| 58 | case BLK_INTEGRITY_CSUM_CRC: | ||
| 59 | case BLK_INTEGRITY_CSUM_IP: | ||
| 60 | return bi->tuple_size == sizeof(struct t10_pi_tuple); | ||
| 61 | default: | ||
| 62 | pr_warn_once("%s: unknown integrity checksum type:%d\n", | ||
| 63 | __func__, bi->csum_type); | ||
| 64 | fallthrough; | ||
| 65 | case BLK_INTEGRITY_CSUM_NONE: | ||
| 66 | return false; | ||
| 67 | } | ||
| 68 | } | ||
| 69 | |||
| 46 | /** | 70 | /** |
| 47 | * __bio_integrity_endio - Integrity I/O completion function | 71 | * __bio_integrity_endio - Integrity I/O completion function |
| 48 | * @bio: Protected bio | 72 | * @bio: Protected bio |
| @@ -54,12 +78,12 @@ static void bio_integrity_verify_fn(struct work_struct *work) · 5 unmodified lines | |||
| 54 | */ | 78 | */ |
| 55 | bool __bio_integrity_endio(struct bio *bio) | 79 | bool __bio_integrity_endio(struct bio *bio) |
| 56 | { | 80 | { |
| 57 | struct blk_integrity *bi = blk_get_integrity(bio->bi_bdev->bd_disk); | ||
| 58 | struct bio_integrity_payload *bip = bio_integrity(bio); | 81 | struct bio_integrity_payload *bip = bio_integrity(bio); |
| 59 | struct bio_integrity_data *bid = | 82 | struct bio_integrity_data *bid = |
| 60 | container_of(bip, struct bio_integrity_data, bip); | 83 | container_of(bip, struct bio_integrity_data, bip); |
| 61 | 84 | ||
| 62 | if (bio_op(bio) == REQ_OP_READ && !bio->bi_status && bi->csum_type) { | 85 | if (bio_op(bio) == REQ_OP_READ && !bio->bi_status && |
| 86 | bip_should_check(bip)) { | ||
| 63 | INIT_WORK(&bid->work, bio_integrity_verify_fn); | 87 | INIT_WORK(&bid->work, bio_integrity_verify_fn); |
| 64 | queue_work(kintegrityd_wq, &bid->work); | 88 | queue_work(kintegrityd_wq, &bid->work); |
| 65 | return false; | 89 | return false; |
| @@ -84,6 +108,7 @@ bool bio_integrity_prep(struct bio *bio) · 18 unmodified lines | |||
| 84 | { | 108 | { |
| 85 | struct blk_integrity *bi = blk_get_integrity(bio->bi_bdev->bd_disk); | 109 | struct blk_integrity *bi = blk_get_integrity(bio->bi_bdev->bd_disk); |
| 86 | struct bio_integrity_data *bid; | 110 | struct bio_integrity_data *bid; |
| 111 | bool set_flags = true; | ||
| 87 | gfp_t gfp = GFP_NOIO; | 112 | gfp_t gfp = GFP_NOIO; |
| 88 | unsigned int len; | 113 | unsigned int len; |
| 89 | void *buf; | 114 | void *buf; |
| @@ -100,19 +125,24 @@ bool bio_integrity_prep(struct bio *bio) · 10 unmodified lines | |||
| 100 | 125 | ||
| 101 | switch (bio_op(bio)) { | 126 | switch (bio_op(bio)) { |
| 102 | case REQ_OP_READ: | 127 | case REQ_OP_READ: |
| 103 | if (bi->flags & BLK_INTEGRITY_NOVERIFY) | 128 | if (bi->flags & BLK_INTEGRITY_NOVERIFY) { |
| 104 | return true; | 129 | if (bi_offload_capable(bi)) |
| 130 | return true; | ||
| 131 | set_flags = false; | ||
| 132 | } | ||
| 105 | break; | 133 | break; |
| 106 | case REQ_OP_WRITE: | 134 | case REQ_OP_WRITE: |
| 107 | if (bi->flags & BLK_INTEGRITY_NOGENERATE) | ||
| 108 | return true; | ||
| 109 | |||
| 110 | /* | 135 | /* |
| 111 | * Zero the memory allocated to not leak uninitialized kernel | 136 | * Zero the memory allocated to not leak uninitialized kernel |
| 112 | * memory to disk for non-integrity metadata where nothing else | 137 | * memory to disk for non-integrity metadata where nothing else |
| 113 | * initializes the memory. | 138 | * initializes the memory. |
| 114 | */ | 139 | */ |
| 115 | if (bi->csum_type == BLK_INTEGRITY_CSUM_NONE) | 140 | if (bi->flags & BLK_INTEGRITY_NOGENERATE) { |
| 141 | if (bi_offload_capable(bi)) | ||
| 142 | return true; | ||
| 143 | set_flags = false; | ||
| 144 | gfp |= __GFP_ZERO; | ||
| 145 | } else if (bi->csum_type == BLK_INTEGRITY_CSUM_NONE) | ||
| 116 | gfp |= __GFP_ZERO; | 146 | gfp |= __GFP_ZERO; |
| 117 | break; | 147 | break; |
| 118 | default: | 148 | default: |
| @@ -137,19 +167,21 @@ bool bio_integrity_prep(struct bio *bio) · 18 unmodified lines | |||
| 137 | bid->bip.bip_flags |= BIP_BLOCK_INTEGRITY; | 167 | bid->bip.bip_flags |= BIP_BLOCK_INTEGRITY; |
| 138 | bip_set_seed(&bid->bip, bio->bi_iter.bi_sector); | 168 | bip_set_seed(&bid->bip, bio->bi_iter.bi_sector); |
| 139 | 169 | ||
| 140 | if (bi->csum_type == BLK_INTEGRITY_CSUM_IP) | 170 | if (set_flags) { |
| 141 | bid->bip.bip_flags |= BIP_IP_CHECKSUM; | 171 | if (bi->csum_type == BLK_INTEGRITY_CSUM_IP) |
| 142 | if (bi->csum_type) | 172 | bid->bip.bip_flags |= BIP_IP_CHECKSUM; |
| 143 | bid->bip.bip_flags |= BIP_CHECK_GUARD; | 173 | if (bi->csum_type) |
| 144 | if (bi->flags & BLK_INTEGRITY_REF_TAG) | 174 | bid->bip.bip_flags |= BIP_CHECK_GUARD; |
| 145 | bid->bip.bip_flags |= BIP_CHECK_REFTAG; | 175 | if (bi->flags & BLK_INTEGRITY_REF_TAG) |
| 176 | bid->bip.bip_flags |= BIP_CHECK_REFTAG; | ||
| 177 | } | ||
| 146 | 178 | ||
| 147 | if (bio_integrity_add_page(bio, virt_to_page(buf), len, | 179 | if (bio_integrity_add_page(bio, virt_to_page(buf), len, |
| 148 | offset_in_page(buf)) < len) | 180 | offset_in_page(buf)) < len) |
| 149 | goto err_end_io; | 181 | goto err_end_io; |
| 150 | 182 | ||
| 151 | /* Auto-generate integrity metadata if this is a write */ | 183 | /* Auto-generate integrity metadata if this is a write */ |
| 152 | if (bio_data_dir(bio) == WRITE) | 184 | if (bio_data_dir(bio) == WRITE && bip_should_check(&bid->bip)) |
| 153 | blk_integrity_generate(bio); | 185 | blk_integrity_generate(bio); |
| 154 | else | 186 | else |
| 155 | bid->saved_bio_iter = bio->bi_iter; | 187 | bid->saved_bio_iter = bio->bi_iter; |
| @@ -611,7 +611,7 @@ struct bio *bio_kmalloc(unsigned short nr_vecs, gfp_t gfp_mask) · 610 unmodified lines | |||
| 611 | { | 611 | { |
| 612 | struct bio *bio; | 612 | struct bio *bio; |
| 613 | 613 | ||
| 614 | if (nr_vecs > UIO_MAXIOV) | 614 | if (nr_vecs > BIO_MAX_INLINE_VECS) |
| 615 | return NULL; | 615 | return NULL; |
| 616 | return kmalloc(struct_size(bio, bi_inline_vecs, nr_vecs), gfp_mask); | 616 | return kmalloc(struct_size(bio, bi_inline_vecs, nr_vecs), gfp_mask); |
| 617 | } | 617 | } |
| @@ -455,7 +455,7 @@ priority_bands_fops_write(struct file *file, const char __user *user_buf, size_t · 454 unmodified lines | |||
| 455 | if (ret < 0) | 455 | if (ret < 0) |
| 456 | return ret; | 456 | return ret; |
| 457 | 457 | ||
| 458 | buf[size] = '\0'; | 458 | buf[ret] = '\0'; |
| 459 | ret = sscanf(buf, "%u %u %u %u", &band, &grace_period, &process_grace_period, | 459 | ret = sscanf(buf, "%u %u %u %u", &band, &grace_period, &process_grace_period, |
| 460 | &process_quantum); | 460 | &process_quantum); |
| 461 | if (ret != 4) | 461 | if (ret != 4) |
| @@ -231,16 +231,18 @@ static int acpi_pptt_leaf_node(struct acpi_table_header *table_hdr, · 230 unmodified lines | |||
| 231 | sizeof(struct acpi_table_pptt)); | 231 | sizeof(struct acpi_table_pptt)); |
| 232 | proc_sz = sizeof(struct acpi_pptt_processor); | 232 | proc_sz = sizeof(struct acpi_pptt_processor); |
| 233 | 233 | ||
| 234 | while ((unsigned long)entry + proc_sz < table_end) { | 234 | /* ignore subtable types that are smaller than a processor node */ |
| 235 | while ((unsigned long)entry + proc_sz <= table_end) { | ||
| 235 | cpu_node = (struct acpi_pptt_processor *)entry; | 236 | cpu_node = (struct acpi_pptt_processor *)entry; |
| 237 | |||
| 236 | if (entry->type == ACPI_PPTT_TYPE_PROCESSOR && | 238 | if (entry->type == ACPI_PPTT_TYPE_PROCESSOR && |
| 237 | cpu_node->parent == node_entry) | 239 | cpu_node->parent == node_entry) |
| 238 | return 0; | 240 | return 0; |
| 239 | if (entry->length == 0) | 241 | if (entry->length == 0) |
| 240 | return 0; | 242 | return 0; |
| 243 | |||
| 241 | entry = ACPI_ADD_PTR(struct acpi_subtable_header, entry, | 244 | entry = ACPI_ADD_PTR(struct acpi_subtable_header, entry, |
| 242 | entry->length); | 245 | entry->length); |
| 243 | |||
| 244 | } | 246 | } |
| 245 | return 1; | 247 | return 1; |
| 246 | } | 248 | } |
| @@ -273,15 +275,18 @@ static struct acpi_pptt_processor *acpi_find_processor_node(struct acpi_table_he · 26 unmodified lines | |||
| 273 | proc_sz = sizeof(struct acpi_pptt_processor); | 275 | proc_sz = sizeof(struct acpi_pptt_processor); |
| 274 | 276 | ||
| 275 | /* find the processor structure associated with this cpuid */ | 277 | /* find the processor structure associated with this cpuid */ |
| 276 | while ((unsigned long)entry + proc_sz < table_end) { | 278 | while ((unsigned long)entry + proc_sz <= table_end) { |
| 277 | cpu_node = (struct acpi_pptt_processor *)entry; | 279 | cpu_node = (struct acpi_pptt_processor *)entry; |
| 278 | 280 | ||
| 279 | if (entry->length == 0) { | 281 | if (entry->length == 0) { |
| 280 | pr_warn("Invalid zero length subtable\n"); | 282 | pr_warn("Invalid zero length subtable\n"); |
| 281 | break; | 283 | break; |
| 282 | } | 284 | } |
| 285 | /* entry->length may not equal proc_sz, revalidate the processor structure length */ | ||
| 283 | if (entry->type == ACPI_PPTT_TYPE_PROCESSOR && | 286 | if (entry->type == ACPI_PPTT_TYPE_PROCESSOR && |
| 284 | acpi_cpu_id == cpu_node->acpi_processor_id && | 287 | acpi_cpu_id == cpu_node->acpi_processor_id && |
| 288 | (unsigned long)entry + entry->length <= table_end && | ||
| 289 | entry->length == proc_sz + cpu_node->number_of_priv_resources * sizeof(u32) && | ||
| 285 | acpi_pptt_leaf_node(table_hdr, cpu_node)) { | 290 | acpi_pptt_leaf_node(table_hdr, cpu_node)) { |
| 286 | return (struct acpi_pptt_processor *)entry; | 291 | return (struct acpi_pptt_processor *)entry; |
| 287 | } | 292 | } |
| @@ -1708,7 +1708,7 @@ static void ublk_cancel_cmd(struct ublk_queue *ubq, unsigned tag, · 1707 unmodified lines | |||
| 1708 | * that ublk_dispatch_req() is always called | 1708 | * that ublk_dispatch_req() is always called |
| 1709 | */ | 1709 | */ |
| 1710 | req = blk_mq_tag_to_rq(ub->tag_set.tags[ubq->q_id], tag); | 1710 | req = blk_mq_tag_to_rq(ub->tag_set.tags[ubq->q_id], tag); |
| 1711 | if (req && blk_mq_request_started(req)) | 1711 | if (req && blk_mq_request_started(req) && req->tag == tag) |
| 1712 | return; | 1712 | return; |
| 1713 | 1713 | ||
| 1714 | spin_lock(&ubq->cancel_lock); | 1714 | spin_lock(&ubq->cancel_lock); |
| @@ -201,7 +201,7 @@ static void tpm_buf_read(struct tpm_buf *buf, off_t *offset, size_t count, void · 200 unmodified lines | |||
| 201 | */ | 201 | */ |
| 202 | u8 tpm_buf_read_u8(struct tpm_buf *buf, off_t *offset) | 202 | u8 tpm_buf_read_u8(struct tpm_buf *buf, off_t *offset) |
| 203 | { | 203 | { |
| 204 | u8 value; | 204 | u8 value = 0; |
| 205 | 205 | ||
| 206 | tpm_buf_read(buf, offset, sizeof(value), &value); | 206 | tpm_buf_read(buf, offset, sizeof(value), &value); |
| 207 | 207 | ||
| @@ -218,7 +218,7 @@ EXPORT_SYMBOL_GPL(tpm_buf_read_u8); · 10 unmodified lines | |||
| 218 | */ | 218 | */ |
| 219 | u16 tpm_buf_read_u16(struct tpm_buf *buf, off_t *offset) | 219 | u16 tpm_buf_read_u16(struct tpm_buf *buf, off_t *offset) |
| 220 | { | 220 | { |
| 221 | u16 value; | 221 | u16 value = 0; |
| 222 | 222 | ||
| 223 | tpm_buf_read(buf, offset, sizeof(value), &value); | 223 | tpm_buf_read(buf, offset, sizeof(value), &value); |
| 224 | 224 | ||
| @@ -235,7 +235,7 @@ EXPORT_SYMBOL_GPL(tpm_buf_read_u16); · 10 unmodified lines | |||
| 235 | */ | 235 | */ |
| 236 | u32 tpm_buf_read_u32(struct tpm_buf *buf, off_t *offset) | 236 | u32 tpm_buf_read_u32(struct tpm_buf *buf, off_t *offset) |
| 237 | { | 237 | { |
| 238 | u32 value; | 238 | u32 value = 0; |
| 239 | 239 | ||
| 240 | tpm_buf_read(buf, offset, sizeof(value), &value); | 240 | tpm_buf_read(buf, offset, sizeof(value), &value); |
| 241 | 241 | ||
| @@ -40,11 +40,6 @@ · 39 unmodified lines | |||
| 40 | * | 40 | * |
| 41 | * These are the usage functions: | 41 | * These are the usage functions: |
| 42 | * | 42 | * |
| 43 | * tpm2_start_auth_session() which allocates the opaque auth structure | ||
| 44 | * and gets a session from the TPM. This must be called before | ||
| 45 | * any of the following functions. The session is protected by a | ||
| 46 | * session_key which is derived from a random salt value | ||
| 47 | * encrypted to the NULL seed. | ||
| 48 | * tpm2_end_auth_session() kills the session and frees the resources. | 43 | * tpm2_end_auth_session() kills the session and frees the resources. |
| 49 | * Under normal operation this function is done by | 44 | * Under normal operation this function is done by |
| 50 | * tpm_buf_check_hmac_response(), so this is only to be used on | 45 | * tpm_buf_check_hmac_response(), so this is only to be used on |
| @@ -963,16 +958,13 @@ err: · 912 unmodified lines | |||
| 963 | } | 958 | } |
| 964 | 959 | ||
| 965 | /** | 960 | /** |
| 966 | * tpm2_start_auth_session() - create a HMAC authentication session with the TPM | 961 | * tpm2_start_auth_session() - Create an a HMAC authentication session |
| 967 | * @chip: the TPM chip structure to create the session with | 962 | * @chip: A TPM chip |
| 968 | * | 963 | * |
| 969 | * This function loads the NULL seed from its saved context and starts | 964 | * Loads the ephemeral key (null seed), and starts an HMAC authenticated |
| 970 | * an authentication session on the null seed, fills in the | 965 | * session. The null seed is flushed before the return. |
| 971 | * @chip->auth structure to contain all the session details necessary | ||
| 972 | * for performing the HMAC, encrypt and decrypt operations and | ||
| 973 | * returns. The NULL seed is flushed before this function returns. | ||
| 974 | * | 966 | * |
| 975 | * Return: zero on success or actual error encountered. | 967 | * Returns zero on success, or a POSIX error code. |
| 976 | */ | 968 | */ |
| 977 | int tpm2_start_auth_session(struct tpm_chip *chip) | 969 | int tpm2_start_auth_session(struct tpm_chip *chip) |
| 978 | { | 970 | { |
| @@ -1024,7 +1016,7 @@ int tpm2_start_auth_session(struct tpm_chip *chip) · 45 unmodified lines | |||
| 1024 | /* hash algorithm for session */ | 1016 | /* hash algorithm for session */ |
| 1025 | tpm_buf_append_u16(&buf, TPM_ALG_SHA256); | 1017 | tpm_buf_append_u16(&buf, TPM_ALG_SHA256); |
| 1026 | 1018 | ||
| 1027 | rc = tpm_transmit_cmd(chip, &buf, 0, "start auth session"); | 1019 | rc = tpm_ret_to_err(tpm_transmit_cmd(chip, &buf, 0, "StartAuthSession")); |
| 1028 | tpm2_flush_context(chip, null_key); | 1020 | tpm2_flush_context(chip, null_key); |
| 1029 | 1021 | ||
| 1030 | if (rc == TPM2_RC_SUCCESS) | 1022 | if (rc == TPM2_RC_SUCCESS) |
| @@ -54,7 +54,7 @@ enum tis_int_flags { · 53 unmodified lines | |||
| 54 | enum tis_defaults { | 54 | enum tis_defaults { |
| 55 | TIS_MEM_LEN = 0x5000, | 55 | TIS_MEM_LEN = 0x5000, |
| 56 | TIS_SHORT_TIMEOUT = 750, /* ms */ | 56 | TIS_SHORT_TIMEOUT = 750, /* ms */ |
| 57 | TIS_LONG_TIMEOUT = 2000, /* 2 sec */ | 57 | TIS_LONG_TIMEOUT = 4000, /* 4 secs */ |
| 58 | TIS_TIMEOUT_MIN_ATML = 14700, /* usecs */ | 58 | TIS_TIMEOUT_MIN_ATML = 14700, /* usecs */ |
| 59 | TIS_TIMEOUT_MAX_ATML = 15000, /* usecs */ | 59 | TIS_TIMEOUT_MAX_ATML = 15000, /* usecs */ |
| 60 | }; | 60 | }; |
| @@ -320,8 +320,9 @@ void dma_resv_add_fence(struct dma_resv *obj, struct dma_fence *fence, · 319 unmodified lines | |||
| 320 | count++; | 320 | count++; |
| 321 | 321 | ||
| 322 | dma_resv_list_set(fobj, i, fence, usage); | 322 | dma_resv_list_set(fobj, i, fence, usage); |
| 323 | /* pointer update must be visible before we extend the num_fences */ | 323 | /* fence update must be visible before we extend the num_fences */ |
| 324 | smp_store_mb(fobj->num_fences, count); | 324 | smp_wmb(); |
| 325 | fobj->num_fences = count; | ||
| 325 | } | 326 | } |
| 326 | EXPORT_SYMBOL(dma_resv_add_fence); | 327 | EXPORT_SYMBOL(dma_resv_add_fence); |
| 327 | 328 | ||
| @@ -342,6 +342,9 @@ static void pt_cmd_callback_work(void *data, int err) · 341 unmodified lines | |||
| 342 | struct pt_dma_chan *chan; | 342 | struct pt_dma_chan *chan; |
| 343 | unsigned long flags; | 343 | unsigned long flags; |
| 344 | 344 | ||
| 345 | if (!desc) | ||
| 346 | return; | ||
| 347 | |||
| 345 | dma_chan = desc->vd.tx.chan; | 348 | dma_chan = desc->vd.tx.chan; |
| 346 | chan = to_pt_chan(dma_chan); | 349 | chan = to_pt_chan(dma_chan); |
| 347 | 350 | ||
| @@ -355,16 +358,14 @@ static void pt_cmd_callback_work(void *data, int err) · 7 unmodified lines | |||
| 355 | desc->status = DMA_ERROR; | 358 | desc->status = DMA_ERROR; |
| 356 | 359 | ||
| 357 | spin_lock_irqsave(&chan->vc.lock, flags); | 360 | spin_lock_irqsave(&chan->vc.lock, flags); |
| 358 | if (desc) { | 361 | if (desc->status != DMA_COMPLETE) { |
| 359 | if (desc->status != DMA_COMPLETE) { | 362 | if (desc->status != DMA_ERROR) |
| 360 | if (desc->status != DMA_ERROR) | 363 | desc->status = DMA_COMPLETE; |
| 361 | desc->status = DMA_COMPLETE; | ||
| 362 | 364 | ||
| 363 | dma_cookie_complete(tx_desc); | 365 | dma_cookie_complete(tx_desc); |
| 364 | dma_descriptor_unmap(tx_desc); | 366 | dma_descriptor_unmap(tx_desc); |
| 365 | } else { | 367 | } else { |
| 366 | tx_desc = NULL; | 368 | tx_desc = NULL; |
| 367 | } | ||
| 368 | } | 369 | } |
| 369 | spin_unlock_irqrestore(&chan->vc.lock, flags); | 370 | spin_unlock_irqrestore(&chan->vc.lock, flags); |
| 370 | 371 | ||
| @@ -841,9 +841,9 @@ static int dmatest_func(void *data) · 840 unmodified lines | |||
| 841 | } else { | 841 | } else { |
| 842 | dma_async_issue_pending(chan); | 842 | dma_async_issue_pending(chan); |
| 843 | 843 | ||
| 844 | wait_event_timeout(thread->done_wait, | 844 | wait_event_freezable_timeout(thread->done_wait, |
| 845 | done->done, | 845 | done->done, |
| 846 | msecs_to_jiffies(params->timeout)); | 846 | msecs_to_jiffies(params->timeout)); |
| 847 | 847 | ||
| 848 | status = dma_async_is_tx_complete(chan, cookie, NULL, | 848 | status = dma_async_is_tx_complete(chan, cookie, NULL, |
| 849 | NULL); | 849 | NULL); |
| @@ -57,7 +57,7 @@ static irqreturn_t fsl_edma3_tx_handler(int irq, void *dev_id) · 56 unmodified lines | |||
| 57 | 57 | ||
| 58 | intr = edma_readl_chreg(fsl_chan, ch_int); | 58 | intr = edma_readl_chreg(fsl_chan, ch_int); |
| 59 | if (!intr) | 59 | if (!intr) |
| 60 | return IRQ_HANDLED; | 60 | return IRQ_NONE; |
| 61 | 61 | ||
| 62 | edma_writel_chreg(fsl_chan, 1, ch_int); | 62 | edma_writel_chreg(fsl_chan, 1, ch_int); |
| 63 | 63 | ||
| @@ -222,7 +222,7 @@ static int idxd_cdev_open(struct inode *inode, struct file *filp) · 221 unmodified lines | |||
| 222 | struct idxd_wq *wq; | 222 | struct idxd_wq *wq; |
| 223 | struct device *dev, *fdev; | 223 | struct device *dev, *fdev; |
| 224 | int rc = 0; | 224 | int rc = 0; |
| 225 | struct iommu_sva *sva; | 225 | struct iommu_sva *sva = NULL; |
| 226 | unsigned int pasid; | 226 | unsigned int pasid; |
| 227 | struct idxd_cdev *idxd_cdev; | 227 | struct idxd_cdev *idxd_cdev; |
| 228 | 228 | ||
| @@ -317,7 +317,7 @@ failed_set_pasid: · 88 unmodified lines | |||
| 317 | if (device_user_pasid_enabled(idxd)) | 317 | if (device_user_pasid_enabled(idxd)) |
| 318 | idxd_xa_pasid_remove(ctx); | 318 | idxd_xa_pasid_remove(ctx); |
| 319 | failed_get_pasid: | 319 | failed_get_pasid: |
| 320 | if (device_user_pasid_enabled(idxd)) | 320 | if (device_user_pasid_enabled(idxd) && !IS_ERR_OR_NULL(sva)) |
| 321 | iommu_sva_unbind_device(sva); | 321 | iommu_sva_unbind_device(sva); |
| 322 | failed: | 322 | failed: |
| 323 | mutex_unlock(&wq->wq_lock); | 323 | mutex_unlock(&wq->wq_lock); |
| @@ -407,6 +407,9 @@ static int idxd_cdev_mmap(struct file *filp, struct vm_area_struct *vma) · 83 unmodified lines | |||
| 407 | if (!idxd->user_submission_safe && !capable(CAP_SYS_RAWIO)) | 407 | if (!idxd->user_submission_safe && !capable(CAP_SYS_RAWIO)) |
| 408 | return -EPERM; | 408 | return -EPERM; |
| 409 | 409 | ||
| 410 | if (current->mm != ctx->mm) | ||
| 411 | return -EPERM; | ||
| 412 | |||
| 410 | rc = check_vma(wq, vma, __func__); | 413 | rc = check_vma(wq, vma, __func__); |
| 411 | if (rc < 0) | 414 | if (rc < 0) |
| 412 | return rc; | 415 | return rc; |
| @@ -473,6 +476,9 @@ static ssize_t idxd_cdev_write(struct file *filp, const char __user *buf, size_t · 60 unmodified lines | |||
| 473 | ssize_t written = 0; | 476 | ssize_t written = 0; |
| 474 | int i; | 477 | int i; |
| 475 | 478 | ||
| 479 | if (current->mm != ctx->mm) | ||
| 480 | return -EPERM; | ||
| 481 | |||
| 476 | for (i = 0; i < len/sizeof(struct dsa_hw_desc); i++) { | 482 | for (i = 0; i < len/sizeof(struct dsa_hw_desc); i++) { |
| 477 | int rc = idxd_submit_user_descriptor(ctx, udesc + i); | 483 | int rc = idxd_submit_user_descriptor(ctx, udesc + i); |
| 478 | 484 | ||
| @@ -493,6 +499,9 @@ static __poll_t idxd_cdev_poll(struct file *filp, · 14 unmodified lines | |||
| 493 | struct idxd_device *idxd = wq->idxd; | 499 | struct idxd_device *idxd = wq->idxd; |
| 494 | __poll_t out = 0; | 500 | __poll_t out = 0; |
| 495 | 501 | ||
| 502 | if (current->mm != ctx->mm) | ||
| 503 | return POLLNVAL; | ||
| 504 | |||
| 496 | poll_wait(filp, &wq->err_queue, wait); | 505 | poll_wait(filp, &wq->err_queue, wait); |
| 497 | spin_lock(&idxd->dev_lock); | 506 | spin_lock(&idxd->dev_lock); |
| 498 | if (idxd->sw_err.valid) | 507 | if (idxd->sw_err.valid) |
| @@ -155,6 +155,25 @@ static void idxd_cleanup_interrupts(struct idxd_device *idxd) · 154 unmodified lines | |||
| 155 | pci_free_irq_vectors(pdev); | 155 | pci_free_irq_vectors(pdev); |
| 156 | } | 156 | } |
| 157 | 157 | ||
| 158 | static void idxd_clean_wqs(struct idxd_device *idxd) | ||
| 159 | { | ||
| 160 | struct idxd_wq *wq; | ||
| 161 | struct device *conf_dev; | ||
| 162 | int i; | ||
| 163 | |||
| 164 | for (i = 0; i < idxd->max_wqs; i++) { | ||
| 165 | wq = idxd->wqs[i]; | ||
| 166 | if (idxd->hw.wq_cap.op_config) | ||
| 167 | bitmap_free(wq->opcap_bmap); | ||
| 168 | kfree(wq->wqcfg); | ||
| 169 | conf_dev = wq_confdev(wq); | ||
| 170 | put_device(conf_dev); | ||
| 171 | kfree(wq); | ||
| 172 | } | ||
| 173 | bitmap_free(idxd->wq_enable_map); | ||
| 174 | kfree(idxd->wqs); | ||
| 175 | } | ||
| 176 | |||
| 158 | static int idxd_setup_wqs(struct idxd_device *idxd) | 177 | static int idxd_setup_wqs(struct idxd_device *idxd) |
| 159 | { | 178 | { |
| 160 | struct device *dev = &idxd->pdev->dev; | 179 | struct device *dev = &idxd->pdev->dev; |
| @@ -169,8 +188,8 @@ static int idxd_setup_wqs(struct idxd_device *idxd) · 8 unmodified lines | |||
| 169 | 188 | ||
| 170 | idxd->wq_enable_map = bitmap_zalloc_node(idxd->max_wqs, GFP_KERNEL, dev_to_node(dev)); | 189 | idxd->wq_enable_map = bitmap_zalloc_node(idxd->max_wqs, GFP_KERNEL, dev_to_node(dev)); |
| 171 | if (!idxd->wq_enable_map) { | 190 | if (!idxd->wq_enable_map) { |
| 172 | kfree(idxd->wqs); | 191 | rc = -ENOMEM; |
| 173 | return -ENOMEM; | 192 | goto err_bitmap; |
| 174 | } | 193 | } |
| 175 | 194 | ||
| 176 | for (i = 0; i < idxd->max_wqs; i++) { | 195 | for (i = 0; i < idxd->max_wqs; i++) { |
| @@ -189,10 +208,8 @@ static int idxd_setup_wqs(struct idxd_device *idxd) · 12 unmodified lines | |||
| 189 | conf_dev->bus = &dsa_bus_type; | 208 | conf_dev->bus = &dsa_bus_type; |
| 190 | conf_dev->type = &idxd_wq_device_type; | 209 | conf_dev->type = &idxd_wq_device_type; |
| 191 | rc = dev_set_name(conf_dev, "wq%d.%d", idxd->id, wq->id); | 210 | rc = dev_set_name(conf_dev, "wq%d.%d", idxd->id, wq->id); |
| 192 | if (rc < 0) { | 211 | if (rc < 0) |
| 193 | put_device(conf_dev); | ||
| 194 | goto err; | 212 | goto err; |
| 195 | } | ||
| 196 | 213 | ||
| 197 | mutex_init(&wq->wq_lock); | 214 | mutex_init(&wq->wq_lock); |
| 198 | init_waitqueue_head(&wq->err_queue); | 215 | init_waitqueue_head(&wq->err_queue); |
| @@ -203,7 +220,6 @@ static int idxd_setup_wqs(struct idxd_device *idxd) · 4 unmodified lines | |||
| 203 | wq->enqcmds_retries = IDXD_ENQCMDS_RETRIES; | 220 | wq->enqcmds_retries = IDXD_ENQCMDS_RETRIES; |
| 204 | wq->wqcfg = kzalloc_node(idxd->wqcfg_size, GFP_KERNEL, dev_to_node(dev)); | 221 | wq->wqcfg = kzalloc_node(idxd->wqcfg_size, GFP_KERNEL, dev_to_node(dev)); |
| 205 | if (!wq->wqcfg) { | 222 | if (!wq->wqcfg) { |
| 206 | put_device(conf_dev); | ||
| 207 | rc = -ENOMEM; | 223 | rc = -ENOMEM; |
| 208 | goto err; | 224 | goto err; |
| 209 | } | 225 | } |
| @@ -211,9 +227,8 @@ static int idxd_setup_wqs(struct idxd_device *idxd) · 1 unmodified line | |||
| 211 | if (idxd->hw.wq_cap.op_config) { | 227 | if (idxd->hw.wq_cap.op_config) { |
| 212 | wq->opcap_bmap = bitmap_zalloc(IDXD_MAX_OPCAP_BITS, GFP_KERNEL); | 228 | wq->opcap_bmap = bitmap_zalloc(IDXD_MAX_OPCAP_BITS, GFP_KERNEL); |
| 213 | if (!wq->opcap_bmap) { | 229 | if (!wq->opcap_bmap) { |
| 214 | put_device(conf_dev); | ||
| 215 | rc = -ENOMEM; | 230 | rc = -ENOMEM; |
| 216 | goto err; | 231 | goto err_opcap_bmap; |
| 217 | } | 232 | } |
| 218 | bitmap_copy(wq->opcap_bmap, idxd->opcap_bmap, IDXD_MAX_OPCAP_BITS); | 233 | bitmap_copy(wq->opcap_bmap, idxd->opcap_bmap, IDXD_MAX_OPCAP_BITS); |
| 219 | } | 234 | } |
| @@ -224,15 +239,46 @@ static int idxd_setup_wqs(struct idxd_device *idxd) · 4 unmodified lines | |||
| 224 | 239 | ||
| 225 | return 0; | 240 | return 0; |
| 226 | 241 | ||
| 227 | err: | 242 | err_opcap_bmap: |
| 243 | kfree(wq->wqcfg); | ||
| 244 | |||
| 245 | err: | ||
| 246 | put_device(conf_dev); | ||
| 247 | kfree(wq); | ||
| 248 | |||
| 228 | while (--i >= 0) { | 249 | while (--i >= 0) { |
| 229 | wq = idxd->wqs[i]; | 250 | wq = idxd->wqs[i]; |
| 251 | if (idxd->hw.wq_cap.op_config) | ||
| 252 | bitmap_free(wq->opcap_bmap); | ||
| 253 | kfree(wq->wqcfg); | ||
| 230 | conf_dev = wq_confdev(wq); | 254 | conf_dev = wq_confdev(wq); |
| 231 | put_device(conf_dev); | 255 | put_device(conf_dev); |
| 256 | kfree(wq); | ||
| 257 | |||
| 232 | } | 258 | } |
| 259 | bitmap_free(idxd->wq_enable_map); | ||
| 260 | |||
| 261 | err_bitmap: | ||
| 262 | kfree(idxd->wqs); | ||
| 263 | |||
| 233 | return rc; | 264 | return rc; |
| 234 | } | 265 | } |
| 235 | 266 | ||
| 267 | static void idxd_clean_engines(struct idxd_device *idxd) | ||
| 268 | { | ||
| 269 | struct idxd_engine *engine; | ||
| 270 | struct device *conf_dev; | ||
| 271 | int i; | ||
| 272 | |||
| 273 | for (i = 0; i < idxd->max_engines; i++) { | ||
| 274 | engine = idxd->engines[i]; | ||
| 275 | conf_dev = engine_confdev(engine); | ||
| 276 | put_device(conf_dev); | ||
| 277 | kfree(engine); | ||
| 278 | } | ||
| 279 | kfree(idxd->engines); | ||
| 280 | } | ||
| 281 | |||
| 236 | static int idxd_setup_engines(struct idxd_device *idxd) | 282 | static int idxd_setup_engines(struct idxd_device *idxd) |
| 237 | { | 283 | { |
| 238 | struct idxd_engine *engine; | 284 | struct idxd_engine *engine; |
| @@ -263,6 +309,7 @@ static int idxd_setup_engines(struct idxd_device *idxd) · 24 unmodified lines | |||
| 263 | rc = dev_set_name(conf_dev, "engine%d.%d", idxd->id, engine->id); | 309 | rc = dev_set_name(conf_dev, "engine%d.%d", idxd->id, engine->id); |
| 264 | if (rc < 0) { | 310 | if (rc < 0) { |
| 265 | put_device(conf_dev); | 311 | put_device(conf_dev); |
| 312 | kfree(engine); | ||
| 266 | goto err; | 313 | goto err; |
| 267 | } | 314 | } |
| 268 | 315 | ||
| @@ -276,10 +323,26 @@ static int idxd_setup_engines(struct idxd_device *idxd) · 7 unmodified lines | |||
| 276 | engine = idxd->engines[i]; | 323 | engine = idxd->engines[i]; |
| 277 | conf_dev = engine_confdev(engine); | 324 | conf_dev = engine_confdev(engine); |
| 278 | put_device(conf_dev); | 325 | put_device(conf_dev); |
| 326 | kfree(engine); | ||
| 279 | } | 327 | } |
| 328 | kfree(idxd->engines); | ||
| 329 | |||
| 280 | return rc; | 330 | return rc; |
| 281 | } | 331 | } |
| 282 | 332 | ||
| 333 | static void idxd_clean_groups(struct idxd_device *idxd) | ||
| 334 | { | ||
| 335 | struct idxd_group *group; | ||
| 336 | int i; | ||
| 337 | |||
| 338 | for (i = 0; i < idxd->max_groups; i++) { | ||
| 339 | group = idxd->groups[i]; | ||
| 340 | put_device(group_confdev(group)); | ||
| 341 | kfree(group); | ||
| 342 | } | ||
| 343 | kfree(idxd->groups); | ||
| 344 | } | ||
| 345 | |||
| 283 | static int idxd_setup_groups(struct idxd_device *idxd) | 346 | static int idxd_setup_groups(struct idxd_device *idxd) |
| 284 | { | 347 | { |
| 285 | struct device *dev = &idxd->pdev->dev; | 348 | struct device *dev = &idxd->pdev->dev; |
| @@ -310,6 +373,7 @@ static int idxd_setup_groups(struct idxd_device *idxd) · 24 unmodified lines | |||
| 310 | rc = dev_set_name(conf_dev, "group%d.%d", idxd->id, group->id); | 373 | rc = dev_set_name(conf_dev, "group%d.%d", idxd->id, group->id); |
| 311 | if (rc < 0) { | 374 | if (rc < 0) { |
| 312 | put_device(conf_dev); | 375 | put_device(conf_dev); |
| 376 | kfree(group); | ||
| 313 | goto err; | 377 | goto err; |
| 314 | } | 378 | } |
| 315 | 379 | ||
| @@ -334,20 +398,18 @@ static int idxd_setup_groups(struct idxd_device *idxd) · 18 unmodified lines | |||
| 334 | while (--i >= 0) { | 398 | while (--i >= 0) { |
| 335 | group = idxd->groups[i]; | 399 | group = idxd->groups[i]; |
| 336 | put_device(group_confdev(group)); | 400 | put_device(group_confdev(group)); |
| 401 | kfree(group); | ||
| 337 | } | 402 | } |
| 403 | kfree(idxd->groups); | ||
| 404 | |||
| 338 | return rc; | 405 | return rc; |
| 339 | } | 406 | } |
| 340 | 407 | ||
| 341 | static void idxd_cleanup_internals(struct idxd_device *idxd) | 408 | static void idxd_cleanup_internals(struct idxd_device *idxd) |
| 342 | { | 409 | { |
| 343 | int i; | 410 | idxd_clean_groups(idxd); |
| 344 | 411 | idxd_clean_engines(idxd); | |
| 345 | for (i = 0; i < idxd->max_groups; i++) | 412 | idxd_clean_wqs(idxd); |
| 346 | put_device(group_confdev(idxd->groups[i])); | ||
| 347 | for (i = 0; i < idxd->max_engines; i++) | ||
| 348 | put_device(engine_confdev(idxd->engines[i])); | ||
| 349 | for (i = 0; i < idxd->max_wqs; i++) | ||
| 350 | put_device(wq_confdev(idxd->wqs[i])); | ||
| 351 | destroy_workqueue(idxd->wq); | 413 | destroy_workqueue(idxd->wq); |
| 352 | } | 414 | } |
| 353 | 415 | ||
| @@ -390,7 +452,7 @@ static int idxd_init_evl(struct idxd_device *idxd) · 36 unmodified lines | |||
| 390 | static int idxd_setup_internals(struct idxd_device *idxd) | 452 | static int idxd_setup_internals(struct idxd_device *idxd) |
| 391 | { | 453 | { |
| 392 | struct device *dev = &idxd->pdev->dev; | 454 | struct device *dev = &idxd->pdev->dev; |
| 393 | int rc, i; | 455 | int rc; |
| 394 | 456 | ||
| 395 | init_waitqueue_head(&idxd->cmd_waitq); | 457 | init_waitqueue_head(&idxd->cmd_waitq); |
| 396 | 458 | ||
| @@ -421,14 +483,11 @@ static int idxd_setup_internals(struct idxd_device *idxd) · 24 unmodified lines | |||
| 421 | err_evl: | 483 | err_evl: |
| 422 | destroy_workqueue(idxd->wq); | 484 | destroy_workqueue(idxd->wq); |
| 423 | err_wkq_create: | 485 | err_wkq_create: |
| 424 | for (i = 0; i < idxd->max_groups; i++) | 486 | idxd_clean_groups(idxd); |
| 425 | put_device(group_confdev(idxd->groups[i])); | ||
| 426 | err_group: | 487 | err_group: |
| 427 | for (i = 0; i < idxd->max_engines; i++) | 488 | idxd_clean_engines(idxd); |
| 428 | put_device(engine_confdev(idxd->engines[i])); | ||
| 429 | err_engine: | 489 | err_engine: |
| 430 | for (i = 0; i < idxd->max_wqs; i++) | 490 | idxd_clean_wqs(idxd); |
| 431 | put_device(wq_confdev(idxd->wqs[i])); | ||
| 432 | err_wqs: | 491 | err_wqs: |
| 433 | return rc; | 492 | return rc; |
| 434 | } | 493 | } |
| @@ -528,6 +587,17 @@ static void idxd_read_caps(struct idxd_device *idxd) · 93 unmodified lines | |||
| 528 | idxd->hw.iaa_cap.bits = ioread64(idxd->reg_base + IDXD_IAACAP_OFFSET); | 587 | idxd->hw.iaa_cap.bits = ioread64(idxd->reg_base + IDXD_IAACAP_OFFSET); |
| 529 | } | 588 | } |
| 530 | 589 | ||
| 590 | static void idxd_free(struct idxd_device *idxd) | ||
| 591 | { | ||
| 592 | if (!idxd) | ||
| 593 | return; | ||
| 594 | |||
| 595 | put_device(idxd_confdev(idxd)); | ||
| 596 | bitmap_free(idxd->opcap_bmap); | ||
| 597 | ida_free(&idxd_ida, idxd->id); | ||
| 598 | kfree(idxd); | ||
| 599 | } | ||
| 600 | |||
| 531 | static struct idxd_device *idxd_alloc(struct pci_dev *pdev, struct idxd_driver_data *data) | 601 | static struct idxd_device *idxd_alloc(struct pci_dev *pdev, struct idxd_driver_data *data) |
| 532 | { | 602 | { |
| 533 | struct device *dev = &pdev->dev; | 603 | struct device *dev = &pdev->dev; |
| @@ -545,28 +615,34 @@ static struct idxd_device *idxd_alloc(struct pci_dev *pdev, struct idxd_driver_d · 11 unmodified lines | |||
| 545 | idxd_dev_set_type(&idxd->idxd_dev, idxd->data->type); | 615 | idxd_dev_set_type(&idxd->idxd_dev, idxd->data->type); |
| 546 | idxd->id = ida_alloc(&idxd_ida, GFP_KERNEL); | 616 | idxd->id = ida_alloc(&idxd_ida, GFP_KERNEL); |
| 547 | if (idxd->id < 0) | 617 | if (idxd->id < 0) |
| 548 | return NULL; | 618 | goto err_ida; |
| 549 | 619 | ||
| 550 | idxd->opcap_bmap = bitmap_zalloc_node(IDXD_MAX_OPCAP_BITS, GFP_KERNEL, dev_to_node(dev)); | 620 | idxd->opcap_bmap = bitmap_zalloc_node(IDXD_MAX_OPCAP_BITS, GFP_KERNEL, dev_to_node(dev)); |
| 551 | if (!idxd->opcap_bmap) { | 621 | if (!idxd->opcap_bmap) |
| 552 | ida_free(&idxd_ida, idxd->id); | 622 | goto err_opcap; |
| 553 | return NULL; | ||
| 554 | } | ||
| 555 | 623 | ||
| 556 | device_initialize(conf_dev); | 624 | device_initialize(conf_dev); |
| 557 | conf_dev->parent = dev; | 625 | conf_dev->parent = dev; |
| 558 | conf_dev->bus = &dsa_bus_type; | 626 | conf_dev->bus = &dsa_bus_type; |
| 559 | conf_dev->type = idxd->data->dev_type; | 627 | conf_dev->type = idxd->data->dev_type; |
| 560 | rc = dev_set_name(conf_dev, "%s%d", idxd->data->name_prefix, idxd->id); | 628 | rc = dev_set_name(conf_dev, "%s%d", idxd->data->name_prefix, idxd->id); |
| 561 | if (rc < 0) { | 629 | if (rc < 0) |
| 562 | put_device(conf_dev); | 630 | goto err_name; |
| 563 | return NULL; | ||
| 564 | } | ||
| 565 | 631 | ||
| 566 | spin_lock_init(&idxd->dev_lock); | 632 | spin_lock_init(&idxd->dev_lock); |
| 567 | spin_lock_init(&idxd->cmd_lock); | 633 | spin_lock_init(&idxd->cmd_lock); |
| 568 | 634 | ||
| 569 | return idxd; | 635 | return idxd; |
| 636 | |||
| 637 | err_name: | ||
| 638 | put_device(conf_dev); | ||
| 639 | bitmap_free(idxd->opcap_bmap); | ||
| 640 | err_opcap: | ||
| 641 | ida_free(&idxd_ida, idxd->id); | ||
| 642 | err_ida: | ||
| 643 | kfree(idxd); | ||
| 644 | |||
| 645 | return NULL; | ||
| 570 | } | 646 | } |
| 571 | 647 | ||
| 572 | static int idxd_enable_system_pasid(struct idxd_device *idxd) | 648 | static int idxd_enable_system_pasid(struct idxd_device *idxd) |
| @@ -1190,7 +1266,7 @@ int idxd_pci_probe_alloc(struct idxd_device *idxd, struct pci_dev *pdev, · 617 unmodified lines | |||
| 1190 | err: | 1266 | err: |
| 1191 | pci_iounmap(pdev, idxd->reg_base); | 1267 | pci_iounmap(pdev, idxd->reg_base); |
| 1192 | err_iomap: | 1268 | err_iomap: |
| 1193 | put_device(idxd_confdev(idxd)); | 1269 | idxd_free(idxd); |
| 1194 | err_idxd_alloc: | 1270 | err_idxd_alloc: |
| 1195 | pci_disable_device(pdev); | 1271 | pci_disable_device(pdev); |
| 1196 | return rc; | 1272 | return rc; |
| @@ -1232,7 +1308,6 @@ static void idxd_shutdown(struct pci_dev *pdev) · 35 unmodified lines | |||
| 1232 | static void idxd_remove(struct pci_dev *pdev) | 1308 | static void idxd_remove(struct pci_dev *pdev) |
| 1233 | { | 1309 | { |
| 1234 | struct idxd_device *idxd = pci_get_drvdata(pdev); | 1310 | struct idxd_device *idxd = pci_get_drvdata(pdev); |
| 1235 | struct idxd_irq_entry *irq_entry; | ||
| 1236 | 1311 | ||
| 1237 | idxd_unregister_devices(idxd); | 1312 | idxd_unregister_devices(idxd); |
| 1238 | /* | 1313 | /* |
| @@ -1245,20 +1320,12 @@ static void idxd_remove(struct pci_dev *pdev) · 6 unmodified lines | |||
| 1245 | get_device(idxd_confdev(idxd)); | 1320 | get_device(idxd_confdev(idxd)); |
| 1246 | device_unregister(idxd_confdev(idxd)); | 1321 | device_unregister(idxd_confdev(idxd)); |
| 1247 | idxd_shutdown(pdev); | 1322 | idxd_shutdown(pdev); |
| 1248 | if (device_pasid_enabled(idxd)) | ||
| 1249 | idxd_disable_system_pasid(idxd); | ||
| 1250 | idxd_device_remove_debugfs(idxd); | 1323 | idxd_device_remove_debugfs(idxd); |
| 1251 | 1324 | idxd_cleanup(idxd); | |
| 1252 | irq_entry = idxd_get_ie(idxd, 0); | ||
| 1253 | free_irq(irq_entry->vector, irq_entry); | ||
| 1254 | pci_free_irq_vectors(pdev); | ||
| 1255 | pci_iounmap(pdev, idxd->reg_base); | 1325 | pci_iounmap(pdev, idxd->reg_base); |
| 1256 | if (device_user_pasid_enabled(idxd)) | ||
| 1257 | idxd_disable_sva(pdev); | ||
| 1258 | pci_disable_device(pdev); | ||
| 1259 | destroy_workqueue(idxd->wq); | ||
| 1260 | perfmon_pmu_remove(idxd); | ||
| 1261 | put_device(idxd_confdev(idxd)); | 1326 | put_device(idxd_confdev(idxd)); |
| 1327 | idxd_free(idxd); | ||
| 1328 | pci_disable_device(pdev); | ||
| 1262 | } | 1329 | } |
| 1263 | 1330 | ||
| 1264 | static struct pci_driver idxd_pci_driver = { | 1331 | static struct pci_driver idxd_pci_driver = { |
| @@ -420,15 +420,11 @@ static struct virt_dma_desc *mtk_cqdma_find_active_desc(struct dma_chan *c, · 419 unmodified lines | |||
| 420 | { | 420 | { |
| 421 | struct mtk_cqdma_vchan *cvc = to_cqdma_vchan(c); | 421 | struct mtk_cqdma_vchan *cvc = to_cqdma_vchan(c); |
| 422 | struct virt_dma_desc *vd; | 422 | struct virt_dma_desc *vd; |
| 423 | unsigned long flags; | ||
| 424 | 423 | ||
| 425 | spin_lock_irqsave(&cvc->pc->lock, flags); | ||
| 426 | list_for_each_entry(vd, &cvc->pc->queue, node) | 424 | list_for_each_entry(vd, &cvc->pc->queue, node) |
| 427 | if (vd->tx.cookie == cookie) { | 425 | if (vd->tx.cookie == cookie) { |
| 428 | spin_unlock_irqrestore(&cvc->pc->lock, flags); | ||
| 429 | return vd; | 426 | return vd; |
| 430 | } | 427 | } |
| 431 | spin_unlock_irqrestore(&cvc->pc->lock, flags); | ||
| 432 | 428 | ||
| 433 | list_for_each_entry(vd, &cvc->vc.desc_issued, node) | 429 | list_for_each_entry(vd, &cvc->vc.desc_issued, node) |
| 434 | if (vd->tx.cookie == cookie) | 430 | if (vd->tx.cookie == cookie) |
| @@ -452,9 +448,11 @@ static enum dma_status mtk_cqdma_tx_status(struct dma_chan *c, · 17 unmodified lines | |||
| 452 | if (ret == DMA_COMPLETE || !txstate) | 448 | if (ret == DMA_COMPLETE || !txstate) |
| 453 | return ret; | 449 | return ret; |
| 454 | 450 | ||
| 451 | spin_lock_irqsave(&cvc->pc->lock, flags); | ||
| 455 | spin_lock_irqsave(&cvc->vc.lock, flags); | 452 | spin_lock_irqsave(&cvc->vc.lock, flags); |
| 456 | vd = mtk_cqdma_find_active_desc(c, cookie); | 453 | vd = mtk_cqdma_find_active_desc(c, cookie); |
| 457 | spin_unlock_irqrestore(&cvc->vc.lock, flags); | 454 | spin_unlock_irqrestore(&cvc->vc.lock, flags); |
| 455 | spin_unlock_irqrestore(&cvc->pc->lock, flags); | ||
| 458 | 456 | ||
| 459 | if (vd) { | 457 | if (vd) { |
| 460 | cvd = to_cqdma_vdesc(vd); | 458 | cvd = to_cqdma_vdesc(vd); |
| @@ -1091,8 +1091,11 @@ static void udma_check_tx_completion(struct work_struct *work) · 1090 unmodified lines | |||
| 1091 | u32 residue_diff; | 1091 | u32 residue_diff; |
| 1092 | ktime_t time_diff; | 1092 | ktime_t time_diff; |
| 1093 | unsigned long delay; | 1093 | unsigned long delay; |
| 1094 | unsigned long flags; | ||
| 1094 | 1095 | ||
| 1095 | while (1) { | 1096 | while (1) { |
| 1097 | spin_lock_irqsave(&uc->vc.lock, flags); | ||
| 1098 | |||
| 1096 | if (uc->desc) { | 1099 | if (uc->desc) { |
| 1097 | /* Get previous residue and time stamp */ | 1100 | /* Get previous residue and time stamp */ |
| 1098 | residue_diff = uc->tx_drain.residue; | 1101 | residue_diff = uc->tx_drain.residue; |
| @@ -1127,6 +1130,8 @@ static void udma_check_tx_completion(struct work_struct *work) · 28 unmodified lines | |||
| 1127 | break; | 1130 | break; |
| 1128 | } | 1131 | } |
| 1129 | 1132 | ||
| 1133 | spin_unlock_irqrestore(&uc->vc.lock, flags); | ||
| 1134 | |||
| 1130 | usleep_range(ktime_to_us(delay), | 1135 | usleep_range(ktime_to_us(delay), |
| 1131 | ktime_to_us(delay) + 10); | 1136 | ktime_to_us(delay) + 10); |
| 1132 | continue; | 1137 | continue; |
| @@ -1143,6 +1148,8 @@ static void udma_check_tx_completion(struct work_struct *work) · 10 unmodified lines | |||
| 1143 | 1148 | ||
| 1144 | break; | 1149 | break; |
| 1145 | } | 1150 | } |
| 1151 | |||
| 1152 | spin_unlock_irqrestore(&uc->vc.lock, flags); | ||
| 1146 | } | 1153 | } |
| 1147 | 1154 | ||
| 1148 | static irqreturn_t udma_ring_irq_handler(int irq, void *data) | 1155 | static irqreturn_t udma_ring_irq_handler(int irq, void *data) |
| @@ -4246,7 +4253,6 @@ static struct dma_chan *udma_of_xlate(struct of_phandle_args *dma_spec, · 3097 unmodified lines | |||
| 4246 | struct of_dma *ofdma) | 4253 | struct of_dma *ofdma) |
| 4247 | { | 4254 | { |
| 4248 | struct udma_dev *ud = ofdma->of_dma_data; | 4255 | struct udma_dev *ud = ofdma->of_dma_data; |
| 4249 | dma_cap_mask_t mask = ud->ddev.cap_mask; | ||
| 4250 | struct udma_filter_param filter_param; | 4256 | struct udma_filter_param filter_param; |
| 4251 | struct dma_chan *chan; | 4257 | struct dma_chan *chan; |
| 4252 | 4258 | ||
| @@ -4278,7 +4284,7 @@ static struct dma_chan *udma_of_xlate(struct of_phandle_args *dma_spec, · 25 unmodified lines | |||
| 4278 | } | 4284 | } |
| 4279 | } | 4285 | } |
| 4280 | 4286 | ||
| 4281 | chan = __dma_request_channel(&mask, udma_dma_filter_fn, &filter_param, | 4287 | chan = __dma_request_channel(&ud->ddev.cap_mask, udma_dma_filter_fn, &filter_param, |
| 4282 | ofdma->of_node); | 4288 | ofdma->of_node); |
| 4283 | if (!chan) { | 4289 | if (!chan) { |
| 4284 | dev_err(ud->dev, "get channel fail in %s.\n", __func__); | 4290 | dev_err(ud->dev, "get channel fail in %s.\n", __func__); |
| @@ -1204,6 +1204,8 @@ static int pca953x_restore_context(struct pca953x_chip *chip) · 1203 unmodified lines | |||
| 1204 | 1204 | ||
| 1205 | guard(mutex)(&chip->i2c_lock); | 1205 | guard(mutex)(&chip->i2c_lock); |
| 1206 | 1206 | ||
| 1207 | if (chip->client->irq > 0) | ||
| 1208 | enable_irq(chip->client->irq); | ||
| 1207 | regcache_cache_only(chip->regmap, false); | 1209 | regcache_cache_only(chip->regmap, false); |
| 1208 | regcache_mark_dirty(chip->regmap); | 1210 | regcache_mark_dirty(chip->regmap); |
| 1209 | ret = pca953x_regcache_sync(chip); | 1211 | ret = pca953x_regcache_sync(chip); |
| @@ -1216,6 +1218,10 @@ static int pca953x_restore_context(struct pca953x_chip *chip) · 6 unmodified lines | |||
| 1216 | static void pca953x_save_context(struct pca953x_chip *chip) | 1218 | static void pca953x_save_context(struct pca953x_chip *chip) |
| 1217 | { | 1219 | { |
| 1218 | guard(mutex)(&chip->i2c_lock); | 1220 | guard(mutex)(&chip->i2c_lock); |
| 1221 | |||
| 1222 | /* Disable IRQ to prevent early triggering while regmap "cache only" is on */ | ||
| 1223 | if (chip->client->irq > 0) | ||
| 1224 | disable_irq(chip->client->irq); | ||
| 1219 | regcache_cache_only(chip->regmap, true); | 1225 | regcache_cache_only(chip->regmap, true); |
| 1220 | } | 1226 | } |
| 1221 | 1227 | ||
| @@ -401,10 +401,15 @@ static ssize_t gpio_virtuser_direction_do_write(struct file *file, · 400 unmodified lines | |||
| 401 | char buf[32], *trimmed; | 401 | char buf[32], *trimmed; |
| 402 | int ret, dir, val = 0; | 402 | int ret, dir, val = 0; |
| 403 | 403 | ||
| 404 | ret = simple_write_to_buffer(buf, sizeof(buf), ppos, user_buf, count); | 404 | if (count >= sizeof(buf)) |
| 405 | return -EINVAL; | ||
| 406 | |||
| 407 | ret = simple_write_to_buffer(buf, sizeof(buf) - 1, ppos, user_buf, count); | ||
| 405 | if (ret < 0) | 408 | if (ret < 0) |
| 406 | return ret; | 409 | return ret; |
| 407 | 410 | ||
| 411 | buf[ret] = '\0'; | ||
| 412 | |||
| 408 | trimmed = strim(buf); | 413 | trimmed = strim(buf); |
| 409 | 414 | ||
| 410 | if (strcmp(trimmed, "input") == 0) { | 415 | if (strcmp(trimmed, "input") == 0) { |
| @@ -623,12 +628,15 @@ static ssize_t gpio_virtuser_consumer_write(struct file *file, · 212 unmodified lines | |||
| 623 | char buf[GPIO_VIRTUSER_NAME_BUF_LEN + 2]; | 628 | char buf[GPIO_VIRTUSER_NAME_BUF_LEN + 2]; |
| 624 | int ret; | 629 | int ret; |
| 625 | 630 | ||
| 631 | if (count >= sizeof(buf)) | ||
| 632 | return -EINVAL; | ||
| 633 | |||
| 626 | ret = simple_write_to_buffer(buf, GPIO_VIRTUSER_NAME_BUF_LEN, ppos, | 634 | ret = simple_write_to_buffer(buf, GPIO_VIRTUSER_NAME_BUF_LEN, ppos, |
| 627 | user_buf, count); | 635 | user_buf, count); |
| 628 | if (ret < 0) | 636 | if (ret < 0) |
| 629 | return ret; | 637 | return ret; |
| 630 | 638 | ||
| 631 | buf[strlen(buf) - 1] = '\0'; | 639 | buf[ret] = '\0'; |
| 632 | 640 | ||
| 633 | ret = gpiod_set_consumer_name(data->ad.desc, buf); | 641 | ret = gpiod_set_consumer_name(data->ad.desc, buf); |
| 634 | if (ret) | 642 | if (ret) |
| @@ -109,7 +109,7 @@ int amdgpu_unmap_static_csa(struct amdgpu_device *adev, struct amdgpu_vm *vm, · 108 unmodified lines | |||
| 109 | struct drm_exec exec; | 109 | struct drm_exec exec; |
| 110 | int r; | 110 | int r; |
| 111 | 111 | ||
| 112 | drm_exec_init(&exec, DRM_EXEC_INTERRUPTIBLE_WAIT, 0); | 112 | drm_exec_init(&exec, 0, 0); |
| 113 | drm_exec_until_all_locked(&exec) { | 113 | drm_exec_until_all_locked(&exec) { |
| 114 | r = amdgpu_vm_lock_pd(vm, &exec, 0); | 114 | r = amdgpu_vm_lock_pd(vm, &exec, 0); |
| 115 | if (likely(!r)) | 115 | if (likely(!r)) |
| @@ -752,6 +752,18 @@ static int gmc_v11_0_sw_init(struct amdgpu_ip_block *ip_block) · 751 unmodified lines | |||
| 752 | adev->gmc.vram_type = vram_type; | 752 | adev->gmc.vram_type = vram_type; |
| 753 | adev->gmc.vram_vendor = vram_vendor; | 753 | adev->gmc.vram_vendor = vram_vendor; |
| 754 | 754 | ||
| 755 | /* The mall_size is already calculated as mall_size_per_umc * num_umc. | ||
| 756 | * However, for gfx1151, which features a 2-to-1 UMC mapping, | ||
| 757 | * the result must be multiplied by 2 to determine the actual mall size. | ||
| 758 | */ | ||
| 759 | switch (amdgpu_ip_version(adev, GC_HWIP, 0)) { | ||
| 760 | case IP_VERSION(11, 5, 1): | ||
| 761 | adev->gmc.mall_size *= 2; | ||
| 762 | break; | ||
| 763 | default: | ||
| 764 | break; | ||
| 765 | } | ||
| 766 | |||
| 755 | switch (amdgpu_ip_version(adev, GC_HWIP, 0)) { | 767 | switch (amdgpu_ip_version(adev, GC_HWIP, 0)) { |
| 756 | case IP_VERSION(11, 0, 0): | 768 | case IP_VERSION(11, 0, 0): |
| 757 | case IP_VERSION(11, 0, 1): | 769 | case IP_VERSION(11, 0, 1): |
| @@ -1023,6 +1023,10 @@ static int vcn_v4_0_5_start_dpg_mode(struct amdgpu_vcn_inst *vinst, · 1022 unmodified lines | |||
| 1023 | ring->doorbell_index << VCN_RB1_DB_CTRL__OFFSET__SHIFT | | 1023 | ring->doorbell_index << VCN_RB1_DB_CTRL__OFFSET__SHIFT | |
| 1024 | VCN_RB1_DB_CTRL__EN_MASK); | 1024 | VCN_RB1_DB_CTRL__EN_MASK); |
| 1025 | 1025 | ||
| 1026 | /* Keeping one read-back to ensure all register writes are done, otherwise | ||
| 1027 | * it may introduce race conditions */ | ||
| 1028 | RREG32_SOC15(VCN, inst_idx, regVCN_RB1_DB_CTRL); | ||
| 1029 | |||
| 1026 | return 0; | 1030 | return 0; |
| 1027 | } | 1031 | } |
| 1028 | 1032 | ||
| @@ -1205,6 +1209,10 @@ static int vcn_v4_0_5_start(struct amdgpu_vcn_inst *vinst) · 176 unmodified lines | |||
| 1205 | WREG32_SOC15(VCN, i, regVCN_RB_ENABLE, tmp); | 1209 | WREG32_SOC15(VCN, i, regVCN_RB_ENABLE, tmp); |
| 1206 | fw_shared->sq.queue_mode &= ~(FW_QUEUE_RING_RESET | FW_QUEUE_DPG_HOLD_OFF); | 1210 | fw_shared->sq.queue_mode &= ~(FW_QUEUE_RING_RESET | FW_QUEUE_DPG_HOLD_OFF); |
| 1207 | 1211 | ||
| 1212 | /* Keeping one read-back to ensure all register writes are done, otherwise | ||
| 1213 | * it may introduce race conditions */ | ||
| 1214 | RREG32_SOC15(VCN, i, regVCN_RB_ENABLE); | ||
| 1215 | |||
| 1208 | return 0; | 1216 | return 0; |
| 1209 | } | 1217 | } |
| 1210 | 1218 | ||
| @@ -372,6 +372,8 @@ get_crtc_by_otg_inst(struct amdgpu_device *adev, · 371 unmodified lines | |||
| 372 | static inline bool is_dc_timing_adjust_needed(struct dm_crtc_state *old_state, | 372 | static inline bool is_dc_timing_adjust_needed(struct dm_crtc_state *old_state, |
| 373 | struct dm_crtc_state *new_state) | 373 | struct dm_crtc_state *new_state) |
| 374 | { | 374 | { |
| 375 | if (new_state->stream->adjust.timing_adjust_pending) | ||
| 376 | return true; | ||
| 375 | if (new_state->freesync_config.state == VRR_STATE_ACTIVE_FIXED) | 377 | if (new_state->freesync_config.state == VRR_STATE_ACTIVE_FIXED) |
| 376 | return true; | 378 | return true; |
| 377 | else if (amdgpu_dm_crtc_vrr_active(old_state) != amdgpu_dm_crtc_vrr_active(new_state)) | 379 | else if (amdgpu_dm_crtc_vrr_active(old_state) != amdgpu_dm_crtc_vrr_active(new_state)) |
| @@ -12763,7 +12765,8 @@ int amdgpu_dm_process_dmub_aux_transfer_sync( · 12385 unmodified lines | |||
| 12763 | /* The reply is stored in the top nibble of the command. */ | 12765 | /* The reply is stored in the top nibble of the command. */ |
| 12764 | payload->reply[0] = (adev->dm.dmub_notify->aux_reply.command >> 4) & 0xF; | 12766 | payload->reply[0] = (adev->dm.dmub_notify->aux_reply.command >> 4) & 0xF; |
| 12765 | 12767 | ||
| 12766 | if (!payload->write && p_notify->aux_reply.length) | 12768 | /*write req may receive a byte indicating partially written number as well*/ |
| 12769 | if (p_notify->aux_reply.length) | ||
| 12767 | memcpy(payload->data, p_notify->aux_reply.data, | 12770 | memcpy(payload->data, p_notify->aux_reply.data, |
| 12768 | p_notify->aux_reply.length); | 12771 | p_notify->aux_reply.length); |
| 12769 | 12772 | ||
| @@ -62,6 +62,7 @@ static ssize_t dm_dp_aux_transfer(struct drm_dp_aux *aux, · 61 unmodified lines | |||
| 62 | enum aux_return_code_type operation_result; | 62 | enum aux_return_code_type operation_result; |
| 63 | struct amdgpu_device *adev; | 63 | struct amdgpu_device *adev; |
| 64 | struct ddc_service *ddc; | 64 | struct ddc_service *ddc; |
| 65 | uint8_t copy[16]; | ||
| 65 | 66 | ||
| 66 | if (WARN_ON(msg->size > 16)) | 67 | if (WARN_ON(msg->size > 16)) |
| 67 | return -E2BIG; | 68 | return -E2BIG; |
| @@ -77,6 +78,11 @@ static ssize_t dm_dp_aux_transfer(struct drm_dp_aux *aux, · 9 unmodified lines | |||
| 77 | (msg->request & DP_AUX_I2C_WRITE_STATUS_UPDATE) != 0; | 78 | (msg->request & DP_AUX_I2C_WRITE_STATUS_UPDATE) != 0; |
| 78 | payload.defer_delay = 0; | 79 | payload.defer_delay = 0; |
| 79 | 80 | ||
| 81 | if (payload.write) { | ||
| 82 | memcpy(copy, msg->buffer, msg->size); | ||
| 83 | payload.data = copy; | ||
| 84 | } | ||
| 85 | |||
| 80 | result = dc_link_aux_transfer_raw(TO_DM_AUX(aux)->ddc_service, &payload, | 86 | result = dc_link_aux_transfer_raw(TO_DM_AUX(aux)->ddc_service, &payload, |
| 81 | &operation_result); | 87 | &operation_result); |
| 82 | 88 | ||
| @@ -100,9 +106,9 @@ static ssize_t dm_dp_aux_transfer(struct drm_dp_aux *aux, · 17 unmodified lines | |||
| 100 | */ | 106 | */ |
| 101 | if (payload.write && result >= 0) { | 107 | if (payload.write && result >= 0) { |
| 102 | if (result) { | 108 | if (result) { |
| 103 | /*one byte indicating partially written bytes. Force 0 to retry*/ | 109 | /*one byte indicating partially written bytes*/ |
| 104 | drm_info(adev_to_drm(adev), "amdgpu: AUX partially written\n"); | 110 | drm_dbg_dp(adev_to_drm(adev), "amdgpu: AUX partially written\n"); |
| 105 | result = 0; | 111 | result = payload.data[0]; |
| 106 | } else if (!payload.reply[0]) | 112 | } else if (!payload.reply[0]) |
| 107 | /*I2C_ACK|AUX_ACK*/ | 113 | /*I2C_ACK|AUX_ACK*/ |
| 108 | result = msg->size; | 114 | result = msg->size; |
| @@ -127,11 +133,11 @@ static ssize_t dm_dp_aux_transfer(struct drm_dp_aux *aux, · 18 unmodified lines | |||
| 127 | break; | 133 | break; |
| 128 | } | 134 | } |
| 129 | 135 | ||
| 130 | drm_info(adev_to_drm(adev), "amdgpu: DP AUX transfer fail:%d\n", operation_result); | 136 | drm_dbg_dp(adev_to_drm(adev), "amdgpu: DP AUX transfer fail:%d\n", operation_result); |
| 131 | } | 137 | } |
| 132 | 138 | ||
| 133 | if (payload.reply[0]) | 139 | if (payload.reply[0]) |
| 134 | drm_info(adev_to_drm(adev), "amdgpu: AUX reply command not ACK: 0x%02x.", | 140 | drm_dbg_dp(adev_to_drm(adev), "amdgpu: AUX reply command not ACK: 0x%02x.", |
| 135 | payload.reply[0]); | 141 | payload.reply[0]); |
| 136 | 142 | ||
| 137 | return result; | 143 | return result; |
| @@ -439,9 +439,12 @@ bool dc_stream_adjust_vmin_vmax(struct dc *dc, · 438 unmodified lines | |||
| 439 | * Don't adjust DRR while there's bandwidth optimizations pending to | 439 | * Don't adjust DRR while there's bandwidth optimizations pending to |
| 440 | * avoid conflicting with firmware updates. | 440 | * avoid conflicting with firmware updates. |
| 441 | */ | 441 | */ |
| 442 | if (dc->ctx->dce_version > DCE_VERSION_MAX) | 442 | if (dc->ctx->dce_version > DCE_VERSION_MAX) { |
| 443 | if (dc->optimized_required || dc->wm_optimized_required) | 443 | if (dc->optimized_required || dc->wm_optimized_required) { |
| 444 | stream->adjust.timing_adjust_pending = true; | ||
| 444 | return false; | 445 | return false; |
| 446 | } | ||
| 447 | } | ||
| 445 | 448 | ||
| 446 | dc_exit_ips_for_hw_access(dc); | 449 | dc_exit_ips_for_hw_access(dc); |
| 447 | 450 | ||
| @@ -3168,7 +3171,8 @@ static void copy_stream_update_to_stream(struct dc *dc, · 2720 unmodified lines | |||
| 3168 | 3171 | ||
| 3169 | if (update->crtc_timing_adjust) { | 3172 | if (update->crtc_timing_adjust) { |
| 3170 | if (stream->adjust.v_total_min != update->crtc_timing_adjust->v_total_min || | 3173 | if (stream->adjust.v_total_min != update->crtc_timing_adjust->v_total_min || |
| 3171 | stream->adjust.v_total_max != update->crtc_timing_adjust->v_total_max) | 3174 | stream->adjust.v_total_max != update->crtc_timing_adjust->v_total_max || |
| 3175 | stream->adjust.timing_adjust_pending) | ||
| 3172 | update->crtc_timing_adjust->timing_adjust_pending = true; | 3176 | update->crtc_timing_adjust->timing_adjust_pending = true; |
| 3173 | stream->adjust = *update->crtc_timing_adjust; | 3177 | stream->adjust = *update->crtc_timing_adjust; |
| 3174 | update->crtc_timing_adjust->timing_adjust_pending = false; | 3178 | update->crtc_timing_adjust->timing_adjust_pending = false; |
| @@ -195,9 +195,9 @@ struct _vcs_dpi_soc_bounding_box_st dcn3_5_soc = { · 194 unmodified lines | |||
| 195 | .dcn_downspread_percent = 0.5, | 195 | .dcn_downspread_percent = 0.5, |
| 196 | .gpuvm_min_page_size_bytes = 4096, | 196 | .gpuvm_min_page_size_bytes = 4096, |
| 197 | .hostvm_min_page_size_bytes = 4096, | 197 | .hostvm_min_page_size_bytes = 4096, |
| 198 | .do_urgent_latency_adjustment = 1, | 198 | .do_urgent_latency_adjustment = 0, |
| 199 | .urgent_latency_adjustment_fabric_clock_component_us = 0, | 199 | .urgent_latency_adjustment_fabric_clock_component_us = 0, |
| 200 | .urgent_latency_adjustment_fabric_clock_reference_mhz = 3000, | 200 | .urgent_latency_adjustment_fabric_clock_reference_mhz = 0, |
| 201 | }; | 201 | }; |
| 202 | 202 | ||
| 203 | void dcn35_build_wm_range_table_fpu(struct clk_mgr *clk_mgr) | 203 | void dcn35_build_wm_range_table_fpu(struct clk_mgr *clk_mgr) |
| @@ -910,7 +910,7 @@ static void populate_dml21_plane_config_from_plane_state(struct dml2_context *dm · 909 unmodified lines | |||
| 910 | } | 910 | } |
| 911 | 911 | ||
| 912 | //TODO : Could be possibly moved to a common helper layer. | 912 | //TODO : Could be possibly moved to a common helper layer. |
| 913 | static bool dml21_wrapper_get_plane_id(const struct dc_state *context, const struct dc_plane_state *plane, unsigned int *plane_id) | 913 | static bool dml21_wrapper_get_plane_id(const struct dc_state *context, unsigned int stream_id, const struct dc_plane_state *plane, unsigned int *plane_id) |
| 914 | { | 914 | { |
| 915 | int i, j; | 915 | int i, j; |
| 916 | 916 | ||
| @@ -918,10 +918,12 @@ static bool dml21_wrapper_get_plane_id(const struct dc_state *context, const str · 1 unmodified line | |||
| 918 | return false; | 918 | return false; |
| 919 | 919 | ||
| 920 | for (i = 0; i < context->stream_count; i++) { | 920 | for (i = 0; i < context->stream_count; i++) { |
| 921 | for (j = 0; j < context->stream_status[i].plane_count; j++) { | 921 | if (context->streams[i]->stream_id == stream_id) { |
| 922 | if (context->stream_status[i].plane_states[j] == plane) { | 922 | for (j = 0; j < context->stream_status[i].plane_count; j++) { |
| 923 | *plane_id = (i << 16) | j; | 923 | if (context->stream_status[i].plane_states[j] == plane) { |
| 924 | return true; | 924 | *plane_id = (i << 16) | j; |
| 925 | return true; | ||
| 926 | } | ||
| 925 | } | 927 | } |
| 926 | } | 928 | } |
| 927 | } | 929 | } |
| @@ -944,14 +946,14 @@ static unsigned int map_stream_to_dml21_display_cfg(const struct dml2_context *d · 16 unmodified lines | |||
| 944 | return location; | 946 | return location; |
| 945 | } | 947 | } |
| 946 | 948 | ||
| 947 | static unsigned int map_plane_to_dml21_display_cfg(const struct dml2_context *dml_ctx, | 949 | static unsigned int map_plane_to_dml21_display_cfg(const struct dml2_context *dml_ctx, unsigned int stream_id, |
| 948 | const struct dc_plane_state *plane, const struct dc_state *context) | 950 | const struct dc_plane_state *plane, const struct dc_state *context) |
| 949 | { | 951 | { |
| 950 | unsigned int plane_id; | 952 | unsigned int plane_id; |
| 951 | int i = 0; | 953 | int i = 0; |
| 952 | int location = -1; | 954 | int location = -1; |
| 953 | 955 | ||
| 954 | if (!dml21_wrapper_get_plane_id(context, plane, &plane_id)) { | 956 | if (!dml21_wrapper_get_plane_id(context, stream_id, plane, &plane_id)) { |
| 955 | ASSERT(false); | 957 | ASSERT(false); |
| 956 | return -1; | 958 | return -1; |
| 957 | } | 959 | } |
| @@ -1037,7 +1039,7 @@ bool dml21_map_dc_state_into_dml_display_cfg(const struct dc *in_dc, struct dc_s · 79 unmodified lines | |||
| 1037 | dml_dispcfg->plane_descriptors[disp_cfg_plane_location].stream_index = disp_cfg_stream_location; | 1039 | dml_dispcfg->plane_descriptors[disp_cfg_plane_location].stream_index = disp_cfg_stream_location; |
| 1038 | } else { | 1040 | } else { |
| 1039 | for (plane_index = 0; plane_index < context->stream_status[stream_index].plane_count; plane_index++) { | 1041 | for (plane_index = 0; plane_index < context->stream_status[stream_index].plane_count; plane_index++) { |
| 1040 | disp_cfg_plane_location = map_plane_to_dml21_display_cfg(dml_ctx, context->stream_status[stream_index].plane_states[plane_index], context); | 1042 | disp_cfg_plane_location = map_plane_to_dml21_display_cfg(dml_ctx, context->streams[stream_index]->stream_id, context->stream_status[stream_index].plane_states[plane_index], context); |
| 1041 | 1043 | ||
| 1042 | if (disp_cfg_plane_location < 0) | 1044 | if (disp_cfg_plane_location < 0) |
| 1043 | disp_cfg_plane_location = dml_dispcfg->num_planes++; | 1045 | disp_cfg_plane_location = dml_dispcfg->num_planes++; |
| @@ -1048,7 +1050,7 @@ bool dml21_map_dc_state_into_dml_display_cfg(const struct dc *in_dc, struct dc_s · 4 unmodified lines | |||
| 1048 | populate_dml21_plane_config_from_plane_state(dml_ctx, &dml_dispcfg->plane_descriptors[disp_cfg_plane_location], context->stream_status[stream_index].plane_states[plane_index], context, stream_index); | 1050 | populate_dml21_plane_config_from_plane_state(dml_ctx, &dml_dispcfg->plane_descriptors[disp_cfg_plane_location], context->stream_status[stream_index].plane_states[plane_index], context, stream_index); |
| 1049 | dml_dispcfg->plane_descriptors[disp_cfg_plane_location].stream_index = disp_cfg_stream_location; | 1051 | dml_dispcfg->plane_descriptors[disp_cfg_plane_location].stream_index = disp_cfg_stream_location; |
| 1050 | 1052 | ||
| 1051 | if (dml21_wrapper_get_plane_id(context, context->stream_status[stream_index].plane_states[plane_index], &dml_ctx->v21.dml_to_dc_pipe_mapping.disp_cfg_to_plane_id[disp_cfg_plane_location])) | 1053 | if (dml21_wrapper_get_plane_id(context, context->streams[stream_index]->stream_id, context->stream_status[stream_index].plane_states[plane_index], &dml_ctx->v21.dml_to_dc_pipe_mapping.disp_cfg_to_plane_id[disp_cfg_plane_location])) |
| 1052 | dml_ctx->v21.dml_to_dc_pipe_mapping.disp_cfg_to_plane_id_valid[disp_cfg_plane_location] = true; | 1054 | dml_ctx->v21.dml_to_dc_pipe_mapping.disp_cfg_to_plane_id_valid[disp_cfg_plane_location] = true; |
| 1053 | 1055 | ||
| 1054 | /* apply forced pstate policy */ | 1056 | /* apply forced pstate policy */ |
| @@ -120,10 +120,11 @@ void dpp401_set_cursor_attributes( · 119 unmodified lines | |||
| 120 | enum dc_cursor_color_format color_format = cursor_attributes->color_format; | 120 | enum dc_cursor_color_format color_format = cursor_attributes->color_format; |
| 121 | int cur_rom_en = 0; | 121 | int cur_rom_en = 0; |
| 122 | 122 | ||
| 123 | // DCN4 should always do Cursor degamma for Cursor Color modes | ||
| 124 | if (color_format == CURSOR_MODE_COLOR_PRE_MULTIPLIED_ALPHA || | 123 | if (color_format == CURSOR_MODE_COLOR_PRE_MULTIPLIED_ALPHA || |
| 125 | color_format == CURSOR_MODE_COLOR_UN_PRE_MULTIPLIED_ALPHA) { | 124 | color_format == CURSOR_MODE_COLOR_UN_PRE_MULTIPLIED_ALPHA) { |
| 126 | cur_rom_en = 1; | 125 | if (cursor_attributes->attribute_flags.bits.ENABLE_CURSOR_DEGAMMA) { |
| 126 | cur_rom_en = 1; | ||
| 127 | } | ||
| 127 | } | 128 | } |
| 128 | 129 | ||
| 129 | REG_UPDATE_3(CURSOR0_CONTROL, | 130 | REG_UPDATE_3(CURSOR0_CONTROL, |
| @@ -1980,9 +1980,9 @@ void dcn401_program_pipe( · 1979 unmodified lines | |||
| 1980 | dc->res_pool->hubbub, pipe_ctx->plane_res.hubp->inst, pipe_ctx->hubp_regs.det_size); | 1980 | dc->res_pool->hubbub, pipe_ctx->plane_res.hubp->inst, pipe_ctx->hubp_regs.det_size); |
| 1981 | } | 1981 | } |
| 1982 | 1982 | ||
| 1983 | if (pipe_ctx->update_flags.raw || | 1983 | if (pipe_ctx->plane_state && (pipe_ctx->update_flags.raw || |
| 1984 | (pipe_ctx->plane_state && pipe_ctx->plane_state->update_flags.raw) || | 1984 | pipe_ctx->plane_state->update_flags.raw || |
| 1985 | pipe_ctx->stream->update_flags.raw) | 1985 | pipe_ctx->stream->update_flags.raw)) |
| 1986 | dc->hwss.update_dchubp_dpp(dc, pipe_ctx, context); | 1986 | dc->hwss.update_dchubp_dpp(dc, pipe_ctx, context); |
| 1987 | 1987 | ||
| 1988 | if (pipe_ctx->plane_state && (pipe_ctx->update_flags.bits.enable || | 1988 | if (pipe_ctx->plane_state && (pipe_ctx->update_flags.bits.enable || |
| @@ -148,6 +148,7 @@ void link_blank_dp_stream(struct dc_link *link, bool hw_init) · 147 unmodified lines | |||
| 148 | void link_set_all_streams_dpms_off_for_link(struct dc_link *link) | 148 | void link_set_all_streams_dpms_off_for_link(struct dc_link *link) |
| 149 | { | 149 | { |
| 150 | struct pipe_ctx *pipes[MAX_PIPES]; | 150 | struct pipe_ctx *pipes[MAX_PIPES]; |
| 151 | struct dc_stream_state *streams[MAX_PIPES]; | ||
| 151 | struct dc_state *state = link->dc->current_state; | 152 | struct dc_state *state = link->dc->current_state; |
| 152 | uint8_t count; | 153 | uint8_t count; |
| 153 | int i; | 154 | int i; |
| @@ -160,10 +161,18 @@ void link_set_all_streams_dpms_off_for_link(struct dc_link *link) · 6 unmodified lines | |||
| 160 | 161 | ||
| 161 | link_get_master_pipes_with_dpms_on(link, state, &count, pipes); | 162 | link_get_master_pipes_with_dpms_on(link, state, &count, pipes); |
| 162 | 163 | ||
| 164 | /* The subsequent call to dc_commit_updates_for_stream for a full update | ||
| 165 | * will release the current state and swap to a new state. Releasing the | ||
| 166 | * current state results in the stream pointers in the pipe_ctx structs | ||
| 167 | * to be zero'd. Hence, cache all streams prior to dc_commit_updates_for_stream. | ||
| 168 | */ | ||
| 169 | for (i = 0; i < count; i++) | ||
| 170 | streams[i] = pipes[i]->stream; | ||
| 171 | |||
| 163 | for (i = 0; i < count; i++) { | 172 | for (i = 0; i < count; i++) { |
| 164 | stream_update.stream = pipes[i]->stream; | 173 | stream_update.stream = streams[i]; |
| 165 | dc_commit_updates_for_stream(link->ctx->dc, NULL, 0, | 174 | dc_commit_updates_for_stream(link->ctx->dc, NULL, 0, |
| 166 | pipes[i]->stream, &stream_update, | 175 | streams[i], &stream_update, |
| 167 | state); | 176 | state); |
| 168 | } | 177 | } |
| 169 | 178 | ||
| @@ -1118,6 +1118,10 @@ static void __drm_gpusvm_range_unmap_pages(struct drm_gpusvm *gpusvm, · 1117 unmodified lines | |||
| 1118 | lockdep_assert_held(&gpusvm->notifier_lock); | 1118 | lockdep_assert_held(&gpusvm->notifier_lock); |
| 1119 | 1119 | ||
| 1120 | if (range->flags.has_dma_mapping) { | 1120 | if (range->flags.has_dma_mapping) { |
| 1121 | struct drm_gpusvm_range_flags flags = { | ||
| 1122 | .__flags = range->flags.__flags, | ||
| 1123 | }; | ||
| 1124 | |||
| 1121 | for (i = 0, j = 0; i < npages; j++) { | 1125 | for (i = 0, j = 0; i < npages; j++) { |
| 1122 | struct drm_pagemap_device_addr *addr = &range->dma_addr[j]; | 1126 | struct drm_pagemap_device_addr *addr = &range->dma_addr[j]; |
| 1123 | 1127 | ||
| @@ -1131,8 +1135,12 @@ static void __drm_gpusvm_range_unmap_pages(struct drm_gpusvm *gpusvm, · 7 unmodified lines | |||
| 1131 | dev, *addr); | 1135 | dev, *addr); |
| 1132 | i += 1 << addr->order; | 1136 | i += 1 << addr->order; |
| 1133 | } | 1137 | } |
| 1134 | range->flags.has_devmem_pages = false; | 1138 | |
| 1135 | range->flags.has_dma_mapping = false; | 1139 | /* WRITE_ONCE pairs with READ_ONCE for opportunistic checks */ |
| 1140 | flags.has_devmem_pages = false; | ||
| 1141 | flags.has_dma_mapping = false; | ||
| 1142 | WRITE_ONCE(range->flags.__flags, flags.__flags); | ||
| 1143 | |||
| 1136 | range->dpagemap = NULL; | 1144 | range->dpagemap = NULL; |
| 1137 | } | 1145 | } |
| 1138 | } | 1146 | } |
| @@ -1334,6 +1342,7 @@ int drm_gpusvm_range_get_pages(struct drm_gpusvm *gpusvm, · 195 unmodified lines | |||
| 1334 | int err = 0; | 1342 | int err = 0; |
| 1335 | struct dev_pagemap *pagemap; | 1343 | struct dev_pagemap *pagemap; |
| 1336 | struct drm_pagemap *dpagemap; | 1344 | struct drm_pagemap *dpagemap; |
| 1345 | struct drm_gpusvm_range_flags flags; | ||
| 1337 | 1346 | ||
| 1338 | retry: | 1347 | retry: |
| 1339 | hmm_range.notifier_seq = mmu_interval_read_begin(notifier); | 1348 | hmm_range.notifier_seq = mmu_interval_read_begin(notifier); |
| @@ -1378,7 +1387,8 @@ map_pages: · 38 unmodified lines | |||
| 1378 | */ | 1387 | */ |
| 1379 | drm_gpusvm_notifier_lock(gpusvm); | 1388 | drm_gpusvm_notifier_lock(gpusvm); |
| 1380 | 1389 | ||
| 1381 | if (range->flags.unmapped) { | 1390 | flags.__flags = range->flags.__flags; |
| 1391 | if (flags.unmapped) { | ||
| 1382 | drm_gpusvm_notifier_unlock(gpusvm); | 1392 | drm_gpusvm_notifier_unlock(gpusvm); |
| 1383 | err = -EFAULT; | 1393 | err = -EFAULT; |
| 1384 | goto err_free; | 1394 | goto err_free; |
| @@ -1454,6 +1464,11 @@ map_pages: · 69 unmodified lines | |||
| 1454 | goto err_unmap; | 1464 | goto err_unmap; |
| 1455 | } | 1465 | } |
| 1456 | 1466 | ||
| 1467 | if (ctx->devmem_only) { | ||
| 1468 | err = -EFAULT; | ||
| 1469 | goto err_unmap; | ||
| 1470 | } | ||
| 1471 | |||
| 1457 | addr = dma_map_page(gpusvm->drm->dev, | 1472 | addr = dma_map_page(gpusvm->drm->dev, |
| 1458 | page, 0, | 1473 | page, 0, |
| 1459 | PAGE_SIZE << order, | 1474 | PAGE_SIZE << order, |
| @@ -1469,14 +1484,17 @@ map_pages: · 9 unmodified lines | |||
| 1469 | } | 1484 | } |
| 1470 | i += 1 << order; | 1485 | i += 1 << order; |
| 1471 | num_dma_mapped = i; | 1486 | num_dma_mapped = i; |
| 1472 | range->flags.has_dma_mapping = true; | 1487 | flags.has_dma_mapping = true; |
| 1473 | } | 1488 | } |
| 1474 | 1489 | ||
| 1475 | if (zdd) { | 1490 | if (zdd) { |
| 1476 | range->flags.has_devmem_pages = true; | 1491 | flags.has_devmem_pages = true; |
| 1477 | range->dpagemap = dpagemap; | 1492 | range->dpagemap = dpagemap; |
| 1478 | } | 1493 | } |
| 1479 | 1494 | ||
| 1495 | /* WRITE_ONCE pairs with READ_ONCE for opportunistic checks */ | ||
| 1496 | WRITE_ONCE(range->flags.__flags, flags.__flags); | ||
| 1497 | |||
| 1480 | drm_gpusvm_notifier_unlock(gpusvm); | 1498 | drm_gpusvm_notifier_unlock(gpusvm); |
| 1481 | kvfree(pfns); | 1499 | kvfree(pfns); |
| 1482 | set_seqno: | 1500 | set_seqno: |
| @@ -1765,6 +1783,8 @@ int drm_gpusvm_migrate_to_devmem(struct drm_gpusvm *gpusvm, · 282 unmodified lines | |||
| 1765 | goto err_finalize; | 1783 | goto err_finalize; |
| 1766 | 1784 | ||
| 1767 | /* Upon success bind devmem allocation to range and zdd */ | 1785 | /* Upon success bind devmem allocation to range and zdd */ |
| 1786 | devmem_allocation->timeslice_expiration = get_jiffies_64() + | ||
| 1787 | msecs_to_jiffies(ctx->timeslice_ms); | ||
| 1768 | zdd->devmem_allocation = devmem_allocation; /* Owns ref */ | 1788 | zdd->devmem_allocation = devmem_allocation; /* Owns ref */ |
| 1769 | 1789 | ||
| 1770 | err_finalize: | 1790 | err_finalize: |
| @@ -1985,6 +2005,13 @@ static int __drm_gpusvm_migrate_to_ram(struct vm_area_struct *vas, · 214 unmodified lines | |||
| 1985 | void *buf; | 2005 | void *buf; |
| 1986 | int i, err = 0; | 2006 | int i, err = 0; |
| 1987 | 2007 | ||
| 2008 | if (page) { | ||
| 2009 | zdd = page->zone_device_data; | ||
| 2010 | if (time_before64(get_jiffies_64(), | ||
| 2011 | zdd->devmem_allocation->timeslice_expiration)) | ||
| 2012 | return 0; | ||
| 2013 | } | ||
| 2014 | |||
| 1988 | start = ALIGN_DOWN(fault_addr, size); | 2015 | start = ALIGN_DOWN(fault_addr, size); |
| 1989 | end = ALIGN(fault_addr + 1, size); | 2016 | end = ALIGN(fault_addr + 1, size); |
| 1990 | 2017 | ||
| @@ -75,7 +75,7 @@ static void meson_encoder_hdmi_set_vclk(struct meson_encoder_hdmi *encoder_hdmi, · 74 unmodified lines | |||
| 75 | unsigned long long venc_freq; | 75 | unsigned long long venc_freq; |
| 76 | unsigned long long hdmi_freq; | 76 | unsigned long long hdmi_freq; |
| 77 | 77 | ||
| 78 | vclk_freq = mode->clock * 1000; | 78 | vclk_freq = mode->clock * 1000ULL; |
| 79 | 79 | ||
| 80 | /* For 420, pixel clock is half unlike venc clock */ | 80 | /* For 420, pixel clock is half unlike venc clock */ |
| 81 | if (encoder_hdmi->output_bus_fmt == MEDIA_BUS_FMT_UYYVYY8_0_5X24) | 81 | if (encoder_hdmi->output_bus_fmt == MEDIA_BUS_FMT_UYYVYY8_0_5X24) |
| @@ -123,7 +123,7 @@ static enum drm_mode_status meson_encoder_hdmi_mode_valid(struct drm_bridge *bri · 41 unmodified lines | |||
| 123 | struct meson_encoder_hdmi *encoder_hdmi = bridge_to_meson_encoder_hdmi(bridge); | 123 | struct meson_encoder_hdmi *encoder_hdmi = bridge_to_meson_encoder_hdmi(bridge); |
| 124 | struct meson_drm *priv = encoder_hdmi->priv; | 124 | struct meson_drm *priv = encoder_hdmi->priv; |
| 125 | bool is_hdmi2_sink = display_info->hdmi.scdc.supported; | 125 | bool is_hdmi2_sink = display_info->hdmi.scdc.supported; |
| 126 | unsigned long long clock = mode->clock * 1000; | 126 | unsigned long long clock = mode->clock * 1000ULL; |
| 127 | unsigned long long phy_freq; | 127 | unsigned long long phy_freq; |
| 128 | unsigned long long vclk_freq; | 128 | unsigned long long vclk_freq; |
| 129 | unsigned long long venc_freq; | 129 | unsigned long long venc_freq; |
| @@ -390,7 +390,10 @@ static int panel_mipi_dbi_spi_probe(struct spi_device *spi) · 389 unmodified lines | |||
| 390 | 390 | ||
| 391 | spi_set_drvdata(spi, drm); | 391 | spi_set_drvdata(spi, drm); |
| 392 | 392 | ||
| 393 | drm_client_setup(drm, NULL); | 393 | if (bpp == 16) |
| 394 | drm_client_setup_with_fourcc(drm, DRM_FORMAT_RGB565); | ||
| 395 | else | ||
| 396 | drm_client_setup_with_fourcc(drm, DRM_FORMAT_RGB888); | ||
| 394 | 397 | ||
| 395 | return 0; | 398 | return 0; |
| 396 | } | 399 | } |
| @@ -47,6 +47,10 @@ · 46 unmodified lines | |||
| 47 | #define MI_LRI_FORCE_POSTED REG_BIT(12) | 47 | #define MI_LRI_FORCE_POSTED REG_BIT(12) |
| 48 | #define MI_LRI_LEN(x) (((x) & 0xff) + 1) | 48 | #define MI_LRI_LEN(x) (((x) & 0xff) + 1) |
| 49 | 49 | ||
| 50 | #define MI_STORE_REGISTER_MEM (__MI_INSTR(0x24) | XE_INSTR_NUM_DW(4)) | ||
| 51 | #define MI_SRM_USE_GGTT REG_BIT(22) | ||
| 52 | #define MI_SRM_ADD_CS_OFFSET REG_BIT(19) | ||
| 53 | |||
| 50 | #define MI_FLUSH_DW __MI_INSTR(0x26) | 54 | #define MI_FLUSH_DW __MI_INSTR(0x26) |
| 51 | #define MI_FLUSH_DW_PROTECTED_MEM_EN REG_BIT(22) | 55 | #define MI_FLUSH_DW_PROTECTED_MEM_EN REG_BIT(22) |
| 52 | #define MI_FLUSH_DW_STORE_INDEX REG_BIT(21) | 56 | #define MI_FLUSH_DW_STORE_INDEX REG_BIT(21) |
| @@ -43,6 +43,10 @@ · 42 unmodified lines | |||
| 43 | #define XEHPC_BCS8_RING_BASE 0x3ee000 | 43 | #define XEHPC_BCS8_RING_BASE 0x3ee000 |
| 44 | #define GSCCS_RING_BASE 0x11a000 | 44 | #define GSCCS_RING_BASE 0x11a000 |
| 45 | 45 | ||
| 46 | #define ENGINE_ID(base) XE_REG((base) + 0x8c) | ||
| 47 | #define ENGINE_INSTANCE_ID REG_GENMASK(9, 4) | ||
| 48 | #define ENGINE_CLASS_ID REG_GENMASK(2, 0) | ||
| 49 | |||
| 46 | #define RING_TAIL(base) XE_REG((base) + 0x30) | 50 | #define RING_TAIL(base) XE_REG((base) + 0x30) |
| 47 | #define TAIL_ADDR REG_GENMASK(20, 3) | 51 | #define TAIL_ADDR REG_GENMASK(20, 3) |
| 48 | 52 | ||
| @@ -154,6 +158,7 @@ · 105 unmodified lines | |||
| 154 | #define STOP_RING REG_BIT(8) | 158 | #define STOP_RING REG_BIT(8) |
| 155 | 159 | ||
| 156 | #define RING_CTX_TIMESTAMP(base) XE_REG((base) + 0x3a8) | 160 | #define RING_CTX_TIMESTAMP(base) XE_REG((base) + 0x3a8) |
| 161 | #define RING_CTX_TIMESTAMP_UDW(base) XE_REG((base) + 0x3ac) | ||
| 157 | #define CSBE_DEBUG_STATUS(base) XE_REG((base) + 0x3fc) | 162 | #define CSBE_DEBUG_STATUS(base) XE_REG((base) + 0x3fc) |
| 158 | 163 | ||
| 159 | #define RING_FORCE_TO_NONPRIV(base, i) XE_REG(((base) + 0x4d0) + (i) * 4) | 164 | #define RING_FORCE_TO_NONPRIV(base, i) XE_REG(((base) + 0x4d0) + (i) * 4) |
| @@ -157,6 +157,7 @@ · 156 unmodified lines | |||
| 157 | #define XEHPG_SC_INSTDONE_EXTRA2 XE_REG_MCR(0x7108) | 157 | #define XEHPG_SC_INSTDONE_EXTRA2 XE_REG_MCR(0x7108) |
| 158 | 158 | ||
| 159 | #define COMMON_SLICE_CHICKEN4 XE_REG(0x7300, XE_REG_OPTION_MASKED) | 159 | #define COMMON_SLICE_CHICKEN4 XE_REG(0x7300, XE_REG_OPTION_MASKED) |
| 160 | #define SBE_PUSH_CONSTANT_BEHIND_FIX_ENABLE REG_BIT(12) | ||
| 160 | #define DISABLE_TDC_LOAD_BALANCING_CALC REG_BIT(6) | 161 | #define DISABLE_TDC_LOAD_BALANCING_CALC REG_BIT(6) |
| 161 | 162 | ||
| 162 | #define COMMON_SLICE_CHICKEN3 XE_REG(0x7304, XE_REG_OPTION_MASKED) | 163 | #define COMMON_SLICE_CHICKEN3 XE_REG(0x7304, XE_REG_OPTION_MASKED) |
| @@ -11,7 +11,9 @@ · 10 unmodified lines | |||
| 11 | #define CTX_RING_TAIL (0x06 + 1) | 11 | #define CTX_RING_TAIL (0x06 + 1) |
| 12 | #define CTX_RING_START (0x08 + 1) | 12 | #define CTX_RING_START (0x08 + 1) |
| 13 | #define CTX_RING_CTL (0x0a + 1) | 13 | #define CTX_RING_CTL (0x0a + 1) |
| 14 | #define CTX_BB_PER_CTX_PTR (0x12 + 1) | ||
| 14 | #define CTX_TIMESTAMP (0x22 + 1) | 15 | #define CTX_TIMESTAMP (0x22 + 1) |
| 16 | #define CTX_TIMESTAMP_UDW (0x24 + 1) | ||
| 15 | #define CTX_INDIRECT_RING_STATE (0x26 + 1) | 17 | #define CTX_INDIRECT_RING_STATE (0x26 + 1) |
| 16 | #define CTX_PDP0_UDW (0x30 + 1) | 18 | #define CTX_PDP0_UDW (0x30 + 1) |
| 17 | #define CTX_PDP0_LDW (0x32 + 1) | 19 | #define CTX_PDP0_LDW (0x32 + 1) |
| @@ -330,6 +330,8 @@ struct xe_device { · 329 unmodified lines | |||
| 330 | u8 has_sriov:1; | 330 | u8 has_sriov:1; |
| 331 | /** @info.has_usm: Device has unified shared memory support */ | 331 | /** @info.has_usm: Device has unified shared memory support */ |
| 332 | u8 has_usm:1; | 332 | u8 has_usm:1; |
| 333 | /** @info.has_64bit_timestamp: Device supports 64-bit timestamps */ | ||
| 334 | u8 has_64bit_timestamp:1; | ||
| 333 | /** @info.is_dgfx: is discrete device */ | 335 | /** @info.is_dgfx: is discrete device */ |
| 334 | u8 is_dgfx:1; | 336 | u8 is_dgfx:1; |
| 335 | /** | 337 | /** |
| @@ -830,7 +830,7 @@ void xe_exec_queue_update_run_ticks(struct xe_exec_queue *q) · 829 unmodified lines | |||
| 830 | { | 830 | { |
| 831 | struct xe_device *xe = gt_to_xe(q->gt); | 831 | struct xe_device *xe = gt_to_xe(q->gt); |
| 832 | struct xe_lrc *lrc; | 832 | struct xe_lrc *lrc; |
| 833 | u32 old_ts, new_ts; | 833 | u64 old_ts, new_ts; |
| 834 | int idx; | 834 | int idx; |
| 835 | 835 | ||
| 836 | /* | 836 | /* |
| @@ -941,7 +941,7 @@ static bool check_timeout(struct xe_exec_queue *q, struct xe_sched_job *job) · 940 unmodified lines | |||
| 941 | return xe_sched_invalidate_job(job, 2); | 941 | return xe_sched_invalidate_job(job, 2); |
| 942 | } | 942 | } |
| 943 | 943 | ||
| 944 | ctx_timestamp = xe_lrc_ctx_timestamp(q->lrc[0]); | 944 | ctx_timestamp = lower_32_bits(xe_lrc_ctx_timestamp(q->lrc[0])); |
| 945 | ctx_job_timestamp = xe_lrc_ctx_job_timestamp(q->lrc[0]); | 945 | ctx_job_timestamp = xe_lrc_ctx_job_timestamp(q->lrc[0]); |
| 946 | 946 | ||
| 947 | /* | 947 | /* |
| @@ -24,6 +24,7 @@ · 23 unmodified lines | |||
| 24 | #include "xe_hw_fence.h" | 24 | #include "xe_hw_fence.h" |
| 25 | #include "xe_map.h" | 25 | #include "xe_map.h" |
| 26 | #include "xe_memirq.h" | 26 | #include "xe_memirq.h" |
| 27 | #include "xe_mmio.h" | ||
| 27 | #include "xe_sriov.h" | 28 | #include "xe_sriov.h" |
| 28 | #include "xe_trace_lrc.h" | 29 | #include "xe_trace_lrc.h" |
| 29 | #include "xe_vm.h" | 30 | #include "xe_vm.h" |
| @@ -650,6 +651,7 @@ u32 xe_lrc_pphwsp_offset(struct xe_lrc *lrc) · 620 unmodified lines | |||
| 650 | #define LRC_START_SEQNO_PPHWSP_OFFSET (LRC_SEQNO_PPHWSP_OFFSET + 8) | 651 | #define LRC_START_SEQNO_PPHWSP_OFFSET (LRC_SEQNO_PPHWSP_OFFSET + 8) |
| 651 | #define LRC_CTX_JOB_TIMESTAMP_OFFSET (LRC_START_SEQNO_PPHWSP_OFFSET + 8) | 652 | #define LRC_CTX_JOB_TIMESTAMP_OFFSET (LRC_START_SEQNO_PPHWSP_OFFSET + 8) |
| 652 | #define LRC_PARALLEL_PPHWSP_OFFSET 2048 | 653 | #define LRC_PARALLEL_PPHWSP_OFFSET 2048 |
| 654 | #define LRC_ENGINE_ID_PPHWSP_OFFSET 2096 | ||
| 653 | #define LRC_PPHWSP_SIZE SZ_4K | 655 | #define LRC_PPHWSP_SIZE SZ_4K |
| 654 | 656 | ||
| 655 | u32 xe_lrc_regs_offset(struct xe_lrc *lrc) | 657 | u32 xe_lrc_regs_offset(struct xe_lrc *lrc) |
| @@ -684,7 +686,7 @@ static inline u32 __xe_lrc_start_seqno_offset(struct xe_lrc *lrc) · 28 unmodified lines | |||
| 684 | 686 | ||
| 685 | static u32 __xe_lrc_ctx_job_timestamp_offset(struct xe_lrc *lrc) | 687 | static u32 __xe_lrc_ctx_job_timestamp_offset(struct xe_lrc *lrc) |
| 686 | { | 688 | { |
| 687 | /* The start seqno is stored in the driver-defined portion of PPHWSP */ | 689 | /* This is stored in the driver-defined portion of PPHWSP */ |
| 688 | return xe_lrc_pphwsp_offset(lrc) + LRC_CTX_JOB_TIMESTAMP_OFFSET; | 690 | return xe_lrc_pphwsp_offset(lrc) + LRC_CTX_JOB_TIMESTAMP_OFFSET; |
| 689 | } | 691 | } |
| 690 | 692 | ||
| @@ -694,11 +696,21 @@ static inline u32 __xe_lrc_parallel_offset(struct xe_lrc *lrc) · 3 unmodified lines | |||
| 694 | return xe_lrc_pphwsp_offset(lrc) + LRC_PARALLEL_PPHWSP_OFFSET; | 696 | return xe_lrc_pphwsp_offset(lrc) + LRC_PARALLEL_PPHWSP_OFFSET; |
| 695 | } | 697 | } |
| 696 | 698 | ||
| 699 | static inline u32 __xe_lrc_engine_id_offset(struct xe_lrc *lrc) | ||
| 700 | { | ||
| 701 | return xe_lrc_pphwsp_offset(lrc) + LRC_ENGINE_ID_PPHWSP_OFFSET; | ||
| 702 | } | ||
| 703 | |||
| 697 | static u32 __xe_lrc_ctx_timestamp_offset(struct xe_lrc *lrc) | 704 | static u32 __xe_lrc_ctx_timestamp_offset(struct xe_lrc *lrc) |
| 698 | { | 705 | { |
| 699 | return __xe_lrc_regs_offset(lrc) + CTX_TIMESTAMP * sizeof(u32); | 706 | return __xe_lrc_regs_offset(lrc) + CTX_TIMESTAMP * sizeof(u32); |
| 700 | } | 707 | } |
| 701 | 708 | ||
| 709 | static u32 __xe_lrc_ctx_timestamp_udw_offset(struct xe_lrc *lrc) | ||
| 710 | { | ||
| 711 | return __xe_lrc_regs_offset(lrc) + CTX_TIMESTAMP_UDW * sizeof(u32); | ||
| 712 | } | ||
| 713 | |||
| 702 | static inline u32 __xe_lrc_indirect_ring_offset(struct xe_lrc *lrc) | 714 | static inline u32 __xe_lrc_indirect_ring_offset(struct xe_lrc *lrc) |
| 703 | { | 715 | { |
| 704 | /* Indirect ring state page is at the very end of LRC */ | 716 | /* Indirect ring state page is at the very end of LRC */ |
| @@ -726,8 +738,10 @@ DECL_MAP_ADDR_HELPERS(regs) · 21 unmodified lines | |||
| 726 | DECL_MAP_ADDR_HELPERS(start_seqno) | 738 | DECL_MAP_ADDR_HELPERS(start_seqno) |
| 727 | DECL_MAP_ADDR_HELPERS(ctx_job_timestamp) | 739 | DECL_MAP_ADDR_HELPERS(ctx_job_timestamp) |
| 728 | DECL_MAP_ADDR_HELPERS(ctx_timestamp) | 740 | DECL_MAP_ADDR_HELPERS(ctx_timestamp) |
| 741 | DECL_MAP_ADDR_HELPERS(ctx_timestamp_udw) | ||
| 729 | DECL_MAP_ADDR_HELPERS(parallel) | 742 | DECL_MAP_ADDR_HELPERS(parallel) |
| 730 | DECL_MAP_ADDR_HELPERS(indirect_ring) | 743 | DECL_MAP_ADDR_HELPERS(indirect_ring) |
| 744 | DECL_MAP_ADDR_HELPERS(engine_id) | ||
| 731 | 745 | ||
| 732 | #undef DECL_MAP_ADDR_HELPERS | 746 | #undef DECL_MAP_ADDR_HELPERS |
| 733 | 747 | ||
| @@ -742,19 +756,38 @@ u32 xe_lrc_ctx_timestamp_ggtt_addr(struct xe_lrc *lrc) · 8 unmodified lines | |||
| 742 | return __xe_lrc_ctx_timestamp_ggtt_addr(lrc); | 756 | return __xe_lrc_ctx_timestamp_ggtt_addr(lrc); |
| 743 | } | 757 | } |
| 744 | 758 | ||
| 759 | /** | ||
| 760 | * xe_lrc_ctx_timestamp_udw_ggtt_addr() - Get ctx timestamp udw GGTT address | ||
| 761 | * @lrc: Pointer to the lrc. | ||
| 762 | * | ||
| 763 | * Returns: ctx timestamp udw GGTT address | ||
| 764 | */ | ||
| 765 | u32 xe_lrc_ctx_timestamp_udw_ggtt_addr(struct xe_lrc *lrc) | ||
| 766 | { | ||
| 767 | return __xe_lrc_ctx_timestamp_udw_ggtt_addr(lrc); | ||
| 768 | } | ||
| 769 | |||
| 745 | /** | 770 | /** |
| 746 | * xe_lrc_ctx_timestamp() - Read ctx timestamp value | 771 | * xe_lrc_ctx_timestamp() - Read ctx timestamp value |
| 747 | * @lrc: Pointer to the lrc. | 772 | * @lrc: Pointer to the lrc. |
| 748 | * | 773 | * |
| 749 | * Returns: ctx timestamp value | 774 | * Returns: ctx timestamp value |
| 750 | */ | 775 | */ |
| 751 | u32 xe_lrc_ctx_timestamp(struct xe_lrc *lrc) | 776 | u64 xe_lrc_ctx_timestamp(struct xe_lrc *lrc) |
| 752 | { | 777 | { |
| 753 | struct xe_device *xe = lrc_to_xe(lrc); | 778 | struct xe_device *xe = lrc_to_xe(lrc); |
| 754 | struct iosys_map map; | 779 | struct iosys_map map; |
| 780 | u32 ldw, udw = 0; | ||
| 755 | 781 | ||
| 756 | map = __xe_lrc_ctx_timestamp_map(lrc); | 782 | map = __xe_lrc_ctx_timestamp_map(lrc); |
| 757 | return xe_map_read32(xe, &map); | 783 | ldw = xe_map_read32(xe, &map); |
| 784 | |||
| 785 | if (xe->info.has_64bit_timestamp) { | ||
| 786 | map = __xe_lrc_ctx_timestamp_udw_map(lrc); | ||
| 787 | udw = xe_map_read32(xe, &map); | ||
| 788 | } | ||
| 789 | |||
| 790 | return (u64)udw << 32 | ldw; | ||
| 758 | } | 791 | } |
| 759 | 792 | ||
| 760 | /** | 793 | /** |
| @@ -864,7 +897,7 @@ static void *empty_lrc_data(struct xe_hw_engine *hwe) · 103 unmodified lines | |||
| 864 | 897 | ||
| 865 | static void xe_lrc_set_ppgtt(struct xe_lrc *lrc, struct xe_vm *vm) | 898 | static void xe_lrc_set_ppgtt(struct xe_lrc *lrc, struct xe_vm *vm) |
| 866 | { | 899 | { |
| 867 | u64 desc = xe_vm_pdp4_descriptor(vm, lrc->tile); | 900 | u64 desc = xe_vm_pdp4_descriptor(vm, gt_to_tile(lrc->gt)); |
| 868 | 901 | ||
| 869 | xe_lrc_write_ctx_reg(lrc, CTX_PDP0_UDW, upper_32_bits(desc)); | 902 | xe_lrc_write_ctx_reg(lrc, CTX_PDP0_UDW, upper_32_bits(desc)); |
| 870 | xe_lrc_write_ctx_reg(lrc, CTX_PDP0_LDW, lower_32_bits(desc)); | 903 | xe_lrc_write_ctx_reg(lrc, CTX_PDP0_LDW, lower_32_bits(desc)); |
| @@ -877,6 +910,65 @@ static void xe_lrc_finish(struct xe_lrc *lrc) · 6 unmodified lines | |||
| 877 | xe_bo_unpin(lrc->bo); | 910 | xe_bo_unpin(lrc->bo); |
| 878 | xe_bo_unlock(lrc->bo); | 911 | xe_bo_unlock(lrc->bo); |
| 879 | xe_bo_put(lrc->bo); | 912 | xe_bo_put(lrc->bo); |
| 913 | xe_bo_unpin_map_no_vm(lrc->bb_per_ctx_bo); | ||
| 914 | } | ||
| 915 | |||
| 916 | /* | ||
| 917 | * xe_lrc_setup_utilization() - Setup wa bb to assist in calculating active | ||
| 918 | * context run ticks. | ||
| 919 | * @lrc: Pointer to the lrc. | ||
| 920 | * | ||
| 921 | * Context Timestamp (CTX_TIMESTAMP) in the LRC accumulates the run ticks of the | ||
| 922 | * context, but only gets updated when the context switches out. In order to | ||
| 923 | * check how long a context has been active before it switches out, two things | ||
| 924 | * are required: | ||
| 925 | * | ||
| 926 | * (1) Determine if the context is running: | ||
| 927 | * To do so, we program the WA BB to set an initial value for CTX_TIMESTAMP in | ||
| 928 | * the LRC. The value chosen is 1 since 0 is the initial value when the LRC is | ||
| 929 | * initialized. During a query, we just check for this value to determine if the | ||
| 930 | * context is active. If the context switched out, it would overwrite this | ||
| 931 | * location with the actual CTX_TIMESTAMP MMIO value. Note that WA BB runs as | ||
| 932 | * the last part of context restore, so reusing this LRC location will not | ||
| 933 | * clobber anything. | ||
| 934 | * | ||
| 935 | * (2) Calculate the time that the context has been active for: | ||
| 936 | * The CTX_TIMESTAMP ticks only when the context is active. If a context is | ||
| 937 | * active, we just use the CTX_TIMESTAMP MMIO as the new value of utilization. | ||
| 938 | * While doing so, we need to read the CTX_TIMESTAMP MMIO for the specific | ||
| 939 | * engine instance. Since we do not know which instance the context is running | ||
| 940 | * on until it is scheduled, we also read the ENGINE_ID MMIO in the WA BB and | ||
| 941 | * store it in the PPHSWP. | ||
| 942 | */ | ||
| 943 | #define CONTEXT_ACTIVE 1ULL | ||
| 944 | static void xe_lrc_setup_utilization(struct xe_lrc *lrc) | ||
| 945 | { | ||
| 946 | u32 *cmd; | ||
| 947 | |||
| 948 | cmd = lrc->bb_per_ctx_bo->vmap.vaddr; | ||
| 949 | |||
| 950 | *cmd++ = MI_STORE_REGISTER_MEM | MI_SRM_USE_GGTT | MI_SRM_ADD_CS_OFFSET; | ||
| 951 | *cmd++ = ENGINE_ID(0).addr; | ||
| 952 | *cmd++ = __xe_lrc_engine_id_ggtt_addr(lrc); | ||
| 953 | *cmd++ = 0; | ||
| 954 | |||
| 955 | *cmd++ = MI_STORE_DATA_IMM | MI_SDI_GGTT | MI_SDI_NUM_DW(1); | ||
| 956 | *cmd++ = __xe_lrc_ctx_timestamp_ggtt_addr(lrc); | ||
| 957 | *cmd++ = 0; | ||
| 958 | *cmd++ = lower_32_bits(CONTEXT_ACTIVE); | ||
| 959 | |||
| 960 | if (lrc_to_xe(lrc)->info.has_64bit_timestamp) { | ||
| 961 | *cmd++ = MI_STORE_DATA_IMM | MI_SDI_GGTT | MI_SDI_NUM_DW(1); | ||
| 962 | *cmd++ = __xe_lrc_ctx_timestamp_udw_ggtt_addr(lrc); | ||
| 963 | *cmd++ = 0; | ||
| 964 | *cmd++ = upper_32_bits(CONTEXT_ACTIVE); | ||
| 965 | } | ||
| 966 | |||
| 967 | *cmd++ = MI_BATCH_BUFFER_END; | ||
| 968 | |||
| 969 | xe_lrc_write_ctx_reg(lrc, CTX_BB_PER_CTX_PTR, | ||
| 970 | xe_bo_ggtt_addr(lrc->bb_per_ctx_bo) | 1); | ||
| 971 | |||
| 880 | } | 972 | } |
| 881 | 973 | ||
| 882 | #define PVC_CTX_ASID (0x2e + 1) | 974 | #define PVC_CTX_ASID (0x2e + 1) |
| @@ -893,31 +985,40 @@ static int xe_lrc_init(struct xe_lrc *lrc, struct xe_hw_engine *hwe, · 10 unmodified lines | |||
| 893 | void *init_data = NULL; | 985 | void *init_data = NULL; |
| 894 | u32 arb_enable; | 986 | u32 arb_enable; |
| 895 | u32 lrc_size; | 987 | u32 lrc_size; |
| 988 | u32 bo_flags; | ||
| 896 | int err; | 989 | int err; |
| 897 | 990 | ||
| 898 | kref_init(&lrc->refcount); | 991 | kref_init(&lrc->refcount); |
| 992 | lrc->gt = gt; | ||
| 899 | lrc->flags = 0; | 993 | lrc->flags = 0; |
| 900 | lrc_size = ring_size + xe_gt_lrc_size(gt, hwe->class); | 994 | lrc_size = ring_size + xe_gt_lrc_size(gt, hwe->class); |
| 901 | if (xe_gt_has_indirect_ring_state(gt)) | 995 | if (xe_gt_has_indirect_ring_state(gt)) |
| 902 | lrc->flags |= XE_LRC_FLAG_INDIRECT_RING_STATE; | 996 | lrc->flags |= XE_LRC_FLAG_INDIRECT_RING_STATE; |
| 903 | 997 | ||
| 998 | bo_flags = XE_BO_FLAG_VRAM_IF_DGFX(tile) | XE_BO_FLAG_GGTT | | ||
| 999 | XE_BO_FLAG_GGTT_INVALIDATE; | ||
| 1000 | |||
| 904 | /* | 1001 | /* |
| 905 | * FIXME: Perma-pinning LRC as we don't yet support moving GGTT address | 1002 | * FIXME: Perma-pinning LRC as we don't yet support moving GGTT address |
| 906 | * via VM bind calls. | 1003 | * via VM bind calls. |
| 907 | */ | 1004 | */ |
| 908 | lrc->bo = xe_bo_create_pin_map(xe, tile, vm, lrc_size, | 1005 | lrc->bo = xe_bo_create_pin_map(xe, tile, vm, lrc_size, |
| 909 | ttm_bo_type_kernel, | 1006 | ttm_bo_type_kernel, |
| 910 | XE_BO_FLAG_VRAM_IF_DGFX(tile) | | 1007 | bo_flags); |
| 911 | XE_BO_FLAG_GGTT | | ||
| 912 | XE_BO_FLAG_GGTT_INVALIDATE); | ||
| 913 | if (IS_ERR(lrc->bo)) | 1008 | if (IS_ERR(lrc->bo)) |
| 914 | return PTR_ERR(lrc->bo); | 1009 | return PTR_ERR(lrc->bo); |
| 915 | 1010 | ||
| 1011 | lrc->bb_per_ctx_bo = xe_bo_create_pin_map(xe, tile, NULL, SZ_4K, | ||
| 1012 | ttm_bo_type_kernel, | ||
| 1013 | bo_flags); | ||
| 1014 | if (IS_ERR(lrc->bb_per_ctx_bo)) { | ||
| 1015 | err = PTR_ERR(lrc->bb_per_ctx_bo); | ||
| 1016 | goto err_lrc_finish; | ||
| 1017 | } | ||
| 1018 | |||
| 916 | lrc->size = lrc_size; | 1019 | lrc->size = lrc_size; |
| 917 | lrc->tile = gt_to_tile(hwe->gt); | ||
| 918 | lrc->ring.size = ring_size; | 1020 | lrc->ring.size = ring_size; |
| 919 | lrc->ring.tail = 0; | 1021 | lrc->ring.tail = 0; |
| 920 | lrc->ctx_timestamp = 0; | ||
| 921 | 1022 | ||
| 922 | xe_hw_fence_ctx_init(&lrc->fence_ctx, hwe->gt, | 1023 | xe_hw_fence_ctx_init(&lrc->fence_ctx, hwe->gt, |
| 923 | hwe->fence_irq, hwe->name); | 1024 | hwe->fence_irq, hwe->name); |
| @@ -990,7 +1091,10 @@ static int xe_lrc_init(struct xe_lrc *lrc, struct xe_hw_engine *hwe, · 66 unmodified lines | |||
| 990 | xe_lrc_read_ctx_reg(lrc, CTX_CONTEXT_CONTROL) | | 1091 | xe_lrc_read_ctx_reg(lrc, CTX_CONTEXT_CONTROL) | |
| 991 | _MASKED_BIT_ENABLE(CTX_CTRL_PXP_ENABLE)); | 1092 | _MASKED_BIT_ENABLE(CTX_CTRL_PXP_ENABLE)); |
| 992 | 1093 | ||
| 1094 | lrc->ctx_timestamp = 0; | ||
| 993 | xe_lrc_write_ctx_reg(lrc, CTX_TIMESTAMP, 0); | 1095 | xe_lrc_write_ctx_reg(lrc, CTX_TIMESTAMP, 0); |
| 1096 | if (lrc_to_xe(lrc)->info.has_64bit_timestamp) | ||
| 1097 | xe_lrc_write_ctx_reg(lrc, CTX_TIMESTAMP_UDW, 0); | ||
| 994 | 1098 | ||
| 995 | if (xe->info.has_asid && vm) | 1099 | if (xe->info.has_asid && vm) |
| 996 | xe_lrc_write_ctx_reg(lrc, PVC_CTX_ASID, vm->usm.asid); | 1100 | xe_lrc_write_ctx_reg(lrc, PVC_CTX_ASID, vm->usm.asid); |
| @@ -1019,6 +1123,8 @@ static int xe_lrc_init(struct xe_lrc *lrc, struct xe_hw_engine *hwe, · 22 unmodified lines | |||
| 1019 | map = __xe_lrc_start_seqno_map(lrc); | 1123 | map = __xe_lrc_start_seqno_map(lrc); |
| 1020 | xe_map_write32(lrc_to_xe(lrc), &map, lrc->fence_ctx.next_seqno - 1); | 1124 | xe_map_write32(lrc_to_xe(lrc), &map, lrc->fence_ctx.next_seqno - 1); |
| 1021 | 1125 | ||
| 1126 | xe_lrc_setup_utilization(lrc); | ||
| 1127 | |||
| 1022 | return 0; | 1128 | return 0; |
| 1023 | 1129 | ||
| 1024 | err_lrc_finish: | 1130 | err_lrc_finish: |
| @@ -1238,6 +1344,21 @@ struct iosys_map xe_lrc_parallel_map(struct xe_lrc *lrc) · 213 unmodified lines | |||
| 1238 | return __xe_lrc_parallel_map(lrc); | 1344 | return __xe_lrc_parallel_map(lrc); |
| 1239 | } | 1345 | } |
| 1240 | 1346 | ||
| 1347 | /** | ||
| 1348 | * xe_lrc_engine_id() - Read engine id value | ||
| 1349 | * @lrc: Pointer to the lrc. | ||
| 1350 | * | ||
| 1351 | * Returns: context id value | ||
| 1352 | */ | ||
| 1353 | static u32 xe_lrc_engine_id(struct xe_lrc *lrc) | ||
| 1354 | { | ||
| 1355 | struct xe_device *xe = lrc_to_xe(lrc); | ||
| 1356 | struct iosys_map map; | ||
| 1357 | |||
| 1358 | map = __xe_lrc_engine_id_map(lrc); | ||
| 1359 | return xe_map_read32(xe, &map); | ||
| 1360 | } | ||
| 1361 | |||
| 1241 | static int instr_dw(u32 cmd_header) | 1362 | static int instr_dw(u32 cmd_header) |
| 1242 | { | 1363 | { |
| 1243 | /* GFXPIPE "SINGLE_DW" opcodes are a single dword */ | 1364 | /* GFXPIPE "SINGLE_DW" opcodes are a single dword */ |
| @@ -1684,7 +1805,7 @@ struct xe_lrc_snapshot *xe_lrc_snapshot_capture(struct xe_lrc *lrc) · 440 unmodified lines | |||
| 1684 | snapshot->lrc_offset = xe_lrc_pphwsp_offset(lrc); | 1805 | snapshot->lrc_offset = xe_lrc_pphwsp_offset(lrc); |
| 1685 | snapshot->lrc_size = lrc->bo->size - snapshot->lrc_offset; | 1806 | snapshot->lrc_size = lrc->bo->size - snapshot->lrc_offset; |
| 1686 | snapshot->lrc_snapshot = NULL; | 1807 | snapshot->lrc_snapshot = NULL; |
| 1687 | snapshot->ctx_timestamp = xe_lrc_ctx_timestamp(lrc); | 1808 | snapshot->ctx_timestamp = lower_32_bits(xe_lrc_ctx_timestamp(lrc)); |
| 1688 | snapshot->ctx_job_timestamp = xe_lrc_ctx_job_timestamp(lrc); | 1809 | snapshot->ctx_job_timestamp = xe_lrc_ctx_job_timestamp(lrc); |
| 1689 | return snapshot; | 1810 | return snapshot; |
| 1690 | } | 1811 | } |
| @@ -1784,22 +1905,74 @@ void xe_lrc_snapshot_free(struct xe_lrc_snapshot *snapshot) · 93 unmodified lines | |||
| 1784 | kfree(snapshot); | 1905 | kfree(snapshot); |
| 1785 | } | 1906 | } |
| 1786 | 1907 | ||
| 1908 | static int get_ctx_timestamp(struct xe_lrc *lrc, u32 engine_id, u64 *reg_ctx_ts) | ||
| 1909 | { | ||
| 1910 | u16 class = REG_FIELD_GET(ENGINE_CLASS_ID, engine_id); | ||
| 1911 | u16 instance = REG_FIELD_GET(ENGINE_INSTANCE_ID, engine_id); | ||
| 1912 | struct xe_hw_engine *hwe; | ||
| 1913 | u64 val; | ||
| 1914 | |||
| 1915 | hwe = xe_gt_hw_engine(lrc->gt, class, instance, false); | ||
| 1916 | if (xe_gt_WARN_ONCE(lrc->gt, !hwe || xe_hw_engine_is_reserved(hwe), | ||
| 1917 | "Unexpected engine class:instance %d:%d for context utilization\n", | ||
| 1918 | class, instance)) | ||
| 1919 | return -1; | ||
| 1920 | |||
| 1921 | if (lrc_to_xe(lrc)->info.has_64bit_timestamp) | ||
| 1922 | val = xe_mmio_read64_2x32(&hwe->gt->mmio, | ||
| 1923 | RING_CTX_TIMESTAMP(hwe->mmio_base)); | ||
| 1924 | else | ||
| 1925 | val = xe_mmio_read32(&hwe->gt->mmio, | ||
| 1926 | RING_CTX_TIMESTAMP(hwe->mmio_base)); | ||
| 1927 | |||
| 1928 | *reg_ctx_ts = val; | ||
| 1929 | |||
| 1930 | return 0; | ||
| 1931 | } | ||
| 1932 | |||
| 1787 | /** | 1933 | /** |
| 1788 | * xe_lrc_update_timestamp() - Update ctx timestamp | 1934 | * xe_lrc_update_timestamp() - Update ctx timestamp |
| 1789 | * @lrc: Pointer to the lrc. | 1935 | * @lrc: Pointer to the lrc. |
| 1790 | * @old_ts: Old timestamp value | 1936 | * @old_ts: Old timestamp value |
| 1791 | * | 1937 | * |
| 1792 | * Populate @old_ts current saved ctx timestamp, read new ctx timestamp and | 1938 | * Populate @old_ts current saved ctx timestamp, read new ctx timestamp and |
| 1793 | * update saved value. | 1939 | * update saved value. With support for active contexts, the calculation may be |
| 1940 | * slightly racy, so follow a read-again logic to ensure that the context is | ||
| 1941 | * still active before returning the right timestamp. | ||
| 1794 | * | 1942 | * |
| 1795 | * Returns: New ctx timestamp value | 1943 | * Returns: New ctx timestamp value |
| 1796 | */ | 1944 | */ |
| 1797 | u32 xe_lrc_update_timestamp(struct xe_lrc *lrc, u32 *old_ts) | 1945 | u64 xe_lrc_update_timestamp(struct xe_lrc *lrc, u64 *old_ts) |
| 1798 | { | 1946 | { |
| 1947 | u64 lrc_ts, reg_ts; | ||
| 1948 | u32 engine_id; | ||
| 1949 | |||
| 1799 | *old_ts = lrc->ctx_timestamp; | 1950 | *old_ts = lrc->ctx_timestamp; |
| 1800 | 1951 | ||
| 1801 | lrc->ctx_timestamp = xe_lrc_ctx_timestamp(lrc); | 1952 | lrc_ts = xe_lrc_ctx_timestamp(lrc); |
| 1953 | /* CTX_TIMESTAMP mmio read is invalid on VF, so return the LRC value */ | ||
| 1954 | if (IS_SRIOV_VF(lrc_to_xe(lrc))) { | ||
| 1955 | lrc->ctx_timestamp = lrc_ts; | ||
| 1956 | goto done; | ||
| 1957 | } | ||
| 1958 | |||
| 1959 | if (lrc_ts == CONTEXT_ACTIVE) { | ||
| 1960 | engine_id = xe_lrc_engine_id(lrc); | ||
| 1961 | if (!get_ctx_timestamp(lrc, engine_id, ®_ts)) | ||
| 1962 | lrc->ctx_timestamp = reg_ts; | ||
| 1963 | |||
| 1964 | /* read lrc again to ensure context is still active */ | ||
| 1965 | lrc_ts = xe_lrc_ctx_timestamp(lrc); | ||
| 1966 | } | ||
| 1967 | |||
| 1968 | /* | ||
| 1969 | * If context switched out, just use the lrc_ts. Note that this needs to | ||
| 1970 | * be a separate if condition. | ||
| 1971 | */ | ||
| 1972 | if (lrc_ts != CONTEXT_ACTIVE) | ||
| 1973 | lrc->ctx_timestamp = lrc_ts; | ||
| 1802 | 1974 | ||
| 1975 | done: | ||
| 1803 | trace_xe_lrc_update_timestamp(lrc, *old_ts); | 1976 | trace_xe_lrc_update_timestamp(lrc, *old_ts); |
| 1804 | 1977 | ||
| 1805 | return lrc->ctx_timestamp; | 1978 | return lrc->ctx_timestamp; |
| @@ -120,7 +120,8 @@ void xe_lrc_snapshot_print(struct xe_lrc_snapshot *snapshot, struct drm_printer · 119 unmodified lines | |||
| 120 | void xe_lrc_snapshot_free(struct xe_lrc_snapshot *snapshot); | 120 | void xe_lrc_snapshot_free(struct xe_lrc_snapshot *snapshot); |
| 121 | 121 | ||
| 122 | u32 xe_lrc_ctx_timestamp_ggtt_addr(struct xe_lrc *lrc); | 122 | u32 xe_lrc_ctx_timestamp_ggtt_addr(struct xe_lrc *lrc); |
| 123 | u32 xe_lrc_ctx_timestamp(struct xe_lrc *lrc); | 123 | u32 xe_lrc_ctx_timestamp_udw_ggtt_addr(struct xe_lrc *lrc); |
| 124 | u64 xe_lrc_ctx_timestamp(struct xe_lrc *lrc); | ||
| 124 | u32 xe_lrc_ctx_job_timestamp_ggtt_addr(struct xe_lrc *lrc); | 125 | u32 xe_lrc_ctx_job_timestamp_ggtt_addr(struct xe_lrc *lrc); |
| 125 | u32 xe_lrc_ctx_job_timestamp(struct xe_lrc *lrc); | 126 | u32 xe_lrc_ctx_job_timestamp(struct xe_lrc *lrc); |
| 126 | 127 | ||
| @@ -136,6 +137,6 @@ u32 xe_lrc_ctx_job_timestamp(struct xe_lrc *lrc); · 9 unmodified lines | |||
| 136 | * | 137 | * |
| 137 | * Returns the current LRC timestamp | 138 | * Returns the current LRC timestamp |
| 138 | */ | 139 | */ |
| 139 | u32 xe_lrc_update_timestamp(struct xe_lrc *lrc, u32 *old_ts); | 140 | u64 xe_lrc_update_timestamp(struct xe_lrc *lrc, u64 *old_ts); |
| 140 | 141 | ||
| 141 | #endif | 142 | #endif |
| @@ -25,8 +25,8 @@ struct xe_lrc { · 24 unmodified lines | |||
| 25 | /** @size: size of lrc including any indirect ring state page */ | 25 | /** @size: size of lrc including any indirect ring state page */ |
| 26 | u32 size; | 26 | u32 size; |
| 27 | 27 | ||
| 28 | /** @tile: tile which this LRC belongs to */ | 28 | /** @gt: gt which this LRC belongs to */ |
| 29 | struct xe_tile *tile; | 29 | struct xe_gt *gt; |
| 30 | 30 | ||
| 31 | /** @flags: LRC flags */ | 31 | /** @flags: LRC flags */ |
| 32 | #define XE_LRC_FLAG_INDIRECT_RING_STATE 0x1 | 32 | #define XE_LRC_FLAG_INDIRECT_RING_STATE 0x1 |
| @@ -52,7 +52,10 @@ struct xe_lrc { · 19 unmodified lines | |||
| 52 | struct xe_hw_fence_ctx fence_ctx; | 52 | struct xe_hw_fence_ctx fence_ctx; |
| 53 | 53 | ||
| 54 | /** @ctx_timestamp: readout value of CTX_TIMESTAMP on last update */ | 54 | /** @ctx_timestamp: readout value of CTX_TIMESTAMP on last update */ |
| 55 | u32 ctx_timestamp; | 55 | u64 ctx_timestamp; |
| 56 | |||
| 57 | /** @bb_per_ctx_bo: buffer object for per context batch wa buffer */ | ||
| 58 | struct xe_bo *bb_per_ctx_bo; | ||
| 56 | }; | 59 | }; |
| 57 | 60 | ||
| 58 | struct xe_lrc_snapshot; | 61 | struct xe_lrc_snapshot; |
| @@ -29,9 +29,6 @@ struct xe_modparam xe_modparam = { · 28 unmodified lines | |||
| 29 | module_param_named(svm_notifier_size, xe_modparam.svm_notifier_size, uint, 0600); | 29 | module_param_named(svm_notifier_size, xe_modparam.svm_notifier_size, uint, 0600); |
| 30 | MODULE_PARM_DESC(svm_notifier_size, "Set the svm notifier size(in MiB), must be power of 2"); | 30 | MODULE_PARM_DESC(svm_notifier_size, "Set the svm notifier size(in MiB), must be power of 2"); |
| 31 | 31 | ||
| 32 | module_param_named(always_migrate_to_vram, xe_modparam.always_migrate_to_vram, bool, 0444); | ||
| 33 | MODULE_PARM_DESC(always_migrate_to_vram, "Always migrate to VRAM on GPU fault"); | ||
| 34 | |||
| 35 | module_param_named_unsafe(force_execlist, xe_modparam.force_execlist, bool, 0444); | 32 | module_param_named_unsafe(force_execlist, xe_modparam.force_execlist, bool, 0444); |
| 36 | MODULE_PARM_DESC(force_execlist, "Force Execlist submission"); | 33 | MODULE_PARM_DESC(force_execlist, "Force Execlist submission"); |
| 37 | 34 | ||
| @@ -12,7 +12,6 @@ · 11 unmodified lines | |||
| 12 | struct xe_modparam { | 12 | struct xe_modparam { |
| 13 | bool force_execlist; | 13 | bool force_execlist; |
| 14 | bool probe_display; | 14 | bool probe_display; |
| 15 | bool always_migrate_to_vram; | ||
| 16 | u32 force_vram_bar_size; | 15 | u32 force_vram_bar_size; |
| 17 | int guc_log_level; | 16 | int guc_log_level; |
| 18 | char *guc_firmware_path; | 17 | char *guc_firmware_path; |
| @@ -140,6 +140,7 @@ static const struct xe_graphics_desc graphics_xelpg = { · 139 unmodified lines | |||
| 140 | .has_indirect_ring_state = 1, \ | 140 | .has_indirect_ring_state = 1, \ |
| 141 | .has_range_tlb_invalidation = 1, \ | 141 | .has_range_tlb_invalidation = 1, \ |
| 142 | .has_usm = 1, \ | 142 | .has_usm = 1, \ |
| 143 | .has_64bit_timestamp = 1, \ | ||
| 143 | .va_bits = 48, \ | 144 | .va_bits = 48, \ |
| 144 | .vm_max_level = 4, \ | 145 | .vm_max_level = 4, \ |
| 145 | .hw_engine_mask = \ | 146 | .hw_engine_mask = \ |
| @@ -668,6 +669,7 @@ static int xe_info_init(struct xe_device *xe, · 522 unmodified lines | |||
| 668 | 669 | ||
| 669 | xe->info.has_range_tlb_invalidation = graphics_desc->has_range_tlb_invalidation; | 670 | xe->info.has_range_tlb_invalidation = graphics_desc->has_range_tlb_invalidation; |
| 670 | xe->info.has_usm = graphics_desc->has_usm; | 671 | xe->info.has_usm = graphics_desc->has_usm; |
| 672 | xe->info.has_64bit_timestamp = graphics_desc->has_64bit_timestamp; | ||
| 671 | 673 | ||
| 672 | for_each_remote_tile(tile, xe, id) { | 674 | for_each_remote_tile(tile, xe, id) { |
| 673 | int err; | 675 | int err; |
| @@ -21,6 +21,7 @@ struct xe_graphics_desc { · 20 unmodified lines | |||
| 21 | u8 has_indirect_ring_state:1; | 21 | u8 has_indirect_ring_state:1; |
| 22 | u8 has_range_tlb_invalidation:1; | 22 | u8 has_range_tlb_invalidation:1; |
| 23 | u8 has_usm:1; | 23 | u8 has_usm:1; |
| 24 | u8 has_64bit_timestamp:1; | ||
| 24 | }; | 25 | }; |
| 25 | 26 | ||
| 26 | struct xe_media_desc { | 27 | struct xe_media_desc { |
| @@ -2232,11 +2232,19 @@ static void op_commit(struct xe_vm *vm, · 2231 unmodified lines | |||
| 2232 | } | 2232 | } |
| 2233 | case DRM_GPUVA_OP_DRIVER: | 2233 | case DRM_GPUVA_OP_DRIVER: |
| 2234 | { | 2234 | { |
| 2235 | /* WRITE_ONCE pairs with READ_ONCE in xe_svm.c */ | ||
| 2236 | |||
| 2235 | if (op->subop == XE_VMA_SUBOP_MAP_RANGE) { | 2237 | if (op->subop == XE_VMA_SUBOP_MAP_RANGE) { |
| 2236 | op->map_range.range->tile_present |= BIT(tile->id); | 2238 | WRITE_ONCE(op->map_range.range->tile_present, |
| 2237 | op->map_range.range->tile_invalidated &= ~BIT(tile->id); | 2239 | op->map_range.range->tile_present | |
| 2240 | BIT(tile->id)); | ||
| 2241 | WRITE_ONCE(op->map_range.range->tile_invalidated, | ||
| 2242 | op->map_range.range->tile_invalidated & | ||
| 2243 | ~BIT(tile->id)); | ||
| 2238 | } else if (op->subop == XE_VMA_SUBOP_UNMAP_RANGE) { | 2244 | } else if (op->subop == XE_VMA_SUBOP_UNMAP_RANGE) { |
| 2239 | op->unmap_range.range->tile_present &= ~BIT(tile->id); | 2245 | WRITE_ONCE(op->unmap_range.range->tile_present, |
| 2246 | op->unmap_range.range->tile_present & | ||
| 2247 | ~BIT(tile->id)); | ||
| 2240 | } | 2248 | } |
| 2241 | break; | 2249 | break; |
| 2242 | } | 2250 | } |
| @@ -234,13 +234,10 @@ static u32 get_ppgtt_flag(struct xe_sched_job *job) · 233 unmodified lines | |||
| 234 | 234 | ||
| 235 | static int emit_copy_timestamp(struct xe_lrc *lrc, u32 *dw, int i) | 235 | static int emit_copy_timestamp(struct xe_lrc *lrc, u32 *dw, int i) |
| 236 | { | 236 | { |
| 237 | dw[i++] = MI_COPY_MEM_MEM | MI_COPY_MEM_MEM_SRC_GGTT | | 237 | dw[i++] = MI_STORE_REGISTER_MEM | MI_SRM_USE_GGTT | MI_SRM_ADD_CS_OFFSET; |
| 238 | MI_COPY_MEM_MEM_DST_GGTT; | 238 | dw[i++] = RING_CTX_TIMESTAMP(0).addr; |
| 239 | dw[i++] = xe_lrc_ctx_job_timestamp_ggtt_addr(lrc); | 239 | dw[i++] = xe_lrc_ctx_job_timestamp_ggtt_addr(lrc); |
| 240 | dw[i++] = 0; | 240 | dw[i++] = 0; |
| 241 | dw[i++] = xe_lrc_ctx_timestamp_ggtt_addr(lrc); | ||
| 242 | dw[i++] = 0; | ||
| 243 | dw[i++] = MI_NOOP; | ||
| 244 | 241 | ||
| 245 | return i; | 242 | return i; |
| 246 | } | 243 | } |
| @@ -227,7 +227,7 @@ struct xe_shrinker *xe_shrinker_create(struct xe_device *xe) · 226 unmodified lines | |||
| 227 | if (!shrinker) | 227 | if (!shrinker) |
| 228 | return ERR_PTR(-ENOMEM); | 228 | return ERR_PTR(-ENOMEM); |
| 229 | 229 | ||
| 230 | shrinker->shrink = shrinker_alloc(0, "xe system shrinker"); | 230 | shrinker->shrink = shrinker_alloc(0, "drm-xe_gem:%s", xe->drm.unique); |
| 231 | if (!shrinker->shrink) { | 231 | if (!shrinker->shrink) { |
| 232 | kfree(shrinker); | 232 | kfree(shrinker); |
| 233 | return ERR_PTR(-ENOMEM); | 233 | return ERR_PTR(-ENOMEM); |
| @@ -15,8 +15,17 @@ · 14 unmodified lines | |||
| 15 | 15 | ||
| 16 | static bool xe_svm_range_in_vram(struct xe_svm_range *range) | 16 | static bool xe_svm_range_in_vram(struct xe_svm_range *range) |
| 17 | { | 17 | { |
| 18 | /* Not reliable without notifier lock */ | 18 | /* |
| 19 | return range->base.flags.has_devmem_pages; | 19 | * Advisory only check whether the range is currently backed by VRAM |
| 20 | * memory. | ||
| 21 | */ | ||
| 22 | |||
| 23 | struct drm_gpusvm_range_flags flags = { | ||
| 24 | /* Pairs with WRITE_ONCE in drm_gpusvm.c */ | ||
| 25 | .__flags = READ_ONCE(range->base.flags.__flags), | ||
| 26 | }; | ||
| 27 | |||
| 28 | return flags.has_devmem_pages; | ||
| 20 | } | 29 | } |
| 21 | 30 | ||
| 22 | static bool xe_svm_range_has_vram_binding(struct xe_svm_range *range) | 31 | static bool xe_svm_range_has_vram_binding(struct xe_svm_range *range) |
| @@ -645,9 +654,16 @@ void xe_svm_fini(struct xe_vm *vm) · 622 unmodified lines | |||
| 645 | } | 654 | } |
| 646 | 655 | ||
| 647 | static bool xe_svm_range_is_valid(struct xe_svm_range *range, | 656 | static bool xe_svm_range_is_valid(struct xe_svm_range *range, |
| 648 | struct xe_tile *tile) | 657 | struct xe_tile *tile, |
| 658 | bool devmem_only) | ||
| 649 | { | 659 | { |
| 650 | return (range->tile_present & ~range->tile_invalidated) & BIT(tile->id); | 660 | /* |
| 661 | * Advisory only check whether the range currently has a valid mapping, | ||
| 662 | * READ_ONCE pairs with WRITE_ONCE in xe_pt.c | ||
| 663 | */ | ||
| 664 | return ((READ_ONCE(range->tile_present) & | ||
| 665 | ~READ_ONCE(range->tile_invalidated)) & BIT(tile->id)) && | ||
| 666 | (!devmem_only || xe_svm_range_in_vram(range)); | ||
| 651 | } | 667 | } |
| 652 | 668 | ||
| 653 | static struct xe_vram_region *tile_to_vr(struct xe_tile *tile) | 669 | static struct xe_vram_region *tile_to_vr(struct xe_tile *tile) |
| @@ -712,6 +728,36 @@ unlock: · 58 unmodified lines | |||
| 712 | return err; | 728 | return err; |
| 713 | } | 729 | } |
| 714 | 730 | ||
| 731 | static bool supports_4K_migration(struct xe_device *xe) | ||
| 732 | { | ||
| 733 | if (xe->info.vram_flags & XE_VRAM_FLAGS_NEED64K) | ||
| 734 | return false; | ||
| 735 | |||
| 736 | return true; | ||
| 737 | } | ||
| 738 | |||
| 739 | static bool xe_svm_range_needs_migrate_to_vram(struct xe_svm_range *range, | ||
| 740 | struct xe_vma *vma) | ||
| 741 | { | ||
| 742 | struct xe_vm *vm = range_to_vm(&range->base); | ||
| 743 | u64 range_size = xe_svm_range_size(range); | ||
| 744 | |||
| 745 | if (!range->base.flags.migrate_devmem) | ||
| 746 | return false; | ||
| 747 | |||
| 748 | if (xe_svm_range_in_vram(range)) { | ||
| 749 | drm_dbg(&vm->xe->drm, "Range is already in VRAM\n"); | ||
| 750 | return false; | ||
| 751 | } | ||
| 752 | |||
| 753 | if (range_size <= SZ_64K && !supports_4K_migration(vm->xe)) { | ||
| 754 | drm_dbg(&vm->xe->drm, "Platform doesn't support SZ_4K range migration\n"); | ||
| 755 | return false; | ||
| 756 | } | ||
| 757 | |||
| 758 | return true; | ||
| 759 | } | ||
| 760 | |||
| 715 | /** | 761 | /** |
| 716 | * xe_svm_handle_pagefault() - SVM handle page fault | 762 | * xe_svm_handle_pagefault() - SVM handle page fault |
| 717 | * @vm: The VM. | 763 | * @vm: The VM. |
| @@ -735,11 +781,16 @@ int xe_svm_handle_pagefault(struct xe_vm *vm, struct xe_vma *vma, · 17 unmodified lines | |||
| 735 | IS_ENABLED(CONFIG_DRM_XE_DEVMEM_MIRROR), | 781 | IS_ENABLED(CONFIG_DRM_XE_DEVMEM_MIRROR), |
| 736 | .check_pages_threshold = IS_DGFX(vm->xe) && | 782 | .check_pages_threshold = IS_DGFX(vm->xe) && |
| 737 | IS_ENABLED(CONFIG_DRM_XE_DEVMEM_MIRROR) ? SZ_64K : 0, | 783 | IS_ENABLED(CONFIG_DRM_XE_DEVMEM_MIRROR) ? SZ_64K : 0, |
| 784 | .devmem_only = atomic && IS_DGFX(vm->xe) && | ||
| 785 | IS_ENABLED(CONFIG_DRM_XE_DEVMEM_MIRROR), | ||
| 786 | .timeslice_ms = atomic && IS_DGFX(vm->xe) && | ||
| 787 | IS_ENABLED(CONFIG_DRM_XE_DEVMEM_MIRROR) ? 5 : 0, | ||
| 738 | }; | 788 | }; |
| 739 | struct xe_svm_range *range; | 789 | struct xe_svm_range *range; |
| 740 | struct drm_gpusvm_range *r; | 790 | struct drm_gpusvm_range *r; |
| 741 | struct drm_exec exec; | 791 | struct drm_exec exec; |
| 742 | struct dma_fence *fence; | 792 | struct dma_fence *fence; |
| 793 | int migrate_try_count = ctx.devmem_only ? 3 : 1; | ||
| 743 | ktime_t end = 0; | 794 | ktime_t end = 0; |
| 744 | int err; | 795 | int err; |
| 745 | 796 | ||
| @@ -758,24 +809,31 @@ retry: · 12 unmodified lines | |||
| 758 | if (IS_ERR(r)) | 809 | if (IS_ERR(r)) |
| 759 | return PTR_ERR(r); | 810 | return PTR_ERR(r); |
| 760 | 811 | ||
| 812 | if (ctx.devmem_only && !r->flags.migrate_devmem) | ||
| 813 | return -EACCES; | ||
| 814 | |||
| 761 | range = to_xe_range(r); | 815 | range = to_xe_range(r); |
| 762 | if (xe_svm_range_is_valid(range, tile)) | 816 | if (xe_svm_range_is_valid(range, tile, ctx.devmem_only)) |
| 763 | return 0; | 817 | return 0; |
| 764 | 818 | ||
| 765 | range_debug(range, "PAGE FAULT"); | 819 | range_debug(range, "PAGE FAULT"); |
| 766 | 820 | ||
| 767 | /* XXX: Add migration policy, for now migrate range once */ | 821 | if (--migrate_try_count >= 0 && |
| 768 | if (!range->skip_migrate && range->base.flags.migrate_devmem && | 822 | xe_svm_range_needs_migrate_to_vram(range, vma)) { |
| 769 | xe_svm_range_size(range) >= SZ_64K) { | ||
| 770 | range->skip_migrate = true; | ||
| 771 | |||
| 772 | err = xe_svm_alloc_vram(vm, tile, range, &ctx); | 823 | err = xe_svm_alloc_vram(vm, tile, range, &ctx); |
| 824 | ctx.timeslice_ms <<= 1; /* Double timeslice if we have to retry */ | ||
| 773 | if (err) { | 825 | if (err) { |
| 774 | drm_dbg(&vm->xe->drm, | 826 | if (migrate_try_count || !ctx.devmem_only) { |
| 775 | "VRAM allocation failed, falling back to " | 827 | drm_dbg(&vm->xe->drm, |
| 776 | "retrying fault, asid=%u, errno=%pe\n", | 828 | "VRAM allocation failed, falling back to retrying fault, asid=%u, errno=%pe\n", |
| 777 | vm->usm.asid, ERR_PTR(err)); | 829 | vm->usm.asid, ERR_PTR(err)); |
| 778 | goto retry; | 830 | goto retry; |
| 831 | } else { | ||
| 832 | drm_err(&vm->xe->drm, | ||
| 833 | "VRAM allocation failed, retry count exceeded, asid=%u, errno=%pe\n", | ||
| 834 | vm->usm.asid, ERR_PTR(err)); | ||
| 835 | return err; | ||
| 836 | } | ||
| 779 | } | 837 | } |
| 780 | } | 838 | } |
| 781 | 839 | ||
| @@ -783,15 +841,23 @@ retry: · 1 unmodified line | |||
| 783 | err = drm_gpusvm_range_get_pages(&vm->svm.gpusvm, r, &ctx); | 841 | err = drm_gpusvm_range_get_pages(&vm->svm.gpusvm, r, &ctx); |
| 784 | /* Corner where CPU mappings have changed */ | 842 | /* Corner where CPU mappings have changed */ |
| 785 | if (err == -EOPNOTSUPP || err == -EFAULT || err == -EPERM) { | 843 | if (err == -EOPNOTSUPP || err == -EFAULT || err == -EPERM) { |
| 786 | if (err == -EOPNOTSUPP) { | 844 | ctx.timeslice_ms <<= 1; /* Double timeslice if we have to retry */ |
| 787 | range_debug(range, "PAGE FAULT - EVICT PAGES"); | 845 | if (migrate_try_count > 0 || !ctx.devmem_only) { |
| 788 | drm_gpusvm_range_evict(&vm->svm.gpusvm, &range->base); | 846 | if (err == -EOPNOTSUPP) { |
| 847 | range_debug(range, "PAGE FAULT - EVICT PAGES"); | ||
| 848 | drm_gpusvm_range_evict(&vm->svm.gpusvm, | ||
| 849 | &range->base); | ||
| 850 | } | ||
| 851 | drm_dbg(&vm->xe->drm, | ||
| 852 | "Get pages failed, falling back to retrying, asid=%u, gpusvm=%p, errno=%pe\n", | ||
| 853 | vm->usm.asid, &vm->svm.gpusvm, ERR_PTR(err)); | ||
| 854 | range_debug(range, "PAGE FAULT - RETRY PAGES"); | ||
| 855 | goto retry; | ||
| 856 | } else { | ||
| 857 | drm_err(&vm->xe->drm, | ||
| 858 | "Get pages failed, retry count exceeded, asid=%u, gpusvm=%p, errno=%pe\n", | ||
| 859 | vm->usm.asid, &vm->svm.gpusvm, ERR_PTR(err)); | ||
| 789 | } | 860 | } |
| 790 | drm_dbg(&vm->xe->drm, | ||
| 791 | "Get pages failed, falling back to retrying, asid=%u, gpusvm=%p, errno=%pe\n", | ||
| 792 | vm->usm.asid, &vm->svm.gpusvm, ERR_PTR(err)); | ||
| 793 | range_debug(range, "PAGE FAULT - RETRY PAGES"); | ||
| 794 | goto retry; | ||
| 795 | } | 861 | } |
| 796 | if (err) { | 862 | if (err) { |
| 797 | range_debug(range, "PAGE FAULT - FAIL PAGE COLLECT"); | 863 | range_debug(range, "PAGE FAULT - FAIL PAGE COLLECT"); |
| @@ -815,6 +881,7 @@ retry_bind: · 17 unmodified lines | |||
| 815 | drm_exec_fini(&exec); | 881 | drm_exec_fini(&exec); |
| 816 | err = PTR_ERR(fence); | 882 | err = PTR_ERR(fence); |
| 817 | if (err == -EAGAIN) { | 883 | if (err == -EAGAIN) { |
| 884 | ctx.timeslice_ms <<= 1; /* Double timeslice if we have to retry */ | ||
| 818 | range_debug(range, "PAGE FAULT - RETRY BIND"); | 885 | range_debug(range, "PAGE FAULT - RETRY BIND"); |
| 819 | goto retry; | 886 | goto retry; |
| 820 | } | 887 | } |
| @@ -825,9 +892,6 @@ retry_bind: · 4 unmodified lines | |||
| 825 | } | 892 | } |
| 826 | drm_exec_fini(&exec); | 893 | drm_exec_fini(&exec); |
| 827 | 894 | ||
| 828 | if (xe_modparam.always_migrate_to_vram) | ||
| 829 | range->skip_migrate = false; | ||
| 830 | |||
| 831 | dma_fence_wait(fence, false); | 895 | dma_fence_wait(fence, false); |
| 832 | dma_fence_put(fence); | 896 | dma_fence_put(fence); |
| 833 | 897 | ||
| @@ -36,11 +36,6 @@ struct xe_svm_range { · 35 unmodified lines | |||
| 36 | * range. Protected by GPU SVM notifier lock. | 36 | * range. Protected by GPU SVM notifier lock. |
| 37 | */ | 37 | */ |
| 38 | u8 tile_invalidated; | 38 | u8 tile_invalidated; |
| 39 | /** | ||
| 40 | * @skip_migrate: Skip migration to VRAM, protected by GPU fault handler | ||
| 41 | * locking. | ||
| 42 | */ | ||
| 43 | u8 skip_migrate :1; | ||
| 44 | }; | 39 | }; |
| 45 | 40 | ||
| 46 | #if IS_ENABLED(CONFIG_DRM_GPUSVM) | 41 | #if IS_ENABLED(CONFIG_DRM_GPUSVM) |
| @@ -19,12 +19,12 @@ · 18 unmodified lines | |||
| 19 | #define __dev_name_lrc(lrc) dev_name(gt_to_xe((lrc)->fence_ctx.gt)->drm.dev) | 19 | #define __dev_name_lrc(lrc) dev_name(gt_to_xe((lrc)->fence_ctx.gt)->drm.dev) |
| 20 | 20 | ||
| 21 | TRACE_EVENT(xe_lrc_update_timestamp, | 21 | TRACE_EVENT(xe_lrc_update_timestamp, |
| 22 | TP_PROTO(struct xe_lrc *lrc, uint32_t old), | 22 | TP_PROTO(struct xe_lrc *lrc, uint64_t old), |
| 23 | TP_ARGS(lrc, old), | 23 | TP_ARGS(lrc, old), |
| 24 | TP_STRUCT__entry( | 24 | TP_STRUCT__entry( |
| 25 | __field(struct xe_lrc *, lrc) | 25 | __field(struct xe_lrc *, lrc) |
| 26 | __field(u32, old) | 26 | __field(u64, old) |
| 27 | __field(u32, new) | 27 | __field(u64, new) |
| 28 | __string(name, lrc->fence_ctx.name) | 28 | __string(name, lrc->fence_ctx.name) |
| 29 | __string(device_id, __dev_name_lrc(lrc)) | 29 | __string(device_id, __dev_name_lrc(lrc)) |
| 30 | ), | 30 | ), |
| @@ -36,7 +36,7 @@ TRACE_EVENT(xe_lrc_update_timestamp, · 5 unmodified lines | |||
| 36 | __assign_str(name); | 36 | __assign_str(name); |
| 37 | __assign_str(device_id); | 37 | __assign_str(device_id); |
| 38 | ), | 38 | ), |
| 39 | TP_printk("lrc=:%p lrc->name=%s old=%u new=%u device_id:%s", | 39 | TP_printk("lrc=:%p lrc->name=%s old=%llu new=%llu device_id:%s", |
| 40 | __entry->lrc, __get_str(name), | 40 | __entry->lrc, __get_str(name), |
| 41 | __entry->old, __entry->new, | 41 | __entry->old, __entry->new, |
| 42 | __get_str(device_id)) | 42 | __get_str(device_id)) |
| @@ -815,6 +815,10 @@ static const struct xe_rtp_entry_sr lrc_was[] = { · 814 unmodified lines | |||
| 815 | XE_RTP_RULES(GRAPHICS_VERSION(2001), ENGINE_CLASS(RENDER)), | 815 | XE_RTP_RULES(GRAPHICS_VERSION(2001), ENGINE_CLASS(RENDER)), |
| 816 | XE_RTP_ACTIONS(SET(CHICKEN_RASTER_1, DIS_CLIP_NEGATIVE_BOUNDING_BOX)) | 816 | XE_RTP_ACTIONS(SET(CHICKEN_RASTER_1, DIS_CLIP_NEGATIVE_BOUNDING_BOX)) |
| 817 | }, | 817 | }, |
| 818 | { XE_RTP_NAME("22021007897"), | ||
| 819 | XE_RTP_RULES(GRAPHICS_VERSION(2001), ENGINE_CLASS(RENDER)), | ||
| 820 | XE_RTP_ACTIONS(SET(COMMON_SLICE_CHICKEN4, SBE_PUSH_CONSTANT_BEHIND_FIX_ENABLE)) | ||
| 821 | }, | ||
| 818 | 822 | ||
| 819 | /* Xe3_LPG */ | 823 | /* Xe3_LPG */ |
| 820 | { XE_RTP_NAME("14021490052"), | 824 | { XE_RTP_NAME("14021490052"), |
| @@ -83,6 +83,9 @@ static int amd_sfh_hid_client_deinit(struct amd_mp2_dev *privdata) · 82 unmodified lines | |||
| 83 | case ALS_IDX: | 83 | case ALS_IDX: |
| 84 | privdata->dev_en.is_als_present = false; | 84 | privdata->dev_en.is_als_present = false; |
| 85 | break; | 85 | break; |
| 86 | case SRA_IDX: | ||
| 87 | privdata->dev_en.is_sra_present = false; | ||
| 88 | break; | ||
| 86 | } | 89 | } |
| 87 | 90 | ||
| 88 | if (cl_data->sensor_sts[i] == SENSOR_ENABLED) { | 91 | if (cl_data->sensor_sts[i] == SENSOR_ENABLED) { |
| @@ -134,9 +137,6 @@ static int amd_sfh1_1_hid_client_init(struct amd_mp2_dev *privdata) · 45 unmodified lines | |||
| 134 | for (i = 0; i < cl_data->num_hid_devices; i++) { | 137 | for (i = 0; i < cl_data->num_hid_devices; i++) { |
| 135 | cl_data->sensor_sts[i] = SENSOR_DISABLED; | 138 | cl_data->sensor_sts[i] = SENSOR_DISABLED; |
| 136 | 139 | ||
| 137 | if (cl_data->num_hid_devices == 1 && cl_data->sensor_idx[0] == SRA_IDX) | ||
| 138 | break; | ||
| 139 | |||
| 140 | if (cl_data->sensor_idx[i] == SRA_IDX) { | 140 | if (cl_data->sensor_idx[i] == SRA_IDX) { |
| 141 | info.sensor_idx = cl_data->sensor_idx[i]; | 141 | info.sensor_idx = cl_data->sensor_idx[i]; |
| 142 | writel(0, privdata->mmio + amd_get_p2c_val(privdata, 0)); | 142 | writel(0, privdata->mmio + amd_get_p2c_val(privdata, 0)); |
| @@ -145,8 +145,10 @@ static int amd_sfh1_1_hid_client_init(struct amd_mp2_dev *privdata) · 2 unmodified lines | |||
| 145 | (privdata, cl_data->sensor_idx[i], ENABLE_SENSOR); | 145 | (privdata, cl_data->sensor_idx[i], ENABLE_SENSOR); |
| 146 | 146 | ||
| 147 | cl_data->sensor_sts[i] = (status == 0) ? SENSOR_ENABLED : SENSOR_DISABLED; | 147 | cl_data->sensor_sts[i] = (status == 0) ? SENSOR_ENABLED : SENSOR_DISABLED; |
| 148 | if (cl_data->sensor_sts[i] == SENSOR_ENABLED) | 148 | if (cl_data->sensor_sts[i] == SENSOR_ENABLED) { |
| 149 | cl_data->is_any_sensor_enabled = true; | ||
| 149 | privdata->dev_en.is_sra_present = true; | 150 | privdata->dev_en.is_sra_present = true; |
| 151 | } | ||
| 150 | continue; | 152 | continue; |
| 151 | } | 153 | } |
| 152 | 154 | ||
| @@ -238,6 +240,8 @@ static int amd_sfh1_1_hid_client_init(struct amd_mp2_dev *privdata) · 85 unmodified lines | |||
| 238 | cleanup: | 240 | cleanup: |
| 239 | amd_sfh_hid_client_deinit(privdata); | 241 | amd_sfh_hid_client_deinit(privdata); |
| 240 | for (i = 0; i < cl_data->num_hid_devices; i++) { | 242 | for (i = 0; i < cl_data->num_hid_devices; i++) { |
| 243 | if (cl_data->sensor_idx[i] == SRA_IDX) | ||
| 244 | continue; | ||
| 241 | devm_kfree(dev, cl_data->feature_report[i]); | 245 | devm_kfree(dev, cl_data->feature_report[i]); |
| 242 | devm_kfree(dev, in_data->input_report[i]); | 246 | devm_kfree(dev, in_data->input_report[i]); |
| 243 | devm_kfree(dev, cl_data->report_descr[i]); | 247 | devm_kfree(dev, cl_data->report_descr[i]); |
| @@ -38,6 +38,9 @@ dispatch_hid_bpf_device_event(struct hid_device *hdev, enum hid_report_type type · 37 unmodified lines | |||
| 38 | struct hid_bpf_ops *e; | 38 | struct hid_bpf_ops *e; |
| 39 | int ret; | 39 | int ret; |
| 40 | 40 | ||
| 41 | if (unlikely(hdev->bpf.destroyed)) | ||
| 42 | return ERR_PTR(-ENODEV); | ||
| 43 | |||
| 41 | if (type >= HID_REPORT_TYPES) | 44 | if (type >= HID_REPORT_TYPES) |
| 42 | return ERR_PTR(-EINVAL); | 45 | return ERR_PTR(-EINVAL); |
| 43 | 46 | ||
| @@ -93,6 +96,9 @@ int dispatch_hid_bpf_raw_requests(struct hid_device *hdev, · 49 unmodified lines | |||
| 93 | struct hid_bpf_ops *e; | 96 | struct hid_bpf_ops *e; |
| 94 | int ret, idx; | 97 | int ret, idx; |
| 95 | 98 | ||
| 99 | if (unlikely(hdev->bpf.destroyed)) | ||
| 100 | return -ENODEV; | ||
| 101 | |||
| 96 | if (rtype >= HID_REPORT_TYPES) | 102 | if (rtype >= HID_REPORT_TYPES) |
| 97 | return -EINVAL; | 103 | return -EINVAL; |
| 98 | 104 | ||
| @@ -130,6 +136,9 @@ int dispatch_hid_bpf_output_report(struct hid_device *hdev, · 31 unmodified lines | |||
| 130 | struct hid_bpf_ops *e; | 136 | struct hid_bpf_ops *e; |
| 131 | int ret, idx; | 137 | int ret, idx; |
| 132 | 138 | ||
| 139 | if (unlikely(hdev->bpf.destroyed)) | ||
| 140 | return -ENODEV; | ||
| 141 | |||
| 133 | idx = srcu_read_lock(&hdev->bpf.srcu); | 142 | idx = srcu_read_lock(&hdev->bpf.srcu); |
| 134 | list_for_each_entry_srcu(e, &hdev->bpf.prog_list, list, | 143 | list_for_each_entry_srcu(e, &hdev->bpf.prog_list, list, |
| 135 | srcu_read_lock_held(&hdev->bpf.srcu)) { | 144 | srcu_read_lock_held(&hdev->bpf.srcu)) { |
| @@ -157,6 +157,7 @@ static const __u8 fixed_rdesc_vendor[] = { · 156 unmodified lines | |||
| 157 | ReportCount(5) // padding | 157 | ReportCount(5) // padding |
| 158 | Input(Const) | 158 | Input(Const) |
| 159 | // Byte 4 in report - just exists so we get to be a tablet pad | 159 | // Byte 4 in report - just exists so we get to be a tablet pad |
| 160 | UsagePage_Digitizers | ||
| 160 | Usage_Dig_BarrelSwitch // BTN_STYLUS | 161 | Usage_Dig_BarrelSwitch // BTN_STYLUS |
| 161 | ReportCount(1) | 162 | ReportCount(1) |
| 162 | ReportSize(1) | 163 | ReportSize(1) |
| @@ -41,6 +41,10 @@ · 40 unmodified lines | |||
| 41 | #define USB_VENDOR_ID_ACTIONSTAR 0x2101 | 41 | #define USB_VENDOR_ID_ACTIONSTAR 0x2101 |
| 42 | #define USB_DEVICE_ID_ACTIONSTAR_1011 0x1011 | 42 | #define USB_DEVICE_ID_ACTIONSTAR_1011 0x1011 |
| 43 | 43 | ||
| 44 | #define USB_VENDOR_ID_ADATA_XPG 0x125f | ||
| 45 | #define USB_VENDOR_ID_ADATA_XPG_WL_GAMING_MOUSE 0x7505 | ||
| 46 | #define USB_VENDOR_ID_ADATA_XPG_WL_GAMING_MOUSE_DONGLE 0x7506 | ||
| 47 | |||
| 44 | #define USB_VENDOR_ID_ADS_TECH 0x06e1 | 48 | #define USB_VENDOR_ID_ADS_TECH 0x06e1 |
| 45 | #define USB_DEVICE_ID_ADS_TECH_RADIO_SI470X 0xa155 | 49 | #define USB_DEVICE_ID_ADS_TECH_RADIO_SI470X 0xa155 |
| 46 | 50 | ||
| @@ -27,6 +27,8 @@ · 26 unmodified lines | |||
| 27 | static const struct hid_device_id hid_quirks[] = { | 27 | static const struct hid_device_id hid_quirks[] = { |
| 28 | { HID_USB_DEVICE(USB_VENDOR_ID_AASHIMA, USB_DEVICE_ID_AASHIMA_GAMEPAD), HID_QUIRK_BADPAD }, | 28 | { HID_USB_DEVICE(USB_VENDOR_ID_AASHIMA, USB_DEVICE_ID_AASHIMA_GAMEPAD), HID_QUIRK_BADPAD }, |
| 29 | { HID_USB_DEVICE(USB_VENDOR_ID_AASHIMA, USB_DEVICE_ID_AASHIMA_PREDATOR), HID_QUIRK_BADPAD }, | 29 | { HID_USB_DEVICE(USB_VENDOR_ID_AASHIMA, USB_DEVICE_ID_AASHIMA_PREDATOR), HID_QUIRK_BADPAD }, |
| 30 | { HID_USB_DEVICE(USB_VENDOR_ID_ADATA_XPG, USB_VENDOR_ID_ADATA_XPG_WL_GAMING_MOUSE), HID_QUIRK_ALWAYS_POLL }, | ||
| 31 | { HID_USB_DEVICE(USB_VENDOR_ID_ADATA_XPG, USB_VENDOR_ID_ADATA_XPG_WL_GAMING_MOUSE_DONGLE), HID_QUIRK_ALWAYS_POLL }, | ||
| 30 | { HID_USB_DEVICE(USB_VENDOR_ID_AFATECH, USB_DEVICE_ID_AFATECH_AF9016), HID_QUIRK_FULLSPEED_INTERVAL }, | 32 | { HID_USB_DEVICE(USB_VENDOR_ID_AFATECH, USB_DEVICE_ID_AFATECH_AF9016), HID_QUIRK_FULLSPEED_INTERVAL }, |
| 31 | { HID_USB_DEVICE(USB_VENDOR_ID_AIREN, USB_DEVICE_ID_AIREN_SLIMPLUS), HID_QUIRK_NOGET }, | 33 | { HID_USB_DEVICE(USB_VENDOR_ID_AIREN, USB_DEVICE_ID_AIREN_SLIMPLUS), HID_QUIRK_NOGET }, |
| 32 | { HID_USB_DEVICE(USB_VENDOR_ID_AKAI_09E8, USB_DEVICE_ID_AKAI_09E8_MIDIMIX), HID_QUIRK_NO_INIT_REPORTS }, | 34 | { HID_USB_DEVICE(USB_VENDOR_ID_AKAI_09E8, USB_DEVICE_ID_AKAI_09E8_MIDIMIX), HID_QUIRK_NO_INIT_REPORTS }, |
| @@ -1150,11 +1150,9 @@ static void steam_client_ll_close(struct hid_device *hdev) · 1149 unmodified lines | |||
| 1150 | struct steam_device *steam = hdev->driver_data; | 1150 | struct steam_device *steam = hdev->driver_data; |
| 1151 | 1151 | ||
| 1152 | unsigned long flags; | 1152 | unsigned long flags; |
| 1153 | bool connected; | ||
| 1154 | 1153 | ||
| 1155 | spin_lock_irqsave(&steam->lock, flags); | 1154 | spin_lock_irqsave(&steam->lock, flags); |
| 1156 | steam->client_opened--; | 1155 | steam->client_opened--; |
| 1157 | connected = steam->connected && !steam->client_opened; | ||
| 1158 | spin_unlock_irqrestore(&steam->lock, flags); | 1156 | spin_unlock_irqrestore(&steam->lock, flags); |
| 1159 | 1157 | ||
| 1160 | schedule_work(&steam->unregister_work); | 1158 | schedule_work(&steam->unregister_work); |
| @@ -174,6 +174,7 @@ static void thrustmaster_interrupts(struct hid_device *hdev) · 173 unmodified lines | |||
| 174 | u8 ep_addr[2] = {b_ep, 0}; | 174 | u8 ep_addr[2] = {b_ep, 0}; |
| 175 | 175 | ||
| 176 | if (!usb_check_int_endpoints(usbif, ep_addr)) { | 176 | if (!usb_check_int_endpoints(usbif, ep_addr)) { |
| 177 | kfree(send_buf); | ||
| 177 | hid_err(hdev, "Unexpected non-int endpoint\n"); | 178 | hid_err(hdev, "Unexpected non-int endpoint\n"); |
| 178 | return; | 179 | return; |
| 179 | } | 180 | } |
| @@ -142,11 +142,12 @@ static int uclogic_input_configured(struct hid_device *hdev, · 141 unmodified lines | |||
| 142 | suffix = "System Control"; | 142 | suffix = "System Control"; |
| 143 | break; | 143 | break; |
| 144 | } | 144 | } |
| 145 | } | 145 | } else { |
| 146 | |||
| 147 | if (suffix) | ||
| 148 | hi->input->name = devm_kasprintf(&hdev->dev, GFP_KERNEL, | 146 | hi->input->name = devm_kasprintf(&hdev->dev, GFP_KERNEL, |
| 149 | "%s %s", hdev->name, suffix); | 147 | "%s %s", hdev->name, suffix); |
| 148 | if (!hi->input->name) | ||
| 149 | return -ENOMEM; | ||
| 150 | } | ||
| 150 | 151 | ||
| 151 | return 0; | 152 | return 0; |
| 152 | } | 153 | } |
| @@ -70,10 +70,16 @@ static void wacom_wac_queue_flush(struct hid_device *hdev, · 69 unmodified lines | |||
| 70 | { | 70 | { |
| 71 | while (!kfifo_is_empty(fifo)) { | 71 | while (!kfifo_is_empty(fifo)) { |
| 72 | int size = kfifo_peek_len(fifo); | 72 | int size = kfifo_peek_len(fifo); |
| 73 | u8 *buf = kzalloc(size, GFP_KERNEL); | 73 | u8 *buf; |
| 74 | unsigned int count; | 74 | unsigned int count; |
| 75 | int err; | 75 | int err; |
| 76 | 76 | ||
| 77 | buf = kzalloc(size, GFP_KERNEL); | ||
| 78 | if (!buf) { | ||
| 79 | kfifo_skip(fifo); | ||
| 80 | continue; | ||
| 81 | } | ||
| 82 | |||
| 77 | count = kfifo_out(fifo, buf, size); | 83 | count = kfifo_out(fifo, buf, size); |
| 78 | if (count != size) { | 84 | if (count != size) { |
| 79 | // Hard to say what is the "right" action in this | 85 | // Hard to say what is the "right" action in this |
| @@ -81,6 +87,7 @@ static void wacom_wac_queue_flush(struct hid_device *hdev, · 1 unmodified line | |||
| 81 | // to flush seems reasonable enough, however. | 87 | // to flush seems reasonable enough, however. |
| 82 | hid_warn(hdev, "%s: removed fifo entry with unexpected size\n", | 88 | hid_warn(hdev, "%s: removed fifo entry with unexpected size\n", |
| 83 | __func__); | 89 | __func__); |
| 90 | kfree(buf); | ||
| 84 | continue; | 91 | continue; |
| 85 | } | 92 | } |
| 86 | err = hid_report_raw_event(hdev, HID_INPUT_REPORT, buf, size, false); | 93 | err = hid_report_raw_event(hdev, HID_INPUT_REPORT, buf, size, false); |
| @@ -2361,6 +2368,8 @@ static int wacom_parse_and_register(struct wacom *wacom, bool wireless) · 2274 unmodified lines | |||
| 2361 | unsigned int connect_mask = HID_CONNECT_HIDRAW; | 2368 | unsigned int connect_mask = HID_CONNECT_HIDRAW; |
| 2362 | 2369 | ||
| 2363 | features->pktlen = wacom_compute_pktlen(hdev); | 2370 | features->pktlen = wacom_compute_pktlen(hdev); |
| 2371 | if (!features->pktlen) | ||
| 2372 | return -ENODEV; | ||
| 2364 | 2373 | ||
| 2365 | if (!devres_open_group(&hdev->dev, wacom, GFP_KERNEL)) | 2374 | if (!devres_open_group(&hdev->dev, wacom, GFP_KERNEL)) |
| 2366 | return -ENOMEM; | 2375 | return -ENOMEM; |
| @@ -1077,68 +1077,10 @@ int vmbus_sendpacket(struct vmbus_channel *channel, void *buffer, · 1076 unmodified lines | |||
| 1077 | EXPORT_SYMBOL(vmbus_sendpacket); | 1077 | EXPORT_SYMBOL(vmbus_sendpacket); |
| 1078 | 1078 | ||
| 1079 | /* | 1079 | /* |
| 1080 | * vmbus_sendpacket_pagebuffer - Send a range of single-page buffer | 1080 | * vmbus_sendpacket_mpb_desc - Send one or more multi-page buffer packets |
| 1081 | * packets using a GPADL Direct packet type. This interface allows you | ||
| 1082 | * to control notifying the host. This will be useful for sending | ||
| 1083 | * batched data. Also the sender can control the send flags | ||
| 1084 | * explicitly. | ||
| 1085 | */ | ||
| 1086 | int vmbus_sendpacket_pagebuffer(struct vmbus_channel *channel, | ||
| 1087 | struct hv_page_buffer pagebuffers[], | ||
| 1088 | u32 pagecount, void *buffer, u32 bufferlen, | ||
| 1089 | u64 requestid) | ||
| 1090 | { | ||
| 1091 | int i; | ||
| 1092 | struct vmbus_channel_packet_page_buffer desc; | ||
| 1093 | u32 descsize; | ||
| 1094 | u32 packetlen; | ||
| 1095 | u32 packetlen_aligned; | ||
| 1096 | struct kvec bufferlist[3]; | ||
| 1097 | u64 aligned_data = 0; | ||
| 1098 | |||
| 1099 | if (pagecount > MAX_PAGE_BUFFER_COUNT) | ||
| 1100 | return -EINVAL; | ||
| 1101 | |||
| 1102 | /* | ||
| 1103 | * Adjust the size down since vmbus_channel_packet_page_buffer is the | ||
| 1104 | * largest size we support | ||
| 1105 | */ | ||
| 1106 | descsize = sizeof(struct vmbus_channel_packet_page_buffer) - | ||
| 1107 | ((MAX_PAGE_BUFFER_COUNT - pagecount) * | ||
| 1108 | sizeof(struct hv_page_buffer)); | ||
| 1109 | packetlen = descsize + bufferlen; | ||
| 1110 | packetlen_aligned = ALIGN(packetlen, sizeof(u64)); | ||
| 1111 | |||
| 1112 | /* Setup the descriptor */ | ||
| 1113 | desc.type = VM_PKT_DATA_USING_GPA_DIRECT; | ||
| 1114 | desc.flags = VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED; | ||
| 1115 | desc.dataoffset8 = descsize >> 3; /* in 8-bytes granularity */ | ||
| 1116 | desc.length8 = (u16)(packetlen_aligned >> 3); | ||
| 1117 | desc.transactionid = VMBUS_RQST_ERROR; /* will be updated in hv_ringbuffer_write() */ | ||
| 1118 | desc.reserved = 0; | ||
| 1119 | desc.rangecount = pagecount; | ||
| 1120 | |||
| 1121 | for (i = 0; i < pagecount; i++) { | ||
| 1122 | desc.range[i].len = pagebuffers[i].len; | ||
| 1123 | desc.range[i].offset = pagebuffers[i].offset; | ||
| 1124 | desc.range[i].pfn = pagebuffers[i].pfn; | ||
| 1125 | } | ||
| 1126 | |||
| 1127 | bufferlist[0].iov_base = &desc; | ||
| 1128 | bufferlist[0].iov_len = descsize; | ||
| 1129 | bufferlist[1].iov_base = buffer; | ||
| 1130 | bufferlist[1].iov_len = bufferlen; | ||
| 1131 | bufferlist[2].iov_base = &aligned_data; | ||
| 1132 | bufferlist[2].iov_len = (packetlen_aligned - packetlen); | ||
| 1133 | |||
| 1134 | return hv_ringbuffer_write(channel, bufferlist, 3, requestid, NULL); | ||
| 1135 | } | ||
| 1136 | EXPORT_SYMBOL_GPL(vmbus_sendpacket_pagebuffer); | ||
| 1137 | |||
| 1138 | /* | ||
| 1139 | * vmbus_sendpacket_multipagebuffer - Send a multi-page buffer packet | ||
| 1140 | * using a GPADL Direct packet type. | 1081 | * using a GPADL Direct packet type. |
| 1141 | * The buffer includes the vmbus descriptor. | 1082 | * The desc argument must include space for the VMBus descriptor. The |
| 1083 | * rangecount field must already be set. | ||
| 1142 | */ | 1084 | */ |
| 1143 | int vmbus_sendpacket_mpb_desc(struct vmbus_channel *channel, | 1085 | int vmbus_sendpacket_mpb_desc(struct vmbus_channel *channel, |
| 1144 | struct vmbus_packet_mpb_array *desc, | 1086 | struct vmbus_packet_mpb_array *desc, |
| @@ -1160,7 +1102,6 @@ int vmbus_sendpacket_mpb_desc(struct vmbus_channel *channel, · 15 unmodified lines | |||
| 1160 | desc->length8 = (u16)(packetlen_aligned >> 3); | 1102 | desc->length8 = (u16)(packetlen_aligned >> 3); |
| 1161 | desc->transactionid = VMBUS_RQST_ERROR; /* will be updated in hv_ringbuffer_write() */ | 1103 | desc->transactionid = VMBUS_RQST_ERROR; /* will be updated in hv_ringbuffer_write() */ |
| 1162 | desc->reserved = 0; | 1104 | desc->reserved = 0; |
| 1163 | desc->rangecount = 1; | ||
| 1164 | 1105 | ||
| 1165 | bufferlist[0].iov_base = desc; | 1106 | bufferlist[0].iov_base = desc; |
| 1166 | bufferlist[0].iov_len = desc_size; | 1107 | bufferlist[0].iov_len = desc_size; |
| @@ -278,9 +278,11 @@ static int i2c_dw_pci_probe(struct pci_dev *pdev, · 277 unmodified lines | |||
| 278 | 278 | ||
| 279 | if ((dev->flags & MODEL_MASK) == MODEL_AMD_NAVI_GPU) { | 279 | if ((dev->flags & MODEL_MASK) == MODEL_AMD_NAVI_GPU) { |
| 280 | dev->slave = i2c_new_ccgx_ucsi(&dev->adapter, dev->irq, &dgpu_node); | 280 | dev->slave = i2c_new_ccgx_ucsi(&dev->adapter, dev->irq, &dgpu_node); |
| 281 | if (IS_ERR(dev->slave)) | 281 | if (IS_ERR(dev->slave)) { |
| 282 | i2c_del_adapter(&dev->adapter); | ||
| 282 | return dev_err_probe(device, PTR_ERR(dev->slave), | 283 | return dev_err_probe(device, PTR_ERR(dev->slave), |
| 283 | "register UCSI failed\n"); | 284 | "register UCSI failed\n"); |
| 285 | } | ||
| 284 | } | 286 | } |
| 285 | 287 | ||
| 286 | pm_runtime_set_autosuspend_delay(device, 1000); | 288 | pm_runtime_set_autosuspend_delay(device, 1000); |
| @@ -1352,6 +1352,9 @@ static void ib_device_notify_register(struct ib_device *device) · 1351 unmodified lines | |||
| 1352 | 1352 | ||
| 1353 | down_read(&devices_rwsem); | 1353 | down_read(&devices_rwsem); |
| 1354 | 1354 | ||
| 1355 | /* Mark for userspace that device is ready */ | ||
| 1356 | kobject_uevent(&device->dev.kobj, KOBJ_ADD); | ||
| 1357 | |||
| 1355 | ret = rdma_nl_notify_event(device, 0, RDMA_REGISTER_EVENT); | 1358 | ret = rdma_nl_notify_event(device, 0, RDMA_REGISTER_EVENT); |
| 1356 | if (ret) | 1359 | if (ret) |
| 1357 | goto out; | 1360 | goto out; |
| @@ -1468,10 +1471,9 @@ int ib_register_device(struct ib_device *device, const char *name, · 110 unmodified lines | |||
| 1468 | return ret; | 1471 | return ret; |
| 1469 | } | 1472 | } |
| 1470 | dev_set_uevent_suppress(&device->dev, false); | 1473 | dev_set_uevent_suppress(&device->dev, false); |
| 1471 | /* Mark for userspace that device is ready */ | ||
| 1472 | kobject_uevent(&device->dev.kobj, KOBJ_ADD); | ||
| 1473 | 1474 | ||
| 1474 | ib_device_notify_register(device); | 1475 | ib_device_notify_register(device); |
| 1476 | |||
| 1475 | ib_device_put(device); | 1477 | ib_device_put(device); |
| 1476 | 1478 | ||
| 1477 | return 0; | 1479 | return 0; |
| @@ -221,7 +221,7 @@ static int irdma_init_interrupts(struct irdma_pci_f *rf, struct ice_pf *pf) · 220 unmodified lines | |||
| 221 | break; | 221 | break; |
| 222 | 222 | ||
| 223 | if (i < IRDMA_MIN_MSIX) { | 223 | if (i < IRDMA_MIN_MSIX) { |
| 224 | for (; i > 0; i--) | 224 | while (--i >= 0) |
| 225 | ice_free_rdma_qvector(pf, &rf->msix_entries[i]); | 225 | ice_free_rdma_qvector(pf, &rf->msix_entries[i]); |
| 226 | 226 | ||
| 227 | kfree(rf->msix_entries); | 227 | kfree(rf->msix_entries); |
| @@ -255,6 +255,8 @@ static void irdma_remove(struct auxiliary_device *aux_dev) · 27 unmodified lines | |||
| 255 | ice_rdma_update_vsi_filter(pf, iwdev->vsi_num, false); | 255 | ice_rdma_update_vsi_filter(pf, iwdev->vsi_num, false); |
| 256 | irdma_deinit_interrupts(iwdev->rf, pf); | 256 | irdma_deinit_interrupts(iwdev->rf, pf); |
| 257 | 257 | ||
| 258 | kfree(iwdev->rf); | ||
| 259 | |||
| 258 | pr_debug("INIT: Gen2 PF[%d] device remove success\n", PCI_FUNC(pf->pdev->devfn)); | 260 | pr_debug("INIT: Gen2 PF[%d] device remove success\n", PCI_FUNC(pf->pdev->devfn)); |
| 259 | } | 261 | } |
| 260 | 262 | ||
| @@ -4871,5 +4871,4 @@ void irdma_ib_dealloc_device(struct ib_device *ibdev) · 4870 unmodified lines | |||
| 4871 | 4871 | ||
| 4872 | irdma_rt_deinit_hw(iwdev); | 4872 | irdma_rt_deinit_hw(iwdev); |
| 4873 | irdma_ctrl_deinit_hw(iwdev->rf); | 4873 | irdma_ctrl_deinit_hw(iwdev->rf); |
| 4874 | kfree(iwdev->rf); | ||
| 4875 | } | 4874 | } |
| @@ -56,11 +56,8 @@ int rxe_cq_from_init(struct rxe_dev *rxe, struct rxe_cq *cq, int cqe, · 55 unmodified lines | |||
| 56 | 56 | ||
| 57 | err = do_mmap_info(rxe, uresp ? &uresp->mi : NULL, udata, | 57 | err = do_mmap_info(rxe, uresp ? &uresp->mi : NULL, udata, |
| 58 | cq->queue->buf, cq->queue->buf_size, &cq->queue->ip); | 58 | cq->queue->buf, cq->queue->buf_size, &cq->queue->ip); |
| 59 | if (err) { | 59 | if (err) |
| 60 | vfree(cq->queue->buf); | ||
| 61 | kfree(cq->queue); | ||
| 62 | return err; | 60 | return err; |
| 63 | } | ||
| 64 | 61 | ||
| 65 | cq->is_user = uresp; | 62 | cq->is_user = uresp; |
| 66 | 63 | ||
| @@ -252,7 +252,7 @@ static void __init gicv2m_teardown(void) · 251 unmodified lines | |||
| 252 | static struct msi_parent_ops gicv2m_msi_parent_ops = { | 252 | static struct msi_parent_ops gicv2m_msi_parent_ops = { |
| 253 | .supported_flags = GICV2M_MSI_FLAGS_SUPPORTED, | 253 | .supported_flags = GICV2M_MSI_FLAGS_SUPPORTED, |
| 254 | .required_flags = GICV2M_MSI_FLAGS_REQUIRED, | 254 | .required_flags = GICV2M_MSI_FLAGS_REQUIRED, |
| 255 | .chip_flags = MSI_CHIP_FLAG_SET_EOI | MSI_CHIP_FLAG_SET_ACK, | 255 | .chip_flags = MSI_CHIP_FLAG_SET_EOI, |
| 256 | .bus_select_token = DOMAIN_BUS_NEXUS, | 256 | .bus_select_token = DOMAIN_BUS_NEXUS, |
| 257 | .bus_select_mask = MATCH_PCI_MSI | MATCH_PLATFORM_MSI, | 257 | .bus_select_mask = MATCH_PCI_MSI | MATCH_PLATFORM_MSI, |
| 258 | .prefix = "GICv2m-", | 258 | .prefix = "GICv2m-", |
| @@ -203,7 +203,7 @@ static bool its_init_dev_msi_info(struct device *dev, struct irq_domain *domain, · 202 unmodified lines | |||
| 203 | const struct msi_parent_ops gic_v3_its_msi_parent_ops = { | 203 | const struct msi_parent_ops gic_v3_its_msi_parent_ops = { |
| 204 | .supported_flags = ITS_MSI_FLAGS_SUPPORTED, | 204 | .supported_flags = ITS_MSI_FLAGS_SUPPORTED, |
| 205 | .required_flags = ITS_MSI_FLAGS_REQUIRED, | 205 | .required_flags = ITS_MSI_FLAGS_REQUIRED, |
| 206 | .chip_flags = MSI_CHIP_FLAG_SET_EOI | MSI_CHIP_FLAG_SET_ACK, | 206 | .chip_flags = MSI_CHIP_FLAG_SET_EOI, |
| 207 | .bus_select_token = DOMAIN_BUS_NEXUS, | 207 | .bus_select_token = DOMAIN_BUS_NEXUS, |
| 208 | .bus_select_mask = MATCH_PCI_MSI | MATCH_PLATFORM_MSI, | 208 | .bus_select_mask = MATCH_PCI_MSI | MATCH_PLATFORM_MSI, |
| 209 | .prefix = "ITS-", | 209 | .prefix = "ITS-", |
| @@ -197,7 +197,7 @@ static bool mbi_init_dev_msi_info(struct device *dev, struct irq_domain *domain, · 196 unmodified lines | |||
| 197 | static const struct msi_parent_ops gic_v3_mbi_msi_parent_ops = { | 197 | static const struct msi_parent_ops gic_v3_mbi_msi_parent_ops = { |
| 198 | .supported_flags = MBI_MSI_FLAGS_SUPPORTED, | 198 | .supported_flags = MBI_MSI_FLAGS_SUPPORTED, |
| 199 | .required_flags = MBI_MSI_FLAGS_REQUIRED, | 199 | .required_flags = MBI_MSI_FLAGS_REQUIRED, |
| 200 | .chip_flags = MSI_CHIP_FLAG_SET_EOI | MSI_CHIP_FLAG_SET_ACK, | 200 | .chip_flags = MSI_CHIP_FLAG_SET_EOI, |
| 201 | .bus_select_token = DOMAIN_BUS_NEXUS, | 201 | .bus_select_token = DOMAIN_BUS_NEXUS, |
| 202 | .bus_select_mask = MATCH_PCI_MSI | MATCH_PLATFORM_MSI, | 202 | .bus_select_mask = MATCH_PCI_MSI | MATCH_PLATFORM_MSI, |
| 203 | .prefix = "MBI-", | 203 | .prefix = "MBI-", |
| @@ -161,7 +161,7 @@ static const struct irq_domain_ops gicp_domain_ops = { · 160 unmodified lines | |||
| 161 | static const struct msi_parent_ops gicp_msi_parent_ops = { | 161 | static const struct msi_parent_ops gicp_msi_parent_ops = { |
| 162 | .supported_flags = GICP_MSI_FLAGS_SUPPORTED, | 162 | .supported_flags = GICP_MSI_FLAGS_SUPPORTED, |
| 163 | .required_flags = GICP_MSI_FLAGS_REQUIRED, | 163 | .required_flags = GICP_MSI_FLAGS_REQUIRED, |
| 164 | .chip_flags = MSI_CHIP_FLAG_SET_EOI | MSI_CHIP_FLAG_SET_ACK, | 164 | .chip_flags = MSI_CHIP_FLAG_SET_EOI, |
| 165 | .bus_select_token = DOMAIN_BUS_GENERIC_MSI, | 165 | .bus_select_token = DOMAIN_BUS_GENERIC_MSI, |
| 166 | .bus_select_mask = MATCH_PLATFORM_MSI, | 166 | .bus_select_mask = MATCH_PLATFORM_MSI, |
| 167 | .prefix = "GICP-", | 167 | .prefix = "GICP-", |
| @@ -157,7 +157,7 @@ static const struct irq_domain_ops odmi_domain_ops = { · 156 unmodified lines | |||
| 157 | static const struct msi_parent_ops odmi_msi_parent_ops = { | 157 | static const struct msi_parent_ops odmi_msi_parent_ops = { |
| 158 | .supported_flags = ODMI_MSI_FLAGS_SUPPORTED, | 158 | .supported_flags = ODMI_MSI_FLAGS_SUPPORTED, |
| 159 | .required_flags = ODMI_MSI_FLAGS_REQUIRED, | 159 | .required_flags = ODMI_MSI_FLAGS_REQUIRED, |
| 160 | .chip_flags = MSI_CHIP_FLAG_SET_EOI | MSI_CHIP_FLAG_SET_ACK, | 160 | .chip_flags = MSI_CHIP_FLAG_SET_EOI, |
| 161 | .bus_select_token = DOMAIN_BUS_GENERIC_MSI, | 161 | .bus_select_token = DOMAIN_BUS_GENERIC_MSI, |
| 162 | .bus_select_mask = MATCH_PLATFORM_MSI, | 162 | .bus_select_mask = MATCH_PLATFORM_MSI, |
| 163 | .prefix = "ODMI-", | 163 | .prefix = "ODMI-", |
| @@ -208,17 +208,17 @@ skip: · 207 unmodified lines | |||
| 208 | } | 208 | } |
| 209 | 209 | ||
| 210 | #ifdef CONFIG_SMP | 210 | #ifdef CONFIG_SMP |
| 211 | static void __imsic_local_timer_start(struct imsic_local_priv *lpriv) | 211 | static void __imsic_local_timer_start(struct imsic_local_priv *lpriv, unsigned int cpu) |
| 212 | { | 212 | { |
| 213 | lockdep_assert_held(&lpriv->lock); | 213 | lockdep_assert_held(&lpriv->lock); |
| 214 | 214 | ||
| 215 | if (!timer_pending(&lpriv->timer)) { | 215 | if (!timer_pending(&lpriv->timer)) { |
| 216 | lpriv->timer.expires = jiffies + 1; | 216 | lpriv->timer.expires = jiffies + 1; |
| 217 | add_timer_on(&lpriv->timer, smp_processor_id()); | 217 | add_timer_on(&lpriv->timer, cpu); |
| 218 | } | 218 | } |
| 219 | } | 219 | } |
| 220 | #else | 220 | #else |
| 221 | static inline void __imsic_local_timer_start(struct imsic_local_priv *lpriv) | 221 | static inline void __imsic_local_timer_start(struct imsic_local_priv *lpriv, unsigned int cpu) |
| 222 | { | 222 | { |
| 223 | } | 223 | } |
| 224 | #endif | 224 | #endif |
| @@ -233,7 +233,7 @@ void imsic_local_sync_all(bool force_all) · 8 unmodified lines | |||
| 233 | if (force_all) | 233 | if (force_all) |
| 234 | bitmap_fill(lpriv->dirty_bitmap, imsic->global.nr_ids + 1); | 234 | bitmap_fill(lpriv->dirty_bitmap, imsic->global.nr_ids + 1); |
| 235 | if (!__imsic_local_sync(lpriv)) | 235 | if (!__imsic_local_sync(lpriv)) |
| 236 | __imsic_local_timer_start(lpriv); | 236 | __imsic_local_timer_start(lpriv, smp_processor_id()); |
| 237 | 237 | ||
| 238 | raw_spin_unlock_irqrestore(&lpriv->lock, flags); | 238 | raw_spin_unlock_irqrestore(&lpriv->lock, flags); |
| 239 | } | 239 | } |
| @@ -278,7 +278,7 @@ static void __imsic_remote_sync(struct imsic_local_priv *lpriv, unsigned int cpu · 38 unmodified lines | |||
| 278 | return; | 278 | return; |
| 279 | } | 279 | } |
| 280 | 280 | ||
| 281 | __imsic_local_timer_start(lpriv); | 281 | __imsic_local_timer_start(lpriv, cpu); |
| 282 | } | 282 | } |
| 283 | } | 283 | } |
| 284 | #else | 284 | #else |
| @@ -326,6 +326,26 @@ static void b53_get_vlan_entry(struct b53_device *dev, u16 vid, · 325 unmodified lines | |||
| 326 | } | 326 | } |
| 327 | } | 327 | } |
| 328 | 328 | ||
| 329 | static void b53_set_eap_mode(struct b53_device *dev, int port, int mode) | ||
| 330 | { | ||
| 331 | u64 eap_conf; | ||
| 332 | |||
| 333 | if (is5325(dev) || is5365(dev) || dev->chip_id == BCM5389_DEVICE_ID) | ||
| 334 | return; | ||
| 335 | |||
| 336 | b53_read64(dev, B53_EAP_PAGE, B53_PORT_EAP_CONF(port), &eap_conf); | ||
| 337 | |||
| 338 | if (is63xx(dev)) { | ||
| 339 | eap_conf &= ~EAP_MODE_MASK_63XX; | ||
| 340 | eap_conf |= (u64)mode << EAP_MODE_SHIFT_63XX; | ||
| 341 | } else { | ||
| 342 | eap_conf &= ~EAP_MODE_MASK; | ||
| 343 | eap_conf |= (u64)mode << EAP_MODE_SHIFT; | ||
| 344 | } | ||
| 345 | |||
| 346 | b53_write64(dev, B53_EAP_PAGE, B53_PORT_EAP_CONF(port), eap_conf); | ||
| 347 | } | ||
| 348 | |||
| 329 | static void b53_set_forwarding(struct b53_device *dev, int enable) | 349 | static void b53_set_forwarding(struct b53_device *dev, int enable) |
| 330 | { | 350 | { |
| 331 | u8 mgmt; | 351 | u8 mgmt; |
| @@ -586,6 +606,13 @@ int b53_setup_port(struct dsa_switch *ds, int port) · 254 unmodified lines | |||
| 586 | b53_port_set_mcast_flood(dev, port, true); | 606 | b53_port_set_mcast_flood(dev, port, true); |
| 587 | b53_port_set_learning(dev, port, false); | 607 | b53_port_set_learning(dev, port, false); |
| 588 | 608 | ||
| 609 | /* Force all traffic to go to the CPU port to prevent the ASIC from | ||
| 610 | * trying to forward to bridged ports on matching FDB entries, then | ||
| 611 | * dropping frames because it isn't allowed to forward there. | ||
| 612 | */ | ||
| 613 | if (dsa_is_user_port(ds, port)) | ||
| 614 | b53_set_eap_mode(dev, port, EAP_MODE_SIMPLIFIED); | ||
| 615 | |||
| 589 | return 0; | 616 | return 0; |
| 590 | } | 617 | } |
| 591 | EXPORT_SYMBOL(b53_setup_port); | 618 | EXPORT_SYMBOL(b53_setup_port); |
| @@ -2042,6 +2069,9 @@ int b53_br_join(struct dsa_switch *ds, int port, struct dsa_bridge bridge, · 1450 unmodified lines | |||
| 2042 | pvlan |= BIT(i); | 2069 | pvlan |= BIT(i); |
| 2043 | } | 2070 | } |
| 2044 | 2071 | ||
| 2072 | /* Disable redirection of unknown SA to the CPU port */ | ||
| 2073 | b53_set_eap_mode(dev, port, EAP_MODE_BASIC); | ||
| 2074 | |||
| 2045 | /* Configure the local port VLAN control membership to include | 2075 | /* Configure the local port VLAN control membership to include |
| 2046 | * remote ports and update the local port bitmask | 2076 | * remote ports and update the local port bitmask |
| 2047 | */ | 2077 | */ |
| @@ -2077,6 +2107,9 @@ void b53_br_leave(struct dsa_switch *ds, int port, struct dsa_bridge bridge) · 29 unmodified lines | |||
| 2077 | pvlan &= ~BIT(i); | 2107 | pvlan &= ~BIT(i); |
| 2078 | } | 2108 | } |
| 2079 | 2109 | ||
| 2110 | /* Enable redirection of unknown SA to the CPU port */ | ||
| 2111 | b53_set_eap_mode(dev, port, EAP_MODE_SIMPLIFIED); | ||
| 2112 | |||
| 2080 | b53_write16(dev, B53_PVLAN_PAGE, B53_PVLAN_PORT_MASK(port), pvlan); | 2113 | b53_write16(dev, B53_PVLAN_PAGE, B53_PVLAN_PORT_MASK(port), pvlan); |
| 2081 | dev->ports[port].vlan_ctl_mask = pvlan; | 2114 | dev->ports[port].vlan_ctl_mask = pvlan; |
| 2082 | 2115 | ||
| @@ -50,6 +50,9 @@ · 49 unmodified lines | |||
| 50 | /* Jumbo Frame Registers */ | 50 | /* Jumbo Frame Registers */ |
| 51 | #define B53_JUMBO_PAGE 0x40 | 51 | #define B53_JUMBO_PAGE 0x40 |
| 52 | 52 | ||
| 53 | /* EAP Registers */ | ||
| 54 | #define B53_EAP_PAGE 0x42 | ||
| 55 | |||
| 53 | /* EEE Control Registers Page */ | 56 | /* EEE Control Registers Page */ |
| 54 | #define B53_EEE_PAGE 0x92 | 57 | #define B53_EEE_PAGE 0x92 |
| 55 | 58 | ||
| @@ -480,6 +483,17 @@ · 424 unmodified lines | |||
| 480 | #define JMS_MIN_SIZE 1518 | 483 | #define JMS_MIN_SIZE 1518 |
| 481 | #define JMS_MAX_SIZE 9724 | 484 | #define JMS_MAX_SIZE 9724 |
| 482 | 485 | ||
| 486 | /************************************************************************* | ||
| 487 | * EAP Page Registers | ||
| 488 | *************************************************************************/ | ||
| 489 | #define B53_PORT_EAP_CONF(i) (0x20 + 8 * (i)) | ||
| 490 | #define EAP_MODE_SHIFT 51 | ||
| 491 | #define EAP_MODE_SHIFT_63XX 50 | ||
| 492 | #define EAP_MODE_MASK (0x3ull << EAP_MODE_SHIFT) | ||
| 493 | #define EAP_MODE_MASK_63XX (0x3ull << EAP_MODE_SHIFT_63XX) | ||
| 494 | #define EAP_MODE_BASIC 0 | ||
| 495 | #define EAP_MODE_SIMPLIFIED 3 | ||
| 496 | |||
| 483 | /************************************************************************* | 497 | /************************************************************************* |
| 484 | * EEE Configuration Page Registers | 498 | * EEE Configuration Page Registers |
| 485 | *************************************************************************/ | 499 | *************************************************************************/ |
| @@ -265,16 +265,70 @@ static void ksz_phylink_mac_link_down(struct phylink_config *config, · 264 unmodified lines | |||
| 265 | unsigned int mode, | 265 | unsigned int mode, |
| 266 | phy_interface_t interface); | 266 | phy_interface_t interface); |
| 267 | 267 | ||
| 268 | /** | ||
| 269 | * ksz_phylink_mac_disable_tx_lpi() - Callback to signal LPI support (Dummy) | ||
| 270 | * @config: phylink config structure | ||
| 271 | * | ||
| 272 | * This function is a dummy handler. See ksz_phylink_mac_enable_tx_lpi() for | ||
| 273 | * a detailed explanation of EEE/LPI handling in KSZ switches. | ||
| 274 | */ | ||
| 275 | static void ksz_phylink_mac_disable_tx_lpi(struct phylink_config *config) | ||
| 276 | { | ||
| 277 | } | ||
| 278 | |||
| 279 | /** | ||
| 280 | * ksz_phylink_mac_enable_tx_lpi() - Callback to signal LPI support (Dummy) | ||
| 281 | * @config: phylink config structure | ||
| 282 | * @timer: timer value before entering LPI (unused) | ||
| 283 | * @tx_clock_stop: whether to stop the TX clock in LPI mode (unused) | ||
| 284 | * | ||
| 285 | * This function signals to phylink that the driver architecture supports | ||
| 286 | * LPI management, enabling phylink to control EEE advertisement during | ||
| 287 | * negotiation according to IEEE Std 802.3 (Clause 78). | ||
| 288 | * | ||
| 289 | * Hardware Management of EEE/LPI State: | ||
| 290 | * For KSZ switch ports with integrated PHYs (e.g., KSZ9893R ports 1-2), | ||
| 291 | * observation and testing suggest that the actual EEE / Low Power Idle (LPI) | ||
| 292 | * state transitions are managed autonomously by the hardware based on | ||
| 293 | * the auto-negotiation results. (Note: While the datasheet describes EEE | ||
| 294 | * operation based on negotiation, it doesn't explicitly detail the internal | ||
| 295 | * MAC/PHY interaction, so autonomous hardware management of the MAC state | ||
| 296 | * for LPI is inferred from observed behavior). | ||
| 297 | * This hardware control, consistent with the switch's ability to operate | ||
| 298 | * autonomously via strapping, means MAC-level software intervention is not | ||
| 299 | * required or exposed for managing the LPI state once EEE is negotiated. | ||
| 300 | * (Ref: KSZ9893R Data Sheet DS00002420D, primarily Section 4.7.5 explaining | ||
| 301 | * EEE, also Sections 4.1.7 on Auto-Negotiation and 3.2.1 on Configuration | ||
| 302 | * Straps). | ||
| 303 | * | ||
| 304 | * Additionally, ports configured as MAC interfaces (e.g., KSZ9893R port 3) | ||
| 305 | * lack documented MAC-level LPI control. | ||
| 306 | * | ||
| 307 | * Therefore, this callback performs no action and serves primarily to inform | ||
| 308 | * phylink of LPI awareness and to document the inferred hardware behavior. | ||
| 309 | * | ||
| 310 | * Returns: 0 (Always success) | ||
| 311 | */ | ||
| 312 | static int ksz_phylink_mac_enable_tx_lpi(struct phylink_config *config, | ||
| 313 | u32 timer, bool tx_clock_stop) | ||
| 314 | { | ||
| 315 | return 0; | ||
| 316 | } | ||
| 317 | |||
| 268 | static const struct phylink_mac_ops ksz88x3_phylink_mac_ops = { | 318 | static const struct phylink_mac_ops ksz88x3_phylink_mac_ops = { |
| 269 | .mac_config = ksz88x3_phylink_mac_config, | 319 | .mac_config = ksz88x3_phylink_mac_config, |
| 270 | .mac_link_down = ksz_phylink_mac_link_down, | 320 | .mac_link_down = ksz_phylink_mac_link_down, |
| 271 | .mac_link_up = ksz8_phylink_mac_link_up, | 321 | .mac_link_up = ksz8_phylink_mac_link_up, |
| 322 | .mac_disable_tx_lpi = ksz_phylink_mac_disable_tx_lpi, | ||
| 323 | .mac_enable_tx_lpi = ksz_phylink_mac_enable_tx_lpi, | ||
| 272 | }; | 324 | }; |
| 273 | 325 | ||
| 274 | static const struct phylink_mac_ops ksz8_phylink_mac_ops = { | 326 | static const struct phylink_mac_ops ksz8_phylink_mac_ops = { |
| 275 | .mac_config = ksz_phylink_mac_config, | 327 | .mac_config = ksz_phylink_mac_config, |
| 276 | .mac_link_down = ksz_phylink_mac_link_down, | 328 | .mac_link_down = ksz_phylink_mac_link_down, |
| 277 | .mac_link_up = ksz8_phylink_mac_link_up, | 329 | .mac_link_up = ksz8_phylink_mac_link_up, |
| 330 | .mac_disable_tx_lpi = ksz_phylink_mac_disable_tx_lpi, | ||
| 331 | .mac_enable_tx_lpi = ksz_phylink_mac_enable_tx_lpi, | ||
| 278 | }; | 332 | }; |
| 279 | 333 | ||
| 280 | static const struct ksz_dev_ops ksz88xx_dev_ops = { | 334 | static const struct ksz_dev_ops ksz88xx_dev_ops = { |
| @@ -358,6 +412,8 @@ static const struct phylink_mac_ops ksz9477_phylink_mac_ops = { · 77 unmodified lines | |||
| 358 | .mac_config = ksz_phylink_mac_config, | 412 | .mac_config = ksz_phylink_mac_config, |
| 359 | .mac_link_down = ksz_phylink_mac_link_down, | 413 | .mac_link_down = ksz_phylink_mac_link_down, |
| 360 | .mac_link_up = ksz9477_phylink_mac_link_up, | 414 | .mac_link_up = ksz9477_phylink_mac_link_up, |
| 415 | .mac_disable_tx_lpi = ksz_phylink_mac_disable_tx_lpi, | ||
| 416 | .mac_enable_tx_lpi = ksz_phylink_mac_enable_tx_lpi, | ||
| 361 | }; | 417 | }; |
| 362 | 418 | ||
| 363 | static const struct ksz_dev_ops ksz9477_dev_ops = { | 419 | static const struct ksz_dev_ops ksz9477_dev_ops = { |
| @@ -401,6 +457,8 @@ static const struct phylink_mac_ops lan937x_phylink_mac_ops = { · 37 unmodified lines | |||
| 401 | .mac_config = ksz_phylink_mac_config, | 457 | .mac_config = ksz_phylink_mac_config, |
| 402 | .mac_link_down = ksz_phylink_mac_link_down, | 458 | .mac_link_down = ksz_phylink_mac_link_down, |
| 403 | .mac_link_up = ksz9477_phylink_mac_link_up, | 459 | .mac_link_up = ksz9477_phylink_mac_link_up, |
| 460 | .mac_disable_tx_lpi = ksz_phylink_mac_disable_tx_lpi, | ||
| 461 | .mac_enable_tx_lpi = ksz_phylink_mac_enable_tx_lpi, | ||
| 404 | }; | 462 | }; |
| 405 | 463 | ||
| 406 | static const struct ksz_dev_ops lan937x_dev_ops = { | 464 | static const struct ksz_dev_ops lan937x_dev_ops = { |
| @@ -2016,6 +2074,18 @@ static void ksz_phylink_get_caps(struct dsa_switch *ds, int port, · 1609 unmodified lines | |||
| 2016 | 2074 | ||
| 2017 | if (dev->dev_ops->get_caps) | 2075 | if (dev->dev_ops->get_caps) |
| 2018 | dev->dev_ops->get_caps(dev, port, config); | 2076 | dev->dev_ops->get_caps(dev, port, config); |
| 2077 | |||
| 2078 | if (ds->ops->support_eee && ds->ops->support_eee(ds, port)) { | ||
| 2079 | memcpy(config->lpi_interfaces, config->supported_interfaces, | ||
| 2080 | sizeof(config->lpi_interfaces)); | ||
| 2081 | |||
| 2082 | config->lpi_capabilities = MAC_100FD; | ||
| 2083 | if (dev->info->gbit_capable[port]) | ||
| 2084 | config->lpi_capabilities |= MAC_1000FD; | ||
| 2085 | |||
| 2086 | /* EEE is fully operational */ | ||
| 2087 | config->eee_enabled_default = true; | ||
| 2088 | } | ||
| 2019 | } | 2089 | } |
| 2020 | 2090 | ||
| 2021 | void ksz_r_mib_stats64(struct ksz_device *dev, int port) | 2091 | void ksz_r_mib_stats64(struct ksz_device *dev, int port) |
| @@ -3008,31 +3078,6 @@ static u32 ksz_get_phy_flags(struct dsa_switch *ds, int port) · 986 unmodified lines | |||
| 3008 | if (!port) | 3078 | if (!port) |
| 3009 | return MICREL_KSZ8_P1_ERRATA; | 3079 | return MICREL_KSZ8_P1_ERRATA; |
| 3010 | break; | 3080 | break; |
| 3011 | case KSZ8567_CHIP_ID: | ||
| 3012 | /* KSZ8567R Errata DS80000752C Module 4 */ | ||
| 3013 | case KSZ8765_CHIP_ID: | ||
| 3014 | case KSZ8794_CHIP_ID: | ||
| 3015 | case KSZ8795_CHIP_ID: | ||
| 3016 | /* KSZ879x/KSZ877x/KSZ876x Errata DS80000687C Module 2 */ | ||
| 3017 | case KSZ9477_CHIP_ID: | ||
| 3018 | /* KSZ9477S Errata DS80000754A Module 4 */ | ||
| 3019 | case KSZ9567_CHIP_ID: | ||
| 3020 | /* KSZ9567S Errata DS80000756A Module 4 */ | ||
| 3021 | case KSZ9896_CHIP_ID: | ||
| 3022 | /* KSZ9896C Errata DS80000757A Module 3 */ | ||
| 3023 | case KSZ9897_CHIP_ID: | ||
| 3024 | case LAN9646_CHIP_ID: | ||
| 3025 | /* KSZ9897R Errata DS80000758C Module 4 */ | ||
| 3026 | /* Energy Efficient Ethernet (EEE) feature select must be manually disabled | ||
| 3027 | * The EEE feature is enabled by default, but it is not fully | ||
| 3028 | * operational. It must be manually disabled through register | ||
| 3029 | * controls. If not disabled, the PHY ports can auto-negotiate | ||
| 3030 | * to enable EEE, and this feature can cause link drops when | ||
| 3031 | * linked to another device supporting EEE. | ||
| 3032 | * | ||
| 3033 | * The same item appears in the errata for all switches above. | ||
| 3034 | */ | ||
| 3035 | return MICREL_NO_EEE; | ||
| 3036 | } | 3081 | } |
| 3037 | 3082 | ||
| 3038 | return 0; | 3083 | return 0; |
| @@ -3466,6 +3511,20 @@ static int ksz_max_mtu(struct dsa_switch *ds, int port) · 427 unmodified lines | |||
| 3466 | return -EOPNOTSUPP; | 3511 | return -EOPNOTSUPP; |
| 3467 | } | 3512 | } |
| 3468 | 3513 | ||
| 3514 | /** | ||
| 3515 | * ksz_support_eee - Determine Energy Efficient Ethernet (EEE) support for a | ||
| 3516 | * port | ||
| 3517 | * @ds: Pointer to the DSA switch structure | ||
| 3518 | * @port: Port number to check | ||
| 3519 | * | ||
| 3520 | * This function also documents devices where EEE was initially advertised but | ||
| 3521 | * later withdrawn due to reliability issues, as described in official errata | ||
| 3522 | * documents. These devices are explicitly listed to record known limitations, | ||
| 3523 | * even if there is no technical necessity for runtime checks. | ||
| 3524 | * | ||
| 3525 | * Returns: true if the internal PHY on the given port supports fully | ||
| 3526 | * operational EEE, false otherwise. | ||
| 3527 | */ | ||
| 3469 | static bool ksz_support_eee(struct dsa_switch *ds, int port) | 3528 | static bool ksz_support_eee(struct dsa_switch *ds, int port) |
| 3470 | { | 3529 | { |
| 3471 | struct ksz_device *dev = ds->priv; | 3530 | struct ksz_device *dev = ds->priv; |
| @@ -3475,15 +3534,35 @@ static bool ksz_support_eee(struct dsa_switch *ds, int port) · 3 unmodified lines | |||
| 3475 | 3534 | ||
| 3476 | switch (dev->chip_id) { | 3535 | switch (dev->chip_id) { |
| 3477 | case KSZ8563_CHIP_ID: | 3536 | case KSZ8563_CHIP_ID: |
| 3537 | case KSZ9563_CHIP_ID: | ||
| 3538 | case KSZ9893_CHIP_ID: | ||
| 3539 | return true; | ||
| 3478 | case KSZ8567_CHIP_ID: | 3540 | case KSZ8567_CHIP_ID: |
| 3541 | /* KSZ8567R Errata DS80000752C Module 4 */ | ||
| 3542 | case KSZ8765_CHIP_ID: | ||
| 3543 | case KSZ8794_CHIP_ID: | ||
| 3544 | case KSZ8795_CHIP_ID: | ||
| 3545 | /* KSZ879x/KSZ877x/KSZ876x Errata DS80000687C Module 2 */ | ||
| 3479 | case KSZ9477_CHIP_ID: | 3546 | case KSZ9477_CHIP_ID: |
| 3480 | case KSZ9563_CHIP_ID: | 3547 | /* KSZ9477S Errata DS80000754A Module 4 */ |
| 3481 | case KSZ9567_CHIP_ID: | 3548 | case KSZ9567_CHIP_ID: |
| 3482 | case KSZ9893_CHIP_ID: | 3549 | /* KSZ9567S Errata DS80000756A Module 4 */ |
| 3483 | case KSZ9896_CHIP_ID: | 3550 | case KSZ9896_CHIP_ID: |
| 3551 | /* KSZ9896C Errata DS80000757A Module 3 */ | ||
| 3484 | case KSZ9897_CHIP_ID: | 3552 | case KSZ9897_CHIP_ID: |
| 3485 | case LAN9646_CHIP_ID: | 3553 | case LAN9646_CHIP_ID: |
| 3486 | return true; | 3554 | /* KSZ9897R Errata DS80000758C Module 4 */ |
| 3555 | /* Energy Efficient Ethernet (EEE) feature select must be | ||
| 3556 | * manually disabled | ||
| 3557 | * The EEE feature is enabled by default, but it is not fully | ||
| 3558 | * operational. It must be manually disabled through register | ||
| 3559 | * controls. If not disabled, the PHY ports can auto-negotiate | ||
| 3560 | * to enable EEE, and this feature can cause link drops when | ||
| 3561 | * linked to another device supporting EEE. | ||
| 3562 | * | ||
| 3563 | * The same item appears in the errata for all switches above. | ||
| 3564 | */ | ||
| 3565 | break; | ||
| 3487 | } | 3566 | } |
| 3488 | 3567 | ||
| 3489 | return false; | 3568 | return false; |
| @@ -2081,6 +2081,7 @@ static void sja1105_bridge_stp_state_set(struct dsa_switch *ds, int port, · 2080 unmodified lines | |||
| 2081 | switch (state) { | 2081 | switch (state) { |
| 2082 | case BR_STATE_DISABLED: | 2082 | case BR_STATE_DISABLED: |
| 2083 | case BR_STATE_BLOCKING: | 2083 | case BR_STATE_BLOCKING: |
| 2084 | case BR_STATE_LISTENING: | ||
| 2084 | /* From UM10944 description of DRPDTAG (why put this there?): | 2085 | /* From UM10944 description of DRPDTAG (why put this there?): |
| 2085 | * "Management traffic flows to the port regardless of the state | 2086 | * "Management traffic flows to the port regardless of the state |
| 2086 | * of the INGRESS flag". So BPDUs are still be allowed to pass. | 2087 | * of the INGRESS flag". So BPDUs are still be allowed to pass. |
| @@ -2090,11 +2091,6 @@ static void sja1105_bridge_stp_state_set(struct dsa_switch *ds, int port, · 3 unmodified lines | |||
| 2090 | mac[port].egress = false; | 2091 | mac[port].egress = false; |
| 2091 | mac[port].dyn_learn = false; | 2092 | mac[port].dyn_learn = false; |
| 2092 | break; | 2093 | break; |
| 2093 | case BR_STATE_LISTENING: | ||
| 2094 | mac[port].ingress = true; | ||
| 2095 | mac[port].egress = false; | ||
| 2096 | mac[port].dyn_learn = false; | ||
| 2097 | break; | ||
| 2098 | case BR_STATE_LEARNING: | 2094 | case BR_STATE_LEARNING: |
| 2099 | mac[port].ingress = true; | 2095 | mac[port].ingress = true; |
| 2100 | mac[port].egress = false; | 2096 | mac[port].egress = false; |
| @@ -14013,13 +14013,28 @@ static void bnxt_unlock_sp(struct bnxt *bp) · 14012 unmodified lines | |||
| 14013 | netdev_unlock(bp->dev); | 14013 | netdev_unlock(bp->dev); |
| 14014 | } | 14014 | } |
| 14015 | 14015 | ||
| 14016 | /* Same as bnxt_lock_sp() with additional rtnl_lock */ | ||
| 14017 | static void bnxt_rtnl_lock_sp(struct bnxt *bp) | ||
| 14018 | { | ||
| 14019 | clear_bit(BNXT_STATE_IN_SP_TASK, &bp->state); | ||
| 14020 | rtnl_lock(); | ||
| 14021 | netdev_lock(bp->dev); | ||
| 14022 | } | ||
| 14023 | |||
| 14024 | static void bnxt_rtnl_unlock_sp(struct bnxt *bp) | ||
| 14025 | { | ||
| 14026 | set_bit(BNXT_STATE_IN_SP_TASK, &bp->state); | ||
| 14027 | netdev_unlock(bp->dev); | ||
| 14028 | rtnl_unlock(); | ||
| 14029 | } | ||
| 14030 | |||
| 14016 | /* Only called from bnxt_sp_task() */ | 14031 | /* Only called from bnxt_sp_task() */ |
| 14017 | static void bnxt_reset(struct bnxt *bp, bool silent) | 14032 | static void bnxt_reset(struct bnxt *bp, bool silent) |
| 14018 | { | 14033 | { |
| 14019 | bnxt_lock_sp(bp); | 14034 | bnxt_rtnl_lock_sp(bp); |
| 14020 | if (test_bit(BNXT_STATE_OPEN, &bp->state)) | 14035 | if (test_bit(BNXT_STATE_OPEN, &bp->state)) |
| 14021 | bnxt_reset_task(bp, silent); | 14036 | bnxt_reset_task(bp, silent); |
| 14022 | bnxt_unlock_sp(bp); | 14037 | bnxt_rtnl_unlock_sp(bp); |
| 14023 | } | 14038 | } |
| 14024 | 14039 | ||
| 14025 | /* Only called from bnxt_sp_task() */ | 14040 | /* Only called from bnxt_sp_task() */ |
| @@ -14027,9 +14042,9 @@ static void bnxt_rx_ring_reset(struct bnxt *bp) · 1 unmodified line | |||
| 14027 | { | 14042 | { |
| 14028 | int i; | 14043 | int i; |
| 14029 | 14044 | ||
| 14030 | bnxt_lock_sp(bp); | 14045 | bnxt_rtnl_lock_sp(bp); |
| 14031 | if (!test_bit(BNXT_STATE_OPEN, &bp->state)) { | 14046 | if (!test_bit(BNXT_STATE_OPEN, &bp->state)) { |
| 14032 | bnxt_unlock_sp(bp); | 14047 | bnxt_rtnl_unlock_sp(bp); |
| 14033 | return; | 14048 | return; |
| 14034 | } | 14049 | } |
| 14035 | /* Disable and flush TPA before resetting the RX ring */ | 14050 | /* Disable and flush TPA before resetting the RX ring */ |
| @@ -14068,7 +14083,7 @@ static void bnxt_rx_ring_reset(struct bnxt *bp) · 32 unmodified lines | |||
| 14068 | } | 14083 | } |
| 14069 | if (bp->flags & BNXT_FLAG_TPA) | 14084 | if (bp->flags & BNXT_FLAG_TPA) |
| 14070 | bnxt_set_tpa(bp, true); | 14085 | bnxt_set_tpa(bp, true); |
| 14071 | bnxt_unlock_sp(bp); | 14086 | bnxt_rtnl_unlock_sp(bp); |
| 14072 | } | 14087 | } |
| 14073 | 14088 | ||
| 14074 | static void bnxt_fw_fatal_close(struct bnxt *bp) | 14089 | static void bnxt_fw_fatal_close(struct bnxt *bp) |
| @@ -14960,15 +14975,17 @@ static void bnxt_fw_reset_task(struct work_struct *work) · 885 unmodified lines | |||
| 14960 | bp->fw_reset_state = BNXT_FW_RESET_STATE_OPENING; | 14975 | bp->fw_reset_state = BNXT_FW_RESET_STATE_OPENING; |
| 14961 | fallthrough; | 14976 | fallthrough; |
| 14962 | case BNXT_FW_RESET_STATE_OPENING: | 14977 | case BNXT_FW_RESET_STATE_OPENING: |
| 14963 | while (!netdev_trylock(bp->dev)) { | 14978 | while (!rtnl_trylock()) { |
| 14964 | bnxt_queue_fw_reset_work(bp, HZ / 10); | 14979 | bnxt_queue_fw_reset_work(bp, HZ / 10); |
| 14965 | return; | 14980 | return; |
| 14966 | } | 14981 | } |
| 14982 | netdev_lock(bp->dev); | ||
| 14967 | rc = bnxt_open(bp->dev); | 14983 | rc = bnxt_open(bp->dev); |
| 14968 | if (rc) { | 14984 | if (rc) { |
| 14969 | netdev_err(bp->dev, "bnxt_open() failed during FW reset\n"); | 14985 | netdev_err(bp->dev, "bnxt_open() failed during FW reset\n"); |
| 14970 | bnxt_fw_reset_abort(bp, rc); | 14986 | bnxt_fw_reset_abort(bp, rc); |
| 14971 | netdev_unlock(bp->dev); | 14987 | netdev_unlock(bp->dev); |
| 14988 | rtnl_unlock(); | ||
| 14972 | goto ulp_start; | 14989 | goto ulp_start; |
| 14973 | } | 14990 | } |
| 14974 | 14991 | ||
| @@ -14988,6 +15005,7 @@ static void bnxt_fw_reset_task(struct work_struct *work) · 13 unmodified lines | |||
| 14988 | bnxt_dl_health_fw_status_update(bp, true); | 15005 | bnxt_dl_health_fw_status_update(bp, true); |
| 14989 | } | 15006 | } |
| 14990 | netdev_unlock(bp->dev); | 15007 | netdev_unlock(bp->dev); |
| 15008 | rtnl_unlock(); | ||
| 14991 | bnxt_ulp_start(bp, 0); | 15009 | bnxt_ulp_start(bp, 0); |
| 14992 | bnxt_reenable_sriov(bp); | 15010 | bnxt_reenable_sriov(bp); |
| 14993 | netdev_lock(bp->dev); | 15011 | netdev_lock(bp->dev); |
| @@ -15936,7 +15954,7 @@ err_reset: · 942 unmodified lines | |||
| 15936 | rc); | 15954 | rc); |
| 15937 | napi_enable_locked(&bnapi->napi); | 15955 | napi_enable_locked(&bnapi->napi); |
| 15938 | bnxt_db_nq_arm(bp, &cpr->cp_db, cpr->cp_raw_cons); | 15956 | bnxt_db_nq_arm(bp, &cpr->cp_db, cpr->cp_raw_cons); |
| 15939 | bnxt_reset_task(bp, true); | 15957 | netif_close(dev); |
| 15940 | return rc; | 15958 | return rc; |
| 15941 | } | 15959 | } |
| 15942 | 15960 | ||
| @@ -16752,6 +16770,7 @@ static int bnxt_resume(struct device *device) · 809 unmodified lines | |||
| 16752 | struct bnxt *bp = netdev_priv(dev); | 16770 | struct bnxt *bp = netdev_priv(dev); |
| 16753 | int rc = 0; | 16771 | int rc = 0; |
| 16754 | 16772 | ||
| 16773 | rtnl_lock(); | ||
| 16755 | netdev_lock(dev); | 16774 | netdev_lock(dev); |
| 16756 | rc = pci_enable_device(bp->pdev); | 16775 | rc = pci_enable_device(bp->pdev); |
| 16757 | if (rc) { | 16776 | if (rc) { |
| @@ -16796,6 +16815,7 @@ static int bnxt_resume(struct device *device) · 38 unmodified lines | |||
| 16796 | 16815 | ||
| 16797 | resume_exit: | 16816 | resume_exit: |
| 16798 | netdev_unlock(bp->dev); | 16817 | netdev_unlock(bp->dev); |
| 16818 | rtnl_unlock(); | ||
| 16799 | bnxt_ulp_start(bp, rc); | 16819 | bnxt_ulp_start(bp, rc); |
| 16800 | if (!rc) | 16820 | if (!rc) |
| 16801 | bnxt_reenable_sriov(bp); | 16821 | bnxt_reenable_sriov(bp); |
| @@ -16961,6 +16981,7 @@ static void bnxt_io_resume(struct pci_dev *pdev) · 159 unmodified lines | |||
| 16961 | int err; | 16981 | int err; |
| 16962 | 16982 | ||
| 16963 | netdev_info(bp->dev, "PCI Slot Resume\n"); | 16983 | netdev_info(bp->dev, "PCI Slot Resume\n"); |
| 16984 | rtnl_lock(); | ||
| 16964 | netdev_lock(netdev); | 16985 | netdev_lock(netdev); |
| 16965 | 16986 | ||
| 16966 | err = bnxt_hwrm_func_qcaps(bp); | 16987 | err = bnxt_hwrm_func_qcaps(bp); |
| @@ -16978,6 +16999,7 @@ static void bnxt_io_resume(struct pci_dev *pdev) · 11 unmodified lines | |||
| 16978 | netif_device_attach(netdev); | 16999 | netif_device_attach(netdev); |
| 16979 | 17000 | ||
| 16980 | netdev_unlock(netdev); | 17001 | netdev_unlock(netdev); |
| 17002 | rtnl_unlock(); | ||
| 16981 | bnxt_ulp_start(bp, err); | 17003 | bnxt_ulp_start(bp, err); |
| 16982 | if (!err) | 17004 | if (!err) |
| 16983 | bnxt_reenable_sriov(bp); | 17005 | bnxt_reenable_sriov(bp); |
| @@ -997,22 +997,15 @@ static void macb_update_stats(struct macb *bp) · 996 unmodified lines | |||
| 997 | 997 | ||
| 998 | static int macb_halt_tx(struct macb *bp) | 998 | static int macb_halt_tx(struct macb *bp) |
| 999 | { | 999 | { |
| 1000 | unsigned long halt_time, timeout; | 1000 | u32 status; |
| 1001 | u32 status; | ||
| 1002 | 1001 | ||
| 1003 | macb_writel(bp, NCR, macb_readl(bp, NCR) | MACB_BIT(THALT)); | 1002 | macb_writel(bp, NCR, macb_readl(bp, NCR) | MACB_BIT(THALT)); |
| 1004 | 1003 | ||
| 1005 | timeout = jiffies + usecs_to_jiffies(MACB_HALT_TIMEOUT); | 1004 | /* Poll TSR until TGO is cleared or timeout. */ |
| 1006 | do { | 1005 | return read_poll_timeout_atomic(macb_readl, status, |
| 1007 | halt_time = jiffies; | 1006 | !(status & MACB_BIT(TGO)), |
| 1008 | status = macb_readl(bp, TSR); | 1007 | 250, MACB_HALT_TIMEOUT, false, |
| 1009 | if (!(status & MACB_BIT(TGO))) | 1008 | bp, TSR); |
| 1010 | return 0; | ||
| 1011 | |||
| 1012 | udelay(250); | ||
| 1013 | } while (time_before(halt_time, timeout)); | ||
| 1014 | |||
| 1015 | return -ETIMEDOUT; | ||
| 1016 | } | 1009 | } |
| 1017 | 1010 | ||
| 1018 | static void macb_tx_unmap(struct macb *bp, struct macb_tx_skb *tx_skb, int budget) | 1011 | static void macb_tx_unmap(struct macb *bp, struct macb_tx_skb *tx_skb, int budget) |
| @@ -67,6 +67,8 @@ · 66 unmodified lines | |||
| 67 | #define TSNEP_TX_TYPE_XDP_NDO_MAP_PAGE (TSNEP_TX_TYPE_XDP_NDO | TSNEP_TX_TYPE_MAP_PAGE) | 67 | #define TSNEP_TX_TYPE_XDP_NDO_MAP_PAGE (TSNEP_TX_TYPE_XDP_NDO | TSNEP_TX_TYPE_MAP_PAGE) |
| 68 | #define TSNEP_TX_TYPE_XDP (TSNEP_TX_TYPE_XDP_TX | TSNEP_TX_TYPE_XDP_NDO) | 68 | #define TSNEP_TX_TYPE_XDP (TSNEP_TX_TYPE_XDP_TX | TSNEP_TX_TYPE_XDP_NDO) |
| 69 | #define TSNEP_TX_TYPE_XSK BIT(12) | 69 | #define TSNEP_TX_TYPE_XSK BIT(12) |
| 70 | #define TSNEP_TX_TYPE_TSTAMP BIT(13) | ||
| 71 | #define TSNEP_TX_TYPE_SKB_TSTAMP (TSNEP_TX_TYPE_SKB | TSNEP_TX_TYPE_TSTAMP) | ||
| 70 | 72 | ||
| 71 | #define TSNEP_XDP_TX BIT(0) | 73 | #define TSNEP_XDP_TX BIT(0) |
| 72 | #define TSNEP_XDP_REDIRECT BIT(1) | 74 | #define TSNEP_XDP_REDIRECT BIT(1) |
| @@ -386,8 +388,7 @@ static void tsnep_tx_activate(struct tsnep_tx *tx, int index, int length, · 313 unmodified lines | |||
| 386 | if (entry->skb) { | 388 | if (entry->skb) { |
| 387 | entry->properties = length & TSNEP_DESC_LENGTH_MASK; | 389 | entry->properties = length & TSNEP_DESC_LENGTH_MASK; |
| 388 | entry->properties |= TSNEP_DESC_INTERRUPT_FLAG; | 390 | entry->properties |= TSNEP_DESC_INTERRUPT_FLAG; |
| 389 | if ((entry->type & TSNEP_TX_TYPE_SKB) && | 391 | if ((entry->type & TSNEP_TX_TYPE_SKB_TSTAMP) == TSNEP_TX_TYPE_SKB_TSTAMP) |
| 390 | (skb_shinfo(entry->skb)->tx_flags & SKBTX_IN_PROGRESS)) | ||
| 391 | entry->properties |= TSNEP_DESC_EXTENDED_WRITEBACK_FLAG; | 392 | entry->properties |= TSNEP_DESC_EXTENDED_WRITEBACK_FLAG; |
| 392 | 393 | ||
| 393 | /* toggle user flag to prevent false acknowledge | 394 | /* toggle user flag to prevent false acknowledge |
| @@ -479,7 +480,8 @@ static int tsnep_tx_map_frag(skb_frag_t *frag, struct tsnep_tx_entry *entry, · 85 unmodified lines | |||
| 479 | return mapped; | 480 | return mapped; |
| 480 | } | 481 | } |
| 481 | 482 | ||
| 482 | static int tsnep_tx_map(struct sk_buff *skb, struct tsnep_tx *tx, int count) | 483 | static int tsnep_tx_map(struct sk_buff *skb, struct tsnep_tx *tx, int count, |
| 484 | bool do_tstamp) | ||
| 483 | { | 485 | { |
| 484 | struct device *dmadev = tx->adapter->dmadev; | 486 | struct device *dmadev = tx->adapter->dmadev; |
| 485 | struct tsnep_tx_entry *entry; | 487 | struct tsnep_tx_entry *entry; |
| @@ -505,6 +507,9 @@ static int tsnep_tx_map(struct sk_buff *skb, struct tsnep_tx *tx, int count) · 19 unmodified lines | |||
| 505 | entry->type = TSNEP_TX_TYPE_SKB_INLINE; | 507 | entry->type = TSNEP_TX_TYPE_SKB_INLINE; |
| 506 | mapped = 0; | 508 | mapped = 0; |
| 507 | } | 509 | } |
| 510 | |||
| 511 | if (do_tstamp) | ||
| 512 | entry->type |= TSNEP_TX_TYPE_TSTAMP; | ||
| 508 | } else { | 513 | } else { |
| 509 | skb_frag_t *frag = &skb_shinfo(skb)->frags[i - 1]; | 514 | skb_frag_t *frag = &skb_shinfo(skb)->frags[i - 1]; |
| 510 | 515 | ||
| @@ -558,11 +563,12 @@ static int tsnep_tx_unmap(struct tsnep_tx *tx, int index, int count) · 47 unmodified lines | |||
| 558 | static netdev_tx_t tsnep_xmit_frame_ring(struct sk_buff *skb, | 563 | static netdev_tx_t tsnep_xmit_frame_ring(struct sk_buff *skb, |
| 559 | struct tsnep_tx *tx) | 564 | struct tsnep_tx *tx) |
| 560 | { | 565 | { |
| 561 | int count = 1; | ||
| 562 | struct tsnep_tx_entry *entry; | 566 | struct tsnep_tx_entry *entry; |
| 567 | bool do_tstamp = false; | ||
| 568 | int count = 1; | ||
| 563 | int length; | 569 | int length; |
| 564 | int i; | ||
| 565 | int retval; | 570 | int retval; |
| 571 | int i; | ||
| 566 | 572 | ||
| 567 | if (skb_shinfo(skb)->nr_frags > 0) | 573 | if (skb_shinfo(skb)->nr_frags > 0) |
| 568 | count += skb_shinfo(skb)->nr_frags; | 574 | count += skb_shinfo(skb)->nr_frags; |
| @@ -579,7 +585,13 @@ static netdev_tx_t tsnep_xmit_frame_ring(struct sk_buff *skb, · 10 unmodified lines | |||
| 579 | entry = &tx->entry[tx->write]; | 585 | entry = &tx->entry[tx->write]; |
| 580 | entry->skb = skb; | 586 | entry->skb = skb; |
| 581 | 587 | ||
| 582 | retval = tsnep_tx_map(skb, tx, count); | 588 | if (unlikely(skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP) && |
| 589 | tx->adapter->hwtstamp_config.tx_type == HWTSTAMP_TX_ON) { | ||
| 590 | skb_shinfo(skb)->tx_flags |= SKBTX_IN_PROGRESS; | ||
| 591 | do_tstamp = true; | ||
| 592 | } | ||
| 593 | |||
| 594 | retval = tsnep_tx_map(skb, tx, count, do_tstamp); | ||
| 583 | if (retval < 0) { | 595 | if (retval < 0) { |
| 584 | tsnep_tx_unmap(tx, tx->write, count); | 596 | tsnep_tx_unmap(tx, tx->write, count); |
| 585 | dev_kfree_skb_any(entry->skb); | 597 | dev_kfree_skb_any(entry->skb); |
| @@ -591,9 +603,6 @@ static netdev_tx_t tsnep_xmit_frame_ring(struct sk_buff *skb, · 5 unmodified lines | |||
| 591 | } | 603 | } |
| 592 | length = retval; | 604 | length = retval; |
| 593 | 605 | ||
| 594 | if (skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP) | ||
| 595 | skb_shinfo(skb)->tx_flags |= SKBTX_IN_PROGRESS; | ||
| 596 | |||
| 597 | for (i = 0; i < count; i++) | 606 | for (i = 0; i < count; i++) |
| 598 | tsnep_tx_activate(tx, (tx->write + i) & TSNEP_RING_MASK, length, | 607 | tsnep_tx_activate(tx, (tx->write + i) & TSNEP_RING_MASK, length, |
| 599 | i == count - 1); | 608 | i == count - 1); |
| @@ -844,8 +853,7 @@ static bool tsnep_tx_poll(struct tsnep_tx *tx, int napi_budget) · 244 unmodified lines | |||
| 844 | 853 | ||
| 845 | length = tsnep_tx_unmap(tx, tx->read, count); | 854 | length = tsnep_tx_unmap(tx, tx->read, count); |
| 846 | 855 | ||
| 847 | if ((entry->type & TSNEP_TX_TYPE_SKB) && | 856 | if (((entry->type & TSNEP_TX_TYPE_SKB_TSTAMP) == TSNEP_TX_TYPE_SKB_TSTAMP) && |
| 848 | (skb_shinfo(entry->skb)->tx_flags & SKBTX_IN_PROGRESS) && | ||
| 849 | (__le32_to_cpu(entry->desc_wb->properties) & | 857 | (__le32_to_cpu(entry->desc_wb->properties) & |
| 850 | TSNEP_DESC_EXTENDED_WRITEBACK_FLAG)) { | 858 | TSNEP_DESC_EXTENDED_WRITEBACK_FLAG)) { |
| 851 | struct skb_shared_hwtstamps hwtstamps; | 859 | struct skb_shared_hwtstamps hwtstamps; |
| @@ -717,6 +717,11 @@ int cgx_get_rx_stats(void *cgxd, int lmac_id, int idx, u64 *rx_stat) · 716 unmodified lines | |||
| 717 | 717 | ||
| 718 | if (!is_lmac_valid(cgx, lmac_id)) | 718 | if (!is_lmac_valid(cgx, lmac_id)) |
| 719 | return -ENODEV; | 719 | return -ENODEV; |
| 720 | |||
| 721 | /* pass lmac as 0 for CGX_CMR_RX_STAT9-12 */ | ||
| 722 | if (idx >= CGX_RX_STAT_GLOBAL_INDEX) | ||
| 723 | lmac_id = 0; | ||
| 724 | |||
| 720 | *rx_stat = cgx_read(cgx, lmac_id, CGXX_CMRX_RX_STAT0 + (idx * 8)); | 725 | *rx_stat = cgx_read(cgx, lmac_id, CGXX_CMRX_RX_STAT0 + (idx * 8)); |
| 721 | return 0; | 726 | return 0; |
| 722 | } | 727 | } |
| @@ -531,7 +531,8 @@ static int cn10k_mcs_write_tx_secy(struct otx2_nic *pfvf, · 530 unmodified lines | |||
| 531 | if (sw_tx_sc->encrypt) | 531 | if (sw_tx_sc->encrypt) |
| 532 | sectag_tci |= (MCS_TCI_E | MCS_TCI_C); | 532 | sectag_tci |= (MCS_TCI_E | MCS_TCI_C); |
| 533 | 533 | ||
| 534 | policy = FIELD_PREP(MCS_TX_SECY_PLCY_MTU, secy->netdev->mtu); | 534 | policy = FIELD_PREP(MCS_TX_SECY_PLCY_MTU, |
| 535 | pfvf->netdev->mtu + OTX2_ETH_HLEN); | ||
| 535 | /* Write SecTag excluding AN bits(1..0) */ | 536 | /* Write SecTag excluding AN bits(1..0) */ |
| 536 | policy |= FIELD_PREP(MCS_TX_SECY_PLCY_ST_TCI, sectag_tci >> 2); | 537 | policy |= FIELD_PREP(MCS_TX_SECY_PLCY_ST_TCI, sectag_tci >> 2); |
| 537 | policy |= FIELD_PREP(MCS_TX_SECY_PLCY_ST_OFFSET, tag_offset); | 538 | policy |= FIELD_PREP(MCS_TX_SECY_PLCY_ST_OFFSET, tag_offset); |
| @@ -356,6 +356,7 @@ struct otx2_flow_config { · 355 unmodified lines | |||
| 356 | struct list_head flow_list_tc; | 356 | struct list_head flow_list_tc; |
| 357 | u8 ucast_flt_cnt; | 357 | u8 ucast_flt_cnt; |
| 358 | bool ntuple; | 358 | bool ntuple; |
| 359 | u16 ntuple_cnt; | ||
| 359 | }; | 360 | }; |
| 360 | 361 | ||
| 361 | struct dev_hw_ops { | 362 | struct dev_hw_ops { |
| @@ -41,6 +41,7 @@ static int otx2_dl_mcam_count_set(struct devlink *devlink, u32 id, · 40 unmodified lines | |||
| 41 | if (!pfvf->flow_cfg) | 41 | if (!pfvf->flow_cfg) |
| 42 | return 0; | 42 | return 0; |
| 43 | 43 | ||
| 44 | pfvf->flow_cfg->ntuple_cnt = ctx->val.vu16; | ||
| 44 | otx2_alloc_mcam_entries(pfvf, ctx->val.vu16); | 45 | otx2_alloc_mcam_entries(pfvf, ctx->val.vu16); |
| 45 | 46 | ||
| 46 | return 0; | 47 | return 0; |
| @@ -315,7 +315,7 @@ static void otx2_get_pauseparam(struct net_device *netdev, · 314 unmodified lines | |||
| 315 | struct otx2_nic *pfvf = netdev_priv(netdev); | 315 | struct otx2_nic *pfvf = netdev_priv(netdev); |
| 316 | struct cgx_pause_frm_cfg *req, *rsp; | 316 | struct cgx_pause_frm_cfg *req, *rsp; |
| 317 | 317 | ||
| 318 | if (is_otx2_lbkvf(pfvf->pdev)) | 318 | if (is_otx2_lbkvf(pfvf->pdev) || is_otx2_sdp_rep(pfvf->pdev)) |
| 319 | return; | 319 | return; |
| 320 | 320 | ||
| 321 | mutex_lock(&pfvf->mbox.lock); | 321 | mutex_lock(&pfvf->mbox.lock); |
| @@ -347,7 +347,7 @@ static int otx2_set_pauseparam(struct net_device *netdev, · 25 unmodified lines | |||
| 347 | if (pause->autoneg) | 347 | if (pause->autoneg) |
| 348 | return -EOPNOTSUPP; | 348 | return -EOPNOTSUPP; |
| 349 | 349 | ||
| 350 | if (is_otx2_lbkvf(pfvf->pdev)) | 350 | if (is_otx2_lbkvf(pfvf->pdev) || is_otx2_sdp_rep(pfvf->pdev)) |
| 351 | return -EOPNOTSUPP; | 351 | return -EOPNOTSUPP; |
| 352 | 352 | ||
| 353 | if (pause->rx_pause) | 353 | if (pause->rx_pause) |
| @@ -941,8 +941,8 @@ static u32 otx2_get_link(struct net_device *netdev) · 587 unmodified lines | |||
| 941 | { | 941 | { |
| 942 | struct otx2_nic *pfvf = netdev_priv(netdev); | 942 | struct otx2_nic *pfvf = netdev_priv(netdev); |
| 943 | 943 | ||
| 944 | /* LBK link is internal and always UP */ | 944 | /* LBK and SDP links are internal and always UP */ |
| 945 | if (is_otx2_lbkvf(pfvf->pdev)) | 945 | if (is_otx2_lbkvf(pfvf->pdev) || is_otx2_sdp_rep(pfvf->pdev)) |
| 946 | return 1; | 946 | return 1; |
| 947 | return pfvf->linfo.link_up; | 947 | return pfvf->linfo.link_up; |
| 948 | } | 948 | } |
| @@ -1413,7 +1413,7 @@ static int otx2vf_get_link_ksettings(struct net_device *netdev, · 464 unmodified lines | |||
| 1413 | { | 1413 | { |
| 1414 | struct otx2_nic *pfvf = netdev_priv(netdev); | 1414 | struct otx2_nic *pfvf = netdev_priv(netdev); |
| 1415 | 1415 | ||
| 1416 | if (is_otx2_lbkvf(pfvf->pdev)) { | 1416 | if (is_otx2_lbkvf(pfvf->pdev) || is_otx2_sdp_rep(pfvf->pdev)) { |
| 1417 | cmd->base.duplex = DUPLEX_FULL; | 1417 | cmd->base.duplex = DUPLEX_FULL; |
| 1418 | cmd->base.speed = SPEED_100000; | 1418 | cmd->base.speed = SPEED_100000; |
| 1419 | } else { | 1419 | } else { |
| @@ -247,7 +247,7 @@ int otx2_mcam_entry_init(struct otx2_nic *pfvf) · 246 unmodified lines | |||
| 247 | mutex_unlock(&pfvf->mbox.lock); | 247 | mutex_unlock(&pfvf->mbox.lock); |
| 248 | 248 | ||
| 249 | /* Allocate entries for Ntuple filters */ | 249 | /* Allocate entries for Ntuple filters */ |
| 250 | count = otx2_alloc_mcam_entries(pfvf, OTX2_DEFAULT_FLOWCOUNT); | 250 | count = otx2_alloc_mcam_entries(pfvf, flow_cfg->ntuple_cnt); |
| 251 | if (count <= 0) { | 251 | if (count <= 0) { |
| 252 | otx2_clear_ntuple_flow_info(pfvf, flow_cfg); | 252 | otx2_clear_ntuple_flow_info(pfvf, flow_cfg); |
| 253 | return 0; | 253 | return 0; |
| @@ -307,6 +307,7 @@ int otx2_mcam_flow_init(struct otx2_nic *pf) · 53 unmodified lines | |||
| 307 | INIT_LIST_HEAD(&pf->flow_cfg->flow_list_tc); | 307 | INIT_LIST_HEAD(&pf->flow_cfg->flow_list_tc); |
| 308 | 308 | ||
| 309 | pf->flow_cfg->ucast_flt_cnt = OTX2_DEFAULT_UNICAST_FLOWS; | 309 | pf->flow_cfg->ucast_flt_cnt = OTX2_DEFAULT_UNICAST_FLOWS; |
| 310 | pf->flow_cfg->ntuple_cnt = OTX2_DEFAULT_FLOWCOUNT; | ||
| 310 | 311 | ||
| 311 | /* Allocate bare minimum number of MCAM entries needed for | 312 | /* Allocate bare minimum number of MCAM entries needed for |
| 312 | * unicast and ntuple filters. | 313 | * unicast and ntuple filters. |
| @@ -4748,7 +4748,7 @@ static int mtk_add_mac(struct mtk_eth *eth, struct device_node *np) · 4747 unmodified lines | |||
| 4748 | } | 4748 | } |
| 4749 | 4749 | ||
| 4750 | if (mtk_is_netsys_v3_or_greater(mac->hw) && | 4750 | if (mtk_is_netsys_v3_or_greater(mac->hw) && |
| 4751 | MTK_HAS_CAPS(mac->hw->soc->caps, MTK_ESW_BIT) && | 4751 | MTK_HAS_CAPS(mac->hw->soc->caps, MTK_ESW) && |
| 4752 | id == MTK_GMAC1_ID) { | 4752 | id == MTK_GMAC1_ID) { |
| 4753 | mac->phylink_config.mac_capabilities = MAC_ASYM_PAUSE | | 4753 | mac->phylink_config.mac_capabilities = MAC_ASYM_PAUSE | |
| 4754 | MAC_SYM_PAUSE | | 4754 | MAC_SYM_PAUSE | |
| @@ -4349,6 +4349,10 @@ static netdev_features_t mlx5e_fix_uplink_rep_features(struct net_device *netdev · 4348 unmodified lines | |||
| 4349 | if (netdev->features & NETIF_F_HW_VLAN_CTAG_FILTER) | 4349 | if (netdev->features & NETIF_F_HW_VLAN_CTAG_FILTER) |
| 4350 | netdev_warn(netdev, "Disabling HW_VLAN CTAG FILTERING, not supported in switchdev mode\n"); | 4350 | netdev_warn(netdev, "Disabling HW_VLAN CTAG FILTERING, not supported in switchdev mode\n"); |
| 4351 | 4351 | ||
| 4352 | features &= ~NETIF_F_HW_MACSEC; | ||
| 4353 | if (netdev->features & NETIF_F_HW_MACSEC) | ||
| 4354 | netdev_warn(netdev, "Disabling HW MACsec offload, not supported in switchdev mode\n"); | ||
| 4355 | |||
| 4352 | return features; | 4356 | return features; |
| 4353 | } | 4357 | } |
| 4354 | 4358 | ||
| @@ -3014,6 +3014,9 @@ static int mlxsw_sp_neigh_rif_made_sync(struct mlxsw_sp *mlxsw_sp, · 3013 unmodified lines | |||
| 3014 | .rif = rif, | 3014 | .rif = rif, |
| 3015 | }; | 3015 | }; |
| 3016 | 3016 | ||
| 3017 | if (!mlxsw_sp_dev_lower_is_port(mlxsw_sp_rif_dev(rif))) | ||
| 3018 | return 0; | ||
| 3019 | |||
| 3017 | neigh_for_each(&arp_tbl, mlxsw_sp_neigh_rif_made_sync_each, &rms); | 3020 | neigh_for_each(&arp_tbl, mlxsw_sp_neigh_rif_made_sync_each, &rms); |
| 3018 | if (rms.err) | 3021 | if (rms.err) |
| 3019 | goto err_arp; | 3022 | goto err_arp; |
| @@ -203,7 +203,7 @@ static struct pci_driver qede_pci_driver = { · 202 unmodified lines | |||
| 203 | }; | 203 | }; |
| 204 | 204 | ||
| 205 | static struct qed_eth_cb_ops qede_ll_ops = { | 205 | static struct qed_eth_cb_ops qede_ll_ops = { |
| 206 | { | 206 | .common = { |
| 207 | #ifdef CONFIG_RFS_ACCEL | 207 | #ifdef CONFIG_RFS_ACCEL |
| 208 | .arfs_filter_op = qede_arfs_filter_op, | 208 | .arfs_filter_op = qede_arfs_filter_op, |
| 209 | #endif | 209 | #endif |
| @@ -1484,8 +1484,11 @@ static int qlcnic_sriov_channel_cfg_cmd(struct qlcnic_adapter *adapter, u8 cmd_o · 1483 unmodified lines | |||
| 1484 | } | 1484 | } |
| 1485 | 1485 | ||
| 1486 | cmd_op = (cmd.rsp.arg[0] & 0xff); | 1486 | cmd_op = (cmd.rsp.arg[0] & 0xff); |
| 1487 | if (cmd.rsp.arg[0] >> 25 == 2) | 1487 | if (cmd.rsp.arg[0] >> 25 == 2) { |
| 1488 | return 2; | 1488 | ret = 2; |
| 1489 | goto out; | ||
| 1490 | } | ||
| 1491 | |||
| 1489 | if (cmd_op == QLCNIC_BC_CMD_CHANNEL_INIT) | 1492 | if (cmd_op == QLCNIC_BC_CMD_CHANNEL_INIT) |
| 1490 | set_bit(QLC_BC_VF_STATE, &vf->state); | 1493 | set_bit(QLC_BC_VF_STATE, &vf->state); |
| 1491 | else | 1494 | else |
| @@ -434,14 +434,20 @@ static int wx_host_interface_command_r(struct wx *wx, u32 *buffer, · 433 unmodified lines | |||
| 434 | wr32m(wx, WX_SW2FW_MBOX_CMD, WX_SW2FW_MBOX_CMD_VLD, WX_SW2FW_MBOX_CMD_VLD); | 434 | wr32m(wx, WX_SW2FW_MBOX_CMD, WX_SW2FW_MBOX_CMD_VLD, WX_SW2FW_MBOX_CMD_VLD); |
| 435 | 435 | ||
| 436 | /* polling reply from FW */ | 436 | /* polling reply from FW */ |
| 437 | err = read_poll_timeout(wx_poll_fw_reply, reply, reply, 1000, 50000, | 437 | err = read_poll_timeout(wx_poll_fw_reply, reply, reply, 2000, |
| 438 | true, wx, buffer, send_cmd); | 438 | timeout * 1000, true, wx, buffer, send_cmd); |
| 439 | if (err) { | 439 | if (err) { |
| 440 | wx_err(wx, "Polling from FW messages timeout, cmd: 0x%x, index: %d\n", | 440 | wx_err(wx, "Polling from FW messages timeout, cmd: 0x%x, index: %d\n", |
| 441 | send_cmd, wx->swfw_index); | 441 | send_cmd, wx->swfw_index); |
| 442 | goto rel_out; | 442 | goto rel_out; |
| 443 | } | 443 | } |
| 444 | 444 | ||
| 445 | if (hdr->cmd_or_resp.ret_status == 0x80) { | ||
| 446 | wx_err(wx, "Unknown FW command: 0x%x\n", send_cmd); | ||
| 447 | err = -EINVAL; | ||
| 448 | goto rel_out; | ||
| 449 | } | ||
| 450 | |||
| 445 | /* expect no reply from FW then return */ | 451 | /* expect no reply from FW then return */ |
| 446 | if (!return_data) | 452 | if (!return_data) |
| 447 | goto rel_out; | 453 | goto rel_out; |
| @@ -99,9 +99,15 @@ static int txgbe_calc_eeprom_checksum(struct wx *wx, u16 *checksum) · 98 unmodified lines | |||
| 99 | } | 99 | } |
| 100 | local_buffer = eeprom_ptrs; | 100 | local_buffer = eeprom_ptrs; |
| 101 | 101 | ||
| 102 | for (i = 0; i < TXGBE_EEPROM_LAST_WORD; i++) | 102 | for (i = 0; i < TXGBE_EEPROM_LAST_WORD; i++) { |
| 103 | if (wx->mac.type == wx_mac_aml) { | ||
| 104 | if (i >= TXGBE_EEPROM_I2C_SRART_PTR && | ||
| 105 | i < TXGBE_EEPROM_I2C_END_PTR) | ||
| 106 | local_buffer[i] = 0xffff; | ||
| 107 | } | ||
| 103 | if (i != wx->eeprom.sw_region_offset + TXGBE_EEPROM_CHECKSUM) | 108 | if (i != wx->eeprom.sw_region_offset + TXGBE_EEPROM_CHECKSUM) |
| 104 | *checksum += local_buffer[i]; | 109 | *checksum += local_buffer[i]; |
| 110 | } | ||
| 105 | 111 | ||
| 106 | kvfree(eeprom_ptrs); | 112 | kvfree(eeprom_ptrs); |
| 107 | 113 | ||
| @@ -158,6 +158,8 @@ · 157 unmodified lines | |||
| 158 | #define TXGBE_EEPROM_VERSION_L 0x1D | 158 | #define TXGBE_EEPROM_VERSION_L 0x1D |
| 159 | #define TXGBE_EEPROM_VERSION_H 0x1E | 159 | #define TXGBE_EEPROM_VERSION_H 0x1E |
| 160 | #define TXGBE_ISCSI_BOOT_CONFIG 0x07 | 160 | #define TXGBE_ISCSI_BOOT_CONFIG 0x07 |
| 161 | #define TXGBE_EEPROM_I2C_SRART_PTR 0x580 | ||
| 162 | #define TXGBE_EEPROM_I2C_END_PTR 0x800 | ||
| 161 | 163 | ||
| 162 | #define TXGBE_MAX_MSIX_VECTORS 64 | 164 | #define TXGBE_MAX_MSIX_VECTORS 64 |
| 163 | #define TXGBE_MAX_FDIR_INDICES 63 | 165 | #define TXGBE_MAX_FDIR_INDICES 63 |
| @@ -158,7 +158,6 @@ struct hv_netvsc_packet { · 157 unmodified lines | |||
| 158 | u8 cp_partial; /* partial copy into send buffer */ | 158 | u8 cp_partial; /* partial copy into send buffer */ |
| 159 | 159 | ||
| 160 | u8 rmsg_size; /* RNDIS header and PPI size */ | 160 | u8 rmsg_size; /* RNDIS header and PPI size */ |
| 161 | u8 rmsg_pgcnt; /* page count of RNDIS header and PPI */ | ||
| 162 | u8 page_buf_cnt; | 161 | u8 page_buf_cnt; |
| 163 | 162 | ||
| 164 | u16 q_idx; | 163 | u16 q_idx; |
| @@ -893,6 +892,18 @@ struct nvsp_message { · 728 unmodified lines | |||
| 893 | sizeof(struct nvsp_message)) | 892 | sizeof(struct nvsp_message)) |
| 894 | #define NETVSC_MIN_IN_MSG_SIZE sizeof(struct vmpacket_descriptor) | 893 | #define NETVSC_MIN_IN_MSG_SIZE sizeof(struct vmpacket_descriptor) |
| 895 | 894 | ||
| 895 | /* Maximum # of contiguous data ranges that can make up a trasmitted packet. | ||
| 896 | * Typically it's the max SKB fragments plus 2 for the rndis packet and the | ||
| 897 | * linear portion of the SKB. But if MAX_SKB_FRAGS is large, the value may | ||
| 898 | * need to be limited to MAX_PAGE_BUFFER_COUNT, which is the max # of entries | ||
| 899 | * in a GPA direct packet sent to netvsp over VMBus. | ||
| 900 | */ | ||
| 901 | #if MAX_SKB_FRAGS + 2 < MAX_PAGE_BUFFER_COUNT | ||
| 902 | #define MAX_DATA_RANGES (MAX_SKB_FRAGS + 2) | ||
| 903 | #else | ||
| 904 | #define MAX_DATA_RANGES MAX_PAGE_BUFFER_COUNT | ||
| 905 | #endif | ||
| 906 | |||
| 896 | /* Estimated requestor size: | 907 | /* Estimated requestor size: |
| 897 | * out_ring_size/min_out_msg_size + in_ring_size/min_in_msg_size | 908 | * out_ring_size/min_out_msg_size + in_ring_size/min_in_msg_size |
| 898 | */ | 909 | */ |
| @@ -953,8 +953,7 @@ static void netvsc_copy_to_send_buf(struct netvsc_device *net_device, · 952 unmodified lines | |||
| 953 | + pend_size; | 953 | + pend_size; |
| 954 | int i; | 954 | int i; |
| 955 | u32 padding = 0; | 955 | u32 padding = 0; |
| 956 | u32 page_count = packet->cp_partial ? packet->rmsg_pgcnt : | 956 | u32 page_count = packet->cp_partial ? 1 : packet->page_buf_cnt; |
| 957 | packet->page_buf_cnt; | ||
| 958 | u32 remain; | 957 | u32 remain; |
| 959 | 958 | ||
| 960 | /* Add padding */ | 959 | /* Add padding */ |
| @@ -1055,6 +1054,42 @@ static int netvsc_dma_map(struct hv_device *hv_dev, · 94 unmodified lines | |||
| 1055 | return 0; | 1054 | return 0; |
| 1056 | } | 1055 | } |
| 1057 | 1056 | ||
| 1057 | /* Build an "array" of mpb entries describing the data to be transferred | ||
| 1058 | * over VMBus. After the desc header fields, each "array" entry is variable | ||
| 1059 | * size, and each entry starts after the end of the previous entry. The | ||
| 1060 | * "offset" and "len" fields for each entry imply the size of the entry. | ||
| 1061 | * | ||
| 1062 | * The pfns are in HV_HYP_PAGE_SIZE, because all communication with Hyper-V | ||
| 1063 | * uses that granularity, even if the system page size of the guest is larger. | ||
| 1064 | * Each entry in the input "pb" array must describe a contiguous range of | ||
| 1065 | * guest physical memory so that the pfns are sequential if the range crosses | ||
| 1066 | * a page boundary. The offset field must be < HV_HYP_PAGE_SIZE. | ||
| 1067 | */ | ||
| 1068 | static inline void netvsc_build_mpb_array(struct hv_page_buffer *pb, | ||
| 1069 | u32 page_buffer_count, | ||
| 1070 | struct vmbus_packet_mpb_array *desc, | ||
| 1071 | u32 *desc_size) | ||
| 1072 | { | ||
| 1073 | struct hv_mpb_array *mpb_entry = &desc->range; | ||
| 1074 | int i, j; | ||
| 1075 | |||
| 1076 | for (i = 0; i < page_buffer_count; i++) { | ||
| 1077 | u32 offset = pb[i].offset; | ||
| 1078 | u32 len = pb[i].len; | ||
| 1079 | |||
| 1080 | mpb_entry->offset = offset; | ||
| 1081 | mpb_entry->len = len; | ||
| 1082 | |||
| 1083 | for (j = 0; j < HVPFN_UP(offset + len); j++) | ||
| 1084 | mpb_entry->pfn_array[j] = pb[i].pfn + j; | ||
| 1085 | |||
| 1086 | mpb_entry = (struct hv_mpb_array *)&mpb_entry->pfn_array[j]; | ||
| 1087 | } | ||
| 1088 | |||
| 1089 | desc->rangecount = page_buffer_count; | ||
| 1090 | *desc_size = (char *)mpb_entry - (char *)desc; | ||
| 1091 | } | ||
| 1092 | |||
| 1058 | static inline int netvsc_send_pkt( | 1093 | static inline int netvsc_send_pkt( |
| 1059 | struct hv_device *device, | 1094 | struct hv_device *device, |
| 1060 | struct hv_netvsc_packet *packet, | 1095 | struct hv_netvsc_packet *packet, |
| @@ -1097,8 +1132,11 @@ static inline int netvsc_send_pkt( · 36 unmodified lines | |||
| 1097 | 1132 | ||
| 1098 | packet->dma_range = NULL; | 1133 | packet->dma_range = NULL; |
| 1099 | if (packet->page_buf_cnt) { | 1134 | if (packet->page_buf_cnt) { |
| 1135 | struct vmbus_channel_packet_page_buffer desc; | ||
| 1136 | u32 desc_size; | ||
| 1137 | |||
| 1100 | if (packet->cp_partial) | 1138 | if (packet->cp_partial) |
| 1101 | pb += packet->rmsg_pgcnt; | 1139 | pb++; |
| 1102 | 1140 | ||
| 1103 | ret = netvsc_dma_map(ndev_ctx->device_ctx, packet, pb); | 1141 | ret = netvsc_dma_map(ndev_ctx->device_ctx, packet, pb); |
| 1104 | if (ret) { | 1142 | if (ret) { |
| @@ -1106,11 +1144,12 @@ static inline int netvsc_send_pkt( · 1 unmodified line | |||
| 1106 | goto exit; | 1144 | goto exit; |
| 1107 | } | 1145 | } |
| 1108 | 1146 | ||
| 1109 | ret = vmbus_sendpacket_pagebuffer(out_channel, | 1147 | netvsc_build_mpb_array(pb, packet->page_buf_cnt, |
| 1110 | pb, packet->page_buf_cnt, | 1148 | (struct vmbus_packet_mpb_array *)&desc, |
| 1111 | &nvmsg, sizeof(nvmsg), | 1149 | &desc_size); |
| 1112 | req_id); | 1150 | ret = vmbus_sendpacket_mpb_desc(out_channel, |
| 1113 | 1151 | (struct vmbus_packet_mpb_array *)&desc, | |
| 1152 | desc_size, &nvmsg, sizeof(nvmsg), req_id); | ||
| 1114 | if (ret) | 1153 | if (ret) |
| 1115 | netvsc_dma_unmap(ndev_ctx->device_ctx, packet); | 1154 | netvsc_dma_unmap(ndev_ctx->device_ctx, packet); |
| 1116 | } else { | 1155 | } else { |
| @@ -1259,7 +1298,7 @@ int netvsc_send(struct net_device *ndev, · 142 unmodified lines | |||
| 1259 | packet->send_buf_index = section_index; | 1298 | packet->send_buf_index = section_index; |
| 1260 | 1299 | ||
| 1261 | if (packet->cp_partial) { | 1300 | if (packet->cp_partial) { |
| 1262 | packet->page_buf_cnt -= packet->rmsg_pgcnt; | 1301 | packet->page_buf_cnt--; |
| 1263 | packet->total_data_buflen = msd_len + packet->rmsg_size; | 1302 | packet->total_data_buflen = msd_len + packet->rmsg_size; |
| 1264 | } else { | 1303 | } else { |
| 1265 | packet->page_buf_cnt = 0; | 1304 | packet->page_buf_cnt = 0; |
| @@ -326,43 +326,10 @@ static u16 netvsc_select_queue(struct net_device *ndev, struct sk_buff *skb, · 325 unmodified lines | |||
| 326 | return txq; | 326 | return txq; |
| 327 | } | 327 | } |
| 328 | 328 | ||
| 329 | static u32 fill_pg_buf(unsigned long hvpfn, u32 offset, u32 len, | ||
| 330 | struct hv_page_buffer *pb) | ||
| 331 | { | ||
| 332 | int j = 0; | ||
| 333 | |||
| 334 | hvpfn += offset >> HV_HYP_PAGE_SHIFT; | ||
| 335 | offset = offset & ~HV_HYP_PAGE_MASK; | ||
| 336 | |||
| 337 | while (len > 0) { | ||
| 338 | unsigned long bytes; | ||
| 339 | |||
| 340 | bytes = HV_HYP_PAGE_SIZE - offset; | ||
| 341 | if (bytes > len) | ||
| 342 | bytes = len; | ||
| 343 | pb[j].pfn = hvpfn; | ||
| 344 | pb[j].offset = offset; | ||
| 345 | pb[j].len = bytes; | ||
| 346 | |||
| 347 | offset += bytes; | ||
| 348 | len -= bytes; | ||
| 349 | |||
| 350 | if (offset == HV_HYP_PAGE_SIZE && len) { | ||
| 351 | hvpfn++; | ||
| 352 | offset = 0; | ||
| 353 | j++; | ||
| 354 | } | ||
| 355 | } | ||
| 356 | |||
| 357 | return j + 1; | ||
| 358 | } | ||
| 359 | |||
| 360 | static u32 init_page_array(void *hdr, u32 len, struct sk_buff *skb, | 329 | static u32 init_page_array(void *hdr, u32 len, struct sk_buff *skb, |
| 361 | struct hv_netvsc_packet *packet, | 330 | struct hv_netvsc_packet *packet, |
| 362 | struct hv_page_buffer *pb) | 331 | struct hv_page_buffer *pb) |
| 363 | { | 332 | { |
| 364 | u32 slots_used = 0; | ||
| 365 | char *data = skb->data; | ||
| 366 | int frags = skb_shinfo(skb)->nr_frags; | 333 | int frags = skb_shinfo(skb)->nr_frags; |
| 367 | int i; | 334 | int i; |
| 368 | 335 | ||
| @@ -371,28 +338,27 @@ static u32 init_page_array(void *hdr, u32 len, struct sk_buff *skb, · 2 unmodified lines | |||
| 371 | * 2. skb linear data | 338 | * 2. skb linear data |
| 372 | * 3. skb fragment data | 339 | * 3. skb fragment data |
| 373 | */ | 340 | */ |
| 374 | slots_used += fill_pg_buf(virt_to_hvpfn(hdr), | ||
| 375 | offset_in_hvpage(hdr), | ||
| 376 | len, | ||
| 377 | &pb[slots_used]); | ||
| 378 | 341 | ||
| 342 | pb[0].offset = offset_in_hvpage(hdr); | ||
| 343 | pb[0].len = len; | ||
| 344 | pb[0].pfn = virt_to_hvpfn(hdr); | ||
| 379 | packet->rmsg_size = len; | 345 | packet->rmsg_size = len; |
| 380 | packet->rmsg_pgcnt = slots_used; | ||
| 381 | 346 | ||
| 382 | slots_used += fill_pg_buf(virt_to_hvpfn(data), | 347 | pb[1].offset = offset_in_hvpage(skb->data); |
| 383 | offset_in_hvpage(data), | 348 | pb[1].len = skb_headlen(skb); |
| 384 | skb_headlen(skb), | 349 | pb[1].pfn = virt_to_hvpfn(skb->data); |
| 385 | &pb[slots_used]); | ||
| 386 | 350 | ||
| 387 | for (i = 0; i < frags; i++) { | 351 | for (i = 0; i < frags; i++) { |
| 388 | skb_frag_t *frag = skb_shinfo(skb)->frags + i; | 352 | skb_frag_t *frag = skb_shinfo(skb)->frags + i; |
| 353 | struct hv_page_buffer *cur_pb = &pb[i + 2]; | ||
| 354 | u64 pfn = page_to_hvpfn(skb_frag_page(frag)); | ||
| 355 | u32 offset = skb_frag_off(frag); | ||
| 389 | 356 | ||
| 390 | slots_used += fill_pg_buf(page_to_hvpfn(skb_frag_page(frag)), | 357 | cur_pb->offset = offset_in_hvpage(offset); |
| 391 | skb_frag_off(frag), | 358 | cur_pb->len = skb_frag_size(frag); |
| 392 | skb_frag_size(frag), | 359 | cur_pb->pfn = pfn + (offset >> HV_HYP_PAGE_SHIFT); |
| 393 | &pb[slots_used]); | ||
| 394 | } | 360 | } |
| 395 | return slots_used; | 361 | return frags + 2; |
| 396 | } | 362 | } |
| 397 | 363 | ||
| 398 | static int count_skb_frag_slots(struct sk_buff *skb) | 364 | static int count_skb_frag_slots(struct sk_buff *skb) |
| @@ -483,7 +449,7 @@ static int netvsc_xmit(struct sk_buff *skb, struct net_device *net, bool xdp_tx) · 84 unmodified lines | |||
| 483 | struct net_device *vf_netdev; | 449 | struct net_device *vf_netdev; |
| 484 | u32 rndis_msg_size; | 450 | u32 rndis_msg_size; |
| 485 | u32 hash; | 451 | u32 hash; |
| 486 | struct hv_page_buffer pb[MAX_PAGE_BUFFER_COUNT]; | 452 | struct hv_page_buffer pb[MAX_DATA_RANGES]; |
| 487 | 453 | ||
| 488 | /* If VF is present and up then redirect packets to it. | 454 | /* If VF is present and up then redirect packets to it. |
| 489 | * Skip the VF if it is marked down or has no carrier. | 455 | * Skip the VF if it is marked down or has no carrier. |
| @@ -225,8 +225,7 @@ static int rndis_filter_send_request(struct rndis_device *dev, · 224 unmodified lines | |||
| 225 | struct rndis_request *req) | 225 | struct rndis_request *req) |
| 226 | { | 226 | { |
| 227 | struct hv_netvsc_packet *packet; | 227 | struct hv_netvsc_packet *packet; |
| 228 | struct hv_page_buffer page_buf[2]; | 228 | struct hv_page_buffer pb; |
| 229 | struct hv_page_buffer *pb = page_buf; | ||
| 230 | int ret; | 229 | int ret; |
| 231 | 230 | ||
| 232 | /* Setup the packet to send it */ | 231 | /* Setup the packet to send it */ |
| @@ -235,27 +234,14 @@ static int rndis_filter_send_request(struct rndis_device *dev, · 2 unmodified lines | |||
| 235 | packet->total_data_buflen = req->request_msg.msg_len; | 234 | packet->total_data_buflen = req->request_msg.msg_len; |
| 236 | packet->page_buf_cnt = 1; | 235 | packet->page_buf_cnt = 1; |
| 237 | 236 | ||
| 238 | pb[0].pfn = virt_to_phys(&req->request_msg) >> | 237 | pb.pfn = virt_to_phys(&req->request_msg) >> HV_HYP_PAGE_SHIFT; |
| 239 | HV_HYP_PAGE_SHIFT; | 238 | pb.len = req->request_msg.msg_len; |
| 240 | pb[0].len = req->request_msg.msg_len; | 239 | pb.offset = offset_in_hvpage(&req->request_msg); |
| 241 | pb[0].offset = offset_in_hvpage(&req->request_msg); | ||
| 242 | |||
| 243 | /* Add one page_buf when request_msg crossing page boundary */ | ||
| 244 | if (pb[0].offset + pb[0].len > HV_HYP_PAGE_SIZE) { | ||
| 245 | packet->page_buf_cnt++; | ||
| 246 | pb[0].len = HV_HYP_PAGE_SIZE - | ||
| 247 | pb[0].offset; | ||
| 248 | pb[1].pfn = virt_to_phys((void *)&req->request_msg | ||
| 249 | + pb[0].len) >> HV_HYP_PAGE_SHIFT; | ||
| 250 | pb[1].offset = 0; | ||
| 251 | pb[1].len = req->request_msg.msg_len - | ||
| 252 | pb[0].len; | ||
| 253 | } | ||
| 254 | 240 | ||
| 255 | trace_rndis_send(dev->ndev, 0, &req->request_msg); | 241 | trace_rndis_send(dev->ndev, 0, &req->request_msg); |
| 256 | 242 | ||
| 257 | rcu_read_lock_bh(); | 243 | rcu_read_lock_bh(); |
| 258 | ret = netvsc_send(dev->ndev, packet, NULL, pb, NULL, false); | 244 | ret = netvsc_send(dev->ndev, packet, NULL, &pb, NULL, false); |
| 259 | rcu_read_unlock_bh(); | 245 | rcu_read_unlock_bh(); |
| 260 | 246 | ||
| 261 | return ret; | 247 | return ret; |
| @@ -2027,12 +2027,6 @@ static int ksz9477_config_init(struct phy_device *phydev) · 2026 unmodified lines | |||
| 2027 | return err; | 2027 | return err; |
| 2028 | } | 2028 | } |
| 2029 | 2029 | ||
| 2030 | /* According to KSZ9477 Errata DS80000754C (Module 4) all EEE modes | ||
| 2031 | * in this switch shall be regarded as broken. | ||
| 2032 | */ | ||
| 2033 | if (phydev->dev_flags & MICREL_NO_EEE) | ||
| 2034 | phy_disable_eee(phydev); | ||
| 2035 | |||
| 2036 | return kszphy_config_init(phydev); | 2030 | return kszphy_config_init(phydev); |
| 2037 | } | 2031 | } |
| 2038 | 2032 | ||
| @@ -5705,7 +5699,6 @@ static struct phy_driver ksphy_driver[] = { · 3666 unmodified lines | |||
| 5705 | .handle_interrupt = kszphy_handle_interrupt, | 5699 | .handle_interrupt = kszphy_handle_interrupt, |
| 5706 | .suspend = genphy_suspend, | 5700 | .suspend = genphy_suspend, |
| 5707 | .resume = ksz9477_resume, | 5701 | .resume = ksz9477_resume, |
| 5708 | .get_features = ksz9477_get_features, | ||
| 5709 | } }; | 5702 | } }; |
| 5710 | 5703 | ||
| 5711 | module_phy_driver(ksphy_driver); | 5704 | module_phy_driver(ksphy_driver); |
| @@ -1011,6 +1011,7 @@ void mt76_dma_cleanup(struct mt76_dev *dev) · 1010 unmodified lines | |||
| 1011 | int i; | 1011 | int i; |
| 1012 | 1012 | ||
| 1013 | mt76_worker_disable(&dev->tx_worker); | 1013 | mt76_worker_disable(&dev->tx_worker); |
| 1014 | napi_disable(&dev->tx_napi); | ||
| 1014 | netif_napi_del(&dev->tx_napi); | 1015 | netif_napi_del(&dev->tx_napi); |
| 1015 | 1016 | ||
| 1016 | for (i = 0; i < ARRAY_SIZE(dev->phys); i++) { | 1017 | for (i = 0; i < ARRAY_SIZE(dev->phys); i++) { |
| @@ -1924,14 +1924,14 @@ mt7925_mcu_sta_cmd(struct mt76_phy *phy, · 1923 unmodified lines | |||
| 1924 | mt7925_mcu_sta_mld_tlv(skb, info->vif, info->link_sta->sta); | 1924 | mt7925_mcu_sta_mld_tlv(skb, info->vif, info->link_sta->sta); |
| 1925 | mt7925_mcu_sta_eht_mld_tlv(skb, info->vif, info->link_sta->sta); | 1925 | mt7925_mcu_sta_eht_mld_tlv(skb, info->vif, info->link_sta->sta); |
| 1926 | } | 1926 | } |
| 1927 | |||
| 1928 | mt7925_mcu_sta_hdr_trans_tlv(skb, info->vif, info->link_sta); | ||
| 1929 | } | 1927 | } |
| 1930 | 1928 | ||
| 1931 | if (!info->enable) { | 1929 | if (!info->enable) { |
| 1932 | mt7925_mcu_sta_remove_tlv(skb); | 1930 | mt7925_mcu_sta_remove_tlv(skb); |
| 1933 | mt76_connac_mcu_add_tlv(skb, STA_REC_MLD_OFF, | 1931 | mt76_connac_mcu_add_tlv(skb, STA_REC_MLD_OFF, |
| 1934 | sizeof(struct tlv)); | 1932 | sizeof(struct tlv)); |
| 1933 | } else { | ||
| 1934 | mt7925_mcu_sta_hdr_trans_tlv(skb, info->vif, info->link_sta); | ||
| 1935 | } | 1935 | } |
| 1936 | 1936 | ||
| 1937 | return mt76_mcu_skb_send_msg(dev, skb, info->cmd, true); | 1937 | return mt76_mcu_skb_send_msg(dev, skb, info->cmd, true); |
| @@ -2059,7 +2059,21 @@ static bool nvme_update_disk_info(struct nvme_ns *ns, struct nvme_id_ns *id, · 2058 unmodified lines | |||
| 2059 | if (id->nsfeat & NVME_NS_FEAT_ATOMICS && id->nawupf) | 2059 | if (id->nsfeat & NVME_NS_FEAT_ATOMICS && id->nawupf) |
| 2060 | atomic_bs = (1 + le16_to_cpu(id->nawupf)) * bs; | 2060 | atomic_bs = (1 + le16_to_cpu(id->nawupf)) * bs; |
| 2061 | else | 2061 | else |
| 2062 | atomic_bs = (1 + ns->ctrl->subsys->awupf) * bs; | 2062 | atomic_bs = (1 + ns->ctrl->awupf) * bs; |
| 2063 | |||
| 2064 | /* | ||
| 2065 | * Set subsystem atomic bs. | ||
| 2066 | */ | ||
| 2067 | if (ns->ctrl->subsys->atomic_bs) { | ||
| 2068 | if (atomic_bs != ns->ctrl->subsys->atomic_bs) { | ||
| 2069 | dev_err_ratelimited(ns->ctrl->device, | ||
| 2070 | "%s: Inconsistent Atomic Write Size, Namespace will not be added: Subsystem=%d bytes, Controller/Namespace=%d bytes\n", | ||
| 2071 | ns->disk ? ns->disk->disk_name : "?", | ||
| 2072 | ns->ctrl->subsys->atomic_bs, | ||
| 2073 | atomic_bs); | ||
| 2074 | } | ||
| 2075 | } else | ||
| 2076 | ns->ctrl->subsys->atomic_bs = atomic_bs; | ||
| 2063 | 2077 | ||
| 2064 | nvme_update_atomic_write_disk_info(ns, id, lim, bs, atomic_bs); | 2078 | nvme_update_atomic_write_disk_info(ns, id, lim, bs, atomic_bs); |
| 2065 | } | 2079 | } |
| @@ -2201,6 +2215,17 @@ static int nvme_update_ns_info_block(struct nvme_ns *ns, · 135 unmodified lines | |||
| 2201 | nvme_set_chunk_sectors(ns, id, &lim); | 2215 | nvme_set_chunk_sectors(ns, id, &lim); |
| 2202 | if (!nvme_update_disk_info(ns, id, &lim)) | 2216 | if (!nvme_update_disk_info(ns, id, &lim)) |
| 2203 | capacity = 0; | 2217 | capacity = 0; |
| 2218 | |||
| 2219 | /* | ||
| 2220 | * Validate the max atomic write size fits within the subsystem's | ||
| 2221 | * atomic write capabilities. | ||
| 2222 | */ | ||
| 2223 | if (lim.atomic_write_hw_max > ns->ctrl->subsys->atomic_bs) { | ||
| 2224 | blk_mq_unfreeze_queue(ns->disk->queue, memflags); | ||
| 2225 | ret = -ENXIO; | ||
| 2226 | goto out; | ||
| 2227 | } | ||
| 2228 | |||
| 2204 | nvme_config_discard(ns, &lim); | 2229 | nvme_config_discard(ns, &lim); |
| 2205 | if (IS_ENABLED(CONFIG_BLK_DEV_ZONED) && | 2230 | if (IS_ENABLED(CONFIG_BLK_DEV_ZONED) && |
| 2206 | ns->head->ids.csi == NVME_CSI_ZNS) | 2231 | ns->head->ids.csi == NVME_CSI_ZNS) |
| @@ -3031,7 +3056,6 @@ static int nvme_init_subsystem(struct nvme_ctrl *ctrl, struct nvme_id_ctrl *id) · 824 unmodified lines | |||
| 3031 | kfree(subsys); | 3056 | kfree(subsys); |
| 3032 | return -EINVAL; | 3057 | return -EINVAL; |
| 3033 | } | 3058 | } |
| 3034 | subsys->awupf = le16_to_cpu(id->awupf); | ||
| 3035 | nvme_mpath_default_iopolicy(subsys); | 3059 | nvme_mpath_default_iopolicy(subsys); |
| 3036 | 3060 | ||
| 3037 | subsys->dev.class = &nvme_subsys_class; | 3061 | subsys->dev.class = &nvme_subsys_class; |
| @@ -3441,7 +3465,7 @@ static int nvme_init_identify(struct nvme_ctrl *ctrl) · 403 unmodified lines | |||
| 3441 | dev_pm_qos_expose_latency_tolerance(ctrl->device); | 3465 | dev_pm_qos_expose_latency_tolerance(ctrl->device); |
| 3442 | else if (!ctrl->apst_enabled && prev_apst_enabled) | 3466 | else if (!ctrl->apst_enabled && prev_apst_enabled) |
| 3443 | dev_pm_qos_hide_latency_tolerance(ctrl->device); | 3467 | dev_pm_qos_hide_latency_tolerance(ctrl->device); |
| 3444 | 3468 | ctrl->awupf = le16_to_cpu(id->awupf); | |
| 3445 | out_free: | 3469 | out_free: |
| 3446 | kfree(id); | 3470 | kfree(id); |
| 3447 | return ret; | 3471 | return ret; |
| @@ -638,7 +638,8 @@ int nvme_mpath_alloc_disk(struct nvme_ctrl *ctrl, struct nvme_ns_head *head) · 637 unmodified lines | |||
| 638 | 638 | ||
| 639 | blk_set_stacking_limits(&lim); | 639 | blk_set_stacking_limits(&lim); |
| 640 | lim.dma_alignment = 3; | 640 | lim.dma_alignment = 3; |
| 641 | lim.features |= BLK_FEAT_IO_STAT | BLK_FEAT_NOWAIT | BLK_FEAT_POLL; | 641 | lim.features |= BLK_FEAT_IO_STAT | BLK_FEAT_NOWAIT | |
| 642 | BLK_FEAT_POLL | BLK_FEAT_ATOMIC_WRITES; | ||
| 642 | if (head->ids.csi == NVME_CSI_ZNS) | 643 | if (head->ids.csi == NVME_CSI_ZNS) |
| 643 | lim.features |= BLK_FEAT_ZONED; | 644 | lim.features |= BLK_FEAT_ZONED; |
| 644 | 645 | ||
| @@ -410,6 +410,7 @@ struct nvme_ctrl { · 409 unmodified lines | |||
| 410 | 410 | ||
| 411 | enum nvme_ctrl_type cntrltype; | 411 | enum nvme_ctrl_type cntrltype; |
| 412 | enum nvme_dctype dctype; | 412 | enum nvme_dctype dctype; |
| 413 | u16 awupf; /* 0's based value. */ | ||
| 413 | }; | 414 | }; |
| 414 | 415 | ||
| 415 | static inline enum nvme_ctrl_state nvme_ctrl_state(struct nvme_ctrl *ctrl) | 416 | static inline enum nvme_ctrl_state nvme_ctrl_state(struct nvme_ctrl *ctrl) |
| @@ -442,11 +443,11 @@ struct nvme_subsystem { · 26 unmodified lines | |||
| 442 | u8 cmic; | 443 | u8 cmic; |
| 443 | enum nvme_subsys_type subtype; | 444 | enum nvme_subsys_type subtype; |
| 444 | u16 vendor_id; | 445 | u16 vendor_id; |
| 445 | u16 awupf; /* 0's based awupf value. */ | ||
| 446 | struct ida ns_ida; | 446 | struct ida ns_ida; |
| 447 | #ifdef CONFIG_NVME_MULTIPATH | 447 | #ifdef CONFIG_NVME_MULTIPATH |
| 448 | enum nvme_iopolicy iopolicy; | 448 | enum nvme_iopolicy iopolicy; |
| 449 | #endif | 449 | #endif |
| 450 | u32 atomic_bs; | ||
| 450 | }; | 451 | }; |
| 451 | 452 | ||
| 452 | /* | 453 | /* |
| @@ -390,7 +390,7 @@ static bool nvme_dbbuf_update_and_check_event(u16 value, __le32 *dbbuf_db, · 389 unmodified lines | |||
| 390 | * as it only leads to a small amount of wasted memory for the lifetime of | 390 | * as it only leads to a small amount of wasted memory for the lifetime of |
| 391 | * the I/O. | 391 | * the I/O. |
| 392 | */ | 392 | */ |
| 393 | static int nvme_pci_npages_prp(void) | 393 | static __always_inline int nvme_pci_npages_prp(void) |
| 394 | { | 394 | { |
| 395 | unsigned max_bytes = (NVME_MAX_KB_SZ * 1024) + NVME_CTRL_PAGE_SIZE; | 395 | unsigned max_bytes = (NVME_MAX_KB_SZ * 1024) + NVME_CTRL_PAGE_SIZE; |
| 396 | unsigned nprps = DIV_ROUND_UP(max_bytes, NVME_CTRL_PAGE_SIZE); | 396 | unsigned nprps = DIV_ROUND_UP(max_bytes, NVME_CTRL_PAGE_SIZE); |
| @@ -1202,7 +1202,9 @@ static void nvme_poll_irqdisable(struct nvme_queue *nvmeq) · 805 unmodified lines | |||
| 1202 | WARN_ON_ONCE(test_bit(NVMEQ_POLLED, &nvmeq->flags)); | 1202 | WARN_ON_ONCE(test_bit(NVMEQ_POLLED, &nvmeq->flags)); |
| 1203 | 1203 | ||
| 1204 | disable_irq(pci_irq_vector(pdev, nvmeq->cq_vector)); | 1204 | disable_irq(pci_irq_vector(pdev, nvmeq->cq_vector)); |
| 1205 | spin_lock(&nvmeq->cq_poll_lock); | ||
| 1205 | nvme_poll_cq(nvmeq, NULL); | 1206 | nvme_poll_cq(nvmeq, NULL); |
| 1207 | spin_unlock(&nvmeq->cq_poll_lock); | ||
| 1206 | enable_irq(pci_irq_vector(pdev, nvmeq->cq_vector)); | 1208 | enable_irq(pci_irq_vector(pdev, nvmeq->cq_vector)); |
| 1207 | } | 1209 | } |
| 1208 | 1210 | ||
| @@ -3737,6 +3739,8 @@ static const struct pci_device_id nvme_id_table[] = { · 2528 unmodified lines | |||
| 3737 | .driver_data = NVME_QUIRK_NO_DEEPEST_PS, }, | 3739 | .driver_data = NVME_QUIRK_NO_DEEPEST_PS, }, |
| 3738 | { PCI_DEVICE(0x1e49, 0x0041), /* ZHITAI TiPro7000 NVMe SSD */ | 3740 | { PCI_DEVICE(0x1e49, 0x0041), /* ZHITAI TiPro7000 NVMe SSD */ |
| 3739 | .driver_data = NVME_QUIRK_NO_DEEPEST_PS, }, | 3741 | .driver_data = NVME_QUIRK_NO_DEEPEST_PS, }, |
| 3742 | { PCI_DEVICE(0x025e, 0xf1ac), /* SOLIDIGM P44 pro SSDPFKKW020X7 */ | ||
| 3743 | .driver_data = NVME_QUIRK_NO_DEEPEST_PS, }, | ||
| 3740 | { PCI_DEVICE(0xc0a9, 0x540a), /* Crucial P2 */ | 3744 | { PCI_DEVICE(0xc0a9, 0x540a), /* Crucial P2 */ |
| 3741 | .driver_data = NVME_QUIRK_BOGUS_NID, }, | 3745 | .driver_data = NVME_QUIRK_BOGUS_NID, }, |
| 3742 | { PCI_DEVICE(0x1d97, 0x2263), /* Lexar NM610 */ | 3746 | { PCI_DEVICE(0x1d97, 0x2263), /* Lexar NM610 */ |
| @@ -62,8 +62,7 @@ static DEFINE_MUTEX(nvmet_pci_epf_ports_mutex); · 61 unmodified lines | |||
| 62 | #define NVMET_PCI_EPF_CQ_RETRY_INTERVAL msecs_to_jiffies(1) | 62 | #define NVMET_PCI_EPF_CQ_RETRY_INTERVAL msecs_to_jiffies(1) |
| 63 | 63 | ||
| 64 | enum nvmet_pci_epf_queue_flags { | 64 | enum nvmet_pci_epf_queue_flags { |
| 65 | NVMET_PCI_EPF_Q_IS_SQ = 0, /* The queue is a submission queue */ | 65 | NVMET_PCI_EPF_Q_LIVE = 0, /* The queue is live */ |
| 66 | NVMET_PCI_EPF_Q_LIVE, /* The queue is live */ | ||
| 67 | NVMET_PCI_EPF_Q_IRQ_ENABLED, /* IRQ is enabled for this queue */ | 66 | NVMET_PCI_EPF_Q_IRQ_ENABLED, /* IRQ is enabled for this queue */ |
| 68 | }; | 67 | }; |
| 69 | 68 | ||
| @@ -596,9 +595,6 @@ static bool nvmet_pci_epf_should_raise_irq(struct nvmet_pci_epf_ctrl *ctrl, · 526 unmodified lines | |||
| 596 | struct nvmet_pci_epf_irq_vector *iv = cq->iv; | 595 | struct nvmet_pci_epf_irq_vector *iv = cq->iv; |
| 597 | bool ret; | 596 | bool ret; |
| 598 | 597 | ||
| 599 | if (!test_bit(NVMET_PCI_EPF_Q_IRQ_ENABLED, &cq->flags)) | ||
| 600 | return false; | ||
| 601 | |||
| 602 | /* IRQ coalescing for the admin queue is not allowed. */ | 598 | /* IRQ coalescing for the admin queue is not allowed. */ |
| 603 | if (!cq->qid) | 599 | if (!cq->qid) |
| 604 | return true; | 600 | return true; |
| @@ -625,7 +621,8 @@ static void nvmet_pci_epf_raise_irq(struct nvmet_pci_epf_ctrl *ctrl, · 20 unmodified lines | |||
| 625 | struct pci_epf *epf = nvme_epf->epf; | 621 | struct pci_epf *epf = nvme_epf->epf; |
| 626 | int ret = 0; | 622 | int ret = 0; |
| 627 | 623 | ||
| 628 | if (!test_bit(NVMET_PCI_EPF_Q_LIVE, &cq->flags)) | 624 | if (!test_bit(NVMET_PCI_EPF_Q_LIVE, &cq->flags) || |
| 625 | !test_bit(NVMET_PCI_EPF_Q_IRQ_ENABLED, &cq->flags)) | ||
| 629 | return; | 626 | return; |
| 630 | 627 | ||
| 631 | mutex_lock(&ctrl->irq_lock); | 628 | mutex_lock(&ctrl->irq_lock); |
| @@ -636,14 +633,16 @@ static void nvmet_pci_epf_raise_irq(struct nvmet_pci_epf_ctrl *ctrl, · 4 unmodified lines | |||
| 636 | switch (nvme_epf->irq_type) { | 633 | switch (nvme_epf->irq_type) { |
| 637 | case PCI_IRQ_MSIX: | 634 | case PCI_IRQ_MSIX: |
| 638 | case PCI_IRQ_MSI: | 635 | case PCI_IRQ_MSI: |
| 636 | /* | ||
| 637 | * If we fail to raise an MSI or MSI-X interrupt, it is likely | ||
| 638 | * because the host is using legacy INTX IRQs (e.g. BIOS, | ||
| 639 | * grub), but we can fallback to the INTX type only if the | ||
| 640 | * endpoint controller supports this type. | ||
| 641 | */ | ||
| 639 | ret = pci_epc_raise_irq(epf->epc, epf->func_no, epf->vfunc_no, | 642 | ret = pci_epc_raise_irq(epf->epc, epf->func_no, epf->vfunc_no, |
| 640 | nvme_epf->irq_type, cq->vector + 1); | 643 | nvme_epf->irq_type, cq->vector + 1); |
| 641 | if (!ret) | 644 | if (!ret || !nvme_epf->epc_features->intx_capable) |
| 642 | break; | 645 | break; |
| 643 | /* | ||
| 644 | * If we got an error, it is likely because the host is using | ||
| 645 | * legacy IRQs (e.g. BIOS, grub). | ||
| 646 | */ | ||
| 647 | fallthrough; | 646 | fallthrough; |
| 648 | case PCI_IRQ_INTX: | 647 | case PCI_IRQ_INTX: |
| 649 | ret = pci_epc_raise_irq(epf->epc, epf->func_no, epf->vfunc_no, | 648 | ret = pci_epc_raise_irq(epf->epc, epf->func_no, epf->vfunc_no, |
| @@ -656,7 +655,9 @@ static void nvmet_pci_epf_raise_irq(struct nvmet_pci_epf_ctrl *ctrl, · 6 unmodified lines | |||
| 656 | } | 655 | } |
| 657 | 656 | ||
| 658 | if (ret) | 657 | if (ret) |
| 659 | dev_err(ctrl->dev, "Failed to raise IRQ (err=%d)\n", ret); | 658 | dev_err_ratelimited(ctrl->dev, |
| 659 | "CQ[%u]: Failed to raise IRQ (err=%d)\n", | ||
| 660 | cq->qid, ret); | ||
| 660 | 661 | ||
| 661 | unlock: | 662 | unlock: |
| 662 | mutex_unlock(&ctrl->irq_lock); | 663 | mutex_unlock(&ctrl->irq_lock); |
| @@ -1319,8 +1320,14 @@ static u16 nvmet_pci_epf_create_cq(struct nvmet_ctrl *tctrl, · 656 unmodified lines | |||
| 1319 | 1320 | ||
| 1320 | set_bit(NVMET_PCI_EPF_Q_LIVE, &cq->flags); | 1321 | set_bit(NVMET_PCI_EPF_Q_LIVE, &cq->flags); |
| 1321 | 1322 | ||
| 1322 | dev_dbg(ctrl->dev, "CQ[%u]: %u entries of %zu B, IRQ vector %u\n", | 1323 | if (test_bit(NVMET_PCI_EPF_Q_IRQ_ENABLED, &cq->flags)) |
| 1323 | cqid, qsize, cq->qes, cq->vector); | 1324 | dev_dbg(ctrl->dev, |
| 1325 | "CQ[%u]: %u entries of %zu B, IRQ vector %u\n", | ||
| 1326 | cqid, qsize, cq->qes, cq->vector); | ||
| 1327 | else | ||
| 1328 | dev_dbg(ctrl->dev, | ||
| 1329 | "CQ[%u]: %u entries of %zu B, IRQ disabled\n", | ||
| 1330 | cqid, qsize, cq->qes); | ||
| 1324 | 1331 | ||
| 1325 | return NVME_SC_SUCCESS; | 1332 | return NVME_SC_SUCCESS; |
| 1326 | 1333 | ||
| @@ -1344,7 +1351,8 @@ static u16 nvmet_pci_epf_delete_cq(struct nvmet_ctrl *tctrl, u16 cqid) · 17 unmodified lines | |||
| 1344 | 1351 | ||
| 1345 | cancel_delayed_work_sync(&cq->work); | 1352 | cancel_delayed_work_sync(&cq->work); |
| 1346 | nvmet_pci_epf_drain_queue(cq); | 1353 | nvmet_pci_epf_drain_queue(cq); |
| 1347 | nvmet_pci_epf_remove_irq_vector(ctrl, cq->vector); | 1354 | if (test_and_clear_bit(NVMET_PCI_EPF_Q_IRQ_ENABLED, &cq->flags)) |
| 1355 | nvmet_pci_epf_remove_irq_vector(ctrl, cq->vector); | ||
| 1348 | nvmet_pci_epf_mem_unmap(ctrl->nvme_epf, &cq->pci_map); | 1356 | nvmet_pci_epf_mem_unmap(ctrl->nvme_epf, &cq->pci_map); |
| 1349 | 1357 | ||
| 1350 | return NVME_SC_SUCCESS; | 1358 | return NVME_SC_SUCCESS; |
| @@ -1533,7 +1541,6 @@ static void nvmet_pci_epf_init_queue(struct nvmet_pci_epf_ctrl *ctrl, · 182 unmodified lines | |||
| 1533 | 1541 | ||
| 1534 | if (sq) { | 1542 | if (sq) { |
| 1535 | queue = &ctrl->sq[qid]; | 1543 | queue = &ctrl->sq[qid]; |
| 1536 | set_bit(NVMET_PCI_EPF_Q_IS_SQ, &queue->flags); | ||
| 1537 | } else { | 1544 | } else { |
| 1538 | queue = &ctrl->cq[qid]; | 1545 | queue = &ctrl->cq[qid]; |
| 1539 | INIT_DELAYED_WORK(&queue->work, nvmet_pci_epf_cq_work); | 1546 | INIT_DELAYED_WORK(&queue->work, nvmet_pci_epf_cq_work); |
| @@ -93,6 +93,16 @@ static const struct of_device_id can_transceiver_phy_ids[] = { · 92 unmodified lines | |||
| 93 | }; | 93 | }; |
| 94 | MODULE_DEVICE_TABLE(of, can_transceiver_phy_ids); | 94 | MODULE_DEVICE_TABLE(of, can_transceiver_phy_ids); |
| 95 | 95 | ||
| 96 | /* Temporary wrapper until the multiplexer subsystem supports optional muxes */ | ||
| 97 | static inline struct mux_state * | ||
| 98 | devm_mux_state_get_optional(struct device *dev, const char *mux_name) | ||
| 99 | { | ||
| 100 | if (!of_property_present(dev->of_node, "mux-states")) | ||
| 101 | return NULL; | ||
| 102 | |||
| 103 | return devm_mux_state_get(dev, mux_name); | ||
| 104 | } | ||
| 105 | |||
| 96 | static int can_transceiver_phy_probe(struct platform_device *pdev) | 106 | static int can_transceiver_phy_probe(struct platform_device *pdev) |
| 97 | { | 107 | { |
| 98 | struct phy_provider *phy_provider; | 108 | struct phy_provider *phy_provider; |
| @@ -114,13 +124,11 @@ static int can_transceiver_phy_probe(struct platform_device *pdev) · 15 unmodified lines | |||
| 114 | match = of_match_node(can_transceiver_phy_ids, pdev->dev.of_node); | 124 | match = of_match_node(can_transceiver_phy_ids, pdev->dev.of_node); |
| 115 | drvdata = match->data; | 125 | drvdata = match->data; |
| 116 | 126 | ||
| 117 | mux_state = devm_mux_state_get(dev, NULL); | 127 | mux_state = devm_mux_state_get_optional(dev, NULL); |
| 118 | if (IS_ERR(mux_state)) { | 128 | if (IS_ERR(mux_state)) |
| 119 | if (PTR_ERR(mux_state) == -EPROBE_DEFER) | 129 | return PTR_ERR(mux_state); |
| 120 | return PTR_ERR(mux_state); | 130 | |
| 121 | } else { | 131 | can_transceiver_phy->mux_state = mux_state; |
| 122 | can_transceiver_phy->mux_state = mux_state; | ||
| 123 | } | ||
| 124 | 132 | ||
| 125 | phy = devm_phy_create(dev, dev->of_node, | 133 | phy = devm_phy_create(dev, dev->of_node, |
| 126 | &can_transceiver_phy_ops); | 134 | &can_transceiver_phy_ops); |
| @@ -1754,7 +1754,8 @@ static void qmp_ufs_init_registers(struct qmp_ufs *qmp, const struct qmp_phy_cfg · 1753 unmodified lines | |||
| 1754 | qmp_ufs_init_all(qmp, &cfg->tbls_hs_overlay[i]); | 1754 | qmp_ufs_init_all(qmp, &cfg->tbls_hs_overlay[i]); |
| 1755 | } | 1755 | } |
| 1756 | 1756 | ||
| 1757 | qmp_ufs_init_all(qmp, &cfg->tbls_hs_b); | 1757 | if (qmp->mode == PHY_MODE_UFS_HS_B) |
| 1758 | qmp_ufs_init_all(qmp, &cfg->tbls_hs_b); | ||
| 1758 | } | 1759 | } |
| 1759 | 1760 | ||
| 1760 | static int qmp_ufs_com_init(struct qmp_ufs *qmp) | 1761 | static int qmp_ufs_com_init(struct qmp_ufs *qmp) |
| @@ -9,6 +9,7 @@ · 8 unmodified lines | |||
| 9 | * Copyright (C) 2014 Cogent Embedded, Inc. | 9 | * Copyright (C) 2014 Cogent Embedded, Inc. |
| 10 | */ | 10 | */ |
| 11 | 11 | ||
| 12 | #include <linux/cleanup.h> | ||
| 12 | #include <linux/extcon-provider.h> | 13 | #include <linux/extcon-provider.h> |
| 13 | #include <linux/interrupt.h> | 14 | #include <linux/interrupt.h> |
| 14 | #include <linux/io.h> | 15 | #include <linux/io.h> |
| @@ -107,7 +108,6 @@ struct rcar_gen3_phy { · 92 unmodified lines | |||
| 107 | struct rcar_gen3_chan *ch; | 108 | struct rcar_gen3_chan *ch; |
| 108 | u32 int_enable_bits; | 109 | u32 int_enable_bits; |
| 109 | bool initialized; | 110 | bool initialized; |
| 110 | bool otg_initialized; | ||
| 111 | bool powered; | 111 | bool powered; |
| 112 | }; | 112 | }; |
| 113 | 113 | ||
| @@ -119,9 +119,8 @@ struct rcar_gen3_chan { · 5 unmodified lines | |||
| 119 | struct regulator *vbus; | 119 | struct regulator *vbus; |
| 120 | struct reset_control *rstc; | 120 | struct reset_control *rstc; |
| 121 | struct work_struct work; | 121 | struct work_struct work; |
| 122 | struct mutex lock; /* protects rphys[...].powered */ | 122 | spinlock_t lock; /* protects access to hardware and driver data structure. */ |
| 123 | enum usb_dr_mode dr_mode; | 123 | enum usb_dr_mode dr_mode; |
| 124 | int irq; | ||
| 125 | u32 obint_enable_bits; | 124 | u32 obint_enable_bits; |
| 126 | bool extcon_host; | 125 | bool extcon_host; |
| 127 | bool is_otg_channel; | 126 | bool is_otg_channel; |
| @@ -320,16 +319,15 @@ static bool rcar_gen3_is_any_rphy_initialized(struct rcar_gen3_chan *ch) · 192 unmodified lines | |||
| 320 | return false; | 319 | return false; |
| 321 | } | 320 | } |
| 322 | 321 | ||
| 323 | static bool rcar_gen3_needs_init_otg(struct rcar_gen3_chan *ch) | 322 | static bool rcar_gen3_is_any_otg_rphy_initialized(struct rcar_gen3_chan *ch) |
| 324 | { | 323 | { |
| 325 | int i; | 324 | for (enum rcar_gen3_phy_index i = PHY_INDEX_BOTH_HC; i <= PHY_INDEX_EHCI; |
| 326 | 325 | i++) { | |
| 327 | for (i = 0; i < NUM_OF_PHYS; i++) { | 326 | if (ch->rphys[i].initialized) |
| 328 | if (ch->rphys[i].otg_initialized) | 327 | return true; |
| 329 | return false; | ||
| 330 | } | 328 | } |
| 331 | 329 | ||
| 332 | return true; | 330 | return false; |
| 333 | } | 331 | } |
| 334 | 332 | ||
| 335 | static bool rcar_gen3_are_all_rphys_power_off(struct rcar_gen3_chan *ch) | 333 | static bool rcar_gen3_are_all_rphys_power_off(struct rcar_gen3_chan *ch) |
| @@ -351,7 +349,9 @@ static ssize_t role_store(struct device *dev, struct device_attribute *attr, · 15 unmodified lines | |||
| 351 | bool is_b_device; | 349 | bool is_b_device; |
| 352 | enum phy_mode cur_mode, new_mode; | 350 | enum phy_mode cur_mode, new_mode; |
| 353 | 351 | ||
| 354 | if (!ch->is_otg_channel || !rcar_gen3_is_any_rphy_initialized(ch)) | 352 | guard(spinlock_irqsave)(&ch->lock); |
| 353 | |||
| 354 | if (!ch->is_otg_channel || !rcar_gen3_is_any_otg_rphy_initialized(ch)) | ||
| 355 | return -EIO; | 355 | return -EIO; |
| 356 | 356 | ||
| 357 | if (sysfs_streq(buf, "host")) | 357 | if (sysfs_streq(buf, "host")) |
| @@ -389,7 +389,7 @@ static ssize_t role_show(struct device *dev, struct device_attribute *attr, · 31 unmodified lines | |||
| 389 | { | 389 | { |
| 390 | struct rcar_gen3_chan *ch = dev_get_drvdata(dev); | 390 | struct rcar_gen3_chan *ch = dev_get_drvdata(dev); |
| 391 | 391 | ||
| 392 | if (!ch->is_otg_channel || !rcar_gen3_is_any_rphy_initialized(ch)) | 392 | if (!ch->is_otg_channel || !rcar_gen3_is_any_otg_rphy_initialized(ch)) |
| 393 | return -EIO; | 393 | return -EIO; |
| 394 | 394 | ||
| 395 | return sprintf(buf, "%s\n", rcar_gen3_is_host(ch) ? "host" : | 395 | return sprintf(buf, "%s\n", rcar_gen3_is_host(ch) ? "host" : |
| @@ -402,6 +402,9 @@ static void rcar_gen3_init_otg(struct rcar_gen3_chan *ch) · 6 unmodified lines | |||
| 402 | void __iomem *usb2_base = ch->base; | 402 | void __iomem *usb2_base = ch->base; |
| 403 | u32 val; | 403 | u32 val; |
| 404 | 404 | ||
| 405 | if (!ch->is_otg_channel || rcar_gen3_is_any_otg_rphy_initialized(ch)) | ||
| 406 | return; | ||
| 407 | |||
| 405 | /* Should not use functions of read-modify-write a register */ | 408 | /* Should not use functions of read-modify-write a register */ |
| 406 | val = readl(usb2_base + USB2_LINECTRL1); | 409 | val = readl(usb2_base + USB2_LINECTRL1); |
| 407 | val = (val & ~USB2_LINECTRL1_DP_RPD) | USB2_LINECTRL1_DPRPD_EN | | 410 | val = (val & ~USB2_LINECTRL1_DP_RPD) | USB2_LINECTRL1_DPRPD_EN | |
| @@ -415,7 +418,7 @@ static void rcar_gen3_init_otg(struct rcar_gen3_chan *ch) · 7 unmodified lines | |||
| 415 | val = readl(usb2_base + USB2_ADPCTRL); | 418 | val = readl(usb2_base + USB2_ADPCTRL); |
| 416 | writel(val | USB2_ADPCTRL_IDPULLUP, usb2_base + USB2_ADPCTRL); | 419 | writel(val | USB2_ADPCTRL_IDPULLUP, usb2_base + USB2_ADPCTRL); |
| 417 | } | 420 | } |
| 418 | msleep(20); | 421 | mdelay(20); |
| 419 | 422 | ||
| 420 | writel(0xffffffff, usb2_base + USB2_OBINTSTA); | 423 | writel(0xffffffff, usb2_base + USB2_OBINTSTA); |
| 421 | writel(ch->obint_enable_bits, usb2_base + USB2_OBINTEN); | 424 | writel(ch->obint_enable_bits, usb2_base + USB2_OBINTEN); |
| @@ -427,16 +430,27 @@ static irqreturn_t rcar_gen3_phy_usb2_irq(int irq, void *_ch) · 5 unmodified lines | |||
| 427 | { | 430 | { |
| 428 | struct rcar_gen3_chan *ch = _ch; | 431 | struct rcar_gen3_chan *ch = _ch; |
| 429 | void __iomem *usb2_base = ch->base; | 432 | void __iomem *usb2_base = ch->base; |
| 430 | u32 status = readl(usb2_base + USB2_OBINTSTA); | 433 | struct device *dev = ch->dev; |
| 431 | irqreturn_t ret = IRQ_NONE; | 434 | irqreturn_t ret = IRQ_NONE; |
| 435 | u32 status; | ||
| 436 | |||
| 437 | pm_runtime_get_noresume(dev); | ||
| 438 | |||
| 439 | if (pm_runtime_suspended(dev)) | ||
| 440 | goto rpm_put; | ||
| 432 | 441 | ||
| 433 | if (status & ch->obint_enable_bits) { | 442 | scoped_guard(spinlock, &ch->lock) { |
| 434 | dev_vdbg(ch->dev, "%s: %08x\n", __func__, status); | 443 | status = readl(usb2_base + USB2_OBINTSTA); |
| 435 | writel(ch->obint_enable_bits, usb2_base + USB2_OBINTSTA); | 444 | if (status & ch->obint_enable_bits) { |
| 436 | rcar_gen3_device_recognition(ch); | 445 | dev_vdbg(dev, "%s: %08x\n", __func__, status); |
| 437 | ret = IRQ_HANDLED; | 446 | writel(ch->obint_enable_bits, usb2_base + USB2_OBINTSTA); |
| 447 | rcar_gen3_device_recognition(ch); | ||
| 448 | ret = IRQ_HANDLED; | ||
| 449 | } | ||
| 438 | } | 450 | } |
| 439 | 451 | ||
| 452 | rpm_put: | ||
| 453 | pm_runtime_put_noidle(dev); | ||
| 440 | return ret; | 454 | return ret; |
| 441 | } | 455 | } |
| 442 | 456 | ||
| @@ -446,32 +460,23 @@ static int rcar_gen3_phy_usb2_init(struct phy *p) · 3 unmodified lines | |||
| 446 | struct rcar_gen3_chan *channel = rphy->ch; | 460 | struct rcar_gen3_chan *channel = rphy->ch; |
| 447 | void __iomem *usb2_base = channel->base; | 461 | void __iomem *usb2_base = channel->base; |
| 448 | u32 val; | 462 | u32 val; |
| 449 | int ret; | ||
| 450 | 463 | ||
| 451 | if (!rcar_gen3_is_any_rphy_initialized(channel) && channel->irq >= 0) { | 464 | guard(spinlock_irqsave)(&channel->lock); |
| 452 | INIT_WORK(&channel->work, rcar_gen3_phy_usb2_work); | ||
| 453 | ret = request_irq(channel->irq, rcar_gen3_phy_usb2_irq, | ||
| 454 | IRQF_SHARED, dev_name(channel->dev), channel); | ||
| 455 | if (ret < 0) { | ||
| 456 | dev_err(channel->dev, "No irq handler (%d)\n", channel->irq); | ||
| 457 | return ret; | ||
| 458 | } | ||
| 459 | } | ||
| 460 | 465 | ||
| 461 | /* Initialize USB2 part */ | 466 | /* Initialize USB2 part */ |
| 462 | val = readl(usb2_base + USB2_INT_ENABLE); | 467 | val = readl(usb2_base + USB2_INT_ENABLE); |
| 463 | val |= USB2_INT_ENABLE_UCOM_INTEN | rphy->int_enable_bits; | 468 | val |= USB2_INT_ENABLE_UCOM_INTEN | rphy->int_enable_bits; |
| 464 | writel(val, usb2_base + USB2_INT_ENABLE); | 469 | writel(val, usb2_base + USB2_INT_ENABLE); |
| 465 | writel(USB2_SPD_RSM_TIMSET_INIT, usb2_base + USB2_SPD_RSM_TIMSET); | 470 | |
| 466 | writel(USB2_OC_TIMSET_INIT, usb2_base + USB2_OC_TIMSET); | 471 | if (!rcar_gen3_is_any_rphy_initialized(channel)) { |
| 467 | 472 | writel(USB2_SPD_RSM_TIMSET_INIT, usb2_base + USB2_SPD_RSM_TIMSET); | |
| 468 | /* Initialize otg part */ | 473 | writel(USB2_OC_TIMSET_INIT, usb2_base + USB2_OC_TIMSET); |
| 469 | if (channel->is_otg_channel) { | ||
| 470 | if (rcar_gen3_needs_init_otg(channel)) | ||
| 471 | rcar_gen3_init_otg(channel); | ||
| 472 | rphy->otg_initialized = true; | ||
| 473 | } | 474 | } |
| 474 | 475 | ||
| 476 | /* Initialize otg part (only if we initialize a PHY with IRQs). */ | ||
| 477 | if (rphy->int_enable_bits) | ||
| 478 | rcar_gen3_init_otg(channel); | ||
| 479 | |||
| 475 | rphy->initialized = true; | 480 | rphy->initialized = true; |
| 476 | 481 | ||
| 477 | return 0; | 482 | return 0; |
| @@ -484,10 +489,9 @@ static int rcar_gen3_phy_usb2_exit(struct phy *p) · 6 unmodified lines | |||
| 484 | void __iomem *usb2_base = channel->base; | 489 | void __iomem *usb2_base = channel->base; |
| 485 | u32 val; | 490 | u32 val; |
| 486 | 491 | ||
| 487 | rphy->initialized = false; | 492 | guard(spinlock_irqsave)(&channel->lock); |
| 488 | 493 | ||
| 489 | if (channel->is_otg_channel) | 494 | rphy->initialized = false; |
| 490 | rphy->otg_initialized = false; | ||
| 491 | 495 | ||
| 492 | val = readl(usb2_base + USB2_INT_ENABLE); | 496 | val = readl(usb2_base + USB2_INT_ENABLE); |
| 493 | val &= ~rphy->int_enable_bits; | 497 | val &= ~rphy->int_enable_bits; |
| @@ -495,9 +499,6 @@ static int rcar_gen3_phy_usb2_exit(struct phy *p) · 1 unmodified line | |||
| 495 | val &= ~USB2_INT_ENABLE_UCOM_INTEN; | 499 | val &= ~USB2_INT_ENABLE_UCOM_INTEN; |
| 496 | writel(val, usb2_base + USB2_INT_ENABLE); | 500 | writel(val, usb2_base + USB2_INT_ENABLE); |
| 497 | 501 | ||
| 498 | if (channel->irq >= 0 && !rcar_gen3_is_any_rphy_initialized(channel)) | ||
| 499 | free_irq(channel->irq, channel); | ||
| 500 | |||
| 501 | return 0; | 502 | return 0; |
| 502 | } | 503 | } |
| 503 | 504 | ||
| @@ -509,16 +510,17 @@ static int rcar_gen3_phy_usb2_power_on(struct phy *p) · 5 unmodified lines | |||
| 509 | u32 val; | 510 | u32 val; |
| 510 | int ret = 0; | 511 | int ret = 0; |
| 511 | 512 | ||
| 512 | mutex_lock(&channel->lock); | ||
| 513 | if (!rcar_gen3_are_all_rphys_power_off(channel)) | ||
| 514 | goto out; | ||
| 515 | |||
| 516 | if (channel->vbus) { | 513 | if (channel->vbus) { |
| 517 | ret = regulator_enable(channel->vbus); | 514 | ret = regulator_enable(channel->vbus); |
| 518 | if (ret) | 515 | if (ret) |
| 519 | goto out; | 516 | return ret; |
| 520 | } | 517 | } |
| 521 | 518 | ||
| 519 | guard(spinlock_irqsave)(&channel->lock); | ||
| 520 | |||
| 521 | if (!rcar_gen3_are_all_rphys_power_off(channel)) | ||
| 522 | goto out; | ||
| 523 | |||
| 522 | val = readl(usb2_base + USB2_USBCTR); | 524 | val = readl(usb2_base + USB2_USBCTR); |
| 523 | val |= USB2_USBCTR_PLL_RST; | 525 | val |= USB2_USBCTR_PLL_RST; |
| 524 | writel(val, usb2_base + USB2_USBCTR); | 526 | writel(val, usb2_base + USB2_USBCTR); |
| @@ -528,7 +530,6 @@ static int rcar_gen3_phy_usb2_power_on(struct phy *p) · 3 unmodified lines | |||
| 528 | out: | 530 | out: |
| 529 | /* The powered flag should be set for any other phys anyway */ | 531 | /* The powered flag should be set for any other phys anyway */ |
| 530 | rphy->powered = true; | 532 | rphy->powered = true; |
| 531 | mutex_unlock(&channel->lock); | ||
| 532 | 533 | ||
| 533 | return 0; | 534 | return 0; |
| 534 | } | 535 | } |
| @@ -539,18 +540,20 @@ static int rcar_gen3_phy_usb2_power_off(struct phy *p) · 4 unmodified lines | |||
| 539 | struct rcar_gen3_chan *channel = rphy->ch; | 540 | struct rcar_gen3_chan *channel = rphy->ch; |
| 540 | int ret = 0; | 541 | int ret = 0; |
| 541 | 542 | ||
| 542 | mutex_lock(&channel->lock); | 543 | scoped_guard(spinlock_irqsave, &channel->lock) { |
| 543 | rphy->powered = false; | 544 | rphy->powered = false; |
| 544 | 545 | ||
| 545 | if (!rcar_gen3_are_all_rphys_power_off(channel)) | 546 | if (rcar_gen3_are_all_rphys_power_off(channel)) { |
| 546 | goto out; | 547 | u32 val = readl(channel->base + USB2_USBCTR); |
| 548 | |||
| 549 | val |= USB2_USBCTR_PLL_RST; | ||
| 550 | writel(val, channel->base + USB2_USBCTR); | ||
| 551 | } | ||
| 552 | } | ||
| 547 | 553 | ||
| 548 | if (channel->vbus) | 554 | if (channel->vbus) |
| 549 | ret = regulator_disable(channel->vbus); | 555 | ret = regulator_disable(channel->vbus); |
| 550 | 556 | ||
| 551 | out: | ||
| 552 | mutex_unlock(&channel->lock); | ||
| 553 | |||
| 554 | return ret; | 557 | return ret; |
| 555 | } | 558 | } |
| 556 | 559 | ||
| @@ -703,7 +706,7 @@ static int rcar_gen3_phy_usb2_probe(struct platform_device *pdev) · 146 unmodified lines | |||
| 703 | struct device *dev = &pdev->dev; | 706 | struct device *dev = &pdev->dev; |
| 704 | struct rcar_gen3_chan *channel; | 707 | struct rcar_gen3_chan *channel; |
| 705 | struct phy_provider *provider; | 708 | struct phy_provider *provider; |
| 706 | int ret = 0, i; | 709 | int ret = 0, i, irq; |
| 707 | 710 | ||
| 708 | if (!dev->of_node) { | 711 | if (!dev->of_node) { |
| 709 | dev_err(dev, "This driver needs device tree\n"); | 712 | dev_err(dev, "This driver needs device tree\n"); |
| @@ -719,8 +722,6 @@ static int rcar_gen3_phy_usb2_probe(struct platform_device *pdev) · 9 unmodified lines | |||
| 719 | return PTR_ERR(channel->base); | 722 | return PTR_ERR(channel->base); |
| 720 | 723 | ||
| 721 | channel->obint_enable_bits = USB2_OBINT_BITS; | 724 | channel->obint_enable_bits = USB2_OBINT_BITS; |
| 722 | /* get irq number here and request_irq for OTG in phy_init */ | ||
| 723 | channel->irq = platform_get_irq_optional(pdev, 0); | ||
| 724 | channel->dr_mode = rcar_gen3_get_dr_mode(dev->of_node); | 725 | channel->dr_mode = rcar_gen3_get_dr_mode(dev->of_node); |
| 725 | if (channel->dr_mode != USB_DR_MODE_UNKNOWN) { | 726 | if (channel->dr_mode != USB_DR_MODE_UNKNOWN) { |
| 726 | channel->is_otg_channel = true; | 727 | channel->is_otg_channel = true; |
| @@ -763,7 +764,7 @@ static int rcar_gen3_phy_usb2_probe(struct platform_device *pdev) · 36 unmodified lines | |||
| 763 | if (phy_data->no_adp_ctrl) | 764 | if (phy_data->no_adp_ctrl) |
| 764 | channel->obint_enable_bits = USB2_OBINT_IDCHG_EN; | 765 | channel->obint_enable_bits = USB2_OBINT_IDCHG_EN; |
| 765 | 766 | ||
| 766 | mutex_init(&channel->lock); | 767 | spin_lock_init(&channel->lock); |
| 767 | for (i = 0; i < NUM_OF_PHYS; i++) { | 768 | for (i = 0; i < NUM_OF_PHYS; i++) { |
| 768 | channel->rphys[i].phy = devm_phy_create(dev, NULL, | 769 | channel->rphys[i].phy = devm_phy_create(dev, NULL, |
| 769 | phy_data->phy_usb2_ops); | 770 | phy_data->phy_usb2_ops); |
| @@ -789,6 +790,20 @@ static int rcar_gen3_phy_usb2_probe(struct platform_device *pdev) · 19 unmodified lines | |||
| 789 | channel->vbus = NULL; | 790 | channel->vbus = NULL; |
| 790 | } | 791 | } |
| 791 | 792 | ||
| 793 | irq = platform_get_irq_optional(pdev, 0); | ||
| 794 | if (irq < 0 && irq != -ENXIO) { | ||
| 795 | ret = irq; | ||
| 796 | goto error; | ||
| 797 | } else if (irq > 0) { | ||
| 798 | INIT_WORK(&channel->work, rcar_gen3_phy_usb2_work); | ||
| 799 | ret = devm_request_irq(dev, irq, rcar_gen3_phy_usb2_irq, | ||
| 800 | IRQF_SHARED, dev_name(dev), channel); | ||
| 801 | if (ret < 0) { | ||
| 802 | dev_err(dev, "Failed to request irq (%d)\n", irq); | ||
| 803 | goto error; | ||
| 804 | } | ||
| 805 | } | ||
| 806 | |||
| 792 | provider = devm_of_phy_provider_register(dev, rcar_gen3_phy_usb2_xlate); | 807 | provider = devm_of_phy_provider_register(dev, rcar_gen3_phy_usb2_xlate); |
| 793 | if (IS_ERR(provider)) { | 808 | if (IS_ERR(provider)) { |
| 794 | dev_err(dev, "Failed to register PHY provider\n"); | 809 | dev_err(dev, "Failed to register PHY provider\n"); |
| @@ -1653,7 +1653,7 @@ static __maybe_unused int samsung_mipi_dcphy_runtime_resume(struct device *dev) · 1652 unmodified lines | |||
| 1653 | return ret; | 1653 | return ret; |
| 1654 | } | 1654 | } |
| 1655 | 1655 | ||
| 1656 | clk_prepare_enable(samsung->ref_clk); | 1656 | ret = clk_prepare_enable(samsung->ref_clk); |
| 1657 | if (ret) { | 1657 | if (ret) { |
| 1658 | dev_err(samsung->dev, "Failed to enable reference clock, %d\n", ret); | 1658 | dev_err(samsung->dev, "Failed to enable reference clock, %d\n", ret); |
| 1659 | clk_disable_unprepare(samsung->pclk); | 1659 | clk_disable_unprepare(samsung->pclk); |
| @@ -476,6 +476,8 @@ static const struct ropll_config ropll_tmds_cfg[] = { · 475 unmodified lines | |||
| 476 | 1, 1, 0, 0x20, 0x0c, 1, 0x0e, 0, 0, }, | 476 | 1, 1, 0, 0x20, 0x0c, 1, 0x0e, 0, 0, }, |
| 477 | { 650000, 162, 162, 1, 1, 11, 1, 1, 1, 1, 1, 1, 1, 54, 0, 16, 4, 1, | 477 | { 650000, 162, 162, 1, 1, 11, 1, 1, 1, 1, 1, 1, 1, 54, 0, 16, 4, 1, |
| 478 | 1, 1, 0, 0x20, 0x0c, 1, 0x0e, 0, 0, }, | 478 | 1, 1, 0, 0x20, 0x0c, 1, 0x0e, 0, 0, }, |
| 479 | { 502500, 84, 84, 1, 1, 7, 1, 1, 1, 1, 1, 1, 1, 11, 1, 4, 5, | ||
| 480 | 4, 11, 1, 0, 0x20, 0x0c, 1, 0x0e, 0, 0, }, | ||
| 479 | { 337500, 0x70, 0x70, 1, 1, 0xf, 1, 1, 1, 1, 1, 1, 1, 0x2, 0, 0x01, 5, | 481 | { 337500, 0x70, 0x70, 1, 1, 0xf, 1, 1, 1, 1, 1, 1, 1, 0x2, 0, 0x01, 5, |
| 480 | 1, 1, 1, 0, 0x20, 0x0c, 1, 0x0e, 0, 0, }, | 482 | 1, 1, 1, 0, 0x20, 0x0c, 1, 0x0e, 0, 0, }, |
| 481 | { 400000, 100, 100, 1, 1, 11, 1, 1, 0, 1, 0, 1, 1, 0x9, 0, 0x05, 0, | 483 | { 400000, 100, 100, 1, 1, 11, 1, 1, 0, 1, 0, 1, 1, 0x9, 0, 0x05, 0, |
| @@ -18,6 +18,8 @@ · 17 unmodified lines | |||
| 18 | #include <linux/usb/of.h> | 18 | #include <linux/usb/of.h> |
| 19 | 19 | ||
| 20 | #define USB_125M_CLK_RATE 125000000 | 20 | #define USB_125M_CLK_RATE 125000000 |
| 21 | #define USB_CLK_MODE_OFF 0x0 | ||
| 22 | #define USB_CLK_MODE_RX_NORMAL_PWR BIT(1) | ||
| 21 | #define USB_LS_KEEPALIVE_OFF 0x4 | 23 | #define USB_LS_KEEPALIVE_OFF 0x4 |
| 22 | #define USB_LS_KEEPALIVE_ENABLE BIT(4) | 24 | #define USB_LS_KEEPALIVE_ENABLE BIT(4) |
| 23 | 25 | ||
| @@ -78,6 +80,7 @@ static int jh7110_usb2_phy_init(struct phy *_phy) · 54 unmodified lines | |||
| 78 | { | 80 | { |
| 79 | struct jh7110_usb2_phy *phy = phy_get_drvdata(_phy); | 81 | struct jh7110_usb2_phy *phy = phy_get_drvdata(_phy); |
| 80 | int ret; | 82 | int ret; |
| 83 | unsigned int val; | ||
| 81 | 84 | ||
| 82 | ret = clk_set_rate(phy->usb_125m_clk, USB_125M_CLK_RATE); | 85 | ret = clk_set_rate(phy->usb_125m_clk, USB_125M_CLK_RATE); |
| 83 | if (ret) | 86 | if (ret) |
| @@ -87,6 +90,10 @@ static int jh7110_usb2_phy_init(struct phy *_phy) · 3 unmodified lines | |||
| 87 | if (ret) | 90 | if (ret) |
| 88 | return ret; | 91 | return ret; |
| 89 | 92 | ||
| 93 | val = readl(phy->regs + USB_CLK_MODE_OFF); | ||
| 94 | val |= USB_CLK_MODE_RX_NORMAL_PWR; | ||
| 95 | writel(val, phy->regs + USB_CLK_MODE_OFF); | ||
| 96 | |||
| 90 | return 0; | 97 | return 0; |
| 91 | } | 98 | } |
| 92 | 99 | ||
| @@ -237,6 +237,8 @@ · 236 unmodified lines | |||
| 237 | #define DATA0_VAL_PD BIT(1) | 237 | #define DATA0_VAL_PD BIT(1) |
| 238 | #define USE_XUSB_AO BIT(4) | 238 | #define USE_XUSB_AO BIT(4) |
| 239 | 239 | ||
| 240 | #define TEGRA_UTMI_PAD_MAX 4 | ||
| 241 | |||
| 240 | #define TEGRA186_LANE(_name, _offset, _shift, _mask, _type) \ | 242 | #define TEGRA186_LANE(_name, _offset, _shift, _mask, _type) \ |
| 241 | { \ | 243 | { \ |
| 242 | .name = _name, \ | 244 | .name = _name, \ |
| @@ -269,7 +271,7 @@ struct tegra186_xusb_padctl { · 26 unmodified lines | |||
| 269 | 271 | ||
| 270 | /* UTMI bias and tracking */ | 272 | /* UTMI bias and tracking */ |
| 271 | struct clk *usb2_trk_clk; | 273 | struct clk *usb2_trk_clk; |
| 272 | unsigned int bias_pad_enable; | 274 | DECLARE_BITMAP(utmi_pad_enabled, TEGRA_UTMI_PAD_MAX); |
| 273 | 275 | ||
| 274 | /* padctl context */ | 276 | /* padctl context */ |
| 275 | struct tegra186_xusb_padctl_context context; | 277 | struct tegra186_xusb_padctl_context context; |
| @@ -603,12 +605,8 @@ static void tegra186_utmi_bias_pad_power_on(struct tegra_xusb_padctl *padctl) · 327 unmodified lines | |||
| 603 | u32 value; | 605 | u32 value; |
| 604 | int err; | 606 | int err; |
| 605 | 607 | ||
| 606 | mutex_lock(&padctl->lock); | 608 | if (!bitmap_empty(priv->utmi_pad_enabled, TEGRA_UTMI_PAD_MAX)) |
| 607 | |||
| 608 | if (priv->bias_pad_enable++ > 0) { | ||
| 609 | mutex_unlock(&padctl->lock); | ||
| 610 | return; | 609 | return; |
| 611 | } | ||
| 612 | 610 | ||
| 613 | err = clk_prepare_enable(priv->usb2_trk_clk); | 611 | err = clk_prepare_enable(priv->usb2_trk_clk); |
| 614 | if (err < 0) | 612 | if (err < 0) |
| @@ -658,8 +656,6 @@ static void tegra186_utmi_bias_pad_power_on(struct tegra_xusb_padctl *padctl) · 43 unmodified lines | |||
| 658 | } else { | 656 | } else { |
| 659 | clk_disable_unprepare(priv->usb2_trk_clk); | 657 | clk_disable_unprepare(priv->usb2_trk_clk); |
| 660 | } | 658 | } |
| 661 | |||
| 662 | mutex_unlock(&padctl->lock); | ||
| 663 | } | 659 | } |
| 664 | 660 | ||
| 665 | static void tegra186_utmi_bias_pad_power_off(struct tegra_xusb_padctl *padctl) | 661 | static void tegra186_utmi_bias_pad_power_off(struct tegra_xusb_padctl *padctl) |
| @@ -667,17 +663,8 @@ static void tegra186_utmi_bias_pad_power_off(struct tegra_xusb_padctl *padctl) · 1 unmodified line | |||
| 667 | struct tegra186_xusb_padctl *priv = to_tegra186_xusb_padctl(padctl); | 663 | struct tegra186_xusb_padctl *priv = to_tegra186_xusb_padctl(padctl); |
| 668 | u32 value; | 664 | u32 value; |
| 669 | 665 | ||
| 670 | mutex_lock(&padctl->lock); | 666 | if (!bitmap_empty(priv->utmi_pad_enabled, TEGRA_UTMI_PAD_MAX)) |
| 671 | |||
| 672 | if (WARN_ON(priv->bias_pad_enable == 0)) { | ||
| 673 | mutex_unlock(&padctl->lock); | ||
| 674 | return; | ||
| 675 | } | ||
| 676 | |||
| 677 | if (--priv->bias_pad_enable > 0) { | ||
| 678 | mutex_unlock(&padctl->lock); | ||
| 679 | return; | 667 | return; |
| 680 | } | ||
| 681 | 668 | ||
| 682 | value = padctl_readl(padctl, XUSB_PADCTL_USB2_BIAS_PAD_CTL1); | 669 | value = padctl_readl(padctl, XUSB_PADCTL_USB2_BIAS_PAD_CTL1); |
| 683 | value |= USB2_PD_TRK; | 670 | value |= USB2_PD_TRK; |
| @@ -690,13 +677,13 @@ static void tegra186_utmi_bias_pad_power_off(struct tegra_xusb_padctl *padctl) · 6 unmodified lines | |||
| 690 | clk_disable_unprepare(priv->usb2_trk_clk); | 677 | clk_disable_unprepare(priv->usb2_trk_clk); |
| 691 | } | 678 | } |
| 692 | 679 | ||
| 693 | mutex_unlock(&padctl->lock); | ||
| 694 | } | 680 | } |
| 695 | 681 | ||
| 696 | static void tegra186_utmi_pad_power_on(struct phy *phy) | 682 | static void tegra186_utmi_pad_power_on(struct phy *phy) |
| 697 | { | 683 | { |
| 698 | struct tegra_xusb_lane *lane = phy_get_drvdata(phy); | 684 | struct tegra_xusb_lane *lane = phy_get_drvdata(phy); |
| 699 | struct tegra_xusb_padctl *padctl = lane->pad->padctl; | 685 | struct tegra_xusb_padctl *padctl = lane->pad->padctl; |
| 686 | struct tegra186_xusb_padctl *priv = to_tegra186_xusb_padctl(padctl); | ||
| 700 | struct tegra_xusb_usb2_port *port; | 687 | struct tegra_xusb_usb2_port *port; |
| 701 | struct device *dev = padctl->dev; | 688 | struct device *dev = padctl->dev; |
| 702 | unsigned int index = lane->index; | 689 | unsigned int index = lane->index; |
| @@ -705,9 +692,16 @@ static void tegra186_utmi_pad_power_on(struct phy *phy) · 2 unmodified lines | |||
| 705 | if (!phy) | 692 | if (!phy) |
| 706 | return; | 693 | return; |
| 707 | 694 | ||
| 695 | mutex_lock(&padctl->lock); | ||
| 696 | if (test_bit(index, priv->utmi_pad_enabled)) { | ||
| 697 | mutex_unlock(&padctl->lock); | ||
| 698 | return; | ||
| 699 | } | ||
| 700 | |||
| 708 | port = tegra_xusb_find_usb2_port(padctl, index); | 701 | port = tegra_xusb_find_usb2_port(padctl, index); |
| 709 | if (!port) { | 702 | if (!port) { |
| 710 | dev_err(dev, "no port found for USB2 lane %u\n", index); | 703 | dev_err(dev, "no port found for USB2 lane %u\n", index); |
| 704 | mutex_unlock(&padctl->lock); | ||
| 711 | return; | 705 | return; |
| 712 | } | 706 | } |
| 713 | 707 | ||
| @@ -724,18 +718,28 @@ static void tegra186_utmi_pad_power_on(struct phy *phy) · 10 unmodified lines | |||
| 724 | value = padctl_readl(padctl, XUSB_PADCTL_USB2_OTG_PADX_CTL1(index)); | 718 | value = padctl_readl(padctl, XUSB_PADCTL_USB2_OTG_PADX_CTL1(index)); |
| 725 | value &= ~USB2_OTG_PD_DR; | 719 | value &= ~USB2_OTG_PD_DR; |
| 726 | padctl_writel(padctl, value, XUSB_PADCTL_USB2_OTG_PADX_CTL1(index)); | 720 | padctl_writel(padctl, value, XUSB_PADCTL_USB2_OTG_PADX_CTL1(index)); |
| 721 | |||
| 722 | set_bit(index, priv->utmi_pad_enabled); | ||
| 723 | mutex_unlock(&padctl->lock); | ||
| 727 | } | 724 | } |
| 728 | 725 | ||
| 729 | static void tegra186_utmi_pad_power_down(struct phy *phy) | 726 | static void tegra186_utmi_pad_power_down(struct phy *phy) |
| 730 | { | 727 | { |
| 731 | struct tegra_xusb_lane *lane = phy_get_drvdata(phy); | 728 | struct tegra_xusb_lane *lane = phy_get_drvdata(phy); |
| 732 | struct tegra_xusb_padctl *padctl = lane->pad->padctl; | 729 | struct tegra_xusb_padctl *padctl = lane->pad->padctl; |
| 730 | struct tegra186_xusb_padctl *priv = to_tegra186_xusb_padctl(padctl); | ||
| 733 | unsigned int index = lane->index; | 731 | unsigned int index = lane->index; |
| 734 | u32 value; | 732 | u32 value; |
| 735 | 733 | ||
| 736 | if (!phy) | 734 | if (!phy) |
| 737 | return; | 735 | return; |
| 738 | 736 | ||
| 737 | mutex_lock(&padctl->lock); | ||
| 738 | if (!test_bit(index, priv->utmi_pad_enabled)) { | ||
| 739 | mutex_unlock(&padctl->lock); | ||
| 740 | return; | ||
| 741 | } | ||
| 742 | |||
| 739 | dev_dbg(padctl->dev, "power down UTMI pad %u\n", index); | 743 | dev_dbg(padctl->dev, "power down UTMI pad %u\n", index); |
| 740 | 744 | ||
| 741 | value = padctl_readl(padctl, XUSB_PADCTL_USB2_OTG_PADX_CTL0(index)); | 745 | value = padctl_readl(padctl, XUSB_PADCTL_USB2_OTG_PADX_CTL0(index)); |
| @@ -748,7 +752,11 @@ static void tegra186_utmi_pad_power_down(struct phy *phy) · 6 unmodified lines | |||
| 748 | 752 | ||
| 749 | udelay(2); | 753 | udelay(2); |
| 750 | 754 | ||
| 755 | clear_bit(index, priv->utmi_pad_enabled); | ||
| 756 | |||
| 751 | tegra186_utmi_bias_pad_power_off(padctl); | 757 | tegra186_utmi_bias_pad_power_off(padctl); |
| 758 | |||
| 759 | mutex_unlock(&padctl->lock); | ||
| 752 | } | 760 | } |
| 753 | 761 | ||
| 754 | static int tegra186_xusb_padctl_vbus_override(struct tegra_xusb_padctl *padctl, | 762 | static int tegra186_xusb_padctl_vbus_override(struct tegra_xusb_padctl *padctl, |
| @@ -548,16 +548,16 @@ static int tegra_xusb_port_init(struct tegra_xusb_port *port, · 547 unmodified lines | |||
| 548 | 548 | ||
| 549 | err = dev_set_name(&port->dev, "%s-%u", name, index); | 549 | err = dev_set_name(&port->dev, "%s-%u", name, index); |
| 550 | if (err < 0) | 550 | if (err < 0) |
| 551 | goto unregister; | 551 | goto put_device; |
| 552 | 552 | ||
| 553 | err = device_add(&port->dev); | 553 | err = device_add(&port->dev); |
| 554 | if (err < 0) | 554 | if (err < 0) |
| 555 | goto unregister; | 555 | goto put_device; |
| 556 | 556 | ||
| 557 | return 0; | 557 | return 0; |
| 558 | 558 | ||
| 559 | unregister: | 559 | put_device: |
| 560 | device_unregister(&port->dev); | 560 | put_device(&port->dev); |
| 561 | return err; | 561 | return err; |
| 562 | } | 562 | } |
| 563 | 563 | ||
| @@ -27,9 +27,8 @@ · 26 unmodified lines | |||
| 27 | 27 | ||
| 28 | #include "hsmp.h" | 28 | #include "hsmp.h" |
| 29 | 29 | ||
| 30 | #define DRIVER_NAME "amd_hsmp" | 30 | #define DRIVER_NAME "hsmp_acpi" |
| 31 | #define DRIVER_VERSION "2.3" | 31 | #define DRIVER_VERSION "2.3" |
| 32 | #define ACPI_HSMP_DEVICE_HID "AMDI0097" | ||
| 33 | 32 | ||
| 34 | /* These are the strings specified in ACPI table */ | 33 | /* These are the strings specified in ACPI table */ |
| 35 | #define MSG_IDOFF_STR "MsgIdOffset" | 34 | #define MSG_IDOFF_STR "MsgIdOffset" |
| @@ -23,6 +23,7 @@ · 22 unmodified lines | |||
| 23 | 23 | ||
| 24 | #define HSMP_CDEV_NAME "hsmp_cdev" | 24 | #define HSMP_CDEV_NAME "hsmp_cdev" |
| 25 | #define HSMP_DEVNODE_NAME "hsmp" | 25 | #define HSMP_DEVNODE_NAME "hsmp" |
| 26 | #define ACPI_HSMP_DEVICE_HID "AMDI0097" | ||
| 26 | 27 | ||
| 27 | struct hsmp_mbaddr_info { | 28 | struct hsmp_mbaddr_info { |
| 28 | u32 base_addr; | 29 | u32 base_addr; |
| @@ -11,6 +11,7 @@ · 10 unmodified lines | |||
| 11 | 11 | ||
| 12 | #include <asm/amd/hsmp.h> | 12 | #include <asm/amd/hsmp.h> |
| 13 | 13 | ||
| 14 | #include <linux/acpi.h> | ||
| 14 | #include <linux/build_bug.h> | 15 | #include <linux/build_bug.h> |
| 15 | #include <linux/device.h> | 16 | #include <linux/device.h> |
| 16 | #include <linux/module.h> | 17 | #include <linux/module.h> |
| @@ -266,7 +267,7 @@ static bool legacy_hsmp_support(void) · 249 unmodified lines | |||
| 266 | } | 267 | } |
| 267 | case 0x1A: | 268 | case 0x1A: |
| 268 | switch (boot_cpu_data.x86_model) { | 269 | switch (boot_cpu_data.x86_model) { |
| 269 | case 0x00 ... 0x1F: | 270 | case 0x00 ... 0x0F: |
| 270 | return true; | 271 | return true; |
| 271 | default: | 272 | default: |
| 272 | return false; | 273 | return false; |
| @@ -288,6 +289,9 @@ static int __init hsmp_plt_init(void) · 15 unmodified lines | |||
| 288 | return ret; | 289 | return ret; |
| 289 | } | 290 | } |
| 290 | 291 | ||
| 292 | if (acpi_dev_present(ACPI_HSMP_DEVICE_HID, NULL, -1)) | ||
| 293 | return -ENODEV; | ||
| 294 | |||
| 291 | hsmp_pdev = get_hsmp_pdev(); | 295 | hsmp_pdev = get_hsmp_pdev(); |
| 292 | if (!hsmp_pdev) | 296 | if (!hsmp_pdev) |
| 293 | return -ENOMEM; | 297 | return -ENOMEM; |
| @@ -218,6 +218,13 @@ static const struct dmi_system_id fwbug_list[] = { · 217 unmodified lines | |||
| 218 | DMI_MATCH(DMI_BIOS_VERSION, "03.05"), | 218 | DMI_MATCH(DMI_BIOS_VERSION, "03.05"), |
| 219 | } | 219 | } |
| 220 | }, | 220 | }, |
| 221 | { | ||
| 222 | .ident = "MECHREVO Wujie 14X (GX4HRXL)", | ||
| 223 | .driver_data = &quirk_spurious_8042, | ||
| 224 | .matches = { | ||
| 225 | DMI_MATCH(DMI_BOARD_NAME, "WUJIE14-GX4HRXL"), | ||
| 226 | } | ||
| 227 | }, | ||
| 221 | {} | 228 | {} |
| 222 | }; | 229 | }; |
| 223 | 230 | ||
| @@ -334,6 +334,11 @@ static int amd_pmf_start_policy_engine(struct amd_pmf_dev *dev) · 333 unmodified lines | |||
| 334 | return 0; | 334 | return 0; |
| 335 | } | 335 | } |
| 336 | 336 | ||
| 337 | static inline bool amd_pmf_pb_valid(struct amd_pmf_dev *dev) | ||
| 338 | { | ||
| 339 | return memchr_inv(dev->policy_buf, 0xff, dev->policy_sz); | ||
| 340 | } | ||
| 341 | |||
| 337 | #ifdef CONFIG_AMD_PMF_DEBUG | 342 | #ifdef CONFIG_AMD_PMF_DEBUG |
| 338 | static void amd_pmf_hex_dump_pb(struct amd_pmf_dev *dev) | 343 | static void amd_pmf_hex_dump_pb(struct amd_pmf_dev *dev) |
| 339 | { | 344 | { |
| @@ -361,12 +366,22 @@ static ssize_t amd_pmf_get_pb_data(struct file *filp, const char __user *buf, · 21 unmodified lines | |||
| 361 | dev->policy_buf = new_policy_buf; | 366 | dev->policy_buf = new_policy_buf; |
| 362 | dev->policy_sz = length; | 367 | dev->policy_sz = length; |
| 363 | 368 | ||
| 369 | if (!amd_pmf_pb_valid(dev)) { | ||
| 370 | ret = -EINVAL; | ||
| 371 | goto cleanup; | ||
| 372 | } | ||
| 373 | |||
| 364 | amd_pmf_hex_dump_pb(dev); | 374 | amd_pmf_hex_dump_pb(dev); |
| 365 | ret = amd_pmf_start_policy_engine(dev); | 375 | ret = amd_pmf_start_policy_engine(dev); |
| 366 | if (ret < 0) | 376 | if (ret < 0) |
| 367 | return ret; | 377 | goto cleanup; |
| 368 | 378 | ||
| 369 | return length; | 379 | return length; |
| 380 | |||
| 381 | cleanup: | ||
| 382 | kfree(dev->policy_buf); | ||
| 383 | dev->policy_buf = NULL; | ||
| 384 | return ret; | ||
| 370 | } | 385 | } |
| 371 | 386 | ||
| 372 | static const struct file_operations pb_fops = { | 387 | static const struct file_operations pb_fops = { |
| @@ -528,6 +543,12 @@ int amd_pmf_init_smart_pc(struct amd_pmf_dev *dev) · 155 unmodified lines | |||
| 528 | 543 | ||
| 529 | memcpy_fromio(dev->policy_buf, dev->policy_base, dev->policy_sz); | 544 | memcpy_fromio(dev->policy_buf, dev->policy_base, dev->policy_sz); |
| 530 | 545 | ||
| 546 | if (!amd_pmf_pb_valid(dev)) { | ||
| 547 | dev_info(dev->dev, "No Smart PC policy present\n"); | ||
| 548 | ret = -EINVAL; | ||
| 549 | goto err_free_policy; | ||
| 550 | } | ||
| 551 | |||
| 531 | amd_pmf_hex_dump_pb(dev); | 552 | amd_pmf_hex_dump_pb(dev); |
| 532 | 553 | ||
| 533 | dev->prev_data = kzalloc(sizeof(*dev->prev_data), GFP_KERNEL); | 554 | dev->prev_data = kzalloc(sizeof(*dev->prev_data), GFP_KERNEL); |
| @@ -4779,7 +4779,8 @@ static int asus_wmi_add(struct platform_device *pdev) · 4778 unmodified lines | |||
| 4779 | goto fail_leds; | 4779 | goto fail_leds; |
| 4780 | 4780 | ||
| 4781 | asus_wmi_get_devstate(asus, ASUS_WMI_DEVID_WLAN, &result); | 4781 | asus_wmi_get_devstate(asus, ASUS_WMI_DEVID_WLAN, &result); |
| 4782 | if (result & (ASUS_WMI_DSTS_PRESENCE_BIT | ASUS_WMI_DSTS_USER_BIT)) | 4782 | if ((result & (ASUS_WMI_DSTS_PRESENCE_BIT | ASUS_WMI_DSTS_USER_BIT)) == |
| 4783 | (ASUS_WMI_DSTS_PRESENCE_BIT | ASUS_WMI_DSTS_USER_BIT)) | ||
| 4783 | asus->driver->wlan_ctrl_by_user = 1; | 4784 | asus->driver->wlan_ctrl_by_user = 1; |
| 4784 | 4785 | ||
| 4785 | if (!(asus->driver->wlan_ctrl_by_user && ashs_present())) { | 4786 | if (!(asus->driver->wlan_ctrl_by_user && ashs_present())) { |
| @@ -11478,6 +11478,8 @@ static int __must_check __init get_thinkpad_model_data( · 11477 unmodified lines | |||
| 11478 | tp->vendor = PCI_VENDOR_ID_IBM; | 11478 | tp->vendor = PCI_VENDOR_ID_IBM; |
| 11479 | else if (dmi_name_in_vendors("LENOVO")) | 11479 | else if (dmi_name_in_vendors("LENOVO")) |
| 11480 | tp->vendor = PCI_VENDOR_ID_LENOVO; | 11480 | tp->vendor = PCI_VENDOR_ID_LENOVO; |
| 11481 | else if (dmi_name_in_vendors("NEC")) | ||
| 11482 | tp->vendor = PCI_VENDOR_ID_LENOVO; | ||
| 11481 | else | 11483 | else |
| 11482 | return 0; | 11484 | return 0; |
| 11483 | 11485 | ||
| @@ -132,7 +132,7 @@ static int max20086_regulators_register(struct max20086 *chip) · 131 unmodified lines | |||
| 132 | 132 | ||
| 133 | static int max20086_parse_regulators_dt(struct max20086 *chip, bool *boot_on) | 133 | static int max20086_parse_regulators_dt(struct max20086 *chip, bool *boot_on) |
| 134 | { | 134 | { |
| 135 | struct of_regulator_match matches[MAX20086_MAX_REGULATORS] = { }; | 135 | struct of_regulator_match *matches; |
| 136 | struct device_node *node; | 136 | struct device_node *node; |
| 137 | unsigned int i; | 137 | unsigned int i; |
| 138 | int ret; | 138 | int ret; |
| @@ -143,6 +143,11 @@ static int max20086_parse_regulators_dt(struct max20086 *chip, bool *boot_on) · 4 unmodified lines | |||
| 143 | return -ENODEV; | 143 | return -ENODEV; |
| 144 | } | 144 | } |
| 145 | 145 | ||
| 146 | matches = devm_kcalloc(chip->dev, chip->info->num_outputs, | ||
| 147 | sizeof(*matches), GFP_KERNEL); | ||
| 148 | if (!matches) | ||
| 149 | return -ENOMEM; | ||
| 150 | |||
| 146 | for (i = 0; i < chip->info->num_outputs; ++i) | 151 | for (i = 0; i < chip->info->num_outputs; ++i) |
| 147 | matches[i].name = max20086_output_names[i]; | 152 | matches[i].name = max20086_output_names[i]; |
| 148 | 153 | ||
| @@ -169,6 +169,7 @@ static void *sd_zbc_alloc_report_buffer(struct scsi_disk *sdkp, · 168 unmodified lines | |||
| 169 | unsigned int nr_zones, size_t *buflen) | 169 | unsigned int nr_zones, size_t *buflen) |
| 170 | { | 170 | { |
| 171 | struct request_queue *q = sdkp->disk->queue; | 171 | struct request_queue *q = sdkp->disk->queue; |
| 172 | unsigned int max_segments; | ||
| 172 | size_t bufsize; | 173 | size_t bufsize; |
| 173 | void *buf; | 174 | void *buf; |
| 174 | 175 | ||
| @@ -180,12 +181,15 @@ static void *sd_zbc_alloc_report_buffer(struct scsi_disk *sdkp, · 5 unmodified lines | |||
| 180 | * Furthermore, since the report zone command cannot be split, make | 181 | * Furthermore, since the report zone command cannot be split, make |
| 181 | * sure that the allocated buffer can always be mapped by limiting the | 182 | * sure that the allocated buffer can always be mapped by limiting the |
| 182 | * number of pages allocated to the HBA max segments limit. | 183 | * number of pages allocated to the HBA max segments limit. |
| 184 | * Since max segments can be larger than the max inline bio vectors, | ||
| 185 | * further limit the allocated buffer to BIO_MAX_INLINE_VECS. | ||
| 183 | */ | 186 | */ |
| 184 | nr_zones = min(nr_zones, sdkp->zone_info.nr_zones); | 187 | nr_zones = min(nr_zones, sdkp->zone_info.nr_zones); |
| 185 | bufsize = roundup((nr_zones + 1) * 64, SECTOR_SIZE); | 188 | bufsize = roundup((nr_zones + 1) * 64, SECTOR_SIZE); |
| 186 | bufsize = min_t(size_t, bufsize, | 189 | bufsize = min_t(size_t, bufsize, |
| 187 | queue_max_hw_sectors(q) << SECTOR_SHIFT); | 190 | queue_max_hw_sectors(q) << SECTOR_SHIFT); |
| 188 | bufsize = min_t(size_t, bufsize, queue_max_segments(q) << PAGE_SHIFT); | 191 | max_segments = min(BIO_MAX_INLINE_VECS, queue_max_segments(q)); |
| 192 | bufsize = min_t(size_t, bufsize, max_segments << PAGE_SHIFT); | ||
| 189 | 193 | ||
| 190 | while (bufsize >= SECTOR_SIZE) { | 194 | while (bufsize >= SECTOR_SIZE) { |
| 191 | buf = kvzalloc(bufsize, GFP_KERNEL | __GFP_NORETRY); | 195 | buf = kvzalloc(bufsize, GFP_KERNEL | __GFP_NORETRY); |
| @@ -1819,6 +1819,7 @@ static int storvsc_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *scmnd) · 1818 unmodified lines | |||
| 1819 | return SCSI_MLQUEUE_DEVICE_BUSY; | 1819 | return SCSI_MLQUEUE_DEVICE_BUSY; |
| 1820 | } | 1820 | } |
| 1821 | 1821 | ||
| 1822 | payload->rangecount = 1; | ||
| 1822 | payload->range.len = length; | 1823 | payload->range.len = length; |
| 1823 | payload->range.offset = offset_in_hvpg; | 1824 | payload->range.offset = offset_in_hvpg; |
| 1824 | 1825 | ||
| @@ -122,6 +122,10 @@ int sdw_bus_master_add(struct sdw_bus *bus, struct device *parent, · 121 unmodified lines | |||
| 122 | set_bit(SDW_GROUP13_DEV_NUM, bus->assigned); | 122 | set_bit(SDW_GROUP13_DEV_NUM, bus->assigned); |
| 123 | set_bit(SDW_MASTER_DEV_NUM, bus->assigned); | 123 | set_bit(SDW_MASTER_DEV_NUM, bus->assigned); |
| 124 | 124 | ||
| 125 | ret = sdw_irq_create(bus, fwnode); | ||
| 126 | if (ret) | ||
| 127 | return ret; | ||
| 128 | |||
| 125 | /* | 129 | /* |
| 126 | * SDW is an enumerable bus, but devices can be powered off. So, | 130 | * SDW is an enumerable bus, but devices can be powered off. So, |
| 127 | * they won't be able to report as present. | 131 | * they won't be able to report as present. |
| @@ -138,6 +142,7 @@ int sdw_bus_master_add(struct sdw_bus *bus, struct device *parent, · 10 unmodified lines | |||
| 138 | 142 | ||
| 139 | if (ret < 0) { | 143 | if (ret < 0) { |
| 140 | dev_err(bus->dev, "Finding slaves failed:%d\n", ret); | 144 | dev_err(bus->dev, "Finding slaves failed:%d\n", ret); |
| 145 | sdw_irq_delete(bus); | ||
| 141 | return ret; | 146 | return ret; |
| 142 | } | 147 | } |
| 143 | 148 | ||
| @@ -156,10 +161,6 @@ int sdw_bus_master_add(struct sdw_bus *bus, struct device *parent, · 12 unmodified lines | |||
| 156 | bus->params.curr_bank = SDW_BANK0; | 161 | bus->params.curr_bank = SDW_BANK0; |
| 157 | bus->params.next_bank = SDW_BANK1; | 162 | bus->params.next_bank = SDW_BANK1; |
| 158 | 163 | ||
| 159 | ret = sdw_irq_create(bus, fwnode); | ||
| 160 | if (ret) | ||
| 161 | return ret; | ||
| 162 | |||
| 163 | return 0; | 164 | return 0; |
| 164 | } | 165 | } |
| 165 | EXPORT_SYMBOL(sdw_bus_master_add); | 166 | EXPORT_SYMBOL(sdw_bus_master_add); |
| @@ -420,7 +420,7 @@ MODULE_LICENSE("GPL"); · 419 unmodified lines | |||
| 420 | static void spi_test_print_hex_dump(char *pre, const void *ptr, size_t len) | 420 | static void spi_test_print_hex_dump(char *pre, const void *ptr, size_t len) |
| 421 | { | 421 | { |
| 422 | /* limit the hex_dump */ | 422 | /* limit the hex_dump */ |
| 423 | if (len < 1024) { | 423 | if (len <= 1024) { |
| 424 | print_hex_dump(KERN_INFO, pre, | 424 | print_hex_dump(KERN_INFO, pre, |
| 425 | DUMP_PREFIX_OFFSET, 16, 1, | 425 | DUMP_PREFIX_OFFSET, 16, 1, |
| 426 | ptr, len, 0); | 426 | ptr, len, 0); |
| @@ -264,6 +264,9 @@ static int sun4i_spi_transfer_one(struct spi_controller *host, · 263 unmodified lines | |||
| 264 | else | 264 | else |
| 265 | reg |= SUN4I_CTL_DHB; | 265 | reg |= SUN4I_CTL_DHB; |
| 266 | 266 | ||
| 267 | /* Now that the settings are correct, enable the interface */ | ||
| 268 | reg |= SUN4I_CTL_ENABLE; | ||
| 269 | |||
| 267 | sun4i_spi_write(sspi, SUN4I_CTL_REG, reg); | 270 | sun4i_spi_write(sspi, SUN4I_CTL_REG, reg); |
| 268 | 271 | ||
| 269 | /* Ensure that we have a parent clock fast enough */ | 272 | /* Ensure that we have a parent clock fast enough */ |
| @@ -404,7 +407,7 @@ static int sun4i_spi_runtime_resume(struct device *dev) · 134 unmodified lines | |||
| 404 | } | 407 | } |
| 405 | 408 | ||
| 406 | sun4i_spi_write(sspi, SUN4I_CTL_REG, | 409 | sun4i_spi_write(sspi, SUN4I_CTL_REG, |
| 407 | SUN4I_CTL_ENABLE | SUN4I_CTL_MASTER | SUN4I_CTL_TP); | 410 | SUN4I_CTL_MASTER | SUN4I_CTL_TP); |
| 408 | 411 | ||
| 409 | return 0; | 412 | return 0; |
| 410 | 413 | ||
| @@ -728,9 +728,9 @@ static int tegra_spi_set_hw_cs_timing(struct spi_device *spi) · 727 unmodified lines | |||
| 728 | u32 inactive_cycles; | 728 | u32 inactive_cycles; |
| 729 | u8 cs_state; | 729 | u8 cs_state; |
| 730 | 730 | ||
| 731 | if ((setup->unit && setup->unit != SPI_DELAY_UNIT_SCK) || | 731 | if ((setup->value && setup->unit != SPI_DELAY_UNIT_SCK) || |
| 732 | (hold->unit && hold->unit != SPI_DELAY_UNIT_SCK) || | 732 | (hold->value && hold->unit != SPI_DELAY_UNIT_SCK) || |
| 733 | (inactive->unit && inactive->unit != SPI_DELAY_UNIT_SCK)) { | 733 | (inactive->value && inactive->unit != SPI_DELAY_UNIT_SCK)) { |
| 734 | dev_err(&spi->dev, | 734 | dev_err(&spi->dev, |
| 735 | "Invalid delay unit %d, should be SPI_DELAY_UNIT_SCK\n", | 735 | "Invalid delay unit %d, should be SPI_DELAY_UNIT_SCK\n", |
| 736 | SPI_DELAY_UNIT_SCK); | 736 | SPI_DELAY_UNIT_SCK); |
| @@ -475,7 +475,7 @@ static void reply_ump_stream_ep_info(struct f_midi2_ep *ep) · 474 unmodified lines | |||
| 475 | /* reply a UMP EP device info */ | 475 | /* reply a UMP EP device info */ |
| 476 | static void reply_ump_stream_ep_device(struct f_midi2_ep *ep) | 476 | static void reply_ump_stream_ep_device(struct f_midi2_ep *ep) |
| 477 | { | 477 | { |
| 478 | struct snd_ump_stream_msg_devince_info rep = { | 478 | struct snd_ump_stream_msg_device_info rep = { |
| 479 | .type = UMP_MSG_TYPE_STREAM, | 479 | .type = UMP_MSG_TYPE_STREAM, |
| 480 | .status = UMP_STREAM_MSG_STATUS_DEVICE_INFO, | 480 | .status = UMP_STREAM_MSG_STATUS_DEVICE_INFO, |
| 481 | .manufacture_id = ep->info.manufacturer, | 481 | .manufacture_id = ep->info.manufacturer, |
| @@ -192,7 +192,8 @@ static inline int bch2_backpointers_maybe_flush(struct btree_trans *trans, · 191 unmodified lines | |||
| 192 | static int backpointer_target_not_found(struct btree_trans *trans, | 192 | static int backpointer_target_not_found(struct btree_trans *trans, |
| 193 | struct bkey_s_c_backpointer bp, | 193 | struct bkey_s_c_backpointer bp, |
| 194 | struct bkey_s_c target_k, | 194 | struct bkey_s_c target_k, |
| 195 | struct bkey_buf *last_flushed) | 195 | struct bkey_buf *last_flushed, |
| 196 | bool commit) | ||
| 196 | { | 197 | { |
| 197 | struct bch_fs *c = trans->c; | 198 | struct bch_fs *c = trans->c; |
| 198 | struct printbuf buf = PRINTBUF; | 199 | struct printbuf buf = PRINTBUF; |
| @@ -228,18 +229,77 @@ static int backpointer_target_not_found(struct btree_trans *trans, · 29 unmodified lines | |||
| 228 | } | 229 | } |
| 229 | 230 | ||
| 230 | if (fsck_err(trans, backpointer_to_missing_ptr, | 231 | if (fsck_err(trans, backpointer_to_missing_ptr, |
| 231 | "%s", buf.buf)) | 232 | "%s", buf.buf)) { |
| 232 | ret = bch2_backpointer_del(trans, bp.k->p); | 233 | ret = bch2_backpointer_del(trans, bp.k->p); |
| 234 | if (ret || !commit) | ||
| 235 | goto out; | ||
| 236 | |||
| 237 | /* | ||
| 238 | * Normally, on transaction commit from inside a transaction, | ||
| 239 | * we'll return -BCH_ERR_transaction_restart_nested, since a | ||
| 240 | * transaction commit invalidates pointers given out by peek(). | ||
| 241 | * | ||
| 242 | * However, since we're updating a write buffer btree, if we | ||
| 243 | * return a transaction restart and loop we won't see that the | ||
| 244 | * backpointer has been deleted without an additional write | ||
| 245 | * buffer flush - and those are expensive. | ||
| 246 | * | ||
| 247 | * So we're relying on the caller immediately advancing to the | ||
| 248 | * next backpointer and starting a new transaction immediately | ||
| 249 | * after backpointer_get_key() returns NULL: | ||
| 250 | */ | ||
| 251 | ret = bch2_trans_commit(trans, NULL, NULL, BCH_TRANS_COMMIT_no_enospc); | ||
| 252 | } | ||
| 253 | out: | ||
| 233 | fsck_err: | 254 | fsck_err: |
| 234 | printbuf_exit(&buf); | 255 | printbuf_exit(&buf); |
| 235 | return ret; | 256 | return ret; |
| 236 | } | 257 | } |
| 237 | 258 | ||
| 238 | struct bkey_s_c bch2_backpointer_get_key(struct btree_trans *trans, | 259 | static struct btree *__bch2_backpointer_get_node(struct btree_trans *trans, |
| 239 | struct bkey_s_c_backpointer bp, | 260 | struct bkey_s_c_backpointer bp, |
| 240 | struct btree_iter *iter, | 261 | struct btree_iter *iter, |
| 241 | unsigned iter_flags, | 262 | struct bkey_buf *last_flushed, |
| 242 | struct bkey_buf *last_flushed) | 263 | bool commit) |
| 264 | { | ||
| 265 | struct bch_fs *c = trans->c; | ||
| 266 | |||
| 267 | BUG_ON(!bp.v->level); | ||
| 268 | |||
| 269 | bch2_trans_node_iter_init(trans, iter, | ||
| 270 | bp.v->btree_id, | ||
| 271 | bp.v->pos, | ||
| 272 | 0, | ||
| 273 | bp.v->level - 1, | ||
| 274 | 0); | ||
| 275 | struct btree *b = bch2_btree_iter_peek_node(trans, iter); | ||
| 276 | if (IS_ERR_OR_NULL(b)) | ||
| 277 | goto err; | ||
| 278 | |||
| 279 | BUG_ON(b->c.level != bp.v->level - 1); | ||
| 280 | |||
| 281 | if (extent_matches_bp(c, bp.v->btree_id, bp.v->level, | ||
| 282 | bkey_i_to_s_c(&b->key), bp)) | ||
| 283 | return b; | ||
| 284 | |||
| 285 | if (btree_node_will_make_reachable(b)) { | ||
| 286 | b = ERR_PTR(-BCH_ERR_backpointer_to_overwritten_btree_node); | ||
| 287 | } else { | ||
| 288 | int ret = backpointer_target_not_found(trans, bp, bkey_i_to_s_c(&b->key), | ||
| 289 | last_flushed, commit); | ||
| 290 | b = ret ? ERR_PTR(ret) : NULL; | ||
| 291 | } | ||
| 292 | err: | ||
| 293 | bch2_trans_iter_exit(trans, iter); | ||
| 294 | return b; | ||
| 295 | } | ||
| 296 | |||
| 297 | static struct bkey_s_c __bch2_backpointer_get_key(struct btree_trans *trans, | ||
| 298 | struct bkey_s_c_backpointer bp, | ||
| 299 | struct btree_iter *iter, | ||
| 300 | unsigned iter_flags, | ||
| 301 | struct bkey_buf *last_flushed, | ||
| 302 | bool commit) | ||
| 243 | { | 303 | { |
| 244 | struct bch_fs *c = trans->c; | 304 | struct bch_fs *c = trans->c; |
| 245 | 305 | ||
| @@ -277,10 +337,10 @@ struct bkey_s_c bch2_backpointer_get_key(struct btree_trans *trans, · 31 unmodified lines | |||
| 277 | bch2_trans_iter_exit(trans, iter); | 337 | bch2_trans_iter_exit(trans, iter); |
| 278 | 338 | ||
| 279 | if (!bp.v->level) { | 339 | if (!bp.v->level) { |
| 280 | int ret = backpointer_target_not_found(trans, bp, k, last_flushed); | 340 | int ret = backpointer_target_not_found(trans, bp, k, last_flushed, commit); |
| 281 | return ret ? bkey_s_c_err(ret) : bkey_s_c_null; | 341 | return ret ? bkey_s_c_err(ret) : bkey_s_c_null; |
| 282 | } else { | 342 | } else { |
| 283 | struct btree *b = bch2_backpointer_get_node(trans, bp, iter, last_flushed); | 343 | struct btree *b = __bch2_backpointer_get_node(trans, bp, iter, last_flushed, commit); |
| 284 | if (b == ERR_PTR(-BCH_ERR_backpointer_to_overwritten_btree_node)) | 344 | if (b == ERR_PTR(-BCH_ERR_backpointer_to_overwritten_btree_node)) |
| 285 | return bkey_s_c_null; | 345 | return bkey_s_c_null; |
| 286 | if (IS_ERR_OR_NULL(b)) | 346 | if (IS_ERR_OR_NULL(b)) |
| @@ -295,35 +355,16 @@ struct btree *bch2_backpointer_get_node(struct btree_trans *trans, · 8 unmodified lines | |||
| 295 | struct btree_iter *iter, | 355 | struct btree_iter *iter, |
| 296 | struct bkey_buf *last_flushed) | 356 | struct bkey_buf *last_flushed) |
| 297 | { | 357 | { |
| 298 | struct bch_fs *c = trans->c; | 358 | return __bch2_backpointer_get_node(trans, bp, iter, last_flushed, true); |
| 299 | 359 | } | |
| 300 | BUG_ON(!bp.v->level); | ||
| 301 | |||
| 302 | bch2_trans_node_iter_init(trans, iter, | ||
| 303 | bp.v->btree_id, | ||
| 304 | bp.v->pos, | ||
| 305 | 0, | ||
| 306 | bp.v->level - 1, | ||
| 307 | 0); | ||
| 308 | struct btree *b = bch2_btree_iter_peek_node(trans, iter); | ||
| 309 | if (IS_ERR_OR_NULL(b)) | ||
| 310 | goto err; | ||
| 311 | |||
| 312 | BUG_ON(b->c.level != bp.v->level - 1); | ||
| 313 | |||
| 314 | if (extent_matches_bp(c, bp.v->btree_id, bp.v->level, | ||
| 315 | bkey_i_to_s_c(&b->key), bp)) | ||
| 316 | return b; | ||
| 317 | 360 | ||
| 318 | if (btree_node_will_make_reachable(b)) { | 361 | struct bkey_s_c bch2_backpointer_get_key(struct btree_trans *trans, |
| 319 | b = ERR_PTR(-BCH_ERR_backpointer_to_overwritten_btree_node); | 362 | struct bkey_s_c_backpointer bp, |
| 320 | } else { | 363 | struct btree_iter *iter, |
| 321 | int ret = backpointer_target_not_found(trans, bp, bkey_i_to_s_c(&b->key), last_flushed); | 364 | unsigned iter_flags, |
| 322 | b = ret ? ERR_PTR(ret) : NULL; | 365 | struct bkey_buf *last_flushed) |
| 323 | } | 366 | { |
| 324 | err: | 367 | return __bch2_backpointer_get_key(trans, bp, iter, iter_flags, last_flushed, true); |
| 325 | bch2_trans_iter_exit(trans, iter); | ||
| 326 | return b; | ||
| 327 | } | 368 | } |
| 328 | 369 | ||
| 329 | static int bch2_check_backpointer_has_valid_bucket(struct btree_trans *trans, struct bkey_s_c k, | 370 | static int bch2_check_backpointer_has_valid_bucket(struct btree_trans *trans, struct bkey_s_c k, |
| @@ -521,7 +562,7 @@ check_existing_bp: · 191 unmodified lines | |||
| 521 | struct bkey_s_c_backpointer other_bp = bkey_s_c_to_backpointer(bp_k); | 562 | struct bkey_s_c_backpointer other_bp = bkey_s_c_to_backpointer(bp_k); |
| 522 | 563 | ||
| 523 | struct bkey_s_c other_extent = | 564 | struct bkey_s_c other_extent = |
| 524 | bch2_backpointer_get_key(trans, other_bp, &other_extent_iter, 0, NULL); | 565 | __bch2_backpointer_get_key(trans, other_bp, &other_extent_iter, 0, NULL, false); |
| 525 | ret = bkey_err(other_extent); | 566 | ret = bkey_err(other_extent); |
| 526 | if (ret == -BCH_ERR_backpointer_to_overwritten_btree_node) | 567 | if (ret == -BCH_ERR_backpointer_to_overwritten_btree_node) |
| 527 | ret = 0; | 568 | ret = 0; |
| @@ -852,7 +852,6 @@ out: · 851 unmodified lines | |||
| 852 | b->sib_u64s[1] = 0; | 852 | b->sib_u64s[1] = 0; |
| 853 | b->whiteout_u64s = 0; | 853 | b->whiteout_u64s = 0; |
| 854 | bch2_btree_keys_init(b); | 854 | bch2_btree_keys_init(b); |
| 855 | set_btree_node_accessed(b); | ||
| 856 | 855 | ||
| 857 | bch2_time_stats_update(&c->times[BCH_TIME_btree_node_mem_alloc], | 856 | bch2_time_stats_update(&c->times[BCH_TIME_btree_node_mem_alloc], |
| 858 | start_time); | 857 | start_time); |
| @@ -1286,6 +1285,10 @@ lock_node: · 427 unmodified lines | |||
| 1286 | six_unlock_read(&b->c.lock); | 1285 | six_unlock_read(&b->c.lock); |
| 1287 | goto retry; | 1286 | goto retry; |
| 1288 | } | 1287 | } |
| 1288 | |||
| 1289 | /* avoid atomic set bit if it's not needed: */ | ||
| 1290 | if (!btree_node_accessed(b)) | ||
| 1291 | set_btree_node_accessed(b); | ||
| 1289 | } | 1292 | } |
| 1290 | 1293 | ||
| 1291 | /* XXX: waiting on IO with btree locks held: */ | 1294 | /* XXX: waiting on IO with btree locks held: */ |
| @@ -1301,10 +1304,6 @@ lock_node: · 9 unmodified lines | |||
| 1301 | prefetch(p + L1_CACHE_BYTES * 2); | 1304 | prefetch(p + L1_CACHE_BYTES * 2); |
| 1302 | } | 1305 | } |
| 1303 | 1306 | ||
| 1304 | /* avoid atomic set bit if it's not needed: */ | ||
| 1305 | if (!btree_node_accessed(b)) | ||
| 1306 | set_btree_node_accessed(b); | ||
| 1307 | |||
| 1308 | if (unlikely(btree_node_read_error(b))) { | 1307 | if (unlikely(btree_node_read_error(b))) { |
| 1309 | six_unlock_read(&b->c.lock); | 1308 | six_unlock_read(&b->c.lock); |
| 1310 | b = ERR_PTR(-BCH_ERR_btree_node_read_err_cached); | 1309 | b = ERR_PTR(-BCH_ERR_btree_node_read_err_cached); |
| @@ -1971,6 +1971,12 @@ struct btree *bch2_btree_iter_next_node(struct btree_trans *trans, struct btree_ · 1970 unmodified lines | |||
| 1971 | return NULL; | 1971 | return NULL; |
| 1972 | } | 1972 | } |
| 1973 | 1973 | ||
| 1974 | /* | ||
| 1975 | * We don't correctly handle nodes with extra intent locks here: | ||
| 1976 | * downgrade so we don't violate locking invariants | ||
| 1977 | */ | ||
| 1978 | bch2_btree_path_downgrade(trans, path); | ||
| 1979 | |||
| 1974 | if (!bch2_btree_node_relock(trans, path, path->level + 1)) { | 1980 | if (!bch2_btree_node_relock(trans, path, path->level + 1)) { |
| 1975 | __bch2_btree_path_unlock(trans, path); | 1981 | __bch2_btree_path_unlock(trans, path); |
| 1976 | path->l[path->level].b = ERR_PTR(-BCH_ERR_no_btree_node_relock); | 1982 | path->l[path->level].b = ERR_PTR(-BCH_ERR_no_btree_node_relock); |
| @@ -2743,7 +2749,7 @@ struct bkey_s_c bch2_btree_iter_peek_slot(struct btree_trans *trans, struct btre · 766 unmodified lines | |||
| 2743 | ret = trans_maybe_inject_restart(trans, _RET_IP_); | 2749 | ret = trans_maybe_inject_restart(trans, _RET_IP_); |
| 2744 | if (unlikely(ret)) { | 2750 | if (unlikely(ret)) { |
| 2745 | k = bkey_s_c_err(ret); | 2751 | k = bkey_s_c_err(ret); |
| 2746 | goto out_no_locked; | 2752 | goto out; |
| 2747 | } | 2753 | } |
| 2748 | 2754 | ||
| 2749 | /* extents can't span inode numbers: */ | 2755 | /* extents can't span inode numbers: */ |
| @@ -2763,13 +2769,15 @@ struct bkey_s_c bch2_btree_iter_peek_slot(struct btree_trans *trans, struct btre · 13 unmodified lines | |||
| 2763 | ret = bch2_btree_path_traverse(trans, iter->path, iter->flags); | 2769 | ret = bch2_btree_path_traverse(trans, iter->path, iter->flags); |
| 2764 | if (unlikely(ret)) { | 2770 | if (unlikely(ret)) { |
| 2765 | k = bkey_s_c_err(ret); | 2771 | k = bkey_s_c_err(ret); |
| 2766 | goto out_no_locked; | 2772 | goto out; |
| 2767 | } | 2773 | } |
| 2768 | 2774 | ||
| 2769 | struct btree_path *path = btree_iter_path(trans, iter); | 2775 | struct btree_path *path = btree_iter_path(trans, iter); |
| 2770 | if (unlikely(!btree_path_node(path, path->level))) | 2776 | if (unlikely(!btree_path_node(path, path->level))) |
| 2771 | return bkey_s_c_null; | 2777 | return bkey_s_c_null; |
| 2772 | 2778 | ||
| 2779 | btree_path_set_should_be_locked(trans, path); | ||
| 2780 | |||
| 2773 | if ((iter->flags & BTREE_ITER_cached) || | 2781 | if ((iter->flags & BTREE_ITER_cached) || |
| 2774 | !(iter->flags & (BTREE_ITER_is_extents|BTREE_ITER_filter_snapshots))) { | 2782 | !(iter->flags & (BTREE_ITER_is_extents|BTREE_ITER_filter_snapshots))) { |
| 2775 | k = bkey_s_c_null; | 2783 | k = bkey_s_c_null; |
| @@ -2790,12 +2798,12 @@ struct bkey_s_c bch2_btree_iter_peek_slot(struct btree_trans *trans, struct btre · 14 unmodified lines | |||
| 2790 | if (!bkey_err(k)) | 2798 | if (!bkey_err(k)) |
| 2791 | iter->k = *k.k; | 2799 | iter->k = *k.k; |
| 2792 | /* We're not returning a key from iter->path: */ | 2800 | /* We're not returning a key from iter->path: */ |
| 2793 | goto out_no_locked; | 2801 | goto out; |
| 2794 | } | 2802 | } |
| 2795 | 2803 | ||
| 2796 | k = bch2_btree_path_peek_slot(trans->paths + iter->path, &iter->k); | 2804 | k = bch2_btree_path_peek_slot(btree_iter_path(trans, iter), &iter->k); |
| 2797 | if (unlikely(!k.k)) | 2805 | if (unlikely(!k.k)) |
| 2798 | goto out_no_locked; | 2806 | goto out; |
| 2799 | 2807 | ||
| 2800 | if (unlikely(k.k->type == KEY_TYPE_whiteout && | 2808 | if (unlikely(k.k->type == KEY_TYPE_whiteout && |
| 2801 | (iter->flags & BTREE_ITER_filter_snapshots) && | 2809 | (iter->flags & BTREE_ITER_filter_snapshots) && |
| @@ -2833,7 +2841,7 @@ struct bkey_s_c bch2_btree_iter_peek_slot(struct btree_trans *trans, struct btre · 31 unmodified lines | |||
| 2833 | } | 2841 | } |
| 2834 | 2842 | ||
| 2835 | if (unlikely(bkey_err(k))) | 2843 | if (unlikely(bkey_err(k))) |
| 2836 | goto out_no_locked; | 2844 | goto out; |
| 2837 | 2845 | ||
| 2838 | next = k.k ? bkey_start_pos(k.k) : POS_MAX; | 2846 | next = k.k ? bkey_start_pos(k.k) : POS_MAX; |
| 2839 | 2847 | ||
| @@ -2855,8 +2863,6 @@ struct bkey_s_c bch2_btree_iter_peek_slot(struct btree_trans *trans, struct btre · 15 unmodified lines | |||
| 2855 | } | 2863 | } |
| 2856 | } | 2864 | } |
| 2857 | out: | 2865 | out: |
| 2858 | btree_path_set_should_be_locked(trans, btree_iter_path(trans, iter)); | ||
| 2859 | out_no_locked: | ||
| 2860 | bch2_btree_iter_verify_entry_exit(iter); | 2866 | bch2_btree_iter_verify_entry_exit(iter); |
| 2861 | bch2_btree_iter_verify(trans, iter); | 2867 | bch2_btree_iter_verify(trans, iter); |
| 2862 | ret = bch2_btree_iter_verify_ret(trans, iter, k); | 2868 | ret = bch2_btree_iter_verify_ret(trans, iter, k); |
| @@ -376,6 +376,19 @@ int bch2_accounting_mem_insert(struct bch_fs *c, struct bkey_s_c_accounting a, · 375 unmodified lines | |||
| 376 | return ret; | 376 | return ret; |
| 377 | } | 377 | } |
| 378 | 378 | ||
| 379 | int bch2_accounting_mem_insert_locked(struct bch_fs *c, struct bkey_s_c_accounting a, | ||
| 380 | enum bch_accounting_mode mode) | ||
| 381 | { | ||
| 382 | struct bch_replicas_padded r; | ||
| 383 | |||
| 384 | if (mode != BCH_ACCOUNTING_read && | ||
| 385 | accounting_to_replicas(&r.e, a.k->p) && | ||
| 386 | !bch2_replicas_marked_locked(c, &r.e)) | ||
| 387 | return -BCH_ERR_btree_insert_need_mark_replicas; | ||
| 388 | |||
| 389 | return __bch2_accounting_mem_insert(c, a); | ||
| 390 | } | ||
| 391 | |||
| 379 | static bool accounting_mem_entry_is_zero(struct accounting_mem_entry *e) | 392 | static bool accounting_mem_entry_is_zero(struct accounting_mem_entry *e) |
| 380 | { | 393 | { |
| 381 | for (unsigned i = 0; i < e->nr_counters; i++) | 394 | for (unsigned i = 0; i < e->nr_counters; i++) |
| @@ -583,7 +596,7 @@ int bch2_gc_accounting_done(struct bch_fs *c) · 201 unmodified lines | |||
| 583 | accounting_key_init(&k_i.k, &acc_k, src_v, nr); | 596 | accounting_key_init(&k_i.k, &acc_k, src_v, nr); |
| 584 | bch2_accounting_mem_mod_locked(trans, | 597 | bch2_accounting_mem_mod_locked(trans, |
| 585 | bkey_i_to_s_c_accounting(&k_i.k), | 598 | bkey_i_to_s_c_accounting(&k_i.k), |
| 586 | BCH_ACCOUNTING_normal); | 599 | BCH_ACCOUNTING_normal, true); |
| 587 | 600 | ||
| 588 | preempt_disable(); | 601 | preempt_disable(); |
| 589 | struct bch_fs_usage_base *dst = this_cpu_ptr(c->usage); | 602 | struct bch_fs_usage_base *dst = this_cpu_ptr(c->usage); |
| @@ -612,7 +625,7 @@ static int accounting_read_key(struct btree_trans *trans, struct bkey_s_c k) · 22 unmodified lines | |||
| 612 | 625 | ||
| 613 | percpu_down_read(&c->mark_lock); | 626 | percpu_down_read(&c->mark_lock); |
| 614 | int ret = bch2_accounting_mem_mod_locked(trans, bkey_s_c_to_accounting(k), | 627 | int ret = bch2_accounting_mem_mod_locked(trans, bkey_s_c_to_accounting(k), |
| 615 | BCH_ACCOUNTING_read); | 628 | BCH_ACCOUNTING_read, false); |
| 616 | percpu_up_read(&c->mark_lock); | 629 | percpu_up_read(&c->mark_lock); |
| 617 | return ret; | 630 | return ret; |
| 618 | } | 631 | } |
| @@ -136,6 +136,7 @@ enum bch_accounting_mode { · 135 unmodified lines | |||
| 136 | }; | 136 | }; |
| 137 | 137 | ||
| 138 | int bch2_accounting_mem_insert(struct bch_fs *, struct bkey_s_c_accounting, enum bch_accounting_mode); | 138 | int bch2_accounting_mem_insert(struct bch_fs *, struct bkey_s_c_accounting, enum bch_accounting_mode); |
| 139 | int bch2_accounting_mem_insert_locked(struct bch_fs *, struct bkey_s_c_accounting, enum bch_accounting_mode); | ||
| 139 | void bch2_accounting_mem_gc(struct bch_fs *); | 140 | void bch2_accounting_mem_gc(struct bch_fs *); |
| 140 | 141 | ||
| 141 | static inline bool bch2_accounting_is_mem(struct disk_accounting_pos acc) | 142 | static inline bool bch2_accounting_is_mem(struct disk_accounting_pos acc) |
| @@ -150,7 +151,8 @@ static inline bool bch2_accounting_is_mem(struct disk_accounting_pos acc) · 8 unmodified lines | |||
| 150 | */ | 151 | */ |
| 151 | static inline int bch2_accounting_mem_mod_locked(struct btree_trans *trans, | 152 | static inline int bch2_accounting_mem_mod_locked(struct btree_trans *trans, |
| 152 | struct bkey_s_c_accounting a, | 153 | struct bkey_s_c_accounting a, |
| 153 | enum bch_accounting_mode mode) | 154 | enum bch_accounting_mode mode, |
| 155 | bool write_locked) | ||
| 154 | { | 156 | { |
| 155 | struct bch_fs *c = trans->c; | 157 | struct bch_fs *c = trans->c; |
| 156 | struct bch_accounting_mem *acc = &c->accounting; | 158 | struct bch_accounting_mem *acc = &c->accounting; |
| @@ -189,7 +191,11 @@ static inline int bch2_accounting_mem_mod_locked(struct btree_trans *trans, · 32 unmodified lines | |||
| 189 | 191 | ||
| 190 | while ((idx = eytzinger0_find(acc->k.data, acc->k.nr, sizeof(acc->k.data[0]), | 192 | while ((idx = eytzinger0_find(acc->k.data, acc->k.nr, sizeof(acc->k.data[0]), |
| 191 | accounting_pos_cmp, &a.k->p)) >= acc->k.nr) { | 193 | accounting_pos_cmp, &a.k->p)) >= acc->k.nr) { |
| 192 | int ret = bch2_accounting_mem_insert(c, a, mode); | 194 | int ret = 0; |
| 195 | if (unlikely(write_locked)) | ||
| 196 | ret = bch2_accounting_mem_insert_locked(c, a, mode); | ||
| 197 | else | ||
| 198 | ret = bch2_accounting_mem_insert(c, a, mode); | ||
| 193 | if (ret) | 199 | if (ret) |
| 194 | return ret; | 200 | return ret; |
| 195 | } | 201 | } |
| @@ -206,7 +212,7 @@ static inline int bch2_accounting_mem_mod_locked(struct btree_trans *trans, · 10 unmodified lines | |||
| 206 | static inline int bch2_accounting_mem_add(struct btree_trans *trans, struct bkey_s_c_accounting a, bool gc) | 212 | static inline int bch2_accounting_mem_add(struct btree_trans *trans, struct bkey_s_c_accounting a, bool gc) |
| 207 | { | 213 | { |
| 208 | percpu_down_read(&trans->c->mark_lock); | 214 | percpu_down_read(&trans->c->mark_lock); |
| 209 | int ret = bch2_accounting_mem_mod_locked(trans, a, gc ? BCH_ACCOUNTING_gc : BCH_ACCOUNTING_normal); | 215 | int ret = bch2_accounting_mem_mod_locked(trans, a, gc ? BCH_ACCOUNTING_gc : BCH_ACCOUNTING_normal, false); |
| 210 | percpu_up_read(&trans->c->mark_lock); | 216 | percpu_up_read(&trans->c->mark_lock); |
| 211 | return ret; | 217 | return ret; |
| 212 | } | 218 | } |
| @@ -259,7 +265,7 @@ static inline int bch2_accounting_trans_commit_hook(struct btree_trans *trans, · 46 unmodified lines | |||
| 259 | EBUG_ON(bversion_zero(a->k.bversion)); | 265 | EBUG_ON(bversion_zero(a->k.bversion)); |
| 260 | 266 | ||
| 261 | return likely(!(commit_flags & BCH_TRANS_COMMIT_skip_accounting_apply)) | 267 | return likely(!(commit_flags & BCH_TRANS_COMMIT_skip_accounting_apply)) |
| 262 | ? bch2_accounting_mem_mod_locked(trans, accounting_i_to_s_c(a), BCH_ACCOUNTING_normal) | 268 | ? bch2_accounting_mem_mod_locked(trans, accounting_i_to_s_c(a), BCH_ACCOUNTING_normal, false) |
| 263 | : 0; | 269 | : 0; |
| 264 | } | 270 | } |
| 265 | 271 | ||
| @@ -271,7 +277,7 @@ static inline void bch2_accounting_trans_commit_revert(struct btree_trans *trans · 5 unmodified lines | |||
| 271 | struct bkey_s_accounting a = accounting_i_to_s(a_i); | 277 | struct bkey_s_accounting a = accounting_i_to_s(a_i); |
| 272 | 278 | ||
| 273 | bch2_accounting_neg(a); | 279 | bch2_accounting_neg(a); |
| 274 | bch2_accounting_mem_mod_locked(trans, a.c, BCH_ACCOUNTING_normal); | 280 | bch2_accounting_mem_mod_locked(trans, a.c, BCH_ACCOUNTING_normal, false); |
| 275 | bch2_accounting_neg(a); | 281 | bch2_accounting_neg(a); |
| 276 | } | 282 | } |
| 277 | } | 283 | } |
| @@ -1429,7 +1429,9 @@ static int bch2_next_fiemap_extent(struct btree_trans *trans, · 1428 unmodified lines | |||
| 1429 | if (ret) | 1429 | if (ret) |
| 1430 | goto err; | 1430 | goto err; |
| 1431 | 1431 | ||
| 1432 | ret = bch2_next_fiemap_pagecache_extent(trans, inode, start, end, cur); | 1432 | u64 pagecache_end = k.k ? max(start, bkey_start_offset(k.k)) : end; |
| 1433 | |||
| 1434 | ret = bch2_next_fiemap_pagecache_extent(trans, inode, start, pagecache_end, cur); | ||
| 1433 | if (ret) | 1435 | if (ret) |
| 1434 | goto err; | 1436 | goto err; |
| 1435 | 1437 | ||
| @@ -2446,7 +2446,7 @@ static int check_subvol_path(struct btree_trans *trans, struct btree_iter *iter, · 2445 unmodified lines | |||
| 2446 | u32 parent = le32_to_cpu(s.v->fs_path_parent); | 2446 | u32 parent = le32_to_cpu(s.v->fs_path_parent); |
| 2447 | 2447 | ||
| 2448 | if (darray_u32_has(&subvol_path, parent)) { | 2448 | if (darray_u32_has(&subvol_path, parent)) { |
| 2449 | if (fsck_err(c, subvol_loop, "subvolume loop")) | 2449 | if (fsck_err(trans, subvol_loop, "subvolume loop")) |
| 2450 | ret = reattach_subvol(trans, s); | 2450 | ret = reattach_subvol(trans, s); |
| 2451 | break; | 2451 | break; |
| 2452 | } | 2452 | } |
| @@ -17,6 +17,8 @@ · 16 unmodified lines | |||
| 17 | #include <linux/kthread.h> | 17 | #include <linux/kthread.h> |
| 18 | #include <linux/sched/mm.h> | 18 | #include <linux/sched/mm.h> |
| 19 | 19 | ||
| 20 | static bool __should_discard_bucket(struct journal *, struct journal_device *); | ||
| 21 | |||
| 20 | /* Free space calculations: */ | 22 | /* Free space calculations: */ |
| 21 | 23 | ||
| 22 | static unsigned journal_space_from(struct journal_device *ja, | 24 | static unsigned journal_space_from(struct journal_device *ja, |
| @@ -203,8 +205,7 @@ void bch2_journal_space_available(struct journal *j) · 180 unmodified lines | |||
| 203 | ja->bucket_seq[ja->dirty_idx_ondisk] < j->last_seq_ondisk) | 205 | ja->bucket_seq[ja->dirty_idx_ondisk] < j->last_seq_ondisk) |
| 204 | ja->dirty_idx_ondisk = (ja->dirty_idx_ondisk + 1) % ja->nr; | 206 | ja->dirty_idx_ondisk = (ja->dirty_idx_ondisk + 1) % ja->nr; |
| 205 | 207 | ||
| 206 | if (ja->discard_idx != ja->dirty_idx_ondisk) | 208 | can_discard |= __should_discard_bucket(j, ja); |
| 207 | can_discard = true; | ||
| 208 | 209 | ||
| 209 | max_entry_size = min_t(unsigned, max_entry_size, ca->mi.bucket_size); | 210 | max_entry_size = min_t(unsigned, max_entry_size, ca->mi.bucket_size); |
| 210 | nr_online++; | 211 | nr_online++; |
| @@ -264,13 +265,19 @@ out: · 53 unmodified lines | |||
| 264 | 265 | ||
| 265 | /* Discards - last part of journal reclaim: */ | 266 | /* Discards - last part of journal reclaim: */ |
| 266 | 267 | ||
| 267 | static bool should_discard_bucket(struct journal *j, struct journal_device *ja) | 268 | static bool __should_discard_bucket(struct journal *j, struct journal_device *ja) |
| 268 | { | 269 | { |
| 269 | spin_lock(&j->lock); | ||
| 270 | unsigned min_free = max(4, ja->nr / 8); | 270 | unsigned min_free = max(4, ja->nr / 8); |
| 271 | 271 | ||
| 272 | bool ret = bch2_journal_dev_buckets_available(j, ja, journal_space_discarded) < min_free && | 272 | return bch2_journal_dev_buckets_available(j, ja, journal_space_discarded) < |
| 273 | min_free && | ||
| 273 | ja->discard_idx != ja->dirty_idx_ondisk; | 274 | ja->discard_idx != ja->dirty_idx_ondisk; |
| 275 | } | ||
| 276 | |||
| 277 | static bool should_discard_bucket(struct journal *j, struct journal_device *ja) | ||
| 278 | { | ||
| 279 | spin_lock(&j->lock); | ||
| 280 | bool ret = __should_discard_bucket(j, ja); | ||
| 274 | spin_unlock(&j->lock); | 281 | spin_unlock(&j->lock); |
| 275 | 282 | ||
| 276 | return ret; | 283 | return ret; |
| @@ -309,7 +309,7 @@ static int bch2_bkey_clear_needs_rebalance(struct btree_trans *trans, · 308 unmodified lines | |||
| 309 | struct btree_iter *iter, | 309 | struct btree_iter *iter, |
| 310 | struct bkey_s_c k) | 310 | struct bkey_s_c k) |
| 311 | { | 311 | { |
| 312 | if (!bch2_bkey_rebalance_opts(k)) | 312 | if (k.k->type == KEY_TYPE_reflink_v || !bch2_bkey_rebalance_opts(k)) |
| 313 | return 0; | 313 | return 0; |
| 314 | 314 | ||
| 315 | struct bkey_i *n = bch2_bkey_make_mut(trans, iter, &k, 0); | 315 | struct bkey_i *n = bch2_bkey_make_mut(trans, iter, &k, 0); |
| @@ -830,6 +830,7 @@ static int load_elf_binary(struct linux_binprm *bprm) · 829 unmodified lines | |||
| 830 | struct elf_phdr *elf_ppnt, *elf_phdata, *interp_elf_phdata = NULL; | 830 | struct elf_phdr *elf_ppnt, *elf_phdata, *interp_elf_phdata = NULL; |
| 831 | struct elf_phdr *elf_property_phdata = NULL; | 831 | struct elf_phdr *elf_property_phdata = NULL; |
| 832 | unsigned long elf_brk; | 832 | unsigned long elf_brk; |
| 833 | bool brk_moved = false; | ||
| 833 | int retval, i; | 834 | int retval, i; |
| 834 | unsigned long elf_entry; | 835 | unsigned long elf_entry; |
| 835 | unsigned long e_entry; | 836 | unsigned long e_entry; |
| @@ -1097,15 +1098,19 @@ out_free_interp: · 261 unmodified lines | |||
| 1097 | /* Calculate any requested alignment. */ | 1098 | /* Calculate any requested alignment. */ |
| 1098 | alignment = maximum_alignment(elf_phdata, elf_ex->e_phnum); | 1099 | alignment = maximum_alignment(elf_phdata, elf_ex->e_phnum); |
| 1099 | 1100 | ||
| 1100 | /* | 1101 | /** |
| 1101 | * There are effectively two types of ET_DYN | 1102 | * DOC: PIE handling |
| 1102 | * binaries: programs (i.e. PIE: ET_DYN with PT_INTERP) | 1103 | * |
| 1103 | * and loaders (ET_DYN without PT_INTERP, since they | 1104 | * There are effectively two types of ET_DYN ELF |
| 1104 | * _are_ the ELF interpreter). The loaders must | 1105 | * binaries: programs (i.e. PIE: ET_DYN with |
| 1105 | * be loaded away from programs since the program | 1106 | * PT_INTERP) and loaders (i.e. static PIE: ET_DYN |
| 1106 | * may otherwise collide with the loader (especially | 1107 | * without PT_INTERP, usually the ELF interpreter |
| 1107 | * for ET_EXEC which does not have a randomized | 1108 | * itself). Loaders must be loaded away from programs |
| 1108 | * position). For example to handle invocations of | 1109 | * since the program may otherwise collide with the |
| 1110 | * loader (especially for ET_EXEC which does not have | ||
| 1111 | * a randomized position). | ||
| 1112 | * | ||
| 1113 | * For example, to handle invocations of | ||
| 1109 | * "./ld.so someprog" to test out a new version of | 1114 | * "./ld.so someprog" to test out a new version of |
| 1110 | * the loader, the subsequent program that the | 1115 | * the loader, the subsequent program that the |
| 1111 | * loader loads must avoid the loader itself, so | 1116 | * loader loads must avoid the loader itself, so |
| @@ -1118,6 +1123,9 @@ out_free_interp: · 6 unmodified lines | |||
| 1118 | * ELF_ET_DYN_BASE and loaders are loaded into the | 1123 | * ELF_ET_DYN_BASE and loaders are loaded into the |
| 1119 | * independently randomized mmap region (0 load_bias | 1124 | * independently randomized mmap region (0 load_bias |
| 1120 | * without MAP_FIXED nor MAP_FIXED_NOREPLACE). | 1125 | * without MAP_FIXED nor MAP_FIXED_NOREPLACE). |
| 1126 | * | ||
| 1127 | * See below for "brk" handling details, which is | ||
| 1128 | * also affected by program vs loader and ASLR. | ||
| 1121 | */ | 1129 | */ |
| 1122 | if (interpreter) { | 1130 | if (interpreter) { |
| 1123 | /* On ET_DYN with PT_INTERP, we do the ASLR. */ | 1131 | /* On ET_DYN with PT_INTERP, we do the ASLR. */ |
| @@ -1234,8 +1242,6 @@ out_free_interp: · 110 unmodified lines | |||
| 1234 | start_data += load_bias; | 1242 | start_data += load_bias; |
| 1235 | end_data += load_bias; | 1243 | end_data += load_bias; |
| 1236 | 1244 | ||
| 1237 | current->mm->start_brk = current->mm->brk = ELF_PAGEALIGN(elf_brk); | ||
| 1238 | |||
| 1239 | if (interpreter) { | 1245 | if (interpreter) { |
| 1240 | elf_entry = load_elf_interp(interp_elf_ex, | 1246 | elf_entry = load_elf_interp(interp_elf_ex, |
| 1241 | interpreter, | 1247 | interpreter, |
| @@ -1291,27 +1297,44 @@ out_free_interp: · 49 unmodified lines | |||
| 1291 | mm->end_data = end_data; | 1297 | mm->end_data = end_data; |
| 1292 | mm->start_stack = bprm->p; | 1298 | mm->start_stack = bprm->p; |
| 1293 | 1299 | ||
| 1294 | if ((current->flags & PF_RANDOMIZE) && (snapshot_randomize_va_space > 1)) { | 1300 | /** |
| 1301 | * DOC: "brk" handling | ||
| 1302 | * | ||
| 1303 | * For architectures with ELF randomization, when executing a | ||
| 1304 | * loader directly (i.e. static PIE: ET_DYN without PT_INTERP), | ||
| 1305 | * move the brk area out of the mmap region and into the unused | ||
| 1306 | * ELF_ET_DYN_BASE region. Since "brk" grows up it may collide | ||
| 1307 | * early with the stack growing down or other regions being put | ||
| 1308 | * into the mmap region by the kernel (e.g. vdso). | ||
| 1309 | * | ||
| 1310 | * In the CONFIG_COMPAT_BRK case, though, everything is turned | ||
| 1311 | * off because we're not allowed to move the brk at all. | ||
| 1312 | */ | ||
| 1313 | if (!IS_ENABLED(CONFIG_COMPAT_BRK) && | ||
| 1314 | IS_ENABLED(CONFIG_ARCH_HAS_ELF_RANDOMIZE) && | ||
| 1315 | elf_ex->e_type == ET_DYN && !interpreter) { | ||
| 1316 | elf_brk = ELF_ET_DYN_BASE; | ||
| 1317 | /* This counts as moving the brk, so let brk(2) know. */ | ||
| 1318 | brk_moved = true; | ||
| 1319 | } | ||
| 1320 | mm->start_brk = mm->brk = ELF_PAGEALIGN(elf_brk); | ||
| 1321 | |||
| 1322 | if ((current->flags & PF_RANDOMIZE) && snapshot_randomize_va_space > 1) { | ||
| 1295 | /* | 1323 | /* |
| 1296 | * For architectures with ELF randomization, when executing | 1324 | * If we didn't move the brk to ELF_ET_DYN_BASE (above), |
| 1297 | * a loader directly (i.e. no interpreter listed in ELF | 1325 | * leave a gap between .bss and brk. |
| 1298 | * headers), move the brk area out of the mmap region | ||
| 1299 | * (since it grows up, and may collide early with the stack | ||
| 1300 | * growing down), and into the unused ELF_ET_DYN_BASE region. | ||
| 1301 | */ | 1326 | */ |
| 1302 | if (IS_ENABLED(CONFIG_ARCH_HAS_ELF_RANDOMIZE) && | 1327 | if (!brk_moved) |
| 1303 | elf_ex->e_type == ET_DYN && !interpreter) { | ||
| 1304 | mm->brk = mm->start_brk = ELF_ET_DYN_BASE; | ||
| 1305 | } else { | ||
| 1306 | /* Otherwise leave a gap between .bss and brk. */ | ||
| 1307 | mm->brk = mm->start_brk = mm->brk + PAGE_SIZE; | 1328 | mm->brk = mm->start_brk = mm->brk + PAGE_SIZE; |
| 1308 | } | ||
| 1309 | 1329 | ||
| 1310 | mm->brk = mm->start_brk = arch_randomize_brk(mm); | 1330 | mm->brk = mm->start_brk = arch_randomize_brk(mm); |
| 1331 | brk_moved = true; | ||
| 1332 | } | ||
| 1333 | |||
| 1311 | #ifdef compat_brk_randomized | 1334 | #ifdef compat_brk_randomized |
| 1335 | if (brk_moved) | ||
| 1312 | current->brk_randomized = 1; | 1336 | current->brk_randomized = 1; |
| 1313 | #endif | 1337 | #endif |
| 1314 | } | ||
| 1315 | 1338 | ||
| 1316 | if (current->personality & MMAP_PAGE_ZERO) { | 1339 | if (current->personality & MMAP_PAGE_ZERO) { |
| 1317 | /* Why this, you ask??? Well SVr4 maps page 0 as read-only, | 1340 | /* Why this, you ask??? Well SVr4 maps page 0 as read-only, |
| @@ -94,8 +94,6 @@ static void __add_to_discard_list(struct btrfs_discard_ctl *discard_ctl, · 93 unmodified lines | |||
| 94 | struct btrfs_block_group *block_group) | 94 | struct btrfs_block_group *block_group) |
| 95 | { | 95 | { |
| 96 | lockdep_assert_held(&discard_ctl->lock); | 96 | lockdep_assert_held(&discard_ctl->lock); |
| 97 | if (!btrfs_run_discard_work(discard_ctl)) | ||
| 98 | return; | ||
| 99 | 97 | ||
| 100 | if (list_empty(&block_group->discard_list) || | 98 | if (list_empty(&block_group->discard_list) || |
| 101 | block_group->discard_index == BTRFS_DISCARD_INDEX_UNUSED) { | 99 | block_group->discard_index == BTRFS_DISCARD_INDEX_UNUSED) { |
| @@ -118,6 +116,9 @@ static void add_to_discard_list(struct btrfs_discard_ctl *discard_ctl, · 16 unmodified lines | |||
| 118 | if (!btrfs_is_block_group_data_only(block_group)) | 116 | if (!btrfs_is_block_group_data_only(block_group)) |
| 119 | return; | 117 | return; |
| 120 | 118 | ||
| 119 | if (!btrfs_run_discard_work(discard_ctl)) | ||
| 120 | return; | ||
| 121 | |||
| 121 | spin_lock(&discard_ctl->lock); | 122 | spin_lock(&discard_ctl->lock); |
| 122 | __add_to_discard_list(discard_ctl, block_group); | 123 | __add_to_discard_list(discard_ctl, block_group); |
| 123 | spin_unlock(&discard_ctl->lock); | 124 | spin_unlock(&discard_ctl->lock); |
| @@ -244,6 +245,18 @@ again: · 120 unmodified lines | |||
| 244 | block_group->used != 0) { | 245 | block_group->used != 0) { |
| 245 | if (btrfs_is_block_group_data_only(block_group)) { | 246 | if (btrfs_is_block_group_data_only(block_group)) { |
| 246 | __add_to_discard_list(discard_ctl, block_group); | 247 | __add_to_discard_list(discard_ctl, block_group); |
| 248 | /* | ||
| 249 | * The block group must have been moved to other | ||
| 250 | * discard list even if discard was disabled in | ||
| 251 | * the meantime or a transaction abort happened, | ||
| 252 | * otherwise we can end up in an infinite loop, | ||
| 253 | * always jumping into the 'again' label and | ||
| 254 | * keep getting this block group over and over | ||
| 255 | * in case there are no other block groups in | ||
| 256 | * the discard lists. | ||
| 257 | */ | ||
| 258 | ASSERT(block_group->discard_index != | ||
| 259 | BTRFS_DISCARD_INDEX_UNUSED); | ||
| 247 | } else { | 260 | } else { |
| 248 | list_del_init(&block_group->discard_list); | 261 | list_del_init(&block_group->discard_list); |
| 249 | btrfs_put_block_group(block_group); | 262 | btrfs_put_block_group(block_group); |
| @@ -300,6 +300,7 @@ enum { · 299 unmodified lines | |||
| 300 | #define BTRFS_FEATURE_INCOMPAT_SAFE_CLEAR 0ULL | 300 | #define BTRFS_FEATURE_INCOMPAT_SAFE_CLEAR 0ULL |
| 301 | 301 | ||
| 302 | #define BTRFS_DEFAULT_COMMIT_INTERVAL (30) | 302 | #define BTRFS_DEFAULT_COMMIT_INTERVAL (30) |
| 303 | #define BTRFS_WARNING_COMMIT_INTERVAL (300) | ||
| 303 | #define BTRFS_DEFAULT_MAX_INLINE (2048) | 304 | #define BTRFS_DEFAULT_MAX_INLINE (2048) |
| 304 | 305 | ||
| 305 | struct btrfs_dev_replace { | 306 | struct btrfs_dev_replace { |
| @@ -1109,6 +1109,7 @@ static void submit_one_async_extent(struct async_chunk *async_chunk, · 1108 unmodified lines | |||
| 1109 | struct extent_state *cached = NULL; | 1109 | struct extent_state *cached = NULL; |
| 1110 | struct extent_map *em; | 1110 | struct extent_map *em; |
| 1111 | int ret = 0; | 1111 | int ret = 0; |
| 1112 | bool free_pages = false; | ||
| 1112 | u64 start = async_extent->start; | 1113 | u64 start = async_extent->start; |
| 1113 | u64 end = async_extent->start + async_extent->ram_size - 1; | 1114 | u64 end = async_extent->start + async_extent->ram_size - 1; |
| 1114 | 1115 | ||
| @@ -1129,7 +1130,10 @@ static void submit_one_async_extent(struct async_chunk *async_chunk, · 14 unmodified lines | |||
| 1129 | } | 1130 | } |
| 1130 | 1131 | ||
| 1131 | if (async_extent->compress_type == BTRFS_COMPRESS_NONE) { | 1132 | if (async_extent->compress_type == BTRFS_COMPRESS_NONE) { |
| 1133 | ASSERT(!async_extent->folios); | ||
| 1134 | ASSERT(async_extent->nr_folios == 0); | ||
| 1132 | submit_uncompressed_range(inode, async_extent, locked_folio); | 1135 | submit_uncompressed_range(inode, async_extent, locked_folio); |
| 1136 | free_pages = true; | ||
| 1133 | goto done; | 1137 | goto done; |
| 1134 | } | 1138 | } |
| 1135 | 1139 | ||
| @@ -1145,6 +1149,7 @@ static void submit_one_async_extent(struct async_chunk *async_chunk, · 9 unmodified lines | |||
| 1145 | * fall back to uncompressed. | 1149 | * fall back to uncompressed. |
| 1146 | */ | 1150 | */ |
| 1147 | submit_uncompressed_range(inode, async_extent, locked_folio); | 1151 | submit_uncompressed_range(inode, async_extent, locked_folio); |
| 1152 | free_pages = true; | ||
| 1148 | goto done; | 1153 | goto done; |
| 1149 | } | 1154 | } |
| 1150 | 1155 | ||
| @@ -1186,6 +1191,8 @@ static void submit_one_async_extent(struct async_chunk *async_chunk, · 35 unmodified lines | |||
| 1186 | done: | 1191 | done: |
| 1187 | if (async_chunk->blkcg_css) | 1192 | if (async_chunk->blkcg_css) |
| 1188 | kthread_associate_blkcg(NULL); | 1193 | kthread_associate_blkcg(NULL); |
| 1194 | if (free_pages) | ||
| 1195 | free_async_extent_pages(async_extent); | ||
| 1189 | kfree(async_extent); | 1196 | kfree(async_extent); |
| 1190 | return; | 1197 | return; |
| 1191 | 1198 | ||
| @@ -569,6 +569,10 @@ static int btrfs_parse_param(struct fs_context *fc, struct fs_parameter *param) · 568 unmodified lines | |||
| 569 | break; | 569 | break; |
| 570 | case Opt_commit_interval: | 570 | case Opt_commit_interval: |
| 571 | ctx->commit_interval = result.uint_32; | 571 | ctx->commit_interval = result.uint_32; |
| 572 | if (ctx->commit_interval > BTRFS_WARNING_COMMIT_INTERVAL) { | ||
| 573 | btrfs_warn(NULL, "excessive commit interval %u, use with care", | ||
| 574 | ctx->commit_interval); | ||
| 575 | } | ||
| 572 | if (ctx->commit_interval == 0) | 576 | if (ctx->commit_interval == 0) |
| 573 | ctx->commit_interval = BTRFS_DEFAULT_COMMIT_INTERVAL; | 577 | ctx->commit_interval = BTRFS_DEFAULT_COMMIT_INTERVAL; |
| 574 | break; | 578 | break; |
| @@ -1220,10 +1220,8 @@ void mark_buffer_write_io_error(struct buffer_head *bh) · 1219 unmodified lines | |||
| 1220 | /* FIXME: do we need to set this in both places? */ | 1220 | /* FIXME: do we need to set this in both places? */ |
| 1221 | if (bh->b_folio && bh->b_folio->mapping) | 1221 | if (bh->b_folio && bh->b_folio->mapping) |
| 1222 | mapping_set_error(bh->b_folio->mapping, -EIO); | 1222 | mapping_set_error(bh->b_folio->mapping, -EIO); |
| 1223 | if (bh->b_assoc_map) { | 1223 | if (bh->b_assoc_map) |
| 1224 | mapping_set_error(bh->b_assoc_map, -EIO); | 1224 | mapping_set_error(bh->b_assoc_map, -EIO); |
| 1225 | errseq_set(&bh->b_assoc_map->host->i_sb->s_wb_err, -EIO); | ||
| 1226 | } | ||
| 1227 | } | 1225 | } |
| 1228 | EXPORT_SYMBOL(mark_buffer_write_io_error); | 1226 | EXPORT_SYMBOL(mark_buffer_write_io_error); |
| 1229 | 1227 | ||
| @@ -2111,9 +2111,10 @@ static int ep_poll(struct eventpoll *ep, struct epoll_event __user *events, · 2110 unmodified lines | |||
| 2111 | 2111 | ||
| 2112 | write_unlock_irq(&ep->lock); | 2112 | write_unlock_irq(&ep->lock); |
| 2113 | 2113 | ||
| 2114 | if (!eavail && ep_schedule_timeout(to)) | 2114 | if (!eavail) |
| 2115 | timed_out = !schedule_hrtimeout_range(to, slack, | 2115 | timed_out = !ep_schedule_timeout(to) || |
| 2116 | HRTIMER_MODE_ABS); | 2116 | !schedule_hrtimeout_range(to, slack, |
| 2117 | HRTIMER_MODE_ABS); | ||
| 2117 | __set_current_state(TASK_RUNNING); | 2118 | __set_current_state(TASK_RUNNING); |
| 2118 | 2119 | ||
| 2119 | /* | 2120 | /* |
| @@ -1105,6 +1105,8 @@ struct nfs_server *nfs_create_server(struct fs_context *fc) · 1104 unmodified lines | |||
| 1105 | if (server->namelen == 0 || server->namelen > NFS2_MAXNAMLEN) | 1105 | if (server->namelen == 0 || server->namelen > NFS2_MAXNAMLEN) |
| 1106 | server->namelen = NFS2_MAXNAMLEN; | 1106 | server->namelen = NFS2_MAXNAMLEN; |
| 1107 | } | 1107 | } |
| 1108 | /* Linux 'subtree_check' borkenness mandates this setting */ | ||
| 1109 | server->fh_expire_type = NFS_FH_VOL_RENAME; | ||
| 1108 | 1110 | ||
| 1109 | if (!(fattr->valid & NFS_ATTR_FATTR)) { | 1111 | if (!(fattr->valid & NFS_ATTR_FATTR)) { |
| 1110 | error = ctx->nfs_mod->rpc_ops->getattr(server, ctx->mntfh, | 1112 | error = ctx->nfs_mod->rpc_ops->getattr(server, ctx->mntfh, |
| @@ -1199,6 +1201,10 @@ void nfs_clients_init(struct net *net) · 88 unmodified lines | |||
| 1199 | INIT_LIST_HEAD(&nn->nfs_volume_list); | 1201 | INIT_LIST_HEAD(&nn->nfs_volume_list); |
| 1200 | #if IS_ENABLED(CONFIG_NFS_V4) | 1202 | #if IS_ENABLED(CONFIG_NFS_V4) |
| 1201 | idr_init(&nn->cb_ident_idr); | 1203 | idr_init(&nn->cb_ident_idr); |
| 1204 | #endif | ||
| 1205 | #if IS_ENABLED(CONFIG_NFS_V4_1) | ||
| 1206 | INIT_LIST_HEAD(&nn->nfs4_data_server_cache); | ||
| 1207 | spin_lock_init(&nn->nfs4_data_server_lock); | ||
| 1202 | #endif | 1208 | #endif |
| 1203 | spin_lock_init(&nn->nfs_client_lock); | 1209 | spin_lock_init(&nn->nfs_client_lock); |
| 1204 | nn->boot_time = ktime_get_real(); | 1210 | nn->boot_time = ktime_get_real(); |
| @@ -1216,6 +1222,9 @@ void nfs_clients_exit(struct net *net) · 11 unmodified lines | |||
| 1216 | nfs_cleanup_cb_ident_idr(net); | 1222 | nfs_cleanup_cb_ident_idr(net); |
| 1217 | WARN_ON_ONCE(!list_empty(&nn->nfs_client_list)); | 1223 | WARN_ON_ONCE(!list_empty(&nn->nfs_client_list)); |
| 1218 | WARN_ON_ONCE(!list_empty(&nn->nfs_volume_list)); | 1224 | WARN_ON_ONCE(!list_empty(&nn->nfs_volume_list)); |
| 1225 | #if IS_ENABLED(CONFIG_NFS_V4_1) | ||
| 1226 | WARN_ON_ONCE(!list_empty(&nn->nfs4_data_server_cache)); | ||
| 1227 | #endif | ||
| 1219 | } | 1228 | } |
| 1220 | 1229 | ||
| 1221 | #ifdef CONFIG_PROC_FS | 1230 | #ifdef CONFIG_PROC_FS |
| @@ -2676,6 +2676,18 @@ nfs_unblock_rename(struct rpc_task *task, struct nfs_renamedata *data) · 2675 unmodified lines | |||
| 2676 | unblock_revalidate(new_dentry); | 2676 | unblock_revalidate(new_dentry); |
| 2677 | } | 2677 | } |
| 2678 | 2678 | ||
| 2679 | static bool nfs_rename_is_unsafe_cross_dir(struct dentry *old_dentry, | ||
| 2680 | struct dentry *new_dentry) | ||
| 2681 | { | ||
| 2682 | struct nfs_server *server = NFS_SB(old_dentry->d_sb); | ||
| 2683 | |||
| 2684 | if (old_dentry->d_parent != new_dentry->d_parent) | ||
| 2685 | return false; | ||
| 2686 | if (server->fh_expire_type & NFS_FH_RENAME_UNSAFE) | ||
| 2687 | return !(server->fh_expire_type & NFS_FH_NOEXPIRE_WITH_OPEN); | ||
| 2688 | return true; | ||
| 2689 | } | ||
| 2690 | |||
| 2679 | /* | 2691 | /* |
| 2680 | * RENAME | 2692 | * RENAME |
| 2681 | * FIXME: Some nfsds, like the Linux user space nfsd, may generate a | 2693 | * FIXME: Some nfsds, like the Linux user space nfsd, may generate a |
| @@ -2763,7 +2775,8 @@ int nfs_rename(struct mnt_idmap *idmap, struct inode *old_dir, · 81 unmodified lines | |||
| 2763 | 2775 | ||
| 2764 | } | 2776 | } |
| 2765 | 2777 | ||
| 2766 | if (S_ISREG(old_inode->i_mode)) | 2778 | if (S_ISREG(old_inode->i_mode) && |
| 2779 | nfs_rename_is_unsafe_cross_dir(old_dentry, new_dentry)) | ||
| 2767 | nfs_sync_inode(old_inode); | 2780 | nfs_sync_inode(old_inode); |
| 2768 | task = nfs_async_rename(old_dir, new_dir, old_dentry, new_dentry, | 2781 | task = nfs_async_rename(old_dir, new_dir, old_dentry, new_dentry, |
| 2769 | must_unblock ? nfs_unblock_rename : NULL); | 2782 | must_unblock ? nfs_unblock_rename : NULL); |
| @@ -757,7 +757,6 @@ static void nfs_direct_write_completion(struct nfs_pgio_header *hdr) · 756 unmodified lines | |||
| 757 | { | 757 | { |
| 758 | struct nfs_direct_req *dreq = hdr->dreq; | 758 | struct nfs_direct_req *dreq = hdr->dreq; |
| 759 | struct nfs_commit_info cinfo; | 759 | struct nfs_commit_info cinfo; |
| 760 | struct nfs_page *req = nfs_list_entry(hdr->pages.next); | ||
| 761 | struct inode *inode = dreq->inode; | 760 | struct inode *inode = dreq->inode; |
| 762 | int flags = NFS_ODIRECT_DONE; | 761 | int flags = NFS_ODIRECT_DONE; |
| 763 | 762 | ||
| @@ -786,6 +785,7 @@ static void nfs_direct_write_completion(struct nfs_pgio_header *hdr) · 22 unmodified lines | |||
| 786 | spin_unlock(&inode->i_lock); | 785 | spin_unlock(&inode->i_lock); |
| 787 | 786 | ||
| 788 | while (!list_empty(&hdr->pages)) { | 787 | while (!list_empty(&hdr->pages)) { |
| 788 | struct nfs_page *req; | ||
| 789 | 789 | ||
| 790 | req = nfs_list_entry(hdr->pages.next); | 790 | req = nfs_list_entry(hdr->pages.next); |
| 791 | nfs_list_remove_request(req); | 791 | nfs_list_remove_request(req); |
| @@ -76,6 +76,7 @@ nfs4_fl_alloc_deviceid_node(struct nfs_server *server, struct pnfs_device *pdev, · 75 unmodified lines | |||
| 76 | struct page *scratch; | 76 | struct page *scratch; |
| 77 | struct list_head dsaddrs; | 77 | struct list_head dsaddrs; |
| 78 | struct nfs4_pnfs_ds_addr *da; | 78 | struct nfs4_pnfs_ds_addr *da; |
| 79 | struct net *net = server->nfs_client->cl_net; | ||
| 79 | 80 | ||
| 80 | /* set up xdr stream */ | 81 | /* set up xdr stream */ |
| 81 | scratch = alloc_page(gfp_flags); | 82 | scratch = alloc_page(gfp_flags); |
| @@ -159,8 +160,7 @@ nfs4_fl_alloc_deviceid_node(struct nfs_server *server, struct pnfs_device *pdev, · 77 unmodified lines | |||
| 159 | 160 | ||
| 160 | mp_count = be32_to_cpup(p); /* multipath count */ | 161 | mp_count = be32_to_cpup(p); /* multipath count */ |
| 161 | for (j = 0; j < mp_count; j++) { | 162 | for (j = 0; j < mp_count; j++) { |
| 162 | da = nfs4_decode_mp_ds_addr(server->nfs_client->cl_net, | 163 | da = nfs4_decode_mp_ds_addr(net, &stream, gfp_flags); |
| 163 | &stream, gfp_flags); | ||
| 164 | if (da) | 164 | if (da) |
| 165 | list_add_tail(&da->da_node, &dsaddrs); | 165 | list_add_tail(&da->da_node, &dsaddrs); |
| 166 | } | 166 | } |
| @@ -170,7 +170,7 @@ nfs4_fl_alloc_deviceid_node(struct nfs_server *server, struct pnfs_device *pdev, · 3 unmodified lines | |||
| 170 | goto out_err_free_deviceid; | 170 | goto out_err_free_deviceid; |
| 171 | } | 171 | } |
| 172 | 172 | ||
| 173 | dsaddr->ds_list[i] = nfs4_pnfs_ds_add(&dsaddrs, gfp_flags); | 173 | dsaddr->ds_list[i] = nfs4_pnfs_ds_add(net, &dsaddrs, gfp_flags); |
| 174 | if (!dsaddr->ds_list[i]) | 174 | if (!dsaddr->ds_list[i]) |
| 175 | goto out_err_drain_dsaddrs; | 175 | goto out_err_drain_dsaddrs; |
| 176 | trace_fl_getdevinfo(server, &pdev->dev_id, dsaddr->ds_list[i]->ds_remotestr); | 176 | trace_fl_getdevinfo(server, &pdev->dev_id, dsaddr->ds_list[i]->ds_remotestr); |
| @@ -1329,7 +1329,7 @@ static int ff_layout_read_done_cb(struct rpc_task *task, · 1328 unmodified lines | |||
| 1329 | hdr->args.offset, hdr->args.count, | 1329 | hdr->args.offset, hdr->args.count, |
| 1330 | &hdr->res.op_status, OP_READ, | 1330 | &hdr->res.op_status, OP_READ, |
| 1331 | task->tk_status); | 1331 | task->tk_status); |
| 1332 | trace_ff_layout_read_error(hdr); | 1332 | trace_ff_layout_read_error(hdr, task->tk_status); |
| 1333 | } | 1333 | } |
| 1334 | 1334 | ||
| 1335 | err = ff_layout_async_handle_error(task, hdr->args.context->state, | 1335 | err = ff_layout_async_handle_error(task, hdr->args.context->state, |
| @@ -1502,7 +1502,7 @@ static int ff_layout_write_done_cb(struct rpc_task *task, · 166 unmodified lines | |||
| 1502 | hdr->args.offset, hdr->args.count, | 1502 | hdr->args.offset, hdr->args.count, |
| 1503 | &hdr->res.op_status, OP_WRITE, | 1503 | &hdr->res.op_status, OP_WRITE, |
| 1504 | task->tk_status); | 1504 | task->tk_status); |
| 1505 | trace_ff_layout_write_error(hdr); | 1505 | trace_ff_layout_write_error(hdr, task->tk_status); |
| 1506 | } | 1506 | } |
| 1507 | 1507 | ||
| 1508 | err = ff_layout_async_handle_error(task, hdr->args.context->state, | 1508 | err = ff_layout_async_handle_error(task, hdr->args.context->state, |
| @@ -1551,7 +1551,7 @@ static int ff_layout_commit_done_cb(struct rpc_task *task, · 42 unmodified lines | |||
| 1551 | data->args.offset, data->args.count, | 1551 | data->args.offset, data->args.count, |
| 1552 | &data->res.op_status, OP_COMMIT, | 1552 | &data->res.op_status, OP_COMMIT, |
| 1553 | task->tk_status); | 1553 | task->tk_status); |
| 1554 | trace_ff_layout_commit_error(data); | 1554 | trace_ff_layout_commit_error(data, task->tk_status); |
| 1555 | } | 1555 | } |
| 1556 | 1556 | ||
| 1557 | err = ff_layout_async_handle_error(task, NULL, data->ds_clp, | 1557 | err = ff_layout_async_handle_error(task, NULL, data->ds_clp, |
| @@ -49,6 +49,7 @@ nfs4_ff_alloc_deviceid_node(struct nfs_server *server, struct pnfs_device *pdev, · 48 unmodified lines | |||
| 49 | struct nfs4_pnfs_ds_addr *da; | 49 | struct nfs4_pnfs_ds_addr *da; |
| 50 | struct nfs4_ff_layout_ds *new_ds = NULL; | 50 | struct nfs4_ff_layout_ds *new_ds = NULL; |
| 51 | struct nfs4_ff_ds_version *ds_versions = NULL; | 51 | struct nfs4_ff_ds_version *ds_versions = NULL; |
| 52 | struct net *net = server->nfs_client->cl_net; | ||
| 52 | u32 mp_count; | 53 | u32 mp_count; |
| 53 | u32 version_count; | 54 | u32 version_count; |
| 54 | __be32 *p; | 55 | __be32 *p; |
| @@ -80,8 +81,7 @@ nfs4_ff_alloc_deviceid_node(struct nfs_server *server, struct pnfs_device *pdev, · 25 unmodified lines | |||
| 80 | 81 | ||
| 81 | for (i = 0; i < mp_count; i++) { | 82 | for (i = 0; i < mp_count; i++) { |
| 82 | /* multipath ds */ | 83 | /* multipath ds */ |
| 83 | da = nfs4_decode_mp_ds_addr(server->nfs_client->cl_net, | 84 | da = nfs4_decode_mp_ds_addr(net, &stream, gfp_flags); |
| 84 | &stream, gfp_flags); | ||
| 85 | if (da) | 85 | if (da) |
| 86 | list_add_tail(&da->da_node, &dsaddrs); | 86 | list_add_tail(&da->da_node, &dsaddrs); |
| 87 | } | 87 | } |
| @@ -149,7 +149,7 @@ nfs4_ff_alloc_deviceid_node(struct nfs_server *server, struct pnfs_device *pdev, · 61 unmodified lines | |||
| 149 | new_ds->ds_versions = ds_versions; | 149 | new_ds->ds_versions = ds_versions; |
| 150 | new_ds->ds_versions_cnt = version_count; | 150 | new_ds->ds_versions_cnt = version_count; |
| 151 | 151 | ||
| 152 | new_ds->ds = nfs4_pnfs_ds_add(&dsaddrs, gfp_flags); | 152 | new_ds->ds = nfs4_pnfs_ds_add(net, &dsaddrs, gfp_flags); |
| 153 | if (!new_ds->ds) | 153 | if (!new_ds->ds) |
| 154 | goto out_err_drain_dsaddrs; | 154 | goto out_err_drain_dsaddrs; |
| 155 | 155 | ||
| @@ -278,6 +278,7 @@ nfs_local_open_fh(struct nfs_client *clp, const struct cred *cred, · 277 unmodified lines | |||
| 278 | new = __nfs_local_open_fh(clp, cred, fh, nfl, mode); | 278 | new = __nfs_local_open_fh(clp, cred, fh, nfl, mode); |
| 279 | if (IS_ERR(new)) | 279 | if (IS_ERR(new)) |
| 280 | return NULL; | 280 | return NULL; |
| 281 | rcu_read_lock(); | ||
| 281 | /* try to swap in the pointer */ | 282 | /* try to swap in the pointer */ |
| 282 | spin_lock(&clp->cl_uuid.lock); | 283 | spin_lock(&clp->cl_uuid.lock); |
| 283 | nf = rcu_dereference_protected(*pnf, 1); | 284 | nf = rcu_dereference_protected(*pnf, 1); |
| @@ -287,7 +288,6 @@ nfs_local_open_fh(struct nfs_client *clp, const struct cred *cred, · 3 unmodified lines | |||
| 287 | rcu_assign_pointer(*pnf, nf); | 288 | rcu_assign_pointer(*pnf, nf); |
| 288 | } | 289 | } |
| 289 | spin_unlock(&clp->cl_uuid.lock); | 290 | spin_unlock(&clp->cl_uuid.lock); |
| 290 | rcu_read_lock(); | ||
| 291 | } | 291 | } |
| 292 | nf = nfs_local_file_get(nf); | 292 | nf = nfs_local_file_get(nf); |
| 293 | rcu_read_unlock(); | 293 | rcu_read_unlock(); |
| @@ -31,7 +31,11 @@ struct nfs_net { · 30 unmodified lines | |||
| 31 | unsigned short nfs_callback_tcpport; | 31 | unsigned short nfs_callback_tcpport; |
| 32 | unsigned short nfs_callback_tcpport6; | 32 | unsigned short nfs_callback_tcpport6; |
| 33 | int cb_users[NFS4_MAX_MINOR_VERSION + 1]; | 33 | int cb_users[NFS4_MAX_MINOR_VERSION + 1]; |
| 34 | #endif | 34 | #endif /* CONFIG_NFS_V4 */ |
| 35 | #if IS_ENABLED(CONFIG_NFS_V4_1) | ||
| 36 | struct list_head nfs4_data_server_cache; | ||
| 37 | spinlock_t nfs4_data_server_lock; | ||
| 38 | #endif /* CONFIG_NFS_V4_1 */ | ||
| 35 | struct nfs_netns_client *nfs_client; | 39 | struct nfs_netns_client *nfs_client; |
| 36 | spinlock_t nfs_client_lock; | 40 | spinlock_t nfs_client_lock; |
| 37 | ktime_t boot_time; | 41 | ktime_t boot_time; |
| @@ -104,7 +104,7 @@ struct posix_acl *nfs3_get_acl(struct inode *inode, int type, bool rcu) · 103 unmodified lines | |||
| 104 | 104 | ||
| 105 | switch (status) { | 105 | switch (status) { |
| 106 | case 0: | 106 | case 0: |
| 107 | status = nfs_refresh_inode(inode, res.fattr); | 107 | nfs_refresh_inode(inode, res.fattr); |
| 108 | break; | 108 | break; |
| 109 | case -EPFNOSUPPORT: | 109 | case -EPFNOSUPPORT: |
| 110 | case -EPROTONOSUPPORT: | 110 | case -EPROTONOSUPPORT: |
| @@ -671,6 +671,15 @@ nfs4_async_handle_exception(struct rpc_task *task, struct nfs_server *server, · 670 unmodified lines | |||
| 671 | struct nfs_client *clp = server->nfs_client; | 671 | struct nfs_client *clp = server->nfs_client; |
| 672 | int ret; | 672 | int ret; |
| 673 | 673 | ||
| 674 | if ((task->tk_rpc_status == -ENETDOWN || | ||
| 675 | task->tk_rpc_status == -ENETUNREACH) && | ||
| 676 | task->tk_flags & RPC_TASK_NETUNREACH_FATAL) { | ||
| 677 | exception->delay = 0; | ||
| 678 | exception->recovering = 0; | ||
| 679 | exception->retry = 0; | ||
| 680 | return -EIO; | ||
| 681 | } | ||
| 682 | |||
| 674 | ret = nfs4_do_handle_exception(server, errorcode, exception); | 683 | ret = nfs4_do_handle_exception(server, errorcode, exception); |
| 675 | if (exception->delay) { | 684 | if (exception->delay) { |
| 676 | int ret2 = nfs4_exception_should_retrans(server, exception); | 685 | int ret2 = nfs4_exception_should_retrans(server, exception); |
| @@ -7074,10 +7083,18 @@ static struct nfs4_unlockdata *nfs4_alloc_unlockdata(struct file_lock *fl, · 6397 unmodified lines | |||
| 7074 | struct nfs4_unlockdata *p; | 7083 | struct nfs4_unlockdata *p; |
| 7075 | struct nfs4_state *state = lsp->ls_state; | 7084 | struct nfs4_state *state = lsp->ls_state; |
| 7076 | struct inode *inode = state->inode; | 7085 | struct inode *inode = state->inode; |
| 7086 | struct nfs_lock_context *l_ctx; | ||
| 7077 | 7087 | ||
| 7078 | p = kzalloc(sizeof(*p), GFP_KERNEL); | 7088 | p = kzalloc(sizeof(*p), GFP_KERNEL); |
| 7079 | if (p == NULL) | 7089 | if (p == NULL) |
| 7080 | return NULL; | 7090 | return NULL; |
| 7091 | l_ctx = nfs_get_lock_context(ctx); | ||
| 7092 | if (!IS_ERR(l_ctx)) { | ||
| 7093 | p->l_ctx = l_ctx; | ||
| 7094 | } else { | ||
| 7095 | kfree(p); | ||
| 7096 | return NULL; | ||
| 7097 | } | ||
| 7081 | p->arg.fh = NFS_FH(inode); | 7098 | p->arg.fh = NFS_FH(inode); |
| 7082 | p->arg.fl = &p->fl; | 7099 | p->arg.fl = &p->fl; |
| 7083 | p->arg.seqid = seqid; | 7100 | p->arg.seqid = seqid; |
| @@ -7085,7 +7102,6 @@ static struct nfs4_unlockdata *nfs4_alloc_unlockdata(struct file_lock *fl, · 1 unmodified line | |||
| 7085 | p->lsp = lsp; | 7102 | p->lsp = lsp; |
| 7086 | /* Ensure we don't close file until we're done freeing locks! */ | 7103 | /* Ensure we don't close file until we're done freeing locks! */ |
| 7087 | p->ctx = get_nfs_open_context(ctx); | 7104 | p->ctx = get_nfs_open_context(ctx); |
| 7088 | p->l_ctx = nfs_get_lock_context(ctx); | ||
| 7089 | locks_init_lock(&p->fl); | 7105 | locks_init_lock(&p->fl); |
| 7090 | locks_copy_lock(&p->fl, fl); | 7106 | locks_copy_lock(&p->fl, fl); |
| 7091 | p->server = NFS_SERVER(inode); | 7107 | p->server = NFS_SERVER(inode); |
| @@ -2051,13 +2051,15 @@ TRACE_EVENT(fl_getdevinfo, · 2050 unmodified lines | |||
| 2051 | 2051 | ||
| 2052 | DECLARE_EVENT_CLASS(nfs4_flexfiles_io_event, | 2052 | DECLARE_EVENT_CLASS(nfs4_flexfiles_io_event, |
| 2053 | TP_PROTO( | 2053 | TP_PROTO( |
| 2054 | const struct nfs_pgio_header *hdr | 2054 | const struct nfs_pgio_header *hdr, |
| 2055 | int error | ||
| 2055 | ), | 2056 | ), |
| 2056 | 2057 | ||
| 2057 | TP_ARGS(hdr), | 2058 | TP_ARGS(hdr, error), |
| 2058 | 2059 | ||
| 2059 | TP_STRUCT__entry( | 2060 | TP_STRUCT__entry( |
| 2060 | __field(unsigned long, error) | 2061 | __field(unsigned long, error) |
| 2062 | __field(unsigned long, nfs_error) | ||
| 2061 | __field(dev_t, dev) | 2063 | __field(dev_t, dev) |
| 2062 | __field(u32, fhandle) | 2064 | __field(u32, fhandle) |
| 2063 | __field(u64, fileid) | 2065 | __field(u64, fileid) |
| @@ -2073,7 +2075,8 @@ DECLARE_EVENT_CLASS(nfs4_flexfiles_io_event, · 9 unmodified lines | |||
| 2073 | TP_fast_assign( | 2075 | TP_fast_assign( |
| 2074 | const struct inode *inode = hdr->inode; | 2076 | const struct inode *inode = hdr->inode; |
| 2075 | 2077 | ||
| 2076 | __entry->error = hdr->res.op_status; | 2078 | __entry->error = -error; |
| 2079 | __entry->nfs_error = hdr->res.op_status; | ||
| 2077 | __entry->fhandle = nfs_fhandle_hash(hdr->args.fh); | 2080 | __entry->fhandle = nfs_fhandle_hash(hdr->args.fh); |
| 2078 | __entry->fileid = NFS_FILEID(inode); | 2081 | __entry->fileid = NFS_FILEID(inode); |
| 2079 | __entry->dev = inode->i_sb->s_dev; | 2082 | __entry->dev = inode->i_sb->s_dev; |
| @@ -2088,7 +2091,8 @@ DECLARE_EVENT_CLASS(nfs4_flexfiles_io_event, · 8 unmodified lines | |||
| 2088 | 2091 | ||
| 2089 | TP_printk( | 2092 | TP_printk( |
| 2090 | "error=%ld (%s) fileid=%02x:%02x:%llu fhandle=0x%08x " | 2093 | "error=%ld (%s) fileid=%02x:%02x:%llu fhandle=0x%08x " |
| 2091 | "offset=%llu count=%u stateid=%d:0x%08x dstaddr=%s", | 2094 | "offset=%llu count=%u stateid=%d:0x%08x dstaddr=%s " |
| 2095 | "nfs_error=%lu (%s)", | ||
| 2092 | -__entry->error, | 2096 | -__entry->error, |
| 2093 | show_nfs4_status(__entry->error), | 2097 | show_nfs4_status(__entry->error), |
| 2094 | MAJOR(__entry->dev), MINOR(__entry->dev), | 2098 | MAJOR(__entry->dev), MINOR(__entry->dev), |
| @@ -2096,28 +2100,32 @@ DECLARE_EVENT_CLASS(nfs4_flexfiles_io_event, · 1 unmodified line | |||
| 2096 | __entry->fhandle, | 2100 | __entry->fhandle, |
| 2097 | __entry->offset, __entry->count, | 2101 | __entry->offset, __entry->count, |
| 2098 | __entry->stateid_seq, __entry->stateid_hash, | 2102 | __entry->stateid_seq, __entry->stateid_hash, |
| 2099 | __get_str(dstaddr) | 2103 | __get_str(dstaddr), __entry->nfs_error, |
| 2104 | show_nfs4_status(__entry->nfs_error) | ||
| 2100 | ) | 2105 | ) |
| 2101 | ); | 2106 | ); |
| 2102 | 2107 | ||
| 2103 | #define DEFINE_NFS4_FLEXFILES_IO_EVENT(name) \ | 2108 | #define DEFINE_NFS4_FLEXFILES_IO_EVENT(name) \ |
| 2104 | DEFINE_EVENT(nfs4_flexfiles_io_event, name, \ | 2109 | DEFINE_EVENT(nfs4_flexfiles_io_event, name, \ |
| 2105 | TP_PROTO( \ | 2110 | TP_PROTO( \ |
| 2106 | const struct nfs_pgio_header *hdr \ | 2111 | const struct nfs_pgio_header *hdr, \ |
| 2112 | int error \ | ||
| 2107 | ), \ | 2113 | ), \ |
| 2108 | TP_ARGS(hdr)) | 2114 | TP_ARGS(hdr, error)) |
| 2109 | DEFINE_NFS4_FLEXFILES_IO_EVENT(ff_layout_read_error); | 2115 | DEFINE_NFS4_FLEXFILES_IO_EVENT(ff_layout_read_error); |
| 2110 | DEFINE_NFS4_FLEXFILES_IO_EVENT(ff_layout_write_error); | 2116 | DEFINE_NFS4_FLEXFILES_IO_EVENT(ff_layout_write_error); |
| 2111 | 2117 | ||
| 2112 | TRACE_EVENT(ff_layout_commit_error, | 2118 | TRACE_EVENT(ff_layout_commit_error, |
| 2113 | TP_PROTO( | 2119 | TP_PROTO( |
| 2114 | const struct nfs_commit_data *data | 2120 | const struct nfs_commit_data *data, |
| 2121 | int error | ||
| 2115 | ), | 2122 | ), |
| 2116 | 2123 | ||
| 2117 | TP_ARGS(data), | 2124 | TP_ARGS(data, error), |
| 2118 | 2125 | ||
| 2119 | TP_STRUCT__entry( | 2126 | TP_STRUCT__entry( |
| 2120 | __field(unsigned long, error) | 2127 | __field(unsigned long, error) |
| 2128 | __field(unsigned long, nfs_error) | ||
| 2121 | __field(dev_t, dev) | 2129 | __field(dev_t, dev) |
| 2122 | __field(u32, fhandle) | 2130 | __field(u32, fhandle) |
| 2123 | __field(u64, fileid) | 2131 | __field(u64, fileid) |
| @@ -2131,7 +2139,8 @@ TRACE_EVENT(ff_layout_commit_error, · 7 unmodified lines | |||
| 2131 | TP_fast_assign( | 2139 | TP_fast_assign( |
| 2132 | const struct inode *inode = data->inode; | 2140 | const struct inode *inode = data->inode; |
| 2133 | 2141 | ||
| 2134 | __entry->error = data->res.op_status; | 2142 | __entry->error = -error; |
| 2143 | __entry->nfs_error = data->res.op_status; | ||
| 2135 | __entry->fhandle = nfs_fhandle_hash(data->args.fh); | 2144 | __entry->fhandle = nfs_fhandle_hash(data->args.fh); |
| 2136 | __entry->fileid = NFS_FILEID(inode); | 2145 | __entry->fileid = NFS_FILEID(inode); |
| 2137 | __entry->dev = inode->i_sb->s_dev; | 2146 | __entry->dev = inode->i_sb->s_dev; |
| @@ -2142,14 +2151,15 @@ TRACE_EVENT(ff_layout_commit_error, · 4 unmodified lines | |||
| 2142 | 2151 | ||
| 2143 | TP_printk( | 2152 | TP_printk( |
| 2144 | "error=%ld (%s) fileid=%02x:%02x:%llu fhandle=0x%08x " | 2153 | "error=%ld (%s) fileid=%02x:%02x:%llu fhandle=0x%08x " |
| 2145 | "offset=%llu count=%u dstaddr=%s", | 2154 | "offset=%llu count=%u dstaddr=%s nfs_error=%lu (%s)", |
| 2146 | -__entry->error, | 2155 | -__entry->error, |
| 2147 | show_nfs4_status(__entry->error), | 2156 | show_nfs4_status(__entry->error), |
| 2148 | MAJOR(__entry->dev), MINOR(__entry->dev), | 2157 | MAJOR(__entry->dev), MINOR(__entry->dev), |
| 2149 | (unsigned long long)__entry->fileid, | 2158 | (unsigned long long)__entry->fileid, |
| 2150 | __entry->fhandle, | 2159 | __entry->fhandle, |
| 2151 | __entry->offset, __entry->count, | 2160 | __entry->offset, __entry->count, |
| 2152 | __get_str(dstaddr) | 2161 | __get_str(dstaddr), __entry->nfs_error, |
| 2162 | show_nfs4_status(__entry->nfs_error) | ||
| 2153 | ) | 2163 | ) |
| 2154 | ); | 2164 | ); |
| 2155 | 2165 | ||
| @@ -745,6 +745,14 @@ pnfs_mark_matching_lsegs_invalid(struct pnfs_layout_hdr *lo, · 744 unmodified lines | |||
| 745 | return remaining; | 745 | return remaining; |
| 746 | } | 746 | } |
| 747 | 747 | ||
| 748 | static void pnfs_reset_return_info(struct pnfs_layout_hdr *lo) | ||
| 749 | { | ||
| 750 | struct pnfs_layout_segment *lseg; | ||
| 751 | |||
| 752 | list_for_each_entry(lseg, &lo->plh_return_segs, pls_list) | ||
| 753 | pnfs_set_plh_return_info(lo, lseg->pls_range.iomode, 0); | ||
| 754 | } | ||
| 755 | |||
| 748 | static void | 756 | static void |
| 749 | pnfs_free_returned_lsegs(struct pnfs_layout_hdr *lo, | 757 | pnfs_free_returned_lsegs(struct pnfs_layout_hdr *lo, |
| 750 | struct list_head *free_me, | 758 | struct list_head *free_me, |
| @@ -1246,21 +1254,15 @@ static void pnfs_clear_layoutcommit(struct inode *inode, · 495 unmodified lines | |||
| 1246 | static void | 1254 | static void |
| 1247 | pnfs_layoutreturn_retry_later_locked(struct pnfs_layout_hdr *lo, | 1255 | pnfs_layoutreturn_retry_later_locked(struct pnfs_layout_hdr *lo, |
| 1248 | const nfs4_stateid *arg_stateid, | 1256 | const nfs4_stateid *arg_stateid, |
| 1249 | const struct pnfs_layout_range *range) | 1257 | const struct pnfs_layout_range *range, |
| 1258 | struct list_head *freeme) | ||
| 1250 | { | 1259 | { |
| 1251 | const struct pnfs_layout_segment *lseg; | ||
| 1252 | u32 seq = be32_to_cpu(arg_stateid->seqid); | ||
| 1253 | |||
| 1254 | if (pnfs_layout_is_valid(lo) && | 1260 | if (pnfs_layout_is_valid(lo) && |
| 1255 | nfs4_stateid_match_other(&lo->plh_stateid, arg_stateid)) { | 1261 | nfs4_stateid_match_other(&lo->plh_stateid, arg_stateid)) |
| 1256 | list_for_each_entry(lseg, &lo->plh_return_segs, pls_list) { | 1262 | pnfs_reset_return_info(lo); |
| 1257 | if (pnfs_seqid_is_newer(lseg->pls_seq, seq) || | 1263 | else |
| 1258 | !pnfs_should_free_range(&lseg->pls_range, range)) | 1264 | pnfs_mark_layout_stateid_invalid(lo, freeme); |
| 1259 | continue; | 1265 | pnfs_clear_layoutreturn_waitbit(lo); |
| 1260 | pnfs_set_plh_return_info(lo, range->iomode, seq); | ||
| 1261 | break; | ||
| 1262 | } | ||
| 1263 | } | ||
| 1264 | } | 1266 | } |
| 1265 | 1267 | ||
| 1266 | void pnfs_layoutreturn_retry_later(struct pnfs_layout_hdr *lo, | 1268 | void pnfs_layoutreturn_retry_later(struct pnfs_layout_hdr *lo, |
| @@ -1268,11 +1270,12 @@ void pnfs_layoutreturn_retry_later(struct pnfs_layout_hdr *lo, · 1 unmodified line | |||
| 1268 | const struct pnfs_layout_range *range) | 1270 | const struct pnfs_layout_range *range) |
| 1269 | { | 1271 | { |
| 1270 | struct inode *inode = lo->plh_inode; | 1272 | struct inode *inode = lo->plh_inode; |
| 1273 | LIST_HEAD(freeme); | ||
| 1271 | 1274 | ||
| 1272 | spin_lock(&inode->i_lock); | 1275 | spin_lock(&inode->i_lock); |
| 1273 | pnfs_layoutreturn_retry_later_locked(lo, arg_stateid, range); | 1276 | pnfs_layoutreturn_retry_later_locked(lo, arg_stateid, range, &freeme); |
| 1274 | pnfs_clear_layoutreturn_waitbit(lo); | ||
| 1275 | spin_unlock(&inode->i_lock); | 1277 | spin_unlock(&inode->i_lock); |
| 1278 | pnfs_free_lseg_list(&freeme); | ||
| 1276 | } | 1279 | } |
| 1277 | 1280 | ||
| 1278 | void pnfs_layoutreturn_free_lsegs(struct pnfs_layout_hdr *lo, | 1281 | void pnfs_layoutreturn_free_lsegs(struct pnfs_layout_hdr *lo, |
| @@ -1292,6 +1295,7 @@ void pnfs_layoutreturn_free_lsegs(struct pnfs_layout_hdr *lo, · 13 unmodified lines | |||
| 1292 | pnfs_mark_matching_lsegs_invalid(lo, &freeme, range, seq); | 1295 | pnfs_mark_matching_lsegs_invalid(lo, &freeme, range, seq); |
| 1293 | pnfs_free_returned_lsegs(lo, &freeme, range, seq); | 1296 | pnfs_free_returned_lsegs(lo, &freeme, range, seq); |
| 1294 | pnfs_set_layout_stateid(lo, stateid, NULL, true); | 1297 | pnfs_set_layout_stateid(lo, stateid, NULL, true); |
| 1298 | pnfs_reset_return_info(lo); | ||
| 1295 | } else | 1299 | } else |
| 1296 | pnfs_mark_layout_stateid_invalid(lo, &freeme); | 1300 | pnfs_mark_layout_stateid_invalid(lo, &freeme); |
| 1297 | out_unlock: | 1301 | out_unlock: |
| @@ -1661,6 +1665,18 @@ int pnfs_roc_done(struct rpc_task *task, struct nfs4_layoutreturn_args **argpp, · 363 unmodified lines | |||
| 1661 | /* Was there an RPC level error? If not, retry */ | 1665 | /* Was there an RPC level error? If not, retry */ |
| 1662 | if (task->tk_rpc_status == 0) | 1666 | if (task->tk_rpc_status == 0) |
| 1663 | break; | 1667 | break; |
| 1668 | /* | ||
| 1669 | * Is there a fatal network level error? | ||
| 1670 | * If so release the layout, but flag the error. | ||
| 1671 | */ | ||
| 1672 | if ((task->tk_rpc_status == -ENETDOWN || | ||
| 1673 | task->tk_rpc_status == -ENETUNREACH) && | ||
| 1674 | task->tk_flags & RPC_TASK_NETUNREACH_FATAL) { | ||
| 1675 | *ret = 0; | ||
| 1676 | (*respp)->lrs_present = 0; | ||
| 1677 | retval = -EIO; | ||
| 1678 | break; | ||
| 1679 | } | ||
| 1664 | /* If the call was not sent, let caller handle it */ | 1680 | /* If the call was not sent, let caller handle it */ |
| 1665 | if (!RPC_WAS_SENT(task)) | 1681 | if (!RPC_WAS_SENT(task)) |
| 1666 | return 0; | 1682 | return 0; |
| @@ -1695,6 +1711,7 @@ void pnfs_roc_release(struct nfs4_layoutreturn_args *args, · 28 unmodified lines | |||
| 1695 | struct inode *inode = args->inode; | 1711 | struct inode *inode = args->inode; |
| 1696 | const nfs4_stateid *res_stateid = NULL; | 1712 | const nfs4_stateid *res_stateid = NULL; |
| 1697 | struct nfs4_xdr_opaque_data *ld_private = args->ld_private; | 1713 | struct nfs4_xdr_opaque_data *ld_private = args->ld_private; |
| 1714 | LIST_HEAD(freeme); | ||
| 1698 | 1715 | ||
| 1699 | switch (ret) { | 1716 | switch (ret) { |
| 1700 | case -NFS4ERR_BADSESSION: | 1717 | case -NFS4ERR_BADSESSION: |
| @@ -1703,9 +1720,9 @@ void pnfs_roc_release(struct nfs4_layoutreturn_args *args, · 2 unmodified lines | |||
| 1703 | case -NFS4ERR_NOMATCHING_LAYOUT: | 1720 | case -NFS4ERR_NOMATCHING_LAYOUT: |
| 1704 | spin_lock(&inode->i_lock); | 1721 | spin_lock(&inode->i_lock); |
| 1705 | pnfs_layoutreturn_retry_later_locked(lo, &args->stateid, | 1722 | pnfs_layoutreturn_retry_later_locked(lo, &args->stateid, |
| 1706 | &args->range); | 1723 | &args->range, &freeme); |
| 1707 | pnfs_clear_layoutreturn_waitbit(lo); | ||
| 1708 | spin_unlock(&inode->i_lock); | 1724 | spin_unlock(&inode->i_lock); |
| 1725 | pnfs_free_lseg_list(&freeme); | ||
| 1709 | break; | 1726 | break; |
| 1710 | case 0: | 1727 | case 0: |
| 1711 | if (res->lrs_present) | 1728 | if (res->lrs_present) |
| @@ -60,6 +60,7 @@ struct nfs4_pnfs_ds { · 59 unmodified lines | |||
| 60 | struct list_head ds_node; /* nfs4_pnfs_dev_hlist dev_dslist */ | 60 | struct list_head ds_node; /* nfs4_pnfs_dev_hlist dev_dslist */ |
| 61 | char *ds_remotestr; /* comma sep list of addrs */ | 61 | char *ds_remotestr; /* comma sep list of addrs */ |
| 62 | struct list_head ds_addrs; | 62 | struct list_head ds_addrs; |
| 63 | const struct net *ds_net; | ||
| 63 | struct nfs_client *ds_clp; | 64 | struct nfs_client *ds_clp; |
| 64 | refcount_t ds_count; | 65 | refcount_t ds_count; |
| 65 | unsigned long ds_state; | 66 | unsigned long ds_state; |
| @@ -415,7 +416,8 @@ int pnfs_generic_commit_pagelist(struct inode *inode, · 349 unmodified lines | |||
| 415 | int pnfs_generic_scan_commit_lists(struct nfs_commit_info *cinfo, int max); | 416 | int pnfs_generic_scan_commit_lists(struct nfs_commit_info *cinfo, int max); |
| 416 | void pnfs_generic_write_commit_done(struct rpc_task *task, void *data); | 417 | void pnfs_generic_write_commit_done(struct rpc_task *task, void *data); |
| 417 | void nfs4_pnfs_ds_put(struct nfs4_pnfs_ds *ds); | 418 | void nfs4_pnfs_ds_put(struct nfs4_pnfs_ds *ds); |
| 418 | struct nfs4_pnfs_ds *nfs4_pnfs_ds_add(struct list_head *dsaddrs, | 419 | struct nfs4_pnfs_ds *nfs4_pnfs_ds_add(const struct net *net, |
| 420 | struct list_head *dsaddrs, | ||
| 419 | gfp_t gfp_flags); | 421 | gfp_t gfp_flags); |
| 420 | void nfs4_pnfs_v3_ds_connect_unload(void); | 422 | void nfs4_pnfs_v3_ds_connect_unload(void); |
| 421 | int nfs4_pnfs_ds_connect(struct nfs_server *mds_srv, struct nfs4_pnfs_ds *ds, | 423 | int nfs4_pnfs_ds_connect(struct nfs_server *mds_srv, struct nfs4_pnfs_ds *ds, |
| @@ -16,6 +16,7 @@ · 15 unmodified lines | |||
| 16 | #include "nfs4session.h" | 16 | #include "nfs4session.h" |
| 17 | #include "internal.h" | 17 | #include "internal.h" |
| 18 | #include "pnfs.h" | 18 | #include "pnfs.h" |
| 19 | #include "netns.h" | ||
| 19 | 20 | ||
| 20 | #define NFSDBG_FACILITY NFSDBG_PNFS | 21 | #define NFSDBG_FACILITY NFSDBG_PNFS |
| 21 | 22 | ||
| @@ -504,14 +505,14 @@ EXPORT_SYMBOL_GPL(pnfs_generic_commit_pagelist); · 482 unmodified lines | |||
| 504 | /* | 505 | /* |
| 505 | * Data server cache | 506 | * Data server cache |
| 506 | * | 507 | * |
| 507 | * Data servers can be mapped to different device ids. | 508 | * Data servers can be mapped to different device ids, but should |
| 508 | * nfs4_pnfs_ds reference counting | 509 | * never be shared between net namespaces. |
| 510 | * | ||
| 511 | * nfs4_pnfs_ds reference counting: | ||
| 509 | * - set to 1 on allocation | 512 | * - set to 1 on allocation |
| 510 | * - incremented when a device id maps a data server already in the cache. | 513 | * - incremented when a device id maps a data server already in the cache. |
| 511 | * - decremented when deviceid is removed from the cache. | 514 | * - decremented when deviceid is removed from the cache. |
| 512 | */ | 515 | */ |
| 513 | static DEFINE_SPINLOCK(nfs4_ds_cache_lock); | ||
| 514 | static LIST_HEAD(nfs4_data_server_cache); | ||
| 515 | 516 | ||
| 516 | /* Debug routines */ | 517 | /* Debug routines */ |
| 517 | static void | 518 | static void |
| @@ -604,11 +605,11 @@ _same_data_server_addrs_locked(const struct list_head *dsaddrs1, · 86 unmodified lines | |||
| 604 | * Lookup DS by addresses. nfs4_ds_cache_lock is held | 605 | * Lookup DS by addresses. nfs4_ds_cache_lock is held |
| 605 | */ | 606 | */ |
| 606 | static struct nfs4_pnfs_ds * | 607 | static struct nfs4_pnfs_ds * |
| 607 | _data_server_lookup_locked(const struct list_head *dsaddrs) | 608 | _data_server_lookup_locked(const struct nfs_net *nn, const struct list_head *dsaddrs) |
| 608 | { | 609 | { |
| 609 | struct nfs4_pnfs_ds *ds; | 610 | struct nfs4_pnfs_ds *ds; |
| 610 | 611 | ||
| 611 | list_for_each_entry(ds, &nfs4_data_server_cache, ds_node) | 612 | list_for_each_entry(ds, &nn->nfs4_data_server_cache, ds_node) |
| 612 | if (_same_data_server_addrs_locked(&ds->ds_addrs, dsaddrs)) | 613 | if (_same_data_server_addrs_locked(&ds->ds_addrs, dsaddrs)) |
| 613 | return ds; | 614 | return ds; |
| 614 | return NULL; | 615 | return NULL; |
| @@ -653,10 +654,11 @@ static void destroy_ds(struct nfs4_pnfs_ds *ds) · 38 unmodified lines | |||
| 653 | 654 | ||
| 654 | void nfs4_pnfs_ds_put(struct nfs4_pnfs_ds *ds) | 655 | void nfs4_pnfs_ds_put(struct nfs4_pnfs_ds *ds) |
| 655 | { | 656 | { |
| 656 | if (refcount_dec_and_lock(&ds->ds_count, | 657 | struct nfs_net *nn = net_generic(ds->ds_net, nfs_net_id); |
| 657 | &nfs4_ds_cache_lock)) { | 658 | |
| 659 | if (refcount_dec_and_lock(&ds->ds_count, &nn->nfs4_data_server_lock)) { | ||
| 658 | list_del_init(&ds->ds_node); | 660 | list_del_init(&ds->ds_node); |
| 659 | spin_unlock(&nfs4_ds_cache_lock); | 661 | spin_unlock(&nn->nfs4_data_server_lock); |
| 660 | destroy_ds(ds); | 662 | destroy_ds(ds); |
| 661 | } | 663 | } |
| 662 | } | 664 | } |
| @@ -716,8 +718,9 @@ out_err: · 53 unmodified lines | |||
| 716 | * uncached and return cached struct nfs4_pnfs_ds. | 718 | * uncached and return cached struct nfs4_pnfs_ds. |
| 717 | */ | 719 | */ |
| 718 | struct nfs4_pnfs_ds * | 720 | struct nfs4_pnfs_ds * |
| 719 | nfs4_pnfs_ds_add(struct list_head *dsaddrs, gfp_t gfp_flags) | 721 | nfs4_pnfs_ds_add(const struct net *net, struct list_head *dsaddrs, gfp_t gfp_flags) |
| 720 | { | 722 | { |
| 723 | struct nfs_net *nn = net_generic(net, nfs_net_id); | ||
| 721 | struct nfs4_pnfs_ds *tmp_ds, *ds = NULL; | 724 | struct nfs4_pnfs_ds *tmp_ds, *ds = NULL; |
| 722 | char *remotestr; | 725 | char *remotestr; |
| 723 | 726 | ||
| @@ -733,16 +736,17 @@ nfs4_pnfs_ds_add(struct list_head *dsaddrs, gfp_t gfp_flags) · 9 unmodified lines | |||
| 733 | /* this is only used for debugging, so it's ok if its NULL */ | 736 | /* this is only used for debugging, so it's ok if its NULL */ |
| 734 | remotestr = nfs4_pnfs_remotestr(dsaddrs, gfp_flags); | 737 | remotestr = nfs4_pnfs_remotestr(dsaddrs, gfp_flags); |
| 735 | 738 | ||
| 736 | spin_lock(&nfs4_ds_cache_lock); | 739 | spin_lock(&nn->nfs4_data_server_lock); |
| 737 | tmp_ds = _data_server_lookup_locked(dsaddrs); | 740 | tmp_ds = _data_server_lookup_locked(nn, dsaddrs); |
| 738 | if (tmp_ds == NULL) { | 741 | if (tmp_ds == NULL) { |
| 739 | INIT_LIST_HEAD(&ds->ds_addrs); | 742 | INIT_LIST_HEAD(&ds->ds_addrs); |
| 740 | list_splice_init(dsaddrs, &ds->ds_addrs); | 743 | list_splice_init(dsaddrs, &ds->ds_addrs); |
| 741 | ds->ds_remotestr = remotestr; | 744 | ds->ds_remotestr = remotestr; |
| 742 | refcount_set(&ds->ds_count, 1); | 745 | refcount_set(&ds->ds_count, 1); |
| 743 | INIT_LIST_HEAD(&ds->ds_node); | 746 | INIT_LIST_HEAD(&ds->ds_node); |
| 747 | ds->ds_net = net; | ||
| 744 | ds->ds_clp = NULL; | 748 | ds->ds_clp = NULL; |
| 745 | list_add(&ds->ds_node, &nfs4_data_server_cache); | 749 | list_add(&ds->ds_node, &nn->nfs4_data_server_cache); |
| 746 | dprintk("%s add new data server %s\n", __func__, | 750 | dprintk("%s add new data server %s\n", __func__, |
| 747 | ds->ds_remotestr); | 751 | ds->ds_remotestr); |
| 748 | } else { | 752 | } else { |
| @@ -754,7 +758,7 @@ nfs4_pnfs_ds_add(struct list_head *dsaddrs, gfp_t gfp_flags) · 5 unmodified lines | |||
| 754 | refcount_read(&tmp_ds->ds_count)); | 758 | refcount_read(&tmp_ds->ds_count)); |
| 755 | ds = tmp_ds; | 759 | ds = tmp_ds; |
| 756 | } | 760 | } |
| 757 | spin_unlock(&nfs4_ds_cache_lock); | 761 | spin_unlock(&nn->nfs4_data_server_lock); |
| 758 | out: | 762 | out: |
| 759 | return ds; | 763 | return ds; |
| 760 | } | 764 | } |
| @@ -160,8 +160,10 @@ static int cifs_prepare_read(struct netfs_io_subrequest *subreq) · 159 unmodified lines | |||
| 160 | server = cifs_pick_channel(tlink_tcon(req->cfile->tlink)->ses); | 160 | server = cifs_pick_channel(tlink_tcon(req->cfile->tlink)->ses); |
| 161 | rdata->server = server; | 161 | rdata->server = server; |
| 162 | 162 | ||
| 163 | cifs_negotiate_rsize(server, cifs_sb->ctx, | 163 | if (cifs_sb->ctx->rsize == 0) { |
| 164 | tlink_tcon(req->cfile->tlink)); | 164 | cifs_negotiate_rsize(server, cifs_sb->ctx, |
| 165 | tlink_tcon(req->cfile->tlink)); | ||
| 166 | } | ||
| 165 | 167 | ||
| 166 | rc = server->ops->wait_mtu_credits(server, cifs_sb->ctx->rsize, | 168 | rc = server->ops->wait_mtu_credits(server, cifs_sb->ctx->rsize, |
| 167 | &size, &rdata->credits); | 169 | &size, &rdata->credits); |
| @@ -2968,7 +2968,7 @@ replay_again: · 2967 unmodified lines | |||
| 2968 | /* Eventually save off posix specific response info and timestamps */ | 2968 | /* Eventually save off posix specific response info and timestamps */ |
| 2969 | 2969 | ||
| 2970 | err_free_rsp_buf: | 2970 | err_free_rsp_buf: |
| 2971 | free_rsp_buf(resp_buftype, rsp); | 2971 | free_rsp_buf(resp_buftype, rsp_iov.iov_base); |
| 2972 | kfree(pc_buf); | 2972 | kfree(pc_buf); |
| 2973 | err_free_req: | 2973 | err_free_req: |
| 2974 | cifs_small_buf_release(req); | 2974 | cifs_small_buf_release(req); |
| @@ -115,7 +115,7 @@ void udf_truncate_tail_extent(struct inode *inode) · 114 unmodified lines | |||
| 115 | } | 115 | } |
| 116 | /* This inode entry is in-memory only and thus we don't have to mark | 116 | /* This inode entry is in-memory only and thus we don't have to mark |
| 117 | * the inode dirty */ | 117 | * the inode dirty */ |
| 118 | if (ret == 0) | 118 | if (ret >= 0) |
| 119 | iinfo->i_lenExtents = inode->i_size; | 119 | iinfo->i_lenExtents = inode->i_size; |
| 120 | brelse(epos.bh); | 120 | brelse(epos.bh); |
| 121 | } | 121 | } |
| @@ -1428,6 +1428,15 @@ static bool xattr_is_trusted(const char *name) · 1427 unmodified lines | |||
| 1428 | return !strncmp(name, XATTR_TRUSTED_PREFIX, XATTR_TRUSTED_PREFIX_LEN); | 1428 | return !strncmp(name, XATTR_TRUSTED_PREFIX, XATTR_TRUSTED_PREFIX_LEN); |
| 1429 | } | 1429 | } |
| 1430 | 1430 | ||
| 1431 | static bool xattr_is_maclabel(const char *name) | ||
| 1432 | { | ||
| 1433 | const char *suffix = name + XATTR_SECURITY_PREFIX_LEN; | ||
| 1434 | |||
| 1435 | return !strncmp(name, XATTR_SECURITY_PREFIX, | ||
| 1436 | XATTR_SECURITY_PREFIX_LEN) && | ||
| 1437 | security_ismaclabel(suffix); | ||
| 1438 | } | ||
| 1439 | |||
| 1431 | /** | 1440 | /** |
| 1432 | * simple_xattr_list - list all xattr objects | 1441 | * simple_xattr_list - list all xattr objects |
| 1433 | * @inode: inode from which to get the xattrs | 1442 | * @inode: inode from which to get the xattrs |
| @@ -1460,6 +1469,17 @@ ssize_t simple_xattr_list(struct inode *inode, struct simple_xattrs *xattrs, · 26 unmodified lines | |||
| 1460 | if (err) | 1469 | if (err) |
| 1461 | return err; | 1470 | return err; |
| 1462 | 1471 | ||
| 1472 | err = security_inode_listsecurity(inode, buffer, remaining_size); | ||
| 1473 | if (err < 0) | ||
| 1474 | return err; | ||
| 1475 | |||
| 1476 | if (buffer) { | ||
| 1477 | if (remaining_size < err) | ||
| 1478 | return -ERANGE; | ||
| 1479 | buffer += err; | ||
| 1480 | } | ||
| 1481 | remaining_size -= err; | ||
| 1482 | |||
| 1463 | read_lock(&xattrs->lock); | 1483 | read_lock(&xattrs->lock); |
| 1464 | for (rbp = rb_first(&xattrs->rb_root); rbp; rbp = rb_next(rbp)) { | 1484 | for (rbp = rb_first(&xattrs->rb_root); rbp; rbp = rb_next(rbp)) { |
| 1465 | xattr = rb_entry(rbp, struct simple_xattr, rb_node); | 1485 | xattr = rb_entry(rbp, struct simple_xattr, rb_node); |
| @@ -1468,6 +1488,10 @@ ssize_t simple_xattr_list(struct inode *inode, struct simple_xattrs *xattrs, · 2 unmodified lines | |||
| 1468 | if (!trusted && xattr_is_trusted(xattr->name)) | 1488 | if (!trusted && xattr_is_trusted(xattr->name)) |
| 1469 | continue; | 1489 | continue; |
| 1470 | 1490 | ||
| 1491 | /* skip MAC labels; these are provided by LSM above */ | ||
| 1492 | if (xattr_is_maclabel(xattr->name)) | ||
| 1493 | continue; | ||
| 1494 | |||
| 1471 | err = xattr_list_one(&buffer, &remaining_size, xattr->name); | 1495 | err = xattr_list_one(&buffer, &remaining_size, xattr->name); |
| 1472 | if (err) | 1496 | if (err) |
| 1473 | break; | 1497 | break; |
| @@ -1149,7 +1149,7 @@ xfs_init_percpu_counters( · 1148 unmodified lines | |||
| 1149 | return 0; | 1149 | return 0; |
| 1150 | 1150 | ||
| 1151 | free_freecounters: | 1151 | free_freecounters: |
| 1152 | while (--i > 0) | 1152 | while (--i >= 0) |
| 1153 | percpu_counter_destroy(&mp->m_free[i].count); | 1153 | percpu_counter_destroy(&mp->m_free[i].count); |
| 1154 | percpu_counter_destroy(&mp->m_delalloc_rtextents); | 1154 | percpu_counter_destroy(&mp->m_delalloc_rtextents); |
| 1155 | free_delalloc: | 1155 | free_delalloc: |
| @@ -2114,6 +2114,21 @@ xfs_fs_reconfigure( · 958 unmodified lines | |||
| 2114 | if (error) | 2114 | if (error) |
| 2115 | return error; | 2115 | return error; |
| 2116 | 2116 | ||
| 2117 | /* attr2 -> noattr2 */ | ||
| 2118 | if (xfs_has_noattr2(new_mp)) { | ||
| 2119 | if (xfs_has_crc(mp)) { | ||
| 2120 | xfs_warn(mp, | ||
| 2121 | "attr2 is always enabled for a V5 filesystem - can't be changed."); | ||
| 2122 | return -EINVAL; | ||
| 2123 | } | ||
| 2124 | mp->m_features &= ~XFS_FEAT_ATTR2; | ||
| 2125 | mp->m_features |= XFS_FEAT_NOATTR2; | ||
| 2126 | } else if (xfs_has_attr2(new_mp)) { | ||
| 2127 | /* noattr2 -> attr2 */ | ||
| 2128 | mp->m_features &= ~XFS_FEAT_NOATTR2; | ||
| 2129 | mp->m_features |= XFS_FEAT_ATTR2; | ||
| 2130 | } | ||
| 2131 | |||
| 2117 | /* inode32 -> inode64 */ | 2132 | /* inode32 -> inode64 */ |
| 2118 | if (xfs_has_small_inums(mp) && !xfs_has_small_inums(new_mp)) { | 2133 | if (xfs_has_small_inums(mp) && !xfs_has_small_inums(new_mp)) { |
| 2119 | mp->m_features &= ~XFS_FEAT_SMALL_INUMS; | 2134 | mp->m_features &= ~XFS_FEAT_SMALL_INUMS; |
| @@ -2126,6 +2141,17 @@ xfs_fs_reconfigure( · 6 unmodified lines | |||
| 2126 | mp->m_maxagi = xfs_set_inode_alloc(mp, mp->m_sb.sb_agcount); | 2141 | mp->m_maxagi = xfs_set_inode_alloc(mp, mp->m_sb.sb_agcount); |
| 2127 | } | 2142 | } |
| 2128 | 2143 | ||
| 2144 | /* | ||
| 2145 | * Now that mp has been modified according to the remount options, we | ||
| 2146 | * do a final option validation with xfs_finish_flags() just like it is | ||
| 2147 | * just like it is done during mount. We cannot use | ||
| 2148 | * done during mount. We cannot use xfs_finish_flags() on new_mp as it | ||
| 2149 | * contains only the user given options. | ||
| 2150 | */ | ||
| 2151 | error = xfs_finish_flags(mp); | ||
| 2152 | if (error) | ||
| 2153 | return error; | ||
| 2154 | |||
| 2129 | /* ro -> rw */ | 2155 | /* ro -> rw */ |
| 2130 | if (xfs_is_readonly(mp) && !(flags & SB_RDONLY)) { | 2156 | if (xfs_is_readonly(mp) && !(flags & SB_RDONLY)) { |
| 2131 | error = xfs_remount_rw(mp); | 2157 | error = xfs_remount_rw(mp); |
| @@ -315,7 +315,7 @@ xfs_ail_splice( · 314 unmodified lines | |||
| 315 | } | 315 | } |
| 316 | 316 | ||
| 317 | /* | 317 | /* |
| 318 | * Delete the given item from the AIL. Return a pointer to the item. | 318 | * Delete the given item from the AIL. |
| 319 | */ | 319 | */ |
| 320 | static void | 320 | static void |
| 321 | xfs_ail_delete( | 321 | xfs_ail_delete( |
| @@ -777,26 +777,28 @@ xfs_ail_update_finish( · 455 unmodified lines | |||
| 777 | } | 777 | } |
| 778 | 778 | ||
| 779 | /* | 779 | /* |
| 780 | * xfs_trans_ail_update - bulk AIL insertion operation. | 780 | * xfs_trans_ail_update_bulk - bulk AIL insertion operation. |
| 781 | * | 781 | * |
| 782 | * @xfs_trans_ail_update takes an array of log items that all need to be | 782 | * @xfs_trans_ail_update_bulk takes an array of log items that all need to be |
| 783 | * positioned at the same LSN in the AIL. If an item is not in the AIL, it will | 783 | * positioned at the same LSN in the AIL. If an item is not in the AIL, it will |
| 784 | * be added. Otherwise, it will be repositioned by removing it and re-adding | 784 | * be added. Otherwise, it will be repositioned by removing it and re-adding |
| 785 | * it to the AIL. If we move the first item in the AIL, update the log tail to | 785 | * it to the AIL. |
| 786 | * match the new minimum LSN in the AIL. | ||
| 787 | * | 786 | * |
| 788 | * This function takes the AIL lock once to execute the update operations on | 787 | * If we move the first item in the AIL, update the log tail to match the new |
| 789 | * all the items in the array, and as such should not be called with the AIL | 788 | * minimum LSN in the AIL. |
| 790 | * lock held. As a result, once we have the AIL lock, we need to check each log | ||
| 791 | * item LSN to confirm it needs to be moved forward in the AIL. | ||
| 792 | * | 789 | * |
| 793 | * To optimise the insert operation, we delete all the items from the AIL in | 790 | * This function should be called with the AIL lock held. |
| 794 | * the first pass, moving them into a temporary list, then splice the temporary | ||
| 795 | * list into the correct position in the AIL. This avoids needing to do an | ||
| 796 | * insert operation on every item. | ||
| 797 | * | 791 | * |
| 798 | * This function must be called with the AIL lock held. The lock is dropped | 792 | * To optimise the insert operation, we add all items to a temporary list, then |
| 799 | * before returning. | 793 | * splice this list into the correct position in the AIL. |
| 794 | * | ||
| 795 | * Items that are already in the AIL are first deleted from their current | ||
| 796 | * location before being added to the temporary list. | ||
| 797 | * | ||
| 798 | * This avoids needing to do an insert operation on every item. | ||
| 799 | * | ||
| 800 | * The AIL lock is dropped by xfs_ail_update_finish() before returning to | ||
| 801 | * the caller. | ||
| 800 | */ | 802 | */ |
| 801 | void | 803 | void |
| 802 | xfs_trans_ail_update_bulk( | 804 | xfs_trans_ail_update_bulk( |
| @@ -807,7 +807,8 @@ xfs_zone_gc_write_chunk( · 806 unmodified lines | |||
| 807 | { | 807 | { |
| 808 | struct xfs_zone_gc_data *data = chunk->data; | 808 | struct xfs_zone_gc_data *data = chunk->data; |
| 809 | struct xfs_mount *mp = chunk->ip->i_mount; | 809 | struct xfs_mount *mp = chunk->ip->i_mount; |
| 810 | unsigned int folio_offset = chunk->bio.bi_io_vec->bv_offset; | 810 | phys_addr_t bvec_paddr = |
| 811 | bvec_phys(bio_first_bvec_all(&chunk->bio)); | ||
| 811 | struct xfs_gc_bio *split_chunk; | 812 | struct xfs_gc_bio *split_chunk; |
| 812 | 813 | ||
| 813 | if (chunk->bio.bi_status) | 814 | if (chunk->bio.bi_status) |
| @@ -822,7 +823,7 @@ xfs_zone_gc_write_chunk( · 8 unmodified lines | |||
| 822 | 823 | ||
| 823 | bio_reset(&chunk->bio, mp->m_rtdev_targp->bt_bdev, REQ_OP_WRITE); | 824 | bio_reset(&chunk->bio, mp->m_rtdev_targp->bt_bdev, REQ_OP_WRITE); |
| 824 | bio_add_folio_nofail(&chunk->bio, chunk->scratch->folio, chunk->len, | 825 | bio_add_folio_nofail(&chunk->bio, chunk->scratch->folio, chunk->len, |
| 825 | folio_offset); | 826 | offset_in_folio(chunk->scratch->folio, bvec_paddr)); |
| 826 | 827 | ||
| 827 | while ((split_chunk = xfs_zone_gc_split_write(data, chunk))) | 828 | while ((split_chunk = xfs_zone_gc_split_write(data, chunk))) |
| 828 | xfs_zone_gc_submit_write(data, split_chunk); | 829 | xfs_zone_gc_submit_write(data, split_chunk); |
| @@ -89,6 +89,7 @@ struct drm_gpusvm_devmem_ops { · 88 unmodified lines | |||
| 89 | * @ops: Pointer to the operations structure for GPU SVM device memory | 89 | * @ops: Pointer to the operations structure for GPU SVM device memory |
| 90 | * @dpagemap: The struct drm_pagemap of the pages this allocation belongs to. | 90 | * @dpagemap: The struct drm_pagemap of the pages this allocation belongs to. |
| 91 | * @size: Size of device memory allocation | 91 | * @size: Size of device memory allocation |
| 92 | * @timeslice_expiration: Timeslice expiration in jiffies | ||
| 92 | */ | 93 | */ |
| 93 | struct drm_gpusvm_devmem { | 94 | struct drm_gpusvm_devmem { |
| 94 | struct device *dev; | 95 | struct device *dev; |
| @@ -97,6 +98,7 @@ struct drm_gpusvm_devmem { · 2 unmodified lines | |||
| 97 | const struct drm_gpusvm_devmem_ops *ops; | 98 | const struct drm_gpusvm_devmem_ops *ops; |
| 98 | struct drm_pagemap *dpagemap; | 99 | struct drm_pagemap *dpagemap; |
| 99 | size_t size; | 100 | size_t size; |
| 101 | u64 timeslice_expiration; | ||
| 100 | }; | 102 | }; |
| 101 | 103 | ||
| 102 | /** | 104 | /** |
| @@ -185,6 +187,31 @@ struct drm_gpusvm_notifier { · 82 unmodified lines | |||
| 185 | } flags; | 187 | } flags; |
| 186 | }; | 188 | }; |
| 187 | 189 | ||
| 190 | /** | ||
| 191 | * struct drm_gpusvm_range_flags - Structure representing a GPU SVM range flags | ||
| 192 | * | ||
| 193 | * @migrate_devmem: Flag indicating whether the range can be migrated to device memory | ||
| 194 | * @unmapped: Flag indicating if the range has been unmapped | ||
| 195 | * @partial_unmap: Flag indicating if the range has been partially unmapped | ||
| 196 | * @has_devmem_pages: Flag indicating if the range has devmem pages | ||
| 197 | * @has_dma_mapping: Flag indicating if the range has a DMA mapping | ||
| 198 | * @__flags: Flags for range in u16 form (used for READ_ONCE) | ||
| 199 | */ | ||
| 200 | struct drm_gpusvm_range_flags { | ||
| 201 | union { | ||
| 202 | struct { | ||
| 203 | /* All flags below must be set upon creation */ | ||
| 204 | u16 migrate_devmem : 1; | ||
| 205 | /* All flags below must be set / cleared under notifier lock */ | ||
| 206 | u16 unmapped : 1; | ||
| 207 | u16 partial_unmap : 1; | ||
| 208 | u16 has_devmem_pages : 1; | ||
| 209 | u16 has_dma_mapping : 1; | ||
| 210 | }; | ||
| 211 | u16 __flags; | ||
| 212 | }; | ||
| 213 | }; | ||
| 214 | |||
| 188 | /** | 215 | /** |
| 189 | * struct drm_gpusvm_range - Structure representing a GPU SVM range | 216 | * struct drm_gpusvm_range - Structure representing a GPU SVM range |
| 190 | * | 217 | * |
| @@ -198,11 +225,6 @@ struct drm_gpusvm_notifier { · 7 unmodified lines | |||
| 198 | * @dpagemap: The struct drm_pagemap of the device pages we're dma-mapping. | 225 | * @dpagemap: The struct drm_pagemap of the device pages we're dma-mapping. |
| 199 | * Note this is assuming only one drm_pagemap per range is allowed. | 226 | * Note this is assuming only one drm_pagemap per range is allowed. |
| 200 | * @flags: Flags for range | 227 | * @flags: Flags for range |
| 201 | * @flags.migrate_devmem: Flag indicating whether the range can be migrated to device memory | ||
| 202 | * @flags.unmapped: Flag indicating if the range has been unmapped | ||
| 203 | * @flags.partial_unmap: Flag indicating if the range has been partially unmapped | ||
| 204 | * @flags.has_devmem_pages: Flag indicating if the range has devmem pages | ||
| 205 | * @flags.has_dma_mapping: Flag indicating if the range has a DMA mapping | ||
| 206 | * | 228 | * |
| 207 | * This structure represents a GPU SVM range used for tracking memory ranges | 229 | * This structure represents a GPU SVM range used for tracking memory ranges |
| 208 | * mapped in a DRM device. | 230 | * mapped in a DRM device. |
| @@ -216,15 +238,7 @@ struct drm_gpusvm_range { · 7 unmodified lines | |||
| 216 | unsigned long notifier_seq; | 238 | unsigned long notifier_seq; |
| 217 | struct drm_pagemap_device_addr *dma_addr; | 239 | struct drm_pagemap_device_addr *dma_addr; |
| 218 | struct drm_pagemap *dpagemap; | 240 | struct drm_pagemap *dpagemap; |
| 219 | struct { | 241 | struct drm_gpusvm_range_flags flags; |
| 220 | /* All flags below must be set upon creation */ | ||
| 221 | u16 migrate_devmem : 1; | ||
| 222 | /* All flags below must be set / cleared under notifier lock */ | ||
| 223 | u16 unmapped : 1; | ||
| 224 | u16 partial_unmap : 1; | ||
| 225 | u16 has_devmem_pages : 1; | ||
| 226 | u16 has_dma_mapping : 1; | ||
| 227 | } flags; | ||
| 228 | }; | 242 | }; |
| 229 | 243 | ||
| 230 | /** | 244 | /** |
| @@ -283,17 +297,22 @@ struct drm_gpusvm { · 52 unmodified lines | |||
| 283 | * @check_pages_threshold: Check CPU pages for present if chunk is less than or | 297 | * @check_pages_threshold: Check CPU pages for present if chunk is less than or |
| 284 | * equal to threshold. If not present, reduce chunk | 298 | * equal to threshold. If not present, reduce chunk |
| 285 | * size. | 299 | * size. |
| 300 | * @timeslice_ms: The timeslice MS which in minimum time a piece of memory | ||
| 301 | * remains with either exclusive GPU or CPU access. | ||
| 286 | * @in_notifier: entering from a MMU notifier | 302 | * @in_notifier: entering from a MMU notifier |
| 287 | * @read_only: operating on read-only memory | 303 | * @read_only: operating on read-only memory |
| 288 | * @devmem_possible: possible to use device memory | 304 | * @devmem_possible: possible to use device memory |
| 305 | * @devmem_only: use only device memory | ||
| 289 | * | 306 | * |
| 290 | * Context that is DRM GPUSVM is operating in (i.e. user arguments). | 307 | * Context that is DRM GPUSVM is operating in (i.e. user arguments). |
| 291 | */ | 308 | */ |
| 292 | struct drm_gpusvm_ctx { | 309 | struct drm_gpusvm_ctx { |
| 293 | unsigned long check_pages_threshold; | 310 | unsigned long check_pages_threshold; |
| 311 | unsigned long timeslice_ms; | ||
| 294 | unsigned int in_notifier :1; | 312 | unsigned int in_notifier :1; |
| 295 | unsigned int read_only :1; | 313 | unsigned int read_only :1; |
| 296 | unsigned int devmem_possible :1; | 314 | unsigned int devmem_possible :1; |
| 315 | unsigned int devmem_only :1; | ||
| 297 | }; | 316 | }; |
| 298 | 317 | ||
| 299 | int drm_gpusvm_init(struct drm_gpusvm *gpusvm, | 318 | int drm_gpusvm_init(struct drm_gpusvm *gpusvm, |
| @@ -11,6 +11,7 @@ · 10 unmodified lines | |||
| 11 | #include <linux/uio.h> | 11 | #include <linux/uio.h> |
| 12 | 12 | ||
| 13 | #define BIO_MAX_VECS 256U | 13 | #define BIO_MAX_VECS 256U |
| 14 | #define BIO_MAX_INLINE_VECS UIO_MAXIOV | ||
| 14 | 15 | ||
| 15 | struct queue_limits; | 16 | struct queue_limits; |
| 16 | 17 | ||
| @@ -1167,13 +1167,6 @@ extern int vmbus_sendpacket(struct vmbus_channel *channel, · 1166 unmodified lines | |||
| 1167 | enum vmbus_packet_type type, | 1167 | enum vmbus_packet_type type, |
| 1168 | u32 flags); | 1168 | u32 flags); |
| 1169 | 1169 | ||
| 1170 | extern int vmbus_sendpacket_pagebuffer(struct vmbus_channel *channel, | ||
| 1171 | struct hv_page_buffer pagebuffers[], | ||
| 1172 | u32 pagecount, | ||
| 1173 | void *buffer, | ||
| 1174 | u32 bufferlen, | ||
| 1175 | u64 requestid); | ||
| 1176 | |||
| 1177 | extern int vmbus_sendpacket_mpb_desc(struct vmbus_channel *channel, | 1170 | extern int vmbus_sendpacket_mpb_desc(struct vmbus_channel *channel, |
| 1178 | struct vmbus_packet_mpb_array *mpb, | 1171 | struct vmbus_packet_mpb_array *mpb, |
| 1179 | u32 desc_size, | 1172 | u32 desc_size, |
| @@ -44,7 +44,6 @@ · 43 unmodified lines | |||
| 44 | #define MICREL_PHY_50MHZ_CLK BIT(0) | 44 | #define MICREL_PHY_50MHZ_CLK BIT(0) |
| 45 | #define MICREL_PHY_FXEN BIT(1) | 45 | #define MICREL_PHY_FXEN BIT(1) |
| 46 | #define MICREL_KSZ8_P1_ERRATA BIT(2) | 46 | #define MICREL_KSZ8_P1_ERRATA BIT(2) |
| 47 | #define MICREL_NO_EEE BIT(3) | ||
| 48 | 47 | ||
| 49 | #define MICREL_KSZ9021_EXTREG_CTRL 0xB | 48 | #define MICREL_KSZ9021_EXTREG_CTRL 0xB |
| 50 | #define MICREL_KSZ9021_EXTREG_DATA_WRITE 0xC | 49 | #define MICREL_KSZ9021_EXTREG_DATA_WRITE 0xC |
| @@ -213,6 +213,15 @@ struct nfs_server { · 212 unmodified lines | |||
| 213 | char *fscache_uniq; /* Uniquifier (or NULL) */ | 213 | char *fscache_uniq; /* Uniquifier (or NULL) */ |
| 214 | #endif | 214 | #endif |
| 215 | 215 | ||
| 216 | /* The following #defines numerically match the NFSv4 equivalents */ | ||
| 217 | #define NFS_FH_NOEXPIRE_WITH_OPEN (0x1) | ||
| 218 | #define NFS_FH_VOLATILE_ANY (0x2) | ||
| 219 | #define NFS_FH_VOL_MIGRATION (0x4) | ||
| 220 | #define NFS_FH_VOL_RENAME (0x8) | ||
| 221 | #define NFS_FH_RENAME_UNSAFE (NFS_FH_VOLATILE_ANY | NFS_FH_VOL_RENAME) | ||
| 222 | u32 fh_expire_type; /* V4 bitmask representing file | ||
| 223 | handle volatility type for | ||
| 224 | this filesystem */ | ||
| 216 | u32 pnfs_blksize; /* layout_blksize attr */ | 225 | u32 pnfs_blksize; /* layout_blksize attr */ |
| 217 | #if IS_ENABLED(CONFIG_NFS_V4) | 226 | #if IS_ENABLED(CONFIG_NFS_V4) |
| 218 | u32 attr_bitmask[3];/* V4 bitmask representing the set | 227 | u32 attr_bitmask[3];/* V4 bitmask representing the set |
| @@ -236,9 +245,6 @@ struct nfs_server { · 17 unmodified lines | |||
| 236 | u32 acl_bitmask; /* V4 bitmask representing the ACEs | 245 | u32 acl_bitmask; /* V4 bitmask representing the ACEs |
| 237 | that are supported on this | 246 | that are supported on this |
| 238 | filesystem */ | 247 | filesystem */ |
| 239 | u32 fh_expire_type; /* V4 bitmask representing file | ||
| 240 | handle volatility type for | ||
| 241 | this filesystem */ | ||
| 242 | struct pnfs_layoutdriver_type *pnfs_curr_ld; /* Active layout driver */ | 248 | struct pnfs_layoutdriver_type *pnfs_curr_ld; /* Active layout driver */ |
| 243 | struct rpc_wait_queue roc_rpcwaitq; | 249 | struct rpc_wait_queue roc_rpcwaitq; |
| 244 | void *pnfs_ld_data; /* per mount point data */ | 250 | void *pnfs_ld_data; /* per mount point data */ |
| @@ -188,6 +188,13 @@ static inline struct alloc_tag *__pgalloc_tag_get(struct page *page) · 187 unmodified lines | |||
| 188 | return tag; | 188 | return tag; |
| 189 | } | 189 | } |
| 190 | 190 | ||
| 191 | static inline struct alloc_tag *pgalloc_tag_get(struct page *page) | ||
| 192 | { | ||
| 193 | if (mem_alloc_profiling_enabled()) | ||
| 194 | return __pgalloc_tag_get(page); | ||
| 195 | return NULL; | ||
| 196 | } | ||
| 197 | |||
| 191 | void pgalloc_tag_split(struct folio *folio, int old_order, int new_order); | 198 | void pgalloc_tag_split(struct folio *folio, int old_order, int new_order); |
| 192 | void pgalloc_tag_swap(struct folio *new, struct folio *old); | 199 | void pgalloc_tag_swap(struct folio *new, struct folio *old); |
| 193 | 200 | ||
| @@ -199,6 +206,7 @@ static inline void clear_page_tag_ref(struct page *page) {} · 5 unmodified lines | |||
| 199 | static inline void alloc_tag_sec_init(void) {} | 206 | static inline void alloc_tag_sec_init(void) {} |
| 200 | static inline void pgalloc_tag_split(struct folio *folio, int old_order, int new_order) {} | 207 | static inline void pgalloc_tag_split(struct folio *folio, int old_order, int new_order) {} |
| 201 | static inline void pgalloc_tag_swap(struct folio *new, struct folio *old) {} | 208 | static inline void pgalloc_tag_swap(struct folio *new, struct folio *old) {} |
| 209 | static inline struct alloc_tag *pgalloc_tag_get(struct page *page) { return NULL; } | ||
| 202 | 210 | ||
| 203 | #endif /* CONFIG_MEM_ALLOC_PROFILING */ | 211 | #endif /* CONFIG_MEM_ALLOC_PROFILING */ |
| 204 | 212 | ||
| @@ -365,7 +365,7 @@ struct sdw_intel_res { · 364 unmodified lines | |||
| 365 | * on e.g. which machine driver to select (I2S mode, HDaudio or | 365 | * on e.g. which machine driver to select (I2S mode, HDaudio or |
| 366 | * SoundWire). | 366 | * SoundWire). |
| 367 | */ | 367 | */ |
| 368 | int sdw_intel_acpi_scan(acpi_handle *parent_handle, | 368 | int sdw_intel_acpi_scan(acpi_handle parent_handle, |
| 369 | struct sdw_intel_acpi_info *info); | 369 | struct sdw_intel_acpi_info *info); |
| 370 | 370 | ||
| 371 | void sdw_intel_process_wakeen_event(struct sdw_intel_ctx *ctx); | 371 | void sdw_intel_process_wakeen_event(struct sdw_intel_ctx *ctx); |
| @@ -224,7 +224,7 @@ enum tpm2_const { · 223 unmodified lines | |||
| 224 | 224 | ||
| 225 | enum tpm2_timeouts { | 225 | enum tpm2_timeouts { |
| 226 | TPM2_TIMEOUT_A = 750, | 226 | TPM2_TIMEOUT_A = 750, |
| 227 | TPM2_TIMEOUT_B = 2000, | 227 | TPM2_TIMEOUT_B = 4000, |
| 228 | TPM2_TIMEOUT_C = 200, | 228 | TPM2_TIMEOUT_C = 200, |
| 229 | TPM2_TIMEOUT_D = 30, | 229 | TPM2_TIMEOUT_D = 30, |
| 230 | TPM2_DURATION_SHORT = 20, | 230 | TPM2_DURATION_SHORT = 20, |
| @@ -257,6 +257,7 @@ enum tpm2_return_codes { · 26 unmodified lines | |||
| 257 | TPM2_RC_TESTING = 0x090A, /* RC_WARN */ | 257 | TPM2_RC_TESTING = 0x090A, /* RC_WARN */ |
| 258 | TPM2_RC_REFERENCE_H0 = 0x0910, | 258 | TPM2_RC_REFERENCE_H0 = 0x0910, |
| 259 | TPM2_RC_RETRY = 0x0922, | 259 | TPM2_RC_RETRY = 0x0922, |
| 260 | TPM2_RC_SESSION_MEMORY = 0x0903, | ||
| 260 | }; | 261 | }; |
| 261 | 262 | ||
| 262 | enum tpm2_command_codes { | 263 | enum tpm2_command_codes { |
| @@ -437,6 +438,24 @@ static inline u32 tpm2_rc_value(u32 rc) · 174 unmodified lines | |||
| 437 | return (rc & BIT(7)) ? rc & 0xbf : rc; | 438 | return (rc & BIT(7)) ? rc & 0xbf : rc; |
| 438 | } | 439 | } |
| 439 | 440 | ||
| 441 | /* | ||
| 442 | * Convert a return value from tpm_transmit_cmd() to POSIX error code. | ||
| 443 | */ | ||
| 444 | static inline ssize_t tpm_ret_to_err(ssize_t ret) | ||
| 445 | { | ||
| 446 | if (ret < 0) | ||
| 447 | return ret; | ||
| 448 | |||
| 449 | switch (tpm2_rc_value(ret)) { | ||
| 450 | case TPM2_RC_SUCCESS: | ||
| 451 | return 0; | ||
| 452 | case TPM2_RC_SESSION_MEMORY: | ||
| 453 | return -ENOMEM; | ||
| 454 | default: | ||
| 455 | return -EFAULT; | ||
| 456 | } | ||
| 457 | } | ||
| 458 | |||
| 440 | #if defined(CONFIG_TCG_TPM) || defined(CONFIG_TCG_TPM_MODULE) | 459 | #if defined(CONFIG_TCG_TPM) || defined(CONFIG_TCG_TPM_MODULE) |
| 441 | 460 | ||
| 442 | extern int tpm_is_tpm2(struct tpm_chip *chip); | 461 | extern int tpm_is_tpm2(struct tpm_chip *chip); |
| @@ -1798,6 +1798,7 @@ struct hci_conn_params *hci_pend_le_action_lookup(struct list_head *list, · 1797 unmodified lines | |||
| 1798 | void hci_uuids_clear(struct hci_dev *hdev); | 1798 | void hci_uuids_clear(struct hci_dev *hdev); |
| 1799 | 1799 | ||
| 1800 | void hci_link_keys_clear(struct hci_dev *hdev); | 1800 | void hci_link_keys_clear(struct hci_dev *hdev); |
| 1801 | u8 *hci_conn_key_enc_size(struct hci_conn *conn); | ||
| 1801 | struct link_key *hci_find_link_key(struct hci_dev *hdev, bdaddr_t *bdaddr); | 1802 | struct link_key *hci_find_link_key(struct hci_dev *hdev, bdaddr_t *bdaddr); |
| 1802 | struct link_key *hci_add_link_key(struct hci_dev *hdev, struct hci_conn *conn, | 1803 | struct link_key *hci_add_link_key(struct hci_dev *hdev, struct hci_conn *conn, |
| 1803 | bdaddr_t *bdaddr, u8 *val, u8 type, | 1804 | bdaddr_t *bdaddr, u8 *val, u8 type, |
| @@ -1031,6 +1031,21 @@ static inline struct sk_buff *__qdisc_dequeue_head(struct qdisc_skb_head *qh) · 1030 unmodified lines | |||
| 1031 | return skb; | 1031 | return skb; |
| 1032 | } | 1032 | } |
| 1033 | 1033 | ||
| 1034 | static inline struct sk_buff *qdisc_dequeue_internal(struct Qdisc *sch, bool direct) | ||
| 1035 | { | ||
| 1036 | struct sk_buff *skb; | ||
| 1037 | |||
| 1038 | skb = __skb_dequeue(&sch->gso_skb); | ||
| 1039 | if (skb) { | ||
| 1040 | sch->q.qlen--; | ||
| 1041 | return skb; | ||
| 1042 | } | ||
| 1043 | if (direct) | ||
| 1044 | return __qdisc_dequeue_head(&sch->q); | ||
| 1045 | else | ||
| 1046 | return sch->dequeue(sch); | ||
| 1047 | } | ||
| 1048 | |||
| 1034 | static inline struct sk_buff *qdisc_dequeue_head(struct Qdisc *sch) | 1049 | static inline struct sk_buff *qdisc_dequeue_head(struct Qdisc *sch) |
| 1035 | { | 1050 | { |
| 1036 | struct sk_buff *skb = __qdisc_dequeue_head(&sch->q); | 1051 | struct sk_buff *skb = __qdisc_dequeue_head(&sch->q); |
| @@ -604,7 +604,7 @@ struct snd_ump_stream_msg_ep_info { · 603 unmodified lines | |||
| 604 | } __packed; | 604 | } __packed; |
| 605 | 605 | ||
| 606 | /* UMP Stream Message: Device Info Notification (128bit) */ | 606 | /* UMP Stream Message: Device Info Notification (128bit) */ |
| 607 | struct snd_ump_stream_msg_devince_info { | 607 | struct snd_ump_stream_msg_device_info { |
| 608 | #ifdef __BIG_ENDIAN_BITFIELD | 608 | #ifdef __BIG_ENDIAN_BITFIELD |
| 609 | /* 0 */ | 609 | /* 0 */ |
| 610 | u32 type:4; | 610 | u32 type:4; |
| @@ -754,7 +754,7 @@ struct snd_ump_stream_msg_fb_name { · 143 unmodified lines | |||
| 754 | union snd_ump_stream_msg { | 754 | union snd_ump_stream_msg { |
| 755 | struct snd_ump_stream_msg_ep_discovery ep_discovery; | 755 | struct snd_ump_stream_msg_ep_discovery ep_discovery; |
| 756 | struct snd_ump_stream_msg_ep_info ep_info; | 756 | struct snd_ump_stream_msg_ep_info ep_info; |
| 757 | struct snd_ump_stream_msg_devince_info device_info; | 757 | struct snd_ump_stream_msg_device_info device_info; |
| 758 | struct snd_ump_stream_msg_stream_cfg stream_cfg; | 758 | struct snd_ump_stream_msg_stream_cfg stream_cfg; |
| 759 | struct snd_ump_stream_msg_fb_discovery fb_discovery; | 759 | struct snd_ump_stream_msg_fb_discovery fb_discovery; |
| 760 | struct snd_ump_stream_msg_fb_info fb_info; | 760 | struct snd_ump_stream_msg_fb_info fb_info; |
| @@ -87,11 +87,6 @@ config CC_CAN_LINK · 86 unmodified lines | |||
| 87 | default $(success,$(srctree)/scripts/cc-can-link.sh $(CC) $(CLANG_FLAGS) $(USERCFLAGS) $(USERLDFLAGS) $(m64-flag)) if 64BIT | 87 | default $(success,$(srctree)/scripts/cc-can-link.sh $(CC) $(CLANG_FLAGS) $(USERCFLAGS) $(USERLDFLAGS) $(m64-flag)) if 64BIT |
| 88 | default $(success,$(srctree)/scripts/cc-can-link.sh $(CC) $(CLANG_FLAGS) $(USERCFLAGS) $(USERLDFLAGS) $(m32-flag)) | 88 | default $(success,$(srctree)/scripts/cc-can-link.sh $(CC) $(CLANG_FLAGS) $(USERCFLAGS) $(USERLDFLAGS) $(m32-flag)) |
| 89 | 89 | ||
| 90 | config CC_CAN_LINK_STATIC | ||
| 91 | bool | ||
| 92 | default $(success,$(srctree)/scripts/cc-can-link.sh $(CC) $(CLANG_FLAGS) $(USERCFLAGS) $(USERLDFLAGS) $(m64-flag) -static) if 64BIT | ||
| 93 | default $(success,$(srctree)/scripts/cc-can-link.sh $(CC) $(CLANG_FLAGS) $(USERCFLAGS) $(USERLDFLAGS) $(m32-flag) -static) | ||
| 94 | |||
| 95 | # Fixed in GCC 14, 13.3, 12.4 and 11.5 | 90 | # Fixed in GCC 14, 13.3, 12.4 and 11.5 |
| 96 | # https://gcc.gnu.org/bugzilla/show_bug.cgi?id=113921 | 91 | # https://gcc.gnu.org/bugzilla/show_bug.cgi?id=113921 |
| 97 | config GCC_ASM_GOTO_OUTPUT_BROKEN | 92 | config GCC_ASM_GOTO_OUTPUT_BROKEN |
| @@ -86,13 +86,8 @@ static inline void napi_show_fdinfo(struct io_ring_ctx *ctx, · 85 unmodified lines | |||
| 86 | } | 86 | } |
| 87 | #endif | 87 | #endif |
| 88 | 88 | ||
| 89 | /* | 89 | static void __io_uring_show_fdinfo(struct io_ring_ctx *ctx, struct seq_file *m) |
| 90 | * Caller holds a reference to the file already, we don't need to do | ||
| 91 | * anything else to get an extra reference. | ||
| 92 | */ | ||
| 93 | __cold void io_uring_show_fdinfo(struct seq_file *m, struct file *file) | ||
| 94 | { | 90 | { |
| 95 | struct io_ring_ctx *ctx = file->private_data; | ||
| 96 | struct io_overflow_cqe *ocqe; | 91 | struct io_overflow_cqe *ocqe; |
| 97 | struct io_rings *r = ctx->rings; | 92 | struct io_rings *r = ctx->rings; |
| 98 | struct rusage sq_usage; | 93 | struct rusage sq_usage; |
| @@ -106,7 +101,6 @@ __cold void io_uring_show_fdinfo(struct seq_file *m, struct file *file) · 7 unmodified lines | |||
| 106 | unsigned int sq_entries, cq_entries; | 101 | unsigned int sq_entries, cq_entries; |
| 107 | int sq_pid = -1, sq_cpu = -1; | 102 | int sq_pid = -1, sq_cpu = -1; |
| 108 | u64 sq_total_time = 0, sq_work_time = 0; | 103 | u64 sq_total_time = 0, sq_work_time = 0; |
| 109 | bool has_lock; | ||
| 110 | unsigned int i; | 104 | unsigned int i; |
| 111 | 105 | ||
| 112 | if (ctx->flags & IORING_SETUP_CQE32) | 106 | if (ctx->flags & IORING_SETUP_CQE32) |
| @@ -176,15 +170,7 @@ __cold void io_uring_show_fdinfo(struct seq_file *m, struct file *file) · 63 unmodified lines | |||
| 176 | seq_printf(m, "\n"); | 170 | seq_printf(m, "\n"); |
| 177 | } | 171 | } |
| 178 | 172 | ||
| 179 | /* | 173 | if (ctx->flags & IORING_SETUP_SQPOLL) { |
| 180 | * Avoid ABBA deadlock between the seq lock and the io_uring mutex, | ||
| 181 | * since fdinfo case grabs it in the opposite direction of normal use | ||
| 182 | * cases. If we fail to get the lock, we just don't iterate any | ||
| 183 | * structures that could be going away outside the io_uring mutex. | ||
| 184 | */ | ||
| 185 | has_lock = mutex_trylock(&ctx->uring_lock); | ||
| 186 | |||
| 187 | if (has_lock && (ctx->flags & IORING_SETUP_SQPOLL)) { | ||
| 188 | struct io_sq_data *sq = ctx->sq_data; | 174 | struct io_sq_data *sq = ctx->sq_data; |
| 189 | 175 | ||
| 190 | /* | 176 | /* |
| @@ -206,7 +192,7 @@ __cold void io_uring_show_fdinfo(struct seq_file *m, struct file *file) · 15 unmodified lines | |||
| 206 | seq_printf(m, "SqTotalTime:\t%llu\n", sq_total_time); | 192 | seq_printf(m, "SqTotalTime:\t%llu\n", sq_total_time); |
| 207 | seq_printf(m, "SqWorkTime:\t%llu\n", sq_work_time); | 193 | seq_printf(m, "SqWorkTime:\t%llu\n", sq_work_time); |
| 208 | seq_printf(m, "UserFiles:\t%u\n", ctx->file_table.data.nr); | 194 | seq_printf(m, "UserFiles:\t%u\n", ctx->file_table.data.nr); |
| 209 | for (i = 0; has_lock && i < ctx->file_table.data.nr; i++) { | 195 | for (i = 0; i < ctx->file_table.data.nr; i++) { |
| 210 | struct file *f = NULL; | 196 | struct file *f = NULL; |
| 211 | 197 | ||
| 212 | if (ctx->file_table.data.nodes[i]) | 198 | if (ctx->file_table.data.nodes[i]) |
| @@ -218,7 +204,7 @@ __cold void io_uring_show_fdinfo(struct seq_file *m, struct file *file) · 5 unmodified lines | |||
| 218 | } | 204 | } |
| 219 | } | 205 | } |
| 220 | seq_printf(m, "UserBufs:\t%u\n", ctx->buf_table.nr); | 206 | seq_printf(m, "UserBufs:\t%u\n", ctx->buf_table.nr); |
| 221 | for (i = 0; has_lock && i < ctx->buf_table.nr; i++) { | 207 | for (i = 0; i < ctx->buf_table.nr; i++) { |
| 222 | struct io_mapped_ubuf *buf = NULL; | 208 | struct io_mapped_ubuf *buf = NULL; |
| 223 | 209 | ||
| 224 | if (ctx->buf_table.nodes[i]) | 210 | if (ctx->buf_table.nodes[i]) |
| @@ -228,7 +214,7 @@ __cold void io_uring_show_fdinfo(struct seq_file *m, struct file *file) · 3 unmodified lines | |||
| 228 | else | 214 | else |
| 229 | seq_printf(m, "%5u: <none>\n", i); | 215 | seq_printf(m, "%5u: <none>\n", i); |
| 230 | } | 216 | } |
| 231 | if (has_lock && !xa_empty(&ctx->personalities)) { | 217 | if (!xa_empty(&ctx->personalities)) { |
| 232 | unsigned long index; | 218 | unsigned long index; |
| 233 | const struct cred *cred; | 219 | const struct cred *cred; |
| 234 | 220 | ||
| @@ -238,7 +224,7 @@ __cold void io_uring_show_fdinfo(struct seq_file *m, struct file *file) · 3 unmodified lines | |||
| 238 | } | 224 | } |
| 239 | 225 | ||
| 240 | seq_puts(m, "PollList:\n"); | 226 | seq_puts(m, "PollList:\n"); |
| 241 | for (i = 0; has_lock && i < (1U << ctx->cancel_table.hash_bits); i++) { | 227 | for (i = 0; i < (1U << ctx->cancel_table.hash_bits); i++) { |
| 242 | struct io_hash_bucket *hb = &ctx->cancel_table.hbs[i]; | 228 | struct io_hash_bucket *hb = &ctx->cancel_table.hbs[i]; |
| 243 | struct io_kiocb *req; | 229 | struct io_kiocb *req; |
| 244 | 230 | ||
| @@ -247,9 +233,6 @@ __cold void io_uring_show_fdinfo(struct seq_file *m, struct file *file) · 2 unmodified lines | |||
| 247 | task_work_pending(req->tctx->task)); | 233 | task_work_pending(req->tctx->task)); |
| 248 | } | 234 | } |
| 249 | 235 | ||
| 250 | if (has_lock) | ||
| 251 | mutex_unlock(&ctx->uring_lock); | ||
| 252 | |||
| 253 | seq_puts(m, "CqOverflowList:\n"); | 236 | seq_puts(m, "CqOverflowList:\n"); |
| 254 | spin_lock(&ctx->completion_lock); | 237 | spin_lock(&ctx->completion_lock); |
| 255 | list_for_each_entry(ocqe, &ctx->cq_overflow_list, list) { | 238 | list_for_each_entry(ocqe, &ctx->cq_overflow_list, list) { |
| @@ -262,4 +245,23 @@ __cold void io_uring_show_fdinfo(struct seq_file *m, struct file *file) · 6 unmodified lines | |||
| 262 | spin_unlock(&ctx->completion_lock); | 245 | spin_unlock(&ctx->completion_lock); |
| 263 | napi_show_fdinfo(ctx, m); | 246 | napi_show_fdinfo(ctx, m); |
| 264 | } | 247 | } |
| 248 | |||
| 249 | /* | ||
| 250 | * Caller holds a reference to the file already, we don't need to do | ||
| 251 | * anything else to get an extra reference. | ||
| 252 | */ | ||
| 253 | __cold void io_uring_show_fdinfo(struct seq_file *m, struct file *file) | ||
| 254 | { | ||
| 255 | struct io_ring_ctx *ctx = file->private_data; | ||
| 256 | |||
| 257 | /* | ||
| 258 | * Avoid ABBA deadlock between the seq lock and the io_uring mutex, | ||
| 259 | * since fdinfo case grabs it in the opposite direction of normal use | ||
| 260 | * cases. | ||
| 261 | */ | ||
| 262 | if (mutex_trylock(&ctx->uring_lock)) { | ||
| 263 | __io_uring_show_fdinfo(ctx, m); | ||
| 264 | mutex_unlock(&ctx->uring_lock); | ||
| 265 | } | ||
| 266 | } | ||
| 265 | #endif | 267 | #endif |
| @@ -116,7 +116,7 @@ static int io_region_init_ptr(struct io_mapped_region *mr) · 115 unmodified lines | |||
| 116 | void *ptr; | 116 | void *ptr; |
| 117 | 117 | ||
| 118 | if (io_check_coalesce_buffer(mr->pages, mr->nr_pages, &ifd)) { | 118 | if (io_check_coalesce_buffer(mr->pages, mr->nr_pages, &ifd)) { |
| 119 | if (ifd.nr_folios == 1) { | 119 | if (ifd.nr_folios == 1 && !PageHighMem(mr->pages[0])) { |
| 120 | mr->ptr = page_address(mr->pages[0]); | 120 | mr->ptr = page_address(mr->pages[0]); |
| 121 | return 0; | 121 | return 0; |
| 122 | } | 122 | } |
| @@ -254,6 +254,11 @@ int io_uring_cmd(struct io_kiocb *req, unsigned int issue_flags) · 253 unmodified lines | |||
| 254 | return -EOPNOTSUPP; | 254 | return -EOPNOTSUPP; |
| 255 | issue_flags |= IO_URING_F_IOPOLL; | 255 | issue_flags |= IO_URING_F_IOPOLL; |
| 256 | req->iopoll_completed = 0; | 256 | req->iopoll_completed = 0; |
| 257 | if (ctx->flags & IORING_SETUP_HYBRID_IOPOLL) { | ||
| 258 | /* make sure every req only blocks once */ | ||
| 259 | req->flags &= ~REQ_F_IOPOLL_STATE; | ||
| 260 | req->iopoll_start = ktime_get_ns(); | ||
| 261 | } | ||
| 257 | } | 262 | } |
| 258 | 263 | ||
| 259 | ret = file->f_op->uring_cmd(ioucmd, issue_flags); | 264 | ret = file->f_op->uring_cmd(ioucmd, issue_flags); |
| @@ -1116,9 +1116,11 @@ void cpuset_update_tasks_cpumask(struct cpuset *cs, struct cpumask *new_cpus) · 1115 unmodified lines | |||
| 1116 | 1116 | ||
| 1117 | if (top_cs) { | 1117 | if (top_cs) { |
| 1118 | /* | 1118 | /* |
| 1119 | * Percpu kthreads in top_cpuset are ignored | 1119 | * PF_NO_SETAFFINITY tasks are ignored. |
| 1120 | * All per cpu kthreads should have PF_NO_SETAFFINITY | ||
| 1121 | * flag set, see kthread_set_per_cpu(). | ||
| 1120 | */ | 1122 | */ |
| 1121 | if (kthread_is_per_cpu(task)) | 1123 | if (task->flags & PF_NO_SETAFFINITY) |
| 1122 | continue; | 1124 | continue; |
| 1123 | cpumask_andnot(new_cpus, possible_mask, subpartitions_cpus); | 1125 | cpumask_andnot(new_cpus, possible_mask, subpartitions_cpus); |
| 1124 | } else { | 1126 | } else { |
| @@ -498,10 +498,6 @@ struct vm_area_struct *vm_area_dup(struct vm_area_struct *orig) · 497 unmodified lines | |||
| 498 | vma_numab_state_init(new); | 498 | vma_numab_state_init(new); |
| 499 | dup_anon_vma_name(orig, new); | 499 | dup_anon_vma_name(orig, new); |
| 500 | 500 | ||
| 501 | /* track_pfn_copy() will later take care of copying internal state. */ | ||
| 502 | if (unlikely(new->vm_flags & VM_PFNMAP)) | ||
| 503 | untrack_pfn_clear(new); | ||
| 504 | |||
| 505 | return new; | 501 | return new; |
| 506 | } | 502 | } |
| 507 | 503 | ||
| @@ -672,6 +668,11 @@ static __latent_entropy int dup_mmap(struct mm_struct *mm, · 164 unmodified lines | |||
| 672 | tmp = vm_area_dup(mpnt); | 668 | tmp = vm_area_dup(mpnt); |
| 673 | if (!tmp) | 669 | if (!tmp) |
| 674 | goto fail_nomem; | 670 | goto fail_nomem; |
| 671 | |||
| 672 | /* track_pfn_copy() will later take care of copying internal state. */ | ||
| 673 | if (unlikely(tmp->vm_flags & VM_PFNMAP)) | ||
| 674 | untrack_pfn_clear(tmp); | ||
| 675 | |||
| 675 | retval = vma_dup_policy(mpnt, tmp); | 676 | retval = vma_dup_policy(mpnt, tmp); |
| 676 | if (retval) | 677 | if (retval) |
| 677 | goto fail_nomem_policy; | 678 | goto fail_nomem_policy; |
| @@ -192,6 +192,11 @@ config GENDWARFKSYMS · 191 unmodified lines | |||
| 192 | depends on !DEBUG_INFO_REDUCED && !DEBUG_INFO_SPLIT | 192 | depends on !DEBUG_INFO_REDUCED && !DEBUG_INFO_SPLIT |
| 193 | # Requires ELF object files. | 193 | # Requires ELF object files. |
| 194 | depends on !LTO | 194 | depends on !LTO |
| 195 | # To avoid conflicts with the discarded __gendwarfksyms_ptr symbols on | ||
| 196 | # X86, requires pahole before commit 47dcb534e253 ("btf_encoder: Stop | ||
| 197 | # indexing symbols for VARs") or after commit 9810758003ce ("btf_encoder: | ||
| 198 | # Verify 0 address DWARF variables are in ELF section"). | ||
| 199 | depends on !X86 || !DEBUG_INFO_BTF || PAHOLE_VERSION < 128 || PAHOLE_VERSION > 129 | ||
| 195 | help | 200 | help |
| 196 | Calculate symbol versions from DWARF debugging information using | 201 | Calculate symbol versions from DWARF debugging information using |
| 197 | gendwarfksyms. Requires DEBUG_INFO to be enabled. | 202 | gendwarfksyms. Requires DEBUG_INFO to be enabled. |
| @@ -1118,8 +1118,38 @@ static void scx_kf_disallow(u32 mask) · 1117 unmodified lines | |||
| 1118 | current->scx.kf_mask &= ~mask; | 1118 | current->scx.kf_mask &= ~mask; |
| 1119 | } | 1119 | } |
| 1120 | 1120 | ||
| 1121 | #define SCX_CALL_OP(mask, op, args...) \ | 1121 | /* |
| 1122 | * Track the rq currently locked. | ||
| 1123 | * | ||
| 1124 | * This allows kfuncs to safely operate on rq from any scx ops callback, | ||
| 1125 | * knowing which rq is already locked. | ||
| 1126 | */ | ||
| 1127 | static DEFINE_PER_CPU(struct rq *, locked_rq); | ||
| 1128 | |||
| 1129 | static inline void update_locked_rq(struct rq *rq) | ||
| 1130 | { | ||
| 1131 | /* | ||
| 1132 | * Check whether @rq is actually locked. This can help expose bugs | ||
| 1133 | * or incorrect assumptions about the context in which a kfunc or | ||
| 1134 | * callback is executed. | ||
| 1135 | */ | ||
| 1136 | if (rq) | ||
| 1137 | lockdep_assert_rq_held(rq); | ||
| 1138 | __this_cpu_write(locked_rq, rq); | ||
| 1139 | } | ||
| 1140 | |||
| 1141 | /* | ||
| 1142 | * Return the rq currently locked from an scx callback, or NULL if no rq is | ||
| 1143 | * locked. | ||
| 1144 | */ | ||
| 1145 | static inline struct rq *scx_locked_rq(void) | ||
| 1146 | { | ||
| 1147 | return __this_cpu_read(locked_rq); | ||
| 1148 | } | ||
| 1149 | |||
| 1150 | #define SCX_CALL_OP(mask, op, rq, args...) \ | ||
| 1122 | do { \ | 1151 | do { \ |
| 1152 | update_locked_rq(rq); \ | ||
| 1123 | if (mask) { \ | 1153 | if (mask) { \ |
| 1124 | scx_kf_allow(mask); \ | 1154 | scx_kf_allow(mask); \ |
| 1125 | scx_ops.op(args); \ | 1155 | scx_ops.op(args); \ |
| @@ -1127,11 +1157,14 @@ do { \ · 1 unmodified line | |||
| 1127 | } else { \ | 1157 | } else { \ |
| 1128 | scx_ops.op(args); \ | 1158 | scx_ops.op(args); \ |
| 1129 | } \ | 1159 | } \ |
| 1160 | update_locked_rq(NULL); \ | ||
| 1130 | } while (0) | 1161 | } while (0) |
| 1131 | 1162 | ||
| 1132 | #define SCX_CALL_OP_RET(mask, op, args...) \ | 1163 | #define SCX_CALL_OP_RET(mask, op, rq, args...) \ |
| 1133 | ({ \ | 1164 | ({ \ |
| 1134 | __typeof__(scx_ops.op(args)) __ret; \ | 1165 | __typeof__(scx_ops.op(args)) __ret; \ |
| 1166 | \ | ||
| 1167 | update_locked_rq(rq); \ | ||
| 1135 | if (mask) { \ | 1168 | if (mask) { \ |
| 1136 | scx_kf_allow(mask); \ | 1169 | scx_kf_allow(mask); \ |
| 1137 | __ret = scx_ops.op(args); \ | 1170 | __ret = scx_ops.op(args); \ |
| @@ -1139,6 +1172,7 @@ do { \ · 1 unmodified line | |||
| 1139 | } else { \ | 1172 | } else { \ |
| 1140 | __ret = scx_ops.op(args); \ | 1173 | __ret = scx_ops.op(args); \ |
| 1141 | } \ | 1174 | } \ |
| 1175 | update_locked_rq(NULL); \ | ||
| 1142 | __ret; \ | 1176 | __ret; \ |
| 1143 | }) | 1177 | }) |
| 1144 | 1178 | ||
| @@ -1153,31 +1187,31 @@ do { \ · 8 unmodified lines | |||
| 1153 | * scx_kf_allowed_on_arg_tasks() to test whether the invocation is allowed on | 1187 | * scx_kf_allowed_on_arg_tasks() to test whether the invocation is allowed on |
| 1154 | * the specific task. | 1188 | * the specific task. |
| 1155 | */ | 1189 | */ |
| 1156 | #define SCX_CALL_OP_TASK(mask, op, task, args...) \ | 1190 | #define SCX_CALL_OP_TASK(mask, op, rq, task, args...) \ |
| 1157 | do { \ | 1191 | do { \ |
| 1158 | BUILD_BUG_ON((mask) & ~__SCX_KF_TERMINAL); \ | 1192 | BUILD_BUG_ON((mask) & ~__SCX_KF_TERMINAL); \ |
| 1159 | current->scx.kf_tasks[0] = task; \ | 1193 | current->scx.kf_tasks[0] = task; \ |
| 1160 | SCX_CALL_OP(mask, op, task, ##args); \ | 1194 | SCX_CALL_OP(mask, op, rq, task, ##args); \ |
| 1161 | current->scx.kf_tasks[0] = NULL; \ | 1195 | current->scx.kf_tasks[0] = NULL; \ |
| 1162 | } while (0) | 1196 | } while (0) |
| 1163 | 1197 | ||
| 1164 | #define SCX_CALL_OP_TASK_RET(mask, op, task, args...) \ | 1198 | #define SCX_CALL_OP_TASK_RET(mask, op, rq, task, args...) \ |
| 1165 | ({ \ | 1199 | ({ \ |
| 1166 | __typeof__(scx_ops.op(task, ##args)) __ret; \ | 1200 | __typeof__(scx_ops.op(task, ##args)) __ret; \ |
| 1167 | BUILD_BUG_ON((mask) & ~__SCX_KF_TERMINAL); \ | 1201 | BUILD_BUG_ON((mask) & ~__SCX_KF_TERMINAL); \ |
| 1168 | current->scx.kf_tasks[0] = task; \ | 1202 | current->scx.kf_tasks[0] = task; \ |
| 1169 | __ret = SCX_CALL_OP_RET(mask, op, task, ##args); \ | 1203 | __ret = SCX_CALL_OP_RET(mask, op, rq, task, ##args); \ |
| 1170 | current->scx.kf_tasks[0] = NULL; \ | 1204 | current->scx.kf_tasks[0] = NULL; \ |
| 1171 | __ret; \ | 1205 | __ret; \ |
| 1172 | }) | 1206 | }) |
| 1173 | 1207 | ||
| 1174 | #define SCX_CALL_OP_2TASKS_RET(mask, op, task0, task1, args...) \ | 1208 | #define SCX_CALL_OP_2TASKS_RET(mask, op, rq, task0, task1, args...) \ |
| 1175 | ({ \ | 1209 | ({ \ |
| 1176 | __typeof__(scx_ops.op(task0, task1, ##args)) __ret; \ | 1210 | __typeof__(scx_ops.op(task0, task1, ##args)) __ret; \ |
| 1177 | BUILD_BUG_ON((mask) & ~__SCX_KF_TERMINAL); \ | 1211 | BUILD_BUG_ON((mask) & ~__SCX_KF_TERMINAL); \ |
| 1178 | current->scx.kf_tasks[0] = task0; \ | 1212 | current->scx.kf_tasks[0] = task0; \ |
| 1179 | current->scx.kf_tasks[1] = task1; \ | 1213 | current->scx.kf_tasks[1] = task1; \ |
| 1180 | __ret = SCX_CALL_OP_RET(mask, op, task0, task1, ##args); \ | 1214 | __ret = SCX_CALL_OP_RET(mask, op, rq, task0, task1, ##args); \ |
| 1181 | current->scx.kf_tasks[0] = NULL; \ | 1215 | current->scx.kf_tasks[0] = NULL; \ |
| 1182 | current->scx.kf_tasks[1] = NULL; \ | 1216 | current->scx.kf_tasks[1] = NULL; \ |
| 1183 | __ret; \ | 1217 | __ret; \ |
| @@ -2172,7 +2206,7 @@ static void do_enqueue_task(struct rq *rq, struct task_struct *p, u64 enq_flags, · 988 unmodified lines | |||
| 2172 | WARN_ON_ONCE(*ddsp_taskp); | 2206 | WARN_ON_ONCE(*ddsp_taskp); |
| 2173 | *ddsp_taskp = p; | 2207 | *ddsp_taskp = p; |
| 2174 | 2208 | ||
| 2175 | SCX_CALL_OP_TASK(SCX_KF_ENQUEUE, enqueue, p, enq_flags); | 2209 | SCX_CALL_OP_TASK(SCX_KF_ENQUEUE, enqueue, rq, p, enq_flags); |
| 2176 | 2210 | ||
| 2177 | *ddsp_taskp = NULL; | 2211 | *ddsp_taskp = NULL; |
| 2178 | if (p->scx.ddsp_dsq_id != SCX_DSQ_INVALID) | 2212 | if (p->scx.ddsp_dsq_id != SCX_DSQ_INVALID) |
| @@ -2269,7 +2303,7 @@ static void enqueue_task_scx(struct rq *rq, struct task_struct *p, int enq_flags · 90 unmodified lines | |||
| 2269 | add_nr_running(rq, 1); | 2303 | add_nr_running(rq, 1); |
| 2270 | 2304 | ||
| 2271 | if (SCX_HAS_OP(runnable) && !task_on_rq_migrating(p)) | 2305 | if (SCX_HAS_OP(runnable) && !task_on_rq_migrating(p)) |
| 2272 | SCX_CALL_OP_TASK(SCX_KF_REST, runnable, p, enq_flags); | 2306 | SCX_CALL_OP_TASK(SCX_KF_REST, runnable, rq, p, enq_flags); |
| 2273 | 2307 | ||
| 2274 | if (enq_flags & SCX_ENQ_WAKEUP) | 2308 | if (enq_flags & SCX_ENQ_WAKEUP) |
| 2275 | touch_core_sched(rq, p); | 2309 | touch_core_sched(rq, p); |
| @@ -2283,7 +2317,7 @@ out: · 7 unmodified lines | |||
| 2283 | __scx_add_event(SCX_EV_SELECT_CPU_FALLBACK, 1); | 2317 | __scx_add_event(SCX_EV_SELECT_CPU_FALLBACK, 1); |
| 2284 | } | 2318 | } |
| 2285 | 2319 | ||
| 2286 | static void ops_dequeue(struct task_struct *p, u64 deq_flags) | 2320 | static void ops_dequeue(struct rq *rq, struct task_struct *p, u64 deq_flags) |
| 2287 | { | 2321 | { |
| 2288 | unsigned long opss; | 2322 | unsigned long opss; |
| 2289 | 2323 | ||
| @@ -2304,7 +2338,7 @@ static void ops_dequeue(struct task_struct *p, u64 deq_flags) · 14 unmodified lines | |||
| 2304 | BUG(); | 2338 | BUG(); |
| 2305 | case SCX_OPSS_QUEUED: | 2339 | case SCX_OPSS_QUEUED: |
| 2306 | if (SCX_HAS_OP(dequeue)) | 2340 | if (SCX_HAS_OP(dequeue)) |
| 2307 | SCX_CALL_OP_TASK(SCX_KF_REST, dequeue, p, deq_flags); | 2341 | SCX_CALL_OP_TASK(SCX_KF_REST, dequeue, rq, p, deq_flags); |
| 2308 | 2342 | ||
| 2309 | if (atomic_long_try_cmpxchg(&p->scx.ops_state, &opss, | 2343 | if (atomic_long_try_cmpxchg(&p->scx.ops_state, &opss, |
| 2310 | SCX_OPSS_NONE)) | 2344 | SCX_OPSS_NONE)) |
| @@ -2337,7 +2371,7 @@ static bool dequeue_task_scx(struct rq *rq, struct task_struct *p, int deq_flags · 26 unmodified lines | |||
| 2337 | return true; | 2371 | return true; |
| 2338 | } | 2372 | } |
| 2339 | 2373 | ||
| 2340 | ops_dequeue(p, deq_flags); | 2374 | ops_dequeue(rq, p, deq_flags); |
| 2341 | 2375 | ||
| 2342 | /* | 2376 | /* |
| 2343 | * A currently running task which is going off @rq first gets dequeued | 2377 | * A currently running task which is going off @rq first gets dequeued |
| @@ -2353,11 +2387,11 @@ static bool dequeue_task_scx(struct rq *rq, struct task_struct *p, int deq_flags · 9 unmodified lines | |||
| 2353 | */ | 2387 | */ |
| 2354 | if (SCX_HAS_OP(stopping) && task_current(rq, p)) { | 2388 | if (SCX_HAS_OP(stopping) && task_current(rq, p)) { |
| 2355 | update_curr_scx(rq); | 2389 | update_curr_scx(rq); |
| 2356 | SCX_CALL_OP_TASK(SCX_KF_REST, stopping, p, false); | 2390 | SCX_CALL_OP_TASK(SCX_KF_REST, stopping, rq, p, false); |
| 2357 | } | 2391 | } |
| 2358 | 2392 | ||
| 2359 | if (SCX_HAS_OP(quiescent) && !task_on_rq_migrating(p)) | 2393 | if (SCX_HAS_OP(quiescent) && !task_on_rq_migrating(p)) |
| 2360 | SCX_CALL_OP_TASK(SCX_KF_REST, quiescent, p, deq_flags); | 2394 | SCX_CALL_OP_TASK(SCX_KF_REST, quiescent, rq, p, deq_flags); |
| 2361 | 2395 | ||
| 2362 | if (deq_flags & SCX_DEQ_SLEEP) | 2396 | if (deq_flags & SCX_DEQ_SLEEP) |
| 2363 | p->scx.flags |= SCX_TASK_DEQD_FOR_SLEEP; | 2397 | p->scx.flags |= SCX_TASK_DEQD_FOR_SLEEP; |
| @@ -2377,7 +2411,7 @@ static void yield_task_scx(struct rq *rq) · 13 unmodified lines | |||
| 2377 | struct task_struct *p = rq->curr; | 2411 | struct task_struct *p = rq->curr; |
| 2378 | 2412 | ||
| 2379 | if (SCX_HAS_OP(yield)) | 2413 | if (SCX_HAS_OP(yield)) |
| 2380 | SCX_CALL_OP_2TASKS_RET(SCX_KF_REST, yield, p, NULL); | 2414 | SCX_CALL_OP_2TASKS_RET(SCX_KF_REST, yield, rq, p, NULL); |
| 2381 | else | 2415 | else |
| 2382 | p->scx.slice = 0; | 2416 | p->scx.slice = 0; |
| 2383 | } | 2417 | } |
| @@ -2387,7 +2421,7 @@ static bool yield_to_task_scx(struct rq *rq, struct task_struct *to) · 3 unmodified lines | |||
| 2387 | struct task_struct *from = rq->curr; | 2421 | struct task_struct *from = rq->curr; |
| 2388 | 2422 | ||
| 2389 | if (SCX_HAS_OP(yield)) | 2423 | if (SCX_HAS_OP(yield)) |
| 2390 | return SCX_CALL_OP_2TASKS_RET(SCX_KF_REST, yield, from, to); | 2424 | return SCX_CALL_OP_2TASKS_RET(SCX_KF_REST, yield, rq, from, to); |
| 2391 | else | 2425 | else |
| 2392 | return false; | 2426 | return false; |
| 2393 | } | 2427 | } |
| @@ -2945,7 +2979,7 @@ static int balance_one(struct rq *rq, struct task_struct *prev) · 551 unmodified lines | |||
| 2945 | * emitted in switch_class(). | 2979 | * emitted in switch_class(). |
| 2946 | */ | 2980 | */ |
| 2947 | if (SCX_HAS_OP(cpu_acquire)) | 2981 | if (SCX_HAS_OP(cpu_acquire)) |
| 2948 | SCX_CALL_OP(SCX_KF_REST, cpu_acquire, cpu_of(rq), NULL); | 2982 | SCX_CALL_OP(SCX_KF_REST, cpu_acquire, rq, cpu_of(rq), NULL); |
| 2949 | rq->scx.cpu_released = false; | 2983 | rq->scx.cpu_released = false; |
| 2950 | } | 2984 | } |
| 2951 | 2985 | ||
| @@ -2990,7 +3024,7 @@ static int balance_one(struct rq *rq, struct task_struct *prev) · 38 unmodified lines | |||
| 2990 | do { | 3024 | do { |
| 2991 | dspc->nr_tasks = 0; | 3025 | dspc->nr_tasks = 0; |
| 2992 | 3026 | ||
| 2993 | SCX_CALL_OP(SCX_KF_DISPATCH, dispatch, cpu_of(rq), | 3027 | SCX_CALL_OP(SCX_KF_DISPATCH, dispatch, rq, cpu_of(rq), |
| 2994 | prev_on_scx ? prev : NULL); | 3028 | prev_on_scx ? prev : NULL); |
| 2995 | 3029 | ||
| 2996 | flush_dispatch_buf(rq); | 3030 | flush_dispatch_buf(rq); |
| @@ -3104,7 +3138,7 @@ static void set_next_task_scx(struct rq *rq, struct task_struct *p, bool first) · 107 unmodified lines | |||
| 3104 | * Core-sched might decide to execute @p before it is | 3138 | * Core-sched might decide to execute @p before it is |
| 3105 | * dispatched. Call ops_dequeue() to notify the BPF scheduler. | 3139 | * dispatched. Call ops_dequeue() to notify the BPF scheduler. |
| 3106 | */ | 3140 | */ |
| 3107 | ops_dequeue(p, SCX_DEQ_CORE_SCHED_EXEC); | 3141 | ops_dequeue(rq, p, SCX_DEQ_CORE_SCHED_EXEC); |
| 3108 | dispatch_dequeue(rq, p); | 3142 | dispatch_dequeue(rq, p); |
| 3109 | } | 3143 | } |
| 3110 | 3144 | ||
| @@ -3112,7 +3146,7 @@ static void set_next_task_scx(struct rq *rq, struct task_struct *p, bool first) · 1 unmodified line | |||
| 3112 | 3146 | ||
| 3113 | /* see dequeue_task_scx() on why we skip when !QUEUED */ | 3147 | /* see dequeue_task_scx() on why we skip when !QUEUED */ |
| 3114 | if (SCX_HAS_OP(running) && (p->scx.flags & SCX_TASK_QUEUED)) | 3148 | if (SCX_HAS_OP(running) && (p->scx.flags & SCX_TASK_QUEUED)) |
| 3115 | SCX_CALL_OP_TASK(SCX_KF_REST, running, p); | 3149 | SCX_CALL_OP_TASK(SCX_KF_REST, running, rq, p); |
| 3116 | 3150 | ||
| 3117 | clr_task_runnable(p, true); | 3151 | clr_task_runnable(p, true); |
| 3118 | 3152 | ||
| @@ -3193,8 +3227,7 @@ static void switch_class(struct rq *rq, struct task_struct *next) · 74 unmodified lines | |||
| 3193 | .task = next, | 3227 | .task = next, |
| 3194 | }; | 3228 | }; |
| 3195 | 3229 | ||
| 3196 | SCX_CALL_OP(SCX_KF_CPU_RELEASE, | 3230 | SCX_CALL_OP(SCX_KF_CPU_RELEASE, cpu_release, rq, cpu_of(rq), &args); |
| 3197 | cpu_release, cpu_of(rq), &args); | ||
| 3198 | } | 3231 | } |
| 3199 | rq->scx.cpu_released = true; | 3232 | rq->scx.cpu_released = true; |
| 3200 | } | 3233 | } |
| @@ -3207,7 +3240,7 @@ static void put_prev_task_scx(struct rq *rq, struct task_struct *p, · 6 unmodified lines | |||
| 3207 | 3240 | ||
| 3208 | /* see dequeue_task_scx() on why we skip when !QUEUED */ | 3241 | /* see dequeue_task_scx() on why we skip when !QUEUED */ |
| 3209 | if (SCX_HAS_OP(stopping) && (p->scx.flags & SCX_TASK_QUEUED)) | 3242 | if (SCX_HAS_OP(stopping) && (p->scx.flags & SCX_TASK_QUEUED)) |
| 3210 | SCX_CALL_OP_TASK(SCX_KF_REST, stopping, p, true); | 3243 | SCX_CALL_OP_TASK(SCX_KF_REST, stopping, rq, p, true); |
| 3211 | 3244 | ||
| 3212 | if (p->scx.flags & SCX_TASK_QUEUED) { | 3245 | if (p->scx.flags & SCX_TASK_QUEUED) { |
| 3213 | set_task_runnable(rq, p); | 3246 | set_task_runnable(rq, p); |
| @@ -3348,7 +3381,7 @@ bool scx_prio_less(const struct task_struct *a, const struct task_struct *b, · 134 unmodified lines | |||
| 3348 | * verifier. | 3381 | * verifier. |
| 3349 | */ | 3382 | */ |
| 3350 | if (SCX_HAS_OP(core_sched_before) && !scx_rq_bypassing(task_rq(a))) | 3383 | if (SCX_HAS_OP(core_sched_before) && !scx_rq_bypassing(task_rq(a))) |
| 3351 | return SCX_CALL_OP_2TASKS_RET(SCX_KF_REST, core_sched_before, | 3384 | return SCX_CALL_OP_2TASKS_RET(SCX_KF_REST, core_sched_before, NULL, |
| 3352 | (struct task_struct *)a, | 3385 | (struct task_struct *)a, |
| 3353 | (struct task_struct *)b); | 3386 | (struct task_struct *)b); |
| 3354 | else | 3387 | else |
| @@ -3385,7 +3418,7 @@ static int select_task_rq_scx(struct task_struct *p, int prev_cpu, int wake_flag · 30 unmodified lines | |||
| 3385 | *ddsp_taskp = p; | 3418 | *ddsp_taskp = p; |
| 3386 | 3419 | ||
| 3387 | cpu = SCX_CALL_OP_TASK_RET(SCX_KF_ENQUEUE | SCX_KF_SELECT_CPU, | 3420 | cpu = SCX_CALL_OP_TASK_RET(SCX_KF_ENQUEUE | SCX_KF_SELECT_CPU, |
| 3388 | select_cpu, p, prev_cpu, wake_flags); | 3421 | select_cpu, NULL, p, prev_cpu, wake_flags); |
| 3389 | p->scx.selected_cpu = cpu; | 3422 | p->scx.selected_cpu = cpu; |
| 3390 | *ddsp_taskp = NULL; | 3423 | *ddsp_taskp = NULL; |
| 3391 | if (ops_cpu_valid(cpu, "from ops.select_cpu()")) | 3424 | if (ops_cpu_valid(cpu, "from ops.select_cpu()")) |
| @@ -3430,8 +3463,8 @@ static void set_cpus_allowed_scx(struct task_struct *p, · 38 unmodified lines | |||
| 3430 | * designation pointless. Cast it away when calling the operation. | 3463 | * designation pointless. Cast it away when calling the operation. |
| 3431 | */ | 3464 | */ |
| 3432 | if (SCX_HAS_OP(set_cpumask)) | 3465 | if (SCX_HAS_OP(set_cpumask)) |
| 3433 | SCX_CALL_OP_TASK(SCX_KF_REST, set_cpumask, p, | 3466 | SCX_CALL_OP_TASK(SCX_KF_REST, set_cpumask, NULL, |
| 3434 | (struct cpumask *)p->cpus_ptr); | 3467 | p, (struct cpumask *)p->cpus_ptr); |
| 3435 | } | 3468 | } |
| 3436 | 3469 | ||
| 3437 | static void handle_hotplug(struct rq *rq, bool online) | 3470 | static void handle_hotplug(struct rq *rq, bool online) |
| @@ -3444,9 +3477,9 @@ static void handle_hotplug(struct rq *rq, bool online) · 6 unmodified lines | |||
| 3444 | scx_idle_update_selcpu_topology(&scx_ops); | 3477 | scx_idle_update_selcpu_topology(&scx_ops); |
| 3445 | 3478 | ||
| 3446 | if (online && SCX_HAS_OP(cpu_online)) | 3479 | if (online && SCX_HAS_OP(cpu_online)) |
| 3447 | SCX_CALL_OP(SCX_KF_UNLOCKED, cpu_online, cpu); | 3480 | SCX_CALL_OP(SCX_KF_UNLOCKED, cpu_online, NULL, cpu); |
| 3448 | else if (!online && SCX_HAS_OP(cpu_offline)) | 3481 | else if (!online && SCX_HAS_OP(cpu_offline)) |
| 3449 | SCX_CALL_OP(SCX_KF_UNLOCKED, cpu_offline, cpu); | 3482 | SCX_CALL_OP(SCX_KF_UNLOCKED, cpu_offline, NULL, cpu); |
| 3450 | else | 3483 | else |
| 3451 | scx_ops_exit(SCX_ECODE_ACT_RESTART | SCX_ECODE_RSN_HOTPLUG, | 3484 | scx_ops_exit(SCX_ECODE_ACT_RESTART | SCX_ECODE_RSN_HOTPLUG, |
| 3452 | "cpu %d going %s, exiting scheduler", cpu, | 3485 | "cpu %d going %s, exiting scheduler", cpu, |
| @@ -3550,7 +3583,7 @@ static void task_tick_scx(struct rq *rq, struct task_struct *curr, int queued) · 97 unmodified lines | |||
| 3550 | curr->scx.slice = 0; | 3583 | curr->scx.slice = 0; |
| 3551 | touch_core_sched(rq, curr); | 3584 | touch_core_sched(rq, curr); |
| 3552 | } else if (SCX_HAS_OP(tick)) { | 3585 | } else if (SCX_HAS_OP(tick)) { |
| 3553 | SCX_CALL_OP_TASK(SCX_KF_REST, tick, curr); | 3586 | SCX_CALL_OP_TASK(SCX_KF_REST, tick, rq, curr); |
| 3554 | } | 3587 | } |
| 3555 | 3588 | ||
| 3556 | if (!curr->scx.slice) | 3589 | if (!curr->scx.slice) |
| @@ -3627,7 +3660,7 @@ static int scx_ops_init_task(struct task_struct *p, struct task_group *tg, bool · 70 unmodified lines | |||
| 3627 | .fork = fork, | 3660 | .fork = fork, |
| 3628 | }; | 3661 | }; |
| 3629 | 3662 | ||
| 3630 | ret = SCX_CALL_OP_RET(SCX_KF_UNLOCKED, init_task, p, &args); | 3663 | ret = SCX_CALL_OP_RET(SCX_KF_UNLOCKED, init_task, NULL, p, &args); |
| 3631 | if (unlikely(ret)) { | 3664 | if (unlikely(ret)) { |
| 3632 | ret = ops_sanitize_err("init_task", ret); | 3665 | ret = ops_sanitize_err("init_task", ret); |
| 3633 | return ret; | 3666 | return ret; |
| @@ -3668,9 +3701,10 @@ static int scx_ops_init_task(struct task_struct *p, struct task_group *tg, bool · 34 unmodified lines | |||
| 3668 | 3701 | ||
| 3669 | static void scx_ops_enable_task(struct task_struct *p) | 3702 | static void scx_ops_enable_task(struct task_struct *p) |
| 3670 | { | 3703 | { |
| 3704 | struct rq *rq = task_rq(p); | ||
| 3671 | u32 weight; | 3705 | u32 weight; |
| 3672 | 3706 | ||
| 3673 | lockdep_assert_rq_held(task_rq(p)); | 3707 | lockdep_assert_rq_held(rq); |
| 3674 | 3708 | ||
| 3675 | /* | 3709 | /* |
| 3676 | * Set the weight before calling ops.enable() so that the scheduler | 3710 | * Set the weight before calling ops.enable() so that the scheduler |
| @@ -3684,20 +3718,22 @@ static void scx_ops_enable_task(struct task_struct *p) · 7 unmodified lines | |||
| 3684 | p->scx.weight = sched_weight_to_cgroup(weight); | 3718 | p->scx.weight = sched_weight_to_cgroup(weight); |
| 3685 | 3719 | ||
| 3686 | if (SCX_HAS_OP(enable)) | 3720 | if (SCX_HAS_OP(enable)) |
| 3687 | SCX_CALL_OP_TASK(SCX_KF_REST, enable, p); | 3721 | SCX_CALL_OP_TASK(SCX_KF_REST, enable, rq, p); |
| 3688 | scx_set_task_state(p, SCX_TASK_ENABLED); | 3722 | scx_set_task_state(p, SCX_TASK_ENABLED); |
| 3689 | 3723 | ||
| 3690 | if (SCX_HAS_OP(set_weight)) | 3724 | if (SCX_HAS_OP(set_weight)) |
| 3691 | SCX_CALL_OP_TASK(SCX_KF_REST, set_weight, p, p->scx.weight); | 3725 | SCX_CALL_OP_TASK(SCX_KF_REST, set_weight, rq, p, p->scx.weight); |
| 3692 | } | 3726 | } |
| 3693 | 3727 | ||
| 3694 | static void scx_ops_disable_task(struct task_struct *p) | 3728 | static void scx_ops_disable_task(struct task_struct *p) |
| 3695 | { | 3729 | { |
| 3696 | lockdep_assert_rq_held(task_rq(p)); | 3730 | struct rq *rq = task_rq(p); |
| 3731 | |||
| 3732 | lockdep_assert_rq_held(rq); | ||
| 3697 | WARN_ON_ONCE(scx_get_task_state(p) != SCX_TASK_ENABLED); | 3733 | WARN_ON_ONCE(scx_get_task_state(p) != SCX_TASK_ENABLED); |
| 3698 | 3734 | ||
| 3699 | if (SCX_HAS_OP(disable)) | 3735 | if (SCX_HAS_OP(disable)) |
| 3700 | SCX_CALL_OP_TASK(SCX_KF_REST, disable, p); | 3736 | SCX_CALL_OP_TASK(SCX_KF_REST, disable, rq, p); |
| 3701 | scx_set_task_state(p, SCX_TASK_READY); | 3737 | scx_set_task_state(p, SCX_TASK_READY); |
| 3702 | } | 3738 | } |
| 3703 | 3739 | ||
| @@ -3726,7 +3762,7 @@ static void scx_ops_exit_task(struct task_struct *p) · 22 unmodified lines | |||
| 3726 | } | 3762 | } |
| 3727 | 3763 | ||
| 3728 | if (SCX_HAS_OP(exit_task)) | 3764 | if (SCX_HAS_OP(exit_task)) |
| 3729 | SCX_CALL_OP_TASK(SCX_KF_REST, exit_task, p, &args); | 3765 | SCX_CALL_OP_TASK(SCX_KF_REST, exit_task, task_rq(p), p, &args); |
| 3730 | scx_set_task_state(p, SCX_TASK_NONE); | 3766 | scx_set_task_state(p, SCX_TASK_NONE); |
| 3731 | } | 3767 | } |
| 3732 | 3768 | ||
| @@ -3835,7 +3871,7 @@ static void reweight_task_scx(struct rq *rq, struct task_struct *p, · 102 unmodified lines | |||
| 3835 | 3871 | ||
| 3836 | p->scx.weight = sched_weight_to_cgroup(scale_load_down(lw->weight)); | 3872 | p->scx.weight = sched_weight_to_cgroup(scale_load_down(lw->weight)); |
| 3837 | if (SCX_HAS_OP(set_weight)) | 3873 | if (SCX_HAS_OP(set_weight)) |
| 3838 | SCX_CALL_OP_TASK(SCX_KF_REST, set_weight, p, p->scx.weight); | 3874 | SCX_CALL_OP_TASK(SCX_KF_REST, set_weight, rq, p, p->scx.weight); |
| 3839 | } | 3875 | } |
| 3840 | 3876 | ||
| 3841 | static void prio_changed_scx(struct rq *rq, struct task_struct *p, int oldprio) | 3877 | static void prio_changed_scx(struct rq *rq, struct task_struct *p, int oldprio) |
| @@ -3851,8 +3887,8 @@ static void switching_to_scx(struct rq *rq, struct task_struct *p) · 9 unmodified lines | |||
| 3851 | * different scheduler class. Keep the BPF scheduler up-to-date. | 3887 | * different scheduler class. Keep the BPF scheduler up-to-date. |
| 3852 | */ | 3888 | */ |
| 3853 | if (SCX_HAS_OP(set_cpumask)) | 3889 | if (SCX_HAS_OP(set_cpumask)) |
| 3854 | SCX_CALL_OP_TASK(SCX_KF_REST, set_cpumask, p, | 3890 | SCX_CALL_OP_TASK(SCX_KF_REST, set_cpumask, rq, |
| 3855 | (struct cpumask *)p->cpus_ptr); | 3891 | p, (struct cpumask *)p->cpus_ptr); |
| 3856 | } | 3892 | } |
| 3857 | 3893 | ||
| 3858 | static void switched_from_scx(struct rq *rq, struct task_struct *p) | 3894 | static void switched_from_scx(struct rq *rq, struct task_struct *p) |
| @@ -3913,7 +3949,7 @@ int scx_tg_online(struct task_group *tg) · 54 unmodified lines | |||
| 3913 | struct scx_cgroup_init_args args = | 3949 | struct scx_cgroup_init_args args = |
| 3914 | { .weight = tg->scx_weight }; | 3950 | { .weight = tg->scx_weight }; |
| 3915 | 3951 | ||
| 3916 | ret = SCX_CALL_OP_RET(SCX_KF_UNLOCKED, cgroup_init, | 3952 | ret = SCX_CALL_OP_RET(SCX_KF_UNLOCKED, cgroup_init, NULL, |
| 3917 | tg->css.cgroup, &args); | 3953 | tg->css.cgroup, &args); |
| 3918 | if (ret) | 3954 | if (ret) |
| 3919 | ret = ops_sanitize_err("cgroup_init", ret); | 3955 | ret = ops_sanitize_err("cgroup_init", ret); |
| @@ -3935,7 +3971,7 @@ void scx_tg_offline(struct task_group *tg) · 15 unmodified lines | |||
| 3935 | percpu_down_read(&scx_cgroup_rwsem); | 3971 | percpu_down_read(&scx_cgroup_rwsem); |
| 3936 | 3972 | ||
| 3937 | if (SCX_HAS_OP(cgroup_exit) && (tg->scx_flags & SCX_TG_INITED)) | 3973 | if (SCX_HAS_OP(cgroup_exit) && (tg->scx_flags & SCX_TG_INITED)) |
| 3938 | SCX_CALL_OP(SCX_KF_UNLOCKED, cgroup_exit, tg->css.cgroup); | 3974 | SCX_CALL_OP(SCX_KF_UNLOCKED, cgroup_exit, NULL, tg->css.cgroup); |
| 3939 | tg->scx_flags &= ~(SCX_TG_ONLINE | SCX_TG_INITED); | 3975 | tg->scx_flags &= ~(SCX_TG_ONLINE | SCX_TG_INITED); |
| 3940 | 3976 | ||
| 3941 | percpu_up_read(&scx_cgroup_rwsem); | 3977 | percpu_up_read(&scx_cgroup_rwsem); |
| @@ -3968,7 +4004,7 @@ int scx_cgroup_can_attach(struct cgroup_taskset *tset) · 26 unmodified lines | |||
| 3968 | continue; | 4004 | continue; |
| 3969 | 4005 | ||
| 3970 | if (SCX_HAS_OP(cgroup_prep_move)) { | 4006 | if (SCX_HAS_OP(cgroup_prep_move)) { |
| 3971 | ret = SCX_CALL_OP_RET(SCX_KF_UNLOCKED, cgroup_prep_move, | 4007 | ret = SCX_CALL_OP_RET(SCX_KF_UNLOCKED, cgroup_prep_move, NULL, |
| 3972 | p, from, css->cgroup); | 4008 | p, from, css->cgroup); |
| 3973 | if (ret) | 4009 | if (ret) |
| 3974 | goto err; | 4010 | goto err; |
| @@ -3982,8 +4018,8 @@ int scx_cgroup_can_attach(struct cgroup_taskset *tset) · 7 unmodified lines | |||
| 3982 | err: | 4018 | err: |
| 3983 | cgroup_taskset_for_each(p, css, tset) { | 4019 | cgroup_taskset_for_each(p, css, tset) { |
| 3984 | if (SCX_HAS_OP(cgroup_cancel_move) && p->scx.cgrp_moving_from) | 4020 | if (SCX_HAS_OP(cgroup_cancel_move) && p->scx.cgrp_moving_from) |
| 3985 | SCX_CALL_OP(SCX_KF_UNLOCKED, cgroup_cancel_move, p, | 4021 | SCX_CALL_OP(SCX_KF_UNLOCKED, cgroup_cancel_move, NULL, |
| 3986 | p->scx.cgrp_moving_from, css->cgroup); | 4022 | p, p->scx.cgrp_moving_from, css->cgroup); |
| 3987 | p->scx.cgrp_moving_from = NULL; | 4023 | p->scx.cgrp_moving_from = NULL; |
| 3988 | } | 4024 | } |
| 3989 | 4025 | ||
| @@ -4001,8 +4037,8 @@ void scx_cgroup_move_task(struct task_struct *p) · 11 unmodified lines | |||
| 4001 | * cgrp_moving_from set. | 4037 | * cgrp_moving_from set. |
| 4002 | */ | 4038 | */ |
| 4003 | if (SCX_HAS_OP(cgroup_move) && !WARN_ON_ONCE(!p->scx.cgrp_moving_from)) | 4039 | if (SCX_HAS_OP(cgroup_move) && !WARN_ON_ONCE(!p->scx.cgrp_moving_from)) |
| 4004 | SCX_CALL_OP_TASK(SCX_KF_UNLOCKED, cgroup_move, p, | 4040 | SCX_CALL_OP_TASK(SCX_KF_UNLOCKED, cgroup_move, NULL, |
| 4005 | p->scx.cgrp_moving_from, tg_cgrp(task_group(p))); | 4041 | p, p->scx.cgrp_moving_from, tg_cgrp(task_group(p))); |
| 4006 | p->scx.cgrp_moving_from = NULL; | 4042 | p->scx.cgrp_moving_from = NULL; |
| 4007 | } | 4043 | } |
| 4008 | 4044 | ||
| @@ -4021,8 +4057,8 @@ void scx_cgroup_cancel_attach(struct cgroup_taskset *tset) · 12 unmodified lines | |||
| 4021 | 4057 | ||
| 4022 | cgroup_taskset_for_each(p, css, tset) { | 4058 | cgroup_taskset_for_each(p, css, tset) { |
| 4023 | if (SCX_HAS_OP(cgroup_cancel_move) && p->scx.cgrp_moving_from) | 4059 | if (SCX_HAS_OP(cgroup_cancel_move) && p->scx.cgrp_moving_from) |
| 4024 | SCX_CALL_OP(SCX_KF_UNLOCKED, cgroup_cancel_move, p, | 4060 | SCX_CALL_OP(SCX_KF_UNLOCKED, cgroup_cancel_move, NULL, |
| 4025 | p->scx.cgrp_moving_from, css->cgroup); | 4061 | p, p->scx.cgrp_moving_from, css->cgroup); |
| 4026 | p->scx.cgrp_moving_from = NULL; | 4062 | p->scx.cgrp_moving_from = NULL; |
| 4027 | } | 4063 | } |
| 4028 | out_unlock: | 4064 | out_unlock: |
| @@ -4035,7 +4071,7 @@ void scx_group_set_weight(struct task_group *tg, unsigned long weight) · 6 unmodified lines | |||
| 4035 | 4071 | ||
| 4036 | if (scx_cgroup_enabled && tg->scx_weight != weight) { | 4072 | if (scx_cgroup_enabled && tg->scx_weight != weight) { |
| 4037 | if (SCX_HAS_OP(cgroup_set_weight)) | 4073 | if (SCX_HAS_OP(cgroup_set_weight)) |
| 4038 | SCX_CALL_OP(SCX_KF_UNLOCKED, cgroup_set_weight, | 4074 | SCX_CALL_OP(SCX_KF_UNLOCKED, cgroup_set_weight, NULL, |
| 4039 | tg_cgrp(tg), weight); | 4075 | tg_cgrp(tg), weight); |
| 4040 | tg->scx_weight = weight; | 4076 | tg->scx_weight = weight; |
| 4041 | } | 4077 | } |
| @@ -4224,7 +4260,7 @@ static void scx_cgroup_exit(void) · 182 unmodified lines | |||
| 4224 | continue; | 4260 | continue; |
| 4225 | rcu_read_unlock(); | 4261 | rcu_read_unlock(); |
| 4226 | 4262 | ||
| 4227 | SCX_CALL_OP(SCX_KF_UNLOCKED, cgroup_exit, css->cgroup); | 4263 | SCX_CALL_OP(SCX_KF_UNLOCKED, cgroup_exit, NULL, css->cgroup); |
| 4228 | 4264 | ||
| 4229 | rcu_read_lock(); | 4265 | rcu_read_lock(); |
| 4230 | css_put(css); | 4266 | css_put(css); |
| @@ -4261,7 +4297,7 @@ static int scx_cgroup_init(void) · 30 unmodified lines | |||
| 4261 | continue; | 4297 | continue; |
| 4262 | rcu_read_unlock(); | 4298 | rcu_read_unlock(); |
| 4263 | 4299 | ||
| 4264 | ret = SCX_CALL_OP_RET(SCX_KF_UNLOCKED, cgroup_init, | 4300 | ret = SCX_CALL_OP_RET(SCX_KF_UNLOCKED, cgroup_init, NULL, |
| 4265 | css->cgroup, &args); | 4301 | css->cgroup, &args); |
| 4266 | if (ret) { | 4302 | if (ret) { |
| 4267 | css_put(css); | 4303 | css_put(css); |
| @@ -4758,7 +4794,7 @@ static void scx_ops_disable_workfn(struct kthread_work *work) · 490 unmodified lines | |||
| 4758 | } | 4794 | } |
| 4759 | 4795 | ||
| 4760 | if (scx_ops.exit) | 4796 | if (scx_ops.exit) |
| 4761 | SCX_CALL_OP(SCX_KF_UNLOCKED, exit, ei); | 4797 | SCX_CALL_OP(SCX_KF_UNLOCKED, exit, NULL, ei); |
| 4762 | 4798 | ||
| 4763 | cancel_delayed_work_sync(&scx_watchdog_work); | 4799 | cancel_delayed_work_sync(&scx_watchdog_work); |
| 4764 | 4800 | ||
| @@ -4965,7 +5001,7 @@ static void scx_dump_task(struct seq_buf *s, struct scx_dump_ctx *dctx, · 200 unmodified lines | |||
| 4965 | 5001 | ||
| 4966 | if (SCX_HAS_OP(dump_task)) { | 5002 | if (SCX_HAS_OP(dump_task)) { |
| 4967 | ops_dump_init(s, " "); | 5003 | ops_dump_init(s, " "); |
| 4968 | SCX_CALL_OP(SCX_KF_REST, dump_task, dctx, p); | 5004 | SCX_CALL_OP(SCX_KF_REST, dump_task, NULL, dctx, p); |
| 4969 | ops_dump_exit(); | 5005 | ops_dump_exit(); |
| 4970 | } | 5006 | } |
| 4971 | 5007 | ||
| @@ -5012,7 +5048,7 @@ static void scx_dump_state(struct scx_exit_info *ei, size_t dump_len) · 40 unmodified lines | |||
| 5012 | 5048 | ||
| 5013 | if (SCX_HAS_OP(dump)) { | 5049 | if (SCX_HAS_OP(dump)) { |
| 5014 | ops_dump_init(&s, ""); | 5050 | ops_dump_init(&s, ""); |
| 5015 | SCX_CALL_OP(SCX_KF_UNLOCKED, dump, &dctx); | 5051 | SCX_CALL_OP(SCX_KF_UNLOCKED, dump, NULL, &dctx); |
| 5016 | ops_dump_exit(); | 5052 | ops_dump_exit(); |
| 5017 | } | 5053 | } |
| 5018 | 5054 | ||
| @@ -5069,7 +5105,7 @@ static void scx_dump_state(struct scx_exit_info *ei, size_t dump_len) · 50 unmodified lines | |||
| 5069 | used = seq_buf_used(&ns); | 5105 | used = seq_buf_used(&ns); |
| 5070 | if (SCX_HAS_OP(dump_cpu)) { | 5106 | if (SCX_HAS_OP(dump_cpu)) { |
| 5071 | ops_dump_init(&ns, " "); | 5107 | ops_dump_init(&ns, " "); |
| 5072 | SCX_CALL_OP(SCX_KF_REST, dump_cpu, &dctx, cpu, idle); | 5108 | SCX_CALL_OP(SCX_KF_REST, dump_cpu, NULL, &dctx, cpu, idle); |
| 5073 | ops_dump_exit(); | 5109 | ops_dump_exit(); |
| 5074 | } | 5110 | } |
| 5075 | 5111 | ||
| @@ -5328,7 +5364,7 @@ static int scx_ops_enable(struct sched_ext_ops *ops, struct bpf_link *link) · 252 unmodified lines | |||
| 5328 | scx_idle_enable(ops); | 5364 | scx_idle_enable(ops); |
| 5329 | 5365 | ||
| 5330 | if (scx_ops.init) { | 5366 | if (scx_ops.init) { |
| 5331 | ret = SCX_CALL_OP_RET(SCX_KF_UNLOCKED, init); | 5367 | ret = SCX_CALL_OP_RET(SCX_KF_UNLOCKED, init, NULL); |
| 5332 | if (ret) { | 5368 | if (ret) { |
| 5333 | ret = ops_sanitize_err("init", ret); | 5369 | ret = ops_sanitize_err("init", ret); |
| 5334 | cpus_read_unlock(); | 5370 | cpus_read_unlock(); |
| @@ -6791,6 +6827,12 @@ __bpf_kfunc int bpf_iter_scx_dsq_new(struct bpf_iter_scx_dsq *it, u64 dsq_id, · 1456 unmodified lines | |||
| 6791 | BUILD_BUG_ON(__alignof__(struct bpf_iter_scx_dsq_kern) != | 6827 | BUILD_BUG_ON(__alignof__(struct bpf_iter_scx_dsq_kern) != |
| 6792 | __alignof__(struct bpf_iter_scx_dsq)); | 6828 | __alignof__(struct bpf_iter_scx_dsq)); |
| 6793 | 6829 | ||
| 6830 | /* | ||
| 6831 | * next() and destroy() will be called regardless of the return value. | ||
| 6832 | * Always clear $kit->dsq. | ||
| 6833 | */ | ||
| 6834 | kit->dsq = NULL; | ||
| 6835 | |||
| 6794 | if (flags & ~__SCX_DSQ_ITER_USER_FLAGS) | 6836 | if (flags & ~__SCX_DSQ_ITER_USER_FLAGS) |
| 6795 | return -EINVAL; | 6837 | return -EINVAL; |
| 6796 | 6838 | ||
| @@ -7077,13 +7119,32 @@ __bpf_kfunc void scx_bpf_cpuperf_set(s32 cpu, u32 perf) · 280 unmodified lines | |||
| 7077 | } | 7119 | } |
| 7078 | 7120 | ||
| 7079 | if (ops_cpu_valid(cpu, NULL)) { | 7121 | if (ops_cpu_valid(cpu, NULL)) { |
| 7080 | struct rq *rq = cpu_rq(cpu); | 7122 | struct rq *rq = cpu_rq(cpu), *locked_rq = scx_locked_rq(); |
| 7123 | struct rq_flags rf; | ||
| 7124 | |||
| 7125 | /* | ||
| 7126 | * When called with an rq lock held, restrict the operation | ||
| 7127 | * to the corresponding CPU to prevent ABBA deadlocks. | ||
| 7128 | */ | ||
| 7129 | if (locked_rq && rq != locked_rq) { | ||
| 7130 | scx_ops_error("Invalid target CPU %d", cpu); | ||
| 7131 | return; | ||
| 7132 | } | ||
| 7133 | |||
| 7134 | /* | ||
| 7135 | * If no rq lock is held, allow to operate on any CPU by | ||
| 7136 | * acquiring the corresponding rq lock. | ||
| 7137 | */ | ||
| 7138 | if (!locked_rq) { | ||
| 7139 | rq_lock_irqsave(rq, &rf); | ||
| 7140 | update_rq_clock(rq); | ||
| 7141 | } | ||
| 7081 | 7142 | ||
| 7082 | rq->scx.cpuperf_target = perf; | 7143 | rq->scx.cpuperf_target = perf; |
| 7144 | cpufreq_update_util(rq, 0); | ||
| 7083 | 7145 | ||
| 7084 | rcu_read_lock_sched_notrace(); | 7146 | if (!locked_rq) |
| 7085 | cpufreq_update_util(cpu_rq(cpu), 0); | 7147 | rq_unlock_irqrestore(rq, &rf); |
| 7086 | rcu_read_unlock_sched_notrace(); | ||
| 7087 | } | 7148 | } |
| 7088 | } | 7149 | } |
| 7089 | 7150 | ||
| @@ -7314,12 +7375,6 @@ BTF_ID_FLAGS(func, scx_bpf_nr_cpu_ids) · 224 unmodified lines | |||
| 7314 | BTF_ID_FLAGS(func, scx_bpf_get_possible_cpumask, KF_ACQUIRE) | 7375 | BTF_ID_FLAGS(func, scx_bpf_get_possible_cpumask, KF_ACQUIRE) |
| 7315 | BTF_ID_FLAGS(func, scx_bpf_get_online_cpumask, KF_ACQUIRE) | 7376 | BTF_ID_FLAGS(func, scx_bpf_get_online_cpumask, KF_ACQUIRE) |
| 7316 | BTF_ID_FLAGS(func, scx_bpf_put_cpumask, KF_RELEASE) | 7377 | BTF_ID_FLAGS(func, scx_bpf_put_cpumask, KF_RELEASE) |
| 7317 | BTF_ID_FLAGS(func, scx_bpf_get_idle_cpumask, KF_ACQUIRE) | ||
| 7318 | BTF_ID_FLAGS(func, scx_bpf_get_idle_smtmask, KF_ACQUIRE) | ||
| 7319 | BTF_ID_FLAGS(func, scx_bpf_put_idle_cpumask, KF_RELEASE) | ||
| 7320 | BTF_ID_FLAGS(func, scx_bpf_test_and_clear_cpu_idle) | ||
| 7321 | BTF_ID_FLAGS(func, scx_bpf_pick_idle_cpu, KF_RCU) | ||
| 7322 | BTF_ID_FLAGS(func, scx_bpf_pick_any_cpu, KF_RCU) | ||
| 7323 | BTF_ID_FLAGS(func, scx_bpf_task_running, KF_RCU) | 7378 | BTF_ID_FLAGS(func, scx_bpf_task_running, KF_RCU) |
| 7324 | BTF_ID_FLAGS(func, scx_bpf_task_cpu, KF_RCU) | 7379 | BTF_ID_FLAGS(func, scx_bpf_task_cpu, KF_RCU) |
| 7325 | BTF_ID_FLAGS(func, scx_bpf_cpu_rq) | 7380 | BTF_ID_FLAGS(func, scx_bpf_cpu_rq) |
| @@ -674,7 +674,7 @@ void __scx_update_idle(struct rq *rq, bool idle, bool do_notify) · 673 unmodified lines | |||
| 674 | * managed by put_prev_task_idle()/set_next_task_idle(). | 674 | * managed by put_prev_task_idle()/set_next_task_idle(). |
| 675 | */ | 675 | */ |
| 676 | if (SCX_HAS_OP(update_idle) && do_notify && !scx_rq_bypassing(rq)) | 676 | if (SCX_HAS_OP(update_idle) && do_notify && !scx_rq_bypassing(rq)) |
| 677 | SCX_CALL_OP(SCX_KF_REST, update_idle, cpu_of(rq), idle); | 677 | SCX_CALL_OP(SCX_KF_REST, update_idle, rq, cpu_of(rq), idle); |
| 678 | 678 | ||
| 679 | /* | 679 | /* |
| 680 | * Update the idle masks: | 680 | * Update the idle masks: |
| @@ -454,7 +454,8 @@ static void fprobe_remove_node_in_module(struct module *mod, struct hlist_head * · 453 unmodified lines | |||
| 454 | struct fprobe_hlist_node *node; | 454 | struct fprobe_hlist_node *node; |
| 455 | int ret = 0; | 455 | int ret = 0; |
| 456 | 456 | ||
| 457 | hlist_for_each_entry_rcu(node, head, hlist) { | 457 | hlist_for_each_entry_rcu(node, head, hlist, |
| 458 | lockdep_is_held(&fprobe_mutex)) { | ||
| 458 | if (!within_module(node->addr, mod)) | 459 | if (!within_module(node->addr, mod)) |
| 459 | continue; | 460 | continue; |
| 460 | if (delete_fprobe_node(node)) | 461 | if (delete_fprobe_node(node)) |
| @@ -1887,10 +1887,12 @@ static void rb_meta_validate_events(struct ring_buffer_per_cpu *cpu_buffer) · 1886 unmodified lines | |||
| 1887 | 1887 | ||
| 1888 | head_page = cpu_buffer->head_page; | 1888 | head_page = cpu_buffer->head_page; |
| 1889 | 1889 | ||
| 1890 | /* If both the head and commit are on the reader_page then we are done. */ | 1890 | /* If the commit_buffer is the reader page, update the commit page */ |
| 1891 | if (head_page == cpu_buffer->reader_page && | 1891 | if (meta->commit_buffer == (unsigned long)cpu_buffer->reader_page->page) { |
| 1892 | head_page == cpu_buffer->commit_page) | 1892 | cpu_buffer->commit_page = cpu_buffer->reader_page; |
| 1893 | /* Nothing more to do, the only page is the reader page */ | ||
| 1893 | goto done; | 1894 | goto done; |
| 1895 | } | ||
| 1894 | 1896 | ||
| 1895 | /* Iterate until finding the commit page */ | 1897 | /* Iterate until finding the commit page */ |
| 1896 | for (i = 0; i < meta->nr_subbufs + 1; i++, rb_inc_page(&head_page)) { | 1898 | for (i = 0; i < meta->nr_subbufs + 1; i++, rb_inc_page(&head_page)) { |
| @@ -16,7 +16,7 @@ · 15 unmodified lines | |||
| 16 | #include "trace_output.h" /* for trace_event_sem */ | 16 | #include "trace_output.h" /* for trace_event_sem */ |
| 17 | #include "trace_dynevent.h" | 17 | #include "trace_dynevent.h" |
| 18 | 18 | ||
| 19 | static DEFINE_MUTEX(dyn_event_ops_mutex); | 19 | DEFINE_MUTEX(dyn_event_ops_mutex); |
| 20 | static LIST_HEAD(dyn_event_ops_list); | 20 | static LIST_HEAD(dyn_event_ops_list); |
| 21 | 21 | ||
| 22 | bool trace_event_dyn_try_get_ref(struct trace_event_call *dyn_call) | 22 | bool trace_event_dyn_try_get_ref(struct trace_event_call *dyn_call) |
| @@ -116,6 +116,20 @@ int dyn_event_release(const char *raw_command, struct dyn_event_operations *type · 93 unmodified lines | |||
| 116 | return ret; | 116 | return ret; |
| 117 | } | 117 | } |
| 118 | 118 | ||
| 119 | /* | ||
| 120 | * Locked version of event creation. The event creation must be protected by | ||
| 121 | * dyn_event_ops_mutex because of protecting trace_probe_log. | ||
| 122 | */ | ||
| 123 | int dyn_event_create(const char *raw_command, struct dyn_event_operations *type) | ||
| 124 | { | ||
| 125 | int ret; | ||
| 126 | |||
| 127 | mutex_lock(&dyn_event_ops_mutex); | ||
| 128 | ret = type->create(raw_command); | ||
| 129 | mutex_unlock(&dyn_event_ops_mutex); | ||
| 130 | return ret; | ||
| 131 | } | ||
| 132 | |||
| 119 | static int create_dyn_event(const char *raw_command) | 133 | static int create_dyn_event(const char *raw_command) |
| 120 | { | 134 | { |
| 121 | struct dyn_event_operations *ops; | 135 | struct dyn_event_operations *ops; |
| @@ -100,6 +100,7 @@ void *dyn_event_seq_next(struct seq_file *m, void *v, loff_t *pos); · 99 unmodified lines | |||
| 100 | void dyn_event_seq_stop(struct seq_file *m, void *v); | 100 | void dyn_event_seq_stop(struct seq_file *m, void *v); |
| 101 | int dyn_events_release_all(struct dyn_event_operations *type); | 101 | int dyn_events_release_all(struct dyn_event_operations *type); |
| 102 | int dyn_event_release(const char *raw_command, struct dyn_event_operations *type); | 102 | int dyn_event_release(const char *raw_command, struct dyn_event_operations *type); |
| 103 | int dyn_event_create(const char *raw_command, struct dyn_event_operations *type); | ||
| 103 | 104 | ||
| 104 | /* | 105 | /* |
| 105 | * for_each_dyn_event - iterate over the dyn_event list | 106 | * for_each_dyn_event - iterate over the dyn_event list |
| @@ -969,10 +969,13 @@ static int __trace_eprobe_create(int argc, const char *argv[]) · 968 unmodified lines | |||
| 969 | goto error; | 969 | goto error; |
| 970 | } | 970 | } |
| 971 | } | 971 | } |
| 972 | trace_probe_log_clear(); | ||
| 972 | return ret; | 973 | return ret; |
| 974 | |||
| 973 | parse_error: | 975 | parse_error: |
| 974 | ret = -EINVAL; | 976 | ret = -EINVAL; |
| 975 | error: | 977 | error: |
| 978 | trace_probe_log_clear(); | ||
| 976 | trace_event_probe_cleanup(ep); | 979 | trace_event_probe_cleanup(ep); |
| 977 | return ret; | 980 | return ret; |
| 978 | } | 981 | } |
| @@ -1560,7 +1560,7 @@ stacktrace_trigger(struct event_trigger_data *data, · 1559 unmodified lines | |||
| 1560 | struct trace_event_file *file = data->private_data; | 1560 | struct trace_event_file *file = data->private_data; |
| 1561 | 1561 | ||
| 1562 | if (file) | 1562 | if (file) |
| 1563 | __trace_stack(file->tr, tracing_gen_ctx(), STACK_SKIP); | 1563 | __trace_stack(file->tr, tracing_gen_ctx_dec(), STACK_SKIP); |
| 1564 | else | 1564 | else |
| 1565 | trace_dump_stack(STACK_SKIP); | 1565 | trace_dump_stack(STACK_SKIP); |
| 1566 | } | 1566 | } |
| @@ -633,11 +633,7 @@ ftrace_traceoff(unsigned long ip, unsigned long parent_ip, · 632 unmodified lines | |||
| 633 | 633 | ||
| 634 | static __always_inline void trace_stack(struct trace_array *tr) | 634 | static __always_inline void trace_stack(struct trace_array *tr) |
| 635 | { | 635 | { |
| 636 | unsigned int trace_ctx; | 636 | __trace_stack(tr, tracing_gen_ctx_dec(), FTRACE_STACK_SKIP); |
| 637 | |||
| 638 | trace_ctx = tracing_gen_ctx(); | ||
| 639 | |||
| 640 | __trace_stack(tr, trace_ctx, FTRACE_STACK_SKIP); | ||
| 641 | } | 637 | } |
| 642 | 638 | ||
| 643 | static void | 639 | static void |
| @@ -1089,7 +1089,7 @@ static int create_or_delete_trace_kprobe(const char *raw_command) · 1088 unmodified lines | |||
| 1089 | if (raw_command[0] == '-') | 1089 | if (raw_command[0] == '-') |
| 1090 | return dyn_event_release(raw_command, &trace_kprobe_ops); | 1090 | return dyn_event_release(raw_command, &trace_kprobe_ops); |
| 1091 | 1091 | ||
| 1092 | ret = trace_kprobe_create(raw_command); | 1092 | ret = dyn_event_create(raw_command, &trace_kprobe_ops); |
| 1093 | return ret == -ECANCELED ? -EINVAL : ret; | 1093 | return ret == -ECANCELED ? -EINVAL : ret; |
| 1094 | } | 1094 | } |
| 1095 | 1095 | ||
| @@ -154,9 +154,12 @@ fail: · 153 unmodified lines | |||
| 154 | } | 154 | } |
| 155 | 155 | ||
| 156 | static struct trace_probe_log trace_probe_log; | 156 | static struct trace_probe_log trace_probe_log; |
| 157 | extern struct mutex dyn_event_ops_mutex; | ||
| 157 | 158 | ||
| 158 | void trace_probe_log_init(const char *subsystem, int argc, const char **argv) | 159 | void trace_probe_log_init(const char *subsystem, int argc, const char **argv) |
| 159 | { | 160 | { |
| 161 | lockdep_assert_held(&dyn_event_ops_mutex); | ||
| 162 | |||
| 160 | trace_probe_log.subsystem = subsystem; | 163 | trace_probe_log.subsystem = subsystem; |
| 161 | trace_probe_log.argc = argc; | 164 | trace_probe_log.argc = argc; |
| 162 | trace_probe_log.argv = argv; | 165 | trace_probe_log.argv = argv; |
| @@ -165,11 +168,15 @@ void trace_probe_log_init(const char *subsystem, int argc, const char **argv) · 2 unmodified lines | |||
| 165 | 168 | ||
| 166 | void trace_probe_log_clear(void) | 169 | void trace_probe_log_clear(void) |
| 167 | { | 170 | { |
| 171 | lockdep_assert_held(&dyn_event_ops_mutex); | ||
| 172 | |||
| 168 | memset(&trace_probe_log, 0, sizeof(trace_probe_log)); | 173 | memset(&trace_probe_log, 0, sizeof(trace_probe_log)); |
| 169 | } | 174 | } |
| 170 | 175 | ||
| 171 | void trace_probe_log_set_index(int index) | 176 | void trace_probe_log_set_index(int index) |
| 172 | { | 177 | { |
| 178 | lockdep_assert_held(&dyn_event_ops_mutex); | ||
| 179 | |||
| 173 | trace_probe_log.index = index; | 180 | trace_probe_log.index = index; |
| 174 | } | 181 | } |
| 175 | 182 | ||
| @@ -178,6 +185,8 @@ void __trace_probe_log_err(int offset, int err_type) · 2 unmodified lines | |||
| 178 | char *command, *p; | 185 | char *command, *p; |
| 179 | int i, len = 0, pos = 0; | 186 | int i, len = 0, pos = 0; |
| 180 | 187 | ||
| 188 | lockdep_assert_held(&dyn_event_ops_mutex); | ||
| 189 | |||
| 181 | if (!trace_probe_log.argv) | 190 | if (!trace_probe_log.argv) |
| 182 | return; | 191 | return; |
| 183 | 192 | ||
| @@ -741,7 +741,7 @@ static int create_or_delete_trace_uprobe(const char *raw_command) · 740 unmodified lines | |||
| 741 | if (raw_command[0] == '-') | 741 | if (raw_command[0] == '-') |
| 742 | return dyn_event_release(raw_command, &trace_uprobe_ops); | 742 | return dyn_event_release(raw_command, &trace_uprobe_ops); |
| 743 | 743 | ||
| 744 | ret = trace_uprobe_create(raw_command); | 744 | ret = dyn_event_create(raw_command, &trace_uprobe_ops); |
| 745 | return ret == -ECANCELED ? -EINVAL : ret; | 745 | return ret == -ECANCELED ? -EINVAL : ret; |
| 746 | } | 746 | } |
| 747 | 747 | ||
| @@ -3010,7 +3010,7 @@ struct folio *alloc_hugetlb_folio(struct vm_area_struct *vma, · 3009 unmodified lines | |||
| 3010 | struct hugepage_subpool *spool = subpool_vma(vma); | 3010 | struct hugepage_subpool *spool = subpool_vma(vma); |
| 3011 | struct hstate *h = hstate_vma(vma); | 3011 | struct hstate *h = hstate_vma(vma); |
| 3012 | struct folio *folio; | 3012 | struct folio *folio; |
| 3013 | long retval, gbl_chg; | 3013 | long retval, gbl_chg, gbl_reserve; |
| 3014 | map_chg_state map_chg; | 3014 | map_chg_state map_chg; |
| 3015 | int ret, idx; | 3015 | int ret, idx; |
| 3016 | struct hugetlb_cgroup *h_cg = NULL; | 3016 | struct hugetlb_cgroup *h_cg = NULL; |
| @@ -3163,8 +3163,16 @@ out_uncharge_cgroup_reservation: · 146 unmodified lines | |||
| 3163 | hugetlb_cgroup_uncharge_cgroup_rsvd(idx, pages_per_huge_page(h), | 3163 | hugetlb_cgroup_uncharge_cgroup_rsvd(idx, pages_per_huge_page(h), |
| 3164 | h_cg); | 3164 | h_cg); |
| 3165 | out_subpool_put: | 3165 | out_subpool_put: |
| 3166 | if (map_chg) | 3166 | /* |
| 3167 | hugepage_subpool_put_pages(spool, 1); | 3167 | * put page to subpool iff the quota of subpool's rsv_hpages is used |
| 3168 | * during hugepage_subpool_get_pages. | ||
| 3169 | */ | ||
| 3170 | if (map_chg && !gbl_chg) { | ||
| 3171 | gbl_reserve = hugepage_subpool_put_pages(spool, 1); | ||
| 3172 | hugetlb_acct_memory(h, -gbl_reserve); | ||
| 3173 | } | ||
| 3174 | |||
| 3175 | |||
| 3168 | out_end_reservation: | 3176 | out_end_reservation: |
| 3169 | if (map_chg != MAP_CHG_ENFORCED) | 3177 | if (map_chg != MAP_CHG_ENFORCED) |
| 3170 | vma_end_reservation(h, vma, addr); | 3178 | vma_end_reservation(h, vma, addr); |
| @@ -7239,7 +7247,7 @@ bool hugetlb_reserve_pages(struct inode *inode, · 4068 unmodified lines | |||
| 7239 | struct vm_area_struct *vma, | 7247 | struct vm_area_struct *vma, |
| 7240 | vm_flags_t vm_flags) | 7248 | vm_flags_t vm_flags) |
| 7241 | { | 7249 | { |
| 7242 | long chg = -1, add = -1; | 7250 | long chg = -1, add = -1, spool_resv, gbl_resv; |
| 7243 | struct hstate *h = hstate_inode(inode); | 7251 | struct hstate *h = hstate_inode(inode); |
| 7244 | struct hugepage_subpool *spool = subpool_inode(inode); | 7252 | struct hugepage_subpool *spool = subpool_inode(inode); |
| 7245 | struct resv_map *resv_map; | 7253 | struct resv_map *resv_map; |
| @@ -7374,8 +7382,16 @@ bool hugetlb_reserve_pages(struct inode *inode, · 128 unmodified lines | |||
| 7374 | return true; | 7382 | return true; |
| 7375 | 7383 | ||
| 7376 | out_put_pages: | 7384 | out_put_pages: |
| 7377 | /* put back original number of pages, chg */ | 7385 | spool_resv = chg - gbl_reserve; |
| 7378 | (void)hugepage_subpool_put_pages(spool, chg); | 7386 | if (spool_resv) { |
| 7387 | /* put sub pool's reservation back, chg - gbl_reserve */ | ||
| 7388 | gbl_resv = hugepage_subpool_put_pages(spool, spool_resv); | ||
| 7389 | /* | ||
| 7390 | * subpool's reserved pages can not be put back due to race, | ||
| 7391 | * return to hstate. | ||
| 7392 | */ | ||
| 7393 | hugetlb_acct_memory(h, -gbl_resv); | ||
| 7394 | } | ||
| 7379 | out_uncharge_cgroup: | 7395 | out_uncharge_cgroup: |
| 7380 | hugetlb_cgroup_uncharge_cgroup_rsvd(hstate_index(h), | 7396 | hugetlb_cgroup_uncharge_cgroup_rsvd(hstate_index(h), |
| 7381 | chg * pages_per_huge_page(h), h_cg); | 7397 | chg * pages_per_huge_page(h), h_cg); |
| @@ -1590,7 +1590,6 @@ unsigned long move_page_tables(struct pagetable_move_control *pmc); · 1589 unmodified lines | |||
| 1590 | 1590 | ||
| 1591 | #ifdef CONFIG_UNACCEPTED_MEMORY | 1591 | #ifdef CONFIG_UNACCEPTED_MEMORY |
| 1592 | void accept_page(struct page *page); | 1592 | void accept_page(struct page *page); |
| 1593 | void unaccepted_cleanup_work(struct work_struct *work); | ||
| 1594 | #else /* CONFIG_UNACCEPTED_MEMORY */ | 1593 | #else /* CONFIG_UNACCEPTED_MEMORY */ |
| 1595 | static inline void accept_page(struct page *page) | 1594 | static inline void accept_page(struct page *page) |
| 1596 | { | 1595 | { |
| @@ -3751,7 +3751,7 @@ static bool __wp_can_reuse_large_anon_folio(struct folio *folio, · 3750 unmodified lines | |||
| 3751 | 3751 | ||
| 3752 | /* Stabilize the mapcount vs. refcount and recheck. */ | 3752 | /* Stabilize the mapcount vs. refcount and recheck. */ |
| 3753 | folio_lock_large_mapcount(folio); | 3753 | folio_lock_large_mapcount(folio); |
| 3754 | VM_WARN_ON_ONCE(folio_large_mapcount(folio) < folio_ref_count(folio)); | 3754 | VM_WARN_ON_ONCE_FOLIO(folio_large_mapcount(folio) > folio_ref_count(folio), folio); |
| 3755 | 3755 | ||
| 3756 | if (folio_test_large_maybe_mapped_shared(folio)) | 3756 | if (folio_test_large_maybe_mapped_shared(folio)) |
| 3757 | goto unlock; | 3757 | goto unlock; |
| @@ -1441,7 +1441,6 @@ static void __meminit zone_init_free_lists(struct zone *zone) · 1440 unmodified lines | |||
| 1441 | 1441 | ||
| 1442 | #ifdef CONFIG_UNACCEPTED_MEMORY | 1442 | #ifdef CONFIG_UNACCEPTED_MEMORY |
| 1443 | INIT_LIST_HEAD(&zone->unaccepted_pages); | 1443 | INIT_LIST_HEAD(&zone->unaccepted_pages); |
| 1444 | INIT_WORK(&zone->unaccepted_cleanup, unaccepted_cleanup_work); | ||
| 1445 | #endif | 1444 | #endif |
| 1446 | } | 1445 | } |
| 1447 | 1446 | ||
| @@ -290,7 +290,8 @@ EXPORT_SYMBOL(nr_online_nodes); · 289 unmodified lines | |||
| 290 | #endif | 290 | #endif |
| 291 | 291 | ||
| 292 | static bool page_contains_unaccepted(struct page *page, unsigned int order); | 292 | static bool page_contains_unaccepted(struct page *page, unsigned int order); |
| 293 | static bool cond_accept_memory(struct zone *zone, unsigned int order); | 293 | static bool cond_accept_memory(struct zone *zone, unsigned int order, |
| 294 | int alloc_flags); | ||
| 294 | static bool __free_unaccepted(struct page *page); | 295 | static bool __free_unaccepted(struct page *page); |
| 295 | 296 | ||
| 296 | int page_group_by_mobility_disabled __read_mostly; | 297 | int page_group_by_mobility_disabled __read_mostly; |
| @@ -1151,14 +1152,9 @@ static inline void pgalloc_tag_sub(struct page *page, unsigned int nr) · 854 unmodified lines | |||
| 1151 | __pgalloc_tag_sub(page, nr); | 1152 | __pgalloc_tag_sub(page, nr); |
| 1152 | } | 1153 | } |
| 1153 | 1154 | ||
| 1154 | static inline void pgalloc_tag_sub_pages(struct page *page, unsigned int nr) | 1155 | /* When tag is not NULL, assuming mem_alloc_profiling_enabled */ |
| 1156 | static inline void pgalloc_tag_sub_pages(struct alloc_tag *tag, unsigned int nr) | ||
| 1155 | { | 1157 | { |
| 1156 | struct alloc_tag *tag; | ||
| 1157 | |||
| 1158 | if (!mem_alloc_profiling_enabled()) | ||
| 1159 | return; | ||
| 1160 | |||
| 1161 | tag = __pgalloc_tag_get(page); | ||
| 1162 | if (tag) | 1158 | if (tag) |
| 1163 | this_cpu_sub(tag->counters->bytes, PAGE_SIZE * nr); | 1159 | this_cpu_sub(tag->counters->bytes, PAGE_SIZE * nr); |
| 1164 | } | 1160 | } |
| @@ -1168,7 +1164,7 @@ static inline void pgalloc_tag_sub_pages(struct page *page, unsigned int nr) · 3 unmodified lines | |||
| 1168 | static inline void pgalloc_tag_add(struct page *page, struct task_struct *task, | 1164 | static inline void pgalloc_tag_add(struct page *page, struct task_struct *task, |
| 1169 | unsigned int nr) {} | 1165 | unsigned int nr) {} |
| 1170 | static inline void pgalloc_tag_sub(struct page *page, unsigned int nr) {} | 1166 | static inline void pgalloc_tag_sub(struct page *page, unsigned int nr) {} |
| 1171 | static inline void pgalloc_tag_sub_pages(struct page *page, unsigned int nr) {} | 1167 | static inline void pgalloc_tag_sub_pages(struct alloc_tag *tag, unsigned int nr) {} |
| 1172 | 1168 | ||
| 1173 | #endif /* CONFIG_MEM_ALLOC_PROFILING */ | 1169 | #endif /* CONFIG_MEM_ALLOC_PROFILING */ |
| 1174 | 1170 | ||
| @@ -3616,7 +3612,7 @@ retry: · 2441 unmodified lines | |||
| 3616 | } | 3612 | } |
| 3617 | } | 3613 | } |
| 3618 | 3614 | ||
| 3619 | cond_accept_memory(zone, order); | 3615 | cond_accept_memory(zone, order, alloc_flags); |
| 3620 | 3616 | ||
| 3621 | /* | 3617 | /* |
| 3622 | * Detect whether the number of free pages is below high | 3618 | * Detect whether the number of free pages is below high |
| @@ -3643,7 +3639,7 @@ check_alloc_wmark: · 20 unmodified lines | |||
| 3643 | gfp_mask)) { | 3639 | gfp_mask)) { |
| 3644 | int ret; | 3640 | int ret; |
| 3645 | 3641 | ||
| 3646 | if (cond_accept_memory(zone, order)) | 3642 | if (cond_accept_memory(zone, order, alloc_flags)) |
| 3647 | goto try_this_zone; | 3643 | goto try_this_zone; |
| 3648 | 3644 | ||
| 3649 | /* | 3645 | /* |
| @@ -3696,7 +3692,7 @@ try_this_zone: · 46 unmodified lines | |||
| 3696 | 3692 | ||
| 3697 | return page; | 3693 | return page; |
| 3698 | } else { | 3694 | } else { |
| 3699 | if (cond_accept_memory(zone, order)) | 3695 | if (cond_accept_memory(zone, order, alloc_flags)) |
| 3700 | goto try_this_zone; | 3696 | goto try_this_zone; |
| 3701 | 3697 | ||
| 3702 | /* Try again if zone has deferred pages */ | 3698 | /* Try again if zone has deferred pages */ |
| @@ -4849,7 +4845,7 @@ unsigned long alloc_pages_bulk_noprof(gfp_t gfp, int preferred_nid, · 1146 unmodified lines | |||
| 4849 | goto failed; | 4845 | goto failed; |
| 4850 | } | 4846 | } |
| 4851 | 4847 | ||
| 4852 | cond_accept_memory(zone, 0); | 4848 | cond_accept_memory(zone, 0, alloc_flags); |
| 4853 | retry_this_zone: | 4849 | retry_this_zone: |
| 4854 | mark = wmark_pages(zone, alloc_flags & ALLOC_WMARK_MASK) + nr_pages; | 4850 | mark = wmark_pages(zone, alloc_flags & ALLOC_WMARK_MASK) + nr_pages; |
| 4855 | if (zone_watermark_fast(zone, 0, mark, | 4851 | if (zone_watermark_fast(zone, 0, mark, |
| @@ -4858,7 +4854,7 @@ retry_this_zone: · 2 unmodified lines | |||
| 4858 | break; | 4854 | break; |
| 4859 | } | 4855 | } |
| 4860 | 4856 | ||
| 4861 | if (cond_accept_memory(zone, 0)) | 4857 | if (cond_accept_memory(zone, 0, alloc_flags)) |
| 4862 | goto retry_this_zone; | 4858 | goto retry_this_zone; |
| 4863 | 4859 | ||
| 4864 | /* Try again if zone has deferred pages */ | 4860 | /* Try again if zone has deferred pages */ |
| @@ -5065,11 +5061,13 @@ static void ___free_pages(struct page *page, unsigned int order, · 200 unmodified lines | |||
| 5065 | { | 5061 | { |
| 5066 | /* get PageHead before we drop reference */ | 5062 | /* get PageHead before we drop reference */ |
| 5067 | int head = PageHead(page); | 5063 | int head = PageHead(page); |
| 5064 | /* get alloc tag in case the page is released by others */ | ||
| 5065 | struct alloc_tag *tag = pgalloc_tag_get(page); | ||
| 5068 | 5066 | ||
| 5069 | if (put_page_testzero(page)) | 5067 | if (put_page_testzero(page)) |
| 5070 | __free_frozen_pages(page, order, fpi_flags); | 5068 | __free_frozen_pages(page, order, fpi_flags); |
| 5071 | else if (!head) { | 5069 | else if (!head) { |
| 5072 | pgalloc_tag_sub_pages(page, (1 << order) - 1); | 5070 | pgalloc_tag_sub_pages(tag, (1 << order) - 1); |
| 5073 | while (order-- > 0) | 5071 | while (order-- > 0) |
| 5074 | __free_frozen_pages(page + (1 << order), order, | 5072 | __free_frozen_pages(page + (1 << order), order, |
| 5075 | fpi_flags); | 5073 | fpi_flags); |
| @@ -7174,16 +7172,8 @@ bool has_managed_dma(void) · 2098 unmodified lines | |||
| 7174 | 7172 | ||
| 7175 | #ifdef CONFIG_UNACCEPTED_MEMORY | 7173 | #ifdef CONFIG_UNACCEPTED_MEMORY |
| 7176 | 7174 | ||
| 7177 | /* Counts number of zones with unaccepted pages. */ | ||
| 7178 | static DEFINE_STATIC_KEY_FALSE(zones_with_unaccepted_pages); | ||
| 7179 | |||
| 7180 | static bool lazy_accept = true; | 7175 | static bool lazy_accept = true; |
| 7181 | 7176 | ||
| 7182 | void unaccepted_cleanup_work(struct work_struct *work) | ||
| 7183 | { | ||
| 7184 | static_branch_dec(&zones_with_unaccepted_pages); | ||
| 7185 | } | ||
| 7186 | |||
| 7187 | static int __init accept_memory_parse(char *p) | 7177 | static int __init accept_memory_parse(char *p) |
| 7188 | { | 7178 | { |
| 7189 | if (!strcmp(p, "lazy")) { | 7179 | if (!strcmp(p, "lazy")) { |
| @@ -7208,11 +7198,7 @@ static bool page_contains_unaccepted(struct page *page, unsigned int order) · 18 unmodified lines | |||
| 7208 | static void __accept_page(struct zone *zone, unsigned long *flags, | 7198 | static void __accept_page(struct zone *zone, unsigned long *flags, |
| 7209 | struct page *page) | 7199 | struct page *page) |
| 7210 | { | 7200 | { |
| 7211 | bool last; | ||
| 7212 | |||
| 7213 | list_del(&page->lru); | 7201 | list_del(&page->lru); |
| 7214 | last = list_empty(&zone->unaccepted_pages); | ||
| 7215 | |||
| 7216 | account_freepages(zone, -MAX_ORDER_NR_PAGES, MIGRATE_MOVABLE); | 7202 | account_freepages(zone, -MAX_ORDER_NR_PAGES, MIGRATE_MOVABLE); |
| 7217 | __mod_zone_page_state(zone, NR_UNACCEPTED, -MAX_ORDER_NR_PAGES); | 7203 | __mod_zone_page_state(zone, NR_UNACCEPTED, -MAX_ORDER_NR_PAGES); |
| 7218 | __ClearPageUnaccepted(page); | 7204 | __ClearPageUnaccepted(page); |
| @@ -7221,28 +7207,6 @@ static void __accept_page(struct zone *zone, unsigned long *flags, · 2 unmodified lines | |||
| 7221 | accept_memory(page_to_phys(page), PAGE_SIZE << MAX_PAGE_ORDER); | 7207 | accept_memory(page_to_phys(page), PAGE_SIZE << MAX_PAGE_ORDER); |
| 7222 | 7208 | ||
| 7223 | __free_pages_ok(page, MAX_PAGE_ORDER, FPI_TO_TAIL); | 7209 | __free_pages_ok(page, MAX_PAGE_ORDER, FPI_TO_TAIL); |
| 7224 | |||
| 7225 | if (last) { | ||
| 7226 | /* | ||
| 7227 | * There are two corner cases: | ||
| 7228 | * | ||
| 7229 | * - If allocation occurs during the CPU bring up, | ||
| 7230 | * static_branch_dec() cannot be used directly as | ||
| 7231 | * it causes a deadlock on cpu_hotplug_lock. | ||
| 7232 | * | ||
| 7233 | * Instead, use schedule_work() to prevent deadlock. | ||
| 7234 | * | ||
| 7235 | * - If allocation occurs before workqueues are initialized, | ||
| 7236 | * static_branch_dec() should be called directly. | ||
| 7237 | * | ||
| 7238 | * Workqueues are initialized before CPU bring up, so this | ||
| 7239 | * will not conflict with the first scenario. | ||
| 7240 | */ | ||
| 7241 | if (system_wq) | ||
| 7242 | schedule_work(&zone->unaccepted_cleanup); | ||
| 7243 | else | ||
| 7244 | unaccepted_cleanup_work(&zone->unaccepted_cleanup); | ||
| 7245 | } | ||
| 7246 | } | 7210 | } |
| 7247 | 7211 | ||
| 7248 | void accept_page(struct page *page) | 7212 | void accept_page(struct page *page) |
| @@ -7279,20 +7243,17 @@ static bool try_to_accept_memory_one(struct zone *zone) · 30 unmodified lines | |||
| 7279 | return true; | 7243 | return true; |
| 7280 | } | 7244 | } |
| 7281 | 7245 | ||
| 7282 | static inline bool has_unaccepted_memory(void) | 7246 | static bool cond_accept_memory(struct zone *zone, unsigned int order, |
| 7283 | { | 7247 | int alloc_flags) |
| 7284 | return static_branch_unlikely(&zones_with_unaccepted_pages); | ||
| 7285 | } | ||
| 7286 | |||
| 7287 | static bool cond_accept_memory(struct zone *zone, unsigned int order) | ||
| 7288 | { | 7248 | { |
| 7289 | long to_accept, wmark; | 7249 | long to_accept, wmark; |
| 7290 | bool ret = false; | 7250 | bool ret = false; |
| 7291 | 7251 | ||
| 7292 | if (!has_unaccepted_memory()) | 7252 | if (list_empty(&zone->unaccepted_pages)) |
| 7293 | return false; | 7253 | return false; |
| 7294 | 7254 | ||
| 7295 | if (list_empty(&zone->unaccepted_pages)) | 7255 | /* Bailout, since try_to_accept_memory_one() needs to take a lock */ |
| 7256 | if (alloc_flags & ALLOC_TRYLOCK) | ||
| 7296 | return false; | 7257 | return false; |
| 7297 | 7258 | ||
| 7298 | wmark = promo_wmark_pages(zone); | 7259 | wmark = promo_wmark_pages(zone); |
| @@ -7325,22 +7286,17 @@ static bool __free_unaccepted(struct page *page) · 26 unmodified lines | |||
| 7325 | { | 7286 | { |
| 7326 | struct zone *zone = page_zone(page); | 7287 | struct zone *zone = page_zone(page); |
| 7327 | unsigned long flags; | 7288 | unsigned long flags; |
| 7328 | bool first = false; | ||
| 7329 | 7289 | ||
| 7330 | if (!lazy_accept) | 7290 | if (!lazy_accept) |
| 7331 | return false; | 7291 | return false; |
| 7332 | 7292 | ||
| 7333 | spin_lock_irqsave(&zone->lock, flags); | 7293 | spin_lock_irqsave(&zone->lock, flags); |
| 7334 | first = list_empty(&zone->unaccepted_pages); | ||
| 7335 | list_add_tail(&page->lru, &zone->unaccepted_pages); | 7294 | list_add_tail(&page->lru, &zone->unaccepted_pages); |
| 7336 | account_freepages(zone, MAX_ORDER_NR_PAGES, MIGRATE_MOVABLE); | 7295 | account_freepages(zone, MAX_ORDER_NR_PAGES, MIGRATE_MOVABLE); |
| 7337 | __mod_zone_page_state(zone, NR_UNACCEPTED, MAX_ORDER_NR_PAGES); | 7296 | __mod_zone_page_state(zone, NR_UNACCEPTED, MAX_ORDER_NR_PAGES); |
| 7338 | __SetPageUnaccepted(page); | 7297 | __SetPageUnaccepted(page); |
| 7339 | spin_unlock_irqrestore(&zone->lock, flags); | 7298 | spin_unlock_irqrestore(&zone->lock, flags); |
| 7340 | 7299 | ||
| 7341 | if (first) | ||
| 7342 | static_branch_inc(&zones_with_unaccepted_pages); | ||
| 7343 | |||
| 7344 | return true; | 7300 | return true; |
| 7345 | } | 7301 | } |
| 7346 | 7302 | ||
| @@ -7351,7 +7307,8 @@ static bool page_contains_unaccepted(struct page *page, unsigned int order) · 4 unmodified lines | |||
| 7351 | return false; | 7307 | return false; |
| 7352 | } | 7308 | } |
| 7353 | 7309 | ||
| 7354 | static bool cond_accept_memory(struct zone *zone, unsigned int order) | 7310 | static bool cond_accept_memory(struct zone *zone, unsigned int order, |
| 7311 | int alloc_flags) | ||
| 7355 | { | 7312 | { |
| 7356 | return false; | 7313 | return false; |
| 7357 | } | 7314 | } |
| @@ -7422,11 +7379,6 @@ struct page *try_alloc_pages_noprof(int nid, unsigned int order) · 64 unmodified lines | |||
| 7422 | if (!pcp_allowed_order(order)) | 7379 | if (!pcp_allowed_order(order)) |
| 7423 | return NULL; | 7380 | return NULL; |
| 7424 | 7381 | ||
| 7425 | #ifdef CONFIG_UNACCEPTED_MEMORY | ||
| 7426 | /* Bailout, since try_to_accept_memory_one() needs to take a lock */ | ||
| 7427 | if (has_unaccepted_memory()) | ||
| 7428 | return NULL; | ||
| 7429 | #endif | ||
| 7430 | /* Bailout, since _deferred_grow_zone() needs to take a lock */ | 7382 | /* Bailout, since _deferred_grow_zone() needs to take a lock */ |
| 7431 | if (deferred_pages_enabled()) | 7383 | if (deferred_pages_enabled()) |
| 7432 | return NULL; | 7384 | return NULL; |
| @@ -3331,6 +3331,15 @@ SYSCALL_DEFINE2(swapon, const char __user *, specialfile, int, swap_flags) · 3330 unmodified lines | |||
| 3331 | goto bad_swap_unlock_inode; | 3331 | goto bad_swap_unlock_inode; |
| 3332 | } | 3332 | } |
| 3333 | 3333 | ||
| 3334 | /* | ||
| 3335 | * The swap subsystem needs a major overhaul to support this. | ||
| 3336 | * It doesn't work yet so just disable it for now. | ||
| 3337 | */ | ||
| 3338 | if (mapping_min_folio_order(mapping) > 0) { | ||
| 3339 | error = -EINVAL; | ||
| 3340 | goto bad_swap_unlock_inode; | ||
| 3341 | } | ||
| 3342 | |||
| 3334 | /* | 3343 | /* |
| 3335 | * Read the swap header. | 3344 | * Read the swap header. |
| 3336 | */ | 3345 | */ |
| @@ -1064,8 +1064,13 @@ static int move_present_pte(struct mm_struct *mm, · 1063 unmodified lines | |||
| 1064 | src_folio->index = linear_page_index(dst_vma, dst_addr); | 1064 | src_folio->index = linear_page_index(dst_vma, dst_addr); |
| 1065 | 1065 | ||
| 1066 | orig_dst_pte = mk_pte(&src_folio->page, dst_vma->vm_page_prot); | 1066 | orig_dst_pte = mk_pte(&src_folio->page, dst_vma->vm_page_prot); |
| 1067 | /* Follow mremap() behavior and treat the entry dirty after the move */ | 1067 | /* Set soft dirty bit so userspace can notice the pte was moved */ |
| 1068 | orig_dst_pte = pte_mkwrite(pte_mkdirty(orig_dst_pte), dst_vma); | 1068 | #ifdef CONFIG_MEM_SOFT_DIRTY |
| 1069 | orig_dst_pte = pte_mksoft_dirty(orig_dst_pte); | ||
| 1070 | #endif | ||
| 1071 | if (pte_dirty(orig_src_pte)) | ||
| 1072 | orig_dst_pte = pte_mkdirty(orig_dst_pte); | ||
| 1073 | orig_dst_pte = pte_mkwrite(orig_dst_pte, dst_vma); | ||
| 1069 | 1074 | ||
| 1070 | set_pte_at(mm, dst_addr, dst_pte, orig_dst_pte); | 1075 | set_pte_at(mm, dst_addr, dst_pte, orig_dst_pte); |
| 1071 | out: | 1076 | out: |
| @@ -1100,6 +1105,9 @@ static int move_swap_pte(struct mm_struct *mm, struct vm_area_struct *dst_vma, · 28 unmodified lines | |||
| 1100 | } | 1105 | } |
| 1101 | 1106 | ||
| 1102 | orig_src_pte = ptep_get_and_clear(mm, src_addr, src_pte); | 1107 | orig_src_pte = ptep_get_and_clear(mm, src_addr, src_pte); |
| 1108 | #ifdef CONFIG_MEM_SOFT_DIRTY | ||
| 1109 | orig_src_pte = pte_swp_mksoft_dirty(orig_src_pte); | ||
| 1110 | #endif | ||
| 1103 | set_pte_at(mm, dst_addr, dst_pte, orig_src_pte); | 1111 | set_pte_at(mm, dst_addr, dst_pte, orig_src_pte); |
| 1104 | double_pt_unlock(dst_ptl, src_ptl); | 1112 | double_pt_unlock(dst_ptl, src_ptl); |
| 1105 | 1113 | ||
| @@ -1243,19 +1243,19 @@ void zs_obj_write(struct zs_pool *pool, unsigned long handle, · 1242 unmodified lines | |||
| 1243 | class = zspage_class(pool, zspage); | 1243 | class = zspage_class(pool, zspage); |
| 1244 | off = offset_in_page(class->size * obj_idx); | 1244 | off = offset_in_page(class->size * obj_idx); |
| 1245 | 1245 | ||
| 1246 | if (off + class->size <= PAGE_SIZE) { | 1246 | if (!ZsHugePage(zspage)) |
| 1247 | off += ZS_HANDLE_SIZE; | ||
| 1248 | |||
| 1249 | if (off + mem_len <= PAGE_SIZE) { | ||
| 1247 | /* this object is contained entirely within a page */ | 1250 | /* this object is contained entirely within a page */ |
| 1248 | void *dst = kmap_local_zpdesc(zpdesc); | 1251 | void *dst = kmap_local_zpdesc(zpdesc); |
| 1249 | 1252 | ||
| 1250 | if (!ZsHugePage(zspage)) | ||
| 1251 | off += ZS_HANDLE_SIZE; | ||
| 1252 | memcpy(dst + off, handle_mem, mem_len); | 1253 | memcpy(dst + off, handle_mem, mem_len); |
| 1253 | kunmap_local(dst); | 1254 | kunmap_local(dst); |
| 1254 | } else { | 1255 | } else { |
| 1255 | /* this object spans two pages */ | 1256 | /* this object spans two pages */ |
| 1256 | size_t sizes[2]; | 1257 | size_t sizes[2]; |
| 1257 | 1258 | ||
| 1258 | off += ZS_HANDLE_SIZE; | ||
| 1259 | sizes[0] = PAGE_SIZE - off; | 1259 | sizes[0] = PAGE_SIZE - off; |
| 1260 | sizes[1] = mem_len - sizes[0]; | 1260 | sizes[1] = mem_len - sizes[0]; |
| 1261 | 1261 | ||
| @@ -506,28 +506,32 @@ batadv_hardif_is_iface_up(const struct batadv_hard_iface *hard_iface) · 505 unmodified lines | |||
| 506 | return false; | 506 | return false; |
| 507 | } | 507 | } |
| 508 | 508 | ||
| 509 | static void batadv_check_known_mac_addr(const struct net_device *net_dev) | 509 | static void batadv_check_known_mac_addr(const struct batadv_hard_iface *hard_iface) |
| 510 | { | 510 | { |
| 511 | const struct batadv_hard_iface *hard_iface; | 511 | const struct net_device *mesh_iface = hard_iface->mesh_iface; |
| 512 | const struct batadv_hard_iface *tmp_hard_iface; | ||
| 512 | 513 | ||
| 513 | rcu_read_lock(); | 514 | if (!mesh_iface) |
| 514 | list_for_each_entry_rcu(hard_iface, &batadv_hardif_list, list) { | 515 | return; |
| 515 | if (hard_iface->if_status != BATADV_IF_ACTIVE && | 516 | |
| 516 | hard_iface->if_status != BATADV_IF_TO_BE_ACTIVATED) | 517 | list_for_each_entry(tmp_hard_iface, &batadv_hardif_list, list) { |
| 518 | if (tmp_hard_iface == hard_iface) | ||
| 519 | continue; | ||
| 520 | |||
| 521 | if (tmp_hard_iface->mesh_iface != mesh_iface) | ||
| 517 | continue; | 522 | continue; |
| 518 | 523 | ||
| 519 | if (hard_iface->net_dev == net_dev) | 524 | if (tmp_hard_iface->if_status == BATADV_IF_NOT_IN_USE) |
| 520 | continue; | 525 | continue; |
| 521 | 526 | ||
| 522 | if (!batadv_compare_eth(hard_iface->net_dev->dev_addr, | 527 | if (!batadv_compare_eth(tmp_hard_iface->net_dev->dev_addr, |
| 523 | net_dev->dev_addr)) | 528 | hard_iface->net_dev->dev_addr)) |
| 524 | continue; | 529 | continue; |
| 525 | 530 | ||
| 526 | pr_warn("The newly added mac address (%pM) already exists on: %s\n", | 531 | pr_warn("The newly added mac address (%pM) already exists on: %s\n", |
| 527 | net_dev->dev_addr, hard_iface->net_dev->name); | 532 | hard_iface->net_dev->dev_addr, tmp_hard_iface->net_dev->name); |
| 528 | pr_warn("It is strongly recommended to keep mac addresses unique to avoid problems!\n"); | 533 | pr_warn("It is strongly recommended to keep mac addresses unique to avoid problems!\n"); |
| 529 | } | 534 | } |
| 530 | rcu_read_unlock(); | ||
| 531 | } | 535 | } |
| 532 | 536 | ||
| 533 | /** | 537 | /** |
| @@ -763,6 +767,8 @@ int batadv_hardif_enable_interface(struct batadv_hard_iface *hard_iface, · 229 unmodified lines | |||
| 763 | hard_iface->net_dev->name, hardif_mtu, | 767 | hard_iface->net_dev->name, hardif_mtu, |
| 764 | required_mtu); | 768 | required_mtu); |
| 765 | 769 | ||
| 770 | batadv_check_known_mac_addr(hard_iface); | ||
| 771 | |||
| 766 | if (batadv_hardif_is_iface_up(hard_iface)) | 772 | if (batadv_hardif_is_iface_up(hard_iface)) |
| 767 | batadv_hardif_activate_interface(hard_iface); | 773 | batadv_hardif_activate_interface(hard_iface); |
| 768 | else | 774 | else |
| @@ -901,7 +907,6 @@ batadv_hardif_add_interface(struct net_device *net_dev) · 132 unmodified lines | |||
| 901 | 907 | ||
| 902 | batadv_v_hardif_init(hard_iface); | 908 | batadv_v_hardif_init(hard_iface); |
| 903 | 909 | ||
| 904 | batadv_check_known_mac_addr(hard_iface->net_dev); | ||
| 905 | kref_get(&hard_iface->refcount); | 910 | kref_get(&hard_iface->refcount); |
| 906 | list_add_tail_rcu(&hard_iface->list, &batadv_hardif_list); | 911 | list_add_tail_rcu(&hard_iface->list, &batadv_hardif_list); |
| 907 | batadv_hardif_generation++; | 912 | batadv_hardif_generation++; |
| @@ -988,7 +993,7 @@ static int batadv_hard_if_event(struct notifier_block *this, · 80 unmodified lines | |||
| 988 | if (hard_iface->if_status == BATADV_IF_NOT_IN_USE) | 993 | if (hard_iface->if_status == BATADV_IF_NOT_IN_USE) |
| 989 | goto hardif_put; | 994 | goto hardif_put; |
| 990 | 995 | ||
| 991 | batadv_check_known_mac_addr(hard_iface->net_dev); | 996 | batadv_check_known_mac_addr(hard_iface); |
| 992 | 997 | ||
| 993 | bat_priv = netdev_priv(hard_iface->mesh_iface); | 998 | bat_priv = netdev_priv(hard_iface->mesh_iface); |
| 994 | bat_priv->algo_ops->iface.update_mac(hard_iface); | 999 | bat_priv->algo_ops->iface.update_mac(hard_iface); |
| @@ -3023,3 +3023,27 @@ void hci_conn_tx_dequeue(struct hci_conn *conn) · 3022 unmodified lines | |||
| 3023 | 3023 | ||
| 3024 | kfree_skb(skb); | 3024 | kfree_skb(skb); |
| 3025 | } | 3025 | } |
| 3026 | |||
| 3027 | u8 *hci_conn_key_enc_size(struct hci_conn *conn) | ||
| 3028 | { | ||
| 3029 | if (conn->type == ACL_LINK) { | ||
| 3030 | struct link_key *key; | ||
| 3031 | |||
| 3032 | key = hci_find_link_key(conn->hdev, &conn->dst); | ||
| 3033 | if (!key) | ||
| 3034 | return NULL; | ||
| 3035 | |||
| 3036 | return &key->pin_len; | ||
| 3037 | } else if (conn->type == LE_LINK) { | ||
| 3038 | struct smp_ltk *ltk; | ||
| 3039 | |||
| 3040 | ltk = hci_find_ltk(conn->hdev, &conn->dst, conn->dst_type, | ||
| 3041 | conn->role); | ||
| 3042 | if (!ltk) | ||
| 3043 | return NULL; | ||
| 3044 | |||
| 3045 | return <k->enc_size; | ||
| 3046 | } | ||
| 3047 | |||
| 3048 | return NULL; | ||
| 3049 | } | ||
| @@ -739,10 +739,17 @@ static u8 hci_cc_read_enc_key_size(struct hci_dev *hdev, void *data, · 738 unmodified lines | |||
| 739 | handle); | 739 | handle); |
| 740 | conn->enc_key_size = 0; | 740 | conn->enc_key_size = 0; |
| 741 | } else { | 741 | } else { |
| 742 | u8 *key_enc_size = hci_conn_key_enc_size(conn); | ||
| 743 | |||
| 742 | conn->enc_key_size = rp->key_size; | 744 | conn->enc_key_size = rp->key_size; |
| 743 | status = 0; | 745 | status = 0; |
| 744 | 746 | ||
| 745 | if (conn->enc_key_size < hdev->min_enc_key_size) { | 747 | /* Attempt to check if the key size is too small or if it has |
| 748 | * been downgraded from the last time it was stored as part of | ||
| 749 | * the link_key. | ||
| 750 | */ | ||
| 751 | if (conn->enc_key_size < hdev->min_enc_key_size || | ||
| 752 | (key_enc_size && conn->enc_key_size < *key_enc_size)) { | ||
| 746 | /* As slave role, the conn->state has been set to | 753 | /* As slave role, the conn->state has been set to |
| 747 | * BT_CONNECTED and l2cap conn req might not be received | 754 | * BT_CONNECTED and l2cap conn req might not be received |
| 748 | * yet, at this moment the l2cap layer almost does | 755 | * yet, at this moment the l2cap layer almost does |
| @@ -755,6 +762,10 @@ static u8 hci_cc_read_enc_key_size(struct hci_dev *hdev, void *data, · 6 unmodified lines | |||
| 755 | clear_bit(HCI_CONN_ENCRYPT, &conn->flags); | 762 | clear_bit(HCI_CONN_ENCRYPT, &conn->flags); |
| 756 | clear_bit(HCI_CONN_AES_CCM, &conn->flags); | 763 | clear_bit(HCI_CONN_AES_CCM, &conn->flags); |
| 757 | } | 764 | } |
| 765 | |||
| 766 | /* Update the key encryption size with the connection one */ | ||
| 767 | if (key_enc_size && *key_enc_size != conn->enc_key_size) | ||
| 768 | *key_enc_size = conn->enc_key_size; | ||
| 758 | } | 769 | } |
| 759 | 770 | ||
| 760 | hci_encrypt_cfm(conn, status); | 771 | hci_encrypt_cfm(conn, status); |
| @@ -3065,6 +3076,34 @@ static void hci_inquiry_result_evt(struct hci_dev *hdev, void *edata, · 2304 unmodified lines | |||
| 3065 | hci_dev_unlock(hdev); | 3076 | hci_dev_unlock(hdev); |
| 3066 | } | 3077 | } |
| 3067 | 3078 | ||
| 3079 | static int hci_read_enc_key_size(struct hci_dev *hdev, struct hci_conn *conn) | ||
| 3080 | { | ||
| 3081 | struct hci_cp_read_enc_key_size cp; | ||
| 3082 | u8 *key_enc_size = hci_conn_key_enc_size(conn); | ||
| 3083 | |||
| 3084 | if (!read_key_size_capable(hdev)) { | ||
| 3085 | conn->enc_key_size = HCI_LINK_KEY_SIZE; | ||
| 3086 | return -EOPNOTSUPP; | ||
| 3087 | } | ||
| 3088 | |||
| 3089 | bt_dev_dbg(hdev, "hcon %p", conn); | ||
| 3090 | |||
| 3091 | memset(&cp, 0, sizeof(cp)); | ||
| 3092 | cp.handle = cpu_to_le16(conn->handle); | ||
| 3093 | |||
| 3094 | /* If the key enc_size is already known, use it as conn->enc_key_size, | ||
| 3095 | * otherwise use hdev->min_enc_key_size so the likes of | ||
| 3096 | * l2cap_check_enc_key_size don't fail while waiting for | ||
| 3097 | * HCI_OP_READ_ENC_KEY_SIZE response. | ||
| 3098 | */ | ||
| 3099 | if (key_enc_size && *key_enc_size) | ||
| 3100 | conn->enc_key_size = *key_enc_size; | ||
| 3101 | else | ||
| 3102 | conn->enc_key_size = hdev->min_enc_key_size; | ||
| 3103 | |||
| 3104 | return hci_send_cmd(hdev, HCI_OP_READ_ENC_KEY_SIZE, sizeof(cp), &cp); | ||
| 3105 | } | ||
| 3106 | |||
| 3068 | static void hci_conn_complete_evt(struct hci_dev *hdev, void *data, | 3107 | static void hci_conn_complete_evt(struct hci_dev *hdev, void *data, |
| 3069 | struct sk_buff *skb) | 3108 | struct sk_buff *skb) |
| 3070 | { | 3109 | { |
| @@ -3157,23 +3196,11 @@ static void hci_conn_complete_evt(struct hci_dev *hdev, void *data, · 86 unmodified lines | |||
| 3157 | if (ev->encr_mode == 1 && !test_bit(HCI_CONN_ENCRYPT, &conn->flags) && | 3196 | if (ev->encr_mode == 1 && !test_bit(HCI_CONN_ENCRYPT, &conn->flags) && |
| 3158 | ev->link_type == ACL_LINK) { | 3197 | ev->link_type == ACL_LINK) { |
| 3159 | struct link_key *key; | 3198 | struct link_key *key; |
| 3160 | struct hci_cp_read_enc_key_size cp; | ||
| 3161 | 3199 | ||
| 3162 | key = hci_find_link_key(hdev, &ev->bdaddr); | 3200 | key = hci_find_link_key(hdev, &ev->bdaddr); |
| 3163 | if (key) { | 3201 | if (key) { |
| 3164 | set_bit(HCI_CONN_ENCRYPT, &conn->flags); | 3202 | set_bit(HCI_CONN_ENCRYPT, &conn->flags); |
| 3165 | 3203 | hci_read_enc_key_size(hdev, conn); | |
| 3166 | if (!read_key_size_capable(hdev)) { | ||
| 3167 | conn->enc_key_size = HCI_LINK_KEY_SIZE; | ||
| 3168 | } else { | ||
| 3169 | cp.handle = cpu_to_le16(conn->handle); | ||
| 3170 | if (hci_send_cmd(hdev, HCI_OP_READ_ENC_KEY_SIZE, | ||
| 3171 | sizeof(cp), &cp)) { | ||
| 3172 | bt_dev_err(hdev, "sending read key size failed"); | ||
| 3173 | conn->enc_key_size = HCI_LINK_KEY_SIZE; | ||
| 3174 | } | ||
| 3175 | } | ||
| 3176 | |||
| 3177 | hci_encrypt_cfm(conn, ev->status); | 3204 | hci_encrypt_cfm(conn, ev->status); |
| 3178 | } | 3205 | } |
| 3179 | } | 3206 | } |
| @@ -3612,24 +3639,8 @@ static void hci_encrypt_change_evt(struct hci_dev *hdev, void *data, · 432 unmodified lines | |||
| 3612 | 3639 | ||
| 3613 | /* Try reading the encryption key size for encrypted ACL links */ | 3640 | /* Try reading the encryption key size for encrypted ACL links */ |
| 3614 | if (!ev->status && ev->encrypt && conn->type == ACL_LINK) { | 3641 | if (!ev->status && ev->encrypt && conn->type == ACL_LINK) { |
| 3615 | struct hci_cp_read_enc_key_size cp; | 3642 | if (hci_read_enc_key_size(hdev, conn)) |
| 3616 | |||
| 3617 | /* Only send HCI_Read_Encryption_Key_Size if the | ||
| 3618 | * controller really supports it. If it doesn't, assume | ||
| 3619 | * the default size (16). | ||
| 3620 | */ | ||
| 3621 | if (!read_key_size_capable(hdev)) { | ||
| 3622 | conn->enc_key_size = HCI_LINK_KEY_SIZE; | ||
| 3623 | goto notify; | ||
| 3624 | } | ||
| 3625 | |||
| 3626 | cp.handle = cpu_to_le16(conn->handle); | ||
| 3627 | if (hci_send_cmd(hdev, HCI_OP_READ_ENC_KEY_SIZE, | ||
| 3628 | sizeof(cp), &cp)) { | ||
| 3629 | bt_dev_err(hdev, "sending read key size failed"); | ||
| 3630 | conn->enc_key_size = HCI_LINK_KEY_SIZE; | ||
| 3631 | goto notify; | 3643 | goto notify; |
| 3632 | } | ||
| 3633 | 3644 | ||
| 3634 | goto unlock; | 3645 | goto unlock; |
| 3635 | } | 3646 | } |
| @@ -7506,11 +7506,16 @@ static void add_device_complete(struct hci_dev *hdev, void *data, int err) · 7505 unmodified lines | |||
| 7506 | struct mgmt_cp_add_device *cp = cmd->param; | 7506 | struct mgmt_cp_add_device *cp = cmd->param; |
| 7507 | 7507 | ||
| 7508 | if (!err) { | 7508 | if (!err) { |
| 7509 | struct hci_conn_params *params; | ||
| 7510 | |||
| 7511 | params = hci_conn_params_lookup(hdev, &cp->addr.bdaddr, | ||
| 7512 | le_addr_type(cp->addr.type)); | ||
| 7513 | |||
| 7509 | device_added(cmd->sk, hdev, &cp->addr.bdaddr, cp->addr.type, | 7514 | device_added(cmd->sk, hdev, &cp->addr.bdaddr, cp->addr.type, |
| 7510 | cp->action); | 7515 | cp->action); |
| 7511 | device_flags_changed(NULL, hdev, &cp->addr.bdaddr, | 7516 | device_flags_changed(NULL, hdev, &cp->addr.bdaddr, |
| 7512 | cp->addr.type, hdev->conn_flags, | 7517 | cp->addr.type, hdev->conn_flags, |
| 7513 | PTR_UINT(cmd->user_data)); | 7518 | params ? params->flags : 0); |
| 7514 | } | 7519 | } |
| 7515 | 7520 | ||
| 7516 | mgmt_cmd_complete(cmd->sk, hdev->id, MGMT_OP_ADD_DEVICE, | 7521 | mgmt_cmd_complete(cmd->sk, hdev->id, MGMT_OP_ADD_DEVICE, |
| @@ -7613,8 +7618,6 @@ static int add_device(struct sock *sk, struct hci_dev *hdev, · 96 unmodified lines | |||
| 7613 | goto unlock; | 7618 | goto unlock; |
| 7614 | } | 7619 | } |
| 7615 | 7620 | ||
| 7616 | cmd->user_data = UINT_PTR(current_flags); | ||
| 7617 | |||
| 7618 | err = hci_cmd_sync_queue(hdev, add_device_sync, cmd, | 7621 | err = hci_cmd_sync_queue(hdev, add_device_sync, cmd, |
| 7619 | add_device_complete); | 7622 | add_device_complete); |
| 7620 | if (err < 0) { | 7623 | if (err < 0) { |
| @@ -10441,6 +10441,7 @@ static void netdev_sync_lower_features(struct net_device *upper, · 10440 unmodified lines | |||
| 10441 | if (!(features & feature) && (lower->features & feature)) { | 10441 | if (!(features & feature) && (lower->features & feature)) { |
| 10442 | netdev_dbg(upper, "Disabling feature %pNF on lower dev %s.\n", | 10442 | netdev_dbg(upper, "Disabling feature %pNF on lower dev %s.\n", |
| 10443 | &feature, lower->name); | 10443 | &feature, lower->name); |
| 10444 | netdev_lock_ops(lower); | ||
| 10444 | lower->wanted_features &= ~feature; | 10445 | lower->wanted_features &= ~feature; |
| 10445 | __netdev_update_features(lower); | 10446 | __netdev_update_features(lower); |
| 10446 | 10447 | ||
| @@ -10449,6 +10450,7 @@ static void netdev_sync_lower_features(struct net_device *upper, · 2 unmodified lines | |||
| 10449 | &feature, lower->name); | 10450 | &feature, lower->name); |
| 10450 | else | 10451 | else |
| 10451 | netdev_features_change(lower); | 10452 | netdev_features_change(lower); |
| 10453 | netdev_unlock_ops(lower); | ||
| 10452 | } | 10454 | } |
| 10453 | } | 10455 | } |
| 10454 | } | 10456 | } |
| @@ -200,6 +200,8 @@ net_devmem_bind_dmabuf(struct net_device *dev, unsigned int dmabuf_fd, · 199 unmodified lines | |||
| 200 | 200 | ||
| 201 | refcount_set(&binding->ref, 1); | 201 | refcount_set(&binding->ref, 1); |
| 202 | 202 | ||
| 203 | mutex_init(&binding->lock); | ||
| 204 | |||
| 203 | binding->dmabuf = dmabuf; | 205 | binding->dmabuf = dmabuf; |
| 204 | 206 | ||
| 205 | binding->attachment = dma_buf_attach(binding->dmabuf, dev->dev.parent); | 207 | binding->attachment = dma_buf_attach(binding->dmabuf, dev->dev.parent); |
| @@ -379,6 +381,11 @@ static void mp_dmabuf_devmem_uninstall(void *mp_priv, · 173 unmodified lines | |||
| 379 | xa_for_each(&binding->bound_rxqs, xa_idx, bound_rxq) { | 381 | xa_for_each(&binding->bound_rxqs, xa_idx, bound_rxq) { |
| 380 | if (bound_rxq == rxq) { | 382 | if (bound_rxq == rxq) { |
| 381 | xa_erase(&binding->bound_rxqs, xa_idx); | 383 | xa_erase(&binding->bound_rxqs, xa_idx); |
| 384 | if (xa_empty(&binding->bound_rxqs)) { | ||
| 385 | mutex_lock(&binding->lock); | ||
| 386 | binding->dev = NULL; | ||
| 387 | mutex_unlock(&binding->lock); | ||
| 388 | } | ||
| 382 | break; | 389 | break; |
| 383 | } | 390 | } |
| 384 | } | 391 | } |
| @@ -20,6 +20,8 @@ struct net_devmem_dmabuf_binding { · 19 unmodified lines | |||
| 20 | struct sg_table *sgt; | 20 | struct sg_table *sgt; |
| 21 | struct net_device *dev; | 21 | struct net_device *dev; |
| 22 | struct gen_pool *chunk_pool; | 22 | struct gen_pool *chunk_pool; |
| 23 | /* Protect dev */ | ||
| 24 | struct mutex lock; | ||
| 23 | 25 | ||
| 24 | /* The user holds a ref (via the netlink API) for as long as they want | 26 | /* The user holds a ref (via the netlink API) for as long as they want |
| 25 | * the binding to remain alive. Each page pool using this binding holds | 27 | * the binding to remain alive. Each page pool using this binding holds |
| @@ -979,14 +979,25 @@ void netdev_nl_sock_priv_destroy(struct netdev_nl_sock *priv) · 978 unmodified lines | |||
| 979 | { | 979 | { |
| 980 | struct net_devmem_dmabuf_binding *binding; | 980 | struct net_devmem_dmabuf_binding *binding; |
| 981 | struct net_devmem_dmabuf_binding *temp; | 981 | struct net_devmem_dmabuf_binding *temp; |
| 982 | netdevice_tracker dev_tracker; | ||
| 982 | struct net_device *dev; | 983 | struct net_device *dev; |
| 983 | 984 | ||
| 984 | mutex_lock(&priv->lock); | 985 | mutex_lock(&priv->lock); |
| 985 | list_for_each_entry_safe(binding, temp, &priv->bindings, list) { | 986 | list_for_each_entry_safe(binding, temp, &priv->bindings, list) { |
| 987 | mutex_lock(&binding->lock); | ||
| 986 | dev = binding->dev; | 988 | dev = binding->dev; |
| 989 | if (!dev) { | ||
| 990 | mutex_unlock(&binding->lock); | ||
| 991 | net_devmem_unbind_dmabuf(binding); | ||
| 992 | continue; | ||
| 993 | } | ||
| 994 | netdev_hold(dev, &dev_tracker, GFP_KERNEL); | ||
| 995 | mutex_unlock(&binding->lock); | ||
| 996 | |||
| 987 | netdev_lock(dev); | 997 | netdev_lock(dev); |
| 988 | net_devmem_unbind_dmabuf(binding); | 998 | net_devmem_unbind_dmabuf(binding); |
| 989 | netdev_unlock(dev); | 999 | netdev_unlock(dev); |
| 1000 | netdev_put(dev, &dev_tracker); | ||
| 990 | } | 1001 | } |
| 991 | mutex_unlock(&priv->lock); | 1002 | mutex_unlock(&priv->lock); |
| 992 | } | 1003 | } |
| @@ -1354,10 +1354,12 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) · 1353 unmodified lines | |||
| 1354 | hw->wiphy->software_iftypes |= BIT(NL80211_IFTYPE_MONITOR); | 1354 | hw->wiphy->software_iftypes |= BIT(NL80211_IFTYPE_MONITOR); |
| 1355 | 1355 | ||
| 1356 | 1356 | ||
| 1357 | local->int_scan_req = kzalloc(sizeof(*local->int_scan_req) + | 1357 | local->int_scan_req = kzalloc(struct_size(local->int_scan_req, |
| 1358 | sizeof(void *) * channels, GFP_KERNEL); | 1358 | channels, channels), |
| 1359 | GFP_KERNEL); | ||
| 1359 | if (!local->int_scan_req) | 1360 | if (!local->int_scan_req) |
| 1360 | return -ENOMEM; | 1361 | return -ENOMEM; |
| 1362 | local->int_scan_req->n_channels = channels; | ||
| 1361 | 1363 | ||
| 1362 | eth_broadcast_addr(local->int_scan_req->bssid); | 1364 | eth_broadcast_addr(local->int_scan_req->bssid); |
| 1363 | 1365 | ||
| @@ -117,11 +117,18 @@ static int mctp_dump_addrinfo(struct sk_buff *skb, struct netlink_callback *cb) · 116 unmodified lines | |||
| 117 | struct net_device *dev; | 117 | struct net_device *dev; |
| 118 | struct ifaddrmsg *hdr; | 118 | struct ifaddrmsg *hdr; |
| 119 | struct mctp_dev *mdev; | 119 | struct mctp_dev *mdev; |
| 120 | int ifindex, rc; | 120 | int ifindex = 0, rc; |
| 121 | 121 | ||
| 122 | hdr = nlmsg_data(cb->nlh); | 122 | /* Filter by ifindex if a header is provided */ |
| 123 | // filter by ifindex if requested | 123 | if (cb->nlh->nlmsg_len >= nlmsg_msg_size(sizeof(*hdr))) { |
| 124 | ifindex = hdr->ifa_index; | 124 | hdr = nlmsg_data(cb->nlh); |
| 125 | ifindex = hdr->ifa_index; | ||
| 126 | } else { | ||
| 127 | if (cb->strict_check) { | ||
| 128 | NL_SET_ERR_MSG(cb->extack, "mctp: Invalid header for addr dump request"); | ||
| 129 | return -EINVAL; | ||
| 130 | } | ||
| 131 | } | ||
| 125 | 132 | ||
| 126 | rcu_read_lock(); | 133 | rcu_read_lock(); |
| 127 | for_each_netdev_dump(net, dev, mcb->ifindex) { | 134 | for_each_netdev_dump(net, dev, mcb->ifindex) { |
| @@ -313,8 +313,10 @@ static void mctp_flow_prepare_output(struct sk_buff *skb, struct mctp_dev *dev) · 312 unmodified lines | |||
| 313 | 313 | ||
| 314 | key = flow->key; | 314 | key = flow->key; |
| 315 | 315 | ||
| 316 | if (WARN_ON(key->dev && key->dev != dev)) | 316 | if (key->dev) { |
| 317 | WARN_ON(key->dev != dev); | ||
| 317 | return; | 318 | return; |
| 319 | } | ||
| 318 | 320 | ||
| 319 | mctp_dev_set_key(dev, key); | 321 | mctp_dev_set_key(dev, key); |
| 320 | } | 322 | } |
| @@ -144,7 +144,7 @@ static int codel_change(struct Qdisc *sch, struct nlattr *opt, · 143 unmodified lines | |||
| 144 | 144 | ||
| 145 | qlen = sch->q.qlen; | 145 | qlen = sch->q.qlen; |
| 146 | while (sch->q.qlen > sch->limit) { | 146 | while (sch->q.qlen > sch->limit) { |
| 147 | struct sk_buff *skb = __qdisc_dequeue_head(&sch->q); | 147 | struct sk_buff *skb = qdisc_dequeue_internal(sch, true); |
| 148 | 148 | ||
| 149 | dropped += qdisc_pkt_len(skb); | 149 | dropped += qdisc_pkt_len(skb); |
| 150 | qdisc_qstats_backlog_dec(sch, skb); | 150 | qdisc_qstats_backlog_dec(sch, skb); |
| @@ -1136,7 +1136,7 @@ static int fq_change(struct Qdisc *sch, struct nlattr *opt, · 1135 unmodified lines | |||
| 1136 | sch_tree_lock(sch); | 1136 | sch_tree_lock(sch); |
| 1137 | } | 1137 | } |
| 1138 | while (sch->q.qlen > sch->limit) { | 1138 | while (sch->q.qlen > sch->limit) { |
| 1139 | struct sk_buff *skb = fq_dequeue(sch); | 1139 | struct sk_buff *skb = qdisc_dequeue_internal(sch, false); |
| 1140 | 1140 | ||
| 1141 | if (!skb) | 1141 | if (!skb) |
| 1142 | break; | 1142 | break; |
| @@ -441,7 +441,7 @@ static int fq_codel_change(struct Qdisc *sch, struct nlattr *opt, · 440 unmodified lines | |||
| 441 | 441 | ||
| 442 | while (sch->q.qlen > sch->limit || | 442 | while (sch->q.qlen > sch->limit || |
| 443 | q->memory_usage > q->memory_limit) { | 443 | q->memory_usage > q->memory_limit) { |
| 444 | struct sk_buff *skb = fq_codel_dequeue(sch); | 444 | struct sk_buff *skb = qdisc_dequeue_internal(sch, false); |
| 445 | 445 | ||
| 446 | q->cstats.drop_len += qdisc_pkt_len(skb); | 446 | q->cstats.drop_len += qdisc_pkt_len(skb); |
| 447 | rtnl_kfree_skbs(skb, skb); | 447 | rtnl_kfree_skbs(skb, skb); |
| @@ -366,7 +366,7 @@ static int fq_pie_change(struct Qdisc *sch, struct nlattr *opt, · 365 unmodified lines | |||
| 366 | 366 | ||
| 367 | /* Drop excess packets if new limit is lower */ | 367 | /* Drop excess packets if new limit is lower */ |
| 368 | while (sch->q.qlen > sch->limit) { | 368 | while (sch->q.qlen > sch->limit) { |
| 369 | struct sk_buff *skb = fq_pie_qdisc_dequeue(sch); | 369 | struct sk_buff *skb = qdisc_dequeue_internal(sch, false); |
| 370 | 370 | ||
| 371 | len_dropped += qdisc_pkt_len(skb); | 371 | len_dropped += qdisc_pkt_len(skb); |
| 372 | num_dropped += 1; | 372 | num_dropped += 1; |
| @@ -564,7 +564,7 @@ static int hhf_change(struct Qdisc *sch, struct nlattr *opt, · 563 unmodified lines | |||
| 564 | qlen = sch->q.qlen; | 564 | qlen = sch->q.qlen; |
| 565 | prev_backlog = sch->qstats.backlog; | 565 | prev_backlog = sch->qstats.backlog; |
| 566 | while (sch->q.qlen > sch->limit) { | 566 | while (sch->q.qlen > sch->limit) { |
| 567 | struct sk_buff *skb = hhf_dequeue(sch); | 567 | struct sk_buff *skb = qdisc_dequeue_internal(sch, false); |
| 568 | 568 | ||
| 569 | rtnl_kfree_skbs(skb, skb); | 569 | rtnl_kfree_skbs(skb, skb); |
| 570 | } | 570 | } |
| @@ -195,7 +195,7 @@ static int pie_change(struct Qdisc *sch, struct nlattr *opt, · 194 unmodified lines | |||
| 195 | /* Drop excess packets if new limit is lower */ | 195 | /* Drop excess packets if new limit is lower */ |
| 196 | qlen = sch->q.qlen; | 196 | qlen = sch->q.qlen; |
| 197 | while (sch->q.qlen > sch->limit) { | 197 | while (sch->q.qlen > sch->limit) { |
| 198 | struct sk_buff *skb = __qdisc_dequeue_head(&sch->q); | 198 | struct sk_buff *skb = qdisc_dequeue_internal(sch, true); |
| 199 | 199 | ||
| 200 | dropped += qdisc_pkt_len(skb); | 200 | dropped += qdisc_pkt_len(skb); |
| 201 | qdisc_qstats_backlog_dec(sch, skb); | 201 | qdisc_qstats_backlog_dec(sch, skb); |
| @@ -396,7 +396,6 @@ static int tls_strp_read_copy(struct tls_strparser *strp, bool qshort) · 395 unmodified lines | |||
| 396 | return 0; | 396 | return 0; |
| 397 | 397 | ||
| 398 | shinfo = skb_shinfo(strp->anchor); | 398 | shinfo = skb_shinfo(strp->anchor); |
| 399 | shinfo->frag_list = NULL; | ||
| 400 | 399 | ||
| 401 | /* If we don't know the length go max plus page for cipher overhead */ | 400 | /* If we don't know the length go max plus page for cipher overhead */ |
| 402 | need_spc = strp->stm.full_len ?: TLS_MAX_PAYLOAD_SIZE + PAGE_SIZE; | 401 | need_spc = strp->stm.full_len ?: TLS_MAX_PAYLOAD_SIZE + PAGE_SIZE; |
| @@ -412,6 +411,8 @@ static int tls_strp_read_copy(struct tls_strparser *strp, bool qshort) · 9 unmodified lines | |||
| 412 | page, 0, 0); | 411 | page, 0, 0); |
| 413 | } | 412 | } |
| 414 | 413 | ||
| 414 | shinfo->frag_list = NULL; | ||
| 415 | |||
| 415 | strp->copy_mode = 1; | 416 | strp->copy_mode = 1; |
| 416 | strp->stm.offset = 0; | 417 | strp->stm.offset = 0; |
| 417 | 418 | ||
| @@ -112,7 +112,7 @@ static int __init sample_trace_array_init(void) · 111 unmodified lines | |||
| 112 | /* | 112 | /* |
| 113 | * If context specific per-cpu buffers havent already been allocated. | 113 | * If context specific per-cpu buffers havent already been allocated. |
| 114 | */ | 114 | */ |
| 115 | trace_printk_init_buffers(); | 115 | trace_array_init_printk(tr); |
| 116 | 116 | ||
| 117 | simple_tsk = kthread_run(simple_thread, NULL, "sample-instance"); | 117 | simple_tsk = kthread_run(simple_thread, NULL, "sample-instance"); |
| 118 | if (IS_ERR(simple_tsk)) { | 118 | if (IS_ERR(simple_tsk)) { |
| @@ -37,6 +37,18 @@ KBUILD_CFLAGS += -Wno-gnu · 36 unmodified lines | |||
| 37 | # https://gcc.gnu.org/bugzilla/show_bug.cgi?id=111219 | 37 | # https://gcc.gnu.org/bugzilla/show_bug.cgi?id=111219 |
| 38 | KBUILD_CFLAGS += $(call cc-disable-warning, format-overflow-non-kprintf) | 38 | KBUILD_CFLAGS += $(call cc-disable-warning, format-overflow-non-kprintf) |
| 39 | KBUILD_CFLAGS += $(call cc-disable-warning, format-truncation-non-kprintf) | 39 | KBUILD_CFLAGS += $(call cc-disable-warning, format-truncation-non-kprintf) |
| 40 | |||
| 41 | # Clang may emit a warning when a const variable, such as the dummy variables | ||
| 42 | # in typecheck(), or const member of an aggregate type are not initialized, | ||
| 43 | # which can result in unexpected behavior. However, in many audited cases of | ||
| 44 | # the "field" variant of the warning, this is intentional because the field is | ||
| 45 | # never used within a particular call path, the field is within a union with | ||
| 46 | # other non-const members, or the containing object is not const so the field | ||
| 47 | # can be modified via memcpy() / memset(). While the variable warning also gets | ||
| 48 | # disabled with this same switch, there should not be too much coverage lost | ||
| 49 | # because -Wuninitialized will still flag when an uninitialized const variable | ||
| 50 | # is used. | ||
| 51 | KBUILD_CFLAGS += $(call cc-disable-warning, default-const-init-unsafe) | ||
| 40 | else | 52 | else |
| 41 | 53 | ||
| 42 | # gcc inanely warns about local variables called 'main' | 54 | # gcc inanely warns about local variables called 'main' |
| @@ -94,10 +94,10 @@ $(vmlinux-final): $(RESOLVE_BTFIDS) · 93 unmodified lines | |||
| 94 | endif | 94 | endif |
| 95 | 95 | ||
| 96 | ifdef CONFIG_BUILDTIME_TABLE_SORT | 96 | ifdef CONFIG_BUILDTIME_TABLE_SORT |
| 97 | vmlinux: scripts/sorttable | 97 | $(vmlinux-final): scripts/sorttable |
| 98 | endif | 98 | endif |
| 99 | 99 | ||
| 100 | # module.builtin.ranges | 100 | # modules.builtin.ranges |
| 101 | # --------------------------------------------------------------------------- | 101 | # --------------------------------------------------------------------------- |
| 102 | ifdef CONFIG_BUILTIN_MODULE_RANGES | 102 | ifdef CONFIG_BUILTIN_MODULE_RANGES |
| 103 | __default: modules.builtin.ranges | 103 | __default: modules.builtin.ranges |
| @@ -73,7 +73,7 @@ vmlinux.o: $(initcalls-lds) vmlinux.a $(KBUILD_VMLINUX_LIBS) FORCE · 72 unmodified lines | |||
| 73 | 73 | ||
| 74 | targets += vmlinux.o | 74 | targets += vmlinux.o |
| 75 | 75 | ||
| 76 | # module.builtin.modinfo | 76 | # modules.builtin.modinfo |
| 77 | # --------------------------------------------------------------------------- | 77 | # --------------------------------------------------------------------------- |
| 78 | 78 | ||
| 79 | OBJCOPYFLAGS_modules.builtin.modinfo := -j .modinfo -O binary | 79 | OBJCOPYFLAGS_modules.builtin.modinfo := -j .modinfo -O binary |
| @@ -82,7 +82,7 @@ targets += modules.builtin.modinfo · 2 unmodified lines | |||
| 82 | modules.builtin.modinfo: vmlinux.o FORCE | 82 | modules.builtin.modinfo: vmlinux.o FORCE |
| 83 | $(call if_changed,objcopy) | 83 | $(call if_changed,objcopy) |
| 84 | 84 | ||
| 85 | # module.builtin | 85 | # modules.builtin |
| 86 | # --------------------------------------------------------------------------- | 86 | # --------------------------------------------------------------------------- |
| 87 | 87 | ||
| 88 | # The second line aids cases where multiple modules share the same object. | 88 | # The second line aids cases where multiple modules share the same object. |
| @@ -16,6 +16,7 @@ Source1: config · 15 unmodified lines | |||
| 16 | Source2: diff.patch | 16 | Source2: diff.patch |
| 17 | Provides: kernel-%{KERNELRELEASE} | 17 | Provides: kernel-%{KERNELRELEASE} |
| 18 | BuildRequires: bc binutils bison dwarves | 18 | BuildRequires: bc binutils bison dwarves |
| 19 | BuildRequires: (elfutils-devel or libdw-devel) | ||
| 19 | BuildRequires: (elfutils-libelf-devel or libelf-devel) flex | 20 | BuildRequires: (elfutils-libelf-devel or libelf-devel) flex |
| 20 | BuildRequires: gcc make openssl openssl-devel perl python3 rsync | 21 | BuildRequires: gcc make openssl openssl-devel perl python3 rsync |
| 21 | 22 | ||
| @@ -210,7 +210,7 @@ Rules-Requires-Root: no · 209 unmodified lines | |||
| 210 | Build-Depends: debhelper-compat (= 12) | 210 | Build-Depends: debhelper-compat (= 12) |
| 211 | Build-Depends-Arch: bc, bison, flex, | 211 | Build-Depends-Arch: bc, bison, flex, |
| 212 | gcc-${host_gnu} <!pkg.${sourcename}.nokernelheaders>, | 212 | gcc-${host_gnu} <!pkg.${sourcename}.nokernelheaders>, |
| 213 | kmod, libelf-dev:native, | 213 | kmod, libdw-dev:native, libelf-dev:native, |
| 214 | libssl-dev:native, libssl-dev <!pkg.${sourcename}.nokernelheaders>, | 214 | libssl-dev:native, libssl-dev <!pkg.${sourcename}.nokernelheaders>, |
| 215 | python3:native, rsync | 215 | python3:native, rsync |
| 216 | Homepage: https://www.kernel.org/ | 216 | Homepage: https://www.kernel.org/ |
| @@ -175,7 +175,7 @@ static void test_get_hierarchy(struct kunit *const test) · 174 unmodified lines | |||
| 175 | KUNIT_EXPECT_EQ(test, 10, get_hierarchy(&dom2, 0)->id); | 175 | KUNIT_EXPECT_EQ(test, 10, get_hierarchy(&dom2, 0)->id); |
| 176 | KUNIT_EXPECT_EQ(test, 20, get_hierarchy(&dom2, 1)->id); | 176 | KUNIT_EXPECT_EQ(test, 20, get_hierarchy(&dom2, 1)->id); |
| 177 | KUNIT_EXPECT_EQ(test, 30, get_hierarchy(&dom2, 2)->id); | 177 | KUNIT_EXPECT_EQ(test, 30, get_hierarchy(&dom2, 2)->id); |
| 178 | KUNIT_EXPECT_EQ(test, 30, get_hierarchy(&dom2, -1)->id); | 178 | /* KUNIT_EXPECT_EQ(test, 30, get_hierarchy(&dom2, -1)->id); */ |
| 179 | } | 179 | } |
| 180 | 180 | ||
| 181 | #endif /* CONFIG_SECURITY_LANDLOCK_KUNIT_TEST */ | 181 | #endif /* CONFIG_SECURITY_LANDLOCK_KUNIT_TEST */ |
| @@ -437,7 +437,7 @@ void landlock_log_denial(const struct landlock_cred_security *const subject, · 255 unmodified lines | |||
| 437 | return; | 437 | return; |
| 438 | 438 | ||
| 439 | /* Checks if the current exec was restricting itself. */ | 439 | /* Checks if the current exec was restricting itself. */ |
| 440 | if (subject->domain_exec & (1 << youngest_layer)) { | 440 | if (subject->domain_exec & BIT(youngest_layer)) { |
| 441 | /* Ignores denials for the same execution. */ | 441 | /* Ignores denials for the same execution. */ |
| 442 | if (!youngest_denied->log_same_exec) | 442 | if (!youngest_denied->log_same_exec) |
| 443 | return; | 443 | return; |
| @@ -7,6 +7,7 @@ · 6 unmodified lines | |||
| 7 | 7 | ||
| 8 | #include <kunit/test.h> | 8 | #include <kunit/test.h> |
| 9 | #include <linux/atomic.h> | 9 | #include <linux/atomic.h> |
| 10 | #include <linux/bitops.h> | ||
| 10 | #include <linux/random.h> | 11 | #include <linux/random.h> |
| 11 | #include <linux/spinlock.h> | 12 | #include <linux/spinlock.h> |
| 12 | 13 | ||
| @@ -25,7 +26,7 @@ static void __init init_id(atomic64_t *const counter, const u32 random_32bits) · 12 unmodified lines | |||
| 25 | * Ensures sure 64-bit values are always used by user space (or may | 26 | * Ensures sure 64-bit values are always used by user space (or may |
| 26 | * fail with -EOVERFLOW), and makes this testable. | 27 | * fail with -EOVERFLOW), and makes this testable. |
| 27 | */ | 28 | */ |
| 28 | init = 1ULL << 32; | 29 | init = BIT_ULL(32); |
| 29 | 30 | ||
| 30 | /* | 31 | /* |
| 31 | * Makes a large (2^32) boot-time value to limit ID collision in logs | 32 | * Makes a large (2^32) boot-time value to limit ID collision in logs |
| @@ -105,7 +106,7 @@ static u64 get_id_range(size_t number_of_ids, atomic64_t *const counter, · 73 unmodified lines | |||
| 105 | * to get a new ID (e.g. a full landlock_restrict_self() call), and the | 106 | * to get a new ID (e.g. a full landlock_restrict_self() call), and the |
| 106 | * cost of draining all available IDs during the system's uptime. | 107 | * cost of draining all available IDs during the system's uptime. |
| 107 | */ | 108 | */ |
| 108 | random_4bits = random_4bits % (1 << 4); | 109 | random_4bits &= 0b1111; |
| 109 | step = number_of_ids + random_4bits; | 110 | step = number_of_ids + random_4bits; |
| 110 | 111 | ||
| 111 | /* It is safe to cast a signed atomic to an unsigned value. */ | 112 | /* It is safe to cast a signed atomic to an unsigned value. */ |
| @@ -144,6 +145,19 @@ static void test_range1_rand1(struct kunit *const test) · 32 unmodified lines | |||
| 144 | init + 2); | 145 | init + 2); |
| 145 | } | 146 | } |
| 146 | 147 | ||
| 148 | static void test_range1_rand15(struct kunit *const test) | ||
| 149 | { | ||
| 150 | atomic64_t counter; | ||
| 151 | u64 init; | ||
| 152 | |||
| 153 | init = get_random_u32(); | ||
| 154 | atomic64_set(&counter, init); | ||
| 155 | KUNIT_EXPECT_EQ(test, get_id_range(1, &counter, 15), init); | ||
| 156 | KUNIT_EXPECT_EQ( | ||
| 157 | test, get_id_range(get_random_u8(), &counter, get_random_u8()), | ||
| 158 | init + 16); | ||
| 159 | } | ||
| 160 | |||
| 147 | static void test_range1_rand16(struct kunit *const test) | 161 | static void test_range1_rand16(struct kunit *const test) |
| 148 | { | 162 | { |
| 149 | atomic64_t counter; | 163 | atomic64_t counter; |
| @@ -196,6 +210,19 @@ static void test_range2_rand2(struct kunit *const test) · 46 unmodified lines | |||
| 196 | init + 4); | 210 | init + 4); |
| 197 | } | 211 | } |
| 198 | 212 | ||
| 213 | static void test_range2_rand15(struct kunit *const test) | ||
| 214 | { | ||
| 215 | atomic64_t counter; | ||
| 216 | u64 init; | ||
| 217 | |||
| 218 | init = get_random_u32(); | ||
| 219 | atomic64_set(&counter, init); | ||
| 220 | KUNIT_EXPECT_EQ(test, get_id_range(2, &counter, 15), init); | ||
| 221 | KUNIT_EXPECT_EQ( | ||
| 222 | test, get_id_range(get_random_u8(), &counter, get_random_u8()), | ||
| 223 | init + 17); | ||
| 224 | } | ||
| 225 | |||
| 199 | static void test_range2_rand16(struct kunit *const test) | 226 | static void test_range2_rand16(struct kunit *const test) |
| 200 | { | 227 | { |
| 201 | atomic64_t counter; | 228 | atomic64_t counter; |
| @@ -232,10 +259,12 @@ static struct kunit_case __refdata test_cases[] = { · 30 unmodified lines | |||
| 232 | KUNIT_CASE(test_init_once), | 259 | KUNIT_CASE(test_init_once), |
| 233 | KUNIT_CASE(test_range1_rand0), | 260 | KUNIT_CASE(test_range1_rand0), |
| 234 | KUNIT_CASE(test_range1_rand1), | 261 | KUNIT_CASE(test_range1_rand1), |
| 262 | KUNIT_CASE(test_range1_rand15), | ||
| 235 | KUNIT_CASE(test_range1_rand16), | 263 | KUNIT_CASE(test_range1_rand16), |
| 236 | KUNIT_CASE(test_range2_rand0), | 264 | KUNIT_CASE(test_range2_rand0), |
| 237 | KUNIT_CASE(test_range2_rand1), | 265 | KUNIT_CASE(test_range2_rand1), |
| 238 | KUNIT_CASE(test_range2_rand2), | 266 | KUNIT_CASE(test_range2_rand2), |
| 267 | KUNIT_CASE(test_range2_rand15), | ||
| 239 | KUNIT_CASE(test_range2_rand16), | 268 | KUNIT_CASE(test_range2_rand16), |
| 240 | {} | 269 | {} |
| 241 | /* clang-format on */ | 270 | /* clang-format on */ |
| @@ -9,6 +9,7 @@ · 8 unmodified lines | |||
| 9 | 9 | ||
| 10 | #include <asm/current.h> | 10 | #include <asm/current.h> |
| 11 | #include <linux/anon_inodes.h> | 11 | #include <linux/anon_inodes.h> |
| 12 | #include <linux/bitops.h> | ||
| 12 | #include <linux/build_bug.h> | 13 | #include <linux/build_bug.h> |
| 13 | #include <linux/capability.h> | 14 | #include <linux/capability.h> |
| 14 | #include <linux/cleanup.h> | 15 | #include <linux/cleanup.h> |
| @@ -563,7 +564,7 @@ SYSCALL_DEFINE2(landlock_restrict_self, const int, ruleset_fd, const __u32, · 548 unmodified lines | |||
| 563 | new_llcred->domain = new_dom; | 564 | new_llcred->domain = new_dom; |
| 564 | 565 | ||
| 565 | #ifdef CONFIG_AUDIT | 566 | #ifdef CONFIG_AUDIT |
| 566 | new_llcred->domain_exec |= 1 << (new_dom->num_layers - 1); | 567 | new_llcred->domain_exec |= BIT(new_dom->num_layers - 1); |
| 567 | #endif /* CONFIG_AUDIT */ | 568 | #endif /* CONFIG_AUDIT */ |
| 568 | 569 | ||
| 569 | return commit_creds(new_cred); | 570 | return commit_creds(new_cred); |
| @@ -732,15 +732,21 @@ static int snd_seq_deliver_single_event(struct snd_seq_client *client, · 731 unmodified lines | |||
| 732 | */ | 732 | */ |
| 733 | static int __deliver_to_subscribers(struct snd_seq_client *client, | 733 | static int __deliver_to_subscribers(struct snd_seq_client *client, |
| 734 | struct snd_seq_event *event, | 734 | struct snd_seq_event *event, |
| 735 | struct snd_seq_client_port *src_port, | 735 | int port, int atomic, int hop) |
| 736 | int atomic, int hop) | ||
| 737 | { | 736 | { |
| 737 | struct snd_seq_client_port *src_port; | ||
| 738 | struct snd_seq_subscribers *subs; | 738 | struct snd_seq_subscribers *subs; |
| 739 | int err, result = 0, num_ev = 0; | 739 | int err, result = 0, num_ev = 0; |
| 740 | union __snd_seq_event event_saved; | 740 | union __snd_seq_event event_saved; |
| 741 | size_t saved_size; | 741 | size_t saved_size; |
| 742 | struct snd_seq_port_subs_info *grp; | 742 | struct snd_seq_port_subs_info *grp; |
| 743 | 743 | ||
| 744 | if (port < 0) | ||
| 745 | return 0; | ||
| 746 | src_port = snd_seq_port_use_ptr(client, port); | ||
| 747 | if (!src_port) | ||
| 748 | return 0; | ||
| 749 | |||
| 744 | /* save original event record */ | 750 | /* save original event record */ |
| 745 | saved_size = snd_seq_event_packet_size(event); | 751 | saved_size = snd_seq_event_packet_size(event); |
| 746 | memcpy(&event_saved, event, saved_size); | 752 | memcpy(&event_saved, event, saved_size); |
| @@ -775,6 +781,7 @@ static int __deliver_to_subscribers(struct snd_seq_client *client, · 28 unmodified lines | |||
| 775 | read_unlock(&grp->list_lock); | 781 | read_unlock(&grp->list_lock); |
| 776 | else | 782 | else |
| 777 | up_read(&grp->list_mutex); | 783 | up_read(&grp->list_mutex); |
| 784 | snd_seq_port_unlock(src_port); | ||
| 778 | memcpy(event, &event_saved, saved_size); | 785 | memcpy(event, &event_saved, saved_size); |
| 779 | return (result < 0) ? result : num_ev; | 786 | return (result < 0) ? result : num_ev; |
| 780 | } | 787 | } |
| @@ -783,25 +790,32 @@ static int deliver_to_subscribers(struct snd_seq_client *client, · 2 unmodified lines | |||
| 783 | struct snd_seq_event *event, | 790 | struct snd_seq_event *event, |
| 784 | int atomic, int hop) | 791 | int atomic, int hop) |
| 785 | { | 792 | { |
| 786 | struct snd_seq_client_port *src_port; | 793 | int ret; |
| 787 | int ret = 0, ret2; | 794 | #if IS_ENABLED(CONFIG_SND_SEQ_UMP) |
| 788 | 795 | int ret2; | |
| 789 | src_port = snd_seq_port_use_ptr(client, event->source.port); | 796 | #endif |
| 790 | if (src_port) { | ||
| 791 | ret = __deliver_to_subscribers(client, event, src_port, atomic, hop); | ||
| 792 | snd_seq_port_unlock(src_port); | ||
| 793 | } | ||
| 794 | |||
| 795 | if (client->ump_endpoint_port < 0 || | ||
| 796 | event->source.port == client->ump_endpoint_port) | ||
| 797 | return ret; | ||
| 798 | 797 | ||
| 799 | src_port = snd_seq_port_use_ptr(client, client->ump_endpoint_port); | 798 | ret = __deliver_to_subscribers(client, event, |
| 800 | if (!src_port) | 799 | event->source.port, atomic, hop); |
| 800 | #if IS_ENABLED(CONFIG_SND_SEQ_UMP) | ||
| 801 | if (!snd_seq_client_is_ump(client) || client->ump_endpoint_port < 0) | ||
| 801 | return ret; | 802 | return ret; |
| 802 | ret2 = __deliver_to_subscribers(client, event, src_port, atomic, hop); | 803 | /* If it's an event from EP port (and with a UMP group), |
| 803 | snd_seq_port_unlock(src_port); | 804 | * deliver to subscribers of the corresponding UMP group port, too. |
| 804 | return ret2 < 0 ? ret2 : ret; | 805 | * Or, if it's from non-EP port, deliver to subscribers of EP port, too. |
| 806 | */ | ||
| 807 | if (event->source.port == client->ump_endpoint_port) | ||
| 808 | ret2 = __deliver_to_subscribers(client, event, | ||
| 809 | snd_seq_ump_group_port(event), | ||
| 810 | atomic, hop); | ||
| 811 | else | ||
| 812 | ret2 = __deliver_to_subscribers(client, event, | ||
| 813 | client->ump_endpoint_port, | ||
| 814 | atomic, hop); | ||
| 815 | if (ret2 < 0) | ||
| 816 | return ret2; | ||
| 817 | #endif | ||
| 818 | return ret; | ||
| 805 | } | 819 | } |
| 806 | 820 | ||
| 807 | /* deliver an event to the destination port(s). | 821 | /* deliver an event to the destination port(s). |
| @@ -1285,3 +1285,21 @@ int snd_seq_deliver_to_ump(struct snd_seq_client *source, · 1284 unmodified lines | |||
| 1285 | else | 1285 | else |
| 1286 | return cvt_to_ump_midi1(dest, dest_port, event, atomic, hop); | 1286 | return cvt_to_ump_midi1(dest, dest_port, event, atomic, hop); |
| 1287 | } | 1287 | } |
| 1288 | |||
| 1289 | /* return the UMP group-port number of the event; | ||
| 1290 | * return -1 if groupless or non-UMP event | ||
| 1291 | */ | ||
| 1292 | int snd_seq_ump_group_port(const struct snd_seq_event *event) | ||
| 1293 | { | ||
| 1294 | const struct snd_seq_ump_event *ump_ev = | ||
| 1295 | (const struct snd_seq_ump_event *)event; | ||
| 1296 | unsigned char type; | ||
| 1297 | |||
| 1298 | if (!snd_seq_ev_is_ump(event)) | ||
| 1299 | return -1; | ||
| 1300 | type = ump_message_type(ump_ev->ump[0]); | ||
| 1301 | if (ump_is_groupless_msg(type)) | ||
| 1302 | return -1; | ||
| 1303 | /* group-port number starts from 1 */ | ||
| 1304 | return ump_message_group(ump_ev->ump[0]) + 1; | ||
| 1305 | } | ||
| @@ -18,5 +18,6 @@ int snd_seq_deliver_to_ump(struct snd_seq_client *source, · 17 unmodified lines | |||
| 18 | struct snd_seq_client_port *dest_port, | 18 | struct snd_seq_client_port *dest_port, |
| 19 | struct snd_seq_event *event, | 19 | struct snd_seq_event *event, |
| 20 | int atomic, int hop); | 20 | int atomic, int hop); |
| 21 | int snd_seq_ump_group_port(const struct snd_seq_event *event); | ||
| 21 | 22 | ||
| 22 | #endif /* __SEQ_UMP_CONVERT_H */ | 23 | #endif /* __SEQ_UMP_CONVERT_H */ |
| @@ -177,7 +177,7 @@ static acpi_status sdw_intel_acpi_cb(acpi_handle handle, u32 level, · 176 unmodified lines | |||
| 177 | * sdw_intel_startup() is required for creation of devices and bus | 177 | * sdw_intel_startup() is required for creation of devices and bus |
| 178 | * startup | 178 | * startup |
| 179 | */ | 179 | */ |
| 180 | int sdw_intel_acpi_scan(acpi_handle *parent_handle, | 180 | int sdw_intel_acpi_scan(acpi_handle parent_handle, |
| 181 | struct sdw_intel_acpi_info *info) | 181 | struct sdw_intel_acpi_info *info) |
| 182 | { | 182 | { |
| 183 | acpi_status status; | 183 | acpi_status status; |
| @@ -1561,7 +1561,7 @@ static int snd_es1968_capture_open(struct snd_pcm_substream *substream) · 1560 unmodified lines | |||
| 1561 | struct snd_pcm_runtime *runtime = substream->runtime; | 1561 | struct snd_pcm_runtime *runtime = substream->runtime; |
| 1562 | struct es1968 *chip = snd_pcm_substream_chip(substream); | 1562 | struct es1968 *chip = snd_pcm_substream_chip(substream); |
| 1563 | struct esschan *es; | 1563 | struct esschan *es; |
| 1564 | int apu1, apu2; | 1564 | int err, apu1, apu2; |
| 1565 | 1565 | ||
| 1566 | apu1 = snd_es1968_alloc_apu_pair(chip, ESM_APU_PCM_CAPTURE); | 1566 | apu1 = snd_es1968_alloc_apu_pair(chip, ESM_APU_PCM_CAPTURE); |
| 1567 | if (apu1 < 0) | 1567 | if (apu1 < 0) |
| @@ -1605,7 +1605,9 @@ static int snd_es1968_capture_open(struct snd_pcm_substream *substream) · 37 unmodified lines | |||
| 1605 | runtime->hw = snd_es1968_capture; | 1605 | runtime->hw = snd_es1968_capture; |
| 1606 | runtime->hw.buffer_bytes_max = runtime->hw.period_bytes_max = | 1606 | runtime->hw.buffer_bytes_max = runtime->hw.period_bytes_max = |
| 1607 | calc_available_memory_size(chip) - 1024; /* keep MIXBUF size */ | 1607 | calc_available_memory_size(chip) - 1024; /* keep MIXBUF size */ |
| 1608 | snd_pcm_hw_constraint_pow2(runtime, 0, SNDRV_PCM_HW_PARAM_BUFFER_BYTES); | 1608 | err = snd_pcm_hw_constraint_pow2(runtime, 0, SNDRV_PCM_HW_PARAM_BUFFER_BYTES); |
| 1609 | if (err < 0) | ||
| 1610 | return err; | ||
| 1609 | 1611 | ||
| 1610 | spin_lock_irq(&chip->substream_lock); | 1612 | spin_lock_irq(&chip->substream_lock); |
| 1611 | list_add(&es->list, &chip->substream_list); | 1613 | list_add(&es->list, &chip->substream_list); |
| @@ -14,7 +14,7 @@ if SND_SUPERH · 13 unmodified lines | |||
| 14 | 14 | ||
| 15 | config SND_AICA | 15 | config SND_AICA |
| 16 | tristate "Dreamcast Yamaha AICA sound" | 16 | tristate "Dreamcast Yamaha AICA sound" |
| 17 | depends on SH_DREAMCAST | 17 | depends on SH_DREAMCAST && SH_DMA_API |
| 18 | select SND_PCM | 18 | select SND_PCM |
| 19 | select G2_DMA | 19 | select G2_DMA |
| 20 | help | 20 | help |
| @@ -2242,6 +2242,8 @@ static const struct usb_audio_quirk_flags_table quirk_flags_table[] = { · 2241 unmodified lines | |||
| 2242 | QUIRK_FLAG_CTL_MSG_DELAY_1M), | 2242 | QUIRK_FLAG_CTL_MSG_DELAY_1M), |
| 2243 | DEVICE_FLG(0x0c45, 0x6340, /* Sonix HD USB Camera */ | 2243 | DEVICE_FLG(0x0c45, 0x6340, /* Sonix HD USB Camera */ |
| 2244 | QUIRK_FLAG_GET_SAMPLE_RATE), | 2244 | QUIRK_FLAG_GET_SAMPLE_RATE), |
| 2245 | DEVICE_FLG(0x0c45, 0x636b, /* Microdia JP001 USB Camera */ | ||
| 2246 | QUIRK_FLAG_GET_SAMPLE_RATE), | ||
| 2245 | DEVICE_FLG(0x0d8c, 0x0014, /* USB Audio Device */ | 2247 | DEVICE_FLG(0x0d8c, 0x0014, /* USB Audio Device */ |
| 2246 | QUIRK_FLAG_CTL_MSG_DELAY_1M), | 2248 | QUIRK_FLAG_CTL_MSG_DELAY_1M), |
| 2247 | DEVICE_FLG(0x0ecb, 0x205c, /* JBL Quantum610 Wireless */ | 2249 | DEVICE_FLG(0x0ecb, 0x205c, /* JBL Quantum610 Wireless */ |
| @@ -2250,6 +2252,8 @@ static const struct usb_audio_quirk_flags_table quirk_flags_table[] = { · 2 unmodified lines | |||
| 2250 | QUIRK_FLAG_FIXED_RATE), | 2252 | QUIRK_FLAG_FIXED_RATE), |
| 2251 | DEVICE_FLG(0x0fd9, 0x0008, /* Hauppauge HVR-950Q */ | 2253 | DEVICE_FLG(0x0fd9, 0x0008, /* Hauppauge HVR-950Q */ |
| 2252 | QUIRK_FLAG_SHARE_MEDIA_DEVICE | QUIRK_FLAG_ALIGN_TRANSFER), | 2254 | QUIRK_FLAG_SHARE_MEDIA_DEVICE | QUIRK_FLAG_ALIGN_TRANSFER), |
| 2255 | DEVICE_FLG(0x1101, 0x0003, /* Audioengine D1 */ | ||
| 2256 | QUIRK_FLAG_GET_SAMPLE_RATE), | ||
| 2253 | DEVICE_FLG(0x1224, 0x2a25, /* Jieli Technology USB PHY 2.0 */ | 2257 | DEVICE_FLG(0x1224, 0x2a25, /* Jieli Technology USB PHY 2.0 */ |
| 2254 | QUIRK_FLAG_GET_SAMPLE_RATE | QUIRK_FLAG_MIC_RES_16), | 2258 | QUIRK_FLAG_GET_SAMPLE_RATE | QUIRK_FLAG_MIC_RES_16), |
| 2255 | DEVICE_FLG(0x1395, 0x740a, /* Sennheiser DECT */ | 2259 | DEVICE_FLG(0x1395, 0x740a, /* Sennheiser DECT */ |
| @@ -338,16 +338,24 @@ def main(): · 337 unmodified lines | |||
| 338 | print('Capabilities:') | 338 | print('Capabilities:') |
| 339 | [print(f'\t{v}') for v in bits_to_dict(tsinfo['timestamping'])] | 339 | [print(f'\t{v}') for v in bits_to_dict(tsinfo['timestamping'])] |
| 340 | 340 | ||
| 341 | print(f'PTP Hardware Clock: {tsinfo["phc-index"]}') | 341 | print(f'PTP Hardware Clock: {tsinfo.get("phc-index", "none")}') |
| 342 | 342 | ||
| 343 | print('Hardware Transmit Timestamp Modes:') | 343 | if 'tx-types' in tsinfo: |
| 344 | [print(f'\t{v}') for v in bits_to_dict(tsinfo['tx-types'])] | 344 | print('Hardware Transmit Timestamp Modes:') |
| 345 | [print(f'\t{v}') for v in bits_to_dict(tsinfo['tx-types'])] | ||
| 346 | else: | ||
| 347 | print('Hardware Transmit Timestamp Modes: none') | ||
| 348 | |||
| 349 | if 'rx-filters' in tsinfo: | ||
| 350 | print('Hardware Receive Filter Modes:') | ||
| 351 | [print(f'\t{v}') for v in bits_to_dict(tsinfo['rx-filters'])] | ||
| 352 | else: | ||
| 353 | print('Hardware Receive Filter Modes: none') | ||
| 345 | 354 | ||
| 346 | print('Hardware Receive Filter Modes:') | 355 | if 'stats' in tsinfo and tsinfo['stats']: |
| 347 | [print(f'\t{v}') for v in bits_to_dict(tsinfo['rx-filters'])] | 356 | print('Statistics:') |
| 357 | [print(f'\t{k}: {v}') for k, v in tsinfo['stats'].items()] | ||
| 348 | 358 | ||
| 349 | print('Statistics:') | ||
| 350 | [print(f'\t{k}: {v}') for k, v in tsinfo['stats'].items()] | ||
| 351 | return | 359 | return |
| 352 | 360 | ||
| 353 | print(f'Settings for {args.device}:') | 361 | print(f'Settings for {args.device}:') |
| @@ -1143,10 +1143,9 @@ class Family(SpecFamily): · 1142 unmodified lines | |||
| 1143 | self.pure_nested_structs[nested].request = True | 1143 | self.pure_nested_structs[nested].request = True |
| 1144 | if attr in rs_members['reply']: | 1144 | if attr in rs_members['reply']: |
| 1145 | self.pure_nested_structs[nested].reply = True | 1145 | self.pure_nested_structs[nested].reply = True |
| 1146 | 1146 | if spec.is_multi_val(): | |
| 1147 | if spec.is_multi_val(): | 1147 | child = self.pure_nested_structs.get(nested) |
| 1148 | child = self.pure_nested_structs.get(nested) | 1148 | child.in_multi_val = True |
| 1149 | child.in_multi_val = True | ||
| 1150 | 1149 | ||
| 1151 | self._sort_pure_types() | 1150 | self._sort_pure_types() |
| 1152 | 1151 | ||
| @@ -431,6 +431,22 @@ static int parse_address(const char *str, int port, struct sockaddr_in6 *sin6) · 430 unmodified lines | |||
| 431 | return 0; | 431 | return 0; |
| 432 | } | 432 | } |
| 433 | 433 | ||
| 434 | static struct netdev_queue_id *create_queues(void) | ||
| 435 | { | ||
| 436 | struct netdev_queue_id *queues; | ||
| 437 | size_t i = 0; | ||
| 438 | |||
| 439 | queues = calloc(num_queues, sizeof(*queues)); | ||
| 440 | for (i = 0; i < num_queues; i++) { | ||
| 441 | queues[i]._present.type = 1; | ||
| 442 | queues[i]._present.id = 1; | ||
| 443 | queues[i].type = NETDEV_QUEUE_TYPE_RX; | ||
| 444 | queues[i].id = start_queue + i; | ||
| 445 | } | ||
| 446 | |||
| 447 | return queues; | ||
| 448 | } | ||
| 449 | |||
| 434 | int do_server(struct memory_buffer *mem) | 450 | int do_server(struct memory_buffer *mem) |
| 435 | { | 451 | { |
| 436 | char ctrl_data[sizeof(int) * 20000]; | 452 | char ctrl_data[sizeof(int) * 20000]; |
| @@ -448,7 +464,6 @@ int do_server(struct memory_buffer *mem) · 11 unmodified lines | |||
| 448 | char buffer[256]; | 464 | char buffer[256]; |
| 449 | int socket_fd; | 465 | int socket_fd; |
| 450 | int client_fd; | 466 | int client_fd; |
| 451 | size_t i = 0; | ||
| 452 | int ret; | 467 | int ret; |
| 453 | 468 | ||
| 454 | ret = parse_address(server_ip, atoi(port), &server_sin); | 469 | ret = parse_address(server_ip, atoi(port), &server_sin); |
| @@ -471,16 +486,7 @@ int do_server(struct memory_buffer *mem) · 16 unmodified lines | |||
| 471 | 486 | ||
| 472 | sleep(1); | 487 | sleep(1); |
| 473 | 488 | ||
| 474 | queues = malloc(sizeof(*queues) * num_queues); | 489 | if (bind_rx_queue(ifindex, mem->fd, create_queues(), num_queues, &ys)) |
| 475 | |||
| 476 | for (i = 0; i < num_queues; i++) { | ||
| 477 | queues[i]._present.type = 1; | ||
| 478 | queues[i]._present.id = 1; | ||
| 479 | queues[i].type = NETDEV_QUEUE_TYPE_RX; | ||
| 480 | queues[i].id = start_queue + i; | ||
| 481 | } | ||
| 482 | |||
| 483 | if (bind_rx_queue(ifindex, mem->fd, queues, num_queues, &ys)) | ||
| 484 | error(1, 0, "Failed to bind\n"); | 490 | error(1, 0, "Failed to bind\n"); |
| 485 | 491 | ||
| 486 | tmp_mem = malloc(mem->size); | 492 | tmp_mem = malloc(mem->size); |
| @@ -545,7 +551,6 @@ int do_server(struct memory_buffer *mem) · 58 unmodified lines | |||
| 545 | goto cleanup; | 551 | goto cleanup; |
| 546 | } | 552 | } |
| 547 | 553 | ||
| 548 | i++; | ||
| 549 | for (cm = CMSG_FIRSTHDR(&msg); cm; cm = CMSG_NXTHDR(&msg, cm)) { | 554 | for (cm = CMSG_FIRSTHDR(&msg); cm; cm = CMSG_NXTHDR(&msg, cm)) { |
| 550 | if (cm->cmsg_level != SOL_SOCKET || | 555 | if (cm->cmsg_level != SOL_SOCKET || |
| 551 | (cm->cmsg_type != SCM_DEVMEM_DMABUF && | 556 | (cm->cmsg_type != SCM_DEVMEM_DMABUF && |
| @@ -630,10 +635,8 @@ cleanup: · 78 unmodified lines | |||
| 630 | 635 | ||
| 631 | void run_devmem_tests(void) | 636 | void run_devmem_tests(void) |
| 632 | { | 637 | { |
| 633 | struct netdev_queue_id *queues; | ||
| 634 | struct memory_buffer *mem; | 638 | struct memory_buffer *mem; |
| 635 | struct ynl_sock *ys; | 639 | struct ynl_sock *ys; |
| 636 | size_t i = 0; | ||
| 637 | 640 | ||
| 638 | mem = provider->alloc(getpagesize() * NUM_PAGES); | 641 | mem = provider->alloc(getpagesize() * NUM_PAGES); |
| 639 | 642 | ||
| @@ -641,38 +644,24 @@ void run_devmem_tests(void) · 1 unmodified line | |||
| 641 | if (configure_rss()) | 644 | if (configure_rss()) |
| 642 | error(1, 0, "rss error\n"); | 645 | error(1, 0, "rss error\n"); |
| 643 | 646 | ||
| 644 | queues = calloc(num_queues, sizeof(*queues)); | ||
| 645 | |||
| 646 | if (configure_headersplit(1)) | 647 | if (configure_headersplit(1)) |
| 647 | error(1, 0, "Failed to configure header split\n"); | 648 | error(1, 0, "Failed to configure header split\n"); |
| 648 | 649 | ||
| 649 | if (!bind_rx_queue(ifindex, mem->fd, queues, num_queues, &ys)) | 650 | if (!bind_rx_queue(ifindex, mem->fd, |
| 651 | calloc(num_queues, sizeof(struct netdev_queue_id)), | ||
| 652 | num_queues, &ys)) | ||
| 650 | error(1, 0, "Binding empty queues array should have failed\n"); | 653 | error(1, 0, "Binding empty queues array should have failed\n"); |
| 651 | 654 | ||
| 652 | for (i = 0; i < num_queues; i++) { | ||
| 653 | queues[i]._present.type = 1; | ||
| 654 | queues[i]._present.id = 1; | ||
| 655 | queues[i].type = NETDEV_QUEUE_TYPE_RX; | ||
| 656 | queues[i].id = start_queue + i; | ||
| 657 | } | ||
| 658 | |||
| 659 | if (configure_headersplit(0)) | 655 | if (configure_headersplit(0)) |
| 660 | error(1, 0, "Failed to configure header split\n"); | 656 | error(1, 0, "Failed to configure header split\n"); |
| 661 | 657 | ||
| 662 | if (!bind_rx_queue(ifindex, mem->fd, queues, num_queues, &ys)) | 658 | if (!bind_rx_queue(ifindex, mem->fd, create_queues(), num_queues, &ys)) |
| 663 | error(1, 0, "Configure dmabuf with header split off should have failed\n"); | 659 | error(1, 0, "Configure dmabuf with header split off should have failed\n"); |
| 664 | 660 | ||
| 665 | if (configure_headersplit(1)) | 661 | if (configure_headersplit(1)) |
| 666 | error(1, 0, "Failed to configure header split\n"); | 662 | error(1, 0, "Failed to configure header split\n"); |
| 667 | 663 | ||
| 668 | for (i = 0; i < num_queues; i++) { | 664 | if (bind_rx_queue(ifindex, mem->fd, create_queues(), num_queues, &ys)) |
| 669 | queues[i]._present.type = 1; | ||
| 670 | queues[i]._present.id = 1; | ||
| 671 | queues[i].type = NETDEV_QUEUE_TYPE_RX; | ||
| 672 | queues[i].id = start_queue + i; | ||
| 673 | } | ||
| 674 | |||
| 675 | if (bind_rx_queue(ifindex, mem->fd, queues, num_queues, &ys)) | ||
| 676 | error(1, 0, "Failed to bind\n"); | 665 | error(1, 0, "Failed to bind\n"); |
| 677 | 666 | ||
| 678 | /* Deactivating a bound queue should not be legal */ | 667 | /* Deactivating a bound queue should not be legal */ |
| @@ -189,5 +189,29 @@ · 188 unmodified lines | |||
| 189 | "teardown": [ | 189 | "teardown": [ |
| 190 | "$TC qdisc del dev $DUMMY handle 1: root" | 190 | "$TC qdisc del dev $DUMMY handle 1: root" |
| 191 | ] | 191 | ] |
| 192 | }, | ||
| 193 | { | ||
| 194 | "id": "deb1", | ||
| 195 | "name": "CODEL test qdisc limit trimming", | ||
| 196 | "category": ["qdisc", "codel"], | ||
| 197 | "plugins": { | ||
| 198 | "requires": ["nsPlugin", "scapyPlugin"] | ||
| 199 | }, | ||
| 200 | "setup": [ | ||
| 201 | "$TC qdisc add dev $DEV1 handle 1: root codel limit 10" | ||
| 202 | ], | ||
| 203 | "scapy": [ | ||
| 204 | { | ||
| 205 | "iface": "$DEV0", | ||
| 206 | "count": 10, | ||
| 207 | "packet": "Ether(type=0x800)/IP(src='10.0.0.10',dst='10.0.0.20')/TCP(sport=5000,dport=10)" | ||
| 208 | } | ||
| 209 | ], | ||
| 210 | "cmdUnderTest": "$TC qdisc change dev $DEV1 handle 1: root codel limit 1", | ||
| 211 | "expExitCode": "0", | ||
| 212 | "verifyCmd": "$TC qdisc show dev $DEV1", | ||
| 213 | "matchPattern": "qdisc codel 1: root refcnt [0-9]+ limit 1p target 5ms interval 100ms", | ||
| 214 | "matchCount": "1", | ||
| 215 | "teardown": ["$TC qdisc del dev $DEV1 handle 1: root"] | ||
| 192 | } | 216 | } |
| 193 | ] | 217 | ] |
| @@ -377,5 +377,27 @@ · 376 unmodified lines | |||
| 377 | "teardown": [ | 377 | "teardown": [ |
| 378 | "$TC qdisc del dev $DUMMY handle 1: root" | 378 | "$TC qdisc del dev $DUMMY handle 1: root" |
| 379 | ] | 379 | ] |
| 380 | }, | ||
| 381 | { | ||
| 382 | "id": "9479", | ||
| 383 | "name": "FQ test qdisc limit trimming", | ||
| 384 | "category": ["qdisc", "fq"], | ||
| 385 | "plugins": {"requires": ["nsPlugin", "scapyPlugin"]}, | ||
| 386 | "setup": [ | ||
| 387 | "$TC qdisc add dev $DEV1 handle 1: root fq limit 10" | ||
| 388 | ], | ||
| 389 | "scapy": [ | ||
| 390 | { | ||
| 391 | "iface": "$DEV0", | ||
| 392 | "count": 10, | ||
| 393 | "packet": "Ether(type=0x800)/IP(src='10.0.0.10',dst='10.0.0.20')/TCP(sport=5000,dport=10)" | ||
| 394 | } | ||
| 395 | ], | ||
| 396 | "cmdUnderTest": "$TC qdisc change dev $DEV1 handle 1: root fq limit 1", | ||
| 397 | "expExitCode": "0", | ||
| 398 | "verifyCmd": "$TC qdisc show dev $DEV1", | ||
| 399 | "matchPattern": "qdisc fq 1: root refcnt [0-9]+ limit 1p", | ||
| 400 | "matchCount": "1", | ||
| 401 | "teardown": ["$TC qdisc del dev $DEV1 handle 1: root"] | ||
| 380 | } | 402 | } |
| 381 | ] | 403 | ] |
| @@ -294,5 +294,27 @@ · 293 unmodified lines | |||
| 294 | "teardown": [ | 294 | "teardown": [ |
| 295 | "$TC qdisc del dev $DUMMY handle 1: root" | 295 | "$TC qdisc del dev $DUMMY handle 1: root" |
| 296 | ] | 296 | ] |
| 297 | }, | ||
| 298 | { | ||
| 299 | "id": "0436", | ||
| 300 | "name": "FQ_CODEL test qdisc limit trimming", | ||
| 301 | "category": ["qdisc", "fq_codel"], | ||
| 302 | "plugins": {"requires": ["nsPlugin", "scapyPlugin"]}, | ||
| 303 | "setup": [ | ||
| 304 | "$TC qdisc add dev $DEV1 handle 1: root fq_codel limit 10" | ||
| 305 | ], | ||
| 306 | "scapy": [ | ||
| 307 | { | ||
| 308 | "iface": "$DEV0", | ||
| 309 | "count": 10, | ||
| 310 | "packet": "Ether(type=0x800)/IP(src='10.0.0.10',dst='10.0.0.20')/TCP(sport=5000,dport=10)" | ||
| 311 | } | ||
| 312 | ], | ||
| 313 | "cmdUnderTest": "$TC qdisc change dev $DEV1 handle 1: root fq_codel limit 1", | ||
| 314 | "expExitCode": "0", | ||
| 315 | "verifyCmd": "$TC qdisc show dev $DEV1", | ||
| 316 | "matchPattern": "qdisc fq_codel 1: root refcnt [0-9]+ limit 1p flows 1024 quantum.*target 5ms interval 100ms memory_limit 32Mb ecn drop_batch 64", | ||
| 317 | "matchCount": "1", | ||
| 318 | "teardown": ["$TC qdisc del dev $DEV1 handle 1: root"] | ||
| 297 | } | 319 | } |
| 298 | ] | 320 | ] |
| @@ -18,5 +18,27 @@ · 17 unmodified lines | |||
| 18 | "matchCount": "1", | 18 | "matchCount": "1", |
| 19 | "teardown": [ | 19 | "teardown": [ |
| 20 | ] | 20 | ] |
| 21 | }, | ||
| 22 | { | ||
| 23 | "id": "83bf", | ||
| 24 | "name": "FQ_PIE test qdisc limit trimming", | ||
| 25 | "category": ["qdisc", "fq_pie"], | ||
| 26 | "plugins": {"requires": ["nsPlugin", "scapyPlugin"]}, | ||
| 27 | "setup": [ | ||
| 28 | "$TC qdisc add dev $DEV1 handle 1: root fq_pie limit 10" | ||
| 29 | ], | ||
| 30 | "scapy": [ | ||
| 31 | { | ||
| 32 | "iface": "$DEV0", | ||
| 33 | "count": 10, | ||
| 34 | "packet": "Ether(type=0x800)/IP(src='10.0.0.10',dst='10.0.0.20')/TCP(sport=5000,dport=10)" | ||
| 35 | } | ||
| 36 | ], | ||
| 37 | "cmdUnderTest": "$TC qdisc change dev $DEV1 handle 1: root fq_pie limit 1", | ||
| 38 | "expExitCode": "0", | ||
| 39 | "verifyCmd": "$TC qdisc show dev $DEV1", | ||
| 40 | "matchPattern": "qdisc fq_pie 1: root refcnt [0-9]+ limit 1p", | ||
| 41 | "matchCount": "1", | ||
| 42 | "teardown": ["$TC qdisc del dev $DEV1 handle 1: root"] | ||
| 21 | } | 43 | } |
| 22 | ] | 44 | ] |
| @@ -188,5 +188,27 @@ · 187 unmodified lines | |||
| 188 | "teardown": [ | 188 | "teardown": [ |
| 189 | "$TC qdisc del dev $DUMMY handle 1: root" | 189 | "$TC qdisc del dev $DUMMY handle 1: root" |
| 190 | ] | 190 | ] |
| 191 | }, | ||
| 192 | { | ||
| 193 | "id": "385f", | ||
| 194 | "name": "HHF test qdisc limit trimming", | ||
| 195 | "category": ["qdisc", "hhf"], | ||
| 196 | "plugins": {"requires": ["nsPlugin", "scapyPlugin"]}, | ||
| 197 | "setup": [ | ||
| 198 | "$TC qdisc add dev $DEV1 handle 1: root hhf limit 10" | ||
| 199 | ], | ||
| 200 | "scapy": [ | ||
| 201 | { | ||
| 202 | "iface": "$DEV0", | ||
| 203 | "count": 10, | ||
| 204 | "packet": "Ether(type=0x800)/IP(src='10.0.0.10',dst='10.0.0.20')/TCP(sport=5000,dport=10)" | ||
| 205 | } | ||
| 206 | ], | ||
| 207 | "cmdUnderTest": "$TC qdisc change dev $DEV1 handle 1: root hhf limit 1", | ||
| 208 | "expExitCode": "0", | ||
| 209 | "verifyCmd": "$TC qdisc show dev $DEV1", | ||
| 210 | "matchPattern": "qdisc hhf 1: root refcnt [0-9]+ limit 1p.*hh_limit 2048 reset_timeout 40ms admit_bytes 128Kb evict_timeout 1s non_hh_weight 2", | ||
| 211 | "matchCount": "1", | ||
| 212 | "teardown": ["$TC qdisc del dev $DEV1 handle 1: root"] | ||
| 191 | } | 213 | } |
| 192 | ] | 214 | ] |
| @@ -0,0 +1,24 @@ | |||
| 1 | [ | ||
| 2 | { | ||
| 3 | "id": "6158", | ||
| 4 | "name": "PIE test qdisc limit trimming", | ||
| 5 | "category": ["qdisc", "pie"], | ||
| 6 | "plugins": {"requires": ["nsPlugin", "scapyPlugin"]}, | ||
| 7 | "setup": [ | ||
| 8 | "$TC qdisc add dev $DEV1 handle 1: root pie limit 10" | ||
| 9 | ], | ||
| 10 | "scapy": [ | ||
| 11 | { | ||
| 12 | "iface": "$DEV0", | ||
| 13 | "count": 10, | ||
| 14 | "packet": "Ether(type=0x800)/IP(src='10.0.0.10',dst='10.0.0.20')/TCP(sport=5000,dport=10)" | ||
| 15 | } | ||
| 16 | ], | ||
| 17 | "cmdUnderTest": "$TC qdisc change dev $DEV1 handle 1: root pie limit 1", | ||
| 18 | "expExitCode": "0", | ||
| 19 | "verifyCmd": "$TC qdisc show dev $DEV1", | ||
| 20 | "matchPattern": "qdisc pie 1: root refcnt [0-9]+ limit 1p", | ||
| 21 | "matchCount": "1", | ||
| 22 | "teardown": ["$TC qdisc del dev $DEV1 handle 1: root"] | ||
| 23 | } | ||
| 24 | ] | ||
| @@ -1264,21 +1264,25 @@ static void test_unsent_bytes_client(const struct test_opts *opts, int type) · 1263 unmodified lines | |||
| 1264 | send_buf(fd, buf, sizeof(buf), 0, sizeof(buf)); | 1264 | send_buf(fd, buf, sizeof(buf), 0, sizeof(buf)); |
| 1265 | control_expectln("RECEIVED"); | 1265 | control_expectln("RECEIVED"); |
| 1266 | 1266 | ||
| 1267 | ret = ioctl(fd, SIOCOUTQ, &sock_bytes_unsent); | 1267 | /* SIOCOUTQ isn't guaranteed to instantly track sent data. Even though |
| 1268 | if (ret < 0) { | 1268 | * the "RECEIVED" message means that the other side has received the |
| 1269 | if (errno == EOPNOTSUPP) { | 1269 | * data, there can be a delay in our kernel before updating the "unsent |
| 1270 | fprintf(stderr, "Test skipped, SIOCOUTQ not supported.\n"); | 1270 | * bytes" counter. Repeat SIOCOUTQ until it returns 0. |
| 1271 | } else { | 1271 | */ |
| 1272 | timeout_begin(TIMEOUT); | ||
| 1273 | do { | ||
| 1274 | ret = ioctl(fd, SIOCOUTQ, &sock_bytes_unsent); | ||
| 1275 | if (ret < 0) { | ||
| 1276 | if (errno == EOPNOTSUPP) { | ||
| 1277 | fprintf(stderr, "Test skipped, SIOCOUTQ not supported.\n"); | ||
| 1278 | break; | ||
| 1279 | } | ||
| 1272 | perror("ioctl"); | 1280 | perror("ioctl"); |
| 1273 | exit(EXIT_FAILURE); | 1281 | exit(EXIT_FAILURE); |
| 1274 | } | 1282 | } |
| 1275 | } else if (ret == 0 && sock_bytes_unsent != 0) { | 1283 | timeout_check("SIOCOUTQ"); |
| 1276 | fprintf(stderr, | 1284 | } while (sock_bytes_unsent != 0); |
| 1277 | "Unexpected 'SIOCOUTQ' value, expected 0, got %i\n", | 1285 | timeout_end(); |
| 1278 | sock_bytes_unsent); | ||
| 1279 | exit(EXIT_FAILURE); | ||
| 1280 | } | ||
| 1281 | |||
| 1282 | close(fd); | 1286 | close(fd); |
| 1283 | } | 1287 | } |
| 1284 | 1288 | ||
| @@ -59,6 +59,10 @@ ifeq ($(SRCARCH),arc) · 58 unmodified lines | |||
| 59 | no-header-test += linux/bpf_perf_event.h | 59 | no-header-test += linux/bpf_perf_event.h |
| 60 | endif | 60 | endif |
| 61 | 61 | ||
| 62 | ifeq ($(SRCARCH),openrisc) | ||
| 63 | no-header-test += linux/bpf_perf_event.h | ||
| 64 | endif | ||
| 65 | |||
| 62 | ifeq ($(SRCARCH),powerpc) | 66 | ifeq ($(SRCARCH),powerpc) |
| 63 | no-header-test += linux/bpf_perf_event.h | 67 | no-header-test += linux/bpf_perf_event.h |
| 64 | endif | 68 | endif |