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 @@ | |||
22 | */ | 22 | */ |
23 | 23 | ||
24 | #include <linux/gfp.h> | 24 | #include <linux/gfp.h> |
25 | #include <linux/sched.h> | ||
25 | 26 | ||
26 | #include "wl12xx.h" | 27 | #include "wl12xx.h" |
27 | #include "acx.h" | 28 | #include "acx.h" |
@@ -95,6 +96,7 @@ static int wl1271_rx_handle_data(struct wl1271 *wl, u8 *data, u32 length) | |||
95 | struct ieee80211_hdr *hdr; | 96 | struct ieee80211_hdr *hdr; |
96 | u8 *buf; | 97 | u8 *buf; |
97 | u8 beacon = 0; | 98 | u8 beacon = 0; |
99 | u8 is_data = 0; | ||
98 | 100 | ||
99 | /* | 101 | /* |
100 | * In PLT mode we seem to get frames and mac80211 warns about them, | 102 | * 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) | |||
106 | /* the data read starts with the descriptor */ | 108 | /* the data read starts with the descriptor */ |
107 | desc = (struct wl1271_rx_descriptor *) data; | 109 | desc = (struct wl1271_rx_descriptor *) data; |
108 | 110 | ||
111 | if (desc->packet_class == WL12XX_RX_CLASS_LOGGER) { | ||
112 | size_t len = length - sizeof(*desc); | ||
113 | wl12xx_copy_fwlog(wl, data + sizeof(*desc), len); | ||
114 | wake_up_interruptible(&wl->fwlog_waitq); | ||
115 | return 0; | ||
116 | } | ||
117 | |||
109 | switch (desc->status & WL1271_RX_DESC_STATUS_MASK) { | 118 | switch (desc->status & WL1271_RX_DESC_STATUS_MASK) { |
110 | /* discard corrupted packets */ | 119 | /* discard corrupted packets */ |
111 | case WL1271_RX_DESC_DRIVER_RX_Q_FAIL: | 120 | 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) | |||
137 | hdr = (struct ieee80211_hdr *)skb->data; | 146 | hdr = (struct ieee80211_hdr *)skb->data; |
138 | if (ieee80211_is_beacon(hdr->frame_control)) | 147 | if (ieee80211_is_beacon(hdr->frame_control)) |
139 | beacon = 1; | 148 | beacon = 1; |
149 | if (ieee80211_is_data_present(hdr->frame_control)) | ||
150 | is_data = 1; | ||
140 | 151 | ||
141 | wl1271_rx_status(wl, desc, IEEE80211_SKB_RXCB(skb), beacon); | 152 | wl1271_rx_status(wl, desc, IEEE80211_SKB_RXCB(skb), beacon); |
142 | 153 | ||
@@ -147,9 +158,9 @@ static int wl1271_rx_handle_data(struct wl1271 *wl, u8 *data, u32 length) | |||
147 | skb_trim(skb, skb->len - desc->pad_len); | 158 | skb_trim(skb, skb->len - desc->pad_len); |
148 | 159 | ||
149 | skb_queue_tail(&wl->deferred_rx_queue, skb); | 160 | skb_queue_tail(&wl->deferred_rx_queue, skb); |
150 | ieee80211_queue_work(wl->hw, &wl->netstack_work); | 161 | queue_work(wl->freezable_wq, &wl->netstack_work); |
151 | 162 | ||
152 | return 0; | 163 | return is_data; |
153 | } | 164 | } |
154 | 165 | ||
155 | void wl1271_rx(struct wl1271 *wl, struct wl1271_fw_common_status *status) | 166 | 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) | |||
162 | u32 mem_block; | 173 | u32 mem_block; |
163 | u32 pkt_length; | 174 | u32 pkt_length; |
164 | u32 pkt_offset; | 175 | u32 pkt_offset; |
176 | bool is_ap = (wl->bss_type == BSS_TYPE_AP_BSS); | ||
177 | bool had_data = false; | ||
165 | 178 | ||
166 | while (drv_rx_counter != fw_rx_counter) { | 179 | while (drv_rx_counter != fw_rx_counter) { |
167 | buf_size = 0; | 180 | buf_size = 0; |
@@ -214,9 +227,11 @@ void wl1271_rx(struct wl1271 *wl, struct wl1271_fw_common_status *status) | |||
214 | * conditions, in that case the received frame will just | 227 | * conditions, in that case the received frame will just |
215 | * be dropped. | 228 | * be dropped. |
216 | */ | 229 | */ |
217 | wl1271_rx_handle_data(wl, | 230 | if (wl1271_rx_handle_data(wl, |
218 | wl->aggr_buf + pkt_offset, | 231 | wl->aggr_buf + pkt_offset, |
219 | pkt_length); | 232 | pkt_length) == 1) |
233 | had_data = true; | ||
234 | |||
220 | wl->rx_counter++; | 235 | wl->rx_counter++; |
221 | drv_rx_counter++; | 236 | drv_rx_counter++; |
222 | drv_rx_counter &= NUM_RX_PKT_DESC_MOD_MASK; | 237 | 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) | |||
230 | */ | 245 | */ |
231 | if (wl->quirks & WL12XX_QUIRK_END_OF_TRANSACTION) | 246 | if (wl->quirks & WL12XX_QUIRK_END_OF_TRANSACTION) |
232 | wl1271_write32(wl, RX_DRIVER_COUNTER_ADDRESS, wl->rx_counter); | 247 | wl1271_write32(wl, RX_DRIVER_COUNTER_ADDRESS, wl->rx_counter); |
248 | |||
249 | if (!is_ap && wl->conf.rx_streaming.interval && had_data && | ||
250 | (wl->conf.rx_streaming.always || | ||
251 | test_bit(WL1271_FLAG_SOFT_GEMINI, &wl->flags))) { | ||
252 | u32 timeout = wl->conf.rx_streaming.duration; | ||
253 | |||
254 | /* restart rx streaming */ | ||
255 | if (!test_bit(WL1271_FLAG_RX_STREAMING_STARTED, &wl->flags)) | ||
256 | ieee80211_queue_work(wl->hw, | ||
257 | &wl->rx_streaming_enable_work); | ||
258 | |||
259 | mod_timer(&wl->rx_streaming_timer, | ||
260 | jiffies + msecs_to_jiffies(timeout)); | ||
261 | } | ||
233 | } | 262 | } |
234 | 263 | ||
235 | void wl1271_set_default_filters(struct wl1271 *wl) | 264 | void wl1271_set_default_filters(struct wl1271 *wl) |