linux-pci.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 0/8] PCI/VPD: Extend PCI VPD API
@ 2021-08-18 18:58 Heiner Kallweit
  2021-08-18 18:59 ` [PATCH 1/8] PCI/VPD: Add pci_vpd_alloc Heiner Kallweit
                   ` (8 more replies)
  0 siblings, 9 replies; 11+ messages in thread
From: Heiner Kallweit @ 2021-08-18 18:58 UTC (permalink / raw)
  To: Edward Cree, Martin Habets, Siva Reddy Kallam,
	Prashant Sreedharan, Michael Chan, David Miller, Jakub Kicinski
  Cc: linux-pci, netdev

This series adds three functions to the PCI VPD API that help to
simplify driver code. First users are sfc and tg3 drivers because
I have test hw. The other users of the VPD API will benefit from a
migration as well.
I'd propose to apply this series via the PCI tree.

Added API calls:

pci_vpd_alloc()
Dynamically allocates a properly sized buffer and reads the VPD into it.

pci_vpd_find_ro_info_keyword()
Locates an info field keyword in the VPD RO section.
pci_vpd_find_info_keyword() can be removed once all
users have been migrated.

pci_vpd_check_csum()
Check VPD checksum based on algorithm defined in the PCI specification.

Tested on a SFN6122F and a BCM95719 card.

Heiner Kallweit (8):
  PCI/VPD: Add pci_vpd_alloc
  PCI/VPD: Add pci_vpd_find_ro_info_keyword and pci_vpd_check_csum
  PCI/VPD: Add missing VPD RO field keywords
  sfc: Use new function pci_vpd_alloc
  sfc: Use new VPD API function pci_vpd_find_ro_info_keyword
  tg3: Use new function pci_vpd_alloc
  tg3: Use new function pci_vpd_check_csum
  tg3: Use new function pci_vpd_find_ro_info_keyword

 drivers/net/ethernet/broadcom/tg3.c | 115 +++++++---------------------
 drivers/net/ethernet/broadcom/tg3.h |   1 -
 drivers/net/ethernet/sfc/efx.c      |  78 +++++--------------
 drivers/pci/vpd.c                   |  82 ++++++++++++++++++++
 include/linux/pci.h                 |  32 ++++++++
 5 files changed, 163 insertions(+), 145 deletions(-)

-- 
2.32.0


^ permalink raw reply	[flat|nested] 11+ messages in thread

* [PATCH 1/8] PCI/VPD: Add pci_vpd_alloc
  2021-08-18 18:58 [PATCH 0/8] PCI/VPD: Extend PCI VPD API Heiner Kallweit
@ 2021-08-18 18:59 ` Heiner Kallweit
  2021-08-18 19:00 ` [PATCH 2/8] PCI/VPD: Add pci_vpd_find_ro_info_keyword and pci_vpd_check_csum Heiner Kallweit
                   ` (7 subsequent siblings)
  8 siblings, 0 replies; 11+ messages in thread
From: Heiner Kallweit @ 2021-08-18 18:59 UTC (permalink / raw)
  To: Edward Cree, Martin Habets, Siva Reddy Kallam,
	Prashant Sreedharan, Michael Chan, David Miller, Jakub Kicinski
  Cc: linux-pci, netdev

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 what's not too nice.
So let's extend the VPD API with a function that dynamically allocates
a properly sized buffer.

Signed-off-by: Heiner Kallweit <hkallweit1@gmail.com>
---
 drivers/pci/vpd.c   | 26 ++++++++++++++++++++++++++
 include/linux/pci.h |  9 +++++++++
 2 files changed, 35 insertions(+)

diff --git a/drivers/pci/vpd.c b/drivers/pci/vpd.c
index 3b0425fb4..7c3a09737 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 e752cc39a..3061cc943 100644
--- a/include/linux/pci.h
+++ b/include/linux/pci.h
@@ -2330,6 +2330,15 @@ static inline u8 pci_vpd_info_field_size(const u8 *info_field)
 	return info_field[2];
 }
 
+/**
+ * pci_vpd_alloc - Allocates buffer and reads 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
-- 
2.32.0



^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [PATCH 2/8] PCI/VPD: Add pci_vpd_find_ro_info_keyword and pci_vpd_check_csum
  2021-08-18 18:58 [PATCH 0/8] PCI/VPD: Extend PCI VPD API Heiner Kallweit
  2021-08-18 18:59 ` [PATCH 1/8] PCI/VPD: Add pci_vpd_alloc Heiner Kallweit
