summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHeiner Kallweit <hkallweit1@gmail.com>2021-08-18 20:59:31 +0200
committerBjorn Helgaas <bhelgaas@google.com>2021-08-20 15:13:20 -0500
commit76f3c032adad86aad26f8ad3eebc993b4ba32138 (patch)
treed4ad227a456d5233f998fb2435d94f35a215e0cc
parentfe7568cf2f2dc3a0783f6ffdb3802c1ce2085466 (diff)
downloadlinux-76f3c032adad86aad26f8ad3eebc993b4ba32138.tar.bz2
PCI/VPD: Add pci_vpd_alloc()
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>
-rw-r--r--drivers/pci/vpd.c26
-rw-r--r--include/linux/pci.h9
2 files changed, 35 insertions, 0 deletions
diff --git a/drivers/pci/vpd.c b/drivers/pci/vpd.c
index 3b0425fb49f5..7c3a097379bb 100644
--- a/drivers/pci/vpd.c
+++ b/drivers/pci/vpd.c
@@ -270,6 +270,32 @@ const struct attribute_group pci_dev_vpd_attr_group = {
.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;
diff --git a/include/linux/pci.h b/include/linux/pci.h
index e752cc39a1fe..8c681e24be8b 100644
--- a/include/linux/pci.h
+++ b/include/linux/pci.h
@@ -2331,6 +2331,15 @@ static inline u8 pci_vpd_info_field_size(const u8 *info_field)
}
/**
+ * 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
* @len: The length of the vpd buffer