aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net
diff options
context:
space:
mode:
authorJohannes Berg <johannes.berg@intel.com>2012-04-09 20:46:57 -0400
committerJohn W. Linville <linville@tuxdriver.com>2012-04-12 15:06:09 -0400
commit48dffd397ec13e7fb4a52b77e8b07ed8ea12a938 (patch)
tree3aa3299657eefd6c7dd5cb843b72b10cb6669d08 /drivers/net
parent4e80986d6dd141cab47c6ccfe1bce051f4f883d9 (diff)
iwlwifi: split force_reset debugfs file
Split the force_reset debugfs file into two different files: * "rf_reset" triggers a reset of the RF when written to and exposes statistics on RF resets when read * fw_restart triggers a firmware restart when written to and lives in the transport This cleans up all sources of firmware restart to originate within the transport layer and allows us to simplify some code. Signed-off-by: Johannes Berg <johannes.berg@intel.com> Signed-off-by: Wey-Yi Guy <wey-yi.w.guy@intel.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net')
-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