aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/net/qlcnic/qlcnic.h2
-rw-r--r--drivers/net/qlcnic/qlcnic_hdr.h6
-rw-r--r--drivers/net/qlcnic/qlcnic_init.c109
-rw-r--r--drivers/net/qlcnic/qlcnic_main.c11
4 files changed, 100 insertions, 28 deletions
diff --git a/drivers/net/qlcnic/qlcnic.h b/drivers/net/qlcnic/qlcnic.h
index 1f5c10bc9376..74eff18fc1ec 100644
--- a/drivers/net/qlcnic/qlcnic.h
+++ b/drivers/net/qlcnic/qlcnic.h
@@ -978,7 +978,7 @@ struct qlcnic_adapter {
978 u32 temp; 978 u32 temp;
979 979
980 u32 int_vec_bit; 980 u32 int_vec_bit;
981 u32 heartbit; 981 u32 heartbeat;
982 982
983 u8 max_mac_filters; 983 u8 max_mac_filters;
984 u8 dev_state; 984 u8 dev_state;
diff --git a/drivers/net/qlcnic/qlcnic_hdr.h b/drivers/net/qlcnic/qlcnic_hdr.h
index bce1b1d541b7..716203e41dc7 100644
--- a/drivers/net/qlcnic/qlcnic_hdr.h
+++ b/drivers/net/qlcnic/qlcnic_hdr.h
@@ -747,8 +747,12 @@ enum {
747 747
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_RCVPEG_CHECK_RETRY_COUNT 2000
751#define QLCNIC_RCVPEG_CHECK_DELAY 10
752#define QLCNIC_CMDPEG_CHECK_RETRY_COUNT 60
753#define QLCNIC_CMDPEG_CHECK_DELAY 500
750#define QLCNIC_HEARTBEAT_PERIOD_MSECS 200 754#define QLCNIC_HEARTBEAT_PERIOD_MSECS 200
751#define QLCNIC_HEARTBEAT_RETRY_COUNT 45 755#define QLCNIC_HEARTBEAT_CHECK_RETRY_COUNT 45
752 756
753#define ISR_MSI_INT_TRIGGER(FUNC) (QLCNIC_PCIX_PS_REG(PCIX_MSI_F(FUNC))) 757#define ISR_MSI_INT_TRIGGER(FUNC) (QLCNIC_PCIX_PS_REG(PCIX_MSI_F(FUNC)))
754#define ISR_LEGACY_INT_TRIGGERED(VAL) (((VAL) & 0x300) == 0x200) 758#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 eb8256bec516..8e0e7a3bbf9e 100644
--- a/drivers/net/qlcnic/qlcnic_init.c
+++ b/drivers/net/qlcnic/qlcnic_init.c
@@ -46,6 +46,9 @@ static void
46qlcnic_post_rx_buffers_nodb(struct qlcnic_adapter *adapter, 46qlcnic_post_rx_buffers_nodb(struct qlcnic_adapter *adapter,
47 struct qlcnic_host_rds_ring *rds_ring); 47 struct qlcnic_host_rds_ring *rds_ring);
48 48
49static int
50qlcnic_check_fw_hearbeat(struct qlcnic_adapter *adapter);
51
49static void crb_addr_transform_setup(void) 52static void crb_addr_transform_setup(void)
50{ 53{
51 crb_addr_transform(XDMA); 54 crb_addr_transform(XDMA);
@@ -544,31 +547,77 @@ int qlcnic_pinit_from_rom(struct qlcnic_adapter *adapter)
544 return 0; 547 return 0;
545} 548}
546 549
547int 550static int qlcnic_cmd_peg_ready(struct qlcnic_adapter *adapter)
548qlcnic_check_fw_status(struct qlcnic_adapter *adapter)
549{ 551{
550 u32 heartbit, cmdpeg_state, ret = -EIO; 552 u32 val;
551 int retries = QLCNIC_HEARTBEAT_RETRY_COUNT; 553 int retries = QLCNIC_CMDPEG_CHECK_RETRY_COUNT;
552 554
553 adapter->heartbit = QLCRD32(adapter, QLCNIC_PEG_ALIVE_COUNTER);
554 do { 555 do {
555 msleep(QLCNIC_HEARTBEAT_PERIOD_MSECS); 556 val = QLCRD32(adapter, CRB_CMDPEG_STATE);
556 heartbit = QLCRD32(adapter, QLCNIC_PEG_ALIVE_COUNTER); 557
557 if (heartbit != adapter->heartbit) { 558 switch (val) {
558 cmdpeg_state = QLCRD32(adapter, CRB_CMDPEG_STATE); 559 case PHAN_INITIALIZE_COMPLETE:
559 /* Ensure peg states are initialized */ 560 case PHAN_INITIALIZE_ACK:
560 if (cmdpeg_state == PHAN_INITIALIZE_COMPLETE || 561 return 0;
561 cmdpeg_state == PHAN_INITIALIZE_ACK) { 562 case PHAN_INITIALIZE_FAILED:
562 /* Complete firmware handshake */ 563 goto out_err;
563 QLCWR32(adapter, CRB_CMDPEG_STATE, 564 default:
564 PHAN_INITIALIZE_ACK); 565 break;
565 ret = QLCNIC_RCODE_SUCCESS;
566 break;
567 }
568 } 566 }
567
568 msleep(QLCNIC_CMDPEG_CHECK_DELAY);
569
569 } while (--retries); 570 } while (--retries);
570 571
571 return ret; 572 QLCWR32(adapter, CRB_CMDPEG_STATE, PHAN_INITIALIZE_FAILED);
573
574out_err:
575 dev_err(&adapter->pdev->dev, "Command Peg initialization not "
576 "complete, state: 0x%x.\n", val);
577 return -EIO;
578}
579
580static int
581qlcnic_receive_peg_ready(struct qlcnic_adapter *adapter)
582{
583 u32 val;
584 int retries = QLCNIC_RCVPEG_CHECK_RETRY_COUNT;
585
586 do {
587 val = QLCRD32(adapter, CRB_RCVPEG_STATE);
588
589 if (val == PHAN_PEG_RCV_INITIALIZED)
590 return 0;
591
592 msleep(QLCNIC_RCVPEG_CHECK_DELAY);
593
594 } while (--retries);
595
596 if (!retries) {
597 dev_err(&adapter->pdev->dev, "Receive Peg initialization not "
598 "complete, state: 0x%x.\n", val);
599 return -EIO;
600 }
601
602 return 0;
603}
604
605int
606qlcnic_check_fw_status(struct qlcnic_adapter *adapter)
607{
608 int err;
609
610 err = qlcnic_cmd_peg_ready(adapter);
611 if (err)
612 return err;
613
614 err = qlcnic_receive_peg_ready(adapter);
615 if (err)
616 return err;
617
618 QLCWR32(adapter, CRB_CMDPEG_STATE, PHAN_INITIALIZE_ACK);
619
620 return err;
572} 621}
573 622
574int 623int
@@ -943,12 +992,32 @@ static void qlcnic_rom_lock_recovery(struct qlcnic_adapter *adapter)
943 qlcnic_pcie_sem_unlock(adapter, 2); 992 qlcnic_pcie_sem_unlock(adapter, 2);
944} 993}
945 994
995static int
996qlcnic_check_fw_hearbeat(struct qlcnic_adapter *adapter)
997{
998 u32 heartbeat, ret = -EIO;
999 int retries = QLCNIC_HEARTBEAT_CHECK_RETRY_COUNT;
1000
1001 adapter->heartbeat = QLCRD32(adapter, QLCNIC_PEG_ALIVE_COUNTER);
1002
1003 do {
1004 msleep(QLCNIC_HEARTBEAT_PERIOD_MSECS);
1005 heartbeat = QLCRD32(adapter, QLCNIC_PEG_ALIVE_COUNTER);
1006 if (heartbeat != adapter->heartbeat) {
1007 ret = QLCNIC_RCODE_SUCCESS;
1008 break;
1009 }
1010 } while (--retries);
1011
1012 return ret;
1013}
1014
946int 1015int
947qlcnic_need_fw_reset(struct qlcnic_adapter *adapter) 1016qlcnic_need_fw_reset(struct qlcnic_adapter *adapter)
948{ 1017{
949 u32 val, version, major, minor, build; 1018 u32 val, version, major, minor, build;
950 1019
951 if (qlcnic_check_fw_status(adapter)) { 1020 if (qlcnic_check_fw_hearbeat(adapter)) {
952 qlcnic_rom_lock_recovery(adapter); 1021 qlcnic_rom_lock_recovery(adapter);
953 return 1; 1022 return 1;
954 } 1023 }
diff --git a/drivers/net/qlcnic/qlcnic_main.c b/drivers/net/qlcnic/qlcnic_main.c
index 6999d5aaa157..771a160b88c1 100644
--- a/drivers/net/qlcnic/qlcnic_main.c
+++ b/drivers/net/qlcnic/qlcnic_main.c
@@ -983,7 +983,7 @@ qlcnic_start_firmware(struct qlcnic_adapter *adapter)
983 983
984 err = qlcnic_need_fw_reset(adapter); 984 err = qlcnic_need_fw_reset(adapter);
985 if (err == 0) 985 if (err == 0)
986 goto set_dev_ready; 986 goto check_fw_status;
987 987
988 err = qlcnic_pinit_from_rom(adapter); 988 err = qlcnic_pinit_from_rom(adapter);
989 if (err) 989 if (err)
@@ -1002,7 +1002,6 @@ check_fw_status:
1002 if (err) 1002 if (err)
1003 goto err_out; 1003 goto err_out;
1004 1004
1005set_dev_ready:
1006 QLCWR32(adapter, QLCNIC_CRB_DEV_STATE, QLCNIC_DEV_READY); 1005 QLCWR32(adapter, QLCNIC_CRB_DEV_STATE, QLCNIC_DEV_READY);
1007 qlcnic_idc_debug_info(adapter, 1); 1006 qlcnic_idc_debug_info(adapter, 1);
1008 1007
@@ -2795,7 +2794,7 @@ done:
2795static int 2794static int
2796qlcnic_check_health(struct qlcnic_adapter *adapter) 2795qlcnic_check_health(struct qlcnic_adapter *adapter)
2797{ 2796{
2798 u32 state = 0, heartbit; 2797 u32 state = 0, heartbeat;
2799 struct net_device *netdev = adapter->netdev; 2798 struct net_device *netdev = adapter->netdev;
2800 2799
2801 if (qlcnic_check_temp(adapter)) 2800 if (qlcnic_check_temp(adapter))
@@ -2811,9 +2810,9 @@ qlcnic_check_health(struct qlcnic_adapter *adapter)
2811 adapter->need_fw_reset = 1; 2810 adapter->need_fw_reset = 1;
2812 } 2811 }
2813 2812
2814 heartbit = QLCRD32(adapter, QLCNIC_PEG_ALIVE_COUNTER); 2813 heartbeat = QLCRD32(adapter, QLCNIC_PEG_ALIVE_COUNTER);
2815 if (heartbit != adapter->heartbit) { 2814 if (heartbeat != adapter->heartbeat) {
2816 adapter->heartbit = heartbit; 2815 adapter->heartbeat = heartbeat;
2817 adapter->fw_fail_cnt = 0; 2816 adapter->fw_fail_cnt = 0;
2818 if (adapter->need_fw_reset) 2817 if (adapter->need_fw_reset)
2819 goto detach; 2818 goto detach;