aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBarak Witkowski <barak@broadcom.com>2011-12-13 19:14:53 -0500
committerDavid S. Miller <davem@davemloft.net>2011-12-14 13:34:55 -0500
commitfcdf95cb293603acdff910715c8aa2b19ed29df4 (patch)
tree72b72297bce28f095fc1630fc48dd2387f9de55a
parentde93cb2eaffd6d3e44bc738babfac35769d79720 (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.c35
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)
9931static void __devinit bnx2x_read_fwinfo(struct bnx2x *bp) 9931static 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 }
9991out_not_found: 10011out_not_found:
10012 kfree(vpd_extended_data);
9992 return; 10013 return;
9993} 10014}
9994 10015