From 77ddaa108f727b5ef3be004b952d2c3d3ffc48e5 Mon Sep 17 00:00:00 2001 From: Eliad Peller Date: Sun, 15 May 2011 11:10:29 +0300 Subject: 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 Signed-off-by: Luciano Coelho --- drivers/net/wireless/wl12xx/rx.c | 29 +++++++++++++++++++++++++---- 1 file changed, 25 insertions(+), 4 deletions(-) (limited to 'drivers/net/wireless/wl12xx/rx.c') 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) 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, @@ -137,6 +138,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); @@ -149,7 +152,7 @@ static int wl1271_rx_handle_data(struct wl1271 *wl, u8 *data, u32 length) skb_queue_tail(&wl->deferred_rx_queue, skb); ieee80211_queue_work(wl->hw, &wl->netstack_work); - return 0; + return is_data; } void 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) 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 +219,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 +237,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) -- cgit v1.2.3 From 92ef8960aee2f840c6a54c968d40199843f015c0 Mon Sep 17 00:00:00 2001 From: Eliad Peller Date: Tue, 7 Jun 2011 12:50:46 +0300 Subject: wl12xx: use freezable workqueue for netstack_work When resuming (after wowlan), we want the rx packets (which is usually the wake-up packet itself) to be passed to mac80211 only after the resume notifier was completed, and mac80211 is up and running (otherwise, the packets will be dropped). By enqueueing the netstack_work to a freezable workqueue, we can guarantee the rx processing to occur only after mac80211 was resumed. Signed-off-by: Eliad Peller Signed-off-by: Ido Yariv Signed-off-by: Luciano Coelho --- drivers/net/wireless/wl12xx/rx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net/wireless/wl12xx/rx.c') diff --git a/drivers/net/wireless/wl12xx/rx.c b/drivers/net/wireless/wl12xx/rx.c index db230a503bf7..9357695340cf 100644 --- a/drivers/net/wireless/wl12xx/rx.c +++ b/drivers/net/wireless/wl12xx/rx.c @@ -150,7 +150,7 @@ 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 is_data; } -- cgit v1.2.3 From 95dac04f881322b510c45e5ae83f0dbee4f823a2 Mon Sep 17 00:00:00 2001 From: Ido Yariv Date: Mon, 6 Jun 2011 14:57:06 +0300 Subject: wl12xx: Support routing FW logs to the host A recently added feature to the firmware enables the driver to retrieve firmware logs via the host bus (SDIO or SPI). There are two modes of operation: 1. On-demand: The FW collects its log in an internal ring buffer. This buffer can later be read, for example, upon recovery. 2. Continuous: The FW pushes the FW logs as special packets in the RX path. Reading the internal ring buffer does not involve the FW. Thus, as long as the HW is not in ELP, it should be possible to read the logs, even if the FW crashes. A sysfs binary file named "fwlog" was added to support this feature, letting a monitor process read the FW messages. The log is transferred from the FW only when available, so the reading process might block. Signed-off-by: Ido Yariv Signed-off-by: Luciano Coelho --- drivers/net/wireless/wl12xx/rx.c | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'drivers/net/wireless/wl12xx/rx.c') diff --git a/drivers/net/wireless/wl12xx/rx.c b/drivers/net/wireless/wl12xx/rx.c index 9357695340cf..0450fb49dbb1 100644 --- a/drivers/net/wireless/wl12xx/rx.c +++ b/drivers/net/wireless/wl12xx/rx.c @@ -22,6 +22,7 @@ */ #include +#include #include "wl12xx.h" #include "acx.h" @@ -107,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: -- cgit v1.2.3