PCI/VPD: Add pci_vpd_alloc()
authorHeiner Kallweit <hkallweit1@gmail.com>
Wed, 18 Aug 2021 18:59:31 +0000 (20:59 +0200)
committerBjorn Helgaas <bhelgaas@google.com>
Fri, 20 Aug 2021 20:13:20 +0000 (15:13 -0500)
Several users of the VPD API use a fixed-size buffer and read the VPD into
it for further usage. This requires special handling for the case that the
buffer isn't big enough to hold the full VPD data.  Also the buffer is
often allocated on the stack, which isn't too nice.

Add pci_vpd_alloc() to dynamically allocate buffer of the correct size and
read VPD into it.

Link: https://lore.kernel.org/r/955ff598-0021-8446-f856-0c2c077635d7@gmail.com
Signed-off-by: Heiner Kallweit <hkallweit1@gmail.com>
Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
drivers/pci/vpd.c
include/linux/pci.h

index 3b0425fb49f5686ed273c1cbcb8a0b831125ba55..7c3a097379bb7182262483ebf35ea2ef50aedd17 100644 (file)
@@ -270,6 +270,32 @@ const struct attribute_group pci_dev_vpd_attr_group = {
        .is_bin_visible = vpd_attr_is_visible,
 };
 
        .is_bin_visible = vpd_attr_is_visible,
 };
 
+void *pci_vpd_alloc(struct pci_dev *dev, unsigned int *size)
+{
+       unsigned int len = dev->vpd.len;
+       void *buf;
+       int cnt;
+
+       if (!dev->vpd.cap)
+               return ERR_PTR(-ENODEV);
+
+       buf = kmalloc(len, GFP_KERNEL);
+       if (!buf)
+               return ERR_PTR(-ENOMEM);
+
+       cnt = pci_read_vpd(dev, 0, len, buf);
+       if (cnt != len) {
+               kfree(buf);
+               return ERR_PTR(-EIO);
+       }
+
+       if (size)
+               *size = len;
+
+       return buf;
+}
+EXPORT_SYMBOL_GPL(pci_vpd_alloc);
+
 int pci_vpd_find_tag(const u8 *buf, unsigned int len, u8 rdt)
 {
        int i = 0;
 int pci_vpd_find_tag(const u8 *buf, unsigned int len, u8 rdt)
 {
        int i = 0;
index e752cc39a1fe448169f40d5625d52e854985346c..8c681e24be8b4fd279696c1be063e72e6dcfae4c 100644 (file)
@@ -2330,6 +2330,15 @@ static inline u8 pci_vpd_info_field_size(const u8 *info_field)
        return info_field[2];
 }
 
        return info_field[2];
 }
 
+/**
+ * pci_vpd_alloc - Allocate buffer and read VPD into it
+ * @dev: PCI device
+ * @size: pointer to field where VPD length is returned
+ *
+ * Returns pointer to allocated buffer or an ERR_PTR in case of failure
+ */
+void *pci_vpd_alloc(struct pci_dev *dev, unsigned int *size);
+
 /**
  * pci_vpd_find_tag - Locates the Resource Data Type tag provided
  * @buf: Pointer to buffered vpd data
 /**
  * pci_vpd_find_tag - Locates the Resource Data Type tag provided
  * @buf: Pointer to buffered vpd data