@ 2021-08-18 19:00 ` Heiner Kallweit
  2021-08-18 19:01 ` [PATCH 3/8] PCI/VPD: Add missing VPD RO field keywords Heiner Kallweit
                   ` (6 subsequent siblings)
  8 siblings, 0 replies; 11+ messages in thread
From: Heiner Kallweit @ 2021-08-18 19:00 UTC (permalink / raw)
  To: Edward Cree, Martin Habets, Siva Reddy Kallam,
	Prashant Sreedharan, Michael Chan, David Miller, Jakub Kicinski
  Cc: linux-pci, netdev

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. Therefore add an API function that combines these
functionalities. pci_vpd_find_info_keyword() can be phased out once
all users are converted.

VPD checksum information and checksum calculation are part of the PCI
standard. Therefore checksum handling can and should be moved into
PCI VPD core. Add an API function pci_vpd_check_csum() for that.

Signed-off-by: Heiner Kallweit <hkallweit1@gmail.com>
---
 drivers/pci/vpd.c   | 56 +++++++++++++++++++++++++++++++++++++++++++++
 include/linux/pci.h | 21 +++++++++++++++++
 2 files changed, 77 insertions(+)

diff --git a/drivers/pci/vpd.c b/drivers/pci/vpd.c
index 7c3a09737..01e575947 100644
--- a/drivers/pci/vpd.c
+++ b/drivers/pci/vpd.c
@@ -380,6 +380,62 @@ 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);
+
+int pci_vpd_check_csum(const void *buf, unsigned int len)
+{
+	const u8 *vpd = buf;
+	unsigned int size;
+	u8 csum = 0;
+	int rv_start;
+
+	rv_start = pci_vpd_find_ro_info_keyword(buf, len, PCI_VPD_RO_KEYWORD_CHKSUM, &size);
+	if (rv_start == -ENOENT) /* no checksum in VPD */
+		return 1;
+	else if (rv_start < 0)
+		return rv_start;
+
+	if (!size)
+		return -EINVAL;
+
+	while (rv_start >= 0)
+		csum += vpd[rv_start--];
+
+	return csum ? -EILSEQ : 0;
+}
+EXPORT_SYMBOL_GPL(pci_vpd_check_csum);
+
 #ifdef CONFIG_PCI_QUIRKS
 /*
  * Quirk non-zero PCI functions to route VPD access through function 0 for
diff --git a/include/linux/pci.h b/include/linux/pci.h
index 3061cc943..a82f5910f 100644
--- a/include/linux/pci.h
+++ b/include/linux/pci.h
@@ -2363,6 +2363,27 @@ 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_check_csum - Check VPD checksum
+ * @buf: Pointer to buffered vpd data
+ * @len: VPD size
+ *
+ * Returns 1 if VPD has no checksum, otherwise 0 or an errno
+ */
+int pci_vpd_check_csum(const void *buf, unsigned int len);
+
+/**
+ * pci_vpd_find_ro_info_keyword - Locates an 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;
-- 
2.32.0



^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [PATCH 3/8] PCI/VPD: Add missing VPD RO field keywords
  2021-08-18 18:58 [PATCH 0/8] PCI/VPD: Extend PCI VPD API Heiner Kallweit
  2021-08-18 18:59 ` [PATCH 1/8] PCI/VPD: Add pci_vpd_alloc Heiner Kallweit
  2021-08-18 19:00 ` [PATCH 2/8] PCI/VPD: Add pci_vpd_find_ro_info_keyword and pci_vpd_check_csum Heiner Kallweit
@ 2021-08-18 19:01 ` Heiner Kallweit
  2021-08-18 19:02 ` [PATCH 4/8] sfc: Use new function pci_vpd_alloc Heiner Kallweit
                   ` (5 subsequent siblings)
  8 siblings, 0 replies; 11+ messages in thread
From: Heiner Kallweit @ 2021-08-18 19:01 UTC (permalink / raw)
  To: Edward Cree, Martin Habets, Siva Reddy Kallam,
	Prashant Sreedharan, Michael Chan, David Miller, Jakub Kicinski
  Cc: linux-pci, netdev

This patch adds further keywords that are defined in the PCI spec.

Signed-off-by: Heiner Kallweit <hkallweit1@gmail.com>
---
 include/linux/pci.h | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/include/linux/pci.h b/include/linux/pci.h
index a82f5910f..629c810ae 100644
--- a/include/linux/pci.h
+++ b/include/linux/pci.h
@@ -2274,6 +2274,8 @@ int pci_enable_atomic_ops_to_root(struct pci_dev *dev, u32 cap_mask);
 #define PCI_VPD_RO_KEYWORD_MFR_ID	"MN"
 #define PCI_VPD_RO_KEYWORD_VENDOR0	"V0"
 #define PCI_VPD_RO_KEYWORD_CHKSUM	"RV"
