diff options
Diffstat (limited to 'drivers/net/cxgb4')
-rw-r--r-- | drivers/net/cxgb4/t4_hw.c | 41 |
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 | */ | ||
337 | struct 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); |