Commit e0997728 authored by Bjorn Helgaas's avatar Bjorn Helgaas
Browse files

Merge branch 'pci/misc'

  - Generalize multi-function power dependency device links (Abhishek Sahu)

  - Add NVIDIA GPU multi-function power dependencies (Abhishek Sahu)

  - Optimize /proc/bus/pci/devices by using seq_puts() instead of
    seq_printf() (Markus Elfring)

  - Enable NVIDIA HDA controllers if BIOS didn't (Lukas Wunner)

* pci/misc:
  PCI: Enable NVIDIA HDA controllers
  PCI: Use seq_puts() instead of seq_printf() in show_device()
  PCI: Add NVIDIA GPU multi-function power dependencies
  PCI: Generalize multi-function power dependency device links
parents 8cf80c5c b516ea58
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -377,7 +377,7 @@ static int show_device(struct seq_file *m, void *v)
	}
	seq_putc(m, '\t');
	if (drv)
		seq_printf(m, "%s", drv->name);
		seq_puts(m, drv->name);
	seq_putc(m, '\n');
	return 0;
}
+90 −20
Original line number Diff line number Diff line
@@ -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,
	if (device_link_add(&pdev->dev, &supplier_pdev->dev,
			    DL_FLAG_STATELESS | DL_FLAG_PM_RUNTIME))
		pci_err(hda, "cannot link HDA to GPU %s\n", pci_name(gpu));
		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(&pdev->dev);
	pci_dev_put(supplier_pdev);
}

	pm_runtime_allow(&hda->dev);
	pci_dev_put(gpu);
/*
 * 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);
@@ -4971,6 +4985,62 @@ DECLARE_PCI_FIXUP_CLASS_FINAL(PCI_VENDOR_ID_AMD, PCI_ANY_ID,
DECLARE_PCI_FIXUP_CLASS_FINAL(PCI_VENDOR_ID_NVIDIA, PCI_ANY_ID,
			      PCI_CLASS_MULTIMEDIA_HD_AUDIO, 8, quirk_gpu_hda);

/*
 * Create device link for NVIDIA GPU with integrated USB xHCI Host
 * controller to VGA.
 */
static void quirk_gpu_usb(struct pci_dev *usb)
{
	pci_create_device_link(usb, 2, 0, PCI_BASE_CLASS_DISPLAY, 16);
}
DECLARE_PCI_FIXUP_CLASS_FINAL(PCI_VENDOR_ID_NVIDIA, PCI_ANY_ID,
			      PCI_CLASS_SERIAL_USB, 8, quirk_gpu_usb);

/*
 * Create device link for NVIDIA GPU with integrated Type-C UCSI controller
 * to VGA. Currently there is no class code defined for UCSI device over PCI
 * so using UNKNOWN class for now and it will be updated when UCSI
 * over PCI gets a class code.
 */
#define PCI_CLASS_SERIAL_UNKNOWN	0x0c80
static void quirk_gpu_usb_typec_ucsi(struct pci_dev *ucsi)
{
	pci_create_device_link(ucsi, 3, 0, PCI_BASE_CLASS_DISPLAY, 16);
}
DECLARE_PCI_FIXUP_CLASS_FINAL(PCI_VENDOR_ID_NVIDIA, PCI_ANY_ID,
			      PCI_CLASS_SERIAL_UNKNOWN, 8,
			      quirk_gpu_usb_typec_ucsi);

/*
 * Enable the NVIDIA GPU integrated HDA controller if the BIOS left it
 * disabled.  https://devtalk.nvidia.com/default/topic/1024022
 */
static void quirk_nvidia_hda(struct pci_dev *gpu)
{
	u8 hdr_type;
	u32 val;

	/* There was no integrated HDA controller before MCP89 */
	if (gpu->device < PCI_DEVICE_ID_NVIDIA_GEFORCE_320M)
		return;

	/* Bit 25 at offset 0x488 enables the HDA controller */
	pci_read_config_dword(gpu, 0x488, &val);
	if (val & BIT(25))
		return;

	pci_info(gpu, "Enabling HDA controller\n");
	pci_write_config_dword(gpu, 0x488, val | BIT(25));

	/* The GPU becomes a multi-function device when the HDA is enabled */
	pci_read_config_byte(gpu, PCI_HEADER_TYPE, &hdr_type);
	gpu->multifunction = !!(hdr_type & 0x80);
}
DECLARE_PCI_FIXUP_CLASS_HEADER(PCI_VENDOR_ID_NVIDIA, PCI_ANY_ID,
			       PCI_BASE_CLASS_DISPLAY, 16, quirk_nvidia_hda);
DECLARE_PCI_FIXUP_CLASS_RESUME_EARLY(PCI_VENDOR_ID_NVIDIA, PCI_ANY_ID,
			       PCI_BASE_CLASS_DISPLAY, 16, quirk_nvidia_hda);

/*
 * Some IDT switches incorrectly flag an ACS Source Validation error on
 * completions for config read requests even though PCIe r4.0, sec
+1 −0
Original line number Diff line number Diff line
@@ -1336,6 +1336,7 @@
#define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP78S_SMBUS    0x0752
#define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP77_IDE       0x0759
#define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP73_SMBUS     0x07D8
#define PCI_DEVICE_ID_NVIDIA_GEFORCE_320M           0x08A0
#define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP79_SMBUS     0x0AA2
#define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP89_SATA	    0x0D85