aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/qlcnic/qlcnic_init.c
diff options
context:
space:
mode:
authoramit salecha <amit.salecha@qlogic.com>2011-01-09 19:15:21 -0500
committerDavid S. Miller <davem@davemloft.net>2011-01-10 16:34:54 -0500
commit0e5f20b656c14d91efe61240d44b6f4b53ea939e (patch)
tree922d04e0def9723cae63d8a0de1daa77d9bf2c94 /drivers/net/qlcnic/qlcnic_init.c
parentfacb4edc1e0e849ea98e147a821e60d6d6272c0a (diff)
qlcnic: fix flash fw version read
Driver is reading flash fw version from defined address, this address may be invalid. Indeed Driver should read address for fw version through flash layout table. Flash layout table has defined region and address for fw version address should be read from fw image region. Driver has check for old firmware, this bug can cause driver load fail. This patch will try to read fw version from flash image region, if that fails, read from defined address. Signed-off-by: Amit Kumar Salecha <amit.salecha@qlogic.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/qlcnic/qlcnic_init.c')
-rw-r--r--drivers/net/qlcnic/qlcnic_init.c63
1 files changed, 62 insertions, 1 deletions
diff --git a/drivers/net/qlcnic/qlcnic_init.c b/drivers/net/qlcnic/qlcnic_init.c
index 9b9c7c39d3ee..a7f1d5b7e811 100644
--- a/drivers/net/qlcnic/qlcnic_init.c
+++ b/drivers/net/qlcnic/qlcnic_init.c
@@ -627,12 +627,73 @@ qlcnic_setup_idc_param(struct qlcnic_adapter *adapter) {
627 return 0; 627 return 0;
628} 628}
629 629
630static int qlcnic_get_flt_entry(struct qlcnic_adapter *adapter, u8 region,
631 struct qlcnic_flt_entry *region_entry)
632{
633 struct qlcnic_flt_header flt_hdr;
634 struct qlcnic_flt_entry *flt_entry;
635 int i = 0, ret;
636 u32 entry_size;
637
638 memset(region_entry, 0, sizeof(struct qlcnic_flt_entry));
639 ret = qlcnic_rom_fast_read_words(adapter, QLCNIC_FLT_LOCATION,
640 (u8 *)&flt_hdr,
641 sizeof(struct qlcnic_flt_header));
642 if (ret) {
643 dev_warn(&adapter->pdev->dev,
644 "error reading flash layout header\n");
645 return -EIO;
646 }
647
648 entry_size = flt_hdr.len - sizeof(struct qlcnic_flt_header);
649 flt_entry = (struct qlcnic_flt_entry *)vzalloc(entry_size);
650 if (flt_entry == NULL) {
651 dev_warn(&adapter->pdev->dev, "error allocating memory\n");
652 return -EIO;
653 }
654
655 ret = qlcnic_rom_fast_read_words(adapter, QLCNIC_FLT_LOCATION +
656 sizeof(struct qlcnic_flt_header),
657 (u8 *)flt_entry, entry_size);
658 if (ret) {
659 dev_warn(&adapter->pdev->dev,
660 "error reading flash layout entries\n");
661 goto err_out;
662 }
663
664 while (i < (entry_size/sizeof(struct qlcnic_flt_entry))) {
665 if (flt_entry[i].region == region)
666 break;
667 i++;
668 }
669 if (i >= (entry_size/sizeof(struct qlcnic_flt_entry))) {
670 dev_warn(&adapter->pdev->dev,
671 "region=%x not found in %d regions\n", region, i);
672 ret = -EIO;
673 goto err_out;
674 }
675 memcpy(region_entry, &flt_entry[i], sizeof(struct qlcnic_flt_entry));
676
677err_out:
678 vfree(flt_entry);
679 return ret;
680}
681
630int 682int
631qlcnic_check_flash_fw_ver(struct qlcnic_adapter *adapter) 683qlcnic_check_flash_fw_ver(struct qlcnic_adapter *adapter)
632{ 684{
685 struct qlcnic_flt_entry fw_entry;
633 u32 ver = -1, min_ver; 686 u32 ver = -1, min_ver;
687 int ret;
634 688
635 qlcnic_rom_fast_read(adapter, QLCNIC_FW_VERSION_OFFSET, (int *)&ver); 689 ret = qlcnic_get_flt_entry(adapter, QLCNIC_FW_IMAGE_REGION, &fw_entry);
690 if (!ret)
691 /* 0-4:-signature, 4-8:-fw version */
692 qlcnic_rom_fast_read(adapter, fw_entry.start_addr + 4,
693 (int *)&ver);
694 else
695 qlcnic_rom_fast_read(adapter, QLCNIC_FW_VERSION_OFFSET,
696 (int *)&ver);
636 697
637 ver = QLCNIC_DECODE_VERSION(ver); 698 ver = QLCNIC_DECODE_VERSION(ver);
638 min_ver = QLCNIC_MIN_FW_VERSION; 699 min_ver = QLCNIC_MIN_FW_VERSION;