aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/net/cxgb4/t4_hw.c41
1 files changed, 21 insertions, 20 deletions
diff --git a/drivers/net/cxgb4/t4_hw.c b/drivers/net/cxgb4/t4_hw.c
index c7fb549776d..b9fd8a6f2cc 100644
--- a/drivers/net/cxgb4/t4_hw.c
+++ b/drivers/net/cxgb4/t4_hw.c
@@ -330,18 +330,6 @@ int t4_edc_read(struct adapter *adap, int idx, u32 addr, __be32 *data, u64 *ecc)
330 return 0; 330 return 0;
331} 331}
332 332
333/*
334 * Partial EEPROM Vital Product Data structure. Includes only the ID and
335 * VPD-R header.
336 */
337struct t4_vpd_hdr {
338 u8 id_tag;
339 u8 id_len[2];
340 u8 id_data[ID_LEN];
341 u8 vpdr_tag;
342 u8 vpdr_len[2];
343};
344
345#define EEPROM_STAT_ADDR 0x7bfc 333#define EEPROM_STAT_ADDR 0x7bfc
346#define VPD_BASE 0 334#define VPD_BASE 0
347#define VPD_LEN 512 335#define VPD_LEN 512
@@ -372,23 +360,36 @@ static int get_vpd_params(struct adapter *adapter, struct vpd_params *p)
372 int i, ret; 360 int i, ret;
373 int ec, sn; 361 int ec, sn;
374 u8 vpd[VPD_LEN], csum; 362 u8 vpd[VPD_LEN], csum;
375 unsigned int vpdr_len; 363 unsigned int vpdr_len, kw_offset, id_len;
376 const struct t4_vpd_hdr *v;
377 364
378 ret = pci_read_vpd(adapter->pdev, VPD_BASE, sizeof(vpd), vpd); 365 ret = pci_read_vpd(adapter->pdev, VPD_BASE, sizeof(vpd), vpd);
379 if (ret < 0) 366 if (ret < 0)
380 return ret; 367 return ret;
381 368
382 v = (const struct t4_vpd_hdr *)vpd; 369 if (vpd[0] != PCI_VPD_LRDT_ID_STRING) {
383 vpdr_len = pci_vpd_lrdt_size(&v->vpdr_tag); 370 dev_err(adapter->pdev_dev, "missing VPD ID string\n");
384 if (vpdr_len + sizeof(struct t4_vpd_hdr) > VPD_LEN) { 371 return -EINVAL;
372 }
373
374 id_len = pci_vpd_lrdt_size(vpd);
375 if (id_len > ID_LEN)
376 id_len = ID_LEN;
377
378 i = pci_vpd_find_tag(vpd, 0, VPD_LEN, PCI_VPD_LRDT_RO_DATA);
379 if (i < 0) {
380 dev_err(adapter->pdev_dev, "missing VPD-R section\n");
381 return -EINVAL;
382 }
383
384 vpdr_len = pci_vpd_lrdt_size(&vpd[i]);
385 kw_offset = i + PCI_VPD_LRDT_TAG_SIZE;
386 if (vpdr_len + kw_offset > VPD_LEN) {
385 dev_err(adapter->pdev_dev, "bad VPD-R length %u\n", vpdr_len); 387 dev_err(adapter->pdev_dev, "bad VPD-R length %u\n", vpdr_len);
386 return -EINVAL; 388 return -EINVAL;
387 } 389 }
388 390
389#define FIND_VPD_KW(var, name) do { \ 391#define FIND_VPD_KW(var, name) do { \
390 var = pci_vpd_find_info_keyword(&v->id_tag, sizeof(struct t4_vpd_hdr), \ 392 var = pci_vpd_find_info_keyword(vpd, kw_offset, vpdr_len, name); \
391 vpdr_len, name); \
392 if (var < 0) { \ 393 if (var < 0) { \
393 dev_err(adapter->pdev_dev, "missing VPD keyword " name "\n"); \ 394 dev_err(adapter->pdev_dev, "missing VPD keyword " name "\n"); \
394 return -EINVAL; \ 395 return -EINVAL; \
@@ -410,7 +411,7 @@ static int get_vpd_params(struct adapter *adapter, struct vpd_params *p)
410 FIND_VPD_KW(sn, "SN"); 411 FIND_VPD_KW(sn, "SN");
411#undef FIND_VPD_KW 412#undef FIND_VPD_KW
412 413
413 memcpy(p->id, v->id_data, ID_LEN); 414 memcpy(p->id, vpd + PCI_VPD_LRDT_TAG_SIZE, id_len);
414 strim(p->id); 415 strim(p->id);
415 memcpy(p->ec, vpd + ec, EC_LEN); 416 memcpy(p->ec, vpd + ec, EC_LEN);
416 strim(p->ec); 417 strim(p->ec);