mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-07-22 02:17:36 -04:00
Merge git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net
Cross-merge networking fixes after downstream PR (net-7.1-rc4). No conflicts, or adjacent changes. Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
1
.mailmap
1
.mailmap
@@ -682,6 +682,7 @@ Peter A Jonsson <pj@ludd.ltu.se>
|
||||
Peter Hilber <peter.hilber@oss.qualcomm.com> <quic_philber@quicinc.com>
|
||||
Peter Oruba <peter.oruba@amd.com>
|
||||
Peter Oruba <peter@oruba.de>
|
||||
Peter Rosin <peda@lysator.liu.se> <peda@axentia.se>
|
||||
Pierre-Louis Bossart <pierre-louis.bossart@linux.dev> <pierre-louis.bossart@linux.intel.com>
|
||||
Pratyush Anand <pratyush.anand@gmail.com> <pratyush.anand@st.com>
|
||||
Pratyush Yadav <pratyush@kernel.org> <ptyadav@amazon.de>
|
||||
|
||||
@@ -16,10 +16,15 @@ allOf:
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
enum:
|
||||
- amlogic,meson6-i2c # Meson6, Meson8 and compatible SoCs
|
||||
- amlogic,meson-gxbb-i2c # GXBB and compatible SoCs
|
||||
- amlogic,meson-axg-i2c # AXG and compatible SoCs
|
||||
oneOf:
|
||||
- items:
|
||||
- enum:
|
||||
- amlogic,t7-i2c
|
||||
- const: amlogic,meson-axg-i2c
|
||||
- enum:
|
||||
- amlogic,meson6-i2c # Meson6, Meson8 and compatible SoCs
|
||||
- amlogic,meson-gxbb-i2c # GXBB and compatible SoCs
|
||||
- amlogic,meson-axg-i2c # AXG and compatible SoCs
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
@@ -22,7 +22,9 @@ properties:
|
||||
compatible:
|
||||
oneOf:
|
||||
- items:
|
||||
- const: apple,t6020-i2c
|
||||
- enum:
|
||||
- apple,t6020-i2c
|
||||
- apple,t8122-i2c
|
||||
- const: apple,t8103-i2c
|
||||
- items:
|
||||
- enum:
|
||||
|
||||
@@ -135,4 +135,4 @@ References
|
||||
|
||||
4. **Lenovo IdeaPad Laptop Driver:** Reference for DMI-based hardware
|
||||
feature gating in Lenovo laptops.
|
||||
https://github.com/torvalds/linux/blob/master/drivers/platform/x86/ideapad-laptop.c
|
||||
https://github.com/torvalds/linux/blob/master/drivers/platform/x86/lenovo/ideapad-laptop.c
|
||||
|
||||
@@ -69,6 +69,15 @@ properties:
|
||||
header:
|
||||
description: For C-compatible languages, header which already defines this value.
|
||||
type: string
|
||||
scope:
|
||||
description: |
|
||||
Visibility of this definition. "uapi" (default) renders into
|
||||
the uAPI header, "kernel" renders into the kernel-side
|
||||
generated header, "user" renders into the user-side
|
||||
generated header. When combined with `header:`, the
|
||||
definition is not rendered, and the named header is
|
||||
included only by code matching the scope.
|
||||
enum: [ uapi, kernel, user ]
|
||||
type:
|
||||
enum: [ const, enum, flags ]
|
||||
doc:
|
||||
|
||||
@@ -83,6 +83,15 @@ properties:
|
||||
header:
|
||||
description: For C-compatible languages, header which already defines this value.
|
||||
type: string
|
||||
scope:
|
||||
description: |
|
||||
Visibility of this definition. "uapi" (default) renders into
|
||||
the uAPI header, "kernel" renders into the kernel-side
|
||||
generated header, "user" renders into the user-side
|
||||
generated header. When combined with `header:`, the
|
||||
definition is not rendered, and the named header is
|
||||
included only by code matching the scope.
|
||||
enum: [ uapi, kernel, user ]
|
||||
type:
|
||||
enum: [ const, enum, flags, struct ] # Trim
|
||||
doc:
|
||||
|
||||
@@ -55,6 +55,15 @@ properties:
|
||||
header:
|
||||
description: For C-compatible languages, header which already defines this value.
|
||||
type: string
|
||||
scope:
|
||||
description: |
|
||||
Visibility of this definition. "uapi" (default) renders into
|
||||
the uAPI header, "kernel" renders into the kernel-side
|
||||
generated header, "user" renders into the user-side
|
||||
generated header. When combined with `header:`, the
|
||||
definition is not rendered, and the named header is
|
||||
included only by code matching the scope.
|
||||
enum: [ uapi, kernel, user ]
|
||||
type:
|
||||
enum: [ const, enum, flags ]
|
||||
doc:
|
||||
|
||||
@@ -87,6 +87,15 @@ properties:
|
||||
header:
|
||||
description: For C-compatible languages, header which already defines this value.
|
||||
type: string
|
||||
scope:
|
||||
description: |
|
||||
Visibility of this definition. "uapi" (default) renders into
|
||||
the uAPI header, "kernel" renders into the kernel-side
|
||||
generated header, "user" renders into the user-side
|
||||
generated header. When combined with `header:`, the
|
||||
definition is not rendered, and the named header is
|
||||
included only by code matching the scope.
|
||||
enum: [ uapi, kernel, user ]
|
||||
type:
|
||||
enum: [ const, enum, flags, struct ] # Trim
|
||||
doc:
|
||||
|
||||
@@ -33,6 +33,11 @@ doc: |
|
||||
@cap-get operation.
|
||||
|
||||
definitions:
|
||||
-
|
||||
type: const
|
||||
name: max-handle-id
|
||||
value: 0x3fffffe
|
||||
scope: kernel
|
||||
-
|
||||
type: enum
|
||||
name: scope
|
||||
@@ -140,6 +145,8 @@ attribute-sets:
|
||||
-
|
||||
name: id
|
||||
type: u32
|
||||
checks:
|
||||
max: max-handle-id
|
||||
doc: |
|
||||
Numeric identifier of a shaper. The id semantic depends on
|
||||
the scope. For @queue scope it's the queue id and for @node
|
||||
|
||||
@@ -24,6 +24,97 @@ Quick access to CPU number, node ID
|
||||
Allows to implement per CPU data efficiently. Documentation is in code and
|
||||
selftests. :(
|
||||
|
||||
Optimized RSEQ V2
|
||||
-----------------
|
||||
|
||||
On architectures which utilize the generic entry code and generic TIF bits
|
||||
the kernel supports runtime optimizations for RSEQ, which also enable
|
||||
enhanced features like scheduler time slice extensions.
|
||||
|
||||
To enable them a task has to register the RSEQ region with at least the
|
||||
length advertised by getauxval(AT_RSEQ_FEATURE_SIZE).
|
||||
|
||||
If existing binaries register with RSEQ_ORIG_SIZE (32 bytes), the kernel
|
||||
keeps the legacy low performance mode enabled to fulfil the expectations
|
||||
of existing users regarding the original RSEQ implementation behaviour.
|
||||
|
||||
The following table documents the ABI and behavioral guarantees of the
|
||||
legacy and the optimized V2 mode.
|
||||
|
||||
.. list-table:: RSEQ modes
|
||||
:header-rows: 1
|
||||
|
||||
* - Nr
|
||||
- What
|
||||
|
||||
- Legacy
|
||||
- Optimized V2
|
||||
|
||||
* - 1
|
||||
- The cpu_id_start, cpu_id, node_id and mm_cid fields (User mode read
|
||||
only)
|
||||
.. Legacy
|
||||
- Updated by the kernel unconditionally after each context switch and
|
||||
before signal delivery
|
||||
.. Optimized V2
|
||||
- Updated by the kernel if and only if they change, i.e. if the task
|
||||
is migrated or mm_cid changes
|
||||
|
||||
* - 2
|
||||
- The rseq_cs critical section field
|
||||
.. Legacy
|
||||
- Evaluated and handled unconditionally after each context switch and
|
||||
before signal delivery
|
||||
.. Optimized V2
|
||||
- Evaluated and handled conditionally only when user space was
|
||||
interrupted and was scheduled out or before delivering a signal in
|
||||
the interrupted context.
|
||||
|
||||
* - 3
|
||||
- Read only fields
|
||||
.. Legacy
|
||||
- No strict enforcement except in debug mode
|
||||
.. Optimized V2
|
||||
- Strict enforcement
|
||||
|
||||
* - 4
|
||||
- membarrier(...RSEQ)
|
||||
.. Legacy
|
||||
- All running threads of the process are interrupted and the ID fields
|
||||
are rewritten and eventually active critical sections are aborted
|
||||
before they return to user space. All threads which are scheduled
|
||||
out whether voluntary or not are covered by #1/#2 above.
|
||||
.. Optimized V2
|
||||
- All running threads of the process are interrupted and eventually
|
||||
active critical sections are aborted before these threads return to
|
||||
user space. The ID fields are only updated if changed as a
|
||||
consequence of the interrupt. All threads which are scheduled out
|
||||
whether voluntary or not are covered by #1/#2 above.
|
||||
|
||||
* - 5
|
||||
- Time slice extensions
|
||||
.. Legacy
|
||||
- Not supported
|
||||
.. Optimized V2
|
||||
- Supported
|
||||
|
||||
The legacy mode is obviously less performant as it does unconditional
|
||||
updates and critical section checks even if not strictly required by the
|
||||
ABI contract. That can't be changed anymore as some users depend on that
|
||||
observed behavior, which in turn enables them to violate the ABI and
|
||||
overwrite the cpu_id_start field for their own purposes. This is obviously
|
||||
discouraged as it renders RSEQ incompatible with the intended usage and
|
||||
breaks the expectation of other libraries in the same application.
|
||||
|
||||
The ABI compliant optimized v2 mode, which respects the read only fields,
|
||||
does not require unconditional updates and therefore is way more
|
||||
performant. The kernel validates the read only fields for compliance. If
|
||||
user space modifies them, the process is killed. Compliant usage allows
|
||||
multiple libraries in the same application to benefit from the RSEQ
|
||||
functionality without disturbing each other. The ABI compliant optimized v2
|
||||
mode also enables extended RSEQ features like time slice extensions.
|
||||
|
||||
|
||||
Scheduler time slice extensions
|
||||
-------------------------------
|
||||
|
||||
@@ -37,7 +128,8 @@ The prerequisites for this functionality are:
|
||||
|
||||
* Enabled at boot time (default is enabled)
|
||||
|
||||
* A rseq userspace pointer has been registered for the thread
|
||||
* A rseq userspace pointer has been registered for the thread in
|
||||
optimized V2 mode
|
||||
|
||||
The thread has to enable the functionality via prctl(2)::
|
||||
|
||||
|
||||
@@ -656,8 +656,8 @@ References
|
||||
See [white-paper]_, [api-spec]_, [amd-apm]_, [kvm-forum]_, and [snp-fw-abi]_
|
||||
for more info.
|
||||
|
||||
.. [white-paper] https://developer.amd.com/wordpress/media/2013/12/AMD_Memory_Encryption_Whitepaper_v7-Public.pdf
|
||||
.. [api-spec] https://support.amd.com/TechDocs/55766_SEV-KM_API_Specification.pdf
|
||||
.. [amd-apm] https://support.amd.com/TechDocs/24593.pdf (section 15.34)
|
||||
.. [white-paper] https://docs.amd.com/v/u/en-US/memory-encryption-white-paper
|
||||
.. [api-spec] https://docs.amd.com/v/u/en-US/55766_PUB_3.24_SEV_API
|
||||
.. [amd-apm] https://docs.amd.com/v/u/en-US/24593_3.44_APM_Vol2 (section 15.34)
|
||||
.. [kvm-forum] https://www.linux-kvm.org/images/7/74/02x08A-Thomas_Lendacky-AMDs_Virtualizatoin_Memory_Encryption_Technology.pdf
|
||||
.. [snp-fw-abi] https://www.amd.com/system/files/TechDocs/56860.pdf
|
||||
.. [snp-fw-abi] https://www.amd.com/content/dam/amd/en/documents/developer/56860.pdf
|
||||
|
||||
53
MAINTAINERS
53
MAINTAINERS
@@ -68,6 +68,12 @@ Maintainers List
|
||||
first. When adding to this list, please keep the entries in
|
||||
alphabetical order.
|
||||
|
||||
3C509 NETWORK DRIVER
|
||||
M: "Maciej W. Rozycki" <macro@orcam.me.uk>
|
||||
L: netdev@vger.kernel.org
|
||||
S: Maintained
|
||||
F: drivers/net/ethernet/3com/3c509.c
|
||||
|
||||
3C59X NETWORK DRIVER
|
||||
M: Steffen Klassert <klassert@kernel.org>
|
||||
L: netdev@vger.kernel.org
|
||||
@@ -2015,7 +2021,7 @@ F: Documentation/hwmon/aquacomputer_d5next.rst
|
||||
F: drivers/hwmon/aquacomputer_d5next.c
|
||||
|
||||
AQUANTIA ETHERNET DRIVER (atlantic)
|
||||
M: Igor Russkikh <irusskikh@marvell.com>
|
||||
M: Sukhdeep Singh <sukhdeeps@marvell.com>
|
||||
L: netdev@vger.kernel.org
|
||||
S: Maintained
|
||||
W: https://www.marvell.com/
|
||||
@@ -2024,7 +2030,7 @@ F: Documentation/networking/device_drivers/ethernet/aquantia/atlantic.rst
|
||||
F: drivers/net/ethernet/aquantia/atlantic/
|
||||
|
||||
AQUANTIA ETHERNET DRIVER PTP SUBSYSTEM
|
||||
M: Egor Pomozov <epomozov@marvell.com>
|
||||
M: Sukhdeep Singh <sukhdeeps@marvell.com>
|
||||
L: netdev@vger.kernel.org
|
||||
S: Maintained
|
||||
W: http://www.aquantia.com
|
||||
@@ -4181,8 +4187,8 @@ F: include/uapi/linux/sonet.h
|
||||
F: net/atm/
|
||||
|
||||
ATMEL MACB ETHERNET DRIVER
|
||||
M: Nicolas Ferre <nicolas.ferre@microchip.com>
|
||||
M: Claudiu Beznea <claudiu.beznea@tuxon.dev>
|
||||
M: Théo Lebrun <theo.lebrun@bootlin.com>
|
||||
R: Conor Dooley <conor.dooley@microchip.com>
|
||||
S: Maintained
|
||||
F: drivers/net/ethernet/cadence/
|
||||
|
||||
@@ -4299,18 +4305,16 @@ F: Documentation/devicetree/bindings/leds/backlight/awinic,aw99706.yaml
|
||||
F: drivers/video/backlight/aw99706.c
|
||||
|
||||
AXENTIA ARM DEVICES
|
||||
M: Peter Rosin <peda@axentia.se>
|
||||
L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
|
||||
S: Maintained
|
||||
S: Orphan
|
||||
F: arch/arm/boot/dts/microchip/at91-linea.dtsi
|
||||
F: arch/arm/boot/dts/microchip/at91-natte.dtsi
|
||||
F: arch/arm/boot/dts/microchip/at91-nattis-2-natte-2.dts
|
||||
F: arch/arm/boot/dts/microchip/at91-tse850-3.dts
|
||||
|
||||
AXENTIA ASOC DRIVERS
|
||||
M: Peter Rosin <peda@axentia.se>
|
||||
L: linux-sound@vger.kernel.org
|
||||
S: Maintained
|
||||
S: Orphan
|
||||
F: Documentation/devicetree/bindings/sound/axentia,*
|
||||
F: sound/soc/atmel/tse850-pcm5142.c
|
||||
|
||||
@@ -6358,6 +6362,7 @@ F: include/uapi/linux/comedi.h
|
||||
COMMON CLK FRAMEWORK
|
||||
M: Michael Turquette <mturquette@baylibre.com>
|
||||
M: Stephen Boyd <sboyd@kernel.org>
|
||||
R: Brian Masney <bmasney@redhat.com>
|
||||
L: linux-clk@vger.kernel.org
|
||||
S: Maintained
|
||||
Q: http://patchwork.kernel.org/project/linux-clk/list/
|
||||
@@ -8199,10 +8204,9 @@ F: include/uapi/drm/nouveau_drm.h
|
||||
CORE DRIVER FOR NVIDIA GPUS [RUST]
|
||||
M: Danilo Krummrich <dakr@kernel.org>
|
||||
M: Alexandre Courbot <acourbot@nvidia.com>
|
||||
L: nouveau@lists.freedesktop.org
|
||||
L: nova-gpu@lists.linux.dev
|
||||
S: Supported
|
||||
W: https://rust-for-linux.com/nova-gpu-driver
|
||||
Q: https://patchwork.freedesktop.org/project/nouveau/
|
||||
B: https://gitlab.freedesktop.org/drm/nova/-/issues
|
||||
C: irc://irc.oftc.net/nouveau
|
||||
T: git https://gitlab.freedesktop.org/drm/rust/kernel.git drm-rust-next
|
||||
@@ -8211,10 +8215,9 @@ F: drivers/gpu/nova-core/
|
||||
|
||||
DRM DRIVER FOR NVIDIA GPUS [RUST]
|
||||
M: Danilo Krummrich <dakr@kernel.org>
|
||||
L: nouveau@lists.freedesktop.org
|
||||
L: nova-gpu@lists.linux.dev
|
||||
S: Supported
|
||||
W: https://rust-for-linux.com/nova-gpu-driver
|
||||
Q: https://patchwork.freedesktop.org/project/nouveau/
|
||||
B: https://gitlab.freedesktop.org/drm/nova/-/issues
|
||||
C: irc://irc.oftc.net/nouveau
|
||||
T: git https://gitlab.freedesktop.org/drm/rust/kernel.git drm-rust-next
|
||||
@@ -12052,7 +12055,7 @@ F: Documentation/i2c/busses/i2c-nvidia-gpu.rst
|
||||
F: drivers/i2c/busses/i2c-nvidia-gpu.c
|
||||
|
||||
I2C MUXES
|
||||
M: Peter Rosin <peda@axentia.se>
|
||||
M: Peter Rosin <peda@lysator.liu.se>
|
||||
L: linux-i2c@vger.kernel.org
|
||||
S: Maintained
|
||||
F: Documentation/devicetree/bindings/i2c/i2c-arb*
|
||||
@@ -12453,7 +12456,7 @@ F: drivers/iio/industrialio-backend.c
|
||||
F: include/linux/iio/backend.h
|
||||
|
||||
IIO DIGITAL POTENTIOMETER DAC
|
||||
M: Peter Rosin <peda@axentia.se>
|
||||
M: Peter Rosin <peda@lysator.liu.se>
|
||||
L: linux-iio@vger.kernel.org
|
||||
S: Maintained
|
||||
F: Documentation/ABI/testing/sysfs-bus-iio-dac-dpot-dac
|
||||
@@ -12461,7 +12464,7 @@ F: Documentation/devicetree/bindings/iio/dac/dpot-dac.yaml
|
||||
F: drivers/iio/dac/dpot-dac.c
|
||||
|
||||
IIO ENVELOPE DETECTOR
|
||||
M: Peter Rosin <peda@axentia.se>
|
||||
M: Peter Rosin <peda@lysator.liu.se>
|
||||
L: linux-iio@vger.kernel.org
|
||||
S: Maintained
|
||||
F: Documentation/ABI/testing/sysfs-bus-iio-adc-envelope-detector
|
||||
@@ -12477,7 +12480,7 @@ F: include/linux/iio/iio-gts-helper.h
|
||||
F: drivers/iio/test/iio-test-gts.c
|
||||
|
||||
IIO MULTIPLEXER
|
||||
M: Peter Rosin <peda@axentia.se>
|
||||
M: Peter Rosin <peda@lysator.liu.se>
|
||||
L: linux-iio@vger.kernel.org
|
||||
S: Maintained
|
||||
F: Documentation/devicetree/bindings/iio/multiplexer/io-channel-mux.yaml
|
||||
@@ -12508,7 +12511,7 @@ F: include/linux/iio/
|
||||
F: tools/iio/
|
||||
|
||||
IIO UNIT CONVERTER
|
||||
M: Peter Rosin <peda@axentia.se>
|
||||
M: Peter Rosin <peda@lysator.liu.se>
|
||||
L: linux-iio@vger.kernel.org
|
||||
S: Maintained
|
||||
F: Documentation/devicetree/bindings/iio/afe/current-sense-amplifier.yaml
|
||||
@@ -14058,6 +14061,7 @@ KERNEL VIRTUAL MACHINE FOR ARM64 (KVM/arm64)
|
||||
M: Marc Zyngier <maz@kernel.org>
|
||||
M: Oliver Upton <oupton@kernel.org>
|
||||
R: Joey Gouly <joey.gouly@arm.com>
|
||||
R: Steffen Eiden <seiden@linux.ibm.com>
|
||||
R: Suzuki K Poulose <suzuki.poulose@arm.com>
|
||||
R: Zenghui Yu <yuzenghui@huawei.com>
|
||||
L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
|
||||
@@ -15724,7 +15728,7 @@ F: Documentation/devicetree/bindings/media/i2c/maxim,max96717.yaml
|
||||
F: drivers/media/i2c/max96717.c
|
||||
|
||||
MAX9860 MONO AUDIO VOICE CODEC DRIVER
|
||||
M: Peter Rosin <peda@axentia.se>
|
||||
M: Peter Rosin <peda@lysator.liu.se>
|
||||
L: linux-sound@vger.kernel.org
|
||||
S: Maintained
|
||||
F: Documentation/devicetree/bindings/sound/max9860.txt
|
||||
@@ -15939,7 +15943,7 @@ F: Documentation/devicetree/bindings/net/can/microchip,mcp251xfd.yaml
|
||||
F: drivers/net/can/spi/mcp251xfd/
|
||||
|
||||
MCP4018 AND MCP4531 MICROCHIP DIGITAL POTENTIOMETER DRIVERS
|
||||
M: Peter Rosin <peda@axentia.se>
|
||||
M: Peter Rosin <peda@lysator.liu.se>
|
||||
L: linux-iio@vger.kernel.org
|
||||
S: Maintained
|
||||
F: Documentation/ABI/testing/sysfs-bus-iio-potentiometer-mcp4531
|
||||
@@ -18244,7 +18248,7 @@ F: include/linux/mmc/
|
||||
F: include/uapi/linux/mmc/
|
||||
|
||||
MULTIPLEXER SUBSYSTEM
|
||||
M: Peter Rosin <peda@axentia.se>
|
||||
M: Peter Rosin <peda@lysator.liu.se>
|
||||
S: Odd Fixes
|
||||
F: Documentation/ABI/testing/sysfs-class-mux*
|
||||
F: Documentation/devicetree/bindings/mux/
|
||||
@@ -19353,7 +19357,7 @@ F: include/dt-bindings/display/tda998x.h
|
||||
K: "nxp,tda998x"
|
||||
|
||||
NXP TFA9879 DRIVER
|
||||
M: Peter Rosin <peda@axentia.se>
|
||||
M: Peter Rosin <peda@lysator.liu.se>
|
||||
L: linux-sound@vger.kernel.org
|
||||
S: Maintained
|
||||
F: Documentation/devicetree/bindings/sound/trivial-codec.yaml
|
||||
@@ -20354,13 +20358,14 @@ F: Documentation/devicetree/bindings/pci/marvell,armada8k-pcie.yaml
|
||||
F: drivers/pci/controller/dwc/pcie-armada8k.c
|
||||
|
||||
PCI DRIVER FOR CADENCE PCIE IP
|
||||
R: Aksh Garg <a-garg7@ti.com>
|
||||
L: linux-pci@vger.kernel.org
|
||||
S: Orphan
|
||||
F: Documentation/devicetree/bindings/pci/cdns,*
|
||||
F: drivers/pci/controller/cadence/*cadence*
|
||||
F: drivers/pci/controller/cadence/
|
||||
|
||||
PCI DRIVER FOR CIX Sky1
|
||||
M: Hans Zhang <hans.zhang@cixtech.com>
|
||||
M: Hans Zhang <18255117159@163.com>
|
||||
L: linux-pci@vger.kernel.org
|
||||
S: Maintained
|
||||
F: Documentation/devicetree/bindings/pci/cix,sky1-pcie-*.yaml
|
||||
@@ -20472,7 +20477,7 @@ F: drivers/pci/controller/plda/pcie-plda-host.c
|
||||
F: drivers/pci/controller/plda/pcie-plda.h
|
||||
|
||||
PCI DRIVER FOR RENESAS R-CAR
|
||||
M: Marek Vasut <marek.vasut+renesas@gmail.com>
|
||||
M: Marek Vasut <marek.vasut+renesas@mailbox.org>
|
||||
M: Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com>
|
||||
L: linux-pci@vger.kernel.org
|
||||
L: linux-renesas-soc@vger.kernel.org
|
||||
|
||||
4
Makefile
4
Makefile
@@ -2,7 +2,7 @@
|
||||
VERSION = 7
|
||||
PATCHLEVEL = 1
|
||||
SUBLEVEL = 0
|
||||
EXTRAVERSION = -rc2
|
||||
EXTRAVERSION = -rc3
|
||||
NAME = Baby Opossum Posse
|
||||
|
||||
# *DOCUMENTATION*
|
||||
@@ -486,6 +486,8 @@ export rust_common_flags := --edition=2021 \
|
||||
-Wclippy::as_ptr_cast_mut \
|
||||
-Wclippy::as_underscore \
|
||||
-Wclippy::cast_lossless \
|
||||
-Aclippy::collapsible_if \
|
||||
-Aclippy::collapsible_match \
|
||||
-Wclippy::ignored_unit_patterns \
|
||||
-Aclippy::incompatible_msrv \
|
||||
-Wclippy::mut_mut \
|
||||
|
||||
@@ -23,6 +23,7 @@ static inline u64 tcr_el2_ps_to_tcr_el1_ips(u64 tcr_el2)
|
||||
static inline u64 translate_tcr_el2_to_tcr_el1(u64 tcr)
|
||||
{
|
||||
return TCR_EPD1_MASK | /* disable TTBR1_EL1 */
|
||||
((tcr & TCR_EL2_DS) ? TCR_DS : 0) |
|
||||
((tcr & TCR_EL2_TBI) ? TCR_TBI0 : 0) |
|
||||
tcr_el2_ps_to_tcr_el1_ips(tcr) |
|
||||
(tcr & TCR_EL2_TG0_MASK) |
|
||||
|
||||
@@ -844,7 +844,7 @@
|
||||
#define INIT_SCTLR_EL2_MMU_ON \
|
||||
(SCTLR_ELx_M | SCTLR_ELx_C | SCTLR_ELx_SA | SCTLR_ELx_I | \
|
||||
SCTLR_ELx_IESB | SCTLR_ELx_WXN | ENDIAN_SET_EL2 | \
|
||||
SCTLR_ELx_ITFSB | SCTLR_EL2_RES1)
|
||||
SCTLR_ELx_ITFSB | SCTLR_ELx_EIS | SCTLR_ELx_EOS | SCTLR_EL2_RES1)
|
||||
|
||||
#define INIT_SCTLR_EL2_MMU_OFF \
|
||||
(SCTLR_EL2_RES1 | ENDIAN_SET_EL2)
|
||||
|
||||
@@ -983,8 +983,8 @@ static int sve_set_common(struct task_struct *target,
|
||||
}
|
||||
|
||||
/* Always zero V regs, FPSR, and FPCR */
|
||||
memset(¤t->thread.uw.fpsimd_state, 0,
|
||||
sizeof(current->thread.uw.fpsimd_state));
|
||||
memset(&target->thread.uw.fpsimd_state, 0,
|
||||
sizeof(target->thread.uw.fpsimd_state));
|
||||
|
||||
/* Registers: FPSIMD-only case */
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
* Author: Christoffer Dall <c.dall@virtualopensystems.com>
|
||||
*/
|
||||
|
||||
#include <linux/arm-smccc.h>
|
||||
#include <linux/bug.h>
|
||||
#include <linux/cpu_pm.h>
|
||||
#include <linux/errno.h>
|
||||
@@ -2638,6 +2639,22 @@ static int init_pkvm_host_sve_state(void)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int pkvm_check_sme_dvmsync_fw_call(void)
|
||||
{
|
||||
struct arm_smccc_res res;
|
||||
|
||||
if (!cpus_have_final_cap(ARM64_WORKAROUND_4193714))
|
||||
return 0;
|
||||
|
||||
arm_smccc_1_1_smc(ARM_SMCCC_CPU_WORKAROUND_4193714, &res);
|
||||
if (res.a0) {
|
||||
kvm_err("pKVM requires firmware support for C1-Pro erratum 4193714\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Finalizes the initialization of hyp mode, once everything else is initialized
|
||||
* and the initialziation process cannot fail.
|
||||
@@ -2838,6 +2855,10 @@ static int __init init_hyp_mode(void)
|
||||
if (err)
|
||||
goto out_err;
|
||||
|
||||
err = pkvm_check_sme_dvmsync_fw_call();
|
||||
if (err)
|
||||
goto out_err;
|
||||
|
||||
err = kvm_hyp_init_protection(hyp_va_bits);
|
||||
if (err) {
|
||||
kvm_err("Failed to init hyp memory protection\n");
|
||||
|
||||
@@ -245,7 +245,7 @@ static inline void __activate_traps_ich_hfgxtr(struct kvm_vcpu *vcpu)
|
||||
__activate_fgt(hctxt, vcpu, ICH_HFGITR_EL2);
|
||||
}
|
||||
|
||||
#define __deactivate_fgt(htcxt, vcpu, reg) \
|
||||
#define __deactivate_fgt(hctxt, vcpu, reg) \
|
||||
do { \
|
||||
write_sysreg_s(ctxt_sys_reg(hctxt, reg), \
|
||||
SYS_ ## reg); \
|
||||
|
||||
@@ -35,6 +35,9 @@ void trace_clock_update(u32 mult, u32 shift, u64 epoch_ns, u64 epoch_cyc)
|
||||
struct clock_data *clock = &trace_clock_data;
|
||||
u64 bank = clock->cur ^ 1;
|
||||
|
||||
if (!mult || shift >= 64)
|
||||
return;
|
||||
|
||||
clock->data[bank].mult = mult;
|
||||
clock->data[bank].shift = shift;
|
||||
clock->data[bank].epoch_ns = epoch_ns;
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
*/
|
||||
|
||||
#include <linux/kvm_host.h>
|
||||
|
||||
#include <asm/kvm_emulate.h>
|
||||
#include <asm/kvm_hyp.h>
|
||||
#include <asm/kvm_mmu.h>
|
||||
@@ -14,6 +15,7 @@
|
||||
|
||||
#include <hyp/fault.h>
|
||||
|
||||
#include <nvhe/arm-smccc.h>
|
||||
#include <nvhe/gfp.h>
|
||||
#include <nvhe/memory.h>
|
||||
#include <nvhe/mem_protect.h>
|
||||
@@ -29,6 +31,19 @@ static struct hyp_pool host_s2_pool;
|
||||
static DEFINE_PER_CPU(struct pkvm_hyp_vm *, __current_vm);
|
||||
#define current_vm (*this_cpu_ptr(&__current_vm))
|
||||
|
||||
static void pkvm_sme_dvmsync_fw_call(void)
|
||||
{
|
||||
if (alternative_has_cap_unlikely(ARM64_WORKAROUND_4193714)) {
|
||||
struct arm_smccc_res res;
|
||||
|
||||
/*
|
||||
* Ignore the return value. Probing for the workaround
|
||||
* availability took place in init_hyp_mode().
|
||||
*/
|
||||
hyp_smccc_1_1_smc(ARM_SMCCC_CPU_WORKAROUND_4193714, &res);
|
||||
}
|
||||
}
|
||||
|
||||
static void guest_lock_component(struct pkvm_hyp_vm *vm)
|
||||
{
|
||||
hyp_spin_lock(&vm->lock);
|
||||
@@ -574,8 +589,14 @@ static int host_stage2_set_owner_metadata_locked(phys_addr_t addr, u64 size,
|
||||
ret = host_stage2_try(kvm_pgtable_stage2_annotate, &host_mmu.pgt,
|
||||
addr, size, &host_s2_pool,
|
||||
KVM_HOST_INVALID_PTE_TYPE_DONATION, annotation);
|
||||
if (!ret)
|
||||
if (!ret) {
|
||||
/*
|
||||
* After stage2 maintenance has happened, but before the page
|
||||
* owner has changed.
|
||||
*/
|
||||
pkvm_sme_dvmsync_fw_call();
|
||||
__host_update_page_state(addr, size, PKVM_NOPAGE);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
@@ -1369,6 +1390,22 @@ int __pkvm_host_reclaim_page_guest(u64 gfn, struct pkvm_hyp_vm *vm)
|
||||
return ret && ret != -EHWPOISON ? ret : 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* share/donate install at most one stage-2 leaf (PAGE_SIZE, or one
|
||||
* KVM_PGTABLE_LAST_LEVEL - 1 block for share). kvm_mmu_cache_min_pages()
|
||||
* bounds the worst-case allocation: exact for the PAGE_SIZE leaf,
|
||||
* conservative by one for the block.
|
||||
*/
|
||||
static int __guest_check_pgtable_memcache(struct pkvm_hyp_vcpu *vcpu)
|
||||
{
|
||||
struct pkvm_hyp_vm *vm = pkvm_hyp_vcpu_to_hyp_vm(vcpu);
|
||||
|
||||
if (vcpu->vcpu.arch.pkvm_memcache.nr_pages < kvm_mmu_cache_min_pages(vm->pgt.mmu))
|
||||
return -ENOMEM;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int __pkvm_host_donate_guest(u64 pfn, u64 gfn, struct pkvm_hyp_vcpu *vcpu)
|
||||
{
|
||||
struct pkvm_hyp_vm *vm = pkvm_hyp_vcpu_to_hyp_vm(vcpu);
|
||||
@@ -1388,6 +1425,10 @@ int __pkvm_host_donate_guest(u64 pfn, u64 gfn, struct pkvm_hyp_vcpu *vcpu)
|
||||
if (ret)
|
||||
goto unlock;
|
||||
|
||||
ret = __guest_check_pgtable_memcache(vcpu);
|
||||
if (ret)
|
||||
goto unlock;
|
||||
|
||||
meta = host_stage2_encode_gfn_meta(vm, gfn);
|
||||
WARN_ON(host_stage2_set_owner_metadata_locked(phys, PAGE_SIZE,
|
||||
PKVM_ID_GUEST, meta));
|
||||
@@ -1453,6 +1494,10 @@ int __pkvm_host_share_guest(u64 pfn, u64 gfn, u64 nr_pages, struct pkvm_hyp_vcpu
|
||||
}
|
||||
}
|
||||
|
||||
ret = __guest_check_pgtable_memcache(vcpu);
|
||||
if (ret)
|
||||
goto unlock;
|
||||
|
||||
for_each_hyp_page(page, phys, size) {
|
||||
set_host_state(page, PKVM_PAGE_SHARED_OWNED);
|
||||
page->host_share_guest_count++;
|
||||
|
||||
@@ -752,16 +752,30 @@ static struct pkvm_hyp_vcpu selftest_vcpu = {
|
||||
struct pkvm_hyp_vcpu *init_selftest_vm(void *virt)
|
||||
{
|
||||
struct hyp_page *p = hyp_virt_to_page(virt);
|
||||
unsigned long min_pages, seeded = 0;
|
||||
int i;
|
||||
|
||||
selftest_vm.kvm.arch.mmu.vtcr = host_mmu.arch.mmu.vtcr;
|
||||
WARN_ON(kvm_guest_prepare_stage2(&selftest_vm, virt));
|
||||
|
||||
/*
|
||||
* Mirror pkvm_refill_memcache() for the share/donate pre-checks;
|
||||
* the selftest invokes those functions directly and would
|
||||
* otherwise see an empty memcache.
|
||||
*/
|
||||
min_pages = kvm_mmu_cache_min_pages(&selftest_vm.kvm.arch.mmu);
|
||||
|
||||
for (i = 0; i < pkvm_selftest_pages(); i++) {
|
||||
if (p[i].refcount)
|
||||
continue;
|
||||
p[i].refcount = 1;
|
||||
hyp_put_page(&selftest_vm.pool, hyp_page_to_virt(&p[i]));
|
||||
if (seeded < min_pages) {
|
||||
push_hyp_memcache(&selftest_vcpu.vcpu.arch.pkvm_memcache,
|
||||
hyp_page_to_virt(&p[i]), hyp_virt_to_phys);
|
||||
seeded++;
|
||||
} else {
|
||||
hyp_put_page(&selftest_vm.pool, hyp_page_to_virt(&p[i]));
|
||||
}
|
||||
}
|
||||
|
||||
selftest_vm.kvm.arch.pkvm.handle = __pkvm_reserve_vm();
|
||||
|
||||
@@ -663,7 +663,8 @@ static void __noreturn __hyp_call_panic(u64 spsr, u64 elr, u64 par)
|
||||
host_ctxt = host_data_ptr(host_ctxt);
|
||||
vcpu = host_ctxt->__hyp_running_vcpu;
|
||||
|
||||
__deactivate_traps(vcpu);
|
||||
if (vcpu)
|
||||
__deactivate_traps(vcpu);
|
||||
sysreg_restore_host_state_vhe(host_ctxt);
|
||||
|
||||
panic("HYP panic:\nPS:%08llx PC:%016llx ESR:%08llx\nFAR:%016llx HPFAR:%016llx PAR:%016llx\nVCPU:%p\n",
|
||||
|
||||
@@ -1576,21 +1576,24 @@ struct kvm_s2_fault_desc {
|
||||
static int gmem_abort(const struct kvm_s2_fault_desc *s2fd)
|
||||
{
|
||||
bool write_fault, exec_fault;
|
||||
bool perm_fault = kvm_vcpu_trap_is_permission_fault(s2fd->vcpu);
|
||||
enum kvm_pgtable_walk_flags flags = KVM_PGTABLE_WALK_SHARED;
|
||||
enum kvm_pgtable_prot prot = KVM_PGTABLE_PROT_R;
|
||||
struct kvm_pgtable *pgt = s2fd->vcpu->arch.hw_mmu->pgt;
|
||||
unsigned long mmu_seq;
|
||||
struct page *page;
|
||||
struct kvm *kvm = s2fd->vcpu->kvm;
|
||||
void *memcache;
|
||||
void *memcache = NULL;
|
||||
kvm_pfn_t pfn;
|
||||
gfn_t gfn;
|
||||
int ret;
|
||||
|
||||
memcache = get_mmu_memcache(s2fd->vcpu);
|
||||
ret = topup_mmu_memcache(s2fd->vcpu, memcache);
|
||||
if (ret)
|
||||
return ret;
|
||||
if (!perm_fault) {
|
||||
memcache = get_mmu_memcache(s2fd->vcpu);
|
||||
ret = topup_mmu_memcache(s2fd->vcpu, memcache);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (s2fd->nested)
|
||||
gfn = kvm_s2_trans_output(s2fd->nested) >> PAGE_SHIFT;
|
||||
@@ -1631,9 +1634,19 @@ static int gmem_abort(const struct kvm_s2_fault_desc *s2fd)
|
||||
goto out_unlock;
|
||||
}
|
||||
|
||||
ret = KVM_PGT_FN(kvm_pgtable_stage2_map)(pgt, s2fd->fault_ipa, PAGE_SIZE,
|
||||
__pfn_to_phys(pfn), prot,
|
||||
memcache, flags);
|
||||
if (perm_fault) {
|
||||
/*
|
||||
* Drop the SW bits in favour of those stored in the
|
||||
* PTE, which will be preserved.
|
||||
*/
|
||||
prot &= ~KVM_NV_GUEST_MAP_SZ;
|
||||
ret = KVM_PGT_FN(kvm_pgtable_stage2_relax_perms)(pgt, s2fd->fault_ipa,
|
||||
prot, flags);
|
||||
} else {
|
||||
ret = KVM_PGT_FN(kvm_pgtable_stage2_map)(pgt, s2fd->fault_ipa, PAGE_SIZE,
|
||||
__pfn_to_phys(pfn), prot,
|
||||
memcache, flags);
|
||||
}
|
||||
|
||||
out_unlock:
|
||||
kvm_release_faultin_page(kvm, page, !!ret, prot & KVM_PGTABLE_PROT_W);
|
||||
|
||||
@@ -76,7 +76,6 @@ CONFIG_SERIAL_8250_CONSOLE=y
|
||||
# CONFIG_HW_RANDOM is not set
|
||||
# CONFIG_HWMON is not set
|
||||
CONFIG_FB=y
|
||||
CONFIG_FIRMWARE_EDID=y
|
||||
CONFIG_FB_TILEBLITTING=y
|
||||
CONFIG_FB_RADEON=y
|
||||
CONFIG_FB_3DFX=y
|
||||
|
||||
@@ -76,7 +76,6 @@ CONFIG_SERIAL_8250_CONSOLE=y
|
||||
CONFIG_NVRAM=y
|
||||
# CONFIG_HWMON is not set
|
||||
CONFIG_FB=y
|
||||
CONFIG_FIRMWARE_EDID=y
|
||||
CONFIG_FB_OF=y
|
||||
CONFIG_FB_MATROX=y
|
||||
CONFIG_FB_MATROX_MILLENIUM=y
|
||||
|
||||
@@ -121,7 +121,6 @@ CONFIG_I2C_CHARDEV=y
|
||||
CONFIG_AGP=m
|
||||
CONFIG_AGP_UNINORTH=m
|
||||
CONFIG_FB=y
|
||||
CONFIG_FIRMWARE_EDID=y
|
||||
CONFIG_FB_TILEBLITTING=y
|
||||
CONFIG_FB_OF=y
|
||||
CONFIG_FB_NVIDIA=y
|
||||
|
||||
@@ -98,7 +98,6 @@ CONFIG_SENSORS_LM85=y
|
||||
CONFIG_SENSORS_LM90=y
|
||||
CONFIG_DRM=y
|
||||
CONFIG_DRM_RADEON=y
|
||||
CONFIG_FIRMWARE_EDID=y
|
||||
CONFIG_FB_TILEBLITTING=y
|
||||
CONFIG_FB_VGA16=y
|
||||
CONFIG_FB_NVIDIA=y
|
||||
|
||||
@@ -196,7 +196,6 @@ CONFIG_I2C_CHARDEV=y
|
||||
# CONFIG_PTP_1588_CLOCK is not set
|
||||
CONFIG_DRM=y
|
||||
CONFIG_DRM_AST=y
|
||||
CONFIG_FIRMWARE_EDID=y
|
||||
CONFIG_FB_OF=y
|
||||
CONFIG_FB_MATROX=m
|
||||
CONFIG_FB_MATROX_MILLENIUM=y
|
||||
|
||||
@@ -249,7 +249,6 @@ CONFIG_I2C_CHARDEV=y
|
||||
CONFIG_I2C_AMD8111=y
|
||||
CONFIG_I2C_PASEMI=y
|
||||
CONFIG_FB=y
|
||||
CONFIG_FIRMWARE_EDID=y
|
||||
CONFIG_FB_OF=y
|
||||
CONFIG_FB_MATROX=y
|
||||
CONFIG_FB_MATROX_MILLENIUM=y
|
||||
|
||||
@@ -118,7 +118,6 @@ CONFIG_SERIAL_8250_CONSOLE=y
|
||||
CONFIG_I2C_CHARDEV=y
|
||||
CONFIG_I2C_AMD8111=y
|
||||
CONFIG_FB=y
|
||||
CONFIG_FIRMWARE_EDID=y
|
||||
CONFIG_FB_OF=y
|
||||
CONFIG_FB_MATROX=y
|
||||
CONFIG_FB_MATROX_MILLENIUM=y
|
||||
|
||||
@@ -214,7 +214,6 @@ CONFIG_SENSORS_IBMPOWERNV=m
|
||||
CONFIG_DRM=m
|
||||
CONFIG_DRM_AST=m
|
||||
CONFIG_FB=y
|
||||
CONFIG_FIRMWARE_EDID=y
|
||||
# CONFIG_VGA_CONSOLE is not set
|
||||
CONFIG_FRAMEBUFFER_CONSOLE=y
|
||||
CONFIG_LOGO=y
|
||||
|
||||
@@ -62,6 +62,12 @@ CC32FLAGSREMOVE += -fno-stack-clash-protection
|
||||
# 32-bit one. clang validates the values passed to these arguments during
|
||||
# parsing, even when -fno-stack-protector is passed afterwards.
|
||||
CC32FLAGSREMOVE += -mstack-protector-guard%
|
||||
# ftrace is disabled for the vdso but arch/powerpc/Makefile adds this define to
|
||||
# KBUILD_CPPFLAGS, which enables use of the 'patchable_function_entry'
|
||||
# attribute in the 'inline' define via 'notrace'. This attribute is not
|
||||
# supported for the powerpcle target, resulting in many instances of
|
||||
# -Wunknown-attributes.
|
||||
CC32FLAGSREMOVE += -DCC_USING_PATCHABLE_FUNCTION_ENTRY
|
||||
endif
|
||||
LD32FLAGS := -Wl,-soname=linux-vdso32.so.1
|
||||
AS32FLAGS := -D__VDSO32__
|
||||
|
||||
@@ -16,4 +16,4 @@ GCOV_PROFILE_core_$(BITS).o := n
|
||||
KCOV_INSTRUMENT_core_$(BITS).o := n
|
||||
UBSAN_SANITIZE_core_$(BITS).o := n
|
||||
KASAN_SANITIZE_core.o := n
|
||||
KASAN_SANITIZE_core_$(BITS) := n
|
||||
KASAN_SANITIZE_core_$(BITS).o := n
|
||||
|
||||
@@ -52,7 +52,14 @@ int exit_vmx_usercopy(void)
|
||||
}
|
||||
EXPORT_SYMBOL(exit_vmx_usercopy);
|
||||
|
||||
int enter_vmx_ops(void)
|
||||
/*
|
||||
* Can be called from kexec copy_page() path with MMU off. The kexec
|
||||
* code sets preempt_count to HARDIRQ_OFFSET so we return early here.
|
||||
* Since in_interrupt() is always inline, __no_sanitize_address on this
|
||||
* function is sufficient to avoid KASAN shadow memory accesses in real
|
||||
* mode.
|
||||
*/
|
||||
int __no_sanitize_address enter_vmx_ops(void)
|
||||
{
|
||||
if (in_interrupt())
|
||||
return 0;
|
||||
|
||||
@@ -2242,6 +2242,7 @@ static void record_and_restart(struct perf_event *event, unsigned long val,
|
||||
const u64 last_period = event->hw.last_period;
|
||||
s64 prev, delta, left;
|
||||
int record = 0;
|
||||
int mark_event = regs->dsisr & MMCRA_SAMPLE_ENABLE;
|
||||
|
||||
if (event->hw.state & PERF_HES_STOPPED) {
|
||||
write_pmc(event->hw.idx, 0);
|
||||
@@ -2304,9 +2305,9 @@ static void record_and_restart(struct perf_event *event, unsigned long val,
|
||||
* In ISA v3.0 and before values "0" and "7" are considered reserved.
|
||||
* In ISA v3.1, value "7" has been used to indicate "larx/stcx".
|
||||
* Drop the sample if "type" has reserved values for this field with a
|
||||
* ISA version check.
|
||||
* ISA version check for marked events.
|
||||
*/
|
||||
if (event->attr.sample_type & PERF_SAMPLE_DATA_SRC &&
|
||||
if (mark_event && event->attr.sample_type & PERF_SAMPLE_DATA_SRC &&
|
||||
ppmu->get_mem_data_src) {
|
||||
val = (regs->dar & SIER_TYPE_MASK) >> SIER_TYPE_SHIFT;
|
||||
if (val == 0 || (val == 7 && !cpu_has_feature(CPU_FTR_ARCH_31))) {
|
||||
|
||||
@@ -477,7 +477,7 @@ int cpm1_gpiochip_add16(struct device *dev)
|
||||
struct device_node *np = dev->of_node;
|
||||
struct cpm1_gpio16_chip *cpm1_gc;
|
||||
struct gpio_chip *gc;
|
||||
u16 mask;
|
||||
u32 mask;
|
||||
|
||||
cpm1_gc = devm_kzalloc(dev, sizeof(*cpm1_gc), GFP_KERNEL);
|
||||
if (!cpm1_gc)
|
||||
@@ -485,7 +485,7 @@ int cpm1_gpiochip_add16(struct device *dev)
|
||||
|
||||
spin_lock_init(&cpm1_gc->lock);
|
||||
|
||||
if (!of_property_read_u16(np, "fsl,cpm1-gpio-irq-mask", &mask)) {
|
||||
if (!of_property_read_u32(np, "fsl,cpm1-gpio-irq-mask", &mask)) {
|
||||
int i, j;
|
||||
|
||||
for (i = 0, j = 0; i < 16; i++)
|
||||
|
||||
@@ -272,13 +272,12 @@ void __init pas_pci_init(void)
|
||||
{
|
||||
struct device_node *root = of_find_node_by_path("/");
|
||||
struct device_node *np;
|
||||
int res;
|
||||
|
||||
pci_set_flags(PCI_SCAN_ALL_PCIE_DEVS);
|
||||
|
||||
np = of_find_compatible_node(root, NULL, "pasemi,rootbus");
|
||||
if (np) {
|
||||
res = pas_add_bridge(np);
|
||||
pas_add_bridge(np);
|
||||
of_node_put(np);
|
||||
}
|
||||
of_node_put(root);
|
||||
|
||||
@@ -950,8 +950,6 @@ static int __init ps3_start_probe_thread(enum ps3_bus_type bus_type)
|
||||
|
||||
static int __init ps3_register_devices(void)
|
||||
{
|
||||
int result;
|
||||
|
||||
if (!firmware_has_feature(FW_FEATURE_PS3_LV1))
|
||||
return -ENODEV;
|
||||
|
||||
@@ -959,7 +957,7 @@ static int __init ps3_register_devices(void)
|
||||
|
||||
/* ps3_repository_dump_bus_info(); */
|
||||
|
||||
result = ps3_start_probe_thread(PS3_BUS_TYPE_STORAGE);
|
||||
ps3_start_probe_thread(PS3_BUS_TYPE_STORAGE);
|
||||
|
||||
ps3_register_vuart_devices();
|
||||
|
||||
|
||||
@@ -16,6 +16,7 @@ static void *htm_buf;
|
||||
static void *htm_status_buf;
|
||||
static void *htm_info_buf;
|
||||
static void *htm_caps_buf;
|
||||
static void *htm_mem_buf;
|
||||
static u32 nodeindex;
|
||||
static u32 nodalchipindex;
|
||||
static u32 coreindexonchip;
|
||||
@@ -86,7 +87,7 @@ static ssize_t htm_return_check(long rc)
|
||||
static ssize_t htmdump_read(struct file *filp, char __user *ubuf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
void *htm_buf = filp->private_data;
|
||||
void *htm_buf_data = filp->private_data;
|
||||
unsigned long page, read_size, available;
|
||||
loff_t offset;
|
||||
long rc, ret;
|
||||
@@ -100,7 +101,7 @@ static ssize_t htmdump_read(struct file *filp, char __user *ubuf,
|
||||
* - last three values are address, size and offset
|
||||
*/
|
||||
rc = htm_hcall_wrapper(htmflags, nodeindex, nodalchipindex, coreindexonchip,
|
||||
htmtype, H_HTM_OP_DUMP_DATA, virt_to_phys(htm_buf),
|
||||
htmtype, H_HTM_OP_DUMP_DATA, virt_to_phys(htm_buf_data),
|
||||
PAGE_SIZE, page);
|
||||
|
||||
ret = htm_return_check(rc);
|
||||
@@ -112,7 +113,61 @@ static ssize_t htmdump_read(struct file *filp, char __user *ubuf,
|
||||
available = PAGE_SIZE;
|
||||
read_size = min(count, available);
|
||||
*ppos += read_size;
|
||||
return simple_read_from_buffer(ubuf, count, &offset, htm_buf, available);
|
||||
return simple_read_from_buffer(ubuf, count, &offset, htm_buf_data, available);
|
||||
}
|
||||
|
||||
static ssize_t htmsystem_mem_read(struct file *filp, char __user *ubuf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
void *htm_mem_data = filp->private_data;
|
||||
long rc, ret;
|
||||
u64 *num_entries;
|
||||
u64 to_copy = 0;
|
||||
loff_t offset = 0;
|
||||
u64 mem_offset = 0;
|
||||
|
||||
/*
|
||||
* Invoke H_HTM call with:
|
||||
* - operation as htm status (H_HTM_OP_STATUS)
|
||||
* - last three values as addr, size and offset. "offset"
|
||||
* is value from output buffer header that points to next
|
||||
* entry to dump. 0 is the first entry to dump. next entry
|
||||
* is read from the output bufferbyte offset 0x8.
|
||||
*
|
||||
* When first time hcall is invoked, mem_offset should be
|
||||
* zero because zero is the first entry.
|
||||
* In the next hcall, offset of next entry to read from is
|
||||
* picked from output buffer header itself. So don't fill
|
||||
* mem_offset for first read.
|
||||
*
|
||||
* If there is no further data to read in next iteration,
|
||||
* offset value from output buffer header will point to -1.
|
||||
*/
|
||||
if (*ppos) {
|
||||
mem_offset = *(u64 *)(htm_mem_data + 0x8);
|
||||
if (mem_offset == -1)
|
||||
return 0;
|
||||
}
|
||||
rc = htm_hcall_wrapper(htmflags, nodeindex, nodalchipindex, coreindexonchip,
|
||||
htmtype, H_HTM_OP_DUMP_SYSMEM_CONF, virt_to_phys(htm_mem_data),
|
||||
PAGE_SIZE, be64_to_cpu(mem_offset));
|
||||
ret = htm_return_check(rc);
|
||||
if (ret <= 0) {
|
||||
pr_debug("H_HTM hcall returned for op: H_HTM_OP_DUMP_SYSMEM_CONF with hcall returning %ld\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* HTM system mem buffer, start of buffer + 0x10 gives the
|
||||
* number of HTM entries in the buffer.
|
||||
* So total count to copy is:
|
||||
* 32 bytes (for first 5 fields) + (number of HTM entries * entry size)
|
||||
*/
|
||||
num_entries = htm_mem_data + 0x10;
|
||||
to_copy = 32 + (be64_to_cpu(*num_entries) * 32);
|
||||
|
||||
*ppos += to_copy;
|
||||
return simple_read_from_buffer(ubuf, count, &offset, htm_mem_data, to_copy);
|
||||
}
|
||||
|
||||
static const struct file_operations htmdump_fops = {
|
||||
@@ -121,6 +176,12 @@ static const struct file_operations htmdump_fops = {
|
||||
.open = simple_open,
|
||||
};
|
||||
|
||||
static const struct file_operations htmsystem_mem_fops = {
|
||||
.llseek = NULL,
|
||||
.read = htmsystem_mem_read,
|
||||
.open = simple_open,
|
||||
};
|
||||
|
||||
static int htmconfigure_set(void *data, u64 val)
|
||||
{
|
||||
long rc, ret;
|
||||
@@ -226,20 +287,31 @@ static int htmstart_get(void *data, u64 *val)
|
||||
static ssize_t htmstatus_read(struct file *filp, char __user *ubuf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
void *htm_status_buf = filp->private_data;
|
||||
void *htm_status_data = filp->private_data;
|
||||
long rc, ret;
|
||||
u64 *num_entries;
|
||||
u64 to_copy;
|
||||
int htmstatus_flag;
|
||||
loff_t offset = 0;
|
||||
u64 status_offset = 0;
|
||||
|
||||
/*
|
||||
* Invoke H_HTM call with:
|
||||
* - operation as htm status (H_HTM_OP_STATUS)
|
||||
* - last three values as addr, size and offset
|
||||
* - last three values as addr, size and offset.
|
||||
* "offset" is value from output buffer header
|
||||
* that points to next entry to dump. 0 is the first
|
||||
* entry to dump. next entry is read from the output
|
||||
* bufferbyte offset 0x8.
|
||||
*/
|
||||
if (*ppos) {
|
||||
status_offset = *(u64 *)(htm_status_data + 0x8);
|
||||
if (status_offset == -1)
|
||||
return 0;
|
||||
}
|
||||
rc = htm_hcall_wrapper(htmflags, nodeindex, nodalchipindex, coreindexonchip,
|
||||
htmtype, H_HTM_OP_STATUS, virt_to_phys(htm_status_buf),
|
||||
PAGE_SIZE, 0);
|
||||
htmtype, H_HTM_OP_STATUS, virt_to_phys(htm_status_data),
|
||||
PAGE_SIZE, be64_to_cpu(status_offset));
|
||||
|
||||
ret = htm_return_check(rc);
|
||||
if (ret <= 0) {
|
||||
@@ -255,13 +327,15 @@ static ssize_t htmstatus_read(struct file *filp, char __user *ubuf,
|
||||
* So total count to copy is:
|
||||
* 32 bytes (for first 7 fields) + (number of HTM entries * entry size)
|
||||
*/
|
||||
num_entries = htm_status_buf + 0x10;
|
||||
num_entries = htm_status_data + 0x10;
|
||||
if (htmtype == 0x2)
|
||||
htmstatus_flag = 0x8;
|
||||
else
|
||||
htmstatus_flag = 0x6;
|
||||
to_copy = 32 + (be64_to_cpu(*num_entries) * htmstatus_flag);
|
||||
return simple_read_from_buffer(ubuf, count, ppos, htm_status_buf, to_copy);
|
||||
*ppos += to_copy;
|
||||
|
||||
return simple_read_from_buffer(ubuf, count, &offset, htm_status_data, to_copy);
|
||||
}
|
||||
|
||||
static const struct file_operations htmstatus_fops = {
|
||||
@@ -273,19 +347,30 @@ static const struct file_operations htmstatus_fops = {
|
||||
static ssize_t htminfo_read(struct file *filp, char __user *ubuf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
void *htm_info_buf = filp->private_data;
|
||||
void *htm_info_data = filp->private_data;
|
||||
long rc, ret;
|
||||
u64 *num_entries;
|
||||
u64 to_copy;
|
||||
loff_t offset = 0;
|
||||
u64 info_offset = 0;
|
||||
|
||||
/*
|
||||
* Invoke H_HTM call with:
|
||||
* - operation as htm status (H_HTM_OP_STATUS)
|
||||
* - last three values as addr, size and offset
|
||||
* "offset" is value from output buffer header
|
||||
* that points to next entry to dump. 0 is the first
|
||||
* entry to dump. next entry is read from the output
|
||||
* bufferbyte offset 0x8.
|
||||
*/
|
||||
if (*ppos) {
|
||||
info_offset = *(u64 *)(htm_info_data + 0x8);
|
||||
if (info_offset == -1)
|
||||
return 0;
|
||||
}
|
||||
rc = htm_hcall_wrapper(htmflags, nodeindex, nodalchipindex, coreindexonchip,
|
||||
htmtype, H_HTM_OP_DUMP_SYSPROC_CONF, virt_to_phys(htm_info_buf),
|
||||
PAGE_SIZE, 0);
|
||||
htmtype, H_HTM_OP_DUMP_SYSPROC_CONF, virt_to_phys(htm_info_data),
|
||||
PAGE_SIZE, be64_to_cpu(info_offset));
|
||||
|
||||
ret = htm_return_check(rc);
|
||||
if (ret <= 0) {
|
||||
@@ -301,15 +386,17 @@ static ssize_t htminfo_read(struct file *filp, char __user *ubuf,
|
||||
* So total count to copy is:
|
||||
* 32 bytes (for first 5 fields) + (number of HTM entries * entry size)
|
||||
*/
|
||||
num_entries = htm_info_buf + 0x10;
|
||||
num_entries = htm_info_data + 0x10;
|
||||
to_copy = 32 + (be64_to_cpu(*num_entries) * 16);
|
||||
return simple_read_from_buffer(ubuf, count, ppos, htm_info_buf, to_copy);
|
||||
|
||||
*ppos += to_copy;
|
||||
return simple_read_from_buffer(ubuf, count, &offset, htm_info_data, to_copy);
|
||||
}
|
||||
|
||||
static ssize_t htmcaps_read(struct file *filp, char __user *ubuf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
void *htm_caps_buf = filp->private_data;
|
||||
void *htm_caps_data = filp->private_data;
|
||||
long rc, ret;
|
||||
|
||||
/*
|
||||
@@ -319,7 +406,7 @@ static ssize_t htmcaps_read(struct file *filp, char __user *ubuf,
|
||||
* and zero
|
||||
*/
|
||||
rc = htm_hcall_wrapper(htmflags, nodeindex, nodalchipindex, coreindexonchip,
|
||||
htmtype, H_HTM_OP_CAPABILITIES, virt_to_phys(htm_caps_buf),
|
||||
htmtype, H_HTM_OP_CAPABILITIES, virt_to_phys(htm_caps_data),
|
||||
0x80, 0);
|
||||
|
||||
ret = htm_return_check(rc);
|
||||
@@ -328,7 +415,7 @@ static ssize_t htmcaps_read(struct file *filp, char __user *ubuf,
|
||||
return ret;
|
||||
}
|
||||
|
||||
return simple_read_from_buffer(ubuf, count, ppos, htm_caps_buf, 0x80);
|
||||
return simple_read_from_buffer(ubuf, count, ppos, htm_caps_data, 0x80);
|
||||
}
|
||||
|
||||
static const struct file_operations htminfo_fops = {
|
||||
@@ -457,9 +544,17 @@ static int htmdump_init_debugfs(void)
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
/* Memory to present HTM system memory configuration */
|
||||
htm_mem_buf = kmalloc(PAGE_SIZE, GFP_KERNEL);
|
||||
if (!htm_mem_buf) {
|
||||
pr_err("Failed to allocate htm mem buf\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
debugfs_create_file("htmstatus", 0400, htmdump_debugfs_dir, htm_status_buf, &htmstatus_fops);
|
||||
debugfs_create_file("htminfo", 0400, htmdump_debugfs_dir, htm_info_buf, &htminfo_fops);
|
||||
debugfs_create_file("htmcaps", 0400, htmdump_debugfs_dir, htm_caps_buf, &htmcaps_fops);
|
||||
debugfs_create_file("htmsystem_mem", 0400, htmdump_debugfs_dir, htm_mem_buf, &htmsystem_mem_fops);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -482,6 +577,10 @@ static void __exit htmdump_exit(void)
|
||||
{
|
||||
debugfs_remove_recursive(htmdump_debugfs_dir);
|
||||
kfree(htm_buf);
|
||||
kfree(htm_status_buf);
|
||||
kfree(htm_info_buf);
|
||||
kfree(htm_caps_buf);
|
||||
kfree(htm_mem_buf);
|
||||
}
|
||||
|
||||
module_init(htmdump_init);
|
||||
|
||||
@@ -190,33 +190,34 @@ static int hvpipe_rtas_recv_msg(char __user *buf, int size)
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
ret = rtas_ibm_receive_hvpipe_msg(work_area, &srcID,
|
||||
&bytes_written);
|
||||
if (!ret) {
|
||||
/*
|
||||
* Recv HVPIPE RTAS is successful.
|
||||
* When releasing FD or no one is waiting on the
|
||||
* specific source, issue recv HVPIPE RTAS call
|
||||
* so that pipe is not blocked - this func is called
|
||||
* with NULL buf.
|
||||
*/
|
||||
if (buf) {
|
||||
if (size < bytes_written) {
|
||||
pr_err("Received the payload size = %d, but the buffer size = %d\n",
|
||||
bytes_written, size);
|
||||
bytes_written = size;
|
||||
}
|
||||
ret = copy_to_user(buf,
|
||||
rtas_work_area_raw_buf(work_area),
|
||||
bytes_written);
|
||||
if (!ret)
|
||||
ret = bytes_written;
|
||||
}
|
||||
} else {
|
||||
pr_err("ibm,receive-hvpipe-msg failed with %d\n",
|
||||
ret);
|
||||
/*
|
||||
* Recv HVPIPE RTAS is successful.
|
||||
* When releasing FD or no one is waiting on the
|
||||
* specific source, issue recv HVPIPE RTAS call
|
||||
* so that pipe is not blocked - this func is called
|
||||
* with NULL buf.
|
||||
*/
|
||||
ret = rtas_ibm_receive_hvpipe_msg(work_area, &srcID, &bytes_written);
|
||||
if (ret) {
|
||||
pr_err("ibm,receive-hvpipe-msg failed with %d\n", ret);
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (!buf)
|
||||
goto out;
|
||||
|
||||
if (size < bytes_written) {
|
||||
pr_err("Received the payload size = %d, but the buffer size = %d\n",
|
||||
bytes_written, size);
|
||||
bytes_written = size;
|
||||
}
|
||||
|
||||
if (copy_to_user(buf, rtas_work_area_raw_buf(work_area), bytes_written))
|
||||
ret = -EFAULT;
|
||||
else
|
||||
ret = bytes_written;
|
||||
|
||||
out:
|
||||
rtas_work_area_free(work_area);
|
||||
return ret;
|
||||
}
|
||||
@@ -327,8 +328,8 @@ static ssize_t papr_hvpipe_handle_read(struct file *file,
|
||||
{
|
||||
|
||||
struct hvpipe_source_info *src_info = file->private_data;
|
||||
struct papr_hvpipe_hdr hdr;
|
||||
long ret;
|
||||
struct papr_hvpipe_hdr hdr = {};
|
||||
ssize_t ret = 0;
|
||||
|
||||
/*
|
||||
* Return -ENXIO during migration
|
||||
@@ -376,7 +377,7 @@ static ssize_t papr_hvpipe_handle_read(struct file *file,
|
||||
|
||||
ret = copy_to_user(buf, &hdr, HVPIPE_HDR_LEN);
|
||||
if (ret)
|
||||
return ret;
|
||||
return -EFAULT;
|
||||
|
||||
/*
|
||||
* Message event has payload, so get the payload with
|
||||
@@ -385,19 +386,23 @@ static ssize_t papr_hvpipe_handle_read(struct file *file,
|
||||
if (hdr.flags & HVPIPE_MSG_AVAILABLE) {
|
||||
ret = hvpipe_rtas_recv_msg(buf + HVPIPE_HDR_LEN,
|
||||
size - HVPIPE_HDR_LEN);
|
||||
if (ret > 0) {
|
||||
/*
|
||||
* Always clear MSG_AVAILABLE once the RTAS call has drained
|
||||
* the message, regardless of whether copy_to_user succeeded.
|
||||
*/
|
||||
if (ret >= 0 || ret == -EFAULT)
|
||||
src_info->hvpipe_status &= ~HVPIPE_MSG_AVAILABLE;
|
||||
ret += HVPIPE_HDR_LEN;
|
||||
}
|
||||
} else if (hdr.flags & HVPIPE_LOST_CONNECTION) {
|
||||
/*
|
||||
* Hypervisor is closing the pipe for the specific
|
||||
* source. So notify user space.
|
||||
*/
|
||||
src_info->hvpipe_status &= ~HVPIPE_LOST_CONNECTION;
|
||||
ret = HVPIPE_HDR_LEN;
|
||||
}
|
||||
|
||||
if (ret >= 0)
|
||||
ret += HVPIPE_HDR_LEN;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -444,16 +449,18 @@ static int papr_hvpipe_handle_release(struct inode *inode,
|
||||
struct file *file)
|
||||
{
|
||||
struct hvpipe_source_info *src_info;
|
||||
unsigned long flags;
|
||||
|
||||
/*
|
||||
* Hold the lock, remove source from src_list, reset the
|
||||
* hvpipe status and release the lock to prevent any race
|
||||
* with message event IRQ.
|
||||
*/
|
||||
spin_lock(&hvpipe_src_list_lock);
|
||||
spin_lock_irqsave(&hvpipe_src_list_lock, flags);
|
||||
src_info = file->private_data;
|
||||
list_del(&src_info->list);
|
||||
file->private_data = NULL;
|
||||
spin_unlock_irqrestore(&hvpipe_src_list_lock, flags);
|
||||
/*
|
||||
* If the pipe for this specific source has any pending
|
||||
* payload, issue recv HVPIPE RTAS so that pipe will not
|
||||
@@ -461,10 +468,8 @@ static int papr_hvpipe_handle_release(struct inode *inode,
|
||||
*/
|
||||
if (src_info->hvpipe_status & HVPIPE_MSG_AVAILABLE) {
|
||||
src_info->hvpipe_status = 0;
|
||||
spin_unlock(&hvpipe_src_list_lock);
|
||||
hvpipe_rtas_recv_msg(NULL, 0);
|
||||
} else
|
||||
spin_unlock(&hvpipe_src_list_lock);
|
||||
}
|
||||
|
||||
kfree(src_info);
|
||||
return 0;
|
||||
@@ -479,50 +484,53 @@ static const struct file_operations papr_hvpipe_handle_ops = {
|
||||
|
||||
static int papr_hvpipe_dev_create_handle(u32 srcID)
|
||||
{
|
||||
struct hvpipe_source_info *src_info __free(kfree) = NULL;
|
||||
|
||||
spin_lock(&hvpipe_src_list_lock);
|
||||
/*
|
||||
* Do not allow more than one process communicates with
|
||||
* each source.
|
||||
*/
|
||||
src_info = hvpipe_find_source(srcID);
|
||||
if (src_info) {
|
||||
spin_unlock(&hvpipe_src_list_lock);
|
||||
pr_err("pid(%d) is already using the source(%d)\n",
|
||||
src_info->tsk->pid, srcID);
|
||||
return -EALREADY;
|
||||
}
|
||||
spin_unlock(&hvpipe_src_list_lock);
|
||||
struct hvpipe_source_info *src_info;
|
||||
int fd;
|
||||
unsigned long flags;
|
||||
|
||||
src_info = kzalloc_obj(*src_info, GFP_KERNEL_ACCOUNT);
|
||||
if (!src_info)
|
||||
return -ENOMEM;
|
||||
|
||||
src_info->srcID = srcID;
|
||||
src_info->tsk = current;
|
||||
init_waitqueue_head(&src_info->recv_wqh);
|
||||
|
||||
FD_PREPARE(fdf, O_RDONLY | O_CLOEXEC,
|
||||
anon_inode_getfile("[papr-hvpipe]", &papr_hvpipe_handle_ops,
|
||||
(void *)src_info, O_RDWR));
|
||||
if (fdf.err)
|
||||
return fdf.err;
|
||||
|
||||
retain_and_null_ptr(src_info);
|
||||
spin_lock(&hvpipe_src_list_lock);
|
||||
/*
|
||||
* If two processes are executing ioctl() for the same
|
||||
* source ID concurrently, prevent the second process to
|
||||
* acquire FD.
|
||||
* Do not allow more than one process communicates with
|
||||
* each source.
|
||||
*/
|
||||
spin_lock_irqsave(&hvpipe_src_list_lock, flags);
|
||||
if (hvpipe_find_source(srcID)) {
|
||||
spin_unlock(&hvpipe_src_list_lock);
|
||||
spin_unlock_irqrestore(&hvpipe_src_list_lock, flags);
|
||||
pr_err("pid(%s:%d) could not get the source(%d)\n",
|
||||
current->comm, task_pid_nr(current), srcID);
|
||||
kfree(src_info);
|
||||
return -EALREADY;
|
||||
}
|
||||
list_add(&src_info->list, &hvpipe_src_list);
|
||||
spin_unlock(&hvpipe_src_list_lock);
|
||||
return fd_publish(fdf);
|
||||
spin_unlock_irqrestore(&hvpipe_src_list_lock, flags);
|
||||
|
||||
fd = FD_ADD(O_RDONLY | O_CLOEXEC,
|
||||
anon_inode_getfile("[papr-hvpipe]", &papr_hvpipe_handle_ops,
|
||||
(void *)src_info, O_RDWR));
|
||||
if (fd < 0) {
|
||||
spin_lock_irqsave(&hvpipe_src_list_lock, flags);
|
||||
list_del(&src_info->list);
|
||||
spin_unlock_irqrestore(&hvpipe_src_list_lock, flags);
|
||||
/*
|
||||
* if we fail to add FD, that means no userspace program is
|
||||
* polling. In that case if there is a msg pending because the
|
||||
* interrupt was fired after the src_info was added to the
|
||||
* global list, then let's consume it here, to unblock the
|
||||
* hvpipe
|
||||
*/
|
||||
if (src_info->hvpipe_status & HVPIPE_MSG_AVAILABLE)
|
||||
hvpipe_rtas_recv_msg(NULL, 0);
|
||||
kfree(src_info);
|
||||
return fd;
|
||||
}
|
||||
|
||||
return fd;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -685,20 +693,19 @@ static int __init enable_hvpipe_IRQ(void)
|
||||
struct device_node *np;
|
||||
|
||||
hvpipe_check_exception_token = rtas_function_token(RTAS_FN_CHECK_EXCEPTION);
|
||||
if (hvpipe_check_exception_token == RTAS_UNKNOWN_SERVICE)
|
||||
if (hvpipe_check_exception_token == RTAS_UNKNOWN_SERVICE)
|
||||
return -ENODEV;
|
||||
|
||||
/* hvpipe events */
|
||||
np = of_find_node_by_path("/event-sources/ibm,hvpipe-msg-events");
|
||||
if (np != NULL) {
|
||||
request_event_sources_irqs(np, hvpipe_event_interrupt,
|
||||
"HPIPE_EVENT");
|
||||
of_node_put(np);
|
||||
} else {
|
||||
pr_err("Can not enable hvpipe event IRQ\n");
|
||||
if (!np) {
|
||||
pr_err("No device node found, could not enable hvpipe event IRQ\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
request_event_sources_irqs(np, hvpipe_event_interrupt, "HPIPE_EVENT");
|
||||
of_node_put(np);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -775,23 +782,29 @@ static int __init papr_hvpipe_init(void)
|
||||
}
|
||||
|
||||
ret = enable_hvpipe_IRQ();
|
||||
if (!ret) {
|
||||
ret = set_hvpipe_sys_param(1);
|
||||
if (!ret)
|
||||
ret = misc_register(&papr_hvpipe_dev);
|
||||
}
|
||||
if (ret)
|
||||
goto out_wq;
|
||||
|
||||
if (!ret) {
|
||||
pr_info("hvpipe feature is enabled\n");
|
||||
hvpipe_feature = true;
|
||||
return 0;
|
||||
}
|
||||
ret = misc_register(&papr_hvpipe_dev);
|
||||
if (ret)
|
||||
goto out_wq;
|
||||
|
||||
pr_err("hvpipe feature is not enabled %d\n", ret);
|
||||
ret = set_hvpipe_sys_param(1);
|
||||
if (ret)
|
||||
goto out_misc;
|
||||
|
||||
pr_info("hvpipe feature is enabled\n");
|
||||
hvpipe_feature = true;
|
||||
return 0;
|
||||
|
||||
out_misc:
|
||||
misc_deregister(&papr_hvpipe_dev);
|
||||
out_wq:
|
||||
destroy_workqueue(papr_hvpipe_wq);
|
||||
out:
|
||||
kfree(papr_hvpipe_work);
|
||||
papr_hvpipe_work = NULL;
|
||||
pr_err("hvpipe feature is not enabled %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
machine_device_initcall(pseries, papr_hvpipe_init);
|
||||
|
||||
@@ -21,7 +21,6 @@ struct hvpipe_source_info {
|
||||
u32 srcID;
|
||||
u32 hvpipe_status;
|
||||
wait_queue_head_t recv_wqh; /* wake up poll() waitq */
|
||||
struct task_struct *tsk;
|
||||
};
|
||||
|
||||
/*
|
||||
|
||||
@@ -3310,8 +3310,7 @@ static void aen_host_forward(unsigned long si)
|
||||
struct zpci_gaite *gaite;
|
||||
struct kvm *kvm;
|
||||
|
||||
gaite = (struct zpci_gaite *)aift->gait +
|
||||
(si * sizeof(struct zpci_gaite));
|
||||
gaite = aift->gait + si;
|
||||
if (gaite->count == 0)
|
||||
return;
|
||||
if (gaite->aisb != 0)
|
||||
|
||||
@@ -166,7 +166,7 @@ static int kvm_zpci_set_airq(struct zpci_dev *zdev)
|
||||
fib.fmt0.noi = airq_iv_end(zdev->aibv);
|
||||
fib.fmt0.aibv = virt_to_phys(zdev->aibv->vector);
|
||||
fib.fmt0.aibvo = 0;
|
||||
fib.fmt0.aisb = virt_to_phys(aift->sbv->vector + (zdev->aisb / 64) * 8);
|
||||
fib.fmt0.aisb = virt_to_phys(aift->sbv->vector) + (zdev->aisb / 64) * 8;
|
||||
fib.fmt0.aisbo = zdev->aisb & 63;
|
||||
fib.gd = zdev->gisa;
|
||||
|
||||
@@ -290,8 +290,7 @@ static int kvm_s390_pci_aif_enable(struct zpci_dev *zdev, struct zpci_fib *fib,
|
||||
phys_to_virt(fib->fmt0.aibv));
|
||||
|
||||
spin_lock_irq(&aift->gait_lock);
|
||||
gaite = (struct zpci_gaite *)aift->gait + (zdev->aisb *
|
||||
sizeof(struct zpci_gaite));
|
||||
gaite = aift->gait + zdev->aisb;
|
||||
|
||||
/* If assist not requested, host will get all alerts */
|
||||
if (assist)
|
||||
@@ -309,7 +308,7 @@ static int kvm_s390_pci_aif_enable(struct zpci_dev *zdev, struct zpci_fib *fib,
|
||||
|
||||
/* Update guest FIB for re-issue */
|
||||
fib->fmt0.aisbo = zdev->aisb & 63;
|
||||
fib->fmt0.aisb = virt_to_phys(aift->sbv->vector + (zdev->aisb / 64) * 8);
|
||||
fib->fmt0.aisb = virt_to_phys(aift->sbv->vector) + (zdev->aisb / 64) * 8;
|
||||
fib->fmt0.isc = gisc;
|
||||
|
||||
/* Save some guest fib values in the host for later use */
|
||||
@@ -357,8 +356,7 @@ static int kvm_s390_pci_aif_disable(struct zpci_dev *zdev, bool force)
|
||||
if (zdev->kzdev->fib.fmt0.aibv == 0)
|
||||
goto out;
|
||||
spin_lock_irq(&aift->gait_lock);
|
||||
gaite = (struct zpci_gaite *)aift->gait + (zdev->aisb *
|
||||
sizeof(struct zpci_gaite));
|
||||
gaite = aift->gait + zdev->aisb;
|
||||
isc = gaite->gisc;
|
||||
gaite->count--;
|
||||
if (gaite->count == 0) {
|
||||
|
||||
@@ -1294,13 +1294,16 @@ int x86_perf_rdpmc_index(struct perf_event *event)
|
||||
return event->hw.event_base_rdpmc;
|
||||
}
|
||||
|
||||
static inline int match_prev_assignment(struct hw_perf_event *hwc,
|
||||
static inline int match_prev_assignment(struct perf_event *event,
|
||||
struct cpu_hw_events *cpuc,
|
||||
int i)
|
||||
{
|
||||
struct hw_perf_event *hwc = &event->hw;
|
||||
|
||||
return hwc->idx == cpuc->assign[i] &&
|
||||
hwc->last_cpu == smp_processor_id() &&
|
||||
hwc->last_tag == cpuc->tags[i];
|
||||
hwc->last_cpu == smp_processor_id() &&
|
||||
hwc->last_tag == cpuc->tags[i] &&
|
||||
!is_acr_event_group(event);
|
||||
}
|
||||
|
||||
static void x86_pmu_start(struct perf_event *event, int flags);
|
||||
@@ -1346,7 +1349,7 @@ static void x86_pmu_enable(struct pmu *pmu)
|
||||
* - no other event has used the counter since
|
||||
*/
|
||||
if (hwc->idx == -1 ||
|
||||
match_prev_assignment(hwc, cpuc, i))
|
||||
match_prev_assignment(event, cpuc, i))
|
||||
continue;
|
||||
|
||||
/*
|
||||
@@ -1367,7 +1370,7 @@ static void x86_pmu_enable(struct pmu *pmu)
|
||||
event = cpuc->event_list[i];
|
||||
hwc = &event->hw;
|
||||
|
||||
if (!match_prev_assignment(hwc, cpuc, i))
|
||||
if (!match_prev_assignment(event, cpuc, i))
|
||||
x86_assign_hw_event(event, cpuc, i);
|
||||
else if (i < n_running)
|
||||
continue;
|
||||
|
||||
@@ -3118,11 +3118,11 @@ static void intel_pmu_enable_fixed(struct perf_event *event)
|
||||
intel_set_masks(event, idx);
|
||||
|
||||
/*
|
||||
* Enable IRQ generation (0x8), if not PEBS,
|
||||
* and enable ring-3 counting (0x2) and ring-0 counting (0x1)
|
||||
* if requested:
|
||||
* Enable IRQ generation (0x8), if not PEBS or self-reloaded
|
||||
* ACR event, and enable ring-3 counting (0x2) and ring-0
|
||||
* counting (0x1) if requested:
|
||||
*/
|
||||
if (!event->attr.precise_ip)
|
||||
if (!event->attr.precise_ip && !is_acr_self_reload_event(event))
|
||||
bits |= INTEL_FIXED_0_ENABLE_PMI;
|
||||
if (hwc->config & ARCH_PERFMON_EVENTSEL_USR)
|
||||
bits |= INTEL_FIXED_0_USER;
|
||||
@@ -3306,6 +3306,15 @@ static void intel_pmu_enable_event(struct perf_event *event)
|
||||
intel_set_masks(event, idx);
|
||||
static_call_cond(intel_pmu_enable_acr_event)(event);
|
||||
static_call_cond(intel_pmu_enable_event_ext)(event);
|
||||
/*
|
||||
* For self-reloaded ACR event, don't enable PMI since
|
||||
* HW won't set overflow bit in GLOBAL_STATUS. Otherwise,
|
||||
* the PMI would be recognized as a suspicious NMI.
|
||||
*/
|
||||
if (is_acr_self_reload_event(event))
|
||||
hwc->config &= ~ARCH_PERFMON_EVENTSEL_INT;
|
||||
else if (!event->attr.precise_ip)
|
||||
hwc->config |= ARCH_PERFMON_EVENTSEL_INT;
|
||||
__x86_pmu_enable_event(hwc, enable_mask);
|
||||
break;
|
||||
case INTEL_PMC_IDX_FIXED ... INTEL_PMC_IDX_FIXED_BTS - 1:
|
||||
@@ -3332,23 +3341,41 @@ static void intel_pmu_enable_event(struct perf_event *event)
|
||||
static void intel_pmu_acr_late_setup(struct cpu_hw_events *cpuc)
|
||||
{
|
||||
struct perf_event *event, *leader;
|
||||
int i, j, idx;
|
||||
int i, j, k, bit, idx;
|
||||
|
||||
/*
|
||||
* FIXME: ACR mask parsing relies on cpuc->event_list[] (active events only).
|
||||
* Disabling an ACR event causes bit-shifting errors in the acr_mask of
|
||||
* remaining group members. As ACR sampling requires all events to be active,
|
||||
* this limitation is acceptable for now. Revisit if independent event toggling
|
||||
* is required.
|
||||
*/
|
||||
for (i = 0; i < cpuc->n_events; i++) {
|
||||
leader = cpuc->event_list[i];
|
||||
if (!is_acr_event_group(leader))
|
||||
continue;
|
||||
|
||||
/* The ACR events must be contiguous. */
|
||||
/* Find the last event of the ACR group. */
|
||||
for (j = i; j < cpuc->n_events; j++) {
|
||||
event = cpuc->event_list[j];
|
||||
if (event->group_leader != leader->group_leader)
|
||||
break;
|
||||
for_each_set_bit(idx, (unsigned long *)&event->attr.config2, X86_PMC_IDX_MAX) {
|
||||
if (i + idx >= cpuc->n_events ||
|
||||
!is_acr_event_group(cpuc->event_list[i + idx]))
|
||||
return;
|
||||
__set_bit(cpuc->assign[i + idx], (unsigned long *)&event->hw.config1);
|
||||
}
|
||||
|
||||
/*
|
||||
* Translate the user-space ACR mask (attr.config2) into the physical
|
||||
* counter bitmask (hw.config1) for each ACR event in the group.
|
||||
* NOTE: ACR event contiguity is guaranteed by intel_pmu_hw_config().
|
||||
*/
|
||||
for (k = i; k < j; k++) {
|
||||
event = cpuc->event_list[k];
|
||||
event->hw.config1 = 0;
|
||||
for_each_set_bit(bit, (unsigned long *)&event->attr.config2, X86_PMC_IDX_MAX) {
|
||||
idx = i + bit;
|
||||
/* Event index of ACR group must locate in [i, j). */
|
||||
if (idx >= j || !is_acr_event_group(cpuc->event_list[idx]))
|
||||
continue;
|
||||
__set_bit(cpuc->assign[idx], (unsigned long *)&event->hw.config1);
|
||||
}
|
||||
}
|
||||
i = j - 1;
|
||||
@@ -7504,6 +7531,7 @@ static __always_inline void intel_pmu_init_pnc(struct pmu *pmu)
|
||||
hybrid(pmu, event_constraints) = intel_pnc_event_constraints;
|
||||
hybrid(pmu, pebs_constraints) = intel_pnc_pebs_event_constraints;
|
||||
hybrid(pmu, extra_regs) = intel_pnc_extra_regs;
|
||||
static_call_update(intel_pmu_enable_acr_event, intel_pmu_enable_acr);
|
||||
}
|
||||
|
||||
static __always_inline void intel_pmu_init_skt(struct pmu *pmu)
|
||||
|
||||
@@ -137,6 +137,16 @@ static inline bool is_acr_event_group(struct perf_event *event)
|
||||
return check_leader_group(event->group_leader, PERF_X86_EVENT_ACR);
|
||||
}
|
||||
|
||||
static inline bool is_acr_self_reload_event(struct perf_event *event)
|
||||
{
|
||||
struct hw_perf_event *hwc = &event->hw;
|
||||
|
||||
if (hwc->idx < 0)
|
||||
return false;
|
||||
|
||||
return test_bit(hwc->idx, (unsigned long *)&hwc->config1);
|
||||
}
|
||||
|
||||
struct amd_nb {
|
||||
int nb_id; /* NorthBridge id */
|
||||
int refcnt; /* reference count */
|
||||
|
||||
@@ -803,9 +803,10 @@
|
||||
#define MSR_AMD64_LBR_SELECT 0xc000010e
|
||||
|
||||
/* Zen4 */
|
||||
#define MSR_ZEN4_BP_CFG 0xc001102e
|
||||
#define MSR_ZEN4_BP_CFG 0xc001102e
|
||||
#define MSR_ZEN4_BP_CFG_BP_SPEC_REDUCE_BIT 4
|
||||
#define MSR_ZEN4_BP_CFG_SHARED_BTB_FIX_BIT 5
|
||||
#define MSR_ZEN2_BP_CFG_BUG_FIX_BIT 33
|
||||
|
||||
/* Fam 19h MSRs */
|
||||
#define MSR_F19H_UMC_PERF_CTL 0xc0010800
|
||||
|
||||
@@ -989,6 +989,9 @@ static void init_amd_zen2(struct cpuinfo_x86 *c)
|
||||
|
||||
/* Correct misconfigured CPUID on some clients. */
|
||||
clear_cpu_cap(c, X86_FEATURE_INVLPGB);
|
||||
|
||||
if (!cpu_has(c, X86_FEATURE_HYPERVISOR))
|
||||
msr_set_bit(MSR_ZEN4_BP_CFG, MSR_ZEN2_BP_CFG_BUG_FIX_BIT);
|
||||
}
|
||||
|
||||
static void init_amd_zen3(struct cpuinfo_x86 *c)
|
||||
|
||||
@@ -450,6 +450,10 @@ __init static int append_e820_table(struct boot_e820_entry *entries, u32 nr_entr
|
||||
{
|
||||
struct boot_e820_entry *entry = entries;
|
||||
|
||||
/* If there aren't any entries, we'll want to fall back to another source: */
|
||||
if (!nr_entries)
|
||||
return -ENOENT;
|
||||
|
||||
while (nr_entries) {
|
||||
u64 start = entry->addr;
|
||||
u64 size = entry->size;
|
||||
@@ -458,7 +462,7 @@ __init static int append_e820_table(struct boot_e820_entry *entries, u32 nr_entr
|
||||
|
||||
/* Ignore the remaining entries on 64-bit overflow: */
|
||||
if (start > end && likely(size))
|
||||
return -1;
|
||||
return -EINVAL;
|
||||
|
||||
e820__range_add(start, size, type);
|
||||
|
||||
|
||||
@@ -4481,7 +4481,7 @@ static const struct opcode opcode_map_0f_38[256] = {
|
||||
X16(N), X16(N),
|
||||
/* 0x20 - 0x2f */
|
||||
X8(N),
|
||||
X2(N), GP(SrcReg | DstMem | ModRM | Mov | Aligned, &pfx_0f_e7_0f_38_2a), N, N, N, N, N,
|
||||
X2(N), GP(SrcMem | DstReg | ModRM | Mov | Aligned, &pfx_0f_e7_0f_38_2a), N, N, N, N, N,
|
||||
/* 0x30 - 0x7f */
|
||||
X16(N), X16(N), X16(N), X16(N), X16(N),
|
||||
/* 0x80 - 0xef */
|
||||
|
||||
@@ -2526,6 +2526,23 @@ static void shadow_walk_next(struct kvm_shadow_walk_iterator *iterator)
|
||||
__shadow_walk_next(iterator, *iterator->sptep);
|
||||
}
|
||||
|
||||
/*
|
||||
* Note: while normally KVM uses a "bool flush" return value to let
|
||||
* the caller batch flushes, __link_shadow_page() flushes immediately
|
||||
* before populating the parent PTE with the new shadow page. The
|
||||
* typical callers, direct_map() and FNAME(fetch)(), are not going
|
||||
* to zap more than one huge SPTE anyway.
|
||||
*
|
||||
* The only exception, where @flush can be false, is when a huge SPTE
|
||||
* is replaced with a shadow page SPTE with a fully populated page table,
|
||||
* which can happen from shadow_mmu_split_huge_page(). In this case,
|
||||
* no memory is unmapped across the change to the page tables and no
|
||||
* immediate flush is needed for correctness.
|
||||
*
|
||||
* Even in that case, calls to kvm_mmu_commit_zap_page() are not
|
||||
* batched. Doing so would require adding an invalid_list argument
|
||||
* all the way down to __walk_slot_rmaps().
|
||||
*/
|
||||
static void __link_shadow_page(struct kvm *kvm,
|
||||
struct kvm_mmu_memory_cache *cache, u64 *sptep,
|
||||
struct kvm_mmu_page *sp, bool flush)
|
||||
@@ -2541,8 +2558,10 @@ static void __link_shadow_page(struct kvm *kvm,
|
||||
parent_sp = sptep_to_sp(sptep);
|
||||
WARN_ON_ONCE(parent_sp->role.level == PG_LEVEL_4K);
|
||||
|
||||
mmu_page_zap_pte(kvm, parent_sp, sptep, &invalid_list);
|
||||
kvm_mmu_remote_flush_or_zap(kvm, &invalid_list, true);
|
||||
if (mmu_page_zap_pte(kvm, parent_sp, sptep, &invalid_list))
|
||||
kvm_mmu_commit_zap_page(kvm, &invalid_list);
|
||||
else if (flush)
|
||||
kvm_flush_remote_tlbs_sptep(kvm, sptep);
|
||||
}
|
||||
|
||||
spte = make_nonleaf_spte(sp->spt, sp_ad_disabled(sp));
|
||||
|
||||
@@ -160,6 +160,16 @@ void nested_vmcb02_recalc_intercepts(struct vcpu_svm *svm)
|
||||
if (!intercept_smi)
|
||||
vmcb_clr_intercept(&vmcb02->control, INTERCEPT_SMI);
|
||||
|
||||
/*
|
||||
* Intercept PAUSE if and only if L1 wants to. KVM intercepts PAUSE so
|
||||
* that a vCPU that may be spinning waiting for a lock can be scheduled
|
||||
* out in favor of the vCPU that holds said lock. KVM doesn't support
|
||||
* yielding across L2 vCPUs, as KVM has limited visilibity into which
|
||||
* L2 vCPUs are in the same L2 VM, i.e. may be contending for locks.
|
||||
*/
|
||||
if (!vmcb12_is_intercept(&svm->nested.ctl, INTERCEPT_PAUSE))
|
||||
vmcb_clr_intercept(&vmcb02->control, INTERCEPT_PAUSE);
|
||||
|
||||
if (nested_vmcb_needs_vls_intercept(svm)) {
|
||||
/*
|
||||
* If the virtual VMLOAD/VMSAVE is not enabled for the L2,
|
||||
@@ -819,7 +829,6 @@ static void nested_vmcb02_prepare_control(struct vcpu_svm *svm)
|
||||
struct vmcb *vmcb02 = svm->nested.vmcb02.ptr;
|
||||
struct vmcb *vmcb01 = svm->vmcb01.ptr;
|
||||
struct kvm_vcpu *vcpu = &svm->vcpu;
|
||||
u32 pause_count12, pause_thresh12;
|
||||
|
||||
nested_svm_transition_tlb_flush(vcpu);
|
||||
|
||||
@@ -947,31 +956,13 @@ static void nested_vmcb02_prepare_control(struct vcpu_svm *svm)
|
||||
vmcb02->control.misc_ctl2 |= SVM_MISC2_ENABLE_V_VMLOAD_VMSAVE;
|
||||
|
||||
if (guest_cpu_cap_has(vcpu, X86_FEATURE_PAUSEFILTER))
|
||||
pause_count12 = vmcb12_ctrl->pause_filter_count;
|
||||
vmcb02->control.pause_filter_count = vmcb12_ctrl->pause_filter_count;
|
||||
else
|
||||
pause_count12 = 0;
|
||||
vmcb02->control.pause_filter_count = 0;
|
||||
if (guest_cpu_cap_has(vcpu, X86_FEATURE_PFTHRESHOLD))
|
||||
pause_thresh12 = vmcb12_ctrl->pause_filter_thresh;
|
||||
vmcb02->control.pause_filter_thresh = vmcb12_ctrl->pause_filter_thresh;
|
||||
else
|
||||
pause_thresh12 = 0;
|
||||
if (kvm_pause_in_guest(svm->vcpu.kvm)) {
|
||||
/* use guest values since host doesn't intercept PAUSE */
|
||||
vmcb02->control.pause_filter_count = pause_count12;
|
||||
vmcb02->control.pause_filter_thresh = pause_thresh12;
|
||||
|
||||
} else {
|
||||
/* start from host values otherwise */
|
||||
vmcb02->control.pause_filter_count = vmcb01->control.pause_filter_count;
|
||||
vmcb02->control.pause_filter_thresh = vmcb01->control.pause_filter_thresh;
|
||||
|
||||
/* ... but ensure filtering is disabled if so requested. */
|
||||
if (vmcb12_is_intercept(vmcb12_ctrl, INTERCEPT_PAUSE)) {
|
||||
if (!pause_count12)
|
||||
vmcb02->control.pause_filter_count = 0;
|
||||
if (!pause_thresh12)
|
||||
vmcb02->control.pause_filter_thresh = 0;
|
||||
}
|
||||
}
|
||||
vmcb02->control.pause_filter_thresh = 0;
|
||||
|
||||
/*
|
||||
* Take ALLOW_LARGER_RAP from vmcb12 even though it should be safe to
|
||||
@@ -1298,12 +1289,6 @@ void nested_svm_vmexit(struct vcpu_svm *svm)
|
||||
/* in case we halted in L2 */
|
||||
kvm_set_mp_state(vcpu, KVM_MP_STATE_RUNNABLE);
|
||||
|
||||
if (!kvm_pause_in_guest(vcpu->kvm)) {
|
||||
vmcb01->control.pause_filter_count = vmcb02->control.pause_filter_count;
|
||||
vmcb_mark_dirty(vmcb01, VMCB_INTERCEPTS);
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* Invalidate last_bus_lock_rip unless KVM is still waiting for the
|
||||
* guest to make forward progress before re-enabling bus lock detection.
|
||||
|
||||
@@ -913,7 +913,15 @@ static void grow_ple_window(struct kvm_vcpu *vcpu)
|
||||
struct vmcb_control_area *control = &svm->vmcb->control;
|
||||
int old = control->pause_filter_count;
|
||||
|
||||
if (kvm_pause_in_guest(vcpu->kvm))
|
||||
/* Adjusting pause_filter_count makes no sense if PLE is disabled. */
|
||||
WARN_ON_ONCE(kvm_pause_in_guest(vcpu->kvm));
|
||||
|
||||
/*
|
||||
* While running L2, KVM should intercept PAUSE if and only if L1 wants
|
||||
* to intercept PAUSE, and L1's intercept should take priority, i.e.
|
||||
* KVM should never handle a PAUSE intercept from L2.
|
||||
*/
|
||||
if (WARN_ON_ONCE(is_guest_mode(vcpu)))
|
||||
return;
|
||||
|
||||
control->pause_filter_count = __grow_ple_window(old,
|
||||
@@ -934,7 +942,10 @@ static void shrink_ple_window(struct kvm_vcpu *vcpu)
|
||||
struct vmcb_control_area *control = &svm->vmcb->control;
|
||||
int old = control->pause_filter_count;
|
||||
|
||||
if (kvm_pause_in_guest(vcpu->kvm))
|
||||
/* Adjusting pause_filter_count makes no sense if PLE is disabled. */
|
||||
WARN_ON_ONCE(kvm_pause_in_guest(vcpu->kvm));
|
||||
|
||||
if (is_guest_mode(vcpu))
|
||||
return;
|
||||
|
||||
control->pause_filter_count =
|
||||
|
||||
@@ -154,7 +154,7 @@ TRACE_EVENT(kvm_xen_hypercall,
|
||||
__entry->a2 = a2;
|
||||
__entry->a3 = a3;
|
||||
__entry->a4 = a4;
|
||||
__entry->a4 = a5;
|
||||
__entry->a5 = a5;
|
||||
),
|
||||
|
||||
TP_printk("cpl %d nr 0x%lx a0 0x%lx a1 0x%lx a2 0x%lx a3 0x%lx a4 0x%lx a5 %lx",
|
||||
|
||||
@@ -14,6 +14,7 @@ extern bool __read_mostly flexpriority_enabled;
|
||||
extern bool __read_mostly enable_ept;
|
||||
extern bool __read_mostly enable_unrestricted_guest;
|
||||
extern bool __read_mostly enable_ept_ad_bits;
|
||||
extern bool __read_mostly enable_cet;
|
||||
extern bool __read_mostly enable_pml;
|
||||
extern int __read_mostly pt_mode;
|
||||
|
||||
|
||||
@@ -108,6 +108,9 @@ module_param_named(unrestricted_guest,
|
||||
bool __read_mostly enable_ept_ad_bits = 1;
|
||||
module_param_named(eptad, enable_ept_ad_bits, bool, 0444);
|
||||
|
||||
bool __read_mostly enable_cet = 1;
|
||||
module_param_named(cet, enable_cet, bool, 0444);
|
||||
|
||||
static bool __read_mostly emulate_invalid_guest_state = true;
|
||||
module_param(emulate_invalid_guest_state, bool, 0444);
|
||||
|
||||
@@ -4476,7 +4479,7 @@ void vmx_set_constant_host_state(struct vcpu_vmx *vmx)
|
||||
* SSP is reloaded from IA32_PL3_SSP. Check SDM Vol.2A/B Chapter
|
||||
* 3 and 4 for details.
|
||||
*/
|
||||
if (cpu_has_load_cet_ctrl()) {
|
||||
if (enable_cet) {
|
||||
vmcs_writel(HOST_S_CET, kvm_host.s_cet);
|
||||
vmcs_writel(HOST_SSP, 0);
|
||||
vmcs_writel(HOST_INTR_SSP_TABLE, 0);
|
||||
@@ -4532,6 +4535,10 @@ static u32 vmx_get_initial_vmentry_ctrl(void)
|
||||
if (vmx_pt_mode_is_system())
|
||||
vmentry_ctrl &= ~(VM_ENTRY_PT_CONCEAL_PIP |
|
||||
VM_ENTRY_LOAD_IA32_RTIT_CTL);
|
||||
|
||||
if (!enable_cet)
|
||||
vmentry_ctrl &= ~VM_ENTRY_LOAD_CET_STATE;
|
||||
|
||||
/*
|
||||
* IA32e mode, and loading of EFER and PERF_GLOBAL_CTRL are toggled dynamically.
|
||||
*/
|
||||
@@ -4546,6 +4553,9 @@ static u32 vmx_get_initial_vmexit_ctrl(void)
|
||||
{
|
||||
u32 vmexit_ctrl = vmcs_config.vmexit_ctrl;
|
||||
|
||||
if (!enable_cet)
|
||||
vmexit_ctrl &= ~VM_EXIT_LOAD_CET_STATE;
|
||||
|
||||
/*
|
||||
* Not used by KVM and never set in vmcs01 or vmcs02, but emulated for
|
||||
* nested virtualization and thus allowed to be set in vmcs12.
|
||||
@@ -8155,7 +8165,7 @@ static __init void vmx_set_cpu_caps(void)
|
||||
* VMX_BASIC[bit56] == 0, inject #CP at VMX entry with error code
|
||||
* fails, so disable CET in this case too.
|
||||
*/
|
||||
if (!cpu_has_load_cet_ctrl() || !enable_unrestricted_guest ||
|
||||
if (!enable_cet || !enable_unrestricted_guest ||
|
||||
!cpu_has_vmx_basic_no_hw_errcode_cc()) {
|
||||
kvm_cpu_cap_clear(X86_FEATURE_SHSTK);
|
||||
kvm_cpu_cap_clear(X86_FEATURE_IBT);
|
||||
@@ -8630,6 +8640,9 @@ __init int vmx_hardware_setup(void)
|
||||
!cpu_has_vmx_invept_global())
|
||||
enable_ept = 0;
|
||||
|
||||
if (!cpu_has_load_cet_ctrl())
|
||||
enable_cet = 0;
|
||||
|
||||
/* NX support is required for shadow paging. */
|
||||
if (!enable_ept && !boot_cpu_has(X86_FEATURE_NX)) {
|
||||
pr_err_ratelimited("NX (Execute Disable) not supported\n");
|
||||
|
||||
@@ -695,17 +695,22 @@ static void __init xen_e820_resolve_conflicts(phys_addr_t start,
|
||||
return;
|
||||
|
||||
end = start + size;
|
||||
entry = xen_e820_table.entries;
|
||||
mapcnt = 0;
|
||||
|
||||
for (mapcnt = 0; mapcnt < xen_e820_table.nr_entries; mapcnt++) {
|
||||
while (mapcnt < xen_e820_table.nr_entries) {
|
||||
entry = xen_e820_table.entries + mapcnt;
|
||||
if (entry->addr >= end)
|
||||
return;
|
||||
|
||||
if (entry->addr + entry->size > start &&
|
||||
entry->type == E820_TYPE_NVS)
|
||||
entry->type == E820_TYPE_NVS) {
|
||||
xen_e820_swap_entry_with_ram(entry);
|
||||
/* E820 map has been changed, restart loop! */
|
||||
mapcnt = 0;
|
||||
continue;
|
||||
}
|
||||
|
||||
entry++;
|
||||
mapcnt++;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -857,6 +857,8 @@ long compat_blkdev_ioctl(struct file *file, unsigned cmd, unsigned long arg)
|
||||
#endif
|
||||
|
||||
struct blk_iou_cmd {
|
||||
u64 start;
|
||||
u64 len;
|
||||
int res;
|
||||
bool nowait;
|
||||
};
|
||||
@@ -946,23 +948,27 @@ int blkdev_uring_cmd(struct io_uring_cmd *cmd, unsigned int issue_flags)
|
||||
{
|
||||
struct block_device *bdev = I_BDEV(cmd->file->f_mapping->host);
|
||||
struct blk_iou_cmd *bic = io_uring_cmd_to_pdu(cmd, struct blk_iou_cmd);
|
||||
const struct io_uring_sqe *sqe = cmd->sqe;
|
||||
u32 cmd_op = cmd->cmd_op;
|
||||
uint64_t start, len;
|
||||
|
||||
if (unlikely(sqe->ioprio || sqe->__pad1 || sqe->len ||
|
||||
sqe->rw_flags || sqe->file_index))
|
||||
return -EINVAL;
|
||||
/* Read what we need from the SQE on the first issue */
|
||||
if (!(issue_flags & IORING_URING_CMD_REISSUE)) {
|
||||
const struct io_uring_sqe *sqe = cmd->sqe;
|
||||
|
||||
if (unlikely(sqe->ioprio || sqe->__pad1 || sqe->len ||
|
||||
sqe->rw_flags || sqe->file_index))
|
||||
return -EINVAL;
|
||||
|
||||
bic->start = READ_ONCE(sqe->addr);
|
||||
bic->len = READ_ONCE(sqe->addr3);
|
||||
}
|
||||
|
||||
bic->res = 0;
|
||||
bic->nowait = issue_flags & IO_URING_F_NONBLOCK;
|
||||
|
||||
start = READ_ONCE(sqe->addr);
|
||||
len = READ_ONCE(sqe->addr3);
|
||||
|
||||
switch (cmd_op) {
|
||||
case BLOCK_URING_CMD_DISCARD:
|
||||
return blkdev_cmd_discard(cmd, bdev, start, len, bic->nowait);
|
||||
return blkdev_cmd_discard(cmd, bdev, bic->start, bic->len,
|
||||
bic->nowait);
|
||||
}
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
@@ -537,6 +537,26 @@ static const struct file_operations ivpu_fops = {
|
||||
#endif
|
||||
};
|
||||
|
||||
static int ivpu_gem_prime_handle_to_fd(struct drm_device *dev, struct drm_file *file_priv,
|
||||
u32 handle, u32 flags, int *prime_fd)
|
||||
{
|
||||
struct drm_gem_object *obj;
|
||||
|
||||
obj = drm_gem_object_lookup(file_priv, handle);
|
||||
if (!obj)
|
||||
return -ENOENT;
|
||||
|
||||
if (drm_gem_is_imported(obj)) {
|
||||
/* Do not allow re-exporting */
|
||||
drm_gem_object_put(obj);
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
drm_gem_object_put(obj);
|
||||
|
||||
return drm_gem_prime_handle_to_fd(dev, file_priv, handle, flags, prime_fd);
|
||||
}
|
||||
|
||||
static const struct drm_driver driver = {
|
||||
.driver_features = DRIVER_GEM | DRIVER_COMPUTE_ACCEL,
|
||||
|
||||
@@ -545,6 +565,7 @@ static const struct drm_driver driver = {
|
||||
|
||||
.gem_create_object = ivpu_gem_create_object,
|
||||
.gem_prime_import = ivpu_gem_prime_import,
|
||||
.prime_handle_to_fd = ivpu_gem_prime_handle_to_fd,
|
||||
|
||||
.ioctls = ivpu_drm_ioctls,
|
||||
.num_ioctls = ARRAY_SIZE(ivpu_drm_ioctls),
|
||||
|
||||
@@ -497,11 +497,11 @@ static void decode_ras_msg(struct qaic_device *qdev, struct ras_data *msg)
|
||||
qdev->ce_count++;
|
||||
break;
|
||||
case UE:
|
||||
if (qdev->ce_count != UINT_MAX)
|
||||
if (qdev->ue_count != UINT_MAX)
|
||||
qdev->ue_count++;
|
||||
break;
|
||||
case UE_NF:
|
||||
if (qdev->ce_count != UINT_MAX)
|
||||
if (qdev->ue_nf_count != UINT_MAX)
|
||||
qdev->ue_nf_count++;
|
||||
break;
|
||||
default:
|
||||
|
||||
@@ -204,7 +204,6 @@ pub(crate) fn reservation_abort(&mut self, offset: usize) -> Result<FreedRange>
|
||||
// caller will mark them as unused, which means that they can be freed if the system comes
|
||||
// under memory pressure.
|
||||
let mut freed_range = FreedRange::interior_pages(offset, size);
|
||||
#[expect(clippy::collapsible_if)] // reads better like this
|
||||
if offset % PAGE_SIZE != 0 {
|
||||
if i == 0 || self.ranges[i - 1].endpoint() <= (offset & PAGE_MASK) {
|
||||
freed_range.start_page_idx -= 1;
|
||||
|
||||
@@ -900,6 +900,20 @@ static int ublk_validate_params(const struct ublk_device *ub)
|
||||
if (p->logical_bs_shift > PAGE_SHIFT || p->logical_bs_shift < 9)
|
||||
return -EINVAL;
|
||||
|
||||
/*
|
||||
* 256M is a reasonable upper bound for physical block size,
|
||||
* io_min and io_opt; it aligns with the maximum physical
|
||||
* block size possible in NVMe.
|
||||
*/
|
||||
if (p->physical_bs_shift > ilog2(SZ_256M))
|
||||
return -EINVAL;
|
||||
|
||||
if (p->io_min_shift > ilog2(SZ_256M))
|
||||
return -EINVAL;
|
||||
|
||||
if (p->io_opt_shift > ilog2(SZ_256M))
|
||||
return -EINVAL;
|
||||
|
||||
if (p->logical_bs_shift > p->physical_bs_shift)
|
||||
return -EINVAL;
|
||||
|
||||
@@ -2397,8 +2411,14 @@ static void ublk_reset_ch_dev(struct ublk_device *ub)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ub->dev_info.nr_hw_queues; i++)
|
||||
ublk_queue_reinit(ub, ublk_get_queue(ub, i));
|
||||
for (i = 0; i < ub->dev_info.nr_hw_queues; i++) {
|
||||
struct ublk_queue *ubq = ublk_get_queue(ub, i);
|
||||
|
||||
/* Sync with ublk_cancel_cmd() */
|
||||
spin_lock(&ubq->cancel_lock);
|
||||
ublk_queue_reinit(ub, ubq);
|
||||
spin_unlock(&ubq->cancel_lock);
|
||||
}
|
||||
|
||||
/* set to NULL, otherwise new tasks cannot mmap io_cmd_buf */
|
||||
ub->mm = NULL;
|
||||
@@ -2739,6 +2759,7 @@ static void ublk_cancel_cmd(struct ublk_queue *ubq, unsigned tag,
|
||||
{
|
||||
struct ublk_io *io = &ubq->ios[tag];
|
||||
struct ublk_device *ub = ubq->dev;
|
||||
struct io_uring_cmd *cmd = NULL;
|
||||
struct request *req;
|
||||
bool done;
|
||||
|
||||
@@ -2761,12 +2782,15 @@ static void ublk_cancel_cmd(struct ublk_queue *ubq, unsigned tag,
|
||||
|
||||
spin_lock(&ubq->cancel_lock);
|
||||
done = !!(io->flags & UBLK_IO_FLAG_CANCELED);
|
||||
if (!done)
|
||||
if (!done) {
|
||||
io->flags |= UBLK_IO_FLAG_CANCELED;
|
||||
cmd = io->cmd;
|
||||
io->cmd = NULL;
|
||||
}
|
||||
spin_unlock(&ubq->cancel_lock);
|
||||
|
||||
if (!done)
|
||||
io_uring_cmd_done(io->cmd, UBLK_IO_RES_ABORT, issue_flags);
|
||||
if (!done && cmd)
|
||||
io_uring_cmd_done(cmd, UBLK_IO_RES_ABORT, issue_flags);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -3496,8 +3520,10 @@ static void ublk_ch_uring_cmd_cb(struct io_tw_req tw_req, io_tw_token_t tw)
|
||||
{
|
||||
unsigned int issue_flags = IO_URING_CMD_TASK_WORK_ISSUE_FLAGS;
|
||||
struct io_uring_cmd *cmd = io_uring_cmd_from_tw(tw_req);
|
||||
int ret = ublk_ch_uring_cmd_local(cmd, issue_flags);
|
||||
int ret = -ECANCELED;
|
||||
|
||||
if (!tw.cancel)
|
||||
ret = ublk_ch_uring_cmd_local(cmd, issue_flags);
|
||||
if (ret != -EIOCBQUEUED)
|
||||
io_uring_cmd_done(cmd, ret, issue_flags);
|
||||
}
|
||||
@@ -4990,13 +5016,15 @@ static int ublk_ctrl_set_params(struct ublk_device *ub,
|
||||
*/
|
||||
ret = -EACCES;
|
||||
} else if (copy_from_user(&ub->params, argp, ph.len)) {
|
||||
/* zero out partial copy so no stale params survive */
|
||||
memset(&ub->params, 0, sizeof(ub->params));
|
||||
ret = -EFAULT;
|
||||
} else {
|
||||
/* clear all we don't support yet */
|
||||
ub->params.types &= UBLK_PARAM_TYPE_ALL;
|
||||
ret = ublk_validate_params(ub);
|
||||
if (ret)
|
||||
ub->params.types = 0;
|
||||
memset(&ub->params, 0, sizeof(ub->params));
|
||||
}
|
||||
mutex_unlock(&ub->mutex);
|
||||
|
||||
|
||||
@@ -110,6 +110,7 @@ struct eqc_match_data {
|
||||
|
||||
const char *reset_auxdev_name;
|
||||
const char *pinctrl_auxdev_name;
|
||||
const char *eth_phy_auxdev_name;
|
||||
|
||||
unsigned int early_clk_count;
|
||||
};
|
||||
@@ -321,38 +322,18 @@ static void eqc_probe_init_fixed_factors(struct device *dev,
|
||||
}
|
||||
}
|
||||
|
||||
static void eqc_auxdev_release(struct device *dev)
|
||||
{
|
||||
struct auxiliary_device *adev = to_auxiliary_dev(dev);
|
||||
|
||||
kfree(adev);
|
||||
}
|
||||
|
||||
static int eqc_auxdev_create(struct device *dev, void __iomem *base,
|
||||
const char *name, u32 id)
|
||||
static void eqc_auxdev_create_optional(struct device *dev, void __iomem *base,
|
||||
const char *name)
|
||||
{
|
||||
struct auxiliary_device *adev;
|
||||
int ret;
|
||||
|
||||
adev = kzalloc_obj(*adev);
|
||||
if (!adev)
|
||||
return -ENOMEM;
|
||||
|
||||
adev->name = name;
|
||||
adev->dev.parent = dev;
|
||||
adev->dev.platform_data = (void __force *)base;
|
||||
adev->dev.release = eqc_auxdev_release;
|
||||
adev->id = id;
|
||||
|
||||
ret = auxiliary_device_init(adev);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = auxiliary_device_add(adev);
|
||||
if (ret)
|
||||
auxiliary_device_uninit(adev);
|
||||
|
||||
return ret;
|
||||
if (name) {
|
||||
adev = devm_auxiliary_device_create(dev, name,
|
||||
(void __force *)base);
|
||||
if (!adev)
|
||||
dev_warn(dev, "failed creating auxiliary device %s.%s\n",
|
||||
KBUILD_MODNAME, name);
|
||||
}
|
||||
}
|
||||
|
||||
static int eqc_probe(struct platform_device *pdev)
|
||||
@@ -364,7 +345,6 @@ static int eqc_probe(struct platform_device *pdev)
|
||||
unsigned int i, clk_count;
|
||||
struct resource *res;
|
||||
void __iomem *base;
|
||||
int ret;
|
||||
|
||||
data = device_get_match_data(dev);
|
||||
if (!data)
|
||||
@@ -378,21 +358,10 @@ static int eqc_probe(struct platform_device *pdev)
|
||||
if (!base)
|
||||
return -ENOMEM;
|
||||
|
||||
/* Init optional reset auxiliary device. */
|
||||
if (data->reset_auxdev_name) {
|
||||
ret = eqc_auxdev_create(dev, base, data->reset_auxdev_name, 0);
|
||||
if (ret)
|
||||
dev_warn(dev, "failed creating auxiliary device %s.%s: %d\n",
|
||||
KBUILD_MODNAME, data->reset_auxdev_name, ret);
|
||||
}
|
||||
|
||||
/* Init optional pinctrl auxiliary device. */
|
||||
if (data->pinctrl_auxdev_name) {
|
||||
ret = eqc_auxdev_create(dev, base, data->pinctrl_auxdev_name, 0);
|
||||
if (ret)
|
||||
dev_warn(dev, "failed creating auxiliary device %s.%s: %d\n",
|
||||
KBUILD_MODNAME, data->pinctrl_auxdev_name, ret);
|
||||
}
|
||||
/* Init optional auxiliary devices. */
|
||||
eqc_auxdev_create_optional(dev, base, data->reset_auxdev_name);
|
||||
eqc_auxdev_create_optional(dev, base, data->pinctrl_auxdev_name);
|
||||
eqc_auxdev_create_optional(dev, base, data->eth_phy_auxdev_name);
|
||||
|
||||
if (data->pll_count + data->div_count + data->fixed_factor_count == 0)
|
||||
return 0; /* Zero clocks, we are done. */
|
||||
@@ -553,6 +522,7 @@ static const struct eqc_match_data eqc_eyeq5_match_data = {
|
||||
|
||||
.reset_auxdev_name = "reset",
|
||||
.pinctrl_auxdev_name = "pinctrl",
|
||||
.eth_phy_auxdev_name = "phy",
|
||||
|
||||
.early_clk_count = ARRAY_SIZE(eqc_eyeq5_early_plls) +
|
||||
ARRAY_SIZE(eqc_eyeq5_early_fixed_factors),
|
||||
|
||||
@@ -153,7 +153,7 @@ static int rk808_clkout_probe(struct platform_device *pdev)
|
||||
struct rk808_clkout *rk808_clkout;
|
||||
int ret;
|
||||
|
||||
dev->of_node = pdev->dev.parent->of_node;
|
||||
device_set_of_node_from_dev(dev, dev->parent);
|
||||
|
||||
rk808_clkout = devm_kzalloc(dev,
|
||||
sizeof(*rk808_clkout), GFP_KERNEL);
|
||||
|
||||
@@ -846,7 +846,7 @@ static const struct clk_parent_data top_parents[] = {
|
||||
CCU_PARENT_HW(pll6_d3),
|
||||
};
|
||||
CCU_MUX_DIV_GATE_FC_DEFINE(top_dclk, top_parents, APMU_TOP_DCLK_CTRL, 5, 3,
|
||||
BIT(8), 2, 3, BIT(1), 0);
|
||||
BIT(8), 2, 3, BIT(1), CLK_IS_CRITICAL);
|
||||
|
||||
static const struct clk_parent_data ucie_parents[] = {
|
||||
CCU_PARENT_HW(pll1_d8_307p2),
|
||||
|
||||
@@ -777,9 +777,9 @@ static int init_one_mc(struct mc_priv *priv, struct platform_device *pdev, int i
|
||||
u32 num_chans, rank, dwidth, config;
|
||||
struct edac_mc_layer layers[2];
|
||||
struct mem_ctl_info *mci;
|
||||
char name[MC_NAME_LEN];
|
||||
struct device *dev;
|
||||
enum dev_type dt;
|
||||
char *name;
|
||||
int rc;
|
||||
|
||||
config = priv->adec[CONF + i * ADEC_NUM];
|
||||
@@ -813,13 +813,9 @@ static int init_one_mc(struct mc_priv *priv, struct platform_device *pdev, int i
|
||||
layers[1].is_virt_csrow = false;
|
||||
|
||||
rc = -ENOMEM;
|
||||
name = kzalloc(MC_NAME_LEN, GFP_KERNEL);
|
||||
if (!name)
|
||||
return rc;
|
||||
|
||||
dev = kzalloc(sizeof(*dev), GFP_KERNEL);
|
||||
if (!dev)
|
||||
goto err_name_free;
|
||||
return rc;
|
||||
|
||||
mci = edac_mc_alloc(i, ARRAY_SIZE(layers), layers, sizeof(struct mc_priv));
|
||||
if (!mci) {
|
||||
@@ -858,8 +854,6 @@ static int init_one_mc(struct mc_priv *priv, struct platform_device *pdev, int i
|
||||
edac_mc_free(mci);
|
||||
err_dev_free:
|
||||
kfree(dev);
|
||||
err_name_free:
|
||||
kfree(name);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
@@ -3149,11 +3149,7 @@ static int __init amdgpu_init(void)
|
||||
|
||||
r = amdgpu_sync_init();
|
||||
if (r)
|
||||
goto error_sync;
|
||||
|
||||
r = amdgpu_userq_fence_slab_init();
|
||||
if (r)
|
||||
goto error_fence;
|
||||
return r;
|
||||
|
||||
amdgpu_register_atpx_handler();
|
||||
amdgpu_acpi_detect();
|
||||
@@ -3161,7 +3157,7 @@ static int __init amdgpu_init(void)
|
||||
/* Ignore KFD init failures when CONFIG_HSA_AMD is not set. */
|
||||
r = amdgpu_amdkfd_init();
|
||||
if (r && r != -ENOENT)
|
||||
goto error_fence;
|
||||
goto error_fini_sync;
|
||||
|
||||
if (amdgpu_pp_feature_mask & PP_OVERDRIVE_MASK) {
|
||||
add_taint(TAINT_CPU_OUT_OF_SPEC, LOCKDEP_STILL_OK);
|
||||
@@ -3172,10 +3168,8 @@ static int __init amdgpu_init(void)
|
||||
/* let modprobe override vga console setting */
|
||||
return pci_register_driver(&amdgpu_kms_pci_driver);
|
||||
|
||||
error_fence:
|
||||
error_fini_sync:
|
||||
amdgpu_sync_fini();
|
||||
|
||||
error_sync:
|
||||
return r;
|
||||
}
|
||||
|
||||
@@ -3186,7 +3180,6 @@ static void __exit amdgpu_exit(void)
|
||||
amdgpu_unregister_atpx_handler();
|
||||
amdgpu_acpi_release();
|
||||
amdgpu_sync_fini();
|
||||
amdgpu_userq_fence_slab_fini();
|
||||
mmu_notifier_synchronize();
|
||||
amdgpu_xcp_drv_release();
|
||||
}
|
||||
|
||||
@@ -262,12 +262,19 @@ void amdgpu_gart_table_ram_free(struct amdgpu_device *adev)
|
||||
*/
|
||||
int amdgpu_gart_table_vram_alloc(struct amdgpu_device *adev)
|
||||
{
|
||||
int r;
|
||||
|
||||
if (adev->gart.bo != NULL)
|
||||
return 0;
|
||||
|
||||
return amdgpu_bo_create_kernel(adev, adev->gart.table_size, PAGE_SIZE,
|
||||
AMDGPU_GEM_DOMAIN_VRAM, &adev->gart.bo,
|
||||
NULL, (void *)&adev->gart.ptr);
|
||||
r = amdgpu_bo_create_kernel(adev, adev->gart.table_size, PAGE_SIZE,
|
||||
AMDGPU_GEM_DOMAIN_VRAM, &adev->gart.bo,
|
||||
NULL, (void *)&adev->gart.ptr);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
memset_io(adev->gart.ptr, adev->gart.gart_pte_flags, adev->gart.table_size);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -32,29 +32,9 @@
|
||||
#include "amdgpu.h"
|
||||
#include "amdgpu_userq_fence.h"
|
||||
|
||||
static const struct dma_fence_ops amdgpu_userq_fence_ops;
|
||||
static struct kmem_cache *amdgpu_userq_fence_slab;
|
||||
|
||||
#define AMDGPU_USERQ_MAX_HANDLES (1U << 16)
|
||||
|
||||
int amdgpu_userq_fence_slab_init(void)
|
||||
{
|
||||
amdgpu_userq_fence_slab = kmem_cache_create("amdgpu_userq_fence",
|
||||
sizeof(struct amdgpu_userq_fence),
|
||||
0,
|
||||
SLAB_HWCACHE_ALIGN,
|
||||
NULL);
|
||||
if (!amdgpu_userq_fence_slab)
|
||||
return -ENOMEM;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void amdgpu_userq_fence_slab_fini(void)
|
||||
{
|
||||
rcu_barrier();
|
||||
kmem_cache_destroy(amdgpu_userq_fence_slab);
|
||||
}
|
||||
static const struct dma_fence_ops amdgpu_userq_fence_ops;
|
||||
|
||||
static inline struct amdgpu_userq_fence *to_amdgpu_userq_fence(struct dma_fence *f)
|
||||
{
|
||||
@@ -231,7 +211,7 @@ void amdgpu_userq_fence_driver_put(struct amdgpu_userq_fence_driver *fence_drv)
|
||||
|
||||
static int amdgpu_userq_fence_alloc(struct amdgpu_userq_fence **userq_fence)
|
||||
{
|
||||
*userq_fence = kmem_cache_alloc(amdgpu_userq_fence_slab, GFP_ATOMIC);
|
||||
*userq_fence = kmalloc(sizeof(**userq_fence), GFP_KERNEL);
|
||||
return *userq_fence ? 0 : -ENOMEM;
|
||||
}
|
||||
|
||||
@@ -342,7 +322,7 @@ static void amdgpu_userq_fence_free(struct rcu_head *rcu)
|
||||
amdgpu_userq_fence_driver_put(fence_drv);
|
||||
|
||||
kvfree(userq_fence->fence_drv_array);
|
||||
kmem_cache_free(amdgpu_userq_fence_slab, userq_fence);
|
||||
kfree(userq_fence);
|
||||
}
|
||||
|
||||
static void amdgpu_userq_fence_release(struct dma_fence *f)
|
||||
@@ -545,7 +525,7 @@ int amdgpu_userq_signal_ioctl(struct drm_device *dev, void *data,
|
||||
r = amdgpu_userq_fence_create(queue, userq_fence, wptr, &fence);
|
||||
if (r) {
|
||||
mutex_unlock(&userq_mgr->userq_mutex);
|
||||
kmem_cache_free(amdgpu_userq_fence_slab, userq_fence);
|
||||
kfree(userq_fence);
|
||||
goto put_gobj_write;
|
||||
}
|
||||
|
||||
|
||||
@@ -58,9 +58,6 @@ struct amdgpu_userq_fence_driver {
|
||||
char timeline_name[TASK_COMM_LEN];
|
||||
};
|
||||
|
||||
int amdgpu_userq_fence_slab_init(void);
|
||||
void amdgpu_userq_fence_slab_fini(void);
|
||||
|
||||
void amdgpu_userq_fence_driver_get(struct amdgpu_userq_fence_driver *fence_drv);
|
||||
void amdgpu_userq_fence_driver_put(struct amdgpu_userq_fence_driver *fence_drv);
|
||||
int amdgpu_userq_fence_driver_alloc(struct amdgpu_device *adev,
|
||||
|
||||
@@ -5660,9 +5660,6 @@ static void gfx_v9_0_ring_emit_fence_kiq(struct amdgpu_ring *ring, u64 addr,
|
||||
{
|
||||
struct amdgpu_device *adev = ring->adev;
|
||||
|
||||
/* we only allocate 32bit for each seq wb address */
|
||||
BUG_ON(flags & AMDGPU_FENCE_FLAG_64BIT);
|
||||
|
||||
/* write fence seq to the "addr" */
|
||||
amdgpu_ring_write(ring, PACKET3(PACKET3_WRITE_DATA, 3));
|
||||
amdgpu_ring_write(ring, (WRITE_DATA_ENGINE_SEL(0) |
|
||||
|
||||
@@ -30,34 +30,6 @@
|
||||
#define AMDGPU_USERQ_PROC_CTX_SZ PAGE_SIZE
|
||||
#define AMDGPU_USERQ_GANG_CTX_SZ PAGE_SIZE
|
||||
|
||||
static int
|
||||
mes_userq_map_gtt_bo_to_gart(struct amdgpu_bo *bo)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = amdgpu_bo_reserve(bo, true);
|
||||
if (ret) {
|
||||
DRM_ERROR("Failed to reserve bo. ret %d\n", ret);
|
||||
goto err_reserve_bo_failed;
|
||||
}
|
||||
|
||||
ret = amdgpu_ttm_alloc_gart(&bo->tbo);
|
||||
if (ret) {
|
||||
DRM_ERROR("Failed to bind bo to GART. ret %d\n", ret);
|
||||
goto err_map_bo_gart_failed;
|
||||
}
|
||||
|
||||
amdgpu_bo_unreserve(bo);
|
||||
bo = amdgpu_bo_ref(bo);
|
||||
|
||||
return 0;
|
||||
|
||||
err_map_bo_gart_failed:
|
||||
amdgpu_bo_unreserve(bo);
|
||||
err_reserve_bo_failed:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int
|
||||
mes_userq_create_wptr_mapping(struct amdgpu_device *adev,
|
||||
struct amdgpu_userq_mgr *uq_mgr,
|
||||
@@ -65,55 +37,62 @@ mes_userq_create_wptr_mapping(struct amdgpu_device *adev,
|
||||
uint64_t wptr)
|
||||
{
|
||||
struct amdgpu_bo_va_mapping *wptr_mapping;
|
||||
struct amdgpu_vm *wptr_vm;
|
||||
struct amdgpu_userq_obj *wptr_obj = &queue->wptr_obj;
|
||||
struct amdgpu_bo *obj;
|
||||
struct amdgpu_vm *vm = queue->vm;
|
||||
struct drm_exec exec;
|
||||
int ret;
|
||||
|
||||
wptr_vm = queue->vm;
|
||||
ret = amdgpu_bo_reserve(wptr_vm->root.bo, false);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
wptr &= AMDGPU_GMC_HOLE_MASK;
|
||||
wptr_mapping = amdgpu_vm_bo_lookup_mapping(wptr_vm, wptr >> PAGE_SHIFT);
|
||||
amdgpu_bo_unreserve(wptr_vm->root.bo);
|
||||
if (!wptr_mapping) {
|
||||
DRM_ERROR("Failed to lookup wptr bo\n");
|
||||
return -EINVAL;
|
||||
|
||||
drm_exec_init(&exec, DRM_EXEC_IGNORE_DUPLICATES, 2);
|
||||
drm_exec_until_all_locked(&exec) {
|
||||
ret = amdgpu_vm_lock_pd(vm, &exec, 1);
|
||||
drm_exec_retry_on_contention(&exec);
|
||||
if (unlikely(ret))
|
||||
goto fail_lock;
|
||||
|
||||
wptr_mapping = amdgpu_vm_bo_lookup_mapping(vm, wptr >> PAGE_SHIFT);
|
||||
if (!wptr_mapping) {
|
||||
ret = -EINVAL;
|
||||
goto fail_lock;
|
||||
}
|
||||
|
||||
obj = wptr_mapping->bo_va->base.bo;
|
||||
ret = drm_exec_lock_obj(&exec, &obj->tbo.base);
|
||||
drm_exec_retry_on_contention(&exec);
|
||||
if (unlikely(ret))
|
||||
goto fail_lock;
|
||||
}
|
||||
|
||||
wptr_obj->obj = wptr_mapping->bo_va->base.bo;
|
||||
wptr_obj->obj = amdgpu_bo_ref(wptr_mapping->bo_va->base.bo);
|
||||
if (wptr_obj->obj->tbo.base.size > PAGE_SIZE) {
|
||||
DRM_ERROR("Requested GART mapping for wptr bo larger than one page\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ret = mes_userq_map_gtt_bo_to_gart(wptr_obj->obj);
|
||||
if (ret) {
|
||||
DRM_ERROR("Failed to map wptr bo to GART\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = amdgpu_bo_reserve(wptr_obj->obj, true);
|
||||
if (ret) {
|
||||
DRM_ERROR("Failed to reserve wptr bo\n");
|
||||
return ret;
|
||||
ret = -EINVAL;
|
||||
goto fail_map;
|
||||
}
|
||||
|
||||
/* TODO use eviction fence instead of pinning. */
|
||||
ret = amdgpu_bo_pin(wptr_obj->obj, AMDGPU_GEM_DOMAIN_GTT);
|
||||
if (ret) {
|
||||
drm_file_err(uq_mgr->file, "[Usermode queues] Failed to pin wptr bo\n");
|
||||
goto unresv_bo;
|
||||
DRM_ERROR("Failed to pin wptr bo. ret %d\n", ret);
|
||||
goto fail_map;
|
||||
}
|
||||
|
||||
ret = amdgpu_ttm_alloc_gart(&wptr_obj->obj->tbo);
|
||||
if (ret) {
|
||||
DRM_ERROR("Failed to bind bo to GART. ret %d\n", ret);
|
||||
goto fail_map;
|
||||
}
|
||||
|
||||
queue->wptr_obj.gpu_addr = amdgpu_bo_gpu_offset(wptr_obj->obj);
|
||||
amdgpu_bo_unreserve(wptr_obj->obj);
|
||||
|
||||
drm_exec_fini(&exec);
|
||||
return 0;
|
||||
|
||||
unresv_bo:
|
||||
amdgpu_bo_unreserve(wptr_obj->obj);
|
||||
fail_map:
|
||||
amdgpu_bo_unref(&wptr_obj->obj);
|
||||
fail_lock:
|
||||
drm_exec_fini(&exec);
|
||||
return ret;
|
||||
|
||||
}
|
||||
|
||||
@@ -889,7 +889,7 @@ static void sdma_v4_0_ring_emit_fence(struct amdgpu_ring *ring, u64 addr, u64 se
|
||||
/* write the fence */
|
||||
amdgpu_ring_write(ring, SDMA_PKT_HEADER_OP(SDMA_OP_FENCE));
|
||||
/* zero in first two bits */
|
||||
BUG_ON(addr & 0x3);
|
||||
WARN_ON(addr & 0x3);
|
||||
amdgpu_ring_write(ring, lower_32_bits(addr));
|
||||
amdgpu_ring_write(ring, upper_32_bits(addr));
|
||||
amdgpu_ring_write(ring, lower_32_bits(seq));
|
||||
@@ -899,7 +899,7 @@ static void sdma_v4_0_ring_emit_fence(struct amdgpu_ring *ring, u64 addr, u64 se
|
||||
addr += 4;
|
||||
amdgpu_ring_write(ring, SDMA_PKT_HEADER_OP(SDMA_OP_FENCE));
|
||||
/* zero in first two bits */
|
||||
BUG_ON(addr & 0x3);
|
||||
WARN_ON(addr & 0x3);
|
||||
amdgpu_ring_write(ring, lower_32_bits(addr));
|
||||
amdgpu_ring_write(ring, upper_32_bits(addr));
|
||||
amdgpu_ring_write(ring, upper_32_bits(seq));
|
||||
|
||||
@@ -1360,7 +1360,7 @@ static int kfd_ioctl_map_memory_to_gpu(struct file *filep,
|
||||
peer_pdd = kfd_process_device_data_by_id(p, devices_arr[i]);
|
||||
if (WARN_ON_ONCE(!peer_pdd))
|
||||
continue;
|
||||
kfd_flush_tlb(peer_pdd, TLB_FLUSH_LEGACY);
|
||||
kfd_flush_tlb(peer_pdd);
|
||||
}
|
||||
kfree(devices_arr);
|
||||
|
||||
@@ -1455,7 +1455,7 @@ static int kfd_ioctl_unmap_memory_from_gpu(struct file *filep,
|
||||
if (WARN_ON_ONCE(!peer_pdd))
|
||||
continue;
|
||||
if (flush_tlb)
|
||||
kfd_flush_tlb(peer_pdd, TLB_FLUSH_HEAVYWEIGHT);
|
||||
kfd_flush_tlb(peer_pdd);
|
||||
|
||||
/* Remove dma mapping after tlb flush to avoid IO_PAGE_FAULT */
|
||||
err = amdgpu_amdkfd_gpuvm_dmaunmap_mem(mem, peer_pdd->drm_priv);
|
||||
|
||||
@@ -1737,37 +1737,6 @@ bool kgd2kfd_vmfault_fast_path(struct amdgpu_device *adev, struct amdgpu_iv_entr
|
||||
return false;
|
||||
}
|
||||
|
||||
/* check if there is kfd process still uses adev */
|
||||
static bool kgd2kfd_check_device_idle(struct amdgpu_device *adev)
|
||||
{
|
||||
struct kfd_process *p;
|
||||
struct hlist_node *p_temp;
|
||||
unsigned int temp;
|
||||
struct kfd_node *dev;
|
||||
|
||||
mutex_lock(&kfd_processes_mutex);
|
||||
|
||||
if (hash_empty(kfd_processes_table)) {
|
||||
mutex_unlock(&kfd_processes_mutex);
|
||||
return true;
|
||||
}
|
||||
|
||||
/* check if there is device still use adev */
|
||||
hash_for_each_safe(kfd_processes_table, temp, p_temp, p, kfd_processes) {
|
||||
for (int i = 0; i < p->n_pdds; i++) {
|
||||
dev = p->pdds[i]->dev;
|
||||
if (dev->adev == adev) {
|
||||
mutex_unlock(&kfd_processes_mutex);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mutex_unlock(&kfd_processes_mutex);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/** kgd2kfd_teardown_processes - gracefully tear down existing
|
||||
* kfd processes that use adev
|
||||
*
|
||||
@@ -1800,7 +1769,7 @@ void kgd2kfd_teardown_processes(struct amdgpu_device *adev)
|
||||
mutex_unlock(&kfd_processes_mutex);
|
||||
|
||||
/* wait all kfd processes use adev terminate */
|
||||
while (!kgd2kfd_check_device_idle(adev))
|
||||
while (!!atomic_read(&adev->kfd.dev->kfd_processes_count))
|
||||
cond_resched();
|
||||
}
|
||||
|
||||
|
||||
@@ -572,7 +572,7 @@ static int allocate_vmid(struct device_queue_manager *dqm,
|
||||
qpd->vmid,
|
||||
qpd->page_table_base);
|
||||
/* invalidate the VM context after pasid and vmid mapping is set up */
|
||||
kfd_flush_tlb(qpd_to_pdd(qpd), TLB_FLUSH_LEGACY);
|
||||
kfd_flush_tlb(qpd_to_pdd(qpd));
|
||||
|
||||
if (dqm->dev->kfd2kgd->set_scratch_backing_va)
|
||||
dqm->dev->kfd2kgd->set_scratch_backing_va(dqm->dev->adev,
|
||||
@@ -610,7 +610,7 @@ static void deallocate_vmid(struct device_queue_manager *dqm,
|
||||
if (flush_texture_cache_nocpsch(q->device, qpd))
|
||||
dev_err(dev, "Failed to flush TC\n");
|
||||
|
||||
kfd_flush_tlb(qpd_to_pdd(qpd), TLB_FLUSH_LEGACY);
|
||||
kfd_flush_tlb(qpd_to_pdd(qpd));
|
||||
|
||||
/* Release the vmid mapping */
|
||||
set_pasid_vmid_mapping(dqm, 0, qpd->vmid);
|
||||
@@ -1284,7 +1284,7 @@ static int restore_process_queues_nocpsch(struct device_queue_manager *dqm,
|
||||
dqm->dev->adev,
|
||||
qpd->vmid,
|
||||
qpd->page_table_base);
|
||||
kfd_flush_tlb(pdd, TLB_FLUSH_LEGACY);
|
||||
kfd_flush_tlb(pdd);
|
||||
}
|
||||
|
||||
/* Take a safe reference to the mm_struct, which may otherwise
|
||||
|
||||
@@ -1554,13 +1554,13 @@ void kfd_signal_reset_event(struct kfd_node *dev);
|
||||
void kfd_signal_poison_consumed_event(struct kfd_node *dev, u32 pasid);
|
||||
void kfd_signal_process_terminate_event(struct kfd_process *p);
|
||||
|
||||
static inline void kfd_flush_tlb(struct kfd_process_device *pdd,
|
||||
enum TLB_FLUSH_TYPE type)
|
||||
static inline void kfd_flush_tlb(struct kfd_process_device *pdd)
|
||||
{
|
||||
struct amdgpu_device *adev = pdd->dev->adev;
|
||||
struct amdgpu_vm *vm = drm_priv_to_vm(pdd->drm_priv);
|
||||
|
||||
amdgpu_vm_flush_compute_tlb(adev, vm, type, pdd->dev->xcc_mask);
|
||||
amdgpu_vm_flush_compute_tlb(adev, vm, TLB_FLUSH_HEAVYWEIGHT,
|
||||
pdd->dev->xcc_mask);
|
||||
}
|
||||
|
||||
static inline bool kfd_flush_tlb_after_unmap(struct kfd_dev *dev)
|
||||
|
||||
@@ -1424,7 +1424,7 @@ svm_range_unmap_from_gpus(struct svm_range *prange, unsigned long start,
|
||||
if (r)
|
||||
break;
|
||||
}
|
||||
kfd_flush_tlb(pdd, TLB_FLUSH_HEAVYWEIGHT);
|
||||
kfd_flush_tlb(pdd);
|
||||
}
|
||||
|
||||
return r;
|
||||
@@ -1571,7 +1571,7 @@ svm_range_map_to_gpus(struct svm_range *prange, unsigned long offset,
|
||||
}
|
||||
}
|
||||
|
||||
kfd_flush_tlb(pdd, TLB_FLUSH_LEGACY);
|
||||
kfd_flush_tlb(pdd);
|
||||
}
|
||||
|
||||
return r;
|
||||
|
||||
@@ -1333,12 +1333,13 @@ static int ci_populate_all_memory_levels(struct pp_hwmgr *hwmgr)
|
||||
|
||||
dev_id = adev->pdev->device;
|
||||
|
||||
if ((dpm_table->mclk_table.count >= 2)
|
||||
&& ((dev_id == 0x67B0) || (dev_id == 0x67B1))) {
|
||||
smu_data->smc_state_table.MemoryLevel[1].MinVddci =
|
||||
smu_data->smc_state_table.MemoryLevel[0].MinVddci;
|
||||
smu_data->smc_state_table.MemoryLevel[1].MinMvdd =
|
||||
smu_data->smc_state_table.MemoryLevel[0].MinMvdd;
|
||||
if ((dpm_table->mclk_table.count >= 2) &&
|
||||
((dev_id == 0x67B0) || (dev_id == 0x67B1)) &&
|
||||
(adev->pdev->revision == 0)) {
|
||||
smu_data->smc_state_table.MemoryLevel[1].MinVddc =
|
||||
smu_data->smc_state_table.MemoryLevel[0].MinVddc;
|
||||
smu_data->smc_state_table.MemoryLevel[1].MinVddcPhases =
|
||||
smu_data->smc_state_table.MemoryLevel[0].MinVddcPhases;
|
||||
}
|
||||
smu_data->smc_state_table.MemoryLevel[0].ActivityLevel = 0x1F;
|
||||
CONVERT_FROM_HOST_TO_SMC_US(smu_data->smc_state_table.MemoryLevel[0].ActivityLevel);
|
||||
|
||||
@@ -1293,7 +1293,7 @@ static const struct drm_edid *tda998x_edid_read(struct tda998x_priv *priv,
|
||||
* can't handle signals gracefully.
|
||||
*/
|
||||
if (tda998x_edid_delay_wait(priv))
|
||||
return 0;
|
||||
return NULL;
|
||||
|
||||
if (priv->rev == TDA19988)
|
||||
reg_clear(priv, REG_TX4, TX4_PD_RAM);
|
||||
@@ -1762,7 +1762,7 @@ static const struct drm_bridge_funcs tda998x_bridge_funcs = {
|
||||
static int tda998x_get_audio_ports(struct tda998x_priv *priv,
|
||||
struct device_node *np)
|
||||
{
|
||||
const u32 *port_data;
|
||||
const __be32 *port_data;
|
||||
u32 size;
|
||||
int i;
|
||||
|
||||
|
||||
@@ -490,7 +490,7 @@ static void drm_fb_helper_memory_range_to_clip(struct fb_info *info, off_t off,
|
||||
* the number of horizontal pixels that need an update.
|
||||
*/
|
||||
off_t bit_off = (off % line_length) * 8;
|
||||
off_t bit_end = (end % line_length) * 8;
|
||||
off_t bit_end = bit_off + len * 8;
|
||||
|
||||
x1 = bit_off / info->var.bits_per_pixel;
|
||||
x2 = DIV_ROUND_UP(bit_end, info->var.bits_per_pixel);
|
||||
|
||||
@@ -1019,7 +1019,7 @@ int drm_gem_change_handle_ioctl(struct drm_device *dev, void *data,
|
||||
struct drm_file *file_priv)
|
||||
{
|
||||
struct drm_gem_change_handle *args = data;
|
||||
struct drm_gem_object *obj;
|
||||
struct drm_gem_object *obj, *idrobj;
|
||||
int handle, ret;
|
||||
|
||||
if (!drm_core_check_feature(dev, DRIVER_GEM))
|
||||
@@ -1042,8 +1042,29 @@ int drm_gem_change_handle_ioctl(struct drm_device *dev, void *data,
|
||||
mutex_lock(&file_priv->prime.lock);
|
||||
|
||||
spin_lock(&file_priv->table_lock);
|
||||
|
||||
/* When create_tail allocs an obj idr, it needs to first alloc as NULL,
|
||||
* then later replace with the correct object. This is not necessary
|
||||
* here, because the only operations that could race are drm_prime
|
||||
* bookkeeping, and we hold the prime lock.
|
||||
*/
|
||||
ret = idr_alloc(&file_priv->object_idr, obj, handle, handle + 1,
|
||||
GFP_NOWAIT);
|
||||
|
||||
if (ret < 0) {
|
||||
spin_unlock(&file_priv->table_lock);
|
||||
goto out_unlock;
|
||||
}
|
||||
|
||||
idrobj = idr_replace(&file_priv->object_idr, NULL, handle);
|
||||
if (idrobj != obj) {
|
||||
idr_replace(&file_priv->object_idr, idrobj, handle);
|
||||
idr_remove(&file_priv->object_idr, args->new_handle);
|
||||
spin_unlock(&file_priv->table_lock);
|
||||
ret = -ENOENT;
|
||||
goto out_unlock;
|
||||
}
|
||||
|
||||
spin_unlock(&file_priv->table_lock);
|
||||
|
||||
if (ret < 0)
|
||||
@@ -1055,6 +1076,8 @@ int drm_gem_change_handle_ioctl(struct drm_device *dev, void *data,
|
||||
if (ret < 0) {
|
||||
spin_lock(&file_priv->table_lock);
|
||||
idr_remove(&file_priv->object_idr, handle);
|
||||
idrobj = idr_replace(&file_priv->object_idr, obj, handle);
|
||||
WARN_ON(idrobj != NULL);
|
||||
spin_unlock(&file_priv->table_lock);
|
||||
goto out_unlock;
|
||||
}
|
||||
|
||||
@@ -116,16 +116,18 @@ int etnaviv_sched_push_job(struct etnaviv_gem_submit *submit)
|
||||
*/
|
||||
mutex_lock(&gpu->sched_lock);
|
||||
|
||||
ret = xa_alloc_cyclic(&gpu->user_fences, &submit->out_fence_id,
|
||||
NULL, xa_limit_32b, &gpu->next_user_fence,
|
||||
GFP_KERNEL);
|
||||
if (ret < 0)
|
||||
goto out_unlock;
|
||||
|
||||
drm_sched_job_arm(&submit->sched_job);
|
||||
|
||||
submit->out_fence = dma_fence_get(&submit->sched_job.s_fence->finished);
|
||||
ret = xa_alloc_cyclic(&gpu->user_fences, &submit->out_fence_id,
|
||||
submit->out_fence, xa_limit_32b,
|
||||
&gpu->next_user_fence, GFP_KERNEL);
|
||||
if (ret < 0) {
|
||||
drm_sched_job_cleanup(&submit->sched_job);
|
||||
goto out_unlock;
|
||||
}
|
||||
|
||||
xa_store(&gpu->user_fences, submit->out_fence_id,
|
||||
submit->out_fence, GFP_KERNEL);
|
||||
|
||||
/* the scheduler holds on to the job now */
|
||||
kref_get(&submit->refcount);
|
||||
|
||||
@@ -423,7 +423,9 @@ static int exynos_mic_probe(struct platform_device *pdev)
|
||||
|
||||
mic->bridge.of_node = dev->of_node;
|
||||
|
||||
drm_bridge_add(&mic->bridge);
|
||||
ret = devm_drm_bridge_add(dev, &mic->bridge);
|
||||
if (ret)
|
||||
goto err;
|
||||
|
||||
pm_runtime_enable(dev);
|
||||
|
||||
@@ -443,12 +445,8 @@ static int exynos_mic_probe(struct platform_device *pdev)
|
||||
|
||||
static void exynos_mic_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct exynos_mic *mic = platform_get_drvdata(pdev);
|
||||
|
||||
component_del(&pdev->dev, &exynos_mic_component_ops);
|
||||
pm_runtime_disable(&pdev->dev);
|
||||
|
||||
drm_bridge_remove(&mic->bridge);
|
||||
}
|
||||
|
||||
static const struct of_device_id exynos_mic_of_match[] = {
|
||||
|
||||
@@ -750,9 +750,8 @@ static bool has_auxccs(struct drm_device *drm)
|
||||
{
|
||||
struct drm_i915_private *i915 = to_i915(drm);
|
||||
|
||||
return IS_GRAPHICS_VER(i915, 9, 12) ||
|
||||
IS_ALDERLAKE_P(i915) ||
|
||||
IS_METEORLAKE(i915);
|
||||
return IS_GRAPHICS_VER(i915, 9, 12) &&
|
||||
!HAS_FLAT_CCS(i915);
|
||||
}
|
||||
|
||||
static bool has_fenced_regions(struct drm_device *drm)
|
||||
|
||||
@@ -2513,6 +2513,7 @@ static const struct nvkm_device_chip
|
||||
nv170_chipset = {
|
||||
.name = "GA100",
|
||||
.bar = { 0x00000001, tu102_bar_new },
|
||||
.bios = { 0x00000001, nvkm_bios_new },
|
||||
.devinit = { 0x00000001, ga100_devinit_new },
|
||||
.fault = { 0x00000001, tu102_fault_new },
|
||||
.fb = { 0x00000001, ga100_fb_new },
|
||||
@@ -2529,7 +2530,6 @@ nv170_chipset = {
|
||||
.vfn = { 0x00000001, ga100_vfn_new },
|
||||
.ce = { 0x000003ff, ga100_ce_new },
|
||||
.fifo = { 0x00000001, ga100_fifo_new },
|
||||
.sec2 = { 0x00000001, tu102_sec2_new },
|
||||
};
|
||||
|
||||
static const struct nvkm_device_chip
|
||||
@@ -3341,7 +3341,6 @@ nvkm_device_ctor(const struct nvkm_device_func *func,
|
||||
case 0x166: device->chip = &nv166_chipset; break;
|
||||
case 0x167: device->chip = &nv167_chipset; break;
|
||||
case 0x168: device->chip = &nv168_chipset; break;
|
||||
case 0x170: device->chip = &nv170_chipset; break;
|
||||
case 0x172: device->chip = &nv172_chipset; break;
|
||||
case 0x173: device->chip = &nv173_chipset; break;
|
||||
case 0x174: device->chip = &nv174_chipset; break;
|
||||
@@ -3361,6 +3360,14 @@ nvkm_device_ctor(const struct nvkm_device_func *func,
|
||||
case 0x1b6: device->chip = &nv1b6_chipset; break;
|
||||
case 0x1b7: device->chip = &nv1b7_chipset; break;
|
||||
default:
|
||||
if (nvkm_boolopt(device->cfgopt, "NvEnableUnsupportedChipsets", false)) {
|
||||
switch (device->chipset) {
|
||||
case 0x170: device->chip = &nv170_chipset; break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!device->chip) {
|
||||
nvdev_error(device, "unknown chipset (%08x)\n", boot0);
|
||||
ret = -ENODEV;
|
||||
|
||||
@@ -41,11 +41,15 @@ ga100_gsp_flcn = {
|
||||
static const struct nvkm_gsp_func
|
||||
ga100_gsp = {
|
||||
.flcn = &ga100_gsp_flcn,
|
||||
.fwsec = &tu102_gsp_fwsec,
|
||||
|
||||
.sig_section = ".fwsignature_ga100",
|
||||
|
||||
.booter.ctor = tu102_gsp_booter_ctor,
|
||||
|
||||
.fwsec_sb.ctor = tu102_gsp_fwsec_sb_ctor,
|
||||
.fwsec_sb.dtor = tu102_gsp_fwsec_sb_dtor,
|
||||
|
||||
.dtor = r535_gsp_dtor,
|
||||
.oneinit = tu102_gsp_oneinit,
|
||||
.init = tu102_gsp_init,
|
||||
|
||||
@@ -318,13 +318,8 @@ tu102_gsp_oneinit(struct nvkm_gsp *gsp)
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/*
|
||||
* Calculate FB layout. FRTS is a memory region created by the FWSEC-FRTS firmware.
|
||||
* FWSEC comes from VBIOS. So on systems with no VBIOS (e.g. GA100), the FRTS does
|
||||
* not exist. Therefore, use the existence of VBIOS to determine whether to reserve
|
||||
* an FRTS region.
|
||||
*/
|
||||
gsp->fb.wpr2.frts.size = device->bios ? 0x100000 : 0;
|
||||
/* Calculate FB layout. */
|
||||
gsp->fb.wpr2.frts.size = 0x100000;
|
||||
gsp->fb.wpr2.frts.addr = ALIGN_DOWN(gsp->fb.bios.addr, 0x20000) - gsp->fb.wpr2.frts.size;
|
||||
|
||||
gsp->fb.wpr2.boot.size = gsp->boot.fw.size;
|
||||
@@ -348,12 +343,9 @@ tu102_gsp_oneinit(struct nvkm_gsp *gsp)
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* Only boot FWSEC-FRTS if it actually exists */
|
||||
if (gsp->fb.wpr2.frts.size) {
|
||||
ret = nvkm_gsp_fwsec_frts(gsp);
|
||||
if (WARN_ON(ret))
|
||||
return ret;
|
||||
}
|
||||
ret = nvkm_gsp_fwsec_frts(gsp);
|
||||
if (WARN_ON(ret))
|
||||
return ret;
|
||||
|
||||
/* Reset GSP into RISC-V mode. */
|
||||
ret = gsp->func->reset(gsp);
|
||||
|
||||
@@ -208,6 +208,7 @@ config DRM_PANEL_HIMAX_HX83121A
|
||||
depends on OF
|
||||
depends on DRM_MIPI_DSI
|
||||
depends on BACKLIGHT_CLASS_DEVICE
|
||||
select DRM_DISPLAY_DSC_HELPER
|
||||
select DRM_KMS_HELPER
|
||||
help
|
||||
Say Y here if you want to enable support for Himax HX83121A-based
|
||||
|
||||
@@ -1324,6 +1324,8 @@ static int boe_panel_disable(struct drm_panel *panel)
|
||||
mipi_dsi_dcs_set_display_off_multi(&ctx);
|
||||
mipi_dsi_dcs_enter_sleep_mode_multi(&ctx);
|
||||
|
||||
boe->dsi->mode_flags |= MIPI_DSI_MODE_LPM;
|
||||
|
||||
mipi_dsi_msleep(&ctx, 150);
|
||||
|
||||
return ctx.accum_err;
|
||||
|
||||
@@ -98,9 +98,7 @@ static int feiyang_enable(struct drm_panel *panel)
|
||||
/* T12 (video & logic signal rise + backlight rise) T12 >= 200ms */
|
||||
msleep(200);
|
||||
|
||||
mipi_dsi_dcs_set_display_on(ctx->dsi);
|
||||
|
||||
return 0;
|
||||
return mipi_dsi_dcs_set_display_on(ctx->dsi);
|
||||
}
|
||||
|
||||
static int feiyang_disable(struct drm_panel *panel)
|
||||
|
||||
@@ -937,6 +937,8 @@ static int hx83102_disable(struct drm_panel *panel)
|
||||
mipi_dsi_dcs_set_display_off_multi(&dsi_ctx);
|
||||
mipi_dsi_dcs_enter_sleep_mode_multi(&dsi_ctx);
|
||||
|
||||
dsi->mode_flags |= MIPI_DSI_MODE_LPM;
|
||||
|
||||
mipi_dsi_msleep(&dsi_ctx, 150);
|
||||
|
||||
return dsi_ctx.accum_err;
|
||||
|
||||
@@ -596,8 +596,8 @@ static int himax_probe(struct mipi_dsi_device *dsi)
|
||||
|
||||
ctx = devm_drm_panel_alloc(dev, struct himax, panel, &himax_panel_funcs,
|
||||
DRM_MODE_CONNECTOR_DSI);
|
||||
if (!ctx)
|
||||
return -ENOMEM;
|
||||
if (IS_ERR(ctx))
|
||||
return PTR_ERR(ctx);
|
||||
|
||||
ret = devm_regulator_bulk_get_const(&dsi->dev,
|
||||
ARRAY_SIZE(himax_supplies),
|
||||
|
||||
@@ -118,12 +118,13 @@ qxl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
|
||||
/* Complete initialization. */
|
||||
ret = drm_dev_register(&qdev->ddev, ent->driver_data);
|
||||
if (ret)
|
||||
goto modeset_cleanup;
|
||||
goto poll_fini;
|
||||
|
||||
drm_client_setup(&qdev->ddev, NULL);
|
||||
return 0;
|
||||
|
||||
modeset_cleanup:
|
||||
poll_fini:
|
||||
drm_kms_helper_poll_fini(&qdev->ddev);
|
||||
qxl_modeset_fini(qdev);
|
||||
unload:
|
||||
qxl_device_fini(qdev);
|
||||
@@ -154,6 +155,7 @@ qxl_pci_remove(struct pci_dev *pdev)
|
||||
{
|
||||
struct drm_device *dev = pci_get_drvdata(pdev);
|
||||
|
||||
drm_kms_helper_poll_fini(dev);
|
||||
drm_dev_unregister(dev);
|
||||
drm_atomic_helper_shutdown(dev);
|
||||
if (pci_is_vga(pdev) && pdev->revision < 5)
|
||||
|
||||
@@ -2461,7 +2461,8 @@ static void ci_register_patching_mc_arb(struct radeon_device *rdev,
|
||||
|
||||
if (patch &&
|
||||
((rdev->pdev->device == 0x67B0) ||
|
||||
(rdev->pdev->device == 0x67B1))) {
|
||||
(rdev->pdev->device == 0x67B1)) &&
|
||||
(rdev->pdev->revision == 0)) {
|
||||
if ((memory_clock > 100000) && (memory_clock <= 125000)) {
|
||||
tmp2 = (((0x31 * engine_clock) / 125000) - 1) & 0xff;
|
||||
*dram_timimg2 &= ~0x00ff0000;
|
||||
@@ -3304,7 +3305,8 @@ static int ci_populate_all_memory_levels(struct radeon_device *rdev)
|
||||
pi->smc_state_table.MemoryLevel[0].EnabledForActivity = 1;
|
||||
|
||||
if ((dpm_table->mclk_table.count >= 2) &&
|
||||
((rdev->pdev->device == 0x67B0) || (rdev->pdev->device == 0x67B1))) {
|
||||
((rdev->pdev->device == 0x67B0) || (rdev->pdev->device == 0x67B1)) &&
|
||||
(rdev->pdev->revision == 0)) {
|
||||
pi->smc_state_table.MemoryLevel[1].MinVddc =
|
||||
pi->smc_state_table.MemoryLevel[0].MinVddc;
|
||||
pi->smc_state_table.MemoryLevel[1].MinVddcPhases =
|
||||
@@ -4493,7 +4495,8 @@ static int ci_register_patching_mc_seq(struct radeon_device *rdev,
|
||||
|
||||
if (patch &&
|
||||
((rdev->pdev->device == 0x67B0) ||
|
||||
(rdev->pdev->device == 0x67B1))) {
|
||||
(rdev->pdev->device == 0x67B1)) &&
|
||||
(rdev->pdev->revision == 0)) {
|
||||
for (i = 0; i < table->last; i++) {
|
||||
if (table->last >= SMU7_DISCRETE_MC_REGISTER_ARRAY_SIZE)
|
||||
return -EINVAL;
|
||||
|
||||
@@ -741,6 +741,7 @@ static int sti_hda_probe(struct platform_device *pdev)
|
||||
struct device *dev = &pdev->dev;
|
||||
struct sti_hda *hda;
|
||||
struct resource *res;
|
||||
int ret;
|
||||
|
||||
DRM_INFO("%s\n", __func__);
|
||||
|
||||
@@ -779,7 +780,9 @@ static int sti_hda_probe(struct platform_device *pdev)
|
||||
return PTR_ERR(hda->clk_hddac);
|
||||
}
|
||||
|
||||
drm_bridge_add(&hda->bridge);
|
||||
ret = devm_drm_bridge_add(dev, &hda->bridge);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
platform_set_drvdata(pdev, hda);
|
||||
|
||||
@@ -788,10 +791,7 @@ static int sti_hda_probe(struct platform_device *pdev)
|
||||
|
||||
static void sti_hda_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct sti_hda *hda = platform_get_drvdata(pdev);
|
||||
|
||||
component_del(&pdev->dev, &sti_hda_ops);
|
||||
drm_bridge_remove(&hda->bridge);
|
||||
}
|
||||
|
||||
static const struct of_device_id hda_of_match[] = {
|
||||
|
||||
@@ -761,25 +761,21 @@ static int bochs_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent
|
||||
|
||||
ret = pcim_enable_device(pdev);
|
||||
if (ret)
|
||||
goto err_free_dev;
|
||||
return ret;
|
||||
|
||||
pci_set_drvdata(pdev, dev);
|
||||
|
||||
ret = bochs_load(bochs);
|
||||
if (ret)
|
||||
goto err_free_dev;
|
||||
return ret;
|
||||
|
||||
ret = drm_dev_register(dev, 0);
|
||||
if (ret)
|
||||
goto err_free_dev;
|
||||
return ret;
|
||||
|
||||
drm_client_setup(dev, NULL);
|
||||
|
||||
return ret;
|
||||
|
||||
err_free_dev:
|
||||
drm_dev_put(dev);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void bochs_pci_remove(struct pci_dev *pdev)
|
||||
|
||||
@@ -206,6 +206,14 @@ static struct page *ttm_pool_alloc_page(struct ttm_pool *pool, gfp_t gfp_flags,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void __free_pages_gpu_account(struct page *p, unsigned int order,
|
||||
bool reclaim)
|
||||
{
|
||||
mod_lruvec_page_state(p, reclaim ? NR_GPU_RECLAIM : NR_GPU_ACTIVE,
|
||||
-(1 << order));
|
||||
__free_pages(p, order);
|
||||
}
|
||||
|
||||
/* Reset the caching and pages of size 1 << order */
|
||||
static void ttm_pool_free_page(struct ttm_pool *pool, enum ttm_caching caching,
|
||||
unsigned int order, struct page *p, bool reclaim)
|
||||
@@ -223,9 +231,7 @@ static void ttm_pool_free_page(struct ttm_pool *pool, enum ttm_caching caching,
|
||||
#endif
|
||||
|
||||
if (!pool || !ttm_pool_uses_dma_alloc(pool)) {
|
||||
mod_lruvec_page_state(p, reclaim ? NR_GPU_RECLAIM : NR_GPU_ACTIVE,
|
||||
-(1 << order));
|
||||
__free_pages(p, order);
|
||||
__free_pages_gpu_account(p, order, reclaim);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -606,7 +612,7 @@ static int ttm_pool_restore_commit(struct ttm_pool_tt_restore *restore,
|
||||
*/
|
||||
ttm_pool_split_for_swap(restore->pool, p);
|
||||
copy_highpage(restore->alloced_page + i, p);
|
||||
__free_pages(p, 0);
|
||||
__free_pages_gpu_account(p, 0, false);
|
||||
}
|
||||
|
||||
restore->restored_pages++;
|
||||
@@ -1068,7 +1074,7 @@ long ttm_pool_backup(struct ttm_pool *pool, struct ttm_tt *tt,
|
||||
if (flags->purge) {
|
||||
shrunken += num_pages;
|
||||
page->private = 0;
|
||||
__free_pages(page, order);
|
||||
__free_pages_gpu_account(page, order, false);
|
||||
memset(tt->pages + i, 0,
|
||||
num_pages * sizeof(*tt->pages));
|
||||
}
|
||||
@@ -1109,7 +1115,7 @@ long ttm_pool_backup(struct ttm_pool *pool, struct ttm_tt *tt,
|
||||
}
|
||||
handle = shandle;
|
||||
tt->pages[i] = ttm_backup_handle_to_page_ptr(handle);
|
||||
put_page(page);
|
||||
__free_pages_gpu_account(page, 0, false);
|
||||
shrunken++;
|
||||
}
|
||||
|
||||
|
||||
@@ -37,9 +37,17 @@ static bool intel_hdcp_gsc_check_status(struct drm_device *drm)
|
||||
struct xe_device *xe = to_xe_device(drm);
|
||||
struct xe_tile *tile = xe_device_get_root_tile(xe);
|
||||
struct xe_gt *gt = tile->media_gt;
|
||||
struct xe_gsc *gsc = >->uc.gsc;
|
||||
struct xe_gsc *gsc;
|
||||
|
||||
if (!gsc || !xe_uc_fw_is_available(&gsc->fw)) {
|
||||
if (!gt) {
|
||||
drm_dbg_kms(&xe->drm,
|
||||
"not checking GSC status for HDCP2.x: media GT not present or disabled\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
gsc = >->uc.gsc;
|
||||
|
||||
if (!xe_uc_fw_is_available(&gsc->fw)) {
|
||||
drm_dbg_kms(&xe->drm,
|
||||
"GSC Components not ready for HDCP2.x\n");
|
||||
return false;
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user