2011-04-26 20:35:47

by Arik Nemtsov

[permalink] [raw]
Subject: [PATCH 1/2] wl12xx: implement the tx_frames_pending mac80211 callback

Frames are considered pending when they reside in the driver TX queue or
already queued in the FW.

This notion of "pending" is appropriate for power save considerations in
STA mode, but not necessarily in other modes (for instance P2P-GO).

Signed-off-by: Arik Nemtsov <[email protected]>
---
drivers/net/wireless/wl12xx/main.c | 23 +++++++++++++++++++++++
1 files changed, 23 insertions(+), 0 deletions(-)

diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c
index dad81f6..3dc89f7 100644
--- a/drivers/net/wireless/wl12xx/main.c
+++ b/drivers/net/wireless/wl12xx/main.c
@@ -3140,6 +3140,28 @@ out:
return ret;
}

+bool wl1271_tx_frames_pending(struct ieee80211_hw *hw)
+{
+ struct wl1271 *wl = hw->priv;
+ bool ret = false;
+
+ mutex_lock(&wl->mutex);
+
+ if (unlikely(wl->state == WL1271_STATE_OFF))
+ goto out;
+
+ /* packets are considered pending if in the TX queue or the FW */
+ ret = (wl->tx_queue_count > 0) || (wl->tx_frames_cnt > 0);
+
+ /* the above is appropriate for STA mode for PS purposes */
+ WARN_ON(wl->bss_type != BSS_TYPE_STA_BSS);
+
+out:
+ mutex_unlock(&wl->mutex);
+
+ return ret;
+}
+
/* can't be const, mac80211 writes to this */
static struct ieee80211_rate wl1271_rates[] = {
{ .bitrate = 10,
@@ -3391,6 +3413,7 @@ static const struct ieee80211_ops wl1271_ops = {
.sta_add = wl1271_op_sta_add,
.sta_remove = wl1271_op_sta_remove,
.ampdu_action = wl1271_op_ampdu_action,
+ .tx_frames_pending = wl1271_tx_frames_pending,
CFG80211_TESTMODE_CMD(wl1271_tm_cmd)
};

--
1.7.1



2011-04-26 20:35:50

by Arik Nemtsov

[permalink] [raw]
Subject: [PATCH 2/2] wl12xx: discard corrupted packets in RX

When packets arrive with a RX descriptor indicating corruption, discard
them.

In general white-list the RX descriptor status to prevent rouge data
from being sent up.

Signed-off-by: Arik Nemtsov <[email protected]>
---
drivers/net/wireless/wl12xx/rx.c | 33 ++++++++++++++++++++++++++-------
1 files changed, 26 insertions(+), 7 deletions(-)

diff --git a/drivers/net/wireless/wl12xx/rx.c b/drivers/net/wireless/wl12xx/rx.c
index faf5a1d..7009103 100644
--- a/drivers/net/wireless/wl12xx/rx.c
+++ b/drivers/net/wireless/wl12xx/rx.c
@@ -76,12 +76,15 @@ static void wl1271_rx_status(struct wl1271 *wl,
status->band);

if (desc->flags & WL1271_RX_DESC_ENCRYPT_MASK) {
- status->flag |= RX_FLAG_IV_STRIPPED | RX_FLAG_MMIC_STRIPPED;
+ u8 desc_err_code = desc->status & WL1271_RX_DESC_STATUS_MASK;

- if (likely(!(desc->status & WL1271_RX_DESC_DECRYPT_FAIL)))
- status->flag |= RX_FLAG_DECRYPTED;
- if (unlikely(desc->status & WL1271_RX_DESC_MIC_FAIL))
+ status->flag |= RX_FLAG_IV_STRIPPED | RX_FLAG_MMIC_STRIPPED |
+ RX_FLAG_DECRYPTED;
+
+ if (unlikely(desc_err_code == WL1271_RX_DESC_MIC_FAIL)) {
status->flag |= RX_FLAG_MMIC_ERROR;
+ wl1271_warning("Michael MIC error");
+ }
}
}

@@ -100,6 +103,25 @@ static int wl1271_rx_handle_data(struct wl1271 *wl, u8 *data, u32 length)
if (unlikely(wl->state == WL1271_STATE_PLT))
return -EINVAL;

+ /* the data read starts with the descriptor */
+ desc = (struct wl1271_rx_descriptor *) data;
+
+ switch (desc->status & WL1271_RX_DESC_STATUS_MASK) {
+ /* discard corrupted packets */
+ case WL1271_RX_DESC_DRIVER_RX_Q_FAIL:
+ case WL1271_RX_DESC_DECRYPT_FAIL:
+ wl1271_warning("corrupted packet in RX with status: 0x%x",
+ desc->status & WL1271_RX_DESC_STATUS_MASK);
+ return -EINVAL;
+ case WL1271_RX_DESC_SUCCESS:
+ case WL1271_RX_DESC_MIC_FAIL:
+ break;
+ default:
+ wl1271_error("invalid RX descriptor status: 0x%x",
+ desc->status & WL1271_RX_DESC_STATUS_MASK);
+ return -EINVAL;
+ }
+
skb = __dev_alloc_skb(length, GFP_KERNEL);
if (!skb) {
wl1271_error("Couldn't allocate RX frame");
@@ -109,9 +131,6 @@ static int wl1271_rx_handle_data(struct wl1271 *wl, u8 *data, u32 length)
buf = skb_put(skb, length);
memcpy(buf, data, length);

- /* the data read starts with the descriptor */
- desc = (struct wl1271_rx_descriptor *) buf;
-
/* now we pull the descriptor out of the buffer */
skb_pull(skb, sizeof(*desc));

--
1.7.1


2011-04-29 20:08:33

by Luciano Coelho

[permalink] [raw]
Subject: Re: [PATCH 1/2] wl12xx: implement the tx_frames_pending mac80211 callback

On Tue, 2011-04-26 at 23:35 +0300, Arik Nemtsov wrote:
> Frames are considered pending when they reside in the driver TX queue or
> already queued in the FW.
>
> This notion of "pending" is appropriate for power save considerations in
> STA mode, but not necessarily in other modes (for instance P2P-GO).
>
> Signed-off-by: Arik Nemtsov <[email protected]>
> ---

Applied, thanks!


> diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c
> index dad81f6..3dc89f7 100644
> --- a/drivers/net/wireless/wl12xx/main.c
> +++ b/drivers/net/wireless/wl12xx/main.c
> @@ -3140,6 +3140,28 @@ out:
> return ret;
> }
>
> +bool wl1271_tx_frames_pending(struct ieee80211_hw *hw)

Added static here to avoid a sparse warning complaining that this
function is not exported but it was also not declared static.

--
Cheers,
Luca.


2011-04-29 20:08:57

by Luciano Coelho

[permalink] [raw]
Subject: Re: [PATCH 2/2] wl12xx: discard corrupted packets in RX

On Tue, 2011-04-26 at 23:35 +0300, Arik Nemtsov wrote:
> When packets arrive with a RX descriptor indicating corruption, discard
> them.
>
> In general white-list the RX descriptor status to prevent rouge data
> from being sent up.
>
> Signed-off-by: Arik Nemtsov <[email protected]>
> ---

Applied, thanks!

--
Cheers,
Luca.