diff options
Diffstat (limited to 'drivers/net/wireless/wl12xx/rx.c')
| -rw-r--r-- | drivers/net/wireless/wl12xx/rx.c | 39 | 
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)  |