aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJohn W. Linville <linville@tuxdriver.com>2011-05-13 15:18:35 -0400
committerJohn W. Linville <linville@tuxdriver.com>2011-05-13 15:18:35 -0400
commitb376704bf57e1b731fe2dd6e9aa83a1d42a45ef9 (patch)
tree298b05b5875d63e4228a0416d94844f575028edf
parent1159024d4c0aafecaa0c6635c55153b4b39cc1c8 (diff)
parent9439064cd9fce8a4db716a748dbf581eb234f9c7 (diff)
Merge branch 'for-linville' of git://git.kernel.org/pub/scm/linux/kernel/git/luca/wl12xx
-rw-r--r--drivers/net/wireless/wl12xx/boot.c4
-rw-r--r--drivers/net/wireless/wl12xx/conf.h21
-rw-r--r--drivers/net/wireless/wl12xx/debugfs.c1
-rw-r--r--drivers/net/wireless/wl12xx/event.c23
-rw-r--r--drivers/net/wireless/wl12xx/main.c260
-rw-r--r--drivers/net/wireless/wl12xx/ps.h2
-rw-r--r--drivers/net/wireless/wl12xx/scan.c243
-rw-r--r--drivers/net/wireless/wl12xx/scan.h114
-rw-r--r--drivers/net/wireless/wl12xx/sdio.c64
-rw-r--r--drivers/net/wireless/wl12xx/wl12xx.h12
10 files changed, 728 insertions, 16 deletions
diff --git a/drivers/net/wireless/wl12xx/boot.c b/drivers/net/wireless/wl12xx/boot.c
index 2b0cf85788b3..b07f8b7e5f11 100644
--- a/drivers/net/wireless/wl12xx/boot.c
+++ b/drivers/net/wireless/wl12xx/boot.c
@@ -478,7 +478,9 @@ static int wl1271_boot_run_firmware(struct wl1271 *wl)
478 DISCONNECT_EVENT_COMPLETE_ID | 478 DISCONNECT_EVENT_COMPLETE_ID |
479 RSSI_SNR_TRIGGER_0_EVENT_ID | 479 RSSI_SNR_TRIGGER_0_EVENT_ID |
480 PSPOLL_DELIVERY_FAILURE_EVENT_ID | 480 PSPOLL_DELIVERY_FAILURE_EVENT_ID |
481 SOFT_GEMINI_SENSE_EVENT_ID; 481 SOFT_GEMINI_SENSE_EVENT_ID |
482 PERIODIC_SCAN_REPORT_EVENT_ID |
483 PERIODIC_SCAN_COMPLETE_EVENT_ID;
482 484
483 if (wl->bss_type == BSS_TYPE_AP_BSS) 485 if (wl->bss_type == BSS_TYPE_AP_BSS)
484 wl->event_mask |= STA_REMOVE_COMPLETE_EVENT_ID; 486 wl->event_mask |= STA_REMOVE_COMPLETE_EVENT_ID;
diff --git a/drivers/net/wireless/wl12xx/conf.h b/drivers/net/wireless/wl12xx/conf.h
index 1f947368f9ee..ba558fcc76d0 100644
--- a/drivers/net/wireless/wl12xx/conf.h
+++ b/drivers/net/wireless/wl12xx/conf.h
@@ -1147,6 +1147,26 @@ struct conf_scan_settings {
1147 1147
1148}; 1148};
1149 1149
1150struct conf_sched_scan_settings {
1151 /* minimum time to wait on the channel for active scans (in TUs) */
1152 u16 min_dwell_time_active;
1153
1154 /* maximum time to wait on the channel for active scans (in TUs) */
1155 u16 max_dwell_time_active;
1156
1157 /* time to wait on the channel for passive scans (in TUs) */
1158 u32 dwell_time_passive;
1159
1160 /* number of probe requests to send on each channel in active scans */
1161 u8 num_probe_reqs;
1162
1163 /* RSSI threshold to be used for filtering */
1164 s8 rssi_threshold;
1165
1166 /* SNR threshold to be used for filtering */
1167 s8 snr_threshold;
1168};
1169
1150/* these are number of channels on the band divided by two, rounded up */ 1170/* these are number of channels on the band divided by two, rounded up */
1151#define CONF_TX_PWR_COMPENSATION_LEN_2 7 1171#define CONF_TX_PWR_COMPENSATION_LEN_2 7
1152#define CONF_TX_PWR_COMPENSATION_LEN_5 18 1172#define CONF_TX_PWR_COMPENSATION_LEN_5 18
@@ -1234,6 +1254,7 @@ struct conf_drv_settings {
1234 struct conf_pm_config_settings pm_config; 1254 struct conf_pm_config_settings pm_config;
1235 struct conf_roam_trigger_settings roam_trigger; 1255 struct conf_roam_trigger_settings roam_trigger;
1236 struct conf_scan_settings scan; 1256 struct conf_scan_settings scan;
1257 struct conf_sched_scan_settings sched_scan;
1237 struct conf_rf_settings rf; 1258 struct conf_rf_settings rf;
1238 struct conf_ht_setting ht; 1259 struct conf_ht_setting ht;
1239 struct conf_memory_settings mem_wl127x; 1260 struct conf_memory_settings mem_wl127x;
diff --git a/drivers/net/wireless/wl12xx/debugfs.c b/drivers/net/wireless/wl12xx/debugfs.c
index b2f692babed7..f1f8df9b6cd7 100644
--- a/drivers/net/wireless/wl12xx/debugfs.c
+++ b/drivers/net/wireless/wl12xx/debugfs.c
@@ -377,6 +377,7 @@ static ssize_t driver_state_read(struct file *file, char __user *user_buf,
377 DRIVER_STATE_PRINT_HEX(platform_quirks); 377 DRIVER_STATE_PRINT_HEX(platform_quirks);
378 DRIVER_STATE_PRINT_HEX(chip.id); 378 DRIVER_STATE_PRINT_HEX(chip.id);
379 DRIVER_STATE_PRINT_STR(chip.fw_ver_str); 379 DRIVER_STATE_PRINT_STR(chip.fw_ver_str);
380 DRIVER_STATE_PRINT_INT(sched_scanning);
380 381
381#undef DRIVER_STATE_PRINT_INT 382#undef DRIVER_STATE_PRINT_INT
382#undef DRIVER_STATE_PRINT_LONG 383#undef DRIVER_STATE_PRINT_LONG
diff --git a/drivers/net/wireless/wl12xx/event.c b/drivers/net/wireless/wl12xx/event.c
index ae69330e807c..c3c554cd6580 100644
--- a/drivers/net/wireless/wl12xx/event.c
+++ b/drivers/net/wireless/wl12xx/event.c
@@ -135,6 +135,13 @@ static int wl1271_event_ps_report(struct wl1271 *wl,
135 135
136 /* enable beacon early termination */ 136 /* enable beacon early termination */
137 ret = wl1271_acx_bet_enable(wl, true); 137 ret = wl1271_acx_bet_enable(wl, true);
138 if (ret < 0)
139 break;
140
141 if (wl->ps_compl) {
142 complete(wl->ps_compl);
143 wl->ps_compl = NULL;
144 }
138 break; 145 break;
139 default: 146 default:
140 break; 147 break;
@@ -188,6 +195,22 @@ static int wl1271_event_process(struct wl1271 *wl, struct event_mailbox *mbox)
188 wl1271_scan_stm(wl); 195 wl1271_scan_stm(wl);
189 } 196 }
190 197
198 if (vector & PERIODIC_SCAN_REPORT_EVENT_ID) {
199 wl1271_debug(DEBUG_EVENT, "PERIODIC_SCAN_REPORT_EVENT "
200 "(status 0x%0x)", mbox->scheduled_scan_status);
201
202 wl1271_scan_sched_scan_results(wl);
203 }
204
205 if (vector & PERIODIC_SCAN_COMPLETE_EVENT_ID) {
206 wl1271_debug(DEBUG_EVENT, "PERIODIC_SCAN_COMPLETE_EVENT "
207 "(status 0x%0x)", mbox->scheduled_scan_status);
208 if (wl->sched_scanning) {
209 wl1271_scan_sched_scan_stop(wl);
210 ieee80211_sched_scan_stopped(wl->hw);
211 }
212 }
213
191 /* disable dynamic PS when requested by the firmware */ 214 /* disable dynamic PS when requested by the firmware */
192 if (vector & SOFT_GEMINI_SENSE_EVENT_ID && 215 if (vector & SOFT_GEMINI_SENSE_EVENT_ID &&
193 wl->bss_type == BSS_TYPE_STA_BSS) { 216 wl->bss_type == BSS_TYPE_STA_BSS) {
diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c
index 6dab6f0c91bc..610be03a198b 100644
--- a/drivers/net/wireless/wl12xx/main.c
+++ b/drivers/net/wireless/wl12xx/main.c
@@ -257,12 +257,16 @@ static struct conf_drv_settings default_conf = {
257 .wake_up_event = CONF_WAKE_UP_EVENT_DTIM, 257 .wake_up_event = CONF_WAKE_UP_EVENT_DTIM,
258 .listen_interval = 1, 258 .listen_interval = 1,
259 .bcn_filt_mode = CONF_BCN_FILT_MODE_ENABLED, 259 .bcn_filt_mode = CONF_BCN_FILT_MODE_ENABLED,
260 .bcn_filt_ie_count = 1, 260 .bcn_filt_ie_count = 2,
261 .bcn_filt_ie = { 261 .bcn_filt_ie = {
262 [0] = { 262 [0] = {
263 .ie = WLAN_EID_CHANNEL_SWITCH, 263 .ie = WLAN_EID_CHANNEL_SWITCH,
264 .rule = CONF_BCN_RULE_PASS_ON_APPEARANCE, 264 .rule = CONF_BCN_RULE_PASS_ON_APPEARANCE,
265 } 265 },
266 [1] = {
267 .ie = WLAN_EID_HT_INFORMATION,
268 .rule = CONF_BCN_RULE_PASS_ON_CHANGE,
269 },
266 }, 270 },
267 .synch_fail_thold = 10, 271 .synch_fail_thold = 10,
268 .bss_lose_timeout = 100, 272 .bss_lose_timeout = 100,
@@ -302,6 +306,15 @@ static struct conf_drv_settings default_conf = {
302 .max_dwell_time_passive = 100000, 306 .max_dwell_time_passive = 100000,
303 .num_probe_reqs = 2, 307 .num_probe_reqs = 2,
304 }, 308 },
309 .sched_scan = {
310 /* sched_scan requires dwell times in TU instead of TU/1000 */
311 .min_dwell_time_active = 8,
312 .max_dwell_time_active = 30,
313 .dwell_time_passive = 100,
314 .num_probe_reqs = 2,
315 .rssi_threshold = -90,
316 .snr_threshold = 0,
317 },
305 .rf = { 318 .rf = {
306 .tx_per_channel_power_compensation_2 = { 319 .tx_per_channel_power_compensation_2 = {
307 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 320 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
@@ -975,6 +988,11 @@ static void wl1271_recovery_work(struct work_struct *work)
975 /* Prevent spurious TX during FW restart */ 988 /* Prevent spurious TX during FW restart */
976 ieee80211_stop_queues(wl->hw); 989 ieee80211_stop_queues(wl->hw);
977 990
991 if (wl->sched_scanning) {
992 ieee80211_sched_scan_stopped(wl->hw);
993 wl->sched_scanning = false;
994 }
995
978 /* reboot the chipset */ 996 /* reboot the chipset */
979 __wl1271_op_remove_interface(wl, false); 997 __wl1271_op_remove_interface(wl, false);
980 ieee80211_restart_hw(wl->hw); 998 ieee80211_restart_hw(wl->hw);
@@ -1332,6 +1350,150 @@ static struct notifier_block wl1271_dev_notifier = {
1332 .notifier_call = wl1271_dev_notify, 1350 .notifier_call = wl1271_dev_notify,
1333}; 1351};
1334 1352
1353static int wl1271_configure_suspend(struct wl1271 *wl)
1354{
1355 int ret;
1356
1357 if (wl->bss_type != BSS_TYPE_STA_BSS)
1358 return 0;
1359
1360 mutex_lock(&wl->mutex);
1361
1362 ret = wl1271_ps_elp_wakeup(wl);
1363 if (ret < 0)
1364 goto out_unlock;
1365
1366 /* enter psm if needed*/
1367 if (!test_bit(WL1271_FLAG_PSM, &wl->flags)) {
1368 DECLARE_COMPLETION_ONSTACK(compl);
1369
1370 wl->ps_compl = &compl;
1371 ret = wl1271_ps_set_mode(wl, STATION_POWER_SAVE_MODE,
1372 wl->basic_rate, true);
1373 if (ret < 0)
1374 goto out_sleep;
1375
1376 /* we must unlock here so we will be able to get events */
1377 wl1271_ps_elp_sleep(wl);
1378 mutex_unlock(&wl->mutex);
1379
1380 ret = wait_for_completion_timeout(
1381 &compl, msecs_to_jiffies(WL1271_PS_COMPLETE_TIMEOUT));
1382 if (ret <= 0) {
1383 wl1271_warning("couldn't enter ps mode!");
1384 ret = -EBUSY;
1385 goto out;
1386 }
1387
1388 /* take mutex again, and wakeup */
1389 mutex_lock(&wl->mutex);
1390
1391 ret = wl1271_ps_elp_wakeup(wl);
1392 if (ret < 0)
1393 goto out_unlock;
1394 }
1395out_sleep:
1396 wl1271_ps_elp_sleep(wl);
1397out_unlock:
1398 mutex_unlock(&wl->mutex);
1399out:
1400 return ret;
1401
1402}
1403
1404static void wl1271_configure_resume(struct wl1271 *wl)
1405{
1406 int ret;
1407
1408 if (wl->bss_type != BSS_TYPE_STA_BSS)
1409 return;
1410
1411 mutex_lock(&wl->mutex);
1412 ret = wl1271_ps_elp_wakeup(wl);
1413 if (ret < 0)
1414 goto out;
1415
1416 /* exit psm if it wasn't configured */
1417 if (!test_bit(WL1271_FLAG_PSM_REQUESTED, &wl->flags))
1418 wl1271_ps_set_mode(wl, STATION_ACTIVE_MODE,
1419 wl->basic_rate, true);
1420
1421 wl1271_ps_elp_sleep(wl);
1422out:
1423 mutex_unlock(&wl->mutex);
1424}
1425
1426static int wl1271_op_suspend(struct ieee80211_hw *hw,
1427 struct cfg80211_wowlan *wow)
1428{
1429 struct wl1271 *wl = hw->priv;
1430 wl1271_debug(DEBUG_MAC80211, "mac80211 suspend wow=%d", !!wow);
1431 wl->wow_enabled = !!wow;
1432 if (wl->wow_enabled) {
1433 int ret;
1434 ret = wl1271_configure_suspend(wl);
1435 if (ret < 0) {
1436 wl1271_warning("couldn't prepare device to suspend");
1437 return ret;
1438 }
1439 /* flush any remaining work */
1440 wl1271_debug(DEBUG_MAC80211, "flushing remaining works");
1441 flush_delayed_work(&wl->scan_complete_work);
1442
1443 /*
1444 * disable and re-enable interrupts in order to flush
1445 * the threaded_irq
1446 */
1447 wl1271_disable_interrupts(wl);
1448
1449 /*
1450 * set suspended flag to avoid triggering a new threaded_irq
1451 * work. no need for spinlock as interrupts are disabled.
1452 */
1453 set_bit(WL1271_FLAG_SUSPENDED, &wl->flags);
1454
1455 wl1271_enable_interrupts(wl);
1456 flush_work(&wl->tx_work);
1457 flush_delayed_work(&wl->pspoll_work);
1458 flush_delayed_work(&wl->elp_work);
1459 }
1460 return 0;
1461}
1462
1463static int wl1271_op_resume(struct ieee80211_hw *hw)
1464{
1465 struct wl1271 *wl = hw->priv;
1466 wl1271_debug(DEBUG_MAC80211, "mac80211 resume wow=%d",
1467 wl->wow_enabled);
1468
1469 /*
1470 * re-enable irq_work enqueuing, and call irq_work directly if
1471 * there is a pending work.
1472 */
1473 if (wl->wow_enabled) {
1474 struct wl1271 *wl = hw->priv;
1475 unsigned long flags;
1476 bool run_irq_work = false;
1477
1478 spin_lock_irqsave(&wl->wl_lock, flags);
1479 clear_bit(WL1271_FLAG_SUSPENDED, &wl->flags);
1480 if (test_and_clear_bit(WL1271_FLAG_PENDING_WORK, &wl->flags))
1481 run_irq_work = true;
1482 spin_unlock_irqrestore(&wl->wl_lock, flags);
1483
1484 if (run_irq_work) {
1485 wl1271_debug(DEBUG_MAC80211,
1486 "run postponed irq_work directly");
1487 wl1271_irq(0, wl);
1488 wl1271_enable_interrupts(wl);
1489 }
1490
1491 wl1271_configure_resume(wl);
1492 }
1493
1494 return 0;
1495}
1496
1335static int wl1271_op_start(struct ieee80211_hw *hw) 1497static int wl1271_op_start(struct ieee80211_hw *hw)
1336{ 1498{
1337 wl1271_debug(DEBUG_MAC80211, "mac80211 start"); 1499 wl1271_debug(DEBUG_MAC80211, "mac80211 start");
@@ -1563,6 +1725,7 @@ static void __wl1271_op_remove_interface(struct wl1271 *wl,
1563 memset(wl->ap_hlid_map, 0, sizeof(wl->ap_hlid_map)); 1725 memset(wl->ap_hlid_map, 0, sizeof(wl->ap_hlid_map));
1564 wl->ap_fw_ps_map = 0; 1726 wl->ap_fw_ps_map = 0;
1565 wl->ap_ps_map = 0; 1727 wl->ap_ps_map = 0;
1728 wl->sched_scanning = false;
1566 1729
1567 /* 1730 /*
1568 * this is performed after the cancel_work calls and the associated 1731 * this is performed after the cancel_work calls and the associated
@@ -1765,6 +1928,13 @@ static int wl1271_sta_handle_idle(struct wl1271 *wl, bool idle)
1765 wl->session_counter++; 1928 wl->session_counter++;
1766 if (wl->session_counter >= SESSION_COUNTER_MAX) 1929 if (wl->session_counter >= SESSION_COUNTER_MAX)
1767 wl->session_counter = 0; 1930 wl->session_counter = 0;
1931
1932 /* The current firmware only supports sched_scan in idle */
1933 if (wl->sched_scanning) {
1934 wl1271_scan_sched_scan_stop(wl);
1935 ieee80211_sched_scan_stopped(wl->hw);
1936 }
1937
1768 ret = wl1271_dummy_join(wl); 1938 ret = wl1271_dummy_join(wl);
1769 if (ret < 0) 1939 if (ret < 0)
1770 goto out; 1940 goto out;
@@ -2317,6 +2487,60 @@ out:
2317 return ret; 2487 return ret;
2318} 2488}
2319 2489
2490static int wl1271_op_sched_scan_start(struct ieee80211_hw *hw,
2491 struct ieee80211_vif *vif,
2492 struct cfg80211_sched_scan_request *req,
2493 struct ieee80211_sched_scan_ies *ies)
2494{
2495 struct wl1271 *wl = hw->priv;
2496 int ret;
2497
2498 wl1271_debug(DEBUG_MAC80211, "wl1271_op_sched_scan_start");
2499
2500 mutex_lock(&wl->mutex);
2501
2502 ret = wl1271_ps_elp_wakeup(wl);
2503 if (ret < 0)
2504 goto out;
2505
2506 ret = wl1271_scan_sched_scan_config(wl, req, ies);
2507 if (ret < 0)
2508 goto out_sleep;
2509
2510 ret = wl1271_scan_sched_scan_start(wl);
2511 if (ret < 0)
2512 goto out_sleep;
2513
2514 wl->sched_scanning = true;
2515
2516out_sleep:
2517 wl1271_ps_elp_sleep(wl);
2518out:
2519 mutex_unlock(&wl->mutex);
2520 return ret;
2521}
2522
2523static void wl1271_op_sched_scan_stop(struct ieee80211_hw *hw,
2524 struct ieee80211_vif *vif)
2525{
2526 struct wl1271 *wl = hw->priv;
2527 int ret;
2528
2529 wl1271_debug(DEBUG_MAC80211, "wl1271_op_sched_scan_stop");
2530
2531 mutex_lock(&wl->mutex);
2532
2533 ret = wl1271_ps_elp_wakeup(wl);
2534 if (ret < 0)
2535 goto out;
2536
2537 wl1271_scan_sched_scan_stop(wl);
2538
2539 wl1271_ps_elp_sleep(wl);
2540out:
2541 mutex_unlock(&wl->mutex);
2542}
2543
2320static int wl1271_op_set_frag_threshold(struct ieee80211_hw *hw, u32 value) 2544static int wl1271_op_set_frag_threshold(struct ieee80211_hw *hw, u32 value)
2321{ 2545{
2322 struct wl1271 *wl = hw->priv; 2546 struct wl1271 *wl = hw->priv;
@@ -2376,20 +2600,24 @@ out:
2376static int wl1271_ssid_set(struct wl1271 *wl, struct sk_buff *skb, 2600static int wl1271_ssid_set(struct wl1271 *wl, struct sk_buff *skb,
2377 int offset) 2601 int offset)
2378{ 2602{
2379 u8 *ptr = skb->data + offset; 2603 u8 ssid_len;
2604 const u8 *ptr = cfg80211_find_ie(WLAN_EID_SSID, skb->data + offset,
2605 skb->len - offset);
2380 2606
2381 /* find the location of the ssid in the beacon */ 2607 if (!ptr) {
2382 while (ptr < skb->data + skb->len) { 2608 wl1271_error("No SSID in IEs!");
2383 if (ptr[0] == WLAN_EID_SSID) { 2609 return -ENOENT;
2384 wl->ssid_len = ptr[1];
2385 memcpy(wl->ssid, ptr+2, wl->ssid_len);
2386 return 0;
2387 }
2388 ptr += (ptr[1] + 2);
2389 } 2610 }
2390 2611
2391 wl1271_error("No SSID in IEs!\n"); 2612 ssid_len = ptr[1];
2392 return -ENOENT; 2613 if (ssid_len > IEEE80211_MAX_SSID_LEN) {
2614 wl1271_error("SSID is too long!");
2615 return -EINVAL;
2616 }
2617
2618 wl->ssid_len = ssid_len;
2619 memcpy(wl->ssid, ptr+2, ssid_len);
2620 return 0;
2393} 2621}
2394 2622
2395static int wl1271_bss_erp_info_changed(struct wl1271 *wl, 2623static int wl1271_bss_erp_info_changed(struct wl1271 *wl,
@@ -3422,12 +3650,16 @@ static const struct ieee80211_ops wl1271_ops = {
3422 .stop = wl1271_op_stop, 3650 .stop = wl1271_op_stop,
3423 .add_interface = wl1271_op_add_interface, 3651 .add_interface = wl1271_op_add_interface,
3424 .remove_interface = wl1271_op_remove_interface, 3652 .remove_interface = wl1271_op_remove_interface,
3653 .suspend = wl1271_op_suspend,
3654 .resume = wl1271_op_resume,
3425 .config = wl1271_op_config, 3655 .config = wl1271_op_config,
3426 .prepare_multicast = wl1271_op_prepare_multicast, 3656 .prepare_multicast = wl1271_op_prepare_multicast,
3427 .configure_filter = wl1271_op_configure_filter, 3657 .configure_filter = wl1271_op_configure_filter,
3428 .tx = wl1271_op_tx, 3658 .tx = wl1271_op_tx,
3429 .set_key = wl1271_op_set_key, 3659 .set_key = wl1271_op_set_key,
3430 .hw_scan = wl1271_op_hw_scan, 3660 .hw_scan = wl1271_op_hw_scan,
3661 .sched_scan_start = wl1271_op_sched_scan_start,
3662 .sched_scan_stop = wl1271_op_sched_scan_stop,
3431 .bss_info_changed = wl1271_op_bss_info_changed, 3663 .bss_info_changed = wl1271_op_bss_info_changed,
3432 .set_frag_threshold = wl1271_op_set_frag_threshold, 3664 .set_frag_threshold = wl1271_op_set_frag_threshold,
3433 .set_rts_threshold = wl1271_op_set_rts_threshold, 3665 .set_rts_threshold = wl1271_op_set_rts_threshold,
@@ -3626,6 +3858,7 @@ int wl1271_init_ieee80211(struct wl1271 *wl)
3626 IEEE80211_HW_CONNECTION_MONITOR | 3858 IEEE80211_HW_CONNECTION_MONITOR |
3627 IEEE80211_HW_SUPPORTS_CQM_RSSI | 3859 IEEE80211_HW_SUPPORTS_CQM_RSSI |
3628 IEEE80211_HW_REPORTS_TX_ACK_STATUS | 3860 IEEE80211_HW_REPORTS_TX_ACK_STATUS |
3861 IEEE80211_HW_SPECTRUM_MGMT |
3629 IEEE80211_HW_AP_LINK_PS; 3862 IEEE80211_HW_AP_LINK_PS;
3630 3863
3631 wl->hw->wiphy->cipher_suites = cipher_suites; 3864 wl->hw->wiphy->cipher_suites = cipher_suites;
@@ -3747,6 +3980,7 @@ struct ieee80211_hw *wl1271_alloc_hw(void)
3747 wl->ap_fw_ps_map = 0; 3980 wl->ap_fw_ps_map = 0;
3748 wl->quirks = 0; 3981 wl->quirks = 0;
3749 wl->platform_quirks = 0; 3982 wl->platform_quirks = 0;
3983 wl->sched_scanning = false;
3750 3984
3751 memset(wl->tx_frames_map, 0, sizeof(wl->tx_frames_map)); 3985 memset(wl->tx_frames_map, 0, sizeof(wl->tx_frames_map));
3752 for (i = 0; i < ACX_TX_DESCRIPTORS; i++) 3986 for (i = 0; i < ACX_TX_DESCRIPTORS; i++)
diff --git a/drivers/net/wireless/wl12xx/ps.h b/drivers/net/wireless/wl12xx/ps.h
index c41bd0a711bc..25eb9bc9b628 100644
--- a/drivers/net/wireless/wl12xx/ps.h
+++ b/drivers/net/wireless/wl12xx/ps.h
@@ -35,4 +35,6 @@ void wl1271_elp_work(struct work_struct *work);
35void wl1271_ps_link_start(struct wl1271 *wl, u8 hlid, bool clean_queues); 35void wl1271_ps_link_start(struct wl1271 *wl, u8 hlid, bool clean_queues);
36void wl1271_ps_link_end(struct wl1271 *wl, u8 hlid); 36void wl1271_ps_link_end(struct wl1271 *wl, u8 hlid);
37 37
38#define WL1271_PS_COMPLETE_TIMEOUT 500
39
38#endif /* __WL1271_PS_H__ */ 40#endif /* __WL1271_PS_H__ */
diff --git a/drivers/net/wireless/wl12xx/scan.c b/drivers/net/wireless/wl12xx/scan.c
index 5d0544c8f3f5..f37e5a391976 100644
--- a/drivers/net/wireless/wl12xx/scan.c
+++ b/drivers/net/wireless/wl12xx/scan.c
@@ -320,3 +320,246 @@ int wl1271_scan(struct wl1271 *wl, const u8 *ssid, size_t ssid_len,
320 320
321 return 0; 321 return 0;
322} 322}
323
324static int
325wl1271_scan_get_sched_scan_channels(struct wl1271 *wl,
326 struct cfg80211_sched_scan_request *req,
327 struct conn_scan_ch_params *channels,
328 u32 band, bool radar, bool passive,
329 int start)
330{
331 struct conf_sched_scan_settings *c = &wl->conf.sched_scan;
332 int i, j;
333 u32 flags;
334
335 for (i = 0, j = start;
336 i < req->n_channels && j < MAX_CHANNELS_ALL_BANDS;
337 i++) {
338 flags = req->channels[i]->flags;
339
340 if (!(flags & IEEE80211_CHAN_DISABLED) &&
341 ((flags & IEEE80211_CHAN_PASSIVE_SCAN) == passive) &&
342 ((flags & IEEE80211_CHAN_RADAR) == radar) &&
343 (req->channels[i]->band == band)) {
344 wl1271_debug(DEBUG_SCAN, "band %d, center_freq %d ",
345 req->channels[i]->band,
346 req->channels[i]->center_freq);
347 wl1271_debug(DEBUG_SCAN, "hw_value %d, flags %X",
348 req->channels[i]->hw_value,
349 req->channels[i]->flags);
350 wl1271_debug(DEBUG_SCAN, "max_power %d",
351 req->channels[i]->max_power);
352
353 if (flags & IEEE80211_CHAN_PASSIVE_SCAN) {
354 channels[j].passive_duration =
355 cpu_to_le16(c->dwell_time_passive);
356 } else {
357 channels[j].min_duration =
358 cpu_to_le16(c->min_dwell_time_active);
359 channels[j].max_duration =
360 cpu_to_le16(c->max_dwell_time_active);
361 }
362 channels[j].tx_power_att = req->channels[j]->max_power;
363 channels[j].channel = req->channels[i]->hw_value;
364
365 j++;
366 }
367 }
368
369 return j - start;
370}
371
372static int
373wl1271_scan_sched_scan_channels(struct wl1271 *wl,
374 struct cfg80211_sched_scan_request *req,
375 struct wl1271_cmd_sched_scan_config *cfg)
376{
377 int idx = 0;
378
379 cfg->passive[0] =
380 wl1271_scan_get_sched_scan_channels(wl, req, cfg->channels,
381 IEEE80211_BAND_2GHZ,
382 false, true, idx);
383 idx += cfg->passive[0];
384
385 cfg->active[0] =
386 wl1271_scan_get_sched_scan_channels(wl, req, cfg->channels,
387 IEEE80211_BAND_2GHZ,
388 false, false, idx);
389 idx += cfg->active[0];
390
391 cfg->passive[1] =
392 wl1271_scan_get_sched_scan_channels(wl, req, cfg->channels,
393 IEEE80211_BAND_5GHZ,
394 false, true, idx);
395 idx += cfg->passive[1];
396
397 cfg->active[1] =
398 wl1271_scan_get_sched_scan_channels(wl, req, cfg->channels,
399 IEEE80211_BAND_5GHZ,
400 false, false, 14);
401 idx += cfg->active[1];
402
403 cfg->dfs =
404 wl1271_scan_get_sched_scan_channels(wl, req, cfg->channels,
405 IEEE80211_BAND_5GHZ,
406 true, false, idx);
407 idx += cfg->dfs;
408
409 wl1271_debug(DEBUG_SCAN, " 2.4GHz: active %d passive %d",
410 cfg->active[0], cfg->passive[0]);
411 wl1271_debug(DEBUG_SCAN, " 5GHz: active %d passive %d",
412 cfg->active[1], cfg->passive[1]);
413
414 return idx;
415}
416
417int wl1271_scan_sched_scan_config(struct wl1271 *wl,
418 struct cfg80211_sched_scan_request *req,
419 struct ieee80211_sched_scan_ies *ies)
420{
421 struct wl1271_cmd_sched_scan_config *cfg = NULL;
422 struct conf_sched_scan_settings *c = &wl->conf.sched_scan;
423 int i, total_channels, ret;
424
425 wl1271_debug(DEBUG_CMD, "cmd sched_scan scan config");
426
427 cfg = kzalloc(sizeof(*cfg), GFP_KERNEL);
428 if (!cfg)
429 return -ENOMEM;
430
431 cfg->rssi_threshold = c->rssi_threshold;
432 cfg->snr_threshold = c->snr_threshold;
433 cfg->n_probe_reqs = c->num_probe_reqs;
434 /* cycles set to 0 it means infinite (until manually stopped) */
435 cfg->cycles = 0;
436 /* report APs when at least 1 is found */
437 cfg->report_after = 1;
438 /* don't stop scanning automatically when something is found */
439 cfg->terminate = 0;
440 cfg->tag = WL1271_SCAN_DEFAULT_TAG;
441 /* don't filter on BSS type */
442 cfg->bss_type = SCAN_BSS_TYPE_ANY;
443 /* currently NL80211 supports only a single interval */
444 for (i = 0; i < SCAN_MAX_CYCLE_INTERVALS; i++)
445 cfg->intervals[i] = cpu_to_le32(req->interval);
446
447 if (req->ssids[0].ssid_len && req->ssids[0].ssid) {
448 cfg->filter_type = SCAN_SSID_FILTER_SPECIFIC;
449 cfg->ssid_len = req->ssids[0].ssid_len;
450 memcpy(cfg->ssid, req->ssids[0].ssid,
451 req->ssids[0].ssid_len);
452 } else {
453 cfg->filter_type = SCAN_SSID_FILTER_ANY;
454 cfg->ssid_len = 0;
455 }
456
457 total_channels = wl1271_scan_sched_scan_channels(wl, req, cfg);
458 if (total_channels == 0) {
459 wl1271_error("scan channel list is empty");
460 ret = -EINVAL;
461 goto out;
462 }
463
464 if (cfg->active[0]) {
465 ret = wl1271_cmd_build_probe_req(wl, req->ssids[0].ssid,
466 req->ssids[0].ssid_len,
467 ies->ie[IEEE80211_BAND_2GHZ],
468 ies->len[IEEE80211_BAND_2GHZ],
469 IEEE80211_BAND_2GHZ);
470 if (ret < 0) {
471 wl1271_error("2.4GHz PROBE request template failed");
472 goto out;
473 }
474 }
475
476 if (cfg->active[1]) {
477 ret = wl1271_cmd_build_probe_req(wl, req->ssids[0].ssid,
478 req->ssids[0].ssid_len,
479 ies->ie[IEEE80211_BAND_5GHZ],
480 ies->len[IEEE80211_BAND_5GHZ],
481 IEEE80211_BAND_5GHZ);
482 if (ret < 0) {
483 wl1271_error("5GHz PROBE request template failed");
484 goto out;
485 }
486 }
487
488 wl1271_dump(DEBUG_SCAN, "SCAN_CFG: ", cfg, sizeof(*cfg));
489
490 ret = wl1271_cmd_send(wl, CMD_CONNECTION_SCAN_CFG, cfg,
491 sizeof(*cfg), 0);
492 if (ret < 0) {
493 wl1271_error("SCAN configuration failed");
494 goto out;
495 }
496out:
497 kfree(cfg);
498 return ret;
499}
500
501int wl1271_scan_sched_scan_start(struct wl1271 *wl)
502{
503 struct wl1271_cmd_sched_scan_start *start;
504 int ret = 0;
505
506 wl1271_debug(DEBUG_CMD, "cmd periodic scan start");
507
508 if (wl->bss_type != BSS_TYPE_STA_BSS)
509 return -EOPNOTSUPP;
510
511 if (!test_bit(WL1271_FLAG_IDLE, &wl->flags))
512 return -EBUSY;
513
514 start = kzalloc(sizeof(*start), GFP_KERNEL);
515 if (!start)
516 return -ENOMEM;
517
518 start->tag = WL1271_SCAN_DEFAULT_TAG;
519
520 ret = wl1271_cmd_send(wl, CMD_START_PERIODIC_SCAN, start,
521 sizeof(*start), 0);
522 if (ret < 0) {
523 wl1271_error("failed to send scan start command");
524 goto out_free;
525 }
526
527out_free:
528 kfree(start);
529 return ret;
530}
531
532void wl1271_scan_sched_scan_results(struct wl1271 *wl)
533{
534 wl1271_debug(DEBUG_SCAN, "got periodic scan results");
535
536 ieee80211_sched_scan_results(wl->hw);
537}
538
539void wl1271_scan_sched_scan_stop(struct wl1271 *wl)
540{
541 struct wl1271_cmd_sched_scan_stop *stop;
542 int ret = 0;
543
544 wl1271_debug(DEBUG_CMD, "cmd periodic scan stop");
545
546 /* FIXME: what to do if alloc'ing to stop fails? */
547 stop = kzalloc(sizeof(*stop), GFP_KERNEL);
548 if (!stop) {
549 wl1271_error("failed to alloc memory to send sched scan stop");
550 return;
551 }
552
553 stop->tag = WL1271_SCAN_DEFAULT_TAG;
554
555 ret = wl1271_cmd_send(wl, CMD_STOP_PERIODIC_SCAN, stop,
556 sizeof(*stop), 0);
557 if (ret < 0) {
558 wl1271_error("failed to send sched scan stop command");
559 goto out_free;
560 }
561 wl->sched_scanning = false;
562
563out_free:
564 kfree(stop);
565}
diff --git a/drivers/net/wireless/wl12xx/scan.h b/drivers/net/wireless/wl12xx/scan.h
index 421a750add5a..c83319579ca3 100644
--- a/drivers/net/wireless/wl12xx/scan.h
+++ b/drivers/net/wireless/wl12xx/scan.h
@@ -33,6 +33,12 @@ int wl1271_scan_build_probe_req(struct wl1271 *wl,
33 const u8 *ie, size_t ie_len, u8 band); 33 const u8 *ie, size_t ie_len, u8 band);
34void wl1271_scan_stm(struct wl1271 *wl); 34void wl1271_scan_stm(struct wl1271 *wl);
35void wl1271_scan_complete_work(struct work_struct *work); 35void wl1271_scan_complete_work(struct work_struct *work);
36int wl1271_scan_sched_scan_config(struct wl1271 *wl,
37 struct cfg80211_sched_scan_request *req,
38 struct ieee80211_sched_scan_ies *ies);
39int wl1271_scan_sched_scan_start(struct wl1271 *wl);
40void wl1271_scan_sched_scan_stop(struct wl1271 *wl);
41void wl1271_scan_sched_scan_results(struct wl1271 *wl);
36 42
37#define WL1271_SCAN_MAX_CHANNELS 24 43#define WL1271_SCAN_MAX_CHANNELS 24
38#define WL1271_SCAN_DEFAULT_TAG 1 44#define WL1271_SCAN_DEFAULT_TAG 1
@@ -106,4 +112,112 @@ struct wl1271_cmd_trigger_scan_to {
106 __le32 timeout; 112 __le32 timeout;
107} __packed; 113} __packed;
108 114
115#define MAX_CHANNELS_ALL_BANDS 41
116#define SCAN_MAX_CYCLE_INTERVALS 16
117#define SCAN_MAX_BANDS 3
118
119enum {
120 SCAN_CHANNEL_TYPE_2GHZ_PASSIVE,
121 SCAN_CHANNEL_TYPE_2GHZ_ACTIVE,
122 SCAN_CHANNEL_TYPE_5GHZ_PASSIVE,
123 SCAN_CHANNEL_TYPE_5GHZ_ACTIVE,
124 SCAN_CHANNEL_TYPE_5GHZ_DFS,
125};
126
127enum {
128 SCAN_SSID_FILTER_ANY = 0,
129 SCAN_SSID_FILTER_SPECIFIC = 1,
130 SCAN_SSID_FILTER_LIST = 2,
131 SCAN_SSID_FILTER_DISABLED = 3
132};
133
134enum {
135 SCAN_BSS_TYPE_INDEPENDENT,
136 SCAN_BSS_TYPE_INFRASTRUCTURE,
137 SCAN_BSS_TYPE_ANY,
138};
139
140struct conn_scan_ch_params {
141 __le16 min_duration;
142 __le16 max_duration;
143 __le16 passive_duration;
144
145 u8 channel;
146 u8 tx_power_att;
147
148 /* bit 0: DFS channel; bit 1: DFS enabled */
149 u8 flags;
150
151 u8 padding[3];
152} __packed;
153
154struct wl1271_cmd_sched_scan_config {
155 struct wl1271_cmd_header header;
156
157 __le32 intervals[SCAN_MAX_CYCLE_INTERVALS];
158
159 s8 rssi_threshold; /* for filtering (in dBm) */
160 s8 snr_threshold; /* for filtering (in dB) */
161
162 u8 cycles; /* maximum number of scan cycles */
163 u8 report_after; /* report when this number of results are received */
164 u8 terminate; /* stop scanning after reporting */
165
166 u8 tag;
167 u8 bss_type; /* for filtering */
168 u8 filter_type;
169
170 u8 ssid_len; /* For SCAN_SSID_FILTER_SPECIFIC */
171 u8 ssid[IW_ESSID_MAX_SIZE];
172
173 u8 n_probe_reqs; /* Number of probes requests per channel */
174
175 u8 passive[SCAN_MAX_BANDS];
176 u8 active[SCAN_MAX_BANDS];
177
178 u8 dfs;
179
180 u8 padding[3];
181
182 struct conn_scan_ch_params channels[MAX_CHANNELS_ALL_BANDS];
183} __packed;
184
185
186#define SCHED_SCAN_MAX_SSIDS 8
187
188enum {
189 SCAN_SSID_TYPE_PUBLIC = 0,
190 SCAN_SSID_TYPE_HIDDEN = 1,
191};
192
193struct wl1271_ssid {
194 u8 type;
195 u8 len;
196 u8 ssid[IW_ESSID_MAX_SIZE];
197 /* u8 padding[2]; */
198} __packed;
199
200struct wl1271_cmd_sched_scan_ssid_list {
201 struct wl1271_cmd_header header;
202
203 u8 n_ssids;
204 struct wl1271_ssid ssids[SCHED_SCAN_MAX_SSIDS];
205 u8 padding[3];
206} __packed;
207
208struct wl1271_cmd_sched_scan_start {
209 struct wl1271_cmd_header header;
210
211 u8 tag;
212 u8 padding[3];
213} __packed;
214
215struct wl1271_cmd_sched_scan_stop {
216 struct wl1271_cmd_header header;
217
218 u8 tag;
219 u8 padding[3];
220} __packed;
221
222
109#endif /* __WL1271_SCAN_H__ */ 223#endif /* __WL1271_SCAN_H__ */
diff --git a/drivers/net/wireless/wl12xx/sdio.c b/drivers/net/wireless/wl12xx/sdio.c
index bcd4ad7ba90d..92d29a860fc0 100644
--- a/drivers/net/wireless/wl12xx/sdio.c
+++ b/drivers/net/wireless/wl12xx/sdio.c
@@ -82,6 +82,16 @@ static irqreturn_t wl1271_hardirq(int irq, void *cookie)
82 complete(wl->elp_compl); 82 complete(wl->elp_compl);
83 wl->elp_compl = NULL; 83 wl->elp_compl = NULL;
84 } 84 }
85
86 if (test_bit(WL1271_FLAG_SUSPENDED, &wl->flags)) {
87 /* don't enqueue a work right now. mark it as pending */
88 set_bit(WL1271_FLAG_PENDING_WORK, &wl->flags);
89 wl1271_debug(DEBUG_IRQ, "should not enqueue work");
90 disable_irq_nosync(wl->irq);
91 pm_wakeup_event(wl1271_sdio_wl_to_dev(wl), 0);
92 spin_unlock_irqrestore(&wl->wl_lock, flags);
93 return IRQ_HANDLED;
94 }
85 spin_unlock_irqrestore(&wl->wl_lock, flags); 95 spin_unlock_irqrestore(&wl->wl_lock, flags);
86 96
87 return IRQ_WAKE_THREAD; 97 return IRQ_WAKE_THREAD;
@@ -221,6 +231,7 @@ static int __devinit wl1271_probe(struct sdio_func *func,
221 const struct wl12xx_platform_data *wlan_data; 231 const struct wl12xx_platform_data *wlan_data;
222 struct wl1271 *wl; 232 struct wl1271 *wl;
223 unsigned long irqflags; 233 unsigned long irqflags;
234 mmc_pm_flag_t mmcflags;
224 int ret; 235 int ret;
225 236
226 /* We are only able to handle the wlan function */ 237 /* We are only able to handle the wlan function */
@@ -267,8 +278,18 @@ static int __devinit wl1271_probe(struct sdio_func *func,
267 goto out_free; 278 goto out_free;
268 } 279 }
269 280
281 enable_irq_wake(wl->irq);
282 device_init_wakeup(wl1271_sdio_wl_to_dev(wl), 1);
283
270 disable_irq(wl->irq); 284 disable_irq(wl->irq);
271 285
286 /* if sdio can keep power while host is suspended, enable wow */
287 mmcflags = sdio_get_host_pm_caps(func);
288 wl1271_debug(DEBUG_SDIO, "sdio PM caps = 0x%x", mmcflags);
289
290 if (mmcflags & MMC_PM_KEEP_POWER)
291 hw->wiphy->wowlan.flags = WIPHY_WOWLAN_ANY;
292
272 ret = wl1271_init_ieee80211(wl); 293 ret = wl1271_init_ieee80211(wl);
273 if (ret) 294 if (ret)
274 goto out_irq; 295 goto out_irq;
@@ -303,6 +324,8 @@ static void __devexit wl1271_remove(struct sdio_func *func)
303 pm_runtime_get_noresume(&func->dev); 324 pm_runtime_get_noresume(&func->dev);
304 325
305 wl1271_unregister_hw(wl); 326 wl1271_unregister_hw(wl);
327 device_init_wakeup(wl1271_sdio_wl_to_dev(wl), 0);
328 disable_irq_wake(wl->irq);
306 free_irq(wl->irq, wl); 329 free_irq(wl->irq, wl);
307 wl1271_free_hw(wl); 330 wl1271_free_hw(wl);
308} 331}
@@ -311,11 +334,50 @@ static int wl1271_suspend(struct device *dev)
311{ 334{
312 /* Tell MMC/SDIO core it's OK to power down the card 335 /* Tell MMC/SDIO core it's OK to power down the card
313 * (if it isn't already), but not to remove it completely */ 336 * (if it isn't already), but not to remove it completely */
314 return 0; 337 struct sdio_func *func = dev_to_sdio_func(dev);
338 struct wl1271 *wl = sdio_get_drvdata(func);
339 mmc_pm_flag_t sdio_flags;
340 int ret = 0;
341
342 wl1271_debug(DEBUG_MAC80211, "wl1271 suspend. wow_enabled: %d",
343 wl->wow_enabled);
344
345 /* check whether sdio should keep power */
346 if (wl->wow_enabled) {
347 sdio_flags = sdio_get_host_pm_caps(func);
348
349 if (!(sdio_flags & MMC_PM_KEEP_POWER)) {
350 wl1271_error("can't keep power while host "
351 "is suspended");
352 ret = -EINVAL;
353 goto out;
354 }
355
356 /* keep power while host suspended */
357 ret = sdio_set_host_pm_flags(func, MMC_PM_KEEP_POWER);
358 if (ret) {
359 wl1271_error("error while trying to keep power");
360 goto out;
361 }
362
363 /* release host */
364 sdio_release_host(func);
365 }
366out:
367 return ret;
315} 368}
316 369
317static int wl1271_resume(struct device *dev) 370static int wl1271_resume(struct device *dev)
318{ 371{
372 struct sdio_func *func = dev_to_sdio_func(dev);
373 struct wl1271 *wl = sdio_get_drvdata(func);
374
375 wl1271_debug(DEBUG_MAC80211, "wl1271 resume");
376 if (wl->wow_enabled) {
377 /* claim back host */
378 sdio_claim_host(func);
379 }
380
319 return 0; 381 return 0;
320} 382}
321 383
diff --git a/drivers/net/wireless/wl12xx/wl12xx.h b/drivers/net/wireless/wl12xx/wl12xx.h
index b7601438ecac..fbe8f46d1232 100644
--- a/drivers/net/wireless/wl12xx/wl12xx.h
+++ b/drivers/net/wireless/wl12xx/wl12xx.h
@@ -351,13 +351,14 @@ enum wl12xx_flags {
351 WL1271_FLAG_PSM_REQUESTED, 351 WL1271_FLAG_PSM_REQUESTED,
352 WL1271_FLAG_IRQ_RUNNING, 352 WL1271_FLAG_IRQ_RUNNING,
353 WL1271_FLAG_IDLE, 353 WL1271_FLAG_IDLE,
354 WL1271_FLAG_IDLE_REQUESTED,
355 WL1271_FLAG_PSPOLL_FAILURE, 354 WL1271_FLAG_PSPOLL_FAILURE,
356 WL1271_FLAG_STA_STATE_SENT, 355 WL1271_FLAG_STA_STATE_SENT,
357 WL1271_FLAG_FW_TX_BUSY, 356 WL1271_FLAG_FW_TX_BUSY,
358 WL1271_FLAG_AP_STARTED, 357 WL1271_FLAG_AP_STARTED,
359 WL1271_FLAG_IF_INITIALIZED, 358 WL1271_FLAG_IF_INITIALIZED,
360 WL1271_FLAG_DUMMY_PACKET_PENDING, 359 WL1271_FLAG_DUMMY_PACKET_PENDING,
360 WL1271_FLAG_SUSPENDED,
361 WL1271_FLAG_PENDING_WORK,
361}; 362};
362 363
363struct wl1271_link { 364struct wl1271_link {
@@ -480,6 +481,8 @@ struct wl1271 {
480 struct wl1271_scan scan; 481 struct wl1271_scan scan;
481 struct delayed_work scan_complete_work; 482 struct delayed_work scan_complete_work;
482 483
484 bool sched_scanning;
485
483 /* probe-req template for the current AP */ 486 /* probe-req template for the current AP */
484 struct sk_buff *probereq; 487 struct sk_buff *probereq;
485 488
@@ -510,6 +513,7 @@ struct wl1271 {
510 unsigned int rx_filter; 513 unsigned int rx_filter;
511 514
512 struct completion *elp_compl; 515 struct completion *elp_compl;
516 struct completion *ps_compl;
513 struct delayed_work elp_work; 517 struct delayed_work elp_work;
514 struct delayed_work pspoll_work; 518 struct delayed_work pspoll_work;
515 519
@@ -564,6 +568,12 @@ struct wl1271 {
564 int tcxo_clock; 568 int tcxo_clock;
565 569
566 /* 570 /*
571 * wowlan trigger was configured during suspend.
572 * (currently, only "ANY" trigger is supported)
573 */
574 bool wow_enabled;
575
576 /*
567 * AP-mode - links indexed by HLID. The global and broadcast links 577 * AP-mode - links indexed by HLID. The global and broadcast links
568 * are always active. 578 * are always active.
569 */ 579 */