PCI/VPD: Add pci_vpd_find_ro_info_keyword()
authorHeiner Kallweit <hkallweit1@gmail.com>
Wed, 18 Aug 2021 19:00:57 +0000 (21:00 +0200)
committerBjorn Helgaas <bhelgaas@google.com>
Fri, 20 Aug 2021 20:48:27 +0000 (15:48 -0500)
All users of pci_vpd_find_info_keyword() are interested in the VPD RO
section only. In addition all calls are followed by the same activities to
calculate start of tag data area and size of the data area.

Add pci_vpd_find_ro_info_keyword() that combines these functionalities.

pci_vpd_find_info_keyword() can be phased out once all users are converted.

[bhelgaas: split pci_vpd_check_csum() to separate patch]
Link: https://lore.kernel.org/r/1643bd7a-088e-1028-c9b0-9d112cf48d63@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 7c3a097379bb7182262483ebf35ea2ef50aedd17..b1d012900f1e43f4e4870e714ac40b3a9dfcad5d 100644 (file)
@@ -380,6 +380,39 @@ ssize_t pci_write_vpd(struct pci_dev *dev, loff_t pos, size_t count, const void
 }
 EXPORT_SYMBOL(pci_write_vpd);
 
+int pci_vpd_find_ro_info_keyword(const void *buf, unsigned int len,
+                                const char *kw, unsigned int *size)
+{
+       int ro_start, infokw_start;
+       unsigned int ro_len, infokw_size;
+
+       ro_start = pci_vpd_find_tag(buf, len, PCI_VPD_LRDT_RO_DATA);
+       if (ro_start < 0)
+               return ro_start;
+
+       ro_len = pci_vpd_lrdt_size(buf + ro_start);
+       ro_start += PCI_VPD_LRDT_TAG_SIZE;
+
+       if (ro_start + ro_len > len)
+               ro_len = len - ro_start;
+
+       infokw_start = pci_vpd_find_info_keyword(buf, ro_start, ro_len, kw);
+       if (infokw_start < 0)
+               return infokw_start;
+
+       infokw_size = pci_vpd_info_field_size(buf + infokw_start);
+       infokw_start += PCI_VPD_INFO_FLD_HDR_SIZE;
+
+       if (infokw_start + infokw_size > len)
+               return -EINVAL;
+
+       if (size)
+               *size = infokw_size;
+
+       return infokw_start;
+}
+EXPORT_SYMBOL_GPL(pci_vpd_find_ro_info_keyword);
+
 #ifdef CONFIG_PCI_QUIRKS
 /*
  * Quirk non-zero PCI functions to route VPD access through function 0 for
index 8c681e24be8b4fd279696c1be063e72e6dcfae4c..9e3b60963a52b851c1c3cc0d404494fcd8db275d 100644 (file)
@@ -2363,6 +2363,19 @@ int pci_vpd_find_tag(const u8 *buf, unsigned int len, u8 rdt);
 int pci_vpd_find_info_keyword(const u8 *buf, unsigned int off,
                              unsigned int len, const char *kw);
 
+/**
+ * pci_vpd_find_ro_info_keyword - Locate info field keyword in VPD RO section
+ * @buf: Pointer to buffered VPD data
+ * @len: The length of the buffer area in which to search
+ * @kw: The keyword to search for
+ * @size: Pointer to field where length of found keyword data is returned
+ *
+ * Returns the index of the information field keyword data or -ENOENT if
+ * not found.
+ */
+int pci_vpd_find_ro_info_keyword(const void *buf, unsigned int len,
+                                const char *kw, unsigned int *size);
+
 /* PCI <-> OF binding helpers */
 #ifdef CONFIG_OF
 struct device_node;