Commit 7639afad authored by Linus Torvalds's avatar Linus Torvalds
Browse files
Pull PCI fixes from Bjorn Helgaas:

 - Defer VPD sizing until we actually need the contents; fixes a
   boot-time slowdown reported by Dave Jones (Bjorn Helgaas)

 - Stop clobbering OF fwnodes when we look for an ACPI fwnode; fixes a
   virtio-iommu boot regression (Jean-Philippe Brucker)

 - Add AMD GPU multi-function power dependencies; fixes runtime power
   management, including GPU resume and temp and fan sensor issues (Evan
   Quan)

 - Update VMD maintainer to Nirmal Patel (Jon Derrick)

* tag 'pci-v5.15-fixes-1' of git://git.kernel.org/pub/scm/linux/kernel/git/helgaas/pci:
  MAINTAINERS: Add Nirmal Patel as VMD maintainer
  PCI: Add AMD GPU multi-function power dependencies
  PCI/ACPI: Don't reset a fwnode set by OF
  PCI/VPD: Defer VPD sizing until first access
parents ddf21bd8 e042a453
Loading
Loading
Loading
Loading
+2 −1
Original line number Diff line number Diff line
@@ -14342,7 +14342,8 @@ F: Documentation/devicetree/bindings/pci/intel,ixp4xx-pci.yaml
F:	drivers/pci/controller/pci-ixp4xx.c
PCI DRIVER FOR INTEL VOLUME MANAGEMENT DEVICE (VMD)
M:	Jonathan Derrick <jonathan.derrick@intel.com>
M:	Nirmal Patel <nirmal.patel@linux.intel.com>
R:	Jonathan Derrick <jonathan.derrick@linux.dev>
L:	linux-pci@vger.kernel.org
S:	Supported
F:	drivers/pci/controller/vmd.c
+1 −1
Original line number Diff line number Diff line
@@ -937,7 +937,7 @@ static struct acpi_device *acpi_pci_find_companion(struct device *dev);

void pci_set_acpi_fwnode(struct pci_dev *dev)
{
	if (!ACPI_COMPANION(&dev->dev) && !pci_dev_is_added(dev))
	if (!dev_fwnode(&dev->dev) && !pci_dev_is_added(dev))
		ACPI_COMPANION_SET(&dev->dev,
				   acpi_pci_find_companion(&dev->dev));
}
+7 −2
Original line number Diff line number Diff line
@@ -5435,7 +5435,7 @@ 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
 * Create device link for GPUs with integrated USB xHCI Host
 * controller to VGA.
 */
static void quirk_gpu_usb(struct pci_dev *usb)
@@ -5444,9 +5444,11 @@ static void quirk_gpu_usb(struct pci_dev *usb)
}
DECLARE_PCI_FIXUP_CLASS_FINAL(PCI_VENDOR_ID_NVIDIA, PCI_ANY_ID,
			      PCI_CLASS_SERIAL_USB, 8, quirk_gpu_usb);
DECLARE_PCI_FIXUP_CLASS_FINAL(PCI_VENDOR_ID_ATI, PCI_ANY_ID,
			      PCI_CLASS_SERIAL_USB, 8, quirk_gpu_usb);

/*
 * Create device link for NVIDIA GPU with integrated Type-C UCSI controller
 * Create device link for GPUs 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.
@@ -5459,6 +5461,9 @@ static void quirk_gpu_usb_typec_ucsi(struct pci_dev *ucsi)
DECLARE_PCI_FIXUP_CLASS_FINAL(PCI_VENDOR_ID_NVIDIA, PCI_ANY_ID,
			      PCI_CLASS_SERIAL_UNKNOWN, 8,
			      quirk_gpu_usb_typec_ucsi);
DECLARE_PCI_FIXUP_CLASS_FINAL(PCI_VENDOR_ID_ATI, 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
+26 −10
Original line number Diff line number Diff line
@@ -99,6 +99,24 @@ static size_t pci_vpd_size(struct pci_dev *dev)
	return off ?: PCI_VPD_SZ_INVALID;
}

static bool pci_vpd_available(struct pci_dev *dev)
{
	struct pci_vpd *vpd = &dev->vpd;

	if (!vpd->cap)
		return false;

	if (vpd->len == 0) {
		vpd->len = pci_vpd_size(dev);
		if (vpd->len == PCI_VPD_SZ_INVALID) {
			vpd->cap = 0;
			return false;
		}
	}

	return true;
}

/*
 * Wait for last operation to complete.
 * This code has to spin since there is no other notification from the PCI
@@ -145,7 +163,7 @@ static ssize_t pci_vpd_read(struct pci_dev *dev, loff_t pos, size_t count,
	loff_t end = pos + count;
	u8 *buf = arg;

	if (!vpd->cap)
	if (!pci_vpd_available(dev))
		return -ENODEV;

	if (pos < 0)
@@ -206,7 +224,7 @@ static ssize_t pci_vpd_write(struct pci_dev *dev, loff_t pos, size_t count,
	loff_t end = pos + count;
	int ret = 0;

	if (!vpd->cap)
	if (!pci_vpd_available(dev))
		return -ENODEV;

	if (pos < 0 || (pos & 3) || (count & 3))
@@ -242,14 +260,11 @@ static ssize_t pci_vpd_write(struct pci_dev *dev, loff_t pos, size_t count,

void pci_vpd_init(struct pci_dev *dev)
{
	if (dev->vpd.len == PCI_VPD_SZ_INVALID)
		return;

	dev->vpd.cap = pci_find_capability(dev, PCI_CAP_ID_VPD);
	mutex_init(&dev->vpd.lock);

	if (!dev->vpd.len)
		dev->vpd.len = pci_vpd_size(dev);

	if (dev->vpd.len == PCI_VPD_SZ_INVALID)
		dev->vpd.cap = 0;
}

static ssize_t vpd_read(struct file *filp, struct kobject *kobj,
@@ -294,13 +309,14 @@ const struct attribute_group pci_dev_vpd_attr_group = {

void *pci_vpd_alloc(struct pci_dev *dev, unsigned int *size)
{
	unsigned int len = dev->vpd.len;
	unsigned int len;
	void *buf;
	int cnt;

	if (!dev->vpd.cap)
	if (!pci_vpd_available(dev))
		return ERR_PTR(-ENODEV);

	len = dev->vpd.len;
	buf = kmalloc(len, GFP_KERNEL);
	if (!buf)
		return ERR_PTR(-ENOMEM);