aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/iwlwifi
diff options
context:
space:
mode:
authorWey-Yi Guy <wey-yi.w.guy@intel.com>2009-07-17 12:30:23 -0400
committerJohn W. Linville <linville@tuxdriver.com>2009-07-24 15:05:25 -0400
commit34a66de628b5dcc4a93129610ccd24814935e8cd (patch)
tree557a91aa61443b7b0140b84cb75249158bb78f93 /drivers/net/wireless/iwlwifi
parentcce53aa347c1e023d967b1cb1aa393c725aedba5 (diff)
iwlwifi: uCode Alive notification with timeout
Wait for REPLY_ALIVE notification from init and runtime uCode. based on the type of REPLY_ALIVE, different status bit will be set to wake up the queue: STATUS_INIT_UCODE_ALIVE for init uCode STATUS_RT_UCODE_ALIVE for runtime uCode. If timeout, attempt to download the failing uCode image again. This can only be done for the init ucode images of all iwlagn devices and the runtime ucode image of the 5000 series and up. If there is a problem with the 4965 runtime ucode coming up we restart the interface and thus trigger a new download of the init ucode also. Signed-off-by: Wey-Yi Guy <wey-yi.w.guy@intel.com> Signed-off-by: Reinette Chatre <reinette.chatre@intel.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless/iwlwifi')
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-4965.c26
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-agn.c50
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-core.c39
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-core.h2
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-dev.h2
5 files changed, 109 insertions, 10 deletions
diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c
index f4eb683aa2d5..272409c80619 100644
--- a/drivers/net/wireless/iwlwifi/iwl-4965.c
+++ b/drivers/net/wireless/iwlwifi/iwl-4965.c
@@ -146,7 +146,7 @@ static int iwl4965_load_bsm(struct iwl_priv *priv)
146 146
147 IWL_DEBUG_INFO(priv, "Begin load bsm\n"); 147 IWL_DEBUG_INFO(priv, "Begin load bsm\n");
148 148
149 priv->ucode_type = UCODE_RT; 149 priv->ucode_type = UCODE_INIT;
150 150
151 /* make sure bootstrap program is no larger than BSM's SRAM size */ 151 /* make sure bootstrap program is no larger than BSM's SRAM size */
152 if (len > IWL49_MAX_BSM_SIZE) 152 if (len > IWL49_MAX_BSM_SIZE)
@@ -256,6 +256,8 @@ static int iwl4965_set_ucode_ptrs(struct iwl_priv *priv)
256*/ 256*/
257static void iwl4965_init_alive_start(struct iwl_priv *priv) 257static void iwl4965_init_alive_start(struct iwl_priv *priv)
258{ 258{
259 int ret;
260
259 /* Check alive response for "valid" sign from uCode */ 261 /* Check alive response for "valid" sign from uCode */
260 if (priv->card_alive_init.is_valid != UCODE_VALID_OK) { 262 if (priv->card_alive_init.is_valid != UCODE_VALID_OK) {
261 /* We had an error bringing up the hardware, so take it 263 /* We had an error bringing up the hardware, so take it
@@ -287,6 +289,28 @@ static void iwl4965_init_alive_start(struct iwl_priv *priv)
287 IWL_DEBUG_INFO(priv, "Couldn't set up uCode pointers.\n"); 289 IWL_DEBUG_INFO(priv, "Couldn't set up uCode pointers.\n");
288 goto restart; 290 goto restart;
289 } 291 }
292 priv->ucode_type = UCODE_RT;
293 if (test_bit(STATUS_RT_UCODE_ALIVE, &priv->status)) {
294 IWL_WARN(priv, "Runtime uCode already alive? "
295 "Waiting for alive anyway\n");
296 clear_bit(STATUS_RT_UCODE_ALIVE, &priv->status);
297 }
298 ret = wait_event_interruptible_timeout(
299 priv->wait_command_queue,
300 test_bit(STATUS_RT_UCODE_ALIVE, &priv->status),
301 UCODE_ALIVE_TIMEOUT);
302 if (!ret) {
303 /* FIXME: if STATUS_RT_UCODE_ALIVE timeout
304 * go back to restart the download Init uCode again
305 * this might cause to trap in the restart loop
306 */
307 priv->ucode_type = UCODE_NONE;
308 if (!test_bit(STATUS_RT_UCODE_ALIVE, &priv->status)) {
309 IWL_ERR(priv, "Runtime timeout after %dms\n",
310 jiffies_to_msecs(UCODE_ALIVE_TIMEOUT));
311 goto restart;
312 }
313 }
290 return; 314 return;
291 315
292restart: 316restart:
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c
index 6b874dab4120..f61f653a1b72 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn.c
@@ -533,12 +533,16 @@ static void iwl_rx_reply_alive(struct iwl_priv *priv,
533 533
534 if (palive->ver_subtype == INITIALIZE_SUBTYPE) { 534 if (palive->ver_subtype == INITIALIZE_SUBTYPE) {
535 IWL_DEBUG_INFO(priv, "Initialization Alive received.\n"); 535 IWL_DEBUG_INFO(priv, "Initialization Alive received.\n");
536 set_bit(STATUS_INIT_UCODE_ALIVE, &priv->status);
537 wake_up_interruptible(&priv->wait_command_queue);
536 memcpy(&priv->card_alive_init, 538 memcpy(&priv->card_alive_init,
537 &pkt->u.alive_frame, 539 &pkt->u.alive_frame,
538 sizeof(struct iwl_init_alive_resp)); 540 sizeof(struct iwl_init_alive_resp));
539 pwork = &priv->init_alive_start; 541 pwork = &priv->init_alive_start;
540 } else { 542 } else {
541 IWL_DEBUG_INFO(priv, "Runtime Alive received.\n"); 543 IWL_DEBUG_INFO(priv, "Runtime Alive received.\n");
544 set_bit(STATUS_RT_UCODE_ALIVE, &priv->status);
545 wake_up_interruptible(&priv->wait_command_queue);
542 memcpy(&priv->card_alive, &pkt->u.alive_frame, 546 memcpy(&priv->card_alive, &pkt->u.alive_frame,
543 sizeof(struct iwl_alive_resp)); 547 sizeof(struct iwl_alive_resp));
544 pwork = &priv->alive_start; 548 pwork = &priv->alive_start;
@@ -1782,6 +1786,7 @@ static int __iwl_up(struct iwl_priv *priv)
1782{ 1786{
1783 int i; 1787 int i;
1784 int ret; 1788 int ret;
1789 unsigned long status;
1785 1790
1786 if (test_bit(STATUS_EXIT_PENDING, &priv->status)) { 1791 if (test_bit(STATUS_EXIT_PENDING, &priv->status)) {
1787 IWL_WARN(priv, "Exit pending; will not bring the NIC up\n"); 1792 IWL_WARN(priv, "Exit pending; will not bring the NIC up\n");
@@ -1859,6 +1864,51 @@ static int __iwl_up(struct iwl_priv *priv)
1859 /* start card; "initialize" will load runtime ucode */ 1864 /* start card; "initialize" will load runtime ucode */
1860 iwl_nic_start(priv); 1865 iwl_nic_start(priv);
1861 1866
1867 /* Just finish download Init or Runtime uCode image to device
1868 * now we wait here for uCode send REPLY_ALIVE notification
1869 * to indicate uCode is ready.
1870 * 1) For Init uCode image, all iwlagn devices should wait here
1871 * on STATUS_INIT_UCODE_ALIVE status bit; if timeout before
1872 * receive the REPLY_ALIVE notification, go back and try to
1873 * download the Init uCode image again.
1874 * 2) For Runtime uCode image, all iwlagn devices except 4965
1875 * wait here on STATUS_RT_UCODE_ALIVE status bit; if
1876 * timeout before receive the REPLY_ALIVE notification, go back
1877 * and download the Runtime uCode image again.
1878 * 3) For 4965 Runtime uCode, it will not go through this path,
1879 * need to wait for STATUS_RT_UCODE_ALIVE status bit in
1880 * iwl4965_init_alive_start() function; if timeout, need to
1881 * restart and download Init uCode image.
1882 */
1883 if (priv->ucode_type == UCODE_INIT)
1884 status = STATUS_INIT_UCODE_ALIVE;
1885 else
1886 status = STATUS_RT_UCODE_ALIVE;
1887 if (test_bit(status, &priv->status)) {
1888 IWL_WARN(priv,
1889 "%s uCode already alive? "
1890 "Waiting for alive anyway\n",
1891 (status == STATUS_INIT_UCODE_ALIVE)
1892 ? "INIT" : "Runtime");
1893 clear_bit(status, &priv->status);
1894 }
1895 ret = wait_event_interruptible_timeout(
1896 priv->wait_command_queue,
1897 test_bit(status, &priv->status),
1898 UCODE_ALIVE_TIMEOUT);
1899 if (!ret) {
1900 if (!test_bit(status, &priv->status)) {
1901 priv->ucode_type =
1902 (status == STATUS_INIT_UCODE_ALIVE)
1903 ? UCODE_NONE : UCODE_INIT;
1904 IWL_ERR(priv,
1905 "%s timeout after %dms\n",
1906 (status == STATUS_INIT_UCODE_ALIVE)
1907 ? "INIT" : "Runtime",
1908 jiffies_to_msecs(UCODE_ALIVE_TIMEOUT));
1909 continue;
1910 }
1911 }
1862 IWL_DEBUG_INFO(priv, DRV_NAME " is coming up\n"); 1912 IWL_DEBUG_INFO(priv, DRV_NAME " is coming up\n");
1863 1913
1864 return 0; 1914 return 0;
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c
index b82480a51782..8655e092fca7 100644
--- a/drivers/net/wireless/iwlwifi/iwl-core.c
+++ b/drivers/net/wireless/iwlwifi/iwl-core.c
@@ -1341,10 +1341,17 @@ static void iwl_dump_nic_error_log(struct iwl_priv *priv)
1341 u32 desc, time, count, base, data1; 1341 u32 desc, time, count, base, data1;
1342 u32 blink1, blink2, ilink1, ilink2; 1342 u32 blink1, blink2, ilink1, ilink2;
1343 1343
1344 if (priv->ucode_type == UCODE_INIT) 1344 switch (priv->ucode_type) {
1345 base = le32_to_cpu(priv->card_alive_init.error_event_table_ptr); 1345 case UCODE_RT:
1346 else
1347 base = le32_to_cpu(priv->card_alive.error_event_table_ptr); 1346 base = le32_to_cpu(priv->card_alive.error_event_table_ptr);
1347 break;
1348 case UCODE_INIT:
1349 base = le32_to_cpu(priv->card_alive_init.error_event_table_ptr);
1350 break;
1351 default:
1352 IWL_ERR(priv, "uCode image not available\n");
1353 return;
1354 }
1348 1355
1349 if (!priv->cfg->ops->lib->is_valid_rtc_data_addr(base)) { 1356 if (!priv->cfg->ops->lib->is_valid_rtc_data_addr(base)) {
1350 IWL_ERR(priv, "Not valid error log pointer 0x%08X\n", base); 1357 IWL_ERR(priv, "Not valid error log pointer 0x%08X\n", base);
@@ -1396,10 +1403,17 @@ static void iwl_print_event_log(struct iwl_priv *priv, u32 start_idx,
1396 1403
1397 if (num_events == 0) 1404 if (num_events == 0)
1398 return; 1405 return;
1399 if (priv->ucode_type == UCODE_INIT) 1406 switch (priv->ucode_type) {
1400 base = le32_to_cpu(priv->card_alive_init.log_event_table_ptr); 1407 case UCODE_RT:
1401 else
1402 base = le32_to_cpu(priv->card_alive.log_event_table_ptr); 1408 base = le32_to_cpu(priv->card_alive.log_event_table_ptr);
1409 break;
1410 case UCODE_INIT:
1411 base = le32_to_cpu(priv->card_alive_init.log_event_table_ptr);
1412 break;
1413 default:
1414 IWL_ERR(priv, "uCode image not available\n");
1415 return;
1416 }
1403 1417
1404 if (mode == 0) 1418 if (mode == 0)
1405 event_size = 2 * sizeof(u32); 1419 event_size = 2 * sizeof(u32);
@@ -1436,10 +1450,17 @@ void iwl_dump_nic_event_log(struct iwl_priv *priv)
1436 u32 next_entry; /* index of next entry to be written by uCode */ 1450 u32 next_entry; /* index of next entry to be written by uCode */
1437 u32 size; /* # entries that we'll print */ 1451 u32 size; /* # entries that we'll print */
1438 1452
1439 if (priv->ucode_type == UCODE_INIT) 1453 switch (priv->ucode_type) {
1440 base = le32_to_cpu(priv->card_alive_init.log_event_table_ptr); 1454 case UCODE_RT:
1441 else
1442 base = le32_to_cpu(priv->card_alive.log_event_table_ptr); 1455 base = le32_to_cpu(priv->card_alive.log_event_table_ptr);
1456 break;
1457 case UCODE_INIT:
1458 base = le32_to_cpu(priv->card_alive_init.log_event_table_ptr);
1459 break;
1460 default:
1461 IWL_ERR(priv, "uCode image not available\n");
1462 return;
1463 }
1443 1464
1444 if (!priv->cfg->ops->lib->is_valid_rtc_data_addr(base)) { 1465 if (!priv->cfg->ops->lib->is_valid_rtc_data_addr(base)) {
1445 IWL_ERR(priv, "Invalid event log pointer 0x%08X\n", base); 1466 IWL_ERR(priv, "Invalid event log pointer 0x%08X\n", base);
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h
index c844fab95abb..a697b843863b 100644
--- a/drivers/net/wireless/iwlwifi/iwl-core.h
+++ b/drivers/net/wireless/iwlwifi/iwl-core.h
@@ -512,6 +512,8 @@ void iwlcore_free_geos(struct iwl_priv *priv);
512#define STATUS_POWER_PMI 16 512#define STATUS_POWER_PMI 16
513#define STATUS_FW_ERROR 17 513#define STATUS_FW_ERROR 17
514#define STATUS_MODE_PENDING 18 514#define STATUS_MODE_PENDING 18
515#define STATUS_INIT_UCODE_ALIVE 19
516#define STATUS_RT_UCODE_ALIVE 20
515 517
516 518
517static inline int iwl_is_ready(struct iwl_priv *priv) 519static inline int iwl_is_ready(struct iwl_priv *priv)
diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h
index f4afd0c3265f..926df3ae2416 100644
--- a/drivers/net/wireless/iwlwifi/iwl-dev.h
+++ b/drivers/net/wireless/iwlwifi/iwl-dev.h
@@ -772,6 +772,8 @@ struct iwl_calib_result {
772 size_t buf_len; 772 size_t buf_len;
773}; 773};
774 774
775#define UCODE_ALIVE_TIMEOUT (5 * HZ)
776
775enum ucode_type { 777enum ucode_type {
776 UCODE_NONE = 0, 778 UCODE_NONE = 0,
777 UCODE_INIT, 779 UCODE_INIT,