aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/bnx2.c
diff options
context:
space:
mode:
authorMichael Chan <mchan@broadcom.com>2009-12-03 04:46:34 -0500
committerDavid S. Miller <davem@davemloft.net>2009-12-03 16:18:13 -0500
commit76d9906170259b581691c3cec6bc5d4ab3aaaede (patch)
treeba70b891341fe7e3c3a4b2c014cf2e64c313d465 /drivers/net/bnx2.c
parentb929e53cb7796a8abe47174dfdfdf90cbb65a8bf (diff)
bnx2: Read firmware version from VPD.
And display it through ethtool -i. Signed-off-by: Michael Chan <mchan@broadcom.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/bnx2.c')
-rw-r--r--drivers/net/bnx2.c102
1 files changed, 99 insertions, 3 deletions
diff --git a/drivers/net/bnx2.c b/drivers/net/bnx2.c
index dba3840d7df9..b7bc74b0d1b6 100644
--- a/drivers/net/bnx2.c
+++ b/drivers/net/bnx2.c
@@ -7722,6 +7722,93 @@ bnx2_get_pci_speed(struct bnx2 *bp)
7722 7722
7723} 7723}
7724 7724
7725static void __devinit
7726bnx2_read_vpd_fw_ver(struct bnx2 *bp)
7727{
7728 int rc, i, v0_len = 0;
7729 u8 *data;
7730 u8 *v0_str = NULL;
7731 bool mn_match = false;
7732
7733#define BNX2_MAX_VER_SLEN 30
7734
7735 data = kmalloc(256, GFP_KERNEL);
7736 if (!data)
7737 return;
7738
7739 rc = bnx2_nvram_read(bp, 0x300, data + 128, 128);
7740 if (rc)
7741 goto vpd_done;
7742
7743 for (i = 0; i < 128; i += 4) {
7744 data[i] = data[i + 131];
7745 data[i + 1] = data[i + 130];
7746 data[i + 2] = data[i + 129];
7747 data[i + 3] = data[i + 128];
7748 }
7749
7750 for (i = 0; i < 128; ) {
7751 unsigned char val = data[i];
7752 unsigned int block_end;
7753
7754 if (val == 0x82 || val == 0x91) {
7755 i = (i + 3 + (data[i + 1] + (data[i + 2] << 8)));
7756 continue;
7757 }
7758
7759 if (val != 0x90)
7760 goto vpd_done;
7761
7762 block_end = (i + 3 + (data[i + 1] + (data[i + 2] << 8)));
7763 i += 3;
7764
7765 if (block_end > 128)
7766 goto vpd_done;
7767
7768 while (i < (block_end - 2)) {
7769 if (data[i] == 'M' && data[i + 1] == 'N') {
7770 int mn_len = data[i + 2];
7771
7772 if (mn_len != 4)
7773 goto vpd_done;
7774
7775 i += 3;
7776 if (memcmp(&data[i], "1028", 4))
7777 goto vpd_done;
7778 mn_match = true;
7779 i += 4;
7780
7781 } else if (data[i] == 'V' && data[i + 1] == '0') {
7782 v0_len = data[i + 2];
7783
7784 i += 3;
7785 if (v0_len > BNX2_MAX_VER_SLEN ||
7786 (v0_len + i) > 128)
7787 goto vpd_done;
7788
7789 if (v0_len > BNX2_MAX_VER_SLEN)
7790 v0_len = BNX2_MAX_VER_SLEN;
7791
7792 v0_str = &data[i];
7793 i += data[i + 2];
7794
7795 } else {
7796 i += 3 + data[i + 2];
7797 }
7798
7799 if (mn_match && v0_str) {
7800 memcpy(bp->fw_version, v0_str, v0_len);
7801 bp->fw_version[v0_len] = ' ';
7802 goto vpd_done;
7803 }
7804 }
7805 goto vpd_done;
7806 }
7807
7808vpd_done:
7809 kfree(data);
7810}
7811
7725static int __devinit 7812static int __devinit
7726bnx2_init_board(struct pci_dev *pdev, struct net_device *dev) 7813bnx2_init_board(struct pci_dev *pdev, struct net_device *dev)
7727{ 7814{
@@ -7895,10 +7982,18 @@ bnx2_init_board(struct pci_dev *pdev, struct net_device *dev)
7895 goto err_out_unmap; 7982 goto err_out_unmap;
7896 } 7983 }
7897 7984
7985 bnx2_read_vpd_fw_ver(bp);
7986
7987 j = strlen(bp->fw_version);
7898 reg = bnx2_shmem_rd(bp, BNX2_DEV_INFO_BC_REV); 7988 reg = bnx2_shmem_rd(bp, BNX2_DEV_INFO_BC_REV);
7899 for (i = 0, j = 0; i < 3; i++) { 7989 for (i = 0; i < 3 && j < 24; i++) {
7900 u8 num, k, skip0; 7990 u8 num, k, skip0;
7901 7991
7992 if (i == 0) {
7993 bp->fw_version[j++] = 'b';
7994 bp->fw_version[j++] = 'c';
7995 bp->fw_version[j++] = ' ';
7996 }
7902 num = (u8) (reg >> (24 - (i * 8))); 7997 num = (u8) (reg >> (24 - (i * 8)));
7903 for (k = 100, skip0 = 1; k >= 1; num %= k, k /= 10) { 7998 for (k = 100, skip0 = 1; k >= 1; num %= k, k /= 10) {
7904 if (num >= k || !skip0 || k == 1) { 7999 if (num >= k || !skip0 || k == 1) {
@@ -7929,8 +8024,9 @@ bnx2_init_board(struct pci_dev *pdev, struct net_device *dev)
7929 reg != BNX2_CONDITION_MFW_RUN_NONE) { 8024 reg != BNX2_CONDITION_MFW_RUN_NONE) {
7930 u32 addr = bnx2_shmem_rd(bp, BNX2_MFW_VER_PTR); 8025 u32 addr = bnx2_shmem_rd(bp, BNX2_MFW_VER_PTR);
7931 8026
7932 bp->fw_version[j++] = ' '; 8027 if (j < 32)
7933 for (i = 0; i < 3; i++) { 8028 bp->fw_version[j++] = ' ';
8029 for (i = 0; i < 3 && j < 28; i++) {
7934 reg = bnx2_reg_rd_ind(bp, addr + i * 4); 8030 reg = bnx2_reg_rd_ind(bp, addr + i * 4);
7935 reg = swab32(reg); 8031 reg = swab32(reg);
7936 memcpy(&bp->fw_version[j], &reg, 4); 8032 memcpy(&bp->fw_version[j], &reg, 4);