aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/cxgb4
diff options
context:
space:
mode:
authorDimitris Michailidis <dm@chelsio.com>2010-12-14 16:36:54 -0500
committerDavid S. Miller <davem@davemloft.net>2010-12-16 16:16:04 -0500
commit23d88e1d3e4a5b807ce6725f9294b7b9dfcd89a1 (patch)
tree09d5e7a5d61fbfb8deace982bdcc04a2cb71bbc0 /drivers/net/cxgb4
parent005b5717faac22264c1f61908ec5ac5b98108d99 (diff)
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: Dimitris Michailidis <dm@chelsio.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/cxgb4')
-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 c7fb549776dc..b9fd8a6f2cc4 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);