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 | 102 | Arnaud Patard <arnaud.patard@rtp-net.org> |
| 103 | 103 | Arnd Bergmann <arnd@arndb.de> |
| 104 | 104 | Arun Kumar Neelakantam <quic_aneela@quicinc.com> <aneela@codeaurora.org> |
| 105 | +Asahi Lina <lina+kernel@asahilina.net> <lina@asahilina.net> | |
| 105 | 106 | Ashok Raj Nagarajan <quic_arnagara@quicinc.com> <arnagara@codeaurora.org> |
| 106 | 107 | Ashwin Chaugule <quic_ashwinc@quicinc.com> <ashwinc@codeaurora.org> |
| 107 | 108 | Asutosh Das <quic_asutoshd@quicinc.com> <asutoshd@codeaurora.org> |
| @@ -1,6 +1,6 @@ | ||
| 1 | 1 | What: /sys/bus/hid/drivers/hid-appletb-kbd/<dev>/mode |
| 2 | −Date: September, 2023 | |
| 3 | −KernelVersion: 6.5 | |
| 2 | +Date: March, 2025 | |
| 3 | +KernelVersion: 6.15 | |
| 4 | 4 | Contact: linux-input@vger.kernel.org |
| 5 | 5 | Description: |
| 6 | 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 | 46 | `KBUILD_BUILD_USER and KBUILD_BUILD_HOST`_ variables. If you are |
| 47 | 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 | 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 | 132 | .. _KBUILD_BUILD_TIMESTAMP: kbuild.html#kbuild-build-timestamp |
| 118 | 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 | 136 | .. _Reproducible Builds project: https://reproducible-builds.org/ |
| 120 | 137 | .. _SOURCE_DATE_EPOCH: https://reproducible-builds.org/docs/source-date-epoch/ |
| @@ -2017,7 +2017,8 @@ attribute-sets: · 2016 unmodified lines | ||
| 2017 | 2017 | attributes: |
| 2018 | 2018 | - |
| 2019 | 2019 | name: act |
| 2020 | − type: nest | |
| 2020 | + type: indexed-array | |
| 2021 | + sub-type: nest | |
| 2021 | 2022 | nested-attributes: tc-act-attrs |
| 2022 | 2023 | - |
| 2023 | 2024 | name: police |
| @@ -2250,7 +2251,8 @@ attribute-sets: · 226 unmodified lines | ||
| 2250 | 2251 | attributes: |
| 2251 | 2252 | - |
| 2252 | 2253 | name: act |
| 2253 | − type: nest | |
| 2254 | + type: indexed-array | |
| 2255 | + sub-type: nest | |
| 2254 | 2256 | nested-attributes: tc-act-attrs |
| 2255 | 2257 | - |
| 2256 | 2258 | name: police |
| @@ -2745,7 +2747,7 @@ attribute-sets: · 488 unmodified lines | ||
| 2745 | 2747 | type: u16 |
| 2746 | 2748 | byte-order: big-endian |
| 2747 | 2749 | - |
| 2748 | − name: key-l2-tpv3-sid | |
| 2750 | + name: key-l2tpv3-sid | |
| 2749 | 2751 | type: u32 |
| 2750 | 2752 | byte-order: big-endian |
| 2751 | 2753 | - |
| @@ -3504,7 +3506,7 @@ attribute-sets: · 752 unmodified lines | ||
| 3504 | 3506 | name: rate64 |
| 3505 | 3507 | type: u64 |
| 3506 | 3508 | - |
| 3507 | − name: prate4 | |
| 3509 | + name: prate64 | |
| 3508 | 3510 | type: u64 |
| 3509 | 3511 | - |
| 3510 | 3512 | name: burst |
| @@ -811,11 +811,9 @@ Documentation/devicetree/bindings/ptp/timestamper.txt for more details. · 810 unmodified lines | ||
| 811 | 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 | |
| 815 | −modification to MAC drivers, so it is more difficult to ensure correctness of | |
| 816 | −all possible code paths - is that they uncover bugs which were impossible to | |
| 817 | −trigger before the existence of stacked PTP clocks. One example has to do with | |
| 818 | −this line of code, already presented earlier:: | |
| 814 | +The use of stacked PHCs may uncover MAC driver bugs which were impossible to | |
| 815 | +trigger without them. One example has to do with this line of code, already | |
| 816 | +presented earlier:: | |
| 819 | 817 | |
| 820 | 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 | 10147 | F: include/linux/gpio/regmap.h |
| 10148 | 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 | 10157 | GPIO SUBSYSTEM |
| 10151 | 10158 | M: Linus Walleij <linus.walleij@linaro.org> |
| 10152 | 10159 | M: Bartosz Golaszewski <brgl@bgdev.pl> |
| @@ -15542,6 +15549,18 @@ S: Maintained · 5389 unmodified lines | ||
| 15542 | 15549 | F: include/linux/execmem.h |
| 15543 | 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 | 15564 | MEMORY MANAGEMENT - NUMA MEMBLOCKS AND NUMA EMULATION |
| 15546 | 15565 | M: Andrew Morton <akpm@linux-foundation.org> |
| 15547 | 15566 | M: Mike Rapoport <rppt@kernel.org> |
| @@ -18432,7 +18451,7 @@ F: include/uapi/linux/ppdev.h · 2884 unmodified lines | ||
| 18432 | 18451 | PARAVIRT_OPS INTERFACE |
| 18433 | 18452 | M: Juergen Gross <jgross@suse.com> |
| 18434 | 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 | 18455 | R: Broadcom internal kernel review list <bcm-kernel-feedback-list@broadcom.com> |
| 18437 | 18456 | L: virtualization@lists.linux.dev |
| 18438 | 18457 | L: x86@kernel.org |
| @@ -22916,7 +22935,6 @@ F: drivers/accessibility/speakup/ · 4477 unmodified lines | ||
| 22916 | 22935 | |
| 22917 | 22936 | SPEAR PLATFORM/CLOCK/PINCTRL SUPPORT |
| 22918 | 22937 | M: Viresh Kumar <vireshk@kernel.org> |
| 22919 | −M: Shiraz Hashim <shiraz.linux.kernel@gmail.com> | |
| 22920 | 22938 | L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) |
| 22921 | 22939 | L: soc@lists.linux.dev |
| 22922 | 22940 | S: Maintained |
| @@ -25918,7 +25936,7 @@ F: drivers/misc/vmw_balloon.c · 2995 unmodified lines | ||
| 25918 | 25936 | |
| 25919 | 25937 | VMWARE HYPERVISOR INTERFACE |
| 25920 | 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 | 25940 | R: Broadcom internal kernel review list <bcm-kernel-feedback-list@broadcom.com> |
| 25923 | 25941 | L: virtualization@lists.linux.dev |
| 25924 | 25942 | L: x86@kernel.org |
| @@ -25946,7 +25964,7 @@ F: drivers/scsi/vmw_pvscsi.h · 21 unmodified lines | ||
| 25946 | 25964 | VMWARE VIRTUAL PTP CLOCK DRIVER |
| 25947 | 25965 | M: Nick Shi <nick.shi@broadcom.com> |
| 25948 | 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 | 25968 | R: Broadcom internal kernel review list <bcm-kernel-feedback-list@broadcom.com> |
| 25951 | 25969 | L: netdev@vger.kernel.org |
| 25952 | 25970 | S: Supported |
| @@ -2,7 +2,7 @@ · 1 unmodified line | ||
| 2 | 2 | VERSION = 6 |
| 3 | 3 | PATCHLEVEL = 15 |
| 4 | 4 | SUBLEVEL = 0 |
| 5 | −EXTRAVERSION = -rc6 | |
| 5 | +EXTRAVERSION = -rc7 | |
| 6 | 6 | NAME = Baby Opossum Posse |
| 7 | 7 | |
| 8 | 8 | # *DOCUMENTATION* |
| @@ -1068,8 +1068,7 @@ KBUILD_CFLAGS += -fno-builtin-wcslen · 1059 unmodified lines | ||
| 1068 | 1068 | |
| 1069 | 1069 | # change __FILE__ to the relative path to the source directory |
| 1070 | 1070 | ifdef building_out_of_srctree |
| 1071 | −KBUILD_CPPFLAGS += $(call cc-option,-ffile-prefix-map=$(srcroot)/=) | |
| 1072 | −KBUILD_RUSTFLAGS += --remap-path-prefix=$(srcroot)/= | |
| 1071 | +KBUILD_CPPFLAGS += $(call cc-option,-fmacro-prefix-map=$(srcroot)/=) | |
| 1073 | 1072 | endif |
| 1074 | 1073 | |
| 1075 | 1074 | # include additional Makefiles when needed |
| @@ -451,7 +451,7 @@ · 450 unmodified lines | ||
| 451 | 451 | pwm_ef: pwm@86c0 { |
| 452 | 452 | compatible = "amlogic,meson8-pwm-v2"; |
| 453 | 453 | clocks = <&xtal>, |
| 454 | − <>, /* unknown/untested, the datasheet calls it "Video PLL" */ | |
| 454 | + <0>, /* unknown/untested, the datasheet calls it "Video PLL" */ | |
| 455 | 455 | <&clkc CLKID_FCLK_DIV4>, |
| 456 | 456 | <&clkc CLKID_FCLK_DIV3>; |
| 457 | 457 | reg = <0x86c0 0x10>; |
| @@ -705,7 +705,7 @@ · 247 unmodified lines | ||
| 705 | 705 | &pwm_ab { |
| 706 | 706 | compatible = "amlogic,meson8-pwm-v2"; |
| 707 | 707 | clocks = <&xtal>, |
| 708 | − <>, /* unknown/untested, the datasheet calls it "Video PLL" */ | |
| 708 | + <0>, /* unknown/untested, the datasheet calls it "Video PLL" */ | |
| 709 | 709 | <&clkc CLKID_FCLK_DIV4>, |
| 710 | 710 | <&clkc CLKID_FCLK_DIV3>; |
| 711 | 711 | }; |
| @@ -713,7 +713,7 @@ · 1 unmodified line | ||
| 713 | 713 | &pwm_cd { |
| 714 | 714 | compatible = "amlogic,meson8-pwm-v2"; |
| 715 | 715 | clocks = <&xtal>, |
| 716 | − <>, /* unknown/untested, the datasheet calls it "Video PLL" */ | |
| 716 | + <0>, /* unknown/untested, the datasheet calls it "Video PLL" */ | |
| 717 | 717 | <&clkc CLKID_FCLK_DIV4>, |
| 718 | 718 | <&clkc CLKID_FCLK_DIV3>; |
| 719 | 719 | }; |
| @@ -406,7 +406,7 @@ · 405 unmodified lines | ||
| 406 | 406 | compatible = "amlogic,meson8b-pwm-v2", "amlogic,meson8-pwm-v2"; |
| 407 | 407 | reg = <0x86c0 0x10>; |
| 408 | 408 | clocks = <&xtal>, |
| 409 | − <>, /* unknown/untested, the datasheet calls it "Video PLL" */ | |
| 409 | + <0>, /* unknown/untested, the datasheet calls it "Video PLL" */ | |
| 410 | 410 | <&clkc CLKID_FCLK_DIV4>, |
| 411 | 411 | <&clkc CLKID_FCLK_DIV3>; |
| 412 | 412 | #pwm-cells = <3>; |
| @@ -680,7 +680,7 @@ · 267 unmodified lines | ||
| 680 | 680 | &pwm_ab { |
| 681 | 681 | compatible = "amlogic,meson8b-pwm-v2", "amlogic,meson8-pwm-v2"; |
| 682 | 682 | clocks = <&xtal>, |
| 683 | − <>, /* unknown/untested, the datasheet calls it "Video PLL" */ | |
| 683 | + <0>, /* unknown/untested, the datasheet calls it "Video PLL" */ | |
| 684 | 684 | <&clkc CLKID_FCLK_DIV4>, |
| 685 | 685 | <&clkc CLKID_FCLK_DIV3>; |
| 686 | 686 | }; |
| @@ -688,7 +688,7 @@ · 1 unmodified line | ||
| 688 | 688 | &pwm_cd { |
| 689 | 689 | compatible = "amlogic,meson8b-pwm-v2", "amlogic,meson8-pwm-v2"; |
| 690 | 690 | clocks = <&xtal>, |
| 691 | − <>, /* unknown/untested, the datasheet calls it "Video PLL" */ | |
| 691 | + <0>, /* unknown/untested, the datasheet calls it "Video PLL" */ | |
| 692 | 692 | <&clkc CLKID_FCLK_DIV4>, |
| 693 | 693 | <&clkc CLKID_FCLK_DIV3>; |
| 694 | 694 | }; |
| @@ -151,7 +151,7 @@ · 150 unmodified lines | ||
| 151 | 151 | al,msi-num-spis = <160>; |
| 152 | 152 | }; |
| 153 | 153 | |
| 154 | − io-fabric@fc000000 { | |
| 154 | + io-bus@fc000000 { | |
| 155 | 155 | compatible = "simple-bus"; |
| 156 | 156 | #address-cells = <1>; |
| 157 | 157 | #size-cells = <1>; |
| @@ -361,7 +361,7 @@ · 360 unmodified lines | ||
| 361 | 361 | interrupt-parent = <&gic>; |
| 362 | 362 | }; |
| 363 | 363 | |
| 364 | − io-fabric@fc000000 { | |
| 364 | + io-bus@fc000000 { | |
| 365 | 365 | compatible = "simple-bus"; |
| 366 | 366 | #address-cells = <1>; |
| 367 | 367 | #size-cells = <1>; |
| @@ -2313,7 +2313,7 @@ · 2312 unmodified lines | ||
| 2313 | 2313 | "amlogic,meson8-pwm-v2"; |
| 2314 | 2314 | reg = <0x0 0x19000 0x0 0x20>; |
| 2315 | 2315 | clocks = <&xtal>, |
| 2316 | − <>, /* unknown/untested, the datasheet calls it "vid_pll" */ | |
| 2316 | + <0>, /* unknown/untested, the datasheet calls it "vid_pll" */ | |
| 2317 | 2317 | <&clkc CLKID_FCLK_DIV4>, |
| 2318 | 2318 | <&clkc CLKID_FCLK_DIV3>; |
| 2319 | 2319 | #pwm-cells = <3>; |
| @@ -2325,7 +2325,7 @@ · 5 unmodified lines | ||
| 2325 | 2325 | "amlogic,meson8-pwm-v2"; |
| 2326 | 2326 | reg = <0x0 0x1a000 0x0 0x20>; |
| 2327 | 2327 | clocks = <&xtal>, |
| 2328 | − <>, /* unknown/untested, the datasheet calls it "vid_pll" */ | |
| 2328 | + <0>, /* unknown/untested, the datasheet calls it "vid_pll" */ | |
| 2329 | 2329 | <&clkc CLKID_FCLK_DIV4>, |
| 2330 | 2330 | <&clkc CLKID_FCLK_DIV3>; |
| 2331 | 2331 | #pwm-cells = <3>; |
| @@ -2337,7 +2337,7 @@ · 5 unmodified lines | ||
| 2337 | 2337 | "amlogic,meson8-pwm-v2"; |
| 2338 | 2338 | reg = <0x0 0x1b000 0x0 0x20>; |
| 2339 | 2339 | clocks = <&xtal>, |
| 2340 | − <>, /* unknown/untested, the datasheet calls it "vid_pll" */ | |
| 2340 | + <0>, /* unknown/untested, the datasheet calls it "vid_pll" */ | |
| 2341 | 2341 | <&clkc CLKID_FCLK_DIV4>, |
| 2342 | 2342 | <&clkc CLKID_FCLK_DIV3>; |
| 2343 | 2343 | #pwm-cells = <3>; |
| @@ -116,6 +116,10 @@ · 115 unmodified lines | ||
| 116 | 116 | status = "okay"; |
| 117 | 117 | }; |
| 118 | 118 | |
| 119 | +&clkc_audio { | |
| 120 | + status = "okay"; | |
| 121 | +}; | |
| 122 | + | |
| 119 | 123 | &frddr_a { |
| 120 | 124 | status = "okay"; |
| 121 | 125 | }; |
| @@ -741,7 +741,7 @@ · 740 unmodified lines | ||
| 741 | 741 | |
| 742 | 742 | &pwm_ab { |
| 743 | 743 | clocks = <&xtal>, |
| 744 | − <>, /* unknown/untested, the datasheet calls it "vid_pll" */ | |
| 744 | + <0>, /* unknown/untested, the datasheet calls it "vid_pll" */ | |
| 745 | 745 | <&clkc CLKID_FCLK_DIV4>, |
| 746 | 746 | <&clkc CLKID_FCLK_DIV3>; |
| 747 | 747 | }; |
| @@ -752,14 +752,14 @@ · 4 unmodified lines | ||
| 752 | 752 | |
| 753 | 753 | &pwm_cd { |
| 754 | 754 | clocks = <&xtal>, |
| 755 | − <>, /* unknown/untested, the datasheet calls it "vid_pll" */ | |
| 755 | + <0>, /* unknown/untested, the datasheet calls it "vid_pll" */ | |
| 756 | 756 | <&clkc CLKID_FCLK_DIV4>, |
| 757 | 757 | <&clkc CLKID_FCLK_DIV3>; |
| 758 | 758 | }; |
| 759 | 759 | |
| 760 | 760 | &pwm_ef { |
| 761 | 761 | clocks = <&xtal>, |
| 762 | − <>, /* unknown/untested, the datasheet calls it "vid_pll" */ | |
| 762 | + <0>, /* unknown/untested, the datasheet calls it "vid_pll" */ | |
| 763 | 763 | <&clkc CLKID_FCLK_DIV4>, |
| 764 | 764 | <&clkc CLKID_FCLK_DIV3>; |
| 765 | 765 | }; |
| @@ -811,7 +811,7 @@ · 810 unmodified lines | ||
| 811 | 811 | |
| 812 | 812 | &pwm_ab { |
| 813 | 813 | clocks = <&xtal>, |
| 814 | − <>, /* unknown/untested, the datasheet calls it "vid_pll" */ | |
| 814 | + <0>, /* unknown/untested, the datasheet calls it "vid_pll" */ | |
| 815 | 815 | <&clkc CLKID_FCLK_DIV4>, |
| 816 | 816 | <&clkc CLKID_FCLK_DIV3>; |
| 817 | 817 | }; |
| @@ -822,14 +822,14 @@ · 4 unmodified lines | ||
| 822 | 822 | |
| 823 | 823 | &pwm_cd { |
| 824 | 824 | clocks = <&xtal>, |
| 825 | − <>, /* unknown/untested, the datasheet calls it "vid_pll" */ | |
| 825 | + <0>, /* unknown/untested, the datasheet calls it "vid_pll" */ | |
| 826 | 826 | <&clkc CLKID_FCLK_DIV4>, |
| 827 | 827 | <&clkc CLKID_FCLK_DIV3>; |
| 828 | 828 | }; |
| 829 | 829 | |
| 830 | 830 | &pwm_ef { |
| 831 | 831 | clocks = <&xtal>, |
| 832 | − <>, /* unknown/untested, the datasheet calls it "vid_pll" */ | |
| 832 | + <0>, /* unknown/untested, the datasheet calls it "vid_pll" */ | |
| 833 | 833 | <&clkc CLKID_FCLK_DIV4>, |
| 834 | 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 | 90 | &display_dfr { |
| 81 | 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 | 53 | &display_dfr { |
| 44 | 54 | status = "okay"; |
| 45 | 55 | }; |
| @@ -88,3 +88,5 @@ · 87 unmodified lines | ||
| 88 | 88 | <0>, <0>, <400000000>, |
| 89 | 89 | <1039500000>; |
| 90 | 90 | }; |
| 91 | + | |
| 92 | +/delete-node/ &{noc_opp_table/opp-1000000000}; | |
| @@ -35,7 +35,6 @@ · 34 unmodified lines | ||
| 35 | 35 | <0x1 0x00000000 0 0xc0000000>; |
| 36 | 36 | }; |
| 37 | 37 | |
| 38 | − | |
| 39 | 38 | reg_usdhc2_vmmc: regulator-usdhc2-vmmc { |
| 40 | 39 | compatible = "regulator-fixed"; |
| 41 | 40 | regulator-name = "VSD_3V3"; |
| @@ -46,6 +45,16 @@ · 4 unmodified lines | ||
| 46 | 45 | startup-delay-us = <100>; |
| 47 | 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 | 60 | &A53_0 { |
| @@ -205,6 +214,7 @@ · 153 unmodified lines | ||
| 205 | 214 | pinctrl-2 = <&pinctrl_usdhc2_200mhz>, <&pinctrl_usdhc2_gpio>; |
| 206 | 215 | cd-gpios = <&gpio1 14 GPIO_ACTIVE_LOW>; |
| 207 | 216 | vmmc-supply = <®_usdhc2_vmmc>; |
| 217 | + vqmmc-supply = <®_usdhc2_vqmmc>; | |
| 208 | 218 | bus-width = <4>; |
| 209 | 219 | status = "okay"; |
| 210 | 220 | }; |
| @@ -1645,6 +1645,12 @@ · 1644 unmodified lines | ||
| 1645 | 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 | 1654 | opp-1000000000 { |
| 1649 | 1655 | opp-hz = /bits/ 64 <1000000000>; |
| 1650 | 1656 | }; |
| @@ -31,7 +31,7 @@ · 30 unmodified lines | ||
| 31 | 31 | }; |
| 32 | 32 | |
| 33 | 33 | vcc3v3_btreg: vcc3v3-btreg { |
| 34 | − compatible = "regulator-gpio"; | |
| 34 | + compatible = "regulator-fixed"; | |
| 35 | 35 | enable-active-high; |
| 36 | 36 | pinctrl-names = "default"; |
| 37 | 37 | pinctrl-0 = <&bt_enable_h>; |
| @@ -39,7 +39,6 @@ · 1 unmodified line | ||
| 39 | 39 | regulator-min-microvolt = <3300000>; |
| 40 | 40 | regulator-max-microvolt = <3300000>; |
| 41 | 41 | regulator-always-on; |
| 42 | − states = <3300000 0x0>; | |
| 43 | 42 | }; |
| 44 | 43 | |
| 45 | 44 | vcc3v3_rf_aux_mod: regulator-vcc3v3-rf-aux-mod { |
| @@ -26,5 +26,5 @@ · 25 unmodified lines | ||
| 26 | 26 | }; |
| 27 | 27 | |
| 28 | 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 | 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 | 43 | sdio_pwrseq: sdio-pwrseq { |
| 44 | 44 | compatible = "mmc-pwrseq-simple"; |
| 45 | 45 | clocks = <&rk808 1>; |
| 46 | − clock-names = "lpo"; | |
| 46 | + clock-names = "ext_clock"; | |
| 47 | 47 | pinctrl-names = "default"; |
| 48 | 48 | pinctrl-0 = <&wifi_enable_h>; |
| 49 | 49 | reset-gpios = <&gpio0 RK_PB2 GPIO_ACTIVE_LOW>; |
| @@ -775,7 +775,7 @@ · 774 unmodified lines | ||
| 775 | 775 | rockchip,default-sample-phase = <90>; |
| 776 | 776 | status = "okay"; |
| 777 | 777 | |
| 778 | − sdio-wifi@1 { | |
| 778 | + wifi@1 { | |
| 779 | 779 | compatible = "brcm,bcm4329-fmac"; |
| 780 | 780 | reg = <1>; |
| 781 | 781 | interrupt-parent = <&gpio2>; |
| @@ -619,6 +619,8 @@ · 618 unmodified lines | ||
| 619 | 619 | bus-width = <8>; |
| 620 | 620 | max-frequency = <200000000>; |
| 621 | 621 | non-removable; |
| 622 | + pinctrl-names = "default"; | |
| 623 | + pinctrl-0 = <&emmc_bus8 &emmc_clk &emmc_cmd &emmc_datastrobe>; | |
| 622 | 624 | status = "okay"; |
| 623 | 625 | }; |
| 624 | 626 | |
| @@ -610,7 +610,7 @@ · 609 unmodified lines | ||
| 610 | 610 | reg = <0x51>; |
| 611 | 611 | clock-output-names = "hym8563"; |
| 612 | 612 | interrupt-parent = <&gpio0>; |
| 613 | − interrupts = <RK_PB0 IRQ_TYPE_LEVEL_LOW>; | |
| 613 | + interrupts = <RK_PA0 IRQ_TYPE_LEVEL_LOW>; | |
| 614 | 614 | pinctrl-names = "default"; |
| 615 | 615 | pinctrl-0 = <&hym8563_int>; |
| 616 | 616 | wakeup-source; |
| @@ -222,6 +222,10 @@ · 221 unmodified lines | ||
| 222 | 222 | compatible = "realtek,rt5616"; |
| 223 | 223 | reg = <0x1b>; |
| 224 | 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 | 216 | &package_thermal { |
| 217 | + polling-delay = <1000>; | |
| 218 | + | |
| 217 | 219 | trips { |
| 218 | 220 | package_active1: trip-active1 { |
| 219 | 221 | temperature = <45000>; |
| @@ -11,20 +11,15 @@ · 10 unmodified lines | ||
| 11 | 11 | compatible = "operating-points-v2"; |
| 12 | 12 | opp-shared; |
| 13 | 13 | |
| 14 | − opp-1416000000 { | |
| 15 | − opp-hz = /bits/ 64 <1416000000>; | |
| 14 | + opp-1200000000 { | |
| 15 | + opp-hz = /bits/ 64 <1200000000>; | |
| 16 | 16 | opp-microvolt = <750000 750000 950000>; |
| 17 | 17 | clock-latency-ns = <40000>; |
| 18 | 18 | opp-suspend; |
| 19 | 19 | }; |
| 20 | − opp-1608000000 { | |
| 21 | − opp-hz = /bits/ 64 <1608000000>; | |
| 22 | − opp-microvolt = <887500 887500 950000>; | |
| 23 | − clock-latency-ns = <40000>; | |
| 24 | − }; | |
| 25 | − opp-1704000000 { | |
| 26 | − opp-hz = /bits/ 64 <1704000000>; | |
| 27 | − opp-microvolt = <937500 937500 950000>; | |
| 20 | + opp-1296000000 { | |
| 21 | + opp-hz = /bits/ 64 <1296000000>; | |
| 22 | + opp-microvolt = <775000 775000 950000>; | |
| 28 | 23 | clock-latency-ns = <40000>; |
| 29 | 24 | }; |
| 30 | 25 | }; |
| @@ -33,9 +28,14 @@ · 2 unmodified lines | ||
| 33 | 28 | compatible = "operating-points-v2"; |
| 34 | 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 | 36 | opp-1416000000 { |
| 37 | 37 | opp-hz = /bits/ 64 <1416000000>; |
| 38 | − opp-microvolt = <750000 750000 950000>; | |
| 38 | + opp-microvolt = <762500 762500 950000>; | |
| 39 | 39 | clock-latency-ns = <40000>; |
| 40 | 40 | }; |
| 41 | 41 | opp-1608000000 { |
| @@ -43,25 +43,20 @@ · 1 unmodified line | ||
| 43 | 43 | opp-microvolt = <787500 787500 950000>; |
| 44 | 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 | 48 | cluster2_opp_table: opp-table-cluster2 { |
| 59 | 49 | compatible = "operating-points-v2"; |
| 60 | 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 | 57 | opp-1416000000 { |
| 63 | 58 | opp-hz = /bits/ 64 <1416000000>; |
| 64 | − opp-microvolt = <750000 750000 950000>; | |
| 59 | + opp-microvolt = <762500 762500 950000>; | |
| 65 | 60 | clock-latency-ns = <40000>; |
| 66 | 61 | }; |
| 67 | 62 | opp-1608000000 { |
| @@ -69,16 +64,6 @@ · 1 unmodified line | ||
| 69 | 64 | opp-microvolt = <787500 787500 950000>; |
| 70 | 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 | 69 | gpu_opp_table: opp-table { |
| @@ -104,10 +89,6 @@ · 19 unmodified lines | ||
| 104 | 89 | opp-hz = /bits/ 64 <700000000>; |
| 105 | 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 | 81 | #define ARM_CPU_PART_CORTEX_A78AE 0xD42 |
| 82 | 82 | #define ARM_CPU_PART_CORTEX_X1 0xD44 |
| 83 | 83 | #define ARM_CPU_PART_CORTEX_A510 0xD46 |
| 84 | +#define ARM_CPU_PART_CORTEX_X1C 0xD4C | |
| 84 | 85 | #define ARM_CPU_PART_CORTEX_A520 0xD80 |
| 85 | 86 | #define ARM_CPU_PART_CORTEX_A710 0xD47 |
| 86 | 87 | #define ARM_CPU_PART_CORTEX_A715 0xD4D |
| @@ -168,6 +169,7 @@ · 81 unmodified lines | ||
| 168 | 169 | #define MIDR_CORTEX_A78AE MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A78AE) |
| 169 | 170 | #define MIDR_CORTEX_X1 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_X1) |
| 170 | 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 | 173 | #define MIDR_CORTEX_A520 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A520) |
| 172 | 174 | #define MIDR_CORTEX_A710 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A710) |
| 173 | 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 | 707 | #endif |
| 708 | 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 | 710 | u32 aarch64_insn_gen_mrs(enum aarch64_insn_register result, |
| 710 | 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 | 98 | enum mitigation_state arm64_get_spectre_bhb_state(void); |
| 99 | 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 | 103 | void spectre_bhb_enable_mitigation(const struct arm64_cpu_capabilities *__unused); |
| 101 | 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 | 891 | MIDR_ALL_VERSIONS(MIDR_CORTEX_A78AE), |
| 892 | 892 | MIDR_ALL_VERSIONS(MIDR_CORTEX_A78C), |
| 893 | 893 | MIDR_ALL_VERSIONS(MIDR_CORTEX_X1), |
| 894 | + MIDR_ALL_VERSIONS(MIDR_CORTEX_X1C), | |
| 894 | 895 | MIDR_ALL_VERSIONS(MIDR_CORTEX_A710), |
| 895 | 896 | MIDR_ALL_VERSIONS(MIDR_CORTEX_X2), |
| 896 | 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 | 1000 | return true; |
| 1000 | 1001 | } |
| 1001 | 1002 | |
| 1003 | +u8 get_spectre_bhb_loop_value(void) | |
| 1004 | +{ | |
| 1005 | + return max_bhb_k; | |
| 1006 | +} | |
| 1007 | + | |
| 1002 | 1008 | static void this_cpu_set_vectors(enum arm64_bp_harden_el1_vectors slot) |
| 1003 | 1009 | { |
| 1004 | 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 | 1022 | isb(); |
| 1017 | 1023 | } |
| 1018 | 1024 | |
| 1019 | −static bool __read_mostly __nospectre_bhb; | |
| 1025 | +bool __read_mostly __nospectre_bhb; | |
| 1020 | 1026 | static int __init parse_spectre_bhb_param(char *str) |
| 1021 | 1027 | { |
| 1022 | 1028 | __nospectre_bhb = true; |
| @@ -1094,6 +1100,11 @@ void spectre_bhb_enable_mitigation(const struct arm64_cpu_capabilities *entry) · 71 unmodified lines | ||
| 1094 | 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 | 1108 | /* Patched to NOP when enabled */ |
| 1098 | 1109 | void noinstr spectre_bhb_patch_loop_mitigation_enable(struct alt_instr *alt, |
| 1099 | 1110 | __le32 *origptr, |
| @@ -5,6 +5,7 @@ · 4 unmodified lines | ||
| 5 | 5 | * |
| 6 | 6 | * Copyright (C) 2014-2016 Zi Shen Lim <zlim.lnx@gmail.com> |
| 7 | 7 | */ |
| 8 | +#include <linux/bitfield.h> | |
| 8 | 9 | #include <linux/bitops.h> |
| 9 | 10 | #include <linux/bug.h> |
| 10 | 11 | #include <linux/printk.h> |
| @@ -1500,43 +1501,41 @@ u32 aarch64_insn_gen_extr(enum aarch64_insn_variant variant, · 1489 unmodified lines | ||
| 1500 | 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 | 1506 | switch (type) { |
| 1509 | 1507 | case AARCH64_INSN_MB_SY: |
| 1510 | − opt = 0xf; | |
| 1511 | − break; | |
| 1508 | + return 0xf; | |
| 1512 | 1509 | case AARCH64_INSN_MB_ST: |
| 1513 | − opt = 0xe; | |
| 1514 | − break; | |
| 1510 | + return 0xe; | |
| 1515 | 1511 | case AARCH64_INSN_MB_LD: |
| 1516 | − opt = 0xd; | |
| 1517 | − break; | |
| 1512 | + return 0xd; | |
| 1518 | 1513 | case AARCH64_INSN_MB_ISH: |
| 1519 | − opt = 0xb; | |
| 1520 | − break; | |
| 1514 | + return 0xb; | |
| 1521 | 1515 | case AARCH64_INSN_MB_ISHST: |
| 1522 | − opt = 0xa; | |
| 1523 | − break; | |
| 1516 | + return 0xa; | |
| 1524 | 1517 | case AARCH64_INSN_MB_ISHLD: |
| 1525 | − opt = 0x9; | |
| 1526 | − break; | |
| 1518 | + return 0x9; | |
| 1527 | 1519 | case AARCH64_INSN_MB_NSH: |
| 1528 | − opt = 0x7; | |
| 1529 | − break; | |
| 1520 | + return 0x7; | |
| 1530 | 1521 | case AARCH64_INSN_MB_NSHST: |
| 1531 | − opt = 0x6; | |
| 1532 | − break; | |
| 1522 | + return 0x6; | |
| 1533 | 1523 | case AARCH64_INSN_MB_NSHLD: |
| 1534 | − opt = 0x5; | |
| 1535 | − break; | |
| 1524 | + return 0x5; | |
| 1536 | 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 | 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 | 1540 | insn = aarch64_insn_get_dmb_value(); |
| 1542 | 1541 | insn &= ~GENMASK(11, 8); |
| @@ -1545,6 +1544,21 @@ u32 aarch64_insn_gen_dmb(enum aarch64_insn_mb_type type) · 2 unmodified lines | ||
| 1545 | 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 | 1562 | u32 aarch64_insn_gen_mrs(enum aarch64_insn_register result, |
| 1549 | 1563 | enum aarch64_insn_system_register sysreg) |
| 1550 | 1564 | { |
| @@ -7,6 +7,7 @@ · 6 unmodified lines | ||
| 7 | 7 | |
| 8 | 8 | #define pr_fmt(fmt) "bpf_jit: " fmt |
| 9 | 9 | |
| 10 | +#include <linux/arm-smccc.h> | |
| 10 | 11 | #include <linux/bitfield.h> |
| 11 | 12 | #include <linux/bpf.h> |
| 12 | 13 | #include <linux/filter.h> |
| @@ -17,6 +18,7 @@ · 4 unmodified lines | ||
| 17 | 18 | #include <asm/asm-extable.h> |
| 18 | 19 | #include <asm/byteorder.h> |
| 19 | 20 | #include <asm/cacheflush.h> |
| 21 | +#include <asm/cpufeature.h> | |
| 20 | 22 | #include <asm/debug-monitors.h> |
| 21 | 23 | #include <asm/insn.h> |
| 22 | 24 | #include <asm/text-patching.h> |
| @@ -939,7 +941,51 @@ static void build_plt(struct jit_ctx *ctx) · 916 unmodified lines | ||
| 939 | 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 | 990 | const u8 r0 = bpf2a64[BPF_REG_0]; |
| 945 | 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 | 999 | emit(A64_POP(A64_ZR, ptr, A64_SP), ctx); |
| 954 | 1000 | |
| 1001 | + if (was_classic) | |
| 1002 | + build_bhb_mitigation(ctx); | |
| 1003 | + | |
| 955 | 1004 | /* Restore FP/LR registers */ |
| 956 | 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 | 1008 | emit(A64_MOV(1, A64_R(0), r0), ctx); |
| 960 | 1009 | |
| 961 | 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 | 1949 | ctx.epilogue_offset = ctx.idx; |
| 1901 | − build_epilogue(&ctx); | |
| 1950 | + build_epilogue(&ctx, was_classic); | |
| 1902 | 1951 | build_plt(&ctx); |
| 1903 | 1952 | |
| 1904 | 1953 | extable_align = __alignof__(struct exception_table_entry); |
| @@ -1961,7 +2010,7 @@ skip_init_ctx: · 56 unmodified lines | ||
| 1961 | 2010 | goto out_free_hdr; |
| 1962 | 2011 | } |
| 1963 | 2012 | |
| 1964 | − build_epilogue(&ctx); | |
| 2013 | + build_epilogue(&ctx, was_classic); | |
| 1965 | 2014 | build_plt(&ctx); |
| 1966 | 2015 | |
| 1967 | 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 | 56 | /* Query offset/name of register from its name/offset */ |
| 57 | 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 | 61 | * regs_get_register() - get register value from its offset |
| @@ -15,7 +15,6 @@ typedef u32 uprobe_opcode_t; · 14 unmodified lines | ||
| 15 | 15 | #define UPROBE_XOLBP_INSN __emit_break(BRK_UPROBE_XOLBP) |
| 16 | 16 | |
| 17 | 17 | struct arch_uprobe { |
| 18 | − unsigned long resume_era; | |
| 19 | 18 | u32 insn[2]; |
| 20 | 19 | u32 ixol[2]; |
| 21 | 20 | bool simulate; |
| @@ -16,6 +16,7 @@ · 15 unmodified lines | ||
| 16 | 16 | #include <asm/stackframe.h> |
| 17 | 17 | #include <asm/thread_info.h> |
| 18 | 18 | |
| 19 | + .section .cpuidle.text, "ax" | |
| 19 | 20 | .align 5 |
| 20 | 21 | SYM_FUNC_START(__arch_cpu_idle) |
| 21 | 22 | /* start of idle interrupt region */ |
| @@ -31,14 +32,16 @@ SYM_FUNC_START(__arch_cpu_idle) · 9 unmodified lines | ||
| 31 | 32 | */ |
| 32 | 33 | idle 0 |
| 33 | 34 | /* end of idle interrupt region */ |
| 34 | −1: jr ra | |
| 35 | +idle_exit: | |
| 36 | + jr ra | |
| 35 | 37 | SYM_FUNC_END(__arch_cpu_idle) |
| 38 | + .previous | |
| 36 | 39 | |
| 37 | 40 | SYM_CODE_START(handle_vint) |
| 38 | 41 | UNWIND_HINT_UNDEFINED |
| 39 | 42 | BACKUP_T0T1 |
| 40 | 43 | SAVE_ALL |
| 41 | − la_abs t1, 1b | |
| 44 | + la_abs t1, idle_exit | |
| 42 | 45 | LONG_L t0, sp, PT_ERA |
| 43 | 46 | /* 3 instructions idle interrupt region */ |
| 44 | 47 | ori t0, t0, 0b1100 |
| @@ -18,11 +18,28 @@ static unsigned int euen_mask = CSR_EUEN_FPEN; · 17 unmodified lines | ||
| 18 | 18 | static DEFINE_PER_CPU(bool, in_kernel_fpu); |
| 19 | 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 | 37 | void kernel_fpu_begin(void) |
| 22 | 38 | { |
| 23 | 39 | unsigned int *euen_curr; |
| 24 | 40 | |
| 25 | − preempt_disable(); | |
| 41 | + if (!irqs_disabled()) | |
| 42 | + fpregs_lock(); | |
| 26 | 43 | |
| 27 | 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 | 91 | this_cpu_write(in_kernel_fpu, false); |
| 75 | 92 | |
| 76 | − preempt_enable(); | |
| 93 | + if (!irqs_disabled()) | |
| 94 | + fpregs_unlock(); | |
| 77 | 95 | } |
| 78 | 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 | 111 | return lpj; |
| 112 | 112 | } |
| 113 | 113 | |
| 114 | −static long init_offset __nosavedata; | |
| 114 | +static long init_offset; | |
| 115 | 115 | |
| 116 | 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 | 42 | utask->autask.saved_trap_nr = current->thread.trap_nr; |
| 43 | 43 | current->thread.trap_nr = UPROBE_TRAP_NR; |
| 44 | 44 | instruction_pointer_set(regs, utask->xol_vaddr); |
| 45 | − user_enable_single_step(current); | |
| 46 | 45 | |
| 47 | 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 | 53 | WARN_ON_ONCE(current->thread.trap_nr != UPROBE_TRAP_NR); |
| 55 | 54 | current->thread.trap_nr = utask->autask.saved_trap_nr; |
| 56 | − | |
| 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); | |
| 55 | + instruction_pointer_set(regs, utask->vaddr + LOONGARCH_INSN_SIZE); | |
| 63 | 56 | |
| 64 | 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 | 64 | current->thread.trap_nr = utask->autask.saved_trap_nr; |
| 72 | 65 | instruction_pointer_set(regs, utask->vaddr); |
| 73 | − user_disable_single_step(current); | |
| 74 | 66 | } |
| 75 | 67 | |
| 76 | 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 | 83 | insn.word = auprobe->insn[0]; |
| 92 | 84 | arch_simulate_insn(insn, regs); |
| 93 | − auprobe->resume_era = regs->csr_era; | |
| 94 | 85 | |
| 95 | 86 | return true; |
| 96 | 87 | } |
| @@ -2,6 +2,7 @@ · 1 unmodified line | ||
| 2 | 2 | #include <asm/fpu.h> |
| 3 | 3 | #include <asm/loongson.h> |
| 4 | 4 | #include <asm/sections.h> |
| 5 | +#include <asm/time.h> | |
| 5 | 6 | #include <asm/tlbflush.h> |
| 6 | 7 | #include <linux/suspend.h> |
| 7 | 8 | |
| @@ -14,6 +15,7 @@ struct pt_regs saved_regs; · 6 unmodified lines | ||
| 14 | 15 | |
| 15 | 16 | void save_processor_state(void) |
| 16 | 17 | { |
| 18 | + save_counter(); | |
| 17 | 19 | saved_crmd = csr_read32(LOONGARCH_CSR_CRMD); |
| 18 | 20 | saved_prmd = csr_read32(LOONGARCH_CSR_PRMD); |
| 19 | 21 | saved_euen = csr_read32(LOONGARCH_CSR_EUEN); |
| @@ -26,6 +28,7 @@ void save_processor_state(void) · 6 unmodified lines | ||
| 26 | 28 | |
| 27 | 29 | void restore_processor_state(void) |
| 28 | 30 | { |
| 31 | + sync_counter(); | |
| 29 | 32 | csr_write32(saved_crmd, LOONGARCH_CSR_CRMD); |
| 30 | 33 | csr_write32(saved_prmd, LOONGARCH_CSR_PRMD); |
| 31 | 34 | csr_write32(saved_euen, LOONGARCH_CSR_EUEN); |
| @@ -341,7 +341,7 @@ · 340 unmodified lines | ||
| 341 | 341 | 1024 1024 1024 1024>; |
| 342 | 342 | snps,priority = <0 1 2 3 4 5 6 7>; |
| 343 | 343 | snps,dma-masters = <2>; |
| 344 | − snps,data-width = <4>; | |
| 344 | + snps,data-width = <2>; | |
| 345 | 345 | status = "disabled"; |
| 346 | 346 | }; |
| 347 | 347 | |
| @@ -154,5 +154,6 @@ MRPROPER_FILES += $(HOST_DIR)/include/generated · 153 unmodified lines | ||
| 154 | 154 | archclean: |
| 155 | 155 | @find . \( -name '*.bb' -o -name '*.bbg' -o -name '*.da' \ |
| 156 | 156 | -o -name '*.gcov' \) -type f -print | xargs rm -f |
| 157 | + $(Q)$(MAKE) -f $(srctree)/Makefile ARCH=$(HEADER_ARCH) clean | |
| 157 | 158 | |
| 158 | 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 | 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 | 646 | static void set_pte_enc(pte_t *kpte, int level, void *va) |
| 551 | 647 | { |
| 552 | 648 | struct pte_enc_desc d = { |
| @@ -593,7 +689,8 @@ static void unshare_all_memory(void) · 40 unmodified lines | ||
| 593 | 689 | data = per_cpu(runtime_data, cpu); |
| 594 | 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 | 694 | skipped_addr = true; |
| 598 | 695 | break; |
| 599 | 696 | } |
| @@ -643,11 +740,70 @@ void snp_kexec_begin(void) · 43 unmodified lines | ||
| 643 | 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 | 802 | void snp_kexec_finish(void) |
| 647 | 803 | { |
| 648 | 804 | struct sev_es_runtime_data *data; |
| 805 | + unsigned long size, addr; | |
| 649 | 806 | unsigned int level, cpu; |
| 650 | − unsigned long size; | |
| 651 | 807 | struct ghcb *ghcb; |
| 652 | 808 | pte_t *pte; |
| 653 | 809 | |
| @@ -657,6 +813,8 @@ void snp_kexec_finish(void) · 3 unmodified lines | ||
| 657 | 813 | if (!IS_ENABLED(CONFIG_KEXEC_CORE)) |
| 658 | 814 | return; |
| 659 | 815 | |
| 816 | + shutdown_all_aps(); | |
| 817 | + | |
| 660 | 818 | unshare_all_memory(); |
| 661 | 819 | |
| 662 | 820 | /* |
| @@ -673,54 +831,11 @@ void snp_kexec_finish(void) · 10 unmodified lines | ||
| 673 | 831 | ghcb = &data->ghcb_page; |
| 674 | 832 | pte = lookup_address((unsigned long)ghcb, &level); |
| 675 | 833 | size = page_level_size(level); |
| 676 | − set_pte_enc(pte, level, (void *)ghcb); | |
| 677 | − snp_set_memory_private((unsigned long)ghcb, (size / PAGE_SIZE)); | |
| 678 | − } | |
| 679 | −} | |
| 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); | |
| 834 | + /* Handle the case of a huge page containing the GHCB page */ | |
| 835 | + addr = (unsigned long)ghcb & page_level_mask(level); | |
| 836 | + set_pte_enc(pte, level, (void *)addr); | |
| 837 | + snp_set_memory_private(addr, (size / PAGE_SIZE)); | |
| 721 | 838 | } |
| 722 | − | |
| 723 | − return ret; | |
| 724 | 839 | } |
| 725 | 840 | |
| 726 | 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 | 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 | 872 | static int wakeup_cpu_via_vmgexit(u32 apic_id, unsigned long start_ip) |
| 769 | 873 | { |
| 770 | 874 | struct sev_es_save_area *cur_vmsa, *vmsa; |
| 771 | − struct ghcb_state state; | |
| 772 | 875 | struct svsm_ca *caa; |
| 773 | − unsigned long flags; | |
| 774 | − struct ghcb *ghcb; | |
| 775 | 876 | u8 sipi_vector; |
| 776 | 877 | int cpu, ret; |
| 777 | 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 | 988 | /* Issue VMGEXIT AP Creation NAE event */ |
| 888 | − local_irq_save(flags); | |
| 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 */ | |
| 989 | + ret = vmgexit_ap_control(SVM_VMGEXIT_AP_CREATE, vmsa, apic_id); | |
| 915 | 990 | if (ret) { |
| 916 | 991 | snp_cleanup_vmsa(vmsa, apic_id); |
| 917 | 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 | 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 | 2472 | struct perf_event *event; |
| 2472 | 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 | 2479 | * It needs to call intel_pmu_save_and_restart_reload() to |
| 2479 | 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 | 2483 | event = cpuc->events[bit]; |
| 2483 | 2484 | if (event->hw.flags & PERF_X86_EVENT_AUTO_RELOAD) |
| 2484 | 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 | 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 | 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 | 2628 | (hybrid(cpuc->pmu, fixed_cntr_mask64) << INTEL_PMC_IDX_FIXED); |
| 2628 | 2629 | |
| 2629 | 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 | 2632 | return; |
| 2632 | 2633 | } |
| 2633 | 2634 | |
| @@ -75,7 +75,7 @@ · 74 unmodified lines | ||
| 75 | 75 | #define X86_FEATURE_CENTAUR_MCR ( 3*32+ 3) /* "centaur_mcr" Centaur MCRs (= MTRRs) */ |
| 76 | 76 | #define X86_FEATURE_K8 ( 3*32+ 4) /* Opteron, Athlon64 */ |
| 77 | 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 | 79 | /* Free ( 3*32+ 7) */ |
| 80 | 80 | #define X86_FEATURE_CONSTANT_TSC ( 3*32+ 8) /* "constant_tsc" TSC ticks at a constant rate */ |
| 81 | 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 | 116 | #define GHCB_MSR_VMPL_REQ 0x016 |
| 117 | 117 | #define GHCB_MSR_VMPL_REQ_LEVEL(v) \ |
| 118 | 118 | /* GHCBData[39:32] */ \ |
| 119 | − (((u64)(v) & GENMASK_ULL(7, 0) << 32) | \ | |
| 119 | + ((((u64)(v) & GENMASK_ULL(7, 0)) << 32) | \ | |
| 120 | 120 | /* GHCBDdata[11:0] */ \ |
| 121 | 121 | GHCB_MSR_VMPL_REQ) |
| 122 | 122 | |
| @@ -111,7 +111,9 @@ static bool cfi_paranoid __ro_after_init; · 110 unmodified lines | ||
| 111 | 111 | |
| 112 | 112 | #ifdef CONFIG_MITIGATION_ITS |
| 113 | 113 | |
| 114 | +#ifdef CONFIG_MODULES | |
| 114 | 115 | static struct module *its_mod; |
| 116 | +#endif | |
| 115 | 117 | static void *its_page; |
| 116 | 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 | 151 | return thunk + offset; |
| 150 | 152 | } |
| 151 | 153 | |
| 154 | +#ifdef CONFIG_MODULES | |
| 152 | 155 | void its_init_mod(struct module *mod) |
| 153 | 156 | { |
| 154 | 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 | 191 | kfree(mod->its_page_array); |
| 189 | 192 | } |
| 193 | +#endif /* CONFIG_MODULES */ | |
| 190 | 194 | |
| 191 | 195 | static void *its_alloc(void) |
| 192 | 196 | { |
| @@ -195,6 +199,7 @@ static void *its_alloc(void) · 2 unmodified lines | ||
| 195 | 199 | if (!page) |
| 196 | 200 | return NULL; |
| 197 | 201 | |
| 202 | +#ifdef CONFIG_MODULES | |
| 198 | 203 | if (its_mod) { |
| 199 | 204 | void *tmp = krealloc(its_mod->its_page_array, |
| 200 | 205 | (its_mod->its_num_pages+1) * sizeof(void *), |
| @@ -207,6 +212,7 @@ static void *its_alloc(void) · 6 unmodified lines | ||
| 207 | 212 | |
| 208 | 213 | execmem_make_temp_rw(page, PAGE_SIZE); |
| 209 | 214 | } |
| 215 | +#endif /* CONFIG_MODULES */ | |
| 210 | 216 | |
| 211 | 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 | 474 | case 0x60 ... 0x7f: |
| 475 | 475 | setup_force_cpu_cap(X86_FEATURE_ZEN5); |
| 476 | 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 | 482 | default: |
| 478 | 483 | goto warn; |
| 479 | 484 | } |
| @@ -566,7 +566,7 @@ static void __init lowmem_pfn_init(void) · 565 unmodified lines | ||
| 566 | 566 | "only %luMB highmem pages available, ignoring highmem size of %luMB!\n" |
| 567 | 567 | |
| 568 | 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 | 571 | * We have more RAM than fits into lowmem - we try to put it into |
| 572 | 572 | * highmem, also taking the highmem=x boot parameter into account: |
| @@ -9,6 +9,7 @@ · 8 unmodified lines | ||
| 9 | 9 | * not aware of PI. |
| 10 | 10 | */ |
| 11 | 11 | #include <linux/blk-integrity.h> |
| 12 | +#include <linux/t10-pi.h> | |
| 12 | 13 | #include <linux/workqueue.h> |
| 13 | 14 | #include "blk.h" |
| 14 | 15 | |
| @@ -43,6 +44,29 @@ static void bio_integrity_verify_fn(struct work_struct *work) · 28 unmodified lines | ||
| 43 | 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 | 71 | * __bio_integrity_endio - Integrity I/O completion function |
| 48 | 72 | * @bio: Protected bio |
| @@ -54,12 +78,12 @@ static void bio_integrity_verify_fn(struct work_struct *work) · 5 unmodified lines | ||
| 54 | 78 | */ |
| 55 | 79 | bool __bio_integrity_endio(struct bio *bio) |
| 56 | 80 | { |
| 57 | − struct blk_integrity *bi = blk_get_integrity(bio->bi_bdev->bd_disk); | |
| 58 | 81 | struct bio_integrity_payload *bip = bio_integrity(bio); |
| 59 | 82 | struct bio_integrity_data *bid = |
| 60 | 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 | 87 | INIT_WORK(&bid->work, bio_integrity_verify_fn); |
| 64 | 88 | queue_work(kintegrityd_wq, &bid->work); |
| 65 | 89 | return false; |
| @@ -84,6 +108,7 @@ bool bio_integrity_prep(struct bio *bio) · 18 unmodified lines | ||
| 84 | 108 | { |
| 85 | 109 | struct blk_integrity *bi = blk_get_integrity(bio->bi_bdev->bd_disk); |
| 86 | 110 | struct bio_integrity_data *bid; |
| 111 | + bool set_flags = true; | |
| 87 | 112 | gfp_t gfp = GFP_NOIO; |
| 88 | 113 | unsigned int len; |
| 89 | 114 | void *buf; |
| @@ -100,19 +125,24 @@ bool bio_integrity_prep(struct bio *bio) · 10 unmodified lines | ||
| 100 | 125 | |
| 101 | 126 | switch (bio_op(bio)) { |
| 102 | 127 | case REQ_OP_READ: |
| 103 | − if (bi->flags & BLK_INTEGRITY_NOVERIFY) | |
| 104 | − return true; | |
| 128 | + if (bi->flags & BLK_INTEGRITY_NOVERIFY) { | |
| 129 | + if (bi_offload_capable(bi)) | |
| 130 | + return true; | |
| 131 | + set_flags = false; | |
| 132 | + } | |
| 105 | 133 | break; |
| 106 | 134 | case REQ_OP_WRITE: |
| 107 | − if (bi->flags & BLK_INTEGRITY_NOGENERATE) | |
| 108 | − return true; | |
| 109 | − | |
| 110 | 135 | /* |
| 111 | 136 | * Zero the memory allocated to not leak uninitialized kernel |
| 112 | 137 | * memory to disk for non-integrity metadata where nothing else |
| 113 | 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 | 146 | gfp |= __GFP_ZERO; |
| 117 | 147 | break; |
| 118 | 148 | default: |
| @@ -137,19 +167,21 @@ bool bio_integrity_prep(struct bio *bio) · 18 unmodified lines | ||
| 137 | 167 | bid->bip.bip_flags |= BIP_BLOCK_INTEGRITY; |
| 138 | 168 | bip_set_seed(&bid->bip, bio->bi_iter.bi_sector); |
| 139 | 169 | |
| 140 | − if (bi->csum_type == BLK_INTEGRITY_CSUM_IP) | |
| 141 | − bid->bip.bip_flags |= BIP_IP_CHECKSUM; | |
| 142 | − if (bi->csum_type) | |
| 143 | − bid->bip.bip_flags |= BIP_CHECK_GUARD; | |
| 144 | − if (bi->flags & BLK_INTEGRITY_REF_TAG) | |
| 145 | − bid->bip.bip_flags |= BIP_CHECK_REFTAG; | |
| 170 | + if (set_flags) { | |
| 171 | + if (bi->csum_type == BLK_INTEGRITY_CSUM_IP) | |
| 172 | + bid->bip.bip_flags |= BIP_IP_CHECKSUM; | |
| 173 | + if (bi->csum_type) | |
| 174 | + bid->bip.bip_flags |= BIP_CHECK_GUARD; | |
| 175 | + if (bi->flags & BLK_INTEGRITY_REF_TAG) | |
| 176 | + bid->bip.bip_flags |= BIP_CHECK_REFTAG; | |
| 177 | + } | |
| 146 | 178 | |
| 147 | 179 | if (bio_integrity_add_page(bio, virt_to_page(buf), len, |
| 148 | 180 | offset_in_page(buf)) < len) |
| 149 | 181 | goto err_end_io; |
| 150 | 182 | |
| 151 | 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 | 185 | blk_integrity_generate(bio); |
| 154 | 186 | else |
| 155 | 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 | 612 | struct bio *bio; |
| 613 | 613 | |
| 614 | − if (nr_vecs > UIO_MAXIOV) | |
| 614 | + if (nr_vecs > BIO_MAX_INLINE_VECS) | |
| 615 | 615 | return NULL; |
| 616 | 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 | 455 | if (ret < 0) |
| 456 | 456 | return ret; |
| 457 | 457 | |
| 458 | − buf[size] = '\0'; | |
| 458 | + buf[ret] = '\0'; | |
| 459 | 459 | ret = sscanf(buf, "%u %u %u %u", &band, &grace_period, &process_grace_period, |
| 460 | 460 | &process_quantum); |
| 461 | 461 | if (ret != 4) |
| @@ -231,16 +231,18 @@ static int acpi_pptt_leaf_node(struct acpi_table_header *table_hdr, · 230 unmodified lines | ||
| 231 | 231 | sizeof(struct acpi_table_pptt)); |
| 232 | 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 | 236 | cpu_node = (struct acpi_pptt_processor *)entry; |
| 237 | + | |
| 236 | 238 | if (entry->type == ACPI_PPTT_TYPE_PROCESSOR && |
| 237 | 239 | cpu_node->parent == node_entry) |
| 238 | 240 | return 0; |
| 239 | 241 | if (entry->length == 0) |
| 240 | 242 | return 0; |
| 243 | + | |
| 241 | 244 | entry = ACPI_ADD_PTR(struct acpi_subtable_header, entry, |
| 242 | 245 | entry->length); |
| 243 | − | |
| 244 | 246 | } |
| 245 | 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 | 275 | proc_sz = sizeof(struct acpi_pptt_processor); |
| 274 | 276 | |
| 275 | 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 | 279 | cpu_node = (struct acpi_pptt_processor *)entry; |
| 278 | 280 | |
| 279 | 281 | if (entry->length == 0) { |
| 280 | 282 | pr_warn("Invalid zero length subtable\n"); |
| 281 | 283 | break; |
| 282 | 284 | } |
| 285 | + /* entry->length may not equal proc_sz, revalidate the processor structure length */ | |
| 283 | 286 | if (entry->type == ACPI_PPTT_TYPE_PROCESSOR && |
| 284 | 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 | 290 | acpi_pptt_leaf_node(table_hdr, cpu_node)) { |
| 286 | 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 | 1708 | * that ublk_dispatch_req() is always called |
| 1709 | 1709 | */ |
| 1710 | 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 | 1712 | return; |
| 1713 | 1713 | |
| 1714 | 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 | 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 | 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 | 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 | 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 | 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 | 240 | tpm_buf_read(buf, offset, sizeof(value), &value); |
| 241 | 241 | |
| @@ -40,11 +40,6 @@ · 39 unmodified lines | ||
| 40 | 40 | * |
| 41 | 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 | 43 | * tpm2_end_auth_session() kills the session and frees the resources. |
| 49 | 44 | * Under normal operation this function is done by |
| 50 | 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 | |
| 967 | − * @chip: the TPM chip structure to create the session with | |
| 961 | + * tpm2_start_auth_session() - Create an a HMAC authentication session | |
| 962 | + * @chip: A TPM chip | |
| 968 | 963 | * |
| 969 | − * This function loads the NULL seed from its saved context and starts | |
| 970 | − * an authentication session on the null seed, fills in the | |
| 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. | |
| 964 | + * Loads the ephemeral key (null seed), and starts an HMAC authenticated | |
| 965 | + * session. The null seed is flushed before the return. | |
| 974 | 966 | * |
| 975 | − * Return: zero on success or actual error encountered. | |
| 967 | + * Returns zero on success, or a POSIX error code. | |
| 976 | 968 | */ |
| 977 | 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 | 1016 | /* hash algorithm for session */ |
| 1025 | 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 | 1020 | tpm2_flush_context(chip, null_key); |
| 1029 | 1021 | |
| 1030 | 1022 | if (rc == TPM2_RC_SUCCESS) |
| @@ -54,7 +54,7 @@ enum tis_int_flags { · 53 unmodified lines | ||
| 54 | 54 | enum tis_defaults { |
| 55 | 55 | TIS_MEM_LEN = 0x5000, |
| 56 | 56 | TIS_SHORT_TIMEOUT = 750, /* ms */ |
| 57 | − TIS_LONG_TIMEOUT = 2000, /* 2 sec */ | |
| 57 | + TIS_LONG_TIMEOUT = 4000, /* 4 secs */ | |
| 58 | 58 | TIS_TIMEOUT_MIN_ATML = 14700, /* usecs */ |
| 59 | 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 | 320 | count++; |
| 321 | 321 | |
| 322 | 322 | dma_resv_list_set(fobj, i, fence, usage); |
| 323 | − /* pointer update must be visible before we extend the num_fences */ | |
| 324 | − smp_store_mb(fobj->num_fences, count); | |
| 323 | + /* fence update must be visible before we extend the num_fences */ | |
| 324 | + smp_wmb(); | |
| 325 | + fobj->num_fences = count; | |
| 325 | 326 | } |
| 326 | 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 | 342 | struct pt_dma_chan *chan; |
| 343 | 343 | unsigned long flags; |
| 344 | 344 | |
| 345 | + if (!desc) | |
| 346 | + return; | |
| 347 | + | |
| 345 | 348 | dma_chan = desc->vd.tx.chan; |
| 346 | 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 | 358 | desc->status = DMA_ERROR; |
| 356 | 359 | |
| 357 | 360 | spin_lock_irqsave(&chan->vc.lock, flags); |
| 358 | − if (desc) { | |
| 359 | − if (desc->status != DMA_COMPLETE) { | |
| 360 | − if (desc->status != DMA_ERROR) | |
| 361 | − desc->status = DMA_COMPLETE; | |
| 361 | + if (desc->status != DMA_COMPLETE) { | |
| 362 | + if (desc->status != DMA_ERROR) | |
| 363 | + desc->status = DMA_COMPLETE; | |
| 362 | 364 | |
| 363 | − dma_cookie_complete(tx_desc); | |
| 364 | − dma_descriptor_unmap(tx_desc); | |
| 365 | − } else { | |
| 366 | − tx_desc = NULL; | |
| 367 | − } | |
| 365 | + dma_cookie_complete(tx_desc); | |
| 366 | + dma_descriptor_unmap(tx_desc); | |
| 367 | + } else { | |
| 368 | + tx_desc = NULL; | |
| 368 | 369 | } |
| 369 | 370 | spin_unlock_irqrestore(&chan->vc.lock, flags); |
| 370 | 371 | |
| @@ -841,9 +841,9 @@ static int dmatest_func(void *data) · 840 unmodified lines | ||
| 841 | 841 | } else { |
| 842 | 842 | dma_async_issue_pending(chan); |
| 843 | 843 | |
| 844 | − wait_event_timeout(thread->done_wait, | |
| 845 | − done->done, | |
| 846 | − msecs_to_jiffies(params->timeout)); | |
| 844 | + wait_event_freezable_timeout(thread->done_wait, | |
| 845 | + done->done, | |
| 846 | + msecs_to_jiffies(params->timeout)); | |
| 847 | 847 | |
| 848 | 848 | status = dma_async_is_tx_complete(chan, cookie, NULL, |
| 849 | 849 | NULL); |
| @@ -57,7 +57,7 @@ static irqreturn_t fsl_edma3_tx_handler(int irq, void *dev_id) · 56 unmodified lines | ||
| 57 | 57 | |
| 58 | 58 | intr = edma_readl_chreg(fsl_chan, ch_int); |
| 59 | 59 | if (!intr) |
| 60 | − return IRQ_HANDLED; | |
| 60 | + return IRQ_NONE; | |
| 61 | 61 | |
| 62 | 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 | 222 | struct idxd_wq *wq; |
| 223 | 223 | struct device *dev, *fdev; |
| 224 | 224 | int rc = 0; |
| 225 | − struct iommu_sva *sva; | |
| 225 | + struct iommu_sva *sva = NULL; | |
| 226 | 226 | unsigned int pasid; |
| 227 | 227 | struct idxd_cdev *idxd_cdev; |
| 228 | 228 | |
| @@ -317,7 +317,7 @@ failed_set_pasid: · 88 unmodified lines | ||
| 317 | 317 | if (device_user_pasid_enabled(idxd)) |
| 318 | 318 | idxd_xa_pasid_remove(ctx); |
| 319 | 319 | failed_get_pasid: |
| 320 | − if (device_user_pasid_enabled(idxd)) | |
| 320 | + if (device_user_pasid_enabled(idxd) && !IS_ERR_OR_NULL(sva)) | |
| 321 | 321 | iommu_sva_unbind_device(sva); |
| 322 | 322 | failed: |
| 323 | 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 | 407 | if (!idxd->user_submission_safe && !capable(CAP_SYS_RAWIO)) |
| 408 | 408 | return -EPERM; |
| 409 | 409 | |
| 410 | + if (current->mm != ctx->mm) | |
| 411 | + return -EPERM; | |
| 412 | + | |
| 410 | 413 | rc = check_vma(wq, vma, __func__); |
| 411 | 414 | if (rc < 0) |
| 412 | 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 | 476 | ssize_t written = 0; |
| 474 | 477 | int i; |
| 475 | 478 | |
| 479 | + if (current->mm != ctx->mm) | |
| 480 | + return -EPERM; | |
| 481 | + | |
| 476 | 482 | for (i = 0; i < len/sizeof(struct dsa_hw_desc); i++) { |
| 477 | 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 | 499 | struct idxd_device *idxd = wq->idxd; |
| 494 | 500 | __poll_t out = 0; |
| 495 | 501 | |
| 502 | + if (current->mm != ctx->mm) | |
| 503 | + return POLLNVAL; | |
| 504 | + | |
| 496 | 505 | poll_wait(filp, &wq->err_queue, wait); |
| 497 | 506 | spin_lock(&idxd->dev_lock); |
| 498 | 507 | if (idxd->sw_err.valid) |
| @@ -155,6 +155,25 @@ static void idxd_cleanup_interrupts(struct idxd_device *idxd) · 154 unmodified lines | ||
| 155 | 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 | 177 | static int idxd_setup_wqs(struct idxd_device *idxd) |
| 159 | 178 | { |
| 160 | 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 | 189 | idxd->wq_enable_map = bitmap_zalloc_node(idxd->max_wqs, GFP_KERNEL, dev_to_node(dev)); |
| 171 | 190 | if (!idxd->wq_enable_map) { |
| 172 | − kfree(idxd->wqs); | |
| 173 | − return -ENOMEM; | |
| 191 | + rc = -ENOMEM; | |
| 192 | + goto err_bitmap; | |
| 174 | 193 | } |
| 175 | 194 | |
| 176 | 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 | 208 | conf_dev->bus = &dsa_bus_type; |
| 190 | 209 | conf_dev->type = &idxd_wq_device_type; |
| 191 | 210 | rc = dev_set_name(conf_dev, "wq%d.%d", idxd->id, wq->id); |
| 192 | − if (rc < 0) { | |
| 193 | − put_device(conf_dev); | |
| 211 | + if (rc < 0) | |
| 194 | 212 | goto err; |
| 195 | − } | |
| 196 | 213 | |
| 197 | 214 | mutex_init(&wq->wq_lock); |
| 198 | 215 | init_waitqueue_head(&wq->err_queue); |
| @@ -203,7 +220,6 @@ static int idxd_setup_wqs(struct idxd_device *idxd) · 4 unmodified lines | ||
| 203 | 220 | wq->enqcmds_retries = IDXD_ENQCMDS_RETRIES; |
| 204 | 221 | wq->wqcfg = kzalloc_node(idxd->wqcfg_size, GFP_KERNEL, dev_to_node(dev)); |
| 205 | 222 | if (!wq->wqcfg) { |
| 206 | − put_device(conf_dev); | |
| 207 | 223 | rc = -ENOMEM; |
| 208 | 224 | goto err; |
| 209 | 225 | } |
| @@ -211,9 +227,8 @@ static int idxd_setup_wqs(struct idxd_device *idxd) · 1 unmodified line | ||
| 211 | 227 | if (idxd->hw.wq_cap.op_config) { |
| 212 | 228 | wq->opcap_bmap = bitmap_zalloc(IDXD_MAX_OPCAP_BITS, GFP_KERNEL); |
| 213 | 229 | if (!wq->opcap_bmap) { |
| 214 | − put_device(conf_dev); | |
| 215 | 230 | rc = -ENOMEM; |
| 216 | − goto err; | |
| 231 | + goto err_opcap_bmap; | |
| 217 | 232 | } |
| 218 | 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 | 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 | 249 | while (--i >= 0) { |
| 229 | 250 | wq = idxd->wqs[i]; |
| 251 | + if (idxd->hw.wq_cap.op_config) | |
| 252 | + bitmap_free(wq->opcap_bmap); | |
| 253 | + kfree(wq->wqcfg); | |
| 230 | 254 | conf_dev = wq_confdev(wq); |
| 231 | 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 | 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 | 282 | static int idxd_setup_engines(struct idxd_device *idxd) |
| 237 | 283 | { |
| 238 | 284 | struct idxd_engine *engine; |
| @@ -263,6 +309,7 @@ static int idxd_setup_engines(struct idxd_device *idxd) · 24 unmodified lines | ||
| 263 | 309 | rc = dev_set_name(conf_dev, "engine%d.%d", idxd->id, engine->id); |
| 264 | 310 | if (rc < 0) { |
| 265 | 311 | put_device(conf_dev); |
| 312 | + kfree(engine); | |
| 266 | 313 | goto err; |
| 267 | 314 | } |
| 268 | 315 | |
| @@ -276,10 +323,26 @@ static int idxd_setup_engines(struct idxd_device *idxd) · 7 unmodified lines | ||
| 276 | 323 | engine = idxd->engines[i]; |
| 277 | 324 | conf_dev = engine_confdev(engine); |
| 278 | 325 | put_device(conf_dev); |
| 326 | + kfree(engine); | |
| 279 | 327 | } |
| 328 | + kfree(idxd->engines); | |
| 329 | + | |
| 280 | 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 | 346 | static int idxd_setup_groups(struct idxd_device *idxd) |
| 284 | 347 | { |
| 285 | 348 | struct device *dev = &idxd->pdev->dev; |
| @@ -310,6 +373,7 @@ static int idxd_setup_groups(struct idxd_device *idxd) · 24 unmodified lines | ||
| 310 | 373 | rc = dev_set_name(conf_dev, "group%d.%d", idxd->id, group->id); |
| 311 | 374 | if (rc < 0) { |
| 312 | 375 | put_device(conf_dev); |
| 376 | + kfree(group); | |
| 313 | 377 | goto err; |
| 314 | 378 | } |
| 315 | 379 | |
| @@ -334,20 +398,18 @@ static int idxd_setup_groups(struct idxd_device *idxd) · 18 unmodified lines | ||
| 334 | 398 | while (--i >= 0) { |
| 335 | 399 | group = idxd->groups[i]; |
| 336 | 400 | put_device(group_confdev(group)); |
| 401 | + kfree(group); | |
| 337 | 402 | } |
| 403 | + kfree(idxd->groups); | |
| 404 | + | |
| 338 | 405 | return rc; |
| 339 | 406 | } |
| 340 | 407 | |
| 341 | 408 | static void idxd_cleanup_internals(struct idxd_device *idxd) |
| 342 | 409 | { |
| 343 | − int i; | |
| 344 | − | |
| 345 | − for (i = 0; i < idxd->max_groups; i++) | |
| 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])); | |
| 410 | + idxd_clean_groups(idxd); | |
| 411 | + idxd_clean_engines(idxd); | |
| 412 | + idxd_clean_wqs(idxd); | |
| 351 | 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 | 452 | static int idxd_setup_internals(struct idxd_device *idxd) |
| 391 | 453 | { |
| 392 | 454 | struct device *dev = &idxd->pdev->dev; |
| 393 | − int rc, i; | |
| 455 | + int rc; | |
| 394 | 456 | |
| 395 | 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 | 483 | err_evl: |
| 422 | 484 | destroy_workqueue(idxd->wq); |
| 423 | 485 | err_wkq_create: |
| 424 | − for (i = 0; i < idxd->max_groups; i++) | |
| 425 | − put_device(group_confdev(idxd->groups[i])); | |
| 486 | + idxd_clean_groups(idxd); | |
| 426 | 487 | err_group: |
| 427 | − for (i = 0; i < idxd->max_engines; i++) | |
| 428 | − put_device(engine_confdev(idxd->engines[i])); | |
| 488 | + idxd_clean_engines(idxd); | |
| 429 | 489 | err_engine: |
| 430 | − for (i = 0; i < idxd->max_wqs; i++) | |
| 431 | − put_device(wq_confdev(idxd->wqs[i])); | |
| 490 | + idxd_clean_wqs(idxd); | |
| 432 | 491 | err_wqs: |
| 433 | 492 | return rc; |
| 434 | 493 | } |
| @@ -528,6 +587,17 @@ static void idxd_read_caps(struct idxd_device *idxd) · 93 unmodified lines | ||
| 528 | 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 | 601 | static struct idxd_device *idxd_alloc(struct pci_dev *pdev, struct idxd_driver_data *data) |
| 532 | 602 | { |
| 533 | 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 | 615 | idxd_dev_set_type(&idxd->idxd_dev, idxd->data->type); |
| 546 | 616 | idxd->id = ida_alloc(&idxd_ida, GFP_KERNEL); |
| 547 | 617 | if (idxd->id < 0) |
| 548 | − return NULL; | |
| 618 | + goto err_ida; | |
| 549 | 619 | |
| 550 | 620 | idxd->opcap_bmap = bitmap_zalloc_node(IDXD_MAX_OPCAP_BITS, GFP_KERNEL, dev_to_node(dev)); |
| 551 | − if (!idxd->opcap_bmap) { | |
| 552 | − ida_free(&idxd_ida, idxd->id); | |
| 553 | − return NULL; | |
| 554 | − } | |
| 621 | + if (!idxd->opcap_bmap) | |
| 622 | + goto err_opcap; | |
| 555 | 623 | |
| 556 | 624 | device_initialize(conf_dev); |
| 557 | 625 | conf_dev->parent = dev; |
| 558 | 626 | conf_dev->bus = &dsa_bus_type; |
| 559 | 627 | conf_dev->type = idxd->data->dev_type; |
| 560 | 628 | rc = dev_set_name(conf_dev, "%s%d", idxd->data->name_prefix, idxd->id); |
| 561 | − if (rc < 0) { | |
| 562 | − put_device(conf_dev); | |
| 563 | − return NULL; | |
| 564 | − } | |
| 629 | + if (rc < 0) | |
| 630 | + goto err_name; | |
| 565 | 631 | |
| 566 | 632 | spin_lock_init(&idxd->dev_lock); |
| 567 | 633 | spin_lock_init(&idxd->cmd_lock); |
| 568 | 634 | |
| 569 | 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 | 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 | 1266 | err: |
| 1191 | 1267 | pci_iounmap(pdev, idxd->reg_base); |
| 1192 | 1268 | err_iomap: |
| 1193 | − put_device(idxd_confdev(idxd)); | |
| 1269 | + idxd_free(idxd); | |
| 1194 | 1270 | err_idxd_alloc: |
| 1195 | 1271 | pci_disable_device(pdev); |
| 1196 | 1272 | return rc; |
| @@ -1232,7 +1308,6 @@ static void idxd_shutdown(struct pci_dev *pdev) · 35 unmodified lines | ||
| 1232 | 1308 | static void idxd_remove(struct pci_dev *pdev) |
| 1233 | 1309 | { |
| 1234 | 1310 | struct idxd_device *idxd = pci_get_drvdata(pdev); |
| 1235 | − struct idxd_irq_entry *irq_entry; | |
| 1236 | 1311 | |
| 1237 | 1312 | idxd_unregister_devices(idxd); |
| 1238 | 1313 | /* |
| @@ -1245,20 +1320,12 @@ static void idxd_remove(struct pci_dev *pdev) · 6 unmodified lines | ||
| 1245 | 1320 | get_device(idxd_confdev(idxd)); |
| 1246 | 1321 | device_unregister(idxd_confdev(idxd)); |
| 1247 | 1322 | idxd_shutdown(pdev); |
| 1248 | − if (device_pasid_enabled(idxd)) | |
| 1249 | − idxd_disable_system_pasid(idxd); | |
| 1250 | 1323 | idxd_device_remove_debugfs(idxd); |
| 1251 | − | |
| 1252 | − irq_entry = idxd_get_ie(idxd, 0); | |
| 1253 | − free_irq(irq_entry->vector, irq_entry); | |
| 1254 | − pci_free_irq_vectors(pdev); | |
| 1324 | + idxd_cleanup(idxd); | |
| 1255 | 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 | 1326 | put_device(idxd_confdev(idxd)); |
| 1327 | + idxd_free(idxd); | |
| 1328 | + pci_disable_device(pdev); | |
| 1262 | 1329 | } |
| 1263 | 1330 | |
| 1264 | 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 | 421 | struct mtk_cqdma_vchan *cvc = to_cqdma_vchan(c); |
| 422 | 422 | struct virt_dma_desc *vd; |
| 423 | − unsigned long flags; | |
| 424 | 423 | |
| 425 | − spin_lock_irqsave(&cvc->pc->lock, flags); | |
| 426 | 424 | list_for_each_entry(vd, &cvc->pc->queue, node) |
| 427 | 425 | if (vd->tx.cookie == cookie) { |
| 428 | − spin_unlock_irqrestore(&cvc->pc->lock, flags); | |
| 429 | 426 | return vd; |
| 430 | 427 | } |
| 431 | − spin_unlock_irqrestore(&cvc->pc->lock, flags); | |
| 432 | 428 | |
| 433 | 429 | list_for_each_entry(vd, &cvc->vc.desc_issued, node) |
| 434 | 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 | 448 | if (ret == DMA_COMPLETE || !txstate) |
| 453 | 449 | return ret; |
| 454 | 450 | |
| 451 | + spin_lock_irqsave(&cvc->pc->lock, flags); | |
| 455 | 452 | spin_lock_irqsave(&cvc->vc.lock, flags); |
| 456 | 453 | vd = mtk_cqdma_find_active_desc(c, cookie); |
| 457 | 454 | spin_unlock_irqrestore(&cvc->vc.lock, flags); |
| 455 | + spin_unlock_irqrestore(&cvc->pc->lock, flags); | |
| 458 | 456 | |
| 459 | 457 | if (vd) { |
| 460 | 458 | cvd = to_cqdma_vdesc(vd); |
| @@ -1091,8 +1091,11 @@ static void udma_check_tx_completion(struct work_struct *work) · 1090 unmodified lines | ||
| 1091 | 1091 | u32 residue_diff; |
| 1092 | 1092 | ktime_t time_diff; |
| 1093 | 1093 | unsigned long delay; |
| 1094 | + unsigned long flags; | |
| 1094 | 1095 | |
| 1095 | 1096 | while (1) { |
| 1097 | + spin_lock_irqsave(&uc->vc.lock, flags); | |
| 1098 | + | |
| 1096 | 1099 | if (uc->desc) { |
| 1097 | 1100 | /* Get previous residue and time stamp */ |
| 1098 | 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 | 1130 | break; |
| 1128 | 1131 | } |
| 1129 | 1132 | |
| 1133 | + spin_unlock_irqrestore(&uc->vc.lock, flags); | |
| 1134 | + | |
| 1130 | 1135 | usleep_range(ktime_to_us(delay), |
| 1131 | 1136 | ktime_to_us(delay) + 10); |
| 1132 | 1137 | continue; |
| @@ -1143,6 +1148,8 @@ static void udma_check_tx_completion(struct work_struct *work) · 10 unmodified lines | ||
| 1143 | 1148 | |
| 1144 | 1149 | break; |
| 1145 | 1150 | } |
| 1151 | + | |
| 1152 | + spin_unlock_irqrestore(&uc->vc.lock, flags); | |
| 1146 | 1153 | } |
| 1147 | 1154 | |
| 1148 | 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 | 4253 | struct of_dma *ofdma) |
| 4247 | 4254 | { |
| 4248 | 4255 | struct udma_dev *ud = ofdma->of_dma_data; |
| 4249 | − dma_cap_mask_t mask = ud->ddev.cap_mask; | |
| 4250 | 4256 | struct udma_filter_param filter_param; |
| 4251 | 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 | 4288 | ofdma->of_node); |
| 4283 | 4289 | if (!chan) { |
| 4284 | 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 | 1205 | guard(mutex)(&chip->i2c_lock); |
| 1206 | 1206 | |
| 1207 | + if (chip->client->irq > 0) | |
| 1208 | + enable_irq(chip->client->irq); | |
| 1207 | 1209 | regcache_cache_only(chip->regmap, false); |
| 1208 | 1210 | regcache_mark_dirty(chip->regmap); |
| 1209 | 1211 | ret = pca953x_regcache_sync(chip); |
| @@ -1216,6 +1218,10 @@ static int pca953x_restore_context(struct pca953x_chip *chip) · 6 unmodified lines | ||
| 1216 | 1218 | static void pca953x_save_context(struct pca953x_chip *chip) |
| 1217 | 1219 | { |
| 1218 | 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 | 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 | 401 | char buf[32], *trimmed; |
| 402 | 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 | 408 | if (ret < 0) |
| 406 | 409 | return ret; |
| 407 | 410 | |
| 411 | + buf[ret] = '\0'; | |
| 412 | + | |
| 408 | 413 | trimmed = strim(buf); |
| 409 | 414 | |
| 410 | 415 | if (strcmp(trimmed, "input") == 0) { |
| @@ -623,12 +628,15 @@ static ssize_t gpio_virtuser_consumer_write(struct file *file, · 212 unmodified lines | ||
| 623 | 628 | char buf[GPIO_VIRTUSER_NAME_BUF_LEN + 2]; |
| 624 | 629 | int ret; |
| 625 | 630 | |
| 631 | + if (count >= sizeof(buf)) | |
| 632 | + return -EINVAL; | |
| 633 | + | |
| 626 | 634 | ret = simple_write_to_buffer(buf, GPIO_VIRTUSER_NAME_BUF_LEN, ppos, |
| 627 | 635 | user_buf, count); |
| 628 | 636 | if (ret < 0) |
| 629 | 637 | return ret; |
| 630 | 638 | |
| 631 | − buf[strlen(buf) - 1] = '\0'; | |
| 639 | + buf[ret] = '\0'; | |
| 632 | 640 | |
| 633 | 641 | ret = gpiod_set_consumer_name(data->ad.desc, buf); |
| 634 | 642 | if (ret) |
| @@ -109,7 +109,7 @@ int amdgpu_unmap_static_csa(struct amdgpu_device *adev, struct amdgpu_vm *vm, · 108 unmodified lines | ||
| 109 | 109 | struct drm_exec exec; |
| 110 | 110 | int r; |
| 111 | 111 | |
| 112 | − drm_exec_init(&exec, DRM_EXEC_INTERRUPTIBLE_WAIT, 0); | |
| 112 | + drm_exec_init(&exec, 0, 0); | |
| 113 | 113 | drm_exec_until_all_locked(&exec) { |
| 114 | 114 | r = amdgpu_vm_lock_pd(vm, &exec, 0); |
| 115 | 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 | 752 | adev->gmc.vram_type = vram_type; |
| 753 | 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 | 767 | switch (amdgpu_ip_version(adev, GC_HWIP, 0)) { |
| 756 | 768 | case IP_VERSION(11, 0, 0): |
| 757 | 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 | 1023 | ring->doorbell_index << VCN_RB1_DB_CTRL__OFFSET__SHIFT | |
| 1024 | 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 | 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 | 1209 | WREG32_SOC15(VCN, i, regVCN_RB_ENABLE, tmp); |
| 1206 | 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 | 1216 | return 0; |
| 1209 | 1217 | } |
| 1210 | 1218 | |
| @@ -372,6 +372,8 @@ get_crtc_by_otg_inst(struct amdgpu_device *adev, · 371 unmodified lines | ||
| 372 | 372 | static inline bool is_dc_timing_adjust_needed(struct dm_crtc_state *old_state, |
| 373 | 373 | struct dm_crtc_state *new_state) |
| 374 | 374 | { |
| 375 | + if (new_state->stream->adjust.timing_adjust_pending) | |
| 376 | + return true; | |
| 375 | 377 | if (new_state->freesync_config.state == VRR_STATE_ACTIVE_FIXED) |
| 376 | 378 | return true; |
| 377 | 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 | 12765 | /* The reply is stored in the top nibble of the command. */ |
| 12764 | 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 | 12770 | memcpy(payload->data, p_notify->aux_reply.data, |
| 12768 | 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 | 62 | enum aux_return_code_type operation_result; |
| 63 | 63 | struct amdgpu_device *adev; |
| 64 | 64 | struct ddc_service *ddc; |
| 65 | + uint8_t copy[16]; | |
| 65 | 66 | |
| 66 | 67 | if (WARN_ON(msg->size > 16)) |
| 67 | 68 | return -E2BIG; |
| @@ -77,6 +78,11 @@ static ssize_t dm_dp_aux_transfer(struct drm_dp_aux *aux, · 9 unmodified lines | ||
| 77 | 78 | (msg->request & DP_AUX_I2C_WRITE_STATUS_UPDATE) != 0; |
| 78 | 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 | 86 | result = dc_link_aux_transfer_raw(TO_DM_AUX(aux)->ddc_service, &payload, |
| 81 | 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 | 107 | if (payload.write && result >= 0) { |
| 102 | 108 | if (result) { |
| 103 | − /*one byte indicating partially written bytes. Force 0 to retry*/ | |
| 104 | − drm_info(adev_to_drm(adev), "amdgpu: AUX partially written\n"); | |
| 105 | − result = 0; | |
| 109 | + /*one byte indicating partially written bytes*/ | |
| 110 | + drm_dbg_dp(adev_to_drm(adev), "amdgpu: AUX partially written\n"); | |
| 111 | + result = payload.data[0]; | |
| 106 | 112 | } else if (!payload.reply[0]) |
| 107 | 113 | /*I2C_ACK|AUX_ACK*/ |
| 108 | 114 | result = msg->size; |
| @@ -127,11 +133,11 @@ static ssize_t dm_dp_aux_transfer(struct drm_dp_aux *aux, · 18 unmodified lines | ||
| 127 | 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 | 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 | 141 | payload.reply[0]); |
| 136 | 142 | |
| 137 | 143 | return result; |
| @@ -439,9 +439,12 @@ bool dc_stream_adjust_vmin_vmax(struct dc *dc, · 438 unmodified lines | ||
| 439 | 439 | * Don't adjust DRR while there's bandwidth optimizations pending to |
| 440 | 440 | * avoid conflicting with firmware updates. |
| 441 | 441 | */ |
| 442 | − if (dc->ctx->dce_version > DCE_VERSION_MAX) | |
| 443 | − if (dc->optimized_required || dc->wm_optimized_required) | |
| 442 | + if (dc->ctx->dce_version > DCE_VERSION_MAX) { | |
| 443 | + if (dc->optimized_required || dc->wm_optimized_required) { | |
| 444 | + stream->adjust.timing_adjust_pending = true; | |
| 444 | 445 | return false; |
| 446 | + } | |
| 447 | + } | |
| 445 | 448 | |
| 446 | 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 | 3172 | if (update->crtc_timing_adjust) { |
| 3170 | 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 | 3176 | update->crtc_timing_adjust->timing_adjust_pending = true; |
| 3173 | 3177 | stream->adjust = *update->crtc_timing_adjust; |
| 3174 | 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 | 195 | .dcn_downspread_percent = 0.5, |
| 196 | 196 | .gpuvm_min_page_size_bytes = 4096, |
| 197 | 197 | .hostvm_min_page_size_bytes = 4096, |
| 198 | − .do_urgent_latency_adjustment = 1, | |
| 198 | + .do_urgent_latency_adjustment = 0, | |
| 199 | 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 | 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 | 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 | 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 | 918 | return false; |
| 919 | 919 | |
| 920 | 920 | for (i = 0; i < context->stream_count; i++) { |
| 921 | − for (j = 0; j < context->stream_status[i].plane_count; j++) { | |
| 922 | − if (context->stream_status[i].plane_states[j] == plane) { | |
| 923 | − *plane_id = (i << 16) | j; | |
| 924 | − return true; | |
| 921 | + if (context->streams[i]->stream_id == stream_id) { | |
| 922 | + for (j = 0; j < context->stream_status[i].plane_count; j++) { | |
| 923 | + if (context->stream_status[i].plane_states[j] == plane) { | |
| 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 | 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 | 950 | const struct dc_plane_state *plane, const struct dc_state *context) |
| 949 | 951 | { |
| 950 | 952 | unsigned int plane_id; |
| 951 | 953 | int i = 0; |
| 952 | 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 | 957 | ASSERT(false); |
| 956 | 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 | 1039 | dml_dispcfg->plane_descriptors[disp_cfg_plane_location].stream_index = disp_cfg_stream_location; |
| 1038 | 1040 | } else { |
| 1039 | 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 | 1044 | if (disp_cfg_plane_location < 0) |
| 1043 | 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 | 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 | 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 | 1054 | dml_ctx->v21.dml_to_dc_pipe_mapping.disp_cfg_to_plane_id_valid[disp_cfg_plane_location] = true; |
| 1053 | 1055 | |
| 1054 | 1056 | /* apply forced pstate policy */ |
| @@ -120,10 +120,11 @@ void dpp401_set_cursor_attributes( · 119 unmodified lines | ||
| 120 | 120 | enum dc_cursor_color_format color_format = cursor_attributes->color_format; |
| 121 | 121 | int cur_rom_en = 0; |
| 122 | 122 | |
| 123 | − // DCN4 should always do Cursor degamma for Cursor Color modes | |
| 124 | 123 | if (color_format == CURSOR_MODE_COLOR_PRE_MULTIPLIED_ALPHA || |
| 125 | 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 | 130 | REG_UPDATE_3(CURSOR0_CONTROL, |
| @@ -1980,9 +1980,9 @@ void dcn401_program_pipe( · 1979 unmodified lines | ||
| 1980 | 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 || | |
| 1984 | − (pipe_ctx->plane_state && pipe_ctx->plane_state->update_flags.raw) || | |
| 1985 | − pipe_ctx->stream->update_flags.raw) | |
| 1983 | + if (pipe_ctx->plane_state && (pipe_ctx->update_flags.raw || | |
| 1984 | + pipe_ctx->plane_state->update_flags.raw || | |
| 1985 | + pipe_ctx->stream->update_flags.raw)) | |
| 1986 | 1986 | dc->hwss.update_dchubp_dpp(dc, pipe_ctx, context); |
| 1987 | 1987 | |
| 1988 | 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 | 148 | void link_set_all_streams_dpms_off_for_link(struct dc_link *link) |
| 149 | 149 | { |
| 150 | 150 | struct pipe_ctx *pipes[MAX_PIPES]; |
| 151 | + struct dc_stream_state *streams[MAX_PIPES]; | |
| 151 | 152 | struct dc_state *state = link->dc->current_state; |
| 152 | 153 | uint8_t count; |
| 153 | 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 | 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 | 172 | for (i = 0; i < count; i++) { |
| 164 | − stream_update.stream = pipes[i]->stream; | |
| 173 | + stream_update.stream = streams[i]; | |
| 165 | 174 | dc_commit_updates_for_stream(link->ctx->dc, NULL, 0, |
| 166 | − pipes[i]->stream, &stream_update, | |
| 175 | + streams[i], &stream_update, | |
| 167 | 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 | 1118 | lockdep_assert_held(&gpusvm->notifier_lock); |
| 1119 | 1119 | |
| 1120 | 1120 | if (range->flags.has_dma_mapping) { |
| 1121 | + struct drm_gpusvm_range_flags flags = { | |
| 1122 | + .__flags = range->flags.__flags, | |
| 1123 | + }; | |
| 1124 | + | |
| 1121 | 1125 | for (i = 0, j = 0; i < npages; j++) { |
| 1122 | 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 | 1135 | dev, *addr); |
| 1132 | 1136 | i += 1 << addr->order; |
| 1133 | 1137 | } |
| 1134 | − range->flags.has_devmem_pages = false; | |
| 1135 | − range->flags.has_dma_mapping = false; | |
| 1138 | + | |
| 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 | 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 | 1342 | int err = 0; |
| 1335 | 1343 | struct dev_pagemap *pagemap; |
| 1336 | 1344 | struct drm_pagemap *dpagemap; |
| 1345 | + struct drm_gpusvm_range_flags flags; | |
| 1337 | 1346 | |
| 1338 | 1347 | retry: |
| 1339 | 1348 | hmm_range.notifier_seq = mmu_interval_read_begin(notifier); |
| @@ -1378,7 +1387,8 @@ map_pages: · 38 unmodified lines | ||
| 1378 | 1387 | */ |
| 1379 | 1388 | drm_gpusvm_notifier_lock(gpusvm); |
| 1380 | 1389 | |
| 1381 | − if (range->flags.unmapped) { | |
| 1390 | + flags.__flags = range->flags.__flags; | |
| 1391 | + if (flags.unmapped) { | |
| 1382 | 1392 | drm_gpusvm_notifier_unlock(gpusvm); |
| 1383 | 1393 | err = -EFAULT; |
| 1384 | 1394 | goto err_free; |
| @@ -1454,6 +1464,11 @@ map_pages: · 69 unmodified lines | ||
| 1454 | 1464 | goto err_unmap; |
| 1455 | 1465 | } |
| 1456 | 1466 | |
| 1467 | + if (ctx->devmem_only) { | |
| 1468 | + err = -EFAULT; | |
| 1469 | + goto err_unmap; | |
| 1470 | + } | |
| 1471 | + | |
| 1457 | 1472 | addr = dma_map_page(gpusvm->drm->dev, |
| 1458 | 1473 | page, 0, |
| 1459 | 1474 | PAGE_SIZE << order, |
| @@ -1469,14 +1484,17 @@ map_pages: · 9 unmodified lines | ||
| 1469 | 1484 | } |
| 1470 | 1485 | i += 1 << order; |
| 1471 | 1486 | num_dma_mapped = i; |
| 1472 | − range->flags.has_dma_mapping = true; | |
| 1487 | + flags.has_dma_mapping = true; | |
| 1473 | 1488 | } |
| 1474 | 1489 | |
| 1475 | 1490 | if (zdd) { |
| 1476 | − range->flags.has_devmem_pages = true; | |
| 1491 | + flags.has_devmem_pages = true; | |
| 1477 | 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 | 1498 | drm_gpusvm_notifier_unlock(gpusvm); |
| 1481 | 1499 | kvfree(pfns); |
| 1482 | 1500 | set_seqno: |
| @@ -1765,6 +1783,8 @@ int drm_gpusvm_migrate_to_devmem(struct drm_gpusvm *gpusvm, · 282 unmodified lines | ||
| 1765 | 1783 | goto err_finalize; |
| 1766 | 1784 | |
| 1767 | 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 | 1788 | zdd->devmem_allocation = devmem_allocation; /* Owns ref */ |
| 1769 | 1789 | |
| 1770 | 1790 | err_finalize: |
| @@ -1985,6 +2005,13 @@ static int __drm_gpusvm_migrate_to_ram(struct vm_area_struct *vas, · 214 unmodified lines | ||
| 1985 | 2005 | void *buf; |
| 1986 | 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 | 2015 | start = ALIGN_DOWN(fault_addr, size); |
| 1989 | 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 | 75 | unsigned long long venc_freq; |
| 76 | 76 | unsigned long long hdmi_freq; |
| 77 | 77 | |
| 78 | − vclk_freq = mode->clock * 1000; | |
| 78 | + vclk_freq = mode->clock * 1000ULL; | |
| 79 | 79 | |
| 80 | 80 | /* For 420, pixel clock is half unlike venc clock */ |
| 81 | 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 | 123 | struct meson_encoder_hdmi *encoder_hdmi = bridge_to_meson_encoder_hdmi(bridge); |
| 124 | 124 | struct meson_drm *priv = encoder_hdmi->priv; |
| 125 | 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 | 127 | unsigned long long phy_freq; |
| 128 | 128 | unsigned long long vclk_freq; |
| 129 | 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 | 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 | 398 | return 0; |
| 396 | 399 | } |
| @@ -47,6 +47,10 @@ · 46 unmodified lines | ||
| 47 | 47 | #define MI_LRI_FORCE_POSTED REG_BIT(12) |
| 48 | 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 | 54 | #define MI_FLUSH_DW __MI_INSTR(0x26) |
| 51 | 55 | #define MI_FLUSH_DW_PROTECTED_MEM_EN REG_BIT(22) |
| 52 | 56 | #define MI_FLUSH_DW_STORE_INDEX REG_BIT(21) |
| @@ -43,6 +43,10 @@ · 42 unmodified lines | ||
| 43 | 43 | #define XEHPC_BCS8_RING_BASE 0x3ee000 |
| 44 | 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 | 50 | #define RING_TAIL(base) XE_REG((base) + 0x30) |
| 47 | 51 | #define TAIL_ADDR REG_GENMASK(20, 3) |
| 48 | 52 | |
| @@ -154,6 +158,7 @@ · 105 unmodified lines | ||
| 154 | 158 | #define STOP_RING REG_BIT(8) |
| 155 | 159 | |
| 156 | 160 | #define RING_CTX_TIMESTAMP(base) XE_REG((base) + 0x3a8) |
| 161 | +#define RING_CTX_TIMESTAMP_UDW(base) XE_REG((base) + 0x3ac) | |
| 157 | 162 | #define CSBE_DEBUG_STATUS(base) XE_REG((base) + 0x3fc) |
| 158 | 163 | |
| 159 | 164 | #define RING_FORCE_TO_NONPRIV(base, i) XE_REG(((base) + 0x4d0) + (i) * 4) |
| @@ -157,6 +157,7 @@ · 156 unmodified lines | ||
| 157 | 157 | #define XEHPG_SC_INSTDONE_EXTRA2 XE_REG_MCR(0x7108) |
| 158 | 158 | |
| 159 | 159 | #define COMMON_SLICE_CHICKEN4 XE_REG(0x7300, XE_REG_OPTION_MASKED) |
| 160 | +#define SBE_PUSH_CONSTANT_BEHIND_FIX_ENABLE REG_BIT(12) | |
| 160 | 161 | #define DISABLE_TDC_LOAD_BALANCING_CALC REG_BIT(6) |
| 161 | 162 | |
| 162 | 163 | #define COMMON_SLICE_CHICKEN3 XE_REG(0x7304, XE_REG_OPTION_MASKED) |
| @@ -11,7 +11,9 @@ · 10 unmodified lines | ||
| 11 | 11 | #define CTX_RING_TAIL (0x06 + 1) |
| 12 | 12 | #define CTX_RING_START (0x08 + 1) |
| 13 | 13 | #define CTX_RING_CTL (0x0a + 1) |
| 14 | +#define CTX_BB_PER_CTX_PTR (0x12 + 1) | |
| 14 | 15 | #define CTX_TIMESTAMP (0x22 + 1) |
| 16 | +#define CTX_TIMESTAMP_UDW (0x24 + 1) | |
| 15 | 17 | #define CTX_INDIRECT_RING_STATE (0x26 + 1) |
| 16 | 18 | #define CTX_PDP0_UDW (0x30 + 1) |
| 17 | 19 | #define CTX_PDP0_LDW (0x32 + 1) |
| @@ -330,6 +330,8 @@ struct xe_device { · 329 unmodified lines | ||
| 330 | 330 | u8 has_sriov:1; |
| 331 | 331 | /** @info.has_usm: Device has unified shared memory support */ |
| 332 | 332 | u8 has_usm:1; |
| 333 | + /** @info.has_64bit_timestamp: Device supports 64-bit timestamps */ | |
| 334 | + u8 has_64bit_timestamp:1; | |
| 333 | 335 | /** @info.is_dgfx: is discrete device */ |
| 334 | 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 | 831 | struct xe_device *xe = gt_to_xe(q->gt); |
| 832 | 832 | struct xe_lrc *lrc; |
| 833 | − u32 old_ts, new_ts; | |
| 833 | + u64 old_ts, new_ts; | |
| 834 | 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 | 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 | 945 | ctx_job_timestamp = xe_lrc_ctx_job_timestamp(q->lrc[0]); |
| 946 | 946 | |
| 947 | 947 | /* |
| @@ -24,6 +24,7 @@ · 23 unmodified lines | ||
| 24 | 24 | #include "xe_hw_fence.h" |
| 25 | 25 | #include "xe_map.h" |
| 26 | 26 | #include "xe_memirq.h" |
| 27 | +#include "xe_mmio.h" | |
| 27 | 28 | #include "xe_sriov.h" |
| 28 | 29 | #include "xe_trace_lrc.h" |
| 29 | 30 | #include "xe_vm.h" |
| @@ -650,6 +651,7 @@ u32 xe_lrc_pphwsp_offset(struct xe_lrc *lrc) · 620 unmodified lines | ||
| 650 | 651 | #define LRC_START_SEQNO_PPHWSP_OFFSET (LRC_SEQNO_PPHWSP_OFFSET + 8) |
| 651 | 652 | #define LRC_CTX_JOB_TIMESTAMP_OFFSET (LRC_START_SEQNO_PPHWSP_OFFSET + 8) |
| 652 | 653 | #define LRC_PARALLEL_PPHWSP_OFFSET 2048 |
| 654 | +#define LRC_ENGINE_ID_PPHWSP_OFFSET 2096 | |
| 653 | 655 | #define LRC_PPHWSP_SIZE SZ_4K |
| 654 | 656 | |
| 655 | 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 | 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 | 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 | 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 | 704 | static u32 __xe_lrc_ctx_timestamp_offset(struct xe_lrc *lrc) |
| 698 | 705 | { |
| 699 | 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 | 714 | static inline u32 __xe_lrc_indirect_ring_offset(struct xe_lrc *lrc) |
| 703 | 715 | { |
| 704 | 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 | 738 | DECL_MAP_ADDR_HELPERS(start_seqno) |
| 727 | 739 | DECL_MAP_ADDR_HELPERS(ctx_job_timestamp) |
| 728 | 740 | DECL_MAP_ADDR_HELPERS(ctx_timestamp) |
| 741 | +DECL_MAP_ADDR_HELPERS(ctx_timestamp_udw) | |
| 729 | 742 | DECL_MAP_ADDR_HELPERS(parallel) |
| 730 | 743 | DECL_MAP_ADDR_HELPERS(indirect_ring) |
| 744 | +DECL_MAP_ADDR_HELPERS(engine_id) | |
| 731 | 745 | |
| 732 | 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 | 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 | 771 | * xe_lrc_ctx_timestamp() - Read ctx timestamp value |
| 747 | 772 | * @lrc: Pointer to the lrc. |
| 748 | 773 | * |
| 749 | 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 | 778 | struct xe_device *xe = lrc_to_xe(lrc); |
| 754 | 779 | struct iosys_map map; |
| 780 | + u32 ldw, udw = 0; | |
| 755 | 781 | |
| 756 | 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 | 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 | 902 | xe_lrc_write_ctx_reg(lrc, CTX_PDP0_UDW, upper_32_bits(desc)); |
| 870 | 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 | 910 | xe_bo_unpin(lrc->bo); |
| 878 | 911 | xe_bo_unlock(lrc->bo); |
| 879 | 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 | 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 | 985 | void *init_data = NULL; |
| 894 | 986 | u32 arb_enable; |
| 895 | 987 | u32 lrc_size; |
| 988 | + u32 bo_flags; | |
| 896 | 989 | int err; |
| 897 | 990 | |
| 898 | 991 | kref_init(&lrc->refcount); |
| 992 | + lrc->gt = gt; | |
| 899 | 993 | lrc->flags = 0; |
| 900 | 994 | lrc_size = ring_size + xe_gt_lrc_size(gt, hwe->class); |
| 901 | 995 | if (xe_gt_has_indirect_ring_state(gt)) |
| 902 | 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 | 1002 | * FIXME: Perma-pinning LRC as we don't yet support moving GGTT address |
| 906 | 1003 | * via VM bind calls. |
| 907 | 1004 | */ |
| 908 | 1005 | lrc->bo = xe_bo_create_pin_map(xe, tile, vm, lrc_size, |
| 909 | 1006 | ttm_bo_type_kernel, |
| 910 | − XE_BO_FLAG_VRAM_IF_DGFX(tile) | | |
| 911 | − XE_BO_FLAG_GGTT | | |
| 912 | − XE_BO_FLAG_GGTT_INVALIDATE); | |
| 1007 | + bo_flags); | |
| 913 | 1008 | if (IS_ERR(lrc->bo)) |
| 914 | 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 | 1019 | lrc->size = lrc_size; |
| 917 | − lrc->tile = gt_to_tile(hwe->gt); | |
| 918 | 1020 | lrc->ring.size = ring_size; |
| 919 | 1021 | lrc->ring.tail = 0; |
| 920 | − lrc->ctx_timestamp = 0; | |
| 921 | 1022 | |
| 922 | 1023 | xe_hw_fence_ctx_init(&lrc->fence_ctx, hwe->gt, |
| 923 | 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 | 1091 | xe_lrc_read_ctx_reg(lrc, CTX_CONTEXT_CONTROL) | |
| 991 | 1092 | _MASKED_BIT_ENABLE(CTX_CTRL_PXP_ENABLE)); |
| 992 | 1093 | |
| 1094 | + lrc->ctx_timestamp = 0; | |
| 993 | 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 | 1099 | if (xe->info.has_asid && vm) |
| 996 | 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 | 1123 | map = __xe_lrc_start_seqno_map(lrc); |
| 1020 | 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 | 1128 | return 0; |
| 1023 | 1129 | |
| 1024 | 1130 | err_lrc_finish: |
| @@ -1238,6 +1344,21 @@ struct iosys_map xe_lrc_parallel_map(struct xe_lrc *lrc) · 213 unmodified lines | ||
| 1238 | 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 | 1362 | static int instr_dw(u32 cmd_header) |
| 1242 | 1363 | { |
| 1243 | 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 | 1805 | snapshot->lrc_offset = xe_lrc_pphwsp_offset(lrc); |
| 1685 | 1806 | snapshot->lrc_size = lrc->bo->size - snapshot->lrc_offset; |
| 1686 | 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 | 1809 | snapshot->ctx_job_timestamp = xe_lrc_ctx_job_timestamp(lrc); |
| 1689 | 1810 | return snapshot; |
| 1690 | 1811 | } |
| @@ -1784,22 +1905,74 @@ void xe_lrc_snapshot_free(struct xe_lrc_snapshot *snapshot) · 93 unmodified lines | ||
| 1784 | 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 | 1934 | * xe_lrc_update_timestamp() - Update ctx timestamp |
| 1789 | 1935 | * @lrc: Pointer to the lrc. |
| 1790 | 1936 | * @old_ts: Old timestamp value |
| 1791 | 1937 | * |
| 1792 | 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 | 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 | 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 | 1976 | trace_xe_lrc_update_timestamp(lrc, *old_ts); |
| 1804 | 1977 | |
| 1805 | 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 | 120 | void xe_lrc_snapshot_free(struct xe_lrc_snapshot *snapshot); |
| 121 | 121 | |
| 122 | 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 | 125 | u32 xe_lrc_ctx_job_timestamp_ggtt_addr(struct xe_lrc *lrc); |
| 125 | 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 | 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 | 142 | #endif |
| @@ -25,8 +25,8 @@ struct xe_lrc { · 24 unmodified lines | ||
| 25 | 25 | /** @size: size of lrc including any indirect ring state page */ |
| 26 | 26 | u32 size; |
| 27 | 27 | |
| 28 | − /** @tile: tile which this LRC belongs to */ | |
| 29 | − struct xe_tile *tile; | |
| 28 | + /** @gt: gt which this LRC belongs to */ | |
| 29 | + struct xe_gt *gt; | |
| 30 | 30 | |
| 31 | 31 | /** @flags: LRC flags */ |
| 32 | 32 | #define XE_LRC_FLAG_INDIRECT_RING_STATE 0x1 |
| @@ -52,7 +52,10 @@ struct xe_lrc { · 19 unmodified lines | ||
| 52 | 52 | struct xe_hw_fence_ctx fence_ctx; |
| 53 | 53 | |
| 54 | 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 | 61 | struct xe_lrc_snapshot; |
| @@ -29,9 +29,6 @@ struct xe_modparam xe_modparam = { · 28 unmodified lines | ||
| 29 | 29 | module_param_named(svm_notifier_size, xe_modparam.svm_notifier_size, uint, 0600); |
| 30 | 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 | 32 | module_param_named_unsafe(force_execlist, xe_modparam.force_execlist, bool, 0444); |
| 36 | 33 | MODULE_PARM_DESC(force_execlist, "Force Execlist submission"); |
| 37 | 34 | |
| @@ -12,7 +12,6 @@ · 11 unmodified lines | ||
| 12 | 12 | struct xe_modparam { |
| 13 | 13 | bool force_execlist; |
| 14 | 14 | bool probe_display; |
| 15 | − bool always_migrate_to_vram; | |
| 16 | 15 | u32 force_vram_bar_size; |
| 17 | 16 | int guc_log_level; |
| 18 | 17 | char *guc_firmware_path; |
| @@ -140,6 +140,7 @@ static const struct xe_graphics_desc graphics_xelpg = { · 139 unmodified lines | ||
| 140 | 140 | .has_indirect_ring_state = 1, \ |
| 141 | 141 | .has_range_tlb_invalidation = 1, \ |
| 142 | 142 | .has_usm = 1, \ |
| 143 | + .has_64bit_timestamp = 1, \ | |
| 143 | 144 | .va_bits = 48, \ |
| 144 | 145 | .vm_max_level = 4, \ |
| 145 | 146 | .hw_engine_mask = \ |
| @@ -668,6 +669,7 @@ static int xe_info_init(struct xe_device *xe, · 522 unmodified lines | ||
| 668 | 669 | |
| 669 | 670 | xe->info.has_range_tlb_invalidation = graphics_desc->has_range_tlb_invalidation; |
| 670 | 671 | xe->info.has_usm = graphics_desc->has_usm; |
| 672 | + xe->info.has_64bit_timestamp = graphics_desc->has_64bit_timestamp; | |
| 671 | 673 | |
| 672 | 674 | for_each_remote_tile(tile, xe, id) { |
| 673 | 675 | int err; |
| @@ -21,6 +21,7 @@ struct xe_graphics_desc { · 20 unmodified lines | ||
| 21 | 21 | u8 has_indirect_ring_state:1; |
| 22 | 22 | u8 has_range_tlb_invalidation:1; |
| 23 | 23 | u8 has_usm:1; |
| 24 | + u8 has_64bit_timestamp:1; | |
| 24 | 25 | }; |
| 25 | 26 | |
| 26 | 27 | struct xe_media_desc { |
| @@ -2232,11 +2232,19 @@ static void op_commit(struct xe_vm *vm, · 2231 unmodified lines | ||
| 2232 | 2232 | } |
| 2233 | 2233 | case DRM_GPUVA_OP_DRIVER: |
| 2234 | 2234 | { |
| 2235 | + /* WRITE_ONCE pairs with READ_ONCE in xe_svm.c */ | |
| 2236 | + | |
| 2235 | 2237 | if (op->subop == XE_VMA_SUBOP_MAP_RANGE) { |
| 2236 | − op->map_range.range->tile_present |= BIT(tile->id); | |
| 2237 | − op->map_range.range->tile_invalidated &= ~BIT(tile->id); | |
| 2238 | + WRITE_ONCE(op->map_range.range->tile_present, | |
| 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 | 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 | 2249 | break; |
| 2242 | 2250 | } |
| @@ -234,13 +234,10 @@ static u32 get_ppgtt_flag(struct xe_sched_job *job) · 233 unmodified lines | ||
| 234 | 234 | |
| 235 | 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 | | |
| 238 | − MI_COPY_MEM_MEM_DST_GGTT; | |
| 237 | + dw[i++] = MI_STORE_REGISTER_MEM | MI_SRM_USE_GGTT | MI_SRM_ADD_CS_OFFSET; | |
| 238 | + dw[i++] = RING_CTX_TIMESTAMP(0).addr; | |
| 239 | 239 | dw[i++] = xe_lrc_ctx_job_timestamp_ggtt_addr(lrc); |
| 240 | 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 | 242 | return i; |
| 246 | 243 | } |
| @@ -227,7 +227,7 @@ struct xe_shrinker *xe_shrinker_create(struct xe_device *xe) · 226 unmodified lines | ||
| 227 | 227 | if (!shrinker) |
| 228 | 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 | 231 | if (!shrinker->shrink) { |
| 232 | 232 | kfree(shrinker); |
| 233 | 233 | return ERR_PTR(-ENOMEM); |
| @@ -15,8 +15,17 @@ · 14 unmodified lines | ||
| 15 | 15 | |
| 16 | 16 | static bool xe_svm_range_in_vram(struct xe_svm_range *range) |
| 17 | 17 | { |
| 18 | − /* Not reliable without notifier lock */ | |
| 19 | − return range->base.flags.has_devmem_pages; | |
| 18 | + /* | |
| 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 | 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 | 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 | 669 | static struct xe_vram_region *tile_to_vr(struct xe_tile *tile) |
| @@ -712,6 +728,36 @@ unlock: · 58 unmodified lines | ||
| 712 | 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 | 762 | * xe_svm_handle_pagefault() - SVM handle page fault |
| 717 | 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 | 781 | IS_ENABLED(CONFIG_DRM_XE_DEVMEM_MIRROR), |
| 736 | 782 | .check_pages_threshold = IS_DGFX(vm->xe) && |
| 737 | 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 | 789 | struct xe_svm_range *range; |
| 740 | 790 | struct drm_gpusvm_range *r; |
| 741 | 791 | struct drm_exec exec; |
| 742 | 792 | struct dma_fence *fence; |
| 793 | + int migrate_try_count = ctx.devmem_only ? 3 : 1; | |
| 743 | 794 | ktime_t end = 0; |
| 744 | 795 | int err; |
| 745 | 796 | |
| @@ -758,24 +809,31 @@ retry: · 12 unmodified lines | ||
| 758 | 809 | if (IS_ERR(r)) |
| 759 | 810 | return PTR_ERR(r); |
| 760 | 811 | |
| 812 | + if (ctx.devmem_only && !r->flags.migrate_devmem) | |
| 813 | + return -EACCES; | |
| 814 | + | |
| 761 | 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 | 817 | return 0; |
| 764 | 818 | |
| 765 | 819 | range_debug(range, "PAGE FAULT"); |
| 766 | 820 | |
| 767 | − /* XXX: Add migration policy, for now migrate range once */ | |
| 768 | − if (!range->skip_migrate && range->base.flags.migrate_devmem && | |
| 769 | − xe_svm_range_size(range) >= SZ_64K) { | |
| 770 | − range->skip_migrate = true; | |
| 771 | − | |
| 821 | + if (--migrate_try_count >= 0 && | |
| 822 | + xe_svm_range_needs_migrate_to_vram(range, vma)) { | |
| 772 | 823 | err = xe_svm_alloc_vram(vm, tile, range, &ctx); |
| 824 | + ctx.timeslice_ms <<= 1; /* Double timeslice if we have to retry */ | |
| 773 | 825 | if (err) { |
| 774 | − drm_dbg(&vm->xe->drm, | |
| 775 | − "VRAM allocation failed, falling back to " | |
| 776 | − "retrying fault, asid=%u, errno=%pe\n", | |
| 777 | − vm->usm.asid, ERR_PTR(err)); | |
| 778 | − goto retry; | |
| 826 | + if (migrate_try_count || !ctx.devmem_only) { | |
| 827 | + drm_dbg(&vm->xe->drm, | |
| 828 | + "VRAM allocation failed, falling back to retrying fault, asid=%u, errno=%pe\n", | |
| 829 | + vm->usm.asid, ERR_PTR(err)); | |
| 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 | 841 | err = drm_gpusvm_range_get_pages(&vm->svm.gpusvm, r, &ctx); |
| 784 | 842 | /* Corner where CPU mappings have changed */ |
| 785 | 843 | if (err == -EOPNOTSUPP || err == -EFAULT || err == -EPERM) { |
| 786 | − if (err == -EOPNOTSUPP) { | |
| 787 | − range_debug(range, "PAGE FAULT - EVICT PAGES"); | |
| 788 | − drm_gpusvm_range_evict(&vm->svm.gpusvm, &range->base); | |
| 844 | + ctx.timeslice_ms <<= 1; /* Double timeslice if we have to retry */ | |
| 845 | + if (migrate_try_count > 0 || !ctx.devmem_only) { | |
| 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 | 862 | if (err) { |
| 797 | 863 | range_debug(range, "PAGE FAULT - FAIL PAGE COLLECT"); |
| @@ -815,6 +881,7 @@ retry_bind: · 17 unmodified lines | ||
| 815 | 881 | drm_exec_fini(&exec); |
| 816 | 882 | err = PTR_ERR(fence); |
| 817 | 883 | if (err == -EAGAIN) { |
| 884 | + ctx.timeslice_ms <<= 1; /* Double timeslice if we have to retry */ | |
| 818 | 885 | range_debug(range, "PAGE FAULT - RETRY BIND"); |
| 819 | 886 | goto retry; |
| 820 | 887 | } |
| @@ -825,9 +892,6 @@ retry_bind: · 4 unmodified lines | ||
| 825 | 892 | } |
| 826 | 893 | drm_exec_fini(&exec); |
| 827 | 894 | |
| 828 | − if (xe_modparam.always_migrate_to_vram) | |
| 829 | − range->skip_migrate = false; | |
| 830 | − | |
| 831 | 895 | dma_fence_wait(fence, false); |
| 832 | 896 | dma_fence_put(fence); |
| 833 | 897 | |
| @@ -36,11 +36,6 @@ struct xe_svm_range { · 35 unmodified lines | ||
| 36 | 36 | * range. Protected by GPU SVM notifier lock. |
| 37 | 37 | */ |
| 38 | 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 | 41 | #if IS_ENABLED(CONFIG_DRM_GPUSVM) |
| @@ -19,12 +19,12 @@ · 18 unmodified lines | ||
| 19 | 19 | #define __dev_name_lrc(lrc) dev_name(gt_to_xe((lrc)->fence_ctx.gt)->drm.dev) |
| 20 | 20 | |
| 21 | 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 | 23 | TP_ARGS(lrc, old), |
| 24 | 24 | TP_STRUCT__entry( |
| 25 | 25 | __field(struct xe_lrc *, lrc) |
| 26 | − __field(u32, old) | |
| 27 | − __field(u32, new) | |
| 26 | + __field(u64, old) | |
| 27 | + __field(u64, new) | |
| 28 | 28 | __string(name, lrc->fence_ctx.name) |
| 29 | 29 | __string(device_id, __dev_name_lrc(lrc)) |
| 30 | 30 | ), |
| @@ -36,7 +36,7 @@ TRACE_EVENT(xe_lrc_update_timestamp, · 5 unmodified lines | ||
| 36 | 36 | __assign_str(name); |
| 37 | 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 | 40 | __entry->lrc, __get_str(name), |
| 41 | 41 | __entry->old, __entry->new, |
| 42 | 42 | __get_str(device_id)) |
| @@ -815,6 +815,10 @@ static const struct xe_rtp_entry_sr lrc_was[] = { · 814 unmodified lines | ||
| 815 | 815 | XE_RTP_RULES(GRAPHICS_VERSION(2001), ENGINE_CLASS(RENDER)), |
| 816 | 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 | 823 | /* Xe3_LPG */ |
| 820 | 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 | 83 | case ALS_IDX: |
| 84 | 84 | privdata->dev_en.is_als_present = false; |
| 85 | 85 | break; |
| 86 | + case SRA_IDX: | |
| 87 | + privdata->dev_en.is_sra_present = false; | |
| 88 | + break; | |
| 86 | 89 | } |
| 87 | 90 | |
| 88 | 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 | 137 | for (i = 0; i < cl_data->num_hid_devices; i++) { |
| 135 | 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 | 140 | if (cl_data->sensor_idx[i] == SRA_IDX) { |
| 141 | 141 | info.sensor_idx = cl_data->sensor_idx[i]; |
| 142 | 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 | 145 | (privdata, cl_data->sensor_idx[i], ENABLE_SENSOR); |
| 146 | 146 | |
| 147 | 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 | 150 | privdata->dev_en.is_sra_present = true; |
| 151 | + } | |
| 150 | 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 | 240 | cleanup: |
| 239 | 241 | amd_sfh_hid_client_deinit(privdata); |
| 240 | 242 | for (i = 0; i < cl_data->num_hid_devices; i++) { |
| 243 | + if (cl_data->sensor_idx[i] == SRA_IDX) | |
| 244 | + continue; | |
| 241 | 245 | devm_kfree(dev, cl_data->feature_report[i]); |
| 242 | 246 | devm_kfree(dev, in_data->input_report[i]); |
| 243 | 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 | 38 | struct hid_bpf_ops *e; |
| 39 | 39 | int ret; |
| 40 | 40 | |
| 41 | + if (unlikely(hdev->bpf.destroyed)) | |
| 42 | + return ERR_PTR(-ENODEV); | |
| 43 | + | |
| 41 | 44 | if (type >= HID_REPORT_TYPES) |
| 42 | 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 | 96 | struct hid_bpf_ops *e; |
| 94 | 97 | int ret, idx; |
| 95 | 98 | |
| 99 | + if (unlikely(hdev->bpf.destroyed)) | |
| 100 | + return -ENODEV; | |
| 101 | + | |
| 96 | 102 | if (rtype >= HID_REPORT_TYPES) |
| 97 | 103 | return -EINVAL; |
| 98 | 104 | |
| @@ -130,6 +136,9 @@ int dispatch_hid_bpf_output_report(struct hid_device *hdev, · 31 unmodified lines | ||
| 130 | 136 | struct hid_bpf_ops *e; |
| 131 | 137 | int ret, idx; |
| 132 | 138 | |
| 139 | + if (unlikely(hdev->bpf.destroyed)) | |
| 140 | + return -ENODEV; | |
| 141 | + | |
| 133 | 142 | idx = srcu_read_lock(&hdev->bpf.srcu); |
| 134 | 143 | list_for_each_entry_srcu(e, &hdev->bpf.prog_list, list, |
| 135 | 144 | srcu_read_lock_held(&hdev->bpf.srcu)) { |
| @@ -157,6 +157,7 @@ static const __u8 fixed_rdesc_vendor[] = { · 156 unmodified lines | ||
| 157 | 157 | ReportCount(5) // padding |
| 158 | 158 | Input(Const) |
| 159 | 159 | // Byte 4 in report - just exists so we get to be a tablet pad |
| 160 | + UsagePage_Digitizers | |
| 160 | 161 | Usage_Dig_BarrelSwitch // BTN_STYLUS |
| 161 | 162 | ReportCount(1) |
| 162 | 163 | ReportSize(1) |
| @@ -41,6 +41,10 @@ · 40 unmodified lines | ||
| 41 | 41 | #define USB_VENDOR_ID_ACTIONSTAR 0x2101 |
| 42 | 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 | 48 | #define USB_VENDOR_ID_ADS_TECH 0x06e1 |
| 45 | 49 | #define USB_DEVICE_ID_ADS_TECH_RADIO_SI470X 0xa155 |
| 46 | 50 | |
| @@ -27,6 +27,8 @@ · 26 unmodified lines | ||
| 27 | 27 | static const struct hid_device_id hid_quirks[] = { |
| 28 | 28 | { HID_USB_DEVICE(USB_VENDOR_ID_AASHIMA, USB_DEVICE_ID_AASHIMA_GAMEPAD), HID_QUIRK_BADPAD }, |
| 29 | 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 | 32 | { HID_USB_DEVICE(USB_VENDOR_ID_AFATECH, USB_DEVICE_ID_AFATECH_AF9016), HID_QUIRK_FULLSPEED_INTERVAL }, |
| 31 | 33 | { HID_USB_DEVICE(USB_VENDOR_ID_AIREN, USB_DEVICE_ID_AIREN_SLIMPLUS), HID_QUIRK_NOGET }, |
| 32 | 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 | 1150 | struct steam_device *steam = hdev->driver_data; |
| 1151 | 1151 | |
| 1152 | 1152 | unsigned long flags; |
| 1153 | − bool connected; | |
| 1154 | 1153 | |
| 1155 | 1154 | spin_lock_irqsave(&steam->lock, flags); |
| 1156 | 1155 | steam->client_opened--; |
| 1157 | − connected = steam->connected && !steam->client_opened; | |
| 1158 | 1156 | spin_unlock_irqrestore(&steam->lock, flags); |
| 1159 | 1157 | |
| 1160 | 1158 | schedule_work(&steam->unregister_work); |
| @@ -174,6 +174,7 @@ static void thrustmaster_interrupts(struct hid_device *hdev) · 173 unmodified lines | ||
| 174 | 174 | u8 ep_addr[2] = {b_ep, 0}; |
| 175 | 175 | |
| 176 | 176 | if (!usb_check_int_endpoints(usbif, ep_addr)) { |
| 177 | + kfree(send_buf); | |
| 177 | 178 | hid_err(hdev, "Unexpected non-int endpoint\n"); |
| 178 | 179 | return; |
| 179 | 180 | } |
| @@ -142,11 +142,12 @@ static int uclogic_input_configured(struct hid_device *hdev, · 141 unmodified lines | ||
| 142 | 142 | suffix = "System Control"; |
| 143 | 143 | break; |
| 144 | 144 | } |
| 145 | − } | |
| 146 | − | |
| 147 | − if (suffix) | |
| 145 | + } else { | |
| 148 | 146 | hi->input->name = devm_kasprintf(&hdev->dev, GFP_KERNEL, |
| 149 | 147 | "%s %s", hdev->name, suffix); |
| 148 | + if (!hi->input->name) | |
| 149 | + return -ENOMEM; | |
| 150 | + } | |
| 150 | 151 | |
| 151 | 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 | 71 | while (!kfifo_is_empty(fifo)) { |
| 72 | 72 | int size = kfifo_peek_len(fifo); |
| 73 | − u8 *buf = kzalloc(size, GFP_KERNEL); | |
| 73 | + u8 *buf; | |
| 74 | 74 | unsigned int count; |
| 75 | 75 | int err; |
| 76 | 76 | |
| 77 | + buf = kzalloc(size, GFP_KERNEL); | |
| 78 | + if (!buf) { | |
| 79 | + kfifo_skip(fifo); | |
| 80 | + continue; | |
| 81 | + } | |
| 82 | + | |
| 77 | 83 | count = kfifo_out(fifo, buf, size); |
| 78 | 84 | if (count != size) { |
| 79 | 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 | 87 | // to flush seems reasonable enough, however. |
| 82 | 88 | hid_warn(hdev, "%s: removed fifo entry with unexpected size\n", |
| 83 | 89 | __func__); |
| 90 | + kfree(buf); | |
| 84 | 91 | continue; |
| 85 | 92 | } |
| 86 | 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 | 2368 | unsigned int connect_mask = HID_CONNECT_HIDRAW; |
| 2362 | 2369 | |
| 2363 | 2370 | features->pktlen = wacom_compute_pktlen(hdev); |
| 2371 | + if (!features->pktlen) | |
| 2372 | + return -ENODEV; | |
| 2364 | 2373 | |
| 2365 | 2374 | if (!devres_open_group(&hdev->dev, wacom, GFP_KERNEL)) |
| 2366 | 2375 | return -ENOMEM; |
| @@ -1077,68 +1077,10 @@ int vmbus_sendpacket(struct vmbus_channel *channel, void *buffer, · 1076 unmodified lines | ||
| 1077 | 1077 | EXPORT_SYMBOL(vmbus_sendpacket); |
| 1078 | 1078 | |
| 1079 | 1079 | /* |
| 1080 | − * vmbus_sendpacket_pagebuffer - Send a range of single-page buffer | |
| 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 | |
| 1080 | + * vmbus_sendpacket_mpb_desc - Send one or more multi-page buffer packets | |
| 1140 | 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 | 1085 | int vmbus_sendpacket_mpb_desc(struct vmbus_channel *channel, |
| 1144 | 1086 | struct vmbus_packet_mpb_array *desc, |
| @@ -1160,7 +1102,6 @@ int vmbus_sendpacket_mpb_desc(struct vmbus_channel *channel, · 15 unmodified lines | ||
| 1160 | 1102 | desc->length8 = (u16)(packetlen_aligned >> 3); |
| 1161 | 1103 | desc->transactionid = VMBUS_RQST_ERROR; /* will be updated in hv_ringbuffer_write() */ |
| 1162 | 1104 | desc->reserved = 0; |
| 1163 | − desc->rangecount = 1; | |
| 1164 | 1105 | |
| 1165 | 1106 | bufferlist[0].iov_base = desc; |
| 1166 | 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 | 279 | if ((dev->flags & MODEL_MASK) == MODEL_AMD_NAVI_GPU) { |
| 280 | 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 | 283 | return dev_err_probe(device, PTR_ERR(dev->slave), |
| 283 | 284 | "register UCSI failed\n"); |
| 285 | + } | |
| 284 | 286 | } |
| 285 | 287 | |
| 286 | 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 | 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 | 1358 | ret = rdma_nl_notify_event(device, 0, RDMA_REGISTER_EVENT); |
| 1356 | 1359 | if (ret) |
| 1357 | 1360 | goto out; |
| @@ -1468,10 +1471,9 @@ int ib_register_device(struct ib_device *device, const char *name, · 110 unmodified lines | ||
| 1468 | 1471 | return ret; |
| 1469 | 1472 | } |
| 1470 | 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 | 1475 | ib_device_notify_register(device); |
| 1476 | + | |
| 1475 | 1477 | ib_device_put(device); |
| 1476 | 1478 | |
| 1477 | 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 | 221 | break; |
| 222 | 222 | |
| 223 | 223 | if (i < IRDMA_MIN_MSIX) { |
| 224 | − for (; i > 0; i--) | |
| 224 | + while (--i >= 0) | |
| 225 | 225 | ice_free_rdma_qvector(pf, &rf->msix_entries[i]); |
| 226 | 226 | |
| 227 | 227 | kfree(rf->msix_entries); |
| @@ -255,6 +255,8 @@ static void irdma_remove(struct auxiliary_device *aux_dev) · 27 unmodified lines | ||
| 255 | 255 | ice_rdma_update_vsi_filter(pf, iwdev->vsi_num, false); |
| 256 | 256 | irdma_deinit_interrupts(iwdev->rf, pf); |
| 257 | 257 | |
| 258 | + kfree(iwdev->rf); | |
| 259 | + | |
| 258 | 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 | 4872 | irdma_rt_deinit_hw(iwdev); |
| 4873 | 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 | 57 | err = do_mmap_info(rxe, uresp ? &uresp->mi : NULL, udata, |
| 58 | 58 | cq->queue->buf, cq->queue->buf_size, &cq->queue->ip); |
| 59 | − if (err) { | |
| 60 | − vfree(cq->queue->buf); | |
| 61 | − kfree(cq->queue); | |
| 59 | + if (err) | |
| 62 | 60 | return err; |
| 63 | − } | |
| 64 | 61 | |
| 65 | 62 | cq->is_user = uresp; |
| 66 | 63 | |
| @@ -252,7 +252,7 @@ static void __init gicv2m_teardown(void) · 251 unmodified lines | ||
| 252 | 252 | static struct msi_parent_ops gicv2m_msi_parent_ops = { |
| 253 | 253 | .supported_flags = GICV2M_MSI_FLAGS_SUPPORTED, |
| 254 | 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 | 256 | .bus_select_token = DOMAIN_BUS_NEXUS, |
| 257 | 257 | .bus_select_mask = MATCH_PCI_MSI | MATCH_PLATFORM_MSI, |
| 258 | 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 | 203 | const struct msi_parent_ops gic_v3_its_msi_parent_ops = { |
| 204 | 204 | .supported_flags = ITS_MSI_FLAGS_SUPPORTED, |
| 205 | 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 | 207 | .bus_select_token = DOMAIN_BUS_NEXUS, |
| 208 | 208 | .bus_select_mask = MATCH_PCI_MSI | MATCH_PLATFORM_MSI, |
| 209 | 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 | 197 | static const struct msi_parent_ops gic_v3_mbi_msi_parent_ops = { |
| 198 | 198 | .supported_flags = MBI_MSI_FLAGS_SUPPORTED, |
| 199 | 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 | 201 | .bus_select_token = DOMAIN_BUS_NEXUS, |
| 202 | 202 | .bus_select_mask = MATCH_PCI_MSI | MATCH_PLATFORM_MSI, |
| 203 | 203 | .prefix = "MBI-", |
| @@ -161,7 +161,7 @@ static const struct irq_domain_ops gicp_domain_ops = { · 160 unmodified lines | ||
| 161 | 161 | static const struct msi_parent_ops gicp_msi_parent_ops = { |
| 162 | 162 | .supported_flags = GICP_MSI_FLAGS_SUPPORTED, |
| 163 | 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 | 165 | .bus_select_token = DOMAIN_BUS_GENERIC_MSI, |
| 166 | 166 | .bus_select_mask = MATCH_PLATFORM_MSI, |
| 167 | 167 | .prefix = "GICP-", |
| @@ -157,7 +157,7 @@ static const struct irq_domain_ops odmi_domain_ops = { · 156 unmodified lines | ||
| 157 | 157 | static const struct msi_parent_ops odmi_msi_parent_ops = { |
| 158 | 158 | .supported_flags = ODMI_MSI_FLAGS_SUPPORTED, |
| 159 | 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 | 161 | .bus_select_token = DOMAIN_BUS_GENERIC_MSI, |
| 162 | 162 | .bus_select_mask = MATCH_PLATFORM_MSI, |
| 163 | 163 | .prefix = "ODMI-", |
| @@ -208,17 +208,17 @@ skip: · 207 unmodified lines | ||
| 208 | 208 | } |
| 209 | 209 | |
| 210 | 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 | 213 | lockdep_assert_held(&lpriv->lock); |
| 214 | 214 | |
| 215 | 215 | if (!timer_pending(&lpriv->timer)) { |
| 216 | 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 | 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 | 224 | #endif |
| @@ -233,7 +233,7 @@ void imsic_local_sync_all(bool force_all) · 8 unmodified lines | ||
| 233 | 233 | if (force_all) |
| 234 | 234 | bitmap_fill(lpriv->dirty_bitmap, imsic->global.nr_ids + 1); |
| 235 | 235 | if (!__imsic_local_sync(lpriv)) |
| 236 | − __imsic_local_timer_start(lpriv); | |
| 236 | + __imsic_local_timer_start(lpriv, smp_processor_id()); | |
| 237 | 237 | |
| 238 | 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 | 278 | return; |
| 279 | 279 | } |
| 280 | 280 | |
| 281 | − __imsic_local_timer_start(lpriv); | |
| 281 | + __imsic_local_timer_start(lpriv, cpu); | |
| 282 | 282 | } |
| 283 | 283 | } |
| 284 | 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 | 349 | static void b53_set_forwarding(struct b53_device *dev, int enable) |
| 330 | 350 | { |
| 331 | 351 | u8 mgmt; |
| @@ -586,6 +606,13 @@ int b53_setup_port(struct dsa_switch *ds, int port) · 254 unmodified lines | ||
| 586 | 606 | b53_port_set_mcast_flood(dev, port, true); |
| 587 | 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 | 616 | return 0; |
| 590 | 617 | } |
| 591 | 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 | 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 | 2075 | /* Configure the local port VLAN control membership to include |
| 2046 | 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 | 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 | 2113 | b53_write16(dev, B53_PVLAN_PAGE, B53_PVLAN_PORT_MASK(port), pvlan); |
| 2081 | 2114 | dev->ports[port].vlan_ctl_mask = pvlan; |
| 2082 | 2115 | |
| @@ -50,6 +50,9 @@ · 49 unmodified lines | ||
| 50 | 50 | /* Jumbo Frame Registers */ |
| 51 | 51 | #define B53_JUMBO_PAGE 0x40 |
| 52 | 52 | |
| 53 | +/* EAP Registers */ | |
| 54 | +#define B53_EAP_PAGE 0x42 | |
| 55 | + | |
| 53 | 56 | /* EEE Control Registers Page */ |
| 54 | 57 | #define B53_EEE_PAGE 0x92 |
| 55 | 58 | |
| @@ -480,6 +483,17 @@ · 424 unmodified lines | ||
| 480 | 483 | #define JMS_MIN_SIZE 1518 |
| 481 | 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 | 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 | 265 | unsigned int mode, |
| 266 | 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 | 318 | static const struct phylink_mac_ops ksz88x3_phylink_mac_ops = { |
| 269 | 319 | .mac_config = ksz88x3_phylink_mac_config, |
| 270 | 320 | .mac_link_down = ksz_phylink_mac_link_down, |
| 271 | 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 | 326 | static const struct phylink_mac_ops ksz8_phylink_mac_ops = { |
| 275 | 327 | .mac_config = ksz_phylink_mac_config, |
| 276 | 328 | .mac_link_down = ksz_phylink_mac_link_down, |
| 277 | 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 | 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 | 412 | .mac_config = ksz_phylink_mac_config, |
| 359 | 413 | .mac_link_down = ksz_phylink_mac_link_down, |
| 360 | 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 | 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 | 457 | .mac_config = ksz_phylink_mac_config, |
| 402 | 458 | .mac_link_down = ksz_phylink_mac_link_down, |
| 403 | 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 | 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 | 2075 | if (dev->dev_ops->get_caps) |
| 2018 | 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 | 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 | 3078 | if (!port) |
| 3009 | 3079 | return MICREL_KSZ8_P1_ERRATA; |
| 3010 | 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 | 3083 | return 0; |
| @@ -3466,6 +3511,20 @@ static int ksz_max_mtu(struct dsa_switch *ds, int port) · 427 unmodified lines | ||
| 3466 | 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 | 3528 | static bool ksz_support_eee(struct dsa_switch *ds, int port) |
| 3470 | 3529 | { |
| 3471 | 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 | 3535 | switch (dev->chip_id) { |
| 3477 | 3536 | case KSZ8563_CHIP_ID: |
| 3537 | + case KSZ9563_CHIP_ID: | |
| 3538 | + case KSZ9893_CHIP_ID: | |
| 3539 | + return true; | |
| 3478 | 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 | 3546 | case KSZ9477_CHIP_ID: |
| 3480 | − case KSZ9563_CHIP_ID: | |
| 3547 | + /* KSZ9477S Errata DS80000754A Module 4 */ | |
| 3481 | 3548 | case KSZ9567_CHIP_ID: |
| 3482 | − case KSZ9893_CHIP_ID: | |
| 3549 | + /* KSZ9567S Errata DS80000756A Module 4 */ | |
| 3483 | 3550 | case KSZ9896_CHIP_ID: |
| 3551 | + /* KSZ9896C Errata DS80000757A Module 3 */ | |
| 3484 | 3552 | case KSZ9897_CHIP_ID: |
| 3485 | 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 | 3568 | return false; |
| @@ -2081,6 +2081,7 @@ static void sja1105_bridge_stp_state_set(struct dsa_switch *ds, int port, · 2080 unmodified lines | ||
| 2081 | 2081 | switch (state) { |
| 2082 | 2082 | case BR_STATE_DISABLED: |
| 2083 | 2083 | case BR_STATE_BLOCKING: |
| 2084 | + case BR_STATE_LISTENING: | |
| 2084 | 2085 | /* From UM10944 description of DRPDTAG (why put this there?): |
| 2085 | 2086 | * "Management traffic flows to the port regardless of the state |
| 2086 | 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 | 2091 | mac[port].egress = false; |
| 2091 | 2092 | mac[port].dyn_learn = false; |
| 2092 | 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 | 2094 | case BR_STATE_LEARNING: |
| 2099 | 2095 | mac[port].ingress = true; |
| 2100 | 2096 | mac[port].egress = false; |
| @@ -14013,13 +14013,28 @@ static void bnxt_unlock_sp(struct bnxt *bp) · 14012 unmodified lines | ||
| 14013 | 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 | 14031 | /* Only called from bnxt_sp_task() */ |
| 14017 | 14032 | static void bnxt_reset(struct bnxt *bp, bool silent) |
| 14018 | 14033 | { |
| 14019 | − bnxt_lock_sp(bp); | |
| 14034 | + bnxt_rtnl_lock_sp(bp); | |
| 14020 | 14035 | if (test_bit(BNXT_STATE_OPEN, &bp->state)) |
| 14021 | 14036 | bnxt_reset_task(bp, silent); |
| 14022 | − bnxt_unlock_sp(bp); | |
| 14037 | + bnxt_rtnl_unlock_sp(bp); | |
| 14023 | 14038 | } |
| 14024 | 14039 | |
| 14025 | 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 | 14043 | int i; |
| 14029 | 14044 | |
| 14030 | − bnxt_lock_sp(bp); | |
| 14045 | + bnxt_rtnl_lock_sp(bp); | |
| 14031 | 14046 | if (!test_bit(BNXT_STATE_OPEN, &bp->state)) { |
| 14032 | − bnxt_unlock_sp(bp); | |
| 14047 | + bnxt_rtnl_unlock_sp(bp); | |
| 14033 | 14048 | return; |
| 14034 | 14049 | } |
| 14035 | 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 | 14084 | if (bp->flags & BNXT_FLAG_TPA) |
| 14070 | 14085 | bnxt_set_tpa(bp, true); |
| 14071 | − bnxt_unlock_sp(bp); | |
| 14086 | + bnxt_rtnl_unlock_sp(bp); | |
| 14072 | 14087 | } |
| 14073 | 14088 | |
| 14074 | 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 | 14975 | bp->fw_reset_state = BNXT_FW_RESET_STATE_OPENING; |
| 14961 | 14976 | fallthrough; |
| 14962 | 14977 | case BNXT_FW_RESET_STATE_OPENING: |
| 14963 | − while (!netdev_trylock(bp->dev)) { | |
| 14978 | + while (!rtnl_trylock()) { | |
| 14964 | 14979 | bnxt_queue_fw_reset_work(bp, HZ / 10); |
| 14965 | 14980 | return; |
| 14966 | 14981 | } |
| 14982 | + netdev_lock(bp->dev); | |
| 14967 | 14983 | rc = bnxt_open(bp->dev); |
| 14968 | 14984 | if (rc) { |
| 14969 | 14985 | netdev_err(bp->dev, "bnxt_open() failed during FW reset\n"); |
| 14970 | 14986 | bnxt_fw_reset_abort(bp, rc); |
| 14971 | 14987 | netdev_unlock(bp->dev); |
| 14988 | + rtnl_unlock(); | |
| 14972 | 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 | 15005 | bnxt_dl_health_fw_status_update(bp, true); |
| 14989 | 15006 | } |
| 14990 | 15007 | netdev_unlock(bp->dev); |
| 15008 | + rtnl_unlock(); | |
| 14991 | 15009 | bnxt_ulp_start(bp, 0); |
| 14992 | 15010 | bnxt_reenable_sriov(bp); |
| 14993 | 15011 | netdev_lock(bp->dev); |
| @@ -15936,7 +15954,7 @@ err_reset: · 942 unmodified lines | ||
| 15936 | 15954 | rc); |
| 15937 | 15955 | napi_enable_locked(&bnapi->napi); |
| 15938 | 15956 | bnxt_db_nq_arm(bp, &cpr->cp_db, cpr->cp_raw_cons); |
| 15939 | − bnxt_reset_task(bp, true); | |
| 15957 | + netif_close(dev); | |
| 15940 | 15958 | return rc; |
| 15941 | 15959 | } |
| 15942 | 15960 | |
| @@ -16752,6 +16770,7 @@ static int bnxt_resume(struct device *device) · 809 unmodified lines | ||
| 16752 | 16770 | struct bnxt *bp = netdev_priv(dev); |
| 16753 | 16771 | int rc = 0; |
| 16754 | 16772 | |
| 16773 | + rtnl_lock(); | |
| 16755 | 16774 | netdev_lock(dev); |
| 16756 | 16775 | rc = pci_enable_device(bp->pdev); |
| 16757 | 16776 | if (rc) { |
| @@ -16796,6 +16815,7 @@ static int bnxt_resume(struct device *device) · 38 unmodified lines | ||
| 16796 | 16815 | |
| 16797 | 16816 | resume_exit: |
| 16798 | 16817 | netdev_unlock(bp->dev); |
| 16818 | + rtnl_unlock(); | |
| 16799 | 16819 | bnxt_ulp_start(bp, rc); |
| 16800 | 16820 | if (!rc) |
| 16801 | 16821 | bnxt_reenable_sriov(bp); |
| @@ -16961,6 +16981,7 @@ static void bnxt_io_resume(struct pci_dev *pdev) · 159 unmodified lines | ||
| 16961 | 16981 | int err; |
| 16962 | 16982 | |
| 16963 | 16983 | netdev_info(bp->dev, "PCI Slot Resume\n"); |
| 16984 | + rtnl_lock(); | |
| 16964 | 16985 | netdev_lock(netdev); |
| 16965 | 16986 | |
| 16966 | 16987 | err = bnxt_hwrm_func_qcaps(bp); |
| @@ -16978,6 +16999,7 @@ static void bnxt_io_resume(struct pci_dev *pdev) · 11 unmodified lines | ||
| 16978 | 16999 | netif_device_attach(netdev); |
| 16979 | 17000 | |
| 16980 | 17001 | netdev_unlock(netdev); |
| 17002 | + rtnl_unlock(); | |
| 16981 | 17003 | bnxt_ulp_start(bp, err); |
| 16982 | 17004 | if (!err) |
| 16983 | 17005 | bnxt_reenable_sriov(bp); |
| @@ -997,22 +997,15 @@ static void macb_update_stats(struct macb *bp) · 996 unmodified lines | ||
| 997 | 997 | |
| 998 | 998 | static int macb_halt_tx(struct macb *bp) |
| 999 | 999 | { |
| 1000 | − unsigned long halt_time, timeout; | |
| 1001 | − u32 status; | |
| 1000 | + u32 status; | |
| 1002 | 1001 | |
| 1003 | 1002 | macb_writel(bp, NCR, macb_readl(bp, NCR) | MACB_BIT(THALT)); |
| 1004 | 1003 | |
| 1005 | − timeout = jiffies + usecs_to_jiffies(MACB_HALT_TIMEOUT); | |
| 1006 | − do { | |
| 1007 | − halt_time = jiffies; | |
| 1008 | − status = macb_readl(bp, TSR); | |
| 1009 | − if (!(status & MACB_BIT(TGO))) | |
| 1010 | − return 0; | |
| 1011 | − | |
| 1012 | − udelay(250); | |
| 1013 | − } while (time_before(halt_time, timeout)); | |
| 1014 | − | |
| 1015 | − return -ETIMEDOUT; | |
| 1004 | + /* Poll TSR until TGO is cleared or timeout. */ | |
| 1005 | + return read_poll_timeout_atomic(macb_readl, status, | |
| 1006 | + !(status & MACB_BIT(TGO)), | |
| 1007 | + 250, MACB_HALT_TIMEOUT, false, | |
| 1008 | + bp, TSR); | |
| 1016 | 1009 | } |
| 1017 | 1010 | |
| 1018 | 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 | 67 | #define TSNEP_TX_TYPE_XDP_NDO_MAP_PAGE (TSNEP_TX_TYPE_XDP_NDO | TSNEP_TX_TYPE_MAP_PAGE) |
| 68 | 68 | #define TSNEP_TX_TYPE_XDP (TSNEP_TX_TYPE_XDP_TX | TSNEP_TX_TYPE_XDP_NDO) |
| 69 | 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 | 73 | #define TSNEP_XDP_TX BIT(0) |
| 72 | 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 | 388 | if (entry->skb) { |
| 387 | 389 | entry->properties = length & TSNEP_DESC_LENGTH_MASK; |
| 388 | 390 | entry->properties |= TSNEP_DESC_INTERRUPT_FLAG; |
| 389 | − if ((entry->type & TSNEP_TX_TYPE_SKB) && | |
| 390 | − (skb_shinfo(entry->skb)->tx_flags & SKBTX_IN_PROGRESS)) | |
| 391 | + if ((entry->type & TSNEP_TX_TYPE_SKB_TSTAMP) == TSNEP_TX_TYPE_SKB_TSTAMP) | |
| 391 | 392 | entry->properties |= TSNEP_DESC_EXTENDED_WRITEBACK_FLAG; |
| 392 | 393 | |
| 393 | 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 | 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 | 486 | struct device *dmadev = tx->adapter->dmadev; |
| 485 | 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 | 507 | entry->type = TSNEP_TX_TYPE_SKB_INLINE; |
| 506 | 508 | mapped = 0; |
| 507 | 509 | } |
| 510 | + | |
| 511 | + if (do_tstamp) | |
| 512 | + entry->type |= TSNEP_TX_TYPE_TSTAMP; | |
| 508 | 513 | } else { |
| 509 | 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 | 563 | static netdev_tx_t tsnep_xmit_frame_ring(struct sk_buff *skb, |
| 559 | 564 | struct tsnep_tx *tx) |
| 560 | 565 | { |
| 561 | − int count = 1; | |
| 562 | 566 | struct tsnep_tx_entry *entry; |
| 567 | + bool do_tstamp = false; | |
| 568 | + int count = 1; | |
| 563 | 569 | int length; |
| 564 | − int i; | |
| 565 | 570 | int retval; |
| 571 | + int i; | |
| 566 | 572 | |
| 567 | 573 | if (skb_shinfo(skb)->nr_frags > 0) |
| 568 | 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 | 585 | entry = &tx->entry[tx->write]; |
| 580 | 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 | 595 | if (retval < 0) { |
| 584 | 596 | tsnep_tx_unmap(tx, tx->write, count); |
| 585 | 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 | 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 | 606 | for (i = 0; i < count; i++) |
| 598 | 607 | tsnep_tx_activate(tx, (tx->write + i) & TSNEP_RING_MASK, length, |
| 599 | 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 | 854 | length = tsnep_tx_unmap(tx, tx->read, count); |
| 846 | 855 | |
| 847 | − if ((entry->type & TSNEP_TX_TYPE_SKB) && | |
| 848 | − (skb_shinfo(entry->skb)->tx_flags & SKBTX_IN_PROGRESS) && | |
| 856 | + if (((entry->type & TSNEP_TX_TYPE_SKB_TSTAMP) == TSNEP_TX_TYPE_SKB_TSTAMP) && | |
| 849 | 857 | (__le32_to_cpu(entry->desc_wb->properties) & |
| 850 | 858 | TSNEP_DESC_EXTENDED_WRITEBACK_FLAG)) { |
| 851 | 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 | 718 | if (!is_lmac_valid(cgx, lmac_id)) |
| 719 | 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 | 725 | *rx_stat = cgx_read(cgx, lmac_id, CGXX_CMRX_RX_STAT0 + (idx * 8)); |
| 721 | 726 | return 0; |
| 722 | 727 | } |
| @@ -531,7 +531,8 @@ static int cn10k_mcs_write_tx_secy(struct otx2_nic *pfvf, · 530 unmodified lines | ||
| 531 | 531 | if (sw_tx_sc->encrypt) |
| 532 | 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 | 536 | /* Write SecTag excluding AN bits(1..0) */ |
| 536 | 537 | policy |= FIELD_PREP(MCS_TX_SECY_PLCY_ST_TCI, sectag_tci >> 2); |
| 537 | 538 | policy |= FIELD_PREP(MCS_TX_SECY_PLCY_ST_OFFSET, tag_offset); |
| @@ -356,6 +356,7 @@ struct otx2_flow_config { · 355 unmodified lines | ||
| 356 | 356 | struct list_head flow_list_tc; |
| 357 | 357 | u8 ucast_flt_cnt; |
| 358 | 358 | bool ntuple; |
| 359 | + u16 ntuple_cnt; | |
| 359 | 360 | }; |
| 360 | 361 | |
| 361 | 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 | 41 | if (!pfvf->flow_cfg) |
| 42 | 42 | return 0; |
| 43 | 43 | |
| 44 | + pfvf->flow_cfg->ntuple_cnt = ctx->val.vu16; | |
| 44 | 45 | otx2_alloc_mcam_entries(pfvf, ctx->val.vu16); |
| 45 | 46 | |
| 46 | 47 | return 0; |
| @@ -315,7 +315,7 @@ static void otx2_get_pauseparam(struct net_device *netdev, · 314 unmodified lines | ||
| 315 | 315 | struct otx2_nic *pfvf = netdev_priv(netdev); |
| 316 | 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 | 319 | return; |
| 320 | 320 | |
| 321 | 321 | mutex_lock(&pfvf->mbox.lock); |
| @@ -347,7 +347,7 @@ static int otx2_set_pauseparam(struct net_device *netdev, · 25 unmodified lines | ||
| 347 | 347 | if (pause->autoneg) |
| 348 | 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 | 351 | return -EOPNOTSUPP; |
| 352 | 352 | |
| 353 | 353 | if (pause->rx_pause) |
| @@ -941,8 +941,8 @@ static u32 otx2_get_link(struct net_device *netdev) · 587 unmodified lines | ||
| 941 | 941 | { |
| 942 | 942 | struct otx2_nic *pfvf = netdev_priv(netdev); |
| 943 | 943 | |
| 944 | − /* LBK link is internal and always UP */ | |
| 945 | − if (is_otx2_lbkvf(pfvf->pdev)) | |
| 944 | + /* LBK and SDP links are internal and always UP */ | |
| 945 | + if (is_otx2_lbkvf(pfvf->pdev) || is_otx2_sdp_rep(pfvf->pdev)) | |
| 946 | 946 | return 1; |
| 947 | 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 | 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 | 1417 | cmd->base.duplex = DUPLEX_FULL; |
| 1418 | 1418 | cmd->base.speed = SPEED_100000; |
| 1419 | 1419 | } else { |
| @@ -247,7 +247,7 @@ int otx2_mcam_entry_init(struct otx2_nic *pfvf) · 246 unmodified lines | ||
| 247 | 247 | mutex_unlock(&pfvf->mbox.lock); |
| 248 | 248 | |
| 249 | 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 | 251 | if (count <= 0) { |
| 252 | 252 | otx2_clear_ntuple_flow_info(pfvf, flow_cfg); |
| 253 | 253 | return 0; |
| @@ -307,6 +307,7 @@ int otx2_mcam_flow_init(struct otx2_nic *pf) · 53 unmodified lines | ||
| 307 | 307 | INIT_LIST_HEAD(&pf->flow_cfg->flow_list_tc); |
| 308 | 308 | |
| 309 | 309 | pf->flow_cfg->ucast_flt_cnt = OTX2_DEFAULT_UNICAST_FLOWS; |
| 310 | + pf->flow_cfg->ntuple_cnt = OTX2_DEFAULT_FLOWCOUNT; | |
| 310 | 311 | |
| 311 | 312 | /* Allocate bare minimum number of MCAM entries needed for |
| 312 | 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 | 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 | 4752 | id == MTK_GMAC1_ID) { |
| 4753 | 4753 | mac->phylink_config.mac_capabilities = MAC_ASYM_PAUSE | |
| 4754 | 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 | 4349 | if (netdev->features & NETIF_F_HW_VLAN_CTAG_FILTER) |
| 4350 | 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 | 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 | 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 | 3020 | neigh_for_each(&arp_tbl, mlxsw_sp_neigh_rif_made_sync_each, &rms); |
| 3018 | 3021 | if (rms.err) |
| 3019 | 3022 | goto err_arp; |
| @@ -203,7 +203,7 @@ static struct pci_driver qede_pci_driver = { · 202 unmodified lines | ||
| 203 | 203 | }; |
| 204 | 204 | |
| 205 | 205 | static struct qed_eth_cb_ops qede_ll_ops = { |
| 206 | − { | |
| 206 | + .common = { | |
| 207 | 207 | #ifdef CONFIG_RFS_ACCEL |
| 208 | 208 | .arfs_filter_op = qede_arfs_filter_op, |
| 209 | 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 | 1486 | cmd_op = (cmd.rsp.arg[0] & 0xff); |
| 1487 | − if (cmd.rsp.arg[0] >> 25 == 2) | |
| 1488 | − return 2; | |
| 1487 | + if (cmd.rsp.arg[0] >> 25 == 2) { | |
| 1488 | + ret = 2; | |
| 1489 | + goto out; | |
| 1490 | + } | |
| 1491 | + | |
| 1489 | 1492 | if (cmd_op == QLCNIC_BC_CMD_CHANNEL_INIT) |
| 1490 | 1493 | set_bit(QLC_BC_VF_STATE, &vf->state); |
| 1491 | 1494 | else |
| @@ -434,14 +434,20 @@ static int wx_host_interface_command_r(struct wx *wx, u32 *buffer, · 433 unmodified lines | ||
| 434 | 434 | wr32m(wx, WX_SW2FW_MBOX_CMD, WX_SW2FW_MBOX_CMD_VLD, WX_SW2FW_MBOX_CMD_VLD); |
| 435 | 435 | |
| 436 | 436 | /* polling reply from FW */ |
| 437 | − err = read_poll_timeout(wx_poll_fw_reply, reply, reply, 1000, 50000, | |
| 438 | − true, wx, buffer, send_cmd); | |
| 437 | + err = read_poll_timeout(wx_poll_fw_reply, reply, reply, 2000, | |
| 438 | + timeout * 1000, true, wx, buffer, send_cmd); | |
| 439 | 439 | if (err) { |
| 440 | 440 | wx_err(wx, "Polling from FW messages timeout, cmd: 0x%x, index: %d\n", |
| 441 | 441 | send_cmd, wx->swfw_index); |
| 442 | 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 | 451 | /* expect no reply from FW then return */ |
| 446 | 452 | if (!return_data) |
| 447 | 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 | 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 | 108 | if (i != wx->eeprom.sw_region_offset + TXGBE_EEPROM_CHECKSUM) |
| 104 | 109 | *checksum += local_buffer[i]; |
| 110 | + } | |
| 105 | 111 | |
| 106 | 112 | kvfree(eeprom_ptrs); |
| 107 | 113 | |
| @@ -158,6 +158,8 @@ · 157 unmodified lines | ||
| 158 | 158 | #define TXGBE_EEPROM_VERSION_L 0x1D |
| 159 | 159 | #define TXGBE_EEPROM_VERSION_H 0x1E |
| 160 | 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 | 164 | #define TXGBE_MAX_MSIX_VECTORS 64 |
| 163 | 165 | #define TXGBE_MAX_FDIR_INDICES 63 |
| @@ -158,7 +158,6 @@ struct hv_netvsc_packet { · 157 unmodified lines | ||
| 158 | 158 | u8 cp_partial; /* partial copy into send buffer */ |
| 159 | 159 | |
| 160 | 160 | u8 rmsg_size; /* RNDIS header and PPI size */ |
| 161 | − u8 rmsg_pgcnt; /* page count of RNDIS header and PPI */ | |
| 162 | 161 | u8 page_buf_cnt; |
| 163 | 162 | |
| 164 | 163 | u16 q_idx; |
| @@ -893,6 +892,18 @@ struct nvsp_message { · 728 unmodified lines | ||
| 893 | 892 | sizeof(struct nvsp_message)) |
| 894 | 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 | 907 | /* Estimated requestor size: |
| 897 | 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 | 953 | + pend_size; |
| 954 | 954 | int i; |
| 955 | 955 | u32 padding = 0; |
| 956 | − u32 page_count = packet->cp_partial ? packet->rmsg_pgcnt : | |
| 957 | − packet->page_buf_cnt; | |
| 956 | + u32 page_count = packet->cp_partial ? 1 : packet->page_buf_cnt; | |
| 958 | 957 | u32 remain; |
| 959 | 958 | |
| 960 | 959 | /* Add padding */ |
| @@ -1055,6 +1054,42 @@ static int netvsc_dma_map(struct hv_device *hv_dev, · 94 unmodified lines | ||
| 1055 | 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 | 1093 | static inline int netvsc_send_pkt( |
| 1059 | 1094 | struct hv_device *device, |
| 1060 | 1095 | struct hv_netvsc_packet *packet, |
| @@ -1097,8 +1132,11 @@ static inline int netvsc_send_pkt( · 36 unmodified lines | ||
| 1097 | 1132 | |
| 1098 | 1133 | packet->dma_range = NULL; |
| 1099 | 1134 | if (packet->page_buf_cnt) { |
| 1135 | + struct vmbus_channel_packet_page_buffer desc; | |
| 1136 | + u32 desc_size; | |
| 1137 | + | |
| 1100 | 1138 | if (packet->cp_partial) |
| 1101 | − pb += packet->rmsg_pgcnt; | |
| 1139 | + pb++; | |
| 1102 | 1140 | |
| 1103 | 1141 | ret = netvsc_dma_map(ndev_ctx->device_ctx, packet, pb); |
| 1104 | 1142 | if (ret) { |
| @@ -1106,11 +1144,12 @@ static inline int netvsc_send_pkt( · 1 unmodified line | ||
| 1106 | 1144 | goto exit; |
| 1107 | 1145 | } |
| 1108 | 1146 | |
| 1109 | − ret = vmbus_sendpacket_pagebuffer(out_channel, | |
| 1110 | − pb, packet->page_buf_cnt, | |
| 1111 | − &nvmsg, sizeof(nvmsg), | |
| 1112 | − req_id); | |
| 1113 | − | |
| 1147 | + netvsc_build_mpb_array(pb, packet->page_buf_cnt, | |
| 1148 | + (struct vmbus_packet_mpb_array *)&desc, | |
| 1149 | + &desc_size); | |
| 1150 | + ret = vmbus_sendpacket_mpb_desc(out_channel, | |
| 1151 | + (struct vmbus_packet_mpb_array *)&desc, | |
| 1152 | + desc_size, &nvmsg, sizeof(nvmsg), req_id); | |
| 1114 | 1153 | if (ret) |
| 1115 | 1154 | netvsc_dma_unmap(ndev_ctx->device_ctx, packet); |
| 1116 | 1155 | } else { |
| @@ -1259,7 +1298,7 @@ int netvsc_send(struct net_device *ndev, · 142 unmodified lines | ||
| 1259 | 1298 | packet->send_buf_index = section_index; |
| 1260 | 1299 | |
| 1261 | 1300 | if (packet->cp_partial) { |
| 1262 | − packet->page_buf_cnt -= packet->rmsg_pgcnt; | |
| 1301 | + packet->page_buf_cnt--; | |
| 1263 | 1302 | packet->total_data_buflen = msd_len + packet->rmsg_size; |
| 1264 | 1303 | } else { |
| 1265 | 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 | 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 | 329 | static u32 init_page_array(void *hdr, u32 len, struct sk_buff *skb, |
| 361 | 330 | struct hv_netvsc_packet *packet, |
| 362 | 331 | struct hv_page_buffer *pb) |
| 363 | 332 | { |
| 364 | − u32 slots_used = 0; | |
| 365 | − char *data = skb->data; | |
| 366 | 333 | int frags = skb_shinfo(skb)->nr_frags; |
| 367 | 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 | 338 | * 2. skb linear data |
| 372 | 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 | 345 | packet->rmsg_size = len; |
| 380 | − packet->rmsg_pgcnt = slots_used; | |
| 381 | 346 | |
| 382 | − slots_used += fill_pg_buf(virt_to_hvpfn(data), | |
| 383 | − offset_in_hvpage(data), | |
| 384 | − skb_headlen(skb), | |
| 385 | − &pb[slots_used]); | |
| 347 | + pb[1].offset = offset_in_hvpage(skb->data); | |
| 348 | + pb[1].len = skb_headlen(skb); | |
| 349 | + pb[1].pfn = virt_to_hvpfn(skb->data); | |
| 386 | 350 | |
| 387 | 351 | for (i = 0; i < frags; i++) { |
| 388 | 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)), | |
| 391 | − skb_frag_off(frag), | |
| 392 | − skb_frag_size(frag), | |
| 393 | − &pb[slots_used]); | |
| 357 | + cur_pb->offset = offset_in_hvpage(offset); | |
| 358 | + cur_pb->len = skb_frag_size(frag); | |
| 359 | + cur_pb->pfn = pfn + (offset >> HV_HYP_PAGE_SHIFT); | |
| 394 | 360 | } |
| 395 | − return slots_used; | |
| 361 | + return frags + 2; | |
| 396 | 362 | } |
| 397 | 363 | |
| 398 | 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 | 449 | struct net_device *vf_netdev; |
| 484 | 450 | u32 rndis_msg_size; |
| 485 | 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 | 454 | /* If VF is present and up then redirect packets to it. |
| 489 | 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 | 225 | struct rndis_request *req) |
| 226 | 226 | { |
| 227 | 227 | struct hv_netvsc_packet *packet; |
| 228 | − struct hv_page_buffer page_buf[2]; | |
| 229 | − struct hv_page_buffer *pb = page_buf; | |
| 228 | + struct hv_page_buffer pb; | |
| 230 | 229 | int ret; |
| 231 | 230 | |
| 232 | 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 | 234 | packet->total_data_buflen = req->request_msg.msg_len; |
| 236 | 235 | packet->page_buf_cnt = 1; |
| 237 | 236 | |
| 238 | − pb[0].pfn = virt_to_phys(&req->request_msg) >> | |
| 239 | − HV_HYP_PAGE_SHIFT; | |
| 240 | − pb[0].len = req->request_msg.msg_len; | |
| 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 | − } | |
| 237 | + pb.pfn = virt_to_phys(&req->request_msg) >> HV_HYP_PAGE_SHIFT; | |
| 238 | + pb.len = req->request_msg.msg_len; | |
| 239 | + pb.offset = offset_in_hvpage(&req->request_msg); | |
| 254 | 240 | |
| 255 | 241 | trace_rndis_send(dev->ndev, 0, &req->request_msg); |
| 256 | 242 | |
| 257 | 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 | 245 | rcu_read_unlock_bh(); |
| 260 | 246 | |
| 261 | 247 | return ret; |
| @@ -2027,12 +2027,6 @@ static int ksz9477_config_init(struct phy_device *phydev) · 2026 unmodified lines | ||
| 2027 | 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 | 2030 | return kszphy_config_init(phydev); |
| 2037 | 2031 | } |
| 2038 | 2032 | |
| @@ -5705,7 +5699,6 @@ static struct phy_driver ksphy_driver[] = { · 3666 unmodified lines | ||
| 5705 | 5699 | .handle_interrupt = kszphy_handle_interrupt, |
| 5706 | 5700 | .suspend = genphy_suspend, |
| 5707 | 5701 | .resume = ksz9477_resume, |
| 5708 | − .get_features = ksz9477_get_features, | |
| 5709 | 5702 | } }; |
| 5710 | 5703 | |
| 5711 | 5704 | module_phy_driver(ksphy_driver); |
| @@ -1011,6 +1011,7 @@ void mt76_dma_cleanup(struct mt76_dev *dev) · 1010 unmodified lines | ||
| 1011 | 1011 | int i; |
| 1012 | 1012 | |
| 1013 | 1013 | mt76_worker_disable(&dev->tx_worker); |
| 1014 | + napi_disable(&dev->tx_napi); | |
| 1014 | 1015 | netif_napi_del(&dev->tx_napi); |
| 1015 | 1016 | |
| 1016 | 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 | 1924 | mt7925_mcu_sta_mld_tlv(skb, info->vif, info->link_sta->sta); |
| 1925 | 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 | 1929 | if (!info->enable) { |
| 1932 | 1930 | mt7925_mcu_sta_remove_tlv(skb); |
| 1933 | 1931 | mt76_connac_mcu_add_tlv(skb, STA_REC_MLD_OFF, |
| 1934 | 1932 | sizeof(struct tlv)); |
| 1933 | + } else { | |
| 1934 | + mt7925_mcu_sta_hdr_trans_tlv(skb, info->vif, info->link_sta); | |
| 1935 | 1935 | } |
| 1936 | 1936 | |
| 1937 | 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 | 2059 | if (id->nsfeat & NVME_NS_FEAT_ATOMICS && id->nawupf) |
| 2060 | 2060 | atomic_bs = (1 + le16_to_cpu(id->nawupf)) * bs; |
| 2061 | 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 | 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 | 2215 | nvme_set_chunk_sectors(ns, id, &lim); |
| 2202 | 2216 | if (!nvme_update_disk_info(ns, id, &lim)) |
| 2203 | 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 | 2229 | nvme_config_discard(ns, &lim); |
| 2205 | 2230 | if (IS_ENABLED(CONFIG_BLK_DEV_ZONED) && |
| 2206 | 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 | 3056 | kfree(subsys); |
| 3032 | 3057 | return -EINVAL; |
| 3033 | 3058 | } |
| 3034 | − subsys->awupf = le16_to_cpu(id->awupf); | |
| 3035 | 3059 | nvme_mpath_default_iopolicy(subsys); |
| 3036 | 3060 | |
| 3037 | 3061 | subsys->dev.class = &nvme_subsys_class; |
| @@ -3441,7 +3465,7 @@ static int nvme_init_identify(struct nvme_ctrl *ctrl) · 403 unmodified lines | ||
| 3441 | 3465 | dev_pm_qos_expose_latency_tolerance(ctrl->device); |
| 3442 | 3466 | else if (!ctrl->apst_enabled && prev_apst_enabled) |
| 3443 | 3467 | dev_pm_qos_hide_latency_tolerance(ctrl->device); |
| 3444 | − | |
| 3468 | + ctrl->awupf = le16_to_cpu(id->awupf); | |
| 3445 | 3469 | out_free: |
| 3446 | 3470 | kfree(id); |
| 3447 | 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 | 639 | blk_set_stacking_limits(&lim); |
| 640 | 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 | 643 | if (head->ids.csi == NVME_CSI_ZNS) |
| 643 | 644 | lim.features |= BLK_FEAT_ZONED; |
| 644 | 645 | |
| @@ -410,6 +410,7 @@ struct nvme_ctrl { · 409 unmodified lines | ||
| 410 | 410 | |
| 411 | 411 | enum nvme_ctrl_type cntrltype; |
| 412 | 412 | enum nvme_dctype dctype; |
| 413 | + u16 awupf; /* 0's based value. */ | |
| 413 | 414 | }; |
| 414 | 415 | |
| 415 | 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 | 443 | u8 cmic; |
| 443 | 444 | enum nvme_subsys_type subtype; |
| 444 | 445 | u16 vendor_id; |
| 445 | − u16 awupf; /* 0's based awupf value. */ | |
| 446 | 446 | struct ida ns_ida; |
| 447 | 447 | #ifdef CONFIG_NVME_MULTIPATH |
| 448 | 448 | enum nvme_iopolicy iopolicy; |
| 449 | 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 | 390 | * as it only leads to a small amount of wasted memory for the lifetime of |
| 391 | 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 | 395 | unsigned max_bytes = (NVME_MAX_KB_SZ * 1024) + NVME_CTRL_PAGE_SIZE; |
| 396 | 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 | 1202 | WARN_ON_ONCE(test_bit(NVMEQ_POLLED, &nvmeq->flags)); |
| 1203 | 1203 | |
| 1204 | 1204 | disable_irq(pci_irq_vector(pdev, nvmeq->cq_vector)); |
| 1205 | + spin_lock(&nvmeq->cq_poll_lock); | |
| 1205 | 1206 | nvme_poll_cq(nvmeq, NULL); |
| 1207 | + spin_unlock(&nvmeq->cq_poll_lock); | |
| 1206 | 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 | 3739 | .driver_data = NVME_QUIRK_NO_DEEPEST_PS, }, |
| 3738 | 3740 | { PCI_DEVICE(0x1e49, 0x0041), /* ZHITAI TiPro7000 NVMe SSD */ |
| 3739 | 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 | 3744 | { PCI_DEVICE(0xc0a9, 0x540a), /* Crucial P2 */ |
| 3741 | 3745 | .driver_data = NVME_QUIRK_BOGUS_NID, }, |
| 3742 | 3746 | { PCI_DEVICE(0x1d97, 0x2263), /* Lexar NM610 */ |
| @@ -62,8 +62,7 @@ static DEFINE_MUTEX(nvmet_pci_epf_ports_mutex); · 61 unmodified lines | ||
| 62 | 62 | #define NVMET_PCI_EPF_CQ_RETRY_INTERVAL msecs_to_jiffies(1) |
| 63 | 63 | |
| 64 | 64 | enum nvmet_pci_epf_queue_flags { |
| 65 | − NVMET_PCI_EPF_Q_IS_SQ = 0, /* The queue is a submission queue */ | |
| 66 | − NVMET_PCI_EPF_Q_LIVE, /* The queue is live */ | |
| 65 | + NVMET_PCI_EPF_Q_LIVE = 0, /* The queue is live */ | |
| 67 | 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 | 595 | struct nvmet_pci_epf_irq_vector *iv = cq->iv; |
| 597 | 596 | bool ret; |
| 598 | 597 | |
| 599 | − if (!test_bit(NVMET_PCI_EPF_Q_IRQ_ENABLED, &cq->flags)) | |
| 600 | − return false; | |
| 601 | − | |
| 602 | 598 | /* IRQ coalescing for the admin queue is not allowed. */ |
| 603 | 599 | if (!cq->qid) |
| 604 | 600 | return true; |
| @@ -625,7 +621,8 @@ static void nvmet_pci_epf_raise_irq(struct nvmet_pci_epf_ctrl *ctrl, · 20 unmodified lines | ||
| 625 | 621 | struct pci_epf *epf = nvme_epf->epf; |
| 626 | 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 | 626 | return; |
| 630 | 627 | |
| 631 | 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 | 633 | switch (nvme_epf->irq_type) { |
| 637 | 634 | case PCI_IRQ_MSIX: |
| 638 | 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 | 642 | ret = pci_epc_raise_irq(epf->epc, epf->func_no, epf->vfunc_no, |
| 640 | 643 | nvme_epf->irq_type, cq->vector + 1); |
| 641 | − if (!ret) | |
| 644 | + if (!ret || !nvme_epf->epc_features->intx_capable) | |
| 642 | 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 | 646 | fallthrough; |
| 648 | 647 | case PCI_IRQ_INTX: |
| 649 | 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 | 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 | 662 | unlock: |
| 662 | 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 | 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 | − cqid, qsize, cq->qes, cq->vector); | |
| 1323 | + if (test_bit(NVMET_PCI_EPF_Q_IRQ_ENABLED, &cq->flags)) | |
| 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 | 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 | 1352 | cancel_delayed_work_sync(&cq->work); |
| 1346 | 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 | 1356 | nvmet_pci_epf_mem_unmap(ctrl->nvme_epf, &cq->pci_map); |
| 1349 | 1357 | |
| 1350 | 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 | 1542 | if (sq) { |
| 1535 | 1543 | queue = &ctrl->sq[qid]; |
| 1536 | − set_bit(NVMET_PCI_EPF_Q_IS_SQ, &queue->flags); | |
| 1537 | 1544 | } else { |
| 1538 | 1545 | queue = &ctrl->cq[qid]; |
| 1539 | 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 | 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 | 106 | static int can_transceiver_phy_probe(struct platform_device *pdev) |
| 97 | 107 | { |
| 98 | 108 | struct phy_provider *phy_provider; |
| @@ -114,13 +124,11 @@ static int can_transceiver_phy_probe(struct platform_device *pdev) · 15 unmodified lines | ||
| 114 | 124 | match = of_match_node(can_transceiver_phy_ids, pdev->dev.of_node); |
| 115 | 125 | drvdata = match->data; |
| 116 | 126 | |
| 117 | − mux_state = devm_mux_state_get(dev, NULL); | |
| 118 | − if (IS_ERR(mux_state)) { | |
| 119 | − if (PTR_ERR(mux_state) == -EPROBE_DEFER) | |
| 120 | − return PTR_ERR(mux_state); | |
| 121 | − } else { | |
| 122 | − can_transceiver_phy->mux_state = mux_state; | |
| 123 | − } | |
| 127 | + mux_state = devm_mux_state_get_optional(dev, NULL); | |
| 128 | + if (IS_ERR(mux_state)) | |
| 129 | + return PTR_ERR(mux_state); | |
| 130 | + | |
| 131 | + can_transceiver_phy->mux_state = mux_state; | |
| 124 | 132 | |
| 125 | 133 | phy = devm_phy_create(dev, dev->of_node, |
| 126 | 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 | 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 | 1761 | static int qmp_ufs_com_init(struct qmp_ufs *qmp) |
| @@ -9,6 +9,7 @@ · 8 unmodified lines | ||
| 9 | 9 | * Copyright (C) 2014 Cogent Embedded, Inc. |
| 10 | 10 | */ |
| 11 | 11 | |
| 12 | +#include <linux/cleanup.h> | |
| 12 | 13 | #include <linux/extcon-provider.h> |
| 13 | 14 | #include <linux/interrupt.h> |
| 14 | 15 | #include <linux/io.h> |
| @@ -107,7 +108,6 @@ struct rcar_gen3_phy { · 92 unmodified lines | ||
| 107 | 108 | struct rcar_gen3_chan *ch; |
| 108 | 109 | u32 int_enable_bits; |
| 109 | 110 | bool initialized; |
| 110 | − bool otg_initialized; | |
| 111 | 111 | bool powered; |
| 112 | 112 | }; |
| 113 | 113 | |
| @@ -119,9 +119,8 @@ struct rcar_gen3_chan { · 5 unmodified lines | ||
| 119 | 119 | struct regulator *vbus; |
| 120 | 120 | struct reset_control *rstc; |
| 121 | 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 | 123 | enum usb_dr_mode dr_mode; |
| 124 | − int irq; | |
| 125 | 124 | u32 obint_enable_bits; |
| 126 | 125 | bool extcon_host; |
| 127 | 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 | 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; | |
| 326 | − | |
| 327 | − for (i = 0; i < NUM_OF_PHYS; i++) { | |
| 328 | − if (ch->rphys[i].otg_initialized) | |
| 329 | − return false; | |
| 324 | + for (enum rcar_gen3_phy_index i = PHY_INDEX_BOTH_HC; i <= PHY_INDEX_EHCI; | |
| 325 | + i++) { | |
| 326 | + if (ch->rphys[i].initialized) | |
| 327 | + return true; | |
| 330 | 328 | } |
| 331 | 329 | |
| 332 | − return true; | |
| 330 | + return false; | |
| 333 | 331 | } |
| 334 | 332 | |
| 335 | 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 | 349 | bool is_b_device; |
| 352 | 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 | 355 | return -EIO; |
| 356 | 356 | |
| 357 | 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 | 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 | 393 | return -EIO; |
| 394 | 394 | |
| 395 | 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 | 402 | void __iomem *usb2_base = ch->base; |
| 403 | 403 | u32 val; |
| 404 | 404 | |
| 405 | + if (!ch->is_otg_channel || rcar_gen3_is_any_otg_rphy_initialized(ch)) | |
| 406 | + return; | |
| 407 | + | |
| 405 | 408 | /* Should not use functions of read-modify-write a register */ |
| 406 | 409 | val = readl(usb2_base + USB2_LINECTRL1); |
| 407 | 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 | 418 | val = readl(usb2_base + USB2_ADPCTRL); |
| 416 | 419 | writel(val | USB2_ADPCTRL_IDPULLUP, usb2_base + USB2_ADPCTRL); |
| 417 | 420 | } |
| 418 | − msleep(20); | |
| 421 | + mdelay(20); | |
| 419 | 422 | |
| 420 | 423 | writel(0xffffffff, usb2_base + USB2_OBINTSTA); |
| 421 | 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 | 431 | struct rcar_gen3_chan *ch = _ch; |
| 429 | 432 | void __iomem *usb2_base = ch->base; |
| 430 | − u32 status = readl(usb2_base + USB2_OBINTSTA); | |
| 433 | + struct device *dev = ch->dev; | |
| 431 | 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) { | |
| 434 | − dev_vdbg(ch->dev, "%s: %08x\n", __func__, status); | |
| 435 | − writel(ch->obint_enable_bits, usb2_base + USB2_OBINTSTA); | |
| 436 | − rcar_gen3_device_recognition(ch); | |
| 437 | − ret = IRQ_HANDLED; | |
| 442 | + scoped_guard(spinlock, &ch->lock) { | |
| 443 | + status = readl(usb2_base + USB2_OBINTSTA); | |
| 444 | + if (status & ch->obint_enable_bits) { | |
| 445 | + dev_vdbg(dev, "%s: %08x\n", __func__, status); | |
| 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 | 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 | 460 | struct rcar_gen3_chan *channel = rphy->ch; |
| 447 | 461 | void __iomem *usb2_base = channel->base; |
| 448 | 462 | u32 val; |
| 449 | − int ret; | |
| 450 | 463 | |
| 451 | − if (!rcar_gen3_is_any_rphy_initialized(channel) && channel->irq >= 0) { | |
| 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 | − } | |
| 464 | + guard(spinlock_irqsave)(&channel->lock); | |
| 460 | 465 | |
| 461 | 466 | /* Initialize USB2 part */ |
| 462 | 467 | val = readl(usb2_base + USB2_INT_ENABLE); |
| 463 | 468 | val |= USB2_INT_ENABLE_UCOM_INTEN | rphy->int_enable_bits; |
| 464 | 469 | writel(val, usb2_base + USB2_INT_ENABLE); |
| 465 | − writel(USB2_SPD_RSM_TIMSET_INIT, usb2_base + USB2_SPD_RSM_TIMSET); | |
| 466 | − writel(USB2_OC_TIMSET_INIT, usb2_base + USB2_OC_TIMSET); | |
| 467 | − | |
| 468 | − /* Initialize otg part */ | |
| 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; | |
| 470 | + | |
| 471 | + if (!rcar_gen3_is_any_rphy_initialized(channel)) { | |
| 472 | + writel(USB2_SPD_RSM_TIMSET_INIT, usb2_base + USB2_SPD_RSM_TIMSET); | |
| 473 | + writel(USB2_OC_TIMSET_INIT, usb2_base + USB2_OC_TIMSET); | |
| 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 | 480 | rphy->initialized = true; |
| 476 | 481 | |
| 477 | 482 | return 0; |
| @@ -484,10 +489,9 @@ static int rcar_gen3_phy_usb2_exit(struct phy *p) · 6 unmodified lines | ||
| 484 | 489 | void __iomem *usb2_base = channel->base; |
| 485 | 490 | u32 val; |
| 486 | 491 | |
| 487 | − rphy->initialized = false; | |
| 492 | + guard(spinlock_irqsave)(&channel->lock); | |
| 488 | 493 | |
| 489 | − if (channel->is_otg_channel) | |
| 490 | − rphy->otg_initialized = false; | |
| 494 | + rphy->initialized = false; | |
| 491 | 495 | |
| 492 | 496 | val = readl(usb2_base + USB2_INT_ENABLE); |
| 493 | 497 | val &= ~rphy->int_enable_bits; |
| @@ -495,9 +499,6 @@ static int rcar_gen3_phy_usb2_exit(struct phy *p) · 1 unmodified line | ||
| 495 | 499 | val &= ~USB2_INT_ENABLE_UCOM_INTEN; |
| 496 | 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 | 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 | 510 | u32 val; |
| 510 | 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 | 513 | if (channel->vbus) { |
| 517 | 514 | ret = regulator_enable(channel->vbus); |
| 518 | 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 | 524 | val = readl(usb2_base + USB2_USBCTR); |
| 523 | 525 | val |= USB2_USBCTR_PLL_RST; |
| 524 | 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 | 530 | out: |
| 529 | 531 | /* The powered flag should be set for any other phys anyway */ |
| 530 | 532 | rphy->powered = true; |
| 531 | − mutex_unlock(&channel->lock); | |
| 532 | 533 | |
| 533 | 534 | return 0; |
| 534 | 535 | } |
| @@ -539,18 +540,20 @@ static int rcar_gen3_phy_usb2_power_off(struct phy *p) · 4 unmodified lines | ||
| 539 | 540 | struct rcar_gen3_chan *channel = rphy->ch; |
| 540 | 541 | int ret = 0; |
| 541 | 542 | |
| 542 | − mutex_lock(&channel->lock); | |
| 543 | − rphy->powered = false; | |
| 543 | + scoped_guard(spinlock_irqsave, &channel->lock) { | |
| 544 | + rphy->powered = false; | |
| 544 | 545 | |
| 545 | − if (!rcar_gen3_are_all_rphys_power_off(channel)) | |
| 546 | − goto out; | |
| 546 | + if (rcar_gen3_are_all_rphys_power_off(channel)) { | |
| 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 | 554 | if (channel->vbus) |
| 549 | 555 | ret = regulator_disable(channel->vbus); |
| 550 | 556 | |
| 551 | −out: | |
| 552 | − mutex_unlock(&channel->lock); | |
| 553 | − | |
| 554 | 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 | 706 | struct device *dev = &pdev->dev; |
| 704 | 707 | struct rcar_gen3_chan *channel; |
| 705 | 708 | struct phy_provider *provider; |
| 706 | − int ret = 0, i; | |
| 709 | + int ret = 0, i, irq; | |
| 707 | 710 | |
| 708 | 711 | if (!dev->of_node) { |
| 709 | 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 | 722 | return PTR_ERR(channel->base); |
| 720 | 723 | |
| 721 | 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 | 725 | channel->dr_mode = rcar_gen3_get_dr_mode(dev->of_node); |
| 725 | 726 | if (channel->dr_mode != USB_DR_MODE_UNKNOWN) { |
| 726 | 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 | 764 | if (phy_data->no_adp_ctrl) |
| 764 | 765 | channel->obint_enable_bits = USB2_OBINT_IDCHG_EN; |
| 765 | 766 | |
| 766 | − mutex_init(&channel->lock); | |
| 767 | + spin_lock_init(&channel->lock); | |
| 767 | 768 | for (i = 0; i < NUM_OF_PHYS; i++) { |
| 768 | 769 | channel->rphys[i].phy = devm_phy_create(dev, NULL, |
| 769 | 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 | 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 | 807 | provider = devm_of_phy_provider_register(dev, rcar_gen3_phy_usb2_xlate); |
| 793 | 808 | if (IS_ERR(provider)) { |
| 794 | 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 | 1653 | return ret; |
| 1654 | 1654 | } |
| 1655 | 1655 | |
| 1656 | − clk_prepare_enable(samsung->ref_clk); | |
| 1656 | + ret = clk_prepare_enable(samsung->ref_clk); | |
| 1657 | 1657 | if (ret) { |
| 1658 | 1658 | dev_err(samsung->dev, "Failed to enable reference clock, %d\n", ret); |
| 1659 | 1659 | clk_disable_unprepare(samsung->pclk); |
| @@ -476,6 +476,8 @@ static const struct ropll_config ropll_tmds_cfg[] = { · 475 unmodified lines | ||
| 476 | 476 | 1, 1, 0, 0x20, 0x0c, 1, 0x0e, 0, 0, }, |
| 477 | 477 | { 650000, 162, 162, 1, 1, 11, 1, 1, 1, 1, 1, 1, 1, 54, 0, 16, 4, 1, |
| 478 | 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 | 481 | { 337500, 0x70, 0x70, 1, 1, 0xf, 1, 1, 1, 1, 1, 1, 1, 0x2, 0, 0x01, 5, |
| 480 | 482 | 1, 1, 1, 0, 0x20, 0x0c, 1, 0x0e, 0, 0, }, |
| 481 | 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 | 18 | #include <linux/usb/of.h> |
| 19 | 19 | |
| 20 | 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 | 23 | #define USB_LS_KEEPALIVE_OFF 0x4 |
| 22 | 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 | 81 | struct jh7110_usb2_phy *phy = phy_get_drvdata(_phy); |
| 80 | 82 | int ret; |
| 83 | + unsigned int val; | |
| 81 | 84 | |
| 82 | 85 | ret = clk_set_rate(phy->usb_125m_clk, USB_125M_CLK_RATE); |
| 83 | 86 | if (ret) |
| @@ -87,6 +90,10 @@ static int jh7110_usb2_phy_init(struct phy *_phy) · 3 unmodified lines | ||
| 87 | 90 | if (ret) |
| 88 | 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 | 97 | return 0; |
| 91 | 98 | } |
| 92 | 99 | |
| @@ -237,6 +237,8 @@ · 236 unmodified lines | ||
| 237 | 237 | #define DATA0_VAL_PD BIT(1) |
| 238 | 238 | #define USE_XUSB_AO BIT(4) |
| 239 | 239 | |
| 240 | +#define TEGRA_UTMI_PAD_MAX 4 | |
| 241 | + | |
| 240 | 242 | #define TEGRA186_LANE(_name, _offset, _shift, _mask, _type) \ |
| 241 | 243 | { \ |
| 242 | 244 | .name = _name, \ |
| @@ -269,7 +271,7 @@ struct tegra186_xusb_padctl { · 26 unmodified lines | ||
| 269 | 271 | |
| 270 | 272 | /* UTMI bias and tracking */ |
| 271 | 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 | 276 | /* padctl context */ |
| 275 | 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 | 605 | u32 value; |
| 604 | 606 | int err; |
| 605 | 607 | |
| 606 | − mutex_lock(&padctl->lock); | |
| 607 | − | |
| 608 | − if (priv->bias_pad_enable++ > 0) { | |
| 609 | − mutex_unlock(&padctl->lock); | |
| 608 | + if (!bitmap_empty(priv->utmi_pad_enabled, TEGRA_UTMI_PAD_MAX)) | |
| 610 | 609 | return; |
| 611 | − } | |
| 612 | 610 | |
| 613 | 611 | err = clk_prepare_enable(priv->usb2_trk_clk); |
| 614 | 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 | 656 | } else { |
| 659 | 657 | clk_disable_unprepare(priv->usb2_trk_clk); |
| 660 | 658 | } |
| 661 | − | |
| 662 | − mutex_unlock(&padctl->lock); | |
| 663 | 659 | } |
| 664 | 660 | |
| 665 | 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 | 663 | struct tegra186_xusb_padctl *priv = to_tegra186_xusb_padctl(padctl); |
| 668 | 664 | u32 value; |
| 669 | 665 | |
| 670 | − mutex_lock(&padctl->lock); | |
| 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); | |
| 666 | + if (!bitmap_empty(priv->utmi_pad_enabled, TEGRA_UTMI_PAD_MAX)) | |
| 679 | 667 | return; |
| 680 | − } | |
| 681 | 668 | |
| 682 | 669 | value = padctl_readl(padctl, XUSB_PADCTL_USB2_BIAS_PAD_CTL1); |
| 683 | 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 | 677 | clk_disable_unprepare(priv->usb2_trk_clk); |
| 691 | 678 | } |
| 692 | 679 | |
| 693 | − mutex_unlock(&padctl->lock); | |
| 694 | 680 | } |
| 695 | 681 | |
| 696 | 682 | static void tegra186_utmi_pad_power_on(struct phy *phy) |
| 697 | 683 | { |
| 698 | 684 | struct tegra_xusb_lane *lane = phy_get_drvdata(phy); |
| 699 | 685 | struct tegra_xusb_padctl *padctl = lane->pad->padctl; |
| 686 | + struct tegra186_xusb_padctl *priv = to_tegra186_xusb_padctl(padctl); | |
| 700 | 687 | struct tegra_xusb_usb2_port *port; |
| 701 | 688 | struct device *dev = padctl->dev; |
| 702 | 689 | unsigned int index = lane->index; |
| @@ -705,9 +692,16 @@ static void tegra186_utmi_pad_power_on(struct phy *phy) · 2 unmodified lines | ||
| 705 | 692 | if (!phy) |
| 706 | 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 | 701 | port = tegra_xusb_find_usb2_port(padctl, index); |
| 709 | 702 | if (!port) { |
| 710 | 703 | dev_err(dev, "no port found for USB2 lane %u\n", index); |
| 704 | + mutex_unlock(&padctl->lock); | |
| 711 | 705 | return; |
| 712 | 706 | } |
| 713 | 707 | |
| @@ -724,18 +718,28 @@ static void tegra186_utmi_pad_power_on(struct phy *phy) · 10 unmodified lines | ||
| 724 | 718 | value = padctl_readl(padctl, XUSB_PADCTL_USB2_OTG_PADX_CTL1(index)); |
| 725 | 719 | value &= ~USB2_OTG_PD_DR; |
| 726 | 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 | 726 | static void tegra186_utmi_pad_power_down(struct phy *phy) |
| 730 | 727 | { |
| 731 | 728 | struct tegra_xusb_lane *lane = phy_get_drvdata(phy); |
| 732 | 729 | struct tegra_xusb_padctl *padctl = lane->pad->padctl; |
| 730 | + struct tegra186_xusb_padctl *priv = to_tegra186_xusb_padctl(padctl); | |
| 733 | 731 | unsigned int index = lane->index; |
| 734 | 732 | u32 value; |
| 735 | 733 | |
| 736 | 734 | if (!phy) |
| 737 | 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 | 743 | dev_dbg(padctl->dev, "power down UTMI pad %u\n", index); |
| 740 | 744 | |
| 741 | 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 | 753 | udelay(2); |
| 750 | 754 | |
| 755 | + clear_bit(index, priv->utmi_pad_enabled); | |
| 756 | + | |
| 751 | 757 | tegra186_utmi_bias_pad_power_off(padctl); |
| 758 | + | |
| 759 | + mutex_unlock(&padctl->lock); | |
| 752 | 760 | } |
| 753 | 761 | |
| 754 | 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 | 549 | err = dev_set_name(&port->dev, "%s-%u", name, index); |
| 550 | 550 | if (err < 0) |
| 551 | − goto unregister; | |
| 551 | + goto put_device; | |
| 552 | 552 | |
| 553 | 553 | err = device_add(&port->dev); |
| 554 | 554 | if (err < 0) |
| 555 | − goto unregister; | |
| 555 | + goto put_device; | |
| 556 | 556 | |
| 557 | 557 | return 0; |
| 558 | 558 | |
| 559 | −unregister: | |
| 560 | − device_unregister(&port->dev); | |
| 559 | +put_device: | |
| 560 | + put_device(&port->dev); | |
| 561 | 561 | return err; |
| 562 | 562 | } |
| 563 | 563 | |
| @@ -27,9 +27,8 @@ · 26 unmodified lines | ||
| 27 | 27 | |
| 28 | 28 | #include "hsmp.h" |
| 29 | 29 | |
| 30 | −#define DRIVER_NAME "amd_hsmp" | |
| 30 | +#define DRIVER_NAME "hsmp_acpi" | |
| 31 | 31 | #define DRIVER_VERSION "2.3" |
| 32 | −#define ACPI_HSMP_DEVICE_HID "AMDI0097" | |
| 33 | 32 | |
| 34 | 33 | /* These are the strings specified in ACPI table */ |
| 35 | 34 | #define MSG_IDOFF_STR "MsgIdOffset" |
| @@ -23,6 +23,7 @@ · 22 unmodified lines | ||
| 23 | 23 | |
| 24 | 24 | #define HSMP_CDEV_NAME "hsmp_cdev" |
| 25 | 25 | #define HSMP_DEVNODE_NAME "hsmp" |
| 26 | +#define ACPI_HSMP_DEVICE_HID "AMDI0097" | |
| 26 | 27 | |
| 27 | 28 | struct hsmp_mbaddr_info { |
| 28 | 29 | u32 base_addr; |
| @@ -11,6 +11,7 @@ · 10 unmodified lines | ||
| 11 | 11 | |
| 12 | 12 | #include <asm/amd/hsmp.h> |
| 13 | 13 | |
| 14 | +#include <linux/acpi.h> | |
| 14 | 15 | #include <linux/build_bug.h> |
| 15 | 16 | #include <linux/device.h> |
| 16 | 17 | #include <linux/module.h> |
| @@ -266,7 +267,7 @@ static bool legacy_hsmp_support(void) · 249 unmodified lines | ||
| 266 | 267 | } |
| 267 | 268 | case 0x1A: |
| 268 | 269 | switch (boot_cpu_data.x86_model) { |
| 269 | − case 0x00 ... 0x1F: | |
| 270 | + case 0x00 ... 0x0F: | |
| 270 | 271 | return true; |
| 271 | 272 | default: |
| 272 | 273 | return false; |
| @@ -288,6 +289,9 @@ static int __init hsmp_plt_init(void) · 15 unmodified lines | ||
| 288 | 289 | return ret; |
| 289 | 290 | } |
| 290 | 291 | |
| 292 | + if (acpi_dev_present(ACPI_HSMP_DEVICE_HID, NULL, -1)) | |
| 293 | + return -ENODEV; | |
| 294 | + | |
| 291 | 295 | hsmp_pdev = get_hsmp_pdev(); |
| 292 | 296 | if (!hsmp_pdev) |
| 293 | 297 | return -ENOMEM; |
| @@ -218,6 +218,13 @@ static const struct dmi_system_id fwbug_list[] = { · 217 unmodified lines | ||
| 218 | 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 | 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 | 342 | #ifdef CONFIG_AMD_PMF_DEBUG |
| 338 | 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 | 366 | dev->policy_buf = new_policy_buf; |
| 362 | 367 | dev->policy_sz = length; |
| 363 | 368 | |
| 369 | + if (!amd_pmf_pb_valid(dev)) { | |
| 370 | + ret = -EINVAL; | |
| 371 | + goto cleanup; | |
| 372 | + } | |
| 373 | + | |
| 364 | 374 | amd_pmf_hex_dump_pb(dev); |
| 365 | 375 | ret = amd_pmf_start_policy_engine(dev); |
| 366 | 376 | if (ret < 0) |
| 367 | − return ret; | |
| 377 | + goto cleanup; | |
| 368 | 378 | |
| 369 | 379 | return length; |
| 380 | + | |
| 381 | +cleanup: | |
| 382 | + kfree(dev->policy_buf); | |
| 383 | + dev->policy_buf = NULL; | |
| 384 | + return ret; | |
| 370 | 385 | } |
| 371 | 386 | |
| 372 | 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 | 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 | 552 | amd_pmf_hex_dump_pb(dev); |
| 532 | 553 | |
| 533 | 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 | 4779 | goto fail_leds; |
| 4780 | 4780 | |
| 4781 | 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 | 4784 | asus->driver->wlan_ctrl_by_user = 1; |
| 4784 | 4785 | |
| 4785 | 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 | 11478 | tp->vendor = PCI_VENDOR_ID_IBM; |
| 11479 | 11479 | else if (dmi_name_in_vendors("LENOVO")) |
| 11480 | 11480 | tp->vendor = PCI_VENDOR_ID_LENOVO; |
| 11481 | + else if (dmi_name_in_vendors("NEC")) | |
| 11482 | + tp->vendor = PCI_VENDOR_ID_LENOVO; | |
| 11481 | 11483 | else |
| 11482 | 11484 | return 0; |
| 11483 | 11485 | |
| @@ -132,7 +132,7 @@ static int max20086_regulators_register(struct max20086 *chip) · 131 unmodified lines | ||
| 132 | 132 | |
| 133 | 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 | 136 | struct device_node *node; |
| 137 | 137 | unsigned int i; |
| 138 | 138 | int ret; |
| @@ -143,6 +143,11 @@ static int max20086_parse_regulators_dt(struct max20086 *chip, bool *boot_on) · 4 unmodified lines | ||
| 143 | 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 | 151 | for (i = 0; i < chip->info->num_outputs; ++i) |
| 147 | 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 | 169 | unsigned int nr_zones, size_t *buflen) |
| 170 | 170 | { |
| 171 | 171 | struct request_queue *q = sdkp->disk->queue; |
| 172 | + unsigned int max_segments; | |
| 172 | 173 | size_t bufsize; |
| 173 | 174 | void *buf; |
| 174 | 175 | |
| @@ -180,12 +181,15 @@ static void *sd_zbc_alloc_report_buffer(struct scsi_disk *sdkp, · 5 unmodified lines | ||
| 180 | 181 | * Furthermore, since the report zone command cannot be split, make |
| 181 | 182 | * sure that the allocated buffer can always be mapped by limiting the |
| 182 | 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 | 187 | nr_zones = min(nr_zones, sdkp->zone_info.nr_zones); |
| 185 | 188 | bufsize = roundup((nr_zones + 1) * 64, SECTOR_SIZE); |
| 186 | 189 | bufsize = min_t(size_t, bufsize, |
| 187 | 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 | 194 | while (bufsize >= SECTOR_SIZE) { |
| 191 | 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 | 1819 | return SCSI_MLQUEUE_DEVICE_BUSY; |
| 1820 | 1820 | } |
| 1821 | 1821 | |
| 1822 | + payload->rangecount = 1; | |
| 1822 | 1823 | payload->range.len = length; |
| 1823 | 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 | 122 | set_bit(SDW_GROUP13_DEV_NUM, bus->assigned); |
| 123 | 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 | 130 | * SDW is an enumerable bus, but devices can be powered off. So, |
| 127 | 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 | 143 | if (ret < 0) { |
| 140 | 144 | dev_err(bus->dev, "Finding slaves failed:%d\n", ret); |
| 145 | + sdw_irq_delete(bus); | |
| 141 | 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 | 161 | bus->params.curr_bank = SDW_BANK0; |
| 157 | 162 | bus->params.next_bank = SDW_BANK1; |
| 158 | 163 | |
| 159 | − ret = sdw_irq_create(bus, fwnode); | |
| 160 | − if (ret) | |
| 161 | − return ret; | |
| 162 | − | |
| 163 | 164 | return 0; |
| 164 | 165 | } |
| 165 | 166 | EXPORT_SYMBOL(sdw_bus_master_add); |
| @@ -420,7 +420,7 @@ MODULE_LICENSE("GPL"); · 419 unmodified lines | ||
| 420 | 420 | static void spi_test_print_hex_dump(char *pre, const void *ptr, size_t len) |
| 421 | 421 | { |
| 422 | 422 | /* limit the hex_dump */ |
| 423 | − if (len < 1024) { | |
| 423 | + if (len <= 1024) { | |
| 424 | 424 | print_hex_dump(KERN_INFO, pre, |
| 425 | 425 | DUMP_PREFIX_OFFSET, 16, 1, |
| 426 | 426 | ptr, len, 0); |
| @@ -264,6 +264,9 @@ static int sun4i_spi_transfer_one(struct spi_controller *host, · 263 unmodified lines | ||
| 264 | 264 | else |
| 265 | 265 | reg |= SUN4I_CTL_DHB; |
| 266 | 266 | |
| 267 | + /* Now that the settings are correct, enable the interface */ | |
| 268 | + reg |= SUN4I_CTL_ENABLE; | |
| 269 | + | |
| 267 | 270 | sun4i_spi_write(sspi, SUN4I_CTL_REG, reg); |
| 268 | 271 | |
| 269 | 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 | 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 | 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 | 728 | u32 inactive_cycles; |
| 729 | 729 | u8 cs_state; |
| 730 | 730 | |
| 731 | − if ((setup->unit && setup->unit != SPI_DELAY_UNIT_SCK) || | |
| 732 | − (hold->unit && hold->unit != SPI_DELAY_UNIT_SCK) || | |
| 733 | − (inactive->unit && inactive->unit != SPI_DELAY_UNIT_SCK)) { | |
| 731 | + if ((setup->value && setup->unit != SPI_DELAY_UNIT_SCK) || | |
| 732 | + (hold->value && hold->unit != SPI_DELAY_UNIT_SCK) || | |
| 733 | + (inactive->value && inactive->unit != SPI_DELAY_UNIT_SCK)) { | |
| 734 | 734 | dev_err(&spi->dev, |
| 735 | 735 | "Invalid delay unit %d, should be SPI_DELAY_UNIT_SCK\n", |
| 736 | 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 | 475 | /* reply a UMP EP device info */ |
| 476 | 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 | 479 | .type = UMP_MSG_TYPE_STREAM, |
| 480 | 480 | .status = UMP_STREAM_MSG_STATUS_DEVICE_INFO, |
| 481 | 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 | 192 | static int backpointer_target_not_found(struct btree_trans *trans, |
| 193 | 193 | struct bkey_s_c_backpointer bp, |
| 194 | 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 | 198 | struct bch_fs *c = trans->c; |
| 198 | 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 | 231 | if (fsck_err(trans, backpointer_to_missing_ptr, |
| 231 | − "%s", buf.buf)) | |
| 232 | + "%s", buf.buf)) { | |
| 232 | 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 | 254 | fsck_err: |
| 234 | 255 | printbuf_exit(&buf); |
| 235 | 256 | return ret; |
| 236 | 257 | } |
| 237 | 258 | |
| 238 | −struct bkey_s_c bch2_backpointer_get_key(struct btree_trans *trans, | |
| 239 | − struct bkey_s_c_backpointer bp, | |
| 240 | − struct btree_iter *iter, | |
| 241 | − unsigned iter_flags, | |
| 242 | − struct bkey_buf *last_flushed) | |
| 259 | +static struct btree *__bch2_backpointer_get_node(struct btree_trans *trans, | |
| 260 | + struct bkey_s_c_backpointer bp, | |
| 261 | + struct btree_iter *iter, | |
| 262 | + 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 | 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 | 337 | bch2_trans_iter_exit(trans, iter); |
| 278 | 338 | |
| 279 | 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 | 341 | return ret ? bkey_s_c_err(ret) : bkey_s_c_null; |
| 282 | 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 | 344 | if (b == ERR_PTR(-BCH_ERR_backpointer_to_overwritten_btree_node)) |
| 285 | 345 | return bkey_s_c_null; |
| 286 | 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 | 355 | struct btree_iter *iter, |
| 296 | 356 | struct bkey_buf *last_flushed) |
| 297 | 357 | { |
| 298 | − struct bch_fs *c = trans->c; | |
| 299 | − | |
| 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; | |
| 358 | + return __bch2_backpointer_get_node(trans, bp, iter, last_flushed, true); | |
| 359 | +} | |
| 317 | 360 | |
| 318 | − if (btree_node_will_make_reachable(b)) { | |
| 319 | − b = ERR_PTR(-BCH_ERR_backpointer_to_overwritten_btree_node); | |
| 320 | − } else { | |
| 321 | − int ret = backpointer_target_not_found(trans, bp, bkey_i_to_s_c(&b->key), last_flushed); | |
| 322 | − b = ret ? ERR_PTR(ret) : NULL; | |
| 323 | − } | |
| 324 | −err: | |
| 325 | − bch2_trans_iter_exit(trans, iter); | |
| 326 | − return b; | |
| 361 | +struct bkey_s_c bch2_backpointer_get_key(struct btree_trans *trans, | |
| 362 | + struct bkey_s_c_backpointer bp, | |
| 363 | + struct btree_iter *iter, | |
| 364 | + unsigned iter_flags, | |
| 365 | + struct bkey_buf *last_flushed) | |
| 366 | +{ | |
| 367 | + return __bch2_backpointer_get_key(trans, bp, iter, iter_flags, last_flushed, true); | |
| 327 | 368 | } |
| 328 | 369 | |
| 329 | 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 | 562 | struct bkey_s_c_backpointer other_bp = bkey_s_c_to_backpointer(bp_k); |
| 522 | 563 | |
| 523 | 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 | 566 | ret = bkey_err(other_extent); |
| 526 | 567 | if (ret == -BCH_ERR_backpointer_to_overwritten_btree_node) |
| 527 | 568 | ret = 0; |
| @@ -852,7 +852,6 @@ out: · 851 unmodified lines | ||
| 852 | 852 | b->sib_u64s[1] = 0; |
| 853 | 853 | b->whiteout_u64s = 0; |
| 854 | 854 | bch2_btree_keys_init(b); |
| 855 | − set_btree_node_accessed(b); | |
| 856 | 855 | |
| 857 | 856 | bch2_time_stats_update(&c->times[BCH_TIME_btree_node_mem_alloc], |
| 858 | 857 | start_time); |
| @@ -1286,6 +1285,10 @@ lock_node: · 427 unmodified lines | ||
| 1286 | 1285 | six_unlock_read(&b->c.lock); |
| 1287 | 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 | 1294 | /* XXX: waiting on IO with btree locks held: */ |
| @@ -1301,10 +1304,6 @@ lock_node: · 9 unmodified lines | ||
| 1301 | 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 | 1307 | if (unlikely(btree_node_read_error(b))) { |
| 1309 | 1308 | six_unlock_read(&b->c.lock); |
| 1310 | 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 | 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 | 1980 | if (!bch2_btree_node_relock(trans, path, path->level + 1)) { |
| 1975 | 1981 | __bch2_btree_path_unlock(trans, path); |
| 1976 | 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 | 2749 | ret = trans_maybe_inject_restart(trans, _RET_IP_); |
| 2744 | 2750 | if (unlikely(ret)) { |
| 2745 | 2751 | k = bkey_s_c_err(ret); |
| 2746 | − goto out_no_locked; | |
| 2752 | + goto out; | |
| 2747 | 2753 | } |
| 2748 | 2754 | |
| 2749 | 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 | 2769 | ret = bch2_btree_path_traverse(trans, iter->path, iter->flags); |
| 2764 | 2770 | if (unlikely(ret)) { |
| 2765 | 2771 | k = bkey_s_c_err(ret); |
| 2766 | − goto out_no_locked; | |
| 2772 | + goto out; | |
| 2767 | 2773 | } |
| 2768 | 2774 | |
| 2769 | 2775 | struct btree_path *path = btree_iter_path(trans, iter); |
| 2770 | 2776 | if (unlikely(!btree_path_node(path, path->level))) |
| 2771 | 2777 | return bkey_s_c_null; |
| 2772 | 2778 | |
| 2779 | + btree_path_set_should_be_locked(trans, path); | |
| 2780 | + | |
| 2773 | 2781 | if ((iter->flags & BTREE_ITER_cached) || |
| 2774 | 2782 | !(iter->flags & (BTREE_ITER_is_extents|BTREE_ITER_filter_snapshots))) { |
| 2775 | 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 | 2798 | if (!bkey_err(k)) |
| 2791 | 2799 | iter->k = *k.k; |
| 2792 | 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 | 2805 | if (unlikely(!k.k)) |
| 2798 | − goto out_no_locked; | |
| 2806 | + goto out; | |
| 2799 | 2807 | |
| 2800 | 2808 | if (unlikely(k.k->type == KEY_TYPE_whiteout && |
| 2801 | 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 | 2843 | if (unlikely(bkey_err(k))) |
| 2836 | − goto out_no_locked; | |
| 2844 | + goto out; | |
| 2837 | 2845 | |
| 2838 | 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 | 2865 | out: |
| 2858 | − btree_path_set_should_be_locked(trans, btree_iter_path(trans, iter)); | |
| 2859 | −out_no_locked: | |
| 2860 | 2866 | bch2_btree_iter_verify_entry_exit(iter); |
| 2861 | 2867 | bch2_btree_iter_verify(trans, iter); |
| 2862 | 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 | 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 | 392 | static bool accounting_mem_entry_is_zero(struct accounting_mem_entry *e) |
| 380 | 393 | { |
| 381 | 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 | 596 | accounting_key_init(&k_i.k, &acc_k, src_v, nr); |
| 584 | 597 | bch2_accounting_mem_mod_locked(trans, |
| 585 | 598 | bkey_i_to_s_c_accounting(&k_i.k), |
| 586 | − BCH_ACCOUNTING_normal); | |
| 599 | + BCH_ACCOUNTING_normal, true); | |
| 587 | 600 | |
| 588 | 601 | preempt_disable(); |
| 589 | 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 | 626 | percpu_down_read(&c->mark_lock); |
| 614 | 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 | 629 | percpu_up_read(&c->mark_lock); |
| 617 | 630 | return ret; |
| 618 | 631 | } |
| @@ -136,6 +136,7 @@ enum bch_accounting_mode { · 135 unmodified lines | ||
| 136 | 136 | }; |
| 137 | 137 | |
| 138 | 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 | 140 | void bch2_accounting_mem_gc(struct bch_fs *); |
| 140 | 141 | |
| 141 | 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 | 152 | static inline int bch2_accounting_mem_mod_locked(struct btree_trans *trans, |
| 152 | 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 | 157 | struct bch_fs *c = trans->c; |
| 156 | 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 | 192 | while ((idx = eytzinger0_find(acc->k.data, acc->k.nr, sizeof(acc->k.data[0]), |
| 191 | 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 | 199 | if (ret) |
| 194 | 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 | 212 | static inline int bch2_accounting_mem_add(struct btree_trans *trans, struct bkey_s_c_accounting a, bool gc) |
| 207 | 213 | { |
| 208 | 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 | 216 | percpu_up_read(&trans->c->mark_lock); |
| 211 | 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 | 265 | EBUG_ON(bversion_zero(a->k.bversion)); |
| 260 | 266 | |
| 261 | 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 | 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 | 277 | struct bkey_s_accounting a = accounting_i_to_s(a_i); |
| 272 | 278 | |
| 273 | 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 | 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 | 1429 | if (ret) |
| 1430 | 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 | 1435 | if (ret) |
| 1434 | 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 | 2446 | u32 parent = le32_to_cpu(s.v->fs_path_parent); |
| 2447 | 2447 | |
| 2448 | 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 | 2450 | ret = reattach_subvol(trans, s); |
| 2451 | 2451 | break; |
| 2452 | 2452 | } |
| @@ -17,6 +17,8 @@ · 16 unmodified lines | ||
| 17 | 17 | #include <linux/kthread.h> |
| 18 | 18 | #include <linux/sched/mm.h> |
| 19 | 19 | |
| 20 | +static bool __should_discard_bucket(struct journal *, struct journal_device *); | |
| 21 | + | |
| 20 | 22 | /* Free space calculations: */ |
| 21 | 23 | |
| 22 | 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 | 205 | ja->bucket_seq[ja->dirty_idx_ondisk] < j->last_seq_ondisk) |
| 204 | 206 | ja->dirty_idx_ondisk = (ja->dirty_idx_ondisk + 1) % ja->nr; |
| 205 | 207 | |
| 206 | − if (ja->discard_idx != ja->dirty_idx_ondisk) | |
| 207 | − can_discard = true; | |
| 208 | + can_discard |= __should_discard_bucket(j, ja); | |
| 208 | 209 | |
| 209 | 210 | max_entry_size = min_t(unsigned, max_entry_size, ca->mi.bucket_size); |
| 210 | 211 | nr_online++; |
| @@ -264,13 +265,19 @@ out: · 53 unmodified lines | ||
| 264 | 265 | |
| 265 | 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 | 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 | 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 | 281 | spin_unlock(&j->lock); |
| 275 | 282 | |
| 276 | 283 | return ret; |
| @@ -309,7 +309,7 @@ static int bch2_bkey_clear_needs_rebalance(struct btree_trans *trans, · 308 unmodified lines | ||
| 309 | 309 | struct btree_iter *iter, |
| 310 | 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 | 313 | return 0; |
| 314 | 314 | |
| 315 | 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 | 830 | struct elf_phdr *elf_ppnt, *elf_phdata, *interp_elf_phdata = NULL; |
| 831 | 831 | struct elf_phdr *elf_property_phdata = NULL; |
| 832 | 832 | unsigned long elf_brk; |
| 833 | + bool brk_moved = false; | |
| 833 | 834 | int retval, i; |
| 834 | 835 | unsigned long elf_entry; |
| 835 | 836 | unsigned long e_entry; |
| @@ -1097,15 +1098,19 @@ out_free_interp: · 261 unmodified lines | ||
| 1097 | 1098 | /* Calculate any requested alignment. */ |
| 1098 | 1099 | alignment = maximum_alignment(elf_phdata, elf_ex->e_phnum); |
| 1099 | 1100 | |
| 1100 | − /* | |
| 1101 | − * There are effectively two types of ET_DYN | |
| 1102 | − * binaries: programs (i.e. PIE: ET_DYN with PT_INTERP) | |
| 1103 | − * and loaders (ET_DYN without PT_INTERP, since they | |
| 1104 | − * _are_ the ELF interpreter). The loaders must | |
| 1105 | − * be loaded away from programs since the program | |
| 1106 | − * may otherwise collide with the loader (especially | |
| 1107 | − * for ET_EXEC which does not have a randomized | |
| 1108 | − * position). For example to handle invocations of | |
| 1101 | + /** | |
| 1102 | + * DOC: PIE handling | |
| 1103 | + * | |
| 1104 | + * There are effectively two types of ET_DYN ELF | |
| 1105 | + * binaries: programs (i.e. PIE: ET_DYN with | |
| 1106 | + * PT_INTERP) and loaders (i.e. static PIE: ET_DYN | |
| 1107 | + * without PT_INTERP, usually the ELF interpreter | |
| 1108 | + * itself). Loaders must be loaded away from programs | |
| 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 | 1114 | * "./ld.so someprog" to test out a new version of |
| 1110 | 1115 | * the loader, the subsequent program that the |
| 1111 | 1116 | * loader loads must avoid the loader itself, so |
| @@ -1118,6 +1123,9 @@ out_free_interp: · 6 unmodified lines | ||
| 1118 | 1123 | * ELF_ET_DYN_BASE and loaders are loaded into the |
| 1119 | 1124 | * independently randomized mmap region (0 load_bias |
| 1120 | 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 | 1130 | if (interpreter) { |
| 1123 | 1131 | /* On ET_DYN with PT_INTERP, we do the ASLR. */ |
| @@ -1234,8 +1242,6 @@ out_free_interp: · 110 unmodified lines | ||
| 1234 | 1242 | start_data += load_bias; |
| 1235 | 1243 | end_data += load_bias; |
| 1236 | 1244 | |
| 1237 | − current->mm->start_brk = current->mm->brk = ELF_PAGEALIGN(elf_brk); | |
| 1238 | − | |
| 1239 | 1245 | if (interpreter) { |
| 1240 | 1246 | elf_entry = load_elf_interp(interp_elf_ex, |
| 1241 | 1247 | interpreter, |
| @@ -1291,27 +1297,44 @@ out_free_interp: · 49 unmodified lines | ||
| 1291 | 1297 | mm->end_data = end_data; |
| 1292 | 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 | |
| 1297 | − * a loader directly (i.e. no interpreter listed in ELF | |
| 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. | |
| 1324 | + * If we didn't move the brk to ELF_ET_DYN_BASE (above), | |
| 1325 | + * leave a gap between .bss and brk. | |
| 1301 | 1326 | */ |
| 1302 | − if (IS_ENABLED(CONFIG_ARCH_HAS_ELF_RANDOMIZE) && | |
| 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. */ | |
| 1327 | + if (!brk_moved) | |
| 1307 | 1328 | mm->brk = mm->start_brk = mm->brk + PAGE_SIZE; |
| 1308 | − } | |
| 1309 | 1329 | |
| 1310 | 1330 | mm->brk = mm->start_brk = arch_randomize_brk(mm); |
| 1331 | + brk_moved = true; | |
| 1332 | + } | |
| 1333 | + | |
| 1311 | 1334 | #ifdef compat_brk_randomized |
| 1335 | + if (brk_moved) | |
| 1312 | 1336 | current->brk_randomized = 1; |
| 1313 | 1337 | #endif |
| 1314 | − } | |
| 1315 | 1338 | |
| 1316 | 1339 | if (current->personality & MMAP_PAGE_ZERO) { |
| 1317 | 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 | 94 | struct btrfs_block_group *block_group) |
| 95 | 95 | { |
| 96 | 96 | lockdep_assert_held(&discard_ctl->lock); |
| 97 | − if (!btrfs_run_discard_work(discard_ctl)) | |
| 98 | − return; | |
| 99 | 97 | |
| 100 | 98 | if (list_empty(&block_group->discard_list) || |
| 101 | 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 | 116 | if (!btrfs_is_block_group_data_only(block_group)) |
| 119 | 117 | return; |
| 120 | 118 | |
| 119 | + if (!btrfs_run_discard_work(discard_ctl)) | |
| 120 | + return; | |
| 121 | + | |
| 121 | 122 | spin_lock(&discard_ctl->lock); |
| 122 | 123 | __add_to_discard_list(discard_ctl, block_group); |
| 123 | 124 | spin_unlock(&discard_ctl->lock); |
| @@ -244,6 +245,18 @@ again: · 120 unmodified lines | ||
| 244 | 245 | block_group->used != 0) { |
| 245 | 246 | if (btrfs_is_block_group_data_only(block_group)) { |
| 246 | 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 | 260 | } else { |
| 248 | 261 | list_del_init(&block_group->discard_list); |
| 249 | 262 | btrfs_put_block_group(block_group); |
| @@ -300,6 +300,7 @@ enum { · 299 unmodified lines | ||
| 300 | 300 | #define BTRFS_FEATURE_INCOMPAT_SAFE_CLEAR 0ULL |
| 301 | 301 | |
| 302 | 302 | #define BTRFS_DEFAULT_COMMIT_INTERVAL (30) |
| 303 | +#define BTRFS_WARNING_COMMIT_INTERVAL (300) | |
| 303 | 304 | #define BTRFS_DEFAULT_MAX_INLINE (2048) |
| 304 | 305 | |
| 305 | 306 | struct btrfs_dev_replace { |
| @@ -1109,6 +1109,7 @@ static void submit_one_async_extent(struct async_chunk *async_chunk, · 1108 unmodified lines | ||
| 1109 | 1109 | struct extent_state *cached = NULL; |
| 1110 | 1110 | struct extent_map *em; |
| 1111 | 1111 | int ret = 0; |
| 1112 | + bool free_pages = false; | |
| 1112 | 1113 | u64 start = async_extent->start; |
| 1113 | 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 | 1132 | if (async_extent->compress_type == BTRFS_COMPRESS_NONE) { |
| 1133 | + ASSERT(!async_extent->folios); | |
| 1134 | + ASSERT(async_extent->nr_folios == 0); | |
| 1132 | 1135 | submit_uncompressed_range(inode, async_extent, locked_folio); |
| 1136 | + free_pages = true; | |
| 1133 | 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 | 1149 | * fall back to uncompressed. |
| 1146 | 1150 | */ |
| 1147 | 1151 | submit_uncompressed_range(inode, async_extent, locked_folio); |
| 1152 | + free_pages = true; | |
| 1148 | 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 | 1191 | done: |
| 1187 | 1192 | if (async_chunk->blkcg_css) |
| 1188 | 1193 | kthread_associate_blkcg(NULL); |
| 1194 | + if (free_pages) | |
| 1195 | + free_async_extent_pages(async_extent); | |
| 1189 | 1196 | kfree(async_extent); |
| 1190 | 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 | 569 | break; |
| 570 | 570 | case Opt_commit_interval: |
| 571 | 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 | 576 | if (ctx->commit_interval == 0) |
| 573 | 577 | ctx->commit_interval = BTRFS_DEFAULT_COMMIT_INTERVAL; |
| 574 | 578 | break; |
| @@ -1220,10 +1220,8 @@ void mark_buffer_write_io_error(struct buffer_head *bh) · 1219 unmodified lines | ||
| 1220 | 1220 | /* FIXME: do we need to set this in both places? */ |
| 1221 | 1221 | if (bh->b_folio && bh->b_folio->mapping) |
| 1222 | 1222 | mapping_set_error(bh->b_folio->mapping, -EIO); |
| 1223 | − if (bh->b_assoc_map) { | |
| 1223 | + if (bh->b_assoc_map) | |
| 1224 | 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 | 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 | 2112 | write_unlock_irq(&ep->lock); |
| 2113 | 2113 | |
| 2114 | − if (!eavail && ep_schedule_timeout(to)) | |
| 2115 | − timed_out = !schedule_hrtimeout_range(to, slack, | |
| 2116 | − HRTIMER_MODE_ABS); | |
| 2114 | + if (!eavail) | |
| 2115 | + timed_out = !ep_schedule_timeout(to) || | |
| 2116 | + !schedule_hrtimeout_range(to, slack, | |
| 2117 | + HRTIMER_MODE_ABS); | |
| 2117 | 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 | 1105 | if (server->namelen == 0 || server->namelen > NFS2_MAXNAMLEN) |
| 1106 | 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 | 1111 | if (!(fattr->valid & NFS_ATTR_FATTR)) { |
| 1110 | 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 | 1201 | INIT_LIST_HEAD(&nn->nfs_volume_list); |
| 1200 | 1202 | #if IS_ENABLED(CONFIG_NFS_V4) |
| 1201 | 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 | 1208 | #endif |
| 1203 | 1209 | spin_lock_init(&nn->nfs_client_lock); |
| 1204 | 1210 | nn->boot_time = ktime_get_real(); |
| @@ -1216,6 +1222,9 @@ void nfs_clients_exit(struct net *net) · 11 unmodified lines | ||
| 1216 | 1222 | nfs_cleanup_cb_ident_idr(net); |
| 1217 | 1223 | WARN_ON_ONCE(!list_empty(&nn->nfs_client_list)); |
| 1218 | 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 | 1230 | #ifdef CONFIG_PROC_FS |
| @@ -2676,6 +2676,18 @@ nfs_unblock_rename(struct rpc_task *task, struct nfs_renamedata *data) · 2675 unmodified lines | ||
| 2676 | 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 | 2692 | * RENAME |
| 2681 | 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 | 2780 | nfs_sync_inode(old_inode); |
| 2768 | 2781 | task = nfs_async_rename(old_dir, new_dir, old_dentry, new_dentry, |
| 2769 | 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 | 758 | struct nfs_direct_req *dreq = hdr->dreq; |
| 759 | 759 | struct nfs_commit_info cinfo; |
| 760 | − struct nfs_page *req = nfs_list_entry(hdr->pages.next); | |
| 761 | 760 | struct inode *inode = dreq->inode; |
| 762 | 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 | 785 | spin_unlock(&inode->i_lock); |
| 787 | 786 | |
| 788 | 787 | while (!list_empty(&hdr->pages)) { |
| 788 | + struct nfs_page *req; | |
| 789 | 789 | |
| 790 | 790 | req = nfs_list_entry(hdr->pages.next); |
| 791 | 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 | 76 | struct page *scratch; |
| 77 | 77 | struct list_head dsaddrs; |
| 78 | 78 | struct nfs4_pnfs_ds_addr *da; |
| 79 | + struct net *net = server->nfs_client->cl_net; | |
| 79 | 80 | |
| 80 | 81 | /* set up xdr stream */ |
| 81 | 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 | 161 | mp_count = be32_to_cpup(p); /* multipath count */ |
| 161 | 162 | for (j = 0; j < mp_count; j++) { |
| 162 | − da = nfs4_decode_mp_ds_addr(server->nfs_client->cl_net, | |
| 163 | − &stream, gfp_flags); | |
| 163 | + da = nfs4_decode_mp_ds_addr(net, &stream, gfp_flags); | |
| 164 | 164 | if (da) |
| 165 | 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 | 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 | 174 | if (!dsaddr->ds_list[i]) |
| 175 | 175 | goto out_err_drain_dsaddrs; |
| 176 | 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 | 1329 | hdr->args.offset, hdr->args.count, |
| 1330 | 1330 | &hdr->res.op_status, OP_READ, |
| 1331 | 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 | 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 | 1502 | hdr->args.offset, hdr->args.count, |
| 1503 | 1503 | &hdr->res.op_status, OP_WRITE, |
| 1504 | 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 | 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 | 1551 | data->args.offset, data->args.count, |
| 1552 | 1552 | &data->res.op_status, OP_COMMIT, |
| 1553 | 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 | 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 | 49 | struct nfs4_pnfs_ds_addr *da; |
| 50 | 50 | struct nfs4_ff_layout_ds *new_ds = NULL; |
| 51 | 51 | struct nfs4_ff_ds_version *ds_versions = NULL; |
| 52 | + struct net *net = server->nfs_client->cl_net; | |
| 52 | 53 | u32 mp_count; |
| 53 | 54 | u32 version_count; |
| 54 | 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 | 82 | for (i = 0; i < mp_count; i++) { |
| 82 | 83 | /* multipath ds */ |
| 83 | − da = nfs4_decode_mp_ds_addr(server->nfs_client->cl_net, | |
| 84 | − &stream, gfp_flags); | |
| 84 | + da = nfs4_decode_mp_ds_addr(net, &stream, gfp_flags); | |
| 85 | 85 | if (da) |
| 86 | 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 | 149 | new_ds->ds_versions = ds_versions; |
| 150 | 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 | 153 | if (!new_ds->ds) |
| 154 | 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 | 278 | new = __nfs_local_open_fh(clp, cred, fh, nfl, mode); |
| 279 | 279 | if (IS_ERR(new)) |
| 280 | 280 | return NULL; |
| 281 | + rcu_read_lock(); | |
| 281 | 282 | /* try to swap in the pointer */ |
| 282 | 283 | spin_lock(&clp->cl_uuid.lock); |
| 283 | 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 | 288 | rcu_assign_pointer(*pnf, nf); |
| 288 | 289 | } |
| 289 | 290 | spin_unlock(&clp->cl_uuid.lock); |
| 290 | − rcu_read_lock(); | |
| 291 | 291 | } |
| 292 | 292 | nf = nfs_local_file_get(nf); |
| 293 | 293 | rcu_read_unlock(); |
| @@ -31,7 +31,11 @@ struct nfs_net { · 30 unmodified lines | ||
| 31 | 31 | unsigned short nfs_callback_tcpport; |
| 32 | 32 | unsigned short nfs_callback_tcpport6; |
| 33 | 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 | 39 | struct nfs_netns_client *nfs_client; |
| 36 | 40 | spinlock_t nfs_client_lock; |
| 37 | 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 | 105 | switch (status) { |
| 106 | 106 | case 0: |
| 107 | − status = nfs_refresh_inode(inode, res.fattr); | |
| 107 | + nfs_refresh_inode(inode, res.fattr); | |
| 108 | 108 | break; |
| 109 | 109 | case -EPFNOSUPPORT: |
| 110 | 110 | case -EPROTONOSUPPORT: |
| @@ -671,6 +671,15 @@ nfs4_async_handle_exception(struct rpc_task *task, struct nfs_server *server, · 670 unmodified lines | ||
| 671 | 671 | struct nfs_client *clp = server->nfs_client; |
| 672 | 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 | 683 | ret = nfs4_do_handle_exception(server, errorcode, exception); |
| 675 | 684 | if (exception->delay) { |
| 676 | 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 | 7083 | struct nfs4_unlockdata *p; |
| 7075 | 7084 | struct nfs4_state *state = lsp->ls_state; |
| 7076 | 7085 | struct inode *inode = state->inode; |
| 7086 | + struct nfs_lock_context *l_ctx; | |
| 7077 | 7087 | |
| 7078 | 7088 | p = kzalloc(sizeof(*p), GFP_KERNEL); |
| 7079 | 7089 | if (p == NULL) |
| 7080 | 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 | 7098 | p->arg.fh = NFS_FH(inode); |
| 7082 | 7099 | p->arg.fl = &p->fl; |
| 7083 | 7100 | p->arg.seqid = seqid; |
| @@ -7085,7 +7102,6 @@ static struct nfs4_unlockdata *nfs4_alloc_unlockdata(struct file_lock *fl, · 1 unmodified line | ||
| 7085 | 7102 | p->lsp = lsp; |
| 7086 | 7103 | /* Ensure we don't close file until we're done freeing locks! */ |
| 7087 | 7104 | p->ctx = get_nfs_open_context(ctx); |
| 7088 | − p->l_ctx = nfs_get_lock_context(ctx); | |
| 7089 | 7105 | locks_init_lock(&p->fl); |
| 7090 | 7106 | locks_copy_lock(&p->fl, fl); |
| 7091 | 7107 | p->server = NFS_SERVER(inode); |
| @@ -2051,13 +2051,15 @@ TRACE_EVENT(fl_getdevinfo, · 2050 unmodified lines | ||
| 2051 | 2051 | |
| 2052 | 2052 | DECLARE_EVENT_CLASS(nfs4_flexfiles_io_event, |
| 2053 | 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 | 2060 | TP_STRUCT__entry( |
| 2060 | 2061 | __field(unsigned long, error) |
| 2062 | + __field(unsigned long, nfs_error) | |
| 2061 | 2063 | __field(dev_t, dev) |
| 2062 | 2064 | __field(u32, fhandle) |
| 2063 | 2065 | __field(u64, fileid) |
| @@ -2073,7 +2075,8 @@ DECLARE_EVENT_CLASS(nfs4_flexfiles_io_event, · 9 unmodified lines | ||
| 2073 | 2075 | TP_fast_assign( |
| 2074 | 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 | 2080 | __entry->fhandle = nfs_fhandle_hash(hdr->args.fh); |
| 2078 | 2081 | __entry->fileid = NFS_FILEID(inode); |
| 2079 | 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 | 2092 | TP_printk( |
| 2090 | 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 | 2096 | -__entry->error, |
| 2093 | 2097 | show_nfs4_status(__entry->error), |
| 2094 | 2098 | MAJOR(__entry->dev), MINOR(__entry->dev), |
| @@ -2096,28 +2100,32 @@ DECLARE_EVENT_CLASS(nfs4_flexfiles_io_event, · 1 unmodified line | ||
| 2096 | 2100 | __entry->fhandle, |
| 2097 | 2101 | __entry->offset, __entry->count, |
| 2098 | 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 | 2108 | #define DEFINE_NFS4_FLEXFILES_IO_EVENT(name) \ |
| 2104 | 2109 | DEFINE_EVENT(nfs4_flexfiles_io_event, name, \ |
| 2105 | 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 | 2115 | DEFINE_NFS4_FLEXFILES_IO_EVENT(ff_layout_read_error); |
| 2110 | 2116 | DEFINE_NFS4_FLEXFILES_IO_EVENT(ff_layout_write_error); |
| 2111 | 2117 | |
| 2112 | 2118 | TRACE_EVENT(ff_layout_commit_error, |
| 2113 | 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 | 2126 | TP_STRUCT__entry( |
| 2120 | 2127 | __field(unsigned long, error) |
| 2128 | + __field(unsigned long, nfs_error) | |
| 2121 | 2129 | __field(dev_t, dev) |
| 2122 | 2130 | __field(u32, fhandle) |
| 2123 | 2131 | __field(u64, fileid) |
| @@ -2131,7 +2139,8 @@ TRACE_EVENT(ff_layout_commit_error, · 7 unmodified lines | ||
| 2131 | 2139 | TP_fast_assign( |
| 2132 | 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 | 2144 | __entry->fhandle = nfs_fhandle_hash(data->args.fh); |
| 2136 | 2145 | __entry->fileid = NFS_FILEID(inode); |
| 2137 | 2146 | __entry->dev = inode->i_sb->s_dev; |
| @@ -2142,14 +2151,15 @@ TRACE_EVENT(ff_layout_commit_error, · 4 unmodified lines | ||
| 2142 | 2151 | |
| 2143 | 2152 | TP_printk( |
| 2144 | 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 | 2155 | -__entry->error, |
| 2147 | 2156 | show_nfs4_status(__entry->error), |
| 2148 | 2157 | MAJOR(__entry->dev), MINOR(__entry->dev), |
| 2149 | 2158 | (unsigned long long)__entry->fileid, |
| 2150 | 2159 | __entry->fhandle, |
| 2151 | 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 | 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 | 756 | static void |
| 749 | 757 | pnfs_free_returned_lsegs(struct pnfs_layout_hdr *lo, |
| 750 | 758 | struct list_head *free_me, |
| @@ -1246,21 +1254,15 @@ static void pnfs_clear_layoutcommit(struct inode *inode, · 495 unmodified lines | ||
| 1246 | 1254 | static void |
| 1247 | 1255 | pnfs_layoutreturn_retry_later_locked(struct pnfs_layout_hdr *lo, |
| 1248 | 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 | 1260 | if (pnfs_layout_is_valid(lo) && |
| 1255 | − nfs4_stateid_match_other(&lo->plh_stateid, arg_stateid)) { | |
| 1256 | − list_for_each_entry(lseg, &lo->plh_return_segs, pls_list) { | |
| 1257 | − if (pnfs_seqid_is_newer(lseg->pls_seq, seq) || | |
| 1258 | − !pnfs_should_free_range(&lseg->pls_range, range)) | |
| 1259 | − continue; | |
| 1260 | − pnfs_set_plh_return_info(lo, range->iomode, seq); | |
| 1261 | − break; | |
| 1262 | − } | |
| 1263 | − } | |
| 1261 | + nfs4_stateid_match_other(&lo->plh_stateid, arg_stateid)) | |
| 1262 | + pnfs_reset_return_info(lo); | |
| 1263 | + else | |
| 1264 | + pnfs_mark_layout_stateid_invalid(lo, freeme); | |
| 1265 | + pnfs_clear_layoutreturn_waitbit(lo); | |
| 1264 | 1266 | } |
| 1265 | 1267 | |
| 1266 | 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 | 1270 | const struct pnfs_layout_range *range) |
| 1269 | 1271 | { |
| 1270 | 1272 | struct inode *inode = lo->plh_inode; |
| 1273 | + LIST_HEAD(freeme); | |
| 1271 | 1274 | |
| 1272 | 1275 | spin_lock(&inode->i_lock); |
| 1273 | − pnfs_layoutreturn_retry_later_locked(lo, arg_stateid, range); | |
| 1274 | − pnfs_clear_layoutreturn_waitbit(lo); | |
| 1276 | + pnfs_layoutreturn_retry_later_locked(lo, arg_stateid, range, &freeme); | |
| 1275 | 1277 | spin_unlock(&inode->i_lock); |
| 1278 | + pnfs_free_lseg_list(&freeme); | |
| 1276 | 1279 | } |
| 1277 | 1280 | |
| 1278 | 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 | 1295 | pnfs_mark_matching_lsegs_invalid(lo, &freeme, range, seq); |
| 1293 | 1296 | pnfs_free_returned_lsegs(lo, &freeme, range, seq); |
| 1294 | 1297 | pnfs_set_layout_stateid(lo, stateid, NULL, true); |
| 1298 | + pnfs_reset_return_info(lo); | |
| 1295 | 1299 | } else |
| 1296 | 1300 | pnfs_mark_layout_stateid_invalid(lo, &freeme); |
| 1297 | 1301 | out_unlock: |
| @@ -1661,6 +1665,18 @@ int pnfs_roc_done(struct rpc_task *task, struct nfs4_layoutreturn_args **argpp, · 363 unmodified lines | ||
| 1661 | 1665 | /* Was there an RPC level error? If not, retry */ |
| 1662 | 1666 | if (task->tk_rpc_status == 0) |
| 1663 | 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 | 1680 | /* If the call was not sent, let caller handle it */ |
| 1665 | 1681 | if (!RPC_WAS_SENT(task)) |
| 1666 | 1682 | return 0; |
| @@ -1695,6 +1711,7 @@ void pnfs_roc_release(struct nfs4_layoutreturn_args *args, · 28 unmodified lines | ||
| 1695 | 1711 | struct inode *inode = args->inode; |
| 1696 | 1712 | const nfs4_stateid *res_stateid = NULL; |
| 1697 | 1713 | struct nfs4_xdr_opaque_data *ld_private = args->ld_private; |
| 1714 | + LIST_HEAD(freeme); | |
| 1698 | 1715 | |
| 1699 | 1716 | switch (ret) { |
| 1700 | 1717 | case -NFS4ERR_BADSESSION: |
| @@ -1703,9 +1720,9 @@ void pnfs_roc_release(struct nfs4_layoutreturn_args *args, · 2 unmodified lines | ||
| 1703 | 1720 | case -NFS4ERR_NOMATCHING_LAYOUT: |
| 1704 | 1721 | spin_lock(&inode->i_lock); |
| 1705 | 1722 | pnfs_layoutreturn_retry_later_locked(lo, &args->stateid, |
| 1706 | − &args->range); | |
| 1707 | − pnfs_clear_layoutreturn_waitbit(lo); | |
| 1723 | + &args->range, &freeme); | |
| 1708 | 1724 | spin_unlock(&inode->i_lock); |
| 1725 | + pnfs_free_lseg_list(&freeme); | |
| 1709 | 1726 | break; |
| 1710 | 1727 | case 0: |
| 1711 | 1728 | if (res->lrs_present) |
| @@ -60,6 +60,7 @@ struct nfs4_pnfs_ds { · 59 unmodified lines | ||
| 60 | 60 | struct list_head ds_node; /* nfs4_pnfs_dev_hlist dev_dslist */ |
| 61 | 61 | char *ds_remotestr; /* comma sep list of addrs */ |
| 62 | 62 | struct list_head ds_addrs; |
| 63 | + const struct net *ds_net; | |
| 63 | 64 | struct nfs_client *ds_clp; |
| 64 | 65 | refcount_t ds_count; |
| 65 | 66 | unsigned long ds_state; |
| @@ -415,7 +416,8 @@ int pnfs_generic_commit_pagelist(struct inode *inode, · 349 unmodified lines | ||
| 415 | 416 | int pnfs_generic_scan_commit_lists(struct nfs_commit_info *cinfo, int max); |
| 416 | 417 | void pnfs_generic_write_commit_done(struct rpc_task *task, void *data); |
| 417 | 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 | 421 | gfp_t gfp_flags); |
| 420 | 422 | void nfs4_pnfs_v3_ds_connect_unload(void); |
| 421 | 423 | int nfs4_pnfs_ds_connect(struct nfs_server *mds_srv, struct nfs4_pnfs_ds *ds, |
| @@ -16,6 +16,7 @@ · 15 unmodified lines | ||
| 16 | 16 | #include "nfs4session.h" |
| 17 | 17 | #include "internal.h" |
| 18 | 18 | #include "pnfs.h" |
| 19 | +#include "netns.h" | |
| 19 | 20 | |
| 20 | 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 | 506 | * Data server cache |
| 506 | 507 | * |
| 507 | − * Data servers can be mapped to different device ids. | |
| 508 | − * nfs4_pnfs_ds reference counting | |
| 508 | + * Data servers can be mapped to different device ids, but should | |
| 509 | + * never be shared between net namespaces. | |
| 510 | + * | |
| 511 | + * nfs4_pnfs_ds reference counting: | |
| 509 | 512 | * - set to 1 on allocation |
| 510 | 513 | * - incremented when a device id maps a data server already in the cache. |
| 511 | 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 | 517 | /* Debug routines */ |
| 517 | 518 | static void |
| @@ -604,11 +605,11 @@ _same_data_server_addrs_locked(const struct list_head *dsaddrs1, · 86 unmodified lines | ||
| 604 | 605 | * Lookup DS by addresses. nfs4_ds_cache_lock is held |
| 605 | 606 | */ |
| 606 | 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 | 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 | 613 | if (_same_data_server_addrs_locked(&ds->ds_addrs, dsaddrs)) |
| 613 | 614 | return ds; |
| 614 | 615 | return NULL; |
| @@ -653,10 +654,11 @@ static void destroy_ds(struct nfs4_pnfs_ds *ds) · 38 unmodified lines | ||
| 653 | 654 | |
| 654 | 655 | void nfs4_pnfs_ds_put(struct nfs4_pnfs_ds *ds) |
| 655 | 656 | { |
| 656 | − if (refcount_dec_and_lock(&ds->ds_count, | |
| 657 | − &nfs4_ds_cache_lock)) { | |
| 657 | + struct nfs_net *nn = net_generic(ds->ds_net, nfs_net_id); | |
| 658 | + | |
| 659 | + if (refcount_dec_and_lock(&ds->ds_count, &nn->nfs4_data_server_lock)) { | |
| 658 | 660 | list_del_init(&ds->ds_node); |
| 659 | − spin_unlock(&nfs4_ds_cache_lock); | |
| 661 | + spin_unlock(&nn->nfs4_data_server_lock); | |
| 660 | 662 | destroy_ds(ds); |
| 661 | 663 | } |
| 662 | 664 | } |
| @@ -716,8 +718,9 @@ out_err: · 53 unmodified lines | ||
| 716 | 718 | * uncached and return cached struct nfs4_pnfs_ds. |
| 717 | 719 | */ |
| 718 | 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 | 724 | struct nfs4_pnfs_ds *tmp_ds, *ds = NULL; |
| 722 | 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 | 736 | /* this is only used for debugging, so it's ok if its NULL */ |
| 734 | 737 | remotestr = nfs4_pnfs_remotestr(dsaddrs, gfp_flags); |
| 735 | 738 | |
| 736 | − spin_lock(&nfs4_ds_cache_lock); | |
| 737 | − tmp_ds = _data_server_lookup_locked(dsaddrs); | |
| 739 | + spin_lock(&nn->nfs4_data_server_lock); | |
| 740 | + tmp_ds = _data_server_lookup_locked(nn, dsaddrs); | |
| 738 | 741 | if (tmp_ds == NULL) { |
| 739 | 742 | INIT_LIST_HEAD(&ds->ds_addrs); |
| 740 | 743 | list_splice_init(dsaddrs, &ds->ds_addrs); |
| 741 | 744 | ds->ds_remotestr = remotestr; |
| 742 | 745 | refcount_set(&ds->ds_count, 1); |
| 743 | 746 | INIT_LIST_HEAD(&ds->ds_node); |
| 747 | + ds->ds_net = net; | |
| 744 | 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 | 750 | dprintk("%s add new data server %s\n", __func__, |
| 747 | 751 | ds->ds_remotestr); |
| 748 | 752 | } else { |
| @@ -754,7 +758,7 @@ nfs4_pnfs_ds_add(struct list_head *dsaddrs, gfp_t gfp_flags) · 5 unmodified lines | ||
| 754 | 758 | refcount_read(&tmp_ds->ds_count)); |
| 755 | 759 | ds = tmp_ds; |
| 756 | 760 | } |
| 757 | − spin_unlock(&nfs4_ds_cache_lock); | |
| 761 | + spin_unlock(&nn->nfs4_data_server_lock); | |
| 758 | 762 | out: |
| 759 | 763 | return ds; |
| 760 | 764 | } |
| @@ -160,8 +160,10 @@ static int cifs_prepare_read(struct netfs_io_subrequest *subreq) · 159 unmodified lines | ||
| 160 | 160 | server = cifs_pick_channel(tlink_tcon(req->cfile->tlink)->ses); |
| 161 | 161 | rdata->server = server; |
| 162 | 162 | |
| 163 | − cifs_negotiate_rsize(server, cifs_sb->ctx, | |
| 164 | − tlink_tcon(req->cfile->tlink)); | |
| 163 | + if (cifs_sb->ctx->rsize == 0) { | |
| 164 | + cifs_negotiate_rsize(server, cifs_sb->ctx, | |
| 165 | + tlink_tcon(req->cfile->tlink)); | |
| 166 | + } | |
| 165 | 167 | |
| 166 | 168 | rc = server->ops->wait_mtu_credits(server, cifs_sb->ctx->rsize, |
| 167 | 169 | &size, &rdata->credits); |
| @@ -2968,7 +2968,7 @@ replay_again: · 2967 unmodified lines | ||
| 2968 | 2968 | /* Eventually save off posix specific response info and timestamps */ |
| 2969 | 2969 | |
| 2970 | 2970 | err_free_rsp_buf: |
| 2971 | − free_rsp_buf(resp_buftype, rsp); | |
| 2971 | + free_rsp_buf(resp_buftype, rsp_iov.iov_base); | |
| 2972 | 2972 | kfree(pc_buf); |
| 2973 | 2973 | err_free_req: |
| 2974 | 2974 | cifs_small_buf_release(req); |
| @@ -115,7 +115,7 @@ void udf_truncate_tail_extent(struct inode *inode) · 114 unmodified lines | ||
| 115 | 115 | } |
| 116 | 116 | /* This inode entry is in-memory only and thus we don't have to mark |
| 117 | 117 | * the inode dirty */ |
| 118 | − if (ret == 0) | |
| 118 | + if (ret >= 0) | |
| 119 | 119 | iinfo->i_lenExtents = inode->i_size; |
| 120 | 120 | brelse(epos.bh); |
| 121 | 121 | } |
| @@ -1428,6 +1428,15 @@ static bool xattr_is_trusted(const char *name) · 1427 unmodified lines | ||
| 1428 | 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 | 1441 | * simple_xattr_list - list all xattr objects |
| 1433 | 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 | 1469 | if (err) |
| 1461 | 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 | 1483 | read_lock(&xattrs->lock); |
| 1464 | 1484 | for (rbp = rb_first(&xattrs->rb_root); rbp; rbp = rb_next(rbp)) { |
| 1465 | 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 | 1488 | if (!trusted && xattr_is_trusted(xattr->name)) |
| 1469 | 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 | 1495 | err = xattr_list_one(&buffer, &remaining_size, xattr->name); |
| 1472 | 1496 | if (err) |
| 1473 | 1497 | break; |
| @@ -1149,7 +1149,7 @@ xfs_init_percpu_counters( · 1148 unmodified lines | ||
| 1149 | 1149 | return 0; |
| 1150 | 1150 | |
| 1151 | 1151 | free_freecounters: |
| 1152 | − while (--i > 0) | |
| 1152 | + while (--i >= 0) | |
| 1153 | 1153 | percpu_counter_destroy(&mp->m_free[i].count); |
| 1154 | 1154 | percpu_counter_destroy(&mp->m_delalloc_rtextents); |
| 1155 | 1155 | free_delalloc: |
| @@ -2114,6 +2114,21 @@ xfs_fs_reconfigure( · 958 unmodified lines | ||
| 2114 | 2114 | if (error) |
| 2115 | 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 | 2132 | /* inode32 -> inode64 */ |
| 2118 | 2133 | if (xfs_has_small_inums(mp) && !xfs_has_small_inums(new_mp)) { |
| 2119 | 2134 | mp->m_features &= ~XFS_FEAT_SMALL_INUMS; |
| @@ -2126,6 +2141,17 @@ xfs_fs_reconfigure( · 6 unmodified lines | ||
| 2126 | 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 | 2155 | /* ro -> rw */ |
| 2130 | 2156 | if (xfs_is_readonly(mp) && !(flags & SB_RDONLY)) { |
| 2131 | 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 | 320 | static void |
| 321 | 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 | 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 | |
| 785 | − * it to the AIL. If we move the first item in the AIL, update the log tail to | |
| 786 | − * match the new minimum LSN in the AIL. | |
| 784 | + * be added. Otherwise, it will be repositioned by removing it and re-adding | |
| 785 | + * it to the AIL. | |
| 787 | 786 | * |
| 788 | − * This function takes the AIL lock once to execute the update operations on | |
| 789 | − * all the items in the array, and as such should not be called with 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. | |
| 787 | + * If we move the first item in the AIL, update the log tail to match the new | |
| 788 | + * minimum LSN in the AIL. | |
| 792 | 789 | * |
| 793 | − * To optimise the insert operation, we delete all the items from the AIL in | |
| 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. | |
| 790 | + * This function should be called with the AIL lock held. | |
| 797 | 791 | * |
| 798 | − * This function must be called with the AIL lock held. The lock is dropped | |
| 799 | − * before returning. | |
| 792 | + * To optimise the insert operation, we add all items to a temporary list, then | |
| 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 | 803 | void |
| 802 | 804 | xfs_trans_ail_update_bulk( |
| @@ -807,7 +807,8 @@ xfs_zone_gc_write_chunk( · 806 unmodified lines | ||
| 807 | 807 | { |
| 808 | 808 | struct xfs_zone_gc_data *data = chunk->data; |
| 809 | 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 | 812 | struct xfs_gc_bio *split_chunk; |
| 812 | 813 | |
| 813 | 814 | if (chunk->bio.bi_status) |
| @@ -822,7 +823,7 @@ xfs_zone_gc_write_chunk( · 8 unmodified lines | ||
| 822 | 823 | |
| 823 | 824 | bio_reset(&chunk->bio, mp->m_rtdev_targp->bt_bdev, REQ_OP_WRITE); |
| 824 | 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 | 828 | while ((split_chunk = xfs_zone_gc_split_write(data, chunk))) |
| 828 | 829 | xfs_zone_gc_submit_write(data, split_chunk); |
| @@ -89,6 +89,7 @@ struct drm_gpusvm_devmem_ops { · 88 unmodified lines | ||
| 89 | 89 | * @ops: Pointer to the operations structure for GPU SVM device memory |
| 90 | 90 | * @dpagemap: The struct drm_pagemap of the pages this allocation belongs to. |
| 91 | 91 | * @size: Size of device memory allocation |
| 92 | + * @timeslice_expiration: Timeslice expiration in jiffies | |
| 92 | 93 | */ |
| 93 | 94 | struct drm_gpusvm_devmem { |
| 94 | 95 | struct device *dev; |
| @@ -97,6 +98,7 @@ struct drm_gpusvm_devmem { · 2 unmodified lines | ||
| 97 | 98 | const struct drm_gpusvm_devmem_ops *ops; |
| 98 | 99 | struct drm_pagemap *dpagemap; |
| 99 | 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 | 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 | 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 | 225 | * @dpagemap: The struct drm_pagemap of the device pages we're dma-mapping. |
| 199 | 226 | * Note this is assuming only one drm_pagemap per range is allowed. |
| 200 | 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 | 229 | * This structure represents a GPU SVM range used for tracking memory ranges |
| 208 | 230 | * mapped in a DRM device. |
| @@ -216,15 +238,7 @@ struct drm_gpusvm_range { · 7 unmodified lines | ||
| 216 | 238 | unsigned long notifier_seq; |
| 217 | 239 | struct drm_pagemap_device_addr *dma_addr; |
| 218 | 240 | struct drm_pagemap *dpagemap; |
| 219 | − struct { | |
| 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; | |
| 241 | + struct drm_gpusvm_range_flags flags; | |
| 228 | 242 | }; |
| 229 | 243 | |
| 230 | 244 | /** |
| @@ -283,17 +297,22 @@ struct drm_gpusvm { · 52 unmodified lines | ||
| 283 | 297 | * @check_pages_threshold: Check CPU pages for present if chunk is less than or |
| 284 | 298 | * equal to threshold. If not present, reduce chunk |
| 285 | 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 | 302 | * @in_notifier: entering from a MMU notifier |
| 287 | 303 | * @read_only: operating on read-only memory |
| 288 | 304 | * @devmem_possible: possible to use device memory |
| 305 | + * @devmem_only: use only device memory | |
| 289 | 306 | * |
| 290 | 307 | * Context that is DRM GPUSVM is operating in (i.e. user arguments). |
| 291 | 308 | */ |
| 292 | 309 | struct drm_gpusvm_ctx { |
| 293 | 310 | unsigned long check_pages_threshold; |
| 311 | + unsigned long timeslice_ms; | |
| 294 | 312 | unsigned int in_notifier :1; |
| 295 | 313 | unsigned int read_only :1; |
| 296 | 314 | unsigned int devmem_possible :1; |
| 315 | + unsigned int devmem_only :1; | |
| 297 | 316 | }; |
| 298 | 317 | |
| 299 | 318 | int drm_gpusvm_init(struct drm_gpusvm *gpusvm, |
| @@ -11,6 +11,7 @@ · 10 unmodified lines | ||
| 11 | 11 | #include <linux/uio.h> |
| 12 | 12 | |
| 13 | 13 | #define BIO_MAX_VECS 256U |
| 14 | +#define BIO_MAX_INLINE_VECS UIO_MAXIOV | |
| 14 | 15 | |
| 15 | 16 | struct queue_limits; |
| 16 | 17 | |
| @@ -1167,13 +1167,6 @@ extern int vmbus_sendpacket(struct vmbus_channel *channel, · 1166 unmodified lines | ||
| 1167 | 1167 | enum vmbus_packet_type type, |
| 1168 | 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 | 1170 | extern int vmbus_sendpacket_mpb_desc(struct vmbus_channel *channel, |
| 1178 | 1171 | struct vmbus_packet_mpb_array *mpb, |
| 1179 | 1172 | u32 desc_size, |
| @@ -44,7 +44,6 @@ · 43 unmodified lines | ||
| 44 | 44 | #define MICREL_PHY_50MHZ_CLK BIT(0) |
| 45 | 45 | #define MICREL_PHY_FXEN BIT(1) |
| 46 | 46 | #define MICREL_KSZ8_P1_ERRATA BIT(2) |
| 47 | −#define MICREL_NO_EEE BIT(3) | |
| 48 | 47 | |
| 49 | 48 | #define MICREL_KSZ9021_EXTREG_CTRL 0xB |
| 50 | 49 | #define MICREL_KSZ9021_EXTREG_DATA_WRITE 0xC |
| @@ -213,6 +213,15 @@ struct nfs_server { · 212 unmodified lines | ||
| 213 | 213 | char *fscache_uniq; /* Uniquifier (or NULL) */ |
| 214 | 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 | 225 | u32 pnfs_blksize; /* layout_blksize attr */ |
| 217 | 226 | #if IS_ENABLED(CONFIG_NFS_V4) |
| 218 | 227 | u32 attr_bitmask[3];/* V4 bitmask representing the set |
| @@ -236,9 +245,6 @@ struct nfs_server { · 17 unmodified lines | ||
| 236 | 245 | u32 acl_bitmask; /* V4 bitmask representing the ACEs |
| 237 | 246 | that are supported on this |
| 238 | 247 | filesystem */ |
| 239 | − u32 fh_expire_type; /* V4 bitmask representing file | |
| 240 | − handle volatility type for | |
| 241 | − this filesystem */ | |
| 242 | 248 | struct pnfs_layoutdriver_type *pnfs_curr_ld; /* Active layout driver */ |
| 243 | 249 | struct rpc_wait_queue roc_rpcwaitq; |
| 244 | 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 | 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 | 198 | void pgalloc_tag_split(struct folio *folio, int old_order, int new_order); |
| 192 | 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 | 206 | static inline void alloc_tag_sec_init(void) {} |
| 200 | 207 | static inline void pgalloc_tag_split(struct folio *folio, int old_order, int new_order) {} |
| 201 | 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 | 211 | #endif /* CONFIG_MEM_ALLOC_PROFILING */ |
| 204 | 212 | |
| @@ -365,7 +365,7 @@ struct sdw_intel_res { · 364 unmodified lines | ||
| 365 | 365 | * on e.g. which machine driver to select (I2S mode, HDaudio or |
| 366 | 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 | 369 | struct sdw_intel_acpi_info *info); |
| 370 | 370 | |
| 371 | 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 | 225 | enum tpm2_timeouts { |
| 226 | 226 | TPM2_TIMEOUT_A = 750, |
| 227 | − TPM2_TIMEOUT_B = 2000, | |
| 227 | + TPM2_TIMEOUT_B = 4000, | |
| 228 | 228 | TPM2_TIMEOUT_C = 200, |
| 229 | 229 | TPM2_TIMEOUT_D = 30, |
| 230 | 230 | TPM2_DURATION_SHORT = 20, |
| @@ -257,6 +257,7 @@ enum tpm2_return_codes { · 26 unmodified lines | ||
| 257 | 257 | TPM2_RC_TESTING = 0x090A, /* RC_WARN */ |
| 258 | 258 | TPM2_RC_REFERENCE_H0 = 0x0910, |
| 259 | 259 | TPM2_RC_RETRY = 0x0922, |
| 260 | + TPM2_RC_SESSION_MEMORY = 0x0903, | |
| 260 | 261 | }; |
| 261 | 262 | |
| 262 | 263 | enum tpm2_command_codes { |
| @@ -437,6 +438,24 @@ static inline u32 tpm2_rc_value(u32 rc) · 174 unmodified lines | ||
| 437 | 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 | 459 | #if defined(CONFIG_TCG_TPM) || defined(CONFIG_TCG_TPM_MODULE) |
| 441 | 460 | |
| 442 | 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 | 1798 | void hci_uuids_clear(struct hci_dev *hdev); |
| 1799 | 1799 | |
| 1800 | 1800 | void hci_link_keys_clear(struct hci_dev *hdev); |
| 1801 | +u8 *hci_conn_key_enc_size(struct hci_conn *conn); | |
| 1801 | 1802 | struct link_key *hci_find_link_key(struct hci_dev *hdev, bdaddr_t *bdaddr); |
| 1802 | 1803 | struct link_key *hci_add_link_key(struct hci_dev *hdev, struct hci_conn *conn, |
| 1803 | 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 | 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 | 1049 | static inline struct sk_buff *qdisc_dequeue_head(struct Qdisc *sch) |
| 1035 | 1050 | { |
| 1036 | 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 | 604 | } __packed; |
| 605 | 605 | |
| 606 | 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 | 608 | #ifdef __BIG_ENDIAN_BITFIELD |
| 609 | 609 | /* 0 */ |
| 610 | 610 | u32 type:4; |
| @@ -754,7 +754,7 @@ struct snd_ump_stream_msg_fb_name { · 143 unmodified lines | ||
| 754 | 754 | union snd_ump_stream_msg { |
| 755 | 755 | struct snd_ump_stream_msg_ep_discovery ep_discovery; |
| 756 | 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 | 758 | struct snd_ump_stream_msg_stream_cfg stream_cfg; |
| 759 | 759 | struct snd_ump_stream_msg_fb_discovery fb_discovery; |
| 760 | 760 | struct snd_ump_stream_msg_fb_info fb_info; |
| @@ -87,11 +87,6 @@ config CC_CAN_LINK · 86 unmodified lines | ||
| 87 | 87 | default $(success,$(srctree)/scripts/cc-can-link.sh $(CC) $(CLANG_FLAGS) $(USERCFLAGS) $(USERLDFLAGS) $(m64-flag)) if 64BIT |
| 88 | 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 | 90 | # Fixed in GCC 14, 13.3, 12.4 and 11.5 |
| 96 | 91 | # https://gcc.gnu.org/bugzilla/show_bug.cgi?id=113921 |
| 97 | 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 | 87 | #endif |
| 88 | 88 | |
| 89 | −/* | |
| 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) | |
| 89 | +static void __io_uring_show_fdinfo(struct io_ring_ctx *ctx, struct seq_file *m) | |
| 94 | 90 | { |
| 95 | − struct io_ring_ctx *ctx = file->private_data; | |
| 96 | 91 | struct io_overflow_cqe *ocqe; |
| 97 | 92 | struct io_rings *r = ctx->rings; |
| 98 | 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 | 101 | unsigned int sq_entries, cq_entries; |
| 107 | 102 | int sq_pid = -1, sq_cpu = -1; |
| 108 | 103 | u64 sq_total_time = 0, sq_work_time = 0; |
| 109 | − bool has_lock; | |
| 110 | 104 | unsigned int i; |
| 111 | 105 | |
| 112 | 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 | 170 | seq_printf(m, "\n"); |
| 177 | 171 | } |
| 178 | 172 | |
| 179 | − /* | |
| 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)) { | |
| 173 | + if (ctx->flags & IORING_SETUP_SQPOLL) { | |
| 188 | 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 | 192 | seq_printf(m, "SqTotalTime:\t%llu\n", sq_total_time); |
| 207 | 193 | seq_printf(m, "SqWorkTime:\t%llu\n", sq_work_time); |
| 208 | 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 | 196 | struct file *f = NULL; |
| 211 | 197 | |
| 212 | 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 | 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 | 208 | struct io_mapped_ubuf *buf = NULL; |
| 223 | 209 | |
| 224 | 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 | 214 | else |
| 229 | 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 | 218 | unsigned long index; |
| 233 | 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 | 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 | 228 | struct io_hash_bucket *hb = &ctx->cancel_table.hbs[i]; |
| 243 | 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 | 233 | task_work_pending(req->tctx->task)); |
| 248 | 234 | } |
| 249 | 235 | |
| 250 | − if (has_lock) | |
| 251 | − mutex_unlock(&ctx->uring_lock); | |
| 252 | − | |
| 253 | 236 | seq_puts(m, "CqOverflowList:\n"); |
| 254 | 237 | spin_lock(&ctx->completion_lock); |
| 255 | 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 | 245 | spin_unlock(&ctx->completion_lock); |
| 263 | 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 | 267 | #endif |
| @@ -116,7 +116,7 @@ static int io_region_init_ptr(struct io_mapped_region *mr) · 115 unmodified lines | ||
| 116 | 116 | void *ptr; |
| 117 | 117 | |
| 118 | 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 | 120 | mr->ptr = page_address(mr->pages[0]); |
| 121 | 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 | 254 | return -EOPNOTSUPP; |
| 255 | 255 | issue_flags |= IO_URING_F_IOPOLL; |
| 256 | 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 | 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 | 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 | 1124 | continue; |
| 1123 | 1125 | cpumask_andnot(new_cpus, possible_mask, subpartitions_cpus); |
| 1124 | 1126 | } else { |
| @@ -498,10 +498,6 @@ struct vm_area_struct *vm_area_dup(struct vm_area_struct *orig) · 497 unmodified lines | ||
| 498 | 498 | vma_numab_state_init(new); |
| 499 | 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 | 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 | 668 | tmp = vm_area_dup(mpnt); |
| 673 | 669 | if (!tmp) |
| 674 | 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 | 676 | retval = vma_dup_policy(mpnt, tmp); |
| 676 | 677 | if (retval) |
| 677 | 678 | goto fail_nomem_policy; |
| @@ -192,6 +192,11 @@ config GENDWARFKSYMS · 191 unmodified lines | ||
| 192 | 192 | depends on !DEBUG_INFO_REDUCED && !DEBUG_INFO_SPLIT |
| 193 | 193 | # Requires ELF object files. |
| 194 | 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 | 200 | help |
| 196 | 201 | Calculate symbol versions from DWARF debugging information using |
| 197 | 202 | gendwarfksyms. Requires DEBUG_INFO to be enabled. |
| @@ -1118,8 +1118,38 @@ static void scx_kf_disallow(u32 mask) · 1117 unmodified lines | ||
| 1118 | 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 | 1151 | do { \ |
| 1152 | + update_locked_rq(rq); \ | |
| 1123 | 1153 | if (mask) { \ |
| 1124 | 1154 | scx_kf_allow(mask); \ |
| 1125 | 1155 | scx_ops.op(args); \ |
| @@ -1127,11 +1157,14 @@ do { \ · 1 unmodified line | ||
| 1127 | 1157 | } else { \ |
| 1128 | 1158 | scx_ops.op(args); \ |
| 1129 | 1159 | } \ |
| 1160 | + update_locked_rq(NULL); \ | |
| 1130 | 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 | 1165 | __typeof__(scx_ops.op(args)) __ret; \ |
| 1166 | + \ | |
| 1167 | + update_locked_rq(rq); \ | |
| 1135 | 1168 | if (mask) { \ |
| 1136 | 1169 | scx_kf_allow(mask); \ |
| 1137 | 1170 | __ret = scx_ops.op(args); \ |
| @@ -1139,6 +1172,7 @@ do { \ · 1 unmodified line | ||
| 1139 | 1172 | } else { \ |
| 1140 | 1173 | __ret = scx_ops.op(args); \ |
| 1141 | 1174 | } \ |
| 1175 | + update_locked_rq(NULL); \ | |
| 1142 | 1176 | __ret; \ |
| 1143 | 1177 | }) |
| 1144 | 1178 | |
| @@ -1153,31 +1187,31 @@ do { \ · 8 unmodified lines | ||
| 1153 | 1187 | * scx_kf_allowed_on_arg_tasks() to test whether the invocation is allowed on |
| 1154 | 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 | 1191 | do { \ |
| 1158 | 1192 | BUILD_BUG_ON((mask) & ~__SCX_KF_TERMINAL); \ |
| 1159 | 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 | 1195 | current->scx.kf_tasks[0] = NULL; \ |
| 1162 | 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 | 1200 | __typeof__(scx_ops.op(task, ##args)) __ret; \ |
| 1167 | 1201 | BUILD_BUG_ON((mask) & ~__SCX_KF_TERMINAL); \ |
| 1168 | 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 | 1204 | current->scx.kf_tasks[0] = NULL; \ |
| 1171 | 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 | 1210 | __typeof__(scx_ops.op(task0, task1, ##args)) __ret; \ |
| 1177 | 1211 | BUILD_BUG_ON((mask) & ~__SCX_KF_TERMINAL); \ |
| 1178 | 1212 | current->scx.kf_tasks[0] = task0; \ |
| 1179 | 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 | 1215 | current->scx.kf_tasks[0] = NULL; \ |
| 1182 | 1216 | current->scx.kf_tasks[1] = NULL; \ |
| 1183 | 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 | 2206 | WARN_ON_ONCE(*ddsp_taskp); |
| 2173 | 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 | 2211 | *ddsp_taskp = NULL; |
| 2178 | 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 | 2303 | add_nr_running(rq, 1); |
| 2270 | 2304 | |
| 2271 | 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 | 2308 | if (enq_flags & SCX_ENQ_WAKEUP) |
| 2275 | 2309 | touch_core_sched(rq, p); |
| @@ -2283,7 +2317,7 @@ out: · 7 unmodified lines | ||
| 2283 | 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 | 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 | 2338 | BUG(); |
| 2305 | 2339 | case SCX_OPSS_QUEUED: |
| 2306 | 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 | 2343 | if (atomic_long_try_cmpxchg(&p->scx.ops_state, &opss, |
| 2310 | 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 | 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 | 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 | 2388 | if (SCX_HAS_OP(stopping) && task_current(rq, p)) { |
| 2355 | 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 | 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 | 2396 | if (deq_flags & SCX_DEQ_SLEEP) |
| 2363 | 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 | 2411 | struct task_struct *p = rq->curr; |
| 2378 | 2412 | |
| 2379 | 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 | 2415 | else |
| 2382 | 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 | 2421 | struct task_struct *from = rq->curr; |
| 2388 | 2422 | |
| 2389 | 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 | 2425 | else |
| 2392 | 2426 | return false; |
| 2393 | 2427 | } |
| @@ -2945,7 +2979,7 @@ static int balance_one(struct rq *rq, struct task_struct *prev) · 551 unmodified lines | ||
| 2945 | 2979 | * emitted in switch_class(). |
| 2946 | 2980 | */ |
| 2947 | 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 | 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 | 3024 | do { |
| 2991 | 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 | 3028 | prev_on_scx ? prev : NULL); |
| 2995 | 3029 | |
| 2996 | 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 | 3138 | * Core-sched might decide to execute @p before it is |
| 3105 | 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 | 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 | 3147 | /* see dequeue_task_scx() on why we skip when !QUEUED */ |
| 3114 | 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 | 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 | 3227 | .task = next, |
| 3194 | 3228 | }; |
| 3195 | 3229 | |
| 3196 | − SCX_CALL_OP(SCX_KF_CPU_RELEASE, | |
| 3197 | − cpu_release, cpu_of(rq), &args); | |
| 3230 | + SCX_CALL_OP(SCX_KF_CPU_RELEASE, cpu_release, rq, cpu_of(rq), &args); | |
| 3198 | 3231 | } |
| 3199 | 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 | 3241 | /* see dequeue_task_scx() on why we skip when !QUEUED */ |
| 3209 | 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 | 3245 | if (p->scx.flags & SCX_TASK_QUEUED) { |
| 3213 | 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 | 3381 | * verifier. |
| 3349 | 3382 | */ |
| 3350 | 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 | 3385 | (struct task_struct *)a, |
| 3353 | 3386 | (struct task_struct *)b); |
| 3354 | 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 | 3418 | *ddsp_taskp = p; |
| 3386 | 3419 | |
| 3387 | 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 | 3422 | p->scx.selected_cpu = cpu; |
| 3390 | 3423 | *ddsp_taskp = NULL; |
| 3391 | 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 | 3463 | * designation pointless. Cast it away when calling the operation. |
| 3431 | 3464 | */ |
| 3432 | 3465 | if (SCX_HAS_OP(set_cpumask)) |
| 3433 | − SCX_CALL_OP_TASK(SCX_KF_REST, set_cpumask, p, | |
| 3434 | − (struct cpumask *)p->cpus_ptr); | |
| 3466 | + SCX_CALL_OP_TASK(SCX_KF_REST, set_cpumask, NULL, | |
| 3467 | + p, (struct cpumask *)p->cpus_ptr); | |
| 3435 | 3468 | } |
| 3436 | 3469 | |
| 3437 | 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 | 3477 | scx_idle_update_selcpu_topology(&scx_ops); |
| 3445 | 3478 | |
| 3446 | 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 | 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 | 3483 | else |
| 3451 | 3484 | scx_ops_exit(SCX_ECODE_ACT_RESTART | SCX_ECODE_RSN_HOTPLUG, |
| 3452 | 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 | 3583 | curr->scx.slice = 0; |
| 3551 | 3584 | touch_core_sched(rq, curr); |
| 3552 | 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 | 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 | 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 | 3664 | if (unlikely(ret)) { |
| 3632 | 3665 | ret = ops_sanitize_err("init_task", ret); |
| 3633 | 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 | 3702 | static void scx_ops_enable_task(struct task_struct *p) |
| 3670 | 3703 | { |
| 3704 | + struct rq *rq = task_rq(p); | |
| 3671 | 3705 | u32 weight; |
| 3672 | 3706 | |
| 3673 | − lockdep_assert_rq_held(task_rq(p)); | |
| 3707 | + lockdep_assert_rq_held(rq); | |
| 3674 | 3708 | |
| 3675 | 3709 | /* |
| 3676 | 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 | 3718 | p->scx.weight = sched_weight_to_cgroup(weight); |
| 3685 | 3719 | |
| 3686 | 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 | 3722 | scx_set_task_state(p, SCX_TASK_ENABLED); |
| 3689 | 3723 | |
| 3690 | 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 | 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 | 3733 | WARN_ON_ONCE(scx_get_task_state(p) != SCX_TASK_ENABLED); |
| 3698 | 3734 | |
| 3699 | 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 | 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 | 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 | 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 | 3872 | p->scx.weight = sched_weight_to_cgroup(scale_load_down(lw->weight)); |
| 3837 | 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 | 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 | 3887 | * different scheduler class. Keep the BPF scheduler up-to-date. |
| 3852 | 3888 | */ |
| 3853 | 3889 | if (SCX_HAS_OP(set_cpumask)) |
| 3854 | − SCX_CALL_OP_TASK(SCX_KF_REST, set_cpumask, p, | |
| 3855 | − (struct cpumask *)p->cpus_ptr); | |
| 3890 | + SCX_CALL_OP_TASK(SCX_KF_REST, set_cpumask, rq, | |
| 3891 | + p, (struct cpumask *)p->cpus_ptr); | |
| 3856 | 3892 | } |
| 3857 | 3893 | |
| 3858 | 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 | 3949 | struct scx_cgroup_init_args args = |
| 3914 | 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 | 3953 | tg->css.cgroup, &args); |
| 3918 | 3954 | if (ret) |
| 3919 | 3955 | ret = ops_sanitize_err("cgroup_init", ret); |
| @@ -3935,7 +3971,7 @@ void scx_tg_offline(struct task_group *tg) · 15 unmodified lines | ||
| 3935 | 3971 | percpu_down_read(&scx_cgroup_rwsem); |
| 3936 | 3972 | |
| 3937 | 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 | 3975 | tg->scx_flags &= ~(SCX_TG_ONLINE | SCX_TG_INITED); |
| 3940 | 3976 | |
| 3941 | 3977 | percpu_up_read(&scx_cgroup_rwsem); |
| @@ -3968,7 +4004,7 @@ int scx_cgroup_can_attach(struct cgroup_taskset *tset) · 26 unmodified lines | ||
| 3968 | 4004 | continue; |
| 3969 | 4005 | |
| 3970 | 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 | 4008 | p, from, css->cgroup); |
| 3973 | 4009 | if (ret) |
| 3974 | 4010 | goto err; |
| @@ -3982,8 +4018,8 @@ int scx_cgroup_can_attach(struct cgroup_taskset *tset) · 7 unmodified lines | ||
| 3982 | 4018 | err: |
| 3983 | 4019 | cgroup_taskset_for_each(p, css, tset) { |
| 3984 | 4020 | if (SCX_HAS_OP(cgroup_cancel_move) && p->scx.cgrp_moving_from) |
| 3985 | − SCX_CALL_OP(SCX_KF_UNLOCKED, cgroup_cancel_move, p, | |
| 3986 | − p->scx.cgrp_moving_from, css->cgroup); | |
| 4021 | + SCX_CALL_OP(SCX_KF_UNLOCKED, cgroup_cancel_move, NULL, | |
| 4022 | + p, p->scx.cgrp_moving_from, css->cgroup); | |
| 3987 | 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 | 4037 | * cgrp_moving_from set. |
| 4002 | 4038 | */ |
| 4003 | 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, | |
| 4005 | − p->scx.cgrp_moving_from, tg_cgrp(task_group(p))); | |
| 4040 | + SCX_CALL_OP_TASK(SCX_KF_UNLOCKED, cgroup_move, NULL, | |
| 4041 | + p, p->scx.cgrp_moving_from, tg_cgrp(task_group(p))); | |
| 4006 | 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 | 4058 | cgroup_taskset_for_each(p, css, tset) { |
| 4023 | 4059 | if (SCX_HAS_OP(cgroup_cancel_move) && p->scx.cgrp_moving_from) |
| 4024 | − SCX_CALL_OP(SCX_KF_UNLOCKED, cgroup_cancel_move, p, | |
| 4025 | − p->scx.cgrp_moving_from, css->cgroup); | |
| 4060 | + SCX_CALL_OP(SCX_KF_UNLOCKED, cgroup_cancel_move, NULL, | |
| 4061 | + p, p->scx.cgrp_moving_from, css->cgroup); | |
| 4026 | 4062 | p->scx.cgrp_moving_from = NULL; |
| 4027 | 4063 | } |
| 4028 | 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 | 4072 | if (scx_cgroup_enabled && tg->scx_weight != weight) { |
| 4037 | 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 | 4075 | tg_cgrp(tg), weight); |
| 4040 | 4076 | tg->scx_weight = weight; |
| 4041 | 4077 | } |
| @@ -4224,7 +4260,7 @@ static void scx_cgroup_exit(void) · 182 unmodified lines | ||
| 4224 | 4260 | continue; |
| 4225 | 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 | 4265 | rcu_read_lock(); |
| 4230 | 4266 | css_put(css); |
| @@ -4261,7 +4297,7 @@ static int scx_cgroup_init(void) · 30 unmodified lines | ||
| 4261 | 4297 | continue; |
| 4262 | 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 | 4301 | css->cgroup, &args); |
| 4266 | 4302 | if (ret) { |
| 4267 | 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 | 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 | 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 | 5002 | if (SCX_HAS_OP(dump_task)) { |
| 4967 | 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 | 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 | 5049 | if (SCX_HAS_OP(dump)) { |
| 5014 | 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 | 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 | 5105 | used = seq_buf_used(&ns); |
| 5070 | 5106 | if (SCX_HAS_OP(dump_cpu)) { |
| 5071 | 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 | 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 | 5364 | scx_idle_enable(ops); |
| 5329 | 5365 | |
| 5330 | 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 | 5368 | if (ret) { |
| 5333 | 5369 | ret = ops_sanitize_err("init", ret); |
| 5334 | 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 | 6827 | BUILD_BUG_ON(__alignof__(struct bpf_iter_scx_dsq_kern) != |
| 6792 | 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 | 6836 | if (flags & ~__SCX_DSQ_ITER_USER_FLAGS) |
| 6795 | 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 | 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 | 7143 | rq->scx.cpuperf_target = perf; |
| 7144 | + cpufreq_update_util(rq, 0); | |
| 7083 | 7145 | |
| 7084 | − rcu_read_lock_sched_notrace(); | |
| 7085 | − cpufreq_update_util(cpu_rq(cpu), 0); | |
| 7086 | − rcu_read_unlock_sched_notrace(); | |
| 7146 | + if (!locked_rq) | |
| 7147 | + rq_unlock_irqrestore(rq, &rf); | |
| 7087 | 7148 | } |
| 7088 | 7149 | } |
| 7089 | 7150 | |
| @@ -7314,12 +7375,6 @@ BTF_ID_FLAGS(func, scx_bpf_nr_cpu_ids) · 224 unmodified lines | ||
| 7314 | 7375 | BTF_ID_FLAGS(func, scx_bpf_get_possible_cpumask, KF_ACQUIRE) |
| 7315 | 7376 | BTF_ID_FLAGS(func, scx_bpf_get_online_cpumask, KF_ACQUIRE) |
| 7316 | 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 | 7378 | BTF_ID_FLAGS(func, scx_bpf_task_running, KF_RCU) |
| 7324 | 7379 | BTF_ID_FLAGS(func, scx_bpf_task_cpu, KF_RCU) |
| 7325 | 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 | 674 | * managed by put_prev_task_idle()/set_next_task_idle(). |
| 675 | 675 | */ |
| 676 | 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 | 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 | 454 | struct fprobe_hlist_node *node; |
| 455 | 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 | 459 | if (!within_module(node->addr, mod)) |
| 459 | 460 | continue; |
| 460 | 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 | 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. */ | |
| 1891 | − if (head_page == cpu_buffer->reader_page && | |
| 1892 | − head_page == cpu_buffer->commit_page) | |
| 1890 | + /* If the commit_buffer is the reader page, update the commit page */ | |
| 1891 | + if (meta->commit_buffer == (unsigned long)cpu_buffer->reader_page->page) { | |
| 1892 | + cpu_buffer->commit_page = cpu_buffer->reader_page; | |
| 1893 | + /* Nothing more to do, the only page is the reader page */ | |
| 1893 | 1894 | goto done; |
| 1895 | + } | |
| 1894 | 1896 | |
| 1895 | 1897 | /* Iterate until finding the commit page */ |
| 1896 | 1898 | for (i = 0; i < meta->nr_subbufs + 1; i++, rb_inc_page(&head_page)) { |
| @@ -16,7 +16,7 @@ · 15 unmodified lines | ||
| 16 | 16 | #include "trace_output.h" /* for trace_event_sem */ |
| 17 | 17 | #include "trace_dynevent.h" |
| 18 | 18 | |
| 19 | −static DEFINE_MUTEX(dyn_event_ops_mutex); | |
| 19 | +DEFINE_MUTEX(dyn_event_ops_mutex); | |
| 20 | 20 | static LIST_HEAD(dyn_event_ops_list); |
| 21 | 21 | |
| 22 | 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 | 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 | 133 | static int create_dyn_event(const char *raw_command) |
| 120 | 134 | { |
| 121 | 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 | 100 | void dyn_event_seq_stop(struct seq_file *m, void *v); |
| 101 | 101 | int dyn_events_release_all(struct dyn_event_operations *type); |
| 102 | 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 | 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 | 969 | goto error; |
| 970 | 970 | } |
| 971 | 971 | } |
| 972 | + trace_probe_log_clear(); | |
| 972 | 973 | return ret; |
| 974 | + | |
| 973 | 975 | parse_error: |
| 974 | 976 | ret = -EINVAL; |
| 975 | 977 | error: |
| 978 | + trace_probe_log_clear(); | |
| 976 | 979 | trace_event_probe_cleanup(ep); |
| 977 | 980 | return ret; |
| 978 | 981 | } |
| @@ -1560,7 +1560,7 @@ stacktrace_trigger(struct event_trigger_data *data, · 1559 unmodified lines | ||
| 1560 | 1560 | struct trace_event_file *file = data->private_data; |
| 1561 | 1561 | |
| 1562 | 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 | 1564 | else |
| 1565 | 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 | 634 | static __always_inline void trace_stack(struct trace_array *tr) |
| 635 | 635 | { |
| 636 | − unsigned int trace_ctx; | |
| 637 | − | |
| 638 | − trace_ctx = tracing_gen_ctx(); | |
| 639 | − | |
| 640 | − __trace_stack(tr, trace_ctx, FTRACE_STACK_SKIP); | |
| 636 | + __trace_stack(tr, tracing_gen_ctx_dec(), FTRACE_STACK_SKIP); | |
| 641 | 637 | } |
| 642 | 638 | |
| 643 | 639 | static void |
| @@ -1089,7 +1089,7 @@ static int create_or_delete_trace_kprobe(const char *raw_command) · 1088 unmodified lines | ||
| 1089 | 1089 | if (raw_command[0] == '-') |
| 1090 | 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 | 1093 | return ret == -ECANCELED ? -EINVAL : ret; |
| 1094 | 1094 | } |
| 1095 | 1095 | |
| @@ -154,9 +154,12 @@ fail: · 153 unmodified lines | ||
| 154 | 154 | } |
| 155 | 155 | |
| 156 | 156 | static struct trace_probe_log trace_probe_log; |
| 157 | +extern struct mutex dyn_event_ops_mutex; | |
| 157 | 158 | |
| 158 | 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 | 163 | trace_probe_log.subsystem = subsystem; |
| 161 | 164 | trace_probe_log.argc = argc; |
| 162 | 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 | 169 | void trace_probe_log_clear(void) |
| 167 | 170 | { |
| 171 | + lockdep_assert_held(&dyn_event_ops_mutex); | |
| 172 | + | |
| 168 | 173 | memset(&trace_probe_log, 0, sizeof(trace_probe_log)); |
| 169 | 174 | } |
| 170 | 175 | |
| 171 | 176 | void trace_probe_log_set_index(int index) |
| 172 | 177 | { |
| 178 | + lockdep_assert_held(&dyn_event_ops_mutex); | |
| 179 | + | |
| 173 | 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 | 185 | char *command, *p; |
| 179 | 186 | int i, len = 0, pos = 0; |
| 180 | 187 | |
| 188 | + lockdep_assert_held(&dyn_event_ops_mutex); | |
| 189 | + | |
| 181 | 190 | if (!trace_probe_log.argv) |
| 182 | 191 | return; |
| 183 | 192 | |
| @@ -741,7 +741,7 @@ static int create_or_delete_trace_uprobe(const char *raw_command) · 740 unmodified lines | ||
| 741 | 741 | if (raw_command[0] == '-') |
| 742 | 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 | 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 | 3010 | struct hugepage_subpool *spool = subpool_vma(vma); |
| 3011 | 3011 | struct hstate *h = hstate_vma(vma); |
| 3012 | 3012 | struct folio *folio; |
| 3013 | − long retval, gbl_chg; | |
| 3013 | + long retval, gbl_chg, gbl_reserve; | |
| 3014 | 3014 | map_chg_state map_chg; |
| 3015 | 3015 | int ret, idx; |
| 3016 | 3016 | struct hugetlb_cgroup *h_cg = NULL; |
| @@ -3163,8 +3163,16 @@ out_uncharge_cgroup_reservation: · 146 unmodified lines | ||
| 3163 | 3163 | hugetlb_cgroup_uncharge_cgroup_rsvd(idx, pages_per_huge_page(h), |
| 3164 | 3164 | h_cg); |
| 3165 | 3165 | out_subpool_put: |
| 3166 | − if (map_chg) | |
| 3167 | − hugepage_subpool_put_pages(spool, 1); | |
| 3166 | + /* | |
| 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 | 3176 | out_end_reservation: |
| 3169 | 3177 | if (map_chg != MAP_CHG_ENFORCED) |
| 3170 | 3178 | vma_end_reservation(h, vma, addr); |
| @@ -7239,7 +7247,7 @@ bool hugetlb_reserve_pages(struct inode *inode, · 4068 unmodified lines | ||
| 7239 | 7247 | struct vm_area_struct *vma, |
| 7240 | 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 | 7251 | struct hstate *h = hstate_inode(inode); |
| 7244 | 7252 | struct hugepage_subpool *spool = subpool_inode(inode); |
| 7245 | 7253 | struct resv_map *resv_map; |
| @@ -7374,8 +7382,16 @@ bool hugetlb_reserve_pages(struct inode *inode, · 128 unmodified lines | ||
| 7374 | 7382 | return true; |
| 7375 | 7383 | |
| 7376 | 7384 | out_put_pages: |
| 7377 | − /* put back original number of pages, chg */ | |
| 7378 | − (void)hugepage_subpool_put_pages(spool, chg); | |
| 7385 | + spool_resv = chg - gbl_reserve; | |
| 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 | 7395 | out_uncharge_cgroup: |
| 7380 | 7396 | hugetlb_cgroup_uncharge_cgroup_rsvd(hstate_index(h), |
| 7381 | 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 | 1591 | #ifdef CONFIG_UNACCEPTED_MEMORY |
| 1592 | 1592 | void accept_page(struct page *page); |
| 1593 | −void unaccepted_cleanup_work(struct work_struct *work); | |
| 1594 | 1593 | #else /* CONFIG_UNACCEPTED_MEMORY */ |
| 1595 | 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 | 3752 | /* Stabilize the mapcount vs. refcount and recheck. */ |
| 3753 | 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 | 3756 | if (folio_test_large_maybe_mapped_shared(folio)) |
| 3757 | 3757 | goto unlock; |
| @@ -1441,7 +1441,6 @@ static void __meminit zone_init_free_lists(struct zone *zone) · 1440 unmodified lines | ||
| 1441 | 1441 | |
| 1442 | 1442 | #ifdef CONFIG_UNACCEPTED_MEMORY |
| 1443 | 1443 | INIT_LIST_HEAD(&zone->unaccepted_pages); |
| 1444 | − INIT_WORK(&zone->unaccepted_cleanup, unaccepted_cleanup_work); | |
| 1445 | 1444 | #endif |
| 1446 | 1445 | } |
| 1447 | 1446 | |
| @@ -290,7 +290,8 @@ EXPORT_SYMBOL(nr_online_nodes); · 289 unmodified lines | ||
| 290 | 290 | #endif |
| 291 | 291 | |
| 292 | 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 | 295 | static bool __free_unaccepted(struct page *page); |
| 295 | 296 | |
| 296 | 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 | 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 | 1158 | if (tag) |
| 1163 | 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 | 1164 | static inline void pgalloc_tag_add(struct page *page, struct task_struct *task, |
| 1169 | 1165 | unsigned int nr) {} |
| 1170 | 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 | 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 | 3618 | * Detect whether the number of free pages is below high |
| @@ -3643,7 +3639,7 @@ check_alloc_wmark: · 20 unmodified lines | ||
| 3643 | 3639 | gfp_mask)) { |
| 3644 | 3640 | int ret; |
| 3645 | 3641 | |
| 3646 | − if (cond_accept_memory(zone, order)) | |
| 3642 | + if (cond_accept_memory(zone, order, alloc_flags)) | |
| 3647 | 3643 | goto try_this_zone; |
| 3648 | 3644 | |
| 3649 | 3645 | /* |
| @@ -3696,7 +3692,7 @@ try_this_zone: · 46 unmodified lines | ||
| 3696 | 3692 | |
| 3697 | 3693 | return page; |
| 3698 | 3694 | } else { |
| 3699 | − if (cond_accept_memory(zone, order)) | |
| 3695 | + if (cond_accept_memory(zone, order, alloc_flags)) | |
| 3700 | 3696 | goto try_this_zone; |
| 3701 | 3697 | |
| 3702 | 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 | 4845 | goto failed; |
| 4850 | 4846 | } |
| 4851 | 4847 | |
| 4852 | − cond_accept_memory(zone, 0); | |
| 4848 | + cond_accept_memory(zone, 0, alloc_flags); | |
| 4853 | 4849 | retry_this_zone: |
| 4854 | 4850 | mark = wmark_pages(zone, alloc_flags & ALLOC_WMARK_MASK) + nr_pages; |
| 4855 | 4851 | if (zone_watermark_fast(zone, 0, mark, |
| @@ -4858,7 +4854,7 @@ retry_this_zone: · 2 unmodified lines | ||
| 4858 | 4854 | break; |
| 4859 | 4855 | } |
| 4860 | 4856 | |
| 4861 | − if (cond_accept_memory(zone, 0)) | |
| 4857 | + if (cond_accept_memory(zone, 0, alloc_flags)) | |
| 4862 | 4858 | goto retry_this_zone; |
| 4863 | 4859 | |
| 4864 | 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 | 5062 | /* get PageHead before we drop reference */ |
| 5067 | 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 | 5067 | if (put_page_testzero(page)) |
| 5070 | 5068 | __free_frozen_pages(page, order, fpi_flags); |
| 5071 | 5069 | else if (!head) { |
| 5072 | − pgalloc_tag_sub_pages(page, (1 << order) - 1); | |
| 5070 | + pgalloc_tag_sub_pages(tag, (1 << order) - 1); | |
| 5073 | 5071 | while (order-- > 0) |
| 5074 | 5072 | __free_frozen_pages(page + (1 << order), order, |
| 5075 | 5073 | fpi_flags); |
| @@ -7174,16 +7172,8 @@ bool has_managed_dma(void) · 2098 unmodified lines | ||
| 7174 | 7172 | |
| 7175 | 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 | 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 | 7177 | static int __init accept_memory_parse(char *p) |
| 7188 | 7178 | { |
| 7189 | 7179 | if (!strcmp(p, "lazy")) { |
| @@ -7208,11 +7198,7 @@ static bool page_contains_unaccepted(struct page *page, unsigned int order) · 18 unmodified lines | ||
| 7208 | 7198 | static void __accept_page(struct zone *zone, unsigned long *flags, |
| 7209 | 7199 | struct page *page) |
| 7210 | 7200 | { |
| 7211 | − bool last; | |
| 7212 | − | |
| 7213 | 7201 | list_del(&page->lru); |
| 7214 | − last = list_empty(&zone->unaccepted_pages); | |
| 7215 | − | |
| 7216 | 7202 | account_freepages(zone, -MAX_ORDER_NR_PAGES, MIGRATE_MOVABLE); |
| 7217 | 7203 | __mod_zone_page_state(zone, NR_UNACCEPTED, -MAX_ORDER_NR_PAGES); |
| 7218 | 7204 | __ClearPageUnaccepted(page); |
| @@ -7221,28 +7207,6 @@ static void __accept_page(struct zone *zone, unsigned long *flags, · 2 unmodified lines | ||
| 7221 | 7207 | accept_memory(page_to_phys(page), PAGE_SIZE << MAX_PAGE_ORDER); |
| 7222 | 7208 | |
| 7223 | 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 | 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 | 7243 | return true; |
| 7280 | 7244 | } |
| 7281 | 7245 | |
| 7282 | −static inline bool has_unaccepted_memory(void) | |
| 7283 | −{ | |
| 7284 | − return static_branch_unlikely(&zones_with_unaccepted_pages); | |
| 7285 | −} | |
| 7286 | − | |
| 7287 | −static bool cond_accept_memory(struct zone *zone, unsigned int order) | |
| 7246 | +static bool cond_accept_memory(struct zone *zone, unsigned int order, | |
| 7247 | + int alloc_flags) | |
| 7288 | 7248 | { |
| 7289 | 7249 | long to_accept, wmark; |
| 7290 | 7250 | bool ret = false; |
| 7291 | 7251 | |
| 7292 | − if (!has_unaccepted_memory()) | |
| 7252 | + if (list_empty(&zone->unaccepted_pages)) | |
| 7293 | 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 | 7257 | return false; |
| 7297 | 7258 | |
| 7298 | 7259 | wmark = promo_wmark_pages(zone); |
| @@ -7325,22 +7286,17 @@ static bool __free_unaccepted(struct page *page) · 26 unmodified lines | ||
| 7325 | 7286 | { |
| 7326 | 7287 | struct zone *zone = page_zone(page); |
| 7327 | 7288 | unsigned long flags; |
| 7328 | − bool first = false; | |
| 7329 | 7289 | |
| 7330 | 7290 | if (!lazy_accept) |
| 7331 | 7291 | return false; |
| 7332 | 7292 | |
| 7333 | 7293 | spin_lock_irqsave(&zone->lock, flags); |
| 7334 | − first = list_empty(&zone->unaccepted_pages); | |
| 7335 | 7294 | list_add_tail(&page->lru, &zone->unaccepted_pages); |
| 7336 | 7295 | account_freepages(zone, MAX_ORDER_NR_PAGES, MIGRATE_MOVABLE); |
| 7337 | 7296 | __mod_zone_page_state(zone, NR_UNACCEPTED, MAX_ORDER_NR_PAGES); |
| 7338 | 7297 | __SetPageUnaccepted(page); |
| 7339 | 7298 | spin_unlock_irqrestore(&zone->lock, flags); |
| 7340 | 7299 | |
| 7341 | − if (first) | |
| 7342 | − static_branch_inc(&zones_with_unaccepted_pages); | |
| 7343 | − | |
| 7344 | 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 | 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 | 7313 | return false; |
| 7357 | 7314 | } |
| @@ -7422,11 +7379,6 @@ struct page *try_alloc_pages_noprof(int nid, unsigned int order) · 64 unmodified lines | ||
| 7422 | 7379 | if (!pcp_allowed_order(order)) |
| 7423 | 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 | 7382 | /* Bailout, since _deferred_grow_zone() needs to take a lock */ |
| 7431 | 7383 | if (deferred_pages_enabled()) |
| 7432 | 7384 | return NULL; |
| @@ -3331,6 +3331,15 @@ SYSCALL_DEFINE2(swapon, const char __user *, specialfile, int, swap_flags) · 3330 unmodified lines | ||
| 3331 | 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 | 3344 | * Read the swap header. |
| 3336 | 3345 | */ |
| @@ -1064,8 +1064,13 @@ static int move_present_pte(struct mm_struct *mm, · 1063 unmodified lines | ||
| 1064 | 1064 | src_folio->index = linear_page_index(dst_vma, dst_addr); |
| 1065 | 1065 | |
| 1066 | 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 */ | |
| 1068 | − orig_dst_pte = pte_mkwrite(pte_mkdirty(orig_dst_pte), dst_vma); | |
| 1067 | + /* Set soft dirty bit so userspace can notice the pte was moved */ | |
| 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 | 1075 | set_pte_at(mm, dst_addr, dst_pte, orig_dst_pte); |
| 1071 | 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 | 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 | 1111 | set_pte_at(mm, dst_addr, dst_pte, orig_src_pte); |
| 1104 | 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 | 1243 | class = zspage_class(pool, zspage); |
| 1244 | 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 | 1250 | /* this object is contained entirely within a page */ |
| 1248 | 1251 | void *dst = kmap_local_zpdesc(zpdesc); |
| 1249 | 1252 | |
| 1250 | − if (!ZsHugePage(zspage)) | |
| 1251 | − off += ZS_HANDLE_SIZE; | |
| 1252 | 1253 | memcpy(dst + off, handle_mem, mem_len); |
| 1253 | 1254 | kunmap_local(dst); |
| 1254 | 1255 | } else { |
| 1255 | 1256 | /* this object spans two pages */ |
| 1256 | 1257 | size_t sizes[2]; |
| 1257 | 1258 | |
| 1258 | − off += ZS_HANDLE_SIZE; | |
| 1259 | 1259 | sizes[0] = PAGE_SIZE - off; |
| 1260 | 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 | 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 | − list_for_each_entry_rcu(hard_iface, &batadv_hardif_list, list) { | |
| 515 | − if (hard_iface->if_status != BATADV_IF_ACTIVE && | |
| 516 | − hard_iface->if_status != BATADV_IF_TO_BE_ACTIVATED) | |
| 514 | + if (!mesh_iface) | |
| 515 | + return; | |
| 516 | + | |
| 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 | 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 | 525 | continue; |
| 521 | 526 | |
| 522 | − if (!batadv_compare_eth(hard_iface->net_dev->dev_addr, | |
| 523 | − net_dev->dev_addr)) | |
| 527 | + if (!batadv_compare_eth(tmp_hard_iface->net_dev->dev_addr, | |
| 528 | + hard_iface->net_dev->dev_addr)) | |
| 524 | 529 | continue; |
| 525 | 530 | |
| 526 | 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 | 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 | 767 | hard_iface->net_dev->name, hardif_mtu, |
| 764 | 768 | required_mtu); |
| 765 | 769 | |
| 770 | + batadv_check_known_mac_addr(hard_iface); | |
| 771 | + | |
| 766 | 772 | if (batadv_hardif_is_iface_up(hard_iface)) |
| 767 | 773 | batadv_hardif_activate_interface(hard_iface); |
| 768 | 774 | else |
| @@ -901,7 +907,6 @@ batadv_hardif_add_interface(struct net_device *net_dev) · 132 unmodified lines | ||
| 901 | 907 | |
| 902 | 908 | batadv_v_hardif_init(hard_iface); |
| 903 | 909 | |
| 904 | − batadv_check_known_mac_addr(hard_iface->net_dev); | |
| 905 | 910 | kref_get(&hard_iface->refcount); |
| 906 | 911 | list_add_tail_rcu(&hard_iface->list, &batadv_hardif_list); |
| 907 | 912 | batadv_hardif_generation++; |
| @@ -988,7 +993,7 @@ static int batadv_hard_if_event(struct notifier_block *this, · 80 unmodified lines | ||
| 988 | 993 | if (hard_iface->if_status == BATADV_IF_NOT_IN_USE) |
| 989 | 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 | 998 | bat_priv = netdev_priv(hard_iface->mesh_iface); |
| 994 | 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 | 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 | 739 | handle); |
| 740 | 740 | conn->enc_key_size = 0; |
| 741 | 741 | } else { |
| 742 | + u8 *key_enc_size = hci_conn_key_enc_size(conn); | |
| 743 | + | |
| 742 | 744 | conn->enc_key_size = rp->key_size; |
| 743 | 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 | 753 | /* As slave role, the conn->state has been set to |
| 747 | 754 | * BT_CONNECTED and l2cap conn req might not be received |
| 748 | 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 | 762 | clear_bit(HCI_CONN_ENCRYPT, &conn->flags); |
| 756 | 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 | 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 | 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 | 3107 | static void hci_conn_complete_evt(struct hci_dev *hdev, void *data, |
| 3069 | 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 | 3196 | if (ev->encr_mode == 1 && !test_bit(HCI_CONN_ENCRYPT, &conn->flags) && |
| 3158 | 3197 | ev->link_type == ACL_LINK) { |
| 3159 | 3198 | struct link_key *key; |
| 3160 | − struct hci_cp_read_enc_key_size cp; | |
| 3161 | 3199 | |
| 3162 | 3200 | key = hci_find_link_key(hdev, &ev->bdaddr); |
| 3163 | 3201 | if (key) { |
| 3164 | 3202 | set_bit(HCI_CONN_ENCRYPT, &conn->flags); |
| 3165 | − | |
| 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 | − | |
| 3203 | + hci_read_enc_key_size(hdev, conn); | |
| 3177 | 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 | 3640 | /* Try reading the encryption key size for encrypted ACL links */ |
| 3614 | 3641 | if (!ev->status && ev->encrypt && conn->type == ACL_LINK) { |
| 3615 | − struct hci_cp_read_enc_key_size cp; | |
| 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; | |
| 3642 | + if (hci_read_enc_key_size(hdev, conn)) | |
| 3631 | 3643 | goto notify; |
| 3632 | − } | |
| 3633 | 3644 | |
| 3634 | 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 | 7506 | struct mgmt_cp_add_device *cp = cmd->param; |
| 7507 | 7507 | |
| 7508 | 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 | 7514 | device_added(cmd->sk, hdev, &cp->addr.bdaddr, cp->addr.type, |
| 7510 | 7515 | cp->action); |
| 7511 | 7516 | device_flags_changed(NULL, hdev, &cp->addr.bdaddr, |
| 7512 | 7517 | cp->addr.type, hdev->conn_flags, |
| 7513 | − PTR_UINT(cmd->user_data)); | |
| 7518 | + params ? params->flags : 0); | |
| 7514 | 7519 | } |
| 7515 | 7520 | |
| 7516 | 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 | 7618 | goto unlock; |
| 7614 | 7619 | } |
| 7615 | 7620 | |
| 7616 | − cmd->user_data = UINT_PTR(current_flags); | |
| 7617 | − | |
| 7618 | 7621 | err = hci_cmd_sync_queue(hdev, add_device_sync, cmd, |
| 7619 | 7622 | add_device_complete); |
| 7620 | 7623 | if (err < 0) { |
| @@ -10441,6 +10441,7 @@ static void netdev_sync_lower_features(struct net_device *upper, · 10440 unmodified lines | ||
| 10441 | 10441 | if (!(features & feature) && (lower->features & feature)) { |
| 10442 | 10442 | netdev_dbg(upper, "Disabling feature %pNF on lower dev %s.\n", |
| 10443 | 10443 | &feature, lower->name); |
| 10444 | + netdev_lock_ops(lower); | |
| 10444 | 10445 | lower->wanted_features &= ~feature; |
| 10445 | 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 | 10450 | &feature, lower->name); |
| 10450 | 10451 | else |
| 10451 | 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 | 201 | refcount_set(&binding->ref, 1); |
| 202 | 202 | |
| 203 | + mutex_init(&binding->lock); | |
| 204 | + | |
| 203 | 205 | binding->dmabuf = dmabuf; |
| 204 | 206 | |
| 205 | 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 | 381 | xa_for_each(&binding->bound_rxqs, xa_idx, bound_rxq) { |
| 380 | 382 | if (bound_rxq == rxq) { |
| 381 | 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 | 389 | break; |
| 383 | 390 | } |
| 384 | 391 | } |
| @@ -20,6 +20,8 @@ struct net_devmem_dmabuf_binding { · 19 unmodified lines | ||
| 20 | 20 | struct sg_table *sgt; |
| 21 | 21 | struct net_device *dev; |
| 22 | 22 | struct gen_pool *chunk_pool; |
| 23 | + /* Protect dev */ | |
| 24 | + struct mutex lock; | |
| 23 | 25 | |
| 24 | 26 | /* The user holds a ref (via the netlink API) for as long as they want |
| 25 | 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 | 980 | struct net_devmem_dmabuf_binding *binding; |
| 981 | 981 | struct net_devmem_dmabuf_binding *temp; |
| 982 | + netdevice_tracker dev_tracker; | |
| 982 | 983 | struct net_device *dev; |
| 983 | 984 | |
| 984 | 985 | mutex_lock(&priv->lock); |
| 985 | 986 | list_for_each_entry_safe(binding, temp, &priv->bindings, list) { |
| 987 | + mutex_lock(&binding->lock); | |
| 986 | 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 | 997 | netdev_lock(dev); |
| 988 | 998 | net_devmem_unbind_dmabuf(binding); |
| 989 | 999 | netdev_unlock(dev); |
| 1000 | + netdev_put(dev, &dev_tracker); | |
| 990 | 1001 | } |
| 991 | 1002 | mutex_unlock(&priv->lock); |
| 992 | 1003 | } |
| @@ -1354,10 +1354,12 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) · 1353 unmodified lines | ||
| 1354 | 1354 | hw->wiphy->software_iftypes |= BIT(NL80211_IFTYPE_MONITOR); |
| 1355 | 1355 | |
| 1356 | 1356 | |
| 1357 | − local->int_scan_req = kzalloc(sizeof(*local->int_scan_req) + | |
| 1358 | − sizeof(void *) * channels, GFP_KERNEL); | |
| 1357 | + local->int_scan_req = kzalloc(struct_size(local->int_scan_req, | |
| 1358 | + channels, channels), | |
| 1359 | + GFP_KERNEL); | |
| 1359 | 1360 | if (!local->int_scan_req) |
| 1360 | 1361 | return -ENOMEM; |
| 1362 | + local->int_scan_req->n_channels = channels; | |
| 1361 | 1363 | |
| 1362 | 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 | 117 | struct net_device *dev; |
| 118 | 118 | struct ifaddrmsg *hdr; |
| 119 | 119 | struct mctp_dev *mdev; |
| 120 | − int ifindex, rc; | |
| 121 | − | |
| 122 | − hdr = nlmsg_data(cb->nlh); | |
| 123 | − // filter by ifindex if requested | |
| 124 | − ifindex = hdr->ifa_index; | |
| 120 | + int ifindex = 0, rc; | |
| 121 | + | |
| 122 | + /* Filter by ifindex if a header is provided */ | |
| 123 | + if (cb->nlh->nlmsg_len >= nlmsg_msg_size(sizeof(*hdr))) { | |
| 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 | 133 | rcu_read_lock(); |
| 127 | 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 | 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 | 318 | return; |
| 319 | + } | |
| 318 | 320 | |
| 319 | 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 | 145 | qlen = sch->q.qlen; |
| 146 | 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 | 149 | dropped += qdisc_pkt_len(skb); |
| 150 | 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 | 1136 | sch_tree_lock(sch); |
| 1137 | 1137 | } |
| 1138 | 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 | 1141 | if (!skb) |
| 1142 | 1142 | break; |
| @@ -441,7 +441,7 @@ static int fq_codel_change(struct Qdisc *sch, struct nlattr *opt, · 440 unmodified lines | ||
| 441 | 441 | |
| 442 | 442 | while (sch->q.qlen > sch->limit || |
| 443 | 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 | 446 | q->cstats.drop_len += qdisc_pkt_len(skb); |
| 447 | 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 | 367 | /* Drop excess packets if new limit is lower */ |
| 368 | 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 | 371 | len_dropped += qdisc_pkt_len(skb); |
| 372 | 372 | num_dropped += 1; |
| @@ -564,7 +564,7 @@ static int hhf_change(struct Qdisc *sch, struct nlattr *opt, · 563 unmodified lines | ||
| 564 | 564 | qlen = sch->q.qlen; |
| 565 | 565 | prev_backlog = sch->qstats.backlog; |
| 566 | 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 | 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 | 195 | /* Drop excess packets if new limit is lower */ |
| 196 | 196 | qlen = sch->q.qlen; |
| 197 | 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 | 200 | dropped += qdisc_pkt_len(skb); |
| 201 | 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 | 396 | return 0; |
| 397 | 397 | |
| 398 | 398 | shinfo = skb_shinfo(strp->anchor); |
| 399 | − shinfo->frag_list = NULL; | |
| 400 | 399 | |
| 401 | 400 | /* If we don't know the length go max plus page for cipher overhead */ |
| 402 | 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 | 411 | page, 0, 0); |
| 413 | 412 | } |
| 414 | 413 | |
| 414 | + shinfo->frag_list = NULL; | |
| 415 | + | |
| 415 | 416 | strp->copy_mode = 1; |
| 416 | 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 | 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 | 117 | simple_tsk = kthread_run(simple_thread, NULL, "sample-instance"); |
| 118 | 118 | if (IS_ERR(simple_tsk)) { |
| @@ -37,6 +37,18 @@ KBUILD_CFLAGS += -Wno-gnu · 36 unmodified lines | ||
| 37 | 37 | # https://gcc.gnu.org/bugzilla/show_bug.cgi?id=111219 |
| 38 | 38 | KBUILD_CFLAGS += $(call cc-disable-warning, format-overflow-non-kprintf) |
| 39 | 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 | 52 | else |
| 41 | 53 | |
| 42 | 54 | # gcc inanely warns about local variables called 'main' |
| @@ -94,10 +94,10 @@ $(vmlinux-final): $(RESOLVE_BTFIDS) · 93 unmodified lines | ||
| 94 | 94 | endif |
| 95 | 95 | |
| 96 | 96 | ifdef CONFIG_BUILDTIME_TABLE_SORT |
| 97 | −vmlinux: scripts/sorttable | |
| 97 | +$(vmlinux-final): scripts/sorttable | |
| 98 | 98 | endif |
| 99 | 99 | |
| 100 | −# module.builtin.ranges | |
| 100 | +# modules.builtin.ranges | |
| 101 | 101 | # --------------------------------------------------------------------------- |
| 102 | 102 | ifdef CONFIG_BUILTIN_MODULE_RANGES |
| 103 | 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 | 74 | targets += vmlinux.o |
| 75 | 75 | |
| 76 | −# module.builtin.modinfo | |
| 76 | +# modules.builtin.modinfo | |
| 77 | 77 | # --------------------------------------------------------------------------- |
| 78 | 78 | |
| 79 | 79 | OBJCOPYFLAGS_modules.builtin.modinfo := -j .modinfo -O binary |
| @@ -82,7 +82,7 @@ targets += modules.builtin.modinfo · 2 unmodified lines | ||
| 82 | 82 | modules.builtin.modinfo: vmlinux.o FORCE |
| 83 | 83 | $(call if_changed,objcopy) |
| 84 | 84 | |
| 85 | −# module.builtin | |
| 85 | +# modules.builtin | |
| 86 | 86 | # --------------------------------------------------------------------------- |
| 87 | 87 | |
| 88 | 88 | # The second line aids cases where multiple modules share the same object. |
| @@ -16,6 +16,7 @@ Source1: config · 15 unmodified lines | ||
| 16 | 16 | Source2: diff.patch |
| 17 | 17 | Provides: kernel-%{KERNELRELEASE} |
| 18 | 18 | BuildRequires: bc binutils bison dwarves |
| 19 | +BuildRequires: (elfutils-devel or libdw-devel) | |
| 19 | 20 | BuildRequires: (elfutils-libelf-devel or libelf-devel) flex |
| 20 | 21 | BuildRequires: gcc make openssl openssl-devel perl python3 rsync |
| 21 | 22 | |
| @@ -210,7 +210,7 @@ Rules-Requires-Root: no · 209 unmodified lines | ||
| 210 | 210 | Build-Depends: debhelper-compat (= 12) |
| 211 | 211 | Build-Depends-Arch: bc, bison, flex, |
| 212 | 212 | gcc-${host_gnu} <!pkg.${sourcename}.nokernelheaders>, |
| 213 | − kmod, libelf-dev:native, | |
| 213 | + kmod, libdw-dev:native, libelf-dev:native, | |
| 214 | 214 | libssl-dev:native, libssl-dev <!pkg.${sourcename}.nokernelheaders>, |
| 215 | 215 | python3:native, rsync |
| 216 | 216 | Homepage: https://www.kernel.org/ |
| @@ -175,7 +175,7 @@ static void test_get_hierarchy(struct kunit *const test) · 174 unmodified lines | ||
| 175 | 175 | KUNIT_EXPECT_EQ(test, 10, get_hierarchy(&dom2, 0)->id); |
| 176 | 176 | KUNIT_EXPECT_EQ(test, 20, get_hierarchy(&dom2, 1)->id); |
| 177 | 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 | 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 | 437 | return; |
| 438 | 438 | |
| 439 | 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 | 441 | /* Ignores denials for the same execution. */ |
| 442 | 442 | if (!youngest_denied->log_same_exec) |
| 443 | 443 | return; |
| @@ -7,6 +7,7 @@ · 6 unmodified lines | ||
| 7 | 7 | |
| 8 | 8 | #include <kunit/test.h> |
| 9 | 9 | #include <linux/atomic.h> |
| 10 | +#include <linux/bitops.h> | |
| 10 | 11 | #include <linux/random.h> |
| 11 | 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 | 26 | * Ensures sure 64-bit values are always used by user space (or may |
| 26 | 27 | * fail with -EOVERFLOW), and makes this testable. |
| 27 | 28 | */ |
| 28 | − init = 1ULL << 32; | |
| 29 | + init = BIT_ULL(32); | |
| 29 | 30 | |
| 30 | 31 | /* |
| 31 | 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 | 106 | * to get a new ID (e.g. a full landlock_restrict_self() call), and the |
| 106 | 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 | 110 | step = number_of_ids + random_4bits; |
| 110 | 111 | |
| 111 | 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 | 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 | 161 | static void test_range1_rand16(struct kunit *const test) |
| 148 | 162 | { |
| 149 | 163 | atomic64_t counter; |
| @@ -196,6 +210,19 @@ static void test_range2_rand2(struct kunit *const test) · 46 unmodified lines | ||
| 196 | 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 | 226 | static void test_range2_rand16(struct kunit *const test) |
| 200 | 227 | { |
| 201 | 228 | atomic64_t counter; |
| @@ -232,10 +259,12 @@ static struct kunit_case __refdata test_cases[] = { · 30 unmodified lines | ||
| 232 | 259 | KUNIT_CASE(test_init_once), |
| 233 | 260 | KUNIT_CASE(test_range1_rand0), |
| 234 | 261 | KUNIT_CASE(test_range1_rand1), |
| 262 | + KUNIT_CASE(test_range1_rand15), | |
| 235 | 263 | KUNIT_CASE(test_range1_rand16), |
| 236 | 264 | KUNIT_CASE(test_range2_rand0), |
| 237 | 265 | KUNIT_CASE(test_range2_rand1), |
| 238 | 266 | KUNIT_CASE(test_range2_rand2), |
| 267 | + KUNIT_CASE(test_range2_rand15), | |
| 239 | 268 | KUNIT_CASE(test_range2_rand16), |
| 240 | 269 | {} |
| 241 | 270 | /* clang-format on */ |
| @@ -9,6 +9,7 @@ · 8 unmodified lines | ||
| 9 | 9 | |
| 10 | 10 | #include <asm/current.h> |
| 11 | 11 | #include <linux/anon_inodes.h> |
| 12 | +#include <linux/bitops.h> | |
| 12 | 13 | #include <linux/build_bug.h> |
| 13 | 14 | #include <linux/capability.h> |
| 14 | 15 | #include <linux/cleanup.h> |
| @@ -563,7 +564,7 @@ SYSCALL_DEFINE2(landlock_restrict_self, const int, ruleset_fd, const __u32, · 548 unmodified lines | ||
| 563 | 564 | new_llcred->domain = new_dom; |
| 564 | 565 | |
| 565 | 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 | 568 | #endif /* CONFIG_AUDIT */ |
| 568 | 569 | |
| 569 | 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 | 733 | static int __deliver_to_subscribers(struct snd_seq_client *client, |
| 734 | 734 | struct snd_seq_event *event, |
| 735 | − struct snd_seq_client_port *src_port, | |
| 736 | − int atomic, int hop) | |
| 735 | + int port, int atomic, int hop) | |
| 737 | 736 | { |
| 737 | + struct snd_seq_client_port *src_port; | |
| 738 | 738 | struct snd_seq_subscribers *subs; |
| 739 | 739 | int err, result = 0, num_ev = 0; |
| 740 | 740 | union __snd_seq_event event_saved; |
| 741 | 741 | size_t saved_size; |
| 742 | 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 | 750 | /* save original event record */ |
| 745 | 751 | saved_size = snd_seq_event_packet_size(event); |
| 746 | 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 | 781 | read_unlock(&grp->list_lock); |
| 776 | 782 | else |
| 777 | 783 | up_read(&grp->list_mutex); |
| 784 | + snd_seq_port_unlock(src_port); | |
| 778 | 785 | memcpy(event, &event_saved, saved_size); |
| 779 | 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 | 790 | struct snd_seq_event *event, |
| 784 | 791 | int atomic, int hop) |
| 785 | 792 | { |
| 786 | − struct snd_seq_client_port *src_port; | |
| 787 | − int ret = 0, ret2; | |
| 788 | − | |
| 789 | − src_port = snd_seq_port_use_ptr(client, event->source.port); | |
| 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; | |
| 793 | + int ret; | |
| 794 | +#if IS_ENABLED(CONFIG_SND_SEQ_UMP) | |
| 795 | + int ret2; | |
| 796 | +#endif | |
| 798 | 797 | |
| 799 | − src_port = snd_seq_port_use_ptr(client, client->ump_endpoint_port); | |
| 800 | − if (!src_port) | |
| 798 | + ret = __deliver_to_subscribers(client, event, | |
| 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 | 802 | return ret; |
| 802 | − ret2 = __deliver_to_subscribers(client, event, src_port, atomic, hop); | |
| 803 | − snd_seq_port_unlock(src_port); | |
| 804 | − return ret2 < 0 ? ret2 : ret; | |
| 803 | + /* If it's an event from EP port (and with a UMP group), | |
| 804 | + * deliver to subscribers of the corresponding UMP group port, too. | |
| 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 | 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 | 1285 | else |
| 1286 | 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 | 18 | struct snd_seq_client_port *dest_port, |
| 19 | 19 | struct snd_seq_event *event, |
| 20 | 20 | int atomic, int hop); |
| 21 | +int snd_seq_ump_group_port(const struct snd_seq_event *event); | |
| 21 | 22 | |
| 22 | 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 | 177 | * sdw_intel_startup() is required for creation of devices and bus |
| 178 | 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 | 181 | struct sdw_intel_acpi_info *info) |
| 182 | 182 | { |
| 183 | 183 | acpi_status status; |
| @@ -1561,7 +1561,7 @@ static int snd_es1968_capture_open(struct snd_pcm_substream *substream) · 1560 unmodified lines | ||
| 1561 | 1561 | struct snd_pcm_runtime *runtime = substream->runtime; |
| 1562 | 1562 | struct es1968 *chip = snd_pcm_substream_chip(substream); |
| 1563 | 1563 | struct esschan *es; |
| 1564 | − int apu1, apu2; | |
| 1564 | + int err, apu1, apu2; | |
| 1565 | 1565 | |
| 1566 | 1566 | apu1 = snd_es1968_alloc_apu_pair(chip, ESM_APU_PCM_CAPTURE); |
| 1567 | 1567 | if (apu1 < 0) |
| @@ -1605,7 +1605,9 @@ static int snd_es1968_capture_open(struct snd_pcm_substream *substream) · 37 unmodified lines | ||
| 1605 | 1605 | runtime->hw = snd_es1968_capture; |
| 1606 | 1606 | runtime->hw.buffer_bytes_max = runtime->hw.period_bytes_max = |
| 1607 | 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 | 1612 | spin_lock_irq(&chip->substream_lock); |
| 1611 | 1613 | list_add(&es->list, &chip->substream_list); |
| @@ -14,7 +14,7 @@ if SND_SUPERH · 13 unmodified lines | ||
| 14 | 14 | |
| 15 | 15 | config SND_AICA |
| 16 | 16 | tristate "Dreamcast Yamaha AICA sound" |
| 17 | − depends on SH_DREAMCAST | |
| 17 | + depends on SH_DREAMCAST && SH_DMA_API | |
| 18 | 18 | select SND_PCM |
| 19 | 19 | select G2_DMA |
| 20 | 20 | help |
| @@ -2242,6 +2242,8 @@ static const struct usb_audio_quirk_flags_table quirk_flags_table[] = { · 2241 unmodified lines | ||
| 2242 | 2242 | QUIRK_FLAG_CTL_MSG_DELAY_1M), |
| 2243 | 2243 | DEVICE_FLG(0x0c45, 0x6340, /* Sonix HD USB Camera */ |
| 2244 | 2244 | QUIRK_FLAG_GET_SAMPLE_RATE), |
| 2245 | + DEVICE_FLG(0x0c45, 0x636b, /* Microdia JP001 USB Camera */ | |
| 2246 | + QUIRK_FLAG_GET_SAMPLE_RATE), | |
| 2245 | 2247 | DEVICE_FLG(0x0d8c, 0x0014, /* USB Audio Device */ |
| 2246 | 2248 | QUIRK_FLAG_CTL_MSG_DELAY_1M), |
| 2247 | 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 | 2252 | QUIRK_FLAG_FIXED_RATE), |
| 2251 | 2253 | DEVICE_FLG(0x0fd9, 0x0008, /* Hauppauge HVR-950Q */ |
| 2252 | 2254 | QUIRK_FLAG_SHARE_MEDIA_DEVICE | QUIRK_FLAG_ALIGN_TRANSFER), |
| 2255 | + DEVICE_FLG(0x1101, 0x0003, /* Audioengine D1 */ | |
| 2256 | + QUIRK_FLAG_GET_SAMPLE_RATE), | |
| 2253 | 2257 | DEVICE_FLG(0x1224, 0x2a25, /* Jieli Technology USB PHY 2.0 */ |
| 2254 | 2258 | QUIRK_FLAG_GET_SAMPLE_RATE | QUIRK_FLAG_MIC_RES_16), |
| 2255 | 2259 | DEVICE_FLG(0x1395, 0x740a, /* Sennheiser DECT */ |
| @@ -338,16 +338,24 @@ def main(): · 337 unmodified lines | ||
| 338 | 338 | print('Capabilities:') |
| 339 | 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:') | |
| 344 | − [print(f'\t{v}') for v in bits_to_dict(tsinfo['tx-types'])] | |
| 343 | + if 'tx-types' in tsinfo: | |
| 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:') | |
| 347 | − [print(f'\t{v}') for v in bits_to_dict(tsinfo['rx-filters'])] | |
| 355 | + if 'stats' in tsinfo and tsinfo['stats']: | |
| 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 | 359 | return |
| 352 | 360 | |
| 353 | 361 | print(f'Settings for {args.device}:') |
| @@ -1143,10 +1143,9 @@ class Family(SpecFamily): · 1142 unmodified lines | ||
| 1143 | 1143 | self.pure_nested_structs[nested].request = True |
| 1144 | 1144 | if attr in rs_members['reply']: |
| 1145 | 1145 | self.pure_nested_structs[nested].reply = True |
| 1146 | − | |
| 1147 | − if spec.is_multi_val(): | |
| 1148 | − child = self.pure_nested_structs.get(nested) | |
| 1149 | − child.in_multi_val = True | |
| 1146 | + if spec.is_multi_val(): | |
| 1147 | + child = self.pure_nested_structs.get(nested) | |
| 1148 | + child.in_multi_val = True | |
| 1150 | 1149 | |
| 1151 | 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 | 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 | 450 | int do_server(struct memory_buffer *mem) |
| 435 | 451 | { |
| 436 | 452 | char ctrl_data[sizeof(int) * 20000]; |
| @@ -448,7 +464,6 @@ int do_server(struct memory_buffer *mem) · 11 unmodified lines | ||
| 448 | 464 | char buffer[256]; |
| 449 | 465 | int socket_fd; |
| 450 | 466 | int client_fd; |
| 451 | − size_t i = 0; | |
| 452 | 467 | int ret; |
| 453 | 468 | |
| 454 | 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 | 487 | sleep(1); |
| 473 | 488 | |
| 474 | − queues = malloc(sizeof(*queues) * num_queues); | |
| 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)) | |
| 489 | + if (bind_rx_queue(ifindex, mem->fd, create_queues(), num_queues, &ys)) | |
| 484 | 490 | error(1, 0, "Failed to bind\n"); |
| 485 | 491 | |
| 486 | 492 | tmp_mem = malloc(mem->size); |
| @@ -545,7 +551,6 @@ int do_server(struct memory_buffer *mem) · 58 unmodified lines | ||
| 545 | 551 | goto cleanup; |
| 546 | 552 | } |
| 547 | 553 | |
| 548 | − i++; | |
| 549 | 554 | for (cm = CMSG_FIRSTHDR(&msg); cm; cm = CMSG_NXTHDR(&msg, cm)) { |
| 550 | 555 | if (cm->cmsg_level != SOL_SOCKET || |
| 551 | 556 | (cm->cmsg_type != SCM_DEVMEM_DMABUF && |
| @@ -630,10 +635,8 @@ cleanup: · 78 unmodified lines | ||
| 630 | 635 | |
| 631 | 636 | void run_devmem_tests(void) |
| 632 | 637 | { |
| 633 | − struct netdev_queue_id *queues; | |
| 634 | 638 | struct memory_buffer *mem; |
| 635 | 639 | struct ynl_sock *ys; |
| 636 | − size_t i = 0; | |
| 637 | 640 | |
| 638 | 641 | mem = provider->alloc(getpagesize() * NUM_PAGES); |
| 639 | 642 | |
| @@ -641,38 +644,24 @@ void run_devmem_tests(void) · 1 unmodified line | ||
| 641 | 644 | if (configure_rss()) |
| 642 | 645 | error(1, 0, "rss error\n"); |
| 643 | 646 | |
| 644 | − queues = calloc(num_queues, sizeof(*queues)); | |
| 645 | − | |
| 646 | 647 | if (configure_headersplit(1)) |
| 647 | 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 | 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 | 655 | if (configure_headersplit(0)) |
| 660 | 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 | 659 | error(1, 0, "Configure dmabuf with header split off should have failed\n"); |
| 664 | 660 | |
| 665 | 661 | if (configure_headersplit(1)) |
| 666 | 662 | error(1, 0, "Failed to configure header split\n"); |
| 667 | 663 | |
| 668 | − for (i = 0; i < num_queues; i++) { | |
| 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)) | |
| 664 | + if (bind_rx_queue(ifindex, mem->fd, create_queues(), num_queues, &ys)) | |
| 676 | 665 | error(1, 0, "Failed to bind\n"); |
| 677 | 666 | |
| 678 | 667 | /* Deactivating a bound queue should not be legal */ |
| @@ -189,5 +189,29 @@ · 188 unmodified lines | ||
| 189 | 189 | "teardown": [ |
| 190 | 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 | 377 | "teardown": [ |
| 378 | 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 | 294 | "teardown": [ |
| 295 | 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 | 18 | "matchCount": "1", |
| 19 | 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 | 188 | "teardown": [ |
| 189 | 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 | 1264 | send_buf(fd, buf, sizeof(buf), 0, sizeof(buf)); |
| 1265 | 1265 | control_expectln("RECEIVED"); |
| 1266 | 1266 | |
| 1267 | − ret = ioctl(fd, SIOCOUTQ, &sock_bytes_unsent); | |
| 1268 | − if (ret < 0) { | |
| 1269 | − if (errno == EOPNOTSUPP) { | |
| 1270 | − fprintf(stderr, "Test skipped, SIOCOUTQ not supported.\n"); | |
| 1271 | − } else { | |
| 1267 | + /* SIOCOUTQ isn't guaranteed to instantly track sent data. Even though | |
| 1268 | + * the "RECEIVED" message means that the other side has received the | |
| 1269 | + * data, there can be a delay in our kernel before updating the "unsent | |
| 1270 | + * bytes" counter. Repeat SIOCOUTQ until it returns 0. | |
| 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 | 1280 | perror("ioctl"); |
| 1273 | 1281 | exit(EXIT_FAILURE); |
| 1274 | 1282 | } |
| 1275 | − } else if (ret == 0 && sock_bytes_unsent != 0) { | |
| 1276 | − fprintf(stderr, | |
| 1277 | − "Unexpected 'SIOCOUTQ' value, expected 0, got %i\n", | |
| 1278 | − sock_bytes_unsent); | |
| 1279 | − exit(EXIT_FAILURE); | |
| 1280 | − } | |
| 1281 | − | |
| 1283 | + timeout_check("SIOCOUTQ"); | |
| 1284 | + } while (sock_bytes_unsent != 0); | |
| 1285 | + timeout_end(); | |
| 1282 | 1286 | close(fd); |
| 1283 | 1287 | } |
| 1284 | 1288 | |
| @@ -59,6 +59,10 @@ ifeq ($(SRCARCH),arc) · 58 unmodified lines | ||
| 59 | 59 | no-header-test += linux/bpf_perf_event.h |
| 60 | 60 | endif |
| 61 | 61 | |
| 62 | +ifeq ($(SRCARCH),openrisc) | |
| 63 | +no-header-test += linux/bpf_perf_event.h | |
| 64 | +endif | |
| 65 | + | |
| 62 | 66 | ifeq ($(SRCARCH),powerpc) |
| 63 | 67 | no-header-test += linux/bpf_perf_event.h |
| 64 | 68 | endif |