2 * Scan implementation for ST-Ericsson CW1200 mac80211 drivers
4 * Copyright (c) 2010, ST-Ericsson
5 * Author: Dmitry Tarnyagin <dmitry.tarnyagin@lockless.no>
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation.
12 #include <linux/sched.h>
18 static void cw1200_scan_restart_delayed(struct cw1200_common
*priv
);
20 static int cw1200_scan_start(struct cw1200_common
*priv
, struct wsm_scan
*scan
)
25 switch (priv
->join_status
) {
26 case CW1200_JOIN_STATUS_PRE_STA
:
27 case CW1200_JOIN_STATUS_JOINING
:
33 wiphy_dbg(priv
->hw
->wiphy
, "[SCAN] hw req, type %d, %d channels, flags: 0x%x.\n",
34 scan
->type
, scan
->num_channels
, scan
->flags
);
36 for (i
= 0; i
< scan
->num_channels
; ++i
)
37 tmo
+= scan
->ch
[i
].max_chan_time
+ 10;
39 cancel_delayed_work_sync(&priv
->clear_recent_scan_work
);
40 atomic_set(&priv
->scan
.in_progress
, 1);
41 atomic_set(&priv
->recent_scan
, 1);
42 cw1200_pm_stay_awake(&priv
->pm_state
, msecs_to_jiffies(tmo
));
43 queue_delayed_work(priv
->workqueue
, &priv
->scan
.timeout
,
44 msecs_to_jiffies(tmo
));
45 ret
= wsm_scan(priv
, scan
);
47 atomic_set(&priv
->scan
.in_progress
, 0);
48 cancel_delayed_work_sync(&priv
->scan
.timeout
);
49 cw1200_scan_restart_delayed(priv
);
54 int cw1200_hw_scan(struct ieee80211_hw
*hw
,
55 struct ieee80211_vif
*vif
,
56 struct ieee80211_scan_request
*hw_req
)
58 struct cw1200_common
*priv
= hw
->priv
;
59 struct cfg80211_scan_request
*req
= &hw_req
->req
;
60 struct wsm_template_frame frame
= {
61 .frame_type
= WSM_FRAME_TYPE_PROBE_REQUEST
,
68 /* Scan when P2P_GO corrupt firmware MiniAP mode */
69 if (priv
->join_status
== CW1200_JOIN_STATUS_AP
)
72 if (req
->n_ssids
== 1 && !req
->ssids
[0].ssid_len
)
75 wiphy_dbg(hw
->wiphy
, "[SCAN] Scan request for %d SSIDs.\n",
78 if (req
->n_ssids
> WSM_SCAN_MAX_NUM_OF_SSIDS
)
81 frame
.skb
= ieee80211_probereq_get(hw
, priv
->vif
->addr
, NULL
, 0,
87 skb_put_data(frame
.skb
, req
->ie
, req
->ie_len
);
89 /* will be unlocked in cw1200_scan_work() */
90 down(&priv
->scan
.lock
);
91 mutex_lock(&priv
->conf_mutex
);
93 ret
= wsm_set_template_frame(priv
, &frame
);
95 /* Host want to be the probe responder. */
96 ret
= wsm_set_probe_responder(priv
, true);
99 mutex_unlock(&priv
->conf_mutex
);
100 up(&priv
->scan
.lock
);
101 dev_kfree_skb(frame
.skb
);
107 BUG_ON(priv
->scan
.req
);
108 priv
->scan
.req
= req
;
109 priv
->scan
.n_ssids
= 0;
110 priv
->scan
.status
= 0;
111 priv
->scan
.begin
= &req
->channels
[0];
112 priv
->scan
.curr
= priv
->scan
.begin
;
113 priv
->scan
.end
= &req
->channels
[req
->n_channels
];
114 priv
->scan
.output_power
= priv
->output_power
;
116 for (i
= 0; i
< req
->n_ssids
; ++i
) {
117 struct wsm_ssid
*dst
= &priv
->scan
.ssids
[priv
->scan
.n_ssids
];
118 memcpy(&dst
->ssid
[0], req
->ssids
[i
].ssid
, sizeof(dst
->ssid
));
119 dst
->length
= req
->ssids
[i
].ssid_len
;
120 ++priv
->scan
.n_ssids
;
123 mutex_unlock(&priv
->conf_mutex
);
126 dev_kfree_skb(frame
.skb
);
127 queue_work(priv
->workqueue
, &priv
->scan
.work
);
131 void cw1200_scan_work(struct work_struct
*work
)
133 struct cw1200_common
*priv
= container_of(work
, struct cw1200_common
,
135 struct ieee80211_channel
**it
;
136 struct wsm_scan scan
= {
137 .type
= WSM_SCAN_TYPE_FOREGROUND
,
138 .flags
= WSM_SCAN_FLAG_SPLIT_METHOD
,
140 bool first_run
= (priv
->scan
.begin
== priv
->scan
.curr
&&
141 priv
->scan
.begin
!= priv
->scan
.end
);
145 /* Firmware gets crazy if scan request is sent
146 * when STA is joined but not yet associated.
147 * Force unjoin in this case.
149 if (cancel_delayed_work_sync(&priv
->join_timeout
) > 0)
150 cw1200_join_timeout(&priv
->join_timeout
.work
);
153 mutex_lock(&priv
->conf_mutex
);
156 if (priv
->join_status
== CW1200_JOIN_STATUS_STA
&&
157 !(priv
->powersave_mode
.mode
& WSM_PSM_PS
)) {
158 struct wsm_set_pm pm
= priv
->powersave_mode
;
159 pm
.mode
= WSM_PSM_PS
;
160 cw1200_set_pm(priv
, &pm
);
161 } else if (priv
->join_status
== CW1200_JOIN_STATUS_MONITOR
) {
162 /* FW bug: driver has to restart p2p-dev mode
165 cw1200_disable_listening(priv
);
169 if (!priv
->scan
.req
|| (priv
->scan
.curr
== priv
->scan
.end
)) {
170 struct cfg80211_scan_info info
= {
171 .aborted
= priv
->scan
.status
? 1 : 0,
174 if (priv
->scan
.output_power
!= priv
->output_power
)
175 wsm_set_output_power(priv
, priv
->output_power
* 10);
176 if (priv
->join_status
== CW1200_JOIN_STATUS_STA
&&
177 !(priv
->powersave_mode
.mode
& WSM_PSM_PS
))
178 cw1200_set_pm(priv
, &priv
->powersave_mode
);
180 if (priv
->scan
.status
< 0)
181 wiphy_warn(priv
->hw
->wiphy
,
182 "[SCAN] Scan failed (%d).\n",
184 else if (priv
->scan
.req
)
185 wiphy_dbg(priv
->hw
->wiphy
,
186 "[SCAN] Scan completed.\n");
188 wiphy_dbg(priv
->hw
->wiphy
,
189 "[SCAN] Scan canceled.\n");
191 priv
->scan
.req
= NULL
;
192 cw1200_scan_restart_delayed(priv
);
194 mutex_unlock(&priv
->conf_mutex
);
195 ieee80211_scan_completed(priv
->hw
, &info
);
196 up(&priv
->scan
.lock
);
199 struct ieee80211_channel
*first
= *priv
->scan
.curr
;
200 for (it
= priv
->scan
.curr
+ 1, i
= 1;
201 it
!= priv
->scan
.end
&& i
< WSM_SCAN_MAX_NUM_OF_CHANNELS
;
203 if ((*it
)->band
!= first
->band
)
205 if (((*it
)->flags
^ first
->flags
) &
206 IEEE80211_CHAN_NO_IR
)
208 if (!(first
->flags
& IEEE80211_CHAN_NO_IR
) &&
209 (*it
)->max_power
!= first
->max_power
)
212 scan
.band
= first
->band
;
214 if (priv
->scan
.req
->no_cck
)
215 scan
.max_tx_rate
= WSM_TRANSMIT_RATE_6
;
217 scan
.max_tx_rate
= WSM_TRANSMIT_RATE_1
;
219 (first
->flags
& IEEE80211_CHAN_NO_IR
) ? 0 : 2;
220 scan
.num_ssids
= priv
->scan
.n_ssids
;
221 scan
.ssids
= &priv
->scan
.ssids
[0];
222 scan
.num_channels
= it
- priv
->scan
.curr
;
223 /* TODO: Is it optimal? */
224 scan
.probe_delay
= 100;
225 /* It is not stated in WSM specification, however
226 * FW team says that driver may not use FG scan
229 if (priv
->join_status
== CW1200_JOIN_STATUS_STA
) {
230 scan
.type
= WSM_SCAN_TYPE_BACKGROUND
;
231 scan
.flags
= WSM_SCAN_FLAG_FORCE_BACKGROUND
;
233 scan
.ch
= kcalloc(it
- priv
->scan
.curr
,
234 sizeof(struct wsm_scan_ch
),
237 priv
->scan
.status
= -ENOMEM
;
240 for (i
= 0; i
< scan
.num_channels
; ++i
) {
241 scan
.ch
[i
].number
= priv
->scan
.curr
[i
]->hw_value
;
242 if (priv
->scan
.curr
[i
]->flags
& IEEE80211_CHAN_NO_IR
) {
243 scan
.ch
[i
].min_chan_time
= 50;
244 scan
.ch
[i
].max_chan_time
= 100;
246 scan
.ch
[i
].min_chan_time
= 10;
247 scan
.ch
[i
].max_chan_time
= 25;
250 if (!(first
->flags
& IEEE80211_CHAN_NO_IR
) &&
251 priv
->scan
.output_power
!= first
->max_power
) {
252 priv
->scan
.output_power
= first
->max_power
;
253 wsm_set_output_power(priv
,
254 priv
->scan
.output_power
* 10);
256 priv
->scan
.status
= cw1200_scan_start(priv
, &scan
);
258 if (priv
->scan
.status
)
260 priv
->scan
.curr
= it
;
262 mutex_unlock(&priv
->conf_mutex
);
266 priv
->scan
.curr
= priv
->scan
.end
;
267 mutex_unlock(&priv
->conf_mutex
);
268 queue_work(priv
->workqueue
, &priv
->scan
.work
);
272 static void cw1200_scan_restart_delayed(struct cw1200_common
*priv
)
274 /* FW bug: driver has to restart p2p-dev mode after scan. */
275 if (priv
->join_status
== CW1200_JOIN_STATUS_MONITOR
) {
276 cw1200_enable_listening(priv
);
277 cw1200_update_filtering(priv
);
280 if (priv
->delayed_unjoin
) {
281 priv
->delayed_unjoin
= false;
282 if (queue_work(priv
->workqueue
, &priv
->unjoin_work
) <= 0)
284 } else if (priv
->delayed_link_loss
) {
285 wiphy_dbg(priv
->hw
->wiphy
, "[CQM] Requeue BSS loss.\n");
286 priv
->delayed_link_loss
= 0;
287 cw1200_cqm_bssloss_sm(priv
, 1, 0, 0);
291 static void cw1200_scan_complete(struct cw1200_common
*priv
)
293 queue_delayed_work(priv
->workqueue
, &priv
->clear_recent_scan_work
, HZ
);
294 if (priv
->scan
.direct_probe
) {
295 wiphy_dbg(priv
->hw
->wiphy
, "[SCAN] Direct probe complete.\n");
296 cw1200_scan_restart_delayed(priv
);
297 priv
->scan
.direct_probe
= 0;
298 up(&priv
->scan
.lock
);
301 cw1200_scan_work(&priv
->scan
.work
);
305 void cw1200_scan_failed_cb(struct cw1200_common
*priv
)
307 if (priv
->mode
== NL80211_IFTYPE_UNSPECIFIED
)
308 /* STA is stopped. */
311 if (cancel_delayed_work_sync(&priv
->scan
.timeout
) > 0) {
312 priv
->scan
.status
= -EIO
;
313 queue_delayed_work(priv
->workqueue
, &priv
->scan
.timeout
, 0);
318 void cw1200_scan_complete_cb(struct cw1200_common
*priv
,
319 struct wsm_scan_complete
*arg
)
321 if (priv
->mode
== NL80211_IFTYPE_UNSPECIFIED
)
322 /* STA is stopped. */
325 if (cancel_delayed_work_sync(&priv
->scan
.timeout
) > 0) {
326 priv
->scan
.status
= 1;
327 queue_delayed_work(priv
->workqueue
, &priv
->scan
.timeout
, 0);
331 void cw1200_clear_recent_scan_work(struct work_struct
*work
)
333 struct cw1200_common
*priv
=
334 container_of(work
, struct cw1200_common
,
335 clear_recent_scan_work
.work
);
336 atomic_xchg(&priv
->recent_scan
, 0);
339 void cw1200_scan_timeout(struct work_struct
*work
)
341 struct cw1200_common
*priv
=
342 container_of(work
, struct cw1200_common
, scan
.timeout
.work
);
343 if (atomic_xchg(&priv
->scan
.in_progress
, 0)) {
344 if (priv
->scan
.status
> 0) {
345 priv
->scan
.status
= 0;
346 } else if (!priv
->scan
.status
) {
347 wiphy_warn(priv
->hw
->wiphy
,
348 "Timeout waiting for scan complete notification.\n");
349 priv
->scan
.status
= -ETIMEDOUT
;
350 priv
->scan
.curr
= priv
->scan
.end
;
353 cw1200_scan_complete(priv
);
357 void cw1200_probe_work(struct work_struct
*work
)
359 struct cw1200_common
*priv
=
360 container_of(work
, struct cw1200_common
, scan
.probe_work
.work
);
361 u8 queue_id
= cw1200_queue_get_queue_id(priv
->pending_frame_id
);
362 struct cw1200_queue
*queue
= &priv
->tx_queue
[queue_id
];
363 const struct cw1200_txpriv
*txpriv
;
365 struct wsm_template_frame frame
= {
366 .frame_type
= WSM_FRAME_TYPE_PROBE_REQUEST
,
368 struct wsm_ssid ssids
[1] = {{
371 struct wsm_scan_ch ch
[1] = {{
375 struct wsm_scan scan
= {
376 .type
= WSM_SCAN_TYPE_FOREGROUND
,
387 wiphy_dbg(priv
->hw
->wiphy
, "[SCAN] Direct probe work.\n");
389 mutex_lock(&priv
->conf_mutex
);
390 if (down_trylock(&priv
->scan
.lock
)) {
391 /* Scan is already in progress. Requeue self. */
393 queue_delayed_work(priv
->workqueue
, &priv
->scan
.probe_work
,
394 msecs_to_jiffies(100));
395 mutex_unlock(&priv
->conf_mutex
);
399 /* Make sure we still have a pending probe req */
400 if (cw1200_queue_get_skb(queue
, priv
->pending_frame_id
,
401 &frame
.skb
, &txpriv
)) {
402 up(&priv
->scan
.lock
);
403 mutex_unlock(&priv
->conf_mutex
);
407 wsm
= (struct wsm_tx
*)frame
.skb
->data
;
408 scan
.max_tx_rate
= wsm
->max_tx_rate
;
409 scan
.band
= (priv
->channel
->band
== NL80211_BAND_5GHZ
) ?
410 WSM_PHY_BAND_5G
: WSM_PHY_BAND_2_4G
;
411 if (priv
->join_status
== CW1200_JOIN_STATUS_STA
||
412 priv
->join_status
== CW1200_JOIN_STATUS_IBSS
) {
413 scan
.type
= WSM_SCAN_TYPE_BACKGROUND
;
414 scan
.flags
= WSM_SCAN_FLAG_FORCE_BACKGROUND
;
416 ch
[0].number
= priv
->channel
->hw_value
;
418 skb_pull(frame
.skb
, txpriv
->offset
);
420 ies
= &frame
.skb
->data
[sizeof(struct ieee80211_hdr_3addr
)];
421 ies_len
= frame
.skb
->len
- sizeof(struct ieee80211_hdr_3addr
);
425 (u8
*)cfg80211_find_ie(WLAN_EID_SSID
, ies
, ies_len
);
426 if (ssidie
&& ssidie
[1] && ssidie
[1] <= sizeof(ssids
[0].ssid
)) {
427 u8
*nextie
= &ssidie
[2 + ssidie
[1]];
428 /* Remove SSID from the IE list. It has to be provided
429 * as a separate argument in cw1200_scan_start call
432 /* Store SSID localy */
433 ssids
[0].length
= ssidie
[1];
434 memcpy(ssids
[0].ssid
, &ssidie
[2], ssids
[0].length
);
437 /* Remove SSID from IE list */
439 memmove(&ssidie
[2], nextie
, &ies
[ies_len
] - nextie
);
440 skb_trim(frame
.skb
, frame
.skb
->len
- ssids
[0].length
);
444 /* FW bug: driver has to restart p2p-dev mode after scan */
445 if (priv
->join_status
== CW1200_JOIN_STATUS_MONITOR
)
446 cw1200_disable_listening(priv
);
447 ret
= wsm_set_template_frame(priv
, &frame
);
448 priv
->scan
.direct_probe
= 1;
451 ret
= cw1200_scan_start(priv
, &scan
);
453 mutex_unlock(&priv
->conf_mutex
);
455 skb_push(frame
.skb
, txpriv
->offset
);
457 IEEE80211_SKB_CB(frame
.skb
)->flags
|= IEEE80211_TX_STAT_ACK
;
458 BUG_ON(cw1200_queue_remove(queue
, priv
->pending_frame_id
));
461 priv
->scan
.direct_probe
= 0;
462 up(&priv
->scan
.lock
);