+#define PCI_VPD_RO_KEYWORD_ECLEVEL	"EC"
+#define PCI_VPD_RO_KEYWORD_EXTCAP	"CP"
 
 /**
  * pci_vpd_lrdt_size - Extracts the Large Resource Data Type length
-- 
2.32.0



^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [PATCH 4/8] sfc: Use new function pci_vpd_alloc
  2021-08-18 18:58 [PATCH 0/8] PCI/VPD: Extend PCI VPD API Heiner Kallweit
                   ` (2 preceding siblings ...)
  2021-08-18 19:01 ` [PATCH 3/8] PCI/VPD: Add missing VPD RO field keywords Heiner Kallweit
@ 2021-08-18 19:02 ` Heiner Kallweit
  2021-08-18 19:03 ` [PATCH 5/8] sfc: Use new VPD API function pci_vpd_find_ro_info_keyword Heiner Kallweit
                   ` (4 subsequent siblings)
  8 siblings, 0 replies; 11+ messages in thread
From: Heiner Kallweit @ 2021-08-18 19:02 UTC (permalink / raw)
  To: Edward Cree, Martin Habets, David Miller, Jakub Kicinski
  Cc: linux-pci, netdev

Use new VPD API function pci_vpd_alloc() for dynamically allocating
a properly sized buffer and reading the full VPD data into it.
This avoids having to allocate a buffer on the stack, and we don't
have to make any assumptions on VPD size and location of information
in VPD any longer.

Signed-off-by: Heiner Kallweit <hkallweit1@gmail.com>
---
 drivers/net/ethernet/sfc/efx.c | 29 ++++++++++++++---------------
 1 file changed, 14 insertions(+), 15 deletions(-)

diff --git a/drivers/net/ethernet/sfc/efx.c b/drivers/net/ethernet/sfc/efx.c
index a295e2621..e04a63109 100644
--- a/drivers/net/ethernet/sfc/efx.c
+++ b/drivers/net/ethernet/sfc/efx.c
@@ -900,21 +900,18 @@ static void efx_pci_remove(struct pci_dev *pci_dev)
 
 /* NIC VPD information
  * Called during probe to display the part number of the
- * installed NIC.  VPD is potentially very large but this should
- * always appear within the first 512 bytes.
+ * installed NIC.
  */
