aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorWey-Yi Guy <wey-yi.w.guy@intel.com>2010-02-03 14:47:19 -0500
committerReinette Chatre <reinette.chatre@intel.com>2010-02-11 13:24:12 -0500
commita93e7973d0983d22fcbe5f691244736211639fe7 (patch)
tree161f64fa2297146b8263ea120638404f97fc288c /drivers
parentdff010ac8e57e43669518a14c0e945dfeb80c2a7 (diff)
iwlwifi: multiple force reset mode
Provide the function to perform different type of uCode reset/reload operation. When uCode detect error and can not fix itself, this iwl_force_reset() function allow driver to perform the necessary reset/reload functions and help to bring uCode back to normal operation state. Currently only 2 type of force reset are available: - reset radio - reload firmware Signed-off-by: Wey-Yi Guy <wey-yi.w.guy@intel.com> Signed-off-by: Reinette Chatre <reinette.chatre@intel.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-core.c44
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-core.h2
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-dev.h9
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-rx.c2
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-scan.c10
5 files changed, 52 insertions, 15 deletions
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c
index d390eef2efe5..500ced452098 100644
--- a/drivers/net/wireless/iwlwifi/iwl-core.c
+++ b/drivers/net/wireless/iwlwifi/iwl-core.c
@@ -3334,7 +3334,7 @@ int iwl_dump_fh(struct iwl_priv *priv, char **buf, bool display)
3334} 3334}
3335EXPORT_SYMBOL(iwl_dump_fh); 3335EXPORT_SYMBOL(iwl_dump_fh);
3336 3336
3337void iwl_force_rf_reset(struct iwl_priv *priv) 3337static void iwl_force_rf_reset(struct iwl_priv *priv)
3338{ 3338{
3339 if (test_bit(STATUS_EXIT_PENDING, &priv->status)) 3339 if (test_bit(STATUS_EXIT_PENDING, &priv->status))
3340 return; 3340 return;
@@ -3356,7 +3356,47 @@ void iwl_force_rf_reset(struct iwl_priv *priv)
3356 iwl_internal_short_hw_scan(priv); 3356 iwl_internal_short_hw_scan(priv);
3357 return; 3357 return;
3358} 3358}
3359EXPORT_SYMBOL(iwl_force_rf_reset); 3359
3360#define IWL_DELAY_NEXT_FORCE_RESET (HZ*3)
3361
3362int iwl_force_reset(struct iwl_priv *priv, int mode)
3363{
3364 if (test_bit(STATUS_EXIT_PENDING, &priv->status))
3365 return -EINVAL;
3366
3367 if (priv->last_force_reset_jiffies &&
3368 time_after(priv->last_force_reset_jiffies +
3369 IWL_DELAY_NEXT_FORCE_RESET, jiffies)) {
3370 IWL_DEBUG_INFO(priv, "force reset rejected\n");
3371 return -EAGAIN;
3372 }
3373
3374 IWL_DEBUG_INFO(priv, "perform force reset (%d)\n", mode);
3375
3376 switch (mode) {
3377 case IWL_RF_RESET:
3378 iwl_force_rf_reset(priv);
3379 break;
3380 case IWL_FW_RESET:
3381 IWL_ERR(priv, "On demand firmware reload\n");
3382 /* Set the FW error flag -- cleared on iwl_down */
3383 set_bit(STATUS_FW_ERROR, &priv->status);
3384 wake_up_interruptible(&priv->wait_command_queue);
3385 /*
3386 * Keep the restart process from trying to send host
3387 * commands by clearing the INIT status bit
3388 */
3389 clear_bit(STATUS_READY, &priv->status);
3390 queue_work(priv->workqueue, &priv->restart);
3391 break;
3392 default:
3393 IWL_DEBUG_INFO(priv, "invalid reset request.\n");
3394 return -EINVAL;
3395 }
3396 priv->last_force_reset_jiffies = jiffies;
3397
3398 return 0;
3399}
3360 3400
3361#ifdef CONFIG_PM 3401#ifdef CONFIG_PM
3362 3402
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h
index 8f0c564e68b0..df558796fbe6 100644
--- a/drivers/net/wireless/iwlwifi/iwl-core.h
+++ b/drivers/net/wireless/iwlwifi/iwl-core.h
@@ -501,7 +501,7 @@ int iwl_scan_cancel(struct iwl_priv *priv);
501int iwl_scan_cancel_timeout(struct iwl_priv *priv, unsigned long ms); 501int iwl_scan_cancel_timeout(struct iwl_priv *priv, unsigned long ms);
502int iwl_mac_hw_scan(struct ieee80211_hw *hw, struct cfg80211_scan_request *req); 502int iwl_mac_hw_scan(struct ieee80211_hw *hw, struct cfg80211_scan_request *req);
503int iwl_internal_short_hw_scan(struct iwl_priv *priv); 503int iwl_internal_short_hw_scan(struct iwl_priv *priv);
504void iwl_force_rf_reset(struct iwl_priv *priv); 504int iwl_force_reset(struct iwl_priv *priv, int mode);
505u16 iwl_fill_probe_req(struct iwl_priv *priv, struct ieee80211_mgmt *frame, 505u16 iwl_fill_probe_req(struct iwl_priv *priv, struct ieee80211_mgmt *frame,
506 const u8 *ie, int ie_len, int left); 506 const u8 *ie, int ie_len, int left);
507void iwl_setup_rx_scan_handlers(struct iwl_priv *priv); 507void iwl_setup_rx_scan_handlers(struct iwl_priv *priv);
diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h
index 55dc5a866542..9f1d302e3a34 100644
--- a/drivers/net/wireless/iwlwifi/iwl-dev.h
+++ b/drivers/net/wireless/iwlwifi/iwl-dev.h
@@ -1035,6 +1035,11 @@ struct iwl_event_log {
1035#define IWL_MAX_PLCP_ERR_LONG_THRESHOLD_DEF (100) 1035#define IWL_MAX_PLCP_ERR_LONG_THRESHOLD_DEF (100)
1036#define IWL_MAX_PLCP_ERR_THRESHOLD_MAX (255) 1036#define IWL_MAX_PLCP_ERR_THRESHOLD_MAX (255)
1037 1037
1038enum iwl_reset {
1039 IWL_RF_RESET = 0,
1040 IWL_FW_RESET,
1041};
1042
1038struct iwl_priv { 1043struct iwl_priv {
1039 1044
1040 /* ieee device used by generic ieee processing code */ 1045 /* ieee device used by generic ieee processing code */
@@ -1066,6 +1071,9 @@ struct iwl_priv {
1066 /* storing the jiffies when the plcp error rate is received */ 1071 /* storing the jiffies when the plcp error rate is received */
1067 unsigned long plcp_jiffies; 1072 unsigned long plcp_jiffies;
1068 1073
1074 /* force reset */
1075 unsigned long last_force_reset_jiffies;
1076
1069 /* we allocate array of iwl4965_channel_info for NIC's valid channels. 1077 /* we allocate array of iwl4965_channel_info for NIC's valid channels.
1070 * Access via channel # using indirect index array */ 1078 * Access via channel # using indirect index array */
1071 struct iwl_channel_info *channel_info; /* channel info array */ 1079 struct iwl_channel_info *channel_info; /* channel info array */
@@ -1087,7 +1095,6 @@ struct iwl_priv {
1087 unsigned long scan_start; 1095 unsigned long scan_start;
1088 unsigned long scan_pass_start; 1096 unsigned long scan_pass_start;
1089 unsigned long scan_start_tsf; 1097 unsigned long scan_start_tsf;
1090 unsigned long last_internal_scan_jiffies;
1091 void *scan; 1098 void *scan;
1092 int scan_bands; 1099 int scan_bands;
1093 struct cfg80211_scan_request *scan_request; 1100 struct cfg80211_scan_request *scan_request;
diff --git a/drivers/net/wireless/iwlwifi/iwl-rx.c b/drivers/net/wireless/iwlwifi/iwl-rx.c
index 5df66382d922..909d9c9b9ad8 100644
--- a/drivers/net/wireless/iwlwifi/iwl-rx.c
+++ b/drivers/net/wireless/iwlwifi/iwl-rx.c
@@ -689,7 +689,7 @@ void iwl_rx_statistics(struct iwl_priv *priv,
689 * Reset the RF radio due to the high plcp 689 * Reset the RF radio due to the high plcp
690 * error rate 690 * error rate
691 */ 691 */
692 iwl_force_rf_reset(priv); 692 iwl_force_reset(priv, IWL_RF_RESET);
693 } 693 }
694 } 694 }
695 695
diff --git a/drivers/net/wireless/iwlwifi/iwl-scan.c b/drivers/net/wireless/iwlwifi/iwl-scan.c
index f786a407638f..501477464e07 100644
--- a/drivers/net/wireless/iwlwifi/iwl-scan.c
+++ b/drivers/net/wireless/iwlwifi/iwl-scan.c
@@ -250,8 +250,6 @@ static void iwl_rx_scan_complete_notif(struct iwl_priv *priv,
250 250
251 if (!priv->is_internal_short_scan) 251 if (!priv->is_internal_short_scan)
252 priv->next_scan_jiffies = 0; 252 priv->next_scan_jiffies = 0;
253 else
254 priv->last_internal_scan_jiffies = jiffies;
255 253
256 IWL_DEBUG_INFO(priv, "Setting scan to off\n"); 254 IWL_DEBUG_INFO(priv, "Setting scan to off\n");
257 255
@@ -551,8 +549,6 @@ EXPORT_SYMBOL(iwl_mac_hw_scan);
551 * internal short scan, this function should only been called while associated. 549 * internal short scan, this function should only been called while associated.
552 * It will reset and tune the radio to prevent possible RF related problem 550 * It will reset and tune the radio to prevent possible RF related problem
553 */ 551 */
554#define IWL_DELAY_NEXT_INTERNAL_SCAN (HZ*1)
555
556int iwl_internal_short_hw_scan(struct iwl_priv *priv) 552int iwl_internal_short_hw_scan(struct iwl_priv *priv)
557{ 553{
558 int ret = 0; 554 int ret = 0;
@@ -572,12 +568,6 @@ int iwl_internal_short_hw_scan(struct iwl_priv *priv)
572 ret = -EAGAIN; 568 ret = -EAGAIN;
573 goto out; 569 goto out;
574 } 570 }
575 if (priv->last_internal_scan_jiffies &&
576 time_after(priv->last_internal_scan_jiffies +
577 IWL_DELAY_NEXT_INTERNAL_SCAN, jiffies)) {
578 IWL_DEBUG_SCAN(priv, "internal scan rejected\n");
579 goto out;
580 }
581 571
582 priv->scan_bands = 0; 572 priv->scan_bands = 0;
583 if (priv->band == IEEE80211_BAND_5GHZ) 573 if (priv->band == IEEE80211_BAND_5GHZ)