Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 23d88e1d authored by Dimitris Michailidis's avatar Dimitris Michailidis Committed by David S. Miller
Browse files

cxgb4: extend VPD parsing



Current code parses the VPD RO section for keywords but makes static
assumptions about the location of the section.  Remove them and parse
the VPD to find it.

Signed-off-by: default avatarDimitris Michailidis <dm@chelsio.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 005b5717
Loading
Loading
Loading
Loading
+21 −20
Original line number Original line Diff line number Diff line
@@ -330,18 +330,6 @@ int t4_edc_read(struct adapter *adap, int idx, u32 addr, __be32 *data, u64 *ecc)
	return 0;
	return 0;
}
}


/*
 * Partial EEPROM Vital Product Data structure.  Includes only the ID and
 * VPD-R header.
 */
struct t4_vpd_hdr {
	u8  id_tag;
	u8  id_len[2];
	u8  id_data[ID_LEN];
	u8  vpdr_tag;
	u8  vpdr_len[2];
};

#define EEPROM_STAT_ADDR   0x7bfc
#define EEPROM_STAT_ADDR   0x7bfc
#define VPD_BASE           0
#define VPD_BASE           0
#define VPD_LEN            512
#define VPD_LEN            512
@@ -372,23 +360,36 @@ static int get_vpd_params(struct adapter *adapter, struct vpd_params *p)
	int i, ret;
	int i, ret;
	int ec, sn;
	int ec, sn;
	u8 vpd[VPD_LEN], csum;
	u8 vpd[VPD_LEN], csum;
	unsigned int vpdr_len;
	unsigned int vpdr_len, kw_offset, id_len;
	const struct t4_vpd_hdr *v;


	ret = pci_read_vpd(adapter->pdev, VPD_BASE, sizeof(vpd), vpd);
	ret = pci_read_vpd(adapter->pdev, VPD_BASE, sizeof(vpd), vpd);
	if (ret < 0)
	if (ret < 0)
		return ret;
		return ret;


	v = (const struct t4_vpd_hdr *)vpd;
	if (vpd[0] != PCI_VPD_LRDT_ID_STRING) {
	vpdr_len = pci_vpd_lrdt_size(&v->vpdr_tag);
		dev_err(adapter->pdev_dev, "missing VPD ID string\n");
	if (vpdr_len + sizeof(struct t4_vpd_hdr) > VPD_LEN) {
		return -EINVAL;
	}

	id_len = pci_vpd_lrdt_size(vpd);
	if (id_len > ID_LEN)
		id_len = ID_LEN;

	i = pci_vpd_find_tag(vpd, 0, VPD_LEN, PCI_VPD_LRDT_RO_DATA);
	if (i < 0) {
		dev_err(adapter->pdev_dev, "missing VPD-R section\n");
		return -EINVAL;
	}

	vpdr_len = pci_vpd_lrdt_size(&vpd[i]);
	kw_offset = i + PCI_VPD_LRDT_TAG_SIZE;
	if (vpdr_len + kw_offset > VPD_LEN) {
		dev_err(adapter->pdev_dev, "bad VPD-R length %u\n", vpdr_len);
		dev_err(adapter->pdev_dev, "bad VPD-R length %u\n", vpdr_len);
		return -EINVAL;
		return -EINVAL;
	}
	}


#define FIND_VPD_KW(var, name) do { \
#define FIND_VPD_KW(var, name) do { \
	var = pci_vpd_find_info_keyword(&v->id_tag, sizeof(struct t4_vpd_hdr), \
	var = pci_vpd_find_info_keyword(vpd, kw_offset, vpdr_len, name); \
					vpdr_len, name); \
	if (var < 0) { \
	if (var < 0) { \
		dev_err(adapter->pdev_dev, "missing VPD keyword " name "\n"); \
		dev_err(adapter->pdev_dev, "missing VPD keyword " name "\n"); \
		return -EINVAL; \
		return -EINVAL; \
@@ -410,7 +411,7 @@ static int get_vpd_params(struct adapter *adapter, struct vpd_params *p)
	FIND_VPD_KW(sn, "SN");
	FIND_VPD_KW(sn, "SN");
#undef FIND_VPD_KW
#undef FIND_VPD_KW


	memcpy(p->id, v->id_data, ID_LEN);
	memcpy(p->id, vpd + PCI_VPD_LRDT_TAG_SIZE, id_len);
	strim(p->id);
	strim(p->id);
	memcpy(p->ec, vpd + ec, EC_LEN);
	memcpy(p->ec, vpd + ec, EC_LEN);
	strim(p->ec);
	strim(p->ec);