diff options
-rw-r--r-- | drivers/net/tg3.c | 125 | ||||
-rw-r--r-- | drivers/net/tg3.h | 2 |
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 | ||
10419 | static __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 | |||
10489 | error: | ||
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 |