mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-05-05 12:16:29 -04:00
Merge tag 'v6.15-rc7' into x86/core, to pick up fixes
Pick up build fixes from upstream to make this tree more testable. Signed-off-by: Ingo Molnar <mingo@kernel.org>
This commit is contained in:
1
.mailmap
1
.mailmap
@@ -102,6 +102,7 @@ Ard Biesheuvel <ardb@kernel.org> <ard.biesheuvel@linaro.org>
|
||||
Arnaud Patard <arnaud.patard@rtp-net.org>
|
||||
Arnd Bergmann <arnd@arndb.de>
|
||||
Arun Kumar Neelakantam <quic_aneela@quicinc.com> <aneela@codeaurora.org>
|
||||
Asahi Lina <lina+kernel@asahilina.net> <lina@asahilina.net>
|
||||
Ashok Raj Nagarajan <quic_arnagara@quicinc.com> <arnagara@codeaurora.org>
|
||||
Ashwin Chaugule <quic_ashwinc@quicinc.com> <ashwinc@codeaurora.org>
|
||||
Asutosh Das <quic_asutoshd@quicinc.com> <asutoshd@codeaurora.org>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
What: /sys/bus/hid/drivers/hid-appletb-kbd/<dev>/mode
|
||||
Date: September, 2023
|
||||
KernelVersion: 6.5
|
||||
Date: March, 2025
|
||||
KernelVersion: 6.15
|
||||
Contact: linux-input@vger.kernel.org
|
||||
Description:
|
||||
The set of keys displayed on the Touch Bar.
|
||||
|
||||
@@ -46,6 +46,21 @@ The kernel embeds the building user and host names in
|
||||
`KBUILD_BUILD_USER and KBUILD_BUILD_HOST`_ variables. If you are
|
||||
building from a git commit, you could use its committer address.
|
||||
|
||||
Absolute filenames
|
||||
------------------
|
||||
|
||||
When the kernel is built out-of-tree, debug information may include
|
||||
absolute filenames for the source files. This must be overridden by
|
||||
including the ``-fdebug-prefix-map`` option in the `KCFLAGS`_ variable.
|
||||
|
||||
Depending on the compiler used, the ``__FILE__`` macro may also expand
|
||||
to an absolute filename in an out-of-tree build. Kbuild automatically
|
||||
uses the ``-fmacro-prefix-map`` option to prevent this, if it is
|
||||
supported.
|
||||
|
||||
The Reproducible Builds web site has more information about these
|
||||
`prefix-map options`_.
|
||||
|
||||
Generated files in source packages
|
||||
----------------------------------
|
||||
|
||||
@@ -116,5 +131,7 @@ See ``scripts/setlocalversion`` for details.
|
||||
|
||||
.. _KBUILD_BUILD_TIMESTAMP: kbuild.html#kbuild-build-timestamp
|
||||
.. _KBUILD_BUILD_USER and KBUILD_BUILD_HOST: kbuild.html#kbuild-build-user-kbuild-build-host
|
||||
.. _KCFLAGS: kbuild.html#kcflags
|
||||
.. _prefix-map options: https://reproducible-builds.org/docs/build-path/
|
||||
.. _Reproducible Builds project: https://reproducible-builds.org/
|
||||
.. _SOURCE_DATE_EPOCH: https://reproducible-builds.org/docs/source-date-epoch/
|
||||
|
||||
@@ -2017,7 +2017,8 @@ attribute-sets:
|
||||
attributes:
|
||||
-
|
||||
name: act
|
||||
type: nest
|
||||
type: indexed-array
|
||||
sub-type: nest
|
||||
nested-attributes: tc-act-attrs
|
||||
-
|
||||
name: police
|
||||
@@ -2250,7 +2251,8 @@ attribute-sets:
|
||||
attributes:
|
||||
-
|
||||
name: act
|
||||
type: nest
|
||||
type: indexed-array
|
||||
sub-type: nest
|
||||
nested-attributes: tc-act-attrs
|
||||
-
|
||||
name: police
|
||||
@@ -2745,7 +2747,7 @@ attribute-sets:
|
||||
type: u16
|
||||
byte-order: big-endian
|
||||
-
|
||||
name: key-l2-tpv3-sid
|
||||
name: key-l2tpv3-sid
|
||||
type: u32
|
||||
byte-order: big-endian
|
||||
-
|
||||
@@ -3504,7 +3506,7 @@ attribute-sets:
|
||||
name: rate64
|
||||
type: u64
|
||||
-
|
||||
name: prate4
|
||||
name: prate64
|
||||
type: u64
|
||||
-
|
||||
name: burst
|
||||
|
||||
@@ -811,11 +811,9 @@ Documentation/devicetree/bindings/ptp/timestamper.txt for more details.
|
||||
3.2.4 Other caveats for MAC drivers
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
Stacked PHCs, especially DSA (but not only) - since that doesn't require any
|
||||
modification to MAC drivers, so it is more difficult to ensure correctness of
|
||||
all possible code paths - is that they uncover bugs which were impossible to
|
||||
trigger before the existence of stacked PTP clocks. One example has to do with
|
||||
this line of code, already presented earlier::
|
||||
The use of stacked PHCs may uncover MAC driver bugs which were impossible to
|
||||
trigger without them. One example has to do with this line of code, already
|
||||
presented earlier::
|
||||
|
||||
skb_shinfo(skb)->tx_flags |= SKBTX_IN_PROGRESS;
|
||||
|
||||
|
||||
26
MAINTAINERS
26
MAINTAINERS
@@ -10147,6 +10147,13 @@ F: drivers/gpio/gpio-regmap.c
|
||||
F: include/linux/gpio/regmap.h
|
||||
K: (devm_)?gpio_regmap_(un)?register
|
||||
|
||||
GPIO SLOPPY LOGIC ANALYZER
|
||||
M: Wolfram Sang <wsa+renesas@sang-engineering.com>
|
||||
S: Supported
|
||||
F: Documentation/dev-tools/gpio-sloppy-logic-analyzer.rst
|
||||
F: drivers/gpio/gpio-sloppy-logic-analyzer.c
|
||||
F: tools/gpio/gpio-sloppy-logic-analyzer.sh
|
||||
|
||||
GPIO SUBSYSTEM
|
||||
M: Linus Walleij <linus.walleij@linaro.org>
|
||||
M: Bartosz Golaszewski <brgl@bgdev.pl>
|
||||
@@ -15542,6 +15549,18 @@ S: Maintained
|
||||
F: include/linux/execmem.h
|
||||
F: mm/execmem.c
|
||||
|
||||
MEMORY MANAGEMENT - GUP (GET USER PAGES)
|
||||
M: Andrew Morton <akpm@linux-foundation.org>
|
||||
M: David Hildenbrand <david@redhat.com>
|
||||
R: Jason Gunthorpe <jgg@nvidia.com>
|
||||
R: John Hubbard <jhubbard@nvidia.com>
|
||||
R: Peter Xu <peterx@redhat.com>
|
||||
L: linux-mm@kvack.org
|
||||
S: Maintained
|
||||
W: http://www.linux-mm.org
|
||||
T: git git://git.kernel.org/pub/scm/linux/kernel/git/akpm/mm
|
||||
F: mm/gup.c
|
||||
|
||||
MEMORY MANAGEMENT - NUMA MEMBLOCKS AND NUMA EMULATION
|
||||
M: Andrew Morton <akpm@linux-foundation.org>
|
||||
M: Mike Rapoport <rppt@kernel.org>
|
||||
@@ -18432,7 +18451,7 @@ F: include/uapi/linux/ppdev.h
|
||||
PARAVIRT_OPS INTERFACE
|
||||
M: Juergen Gross <jgross@suse.com>
|
||||
R: Ajay Kaher <ajay.kaher@broadcom.com>
|
||||
R: Alexey Makhalov <alexey.amakhalov@broadcom.com>
|
||||
R: Alexey Makhalov <alexey.makhalov@broadcom.com>
|
||||
R: Broadcom internal kernel review list <bcm-kernel-feedback-list@broadcom.com>
|
||||
L: virtualization@lists.linux.dev
|
||||
L: x86@kernel.org
|
||||
@@ -22916,7 +22935,6 @@ F: drivers/accessibility/speakup/
|
||||
|
||||
SPEAR PLATFORM/CLOCK/PINCTRL SUPPORT
|
||||
M: Viresh Kumar <vireshk@kernel.org>
|
||||
M: Shiraz Hashim <shiraz.linux.kernel@gmail.com>
|
||||
L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
|
||||
L: soc@lists.linux.dev
|
||||
S: Maintained
|
||||
@@ -25918,7 +25936,7 @@ F: drivers/misc/vmw_balloon.c
|
||||
|
||||
VMWARE HYPERVISOR INTERFACE
|
||||
M: Ajay Kaher <ajay.kaher@broadcom.com>
|
||||
M: Alexey Makhalov <alexey.amakhalov@broadcom.com>
|
||||
M: Alexey Makhalov <alexey.makhalov@broadcom.com>
|
||||
R: Broadcom internal kernel review list <bcm-kernel-feedback-list@broadcom.com>
|
||||
L: virtualization@lists.linux.dev
|
||||
L: x86@kernel.org
|
||||
@@ -25946,7 +25964,7 @@ F: drivers/scsi/vmw_pvscsi.h
|
||||
VMWARE VIRTUAL PTP CLOCK DRIVER
|
||||
M: Nick Shi <nick.shi@broadcom.com>
|
||||
R: Ajay Kaher <ajay.kaher@broadcom.com>
|
||||
R: Alexey Makhalov <alexey.amakhalov@broadcom.com>
|
||||
R: Alexey Makhalov <alexey.makhalov@broadcom.com>
|
||||
R: Broadcom internal kernel review list <bcm-kernel-feedback-list@broadcom.com>
|
||||
L: netdev@vger.kernel.org
|
||||
S: Supported
|
||||
|
||||
5
Makefile
5
Makefile
@@ -2,7 +2,7 @@
|
||||
VERSION = 6
|
||||
PATCHLEVEL = 15
|
||||
SUBLEVEL = 0
|
||||
EXTRAVERSION = -rc6
|
||||
EXTRAVERSION = -rc7
|
||||
NAME = Baby Opossum Posse
|
||||
|
||||
# *DOCUMENTATION*
|
||||
@@ -1068,8 +1068,7 @@ KBUILD_CFLAGS += -fno-builtin-wcslen
|
||||
|
||||
# change __FILE__ to the relative path to the source directory
|
||||
ifdef building_out_of_srctree
|
||||
KBUILD_CPPFLAGS += $(call cc-option,-ffile-prefix-map=$(srcroot)/=)
|
||||
KBUILD_RUSTFLAGS += --remap-path-prefix=$(srcroot)/=
|
||||
KBUILD_CPPFLAGS += $(call cc-option,-fmacro-prefix-map=$(srcroot)/=)
|
||||
endif
|
||||
|
||||
# include additional Makefiles when needed
|
||||
|
||||
@@ -451,7 +451,7 @@ analog_top: analog-top@81a8 {
|
||||
pwm_ef: pwm@86c0 {
|
||||
compatible = "amlogic,meson8-pwm-v2";
|
||||
clocks = <&xtal>,
|
||||
<>, /* unknown/untested, the datasheet calls it "Video PLL" */
|
||||
<0>, /* unknown/untested, the datasheet calls it "Video PLL" */
|
||||
<&clkc CLKID_FCLK_DIV4>,
|
||||
<&clkc CLKID_FCLK_DIV3>;
|
||||
reg = <0x86c0 0x10>;
|
||||
@@ -705,7 +705,7 @@ timer@600 {
|
||||
&pwm_ab {
|
||||
compatible = "amlogic,meson8-pwm-v2";
|
||||
clocks = <&xtal>,
|
||||
<>, /* unknown/untested, the datasheet calls it "Video PLL" */
|
||||
<0>, /* unknown/untested, the datasheet calls it "Video PLL" */
|
||||
<&clkc CLKID_FCLK_DIV4>,
|
||||
<&clkc CLKID_FCLK_DIV3>;
|
||||
};
|
||||
@@ -713,7 +713,7 @@ &pwm_ab {
|
||||
&pwm_cd {
|
||||
compatible = "amlogic,meson8-pwm-v2";
|
||||
clocks = <&xtal>,
|
||||
<>, /* unknown/untested, the datasheet calls it "Video PLL" */
|
||||
<0>, /* unknown/untested, the datasheet calls it "Video PLL" */
|
||||
<&clkc CLKID_FCLK_DIV4>,
|
||||
<&clkc CLKID_FCLK_DIV3>;
|
||||
};
|
||||
|
||||
@@ -406,7 +406,7 @@ pwm_ef: pwm@86c0 {
|
||||
compatible = "amlogic,meson8b-pwm-v2", "amlogic,meson8-pwm-v2";
|
||||
reg = <0x86c0 0x10>;
|
||||
clocks = <&xtal>,
|
||||
<>, /* unknown/untested, the datasheet calls it "Video PLL" */
|
||||
<0>, /* unknown/untested, the datasheet calls it "Video PLL" */
|
||||
<&clkc CLKID_FCLK_DIV4>,
|
||||
<&clkc CLKID_FCLK_DIV3>;
|
||||
#pwm-cells = <3>;
|
||||
@@ -680,7 +680,7 @@ timer@600 {
|
||||
&pwm_ab {
|
||||
compatible = "amlogic,meson8b-pwm-v2", "amlogic,meson8-pwm-v2";
|
||||
clocks = <&xtal>,
|
||||
<>, /* unknown/untested, the datasheet calls it "Video PLL" */
|
||||
<0>, /* unknown/untested, the datasheet calls it "Video PLL" */
|
||||
<&clkc CLKID_FCLK_DIV4>,
|
||||
<&clkc CLKID_FCLK_DIV3>;
|
||||
};
|
||||
@@ -688,7 +688,7 @@ &pwm_ab {
|
||||
&pwm_cd {
|
||||
compatible = "amlogic,meson8b-pwm-v2", "amlogic,meson8-pwm-v2";
|
||||
clocks = <&xtal>,
|
||||
<>, /* unknown/untested, the datasheet calls it "Video PLL" */
|
||||
<0>, /* unknown/untested, the datasheet calls it "Video PLL" */
|
||||
<&clkc CLKID_FCLK_DIV4>,
|
||||
<&clkc CLKID_FCLK_DIV3>;
|
||||
};
|
||||
|
||||
@@ -151,7 +151,7 @@ msix: msix@fbe00000 {
|
||||
al,msi-num-spis = <160>;
|
||||
};
|
||||
|
||||
io-fabric@fc000000 {
|
||||
io-bus@fc000000 {
|
||||
compatible = "simple-bus";
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
|
||||
@@ -361,7 +361,7 @@ msix: msix@fbe00000 {
|
||||
interrupt-parent = <&gic>;
|
||||
};
|
||||
|
||||
io-fabric@fc000000 {
|
||||
io-bus@fc000000 {
|
||||
compatible = "simple-bus";
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
|
||||
@@ -2313,7 +2313,7 @@ pwm_ef: pwm@19000 {
|
||||
"amlogic,meson8-pwm-v2";
|
||||
reg = <0x0 0x19000 0x0 0x20>;
|
||||
clocks = <&xtal>,
|
||||
<>, /* unknown/untested, the datasheet calls it "vid_pll" */
|
||||
<0>, /* unknown/untested, the datasheet calls it "vid_pll" */
|
||||
<&clkc CLKID_FCLK_DIV4>,
|
||||
<&clkc CLKID_FCLK_DIV3>;
|
||||
#pwm-cells = <3>;
|
||||
@@ -2325,7 +2325,7 @@ pwm_cd: pwm@1a000 {
|
||||
"amlogic,meson8-pwm-v2";
|
||||
reg = <0x0 0x1a000 0x0 0x20>;
|
||||
clocks = <&xtal>,
|
||||
<>, /* unknown/untested, the datasheet calls it "vid_pll" */
|
||||
<0>, /* unknown/untested, the datasheet calls it "vid_pll" */
|
||||
<&clkc CLKID_FCLK_DIV4>,
|
||||
<&clkc CLKID_FCLK_DIV3>;
|
||||
#pwm-cells = <3>;
|
||||
@@ -2337,7 +2337,7 @@ pwm_ab: pwm@1b000 {
|
||||
"amlogic,meson8-pwm-v2";
|
||||
reg = <0x0 0x1b000 0x0 0x20>;
|
||||
clocks = <&xtal>,
|
||||
<>, /* unknown/untested, the datasheet calls it "vid_pll" */
|
||||
<0>, /* unknown/untested, the datasheet calls it "vid_pll" */
|
||||
<&clkc CLKID_FCLK_DIV4>,
|
||||
<&clkc CLKID_FCLK_DIV3>;
|
||||
#pwm-cells = <3>;
|
||||
|
||||
@@ -116,6 +116,10 @@ &arb {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&clkc_audio {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&frddr_a {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
@@ -741,7 +741,7 @@ mux {
|
||||
|
||||
&pwm_ab {
|
||||
clocks = <&xtal>,
|
||||
<>, /* unknown/untested, the datasheet calls it "vid_pll" */
|
||||
<0>, /* unknown/untested, the datasheet calls it "vid_pll" */
|
||||
<&clkc CLKID_FCLK_DIV4>,
|
||||
<&clkc CLKID_FCLK_DIV3>;
|
||||
};
|
||||
@@ -752,14 +752,14 @@ &pwm_AO_ab {
|
||||
|
||||
&pwm_cd {
|
||||
clocks = <&xtal>,
|
||||
<>, /* unknown/untested, the datasheet calls it "vid_pll" */
|
||||
<0>, /* unknown/untested, the datasheet calls it "vid_pll" */
|
||||
<&clkc CLKID_FCLK_DIV4>,
|
||||
<&clkc CLKID_FCLK_DIV3>;
|
||||
};
|
||||
|
||||
&pwm_ef {
|
||||
clocks = <&xtal>,
|
||||
<>, /* unknown/untested, the datasheet calls it "vid_pll" */
|
||||
<0>, /* unknown/untested, the datasheet calls it "vid_pll" */
|
||||
<&clkc CLKID_FCLK_DIV4>,
|
||||
<&clkc CLKID_FCLK_DIV3>;
|
||||
};
|
||||
|
||||
@@ -811,7 +811,7 @@ internal_phy: ethernet-phy@8 {
|
||||
|
||||
&pwm_ab {
|
||||
clocks = <&xtal>,
|
||||
<>, /* unknown/untested, the datasheet calls it "vid_pll" */
|
||||
<0>, /* unknown/untested, the datasheet calls it "vid_pll" */
|
||||
<&clkc CLKID_FCLK_DIV4>,
|
||||
<&clkc CLKID_FCLK_DIV3>;
|
||||
};
|
||||
@@ -822,14 +822,14 @@ &pwm_AO_ab {
|
||||
|
||||
&pwm_cd {
|
||||
clocks = <&xtal>,
|
||||
<>, /* unknown/untested, the datasheet calls it "vid_pll" */
|
||||
<0>, /* unknown/untested, the datasheet calls it "vid_pll" */
|
||||
<&clkc CLKID_FCLK_DIV4>,
|
||||
<&clkc CLKID_FCLK_DIV3>;
|
||||
};
|
||||
|
||||
&pwm_ef {
|
||||
clocks = <&xtal>,
|
||||
<>, /* unknown/untested, the datasheet calls it "vid_pll" */
|
||||
<0>, /* unknown/untested, the datasheet calls it "vid_pll" */
|
||||
<&clkc CLKID_FCLK_DIV4>,
|
||||
<&clkc CLKID_FCLK_DIV3>;
|
||||
};
|
||||
|
||||
@@ -77,6 +77,16 @@ touchbar0: touchbar@0 {
|
||||
};
|
||||
};
|
||||
|
||||
/*
|
||||
* The driver depends on boot loader initialized state which resets when this
|
||||
* power-domain is powered off. This happens on suspend or when the driver is
|
||||
* missing during boot. Mark the domain as always on until the driver can
|
||||
* handle this.
|
||||
*/
|
||||
&ps_dispdfr_be {
|
||||
apple,always-on;
|
||||
};
|
||||
|
||||
&display_dfr {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
@@ -40,6 +40,16 @@ led-0 {
|
||||
};
|
||||
};
|
||||
|
||||
/*
|
||||
* The driver depends on boot loader initialized state which resets when this
|
||||
* power-domain is powered off. This happens on suspend or when the driver is
|
||||
* missing during boot. Mark the domain as always on until the driver can
|
||||
* handle this.
|
||||
*/
|
||||
&ps_dispdfr_be {
|
||||
apple,always-on;
|
||||
};
|
||||
|
||||
&display_dfr {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
@@ -88,3 +88,5 @@ &media_blk_ctrl {
|
||||
<0>, <0>, <400000000>,
|
||||
<1039500000>;
|
||||
};
|
||||
|
||||
/delete-node/ &{noc_opp_table/opp-1000000000};
|
||||
|
||||
@@ -35,7 +35,6 @@ memory@40000000 {
|
||||
<0x1 0x00000000 0 0xc0000000>;
|
||||
};
|
||||
|
||||
|
||||
reg_usdhc2_vmmc: regulator-usdhc2-vmmc {
|
||||
compatible = "regulator-fixed";
|
||||
regulator-name = "VSD_3V3";
|
||||
@@ -46,6 +45,16 @@ reg_usdhc2_vmmc: regulator-usdhc2-vmmc {
|
||||
startup-delay-us = <100>;
|
||||
off-on-delay-us = <12000>;
|
||||
};
|
||||
|
||||
reg_usdhc2_vqmmc: regulator-usdhc2-vqmmc {
|
||||
compatible = "regulator-gpio";
|
||||
regulator-name = "VSD_VSEL";
|
||||
regulator-min-microvolt = <1800000>;
|
||||
regulator-max-microvolt = <3300000>;
|
||||
gpios = <&gpio2 12 GPIO_ACTIVE_HIGH>;
|
||||
states = <3300000 0x0 1800000 0x1>;
|
||||
vin-supply = <&ldo5>;
|
||||
};
|
||||
};
|
||||
|
||||
&A53_0 {
|
||||
@@ -205,6 +214,7 @@ &usdhc2 {
|
||||
pinctrl-2 = <&pinctrl_usdhc2_200mhz>, <&pinctrl_usdhc2_gpio>;
|
||||
cd-gpios = <&gpio1 14 GPIO_ACTIVE_LOW>;
|
||||
vmmc-supply = <®_usdhc2_vmmc>;
|
||||
vqmmc-supply = <®_usdhc2_vqmmc>;
|
||||
bus-width = <4>;
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
@@ -1645,6 +1645,12 @@ opp-200000000 {
|
||||
opp-hz = /bits/ 64 <200000000>;
|
||||
};
|
||||
|
||||
/* Nominal drive mode maximum */
|
||||
opp-800000000 {
|
||||
opp-hz = /bits/ 64 <800000000>;
|
||||
};
|
||||
|
||||
/* Overdrive mode maximum */
|
||||
opp-1000000000 {
|
||||
opp-hz = /bits/ 64 <1000000000>;
|
||||
};
|
||||
|
||||
@@ -31,7 +31,7 @@ sdio_pwrseq: sdio-pwrseq {
|
||||
};
|
||||
|
||||
vcc3v3_btreg: vcc3v3-btreg {
|
||||
compatible = "regulator-gpio";
|
||||
compatible = "regulator-fixed";
|
||||
enable-active-high;
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&bt_enable_h>;
|
||||
@@ -39,7 +39,6 @@ vcc3v3_btreg: vcc3v3-btreg {
|
||||
regulator-min-microvolt = <3300000>;
|
||||
regulator-max-microvolt = <3300000>;
|
||||
regulator-always-on;
|
||||
states = <3300000 0x0>;
|
||||
};
|
||||
|
||||
vcc3v3_rf_aux_mod: regulator-vcc3v3-rf-aux-mod {
|
||||
|
||||
@@ -26,5 +26,5 @@ &sdio_pwrseq {
|
||||
};
|
||||
|
||||
&vcc3v3_btreg {
|
||||
enable-gpios = <&gpio1 RK_PC3 GPIO_ACTIVE_HIGH>;
|
||||
gpios = <&gpio1 RK_PC3 GPIO_ACTIVE_HIGH>;
|
||||
};
|
||||
|
||||
@@ -39,5 +39,5 @@ &sdio_pwrseq {
|
||||
};
|
||||
|
||||
&vcc3v3_btreg {
|
||||
enable-gpios = <&gpio1 RK_PC2 GPIO_ACTIVE_HIGH>;
|
||||
gpios = <&gpio1 RK_PC2 GPIO_ACTIVE_HIGH>;
|
||||
};
|
||||
|
||||
@@ -43,7 +43,7 @@ led-0 {
|
||||
sdio_pwrseq: sdio-pwrseq {
|
||||
compatible = "mmc-pwrseq-simple";
|
||||
clocks = <&rk808 1>;
|
||||
clock-names = "lpo";
|
||||
clock-names = "ext_clock";
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&wifi_enable_h>;
|
||||
reset-gpios = <&gpio0 RK_PB2 GPIO_ACTIVE_LOW>;
|
||||
|
||||
@@ -775,7 +775,7 @@ &sdmmc1 {
|
||||
rockchip,default-sample-phase = <90>;
|
||||
status = "okay";
|
||||
|
||||
sdio-wifi@1 {
|
||||
wifi@1 {
|
||||
compatible = "brcm,bcm4329-fmac";
|
||||
reg = <1>;
|
||||
interrupt-parent = <&gpio2>;
|
||||
|
||||
@@ -619,6 +619,8 @@ &sdhci {
|
||||
bus-width = <8>;
|
||||
max-frequency = <200000000>;
|
||||
non-removable;
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&emmc_bus8 &emmc_clk &emmc_cmd &emmc_datastrobe>;
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
|
||||
@@ -610,7 +610,7 @@ hym8563: rtc@51 {
|
||||
reg = <0x51>;
|
||||
clock-output-names = "hym8563";
|
||||
interrupt-parent = <&gpio0>;
|
||||
interrupts = <RK_PB0 IRQ_TYPE_LEVEL_LOW>;
|
||||
interrupts = <RK_PA0 IRQ_TYPE_LEVEL_LOW>;
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&hym8563_int>;
|
||||
wakeup-source;
|
||||
|
||||
@@ -222,6 +222,10 @@ rt5616: audio-codec@1b {
|
||||
compatible = "realtek,rt5616";
|
||||
reg = <0x1b>;
|
||||
#sound-dai-cells = <0>;
|
||||
assigned-clocks = <&cru I2S0_8CH_MCLKOUT>;
|
||||
assigned-clock-rates = <12288000>;
|
||||
clocks = <&cru I2S0_8CH_MCLKOUT>;
|
||||
clock-names = "mclk";
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
@@ -214,6 +214,8 @@ rgmii_phy: ethernet-phy@1 {
|
||||
};
|
||||
|
||||
&package_thermal {
|
||||
polling-delay = <1000>;
|
||||
|
||||
trips {
|
||||
package_active1: trip-active1 {
|
||||
temperature = <45000>;
|
||||
|
||||
@@ -11,20 +11,15 @@ cluster0_opp_table: opp-table-cluster0 {
|
||||
compatible = "operating-points-v2";
|
||||
opp-shared;
|
||||
|
||||
opp-1416000000 {
|
||||
opp-hz = /bits/ 64 <1416000000>;
|
||||
opp-1200000000 {
|
||||
opp-hz = /bits/ 64 <1200000000>;
|
||||
opp-microvolt = <750000 750000 950000>;
|
||||
clock-latency-ns = <40000>;
|
||||
opp-suspend;
|
||||
};
|
||||
opp-1608000000 {
|
||||
opp-hz = /bits/ 64 <1608000000>;
|
||||
opp-microvolt = <887500 887500 950000>;
|
||||
clock-latency-ns = <40000>;
|
||||
};
|
||||
opp-1704000000 {
|
||||
opp-hz = /bits/ 64 <1704000000>;
|
||||
opp-microvolt = <937500 937500 950000>;
|
||||
opp-1296000000 {
|
||||
opp-hz = /bits/ 64 <1296000000>;
|
||||
opp-microvolt = <775000 775000 950000>;
|
||||
clock-latency-ns = <40000>;
|
||||
};
|
||||
};
|
||||
@@ -33,9 +28,14 @@ cluster1_opp_table: opp-table-cluster1 {
|
||||
compatible = "operating-points-v2";
|
||||
opp-shared;
|
||||
|
||||
opp-1200000000{
|
||||
opp-hz = /bits/ 64 <1200000000>;
|
||||
opp-microvolt = <750000 750000 950000>;
|
||||
clock-latency-ns = <40000>;
|
||||
};
|
||||
opp-1416000000 {
|
||||
opp-hz = /bits/ 64 <1416000000>;
|
||||
opp-microvolt = <750000 750000 950000>;
|
||||
opp-microvolt = <762500 762500 950000>;
|
||||
clock-latency-ns = <40000>;
|
||||
};
|
||||
opp-1608000000 {
|
||||
@@ -43,25 +43,20 @@ opp-1608000000 {
|
||||
opp-microvolt = <787500 787500 950000>;
|
||||
clock-latency-ns = <40000>;
|
||||
};
|
||||
opp-1800000000 {
|
||||
opp-hz = /bits/ 64 <1800000000>;
|
||||
opp-microvolt = <875000 875000 950000>;
|
||||
clock-latency-ns = <40000>;
|
||||
};
|
||||
opp-2016000000 {
|
||||
opp-hz = /bits/ 64 <2016000000>;
|
||||
opp-microvolt = <950000 950000 950000>;
|
||||
clock-latency-ns = <40000>;
|
||||
};
|
||||
};
|
||||
|
||||
cluster2_opp_table: opp-table-cluster2 {
|
||||
compatible = "operating-points-v2";
|
||||
opp-shared;
|
||||
|
||||
opp-1200000000{
|
||||
opp-hz = /bits/ 64 <1200000000>;
|
||||
opp-microvolt = <750000 750000 950000>;
|
||||
clock-latency-ns = <40000>;
|
||||
};
|
||||
opp-1416000000 {
|
||||
opp-hz = /bits/ 64 <1416000000>;
|
||||
opp-microvolt = <750000 750000 950000>;
|
||||
opp-microvolt = <762500 762500 950000>;
|
||||
clock-latency-ns = <40000>;
|
||||
};
|
||||
opp-1608000000 {
|
||||
@@ -69,16 +64,6 @@ opp-1608000000 {
|
||||
opp-microvolt = <787500 787500 950000>;
|
||||
clock-latency-ns = <40000>;
|
||||
};
|
||||
opp-1800000000 {
|
||||
opp-hz = /bits/ 64 <1800000000>;
|
||||
opp-microvolt = <875000 875000 950000>;
|
||||
clock-latency-ns = <40000>;
|
||||
};
|
||||
opp-2016000000 {
|
||||
opp-hz = /bits/ 64 <2016000000>;
|
||||
opp-microvolt = <950000 950000 950000>;
|
||||
clock-latency-ns = <40000>;
|
||||
};
|
||||
};
|
||||
|
||||
gpu_opp_table: opp-table {
|
||||
@@ -104,10 +89,6 @@ opp-700000000 {
|
||||
opp-hz = /bits/ 64 <700000000>;
|
||||
opp-microvolt = <750000 750000 850000>;
|
||||
};
|
||||
opp-850000000 {
|
||||
opp-hz = /bits/ 64 <800000000>;
|
||||
opp-microvolt = <787500 787500 850000>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
@@ -81,6 +81,7 @@
|
||||
#define ARM_CPU_PART_CORTEX_A78AE 0xD42
|
||||
#define ARM_CPU_PART_CORTEX_X1 0xD44
|
||||
#define ARM_CPU_PART_CORTEX_A510 0xD46
|
||||
#define ARM_CPU_PART_CORTEX_X1C 0xD4C
|
||||
#define ARM_CPU_PART_CORTEX_A520 0xD80
|
||||
#define ARM_CPU_PART_CORTEX_A710 0xD47
|
||||
#define ARM_CPU_PART_CORTEX_A715 0xD4D
|
||||
@@ -168,6 +169,7 @@
|
||||
#define MIDR_CORTEX_A78AE MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A78AE)
|
||||
#define MIDR_CORTEX_X1 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_X1)
|
||||
#define MIDR_CORTEX_A510 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A510)
|
||||
#define MIDR_CORTEX_X1C MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_X1C)
|
||||
#define MIDR_CORTEX_A520 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A520)
|
||||
#define MIDR_CORTEX_A710 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A710)
|
||||
#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,
|
||||
}
|
||||
#endif
|
||||
u32 aarch64_insn_gen_dmb(enum aarch64_insn_mb_type type);
|
||||
u32 aarch64_insn_gen_dsb(enum aarch64_insn_mb_type type);
|
||||
u32 aarch64_insn_gen_mrs(enum aarch64_insn_register result,
|
||||
enum aarch64_insn_system_register sysreg);
|
||||
|
||||
|
||||
@@ -97,6 +97,9 @@ enum mitigation_state arm64_get_meltdown_state(void);
|
||||
|
||||
enum mitigation_state arm64_get_spectre_bhb_state(void);
|
||||
bool is_spectre_bhb_affected(const struct arm64_cpu_capabilities *entry, int scope);
|
||||
extern bool __nospectre_bhb;
|
||||
u8 get_spectre_bhb_loop_value(void);
|
||||
bool is_spectre_bhb_fw_mitigated(void);
|
||||
void spectre_bhb_enable_mitigation(const struct arm64_cpu_capabilities *__unused);
|
||||
bool try_emulate_el1_ssbs(struct pt_regs *regs, u32 instr);
|
||||
|
||||
|
||||
@@ -891,6 +891,7 @@ static u8 spectre_bhb_loop_affected(void)
|
||||
MIDR_ALL_VERSIONS(MIDR_CORTEX_A78AE),
|
||||
MIDR_ALL_VERSIONS(MIDR_CORTEX_A78C),
|
||||
MIDR_ALL_VERSIONS(MIDR_CORTEX_X1),
|
||||
MIDR_ALL_VERSIONS(MIDR_CORTEX_X1C),
|
||||
MIDR_ALL_VERSIONS(MIDR_CORTEX_A710),
|
||||
MIDR_ALL_VERSIONS(MIDR_CORTEX_X2),
|
||||
MIDR_ALL_VERSIONS(MIDR_NEOVERSE_N2),
|
||||
@@ -999,6 +1000,11 @@ bool is_spectre_bhb_affected(const struct arm64_cpu_capabilities *entry,
|
||||
return true;
|
||||
}
|
||||
|
||||
u8 get_spectre_bhb_loop_value(void)
|
||||
{
|
||||
return max_bhb_k;
|
||||
}
|
||||
|
||||
static void this_cpu_set_vectors(enum arm64_bp_harden_el1_vectors slot)
|
||||
{
|
||||
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)
|
||||
isb();
|
||||
}
|
||||
|
||||
static bool __read_mostly __nospectre_bhb;
|
||||
bool __read_mostly __nospectre_bhb;
|
||||
static int __init parse_spectre_bhb_param(char *str)
|
||||
{
|
||||
__nospectre_bhb = true;
|
||||
@@ -1094,6 +1100,11 @@ void spectre_bhb_enable_mitigation(const struct arm64_cpu_capabilities *entry)
|
||||
update_mitigation_state(&spectre_bhb_state, state);
|
||||
}
|
||||
|
||||
bool is_spectre_bhb_fw_mitigated(void)
|
||||
{
|
||||
return test_bit(BHB_FW, &system_bhb_mitigations);
|
||||
}
|
||||
|
||||
/* Patched to NOP when enabled */
|
||||
void noinstr spectre_bhb_patch_loop_mitigation_enable(struct alt_instr *alt,
|
||||
__le32 *origptr,
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
*
|
||||
* Copyright (C) 2014-2016 Zi Shen Lim <zlim.lnx@gmail.com>
|
||||
*/
|
||||
#include <linux/bitfield.h>
|
||||
#include <linux/bitops.h>
|
||||
#include <linux/bug.h>
|
||||
#include <linux/printk.h>
|
||||
@@ -1500,43 +1501,41 @@ u32 aarch64_insn_gen_extr(enum aarch64_insn_variant variant,
|
||||
return aarch64_insn_encode_register(AARCH64_INSN_REGTYPE_RM, insn, Rm);
|
||||
}
|
||||
|
||||
static u32 __get_barrier_crm_val(enum aarch64_insn_mb_type type)
|
||||
{
|
||||
switch (type) {
|
||||
case AARCH64_INSN_MB_SY:
|
||||
return 0xf;
|
||||
case AARCH64_INSN_MB_ST:
|
||||
return 0xe;
|
||||
case AARCH64_INSN_MB_LD:
|
||||
return 0xd;
|
||||
case AARCH64_INSN_MB_ISH:
|
||||
return 0xb;
|
||||
case AARCH64_INSN_MB_ISHST:
|
||||
return 0xa;
|
||||
case AARCH64_INSN_MB_ISHLD:
|
||||
return 0x9;
|
||||
case AARCH64_INSN_MB_NSH:
|
||||
return 0x7;
|
||||
case AARCH64_INSN_MB_NSHST:
|
||||
return 0x6;
|
||||
case AARCH64_INSN_MB_NSHLD:
|
||||
return 0x5;
|
||||
default:
|
||||
pr_err("%s: unknown barrier type %d\n", __func__, type);
|
||||
return AARCH64_BREAK_FAULT;
|
||||
}
|
||||
}
|
||||
|
||||
u32 aarch64_insn_gen_dmb(enum aarch64_insn_mb_type type)
|
||||
{
|
||||
u32 opt;
|
||||
u32 insn;
|
||||
|
||||
switch (type) {
|
||||
case AARCH64_INSN_MB_SY:
|
||||
opt = 0xf;
|
||||
break;
|
||||
case AARCH64_INSN_MB_ST:
|
||||
opt = 0xe;
|
||||
break;
|
||||
case AARCH64_INSN_MB_LD:
|
||||
opt = 0xd;
|
||||
break;
|
||||
case AARCH64_INSN_MB_ISH:
|
||||
opt = 0xb;
|
||||
break;
|
||||
case AARCH64_INSN_MB_ISHST:
|
||||
opt = 0xa;
|
||||
break;
|
||||
case AARCH64_INSN_MB_ISHLD:
|
||||
opt = 0x9;
|
||||
break;
|
||||
case AARCH64_INSN_MB_NSH:
|
||||
opt = 0x7;
|
||||
break;
|
||||
case AARCH64_INSN_MB_NSHST:
|
||||
opt = 0x6;
|
||||
break;
|
||||
case AARCH64_INSN_MB_NSHLD:
|
||||
opt = 0x5;
|
||||
break;
|
||||
default:
|
||||
pr_err("%s: unknown dmb type %d\n", __func__, type);
|
||||
opt = __get_barrier_crm_val(type);
|
||||
if (opt == AARCH64_BREAK_FAULT)
|
||||
return AARCH64_BREAK_FAULT;
|
||||
}
|
||||
|
||||
insn = aarch64_insn_get_dmb_value();
|
||||
insn &= ~GENMASK(11, 8);
|
||||
@@ -1545,6 +1544,21 @@ u32 aarch64_insn_gen_dmb(enum aarch64_insn_mb_type type)
|
||||
return insn;
|
||||
}
|
||||
|
||||
u32 aarch64_insn_gen_dsb(enum aarch64_insn_mb_type type)
|
||||
{
|
||||
u32 opt, insn;
|
||||
|
||||
opt = __get_barrier_crm_val(type);
|
||||
if (opt == AARCH64_BREAK_FAULT)
|
||||
return AARCH64_BREAK_FAULT;
|
||||
|
||||
insn = aarch64_insn_get_dsb_base_value();
|
||||
insn &= ~GENMASK(11, 8);
|
||||
insn |= (opt << 8);
|
||||
|
||||
return insn;
|
||||
}
|
||||
|
||||
u32 aarch64_insn_gen_mrs(enum aarch64_insn_register result,
|
||||
enum aarch64_insn_system_register sysreg)
|
||||
{
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
|
||||
#define pr_fmt(fmt) "bpf_jit: " fmt
|
||||
|
||||
#include <linux/arm-smccc.h>
|
||||
#include <linux/bitfield.h>
|
||||
#include <linux/bpf.h>
|
||||
#include <linux/filter.h>
|
||||
@@ -17,6 +18,7 @@
|
||||
#include <asm/asm-extable.h>
|
||||
#include <asm/byteorder.h>
|
||||
#include <asm/cacheflush.h>
|
||||
#include <asm/cpufeature.h>
|
||||
#include <asm/debug-monitors.h>
|
||||
#include <asm/insn.h>
|
||||
#include <asm/text-patching.h>
|
||||
@@ -939,7 +941,51 @@ static void build_plt(struct jit_ctx *ctx)
|
||||
plt->target = (u64)&dummy_tramp;
|
||||
}
|
||||
|
||||
static void build_epilogue(struct jit_ctx *ctx)
|
||||
/* Clobbers BPF registers 1-4, aka x0-x3 */
|
||||
static void __maybe_unused build_bhb_mitigation(struct jit_ctx *ctx)
|
||||
{
|
||||
const u8 r1 = bpf2a64[BPF_REG_1]; /* aka x0 */
|
||||
u8 k = get_spectre_bhb_loop_value();
|
||||
|
||||
if (!IS_ENABLED(CONFIG_MITIGATE_SPECTRE_BRANCH_HISTORY) ||
|
||||
cpu_mitigations_off() || __nospectre_bhb ||
|
||||
arm64_get_spectre_v2_state() == SPECTRE_VULNERABLE)
|
||||
return;
|
||||
|
||||
if (capable(CAP_SYS_ADMIN))
|
||||
return;
|
||||
|
||||
if (supports_clearbhb(SCOPE_SYSTEM)) {
|
||||
emit(aarch64_insn_gen_hint(AARCH64_INSN_HINT_CLEARBHB), ctx);
|
||||
return;
|
||||
}
|
||||
|
||||
if (k) {
|
||||
emit_a64_mov_i64(r1, k, ctx);
|
||||
emit(A64_B(1), ctx);
|
||||
emit(A64_SUBS_I(true, r1, r1, 1), ctx);
|
||||
emit(A64_B_(A64_COND_NE, -2), ctx);
|
||||
emit(aarch64_insn_gen_dsb(AARCH64_INSN_MB_ISH), ctx);
|
||||
emit(aarch64_insn_get_isb_value(), ctx);
|
||||
}
|
||||
|
||||
if (is_spectre_bhb_fw_mitigated()) {
|
||||
emit(A64_ORR_I(false, r1, AARCH64_INSN_REG_ZR,
|
||||
ARM_SMCCC_ARCH_WORKAROUND_3), ctx);
|
||||
switch (arm_smccc_1_1_get_conduit()) {
|
||||
case SMCCC_CONDUIT_HVC:
|
||||
emit(aarch64_insn_get_hvc_value(), ctx);
|
||||
break;
|
||||
case SMCCC_CONDUIT_SMC:
|
||||
emit(aarch64_insn_get_smc_value(), ctx);
|
||||
break;
|
||||
default:
|
||||
pr_err_once("Firmware mitigation enabled with unknown conduit\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void build_epilogue(struct jit_ctx *ctx, bool was_classic)
|
||||
{
|
||||
const u8 r0 = bpf2a64[BPF_REG_0];
|
||||
const u8 ptr = bpf2a64[TCCNT_PTR];
|
||||
@@ -952,10 +998,13 @@ static void build_epilogue(struct jit_ctx *ctx)
|
||||
|
||||
emit(A64_POP(A64_ZR, ptr, A64_SP), ctx);
|
||||
|
||||
if (was_classic)
|
||||
build_bhb_mitigation(ctx);
|
||||
|
||||
/* Restore FP/LR registers */
|
||||
emit(A64_POP(A64_FP, A64_LR, A64_SP), ctx);
|
||||
|
||||
/* Set return value */
|
||||
/* Move the return value from bpf:r0 (aka x7) to x0 */
|
||||
emit(A64_MOV(1, A64_R(0), r0), ctx);
|
||||
|
||||
/* Authenticate lr */
|
||||
@@ -1898,7 +1947,7 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog)
|
||||
}
|
||||
|
||||
ctx.epilogue_offset = ctx.idx;
|
||||
build_epilogue(&ctx);
|
||||
build_epilogue(&ctx, was_classic);
|
||||
build_plt(&ctx);
|
||||
|
||||
extable_align = __alignof__(struct exception_table_entry);
|
||||
@@ -1961,7 +2010,7 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog)
|
||||
goto out_free_hdr;
|
||||
}
|
||||
|
||||
build_epilogue(&ctx);
|
||||
build_epilogue(&ctx, was_classic);
|
||||
build_plt(&ctx);
|
||||
|
||||
/* Extra pass to validate JITed code. */
|
||||
|
||||
@@ -55,7 +55,7 @@ static inline void instruction_pointer_set(struct pt_regs *regs, unsigned long v
|
||||
|
||||
/* Query offset/name of register from its name/offset */
|
||||
extern int regs_query_register_offset(const char *name);
|
||||
#define MAX_REG_OFFSET (offsetof(struct pt_regs, __last))
|
||||
#define MAX_REG_OFFSET (offsetof(struct pt_regs, __last) - sizeof(unsigned long))
|
||||
|
||||
/**
|
||||
* regs_get_register() - get register value from its offset
|
||||
|
||||
@@ -15,7 +15,6 @@ typedef u32 uprobe_opcode_t;
|
||||
#define UPROBE_XOLBP_INSN __emit_break(BRK_UPROBE_XOLBP)
|
||||
|
||||
struct arch_uprobe {
|
||||
unsigned long resume_era;
|
||||
u32 insn[2];
|
||||
u32 ixol[2];
|
||||
bool simulate;
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
#include <asm/stackframe.h>
|
||||
#include <asm/thread_info.h>
|
||||
|
||||
.section .cpuidle.text, "ax"
|
||||
.align 5
|
||||
SYM_FUNC_START(__arch_cpu_idle)
|
||||
/* start of idle interrupt region */
|
||||
@@ -31,14 +32,16 @@ SYM_FUNC_START(__arch_cpu_idle)
|
||||
*/
|
||||
idle 0
|
||||
/* end of idle interrupt region */
|
||||
1: jr ra
|
||||
idle_exit:
|
||||
jr ra
|
||||
SYM_FUNC_END(__arch_cpu_idle)
|
||||
.previous
|
||||
|
||||
SYM_CODE_START(handle_vint)
|
||||
UNWIND_HINT_UNDEFINED
|
||||
BACKUP_T0T1
|
||||
SAVE_ALL
|
||||
la_abs t1, 1b
|
||||
la_abs t1, idle_exit
|
||||
LONG_L t0, sp, PT_ERA
|
||||
/* 3 instructions idle interrupt region */
|
||||
ori t0, t0, 0b1100
|
||||
|
||||
@@ -18,11 +18,28 @@ static unsigned int euen_mask = CSR_EUEN_FPEN;
|
||||
static DEFINE_PER_CPU(bool, in_kernel_fpu);
|
||||
static DEFINE_PER_CPU(unsigned int, euen_current);
|
||||
|
||||
static inline void fpregs_lock(void)
|
||||
{
|
||||
if (IS_ENABLED(CONFIG_PREEMPT_RT))
|
||||
preempt_disable();
|
||||
else
|
||||
local_bh_disable();
|
||||
}
|
||||
|
||||
static inline void fpregs_unlock(void)
|
||||
{
|
||||
if (IS_ENABLED(CONFIG_PREEMPT_RT))
|
||||
preempt_enable();
|
||||
else
|
||||
local_bh_enable();
|
||||
}
|
||||
|
||||
void kernel_fpu_begin(void)
|
||||
{
|
||||
unsigned int *euen_curr;
|
||||
|
||||
preempt_disable();
|
||||
if (!irqs_disabled())
|
||||
fpregs_lock();
|
||||
|
||||
WARN_ON(this_cpu_read(in_kernel_fpu));
|
||||
|
||||
@@ -73,7 +90,8 @@ void kernel_fpu_end(void)
|
||||
|
||||
this_cpu_write(in_kernel_fpu, false);
|
||||
|
||||
preempt_enable();
|
||||
if (!irqs_disabled())
|
||||
fpregs_unlock();
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(kernel_fpu_end);
|
||||
|
||||
|
||||
@@ -111,7 +111,7 @@ static unsigned long __init get_loops_per_jiffy(void)
|
||||
return lpj;
|
||||
}
|
||||
|
||||
static long init_offset __nosavedata;
|
||||
static long init_offset;
|
||||
|
||||
void save_counter(void)
|
||||
{
|
||||
|
||||
@@ -42,7 +42,6 @@ int arch_uprobe_pre_xol(struct arch_uprobe *auprobe, struct pt_regs *regs)
|
||||
utask->autask.saved_trap_nr = current->thread.trap_nr;
|
||||
current->thread.trap_nr = UPROBE_TRAP_NR;
|
||||
instruction_pointer_set(regs, utask->xol_vaddr);
|
||||
user_enable_single_step(current);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -53,13 +52,7 @@ int arch_uprobe_post_xol(struct arch_uprobe *auprobe, struct pt_regs *regs)
|
||||
|
||||
WARN_ON_ONCE(current->thread.trap_nr != UPROBE_TRAP_NR);
|
||||
current->thread.trap_nr = utask->autask.saved_trap_nr;
|
||||
|
||||
if (auprobe->simulate)
|
||||
instruction_pointer_set(regs, auprobe->resume_era);
|
||||
else
|
||||
instruction_pointer_set(regs, utask->vaddr + LOONGARCH_INSN_SIZE);
|
||||
|
||||
user_disable_single_step(current);
|
||||
instruction_pointer_set(regs, utask->vaddr + LOONGARCH_INSN_SIZE);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -70,7 +63,6 @@ void arch_uprobe_abort_xol(struct arch_uprobe *auprobe, struct pt_regs *regs)
|
||||
|
||||
current->thread.trap_nr = utask->autask.saved_trap_nr;
|
||||
instruction_pointer_set(regs, utask->vaddr);
|
||||
user_disable_single_step(current);
|
||||
}
|
||||
|
||||
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)
|
||||
|
||||
insn.word = auprobe->insn[0];
|
||||
arch_simulate_insn(insn, regs);
|
||||
auprobe->resume_era = regs->csr_era;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
#include <asm/fpu.h>
|
||||
#include <asm/loongson.h>
|
||||
#include <asm/sections.h>
|
||||
#include <asm/time.h>
|
||||
#include <asm/tlbflush.h>
|
||||
#include <linux/suspend.h>
|
||||
|
||||
@@ -14,6 +15,7 @@ struct pt_regs saved_regs;
|
||||
|
||||
void save_processor_state(void)
|
||||
{
|
||||
save_counter();
|
||||
saved_crmd = csr_read32(LOONGARCH_CSR_CRMD);
|
||||
saved_prmd = csr_read32(LOONGARCH_CSR_PRMD);
|
||||
saved_euen = csr_read32(LOONGARCH_CSR_EUEN);
|
||||
@@ -26,6 +28,7 @@ void save_processor_state(void)
|
||||
|
||||
void restore_processor_state(void)
|
||||
{
|
||||
sync_counter();
|
||||
csr_write32(saved_crmd, LOONGARCH_CSR_CRMD);
|
||||
csr_write32(saved_prmd, LOONGARCH_CSR_PRMD);
|
||||
csr_write32(saved_euen, LOONGARCH_CSR_EUEN);
|
||||
|
||||
@@ -341,7 +341,7 @@ dmac: dma-controller@4330000 {
|
||||
1024 1024 1024 1024>;
|
||||
snps,priority = <0 1 2 3 4 5 6 7>;
|
||||
snps,dma-masters = <2>;
|
||||
snps,data-width = <4>;
|
||||
snps,data-width = <2>;
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
|
||||
@@ -154,5 +154,6 @@ MRPROPER_FILES += $(HOST_DIR)/include/generated
|
||||
archclean:
|
||||
@find . \( -name '*.bb' -o -name '*.bbg' -o -name '*.da' \
|
||||
-o -name '*.gcov' \) -type f -print | xargs rm -f
|
||||
$(Q)$(MAKE) -f $(srctree)/Makefile ARCH=$(HEADER_ARCH) clean
|
||||
|
||||
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)
|
||||
set_pages_state(vaddr, npages, SNP_PAGE_STATE_PRIVATE);
|
||||
}
|
||||
|
||||
static int vmgexit_ap_control(u64 event, struct sev_es_save_area *vmsa, u32 apic_id)
|
||||
{
|
||||
bool create = event != SVM_VMGEXIT_AP_DESTROY;
|
||||
struct ghcb_state state;
|
||||
unsigned long flags;
|
||||
struct ghcb *ghcb;
|
||||
int ret = 0;
|
||||
|
||||
local_irq_save(flags);
|
||||
|
||||
ghcb = __sev_get_ghcb(&state);
|
||||
|
||||
vc_ghcb_invalidate(ghcb);
|
||||
|
||||
if (create)
|
||||
ghcb_set_rax(ghcb, vmsa->sev_features);
|
||||
|
||||
ghcb_set_sw_exit_code(ghcb, SVM_VMGEXIT_AP_CREATION);
|
||||
ghcb_set_sw_exit_info_1(ghcb,
|
||||
((u64)apic_id << 32) |
|
||||
((u64)snp_vmpl << 16) |
|
||||
event);
|
||||
ghcb_set_sw_exit_info_2(ghcb, __pa(vmsa));
|
||||
|
||||
sev_es_wr_ghcb_msr(__pa(ghcb));
|
||||
VMGEXIT();
|
||||
|
||||
if (!ghcb_sw_exit_info_1_is_valid(ghcb) ||
|
||||
lower_32_bits(ghcb->save.sw_exit_info_1)) {
|
||||
pr_err("SNP AP %s error\n", (create ? "CREATE" : "DESTROY"));
|
||||
ret = -EINVAL;
|
||||
}
|
||||
|
||||
__sev_put_ghcb(&state);
|
||||
|
||||
local_irq_restore(flags);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int snp_set_vmsa(void *va, void *caa, int apic_id, bool make_vmsa)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (snp_vmpl) {
|
||||
struct svsm_call call = {};
|
||||
unsigned long flags;
|
||||
|
||||
local_irq_save(flags);
|
||||
|
||||
call.caa = this_cpu_read(svsm_caa);
|
||||
call.rcx = __pa(va);
|
||||
|
||||
if (make_vmsa) {
|
||||
/* Protocol 0, Call ID 2 */
|
||||
call.rax = SVSM_CORE_CALL(SVSM_CORE_CREATE_VCPU);
|
||||
call.rdx = __pa(caa);
|
||||
call.r8 = apic_id;
|
||||
} else {
|
||||
/* Protocol 0, Call ID 3 */
|
||||
call.rax = SVSM_CORE_CALL(SVSM_CORE_DELETE_VCPU);
|
||||
}
|
||||
|
||||
ret = svsm_perform_call_protocol(&call);
|
||||
|
||||
local_irq_restore(flags);
|
||||
} else {
|
||||
/*
|
||||
* If the kernel runs at VMPL0, it can change the VMSA
|
||||
* bit for a page using the RMPADJUST instruction.
|
||||
* However, for the instruction to succeed it must
|
||||
* target the permissions of a lesser privileged (higher
|
||||
* numbered) VMPL level, so use VMPL1.
|
||||
*/
|
||||
u64 attrs = 1;
|
||||
|
||||
if (make_vmsa)
|
||||
attrs |= RMPADJUST_VMSA_PAGE_BIT;
|
||||
|
||||
ret = rmpadjust((unsigned long)va, RMP_PG_SIZE_4K, attrs);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void snp_cleanup_vmsa(struct sev_es_save_area *vmsa, int apic_id)
|
||||
{
|
||||
int err;
|
||||
|
||||
err = snp_set_vmsa(vmsa, NULL, apic_id, false);
|
||||
if (err)
|
||||
pr_err("clear VMSA page failed (%u), leaking page\n", err);
|
||||
else
|
||||
free_page((unsigned long)vmsa);
|
||||
}
|
||||
|
||||
static void set_pte_enc(pte_t *kpte, int level, void *va)
|
||||
{
|
||||
struct pte_enc_desc d = {
|
||||
@@ -593,7 +689,8 @@ static void unshare_all_memory(void)
|
||||
data = per_cpu(runtime_data, cpu);
|
||||
ghcb = (unsigned long)&data->ghcb_page;
|
||||
|
||||
if (addr <= ghcb && ghcb <= addr + size) {
|
||||
/* Handle the case of a huge page containing the GHCB page */
|
||||
if (addr <= ghcb && ghcb < addr + size) {
|
||||
skipped_addr = true;
|
||||
break;
|
||||
}
|
||||
@@ -643,11 +740,70 @@ void snp_kexec_begin(void)
|
||||
pr_warn("Failed to stop shared<->private conversions\n");
|
||||
}
|
||||
|
||||
/*
|
||||
* Shutdown all APs except the one handling kexec/kdump and clearing
|
||||
* the VMSA tag on AP's VMSA pages as they are not being used as
|
||||
* VMSA page anymore.
|
||||
*/
|
||||
static void shutdown_all_aps(void)
|
||||
{
|
||||
struct sev_es_save_area *vmsa;
|
||||
int apic_id, this_cpu, cpu;
|
||||
|
||||
this_cpu = get_cpu();
|
||||
|
||||
/*
|
||||
* APs are already in HLT loop when enc_kexec_finish() callback
|
||||
* is invoked.
|
||||
*/
|
||||
for_each_present_cpu(cpu) {
|
||||
vmsa = per_cpu(sev_vmsa, cpu);
|
||||
|
||||
/*
|
||||
* The BSP or offlined APs do not have guest allocated VMSA
|
||||
* and there is no need to clear the VMSA tag for this page.
|
||||
*/
|
||||
if (!vmsa)
|
||||
continue;
|
||||
|
||||
/*
|
||||
* Cannot clear the VMSA tag for the currently running vCPU.
|
||||
*/
|
||||
if (this_cpu == cpu) {
|
||||
unsigned long pa;
|
||||
struct page *p;
|
||||
|
||||
pa = __pa(vmsa);
|
||||
/*
|
||||
* Mark the VMSA page of the running vCPU as offline
|
||||
* so that is excluded and not touched by makedumpfile
|
||||
* while generating vmcore during kdump.
|
||||
*/
|
||||
p = pfn_to_online_page(pa >> PAGE_SHIFT);
|
||||
if (p)
|
||||
__SetPageOffline(p);
|
||||
continue;
|
||||
}
|
||||
|
||||
apic_id = cpuid_to_apicid[cpu];
|
||||
|
||||
/*
|
||||
* Issue AP destroy to ensure AP gets kicked out of guest mode
|
||||
* to allow using RMPADJUST to remove the VMSA tag on it's
|
||||
* VMSA page.
|
||||
*/
|
||||
vmgexit_ap_control(SVM_VMGEXIT_AP_DESTROY, vmsa, apic_id);
|
||||
snp_cleanup_vmsa(vmsa, apic_id);
|
||||
}
|
||||
|
||||
put_cpu();
|
||||
}
|
||||
|
||||
void snp_kexec_finish(void)
|
||||
{
|
||||
struct sev_es_runtime_data *data;
|
||||
unsigned long size, addr;
|
||||
unsigned int level, cpu;
|
||||
unsigned long size;
|
||||
struct ghcb *ghcb;
|
||||
pte_t *pte;
|
||||
|
||||
@@ -657,6 +813,8 @@ void snp_kexec_finish(void)
|
||||
if (!IS_ENABLED(CONFIG_KEXEC_CORE))
|
||||
return;
|
||||
|
||||
shutdown_all_aps();
|
||||
|
||||
unshare_all_memory();
|
||||
|
||||
/*
|
||||
@@ -673,56 +831,13 @@ void snp_kexec_finish(void)
|
||||
ghcb = &data->ghcb_page;
|
||||
pte = lookup_address((unsigned long)ghcb, &level);
|
||||
size = page_level_size(level);
|
||||
set_pte_enc(pte, level, (void *)ghcb);
|
||||
snp_set_memory_private((unsigned long)ghcb, (size / PAGE_SIZE));
|
||||
/* Handle the case of a huge page containing the GHCB page */
|
||||
addr = (unsigned long)ghcb & page_level_mask(level);
|
||||
set_pte_enc(pte, level, (void *)addr);
|
||||
snp_set_memory_private(addr, (size / PAGE_SIZE));
|
||||
}
|
||||
}
|
||||
|
||||
static int snp_set_vmsa(void *va, void *caa, int apic_id, bool make_vmsa)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (snp_vmpl) {
|
||||
struct svsm_call call = {};
|
||||
unsigned long flags;
|
||||
|
||||
local_irq_save(flags);
|
||||
|
||||
call.caa = this_cpu_read(svsm_caa);
|
||||
call.rcx = __pa(va);
|
||||
|
||||
if (make_vmsa) {
|
||||
/* Protocol 0, Call ID 2 */
|
||||
call.rax = SVSM_CORE_CALL(SVSM_CORE_CREATE_VCPU);
|
||||
call.rdx = __pa(caa);
|
||||
call.r8 = apic_id;
|
||||
} else {
|
||||
/* Protocol 0, Call ID 3 */
|
||||
call.rax = SVSM_CORE_CALL(SVSM_CORE_DELETE_VCPU);
|
||||
}
|
||||
|
||||
ret = svsm_perform_call_protocol(&call);
|
||||
|
||||
local_irq_restore(flags);
|
||||
} else {
|
||||
/*
|
||||
* If the kernel runs at VMPL0, it can change the VMSA
|
||||
* bit for a page using the RMPADJUST instruction.
|
||||
* However, for the instruction to succeed it must
|
||||
* target the permissions of a lesser privileged (higher
|
||||
* numbered) VMPL level, so use VMPL1.
|
||||
*/
|
||||
u64 attrs = 1;
|
||||
|
||||
if (make_vmsa)
|
||||
attrs |= RMPADJUST_VMSA_PAGE_BIT;
|
||||
|
||||
ret = rmpadjust((unsigned long)va, RMP_PG_SIZE_4K, attrs);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
#define __ATTR_BASE (SVM_SELECTOR_P_MASK | SVM_SELECTOR_S_MASK)
|
||||
#define INIT_CS_ATTRIBS (__ATTR_BASE | SVM_SELECTOR_READ_MASK | SVM_SELECTOR_CODE_MASK)
|
||||
#define INIT_DS_ATTRIBS (__ATTR_BASE | SVM_SELECTOR_WRITE_MASK)
|
||||
@@ -754,24 +869,10 @@ static void *snp_alloc_vmsa_page(int cpu)
|
||||
return page_address(p + 1);
|
||||
}
|
||||
|
||||
static void snp_cleanup_vmsa(struct sev_es_save_area *vmsa, int apic_id)
|
||||
{
|
||||
int err;
|
||||
|
||||
err = snp_set_vmsa(vmsa, NULL, apic_id, false);
|
||||
if (err)
|
||||
pr_err("clear VMSA page failed (%u), leaking page\n", err);
|
||||
else
|
||||
free_page((unsigned long)vmsa);
|
||||
}
|
||||
|
||||
static int wakeup_cpu_via_vmgexit(u32 apic_id, unsigned long start_ip)
|
||||
{
|
||||
struct sev_es_save_area *cur_vmsa, *vmsa;
|
||||
struct ghcb_state state;
|
||||
struct svsm_ca *caa;
|
||||
unsigned long flags;
|
||||
struct ghcb *ghcb;
|
||||
u8 sipi_vector;
|
||||
int cpu, ret;
|
||||
u64 cr4;
|
||||
@@ -885,33 +986,7 @@ static int wakeup_cpu_via_vmgexit(u32 apic_id, unsigned long start_ip)
|
||||
}
|
||||
|
||||
/* Issue VMGEXIT AP Creation NAE event */
|
||||
local_irq_save(flags);
|
||||
|
||||
ghcb = __sev_get_ghcb(&state);
|
||||
|
||||
vc_ghcb_invalidate(ghcb);
|
||||
ghcb_set_rax(ghcb, vmsa->sev_features);
|
||||
ghcb_set_sw_exit_code(ghcb, SVM_VMGEXIT_AP_CREATION);
|
||||
ghcb_set_sw_exit_info_1(ghcb,
|
||||
((u64)apic_id << 32) |
|
||||
((u64)snp_vmpl << 16) |
|
||||
SVM_VMGEXIT_AP_CREATE);
|
||||
ghcb_set_sw_exit_info_2(ghcb, __pa(vmsa));
|
||||
|
||||
sev_es_wr_ghcb_msr(__pa(ghcb));
|
||||
VMGEXIT();
|
||||
|
||||
if (!ghcb_sw_exit_info_1_is_valid(ghcb) ||
|
||||
lower_32_bits(ghcb->save.sw_exit_info_1)) {
|
||||
pr_err("SNP AP Creation error\n");
|
||||
ret = -EINVAL;
|
||||
}
|
||||
|
||||
__sev_put_ghcb(&state);
|
||||
|
||||
local_irq_restore(flags);
|
||||
|
||||
/* Perform cleanup if there was an error */
|
||||
ret = vmgexit_ap_control(SVM_VMGEXIT_AP_CREATE, vmsa, apic_id);
|
||||
if (ret) {
|
||||
snp_cleanup_vmsa(vmsa, apic_id);
|
||||
vmsa = NULL;
|
||||
|
||||
@@ -2466,8 +2466,9 @@ static void intel_pmu_drain_pebs_core(struct pt_regs *iregs, struct perf_sample_
|
||||
setup_pebs_fixed_sample_data);
|
||||
}
|
||||
|
||||
static void intel_pmu_pebs_event_update_no_drain(struct cpu_hw_events *cpuc, int size)
|
||||
static void intel_pmu_pebs_event_update_no_drain(struct cpu_hw_events *cpuc, u64 mask)
|
||||
{
|
||||
u64 pebs_enabled = cpuc->pebs_enabled & mask;
|
||||
struct perf_event *event;
|
||||
int bit;
|
||||
|
||||
@@ -2478,7 +2479,7 @@ static void intel_pmu_pebs_event_update_no_drain(struct cpu_hw_events *cpuc, int
|
||||
* It needs to call intel_pmu_save_and_restart_reload() to
|
||||
* update the event->count for this case.
|
||||
*/
|
||||
for_each_set_bit(bit, (unsigned long *)&cpuc->pebs_enabled, size) {
|
||||
for_each_set_bit(bit, (unsigned long *)&pebs_enabled, X86_PMC_IDX_MAX) {
|
||||
event = cpuc->events[bit];
|
||||
if (event->hw.flags & PERF_X86_EVENT_AUTO_RELOAD)
|
||||
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
|
||||
}
|
||||
|
||||
if (unlikely(base >= top)) {
|
||||
intel_pmu_pebs_event_update_no_drain(cpuc, size);
|
||||
intel_pmu_pebs_event_update_no_drain(cpuc, mask);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -2627,7 +2628,7 @@ static void intel_pmu_drain_pebs_icl(struct pt_regs *iregs, struct perf_sample_d
|
||||
(hybrid(cpuc->pmu, fixed_cntr_mask64) << INTEL_PMC_IDX_FIXED);
|
||||
|
||||
if (unlikely(base >= top)) {
|
||||
intel_pmu_pebs_event_update_no_drain(cpuc, X86_PMC_IDX_MAX);
|
||||
intel_pmu_pebs_event_update_no_drain(cpuc, mask);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -75,7 +75,7 @@
|
||||
#define X86_FEATURE_CENTAUR_MCR ( 3*32+ 3) /* "centaur_mcr" Centaur MCRs (= MTRRs) */
|
||||
#define X86_FEATURE_K8 ( 3*32+ 4) /* Opteron, Athlon64 */
|
||||
#define X86_FEATURE_ZEN5 ( 3*32+ 5) /* CPU based on Zen5 microarchitecture */
|
||||
/* Free ( 3*32+ 6) */
|
||||
#define X86_FEATURE_ZEN6 ( 3*32+ 6) /* CPU based on Zen6 microarchitecture */
|
||||
/* Free ( 3*32+ 7) */
|
||||
#define X86_FEATURE_CONSTANT_TSC ( 3*32+ 8) /* "constant_tsc" TSC ticks at a constant rate */
|
||||
#define X86_FEATURE_UP ( 3*32+ 9) /* "up" SMP kernel running on UP */
|
||||
|
||||
@@ -116,7 +116,7 @@ enum psc_op {
|
||||
#define GHCB_MSR_VMPL_REQ 0x016
|
||||
#define GHCB_MSR_VMPL_REQ_LEVEL(v) \
|
||||
/* GHCBData[39:32] */ \
|
||||
(((u64)(v) & GENMASK_ULL(7, 0) << 32) | \
|
||||
((((u64)(v) & GENMASK_ULL(7, 0)) << 32) | \
|
||||
/* GHCBDdata[11:0] */ \
|
||||
GHCB_MSR_VMPL_REQ)
|
||||
|
||||
|
||||
@@ -111,7 +111,9 @@ static bool cfi_paranoid __ro_after_init;
|
||||
|
||||
#ifdef CONFIG_MITIGATION_ITS
|
||||
|
||||
#ifdef CONFIG_MODULES
|
||||
static struct module *its_mod;
|
||||
#endif
|
||||
static void *its_page;
|
||||
static unsigned int its_offset;
|
||||
|
||||
@@ -149,6 +151,7 @@ static void *its_init_thunk(void *thunk, int reg)
|
||||
return thunk + offset;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_MODULES
|
||||
void its_init_mod(struct module *mod)
|
||||
{
|
||||
if (!cpu_feature_enabled(X86_FEATURE_INDIRECT_THUNK_ITS))
|
||||
@@ -187,6 +190,7 @@ void its_free_mod(struct module *mod)
|
||||
}
|
||||
kfree(mod->its_page_array);
|
||||
}
|
||||
#endif /* CONFIG_MODULES */
|
||||
|
||||
static void *its_alloc(void)
|
||||
{
|
||||
@@ -195,6 +199,7 @@ static void *its_alloc(void)
|
||||
if (!page)
|
||||
return NULL;
|
||||
|
||||
#ifdef CONFIG_MODULES
|
||||
if (its_mod) {
|
||||
void *tmp = krealloc(its_mod->its_page_array,
|
||||
(its_mod->its_num_pages+1) * sizeof(void *),
|
||||
@@ -207,6 +212,7 @@ static void *its_alloc(void)
|
||||
|
||||
execmem_make_temp_rw(page, PAGE_SIZE);
|
||||
}
|
||||
#endif /* CONFIG_MODULES */
|
||||
|
||||
return no_free_ptr(page);
|
||||
}
|
||||
|
||||
@@ -474,6 +474,11 @@ static void bsp_init_amd(struct cpuinfo_x86 *c)
|
||||
case 0x60 ... 0x7f:
|
||||
setup_force_cpu_cap(X86_FEATURE_ZEN5);
|
||||
break;
|
||||
case 0x50 ... 0x5f:
|
||||
case 0x90 ... 0xaf:
|
||||
case 0xc0 ... 0xcf:
|
||||
setup_force_cpu_cap(X86_FEATURE_ZEN6);
|
||||
break;
|
||||
default:
|
||||
goto warn;
|
||||
}
|
||||
|
||||
@@ -566,7 +566,7 @@ static void __init lowmem_pfn_init(void)
|
||||
"only %luMB highmem pages available, ignoring highmem size of %luMB!\n"
|
||||
|
||||
#define MSG_HIGHMEM_TRIMMED \
|
||||
"Warning: only 4GB will be used. Support for for CONFIG_HIGHMEM64G was removed!\n"
|
||||
"Warning: only 4GB will be used. Support for CONFIG_HIGHMEM64G was removed!\n"
|
||||
/*
|
||||
* We have more RAM than fits into lowmem - we try to put it into
|
||||
* highmem, also taking the highmem=x boot parameter into account:
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
* not aware of PI.
|
||||
*/
|
||||
#include <linux/blk-integrity.h>
|
||||
#include <linux/t10-pi.h>
|
||||
#include <linux/workqueue.h>
|
||||
#include "blk.h"
|
||||
|
||||
@@ -43,6 +44,29 @@ static void bio_integrity_verify_fn(struct work_struct *work)
|
||||
bio_endio(bio);
|
||||
}
|
||||
|
||||
#define BIP_CHECK_FLAGS (BIP_CHECK_GUARD | BIP_CHECK_REFTAG | BIP_CHECK_APPTAG)
|
||||
static bool bip_should_check(struct bio_integrity_payload *bip)
|
||||
{
|
||||
return bip->bip_flags & BIP_CHECK_FLAGS;
|
||||
}
|
||||
|
||||
static bool bi_offload_capable(struct blk_integrity *bi)
|
||||
{
|
||||
switch (bi->csum_type) {
|
||||
case BLK_INTEGRITY_CSUM_CRC64:
|
||||
return bi->tuple_size == sizeof(struct crc64_pi_tuple);
|
||||
case BLK_INTEGRITY_CSUM_CRC:
|
||||
case BLK_INTEGRITY_CSUM_IP:
|
||||
return bi->tuple_size == sizeof(struct t10_pi_tuple);
|
||||
default:
|
||||
pr_warn_once("%s: unknown integrity checksum type:%d\n",
|
||||
__func__, bi->csum_type);
|
||||
fallthrough;
|
||||
case BLK_INTEGRITY_CSUM_NONE:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* __bio_integrity_endio - Integrity I/O completion function
|
||||
* @bio: Protected bio
|
||||
@@ -54,12 +78,12 @@ static void bio_integrity_verify_fn(struct work_struct *work)
|
||||
*/
|
||||
bool __bio_integrity_endio(struct bio *bio)
|
||||
{
|
||||
struct blk_integrity *bi = blk_get_integrity(bio->bi_bdev->bd_disk);
|
||||
struct bio_integrity_payload *bip = bio_integrity(bio);
|
||||
struct bio_integrity_data *bid =
|
||||
container_of(bip, struct bio_integrity_data, bip);
|
||||
|
||||
if (bio_op(bio) == REQ_OP_READ && !bio->bi_status && bi->csum_type) {
|
||||
if (bio_op(bio) == REQ_OP_READ && !bio->bi_status &&
|
||||
bip_should_check(bip)) {
|
||||
INIT_WORK(&bid->work, bio_integrity_verify_fn);
|
||||
queue_work(kintegrityd_wq, &bid->work);
|
||||
return false;
|
||||
@@ -84,6 +108,7 @@ bool bio_integrity_prep(struct bio *bio)
|
||||
{
|
||||
struct blk_integrity *bi = blk_get_integrity(bio->bi_bdev->bd_disk);
|
||||
struct bio_integrity_data *bid;
|
||||
bool set_flags = true;
|
||||
gfp_t gfp = GFP_NOIO;
|
||||
unsigned int len;
|
||||
void *buf;
|
||||
@@ -100,19 +125,24 @@ bool bio_integrity_prep(struct bio *bio)
|
||||
|
||||
switch (bio_op(bio)) {
|
||||
case REQ_OP_READ:
|
||||
if (bi->flags & BLK_INTEGRITY_NOVERIFY)
|
||||
return true;
|
||||
if (bi->flags & BLK_INTEGRITY_NOVERIFY) {
|
||||
if (bi_offload_capable(bi))
|
||||
return true;
|
||||
set_flags = false;
|
||||
}
|
||||
break;
|
||||
case REQ_OP_WRITE:
|
||||
if (bi->flags & BLK_INTEGRITY_NOGENERATE)
|
||||
return true;
|
||||
|
||||
/*
|
||||
* Zero the memory allocated to not leak uninitialized kernel
|
||||
* memory to disk for non-integrity metadata where nothing else
|
||||
* initializes the memory.
|
||||
*/
|
||||
if (bi->csum_type == BLK_INTEGRITY_CSUM_NONE)
|
||||
if (bi->flags & BLK_INTEGRITY_NOGENERATE) {
|
||||
if (bi_offload_capable(bi))
|
||||
return true;
|
||||
set_flags = false;
|
||||
gfp |= __GFP_ZERO;
|
||||
} else if (bi->csum_type == BLK_INTEGRITY_CSUM_NONE)
|
||||
gfp |= __GFP_ZERO;
|
||||
break;
|
||||
default:
|
||||
@@ -137,19 +167,21 @@ bool bio_integrity_prep(struct bio *bio)
|
||||
bid->bip.bip_flags |= BIP_BLOCK_INTEGRITY;
|
||||
bip_set_seed(&bid->bip, bio->bi_iter.bi_sector);
|
||||
|
||||
if (bi->csum_type == BLK_INTEGRITY_CSUM_IP)
|
||||
bid->bip.bip_flags |= BIP_IP_CHECKSUM;
|
||||
if (bi->csum_type)
|
||||
bid->bip.bip_flags |= BIP_CHECK_GUARD;
|
||||
if (bi->flags & BLK_INTEGRITY_REF_TAG)
|
||||
bid->bip.bip_flags |= BIP_CHECK_REFTAG;
|
||||
if (set_flags) {
|
||||
if (bi->csum_type == BLK_INTEGRITY_CSUM_IP)
|
||||
bid->bip.bip_flags |= BIP_IP_CHECKSUM;
|
||||
if (bi->csum_type)
|
||||
bid->bip.bip_flags |= BIP_CHECK_GUARD;
|
||||
if (bi->flags & BLK_INTEGRITY_REF_TAG)
|
||||
bid->bip.bip_flags |= BIP_CHECK_REFTAG;
|
||||
}
|
||||
|
||||
if (bio_integrity_add_page(bio, virt_to_page(buf), len,
|
||||
offset_in_page(buf)) < len)
|
||||
goto err_end_io;
|
||||
|
||||
/* Auto-generate integrity metadata if this is a write */
|
||||
if (bio_data_dir(bio) == WRITE)
|
||||
if (bio_data_dir(bio) == WRITE && bip_should_check(&bid->bip))
|
||||
blk_integrity_generate(bio);
|
||||
else
|
||||
bid->saved_bio_iter = bio->bi_iter;
|
||||
|
||||
@@ -611,7 +611,7 @@ struct bio *bio_kmalloc(unsigned short nr_vecs, gfp_t gfp_mask)
|
||||
{
|
||||
struct bio *bio;
|
||||
|
||||
if (nr_vecs > UIO_MAXIOV)
|
||||
if (nr_vecs > BIO_MAX_INLINE_VECS)
|
||||
return NULL;
|
||||
return kmalloc(struct_size(bio, bi_inline_vecs, nr_vecs), gfp_mask);
|
||||
}
|
||||
|
||||
@@ -455,7 +455,7 @@ priority_bands_fops_write(struct file *file, const char __user *user_buf, size_t
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
buf[size] = '\0';
|
||||
buf[ret] = '\0';
|
||||
ret = sscanf(buf, "%u %u %u %u", &band, &grace_period, &process_grace_period,
|
||||
&process_quantum);
|
||||
if (ret != 4)
|
||||
|
||||
@@ -231,16 +231,18 @@ static int acpi_pptt_leaf_node(struct acpi_table_header *table_hdr,
|
||||
sizeof(struct acpi_table_pptt));
|
||||
proc_sz = sizeof(struct acpi_pptt_processor);
|
||||
|
||||
while ((unsigned long)entry + proc_sz < table_end) {
|
||||
/* ignore subtable types that are smaller than a processor node */
|
||||
while ((unsigned long)entry + proc_sz <= table_end) {
|
||||
cpu_node = (struct acpi_pptt_processor *)entry;
|
||||
|
||||
if (entry->type == ACPI_PPTT_TYPE_PROCESSOR &&
|
||||
cpu_node->parent == node_entry)
|
||||
return 0;
|
||||
if (entry->length == 0)
|
||||
return 0;
|
||||
|
||||
entry = ACPI_ADD_PTR(struct acpi_subtable_header, entry,
|
||||
entry->length);
|
||||
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
@@ -273,15 +275,18 @@ static struct acpi_pptt_processor *acpi_find_processor_node(struct acpi_table_he
|
||||
proc_sz = sizeof(struct acpi_pptt_processor);
|
||||
|
||||
/* find the processor structure associated with this cpuid */
|
||||
while ((unsigned long)entry + proc_sz < table_end) {
|
||||
while ((unsigned long)entry + proc_sz <= table_end) {
|
||||
cpu_node = (struct acpi_pptt_processor *)entry;
|
||||
|
||||
if (entry->length == 0) {
|
||||
pr_warn("Invalid zero length subtable\n");
|
||||
break;
|
||||
}
|
||||
/* entry->length may not equal proc_sz, revalidate the processor structure length */
|
||||
if (entry->type == ACPI_PPTT_TYPE_PROCESSOR &&
|
||||
acpi_cpu_id == cpu_node->acpi_processor_id &&
|
||||
(unsigned long)entry + entry->length <= table_end &&
|
||||
entry->length == proc_sz + cpu_node->number_of_priv_resources * sizeof(u32) &&
|
||||
acpi_pptt_leaf_node(table_hdr, cpu_node)) {
|
||||
return (struct acpi_pptt_processor *)entry;
|
||||
}
|
||||
|
||||
@@ -1708,7 +1708,7 @@ static void ublk_cancel_cmd(struct ublk_queue *ubq, unsigned tag,
|
||||
* that ublk_dispatch_req() is always called
|
||||
*/
|
||||
req = blk_mq_tag_to_rq(ub->tag_set.tags[ubq->q_id], tag);
|
||||
if (req && blk_mq_request_started(req))
|
||||
if (req && blk_mq_request_started(req) && req->tag == tag)
|
||||
return;
|
||||
|
||||
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
|
||||
*/
|
||||
u8 tpm_buf_read_u8(struct tpm_buf *buf, off_t *offset)
|
||||
{
|
||||
u8 value;
|
||||
u8 value = 0;
|
||||
|
||||
tpm_buf_read(buf, offset, sizeof(value), &value);
|
||||
|
||||
@@ -218,7 +218,7 @@ EXPORT_SYMBOL_GPL(tpm_buf_read_u8);
|
||||
*/
|
||||
u16 tpm_buf_read_u16(struct tpm_buf *buf, off_t *offset)
|
||||
{
|
||||
u16 value;
|
||||
u16 value = 0;
|
||||
|
||||
tpm_buf_read(buf, offset, sizeof(value), &value);
|
||||
|
||||
@@ -235,7 +235,7 @@ EXPORT_SYMBOL_GPL(tpm_buf_read_u16);
|
||||
*/
|
||||
u32 tpm_buf_read_u32(struct tpm_buf *buf, off_t *offset)
|
||||
{
|
||||
u32 value;
|
||||
u32 value = 0;
|
||||
|
||||
tpm_buf_read(buf, offset, sizeof(value), &value);
|
||||
|
||||
|
||||
@@ -40,11 +40,6 @@
|
||||
*
|
||||
* These are the usage functions:
|
||||
*
|
||||
* tpm2_start_auth_session() which allocates the opaque auth structure
|
||||
* and gets a session from the TPM. This must be called before
|
||||
* any of the following functions. The session is protected by a
|
||||
* session_key which is derived from a random salt value
|
||||
* encrypted to the NULL seed.
|
||||
* tpm2_end_auth_session() kills the session and frees the resources.
|
||||
* Under normal operation this function is done by
|
||||
* tpm_buf_check_hmac_response(), so this is only to be used on
|
||||
@@ -963,16 +958,13 @@ static int tpm2_load_null(struct tpm_chip *chip, u32 *null_key)
|
||||
}
|
||||
|
||||
/**
|
||||
* tpm2_start_auth_session() - create a HMAC authentication session with the TPM
|
||||
* @chip: the TPM chip structure to create the session with
|
||||
* tpm2_start_auth_session() - Create an a HMAC authentication session
|
||||
* @chip: A TPM chip
|
||||
*
|
||||
* This function loads the NULL seed from its saved context and starts
|
||||
* an authentication session on the null seed, fills in the
|
||||
* @chip->auth structure to contain all the session details necessary
|
||||
* for performing the HMAC, encrypt and decrypt operations and
|
||||
* returns. The NULL seed is flushed before this function returns.
|
||||
* Loads the ephemeral key (null seed), and starts an HMAC authenticated
|
||||
* session. The null seed is flushed before the return.
|
||||
*
|
||||
* Return: zero on success or actual error encountered.
|
||||
* Returns zero on success, or a POSIX error code.
|
||||
*/
|
||||
int tpm2_start_auth_session(struct tpm_chip *chip)
|
||||
{
|
||||
@@ -1024,7 +1016,7 @@ int tpm2_start_auth_session(struct tpm_chip *chip)
|
||||
/* hash algorithm for session */
|
||||
tpm_buf_append_u16(&buf, TPM_ALG_SHA256);
|
||||
|
||||
rc = tpm_transmit_cmd(chip, &buf, 0, "start auth session");
|
||||
rc = tpm_ret_to_err(tpm_transmit_cmd(chip, &buf, 0, "StartAuthSession"));
|
||||
tpm2_flush_context(chip, null_key);
|
||||
|
||||
if (rc == TPM2_RC_SUCCESS)
|
||||
|
||||
@@ -54,7 +54,7 @@ enum tis_int_flags {
|
||||
enum tis_defaults {
|
||||
TIS_MEM_LEN = 0x5000,
|
||||
TIS_SHORT_TIMEOUT = 750, /* ms */
|
||||
TIS_LONG_TIMEOUT = 2000, /* 2 sec */
|
||||
TIS_LONG_TIMEOUT = 4000, /* 4 secs */
|
||||
TIS_TIMEOUT_MIN_ATML = 14700, /* usecs */
|
||||
TIS_TIMEOUT_MAX_ATML = 15000, /* usecs */
|
||||
};
|
||||
|
||||
@@ -320,8 +320,9 @@ void dma_resv_add_fence(struct dma_resv *obj, struct dma_fence *fence,
|
||||
count++;
|
||||
|
||||
dma_resv_list_set(fobj, i, fence, usage);
|
||||
/* pointer update must be visible before we extend the num_fences */
|
||||
smp_store_mb(fobj->num_fences, count);
|
||||
/* fence update must be visible before we extend the num_fences */
|
||||
smp_wmb();
|
||||
fobj->num_fences = count;
|
||||
}
|
||||
EXPORT_SYMBOL(dma_resv_add_fence);
|
||||
|
||||
|
||||
@@ -342,6 +342,9 @@ static void pt_cmd_callback_work(void *data, int err)
|
||||
struct pt_dma_chan *chan;
|
||||
unsigned long flags;
|
||||
|
||||
if (!desc)
|
||||
return;
|
||||
|
||||
dma_chan = desc->vd.tx.chan;
|
||||
chan = to_pt_chan(dma_chan);
|
||||
|
||||
@@ -355,16 +358,14 @@ static void pt_cmd_callback_work(void *data, int err)
|
||||
desc->status = DMA_ERROR;
|
||||
|
||||
spin_lock_irqsave(&chan->vc.lock, flags);
|
||||
if (desc) {
|
||||
if (desc->status != DMA_COMPLETE) {
|
||||
if (desc->status != DMA_ERROR)
|
||||
desc->status = DMA_COMPLETE;
|
||||
if (desc->status != DMA_COMPLETE) {
|
||||
if (desc->status != DMA_ERROR)
|
||||
desc->status = DMA_COMPLETE;
|
||||
|
||||
dma_cookie_complete(tx_desc);
|
||||
dma_descriptor_unmap(tx_desc);
|
||||
} else {
|
||||
tx_desc = NULL;
|
||||
}
|
||||
dma_cookie_complete(tx_desc);
|
||||
dma_descriptor_unmap(tx_desc);
|
||||
} else {
|
||||
tx_desc = NULL;
|
||||
}
|
||||
spin_unlock_irqrestore(&chan->vc.lock, flags);
|
||||
|
||||
|
||||
@@ -841,9 +841,9 @@ static int dmatest_func(void *data)
|
||||
} else {
|
||||
dma_async_issue_pending(chan);
|
||||
|
||||
wait_event_timeout(thread->done_wait,
|
||||
done->done,
|
||||
msecs_to_jiffies(params->timeout));
|
||||
wait_event_freezable_timeout(thread->done_wait,
|
||||
done->done,
|
||||
msecs_to_jiffies(params->timeout));
|
||||
|
||||
status = dma_async_is_tx_complete(chan, cookie, NULL,
|
||||
NULL);
|
||||
|
||||
@@ -57,7 +57,7 @@ static irqreturn_t fsl_edma3_tx_handler(int irq, void *dev_id)
|
||||
|
||||
intr = edma_readl_chreg(fsl_chan, ch_int);
|
||||
if (!intr)
|
||||
return IRQ_HANDLED;
|
||||
return IRQ_NONE;
|
||||
|
||||
edma_writel_chreg(fsl_chan, 1, ch_int);
|
||||
|
||||
|
||||
@@ -222,7 +222,7 @@ static int idxd_cdev_open(struct inode *inode, struct file *filp)
|
||||
struct idxd_wq *wq;
|
||||
struct device *dev, *fdev;
|
||||
int rc = 0;
|
||||
struct iommu_sva *sva;
|
||||
struct iommu_sva *sva = NULL;
|
||||
unsigned int pasid;
|
||||
struct idxd_cdev *idxd_cdev;
|
||||
|
||||
@@ -317,7 +317,7 @@ static int idxd_cdev_open(struct inode *inode, struct file *filp)
|
||||
if (device_user_pasid_enabled(idxd))
|
||||
idxd_xa_pasid_remove(ctx);
|
||||
failed_get_pasid:
|
||||
if (device_user_pasid_enabled(idxd))
|
||||
if (device_user_pasid_enabled(idxd) && !IS_ERR_OR_NULL(sva))
|
||||
iommu_sva_unbind_device(sva);
|
||||
failed:
|
||||
mutex_unlock(&wq->wq_lock);
|
||||
@@ -407,6 +407,9 @@ static int idxd_cdev_mmap(struct file *filp, struct vm_area_struct *vma)
|
||||
if (!idxd->user_submission_safe && !capable(CAP_SYS_RAWIO))
|
||||
return -EPERM;
|
||||
|
||||
if (current->mm != ctx->mm)
|
||||
return -EPERM;
|
||||
|
||||
rc = check_vma(wq, vma, __func__);
|
||||
if (rc < 0)
|
||||
return rc;
|
||||
@@ -473,6 +476,9 @@ static ssize_t idxd_cdev_write(struct file *filp, const char __user *buf, size_t
|
||||
ssize_t written = 0;
|
||||
int i;
|
||||
|
||||
if (current->mm != ctx->mm)
|
||||
return -EPERM;
|
||||
|
||||
for (i = 0; i < len/sizeof(struct dsa_hw_desc); i++) {
|
||||
int rc = idxd_submit_user_descriptor(ctx, udesc + i);
|
||||
|
||||
@@ -493,6 +499,9 @@ static __poll_t idxd_cdev_poll(struct file *filp,
|
||||
struct idxd_device *idxd = wq->idxd;
|
||||
__poll_t out = 0;
|
||||
|
||||
if (current->mm != ctx->mm)
|
||||
return POLLNVAL;
|
||||
|
||||
poll_wait(filp, &wq->err_queue, wait);
|
||||
spin_lock(&idxd->dev_lock);
|
||||
if (idxd->sw_err.valid)
|
||||
|
||||
@@ -155,6 +155,25 @@ static void idxd_cleanup_interrupts(struct idxd_device *idxd)
|
||||
pci_free_irq_vectors(pdev);
|
||||
}
|
||||
|
||||
static void idxd_clean_wqs(struct idxd_device *idxd)
|
||||
{
|
||||
struct idxd_wq *wq;
|
||||
struct device *conf_dev;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < idxd->max_wqs; i++) {
|
||||
wq = idxd->wqs[i];
|
||||
if (idxd->hw.wq_cap.op_config)
|
||||
bitmap_free(wq->opcap_bmap);
|
||||
kfree(wq->wqcfg);
|
||||
conf_dev = wq_confdev(wq);
|
||||
put_device(conf_dev);
|
||||
kfree(wq);
|
||||
}
|
||||
bitmap_free(idxd->wq_enable_map);
|
||||
kfree(idxd->wqs);
|
||||
}
|
||||
|
||||
static int idxd_setup_wqs(struct idxd_device *idxd)
|
||||
{
|
||||
struct device *dev = &idxd->pdev->dev;
|
||||
@@ -169,8 +188,8 @@ static int idxd_setup_wqs(struct idxd_device *idxd)
|
||||
|
||||
idxd->wq_enable_map = bitmap_zalloc_node(idxd->max_wqs, GFP_KERNEL, dev_to_node(dev));
|
||||
if (!idxd->wq_enable_map) {
|
||||
kfree(idxd->wqs);
|
||||
return -ENOMEM;
|
||||
rc = -ENOMEM;
|
||||
goto err_bitmap;
|
||||
}
|
||||
|
||||
for (i = 0; i < idxd->max_wqs; i++) {
|
||||
@@ -189,10 +208,8 @@ static int idxd_setup_wqs(struct idxd_device *idxd)
|
||||
conf_dev->bus = &dsa_bus_type;
|
||||
conf_dev->type = &idxd_wq_device_type;
|
||||
rc = dev_set_name(conf_dev, "wq%d.%d", idxd->id, wq->id);
|
||||
if (rc < 0) {
|
||||
put_device(conf_dev);
|
||||
if (rc < 0)
|
||||
goto err;
|
||||
}
|
||||
|
||||
mutex_init(&wq->wq_lock);
|
||||
init_waitqueue_head(&wq->err_queue);
|
||||
@@ -203,7 +220,6 @@ static int idxd_setup_wqs(struct idxd_device *idxd)
|
||||
wq->enqcmds_retries = IDXD_ENQCMDS_RETRIES;
|
||||
wq->wqcfg = kzalloc_node(idxd->wqcfg_size, GFP_KERNEL, dev_to_node(dev));
|
||||
if (!wq->wqcfg) {
|
||||
put_device(conf_dev);
|
||||
rc = -ENOMEM;
|
||||
goto err;
|
||||
}
|
||||
@@ -211,9 +227,8 @@ static int idxd_setup_wqs(struct idxd_device *idxd)
|
||||
if (idxd->hw.wq_cap.op_config) {
|
||||
wq->opcap_bmap = bitmap_zalloc(IDXD_MAX_OPCAP_BITS, GFP_KERNEL);
|
||||
if (!wq->opcap_bmap) {
|
||||
put_device(conf_dev);
|
||||
rc = -ENOMEM;
|
||||
goto err;
|
||||
goto err_opcap_bmap;
|
||||
}
|
||||
bitmap_copy(wq->opcap_bmap, idxd->opcap_bmap, IDXD_MAX_OPCAP_BITS);
|
||||
}
|
||||
@@ -224,15 +239,46 @@ static int idxd_setup_wqs(struct idxd_device *idxd)
|
||||
|
||||
return 0;
|
||||
|
||||
err:
|
||||
err_opcap_bmap:
|
||||
kfree(wq->wqcfg);
|
||||
|
||||
err:
|
||||
put_device(conf_dev);
|
||||
kfree(wq);
|
||||
|
||||
while (--i >= 0) {
|
||||
wq = idxd->wqs[i];
|
||||
if (idxd->hw.wq_cap.op_config)
|
||||
bitmap_free(wq->opcap_bmap);
|
||||
kfree(wq->wqcfg);
|
||||
conf_dev = wq_confdev(wq);
|
||||
put_device(conf_dev);
|
||||
kfree(wq);
|
||||
|
||||
}
|
||||
bitmap_free(idxd->wq_enable_map);
|
||||
|
||||
err_bitmap:
|
||||
kfree(idxd->wqs);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static void idxd_clean_engines(struct idxd_device *idxd)
|
||||
{
|
||||
struct idxd_engine *engine;
|
||||
struct device *conf_dev;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < idxd->max_engines; i++) {
|
||||
engine = idxd->engines[i];
|
||||
conf_dev = engine_confdev(engine);
|
||||
put_device(conf_dev);
|
||||
kfree(engine);
|
||||
}
|
||||
kfree(idxd->engines);
|
||||
}
|
||||
|
||||
static int idxd_setup_engines(struct idxd_device *idxd)
|
||||
{
|
||||
struct idxd_engine *engine;
|
||||
@@ -263,6 +309,7 @@ static int idxd_setup_engines(struct idxd_device *idxd)
|
||||
rc = dev_set_name(conf_dev, "engine%d.%d", idxd->id, engine->id);
|
||||
if (rc < 0) {
|
||||
put_device(conf_dev);
|
||||
kfree(engine);
|
||||
goto err;
|
||||
}
|
||||
|
||||
@@ -276,10 +323,26 @@ static int idxd_setup_engines(struct idxd_device *idxd)
|
||||
engine = idxd->engines[i];
|
||||
conf_dev = engine_confdev(engine);
|
||||
put_device(conf_dev);
|
||||
kfree(engine);
|
||||
}
|
||||
kfree(idxd->engines);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static void idxd_clean_groups(struct idxd_device *idxd)
|
||||
{
|
||||
struct idxd_group *group;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < idxd->max_groups; i++) {
|
||||
group = idxd->groups[i];
|
||||
put_device(group_confdev(group));
|
||||
kfree(group);
|
||||
}
|
||||
kfree(idxd->groups);
|
||||
}
|
||||
|
||||
static int idxd_setup_groups(struct idxd_device *idxd)
|
||||
{
|
||||
struct device *dev = &idxd->pdev->dev;
|
||||
@@ -310,6 +373,7 @@ static int idxd_setup_groups(struct idxd_device *idxd)
|
||||
rc = dev_set_name(conf_dev, "group%d.%d", idxd->id, group->id);
|
||||
if (rc < 0) {
|
||||
put_device(conf_dev);
|
||||
kfree(group);
|
||||
goto err;
|
||||
}
|
||||
|
||||
@@ -334,20 +398,18 @@ static int idxd_setup_groups(struct idxd_device *idxd)
|
||||
while (--i >= 0) {
|
||||
group = idxd->groups[i];
|
||||
put_device(group_confdev(group));
|
||||
kfree(group);
|
||||
}
|
||||
kfree(idxd->groups);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static void idxd_cleanup_internals(struct idxd_device *idxd)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < idxd->max_groups; i++)
|
||||
put_device(group_confdev(idxd->groups[i]));
|
||||
for (i = 0; i < idxd->max_engines; i++)
|
||||
put_device(engine_confdev(idxd->engines[i]));
|
||||
for (i = 0; i < idxd->max_wqs; i++)
|
||||
put_device(wq_confdev(idxd->wqs[i]));
|
||||
idxd_clean_groups(idxd);
|
||||
idxd_clean_engines(idxd);
|
||||
idxd_clean_wqs(idxd);
|
||||
destroy_workqueue(idxd->wq);
|
||||
}
|
||||
|
||||
@@ -390,7 +452,7 @@ static int idxd_init_evl(struct idxd_device *idxd)
|
||||
static int idxd_setup_internals(struct idxd_device *idxd)
|
||||
{
|
||||
struct device *dev = &idxd->pdev->dev;
|
||||
int rc, i;
|
||||
int rc;
|
||||
|
||||
init_waitqueue_head(&idxd->cmd_waitq);
|
||||
|
||||
@@ -421,14 +483,11 @@ static int idxd_setup_internals(struct idxd_device *idxd)
|
||||
err_evl:
|
||||
destroy_workqueue(idxd->wq);
|
||||
err_wkq_create:
|
||||
for (i = 0; i < idxd->max_groups; i++)
|
||||
put_device(group_confdev(idxd->groups[i]));
|
||||
idxd_clean_groups(idxd);
|
||||
err_group:
|
||||
for (i = 0; i < idxd->max_engines; i++)
|
||||
put_device(engine_confdev(idxd->engines[i]));
|
||||
idxd_clean_engines(idxd);
|
||||
err_engine:
|
||||
for (i = 0; i < idxd->max_wqs; i++)
|
||||
put_device(wq_confdev(idxd->wqs[i]));
|
||||
idxd_clean_wqs(idxd);
|
||||
err_wqs:
|
||||
return rc;
|
||||
}
|
||||
@@ -528,6 +587,17 @@ static void idxd_read_caps(struct idxd_device *idxd)
|
||||
idxd->hw.iaa_cap.bits = ioread64(idxd->reg_base + IDXD_IAACAP_OFFSET);
|
||||
}
|
||||
|
||||
static void idxd_free(struct idxd_device *idxd)
|
||||
{
|
||||
if (!idxd)
|
||||
return;
|
||||
|
||||
put_device(idxd_confdev(idxd));
|
||||
bitmap_free(idxd->opcap_bmap);
|
||||
ida_free(&idxd_ida, idxd->id);
|
||||
kfree(idxd);
|
||||
}
|
||||
|
||||
static struct idxd_device *idxd_alloc(struct pci_dev *pdev, struct idxd_driver_data *data)
|
||||
{
|
||||
struct device *dev = &pdev->dev;
|
||||
@@ -545,28 +615,34 @@ static struct idxd_device *idxd_alloc(struct pci_dev *pdev, struct idxd_driver_d
|
||||
idxd_dev_set_type(&idxd->idxd_dev, idxd->data->type);
|
||||
idxd->id = ida_alloc(&idxd_ida, GFP_KERNEL);
|
||||
if (idxd->id < 0)
|
||||
return NULL;
|
||||
goto err_ida;
|
||||
|
||||
idxd->opcap_bmap = bitmap_zalloc_node(IDXD_MAX_OPCAP_BITS, GFP_KERNEL, dev_to_node(dev));
|
||||
if (!idxd->opcap_bmap) {
|
||||
ida_free(&idxd_ida, idxd->id);
|
||||
return NULL;
|
||||
}
|
||||
if (!idxd->opcap_bmap)
|
||||
goto err_opcap;
|
||||
|
||||
device_initialize(conf_dev);
|
||||
conf_dev->parent = dev;
|
||||
conf_dev->bus = &dsa_bus_type;
|
||||
conf_dev->type = idxd->data->dev_type;
|
||||
rc = dev_set_name(conf_dev, "%s%d", idxd->data->name_prefix, idxd->id);
|
||||
if (rc < 0) {
|
||||
put_device(conf_dev);
|
||||
return NULL;
|
||||
}
|
||||
if (rc < 0)
|
||||
goto err_name;
|
||||
|
||||
spin_lock_init(&idxd->dev_lock);
|
||||
spin_lock_init(&idxd->cmd_lock);
|
||||
|
||||
return idxd;
|
||||
|
||||
err_name:
|
||||
put_device(conf_dev);
|
||||
bitmap_free(idxd->opcap_bmap);
|
||||
err_opcap:
|
||||
ida_free(&idxd_ida, idxd->id);
|
||||
err_ida:
|
||||
kfree(idxd);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
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,
|
||||
err:
|
||||
pci_iounmap(pdev, idxd->reg_base);
|
||||
err_iomap:
|
||||
put_device(idxd_confdev(idxd));
|
||||
idxd_free(idxd);
|
||||
err_idxd_alloc:
|
||||
pci_disable_device(pdev);
|
||||
return rc;
|
||||
@@ -1232,7 +1308,6 @@ static void idxd_shutdown(struct pci_dev *pdev)
|
||||
static void idxd_remove(struct pci_dev *pdev)
|
||||
{
|
||||
struct idxd_device *idxd = pci_get_drvdata(pdev);
|
||||
struct idxd_irq_entry *irq_entry;
|
||||
|
||||
idxd_unregister_devices(idxd);
|
||||
/*
|
||||
@@ -1245,20 +1320,12 @@ static void idxd_remove(struct pci_dev *pdev)
|
||||
get_device(idxd_confdev(idxd));
|
||||
device_unregister(idxd_confdev(idxd));
|
||||
idxd_shutdown(pdev);
|
||||
if (device_pasid_enabled(idxd))
|
||||
idxd_disable_system_pasid(idxd);
|
||||
idxd_device_remove_debugfs(idxd);
|
||||
|
||||
irq_entry = idxd_get_ie(idxd, 0);
|
||||
free_irq(irq_entry->vector, irq_entry);
|
||||
pci_free_irq_vectors(pdev);
|
||||
idxd_cleanup(idxd);
|
||||
pci_iounmap(pdev, idxd->reg_base);
|
||||
if (device_user_pasid_enabled(idxd))
|
||||
idxd_disable_sva(pdev);
|
||||
pci_disable_device(pdev);
|
||||
destroy_workqueue(idxd->wq);
|
||||
perfmon_pmu_remove(idxd);
|
||||
put_device(idxd_confdev(idxd));
|
||||
idxd_free(idxd);
|
||||
pci_disable_device(pdev);
|
||||
}
|
||||
|
||||
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,
|
||||
{
|
||||
struct mtk_cqdma_vchan *cvc = to_cqdma_vchan(c);
|
||||
struct virt_dma_desc *vd;
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&cvc->pc->lock, flags);
|
||||
list_for_each_entry(vd, &cvc->pc->queue, node)
|
||||
if (vd->tx.cookie == cookie) {
|
||||
spin_unlock_irqrestore(&cvc->pc->lock, flags);
|
||||
return vd;
|
||||
}
|
||||
spin_unlock_irqrestore(&cvc->pc->lock, flags);
|
||||
|
||||
list_for_each_entry(vd, &cvc->vc.desc_issued, node)
|
||||
if (vd->tx.cookie == cookie)
|
||||
@@ -452,9 +448,11 @@ static enum dma_status mtk_cqdma_tx_status(struct dma_chan *c,
|
||||
if (ret == DMA_COMPLETE || !txstate)
|
||||
return ret;
|
||||
|
||||
spin_lock_irqsave(&cvc->pc->lock, flags);
|
||||
spin_lock_irqsave(&cvc->vc.lock, flags);
|
||||
vd = mtk_cqdma_find_active_desc(c, cookie);
|
||||
spin_unlock_irqrestore(&cvc->vc.lock, flags);
|
||||
spin_unlock_irqrestore(&cvc->pc->lock, flags);
|
||||
|
||||
if (vd) {
|
||||
cvd = to_cqdma_vdesc(vd);
|
||||
|
||||
@@ -1091,8 +1091,11 @@ static void udma_check_tx_completion(struct work_struct *work)
|
||||
u32 residue_diff;
|
||||
ktime_t time_diff;
|
||||
unsigned long delay;
|
||||
unsigned long flags;
|
||||
|
||||
while (1) {
|
||||
spin_lock_irqsave(&uc->vc.lock, flags);
|
||||
|
||||
if (uc->desc) {
|
||||
/* Get previous residue and time stamp */
|
||||
residue_diff = uc->tx_drain.residue;
|
||||
@@ -1127,6 +1130,8 @@ static void udma_check_tx_completion(struct work_struct *work)
|
||||
break;
|
||||
}
|
||||
|
||||
spin_unlock_irqrestore(&uc->vc.lock, flags);
|
||||
|
||||
usleep_range(ktime_to_us(delay),
|
||||
ktime_to_us(delay) + 10);
|
||||
continue;
|
||||
@@ -1143,6 +1148,8 @@ static void udma_check_tx_completion(struct work_struct *work)
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
spin_unlock_irqrestore(&uc->vc.lock, flags);
|
||||
}
|
||||
|
||||
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,
|
||||
struct of_dma *ofdma)
|
||||
{
|
||||
struct udma_dev *ud = ofdma->of_dma_data;
|
||||
dma_cap_mask_t mask = ud->ddev.cap_mask;
|
||||
struct udma_filter_param filter_param;
|
||||
struct dma_chan *chan;
|
||||
|
||||
@@ -4278,7 +4284,7 @@ static struct dma_chan *udma_of_xlate(struct of_phandle_args *dma_spec,
|
||||
}
|
||||
}
|
||||
|
||||
chan = __dma_request_channel(&mask, udma_dma_filter_fn, &filter_param,
|
||||
chan = __dma_request_channel(&ud->ddev.cap_mask, udma_dma_filter_fn, &filter_param,
|
||||
ofdma->of_node);
|
||||
if (!chan) {
|
||||
dev_err(ud->dev, "get channel fail in %s.\n", __func__);
|
||||
|
||||
@@ -1204,6 +1204,8 @@ static int pca953x_restore_context(struct pca953x_chip *chip)
|
||||
|
||||
guard(mutex)(&chip->i2c_lock);
|
||||
|
||||
if (chip->client->irq > 0)
|
||||
enable_irq(chip->client->irq);
|
||||
regcache_cache_only(chip->regmap, false);
|
||||
regcache_mark_dirty(chip->regmap);
|
||||
ret = pca953x_regcache_sync(chip);
|
||||
@@ -1216,6 +1218,10 @@ static int pca953x_restore_context(struct pca953x_chip *chip)
|
||||
static void pca953x_save_context(struct pca953x_chip *chip)
|
||||
{
|
||||
guard(mutex)(&chip->i2c_lock);
|
||||
|
||||
/* Disable IRQ to prevent early triggering while regmap "cache only" is on */
|
||||
if (chip->client->irq > 0)
|
||||
disable_irq(chip->client->irq);
|
||||
regcache_cache_only(chip->regmap, true);
|
||||
}
|
||||
|
||||
|
||||
@@ -401,10 +401,15 @@ static ssize_t gpio_virtuser_direction_do_write(struct file *file,
|
||||
char buf[32], *trimmed;
|
||||
int ret, dir, val = 0;
|
||||
|
||||
ret = simple_write_to_buffer(buf, sizeof(buf), ppos, user_buf, count);
|
||||
if (count >= sizeof(buf))
|
||||
return -EINVAL;
|
||||
|
||||
ret = simple_write_to_buffer(buf, sizeof(buf) - 1, ppos, user_buf, count);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
buf[ret] = '\0';
|
||||
|
||||
trimmed = strim(buf);
|
||||
|
||||
if (strcmp(trimmed, "input") == 0) {
|
||||
@@ -623,12 +628,15 @@ static ssize_t gpio_virtuser_consumer_write(struct file *file,
|
||||
char buf[GPIO_VIRTUSER_NAME_BUF_LEN + 2];
|
||||
int ret;
|
||||
|
||||
if (count >= sizeof(buf))
|
||||
return -EINVAL;
|
||||
|
||||
ret = simple_write_to_buffer(buf, GPIO_VIRTUSER_NAME_BUF_LEN, ppos,
|
||||
user_buf, count);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
buf[strlen(buf) - 1] = '\0';
|
||||
buf[ret] = '\0';
|
||||
|
||||
ret = gpiod_set_consumer_name(data->ad.desc, buf);
|
||||
if (ret)
|
||||
|
||||
@@ -109,7 +109,7 @@ int amdgpu_unmap_static_csa(struct amdgpu_device *adev, struct amdgpu_vm *vm,
|
||||
struct drm_exec exec;
|
||||
int r;
|
||||
|
||||
drm_exec_init(&exec, DRM_EXEC_INTERRUPTIBLE_WAIT, 0);
|
||||
drm_exec_init(&exec, 0, 0);
|
||||
drm_exec_until_all_locked(&exec) {
|
||||
r = amdgpu_vm_lock_pd(vm, &exec, 0);
|
||||
if (likely(!r))
|
||||
|
||||
@@ -752,6 +752,18 @@ static int gmc_v11_0_sw_init(struct amdgpu_ip_block *ip_block)
|
||||
adev->gmc.vram_type = vram_type;
|
||||
adev->gmc.vram_vendor = vram_vendor;
|
||||
|
||||
/* The mall_size is already calculated as mall_size_per_umc * num_umc.
|
||||
* However, for gfx1151, which features a 2-to-1 UMC mapping,
|
||||
* the result must be multiplied by 2 to determine the actual mall size.
|
||||
*/
|
||||
switch (amdgpu_ip_version(adev, GC_HWIP, 0)) {
|
||||
case IP_VERSION(11, 5, 1):
|
||||
adev->gmc.mall_size *= 2;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
switch (amdgpu_ip_version(adev, GC_HWIP, 0)) {
|
||||
case IP_VERSION(11, 0, 0):
|
||||
case IP_VERSION(11, 0, 1):
|
||||
|
||||
@@ -1023,6 +1023,10 @@ static int vcn_v4_0_5_start_dpg_mode(struct amdgpu_vcn_inst *vinst,
|
||||
ring->doorbell_index << VCN_RB1_DB_CTRL__OFFSET__SHIFT |
|
||||
VCN_RB1_DB_CTRL__EN_MASK);
|
||||
|
||||
/* Keeping one read-back to ensure all register writes are done, otherwise
|
||||
* it may introduce race conditions */
|
||||
RREG32_SOC15(VCN, inst_idx, regVCN_RB1_DB_CTRL);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1205,6 +1209,10 @@ static int vcn_v4_0_5_start(struct amdgpu_vcn_inst *vinst)
|
||||
WREG32_SOC15(VCN, i, regVCN_RB_ENABLE, tmp);
|
||||
fw_shared->sq.queue_mode &= ~(FW_QUEUE_RING_RESET | FW_QUEUE_DPG_HOLD_OFF);
|
||||
|
||||
/* Keeping one read-back to ensure all register writes are done, otherwise
|
||||
* it may introduce race conditions */
|
||||
RREG32_SOC15(VCN, i, regVCN_RB_ENABLE);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -372,6 +372,8 @@ get_crtc_by_otg_inst(struct amdgpu_device *adev,
|
||||
static inline bool is_dc_timing_adjust_needed(struct dm_crtc_state *old_state,
|
||||
struct dm_crtc_state *new_state)
|
||||
{
|
||||
if (new_state->stream->adjust.timing_adjust_pending)
|
||||
return true;
|
||||
if (new_state->freesync_config.state == VRR_STATE_ACTIVE_FIXED)
|
||||
return true;
|
||||
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(
|
||||
/* The reply is stored in the top nibble of the command. */
|
||||
payload->reply[0] = (adev->dm.dmub_notify->aux_reply.command >> 4) & 0xF;
|
||||
|
||||
if (!payload->write && p_notify->aux_reply.length)
|
||||
/*write req may receive a byte indicating partially written number as well*/
|
||||
if (p_notify->aux_reply.length)
|
||||
memcpy(payload->data, p_notify->aux_reply.data,
|
||||
p_notify->aux_reply.length);
|
||||
|
||||
|
||||
@@ -62,6 +62,7 @@ static ssize_t dm_dp_aux_transfer(struct drm_dp_aux *aux,
|
||||
enum aux_return_code_type operation_result;
|
||||
struct amdgpu_device *adev;
|
||||
struct ddc_service *ddc;
|
||||
uint8_t copy[16];
|
||||
|
||||
if (WARN_ON(msg->size > 16))
|
||||
return -E2BIG;
|
||||
@@ -77,6 +78,11 @@ static ssize_t dm_dp_aux_transfer(struct drm_dp_aux *aux,
|
||||
(msg->request & DP_AUX_I2C_WRITE_STATUS_UPDATE) != 0;
|
||||
payload.defer_delay = 0;
|
||||
|
||||
if (payload.write) {
|
||||
memcpy(copy, msg->buffer, msg->size);
|
||||
payload.data = copy;
|
||||
}
|
||||
|
||||
result = dc_link_aux_transfer_raw(TO_DM_AUX(aux)->ddc_service, &payload,
|
||||
&operation_result);
|
||||
|
||||
@@ -100,9 +106,9 @@ static ssize_t dm_dp_aux_transfer(struct drm_dp_aux *aux,
|
||||
*/
|
||||
if (payload.write && result >= 0) {
|
||||
if (result) {
|
||||
/*one byte indicating partially written bytes. Force 0 to retry*/
|
||||
drm_info(adev_to_drm(adev), "amdgpu: AUX partially written\n");
|
||||
result = 0;
|
||||
/*one byte indicating partially written bytes*/
|
||||
drm_dbg_dp(adev_to_drm(adev), "amdgpu: AUX partially written\n");
|
||||
result = payload.data[0];
|
||||
} else if (!payload.reply[0])
|
||||
/*I2C_ACK|AUX_ACK*/
|
||||
result = msg->size;
|
||||
@@ -127,11 +133,11 @@ static ssize_t dm_dp_aux_transfer(struct drm_dp_aux *aux,
|
||||
break;
|
||||
}
|
||||
|
||||
drm_info(adev_to_drm(adev), "amdgpu: DP AUX transfer fail:%d\n", operation_result);
|
||||
drm_dbg_dp(adev_to_drm(adev), "amdgpu: DP AUX transfer fail:%d\n", operation_result);
|
||||
}
|
||||
|
||||
if (payload.reply[0])
|
||||
drm_info(adev_to_drm(adev), "amdgpu: AUX reply command not ACK: 0x%02x.",
|
||||
drm_dbg_dp(adev_to_drm(adev), "amdgpu: AUX reply command not ACK: 0x%02x.",
|
||||
payload.reply[0]);
|
||||
|
||||
return result;
|
||||
|
||||
@@ -439,9 +439,12 @@ bool dc_stream_adjust_vmin_vmax(struct dc *dc,
|
||||
* Don't adjust DRR while there's bandwidth optimizations pending to
|
||||
* avoid conflicting with firmware updates.
|
||||
*/
|
||||
if (dc->ctx->dce_version > DCE_VERSION_MAX)
|
||||
if (dc->optimized_required || dc->wm_optimized_required)
|
||||
if (dc->ctx->dce_version > DCE_VERSION_MAX) {
|
||||
if (dc->optimized_required || dc->wm_optimized_required) {
|
||||
stream->adjust.timing_adjust_pending = true;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
dc_exit_ips_for_hw_access(dc);
|
||||
|
||||
@@ -3168,7 +3171,8 @@ static void copy_stream_update_to_stream(struct dc *dc,
|
||||
|
||||
if (update->crtc_timing_adjust) {
|
||||
if (stream->adjust.v_total_min != update->crtc_timing_adjust->v_total_min ||
|
||||
stream->adjust.v_total_max != update->crtc_timing_adjust->v_total_max)
|
||||
stream->adjust.v_total_max != update->crtc_timing_adjust->v_total_max ||
|
||||
stream->adjust.timing_adjust_pending)
|
||||
update->crtc_timing_adjust->timing_adjust_pending = true;
|
||||
stream->adjust = *update->crtc_timing_adjust;
|
||||
update->crtc_timing_adjust->timing_adjust_pending = false;
|
||||
|
||||
@@ -195,9 +195,9 @@ struct _vcs_dpi_soc_bounding_box_st dcn3_5_soc = {
|
||||
.dcn_downspread_percent = 0.5,
|
||||
.gpuvm_min_page_size_bytes = 4096,
|
||||
.hostvm_min_page_size_bytes = 4096,
|
||||
.do_urgent_latency_adjustment = 1,
|
||||
.do_urgent_latency_adjustment = 0,
|
||||
.urgent_latency_adjustment_fabric_clock_component_us = 0,
|
||||
.urgent_latency_adjustment_fabric_clock_reference_mhz = 3000,
|
||||
.urgent_latency_adjustment_fabric_clock_reference_mhz = 0,
|
||||
};
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
//TODO : Could be possibly moved to a common helper layer.
|
||||
static bool dml21_wrapper_get_plane_id(const struct dc_state *context, const struct dc_plane_state *plane, unsigned int *plane_id)
|
||||
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)
|
||||
{
|
||||
int i, j;
|
||||
|
||||
@@ -918,10 +918,12 @@ static bool dml21_wrapper_get_plane_id(const struct dc_state *context, const str
|
||||
return false;
|
||||
|
||||
for (i = 0; i < context->stream_count; i++) {
|
||||
for (j = 0; j < context->stream_status[i].plane_count; j++) {
|
||||
if (context->stream_status[i].plane_states[j] == plane) {
|
||||
*plane_id = (i << 16) | j;
|
||||
return true;
|
||||
if (context->streams[i]->stream_id == stream_id) {
|
||||
for (j = 0; j < context->stream_status[i].plane_count; j++) {
|
||||
if (context->stream_status[i].plane_states[j] == plane) {
|
||||
*plane_id = (i << 16) | j;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -944,14 +946,14 @@ static unsigned int map_stream_to_dml21_display_cfg(const struct dml2_context *d
|
||||
return location;
|
||||
}
|
||||
|
||||
static unsigned int map_plane_to_dml21_display_cfg(const struct dml2_context *dml_ctx,
|
||||
static unsigned int map_plane_to_dml21_display_cfg(const struct dml2_context *dml_ctx, unsigned int stream_id,
|
||||
const struct dc_plane_state *plane, const struct dc_state *context)
|
||||
{
|
||||
unsigned int plane_id;
|
||||
int i = 0;
|
||||
int location = -1;
|
||||
|
||||
if (!dml21_wrapper_get_plane_id(context, plane, &plane_id)) {
|
||||
if (!dml21_wrapper_get_plane_id(context, stream_id, plane, &plane_id)) {
|
||||
ASSERT(false);
|
||||
return -1;
|
||||
}
|
||||
@@ -1037,7 +1039,7 @@ bool dml21_map_dc_state_into_dml_display_cfg(const struct dc *in_dc, struct dc_s
|
||||
dml_dispcfg->plane_descriptors[disp_cfg_plane_location].stream_index = disp_cfg_stream_location;
|
||||
} else {
|
||||
for (plane_index = 0; plane_index < context->stream_status[stream_index].plane_count; plane_index++) {
|
||||
disp_cfg_plane_location = map_plane_to_dml21_display_cfg(dml_ctx, context->stream_status[stream_index].plane_states[plane_index], context);
|
||||
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);
|
||||
|
||||
if (disp_cfg_plane_location < 0)
|
||||
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
|
||||
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);
|
||||
dml_dispcfg->plane_descriptors[disp_cfg_plane_location].stream_index = disp_cfg_stream_location;
|
||||
|
||||
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]))
|
||||
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]))
|
||||
dml_ctx->v21.dml_to_dc_pipe_mapping.disp_cfg_to_plane_id_valid[disp_cfg_plane_location] = true;
|
||||
|
||||
/* apply forced pstate policy */
|
||||
|
||||
@@ -120,10 +120,11 @@ void dpp401_set_cursor_attributes(
|
||||
enum dc_cursor_color_format color_format = cursor_attributes->color_format;
|
||||
int cur_rom_en = 0;
|
||||
|
||||
// DCN4 should always do Cursor degamma for Cursor Color modes
|
||||
if (color_format == CURSOR_MODE_COLOR_PRE_MULTIPLIED_ALPHA ||
|
||||
color_format == CURSOR_MODE_COLOR_UN_PRE_MULTIPLIED_ALPHA) {
|
||||
cur_rom_en = 1;
|
||||
if (cursor_attributes->attribute_flags.bits.ENABLE_CURSOR_DEGAMMA) {
|
||||
cur_rom_en = 1;
|
||||
}
|
||||
}
|
||||
|
||||
REG_UPDATE_3(CURSOR0_CONTROL,
|
||||
|
||||
@@ -1980,9 +1980,9 @@ void dcn401_program_pipe(
|
||||
dc->res_pool->hubbub, pipe_ctx->plane_res.hubp->inst, pipe_ctx->hubp_regs.det_size);
|
||||
}
|
||||
|
||||
if (pipe_ctx->update_flags.raw ||
|
||||
(pipe_ctx->plane_state && pipe_ctx->plane_state->update_flags.raw) ||
|
||||
pipe_ctx->stream->update_flags.raw)
|
||||
if (pipe_ctx->plane_state && (pipe_ctx->update_flags.raw ||
|
||||
pipe_ctx->plane_state->update_flags.raw ||
|
||||
pipe_ctx->stream->update_flags.raw))
|
||||
dc->hwss.update_dchubp_dpp(dc, pipe_ctx, context);
|
||||
|
||||
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)
|
||||
void link_set_all_streams_dpms_off_for_link(struct dc_link *link)
|
||||
{
|
||||
struct pipe_ctx *pipes[MAX_PIPES];
|
||||
struct dc_stream_state *streams[MAX_PIPES];
|
||||
struct dc_state *state = link->dc->current_state;
|
||||
uint8_t count;
|
||||
int i;
|
||||
@@ -160,10 +161,18 @@ void link_set_all_streams_dpms_off_for_link(struct dc_link *link)
|
||||
|
||||
link_get_master_pipes_with_dpms_on(link, state, &count, pipes);
|
||||
|
||||
/* The subsequent call to dc_commit_updates_for_stream for a full update
|
||||
* will release the current state and swap to a new state. Releasing the
|
||||
* current state results in the stream pointers in the pipe_ctx structs
|
||||
* to be zero'd. Hence, cache all streams prior to dc_commit_updates_for_stream.
|
||||
*/
|
||||
for (i = 0; i < count; i++)
|
||||
streams[i] = pipes[i]->stream;
|
||||
|
||||
for (i = 0; i < count; i++) {
|
||||
stream_update.stream = pipes[i]->stream;
|
||||
stream_update.stream = streams[i];
|
||||
dc_commit_updates_for_stream(link->ctx->dc, NULL, 0,
|
||||
pipes[i]->stream, &stream_update,
|
||||
streams[i], &stream_update,
|
||||
state);
|
||||
}
|
||||
|
||||
|
||||
@@ -1118,6 +1118,10 @@ static void __drm_gpusvm_range_unmap_pages(struct drm_gpusvm *gpusvm,
|
||||
lockdep_assert_held(&gpusvm->notifier_lock);
|
||||
|
||||
if (range->flags.has_dma_mapping) {
|
||||
struct drm_gpusvm_range_flags flags = {
|
||||
.__flags = range->flags.__flags,
|
||||
};
|
||||
|
||||
for (i = 0, j = 0; i < npages; j++) {
|
||||
struct drm_pagemap_device_addr *addr = &range->dma_addr[j];
|
||||
|
||||
@@ -1131,8 +1135,12 @@ static void __drm_gpusvm_range_unmap_pages(struct drm_gpusvm *gpusvm,
|
||||
dev, *addr);
|
||||
i += 1 << addr->order;
|
||||
}
|
||||
range->flags.has_devmem_pages = false;
|
||||
range->flags.has_dma_mapping = false;
|
||||
|
||||
/* WRITE_ONCE pairs with READ_ONCE for opportunistic checks */
|
||||
flags.has_devmem_pages = false;
|
||||
flags.has_dma_mapping = false;
|
||||
WRITE_ONCE(range->flags.__flags, flags.__flags);
|
||||
|
||||
range->dpagemap = NULL;
|
||||
}
|
||||
}
|
||||
@@ -1334,6 +1342,7 @@ int drm_gpusvm_range_get_pages(struct drm_gpusvm *gpusvm,
|
||||
int err = 0;
|
||||
struct dev_pagemap *pagemap;
|
||||
struct drm_pagemap *dpagemap;
|
||||
struct drm_gpusvm_range_flags flags;
|
||||
|
||||
retry:
|
||||
hmm_range.notifier_seq = mmu_interval_read_begin(notifier);
|
||||
@@ -1378,7 +1387,8 @@ int drm_gpusvm_range_get_pages(struct drm_gpusvm *gpusvm,
|
||||
*/
|
||||
drm_gpusvm_notifier_lock(gpusvm);
|
||||
|
||||
if (range->flags.unmapped) {
|
||||
flags.__flags = range->flags.__flags;
|
||||
if (flags.unmapped) {
|
||||
drm_gpusvm_notifier_unlock(gpusvm);
|
||||
err = -EFAULT;
|
||||
goto err_free;
|
||||
@@ -1454,6 +1464,11 @@ int drm_gpusvm_range_get_pages(struct drm_gpusvm *gpusvm,
|
||||
goto err_unmap;
|
||||
}
|
||||
|
||||
if (ctx->devmem_only) {
|
||||
err = -EFAULT;
|
||||
goto err_unmap;
|
||||
}
|
||||
|
||||
addr = dma_map_page(gpusvm->drm->dev,
|
||||
page, 0,
|
||||
PAGE_SIZE << order,
|
||||
@@ -1469,14 +1484,17 @@ int drm_gpusvm_range_get_pages(struct drm_gpusvm *gpusvm,
|
||||
}
|
||||
i += 1 << order;
|
||||
num_dma_mapped = i;
|
||||
range->flags.has_dma_mapping = true;
|
||||
flags.has_dma_mapping = true;
|
||||
}
|
||||
|
||||
if (zdd) {
|
||||
range->flags.has_devmem_pages = true;
|
||||
flags.has_devmem_pages = true;
|
||||
range->dpagemap = dpagemap;
|
||||
}
|
||||
|
||||
/* WRITE_ONCE pairs with READ_ONCE for opportunistic checks */
|
||||
WRITE_ONCE(range->flags.__flags, flags.__flags);
|
||||
|
||||
drm_gpusvm_notifier_unlock(gpusvm);
|
||||
kvfree(pfns);
|
||||
set_seqno:
|
||||
@@ -1765,6 +1783,8 @@ int drm_gpusvm_migrate_to_devmem(struct drm_gpusvm *gpusvm,
|
||||
goto err_finalize;
|
||||
|
||||
/* Upon success bind devmem allocation to range and zdd */
|
||||
devmem_allocation->timeslice_expiration = get_jiffies_64() +
|
||||
msecs_to_jiffies(ctx->timeslice_ms);
|
||||
zdd->devmem_allocation = devmem_allocation; /* Owns ref */
|
||||
|
||||
err_finalize:
|
||||
@@ -1985,6 +2005,13 @@ static int __drm_gpusvm_migrate_to_ram(struct vm_area_struct *vas,
|
||||
void *buf;
|
||||
int i, err = 0;
|
||||
|
||||
if (page) {
|
||||
zdd = page->zone_device_data;
|
||||
if (time_before64(get_jiffies_64(),
|
||||
zdd->devmem_allocation->timeslice_expiration))
|
||||
return 0;
|
||||
}
|
||||
|
||||
start = ALIGN_DOWN(fault_addr, size);
|
||||
end = ALIGN(fault_addr + 1, size);
|
||||
|
||||
|
||||
@@ -75,7 +75,7 @@ static void meson_encoder_hdmi_set_vclk(struct meson_encoder_hdmi *encoder_hdmi,
|
||||
unsigned long long venc_freq;
|
||||
unsigned long long hdmi_freq;
|
||||
|
||||
vclk_freq = mode->clock * 1000;
|
||||
vclk_freq = mode->clock * 1000ULL;
|
||||
|
||||
/* For 420, pixel clock is half unlike venc clock */
|
||||
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
|
||||
struct meson_encoder_hdmi *encoder_hdmi = bridge_to_meson_encoder_hdmi(bridge);
|
||||
struct meson_drm *priv = encoder_hdmi->priv;
|
||||
bool is_hdmi2_sink = display_info->hdmi.scdc.supported;
|
||||
unsigned long long clock = mode->clock * 1000;
|
||||
unsigned long long clock = mode->clock * 1000ULL;
|
||||
unsigned long long phy_freq;
|
||||
unsigned long long vclk_freq;
|
||||
unsigned long long venc_freq;
|
||||
|
||||
@@ -390,7 +390,10 @@ static int panel_mipi_dbi_spi_probe(struct spi_device *spi)
|
||||
|
||||
spi_set_drvdata(spi, drm);
|
||||
|
||||
drm_client_setup(drm, NULL);
|
||||
if (bpp == 16)
|
||||
drm_client_setup_with_fourcc(drm, DRM_FORMAT_RGB565);
|
||||
else
|
||||
drm_client_setup_with_fourcc(drm, DRM_FORMAT_RGB888);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -47,6 +47,10 @@
|
||||
#define MI_LRI_FORCE_POSTED REG_BIT(12)
|
||||
#define MI_LRI_LEN(x) (((x) & 0xff) + 1)
|
||||
|
||||
#define MI_STORE_REGISTER_MEM (__MI_INSTR(0x24) | XE_INSTR_NUM_DW(4))
|
||||
#define MI_SRM_USE_GGTT REG_BIT(22)
|
||||
#define MI_SRM_ADD_CS_OFFSET REG_BIT(19)
|
||||
|
||||
#define MI_FLUSH_DW __MI_INSTR(0x26)
|
||||
#define MI_FLUSH_DW_PROTECTED_MEM_EN REG_BIT(22)
|
||||
#define MI_FLUSH_DW_STORE_INDEX REG_BIT(21)
|
||||
|
||||
@@ -43,6 +43,10 @@
|
||||
#define XEHPC_BCS8_RING_BASE 0x3ee000
|
||||
#define GSCCS_RING_BASE 0x11a000
|
||||
|
||||
#define ENGINE_ID(base) XE_REG((base) + 0x8c)
|
||||
#define ENGINE_INSTANCE_ID REG_GENMASK(9, 4)
|
||||
#define ENGINE_CLASS_ID REG_GENMASK(2, 0)
|
||||
|
||||
#define RING_TAIL(base) XE_REG((base) + 0x30)
|
||||
#define TAIL_ADDR REG_GENMASK(20, 3)
|
||||
|
||||
@@ -154,6 +158,7 @@
|
||||
#define STOP_RING REG_BIT(8)
|
||||
|
||||
#define RING_CTX_TIMESTAMP(base) XE_REG((base) + 0x3a8)
|
||||
#define RING_CTX_TIMESTAMP_UDW(base) XE_REG((base) + 0x3ac)
|
||||
#define CSBE_DEBUG_STATUS(base) XE_REG((base) + 0x3fc)
|
||||
|
||||
#define RING_FORCE_TO_NONPRIV(base, i) XE_REG(((base) + 0x4d0) + (i) * 4)
|
||||
|
||||
@@ -157,6 +157,7 @@
|
||||
#define XEHPG_SC_INSTDONE_EXTRA2 XE_REG_MCR(0x7108)
|
||||
|
||||
#define COMMON_SLICE_CHICKEN4 XE_REG(0x7300, XE_REG_OPTION_MASKED)
|
||||
#define SBE_PUSH_CONSTANT_BEHIND_FIX_ENABLE REG_BIT(12)
|
||||
#define DISABLE_TDC_LOAD_BALANCING_CALC REG_BIT(6)
|
||||
|
||||
#define COMMON_SLICE_CHICKEN3 XE_REG(0x7304, XE_REG_OPTION_MASKED)
|
||||
|
||||
@@ -11,7 +11,9 @@
|
||||
#define CTX_RING_TAIL (0x06 + 1)
|
||||
#define CTX_RING_START (0x08 + 1)
|
||||
#define CTX_RING_CTL (0x0a + 1)
|
||||
#define CTX_BB_PER_CTX_PTR (0x12 + 1)
|
||||
#define CTX_TIMESTAMP (0x22 + 1)
|
||||
#define CTX_TIMESTAMP_UDW (0x24 + 1)
|
||||
#define CTX_INDIRECT_RING_STATE (0x26 + 1)
|
||||
#define CTX_PDP0_UDW (0x30 + 1)
|
||||
#define CTX_PDP0_LDW (0x32 + 1)
|
||||
|
||||
@@ -330,6 +330,8 @@ struct xe_device {
|
||||
u8 has_sriov:1;
|
||||
/** @info.has_usm: Device has unified shared memory support */
|
||||
u8 has_usm:1;
|
||||
/** @info.has_64bit_timestamp: Device supports 64-bit timestamps */
|
||||
u8 has_64bit_timestamp:1;
|
||||
/** @info.is_dgfx: is discrete device */
|
||||
u8 is_dgfx:1;
|
||||
/**
|
||||
|
||||
@@ -830,7 +830,7 @@ void xe_exec_queue_update_run_ticks(struct xe_exec_queue *q)
|
||||
{
|
||||
struct xe_device *xe = gt_to_xe(q->gt);
|
||||
struct xe_lrc *lrc;
|
||||
u32 old_ts, new_ts;
|
||||
u64 old_ts, new_ts;
|
||||
int idx;
|
||||
|
||||
/*
|
||||
|
||||
@@ -941,7 +941,7 @@ static bool check_timeout(struct xe_exec_queue *q, struct xe_sched_job *job)
|
||||
return xe_sched_invalidate_job(job, 2);
|
||||
}
|
||||
|
||||
ctx_timestamp = xe_lrc_ctx_timestamp(q->lrc[0]);
|
||||
ctx_timestamp = lower_32_bits(xe_lrc_ctx_timestamp(q->lrc[0]));
|
||||
ctx_job_timestamp = xe_lrc_ctx_job_timestamp(q->lrc[0]);
|
||||
|
||||
/*
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
#include "xe_hw_fence.h"
|
||||
#include "xe_map.h"
|
||||
#include "xe_memirq.h"
|
||||
#include "xe_mmio.h"
|
||||
#include "xe_sriov.h"
|
||||
#include "xe_trace_lrc.h"
|
||||
#include "xe_vm.h"
|
||||
@@ -650,6 +651,7 @@ u32 xe_lrc_pphwsp_offset(struct xe_lrc *lrc)
|
||||
#define LRC_START_SEQNO_PPHWSP_OFFSET (LRC_SEQNO_PPHWSP_OFFSET + 8)
|
||||
#define LRC_CTX_JOB_TIMESTAMP_OFFSET (LRC_START_SEQNO_PPHWSP_OFFSET + 8)
|
||||
#define LRC_PARALLEL_PPHWSP_OFFSET 2048
|
||||
#define LRC_ENGINE_ID_PPHWSP_OFFSET 2096
|
||||
#define LRC_PPHWSP_SIZE SZ_4K
|
||||
|
||||
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)
|
||||
|
||||
static u32 __xe_lrc_ctx_job_timestamp_offset(struct xe_lrc *lrc)
|
||||
{
|
||||
/* The start seqno is stored in the driver-defined portion of PPHWSP */
|
||||
/* This is stored in the driver-defined portion of PPHWSP */
|
||||
return xe_lrc_pphwsp_offset(lrc) + LRC_CTX_JOB_TIMESTAMP_OFFSET;
|
||||
}
|
||||
|
||||
@@ -694,11 +696,21 @@ static inline u32 __xe_lrc_parallel_offset(struct xe_lrc *lrc)
|
||||
return xe_lrc_pphwsp_offset(lrc) + LRC_PARALLEL_PPHWSP_OFFSET;
|
||||
}
|
||||
|
||||
static inline u32 __xe_lrc_engine_id_offset(struct xe_lrc *lrc)
|
||||
{
|
||||
return xe_lrc_pphwsp_offset(lrc) + LRC_ENGINE_ID_PPHWSP_OFFSET;
|
||||
}
|
||||
|
||||
static u32 __xe_lrc_ctx_timestamp_offset(struct xe_lrc *lrc)
|
||||
{
|
||||
return __xe_lrc_regs_offset(lrc) + CTX_TIMESTAMP * sizeof(u32);
|
||||
}
|
||||
|
||||
static u32 __xe_lrc_ctx_timestamp_udw_offset(struct xe_lrc *lrc)
|
||||
{
|
||||
return __xe_lrc_regs_offset(lrc) + CTX_TIMESTAMP_UDW * sizeof(u32);
|
||||
}
|
||||
|
||||
static inline u32 __xe_lrc_indirect_ring_offset(struct xe_lrc *lrc)
|
||||
{
|
||||
/* Indirect ring state page is at the very end of LRC */
|
||||
@@ -726,8 +738,10 @@ DECL_MAP_ADDR_HELPERS(regs)
|
||||
DECL_MAP_ADDR_HELPERS(start_seqno)
|
||||
DECL_MAP_ADDR_HELPERS(ctx_job_timestamp)
|
||||
DECL_MAP_ADDR_HELPERS(ctx_timestamp)
|
||||
DECL_MAP_ADDR_HELPERS(ctx_timestamp_udw)
|
||||
DECL_MAP_ADDR_HELPERS(parallel)
|
||||
DECL_MAP_ADDR_HELPERS(indirect_ring)
|
||||
DECL_MAP_ADDR_HELPERS(engine_id)
|
||||
|
||||
#undef DECL_MAP_ADDR_HELPERS
|
||||
|
||||
@@ -742,19 +756,38 @@ u32 xe_lrc_ctx_timestamp_ggtt_addr(struct xe_lrc *lrc)
|
||||
return __xe_lrc_ctx_timestamp_ggtt_addr(lrc);
|
||||
}
|
||||
|
||||
/**
|
||||
* xe_lrc_ctx_timestamp_udw_ggtt_addr() - Get ctx timestamp udw GGTT address
|
||||
* @lrc: Pointer to the lrc.
|
||||
*
|
||||
* Returns: ctx timestamp udw GGTT address
|
||||
*/
|
||||
u32 xe_lrc_ctx_timestamp_udw_ggtt_addr(struct xe_lrc *lrc)
|
||||
{
|
||||
return __xe_lrc_ctx_timestamp_udw_ggtt_addr(lrc);
|
||||
}
|
||||
|
||||
/**
|
||||
* xe_lrc_ctx_timestamp() - Read ctx timestamp value
|
||||
* @lrc: Pointer to the lrc.
|
||||
*
|
||||
* Returns: ctx timestamp value
|
||||
*/
|
||||
u32 xe_lrc_ctx_timestamp(struct xe_lrc *lrc)
|
||||
u64 xe_lrc_ctx_timestamp(struct xe_lrc *lrc)
|
||||
{
|
||||
struct xe_device *xe = lrc_to_xe(lrc);
|
||||
struct iosys_map map;
|
||||
u32 ldw, udw = 0;
|
||||
|
||||
map = __xe_lrc_ctx_timestamp_map(lrc);
|
||||
return xe_map_read32(xe, &map);
|
||||
ldw = xe_map_read32(xe, &map);
|
||||
|
||||
if (xe->info.has_64bit_timestamp) {
|
||||
map = __xe_lrc_ctx_timestamp_udw_map(lrc);
|
||||
udw = xe_map_read32(xe, &map);
|
||||
}
|
||||
|
||||
return (u64)udw << 32 | ldw;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -864,7 +897,7 @@ static void *empty_lrc_data(struct xe_hw_engine *hwe)
|
||||
|
||||
static void xe_lrc_set_ppgtt(struct xe_lrc *lrc, struct xe_vm *vm)
|
||||
{
|
||||
u64 desc = xe_vm_pdp4_descriptor(vm, lrc->tile);
|
||||
u64 desc = xe_vm_pdp4_descriptor(vm, gt_to_tile(lrc->gt));
|
||||
|
||||
xe_lrc_write_ctx_reg(lrc, CTX_PDP0_UDW, upper_32_bits(desc));
|
||||
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)
|
||||
xe_bo_unpin(lrc->bo);
|
||||
xe_bo_unlock(lrc->bo);
|
||||
xe_bo_put(lrc->bo);
|
||||
xe_bo_unpin_map_no_vm(lrc->bb_per_ctx_bo);
|
||||
}
|
||||
|
||||
/*
|
||||
* xe_lrc_setup_utilization() - Setup wa bb to assist in calculating active
|
||||
* context run ticks.
|
||||
* @lrc: Pointer to the lrc.
|
||||
*
|
||||
* Context Timestamp (CTX_TIMESTAMP) in the LRC accumulates the run ticks of the
|
||||
* context, but only gets updated when the context switches out. In order to
|
||||
* check how long a context has been active before it switches out, two things
|
||||
* are required:
|
||||
*
|
||||
* (1) Determine if the context is running:
|
||||
* To do so, we program the WA BB to set an initial value for CTX_TIMESTAMP in
|
||||
* the LRC. The value chosen is 1 since 0 is the initial value when the LRC is
|
||||
* initialized. During a query, we just check for this value to determine if the
|
||||
* context is active. If the context switched out, it would overwrite this
|
||||
* location with the actual CTX_TIMESTAMP MMIO value. Note that WA BB runs as
|
||||
* the last part of context restore, so reusing this LRC location will not
|
||||
* clobber anything.
|
||||
*
|
||||
* (2) Calculate the time that the context has been active for:
|
||||
* The CTX_TIMESTAMP ticks only when the context is active. If a context is
|
||||
* active, we just use the CTX_TIMESTAMP MMIO as the new value of utilization.
|
||||
* While doing so, we need to read the CTX_TIMESTAMP MMIO for the specific
|
||||
* engine instance. Since we do not know which instance the context is running
|
||||
* on until it is scheduled, we also read the ENGINE_ID MMIO in the WA BB and
|
||||
* store it in the PPHSWP.
|
||||
*/
|
||||
#define CONTEXT_ACTIVE 1ULL
|
||||
static void xe_lrc_setup_utilization(struct xe_lrc *lrc)
|
||||
{
|
||||
u32 *cmd;
|
||||
|
||||
cmd = lrc->bb_per_ctx_bo->vmap.vaddr;
|
||||
|
||||
*cmd++ = MI_STORE_REGISTER_MEM | MI_SRM_USE_GGTT | MI_SRM_ADD_CS_OFFSET;
|
||||
*cmd++ = ENGINE_ID(0).addr;
|
||||
*cmd++ = __xe_lrc_engine_id_ggtt_addr(lrc);
|
||||
*cmd++ = 0;
|
||||
|
||||
*cmd++ = MI_STORE_DATA_IMM | MI_SDI_GGTT | MI_SDI_NUM_DW(1);
|
||||
*cmd++ = __xe_lrc_ctx_timestamp_ggtt_addr(lrc);
|
||||
*cmd++ = 0;
|
||||
*cmd++ = lower_32_bits(CONTEXT_ACTIVE);
|
||||
|
||||
if (lrc_to_xe(lrc)->info.has_64bit_timestamp) {
|
||||
*cmd++ = MI_STORE_DATA_IMM | MI_SDI_GGTT | MI_SDI_NUM_DW(1);
|
||||
*cmd++ = __xe_lrc_ctx_timestamp_udw_ggtt_addr(lrc);
|
||||
*cmd++ = 0;
|
||||
*cmd++ = upper_32_bits(CONTEXT_ACTIVE);
|
||||
}
|
||||
|
||||
*cmd++ = MI_BATCH_BUFFER_END;
|
||||
|
||||
xe_lrc_write_ctx_reg(lrc, CTX_BB_PER_CTX_PTR,
|
||||
xe_bo_ggtt_addr(lrc->bb_per_ctx_bo) | 1);
|
||||
|
||||
}
|
||||
|
||||
#define PVC_CTX_ASID (0x2e + 1)
|
||||
@@ -893,31 +985,40 @@ static int xe_lrc_init(struct xe_lrc *lrc, struct xe_hw_engine *hwe,
|
||||
void *init_data = NULL;
|
||||
u32 arb_enable;
|
||||
u32 lrc_size;
|
||||
u32 bo_flags;
|
||||
int err;
|
||||
|
||||
kref_init(&lrc->refcount);
|
||||
lrc->gt = gt;
|
||||
lrc->flags = 0;
|
||||
lrc_size = ring_size + xe_gt_lrc_size(gt, hwe->class);
|
||||
if (xe_gt_has_indirect_ring_state(gt))
|
||||
lrc->flags |= XE_LRC_FLAG_INDIRECT_RING_STATE;
|
||||
|
||||
bo_flags = XE_BO_FLAG_VRAM_IF_DGFX(tile) | XE_BO_FLAG_GGTT |
|
||||
XE_BO_FLAG_GGTT_INVALIDATE;
|
||||
|
||||
/*
|
||||
* FIXME: Perma-pinning LRC as we don't yet support moving GGTT address
|
||||
* via VM bind calls.
|
||||
*/
|
||||
lrc->bo = xe_bo_create_pin_map(xe, tile, vm, lrc_size,
|
||||
ttm_bo_type_kernel,
|
||||
XE_BO_FLAG_VRAM_IF_DGFX(tile) |
|
||||
XE_BO_FLAG_GGTT |
|
||||
XE_BO_FLAG_GGTT_INVALIDATE);
|
||||
bo_flags);
|
||||
if (IS_ERR(lrc->bo))
|
||||
return PTR_ERR(lrc->bo);
|
||||
|
||||
lrc->bb_per_ctx_bo = xe_bo_create_pin_map(xe, tile, NULL, SZ_4K,
|
||||
ttm_bo_type_kernel,
|
||||
bo_flags);
|
||||
if (IS_ERR(lrc->bb_per_ctx_bo)) {
|
||||
err = PTR_ERR(lrc->bb_per_ctx_bo);
|
||||
goto err_lrc_finish;
|
||||
}
|
||||
|
||||
lrc->size = lrc_size;
|
||||
lrc->tile = gt_to_tile(hwe->gt);
|
||||
lrc->ring.size = ring_size;
|
||||
lrc->ring.tail = 0;
|
||||
lrc->ctx_timestamp = 0;
|
||||
|
||||
xe_hw_fence_ctx_init(&lrc->fence_ctx, hwe->gt,
|
||||
hwe->fence_irq, hwe->name);
|
||||
@@ -990,7 +1091,10 @@ static int xe_lrc_init(struct xe_lrc *lrc, struct xe_hw_engine *hwe,
|
||||
xe_lrc_read_ctx_reg(lrc, CTX_CONTEXT_CONTROL) |
|
||||
_MASKED_BIT_ENABLE(CTX_CTRL_PXP_ENABLE));
|
||||
|
||||
lrc->ctx_timestamp = 0;
|
||||
xe_lrc_write_ctx_reg(lrc, CTX_TIMESTAMP, 0);
|
||||
if (lrc_to_xe(lrc)->info.has_64bit_timestamp)
|
||||
xe_lrc_write_ctx_reg(lrc, CTX_TIMESTAMP_UDW, 0);
|
||||
|
||||
if (xe->info.has_asid && vm)
|
||||
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,
|
||||
map = __xe_lrc_start_seqno_map(lrc);
|
||||
xe_map_write32(lrc_to_xe(lrc), &map, lrc->fence_ctx.next_seqno - 1);
|
||||
|
||||
xe_lrc_setup_utilization(lrc);
|
||||
|
||||
return 0;
|
||||
|
||||
err_lrc_finish:
|
||||
@@ -1238,6 +1344,21 @@ struct iosys_map xe_lrc_parallel_map(struct xe_lrc *lrc)
|
||||
return __xe_lrc_parallel_map(lrc);
|
||||
}
|
||||
|
||||
/**
|
||||
* xe_lrc_engine_id() - Read engine id value
|
||||
* @lrc: Pointer to the lrc.
|
||||
*
|
||||
* Returns: context id value
|
||||
*/
|
||||
static u32 xe_lrc_engine_id(struct xe_lrc *lrc)
|
||||
{
|
||||
struct xe_device *xe = lrc_to_xe(lrc);
|
||||
struct iosys_map map;
|
||||
|
||||
map = __xe_lrc_engine_id_map(lrc);
|
||||
return xe_map_read32(xe, &map);
|
||||
}
|
||||
|
||||
static int instr_dw(u32 cmd_header)
|
||||
{
|
||||
/* GFXPIPE "SINGLE_DW" opcodes are a single dword */
|
||||
@@ -1684,7 +1805,7 @@ struct xe_lrc_snapshot *xe_lrc_snapshot_capture(struct xe_lrc *lrc)
|
||||
snapshot->lrc_offset = xe_lrc_pphwsp_offset(lrc);
|
||||
snapshot->lrc_size = lrc->bo->size - snapshot->lrc_offset;
|
||||
snapshot->lrc_snapshot = NULL;
|
||||
snapshot->ctx_timestamp = xe_lrc_ctx_timestamp(lrc);
|
||||
snapshot->ctx_timestamp = lower_32_bits(xe_lrc_ctx_timestamp(lrc));
|
||||
snapshot->ctx_job_timestamp = xe_lrc_ctx_job_timestamp(lrc);
|
||||
return snapshot;
|
||||
}
|
||||
@@ -1784,22 +1905,74 @@ void xe_lrc_snapshot_free(struct xe_lrc_snapshot *snapshot)
|
||||
kfree(snapshot);
|
||||
}
|
||||
|
||||
static int get_ctx_timestamp(struct xe_lrc *lrc, u32 engine_id, u64 *reg_ctx_ts)
|
||||
{
|
||||
u16 class = REG_FIELD_GET(ENGINE_CLASS_ID, engine_id);
|
||||
u16 instance = REG_FIELD_GET(ENGINE_INSTANCE_ID, engine_id);
|
||||
struct xe_hw_engine *hwe;
|
||||
u64 val;
|
||||
|
||||
hwe = xe_gt_hw_engine(lrc->gt, class, instance, false);
|
||||
if (xe_gt_WARN_ONCE(lrc->gt, !hwe || xe_hw_engine_is_reserved(hwe),
|
||||
"Unexpected engine class:instance %d:%d for context utilization\n",
|
||||
class, instance))
|
||||
return -1;
|
||||
|
||||
if (lrc_to_xe(lrc)->info.has_64bit_timestamp)
|
||||
val = xe_mmio_read64_2x32(&hwe->gt->mmio,
|
||||
RING_CTX_TIMESTAMP(hwe->mmio_base));
|
||||
else
|
||||
val = xe_mmio_read32(&hwe->gt->mmio,
|
||||
RING_CTX_TIMESTAMP(hwe->mmio_base));
|
||||
|
||||
*reg_ctx_ts = val;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* xe_lrc_update_timestamp() - Update ctx timestamp
|
||||
* @lrc: Pointer to the lrc.
|
||||
* @old_ts: Old timestamp value
|
||||
*
|
||||
* Populate @old_ts current saved ctx timestamp, read new ctx timestamp and
|
||||
* update saved value.
|
||||
* update saved value. With support for active contexts, the calculation may be
|
||||
* slightly racy, so follow a read-again logic to ensure that the context is
|
||||
* still active before returning the right timestamp.
|
||||
*
|
||||
* Returns: New ctx timestamp value
|
||||
*/
|
||||
u32 xe_lrc_update_timestamp(struct xe_lrc *lrc, u32 *old_ts)
|
||||
u64 xe_lrc_update_timestamp(struct xe_lrc *lrc, u64 *old_ts)
|
||||
{
|
||||
u64 lrc_ts, reg_ts;
|
||||
u32 engine_id;
|
||||
|
||||
*old_ts = lrc->ctx_timestamp;
|
||||
|
||||
lrc->ctx_timestamp = xe_lrc_ctx_timestamp(lrc);
|
||||
lrc_ts = xe_lrc_ctx_timestamp(lrc);
|
||||
/* CTX_TIMESTAMP mmio read is invalid on VF, so return the LRC value */
|
||||
if (IS_SRIOV_VF(lrc_to_xe(lrc))) {
|
||||
lrc->ctx_timestamp = lrc_ts;
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (lrc_ts == CONTEXT_ACTIVE) {
|
||||
engine_id = xe_lrc_engine_id(lrc);
|
||||
if (!get_ctx_timestamp(lrc, engine_id, ®_ts))
|
||||
lrc->ctx_timestamp = reg_ts;
|
||||
|
||||
/* read lrc again to ensure context is still active */
|
||||
lrc_ts = xe_lrc_ctx_timestamp(lrc);
|
||||
}
|
||||
|
||||
/*
|
||||
* If context switched out, just use the lrc_ts. Note that this needs to
|
||||
* be a separate if condition.
|
||||
*/
|
||||
if (lrc_ts != CONTEXT_ACTIVE)
|
||||
lrc->ctx_timestamp = lrc_ts;
|
||||
|
||||
done:
|
||||
trace_xe_lrc_update_timestamp(lrc, *old_ts);
|
||||
|
||||
return lrc->ctx_timestamp;
|
||||
|
||||
@@ -120,7 +120,8 @@ void xe_lrc_snapshot_print(struct xe_lrc_snapshot *snapshot, struct drm_printer
|
||||
void xe_lrc_snapshot_free(struct xe_lrc_snapshot *snapshot);
|
||||
|
||||
u32 xe_lrc_ctx_timestamp_ggtt_addr(struct xe_lrc *lrc);
|
||||
u32 xe_lrc_ctx_timestamp(struct xe_lrc *lrc);
|
||||
u32 xe_lrc_ctx_timestamp_udw_ggtt_addr(struct xe_lrc *lrc);
|
||||
u64 xe_lrc_ctx_timestamp(struct xe_lrc *lrc);
|
||||
u32 xe_lrc_ctx_job_timestamp_ggtt_addr(struct xe_lrc *lrc);
|
||||
u32 xe_lrc_ctx_job_timestamp(struct xe_lrc *lrc);
|
||||
|
||||
@@ -136,6 +137,6 @@ u32 xe_lrc_ctx_job_timestamp(struct xe_lrc *lrc);
|
||||
*
|
||||
* Returns the current LRC timestamp
|
||||
*/
|
||||
u32 xe_lrc_update_timestamp(struct xe_lrc *lrc, u32 *old_ts);
|
||||
u64 xe_lrc_update_timestamp(struct xe_lrc *lrc, u64 *old_ts);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -25,8 +25,8 @@ struct xe_lrc {
|
||||
/** @size: size of lrc including any indirect ring state page */
|
||||
u32 size;
|
||||
|
||||
/** @tile: tile which this LRC belongs to */
|
||||
struct xe_tile *tile;
|
||||
/** @gt: gt which this LRC belongs to */
|
||||
struct xe_gt *gt;
|
||||
|
||||
/** @flags: LRC flags */
|
||||
#define XE_LRC_FLAG_INDIRECT_RING_STATE 0x1
|
||||
@@ -52,7 +52,10 @@ struct xe_lrc {
|
||||
struct xe_hw_fence_ctx fence_ctx;
|
||||
|
||||
/** @ctx_timestamp: readout value of CTX_TIMESTAMP on last update */
|
||||
u32 ctx_timestamp;
|
||||
u64 ctx_timestamp;
|
||||
|
||||
/** @bb_per_ctx_bo: buffer object for per context batch wa buffer */
|
||||
struct xe_bo *bb_per_ctx_bo;
|
||||
};
|
||||
|
||||
struct xe_lrc_snapshot;
|
||||
|
||||
@@ -29,9 +29,6 @@ struct xe_modparam xe_modparam = {
|
||||
module_param_named(svm_notifier_size, xe_modparam.svm_notifier_size, uint, 0600);
|
||||
MODULE_PARM_DESC(svm_notifier_size, "Set the svm notifier size(in MiB), must be power of 2");
|
||||
|
||||
module_param_named(always_migrate_to_vram, xe_modparam.always_migrate_to_vram, bool, 0444);
|
||||
MODULE_PARM_DESC(always_migrate_to_vram, "Always migrate to VRAM on GPU fault");
|
||||
|
||||
module_param_named_unsafe(force_execlist, xe_modparam.force_execlist, bool, 0444);
|
||||
MODULE_PARM_DESC(force_execlist, "Force Execlist submission");
|
||||
|
||||
|
||||
@@ -12,7 +12,6 @@
|
||||
struct xe_modparam {
|
||||
bool force_execlist;
|
||||
bool probe_display;
|
||||
bool always_migrate_to_vram;
|
||||
u32 force_vram_bar_size;
|
||||
int guc_log_level;
|
||||
char *guc_firmware_path;
|
||||
|
||||
@@ -140,6 +140,7 @@ static const struct xe_graphics_desc graphics_xelpg = {
|
||||
.has_indirect_ring_state = 1, \
|
||||
.has_range_tlb_invalidation = 1, \
|
||||
.has_usm = 1, \
|
||||
.has_64bit_timestamp = 1, \
|
||||
.va_bits = 48, \
|
||||
.vm_max_level = 4, \
|
||||
.hw_engine_mask = \
|
||||
@@ -668,6 +669,7 @@ static int xe_info_init(struct xe_device *xe,
|
||||
|
||||
xe->info.has_range_tlb_invalidation = graphics_desc->has_range_tlb_invalidation;
|
||||
xe->info.has_usm = graphics_desc->has_usm;
|
||||
xe->info.has_64bit_timestamp = graphics_desc->has_64bit_timestamp;
|
||||
|
||||
for_each_remote_tile(tile, xe, id) {
|
||||
int err;
|
||||
|
||||
@@ -21,6 +21,7 @@ struct xe_graphics_desc {
|
||||
u8 has_indirect_ring_state:1;
|
||||
u8 has_range_tlb_invalidation:1;
|
||||
u8 has_usm:1;
|
||||
u8 has_64bit_timestamp:1;
|
||||
};
|
||||
|
||||
struct xe_media_desc {
|
||||
|
||||
@@ -2232,11 +2232,19 @@ static void op_commit(struct xe_vm *vm,
|
||||
}
|
||||
case DRM_GPUVA_OP_DRIVER:
|
||||
{
|
||||
/* WRITE_ONCE pairs with READ_ONCE in xe_svm.c */
|
||||
|
||||
if (op->subop == XE_VMA_SUBOP_MAP_RANGE) {
|
||||
op->map_range.range->tile_present |= BIT(tile->id);
|
||||
op->map_range.range->tile_invalidated &= ~BIT(tile->id);
|
||||
WRITE_ONCE(op->map_range.range->tile_present,
|
||||
op->map_range.range->tile_present |
|
||||
BIT(tile->id));
|
||||
WRITE_ONCE(op->map_range.range->tile_invalidated,
|
||||
op->map_range.range->tile_invalidated &
|
||||
~BIT(tile->id));
|
||||
} else if (op->subop == XE_VMA_SUBOP_UNMAP_RANGE) {
|
||||
op->unmap_range.range->tile_present &= ~BIT(tile->id);
|
||||
WRITE_ONCE(op->unmap_range.range->tile_present,
|
||||
op->unmap_range.range->tile_present &
|
||||
~BIT(tile->id));
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -234,13 +234,10 @@ static u32 get_ppgtt_flag(struct xe_sched_job *job)
|
||||
|
||||
static int emit_copy_timestamp(struct xe_lrc *lrc, u32 *dw, int i)
|
||||
{
|
||||
dw[i++] = MI_COPY_MEM_MEM | MI_COPY_MEM_MEM_SRC_GGTT |
|
||||
MI_COPY_MEM_MEM_DST_GGTT;
|
||||
dw[i++] = MI_STORE_REGISTER_MEM | MI_SRM_USE_GGTT | MI_SRM_ADD_CS_OFFSET;
|
||||
dw[i++] = RING_CTX_TIMESTAMP(0).addr;
|
||||
dw[i++] = xe_lrc_ctx_job_timestamp_ggtt_addr(lrc);
|
||||
dw[i++] = 0;
|
||||
dw[i++] = xe_lrc_ctx_timestamp_ggtt_addr(lrc);
|
||||
dw[i++] = 0;
|
||||
dw[i++] = MI_NOOP;
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user