qlcnic: device state management fixes for virtual func
authorAmit Kumar Salecha <amit.salecha@qlogic.com>
Tue, 17 Aug 2010 00:34:20 +0000 (00:34 +0000)
committerDavid S. Miller <davem@davemloft.net>
Tue, 17 Aug 2010 10:59:46 +0000 (03:59 -0700)
o NPAR state should be set to operationl by Mangement function only.
o NPAR state should be set to non operational before device reset.
o VF function should wait for NPAR state to be operational.

Signed-off-by: Amit Kumar Salecha <amit.salecha@qlogic.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/qlcnic/qlcnic_hdr.h
drivers/net/qlcnic/qlcnic_main.c

index 15fc32070be3dfd689c7acece6658e866b22f59b..bd346d9aac94cc5d1e6895af64ffdb86fbcd8da9 100644 (file)
@@ -718,8 +718,9 @@ enum {
 #define QLCNIC_DEV_FAILED              0x6
 #define QLCNIC_DEV_QUISCENT            0x7
 
-#define QLCNIC_DEV_NPAR_NOT_RDY        0
-#define QLCNIC_DEV_NPAR_RDY            1
+#define QLCNIC_DEV_NPAR_NON_OPER       0 /* NON Operational */
+#define QLCNIC_DEV_NPAR_OPER           1 /* NPAR Operational */
+#define QLCNIC_DEV_NPAR_OPER_TIMEO     30 /* Operational time out */
 
 #define QLC_DEV_CHECK_ACTIVE(VAL, FN)          ((VAL) &= (1 << (FN * 4)))
 #define QLC_DEV_SET_REF_CNT(VAL, FN)           ((VAL) |= (1 << (FN * 4)))
index 4ecbf41230cbeb9273c406ff3dc13632367c6373..70c4b6b0031eeb8d343351a0c59243ee105ba7d9 100644 (file)
@@ -2398,7 +2398,7 @@ qlcnic_fwinit_work(struct work_struct *work)
 {
        struct qlcnic_adapter *adapter = container_of(work,
                        struct qlcnic_adapter, fw_work.work);
-       u32 dev_state = 0xf, npar_state;
+       u32 dev_state = 0xf;
 
        if (qlcnic_api_lock(adapter))
                goto err_ret;
@@ -2412,16 +2412,8 @@ qlcnic_fwinit_work(struct work_struct *work)
        }
 
        if (adapter->op_mode == QLCNIC_NON_PRIV_FUNC) {
-               npar_state = QLCRD32(adapter, QLCNIC_CRB_DEV_NPAR_STATE);
-               if (npar_state == QLCNIC_DEV_NPAR_RDY) {
-                       qlcnic_api_unlock(adapter);
-                       goto wait_npar;
-               } else {
-                       qlcnic_schedule_work(adapter, qlcnic_fwinit_work,
-                               FW_POLL_DELAY);
-                       qlcnic_api_unlock(adapter);
-                       return;
-               }
+               qlcnic_api_unlock(adapter);
+               goto wait_npar;
        }
 
        if (adapter->fw_wait_cnt++ > adapter->reset_ack_timeo) {
@@ -2470,20 +2462,17 @@ wait_npar:
        QLCDB(adapter, HW, "Func waiting: Device state=%u\n", dev_state);
 
        switch (dev_state) {
-       case QLCNIC_DEV_QUISCENT:
-       case QLCNIC_DEV_NEED_QUISCENT:
-       case QLCNIC_DEV_NEED_RESET:
-               qlcnic_schedule_work(adapter,
-                       qlcnic_fwinit_work, FW_POLL_DELAY);
-               return;
-       case QLCNIC_DEV_FAILED:
-               break;
-
-       default:
+       case QLCNIC_DEV_READY:
                if (!adapter->nic_ops->start_firmware(adapter)) {
                        qlcnic_schedule_work(adapter, qlcnic_attach_work, 0);
                        return;
                }
+       case QLCNIC_DEV_FAILED:
+               break;
+       default:
+               qlcnic_schedule_work(adapter,
+                       qlcnic_fwinit_work, FW_POLL_DELAY);
+               return;
        }
 
 err_ret:
@@ -2530,6 +2519,22 @@ err_ret:
 
 }
 
+/*Transit NPAR state to NON Operational */
+static void
+qlcnic_set_npar_non_operational(struct qlcnic_adapter *adapter)
+{
+       u32 state;
+
+       state = QLCRD32(adapter, QLCNIC_CRB_DEV_NPAR_STATE);
+       if (state == QLCNIC_DEV_NPAR_NON_OPER)
+               return;
+
+       if (qlcnic_api_lock(adapter))
+               return;
+       QLCWR32(adapter, QLCNIC_CRB_DEV_NPAR_STATE, QLCNIC_DEV_NPAR_NON_OPER);
+       qlcnic_api_unlock(adapter);
+}
+
 /*Transit to RESET state from READY state only */
 static void
 qlcnic_dev_request_reset(struct qlcnic_adapter *adapter)
@@ -2548,6 +2553,7 @@ qlcnic_dev_request_reset(struct qlcnic_adapter *adapter)
                qlcnic_idc_debug_info(adapter, 0);
        }
 
