aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net
diff options
context:
space:
mode:
authorAnirban Chakraborty <anirban.chakraborty@qlogic.com>2010-08-26 10:02:52 -0400
committerDavid S. Miller <davem@davemloft.net>2010-08-26 20:13:19 -0400
commit0866d96da02cccc3ca837d0d71687aba962b3f2f (patch)
treefdf48e0ccd0c92819c2d96d3e18562c4092bb471 /drivers/net
parent8cfdce080722101a7fd2a1eff9763ca4008ec626 (diff)
qlcnic: Fix driver load issue in FW hang
If there is a FW hang when the driver loads, it can not determine the FW operational mode. Fix it by checking the FW state first before issuing any FW commands to determine its capabilities and thereby detecting driver operational mode. Signed-off-by: Anirban Chakraborty <anirban.chakraborty@qlogic.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net')
-rw-r--r--drivers/net/qlcnic/qlcnic.h1
-rw-r--r--drivers/net/qlcnic/qlcnic_hdr.h2
-rw-r--r--drivers/net/qlcnic/qlcnic_init.c16
-rw-r--r--drivers/net/qlcnic/qlcnic_main.c116
4 files changed, 75 insertions, 60 deletions
diff --git a/drivers/net/qlcnic/qlcnic.h b/drivers/net/qlcnic/qlcnic.h
index d15de63ed0bb..0a537044d7da 100644
--- a/drivers/net/qlcnic/qlcnic.h
+++ b/drivers/net/qlcnic/qlcnic.h
@@ -902,6 +902,7 @@ struct qlcnic_mac_req {
902#define QLCNIC_BRIDGE_ENABLED 0X10 902#define QLCNIC_BRIDGE_ENABLED 0X10
903#define QLCNIC_DIAG_ENABLED 0x20 903#define QLCNIC_DIAG_ENABLED 0x20
904#define QLCNIC_ESWITCH_ENABLED 0x40 904#define QLCNIC_ESWITCH_ENABLED 0x40
905#define QLCNIC_ADAPTER_INITIALIZED 0x80
905#define QLCNIC_TAGGING_ENABLED 0x100 906#define QLCNIC_TAGGING_ENABLED 0x100
906#define QLCNIC_MACSPOOF 0x200 907#define QLCNIC_MACSPOOF 0x200
907#define QLCNIC_IS_MSI_FAMILY(adapter) \ 908#define QLCNIC_IS_MSI_FAMILY(adapter) \
diff --git a/drivers/net/qlcnic/qlcnic_hdr.h b/drivers/net/qlcnic/qlcnic_hdr.h
index 219de9f4496f..bce1b1d541b7 100644
--- a/drivers/net/qlcnic/qlcnic_hdr.h
+++ b/drivers/net/qlcnic/qlcnic_hdr.h
@@ -748,7 +748,7 @@ enum {
748#define QLCNIC_RESET_TIMEOUT_SECS 10 748#define QLCNIC_RESET_TIMEOUT_SECS 10
749#define QLCNIC_INIT_TIMEOUT_SECS 30 749#define QLCNIC_INIT_TIMEOUT_SECS 30
750#define QLCNIC_HEARTBEAT_PERIOD_MSECS 200 750#define QLCNIC_HEARTBEAT_PERIOD_MSECS 200
751#define QLCNIC_HEARTBEAT_RETRY_COUNT 30 751#define QLCNIC_HEARTBEAT_RETRY_COUNT 45
752 752
753#define ISR_MSI_INT_TRIGGER(FUNC) (QLCNIC_PCIX_PS_REG(PCIX_MSI_F(FUNC))) 753#define ISR_MSI_INT_TRIGGER(FUNC) (QLCNIC_PCIX_PS_REG(PCIX_MSI_F(FUNC)))
754#define ISR_LEGACY_INT_TRIGGERED(VAL) (((VAL) & 0x300) == 0x200) 754#define ISR_LEGACY_INT_TRIGGERED(VAL) (((VAL) & 0x300) == 0x200)
diff --git a/drivers/net/qlcnic/qlcnic_init.c b/drivers/net/qlcnic/qlcnic_init.c
index df91b754bb70..eb8256bec516 100644
--- a/drivers/net/qlcnic/qlcnic_init.c
+++ b/drivers/net/qlcnic/qlcnic_init.c
@@ -547,7 +547,7 @@ int qlcnic_pinit_from_rom(struct qlcnic_adapter *adapter)
547int 547int
548qlcnic_check_fw_status(struct qlcnic_adapter *adapter) 548qlcnic_check_fw_status(struct qlcnic_adapter *adapter)
549{ 549{
550 u32 heartbit, ret = -EIO; 550 u32 heartbit, cmdpeg_state, ret = -EIO;
551 int retries = QLCNIC_HEARTBEAT_RETRY_COUNT; 551 int retries = QLCNIC_HEARTBEAT_RETRY_COUNT;
552 552
553 adapter->heartbit = QLCRD32(adapter, QLCNIC_PEG_ALIVE_COUNTER); 553 adapter->heartbit = QLCRD32(adapter, QLCNIC_PEG_ALIVE_COUNTER);
@@ -555,10 +555,16 @@ qlcnic_check_fw_status(struct qlcnic_adapter *adapter)
555 msleep(QLCNIC_HEARTBEAT_PERIOD_MSECS); 555 msleep(QLCNIC_HEARTBEAT_PERIOD_MSECS);
556 heartbit = QLCRD32(adapter, QLCNIC_PEG_ALIVE_COUNTER); 556 heartbit = QLCRD32(adapter, QLCNIC_PEG_ALIVE_COUNTER);
557 if (heartbit != adapter->heartbit) { 557 if (heartbit != adapter->heartbit) {
558 /* Complete firmware handshake */ 558 cmdpeg_state = QLCRD32(adapter, CRB_CMDPEG_STATE);
559 QLCWR32(adapter, CRB_CMDPEG_STATE, PHAN_INITIALIZE_ACK); 559 /* Ensure peg states are initialized */
560 ret = QLCNIC_RCODE_SUCCESS; 560 if (cmdpeg_state == PHAN_INITIALIZE_COMPLETE ||
561 break; 561 cmdpeg_state == PHAN_INITIALIZE_ACK) {
562 /* Complete firmware handshake */
563 QLCWR32(adapter, CRB_CMDPEG_STATE,
564 PHAN_INITIALIZE_ACK);
565 ret = QLCNIC_RCODE_SUCCESS;
566 break;
567 }
562 } 568 }
563 } while (--retries); 569 } while (--retries);
564 570
diff --git a/drivers/net/qlcnic/qlcnic_main.c b/drivers/net/qlcnic/qlcnic_main.c
index 1b8f67dab9b8..6999d5aaa157 100644
--- a/drivers/net/qlcnic/qlcnic_main.c
+++ b/drivers/net/qlcnic/qlcnic_main.c
@@ -566,12 +566,11 @@ err_lock:
566 return ret; 566 return ret;
567} 567}
568 568
569static u32 569static void
570qlcnic_get_driver_mode(struct qlcnic_adapter *adapter) 570qlcnic_check_vf(struct qlcnic_adapter *adapter)
571{ 571{
572 void __iomem *msix_base_addr; 572 void __iomem *msix_base_addr;
573 void __iomem *priv_op; 573 void __iomem *priv_op;
574 struct qlcnic_info nic_info;
575 u32 func; 574 u32 func;
576 u32 msix_base; 575 u32 msix_base;
577 u32 op_mode, priv_level; 576 u32 op_mode, priv_level;
@@ -586,20 +585,6 @@ qlcnic_get_driver_mode(struct qlcnic_adapter *adapter)
586 func = (func - msix_base)/QLCNIC_MSIX_TBL_PGSIZE; 585 func = (func - msix_base)/QLCNIC_MSIX_TBL_PGSIZE;
587 adapter->ahw.pci_func = func; 586 adapter->ahw.pci_func = func;
588 587
589 if (!qlcnic_get_nic_info(adapter, &nic_info, adapter->ahw.pci_func)) {
590 adapter->capabilities = nic_info.capabilities;
591
592 if (adapter->capabilities & BIT_6)
593 adapter->flags |= QLCNIC_ESWITCH_ENABLED;
594 else
595 adapter->flags &= ~QLCNIC_ESWITCH_ENABLED;
596 }
597
598 if (!(adapter->flags & QLCNIC_ESWITCH_ENABLED)) {
599 adapter->nic_ops = &qlcnic_ops;
600 return adapter->fw_hal_version;
601 }
602
603 /* Determine function privilege level */ 588 /* Determine function privilege level */
604 priv_op = adapter->ahw.pci_base0 + QLCNIC_DRV_OP_MODE; 589 priv_op = adapter->ahw.pci_base0 + QLCNIC_DRV_OP_MODE;
605 op_mode = readl(priv_op); 590 op_mode = readl(priv_op);
@@ -608,37 +593,14 @@ qlcnic_get_driver_mode(struct qlcnic_adapter *adapter)
608 else 593 else
609 priv_level = QLC_DEV_GET_DRV(op_mode, adapter->ahw.pci_func); 594 priv_level = QLC_DEV_GET_DRV(op_mode, adapter->ahw.pci_func);
610 595
611 switch (priv_level) { 596 if (priv_level == QLCNIC_NON_PRIV_FUNC) {
612 case QLCNIC_MGMT_FUNC:
613 adapter->op_mode = QLCNIC_MGMT_FUNC;
614 adapter->nic_ops = &qlcnic_ops;
615 qlcnic_init_pci_info(adapter);
616 /* Set privilege level for other functions */
617 qlcnic_set_function_modes(adapter);
618 dev_info(&adapter->pdev->dev,
619 "HAL Version: %d, Management function\n",
620 adapter->fw_hal_version);
621 break;
622 case QLCNIC_PRIV_FUNC:
623 adapter->op_mode = QLCNIC_PRIV_FUNC;
624 dev_info(&adapter->pdev->dev,
625 "HAL Version: %d, Privileged function\n",
626 adapter->fw_hal_version);
627 adapter->nic_ops = &qlcnic_ops;
628 break;
629 case QLCNIC_NON_PRIV_FUNC:
630 adapter->op_mode = QLCNIC_NON_PRIV_FUNC; 597 adapter->op_mode = QLCNIC_NON_PRIV_FUNC;
631 dev_info(&adapter->pdev->dev, 598 dev_info(&adapter->pdev->dev,
632 "HAL Version: %d Non Privileged function\n", 599 "HAL Version: %d Non Privileged function\n",
633 adapter->fw_hal_version); 600 adapter->fw_hal_version);
634 adapter->nic_ops = &qlcnic_vf_ops; 601 adapter->nic_ops = &qlcnic_vf_ops;
635 break; 602 } else
636 default: 603 adapter->nic_ops = &qlcnic_ops;
637 dev_info(&adapter->pdev->dev, "Unknown function mode: %d\n",
638 priv_level);
639 return 0;
640 }
641 return adapter->fw_hal_version;
642} 604}
643 605
644static int 606static int
@@ -671,10 +633,7 @@ qlcnic_setup_pci_map(struct qlcnic_adapter *adapter)
671 adapter->ahw.pci_base0 = mem_ptr0; 633 adapter->ahw.pci_base0 = mem_ptr0;
672 adapter->ahw.pci_len0 = pci_len0; 634 adapter->ahw.pci_len0 = pci_len0;
673 635
674 if (!qlcnic_get_driver_mode(adapter)) { 636 qlcnic_check_vf(adapter);
675 iounmap(adapter->ahw.pci_base0);
676 return -EIO;
677 }
678 637
679 adapter->ahw.ocm_win_crb = qlcnic_get_ioaddr(adapter, 638 adapter->ahw.ocm_win_crb = qlcnic_get_ioaddr(adapter,
680 QLCNIC_PCIX_PS_REG(PCIX_OCM_WINDOW_REG(adapter->ahw.pci_func))); 639 QLCNIC_PCIX_PS_REG(PCIX_OCM_WINDOW_REG(adapter->ahw.pci_func)));
@@ -719,6 +678,9 @@ qlcnic_check_options(struct qlcnic_adapter *adapter)
719 678
720 adapter->fw_version = QLCNIC_VERSION_CODE(fw_major, fw_minor, fw_build); 679 adapter->fw_version = QLCNIC_VERSION_CODE(fw_major, fw_minor, fw_build);
721 680
681 if (!(adapter->flags & QLCNIC_ADAPTER_INITIALIZED))
682 if (qlcnic_read_mac_addr(adapter))
683 dev_warn(&pdev->dev, "failed to read mac addr\n");
722 if (adapter->portnum == 0) { 684 if (adapter->portnum == 0) {
723 get_brd_name(adapter, brd_name); 685 get_brd_name(adapter, brd_name);
724 686
@@ -837,6 +799,51 @@ qlcnic_set_netdev_features(struct qlcnic_adapter *adapter,
837} 799}
838 800
839static int 801static int
802qlcnic_check_eswitch_mode(struct qlcnic_adapter *adapter)
803{
804 void __iomem *priv_op;
805 u32 op_mode, priv_level;
806 int err = 0;
807
808 if (adapter->flags & QLCNIC_ADAPTER_INITIALIZED)
809 return 0;
810
811 priv_op = adapter->ahw.pci_base0 + QLCNIC_DRV_OP_MODE;
812 op_mode = readl(priv_op);
813 priv_level = QLC_DEV_GET_DRV(op_mode, adapter->ahw.pci_func);
814
815 if (op_mode == QLC_DEV_DRV_DEFAULT)
816 priv_level = QLCNIC_MGMT_FUNC;
817 else
818 priv_level = QLC_DEV_GET_DRV(op_mode, adapter->ahw.pci_func);
819
820 if (adapter->capabilities & BIT_6) {
821 adapter->flags |= QLCNIC_ESWITCH_ENABLED;
822 if (priv_level == QLCNIC_MGMT_FUNC) {
823 adapter->op_mode = QLCNIC_MGMT_FUNC;
824 err = qlcnic_init_pci_info(adapter);
825 if (err)
826 return err;
827 /* Set privilege level for other functions */
828 qlcnic_set_function_modes(adapter);
829 dev_info(&adapter->pdev->dev,
830 "HAL Version: %d, Management function\n",
831 adapter->fw_hal_version);
832 } else if (priv_level == QLCNIC_PRIV_FUNC) {
833 adapter->op_mode = QLCNIC_PRIV_FUNC;
834 dev_info(&adapter->pdev->dev,
835 "HAL Version: %d, Privileged function\n",
836 adapter->fw_hal_version);
837 }
838 } else
839 adapter->flags &= ~QLCNIC_ESWITCH_ENABLED;
840
841 adapter->flags |= QLCNIC_ADAPTER_INITIALIZED;
842
843 return err;
844}
845
846static int
840qlcnic_set_default_offload_settings(struct qlcnic_adapter *adapter) 847qlcnic_set_default_offload_settings(struct qlcnic_adapter *adapter)
841{ 848{
842 struct qlcnic_esw_func_cfg esw_cfg; 849 struct qlcnic_esw_func_cfg esw_cfg;
@@ -1005,8 +1012,14 @@ set_dev_ready:
1005 err = qlcnic_reset_npar_config(adapter); 1012 err = qlcnic_reset_npar_config(adapter);
1006 if (err) 1013 if (err)
1007 goto err_out; 1014 goto err_out;
1008 qlcnic_dev_set_npar_ready(adapter);
1009 qlcnic_check_options(adapter); 1015 qlcnic_check_options(adapter);
1016 err = qlcnic_check_eswitch_mode(adapter);
1017 if (err) {
1018 dev_err(&adapter->pdev->dev,
1019 "Memory allocation failed for eswitch\n");
1020 goto err_out;
1021 }
1022 qlcnic_dev_set_npar_ready(adapter);
1010 adapter->need_fw_reset = 0; 1023 adapter->need_fw_reset = 0;
1011 1024
1012 qlcnic_release_firmware(adapter); 1025 qlcnic_release_firmware(adapter);
@@ -1015,6 +1028,7 @@ set_dev_ready:
1015err_out: 1028err_out:
1016 QLCWR32(adapter, QLCNIC_CRB_DEV_STATE, QLCNIC_DEV_FAILED); 1029 QLCWR32(adapter, QLCNIC_CRB_DEV_STATE, QLCNIC_DEV_FAILED);
1017 dev_err(&adapter->pdev->dev, "Device state set to failed\n"); 1030 dev_err(&adapter->pdev->dev, "Device state set to failed\n");
1031
1018 qlcnic_release_firmware(adapter); 1032 qlcnic_release_firmware(adapter);
1019 return err; 1033 return err;
1020} 1034}
@@ -1419,9 +1433,6 @@ qlcnic_setup_netdev(struct qlcnic_adapter *adapter,
1419 netdev->features |= NETIF_F_LRO; 1433 netdev->features |= NETIF_F_LRO;
1420 netdev->irq = adapter->msix_entries[0].vector; 1434 netdev->irq = adapter->msix_entries[0].vector;
1421 1435
1422 if (qlcnic_read_mac_addr(adapter))
1423 dev_warn(&pdev->dev, "failed to read mac addr\n");
1424
1425 netif_carrier_off(netdev); 1436 netif_carrier_off(netdev);
1426 netif_stop_queue(netdev); 1437 netif_stop_queue(netdev);
1427 1438
@@ -1515,9 +1526,6 @@ qlcnic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
1515 goto err_out_iounmap; 1526 goto err_out_iounmap;
1516 } 1527 }
1517 1528
1518 if (qlcnic_read_mac_addr(adapter))
1519 dev_warn(&pdev->dev, "failed to read mac addr\n");
1520
1521 err = qlcnic_setup_idc_param(adapter); 1529 err = qlcnic_setup_idc_param(adapter);
1522 if (err) 1530 if (err)
1523 goto err_out_iounmap; 1531 goto err_out_iounmap;