Oliver Neukum b2480c
From 6107e5cb907cffc5576cc1297847f9fc69a8d5d9 Mon Sep 17 00:00:00 2001
Oliver Neukum b2480c
From: Heiner Kallweit <hkallweit1@gmail.com>
Oliver Neukum b2480c
Date: Fri, 20 Aug 2021 15:32:42 -0500
Oliver Neukum b2480c
Subject: [PATCH] PCI/VPD: Add pci_vpd_check_csum()
Oliver Neukum b2480c
Git-commit: 6107e5cb907cffc5576cc1297847f9fc69a8d5d9
Oliver Neukum b2480c
References: git-fixes
Oliver Neukum b2480c
Patch-mainline: v5.15-rc1
Oliver Neukum b2480c
Oliver Neukum b2480c
VPD checksum information and checksum calculation are specified by PCIe
Oliver Neukum b2480c
r5.0, sec 6.28.2.2.  Therefore checksum handling can and should be moved
Oliver Neukum b2480c
into the PCI VPD core.
Oliver Neukum b2480c
Oliver Neukum b2480c
Add pci_vpd_check_csum() to validate the VPD checksum.
Oliver Neukum b2480c
Oliver Neukum b2480c
[bhelgaas: split to separate patch]
Oliver Neukum b2480c
Link: https://lore.kernel.org/r/1643bd7a-088e-1028-c9b0-9d112cf48d63@gmail.com
Oliver Neukum b2480c
Signed-off-by: Heiner Kallweit <hkallweit1@gmail.com>
Oliver Neukum b2480c
Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
Oliver Neukum b2480c
Signed-off-by: Oliver Neukum <oneukum@suse.com>
Oliver Neukum b2480c
---
Oliver Neukum b2480c
 drivers/pci/vpd.c   | 23 +++++++++++++++++++++++
Oliver Neukum b2480c
 include/linux/pci.h |  9 +++++++++
Oliver Neukum b2480c
 2 files changed, 32 insertions(+)
Oliver Neukum b2480c
Oliver Neukum b2480c
diff --git a/drivers/pci/vpd.c b/drivers/pci/vpd.c
Oliver Neukum b2480c
index b1d012900f1e..01e57594781e 100644
Oliver Neukum b2480c
--- a/drivers/pci/vpd.c
Oliver Neukum b2480c
+++ b/drivers/pci/vpd.c
Oliver Neukum b2480c
@@ -413,6 +413,29 @@ int pci_vpd_find_ro_info_keyword(const void *buf, unsigned int len,
Oliver Neukum b2480c
 }
Oliver Neukum b2480c
 EXPORT_SYMBOL_GPL(pci_vpd_find_ro_info_keyword);
Oliver Neukum b2480c
 
Oliver Neukum b2480c
+int pci_vpd_check_csum(const void *buf, unsigned int len)
Oliver Neukum b2480c
+{
Oliver Neukum b2480c
+	const u8 *vpd = buf;
Oliver Neukum b2480c
+	unsigned int size;
Oliver Neukum b2480c
+	u8 csum = 0;
Oliver Neukum b2480c
+	int rv_start;
Oliver Neukum b2480c
+
Oliver Neukum b2480c
+	rv_start = pci_vpd_find_ro_info_keyword(buf, len, PCI_VPD_RO_KEYWORD_CHKSUM, &size);
Oliver Neukum b2480c
+	if (rv_start == -ENOENT) /* no checksum in VPD */
Oliver Neukum b2480c
+		return 1;
Oliver Neukum b2480c
+	else if (rv_start < 0)
Oliver Neukum b2480c
+		return rv_start;
Oliver Neukum b2480c
+
Oliver Neukum b2480c
+	if (!size)
Oliver Neukum b2480c
+		return -EINVAL;
Oliver Neukum b2480c
+
Oliver Neukum b2480c
+	while (rv_start >= 0)
Oliver Neukum b2480c
+		csum += vpd[rv_start--];
Oliver Neukum b2480c
+
Oliver Neukum b2480c
+	return csum ? -EILSEQ : 0;
Oliver Neukum b2480c
+}
Oliver Neukum b2480c
+EXPORT_SYMBOL_GPL(pci_vpd_check_csum);
Oliver Neukum b2480c
+
Oliver Neukum b2480c
 #ifdef CONFIG_PCI_QUIRKS
Oliver Neukum b2480c
 /*
Oliver Neukum b2480c
  * Quirk non-zero PCI functions to route VPD access through function 0 for
Oliver Neukum b2480c
diff --git a/include/linux/pci.h b/include/linux/pci.h
Oliver Neukum b2480c
index 9e3b60963a52..827b7eefd550 100644
Oliver Neukum b2480c
--- a/include/linux/pci.h
Oliver Neukum b2480c
+++ b/include/linux/pci.h
Oliver Neukum b2480c
@@ -2376,6 +2376,15 @@ int pci_vpd_find_info_keyword(const u8 *buf, unsigned int off,
Oliver Neukum b2480c
 int pci_vpd_find_ro_info_keyword(const void *buf, unsigned int len,
Oliver Neukum b2480c
 				 const char *kw, unsigned int *size);
Oliver Neukum b2480c
 
Oliver Neukum b2480c
+/**
Oliver Neukum b2480c
+ * pci_vpd_check_csum - Check VPD checksum
Oliver Neukum b2480c
+ * @buf: Pointer to buffered VPD data
Oliver Neukum b2480c
+ * @len: VPD size
Oliver Neukum b2480c
+ *
Oliver Neukum b2480c
+ * Returns 1 if VPD has no checksum, otherwise 0 or an errno
Oliver Neukum b2480c
+ */
Oliver Neukum b2480c
+int pci_vpd_check_csum(const void *buf, unsigned int len);
Oliver Neukum b2480c
+
Oliver Neukum b2480c
 /* PCI <-> OF binding helpers */
Oliver Neukum b2480c
 #ifdef CONFIG_OF
Oliver Neukum b2480c
 struct device_node;
Oliver Neukum b2480c
-- 
Oliver Neukum b2480c
2.26.2
Oliver Neukum b2480c