diff options
Diffstat (limited to 'drivers/net/wireless/wl12xx/main.c')
-rw-r--r-- | drivers/net/wireless/wl12xx/main.c | 122 |
1 files changed, 122 insertions, 0 deletions
diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c index a2171a4e9413..15d8166fbf66 100644 --- a/drivers/net/wireless/wl12xx/main.c +++ b/drivers/net/wireless/wl12xx/main.c | |||
@@ -366,6 +366,7 @@ static struct conf_drv_settings default_conf = { | |||
366 | .duration = 150, | 366 | .duration = 150, |
367 | .queues = 0x1, | 367 | .queues = 0x1, |
368 | .interval = 20, | 368 | .interval = 20, |
369 | .always = 0, | ||
369 | }, | 370 | }, |
370 | .hci_io_ds = HCI_IO_DS_6MA, | 371 | .hci_io_ds = HCI_IO_DS_6MA, |
371 | }; | 372 | }; |
@@ -478,6 +479,117 @@ static int wl1271_reg_notify(struct wiphy *wiphy, | |||
478 | return 0; | 479 | return 0; |
479 | } | 480 | } |
480 | 481 | ||
482 | static int wl1271_set_rx_streaming(struct wl1271 *wl, bool enable) | ||
483 | { | ||
484 | int ret = 0; | ||
485 | |||
486 | /* we should hold wl->mutex */ | ||
487 | ret = wl1271_acx_ps_rx_streaming(wl, enable); | ||
488 | if (ret < 0) | ||
489 | goto out; | ||
490 | |||
491 | if (enable) | ||
492 | set_bit(WL1271_FLAG_RX_STREAMING_STARTED, &wl->flags); | ||
493 | else | ||
494 | clear_bit(WL1271_FLAG_RX_STREAMING_STARTED, &wl->flags); | ||
495 | out: | ||
496 | return ret; | ||
497 | } | ||
498 | |||
499 | /* | ||
500 | * this function is being called when the rx_streaming interval | ||
501 | * has beed changed or rx_streaming should be disabled | ||
502 | */ | ||
503 | int wl1271_recalc_rx_streaming(struct wl1271 *wl) | ||
504 | { | ||
505 | int ret = 0; | ||
506 | int period = wl->conf.rx_streaming.interval; | ||
507 | |||
508 | /* don't reconfigure if rx_streaming is disabled */ | ||
509 | if (!test_bit(WL1271_FLAG_RX_STREAMING_STARTED, &wl->flags)) | ||
510 | goto out; | ||
511 | |||
512 | /* reconfigure/disable according to new streaming_period */ | ||
513 | if (period && | ||
514 | test_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags) && | ||
515 | (wl->conf.rx_streaming.always || | ||
516 | test_bit(WL1271_FLAG_SOFT_GEMINI, &wl->flags))) | ||
517 | ret = wl1271_set_rx_streaming(wl, true); | ||
518 | else { | ||
519 | ret = wl1271_set_rx_streaming(wl, false); | ||
520 | /* don't cancel_work_sync since we might deadlock */ | ||
521 | del_timer_sync(&wl->rx_streaming_timer); | ||
522 | } | ||
523 | out: | ||
524 | return ret; | ||
525 | } | ||
526 | |||
527 | static void wl1271_rx_streaming_enable_work(struct work_struct *work) | ||
528 | { | ||
529 | int ret; | ||
530 | struct wl1271 *wl = | ||
531 | container_of(work, struct wl1271, rx_streaming_enable_work); | ||
532 | |||
533 | mutex_lock(&wl->mutex); | ||
534 | |||
535 | if (test_bit(WL1271_FLAG_RX_STREAMING_STARTED, &wl->flags) || | ||
536 | !test_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags) || | ||
537 | (!wl->conf.rx_streaming.always && | ||
538 | !test_bit(WL1271_FLAG_SOFT_GEMINI, &wl->flags))) | ||
539 | goto out; | ||
540 | |||
541 | if (!wl->conf.rx_streaming.interval) | ||
542 | goto out; | ||
543 | |||
544 | ret = wl1271_ps_elp_wakeup(wl); | ||
545 | if (ret < 0) | ||
546 | goto out; | ||
547 | |||
548 | ret = wl1271_set_rx_streaming(wl, true); | ||
549 | if (ret < 0) | ||
550 | goto out_sleep; | ||
551 | |||
552 | /* stop it after some time of inactivity */ | ||
553 | mod_timer(&wl->rx_streaming_timer, | ||
554 | jiffies + msecs_to_jiffies(wl->conf.rx_streaming.duration)); | ||
555 | |||
556 | out_sleep: | ||
557 | wl1271_ps_elp_sleep(wl); | ||
558 | out: | ||
559 | mutex_unlock(&wl->mutex); | ||
560 | } | ||
561 | |||
562 | static void wl1271_rx_streaming_disable_work(struct work_struct *work) | ||
563 | { | ||
564 | int ret; | ||
565 | struct wl1271 *wl = | ||
566 | container_of(work, struct wl1271, rx_streaming_disable_work); | ||
567 | |||
568 | mutex_lock(&wl->mutex); | ||
569 | |||
570 | if (!test_bit(WL1271_FLAG_RX_STREAMING_STARTED, &wl->flags)) | ||
571 | goto out; | ||
572 | |||
573 | ret = wl1271_ps_elp_wakeup(wl); | ||
574 | if (ret < 0) | ||
575 | goto out; | ||
576 | |||
577 | ret = wl1271_set_rx_streaming(wl, false); | ||
578 | if (ret) | ||
579 | goto out_sleep; | ||
580 | |||
581 | out_sleep: | ||
582 | wl1271_ps_elp_sleep(wl); | ||
583 | out: | ||
584 | mutex_unlock(&wl->mutex); | ||
585 | } | ||
586 | |||
587 | static void wl1271_rx_streaming_timer(unsigned long data) | ||
588 | { | ||
589 | struct wl1271 *wl = (struct wl1271 *)data; | ||
590 | ieee80211_queue_work(wl->hw, &wl->rx_streaming_disable_work); | ||
591 | } | ||
592 | |||
481 | static void wl1271_conf_init(struct wl1271 *wl) | 593 | static void wl1271_conf_init(struct wl1271 *wl) |
482 | { | 594 | { |
483 | 595 | ||
@@ -1699,6 +1811,9 @@ static void __wl1271_op_remove_interface(struct wl1271 *wl, | |||
1699 | cancel_delayed_work_sync(&wl->scan_complete_work); | 1811 | cancel_delayed_work_sync(&wl->scan_complete_work); |
1700 | cancel_work_sync(&wl->netstack_work); | 1812 | cancel_work_sync(&wl->netstack_work); |
1701 | cancel_work_sync(&wl->tx_work); | 1813 | cancel_work_sync(&wl->tx_work); |
1814 | del_timer_sync(&wl->rx_streaming_timer); | ||
1815 | cancel_work_sync(&wl->rx_streaming_enable_work); | ||
1816 | cancel_work_sync(&wl->rx_streaming_disable_work); | ||
1702 | cancel_delayed_work_sync(&wl->pspoll_work); | 1817 | cancel_delayed_work_sync(&wl->pspoll_work); |
1703 | cancel_delayed_work_sync(&wl->elp_work); | 1818 | cancel_delayed_work_sync(&wl->elp_work); |
1704 | 1819 | ||
@@ -3969,6 +4084,11 @@ struct ieee80211_hw *wl1271_alloc_hw(void) | |||
3969 | INIT_WORK(&wl->tx_work, wl1271_tx_work); | 4084 | INIT_WORK(&wl->tx_work, wl1271_tx_work); |
3970 | INIT_WORK(&wl->recovery_work, wl1271_recovery_work); | 4085 | INIT_WORK(&wl->recovery_work, wl1271_recovery_work); |
3971 | INIT_DELAYED_WORK(&wl->scan_complete_work, wl1271_scan_complete_work); | 4086 | INIT_DELAYED_WORK(&wl->scan_complete_work, wl1271_scan_complete_work); |
4087 | INIT_WORK(&wl->rx_streaming_enable_work, | ||
4088 | wl1271_rx_streaming_enable_work); | ||
4089 | INIT_WORK(&wl->rx_streaming_disable_work, | ||
4090 | wl1271_rx_streaming_disable_work); | ||
4091 | |||
3972 | wl->channel = WL1271_DEFAULT_CHANNEL; | 4092 | wl->channel = WL1271_DEFAULT_CHANNEL; |
3973 | wl->beacon_int = WL1271_DEFAULT_BEACON_INT; | 4093 | wl->beacon_int = WL1271_DEFAULT_BEACON_INT; |
3974 | wl->default_key = 0; | 4094 | wl->default_key = 0; |
@@ -3994,6 +4114,8 @@ struct ieee80211_hw *wl1271_alloc_hw(void) | |||
3994 | wl->quirks = 0; | 4114 | wl->quirks = 0; |
3995 | wl->platform_quirks = 0; | 4115 | wl->platform_quirks = 0; |
3996 | wl->sched_scanning = false; | 4116 | wl->sched_scanning = false; |
4117 | setup_timer(&wl->rx_streaming_timer, wl1271_rx_streaming_timer, | ||
4118 | (unsigned long) wl); | ||
3997 | 4119 | ||
3998 | memset(wl->tx_frames_map, 0, sizeof(wl->tx_frames_map)); | 4120 | memset(wl->tx_frames_map, 0, sizeof(wl->tx_frames_map)); |
3999 | for (i = 0; i < ACX_TX_DESCRIPTORS; i++) | 4121 | for (i = 0; i < ACX_TX_DESCRIPTORS; i++) |