diff options
author | Barak Witkowski <barak@broadcom.com> | 2011-12-13 19:14:53 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2011-12-14 13:34:55 -0500 |
commit | fcdf95cb293603acdff910715c8aa2b19ed29df4 (patch) | |
tree | 72b72297bce28f095fc1630fc48dd2387f9de55a | |
parent | de93cb2eaffd6d3e44bc738babfac35769d79720 (diff) |
bnx2x: handle vpd data longer than 128 bytes
Signed-off-by: Barak Witkowski <barak@broadcom.com>
Signed-off-by: Eilon Greenstein <eilong@broadcom.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c | 35 |
1 files changed, 28 insertions, 7 deletions
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c index b45baf99a959..ffeaaa95ed96 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c | |||
@@ -9931,30 +9931,49 @@ static int __devinit bnx2x_get_hwinfo(struct bnx2x *bp) | |||
9931 | static void __devinit bnx2x_read_fwinfo(struct bnx2x *bp) | 9931 | static void __devinit bnx2x_read_fwinfo(struct bnx2x *bp) |
9932 | { | 9932 | { |
9933 | int cnt, i, block_end, rodi; | 9933 | int cnt, i, block_end, rodi; |
9934 | char vpd_data[BNX2X_VPD_LEN+1]; | 9934 | char vpd_start[BNX2X_VPD_LEN+1]; |
9935 | char str_id_reg[VENDOR_ID_LEN+1]; | 9935 | char str_id_reg[VENDOR_ID_LEN+1]; |
9936 | char str_id_cap[VENDOR_ID_LEN+1]; | 9936 | char str_id_cap[VENDOR_ID_LEN+1]; |
9937 | char *vpd_data; | ||
9938 | char *vpd_extended_data = NULL; | ||
9937 | u8 len; | 9939 | u8 len; |
9938 | 9940 | ||
9939 | cnt = pci_read_vpd(bp->pdev, 0, BNX2X_VPD_LEN, vpd_data); | 9941 | cnt = pci_read_vpd(bp->pdev, 0, BNX2X_VPD_LEN, vpd_start); |
9940 | memset(bp->fw_ver, 0, sizeof(bp->fw_ver)); | 9942 | memset(bp->fw_ver, 0, sizeof(bp->fw_ver)); |
9941 | 9943 | ||
9942 | if (cnt < BNX2X_VPD_LEN) | 9944 | if (cnt < BNX2X_VPD_LEN) |
9943 | goto out_not_found; | 9945 | goto out_not_found; |
9944 | 9946 | ||
9945 | i = pci_vpd_find_tag(vpd_data, 0, BNX2X_VPD_LEN, | 9947 | /* VPD RO tag should be first tag after identifier string, hence |
9948 | * we should be able to find it in first BNX2X_VPD_LEN chars | ||
9949 | */ | ||
9950 | i = pci_vpd_find_tag(vpd_start, 0, BNX2X_VPD_LEN, | ||
9946 | PCI_VPD_LRDT_RO_DATA); | 9951 | PCI_VPD_LRDT_RO_DATA); |
9947 | if (i < 0) | 9952 | if (i < 0) |
9948 | goto out_not_found; | 9953 | goto out_not_found; |
9949 | 9954 | ||
9950 | |||
9951 | block_end = i + PCI_VPD_LRDT_TAG_SIZE + | 9955 | block_end = i + PCI_VPD_LRDT_TAG_SIZE + |
9952 | pci_vpd_lrdt_size(&vpd_data[i]); | 9956 | pci_vpd_lrdt_size(&vpd_start[i]); |
9953 | 9957 | ||
9954 | i += PCI_VPD_LRDT_TAG_SIZE; | 9958 | i += PCI_VPD_LRDT_TAG_SIZE; |
9955 | 9959 | ||
9956 | if (block_end > BNX2X_VPD_LEN) | 9960 | if (block_end > BNX2X_VPD_LEN) { |
9957 | goto out_not_found; | 9961 | vpd_extended_data = kmalloc(block_end, GFP_KERNEL); |
9962 | if (vpd_extended_data == NULL) | ||
9963 | goto out_not_found; | ||
9964 | |||
9965 | /* read rest of vpd image into vpd_extended_data */ | ||
9966 | memcpy(vpd_extended_data, vpd_start, BNX2X_VPD_LEN); | ||
9967 | cnt = pci_read_vpd(bp->pdev, BNX2X_VPD_LEN, | ||
9968 | block_end - BNX2X_VPD_LEN, | ||
9969 | vpd_extended_data + BNX2X_VPD_LEN); | ||
9970 | if (cnt < (block_end - BNX2X_VPD_LEN)) | ||
9971 | goto out_not_found; | ||
9972 | vpd_data = vpd_extended_data; | ||
9973 | } else | ||
9974 | vpd_data = vpd_start; | ||
9975 | |||
9976 | /* now vpd_data holds full vpd content in both cases */ | ||
9958 | 9977 | ||
9959 | rodi = pci_vpd_find_info_keyword(vpd_data, i, block_end, | 9978 | rodi = pci_vpd_find_info_keyword(vpd_data, i, block_end, |
9960 | PCI_VPD_RO_KEYWORD_MFR_ID); | 9979 | PCI_VPD_RO_KEYWORD_MFR_ID); |
@@ -9986,9 +10005,11 @@ static void __devinit bnx2x_read_fwinfo(struct bnx2x *bp) | |||
9986 | bp->fw_ver[len] = ' '; | 10005 | bp->fw_ver[len] = ' '; |
9987 | } | 10006 | } |
9988 | } | 10007 | } |
10008 | kfree(vpd_extended_data); | ||
9989 | return; | 10009 | return; |
9990 | } | 10010 | } |
9991 | out_not_found: | 10011 | out_not_found: |
10012 | kfree(vpd_extended_data); | ||
9992 | return; | 10013 | return; |
9993 | } | 10014 | } |
9994 | 10015 | ||