aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/net/tg3.c125
-rw-r--r--drivers/net/tg3.h2
2 files changed, 83 insertions, 44 deletions
diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c
index 52dd516ba786..10fa476fede3 100644
--- a/drivers/net/tg3.c
+++ b/drivers/net/tg3.c
@@ -10416,6 +10416,81 @@ static void tg3_get_ethtool_stats(struct net_device *dev,
10416 memcpy(tmp_stats, tg3_get_estats(tp), sizeof(tp->estats)); 10416 memcpy(tmp_stats, tg3_get_estats(tp), sizeof(tp->estats));
10417} 10417}
10418 10418
10419static __be32 * tg3_vpd_readblock(struct tg3 *tp)
10420{
10421 int i;
10422 __be32 *buf;
10423 u32 offset = 0, len = 0;
10424 u32 magic, val;
10425
10426 if ((tp->tg3_flags3 & TG3_FLG3_NO_NVRAM) ||
10427 tg3_nvram_read(tp, 0, &magic))
10428 return NULL;
10429
10430 if (magic == TG3_EEPROM_MAGIC) {
10431 for (offset = TG3_NVM_DIR_START;
10432 offset < TG3_NVM_DIR_END;
10433 offset += TG3_NVM_DIRENT_SIZE) {
10434 if (tg3_nvram_read(tp, offset, &val))
10435 return NULL;
10436
10437 if ((val >> TG3_NVM_DIRTYPE_SHIFT) ==
10438 TG3_NVM_DIRTYPE_EXTVPD)
10439 break;
10440 }
10441
10442 if (offset != TG3_NVM_DIR_END) {
10443 len = (val & TG3_NVM_DIRTYPE_LENMSK) * 4;
10444 if (tg3_nvram_read(tp, offset + 4, &offset))
10445 return NULL;
10446
10447 offset = tg3_nvram_logical_addr(tp, offset);
10448 }
10449 }
10450
10451 if (!offset || !len) {
10452 offset = TG3_NVM_VPD_OFF;
10453 len = TG3_NVM_VPD_LEN;
10454 }
10455
10456 buf = kmalloc(len, GFP_KERNEL);
10457 if (buf == NULL)
10458 return NULL;
10459
10460 if (magic == TG3_EEPROM_MAGIC) {
10461 for (i = 0; i < len; i += 4) {
10462 /* The data is in little-endian format in NVRAM.
10463 * Use the big-endian read routines to preserve
10464 * the byte order as it exists in NVRAM.
10465 */
10466 if (tg3_nvram_read_be32(tp, offset + i, &buf[i/4]))
10467 goto error;
10468 }
10469 } else {
10470 u8 *ptr;
10471 ssize_t cnt;
10472 unsigned int pos = 0;
10473
10474 ptr = (u8 *)&buf[0];
10475 for (i = 0; pos < len && i < 3; i++, pos += cnt, ptr += cnt) {
10476 cnt = pci_read_vpd(tp->pdev, pos,
10477 len - pos, ptr);
10478 if (cnt == -ETIMEDOUT || cnt == -EINTR)
10479 cnt = 0;
10480 else if (cnt < 0)
10481 goto error;
10482 }
10483 if (pos != len)
10484 goto error;
10485 }
10486
10487 return buf;
10488
10489error:
10490 kfree(buf);
10491 return NULL;
10492}
10493
10419#define NVRAM_TEST_SIZE 0x100 10494#define NVRAM_TEST_SIZE 0x100
10420#define NVRAM_SELFBOOT_FORMAT1_0_SIZE 0x14 10495#define NVRAM_SELFBOOT_FORMAT1_0_SIZE 0x14
10421#define NVRAM_SELFBOOT_FORMAT1_2_SIZE 0x18 10496#define NVRAM_SELFBOOT_FORMAT1_2_SIZE 0x18
@@ -10555,14 +10630,11 @@ static int tg3_test_nvram(struct tg3 *tp)
10555 if (csum != le32_to_cpu(buf[0xfc/4])) 10630 if (csum != le32_to_cpu(buf[0xfc/4]))
10556 goto out; 10631 goto out;
10557 10632
10558 for (i = 0; i < TG3_NVM_VPD_LEN; i += 4) { 10633 kfree(buf);
10559 /* The data is in little-endian format in NVRAM. 10634
10560 * Use the big-endian read routines to preserve 10635 buf = tg3_vpd_readblock(tp);
10561 * the byte order as it exists in NVRAM. 10636 if (!buf)
10562 */ 10637 return -ENOMEM;
10563 if (tg3_nvram_read_be32(tp, TG3_NVM_VPD_OFF + i, &buf[i/4]))
10564 goto out;
10565 }
10566 10638
10567 i = pci_vpd_find_tag((u8 *)buf, 0, TG3_NVM_VPD_LEN, 10639 i = pci_vpd_find_tag((u8 *)buf, 0, TG3_NVM_VPD_LEN,
10568 PCI_VPD_LRDT_RO_DATA); 10640 PCI_VPD_LRDT_RO_DATA);
@@ -12905,46 +12977,11 @@ static void __devinit tg3_read_vpd(struct tg3 *tp)
12905 u8 *vpd_data; 12977 u8 *vpd_data;
12906 unsigned int block_end, rosize, len; 12978 unsigned int block_end, rosize, len;
12907 int j, i = 0; 12979 int j, i = 0;
12908 u32 magic;
12909
12910 if ((tp->tg3_flags3 & TG3_FLG3_NO_NVRAM) ||
12911 tg3_nvram_read(tp, 0x0, &magic))
12912 goto out_no_vpd;
12913 12980
12914 vpd_data = kmalloc(TG3_NVM_VPD_LEN, GFP_KERNEL); 12981 vpd_data = (u8 *)tg3_vpd_readblock(tp);
12915 if (!vpd_data) 12982 if (!vpd_data)
12916 goto out_no_vpd; 12983 goto out_no_vpd;
12917 12984
12918 if (magic == TG3_EEPROM_MAGIC) {
12919 for (i = 0; i < TG3_NVM_VPD_LEN; i += 4) {
12920 u32 tmp;
12921
12922 /* The data is in little-endian format in NVRAM.
12923 * Use the big-endian read routines to preserve
12924 * the byte order as it exists in NVRAM.
12925 */
12926 if (tg3_nvram_read_be32(tp, TG3_NVM_VPD_OFF + i, &tmp))
12927 goto out_not_found;
12928
12929 memcpy(&vpd_data[i], &tmp, sizeof(tmp));
12930 }
12931 } else {
12932 ssize_t cnt;
12933 unsigned int pos = 0;
12934
12935 for (; pos < TG3_NVM_VPD_LEN && i < 3; i++, pos += cnt) {
12936 cnt = pci_read_vpd(tp->pdev, pos,
12937 TG3_NVM_VPD_LEN - pos,
12938 &vpd_data[pos]);
12939 if (cnt == -ETIMEDOUT || cnt == -EINTR)
12940 cnt = 0;
12941 else if (cnt < 0)
12942 goto out_not_found;
12943 }
12944 if (pos != TG3_NVM_VPD_LEN)
12945 goto out_not_found;
12946 }
12947
12948 i = pci_vpd_find_tag(vpd_data, 0, TG3_NVM_VPD_LEN, 12985 i = pci_vpd_find_tag(vpd_data, 0, TG3_NVM_VPD_LEN,
12949 PCI_VPD_LRDT_RO_DATA); 12986 PCI_VPD_LRDT_RO_DATA);
12950 if (i < 0) 12987 if (i < 0)
diff --git a/drivers/net/tg3.h b/drivers/net/tg3.h
index b3ccfcc9ffea..224c3e0ec695 100644
--- a/drivers/net/tg3.h
+++ b/drivers/net/tg3.h
@@ -2009,7 +2009,9 @@
2009#define TG3_NVM_DIR_END 0x78 2009#define TG3_NVM_DIR_END 0x78
2010#define TG3_NVM_DIRENT_SIZE 0xc 2010#define TG3_NVM_DIRENT_SIZE 0xc
2011#define TG3_NVM_DIRTYPE_SHIFT 24 2011#define TG3_NVM_DIRTYPE_SHIFT 24
2012#define TG3_NVM_DIRTYPE_LENMSK 0x003fffff
2012#define TG3_NVM_DIRTYPE_ASFINI 1 2013#define TG3_NVM_DIRTYPE_ASFINI 1
2014#define TG3_NVM_DIRTYPE_EXTVPD 20
2013#define TG3_NVM_PTREV_BCVER 0x94 2015#define TG3_NVM_PTREV_BCVER 0x94
2014#define TG3_NVM_BCVER_MAJMSK 0x0000ff00 2016#define TG3_NVM_BCVER_MAJMSK 0x0000ff00
2015#define TG3_NVM_BCVER_MAJSFT 8 2017#define TG3_NVM_BCVER_MAJSFT 8