aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/qlcnic/qlcnic_main.c
diff options
context:
space:
mode:
authorAmit Kumar Salecha <amit.salecha@qlogic.com>2010-04-21 22:51:37 -0400
committerDavid S. Miller <davem@davemloft.net>2010-04-22 18:28:27 -0400
commitf73dfc50f14d5c4c7f6243a87a65b78aef6f3a48 (patch)
tree7b007ea5cc52cf7730b2fb548cba4961b0fd0b76 /drivers/net/qlcnic/qlcnic_main.c
parentbbd8c6a45b0f8557a8fc38fc763d7a51fac4459d (diff)
qlcnic: fix fw initialization responsibility
Now any pci-func can start fw, whoever sees the reset ack first. Before this, pci-func which sets the RESET state has the responsibility to start fw. 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_main.c')
-rw-r--r--drivers/net/qlcnic/qlcnic_main.c66
1 files changed, 37 insertions, 29 deletions
diff --git a/drivers/net/qlcnic/qlcnic_main.c b/drivers/net/qlcnic/qlcnic_main.c
index ff7705b26450..06349908092f 100644
--- a/drivers/net/qlcnic/qlcnic_main.c
+++ b/drivers/net/qlcnic/qlcnic_main.c
@@ -2015,6 +2015,7 @@ err:
2015 clear_bit(__QLCNIC_RESETTING, &adapter->state); 2015 clear_bit(__QLCNIC_RESETTING, &adapter->state);
2016} 2016}
2017 2017
2018/* Grab api lock, before checking state */
2018static int 2019static int
2019qlcnic_check_drv_state(struct qlcnic_adapter *adapter) 2020qlcnic_check_drv_state(struct qlcnic_adapter *adapter)
2020{ 2021{
@@ -2037,6 +2038,9 @@ qlcnic_can_start_firmware(struct qlcnic_adapter *adapter)
2037 u8 dev_init_timeo = adapter->dev_init_timeo; 2038 u8 dev_init_timeo = adapter->dev_init_timeo;
2038 int portnum = adapter->portnum; 2039 int portnum = adapter->portnum;
2039 2040
2041 if (test_and_clear_bit(__QLCNIC_START_FW, &adapter->state))
2042 return 1;
2043
2040 if (qlcnic_api_lock(adapter)) 2044 if (qlcnic_api_lock(adapter))
2041 return -1; 2045 return -1;
2042 2046
@@ -2044,8 +2048,6 @@ qlcnic_can_start_firmware(struct qlcnic_adapter *adapter)
2044 if (!(val & ((int)0x1 << (portnum * 4)))) { 2048 if (!(val & ((int)0x1 << (portnum * 4)))) {
2045 val |= ((u32)0x1 << (portnum * 4)); 2049 val |= ((u32)0x1 << (portnum * 4));
2046 QLCWR32(adapter, QLCNIC_CRB_DEV_REF_COUNT, val); 2050 QLCWR32(adapter, QLCNIC_CRB_DEV_REF_COUNT, val);
2047 } else if (test_and_clear_bit(__QLCNIC_START_FW, &adapter->state)) {
2048 goto start_fw;
2049 } 2051 }
2050 2052
2051 prev_state = QLCRD32(adapter, QLCNIC_CRB_DEV_STATE); 2053 prev_state = QLCRD32(adapter, QLCNIC_CRB_DEV_STATE);
@@ -2053,7 +2055,6 @@ qlcnic_can_start_firmware(struct qlcnic_adapter *adapter)
2053 2055
2054 switch (prev_state) { 2056 switch (prev_state) {
2055 case QLCNIC_DEV_COLD: 2057 case QLCNIC_DEV_COLD:
2056start_fw:
2057 QLCWR32(adapter, QLCNIC_CRB_DEV_STATE, QLCNIC_DEV_INITIALIZING); 2058 QLCWR32(adapter, QLCNIC_CRB_DEV_STATE, QLCNIC_DEV_INITIALIZING);
2058 qlcnic_api_unlock(adapter); 2059 qlcnic_api_unlock(adapter);
2059 return 1; 2060 return 1;
@@ -2113,51 +2114,59 @@ qlcnic_fwinit_work(struct work_struct *work)
2113{ 2114{
2114 struct qlcnic_adapter *adapter = container_of(work, 2115 struct qlcnic_adapter *adapter = container_of(work,
2115 struct qlcnic_adapter, fw_work.work); 2116 struct qlcnic_adapter, fw_work.work);
2116 int dev_state; 2117 u32 dev_state = 0xf;
2117 2118
2118 if (test_bit(__QLCNIC_START_FW, &adapter->state)) { 2119 if (qlcnic_api_lock(adapter))
2120 goto err_ret;
2119 2121
2120 if (qlcnic_check_drv_state(adapter) && 2122 if (adapter->fw_wait_cnt++ > adapter->reset_ack_timeo) {
2121 (adapter->fw_wait_cnt++ < adapter->reset_ack_timeo)) { 2123 dev_err(&adapter->pdev->dev, "Reset:Failed to get ack %d sec\n",
2122 qlcnic_schedule_work(adapter, 2124 adapter->reset_ack_timeo);
2123 qlcnic_fwinit_work, FW_POLL_DELAY); 2125 goto skip_ack_check;
2124 return; 2126 }
2127
2128 if (!qlcnic_check_drv_state(adapter)) {
2129skip_ack_check:
2130 dev_state = QLCRD32(adapter, QLCNIC_CRB_DEV_STATE);
2131 if (dev_state == QLCNIC_DEV_NEED_RESET) {
2132 QLCWR32(adapter, QLCNIC_CRB_DEV_STATE,
2133 QLCNIC_DEV_INITIALIZING);
2134 set_bit(__QLCNIC_START_FW, &adapter->state);
2135 QLCDB(adapter, DRV, "Restarting fw\n");
2125 } 2136 }
2126 2137
2127 QLCDB(adapter, DRV, "Resetting FW\n"); 2138 qlcnic_api_unlock(adapter);
2139
2128 if (!qlcnic_start_firmware(adapter)) { 2140 if (!qlcnic_start_firmware(adapter)) {
2129 qlcnic_schedule_work(adapter, qlcnic_attach_work, 0); 2141 qlcnic_schedule_work(adapter, qlcnic_attach_work, 0);
2130 return; 2142 return;
2131 } 2143 }
2132
2133 goto err_ret; 2144 goto err_ret;
2134 } 2145 }
2135 2146
2136 if (adapter->fw_wait_cnt++ > (adapter->dev_init_timeo / 2)) { 2147 qlcnic_api_unlock(adapter);
2137 dev_err(&adapter->pdev->dev,
2138 "Waiting for device to reset timeout\n");
2139 goto err_ret;
2140 }
2141 2148
2142 dev_state = QLCRD32(adapter, QLCNIC_CRB_DEV_STATE); 2149 dev_state = QLCRD32(adapter, QLCNIC_CRB_DEV_STATE);
2143 QLCDB(adapter, HW, "Func waiting: Device state=%d\n", dev_state); 2150 QLCDB(adapter, HW, "Func waiting: Device state=%u\n", dev_state);
2144 2151
2145 switch (dev_state) { 2152 switch (dev_state) {
2146 case QLCNIC_DEV_READY: 2153 case QLCNIC_DEV_NEED_RESET:
2147 if (!qlcnic_start_firmware(adapter)) { 2154 qlcnic_schedule_work(adapter,
2148 qlcnic_schedule_work(adapter, qlcnic_attach_work, 0); 2155 qlcnic_fwinit_work, FW_POLL_DELAY);
2149 return; 2156 return;
2150 }
2151 case QLCNIC_DEV_FAILED: 2157 case QLCNIC_DEV_FAILED:
2152 break; 2158 break;
2153 2159
2154 default: 2160 default:
2155 qlcnic_schedule_work(adapter, 2161 if (!qlcnic_start_firmware(adapter)) {
2156 qlcnic_fwinit_work, 2 * FW_POLL_DELAY); 2162 qlcnic_schedule_work(adapter, qlcnic_attach_work, 0);
2157 return; 2163 return;
2164 }
2158 } 2165 }
2159 2166
2160err_ret: 2167err_ret:
2168 dev_err(&adapter->pdev->dev, "Fwinit work failed state=%u "
2169 "fw_wait_cnt=%u\n", dev_state, adapter->fw_wait_cnt);
2161 netif_device_attach(adapter->netdev); 2170 netif_device_attach(adapter->netdev);
2162 qlcnic_clr_all_drv_state(adapter); 2171 qlcnic_clr_all_drv_state(adapter);
2163} 2172}
@@ -2202,6 +2211,7 @@ err_ret:
2202 2211
2203} 2212}
2204 2213
2214/*Transit to RESET state from READY state only */
2205static void 2215static void
2206qlcnic_dev_request_reset(struct qlcnic_adapter *adapter) 2216qlcnic_dev_request_reset(struct qlcnic_adapter *adapter)
2207{ 2217{
@@ -2212,10 +2222,8 @@ qlcnic_dev_request_reset(struct qlcnic_adapter *adapter)
2212 2222
2213 state = QLCRD32(adapter, QLCNIC_CRB_DEV_STATE); 2223 state = QLCRD32(adapter, QLCNIC_CRB_DEV_STATE);
2214 2224
2215 if (state != QLCNIC_DEV_INITIALIZING && 2225 if (state == QLCNIC_DEV_READY) {
2216 state != QLCNIC_DEV_NEED_RESET) {
2217 QLCWR32(adapter, QLCNIC_CRB_DEV_STATE, QLCNIC_DEV_NEED_RESET); 2226 QLCWR32(adapter, QLCNIC_CRB_DEV_STATE, QLCNIC_DEV_NEED_RESET);
2218 set_bit(__QLCNIC_START_FW, &adapter->state);
2219 QLCDB(adapter, DRV, "NEED_RESET state set\n"); 2227 QLCDB(adapter, DRV, "NEED_RESET state set\n");
2220 } 2228 }
2221 2229