+       QLCWR32(adapter, QLCNIC_CRB_DEV_NPAR_STATE, QLCNIC_DEV_NPAR_NON_OPER);
        qlcnic_api_unlock(adapter);
 }
 
@@ -2555,21 +2561,14 @@ qlcnic_dev_request_reset(struct qlcnic_adapter *adapter)
 static void
 qlcnic_dev_set_npar_ready(struct qlcnic_adapter *adapter)
 {
-       u32 state;
-
        if (!(adapter->flags & QLCNIC_ESWITCH_ENABLED) ||
-               adapter->op_mode == QLCNIC_NON_PRIV_FUNC)
+           adapter->op_mode != QLCNIC_MGMT_FUNC)
                return;
        if (qlcnic_api_lock(adapter))
                return;
 
-       state = QLCRD32(adapter, QLCNIC_CRB_DEV_NPAR_STATE);
-
-       if (state != QLCNIC_DEV_NPAR_RDY) {
-               QLCWR32(adapter, QLCNIC_CRB_DEV_NPAR_STATE,
-                       QLCNIC_DEV_NPAR_RDY);
-               QLCDB(adapter, DRV, "NPAR READY state set\n");
-       }
+       QLCWR32(adapter, QLCNIC_CRB_DEV_NPAR_STATE, QLCNIC_DEV_NPAR_OPER);
+       QLCDB(adapter, DRV, "NPAR operational state set\n");
 
        qlcnic_api_unlock(adapter);
 }
@@ -2631,8 +2630,11 @@ qlcnic_check_health(struct qlcnic_adapter *adapter)
                qlcnic_dev_request_reset(adapter);
 
        state = QLCRD32(adapter, QLCNIC_CRB_DEV_STATE);
-       if (state == QLCNIC_DEV_NEED_RESET || state == QLCNIC_DEV_NEED_QUISCENT)
+       if (state == QLCNIC_DEV_NEED_RESET ||
+           state == QLCNIC_DEV_NEED_QUISCENT) {
+               qlcnic_set_npar_non_operational(adapter);
                adapter->need_fw_reset = 1;
+       }
 
        heartbit = QLCRD32(adapter, QLCNIC_PEG_ALIVE_COUNTER);
        if (heartbit != adapter->heartbit) {
@@ -2822,11 +2824,25 @@ static int
 qlcnicvf_start_firmware(struct qlcnic_adapter *adapter)
 {
        int err;
+       u8 npar_opt_timeo = QLCNIC_DEV_NPAR_OPER_TIMEO;
+       u32 npar_state;
 
        err = qlcnic_can_start_firmware(adapter);
        if (err)
                return err;
 
+       npar_state = QLCRD32(adapter, QLCNIC_CRB_DEV_NPAR_STATE);
+       while (npar_state != QLCNIC_DEV_NPAR_OPER && --npar_opt_timeo) {
+               msleep(1000);
+               npar_state = QLCRD32(adapter, QLCNIC_CRB_DEV_NPAR_STATE);
+       }
+
+       if (!npar_opt_timeo) {
+               dev_err(&adapter->pdev->dev,
+                       "Waiting for NPAR state to opertional timeout\n");
+               return -EIO;
+       }
+
        qlcnic_check_options(adapter);
 
        adapter->need_fw_reset = 0;