Blob Blame History Raw
From 6107e5cb907cffc5576cc1297847f9fc69a8d5d9 Mon Sep 17 00:00:00 2001
From: Heiner Kallweit <hkallweit1@gmail.com>
Date: Fri, 20 Aug 2021 15:32:42 -0500
Subject: [PATCH] PCI/VPD: Add pci_vpd_check_csum()
Git-commit: 6107e5cb907cffc5576cc1297847f9fc69a8d5d9
References: git-fixes
Patch-mainline: v5.15-rc1

VPD checksum information and checksum calculation are specified by PCIe
r5.0, sec 6.28.2.2.  Therefore checksum handling can and should be moved
into the PCI VPD core.

Add pci_vpd_check_csum() to validate the VPD checksum.

[bhelgaas: split 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>
Signed-off-by: Oliver Neukum <oneukum@suse.com>
---
 drivers/pci/vpd.c   | 23 +++++++++++++++++++++++
 include/linux/pci.h |  9 +++++++++
 2 files changed, 32 insertions(+)

diff --git a/drivers/pci/vpd.c b/drivers/pci/vpd.c
index b1d012900f1e..01e57594781e 100644
--- a/drivers/pci/vpd.c
+++ b/drivers/pci/vpd.c
@@ -413,6 +413,29 @@ int pci_vpd_find_ro_info_keyword(const void *buf, unsigned int len,
 }
 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 9e3b60963a52..827b7eefd550 100644
--- a/include/linux/pci.h
+++ b/include/linux/pci.h
@@ -2376,6 +2376,15 @@ int pci_vpd_find_info_keyword(const u8 *buf, unsigned int off,
 int pci_vpd_find_ro_info_keyword(const void *buf, unsigned int len,
 				 const char *kw, unsigned int *size);
 
+/**
+ * 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 <-> OF binding helpers */
 #ifdef CONFIG_OF
 struct device_node;
-- 
2.26.2