mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-04-30 21:40:37 -04:00
Merge drm/drm-next into drm-intel-gt-next
Lets eradicate a silent conflict between drm-intel-next and drm-intel-gt-next which added a duplicate function (try_firmware_load). Signed-off-by: Tvrtko Ursulin <tvrtko.ursulin@intel.com>
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -39,6 +39,7 @@
|
||||
*.o.*
|
||||
*.patch
|
||||
*.rmeta
|
||||
*.rpm
|
||||
*.rsi
|
||||
*.s
|
||||
*.so
|
||||
|
||||
@@ -52,9 +52,49 @@ properties:
|
||||
maxItems: 1
|
||||
description: extcon specifier for the Power Delivery
|
||||
|
||||
port:
|
||||
$ref: /schemas/graph.yaml#/properties/port
|
||||
description: A port node pointing to DPI host port node
|
||||
ports:
|
||||
$ref: /schemas/graph.yaml#/properties/ports
|
||||
|
||||
properties:
|
||||
port@0:
|
||||
$ref: /schemas/graph.yaml#/$defs/port-base
|
||||
unevaluatedProperties: false
|
||||
description: A port node pointing to DPI host port node
|
||||
|
||||
properties:
|
||||
endpoint:
|
||||
$ref: /schemas/graph.yaml#/$defs/endpoint-base
|
||||
unevaluatedProperties: false
|
||||
|
||||
properties:
|
||||
link-frequencies:
|
||||
minItems: 1
|
||||
maxItems: 1
|
||||
description: Allowed max link frequencies in Hz
|
||||
|
||||
port@1:
|
||||
$ref: /schemas/graph.yaml#/$defs/port-base
|
||||
unevaluatedProperties: false
|
||||
description: Video port for DP output
|
||||
|
||||
properties:
|
||||
endpoint:
|
||||
$ref: /schemas/graph.yaml#/$defs/endpoint-base
|
||||
unevaluatedProperties: false
|
||||
|
||||
properties:
|
||||
data-lanes:
|
||||
minItems: 1
|
||||
uniqueItems: true
|
||||
items:
|
||||
- enum: [ 0, 1 ]
|
||||
- const: 1
|
||||
- const: 2
|
||||
- const: 3
|
||||
|
||||
required:
|
||||
- port@0
|
||||
- port@1
|
||||
|
||||
required:
|
||||
- compatible
|
||||
@@ -63,6 +103,7 @@ required:
|
||||
- interrupts
|
||||
- reset-gpios
|
||||
- extcon
|
||||
- ports
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
@@ -85,9 +126,24 @@ examples:
|
||||
reset-gpios = <&pio 179 1>;
|
||||
extcon = <&usbc_extcon>;
|
||||
|
||||
port {
|
||||
it6505_in: endpoint {
|
||||
remote-endpoint = <&dpi_out>;
|
||||
ports {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
port@0 {
|
||||
reg = <0>;
|
||||
it6505_in: endpoint {
|
||||
remote-endpoint = <&dpi_out>;
|
||||
link-frequencies = /bits/ 64 <150000000>;
|
||||
};
|
||||
};
|
||||
|
||||
port@1 {
|
||||
reg = <1>;
|
||||
it6505_out: endpoint {
|
||||
remote-endpoint = <&dp_in>;
|
||||
data-lanes = <0 1>;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
@@ -17,7 +17,9 @@ description: |
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: ite,it66121
|
||||
enum:
|
||||
- ite,it66121
|
||||
- ite,it6610
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
@@ -0,0 +1,56 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/display/panel/focaltech,gpt3.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Focaltech GPT3 3.0" (640x480 pixels) IPS LCD panel
|
||||
|
||||
maintainers:
|
||||
- Christophe Branchereau <cbranchereau@gmail.com>
|
||||
|
||||
allOf:
|
||||
- $ref: panel-common.yaml#
|
||||
- $ref: /schemas/spi/spi-peripheral-props.yaml#
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: focaltech,gpt3
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- power-supply
|
||||
- reset-gpios
|
||||
|
||||
unevaluatedProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/gpio/gpio.h>
|
||||
|
||||
spi {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
panel@0 {
|
||||
compatible = "focaltech,gpt3";
|
||||
reg = <0>;
|
||||
|
||||
spi-max-frequency = <3125000>;
|
||||
|
||||
reset-gpios = <&gpe 2 GPIO_ACTIVE_LOW>;
|
||||
|
||||
backlight = <&backlight>;
|
||||
power-supply = <&vcc>;
|
||||
|
||||
port {
|
||||
panel_input: endpoint {
|
||||
remote-endpoint = <&panel_output>;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
@@ -0,0 +1,76 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0-only or BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/display/panel/himax,hx8394.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Himax HX8394 MIPI-DSI LCD panel controller
|
||||
|
||||
maintainers:
|
||||
- Ondrej Jirman <megi@xff.cz>
|
||||
- Javier Martinez Canillas <javierm@redhat.com>
|
||||
|
||||
description:
|
||||
Device tree bindings for panels based on the Himax HX8394 controller,
|
||||
such as the HannStar HSD060BHW4 720x1440 TFT LCD panel connected with
|
||||
a MIPI-DSI video interface.
|
||||
|
||||
allOf:
|
||||
- $ref: panel-common.yaml#
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
items:
|
||||
- enum:
|
||||
- hannstar,hsd060bhw4
|
||||
- const: himax,hx8394
|
||||
|
||||
reg: true
|
||||
|
||||
reset-gpios: true
|
||||
|
||||
backlight: true
|
||||
|
||||
port: true
|
||||
|
||||
vcc-supply:
|
||||
description: Panel power supply
|
||||
|
||||
iovcc-supply:
|
||||
description: I/O voltage supply
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- reset-gpios
|
||||
- backlight
|
||||
- port
|
||||
- vcc-supply
|
||||
- iovcc-supply
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/gpio/gpio.h>
|
||||
|
||||
dsi {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
panel@0 {
|
||||
compatible = "hannstar,hsd060bhw4", "himax,hx8394";
|
||||
reg = <0>;
|
||||
vcc-supply = <®_2v8_p>;
|
||||
iovcc-supply = <®_1v8_p>;
|
||||
reset-gpios = <&gpio3 13 GPIO_ACTIVE_LOW>;
|
||||
backlight = <&backlight>;
|
||||
|
||||
port {
|
||||
mipi_in_panel: endpoint {
|
||||
remote-endpoint = <&mipi_out_panel>;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
...
|
||||
@@ -22,8 +22,9 @@ description: |
|
||||
The standard defines the following interface signals for type C:
|
||||
- Power:
|
||||
- Vdd: Power supply for display module
|
||||
Called power-supply in this binding.
|
||||
- Vddi: Logic level supply for interface signals
|
||||
Combined into one in this binding called: power-supply
|
||||
Called io-supply in this binding.
|
||||
- Interface:
|
||||
- CSx: Chip select
|
||||
- SCL: Serial clock
|
||||
@@ -80,6 +81,11 @@ properties:
|
||||
Controller data/command selection (D/CX) in 4-line SPI mode.
|
||||
If not set, the controller is in 3-line SPI mode.
|
||||
|
||||
io-supply:
|
||||
description: |
|
||||
Logic level supply for interface signals (Vddi).
|
||||
No need to set if this is the same as power-supply.
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
|
||||
@@ -0,0 +1,53 @@
|
||||
# SPDX-License-Identifier: GPL-2.0-only or BSD-2-Clause
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/display/panel/visionox,vtdr6130.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Visionox VTDR6130 AMOLED DSI Panel
|
||||
|
||||
maintainers:
|
||||
- Neil Armstrong <neil.armstrong@linaro.org>
|
||||
|
||||
allOf:
|
||||
- $ref: panel-common.yaml#
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: visionox,vtdr6130
|
||||
|
||||
vddio-supply: true
|
||||
vci-supply: true
|
||||
vdd-supply: true
|
||||
port: true
|
||||
reset-gpios: true
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- vddio-supply
|
||||
- vci-supply
|
||||
- vdd-supply
|
||||
- reset-gpios
|
||||
- port
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/gpio/gpio.h>
|
||||
panel {
|
||||
compatible = "visionox,vtdr6130";
|
||||
|
||||
vddio-supply = <&vreg_l12b_1p8>;
|
||||
vci-supply = <&vreg_l13b_3p0>;
|
||||
vdd-supply = <&vreg_l11b_1p2>;
|
||||
|
||||
reset-gpios = <&tlmm 133 GPIO_ACTIVE_LOW>;
|
||||
|
||||
port {
|
||||
panel0_in: endpoint {
|
||||
remote-endpoint = <&dsi0_out>;
|
||||
};
|
||||
};
|
||||
};
|
||||
...
|
||||
@@ -29,7 +29,10 @@ Things between square brackets are optional.
|
||||
Valid names are::
|
||||
|
||||
- NSTC: 480i output, with the CCIR System-M TV mode and NTSC color encoding
|
||||
- NTSC-J: 480i output, with the CCIR System-M TV mode, the NTSC color
|
||||
encoding, and a black level equal to the blanking level.
|
||||
- PAL: 576i output, with the CCIR System-B TV mode and PAL color encoding
|
||||
- PAL-M: 480i output, with the CCIR System-M TV mode and PAL color encoding
|
||||
|
||||
If 'M' is specified in the mode_option argument (after <yres> and before
|
||||
<bpp> and <refresh>, if specified) the timings will be calculated using
|
||||
@@ -70,6 +73,8 @@ Valid options are::
|
||||
- reflect_y (boolean): Perform an axial symmetry on the Y axis
|
||||
- rotate (integer): Rotate the initial framebuffer by x
|
||||
degrees. Valid values are 0, 90, 180 and 270.
|
||||
- tv_mode: Analog TV mode. One of "NTSC", "NTSC-443", "NTSC-J", "PAL",
|
||||
"PAL-M", "PAL-N", or "SECAM".
|
||||
- panel_orientation, one of "normal", "upside_down", "left_side_up", or
|
||||
"right_side_up". For KMS drivers only, this sets the "panel orientation"
|
||||
property on the kms connector as hint for kms users.
|
||||
|
||||
@@ -188,6 +188,13 @@ Bridge Helper Reference
|
||||
.. kernel-doc:: drivers/gpu/drm/drm_bridge.c
|
||||
:export:
|
||||
|
||||
MIPI-DSI bridge operation
|
||||
-------------------------
|
||||
|
||||
.. kernel-doc:: drivers/gpu/drm/drm_bridge.c
|
||||
:doc: dsi bridge operations
|
||||
|
||||
|
||||
Bridge Connector Helper Reference
|
||||
---------------------------------
|
||||
|
||||
|
||||
@@ -520,6 +520,12 @@ HDMI Specific Connector Properties
|
||||
.. kernel-doc:: drivers/gpu/drm/drm_connector.c
|
||||
:doc: HDMI connector properties
|
||||
|
||||
Analog TV Specific Connector Properties
|
||||
---------------------------------------
|
||||
|
||||
.. kernel-doc:: drivers/gpu/drm/drm_connector.c
|
||||
:doc: Analog TV Connector Properties
|
||||
|
||||
Standard CRTC Properties
|
||||
------------------------
|
||||
|
||||
|
||||
@@ -402,19 +402,19 @@ It's possible to run the IGT-tests in a VM in two ways:
|
||||
1. Use IGT inside a VM
|
||||
2. Use IGT from the host machine and write the results in a shared directory.
|
||||
|
||||
As follow, there is an example of using a VM with a shared directory with
|
||||
the host machine to run igt-tests. As an example it's used virtme::
|
||||
Following is an example of using a VM with a shared directory with
|
||||
the host machine to run igt-tests. This example uses virtme::
|
||||
|
||||
$ virtme-run --rwdir /path/for/shared_dir --kdir=path/for/kernel/directory --mods=auto
|
||||
|
||||
Run the igt-tests in the guest machine, as example it's ran the 'kms_flip'
|
||||
Run the igt-tests in the guest machine. This example runs the 'kms_flip'
|
||||
tests::
|
||||
|
||||
$ /path/for/igt-gpu-tools/scripts/run-tests.sh -p -s -t "kms_flip.*" -v
|
||||
|
||||
In this example, instead of build the igt_runner, Piglit is used
|
||||
(-p option); it's created html summary of the tests results and it's saved
|
||||
in the folder "igt-gpu-tools/results"; it's executed only the igt-tests
|
||||
In this example, instead of building the igt_runner, Piglit is used
|
||||
(-p option). It creates an HTML summary of the test results and saves
|
||||
them in the folder "igt-gpu-tools/results". It executes only the igt-tests
|
||||
matching the -t option.
|
||||
|
||||
Display CRC Support
|
||||
|
||||
@@ -508,17 +508,18 @@ Clean up the debugfs support
|
||||
|
||||
There's a bunch of issues with it:
|
||||
|
||||
- The drm_info_list ->show() function doesn't even bother to cast to the drm
|
||||
structure for you. This is lazy.
|
||||
- Convert drivers to support the drm_debugfs_add_files() function instead of
|
||||
the drm_debugfs_create_files() function.
|
||||
|
||||
- Improve late-register debugfs by rolling out the same debugfs pre-register
|
||||
infrastructure for connector and crtc too. That way, the drivers won't need to
|
||||
split their setup code into init and register anymore.
|
||||
|
||||
- We probably want to have some support for debugfs files on crtc/connectors and
|
||||
maybe other kms objects directly in core. There's even drm_print support in
|
||||
the funcs for these objects to dump kms state, so it's all there. And then the
|
||||
->show() functions should obviously give you a pointer to the right object.
|
||||
|
||||
- The drm_info_list stuff is centered on drm_minor instead of drm_device. For
|
||||
anything we want to print drm_device (or maybe drm_file) is the right thing.
|
||||
|
||||
- The drm_driver->debugfs_init hooks we have is just an artifact of the old
|
||||
midlayered load sequence. DRM debugfs should work more like sysfs, where you
|
||||
can create properties/files for an object anytime you want, and the core
|
||||
@@ -527,8 +528,6 @@ There's a bunch of issues with it:
|
||||
this (together with the drm_minor->drm_device move) would allow us to remove
|
||||
debugfs_init.
|
||||
|
||||
Previous RFC that hasn't landed yet: https://lore.kernel.org/dri-devel/20200513114130.28641-2-wambui.karugax@gmail.com/
|
||||
|
||||
Contact: Daniel Vetter
|
||||
|
||||
Level: Intermediate
|
||||
|
||||
@@ -54,6 +54,25 @@ VEC (Composite TV out) encoder
|
||||
.. kernel-doc:: drivers/gpu/drm/vc4/vc4_vec.c
|
||||
:doc: VC4 SDTV module
|
||||
|
||||
KUnit Tests
|
||||
===========
|
||||
|
||||
The VC4 Driver uses KUnit to perform driver-specific unit and
|
||||
integration tests.
|
||||
|
||||
These tests are using a mock driver and can be ran using the
|
||||
command below, on either arm or arm64 architectures,
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
$ ./tools/testing/kunit/kunit.py run \
|
||||
--kunitconfig=drivers/gpu/drm/vc4/tests/.kunitconfig \
|
||||
--cross_compile aarch64-linux-gnu- --arch arm64
|
||||
|
||||
Parts of the driver that are currently covered by tests are:
|
||||
* The HVS to PixelValve dynamic FIFO assignment, for the BCM2835-7
|
||||
and BCM2711.
|
||||
|
||||
Memory Management and 3D Command Submission
|
||||
===========================================
|
||||
|
||||
|
||||
@@ -104,3 +104,4 @@ to do something different in the near future.
|
||||
../riscv/patch-acceptance
|
||||
../driver-api/media/maintainer-entry-profile
|
||||
../driver-api/vfio-pci-device-specific-driver-acceptance
|
||||
../nvme/feature-and-quirk-policy
|
||||
|
||||
77
Documentation/nvme/feature-and-quirk-policy.rst
Normal file
77
Documentation/nvme/feature-and-quirk-policy.rst
Normal file
@@ -0,0 +1,77 @@
|
||||
.. SPDX-License-Identifier: GPL-2.0
|
||||
|
||||
=======================================
|
||||
Linux NVMe feature and and quirk policy
|
||||
=======================================
|
||||
|
||||
This file explains the policy used to decide what is supported by the
|
||||
Linux NVMe driver and what is not.
|
||||
|
||||
|
||||
Introduction
|
||||
============
|
||||
|
||||
NVM Express is an open collection of standards and information.
|
||||
|
||||
The Linux NVMe host driver in drivers/nvme/host/ supports devices
|
||||
implementing the NVM Express (NVMe) family of specifications, which
|
||||
currently consists of a number of documents:
|
||||
|
||||
- the NVMe Base specification
|
||||
- various Command Set specifications (e.g. NVM Command Set)
|
||||
- various Transport specifications (e.g. PCIe, Fibre Channel, RDMA, TCP)
|
||||
- the NVMe Management Interface specification
|
||||
|
||||
See https://nvmexpress.org/developers/ for the NVMe specifications.
|
||||
|
||||
|
||||
Supported features
|
||||
==================
|
||||
|
||||
NVMe is a large suite of specifications, and contains features that are only
|
||||
useful or suitable for specific use-cases. It is important to note that Linux
|
||||
does not aim to implement every feature in the specification. Every additional
|
||||
feature implemented introduces more code, more maintenance and potentially more
|
||||
bugs. Hence there is an inherent tradeoff between functionality and
|
||||
maintainability of the NVMe host driver.
|
||||
|
||||
Any feature implemented in the Linux NVMe host driver must support the
|
||||
following requirements:
|
||||
|
||||
1. The feature is specified in a release version of an official NVMe
|
||||
specification, or in a ratified Technical Proposal (TP) that is
|
||||
available on NVMe website. Or if it is not directly related to the
|
||||
on-wire protocol, does not contradict any of the NVMe specifications.
|
||||
2. Does not conflict with the Linux architecture, nor the design of the
|
||||
NVMe host driver.
|
||||
3. Has a clear, indisputable value-proposition and a wide consensus across
|
||||
the community.
|
||||
|
||||
Vendor specific extensions are generally not supported in the NVMe host
|
||||
driver.
|
||||
|
||||
It is strongly recommended to work with the Linux NVMe and block layer
|
||||
maintainers and get feedback on specification changes that are intended
|
||||
to be used by the Linux NVMe host driver in order to avoid conflict at a
|
||||
later stage.
|
||||
|
||||
|
||||
Quirks
|
||||
======
|
||||
|
||||
Sometimes implementations of open standards fail to correctly implement parts
|
||||
of the standards. Linux uses identifier-based quirks to work around such
|
||||
implementation bugs. The intent of quirks is to deal with widely available
|
||||
hardware, usually consumer, which Linux users can't use without these quirks.
|
||||
Typically these implementations are not or only superficially tested with Linux
|
||||
by the hardware manufacturer.
|
||||
|
||||
The Linux NVMe maintainers decide ad hoc whether to quirk implementations
|
||||
based on the impact of the problem to Linux users and how it impacts
|
||||
maintainability of the driver. In general quirks are a last resort, if no
|
||||
firmware updates or other workarounds are available from the vendor.
|
||||
|
||||
Quirks will not be added to the Linux kernel for hardware that isn't available
|
||||
on the mass market. Hardware that fails qualification for enterprise Linux
|
||||
distributions, ChromeOS, Android or other consumers of the Linux kernel
|
||||
should be fixed before it is shipped instead of relying on Linux quirks.
|
||||
@@ -222,6 +222,7 @@ Code Seq# Include File Comments
|
||||
'a' 00-0F drivers/crypto/qat/qat_common/adf_cfg_common.h conflict! qat driver
|
||||
'b' 00-FF conflict! bit3 vme host bridge
|
||||
<mailto:natalia@nikhefk.nikhef.nl>
|
||||
'b' 00-0F linux/dma-buf.h conflict!
|
||||
'c' all linux/cm4000_cs.h conflict!
|
||||
'c' 00-7F linux/comstats.h conflict!
|
||||
'c' 00-7F linux/coda.h conflict!
|
||||
|
||||
@@ -949,6 +949,43 @@ The following tables list existing packed RGB formats.
|
||||
- b\ :sub:`2`
|
||||
- b\ :sub:`1`
|
||||
- b\ :sub:`0`
|
||||
* .. _MEDIA-BUS-FMT-BGR666-1X18:
|
||||
|
||||
- MEDIA_BUS_FMT_BGR666_1X18
|
||||
- 0x1023
|
||||
-
|
||||
-
|
||||
-
|
||||
-
|
||||
-
|
||||
-
|
||||
-
|
||||
-
|
||||
-
|
||||
-
|
||||
-
|
||||
-
|
||||
-
|
||||
-
|
||||
-
|
||||
- b\ :sub:`5`
|
||||
- b\ :sub:`4`
|
||||
- b\ :sub:`3`
|
||||
- b\ :sub:`2`
|
||||
- b\ :sub:`1`
|
||||
- b\ :sub:`0`
|
||||
- g\ :sub:`5`
|
||||
- g\ :sub:`4`
|
||||
- g\ :sub:`3`
|
||||
- g\ :sub:`2`
|
||||
- g\ :sub:`1`
|
||||
- g\ :sub:`0`
|
||||
- r\ :sub:`5`
|
||||
- r\ :sub:`4`
|
||||
- r\ :sub:`3`
|
||||
- r\ :sub:`2`
|
||||
- r\ :sub:`1`
|
||||
- r\ :sub:`0`
|
||||
* .. _MEDIA-BUS-FMT-RBG888-1X24:
|
||||
|
||||
- MEDIA_BUS_FMT_RBG888_1X24
|
||||
@@ -1023,6 +1060,80 @@ The following tables list existing packed RGB formats.
|
||||
- b\ :sub:`2`
|
||||
- b\ :sub:`1`
|
||||
- b\ :sub:`0`
|
||||
* .. _MEDIA-BUS-FMT-BGR666-1X24_CPADHI:
|
||||
|
||||
- MEDIA_BUS_FMT_BGR666_1X24_CPADHI
|
||||
- 0x1024
|
||||
-
|
||||
-
|
||||
-
|
||||
-
|
||||
-
|
||||
-
|
||||
-
|
||||
-
|
||||
-
|
||||
- 0
|
||||
- 0
|
||||
- b\ :sub:`5`
|
||||
- b\ :sub:`4`
|
||||
- b\ :sub:`3`
|
||||
- b\ :sub:`2`
|
||||
- b\ :sub:`1`
|
||||
- b\ :sub:`0`
|
||||
- 0
|
||||
- 0
|
||||
- g\ :sub:`5`
|
||||
- g\ :sub:`4`
|
||||
- g\ :sub:`3`
|
||||
- g\ :sub:`2`
|
||||
- g\ :sub:`1`
|
||||
- g\ :sub:`0`
|
||||
- 0
|
||||
- 0
|
||||
- r\ :sub:`5`
|
||||
- r\ :sub:`4`
|
||||
- r\ :sub:`3`
|
||||
- r\ :sub:`2`
|
||||
- r\ :sub:`1`
|
||||
- r\ :sub:`0`
|
||||
* .. _MEDIA-BUS-FMT-RGB565-1X24_CPADHI:
|
||||
|
||||
- MEDIA_BUS_FMT_RGB565_1X24_CPADHI
|
||||
- 0x1022
|
||||
-
|
||||
-
|
||||
-
|
||||
-
|
||||
-
|
||||
-
|
||||
-
|
||||
-
|
||||
-
|
||||
- 0
|
||||
- 0
|
||||
- 0
|
||||
- r\ :sub:`4`
|
||||
- r\ :sub:`3`
|
||||
- r\ :sub:`2`
|
||||
- r\ :sub:`1`
|
||||
- r\ :sub:`0`
|
||||
- 0
|
||||
- 0
|
||||
- g\ :sub:`5`
|
||||
- g\ :sub:`4`
|
||||
- g\ :sub:`3`
|
||||
- g\ :sub:`2`
|
||||
- g\ :sub:`1`
|
||||
- g\ :sub:`0`
|
||||
- 0
|
||||
- 0
|
||||
- 0
|
||||
- b\ :sub:`4`
|
||||
- b\ :sub:`3`
|
||||
- b\ :sub:`2`
|
||||
- b\ :sub:`1`
|
||||
- b\ :sub:`0`
|
||||
* .. _MEDIA-BUS-FMT-BGR888-1X24:
|
||||
|
||||
- MEDIA_BUS_FMT_BGR888_1X24
|
||||
|
||||
@@ -5343,9 +5343,9 @@ KVM_XEN_ATTR_TYPE_SHARED_INFO
|
||||
32 vCPUs in the shared_info page, KVM does not automatically do so
|
||||
and instead requires that KVM_XEN_VCPU_ATTR_TYPE_VCPU_INFO be used
|
||||
explicitly even when the vcpu_info for a given vCPU resides at the
|
||||
"default" location in the shared_info page. This is because KVM is
|
||||
not aware of the Xen CPU id which is used as the index into the
|
||||
vcpu_info[] array, so cannot know the correct default location.
|
||||
"default" location in the shared_info page. This is because KVM may
|
||||
not be aware of the Xen CPU id which is used as the index into the
|
||||
vcpu_info[] array, so may know the correct default location.
|
||||
|
||||
Note that the shared info page may be constantly written to by KVM;
|
||||
it contains the event channel bitmap used to deliver interrupts to
|
||||
@@ -5356,23 +5356,29 @@ KVM_XEN_ATTR_TYPE_SHARED_INFO
|
||||
any vCPU has been running or any event channel interrupts can be
|
||||
routed to the guest.
|
||||
|
||||
Setting the gfn to KVM_XEN_INVALID_GFN will disable the shared info
|
||||
page.
|
||||
|
||||
KVM_XEN_ATTR_TYPE_UPCALL_VECTOR
|
||||
Sets the exception vector used to deliver Xen event channel upcalls.
|
||||
This is the HVM-wide vector injected directly by the hypervisor
|
||||
(not through the local APIC), typically configured by a guest via
|
||||
HVM_PARAM_CALLBACK_IRQ.
|
||||
HVM_PARAM_CALLBACK_IRQ. This can be disabled again (e.g. for guest
|
||||
SHUTDOWN_soft_reset) by setting it to zero.
|
||||
|
||||
KVM_XEN_ATTR_TYPE_EVTCHN
|
||||
This attribute is available when the KVM_CAP_XEN_HVM ioctl indicates
|
||||
support for KVM_XEN_HVM_CONFIG_EVTCHN_SEND features. It configures
|
||||
an outbound port number for interception of EVTCHNOP_send requests
|
||||
from the guest. A given sending port number may be directed back
|
||||
to a specified vCPU (by APIC ID) / port / priority on the guest,
|
||||
or to trigger events on an eventfd. The vCPU and priority can be
|
||||
changed by setting KVM_XEN_EVTCHN_UPDATE in a subsequent call,
|
||||
but other fields cannot change for a given sending port. A port
|
||||
mapping is removed by using KVM_XEN_EVTCHN_DEASSIGN in the flags
|
||||
field.
|
||||
from the guest. A given sending port number may be directed back to
|
||||
a specified vCPU (by APIC ID) / port / priority on the guest, or to
|
||||
trigger events on an eventfd. The vCPU and priority can be changed
|
||||
by setting KVM_XEN_EVTCHN_UPDATE in a subsequent call, but but other
|
||||
fields cannot change for a given sending port. A port mapping is
|
||||
removed by using KVM_XEN_EVTCHN_DEASSIGN in the flags field. Passing
|
||||
KVM_XEN_EVTCHN_RESET in the flags field removes all interception of
|
||||
outbound event channels. The values of the flags field are mutually
|
||||
exclusive and cannot be combined as a bitmask.
|
||||
|
||||
KVM_XEN_ATTR_TYPE_XEN_VERSION
|
||||
This attribute is available when the KVM_CAP_XEN_HVM ioctl indicates
|
||||
@@ -5388,7 +5394,7 @@ KVM_XEN_ATTR_TYPE_RUNSTATE_UPDATE_FLAG
|
||||
support for KVM_XEN_HVM_CONFIG_RUNSTATE_UPDATE_FLAG. It enables the
|
||||
XEN_RUNSTATE_UPDATE flag which allows guest vCPUs to safely read
|
||||
other vCPUs' vcpu_runstate_info. Xen guests enable this feature via
|
||||
the VM_ASST_TYPE_runstate_update_flag of the HYPERVISOR_vm_assist
|
||||
the VMASST_TYPE_runstate_update_flag of the HYPERVISOR_vm_assist
|
||||
hypercall.
|
||||
|
||||
4.127 KVM_XEN_HVM_GET_ATTR
|
||||
@@ -5446,15 +5452,18 @@ KVM_XEN_VCPU_ATTR_TYPE_VCPU_INFO
|
||||
As with the shared_info page for the VM, the corresponding page may be
|
||||
dirtied at any time if event channel interrupt delivery is enabled, so
|
||||
userspace should always assume that the page is dirty without relying
|
||||
on dirty logging.
|
||||
on dirty logging. Setting the gpa to KVM_XEN_INVALID_GPA will disable
|
||||
the vcpu_info.
|
||||
|
||||
KVM_XEN_VCPU_ATTR_TYPE_VCPU_TIME_INFO
|
||||
Sets the guest physical address of an additional pvclock structure
|
||||
for a given vCPU. This is typically used for guest vsyscall support.
|
||||
Setting the gpa to KVM_XEN_INVALID_GPA will disable the structure.
|
||||
|
||||
KVM_XEN_VCPU_ATTR_TYPE_RUNSTATE_ADDR
|
||||
Sets the guest physical address of the vcpu_runstate_info for a given
|
||||
vCPU. This is how a Xen guest tracks CPU state such as steal time.
|
||||
Setting the gpa to KVM_XEN_INVALID_GPA will disable the runstate area.
|
||||
|
||||
KVM_XEN_VCPU_ATTR_TYPE_RUNSTATE_CURRENT
|
||||
Sets the runstate (RUNSTATE_running/_runnable/_blocked/_offline) of
|
||||
@@ -5487,7 +5496,8 @@ KVM_XEN_VCPU_ATTR_TYPE_TIMER
|
||||
This attribute is available when the KVM_CAP_XEN_HVM ioctl indicates
|
||||
support for KVM_XEN_HVM_CONFIG_EVTCHN_SEND features. It sets the
|
||||
event channel port/priority for the VIRQ_TIMER of the vCPU, as well
|
||||
as allowing a pending timer to be saved/restored.
|
||||
as allowing a pending timer to be saved/restored. Setting the timer
|
||||
port to zero disables kernel handling of the singleshot timer.
|
||||
|
||||
KVM_XEN_VCPU_ATTR_TYPE_UPCALL_VECTOR
|
||||
This attribute is available when the KVM_CAP_XEN_HVM ioctl indicates
|
||||
@@ -5495,7 +5505,8 @@ KVM_XEN_VCPU_ATTR_TYPE_UPCALL_VECTOR
|
||||
per-vCPU local APIC upcall vector, configured by a Xen guest with
|
||||
the HVMOP_set_evtchn_upcall_vector hypercall. This is typically
|
||||
used by Windows guests, and is distinct from the HVM-wide upcall
|
||||
vector configured with HVM_PARAM_CALLBACK_IRQ.
|
||||
vector configured with HVM_PARAM_CALLBACK_IRQ. It is disabled by
|
||||
setting the vector to zero.
|
||||
|
||||
|
||||
4.129 KVM_XEN_VCPU_GET_ATTR
|
||||
@@ -6577,11 +6588,6 @@ Please note that the kernel is allowed to use the kvm_run structure as the
|
||||
primary storage for certain register types. Therefore, the kernel may use the
|
||||
values in kvm_run even if the corresponding bit in kvm_dirty_regs is not set.
|
||||
|
||||
::
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
6. Capabilities that can be enabled on vCPUs
|
||||
============================================
|
||||
|
||||
@@ -16,17 +16,26 @@ The acquisition orders for mutexes are as follows:
|
||||
- kvm->slots_lock is taken outside kvm->irq_lock, though acquiring
|
||||
them together is quite rare.
|
||||
|
||||
- Unlike kvm->slots_lock, kvm->slots_arch_lock is released before
|
||||
synchronize_srcu(&kvm->srcu). Therefore kvm->slots_arch_lock
|
||||
can be taken inside a kvm->srcu read-side critical section,
|
||||
while kvm->slots_lock cannot.
|
||||
|
||||
- kvm->mn_active_invalidate_count ensures that pairs of
|
||||
invalidate_range_start() and invalidate_range_end() callbacks
|
||||
use the same memslots array. kvm->slots_lock and kvm->slots_arch_lock
|
||||
are taken on the waiting side in install_new_memslots, so MMU notifiers
|
||||
must not take either kvm->slots_lock or kvm->slots_arch_lock.
|
||||
|
||||
For SRCU:
|
||||
|
||||
- ``synchronize_srcu(&kvm->srcu)`` is called _inside_
|
||||
the kvm->slots_lock critical section, therefore kvm->slots_lock
|
||||
cannot be taken inside a kvm->srcu read-side critical section.
|
||||
Instead, kvm->slots_arch_lock is released before the call
|
||||
to ``synchronize_srcu()`` and _can_ be taken inside a
|
||||
kvm->srcu read-side critical section.
|
||||
|
||||
- kvm->lock is taken inside kvm->srcu, therefore
|
||||
``synchronize_srcu(&kvm->srcu)`` cannot be called inside
|
||||
a kvm->lock critical section. If you cannot delay the
|
||||
call until after kvm->lock is released, use ``call_srcu``.
|
||||
|
||||
On x86:
|
||||
|
||||
- vcpu->mutex is taken outside kvm->arch.hyperv.hv_lock
|
||||
|
||||
14
MAINTAINERS
14
MAINTAINERS
@@ -6550,6 +6550,14 @@ S: Maintained
|
||||
T: git git://anongit.freedesktop.org/drm/drm-misc
|
||||
F: drivers/gpu/drm/tiny/gm12u320.c
|
||||
|
||||
DRM DRIVER FOR HIMAX HX8394 MIPI-DSI LCD panels
|
||||
M: Ondrej Jirman <megi@xff.cz>
|
||||
M: Javier Martinez Canillas <javierm@redhat.com>
|
||||
S: Maintained
|
||||
T: git git://anongit.freedesktop.org/drm/drm-misc
|
||||
F: Documentation/devicetree/bindings/display/panel/himax,hx8394.yaml
|
||||
F: drivers/gpu/drm/panel/panel-himax-hx8394.c
|
||||
|
||||
DRM DRIVER FOR HX8357D PANELS
|
||||
M: Emma Anholt <emma@anholt.net>
|
||||
S: Maintained
|
||||
@@ -6984,7 +6992,7 @@ M: Philipp Zabel <p.zabel@pengutronix.de>
|
||||
L: dri-devel@lists.freedesktop.org
|
||||
S: Maintained
|
||||
F: Documentation/devicetree/bindings/display/imx/
|
||||
F: drivers/gpu/drm/imx/
|
||||
F: drivers/gpu/drm/imx/ipuv3/
|
||||
F: drivers/gpu/ipu-v3/
|
||||
|
||||
DRM DRIVERS FOR FREESCALE IMX BRIDGE
|
||||
@@ -7009,7 +7017,6 @@ M: Xinliang Liu <xinliang.liu@linaro.org>
|
||||
M: Tian Tao <tiantao6@hisilicon.com>
|
||||
R: John Stultz <jstultz@google.com>
|
||||
R: Xinwei Kong <kong.kongxinwei@hisilicon.com>
|
||||
R: Chen Feng <puck.chen@hisilicon.com>
|
||||
L: dri-devel@lists.freedesktop.org
|
||||
S: Maintained
|
||||
T: git git://anongit.freedesktop.org/drm/drm-misc
|
||||
@@ -11468,7 +11475,7 @@ F: arch/x86/kvm/hyperv.*
|
||||
F: arch/x86/kvm/kvm_onhyperv.*
|
||||
F: arch/x86/kvm/svm/hyperv.*
|
||||
F: arch/x86/kvm/svm/svm_onhyperv.*
|
||||
F: arch/x86/kvm/vmx/evmcs.*
|
||||
F: arch/x86/kvm/vmx/hyperv.*
|
||||
|
||||
KVM X86 Xen (KVM/Xen)
|
||||
M: David Woodhouse <dwmw2@infradead.org>
|
||||
@@ -14916,6 +14923,7 @@ L: linux-nvme@lists.infradead.org
|
||||
S: Supported
|
||||
W: http://git.infradead.org/nvme.git
|
||||
T: git://git.infradead.org/nvme.git
|
||||
F: Documentation/nvme/
|
||||
F: drivers/nvme/host/
|
||||
F: drivers/nvme/common/
|
||||
F: include/linux/nvme*
|
||||
|
||||
4
Makefile
4
Makefile
@@ -2,7 +2,7 @@
|
||||
VERSION = 6
|
||||
PATCHLEVEL = 2
|
||||
SUBLEVEL = 0
|
||||
EXTRAVERSION = -rc1
|
||||
EXTRAVERSION = -rc2
|
||||
NAME = Hurr durr I'ma ninja sloth
|
||||
|
||||
# *DOCUMENTATION*
|
||||
@@ -297,7 +297,7 @@ no-compiler-targets := $(no-dot-config-targets) install dtbs_install \
|
||||
headers_install modules_install kernelrelease image_name
|
||||
no-sync-config-targets := $(no-dot-config-targets) %install kernelrelease \
|
||||
image_name
|
||||
single-targets := %.a %.i %.rsi %.ko %.lds %.ll %.lst %.mod %.o %.s %.symtypes %/
|
||||
single-targets := %.a %.i %.ko %.lds %.ll %.lst %.mod %.o %.rsi %.s %.symtypes %/
|
||||
|
||||
config-build :=
|
||||
mixed-build :=
|
||||
|
||||
@@ -1387,7 +1387,7 @@ static int __init amd_core_pmu_init(void)
|
||||
* numbered counter following it.
|
||||
*/
|
||||
for (i = 0; i < x86_pmu.num_counters - 1; i += 2)
|
||||
even_ctr_mask |= 1 << i;
|
||||
even_ctr_mask |= BIT_ULL(i);
|
||||
|
||||
pair_constraint = (struct event_constraint)
|
||||
__EVENT_CONSTRAINT(0, even_ctr_mask, 0,
|
||||
|
||||
@@ -119,7 +119,7 @@ static bool is_coretext(const struct core_text *ct, void *addr)
|
||||
return within_module_coretext(addr);
|
||||
}
|
||||
|
||||
static __init_or_module bool skip_addr(void *dest)
|
||||
static bool skip_addr(void *dest)
|
||||
{
|
||||
if (dest == error_entry)
|
||||
return true;
|
||||
@@ -181,7 +181,7 @@ static const u8 nops[] = {
|
||||
0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90,
|
||||
};
|
||||
|
||||
static __init_or_module void *patch_dest(void *dest, bool direct)
|
||||
static void *patch_dest(void *dest, bool direct)
|
||||
{
|
||||
unsigned int tsize = SKL_TMPL_SIZE;
|
||||
u8 *pad = dest - tsize;
|
||||
|
||||
@@ -37,6 +37,7 @@
|
||||
#include <linux/extable.h>
|
||||
#include <linux/kdebug.h>
|
||||
#include <linux/kallsyms.h>
|
||||
#include <linux/kgdb.h>
|
||||
#include <linux/ftrace.h>
|
||||
#include <linux/kasan.h>
|
||||
#include <linux/moduleloader.h>
|
||||
@@ -281,12 +282,15 @@ static int can_probe(unsigned long paddr)
|
||||
if (ret < 0)
|
||||
return 0;
|
||||
|
||||
#ifdef CONFIG_KGDB
|
||||
/*
|
||||
* Another debugging subsystem might insert this breakpoint.
|
||||
* In that case, we can't recover it.
|
||||
* If there is a dynamically installed kgdb sw breakpoint,
|
||||
* this function should not be probed.
|
||||
*/
|
||||
if (insn.opcode.bytes[0] == INT3_INSN_OPCODE)
|
||||
if (insn.opcode.bytes[0] == INT3_INSN_OPCODE &&
|
||||
kgdb_has_hit_break(addr))
|
||||
return 0;
|
||||
#endif
|
||||
addr += insn.length;
|
||||
}
|
||||
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
#include <linux/extable.h>
|
||||
#include <linux/kdebug.h>
|
||||
#include <linux/kallsyms.h>
|
||||
#include <linux/kgdb.h>
|
||||
#include <linux/ftrace.h>
|
||||
#include <linux/objtool.h>
|
||||
#include <linux/pgtable.h>
|
||||
@@ -279,19 +280,6 @@ static int insn_is_indirect_jump(struct insn *insn)
|
||||
return ret;
|
||||
}
|
||||
|
||||
static bool is_padding_int3(unsigned long addr, unsigned long eaddr)
|
||||
{
|
||||
unsigned char ops;
|
||||
|
||||
for (; addr < eaddr; addr++) {
|
||||
if (get_kernel_nofault(ops, (void *)addr) < 0 ||
|
||||
ops != INT3_INSN_OPCODE)
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Decode whole function to ensure any instructions don't jump into target */
|
||||
static int can_optimize(unsigned long paddr)
|
||||
{
|
||||
@@ -334,15 +322,15 @@ static int can_optimize(unsigned long paddr)
|
||||
ret = insn_decode_kernel(&insn, (void *)recovered_insn);
|
||||
if (ret < 0)
|
||||
return 0;
|
||||
|
||||
#ifdef CONFIG_KGDB
|
||||
/*
|
||||
* In the case of detecting unknown breakpoint, this could be
|
||||
* a padding INT3 between functions. Let's check that all the
|
||||
* rest of the bytes are also INT3.
|
||||
* If there is a dynamically installed kgdb sw breakpoint,
|
||||
* this function should not be probed.
|
||||
*/
|
||||
if (insn.opcode.bytes[0] == INT3_INSN_OPCODE)
|
||||
return is_padding_int3(addr, paddr - offset + size) ? 1 : 0;
|
||||
|
||||
if (insn.opcode.bytes[0] == INT3_INSN_OPCODE &&
|
||||
kgdb_has_hit_break(addr))
|
||||
return 0;
|
||||
#endif
|
||||
/* Recover address */
|
||||
insn.kaddr = (void *)addr;
|
||||
insn.next_byte = (void *)(addr + insn.length);
|
||||
|
||||
@@ -1769,6 +1769,7 @@ static bool hv_is_vp_in_sparse_set(u32 vp_id, u64 valid_bank_mask, u64 sparse_ba
|
||||
}
|
||||
|
||||
struct kvm_hv_hcall {
|
||||
/* Hypercall input data */
|
||||
u64 param;
|
||||
u64 ingpa;
|
||||
u64 outgpa;
|
||||
@@ -1779,12 +1780,21 @@ struct kvm_hv_hcall {
|
||||
bool fast;
|
||||
bool rep;
|
||||
sse128_t xmm[HV_HYPERCALL_MAX_XMM_REGISTERS];
|
||||
|
||||
/*
|
||||
* Current read offset when KVM reads hypercall input data gradually,
|
||||
* either offset in bytes from 'ingpa' for regular hypercalls or the
|
||||
* number of already consumed 'XMM halves' for 'fast' hypercalls.
|
||||
*/
|
||||
union {
|
||||
gpa_t data_offset;
|
||||
int consumed_xmm_halves;
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
static int kvm_hv_get_hc_data(struct kvm *kvm, struct kvm_hv_hcall *hc,
|
||||
u16 orig_cnt, u16 cnt_cap, u64 *data,
|
||||
int consumed_xmm_halves, gpa_t offset)
|
||||
u16 orig_cnt, u16 cnt_cap, u64 *data)
|
||||
{
|
||||
/*
|
||||
* Preserve the original count when ignoring entries via a "cap", KVM
|
||||
@@ -1799,11 +1809,11 @@ static int kvm_hv_get_hc_data(struct kvm *kvm, struct kvm_hv_hcall *hc,
|
||||
* Each XMM holds two sparse banks, but do not count halves that
|
||||
* have already been consumed for hypercall parameters.
|
||||
*/
|
||||
if (orig_cnt > 2 * HV_HYPERCALL_MAX_XMM_REGISTERS - consumed_xmm_halves)
|
||||
if (orig_cnt > 2 * HV_HYPERCALL_MAX_XMM_REGISTERS - hc->consumed_xmm_halves)
|
||||
return HV_STATUS_INVALID_HYPERCALL_INPUT;
|
||||
|
||||
for (i = 0; i < cnt; i++) {
|
||||
j = i + consumed_xmm_halves;
|
||||
j = i + hc->consumed_xmm_halves;
|
||||
if (j % 2)
|
||||
data[i] = sse128_hi(hc->xmm[j / 2]);
|
||||
else
|
||||
@@ -1812,27 +1822,24 @@ static int kvm_hv_get_hc_data(struct kvm *kvm, struct kvm_hv_hcall *hc,
|
||||
return 0;
|
||||
}
|
||||
|
||||
return kvm_read_guest(kvm, hc->ingpa + offset, data,
|
||||
return kvm_read_guest(kvm, hc->ingpa + hc->data_offset, data,
|
||||
cnt * sizeof(*data));
|
||||
}
|
||||
|
||||
static u64 kvm_get_sparse_vp_set(struct kvm *kvm, struct kvm_hv_hcall *hc,
|
||||
u64 *sparse_banks, int consumed_xmm_halves,
|
||||
gpa_t offset)
|
||||
u64 *sparse_banks)
|
||||
{
|
||||
if (hc->var_cnt > HV_MAX_SPARSE_VCPU_BANKS)
|
||||
return -EINVAL;
|
||||
|
||||
/* Cap var_cnt to ignore banks that cannot contain a legal VP index. */
|
||||
return kvm_hv_get_hc_data(kvm, hc, hc->var_cnt, KVM_HV_MAX_SPARSE_VCPU_SET_BITS,
|
||||
sparse_banks, consumed_xmm_halves, offset);
|
||||
sparse_banks);
|
||||
}
|
||||
|
||||
static int kvm_hv_get_tlb_flush_entries(struct kvm *kvm, struct kvm_hv_hcall *hc, u64 entries[],
|
||||
int consumed_xmm_halves, gpa_t offset)
|
||||
static int kvm_hv_get_tlb_flush_entries(struct kvm *kvm, struct kvm_hv_hcall *hc, u64 entries[])
|
||||
{
|
||||
return kvm_hv_get_hc_data(kvm, hc, hc->rep_cnt, hc->rep_cnt,
|
||||
entries, consumed_xmm_halves, offset);
|
||||
return kvm_hv_get_hc_data(kvm, hc, hc->rep_cnt, hc->rep_cnt, entries);
|
||||
}
|
||||
|
||||
static void hv_tlb_flush_enqueue(struct kvm_vcpu *vcpu,
|
||||
@@ -1926,8 +1933,6 @@ static u64 kvm_hv_flush_tlb(struct kvm_vcpu *vcpu, struct kvm_hv_hcall *hc)
|
||||
struct kvm_vcpu *v;
|
||||
unsigned long i;
|
||||
bool all_cpus;
|
||||
int consumed_xmm_halves = 0;
|
||||
gpa_t data_offset;
|
||||
|
||||
/*
|
||||
* The Hyper-V TLFS doesn't allow more than HV_MAX_SPARSE_VCPU_BANKS
|
||||
@@ -1955,12 +1960,12 @@ static u64 kvm_hv_flush_tlb(struct kvm_vcpu *vcpu, struct kvm_hv_hcall *hc)
|
||||
flush.address_space = hc->ingpa;
|
||||
flush.flags = hc->outgpa;
|
||||
flush.processor_mask = sse128_lo(hc->xmm[0]);
|
||||
consumed_xmm_halves = 1;
|
||||
hc->consumed_xmm_halves = 1;
|
||||
} else {
|
||||
if (unlikely(kvm_read_guest(kvm, hc->ingpa,
|
||||
&flush, sizeof(flush))))
|
||||
return HV_STATUS_INVALID_HYPERCALL_INPUT;
|
||||
data_offset = sizeof(flush);
|
||||
hc->data_offset = sizeof(flush);
|
||||
}
|
||||
|
||||
trace_kvm_hv_flush_tlb(flush.processor_mask,
|
||||
@@ -1985,12 +1990,12 @@ static u64 kvm_hv_flush_tlb(struct kvm_vcpu *vcpu, struct kvm_hv_hcall *hc)
|
||||
flush_ex.flags = hc->outgpa;
|
||||
memcpy(&flush_ex.hv_vp_set,
|
||||
&hc->xmm[0], sizeof(hc->xmm[0]));
|
||||
consumed_xmm_halves = 2;
|
||||
hc->consumed_xmm_halves = 2;
|
||||
} else {
|
||||
if (unlikely(kvm_read_guest(kvm, hc->ingpa, &flush_ex,
|
||||
sizeof(flush_ex))))
|
||||
return HV_STATUS_INVALID_HYPERCALL_INPUT;
|
||||
data_offset = sizeof(flush_ex);
|
||||
hc->data_offset = sizeof(flush_ex);
|
||||
}
|
||||
|
||||
trace_kvm_hv_flush_tlb_ex(flush_ex.hv_vp_set.valid_bank_mask,
|
||||
@@ -2009,8 +2014,7 @@ static u64 kvm_hv_flush_tlb(struct kvm_vcpu *vcpu, struct kvm_hv_hcall *hc)
|
||||
if (!hc->var_cnt)
|
||||
goto ret_success;
|
||||
|
||||
if (kvm_get_sparse_vp_set(kvm, hc, sparse_banks,
|
||||
consumed_xmm_halves, data_offset))
|
||||
if (kvm_get_sparse_vp_set(kvm, hc, sparse_banks))
|
||||
return HV_STATUS_INVALID_HYPERCALL_INPUT;
|
||||
}
|
||||
|
||||
@@ -2021,8 +2025,10 @@ static u64 kvm_hv_flush_tlb(struct kvm_vcpu *vcpu, struct kvm_hv_hcall *hc)
|
||||
* consumed_xmm_halves to make sure TLB flush entries are read
|
||||
* from the correct offset.
|
||||
*/
|
||||
data_offset += hc->var_cnt * sizeof(sparse_banks[0]);
|
||||
consumed_xmm_halves += hc->var_cnt;
|
||||
if (hc->fast)
|
||||
hc->consumed_xmm_halves += hc->var_cnt;
|
||||
else
|
||||
hc->data_offset += hc->var_cnt * sizeof(sparse_banks[0]);
|
||||
}
|
||||
|
||||
if (hc->code == HVCALL_FLUSH_VIRTUAL_ADDRESS_SPACE ||
|
||||
@@ -2030,8 +2036,7 @@ static u64 kvm_hv_flush_tlb(struct kvm_vcpu *vcpu, struct kvm_hv_hcall *hc)
|
||||
hc->rep_cnt > ARRAY_SIZE(__tlb_flush_entries)) {
|
||||
tlb_flush_entries = NULL;
|
||||
} else {
|
||||
if (kvm_hv_get_tlb_flush_entries(kvm, hc, __tlb_flush_entries,
|
||||
consumed_xmm_halves, data_offset))
|
||||
if (kvm_hv_get_tlb_flush_entries(kvm, hc, __tlb_flush_entries))
|
||||
return HV_STATUS_INVALID_HYPERCALL_INPUT;
|
||||
tlb_flush_entries = __tlb_flush_entries;
|
||||
}
|
||||
@@ -2180,9 +2185,13 @@ static u64 kvm_hv_send_ipi(struct kvm_vcpu *vcpu, struct kvm_hv_hcall *hc)
|
||||
if (!hc->var_cnt)
|
||||
goto ret_success;
|
||||
|
||||
if (kvm_get_sparse_vp_set(kvm, hc, sparse_banks, 1,
|
||||
offsetof(struct hv_send_ipi_ex,
|
||||
vp_set.bank_contents)))
|
||||
if (!hc->fast)
|
||||
hc->data_offset = offsetof(struct hv_send_ipi_ex,
|
||||
vp_set.bank_contents);
|
||||
else
|
||||
hc->consumed_xmm_halves = 1;
|
||||
|
||||
if (kvm_get_sparse_vp_set(kvm, hc, sparse_banks))
|
||||
return HV_STATUS_INVALID_HYPERCALL_INPUT;
|
||||
}
|
||||
|
||||
|
||||
@@ -426,8 +426,9 @@ void kvm_scan_ioapic_routes(struct kvm_vcpu *vcpu,
|
||||
kvm_set_msi_irq(vcpu->kvm, entry, &irq);
|
||||
|
||||
if (irq.trig_mode &&
|
||||
kvm_apic_match_dest(vcpu, NULL, APIC_DEST_NOSHORT,
|
||||
irq.dest_id, irq.dest_mode))
|
||||
(kvm_apic_match_dest(vcpu, NULL, APIC_DEST_NOSHORT,
|
||||
irq.dest_id, irq.dest_mode) ||
|
||||
kvm_apic_pending_eoi(vcpu, irq.vector)))
|
||||
__set_bit(irq.vector, ioapic_handled_vectors);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -188,11 +188,11 @@ static inline bool lapic_in_kernel(struct kvm_vcpu *vcpu)
|
||||
|
||||
extern struct static_key_false_deferred apic_hw_disabled;
|
||||
|
||||
static inline int kvm_apic_hw_enabled(struct kvm_lapic *apic)
|
||||
static inline bool kvm_apic_hw_enabled(struct kvm_lapic *apic)
|
||||
{
|
||||
if (static_branch_unlikely(&apic_hw_disabled.key))
|
||||
return apic->vcpu->arch.apic_base & MSR_IA32_APICBASE_ENABLE;
|
||||
return MSR_IA32_APICBASE_ENABLE;
|
||||
return true;
|
||||
}
|
||||
|
||||
extern struct static_key_false_deferred apic_sw_disabled;
|
||||
|
||||
@@ -363,7 +363,7 @@ static __always_inline bool is_rsvd_spte(struct rsvd_bits_validate *rsvd_check,
|
||||
* A shadow-present leaf SPTE may be non-writable for 4 possible reasons:
|
||||
*
|
||||
* 1. To intercept writes for dirty logging. KVM write-protects huge pages
|
||||
* so that they can be split be split down into the dirty logging
|
||||
* so that they can be split down into the dirty logging
|
||||
* granularity (4KiB) whenever the guest writes to them. KVM also
|
||||
* write-protects 4KiB pages so that writes can be recorded in the dirty log
|
||||
* (e.g. if not using PML). SPTEs are write-protected for dirty logging
|
||||
|
||||
@@ -1074,7 +1074,9 @@ static int tdp_mmu_map_handle_target_level(struct kvm_vcpu *vcpu,
|
||||
int ret = RET_PF_FIXED;
|
||||
bool wrprot = false;
|
||||
|
||||
WARN_ON(sp->role.level != fault->goal_level);
|
||||
if (WARN_ON_ONCE(sp->role.level != fault->goal_level))
|
||||
return RET_PF_RETRY;
|
||||
|
||||
if (unlikely(!fault->slot))
|
||||
new_spte = make_mmio_spte(vcpu, iter->gfn, ACC_ALL);
|
||||
else
|
||||
@@ -1173,9 +1175,6 @@ int kvm_tdp_mmu_map(struct kvm_vcpu *vcpu, struct kvm_page_fault *fault)
|
||||
if (fault->nx_huge_page_workaround_enabled)
|
||||
disallowed_hugepage_adjust(fault, iter.old_spte, iter.level);
|
||||
|
||||
if (iter.level == fault->goal_level)
|
||||
break;
|
||||
|
||||
/*
|
||||
* If SPTE has been frozen by another thread, just give up and
|
||||
* retry, avoiding unnecessary page table allocation and free.
|
||||
@@ -1183,6 +1182,9 @@ int kvm_tdp_mmu_map(struct kvm_vcpu *vcpu, struct kvm_page_fault *fault)
|
||||
if (is_removed_spte(iter.old_spte))
|
||||
goto retry;
|
||||
|
||||
if (iter.level == fault->goal_level)
|
||||
goto map_target_level;
|
||||
|
||||
/* Step down into the lower level page table if it exists. */
|
||||
if (is_shadow_present_pte(iter.old_spte) &&
|
||||
!is_large_pte(iter.old_spte))
|
||||
@@ -1203,8 +1205,8 @@ int kvm_tdp_mmu_map(struct kvm_vcpu *vcpu, struct kvm_page_fault *fault)
|
||||
r = tdp_mmu_link_sp(kvm, &iter, sp, true);
|
||||
|
||||
/*
|
||||
* Also force the guest to retry the access if the upper level SPTEs
|
||||
* aren't in place.
|
||||
* Force the guest to retry if installing an upper level SPTE
|
||||
* failed, e.g. because a different task modified the SPTE.
|
||||
*/
|
||||
if (r) {
|
||||
tdp_mmu_free_sp(sp);
|
||||
@@ -1214,11 +1216,20 @@ int kvm_tdp_mmu_map(struct kvm_vcpu *vcpu, struct kvm_page_fault *fault)
|
||||
if (fault->huge_page_disallowed &&
|
||||
fault->req_level >= iter.level) {
|
||||
spin_lock(&kvm->arch.tdp_mmu_pages_lock);
|
||||
track_possible_nx_huge_page(kvm, sp);
|
||||
if (sp->nx_huge_page_disallowed)
|
||||
track_possible_nx_huge_page(kvm, sp);
|
||||
spin_unlock(&kvm->arch.tdp_mmu_pages_lock);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* The walk aborted before reaching the target level, e.g. because the
|
||||
* iterator detected an upper level SPTE was frozen during traversal.
|
||||
*/
|
||||
WARN_ON_ONCE(iter.level == fault->goal_level);
|
||||
goto retry;
|
||||
|
||||
map_target_level:
|
||||
ret = tdp_mmu_map_handle_target_level(vcpu, fault, &iter);
|
||||
|
||||
retry:
|
||||
|
||||
@@ -238,7 +238,8 @@ static bool pmc_resume_counter(struct kvm_pmc *pmc)
|
||||
return false;
|
||||
|
||||
/* recalibrate sample period and check if it's accepted by perf core */
|
||||
if (perf_event_period(pmc->perf_event,
|
||||
if (is_sampling_event(pmc->perf_event) &&
|
||||
perf_event_period(pmc->perf_event,
|
||||
get_sample_period(pmc, pmc->counter)))
|
||||
return false;
|
||||
|
||||
|
||||
@@ -140,7 +140,8 @@ static inline u64 get_sample_period(struct kvm_pmc *pmc, u64 counter_value)
|
||||
|
||||
static inline void pmc_update_sample_period(struct kvm_pmc *pmc)
|
||||
{
|
||||
if (!pmc->perf_event || pmc->is_paused)
|
||||
if (!pmc->perf_event || pmc->is_paused ||
|
||||
!is_sampling_event(pmc->perf_event))
|
||||
return;
|
||||
|
||||
perf_event_period(pmc->perf_event,
|
||||
|
||||
@@ -5296,10 +5296,19 @@ static int handle_vmclear(struct kvm_vcpu *vcpu)
|
||||
if (vmptr == vmx->nested.current_vmptr)
|
||||
nested_release_vmcs12(vcpu);
|
||||
|
||||
kvm_vcpu_write_guest(vcpu,
|
||||
vmptr + offsetof(struct vmcs12,
|
||||
launch_state),
|
||||
&zero, sizeof(zero));
|
||||
/*
|
||||
* Silently ignore memory errors on VMCLEAR, Intel's pseudocode
|
||||
* for VMCLEAR includes a "ensure that data for VMCS referenced
|
||||
* by the operand is in memory" clause that guards writes to
|
||||
* memory, i.e. doing nothing for I/O is architecturally valid.
|
||||
*
|
||||
* FIXME: Suppress failures if and only if no memslot is found,
|
||||
* i.e. exit to userspace if __copy_to_user() fails.
|
||||
*/
|
||||
(void)kvm_vcpu_write_guest(vcpu,
|
||||
vmptr + offsetof(struct vmcs12,
|
||||
launch_state),
|
||||
&zero, sizeof(zero));
|
||||
} else if (vmx->nested.hv_evmcs && vmptr == vmx->nested.hv_evmcs_vmptr) {
|
||||
nested_release_evmcs(vcpu);
|
||||
}
|
||||
@@ -6873,7 +6882,8 @@ void nested_vmx_setup_ctls_msrs(struct vmcs_config *vmcs_conf, u32 ept_caps)
|
||||
SECONDARY_EXEC_ENABLE_INVPCID |
|
||||
SECONDARY_EXEC_RDSEED_EXITING |
|
||||
SECONDARY_EXEC_XSAVES |
|
||||
SECONDARY_EXEC_TSC_SCALING;
|
||||
SECONDARY_EXEC_TSC_SCALING |
|
||||
SECONDARY_EXEC_ENABLE_USR_WAIT_PAUSE;
|
||||
|
||||
/*
|
||||
* We can emulate "VMCS shadowing," even if the hardware
|
||||
|
||||
@@ -4459,6 +4459,13 @@ vmx_adjust_secondary_exec_control(struct vcpu_vmx *vmx, u32 *exec_control,
|
||||
* controls for features that are/aren't exposed to the guest.
|
||||
*/
|
||||
if (nested) {
|
||||
/*
|
||||
* All features that can be added or removed to VMX MSRs must
|
||||
* be supported in the first place for nested virtualization.
|
||||
*/
|
||||
if (WARN_ON_ONCE(!(vmcs_config.nested.secondary_ctls_high & control)))
|
||||
enabled = false;
|
||||
|
||||
if (enabled)
|
||||
vmx->nested.msrs.secondary_ctls_high |= control;
|
||||
else
|
||||
|
||||
@@ -13132,6 +13132,9 @@ int kvm_handle_memory_failure(struct kvm_vcpu *vcpu, int r,
|
||||
struct x86_exception *e)
|
||||
{
|
||||
if (r == X86EMUL_PROPAGATE_FAULT) {
|
||||
if (KVM_BUG_ON(!e, vcpu->kvm))
|
||||
return -EIO;
|
||||
|
||||
kvm_inject_emulated_page_fault(vcpu, e);
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -41,7 +41,7 @@ static int kvm_xen_shared_info_init(struct kvm *kvm, gfn_t gfn)
|
||||
int ret = 0;
|
||||
int idx = srcu_read_lock(&kvm->srcu);
|
||||
|
||||
if (gfn == GPA_INVALID) {
|
||||
if (gfn == KVM_XEN_INVALID_GFN) {
|
||||
kvm_gpc_deactivate(gpc);
|
||||
goto out;
|
||||
}
|
||||
@@ -659,7 +659,7 @@ int kvm_xen_hvm_get_attr(struct kvm *kvm, struct kvm_xen_hvm_attr *data)
|
||||
if (kvm->arch.xen.shinfo_cache.active)
|
||||
data->u.shared_info.gfn = gpa_to_gfn(kvm->arch.xen.shinfo_cache.gpa);
|
||||
else
|
||||
data->u.shared_info.gfn = GPA_INVALID;
|
||||
data->u.shared_info.gfn = KVM_XEN_INVALID_GFN;
|
||||
r = 0;
|
||||
break;
|
||||
|
||||
@@ -705,7 +705,7 @@ int kvm_xen_vcpu_set_attr(struct kvm_vcpu *vcpu, struct kvm_xen_vcpu_attr *data)
|
||||
BUILD_BUG_ON(offsetof(struct vcpu_info, time) !=
|
||||
offsetof(struct compat_vcpu_info, time));
|
||||
|
||||
if (data->u.gpa == GPA_INVALID) {
|
||||
if (data->u.gpa == KVM_XEN_INVALID_GPA) {
|
||||
kvm_gpc_deactivate(&vcpu->arch.xen.vcpu_info_cache);
|
||||
r = 0;
|
||||
break;
|
||||
@@ -719,7 +719,7 @@ int kvm_xen_vcpu_set_attr(struct kvm_vcpu *vcpu, struct kvm_xen_vcpu_attr *data)
|
||||
break;
|
||||
|
||||
case KVM_XEN_VCPU_ATTR_TYPE_VCPU_TIME_INFO:
|
||||
if (data->u.gpa == GPA_INVALID) {
|
||||
if (data->u.gpa == KVM_XEN_INVALID_GPA) {
|
||||
kvm_gpc_deactivate(&vcpu->arch.xen.vcpu_time_info_cache);
|
||||
r = 0;
|
||||
break;
|
||||
@@ -739,7 +739,7 @@ int kvm_xen_vcpu_set_attr(struct kvm_vcpu *vcpu, struct kvm_xen_vcpu_attr *data)
|
||||
r = -EOPNOTSUPP;
|
||||
break;
|
||||
}
|
||||
if (data->u.gpa == GPA_INVALID) {
|
||||
if (data->u.gpa == KVM_XEN_INVALID_GPA) {
|
||||
r = 0;
|
||||
deactivate_out:
|
||||
kvm_gpc_deactivate(&vcpu->arch.xen.runstate_cache);
|
||||
@@ -937,7 +937,7 @@ int kvm_xen_vcpu_get_attr(struct kvm_vcpu *vcpu, struct kvm_xen_vcpu_attr *data)
|
||||
if (vcpu->arch.xen.vcpu_info_cache.active)
|
||||
data->u.gpa = vcpu->arch.xen.vcpu_info_cache.gpa;
|
||||
else
|
||||
data->u.gpa = GPA_INVALID;
|
||||
data->u.gpa = KVM_XEN_INVALID_GPA;
|
||||
r = 0;
|
||||
break;
|
||||
|
||||
@@ -945,7 +945,7 @@ int kvm_xen_vcpu_get_attr(struct kvm_vcpu *vcpu, struct kvm_xen_vcpu_attr *data)
|
||||
if (vcpu->arch.xen.vcpu_time_info_cache.active)
|
||||
data->u.gpa = vcpu->arch.xen.vcpu_time_info_cache.gpa;
|
||||
else
|
||||
data->u.gpa = GPA_INVALID;
|
||||
data->u.gpa = KVM_XEN_INVALID_GPA;
|
||||
r = 0;
|
||||
break;
|
||||
|
||||
@@ -1069,6 +1069,7 @@ int kvm_xen_write_hypercall_page(struct kvm_vcpu *vcpu, u64 data)
|
||||
u8 blob_size = lm ? kvm->arch.xen_hvm_config.blob_size_64
|
||||
: kvm->arch.xen_hvm_config.blob_size_32;
|
||||
u8 *page;
|
||||
int ret;
|
||||
|
||||
if (page_num >= blob_size)
|
||||
return 1;
|
||||
@@ -1079,10 +1080,10 @@ int kvm_xen_write_hypercall_page(struct kvm_vcpu *vcpu, u64 data)
|
||||
if (IS_ERR(page))
|
||||
return PTR_ERR(page);
|
||||
|
||||
if (kvm_vcpu_write_guest(vcpu, page_addr, page, PAGE_SIZE)) {
|
||||
kfree(page);
|
||||
ret = kvm_vcpu_write_guest(vcpu, page_addr, page, PAGE_SIZE);
|
||||
kfree(page);
|
||||
if (ret)
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@@ -1183,30 +1184,22 @@ static bool wait_pending_event(struct kvm_vcpu *vcpu, int nr_ports,
|
||||
static bool kvm_xen_schedop_poll(struct kvm_vcpu *vcpu, bool longmode,
|
||||
u64 param, u64 *r)
|
||||
{
|
||||
int idx, i;
|
||||
struct sched_poll sched_poll;
|
||||
evtchn_port_t port, *ports;
|
||||
gpa_t gpa;
|
||||
struct x86_exception e;
|
||||
int i;
|
||||
|
||||
if (!lapic_in_kernel(vcpu) ||
|
||||
!(vcpu->kvm->arch.xen_hvm_config.flags & KVM_XEN_HVM_CONFIG_EVTCHN_SEND))
|
||||
return false;
|
||||
|
||||
idx = srcu_read_lock(&vcpu->kvm->srcu);
|
||||
gpa = kvm_mmu_gva_to_gpa_system(vcpu, param, NULL);
|
||||
srcu_read_unlock(&vcpu->kvm->srcu, idx);
|
||||
if (!gpa) {
|
||||
*r = -EFAULT;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (IS_ENABLED(CONFIG_64BIT) && !longmode) {
|
||||
struct compat_sched_poll sp32;
|
||||
|
||||
/* Sanity check that the compat struct definition is correct */
|
||||
BUILD_BUG_ON(sizeof(sp32) != 16);
|
||||
|
||||
if (kvm_vcpu_read_guest(vcpu, gpa, &sp32, sizeof(sp32))) {
|
||||
if (kvm_read_guest_virt(vcpu, param, &sp32, sizeof(sp32), &e)) {
|
||||
*r = -EFAULT;
|
||||
return true;
|
||||
}
|
||||
@@ -1220,8 +1213,8 @@ static bool kvm_xen_schedop_poll(struct kvm_vcpu *vcpu, bool longmode,
|
||||
sched_poll.nr_ports = sp32.nr_ports;
|
||||
sched_poll.timeout = sp32.timeout;
|
||||
} else {
|
||||
if (kvm_vcpu_read_guest(vcpu, gpa, &sched_poll,
|
||||
sizeof(sched_poll))) {
|
||||
if (kvm_read_guest_virt(vcpu, param, &sched_poll,
|
||||
sizeof(sched_poll), &e)) {
|
||||
*r = -EFAULT;
|
||||
return true;
|
||||
}
|
||||
@@ -1243,18 +1236,13 @@ static bool kvm_xen_schedop_poll(struct kvm_vcpu *vcpu, bool longmode,
|
||||
} else
|
||||
ports = &port;
|
||||
|
||||
for (i = 0; i < sched_poll.nr_ports; i++) {
|
||||
idx = srcu_read_lock(&vcpu->kvm->srcu);
|
||||
gpa = kvm_mmu_gva_to_gpa_system(vcpu,
|
||||
(gva_t)(sched_poll.ports + i),
|
||||
NULL);
|
||||
srcu_read_unlock(&vcpu->kvm->srcu, idx);
|
||||
if (kvm_read_guest_virt(vcpu, (gva_t)sched_poll.ports, ports,
|
||||
sched_poll.nr_ports * sizeof(*ports), &e)) {
|
||||
*r = -EFAULT;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!gpa || kvm_vcpu_read_guest(vcpu, gpa,
|
||||
&ports[i], sizeof(port))) {
|
||||
*r = -EFAULT;
|
||||
goto out;
|
||||
}
|
||||
for (i = 0; i < sched_poll.nr_ports; i++) {
|
||||
if (ports[i] >= max_evtchn_port(vcpu->kvm)) {
|
||||
*r = -EINVAL;
|
||||
goto out;
|
||||
@@ -1330,9 +1318,8 @@ static bool kvm_xen_hcall_vcpu_op(struct kvm_vcpu *vcpu, bool longmode, int cmd,
|
||||
int vcpu_id, u64 param, u64 *r)
|
||||
{
|
||||
struct vcpu_set_singleshot_timer oneshot;
|
||||
struct x86_exception e;
|
||||
s64 delta;
|
||||
gpa_t gpa;
|
||||
int idx;
|
||||
|
||||
if (!kvm_xen_timer_enabled(vcpu))
|
||||
return false;
|
||||
@@ -1343,9 +1330,6 @@ static bool kvm_xen_hcall_vcpu_op(struct kvm_vcpu *vcpu, bool longmode, int cmd,
|
||||
*r = -EINVAL;
|
||||
return true;
|
||||
}
|
||||
idx = srcu_read_lock(&vcpu->kvm->srcu);
|
||||
gpa = kvm_mmu_gva_to_gpa_system(vcpu, param, NULL);
|
||||
srcu_read_unlock(&vcpu->kvm->srcu, idx);
|
||||
|
||||
/*
|
||||
* The only difference for 32-bit compat is the 4 bytes of
|
||||
@@ -1363,9 +1347,8 @@ static bool kvm_xen_hcall_vcpu_op(struct kvm_vcpu *vcpu, bool longmode, int cmd,
|
||||
BUILD_BUG_ON(sizeof_field(struct compat_vcpu_set_singleshot_timer, flags) !=
|
||||
sizeof_field(struct vcpu_set_singleshot_timer, flags));
|
||||
|
||||
if (!gpa ||
|
||||
kvm_vcpu_read_guest(vcpu, gpa, &oneshot, longmode ? sizeof(oneshot) :
|
||||
sizeof(struct compat_vcpu_set_singleshot_timer))) {
|
||||
if (kvm_read_guest_virt(vcpu, param, &oneshot, longmode ? sizeof(oneshot) :
|
||||
sizeof(struct compat_vcpu_set_singleshot_timer), &e)) {
|
||||
*r = -EFAULT;
|
||||
return true;
|
||||
}
|
||||
@@ -1825,20 +1808,20 @@ static int kvm_xen_eventfd_update(struct kvm *kvm,
|
||||
{
|
||||
u32 port = data->u.evtchn.send_port;
|
||||
struct evtchnfd *evtchnfd;
|
||||
int ret;
|
||||
|
||||
if (!port || port >= max_evtchn_port(kvm))
|
||||
return -EINVAL;
|
||||
|
||||
/* Protect writes to evtchnfd as well as the idr lookup. */
|
||||
mutex_lock(&kvm->lock);
|
||||
evtchnfd = idr_find(&kvm->arch.xen.evtchn_ports, port);
|
||||
mutex_unlock(&kvm->lock);
|
||||
|
||||
ret = -ENOENT;
|
||||
if (!evtchnfd)
|
||||
return -ENOENT;
|
||||
goto out_unlock;
|
||||
|
||||
/* For an UPDATE, nothing may change except the priority/vcpu */
|
||||
ret = -EINVAL;
|
||||
if (evtchnfd->type != data->u.evtchn.type)
|
||||
return -EINVAL;
|
||||
goto out_unlock;
|
||||
|
||||
/*
|
||||
* Port cannot change, and if it's zero that was an eventfd
|
||||
@@ -1846,20 +1829,21 @@ static int kvm_xen_eventfd_update(struct kvm *kvm,
|
||||
*/
|
||||
if (!evtchnfd->deliver.port.port ||
|
||||
evtchnfd->deliver.port.port != data->u.evtchn.deliver.port.port)
|
||||
return -EINVAL;
|
||||
goto out_unlock;
|
||||
|
||||
/* We only support 2 level event channels for now */
|
||||
if (data->u.evtchn.deliver.port.priority != KVM_IRQ_ROUTING_XEN_EVTCHN_PRIO_2LEVEL)
|
||||
return -EINVAL;
|
||||
goto out_unlock;
|
||||
|
||||
mutex_lock(&kvm->lock);
|
||||
evtchnfd->deliver.port.priority = data->u.evtchn.deliver.port.priority;
|
||||
if (evtchnfd->deliver.port.vcpu_id != data->u.evtchn.deliver.port.vcpu) {
|
||||
evtchnfd->deliver.port.vcpu_id = data->u.evtchn.deliver.port.vcpu;
|
||||
evtchnfd->deliver.port.vcpu_idx = -1;
|
||||
}
|
||||
ret = 0;
|
||||
out_unlock:
|
||||
mutex_unlock(&kvm->lock);
|
||||
return 0;
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1871,12 +1855,9 @@ static int kvm_xen_eventfd_assign(struct kvm *kvm,
|
||||
{
|
||||
u32 port = data->u.evtchn.send_port;
|
||||
struct eventfd_ctx *eventfd = NULL;
|
||||
struct evtchnfd *evtchnfd = NULL;
|
||||
struct evtchnfd *evtchnfd;
|
||||
int ret = -EINVAL;
|
||||
|
||||
if (!port || port >= max_evtchn_port(kvm))
|
||||
return -EINVAL;
|
||||
|
||||
evtchnfd = kzalloc(sizeof(struct evtchnfd), GFP_KERNEL);
|
||||
if (!evtchnfd)
|
||||
return -ENOMEM;
|
||||
@@ -1952,8 +1933,7 @@ static int kvm_xen_eventfd_deassign(struct kvm *kvm, u32 port)
|
||||
if (!evtchnfd)
|
||||
return -ENOENT;
|
||||
|
||||
if (kvm)
|
||||
synchronize_srcu(&kvm->srcu);
|
||||
synchronize_srcu(&kvm->srcu);
|
||||
if (!evtchnfd->deliver.port.port)
|
||||
eventfd_ctx_put(evtchnfd->deliver.eventfd.ctx);
|
||||
kfree(evtchnfd);
|
||||
@@ -1962,18 +1942,42 @@ static int kvm_xen_eventfd_deassign(struct kvm *kvm, u32 port)
|
||||
|
||||
static int kvm_xen_eventfd_reset(struct kvm *kvm)
|
||||
{
|
||||
struct evtchnfd *evtchnfd;
|
||||
struct evtchnfd *evtchnfd, **all_evtchnfds;
|
||||
int i;
|
||||
int n = 0;
|
||||
|
||||
mutex_lock(&kvm->lock);
|
||||
|
||||
/*
|
||||
* Because synchronize_srcu() cannot be called inside the
|
||||
* critical section, first collect all the evtchnfd objects
|
||||
* in an array as they are removed from evtchn_ports.
|
||||
*/
|
||||
idr_for_each_entry(&kvm->arch.xen.evtchn_ports, evtchnfd, i)
|
||||
n++;
|
||||
|
||||
all_evtchnfds = kmalloc_array(n, sizeof(struct evtchnfd *), GFP_KERNEL);
|
||||
if (!all_evtchnfds) {
|
||||
mutex_unlock(&kvm->lock);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
n = 0;
|
||||
idr_for_each_entry(&kvm->arch.xen.evtchn_ports, evtchnfd, i) {
|
||||
all_evtchnfds[n++] = evtchnfd;
|
||||
idr_remove(&kvm->arch.xen.evtchn_ports, evtchnfd->send_port);
|
||||
synchronize_srcu(&kvm->srcu);
|
||||
}
|
||||
mutex_unlock(&kvm->lock);
|
||||
|
||||
synchronize_srcu(&kvm->srcu);
|
||||
|
||||
while (n--) {
|
||||
evtchnfd = all_evtchnfds[n];
|
||||
if (!evtchnfd->deliver.port.port)
|
||||
eventfd_ctx_put(evtchnfd->deliver.eventfd.ctx);
|
||||
kfree(evtchnfd);
|
||||
}
|
||||
mutex_unlock(&kvm->lock);
|
||||
kfree(all_evtchnfds);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -2002,20 +2006,22 @@ static bool kvm_xen_hcall_evtchn_send(struct kvm_vcpu *vcpu, u64 param, u64 *r)
|
||||
{
|
||||
struct evtchnfd *evtchnfd;
|
||||
struct evtchn_send send;
|
||||
gpa_t gpa;
|
||||
int idx;
|
||||
struct x86_exception e;
|
||||
|
||||
idx = srcu_read_lock(&vcpu->kvm->srcu);
|
||||
gpa = kvm_mmu_gva_to_gpa_system(vcpu, param, NULL);
|
||||
srcu_read_unlock(&vcpu->kvm->srcu, idx);
|
||||
|
||||
if (!gpa || kvm_vcpu_read_guest(vcpu, gpa, &send, sizeof(send))) {
|
||||
/* Sanity check: this structure is the same for 32-bit and 64-bit */
|
||||
BUILD_BUG_ON(sizeof(send) != 4);
|
||||
if (kvm_read_guest_virt(vcpu, param, &send, sizeof(send), &e)) {
|
||||
*r = -EFAULT;
|
||||
return true;
|
||||
}
|
||||
|
||||
/* The evtchn_ports idr is protected by vcpu->kvm->srcu */
|
||||
/*
|
||||
* evtchnfd is protected by kvm->srcu; the idr lookup instead
|
||||
* is protected by RCU.
|
||||
*/
|
||||
rcu_read_lock();
|
||||
evtchnfd = idr_find(&vcpu->kvm->arch.xen.evtchn_ports, send.port);
|
||||
rcu_read_unlock();
|
||||
if (!evtchnfd)
|
||||
return false;
|
||||
|
||||
|
||||
@@ -5317,8 +5317,8 @@ static void bfq_exit_icq_bfqq(struct bfq_io_cq *bic, bool is_sync)
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&bfqd->lock, flags);
|
||||
bfq_exit_bfqq(bfqd, bfqq);
|
||||
bic_set_bfqq(bic, NULL, is_sync);
|
||||
bfq_exit_bfqq(bfqd, bfqq);
|
||||
spin_unlock_irqrestore(&bfqd->lock, flags);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -70,11 +70,7 @@ module_param(device_id_scheme, bool, 0444);
|
||||
static int only_lcd = -1;
|
||||
module_param(only_lcd, int, 0444);
|
||||
|
||||
/*
|
||||
* Display probing is known to take up to 5 seconds, so delay the fallback
|
||||
* backlight registration by 5 seconds + 3 seconds for some extra margin.
|
||||
*/
|
||||
static int register_backlight_delay = 8;
|
||||
static int register_backlight_delay;
|
||||
module_param(register_backlight_delay, int, 0444);
|
||||
MODULE_PARM_DESC(register_backlight_delay,
|
||||
"Delay in seconds before doing fallback (non GPU driver triggered) "
|
||||
@@ -2176,6 +2172,17 @@ static bool should_check_lcd_flag(void)
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* At least one graphics driver has reported that no LCD is connected
|
||||
* via the native interface. cancel the registration for fallback acpi_video0.
|
||||
* If another driver still deems this necessary, it can explicitly register it.
|
||||
*/
|
||||
void acpi_video_report_nolcd(void)
|
||||
{
|
||||
cancel_delayed_work(&video_bus_register_backlight_work);
|
||||
}
|
||||
EXPORT_SYMBOL(acpi_video_report_nolcd);
|
||||
|
||||
int acpi_video_register(void)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
@@ -432,10 +432,24 @@ static const struct dmi_system_id asus_laptop[] = {
|
||||
DMI_MATCH(DMI_BOARD_NAME, "S5602ZA"),
|
||||
},
|
||||
},
|
||||
{
|
||||
.ident = "Asus ExpertBook B2502",
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
|
||||
DMI_MATCH(DMI_BOARD_NAME, "B2502CBA"),
|
||||
},
|
||||
},
|
||||
{ }
|
||||
};
|
||||
|
||||
static const struct dmi_system_id lenovo_82ra[] = {
|
||||
static const struct dmi_system_id lenovo_laptop[] = {
|
||||
{
|
||||
.ident = "LENOVO IdeaPad Flex 5 14ALC7",
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "82R9"),
|
||||
},
|
||||
},
|
||||
{
|
||||
.ident = "LENOVO IdeaPad Flex 5 16ALC7",
|
||||
.matches = {
|
||||
@@ -446,6 +460,17 @@ static const struct dmi_system_id lenovo_82ra[] = {
|
||||
{ }
|
||||
};
|
||||
|
||||
static const struct dmi_system_id schenker_gm_rg[] = {
|
||||
{
|
||||
.ident = "XMG CORE 15 (M22)",
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "SchenkerTechnologiesGmbH"),
|
||||
DMI_MATCH(DMI_BOARD_NAME, "GMxRGxx"),
|
||||
},
|
||||
},
|
||||
{ }
|
||||
};
|
||||
|
||||
struct irq_override_cmp {
|
||||
const struct dmi_system_id *system;
|
||||
unsigned char irq;
|
||||
@@ -458,8 +483,9 @@ struct irq_override_cmp {
|
||||
static const struct irq_override_cmp override_table[] = {
|
||||
{ medion_laptop, 1, ACPI_LEVEL_SENSITIVE, ACPI_ACTIVE_LOW, 0, false },
|
||||
{ asus_laptop, 1, ACPI_LEVEL_SENSITIVE, ACPI_ACTIVE_LOW, 0, false },
|
||||
{ lenovo_82ra, 6, ACPI_LEVEL_SENSITIVE, ACPI_ACTIVE_LOW, 0, true },
|
||||
{ lenovo_82ra, 10, ACPI_LEVEL_SENSITIVE, ACPI_ACTIVE_LOW, 0, true },
|
||||
{ lenovo_laptop, 6, ACPI_LEVEL_SENSITIVE, ACPI_ACTIVE_LOW, 0, true },
|
||||
{ lenovo_laptop, 10, ACPI_LEVEL_SENSITIVE, ACPI_ACTIVE_LOW, 0, true },
|
||||
{ schenker_gm_rg, 1, ACPI_EDGE_SENSITIVE, ACPI_ACTIVE_LOW, 1, true },
|
||||
};
|
||||
|
||||
static bool acpi_dev_irq_override(u32 gsi, u8 triggering, u8 polarity,
|
||||
|
||||
@@ -34,6 +34,7 @@
|
||||
#include <linux/module.h>
|
||||
#include <linux/pci.h>
|
||||
#include <linux/platform_data/x86/nvidia-wmi-ec-backlight.h>
|
||||
#include <linux/pnp.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/workqueue.h>
|
||||
#include <acpi/video.h>
|
||||
@@ -105,6 +106,26 @@ static bool nvidia_wmi_ec_supported(void)
|
||||
}
|
||||
#endif
|
||||
|
||||
static bool apple_gmux_backlight_present(void)
|
||||
{
|
||||
struct acpi_device *adev;
|
||||
struct device *dev;
|
||||
|
||||
adev = acpi_dev_get_first_match_dev(GMUX_ACPI_HID, NULL, -1);
|
||||
if (!adev)
|
||||
return false;
|
||||
|
||||
dev = acpi_get_first_physical_node(adev);
|
||||
if (!dev)
|
||||
return false;
|
||||
|
||||
/*
|
||||
* drivers/platform/x86/apple-gmux.c only supports old style
|
||||
* Apple GMUX with an IO-resource.
|
||||
*/
|
||||
return pnp_get_resource(to_pnp_dev(dev), IORESOURCE_IO, 0) != NULL;
|
||||
}
|
||||
|
||||
/* Force to use vendor driver when the ACPI device is known to be
|
||||
* buggy */
|
||||
static int video_detect_force_vendor(const struct dmi_system_id *d)
|
||||
@@ -767,7 +788,7 @@ static enum acpi_backlight_type __acpi_video_get_backlight_type(bool native)
|
||||
if (nvidia_wmi_ec_present)
|
||||
return acpi_backlight_nvidia_wmi_ec;
|
||||
|
||||
if (apple_gmux_present())
|
||||
if (apple_gmux_backlight_present())
|
||||
return acpi_backlight_apple_gmux;
|
||||
|
||||
/* Use ACPI video if available, except when native should be preferred. */
|
||||
|
||||
@@ -28,10 +28,6 @@ static bool sleep_no_lps0 __read_mostly;
|
||||
module_param(sleep_no_lps0, bool, 0644);
|
||||
MODULE_PARM_DESC(sleep_no_lps0, "Do not use the special LPS0 device interface");
|
||||
|
||||
static bool prefer_microsoft_dsm_guid __read_mostly;
|
||||
module_param(prefer_microsoft_dsm_guid, bool, 0644);
|
||||
MODULE_PARM_DESC(prefer_microsoft_dsm_guid, "Prefer using Microsoft GUID in LPS0 device _DSM evaluation");
|
||||
|
||||
static const struct acpi_device_id lps0_device_ids[] = {
|
||||
{"PNP0D80", },
|
||||
{"", },
|
||||
@@ -369,27 +365,15 @@ static int validate_dsm(acpi_handle handle, const char *uuid, int rev, guid_t *d
|
||||
}
|
||||
|
||||
struct amd_lps0_hid_device_data {
|
||||
const unsigned int rev_id;
|
||||
const bool check_off_by_one;
|
||||
const bool prefer_amd_guid;
|
||||
};
|
||||
|
||||
static const struct amd_lps0_hid_device_data amd_picasso = {
|
||||
.rev_id = 0,
|
||||
.check_off_by_one = true,
|
||||
.prefer_amd_guid = false,
|
||||
};
|
||||
|
||||
static const struct amd_lps0_hid_device_data amd_cezanne = {
|
||||
.rev_id = 0,
|
||||
.check_off_by_one = false,
|
||||
.prefer_amd_guid = false,
|
||||
};
|
||||
|
||||
static const struct amd_lps0_hid_device_data amd_rembrandt = {
|
||||
.rev_id = 2,
|
||||
.check_off_by_one = false,
|
||||
.prefer_amd_guid = true,
|
||||
};
|
||||
|
||||
static const struct acpi_device_id amd_hid_ids[] = {
|
||||
@@ -397,69 +381,27 @@ static const struct acpi_device_id amd_hid_ids[] = {
|
||||
{"AMD0005", (kernel_ulong_t)&amd_picasso, },
|
||||
{"AMDI0005", (kernel_ulong_t)&amd_picasso, },
|
||||
{"AMDI0006", (kernel_ulong_t)&amd_cezanne, },
|
||||
{"AMDI0007", (kernel_ulong_t)&amd_rembrandt, },
|
||||
{}
|
||||
};
|
||||
|
||||
static int lps0_prefer_microsoft(const struct dmi_system_id *id)
|
||||
static int lps0_prefer_amd(const struct dmi_system_id *id)
|
||||
{
|
||||
pr_debug("Preferring Microsoft GUID.\n");
|
||||
prefer_microsoft_dsm_guid = true;
|
||||
pr_debug("Using AMD GUID w/ _REV 2.\n");
|
||||
rev_id = 2;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct dmi_system_id s2idle_dmi_table[] __initconst = {
|
||||
{
|
||||
/*
|
||||
* ASUS TUF Gaming A17 FA707RE
|
||||
* https://bugzilla.kernel.org/show_bug.cgi?id=216101
|
||||
* AMD Rembrandt based HP EliteBook 835/845/865 G9
|
||||
* Contains specialized AML in AMD/_REV 2 path to avoid
|
||||
* triggering a bug in Qualcomm WLAN firmware. This may be
|
||||
* removed in the future if that firmware is fixed.
|
||||
*/
|
||||
.callback = lps0_prefer_microsoft,
|
||||
.callback = lps0_prefer_amd,
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "ASUS TUF Gaming A17"),
|
||||
},
|
||||
},
|
||||
{
|
||||
/* ASUS ROG Zephyrus G14 (2022) */
|
||||
.callback = lps0_prefer_microsoft,
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "ROG Zephyrus G14 GA402"),
|
||||
},
|
||||
},
|
||||
{
|
||||
/*
|
||||
* Lenovo Yoga Slim 7 Pro X 14ARH7
|
||||
* https://bugzilla.kernel.org/show_bug.cgi?id=216473 : 82V2
|
||||
* https://bugzilla.kernel.org/show_bug.cgi?id=216438 : 82TL
|
||||
*/
|
||||
.callback = lps0_prefer_microsoft,
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"),
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "82"),
|
||||
},
|
||||
},
|
||||
{
|
||||
/*
|
||||
* ASUSTeK COMPUTER INC. ROG Flow X13 GV301RE_GV301RE
|
||||
* https://gitlab.freedesktop.org/drm/amd/-/issues/2148
|
||||
*/
|
||||
.callback = lps0_prefer_microsoft,
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "ROG Flow X13 GV301"),
|
||||
},
|
||||
},
|
||||
{
|
||||
/*
|
||||
* ASUSTeK COMPUTER INC. ROG Flow X16 GV601RW_GV601RW
|
||||
* https://gitlab.freedesktop.org/drm/amd/-/issues/2148
|
||||
*/
|
||||
.callback = lps0_prefer_microsoft,
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "ROG Flow X16 GV601"),
|
||||
DMI_MATCH(DMI_BOARD_VENDOR, "HP"),
|
||||
DMI_MATCH(DMI_BOARD_NAME, "8990"),
|
||||
},
|
||||
},
|
||||
{}
|
||||
@@ -484,16 +426,14 @@ static int lps0_device_attach(struct acpi_device *adev,
|
||||
if (dev_id->id[0])
|
||||
data = (const struct amd_lps0_hid_device_data *) dev_id->driver_data;
|
||||
else
|
||||
data = &amd_rembrandt;
|
||||
rev_id = data->rev_id;
|
||||
data = &amd_cezanne;
|
||||
lps0_dsm_func_mask = validate_dsm(adev->handle,
|
||||
ACPI_LPS0_DSM_UUID_AMD, rev_id, &lps0_dsm_guid);
|
||||
if (lps0_dsm_func_mask > 0x3 && data->check_off_by_one) {
|
||||
lps0_dsm_func_mask = (lps0_dsm_func_mask << 1) | 0x1;
|
||||
acpi_handle_debug(adev->handle, "_DSM UUID %s: Adjusted function mask: 0x%x\n",
|
||||
ACPI_LPS0_DSM_UUID_AMD, lps0_dsm_func_mask);
|
||||
} else if (lps0_dsm_func_mask_microsoft > 0 && data->prefer_amd_guid &&
|
||||
!prefer_microsoft_dsm_guid) {
|
||||
} else if (lps0_dsm_func_mask_microsoft > 0 && rev_id) {
|
||||
lps0_dsm_func_mask_microsoft = -EINVAL;
|
||||
acpi_handle_debug(adev->handle, "_DSM Using AMD method\n");
|
||||
}
|
||||
@@ -501,8 +441,7 @@ static int lps0_device_attach(struct acpi_device *adev,
|
||||
rev_id = 1;
|
||||
lps0_dsm_func_mask = validate_dsm(adev->handle,
|
||||
ACPI_LPS0_DSM_UUID, rev_id, &lps0_dsm_guid);
|
||||
if (!prefer_microsoft_dsm_guid)
|
||||
lps0_dsm_func_mask_microsoft = -EINVAL;
|
||||
lps0_dsm_func_mask_microsoft = -EINVAL;
|
||||
}
|
||||
|
||||
if (lps0_dsm_func_mask < 0 && lps0_dsm_func_mask_microsoft < 0)
|
||||
|
||||
@@ -83,6 +83,7 @@ enum board_ids {
|
||||
static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent);
|
||||
static void ahci_remove_one(struct pci_dev *dev);
|
||||
static void ahci_shutdown_one(struct pci_dev *dev);
|
||||
static void ahci_intel_pcs_quirk(struct pci_dev *pdev, struct ahci_host_priv *hpriv);
|
||||
static int ahci_vt8251_hardreset(struct ata_link *link, unsigned int *class,
|
||||
unsigned long deadline);
|
||||
static int ahci_avn_hardreset(struct ata_link *link, unsigned int *class,
|
||||
@@ -676,6 +677,25 @@ static void ahci_pci_save_initial_config(struct pci_dev *pdev,
|
||||
ahci_save_initial_config(&pdev->dev, hpriv);
|
||||
}
|
||||
|
||||
static int ahci_pci_reset_controller(struct ata_host *host)
|
||||
{
|
||||
struct pci_dev *pdev = to_pci_dev(host->dev);
|
||||
struct ahci_host_priv *hpriv = host->private_data;
|
||||
int rc;
|
||||
|
||||
rc = ahci_reset_controller(host);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
/*
|
||||
* If platform firmware failed to enable ports, try to enable
|
||||
* them here.
|
||||
*/
|
||||
ahci_intel_pcs_quirk(pdev, hpriv);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void ahci_pci_init_controller(struct ata_host *host)
|
||||
{
|
||||
struct ahci_host_priv *hpriv = host->private_data;
|
||||
@@ -870,7 +890,7 @@ static int ahci_pci_device_runtime_resume(struct device *dev)
|
||||
struct ata_host *host = pci_get_drvdata(pdev);
|
||||
int rc;
|
||||
|
||||
rc = ahci_reset_controller(host);
|
||||
rc = ahci_pci_reset_controller(host);
|
||||
if (rc)
|
||||
return rc;
|
||||
ahci_pci_init_controller(host);
|
||||
@@ -906,7 +926,7 @@ static int ahci_pci_device_resume(struct device *dev)
|
||||
ahci_mcp89_apple_enable(pdev);
|
||||
|
||||
if (pdev->dev.power.power_state.event == PM_EVENT_SUSPEND) {
|
||||
rc = ahci_reset_controller(host);
|
||||
rc = ahci_pci_reset_controller(host);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
@@ -1784,12 +1804,6 @@ static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
|
||||
/* save initial config */
|
||||
ahci_pci_save_initial_config(pdev, hpriv);
|
||||
|
||||
/*
|
||||
* If platform firmware failed to enable ports, try to enable
|
||||
* them here.
|
||||
*/
|
||||
ahci_intel_pcs_quirk(pdev, hpriv);
|
||||
|
||||
/* prepare host */
|
||||
if (hpriv->cap & HOST_CAP_NCQ) {
|
||||
pi.flags |= ATA_FLAG_NCQ;
|
||||
@@ -1899,7 +1913,7 @@ static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
rc = ahci_reset_controller(host);
|
||||
rc = ahci_pci_reset_controller(host);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
|
||||
@@ -1263,7 +1263,7 @@ EXPORT_SYMBOL_NS_GPL(dma_buf_unmap_attachment_unlocked, DMA_BUF);
|
||||
*
|
||||
* @dmabuf: [in] buffer which is moving
|
||||
*
|
||||
* Informs all attachmenst that they need to destroy and recreated all their
|
||||
* Informs all attachments that they need to destroy and recreate all their
|
||||
* mappings.
|
||||
*/
|
||||
void dma_buf_move_notify(struct dma_buf *dmabuf)
|
||||
@@ -1281,11 +1281,11 @@ EXPORT_SYMBOL_NS_GPL(dma_buf_move_notify, DMA_BUF);
|
||||
/**
|
||||
* DOC: cpu access
|
||||
*
|
||||
* There are mutliple reasons for supporting CPU access to a dma buffer object:
|
||||
* There are multiple reasons for supporting CPU access to a dma buffer object:
|
||||
*
|
||||
* - Fallback operations in the kernel, for example when a device is connected
|
||||
* over USB and the kernel needs to shuffle the data around first before
|
||||
* sending it away. Cache coherency is handled by braketing any transactions
|
||||
* sending it away. Cache coherency is handled by bracketing any transactions
|
||||
* with calls to dma_buf_begin_cpu_access() and dma_buf_end_cpu_access()
|
||||
* access.
|
||||
*
|
||||
@@ -1312,7 +1312,7 @@ EXPORT_SYMBOL_NS_GPL(dma_buf_move_notify, DMA_BUF);
|
||||
* replace ION buffers mmap support was needed.
|
||||
*
|
||||
* There is no special interfaces, userspace simply calls mmap on the dma-buf
|
||||
* fd. But like for CPU access there's a need to braket the actual access,
|
||||
* fd. But like for CPU access there's a need to bracket the actual access,
|
||||
* which is handled by the ioctl (DMA_BUF_IOCTL_SYNC). Note that
|
||||
* DMA_BUF_IOCTL_SYNC can fail with -EAGAIN or -EINTR, in which case it must
|
||||
* be restarted.
|
||||
@@ -1386,10 +1386,10 @@ static int __dma_buf_begin_cpu_access(struct dma_buf *dmabuf,
|
||||
* preparations. Coherency is only guaranteed in the specified range for the
|
||||
* specified access direction.
|
||||
* @dmabuf: [in] buffer to prepare cpu access for.
|
||||
* @direction: [in] length of range for cpu access.
|
||||
* @direction: [in] direction of access.
|
||||
*
|
||||
* After the cpu access is complete the caller should call
|
||||
* dma_buf_end_cpu_access(). Only when cpu access is braketed by both calls is
|
||||
* dma_buf_end_cpu_access(). Only when cpu access is bracketed by both calls is
|
||||
* it guaranteed to be coherent with other DMA access.
|
||||
*
|
||||
* This function will also wait for any DMA transactions tracked through
|
||||
@@ -1429,7 +1429,7 @@ EXPORT_SYMBOL_NS_GPL(dma_buf_begin_cpu_access, DMA_BUF);
|
||||
* actions. Coherency is only guaranteed in the specified range for the
|
||||
* specified access direction.
|
||||
* @dmabuf: [in] buffer to complete cpu access for.
|
||||
* @direction: [in] length of range for cpu access.
|
||||
* @direction: [in] direction of access.
|
||||
*
|
||||
* This terminates CPU access started with dma_buf_begin_cpu_access().
|
||||
*
|
||||
|
||||
@@ -13,6 +13,8 @@
|
||||
#include <linux/slab.h>
|
||||
#include <linux/udmabuf.h>
|
||||
#include <linux/hugetlb.h>
|
||||
#include <linux/vmalloc.h>
|
||||
#include <linux/iosys-map.h>
|
||||
|
||||
static int list_limit = 1024;
|
||||
module_param(list_limit, int, 0644);
|
||||
@@ -60,6 +62,30 @@ static int mmap_udmabuf(struct dma_buf *buf, struct vm_area_struct *vma)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int vmap_udmabuf(struct dma_buf *buf, struct iosys_map *map)
|
||||
{
|
||||
struct udmabuf *ubuf = buf->priv;
|
||||
void *vaddr;
|
||||
|
||||
dma_resv_assert_held(buf->resv);
|
||||
|
||||
vaddr = vm_map_ram(ubuf->pages, ubuf->pagecount, -1);
|
||||
if (!vaddr)
|
||||
return -EINVAL;
|
||||
|
||||
iosys_map_set_vaddr(map, vaddr);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void vunmap_udmabuf(struct dma_buf *buf, struct iosys_map *map)
|
||||
{
|
||||
struct udmabuf *ubuf = buf->priv;
|
||||
|
||||
dma_resv_assert_held(buf->resv);
|
||||
|
||||
vm_unmap_ram(map->vaddr, ubuf->pagecount);
|
||||
}
|
||||
|
||||
static struct sg_table *get_sg_table(struct device *dev, struct dma_buf *buf,
|
||||
enum dma_data_direction direction)
|
||||
{
|
||||
@@ -162,6 +188,8 @@ static const struct dma_buf_ops udmabuf_ops = {
|
||||
.unmap_dma_buf = unmap_udmabuf,
|
||||
.release = release_udmabuf,
|
||||
.mmap = mmap_udmabuf,
|
||||
.vmap = vmap_udmabuf,
|
||||
.vunmap = vunmap_udmabuf,
|
||||
.begin_cpu_access = begin_cpu_udmabuf,
|
||||
.end_cpu_access = end_cpu_udmabuf,
|
||||
};
|
||||
|
||||
@@ -27,25 +27,56 @@ static const struct simplefb_format formats[] = SIMPLEFB_FORMATS;
|
||||
__init bool sysfb_parse_mode(const struct screen_info *si,
|
||||
struct simplefb_platform_data *mode)
|
||||
{
|
||||
const struct simplefb_format *f;
|
||||
__u8 type;
|
||||
u32 bits_per_pixel;
|
||||
unsigned int i;
|
||||
|
||||
type = si->orig_video_isVGA;
|
||||
if (type != VIDEO_TYPE_VLFB && type != VIDEO_TYPE_EFI)
|
||||
return false;
|
||||
|
||||
/*
|
||||
* The meaning of depth and bpp for direct-color formats is
|
||||
* inconsistent:
|
||||
*
|
||||
* - DRM format info specifies depth as the number of color
|
||||
* bits; including alpha, but not including filler bits.
|
||||
* - Linux' EFI platform code computes lfb_depth from the
|
||||
* individual color channels, including the reserved bits.
|
||||
* - VBE 1.1 defines lfb_depth for XRGB1555 as 16, but later
|
||||
* versions use 15.
|
||||
* - On the kernel command line, 'bpp' of 32 is usually
|
||||
* XRGB8888 including the filler bits, but 15 is XRGB1555
|
||||
* not including the filler bit.
|
||||
*
|
||||
* It's not easily possible to fix this in struct screen_info,
|
||||
* as this could break UAPI. The best solution is to compute
|
||||
* bits_per_pixel here and ignore lfb_depth. In the loop below,
|
||||
* ignore simplefb formats with alpha bits, as EFI and VESA
|
||||
* don't specify alpha channels.
|
||||
*/
|
||||
if (si->lfb_depth > 8) {
|
||||
bits_per_pixel = max(max3(si->red_size + si->red_pos,
|
||||
si->green_size + si->green_pos,
|
||||
si->blue_size + si->blue_pos),
|
||||
si->rsvd_size + si->rsvd_pos);
|
||||
} else {
|
||||
bits_per_pixel = si->lfb_depth;
|
||||
}
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(formats); ++i) {
|
||||
f = &formats[i];
|
||||
if (si->lfb_depth == f->bits_per_pixel &&
|
||||
const struct simplefb_format *f = &formats[i];
|
||||
|
||||
if (f->transp.length)
|
||||
continue; /* transparent formats are unsupported by VESA/EFI */
|
||||
|
||||
if (bits_per_pixel == f->bits_per_pixel &&
|
||||
si->red_size == f->red.length &&
|
||||
si->red_pos == f->red.offset &&
|
||||
si->green_size == f->green.length &&
|
||||
si->green_pos == f->green.offset &&
|
||||
si->blue_size == f->blue.length &&
|
||||
si->blue_pos == f->blue.offset &&
|
||||
si->rsvd_size == f->transp.length &&
|
||||
si->rsvd_pos == f->transp.offset) {
|
||||
si->blue_pos == f->blue.offset) {
|
||||
mode->format = f->name;
|
||||
mode->width = si->lfb_width;
|
||||
mode->height = si->lfb_height;
|
||||
|
||||
@@ -12,7 +12,6 @@ menuconfig DRM
|
||||
select HDMI
|
||||
select FB_CMDLINE
|
||||
select I2C
|
||||
select I2C_ALGOBIT
|
||||
select DMA_SHARED_BUFFER
|
||||
select SYNC_FILE
|
||||
# gallium uses SYS_kcmp for os_same_file_description() to de-duplicate
|
||||
@@ -63,6 +62,12 @@ config DRM_USE_DYNAMIC_DEBUG
|
||||
bytes per callsite, the .data costs can be substantial, and
|
||||
are therefore configurable.
|
||||
|
||||
config DRM_KUNIT_TEST_HELPERS
|
||||
tristate
|
||||
depends on DRM && KUNIT
|
||||
help
|
||||
KUnit Helpers for KMS drivers.
|
||||
|
||||
config DRM_KUNIT_TEST
|
||||
tristate "KUnit tests for DRM" if !KUNIT_ALL_TESTS
|
||||
depends on DRM && KUNIT
|
||||
@@ -73,6 +78,7 @@ config DRM_KUNIT_TEST
|
||||
select DRM_KMS_HELPER
|
||||
select DRM_BUDDY
|
||||
select DRM_EXPORT_FOR_TESTS if m
|
||||
select DRM_KUNIT_TEST_HELPERS
|
||||
default KUNIT_ALL_TESTS
|
||||
help
|
||||
This builds unit tests for DRM. This option is not useful for
|
||||
|
||||
@@ -126,7 +126,7 @@ obj-$(CONFIG_DRM_KMS_HELPER) += drm_kms_helper.o
|
||||
# Drivers and the rest
|
||||
#
|
||||
|
||||
obj-$(CONFIG_DRM_KUNIT_TEST) += tests/
|
||||
obj-y += tests/
|
||||
|
||||
obj-$(CONFIG_DRM_MIPI_DBI) += drm_mipi_dbi.o
|
||||
obj-$(CONFIG_DRM_MIPI_DSI) += drm_mipi_dsi.o
|
||||
|
||||
@@ -13,6 +13,8 @@ config DRM_AMDGPU
|
||||
select DRM_TTM_HELPER
|
||||
select POWER_SUPPLY
|
||||
select HWMON
|
||||
select I2C
|
||||
select I2C_ALGOBIT
|
||||
select BACKLIGHT_CLASS_DEVICE
|
||||
select INTERVAL_TREE
|
||||
select DRM_BUDDY
|
||||
|
||||
@@ -81,7 +81,8 @@ amdgpu-y += \
|
||||
# add DF block
|
||||
amdgpu-y += \
|
||||
df_v1_7.o \
|
||||
df_v3_6.o
|
||||
df_v3_6.o \
|
||||
df_v4_3.o
|
||||
|
||||
# add GMC block
|
||||
amdgpu-y += \
|
||||
|
||||
@@ -52,8 +52,7 @@
|
||||
#include <linux/pci.h>
|
||||
#include <linux/aer.h>
|
||||
|
||||
#include <drm/ttm/ttm_bo_api.h>
|
||||
#include <drm/ttm/ttm_bo_driver.h>
|
||||
#include <drm/ttm/ttm_bo.h>
|
||||
#include <drm/ttm/ttm_placement.h>
|
||||
#include <drm/ttm/ttm_execbuf_util.h>
|
||||
|
||||
@@ -150,7 +149,7 @@ struct amdgpu_watchdog_timer
|
||||
* Modules parameters.
|
||||
*/
|
||||
extern int amdgpu_modeset;
|
||||
extern int amdgpu_vram_limit;
|
||||
extern unsigned int amdgpu_vram_limit;
|
||||
extern int amdgpu_vis_vram_limit;
|
||||
extern int amdgpu_gart_size;
|
||||
extern int amdgpu_gtt_size;
|
||||
@@ -195,6 +194,7 @@ extern int amdgpu_emu_mode;
|
||||
extern uint amdgpu_smu_memory_pool_size;
|
||||
extern int amdgpu_smu_pptable_id;
|
||||
extern uint amdgpu_dc_feature_mask;
|
||||
extern uint amdgpu_freesync_vid_mode;
|
||||
extern uint amdgpu_dc_debug_mask;
|
||||
extern uint amdgpu_dc_visual_confirm;
|
||||
extern uint amdgpu_dm_abm_level;
|
||||
@@ -608,7 +608,7 @@ int amdgpu_cs_wait_fences_ioctl(struct drm_device *dev, void *data,
|
||||
struct drm_file *filp);
|
||||
|
||||
/* VRAM scratch page for HDP bug, default vram page */
|
||||
struct amdgpu_vram_scratch {
|
||||
struct amdgpu_mem_scratch {
|
||||
struct amdgpu_bo *robj;
|
||||
volatile uint32_t *ptr;
|
||||
u64 gpu_addr;
|
||||
@@ -755,6 +755,11 @@ struct amdgpu_mqd {
|
||||
#define AMDGPU_PRODUCT_NAME_LEN 64
|
||||
struct amdgpu_reset_domain;
|
||||
|
||||
/*
|
||||
* Non-zero (true) if the GPU has VRAM. Zero (false) otherwise.
|
||||
*/
|
||||
#define AMDGPU_HAS_VRAM(_adev) ((_adev)->gmc.real_vram_size)
|
||||
|
||||
struct amdgpu_device {
|
||||
struct device *dev;
|
||||
struct pci_dev *pdev;
|
||||
@@ -848,7 +853,7 @@ struct amdgpu_device {
|
||||
|
||||
/* memory management */
|
||||
struct amdgpu_mman mman;
|
||||
struct amdgpu_vram_scratch vram_scratch;
|
||||
struct amdgpu_mem_scratch mem_scratch;
|
||||
struct amdgpu_wb wb;
|
||||
atomic64_t num_bytes_moved;
|
||||
atomic64_t num_evictions;
|
||||
@@ -870,7 +875,7 @@ struct amdgpu_device {
|
||||
struct amdgpu_vkms_output *amdgpu_vkms_output;
|
||||
struct amdgpu_mode_info mode_info;
|
||||
/* For pre-DCE11. DCE11 and later are in "struct amdgpu_device->dm" */
|
||||
struct work_struct hotplug_work;
|
||||
struct delayed_work hotplug_work;
|
||||
struct amdgpu_irq_src crtc_irq;
|
||||
struct amdgpu_irq_src vline0_irq;
|
||||
struct amdgpu_irq_src vupdate_irq;
|
||||
|
||||
@@ -97,7 +97,7 @@ struct amdgpu_amdkfd_fence {
|
||||
|
||||
struct amdgpu_kfd_dev {
|
||||
struct kfd_dev *dev;
|
||||
uint64_t vram_used;
|
||||
int64_t vram_used;
|
||||
uint64_t vram_used_aligned;
|
||||
bool init_complete;
|
||||
struct work_struct reset_work;
|
||||
@@ -271,9 +271,9 @@ int amdgpu_amdkfd_get_pcie_bandwidth_mbytes(struct amdgpu_device *adev, bool is_
|
||||
((struct drm_file *)(drm_priv))->driver_priv)->vm)
|
||||
|
||||
int amdgpu_amdkfd_gpuvm_set_vm_pasid(struct amdgpu_device *adev,
|
||||
struct file *filp, u32 pasid);
|
||||
struct amdgpu_vm *avm, u32 pasid);
|
||||
int amdgpu_amdkfd_gpuvm_acquire_process_vm(struct amdgpu_device *adev,
|
||||
struct file *filp,
|
||||
struct amdgpu_vm *avm,
|
||||
void **process_info,
|
||||
struct dma_fence **ef);
|
||||
void amdgpu_amdkfd_gpuvm_release_process_vm(struct amdgpu_device *adev,
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
#include <linux/pagemap.h>
|
||||
#include <linux/sched/mm.h>
|
||||
#include <linux/sched/task.h>
|
||||
#include <drm/ttm/ttm_tt.h>
|
||||
|
||||
#include "amdgpu_object.h"
|
||||
#include "amdgpu_gem.h"
|
||||
@@ -1430,18 +1431,11 @@ static void amdgpu_amdkfd_gpuvm_unpin_bo(struct amdgpu_bo *bo)
|
||||
}
|
||||
|
||||
int amdgpu_amdkfd_gpuvm_set_vm_pasid(struct amdgpu_device *adev,
|
||||
struct file *filp, u32 pasid)
|
||||
struct amdgpu_vm *avm, u32 pasid)
|
||||
|
||||
{
|
||||
struct amdgpu_fpriv *drv_priv;
|
||||
struct amdgpu_vm *avm;
|
||||
int ret;
|
||||
|
||||
ret = amdgpu_file_to_fpriv(filp, &drv_priv);
|
||||
if (ret)
|
||||
return ret;
|
||||
avm = &drv_priv->vm;
|
||||
|
||||
/* Free the original amdgpu allocated pasid,
|
||||
* will be replaced with kfd allocated pasid.
|
||||
*/
|
||||
@@ -1458,19 +1452,12 @@ int amdgpu_amdkfd_gpuvm_set_vm_pasid(struct amdgpu_device *adev,
|
||||
}
|
||||
|
||||
int amdgpu_amdkfd_gpuvm_acquire_process_vm(struct amdgpu_device *adev,
|
||||
struct file *filp,
|
||||
struct amdgpu_vm *avm,
|
||||
void **process_info,
|
||||
struct dma_fence **ef)
|
||||
{
|
||||
struct amdgpu_fpriv *drv_priv;
|
||||
struct amdgpu_vm *avm;
|
||||
int ret;
|
||||
|
||||
ret = amdgpu_file_to_fpriv(filp, &drv_priv);
|
||||
if (ret)
|
||||
return ret;
|
||||
avm = &drv_priv->vm;
|
||||
|
||||
/* Already a compute VM? */
|
||||
if (avm->process_info)
|
||||
return -EINVAL;
|
||||
@@ -1612,6 +1599,7 @@ int amdgpu_amdkfd_gpuvm_alloc_memory_of_gpu(
|
||||
struct amdgpu_bo *bo;
|
||||
struct drm_gem_object *gobj = NULL;
|
||||
u32 domain, alloc_domain;
|
||||
uint64_t aligned_size;
|
||||
u64 alloc_flags;
|
||||
int ret;
|
||||
|
||||
@@ -1667,22 +1655,23 @@ int amdgpu_amdkfd_gpuvm_alloc_memory_of_gpu(
|
||||
* the memory.
|
||||
*/
|
||||
if ((*mem)->aql_queue)
|
||||
size = size >> 1;
|
||||
size >>= 1;
|
||||
aligned_size = PAGE_ALIGN(size);
|
||||
|
||||
(*mem)->alloc_flags = flags;
|
||||
|
||||
amdgpu_sync_create(&(*mem)->sync);
|
||||
|
||||
ret = amdgpu_amdkfd_reserve_mem_limit(adev, size, flags);
|
||||
ret = amdgpu_amdkfd_reserve_mem_limit(adev, aligned_size, flags);
|
||||
if (ret) {
|
||||
pr_debug("Insufficient memory\n");
|
||||
goto err_reserve_limit;
|
||||
}
|
||||
|
||||
pr_debug("\tcreate BO VA 0x%llx size 0x%llx domain %s\n",
|
||||
va, size, domain_string(alloc_domain));
|
||||
va, (*mem)->aql_queue ? size << 1 : size, domain_string(alloc_domain));
|
||||
|
||||
ret = amdgpu_gem_object_create(adev, size, 1, alloc_domain, alloc_flags,
|
||||
ret = amdgpu_gem_object_create(adev, aligned_size, 1, alloc_domain, alloc_flags,
|
||||
bo_type, NULL, &gobj);
|
||||
if (ret) {
|
||||
pr_debug("Failed to create BO on domain %s. ret %d\n",
|
||||
@@ -1739,7 +1728,7 @@ int amdgpu_amdkfd_gpuvm_alloc_memory_of_gpu(
|
||||
/* Don't unreserve system mem limit twice */
|
||||
goto err_reserve_limit;
|
||||
err_bo_create:
|
||||
amdgpu_amdkfd_unreserve_mem_limit(adev, size, flags);
|
||||
amdgpu_amdkfd_unreserve_mem_limit(adev, aligned_size, flags);
|
||||
err_reserve_limit:
|
||||
mutex_destroy(&(*mem)->lock);
|
||||
if (gobj)
|
||||
@@ -2099,7 +2088,7 @@ int amdgpu_amdkfd_map_gtt_bo_to_gart(struct amdgpu_device *adev, struct amdgpu_b
|
||||
}
|
||||
|
||||
amdgpu_amdkfd_remove_eviction_fence(
|
||||
bo, bo->kfd_bo->process_info->eviction_fence);
|
||||
bo, bo->vm_bo->vm->process_info->eviction_fence);
|
||||
|
||||
amdgpu_bo_unreserve(bo);
|
||||
|
||||
|
||||
@@ -28,6 +28,8 @@
|
||||
|
||||
struct hmm_range;
|
||||
|
||||
struct drm_file;
|
||||
|
||||
struct amdgpu_device;
|
||||
struct amdgpu_bo;
|
||||
struct amdgpu_bo_va;
|
||||
|
||||
@@ -411,17 +411,10 @@ static int amdgpu_cgs_get_firmware_info(struct cgs_device *cgs_device,
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
err = request_firmware(&adev->pm.fw, fw_name, adev->dev);
|
||||
if (err) {
|
||||
DRM_ERROR("Failed to request firmware\n");
|
||||
return err;
|
||||
}
|
||||
|
||||
err = amdgpu_ucode_validate(adev->pm.fw);
|
||||
err = amdgpu_ucode_request(adev, &adev->pm.fw, fw_name);
|
||||
if (err) {
|
||||
DRM_ERROR("Failed to load firmware \"%s\"", fw_name);
|
||||
release_firmware(adev->pm.fw);
|
||||
adev->pm.fw = NULL;
|
||||
amdgpu_ucode_release(&adev->pm.fw);
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
@@ -996,13 +996,33 @@ amdgpu_connector_dvi_detect(struct drm_connector *connector, bool force)
|
||||
}
|
||||
}
|
||||
|
||||
if (amdgpu_connector->detected_hpd_without_ddc) {
|
||||
force = true;
|
||||
amdgpu_connector->detected_hpd_without_ddc = false;
|
||||
}
|
||||
|
||||
if (!force && amdgpu_connector_check_hpd_status_unchanged(connector)) {
|
||||
ret = connector->status;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
if (amdgpu_connector->ddc_bus)
|
||||
if (amdgpu_connector->ddc_bus) {
|
||||
dret = amdgpu_display_ddc_probe(amdgpu_connector, false);
|
||||
|
||||
/* Sometimes the pins required for the DDC probe on DVI
|
||||
* connectors don't make contact at the same time that the ones
|
||||
* for HPD do. If the DDC probe fails even though we had an HPD
|
||||
* signal, try again later
|
||||
*/
|
||||
if (!dret && !force &&
|
||||
amdgpu_display_hpd_sense(adev, amdgpu_connector->hpd.hpd)) {
|
||||
DRM_DEBUG_KMS("hpd detected without ddc, retrying in 1 second\n");
|
||||
amdgpu_connector->detected_hpd_without_ddc = true;
|
||||
schedule_delayed_work(&adev->hotplug_work,
|
||||
msecs_to_jiffies(1000));
|
||||
goto exit;
|
||||
}
|
||||
}
|
||||
if (dret) {
|
||||
amdgpu_connector->detected_by_load = false;
|
||||
amdgpu_connector_free_edid(connector);
|
||||
|
||||
@@ -32,6 +32,8 @@
|
||||
|
||||
#include <drm/amdgpu_drm.h>
|
||||
#include <drm/drm_syncobj.h>
|
||||
#include <drm/ttm/ttm_tt.h>
|
||||
|
||||
#include "amdgpu_cs.h"
|
||||
#include "amdgpu.h"
|
||||
#include "amdgpu_trace.h"
|
||||
|
||||
@@ -23,6 +23,8 @@
|
||||
#ifndef __AMDGPU_CS_H__
|
||||
#define __AMDGPU_CS_H__
|
||||
|
||||
#include <linux/ww_mutex.h>
|
||||
|
||||
#include "amdgpu_job.h"
|
||||
#include "amdgpu_bo_list.h"
|
||||
#include "amdgpu_ring.h"
|
||||
|
||||
@@ -1717,7 +1717,7 @@ static void amdgpu_ib_preempt_mark_partial_job(struct amdgpu_ring *ring)
|
||||
|
||||
static int amdgpu_debugfs_ib_preempt(void *data, u64 val)
|
||||
{
|
||||
int r, resched, length;
|
||||
int r, length;
|
||||
struct amdgpu_ring *ring;
|
||||
struct dma_fence **fences = NULL;
|
||||
struct amdgpu_device *adev = (struct amdgpu_device *)data;
|
||||
@@ -1747,8 +1747,6 @@ static int amdgpu_debugfs_ib_preempt(void *data, u64 val)
|
||||
/* stop the scheduler */
|
||||
kthread_park(ring->sched.thread);
|
||||
|
||||
resched = ttm_bo_lock_delayed_workqueue(&adev->mman.bdev);
|
||||
|
||||
/* preempt the IB */
|
||||
r = amdgpu_ring_preempt_ib(ring);
|
||||
if (r) {
|
||||
@@ -1785,8 +1783,6 @@ static int amdgpu_debugfs_ib_preempt(void *data, u64 val)
|
||||
|
||||
up_read(&adev->reset_domain->sem);
|
||||
|
||||
ttm_bo_unlock_delayed_workqueue(&adev->mman.bdev, resched);
|
||||
|
||||
pro_end:
|
||||
kfree(fences);
|
||||
|
||||
|
||||
@@ -36,6 +36,7 @@
|
||||
#include <generated/utsrelease.h>
|
||||
#include <linux/pci-p2pdma.h>
|
||||
|
||||
#include <drm/drm_aperture.h>
|
||||
#include <drm/drm_atomic_helper.h>
|
||||
#include <drm/drm_fb_helper.h>
|
||||
#include <drm/drm_probe_helper.h>
|
||||
@@ -90,6 +91,8 @@ MODULE_FIRMWARE("amdgpu/navi12_gpu_info.bin");
|
||||
#define AMDGPU_MAX_RETRY_LIMIT 2
|
||||
#define AMDGPU_RETRY_SRIOV_RESET(r) ((r) == -EBUSY || (r) == -ETIMEDOUT || (r) == -EINVAL)
|
||||
|
||||
static const struct drm_driver amdgpu_kms_driver;
|
||||
|
||||
const char *amdgpu_asic_name[] = {
|
||||
"TAHITI",
|
||||
"PITCAIRN",
|
||||
@@ -924,32 +927,33 @@ static int amdgpu_device_asic_init(struct amdgpu_device *adev)
|
||||
}
|
||||
|
||||
/**
|
||||
* amdgpu_device_vram_scratch_init - allocate the VRAM scratch page
|
||||
* amdgpu_device_mem_scratch_init - allocate the VRAM scratch page
|
||||
*
|
||||
* @adev: amdgpu_device pointer
|
||||
*
|
||||
* Allocates a scratch page of VRAM for use by various things in the
|
||||
* driver.
|
||||
*/
|
||||
static int amdgpu_device_vram_scratch_init(struct amdgpu_device *adev)
|
||||
static int amdgpu_device_mem_scratch_init(struct amdgpu_device *adev)
|
||||
{
|
||||
return amdgpu_bo_create_kernel(adev, AMDGPU_GPU_PAGE_SIZE,
|
||||
PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM,
|
||||
&adev->vram_scratch.robj,
|
||||
&adev->vram_scratch.gpu_addr,
|
||||
(void **)&adev->vram_scratch.ptr);
|
||||
return amdgpu_bo_create_kernel(adev, AMDGPU_GPU_PAGE_SIZE, PAGE_SIZE,
|
||||
AMDGPU_GEM_DOMAIN_VRAM |
|
||||
AMDGPU_GEM_DOMAIN_GTT,
|
||||
&adev->mem_scratch.robj,
|
||||
&adev->mem_scratch.gpu_addr,
|
||||
(void **)&adev->mem_scratch.ptr);
|
||||
}
|
||||
|
||||
/**
|
||||
* amdgpu_device_vram_scratch_fini - Free the VRAM scratch page
|
||||
* amdgpu_device_mem_scratch_fini - Free the VRAM scratch page
|
||||
*
|
||||
* @adev: amdgpu_device pointer
|
||||
*
|
||||
* Frees the VRAM scratch page.
|
||||
*/
|
||||
static void amdgpu_device_vram_scratch_fini(struct amdgpu_device *adev)
|
||||
static void amdgpu_device_mem_scratch_fini(struct amdgpu_device *adev)
|
||||
{
|
||||
amdgpu_bo_free_kernel(&adev->vram_scratch.robj, NULL, NULL);
|
||||
amdgpu_bo_free_kernel(&adev->mem_scratch.robj, NULL, NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1981,17 +1985,10 @@ static int amdgpu_device_parse_gpu_info_fw(struct amdgpu_device *adev)
|
||||
}
|
||||
|
||||
snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_gpu_info.bin", chip_name);
|
||||
err = request_firmware(&adev->firmware.gpu_info_fw, fw_name, adev->dev);
|
||||
err = amdgpu_ucode_request(adev, &adev->firmware.gpu_info_fw, fw_name);
|
||||
if (err) {
|
||||
dev_err(adev->dev,
|
||||
"Failed to load gpu_info firmware \"%s\"\n",
|
||||
fw_name);
|
||||
goto out;
|
||||
}
|
||||
err = amdgpu_ucode_validate(adev->firmware.gpu_info_fw);
|
||||
if (err) {
|
||||
dev_err(adev->dev,
|
||||
"Failed to validate gpu_info firmware \"%s\"\n",
|
||||
"Failed to get gpu_info firmware \"%s\"\n",
|
||||
fw_name);
|
||||
goto out;
|
||||
}
|
||||
@@ -2390,9 +2387,9 @@ static int amdgpu_device_ip_init(struct amdgpu_device *adev)
|
||||
if (amdgpu_sriov_vf(adev))
|
||||
amdgpu_virt_exchange_data(adev);
|
||||
|
||||
r = amdgpu_device_vram_scratch_init(adev);
|
||||
r = amdgpu_device_mem_scratch_init(adev);
|
||||
if (r) {
|
||||
DRM_ERROR("amdgpu_vram_scratch_init failed %d\n", r);
|
||||
DRM_ERROR("amdgpu_mem_scratch_init failed %d\n", r);
|
||||
goto init_failed;
|
||||
}
|
||||
r = adev->ip_blocks[i].version->funcs->hw_init((void *)adev);
|
||||
@@ -2410,8 +2407,9 @@ static int amdgpu_device_ip_init(struct amdgpu_device *adev)
|
||||
/* right after GMC hw init, we create CSA */
|
||||
if (amdgpu_mcbp) {
|
||||
r = amdgpu_allocate_static_csa(adev, &adev->virt.csa_obj,
|
||||
AMDGPU_GEM_DOMAIN_VRAM,
|
||||
AMDGPU_CSA_SIZE);
|
||||
AMDGPU_GEM_DOMAIN_VRAM |
|
||||
AMDGPU_GEM_DOMAIN_GTT,
|
||||
AMDGPU_CSA_SIZE);
|
||||
if (r) {
|
||||
DRM_ERROR("allocate CSA failed %d\n", r);
|
||||
goto init_failed;
|
||||
@@ -2581,9 +2579,10 @@ int amdgpu_device_set_cg_state(struct amdgpu_device *adev,
|
||||
i = state == AMD_CG_STATE_GATE ? j : adev->num_ip_blocks - j - 1;
|
||||
if (!adev->ip_blocks[i].status.late_initialized)
|
||||
continue;
|
||||
/* skip CG for GFX on S0ix */
|
||||
/* skip CG for GFX, SDMA on S0ix */
|
||||
if (adev->in_s0ix &&
|
||||
adev->ip_blocks[i].version->type == AMD_IP_BLOCK_TYPE_GFX)
|
||||
(adev->ip_blocks[i].version->type == AMD_IP_BLOCK_TYPE_GFX ||
|
||||
adev->ip_blocks[i].version->type == AMD_IP_BLOCK_TYPE_SDMA))
|
||||
continue;
|
||||
/* skip CG for VCE/UVD, it's handled specially */
|
||||
if (adev->ip_blocks[i].version->type != AMD_IP_BLOCK_TYPE_UVD &&
|
||||
@@ -2617,9 +2616,10 @@ int amdgpu_device_set_pg_state(struct amdgpu_device *adev,
|
||||
i = state == AMD_PG_STATE_GATE ? j : adev->num_ip_blocks - j - 1;
|
||||
if (!adev->ip_blocks[i].status.late_initialized)
|
||||
continue;
|
||||
/* skip PG for GFX on S0ix */
|
||||
/* skip PG for GFX, SDMA on S0ix */
|
||||
if (adev->in_s0ix &&
|
||||
adev->ip_blocks[i].version->type == AMD_IP_BLOCK_TYPE_GFX)
|
||||
(adev->ip_blocks[i].version->type == AMD_IP_BLOCK_TYPE_GFX ||
|
||||
adev->ip_blocks[i].version->type == AMD_IP_BLOCK_TYPE_SDMA))
|
||||
continue;
|
||||
/* skip CG for VCE/UVD, it's handled specially */
|
||||
if (adev->ip_blocks[i].version->type != AMD_IP_BLOCK_TYPE_UVD &&
|
||||
@@ -2871,7 +2871,7 @@ static int amdgpu_device_ip_fini(struct amdgpu_device *adev)
|
||||
amdgpu_ucode_free_bo(adev);
|
||||
amdgpu_free_static_csa(&adev->virt.csa_obj);
|
||||
amdgpu_device_wb_fini(adev);
|
||||
amdgpu_device_vram_scratch_fini(adev);
|
||||
amdgpu_device_mem_scratch_fini(adev);
|
||||
amdgpu_ib_pool_fini(adev);
|
||||
}
|
||||
|
||||
@@ -3027,6 +3027,12 @@ static int amdgpu_device_ip_suspend_phase2(struct amdgpu_device *adev)
|
||||
adev->ip_blocks[i].version->type == AMD_IP_BLOCK_TYPE_MES))
|
||||
continue;
|
||||
|
||||
/* SDMA 5.x+ is part of GFX power domain so it's covered by GFXOFF */
|
||||
if (adev->in_s0ix &&
|
||||
(adev->ip_versions[SDMA0_HWIP][0] >= IP_VERSION(5, 0, 0)) &&
|
||||
(adev->ip_blocks[i].version->type == AMD_IP_BLOCK_TYPE_SDMA))
|
||||
continue;
|
||||
|
||||
/* XXX handle errors */
|
||||
r = adev->ip_blocks[i].version->funcs->suspend(adev);
|
||||
/* XXX handle errors */
|
||||
@@ -3227,15 +3233,6 @@ static int amdgpu_device_ip_resume_phase2(struct amdgpu_device *adev)
|
||||
return r;
|
||||
}
|
||||
adev->ip_blocks[i].status.hw = true;
|
||||
|
||||
if (adev->in_s0ix && adev->ip_blocks[i].version->type == AMD_IP_BLOCK_TYPE_SMC) {
|
||||
/* disable gfxoff for IP resume. The gfxoff will be re-enabled in
|
||||
* amdgpu_device_resume() after IP resume.
|
||||
*/
|
||||
amdgpu_gfx_off_ctrl(adev, false);
|
||||
DRM_DEBUG("will disable gfxoff for re-initializing other blocks\n");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return 0;
|
||||
@@ -3687,6 +3684,11 @@ int amdgpu_device_init(struct amdgpu_device *adev,
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
/* Get rid of things like offb */
|
||||
r = drm_aperture_remove_conflicting_pci_framebuffers(adev->pdev, &amdgpu_kms_driver);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
/* Enable TMZ based on IP_VERSION */
|
||||
amdgpu_gmc_tmz_set(adev);
|
||||
|
||||
@@ -3989,10 +3991,8 @@ void amdgpu_device_fini_hw(struct amdgpu_device *adev)
|
||||
}
|
||||
amdgpu_fence_driver_hw_fini(adev);
|
||||
|
||||
if (adev->mman.initialized) {
|
||||
flush_delayed_work(&adev->mman.bdev.wq);
|
||||
ttm_bo_lock_delayed_workqueue(&adev->mman.bdev);
|
||||
}
|
||||
if (adev->mman.initialized)
|
||||
drain_workqueue(adev->mman.bdev.wq);
|
||||
|
||||
if (adev->pm_sysfs_en)
|
||||
amdgpu_pm_sysfs_fini(adev);
|
||||
@@ -4024,8 +4024,7 @@ void amdgpu_device_fini_sw(struct amdgpu_device *adev)
|
||||
|
||||
amdgpu_fence_driver_sw_fini(adev);
|
||||
amdgpu_device_ip_fini(adev);
|
||||
release_firmware(adev->firmware.gpu_info_fw);
|
||||
adev->firmware.gpu_info_fw = NULL;
|
||||
amdgpu_ucode_release(&adev->firmware.gpu_info_fw);
|
||||
adev->accel_working = false;
|
||||
dma_fence_put(rcu_dereference_protected(adev->gang_submit, true));
|
||||
|
||||
@@ -4223,13 +4222,6 @@ int amdgpu_device_resume(struct drm_device *dev, bool fbcon)
|
||||
/* Make sure IB tests flushed */
|
||||
flush_delayed_work(&adev->delayed_init_work);
|
||||
|
||||
if (adev->in_s0ix) {
|
||||
/* re-enable gfxoff after IP resume. This re-enables gfxoff after
|
||||
* it was disabled for IP resume in amdgpu_device_ip_resume_phase2().
|
||||
*/
|
||||
amdgpu_gfx_off_ctrl(adev, true);
|
||||
DRM_DEBUG("will enable gfxoff for the mission mode\n");
|
||||
}
|
||||
if (fbcon)
|
||||
drm_fb_helper_set_suspend_unlocked(adev_to_drm(adev)->fb_helper, false);
|
||||
|
||||
@@ -4610,11 +4602,6 @@ bool amdgpu_device_should_recover_gpu(struct amdgpu_device *adev)
|
||||
if (!amdgpu_ras_is_poison_mode_supported(adev))
|
||||
return true;
|
||||
|
||||
if (!amdgpu_device_ip_check_soft_reset(adev)) {
|
||||
dev_info(adev->dev,"Timeout, but no hardware hang detected.\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (amdgpu_sriov_vf(adev))
|
||||
return true;
|
||||
|
||||
@@ -4739,7 +4726,8 @@ int amdgpu_device_pre_asic_reset(struct amdgpu_device *adev,
|
||||
if (!need_full_reset)
|
||||
need_full_reset = amdgpu_device_ip_need_full_reset(adev);
|
||||
|
||||
if (!need_full_reset && amdgpu_gpu_recovery) {
|
||||
if (!need_full_reset && amdgpu_gpu_recovery &&
|
||||
amdgpu_device_ip_check_soft_reset(adev)) {
|
||||
amdgpu_device_ip_pre_soft_reset(adev);
|
||||
r = amdgpu_device_ip_soft_reset(adev);
|
||||
amdgpu_device_ip_post_soft_reset(adev);
|
||||
|
||||
@@ -33,6 +33,7 @@
|
||||
#include "gmc_v9_0.h"
|
||||
#include "df_v1_7.h"
|
||||
#include "df_v3_6.h"
|
||||
#include "df_v4_3.h"
|
||||
#include "nbio_v6_1.h"
|
||||
#include "nbio_v7_0.h"
|
||||
#include "nbio_v7_4.h"
|
||||
@@ -2329,6 +2330,9 @@ int amdgpu_discovery_set_ip_blocks(struct amdgpu_device *adev)
|
||||
case IP_VERSION(3, 5, 2):
|
||||
adev->df.funcs = &df_v1_7_funcs;
|
||||
break;
|
||||
case IP_VERSION(4, 3, 0):
|
||||
adev->df.funcs = &df_v4_3_funcs;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -63,7 +63,7 @@
|
||||
void amdgpu_display_hotplug_work_func(struct work_struct *work)
|
||||
{
|
||||
struct amdgpu_device *adev = container_of(work, struct amdgpu_device,
|
||||
hotplug_work);
|
||||
hotplug_work.work);
|
||||
struct drm_device *dev = adev_to_drm(adev);
|
||||
struct drm_mode_config *mode_config = &dev->mode_config;
|
||||
struct drm_connector *connector;
|
||||
|
||||
@@ -37,6 +37,7 @@
|
||||
#include "amdgpu_dma_buf.h"
|
||||
#include "amdgpu_xgmi.h"
|
||||
#include <drm/amdgpu_drm.h>
|
||||
#include <drm/ttm/ttm_tt.h>
|
||||
#include <linux/dma-buf.h>
|
||||
#include <linux/dma-fence-array.h>
|
||||
#include <linux/pci-p2pdma.h>
|
||||
|
||||
@@ -23,7 +23,6 @@
|
||||
*/
|
||||
|
||||
#include <drm/amdgpu_drm.h>
|
||||
#include <drm/drm_aperture.h>
|
||||
#include <drm/drm_drv.h>
|
||||
#include <drm/drm_fbdev_generic.h>
|
||||
#include <drm/drm_gem.h>
|
||||
@@ -105,13 +104,15 @@
|
||||
* - 3.46.0 - To enable hot plug amdgpu tests in libdrm
|
||||
* - 3.47.0 - Add AMDGPU_GEM_CREATE_DISCARDABLE and AMDGPU_VM_NOALLOC flags
|
||||
* - 3.48.0 - Add IP discovery version info to HW INFO
|
||||
* 3.49.0 - Add gang submit into CS IOCTL
|
||||
* - 3.49.0 - Add gang submit into CS IOCTL
|
||||
* - 3.50.0 - Update AMDGPU_INFO_DEV_INFO IOCTL for minimum engine and memory clock
|
||||
* Update AMDGPU_INFO_SENSOR IOCTL for PEAK_PSTATE engine and memory clock
|
||||
*/
|
||||
#define KMS_DRIVER_MAJOR 3
|
||||
#define KMS_DRIVER_MINOR 49
|
||||
#define KMS_DRIVER_MINOR 50
|
||||
#define KMS_DRIVER_PATCHLEVEL 0
|
||||
|
||||
int amdgpu_vram_limit;
|
||||
unsigned int amdgpu_vram_limit = UINT_MAX;
|
||||
int amdgpu_vis_vram_limit;
|
||||
int amdgpu_gart_size = -1; /* auto */
|
||||
int amdgpu_gtt_size = -1; /* auto */
|
||||
@@ -181,6 +182,7 @@ int amdgpu_mes_kiq;
|
||||
int amdgpu_noretry = -1;
|
||||
int amdgpu_force_asic_type = -1;
|
||||
int amdgpu_tmz = -1; /* auto */
|
||||
uint amdgpu_freesync_vid_mode;
|
||||
int amdgpu_reset_method = -1; /* auto */
|
||||
int amdgpu_num_kcq = -1;
|
||||
int amdgpu_smartshift_bias;
|
||||
@@ -879,6 +881,32 @@ module_param_named(backlight, amdgpu_backlight, bint, 0444);
|
||||
MODULE_PARM_DESC(tmz, "Enable TMZ feature (-1 = auto (default), 0 = off, 1 = on)");
|
||||
module_param_named(tmz, amdgpu_tmz, int, 0444);
|
||||
|
||||
/**
|
||||
* DOC: freesync_video (uint)
|
||||
* Enable the optimization to adjust front porch timing to achieve seamless
|
||||
* mode change experience when setting a freesync supported mode for which full
|
||||
* modeset is not needed.
|
||||
*
|
||||
* The Display Core will add a set of modes derived from the base FreeSync
|
||||
* video mode into the corresponding connector's mode list based on commonly
|
||||
* used refresh rates and VRR range of the connected display, when users enable
|
||||
* this feature. From the userspace perspective, they can see a seamless mode
|
||||
* change experience when the change between different refresh rates under the
|
||||
* same resolution. Additionally, userspace applications such as Video playback
|
||||
* can read this modeset list and change the refresh rate based on the video
|
||||
* frame rate. Finally, the userspace can also derive an appropriate mode for a
|
||||
* particular refresh rate based on the FreeSync Mode and add it to the
|
||||
* connector's mode list.
|
||||
*
|
||||
* Note: This is an experimental feature.
|
||||
*
|
||||
* The default value: 0 (off).
|
||||
*/
|
||||
MODULE_PARM_DESC(
|
||||
freesync_video,
|
||||
"Enable freesync modesetting optimization feature (0 = off (default), 1 = on)");
|
||||
module_param_named(freesync_video, amdgpu_freesync_vid_mode, uint, 0444);
|
||||
|
||||
/**
|
||||
* DOC: reset_method (int)
|
||||
* GPU reset method (-1 = auto (default), 0 = legacy, 1 = mode0, 2 = mode1, 3 = mode2, 4 = baco)
|
||||
@@ -2095,11 +2123,6 @@ static int amdgpu_pci_probe(struct pci_dev *pdev,
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Get rid of things like offb */
|
||||
ret = drm_aperture_remove_conflicting_pci_framebuffers(pdev, &amdgpu_kms_driver);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
adev = devm_drm_dev_alloc(&pdev->dev, &amdgpu_kms_driver, typeof(*adev), ddev);
|
||||
if (IS_ERR(adev))
|
||||
return PTR_ERR(adev);
|
||||
|
||||
@@ -30,7 +30,6 @@
|
||||
#include <linux/rbtree.h>
|
||||
#include <drm/gpu_scheduler.h>
|
||||
#include <drm/drm_file.h>
|
||||
#include <drm/ttm/ttm_bo_driver.h>
|
||||
#include <linux/sched/mm.h>
|
||||
|
||||
#include "amdgpu_sync.h"
|
||||
|
||||
@@ -34,6 +34,7 @@
|
||||
#include <drm/amdgpu_drm.h>
|
||||
#include <drm/drm_drv.h>
|
||||
#include <drm/drm_gem_ttm_helper.h>
|
||||
#include <drm/ttm/ttm_tt.h>
|
||||
|
||||
#include "amdgpu.h"
|
||||
#include "amdgpu_display.h"
|
||||
@@ -61,10 +62,10 @@ static vm_fault_t amdgpu_gem_fault(struct vm_fault *vmf)
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
ret = ttm_bo_vm_fault_reserved(vmf, vmf->vma->vm_page_prot,
|
||||
TTM_BO_VM_NUM_PREFAULT);
|
||||
ret = ttm_bo_vm_fault_reserved(vmf, vmf->vma->vm_page_prot,
|
||||
TTM_BO_VM_NUM_PREFAULT);
|
||||
|
||||
drm_dev_exit(idx);
|
||||
drm_dev_exit(idx);
|
||||
} else {
|
||||
ret = ttm_bo_vm_dummy_page(vmf, vmf->vma->vm_page_prot);
|
||||
}
|
||||
|
||||
@@ -372,8 +372,11 @@ int amdgpu_gfx_mqd_sw_init(struct amdgpu_device *adev,
|
||||
* KIQ MQD no matter SRIOV or Bare-metal
|
||||
*/
|
||||
r = amdgpu_bo_create_kernel(adev, mqd_size, PAGE_SIZE,
|
||||
AMDGPU_GEM_DOMAIN_VRAM, &ring->mqd_obj,
|
||||
&ring->mqd_gpu_addr, &ring->mqd_ptr);
|
||||
AMDGPU_GEM_DOMAIN_VRAM |
|
||||
AMDGPU_GEM_DOMAIN_GTT,
|
||||
&ring->mqd_obj,
|
||||
&ring->mqd_gpu_addr,
|
||||
&ring->mqd_ptr);
|
||||
if (r) {
|
||||
dev_warn(adev->dev, "failed to create ring mqd ob (%d)", r);
|
||||
return r;
|
||||
|
||||
@@ -35,6 +35,7 @@
|
||||
#include "amdgpu_xgmi.h"
|
||||
|
||||
#include <drm/drm_drv.h>
|
||||
#include <drm/ttm/ttm_tt.h>
|
||||
|
||||
/**
|
||||
* amdgpu_gmc_pdb0_alloc - allocate vram for pdb0
|
||||
@@ -201,13 +202,20 @@ uint64_t amdgpu_gmc_agp_addr(struct ttm_buffer_object *bo)
|
||||
void amdgpu_gmc_vram_location(struct amdgpu_device *adev, struct amdgpu_gmc *mc,
|
||||
u64 base)
|
||||
{
|
||||
uint64_t vis_limit = (uint64_t)amdgpu_vis_vram_limit << 20;
|
||||
uint64_t limit = (uint64_t)amdgpu_vram_limit << 20;
|
||||
|
||||
mc->vram_start = base;
|
||||
mc->vram_end = mc->vram_start + mc->mc_vram_size - 1;
|
||||
if (limit && limit < mc->real_vram_size)
|
||||
if (limit < mc->real_vram_size)
|
||||
mc->real_vram_size = limit;
|
||||
|
||||
if (vis_limit && vis_limit < mc->visible_vram_size)
|
||||
mc->visible_vram_size = vis_limit;
|
||||
|
||||
if (mc->real_vram_size < mc->visible_vram_size)
|
||||
mc->visible_vram_size = mc->real_vram_size;
|
||||
|
||||
if (mc->xgmi.num_physical_nodes == 0) {
|
||||
mc->fb_start = mc->vram_start;
|
||||
mc->fb_end = mc->vram_end;
|
||||
|
||||
@@ -785,9 +785,15 @@ int amdgpu_info_ioctl(struct drm_device *dev, void *data, struct drm_file *filp)
|
||||
if (adev->pm.dpm_enabled) {
|
||||
dev_info->max_engine_clock = amdgpu_dpm_get_sclk(adev, false) * 10;
|
||||
dev_info->max_memory_clock = amdgpu_dpm_get_mclk(adev, false) * 10;
|
||||
dev_info->min_engine_clock = amdgpu_dpm_get_sclk(adev, true) * 10;
|
||||
dev_info->min_memory_clock = amdgpu_dpm_get_mclk(adev, true) * 10;
|
||||
} else {
|
||||
dev_info->max_engine_clock = adev->clock.default_sclk * 10;
|
||||
dev_info->max_memory_clock = adev->clock.default_mclk * 10;
|
||||
dev_info->max_engine_clock =
|
||||
dev_info->min_engine_clock =
|
||||
adev->clock.default_sclk * 10;
|
||||
dev_info->max_memory_clock =
|
||||
dev_info->min_memory_clock =
|
||||
adev->clock.default_mclk * 10;
|
||||
}
|
||||
dev_info->enabled_rb_pipes_mask = adev->gfx.config.backend_enable_mask;
|
||||
dev_info->num_rb_pipes = adev->gfx.config.max_backends_per_se *
|
||||
@@ -1014,6 +1020,24 @@ int amdgpu_info_ioctl(struct drm_device *dev, void *data, struct drm_file *filp)
|
||||
}
|
||||
ui32 /= 100;
|
||||
break;
|
||||
case AMDGPU_INFO_SENSOR_PEAK_PSTATE_GFX_SCLK:
|
||||
/* get peak pstate sclk in Mhz */
|
||||
if (amdgpu_dpm_read_sensor(adev,
|
||||
AMDGPU_PP_SENSOR_PEAK_PSTATE_SCLK,
|
||||
(void *)&ui32, &ui32_size)) {
|
||||
return -EINVAL;
|
||||
}
|
||||
ui32 /= 100;
|
||||
break;
|
||||
case AMDGPU_INFO_SENSOR_PEAK_PSTATE_GFX_MCLK:
|
||||
/* get peak pstate mclk in Mhz */
|
||||
if (amdgpu_dpm_read_sensor(adev,
|
||||
AMDGPU_PP_SENSOR_PEAK_PSTATE_MCLK,
|
||||
(void *)&ui32, &ui32_size)) {
|
||||
return -EINVAL;
|
||||
}
|
||||
ui32 /= 100;
|
||||
break;
|
||||
default:
|
||||
DRM_DEBUG_KMS("Invalid request %d\n",
|
||||
info->sensor_info.type);
|
||||
|
||||
@@ -21,6 +21,8 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#include <linux/firmware.h>
|
||||
|
||||
#include "amdgpu_mes.h"
|
||||
#include "amdgpu.h"
|
||||
#include "soc15_common.h"
|
||||
@@ -1423,3 +1425,60 @@ int amdgpu_mes_self_test(struct amdgpu_device *adev)
|
||||
kfree(vm);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int amdgpu_mes_init_microcode(struct amdgpu_device *adev, int pipe)
|
||||
{
|
||||
const struct mes_firmware_header_v1_0 *mes_hdr;
|
||||
struct amdgpu_firmware_info *info;
|
||||
char ucode_prefix[30];
|
||||
char fw_name[40];
|
||||
int r;
|
||||
|
||||
amdgpu_ucode_ip_version_decode(adev, GC_HWIP, ucode_prefix, sizeof(ucode_prefix));
|
||||
snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_mes%s.bin",
|
||||
ucode_prefix,
|
||||
pipe == AMDGPU_MES_SCHED_PIPE ? "" : "1");
|
||||
r = amdgpu_ucode_request(adev, &adev->mes.fw[pipe], fw_name);
|
||||
if (r)
|
||||
goto out;
|
||||
|
||||
mes_hdr = (const struct mes_firmware_header_v1_0 *)
|
||||
adev->mes.fw[pipe]->data;
|
||||
adev->mes.uc_start_addr[pipe] =
|
||||
le32_to_cpu(mes_hdr->mes_uc_start_addr_lo) |
|
||||
((uint64_t)(le32_to_cpu(mes_hdr->mes_uc_start_addr_hi)) << 32);
|
||||
adev->mes.data_start_addr[pipe] =
|
||||
le32_to_cpu(mes_hdr->mes_data_start_addr_lo) |
|
||||
((uint64_t)(le32_to_cpu(mes_hdr->mes_data_start_addr_hi)) << 32);
|
||||
|
||||
if (adev->firmware.load_type == AMDGPU_FW_LOAD_PSP) {
|
||||
int ucode, ucode_data;
|
||||
|
||||
if (pipe == AMDGPU_MES_SCHED_PIPE) {
|
||||
ucode = AMDGPU_UCODE_ID_CP_MES;
|
||||
ucode_data = AMDGPU_UCODE_ID_CP_MES_DATA;
|
||||
} else {
|
||||
ucode = AMDGPU_UCODE_ID_CP_MES1;
|
||||
ucode_data = AMDGPU_UCODE_ID_CP_MES1_DATA;
|
||||
}
|
||||
|
||||
info = &adev->firmware.ucode[ucode];
|
||||
info->ucode_id = ucode;
|
||||
info->fw = adev->mes.fw[pipe];
|
||||
adev->firmware.fw_size +=
|
||||
ALIGN(le32_to_cpu(mes_hdr->mes_ucode_size_bytes),
|
||||
PAGE_SIZE);
|
||||
|
||||
info = &adev->firmware.ucode[ucode_data];
|
||||
info->ucode_id = ucode_data;
|
||||
info->fw = adev->mes.fw[pipe];
|
||||
adev->firmware.fw_size +=
|
||||
ALIGN(le32_to_cpu(mes_hdr->mes_ucode_data_size_bytes),
|
||||
PAGE_SIZE);
|
||||
}
|
||||
|
||||
return 0;
|
||||
out:
|
||||
amdgpu_ucode_release(&adev->mes.fw[pipe]);
|
||||
return r;
|
||||
}
|
||||
|
||||
@@ -306,6 +306,7 @@ struct amdgpu_mes_funcs {
|
||||
|
||||
int amdgpu_mes_ctx_get_offs(struct amdgpu_ring *ring, unsigned int id_offs);
|
||||
|
||||
int amdgpu_mes_init_microcode(struct amdgpu_device *adev, int pipe);
|
||||
int amdgpu_mes_init(struct amdgpu_device *adev);
|
||||
void amdgpu_mes_fini(struct amdgpu_device *adev);
|
||||
|
||||
|
||||
@@ -534,6 +534,7 @@ struct amdgpu_connector {
|
||||
void *con_priv;
|
||||
bool dac_load_detect;
|
||||
bool detected_by_load; /* if the connection status was determined by load */
|
||||
bool detected_hpd_without_ddc; /* if an HPD signal was detected on DVI, but ddc probing failed */
|
||||
uint16_t connector_object_id;
|
||||
struct amdgpu_hpd hpd;
|
||||
struct amdgpu_router router;
|
||||
|
||||
@@ -470,8 +470,9 @@ static bool amdgpu_bo_validate_size(struct amdgpu_device *adev,
|
||||
return true;
|
||||
|
||||
fail:
|
||||
DRM_DEBUG("BO size %lu > total memory in domain: %llu\n", size,
|
||||
man->size);
|
||||
if (man)
|
||||
DRM_DEBUG("BO size %lu > total memory in domain: %llu\n", size,
|
||||
man->size);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -66,7 +66,8 @@ static int psp_ring_init(struct psp_context *psp,
|
||||
/* allocate 4k Page of Local Frame Buffer memory for ring */
|
||||
ring->ring_size = 0x1000;
|
||||
ret = amdgpu_bo_create_kernel(adev, ring->ring_size, PAGE_SIZE,
|
||||
AMDGPU_GEM_DOMAIN_VRAM,
|
||||
AMDGPU_GEM_DOMAIN_VRAM |
|
||||
AMDGPU_GEM_DOMAIN_GTT,
|
||||
&adev->firmware.rbuf,
|
||||
&ring->ring_mem_mc_addr,
|
||||
(void **)&ring->ring_mem);
|
||||
@@ -122,6 +123,38 @@ static void psp_check_pmfw_centralized_cstate_management(struct psp_context *psp
|
||||
}
|
||||
}
|
||||
|
||||
static int psp_init_sriov_microcode(struct psp_context *psp)
|
||||
{
|
||||
struct amdgpu_device *adev = psp->adev;
|
||||
char ucode_prefix[30];
|
||||
int ret = 0;
|
||||
|
||||
amdgpu_ucode_ip_version_decode(adev, MP0_HWIP, ucode_prefix, sizeof(ucode_prefix));
|
||||
|
||||
switch (adev->ip_versions[MP0_HWIP][0]) {
|
||||
case IP_VERSION(9, 0, 0):
|
||||
case IP_VERSION(11, 0, 7):
|
||||
case IP_VERSION(11, 0, 9):
|
||||
adev->virt.autoload_ucode_id = AMDGPU_UCODE_ID_CP_MEC2;
|
||||
ret = psp_init_cap_microcode(psp, ucode_prefix);
|
||||
break;
|
||||
case IP_VERSION(13, 0, 2):
|
||||
adev->virt.autoload_ucode_id = AMDGPU_UCODE_ID_CP_MEC2;
|
||||
ret = psp_init_cap_microcode(psp, ucode_prefix);
|
||||
ret &= psp_init_ta_microcode(psp, ucode_prefix);
|
||||
break;
|
||||
case IP_VERSION(13, 0, 0):
|
||||
adev->virt.autoload_ucode_id = 0;
|
||||
break;
|
||||
case IP_VERSION(13, 0, 10):
|
||||
adev->virt.autoload_ucode_id = AMDGPU_UCODE_ID_CP_MES1_DATA;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int psp_early_init(void *handle)
|
||||
{
|
||||
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
|
||||
@@ -192,7 +225,10 @@ static int psp_early_init(void *handle)
|
||||
|
||||
psp_check_pmfw_centralized_cstate_management(psp);
|
||||
|
||||
return 0;
|
||||
if (amdgpu_sriov_vf(adev))
|
||||
return psp_init_sriov_microcode(psp);
|
||||
else
|
||||
return psp_init_microcode(psp);
|
||||
}
|
||||
|
||||
void psp_ta_free_shared_buf(struct ta_mem_context *mem_ctx)
|
||||
@@ -350,42 +386,6 @@ static bool psp_get_runtime_db_entry(struct amdgpu_device *adev,
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int psp_init_sriov_microcode(struct psp_context *psp)
|
||||
{
|
||||
struct amdgpu_device *adev = psp->adev;
|
||||
int ret = 0;
|
||||
|
||||
switch (adev->ip_versions[MP0_HWIP][0]) {
|
||||
case IP_VERSION(9, 0, 0):
|
||||
adev->virt.autoload_ucode_id = AMDGPU_UCODE_ID_CP_MEC2;
|
||||
ret = psp_init_cap_microcode(psp, "vega10");
|
||||
break;
|
||||
case IP_VERSION(11, 0, 9):
|
||||
adev->virt.autoload_ucode_id = AMDGPU_UCODE_ID_CP_MEC2;
|
||||
ret = psp_init_cap_microcode(psp, "navi12");
|
||||
break;
|
||||
case IP_VERSION(11, 0, 7):
|
||||
adev->virt.autoload_ucode_id = AMDGPU_UCODE_ID_CP_MEC2;
|
||||
ret = psp_init_cap_microcode(psp, "sienna_cichlid");
|
||||
break;
|
||||
case IP_VERSION(13, 0, 2):
|
||||
adev->virt.autoload_ucode_id = AMDGPU_UCODE_ID_CP_MEC2;
|
||||
ret = psp_init_cap_microcode(psp, "aldebaran");
|
||||
ret &= psp_init_ta_microcode(psp, "aldebaran");
|
||||
break;
|
||||
case IP_VERSION(13, 0, 0):
|
||||
adev->virt.autoload_ucode_id = 0;
|
||||
break;
|
||||
case IP_VERSION(13, 0, 10):
|
||||
adev->virt.autoload_ucode_id = AMDGPU_UCODE_ID_CP_MES1_DATA;
|
||||
break;
|
||||
default:
|
||||
BUG();
|
||||
break;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int psp_sw_init(void *handle)
|
||||
{
|
||||
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
|
||||
@@ -401,15 +401,6 @@ static int psp_sw_init(void *handle)
|
||||
ret = -ENOMEM;
|
||||
}
|
||||
|
||||
if (amdgpu_sriov_vf(adev))
|
||||
ret = psp_init_sriov_microcode(psp);
|
||||
else
|
||||
ret = psp_init_microcode(psp);
|
||||
if (ret) {
|
||||
DRM_ERROR("Failed to load psp firmware!\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
adev->psp.xgmi_context.supports_extended_data =
|
||||
!adev->gmc.xgmi.connected_to_cpu &&
|
||||
adev->ip_versions[MP0_HWIP][0] == IP_VERSION(13, 0, 2);
|
||||
@@ -514,20 +505,11 @@ static int psp_sw_fini(void *handle)
|
||||
|
||||
psp_memory_training_fini(psp);
|
||||
|
||||
release_firmware(psp->sos_fw);
|
||||
psp->sos_fw = NULL;
|
||||
|
||||
release_firmware(psp->asd_fw);
|
||||
psp->asd_fw = NULL;
|
||||
|
||||
release_firmware(psp->ta_fw);
|
||||
psp->ta_fw = NULL;
|
||||
|
||||
release_firmware(psp->cap_fw);
|
||||
psp->cap_fw = NULL;
|
||||
|
||||
release_firmware(psp->toc_fw);
|
||||
psp->toc_fw = NULL;
|
||||
amdgpu_ucode_release(&psp->sos_fw);
|
||||
amdgpu_ucode_release(&psp->asd_fw);
|
||||
amdgpu_ucode_release(&psp->ta_fw);
|
||||
amdgpu_ucode_release(&psp->cap_fw);
|
||||
amdgpu_ucode_release(&psp->toc_fw);
|
||||
|
||||
if (adev->ip_versions[MP0_HWIP][0] == IP_VERSION(11, 0, 0) ||
|
||||
adev->ip_versions[MP0_HWIP][0] == IP_VERSION(11, 0, 7))
|
||||
@@ -797,9 +779,13 @@ static int psp_tmr_init(struct psp_context *psp)
|
||||
|
||||
if (!psp->tmr_bo) {
|
||||
pptr = amdgpu_sriov_vf(psp->adev) ? &tmr_buf : NULL;
|
||||
ret = amdgpu_bo_create_kernel(psp->adev, tmr_size, PSP_TMR_ALIGNMENT,
|
||||
AMDGPU_GEM_DOMAIN_VRAM,
|
||||
&psp->tmr_bo, &psp->tmr_mc_addr, pptr);
|
||||
ret = amdgpu_bo_create_kernel(psp->adev, tmr_size,
|
||||
PSP_TMR_ALIGNMENT,
|
||||
AMDGPU_HAS_VRAM(psp->adev) ?
|
||||
AMDGPU_GEM_DOMAIN_VRAM :
|
||||
AMDGPU_GEM_DOMAIN_GTT,
|
||||
&psp->tmr_bo, &psp->tmr_mc_addr,
|
||||
pptr);
|
||||
}
|
||||
|
||||
return ret;
|
||||
@@ -1092,7 +1078,8 @@ int psp_ta_init_shared_buf(struct psp_context *psp,
|
||||
* physical) for ta to host memory
|
||||
*/
|
||||
return amdgpu_bo_create_kernel(psp->adev, mem_ctx->shared_mem_size,
|
||||
PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM,
|
||||
PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM |
|
||||
AMDGPU_GEM_DOMAIN_GTT,
|
||||
&mem_ctx->shared_bo,
|
||||
&mem_ctx->shared_mc_addr,
|
||||
&mem_ctx->shared_buf);
|
||||
@@ -1901,7 +1888,7 @@ int psp_rap_invoke(struct psp_context *psp, uint32_t ta_cmd_id, enum ta_rap_stat
|
||||
static int psp_securedisplay_initialize(struct psp_context *psp)
|
||||
{
|
||||
int ret;
|
||||
struct securedisplay_cmd *securedisplay_cmd;
|
||||
struct ta_securedisplay_cmd *securedisplay_cmd;
|
||||
|
||||
/*
|
||||
* TODO: bypass the initialize in sriov for now
|
||||
@@ -2908,25 +2895,15 @@ int psp_ring_cmd_submit(struct psp_context *psp,
|
||||
return 0;
|
||||
}
|
||||
|
||||
int psp_init_asd_microcode(struct psp_context *psp,
|
||||
const char *chip_name)
|
||||
int psp_init_asd_microcode(struct psp_context *psp, const char *chip_name)
|
||||
{
|
||||
struct amdgpu_device *adev = psp->adev;
|
||||
char fw_name[PSP_FW_NAME_LEN];
|
||||
const struct psp_firmware_header_v1_0 *asd_hdr;
|
||||
int err = 0;
|
||||
|
||||
if (!chip_name) {
|
||||
dev_err(adev->dev, "invalid chip name for asd microcode\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_asd.bin", chip_name);
|
||||
err = request_firmware(&adev->psp.asd_fw, fw_name, adev->dev);
|
||||
if (err)
|
||||
goto out;
|
||||
|
||||
err = amdgpu_ucode_validate(adev->psp.asd_fw);
|
||||
err = amdgpu_ucode_request(adev, &adev->psp.asd_fw, fw_name);
|
||||
if (err)
|
||||
goto out;
|
||||
|
||||
@@ -2938,31 +2915,19 @@ int psp_init_asd_microcode(struct psp_context *psp,
|
||||
le32_to_cpu(asd_hdr->header.ucode_array_offset_bytes);
|
||||
return 0;
|
||||
out:
|
||||
dev_err(adev->dev, "fail to initialize asd microcode\n");
|
||||
release_firmware(adev->psp.asd_fw);
|
||||
adev->psp.asd_fw = NULL;
|
||||
amdgpu_ucode_release(&adev->psp.asd_fw);
|
||||
return err;
|
||||
}
|
||||
|
||||
int psp_init_toc_microcode(struct psp_context *psp,
|
||||
const char *chip_name)
|
||||
int psp_init_toc_microcode(struct psp_context *psp, const char *chip_name)
|
||||
{
|
||||
struct amdgpu_device *adev = psp->adev;
|
||||
char fw_name[PSP_FW_NAME_LEN];
|
||||
const struct psp_firmware_header_v1_0 *toc_hdr;
|
||||
int err = 0;
|
||||
|
||||
if (!chip_name) {
|
||||
dev_err(adev->dev, "invalid chip name for toc microcode\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_toc.bin", chip_name);
|
||||
err = request_firmware(&adev->psp.toc_fw, fw_name, adev->dev);
|
||||
if (err)
|
||||
goto out;
|
||||
|
||||
err = amdgpu_ucode_validate(adev->psp.toc_fw);
|
||||
err = amdgpu_ucode_request(adev, &adev->psp.toc_fw, fw_name);
|
||||
if (err)
|
||||
goto out;
|
||||
|
||||
@@ -2974,9 +2939,7 @@ int psp_init_toc_microcode(struct psp_context *psp,
|
||||
le32_to_cpu(toc_hdr->header.ucode_array_offset_bytes);
|
||||
return 0;
|
||||
out:
|
||||
dev_err(adev->dev, "fail to request/validate toc microcode\n");
|
||||
release_firmware(adev->psp.toc_fw);
|
||||
adev->psp.toc_fw = NULL;
|
||||
amdgpu_ucode_release(&adev->psp.toc_fw);
|
||||
return err;
|
||||
}
|
||||
|
||||
@@ -3107,8 +3070,7 @@ static int psp_init_sos_base_fw(struct amdgpu_device *adev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int psp_init_sos_microcode(struct psp_context *psp,
|
||||
const char *chip_name)
|
||||
int psp_init_sos_microcode(struct psp_context *psp, const char *chip_name)
|
||||
{
|
||||
struct amdgpu_device *adev = psp->adev;
|
||||
char fw_name[PSP_FW_NAME_LEN];
|
||||
@@ -3121,17 +3083,8 @@ int psp_init_sos_microcode(struct psp_context *psp,
|
||||
uint8_t *ucode_array_start_addr;
|
||||
int fw_index = 0;
|
||||
|
||||
if (!chip_name) {
|
||||
dev_err(adev->dev, "invalid chip name for sos microcode\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_sos.bin", chip_name);
|
||||
err = request_firmware(&adev->psp.sos_fw, fw_name, adev->dev);
|
||||
if (err)
|
||||
goto out;
|
||||
|
||||
err = amdgpu_ucode_validate(adev->psp.sos_fw);
|
||||
err = amdgpu_ucode_request(adev, &adev->psp.sos_fw, fw_name);
|
||||
if (err)
|
||||
goto out;
|
||||
|
||||
@@ -3203,10 +3156,7 @@ int psp_init_sos_microcode(struct psp_context *psp,
|
||||
|
||||
return 0;
|
||||
out:
|
||||
dev_err(adev->dev,
|
||||
"failed to init sos firmware\n");
|
||||
release_firmware(adev->psp.sos_fw);
|
||||
adev->psp.sos_fw = NULL;
|
||||
amdgpu_ucode_release(&adev->psp.sos_fw);
|
||||
|
||||
return err;
|
||||
}
|
||||
@@ -3272,41 +3222,76 @@ static int parse_ta_bin_descriptor(struct psp_context *psp,
|
||||
return 0;
|
||||
}
|
||||
|
||||
int psp_init_ta_microcode(struct psp_context *psp,
|
||||
const char *chip_name)
|
||||
static int parse_ta_v1_microcode(struct psp_context *psp)
|
||||
{
|
||||
const struct ta_firmware_header_v1_0 *ta_hdr;
|
||||
struct amdgpu_device *adev = psp->adev;
|
||||
char fw_name[PSP_FW_NAME_LEN];
|
||||
|
||||
ta_hdr = (const struct ta_firmware_header_v1_0 *) adev->psp.ta_fw->data;
|
||||
|
||||
if (le16_to_cpu(ta_hdr->header.header_version_major) != 1)
|
||||
return -EINVAL;
|
||||
|
||||
adev->psp.xgmi_context.context.bin_desc.fw_version =
|
||||
le32_to_cpu(ta_hdr->xgmi.fw_version);
|
||||
adev->psp.xgmi_context.context.bin_desc.size_bytes =
|
||||
le32_to_cpu(ta_hdr->xgmi.size_bytes);
|
||||
adev->psp.xgmi_context.context.bin_desc.start_addr =
|
||||
(uint8_t *)ta_hdr +
|
||||
le32_to_cpu(ta_hdr->header.ucode_array_offset_bytes);
|
||||
|
||||
adev->psp.ras_context.context.bin_desc.fw_version =
|
||||
le32_to_cpu(ta_hdr->ras.fw_version);
|
||||
adev->psp.ras_context.context.bin_desc.size_bytes =
|
||||
le32_to_cpu(ta_hdr->ras.size_bytes);
|
||||
adev->psp.ras_context.context.bin_desc.start_addr =
|
||||
(uint8_t *)adev->psp.xgmi_context.context.bin_desc.start_addr +
|
||||
le32_to_cpu(ta_hdr->ras.offset_bytes);
|
||||
|
||||
adev->psp.hdcp_context.context.bin_desc.fw_version =
|
||||
le32_to_cpu(ta_hdr->hdcp.fw_version);
|
||||
adev->psp.hdcp_context.context.bin_desc.size_bytes =
|
||||
le32_to_cpu(ta_hdr->hdcp.size_bytes);
|
||||
adev->psp.hdcp_context.context.bin_desc.start_addr =
|
||||
(uint8_t *)ta_hdr +
|
||||
le32_to_cpu(ta_hdr->header.ucode_array_offset_bytes);
|
||||
|
||||
adev->psp.dtm_context.context.bin_desc.fw_version =
|
||||
le32_to_cpu(ta_hdr->dtm.fw_version);
|
||||
adev->psp.dtm_context.context.bin_desc.size_bytes =
|
||||
le32_to_cpu(ta_hdr->dtm.size_bytes);
|
||||
adev->psp.dtm_context.context.bin_desc.start_addr =
|
||||
(uint8_t *)adev->psp.hdcp_context.context.bin_desc.start_addr +
|
||||
le32_to_cpu(ta_hdr->dtm.offset_bytes);
|
||||
|
||||
adev->psp.securedisplay_context.context.bin_desc.fw_version =
|
||||
le32_to_cpu(ta_hdr->securedisplay.fw_version);
|
||||
adev->psp.securedisplay_context.context.bin_desc.size_bytes =
|
||||
le32_to_cpu(ta_hdr->securedisplay.size_bytes);
|
||||
adev->psp.securedisplay_context.context.bin_desc.start_addr =
|
||||
(uint8_t *)adev->psp.hdcp_context.context.bin_desc.start_addr +
|
||||
le32_to_cpu(ta_hdr->securedisplay.offset_bytes);
|
||||
|
||||
adev->psp.ta_fw_version = le32_to_cpu(ta_hdr->header.ucode_version);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int parse_ta_v2_microcode(struct psp_context *psp)
|
||||
{
|
||||
const struct ta_firmware_header_v2_0 *ta_hdr;
|
||||
struct amdgpu_device *adev = psp->adev;
|
||||
int err = 0;
|
||||
int ta_index = 0;
|
||||
|
||||
if (!chip_name) {
|
||||
dev_err(adev->dev, "invalid chip name for ta microcode\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_ta.bin", chip_name);
|
||||
err = request_firmware(&adev->psp.ta_fw, fw_name, adev->dev);
|
||||
if (err)
|
||||
goto out;
|
||||
|
||||
err = amdgpu_ucode_validate(adev->psp.ta_fw);
|
||||
if (err)
|
||||
goto out;
|
||||
|
||||
ta_hdr = (const struct ta_firmware_header_v2_0 *)adev->psp.ta_fw->data;
|
||||
|
||||
if (le16_to_cpu(ta_hdr->header.header_version_major) != 2) {
|
||||
dev_err(adev->dev, "unsupported TA header version\n");
|
||||
err = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
if (le16_to_cpu(ta_hdr->header.header_version_major) != 2)
|
||||
return -EINVAL;
|
||||
|
||||
if (le32_to_cpu(ta_hdr->ta_fw_bin_count) >= UCODE_MAX_PSP_PACKAGING) {
|
||||
dev_err(adev->dev, "packed TA count exceeds maximum limit\n");
|
||||
err = -EINVAL;
|
||||
goto out;
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
for (ta_index = 0; ta_index < le32_to_cpu(ta_hdr->ta_fw_bin_count); ta_index++) {
|
||||
@@ -3314,19 +3299,44 @@ int psp_init_ta_microcode(struct psp_context *psp,
|
||||
&ta_hdr->ta_fw_bin[ta_index],
|
||||
ta_hdr);
|
||||
if (err)
|
||||
goto out;
|
||||
return err;
|
||||
}
|
||||
|
||||
return 0;
|
||||
out:
|
||||
dev_err(adev->dev, "fail to initialize ta microcode\n");
|
||||
release_firmware(adev->psp.ta_fw);
|
||||
adev->psp.ta_fw = NULL;
|
||||
}
|
||||
|
||||
int psp_init_ta_microcode(struct psp_context *psp, const char *chip_name)
|
||||
{
|
||||
const struct common_firmware_header *hdr;
|
||||
struct amdgpu_device *adev = psp->adev;
|
||||
char fw_name[PSP_FW_NAME_LEN];
|
||||
int err;
|
||||
|
||||
snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_ta.bin", chip_name);
|
||||
err = amdgpu_ucode_request(adev, &adev->psp.ta_fw, fw_name);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
hdr = (const struct common_firmware_header *)adev->psp.ta_fw->data;
|
||||
switch (le16_to_cpu(hdr->header_version_major)) {
|
||||
case 1:
|
||||
err = parse_ta_v1_microcode(psp);
|
||||
break;
|
||||
case 2:
|
||||
err = parse_ta_v2_microcode(psp);
|
||||
break;
|
||||
default:
|
||||
dev_err(adev->dev, "unsupported TA header version\n");
|
||||
err = -EINVAL;
|
||||
}
|
||||
|
||||
if (err)
|
||||
amdgpu_ucode_release(&adev->psp.ta_fw);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
int psp_init_cap_microcode(struct psp_context *psp,
|
||||
const char *chip_name)
|
||||
int psp_init_cap_microcode(struct psp_context *psp, const char *chip_name)
|
||||
{
|
||||
struct amdgpu_device *adev = psp->adev;
|
||||
char fw_name[PSP_FW_NAME_LEN];
|
||||
@@ -3334,28 +3344,20 @@ int psp_init_cap_microcode(struct psp_context *psp,
|
||||
struct amdgpu_firmware_info *info = NULL;
|
||||
int err = 0;
|
||||
|
||||
if (!chip_name) {
|
||||
dev_err(adev->dev, "invalid chip name for cap microcode\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (!amdgpu_sriov_vf(adev)) {
|
||||
dev_err(adev->dev, "cap microcode should only be loaded under SRIOV\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_cap.bin", chip_name);
|
||||
err = request_firmware(&adev->psp.cap_fw, fw_name, adev->dev);
|
||||
if (err) {
|
||||
dev_warn(adev->dev, "cap microcode does not exist, skip\n");
|
||||
err = 0;
|
||||
goto out;
|
||||
}
|
||||
|
||||
err = amdgpu_ucode_validate(adev->psp.cap_fw);
|
||||
err = amdgpu_ucode_request(adev, &adev->psp.cap_fw, fw_name);
|
||||
if (err) {
|
||||
if (err == -ENODEV) {
|
||||
dev_warn(adev->dev, "cap microcode does not exist, skip\n");
|
||||
err = 0;
|
||||
goto out;
|
||||
}
|
||||
dev_err(adev->dev, "fail to initialize cap microcode\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
info = &adev->firmware.ucode[AMDGPU_UCODE_ID_CAP];
|
||||
@@ -3372,8 +3374,7 @@ int psp_init_cap_microcode(struct psp_context *psp,
|
||||
return 0;
|
||||
|
||||
out:
|
||||
release_firmware(adev->psp.cap_fw);
|
||||
adev->psp.cap_fw = NULL;
|
||||
amdgpu_ucode_release(&adev->psp.cap_fw);
|
||||
return err;
|
||||
}
|
||||
|
||||
@@ -3444,10 +3445,10 @@ static ssize_t psp_usbc_pd_fw_sysfs_write(struct device *dev,
|
||||
|
||||
/* LFB address which is aligned to 1MB boundary per PSP request */
|
||||
ret = amdgpu_bo_create_kernel(adev, usbc_pd_fw->size, 0x100000,
|
||||
AMDGPU_GEM_DOMAIN_VRAM,
|
||||
&fw_buf_bo,
|
||||
&fw_pri_mc_addr,
|
||||
&fw_pri_cpu_addr);
|
||||
AMDGPU_GEM_DOMAIN_VRAM |
|
||||
AMDGPU_GEM_DOMAIN_GTT,
|
||||
&fw_buf_bo, &fw_pri_mc_addr,
|
||||
&fw_pri_cpu_addr);
|
||||
if (ret)
|
||||
goto rel_buf;
|
||||
|
||||
|
||||
@@ -706,13 +706,23 @@ static int __amdgpu_ras_feature_enable(struct amdgpu_device *adev,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int amdgpu_ras_check_feature_allowed(struct amdgpu_device *adev,
|
||||
struct ras_common_if *head)
|
||||
{
|
||||
if (amdgpu_ras_is_feature_allowed(adev, head) ||
|
||||
amdgpu_ras_is_poison_mode_supported(adev))
|
||||
return 1;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* wrapper of psp_ras_enable_features */
|
||||
int amdgpu_ras_feature_enable(struct amdgpu_device *adev,
|
||||
struct ras_common_if *head, bool enable)
|
||||
{
|
||||
struct amdgpu_ras *con = amdgpu_ras_get_context(adev);
|
||||
union ta_ras_cmd_input *info;
|
||||
int ret;
|
||||
int ret = 0;
|
||||
|
||||
if (!con)
|
||||
return -EINVAL;
|
||||
@@ -736,7 +746,8 @@ int amdgpu_ras_feature_enable(struct amdgpu_device *adev,
|
||||
}
|
||||
|
||||
/* Do not enable if it is not allowed. */
|
||||
WARN_ON(enable && !amdgpu_ras_is_feature_allowed(adev, head));
|
||||
if (enable && !amdgpu_ras_check_feature_allowed(adev, head))
|
||||
goto out;
|
||||
|
||||
/* Only enable ras feature operation handle on host side */
|
||||
if (head->block == AMDGPU_RAS_BLOCK__GFX &&
|
||||
@@ -754,7 +765,6 @@ int amdgpu_ras_feature_enable(struct amdgpu_device *adev,
|
||||
|
||||
/* setup the obj */
|
||||
__amdgpu_ras_feature_enable(adev, head, enable);
|
||||
ret = 0;
|
||||
out:
|
||||
if (head->block == AMDGPU_RAS_BLOCK__GFX)
|
||||
kfree(info);
|
||||
@@ -1087,6 +1097,10 @@ int amdgpu_ras_error_inject(struct amdgpu_device *adev,
|
||||
info->head.block,
|
||||
info->head.sub_block_index);
|
||||
|
||||
/* inject on guest isn't allowed, return success directly */
|
||||
if (amdgpu_sriov_vf(adev))
|
||||
return 0;
|
||||
|
||||
if (!obj)
|
||||
return -EINVAL;
|
||||
|
||||
@@ -1122,11 +1136,54 @@ int amdgpu_ras_error_inject(struct amdgpu_device *adev,
|
||||
}
|
||||
|
||||
/**
|
||||
* amdgpu_ras_query_error_count -- Get error counts of all IPs
|
||||
* amdgpu_ras_query_error_count_helper -- Get error counter for specific IP
|
||||
* @adev: pointer to AMD GPU device
|
||||
* @ce_count: pointer to an integer to be set to the count of correctible errors.
|
||||
* @ue_count: pointer to an integer to be set to the count of uncorrectible errors.
|
||||
* @query_info: pointer to ras_query_if
|
||||
*
|
||||
* Return 0 for query success or do nothing, otherwise return an error
|
||||
* on failures
|
||||
*/
|
||||
static int amdgpu_ras_query_error_count_helper(struct amdgpu_device *adev,
|
||||
unsigned long *ce_count,
|
||||
unsigned long *ue_count,
|
||||
struct ras_query_if *query_info)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (!query_info)
|
||||
/* do nothing if query_info is not specified */
|
||||
return 0;
|
||||
|
||||
ret = amdgpu_ras_query_error_status(adev, query_info);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
*ce_count += query_info->ce_count;
|
||||
*ue_count += query_info->ue_count;
|
||||
|
||||
/* some hardware/IP supports read to clear
|
||||
* no need to explictly reset the err status after the query call */
|
||||
if (adev->ip_versions[MP0_HWIP][0] != IP_VERSION(11, 0, 2) &&
|
||||
adev->ip_versions[MP0_HWIP][0] != IP_VERSION(11, 0, 4)) {
|
||||
if (amdgpu_ras_reset_error_status(adev, query_info->head.block))
|
||||
dev_warn(adev->dev,
|
||||
"Failed to reset error counter and error status\n");
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* amdgpu_ras_query_error_count -- Get error counts of all IPs or specific IP
|
||||
* @adev: pointer to AMD GPU device
|
||||
* @ce_count: pointer to an integer to be set to the count of correctible errors.
|
||||
* @ue_count: pointer to an integer to be set to the count of uncorrectible
|
||||
* errors.
|
||||
* @query_info: pointer to ras_query_if if the query request is only for
|
||||
* specific ip block; if info is NULL, then the qurey request is for
|
||||
* all the ip blocks that support query ras error counters/status
|
||||
*
|
||||
* If set, @ce_count or @ue_count, count and return the corresponding
|
||||
* error counts in those integer pointers. Return 0 if the device
|
||||
@@ -1134,11 +1191,13 @@ int amdgpu_ras_error_inject(struct amdgpu_device *adev,
|
||||
*/
|
||||
int amdgpu_ras_query_error_count(struct amdgpu_device *adev,
|
||||
unsigned long *ce_count,
|
||||
unsigned long *ue_count)
|
||||
unsigned long *ue_count,
|
||||
struct ras_query_if *query_info)
|
||||
{
|
||||
struct amdgpu_ras *con = amdgpu_ras_get_context(adev);
|
||||
struct ras_manager *obj;
|
||||
unsigned long ce, ue;
|
||||
int ret;
|
||||
|
||||
if (!adev->ras_enabled || !con)
|
||||
return -EOPNOTSUPP;
|
||||
@@ -1150,26 +1209,23 @@ int amdgpu_ras_query_error_count(struct amdgpu_device *adev,
|
||||
|
||||
ce = 0;
|
||||
ue = 0;
|
||||
list_for_each_entry(obj, &con->head, node) {
|
||||
struct ras_query_if info = {
|
||||
.head = obj->head,
|
||||
};
|
||||
int res;
|
||||
if (!query_info) {
|
||||
/* query all the ip blocks that support ras query interface */
|
||||
list_for_each_entry(obj, &con->head, node) {
|
||||
struct ras_query_if info = {
|
||||
.head = obj->head,
|
||||
};
|
||||
|
||||
res = amdgpu_ras_query_error_status(adev, &info);
|
||||
if (res)
|
||||
return res;
|
||||
|
||||
if (adev->ip_versions[MP0_HWIP][0] != IP_VERSION(11, 0, 2) &&
|
||||
adev->ip_versions[MP0_HWIP][0] != IP_VERSION(11, 0, 4)) {
|
||||
if (amdgpu_ras_reset_error_status(adev, info.head.block))
|
||||
dev_warn(adev->dev, "Failed to reset error counter and error status");
|
||||
ret = amdgpu_ras_query_error_count_helper(adev, &ce, &ue, &info);
|
||||
}
|
||||
|
||||
ce += info.ce_count;
|
||||
ue += info.ue_count;
|
||||
} else {
|
||||
/* query specific ip block */
|
||||
ret = amdgpu_ras_query_error_count_helper(adev, &ce, &ue, query_info);
|
||||
}
|
||||
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (ce_count)
|
||||
*ce_count = ce;
|
||||
|
||||
@@ -2344,22 +2400,24 @@ static void amdgpu_ras_check_supported(struct amdgpu_device *adev)
|
||||
|
||||
if (amdgpu_atomfirmware_sram_ecc_supported(adev)) {
|
||||
dev_info(adev->dev, "SRAM ECC is active.\n");
|
||||
if (!amdgpu_sriov_vf(adev)) {
|
||||
if (!amdgpu_sriov_vf(adev))
|
||||
adev->ras_hw_enabled |= ~(1 << AMDGPU_RAS_BLOCK__UMC |
|
||||
1 << AMDGPU_RAS_BLOCK__DF);
|
||||
|
||||
if (adev->ip_versions[VCN_HWIP][0] == IP_VERSION(2, 6, 0) ||
|
||||
adev->ip_versions[VCN_HWIP][0] == IP_VERSION(4, 0, 0))
|
||||
adev->ras_hw_enabled |= (1 << AMDGPU_RAS_BLOCK__VCN |
|
||||
1 << AMDGPU_RAS_BLOCK__JPEG);
|
||||
else
|
||||
adev->ras_hw_enabled &= ~(1 << AMDGPU_RAS_BLOCK__VCN |
|
||||
1 << AMDGPU_RAS_BLOCK__JPEG);
|
||||
} else {
|
||||
else
|
||||
adev->ras_hw_enabled |= (1 << AMDGPU_RAS_BLOCK__PCIE_BIF |
|
||||
1 << AMDGPU_RAS_BLOCK__SDMA |
|
||||
1 << AMDGPU_RAS_BLOCK__GFX);
|
||||
}
|
||||
|
||||
/* VCN/JPEG RAS can be supported on both bare metal and
|
||||
* SRIOV environment
|
||||
*/
|
||||
if (adev->ip_versions[VCN_HWIP][0] == IP_VERSION(2, 6, 0) ||
|
||||
adev->ip_versions[VCN_HWIP][0] == IP_VERSION(4, 0, 0))
|
||||
adev->ras_hw_enabled |= (1 << AMDGPU_RAS_BLOCK__VCN |
|
||||
1 << AMDGPU_RAS_BLOCK__JPEG);
|
||||
else
|
||||
adev->ras_hw_enabled &= ~(1 << AMDGPU_RAS_BLOCK__VCN |
|
||||
1 << AMDGPU_RAS_BLOCK__JPEG);
|
||||
} else {
|
||||
dev_info(adev->dev, "SRAM ECC is not presented.\n");
|
||||
}
|
||||
@@ -2395,7 +2453,7 @@ static void amdgpu_ras_counte_dw(struct work_struct *work)
|
||||
|
||||
/* Cache new values.
|
||||
*/
|
||||
if (amdgpu_ras_query_error_count(adev, &ce_count, &ue_count) == 0) {
|
||||
if (amdgpu_ras_query_error_count(adev, &ce_count, &ue_count, NULL) == 0) {
|
||||
atomic_set(&con->ras_ce_count, ce_count);
|
||||
atomic_set(&con->ras_ue_count, ue_count);
|
||||
}
|
||||
@@ -2405,11 +2463,42 @@ static void amdgpu_ras_counte_dw(struct work_struct *work)
|
||||
pm_runtime_put_autosuspend(dev->dev);
|
||||
}
|
||||
|
||||
static void amdgpu_ras_query_poison_mode(struct amdgpu_device *adev)
|
||||
{
|
||||
struct amdgpu_ras *con = amdgpu_ras_get_context(adev);
|
||||
bool df_poison, umc_poison;
|
||||
|
||||
/* poison setting is useless on SRIOV guest */
|
||||
if (amdgpu_sriov_vf(adev) || !con)
|
||||
return;
|
||||
|
||||
/* Init poison supported flag, the default value is false */
|
||||
if (adev->gmc.xgmi.connected_to_cpu) {
|
||||
/* enabled by default when GPU is connected to CPU */
|
||||
con->poison_supported = true;
|
||||
} else if (adev->df.funcs &&
|
||||
adev->df.funcs->query_ras_poison_mode &&
|
||||
adev->umc.ras &&
|
||||
adev->umc.ras->query_ras_poison_mode) {
|
||||
df_poison =
|
||||
adev->df.funcs->query_ras_poison_mode(adev);
|
||||
umc_poison =
|
||||
adev->umc.ras->query_ras_poison_mode(adev);
|
||||
|
||||
/* Only poison is set in both DF and UMC, we can support it */
|
||||
if (df_poison && umc_poison)
|
||||
con->poison_supported = true;
|
||||
else if (df_poison != umc_poison)
|
||||
dev_warn(adev->dev,
|
||||
"Poison setting is inconsistent in DF/UMC(%d:%d)!\n",
|
||||
df_poison, umc_poison);
|
||||
}
|
||||
}
|
||||
|
||||
int amdgpu_ras_init(struct amdgpu_device *adev)
|
||||
{
|
||||
struct amdgpu_ras *con = amdgpu_ras_get_context(adev);
|
||||
int r;
|
||||
bool df_poison, umc_poison;
|
||||
|
||||
if (con)
|
||||
return 0;
|
||||
@@ -2484,26 +2573,7 @@ int amdgpu_ras_init(struct amdgpu_device *adev)
|
||||
goto release_con;
|
||||
}
|
||||
|
||||
/* Init poison supported flag, the default value is false */
|
||||
if (adev->gmc.xgmi.connected_to_cpu) {
|
||||
/* enabled by default when GPU is connected to CPU */
|
||||
con->poison_supported = true;
|
||||
}
|
||||
else if (adev->df.funcs &&
|
||||
adev->df.funcs->query_ras_poison_mode &&
|
||||
adev->umc.ras &&
|
||||
adev->umc.ras->query_ras_poison_mode) {
|
||||
df_poison =
|
||||
adev->df.funcs->query_ras_poison_mode(adev);
|
||||
umc_poison =
|
||||
adev->umc.ras->query_ras_poison_mode(adev);
|
||||
/* Only poison is set in both DF and UMC, we can support it */
|
||||
if (df_poison && umc_poison)
|
||||
con->poison_supported = true;
|
||||
else if (df_poison != umc_poison)
|
||||
dev_warn(adev->dev, "Poison setting is inconsistent in DF/UMC(%d:%d)!\n",
|
||||
df_poison, umc_poison);
|
||||
}
|
||||
amdgpu_ras_query_poison_mode(adev);
|
||||
|
||||
if (amdgpu_ras_fs_init(adev)) {
|
||||
r = -EINVAL;
|
||||
@@ -2564,6 +2634,7 @@ int amdgpu_ras_block_late_init(struct amdgpu_device *adev,
|
||||
{
|
||||
struct amdgpu_ras_block_object *ras_obj = NULL;
|
||||
struct amdgpu_ras *con = amdgpu_ras_get_context(adev);
|
||||
struct ras_query_if *query_info;
|
||||
unsigned long ue_count, ce_count;
|
||||
int r;
|
||||
|
||||
@@ -2605,11 +2676,17 @@ int amdgpu_ras_block_late_init(struct amdgpu_device *adev,
|
||||
|
||||
/* Those are the cached values at init.
|
||||
*/
|
||||
if (amdgpu_ras_query_error_count(adev, &ce_count, &ue_count) == 0) {
|
||||
query_info = kzalloc(sizeof(struct ras_query_if), GFP_KERNEL);
|
||||
if (!query_info)
|
||||
return -ENOMEM;
|
||||
memcpy(&query_info->head, ras_block, sizeof(struct ras_common_if));
|
||||
|
||||
if (amdgpu_ras_query_error_count(adev, &ce_count, &ue_count, query_info) == 0) {
|
||||
atomic_set(&con->ras_ce_count, ce_count);
|
||||
atomic_set(&con->ras_ue_count, ue_count);
|
||||
}
|
||||
|
||||
kfree(query_info);
|
||||
return 0;
|
||||
|
||||
interrupt:
|
||||
|
||||
@@ -540,7 +540,8 @@ void amdgpu_ras_suspend(struct amdgpu_device *adev);
|
||||
|
||||
int amdgpu_ras_query_error_count(struct amdgpu_device *adev,
|
||||
unsigned long *ce_count,
|
||||
unsigned long *ue_count);
|
||||
unsigned long *ue_count,
|
||||
struct ras_query_if *query_info);
|
||||
|
||||
/* error handling functions */
|
||||
int amdgpu_ras_add_bad_pages(struct amdgpu_device *adev,
|
||||
|
||||
@@ -93,7 +93,8 @@ int amdgpu_gfx_rlc_init_sr(struct amdgpu_device *adev, u32 dws)
|
||||
|
||||
/* allocate save restore block */
|
||||
r = amdgpu_bo_create_reserved(adev, dws * 4, PAGE_SIZE,
|
||||
AMDGPU_GEM_DOMAIN_VRAM,
|
||||
AMDGPU_GEM_DOMAIN_VRAM |
|
||||
AMDGPU_GEM_DOMAIN_GTT,
|
||||
&adev->gfx.rlc.save_restore_obj,
|
||||
&adev->gfx.rlc.save_restore_gpu_addr,
|
||||
(void **)&adev->gfx.rlc.sr_ptr);
|
||||
@@ -130,7 +131,8 @@ int amdgpu_gfx_rlc_init_csb(struct amdgpu_device *adev)
|
||||
/* allocate clear state block */
|
||||
adev->gfx.rlc.clear_state_size = dws = adev->gfx.rlc.funcs->get_csb_size(adev);
|
||||
r = amdgpu_bo_create_kernel(adev, dws * 4, PAGE_SIZE,
|
||||
AMDGPU_GEM_DOMAIN_VRAM,
|
||||
AMDGPU_GEM_DOMAIN_VRAM |
|
||||
AMDGPU_GEM_DOMAIN_GTT,
|
||||
&adev->gfx.rlc.clear_state_obj,
|
||||
&adev->gfx.rlc.clear_state_gpu_addr,
|
||||
(void **)&adev->gfx.rlc.cs_ptr);
|
||||
@@ -156,7 +158,8 @@ int amdgpu_gfx_rlc_init_cpt(struct amdgpu_device *adev)
|
||||
int r;
|
||||
|
||||
r = amdgpu_bo_create_reserved(adev, adev->gfx.rlc.cp_table_size,
|
||||
PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM,
|
||||
PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM |
|
||||
AMDGPU_GEM_DOMAIN_GTT,
|
||||
&adev->gfx.rlc.cp_table_obj,
|
||||
&adev->gfx.rlc.cp_table_gpu_addr,
|
||||
(void **)&adev->gfx.rlc.cp_table_ptr);
|
||||
|
||||
@@ -154,16 +154,11 @@ int amdgpu_sdma_process_ecc_irq(struct amdgpu_device *adev,
|
||||
|
||||
static int amdgpu_sdma_init_inst_ctx(struct amdgpu_sdma_instance *sdma_inst)
|
||||
{
|
||||
int err = 0;
|
||||
uint16_t version_major;
|
||||
const struct common_firmware_header *header = NULL;
|
||||
const struct sdma_firmware_header_v1_0 *hdr;
|
||||
const struct sdma_firmware_header_v2_0 *hdr_v2;
|
||||
|
||||
err = amdgpu_ucode_validate(sdma_inst->fw);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
header = (const struct common_firmware_header *)
|
||||
sdma_inst->fw->data;
|
||||
version_major = le16_to_cpu(header->header_version_major);
|
||||
@@ -195,7 +190,7 @@ void amdgpu_sdma_destroy_inst_ctx(struct amdgpu_device *adev,
|
||||
int i;
|
||||
|
||||
for (i = 0; i < adev->sdma.num_instances; i++) {
|
||||
release_firmware(adev->sdma.instance[i].fw);
|
||||
amdgpu_ucode_release(&adev->sdma.instance[i].fw);
|
||||
if (duplicate)
|
||||
break;
|
||||
}
|
||||
@@ -205,16 +200,22 @@ void amdgpu_sdma_destroy_inst_ctx(struct amdgpu_device *adev,
|
||||
}
|
||||
|
||||
int amdgpu_sdma_init_microcode(struct amdgpu_device *adev,
|
||||
char *fw_name, u32 instance,
|
||||
bool duplicate)
|
||||
u32 instance, bool duplicate)
|
||||
{
|
||||
struct amdgpu_firmware_info *info = NULL;
|
||||
const struct common_firmware_header *header = NULL;
|
||||
int err = 0, i;
|
||||
int err, i;
|
||||
const struct sdma_firmware_header_v2_0 *sdma_hdr;
|
||||
uint16_t version_major;
|
||||
char ucode_prefix[30];
|
||||
char fw_name[40];
|
||||
|
||||
err = request_firmware(&adev->sdma.instance[instance].fw, fw_name, adev->dev);
|
||||
amdgpu_ucode_ip_version_decode(adev, SDMA0_HWIP, ucode_prefix, sizeof(ucode_prefix));
|
||||
if (instance == 0)
|
||||
snprintf(fw_name, sizeof(fw_name), "amdgpu/%s.bin", ucode_prefix);
|
||||
else
|
||||
snprintf(fw_name, sizeof(fw_name), "amdgpu/%s%d.bin", ucode_prefix, instance);
|
||||
err = amdgpu_ucode_request(adev, &adev->sdma.instance[instance].fw, fw_name);
|
||||
if (err)
|
||||
goto out;
|
||||
|
||||
@@ -279,10 +280,8 @@ int amdgpu_sdma_init_microcode(struct amdgpu_device *adev,
|
||||
}
|
||||
|
||||
out:
|
||||
if (err) {
|
||||
DRM_ERROR("SDMA: Failed to init firmware \"%s\"\n", fw_name);
|
||||
if (err)
|
||||
amdgpu_sdma_destroy_inst_ctx(adev, duplicate);
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
@@ -124,8 +124,8 @@ int amdgpu_sdma_process_ras_data_cb(struct amdgpu_device *adev,
|
||||
int amdgpu_sdma_process_ecc_irq(struct amdgpu_device *adev,
|
||||
struct amdgpu_irq_src *source,
|
||||
struct amdgpu_iv_entry *entry);
|
||||
int amdgpu_sdma_init_microcode(struct amdgpu_device *adev,
|
||||
char *fw_name, u32 instance, bool duplicate);
|
||||
int amdgpu_sdma_init_microcode(struct amdgpu_device *adev, u32 instance,
|
||||
bool duplicate);
|
||||
void amdgpu_sdma_destroy_inst_ctx(struct amdgpu_device *adev,
|
||||
bool duplicate);
|
||||
void amdgpu_sdma_unset_buffer_funcs_helper(struct amdgpu_device *adev);
|
||||
|
||||
@@ -77,11 +77,11 @@ void psp_securedisplay_parse_resp_status(struct psp_context *psp,
|
||||
}
|
||||
}
|
||||
|
||||
void psp_prep_securedisplay_cmd_buf(struct psp_context *psp, struct securedisplay_cmd **cmd,
|
||||
void psp_prep_securedisplay_cmd_buf(struct psp_context *psp, struct ta_securedisplay_cmd **cmd,
|
||||
enum ta_securedisplay_command command_id)
|
||||
{
|
||||
*cmd = (struct securedisplay_cmd *)psp->securedisplay_context.context.mem_context.shared_buf;
|
||||
memset(*cmd, 0, sizeof(struct securedisplay_cmd));
|
||||
*cmd = (struct ta_securedisplay_cmd *)psp->securedisplay_context.context.mem_context.shared_buf;
|
||||
memset(*cmd, 0, sizeof(struct ta_securedisplay_cmd));
|
||||
(*cmd)->status = TA_SECUREDISPLAY_STATUS__GENERIC_FAILURE;
|
||||
(*cmd)->cmd_id = command_id;
|
||||
}
|
||||
@@ -93,7 +93,7 @@ static ssize_t amdgpu_securedisplay_debugfs_write(struct file *f, const char __u
|
||||
{
|
||||
struct amdgpu_device *adev = (struct amdgpu_device *)file_inode(f)->i_private;
|
||||
struct psp_context *psp = &adev->psp;
|
||||
struct securedisplay_cmd *securedisplay_cmd;
|
||||
struct ta_securedisplay_cmd *securedisplay_cmd;
|
||||
struct drm_device *dev = adev_to_drm(adev);
|
||||
uint32_t phy_id;
|
||||
uint32_t op;
|
||||
|
||||
@@ -30,7 +30,7 @@
|
||||
void amdgpu_securedisplay_debugfs_init(struct amdgpu_device *adev);
|
||||
void psp_securedisplay_parse_resp_status(struct psp_context *psp,
|
||||
enum ta_securedisplay_status status);
|
||||
void psp_prep_securedisplay_cmd_buf(struct psp_context *psp, struct securedisplay_cmd **cmd,
|
||||
void psp_prep_securedisplay_cmd_buf(struct psp_context *psp, struct ta_securedisplay_cmd **cmd,
|
||||
enum ta_securedisplay_command command_id);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -44,10 +44,10 @@
|
||||
#include <linux/module.h>
|
||||
|
||||
#include <drm/drm_drv.h>
|
||||
#include <drm/ttm/ttm_bo_api.h>
|
||||
#include <drm/ttm/ttm_bo_driver.h>
|
||||
#include <drm/ttm/ttm_bo.h>
|
||||
#include <drm/ttm/ttm_placement.h>
|
||||
#include <drm/ttm/ttm_range_manager.h>
|
||||
#include <drm/ttm/ttm_tt.h>
|
||||
|
||||
#include <drm/amdgpu_drm.h>
|
||||
#include <drm/drm_drv.h>
|
||||
@@ -1679,10 +1679,10 @@ static int amdgpu_ttm_reserve_tmr(struct amdgpu_device *adev)
|
||||
/* reserve vram for mem train according to TMR location */
|
||||
amdgpu_ttm_training_data_block_init(adev);
|
||||
ret = amdgpu_bo_create_kernel_at(adev,
|
||||
ctx->c2p_train_data_offset,
|
||||
ctx->train_data_size,
|
||||
&ctx->c2p_bo,
|
||||
NULL);
|
||||
ctx->c2p_train_data_offset,
|
||||
ctx->train_data_size,
|
||||
&ctx->c2p_bo,
|
||||
NULL);
|
||||
if (ret) {
|
||||
DRM_ERROR("alloc c2p_bo failed(%d)!\n", ret);
|
||||
amdgpu_ttm_training_reserve_vram_fini(adev);
|
||||
@@ -1692,10 +1692,10 @@ static int amdgpu_ttm_reserve_tmr(struct amdgpu_device *adev)
|
||||
}
|
||||
|
||||
ret = amdgpu_bo_create_kernel_at(adev,
|
||||
adev->gmc.real_vram_size - adev->mman.discovery_tmr_size,
|
||||
adev->mman.discovery_tmr_size,
|
||||
&adev->mman.discovery_memory,
|
||||
NULL);
|
||||
adev->gmc.real_vram_size - adev->mman.discovery_tmr_size,
|
||||
adev->mman.discovery_tmr_size,
|
||||
&adev->mman.discovery_memory,
|
||||
NULL);
|
||||
if (ret) {
|
||||
DRM_ERROR("alloc tmr failed(%d)!\n", ret);
|
||||
amdgpu_bo_free_kernel(&adev->mman.discovery_memory, NULL, NULL);
|
||||
@@ -1718,7 +1718,6 @@ int amdgpu_ttm_init(struct amdgpu_device *adev)
|
||||
{
|
||||
uint64_t gtt_size;
|
||||
int r;
|
||||
u64 vis_vram_limit;
|
||||
|
||||
mutex_init(&adev->mman.gtt_window_lock);
|
||||
|
||||
@@ -1741,12 +1740,6 @@ int amdgpu_ttm_init(struct amdgpu_device *adev)
|
||||
return r;
|
||||
}
|
||||
|
||||
/* Reduce size of CPU-visible VRAM if requested */
|
||||
vis_vram_limit = (u64)amdgpu_vis_vram_limit * 1024 * 1024;
|
||||
if (amdgpu_vis_vram_limit > 0 &&
|
||||
vis_vram_limit <= adev->gmc.visible_vram_size)
|
||||
adev->gmc.visible_vram_size = vis_vram_limit;
|
||||
|
||||
/* Change the size here instead of the init above so only lpfn is affected */
|
||||
amdgpu_ttm_set_buffer_funcs_status(adev, false);
|
||||
#ifdef CONFIG_64BIT
|
||||
|
||||
@@ -504,7 +504,7 @@ void amdgpu_ucode_print_gpu_info_hdr(const struct common_firmware_header *hdr)
|
||||
}
|
||||
}
|
||||
|
||||
int amdgpu_ucode_validate(const struct firmware *fw)
|
||||
static int amdgpu_ucode_validate(const struct firmware *fw)
|
||||
{
|
||||
const struct common_firmware_header *hdr =
|
||||
(const struct common_firmware_header *)fw->data;
|
||||
@@ -1059,12 +1059,233 @@ int amdgpu_ucode_init_bo(struct amdgpu_device *adev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const char *amdgpu_ucode_legacy_naming(struct amdgpu_device *adev, int block_type)
|
||||
{
|
||||
if (block_type == MP0_HWIP) {
|
||||
switch (adev->ip_versions[MP0_HWIP][0]) {
|
||||
case IP_VERSION(9, 0, 0):
|
||||
switch (adev->asic_type) {
|
||||
case CHIP_VEGA10:
|
||||
return "vega10";
|
||||
case CHIP_VEGA12:
|
||||
return "vega12";
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
break;
|
||||
case IP_VERSION(10, 0, 0):
|
||||
case IP_VERSION(10, 0, 1):
|
||||
if (adev->asic_type == CHIP_RAVEN) {
|
||||
if (adev->apu_flags & AMD_APU_IS_RAVEN2)
|
||||
return "raven2";
|
||||
else if (adev->apu_flags & AMD_APU_IS_PICASSO)
|
||||
return "picasso";
|
||||
return "raven";
|
||||
}
|
||||
break;
|
||||
case IP_VERSION(11, 0, 0):
|
||||
return "navi10";
|
||||
case IP_VERSION(11, 0, 2):
|
||||
return "vega20";
|
||||
case IP_VERSION(11, 0, 4):
|
||||
return "arcturus";
|
||||
case IP_VERSION(11, 0, 5):
|
||||
return "navi14";
|
||||
case IP_VERSION(11, 0, 7):
|
||||
return "sienna_cichlid";
|
||||
case IP_VERSION(11, 0, 9):
|
||||
return "navi12";
|
||||
case IP_VERSION(11, 0, 11):
|
||||
return "navy_flounder";
|
||||
case IP_VERSION(11, 0, 12):
|
||||
return "dimgrey_cavefish";
|
||||
case IP_VERSION(11, 0, 13):
|
||||
return "beige_goby";
|
||||
case IP_VERSION(11, 5, 0):
|
||||
return "vangogh";
|
||||
case IP_VERSION(12, 0, 1):
|
||||
if (adev->asic_type == CHIP_RENOIR) {
|
||||
if (adev->apu_flags & AMD_APU_IS_RENOIR)
|
||||
return "renoir";
|
||||
return "green_sardine";
|
||||
}
|
||||
break;
|
||||
case IP_VERSION(13, 0, 2):
|
||||
return "aldebaran";
|
||||
case IP_VERSION(13, 0, 1):
|
||||
case IP_VERSION(13, 0, 3):
|
||||
return "yellow_carp";
|
||||
}
|
||||
} else if (block_type == MP1_HWIP) {
|
||||
switch (adev->ip_versions[MP1_HWIP][0]) {
|
||||
case IP_VERSION(9, 0, 0):
|
||||
case IP_VERSION(10, 0, 0):
|
||||
case IP_VERSION(10, 0, 1):
|
||||
case IP_VERSION(11, 0, 2):
|
||||
if (adev->asic_type == CHIP_ARCTURUS)
|
||||
return "arcturus_smc";
|
||||
return NULL;
|
||||
case IP_VERSION(11, 0, 0):
|
||||
return "navi10_smc";
|
||||
case IP_VERSION(11, 0, 5):
|
||||
return "navi14_smc";
|
||||
case IP_VERSION(11, 0, 9):
|
||||
return "navi12_smc";
|
||||
case IP_VERSION(11, 0, 7):
|
||||
return "sienna_cichlid_smc";
|
||||
case IP_VERSION(11, 0, 11):
|
||||
return "navy_flounder_smc";
|
||||
case IP_VERSION(11, 0, 12):
|
||||
return "dimgrey_cavefish_smc";
|
||||
case IP_VERSION(11, 0, 13):
|
||||
return "beige_goby_smc";
|
||||
case IP_VERSION(13, 0, 2):
|
||||
return "aldebaran_smc";
|
||||
}
|
||||
} else if (block_type == SDMA0_HWIP) {
|
||||
switch (adev->ip_versions[SDMA0_HWIP][0]) {
|
||||
case IP_VERSION(4, 0, 0):
|
||||
return "vega10_sdma";
|
||||
case IP_VERSION(4, 0, 1):
|
||||
return "vega12_sdma";
|
||||
case IP_VERSION(4, 1, 0):
|
||||
case IP_VERSION(4, 1, 1):
|
||||
if (adev->apu_flags & AMD_APU_IS_RAVEN2)
|
||||
return "raven2_sdma";
|
||||
else if (adev->apu_flags & AMD_APU_IS_PICASSO)
|
||||
return "picasso_sdma";
|
||||
return "raven_sdma";
|
||||
case IP_VERSION(4, 1, 2):
|
||||
if (adev->apu_flags & AMD_APU_IS_RENOIR)
|
||||
return "renoir_sdma";
|
||||
return "green_sardine_sdma";
|
||||
case IP_VERSION(4, 2, 0):
|
||||
return "vega20_sdma";
|
||||
case IP_VERSION(4, 2, 2):
|
||||
return "arcturus_sdma";
|
||||
case IP_VERSION(4, 4, 0):
|
||||
return "aldebaran_sdma";
|
||||
case IP_VERSION(5, 0, 0):
|
||||
return "navi10_sdma";
|
||||
case IP_VERSION(5, 0, 1):
|
||||
return "cyan_skillfish2_sdma";
|
||||
case IP_VERSION(5, 0, 2):
|
||||
return "navi14_sdma";
|
||||
case IP_VERSION(5, 0, 5):
|
||||
return "navi12_sdma";
|
||||
case IP_VERSION(5, 2, 0):
|
||||
return "sienna_cichlid_sdma";
|
||||
case IP_VERSION(5, 2, 2):
|
||||
return "navy_flounder_sdma";
|
||||
case IP_VERSION(5, 2, 4):
|
||||
return "dimgrey_cavefish_sdma";
|
||||
case IP_VERSION(5, 2, 5):
|
||||
return "beige_goby_sdma";
|
||||
case IP_VERSION(5, 2, 3):
|
||||
return "yellow_carp_sdma";
|
||||
case IP_VERSION(5, 2, 1):
|
||||
return "vangogh_sdma";
|
||||
}
|
||||
} else if (block_type == UVD_HWIP) {
|
||||
switch (adev->ip_versions[UVD_HWIP][0]) {
|
||||
case IP_VERSION(1, 0, 0):
|
||||
case IP_VERSION(1, 0, 1):
|
||||
if (adev->apu_flags & AMD_APU_IS_RAVEN2)
|
||||
return "raven2_vcn";
|
||||
else if (adev->apu_flags & AMD_APU_IS_PICASSO)
|
||||
return "picasso_vcn";
|
||||
return "raven_vcn";
|
||||
case IP_VERSION(2, 5, 0):
|
||||
return "arcturus_vcn";
|
||||
case IP_VERSION(2, 2, 0):
|
||||
if (adev->apu_flags & AMD_APU_IS_RENOIR)
|
||||
return "renoir_vcn";
|
||||
return "green_sardine_vcn";
|
||||
case IP_VERSION(2, 6, 0):
|
||||
return "aldebaran_vcn";
|
||||
case IP_VERSION(2, 0, 0):
|
||||
return "navi10_vcn";
|
||||
case IP_VERSION(2, 0, 2):
|
||||
if (adev->asic_type == CHIP_NAVI12)
|
||||
return "navi12_vcn";
|
||||
return "navi14_vcn";
|
||||
case IP_VERSION(3, 0, 0):
|
||||
case IP_VERSION(3, 0, 64):
|
||||
case IP_VERSION(3, 0, 192):
|
||||
if (adev->ip_versions[GC_HWIP][0] == IP_VERSION(10, 3, 0))
|
||||
return "sienna_cichlid_vcn";
|
||||
return "navy_flounder_vcn";
|
||||
case IP_VERSION(3, 0, 2):
|
||||
return "vangogh_vcn";
|
||||
case IP_VERSION(3, 0, 16):
|
||||
return "dimgrey_cavefish_vcn";
|
||||
case IP_VERSION(3, 0, 33):
|
||||
return "beige_goby_vcn";
|
||||
case IP_VERSION(3, 1, 1):
|
||||
return "yellow_carp_vcn";
|
||||
}
|
||||
} else if (block_type == GC_HWIP) {
|
||||
switch (adev->ip_versions[GC_HWIP][0]) {
|
||||
case IP_VERSION(9, 0, 1):
|
||||
return "vega10";
|
||||
case IP_VERSION(9, 2, 1):
|
||||
return "vega12";
|
||||
case IP_VERSION(9, 4, 0):
|
||||
return "vega20";
|
||||
case IP_VERSION(9, 2, 2):
|
||||
case IP_VERSION(9, 1, 0):
|
||||
if (adev->apu_flags & AMD_APU_IS_RAVEN2)
|
||||
return "raven2";
|
||||
else if (adev->apu_flags & AMD_APU_IS_PICASSO)
|
||||
return "picasso";
|
||||
return "raven";
|
||||
case IP_VERSION(9, 4, 1):
|
||||
return "arcturus";
|
||||
case IP_VERSION(9, 3, 0):
|
||||
if (adev->apu_flags & AMD_APU_IS_RENOIR)
|
||||
return "renoir";
|
||||
return "green_sardine";
|
||||
case IP_VERSION(9, 4, 2):
|
||||
return "aldebaran";
|
||||
case IP_VERSION(10, 1, 10):
|
||||
return "navi10";
|
||||
case IP_VERSION(10, 1, 1):
|
||||
return "navi14";
|
||||
case IP_VERSION(10, 1, 2):
|
||||
return "navi12";
|
||||
case IP_VERSION(10, 3, 0):
|
||||
return "sienna_cichlid";
|
||||
case IP_VERSION(10, 3, 2):
|
||||
return "navy_flounder";
|
||||
case IP_VERSION(10, 3, 1):
|
||||
return "vangogh";
|
||||
case IP_VERSION(10, 3, 4):
|
||||
return "dimgrey_cavefish";
|
||||
case IP_VERSION(10, 3, 5):
|
||||
return "beige_goby";
|
||||
case IP_VERSION(10, 3, 3):
|
||||
return "yellow_carp";
|
||||
case IP_VERSION(10, 1, 3):
|
||||
case IP_VERSION(10, 1, 4):
|
||||
return "cyan_skillfish2";
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void amdgpu_ucode_ip_version_decode(struct amdgpu_device *adev, int block_type, char *ucode_prefix, int len)
|
||||
{
|
||||
int maj, min, rev;
|
||||
char *ip_name;
|
||||
const char *legacy;
|
||||
uint32_t version = adev->ip_versions[block_type][0];
|
||||
|
||||
legacy = amdgpu_ucode_legacy_naming(adev, block_type);
|
||||
if (legacy) {
|
||||
snprintf(ucode_prefix, len, "%s", legacy);
|
||||
return;
|
||||
}
|
||||
|
||||
switch (block_type) {
|
||||
case GC_HWIP:
|
||||
ip_name = "gc";
|
||||
@@ -1091,3 +1312,39 @@ void amdgpu_ucode_ip_version_decode(struct amdgpu_device *adev, int block_type,
|
||||
|
||||
snprintf(ucode_prefix, len, "%s_%d_%d_%d", ip_name, maj, min, rev);
|
||||
}
|
||||
|
||||
/*
|
||||
* amdgpu_ucode_request - Fetch and validate amdgpu microcode
|
||||
*
|
||||
* @adev: amdgpu device
|
||||
* @fw: pointer to load firmware to
|
||||
* @fw_name: firmware to load
|
||||
*
|
||||
* This is a helper that will use request_firmware and amdgpu_ucode_validate
|
||||
* to load and run basic validation on firmware. If the load fails, remap
|
||||
* the error code to -ENODEV, so that early_init functions will fail to load.
|
||||
*/
|
||||
int amdgpu_ucode_request(struct amdgpu_device *adev, const struct firmware **fw,
|
||||
const char *fw_name)
|
||||
{
|
||||
int err = request_firmware(fw, fw_name, adev->dev);
|
||||
|
||||
if (err)
|
||||
return -ENODEV;
|
||||
err = amdgpu_ucode_validate(*fw);
|
||||
if (err)
|
||||
dev_dbg(adev->dev, "\"%s\" failed to validate\n", fw_name);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
/*
|
||||
* amdgpu_ucode_release - Release firmware microcode
|
||||
*
|
||||
* @fw: pointer to firmware to release
|
||||
*/
|
||||
void amdgpu_ucode_release(const struct firmware **fw)
|
||||
{
|
||||
release_firmware(*fw);
|
||||
*fw = NULL;
|
||||
}
|
||||
|
||||
@@ -543,7 +543,9 @@ void amdgpu_ucode_print_rlc_hdr(const struct common_firmware_header *hdr);
|
||||
void amdgpu_ucode_print_sdma_hdr(const struct common_firmware_header *hdr);
|
||||
void amdgpu_ucode_print_psp_hdr(const struct common_firmware_header *hdr);
|
||||
void amdgpu_ucode_print_gpu_info_hdr(const struct common_firmware_header *hdr);
|
||||
int amdgpu_ucode_validate(const struct firmware *fw);
|
||||
int amdgpu_ucode_request(struct amdgpu_device *adev, const struct firmware **fw,
|
||||
const char *fw_name);
|
||||
void amdgpu_ucode_release(const struct firmware **fw);
|
||||
bool amdgpu_ucode_hdr_version(union amdgpu_firmware_header *hdr,
|
||||
uint16_t hdr_major, uint16_t hdr_minor);
|
||||
|
||||
|
||||
@@ -169,25 +169,33 @@ int amdgpu_umc_poison_handler(struct amdgpu_device *adev, bool reset)
|
||||
{
|
||||
int ret = AMDGPU_RAS_SUCCESS;
|
||||
|
||||
if (!adev->gmc.xgmi.connected_to_cpu) {
|
||||
struct ras_err_data err_data = {0, 0, 0, NULL};
|
||||
struct ras_common_if head = {
|
||||
.block = AMDGPU_RAS_BLOCK__UMC,
|
||||
};
|
||||
struct ras_manager *obj = amdgpu_ras_find_obj(adev, &head);
|
||||
if (!amdgpu_sriov_vf(adev)) {
|
||||
if (!adev->gmc.xgmi.connected_to_cpu) {
|
||||
struct ras_err_data err_data = {0, 0, 0, NULL};
|
||||
struct ras_common_if head = {
|
||||
.block = AMDGPU_RAS_BLOCK__UMC,
|
||||
};
|
||||
struct ras_manager *obj = amdgpu_ras_find_obj(adev, &head);
|
||||
|
||||
ret = amdgpu_umc_do_page_retirement(adev, &err_data, NULL, reset);
|
||||
ret = amdgpu_umc_do_page_retirement(adev, &err_data, NULL, reset);
|
||||
|
||||
if (ret == AMDGPU_RAS_SUCCESS && obj) {
|
||||
obj->err_data.ue_count += err_data.ue_count;
|
||||
obj->err_data.ce_count += err_data.ce_count;
|
||||
if (ret == AMDGPU_RAS_SUCCESS && obj) {
|
||||
obj->err_data.ue_count += err_data.ue_count;
|
||||
obj->err_data.ce_count += err_data.ce_count;
|
||||
}
|
||||
} else if (reset) {
|
||||
/* MCA poison handler is only responsible for GPU reset,
|
||||
* let MCA notifier do page retirement.
|
||||
*/
|
||||
kgd2kfd_set_sram_ecc_flag(adev->kfd.dev);
|
||||
amdgpu_ras_reset_gpu(adev);
|
||||
}
|
||||
} else if (reset) {
|
||||
/* MCA poison handler is only responsible for GPU reset,
|
||||
* let MCA notifier do page retirement.
|
||||
*/
|
||||
kgd2kfd_set_sram_ecc_flag(adev->kfd.dev);
|
||||
amdgpu_ras_reset_gpu(adev);
|
||||
} else {
|
||||
if (adev->virt.ops && adev->virt.ops->ras_poison_handler)
|
||||
adev->virt.ops->ras_poison_handler(adev);
|
||||
else
|
||||
dev_warn(adev->dev,
|
||||
"No ras_poison_handler interface in SRIOV!\n");
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
||||
@@ -260,19 +260,11 @@ int amdgpu_uvd_sw_init(struct amdgpu_device *adev)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
r = request_firmware(&adev->uvd.fw, fw_name, adev->dev);
|
||||
if (r) {
|
||||
dev_err(adev->dev, "amdgpu_uvd: Can't load firmware \"%s\"\n",
|
||||
fw_name);
|
||||
return r;
|
||||
}
|
||||
|
||||
r = amdgpu_ucode_validate(adev->uvd.fw);
|
||||
r = amdgpu_ucode_request(adev, &adev->uvd.fw, fw_name);
|
||||
if (r) {
|
||||
dev_err(adev->dev, "amdgpu_uvd: Can't validate firmware \"%s\"\n",
|
||||
fw_name);
|
||||
release_firmware(adev->uvd.fw);
|
||||
adev->uvd.fw = NULL;
|
||||
amdgpu_ucode_release(&adev->uvd.fw);
|
||||
return r;
|
||||
}
|
||||
|
||||
@@ -331,8 +323,11 @@ int amdgpu_uvd_sw_init(struct amdgpu_device *adev)
|
||||
if (adev->uvd.harvest_config & (1 << j))
|
||||
continue;
|
||||
r = amdgpu_bo_create_kernel(adev, bo_size, PAGE_SIZE,
|
||||
AMDGPU_GEM_DOMAIN_VRAM, &adev->uvd.inst[j].vcpu_bo,
|
||||
&adev->uvd.inst[j].gpu_addr, &adev->uvd.inst[j].cpu_addr);
|
||||
AMDGPU_GEM_DOMAIN_VRAM |
|
||||
AMDGPU_GEM_DOMAIN_GTT,
|
||||
&adev->uvd.inst[j].vcpu_bo,
|
||||
&adev->uvd.inst[j].gpu_addr,
|
||||
&adev->uvd.inst[j].cpu_addr);
|
||||
if (r) {
|
||||
dev_err(adev->dev, "(%d) failed to allocate UVD bo\n", r);
|
||||
return r;
|
||||
@@ -394,7 +389,7 @@ int amdgpu_uvd_sw_fini(struct amdgpu_device *adev)
|
||||
amdgpu_ring_fini(&adev->uvd.inst[j].ring_enc[i]);
|
||||
}
|
||||
amdgpu_bo_free_kernel(&adev->uvd.ib_bo, NULL, &addr);
|
||||
release_firmware(adev->uvd.fw);
|
||||
amdgpu_ucode_release(&adev->uvd.fw);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -158,19 +158,11 @@ int amdgpu_vce_sw_init(struct amdgpu_device *adev, unsigned long size)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
r = request_firmware(&adev->vce.fw, fw_name, adev->dev);
|
||||
if (r) {
|
||||
dev_err(adev->dev, "amdgpu_vce: Can't load firmware \"%s\"\n",
|
||||
fw_name);
|
||||
return r;
|
||||
}
|
||||
|
||||
r = amdgpu_ucode_validate(adev->vce.fw);
|
||||
r = amdgpu_ucode_request(adev, &adev->vce.fw, fw_name);
|
||||
if (r) {
|
||||
dev_err(adev->dev, "amdgpu_vce: Can't validate firmware \"%s\"\n",
|
||||
fw_name);
|
||||
release_firmware(adev->vce.fw);
|
||||
adev->vce.fw = NULL;
|
||||
amdgpu_ucode_release(&adev->vce.fw);
|
||||
return r;
|
||||
}
|
||||
|
||||
@@ -186,7 +178,9 @@ int amdgpu_vce_sw_init(struct amdgpu_device *adev, unsigned long size)
|
||||
(binary_id << 8));
|
||||
|
||||
r = amdgpu_bo_create_kernel(adev, size, PAGE_SIZE,
|
||||
AMDGPU_GEM_DOMAIN_VRAM, &adev->vce.vcpu_bo,
|
||||
AMDGPU_GEM_DOMAIN_VRAM |
|
||||
AMDGPU_GEM_DOMAIN_GTT,
|
||||
&adev->vce.vcpu_bo,
|
||||
&adev->vce.gpu_addr, &adev->vce.cpu_addr);
|
||||
if (r) {
|
||||
dev_err(adev->dev, "(%d) failed to allocate VCE bo\n", r);
|
||||
@@ -226,7 +220,7 @@ int amdgpu_vce_sw_fini(struct amdgpu_device *adev)
|
||||
for (i = 0; i < adev->vce.num_rings; i++)
|
||||
amdgpu_ring_fini(&adev->vce.ring[i]);
|
||||
|
||||
release_firmware(adev->vce.fw);
|
||||
amdgpu_ucode_release(&adev->vce.fw);
|
||||
mutex_destroy(&adev->vce.idle_mutex);
|
||||
|
||||
return 0;
|
||||
|
||||
@@ -80,10 +80,24 @@ MODULE_FIRMWARE(FIRMWARE_VCN4_0_4);
|
||||
|
||||
static void amdgpu_vcn_idle_work_handler(struct work_struct *work);
|
||||
|
||||
int amdgpu_vcn_early_init(struct amdgpu_device *adev)
|
||||
{
|
||||
char ucode_prefix[30];
|
||||
char fw_name[40];
|
||||
int r;
|
||||
|
||||
amdgpu_ucode_ip_version_decode(adev, UVD_HWIP, ucode_prefix, sizeof(ucode_prefix));
|
||||
snprintf(fw_name, sizeof(fw_name), "amdgpu/%s.bin", ucode_prefix);
|
||||
r = amdgpu_ucode_request(adev, &adev->vcn.fw, fw_name);
|
||||
if (r)
|
||||
amdgpu_ucode_release(&adev->vcn.fw);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
int amdgpu_vcn_sw_init(struct amdgpu_device *adev)
|
||||
{
|
||||
unsigned long bo_size;
|
||||
const char *fw_name;
|
||||
const struct common_firmware_header *hdr;
|
||||
unsigned char fw_check;
|
||||
unsigned int fw_shared_size, log_offset;
|
||||
@@ -99,46 +113,27 @@ int amdgpu_vcn_sw_init(struct amdgpu_device *adev)
|
||||
switch (adev->ip_versions[UVD_HWIP][0]) {
|
||||
case IP_VERSION(1, 0, 0):
|
||||
case IP_VERSION(1, 0, 1):
|
||||
if (adev->apu_flags & AMD_APU_IS_RAVEN2)
|
||||
fw_name = FIRMWARE_RAVEN2;
|
||||
else if (adev->apu_flags & AMD_APU_IS_PICASSO)
|
||||
fw_name = FIRMWARE_PICASSO;
|
||||
else
|
||||
fw_name = FIRMWARE_RAVEN;
|
||||
break;
|
||||
case IP_VERSION(2, 5, 0):
|
||||
fw_name = FIRMWARE_ARCTURUS;
|
||||
if ((adev->firmware.load_type == AMDGPU_FW_LOAD_PSP) &&
|
||||
(adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG))
|
||||
adev->vcn.indirect_sram = true;
|
||||
break;
|
||||
case IP_VERSION(2, 2, 0):
|
||||
if (adev->apu_flags & AMD_APU_IS_RENOIR)
|
||||
fw_name = FIRMWARE_RENOIR;
|
||||
else
|
||||
fw_name = FIRMWARE_GREEN_SARDINE;
|
||||
|
||||
if ((adev->firmware.load_type == AMDGPU_FW_LOAD_PSP) &&
|
||||
(adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG))
|
||||
adev->vcn.indirect_sram = true;
|
||||
break;
|
||||
case IP_VERSION(2, 6, 0):
|
||||
fw_name = FIRMWARE_ALDEBARAN;
|
||||
if ((adev->firmware.load_type == AMDGPU_FW_LOAD_PSP) &&
|
||||
(adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG))
|
||||
adev->vcn.indirect_sram = true;
|
||||
break;
|
||||
case IP_VERSION(2, 0, 0):
|
||||
fw_name = FIRMWARE_NAVI10;
|
||||
if ((adev->firmware.load_type == AMDGPU_FW_LOAD_PSP) &&
|
||||
(adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG))
|
||||
adev->vcn.indirect_sram = true;
|
||||
break;
|
||||
case IP_VERSION(2, 0, 2):
|
||||
if (adev->asic_type == CHIP_NAVI12)
|
||||
fw_name = FIRMWARE_NAVI12;
|
||||
else
|
||||
fw_name = FIRMWARE_NAVI14;
|
||||
if ((adev->firmware.load_type == AMDGPU_FW_LOAD_PSP) &&
|
||||
(adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG))
|
||||
adev->vcn.indirect_sram = true;
|
||||
@@ -146,58 +141,46 @@ int amdgpu_vcn_sw_init(struct amdgpu_device *adev)
|
||||
case IP_VERSION(3, 0, 0):
|
||||
case IP_VERSION(3, 0, 64):
|
||||
case IP_VERSION(3, 0, 192):
|
||||
if (adev->ip_versions[GC_HWIP][0] == IP_VERSION(10, 3, 0))
|
||||
fw_name = FIRMWARE_SIENNA_CICHLID;
|
||||
else
|
||||
fw_name = FIRMWARE_NAVY_FLOUNDER;
|
||||
if ((adev->firmware.load_type == AMDGPU_FW_LOAD_PSP) &&
|
||||
(adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG))
|
||||
adev->vcn.indirect_sram = true;
|
||||
break;
|
||||
case IP_VERSION(3, 0, 2):
|
||||
fw_name = FIRMWARE_VANGOGH;
|
||||
if ((adev->firmware.load_type == AMDGPU_FW_LOAD_PSP) &&
|
||||
(adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG))
|
||||
adev->vcn.indirect_sram = true;
|
||||
break;
|
||||
case IP_VERSION(3, 0, 16):
|
||||
fw_name = FIRMWARE_DIMGREY_CAVEFISH;
|
||||
if ((adev->firmware.load_type == AMDGPU_FW_LOAD_PSP) &&
|
||||
(adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG))
|
||||
adev->vcn.indirect_sram = true;
|
||||
break;
|
||||
case IP_VERSION(3, 0, 33):
|
||||
fw_name = FIRMWARE_BEIGE_GOBY;
|
||||
if ((adev->firmware.load_type == AMDGPU_FW_LOAD_PSP) &&
|
||||
(adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG))
|
||||
adev->vcn.indirect_sram = true;
|
||||
break;
|
||||
case IP_VERSION(3, 1, 1):
|
||||
fw_name = FIRMWARE_YELLOW_CARP;
|
||||
if ((adev->firmware.load_type == AMDGPU_FW_LOAD_PSP) &&
|
||||
(adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG))
|
||||
adev->vcn.indirect_sram = true;
|
||||
break;
|
||||
case IP_VERSION(3, 1, 2):
|
||||
fw_name = FIRMWARE_VCN_3_1_2;
|
||||
if ((adev->firmware.load_type == AMDGPU_FW_LOAD_PSP) &&
|
||||
(adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG))
|
||||
adev->vcn.indirect_sram = true;
|
||||
break;
|
||||
case IP_VERSION(4, 0, 0):
|
||||
fw_name = FIRMWARE_VCN4_0_0;
|
||||
if ((adev->firmware.load_type == AMDGPU_FW_LOAD_PSP) &&
|
||||
(adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG))
|
||||
adev->vcn.indirect_sram = true;
|
||||
break;
|
||||
case IP_VERSION(4, 0, 2):
|
||||
fw_name = FIRMWARE_VCN4_0_2;
|
||||
if ((adev->firmware.load_type == AMDGPU_FW_LOAD_PSP) &&
|
||||
(adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG))
|
||||
adev->vcn.indirect_sram = true;
|
||||
break;
|
||||
case IP_VERSION(4, 0, 4):
|
||||
fw_name = FIRMWARE_VCN4_0_4;
|
||||
if ((adev->firmware.load_type == AMDGPU_FW_LOAD_PSP) &&
|
||||
(adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG))
|
||||
adev->vcn.indirect_sram = true;
|
||||
@@ -206,22 +189,6 @@ int amdgpu_vcn_sw_init(struct amdgpu_device *adev)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
r = request_firmware(&adev->vcn.fw, fw_name, adev->dev);
|
||||
if (r) {
|
||||
dev_err(adev->dev, "amdgpu_vcn: Can't load firmware \"%s\"\n",
|
||||
fw_name);
|
||||
return r;
|
||||
}
|
||||
|
||||
r = amdgpu_ucode_validate(adev->vcn.fw);
|
||||
if (r) {
|
||||
dev_err(adev->dev, "amdgpu_vcn: Can't validate firmware \"%s\"\n",
|
||||
fw_name);
|
||||
release_firmware(adev->vcn.fw);
|
||||
adev->vcn.fw = NULL;
|
||||
return r;
|
||||
}
|
||||
|
||||
hdr = (const struct common_firmware_header *)adev->vcn.fw->data;
|
||||
adev->vcn.fw_version = le32_to_cpu(hdr->ucode_version);
|
||||
|
||||
@@ -274,8 +241,11 @@ int amdgpu_vcn_sw_init(struct amdgpu_device *adev)
|
||||
continue;
|
||||
|
||||
r = amdgpu_bo_create_kernel(adev, bo_size, PAGE_SIZE,
|
||||
AMDGPU_GEM_DOMAIN_VRAM, &adev->vcn.inst[i].vcpu_bo,
|
||||
&adev->vcn.inst[i].gpu_addr, &adev->vcn.inst[i].cpu_addr);
|
||||
AMDGPU_GEM_DOMAIN_VRAM |
|
||||
AMDGPU_GEM_DOMAIN_GTT,
|
||||
&adev->vcn.inst[i].vcpu_bo,
|
||||
&adev->vcn.inst[i].gpu_addr,
|
||||
&adev->vcn.inst[i].cpu_addr);
|
||||
if (r) {
|
||||
dev_err(adev->dev, "(%d) failed to allocate vcn bo\n", r);
|
||||
return r;
|
||||
@@ -296,8 +266,11 @@ int amdgpu_vcn_sw_init(struct amdgpu_device *adev)
|
||||
|
||||
if (adev->vcn.indirect_sram) {
|
||||
r = amdgpu_bo_create_kernel(adev, 64 * 2 * 4, PAGE_SIZE,
|
||||
AMDGPU_GEM_DOMAIN_VRAM, &adev->vcn.inst[i].dpg_sram_bo,
|
||||
&adev->vcn.inst[i].dpg_sram_gpu_addr, &adev->vcn.inst[i].dpg_sram_cpu_addr);
|
||||
AMDGPU_GEM_DOMAIN_VRAM |
|
||||
AMDGPU_GEM_DOMAIN_GTT,
|
||||
&adev->vcn.inst[i].dpg_sram_bo,
|
||||
&adev->vcn.inst[i].dpg_sram_gpu_addr,
|
||||
&adev->vcn.inst[i].dpg_sram_cpu_addr);
|
||||
if (r) {
|
||||
dev_err(adev->dev, "VCN %d (%d) failed to allocate DPG bo\n", i, r);
|
||||
return r;
|
||||
@@ -333,7 +306,7 @@ int amdgpu_vcn_sw_fini(struct amdgpu_device *adev)
|
||||
amdgpu_ring_fini(&adev->vcn.inst[j].ring_enc[i]);
|
||||
}
|
||||
|
||||
release_firmware(adev->vcn.fw);
|
||||
amdgpu_ucode_release(&adev->vcn.fw);
|
||||
mutex_destroy(&adev->vcn.vcn1_jpeg1_workaround);
|
||||
mutex_destroy(&adev->vcn.vcn_pg_lock);
|
||||
|
||||
@@ -1250,8 +1223,16 @@ int amdgpu_vcn_process_poison_irq(struct amdgpu_device *adev,
|
||||
if (!ras_if)
|
||||
return 0;
|
||||
|
||||
ih_data.head = *ras_if;
|
||||
amdgpu_ras_interrupt_dispatch(adev, &ih_data);
|
||||
if (!amdgpu_sriov_vf(adev)) {
|
||||
ih_data.head = *ras_if;
|
||||
amdgpu_ras_interrupt_dispatch(adev, &ih_data);
|
||||
} else {
|
||||
if (adev->virt.ops && adev->virt.ops->ras_poison_handler)
|
||||
adev->virt.ops->ras_poison_handler(adev);
|
||||
else
|
||||
dev_warn(adev->dev,
|
||||
"No ras_poison_handler interface in SRIOV for VCN!\n");
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -369,6 +369,7 @@ enum vcn_ring_type {
|
||||
VCN_UNIFIED_RING,
|
||||
};
|
||||
|
||||
int amdgpu_vcn_early_init(struct amdgpu_device *adev);
|
||||
int amdgpu_vcn_sw_init(struct amdgpu_device *adev);
|
||||
int amdgpu_vcn_sw_fini(struct amdgpu_device *adev);
|
||||
int amdgpu_vcn_suspend(struct amdgpu_device *adev);
|
||||
|
||||
@@ -232,7 +232,8 @@ int amdgpu_virt_alloc_mm_table(struct amdgpu_device *adev)
|
||||
return 0;
|
||||
|
||||
r = amdgpu_bo_create_kernel(adev, PAGE_SIZE, PAGE_SIZE,
|
||||
AMDGPU_GEM_DOMAIN_VRAM,
|
||||
AMDGPU_GEM_DOMAIN_VRAM |
|
||||
AMDGPU_GEM_DOMAIN_GTT,
|
||||
&adev->virt.mm_table.bo,
|
||||
&adev->virt.mm_table.gpu_addr,
|
||||
(void *)&adev->virt.mm_table.cpu_addr);
|
||||
|
||||
@@ -88,6 +88,7 @@ struct amdgpu_virt_ops {
|
||||
int (*wait_reset)(struct amdgpu_device *adev);
|
||||
void (*trans_msg)(struct amdgpu_device *adev, enum idh_request req,
|
||||
u32 data1, u32 data2, u32 data3);
|
||||
void (*ras_poison_handler)(struct amdgpu_device *adev);
|
||||
};
|
||||
|
||||
/*
|
||||
|
||||
@@ -33,6 +33,7 @@
|
||||
|
||||
#include <drm/amdgpu_drm.h>
|
||||
#include <drm/drm_drv.h>
|
||||
#include <drm/ttm/ttm_tt.h>
|
||||
#include "amdgpu.h"
|
||||
#include "amdgpu_trace.h"
|
||||
#include "amdgpu_amdkfd.h"
|
||||
|
||||
@@ -29,7 +29,7 @@
|
||||
#include <linux/rbtree.h>
|
||||
#include <drm/gpu_scheduler.h>
|
||||
#include <drm/drm_file.h>
|
||||
#include <drm/ttm/ttm_bo_driver.h>
|
||||
#include <drm/ttm/ttm_bo.h>
|
||||
#include <linux/sched/mm.h>
|
||||
|
||||
#include "amdgpu_sync.h"
|
||||
|
||||
@@ -882,7 +882,7 @@ void amdgpu_vram_mgr_fini(struct amdgpu_device *adev)
|
||||
kfree(rsv);
|
||||
|
||||
list_for_each_entry_safe(rsv, temp, &mgr->reserved_pages, blocks) {
|
||||
drm_buddy_free_list(&mgr->mm, &rsv->blocks);
|
||||
drm_buddy_free_list(&mgr->mm, &rsv->allocated);
|
||||
kfree(rsv);
|
||||
}
|
||||
drm_buddy_fini(&mgr->mm);
|
||||
|
||||
@@ -73,10 +73,9 @@ u32 amdgpu_cik_gpu_check_soft_reset(struct amdgpu_device *adev);
|
||||
static void cik_sdma_free_microcode(struct amdgpu_device *adev)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < adev->sdma.num_instances; i++) {
|
||||
release_firmware(adev->sdma.instance[i].fw);
|
||||
adev->sdma.instance[i].fw = NULL;
|
||||
}
|
||||
|
||||
for (i = 0; i < adev->sdma.num_instances; i++)
|
||||
amdgpu_ucode_release(&adev->sdma.instance[i].fw);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -137,18 +136,15 @@ static int cik_sdma_init_microcode(struct amdgpu_device *adev)
|
||||
snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_sdma.bin", chip_name);
|
||||
else
|
||||
snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_sdma1.bin", chip_name);
|
||||
err = request_firmware(&adev->sdma.instance[i].fw, fw_name, adev->dev);
|
||||
err = amdgpu_ucode_request(adev, &adev->sdma.instance[i].fw, fw_name);
|
||||
if (err)
|
||||
goto out;
|
||||
err = amdgpu_ucode_validate(adev->sdma.instance[i].fw);
|
||||
}
|
||||
out:
|
||||
if (err) {
|
||||
pr_err("cik_sdma: Failed to load firmware \"%s\"\n", fw_name);
|
||||
for (i = 0; i < adev->sdma.num_instances; i++) {
|
||||
release_firmware(adev->sdma.instance[i].fw);
|
||||
adev->sdma.instance[i].fw = NULL;
|
||||
}
|
||||
for (i = 0; i < adev->sdma.num_instances; i++)
|
||||
amdgpu_ucode_release(&adev->sdma.instance[i].fw);
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
@@ -2837,7 +2837,7 @@ static int dce_v10_0_sw_init(void *handle)
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
INIT_WORK(&adev->hotplug_work,
|
||||
INIT_DELAYED_WORK(&adev->hotplug_work,
|
||||
amdgpu_display_hotplug_work_func);
|
||||
|
||||
drm_kms_helper_poll_init(adev_to_drm(adev));
|
||||
@@ -2902,7 +2902,7 @@ static int dce_v10_0_hw_fini(void *handle)
|
||||
|
||||
dce_v10_0_pageflip_interrupt_fini(adev);
|
||||
|
||||
flush_work(&adev->hotplug_work);
|
||||
flush_delayed_work(&adev->hotplug_work);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -3302,7 +3302,7 @@ static int dce_v10_0_hpd_irq(struct amdgpu_device *adev,
|
||||
|
||||
if (disp_int & mask) {
|
||||
dce_v10_0_hpd_int_ack(adev, hpd);
|
||||
schedule_work(&adev->hotplug_work);
|
||||
schedule_delayed_work(&adev->hotplug_work, 0);
|
||||
DRM_DEBUG("IH: HPD%d\n", hpd + 1);
|
||||
}
|
||||
|
||||
|
||||
@@ -2956,7 +2956,7 @@ static int dce_v11_0_sw_init(void *handle)
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
INIT_WORK(&adev->hotplug_work,
|
||||
INIT_DELAYED_WORK(&adev->hotplug_work,
|
||||
amdgpu_display_hotplug_work_func);
|
||||
|
||||
drm_kms_helper_poll_init(adev_to_drm(adev));
|
||||
@@ -3032,7 +3032,7 @@ static int dce_v11_0_hw_fini(void *handle)
|
||||
|
||||
dce_v11_0_pageflip_interrupt_fini(adev);
|
||||
|
||||
flush_work(&adev->hotplug_work);
|
||||
flush_delayed_work(&adev->hotplug_work);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -3426,7 +3426,7 @@ static int dce_v11_0_hpd_irq(struct amdgpu_device *adev,
|
||||
|
||||
if (disp_int & mask) {
|
||||
dce_v11_0_hpd_int_ack(adev, hpd);
|
||||
schedule_work(&adev->hotplug_work);
|
||||
schedule_delayed_work(&adev->hotplug_work, 0);
|
||||
DRM_DEBUG("IH: HPD%d\n", hpd + 1);
|
||||
}
|
||||
|
||||
|
||||
@@ -2715,7 +2715,7 @@ static int dce_v6_0_sw_init(void *handle)
|
||||
return r;
|
||||
|
||||
/* Pre-DCE11 */
|
||||
INIT_WORK(&adev->hotplug_work,
|
||||
INIT_DELAYED_WORK(&adev->hotplug_work,
|
||||
amdgpu_display_hotplug_work_func);
|
||||
|
||||
drm_kms_helper_poll_init(adev_to_drm(adev));
|
||||
@@ -2776,7 +2776,7 @@ static int dce_v6_0_hw_fini(void *handle)
|
||||
|
||||
dce_v6_0_pageflip_interrupt_fini(adev);
|
||||
|
||||
flush_work(&adev->hotplug_work);
|
||||
flush_delayed_work(&adev->hotplug_work);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -3103,7 +3103,7 @@ static int dce_v6_0_hpd_irq(struct amdgpu_device *adev,
|
||||
tmp = RREG32(mmDC_HPD1_INT_CONTROL + hpd_offsets[hpd]);
|
||||
tmp |= DC_HPD1_INT_CONTROL__DC_HPD1_INT_ACK_MASK;
|
||||
WREG32(mmDC_HPD1_INT_CONTROL + hpd_offsets[hpd], tmp);
|
||||
schedule_work(&adev->hotplug_work);
|
||||
schedule_delayed_work(&adev->hotplug_work, 0);
|
||||
DRM_DEBUG("IH: HPD%d\n", hpd + 1);
|
||||
}
|
||||
|
||||
|
||||
@@ -2739,7 +2739,7 @@ static int dce_v8_0_sw_init(void *handle)
|
||||
return r;
|
||||
|
||||
/* Pre-DCE11 */
|
||||
INIT_WORK(&adev->hotplug_work,
|
||||
INIT_DELAYED_WORK(&adev->hotplug_work,
|
||||
amdgpu_display_hotplug_work_func);
|
||||
|
||||
drm_kms_helper_poll_init(adev_to_drm(adev));
|
||||
@@ -2802,7 +2802,7 @@ static int dce_v8_0_hw_fini(void *handle)
|
||||
|
||||
dce_v8_0_pageflip_interrupt_fini(adev);
|
||||
|
||||
flush_work(&adev->hotplug_work);
|
||||
flush_delayed_work(&adev->hotplug_work);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -3195,7 +3195,7 @@ static int dce_v8_0_hpd_irq(struct amdgpu_device *adev,
|
||||
tmp = RREG32(mmDC_HPD1_INT_CONTROL + hpd_offsets[hpd]);
|
||||
tmp |= DC_HPD1_INT_CONTROL__DC_HPD1_INT_ACK_MASK;
|
||||
WREG32(mmDC_HPD1_INT_CONTROL + hpd_offsets[hpd], tmp);
|
||||
schedule_work(&adev->hotplug_work);
|
||||
schedule_delayed_work(&adev->hotplug_work, 0);
|
||||
DRM_DEBUG("IH: HPD%d\n", hpd + 1);
|
||||
}
|
||||
|
||||
|
||||
61
drivers/gpu/drm/amd/amdgpu/df_v4_3.c
Normal file
61
drivers/gpu/drm/amd/amdgpu/df_v4_3.c
Normal file
@@ -0,0 +1,61 @@
|
||||
/*
|
||||
* Copyright 2022 Advanced Micro Devices, Inc.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
||||
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
* OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
*/
|
||||
#include "amdgpu.h"
|
||||
#include "df_v4_3.h"
|
||||
|
||||
#include "df/df_4_3_offset.h"
|
||||
#include "df/df_4_3_sh_mask.h"
|
||||
|
||||
static bool df_v4_3_query_ras_poison_mode(struct amdgpu_device *adev)
|
||||
{
|
||||
uint32_t hw_assert_msklo, hw_assert_mskhi;
|
||||
uint32_t v0, v1, v28, v31;
|
||||
|
||||
hw_assert_msklo = RREG32_SOC15(DF, 0,
|
||||
regDF_CS_UMC_AON0_HardwareAssertMaskLow);
|
||||
hw_assert_mskhi = RREG32_SOC15(DF, 0,
|
||||
regDF_NCS_PG0_HardwareAssertMaskHigh);
|
||||
|
||||
v0 = REG_GET_FIELD(hw_assert_msklo,
|
||||
DF_CS_UMC_AON0_HardwareAssertMaskLow, HWAssertMsk0);
|
||||
v1 = REG_GET_FIELD(hw_assert_msklo,
|
||||
DF_CS_UMC_AON0_HardwareAssertMaskLow, HWAssertMsk1);
|
||||
v28 = REG_GET_FIELD(hw_assert_mskhi,
|
||||
DF_NCS_PG0_HardwareAssertMaskHigh, HWAssertMsk28);
|
||||
v31 = REG_GET_FIELD(hw_assert_mskhi,
|
||||
DF_NCS_PG0_HardwareAssertMaskHigh, HWAssertMsk31);
|
||||
|
||||
if (v0 && v1 && v28 && v31)
|
||||
return true;
|
||||
else if (!v0 && !v1 && !v28 && !v31)
|
||||
return false;
|
||||
else {
|
||||
dev_warn(adev->dev, "DF poison setting is inconsistent(%d:%d:%d:%d)!\n",
|
||||
v0, v1, v28, v31);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
const struct amdgpu_df_funcs df_v4_3_funcs = {
|
||||
.query_ras_poison_mode = df_v4_3_query_ras_poison_mode,
|
||||
};
|
||||
31
drivers/gpu/drm/amd/amdgpu/df_v4_3.h
Normal file
31
drivers/gpu/drm/amd/amdgpu/df_v4_3.h
Normal file
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
* Copyright 2022 Advanced Micro Devices, Inc.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
||||
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
* OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __DF_V4_3_H__
|
||||
#define __DF_V4_3_H__
|
||||
|
||||
#include "soc15_common.h"
|
||||
|
||||
extern const struct amdgpu_df_funcs df_v4_3_funcs;
|
||||
|
||||
#endif
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user