Merge airlied/drm-next into drm-misc-fixes
Fast forwarding -fixes for 4.17. Signed-off-by: Sean Paul <seanpaul@chromium.org>
This commit is contained in:
commit
8089f9f5a3
@ -1,110 +1,139 @@
|
||||
What: /sys/class/ata_...
|
||||
Date: August 2008
|
||||
Contact: Gwendal Grignou<gwendal@google.com>
|
||||
Description:
|
||||
|
||||
Provide a place in sysfs for storing the ATA topology of the system. This allows
|
||||
retrieving various information about ATA objects.
|
||||
Provide a place in sysfs for storing the ATA topology of the
|
||||
system. This allows retrieving various information about ATA
|
||||
objects.
|
||||
|
||||
Files under /sys/class/ata_port
|
||||
-------------------------------
|
||||
|
||||
For each port, a directory ataX is created where X is the ata_port_id of
|
||||
the port. The device parent is the ata host device.
|
||||
For each port, a directory ataX is created where X is the ata_port_id of the
|
||||
port. The device parent is the ata host device.
|
||||
|
||||
idle_irq (read)
|
||||
|
||||
Number of IRQ received by the port while idle [some ata HBA only].
|
||||
What: /sys/class/ata_port/ataX/nr_pmp_links
|
||||
What: /sys/class/ata_port/ataX/idle_irq
|
||||
Date: May, 2010
|
||||
KernelVersion: v2.6.37
|
||||
Contact: Gwendal Grignou <gwendal@chromium.org>
|
||||
Description:
|
||||
nr_pmp_links: (RO) If a SATA Port Multiplier (PM) is
|
||||
connected, the number of links behind it.
|
||||
|
||||
nr_pmp_links (read)
|
||||
idle_irq: (RO) Number of IRQ received by the port while
|
||||
idle [some ata HBA only].
|
||||
|
||||
If a SATA Port Multiplier (PM) is connected, number of link behind it.
|
||||
|
||||
What: /sys/class/ata_port/ataX/port_no
|
||||
Date: May, 2013
|
||||
KernelVersion: v3.11
|
||||
Contact: Gwendal Grignou <gwendal@chromium.org>
|
||||
Description:
|
||||
(RO) Host local port number. While registering host controller,
|
||||
port numbers are tracked based upon number of ports available on
|
||||
the controller. This attribute is needed by udev for composing
|
||||
persistent links in /dev/disk/by-path.
|
||||
|
||||
Files under /sys/class/ata_link
|
||||
-------------------------------
|
||||
|
||||
Behind each port, there is a ata_link. If there is a SATA PM in the
|
||||
topology, 15 ata_link objects are created.
|
||||
Behind each port, there is a ata_link. If there is a SATA PM in the topology, 15
|
||||
ata_link objects are created.
|
||||
|
||||
If a link is behind a port, the directory name is linkX, where X is
|
||||
ata_port_id of the port.
|
||||
If a link is behind a PM, its name is linkX.Y where X is ata_port_id
|
||||
of the parent port and Y the PM port.
|
||||
If a link is behind a port, the directory name is linkX, where X is ata_port_id
|
||||
of the port. If a link is behind a PM, its name is linkX.Y where X is
|
||||
ata_port_id of the parent port and Y the PM port.
|
||||
|
||||
hw_sata_spd_limit
|
||||
|
||||
Maximum speed supported by the connected SATA device.
|
||||
What: /sys/class/ata_link/linkX[.Y]/hw_sata_spd_limit
|
||||
What: /sys/class/ata_link/linkX[.Y]/sata_spd_limit
|
||||
What: /sys/class/ata_link/linkX[.Y]/sata_spd
|
||||
Date: May, 2010
|
||||
KernelVersion: v2.6.37
|
||||
Contact: Gwendal Grignou <gwendal@chromium.org>
|
||||
Description:
|
||||
hw_sata_spd_limit: (RO) Maximum speed supported by the
|
||||
connected SATA device.
|
||||
|
||||
sata_spd_limit
|
||||
sata_spd_limit: (RO) Maximum speed imposed by libata.
|
||||
|
||||
Maximum speed imposed by libata.
|
||||
sata_spd: (RO) Current speed of the link
|
||||
eg. 1.5, 3 Gbps etc.
|
||||
|
||||
sata_spd
|
||||
|
||||
Current speed of the link [1.5, 3Gps,...].
|
||||
|
||||
Files under /sys/class/ata_device
|
||||
---------------------------------
|
||||
|
||||
Behind each link, up to two ata device are created.
|
||||
The name of the directory is devX[.Y].Z where:
|
||||
- X is ata_port_id of the port where the device is connected,
|
||||
- Y the port of the PM if any, and
|
||||
- Z the device id: for PATA, there is usually 2 devices [0,1],
|
||||
only 1 for SATA.
|
||||
Behind each link, up to two ata devices are created.
|
||||
The name of the directory is devX[.Y].Z where:
|
||||
- X is ata_port_id of the port where the device is connected,
|
||||
- Y the port of the PM if any, and
|
||||
- Z the device id: for PATA, there is usually 2 devices [0,1], only 1 for SATA.
|
||||
|
||||
class
|
||||
Device class. Can be "ata" for disk, "atapi" for packet device,
|
||||
"pmp" for PM, or "none" if no device was found behind the link.
|
||||
|
||||
dma_mode
|
||||
What: /sys/class/ata_device/devX[.Y].Z/spdn_cnt
|
||||
What: /sys/class/ata_device/devX[.Y].Z/gscr
|
||||
What: /sys/class/ata_device/devX[.Y].Z/ering
|
||||
What: /sys/class/ata_device/devX[.Y].Z/id
|
||||
What: /sys/class/ata_device/devX[.Y].Z/pio_mode
|
||||
What: /sys/class/ata_device/devX[.Y].Z/xfer_mode
|
||||
What: /sys/class/ata_device/devX[.Y].Z/dma_mode
|
||||
What: /sys/class/ata_device/devX[.Y].Z/class
|
||||
Date: May, 2010
|
||||
KernelVersion: v2.6.37
|
||||
Contact: Gwendal Grignou <gwendal@chromium.org>
|
||||
Description:
|
||||
spdn_cnt: (RO) Number of times libata decided to lower the
|
||||
speed of link due to errors.
|
||||
|
||||
Transfer modes supported by the device when in DMA mode.
|
||||
Mostly used by PATA device.
|
||||
gscr: (RO) Cached result of the dump of PM GSCR
|
||||
register. Valid registers are:
|
||||
|
||||
pio_mode
|
||||
0: SATA_PMP_GSCR_PROD_ID,
|
||||
1: SATA_PMP_GSCR_REV,
|
||||
2: SATA_PMP_GSCR_PORT_INFO,
|
||||
32: SATA_PMP_GSCR_ERROR,
|
||||
33: SATA_PMP_GSCR_ERROR_EN,
|
||||
64: SATA_PMP_GSCR_FEAT,
|
||||
96: SATA_PMP_GSCR_FEAT_EN,
|
||||
130: SATA_PMP_GSCR_SII_GPIO
|
||||
|
||||
Transfer modes supported by the device when in PIO mode.
|
||||
Mostly used by PATA device.
|
||||
Only valid if the device is a PM.
|
||||
|
||||
xfer_mode
|
||||
ering: (RO) Formatted output of the error ring of the
|
||||
device.
|
||||
|
||||
Current transfer mode.
|
||||
id: (RO) Cached result of IDENTIFY command, as
|
||||
described in ATA8 7.16 and 7.17. Only valid if
|
||||
the device is not a PM.
|
||||
|
||||
id
|
||||
pio_mode: (RO) Transfer modes supported by the device when
|
||||
in PIO mode. Mostly used by PATA device.
|
||||
|
||||
Cached result of IDENTIFY command, as described in ATA8 7.16 and 7.17.
|
||||
Only valid if the device is not a PM.
|
||||
xfer_mode: (RO) Current transfer mode
|
||||
|
||||
gscr
|
||||
dma_mode: (RO) Transfer modes supported by the device when
|
||||
in DMA mode. Mostly used by PATA device.
|
||||
|
||||
Cached result of the dump of PM GSCR register.
|
||||
Valid registers are:
|
||||
0: SATA_PMP_GSCR_PROD_ID,
|
||||
1: SATA_PMP_GSCR_REV,
|
||||
2: SATA_PMP_GSCR_PORT_INFO,
|
||||
32: SATA_PMP_GSCR_ERROR,
|
||||
33: SATA_PMP_GSCR_ERROR_EN,
|
||||
64: SATA_PMP_GSCR_FEAT,
|
||||
96: SATA_PMP_GSCR_FEAT_EN,
|
||||
130: SATA_PMP_GSCR_SII_GPIO
|
||||
Only valid if the device is a PM.
|
||||
class: (RO) Device class. Can be "ata" for disk,
|
||||
"atapi" for packet device, "pmp" for PM, or
|
||||
"none" if no device was found behind the link.
|
||||
|
||||
trim
|
||||
|
||||
Shows the DSM TRIM mode currently used by the device. Valid
|
||||
values are:
|
||||
unsupported: Drive does not support DSM TRIM
|
||||
unqueued: Drive supports unqueued DSM TRIM only
|
||||
queued: Drive supports queued DSM TRIM
|
||||
forced_unqueued: Drive's queued DSM support is known to be
|
||||
buggy and only unqueued TRIM commands
|
||||
are sent
|
||||
What: /sys/class/ata_device/devX[.Y].Z/trim
|
||||
Date: May, 2015
|
||||
KernelVersion: v4.10
|
||||
Contact: Gwendal Grignou <gwendal@chromium.org>
|
||||
Description:
|
||||
(RO) Shows the DSM TRIM mode currently used by the device. Valid
|
||||
values are:
|
||||
|
||||
spdn_cnt
|
||||
unsupported: Drive does not support DSM TRIM
|
||||
|
||||
Number of time libata decided to lower the speed of link due to errors.
|
||||
unqueued: Drive supports unqueued DSM TRIM only
|
||||
|
||||
ering
|
||||
queued: Drive supports queued DSM TRIM
|
||||
|
||||
Formatted output of the error ring of the device.
|
||||
forced_unqueued: Drive's queued DSM support is known to
|
||||
be buggy and only unqueued TRIM commands
|
||||
are sent
|
||||
|
58
Documentation/ABI/testing/sysfs-block-device
Normal file
58
Documentation/ABI/testing/sysfs-block-device
Normal file
@ -0,0 +1,58 @@
|
||||
What: /sys/block/*/device/sw_activity
|
||||
Date: Jun, 2008
|
||||
KernelVersion: v2.6.27
|
||||
Contact: linux-ide@vger.kernel.org
|
||||
Description:
|
||||
(RW) Used by drivers which support software controlled activity
|
||||
LEDs.
|
||||
|
||||
It has the following valid values:
|
||||
|
||||
0 OFF - the LED is not activated on activity
|
||||
1 BLINK_ON - the LED blinks on every 10ms when activity is
|
||||
detected.
|
||||
2 BLINK_OFF - the LED is on when idle, and blinks off
|
||||
every 10ms when activity is detected.
|
||||
|
||||
Note that the user must turn sw_activity OFF it they wish to
|
||||
control the activity LED via the em_message file.
|
||||
|
||||
|
||||
What: /sys/block/*/device/unload_heads
|
||||
Date: Sep, 2008
|
||||
KernelVersion: v2.6.28
|
||||
Contact: linux-ide@vger.kernel.org
|
||||
Description:
|
||||
(RW) Hard disk shock protection
|
||||
|
||||
Writing an integer value to this file will take the heads of the
|
||||
respective drive off the platter and block all I/O operations
|
||||
for the specified number of milliseconds.
|
||||
|
||||
- If the device does not support the unload heads feature,
|
||||
access is denied with -EOPNOTSUPP.
|
||||
- The maximal value accepted for a timeout is 30000
|
||||
milliseconds.
|
||||
- A previously set timeout can be cancelled and disk can resume
|
||||
normal operation immediately by specifying a timeout of 0.
|
||||
- Some hard drives only comply with an earlier version of the
|
||||
ATA standard, but support the unload feature nonetheless.
|
||||
There is no safe way Linux can detect these devices, so this
|
||||
is not enabled by default. If it is known that your device
|
||||
does support the unload feature, then you can tell the kernel
|
||||
to enable it by writing -1. It can be disabled again by
|
||||
writing -2.
|
||||
- Values below -2 are rejected with -EINVAL
|
||||
|
||||
For more information, see
|
||||
Documentation/laptops/disk-shock-protection.txt
|
||||
|
||||
|
||||
What: /sys/block/*/device/ncq_prio_enable
|
||||
Date: Oct, 2016
|
||||
KernelVersion: v4.10
|
||||
Contact: linux-ide@vger.kernel.org
|
||||
Description:
|
||||
(RW) Write to the file to turn on or off the SATA ncq (native
|
||||
command queueing) support. By default this feature is turned
|
||||
off.
|
@ -27,3 +27,92 @@ Description: This file contains the current status of the "SSD Smart Path"
|
||||
the direct i/o path to physical devices. This setting is
|
||||
controller wide, affecting all configured logical drives on the
|
||||
controller. This file is readable and writable.
|
||||
|
||||
What: /sys/class/scsi_host/hostX/link_power_management_policy
|
||||
Date: Oct, 2007
|
||||
KernelVersion: v2.6.24
|
||||
Contact: linux-ide@vger.kernel.org
|
||||
Description:
|
||||
(RW) This parameter allows the user to read and set the link
|
||||
(interface) power management.
|
||||
|
||||
There are four possible options:
|
||||
|
||||
min_power: Tell the controller to try to make the link use the
|
||||
least possible power when possible. This may sacrifice some
|
||||
performance due to increased latency when coming out of lower
|
||||
power states.
|
||||
|
||||
max_performance: Generally, this means no power management.
|
||||
Tell the controller to have performance be a priority over power
|
||||
management.
|
||||
|
||||
medium_power: Tell the controller to enter a lower power state
|
||||
when possible, but do not enter the lowest power state, thus
|
||||
improving latency over min_power setting.
|
||||
|
||||
med_power_with_dipm: Identical to the existing medium_power
|
||||
setting except that it enables dipm (device initiated power
|
||||
management) on top, which makes it match the Windows IRST (Intel
|
||||
Rapid Storage Technology) driver settings. This setting is also
|
||||
close to min_power, except that:
|
||||
a) It does not use host-initiated slumber mode, but it does
|
||||
allow device-initiated slumber
|
||||
b) It does not enable low power device sleep mode (DevSlp).
|
||||
|
||||
What: /sys/class/scsi_host/hostX/em_message
|
||||
What: /sys/class/scsi_host/hostX/em_message_type
|
||||
Date: Jun, 2008
|
||||
KernelVersion: v2.6.27
|
||||
Contact: linux-ide@vger.kernel.org
|
||||
Description:
|
||||
em_message: (RW) Enclosure management support. For the LED
|
||||
protocol, writes and reads correspond to the LED message format
|
||||
as defined in the AHCI spec.
|
||||
|
||||
The user must turn sw_activity (under /sys/block/*/device/) OFF
|
||||
it they wish to control the activity LED via the em_message
|
||||
file.
|
||||
|
||||
em_message_type: (RO) Displays the current enclosure management
|
||||
protocol that is being used by the driver (for eg. LED, SAF-TE,
|
||||
SES-2, SGPIO etc).
|
||||
|
||||
What: /sys/class/scsi_host/hostX/ahci_port_cmd
|
||||
What: /sys/class/scsi_host/hostX/ahci_host_caps
|
||||
What: /sys/class/scsi_host/hostX/ahci_host_cap2
|
||||
Date: Mar, 2010
|
||||
KernelVersion: v2.6.35
|
||||
Contact: linux-ide@vger.kernel.org
|
||||
Description:
|
||||
[to be documented]
|
||||
|
||||
What: /sys/class/scsi_host/hostX/ahci_host_version
|
||||
Date: Mar, 2010
|
||||
KernelVersion: v2.6.35
|
||||
Contact: linux-ide@vger.kernel.org
|
||||
Description:
|
||||
(RO) Display the version of the AHCI spec implemented by the
|
||||
host.
|
||||
|
||||
What: /sys/class/scsi_host/hostX/em_buffer
|
||||
Date: Apr, 2010
|
||||
KernelVersion: v2.6.35
|
||||
Contact: linux-ide@vger.kernel.org
|
||||
Description:
|
||||
(RW) Allows access to AHCI EM (enclosure management) buffer
|
||||
directly if the host supports EM.
|
||||
|
||||
For eg. the AHCI driver supports SGPIO EM messages but the
|
||||
SATA/AHCI specs do not define the SGPIO message format of the EM
|
||||
buffer. Different hardware(HW) vendors may have different
|
||||
definitions. With the em_buffer attribute, this issue can be
|
||||
solved by allowing HW vendors to provide userland drivers and
|
||||
tools for their SGPIO initiators.
|
||||
|
||||
What: /sys/class/scsi_host/hostX/em_message_supported
|
||||
Date: Oct, 2009
|
||||
KernelVersion: v2.6.39
|
||||
Contact: linux-ide@vger.kernel.org
|
||||
Description:
|
||||
(RO) Displays supported enclosure management message types.
|
||||
|
@ -0,0 +1,58 @@
|
||||
Renesas R-Car LVDS Encoder
|
||||
==========================
|
||||
|
||||
These DT bindings describe the LVDS encoder embedded in the Renesas R-Car
|
||||
Gen2, R-Car Gen3 and RZ/G SoCs.
|
||||
|
||||
Required properties:
|
||||
|
||||
- compatible : Shall contain one of
|
||||
- "renesas,r8a7743-lvds" for R8A7743 (RZ/G1M) compatible LVDS encoders
|
||||
- "renesas,r8a7790-lvds" for R8A7790 (R-Car H2) compatible LVDS encoders
|
||||
- "renesas,r8a7791-lvds" for R8A7791 (R-Car M2-W) compatible LVDS encoders
|
||||
- "renesas,r8a7793-lvds" for R8A7793 (R-Car M2-N) compatible LVDS encoders
|
||||
- "renesas,r8a7795-lvds" for R8A7795 (R-Car H3) compatible LVDS encoders
|
||||
- "renesas,r8a7796-lvds" for R8A7796 (R-Car M3-W) compatible LVDS encoders
|
||||
- "renesas,r8a77970-lvds" for R8A77970 (R-Car V3M) compatible LVDS encoders
|
||||
- "renesas,r8a77995-lvds" for R8A77995 (R-Car D3) compatible LVDS encoders
|
||||
|
||||
- reg: Base address and length for the memory-mapped registers
|
||||
- clocks: A phandle + clock-specifier pair for the functional clock
|
||||
- resets: A phandle + reset specifier for the module reset
|
||||
|
||||
Required nodes:
|
||||
|
||||
The LVDS encoder has two video ports. Their connections are modelled using the
|
||||
OF graph bindings specified in Documentation/devicetree/bindings/graph.txt.
|
||||
|
||||
- Video port 0 corresponds to the parallel RGB input
|
||||
- Video port 1 corresponds to the LVDS output
|
||||
|
||||
Each port shall have a single endpoint.
|
||||
|
||||
|
||||
Example:
|
||||
|
||||
lvds0: lvds@feb90000 {
|
||||
compatible = "renesas,r8a7790-lvds";
|
||||
reg = <0 0xfeb90000 0 0x1c>;
|
||||
clocks = <&cpg CPG_MOD 726>;
|
||||
resets = <&cpg 726>;
|
||||
|
||||
ports {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
port@0 {
|
||||
reg = <0>;
|
||||
lvds0_in: endpoint {
|
||||
remote-endpoint = <&du_out_lvds0>;
|
||||
};
|
||||
};
|
||||
port@1 {
|
||||
reg = <1>;
|
||||
lvds0_out: endpoint {
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
@ -1,11 +1,16 @@
|
||||
THS8135 Video DAC
|
||||
-----------------
|
||||
THS8134 and THS8135 Video DAC
|
||||
-----------------------------
|
||||
|
||||
This is the binding for Texas Instruments THS8135 Video DAC bridge.
|
||||
This is the binding for Texas Instruments THS8134, THS8134A, THS8134B and
|
||||
THS8135 Video DAC bridges.
|
||||
|
||||
Required properties:
|
||||
|
||||
- compatible: Must be "ti,ths8135"
|
||||
- compatible: Must be one of
|
||||
"ti,ths8134"
|
||||
"ti,ths8134a," "ti,ths8134"
|
||||
"ti,ths8134b", "ti,ths8134"
|
||||
"ti,ths8135"
|
||||
|
||||
Required nodes:
|
||||
|
@ -10,6 +10,7 @@ Optional properties:
|
||||
- analog: the connector has DVI analog pins
|
||||
- digital: the connector has DVI digital pins
|
||||
- dual-link: the connector has pins for DVI dual-link
|
||||
- hpd-gpios: HPD GPIO number
|
||||
|
||||
Required nodes:
|
||||
- Video port for DVI input
|
||||
|
@ -1,23 +1,3 @@
|
||||
Etnaviv DRM master device
|
||||
=========================
|
||||
|
||||
The Etnaviv DRM master device is a virtual device needed to list all
|
||||
Vivante GPU cores that comprise the GPU subsystem.
|
||||
|
||||
Required properties:
|
||||
- compatible: Should be one of
|
||||
"fsl,imx-gpu-subsystem"
|
||||
"marvell,dove-gpu-subsystem"
|
||||
- cores: Should contain a list of phandles pointing to Vivante GPU devices
|
||||
|
||||
example:
|
||||
|
||||
gpu-subsystem {
|
||||
compatible = "fsl,imx-gpu-subsystem";
|
||||
cores = <&gpu_2d>, <&gpu_3d>;
|
||||
};
|
||||
|
||||
|
||||
Vivante GPU core devices
|
||||
========================
|
||||
|
||||
@ -32,7 +12,9 @@ Required properties:
|
||||
- clocks: should contain one clock for entry in clock-names
|
||||
see Documentation/devicetree/bindings/clock/clock-bindings.txt
|
||||
- clock-names:
|
||||
- "bus": AXI/register clock
|
||||
- "bus": AXI/master interface clock
|
||||
- "reg": AHB/slave interface clock
|
||||
(only required if GPU can gate slave interface independently)
|
||||
- "core": GPU core clock
|
||||
- "shader": Shader clock (only required if GPU has feature PIPE_3D)
|
||||
|
||||
|
@ -7,8 +7,6 @@ Required properties:
|
||||
- reg: Physical base address and length of the registers of controller
|
||||
- reg-names: The names of register regions. The following regions are required:
|
||||
* "dsi_ctrl"
|
||||
- qcom,dsi-host-index: The ID of DSI controller hardware instance. This should
|
||||
be 0 or 1, since we have 2 DSI controllers at most for now.
|
||||
- interrupts: The interrupt signal from the DSI block.
|
||||
- power-domains: Should be <&mmcc MDSS_GDSC>.
|
||||
- clocks: Phandles to device clocks.
|
||||
@ -22,6 +20,8 @@ Required properties:
|
||||
* "core"
|
||||
For DSIv2, we need an additional clock:
|
||||
* "src"
|
||||
For DSI6G v2.0 onwards, we need also need the clock:
|
||||
* "byte_intf"
|
||||
- assigned-clocks: Parents of "byte" and "pixel" for the given platform.
|
||||
- assigned-clock-parents: The Byte clock and Pixel clock PLL outputs provided
|
||||
by a DSI PHY block. See [1] for details on clock bindings.
|
||||
@ -88,21 +88,35 @@ Required properties:
|
||||
* "qcom,dsi-phy-28nm-lp"
|
||||
* "qcom,dsi-phy-20nm"
|
||||
* "qcom,dsi-phy-28nm-8960"
|
||||
- reg: Physical base address and length of the registers of PLL, PHY and PHY
|
||||
regulator
|
||||
* "qcom,dsi-phy-14nm"
|
||||
* "qcom,dsi-phy-10nm"
|
||||
- reg: Physical base address and length of the registers of PLL, PHY. Some
|
||||
revisions require the PHY regulator base address, whereas others require the
|
||||
PHY lane base address. See below for each PHY revision.
|
||||
- reg-names: The names of register regions. The following regions are required:
|
||||
For DSI 28nm HPM/LP/8960 PHYs and 20nm PHY:
|
||||
* "dsi_pll"
|
||||
* "dsi_phy"
|
||||
* "dsi_phy_regulator"
|
||||
For DSI 14nm and 10nm PHYs:
|
||||
* "dsi_pll"
|
||||
* "dsi_phy"
|
||||
* "dsi_phy_lane"
|
||||
- clock-cells: Must be 1. The DSI PHY block acts as a clock provider, creating
|
||||
2 clocks: A byte clock (index 0), and a pixel clock (index 1).
|
||||
- qcom,dsi-phy-index: The ID of DSI PHY hardware instance. This should
|
||||
be 0 or 1, since we have 2 DSI PHYs at most for now.
|
||||
- power-domains: Should be <&mmcc MDSS_GDSC>.
|
||||
- clocks: Phandles to device clocks. See [1] for details on clock bindings.
|
||||
- clock-names: the following clocks are required:
|
||||
* "iface"
|
||||
For 28nm HPM/LP, 28nm 8960 PHYs:
|
||||
- vddio-supply: phandle to vdd-io regulator device node
|
||||
For 20nm PHY:
|
||||
- vddio-supply: phandle to vdd-io regulator device node
|
||||
- vcca-supply: phandle to vcca regulator device node
|
||||
For 14nm PHY:
|
||||
- vcca-supply: phandle to vcca regulator device node
|
||||
For 10nm PHY:
|
||||
- vdds-supply: phandle to vdds regulator device node
|
||||
|
||||
Optional properties:
|
||||
- qcom,dsi-phy-regulator-ldo-mode: Boolean value indicating if the LDO mode PHY
|
||||
|
@ -0,0 +1,31 @@
|
||||
ARM Versatile TFT Panels
|
||||
|
||||
These panels are connected to the daughterboards found on the
|
||||
ARM Versatile reference designs.
|
||||
|
||||
This device node must appear as a child to a "syscon"-compatible
|
||||
node.
|
||||
|
||||
Required properties:
|
||||
- compatible: should be "arm,versatile-tft-panel"
|
||||
|
||||
Required subnodes:
|
||||
- port: see display/panel/panel-common.txt, graph.txt
|
||||
|
||||
|
||||
Example:
|
||||
|
||||
sysreg@0 {
|
||||
compatible = "arm,versatile-sysreg", "syscon", "simple-mfd";
|
||||
reg = <0x00000 0x1000>;
|
||||
|
||||
panel: display@0 {
|
||||
compatible = "arm,versatile-tft-panel";
|
||||
|
||||
port {
|
||||
panel_in: endpoint {
|
||||
remote-endpoint = <&foo>;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
@ -0,0 +1,12 @@
|
||||
AU Optronics Corporation 10.4" (800x600) color TFT LCD panel
|
||||
|
||||
Required properties:
|
||||
- compatible: should be "auo,g104sn02"
|
||||
- power-supply: as specified in the base binding
|
||||
|
||||
Optional properties:
|
||||
- backlight: as specified in the base binding
|
||||
- enable-gpios: as specified in the base binding
|
||||
|
||||
This binding is compatible with the simple-panel binding, which is specified
|
||||
in simple-panel.txt in this directory.
|
@ -80,6 +80,11 @@ The parameters are defined as:
|
||||
| | v | | |
|
||||
+----------+-------------------------------------+----------+-------+
|
||||
|
||||
Note: In addition to being used as subnode(s) of display-timings, the timing
|
||||
subnode may also be used on its own. This is appropriate if only one mode
|
||||
need be conveyed. In this case, the node should be named 'panel-timing'.
|
||||
|
||||
|
||||
Example:
|
||||
|
||||
display-timings {
|
||||
|
@ -0,0 +1,25 @@
|
||||
Kaohsiung Opto-Electronics. TX31D200VM0BAA 12.3" HSXGA LVDS panel
|
||||
|
||||
This binding is compatible with the simple-panel binding, which is specified
|
||||
in simple-panel.txt in this directory.
|
||||
|
||||
Required properties:
|
||||
- compatible: should be "koe,tx31d200vm0baa"
|
||||
|
||||
Optional properties:
|
||||
- backlight: phandle of the backlight device attached to the panel
|
||||
|
||||
Optional nodes:
|
||||
- Video port for LVDS panel input.
|
||||
|
||||
Example:
|
||||
panel {
|
||||
compatible = "koe,tx31d200vm0baa";
|
||||
backlight = <&backlight_lvds>;
|
||||
|
||||
port {
|
||||
panel_in: endpoint {
|
||||
remote-endpoint = <&lvds0_out>;
|
||||
};
|
||||
};
|
||||
};
|
@ -9,6 +9,7 @@ Required properties:
|
||||
|
||||
Optional properties:
|
||||
- reset-gpios: a GPIO spec for the reset pin (active low).
|
||||
- power-supply: phandle of the regulator that provides the supply voltage.
|
||||
|
||||
Example:
|
||||
&dsi {
|
||||
@ -17,5 +18,6 @@ Example:
|
||||
compatible = "orisetech,otm8009a";
|
||||
reg = <0>;
|
||||
reset-gpios = <&gpioh 7 GPIO_ACTIVE_LOW>;
|
||||
power-supply = <&v1v8>;
|
||||
};
|
||||
};
|
||||
|
@ -0,0 +1,25 @@
|
||||
Raydium Semiconductor Corporation RM68200 5.5" 720p MIPI-DSI TFT LCD panel
|
||||
|
||||
The Raydium Semiconductor Corporation RM68200 is a 5.5" 720x1280 TFT LCD
|
||||
panel connected using a MIPI-DSI video interface.
|
||||
|
||||
Required properties:
|
||||
- compatible: "raydium,rm68200"
|
||||
- reg: the virtual channel number of a DSI peripheral
|
||||
|
||||
Optional properties:
|
||||
- reset-gpios: a GPIO spec for the reset pin (active low).
|
||||
- power-supply: phandle of the regulator that provides the supply voltage.
|
||||
- backlight: phandle of the backlight device attached to the panel.
|
||||
|
||||
Example:
|
||||
&dsi {
|
||||
...
|
||||
panel@0 {
|
||||
compatible = "raydium,rm68200";
|
||||
reg = <0>;
|
||||
reset-gpios = <&gpiof 15 GPIO_ACTIVE_LOW>;
|
||||
power-supply = <&v1v8>;
|
||||
backlight = <&pwm_backlight>;
|
||||
};
|
||||
};
|
@ -1,4 +1,8 @@
|
||||
Simple display panel
|
||||
====================
|
||||
|
||||
panel node
|
||||
----------
|
||||
|
||||
Required properties:
|
||||
- power-supply: See panel-common.txt
|
||||
|
@ -13,13 +13,10 @@ Required Properties:
|
||||
- "renesas,du-r8a7794" for R8A7794 (R-Car E2) compatible DU
|
||||
- "renesas,du-r8a7795" for R8A7795 (R-Car H3) compatible DU
|
||||
- "renesas,du-r8a7796" for R8A7796 (R-Car M3-W) compatible DU
|
||||
- "renesas,du-r8a77970" for R8A77970 (R-Car V3M) compatible DU
|
||||
- "renesas,du-r8a77995" for R8A77995 (R-Car D3) compatible DU
|
||||
|
||||
- reg: A list of base address and length of each memory resource, one for
|
||||
each entry in the reg-names property.
|
||||
- reg-names: Name of the memory resources. The DU requires one memory
|
||||
resource for the DU core (named "du") and one memory resource for each
|
||||
LVDS encoder (named "lvds.x" with "x" being the LVDS controller numerical
|
||||
index).
|
||||
- reg: the memory-mapped I/O registers base address and length
|
||||
|
||||
- interrupt-parent: phandle of the parent interrupt controller.
|
||||
- interrupts: Interrupt specifiers for the DU interrupts.
|
||||
@ -29,14 +26,13 @@ Required Properties:
|
||||
- clock-names: Name of the clocks. This property is model-dependent.
|
||||
- R8A7779 uses a single functional clock. The clock doesn't need to be
|
||||
named.
|
||||
- All other DU instances use one functional clock per channel and one
|
||||
clock per LVDS encoder (if available). The functional clocks must be
|
||||
named "du.x" with "x" being the channel numerical index. The LVDS clocks
|
||||
must be named "lvds.x" with "x" being the LVDS encoder numerical index.
|
||||
- In addition to the functional and encoder clocks, all DU versions also
|
||||
support externally supplied pixel clocks. Those clocks are optional.
|
||||
When supplied they must be named "dclkin.x" with "x" being the input
|
||||
clock numerical index.
|
||||
- All other DU instances use one functional clock per channel The
|
||||
functional clocks must be named "du.x" with "x" being the channel
|
||||
numerical index.
|
||||
- In addition to the functional clocks, all DU versions also support
|
||||
externally supplied pixel clocks. Those clocks are optional. When
|
||||
supplied they must be named "dclkin.x" with "x" being the input clock
|
||||
numerical index.
|
||||
|
||||
- vsps: A list of phandle and channel index tuples to the VSPs that handle
|
||||
the memory interfaces for the DU channels. The phandle identifies the VSP
|
||||
@ -63,15 +59,15 @@ corresponding to each DU output.
|
||||
R8A7794 (R-Car E2) DPAD 0 DPAD 1 - -
|
||||
R8A7795 (R-Car H3) DPAD 0 HDMI 0 HDMI 1 LVDS 0
|
||||
R8A7796 (R-Car M3-W) DPAD 0 HDMI 0 LVDS 0 -
|
||||
R8A77970 (R-Car V3M) DPAD 0 LVDS 0 - -
|
||||
R8A77995 (R-Car D3) DPAD 0 LVDS 0 LVDS 1 -
|
||||
|
||||
|
||||
Example: R8A7795 (R-Car H3) ES2.0 DU
|
||||
|
||||
du: display@feb00000 {
|
||||
compatible = "renesas,du-r8a7795";
|
||||
reg = <0 0xfeb00000 0 0x80000>,
|
||||
<0 0xfeb90000 0 0x14>;
|
||||
reg-names = "du", "lvds.0";
|
||||
reg = <0 0xfeb00000 0 0x80000>;
|
||||
interrupts = <GIC_SPI 256 IRQ_TYPE_LEVEL_HIGH>,
|
||||
<GIC_SPI 268 IRQ_TYPE_LEVEL_HIGH>,
|
||||
<GIC_SPI 269 IRQ_TYPE_LEVEL_HIGH>,
|
||||
@ -79,9 +75,8 @@ Example: R8A7795 (R-Car H3) ES2.0 DU
|
||||
clocks = <&cpg CPG_MOD 724>,
|
||||
<&cpg CPG_MOD 723>,
|
||||
<&cpg CPG_MOD 722>,
|
||||
<&cpg CPG_MOD 721>,
|
||||
<&cpg CPG_MOD 727>;
|
||||
clock-names = "du.0", "du.1", "du.2", "du.3", "lvds.0";
|
||||
<&cpg CPG_MOD 721>;
|
||||
clock-names = "du.0", "du.1", "du.2", "du.3";
|
||||
vsps = <&vspd0 0>, <&vspd1 0>, <&vspd2 0>, <&vspd0 1>;
|
||||
|
||||
ports {
|
||||
|
@ -0,0 +1,74 @@
|
||||
Rockchip RK3399 specific extensions to the cdn Display Port
|
||||
================================
|
||||
|
||||
Required properties:
|
||||
- compatible: must be "rockchip,rk3399-cdn-dp"
|
||||
|
||||
- reg: physical base address of the controller and length
|
||||
|
||||
- clocks: from common clock binding: handle to dp clock.
|
||||
|
||||
- clock-names: from common clock binding:
|
||||
Required elements: "core-clk" "pclk" "spdif" "grf"
|
||||
|
||||
- resets : a list of phandle + reset specifier pairs
|
||||
- reset-names : string of reset names
|
||||
Required elements: "apb", "core", "dptx", "spdif"
|
||||
- power-domains : power-domain property defined with a phandle
|
||||
to respective power domain.
|
||||
- assigned-clocks: main clock, should be <&cru SCLK_DP_CORE>
|
||||
- assigned-clock-rates : the DP core clk frequency, shall be: 100000000
|
||||
|
||||
- rockchip,grf: this soc should set GRF regs, so need get grf here.
|
||||
|
||||
- ports: contain a port nodes with endpoint definitions as defined in
|
||||
Documentation/devicetree/bindings/media/video-interfaces.txt.
|
||||
contained 2 endpoints, connecting to the output of vop.
|
||||
|
||||
- phys: from general PHY binding: the phandle for the PHY device.
|
||||
|
||||
- extcon: extcon specifier for the Power Delivery
|
||||
|
||||
- #sound-dai-cells = it must be 1 if your system is using 2 DAIs: I2S, SPDIF
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
Example:
|
||||
cdn_dp: dp@fec00000 {
|
||||
compatible = "rockchip,rk3399-cdn-dp";
|
||||
reg = <0x0 0xfec00000 0x0 0x100000>;
|
||||
interrupts = <GIC_SPI 9 IRQ_TYPE_LEVEL_HIGH>;
|
||||
clocks = <&cru SCLK_DP_CORE>, <&cru PCLK_DP_CTRL>,
|
||||
<&cru SCLK_SPDIF_REC_DPTX>, <&cru PCLK_VIO_GRF>;
|
||||
clock-names = "core-clk", "pclk", "spdif", "grf";
|
||||
assigned-clocks = <&cru SCLK_DP_CORE>;
|
||||
assigned-clock-rates = <100000000>;
|
||||
power-domains = <&power RK3399_PD_HDCP>;
|
||||
phys = <&tcphy0_dp>, <&tcphy1_dp>;
|
||||
resets = <&cru SRST_DPTX_SPDIF_REC>;
|
||||
reset-names = "spdif";
|
||||
extcon = <&fusb0>, <&fusb1>;
|
||||
rockchip,grf = <&grf>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
#sound-dai-cells = <1>;
|
||||
|
||||
ports {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
dp_in: port {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
dp_in_vopb: endpoint@0 {
|
||||
reg = <0>;
|
||||
remote-endpoint = <&vopb_out_dp>;
|
||||
};
|
||||
|
||||
dp_in_vopl: endpoint@1 {
|
||||
reg = <1>;
|
||||
remote-endpoint = <&vopl_out_dp>;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
@ -98,7 +98,7 @@ Example 2: DSI panel
|
||||
compatible = "st,stm32-dsi";
|
||||
reg = <0x40016c00 0x800>;
|
||||
clocks = <&rcc 1 CLK_F469_DSI>, <&clk_hse>;
|
||||
clock-names = "ref", "pclk";
|
||||
clock-names = "pclk", "ref";
|
||||
resets = <&rcc STM32F4_APB2_RESET(DSI)>;
|
||||
reset-names = "apb";
|
||||
|
||||
|
@ -64,6 +64,56 @@ Required properties:
|
||||
first port should be the input endpoint. The second should be the
|
||||
output, usually to an HDMI connector.
|
||||
|
||||
DWC HDMI TX Encoder
|
||||
-------------------
|
||||
|
||||
The HDMI transmitter is a Synopsys DesignWare HDMI 1.4 TX controller IP
|
||||
with Allwinner's own PHY IP. It supports audio and video outputs and CEC.
|
||||
|
||||
These DT bindings follow the Synopsys DWC HDMI TX bindings defined in
|
||||
Documentation/devicetree/bindings/display/bridge/dw_hdmi.txt with the
|
||||
following device-specific properties.
|
||||
|
||||
Required properties:
|
||||
|
||||
- compatible: value must be one of:
|
||||
* "allwinner,sun8i-a83t-dw-hdmi"
|
||||
- reg: base address and size of memory-mapped region
|
||||
- reg-io-width: See dw_hdmi.txt. Shall be 1.
|
||||
- interrupts: HDMI interrupt number
|
||||
- clocks: phandles to the clocks feeding the HDMI encoder
|
||||
* iahb: the HDMI bus clock
|
||||
* isfr: the HDMI register clock
|
||||
* tmds: TMDS clock
|
||||
- clock-names: the clock names mentioned above
|
||||
- resets: phandle to the reset controller
|
||||
- reset-names: must be "ctrl"
|
||||
- phys: phandle to the DWC HDMI PHY
|
||||
- phy-names: must be "phy"
|
||||
|
||||
- ports: A ports node with endpoint definitions as defined in
|
||||
Documentation/devicetree/bindings/media/video-interfaces.txt. The
|
||||
first port should be the input endpoint. The second should be the
|
||||
output, usually to an HDMI connector.
|
||||
|
||||
DWC HDMI PHY
|
||||
------------
|
||||
|
||||
Required properties:
|
||||
- compatible: value must be one of:
|
||||
* allwinner,sun8i-a83t-hdmi-phy
|
||||
* allwinner,sun8i-h3-hdmi-phy
|
||||
- reg: base address and size of memory-mapped region
|
||||
- clocks: phandles to the clocks feeding the HDMI PHY
|
||||
* bus: the HDMI PHY interface clock
|
||||
* mod: the HDMI PHY module clock
|
||||
- clock-names: the clock names mentioned above
|
||||
- resets: phandle to the reset controller driving the PHY
|
||||
- reset-names: must be "phy"
|
||||
|
||||
H3 HDMI PHY requires additional clock:
|
||||
- pll-0: parent of phy clock
|
||||
|
||||
TV Encoder
|
||||
----------
|
||||
|
||||
@ -94,24 +144,29 @@ Required properties:
|
||||
* allwinner,sun7i-a20-tcon
|
||||
* allwinner,sun8i-a33-tcon
|
||||
* allwinner,sun8i-a83t-tcon-lcd
|
||||
* allwinner,sun8i-a83t-tcon-tv
|
||||
* allwinner,sun8i-v3s-tcon
|
||||
* allwinner,sun9i-a80-tcon-lcd
|
||||
* allwinner,sun9i-a80-tcon-tv
|
||||
- reg: base address and size of memory-mapped region
|
||||
- interrupts: interrupt associated to this IP
|
||||
- clocks: phandles to the clocks feeding the TCON. Three are needed:
|
||||
- clocks: phandles to the clocks feeding the TCON.
|
||||
- 'ahb': the interface clocks
|
||||
- 'tcon-ch0': The clock driving the TCON channel 0
|
||||
- 'tcon-ch0': The clock driving the TCON channel 0, if supported
|
||||
- resets: phandles to the reset controllers driving the encoder
|
||||
- "lcd": the reset line for the TCON channel 0
|
||||
- "lcd": the reset line for the TCON
|
||||
- "edp": the reset line for the eDP block (A80 only)
|
||||
|
||||
- clock-names: the clock names mentioned above
|
||||
- reset-names: the reset names mentioned above
|
||||
- clock-output-names: Name of the pixel clock created
|
||||
- clock-output-names: Name of the pixel clock created, if TCON supports
|
||||
channel 0.
|
||||
|
||||
- ports: A ports node with endpoint definitions as defined in
|
||||
Documentation/devicetree/bindings/media/video-interfaces.txt. The
|
||||
first port should be the input endpoint, the second one the output
|
||||
|
||||
The output may have multiple endpoints. The TCON has two channels,
|
||||
The output may have multiple endpoints. TCON can have 1 or 2 channels,
|
||||
usually with the first channel being used for the panels interfaces
|
||||
(RGB, LVDS, etc.), and the second being used for the outputs that
|
||||
require another controller (TV Encoder, HDMI, etc.). The endpoints
|
||||
@ -119,11 +174,13 @@ Required properties:
|
||||
channel the endpoint is associated to. If that property is not
|
||||
present, the endpoint number will be used as the channel number.
|
||||
|
||||
On SoCs other than the A33 and V3s, there is one more clock required:
|
||||
For TCONs with channel 0, there is one more clock required:
|
||||
- 'tcon-ch0': The clock driving the TCON channel 0
|
||||
For TCONs with channel 1, there is one more clock required:
|
||||
- 'tcon-ch1': The clock driving the TCON channel 1
|
||||
|
||||
On SoCs that support LVDS (all SoCs but the A13, H3, H5 and V3s), you
|
||||
need one more reset line:
|
||||
When TCON support LVDS (all TCONs except TV TCON on A83T and those found
|
||||
in A13, H3, H5 and V3s SoCs), you need one more reset line:
|
||||
- 'lvds': The reset line driving the LVDS logic
|
||||
|
||||
And on the A23, A31, A31s and A33, you need one more clock line:
|
||||
@ -134,7 +191,7 @@ DRC
|
||||
---
|
||||
|
||||
The DRC (Dynamic Range Controller), found in the latest Allwinner SoCs
|
||||
(A31, A23, A33), allows to dynamically adjust pixel
|
||||
(A31, A23, A33, A80), allows to dynamically adjust pixel
|
||||
brightness/contrast based on histogram measurements for LCD content
|
||||
adaptive backlight control.
|
||||
|
||||
@ -144,6 +201,7 @@ Required properties:
|
||||
* allwinner,sun6i-a31-drc
|
||||
* allwinner,sun6i-a31s-drc
|
||||
* allwinner,sun8i-a33-drc
|
||||
* allwinner,sun9i-a80-drc
|
||||
- reg: base address and size of the memory-mapped region.
|
||||
- interrupts: interrupt associated to this IP
|
||||
- clocks: phandles to the clocks feeding the DRC
|
||||
@ -170,6 +228,7 @@ Required properties:
|
||||
* allwinner,sun6i-a31-display-backend
|
||||
* allwinner,sun7i-a20-display-backend
|
||||
* allwinner,sun8i-a33-display-backend
|
||||
* allwinner,sun9i-a80-display-backend
|
||||
- reg: base address and size of the memory-mapped region.
|
||||
- interrupts: interrupt associated to this IP
|
||||
- clocks: phandles to the clocks feeding the frontend and backend
|
||||
@ -191,6 +250,28 @@ On the A33, some additional properties are required:
|
||||
- resets and reset-names need to have a phandle to the SAT bus
|
||||
resets, whose name will be "sat"
|
||||
|
||||
DEU
|
||||
---
|
||||
|
||||
The DEU (Detail Enhancement Unit), found in the Allwinner A80 SoC,
|
||||
can sharpen the display content in both luma and chroma channels.
|
||||
|
||||
Required properties:
|
||||
- compatible: value must be one of:
|
||||
* allwinner,sun9i-a80-deu
|
||||
- reg: base address and size of the memory-mapped region.
|
||||
- interrupts: interrupt associated to this IP
|
||||
- clocks: phandles to the clocks feeding the DEU
|
||||
* ahb: the DEU interface clock
|
||||
* mod: the DEU module clock
|
||||
* ram: the DEU DRAM clock
|
||||
- clock-names: the clock names mentioned above
|
||||
- resets: phandles to the reset line driving the DEU
|
||||
|
||||
- ports: A ports node with endpoint definitions as defined in
|
||||
Documentation/devicetree/bindings/media/video-interfaces.txt. The
|
||||
first port should be the input endpoints, the second one the outputs
|
||||
|
||||
Display Engine Frontend
|
||||
-----------------------
|
||||
|
||||
@ -204,6 +285,7 @@ Required properties:
|
||||
* allwinner,sun6i-a31-display-frontend
|
||||
* allwinner,sun7i-a20-display-frontend
|
||||
* allwinner,sun8i-a33-display-frontend
|
||||
* allwinner,sun9i-a80-display-frontend
|
||||
- reg: base address and size of the memory-mapped region.
|
||||
- interrupts: interrupt associated to this IP
|
||||
- clocks: phandles to the clocks feeding the frontend and backend
|
||||
@ -226,6 +308,8 @@ supported.
|
||||
Required properties:
|
||||
- compatible: value must be one of:
|
||||
* allwinner,sun8i-a83t-de2-mixer-0
|
||||
* allwinner,sun8i-a83t-de2-mixer-1
|
||||
* allwinner,sun8i-h3-de2-mixer-0
|
||||
* allwinner,sun8i-v3s-de2-mixer
|
||||
- reg: base address and size of the memory-mapped region.
|
||||
- clocks: phandles to the clocks feeding the mixer
|
||||
@ -256,7 +340,9 @@ Required properties:
|
||||
* allwinner,sun7i-a20-display-engine
|
||||
* allwinner,sun8i-a33-display-engine
|
||||
* allwinner,sun8i-a83t-display-engine
|
||||
* allwinner,sun8i-h3-display-engine
|
||||
* allwinner,sun8i-v3s-display-engine
|
||||
* allwinner,sun9i-a80-display-engine
|
||||
|
||||
- allwinner,pipelines: list of phandle to the display engine
|
||||
frontends (DE 1.0) or mixers (DE 2.0) available.
|
||||
|
@ -3,11 +3,11 @@ Device-Tree bindings for sigma delta modulator
|
||||
Required properties:
|
||||
- compatible: should be "ads1201", "sd-modulator". "sd-modulator" can be use
|
||||
as a generic SD modulator if modulator not specified in compatible list.
|
||||
- #io-channel-cells = <1>: See the IIO bindings section "IIO consumers".
|
||||
- #io-channel-cells = <0>: See the IIO bindings section "IIO consumers".
|
||||
|
||||
Example node:
|
||||
|
||||
ads1202: adc@0 {
|
||||
compatible = "sd-modulator";
|
||||
#io-channel-cells = <1>;
|
||||
#io-channel-cells = <0>;
|
||||
};
|
||||
|
@ -50,14 +50,15 @@ Example:
|
||||
compatible = "marvell,mv88e6085";
|
||||
reg = <0>;
|
||||
reset-gpios = <&gpio5 1 GPIO_ACTIVE_LOW>;
|
||||
};
|
||||
mdio {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
switch1phy0: switch1phy0@0 {
|
||||
reg = <0>;
|
||||
interrupt-parent = <&switch0>;
|
||||
interrupts = <0 IRQ_TYPE_LEVEL_HIGH>;
|
||||
|
||||
mdio {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
switch1phy0: switch1phy0@0 {
|
||||
reg = <0>;
|
||||
interrupt-parent = <&switch0>;
|
||||
interrupts = <0 IRQ_TYPE_LEVEL_HIGH>;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
@ -74,23 +75,24 @@ Example:
|
||||
compatible = "marvell,mv88e6390";
|
||||
reg = <0>;
|
||||
reset-gpios = <&gpio5 1 GPIO_ACTIVE_LOW>;
|
||||
};
|
||||
mdio {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
switch1phy0: switch1phy0@0 {
|
||||
reg = <0>;
|
||||
interrupt-parent = <&switch0>;
|
||||
interrupts = <0 IRQ_TYPE_LEVEL_HIGH>;
|
||||
};
|
||||
};
|
||||
|
||||
mdio1 {
|
||||
compatible = "marvell,mv88e6xxx-mdio-external";
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
switch1phy9: switch1phy0@9 {
|
||||
reg = <9>;
|
||||
mdio {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
switch1phy0: switch1phy0@0 {
|
||||
reg = <0>;
|
||||
interrupt-parent = <&switch0>;
|
||||
interrupts = <0 IRQ_TYPE_LEVEL_HIGH>;
|
||||
};
|
||||
};
|
||||
|
||||
mdio1 {
|
||||
compatible = "marvell,mv88e6xxx-mdio-external";
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
switch1phy9: switch1phy0@9 {
|
||||
reg = <9>;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
@ -27,7 +27,11 @@ Required properties:
|
||||
SoC-specific version corresponding to the platform first followed by
|
||||
the generic version.
|
||||
|
||||
- reg: offset and length of (1) the register block and (2) the stream buffer.
|
||||
- reg: Offset and length of (1) the register block and (2) the stream buffer.
|
||||
The region for the register block is mandatory.
|
||||
The region for the stream buffer is optional, as it is only present on
|
||||
R-Car Gen2 and RZ/G1 SoCs, and on R-Car H3 (R8A7795), M3-W (R8A7796),
|
||||
and M3-N (R8A77965).
|
||||
- interrupts: A list of interrupt-specifiers, one for each entry in
|
||||
interrupt-names.
|
||||
If interrupt-names is not present, an interrupt specifier
|
||||
|
@ -104,6 +104,7 @@ eeti eGalax_eMPIA Technology Inc
|
||||
elan Elan Microelectronic Corp.
|
||||
embest Shenzhen Embest Technology Co., Ltd.
|
||||
emmicro EM Microelectronic
|
||||
emtrion emtrion GmbH
|
||||
energymicro Silicon Laboratories (formerly Energy Micro AS)
|
||||
engicam Engicam S.r.l.
|
||||
epcos EPCOS AG
|
||||
|
@ -87,8 +87,8 @@ Overlay in-kernel API
|
||||
|
||||
The API is quite easy to use.
|
||||
|
||||
1. Call of_overlay_apply() to create and apply an overlay changeset. The return
|
||||
value is an error or a cookie identifying this overlay.
|
||||
1. Call of_overlay_fdt_apply() to create and apply an overlay changeset. The
|
||||
return value is an error or a cookie identifying this overlay.
|
||||
|
||||
2. Call of_overlay_remove() to remove and cleanup the overlay changeset
|
||||
previously created via the call to of_overlay_apply(). Removal of an overlay
|
||||
|
21
Documentation/gpu/drivers.rst
Normal file
21
Documentation/gpu/drivers.rst
Normal file
@ -0,0 +1,21 @@
|
||||
========================
|
||||
GPU Driver Documentation
|
||||
========================
|
||||
|
||||
.. toctree::
|
||||
|
||||
i915
|
||||
meson
|
||||
pl111
|
||||
tegra
|
||||
tinydrm
|
||||
tve200
|
||||
vc4
|
||||
bridge/dw-hdmi
|
||||
|
||||
.. only:: subproject and html
|
||||
|
||||
Indices
|
||||
=======
|
||||
|
||||
* :ref:`genindex`
|
@ -286,6 +286,9 @@ Atomic Mode Setting Function Reference
|
||||
.. kernel-doc:: drivers/gpu/drm/drm_atomic.c
|
||||
:export:
|
||||
|
||||
.. kernel-doc:: drivers/gpu/drm/drm_atomic.c
|
||||
:internal:
|
||||
|
||||
CRTC Abstraction
|
||||
================
|
||||
|
||||
@ -547,8 +550,9 @@ Explicit Fencing Properties
|
||||
Existing KMS Properties
|
||||
-----------------------
|
||||
|
||||
The following table gives description of drm properties exposed by
|
||||
various modules/drivers.
|
||||
The following table gives description of drm properties exposed by various
|
||||
modules/drivers. Because this table is very unwieldy, do not add any new
|
||||
properties here. Instead document them in a section above.
|
||||
|
||||
.. csv-table::
|
||||
:header-rows: 1
|
||||
|
@ -10,16 +10,9 @@ Linux GPU Driver Developer's Guide
|
||||
drm-kms
|
||||
drm-kms-helpers
|
||||
drm-uapi
|
||||
i915
|
||||
meson
|
||||
pl111
|
||||
tegra
|
||||
tinydrm
|
||||
tve200
|
||||
vc4
|
||||
drivers
|
||||
vga-switcheroo
|
||||
vgaarbiter
|
||||
bridge/dw-hdmi
|
||||
todo
|
||||
|
||||
.. only:: subproject and html
|
||||
|
@ -1,5 +1,4 @@
|
||||
Owner Module/Drivers,Group,Property Name,Type,Property Values,Object attached,Description/Restrictions
|
||||
,,“scaling mode”,ENUM,"{ ""None"", ""Full"", ""Center"", ""Full aspect"" }",Connector,"Supported by: amdgpu, gma500, i915, nouveau and radeon."
|
||||
,DVI-I,“subconnector”,ENUM,"{ “Unknown”, “DVI-D”, “DVI-A” }",Connector,TBD
|
||||
,,“select subconnector”,ENUM,"{ “Automatic”, “DVI-D”, “DVI-A” }",Connector,TBD
|
||||
,TV,“subconnector”,ENUM,"{ ""Unknown"", ""Composite"", ""SVIDEO"", ""Component"", ""SCART"" }",Connector,TBD
|
||||
|
|
@ -212,6 +212,16 @@ probably use drm_fb_helper_fbdev_teardown().
|
||||
|
||||
Contact: Maintainer of the driver you plan to convert
|
||||
|
||||
idr_init_base()
|
||||
---------------
|
||||
|
||||
DRM core&drivers uses a lot of idr (integer lookup directories) for mapping
|
||||
userspace IDs to internal objects, and in most places ID=0 means NULL and hence
|
||||
is never used. Switching to idr_init_base() for these would make the idr more
|
||||
efficient.
|
||||
|
||||
Contact: Daniel Vetter
|
||||
|
||||
Core refactorings
|
||||
=================
|
||||
|
||||
@ -440,5 +450,12 @@ See drivers/gpu/drm/amd/display/TODO for tasks.
|
||||
|
||||
Contact: Harry Wentland, Alex Deucher
|
||||
|
||||
i915
|
||||
----
|
||||
|
||||
- Our early/late pm callbacks could be removed in favour of using
|
||||
device_link_add to model the dependency between i915 and snd_had. See
|
||||
https://dri.freedesktop.org/docs/drm/driver-api/device_link.html
|
||||
|
||||
Outside DRM
|
||||
===========
|
||||
|
@ -20,8 +20,8 @@ TCP Segmentation Offload
|
||||
|
||||
TCP segmentation allows a device to segment a single frame into multiple
|
||||
frames with a data payload size specified in skb_shinfo()->gso_size.
|
||||
When TCP segmentation requested the bit for either SKB_GSO_TCP or
|
||||
SKB_GSO_TCP6 should be set in skb_shinfo()->gso_type and
|
||||
When TCP segmentation requested the bit for either SKB_GSO_TCPV4 or
|
||||
SKB_GSO_TCPV6 should be set in skb_shinfo()->gso_type and
|
||||
skb_shinfo()->gso_size should be set to a non-zero value.
|
||||
|
||||
TCP segmentation is dependent on support for the use of partial checksum
|
||||
@ -153,8 +153,18 @@ To signal this, gso_size is set to the special value GSO_BY_FRAGS.
|
||||
|
||||
Therefore, any code in the core networking stack must be aware of the
|
||||
possibility that gso_size will be GSO_BY_FRAGS and handle that case
|
||||
appropriately. (For size checks, the skb_gso_validate_*_len family of
|
||||
helpers do this automatically.)
|
||||
appropriately.
|
||||
|
||||
There are some helpers to make this easier:
|
||||
|
||||
- skb_is_gso(skb) && skb_is_gso_sctp(skb) is the best way to see if
|
||||
an skb is an SCTP GSO skb.
|
||||
|
||||
- For size checks, the skb_gso_validate_*_len family of helpers correctly
|
||||
considers GSO_BY_FRAGS.
|
||||
|
||||
- For manipulating packets, skb_increase_gso_size and skb_decrease_gso_size
|
||||
will check for GSO_BY_FRAGS and WARN if asked to manipulate these skbs.
|
||||
|
||||
This also affects drivers with the NETIF_F_FRAGLIST & NETIF_F_GSO_SCTP bits
|
||||
set. Note also that NETIF_F_GSO_SCTP is included in NETIF_F_GSO_SOFTWARE.
|
||||
|
15
MAINTAINERS
15
MAINTAINERS
@ -766,6 +766,8 @@ F: drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c
|
||||
F: drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.h
|
||||
F: drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v7.c
|
||||
F: drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v8.c
|
||||
F: drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_fence.c
|
||||
F: drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c
|
||||
F: drivers/gpu/drm/amd/amdkfd/
|
||||
F: drivers/gpu/drm/amd/include/cik_structs.h
|
||||
F: drivers/gpu/drm/amd/include/kgd_kfd_interface.h
|
||||
@ -4458,6 +4460,13 @@ T: git git://anongit.freedesktop.org/drm/drm-misc
|
||||
S: Supported
|
||||
F: drivers/gpu/drm/pl111/
|
||||
|
||||
DRM DRIVER FOR ARM VERSATILE TFT PANELS
|
||||
M: Linus Walleij <linus.walleij@linaro.org>
|
||||
T: git git://anongit.freedesktop.org/drm/drm-misc
|
||||
S: Maintained
|
||||
F: drivers/gpu/drm/panel/panel-arm-versatile.c
|
||||
F: Documentation/devicetree/bindings/display/panel/arm,versatile-tft-panel.txt
|
||||
|
||||
DRM DRIVER FOR AST SERVER GRAPHICS CHIPS
|
||||
M: Dave Airlie <airlied@redhat.com>
|
||||
S: Odd Fixes
|
||||
@ -4612,8 +4621,8 @@ F: include/uapi/drm/
|
||||
F: include/linux/vga*
|
||||
|
||||
DRM DRIVERS AND MISC GPU PATCHES
|
||||
M: Daniel Vetter <daniel.vetter@intel.com>
|
||||
M: Gustavo Padovan <gustavo@padovan.org>
|
||||
M: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
|
||||
M: Sean Paul <seanpaul@chromium.org>
|
||||
W: https://01.org/linuxgraphics/gfx-docs/maintainer-tools/drm-misc.html
|
||||
S: Maintained
|
||||
@ -4739,6 +4748,7 @@ F: drivers/gpu/drm/rcar-du/
|
||||
F: drivers/gpu/drm/shmobile/
|
||||
F: include/linux/platform_data/shmob_drm.h
|
||||
F: Documentation/devicetree/bindings/display/bridge/renesas,dw-hdmi.txt
|
||||
F: Documentation/devicetree/bindings/display/bridge/renesas,lvds.txt
|
||||
F: Documentation/devicetree/bindings/display/renesas,du.txt
|
||||
|
||||
DRM DRIVERS FOR ROCKCHIP
|
||||
@ -10334,7 +10344,7 @@ F: drivers/oprofile/
|
||||
F: include/linux/oprofile.h
|
||||
|
||||
ORACLE CLUSTER FILESYSTEM 2 (OCFS2)
|
||||
M: Mark Fasheh <mfasheh@versity.com>
|
||||
M: Mark Fasheh <mark@fasheh.com>
|
||||
M: Joel Becker <jlbec@evilplan.org>
|
||||
L: ocfs2-devel@oss.oracle.com (moderated for non-subscribers)
|
||||
W: http://ocfs2.wiki.kernel.org
|
||||
@ -10844,6 +10854,7 @@ F: drivers/platform/x86/peaq-wmi.c
|
||||
PER-CPU MEMORY ALLOCATOR
|
||||
M: Tejun Heo <tj@kernel.org>
|
||||
M: Christoph Lameter <cl@linux.com>
|
||||
M: Dennis Zhou <dennisszhou@gmail.com>
|
||||
T: git git://git.kernel.org/pub/scm/linux/kernel/git/tj/percpu.git
|
||||
S: Maintained
|
||||
F: include/linux/percpu*.h
|
||||
|
11
Makefile
11
Makefile
@ -2,7 +2,7 @@
|
||||
VERSION = 4
|
||||
PATCHLEVEL = 16
|
||||
SUBLEVEL = 0
|
||||
EXTRAVERSION = -rc6
|
||||
EXTRAVERSION = -rc7
|
||||
NAME = Fearless Coyote
|
||||
|
||||
# *DOCUMENTATION*
|
||||
@ -826,6 +826,15 @@ KBUILD_CFLAGS += $(call cc-disable-warning, pointer-sign)
|
||||
# disable invalid "can't wrap" optimizations for signed / pointers
|
||||
KBUILD_CFLAGS += $(call cc-option,-fno-strict-overflow)
|
||||
|
||||
# clang sets -fmerge-all-constants by default as optimization, but this
|
||||
# is non-conforming behavior for C and in fact breaks the kernel, so we
|
||||
# need to disable it here generally.
|
||||
KBUILD_CFLAGS += $(call cc-option,-fno-merge-all-constants)
|
||||
|
||||
# for gcc -fno-merge-all-constants disables everything, but it is fine
|
||||
# to have actual conforming behavior enabled.
|
||||
KBUILD_CFLAGS += $(call cc-option,-fmerge-constants)
|
||||
|
||||
# Make sure -fstack-check isn't enabled (like gentoo apparently did)
|
||||
KBUILD_CFLAGS += $(call cc-option,-fno-stack-check,)
|
||||
|
||||
|
@ -972,3 +972,13 @@ int pmd_clear_huge(pmd_t *pmdp)
|
||||
pmd_clear(pmdp);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int pud_free_pmd_page(pud_t *pud)
|
||||
{
|
||||
return pud_none(*pud);
|
||||
}
|
||||
|
||||
int pmd_free_pte_page(pmd_t *pmd)
|
||||
{
|
||||
return pmd_none(*pmd);
|
||||
}
|
||||
|
@ -2,7 +2,6 @@
|
||||
#ifndef __H8300_BYTEORDER_H__
|
||||
#define __H8300_BYTEORDER_H__
|
||||
|
||||
#define __BIG_ENDIAN __ORDER_BIG_ENDIAN__
|
||||
#include <linux/byteorder/big_endian.h>
|
||||
|
||||
#endif
|
||||
|
@ -13,6 +13,8 @@ choice
|
||||
config SOC_AMAZON_SE
|
||||
bool "Amazon SE"
|
||||
select SOC_TYPE_XWAY
|
||||
select MFD_SYSCON
|
||||
select MFD_CORE
|
||||
|
||||
config SOC_XWAY
|
||||
bool "XWAY"
|
||||
|
@ -549,9 +549,9 @@ void __init ltq_soc_init(void)
|
||||
clkdev_add_static(ltq_ar9_cpu_hz(), ltq_ar9_fpi_hz(),
|
||||
ltq_ar9_fpi_hz(), CLOCK_250M);
|
||||
clkdev_add_pmu("1f203018.usb2-phy", "phy", 1, 0, PMU_USB0_P);
|
||||
clkdev_add_pmu("1e101000.usb", "otg", 1, 0, PMU_USB0);
|
||||
clkdev_add_pmu("1e101000.usb", "otg", 1, 0, PMU_USB0 | PMU_AHBM);
|
||||
clkdev_add_pmu("1f203034.usb2-phy", "phy", 1, 0, PMU_USB1_P);
|
||||
clkdev_add_pmu("1e106000.usb", "otg", 1, 0, PMU_USB1);
|
||||
clkdev_add_pmu("1e106000.usb", "otg", 1, 0, PMU_USB1 | PMU_AHBM);
|
||||
clkdev_add_pmu("1e180000.etop", "switch", 1, 0, PMU_SWITCH);
|
||||
clkdev_add_pmu("1e103000.sdio", NULL, 1, 0, PMU_SDIO);
|
||||
clkdev_add_pmu("1e103100.deu", NULL, 1, 0, PMU_DEU);
|
||||
@ -560,7 +560,7 @@ void __init ltq_soc_init(void)
|
||||
} else {
|
||||
clkdev_add_static(ltq_danube_cpu_hz(), ltq_danube_fpi_hz(),
|
||||
ltq_danube_fpi_hz(), ltq_danube_pp32_hz());
|
||||
clkdev_add_pmu("1f203018.usb2-phy", "ctrl", 1, 0, PMU_USB0);
|
||||
clkdev_add_pmu("1e101000.usb", "otg", 1, 0, PMU_USB0 | PMU_AHBM);
|
||||
clkdev_add_pmu("1f203018.usb2-phy", "phy", 1, 0, PMU_USB0_P);
|
||||
clkdev_add_pmu("1e103000.sdio", NULL, 1, 0, PMU_SDIO);
|
||||
clkdev_add_pmu("1e103100.deu", NULL, 1, 0, PMU_DEU);
|
||||
|
@ -170,6 +170,28 @@ void prom_soc_init(struct ralink_soc_info *soc_info)
|
||||
u32 n1;
|
||||
u32 rev;
|
||||
|
||||
/* Early detection of CMP support */
|
||||
mips_cm_probe();
|
||||
mips_cpc_probe();
|
||||
|
||||
if (mips_cps_numiocu(0)) {
|
||||
/*
|
||||
* mips_cm_probe() wipes out bootloader
|
||||
* config for CM regions and we have to configure them
|
||||
* again. This SoC cannot talk to pamlbus devices
|
||||
* witout proper iocu region set up.
|
||||
*
|
||||
* FIXME: it would be better to do this with values
|
||||
* from DT, but we need this very early because
|
||||
* without this we cannot talk to pretty much anything
|
||||
* including serial.
|
||||
*/
|
||||
write_gcr_reg0_base(MT7621_PALMBUS_BASE);
|
||||
write_gcr_reg0_mask(~MT7621_PALMBUS_SIZE |
|
||||
CM_GCR_REGn_MASK_CMTGT_IOCU0);
|
||||
__sync();
|
||||
}
|
||||
|
||||
n0 = __raw_readl(sysc + SYSC_REG_CHIP_NAME0);
|
||||
n1 = __raw_readl(sysc + SYSC_REG_CHIP_NAME1);
|
||||
|
||||
@ -194,26 +216,6 @@ void prom_soc_init(struct ralink_soc_info *soc_info)
|
||||
|
||||
rt2880_pinmux_data = mt7621_pinmux_data;
|
||||
|
||||
/* Early detection of CMP support */
|
||||
mips_cm_probe();
|
||||
mips_cpc_probe();
|
||||
|
||||
if (mips_cps_numiocu(0)) {
|
||||
/*
|
||||
* mips_cm_probe() wipes out bootloader
|
||||
* config for CM regions and we have to configure them
|
||||
* again. This SoC cannot talk to pamlbus devices
|
||||
* witout proper iocu region set up.
|
||||
*
|
||||
* FIXME: it would be better to do this with values
|
||||
* from DT, but we need this very early because
|
||||
* without this we cannot talk to pretty much anything
|
||||
* including serial.
|
||||
*/
|
||||
write_gcr_reg0_base(MT7621_PALMBUS_BASE);
|
||||
write_gcr_reg0_mask(~MT7621_PALMBUS_SIZE |
|
||||
CM_GCR_REGn_MASK_CMTGT_IOCU0);
|
||||
}
|
||||
|
||||
if (!register_cps_smp_ops())
|
||||
return;
|
||||
|
@ -96,16 +96,9 @@ static void ralink_restart(char *command)
|
||||
unreachable();
|
||||
}
|
||||
|
||||
static void ralink_halt(void)
|
||||
{
|
||||
local_irq_disable();
|
||||
unreachable();
|
||||
}
|
||||
|
||||
static int __init mips_reboot_setup(void)
|
||||
{
|
||||
_machine_restart = ralink_restart;
|
||||
_machine_halt = ralink_halt;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -315,19 +315,6 @@ config X86_L1_CACHE_SHIFT
|
||||
default "4" if MELAN || M486 || MGEODEGX1
|
||||
default "5" if MWINCHIP3D || MWINCHIPC6 || MCRUSOE || MEFFICEON || MCYRIXIII || MK6 || MPENTIUMIII || MPENTIUMII || M686 || M586MMX || M586TSC || M586 || MVIAC3_2 || MGEODE_LX
|
||||
|
||||
config X86_PPRO_FENCE
|
||||
bool "PentiumPro memory ordering errata workaround"
|
||||
depends on M686 || M586MMX || M586TSC || M586 || M486 || MGEODEGX1
|
||||
---help---
|
||||
Old PentiumPro multiprocessor systems had errata that could cause
|
||||
memory operations to violate the x86 ordering standard in rare cases.
|
||||
Enabling this option will attempt to work around some (but not all)
|
||||
occurrences of this problem, at the cost of much heavier spinlock and
|
||||
memory barrier operations.
|
||||
|
||||
If unsure, say n here. Even distro kernels should think twice before
|
||||
enabling this: there are few systems, and an unlikely bug.
|
||||
|
||||
config X86_F00F_BUG
|
||||
def_bool y
|
||||
depends on M586MMX || M586TSC || M586 || M486
|
||||
|
@ -223,6 +223,15 @@ KBUILD_CFLAGS += $(cfi) $(cfi-sigframe) $(cfi-sections) $(asinstr) $(avx_instr)
|
||||
|
||||
LDFLAGS := -m elf_$(UTS_MACHINE)
|
||||
|
||||
#
|
||||
# The 64-bit kernel must be aligned to 2MB. Pass -z max-page-size=0x200000 to
|
||||
# the linker to force 2MB page size regardless of the default page size used
|
||||
# by the linker.
|
||||
#
|
||||
ifdef CONFIG_X86_64
|
||||
LDFLAGS += $(call ld-option, -z max-page-size=0x200000)
|
||||
endif
|
||||
|
||||
# Speed up the build
|
||||
KBUILD_CFLAGS += -pipe
|
||||
# Workaround for a gcc prelease that unfortunately was shipped in a suse release
|
||||
|
@ -309,6 +309,10 @@ static void parse_elf(void *output)
|
||||
|
||||
switch (phdr->p_type) {
|
||||
case PT_LOAD:
|
||||
#ifdef CONFIG_X86_64
|
||||
if ((phdr->p_align % 0x200000) != 0)
|
||||
error("Alignment of LOAD segment isn't multiple of 2MB");
|
||||
#endif
|
||||
#ifdef CONFIG_RELOCATABLE
|
||||
dest = output;
|
||||
dest += (phdr->p_paddr - LOAD_PHYSICAL_ADDR);
|
||||
|
@ -1138,7 +1138,7 @@ apicinterrupt3 HYPERV_REENLIGHTENMENT_VECTOR \
|
||||
#endif /* CONFIG_HYPERV */
|
||||
|
||||
idtentry debug do_debug has_error_code=0 paranoid=1 shift_ist=DEBUG_STACK
|
||||
idtentry int3 do_int3 has_error_code=0 paranoid=1 shift_ist=DEBUG_STACK
|
||||
idtentry int3 do_int3 has_error_code=0
|
||||
idtentry stack_segment do_stack_segment has_error_code=1
|
||||
|
||||
#ifdef CONFIG_XEN
|
||||
|
@ -5,8 +5,6 @@
|
||||
#undef CONFIG_OPTIMIZE_INLINING
|
||||
#endif
|
||||
|
||||
#undef CONFIG_X86_PPRO_FENCE
|
||||
|
||||
#ifdef CONFIG_X86_64
|
||||
|
||||
/*
|
||||
|
@ -347,7 +347,7 @@ void __init set_vsyscall_pgtable_user_bits(pgd_t *root)
|
||||
set_pgd(pgd, __pgd(pgd_val(*pgd) | _PAGE_USER));
|
||||
p4d = p4d_offset(pgd, VSYSCALL_ADDR);
|
||||
#if CONFIG_PGTABLE_LEVELS >= 5
|
||||
p4d->p4d |= _PAGE_USER;
|
||||
set_p4d(p4d, __p4d(p4d_val(*p4d) | _PAGE_USER));
|
||||
#endif
|
||||
pud = pud_offset(p4d, VSYSCALL_ADDR);
|
||||
set_pud(pud, __pud(pud_val(*pud) | _PAGE_USER));
|
||||
|
@ -2118,7 +2118,8 @@ static int x86_pmu_event_init(struct perf_event *event)
|
||||
event->destroy(event);
|
||||
}
|
||||
|
||||
if (READ_ONCE(x86_pmu.attr_rdpmc))
|
||||
if (READ_ONCE(x86_pmu.attr_rdpmc) &&
|
||||
!(event->hw.flags & PERF_X86_EVENT_LARGE_PEBS))
|
||||
event->hw.flags |= PERF_X86_EVENT_RDPMC_ALLOWED;
|
||||
|
||||
return err;
|
||||
|
@ -2952,9 +2952,9 @@ static void intel_pebs_aliases_skl(struct perf_event *event)
|
||||
return intel_pebs_aliases_precdist(event);
|
||||
}
|
||||
|
||||
static unsigned long intel_pmu_free_running_flags(struct perf_event *event)
|
||||
static unsigned long intel_pmu_large_pebs_flags(struct perf_event *event)
|
||||
{
|
||||
unsigned long flags = x86_pmu.free_running_flags;
|
||||
unsigned long flags = x86_pmu.large_pebs_flags;
|
||||
|
||||
if (event->attr.use_clockid)
|
||||
flags &= ~PERF_SAMPLE_TIME;
|
||||
@ -2976,8 +2976,8 @@ static int intel_pmu_hw_config(struct perf_event *event)
|
||||
if (!event->attr.freq) {
|
||||
event->hw.flags |= PERF_X86_EVENT_AUTO_RELOAD;
|
||||
if (!(event->attr.sample_type &
|
||||
~intel_pmu_free_running_flags(event)))
|
||||
event->hw.flags |= PERF_X86_EVENT_FREERUNNING;
|
||||
~intel_pmu_large_pebs_flags(event)))
|
||||
event->hw.flags |= PERF_X86_EVENT_LARGE_PEBS;
|
||||
}
|
||||
if (x86_pmu.pebs_aliases)
|
||||
x86_pmu.pebs_aliases(event);
|
||||
@ -3194,7 +3194,7 @@ static unsigned bdw_limit_period(struct perf_event *event, unsigned left)
|
||||
X86_CONFIG(.event=0xc0, .umask=0x01)) {
|
||||
if (left < 128)
|
||||
left = 128;
|
||||
left &= ~0x3fu;
|
||||
left &= ~0x3fULL;
|
||||
}
|
||||
return left;
|
||||
}
|
||||
@ -3460,7 +3460,7 @@ static __initconst const struct x86_pmu core_pmu = {
|
||||
.event_map = intel_pmu_event_map,
|
||||
.max_events = ARRAY_SIZE(intel_perfmon_event_map),
|
||||
.apic = 1,
|
||||
.free_running_flags = PEBS_FREERUNNING_FLAGS,
|
||||
.large_pebs_flags = LARGE_PEBS_FLAGS,
|
||||
|
||||
/*
|
||||
* Intel PMCs cannot be accessed sanely above 32-bit width,
|
||||
@ -3502,7 +3502,7 @@ static __initconst const struct x86_pmu intel_pmu = {
|
||||
.event_map = intel_pmu_event_map,
|
||||
.max_events = ARRAY_SIZE(intel_perfmon_event_map),
|
||||
.apic = 1,
|
||||
.free_running_flags = PEBS_FREERUNNING_FLAGS,
|
||||
.large_pebs_flags = LARGE_PEBS_FLAGS,
|
||||
/*
|
||||
* Intel PMCs cannot be accessed sanely above 32 bit width,
|
||||
* so we install an artificial 1<<31 period regardless of
|
||||
|
@ -935,7 +935,7 @@ void intel_pmu_pebs_add(struct perf_event *event)
|
||||
bool needed_cb = pebs_needs_sched_cb(cpuc);
|
||||
|
||||
cpuc->n_pebs++;
|
||||
if (hwc->flags & PERF_X86_EVENT_FREERUNNING)
|
||||
if (hwc->flags & PERF_X86_EVENT_LARGE_PEBS)
|
||||
cpuc->n_large_pebs++;
|
||||
|
||||
pebs_update_state(needed_cb, cpuc, event->ctx->pmu);
|
||||
@ -975,7 +975,7 @@ void intel_pmu_pebs_del(struct perf_event *event)
|
||||
bool needed_cb = pebs_needs_sched_cb(cpuc);
|
||||
|
||||
cpuc->n_pebs--;
|
||||
if (hwc->flags & PERF_X86_EVENT_FREERUNNING)
|
||||
if (hwc->flags & PERF_X86_EVENT_LARGE_PEBS)
|
||||
cpuc->n_large_pebs--;
|
||||
|
||||
pebs_update_state(needed_cb, cpuc, event->ctx->pmu);
|
||||
@ -1530,7 +1530,7 @@ void __init intel_ds_init(void)
|
||||
x86_pmu.pebs_record_size =
|
||||
sizeof(struct pebs_record_skl);
|
||||
x86_pmu.drain_pebs = intel_pmu_drain_pebs_nhm;
|
||||
x86_pmu.free_running_flags |= PERF_SAMPLE_TIME;
|
||||
x86_pmu.large_pebs_flags |= PERF_SAMPLE_TIME;
|
||||
break;
|
||||
|
||||
default:
|
||||
|
@ -3343,6 +3343,7 @@ static struct extra_reg skx_uncore_cha_extra_regs[] = {
|
||||
SNBEP_CBO_EVENT_EXTRA_REG(0x9134, 0xffff, 0x4),
|
||||
SNBEP_CBO_EVENT_EXTRA_REG(0x35, 0xff, 0x8),
|
||||
SNBEP_CBO_EVENT_EXTRA_REG(0x36, 0xff, 0x8),
|
||||
SNBEP_CBO_EVENT_EXTRA_REG(0x38, 0xff, 0x3),
|
||||
EVENT_EXTRA_END
|
||||
};
|
||||
|
||||
@ -3562,24 +3563,27 @@ static struct intel_uncore_type *skx_msr_uncores[] = {
|
||||
NULL,
|
||||
};
|
||||
|
||||
/*
|
||||
* To determine the number of CHAs, it should read bits 27:0 in the CAPID6
|
||||
* register which located at Device 30, Function 3, Offset 0x9C. PCI ID 0x2083.
|
||||
*/
|
||||
#define SKX_CAPID6 0x9c
|
||||
#define SKX_CHA_BIT_MASK GENMASK(27, 0)
|
||||
|
||||
static int skx_count_chabox(void)
|
||||
{
|
||||
struct pci_dev *chabox_dev = NULL;
|
||||
int bus, count = 0;
|
||||
struct pci_dev *dev = NULL;
|
||||
u32 val = 0;
|
||||
|
||||
while (1) {
|
||||
chabox_dev = pci_get_device(PCI_VENDOR_ID_INTEL, 0x208d, chabox_dev);
|
||||
if (!chabox_dev)
|
||||
break;
|
||||
if (count == 0)
|
||||
bus = chabox_dev->bus->number;
|
||||
if (bus != chabox_dev->bus->number)
|
||||
break;
|
||||
count++;
|
||||
}
|
||||
dev = pci_get_device(PCI_VENDOR_ID_INTEL, 0x2083, dev);
|
||||
if (!dev)
|
||||
goto out;
|
||||
|
||||
pci_dev_put(chabox_dev);
|
||||
return count;
|
||||
pci_read_config_dword(dev, SKX_CAPID6, &val);
|
||||
val &= SKX_CHA_BIT_MASK;
|
||||
out:
|
||||
pci_dev_put(dev);
|
||||
return hweight32(val);
|
||||
}
|
||||
|
||||
void skx_uncore_cpu_init(void)
|
||||
|
@ -69,7 +69,7 @@ struct event_constraint {
|
||||
#define PERF_X86_EVENT_RDPMC_ALLOWED 0x0100 /* grant rdpmc permission */
|
||||
#define PERF_X86_EVENT_EXCL_ACCT 0x0200 /* accounted EXCL event */
|
||||
#define PERF_X86_EVENT_AUTO_RELOAD 0x0400 /* use PEBS auto-reload */
|
||||
#define PERF_X86_EVENT_FREERUNNING 0x0800 /* use freerunning PEBS */
|
||||
#define PERF_X86_EVENT_LARGE_PEBS 0x0800 /* use large PEBS */
|
||||
|
||||
|
||||
struct amd_nb {
|
||||
@ -88,7 +88,7 @@ struct amd_nb {
|
||||
* REGS_USER can be handled for events limited to ring 3.
|
||||
*
|
||||
*/
|
||||
#define PEBS_FREERUNNING_FLAGS \
|
||||
#define LARGE_PEBS_FLAGS \
|
||||
(PERF_SAMPLE_IP | PERF_SAMPLE_TID | PERF_SAMPLE_ADDR | \
|
||||
PERF_SAMPLE_ID | PERF_SAMPLE_CPU | PERF_SAMPLE_STREAM_ID | \
|
||||
PERF_SAMPLE_DATA_SRC | PERF_SAMPLE_IDENTIFIER | \
|
||||
@ -608,7 +608,7 @@ struct x86_pmu {
|
||||
struct event_constraint *pebs_constraints;
|
||||
void (*pebs_aliases)(struct perf_event *event);
|
||||
int max_pebs_events;
|
||||
unsigned long free_running_flags;
|
||||
unsigned long large_pebs_flags;
|
||||
|
||||
/*
|
||||
* Intel LBR
|
||||
|
@ -52,11 +52,7 @@ static inline unsigned long array_index_mask_nospec(unsigned long index,
|
||||
#define barrier_nospec() alternative_2("", "mfence", X86_FEATURE_MFENCE_RDTSC, \
|
||||
"lfence", X86_FEATURE_LFENCE_RDTSC)
|
||||
|
||||
#ifdef CONFIG_X86_PPRO_FENCE
|
||||
#define dma_rmb() rmb()
|
||||
#else
|
||||
#define dma_rmb() barrier()
|
||||
#endif
|
||||
#define dma_wmb() barrier()
|
||||
|
||||
#ifdef CONFIG_X86_32
|
||||
@ -68,30 +64,6 @@ static inline unsigned long array_index_mask_nospec(unsigned long index,
|
||||
#define __smp_wmb() barrier()
|
||||
#define __smp_store_mb(var, value) do { (void)xchg(&var, value); } while (0)
|
||||
|
||||
#if defined(CONFIG_X86_PPRO_FENCE)
|
||||
|
||||
/*
|
||||
* For this option x86 doesn't have a strong TSO memory
|
||||
* model and we should fall back to full barriers.
|
||||
*/
|
||||
|
||||
#define __smp_store_release(p, v) \
|
||||
do { \
|
||||
compiletime_assert_atomic_type(*p); \
|
||||
__smp_mb(); \
|
||||
WRITE_ONCE(*p, v); \
|
||||
} while (0)
|
||||
|
||||
#define __smp_load_acquire(p) \
|
||||
({ \
|
||||
typeof(*p) ___p1 = READ_ONCE(*p); \
|
||||
compiletime_assert_atomic_type(*p); \
|
||||
__smp_mb(); \
|
||||
___p1; \
|
||||
})
|
||||
|
||||
#else /* regular x86 TSO memory ordering */
|
||||
|
||||
#define __smp_store_release(p, v) \
|
||||
do { \
|
||||
compiletime_assert_atomic_type(*p); \
|
||||
@ -107,8 +79,6 @@ do { \
|
||||
___p1; \
|
||||
})
|
||||
|
||||
#endif
|
||||
|
||||
/* Atomic operations are already serializing on x86 */
|
||||
#define __smp_mb__before_atomic() barrier()
|
||||
#define __smp_mb__after_atomic() barrier()
|
||||
|
@ -232,21 +232,6 @@ extern void set_iounmap_nonlazy(void);
|
||||
*/
|
||||
#define __ISA_IO_base ((char __iomem *)(PAGE_OFFSET))
|
||||
|
||||
/*
|
||||
* Cache management
|
||||
*
|
||||
* This needed for two cases
|
||||
* 1. Out of order aware processors
|
||||
* 2. Accidentally out of order processors (PPro errata #51)
|
||||
*/
|
||||
|
||||
static inline void flush_write_buffers(void)
|
||||
{
|
||||
#if defined(CONFIG_X86_PPRO_FENCE)
|
||||
asm volatile("lock; addl $0,0(%%esp)": : :"memory");
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif /* __KERNEL__ */
|
||||
|
||||
extern void native_io_delay(void);
|
||||
|
@ -352,6 +352,7 @@ enum vmcs_field {
|
||||
#define INTR_TYPE_NMI_INTR (2 << 8) /* NMI */
|
||||
#define INTR_TYPE_HARD_EXCEPTION (3 << 8) /* processor exception */
|
||||
#define INTR_TYPE_SOFT_INTR (4 << 8) /* software interrupt */
|
||||
#define INTR_TYPE_PRIV_SW_EXCEPTION (5 << 8) /* ICE breakpoint - undocumented */
|
||||
#define INTR_TYPE_SOFT_EXCEPTION (6 << 8) /* software exception */
|
||||
|
||||
/* GUEST_INTERRUPTIBILITY_INFO flags. */
|
||||
|
@ -259,7 +259,7 @@ static void __init dtb_apic_setup(void)
|
||||
dtb_ioapic_setup();
|
||||
}
|
||||
|
||||
#ifdef CONFIG_OF_FLATTREE
|
||||
#ifdef CONFIG_OF_EARLY_FLATTREE
|
||||
static void __init x86_flattree_get_config(void)
|
||||
{
|
||||
u32 size, map_len;
|
||||
|
@ -160,7 +160,6 @@ static const __initconst struct idt_data early_pf_idts[] = {
|
||||
*/
|
||||
static const __initconst struct idt_data dbg_idts[] = {
|
||||
INTG(X86_TRAP_DB, debug),
|
||||
INTG(X86_TRAP_BP, int3),
|
||||
};
|
||||
#endif
|
||||
|
||||
@ -183,7 +182,6 @@ gate_desc debug_idt_table[IDT_ENTRIES] __page_aligned_bss;
|
||||
static const __initconst struct idt_data ist_idts[] = {
|
||||
ISTG(X86_TRAP_DB, debug, DEBUG_STACK),
|
||||
ISTG(X86_TRAP_NMI, nmi, NMI_STACK),
|
||||
SISTG(X86_TRAP_BP, int3, DEBUG_STACK),
|
||||
ISTG(X86_TRAP_DF, double_fault, DOUBLEFAULT_STACK),
|
||||
#ifdef CONFIG_X86_MCE
|
||||
ISTG(X86_TRAP_MC, &machine_check, MCE_STACK),
|
||||
|
@ -37,7 +37,6 @@ static dma_addr_t nommu_map_page(struct device *dev, struct page *page,
|
||||
WARN_ON(size == 0);
|
||||
if (!check_addr("map_single", dev, bus, size))
|
||||
return NOMMU_MAPPING_ERROR;
|
||||
flush_write_buffers();
|
||||
return bus;
|
||||
}
|
||||
|
||||
@ -72,25 +71,9 @@ static int nommu_map_sg(struct device *hwdev, struct scatterlist *sg,
|
||||
return 0;
|
||||
s->dma_length = s->length;
|
||||
}
|
||||
flush_write_buffers();
|
||||
return nents;
|
||||
}
|
||||
|
||||
static void nommu_sync_single_for_device(struct device *dev,
|
||||
dma_addr_t addr, size_t size,
|
||||
enum dma_data_direction dir)
|
||||
{
|
||||
flush_write_buffers();
|
||||
}
|
||||
|
||||
|
||||
static void nommu_sync_sg_for_device(struct device *dev,
|
||||
struct scatterlist *sg, int nelems,
|
||||
enum dma_data_direction dir)
|
||||
{
|
||||
flush_write_buffers();
|
||||
}
|
||||
|
||||
static int nommu_mapping_error(struct device *dev, dma_addr_t dma_addr)
|
||||
{
|
||||
return dma_addr == NOMMU_MAPPING_ERROR;
|
||||
@ -101,8 +84,6 @@ const struct dma_map_ops nommu_dma_ops = {
|
||||
.free = dma_generic_free_coherent,
|
||||
.map_sg = nommu_map_sg,
|
||||
.map_page = nommu_map_page,
|
||||
.sync_single_for_device = nommu_sync_single_for_device,
|
||||
.sync_sg_for_device = nommu_sync_sg_for_device,
|
||||
.is_phys = 1,
|
||||
.mapping_error = nommu_mapping_error,
|
||||
.dma_supported = x86_dma_supported,
|
||||
|
@ -577,7 +577,6 @@ do_general_protection(struct pt_regs *regs, long error_code)
|
||||
}
|
||||
NOKPROBE_SYMBOL(do_general_protection);
|
||||
|
||||
/* May run on IST stack. */
|
||||
dotraplinkage void notrace do_int3(struct pt_regs *regs, long error_code)
|
||||
{
|
||||
#ifdef CONFIG_DYNAMIC_FTRACE
|
||||
@ -592,6 +591,13 @@ dotraplinkage void notrace do_int3(struct pt_regs *regs, long error_code)
|
||||
if (poke_int3_handler(regs))
|
||||
return;
|
||||
|
||||
/*
|
||||
* Use ist_enter despite the fact that we don't use an IST stack.
|
||||
* We can be called from a kprobe in non-CONTEXT_KERNEL kernel
|
||||
* mode or even during context tracking state changes.
|
||||
*
|
||||
* This means that we can't schedule. That's okay.
|
||||
*/
|
||||
ist_enter(regs);
|
||||
RCU_LOCKDEP_WARN(!rcu_is_watching(), "entry code didn't wake RCU");
|
||||
#ifdef CONFIG_KGDB_LOW_LEVEL_TRAP
|
||||
@ -609,15 +615,10 @@ dotraplinkage void notrace do_int3(struct pt_regs *regs, long error_code)
|
||||
SIGTRAP) == NOTIFY_STOP)
|
||||
goto exit;
|
||||
|
||||
/*
|
||||
* Let others (NMI) know that the debug stack is in use
|
||||
* as we may switch to the interrupt stack.
|
||||
*/
|
||||
debug_stack_usage_inc();
|
||||
cond_local_irq_enable(regs);
|
||||
do_trap(X86_TRAP_BP, SIGTRAP, "int3", regs, error_code, NULL);
|
||||
cond_local_irq_disable(regs);
|
||||
debug_stack_usage_dec();
|
||||
|
||||
exit:
|
||||
ist_exit(regs);
|
||||
}
|
||||
|
@ -1045,6 +1045,13 @@ static inline bool is_machine_check(u32 intr_info)
|
||||
(INTR_TYPE_HARD_EXCEPTION | MC_VECTOR | INTR_INFO_VALID_MASK);
|
||||
}
|
||||
|
||||
/* Undocumented: icebp/int1 */
|
||||
static inline bool is_icebp(u32 intr_info)
|
||||
{
|
||||
return (intr_info & (INTR_INFO_INTR_TYPE_MASK | INTR_INFO_VALID_MASK))
|
||||
== (INTR_TYPE_PRIV_SW_EXCEPTION | INTR_INFO_VALID_MASK);
|
||||
}
|
||||
|
||||
static inline bool cpu_has_vmx_msr_bitmap(void)
|
||||
{
|
||||
return vmcs_config.cpu_based_exec_ctrl & CPU_BASED_USE_MSR_BITMAPS;
|
||||
@ -6179,7 +6186,7 @@ static int handle_exception(struct kvm_vcpu *vcpu)
|
||||
(KVM_GUESTDBG_SINGLESTEP | KVM_GUESTDBG_USE_HW_BP))) {
|
||||
vcpu->arch.dr6 &= ~15;
|
||||
vcpu->arch.dr6 |= dr6 | DR6_RTM;
|
||||
if (!(dr6 & ~DR6_RESERVED)) /* icebp */
|
||||
if (is_icebp(intr_info))
|
||||
skip_emulated_instruction(vcpu);
|
||||
|
||||
kvm_queue_exception(vcpu, DB_VECTOR);
|
||||
|
@ -800,17 +800,11 @@ int arch_add_memory(int nid, u64 start, u64 size, struct vmem_altmap *altmap,
|
||||
|
||||
#define PAGE_INUSE 0xFD
|
||||
|
||||
static void __meminit free_pagetable(struct page *page, int order,
|
||||
struct vmem_altmap *altmap)
|
||||
static void __meminit free_pagetable(struct page *page, int order)
|
||||
{
|
||||
unsigned long magic;
|
||||
unsigned int nr_pages = 1 << order;
|
||||
|
||||
if (altmap) {
|
||||
vmem_altmap_free(altmap, nr_pages);
|
||||
return;
|
||||
}
|
||||
|
||||
/* bootmem page has reserved flag */
|
||||
if (PageReserved(page)) {
|
||||
__ClearPageReserved(page);
|
||||
@ -826,8 +820,16 @@ static void __meminit free_pagetable(struct page *page, int order,
|
||||
free_pages((unsigned long)page_address(page), order);
|
||||
}
|
||||
|
||||
static void __meminit free_pte_table(pte_t *pte_start, pmd_t *pmd,
|
||||
static void __meminit free_hugepage_table(struct page *page,
|
||||
struct vmem_altmap *altmap)
|
||||
{
|
||||
if (altmap)
|
||||
vmem_altmap_free(altmap, PMD_SIZE / PAGE_SIZE);
|
||||
else
|
||||
free_pagetable(page, get_order(PMD_SIZE));
|
||||
}
|
||||
|
||||
static void __meminit free_pte_table(pte_t *pte_start, pmd_t *pmd)
|
||||
{
|
||||
pte_t *pte;
|
||||
int i;
|
||||
@ -839,14 +841,13 @@ static void __meminit free_pte_table(pte_t *pte_start, pmd_t *pmd,
|
||||
}
|
||||
|
||||
/* free a pte talbe */
|
||||
free_pagetable(pmd_page(*pmd), 0, altmap);
|
||||
free_pagetable(pmd_page(*pmd), 0);
|
||||
spin_lock(&init_mm.page_table_lock);
|
||||
pmd_clear(pmd);
|
||||
spin_unlock(&init_mm.page_table_lock);
|
||||
}
|
||||
|
||||
static void __meminit free_pmd_table(pmd_t *pmd_start, pud_t *pud,
|
||||
struct vmem_altmap *altmap)
|
||||
static void __meminit free_pmd_table(pmd_t *pmd_start, pud_t *pud)
|
||||
{
|
||||
pmd_t *pmd;
|
||||
int i;
|
||||
@ -858,14 +859,13 @@ static void __meminit free_pmd_table(pmd_t *pmd_start, pud_t *pud,
|
||||
}
|
||||
|
||||
/* free a pmd talbe */
|
||||
free_pagetable(pud_page(*pud), 0, altmap);
|
||||
free_pagetable(pud_page(*pud), 0);
|
||||
spin_lock(&init_mm.page_table_lock);
|
||||
pud_clear(pud);
|
||||
spin_unlock(&init_mm.page_table_lock);
|
||||
}
|
||||
|
||||
static void __meminit free_pud_table(pud_t *pud_start, p4d_t *p4d,
|
||||
struct vmem_altmap *altmap)
|
||||
static void __meminit free_pud_table(pud_t *pud_start, p4d_t *p4d)
|
||||
{
|
||||
pud_t *pud;
|
||||
int i;
|
||||
@ -877,7 +877,7 @@ static void __meminit free_pud_table(pud_t *pud_start, p4d_t *p4d,
|
||||
}
|
||||
|
||||
/* free a pud talbe */
|
||||
free_pagetable(p4d_page(*p4d), 0, altmap);
|
||||
free_pagetable(p4d_page(*p4d), 0);
|
||||
spin_lock(&init_mm.page_table_lock);
|
||||
p4d_clear(p4d);
|
||||
spin_unlock(&init_mm.page_table_lock);
|
||||
@ -885,7 +885,7 @@ static void __meminit free_pud_table(pud_t *pud_start, p4d_t *p4d,
|
||||
|
||||
static void __meminit
|
||||
remove_pte_table(pte_t *pte_start, unsigned long addr, unsigned long end,
|
||||
struct vmem_altmap *altmap, bool direct)
|
||||
bool direct)
|
||||
{
|
||||
unsigned long next, pages = 0;
|
||||
pte_t *pte;
|
||||
@ -916,7 +916,7 @@ remove_pte_table(pte_t *pte_start, unsigned long addr, unsigned long end,
|
||||
* freed when offlining, or simplely not in use.
|
||||
*/
|
||||
if (!direct)
|
||||
free_pagetable(pte_page(*pte), 0, altmap);
|
||||
free_pagetable(pte_page(*pte), 0);
|
||||
|
||||
spin_lock(&init_mm.page_table_lock);
|
||||
pte_clear(&init_mm, addr, pte);
|
||||
@ -939,7 +939,7 @@ remove_pte_table(pte_t *pte_start, unsigned long addr, unsigned long end,
|
||||
|
||||
page_addr = page_address(pte_page(*pte));
|
||||
if (!memchr_inv(page_addr, PAGE_INUSE, PAGE_SIZE)) {
|
||||
free_pagetable(pte_page(*pte), 0, altmap);
|
||||
free_pagetable(pte_page(*pte), 0);
|
||||
|
||||
spin_lock(&init_mm.page_table_lock);
|
||||
pte_clear(&init_mm, addr, pte);
|
||||
@ -974,9 +974,8 @@ remove_pmd_table(pmd_t *pmd_start, unsigned long addr, unsigned long end,
|
||||
if (IS_ALIGNED(addr, PMD_SIZE) &&
|
||||
IS_ALIGNED(next, PMD_SIZE)) {
|
||||
if (!direct)
|
||||
free_pagetable(pmd_page(*pmd),
|
||||
get_order(PMD_SIZE),
|
||||
altmap);
|
||||
free_hugepage_table(pmd_page(*pmd),
|
||||
altmap);
|
||||
|
||||
spin_lock(&init_mm.page_table_lock);
|
||||
pmd_clear(pmd);
|
||||
@ -989,9 +988,8 @@ remove_pmd_table(pmd_t *pmd_start, unsigned long addr, unsigned long end,
|
||||
page_addr = page_address(pmd_page(*pmd));
|
||||
if (!memchr_inv(page_addr, PAGE_INUSE,
|
||||
PMD_SIZE)) {
|
||||
free_pagetable(pmd_page(*pmd),
|
||||
get_order(PMD_SIZE),
|
||||
altmap);
|
||||
free_hugepage_table(pmd_page(*pmd),
|
||||
altmap);
|
||||
|
||||
spin_lock(&init_mm.page_table_lock);
|
||||
pmd_clear(pmd);
|
||||
@ -1003,8 +1001,8 @@ remove_pmd_table(pmd_t *pmd_start, unsigned long addr, unsigned long end,
|
||||
}
|
||||
|
||||
pte_base = (pte_t *)pmd_page_vaddr(*pmd);
|
||||
remove_pte_table(pte_base, addr, next, altmap, direct);
|
||||
free_pte_table(pte_base, pmd, altmap);
|
||||
remove_pte_table(pte_base, addr, next, direct);
|
||||
free_pte_table(pte_base, pmd);
|
||||
}
|
||||
|
||||
/* Call free_pmd_table() in remove_pud_table(). */
|
||||
@ -1033,8 +1031,7 @@ remove_pud_table(pud_t *pud_start, unsigned long addr, unsigned long end,
|
||||
IS_ALIGNED(next, PUD_SIZE)) {
|
||||
if (!direct)
|
||||
free_pagetable(pud_page(*pud),
|
||||
get_order(PUD_SIZE),
|
||||
altmap);
|
||||
get_order(PUD_SIZE));
|
||||
|
||||
spin_lock(&init_mm.page_table_lock);
|
||||
pud_clear(pud);
|
||||
@ -1048,8 +1045,7 @@ remove_pud_table(pud_t *pud_start, unsigned long addr, unsigned long end,
|
||||
if (!memchr_inv(page_addr, PAGE_INUSE,
|
||||
PUD_SIZE)) {
|
||||
free_pagetable(pud_page(*pud),
|
||||
get_order(PUD_SIZE),
|
||||
altmap);
|
||||
get_order(PUD_SIZE));
|
||||
|
||||
spin_lock(&init_mm.page_table_lock);
|
||||
pud_clear(pud);
|
||||
@ -1062,7 +1058,7 @@ remove_pud_table(pud_t *pud_start, unsigned long addr, unsigned long end,
|
||||
|
||||
pmd_base = pmd_offset(pud, 0);
|
||||
remove_pmd_table(pmd_base, addr, next, direct, altmap);
|
||||
free_pmd_table(pmd_base, pud, altmap);
|
||||
free_pmd_table(pmd_base, pud);
|
||||
}
|
||||
|
||||
if (direct)
|
||||
@ -1094,7 +1090,7 @@ remove_p4d_table(p4d_t *p4d_start, unsigned long addr, unsigned long end,
|
||||
* to adapt for boot-time switching between 4 and 5 level page tables.
|
||||
*/
|
||||
if (CONFIG_PGTABLE_LEVELS == 5)
|
||||
free_pud_table(pud_base, p4d, altmap);
|
||||
free_pud_table(pud_base, p4d);
|
||||
}
|
||||
|
||||
if (direct)
|
||||
|
@ -702,4 +702,52 @@ int pmd_clear_huge(pmd_t *pmd)
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* pud_free_pmd_page - Clear pud entry and free pmd page.
|
||||
* @pud: Pointer to a PUD.
|
||||
*
|
||||
* Context: The pud range has been unmaped and TLB purged.
|
||||
* Return: 1 if clearing the entry succeeded. 0 otherwise.
|
||||
*/
|
||||
int pud_free_pmd_page(pud_t *pud)
|
||||
{
|
||||
pmd_t *pmd;
|
||||
int i;
|
||||
|
||||
if (pud_none(*pud))
|
||||
return 1;
|
||||
|
||||
pmd = (pmd_t *)pud_page_vaddr(*pud);
|
||||
|
||||
for (i = 0; i < PTRS_PER_PMD; i++)
|
||||
if (!pmd_free_pte_page(&pmd[i]))
|
||||
return 0;
|
||||
|
||||
pud_clear(pud);
|
||||
free_page((unsigned long)pmd);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* pmd_free_pte_page - Clear pmd entry and free pte page.
|
||||
* @pmd: Pointer to a PMD.
|
||||
*
|
||||
* Context: The pmd range has been unmaped and TLB purged.
|
||||
* Return: 1 if clearing the entry succeeded. 0 otherwise.
|
||||
*/
|
||||
int pmd_free_pte_page(pmd_t *pmd)
|
||||
{
|
||||
pte_t *pte;
|
||||
|
||||
if (pmd_none(*pmd))
|
||||
return 1;
|
||||
|
||||
pte = (pte_t *)pmd_page_vaddr(*pmd);
|
||||
pmd_clear(pmd);
|
||||
free_page((unsigned long)pte);
|
||||
|
||||
return 1;
|
||||
}
|
||||
#endif /* CONFIG_HAVE_ARCH_HUGE_VMAP */
|
||||
|
@ -1188,7 +1188,7 @@ skip_init_addrs:
|
||||
* may converge on the last pass. In such case do one more
|
||||
* pass to emit the final image
|
||||
*/
|
||||
for (pass = 0; pass < 10 || image; pass++) {
|
||||
for (pass = 0; pass < 20 || image; pass++) {
|
||||
proglen = do_jit(prog, addrs, image, oldproglen, &ctx);
|
||||
if (proglen <= 0) {
|
||||
image = NULL;
|
||||
@ -1215,6 +1215,7 @@ skip_init_addrs:
|
||||
}
|
||||
}
|
||||
oldproglen = proglen;
|
||||
cond_resched();
|
||||
}
|
||||
|
||||
if (bpf_jit_enable > 1)
|
||||
|
@ -227,7 +227,7 @@ int __init efi_alloc_page_tables(void)
|
||||
if (!pud) {
|
||||
if (CONFIG_PGTABLE_LEVELS > 4)
|
||||
free_page((unsigned long) pgd_page_vaddr(*pgd));
|
||||
free_page((unsigned long)efi_pgd);
|
||||
free_pages((unsigned long)efi_pgd, PGD_ALLOCATION_ORDER);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
|
@ -30,11 +30,7 @@
|
||||
|
||||
#endif /* CONFIG_X86_32 */
|
||||
|
||||
#ifdef CONFIG_X86_PPRO_FENCE
|
||||
#define dma_rmb() rmb()
|
||||
#else /* CONFIG_X86_PPRO_FENCE */
|
||||
#define dma_rmb() barrier()
|
||||
#endif /* CONFIG_X86_PPRO_FENCE */
|
||||
#define dma_wmb() barrier()
|
||||
|
||||
#include <asm-generic/barrier.h>
|
||||
|
@ -74,10 +74,10 @@ void __init acpi_watchdog_init(void)
|
||||
res.start = gas->address;
|
||||
if (gas->space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY) {
|
||||
res.flags = IORESOURCE_MEM;
|
||||
res.end = res.start + ALIGN(gas->access_width, 4);
|
||||
res.end = res.start + ALIGN(gas->access_width, 4) - 1;
|
||||
} else if (gas->space_id == ACPI_ADR_SPACE_SYSTEM_IO) {
|
||||
res.flags = IORESOURCE_IO;
|
||||
res.end = res.start + gas->access_width;
|
||||
res.end = res.start + gas->access_width - 1;
|
||||
} else {
|
||||
pr_warn("Unsupported address space: %u\n",
|
||||
gas->space_id);
|
||||
|
@ -70,7 +70,6 @@ static async_cookie_t async_cookie;
|
||||
static bool battery_driver_registered;
|
||||
static int battery_bix_broken_package;
|
||||
static int battery_notification_delay_ms;
|
||||
static int battery_full_discharging;
|
||||
static unsigned int cache_time = 1000;
|
||||
module_param(cache_time, uint, 0644);
|
||||
MODULE_PARM_DESC(cache_time, "cache time in milliseconds");
|
||||
@ -215,12 +214,9 @@ static int acpi_battery_get_property(struct power_supply *psy,
|
||||
return -ENODEV;
|
||||
switch (psp) {
|
||||
case POWER_SUPPLY_PROP_STATUS:
|
||||
if (battery->state & ACPI_BATTERY_STATE_DISCHARGING) {
|
||||
if (battery_full_discharging && battery->rate_now == 0)
|
||||
val->intval = POWER_SUPPLY_STATUS_FULL;
|
||||
else
|
||||
val->intval = POWER_SUPPLY_STATUS_DISCHARGING;
|
||||
} else if (battery->state & ACPI_BATTERY_STATE_CHARGING)
|
||||
if (battery->state & ACPI_BATTERY_STATE_DISCHARGING)
|
||||
val->intval = POWER_SUPPLY_STATUS_DISCHARGING;
|
||||
else if (battery->state & ACPI_BATTERY_STATE_CHARGING)
|
||||
val->intval = POWER_SUPPLY_STATUS_CHARGING;
|
||||
else if (acpi_battery_is_charged(battery))
|
||||
val->intval = POWER_SUPPLY_STATUS_FULL;
|
||||
@ -1170,12 +1166,6 @@ battery_notification_delay_quirk(const struct dmi_system_id *d)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __init battery_full_discharging_quirk(const struct dmi_system_id *d)
|
||||
{
|
||||
battery_full_discharging = 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct dmi_system_id bat_dmi_table[] __initconst = {
|
||||
{
|
||||
.callback = battery_bix_broken_package_quirk,
|
||||
@ -1193,38 +1183,6 @@ static const struct dmi_system_id bat_dmi_table[] __initconst = {
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "Aspire V5-573G"),
|
||||
},
|
||||
},
|
||||
{
|
||||
.callback = battery_full_discharging_quirk,
|
||||
.ident = "ASUS GL502VSK",
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "GL502VSK"),
|
||||
},
|
||||
},
|
||||
{
|
||||
.callback = battery_full_discharging_quirk,
|
||||
.ident = "ASUS UX305LA",
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "UX305LA"),
|
||||
},
|
||||
},
|
||||
{
|
||||
.callback = battery_full_discharging_quirk,
|
||||
.ident = "ASUS UX360UA",
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "UX360UA"),
|
||||
},
|
||||
},
|
||||
{
|
||||
.callback = battery_full_discharging_quirk,
|
||||
.ident = "ASUS UX410UAK",
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "UX410UAK"),
|
||||
},
|
||||
},
|
||||
{},
|
||||
};
|
||||
|
||||
|
@ -2675,10 +2675,14 @@ static int acpi_nfit_register_region(struct acpi_nfit_desc *acpi_desc,
|
||||
else
|
||||
ndr_desc->numa_node = NUMA_NO_NODE;
|
||||
|
||||
if(acpi_desc->platform_cap & ACPI_NFIT_CAPABILITY_CACHE_FLUSH)
|
||||
/*
|
||||
* Persistence domain bits are hierarchical, if
|
||||
* ACPI_NFIT_CAPABILITY_CACHE_FLUSH is set then
|
||||
* ACPI_NFIT_CAPABILITY_MEM_FLUSH is implied.
|
||||
*/
|
||||
if (acpi_desc->platform_cap & ACPI_NFIT_CAPABILITY_CACHE_FLUSH)
|
||||
set_bit(ND_REGION_PERSIST_CACHE, &ndr_desc->flags);
|
||||
|
||||
if (acpi_desc->platform_cap & ACPI_NFIT_CAPABILITY_MEM_FLUSH)
|
||||
else if (acpi_desc->platform_cap & ACPI_NFIT_CAPABILITY_MEM_FLUSH)
|
||||
set_bit(ND_REGION_PERSIST_MEMCTRL, &ndr_desc->flags);
|
||||
|
||||
list_for_each_entry(nfit_memdev, &acpi_desc->memdevs, list) {
|
||||
|
@ -103,25 +103,27 @@ int acpi_map_pxm_to_node(int pxm)
|
||||
*/
|
||||
int acpi_map_pxm_to_online_node(int pxm)
|
||||
{
|
||||
int node, n, dist, min_dist;
|
||||
int node, min_node;
|
||||
|
||||
node = acpi_map_pxm_to_node(pxm);
|
||||
|
||||
if (node == NUMA_NO_NODE)
|
||||
node = 0;
|
||||
|
||||
min_node = node;
|
||||
if (!node_online(node)) {
|
||||
min_dist = INT_MAX;
|
||||
int min_dist = INT_MAX, dist, n;
|
||||
|
||||
for_each_online_node(n) {
|
||||
dist = node_distance(node, n);
|
||||
if (dist < min_dist) {
|
||||
min_dist = dist;
|
||||
node = n;
|
||||
min_node = n;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return node;
|
||||
return min_node;
|
||||
}
|
||||
EXPORT_SYMBOL(acpi_map_pxm_to_online_node);
|
||||
|
||||
|
@ -550,7 +550,9 @@ static const struct pci_device_id ahci_pci_tbl[] = {
|
||||
.driver_data = board_ahci_yes_fbs },
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_MARVELL_EXT, 0x9230),
|
||||
.driver_data = board_ahci_yes_fbs },
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_TTI, 0x0642),
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_TTI, 0x0642), /* highpoint rocketraid 642L */
|
||||
.driver_data = board_ahci_yes_fbs },
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_TTI, 0x0645), /* highpoint rocketraid 644L */
|
||||
.driver_data = board_ahci_yes_fbs },
|
||||
|
||||
/* Promise */
|
||||
|
@ -665,6 +665,16 @@ int ahci_stop_engine(struct ata_port *ap)
|
||||
if ((tmp & (PORT_CMD_START | PORT_CMD_LIST_ON)) == 0)
|
||||
return 0;
|
||||
|
||||
/*
|
||||
* Don't try to issue commands but return with ENODEV if the
|
||||
* AHCI controller not available anymore (e.g. due to PCIe hot
|
||||
* unplugging). Otherwise a 500ms delay for each port is added.
|
||||
*/
|
||||
if (tmp == 0xffffffff) {
|
||||
dev_err(ap->host->dev, "AHCI controller unavailable!\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
/* setting HBA to idle */
|
||||
tmp &= ~PORT_CMD_START;
|
||||
writel(tmp, port_mmio + PORT_CMD);
|
||||
|
@ -340,7 +340,7 @@ static int ahci_platform_get_regulator(struct ahci_host_priv *hpriv, u32 port,
|
||||
* 2) regulator for controlling the targets power (optional)
|
||||
* 3) 0 - AHCI_MAX_CLKS clocks, as specified in the devs devicetree node,
|
||||
* or for non devicetree enabled platforms a single clock
|
||||
* 4) phys (optional)
|
||||
* 4) phys (optional)
|
||||
*
|
||||
* RETURNS:
|
||||
* The allocated ahci_host_priv on success, otherwise an ERR_PTR value
|
||||
|
@ -4530,6 +4530,25 @@ static const struct ata_blacklist_entry ata_device_blacklist [] = {
|
||||
{ "PIONEER DVD-RW DVR-212D", NULL, ATA_HORKAGE_NOSETXFER },
|
||||
{ "PIONEER DVD-RW DVR-216D", NULL, ATA_HORKAGE_NOSETXFER },
|
||||
|
||||
/* Crucial BX100 SSD 500GB has broken LPM support */
|
||||
{ "CT500BX100SSD1", NULL, ATA_HORKAGE_NOLPM },
|
||||
|
||||
/* 512GB MX100 with MU01 firmware has both queued TRIM and LPM issues */
|
||||
{ "Crucial_CT512MX100*", "MU01", ATA_HORKAGE_NO_NCQ_TRIM |
|
||||
ATA_HORKAGE_ZERO_AFTER_TRIM |
|
||||
ATA_HORKAGE_NOLPM, },
|
||||
/* 512GB MX100 with newer firmware has only LPM issues */
|
||||
{ "Crucial_CT512MX100*", NULL, ATA_HORKAGE_ZERO_AFTER_TRIM |
|
||||
ATA_HORKAGE_NOLPM, },
|
||||
|
||||
/* 480GB+ M500 SSDs have both queued TRIM and LPM issues */
|
||||
{ "Crucial_CT480M500*", NULL, ATA_HORKAGE_NO_NCQ_TRIM |
|
||||
ATA_HORKAGE_ZERO_AFTER_TRIM |
|
||||
ATA_HORKAGE_NOLPM, },
|
||||
{ "Crucial_CT960M500*", NULL, ATA_HORKAGE_NO_NCQ_TRIM |
|
||||
ATA_HORKAGE_ZERO_AFTER_TRIM |
|
||||
ATA_HORKAGE_NOLPM, },
|
||||
|
||||
/* devices that don't properly handle queued TRIM commands */
|
||||
{ "Micron_M500_*", NULL, ATA_HORKAGE_NO_NCQ_TRIM |
|
||||
ATA_HORKAGE_ZERO_AFTER_TRIM, },
|
||||
@ -4541,7 +4560,9 @@ static const struct ata_blacklist_entry ata_device_blacklist [] = {
|
||||
ATA_HORKAGE_ZERO_AFTER_TRIM, },
|
||||
{ "Crucial_CT*MX100*", "MU01", ATA_HORKAGE_NO_NCQ_TRIM |
|
||||
ATA_HORKAGE_ZERO_AFTER_TRIM, },
|
||||
{ "Samsung SSD 8*", NULL, ATA_HORKAGE_NO_NCQ_TRIM |
|
||||
{ "Samsung SSD 840*", NULL, ATA_HORKAGE_NO_NCQ_TRIM |
|
||||
ATA_HORKAGE_ZERO_AFTER_TRIM, },
|
||||
{ "Samsung SSD 850*", NULL, ATA_HORKAGE_NO_NCQ_TRIM |
|
||||
ATA_HORKAGE_ZERO_AFTER_TRIM, },
|
||||
{ "FCCT*M500*", NULL, ATA_HORKAGE_NO_NCQ_TRIM |
|
||||
ATA_HORKAGE_ZERO_AFTER_TRIM, },
|
||||
@ -5401,8 +5422,7 @@ void ata_qc_issue(struct ata_queued_cmd *qc)
|
||||
* We guarantee to LLDs that they will have at least one
|
||||
* non-zero sg if the command is a data command.
|
||||
*/
|
||||
if (WARN_ON_ONCE(ata_is_data(prot) &&
|
||||
(!qc->sg || !qc->n_elem || !qc->nbytes)))
|
||||
if (ata_is_data(prot) && (!qc->sg || !qc->n_elem || !qc->nbytes))
|
||||
goto sys_err;
|
||||
|
||||
if (ata_is_dma(prot) || (ata_is_pio(prot) &&
|
||||
|
@ -815,7 +815,8 @@ void ata_scsi_port_error_handler(struct Scsi_Host *host, struct ata_port *ap)
|
||||
|
||||
if (ap->pflags & ATA_PFLAG_LOADING)
|
||||
ap->pflags &= ~ATA_PFLAG_LOADING;
|
||||
else if (ap->pflags & ATA_PFLAG_SCSI_HOTPLUG)
|
||||
else if ((ap->pflags & ATA_PFLAG_SCSI_HOTPLUG) &&
|
||||
!(ap->flags & ATA_FLAG_SAS_HOST))
|
||||
schedule_delayed_work(&ap->hotplug_task, 0);
|
||||
|
||||
if (ap->pflags & ATA_PFLAG_RECOVERED)
|
||||
|
@ -3316,6 +3316,12 @@ static unsigned int ata_scsi_pass_thru(struct ata_queued_cmd *qc)
|
||||
goto invalid_fld;
|
||||
}
|
||||
|
||||
/* We may not issue NCQ commands to devices not supporting NCQ */
|
||||
if (ata_is_ncq(tf->protocol) && !ata_ncq_enabled(dev)) {
|
||||
fp = 1;
|
||||
goto invalid_fld;
|
||||
}
|
||||
|
||||
/* sanity check for pio multi commands */
|
||||
if ((cdb[1] & 0xe0) && !is_multi_taskfile(tf)) {
|
||||
fp = 1;
|
||||
@ -4282,7 +4288,7 @@ static inline void ata_scsi_dump_cdb(struct ata_port *ap,
|
||||
#ifdef ATA_DEBUG
|
||||
struct scsi_device *scsidev = cmd->device;
|
||||
|
||||
DPRINTK("CDB (%u:%d,%d,%d) %9ph\n",
|
||||
DPRINTK("CDB (%u:%d,%d,%lld) %9ph\n",
|
||||
ap->print_id,
|
||||
scsidev->channel, scsidev->id, scsidev->lun,
|
||||
cmd->cmnd);
|
||||
@ -4309,7 +4315,9 @@ static inline int __ata_scsi_queuecmd(struct scsi_cmnd *scmd,
|
||||
if (likely((scsi_op != ATA_16) || !atapi_passthru16)) {
|
||||
/* relay SCSI command to ATAPI device */
|
||||
int len = COMMAND_SIZE(scsi_op);
|
||||
if (unlikely(len > scmd->cmd_len || len > dev->cdb_len))
|
||||
if (unlikely(len > scmd->cmd_len ||
|
||||
len > dev->cdb_len ||
|
||||
scmd->cmd_len > ATAPI_CDB_LEN))
|
||||
goto bad_cdb_len;
|
||||
|
||||
xlat_func = atapi_xlat;
|
||||
|
@ -146,6 +146,7 @@
|
||||
enum sata_rcar_type {
|
||||
RCAR_GEN1_SATA,
|
||||
RCAR_GEN2_SATA,
|
||||
RCAR_GEN3_SATA,
|
||||
RCAR_R8A7790_ES1_SATA,
|
||||
};
|
||||
|
||||
@ -784,26 +785,11 @@ static void sata_rcar_setup_port(struct ata_host *host)
|
||||
ioaddr->command_addr = ioaddr->cmd_addr + (ATA_REG_CMD << 2);
|
||||
}
|
||||
|
||||
static void sata_rcar_init_controller(struct ata_host *host)
|
||||
static void sata_rcar_init_module(struct sata_rcar_priv *priv)
|
||||
{
|
||||
struct sata_rcar_priv *priv = host->private_data;
|
||||
void __iomem *base = priv->base;
|
||||
u32 val;
|
||||
|
||||
/* reset and setup phy */
|
||||
switch (priv->type) {
|
||||
case RCAR_GEN1_SATA:
|
||||
sata_rcar_gen1_phy_init(priv);
|
||||
break;
|
||||
case RCAR_GEN2_SATA:
|
||||
case RCAR_R8A7790_ES1_SATA:
|
||||
sata_rcar_gen2_phy_init(priv);
|
||||
break;
|
||||
default:
|
||||
dev_warn(host->dev, "SATA phy is not initialized\n");
|
||||
break;
|
||||
}
|
||||
|
||||
/* SATA-IP reset state */
|
||||
val = ioread32(base + ATAPI_CONTROL1_REG);
|
||||
val |= ATAPI_CONTROL1_RESET;
|
||||
@ -824,10 +810,33 @@ static void sata_rcar_init_controller(struct ata_host *host)
|
||||
/* ack and mask */
|
||||
iowrite32(0, base + SATAINTSTAT_REG);
|
||||
iowrite32(0x7ff, base + SATAINTMASK_REG);
|
||||
|
||||
/* enable interrupts */
|
||||
iowrite32(ATAPI_INT_ENABLE_SATAINT, base + ATAPI_INT_ENABLE_REG);
|
||||
}
|
||||
|
||||
static void sata_rcar_init_controller(struct ata_host *host)
|
||||
{
|
||||
struct sata_rcar_priv *priv = host->private_data;
|
||||
|
||||
/* reset and setup phy */
|
||||
switch (priv->type) {
|
||||
case RCAR_GEN1_SATA:
|
||||
sata_rcar_gen1_phy_init(priv);
|
||||
break;
|
||||
case RCAR_GEN2_SATA:
|
||||
case RCAR_GEN3_SATA:
|
||||
case RCAR_R8A7790_ES1_SATA:
|
||||
sata_rcar_gen2_phy_init(priv);
|
||||
break;
|
||||
default:
|
||||
dev_warn(host->dev, "SATA phy is not initialized\n");
|
||||
break;
|
||||
}
|
||||
|
||||
sata_rcar_init_module(priv);
|
||||
}
|
||||
|
||||
static const struct of_device_id sata_rcar_match[] = {
|
||||
{
|
||||
/* Deprecated by "renesas,sata-r8a7779" */
|
||||
@ -856,7 +865,7 @@ static const struct of_device_id sata_rcar_match[] = {
|
||||
},
|
||||
{
|
||||
.compatible = "renesas,sata-r8a7795",
|
||||
.data = (void *)RCAR_GEN2_SATA
|
||||
.data = (void *)RCAR_GEN3_SATA
|
||||
},
|
||||
{
|
||||
.compatible = "renesas,rcar-gen2-sata",
|
||||
@ -864,7 +873,7 @@ static const struct of_device_id sata_rcar_match[] = {
|
||||
},
|
||||
{
|
||||
.compatible = "renesas,rcar-gen3-sata",
|
||||
.data = (void *)RCAR_GEN2_SATA
|
||||
.data = (void *)RCAR_GEN3_SATA
|
||||
},
|
||||
{ },
|
||||
};
|
||||
@ -982,11 +991,18 @@ static int sata_rcar_resume(struct device *dev)
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* ack and mask */
|
||||
iowrite32(0, base + SATAINTSTAT_REG);
|
||||
iowrite32(0x7ff, base + SATAINTMASK_REG);
|
||||
/* enable interrupts */
|
||||
iowrite32(ATAPI_INT_ENABLE_SATAINT, base + ATAPI_INT_ENABLE_REG);
|
||||
if (priv->type == RCAR_GEN3_SATA) {
|
||||
sata_rcar_gen2_phy_init(priv);
|
||||
sata_rcar_init_module(priv);
|
||||
} else {
|
||||
/* ack and mask */
|
||||
iowrite32(0, base + SATAINTSTAT_REG);
|
||||
iowrite32(0x7ff, base + SATAINTMASK_REG);
|
||||
|
||||
/* enable interrupts */
|
||||
iowrite32(ATAPI_INT_ENABLE_SATAINT,
|
||||
base + ATAPI_INT_ENABLE_REG);
|
||||
}
|
||||
|
||||
ata_host_resume(host);
|
||||
|
||||
|
@ -231,7 +231,6 @@ static const struct usb_device_id blacklist_table[] = {
|
||||
{ USB_DEVICE(0x0930, 0x0227), .driver_info = BTUSB_ATH3012 },
|
||||
{ USB_DEVICE(0x0b05, 0x17d0), .driver_info = BTUSB_ATH3012 },
|
||||
{ USB_DEVICE(0x0cf3, 0x0036), .driver_info = BTUSB_ATH3012 },
|
||||
{ USB_DEVICE(0x0cf3, 0x3004), .driver_info = BTUSB_ATH3012 },
|
||||
{ USB_DEVICE(0x0cf3, 0x3008), .driver_info = BTUSB_ATH3012 },
|
||||
{ USB_DEVICE(0x0cf3, 0x311d), .driver_info = BTUSB_ATH3012 },
|
||||
{ USB_DEVICE(0x0cf3, 0x311e), .driver_info = BTUSB_ATH3012 },
|
||||
@ -264,6 +263,7 @@ static const struct usb_device_id blacklist_table[] = {
|
||||
{ USB_DEVICE(0x0489, 0xe03c), .driver_info = BTUSB_ATH3012 },
|
||||
|
||||
/* QCA ROME chipset */
|
||||
{ USB_DEVICE(0x0cf3, 0x3004), .driver_info = BTUSB_QCA_ROME },
|
||||
{ USB_DEVICE(0x0cf3, 0xe007), .driver_info = BTUSB_QCA_ROME },
|
||||
{ USB_DEVICE(0x0cf3, 0xe009), .driver_info = BTUSB_QCA_ROME },
|
||||
{ USB_DEVICE(0x0cf3, 0xe010), .driver_info = BTUSB_QCA_ROME },
|
||||
@ -386,10 +386,10 @@ static const struct usb_device_id blacklist_table[] = {
|
||||
*/
|
||||
static const struct dmi_system_id btusb_needs_reset_resume_table[] = {
|
||||
{
|
||||
/* Lenovo Yoga 920 (QCA Rome device 0cf3:e300) */
|
||||
/* Dell OptiPlex 3060 (QCA ROME device 0cf3:e007) */
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
|
||||
DMI_MATCH(DMI_PRODUCT_VERSION, "Lenovo YOGA 920"),
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "OptiPlex 3060"),
|
||||
},
|
||||
},
|
||||
{}
|
||||
|
@ -244,7 +244,9 @@ static irqreturn_t bcm_host_wake(int irq, void *data)
|
||||
|
||||
bt_dev_dbg(bdev, "Host wake IRQ");
|
||||
|
||||
pm_request_resume(bdev->dev);
|
||||
pm_runtime_get(bdev->dev);
|
||||
pm_runtime_mark_last_busy(bdev->dev);
|
||||
pm_runtime_put_autosuspend(bdev->dev);
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
@ -301,7 +303,7 @@ static const struct bcm_set_sleep_mode default_sleep_params = {
|
||||
.usb_auto_sleep = 0,
|
||||
.usb_resume_timeout = 0,
|
||||
.break_to_host = 0,
|
||||
.pulsed_host_wake = 0,
|
||||
.pulsed_host_wake = 1,
|
||||
};
|
||||
|
||||
static int bcm_setup_sleep(struct hci_uart *hu)
|
||||
@ -586,8 +588,11 @@ static int bcm_recv(struct hci_uart *hu, const void *data, int count)
|
||||
} else if (!bcm->rx_skb) {
|
||||
/* Delay auto-suspend when receiving completed packet */
|
||||
mutex_lock(&bcm_device_lock);
|
||||
if (bcm->dev && bcm_device_exists(bcm->dev))
|
||||
pm_request_resume(bcm->dev->dev);
|
||||
if (bcm->dev && bcm_device_exists(bcm->dev)) {
|
||||
pm_runtime_get(bcm->dev->dev);
|
||||
pm_runtime_mark_last_busy(bcm->dev->dev);
|
||||
pm_runtime_put_autosuspend(bcm->dev->dev);
|
||||
}
|
||||
mutex_unlock(&bcm_device_lock);
|
||||
}
|
||||
|
||||
|
@ -449,17 +449,17 @@ struct bcm2835_pll_ana_bits {
|
||||
static const struct bcm2835_pll_ana_bits bcm2835_ana_default = {
|
||||
.mask0 = 0,
|
||||
.set0 = 0,
|
||||
.mask1 = (u32)~(A2W_PLL_KI_MASK | A2W_PLL_KP_MASK),
|
||||
.mask1 = A2W_PLL_KI_MASK | A2W_PLL_KP_MASK,
|
||||
.set1 = (2 << A2W_PLL_KI_SHIFT) | (8 << A2W_PLL_KP_SHIFT),
|
||||
.mask3 = (u32)~A2W_PLL_KA_MASK,
|
||||
.mask3 = A2W_PLL_KA_MASK,
|
||||
.set3 = (2 << A2W_PLL_KA_SHIFT),
|
||||
.fb_prediv_mask = BIT(14),
|
||||
};
|
||||
|
||||
static const struct bcm2835_pll_ana_bits bcm2835_ana_pllh = {
|
||||
.mask0 = (u32)~(A2W_PLLH_KA_MASK | A2W_PLLH_KI_LOW_MASK),
|
||||
.mask0 = A2W_PLLH_KA_MASK | A2W_PLLH_KI_LOW_MASK,
|
||||
.set0 = (2 << A2W_PLLH_KA_SHIFT) | (2 << A2W_PLLH_KI_LOW_SHIFT),
|
||||
.mask1 = (u32)~(A2W_PLLH_KI_HIGH_MASK | A2W_PLLH_KP_MASK),
|
||||
.mask1 = A2W_PLLH_KI_HIGH_MASK | A2W_PLLH_KP_MASK,
|
||||
.set1 = (6 << A2W_PLLH_KP_SHIFT),
|
||||
.mask3 = 0,
|
||||
.set3 = 0,
|
||||
@ -623,8 +623,10 @@ static int bcm2835_pll_on(struct clk_hw *hw)
|
||||
~A2W_PLL_CTRL_PWRDN);
|
||||
|
||||
/* Take the PLL out of reset. */
|
||||
spin_lock(&cprman->regs_lock);
|
||||
cprman_write(cprman, data->cm_ctrl_reg,
|
||||
cprman_read(cprman, data->cm_ctrl_reg) & ~CM_PLL_ANARST);
|
||||
spin_unlock(&cprman->regs_lock);
|
||||
|
||||
/* Wait for the PLL to lock. */
|
||||
timeout = ktime_add_ns(ktime_get(), LOCK_TIMEOUT_NS);
|
||||
@ -701,9 +703,11 @@ static int bcm2835_pll_set_rate(struct clk_hw *hw,
|
||||
}
|
||||
|
||||
/* Unmask the reference clock from the oscillator. */
|
||||
spin_lock(&cprman->regs_lock);
|
||||
cprman_write(cprman, A2W_XOSC_CTRL,
|
||||
cprman_read(cprman, A2W_XOSC_CTRL) |
|
||||
data->reference_enable_mask);
|
||||
spin_unlock(&cprman->regs_lock);
|
||||
|
||||
if (do_ana_setup_first)
|
||||
bcm2835_pll_write_ana(cprman, data->ana_reg_base, ana);
|
||||
|
@ -205,6 +205,18 @@ static const struct aspeed_clk_soc_data ast2400_data = {
|
||||
.calc_pll = aspeed_ast2400_calc_pll,
|
||||
};
|
||||
|
||||
static int aspeed_clk_is_enabled(struct clk_hw *hw)
|
||||
{
|
||||
struct aspeed_clk_gate *gate = to_aspeed_clk_gate(hw);
|
||||
u32 clk = BIT(gate->clock_idx);
|
||||
u32 enval = (gate->flags & CLK_GATE_SET_TO_DISABLE) ? 0 : clk;
|
||||
u32 reg;
|
||||
|
||||
regmap_read(gate->map, ASPEED_CLK_STOP_CTRL, ®);
|
||||
|
||||
return ((reg & clk) == enval) ? 1 : 0;
|
||||
}
|
||||
|
||||
static int aspeed_clk_enable(struct clk_hw *hw)
|
||||
{
|
||||
struct aspeed_clk_gate *gate = to_aspeed_clk_gate(hw);
|
||||
@ -215,6 +227,11 @@ static int aspeed_clk_enable(struct clk_hw *hw)
|
||||
|
||||
spin_lock_irqsave(gate->lock, flags);
|
||||
|
||||
if (aspeed_clk_is_enabled(hw)) {
|
||||
spin_unlock_irqrestore(gate->lock, flags);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (gate->reset_idx >= 0) {
|
||||
/* Put IP in reset */
|
||||
regmap_update_bits(gate->map, ASPEED_RESET_CTRL, rst, rst);
|
||||
@ -255,17 +272,6 @@ static void aspeed_clk_disable(struct clk_hw *hw)
|
||||
spin_unlock_irqrestore(gate->lock, flags);
|
||||
}
|
||||
|
||||
static int aspeed_clk_is_enabled(struct clk_hw *hw)
|
||||
{
|
||||
struct aspeed_clk_gate *gate = to_aspeed_clk_gate(hw);
|
||||
u32 clk = BIT(gate->clock_idx);
|
||||
u32 reg;
|
||||
|
||||
regmap_read(gate->map, ASPEED_CLK_STOP_CTRL, ®);
|
||||
|
||||
return (reg & clk) ? 0 : 1;
|
||||
}
|
||||
|
||||
static const struct clk_ops aspeed_clk_gate_ops = {
|
||||
.enable = aspeed_clk_enable,
|
||||
.disable = aspeed_clk_disable,
|
||||
|
@ -1125,8 +1125,10 @@ static int clk_core_round_rate_nolock(struct clk_core *core,
|
||||
{
|
||||
lockdep_assert_held(&prepare_lock);
|
||||
|
||||
if (!core)
|
||||
if (!core) {
|
||||
req->rate = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
clk_core_init_rate_req(core, req);
|
||||
|
||||
@ -2309,8 +2311,11 @@ static int clk_core_set_phase_nolock(struct clk_core *core, int degrees)
|
||||
|
||||
trace_clk_set_phase(core, degrees);
|
||||
|
||||
if (core->ops->set_phase)
|
||||
if (core->ops->set_phase) {
|
||||
ret = core->ops->set_phase(core->hw, degrees);
|
||||
if (!ret)
|
||||
core->phase = degrees;
|
||||
}
|
||||
|
||||
trace_clk_set_phase_complete(core, degrees);
|
||||
|
||||
@ -2967,23 +2972,38 @@ static int __clk_core_init(struct clk_core *core)
|
||||
rate = 0;
|
||||
core->rate = core->req_rate = rate;
|
||||
|
||||
/*
|
||||
* Enable CLK_IS_CRITICAL clocks so newly added critical clocks
|
||||
* don't get accidentally disabled when walking the orphan tree and
|
||||
* reparenting clocks
|
||||
*/
|
||||
if (core->flags & CLK_IS_CRITICAL) {
|
||||
unsigned long flags;
|
||||
|
||||
clk_core_prepare(core);
|
||||
|
||||
flags = clk_enable_lock();
|
||||
clk_core_enable(core);
|
||||
clk_enable_unlock(flags);
|
||||
}
|
||||
|
||||
/*
|
||||
* walk the list of orphan clocks and reparent any that newly finds a
|
||||
* parent.
|
||||
*/
|
||||
hlist_for_each_entry_safe(orphan, tmp2, &clk_orphan_list, child_node) {
|
||||
struct clk_core *parent = __clk_init_parent(orphan);
|
||||
unsigned long flags;
|
||||
|
||||
/*
|
||||
* we could call __clk_set_parent, but that would result in a
|
||||
* redundant call to the .set_rate op, if it exists
|
||||
* We need to use __clk_set_parent_before() and _after() to
|
||||
* to properly migrate any prepare/enable count of the orphan
|
||||
* clock. This is important for CLK_IS_CRITICAL clocks, which
|
||||
* are enabled during init but might not have a parent yet.
|
||||
*/
|
||||
if (parent) {
|
||||
/* update the clk tree topology */
|
||||
flags = clk_enable_lock();
|
||||
clk_reparent(orphan, parent);
|
||||
clk_enable_unlock(flags);
|
||||
__clk_set_parent_before(orphan, parent);
|
||||
__clk_set_parent_after(orphan, parent, NULL);
|
||||
__clk_recalc_accuracies(orphan);
|
||||
__clk_recalc_rates(orphan, 0);
|
||||
}
|
||||
@ -3000,16 +3020,6 @@ static int __clk_core_init(struct clk_core *core)
|
||||
if (core->ops->init)
|
||||
core->ops->init(core->hw);
|
||||
|
||||
if (core->flags & CLK_IS_CRITICAL) {
|
||||
unsigned long flags;
|
||||
|
||||
clk_core_prepare(core);
|
||||
|
||||
flags = clk_enable_lock();
|
||||
clk_core_enable(core);
|
||||
clk_enable_unlock(flags);
|
||||
}
|
||||
|
||||
kref_init(&core->ref);
|
||||
out:
|
||||
clk_pm_runtime_put(core);
|
||||
|
@ -149,6 +149,8 @@ static int hi3660_stub_clk_probe(struct platform_device *pdev)
|
||||
return PTR_ERR(stub_clk_chan.mbox);
|
||||
|
||||
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
if (!res)
|
||||
return -EINVAL;
|
||||
freq_reg = devm_ioremap(dev, res->start, resource_size(res));
|
||||
if (!freq_reg)
|
||||
return -ENOMEM;
|
||||
|
@ -131,7 +131,17 @@ static const char *ieee1588_sels[] = { "pll3_sw", "pll4_sw", "dummy" /* usbphy2_
|
||||
static struct clk *clk[IMX5_CLK_END];
|
||||
static struct clk_onecell_data clk_data;
|
||||
|
||||
static struct clk ** const uart_clks[] __initconst = {
|
||||
static struct clk ** const uart_clks_mx51[] __initconst = {
|
||||
&clk[IMX5_CLK_UART1_IPG_GATE],
|
||||
&clk[IMX5_CLK_UART1_PER_GATE],
|
||||
&clk[IMX5_CLK_UART2_IPG_GATE],
|
||||
&clk[IMX5_CLK_UART2_PER_GATE],
|
||||
&clk[IMX5_CLK_UART3_IPG_GATE],
|
||||
&clk[IMX5_CLK_UART3_PER_GATE],
|
||||
NULL
|
||||
};
|
||||
|
||||
static struct clk ** const uart_clks_mx50_mx53[] __initconst = {
|
||||
&clk[IMX5_CLK_UART1_IPG_GATE],
|
||||
&clk[IMX5_CLK_UART1_PER_GATE],
|
||||
&clk[IMX5_CLK_UART2_IPG_GATE],
|
||||
@ -321,8 +331,6 @@ static void __init mx5_clocks_common_init(void __iomem *ccm_base)
|
||||
clk_prepare_enable(clk[IMX5_CLK_TMAX1]);
|
||||
clk_prepare_enable(clk[IMX5_CLK_TMAX2]); /* esdhc2, fec */
|
||||
clk_prepare_enable(clk[IMX5_CLK_TMAX3]); /* esdhc1, esdhc4 */
|
||||
|
||||
imx_register_uart_clocks(uart_clks);
|
||||
}
|
||||
|
||||
static void __init mx50_clocks_init(struct device_node *np)
|
||||
@ -388,6 +396,8 @@ static void __init mx50_clocks_init(struct device_node *np)
|
||||
|
||||
r = clk_round_rate(clk[IMX5_CLK_USBOH3_PER_GATE], 54000000);
|
||||
clk_set_rate(clk[IMX5_CLK_USBOH3_PER_GATE], r);
|
||||
|
||||
imx_register_uart_clocks(uart_clks_mx50_mx53);
|
||||
}
|
||||
CLK_OF_DECLARE(imx50_ccm, "fsl,imx50-ccm", mx50_clocks_init);
|
||||
|
||||
@ -477,6 +487,8 @@ static void __init mx51_clocks_init(struct device_node *np)
|
||||
val = readl(MXC_CCM_CLPCR);
|
||||
val |= 1 << 23;
|
||||
writel(val, MXC_CCM_CLPCR);
|
||||
|
||||
imx_register_uart_clocks(uart_clks_mx51);
|
||||
}
|
||||
CLK_OF_DECLARE(imx51_ccm, "fsl,imx51-ccm", mx51_clocks_init);
|
||||
|
||||
@ -606,5 +618,7 @@ static void __init mx53_clocks_init(struct device_node *np)
|
||||
|
||||
r = clk_round_rate(clk[IMX5_CLK_USBOH3_PER_GATE], 54000000);
|
||||
clk_set_rate(clk[IMX5_CLK_USBOH3_PER_GATE], r);
|
||||
|
||||
imx_register_uart_clocks(uart_clks_mx50_mx53);
|
||||
}
|
||||
CLK_OF_DECLARE(imx53_ccm, "fsl,imx53-ccm", mx53_clocks_init);
|
||||
|
@ -49,11 +49,10 @@ static int qcom_apcs_msm8916_clk_probe(struct platform_device *pdev)
|
||||
struct clk_regmap_mux_div *a53cc;
|
||||
struct regmap *regmap;
|
||||
struct clk_init_data init = { };
|
||||
int ret;
|
||||
int ret = -ENODEV;
|
||||
|
||||
regmap = dev_get_regmap(parent, NULL);
|
||||
if (IS_ERR(regmap)) {
|
||||
ret = PTR_ERR(regmap);
|
||||
if (!regmap) {
|
||||
dev_err(dev, "failed to get regmap: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
@ -762,7 +762,7 @@ static struct ccu_mp out_a_clk = {
|
||||
.features = CCU_FEATURE_FIXED_PREDIV,
|
||||
.hw.init = CLK_HW_INIT_PARENTS("out-a",
|
||||
clk_out_parents,
|
||||
&ccu_div_ops,
|
||||
&ccu_mp_ops,
|
||||
0),
|
||||
},
|
||||
};
|
||||
@ -783,7 +783,7 @@ static struct ccu_mp out_b_clk = {
|
||||
.features = CCU_FEATURE_FIXED_PREDIV,
|
||||
.hw.init = CLK_HW_INIT_PARENTS("out-b",
|
||||
clk_out_parents,
|
||||
&ccu_div_ops,
|
||||
&ccu_mp_ops,
|
||||
0),
|
||||
},
|
||||
};
|
||||
@ -804,7 +804,7 @@ static struct ccu_mp out_c_clk = {
|
||||
.features = CCU_FEATURE_FIXED_PREDIV,
|
||||
.hw.init = CLK_HW_INIT_PARENTS("out-c",
|
||||
clk_out_parents,
|
||||
&ccu_div_ops,
|
||||
&ccu_mp_ops,
|
||||
0),
|
||||
},
|
||||
};
|
||||
|
@ -45,7 +45,7 @@ static const struct omap_clkctrl_bit_data am3_gpio4_bit_data[] __initconst = {
|
||||
|
||||
static const struct omap_clkctrl_reg_data am3_l4_per_clkctrl_regs[] __initconst = {
|
||||
{ AM3_CPGMAC0_CLKCTRL, NULL, CLKF_SW_SUP, "cpsw_125mhz_gclk", "cpsw_125mhz_clkdm" },
|
||||
{ AM3_LCDC_CLKCTRL, NULL, CLKF_SW_SUP, "lcd_gclk", "lcdc_clkdm" },
|
||||
{ AM3_LCDC_CLKCTRL, NULL, CLKF_SW_SUP | CLKF_SET_RATE_PARENT, "lcd_gclk", "lcdc_clkdm" },
|
||||
{ AM3_USB_OTG_HS_CLKCTRL, NULL, CLKF_SW_SUP, "usbotg_fck", "l3s_clkdm" },
|
||||
{ AM3_TPTC0_CLKCTRL, NULL, CLKF_SW_SUP, "l3_gclk", "l3_clkdm" },
|
||||
{ AM3_EMIF_CLKCTRL, NULL, CLKF_SW_SUP, "dpll_ddr_m2_div2_ck", "l3_clkdm" },
|
||||
|
@ -187,7 +187,7 @@ static const struct omap_clkctrl_reg_data am4_l4_per_clkctrl_regs[] __initconst
|
||||
{ AM4_OCP2SCP0_CLKCTRL, NULL, CLKF_SW_SUP, "l4ls_gclk" },
|
||||
{ AM4_OCP2SCP1_CLKCTRL, NULL, CLKF_SW_SUP, "l4ls_gclk" },
|
||||
{ AM4_EMIF_CLKCTRL, NULL, CLKF_SW_SUP, "dpll_ddr_m2_ck", "emif_clkdm" },
|
||||
{ AM4_DSS_CORE_CLKCTRL, NULL, CLKF_SW_SUP, "disp_clk", "dss_clkdm" },
|
||||
{ AM4_DSS_CORE_CLKCTRL, NULL, CLKF_SW_SUP | CLKF_SET_RATE_PARENT, "disp_clk", "dss_clkdm" },
|
||||
{ AM4_CPGMAC0_CLKCTRL, NULL, CLKF_SW_SUP, "cpsw_125mhz_gclk", "cpsw_125mhz_clkdm" },
|
||||
{ 0 },
|
||||
};
|
||||
|
@ -537,6 +537,8 @@ static void __init _ti_omap4_clkctrl_setup(struct device_node *node)
|
||||
init.parent_names = ®_data->parent;
|
||||
init.num_parents = 1;
|
||||
init.flags = 0;
|
||||
if (reg_data->flags & CLKF_SET_RATE_PARENT)
|
||||
init.flags |= CLK_SET_RATE_PARENT;
|
||||
init.name = kasprintf(GFP_KERNEL, "%s:%s:%04x:%d",
|
||||
node->parent->name, node->name,
|
||||
reg_data->offset, 0);
|
||||
|
@ -171,6 +171,7 @@ void dma_fence_release(struct kref *kref)
|
||||
|
||||
trace_dma_fence_destroy(fence);
|
||||
|
||||
/* Failed to signal before release, could be a refcounting issue */
|
||||
WARN_ON(!list_empty(&fence->cb_list));
|
||||
|
||||
if (fence->ops->release)
|
||||
|
@ -374,8 +374,9 @@ EXPORT_SYMBOL(reservation_object_copy_fences);
|
||||
* @pshared: the array of shared fence ptrs returned (array is krealloc'd to
|
||||
* the required size, and must be freed by caller)
|
||||
*
|
||||
* RETURNS
|
||||
* Zero or -errno
|
||||
* Retrieve all fences from the reservation object. If the pointer for the
|
||||
* exclusive fence is not specified the fence is put into the array of the
|
||||
* shared fences as well. Returns either zero or -ENOMEM.
|
||||
*/
|
||||
int reservation_object_get_fences_rcu(struct reservation_object *obj,
|
||||
struct dma_fence **pfence_excl,
|
||||
@ -389,8 +390,8 @@ int reservation_object_get_fences_rcu(struct reservation_object *obj,
|
||||
|
||||
do {
|
||||
struct reservation_object_list *fobj;
|
||||
unsigned seq;
|
||||
unsigned int i;
|
||||
unsigned int i, seq;
|
||||
size_t sz = 0;
|
||||
|
||||
shared_count = i = 0;
|
||||
|
||||
@ -402,9 +403,14 @@ int reservation_object_get_fences_rcu(struct reservation_object *obj,
|
||||
goto unlock;
|
||||
|
||||
fobj = rcu_dereference(obj->fence);
|
||||
if (fobj) {
|
||||
if (fobj)
|
||||
sz += sizeof(*shared) * fobj->shared_max;
|
||||
|
||||
if (!pfence_excl && fence_excl)
|
||||
sz += sizeof(*shared);
|
||||
|
||||
if (sz) {
|
||||
struct dma_fence **nshared;
|
||||
size_t sz = sizeof(*shared) * fobj->shared_max;
|
||||
|
||||
nshared = krealloc(shared, sz,
|
||||
GFP_NOWAIT | __GFP_NOWARN);
|
||||
@ -420,13 +426,19 @@ int reservation_object_get_fences_rcu(struct reservation_object *obj,
|
||||
break;
|
||||
}
|
||||
shared = nshared;
|
||||
shared_count = fobj->shared_count;
|
||||
|
||||
shared_count = fobj ? fobj->shared_count : 0;
|
||||
for (i = 0; i < shared_count; ++i) {
|
||||
shared[i] = rcu_dereference(fobj->shared[i]);
|
||||
if (!dma_fence_get_rcu(shared[i]))
|
||||
break;
|
||||
}
|
||||
|
||||
if (!pfence_excl && fence_excl) {
|
||||
shared[i] = fence_excl;
|
||||
fence_excl = NULL;
|
||||
++i;
|
||||
++shared_count;
|
||||
}
|
||||
}
|
||||
|
||||
if (i != shared_count || read_seqcount_retry(&obj->seq, seq)) {
|
||||
@ -448,7 +460,8 @@ unlock:
|
||||
|
||||
*pshared_count = shared_count;
|
||||
*pshared = shared;
|
||||
*pfence_excl = fence_excl;
|
||||
if (pfence_excl)
|
||||
*pfence_excl = fence_excl;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
@ -43,14 +43,14 @@
|
||||
* timelines.
|
||||
*
|
||||
* Fences can be created with SW_SYNC_IOC_CREATE_FENCE ioctl with struct
|
||||
* sw_sync_ioctl_create_fence as parameter.
|
||||
* sw_sync_create_fence_data as parameter.
|
||||
*
|
||||
* To increment the timeline counter, SW_SYNC_IOC_INC ioctl should be used
|
||||
* with the increment as u32. This will update the last signaled value
|
||||
* from the timeline and signal any fence that has a seqno smaller or equal
|
||||
* to it.
|
||||
*
|
||||
* struct sw_sync_ioctl_create_fence
|
||||
* struct sw_sync_create_fence_data
|
||||
* @value: the seqno to initialise the fence with
|
||||
* @name: the name of the new sync point
|
||||
* @fence: return the fd of the new sync_file with the created fence
|
||||
@ -235,10 +235,10 @@ static void sync_timeline_signal(struct sync_timeline *obj, unsigned int inc)
|
||||
|
||||
/**
|
||||
* sync_pt_create() - creates a sync pt
|
||||
* @parent: fence's parent sync_timeline
|
||||
* @inc: value of the fence
|
||||
* @obj: parent sync_timeline
|
||||
* @value: value of the fence
|
||||
*
|
||||
* Creates a new sync_pt as a child of @parent. @size bytes will be
|
||||
* Creates a new sync_pt (fence) as a child of @parent. @size bytes will be
|
||||
* allocated allowing for implementation specific data to be kept after
|
||||
* the generic sync_timeline struct. Returns the sync_pt object or
|
||||
* NULL in case of error.
|
||||
|
@ -118,14 +118,15 @@ static void *stm32_dmamux_route_allocate(struct of_phandle_args *dma_spec,
|
||||
spin_lock_irqsave(&dmamux->lock, flags);
|
||||
mux->chan_id = find_first_zero_bit(dmamux->dma_inuse,
|
||||
dmamux->dma_requests);
|
||||
set_bit(mux->chan_id, dmamux->dma_inuse);
|
||||
spin_unlock_irqrestore(&dmamux->lock, flags);
|
||||
|
||||
if (mux->chan_id == dmamux->dma_requests) {
|
||||
spin_unlock_irqrestore(&dmamux->lock, flags);
|
||||
dev_err(&pdev->dev, "Run out of free DMA requests\n");
|
||||
ret = -ENOMEM;
|
||||
goto error;
|
||||
goto error_chan_id;
|
||||
}
|
||||
set_bit(mux->chan_id, dmamux->dma_inuse);
|
||||
spin_unlock_irqrestore(&dmamux->lock, flags);
|
||||
|
||||
/* Look for DMA Master */
|
||||
for (i = 1, min = 0, max = dmamux->dma_reqs[i];
|
||||
@ -173,6 +174,8 @@ static void *stm32_dmamux_route_allocate(struct of_phandle_args *dma_spec,
|
||||
|
||||
error:
|
||||
clear_bit(mux->chan_id, dmamux->dma_inuse);
|
||||
|
||||
error_chan_id:
|
||||
kfree(mux);
|
||||
return ERR_PTR(ret);
|
||||
}
|
||||
|
@ -25,7 +25,6 @@
|
||||
#define _ACP_GFX_IF_H
|
||||
|
||||
#include <linux/types.h>
|
||||
#include "cgs_linux.h"
|
||||
#include "cgs_common.h"
|
||||
|
||||
int amd_acp_hw_init(struct cgs_device *cgs_device,
|
||||
|
@ -30,7 +30,6 @@ FULL_AMD_DISPLAY_PATH = $(FULL_AMD_PATH)/$(DISPLAY_FOLDER_NAME)
|
||||
ccflags-y := -I$(FULL_AMD_PATH)/include/asic_reg \
|
||||
-I$(FULL_AMD_PATH)/include \
|
||||
-I$(FULL_AMD_PATH)/amdgpu \
|
||||
-I$(FULL_AMD_PATH)/scheduler \
|
||||
-I$(FULL_AMD_PATH)/powerplay/inc \
|
||||
-I$(FULL_AMD_PATH)/acp/include \
|
||||
-I$(FULL_AMD_DISPLAY_PATH) \
|
||||
@ -63,7 +62,7 @@ amdgpu-$(CONFIG_DRM_AMDGPU_CIK)+= cik.o cik_ih.o kv_smc.o kv_dpm.o \
|
||||
amdgpu-$(CONFIG_DRM_AMDGPU_SI)+= si.o gmc_v6_0.o gfx_v6_0.o si_ih.o si_dma.o dce_v6_0.o si_dpm.o si_smc.o
|
||||
|
||||
amdgpu-y += \
|
||||
vi.o mxgpu_vi.o nbio_v6_1.o soc15.o mxgpu_ai.o nbio_v7_0.o vega10_reg_init.o
|
||||
vi.o mxgpu_vi.o nbio_v6_1.o soc15.o emu_soc.o mxgpu_ai.o nbio_v7_0.o vega10_reg_init.o
|
||||
|
||||
# add GMC block
|
||||
amdgpu-y += \
|
||||
@ -88,8 +87,7 @@ amdgpu-y += \
|
||||
|
||||
# add SMC block
|
||||
amdgpu-y += \
|
||||
amdgpu_dpm.o \
|
||||
amdgpu_powerplay.o
|
||||
amdgpu_dpm.o
|
||||
|
||||
# add DCE block
|
||||
amdgpu-y += \
|
||||
@ -130,6 +128,8 @@ amdgpu-y += \
|
||||
# add amdkfd interfaces
|
||||
amdgpu-y += \
|
||||
amdgpu_amdkfd.o \
|
||||
amdgpu_amdkfd_fence.o \
|
||||
amdgpu_amdkfd_gpuvm.o \
|
||||
amdgpu_amdkfd_gfx_v8.o
|
||||
|
||||
# add cgs
|
||||
|
@ -68,6 +68,7 @@
|
||||
#include "amdgpu_vce.h"
|
||||
#include "amdgpu_vcn.h"
|
||||
#include "amdgpu_mn.h"
|
||||
#include "amdgpu_gmc.h"
|
||||
#include "amdgpu_dm.h"
|
||||
#include "amdgpu_virt.h"
|
||||
#include "amdgpu_gart.h"
|
||||
@ -127,6 +128,7 @@ extern int amdgpu_job_hang_limit;
|
||||
extern int amdgpu_lbpw;
|
||||
extern int amdgpu_compute_multipipe;
|
||||
extern int amdgpu_gpu_recovery;
|
||||
extern int amdgpu_emu_mode;
|
||||
|
||||
#ifdef CONFIG_DRM_AMDGPU_SI
|
||||
extern int amdgpu_si_support;
|
||||
@ -179,10 +181,6 @@ extern int amdgpu_cik_support;
|
||||
#define CIK_CURSOR_WIDTH 128
|
||||
#define CIK_CURSOR_HEIGHT 128
|
||||
|
||||
/* GPU RESET flags */
|
||||
#define AMDGPU_RESET_INFO_VRAM_LOST (1 << 0)
|
||||
#define AMDGPU_RESET_INFO_FULLRESET (1 << 1)
|
||||
|
||||
struct amdgpu_device;
|
||||
struct amdgpu_ib;
|
||||
struct amdgpu_cs_parser;
|
||||
@ -318,13 +316,6 @@ struct amdgpu_vm_pte_funcs {
|
||||
void (*write_pte)(struct amdgpu_ib *ib, uint64_t pe,
|
||||
uint64_t value, unsigned count,
|
||||
uint32_t incr);
|
||||
|
||||
/* maximum nums of PTEs/PDEs in a single operation */
|
||||
uint32_t set_max_nums_pte_pde;
|
||||
|
||||
/* number of dw to reserve per operation */
|
||||
unsigned set_pte_pde_num_dw;
|
||||
|
||||
/* for linear pte/pde updates without addr mapping */
|
||||
void (*set_pte_pde)(struct amdgpu_ib *ib,
|
||||
uint64_t pe,
|
||||
@ -332,28 +323,6 @@ struct amdgpu_vm_pte_funcs {
|
||||
uint32_t incr, uint64_t flags);
|
||||
};
|
||||
|
||||
/* provided by the gmc block */
|
||||
struct amdgpu_gart_funcs {
|
||||
/* flush the vm tlb via mmio */
|
||||
void (*flush_gpu_tlb)(struct amdgpu_device *adev,
|
||||
uint32_t vmid);
|
||||
/* write pte/pde updates using the cpu */
|
||||
int (*set_pte_pde)(struct amdgpu_device *adev,
|
||||
void *cpu_pt_addr, /* cpu addr of page table */
|
||||
uint32_t gpu_page_idx, /* pte/pde to update */
|
||||
uint64_t addr, /* addr to write into pte/pde */
|
||||
uint64_t flags); /* access flags */
|
||||
/* enable/disable PRT support */
|
||||
void (*set_prt)(struct amdgpu_device *adev, bool enable);
|
||||
/* set pte flags based per asic */
|
||||
uint64_t (*get_vm_pte_flags)(struct amdgpu_device *adev,
|
||||
uint32_t flags);
|
||||
/* get the pde for a given mc addr */
|
||||
void (*get_vm_pde)(struct amdgpu_device *adev, int level,
|
||||
u64 *dst, u64 *flags);
|
||||
uint32_t (*get_invalidate_req)(unsigned int vmid);
|
||||
};
|
||||
|
||||
/* provided by the ih block */
|
||||
struct amdgpu_ih_funcs {
|
||||
/* ring read/write ptr handling, called from interrupt context */
|
||||
@ -370,14 +339,6 @@ struct amdgpu_ih_funcs {
|
||||
bool amdgpu_get_bios(struct amdgpu_device *adev);
|
||||
bool amdgpu_read_bios(struct amdgpu_device *adev);
|
||||
|
||||
/*
|
||||
* Dummy page
|
||||
*/
|
||||
struct amdgpu_dummy_page {
|
||||
struct page *page;
|
||||
dma_addr_t addr;
|
||||
};
|
||||
|
||||
/*
|
||||
* Clocks
|
||||
*/
|
||||
@ -418,8 +379,8 @@ amdgpu_gem_prime_import_sg_table(struct drm_device *dev,
|
||||
struct dma_buf *amdgpu_gem_prime_export(struct drm_device *dev,
|
||||
struct drm_gem_object *gobj,
|
||||
int flags);
|
||||
int amdgpu_gem_prime_pin(struct drm_gem_object *obj);
|
||||
void amdgpu_gem_prime_unpin(struct drm_gem_object *obj);
|
||||
struct drm_gem_object *amdgpu_gem_prime_import(struct drm_device *dev,
|
||||
struct dma_buf *dma_buf);
|
||||
struct reservation_object *amdgpu_gem_prime_res_obj(struct drm_gem_object *);
|
||||
void *amdgpu_gem_prime_vmap(struct drm_gem_object *obj);
|
||||
void amdgpu_gem_prime_vunmap(struct drm_gem_object *obj, void *vaddr);
|
||||
@ -480,7 +441,7 @@ struct amdgpu_sa_bo {
|
||||
void amdgpu_gem_force_release(struct amdgpu_device *adev);
|
||||
int amdgpu_gem_object_create(struct amdgpu_device *adev, unsigned long size,
|
||||
int alignment, u32 initial_domain,
|
||||
u64 flags, bool kernel,
|
||||
u64 flags, enum ttm_bo_type type,
|
||||
struct reservation_object *resv,
|
||||
struct drm_gem_object **obj);
|
||||
|
||||
@ -493,56 +454,6 @@ int amdgpu_mode_dumb_mmap(struct drm_file *filp,
|
||||
int amdgpu_fence_slab_init(void);
|
||||
void amdgpu_fence_slab_fini(void);
|
||||
|
||||
/*
|
||||
* VMHUB structures, functions & helpers
|
||||
*/
|
||||
struct amdgpu_vmhub {
|
||||
uint32_t ctx0_ptb_addr_lo32;
|
||||
uint32_t ctx0_ptb_addr_hi32;
|
||||
uint32_t vm_inv_eng0_req;
|
||||
uint32_t vm_inv_eng0_ack;
|
||||
uint32_t vm_context0_cntl;
|
||||
uint32_t vm_l2_pro_fault_status;
|
||||
uint32_t vm_l2_pro_fault_cntl;
|
||||
};
|
||||
|
||||
/*
|
||||
* GPU MC structures, functions & helpers
|
||||
*/
|
||||
struct amdgpu_mc {
|
||||
resource_size_t aper_size;
|
||||
resource_size_t aper_base;
|
||||
resource_size_t agp_base;
|
||||
/* for some chips with <= 32MB we need to lie
|
||||
* about vram size near mc fb location */
|
||||
u64 mc_vram_size;
|
||||
u64 visible_vram_size;
|
||||
u64 gart_size;
|
||||
u64 gart_start;
|
||||
u64 gart_end;
|
||||
u64 vram_start;
|
||||
u64 vram_end;
|
||||
unsigned vram_width;
|
||||
u64 real_vram_size;
|
||||
int vram_mtrr;
|
||||
u64 mc_mask;
|
||||
const struct firmware *fw; /* MC firmware */
|
||||
uint32_t fw_version;
|
||||
struct amdgpu_irq_src vm_fault;
|
||||
uint32_t vram_type;
|
||||
uint32_t srbm_soft_reset;
|
||||
bool prt_warning;
|
||||
uint64_t stolen_size;
|
||||
/* apertures */
|
||||
u64 shared_aperture_start;
|
||||
u64 shared_aperture_end;
|
||||
u64 private_aperture_start;
|
||||
u64 private_aperture_end;
|
||||
/* protects concurrent invalidation */
|
||||
spinlock_t invalidate_lock;
|
||||
bool translate_further;
|
||||
};
|
||||
|
||||
/*
|
||||
* GPU doorbell structures, functions & helpers
|
||||
*/
|
||||
@ -979,6 +890,7 @@ struct amdgpu_gfx_funcs {
|
||||
void (*read_wave_data)(struct amdgpu_device *adev, uint32_t simd, uint32_t wave, uint32_t *dst, int *no_fields);
|
||||
void (*read_wave_vgprs)(struct amdgpu_device *adev, uint32_t simd, uint32_t wave, uint32_t thread, uint32_t start, uint32_t size, uint32_t *dst);
|
||||
void (*read_wave_sgprs)(struct amdgpu_device *adev, uint32_t simd, uint32_t wave, uint32_t start, uint32_t size, uint32_t *dst);
|
||||
void (*select_me_pipe_q)(struct amdgpu_device *adev, u32 me, u32 pipe, u32 queue);
|
||||
};
|
||||
|
||||
struct amdgpu_ngg_buf {
|
||||
@ -1125,8 +1037,9 @@ struct amdgpu_job {
|
||||
void *owner;
|
||||
uint64_t fence_ctx; /* the fence_context this job uses */
|
||||
bool vm_needs_flush;
|
||||
unsigned vmid;
|
||||
uint64_t vm_pd_addr;
|
||||
unsigned vmid;
|
||||
unsigned pasid;
|
||||
uint32_t gds_base, gds_size;
|
||||
uint32_t gws_base, gws_size;
|
||||
uint32_t oa_base, oa_size;
|
||||
@ -1169,8 +1082,6 @@ struct amdgpu_wb {
|
||||
int amdgpu_device_wb_get(struct amdgpu_device *adev, u32 *wb);
|
||||
void amdgpu_device_wb_free(struct amdgpu_device *adev, u32 wb);
|
||||
|
||||
void amdgpu_device_get_pcie_info(struct amdgpu_device *adev);
|
||||
|
||||
/*
|
||||
* SDMA
|
||||
*/
|
||||
@ -1288,6 +1199,11 @@ struct amdgpu_asic_funcs {
|
||||
void (*set_pcie_lanes)(struct amdgpu_device *adev, int lanes);
|
||||
/* get config memsize register */
|
||||
u32 (*get_config_memsize)(struct amdgpu_device *adev);
|
||||
/* flush hdp write queue */
|
||||
void (*flush_hdp)(struct amdgpu_device *adev, struct amdgpu_ring *ring);
|
||||
/* invalidate hdp read cache */
|
||||
void (*invalidate_hdp)(struct amdgpu_device *adev,
|
||||
struct amdgpu_ring *ring);
|
||||
};
|
||||
|
||||
/*
|
||||
@ -1431,7 +1347,7 @@ struct amdgpu_nbio_funcs {
|
||||
u32 (*get_pcie_data_offset)(struct amdgpu_device *adev);
|
||||
u32 (*get_rev_id)(struct amdgpu_device *adev);
|
||||
void (*mc_access_enable)(struct amdgpu_device *adev, bool enable);
|
||||
void (*hdp_flush)(struct amdgpu_device *adev);
|
||||
void (*hdp_flush)(struct amdgpu_device *adev, struct amdgpu_ring *ring);
|
||||
u32 (*get_memsize)(struct amdgpu_device *adev);
|
||||
void (*sdma_doorbell_range)(struct amdgpu_device *adev, int instance,
|
||||
bool use_doorbell, int doorbell_index);
|
||||
@ -1463,6 +1379,7 @@ enum amd_hw_ip_block_type {
|
||||
ATHUB_HWIP,
|
||||
NBIO_HWIP,
|
||||
MP0_HWIP,
|
||||
MP1_HWIP,
|
||||
UVD_HWIP,
|
||||
VCN_HWIP = UVD_HWIP,
|
||||
VCE_HWIP,
|
||||
@ -1472,15 +1389,14 @@ enum amd_hw_ip_block_type {
|
||||
SMUIO_HWIP,
|
||||
PWR_HWIP,
|
||||
NBIF_HWIP,
|
||||
THM_HWIP,
|
||||
MAX_HWIP
|
||||
};
|
||||
|
||||
#define HWIP_MAX_INSTANCE 6
|
||||
|
||||
struct amd_powerplay {
|
||||
struct cgs_device *cgs_device;
|
||||
void *pp_handle;
|
||||
const struct amd_ip_funcs *ip_funcs;
|
||||
const struct amd_pm_funcs *pp_funcs;
|
||||
};
|
||||
|
||||
@ -1504,6 +1420,7 @@ struct amdgpu_device {
|
||||
const struct amdgpu_asic_funcs *asic_funcs;
|
||||
bool shutdown;
|
||||
bool need_dma32;
|
||||
bool need_swiotlb;
|
||||
bool accel_working;
|
||||
struct work_struct reset_work;
|
||||
struct notifier_block acpi_nb;
|
||||
@ -1573,9 +1490,9 @@ struct amdgpu_device {
|
||||
struct amdgpu_clock clock;
|
||||
|
||||
/* MC */
|
||||
struct amdgpu_mc mc;
|
||||
struct amdgpu_gmc gmc;
|
||||
struct amdgpu_gart gart;
|
||||
struct amdgpu_dummy_page dummy_page;
|
||||
dma_addr_t dummy_page_addr;
|
||||
struct amdgpu_vm_manager vm_manager;
|
||||
struct amdgpu_vmhub vmhub[AMDGPU_MAX_VMHUBS];
|
||||
|
||||
@ -1714,6 +1631,9 @@ uint32_t amdgpu_mm_rreg(struct amdgpu_device *adev, uint32_t reg,
|
||||
uint32_t acc_flags);
|
||||
void amdgpu_mm_wreg(struct amdgpu_device *adev, uint32_t reg, uint32_t v,
|
||||
uint32_t acc_flags);
|
||||
void amdgpu_mm_wreg8(struct amdgpu_device *adev, uint32_t offset, uint8_t value);
|
||||
uint8_t amdgpu_mm_rreg8(struct amdgpu_device *adev, uint32_t offset);
|
||||
|
||||
u32 amdgpu_io_rreg(struct amdgpu_device *adev, u32 reg);
|
||||
void amdgpu_io_wreg(struct amdgpu_device *adev, u32 reg, u32 v);
|
||||
|
||||
@ -1725,6 +1645,8 @@ void amdgpu_mm_wdoorbell64(struct amdgpu_device *adev, u32 index, u64 v);
|
||||
bool amdgpu_device_asic_has_dc_support(enum amd_asic_type asic_type);
|
||||
bool amdgpu_device_has_dc_support(struct amdgpu_device *adev);
|
||||
|
||||
int emu_soc_asic_init(struct amdgpu_device *adev);
|
||||
|
||||
/*
|
||||
* Registers read & write functions.
|
||||
*/
|
||||
@ -1735,6 +1657,9 @@ bool amdgpu_device_has_dc_support(struct amdgpu_device *adev);
|
||||
#define RREG32_NO_KIQ(reg) amdgpu_mm_rreg(adev, (reg), AMDGPU_REGS_NO_KIQ)
|
||||
#define WREG32_NO_KIQ(reg, v) amdgpu_mm_wreg(adev, (reg), (v), AMDGPU_REGS_NO_KIQ)
|
||||
|
||||
#define RREG8(reg) amdgpu_mm_rreg8(adev, (reg))
|
||||
#define WREG8(reg, v) amdgpu_mm_wreg8(adev, (reg), (v))
|
||||
|
||||
#define RREG32(reg) amdgpu_mm_rreg(adev, (reg), 0)
|
||||
#define RREG32_IDX(reg) amdgpu_mm_rreg(adev, (reg), AMDGPU_REGS_IDX)
|
||||
#define DREG32(reg) printk(KERN_INFO "REGISTER: " #reg " : 0x%08X\n", amdgpu_mm_rreg(adev, (reg), 0))
|
||||
@ -1837,13 +1762,17 @@ amdgpu_get_sdma_instance(struct amdgpu_ring *ring)
|
||||
#define amdgpu_asic_read_bios_from_rom(adev, b, l) (adev)->asic_funcs->read_bios_from_rom((adev), (b), (l))
|
||||
#define amdgpu_asic_read_register(adev, se, sh, offset, v)((adev)->asic_funcs->read_register((adev), (se), (sh), (offset), (v)))
|
||||
#define amdgpu_asic_get_config_memsize(adev) (adev)->asic_funcs->get_config_memsize((adev))
|
||||
#define amdgpu_gart_flush_gpu_tlb(adev, vmid) (adev)->gart.gart_funcs->flush_gpu_tlb((adev), (vmid))
|
||||
#define amdgpu_gart_set_pte_pde(adev, pt, idx, addr, flags) (adev)->gart.gart_funcs->set_pte_pde((adev), (pt), (idx), (addr), (flags))
|
||||
#define amdgpu_gart_get_vm_pde(adev, level, dst, flags) (adev)->gart.gart_funcs->get_vm_pde((adev), (level), (dst), (flags))
|
||||
#define amdgpu_asic_flush_hdp(adev, r) (adev)->asic_funcs->flush_hdp((adev), (r))
|
||||
#define amdgpu_asic_invalidate_hdp(adev, r) (adev)->asic_funcs->invalidate_hdp((adev), (r))
|
||||
#define amdgpu_gmc_flush_gpu_tlb(adev, vmid) (adev)->gmc.gmc_funcs->flush_gpu_tlb((adev), (vmid))
|
||||
#define amdgpu_gmc_emit_flush_gpu_tlb(r, vmid, addr) (r)->adev->gmc.gmc_funcs->emit_flush_gpu_tlb((r), (vmid), (addr))
|
||||
#define amdgpu_gmc_emit_pasid_mapping(r, vmid, pasid) (r)->adev->gmc.gmc_funcs->emit_pasid_mapping((r), (vmid), (pasid))
|
||||
#define amdgpu_gmc_set_pte_pde(adev, pt, idx, addr, flags) (adev)->gmc.gmc_funcs->set_pte_pde((adev), (pt), (idx), (addr), (flags))
|
||||
#define amdgpu_gmc_get_vm_pde(adev, level, dst, flags) (adev)->gmc.gmc_funcs->get_vm_pde((adev), (level), (dst), (flags))
|
||||
#define amdgpu_gmc_get_pte_flags(adev, flags) (adev)->gmc.gmc_funcs->get_vm_pte_flags((adev),(flags))
|
||||
#define amdgpu_vm_copy_pte(adev, ib, pe, src, count) ((adev)->vm_manager.vm_pte_funcs->copy_pte((ib), (pe), (src), (count)))
|
||||
#define amdgpu_vm_write_pte(adev, ib, pe, value, count, incr) ((adev)->vm_manager.vm_pte_funcs->write_pte((ib), (pe), (value), (count), (incr)))
|
||||
#define amdgpu_vm_set_pte_pde(adev, ib, pe, addr, count, incr, flags) ((adev)->vm_manager.vm_pte_funcs->set_pte_pde((ib), (pe), (addr), (count), (incr), (flags)))
|
||||
#define amdgpu_vm_get_pte_flags(adev, flags) (adev)->gart.gart_funcs->get_vm_pte_flags((adev),(flags))
|
||||
#define amdgpu_ring_parse_cs(r, p, ib) ((r)->funcs->parse_cs((p), (ib)))
|
||||
#define amdgpu_ring_test_ring(r) (r)->funcs->test_ring((r))
|
||||
#define amdgpu_ring_test_ib(r, t) (r)->funcs->test_ib((r), (t))
|
||||
@ -1856,11 +1785,11 @@ amdgpu_get_sdma_instance(struct amdgpu_ring *ring)
|
||||
#define amdgpu_ring_emit_fence(r, addr, seq, flags) (r)->funcs->emit_fence((r), (addr), (seq), (flags))
|
||||
#define amdgpu_ring_emit_gds_switch(r, v, db, ds, wb, ws, ab, as) (r)->funcs->emit_gds_switch((r), (v), (db), (ds), (wb), (ws), (ab), (as))
|
||||
#define amdgpu_ring_emit_hdp_flush(r) (r)->funcs->emit_hdp_flush((r))
|
||||
#define amdgpu_ring_emit_hdp_invalidate(r) (r)->funcs->emit_hdp_invalidate((r))
|
||||
#define amdgpu_ring_emit_switch_buffer(r) (r)->funcs->emit_switch_buffer((r))
|
||||
#define amdgpu_ring_emit_cntxcntl(r, d) (r)->funcs->emit_cntxcntl((r), (d))
|
||||
#define amdgpu_ring_emit_rreg(r, d) (r)->funcs->emit_rreg((r), (d))
|
||||
#define amdgpu_ring_emit_wreg(r, d, v) (r)->funcs->emit_wreg((r), (d), (v))
|
||||
#define amdgpu_ring_emit_reg_wait(r, d, v, m) (r)->funcs->emit_reg_wait((r), (d), (v), (m))
|
||||
#define amdgpu_ring_emit_tmz(r, b) (r)->funcs->emit_tmz((r), (b))
|
||||
#define amdgpu_ring_pad_ib(r, ib) ((r)->funcs->pad_ib((r), (ib)))
|
||||
#define amdgpu_ring_init_cond_exec(r) (r)->funcs->init_cond_exec((r))
|
||||
@ -1870,7 +1799,6 @@ amdgpu_get_sdma_instance(struct amdgpu_ring *ring)
|
||||
#define amdgpu_ih_decode_iv(adev, iv) (adev)->irq.ih_funcs->decode_iv((adev), (iv))
|
||||
#define amdgpu_ih_set_rptr(adev) (adev)->irq.ih_funcs->set_rptr((adev))
|
||||
#define amdgpu_display_vblank_get_counter(adev, crtc) (adev)->mode_info.funcs->vblank_get_counter((adev), (crtc))
|
||||
#define amdgpu_display_vblank_wait(adev, crtc) (adev)->mode_info.funcs->vblank_wait((adev), (crtc))
|
||||
#define amdgpu_display_backlight_set_level(adev, e, l) (adev)->mode_info.funcs->backlight_set_level((e), (l))
|
||||
#define amdgpu_display_backlight_get_level(adev, e) (adev)->mode_info.funcs->backlight_get_level((e))
|
||||
#define amdgpu_display_hpd_sense(adev, h) (adev)->mode_info.funcs->hpd_sense((adev), (h))
|
||||
@ -1887,26 +1815,24 @@ amdgpu_get_sdma_instance(struct amdgpu_ring *ring)
|
||||
#define amdgpu_gfx_select_se_sh(adev, se, sh, instance) (adev)->gfx.funcs->select_se_sh((adev), (se), (sh), (instance))
|
||||
#define amdgpu_gds_switch(adev, r, v, d, w, a) (adev)->gds.funcs->patch_gds_switch((r), (v), (d), (w), (a))
|
||||
#define amdgpu_psp_check_fw_loading_status(adev, i) (adev)->firmware.funcs->check_fw_loading_status((adev), (i))
|
||||
#define amdgpu_gfx_select_me_pipe_q(adev, me, pipe, q) (adev)->gfx.funcs->select_me_pipe_q((adev), (me), (pipe), (q))
|
||||
|
||||
/* Common functions */
|
||||
int amdgpu_device_gpu_recover(struct amdgpu_device *adev,
|
||||
struct amdgpu_job* job, bool force);
|
||||
void amdgpu_device_pci_config_reset(struct amdgpu_device *adev);
|
||||
bool amdgpu_device_need_post(struct amdgpu_device *adev);
|
||||
void amdgpu_update_display_priority(struct amdgpu_device *adev);
|
||||
void amdgpu_display_update_priority(struct amdgpu_device *adev);
|
||||
|
||||
void amdgpu_cs_report_moved_bytes(struct amdgpu_device *adev, u64 num_bytes,
|
||||
u64 num_vis_bytes);
|
||||
void amdgpu_ttm_placement_from_domain(struct amdgpu_bo *abo, u32 domain);
|
||||
bool amdgpu_ttm_bo_is_amdgpu_bo(struct ttm_buffer_object *bo);
|
||||
void amdgpu_device_vram_location(struct amdgpu_device *adev,
|
||||
struct amdgpu_mc *mc, u64 base);
|
||||
struct amdgpu_gmc *mc, u64 base);
|
||||
void amdgpu_device_gart_location(struct amdgpu_device *adev,
|
||||
struct amdgpu_mc *mc);
|
||||
struct amdgpu_gmc *mc);
|
||||
int amdgpu_device_resize_fb_bar(struct amdgpu_device *adev);
|
||||
void amdgpu_ttm_set_active_vram_size(struct amdgpu_device *adev, u64 size);
|
||||
int amdgpu_ttm_init(struct amdgpu_device *adev);
|
||||
void amdgpu_ttm_fini(struct amdgpu_device *adev);
|
||||
void amdgpu_device_program_register_sequence(struct amdgpu_device *adev,
|
||||
const u32 *registers,
|
||||
const u32 array_size);
|
||||
|
@ -30,6 +30,8 @@
|
||||
const struct kgd2kfd_calls *kgd2kfd;
|
||||
bool (*kgd2kfd_init_p)(unsigned int, const struct kgd2kfd_calls**);
|
||||
|
||||
static const unsigned int compute_vmid_bitmap = 0xFF00;
|
||||
|
||||
int amdgpu_amdkfd_init(void)
|
||||
{
|
||||
int ret;
|
||||
@ -56,6 +58,7 @@ int amdgpu_amdkfd_init(void)
|
||||
#else
|
||||
ret = -ENOENT;
|
||||
#endif
|
||||
amdgpu_amdkfd_gpuvm_init_mem_limits();
|
||||
|
||||
return ret;
|
||||
}
|
||||
@ -78,10 +81,15 @@ void amdgpu_amdkfd_device_probe(struct amdgpu_device *adev)
|
||||
switch (adev->asic_type) {
|
||||
#ifdef CONFIG_DRM_AMDGPU_CIK
|
||||
case CHIP_KAVERI:
|
||||
case CHIP_HAWAII:
|
||||
kfd2kgd = amdgpu_amdkfd_gfx_7_get_functions();
|
||||
break;
|
||||
#endif
|
||||
case CHIP_CARRIZO:
|
||||
case CHIP_TONGA:
|
||||
case CHIP_FIJI:
|
||||
case CHIP_POLARIS10:
|
||||
case CHIP_POLARIS11:
|
||||
kfd2kgd = amdgpu_amdkfd_gfx_8_0_get_functions();
|
||||
break;
|
||||
default:
|
||||
@ -132,9 +140,13 @@ void amdgpu_amdkfd_device_init(struct amdgpu_device *adev)
|
||||
int last_valid_bit;
|
||||
if (adev->kfd) {
|
||||
struct kgd2kfd_shared_resources gpu_resources = {
|
||||
.compute_vmid_bitmap = 0xFF00,
|
||||
.compute_vmid_bitmap = compute_vmid_bitmap,
|
||||
.num_pipe_per_mec = adev->gfx.mec.num_pipe_per_mec,
|
||||
.num_queue_per_pipe = adev->gfx.mec.num_queue_per_pipe
|
||||
.num_queue_per_pipe = adev->gfx.mec.num_queue_per_pipe,
|
||||
.gpuvm_size = min(adev->vm_manager.max_pfn
|
||||
<< AMDGPU_GPU_PAGE_SHIFT,
|
||||
AMDGPU_VA_HOLE_START),
|
||||
.drm_render_minor = adev->ddev->render->index
|
||||
};
|
||||
|
||||
/* this is going to have a few of the MSBs set that we need to
|
||||
@ -204,20 +216,14 @@ int alloc_gtt_mem(struct kgd_dev *kgd, size_t size,
|
||||
void **cpu_ptr)
|
||||
{
|
||||
struct amdgpu_device *adev = (struct amdgpu_device *)kgd;
|
||||
struct kgd_mem **mem = (struct kgd_mem **) mem_obj;
|
||||
struct amdgpu_bo *bo = NULL;
|
||||
int r;
|
||||
uint64_t gpu_addr_tmp = 0;
|
||||
void *cpu_ptr_tmp = NULL;
|
||||
|
||||
BUG_ON(kgd == NULL);
|
||||
BUG_ON(gpu_addr == NULL);
|
||||
BUG_ON(cpu_ptr == NULL);
|
||||
|
||||
*mem = kmalloc(sizeof(struct kgd_mem), GFP_KERNEL);
|
||||
if ((*mem) == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
r = amdgpu_bo_create(adev, size, PAGE_SIZE, true, AMDGPU_GEM_DOMAIN_GTT,
|
||||
AMDGPU_GEM_CREATE_CPU_GTT_USWC, NULL, NULL, 0,
|
||||
&(*mem)->bo);
|
||||
r = amdgpu_bo_create(adev, size, PAGE_SIZE, AMDGPU_GEM_DOMAIN_GTT,
|
||||
AMDGPU_GEM_CREATE_CPU_GTT_USWC, ttm_bo_type_kernel,
|
||||
NULL, &bo);
|
||||
if (r) {
|
||||
dev_err(adev->dev,
|
||||
"failed to allocate BO for amdkfd (%d)\n", r);
|
||||
@ -225,54 +231,53 @@ int alloc_gtt_mem(struct kgd_dev *kgd, size_t size,
|
||||
}
|
||||
|
||||
/* map the buffer */
|
||||
r = amdgpu_bo_reserve((*mem)->bo, true);
|
||||
r = amdgpu_bo_reserve(bo, true);
|
||||
if (r) {
|
||||
dev_err(adev->dev, "(%d) failed to reserve bo for amdkfd\n", r);
|
||||
goto allocate_mem_reserve_bo_failed;
|
||||
}
|
||||
|
||||
r = amdgpu_bo_pin((*mem)->bo, AMDGPU_GEM_DOMAIN_GTT,
|
||||
&(*mem)->gpu_addr);
|
||||
r = amdgpu_bo_pin(bo, AMDGPU_GEM_DOMAIN_GTT,
|
||||
&gpu_addr_tmp);
|
||||
if (r) {
|
||||
dev_err(adev->dev, "(%d) failed to pin bo for amdkfd\n", r);
|
||||
goto allocate_mem_pin_bo_failed;
|
||||
}
|
||||
*gpu_addr = (*mem)->gpu_addr;
|
||||
|
||||
r = amdgpu_bo_kmap((*mem)->bo, &(*mem)->cpu_ptr);
|
||||
r = amdgpu_bo_kmap(bo, &cpu_ptr_tmp);
|
||||
if (r) {
|
||||
dev_err(adev->dev,
|
||||
"(%d) failed to map bo to kernel for amdkfd\n", r);
|
||||
goto allocate_mem_kmap_bo_failed;
|
||||
}
|
||||
*cpu_ptr = (*mem)->cpu_ptr;
|
||||
|
||||
amdgpu_bo_unreserve((*mem)->bo);
|
||||
*mem_obj = bo;
|
||||
*gpu_addr = gpu_addr_tmp;
|
||||
*cpu_ptr = cpu_ptr_tmp;
|
||||
|
||||
amdgpu_bo_unreserve(bo);
|
||||
|
||||
return 0;
|
||||
|
||||
allocate_mem_kmap_bo_failed:
|
||||
amdgpu_bo_unpin((*mem)->bo);
|
||||
amdgpu_bo_unpin(bo);
|
||||
allocate_mem_pin_bo_failed:
|
||||
amdgpu_bo_unreserve((*mem)->bo);
|
||||
amdgpu_bo_unreserve(bo);
|
||||
allocate_mem_reserve_bo_failed:
|
||||
amdgpu_bo_unref(&(*mem)->bo);
|
||||
amdgpu_bo_unref(&bo);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
void free_gtt_mem(struct kgd_dev *kgd, void *mem_obj)
|
||||
{
|
||||
struct kgd_mem *mem = (struct kgd_mem *) mem_obj;
|
||||
struct amdgpu_bo *bo = (struct amdgpu_bo *) mem_obj;
|
||||
|
||||
BUG_ON(mem == NULL);
|
||||
|
||||
amdgpu_bo_reserve(mem->bo, true);
|
||||
amdgpu_bo_kunmap(mem->bo);
|
||||
amdgpu_bo_unpin(mem->bo);
|
||||
amdgpu_bo_unreserve(mem->bo);
|
||||
amdgpu_bo_unref(&(mem->bo));
|
||||
kfree(mem);
|
||||
amdgpu_bo_reserve(bo, true);
|
||||
amdgpu_bo_kunmap(bo);
|
||||
amdgpu_bo_unpin(bo);
|
||||
amdgpu_bo_unreserve(bo);
|
||||
amdgpu_bo_unref(&(bo));
|
||||
}
|
||||
|
||||
void get_local_mem_info(struct kgd_dev *kgd,
|
||||
@ -281,24 +286,29 @@ void get_local_mem_info(struct kgd_dev *kgd,
|
||||
struct amdgpu_device *adev = (struct amdgpu_device *)kgd;
|
||||
uint64_t address_mask = adev->dev->dma_mask ? ~*adev->dev->dma_mask :
|
||||
~((1ULL << 32) - 1);
|
||||
resource_size_t aper_limit = adev->mc.aper_base + adev->mc.aper_size;
|
||||
resource_size_t aper_limit = adev->gmc.aper_base + adev->gmc.aper_size;
|
||||
|
||||
memset(mem_info, 0, sizeof(*mem_info));
|
||||
if (!(adev->mc.aper_base & address_mask || aper_limit & address_mask)) {
|
||||
mem_info->local_mem_size_public = adev->mc.visible_vram_size;
|
||||
mem_info->local_mem_size_private = adev->mc.real_vram_size -
|
||||
adev->mc.visible_vram_size;
|
||||
if (!(adev->gmc.aper_base & address_mask || aper_limit & address_mask)) {
|
||||
mem_info->local_mem_size_public = adev->gmc.visible_vram_size;
|
||||
mem_info->local_mem_size_private = adev->gmc.real_vram_size -
|
||||
adev->gmc.visible_vram_size;
|
||||
} else {
|
||||
mem_info->local_mem_size_public = 0;
|
||||
mem_info->local_mem_size_private = adev->mc.real_vram_size;
|
||||
mem_info->local_mem_size_private = adev->gmc.real_vram_size;
|
||||
}
|
||||
mem_info->vram_width = adev->mc.vram_width;
|
||||
mem_info->vram_width = adev->gmc.vram_width;
|
||||
|
||||
pr_debug("Address base: %pap limit %pap public 0x%llx private 0x%llx\n",
|
||||
&adev->mc.aper_base, &aper_limit,
|
||||
&adev->gmc.aper_base, &aper_limit,
|
||||
mem_info->local_mem_size_public,
|
||||
mem_info->local_mem_size_private);
|
||||
|
||||
if (amdgpu_emu_mode == 1) {
|
||||
mem_info->mem_clk_max = 100;
|
||||
return;
|
||||
}
|
||||
|
||||
if (amdgpu_sriov_vf(adev))
|
||||
mem_info->mem_clk_max = adev->clock.default_mclk / 100;
|
||||
else
|
||||
@ -319,6 +329,9 @@ uint32_t get_max_engine_clock_in_mhz(struct kgd_dev *kgd)
|
||||
struct amdgpu_device *adev = (struct amdgpu_device *)kgd;
|
||||
|
||||
/* the sclk is in quantas of 10kHz */
|
||||
if (amdgpu_emu_mode == 1)
|
||||
return 100;
|
||||
|
||||
if (amdgpu_sriov_vf(adev))
|
||||
return adev->clock.default_sclk / 100;
|
||||
|
||||
@ -354,3 +367,68 @@ uint64_t amdgpu_amdkfd_get_vram_usage(struct kgd_dev *kgd)
|
||||
|
||||
return amdgpu_vram_mgr_usage(&adev->mman.bdev.man[TTM_PL_VRAM]);
|
||||
}
|
||||
|
||||
int amdgpu_amdkfd_submit_ib(struct kgd_dev *kgd, enum kgd_engine_type engine,
|
||||
uint32_t vmid, uint64_t gpu_addr,
|
||||
uint32_t *ib_cmd, uint32_t ib_len)
|
||||
{
|
||||
struct amdgpu_device *adev = (struct amdgpu_device *)kgd;
|
||||
struct amdgpu_job *job;
|
||||
struct amdgpu_ib *ib;
|
||||
struct amdgpu_ring *ring;
|
||||
struct dma_fence *f = NULL;
|
||||
int ret;
|
||||
|
||||
switch (engine) {
|
||||
case KGD_ENGINE_MEC1:
|
||||
ring = &adev->gfx.compute_ring[0];
|
||||
break;
|
||||
case KGD_ENGINE_SDMA1:
|
||||
ring = &adev->sdma.instance[0].ring;
|
||||
break;
|
||||
case KGD_ENGINE_SDMA2:
|
||||
ring = &adev->sdma.instance[1].ring;
|
||||
break;
|
||||
default:
|
||||
pr_err("Invalid engine in IB submission: %d\n", engine);
|
||||
ret = -EINVAL;
|
||||
goto err;
|
||||
}
|
||||
|
||||
ret = amdgpu_job_alloc(adev, 1, &job, NULL);
|
||||
if (ret)
|
||||
goto err;
|
||||
|
||||
ib = &job->ibs[0];
|
||||
memset(ib, 0, sizeof(struct amdgpu_ib));
|
||||
|
||||
ib->gpu_addr = gpu_addr;
|
||||
ib->ptr = ib_cmd;
|
||||
ib->length_dw = ib_len;
|
||||
/* This works for NO_HWS. TODO: need to handle without knowing VMID */
|
||||
job->vmid = vmid;
|
||||
|
||||
ret = amdgpu_ib_schedule(ring, 1, ib, job, &f);
|
||||
if (ret) {
|
||||
DRM_ERROR("amdgpu: failed to schedule IB.\n");
|
||||
goto err_ib_sched;
|
||||
}
|
||||
|
||||
ret = dma_fence_wait(f, false);
|
||||
|
||||
err_ib_sched:
|
||||
dma_fence_put(f);
|
||||
amdgpu_job_free(job);
|
||||
err:
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool amdgpu_amdkfd_is_kfd_vmid(struct amdgpu_device *adev, u32 vmid)
|
||||
{
|
||||
if (adev->kfd) {
|
||||
if ((1 << vmid) & compute_vmid_bitmap)
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
@ -26,15 +26,71 @@
|
||||
#define AMDGPU_AMDKFD_H_INCLUDED
|
||||
|
||||
#include <linux/types.h>
|
||||
#include <linux/mm.h>
|
||||
#include <linux/mmu_context.h>
|
||||
#include <kgd_kfd_interface.h>
|
||||
#include <drm/ttm/ttm_execbuf_util.h>
|
||||
#include "amdgpu_sync.h"
|
||||
#include "amdgpu_vm.h"
|
||||
|
||||
extern const struct kgd2kfd_calls *kgd2kfd;
|
||||
|
||||
struct amdgpu_device;
|
||||
|
||||
struct kfd_bo_va_list {
|
||||
struct list_head bo_list;
|
||||
struct amdgpu_bo_va *bo_va;
|
||||
void *kgd_dev;
|
||||
bool is_mapped;
|
||||
uint64_t va;
|
||||
uint64_t pte_flags;
|
||||
};
|
||||
|
||||
struct kgd_mem {
|
||||
struct mutex lock;
|
||||
struct amdgpu_bo *bo;
|
||||
uint64_t gpu_addr;
|
||||
void *cpu_ptr;
|
||||
struct list_head bo_va_list;
|
||||
/* protected by amdkfd_process_info.lock */
|
||||
struct ttm_validate_buffer validate_list;
|
||||
struct ttm_validate_buffer resv_list;
|
||||
uint32_t domain;
|
||||
unsigned int mapped_to_gpu_memory;
|
||||
uint64_t va;
|
||||
|
||||
uint32_t mapping_flags;
|
||||
|
||||
struct amdkfd_process_info *process_info;
|
||||
|
||||
struct amdgpu_sync sync;
|
||||
|
||||
bool aql_queue;
|
||||
};
|
||||
|
||||
/* KFD Memory Eviction */
|
||||
struct amdgpu_amdkfd_fence {
|
||||
struct dma_fence base;
|
||||
struct mm_struct *mm;
|
||||
spinlock_t lock;
|
||||
char timeline_name[TASK_COMM_LEN];
|
||||
};
|
||||
|
||||
struct amdgpu_amdkfd_fence *amdgpu_amdkfd_fence_create(u64 context,
|
||||
struct mm_struct *mm);
|
||||
bool amdkfd_fence_check_mm(struct dma_fence *f, struct mm_struct *mm);
|
||||
struct amdgpu_amdkfd_fence *to_amdgpu_amdkfd_fence(struct dma_fence *f);
|
||||
|
||||
struct amdkfd_process_info {
|
||||
/* List head of all VMs that belong to a KFD process */
|
||||
struct list_head vm_list_head;
|
||||
/* List head for all KFD BOs that belong to a KFD process. */
|
||||
struct list_head kfd_bo_list;
|
||||
/* Lock to protect kfd_bo_list */
|
||||
struct mutex lock;
|
||||
|
||||
/* Number of VMs */
|
||||
unsigned int n_vms;
|
||||
/* Eviction Fence */
|
||||
struct amdgpu_amdkfd_fence *eviction_fence;
|
||||
};
|
||||
|
||||
int amdgpu_amdkfd_init(void);
|
||||
@ -48,9 +104,15 @@ void amdgpu_amdkfd_device_probe(struct amdgpu_device *adev);
|
||||
void amdgpu_amdkfd_device_init(struct amdgpu_device *adev);
|
||||
void amdgpu_amdkfd_device_fini(struct amdgpu_device *adev);
|
||||
|
||||
int amdgpu_amdkfd_submit_ib(struct kgd_dev *kgd, enum kgd_engine_type engine,
|
||||
uint32_t vmid, uint64_t gpu_addr,
|
||||
uint32_t *ib_cmd, uint32_t ib_len);
|
||||
|
||||
struct kfd2kgd_calls *amdgpu_amdkfd_gfx_7_get_functions(void);
|
||||
struct kfd2kgd_calls *amdgpu_amdkfd_gfx_8_0_get_functions(void);
|
||||
|
||||
bool amdgpu_amdkfd_is_kfd_vmid(struct amdgpu_device *adev, u32 vmid);
|
||||
|
||||
/* Shared API */
|
||||
int alloc_gtt_mem(struct kgd_dev *kgd, size_t size,
|
||||
void **mem_obj, uint64_t *gpu_addr,
|
||||
@ -79,4 +141,36 @@ uint64_t amdgpu_amdkfd_get_vram_usage(struct kgd_dev *kgd);
|
||||
valid; \
|
||||
})
|
||||
|
||||
/* GPUVM API */
|
||||
int amdgpu_amdkfd_gpuvm_create_process_vm(struct kgd_dev *kgd, void **vm,
|
||||
void **process_info,
|
||||
struct dma_fence **ef);
|
||||
int amdgpu_amdkfd_gpuvm_acquire_process_vm(struct kgd_dev *kgd,
|
||||
struct file *filp,
|
||||
void **vm, void **process_info,
|
||||
struct dma_fence **ef);
|
||||
void amdgpu_amdkfd_gpuvm_destroy_cb(struct amdgpu_device *adev,
|
||||
struct amdgpu_vm *vm);
|
||||
void amdgpu_amdkfd_gpuvm_destroy_process_vm(struct kgd_dev *kgd, void *vm);
|
||||
uint32_t amdgpu_amdkfd_gpuvm_get_process_page_dir(void *vm);
|
||||
int amdgpu_amdkfd_gpuvm_alloc_memory_of_gpu(
|
||||
struct kgd_dev *kgd, uint64_t va, uint64_t size,
|
||||
void *vm, struct kgd_mem **mem,
|
||||
uint64_t *offset, uint32_t flags);
|
||||
int amdgpu_amdkfd_gpuvm_free_memory_of_gpu(
|
||||
struct kgd_dev *kgd, struct kgd_mem *mem);
|
||||
int amdgpu_amdkfd_gpuvm_map_memory_to_gpu(
|
||||
struct kgd_dev *kgd, struct kgd_mem *mem, void *vm);
|
||||
int amdgpu_amdkfd_gpuvm_unmap_memory_from_gpu(
|
||||
struct kgd_dev *kgd, struct kgd_mem *mem, void *vm);
|
||||
int amdgpu_amdkfd_gpuvm_sync_memory(
|
||||
struct kgd_dev *kgd, struct kgd_mem *mem, bool intr);
|
||||
int amdgpu_amdkfd_gpuvm_map_gtt_bo_to_kernel(struct kgd_dev *kgd,
|
||||
struct kgd_mem *mem, void **kptr, uint64_t *size);
|
||||
int amdgpu_amdkfd_gpuvm_restore_process_bos(void *process_info,
|
||||
struct dma_fence **ef);
|
||||
|
||||
void amdgpu_amdkfd_gpuvm_init_mem_limits(void);
|
||||
void amdgpu_amdkfd_unreserve_system_memory_limit(struct amdgpu_bo *bo);
|
||||
|
||||
#endif /* AMDGPU_AMDKFD_H_INCLUDED */
|
||||
|
179
drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_fence.c
Normal file
179
drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_fence.c
Normal file
@ -0,0 +1,179 @@
|
||||
/*
|
||||
* Copyright 2016-2018 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 <linux/dma-fence.h>
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/atomic.h>
|
||||
#include <linux/stacktrace.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/sched/mm.h>
|
||||
#include "amdgpu_amdkfd.h"
|
||||
|
||||
static const struct dma_fence_ops amdkfd_fence_ops;
|
||||
static atomic_t fence_seq = ATOMIC_INIT(0);
|
||||
|
||||
/* Eviction Fence
|
||||
* Fence helper functions to deal with KFD memory eviction.
|
||||
* Big Idea - Since KFD submissions are done by user queues, a BO cannot be
|
||||
* evicted unless all the user queues for that process are evicted.
|
||||
*
|
||||
* All the BOs in a process share an eviction fence. When process X wants
|
||||
* to map VRAM memory but TTM can't find enough space, TTM will attempt to
|
||||
* evict BOs from its LRU list. TTM checks if the BO is valuable to evict
|
||||
* by calling ttm_bo_driver->eviction_valuable().
|
||||
*
|
||||
* ttm_bo_driver->eviction_valuable() - will return false if the BO belongs
|
||||
* to process X. Otherwise, it will return true to indicate BO can be
|
||||
* evicted by TTM.
|
||||
*
|
||||
* If ttm_bo_driver->eviction_valuable returns true, then TTM will continue
|
||||
* the evcition process for that BO by calling ttm_bo_evict --> amdgpu_bo_move
|
||||
* --> amdgpu_copy_buffer(). This sets up job in GPU scheduler.
|
||||
*
|
||||
* GPU Scheduler (amd_sched_main) - sets up a cb (fence_add_callback) to
|
||||
* nofity when the BO is free to move. fence_add_callback --> enable_signaling
|
||||
* --> amdgpu_amdkfd_fence.enable_signaling
|
||||
*
|
||||
* amdgpu_amdkfd_fence.enable_signaling - Start a work item that will quiesce
|
||||
* user queues and signal fence. The work item will also start another delayed
|
||||
* work item to restore BOs
|
||||
*/
|
||||
|
||||
struct amdgpu_amdkfd_fence *amdgpu_amdkfd_fence_create(u64 context,
|
||||
struct mm_struct *mm)
|
||||
{
|
||||
struct amdgpu_amdkfd_fence *fence;
|
||||
|
||||
fence = kzalloc(sizeof(*fence), GFP_KERNEL);
|
||||
if (fence == NULL)
|
||||
return NULL;
|
||||
|
||||
/* This reference gets released in amdkfd_fence_release */
|
||||
mmgrab(mm);
|
||||
fence->mm = mm;
|
||||
get_task_comm(fence->timeline_name, current);
|
||||
spin_lock_init(&fence->lock);
|
||||
|
||||
dma_fence_init(&fence->base, &amdkfd_fence_ops, &fence->lock,
|
||||
context, atomic_inc_return(&fence_seq));
|
||||
|
||||
return fence;
|
||||
}
|
||||
|
||||
struct amdgpu_amdkfd_fence *to_amdgpu_amdkfd_fence(struct dma_fence *f)
|
||||
{
|
||||
struct amdgpu_amdkfd_fence *fence;
|
||||
|
||||
if (!f)
|
||||
return NULL;
|
||||
|
||||
fence = container_of(f, struct amdgpu_amdkfd_fence, base);
|
||||
if (fence && f->ops == &amdkfd_fence_ops)
|
||||
return fence;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static const char *amdkfd_fence_get_driver_name(struct dma_fence *f)
|
||||
{
|
||||
return "amdgpu_amdkfd_fence";
|
||||
}
|
||||
|
||||
static const char *amdkfd_fence_get_timeline_name(struct dma_fence *f)
|
||||
{
|
||||
struct amdgpu_amdkfd_fence *fence = to_amdgpu_amdkfd_fence(f);
|
||||
|
||||
return fence->timeline_name;
|
||||
}
|
||||
|
||||
/**
|
||||
* amdkfd_fence_enable_signaling - This gets called when TTM wants to evict
|
||||
* a KFD BO and schedules a job to move the BO.
|
||||
* If fence is already signaled return true.
|
||||
* If fence is not signaled schedule a evict KFD process work item.
|
||||
*/
|
||||
static bool amdkfd_fence_enable_signaling(struct dma_fence *f)
|
||||
{
|
||||
struct amdgpu_amdkfd_fence *fence = to_amdgpu_amdkfd_fence(f);
|
||||
|
||||
if (!fence)
|
||||
return false;
|
||||
|
||||
if (dma_fence_is_signaled(f))
|
||||
return true;
|
||||
|
||||
if (!kgd2kfd->schedule_evict_and_restore_process(fence->mm, f))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* amdkfd_fence_release - callback that fence can be freed
|
||||
*
|
||||
* @fence: fence
|
||||
*
|
||||
* This function is called when the reference count becomes zero.
|
||||
* Drops the mm_struct reference and RCU schedules freeing up the fence.
|
||||
*/
|
||||
static void amdkfd_fence_release(struct dma_fence *f)
|
||||
{
|
||||
struct amdgpu_amdkfd_fence *fence = to_amdgpu_amdkfd_fence(f);
|
||||
|
||||
/* Unconditionally signal the fence. The process is getting
|
||||
* terminated.
|
||||
*/
|
||||
if (WARN_ON(!fence))
|
||||
return; /* Not an amdgpu_amdkfd_fence */
|
||||
|
||||
mmdrop(fence->mm);
|
||||
kfree_rcu(f, rcu);
|
||||
}
|
||||
|
||||
/**
|
||||
* amdkfd_fence_check_mm - Check if @mm is same as that of the fence @f
|
||||
* if same return TRUE else return FALSE.
|
||||
*
|
||||
* @f: [IN] fence
|
||||
* @mm: [IN] mm that needs to be verified
|
||||
*/
|
||||
bool amdkfd_fence_check_mm(struct dma_fence *f, struct mm_struct *mm)
|
||||
{
|
||||
struct amdgpu_amdkfd_fence *fence = to_amdgpu_amdkfd_fence(f);
|
||||
|
||||
if (!fence)
|
||||
return false;
|
||||
else if (fence->mm == mm)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static const struct dma_fence_ops amdkfd_fence_ops = {
|
||||
.get_driver_name = amdkfd_fence_get_driver_name,
|
||||
.get_timeline_name = amdkfd_fence_get_timeline_name,
|
||||
.enable_signaling = amdkfd_fence_enable_signaling,
|
||||
.signaled = NULL,
|
||||
.wait = dma_fence_default_wait,
|
||||
.release = amdkfd_fence_release,
|
||||
};
|
@ -139,11 +139,14 @@ static uint32_t kgd_address_watch_get_offset(struct kgd_dev *kgd,
|
||||
static bool get_atc_vmid_pasid_mapping_valid(struct kgd_dev *kgd, uint8_t vmid);
|
||||
static uint16_t get_atc_vmid_pasid_mapping_pasid(struct kgd_dev *kgd,
|
||||
uint8_t vmid);
|
||||
static void write_vmid_invalidate_request(struct kgd_dev *kgd, uint8_t vmid);
|
||||
|
||||
static uint16_t get_fw_version(struct kgd_dev *kgd, enum kgd_engine_type type);
|
||||
static void set_scratch_backing_va(struct kgd_dev *kgd,
|
||||
uint64_t va, uint32_t vmid);
|
||||
static void set_vm_context_page_table_base(struct kgd_dev *kgd, uint32_t vmid,
|
||||
uint32_t page_table_base);
|
||||
static int invalidate_tlbs(struct kgd_dev *kgd, uint16_t pasid);
|
||||
static int invalidate_tlbs_vmid(struct kgd_dev *kgd, uint16_t vmid);
|
||||
|
||||
/* Because of REG_GET_FIELD() being used, we put this function in the
|
||||
* asic specific file.
|
||||
@ -196,12 +199,26 @@ static const struct kfd2kgd_calls kfd2kgd = {
|
||||
.address_watch_get_offset = kgd_address_watch_get_offset,
|
||||
.get_atc_vmid_pasid_mapping_pasid = get_atc_vmid_pasid_mapping_pasid,
|
||||
.get_atc_vmid_pasid_mapping_valid = get_atc_vmid_pasid_mapping_valid,
|
||||
.write_vmid_invalidate_request = write_vmid_invalidate_request,
|
||||
.get_fw_version = get_fw_version,
|
||||
.set_scratch_backing_va = set_scratch_backing_va,
|
||||
.get_tile_config = get_tile_config,
|
||||
.get_cu_info = get_cu_info,
|
||||
.get_vram_usage = amdgpu_amdkfd_get_vram_usage
|
||||
.get_vram_usage = amdgpu_amdkfd_get_vram_usage,
|
||||
.create_process_vm = amdgpu_amdkfd_gpuvm_create_process_vm,
|
||||
.acquire_process_vm = amdgpu_amdkfd_gpuvm_acquire_process_vm,
|
||||
.destroy_process_vm = amdgpu_amdkfd_gpuvm_destroy_process_vm,
|
||||
.get_process_page_dir = amdgpu_amdkfd_gpuvm_get_process_page_dir,
|
||||
.set_vm_context_page_table_base = set_vm_context_page_table_base,
|
||||
.alloc_memory_of_gpu = amdgpu_amdkfd_gpuvm_alloc_memory_of_gpu,
|
||||
.free_memory_of_gpu = amdgpu_amdkfd_gpuvm_free_memory_of_gpu,
|
||||
.map_memory_to_gpu = amdgpu_amdkfd_gpuvm_map_memory_to_gpu,
|
||||
.unmap_memory_to_gpu = amdgpu_amdkfd_gpuvm_unmap_memory_from_gpu,
|
||||
.sync_memory = amdgpu_amdkfd_gpuvm_sync_memory,
|
||||
.map_gtt_bo_to_kernel = amdgpu_amdkfd_gpuvm_map_gtt_bo_to_kernel,
|
||||
.restore_process_bos = amdgpu_amdkfd_gpuvm_restore_process_bos,
|
||||
.invalidate_tlbs = invalidate_tlbs,
|
||||
.invalidate_tlbs_vmid = invalidate_tlbs_vmid,
|
||||
.submit_ib = amdgpu_amdkfd_submit_ib,
|
||||
};
|
||||
|
||||
struct kfd2kgd_calls *amdgpu_amdkfd_gfx_7_get_functions(void)
|
||||
@ -787,14 +804,7 @@ static uint16_t get_atc_vmid_pasid_mapping_pasid(struct kgd_dev *kgd,
|
||||
struct amdgpu_device *adev = (struct amdgpu_device *) kgd;
|
||||
|
||||
reg = RREG32(mmATC_VMID0_PASID_MAPPING + vmid);
|
||||
return reg & ATC_VMID0_PASID_MAPPING__VALID_MASK;
|
||||
}
|
||||
|
||||
static void write_vmid_invalidate_request(struct kgd_dev *kgd, uint8_t vmid)
|
||||
{
|
||||
struct amdgpu_device *adev = (struct amdgpu_device *) kgd;
|
||||
|
||||
WREG32(mmVM_INVALIDATE_REQUEST, 1 << vmid);
|
||||
return reg & ATC_VMID0_PASID_MAPPING__PASID_MASK;
|
||||
}
|
||||
|
||||
static void set_scratch_backing_va(struct kgd_dev *kgd,
|
||||
@ -812,8 +822,6 @@ static uint16_t get_fw_version(struct kgd_dev *kgd, enum kgd_engine_type type)
|
||||
struct amdgpu_device *adev = (struct amdgpu_device *) kgd;
|
||||
const union amdgpu_firmware_header *hdr;
|
||||
|
||||
BUG_ON(kgd == NULL);
|
||||
|
||||
switch (type) {
|
||||
case KGD_ENGINE_PFP:
|
||||
hdr = (const union amdgpu_firmware_header *)
|
||||
@ -866,3 +874,50 @@ static uint16_t get_fw_version(struct kgd_dev *kgd, enum kgd_engine_type type)
|
||||
return hdr->common.ucode_version;
|
||||
}
|
||||
|
||||
static void set_vm_context_page_table_base(struct kgd_dev *kgd, uint32_t vmid,
|
||||
uint32_t page_table_base)
|
||||
{
|
||||
struct amdgpu_device *adev = get_amdgpu_device(kgd);
|
||||
|
||||
if (!amdgpu_amdkfd_is_kfd_vmid(adev, vmid)) {
|
||||
pr_err("trying to set page table base for wrong VMID\n");
|
||||
return;
|
||||
}
|
||||
WREG32(mmVM_CONTEXT8_PAGE_TABLE_BASE_ADDR + vmid - 8, page_table_base);
|
||||
}
|
||||
|
||||
static int invalidate_tlbs(struct kgd_dev *kgd, uint16_t pasid)
|
||||
{
|
||||
struct amdgpu_device *adev = (struct amdgpu_device *) kgd;
|
||||
int vmid;
|
||||
unsigned int tmp;
|
||||
|
||||
for (vmid = 0; vmid < 16; vmid++) {
|
||||
if (!amdgpu_amdkfd_is_kfd_vmid(adev, vmid))
|
||||
continue;
|
||||
|
||||
tmp = RREG32(mmATC_VMID0_PASID_MAPPING + vmid);
|
||||
if ((tmp & ATC_VMID0_PASID_MAPPING__VALID_MASK) &&
|
||||
(tmp & ATC_VMID0_PASID_MAPPING__PASID_MASK) == pasid) {
|
||||
WREG32(mmVM_INVALIDATE_REQUEST, 1 << vmid);
|
||||
RREG32(mmVM_INVALIDATE_RESPONSE);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int invalidate_tlbs_vmid(struct kgd_dev *kgd, uint16_t vmid)
|
||||
{
|
||||
struct amdgpu_device *adev = (struct amdgpu_device *) kgd;
|
||||
|
||||
if (!amdgpu_amdkfd_is_kfd_vmid(adev, vmid)) {
|
||||
pr_err("non kfd vmid\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
WREG32(mmVM_INVALIDATE_REQUEST, 1 << vmid);
|
||||
RREG32(mmVM_INVALIDATE_RESPONSE);
|
||||
return 0;
|
||||
}
|
||||
|
@ -81,7 +81,6 @@ static int kgd_hqd_destroy(struct kgd_dev *kgd, void *mqd,
|
||||
uint32_t queue_id);
|
||||
static int kgd_hqd_sdma_destroy(struct kgd_dev *kgd, void *mqd,
|
||||
unsigned int utimeout);
|
||||
static void write_vmid_invalidate_request(struct kgd_dev *kgd, uint8_t vmid);
|
||||
static int kgd_address_watch_disable(struct kgd_dev *kgd);
|
||||
static int kgd_address_watch_execute(struct kgd_dev *kgd,
|
||||
unsigned int watch_point_id,
|
||||
@ -99,10 +98,13 @@ static bool get_atc_vmid_pasid_mapping_valid(struct kgd_dev *kgd,
|
||||
uint8_t vmid);
|
||||
static uint16_t get_atc_vmid_pasid_mapping_pasid(struct kgd_dev *kgd,
|
||||
uint8_t vmid);
|
||||
static void write_vmid_invalidate_request(struct kgd_dev *kgd, uint8_t vmid);
|
||||
static uint16_t get_fw_version(struct kgd_dev *kgd, enum kgd_engine_type type);
|
||||
static void set_scratch_backing_va(struct kgd_dev *kgd,
|
||||
uint64_t va, uint32_t vmid);
|
||||
static void set_vm_context_page_table_base(struct kgd_dev *kgd, uint32_t vmid,
|
||||
uint32_t page_table_base);
|
||||
static int invalidate_tlbs(struct kgd_dev *kgd, uint16_t pasid);
|
||||
static int invalidate_tlbs_vmid(struct kgd_dev *kgd, uint16_t vmid);
|
||||
|
||||
/* Because of REG_GET_FIELD() being used, we put this function in the
|
||||
* asic specific file.
|
||||
@ -157,12 +159,26 @@ static const struct kfd2kgd_calls kfd2kgd = {
|
||||
get_atc_vmid_pasid_mapping_pasid,
|
||||
.get_atc_vmid_pasid_mapping_valid =
|
||||
get_atc_vmid_pasid_mapping_valid,
|
||||
.write_vmid_invalidate_request = write_vmid_invalidate_request,
|
||||
.get_fw_version = get_fw_version,
|
||||
.set_scratch_backing_va = set_scratch_backing_va,
|
||||
.get_tile_config = get_tile_config,
|
||||
.get_cu_info = get_cu_info,
|
||||
.get_vram_usage = amdgpu_amdkfd_get_vram_usage
|
||||
.get_vram_usage = amdgpu_amdkfd_get_vram_usage,
|
||||
.create_process_vm = amdgpu_amdkfd_gpuvm_create_process_vm,
|
||||
.acquire_process_vm = amdgpu_amdkfd_gpuvm_acquire_process_vm,
|
||||
.destroy_process_vm = amdgpu_amdkfd_gpuvm_destroy_process_vm,
|
||||
.get_process_page_dir = amdgpu_amdkfd_gpuvm_get_process_page_dir,
|
||||
.set_vm_context_page_table_base = set_vm_context_page_table_base,
|
||||
.alloc_memory_of_gpu = amdgpu_amdkfd_gpuvm_alloc_memory_of_gpu,
|
||||
.free_memory_of_gpu = amdgpu_amdkfd_gpuvm_free_memory_of_gpu,
|
||||
.map_memory_to_gpu = amdgpu_amdkfd_gpuvm_map_memory_to_gpu,
|
||||
.unmap_memory_to_gpu = amdgpu_amdkfd_gpuvm_unmap_memory_from_gpu,
|
||||
.sync_memory = amdgpu_amdkfd_gpuvm_sync_memory,
|
||||
.map_gtt_bo_to_kernel = amdgpu_amdkfd_gpuvm_map_gtt_bo_to_kernel,
|
||||
.restore_process_bos = amdgpu_amdkfd_gpuvm_restore_process_bos,
|
||||
.invalidate_tlbs = invalidate_tlbs,
|
||||
.invalidate_tlbs_vmid = invalidate_tlbs_vmid,
|
||||
.submit_ib = amdgpu_amdkfd_submit_ib,
|
||||
};
|
||||
|
||||
struct kfd2kgd_calls *amdgpu_amdkfd_gfx_8_0_get_functions(void)
|
||||
@ -704,14 +720,7 @@ static uint16_t get_atc_vmid_pasid_mapping_pasid(struct kgd_dev *kgd,
|
||||
struct amdgpu_device *adev = (struct amdgpu_device *) kgd;
|
||||
|
||||
reg = RREG32(mmATC_VMID0_PASID_MAPPING + vmid);
|
||||
return reg & ATC_VMID0_PASID_MAPPING__VALID_MASK;
|
||||
}
|
||||
|
||||
static void write_vmid_invalidate_request(struct kgd_dev *kgd, uint8_t vmid)
|
||||
{
|
||||
struct amdgpu_device *adev = (struct amdgpu_device *) kgd;
|
||||
|
||||
WREG32(mmVM_INVALIDATE_REQUEST, 1 << vmid);
|
||||
return reg & ATC_VMID0_PASID_MAPPING__PASID_MASK;
|
||||
}
|
||||
|
||||
static int kgd_address_watch_disable(struct kgd_dev *kgd)
|
||||
@ -775,8 +784,6 @@ static uint16_t get_fw_version(struct kgd_dev *kgd, enum kgd_engine_type type)
|
||||
struct amdgpu_device *adev = (struct amdgpu_device *) kgd;
|
||||
const union amdgpu_firmware_header *hdr;
|
||||
|
||||
BUG_ON(kgd == NULL);
|
||||
|
||||
switch (type) {
|
||||
case KGD_ENGINE_PFP:
|
||||
hdr = (const union amdgpu_firmware_header *)
|
||||
@ -828,3 +835,51 @@ static uint16_t get_fw_version(struct kgd_dev *kgd, enum kgd_engine_type type)
|
||||
/* Only 12 bit in use*/
|
||||
return hdr->common.ucode_version;
|
||||
}
|
||||
|
||||
static void set_vm_context_page_table_base(struct kgd_dev *kgd, uint32_t vmid,
|
||||
uint32_t page_table_base)
|
||||
{
|
||||
struct amdgpu_device *adev = get_amdgpu_device(kgd);
|
||||
|
||||
if (!amdgpu_amdkfd_is_kfd_vmid(adev, vmid)) {
|
||||
pr_err("trying to set page table base for wrong VMID\n");
|
||||
return;
|
||||
}
|
||||
WREG32(mmVM_CONTEXT8_PAGE_TABLE_BASE_ADDR + vmid - 8, page_table_base);
|
||||
}
|
||||
|
||||
static int invalidate_tlbs(struct kgd_dev *kgd, uint16_t pasid)
|
||||
{
|
||||
struct amdgpu_device *adev = (struct amdgpu_device *) kgd;
|
||||
int vmid;
|
||||
unsigned int tmp;
|
||||
|
||||
for (vmid = 0; vmid < 16; vmid++) {
|
||||
if (!amdgpu_amdkfd_is_kfd_vmid(adev, vmid))
|
||||
continue;
|
||||
|
||||
tmp = RREG32(mmATC_VMID0_PASID_MAPPING + vmid);
|
||||
if ((tmp & ATC_VMID0_PASID_MAPPING__VALID_MASK) &&
|
||||
(tmp & ATC_VMID0_PASID_MAPPING__PASID_MASK) == pasid) {
|
||||
WREG32(mmVM_INVALIDATE_REQUEST, 1 << vmid);
|
||||
RREG32(mmVM_INVALIDATE_RESPONSE);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int invalidate_tlbs_vmid(struct kgd_dev *kgd, uint16_t vmid)
|
||||
{
|
||||
struct amdgpu_device *adev = (struct amdgpu_device *) kgd;
|
||||
|
||||
if (!amdgpu_amdkfd_is_kfd_vmid(adev, vmid)) {
|
||||
pr_err("non kfd vmid %d\n", vmid);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
WREG32(mmVM_INVALIDATE_REQUEST, 1 << vmid);
|
||||
RREG32(mmVM_INVALIDATE_RESPONSE);
|
||||
return 0;
|
||||
}
|
||||
|
1577
drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c
Normal file
1577
drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c
Normal file
File diff suppressed because it is too large
Load Diff
@ -114,6 +114,9 @@ union igp_info {
|
||||
struct atom_integrated_system_info_v1_11 v11;
|
||||
};
|
||||
|
||||
union umc_info {
|
||||
struct atom_umc_info_v3_1 v31;
|
||||
};
|
||||
/*
|
||||
* Return vram width from integrated system info table, if available,
|
||||
* or 0 if not.
|
||||
@ -143,6 +146,94 @@ int amdgpu_atomfirmware_get_vram_width(struct amdgpu_device *adev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int convert_atom_mem_type_to_vram_type (struct amdgpu_device *adev,
|
||||
int atom_mem_type)
|
||||
{
|
||||
int vram_type;
|
||||
|
||||
if (adev->flags & AMD_IS_APU) {
|
||||
switch (atom_mem_type) {
|
||||
case Ddr2MemType:
|
||||
case LpDdr2MemType:
|
||||
vram_type = AMDGPU_VRAM_TYPE_DDR2;
|
||||
break;
|
||||
case Ddr3MemType:
|
||||
case LpDdr3MemType:
|
||||
vram_type = AMDGPU_VRAM_TYPE_DDR3;
|
||||
break;
|
||||
case Ddr4MemType:
|
||||
case LpDdr4MemType:
|
||||
vram_type = AMDGPU_VRAM_TYPE_DDR4;
|
||||
break;
|
||||
default:
|
||||
vram_type = AMDGPU_VRAM_TYPE_UNKNOWN;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
switch (atom_mem_type) {
|
||||
case ATOM_DGPU_VRAM_TYPE_GDDR5:
|
||||
vram_type = AMDGPU_VRAM_TYPE_GDDR5;
|
||||
break;
|
||||
case ATOM_DGPU_VRAM_TYPE_HBM:
|
||||
vram_type = AMDGPU_VRAM_TYPE_HBM;
|
||||
break;
|
||||
default:
|
||||
vram_type = AMDGPU_VRAM_TYPE_UNKNOWN;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return vram_type;
|
||||
}
|
||||
/*
|
||||
* Return vram type from either integrated system info table
|
||||
* or umc info table, if available, or 0 (TYPE_UNKNOWN) if not
|
||||
*/
|
||||
int amdgpu_atomfirmware_get_vram_type(struct amdgpu_device *adev)
|
||||
{
|
||||
struct amdgpu_mode_info *mode_info = &adev->mode_info;
|
||||
int index;
|
||||
u16 data_offset, size;
|
||||
union igp_info *igp_info;
|
||||
union umc_info *umc_info;
|
||||
u8 frev, crev;
|
||||
u8 mem_type;
|
||||
|
||||
if (adev->flags & AMD_IS_APU)
|
||||
index = get_index_into_master_table(atom_master_list_of_data_tables_v2_1,
|
||||
integratedsysteminfo);
|
||||
else
|
||||
index = get_index_into_master_table(atom_master_list_of_data_tables_v2_1,
|
||||
umc_info);
|
||||
if (amdgpu_atom_parse_data_header(mode_info->atom_context,
|
||||
index, &size,
|
||||
&frev, &crev, &data_offset)) {
|
||||
if (adev->flags & AMD_IS_APU) {
|
||||
igp_info = (union igp_info *)
|
||||
(mode_info->atom_context->bios + data_offset);
|
||||
switch (crev) {
|
||||
case 11:
|
||||
mem_type = igp_info->v11.memorytype;
|
||||
return convert_atom_mem_type_to_vram_type(adev, mem_type);
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
umc_info = (union umc_info *)
|
||||
(mode_info->atom_context->bios + data_offset);
|
||||
switch (crev) {
|
||||
case 1:
|
||||
mem_type = umc_info->v31.vram_type;
|
||||
return convert_atom_mem_type_to_vram_type(adev, mem_type);
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
union firmware_info {
|
||||
struct atom_firmware_info_v3_1 v31;
|
||||
};
|
||||
@ -151,10 +242,6 @@ union smu_info {
|
||||
struct atom_smu_info_v3_1 v31;
|
||||
};
|
||||
|
||||
union umc_info {
|
||||
struct atom_umc_info_v3_1 v31;
|
||||
};
|
||||
|
||||
int amdgpu_atomfirmware_get_clock_info(struct amdgpu_device *adev)
|
||||
{
|
||||
struct amdgpu_mode_info *mode_info = &adev->mode_info;
|
||||
|
@ -28,6 +28,7 @@ bool amdgpu_atomfirmware_gpu_supports_virtualization(struct amdgpu_device *adev)
|
||||
void amdgpu_atomfirmware_scratch_regs_init(struct amdgpu_device *adev);
|
||||
int amdgpu_atomfirmware_allocate_fb_scratch(struct amdgpu_device *adev);
|
||||
int amdgpu_atomfirmware_get_vram_width(struct amdgpu_device *adev);
|
||||
int amdgpu_atomfirmware_get_vram_type(struct amdgpu_device *adev);
|
||||
int amdgpu_atomfirmware_get_clock_info(struct amdgpu_device *adev);
|
||||
|
||||
#endif
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user