From: Valentine Fatiev <valentinef@nvidia.com>
Subject: [PATCH] BACKPORT: drivers/infiniband/hw/mlx5/data_direct.c

Change-Id: I7f59f031f1fb00a5211bc9ac6cd7741dd6fc3f2b
---
 drivers/infiniband/hw/mlx5/data_direct.c | 57 +++++++++++++++++++++++-
 1 file changed, 56 insertions(+), 1 deletion(-)

--- a/drivers/infiniband/hw/mlx5/data_direct.c
+++ b/drivers/infiniband/hw/mlx5/data_direct.c
@@ -25,19 +25,80 @@ static const struct pci_device_id mlx5_d
 	{ 0, }
 };
 
+#ifndef HAVE_PCI_VPD_ALLOC
+static 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;
+
+#ifdef HAVE_PCI_VPD_FIND_TAG_GET_4_PARAM
+	ro_start = pci_vpd_find_tag(buf, 0, len, PCI_VPD_LRDT_RO_DATA);
+#else
+	ro_start = pci_vpd_find_tag(buf, len, PCI_VPD_LRDT_RO_DATA);
+#endif
+	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;
+}
+#endif
+
+#ifndef HAVE_PCI_VPD_ALLOC
+#define MLX5_VPD_LEN 1024
+#endif
 static int mlx5_data_direct_vpd_get_vuid(struct mlx5_data_direct_dev *dev)
 {
 	struct pci_dev *pdev = dev->pdev;
-	unsigned int vpd_size, kw_len;
+	unsigned int kw_len;
+#ifdef HAVE_PCI_VPD_ALLOC
+	unsigned int vpd_size;
+#else
+	ssize_t vpd_size;
+#endif
 	u8 *vpd_data;
 	int start;
 	int ret;
 
+#ifdef HAVE_PCI_VPD_ALLOC
 	vpd_data = pci_vpd_alloc(pdev, &vpd_size);
 	if (IS_ERR(vpd_data)) {
 		pci_err(pdev, "Unable to read VPD, err=%ld\n", PTR_ERR(vpd_data));
 		return PTR_ERR(vpd_data);
 	}
+#else
+	vpd_data = kmalloc(MLX5_VPD_LEN, GFP_KERNEL);
+	if (!vpd_data)
+		return -ENOMEM;
+#endif
+
+#ifndef HAVE_PCI_VPD_ALLOC
+	vpd_size = pci_read_vpd(pdev, 0, MLX5_VPD_LEN, vpd_data);
+	if (vpd_size <= 0) {
+		pci_err(pdev, "Unable to read VPD\n");
+		ret = -ENOMEM;
+		goto end;
+	}
+#endif
 
 	start = pci_vpd_find_ro_info_keyword(vpd_data, vpd_size, "VU", &kw_len);
 	if (start < 0) {
