aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net
diff options
context:
space:
mode:
authorEliad Peller <eliad@wizery.com>2011-05-15 04:10:29 -0400
committerLuciano Coelho <coelho@ti.com>2011-06-27 03:15:49 -0400
commit77ddaa108f727b5ef3be004b952d2c3d3ffc48e5 (patch)
treef8eea67a0930d2eb4879024abf2ce1df8ee66ccd /drivers/net
parentf84673d59773ded6efab640c5ee5f44b34116b75 (diff)
wl12xx: add automatic rx streaming triggers
When rx_streaming.interval is non-zero, use automatic rx streaming. Enable rx streaming on the each rx/tx packet, and disable it rx_streaming.duration msecs later. When rx_streaming.always=0 (default), rx streaming is enabled only when there is a coex operation. Signed-off-by: Eliad Peller <eliad@wizery.com> Signed-off-by: Luciano Coelho <coelho@ti.com>
Diffstat (limited to 'drivers/net')
-rw-r--r--drivers/net/wireless/wl12xx/conf.h5
-rw-r--r--drivers/net/wireless/wl12xx/event.c25
-rw-r--r--drivers/net/wireless/wl12xx/main.c122
-rw-r--r--drivers/net/wireless/wl12xx/rx.c29
-rw-r--r--drivers/net/wireless/wl12xx/tx.c25
-rw-r--r--drivers/net/wireless/wl12xx/wl12xx.h8
6 files changed, 203 insertions, 11 deletions
diff --git a/drivers/net/wireless/wl12xx/conf.h b/drivers/net/wireless/wl12xx/conf.h
index 94a5c5646bb4..aa79b437e60e 100644
--- a/drivers/net/wireless/wl12xx/conf.h
+++ b/drivers/net/wireless/wl12xx/conf.h
@@ -1270,6 +1270,11 @@ struct conf_rx_streaming_settings {
1270 * Range: 0 (disabled), 10 - 100 1270 * Range: 0 (disabled), 10 - 100
1271 */ 1271 */
1272 u8 interval; 1272 u8 interval;
1273
1274 /*
1275 * enable rx streaming also when there is no coex activity
1276 */
1277 u8 always;
1273}; 1278};
1274 1279
1275struct conf_drv_settings { 1280struct conf_drv_settings {
diff --git a/drivers/net/wireless/wl12xx/event.c b/drivers/net/wireless/wl12xx/event.c
index 94bbd00ec31b..0c60ffea414d 100644
--- a/drivers/net/wireless/wl12xx/event.c
+++ b/drivers/net/wireless/wl12xx/event.c
@@ -183,6 +183,21 @@ static void wl1271_stop_ba_event(struct wl1271 *wl, u8 ba_allowed)
183 ieee80211_stop_rx_ba_session(wl->vif, wl->ba_rx_bitmap, wl->bssid); 183 ieee80211_stop_rx_ba_session(wl->vif, wl->ba_rx_bitmap, wl->bssid);
184} 184}
185 185
186static void wl12xx_event_soft_gemini_sense(struct wl1271 *wl,
187 u8 enable)
188{
189 if (enable) {
190 /* disable dynamic PS when requested by the firmware */
191 ieee80211_disable_dyn_ps(wl->vif);
192 set_bit(WL1271_FLAG_SOFT_GEMINI, &wl->flags);
193 } else {
194 ieee80211_enable_dyn_ps(wl->vif);
195 clear_bit(WL1271_FLAG_SOFT_GEMINI, &wl->flags);
196 wl1271_recalc_rx_streaming(wl);
197 }
198
199}
200
186static void wl1271_event_mbox_dump(struct event_mailbox *mbox) 201static void wl1271_event_mbox_dump(struct event_mailbox *mbox)
187{ 202{
188 wl1271_debug(DEBUG_EVENT, "MBOX DUMP:"); 203 wl1271_debug(DEBUG_EVENT, "MBOX DUMP:");
@@ -226,14 +241,10 @@ static int wl1271_event_process(struct wl1271 *wl, struct event_mailbox *mbox)
226 } 241 }
227 } 242 }
228 243
229 /* disable dynamic PS when requested by the firmware */
230 if (vector & SOFT_GEMINI_SENSE_EVENT_ID && 244 if (vector & SOFT_GEMINI_SENSE_EVENT_ID &&
231 wl->bss_type == BSS_TYPE_STA_BSS) { 245 wl->bss_type == BSS_TYPE_STA_BSS)
232 if (mbox->soft_gemini_sense_info) 246 wl12xx_event_soft_gemini_sense(wl,
233 ieee80211_disable_dyn_ps(wl->vif); 247 mbox->soft_gemini_sense_info);
234 else
235 ieee80211_enable_dyn_ps(wl->vif);
236 }
237 248
238 /* 249 /*
239 * The BSS_LOSE_EVENT_ID is only needed while psm (and hence beacon 250 * The BSS_LOSE_EVENT_ID is only needed while psm (and hence beacon
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
482static 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);
495out:
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 */
503int 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 }
523out:
524 return ret;
525}
526
527static 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
556out_sleep:
557 wl1271_ps_elp_sleep(wl);
558out:
559 mutex_unlock(&wl->mutex);
560}
561
562static 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
581out_sleep:
582 wl1271_ps_elp_sleep(wl);
583out:
584 mutex_unlock(&wl->mutex);
585}
586
587static 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
481static void wl1271_conf_init(struct wl1271 *wl) 593static 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++)
diff --git a/drivers/net/wireless/wl12xx/rx.c b/drivers/net/wireless/wl12xx/rx.c
index 70091035e019..db230a503bf7 100644
--- a/drivers/net/wireless/wl12xx/rx.c
+++ b/drivers/net/wireless/wl12xx/rx.c
@@ -95,6 +95,7 @@ static int wl1271_rx_handle_data(struct wl1271 *wl, u8 *data, u32 length)
95 struct ieee80211_hdr *hdr; 95 struct ieee80211_hdr *hdr;
96 u8 *buf; 96 u8 *buf;
97 u8 beacon = 0; 97 u8 beacon = 0;
98 u8 is_data = 0;
98 99
99 /* 100 /*
100 * In PLT mode we seem to get frames and mac80211 warns about them, 101 * In PLT mode we seem to get frames and mac80211 warns about them,
@@ -137,6 +138,8 @@ static int wl1271_rx_handle_data(struct wl1271 *wl, u8 *data, u32 length)
137 hdr = (struct ieee80211_hdr *)skb->data; 138 hdr = (struct ieee80211_hdr *)skb->data;
138 if (ieee80211_is_beacon(hdr->frame_control)) 139 if (ieee80211_is_beacon(hdr->frame_control))
139 beacon = 1; 140 beacon = 1;
141 if (ieee80211_is_data_present(hdr->frame_control))
142 is_data = 1;
140 143
141 wl1271_rx_status(wl, desc, IEEE80211_SKB_RXCB(skb), beacon); 144 wl1271_rx_status(wl, desc, IEEE80211_SKB_RXCB(skb), beacon);
142 145
@@ -149,7 +152,7 @@ static int wl1271_rx_handle_data(struct wl1271 *wl, u8 *data, u32 length)
149 skb_queue_tail(&wl->deferred_rx_queue, skb); 152 skb_queue_tail(&wl->deferred_rx_queue, skb);
150 ieee80211_queue_work(wl->hw, &wl->netstack_work); 153 ieee80211_queue_work(wl->hw, &wl->netstack_work);
151 154
152 return 0; 155 return is_data;
153} 156}
154 157
155void wl1271_rx(struct wl1271 *wl, struct wl1271_fw_common_status *status) 158void wl1271_rx(struct wl1271 *wl, struct wl1271_fw_common_status *status)
@@ -162,6 +165,8 @@ void wl1271_rx(struct wl1271 *wl, struct wl1271_fw_common_status *status)
162 u32 mem_block; 165 u32 mem_block;
163 u32 pkt_length; 166 u32 pkt_length;
164 u32 pkt_offset; 167 u32 pkt_offset;
168 bool is_ap = (wl->bss_type == BSS_TYPE_AP_BSS);
169 bool had_data = false;
165 170
166 while (drv_rx_counter != fw_rx_counter) { 171 while (drv_rx_counter != fw_rx_counter) {
167 buf_size = 0; 172 buf_size = 0;
@@ -214,9 +219,11 @@ void wl1271_rx(struct wl1271 *wl, struct wl1271_fw_common_status *status)
214 * conditions, in that case the received frame will just 219 * conditions, in that case the received frame will just
215 * be dropped. 220 * be dropped.
216 */ 221 */
217 wl1271_rx_handle_data(wl, 222 if (wl1271_rx_handle_data(wl,
218 wl->aggr_buf + pkt_offset, 223 wl->aggr_buf + pkt_offset,
219 pkt_length); 224 pkt_length) == 1)
225 had_data = true;
226
220 wl->rx_counter++; 227 wl->rx_counter++;
221 drv_rx_counter++; 228 drv_rx_counter++;
222 drv_rx_counter &= NUM_RX_PKT_DESC_MOD_MASK; 229 drv_rx_counter &= NUM_RX_PKT_DESC_MOD_MASK;
@@ -230,6 +237,20 @@ void wl1271_rx(struct wl1271 *wl, struct wl1271_fw_common_status *status)
230 */ 237 */
231 if (wl->quirks & WL12XX_QUIRK_END_OF_TRANSACTION) 238 if (wl->quirks & WL12XX_QUIRK_END_OF_TRANSACTION)
232 wl1271_write32(wl, RX_DRIVER_COUNTER_ADDRESS, wl->rx_counter); 239 wl1271_write32(wl, RX_DRIVER_COUNTER_ADDRESS, wl->rx_counter);
240
241 if (!is_ap && wl->conf.rx_streaming.interval && had_data &&
242 (wl->conf.rx_streaming.always ||
243 test_bit(WL1271_FLAG_SOFT_GEMINI, &wl->flags))) {
244 u32 timeout = wl->conf.rx_streaming.duration;
245
246 /* restart rx streaming */
247 if (!test_bit(WL1271_FLAG_RX_STREAMING_STARTED, &wl->flags))
248 ieee80211_queue_work(wl->hw,
249 &wl->rx_streaming_enable_work);
250
251 mod_timer(&wl->rx_streaming_timer,
252 jiffies + msecs_to_jiffies(timeout));
253 }
233} 254}
234 255
235void wl1271_set_default_filters(struct wl1271 *wl) 256void wl1271_set_default_filters(struct wl1271 *wl)
diff --git a/drivers/net/wireless/wl12xx/tx.c b/drivers/net/wireless/wl12xx/tx.c
index ca3ab1c1acef..6603e60da04d 100644
--- a/drivers/net/wireless/wl12xx/tx.c
+++ b/drivers/net/wireless/wl12xx/tx.c
@@ -562,17 +562,29 @@ static void wl1271_skb_queue_head(struct wl1271 *wl, struct sk_buff *skb)
562 spin_unlock_irqrestore(&wl->wl_lock, flags); 562 spin_unlock_irqrestore(&wl->wl_lock, flags);
563} 563}
564 564
565static bool wl1271_tx_is_data_present(struct sk_buff *skb)
566{
567 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)(skb->data);
568
569 return ieee80211_is_data_present(hdr->frame_control);
570}
571
565void wl1271_tx_work_locked(struct wl1271 *wl) 572void wl1271_tx_work_locked(struct wl1271 *wl)
566{ 573{
567 struct sk_buff *skb; 574 struct sk_buff *skb;
568 u32 buf_offset = 0; 575 u32 buf_offset = 0;
569 bool sent_packets = false; 576 bool sent_packets = false;
577 bool had_data = false;
578 bool is_ap = (wl->bss_type == BSS_TYPE_AP_BSS);
570 int ret; 579 int ret;
571 580
572 if (unlikely(wl->state == WL1271_STATE_OFF)) 581 if (unlikely(wl->state == WL1271_STATE_OFF))
573 return; 582 return;
574 583
575 while ((skb = wl1271_skb_dequeue(wl))) { 584 while ((skb = wl1271_skb_dequeue(wl))) {
585 if (wl1271_tx_is_data_present(skb))
586 had_data = true;
587
576 ret = wl1271_prepare_tx_frame(wl, skb, buf_offset); 588 ret = wl1271_prepare_tx_frame(wl, skb, buf_offset);
577 if (ret == -EAGAIN) { 589 if (ret == -EAGAIN) {
578 /* 590 /*
@@ -619,6 +631,19 @@ out_ack:
619 631
620 wl1271_handle_tx_low_watermark(wl); 632 wl1271_handle_tx_low_watermark(wl);
621 } 633 }
634 if (!is_ap && wl->conf.rx_streaming.interval && had_data &&
635 (wl->conf.rx_streaming.always ||
636 test_bit(WL1271_FLAG_SOFT_GEMINI, &wl->flags))) {
637 u32 timeout = wl->conf.rx_streaming.duration;
638
639 /* enable rx streaming */
640 if (!test_bit(WL1271_FLAG_RX_STREAMING_STARTED, &wl->flags))
641 ieee80211_queue_work(wl->hw,
642 &wl->rx_streaming_enable_work);
643
644 mod_timer(&wl->rx_streaming_timer,
645 jiffies + msecs_to_jiffies(timeout));
646 }
622} 647}
623 648
624void wl1271_tx_work(struct work_struct *work) 649void wl1271_tx_work(struct work_struct *work)
diff --git a/drivers/net/wireless/wl12xx/wl12xx.h b/drivers/net/wireless/wl12xx/wl12xx.h
index 3bc794a1ee75..4bc22d8b66f5 100644
--- a/drivers/net/wireless/wl12xx/wl12xx.h
+++ b/drivers/net/wireless/wl12xx/wl12xx.h
@@ -359,6 +359,8 @@ enum wl12xx_flags {
359 WL1271_FLAG_DUMMY_PACKET_PENDING, 359 WL1271_FLAG_DUMMY_PACKET_PENDING,
360 WL1271_FLAG_SUSPENDED, 360 WL1271_FLAG_SUSPENDED,
361 WL1271_FLAG_PENDING_WORK, 361 WL1271_FLAG_PENDING_WORK,
362 WL1271_FLAG_SOFT_GEMINI,
363 WL1271_FLAG_RX_STREAMING_STARTED,
362}; 364};
363 365
364struct wl1271_link { 366struct wl1271_link {
@@ -508,6 +510,11 @@ struct wl1271 {
508 /* Default key (for WEP) */ 510 /* Default key (for WEP) */
509 u32 default_key; 511 u32 default_key;
510 512
513 /* Rx Streaming */
514 struct work_struct rx_streaming_enable_work;
515 struct work_struct rx_streaming_disable_work;
516 struct timer_list rx_streaming_timer;
517
511 unsigned int filters; 518 unsigned int filters;
512 unsigned int rx_config; 519 unsigned int rx_config;
513 unsigned int rx_filter; 520 unsigned int rx_filter;
@@ -602,6 +609,7 @@ struct wl1271_station {
602 609
603int wl1271_plt_start(struct wl1271 *wl); 610int wl1271_plt_start(struct wl1271 *wl);
604int wl1271_plt_stop(struct wl1271 *wl); 611int wl1271_plt_stop(struct wl1271 *wl);
612int wl1271_recalc_rx_streaming(struct wl1271 *wl);
605 613
606#define JOIN_TIMEOUT 5000 /* 5000 milliseconds to join */ 614#define JOIN_TIMEOUT 5000 /* 5000 milliseconds to join */
607 615