mirror of
https://github.com/torvalds/linux.git
synced 2024-12-12 06:02:38 +00:00
PCI: Generalize multi-function power dependency device links
Although not allowed by the PCI specs, some multi-function devices have power dependencies between the functions. For example, function 1 may not work unless function 0 is in the D0 power state. The existing quirk_gpu_hda() adds a device link to express this dependency for GPU and HDA devices, but it really is not specific to those device types. Generalize it and rename it to pci_create_device_link() so we can create dependencies between any "consumer" and "producer" functions of a multi-function device, where the consumer is only functional if the producer is in D0. This reorganization should not affect any functionality. Link: https://lore.kernel.org/lkml/20190606092225.17960-2-abhsahu@nvidia.com Signed-off-by: Abhishek Sahu <abhsahu@nvidia.com> [bhelgaas: commit log, reword diagnostic] Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
This commit is contained in:
parent
a188339ca5
commit
a17beb1a08
@ -4934,35 +4934,49 @@ static void quirk_fsl_no_msi(struct pci_dev *pdev)
|
||||
DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_FREESCALE, PCI_ANY_ID, quirk_fsl_no_msi);
|
||||
|
||||
/*
|
||||
* GPUs with integrated HDA controller for streaming audio to attached displays
|
||||
* need a device link from the HDA controller (consumer) to the GPU (supplier)
|
||||
* so that the GPU is powered up whenever the HDA controller is accessed.
|
||||
* The GPU and HDA controller are functions 0 and 1 of the same PCI device.
|
||||
* The device link stays in place until shutdown (or removal of the PCI device
|
||||
* if it's hotplugged). Runtime PM is allowed by default on the HDA controller
|
||||
* to prevent it from permanently keeping the GPU awake.
|
||||
* Although not allowed by the spec, some multi-function devices have
|
||||
* dependencies of one function (consumer) on another (supplier). For the
|
||||
* consumer to work in D0, the supplier must also be in D0. Create a
|
||||
* device link from the consumer to the supplier to enforce this
|
||||
* dependency. Runtime PM is allowed by default on the consumer to prevent
|
||||
* it from permanently keeping the supplier awake.
|
||||
*/
|
||||
static void quirk_gpu_hda(struct pci_dev *hda)
|
||||
static void pci_create_device_link(struct pci_dev *pdev, unsigned int consumer,
|
||||
unsigned int supplier, unsigned int class,
|
||||
unsigned int class_shift)
|
||||
{
|
||||
struct pci_dev *gpu;
|
||||
struct pci_dev *supplier_pdev;
|
||||
|
||||
if (PCI_FUNC(hda->devfn) != 1)
|
||||
if (PCI_FUNC(pdev->devfn) != consumer)
|
||||
return;
|
||||
|
||||
gpu = pci_get_domain_bus_and_slot(pci_domain_nr(hda->bus),
|
||||
hda->bus->number,
|
||||
PCI_DEVFN(PCI_SLOT(hda->devfn), 0));
|
||||
if (!gpu || (gpu->class >> 16) != PCI_BASE_CLASS_DISPLAY) {
|
||||
pci_dev_put(gpu);
|
||||
supplier_pdev = pci_get_domain_bus_and_slot(pci_domain_nr(pdev->bus),
|
||||
pdev->bus->number,
|
||||
PCI_DEVFN(PCI_SLOT(pdev->devfn), supplier));
|
||||
if (!supplier_pdev || (supplier_pdev->class >> class_shift) != class) {
|
||||
pci_dev_put(supplier_pdev);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!device_link_add(&hda->dev, &gpu->dev,
|
||||
DL_FLAG_STATELESS | DL_FLAG_PM_RUNTIME))
|
||||
pci_err(hda, "cannot link HDA to GPU %s\n", pci_name(gpu));
|
||||
if (device_link_add(&pdev->dev, &supplier_pdev->dev,
|
||||
DL_FLAG_STATELESS | DL_FLAG_PM_RUNTIME))
|
||||
pci_info(pdev, "D0 power state depends on %s\n",
|
||||
pci_name(supplier_pdev));
|
||||
else
|
||||
pci_err(pdev, "Cannot enforce power dependency on %s\n",
|
||||
pci_name(supplier_pdev));
|
||||
|
||||
pm_runtime_allow(&hda->dev);
|
||||
pci_dev_put(gpu);
|
||||
pm_runtime_allow(&pdev->dev);
|
||||
pci_dev_put(supplier_pdev);
|
||||
}
|
||||
|
||||
/*
|
||||
* Create device link for GPUs with integrated HDA controller for streaming
|
||||
* audio to attached displays.
|
||||
*/
|
||||
static void quirk_gpu_hda(struct pci_dev *hda)
|
||||
{
|
||||
pci_create_device_link(hda, 1, 0, PCI_BASE_CLASS_DISPLAY, 16);
|
||||
}
|
||||
DECLARE_PCI_FIXUP_CLASS_FINAL(PCI_VENDOR_ID_ATI, PCI_ANY_ID,
|
||||
PCI_CLASS_MULTIMEDIA_HD_AUDIO, 8, quirk_gpu_hda);
|
||||
|
Loading…
Reference in New Issue
Block a user