summaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/wl12xx/rx.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wireless/wl12xx/rx.c')
-rw-r--r--drivers/net/wireless/wl12xx/rx.c39
1 files changed, 34 insertions, 5 deletions
diff --git a/drivers/net/wireless/wl12xx/rx.c b/drivers/net/wireless/wl12xx/rx.c
index 70091035e01..0450fb49dbb 100644
--- a/drivers/net/wireless/wl12xx/rx.c
+++ b/drivers/net/wireless/wl12xx/rx.c
@@ -22,6 +22,7 @@
*/
#include <linux/gfp.h>
+#include <linux/sched.h>
#include "wl12xx.h"
#include "acx.h"
@@ -95,6 +96,7 @@ static int wl1271_rx_handle_data(struct wl1271 *wl, u8 *data, u32 length)
struct ieee80211_hdr *hdr;
u8 *buf;
u8 beacon = 0;
+ u8 is_data = 0;
/*
* In PLT mode we seem to get frames and mac80211 warns about them,
@@ -106,6 +108,13 @@ static int wl1271_rx_handle_data(struct wl1271 *wl, u8 *data, u32 length)
/* the data read starts with the descriptor */
desc = (struct wl1271_rx_descriptor *) data;
+ if (desc->packet_class == WL12XX_RX_CLASS_LOGGER) {
+ size_t len = length - sizeof(*desc);
+ wl12xx_copy_fwlog(wl, data + sizeof(*desc), len);
+ wake_up_interruptible(&wl->fwlog_waitq);
+ return 0;
+ }
+
switch (desc->status & WL1271_RX_DESC_STATUS_MASK) {
/* discard corrupted packets */
case WL1271_RX_DESC_DRIVER_RX_Q_FAIL:
@@ -137,6 +146,8 @@ static int wl1271_rx_handle_data(struct wl1271 *wl, u8 *data, u32 length)
hdr = (struct ieee80211_hdr *)skb->data;
if (ieee80211_is_beacon(hdr->frame_control))
beacon = 1;
+ if (ieee80211_is_data_present(hdr->frame_control))
+ is_data = 1;
wl1271_rx_status(wl, desc, IEEE80211_SKB_RXCB(skb), beacon);
@@ -147,9 +158,9 @@ static int wl1271_rx_handle_data(struct wl1271 *wl, u8 *data, u32 length)
skb_trim(skb, skb->len - desc->pad_len);
skb_queue_tail(&wl->deferred_rx_queue, skb);
- ieee80211_queue_work(wl->hw, &wl->netstack_work);
+ queue_work(wl->freezable_wq, &wl->netstack_work);
- return 0;
+ return is_data;
}
void wl1271_rx(struct wl1271 *wl, struct wl1271_fw_common_status *status)
@@ -162,6 +173,8 @@ void wl1271_rx(struct wl1271 *wl, struct wl1271_fw_common_status *status)
u32 mem_block;
u32 pkt_length;
u32 pkt_offset;
+ bool is_ap = (wl->bss_type == BSS_TYPE_AP_BSS);
+ bool had_data = false;
while (drv_rx_counter != fw_rx_counter) {
buf_size = 0;
@@ -214,9 +227,11 @@ void wl1271_rx(struct wl1271 *wl, struct wl1271_fw_common_status *status)
* conditions, in that case the received frame will just
* be dropped.
*/
- wl1271_rx_handle_data(wl,
- wl->aggr_buf + pkt_offset,
- pkt_length);
+ if (wl1271_rx_handle_data(wl,
+ wl->aggr_buf + pkt_offset,
+ pkt_length) == 1)
+ had_data = true;
+
wl->rx_counter++;
drv_rx_counter++;
drv_rx_counter &= NUM_RX_PKT_DESC_MOD_MASK;
@@ -230,6 +245,20 @@ void wl1271_rx(struct wl1271 *wl, struct wl1271_fw_common_status *status)
*/
if (wl->quirks & WL12XX_QUIRK_END_OF_TRANSACTION)
wl1271_write32(wl, RX_DRIVER_COUNTER_ADDRESS, wl->rx_counter);
+
+ if (!is_ap && wl->conf.rx_streaming.interval && had_data &&
+ (wl->conf.rx_streaming.always ||
+ test_bit(WL1271_FLAG_SOFT_GEMINI, &wl->flags))) {
+ u32 timeout = wl->conf.rx_streaming.duration;
+
+ /* restart rx streaming */
+ if (!test_bit(WL1271_FLAG_RX_STREAMING_STARTED, &wl->flags))
+ ieee80211_queue_work(wl->hw,
+ &wl->rx_streaming_enable_work);
+
+ mod_timer(&wl->rx_streaming_timer,
+ jiffies + msecs_to_jiffies(timeout));
+ }
}
void wl1271_set_default_filters(struct wl1271 *wl)