aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorStanislaw Gruszka <sgruszka@redhat.com>2010-09-13 08:46:36 -0400
committerJohn W. Linville <linville@tuxdriver.com>2010-09-14 16:08:04 -0400
commitcd44600fdd89832c0bc898189270a81be0db01cd (patch)
tree603e3c47b5a743a39f54762a1bb434b4cdec2b52 /drivers
parentd745d472afcbc6354ebfee008123894a7f37e97e (diff)
iwlwifi: report scan completion when abort fail
When we are not able to send abort command to firmware, notify mac80211 that we complete scan, as we will newer do it lately. Check for all possible errors that low level sending command procedure does not check, to assure we catch all failures cases. Patch fix one of the causes of wdev_cleanup_work warning reported at https://bugzilla.redhat.com/show_bug.cgi?id=593566 Signed-off-by: Stanislaw Gruszka <sgruszka@redhat.com> Acked-by: Wey-Yi W Guy <wey-yi.w.guy@intel.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-scan.c131
1 files changed, 67 insertions, 64 deletions
diff --git a/drivers/net/wireless/iwlwifi/iwl-scan.c b/drivers/net/wireless/iwlwifi/iwl-scan.c
index ea338498ee1c..dbb07e8dfcd7 100644
--- a/drivers/net/wireless/iwlwifi/iwl-scan.c
+++ b/drivers/net/wireless/iwlwifi/iwl-scan.c
@@ -54,34 +54,83 @@
54#define IWL_PASSIVE_DWELL_BASE (100) 54#define IWL_PASSIVE_DWELL_BASE (100)
55#define IWL_CHANNEL_TUNE_TIME 5 55#define IWL_CHANNEL_TUNE_TIME 5
56 56
57static int iwl_send_scan_abort(struct iwl_priv *priv)
58{
59 int ret;
60 struct iwl_rx_packet *pkt;
61 struct iwl_host_cmd cmd = {
62 .id = REPLY_SCAN_ABORT_CMD,
63 .flags = CMD_WANT_SKB,
64 };
57 65
66 /* Exit instantly with error when device is not ready
67 * to receive scan abort command or it does not perform
68 * hardware scan currently */
69 if (!test_bit(STATUS_READY, &priv->status) ||
70 !test_bit(STATUS_GEO_CONFIGURED, &priv->status) ||
71 !test_bit(STATUS_SCAN_HW, &priv->status) ||
72 test_bit(STATUS_FW_ERROR, &priv->status) ||
73 test_bit(STATUS_EXIT_PENDING, &priv->status))
74 return -EIO;
58 75
59/** 76 ret = iwl_send_cmd_sync(priv, &cmd);
60 * iwl_scan_cancel - Cancel any currently executing HW scan 77 if (ret)
61 * 78 return ret;
62 * NOTE: priv->mutex is not required before calling this function 79
63 */ 80 pkt = (struct iwl_rx_packet *)cmd.reply_page;
64int iwl_scan_cancel(struct iwl_priv *priv) 81 if (pkt->u.status != CAN_ABORT_STATUS) {
65{ 82 /* The scan abort will return 1 for success or
66 if (!test_bit(STATUS_SCAN_HW, &priv->status)) { 83 * 2 for "failure". A failure condition can be
67 clear_bit(STATUS_SCANNING, &priv->status); 84 * due to simply not being in an active scan which
68 return 0; 85 * can occur if we send the scan abort before we
86 * the microcode has notified us that a scan is
87 * completed. */
88 IWL_DEBUG_INFO(priv, "SCAN_ABORT ret %d.\n", pkt->u.status);
89 ret = -EIO;
69 } 90 }
70 91
71 if (test_bit(STATUS_SCANNING, &priv->status)) { 92 iwl_free_pages(priv, cmd.reply_page);
72 if (!test_and_set_bit(STATUS_SCAN_ABORTING, &priv->status)) { 93 return ret;
73 IWL_DEBUG_SCAN(priv, "Queuing scan abort.\n"); 94}
74 schedule_work(&priv->abort_scan);
75 95
76 } else 96static void iwl_do_scan_abort(struct iwl_priv *priv)
77 IWL_DEBUG_SCAN(priv, "Scan abort already in progress.\n"); 97{
98 int ret;
78 99
79 return test_bit(STATUS_SCANNING, &priv->status); 100 lockdep_assert_held(&priv->mutex);
101
102 if (!test_bit(STATUS_SCANNING, &priv->status)) {
103 IWL_DEBUG_SCAN(priv, "Not performing scan to abort\n");
104 return;
80 } 105 }
81 106
107 if (test_and_set_bit(STATUS_SCAN_ABORTING, &priv->status)) {
108 IWL_DEBUG_SCAN(priv, "Scan abort in progress\n");
109 return;
110 }
111
112 ret = iwl_send_scan_abort(priv);
113 if (ret) {
114 IWL_DEBUG_SCAN(priv, "Send scan abort failed %d\n", ret);
115 clear_bit(STATUS_SCANNING, &priv->status);
116 clear_bit(STATUS_SCAN_HW, &priv->status);
117 clear_bit(STATUS_SCAN_ABORTING, &priv->status);
118 ieee80211_scan_completed(priv->hw, true);
119 } else
120 IWL_DEBUG_SCAN(priv, "Sucessfully send scan abort\n");
121}
122
123/**
124 * iwl_scan_cancel - Cancel any currently executing HW scan
125 */
126int iwl_scan_cancel(struct iwl_priv *priv)
127{
128 IWL_DEBUG_SCAN(priv, "Queuing abort scan\n");
129 schedule_work(&priv->abort_scan);
82 return 0; 130 return 0;
83} 131}
84EXPORT_SYMBOL(iwl_scan_cancel); 132EXPORT_SYMBOL(iwl_scan_cancel);
133
85/** 134/**
86 * iwl_scan_cancel_timeout - Cancel any currently executing HW scan 135 * iwl_scan_cancel_timeout - Cancel any currently executing HW scan
87 * @ms: amount of time to wait (in milliseconds) for scan to abort 136 * @ms: amount of time to wait (in milliseconds) for scan to abort
@@ -108,47 +157,6 @@ int iwl_scan_cancel_timeout(struct iwl_priv *priv, unsigned long ms)
108} 157}
109EXPORT_SYMBOL(iwl_scan_cancel_timeout); 158EXPORT_SYMBOL(iwl_scan_cancel_timeout);
110 159
111static int iwl_send_scan_abort(struct iwl_priv *priv)
112{
113 int ret = 0;
114 struct iwl_rx_packet *pkt;
115 struct iwl_host_cmd cmd = {
116 .id = REPLY_SCAN_ABORT_CMD,
117 .flags = CMD_WANT_SKB,
118 };
119
120 /* If there isn't a scan actively going on in the hardware
121 * then we are in between scan bands and not actually
122 * actively scanning, so don't send the abort command */
123 if (!test_bit(STATUS_SCAN_HW, &priv->status)) {
124 clear_bit(STATUS_SCAN_ABORTING, &priv->status);
125 return 0;
126 }
127
128 ret = iwl_send_cmd_sync(priv, &cmd);
129 if (ret) {
130 clear_bit(STATUS_SCAN_ABORTING, &priv->status);
131 return ret;
132 }
133
134 pkt = (struct iwl_rx_packet *)cmd.reply_page;
135 if (pkt->u.status != CAN_ABORT_STATUS) {
136 /* The scan abort will return 1 for success or
137 * 2 for "failure". A failure condition can be
138 * due to simply not being in an active scan which
139 * can occur if we send the scan abort before we
140 * the microcode has notified us that a scan is
141 * completed. */
142 IWL_DEBUG_INFO(priv, "SCAN_ABORT returned %d.\n", pkt->u.status);
143 clear_bit(STATUS_SCAN_ABORTING, &priv->status);
144 clear_bit(STATUS_SCAN_HW, &priv->status);
145 }
146
147 iwl_free_pages(priv, cmd.reply_page);
148
149 return ret;
150}
151
152/* Service response to REPLY_SCAN_CMD (0x80) */ 160/* Service response to REPLY_SCAN_CMD (0x80) */
153static void iwl_rx_reply_scan(struct iwl_priv *priv, 161static void iwl_rx_reply_scan(struct iwl_priv *priv,
154 struct iwl_rx_mem_buffer *rxb) 162 struct iwl_rx_mem_buffer *rxb)
@@ -527,15 +535,10 @@ static void iwl_bg_abort_scan(struct work_struct *work)
527{ 535{
528 struct iwl_priv *priv = container_of(work, struct iwl_priv, abort_scan); 536 struct iwl_priv *priv = container_of(work, struct iwl_priv, abort_scan);
529 537
530 if (!test_bit(STATUS_READY, &priv->status) ||
531 !test_bit(STATUS_GEO_CONFIGURED, &priv->status))
532 return;
533
534 cancel_delayed_work(&priv->scan_check); 538 cancel_delayed_work(&priv->scan_check);
535 539
536 mutex_lock(&priv->mutex); 540 mutex_lock(&priv->mutex);
537 if (test_bit(STATUS_SCAN_ABORTING, &priv->status)) 541 iwl_do_scan_abort(priv);
538 iwl_send_scan_abort(priv);
539 mutex_unlock(&priv->mutex); 542 mutex_unlock(&priv->mutex);
540} 543}
541 544