aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-agn-rx.c2
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-agn.c6
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-agn.h1
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-core.c71
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-core.h1
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-debugfs.c64
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-dev.h16
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-trans-pcie.c16
8 files changed, 62 insertions, 115 deletions
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rx.c b/drivers/net/wireless/iwlwifi/iwl-agn-rx.c
index 25abbb9b5e07..934ace9468d6 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn-rx.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn-rx.c
@@ -307,7 +307,7 @@ static void iwlagn_recover_from_statistics(struct iwl_priv *priv,
307 307
308 if (iwlagn_mod_params.plcp_check && 308 if (iwlagn_mod_params.plcp_check &&
309 !iwlagn_good_plcp_health(priv, cur_ofdm, cur_ofdm_ht, msecs)) 309 !iwlagn_good_plcp_health(priv, cur_ofdm, cur_ofdm_ht, msecs))
310 iwl_force_reset(priv, IWL_RF_RESET, false); 310 iwl_force_rf_reset(priv, false);
311} 311}
312 312
313/* Calculate noise level, based on measurements during network silence just 313/* Calculate noise level, based on measurements during network silence just
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c
index 096c227640a7..5216713105c6 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn.c
@@ -1332,12 +1332,6 @@ static int iwl_init_drv(struct iwl_priv *priv)
1332 1332
1333 priv->ucode_owner = IWL_OWNERSHIP_DRIVER; 1333 priv->ucode_owner = IWL_OWNERSHIP_DRIVER;
1334 1334
1335 /* initialize force reset */
1336 priv->force_reset[IWL_RF_RESET].reset_duration =
1337 IWL_DELAY_NEXT_FORCE_RF_RESET;
1338 priv->force_reset[IWL_FW_RESET].reset_duration =
1339 IWL_DELAY_NEXT_FORCE_FW_RELOAD;
1340
1341 priv->rx_statistics_jiffies = jiffies; 1335 priv->rx_statistics_jiffies = jiffies;
1342 1336
1343 /* Choose which receivers/antennas to use */ 1337 /* Choose which receivers/antennas to use */
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.h b/drivers/net/wireless/iwlwifi/iwl-agn.h
index 51001622430b..da5ea1b87e6b 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn.h
+++ b/drivers/net/wireless/iwlwifi/iwl-agn.h
@@ -195,6 +195,7 @@ u8 iwl_toggle_tx_ant(struct iwl_priv *priv, u8 ant_idx, u8 valid);
195/* scan */ 195/* scan */
196void iwlagn_post_scan(struct iwl_priv *priv); 196void iwlagn_post_scan(struct iwl_priv *priv);
197void iwlagn_disable_roc(struct iwl_priv *priv); 197void iwlagn_disable_roc(struct iwl_priv *priv);
198int iwl_force_rf_reset(struct iwl_priv *priv, bool external);
198 199
199/* bt coex */ 200/* bt coex */
200void iwlagn_send_advance_bt_config(struct iwl_priv *priv); 201void iwlagn_send_advance_bt_config(struct iwl_priv *priv);
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c
index 6fc1841ff536..6a02ade07a24 100644
--- a/drivers/net/wireless/iwlwifi/iwl-core.c
+++ b/drivers/net/wireless/iwlwifi/iwl-core.c
@@ -746,15 +746,30 @@ void iwl_update_stats(struct iwl_priv *priv, bool is_tx, __le16 fc, u16 len)
746} 746}
747#endif 747#endif
748 748
749static void iwl_force_rf_reset(struct iwl_priv *priv) 749int iwl_force_rf_reset(struct iwl_priv *priv, bool external)
750{ 750{
751 struct iwl_rf_reset *rf_reset;
752
751 if (test_bit(STATUS_EXIT_PENDING, &priv->status)) 753 if (test_bit(STATUS_EXIT_PENDING, &priv->status))
752 return; 754 return -EAGAIN;
753 755
754 if (!iwl_is_any_associated(priv)) { 756 if (!iwl_is_any_associated(priv)) {
755 IWL_DEBUG_SCAN(priv, "force reset rejected: not associated\n"); 757 IWL_DEBUG_SCAN(priv, "force reset rejected: not associated\n");
756 return; 758 return -ENOLINK;
757 } 759 }
760
761 rf_reset = &priv->rf_reset;
762 rf_reset->reset_request_count++;
763 if (!external && rf_reset->last_reset_jiffies &&
764 time_after(rf_reset->last_reset_jiffies +
765 IWL_DELAY_NEXT_FORCE_RF_RESET, jiffies)) {
766 IWL_DEBUG_INFO(priv, "RF reset rejected\n");
767 rf_reset->reset_reject_count++;
768 return -EAGAIN;
769 }
770 rf_reset->reset_success_count++;
771 rf_reset->last_reset_jiffies = jiffies;
772
758 /* 773 /*
759 * There is no easy and better way to force reset the radio, 774 * There is no easy and better way to force reset the radio,
760 * the only known method is switching channel which will force to 775 * the only known method is switching channel which will force to
@@ -766,56 +781,6 @@ static void iwl_force_rf_reset(struct iwl_priv *priv)
766 */ 781 */
767 IWL_DEBUG_INFO(priv, "perform radio reset.\n"); 782 IWL_DEBUG_INFO(priv, "perform radio reset.\n");
768 iwl_internal_short_hw_scan(priv); 783 iwl_internal_short_hw_scan(priv);
769}
770
771
772int iwl_force_reset(struct iwl_priv *priv, int mode, bool external)
773{
774 struct iwl_force_reset *force_reset;
775
776 if (test_bit(STATUS_EXIT_PENDING, &priv->status))
777 return -EINVAL;
778
779 if (mode >= IWL_MAX_FORCE_RESET) {
780 IWL_DEBUG_INFO(priv, "invalid reset request.\n");
781 return -EINVAL;
782 }
783 force_reset = &priv->force_reset[mode];
784 force_reset->reset_request_count++;
785 if (!external) {
786 if (force_reset->last_force_reset_jiffies &&
787 time_after(force_reset->last_force_reset_jiffies +
788 force_reset->reset_duration, jiffies)) {
789 IWL_DEBUG_INFO(priv, "force reset rejected\n");
790 force_reset->reset_reject_count++;
791 return -EAGAIN;
792 }
793 }
794 force_reset->reset_success_count++;
795 force_reset->last_force_reset_jiffies = jiffies;
796 IWL_DEBUG_INFO(priv, "perform force reset (%d)\n", mode);
797 switch (mode) {
798 case IWL_RF_RESET:
799 iwl_force_rf_reset(priv);
800 break;
801 case IWL_FW_RESET:
802 /*
803 * if the request is from external(ex: debugfs),
804 * then always perform the request in regardless the module
805 * parameter setting
806 * if the request is from internal (uCode error or driver
807 * detect failure), then fw_restart module parameter
808 * need to be check before performing firmware reload
809 */
810 if (!external && !iwlagn_mod_params.restart_fw) {
811 IWL_DEBUG_INFO(priv, "Cancel firmware reload based on "
812 "module parameter setting\n");
813 break;
814 }
815 IWL_ERR(priv, "On demand firmware reload\n");
816 iwlagn_fw_error(priv, true);
817 break;
818 }
819 return 0; 784 return 0;
820} 785}
821 786
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h
index f388dc4474da..999a806a3848 100644
--- a/drivers/net/wireless/iwlwifi/iwl-core.h
+++ b/drivers/net/wireless/iwlwifi/iwl-core.h
@@ -164,7 +164,6 @@ int iwl_scan_cancel(struct iwl_priv *priv);
164void iwl_scan_cancel_timeout(struct iwl_priv *priv, unsigned long ms); 164void iwl_scan_cancel_timeout(struct iwl_priv *priv, unsigned long ms);
165void iwl_force_scan_end(struct iwl_priv *priv); 165void iwl_force_scan_end(struct iwl_priv *priv);
166void iwl_internal_short_hw_scan(struct iwl_priv *priv); 166void iwl_internal_short_hw_scan(struct iwl_priv *priv);
167int iwl_force_reset(struct iwl_priv *priv, int mode, bool external);
168void iwl_setup_rx_scan_handlers(struct iwl_priv *priv); 167void iwl_setup_rx_scan_handlers(struct iwl_priv *priv);
169void iwl_setup_scan_deferred_work(struct iwl_priv *priv); 168void iwl_setup_scan_deferred_work(struct iwl_priv *priv);
170void iwl_cancel_scan_deferred_work(struct iwl_priv *priv); 169void iwl_cancel_scan_deferred_work(struct iwl_priv *priv);
diff --git a/drivers/net/wireless/iwlwifi/iwl-debugfs.c b/drivers/net/wireless/iwlwifi/iwl-debugfs.c
index eaf5e66e603c..2e85edac560c 100644
--- a/drivers/net/wireless/iwlwifi/iwl-debugfs.c
+++ b/drivers/net/wireless/iwlwifi/iwl-debugfs.c
@@ -2267,59 +2267,39 @@ static ssize_t iwl_dbgfs_plcp_delta_write(struct file *file,
2267 return count; 2267 return count;
2268} 2268}
2269 2269
2270static ssize_t iwl_dbgfs_force_reset_read(struct file *file, 2270static ssize_t iwl_dbgfs_rf_reset_read(struct file *file,
2271 char __user *user_buf, 2271 char __user *user_buf,
2272 size_t count, loff_t *ppos) 2272 size_t count, loff_t *ppos)
2273{ 2273{
2274 struct iwl_priv *priv = file->private_data; 2274 struct iwl_priv *priv = file->private_data;
2275 int i, pos = 0; 2275 int pos = 0;
2276 char buf[300]; 2276 char buf[300];
2277 const size_t bufsz = sizeof(buf); 2277 const size_t bufsz = sizeof(buf);
2278 struct iwl_force_reset *force_reset; 2278 struct iwl_rf_reset *rf_reset = &priv->rf_reset;
2279
2280 pos += scnprintf(buf + pos, bufsz - pos,
2281 "RF reset statistics\n");
2282 pos += scnprintf(buf + pos, bufsz - pos,
2283 "\tnumber of reset request: %d\n",
2284 rf_reset->reset_request_count);
2285 pos += scnprintf(buf + pos, bufsz - pos,
2286 "\tnumber of reset request success: %d\n",
2287 rf_reset->reset_success_count);
2288 pos += scnprintf(buf + pos, bufsz - pos,
2289 "\tnumber of reset request reject: %d\n",
2290 rf_reset->reset_reject_count);
2279 2291
2280 for (i = 0; i < IWL_MAX_FORCE_RESET; i++) {
2281 force_reset = &priv->force_reset[i];
2282 pos += scnprintf(buf + pos, bufsz - pos,
2283 "Force reset method %d\n", i);
2284 pos += scnprintf(buf + pos, bufsz - pos,
2285 "\tnumber of reset request: %d\n",
2286 force_reset->reset_request_count);
2287 pos += scnprintf(buf + pos, bufsz - pos,
2288 "\tnumber of reset request success: %d\n",
2289 force_reset->reset_success_count);
2290 pos += scnprintf(buf + pos, bufsz - pos,
2291 "\tnumber of reset request reject: %d\n",
2292 force_reset->reset_reject_count);
2293 pos += scnprintf(buf + pos, bufsz - pos,
2294 "\treset duration: %lu\n",
2295 force_reset->reset_duration);
2296 }
2297 return simple_read_from_buffer(user_buf, count, ppos, buf, pos); 2292 return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
2298} 2293}
2299 2294
2300static ssize_t iwl_dbgfs_force_reset_write(struct file *file, 2295static ssize_t iwl_dbgfs_rf_reset_write(struct file *file,
2301 const char __user *user_buf, 2296 const char __user *user_buf,
2302 size_t count, loff_t *ppos) { 2297 size_t count, loff_t *ppos) {
2303 2298
2304 struct iwl_priv *priv = file->private_data; 2299 struct iwl_priv *priv = file->private_data;
2305 char buf[8]; 2300 int ret;
2306 int buf_size;
2307 int reset, ret;
2308 2301
2309 memset(buf, 0, sizeof(buf)); 2302 ret = iwl_force_rf_reset(priv, true);
2310 buf_size = min(count, sizeof(buf) - 1);
2311 if (copy_from_user(buf, user_buf, buf_size))
2312 return -EFAULT;
2313 if (sscanf(buf, "%d", &reset) != 1)
2314 return -EINVAL;
2315 switch (reset) {
2316 case IWL_RF_RESET:
2317 case IWL_FW_RESET:
2318 ret = iwl_force_reset(priv, reset, true);
2319 break;
2320 default:
2321 return -EINVAL;
2322 }
2323 return ret ? ret : count; 2303 return ret ? ret : count;
2324} 2304}
2325 2305
@@ -2507,7 +2487,7 @@ DEBUGFS_WRITE_FILE_OPS(clear_traffic_statistics);
2507DEBUGFS_READ_WRITE_FILE_OPS(ucode_tracing); 2487DEBUGFS_READ_WRITE_FILE_OPS(ucode_tracing);
2508DEBUGFS_READ_WRITE_FILE_OPS(missed_beacon); 2488DEBUGFS_READ_WRITE_FILE_OPS(missed_beacon);
2509DEBUGFS_READ_WRITE_FILE_OPS(plcp_delta); 2489DEBUGFS_READ_WRITE_FILE_OPS(plcp_delta);
2510DEBUGFS_READ_WRITE_FILE_OPS(force_reset); 2490DEBUGFS_READ_WRITE_FILE_OPS(rf_reset);
2511DEBUGFS_READ_FILE_OPS(rxon_flags); 2491DEBUGFS_READ_FILE_OPS(rxon_flags);
2512DEBUGFS_READ_FILE_OPS(rxon_filter_flags); 2492DEBUGFS_READ_FILE_OPS(rxon_filter_flags);
2513DEBUGFS_WRITE_FILE_OPS(txfifo_flush); 2493DEBUGFS_WRITE_FILE_OPS(txfifo_flush);
@@ -2565,7 +2545,7 @@ int iwl_dbgfs_register(struct iwl_priv *priv, const char *name)
2565 DEBUGFS_ADD_FILE(clear_traffic_statistics, dir_debug, S_IWUSR); 2545 DEBUGFS_ADD_FILE(clear_traffic_statistics, dir_debug, S_IWUSR);
2566 DEBUGFS_ADD_FILE(missed_beacon, dir_debug, S_IWUSR); 2546 DEBUGFS_ADD_FILE(missed_beacon, dir_debug, S_IWUSR);
2567 DEBUGFS_ADD_FILE(plcp_delta, dir_debug, S_IWUSR | S_IRUSR); 2547 DEBUGFS_ADD_FILE(plcp_delta, dir_debug, S_IWUSR | S_IRUSR);
2568 DEBUGFS_ADD_FILE(force_reset, dir_debug, S_IWUSR | S_IRUSR); 2548 DEBUGFS_ADD_FILE(rf_reset, dir_debug, S_IWUSR | S_IRUSR);
2569 DEBUGFS_ADD_FILE(ucode_rx_stats, dir_debug, S_IRUSR); 2549 DEBUGFS_ADD_FILE(ucode_rx_stats, dir_debug, S_IRUSR);
2570 DEBUGFS_ADD_FILE(ucode_tx_stats, dir_debug, S_IRUSR); 2550 DEBUGFS_ADD_FILE(ucode_tx_stats, dir_debug, S_IRUSR);
2571 DEBUGFS_ADD_FILE(ucode_general_stats, dir_debug, S_IRUSR); 2551 DEBUGFS_ADD_FILE(ucode_general_stats, dir_debug, S_IRUSR);
diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h
index caaf14c3de1b..58073da16279 100644
--- a/drivers/net/wireless/iwlwifi/iwl-dev.h
+++ b/drivers/net/wireless/iwlwifi/iwl-dev.h
@@ -582,7 +582,6 @@ struct iwl_event_log {
582#define IWL_MAX_PLCP_ERR_THRESHOLD_DISABLE (0) 582#define IWL_MAX_PLCP_ERR_THRESHOLD_DISABLE (0)
583 583
584#define IWL_DELAY_NEXT_FORCE_RF_RESET (HZ*3) 584#define IWL_DELAY_NEXT_FORCE_RF_RESET (HZ*3)
585#define IWL_DELAY_NEXT_FORCE_FW_RELOAD (HZ*5)
586 585
587/* TX queue watchdog timeouts in mSecs */ 586/* TX queue watchdog timeouts in mSecs */
588#define IWL_WATCHHDOG_DISABLED (0) 587#define IWL_WATCHHDOG_DISABLED (0)
@@ -598,18 +597,11 @@ struct iwl_event_log {
598#define IWL_MAX_CONTINUE_RELOAD_CNT 4 597#define IWL_MAX_CONTINUE_RELOAD_CNT 4
599 598
600 599
601enum iwl_reset { 600struct iwl_rf_reset {
602 IWL_RF_RESET = 0,
603 IWL_FW_RESET,
604 IWL_MAX_FORCE_RESET,
605};
606
607struct iwl_force_reset {
608 int reset_request_count; 601 int reset_request_count;
609 int reset_success_count; 602 int reset_success_count;
610 int reset_reject_count; 603 int reset_reject_count;
611 unsigned long reset_duration; 604 unsigned long last_reset_jiffies;
612 unsigned long last_force_reset_jiffies;
613}; 605};
614 606
615/* extend beacon time format bit shifting */ 607/* extend beacon time format bit shifting */
@@ -806,8 +798,8 @@ struct iwl_priv {
806 /*counters */ 798 /*counters */
807 u32 rx_handlers_stats[REPLY_MAX]; 799 u32 rx_handlers_stats[REPLY_MAX];
808 800
809 /* force reset */ 801 /* rf reset */
810 struct iwl_force_reset force_reset[IWL_MAX_FORCE_RESET]; 802 struct iwl_rf_reset rf_reset;
811 803
812 /* firmware reload counter and timestamp */ 804 /* firmware reload counter and timestamp */
813 unsigned long reload_jiffies; 805 unsigned long reload_jiffies;
diff --git a/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c b/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c
index f3695fea45ef..914b6d5df9b2 100644
--- a/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c
+++ b/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c
@@ -1994,11 +1994,26 @@ static ssize_t iwl_dbgfs_fh_reg_read(struct file *file,
1994 return ret; 1994 return ret;
1995} 1995}
1996 1996
1997static ssize_t iwl_dbgfs_fw_restart_write(struct file *file,
1998 const char __user *user_buf,
1999 size_t count, loff_t *ppos)
2000{
2001 struct iwl_trans *trans = file->private_data;
2002
2003 if (!trans->op_mode)
2004 return -EAGAIN;
2005
2006 iwl_op_mode_nic_error(trans->op_mode);
2007
2008 return count;
2009}
2010
1997DEBUGFS_READ_WRITE_FILE_OPS(interrupt); 2011DEBUGFS_READ_WRITE_FILE_OPS(interrupt);
1998DEBUGFS_READ_FILE_OPS(fh_reg); 2012DEBUGFS_READ_FILE_OPS(fh_reg);
1999DEBUGFS_READ_FILE_OPS(rx_queue); 2013DEBUGFS_READ_FILE_OPS(rx_queue);
2000DEBUGFS_READ_FILE_OPS(tx_queue); 2014DEBUGFS_READ_FILE_OPS(tx_queue);
2001DEBUGFS_WRITE_FILE_OPS(csr); 2015DEBUGFS_WRITE_FILE_OPS(csr);
2016DEBUGFS_WRITE_FILE_OPS(fw_restart);
2002 2017
2003/* 2018/*
2004 * Create the debugfs files and directories 2019 * Create the debugfs files and directories
@@ -2012,6 +2027,7 @@ static int iwl_trans_pcie_dbgfs_register(struct iwl_trans *trans,
2012 DEBUGFS_ADD_FILE(interrupt, dir, S_IWUSR | S_IRUSR); 2027 DEBUGFS_ADD_FILE(interrupt, dir, S_IWUSR | S_IRUSR);
2013 DEBUGFS_ADD_FILE(csr, dir, S_IWUSR); 2028 DEBUGFS_ADD_FILE(csr, dir, S_IWUSR);
2014 DEBUGFS_ADD_FILE(fh_reg, dir, S_IRUSR); 2029 DEBUGFS_ADD_FILE(fh_reg, dir, S_IRUSR);
2030 DEBUGFS_ADD_FILE(fw_restart, dir, S_IWUSR);
2015 return 0; 2031 return 0;
2016} 2032}
2017#else 2033#else