aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/net/wireless/wl12xx/cmd.c3
-rw-r--r--drivers/net/wireless/wl12xx/event.c2
-rw-r--r--drivers/net/wireless/wl12xx/main.c104
-rw-r--r--drivers/net/wireless/wl12xx/ps.c10
-rw-r--r--drivers/net/wireless/wl12xx/scan.c18
-rw-r--r--drivers/net/wireless/wl12xx/wl12xx.h2
-rw-r--r--drivers/net/wireless/wl12xx/wl12xx_platform_data.c21
7 files changed, 96 insertions, 64 deletions
diff --git a/drivers/net/wireless/wl12xx/cmd.c b/drivers/net/wireless/wl12xx/cmd.c
index e0d21797948..25990bd38be 100644
--- a/drivers/net/wireless/wl12xx/cmd.c
+++ b/drivers/net/wireless/wl12xx/cmd.c
@@ -1835,6 +1835,9 @@ int wl12xx_stop_dev(struct wl1271 *wl, struct wl12xx_vif *wlvif)
1835 wlvif->bss_type == BSS_TYPE_IBSS))) 1835 wlvif->bss_type == BSS_TYPE_IBSS)))
1836 return -EINVAL; 1836 return -EINVAL;
1837 1837
1838 /* flush all pending packets */
1839 wl1271_tx_work_locked(wl);
1840
1838 if (test_bit(wlvif->dev_role_id, wl->roc_map)) { 1841 if (test_bit(wlvif->dev_role_id, wl->roc_map)) {
1839 ret = wl12xx_croc(wl, wlvif->dev_role_id); 1842 ret = wl12xx_croc(wl, wlvif->dev_role_id);
1840 if (ret < 0) 1843 if (ret < 0)
diff --git a/drivers/net/wireless/wl12xx/event.c b/drivers/net/wireless/wl12xx/event.c
index 00ce794eeba..d3280df68f5 100644
--- a/drivers/net/wireless/wl12xx/event.c
+++ b/drivers/net/wireless/wl12xx/event.c
@@ -267,8 +267,8 @@ static int wl1271_event_process(struct wl1271 *wl, struct event_mailbox *mbox)
267 wl1271_debug(DEBUG_EVENT, "PERIODIC_SCAN_COMPLETE_EVENT " 267 wl1271_debug(DEBUG_EVENT, "PERIODIC_SCAN_COMPLETE_EVENT "
268 "(status 0x%0x)", mbox->scheduled_scan_status); 268 "(status 0x%0x)", mbox->scheduled_scan_status);
269 if (wl->sched_scanning) { 269 if (wl->sched_scanning) {
270 wl1271_scan_sched_scan_stop(wl);
271 ieee80211_sched_scan_stopped(wl->hw); 270 ieee80211_sched_scan_stopped(wl->hw);
271 wl->sched_scanning = false;
272 } 272 }
273 } 273 }
274 274
diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c
index c3058419e22..d5f55a149de 100644
--- a/drivers/net/wireless/wl12xx/main.c
+++ b/drivers/net/wireless/wl12xx/main.c
@@ -450,7 +450,16 @@ static int wl1271_dev_notify(struct notifier_block *me, unsigned long what,
450 if (wl->state == WL1271_STATE_OFF) 450 if (wl->state == WL1271_STATE_OFF)
451 goto out; 451 goto out;
452 452
453 if (dev->operstate != IF_OPER_UP)
454 goto out;
455 /*
456 * The correct behavior should be just getting the appropriate wlvif
457 * from the given dev, but currently we don't have a mac80211
458 * interface for it.
459 */
453 wl12xx_for_each_wlvif_sta(wl, wlvif) { 460 wl12xx_for_each_wlvif_sta(wl, wlvif) {
461 struct ieee80211_vif *vif = wl12xx_wlvif_to_vif(wlvif);
462
454 if (!test_bit(WLVIF_FLAG_STA_ASSOCIATED, &wlvif->flags)) 463 if (!test_bit(WLVIF_FLAG_STA_ASSOCIATED, &wlvif->flags))
455 continue; 464 continue;
456 465
@@ -458,7 +467,8 @@ static int wl1271_dev_notify(struct notifier_block *me, unsigned long what,
458 if (ret < 0) 467 if (ret < 0)
459 goto out; 468 goto out;
460 469
461 wl1271_check_operstate(wl, wlvif, dev->operstate); 470 wl1271_check_operstate(wl, wlvif,
471 ieee80211_get_operstate(vif));
462 472
463 wl1271_ps_elp_sleep(wl); 473 wl1271_ps_elp_sleep(wl);
464 } 474 }
@@ -2036,6 +2046,11 @@ out:
2036 return booted; 2046 return booted;
2037} 2047}
2038 2048
2049static bool wl12xx_dev_role_started(struct wl12xx_vif *wlvif)
2050{
2051 return wlvif->dev_hlid != WL12XX_INVALID_LINK_ID;
2052}
2053
2039static int wl1271_op_add_interface(struct ieee80211_hw *hw, 2054static int wl1271_op_add_interface(struct ieee80211_hw *hw,
2040 struct ieee80211_vif *vif) 2055 struct ieee80211_vif *vif)
2041{ 2056{
@@ -2184,7 +2199,11 @@ static void __wl1271_op_remove_interface(struct wl1271 *wl,
2184 if (ret < 0) 2199 if (ret < 0)
2185 goto deinit; 2200 goto deinit;
2186 2201
2187 if (wlvif->bss_type == BSS_TYPE_STA_BSS) { 2202 if (wlvif->bss_type == BSS_TYPE_STA_BSS ||
2203 wlvif->bss_type == BSS_TYPE_IBSS) {
2204 if (wl12xx_dev_role_started(wlvif))
2205 wl12xx_stop_dev(wl, wlvif);
2206
2188 ret = wl12xx_cmd_role_disable(wl, &wlvif->dev_role_id); 2207 ret = wl12xx_cmd_role_disable(wl, &wlvif->dev_role_id);
2189 if (ret < 0) 2208 if (ret < 0)
2190 goto deinit; 2209 goto deinit;
@@ -2269,6 +2288,17 @@ out:
2269 cancel_work_sync(&wl->recovery_work); 2288 cancel_work_sync(&wl->recovery_work);
2270} 2289}
2271 2290
2291static int wl12xx_op_change_interface(struct ieee80211_hw *hw,
2292 struct ieee80211_vif *vif,
2293 enum nl80211_iftype new_type, bool p2p)
2294{
2295 wl1271_op_remove_interface(hw, vif);
2296
2297 vif->type = ieee80211_iftype_p2p(new_type, p2p);
2298 vif->p2p = p2p;
2299 return wl1271_op_add_interface(hw, vif);
2300}
2301
2272static int wl1271_join(struct wl1271 *wl, struct wl12xx_vif *wlvif, 2302static int wl1271_join(struct wl1271 *wl, struct wl12xx_vif *wlvif,
2273 bool set_assoc) 2303 bool set_assoc)
2274{ 2304{
@@ -2358,25 +2388,18 @@ static void wl1271_set_band_rate(struct wl1271 *wl, struct wl12xx_vif *wlvif)
2358 wlvif->rate_set = wlvif->basic_rate_set; 2388 wlvif->rate_set = wlvif->basic_rate_set;
2359} 2389}
2360 2390
2361static bool wl12xx_is_roc(struct wl1271 *wl)
2362{
2363 u8 role_id;
2364
2365 role_id = find_first_bit(wl->roc_map, WL12XX_MAX_ROLES);
2366 if (role_id >= WL12XX_MAX_ROLES)
2367 return false;
2368
2369 return true;
2370}
2371
2372static int wl1271_sta_handle_idle(struct wl1271 *wl, struct wl12xx_vif *wlvif, 2391static int wl1271_sta_handle_idle(struct wl1271 *wl, struct wl12xx_vif *wlvif,
2373 bool idle) 2392 bool idle)
2374{ 2393{
2375 int ret; 2394 int ret;
2395 bool cur_idle = !test_bit(WLVIF_FLAG_IN_USE, &wlvif->flags);
2396
2397 if (idle == cur_idle)
2398 return 0;
2376 2399
2377 if (idle) { 2400 if (idle) {
2378 /* no need to croc if we weren't busy (e.g. during boot) */ 2401 /* no need to croc if we weren't busy (e.g. during boot) */
2379 if (wl12xx_is_roc(wl)) { 2402 if (wl12xx_dev_role_started(wlvif)) {
2380 ret = wl12xx_stop_dev(wl, wlvif); 2403 ret = wl12xx_stop_dev(wl, wlvif);
2381 if (ret < 0) 2404 if (ret < 0)
2382 goto out; 2405 goto out;
@@ -2391,7 +2414,7 @@ static int wl1271_sta_handle_idle(struct wl1271 *wl, struct wl12xx_vif *wlvif,
2391 ACX_KEEP_ALIVE_TPL_INVALID); 2414 ACX_KEEP_ALIVE_TPL_INVALID);
2392 if (ret < 0) 2415 if (ret < 0)
2393 goto out; 2416 goto out;
2394 set_bit(WL1271_FLAG_IDLE, &wl->flags); 2417 clear_bit(WLVIF_FLAG_IN_USE, &wlvif->flags);
2395 } else { 2418 } else {
2396 /* The current firmware only supports sched_scan in idle */ 2419 /* The current firmware only supports sched_scan in idle */
2397 if (wl->sched_scanning) { 2420 if (wl->sched_scanning) {
@@ -2402,7 +2425,7 @@ static int wl1271_sta_handle_idle(struct wl1271 *wl, struct wl12xx_vif *wlvif,
2402 ret = wl12xx_start_dev(wl, wlvif); 2425 ret = wl12xx_start_dev(wl, wlvif);
2403 if (ret < 0) 2426 if (ret < 0)
2404 goto out; 2427 goto out;
2405 clear_bit(WL1271_FLAG_IDLE, &wl->flags); 2428 set_bit(WLVIF_FLAG_IN_USE, &wlvif->flags);
2406 } 2429 }
2407 2430
2408out: 2431out:
@@ -2446,7 +2469,7 @@ static int wl12xx_config_vif(struct wl1271 *wl, struct wl12xx_vif *wlvif,
2446 2469
2447 if (test_bit(WLVIF_FLAG_STA_ASSOCIATED, 2470 if (test_bit(WLVIF_FLAG_STA_ASSOCIATED,
2448 &wlvif->flags)) { 2471 &wlvif->flags)) {
2449 if (wl12xx_is_roc(wl)) { 2472 if (wl12xx_dev_role_started(wlvif)) {
2450 /* roaming */ 2473 /* roaming */
2451 ret = wl12xx_croc(wl, 2474 ret = wl12xx_croc(wl,
2452 wlvif->dev_role_id); 2475 wlvif->dev_role_id);
@@ -2463,7 +2486,7 @@ static int wl12xx_config_vif(struct wl1271 *wl, struct wl12xx_vif *wlvif,
2463 * not idle. otherwise, CROC will be called 2486 * not idle. otherwise, CROC will be called
2464 * anyway. 2487 * anyway.
2465 */ 2488 */
2466 if (wl12xx_is_roc(wl) && 2489 if (wl12xx_dev_role_started(wlvif) &&
2467 !(conf->flags & IEEE80211_CONF_IDLE)) { 2490 !(conf->flags & IEEE80211_CONF_IDLE)) {
2468 ret = wl12xx_stop_dev(wl, wlvif); 2491 ret = wl12xx_stop_dev(wl, wlvif);
2469 if (ret < 0) 2492 if (ret < 0)
@@ -3010,15 +3033,16 @@ static int wl1271_op_hw_scan(struct ieee80211_hw *hw,
3010 if (ret < 0) 3033 if (ret < 0)
3011 goto out; 3034 goto out;
3012 3035
3036 if (test_bit(WLVIF_FLAG_STA_ASSOCIATED, &wlvif->flags) &&
3037 test_bit(wlvif->role_id, wl->roc_map)) {
3038 /* don't allow scanning right now */
3039 ret = -EBUSY;
3040 goto out_sleep;
3041 }
3042
3013 /* cancel ROC before scanning */ 3043 /* cancel ROC before scanning */
3014 if (wl12xx_is_roc(wl)) { 3044 if (wl12xx_dev_role_started(wlvif))
3015 if (test_bit(WLVIF_FLAG_STA_ASSOCIATED, &wlvif->flags)) {
3016 /* don't allow scanning right now */
3017 ret = -EBUSY;
3018 goto out_sleep;
3019 }
3020 wl12xx_stop_dev(wl, wlvif); 3045 wl12xx_stop_dev(wl, wlvif);
3021 }
3022 3046
3023 ret = wl1271_scan(hw->priv, vif, ssid, len, req); 3047 ret = wl1271_scan(hw->priv, vif, ssid, len, req);
3024out_sleep: 3048out_sleep:
@@ -3829,9 +3853,9 @@ sta_not_found:
3829 } 3853 }
3830 /* 3854 /*
3831 * stop device role if started (we might already be in 3855 * stop device role if started (we might already be in
3832 * STA role). TODO: make it better. 3856 * STA/IBSS role).
3833 */ 3857 */
3834 if (wlvif->dev_role_id != WL12XX_INVALID_ROLE_ID) { 3858 if (wl12xx_dev_role_started(wlvif)) {
3835 ret = wl12xx_stop_dev(wl, wlvif); 3859 ret = wl12xx_stop_dev(wl, wlvif);
3836 if (ret < 0) 3860 if (ret < 0)
3837 goto out; 3861 goto out;
@@ -3948,31 +3972,8 @@ static int wl1271_op_conf_tx(struct ieee80211_hw *hw,
3948 else 3972 else
3949 ps_scheme = CONF_PS_SCHEME_LEGACY; 3973 ps_scheme = CONF_PS_SCHEME_LEGACY;
3950 3974
3951 if (wl->state == WL1271_STATE_OFF) { 3975 if (!test_bit(WLVIF_FLAG_INITIALIZED, &wlvif->flags))
3952 /*
3953 * If the state is off, the parameters will be recorded and
3954 * configured on init. This happens in AP-mode.
3955 */
3956 struct conf_tx_ac_category *conf_ac =
3957 &wl->conf.tx.ac_conf[wl1271_tx_get_queue(queue)];
3958 struct conf_tx_tid *conf_tid =
3959 &wl->conf.tx.tid_conf[wl1271_tx_get_queue(queue)];
3960
3961 conf_ac->ac = wl1271_tx_get_queue(queue);
3962 conf_ac->cw_min = (u8)params->cw_min;
3963 conf_ac->cw_max = params->cw_max;
3964 conf_ac->aifsn = params->aifs;
3965 conf_ac->tx_op_limit = params->txop << 5;
3966
3967 conf_tid->queue_id = wl1271_tx_get_queue(queue);
3968 conf_tid->channel_type = CONF_CHANNEL_TYPE_EDCF;
3969 conf_tid->tsid = wl1271_tx_get_queue(queue);
3970 conf_tid->ps_scheme = ps_scheme;
3971 conf_tid->ack_policy = CONF_ACK_POLICY_LEGACY;
3972 conf_tid->apsd_conf[0] = 0;
3973 conf_tid->apsd_conf[1] = 0;
3974 goto out; 3976 goto out;
3975 }
3976 3977
3977 ret = wl1271_ps_elp_wakeup(wl); 3978 ret = wl1271_ps_elp_wakeup(wl);
3978 if (ret < 0) 3979 if (ret < 0)
@@ -4629,6 +4630,7 @@ static const struct ieee80211_ops wl1271_ops = {
4629 .stop = wl1271_op_stop, 4630 .stop = wl1271_op_stop,
4630 .add_interface = wl1271_op_add_interface, 4631 .add_interface = wl1271_op_add_interface,
4631 .remove_interface = wl1271_op_remove_interface, 4632 .remove_interface = wl1271_op_remove_interface,
4633 .change_interface = wl12xx_op_change_interface,
4632#ifdef CONFIG_PM 4634#ifdef CONFIG_PM
4633 .suspend = wl1271_op_suspend, 4635 .suspend = wl1271_op_suspend,
4634 .resume = wl1271_op_resume, 4636 .resume = wl1271_op_resume,
diff --git a/drivers/net/wireless/wl12xx/ps.c b/drivers/net/wireless/wl12xx/ps.c
index a7a11088dd3..a2bdacdd7e1 100644
--- a/drivers/net/wireless/wl12xx/ps.c
+++ b/drivers/net/wireless/wl12xx/ps.c
@@ -53,8 +53,11 @@ void wl1271_elp_work(struct work_struct *work)
53 goto out; 53 goto out;
54 54
55 wl12xx_for_each_wlvif(wl, wlvif) { 55 wl12xx_for_each_wlvif(wl, wlvif) {
56 if (wlvif->bss_type == BSS_TYPE_AP_BSS)
57 goto out;
58
56 if (!test_bit(WLVIF_FLAG_PSM, &wlvif->flags) && 59 if (!test_bit(WLVIF_FLAG_PSM, &wlvif->flags) &&
57 !test_bit(WL1271_FLAG_IDLE, &wl->flags)) 60 test_bit(WLVIF_FLAG_IN_USE, &wlvif->flags))
58 goto out; 61 goto out;
59 } 62 }
60 63
@@ -78,8 +81,11 @@ void wl1271_ps_elp_sleep(struct wl1271 *wl)
78 return; 81 return;
79 82
80 wl12xx_for_each_wlvif(wl, wlvif) { 83 wl12xx_for_each_wlvif(wl, wlvif) {
84 if (wlvif->bss_type == BSS_TYPE_AP_BSS)
85 return;
86
81 if (!test_bit(WLVIF_FLAG_PSM, &wlvif->flags) && 87 if (!test_bit(WLVIF_FLAG_PSM, &wlvif->flags) &&
82 !test_bit(WL1271_FLAG_IDLE, &wl->flags)) 88 test_bit(WLVIF_FLAG_IN_USE, &wlvif->flags))
83 return; 89 return;
84 } 90 }
85 91
diff --git a/drivers/net/wireless/wl12xx/scan.c b/drivers/net/wireless/wl12xx/scan.c
index 8599dab1fe2..e24111ececc 100644
--- a/drivers/net/wireless/wl12xx/scan.c
+++ b/drivers/net/wireless/wl12xx/scan.c
@@ -437,18 +437,19 @@ wl1271_scan_get_sched_scan_channels(struct wl1271 *wl,
437 437
438 if (flags & IEEE80211_CHAN_RADAR) { 438 if (flags & IEEE80211_CHAN_RADAR) {
439 channels[j].flags |= SCAN_CHANNEL_FLAGS_DFS; 439 channels[j].flags |= SCAN_CHANNEL_FLAGS_DFS;
440
440 channels[j].passive_duration = 441 channels[j].passive_duration =
441 cpu_to_le16(c->dwell_time_dfs); 442 cpu_to_le16(c->dwell_time_dfs);
442 } 443 } else {
443 else if (flags & IEEE80211_CHAN_PASSIVE_SCAN) {
444 channels[j].passive_duration = 444 channels[j].passive_duration =
445 cpu_to_le16(c->dwell_time_passive); 445 cpu_to_le16(c->dwell_time_passive);
446 } else {
447 channels[j].min_duration =
448 cpu_to_le16(c->min_dwell_time_active);
449 channels[j].max_duration =
450 cpu_to_le16(c->max_dwell_time_active);
451 } 446 }
447
448 channels[j].min_duration =
449 cpu_to_le16(c->min_dwell_time_active);
450 channels[j].max_duration =
451 cpu_to_le16(c->max_dwell_time_active);
452
452 channels[j].tx_power_att = req->channels[i]->max_power; 453 channels[j].tx_power_att = req->channels[i]->max_power;
453 channels[j].channel = req->channels[i]->hw_value; 454 channels[j].channel = req->channels[i]->hw_value;
454 455
@@ -703,7 +704,7 @@ int wl1271_scan_sched_scan_start(struct wl1271 *wl, struct wl12xx_vif *wlvif)
703 if (wlvif->bss_type != BSS_TYPE_STA_BSS) 704 if (wlvif->bss_type != BSS_TYPE_STA_BSS)
704 return -EOPNOTSUPP; 705 return -EOPNOTSUPP;
705 706
706 if (!test_bit(WL1271_FLAG_IDLE, &wl->flags)) 707 if (test_bit(WLVIF_FLAG_IN_USE, &wlvif->flags))
707 return -EBUSY; 708 return -EBUSY;
708 709
709 start = kzalloc(sizeof(*start), GFP_KERNEL); 710 start = kzalloc(sizeof(*start), GFP_KERNEL);
@@ -753,7 +754,6 @@ void wl1271_scan_sched_scan_stop(struct wl1271 *wl)
753 wl1271_error("failed to send sched scan stop command"); 754 wl1271_error("failed to send sched scan stop command");
754 goto out_free; 755 goto out_free;
755 } 756 }
756 wl->sched_scanning = false;
757 757
758out_free: 758out_free:
759 kfree(stop); 759 kfree(stop);
diff --git a/drivers/net/wireless/wl12xx/wl12xx.h b/drivers/net/wireless/wl12xx/wl12xx.h
index d21f71ff6f6..b2b09cd0202 100644
--- a/drivers/net/wireless/wl12xx/wl12xx.h
+++ b/drivers/net/wireless/wl12xx/wl12xx.h
@@ -241,7 +241,6 @@ enum wl12xx_flags {
241 WL1271_FLAG_IN_ELP, 241 WL1271_FLAG_IN_ELP,
242 WL1271_FLAG_ELP_REQUESTED, 242 WL1271_FLAG_ELP_REQUESTED,
243 WL1271_FLAG_IRQ_RUNNING, 243 WL1271_FLAG_IRQ_RUNNING,
244 WL1271_FLAG_IDLE,
245 WL1271_FLAG_FW_TX_BUSY, 244 WL1271_FLAG_FW_TX_BUSY,
246 WL1271_FLAG_DUMMY_PACKET_PENDING, 245 WL1271_FLAG_DUMMY_PACKET_PENDING,
247 WL1271_FLAG_SUSPENDED, 246 WL1271_FLAG_SUSPENDED,
@@ -262,6 +261,7 @@ enum wl12xx_vif_flags {
262 WLVIF_FLAG_PSPOLL_FAILURE, 261 WLVIF_FLAG_PSPOLL_FAILURE,
263 WLVIF_FLAG_CS_PROGRESS, 262 WLVIF_FLAG_CS_PROGRESS,
264 WLVIF_FLAG_AP_PROBE_RESP_SET, 263 WLVIF_FLAG_AP_PROBE_RESP_SET,
264 WLVIF_FLAG_IN_USE,
265}; 265};
266 266
267struct wl1271_link { 267struct wl1271_link {
diff --git a/drivers/net/wireless/wl12xx/wl12xx_platform_data.c b/drivers/net/wireless/wl12xx/wl12xx_platform_data.c
index 3c96b332184..998e95895f9 100644
--- a/drivers/net/wireless/wl12xx/wl12xx_platform_data.c
+++ b/drivers/net/wireless/wl12xx/wl12xx_platform_data.c
@@ -1,3 +1,24 @@
1/*
2 * This file is part of wl12xx
3 *
4 * Copyright (C) 2010-2011 Texas Instruments, Inc.
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * version 2 as published by the Free Software Foundation.
9 *
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
18 * 02110-1301 USA
19 *
20 */
21
1#include <linux/module.h> 22#include <linux/module.h>
2#include <linux/err.h> 23#include <linux/err.h>
3#include <linux/wl12xx.h> 24#include <linux/wl12xx.h>