Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

Michael Chan and committed by
David S. Miller
76d99061 b929e53c

+99 -3
+99 -3
drivers/net/bnx2.c
··· 7722 7722 7723 7723 } 7724 7724 7725 + static void __devinit 7726 + bnx2_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 + 7808 + vpd_done: 7809 + kfree(data); 7810 + } 7811 + 7725 7812 static int __devinit 7726 7813 bnx2_init_board(struct pci_dev *pdev, struct net_device *dev) 7727 7814 { ··· 7982 7895 goto err_out_unmap; 7983 7896 } 7984 7897 7898 + bnx2_read_vpd_fw_ver(bp); 7899 + 7900 + j = strlen(bp->fw_version); 7985 7901 reg = bnx2_shmem_rd(bp, BNX2_DEV_INFO_BC_REV); 7986 - for (i = 0, j = 0; i < 3; i++) { 7902 + for (i = 0; i < 3 && j < 24; i++) { 7987 7903 u8 num, k, skip0; 7988 7904 7905 + if (i == 0) { 7906 + bp->fw_version[j++] = 'b'; 7907 + bp->fw_version[j++] = 'c'; 7908 + bp->fw_version[j++] = ' '; 7909 + } 7989 7910 num = (u8) (reg >> (24 - (i * 8))); 7990 7911 for (k = 100, skip0 = 1; k >= 1; num %= k, k /= 10) { 7991 7912 if (num >= k || !skip0 || k == 1) { ··· 8024 7929 reg != BNX2_CONDITION_MFW_RUN_NONE) { 8025 7930 u32 addr = bnx2_shmem_rd(bp, BNX2_MFW_VER_PTR); 8026 7931 8027 - bp->fw_version[j++] = ' '; 8028 - for (i = 0; i < 3; i++) { 7932 + if (j < 32) 7933 + bp->fw_version[j++] = ' '; 7934 + for (i = 0; i < 3 && j < 28; i++) { 8029 7935 reg = bnx2_reg_rd_ind(bp, addr + i * 4); 8030 7936 reg = swab32(reg); 8031 7937 memcpy(&bp->fw_version[j], &reg, 4);