mirror of
https://github.com/torvalds/linux.git
synced 2026-10-12 13:27:02 +02:00
Merge 7.2-rc3 into staging-next
We need the staging fixes in here, and it resolves a merge conflict in: drivers/staging/rtl8723bs/core/rtw_mlme_ext.c Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
commit
0438c40ea4
5
.mailmap
5
.mailmap
|
|
@ -642,7 +642,6 @@ Nicholas Piggin <npiggin@gmail.com> <npiggin@kernel.dk>
|
|||
Nicholas Piggin <npiggin@gmail.com> <npiggin@suse.de>
|
||||
Nicholas Piggin <npiggin@gmail.com> <nickpiggin@yahoo.com.au>
|
||||
Nicholas Piggin <npiggin@gmail.com> <piggin@cyberone.com.au>
|
||||
Nick Desaulniers <nick.desaulniers+lkml@gmail.com> <ndesaulniers@google.com>
|
||||
Nicolas Ferre <nicolas.ferre@microchip.com> <nicolas.ferre@atmel.com>
|
||||
Nicolas Pitre <nico@fluxnic.net> <nicolas.pitre@linaro.org>
|
||||
Nicolas Pitre <nico@fluxnic.net> <nico@linaro.org>
|
||||
|
|
@ -709,6 +708,10 @@ Qi Zheng <qi.zheng@linux.dev> <zhengqi.arch@bytedance.com>
|
|||
Quentin Monnet <qmo@kernel.org> <quentin.monnet@netronome.com>
|
||||
Quentin Monnet <qmo@kernel.org> <quentin@isovalent.com>
|
||||
Quentin Perret <qperret@qperret.net> <quentin.perret@arm.com>
|
||||
Radu Rendec <radu@rendec.net> <radu.rendec@ines.ro>
|
||||
Radu Rendec <radu@rendec.net> <rrendec@arista.com>
|
||||
Radu Rendec <radu@rendec.net> <radu.rendec@gmail.com>
|
||||
Radu Rendec <radu@rendec.net> <rrendec@redhat.com>
|
||||
Rae Moar <raemoar63@gmail.com> <rmoar@google.com>
|
||||
Rafael J. Wysocki <rjw@rjwysocki.net> <rjw@sisk.pl>
|
||||
Rajeev Nandan <quic_rajeevny@quicinc.com> <rajeevny@codeaurora.org>
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ Description:
|
|||
|
||||
Reading this attribute gives the state of the DbC. It
|
||||
can be one of the following states: disabled, enabled,
|
||||
initialized, connected or configured.
|
||||
initialized, connected, configured or suspended.
|
||||
|
||||
What: /sys/bus/pci/drivers/xhci_hcd/.../dbc_idVendor
|
||||
Date: March 2023
|
||||
|
|
|
|||
|
|
@ -47,11 +47,12 @@ ever have can be described at boot. There are no power-domain considerations
|
|||
as such devices are emulated.
|
||||
|
||||
CPU Hotplug on virtual systems is supported. It is distinct from physical
|
||||
CPU Hotplug as all resources are described as ``present``, but CPUs may be
|
||||
marked as disabled by firmware. Only the CPU's online/offline behaviour is
|
||||
influenced by firmware. An example is where a virtual machine boots with a
|
||||
single CPU, and additional CPUs are added once a cloud orchestrator deploys
|
||||
the workload.
|
||||
CPU Hotplug as all vCPU resources are statically described in the firmware
|
||||
configuration tables (e.g. MADT), meaning their maximum possible count is
|
||||
known at boot. However, vCPUs that are not enabled at boot are not marked
|
||||
as ``present`` by the kernel until they are hotplugged. An example is where
|
||||
a virtual machine boots with a single CPU, and additional CPUs are added
|
||||
once a cloud orchestrator deploys the workload.
|
||||
|
||||
For a virtual machine, the VMM (e.g. Qemu) plays the part of firmware.
|
||||
|
||||
|
|
@ -60,16 +61,19 @@ brought online. Firmware can enforce its policy via PSCI's return codes. e.g.
|
|||
``DENIED``.
|
||||
|
||||
The ACPI tables must describe all the resources of the virtual machine. CPUs
|
||||
that firmware wishes to disable either from boot (or later) should not be
|
||||
``enabled`` in the MADT GICC structures, but should have the ``online capable``
|
||||
bit set, to indicate they can be enabled later. The boot CPU must be marked as
|
||||
``enabled``. The 'always on' GICR structure must be used to describe the
|
||||
redistributors.
|
||||
that are hot-pluggable must have the ``online capable`` bit set and the
|
||||
``enabled`` bit cleared in the MADT GICC structures to indicate they can be
|
||||
enabled later. The boot CPU must be marked as ``enabled`` with its
|
||||
``online capable`` bit cleared. The 'always on' GICR structure must be used
|
||||
to describe the redistributors.
|
||||
|
||||
CPUs described as ``online capable`` but not ``enabled`` can be set to enabled
|
||||
by the DSDT's Processor object's _STA method. On virtual systems the _STA method
|
||||
must always report the CPU as ``present``. Changes to the firmware policy can
|
||||
be notified to the OS via device-check or eject-request.
|
||||
must always set the ``ACPI_STA_DEVICE_PRESENT`` bit, while toggling the
|
||||
``ACPI_STA_DEVICE_ENABLED`` bit to reflect its plug status. The kernel will
|
||||
then dynamically mark the vCPU as ``present`` within the OS when the
|
||||
``ACPI_STA_DEVICE_ENABLED`` bit becomes set during hot-add. Changes to the
|
||||
firmware policy can be notified to the OS via device-check or eject-request.
|
||||
|
||||
CPUs described as ``enabled`` in the static table, should not have their _STA
|
||||
modified dynamically by firmware. Soft-restart features such as kexec will
|
||||
|
|
|
|||
|
|
@ -82,121 +82,121 @@ The following keys are defined:
|
|||
version 1.0 of the RISC-V Vector extension manual.
|
||||
|
||||
* :c:macro:`RISCV_HWPROBE_EXT_ZBA`: The Zba address generation extension is
|
||||
supported, as defined in version 1.0 of the Bit-Manipulation ISA
|
||||
extensions.
|
||||
supported, as defined in version 1.0 of the Bit-Manipulation ISA
|
||||
extensions.
|
||||
|
||||
* :c:macro:`RISCV_HWPROBE_EXT_ZBB`: The Zbb extension is supported, as defined
|
||||
in version 1.0 of the Bit-Manipulation ISA extensions.
|
||||
in version 1.0 of the Bit-Manipulation ISA extensions.
|
||||
|
||||
* :c:macro:`RISCV_HWPROBE_EXT_ZBS`: The Zbs extension is supported, as defined
|
||||
in version 1.0 of the Bit-Manipulation ISA extensions.
|
||||
in version 1.0 of the Bit-Manipulation ISA extensions.
|
||||
|
||||
* :c:macro:`RISCV_HWPROBE_EXT_ZICBOZ`: The Zicboz extension is supported, as
|
||||
ratified in commit 3dd606f ("Create cmobase-v1.0.pdf") of riscv-CMOs.
|
||||
ratified in commit 3dd606f ("Create cmobase-v1.0.pdf") of riscv-CMOs.
|
||||
|
||||
* :c:macro:`RISCV_HWPROBE_EXT_ZBC` The Zbc extension is supported, as defined
|
||||
in version 1.0 of the Bit-Manipulation ISA extensions.
|
||||
in version 1.0 of the Bit-Manipulation ISA extensions.
|
||||
|
||||
* :c:macro:`RISCV_HWPROBE_EXT_ZBKB` The Zbkb extension is supported, as
|
||||
defined in version 1.0 of the Scalar Crypto ISA extensions.
|
||||
defined in version 1.0 of the Scalar Crypto ISA extensions.
|
||||
|
||||
* :c:macro:`RISCV_HWPROBE_EXT_ZBKC` The Zbkc extension is supported, as
|
||||
defined in version 1.0 of the Scalar Crypto ISA extensions.
|
||||
defined in version 1.0 of the Scalar Crypto ISA extensions.
|
||||
|
||||
* :c:macro:`RISCV_HWPROBE_EXT_ZBKX` The Zbkx extension is supported, as
|
||||
defined in version 1.0 of the Scalar Crypto ISA extensions.
|
||||
defined in version 1.0 of the Scalar Crypto ISA extensions.
|
||||
|
||||
* :c:macro:`RISCV_HWPROBE_EXT_ZKND` The Zknd extension is supported, as
|
||||
defined in version 1.0 of the Scalar Crypto ISA extensions.
|
||||
defined in version 1.0 of the Scalar Crypto ISA extensions.
|
||||
|
||||
* :c:macro:`RISCV_HWPROBE_EXT_ZKNE` The Zkne extension is supported, as
|
||||
defined in version 1.0 of the Scalar Crypto ISA extensions.
|
||||
defined in version 1.0 of the Scalar Crypto ISA extensions.
|
||||
|
||||
* :c:macro:`RISCV_HWPROBE_EXT_ZKNH` The Zknh extension is supported, as
|
||||
defined in version 1.0 of the Scalar Crypto ISA extensions.
|
||||
defined in version 1.0 of the Scalar Crypto ISA extensions.
|
||||
|
||||
* :c:macro:`RISCV_HWPROBE_EXT_ZKSED` The Zksed extension is supported, as
|
||||
defined in version 1.0 of the Scalar Crypto ISA extensions.
|
||||
defined in version 1.0 of the Scalar Crypto ISA extensions.
|
||||
|
||||
* :c:macro:`RISCV_HWPROBE_EXT_ZKSH` The Zksh extension is supported, as
|
||||
defined in version 1.0 of the Scalar Crypto ISA extensions.
|
||||
defined in version 1.0 of the Scalar Crypto ISA extensions.
|
||||
|
||||
* :c:macro:`RISCV_HWPROBE_EXT_ZKT` The Zkt extension is supported, as defined
|
||||
in version 1.0 of the Scalar Crypto ISA extensions.
|
||||
in version 1.0 of the Scalar Crypto ISA extensions.
|
||||
|
||||
* :c:macro:`RISCV_HWPROBE_EXT_ZVBB`: The Zvbb extension is supported as
|
||||
defined in version 1.0 of the RISC-V Cryptography Extensions Volume II.
|
||||
defined in version 1.0 of the RISC-V Cryptography Extensions Volume II.
|
||||
|
||||
* :c:macro:`RISCV_HWPROBE_EXT_ZVBC`: The Zvbc extension is supported as
|
||||
defined in version 1.0 of the RISC-V Cryptography Extensions Volume II.
|
||||
defined in version 1.0 of the RISC-V Cryptography Extensions Volume II.
|
||||
|
||||
* :c:macro:`RISCV_HWPROBE_EXT_ZVKB`: The Zvkb extension is supported as
|
||||
defined in version 1.0 of the RISC-V Cryptography Extensions Volume II.
|
||||
defined in version 1.0 of the RISC-V Cryptography Extensions Volume II.
|
||||
|
||||
* :c:macro:`RISCV_HWPROBE_EXT_ZVKG`: The Zvkg extension is supported as
|
||||
defined in version 1.0 of the RISC-V Cryptography Extensions Volume II.
|
||||
defined in version 1.0 of the RISC-V Cryptography Extensions Volume II.
|
||||
|
||||
* :c:macro:`RISCV_HWPROBE_EXT_ZVKNED`: The Zvkned extension is supported as
|
||||
defined in version 1.0 of the RISC-V Cryptography Extensions Volume II.
|
||||
defined in version 1.0 of the RISC-V Cryptography Extensions Volume II.
|
||||
|
||||
* :c:macro:`RISCV_HWPROBE_EXT_ZVKNHA`: The Zvknha extension is supported as
|
||||
defined in version 1.0 of the RISC-V Cryptography Extensions Volume II.
|
||||
defined in version 1.0 of the RISC-V Cryptography Extensions Volume II.
|
||||
|
||||
* :c:macro:`RISCV_HWPROBE_EXT_ZVKNHB`: The Zvknhb extension is supported as
|
||||
defined in version 1.0 of the RISC-V Cryptography Extensions Volume II.
|
||||
defined in version 1.0 of the RISC-V Cryptography Extensions Volume II.
|
||||
|
||||
* :c:macro:`RISCV_HWPROBE_EXT_ZVKSED`: The Zvksed extension is supported as
|
||||
defined in version 1.0 of the RISC-V Cryptography Extensions Volume II.
|
||||
defined in version 1.0 of the RISC-V Cryptography Extensions Volume II.
|
||||
|
||||
* :c:macro:`RISCV_HWPROBE_EXT_ZVKSH`: The Zvksh extension is supported as
|
||||
defined in version 1.0 of the RISC-V Cryptography Extensions Volume II.
|
||||
defined in version 1.0 of the RISC-V Cryptography Extensions Volume II.
|
||||
|
||||
* :c:macro:`RISCV_HWPROBE_EXT_ZVKT`: The Zvkt extension is supported as
|
||||
defined in version 1.0 of the RISC-V Cryptography Extensions Volume II.
|
||||
defined in version 1.0 of the RISC-V Cryptography Extensions Volume II.
|
||||
|
||||
* :c:macro:`RISCV_HWPROBE_EXT_ZFH`: The Zfh extension version 1.0 is supported
|
||||
as defined in the RISC-V ISA manual.
|
||||
as defined in the RISC-V ISA manual.
|
||||
|
||||
* :c:macro:`RISCV_HWPROBE_EXT_ZFHMIN`: The Zfhmin extension version 1.0 is
|
||||
supported as defined in the RISC-V ISA manual.
|
||||
supported as defined in the RISC-V ISA manual.
|
||||
|
||||
* :c:macro:`RISCV_HWPROBE_EXT_ZIHINTNTL`: The Zihintntl extension version 1.0
|
||||
is supported as defined in the RISC-V ISA manual.
|
||||
is supported as defined in the RISC-V ISA manual.
|
||||
|
||||
* :c:macro:`RISCV_HWPROBE_EXT_ZVFH`: The Zvfh extension is supported as
|
||||
defined in the RISC-V Vector manual starting from commit e2ccd0548d6c
|
||||
("Remove draft warnings from Zvfh[min]").
|
||||
defined in the RISC-V Vector manual starting from commit e2ccd0548d6c
|
||||
("Remove draft warnings from Zvfh[min]").
|
||||
|
||||
* :c:macro:`RISCV_HWPROBE_EXT_ZVFHMIN`: The Zvfhmin extension is supported as
|
||||
defined in the RISC-V Vector manual starting from commit e2ccd0548d6c
|
||||
("Remove draft warnings from Zvfh[min]").
|
||||
defined in the RISC-V Vector manual starting from commit e2ccd0548d6c
|
||||
("Remove draft warnings from Zvfh[min]").
|
||||
|
||||
* :c:macro:`RISCV_HWPROBE_EXT_ZFA`: The Zfa extension is supported as
|
||||
defined in the RISC-V ISA manual starting from commit 056b6ff467c7
|
||||
("Zfa is ratified").
|
||||
defined in the RISC-V ISA manual starting from commit 056b6ff467c7
|
||||
("Zfa is ratified").
|
||||
|
||||
* :c:macro:`RISCV_HWPROBE_EXT_ZTSO`: The Ztso extension is supported as
|
||||
defined in the RISC-V ISA manual starting from commit 5618fb5a216b
|
||||
("Ztso is now ratified.")
|
||||
defined in the RISC-V ISA manual starting from commit 5618fb5a216b
|
||||
("Ztso is now ratified.")
|
||||
|
||||
* :c:macro:`RISCV_HWPROBE_EXT_ZACAS`: The Zacas extension is supported as
|
||||
defined in the Atomic Compare-and-Swap (CAS) instructions manual starting
|
||||
from commit 5059e0ca641c ("update to ratified").
|
||||
defined in the Atomic Compare-and-Swap (CAS) instructions manual starting
|
||||
from commit 5059e0ca641c ("update to ratified").
|
||||
|
||||
* :c:macro:`RISCV_HWPROBE_EXT_ZICNTR`: The Zicntr extension version 2.0
|
||||
is supported as defined in the RISC-V ISA manual.
|
||||
is supported as defined in the RISC-V ISA manual.
|
||||
|
||||
* :c:macro:`RISCV_HWPROBE_EXT_ZICOND`: The Zicond extension is supported as
|
||||
defined in the RISC-V Integer Conditional (Zicond) operations extension
|
||||
manual starting from commit 95cf1f9 ("Add changes requested by Ved
|
||||
during signoff")
|
||||
defined in the RISC-V Integer Conditional (Zicond) operations extension
|
||||
manual starting from commit 95cf1f9 ("Add changes requested by Ved
|
||||
during signoff")
|
||||
|
||||
* :c:macro:`RISCV_HWPROBE_EXT_ZIHINTPAUSE`: The Zihintpause extension is
|
||||
supported as defined in the RISC-V ISA manual starting from commit
|
||||
d8ab5c78c207 ("Zihintpause is ratified").
|
||||
supported as defined in the RISC-V ISA manual starting from commit
|
||||
d8ab5c78c207 ("Zihintpause is ratified").
|
||||
|
||||
* :c:macro:`RISCV_HWPROBE_EXT_ZIHPM`: The Zihpm extension version 2.0
|
||||
is supported as defined in the RISC-V ISA manual.
|
||||
is supported as defined in the RISC-V ISA manual.
|
||||
|
||||
* :c:macro:`RISCV_HWPROBE_EXT_ZVE32X`: The Vector sub-extension Zve32x is
|
||||
supported, as defined by version 1.0 of the RISC-V Vector extension manual.
|
||||
|
|
@ -214,84 +214,89 @@ The following keys are defined:
|
|||
supported, as defined by version 1.0 of the RISC-V Vector extension manual.
|
||||
|
||||
* :c:macro:`RISCV_HWPROBE_EXT_ZIMOP`: The Zimop May-Be-Operations extension is
|
||||
supported as defined in the RISC-V ISA manual starting from commit
|
||||
58220614a5f ("Zimop is ratified/1.0").
|
||||
supported as defined in the RISC-V ISA manual starting from commit
|
||||
58220614a5f ("Zimop is ratified/1.0").
|
||||
|
||||
* :c:macro:`RISCV_HWPROBE_EXT_ZCA`: The Zca extension part of Zc* standard
|
||||
extensions for code size reduction, as ratified in commit 8be3419c1c0
|
||||
("Zcf doesn't exist on RV64 as it contains no instructions") of
|
||||
riscv-code-size-reduction.
|
||||
extensions for code size reduction, as ratified in commit 8be3419c1c0
|
||||
("Zcf doesn't exist on RV64 as it contains no instructions") of
|
||||
riscv-code-size-reduction.
|
||||
|
||||
* :c:macro:`RISCV_HWPROBE_EXT_ZCB`: The Zcb extension part of Zc* standard
|
||||
extensions for code size reduction, as ratified in commit 8be3419c1c0
|
||||
("Zcf doesn't exist on RV64 as it contains no instructions") of
|
||||
riscv-code-size-reduction.
|
||||
extensions for code size reduction, as ratified in commit 8be3419c1c0
|
||||
("Zcf doesn't exist on RV64 as it contains no instructions") of
|
||||
riscv-code-size-reduction.
|
||||
|
||||
* :c:macro:`RISCV_HWPROBE_EXT_ZCD`: The Zcd extension part of Zc* standard
|
||||
extensions for code size reduction, as ratified in commit 8be3419c1c0
|
||||
("Zcf doesn't exist on RV64 as it contains no instructions") of
|
||||
riscv-code-size-reduction.
|
||||
extensions for code size reduction, as ratified in commit 8be3419c1c0
|
||||
("Zcf doesn't exist on RV64 as it contains no instructions") of
|
||||
riscv-code-size-reduction.
|
||||
|
||||
* :c:macro:`RISCV_HWPROBE_EXT_ZCF`: The Zcf extension part of Zc* standard
|
||||
extensions for code size reduction, as ratified in commit 8be3419c1c0
|
||||
("Zcf doesn't exist on RV64 as it contains no instructions") of
|
||||
riscv-code-size-reduction.
|
||||
extensions for code size reduction, as ratified in commit 8be3419c1c0
|
||||
("Zcf doesn't exist on RV64 as it contains no instructions") of
|
||||
riscv-code-size-reduction.
|
||||
|
||||
* :c:macro:`RISCV_HWPROBE_EXT_ZCMOP`: The Zcmop May-Be-Operations extension is
|
||||
supported as defined in the RISC-V ISA manual starting from commit
|
||||
c732a4f39a4 ("Zcmop is ratified/1.0").
|
||||
supported as defined in the RISC-V ISA manual starting from commit
|
||||
c732a4f39a4 ("Zcmop is ratified/1.0").
|
||||
|
||||
* :c:macro:`RISCV_HWPROBE_EXT_ZAWRS`: The Zawrs extension is supported as
|
||||
ratified in commit 98918c844281 ("Merge pull request #1217 from
|
||||
riscv/zawrs") of riscv-isa-manual.
|
||||
ratified in commit 98918c844281 ("Merge pull request #1217 from
|
||||
riscv/zawrs") of riscv-isa-manual.
|
||||
|
||||
* :c:macro:`RISCV_HWPROBE_EXT_ZAAMO`: The Zaamo extension is supported as
|
||||
defined in the in the RISC-V ISA manual starting from commit e87412e621f1
|
||||
("integrate Zaamo and Zalrsc text (#1304)").
|
||||
defined in the in the RISC-V ISA manual starting from commit e87412e621f1
|
||||
("integrate Zaamo and Zalrsc text (#1304)").
|
||||
|
||||
* :c:macro:`RISCV_HWPROBE_EXT_ZALASR`: The Zalasr extension is supported as
|
||||
frozen at commit 194f0094 ("Version 0.9 for freeze") of riscv-zalasr.
|
||||
frozen at commit 194f0094 ("Version 0.9 for freeze") of riscv-zalasr.
|
||||
|
||||
* :c:macro:`RISCV_HWPROBE_EXT_ZALRSC`: The Zalrsc extension is supported as
|
||||
defined in the in the RISC-V ISA manual starting from commit e87412e621f1
|
||||
("integrate Zaamo and Zalrsc text (#1304)").
|
||||
defined in the in the RISC-V ISA manual starting from commit e87412e621f1
|
||||
("integrate Zaamo and Zalrsc text (#1304)").
|
||||
|
||||
* :c:macro:`RISCV_HWPROBE_EXT_SUPM`: The Supm extension is supported as
|
||||
defined in version 1.0 of the RISC-V Pointer Masking extensions.
|
||||
defined in version 1.0 of the RISC-V Pointer Masking extensions.
|
||||
|
||||
* :c:macro:`RISCV_HWPROBE_EXT_ZFBFMIN`: The Zfbfmin extension is supported as
|
||||
defined in the RISC-V ISA manual starting from commit 4dc23d6229de
|
||||
("Added Chapter title to BF16").
|
||||
defined in the RISC-V ISA manual starting from commit 4dc23d6229de
|
||||
("Added Chapter title to BF16").
|
||||
|
||||
* :c:macro:`RISCV_HWPROBE_EXT_ZVFBFMIN`: The Zvfbfmin extension is supported as
|
||||
defined in the RISC-V ISA manual starting from commit 4dc23d6229de
|
||||
("Added Chapter title to BF16").
|
||||
defined in the RISC-V ISA manual starting from commit 4dc23d6229de
|
||||
("Added Chapter title to BF16").
|
||||
|
||||
* :c:macro:`RISCV_HWPROBE_EXT_ZVFBFWMA`: The Zvfbfwma extension is supported as
|
||||
defined in the RISC-V ISA manual starting from commit 4dc23d6229de
|
||||
("Added Chapter title to BF16").
|
||||
defined in the RISC-V ISA manual starting from commit 4dc23d6229de
|
||||
("Added Chapter title to BF16").
|
||||
|
||||
* :c:macro:`RISCV_HWPROBE_EXT_ZICBOM`: The Zicbom extension is supported, as
|
||||
ratified in commit 3dd606f ("Create cmobase-v1.0.pdf") of riscv-CMOs.
|
||||
ratified in commit 3dd606f ("Create cmobase-v1.0.pdf") of riscv-CMOs.
|
||||
|
||||
* :c:macro:`RISCV_HWPROBE_EXT_ZABHA`: The Zabha extension is supported as
|
||||
ratified in commit 49f49c842ff9 ("Update to Rafified state") of
|
||||
riscv-zabha.
|
||||
ratified in commit 49f49c842ff9 ("Update to Rafified state") of
|
||||
riscv-zabha.
|
||||
|
||||
* :c:macro:`RISCV_HWPROBE_EXT_ZICBOP`: The Zicbop extension is supported, as
|
||||
ratified in commit 3dd606f ("Create cmobase-v1.0.pdf") of riscv-CMOs.
|
||||
ratified in commit 3dd606f ("Create cmobase-v1.0.pdf") of riscv-CMOs.
|
||||
|
||||
* :c:macro:`RISCV_HWPROBE_EXT_ZILSD`: The Zilsd extension is supported as
|
||||
defined in the RISC-V ISA manual starting from commit f88abf1 ("Integrating
|
||||
load/store pair for RV32 with the main manual") of the riscv-isa-manual.
|
||||
defined in the RISC-V ISA manual starting from commit f88abf1 ("Integrating
|
||||
load/store pair for RV32 with the main manual") of the riscv-isa-manual.
|
||||
|
||||
* :c:macro:`RISCV_HWPROBE_EXT_ZCLSD`: The Zclsd extension is supported as
|
||||
defined in the RISC-V ISA manual starting from commit f88abf1 ("Integrating
|
||||
load/store pair for RV32 with the main manual") of the riscv-isa-manual.
|
||||
defined in the RISC-V ISA manual starting from commit f88abf1 ("Integrating
|
||||
load/store pair for RV32 with the main manual") of the riscv-isa-manual.
|
||||
|
||||
* :c:macro:`RISCV_HWPROBE_EXT_ZICFILP`: The Zicfilp extension is supported,
|
||||
as defined in version 1.0 of the RISC-V Control-flow Integrity (CFI)
|
||||
extensions specification, ratified in commit 302a2d45c243
|
||||
("Update build-pdf.yml") of riscv-cfi.
|
||||
|
||||
* :c:macro:`RISCV_HWPROBE_KEY_CPUPERF_0`: Deprecated. Returns similar values to
|
||||
:c:macro:`RISCV_HWPROBE_KEY_MISALIGNED_SCALAR_PERF`, but the key was
|
||||
mistakenly classified as a bitmask rather than a value.
|
||||
:c:macro:`RISCV_HWPROBE_KEY_MISALIGNED_SCALAR_PERF`, but the key was
|
||||
mistakenly classified as a bitmask rather than a value.
|
||||
|
||||
* :c:macro:`RISCV_HWPROBE_KEY_MISALIGNED_SCALAR_PERF`: An enum value describing
|
||||
the performance of misaligned scalar native word accesses on the selected set
|
||||
|
|
@ -326,7 +331,7 @@ The following keys are defined:
|
|||
* :c:macro:`RISCV_HWPROBE_KEY_TIME_CSR_FREQ`: Frequency (in Hz) of `time CSR`.
|
||||
|
||||
* :c:macro:`RISCV_HWPROBE_KEY_MISALIGNED_VECTOR_PERF`: An enum value describing the
|
||||
performance of misaligned vector accesses on the selected set of processors.
|
||||
performance of misaligned vector accesses on the selected set of processors.
|
||||
|
||||
* :c:macro:`RISCV_HWPROBE_MISALIGNED_VECTOR_UNKNOWN`: The performance of misaligned
|
||||
vector accesses is unknown.
|
||||
|
|
@ -348,7 +353,7 @@ The following keys are defined:
|
|||
* MIPS
|
||||
|
||||
* :c:macro:`RISCV_HWPROBE_VENDOR_EXT_XMIPSEXECTL`: The xmipsexectl vendor
|
||||
extension is supported in the MIPS ISA extensions spec.
|
||||
extension is supported in the MIPS ISA extensions spec.
|
||||
|
||||
* :c:macro:`RISCV_HWPROBE_KEY_VENDOR_EXT_THEAD_0`: A bitmask containing the
|
||||
thead vendor extensions that are compatible with the
|
||||
|
|
@ -357,8 +362,8 @@ The following keys are defined:
|
|||
* T-HEAD
|
||||
|
||||
* :c:macro:`RISCV_HWPROBE_VENDOR_EXT_XTHEADVECTOR`: The xtheadvector vendor
|
||||
extension is supported in the T-Head ISA extensions spec starting from
|
||||
commit a18c801634 ("Add T-Head VECTOR vendor extension. ").
|
||||
extension is supported in the T-Head ISA extensions spec starting from
|
||||
commit a18c801634 ("Add T-Head VECTOR vendor extension. ").
|
||||
|
||||
* :c:macro:`RISCV_HWPROBE_KEY_ZICBOM_BLOCK_SIZE`: An unsigned int which
|
||||
represents the size of the Zicbom block in bytes.
|
||||
|
|
@ -370,20 +375,20 @@ The following keys are defined:
|
|||
* SIFIVE
|
||||
|
||||
* :c:macro:`RISCV_HWPROBE_VENDOR_EXT_XSFVQMACCDOD`: The Xsfqmaccdod vendor
|
||||
extension is supported in version 1.1 of SiFive Int8 Matrix Multiplication
|
||||
Extensions Specification.
|
||||
extension is supported in version 1.1 of SiFive Int8 Matrix Multiplication
|
||||
Extensions Specification.
|
||||
|
||||
* :c:macro:`RISCV_HWPROBE_VENDOR_EXT_XSFVQMACCQOQ`: The Xsfqmaccqoq vendor
|
||||
extension is supported in version 1.1 of SiFive Int8 Matrix Multiplication
|
||||
Instruction Extensions Specification.
|
||||
extension is supported in version 1.1 of SiFive Int8 Matrix Multiplication
|
||||
Instruction Extensions Specification.
|
||||
|
||||
* :c:macro:`RISCV_HWPROBE_VENDOR_EXT_XSFVFNRCLIPXFQF`: The Xsfvfnrclipxfqf
|
||||
vendor extension is supported in version 1.0 of SiFive FP32-to-int8 Ranged
|
||||
Clip Instructions Extensions Specification.
|
||||
vendor extension is supported in version 1.0 of SiFive FP32-to-int8 Ranged
|
||||
Clip Instructions Extensions Specification.
|
||||
|
||||
* :c:macro:`RISCV_HWPROBE_VENDOR_EXT_XSFVFWMACCQQQ`: The Xsfvfwmaccqqq
|
||||
vendor extension is supported in version 1.0 of Matrix Multiply Accumulate
|
||||
Instruction Extensions Specification.
|
||||
vendor extension is supported in version 1.0 of Matrix Multiply Accumulate
|
||||
Instruction Extensions Specification.
|
||||
|
||||
* :c:macro:`RISCV_HWPROBE_KEY_ZICBOP_BLOCK_SIZE`: An unsigned int which
|
||||
represents the size of the Zicbop block in bytes.
|
||||
|
|
@ -391,3 +396,8 @@ The following keys are defined:
|
|||
* :c:macro:`RISCV_HWPROBE_KEY_IMA_EXT_1`: A bitmask containing additional
|
||||
extensions that are compatible with the
|
||||
:c:macro:`RISCV_HWPROBE_BASE_BEHAVIOR_IMA`: base system behavior.
|
||||
|
||||
* :c:macro:`RISCV_HWPROBE_EXT_ZICFISS`: The Zicfiss extension is supported,
|
||||
as defined in version 1.0 of the RISC-V Control-flow Integrity (CFI)
|
||||
extensions specification, ratified in commit 302a2d45c243
|
||||
("Update build-pdf.yml") of riscv-cfi.
|
||||
|
|
|
|||
|
|
@ -457,6 +457,13 @@ properties:
|
|||
merged in the riscv-isa-manual by commit dbc79cf28a2 ("Initial seed
|
||||
of zc.adoc to src tree.").
|
||||
|
||||
- const: zclsd
|
||||
description:
|
||||
The Zclsd extension implements the compressed (16-bit) version of the
|
||||
Load/Store Pair for RV32. As with Zilsd, this extension was ratified
|
||||
in commit f88abf1 ("Integrating load/store pair for RV32 with the
|
||||
main manual") of riscv-isa-manual.
|
||||
|
||||
- const: zcmop
|
||||
description:
|
||||
The standard Zcmop extension version 1.0, as ratified in commit
|
||||
|
|
@ -487,6 +494,22 @@ properties:
|
|||
in commit 64074bc ("Update version numbers for Zfh/Zfinx") of
|
||||
riscv-isa-manual.
|
||||
|
||||
- const: zicbom
|
||||
description:
|
||||
The standard Zicbom extension for base cache management operations as
|
||||
ratified in commit 3dd606f ("Create cmobase-v1.0.pdf") of riscv-CMOs.
|
||||
|
||||
- const: zicbop
|
||||
description:
|
||||
The standard Zicbop extension for cache-block prefetch instructions
|
||||
as ratified in commit 3dd606f ("Create cmobase-v1.0.pdf") of
|
||||
riscv-CMOs.
|
||||
|
||||
- const: zicboz
|
||||
description:
|
||||
The standard Zicboz extension for cache-block zeroing as ratified
|
||||
in commit 3dd606f ("Create cmobase-v1.0.pdf") of riscv-CMOs.
|
||||
|
||||
- const: ziccamoa
|
||||
description:
|
||||
The standard Ziccamoa extension for main memory (cacheability and
|
||||
|
|
@ -514,6 +537,66 @@ properties:
|
|||
guarantee on LR/SC sequences, as ratified in commit b1d806605f87
|
||||
("Updated to ratified state.") of the riscv profiles specification.
|
||||
|
||||
- const: zicfilp
|
||||
description: |
|
||||
The standard Zicfilp extension for enforcing forward edge
|
||||
control-flow integrity as ratified in commit 3f8e450 ("merge
|
||||
pull request #227 from ved-rivos/0709") of riscv-cfi
|
||||
github repo.
|
||||
|
||||
- const: zicfiss
|
||||
description: |
|
||||
The standard Zicfiss extension for enforcing backward edge
|
||||
control-flow integrity as ratified in commit 3f8e450 ("merge
|
||||
pull request #227 from ved-rivos/0709") of riscv-cfi
|
||||
github repo.
|
||||
|
||||
- const: zicntr
|
||||
description:
|
||||
The standard Zicntr extension for base counters and timers, as
|
||||
ratified in the 20191213 version of the unprivileged ISA
|
||||
specification.
|
||||
|
||||
- const: zicond
|
||||
description:
|
||||
The standard Zicond extension for conditional arithmetic and
|
||||
conditional-select/move operations as ratified in commit 95cf1f9
|
||||
("Add changes requested by Ved during signoff") of riscv-zicond.
|
||||
|
||||
- const: zicsr
|
||||
description: |
|
||||
The standard Zicsr extension for control and status register
|
||||
instructions, as ratified in the 20191213 version of the
|
||||
unprivileged ISA specification.
|
||||
|
||||
This does not include Chapter 10, "Counters", which documents
|
||||
special case read-only CSRs, that were moved into the Zicntr and
|
||||
Zihpm extensions after the ratification of the 20191213 version of
|
||||
the unprivileged specification.
|
||||
|
||||
- const: zifencei
|
||||
description:
|
||||
The standard Zifencei extension for instruction-fetch fence, as
|
||||
ratified in the 20191213 version of the unprivileged ISA
|
||||
specification.
|
||||
|
||||
- const: zihintntl
|
||||
description:
|
||||
The standard Zihintntl extension for non-temporal locality hints, as
|
||||
ratified in commit 0dc91f5 ("Zihintntl is ratified") of the
|
||||
riscv-isa-manual.
|
||||
|
||||
- const: zihintpause
|
||||
description:
|
||||
The standard Zihintpause extension for pause hints, as ratified in
|
||||
commit d8ab5c7 ("Zihintpause is ratified") of the riscv-isa-manual.
|
||||
|
||||
- const: zihpm
|
||||
description:
|
||||
The standard Zihpm extension for hardware performance counters, as
|
||||
ratified in the 20191213 version of the unprivileged ISA
|
||||
specification.
|
||||
|
||||
- const: zilsd
|
||||
description:
|
||||
The standard Zilsd extension which provides support for aligned
|
||||
|
|
@ -521,12 +604,10 @@ properties:
|
|||
encodings, as ratified in commit f88abf1 ("Integrating
|
||||
load/store pair for RV32 with the main manual") of riscv-isa-manual.
|
||||
|
||||
- const: zclsd
|
||||
- const: zimop
|
||||
description:
|
||||
The Zclsd extension implements the compressed (16-bit) version of the
|
||||
Load/Store Pair for RV32. As with Zilsd, this extension was ratified
|
||||
in commit f88abf1 ("Integrating load/store pair for RV32 with the
|
||||
main manual") of riscv-isa-manual.
|
||||
The standard Zimop extension version 1.0, as ratified in commit
|
||||
58220614a5f ("Zimop is ratified/1.0") of the riscv-isa-manual.
|
||||
|
||||
- const: zk
|
||||
description:
|
||||
|
|
@ -590,87 +671,6 @@ properties:
|
|||
in version 1.0 of RISC-V Cryptography Extensions Volume I
|
||||
specification.
|
||||
|
||||
- const: zicbom
|
||||
description:
|
||||
The standard Zicbom extension for base cache management operations as
|
||||
ratified in commit 3dd606f ("Create cmobase-v1.0.pdf") of riscv-CMOs.
|
||||
|
||||
- const: zicbop
|
||||
description:
|
||||
The standard Zicbop extension for cache-block prefetch instructions
|
||||
as ratified in commit 3dd606f ("Create cmobase-v1.0.pdf") of
|
||||
riscv-CMOs.
|
||||
|
||||
- const: zicboz
|
||||
description:
|
||||
The standard Zicboz extension for cache-block zeroing as ratified
|
||||
in commit 3dd606f ("Create cmobase-v1.0.pdf") of riscv-CMOs.
|
||||
|
||||
- const: zicfilp
|
||||
description: |
|
||||
The standard Zicfilp extension for enforcing forward edge
|
||||
control-flow integrity as ratified in commit 3f8e450 ("merge
|
||||
pull request #227 from ved-rivos/0709") of riscv-cfi
|
||||
github repo.
|
||||
|
||||
- const: zicfiss
|
||||
description: |
|
||||
The standard Zicfiss extension for enforcing backward edge
|
||||
control-flow integrity as ratified in commit 3f8e450 ("merge
|
||||
pull request #227 from ved-rivos/0709") of riscv-cfi
|
||||
github repo.
|
||||
|
||||
- const: zicntr
|
||||
description:
|
||||
The standard Zicntr extension for base counters and timers, as
|
||||
ratified in the 20191213 version of the unprivileged ISA
|
||||
specification.
|
||||
|
||||
- const: zicond
|
||||
description:
|
||||
The standard Zicond extension for conditional arithmetic and
|
||||
conditional-select/move operations as ratified in commit 95cf1f9
|
||||
("Add changes requested by Ved during signoff") of riscv-zicond.
|
||||
|
||||
- const: zicsr
|
||||
description: |
|
||||
The standard Zicsr extension for control and status register
|
||||
instructions, as ratified in the 20191213 version of the
|
||||
unprivileged ISA specification.
|
||||
|
||||
This does not include Chapter 10, "Counters", which documents
|
||||
special case read-only CSRs, that were moved into the Zicntr and
|
||||
Zihpm extensions after the ratification of the 20191213 version of
|
||||
the unprivileged specification.
|
||||
|
||||
- const: zifencei
|
||||
description:
|
||||
The standard Zifencei extension for instruction-fetch fence, as
|
||||
ratified in the 20191213 version of the unprivileged ISA
|
||||
specification.
|
||||
|
||||
- const: zihintpause
|
||||
description:
|
||||
The standard Zihintpause extension for pause hints, as ratified in
|
||||
commit d8ab5c7 ("Zihintpause is ratified") of the riscv-isa-manual.
|
||||
|
||||
- const: zihintntl
|
||||
description:
|
||||
The standard Zihintntl extension for non-temporal locality hints, as
|
||||
ratified in commit 0dc91f5 ("Zihintntl is ratified") of the
|
||||
riscv-isa-manual.
|
||||
|
||||
- const: zihpm
|
||||
description:
|
||||
The standard Zihpm extension for hardware performance counters, as
|
||||
ratified in the 20191213 version of the unprivileged ISA
|
||||
specification.
|
||||
|
||||
- const: zimop
|
||||
description:
|
||||
The standard Zimop extension version 1.0, as ratified in commit
|
||||
58220614a5f ("Zimop is ratified/1.0") of the riscv-isa-manual.
|
||||
|
||||
- const: ztso
|
||||
description:
|
||||
The standard Ztso extension for total store ordering, as ratified
|
||||
|
|
@ -809,18 +809,18 @@ properties:
|
|||
instructions, as ratified in commit 56ed795 ("Update
|
||||
riscv-crypto-spec-vector.adoc") of riscv-crypto.
|
||||
|
||||
- const: zvksh
|
||||
description: |
|
||||
The standard Zvksh extension for ShangMi suite: SM3 secure hash
|
||||
instructions, as ratified in commit 56ed795 ("Update
|
||||
riscv-crypto-spec-vector.adoc") of riscv-crypto.
|
||||
|
||||
- const: zvksg
|
||||
description:
|
||||
The standard Zvksg extension for ShangMi algorithm suite with GCM
|
||||
instructions, as ratified in commit 56ed795 ("Update
|
||||
riscv-crypto-spec-vector.adoc") of riscv-crypto.
|
||||
|
||||
- const: zvksh
|
||||
description: |
|
||||
The standard Zvksh extension for ShangMi suite: SM3 secure hash
|
||||
instructions, as ratified in commit 56ed795 ("Update
|
||||
riscv-crypto-spec-vector.adoc") of riscv-crypto.
|
||||
|
||||
- const: zvkt
|
||||
description:
|
||||
The standard Zvkt extension for vector data-independent execution
|
||||
|
|
|
|||
|
|
@ -308,7 +308,7 @@ an involved disclosed party. The current ambassadors list:
|
|||
|
||||
Google Kees Cook <keescook@chromium.org>
|
||||
|
||||
LLVM Nick Desaulniers <nick.desaulniers+lkml@gmail.com>
|
||||
LLVM Nick Desaulniers <ndesaulniers@google.com>
|
||||
============= ========================================================
|
||||
|
||||
If you want your organization to be added to the ambassadors list, please
|
||||
|
|
|
|||
|
|
@ -287,7 +287,7 @@ revelada involucrada. La lista de embajadores actuales:
|
|||
|
||||
Google Kees Cook <keescook@chromium.org>
|
||||
|
||||
LLVM Nick Desaulniers <nick.desaulniers+lkml@gmail.com>
|
||||
LLVM Nick Desaulniers <ndesaulniers@google.com>
|
||||
============= ========================================================
|
||||
|
||||
Si quiere que su organización se añada a la lista de embajadores, por
|
||||
|
|
|
|||
|
|
@ -6342,7 +6342,7 @@ F: .clang-format
|
|||
|
||||
CLANG/LLVM BUILD SUPPORT
|
||||
M: Nathan Chancellor <nathan@kernel.org>
|
||||
R: Nick Desaulniers <nick.desaulniers+lkml@gmail.com>
|
||||
R: Nick Desaulniers <ndesaulniers@google.com>
|
||||
R: Bill Wendling <morbo@google.com>
|
||||
R: Justin Stitt <justinstitt@google.com>
|
||||
L: llvm@lists.linux.dev
|
||||
|
|
@ -17204,6 +17204,7 @@ R: Liam R. Howlett <liam@infradead.org>
|
|||
R: Vlastimil Babka <vbabka@kernel.org>
|
||||
R: Harry Yoo <harry@kernel.org>
|
||||
R: Jann Horn <jannh@google.com>
|
||||
R: Lance Yang <lance.yang@linux.dev>
|
||||
L: linux-mm@kvack.org
|
||||
S: Maintained
|
||||
F: include/linux/rmap.h
|
||||
|
|
@ -20405,7 +20406,7 @@ F: kernel/padata.c
|
|||
|
||||
PAGE CACHE
|
||||
M: Matthew Wilcox (Oracle) <willy@infradead.org>
|
||||
R: Jan Kara <jack@suse.cz>
|
||||
M: Jan Kara <jack@suse.cz>
|
||||
L: linux-fsdevel@vger.kernel.org
|
||||
L: linux-mm@kvack.org
|
||||
S: Supported
|
||||
|
|
@ -28054,6 +28055,7 @@ F: include/dt-bindings/usb/
|
|||
F: include/linux/usb.h
|
||||
F: include/linux/usb/
|
||||
F: include/uapi/linux/usb/
|
||||
F: rust/kernel/usb.rs
|
||||
|
||||
USB TYPEC BUS FOR ALTERNATE MODES
|
||||
M: Heikki Krogerus <heikki.krogerus@linux.intel.com>
|
||||
|
|
|
|||
2
Makefile
2
Makefile
|
|
@ -2,7 +2,7 @@
|
|||
VERSION = 7
|
||||
PATCHLEVEL = 2
|
||||
SUBLEVEL = 0
|
||||
EXTRAVERSION = -rc2
|
||||
EXTRAVERSION = -rc3
|
||||
NAME = Baby Opossum Posse
|
||||
|
||||
# *DOCUMENTATION*
|
||||
|
|
|
|||
|
|
@ -2,17 +2,11 @@
|
|||
#ifndef _ARCH_ARM64_TLBBATCH_H
|
||||
#define _ARCH_ARM64_TLBBATCH_H
|
||||
|
||||
#include <linux/cpumask.h>
|
||||
|
||||
struct arch_tlbflush_unmap_batch {
|
||||
#ifdef CONFIG_ARM64_ERRATUM_4193714
|
||||
/*
|
||||
* Track CPUs that need SME DVMSync on completion of this batch.
|
||||
* Otherwise, the arm64 HW can do tlb shootdown, so we don't need to
|
||||
* record cpumask for sending IPI
|
||||
* For arm64, HW can do TLB shootdown, so we don't need to record a
|
||||
* cpumask for sending IPIs.
|
||||
*/
|
||||
cpumask_var_t cpumask;
|
||||
#endif
|
||||
};
|
||||
|
||||
#endif /* _ARCH_ARM64_TLBBATCH_H */
|
||||
|
|
|
|||
|
|
@ -82,6 +82,8 @@ static inline unsigned long get_trans_granule(void)
|
|||
|
||||
#ifdef CONFIG_ARM64_ERRATUM_4193714
|
||||
|
||||
extern cpumask_t sme_active_cpus;
|
||||
|
||||
void sme_do_dvmsync(const struct cpumask *mask);
|
||||
|
||||
static inline void sme_dvmsync(struct mm_struct *mm)
|
||||
|
|
@ -92,42 +94,12 @@ static inline void sme_dvmsync(struct mm_struct *mm)
|
|||
sme_do_dvmsync(mm_cpumask(mm));
|
||||
}
|
||||
|
||||
static inline void sme_dvmsync_add_pending(struct arch_tlbflush_unmap_batch *batch,
|
||||
struct mm_struct *mm)
|
||||
static inline void sme_dvmsync_batch(void)
|
||||
{
|
||||
if (!alternative_has_cap_unlikely(ARM64_WORKAROUND_4193714))
|
||||
return;
|
||||
|
||||
/*
|
||||
* Order the mm_cpumask() read after the hardware DVMSync.
|
||||
*/
|
||||
dsb(ish);
|
||||
if (cpumask_empty(mm_cpumask(mm)))
|
||||
return;
|
||||
|
||||
/*
|
||||
* Allocate the batch cpumask on first use. Fall back to an immediate
|
||||
* IPI for this mm in case of failure.
|
||||
*/
|
||||
if (!cpumask_available(batch->cpumask) &&
|
||||
!zalloc_cpumask_var(&batch->cpumask, GFP_ATOMIC)) {
|
||||
sme_do_dvmsync(mm_cpumask(mm));
|
||||
return;
|
||||
}
|
||||
|
||||
cpumask_or(batch->cpumask, batch->cpumask, mm_cpumask(mm));
|
||||
}
|
||||
|
||||
static inline void sme_dvmsync_batch(struct arch_tlbflush_unmap_batch *batch)
|
||||
{
|
||||
if (!alternative_has_cap_unlikely(ARM64_WORKAROUND_4193714))
|
||||
return;
|
||||
|
||||
if (!cpumask_available(batch->cpumask))
|
||||
return;
|
||||
|
||||
sme_do_dvmsync(batch->cpumask);
|
||||
cpumask_clear(batch->cpumask);
|
||||
sme_do_dvmsync(&sme_active_cpus);
|
||||
}
|
||||
|
||||
#else
|
||||
|
|
@ -135,11 +107,7 @@ static inline void sme_dvmsync_batch(struct arch_tlbflush_unmap_batch *batch)
|
|||
static inline void sme_dvmsync(struct mm_struct *mm)
|
||||
{
|
||||
}
|
||||
static inline void sme_dvmsync_add_pending(struct arch_tlbflush_unmap_batch *batch,
|
||||
struct mm_struct *mm)
|
||||
{
|
||||
}
|
||||
static inline void sme_dvmsync_batch(struct arch_tlbflush_unmap_batch *batch)
|
||||
static inline void sme_dvmsync_batch(void)
|
||||
{
|
||||
}
|
||||
|
||||
|
|
@ -285,11 +253,11 @@ static inline void __tlbi_sync_s1ish(struct mm_struct *mm)
|
|||
sme_dvmsync(mm);
|
||||
}
|
||||
|
||||
static inline void __tlbi_sync_s1ish_batch(struct arch_tlbflush_unmap_batch *batch)
|
||||
static inline void __tlbi_sync_s1ish_batch(void)
|
||||
{
|
||||
dsb(ish);
|
||||
__repeat_tlbi_sync(vale1is, 0);
|
||||
sme_dvmsync_batch(batch);
|
||||
sme_dvmsync_batch();
|
||||
}
|
||||
|
||||
static inline void __tlbi_sync_s1ish_kernel(void)
|
||||
|
|
@ -434,7 +402,7 @@ static inline bool arch_tlbbatch_should_defer(struct mm_struct *mm)
|
|||
*/
|
||||
static inline void arch_tlbbatch_flush(struct arch_tlbflush_unmap_batch *batch)
|
||||
{
|
||||
__tlbi_sync_s1ish_batch(batch);
|
||||
__tlbi_sync_s1ish_batch();
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -722,7 +690,6 @@ static inline void arch_tlbbatch_add_pending(struct arch_tlbflush_unmap_batch *b
|
|||
|
||||
__flush_tlb_range(&vma, start, end, PAGE_SIZE, 3,
|
||||
TLBF_NOWALKCACHE | TLBF_NOSYNC);
|
||||
sme_dvmsync_add_pending(batch, mm);
|
||||
}
|
||||
|
||||
static inline bool __pte_flags_need_flush(ptval_t oldval, ptval_t newval)
|
||||
|
|
|
|||
|
|
@ -448,12 +448,14 @@ int acpi_map_cpu(acpi_handle handle, phys_cpuid_t physid, u32 apci_id,
|
|||
return *pcpu;
|
||||
}
|
||||
|
||||
set_cpu_present(*pcpu, true);
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(acpi_map_cpu);
|
||||
|
||||
int acpi_unmap_cpu(int cpu)
|
||||
{
|
||||
set_cpu_present(cpu, false);
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(acpi_unmap_cpu);
|
||||
|
|
|
|||
|
|
@ -1355,6 +1355,7 @@ void do_sve_acc(unsigned long esr, struct pt_regs *regs)
|
|||
* SME/CME erratum handling.
|
||||
*/
|
||||
static cpumask_t sme_dvmsync_cpus;
|
||||
cpumask_t sme_active_cpus;
|
||||
|
||||
/*
|
||||
* These helpers are only called from non-preemptible contexts, so
|
||||
|
|
@ -1368,13 +1369,15 @@ void sme_set_active(void)
|
|||
return;
|
||||
|
||||
cpumask_set_cpu(cpu, mm_cpumask(current->mm));
|
||||
cpumask_set_cpu(cpu, &sme_active_cpus);
|
||||
|
||||
/*
|
||||
* A subsequent (post ERET) SME access may use a stale address
|
||||
* translation. On C1-Pro, a TLBI+DSB on a different CPU will wait for
|
||||
* the completion of cpumask_set_cpu() above as it appears in program
|
||||
* order before the SME access. The post-TLBI+DSB read of mm_cpumask()
|
||||
* will lead to the IPI being issued.
|
||||
* the completion of the cpumask_set_cpu() operations above as they
|
||||
* appear in program order before the SME access. The post-TLBI+DSB
|
||||
* read of mm_cpumask() or sme_active_cpus will lead to the IPI being
|
||||
* issued.
|
||||
*
|
||||
* https://lore.kernel.org/r/ablEXwhfKyJW1i7l@J2N7QTR9R3
|
||||
*/
|
||||
|
|
@ -1392,6 +1395,7 @@ void sme_clear_active(void)
|
|||
* completed on entering EL1.
|
||||
*/
|
||||
cpumask_clear_cpu(cpu, mm_cpumask(current->mm));
|
||||
cpumask_clear_cpu(cpu, &sme_active_cpus);
|
||||
}
|
||||
|
||||
static void sme_dvmsync_ipi(void *unused)
|
||||
|
|
|
|||
|
|
@ -341,41 +341,8 @@ void flush_thread(void)
|
|||
flush_gcs();
|
||||
}
|
||||
|
||||
#ifdef CONFIG_ARM64_ERRATUM_4193714
|
||||
|
||||
static void arch_dup_tlbbatch_mask(struct task_struct *dst)
|
||||
{
|
||||
/*
|
||||
* Clear the inherited cpumask with memset() to cover both cases where
|
||||
* cpumask_var_t is a pointer or an array. It will be allocated lazily
|
||||
* in sme_dvmsync_add_pending() if CPUMASK_OFFSTACK=y.
|
||||
*/
|
||||
if (alternative_has_cap_unlikely(ARM64_WORKAROUND_4193714))
|
||||
memset(&dst->tlb_ubc.arch.cpumask, 0,
|
||||
sizeof(dst->tlb_ubc.arch.cpumask));
|
||||
}
|
||||
|
||||
static void arch_release_tlbbatch_mask(struct task_struct *tsk)
|
||||
{
|
||||
if (alternative_has_cap_unlikely(ARM64_WORKAROUND_4193714))
|
||||
free_cpumask_var(tsk->tlb_ubc.arch.cpumask);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
static void arch_dup_tlbbatch_mask(struct task_struct *dst)
|
||||
{
|
||||
}
|
||||
|
||||
static void arch_release_tlbbatch_mask(struct task_struct *tsk)
|
||||
{
|
||||
}
|
||||
|
||||
#endif /* CONFIG_ARM64_ERRATUM_4193714 */
|
||||
|
||||
void arch_release_task_struct(struct task_struct *tsk)
|
||||
{
|
||||
arch_release_tlbbatch_mask(tsk);
|
||||
fpsimd_release_task(tsk);
|
||||
}
|
||||
|
||||
|
|
@ -391,8 +358,6 @@ int arch_dup_task_struct(struct task_struct *dst, struct task_struct *src)
|
|||
|
||||
*dst = *src;
|
||||
|
||||
arch_dup_tlbbatch_mask(dst);
|
||||
|
||||
/*
|
||||
* Drop stale reference to src's sve_state and convert dst to
|
||||
* non-streaming FPSIMD mode.
|
||||
|
|
|
|||
|
|
@ -535,23 +535,13 @@ void arch_unregister_cpu(int cpu)
|
|||
{
|
||||
acpi_handle acpi_handle = acpi_get_processor_handle(cpu);
|
||||
struct cpu *c = &per_cpu(cpu_devices, cpu);
|
||||
acpi_status status;
|
||||
unsigned long long sta;
|
||||
|
||||
if (!acpi_handle) {
|
||||
pr_err_once("Removing a CPU without associated ACPI handle\n");
|
||||
return;
|
||||
}
|
||||
acpi_status status;
|
||||
|
||||
status = acpi_evaluate_integer(acpi_handle, "_STA", NULL, &sta);
|
||||
if (ACPI_FAILURE(status))
|
||||
return;
|
||||
|
||||
/* For now do not allow anything that looks like physical CPU HP */
|
||||
if (cpu_present(cpu) && !(sta & ACPI_STA_DEVICE_PRESENT)) {
|
||||
if (!ACPI_FAILURE(status) &&
|
||||
cpu_present(cpu) && !(sta & ACPI_STA_DEVICE_PRESENT))
|
||||
pr_err_once("Changing CPU present bit is not supported\n");
|
||||
return;
|
||||
}
|
||||
|
||||
unregister_cpu(c);
|
||||
}
|
||||
|
|
@ -566,6 +556,11 @@ struct acpi_madt_generic_interrupt *acpi_cpu_get_madt_gicc(int cpu)
|
|||
}
|
||||
EXPORT_SYMBOL_GPL(acpi_cpu_get_madt_gicc);
|
||||
|
||||
static bool acpi_cpu_is_present(int cpu)
|
||||
{
|
||||
return acpi_cpu_get_madt_gicc(cpu)->flags & ACPI_MADT_ENABLED;
|
||||
}
|
||||
|
||||
/*
|
||||
* acpi_map_gic_cpu_interface - parse processor MADT entry
|
||||
*
|
||||
|
|
@ -670,6 +665,10 @@ static void __init acpi_parse_and_init_cpus(void)
|
|||
early_map_cpu_to_node(i, acpi_numa_get_nid(i));
|
||||
}
|
||||
#else
|
||||
static bool acpi_cpu_is_present(int cpu)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
#define acpi_parse_and_init_cpus(...) do { } while (0)
|
||||
#endif
|
||||
|
||||
|
|
@ -814,7 +813,8 @@ void __init smp_prepare_cpus(unsigned int max_cpus)
|
|||
if (err)
|
||||
continue;
|
||||
|
||||
set_cpu_present(cpu, true);
|
||||
if (acpi_disabled || acpi_cpu_is_present(cpu))
|
||||
set_cpu_present(cpu, true);
|
||||
numa_store_cpu_info(cpu);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1515,7 +1515,13 @@ static void unmap_hotplug_pmd_range(pud_t *pudp, unsigned long addr,
|
|||
if (free_mapped) {
|
||||
/* CONT blocks are not supported in the vmemmap */
|
||||
WARN_ON(pmd_cont(pmd));
|
||||
flush_tlb_kernel_range(addr, addr + PMD_SIZE);
|
||||
/*
|
||||
* Invalidating a block entry requires just
|
||||
* a single overlapping TLB invalidation,
|
||||
* so limit the range of the flush to a single
|
||||
* page.
|
||||
*/
|
||||
flush_tlb_kernel_range(addr, addr + PAGE_SIZE);
|
||||
free_hotplug_page_range(pmd_page(pmd),
|
||||
PMD_SIZE, altmap);
|
||||
}
|
||||
|
|
@ -1545,7 +1551,8 @@ static void unmap_hotplug_pud_range(p4d_t *p4dp, unsigned long addr,
|
|||
if (pud_leaf(pud)) {
|
||||
pud_clear(pudp);
|
||||
if (free_mapped) {
|
||||
flush_tlb_kernel_range(addr, addr + PUD_SIZE);
|
||||
/* See comment in unmap_hotplug_pmd_range(). */
|
||||
flush_tlb_kernel_range(addr, addr + PAGE_SIZE);
|
||||
free_hotplug_page_range(pud_page(pud),
|
||||
PUD_SIZE, altmap);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1806,7 +1806,7 @@ Res0 15:8
|
|||
UnsignedEnum 7:4 BWE
|
||||
0b0000 NI
|
||||
0b0001 FEAT_BWE
|
||||
0b0002 FEAT_BWE2
|
||||
0b0010 FEAT_BWE2
|
||||
EndEnum
|
||||
UnsignedEnum 3:0 STEP
|
||||
0b0000 NI
|
||||
|
|
|
|||
|
|
@ -79,7 +79,7 @@ static void __init m523x_i2c_init(void)
|
|||
static void __init m523x_fec_init(void)
|
||||
{
|
||||
/* Set multi-function pins to ethernet use */
|
||||
mcf_write8(read8(MCFGPIO_PAR_FECI2C) | 0xf0, MCFGPIO_PAR_FECI2C);
|
||||
mcf_write8(mcf_read8(MCFGPIO_PAR_FECI2C) | 0xf0, MCFGPIO_PAR_FECI2C);
|
||||
}
|
||||
|
||||
/***************************************************************************/
|
||||
|
|
|
|||
|
|
@ -113,11 +113,11 @@ void wildfiremod_halt(void)
|
|||
mcf_write16(read16(MCFGPIO_PEPAR) & ~(1 << (5 * 2)), MCFGPIO_PEPAR);
|
||||
|
||||
/* Make portE.5 an output */
|
||||
mcf_write8(read8(MCFGPIO_PDDR_E) | (1 << 5), MCFGPIO_PDDR_E);
|
||||
mcf_write8(mcf_read8(MCFGPIO_PDDR_E) | (1 << 5), MCFGPIO_PDDR_E);
|
||||
|
||||
/* Now toggle portE.5 from low to high */
|
||||
mcf_write8(read8(MCFGPIO_PODR_E) & ~(1 << 5), MCFGPIO_PODR_E);
|
||||
mcf_write8(read8(MCFGPIO_PODR_E) | (1 << 5), MCFGPIO_PODR_E);
|
||||
mcf_write8(mcf_read8(MCFGPIO_PODR_E) & ~(1 << 5), MCFGPIO_PODR_E);
|
||||
mcf_write8(mcf_read8(MCFGPIO_PODR_E) | (1 << 5), MCFGPIO_PODR_E);
|
||||
|
||||
printk(KERN_EMERG "Failed to hibernate. Halting!\n");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -84,6 +84,12 @@ config ARCH_THEAD
|
|||
help
|
||||
This enables support for the RISC-V based T-HEAD SoCs.
|
||||
|
||||
config ARCH_ULTRARISC
|
||||
bool "UltraRISC RISC-V SoCs"
|
||||
help
|
||||
This enables support for UltraRISC SoC platform hardware,
|
||||
including boards based on the UR-DP1000.
|
||||
|
||||
config ARCH_VIRT
|
||||
bool "QEMU Virt Machine"
|
||||
select POWER_RESET
|
||||
|
|
|
|||
|
|
@ -33,6 +33,7 @@ CONFIG_SOC_STARFIVE=y
|
|||
CONFIG_ARCH_SUNXI=y
|
||||
CONFIG_ARCH_TENSTORRENT=y
|
||||
CONFIG_ARCH_THEAD=y
|
||||
CONFIG_ARCH_ULTRARISC=y
|
||||
CONFIG_ARCH_VIRT=y
|
||||
CONFIG_ARCH_CANAAN=y
|
||||
CONFIG_SMP=y
|
||||
|
|
|
|||
|
|
@ -41,6 +41,9 @@ machine_kexec_prepare(struct kimage *image)
|
|||
if (image->segment[i].memsz <= sizeof(fdt))
|
||||
continue;
|
||||
|
||||
if (!image->segment[i].buf)
|
||||
continue;
|
||||
|
||||
if (image->file_mode)
|
||||
memcpy(&fdt, image->segment[i].buf, sizeof(fdt));
|
||||
else if (copy_from_user(&fdt, image->segment[i].buf, sizeof(fdt)))
|
||||
|
|
|
|||
|
|
@ -190,17 +190,18 @@ static int memtop_get_stride_len(unsigned long *res)
|
|||
static int memtop_get_page_count(unsigned long *res, unsigned long level)
|
||||
{
|
||||
static unsigned long memtop_pages[DIAG310_LEVELMAX];
|
||||
unsigned long pages;
|
||||
unsigned long pages, idx;
|
||||
int rc;
|
||||
|
||||
if (level > DIAG310_LEVELMAX || level < DIAG310_LEVELMIN)
|
||||
return -EINVAL;
|
||||
pages = READ_ONCE(memtop_pages[level - 1]);
|
||||
idx = array_index_nospec(level - 1, ARRAY_SIZE(memtop_pages));
|
||||
pages = READ_ONCE(memtop_pages[idx]);
|
||||
if (!pages) {
|
||||
rc = diag310_get_memtop_size(&pages, level);
|
||||
if (rc)
|
||||
return rc;
|
||||
WRITE_ONCE(memtop_pages[level - 1], pages);
|
||||
WRITE_ONCE(memtop_pages[idx], pages);
|
||||
}
|
||||
*res = pages;
|
||||
return 0;
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@
|
|||
* Here we can supply some information useful to userland.
|
||||
*/
|
||||
|
||||
#include <linux/build-salt.h>
|
||||
#include <linux/uts.h>
|
||||
#include <linux/version.h>
|
||||
#include <linux/elfnote.h>
|
||||
|
|
@ -11,3 +12,5 @@
|
|||
ELFNOTE_START(Linux, 0, "a")
|
||||
.long LINUX_VERSION_CODE
|
||||
ELFNOTE_END
|
||||
|
||||
BUILD_SALT
|
||||
|
|
|
|||
|
|
@ -64,7 +64,7 @@ static inline unsigned long mmap_base(unsigned long rnd,
|
|||
return PAGE_ALIGN(STACK_TOP - gap - rnd);
|
||||
}
|
||||
|
||||
static int get_align_mask(struct file *filp, unsigned long flags)
|
||||
static unsigned long get_align_mask(struct file *filp, unsigned long flags)
|
||||
{
|
||||
if (filp && is_file_hugepages(filp))
|
||||
return huge_page_mask_align(filp);
|
||||
|
|
|
|||
|
|
@ -259,13 +259,13 @@ void amd_brs_disable_all(void)
|
|||
amd_brs_disable();
|
||||
}
|
||||
|
||||
static bool amd_brs_match_plm(struct perf_event *event, u64 to)
|
||||
static bool amd_brs_match_plm(struct perf_event *event, u64 from, u64 to)
|
||||
{
|
||||
int type = event->attr.branch_sample_type;
|
||||
int plm_k = PERF_SAMPLE_BRANCH_KERNEL | PERF_SAMPLE_BRANCH_HV;
|
||||
int plm_u = PERF_SAMPLE_BRANCH_USER;
|
||||
|
||||
if (!(type & plm_k) && kernel_ip(to))
|
||||
if (!(type & plm_k) && (kernel_ip(to) || kernel_ip(from)))
|
||||
return 0;
|
||||
|
||||
if (!(type & plm_u) && !kernel_ip(to))
|
||||
|
|
@ -338,11 +338,11 @@ void amd_brs_drain(void)
|
|||
*/
|
||||
to = (u64)(((s64)to << shift) >> shift);
|
||||
|
||||
if (!amd_brs_match_plm(event, to))
|
||||
continue;
|
||||
|
||||
rdmsrq(brs_from(brs_idx), from);
|
||||
|
||||
if (!amd_brs_match_plm(event, from, to))
|
||||
continue;
|
||||
|
||||
perf_clear_branch_entry_bitfields(br+nr);
|
||||
|
||||
br[nr].from = from;
|
||||
|
|
|
|||
|
|
@ -754,13 +754,11 @@ static void amd_pmu_enable_event(struct perf_event *event)
|
|||
x86_pmu_enable_event(event);
|
||||
}
|
||||
|
||||
static void amd_pmu_enable_all(int added)
|
||||
static void __amd_pmu_enable_all(void)
|
||||
{
|
||||
struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events);
|
||||
int idx;
|
||||
|
||||
amd_brs_enable_all();
|
||||
|
||||
for_each_set_bit(idx, x86_pmu.cntr_mask, X86_PMC_IDX_MAX) {
|
||||
/* only activate events which are marked as active */
|
||||
if (!test_bit(idx, cpuc->active_mask))
|
||||
|
|
@ -775,6 +773,12 @@ static void amd_pmu_enable_all(int added)
|
|||
}
|
||||
}
|
||||
|
||||
static void amd_pmu_enable_all(int added)
|
||||
{
|
||||
amd_brs_enable_all();
|
||||
__amd_pmu_enable_all();
|
||||
}
|
||||
|
||||
static void amd_pmu_v2_enable_event(struct perf_event *event)
|
||||
{
|
||||
struct hw_perf_event *hwc = &event->hw;
|
||||
|
|
@ -1561,7 +1565,7 @@ static inline void amd_pmu_reload_virt(void)
|
|||
* set global enable bits once again
|
||||
*/
|
||||
amd_pmu_v2_disable_all();
|
||||
amd_pmu_enable_all(0);
|
||||
__amd_pmu_enable_all();
|
||||
amd_pmu_v2_enable_all(0);
|
||||
return;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -127,7 +127,8 @@ static void amd_pmu_lbr_filter(void)
|
|||
}
|
||||
|
||||
/* If type does not correspond, then discard */
|
||||
if (type == X86_BR_NONE || (br_sel & type) != type) {
|
||||
if (type == X86_BR_NONE || (br_sel & type) != type ||
|
||||
(!(br_sel & X86_BR_KERNEL) && kernel_ip(cpuc->lbr_entries[i].from))) {
|
||||
cpuc->lbr_entries[i].from = 0; /* mark invalid */
|
||||
compress = true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -43,21 +43,26 @@ bool video_is_primary_device(struct device *dev)
|
|||
if (!pci_is_display(pdev))
|
||||
return false;
|
||||
|
||||
if (pdev == vga_default_device())
|
||||
return true;
|
||||
|
||||
#ifdef CONFIG_SCREEN_INFO
|
||||
numres = screen_info_resources(si, res, ARRAY_SIZE(res));
|
||||
for (i = 0; i < numres; ++i) {
|
||||
if (!(res[i].flags & IORESOURCE_MEM))
|
||||
continue;
|
||||
if (numres > 0) {
|
||||
for (i = 0; i < numres; ++i) {
|
||||
if (!(res[i].flags & IORESOURCE_MEM))
|
||||
continue;
|
||||
|
||||
if (pci_find_resource(pdev, &res[i]))
|
||||
return true;
|
||||
if (pci_find_resource(pdev, &res[i]))
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
return false;
|
||||
/*
|
||||
* No framebuffer was set up by the firmware/bootloader, so fall back
|
||||
* to the default VGA device.
|
||||
*/
|
||||
return pdev == vga_default_device();
|
||||
}
|
||||
EXPORT_SYMBOL(video_is_primary_device);
|
||||
|
||||
|
|
|
|||
|
|
@ -536,6 +536,8 @@ int snp_prepare(void)
|
|||
goto unlock;
|
||||
}
|
||||
|
||||
wbinvd_on_all_cpus();
|
||||
|
||||
/*
|
||||
* MtrrFixDramModEn is not shared between threads on a core,
|
||||
* therefore it must be set on all CPUs prior to enabling SNP.
|
||||
|
|
|
|||
|
|
@ -5218,6 +5218,7 @@ static int blk_hctx_poll(struct request_queue *q, struct blk_mq_hw_ctx *hctx,
|
|||
struct io_comp_batch *iob, unsigned int flags)
|
||||
{
|
||||
int ret;
|
||||
unsigned long timeout = jiffies + 2;
|
||||
|
||||
do {
|
||||
ret = q->mq_ops->poll(hctx, iob);
|
||||
|
|
@ -5228,7 +5229,7 @@ static int blk_hctx_poll(struct request_queue *q, struct blk_mq_hw_ctx *hctx,
|
|||
if (ret < 0 || (flags & BLK_POLL_ONESHOT))
|
||||
break;
|
||||
cpu_relax();
|
||||
} while (!need_resched());
|
||||
} while (!need_resched() && time_before(jiffies, timeout));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -813,6 +813,21 @@ static void wbt_queue_depth_changed(struct rq_qos *rqos)
|
|||
wbt_update_limits(RQWB(rqos));
|
||||
}
|
||||
|
||||
static bool wbt_set_lat_changed(struct request_queue *q, u64 val)
|
||||
{
|
||||
struct rq_qos *rqos = wbt_rq_qos(q);
|
||||
struct rq_wb *rwb;
|
||||
|
||||
if (!rqos)
|
||||
return true;
|
||||
|
||||
rwb = RQWB(rqos);
|
||||
if (rwb->min_lat_nsec != val)
|
||||
return true;
|
||||
|
||||
return rwb_enabled(rwb) != !!val;
|
||||
}
|
||||
|
||||
static void wbt_exit(struct rq_qos *rqos)
|
||||
{
|
||||
struct rq_wb *rwb = RQWB(rqos);
|
||||
|
|
@ -1005,8 +1020,12 @@ int wbt_set_lat(struct gendisk *disk, s64 val)
|
|||
else if (val >= 0)
|
||||
val *= 1000ULL;
|
||||
|
||||
if (wbt_get_min_lat(q) == val)
|
||||
mutex_lock(&disk->rqos_state_mutex);
|
||||
if (!wbt_set_lat_changed(q, val)) {
|
||||
mutex_unlock(&disk->rqos_state_mutex);
|
||||
goto out;
|
||||
}
|
||||
mutex_unlock(&disk->rqos_state_mutex);
|
||||
|
||||
blk_mq_quiesce_queue(q);
|
||||
|
||||
|
|
|
|||
|
|
@ -1923,11 +1923,20 @@ static int disk_alloc_zone_resources(struct gendisk *disk,
|
|||
if (!disk->zone_wplugs_pool)
|
||||
goto free_hash;
|
||||
|
||||
disk->zone_wplugs_wq =
|
||||
alloc_workqueue("%s_zwplugs", WQ_MEM_RECLAIM | WQ_HIGHPRI | WQ_PERCPU,
|
||||
pool_size, disk->disk_name);
|
||||
if (!disk->zone_wplugs_wq)
|
||||
goto destroy_pool;
|
||||
/*
|
||||
* We may already have a zone write plug workqueue as this function may
|
||||
* be called after disk_free_zone_resources(), which does not destroy
|
||||
* the workqueue (the zone write plugs workqueue is destroyed at
|
||||
* disk_release() time).
|
||||
*/
|
||||
if (!disk->zone_wplugs_wq) {
|
||||
disk->zone_wplugs_wq =
|
||||
alloc_workqueue("%s_zwplugs",
|
||||
WQ_MEM_RECLAIM | WQ_HIGHPRI | WQ_PERCPU,
|
||||
pool_size, disk->disk_name);
|
||||
if (!disk->zone_wplugs_wq)
|
||||
goto destroy_pool;
|
||||
}
|
||||
|
||||
disk->zone_wplugs_worker =
|
||||
kthread_create(disk_zone_wplugs_worker, disk,
|
||||
|
|
@ -1935,15 +1944,12 @@ static int disk_alloc_zone_resources(struct gendisk *disk,
|
|||
if (IS_ERR(disk->zone_wplugs_worker)) {
|
||||
ret = PTR_ERR(disk->zone_wplugs_worker);
|
||||
disk->zone_wplugs_worker = NULL;
|
||||
goto destroy_wq;
|
||||
goto destroy_pool;
|
||||
}
|
||||
wake_up_process(disk->zone_wplugs_worker);
|
||||
|
||||
return 0;
|
||||
|
||||
destroy_wq:
|
||||
destroy_workqueue(disk->zone_wplugs_wq);
|
||||
disk->zone_wplugs_wq = NULL;
|
||||
destroy_pool:
|
||||
mempool_destroy(disk->zone_wplugs_pool);
|
||||
disk->zone_wplugs_pool = NULL;
|
||||
|
|
@ -1999,7 +2005,7 @@ static void disk_set_zones_cond_array(struct gendisk *disk, u8 *zones_cond)
|
|||
kfree_rcu_mightsleep(zones_cond);
|
||||
}
|
||||
|
||||
void disk_free_zone_resources(struct gendisk *disk)
|
||||
static void disk_free_zone_resources(struct gendisk *disk)
|
||||
{
|
||||
if (disk->zone_wplugs_worker) {
|
||||
kthread_stop(disk->zone_wplugs_worker);
|
||||
|
|
@ -2007,10 +2013,8 @@ void disk_free_zone_resources(struct gendisk *disk)
|
|||
}
|
||||
WARN_ON_ONCE(!list_empty(&disk->zone_wplugs_list));
|
||||
|
||||
if (disk->zone_wplugs_wq) {
|
||||
destroy_workqueue(disk->zone_wplugs_wq);
|
||||
disk->zone_wplugs_wq = NULL;
|
||||
}
|
||||
if (disk->zone_wplugs_wq)
|
||||
drain_workqueue(disk->zone_wplugs_wq);
|
||||
|
||||
disk_destroy_zone_wplugs_hash_table(disk);
|
||||
|
||||
|
|
@ -2020,6 +2024,16 @@ void disk_free_zone_resources(struct gendisk *disk)
|
|||
disk->nr_zones = 0;
|
||||
}
|
||||
|
||||
void disk_release_zone_resources(struct gendisk *disk)
|
||||
{
|
||||
if (disk->zone_wplugs_wq) {
|
||||
destroy_workqueue(disk->zone_wplugs_wq);
|
||||
disk->zone_wplugs_wq = NULL;
|
||||
}
|
||||
|
||||
disk_free_zone_resources(disk);
|
||||
}
|
||||
|
||||
struct blk_revalidate_zone_args {
|
||||
struct gendisk *disk;
|
||||
u8 *zones_cond;
|
||||
|
|
|
|||
|
|
@ -528,7 +528,7 @@ static inline void ioc_clear_queue(struct request_queue *q)
|
|||
|
||||
#ifdef CONFIG_BLK_DEV_ZONED
|
||||
void disk_init_zone_resources(struct gendisk *disk);
|
||||
void disk_free_zone_resources(struct gendisk *disk);
|
||||
void disk_release_zone_resources(struct gendisk *disk);
|
||||
static inline bool bio_zone_write_plugging(struct bio *bio)
|
||||
{
|
||||
return bio_flagged(bio, BIO_ZONE_WRITE_PLUGGING);
|
||||
|
|
@ -581,7 +581,7 @@ int blkdev_zone_mgmt_ioctl(struct block_device *bdev, blk_mode_t mode,
|
|||
static inline void disk_init_zone_resources(struct gendisk *disk)
|
||||
{
|
||||
}
|
||||
static inline void disk_free_zone_resources(struct gendisk *disk)
|
||||
static inline void disk_release_zone_resources(struct gendisk *disk)
|
||||
{
|
||||
}
|
||||
static inline bool bio_zone_write_plugging(struct bio *bio)
|
||||
|
|
|
|||
|
|
@ -407,10 +407,6 @@ static void add_disk_final(struct gendisk *disk)
|
|||
struct device *ddev = disk_to_dev(disk);
|
||||
|
||||
if (!(disk->flags & GENHD_FL_HIDDEN)) {
|
||||
/* Make sure the first partition scan will be proceed */
|
||||
if (get_capacity(disk) && disk_has_partscan(disk))
|
||||
set_bit(GD_NEED_PART_SCAN, &disk->state);
|
||||
|
||||
bdev_add(disk->part0, ddev->devt);
|
||||
if (get_capacity(disk))
|
||||
disk_scan_partitions(disk, BLK_OPEN_READ);
|
||||
|
|
@ -1300,7 +1296,7 @@ static void disk_release(struct device *dev)
|
|||
|
||||
disk_release_events(disk);
|
||||
kfree(disk->random);
|
||||
disk_free_zone_resources(disk);
|
||||
disk_release_zone_resources(disk);
|
||||
xa_destroy(&disk->part_tbl);
|
||||
|
||||
kobject_put(&disk->queue_kobj);
|
||||
|
|
|
|||
|
|
@ -875,7 +875,7 @@ static int aie2_hwctx_cu_config(struct amdxdna_hwctx *hwctx, void *buf, u32 size
|
|||
if (!hwctx->cus)
|
||||
return -ENOMEM;
|
||||
|
||||
ret = amdxdna_pm_resume_get_locked(xdna);
|
||||
ret = amdxdna_pm_resume_get(xdna);
|
||||
if (ret)
|
||||
goto free_cus;
|
||||
|
||||
|
|
@ -900,13 +900,16 @@ static int aie2_hwctx_cu_config(struct amdxdna_hwctx *hwctx, void *buf, u32 size
|
|||
static void aie2_cmd_wait(struct amdxdna_hwctx *hwctx, u64 seq)
|
||||
{
|
||||
struct dma_fence *out_fence = aie2_cmd_get_out_fence(hwctx, seq);
|
||||
struct amdxdna_dev *xdna = hwctx->client->xdna;
|
||||
|
||||
if (!out_fence) {
|
||||
XDNA_ERR(hwctx->client->xdna, "Failed to get fence");
|
||||
XDNA_ERR(xdna, "Failed to get fence");
|
||||
return;
|
||||
}
|
||||
|
||||
mutex_unlock(&xdna->dev_lock);
|
||||
dma_fence_wait_timeout(out_fence, false, MAX_SCHEDULE_TIMEOUT);
|
||||
mutex_lock(&xdna->dev_lock);
|
||||
dma_fence_put(out_fence);
|
||||
}
|
||||
|
||||
|
|
@ -1039,7 +1042,7 @@ static int aie2_populate_range(struct amdxdna_gem_obj *abo)
|
|||
found = false;
|
||||
down_write(&xdna->notifier_lock);
|
||||
list_for_each_entry(mapp, &abo->mem.umap_list, node) {
|
||||
if (mapp->invalid) {
|
||||
if (mapp->invalid && kref_get_unless_zero(&mapp->refcnt)) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
|
|
@ -1050,11 +1053,9 @@ static int aie2_populate_range(struct amdxdna_gem_obj *abo)
|
|||
up_write(&xdna->notifier_lock);
|
||||
return 0;
|
||||
}
|
||||
kref_get(&mapp->refcnt);
|
||||
|
||||
up_write(&xdna->notifier_lock);
|
||||
|
||||
XDNA_DBG(xdna, "populate memory range %lx %lx",
|
||||
mapp->vma->vm_start, mapp->vma->vm_end);
|
||||
mm = mapp->notifier.mm;
|
||||
if (!mmget_not_zero(mm)) {
|
||||
amdxdna_umap_put(mapp);
|
||||
|
|
@ -1221,10 +1222,6 @@ int aie2_hwctx_heap_expand(struct amdxdna_hwctx *hwctx,
|
|||
u64 addr;
|
||||
int ret;
|
||||
|
||||
ret = amdxdna_pm_resume_get_locked(xdna);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
addr = amdxdna_obj_dma_addr(heap);
|
||||
ret = aie2_add_host_buf(xdna->dev_handle, hwctx->fw_ctx_id,
|
||||
addr, heap->mem.size);
|
||||
|
|
@ -1233,7 +1230,5 @@ int aie2_hwctx_heap_expand(struct amdxdna_hwctx *hwctx,
|
|||
hwctx->name, heap->mem.size, ret);
|
||||
}
|
||||
|
||||
amdxdna_pm_suspend_put(xdna);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -840,7 +840,7 @@ static struct aie2_exec_msg_ops npu_exec_message_ops = {
|
|||
static int aie2_init_exec_req(void *req, struct amdxdna_gem_obj *cmd_abo,
|
||||
size_t *size, u32 *msg_op)
|
||||
{
|
||||
struct amdxdna_dev *xdna = cmd_abo->client->xdna;
|
||||
struct amdxdna_dev *xdna = to_xdna_dev(to_gobj(cmd_abo)->dev);
|
||||
int ret;
|
||||
u32 op;
|
||||
|
||||
|
|
@ -874,7 +874,7 @@ static int
|
|||
aie2_cmdlist_fill_slot(void *slot, struct amdxdna_gem_obj *cmd_abo,
|
||||
size_t *size, u32 *cmd_op)
|
||||
{
|
||||
struct amdxdna_dev *xdna = cmd_abo->client->xdna;
|
||||
struct amdxdna_dev *xdna = to_xdna_dev(to_gobj(cmd_abo)->dev);
|
||||
int ret;
|
||||
u32 op;
|
||||
|
||||
|
|
|
|||
|
|
@ -310,6 +310,7 @@ int amdxdna_drm_destroy_hwctx_ioctl(struct drm_device *dev, void *data, struct d
|
|||
if (!drm_dev_enter(dev, &idx))
|
||||
return -ENODEV;
|
||||
|
||||
mutex_lock(&xdna->client_lock);
|
||||
mutex_lock(&xdna->dev_lock);
|
||||
hwctx = xa_erase(&client->hwctx_xa, args->handle);
|
||||
if (!hwctx) {
|
||||
|
|
@ -328,6 +329,7 @@ int amdxdna_drm_destroy_hwctx_ioctl(struct drm_device *dev, void *data, struct d
|
|||
XDNA_DBG(xdna, "PID %d destroyed HW context %d", client->pid, args->handle);
|
||||
out:
|
||||
mutex_unlock(&xdna->dev_lock);
|
||||
mutex_unlock(&xdna->client_lock);
|
||||
drm_dev_exit(idx);
|
||||
return ret;
|
||||
}
|
||||
|
|
@ -382,16 +384,27 @@ int amdxdna_drm_config_hwctx_ioctl(struct drm_device *dev, void *data, struct dr
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
guard(mutex)(&xdna->dev_lock);
|
||||
ret = amdxdna_pm_resume_get(xdna);
|
||||
if (ret) {
|
||||
XDNA_ERR(xdna, "Resume failed, ret %d", ret);
|
||||
goto free_buf;
|
||||
}
|
||||
|
||||
mutex_lock(&xdna->client_lock);
|
||||
mutex_lock(&xdna->dev_lock);
|
||||
hwctx = xa_load(&client->hwctx_xa, args->handle);
|
||||
if (!hwctx) {
|
||||
XDNA_DBG(xdna, "PID %d failed to get hwctx %d", client->pid, args->handle);
|
||||
ret = -EINVAL;
|
||||
goto free_buf;
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
ret = xdna->dev_info->ops->hwctx_config(hwctx, args->param_type, val, buf, buf_size);
|
||||
|
||||
unlock:
|
||||
mutex_unlock(&xdna->dev_lock);
|
||||
mutex_unlock(&xdna->client_lock);
|
||||
amdxdna_pm_suspend_put(xdna);
|
||||
free_buf:
|
||||
kfree(buf);
|
||||
return ret;
|
||||
|
|
@ -412,16 +425,27 @@ int amdxdna_hwctx_sync_debug_bo(struct amdxdna_client *client, u32 debug_bo_hdl)
|
|||
if (!gobj)
|
||||
return -EINVAL;
|
||||
|
||||
ret = amdxdna_pm_resume_get(xdna);
|
||||
if (ret) {
|
||||
XDNA_ERR(xdna, "Resume failed, ret %d", ret);
|
||||
goto put_obj;
|
||||
}
|
||||
|
||||
abo = to_xdna_obj(gobj);
|
||||
guard(mutex)(&xdna->dev_lock);
|
||||
mutex_lock(&xdna->client_lock);
|
||||
mutex_lock(&xdna->dev_lock);
|
||||
hwctx = xa_load(&client->hwctx_xa, abo->assigned_hwctx);
|
||||
if (!hwctx) {
|
||||
ret = -EINVAL;
|
||||
goto put_obj;
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
ret = xdna->dev_info->ops->hwctx_sync_debug_bo(hwctx, debug_bo_hdl);
|
||||
|
||||
unlock:
|
||||
mutex_unlock(&xdna->dev_lock);
|
||||
mutex_unlock(&xdna->client_lock);
|
||||
amdxdna_pm_suspend_put(xdna);
|
||||
put_obj:
|
||||
drm_gem_object_put(gobj);
|
||||
return ret;
|
||||
|
|
@ -448,9 +472,7 @@ static int amdxdna_hwctx_expand_heap(struct amdxdna_hwctx *hwctx)
|
|||
break;
|
||||
}
|
||||
|
||||
mutex_unlock(&client->mm_lock);
|
||||
ret = xdna->dev_info->ops->hwctx_heap_expand(hwctx, heap);
|
||||
mutex_lock(&client->mm_lock);
|
||||
if (ret) {
|
||||
amdxdna_gem_unpin(heap);
|
||||
drm_gem_object_put(to_gobj(heap));
|
||||
|
|
@ -469,18 +491,26 @@ int amdxdna_update_heap(struct amdxdna_client *client, struct amdxdna_hwctx *hwc
|
|||
unsigned long hwctx_id;
|
||||
int ret;
|
||||
|
||||
guard(mutex)(&client->mm_lock);
|
||||
ret = amdxdna_pm_resume_get_locked(client->xdna);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (hwctx)
|
||||
return amdxdna_hwctx_expand_heap(hwctx);
|
||||
mutex_lock(&client->mm_lock);
|
||||
|
||||
amdxdna_for_each_hwctx(client, hwctx_id, hwctx) {
|
||||
if (hwctx) {
|
||||
ret = amdxdna_hwctx_expand_heap(hwctx);
|
||||
if (ret)
|
||||
return ret;
|
||||
} else {
|
||||
amdxdna_for_each_hwctx(client, hwctx_id, hwctx) {
|
||||
ret = amdxdna_hwctx_expand_heap(hwctx);
|
||||
if (ret)
|
||||
break;
|
||||
}
|
||||
}
|
||||
mutex_unlock(&client->mm_lock);
|
||||
|
||||
return 0;
|
||||
amdxdna_pm_suspend_put(client->xdna);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
|
|||
|
|
@ -198,6 +198,7 @@ amdxdna_gem_destroy_obj(struct amdxdna_gem_obj *abo)
|
|||
*/
|
||||
void *amdxdna_gem_vmap(struct amdxdna_gem_obj *abo)
|
||||
{
|
||||
struct amdxdna_dev *xdna = to_xdna_dev(to_gobj(abo)->dev);
|
||||
struct iosys_map map = IOSYS_MAP_INIT_VADDR(NULL);
|
||||
int ret;
|
||||
|
||||
|
|
@ -210,7 +211,7 @@ void *amdxdna_gem_vmap(struct amdxdna_gem_obj *abo)
|
|||
if (!abo->mem.kva) {
|
||||
ret = drm_gem_vmap(to_gobj(abo), &map);
|
||||
if (ret)
|
||||
XDNA_ERR(abo->client->xdna, "Vmap bo failed, ret %d", ret);
|
||||
XDNA_ERR(xdna, "Vmap bo failed, ret %d", ret);
|
||||
else
|
||||
abo->mem.kva = map.vaddr;
|
||||
}
|
||||
|
|
@ -254,7 +255,7 @@ static bool amdxdna_hmm_invalidate(struct mmu_interval_notifier *mni,
|
|||
|
||||
xdna = to_xdna_dev(to_gobj(abo)->dev);
|
||||
XDNA_DBG(xdna, "Invalidating range 0x%lx, 0x%lx, type %d",
|
||||
mapp->vma->vm_start, mapp->vma->vm_end, abo->type);
|
||||
mapp->range.start, mapp->range.end, abo->type);
|
||||
|
||||
if (!mmu_notifier_range_blockable(range))
|
||||
return false;
|
||||
|
|
@ -284,15 +285,23 @@ static const struct mmu_interval_notifier_ops amdxdna_hmm_ops = {
|
|||
.invalidate = amdxdna_hmm_invalidate,
|
||||
};
|
||||
|
||||
static inline bool compare_range(struct amdxdna_umap *mapp,
|
||||
struct mm_struct *mm,
|
||||
unsigned long start, unsigned long end)
|
||||
{
|
||||
return (!mapp->unmapped && mapp->notifier.mm == mm &&
|
||||
mapp->range.start == start && mapp->range.end == end);
|
||||
}
|
||||
|
||||
static void amdxdna_hmm_unregister(struct amdxdna_gem_obj *abo,
|
||||
struct vm_area_struct *vma)
|
||||
{
|
||||
struct amdxdna_dev *xdna = to_xdna_dev(to_gobj(abo)->dev);
|
||||
struct amdxdna_umap *mapp;
|
||||
|
||||
down_read(&xdna->notifier_lock);
|
||||
down_write(&xdna->notifier_lock);
|
||||
list_for_each_entry(mapp, &abo->mem.umap_list, node) {
|
||||
if (!vma || mapp->vma == vma) {
|
||||
if (!vma || compare_range(mapp, vma->vm_mm, vma->vm_start, vma->vm_end)) {
|
||||
if (!mapp->unmapped) {
|
||||
queue_work(xdna->notifier_wq, &mapp->hmm_unreg_work);
|
||||
mapp->unmapped = true;
|
||||
|
|
@ -301,19 +310,16 @@ static void amdxdna_hmm_unregister(struct amdxdna_gem_obj *abo,
|
|||
break;
|
||||
}
|
||||
}
|
||||
up_read(&xdna->notifier_lock);
|
||||
up_write(&xdna->notifier_lock);
|
||||
}
|
||||
|
||||
static void amdxdna_umap_release(struct kref *ref)
|
||||
{
|
||||
struct amdxdna_umap *mapp = container_of(ref, struct amdxdna_umap, refcnt);
|
||||
struct amdxdna_gem_obj *abo = mapp->abo;
|
||||
struct vm_area_struct *vma = mapp->vma;
|
||||
struct amdxdna_dev *xdna;
|
||||
|
||||
mmu_interval_notifier_remove(&mapp->notifier);
|
||||
if (is_import_bo(abo) && vma->vm_file && vma->vm_file->f_mapping)
|
||||
mapping_clear_unevictable(vma->vm_file->f_mapping);
|
||||
|
||||
xdna = to_xdna_dev(to_gobj(mapp->abo)->dev);
|
||||
down_write(&xdna->notifier_lock);
|
||||
|
|
@ -346,15 +352,30 @@ static int amdxdna_hmm_register(struct amdxdna_gem_obj *abo,
|
|||
unsigned long len = vma->vm_end - vma->vm_start;
|
||||
unsigned long addr = vma->vm_start;
|
||||
struct amdxdna_umap *mapp;
|
||||
u32 nr_pages;
|
||||
unsigned long nr_pages;
|
||||
int ret;
|
||||
|
||||
if (!amdxdna_pasid_on(abo->client)) {
|
||||
/*
|
||||
* When PASID is off, amdxdna_gem_obj_open() called amdxdna_dma_map_bo()
|
||||
* and mem.dma_addr is valid; use the DMA address directly and skip HMM.
|
||||
* Avoid dereferencing abo->client which may be NULL (cleared in close())
|
||||
* while internal kernel references are still held.
|
||||
*/
|
||||
if (abo->mem.dma_addr != AMDXDNA_INVALID_ADDR) {
|
||||
/* Need to set uva for heap uva validation */
|
||||
abo->mem.uva = addr;
|
||||
return 0;
|
||||
}
|
||||
|
||||
down_read(&xdna->notifier_lock);
|
||||
list_for_each_entry(mapp, &abo->mem.umap_list, node) {
|
||||
if (compare_range(mapp, current->mm, addr, addr + len)) {
|
||||
up_read(&xdna->notifier_lock);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
up_read(&xdna->notifier_lock);
|
||||
|
||||
mapp = kzalloc_obj(*mapp);
|
||||
if (!mapp)
|
||||
return -ENOMEM;
|
||||
|
|
@ -380,13 +401,10 @@ static int amdxdna_hmm_register(struct amdxdna_gem_obj *abo,
|
|||
mapp->range.start = vma->vm_start;
|
||||
mapp->range.end = vma->vm_end;
|
||||
mapp->range.default_flags = HMM_PFN_REQ_FAULT;
|
||||
mapp->vma = vma;
|
||||
mapp->abo = abo;
|
||||
kref_init(&mapp->refcnt);
|
||||
|
||||
INIT_WORK(&mapp->hmm_unreg_work, amdxdna_hmm_unreg_work);
|
||||
if (is_import_bo(abo) && vma->vm_file && vma->vm_file->f_mapping)
|
||||
mapping_set_unevictable(vma->vm_file->f_mapping);
|
||||
|
||||
down_write(&xdna->notifier_lock);
|
||||
if (list_empty(&abo->mem.umap_list))
|
||||
|
|
@ -527,6 +545,7 @@ static int amdxdna_gem_dmabuf_mmap(struct dma_buf *dma_buf, struct vm_area_struc
|
|||
|
||||
close_vma:
|
||||
vma->vm_ops->close(vma);
|
||||
return ret;
|
||||
put_obj:
|
||||
drm_gem_object_put(gobj);
|
||||
return ret;
|
||||
|
|
@ -652,8 +671,11 @@ static int amdxdna_gem_obj_open(struct drm_gem_object *gobj, struct drm_file *fi
|
|||
/* No need to set up dma addr mapping in PASID mode. */
|
||||
if (!amdxdna_pasid_on(abo->client)) {
|
||||
ret = amdxdna_dma_map_bo(xdna, abo);
|
||||
if (ret)
|
||||
if (ret) {
|
||||
abo->open_ref--;
|
||||
abo->client = NULL;
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
amdxdna_gem_add_bo_usage(abo);
|
||||
|
|
|
|||
|
|
@ -12,7 +12,6 @@
|
|||
#include "amdxdna_pci_drv.h"
|
||||
|
||||
struct amdxdna_umap {
|
||||
struct vm_area_struct *vma;
|
||||
struct mmu_interval_notifier notifier;
|
||||
struct hmm_range range;
|
||||
struct work_struct hmm_unreg_work;
|
||||
|
|
@ -89,12 +88,19 @@ u64 amdxdna_gem_dev_addr(struct amdxdna_gem_obj *abo);
|
|||
|
||||
static inline u64 amdxdna_dev_bo_offset(struct amdxdna_gem_obj *abo)
|
||||
{
|
||||
return amdxdna_gem_dev_addr(abo) - abo->client->xdna->dev_info->dev_mem_base;
|
||||
return amdxdna_gem_dev_addr(abo) - to_xdna_dev(to_gobj(abo)->dev)->dev_info->dev_mem_base;
|
||||
}
|
||||
|
||||
static inline u64 amdxdna_obj_dma_addr(struct amdxdna_gem_obj *abo)
|
||||
{
|
||||
return amdxdna_pasid_on(abo->client) ? amdxdna_gem_uva(abo) : abo->mem.dma_addr;
|
||||
/*
|
||||
* amdxdna_gem_obj_open() calls amdxdna_dma_map_bo() only when PASID is
|
||||
* off, leaving mem.dma_addr at AMDXDNA_INVALID_ADDR when PASID is on.
|
||||
* Avoid dereferencing abo->client, which is cleared to NULL by
|
||||
* amdxdna_gem_obj_close() while internal kernel references remain.
|
||||
*/
|
||||
return (abo->mem.dma_addr != AMDXDNA_INVALID_ADDR) ?
|
||||
abo->mem.dma_addr : amdxdna_gem_uva(abo);
|
||||
}
|
||||
|
||||
void amdxdna_umap_put(struct amdxdna_umap *mapp);
|
||||
|
|
|
|||
|
|
@ -109,11 +109,16 @@ static int amdxdna_drm_open(struct drm_device *ddev, struct drm_file *filp)
|
|||
{
|
||||
struct amdxdna_dev *xdna = to_xdna_dev(ddev);
|
||||
struct amdxdna_client *client;
|
||||
int ret;
|
||||
|
||||
client = kzalloc_obj(*client);
|
||||
if (!client)
|
||||
return -ENOMEM;
|
||||
|
||||
ret = init_srcu_struct(&client->hwctx_srcu);
|
||||
if (ret)
|
||||
goto free_client;
|
||||
|
||||
client->pid = pid_nr(rcu_access_pointer(filp->pid));
|
||||
client->xdna = xdna;
|
||||
client->pasid = IOMMU_PASID_INVALID;
|
||||
|
|
@ -125,13 +130,12 @@ static int amdxdna_drm_open(struct drm_device *ddev, struct drm_file *filp)
|
|||
XDNA_WARN(xdna, "PASID not available for pid %d", client->pid);
|
||||
if (!amdxdna_use_carveout(xdna)) {
|
||||
XDNA_ERR(xdna, "PASID unavailable and carveout not configured");
|
||||
kfree(client);
|
||||
return -EINVAL;
|
||||
ret = -EINVAL;
|
||||
goto cleanup_srcu;
|
||||
}
|
||||
}
|
||||
}
|
||||
mmgrab(client->mm);
|
||||
init_srcu_struct(&client->hwctx_srcu);
|
||||
xa_init_flags(&client->hwctx_xa, XA_FLAGS_ALLOC);
|
||||
xa_init_flags(&client->dev_heap_xa, XA_FLAGS_ALLOC);
|
||||
drm_mm_init(&client->dev_heap_mm, xdna->dev_info->dev_mem_base,
|
||||
|
|
@ -149,6 +153,12 @@ static int amdxdna_drm_open(struct drm_device *ddev, struct drm_file *filp)
|
|||
|
||||
XDNA_DBG(xdna, "pid %d opened", client->pid);
|
||||
return 0;
|
||||
|
||||
cleanup_srcu:
|
||||
cleanup_srcu_struct(&client->hwctx_srcu);
|
||||
free_client:
|
||||
kfree(client);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void amdxdna_client_cleanup(struct amdxdna_client *client)
|
||||
|
|
@ -373,7 +383,10 @@ static int amdxdna_probe(struct pci_dev *pdev, const struct pci_device_id *id)
|
|||
if (ret)
|
||||
return ret;
|
||||
|
||||
drmm_mutex_init(ddev, &xdna->dev_lock);
|
||||
ret = drmm_mutex_init(ddev, &xdna->dev_lock);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
init_rwsem(&xdna->notifier_lock);
|
||||
INIT_LIST_HEAD(&xdna->client_list);
|
||||
pci_set_drvdata(pdev, xdna);
|
||||
|
|
|
|||
|
|
@ -1658,7 +1658,20 @@ static void binder_txn_latency_free(struct binder_transaction *t)
|
|||
|
||||
static void binder_free_transaction(struct binder_transaction *t)
|
||||
{
|
||||
struct binder_proc *target_proc = t->to_proc;
|
||||
struct binder_thread *target_thread;
|
||||
struct binder_proc *target_proc;
|
||||
|
||||
spin_lock(&t->lock);
|
||||
target_proc = t->to_proc;
|
||||
target_thread = t->to_thread;
|
||||
/*
|
||||
* Pin target_thread to keep target_proc alive. Undelivered
|
||||
* transactions with !target_thread are safe, as target_proc
|
||||
* can only be the current context there.
|
||||
*/
|
||||
if (target_thread)
|
||||
atomic_inc(&target_thread->tmp_ref);
|
||||
spin_unlock(&t->lock);
|
||||
|
||||
if (target_proc) {
|
||||
binder_inner_proc_lock(target_proc);
|
||||
|
|
@ -1672,6 +1685,10 @@ static void binder_free_transaction(struct binder_transaction *t)
|
|||
t->buffer->transaction = NULL;
|
||||
binder_inner_proc_unlock(target_proc);
|
||||
}
|
||||
|
||||
if (target_thread)
|
||||
binder_thread_dec_tmpref(target_thread);
|
||||
|
||||
if (trace_binder_txn_latency_free_enabled())
|
||||
binder_txn_latency_free(t);
|
||||
/*
|
||||
|
|
@ -3080,6 +3097,7 @@ static void binder_transaction(struct binder_proc *proc,
|
|||
int t_debug_id = atomic_inc_return(&binder_last_id);
|
||||
ktime_t t_start_time = ktime_get();
|
||||
struct lsm_context lsmctx = { };
|
||||
size_t lsmctx_aligned_size = 0;
|
||||
LIST_HEAD(sgc_head);
|
||||
LIST_HEAD(pf_head);
|
||||
const void __user *user_buffer = (const void __user *)
|
||||
|
|
@ -3346,7 +3364,6 @@ static void binder_transaction(struct binder_proc *proc,
|
|||
|
||||
if (target_node && target_node->txn_security_ctx) {
|
||||
u32 secid;
|
||||
size_t added_size;
|
||||
|
||||
security_cred_getsecid(proc->cred, &secid);
|
||||
ret = security_secid_to_secctx(secid, &lsmctx);
|
||||
|
|
@ -3358,9 +3375,9 @@ static void binder_transaction(struct binder_proc *proc,
|
|||
return_error_line = __LINE__;
|
||||
goto err_get_secctx_failed;
|
||||
}
|
||||
added_size = ALIGN(lsmctx.len, sizeof(u64));
|
||||
extra_buffers_size += added_size;
|
||||
if (extra_buffers_size < added_size) {
|
||||
lsmctx_aligned_size = ALIGN(lsmctx.len, sizeof(u64));
|
||||
extra_buffers_size += lsmctx_aligned_size;
|
||||
if (extra_buffers_size < lsmctx_aligned_size) {
|
||||
binder_txn_error("%d:%d integer overflow of extra_buffers_size\n",
|
||||
thread->pid, proc->pid);
|
||||
return_error = BR_FAILED_REPLY;
|
||||
|
|
@ -3397,7 +3414,7 @@ static void binder_transaction(struct binder_proc *proc,
|
|||
size_t buf_offset = ALIGN(tr->data_size, sizeof(void *)) +
|
||||
ALIGN(tr->offsets_size, sizeof(void *)) +
|
||||
ALIGN(extra_buffers_size, sizeof(void *)) -
|
||||
ALIGN(lsmctx.len, sizeof(u64));
|
||||
lsmctx_aligned_size;
|
||||
|
||||
t->security_ctx = t->buffer->user_data + buf_offset;
|
||||
err = binder_alloc_copy_to_buffer(&target_proc->alloc,
|
||||
|
|
@ -3452,7 +3469,7 @@ static void binder_transaction(struct binder_proc *proc,
|
|||
off_end_offset = off_start_offset + tr->offsets_size;
|
||||
sg_buf_offset = ALIGN(off_end_offset, sizeof(void *));
|
||||
sg_buf_end_offset = sg_buf_offset + extra_buffers_size -
|
||||
ALIGN(lsmctx.len, sizeof(u64));
|
||||
lsmctx_aligned_size;
|
||||
off_min = 0;
|
||||
for (buffer_offset = off_start_offset; buffer_offset < off_end_offset;
|
||||
buffer_offset += sizeof(binder_size_t)) {
|
||||
|
|
|
|||
|
|
@ -259,7 +259,7 @@ fn drop(&mut self) {
|
|||
|
||||
if let Some(offsets) = info.offsets.clone() {
|
||||
let view = AllocationView::new(self, offsets.start);
|
||||
for i in offsets.step_by(size_of::<usize>()) {
|
||||
for i in offsets.step_by(size_of::<u64>()) {
|
||||
if view.cleanup_object(i).is_err() {
|
||||
pr_warn!("Error cleaning up object at offset {}\n", i)
|
||||
}
|
||||
|
|
@ -420,7 +420,8 @@ pub(crate) fn transfer_binder_object(
|
|||
}
|
||||
|
||||
fn cleanup_object(&self, index_offset: usize) -> Result {
|
||||
let offset = self.alloc.read(index_offset)?;
|
||||
let offset = self.alloc.read::<u64>(index_offset)?;
|
||||
let offset: usize = offset.try_into().map_err(|_| EINVAL)?;
|
||||
let header = self.read::<BinderObjectHeader>(offset)?;
|
||||
match header.type_ {
|
||||
BINDER_TYPE_WEAK_BINDER | BINDER_TYPE_BINDER => {
|
||||
|
|
|
|||
|
|
@ -73,20 +73,17 @@ impl fmt::Debug for BinderError {
|
|||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
match self.reply {
|
||||
BR_FAILED_REPLY => match self.source.as_ref() {
|
||||
Some(source) => f
|
||||
.debug_struct("BR_FAILED_REPLY")
|
||||
.field("source", source)
|
||||
.finish(),
|
||||
Some(source) => source.fmt(f),
|
||||
None => f.pad("BR_FAILED_REPLY"),
|
||||
},
|
||||
BR_DEAD_REPLY => f.pad("BR_DEAD_REPLY"),
|
||||
BR_FROZEN_REPLY => f.pad("BR_FROZEN_REPLY"),
|
||||
BR_TRANSACTION_PENDING_FROZEN => f.pad("BR_TRANSACTION_PENDING_FROZEN"),
|
||||
BR_TRANSACTION_COMPLETE => f.pad("BR_TRANSACTION_COMPLETE"),
|
||||
_ => f
|
||||
.debug_struct("BinderError")
|
||||
.field("reply", &self.reply)
|
||||
.finish(),
|
||||
_ => match self.source.as_ref() {
|
||||
Some(source) => source.fmt(f),
|
||||
None => self.reply.fmt(f),
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -154,10 +154,17 @@ fn debug_print(&self, m: &SeqFile, prefix: &str, _tprefix: &str) -> Result<()> {
|
|||
}
|
||||
|
||||
impl FreezeListener {
|
||||
pub(crate) fn on_process_exit(&self, proc: &Arc<Process>) {
|
||||
/// Called when this freeze listener is cleared abnormally.
|
||||
///
|
||||
/// This occurs either because the process exited or because the process dropped its last
|
||||
/// refcount on the node ref without explicitly removing the freeze listener first.
|
||||
///
|
||||
/// The returned `KVVec` is just a value that should be dropped outside of the lock.
|
||||
pub(crate) fn on_process_cleanup(&self, proc: &Process) -> KVVec<Arc<Process>> {
|
||||
if !self.is_clearing {
|
||||
self.node.remove_freeze_listener(proc);
|
||||
return self.node.remove_freeze_listener(proc);
|
||||
}
|
||||
KVVec::new()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -682,12 +682,13 @@ pub(crate) fn add_freeze_listener(
|
|||
}
|
||||
}
|
||||
|
||||
pub(crate) fn remove_freeze_listener(&self, p: &Arc<Process>) {
|
||||
let _unused_capacity;
|
||||
pub(crate) fn remove_freeze_listener(&self, p: &Process) -> KVVec<Arc<Process>> {
|
||||
let mut guard = self.owner.inner.lock();
|
||||
let inner = self.inner.access_mut(&mut guard);
|
||||
let len = inner.freeze_list.len();
|
||||
inner.freeze_list.retain(|proc| !Arc::ptr_eq(proc, p));
|
||||
inner
|
||||
.freeze_list
|
||||
.retain(|proc| !core::ptr::eq::<Process>(&**proc, p));
|
||||
if len == inner.freeze_list.len() {
|
||||
pr_warn!(
|
||||
"Could not remove freeze listener for {}\n",
|
||||
|
|
@ -695,8 +696,9 @@ pub(crate) fn remove_freeze_listener(&self, p: &Arc<Process>) {
|
|||
);
|
||||
}
|
||||
if inner.freeze_list.is_empty() {
|
||||
_unused_capacity = mem::take(&mut inner.freeze_list);
|
||||
return mem::take(&mut inner.freeze_list);
|
||||
}
|
||||
KVVec::new()
|
||||
}
|
||||
|
||||
pub(crate) fn freeze_list<'a>(&'a self, guard: &'a ProcessInner) -> &'a [Arc<Process>] {
|
||||
|
|
|
|||
|
|
@ -900,7 +900,11 @@ pub(crate) fn insert_or_update_handle(
|
|||
pub(crate) fn get_transaction_node(&self, handle: u32) -> BinderResult<NodeRef> {
|
||||
// When handle is zero, try to get the context manager.
|
||||
if handle == 0 {
|
||||
Ok(self.ctx.get_manager_node(true)?)
|
||||
let node_ref = self.ctx.get_manager_node(true)?;
|
||||
if core::ptr::eq(self, &*node_ref.node.owner) {
|
||||
return Err(EINVAL.into());
|
||||
}
|
||||
Ok(node_ref)
|
||||
} else {
|
||||
Ok(self.get_node_from_handle(handle, true)?)
|
||||
}
|
||||
|
|
@ -942,6 +946,8 @@ pub(crate) fn update_ref(
|
|||
|
||||
// To preserve original binder behaviour, we only fail requests where the manager tries to
|
||||
// increment references on itself.
|
||||
let _to_free_freeze_listener;
|
||||
let _to_free_freeze_listener_cleanup;
|
||||
let mut refs = self.node_refs.lock();
|
||||
if let Some(info) = refs.by_handle.get_mut(&handle) {
|
||||
if info.node_ref().update(inc, strong) {
|
||||
|
|
@ -957,6 +963,14 @@ pub(crate) fn update_ref(
|
|||
unsafe { info.node_ref2().node.remove_node_info(info) };
|
||||
|
||||
let id = info.node_ref().node.global_id();
|
||||
|
||||
if let Some(freeze) = *info.freeze() {
|
||||
if let Some(fl) = refs.freeze_listeners.remove(&freeze) {
|
||||
_to_free_freeze_listener_cleanup = fl.on_process_cleanup(&self);
|
||||
_to_free_freeze_listener = fl;
|
||||
}
|
||||
}
|
||||
|
||||
refs.by_handle.remove(&handle);
|
||||
refs.by_node.remove(&id);
|
||||
refs.handle_is_present.release_id(handle as usize);
|
||||
|
|
@ -1380,7 +1394,7 @@ fn deferred_release(self: Arc<Self>) {
|
|||
// Clean up freeze listeners.
|
||||
let freeze_listeners = take(&mut self.node_refs.lock().freeze_listeners);
|
||||
for listener in freeze_listeners.values() {
|
||||
listener.on_process_exit(&self);
|
||||
listener.on_process_cleanup(&self);
|
||||
}
|
||||
drop(freeze_listeners);
|
||||
|
||||
|
|
|
|||
|
|
@ -28,6 +28,9 @@ const char * const binder_command_strings[] = {
|
|||
"BC_DEAD_BINDER_DONE",
|
||||
"BC_TRANSACTION_SG",
|
||||
"BC_REPLY_SG",
|
||||
"BC_REQUEST_FREEZE_NOTIFICATION",
|
||||
"BC_CLEAR_FREEZE_NOTIFICATION",
|
||||
"BC_FREEZE_NOTIFICATION_DONE",
|
||||
};
|
||||
|
||||
const char * const binder_return_strings[] = {
|
||||
|
|
@ -51,7 +54,9 @@ const char * const binder_return_strings[] = {
|
|||
"BR_FAILED_REPLY",
|
||||
"BR_FROZEN_REPLY",
|
||||
"BR_ONEWAY_SPAM_SUSPECT",
|
||||
"BR_TRANSACTION_PENDING_FROZEN"
|
||||
"BR_TRANSACTION_PENDING_FROZEN",
|
||||
"BR_FROZEN_BINDER",
|
||||
"BR_CLEAR_FREEZE_NOTIFICATION_DONE",
|
||||
};
|
||||
|
||||
#define CREATE_TRACE_POINTS
|
||||
|
|
|
|||
|
|
@ -8,8 +8,8 @@
|
|||
use kernel::sync::atomic::{ordering::Relaxed, Atomic};
|
||||
use kernel::{ioctl::_IOC_NR, seq_file::SeqFile, seq_print};
|
||||
|
||||
const BC_COUNT: usize = _IOC_NR(BC_REPLY_SG) as usize + 1;
|
||||
const BR_COUNT: usize = _IOC_NR(BR_TRANSACTION_PENDING_FROZEN) as usize + 1;
|
||||
const BC_COUNT: usize = _IOC_NR(BC_FREEZE_NOTIFICATION_DONE) as usize + 1;
|
||||
const BR_COUNT: usize = _IOC_NR(BR_CLEAR_FREEZE_NOTIFICATION_DONE) as usize + 1;
|
||||
|
||||
pub(crate) static GLOBAL_STATS: BinderStats = BinderStats::new();
|
||||
|
||||
|
|
|
|||
|
|
@ -495,9 +495,16 @@ pub(crate) fn debug_print(self: &Arc<Self>, m: &SeqFile, print_all: bool) -> Res
|
|||
Ok(())
|
||||
}
|
||||
|
||||
pub(crate) fn clear_extended_error(&self, debug_id: usize) {
|
||||
self.inner.lock().extended_error = ExtendedError::new(debug_id as u32, BR_OK, 0);
|
||||
}
|
||||
|
||||
pub(crate) fn get_extended_error(&self, data: UserSlice) -> Result {
|
||||
let mut writer = data.writer();
|
||||
let ee = self.inner.lock().extended_error;
|
||||
let mut inner = self.inner.lock();
|
||||
let ee = inner.extended_error;
|
||||
inner.extended_error = ExtendedError::new(0, BR_OK, 0);
|
||||
drop(inner);
|
||||
writer.write(&ee)?;
|
||||
Ok(())
|
||||
}
|
||||
|
|
@ -1109,7 +1116,10 @@ fn unwind_transaction_stack(self: &Arc<Self>) {
|
|||
inner.pop_transaction_to_reply(thread.as_ref())
|
||||
} {
|
||||
let reply = Err(BR_DEAD_REPLY);
|
||||
if !transaction.from.deliver_single_reply(reply, &transaction) {
|
||||
if !transaction
|
||||
.from
|
||||
.deliver_single_reply(reply, &transaction, None)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
@ -1121,8 +1131,9 @@ pub(crate) fn deliver_reply(
|
|||
&self,
|
||||
reply: Result<DLArc<Transaction>, u32>,
|
||||
transaction: &DArc<Transaction>,
|
||||
extended_error: Option<ExtendedError>,
|
||||
) {
|
||||
if self.deliver_single_reply(reply, transaction) {
|
||||
if self.deliver_single_reply(reply, transaction, extended_error) {
|
||||
transaction.from.unwind_transaction_stack();
|
||||
}
|
||||
}
|
||||
|
|
@ -1136,6 +1147,7 @@ fn deliver_single_reply(
|
|||
&self,
|
||||
reply: Result<DLArc<Transaction>, u32>,
|
||||
transaction: &DArc<Transaction>,
|
||||
extended_error: Option<ExtendedError>,
|
||||
) -> bool {
|
||||
if let Ok(transaction) = &reply {
|
||||
crate::trace::trace_transaction(true, transaction, Some(&self.task));
|
||||
|
|
@ -1152,6 +1164,12 @@ fn deliver_single_reply(
|
|||
return true;
|
||||
}
|
||||
|
||||
if let Some(ee) = extended_error {
|
||||
if inner.extended_error.command == BR_OK {
|
||||
inner.extended_error = ee;
|
||||
}
|
||||
}
|
||||
|
||||
match reply {
|
||||
Ok(work) => {
|
||||
inner.push_work(work);
|
||||
|
|
@ -1222,6 +1240,9 @@ fn read_transaction_info(
|
|||
info.buffers_size = td.buffers_size as usize;
|
||||
// SAFETY: Above `read` call initializes all bytes, so this union read is ok.
|
||||
info.target_handle = unsafe { td.transaction_data.target.handle };
|
||||
|
||||
info.debug_id = super::next_debug_id();
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
|
@ -1230,6 +1251,8 @@ fn transaction(self: &Arc<Self>, cmd: u32, reader: &mut UserSliceReader) -> Resu
|
|||
let mut info = TransactionInfo::zeroed();
|
||||
self.read_transaction_info(cmd, reader, &mut info)?;
|
||||
|
||||
self.clear_extended_error(info.debug_id);
|
||||
|
||||
let ret = if info.is_reply {
|
||||
self.reply_inner(&mut info)
|
||||
} else if info.is_oneway() {
|
||||
|
|
@ -1239,23 +1262,21 @@ fn transaction(self: &Arc<Self>, cmd: u32, reader: &mut UserSliceReader) -> Resu
|
|||
};
|
||||
|
||||
if let Err(err) = ret {
|
||||
self.push_return_work(err.reply);
|
||||
if err.reply != BR_TRANSACTION_COMPLETE {
|
||||
info.reply = err.reply;
|
||||
}
|
||||
if let Some(source) = &err.source {
|
||||
info.errno = source.to_errno();
|
||||
|
||||
self.push_return_work(err.reply);
|
||||
if let Some(source) = &err.source {
|
||||
info.errno = source.to_errno();
|
||||
info.reply = err.reply;
|
||||
|
||||
{
|
||||
let mut ee = self.inner.lock().extended_error;
|
||||
ee.command = err.reply;
|
||||
ee.param = source.to_errno();
|
||||
{
|
||||
let mut inner = self.inner.lock();
|
||||
inner.extended_error =
|
||||
ExtendedError::new(info.debug_id as u32, err.reply, source.to_errno());
|
||||
}
|
||||
}
|
||||
|
||||
pr_warn!(
|
||||
"{}:{} transaction to {} failed: {source:?}",
|
||||
"{}:{} transaction to {} failed: {err:?}",
|
||||
info.from_pid,
|
||||
info.from_tid,
|
||||
info.to_pid
|
||||
|
|
@ -1320,18 +1341,24 @@ fn reply_inner(self: &Arc<Self>, info: &mut TransactionInfo) -> BinderResult {
|
|||
let allow_fds = orig.flags & TF_ACCEPT_FDS != 0;
|
||||
let reply = Transaction::new_reply(self, process, info, allow_fds)?;
|
||||
self.inner.lock().push_work(completion);
|
||||
orig.from.deliver_reply(Ok(reply), &orig);
|
||||
orig.from.deliver_reply(Ok(reply), &orig, None);
|
||||
Ok(())
|
||||
})()
|
||||
.map_err(|mut err| {
|
||||
// At this point we only return `BR_TRANSACTION_COMPLETE` to the caller, and we must let
|
||||
// the sender know that the transaction has completed (with an error in this case).
|
||||
|
||||
pr_warn!(
|
||||
"Failure {:?} during reply - delivering BR_FAILED_REPLY to sender.",
|
||||
err
|
||||
"{}:{} reply to {} failed: {err:?}",
|
||||
info.from_pid,
|
||||
info.from_tid,
|
||||
info.to_pid
|
||||
);
|
||||
let reply = Err(BR_FAILED_REPLY);
|
||||
orig.from.deliver_reply(reply, &orig);
|
||||
|
||||
let param = err.source.as_ref().map_or(0, |e| e.to_errno());
|
||||
let ee = ExtendedError::new(info.debug_id as u32, err.reply, param);
|
||||
orig.from
|
||||
.deliver_reply(Err(BR_FAILED_REPLY), &orig, Some(ee));
|
||||
err.reply = BR_TRANSACTION_COMPLETE;
|
||||
err
|
||||
});
|
||||
|
|
|
|||
|
|
@ -42,6 +42,7 @@ pub(crate) struct TransactionInfo {
|
|||
pub(crate) reply: u32,
|
||||
pub(crate) oneway_spam_suspect: bool,
|
||||
pub(crate) is_reply: bool,
|
||||
pub(crate) debug_id: usize,
|
||||
}
|
||||
|
||||
impl TransactionInfo {
|
||||
|
|
@ -93,7 +94,6 @@ pub(crate) fn new(
|
|||
from: &Arc<Thread>,
|
||||
info: &mut TransactionInfo,
|
||||
) -> BinderResult<DLArc<Self>> {
|
||||
let debug_id = super::next_debug_id();
|
||||
let allow_fds = node_ref.node.flags & FLAT_BINDER_FLAG_ACCEPTS_FDS != 0;
|
||||
let txn_security_ctx = node_ref.node.flags & FLAT_BINDER_FLAG_TXN_SECURITY_CTX != 0;
|
||||
let mut txn_security_ctx_off = if txn_security_ctx { Some(0) } else { None };
|
||||
|
|
@ -101,7 +101,7 @@ pub(crate) fn new(
|
|||
let mut alloc = match from.copy_transaction_data(
|
||||
to.clone(),
|
||||
info,
|
||||
debug_id,
|
||||
info.debug_id,
|
||||
allow_fds,
|
||||
txn_security_ctx_off.as_mut(),
|
||||
) {
|
||||
|
|
@ -128,7 +128,7 @@ pub(crate) fn new(
|
|||
let data_address = alloc.ptr;
|
||||
|
||||
Ok(DTRWrap::arc_pin_init(pin_init!(Transaction {
|
||||
debug_id,
|
||||
debug_id: info.debug_id,
|
||||
target_node: Some(target_node),
|
||||
from_parent,
|
||||
sender_euid: Kuid::current_euid(),
|
||||
|
|
@ -152,9 +152,8 @@ pub(crate) fn new_reply(
|
|||
info: &mut TransactionInfo,
|
||||
allow_fds: bool,
|
||||
) -> BinderResult<DLArc<Self>> {
|
||||
let debug_id = super::next_debug_id();
|
||||
let mut alloc =
|
||||
match from.copy_transaction_data(to.clone(), info, debug_id, allow_fds, None) {
|
||||
match from.copy_transaction_data(to.clone(), info, info.debug_id, allow_fds, None) {
|
||||
Ok(alloc) => alloc,
|
||||
Err(err) => {
|
||||
pr_warn!("Failure in copy_transaction_data: {:?}", err);
|
||||
|
|
@ -165,7 +164,7 @@ pub(crate) fn new_reply(
|
|||
alloc.set_info_clear_on_drop();
|
||||
}
|
||||
Ok(DTRWrap::arc_pin_init(pin_init!(Transaction {
|
||||
debug_id,
|
||||
debug_id: info.debug_id,
|
||||
target_node: None,
|
||||
from_parent: None,
|
||||
sender_euid: Kuid::current_euid(),
|
||||
|
|
@ -394,7 +393,7 @@ fn do_work(
|
|||
let send_failed_reply = ScopeGuard::new(|| {
|
||||
if self.target_node.is_some() && self.flags & TF_ONE_WAY == 0 {
|
||||
let reply = Err(BR_FAILED_REPLY);
|
||||
self.from.deliver_reply(reply, &self);
|
||||
self.from.deliver_reply(reply, &self, None);
|
||||
}
|
||||
self.drop_outstanding_txn();
|
||||
});
|
||||
|
|
@ -478,7 +477,7 @@ fn cancel(self: DArc<Self>) {
|
|||
// If this is not a reply or oneway transaction, then send a dead reply.
|
||||
if self.target_node.is_some() && self.flags & TF_ONE_WAY == 0 {
|
||||
let reply = Err(BR_DEAD_REPLY);
|
||||
self.from.deliver_reply(reply, &self);
|
||||
self.from.deliver_reply(reply, &self, None);
|
||||
}
|
||||
|
||||
self.drop_outstanding_txn();
|
||||
|
|
|
|||
|
|
@ -1338,7 +1338,7 @@ static int ata_hpa_resize(struct ata_device *dev)
|
|||
/* do we need to do it? */
|
||||
if ((dev->class != ATA_DEV_ATA && dev->class != ATA_DEV_ZAC) ||
|
||||
!ata_id_has_lba(dev->id) || !ata_id_hpa_enabled(dev->id) ||
|
||||
(dev->quirks & ATA_QUIRK_BROKEN_HPA))
|
||||
(dev->quirks & ATA_QUIRK_BROKEN_HPA) || ata_id_is_locked(dev->id))
|
||||
return 0;
|
||||
|
||||
/* read native max address */
|
||||
|
|
@ -3992,7 +3992,7 @@ int ata_dev_revalidate(struct ata_device *dev, unsigned int new_class,
|
|||
|
||||
/* verify n_sectors hasn't changed */
|
||||
if (dev->class != ATA_DEV_ATA || !n_sectors ||
|
||||
dev->n_sectors == n_sectors)
|
||||
dev->n_sectors == n_sectors || ata_id_is_locked(dev->id))
|
||||
return 0;
|
||||
|
||||
/* n_sectors has changed */
|
||||
|
|
|
|||
|
|
@ -1810,6 +1810,11 @@ static int recv_dless_read(struct drbd_peer_device *peer_device, struct drbd_req
|
|||
data_size -= digest_size;
|
||||
}
|
||||
|
||||
if (data_size < 0) {
|
||||
drbd_err(peer_device, "Invalid data reply size\n");
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
/* optimistically update recv_cnt. if receiving fails below,
|
||||
* we disconnect anyways, and counters will be reset. */
|
||||
peer_device->device->recv_cnt += data_size>>9;
|
||||
|
|
|
|||
|
|
@ -3584,6 +3584,7 @@ ublk_batch_auto_buf_reg(const struct ublk_batch_io *uc,
|
|||
#define UBLK_CMD_BATCH_TMP_BUF_SZ (48 * 10)
|
||||
struct ublk_batch_io_iter {
|
||||
void __user *uaddr;
|
||||
const u8 *kaddr;
|
||||
unsigned done, total;
|
||||
unsigned char elem_bytes;
|
||||
/* copy to this buffer from user space */
|
||||
|
|
@ -3632,7 +3633,10 @@ static int ublk_walk_cmd_buf(struct ublk_batch_io_iter *iter,
|
|||
while (iter->done < iter->total) {
|
||||
unsigned int len = min(sizeof(iter->buf), iter->total - iter->done);
|
||||
|
||||
if (copy_from_user(iter->buf, iter->uaddr + iter->done, len)) {
|
||||
if (iter->kaddr) {
|
||||
memcpy(iter->buf, iter->kaddr + iter->done, len);
|
||||
} else if (copy_from_user(iter->buf, iter->uaddr + iter->done,
|
||||
len)) {
|
||||
pr_warn("ublk%d: read batch cmd buffer failed\n",
|
||||
data->ub->dev_info.dev_id);
|
||||
return -EFAULT;
|
||||
|
|
@ -3723,14 +3727,21 @@ static int ublk_handle_batch_prep_cmd(const struct ublk_batch_io_data *data)
|
|||
.total = uc->nr_elem * uc->elem_bytes,
|
||||
.elem_bytes = uc->elem_bytes,
|
||||
};
|
||||
void *cmd_buf;
|
||||
int ret;
|
||||
|
||||
cmd_buf = vmemdup_user(iter.uaddr, iter.total);
|
||||
if (IS_ERR(cmd_buf))
|
||||
return PTR_ERR(cmd_buf);
|
||||
iter.kaddr = cmd_buf;
|
||||
|
||||
mutex_lock(&data->ub->mutex);
|
||||
ret = ublk_walk_cmd_buf(&iter, data, ublk_batch_prep_io);
|
||||
|
||||
if (ret && iter.done)
|
||||
ublk_batch_revert_prep_cmd(&iter, data);
|
||||
mutex_unlock(&data->ub->mutex);
|
||||
kvfree(cmd_buf);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -2079,6 +2079,15 @@ static int blkfront_resume(struct xenbus_device *dev)
|
|||
if (!shadow[j].request)
|
||||
continue;
|
||||
|
||||
/*
|
||||
* For requests split across multiple slots, process the
|
||||
* underlying request only once: skip the linked, sg-less
|
||||
* secondary slot.
|
||||
*/
|
||||
if (shadow[j].associated_id != NO_ASSOCIATED_ID &&
|
||||
shadow[j].num_sg == 0)
|
||||
continue;
|
||||
|
||||
/*
|
||||
* Get the bios in the request so we can re-queue them.
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -255,9 +255,13 @@ static int bpa10x_setup(struct hci_dev *hdev)
|
|||
if (IS_ERR(skb))
|
||||
return PTR_ERR(skb);
|
||||
|
||||
bt_dev_info(hdev, "%s", (char *)(skb->data + 1));
|
||||
/* Bounded print: the device controls skb->len. */
|
||||
if (skb->len > 1) {
|
||||
int len = skb->len - 1;
|
||||
|
||||
hci_set_fw_info(hdev, "%s", skb->data + 1);
|
||||
bt_dev_info(hdev, "%.*s", len, (char *)(skb->data + 1));
|
||||
hci_set_fw_info(hdev, "%.*s", len, skb->data + 1);
|
||||
}
|
||||
|
||||
kfree_skb(skb);
|
||||
return 0;
|
||||
|
|
|
|||
|
|
@ -2127,6 +2127,9 @@ static int btintel_pcie_send_frame(struct hci_dev *hdev,
|
|||
if (test_bit(BTINTEL_PCIE_CORE_HALTED, &data->flags))
|
||||
return -ENODEV;
|
||||
|
||||
if (test_bit(BTINTEL_PCIE_RECOVERY_IN_PROGRESS, &data->flags))
|
||||
return -ENODEV;
|
||||
|
||||
/* Due to the fw limitation, the type header of the packet should be
|
||||
* 4 bytes unlike 1 byte for UART. In UART, the firmware can read
|
||||
* the first byte to get the packet type and redirect the rest of data
|
||||
|
|
@ -2485,7 +2488,6 @@ static void btintel_pcie_inc_recovery_count(struct pci_dev *pdev,
|
|||
}
|
||||
}
|
||||
|
||||
static int btintel_pcie_setup_hdev(struct btintel_pcie_data *data);
|
||||
static void btintel_pcie_reset(struct hci_dev *hdev);
|
||||
|
||||
static int btintel_pcie_acpi_reset_method(struct btintel_pcie_data *data)
|
||||
|
|
@ -2596,12 +2598,45 @@ static void btintel_pcie_perform_pldr(struct btintel_pcie_data *data)
|
|||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Issue a Function Level Reset and hand teardown/re-init off to the PCI
|
||||
* core via device_reprobe(), mirroring the PLDR path's contract.
|
||||
*
|
||||
* Caller must hold pci_lock_rescan_remove() and must have already
|
||||
* disabled interrupts and drained both rx_work and coredump_work.
|
||||
*/
|
||||
static int btintel_pcie_perform_flr(struct btintel_pcie_data *data)
|
||||
{
|
||||
struct pci_dev *pdev = data->pdev;
|
||||
int err;
|
||||
|
||||
/* pci_try_reset_function() avoids the device_lock ABBA against
|
||||
* btintel_pcie_remove(): .remove() runs with device_lock held and
|
||||
* then waits for this work via disable_work_sync(); the blocking
|
||||
* pci_reset_function() would deadlock by trying to re-acquire
|
||||
* device_lock here.
|
||||
*/
|
||||
err = pci_try_reset_function(pdev);
|
||||
if (err) {
|
||||
BT_ERR("Failed resetting the pcie device (%d)", err);
|
||||
return err;
|
||||
}
|
||||
|
||||
/* device_reprobe() always detaches the driver first (running
|
||||
* .remove(), which frees 'data'); any re-probe failure leaves the
|
||||
* device unbound but 'data' is already gone, so just log it.
|
||||
*/
|
||||
if (device_reprobe(&pdev->dev))
|
||||
BT_ERR("BT reprobe failed for BDF:%s", pci_name(pdev));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void btintel_pcie_reset_work(struct work_struct *wk)
|
||||
{
|
||||
struct btintel_pcie_data *data =
|
||||
container_of(wk, struct btintel_pcie_data, reset_work);
|
||||
struct pci_dev *pdev = data->pdev;
|
||||
int err;
|
||||
|
||||
pci_lock_rescan_remove();
|
||||
|
||||
|
|
@ -2621,60 +2656,27 @@ static void btintel_pcie_reset_work(struct work_struct *wk)
|
|||
disable_work_sync(&data->coredump_work);
|
||||
|
||||
bt_dev_dbg(data->hdev, "Release bluetooth interface");
|
||||
|
||||
/* Both reset paths follow the same contract: on success they
|
||||
* destroy 'data' via device_reprobe() (a fresh probe re-INIT_WORKs
|
||||
* the coredump_work with disable count 0), so enable_work() must
|
||||
* NOT be called on the success path. Only the FLR path can fail
|
||||
* with 'data' still alive, in which case we balance the
|
||||
* disable_work_sync() above so a later successful reset is not
|
||||
* permanently blocked.
|
||||
*
|
||||
* pci_lock_rescan_remove() (held above) serializes against PCI
|
||||
* device addition/removal (hotplug), so no device can be added to
|
||||
* or removed from the bus list while this code runs.
|
||||
*/
|
||||
if (data->reset_type == BTINTEL_PCIE_IOSF_PRR_PLDR) {
|
||||
/* This function holds pci_lock_rescan_remove(), which acquires
|
||||
* pci_rescan_remove_lock. This mutex serializes against PCI device
|
||||
* addition/removal (hotplug), so no device can be added to or
|
||||
* removed from the bus list while this code runs.
|
||||
*
|
||||
* device_reprobe() inside btintel_pcie_perform_pldr() destroys
|
||||
* 'data' via .remove(); a fresh probe re-INIT_WORKs the
|
||||
* coredump_work with disable count 0, so we must not call
|
||||
* enable_work() on this path.
|
||||
*/
|
||||
btintel_pcie_perform_pldr(data);
|
||||
goto out;
|
||||
}
|
||||
btintel_pcie_release_hdev(data);
|
||||
|
||||
/* Use pci_try_reset_function() rather than pci_reset_function() to
|
||||
* avoid an ABBA deadlock against btintel_pcie_remove(): the PCI core
|
||||
* calls .remove() with device_lock held, and remove() then waits for
|
||||
* this work via cancel_work_sync(); pci_reset_function() would in
|
||||
* turn try to acquire the same device_lock, deadlocking both paths.
|
||||
*/
|
||||
err = pci_try_reset_function(pdev);
|
||||
if (err) {
|
||||
BT_ERR("Failed resetting the pcie device (%d)", err);
|
||||
goto out_enable;
|
||||
}
|
||||
if (btintel_pcie_perform_flr(data))
|
||||
enable_work(&data->coredump_work);
|
||||
|
||||
btintel_pcie_enable_interrupts(data);
|
||||
btintel_pcie_config_msix(data);
|
||||
|
||||
err = btintel_pcie_enable_bt(data);
|
||||
if (err) {
|
||||
BT_ERR("Failed to enable bluetooth hardware after reset (%d)",
|
||||
err);
|
||||
goto out_enable;
|
||||
}
|
||||
|
||||
btintel_pcie_reset_ia(data);
|
||||
btintel_pcie_start_rx(data);
|
||||
data->flags = 0;
|
||||
|
||||
err = btintel_pcie_setup_hdev(data);
|
||||
if (err) {
|
||||
BT_ERR("Failed registering hdev (%d)", err);
|
||||
goto out_enable;
|
||||
}
|
||||
|
||||
out_enable:
|
||||
/* Balance disable_work_sync() above on every exit. Leaving the
|
||||
* counter incremented on a failed reset would permanently disable
|
||||
* coredump_work even after a later successful reset.
|
||||
*/
|
||||
enable_work(&data->coredump_work);
|
||||
out:
|
||||
pci_dev_put(pdev);
|
||||
pci_unlock_rescan_remove();
|
||||
|
|
|
|||
|
|
@ -1267,6 +1267,12 @@ static int nxp_recv_fw_req_v3(struct hci_dev *hdev, struct sk_buff *skb)
|
|||
}
|
||||
|
||||
nxpdev->fw_dnld_v3_offset = offset - nxpdev->fw_v3_offset_correction;
|
||||
if (nxpdev->fw_dnld_v3_offset >= nxpdev->fw->size ||
|
||||
len > nxpdev->fw->size - nxpdev->fw_dnld_v3_offset) {
|
||||
bt_dev_err(hdev, "FW download out of bounds, ignoring request");
|
||||
len = 0;
|
||||
goto free_skb;
|
||||
}
|
||||
serdev_device_write_buf(nxpdev->serdev, nxpdev->fw->data +
|
||||
nxpdev->fw_dnld_v3_offset, len);
|
||||
|
||||
|
|
|
|||
|
|
@ -239,6 +239,8 @@ static int hci_uart_flush(struct hci_dev *hdev)
|
|||
|
||||
BT_DBG("hdev %p tty %p", hdev, tty);
|
||||
|
||||
disable_work_sync(&hu->write_work);
|
||||
|
||||
if (hu->tx_skb) {
|
||||
kfree_skb(hu->tx_skb); hu->tx_skb = NULL;
|
||||
}
|
||||
|
|
@ -254,6 +256,14 @@ static int hci_uart_flush(struct hci_dev *hdev)
|
|||
|
||||
percpu_up_read(&hu->proto_lock);
|
||||
|
||||
/* Resume TX. Also reschedule in case work was queued concurrently;
|
||||
* this may schedule write_work although there's nothing to do.
|
||||
*/
|
||||
enable_work(&hu->write_work);
|
||||
clear_bit(HCI_UART_SENDING, &hu->tx_state);
|
||||
if (test_bit(HCI_UART_TX_WAKEUP, &hu->tx_state))
|
||||
hci_uart_tx_wakeup(hu);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -271,12 +281,8 @@ static int hci_uart_open(struct hci_dev *hdev)
|
|||
/* Close device */
|
||||
static int hci_uart_close(struct hci_dev *hdev)
|
||||
{
|
||||
struct hci_uart *hu = hci_get_drvdata(hdev);
|
||||
|
||||
BT_DBG("hdev %p", hdev);
|
||||
|
||||
cancel_work_sync(&hu->write_work);
|
||||
|
||||
hci_uart_flush(hdev);
|
||||
hdev->flush = NULL;
|
||||
return 0;
|
||||
|
|
|
|||
|
|
@ -36,7 +36,7 @@ static int tpm_open(struct inode *inode, struct file *file)
|
|||
|
||||
tpm_common_open(file, chip, priv, NULL);
|
||||
|
||||
return 0;
|
||||
return nonseekable_open(inode, file);
|
||||
|
||||
out:
|
||||
clear_bit(0, &chip->is_open);
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@ static int tpmrm_open(struct inode *inode, struct file *file)
|
|||
|
||||
tpm_common_open(file, chip, &priv->priv, &priv->space);
|
||||
|
||||
return 0;
|
||||
return nonseekable_open(inode, file);
|
||||
}
|
||||
|
||||
static int tpmrm_release(struct inode *inode, struct file *file)
|
||||
|
|
|
|||
|
|
@ -254,6 +254,11 @@ static int dibs_lo_move_data(struct dibs_dev *dibs, u64 dmb_tok,
|
|||
read_unlock_bh(&ldev->dmb_ht_lock);
|
||||
return -EINVAL;
|
||||
}
|
||||
if ((u64)offset + size > rmb_node->len) {
|
||||
read_unlock_bh(&ldev->dmb_ht_lock);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
memcpy((char *)rmb_node->cpu_addr + offset, data, size);
|
||||
sba_idx = rmb_node->sba_idx;
|
||||
read_unlock_bh(&ldev->dmb_ht_lock);
|
||||
|
|
|
|||
|
|
@ -117,6 +117,7 @@ struct dwapb_gpio {
|
|||
unsigned int flags;
|
||||
struct reset_control *rst;
|
||||
struct clk_bulk_data clks[DWAPB_NR_CLOCKS];
|
||||
bool clocks_on_for_wake;
|
||||
struct dwapb_gpio_port ports[] __counted_by(nr_ports);
|
||||
};
|
||||
|
||||
|
|
@ -199,6 +200,22 @@ static void dwapb_toggle_trigger(struct dwapb_gpio *gpio, unsigned int offs)
|
|||
dwapb_write(gpio, GPIO_INT_POLARITY, pol);
|
||||
}
|
||||
|
||||
static int dwapb_irq_init_hw(struct gpio_chip *gc)
|
||||
{
|
||||
struct dwapb_gpio *gpio = to_dwapb_gpio(gc);
|
||||
|
||||
/*
|
||||
* GPIO interrupts may retain stale state across warm reboots when
|
||||
* peripherals stay powered. Force a known-safe state before the GPIO
|
||||
* irqchip and irq domain are set up.
|
||||
*/
|
||||
dwapb_write(gpio, GPIO_INTEN, 0);
|
||||
dwapb_write(gpio, GPIO_INTMASK, 0xffffffff);
|
||||
dwapb_write(gpio, GPIO_PORTA_EOI, 0xffffffff);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static u32 dwapb_do_irq(struct dwapb_gpio *gpio)
|
||||
{
|
||||
struct gpio_generic_chip *gen_gc = &gpio->ports[0].chip;
|
||||
|
|
@ -364,11 +381,24 @@ static int dwapb_irq_set_wake(struct irq_data *d, unsigned int enable)
|
|||
struct dwapb_gpio *gpio = to_dwapb_gpio(gc);
|
||||
struct dwapb_context *ctx = gpio->ports[0].ctx;
|
||||
irq_hw_number_t bit = irqd_to_hwirq(d);
|
||||
u32 wake_en = ctx->wake_en;
|
||||
|
||||
if (enable)
|
||||
ctx->wake_en |= BIT(bit);
|
||||
wake_en |= BIT(bit);
|
||||
else
|
||||
ctx->wake_en &= ~BIT(bit);
|
||||
wake_en &= ~BIT(bit);
|
||||
|
||||
#ifdef CONFIG_IRQ_DOMAIN_HIERARCHY
|
||||
if (d->parent_data && !!ctx->wake_en != !!wake_en) {
|
||||
int err;
|
||||
|
||||
err = irq_chip_set_wake_parent(d, enable);
|
||||
if (err)
|
||||
return err;
|
||||
}
|
||||
#endif
|
||||
|
||||
ctx->wake_en = wake_en;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -457,6 +487,7 @@ static void dwapb_configure_irqs(struct dwapb_gpio *gpio,
|
|||
girq = &gc->irq;
|
||||
girq->handler = handle_bad_irq;
|
||||
girq->default_type = IRQ_TYPE_NONE;
|
||||
girq->init_hw = dwapb_irq_init_hw;
|
||||
|
||||
port->pirq = pirq;
|
||||
|
||||
|
|
@ -749,6 +780,8 @@ static int dwapb_gpio_suspend(struct device *dev)
|
|||
int i;
|
||||
|
||||
scoped_guard(gpio_generic_lock_irqsave, gen_gc) {
|
||||
gpio->clocks_on_for_wake = false;
|
||||
|
||||
for (i = 0; i < gpio->nr_ports; i++) {
|
||||
unsigned int offset;
|
||||
unsigned int idx = gpio->ports[i].idx;
|
||||
|
|
@ -770,30 +803,66 @@ static int dwapb_gpio_suspend(struct device *dev)
|
|||
ctx->int_pol = dwapb_read(gpio, GPIO_INT_POLARITY);
|
||||
ctx->int_type = dwapb_read(gpio, GPIO_INTTYPE_LEVEL);
|
||||
ctx->int_deb = dwapb_read(gpio, GPIO_PORTA_DEBOUNCE);
|
||||
|
||||
/* Mask out interrupts */
|
||||
dwapb_write(gpio, GPIO_INTMASK, ~ctx->wake_en);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int dwapb_gpio_suspend_noirq(struct device *dev)
|
||||
{
|
||||
struct dwapb_gpio *gpio = dev_get_drvdata(dev);
|
||||
struct gpio_generic_chip *gen_gc = &gpio->ports[0].chip;
|
||||
bool wake_enabled = false;
|
||||
int i;
|
||||
|
||||
scoped_guard(gpio_generic_lock_irqsave, gen_gc) {
|
||||
for (i = 0; i < gpio->nr_ports; i++) {
|
||||
unsigned int idx = gpio->ports[i].idx;
|
||||
struct dwapb_context *ctx = gpio->ports[i].ctx;
|
||||
|
||||
if (idx == 0) {
|
||||
wake_enabled = ctx->wake_en;
|
||||
dwapb_write(gpio, GPIO_INTMASK, ~ctx->wake_en);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
gpio->clocks_on_for_wake = wake_enabled;
|
||||
}
|
||||
|
||||
if (wake_enabled) {
|
||||
device_set_wakeup_path(dev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
clk_bulk_disable_unprepare(DWAPB_NR_CLOCKS, gpio->clks);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int dwapb_gpio_resume_noirq(struct device *dev)
|
||||
{
|
||||
struct dwapb_gpio *gpio = dev_get_drvdata(dev);
|
||||
int err;
|
||||
|
||||
if (gpio->clocks_on_for_wake)
|
||||
return 0;
|
||||
|
||||
err = clk_bulk_prepare_enable(DWAPB_NR_CLOCKS, gpio->clks);
|
||||
if (err)
|
||||
dev_err(gpio->dev, "Cannot reenable APB/Debounce clocks\n");
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static int dwapb_gpio_resume(struct device *dev)
|
||||
{
|
||||
struct dwapb_gpio *gpio = dev_get_drvdata(dev);
|
||||
struct gpio_chip *gc = &gpio->ports[0].chip.gc;
|
||||
struct gpio_generic_chip *gen_gc = to_gpio_generic_chip(gc);
|
||||
int i, err;
|
||||
|
||||
err = clk_bulk_prepare_enable(DWAPB_NR_CLOCKS, gpio->clks);
|
||||
if (err) {
|
||||
dev_err(gpio->dev, "Cannot reenable APB/Debounce clocks\n");
|
||||
return err;
|
||||
}
|
||||
int i;
|
||||
|
||||
guard(gpio_generic_lock_irqsave)(gen_gc);
|
||||
|
||||
|
|
@ -827,8 +896,11 @@ static int dwapb_gpio_resume(struct device *dev)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static DEFINE_SIMPLE_DEV_PM_OPS(dwapb_gpio_pm_ops,
|
||||
dwapb_gpio_suspend, dwapb_gpio_resume);
|
||||
static const struct dev_pm_ops dwapb_gpio_pm_ops = {
|
||||
SYSTEM_SLEEP_PM_OPS(dwapb_gpio_suspend, dwapb_gpio_resume)
|
||||
NOIRQ_SYSTEM_SLEEP_PM_OPS(dwapb_gpio_suspend_noirq,
|
||||
dwapb_gpio_resume_noirq)
|
||||
};
|
||||
|
||||
static struct platform_driver dwapb_gpio_driver = {
|
||||
.driver = {
|
||||
|
|
|
|||
|
|
@ -1110,6 +1110,7 @@ static void mvebu_gpio_remove_irq_domain(void *data)
|
|||
{
|
||||
struct irq_domain *domain = data;
|
||||
|
||||
irq_domain_remove_generic_chips(domain);
|
||||
irq_domain_remove(domain);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -116,6 +116,24 @@ static int palmas_gpio_input(struct gpio_chip *gc, unsigned offset)
|
|||
return ret;
|
||||
}
|
||||
|
||||
static int palmas_gpio_get_direction(struct gpio_chip *gc, unsigned int offset)
|
||||
{
|
||||
struct palmas_gpio *pg = gpiochip_get_data(gc);
|
||||
struct palmas *palmas = pg->palmas;
|
||||
unsigned int val;
|
||||
unsigned int reg;
|
||||
int ret;
|
||||
int gpio16 = (offset/8);
|
||||
|
||||
offset %= 8;
|
||||
reg = (gpio16) ? PALMAS_GPIO_DATA_DIR2 : PALMAS_GPIO_DATA_DIR;
|
||||
ret = palmas_read(palmas, PALMAS_GPIO_BASE, reg, &val);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return (val & BIT(offset)) ? GPIO_LINE_DIRECTION_OUT : GPIO_LINE_DIRECTION_IN;
|
||||
}
|
||||
|
||||
static int palmas_gpio_to_irq(struct gpio_chip *gc, unsigned offset)
|
||||
{
|
||||
struct palmas_gpio *pg = gpiochip_get_data(gc);
|
||||
|
|
@ -165,6 +183,7 @@ static int palmas_gpio_probe(struct platform_device *pdev)
|
|||
palmas_gpio->gpio_chip.can_sleep = true;
|
||||
palmas_gpio->gpio_chip.direction_input = palmas_gpio_input;
|
||||
palmas_gpio->gpio_chip.direction_output = palmas_gpio_output;
|
||||
palmas_gpio->gpio_chip.get_direction = palmas_gpio_get_direction;
|
||||
palmas_gpio->gpio_chip.to_irq = palmas_gpio_to_irq;
|
||||
palmas_gpio->gpio_chip.set = palmas_gpio_set;
|
||||
palmas_gpio->gpio_chip.get = palmas_gpio_get;
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ struct gpio_shared_proxy_data {
|
|||
struct gpio_chip gc;
|
||||
struct gpio_shared_desc *shared_desc;
|
||||
struct device *dev;
|
||||
bool voted_high;
|
||||
bool voted_change;
|
||||
};
|
||||
|
||||
static int
|
||||
|
|
@ -33,52 +33,54 @@ gpio_shared_proxy_set_unlocked(struct gpio_shared_proxy_data *proxy, int value)
|
|||
|
||||
lockdep_assert_held(&shared_desc->mutex);
|
||||
|
||||
if (value) {
|
||||
/* User wants to set value to high. */
|
||||
if (proxy->voted_high)
|
||||
/* Already voted for high, nothing to do. */
|
||||
if (value != shared_desc->def_val) {
|
||||
/* User wants to vote for a value change. */
|
||||
if (proxy->voted_change)
|
||||
/* Already voted for a change, nothing to do. */
|
||||
goto out;
|
||||
|
||||
/* Haven't voted for high yet. */
|
||||
if (!shared_desc->highcnt) {
|
||||
/* Haven't voted for a value change yet. */
|
||||
if (!shared_desc->votecnt) {
|
||||
/*
|
||||
* Current value is low, need to actually set value
|
||||
* to high.
|
||||
* Current value is default, need to actually set value
|
||||
* to the opposite.
|
||||
*/
|
||||
ret = gpiod_set_value_cansleep(desc, 1);
|
||||
ret = gpiod_set_value_cansleep(desc, value);
|
||||
if (ret)
|
||||
goto out;
|
||||
}
|
||||
|
||||
shared_desc->highcnt++;
|
||||
proxy->voted_high = true;
|
||||
shared_desc->votecnt++;
|
||||
proxy->voted_change = true;
|
||||
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* Desired value is low. */
|
||||
if (!proxy->voted_high)
|
||||
/* We didn't vote for high, nothing to do. */
|
||||
/* Desired value is the default. */
|
||||
if (!proxy->voted_change)
|
||||
/* We didn't vote for change previously, nothing to do. */
|
||||
goto out;
|
||||
|
||||
/* We previously voted for high. */
|
||||
if (shared_desc->highcnt == 1) {
|
||||
/* This is the last remaining vote for high, set value to low. */
|
||||
ret = gpiod_set_value_cansleep(desc, 0);
|
||||
/* We previously voted for change. */
|
||||
if (shared_desc->votecnt == 1) {
|
||||
/* This is the last remaining vote for change, set value to default. */
|
||||
ret = gpiod_set_value_cansleep(desc, shared_desc->def_val);
|
||||
if (ret)
|
||||
goto out;
|
||||
}
|
||||
|
||||
shared_desc->highcnt--;
|
||||
proxy->voted_high = false;
|
||||
shared_desc->votecnt--;
|
||||
proxy->voted_change = false;
|
||||
|
||||
out:
|
||||
if (shared_desc->highcnt)
|
||||
if (shared_desc->votecnt)
|
||||
dev_dbg(proxy->dev,
|
||||
"Voted for value '%s', effective value is 'high', number of votes for 'high': %u\n",
|
||||
str_high_low(value), shared_desc->highcnt);
|
||||
"Voted for value '%s', effective value is '%s', number of votes: %u\n",
|
||||
str_high_low(value), str_high_low(!shared_desc->def_val),
|
||||
shared_desc->votecnt);
|
||||
else
|
||||
dev_dbg(proxy->dev, "Voted for value 'low', effective value is 'low'\n");
|
||||
dev_dbg(proxy->dev, "Voted for value '%s', effective value is '%s'\n",
|
||||
str_high_low(value), str_high_low(shared_desc->def_val));
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
|
@ -106,8 +108,8 @@ static void gpio_shared_proxy_free(struct gpio_chip *gc, unsigned int offset)
|
|||
|
||||
guard(mutex)(&shared_desc->mutex);
|
||||
|
||||
if (proxy->voted_high) {
|
||||
ret = gpio_shared_proxy_set_unlocked(proxy, 0);
|
||||
if (proxy->voted_change) {
|
||||
ret = gpio_shared_proxy_set_unlocked(proxy, shared_desc->def_val);
|
||||
if (ret)
|
||||
dev_err(proxy->dev,
|
||||
"Failed to unset the shared GPIO value on release: %d\n", ret);
|
||||
|
|
@ -196,13 +198,9 @@ static int gpio_shared_proxy_direction_output(struct gpio_chip *gc,
|
|||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (value) {
|
||||
proxy->voted_high = true;
|
||||
shared_desc->highcnt = 1;
|
||||
} else {
|
||||
proxy->voted_high = false;
|
||||
shared_desc->highcnt = 0;
|
||||
}
|
||||
shared_desc->def_val = value;
|
||||
shared_desc->votecnt = 0;
|
||||
proxy->voted_change = false;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -41,7 +41,8 @@ struct gpio_shared_desc {
|
|||
struct gpio_desc *desc;
|
||||
unsigned long cfg;
|
||||
unsigned int usecnt;
|
||||
unsigned int highcnt;
|
||||
unsigned int votecnt;
|
||||
int def_val;
|
||||
struct mutex mutex; /* serializes all proxy operations on this descriptor */
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -1084,22 +1084,30 @@ static int __gpu_buddy_alloc_range(struct gpu_buddy *mm,
|
|||
blocks, total_allocated_on_err);
|
||||
}
|
||||
|
||||
static int __alloc_contig_aligned_retry(struct gpu_buddy *mm,
|
||||
u64 unaligned_offset,
|
||||
u64 size,
|
||||
u64 min_block_size,
|
||||
struct list_head *blocks)
|
||||
{
|
||||
u64 aligned_offset = round_down(unaligned_offset, min_block_size);
|
||||
|
||||
return __gpu_buddy_alloc_range(mm, aligned_offset, size, NULL, blocks);
|
||||
}
|
||||
|
||||
static int __alloc_contig_try_harder(struct gpu_buddy *mm,
|
||||
u64 size,
|
||||
u64 min_block_size,
|
||||
struct list_head *blocks)
|
||||
{
|
||||
u64 rhs_offset, lhs_offset, lhs_size, filled;
|
||||
u64 rhs_offset, lhs_offset, filled;
|
||||
struct gpu_buddy_block *block;
|
||||
unsigned int tree, order;
|
||||
LIST_HEAD(blocks_lhs);
|
||||
unsigned long pages;
|
||||
u64 modify_size;
|
||||
int err;
|
||||
|
||||
modify_size = rounddown_pow_of_two(size);
|
||||
pages = modify_size >> ilog2(mm->chunk_size);
|
||||
order = fls(pages) - 1;
|
||||
order = ilog2(modify_size) - ilog2(mm->chunk_size);
|
||||
if (order == 0)
|
||||
return -ENOSPC;
|
||||
|
||||
|
|
@ -1115,31 +1123,48 @@ static int __alloc_contig_try_harder(struct gpu_buddy *mm,
|
|||
while (iter) {
|
||||
block = rbtree_get_free_block(iter);
|
||||
|
||||
/* Allocate blocks traversing RHS */
|
||||
rhs_offset = gpu_buddy_block_offset(block);
|
||||
|
||||
/* Allocate blocks traversing RHS */
|
||||
err = __gpu_buddy_alloc_range(mm, rhs_offset, size,
|
||||
&filled, blocks);
|
||||
if (!err || err != -ENOSPC)
|
||||
if (err && err != -ENOSPC)
|
||||
return err;
|
||||
|
||||
lhs_size = max((size - filled), min_block_size);
|
||||
if (!IS_ALIGNED(lhs_size, min_block_size))
|
||||
lhs_size = round_up(lhs_size, min_block_size);
|
||||
|
||||
/* Allocate blocks traversing LHS */
|
||||
lhs_offset = gpu_buddy_block_offset(block) - lhs_size;
|
||||
err = __gpu_buddy_alloc_range(mm, lhs_offset, lhs_size,
|
||||
NULL, &blocks_lhs);
|
||||
if (!err) {
|
||||
list_splice(&blocks_lhs, blocks);
|
||||
if (!err && IS_ALIGNED(rhs_offset, min_block_size))
|
||||
return 0;
|
||||
} else if (err != -ENOSPC) {
|
||||
if (!err) {
|
||||
/* Allocate the unaligned RHS offset using round_down */
|
||||
gpu_buddy_free_list_internal(mm, blocks);
|
||||
err = __alloc_contig_aligned_retry(mm, rhs_offset,
|
||||
size,
|
||||
min_block_size,
|
||||
blocks);
|
||||
if (!err)
|
||||
return 0;
|
||||
if (err != -ENOSPC) {
|
||||
gpu_buddy_free_list_internal(mm, blocks);
|
||||
return err;
|
||||
}
|
||||
goto next;
|
||||
}
|
||||
|
||||
if (size - filled > rhs_offset)
|
||||
goto next;
|
||||
|
||||
lhs_offset = rhs_offset - (size - filled);
|
||||
|
||||
/* Allocate the unaligned LHS offset using round_down */
|
||||
gpu_buddy_free_list_internal(mm, blocks);
|
||||
err = __alloc_contig_aligned_retry(mm, lhs_offset, size,
|
||||
min_block_size, blocks);
|
||||
if (!err)
|
||||
return 0;
|
||||
if (err != -ENOSPC) {
|
||||
gpu_buddy_free_list_internal(mm, blocks);
|
||||
return err;
|
||||
}
|
||||
/* Free blocks for the next iteration */
|
||||
next:
|
||||
gpu_buddy_free_list_internal(mm, blocks);
|
||||
|
||||
iter = rb_prev(iter);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1333,7 +1333,8 @@ static bool amdgpu_device_aspm_support_quirk(struct amdgpu_device *adev)
|
|||
* It's unclear if this is a platform-specific or GPU-specific issue.
|
||||
* Disable ASPM on SI for the time being.
|
||||
*/
|
||||
if (adev->family == AMDGPU_FAMILY_SI)
|
||||
if (adev->family == AMDGPU_FAMILY_SI ||
|
||||
(!(adev->pm.pp_feature & PP_PCIE_DPM_MASK) && adev->family == AMDGPU_FAMILY_VI))
|
||||
return true;
|
||||
|
||||
#if IS_ENABLED(CONFIG_X86)
|
||||
|
|
|
|||
|
|
@ -2304,6 +2304,7 @@ static int amdgpu_discovery_set_psp_ip_blocks(struct amdgpu_device *adev)
|
|||
amdgpu_device_ip_block_add(adev, &psp_v14_0_ip_block);
|
||||
break;
|
||||
case IP_VERSION(15, 0, 0):
|
||||
case IP_VERSION(15, 0, 9):
|
||||
amdgpu_device_ip_block_add(adev, &psp_v15_0_ip_block);
|
||||
break;
|
||||
case IP_VERSION(15, 0, 8):
|
||||
|
|
@ -2375,6 +2376,7 @@ static int amdgpu_discovery_set_smu_ip_blocks(struct amdgpu_device *adev)
|
|||
case IP_VERSION(15, 0, 0):
|
||||
case IP_VERSION(15, 0, 5):
|
||||
case IP_VERSION(15, 0, 8):
|
||||
case IP_VERSION(15, 0, 9):
|
||||
amdgpu_device_ip_block_add(adev, &smu_v15_0_ip_block);
|
||||
break;
|
||||
default:
|
||||
|
|
|
|||
|
|
@ -275,6 +275,7 @@ static int psp_early_init(struct amdgpu_ip_block *ip_block)
|
|||
psp->boot_time_tmr = false;
|
||||
break;
|
||||
case IP_VERSION(15, 0, 0):
|
||||
case IP_VERSION(15, 0, 9):
|
||||
psp_v15_0_0_set_psp_funcs(psp);
|
||||
psp->boot_time_tmr = false;
|
||||
break;
|
||||
|
|
@ -3475,7 +3476,9 @@ static int psp_load_non_psp_fw(struct psp_context *psp)
|
|||
amdgpu_ip_version(adev, MP0_HWIP, 0) ==
|
||||
IP_VERSION(15, 0, 0) ||
|
||||
amdgpu_ip_version(adev, MP0_HWIP, 0) ==
|
||||
IP_VERSION(15, 0, 8)) &&
|
||||
IP_VERSION(15, 0, 8) ||
|
||||
amdgpu_ip_version(adev, MP0_HWIP, 0) ==
|
||||
IP_VERSION(15, 0, 9)) &&
|
||||
(ucode->ucode_id == AMDGPU_UCODE_ID_SDMA1 ||
|
||||
ucode->ucode_id == AMDGPU_UCODE_ID_SDMA2 ||
|
||||
ucode->ucode_id == AMDGPU_UCODE_ID_SDMA3))
|
||||
|
|
|
|||
|
|
@ -523,6 +523,15 @@ amdgpu_userq_destroy(struct amdgpu_userq_mgr *uq_mgr, struct amdgpu_usermode_que
|
|||
amdgpu_userq_cleanup(queue);
|
||||
mutex_unlock(&uq_mgr->userq_mutex);
|
||||
|
||||
/*
|
||||
* A failed unmap means MES could not remove the hung queue and is now
|
||||
* unresponsive. Recover the GPU here so the wedged MES does not fail
|
||||
* the next, unrelated queue submission and trigger a reset attributed
|
||||
* to an innocent workload.
|
||||
*/
|
||||
if (r)
|
||||
queue_work(adev->reset_domain->wq, &uq_mgr->reset_work);
|
||||
|
||||
cancel_delayed_work_sync(&queue->hang_detect_work);
|
||||
uq_funcs->mqd_destroy(queue);
|
||||
queue->userq_mgr = NULL;
|
||||
|
|
|
|||
|
|
@ -2460,19 +2460,6 @@ static void amdgpu_vm_destroy_task_info(struct kref *kref)
|
|||
kfree(ti);
|
||||
}
|
||||
|
||||
static inline struct amdgpu_vm *
|
||||
amdgpu_vm_get_vm_from_pasid(struct amdgpu_device *adev, u32 pasid)
|
||||
{
|
||||
struct amdgpu_vm *vm;
|
||||
unsigned long flags;
|
||||
|
||||
xa_lock_irqsave(&adev->vm_manager.pasids, flags);
|
||||
vm = xa_load(&adev->vm_manager.pasids, pasid);
|
||||
xa_unlock_irqrestore(&adev->vm_manager.pasids, flags);
|
||||
|
||||
return vm;
|
||||
}
|
||||
|
||||
/**
|
||||
* amdgpu_vm_put_task_info - reference down the vm task_info ptr
|
||||
*
|
||||
|
|
@ -2519,8 +2506,16 @@ amdgpu_vm_get_task_info_vm(struct amdgpu_vm *vm)
|
|||
struct amdgpu_task_info *
|
||||
amdgpu_vm_get_task_info_pasid(struct amdgpu_device *adev, u32 pasid)
|
||||
{
|
||||
return amdgpu_vm_get_task_info_vm(
|
||||
amdgpu_vm_get_vm_from_pasid(adev, pasid));
|
||||
struct amdgpu_task_info *ti;
|
||||
struct amdgpu_vm *vm;
|
||||
unsigned long flags;
|
||||
|
||||
xa_lock_irqsave(&adev->vm_manager.pasids, flags);
|
||||
vm = xa_load(&adev->vm_manager.pasids, pasid);
|
||||
ti = amdgpu_vm_get_task_info_vm(vm);
|
||||
xa_unlock_irqrestore(&adev->vm_manager.pasids, flags);
|
||||
|
||||
return ti;
|
||||
}
|
||||
|
||||
static int amdgpu_vm_create_task_info(struct amdgpu_vm *vm)
|
||||
|
|
@ -3015,6 +3010,8 @@ bool amdgpu_vm_handle_fault(struct amdgpu_device *adev, u32 pasid,
|
|||
is_compute_context = vm->is_compute_context;
|
||||
|
||||
if (is_compute_context) {
|
||||
__label__ drm_exec_retry;
|
||||
|
||||
/* Release the root PD lock since svm_range_restore_pages
|
||||
* might try to take it.
|
||||
* TODO: rework svm_range_restore_pages so that this isn't
|
||||
|
|
|
|||
|
|
@ -5350,6 +5350,15 @@ static void gfx_v10_0_constants_init(struct amdgpu_device *adev)
|
|||
gfx_v10_0_get_tcc_info(adev);
|
||||
adev->gfx.config.pa_sc_tile_steering_override =
|
||||
gfx_v10_0_init_pa_sc_tile_steering_override(adev);
|
||||
/* Program DB_RING_CONTROL for multiple GFX pipes
|
||||
* Default power up value is 1.
|
||||
* Possible values:
|
||||
* 0 - split occlusion counters between gfx pipes
|
||||
* 1 - all occlusion counters to pipe 0
|
||||
* 2 - all occlusion counters to pipe 1
|
||||
*/
|
||||
WREG32_FIELD15(GC, 0, DB_RING_CONTROL, COUNTER_CONTROL,
|
||||
(adev->gfx.me.num_pipe_per_me > 1) ? 0 : 1);
|
||||
|
||||
/* XXX SH_MEM regs */
|
||||
/* where to put LDS, scratch, GPUVM in FSA64 space */
|
||||
|
|
|
|||
|
|
@ -406,6 +406,7 @@ soc21_asic_reset_method(struct amdgpu_device *adev)
|
|||
case IP_VERSION(14, 0, 4):
|
||||
case IP_VERSION(14, 0, 5):
|
||||
case IP_VERSION(15, 0, 0):
|
||||
case IP_VERSION(15, 0, 9):
|
||||
return AMD_RESET_METHOD_MODE2;
|
||||
default:
|
||||
if (amdgpu_dpm_is_baco_supported(adev))
|
||||
|
|
@ -861,7 +862,6 @@ static int soc21_common_early_init(struct amdgpu_ip_block *ip_block)
|
|||
AMD_CG_SUPPORT_BIF_LS;
|
||||
adev->pg_flags = AMD_PG_SUPPORT_VCN_DPG |
|
||||
AMD_PG_SUPPORT_VCN |
|
||||
AMD_PG_SUPPORT_JPEG_DPG |
|
||||
AMD_PG_SUPPORT_JPEG |
|
||||
AMD_PG_SUPPORT_GFX_PG;
|
||||
adev->external_rev_id = adev->rev_id + 0xF;
|
||||
|
|
@ -889,7 +889,6 @@ static int soc21_common_early_init(struct amdgpu_ip_block *ip_block)
|
|||
AMD_CG_SUPPORT_BIF_LS;
|
||||
adev->pg_flags = AMD_PG_SUPPORT_VCN_DPG |
|
||||
AMD_PG_SUPPORT_VCN |
|
||||
AMD_PG_SUPPORT_JPEG_DPG |
|
||||
AMD_PG_SUPPORT_JPEG |
|
||||
AMD_PG_SUPPORT_GFX_PG;
|
||||
adev->external_rev_id = adev->rev_id + 0x40;
|
||||
|
|
|
|||
|
|
@ -3818,6 +3818,12 @@ bool kfd_dqm_is_queue_in_process(struct device_queue_manager *dqm,
|
|||
dqm_unlock(dqm);
|
||||
return r;
|
||||
}
|
||||
|
||||
size_t mqd_size_from_queue_type(struct device_queue_manager *dqm, enum kfd_queue_type type)
|
||||
{
|
||||
return dqm->mqd_mgrs[get_mqd_type_from_queue_type(type)]->mqd_size;
|
||||
}
|
||||
|
||||
#if defined(CONFIG_DEBUG_FS)
|
||||
|
||||
static void seq_reg_dump(struct seq_file *m,
|
||||
|
|
|
|||
|
|
@ -333,6 +333,8 @@ int debug_refresh_runlist(struct device_queue_manager *dqm);
|
|||
bool kfd_dqm_is_queue_in_process(struct device_queue_manager *dqm,
|
||||
struct qcm_process_device *qpd,
|
||||
int doorbell_off, u32 *queue_format);
|
||||
size_t mqd_size_from_queue_type(struct device_queue_manager *dqm,
|
||||
enum kfd_queue_type type);
|
||||
|
||||
static inline unsigned int get_sh_mem_bases_32(struct kfd_process_device *pdd)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -107,6 +107,9 @@ static int allocate_event_notification_slot(struct kfd_process *p,
|
|||
}
|
||||
|
||||
if (restore_id) {
|
||||
if (*restore_id >= KFD_SIGNAL_EVENT_LIMIT)
|
||||
return -EINVAL;
|
||||
|
||||
id = idr_alloc(&p->event_idr, ev, *restore_id, *restore_id + 1,
|
||||
GFP_KERNEL);
|
||||
} else {
|
||||
|
|
@ -204,7 +207,7 @@ static int create_signal_event(struct file *devkfd, struct kfd_process *p,
|
|||
|
||||
ret = allocate_event_notification_slot(p, ev, restore_id);
|
||||
if (ret) {
|
||||
pr_warn("Signal event wasn't created because out of kernel memory\n");
|
||||
pr_warn("Failed to create signal event notification slot\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -440,7 +440,8 @@ enum kfd_queue_type {
|
|||
KFD_QUEUE_TYPE_SDMA,
|
||||
KFD_QUEUE_TYPE_HIQ,
|
||||
KFD_QUEUE_TYPE_SDMA_XGMI,
|
||||
KFD_QUEUE_TYPE_SDMA_BY_ENG_ID
|
||||
KFD_QUEUE_TYPE_SDMA_BY_ENG_ID,
|
||||
KFD_QUEUE_TYPE_MAX,
|
||||
};
|
||||
|
||||
enum kfd_queue_format {
|
||||
|
|
|
|||
|
|
@ -910,7 +910,7 @@ static void kfd_process_free_id(struct kfd_process *process)
|
|||
{
|
||||
struct kfd_process *primary_process;
|
||||
|
||||
if (process->context_id != KFD_CONTEXT_ID_PRIMARY)
|
||||
if (process->context_id == KFD_CONTEXT_ID_PRIMARY)
|
||||
return;
|
||||
|
||||
primary_process = kfd_lookup_process_by_mm(process->lead_thread->mm);
|
||||
|
|
|
|||
|
|
@ -265,6 +265,11 @@ static int init_user_queue(struct process_queue_manager *pqm,
|
|||
(*q)->process = pqm->process;
|
||||
|
||||
if (dev->kfd->shared_resources.enable_mes) {
|
||||
if (!q_properties->wptr_bo) {
|
||||
pr_debug("Queue initialization with shared MES requires queue buffers to be initialized\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
retval = amdgpu_amdkfd_alloc_kernel_mem(dev->adev,
|
||||
AMDGPU_MES_GANG_CTX_SIZE,
|
||||
AMDGPU_GEM_DOMAIN_GTT,
|
||||
|
|
@ -1003,6 +1008,23 @@ int kfd_criu_restore_queue(struct kfd_process *p,
|
|||
goto exit;
|
||||
}
|
||||
|
||||
pdd = kfd_process_device_data_by_id(p, q_data->gpu_id);
|
||||
if (!pdd) {
|
||||
pr_err("Failed to get pdd\n");
|
||||
ret = -EINVAL;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
if (q_data->type >= KFD_QUEUE_TYPE_MAX) {
|
||||
ret = -EINVAL;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
if (q_data->mqd_size != mqd_size_from_queue_type(pdd->dev->dqm, q_data->type)) {
|
||||
ret = -EINVAL;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
*priv_data_offset += sizeof(*q_data);
|
||||
q_extra_data_size = (uint64_t)q_data->ctl_stack_size + q_data->mqd_size;
|
||||
|
||||
|
|
@ -1025,13 +1047,6 @@ int kfd_criu_restore_queue(struct kfd_process *p,
|
|||
|
||||
*priv_data_offset += q_extra_data_size;
|
||||
|
||||
pdd = kfd_process_device_data_by_id(p, q_data->gpu_id);
|
||||
if (!pdd) {
|
||||
pr_err("Failed to get pdd\n");
|
||||
ret = -EINVAL;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
/*
|
||||
* data stored in this order:
|
||||
* mqd[xcc0], mqd[xcc1],..., ctl_stack[xcc0], ctl_stack[xcc1]...
|
||||
|
|
@ -1042,18 +1057,10 @@ int kfd_criu_restore_queue(struct kfd_process *p,
|
|||
memset(&qp, 0, sizeof(qp));
|
||||
set_queue_properties_from_criu(&qp, q_data, NUM_XCC(pdd->dev->adev->gfx.xcc_mask));
|
||||
|
||||
ret = kfd_queue_acquire_buffers(pdd, &qp);
|
||||
if (ret) {
|
||||
pr_debug("failed to acquire user queue buffers for CRIU\n");
|
||||
goto exit;
|
||||
}
|
||||
|
||||
print_queue_properties(&qp);
|
||||
|
||||
ret = pqm_create_queue(&p->pqm, pdd->dev, &qp, &queue_id, q_data, mqd, ctl_stack, NULL);
|
||||
if (ret) {
|
||||
kfd_queue_unref_bo_vas(pdd, &qp);
|
||||
kfd_queue_release_buffers(pdd, &qp);
|
||||
pr_err("Failed to create new queue err:%d\n", ret);
|
||||
goto exit;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -802,6 +802,7 @@ static int smu_set_funcs(struct amdgpu_device *adev)
|
|||
break;
|
||||
case IP_VERSION(15, 0, 0):
|
||||
case IP_VERSION(15, 0, 5):
|
||||
case IP_VERSION(15, 0, 9):
|
||||
smu_v15_0_0_set_ppt_funcs(smu);
|
||||
break;
|
||||
case IP_VERSION(15, 0, 8):
|
||||
|
|
|
|||
|
|
@ -1621,19 +1621,23 @@ static int smu_v14_0_2_get_power_limit(struct smu_context *smu,
|
|||
table_context->power_play_table;
|
||||
PPTable_t *pptable = table_context->driver_pptable;
|
||||
CustomSkuTable_t *skutable = &pptable->CustomSkuTable;
|
||||
int16_t od_percent_upper = 0, od_percent_lower = 0;
|
||||
uint32_t pp_limit = smu->adev->pm.ac_power ?
|
||||
skutable->SocketPowerLimitAc[PPT_THROTTLER_PPT0] :
|
||||
skutable->SocketPowerLimitDc[PPT_THROTTLER_PPT0];
|
||||
uint32_t msg_limit = pptable->SkuTable.MsgLimits.Power[PPT_THROTTLER_PPT0][POWER_SOURCE_AC];
|
||||
uint32_t power_limit;
|
||||
uint32_t min_limit = min_t(uint32_t, pp_limit, msg_limit);
|
||||
uint32_t max_limit = max_t(uint32_t, pp_limit, msg_limit);
|
||||
int16_t od_percent_upper = 0, od_percent_lower = 0;
|
||||
int ret;
|
||||
|
||||
if (smu_v14_0_get_current_power_limit(smu, &power_limit))
|
||||
power_limit = smu->adev->pm.ac_power ?
|
||||
skutable->SocketPowerLimitAc[PPT_THROTTLER_PPT0] :
|
||||
skutable->SocketPowerLimitDc[PPT_THROTTLER_PPT0];
|
||||
if (current_power_limit) {
|
||||
ret = smu_v14_0_get_current_power_limit(smu, current_power_limit);
|
||||
if (ret)
|
||||
*current_power_limit = pp_limit;
|
||||
}
|
||||
|
||||
if (current_power_limit)
|
||||
*current_power_limit = power_limit;
|
||||
if (default_power_limit)
|
||||
*default_power_limit = power_limit;
|
||||
*default_power_limit = pp_limit;
|
||||
|
||||
if (powerplay_table) {
|
||||
if (smu->od_enabled &&
|
||||
|
|
@ -1647,15 +1651,15 @@ static int smu_v14_0_2_get_power_limit(struct smu_context *smu,
|
|||
}
|
||||
|
||||
dev_dbg(smu->adev->dev, "od percent upper:%d, od percent lower:%d (default power: %d)\n",
|
||||
od_percent_upper, od_percent_lower, power_limit);
|
||||
od_percent_upper, od_percent_lower, pp_limit);
|
||||
|
||||
if (max_power_limit) {
|
||||
*max_power_limit = msg_limit * (100 + od_percent_upper);
|
||||
*max_power_limit = max_limit * (100 + od_percent_upper);
|
||||
*max_power_limit /= 100;
|
||||
}
|
||||
|
||||
if (min_power_limit) {
|
||||
*min_power_limit = power_limit * (100 + od_percent_lower);
|
||||
*min_power_limit = min_limit * (100 + od_percent_lower);
|
||||
*min_power_limit /= 100;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -664,6 +664,7 @@ int smu_v15_0_gfx_off_control(struct smu_context *smu, bool enable)
|
|||
|
||||
switch (amdgpu_ip_version(adev, MP1_HWIP, 0)) {
|
||||
case IP_VERSION(15, 0, 0):
|
||||
case IP_VERSION(15, 0, 9):
|
||||
if (!(adev->pm.pp_feature & PP_GFXOFF_MASK))
|
||||
return 0;
|
||||
if (enable)
|
||||
|
|
|
|||
|
|
@ -1177,7 +1177,8 @@ static int smu_v15_0_common_get_dpm_profile_freq(struct smu_context *smu,
|
|||
smu_v15_0_common_get_dpm_ultimate_freq(smu, SMU_SOCCLK, NULL, &clk_limit);
|
||||
break;
|
||||
case SMU_FCLK:
|
||||
if (amdgpu_ip_version(smu->adev, MP1_HWIP, 0) == IP_VERSION(15, 0, 0))
|
||||
if (amdgpu_ip_version(smu->adev, MP1_HWIP, 0) == IP_VERSION(15, 0, 0) ||
|
||||
amdgpu_ip_version(smu->adev, MP1_HWIP, 0) == IP_VERSION(15, 0, 9))
|
||||
smu_v15_0_common_get_dpm_ultimate_freq(smu, SMU_FCLK, NULL, &clk_limit);
|
||||
else
|
||||
clk_limit = SMU_15_0_UMD_PSTATE_FCLK;
|
||||
|
|
|
|||
|
|
@ -309,7 +309,9 @@ static void analogix_dp_get_adjust_training_lane(struct analogix_dp_device *dp,
|
|||
lane_count = dp->link_train.lane_count;
|
||||
for (lane = 0; lane < lane_count; lane++) {
|
||||
voltage_swing = drm_dp_get_adjust_request_voltage(link_status, lane);
|
||||
voltage_swing >>= DP_TRAIN_VOLTAGE_SWING_SHIFT;
|
||||
pre_emphasis = drm_dp_get_adjust_request_pre_emphasis(link_status, lane);
|
||||
pre_emphasis >>= DP_TRAIN_PRE_EMPHASIS_SHIFT;
|
||||
training_lane = DPCD_VOLTAGE_SWING_SET(voltage_swing) |
|
||||
DPCD_PRE_EMPHASIS_SET(pre_emphasis);
|
||||
|
||||
|
|
@ -355,7 +357,9 @@ static int analogix_dp_process_clock_recovery(struct analogix_dp_device *dp)
|
|||
for (lane = 0; lane < lane_count; lane++) {
|
||||
training_lane = analogix_dp_get_lane_link_training(dp, lane);
|
||||
voltage_swing = drm_dp_get_adjust_request_voltage(link_status, lane);
|
||||
voltage_swing >>= DP_TRAIN_VOLTAGE_SWING_SHIFT;
|
||||
pre_emphasis = drm_dp_get_adjust_request_pre_emphasis(link_status, lane);
|
||||
pre_emphasis >>= DP_TRAIN_PRE_EMPHASIS_SHIFT;
|
||||
|
||||
if (DPCD_VOLTAGE_SWING_GET(training_lane) == voltage_swing &&
|
||||
DPCD_PRE_EMPHASIS_GET(training_lane) == pre_emphasis)
|
||||
|
|
|
|||
|
|
@ -225,16 +225,106 @@ static void drm_fb_helper_resume_worker(struct work_struct *work)
|
|||
console_unlock();
|
||||
}
|
||||
|
||||
static int find_crtc_index_atomic(struct drm_fb_helper *helper)
|
||||
{
|
||||
struct drm_device *dev = helper->dev;
|
||||
int crtc_index = -EINVAL;
|
||||
struct drm_modeset_acquire_ctx ctx;
|
||||
struct drm_plane *plane;
|
||||
int ret = 0;
|
||||
|
||||
drm_modeset_acquire_init(&ctx, 0);
|
||||
|
||||
retry:
|
||||
drm_for_each_plane(plane, dev) {
|
||||
const struct drm_plane_state *plane_state;
|
||||
|
||||
if (plane->type != DRM_PLANE_TYPE_PRIMARY)
|
||||
continue;
|
||||
|
||||
ret = drm_modeset_lock(&plane->mutex, &ctx);
|
||||
if (ret)
|
||||
goto err_drm_modeset_lock;
|
||||
plane_state = plane->state;
|
||||
|
||||
if (plane_state->fb == helper->fb && plane_state->crtc) {
|
||||
struct drm_crtc *crtc = plane_state->crtc;
|
||||
|
||||
ret = drm_modeset_lock(&crtc->mutex, &ctx);
|
||||
if (ret)
|
||||
goto err_drm_modeset_lock;
|
||||
if (crtc->state->active)
|
||||
crtc_index = crtc->index;
|
||||
drm_modeset_unlock(&crtc->mutex);
|
||||
}
|
||||
drm_modeset_unlock(&plane->mutex);
|
||||
|
||||
if (crtc_index >= 0)
|
||||
break;
|
||||
}
|
||||
|
||||
drm_modeset_drop_locks(&ctx);
|
||||
drm_modeset_acquire_fini(&ctx);
|
||||
|
||||
return crtc_index;
|
||||
|
||||
err_drm_modeset_lock:
|
||||
if (ret == -EDEADLK) {
|
||||
drm_modeset_backoff(&ctx);
|
||||
goto retry;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int find_crtc_index_legacy(struct drm_fb_helper *helper)
|
||||
{
|
||||
struct drm_device *dev = helper->dev;
|
||||
struct drm_crtc *crtc;
|
||||
|
||||
drm_for_each_crtc(crtc, dev) {
|
||||
struct drm_plane *plane = crtc->primary;
|
||||
|
||||
if (!crtc->enabled)
|
||||
continue;
|
||||
if (!plane || plane->fb != helper->fb)
|
||||
continue; /* CRTC doesn't display fbdev emulation */
|
||||
|
||||
return crtc->index;
|
||||
}
|
||||
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static int drm_fb_helper_find_crtc_index(struct drm_fb_helper *helper)
|
||||
{
|
||||
struct drm_device *dev = helper->dev;
|
||||
int crtc_index;
|
||||
|
||||
mutex_lock(&dev->mode_config.mutex);
|
||||
|
||||
if (drm_drv_uses_atomic_modeset(dev))
|
||||
crtc_index = find_crtc_index_atomic(helper);
|
||||
else
|
||||
crtc_index = find_crtc_index_legacy(helper);
|
||||
|
||||
mutex_unlock(&dev->mode_config.mutex);
|
||||
|
||||
return crtc_index;
|
||||
}
|
||||
|
||||
static void drm_fb_helper_fb_dirty(struct drm_fb_helper *helper)
|
||||
{
|
||||
struct drm_device *dev = helper->dev;
|
||||
struct drm_clip_rect *clip = &helper->damage_clip;
|
||||
struct drm_clip_rect clip_copy;
|
||||
int crtc_index;
|
||||
unsigned long flags;
|
||||
int ret;
|
||||
|
||||
mutex_lock(&helper->lock);
|
||||
drm_client_modeset_wait_for_vblank(&helper->client, 0);
|
||||
crtc_index = drm_fb_helper_find_crtc_index(helper);
|
||||
if (crtc_index >= 0)
|
||||
drm_client_modeset_wait_for_vblank(&helper->client, crtc_index);
|
||||
mutex_unlock(&helper->lock);
|
||||
|
||||
if (drm_WARN_ON_ONCE(dev, !helper->funcs->fb_dirty))
|
||||
|
|
|
|||
|
|
@ -373,13 +373,25 @@ drm_setclientcap(struct drm_device *dev, void *data, struct drm_file *file_priv)
|
|||
return -EINVAL;
|
||||
file_priv->supports_virtualized_cursor_plane = req->value;
|
||||
break;
|
||||
case DRM_CLIENT_CAP_PLANE_COLOR_PIPELINE:
|
||||
case DRM_CLIENT_CAP_PLANE_COLOR_PIPELINE: {
|
||||
struct drm_plane *plane;
|
||||
bool has_plane_with_color_pipeline = false;
|
||||
|
||||
if (!file_priv->atomic)
|
||||
return -EINVAL;
|
||||
if (req->value > 1)
|
||||
return -EINVAL;
|
||||
drm_for_each_plane(plane, dev) {
|
||||
if (plane->color_pipeline_property) {
|
||||
has_plane_with_color_pipeline = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!has_plane_with_color_pipeline)
|
||||
return -EOPNOTSUPP;
|
||||
file_priv->plane_color_pipeline = req->value;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5737,8 +5737,9 @@ intel_dp_check_mst_status(struct intel_dp *intel_dp)
|
|||
struct intel_display *display = to_intel_display(intel_dp);
|
||||
bool force_retrain = intel_dp->link.force_retrain;
|
||||
bool reprobe_needed = false;
|
||||
int tries = 33;
|
||||
|
||||
for (;;) {
|
||||
while (--tries) {
|
||||
u8 esi[4] = {};
|
||||
u8 ack[4] = {};
|
||||
bool new_irqs;
|
||||
|
|
@ -5781,6 +5782,11 @@ intel_dp_check_mst_status(struct intel_dp *intel_dp)
|
|||
break;
|
||||
}
|
||||
|
||||
if (!tries) {
|
||||
drm_dbg_kms(display->drm, "DPRX ESI not clearing, device may be stuck\n");
|
||||
reprobe_needed = true;
|
||||
}
|
||||
|
||||
return !reprobe_needed;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1223,11 +1223,7 @@ intel_lt_phy_program_port_clock_ctl(struct intel_encoder *encoder,
|
|||
else
|
||||
val |= XELPDP_DDI_CLOCK_SELECT_PREP(display, XELPDP_DDI_CLOCK_SELECT_MAXPCLK);
|
||||
|
||||
/* DP2.0 10G and 20G rates enable MPLLA*/
|
||||
if (port_clock == 1000000 || port_clock == 2000000)
|
||||
val |= XELPDP_SSC_ENABLE_PLLA;
|
||||
else
|
||||
val |= ltpll->ssc_enabled ? XELPDP_SSC_ENABLE_PLLB : 0;
|
||||
val |= ltpll->ssc_enabled ? XELPDP_SSC_ENABLE_PLLA : 0;
|
||||
|
||||
intel_de_rmw(display, XELPDP_PORT_CLOCK_CTL(display, encoder->port),
|
||||
XELPDP_LANE1_PHY_CLOCK_SELECT | XELPDP_FORWARD_CLOCK_UNGATE |
|
||||
|
|
|
|||
|
|
@ -1522,9 +1522,6 @@ int _intel_psr_min_set_context_latency(const struct intel_crtc_state *crtc_state
|
|||
needs_panel_replay)
|
||||
return 0;
|
||||
|
||||
if (intel_vrr_always_use_vrr_tg(display))
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -769,8 +769,8 @@ static int set_proto_ctx_engines(struct drm_i915_file_private *fpriv,
|
|||
struct intel_engine_cs *engine;
|
||||
|
||||
if (copy_from_user(&ci, &user->engines[n], sizeof(ci))) {
|
||||
kfree(set.engines);
|
||||
return -EFAULT;
|
||||
err = -EFAULT;
|
||||
goto err;
|
||||
}
|
||||
|
||||
memset(&set.engines[n], 0, sizeof(set.engines[n]));
|
||||
|
|
@ -786,8 +786,8 @@ static int set_proto_ctx_engines(struct drm_i915_file_private *fpriv,
|
|||
drm_dbg(&i915->drm,
|
||||
"Invalid engine[%d]: { class:%d, instance:%d }\n",
|
||||
n, ci.engine_class, ci.engine_instance);
|
||||
kfree(set.engines);
|
||||
return -ENOENT;
|
||||
err = -ENOENT;
|
||||
goto err;
|
||||
}
|
||||
|
||||
set.engines[n].type = I915_GEM_ENGINE_TYPE_PHYSICAL;
|
||||
|
|
@ -800,15 +800,21 @@ static int set_proto_ctx_engines(struct drm_i915_file_private *fpriv,
|
|||
set_proto_ctx_engines_extensions,
|
||||
ARRAY_SIZE(set_proto_ctx_engines_extensions),
|
||||
&set);
|
||||
if (err) {
|
||||
kfree(set.engines);
|
||||
return err;
|
||||
}
|
||||
if (err)
|
||||
goto err_extensions;
|
||||
|
||||
pc->num_user_engines = set.num_engines;
|
||||
pc->user_engines = set.engines;
|
||||
|
||||
return 0;
|
||||
|
||||
err_extensions:
|
||||
for (n = 0; n < set.num_engines; n++)
|
||||
kfree(set.engines[n].siblings);
|
||||
err:
|
||||
kfree(set.engines);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static int set_proto_ctx_sseu(struct drm_i915_file_private *fpriv,
|
||||
|
|
@ -850,7 +856,7 @@ static int set_proto_ctx_sseu(struct drm_i915_file_private *fpriv,
|
|||
pe = &pc->user_engines[idx];
|
||||
|
||||
/* Only render engine supports RPCS configuration. */
|
||||
if (pe->engine->class != RENDER_CLASS)
|
||||
if (!pe->engine || pe->engine->class != RENDER_CLASS)
|
||||
return -EINVAL;
|
||||
|
||||
sseu = &pe->sseu;
|
||||
|
|
|
|||
|
|
@ -3932,11 +3932,11 @@ execlists_create_virtual(struct intel_engine_cs **siblings, unsigned int count,
|
|||
struct drm_i915_private *i915 = siblings[0]->i915;
|
||||
struct virtual_engine *ve;
|
||||
unsigned int n;
|
||||
int err;
|
||||
int err = -ENOMEM;
|
||||
|
||||
ve = kzalloc_flex(*ve, siblings, count);
|
||||
if (!ve)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
goto err;
|
||||
|
||||
ve->base.i915 = i915;
|
||||
ve->base.gt = siblings[0]->gt;
|
||||
|
|
@ -3968,10 +3968,8 @@ execlists_create_virtual(struct intel_engine_cs **siblings, unsigned int count,
|
|||
intel_engine_init_execlists(&ve->base);
|
||||
|
||||
ve->base.sched_engine = i915_sched_engine_create(ENGINE_VIRTUAL);
|
||||
if (!ve->base.sched_engine) {
|
||||
err = -ENOMEM;
|
||||
goto err_put;
|
||||
}
|
||||
if (!ve->base.sched_engine)
|
||||
goto err_noput;
|
||||
ve->base.sched_engine->private_data = &ve->base;
|
||||
|
||||
ve->base.cops = &virtual_context_ops;
|
||||
|
|
@ -3987,10 +3985,8 @@ execlists_create_virtual(struct intel_engine_cs **siblings, unsigned int count,
|
|||
intel_context_init(&ve->context, &ve->base);
|
||||
|
||||
ve->base.breadcrumbs = intel_breadcrumbs_create(NULL);
|
||||
if (!ve->base.breadcrumbs) {
|
||||
err = -ENOMEM;
|
||||
if (!ve->base.breadcrumbs)
|
||||
goto err_put;
|
||||
}
|
||||
|
||||
for (n = 0; n < count; n++) {
|
||||
struct intel_engine_cs *sibling = siblings[n];
|
||||
|
|
@ -4065,8 +4061,13 @@ execlists_create_virtual(struct intel_engine_cs **siblings, unsigned int count,
|
|||
virtual_engine_initial_hint(ve);
|
||||
return &ve->context;
|
||||
|
||||
err_noput:
|
||||
kfree(ve);
|
||||
goto err;
|
||||
|
||||
err_put:
|
||||
intel_context_put(&ve->context);
|
||||
err:
|
||||
return ERR_PTR(err);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -309,8 +309,8 @@ int pvr_context_create(struct pvr_file *pvr_file, struct drm_pvr_ioctl_create_co
|
|||
goto err_free_ctx;
|
||||
|
||||
ctx->vm_ctx = pvr_vm_context_lookup(pvr_file, args->vm_context_handle);
|
||||
if (IS_ERR(ctx->vm_ctx)) {
|
||||
err = PTR_ERR(ctx->vm_ctx);
|
||||
if (!ctx->vm_ctx) {
|
||||
err = -EINVAL;
|
||||
goto err_free_ctx;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -71,7 +71,7 @@ pvr_fw_trace_init_mask_set(const char *val, const struct kernel_param *kp)
|
|||
return 0;
|
||||
}
|
||||
|
||||
const struct kernel_param_ops pvr_fw_trace_init_mask_ops = {
|
||||
static const struct kernel_param_ops pvr_fw_trace_init_mask_ops = {
|
||||
.set = pvr_fw_trace_init_mask_set,
|
||||
.get = param_get_hexint,
|
||||
};
|
||||
|
|
|
|||
|
|
@ -231,29 +231,26 @@ nvkm_vmm_unref_sptes(struct nvkm_vmm_iter *it, struct nvkm_vmm_pt *pgt,
|
|||
* covered by a number of LPTEs, the LPTEs once again take
|
||||
* control over their address range.
|
||||
*
|
||||
* Determine how many LPTEs need to transition state.
|
||||
* Transition each LPTE individually as each may have a
|
||||
* different target state (sparse, invalid, or valid).
|
||||
*/
|
||||
pgt->pte[ptei].s.spte_valid = false;
|
||||
for (ptes = 1, ptei++; ptei < lpti; ptes++, ptei++) {
|
||||
for (ptei++; ptei < lpti; ptei++) {
|
||||
if (pgt->pte[ptei].s.sptes)
|
||||
break;
|
||||
pgt->pte[ptei].s.spte_valid = false;
|
||||
}
|
||||
|
||||
if (pgt->pte[pteb].s.sparse) {
|
||||
TRA(it, "LPTE %05x: U -> S %d PTEs", pteb, ptes);
|
||||
pair->func->sparse(vmm, pgt->pt[0], pteb, ptes);
|
||||
} else if (!pgt->pte[pteb].s.lpte_valid) {
|
||||
if (pair->func->invalid) {
|
||||
/* If the MMU supports it, restore the LPTE to the
|
||||
* INVALID state to tell the MMU there is no point
|
||||
* trying to fetch the corresponding SPTEs.
|
||||
*/
|
||||
TRA(it, "LPTE %05x: U -> I %d PTEs", pteb, ptes);
|
||||
pair->func->invalid(vmm, pgt->pt[0], pteb, ptes);
|
||||
while (pteb < ptei) {
|
||||
pgt->pte[pteb].s.spte_valid = false;
|
||||
if (pgt->pte[pteb].s.sparse) {
|
||||
TRA(it, "LPTE %05x: U -> S", pteb);
|
||||
pair->func->sparse(vmm, pgt->pt[0], pteb, 1);
|
||||
} else if (!pgt->pte[pteb].s.lpte_valid) {
|
||||
if (pair->func->invalid) {
|
||||
TRA(it, "LPTE %05x: U -> I", pteb);
|
||||
pair->func->invalid(vmm, pgt->pt[0], pteb, 1);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
TRA(it, "LPTE %05x: V %d PTEs", pteb, ptes);
|
||||
pteb++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -180,19 +180,27 @@ static void test_multiple_loops(struct kunit *test)
|
|||
{
|
||||
struct drm_exec exec;
|
||||
|
||||
drm_exec_init(&exec, DRM_EXEC_INTERRUPTIBLE_WAIT, 0);
|
||||
drm_exec_until_all_locked(&exec)
|
||||
{
|
||||
break;
|
||||
}
|
||||
drm_exec_fini(&exec);
|
||||
__label__ drm_exec_retry;
|
||||
|
||||
drm_exec_init(&exec, DRM_EXEC_INTERRUPTIBLE_WAIT, 0);
|
||||
drm_exec_until_all_locked(&exec)
|
||||
{
|
||||
break;
|
||||
drm_exec_init(&exec, DRM_EXEC_INTERRUPTIBLE_WAIT, 0);
|
||||
drm_exec_until_all_locked(&exec)
|
||||
{
|
||||
break;
|
||||
}
|
||||
drm_exec_fini(&exec);
|
||||
}
|
||||
|
||||
{
|
||||
__label__ drm_exec_retry;
|
||||
|
||||
drm_exec_init(&exec, DRM_EXEC_INTERRUPTIBLE_WAIT, 0);
|
||||
drm_exec_until_all_locked(&exec)
|
||||
{
|
||||
break;
|
||||
}
|
||||
drm_exec_fini(&exec);
|
||||
}
|
||||
drm_exec_fini(&exec);
|
||||
KUNIT_SUCCEED(test);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -495,6 +495,8 @@ v3d_get_cpu_indirect_csd_params(struct drm_file *file_priv,
|
|||
sizeof(indirect_csd.wg_uniform_offsets));
|
||||
|
||||
info->indirect = drm_gem_object_lookup(file_priv, indirect_csd.indirect);
|
||||
if (!info->indirect)
|
||||
return -ENOENT;
|
||||
|
||||
return v3d_setup_csd_jobs_and_bos(file_priv, v3d, &indirect_csd.submit,
|
||||
&info->job, &info->clean_job,
|
||||
|
|
|
|||
|
|
@ -9,7 +9,6 @@
|
|||
|
||||
#include <kunit/test-bug.h>
|
||||
#include <kunit/test.h>
|
||||
#include <kunit/test-bug.h>
|
||||
#include <kunit/visibility.h>
|
||||
|
||||
#define PLATFORM_CASE(platform__, graphics_step__) \
|
||||
|
|
|
|||
|
|
@ -292,13 +292,23 @@ int xe_exec_ioctl(struct drm_device *dev, void *data, struct drm_file *file)
|
|||
goto err_exec;
|
||||
}
|
||||
|
||||
/* Wait behind rebinds */
|
||||
/*
|
||||
* Wait behind rebinds and any kernel operations (evictions, defrag
|
||||
* moves, ...) on the VM and all external BOs. The VM's private BOs
|
||||
* carry their kernel ops in the VM dma-resv KERNEL slot, while each
|
||||
* external BO carries them in its own dma-resv KERNEL slot; both are
|
||||
* covered by iterating every object locked by the exec, mirroring the
|
||||
* drm_gpuvm_resv_add_fence() below.
|
||||
*/
|
||||
if (!xe_vm_in_lr_mode(vm)) {
|
||||
err = xe_sched_job_add_deps(job,
|
||||
xe_vm_resv(vm),
|
||||
DMA_RESV_USAGE_KERNEL);
|
||||
if (err)
|
||||
goto err_put_job;
|
||||
struct drm_gem_object *obj;
|
||||
|
||||
drm_exec_for_each_locked_object(exec, obj) {
|
||||
err = xe_sched_job_add_deps(job, obj->resv,
|
||||
DMA_RESV_USAGE_KERNEL);
|
||||
if (err)
|
||||
goto err_put_job;
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < num_syncs && !err; i++)
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user