mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git
synced 2025-01-07 14:32:23 +00:00
More ACPI updates for 5.15-rc1
- Add ACPI support to the PCI VMD driver (Rafael Wysocki). - Rearrange suspend-to-idle support code to reflect the platform firmware expectations on some AMD platforms (Mario Limonciello). - Make SSDT overlays documentation follow the code documented by it more closely (Andy Shevchenko). -----BEGIN PGP SIGNATURE----- iQJGBAABCAAwFiEE4fcc61cGeeHD/fCwgsRv/nhiVHEFAmE41EgSHHJqd0Byand5 c29ja2kubmV0AAoJEILEb/54YlRxZrgP/iStcM1PdEkzW9KInTbI7MDiQl8Iaem2 4AcbrsQmJxAEfJ+kzUuoArjj+y4T8sf49AA9Akg/q3zwf0oBix8JdtPDEx823oG8 7/0zjPJMigmcmGfGIlnQaSYqE30hatsthqF0iyH9AZjRzM1m9MavAtxrwDOD0Chq m6kMObNorm/C0mjdPy71DAbiPbrcsMTFjw27hXHWnfsQFhZeVAoyhh2aFvk790pG QRxpArI8r3dLb9vORQWo0q4jezPrRU6HzfvULVZEtv5+F8VUAby+qi1oGUSNx6CX OB20Z1MFPSolsJvyRkfE8HEq0x1Es37doBROolhmliaKUQezwKPMZKJGgEYyUaSJ bnWmN2wuE39VB6rIWXIaw6bHX3RwWnUJgoMvTZZIexp4kmmy9nsPB119na2odFVW D06yMPZwx9lCDVWNkIbpcCGHkBWvQSZ+X/tROVOgyutJ2Rgph0PTVxQxVZmTnTWm Pq6Tp8lSeatL16vEY75EX5pXbmKiGDIFrGv28Jxou2Arf31hcagY+rxu6YYORefu NdkC2GD4TlQMGm2Ukfo5D/svFzJ/MQvP75ytVP3Oqi7ZFLkU2RzYOun8oOcZjUk6 76CH5/fmSvV2NbZRCDzhxiDXVhBFPaGm0KFnYYKs1V7AskdhnzOkd03z2bseTC0V XNk0fHL1R38J =8lPe -----END PGP SIGNATURE----- Merge tag 'acpi-5.15-rc1-2' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm Pull more ACPI updates from Rafael Wysocki: "These add ACPI support to the PCI VMD driver, improve suspend-to-idle support for AMD platforms and update documentation. Specifics: - Add ACPI support to the PCI VMD driver (Rafael Wysocki) - Rearrange suspend-to-idle support code to reflect the platform firmware expectations on some AMD platforms (Mario Limonciello) - Make SSDT overlays documentation follow the code documented by it more closely (Andy Shevchenko)" * tag 'acpi-5.15-rc1-2' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm: ACPI: PM: s2idle: Run both AMD and Microsoft methods if both are supported Documentation: ACPI: Align the SSDT overlays file with the code PCI: VMD: ACPI: Make ACPI companion lookup work for VMD bus
This commit is contained in:
commit
9c566611ac
@ -30,22 +30,21 @@ following ASL code can be used::
|
||||
{
|
||||
Device (STAC)
|
||||
{
|
||||
Name (_ADR, Zero)
|
||||
Name (_HID, "BMA222E")
|
||||
Name (RBUF, ResourceTemplate ()
|
||||
{
|
||||
I2cSerialBus (0x0018, ControllerInitiated, 0x00061A80,
|
||||
AddressingMode7Bit, "\\_SB.I2C6", 0x00,
|
||||
ResourceConsumer, ,)
|
||||
GpioInt (Edge, ActiveHigh, Exclusive, PullDown, 0x0000,
|
||||
"\\_SB.GPO2", 0x00, ResourceConsumer, , )
|
||||
{ // Pin list
|
||||
0
|
||||
}
|
||||
})
|
||||
|
||||
Method (_CRS, 0, Serialized)
|
||||
{
|
||||
Name (RBUF, ResourceTemplate ()
|
||||
{
|
||||
I2cSerialBus (0x0018, ControllerInitiated, 0x00061A80,
|
||||
AddressingMode7Bit, "\\_SB.I2C6", 0x00,
|
||||
ResourceConsumer, ,)
|
||||
GpioInt (Edge, ActiveHigh, Exclusive, PullDown, 0x0000,
|
||||
"\\_SB.GPO2", 0x00, ResourceConsumer, , )
|
||||
{ // Pin list
|
||||
0
|
||||
}
|
||||
})
|
||||
Return (RBUF)
|
||||
}
|
||||
}
|
||||
@ -75,7 +74,7 @@ This option allows loading of user defined SSDTs from initrd and it is useful
|
||||
when the system does not support EFI or when there is not enough EFI storage.
|
||||
|
||||
It works in a similar way with initrd based ACPI tables override/upgrade: SSDT
|
||||
aml code must be placed in the first, uncompressed, initrd under the
|
||||
AML code must be placed in the first, uncompressed, initrd under the
|
||||
"kernel/firmware/acpi" path. Multiple files can be used and this will translate
|
||||
in loading multiple tables. Only SSDT and OEM tables are allowed. See
|
||||
initrd_table_override.txt for more details.
|
||||
@ -103,12 +102,14 @@ This is the preferred method, when EFI is supported on the platform, because it
|
||||
allows a persistent, OS independent way of storing the user defined SSDTs. There
|
||||
is also work underway to implement EFI support for loading user defined SSDTs
|
||||
and using this method will make it easier to convert to the EFI loading
|
||||
mechanism when that will arrive.
|
||||
mechanism when that will arrive. To enable it, the
|
||||
CONFIG_EFI_CUSTOM_SSDT_OVERLAYS shoyld be chosen to y.
|
||||
|
||||
In order to load SSDTs from an EFI variable the efivar_ssdt kernel command line
|
||||
parameter can be used. The argument for the option is the variable name to
|
||||
use. If there are multiple variables with the same name but with different
|
||||
vendor GUIDs, all of them will be loaded.
|
||||
In order to load SSDTs from an EFI variable the ``"efivar_ssdt=..."`` kernel
|
||||
command line parameter can be used (the name has a limitation of 16 characters).
|
||||
The argument for the option is the variable name to use. If there are multiple
|
||||
variables with the same name but with different vendor GUIDs, all of them will
|
||||
be loaded.
|
||||
|
||||
In order to store the AML code in an EFI variable the efivarfs filesystem can be
|
||||
used. It is enabled and mounted by default in /sys/firmware/efi/efivars in all
|
||||
@ -127,7 +128,7 @@ variable with the content from a given file::
|
||||
|
||||
#!/bin/sh -e
|
||||
|
||||
while ! [ -z "$1" ]; do
|
||||
while [ -n "$1" ]; do
|
||||
case "$1" in
|
||||
"-f") filename="$2"; shift;;
|
||||
"-g") guid="$2"; shift;;
|
||||
@ -167,14 +168,14 @@ variable with the content from a given file::
|
||||
Loading ACPI SSDTs from configfs
|
||||
================================
|
||||
|
||||
This option allows loading of user defined SSDTs from userspace via the configfs
|
||||
This option allows loading of user defined SSDTs from user space via the configfs
|
||||
interface. The CONFIG_ACPI_CONFIGFS option must be select and configfs must be
|
||||
mounted. In the following examples, we assume that configfs has been mounted in
|
||||
/config.
|
||||
/sys/kernel/config.
|
||||
|
||||
New tables can be loading by creating new directories in /config/acpi/table/ and
|
||||
writing the SSDT aml code in the aml attribute::
|
||||
New tables can be loading by creating new directories in /sys/kernel/config/acpi/table
|
||||
and writing the SSDT AML code in the aml attribute::
|
||||
|
||||
cd /config/acpi/table
|
||||
cd /sys/kernel/config/acpi/table
|
||||
mkdir my_ssdt
|
||||
cat ~/ssdt.aml > my_ssdt/aml
|
||||
|
@ -449,25 +449,30 @@ int acpi_s2idle_prepare_late(void)
|
||||
if (pm_debug_messages_on)
|
||||
lpi_check_constraints();
|
||||
|
||||
if (lps0_dsm_func_mask_microsoft > 0) {
|
||||
/* Screen off */
|
||||
if (lps0_dsm_func_mask > 0)
|
||||
acpi_sleep_run_lps0_dsm(acpi_s2idle_vendor_amd() ?
|
||||
ACPI_LPS0_SCREEN_OFF_AMD :
|
||||
ACPI_LPS0_SCREEN_OFF,
|
||||
lps0_dsm_func_mask, lps0_dsm_guid);
|
||||
|
||||
if (lps0_dsm_func_mask_microsoft > 0)
|
||||
acpi_sleep_run_lps0_dsm(ACPI_LPS0_SCREEN_OFF,
|
||||
lps0_dsm_func_mask_microsoft, lps0_dsm_guid_microsoft);
|
||||
|
||||
/* LPS0 entry */
|
||||
if (lps0_dsm_func_mask > 0)
|
||||
acpi_sleep_run_lps0_dsm(acpi_s2idle_vendor_amd() ?
|
||||
ACPI_LPS0_ENTRY_AMD :
|
||||
ACPI_LPS0_ENTRY,
|
||||
lps0_dsm_func_mask, lps0_dsm_guid);
|
||||
if (lps0_dsm_func_mask_microsoft > 0) {
|
||||
acpi_sleep_run_lps0_dsm(ACPI_LPS0_ENTRY,
|
||||
lps0_dsm_func_mask_microsoft, lps0_dsm_guid_microsoft);
|
||||
/* modern standby entry */
|
||||
acpi_sleep_run_lps0_dsm(ACPI_LPS0_MS_ENTRY,
|
||||
lps0_dsm_func_mask_microsoft, lps0_dsm_guid_microsoft);
|
||||
acpi_sleep_run_lps0_dsm(ACPI_LPS0_ENTRY,
|
||||
lps0_dsm_func_mask_microsoft, lps0_dsm_guid_microsoft);
|
||||
} else if (acpi_s2idle_vendor_amd()) {
|
||||
acpi_sleep_run_lps0_dsm(ACPI_LPS0_SCREEN_OFF_AMD,
|
||||
lps0_dsm_func_mask, lps0_dsm_guid);
|
||||
acpi_sleep_run_lps0_dsm(ACPI_LPS0_ENTRY_AMD,
|
||||
lps0_dsm_func_mask, lps0_dsm_guid);
|
||||
} else {
|
||||
acpi_sleep_run_lps0_dsm(ACPI_LPS0_SCREEN_OFF,
|
||||
lps0_dsm_func_mask, lps0_dsm_guid);
|
||||
acpi_sleep_run_lps0_dsm(ACPI_LPS0_ENTRY,
|
||||
lps0_dsm_func_mask, lps0_dsm_guid);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -476,24 +481,30 @@ void acpi_s2idle_restore_early(void)
|
||||
if (!lps0_device_handle || sleep_no_lps0)
|
||||
return;
|
||||
|
||||
if (lps0_dsm_func_mask_microsoft > 0) {
|
||||
acpi_sleep_run_lps0_dsm(ACPI_LPS0_EXIT,
|
||||
lps0_dsm_func_mask_microsoft, lps0_dsm_guid_microsoft);
|
||||
/* Modern standby exit */
|
||||
if (lps0_dsm_func_mask_microsoft > 0)
|
||||
acpi_sleep_run_lps0_dsm(ACPI_LPS0_MS_EXIT,
|
||||
lps0_dsm_func_mask_microsoft, lps0_dsm_guid_microsoft);
|
||||
|
||||
/* LPS0 exit */
|
||||
if (lps0_dsm_func_mask > 0)
|
||||
acpi_sleep_run_lps0_dsm(acpi_s2idle_vendor_amd() ?
|
||||
ACPI_LPS0_EXIT_AMD :
|
||||
ACPI_LPS0_EXIT,
|
||||
lps0_dsm_func_mask, lps0_dsm_guid);
|
||||
if (lps0_dsm_func_mask_microsoft > 0)
|
||||
acpi_sleep_run_lps0_dsm(ACPI_LPS0_EXIT,
|
||||
lps0_dsm_func_mask_microsoft, lps0_dsm_guid_microsoft);
|
||||
|
||||
/* Screen on */
|
||||
if (lps0_dsm_func_mask_microsoft > 0)
|
||||
acpi_sleep_run_lps0_dsm(ACPI_LPS0_SCREEN_ON,
|
||||
lps0_dsm_func_mask_microsoft, lps0_dsm_guid_microsoft);
|
||||
} else if (acpi_s2idle_vendor_amd()) {
|
||||
acpi_sleep_run_lps0_dsm(ACPI_LPS0_EXIT_AMD,
|
||||
lps0_dsm_func_mask, lps0_dsm_guid);
|
||||
acpi_sleep_run_lps0_dsm(ACPI_LPS0_SCREEN_ON_AMD,
|
||||
lps0_dsm_func_mask, lps0_dsm_guid);
|
||||
} else {
|
||||
acpi_sleep_run_lps0_dsm(ACPI_LPS0_EXIT,
|
||||
lps0_dsm_func_mask, lps0_dsm_guid);
|
||||
acpi_sleep_run_lps0_dsm(ACPI_LPS0_SCREEN_ON,
|
||||
lps0_dsm_func_mask, lps0_dsm_guid);
|
||||
}
|
||||
if (lps0_dsm_func_mask > 0)
|
||||
acpi_sleep_run_lps0_dsm(acpi_s2idle_vendor_amd() ?
|
||||
ACPI_LPS0_SCREEN_ON_AMD :
|
||||
ACPI_LPS0_SCREEN_ON,
|
||||
lps0_dsm_func_mask, lps0_dsm_guid);
|
||||
}
|
||||
|
||||
static const struct platform_s2idle_ops acpi_s2idle_ops_lps0 = {
|
||||
|
@ -11,6 +11,7 @@
|
||||
#include <linux/module.h>
|
||||
#include <linux/msi.h>
|
||||
#include <linux/pci.h>
|
||||
#include <linux/pci-acpi.h>
|
||||
#include <linux/pci-ecam.h>
|
||||
#include <linux/srcu.h>
|
||||
#include <linux/rculist.h>
|
||||
@ -447,6 +448,56 @@ static struct pci_ops vmd_ops = {
|
||||
.write = vmd_pci_write,
|
||||
};
|
||||
|
||||
#ifdef CONFIG_ACPI
|
||||
static struct acpi_device *vmd_acpi_find_companion(struct pci_dev *pci_dev)
|
||||
{
|
||||
struct pci_host_bridge *bridge;
|
||||
u32 busnr, addr;
|
||||
|
||||
if (pci_dev->bus->ops != &vmd_ops)
|
||||
return NULL;
|
||||
|
||||
bridge = pci_find_host_bridge(pci_dev->bus);
|
||||
busnr = pci_dev->bus->number - bridge->bus->number;
|
||||
/*
|
||||
* The address computation below is only applicable to relative bus
|
||||
* numbers below 32.
|
||||
*/
|
||||
if (busnr > 31)
|
||||
return NULL;
|
||||
|
||||
addr = (busnr << 24) | ((u32)pci_dev->devfn << 16) | 0x8000FFFFU;
|
||||
|
||||
dev_dbg(&pci_dev->dev, "Looking for ACPI companion (address 0x%x)\n",
|
||||
addr);
|
||||
|
||||
return acpi_find_child_device(ACPI_COMPANION(bridge->dev.parent), addr,
|
||||
false);
|
||||
}
|
||||
|
||||
static bool hook_installed;
|
||||
|
||||
static void vmd_acpi_begin(void)
|
||||
{
|
||||
if (pci_acpi_set_companion_lookup_hook(vmd_acpi_find_companion))
|
||||
return;
|
||||
|
||||
hook_installed = true;
|
||||
}
|
||||
|
||||
static void vmd_acpi_end(void)
|
||||
{
|
||||
if (!hook_installed)
|
||||
return;
|
||||
|
||||
pci_acpi_clear_companion_lookup_hook();
|
||||
hook_installed = false;
|
||||
}
|
||||
#else
|
||||
static inline void vmd_acpi_begin(void) { }
|
||||
static inline void vmd_acpi_end(void) { }
|
||||
#endif /* CONFIG_ACPI */
|
||||
|
||||
static void vmd_attach_resources(struct vmd_dev *vmd)
|
||||
{
|
||||
vmd->dev->resource[VMD_MEMBAR1].child = &vmd->resources[1];
|
||||
@ -747,6 +798,8 @@ static int vmd_enable_domain(struct vmd_dev *vmd, unsigned long features)
|
||||
if (vmd->irq_domain)
|
||||
dev_set_msi_domain(&vmd->bus->dev, vmd->irq_domain);
|
||||
|
||||
vmd_acpi_begin();
|
||||
|
||||
pci_scan_child_bus(vmd->bus);
|
||||
pci_assign_unassigned_bus_resources(vmd->bus);
|
||||
|
||||
@ -760,6 +813,8 @@ static int vmd_enable_domain(struct vmd_dev *vmd, unsigned long features)
|
||||
|
||||
pci_bus_add_devices(vmd->bus);
|
||||
|
||||
vmd_acpi_end();
|
||||
|
||||
WARN(sysfs_create_link(&vmd->dev->dev.kobj, &vmd->bus->dev.kobj,
|
||||
"domain"), "Can't create symlink to domain\n");
|
||||
return 0;
|
||||
|
@ -23,6 +23,7 @@ struct pci_host_bridge *pci_find_host_bridge(struct pci_bus *bus)
|
||||
|
||||
return to_pci_host_bridge(root_bus->bridge);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(pci_find_host_bridge);
|
||||
|
||||
struct device *pci_get_host_bridge_device(struct pci_dev *dev)
|
||||
{
|
||||
|
@ -17,6 +17,7 @@
|
||||
#include <linux/pci-acpi.h>
|
||||
#include <linux/pm_runtime.h>
|
||||
#include <linux/pm_qos.h>
|
||||
#include <linux/rwsem.h>
|
||||
#include "pci.h"
|
||||
|
||||
/*
|
||||
@ -1178,6 +1179,69 @@ void acpi_pci_remove_bus(struct pci_bus *bus)
|
||||
}
|
||||
|
||||
/* ACPI bus type */
|
||||
|
||||
|
||||
static DECLARE_RWSEM(pci_acpi_companion_lookup_sem);
|
||||
static struct acpi_device *(*pci_acpi_find_companion_hook)(struct pci_dev *);
|
||||
|
||||
/**
|
||||
* pci_acpi_set_companion_lookup_hook - Set ACPI companion lookup callback.
|
||||
* @func: ACPI companion lookup callback pointer or NULL.
|
||||
*
|
||||
* Set a special ACPI companion lookup callback for PCI devices whose companion
|
||||
* objects in the ACPI namespace have _ADR with non-standard bus-device-function
|
||||
* encodings.
|
||||
*
|
||||
* Return 0 on success or a negative error code on failure (in which case no
|
||||
* changes are made).
|
||||
*
|
||||
* The caller is responsible for the appropriate ordering of the invocations of
|
||||
* this function with respect to the enumeration of the PCI devices needing the
|
||||
* callback installed by it.
|
||||
*/
|
||||
int pci_acpi_set_companion_lookup_hook(struct acpi_device *(*func)(struct pci_dev *))
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (!func)
|
||||
return -EINVAL;
|
||||
|
||||
down_write(&pci_acpi_companion_lookup_sem);
|
||||
|
||||
if (pci_acpi_find_companion_hook) {
|
||||
ret = -EBUSY;
|
||||
} else {
|
||||
pci_acpi_find_companion_hook = func;
|
||||
ret = 0;
|
||||
}
|
||||
|
||||
up_write(&pci_acpi_companion_lookup_sem);
|
||||
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(pci_acpi_set_companion_lookup_hook);
|
||||
|
||||
/**
|
||||
* pci_acpi_clear_companion_lookup_hook - Clear ACPI companion lookup callback.
|
||||
*
|
||||
* Clear the special ACPI companion lookup callback previously set by
|
||||
* pci_acpi_set_companion_lookup_hook(). Block until the last running instance
|
||||
* of the callback returns before clearing it.
|
||||
*
|
||||
* The caller is responsible for the appropriate ordering of the invocations of
|
||||
* this function with respect to the enumeration of the PCI devices needing the
|
||||
* callback cleared by it.
|
||||
*/
|
||||
void pci_acpi_clear_companion_lookup_hook(void)
|
||||
{
|
||||
down_write(&pci_acpi_companion_lookup_sem);
|
||||
|
||||
pci_acpi_find_companion_hook = NULL;
|
||||
|
||||
up_write(&pci_acpi_companion_lookup_sem);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(pci_acpi_clear_companion_lookup_hook);
|
||||
|
||||
static struct acpi_device *acpi_pci_find_companion(struct device *dev)
|
||||
{
|
||||
struct pci_dev *pci_dev = to_pci_dev(dev);
|
||||
@ -1185,6 +1249,16 @@ static struct acpi_device *acpi_pci_find_companion(struct device *dev)
|
||||
bool check_children;
|
||||
u64 addr;
|
||||
|
||||
down_read(&pci_acpi_companion_lookup_sem);
|
||||
|
||||
adev = pci_acpi_find_companion_hook ?
|
||||
pci_acpi_find_companion_hook(pci_dev) : NULL;
|
||||
|
||||
up_read(&pci_acpi_companion_lookup_sem);
|
||||
|
||||
if (adev)
|
||||
return adev;
|
||||
|
||||
check_children = pci_is_bridge(pci_dev);
|
||||
/* Please ref to ACPI spec for the syntax of _ADR */
|
||||
addr = (PCI_SLOT(pci_dev->devfn) << 16) | PCI_FUNC(pci_dev->devfn);
|
||||
|
@ -122,6 +122,9 @@ static inline void pci_acpi_add_edr_notifier(struct pci_dev *pdev) { }
|
||||
static inline void pci_acpi_remove_edr_notifier(struct pci_dev *pdev) { }
|
||||
#endif /* CONFIG_PCIE_EDR */
|
||||
|
||||
int pci_acpi_set_companion_lookup_hook(struct acpi_device *(*func)(struct pci_dev *));
|
||||
void pci_acpi_clear_companion_lookup_hook(void);
|
||||
|
||||
#else /* CONFIG_ACPI */
|
||||
static inline void acpi_pci_add_bus(struct pci_bus *bus) { }
|
||||
static inline void acpi_pci_remove_bus(struct pci_bus *bus) { }
|
||||
|
Loading…
Reference in New Issue
Block a user