-#define SFC_VPD_LEN 512
 static void efx_probe_vpd_strings(struct efx_nic *efx)
 {
 	struct pci_dev *dev = efx->pci_dev;
-	char vpd_data[SFC_VPD_LEN];
-	ssize_t vpd_size;
 	int ro_start, ro_size, i, j;
+	unsigned int vpd_size;
+	u8 *vpd_data;
 
-	/* Get the vpd data from the device */
-	vpd_size = pci_read_vpd(dev, 0, sizeof(vpd_data), vpd_data);
-	if (vpd_size <= 0) {
-		netif_err(efx, drv, efx->net_dev, "Unable to read VPD\n");
+	vpd_data = pci_vpd_alloc(dev, &vpd_size);
+	if (IS_ERR(vpd_data)) {
+		pci_warn(dev, "Unable to read VPD\n");
 		return;
 	}
 
@@ -922,7 +919,7 @@ static void efx_probe_vpd_strings(struct efx_nic *efx)
 	ro_start = pci_vpd_find_tag(vpd_data, vpd_size, PCI_VPD_LRDT_RO_DATA);
 	if (ro_start < 0) {
 		netif_err(efx, drv, efx->net_dev, "VPD Read-only not found\n");
-		return;
+		goto out;
 	}
 
 	ro_size = pci_vpd_lrdt_size(&vpd_data[ro_start]);
@@ -935,14 +932,14 @@ static void efx_probe_vpd_strings(struct efx_nic *efx)
 	i = pci_vpd_find_info_keyword(vpd_data, i, j, "PN");
 	if (i < 0) {
 		netif_err(efx, drv, efx->net_dev, "Part number not found\n");
-		return;
+		goto out;
 	}
 
 	j = pci_vpd_info_field_size(&vpd_data[i]);
 	i += PCI_VPD_INFO_FLD_HDR_SIZE;
 	if (i + j > vpd_size) {
 		netif_err(efx, drv, efx->net_dev, "Incomplete part number\n");
-		return;
+		goto out;
 	}
 
 	netif_info(efx, drv, efx->net_dev,
@@ -953,21 +950,23 @@ static void efx_probe_vpd_strings(struct efx_nic *efx)
 	i = pci_vpd_find_info_keyword(vpd_data, i, j, "SN");
 	if (i < 0) {
 		netif_err(efx, drv, efx->net_dev, "Serial number not found\n");
-		return;
+		goto out;
 	}
 
 	j = pci_vpd_info_field_size(&vpd_data[i]);
 	i += PCI_VPD_INFO_FLD_HDR_SIZE;
 	if (i + j > vpd_size) {
 		netif_err(efx, drv, efx->net_dev, "Incomplete serial number\n");
-		return;
+		goto out;
 	}
 
 	efx->vpd_sn = kmalloc(j + 1, GFP_KERNEL);
 	if (!efx->vpd_sn)
-		return;
+		goto out;
 
 	snprintf(efx->vpd_sn, j + 1, "%s", &vpd_data[i]);
+out:
+	kfree(vpd_data);
 }
 
 
-- 
2.32.0



^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [PATCH 5/8] sfc: Use new VPD API function pci_vpd_find_ro_info_keyword
  2021-08-18 18:58 [PATCH 0/8] PCI/VPD: Extend PCI VPD API Heiner Kallweit
                   ` (3 preceding siblings ...)
  2021-08-18 19:02 ` [PATCH 4/8] sfc: Use new function pci_vpd_alloc Heiner Kallweit
@ 2021-08-18 19:03 ` Heiner Kallweit
  2021-08-18 19:04 ` [PATCH 6/8] tg3: Use new function pci_vpd_alloc Heiner Kallweit
                   ` (3 subsequent siblings)
  8 siblings, 0 replies; 11+ messages in thread
From: Heiner Kallweit @ 2021-08-18 19:03 UTC (permalink / raw)
  To: Edward Cree, Martin Habets, David Miller, Jakub Kicinski
  Cc: linux-pci, netdev

Use new VPD API function pci_vpd_find_ro_info_keyword() to simplify
the code. In addition replace netif_err() with pci_err() because the
netdevice isn't registered yet what results in very ugly messages.
Use kmemdup_nul() instead of open-coding it.

Signed-off-by: Heiner Kallweit <hkallweit1@gmail.com>
---
 drivers/net/ethernet/sfc/efx.c | 65 ++++++++--------------------------
 1 file changed, 14 insertions(+), 51 deletions(-)

diff --git a/drivers/net/ethernet/sfc/efx.c b/drivers/net/ethernet/sfc/efx.c
index e04a63109..43ef4f529 100644
--- a/drivers/net/ethernet/sfc/efx.c
+++ b/drivers/net/ethernet/sfc/efx.c
@@ -905,9 +905,9 @@ static void efx_pci_remove(struct pci_dev *pci_dev)
 static void efx_probe_vpd_strings(struct efx_nic *efx)
 {
 	struct pci_dev *dev = efx->pci_dev;
-	int ro_start, ro_size, i, j;
-	unsigned int vpd_size;
+	unsigned int vpd_size, kw_len;
 	u8 *vpd_data;
+	int start;
 
 	vpd_data = pci_vpd_alloc(dev, &vpd_size);
 	if (IS_ERR(vpd_data)) {
@@ -915,57 +915,20 @@ static void efx_probe_vpd_strings(struct efx_nic *efx)
 		return;
 	}
 
-	/* Get the Read only section */
-	ro_start = pci_vpd_find_tag(vpd_data, vpd_size, PCI_VPD_LRDT_RO_DATA);
-	if (ro_start < 0) {
-		netif_err(efx, drv, efx->net_dev, "VPD Read-only not found\n");
-		goto out;
-	}
-
-	ro_size = pci_vpd_lrdt_size(&vpd_data[ro_start]);
-	j = ro_size;
-	i = ro_start + PCI_VPD_LRDT_TAG_SIZE;
-	if (i + j > vpd_size)
-		j = vpd_size - i;
-
-	/* Get the Part number */
-	i = pci_vpd_find_info_keyword(vpd_data, i, j, "PN");
-	if (i < 0) {
-		netif_err(efx, drv, efx->net_dev, "Part number not found\n");
-		goto out;
-	}
-
-	j = pci_vpd_info_field_size(&vpd_data[i]);
-	i += PCI_VPD_INFO_FLD_HDR_SIZE;
-	if (i + j > vpd_size) {
-		netif_err(efx, drv, efx->net_dev, "Incomplete part number\n");
-		goto out;
-	}
-
-	netif_info(efx, drv, efx->net_dev,
-		   "Part Number : %.*s\n", j, &vpd_data[i]);
-
-	i = ro_start + PCI_VPD_LRDT_TAG_SIZE;
-	j = ro_size;
-	i = pci_vpd_find_info_keyword(vpd_data, i, j, "SN");
-	if (i < 0) {
-		netif_err(efx, drv, efx->net_dev, "Serial number not found\n");
-		goto out;
-	}
-
-	j = pci_vpd_info_field_size(&vpd_data[i]);
-	i += PCI_VPD_INFO_FLD_HDR_SIZE;
-	if (i + j > vpd_size) {
-		netif_err(efx, drv, efx->net_dev, "Incomplete serial number\n");
-		goto out;
-	}
+	start = pci_vpd_find_ro_info_keyword(vpd_data, vpd_size,
+					     PCI_VPD_RO_KEYWORD_PARTNO, &kw_len);
+	if (start < 0)
+		pci_err(dev, "Part number not found or incomplete\n");
+	else
+		pci_info(dev, "Part Number : %.*s\n", kw_len, vpd_data + start);
 
-	efx->vpd_sn = kmalloc(j + 1, GFP_KERNEL);
-	if (!efx->vpd_sn)
-		goto out;
+	start = pci_vpd_find_ro_info_keyword(vpd_data, vpd_size,
+					     PCI_VPD_RO_KEYWORD_SERIALNO, &kw_len);
+	if (start < 0)
+		pci_err(dev, "Serial number not found or incomplete\n");
+	else
+		efx->vpd_sn = kmemdup_nul(vpd_data + start, kw_len, GFP_KERNEL);
 
-	snprintf(efx->vpd_sn, j + 1, "%s", &vpd_data[i]);
-out:
 	kfree(vpd_data);
 }
 
-- 
2.32.0



^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [PATCH 6/8] tg3: Use new function pci_vpd_alloc
  2021-08-18 18:58 [PATCH 0/8] PCI/VPD: Extend PCI VPD API Heiner Kallweit
                   ` (4 preceding siblings ...)
  2021-08-18 19:03 ` [PATCH 5/8] sfc: Use new VPD API function pci_vpd_find_ro_info_keyword Heiner Kallweit
@ 2021-08-18 19:04 ` Heiner Kallweit
  2021-08-18 19:05 ` [PATCH 7/8] tg3: Use new function pci_vpd_check_csum Heiner Kallweit
                   ` (2 subsequent siblings)
  8 siblings, 0 replies; 11+ messages in thread
From: Heiner Kallweit @ 2021-08-18 19:04 UTC (permalink / raw)
  To: Siva Reddy Kallam, Prashant Sreedharan, Michael Chan,
	David Miller, Jakub Kicinski
  Cc: linux-pci, netdev

Use new VPD API function pci_vpd_alloc() for dynamically allocating
a properly sized buffer and reading the full VPD data into it.
This allows to simplify the code, and we don't have to make
assumptions on VPD size any longer.

Signed-off-by: Heiner Kallweit <hkallweit1@gmail.com>
---
 drivers/net/ethernet/broadcom/tg3.c | 27 ++++++++++-----------------
 drivers/net/ethernet/broadcom/tg3.h |  1 -
 2 files changed, 10 insertions(+), 18 deletions(-)

diff --git a/drivers/net/ethernet/broadcom/tg3.c b/drivers/net/ethernet/broadcom/tg3.c
index 6f82eeaa4..fd4522c81 100644
--- a/drivers/net/ethernet/broadcom/tg3.c
+++ b/drivers/net/ethernet/broadcom/tg3.c
@@ -12791,7 +12791,7 @@ static void tg3_get_ethtool_stats(struct net_device *dev,
 		memset(tmp_stats, 0, sizeof(struct tg3_ethtool_stats));
 }
 
-static __be32 *tg3_vpd_readblock(struct tg3 *tp, u32 *vpdlen)
+static __be32 *tg3_vpd_readblock(struct tg3 *tp, unsigned int *vpdlen)
 {
 	int i;
 	__be32 *buf;
@@ -12825,15 +12825,11 @@ static __be32 *tg3_vpd_readblock(struct tg3 *tp, u32 *vpdlen)
 			offset = TG3_NVM_VPD_OFF;
 			len = TG3_NVM_VPD_LEN;
 		}
-	} else {
-		len = TG3_NVM_PCI_VPD_MAX_LEN;
-	}
 
-	buf = kmalloc(len, GFP_KERNEL);
-	if (buf == NULL)
-		return NULL;
+		buf = kmalloc(len, GFP_KERNEL);
+		if (!buf)
+			return NULL;
 
-	if (magic == TG3_EEPROM_MAGIC) {
 		for (i = 0; i < len; i += 4) {
 			/* The data is in little-endian format in NVRAM.
 			 * Use the big-endian read routines to preserve
@@ -12844,12 +12840,9 @@ static __be32 *tg3_vpd_readblock(struct tg3 *tp, u32 *vpdlen)
 		}
 		*vpdlen = len;
 	} else {
-		ssize_t cnt;
-
-		cnt = pci_read_vpd(tp->pdev, 0, len, (u8 *)buf);
-		if (cnt < 0)
-			goto error;
-		*vpdlen = cnt;
+		buf = pci_vpd_alloc(tp->pdev, vpdlen);
+		if (IS_ERR(buf))
+			return NULL;
 	}
 
 	return buf;
@@ -12871,9 +12864,10 @@ static __be32 *tg3_vpd_readblock(struct tg3 *tp, u32 *vpdlen)
 
 static int tg3_test_nvram(struct tg3 *tp)
 {
-	u32 csum, magic, len;
+	u32 csum, magic;
 	__be32 *buf;
 	int i, j, k, err = 0, size;
+	unsigned int len;
 
 	if (tg3_flag(tp, NO_NVRAM))
 		return 0;
@@ -15621,8 +15615,7 @@ static int tg3_phy_probe(struct tg3 *tp)
 static void tg3_read_vpd(struct tg3 *tp)
 {
 	u8 *vpd_data;
-	unsigned int block_end, rosize, len;
-	u32 vpdlen;
+	unsigned int block_end, rosize, len, vpdlen;
 	int j, i = 0;
 
 	vpd_data = (u8 *)tg3_vpd_readblock(tp, &vpdlen);
diff --git a/drivers/net/ethernet/broadcom/tg3.h b/drivers/net/ethernet/broadcom/tg3.h
index 46ec4fdfd..1000c8940 100644
--- a/drivers/net/ethernet/broadcom/tg3.h
+++ b/drivers/net/ethernet/broadcom/tg3.h
@@ -2101,7 +2101,6 @@
 /* Hardware Legacy NVRAM layout */
 #define TG3_NVM_VPD_OFF			0x100
 #define TG3_NVM_VPD_LEN			256
-#define TG3_NVM_PCI_VPD_MAX_LEN		512
 
 /* Hardware Selfboot NVRAM layout */
 #define TG3_NVM_HWSB_CFG1		0x00000004
-- 
2.32.0



^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [PATCH 7/8] tg3: Use new function pci_vpd_check_csum
  2021-08-18 18:58 [PATCH 0/8] PCI/VPD: Extend PCI VPD API Heiner Kallweit
                   ` (5 preceding siblings ...)
  2021-08-18 19:04 ` [PATCH 6/8] tg3: Use new function pci_vpd_alloc Heiner Kallweit
@ 2021-08-18 19:05 ` Heiner Kallweit
  2021-08-18 19:06 ` [PATCH 8/8] tg3: Use new function pci_vpd_find_ro_info_keyword Heiner Kallweit
  2021-08-20 20:50 ` [PATCH 0/8] PCI/VPD: Extend PCI VPD API Bjorn Helgaas
  8 siblings, 0 replies; 11+ messages in thread
From: Heiner Kallweit @ 2021-08-18 19:05 UTC (permalink / raw)
  To: Siva Reddy Kallam, Prashant Sreedharan, Michael Chan,
	David Miller, Jakub Kicinski
  Cc: linux-pci, netdev

Use new VPD API function pci_vpd_check_csum() to simplify the code.

Signed-off-by: Heiner Kallweit <hkallweit1@gmail.com>
---
 drivers/net/ethernet/broadcom/tg3.c | 31 ++++-------------------------
 1 file changed, 4 insertions(+), 27 deletions(-)

diff --git a/drivers/net/ethernet/broadcom/tg3.c b/drivers/net/ethernet/broadcom/tg3.c
index fd4522c81..309aec742 100644
--- a/drivers/net/ethernet/broadcom/tg3.c
+++ b/drivers/net/ethernet/broadcom/tg3.c
@@ -13010,33 +13010,10 @@ static int tg3_test_nvram(struct tg3 *tp)
 	if (!buf)
 		return -ENOMEM;
 
-	i = pci_vpd_find_tag((u8 *)buf, len, PCI_VPD_LRDT_RO_DATA);
-	if (i > 0) {
-		j = pci_vpd_lrdt_size(&((u8 *)buf)[i]);
-		if (j < 0)
-			goto out;
-
-		if (i + PCI_VPD_LRDT_TAG_SIZE + j > len)
-			goto out;
-
-		i += PCI_VPD_LRDT_TAG_SIZE;
-		j = pci_vpd_find_info_keyword((u8 *)buf, i, j,
-					      PCI_VPD_RO_KEYWORD_CHKSUM);
-		if (j > 0) {
-			u8 csum8 = 0;
-
-			j += PCI_VPD_INFO_FLD_HDR_SIZE;
-
-			for (i = 0; i <= j; i++)
-				csum8 += ((u8 *)buf)[i];
-
-			if (csum8)
-				goto out;
-		}
-	}
-
-	err = 0;
-
+	err = pci_vpd_check_csum(buf, len);
+	/* go on if no checksum found */
+	if (err == 1)
+		err = 0;
 out:
 	kfree(buf);
 	return err;
-- 
2.32.0



^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [PATCH 8/8] tg3: Use new function pci_vpd_find_ro_info_keyword
  2021-08-18 18:58 [PATCH 0/8] PCI/VPD: Extend PCI VPD API Heiner Kallweit
                   ` (6 preceding siblings ...)
  2021-08-18 19:05 ` [PATCH 7/8] tg3: Use new function pci_vpd_check_csum Heiner Kallweit
@ 2021-08-18 19:06 ` Heiner Kallweit
  2021-08-20 20:50 ` [PATCH 0/8] PCI/VPD: Extend PCI VPD API Bjorn Helgaas
  8 siblings, 0 replies; 11+ messages in thread
From: Heiner Kallweit @ 2021-08-18 19:06 UTC (permalink / raw)
  To: Siva Reddy Kallam, Prashant Sreedharan, Michael Chan,
	David Miller, Jakub Kicinski
  Cc: linux-pci, netdev

Use new VPD API function pci_vpd_find_ro_info_keyword() to simplify
the code.

Signed-off-by: Heiner Kallweit <hkallweit1@gmail.com>
---
 drivers/net/ethernet/broadcom/tg3.c | 59 ++++++++---------------------
 1 file changed, 16 insertions(+), 43 deletions(-)

diff --git a/drivers/net/ethernet/broadcom/tg3.c b/drivers/net/ethernet/broadcom/tg3.c
index 309aec742..6637a97d7 100644
--- a/drivers/net/ethernet/broadcom/tg3.c
+++ b/drivers/net/ethernet/broadcom/tg3.c
@@ -15592,63 +15592,36 @@ static int tg3_phy_probe(struct tg3 *tp)
 static void tg3_read_vpd(struct tg3 *tp)
 {
 	u8 *vpd_data;
-	unsigned int block_end, rosize, len, vpdlen;
-	int j, i = 0;
+	unsigned int len, vpdlen;
+	int i;
 
 	vpd_data = (u8 *)tg3_vpd_readblock(tp, &vpdlen);
 	if (!vpd_data)
 		goto out_no_vpd;
 
-	i = pci_vpd_find_tag(vpd_data, vpdlen, PCI_VPD_LRDT_RO_DATA);
+	i = pci_vpd_find_ro_info_keyword(vpd_data, vpdlen,
+					 PCI_VPD_RO_KEYWORD_MFR_ID, &len);
 	if (i < 0)
-		goto out_not_found;
-
-	rosize = pci_vpd_lrdt_size(&vpd_data[i]);
-	block_end = i + PCI_VPD_LRDT_TAG_SIZE + rosize;
-	i += PCI_VPD_LRDT_TAG_SIZE;
-
-	if (block_end > vpdlen)
-		goto out_not_found;
-
-	j = pci_vpd_find_info_keyword(vpd_data, i, rosize,
-				      PCI_VPD_RO_KEYWORD_MFR_ID);
-	if (j > 0) {
-		len = pci_vpd_info_field_size(&vpd_data[j]);
+		goto partno;
 
-		j += PCI_VPD_INFO_FLD_HDR_SIZE;
-		if (j + len > block_end || len != 4 ||
-		    memcmp(&vpd_data[j], "1028", 4))
-			goto partno;
+	if (len != 4 || memcmp(vpd_data + i, "1028", 4))
+		goto partno;
 
-		j = pci_vpd_find_info_keyword(vpd_data, i, rosize,
-					      PCI_VPD_RO_KEYWORD_VENDOR0);
-		if (j < 0)
-			goto partno;
-
-		len = pci_vpd_info_field_size(&vpd_data[j]);
+	i = pci_vpd_find_ro_info_keyword(vpd_data, vpdlen,
+					 PCI_VPD_RO_KEYWORD_VENDOR0, &len);
+	if (i < 0)
+		goto partno;
 
-		j += PCI_VPD_INFO_FLD_HDR_SIZE;
-		if (j + len > block_end)
-			goto partno;
-
-		if (len >= sizeof(tp->fw_ver))
-			len = sizeof(tp->fw_ver) - 1;
-		memset(tp->fw_ver, 0, sizeof(tp->fw_ver));
-		snprintf(tp->fw_ver, sizeof(tp->fw_ver), "%.*s bc ", len,
-			 &vpd_data[j]);
-	}
+	memset(tp->fw_ver, 0, sizeof(tp->fw_ver));
+	snprintf(tp->fw_ver, sizeof(tp->fw_ver), "%.*s bc ", len, vpd_data + i);
 
 partno:
-	i = pci_vpd_find_info_keyword(vpd_data, i, rosize,
-				      PCI_VPD_RO_KEYWORD_PARTNO);
+	i = pci_vpd_find_ro_info_keyword(vpd_data, vpdlen,
+					 PCI_VPD_RO_KEYWORD_PARTNO, &len);
 	if (i < 0)
 		goto out_not_found;
 
-	len = pci_vpd_info_field_size(&vpd_data[i]);
-
-	i += PCI_VPD_INFO_FLD_HDR_SIZE;
-	if (len > TG3_BPN_SIZE ||
-	    (len + i) > vpdlen)
+	if (len > TG3_BPN_SIZE)
 		goto out_not_found;
 
 	memcpy(tp->board_part_number, &vpd_data[i], len);
-- 
2.32.0



^ permalink raw reply related	[flat|nested] 11+ messages in thread

* Re: [PATCH 0/8] PCI/VPD: Extend PCI VPD API
  2021-08-18 18:58 [PATCH 0/8] PCI/VPD: Extend PCI VPD API Heiner Kallweit
                   ` (7 preceding siblings ...)
  2021-08-18 19:06 ` [PATCH 8/8] tg3: Use new function pci_vpd_find_ro_info_keyword Heiner Kallweit
@ 2021-08-20 20:50 ` Bjorn Helgaas
  2021-08-20 21:36   ` Heiner Kallweit
  8 siblings, 1 reply; 11+ messages in thread
From: Bjorn Helgaas @ 2021-08-20 20:50 UTC (permalink / raw)
  To: Heiner Kallweit
  Cc: Edward Cree, Martin Habets, Siva Reddy Kallam,
	Prashant Sreedharan, Michael Chan, David Miller, Jakub Kicinski,
	linux-pci, netdev

On Wed, Aug 18, 2021 at 08:58:18PM +0200, Heiner Kallweit wrote:
> This series adds three functions to the PCI VPD API that help to
> simplify driver code. First users are sfc and tg3 drivers because
> I have test hw. The other users of the VPD API will benefit from a
> migration as well.
> I'd propose to apply this series via the PCI tree.
> 
> Added API calls:
> 
> pci_vpd_alloc()
> Dynamically allocates a properly sized buffer and reads the VPD into it.
> 
> pci_vpd_find_ro_info_keyword()
> Locates an info field keyword in the VPD RO section.
> pci_vpd_find_info_keyword() can be removed once all
> users have been migrated.
> 
> pci_vpd_check_csum()
> Check VPD checksum based on algorithm defined in the PCI specification.
> 
> Tested on a SFN6122F and a BCM95719 card.
> 
> Heiner Kallweit (8):
>   PCI/VPD: Add pci_vpd_alloc
>   PCI/VPD: Add pci_vpd_find_ro_info_keyword and pci_vpd_check_csum
>   PCI/VPD: Add missing VPD RO field keywords
>   sfc: Use new function pci_vpd_alloc
>   sfc: Use new VPD API function pci_vpd_find_ro_info_keyword
>   tg3: Use new function pci_vpd_alloc
>   tg3: Use new function pci_vpd_check_csum
>   tg3: Use new function pci_vpd_find_ro_info_keyword
> 
>  drivers/net/ethernet/broadcom/tg3.c | 115 +++++++---------------------
>  drivers/net/ethernet/broadcom/tg3.h |   1 -
>  drivers/net/ethernet/sfc/efx.c      |  78 +++++--------------
>  drivers/pci/vpd.c                   |  82 ++++++++++++++++++++
>  include/linux/pci.h                 |  32 ++++++++
>  5 files changed, 163 insertions(+), 145 deletions(-)

Beautiful!  I applied this with minor tweaks to pci/vpd for v5.15.

I dropped the "add missing keywords" patch because there are no users
of the missing keywords yet.

I would have removed pci_vpd_find_info_keyword() as well, but it looks
like there are stilla few users of it.

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH 0/8] PCI/VPD: Extend PCI VPD API
  2021-08-20 20:50 ` [PATCH 0/8] PCI/VPD: Extend PCI VPD API Bjorn Helgaas
@ 2021-08-20 21:36   ` Heiner Kallweit
  0 siblings, 0 replies; 11+ messages in thread
From: Heiner Kallweit @ 2021-08-20 21:36 UTC (permalink / raw)
  To: Bjorn Helgaas
  Cc: Edward Cree, Martin Habets, Siva Reddy Kallam,
	Prashant Sreedharan, Michael Chan, David Miller, Jakub Kicinski,
	linux-pci, netdev

On 20.08.2021 22:50, Bjorn Helgaas wrote:
> On Wed, Aug 18, 2021 at 08:58:18PM +0200, Heiner Kallweit wrote:
>> This series adds three functions to the PCI VPD API that help to
>> simplify driver code. First users are sfc and tg3 drivers because
>> I have test hw. The other users of the VPD API will benefit from a
>> migration as well.
>> I'd propose to apply this series via the PCI tree.
>>
>> Added API calls:
>>
>> pci_vpd_alloc()
>> Dynamically allocates a properly sized buffer and reads the VPD into it.
>>
>> pci_vpd_find_ro_info_keyword()
>> Locates an info field keyword in the VPD RO section.
>> pci_vpd_find_info_keyword() can be removed once all
>> users have been migrated.
>>
>> pci_vpd_check_csum()
>> Check VPD checksum based on algorithm defined in the PCI specification.
>>
>> Tested on a SFN6122F and a BCM95719 card.
>>
>> Heiner Kallweit (8):
>>   PCI/VPD: Add pci_vpd_alloc
>>   PCI/VPD: Add pci_vpd_find_ro_info_keyword and pci_vpd_check_csum
>>   PCI/VPD: Add missing VPD RO field keywords
>>   sfc: Use new function pci_vpd_alloc
>>   sfc: Use new VPD API function pci_vpd_find_ro_info_keyword
>>   tg3: Use new function pci_vpd_alloc
>>   tg3: Use new function pci_vpd_check_csum
>>   tg3: Use new function pci_vpd_find_ro_info_keyword
>>
>>  drivers/net/ethernet/broadcom/tg3.c | 115 +++++++---------------------
>>  drivers/net/ethernet/broadcom/tg3.h |   1 -
>>  drivers/net/ethernet/sfc/efx.c      |  78 +++++--------------
>>  drivers/pci/vpd.c                   |  82 ++++++++++++++++++++
>>  include/linux/pci.h                 |  32 ++++++++
>>  5 files changed, 163 insertions(+), 145 deletions(-)
> 
> Beautiful!  I applied this with minor tweaks to pci/vpd for v5.15.
> 
> I dropped the "add missing keywords" patch because there are no users
> of the missing keywords yet.
> 
Chelsio T4 driver is using this keyword. Then I'll add this keyword
when migrating the driver.

> I would have removed pci_vpd_find_info_keyword() as well, but it looks
> like there are stilla few users of it.
> 
Right, there are few more users. In this initial series I only changed
users for which I have test hw.

^ permalink raw reply	[flat|nested] 11+ messages in thread

end of thread, other threads:[~2021-08-20 21:36 UTC | newest]

Thread overview: 11+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-08-18 18:58 [PATCH 0/8] PCI/VPD: Extend PCI VPD API Heiner Kallweit
2021-08-18 18:59 ` [PATCH 1/8] PCI/VPD: Add pci_vpd_alloc Heiner Kallweit
2021-08-18 19:00 ` [PATCH 2/8] PCI/VPD: Add pci_vpd_find_ro_info_keyword and pci_vpd_check_csum Heiner Kallweit
2021-08-18 19:01 ` [PATCH 3/8] PCI/VPD: Add missing VPD RO field keywords Heiner Kallweit
2021-08-18 19:02 ` [PATCH 4/8] sfc: Use new function pci_vpd_alloc Heiner Kallweit
2021-08-18 19:03 ` [PATCH 5/8] sfc: Use new VPD API function pci_vpd_find_ro_info_keyword Heiner Kallweit
2021-08-18 19:04 ` [PATCH 6/8] tg3: Use new function pci_vpd_alloc Heiner Kallweit
2021-08-18 19:05 ` [PATCH 7/8] tg3: Use new function pci_vpd_check_csum Heiner Kallweit
2021-08-18 19:06 ` [PATCH 8/8] tg3: Use new function pci_vpd_find_ro_info_keyword Heiner Kallweit
2021-08-20 20:50 ` [PATCH 0/8] PCI/VPD: Extend PCI VPD API Bjorn Helgaas
2021-08-20 21:36   ` Heiner Kallweit

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).