diff options
author | Dmitry Tarnyagin <dmitry.tarnyagin@stericsson.com> | 2011-06-07 09:12:07 +0200 |
---|---|---|
committer | Philippe Langlais <philippe.langlais@stericsson.com> | 2012-05-22 11:06:19 +0200 |
commit | 8baff0cf82469a4ebfabc775b56772dcd0b6fdfc (patch) | |
tree | 57fb798f0166d5f77ff5bad61be8f83c1c4a5368 /drivers | |
parent | f21ed94daa73a203b5c537c18cf8d0ecfd320f5c (diff) |
cw1200: throughput optimization and fine-tuning.
* Fixed: Do not allocate a dedicated communication channel (buffer) for WSM command stream,
use it for data traffic when needed.
* Additional statistics added to DebugFS: counters for TX policy cache misses and unaligned
skbs memmove.
* Fixed: Strip IV/ICV in the driver to prevent mac80211 layer from double-verification.
Change-Id: I600664466d577df4c2bc62ff49fb22f2d3b024cc
Signed-off-by: Dmitry Tarnyagin <dmitry.tarnyagin@stericsson.com>
Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/24482
Reviewed-by: Robert MARKLUND <robert.marklund@stericsson.com>
Tested-by: Robert MARKLUND <robert.marklund@stericsson.com>
Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/25622
Reviewed-by: Philippe LANGLAIS <philippe.langlais@stericsson.com>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/staging/cw1200/bh.c | 6 | ||||
-rw-r--r-- | drivers/staging/cw1200/debug.c | 5 | ||||
-rw-r--r-- | drivers/staging/cw1200/debug.h | 20 | ||||
-rw-r--r-- | drivers/staging/cw1200/txrx.c | 62 |
4 files changed, 78 insertions, 15 deletions
diff --git a/drivers/staging/cw1200/bh.c b/drivers/staging/cw1200/bh.c index 177274a00d2..d49f9fdf732 100644 --- a/drivers/staging/cw1200/bh.c +++ b/drivers/staging/cw1200/bh.c @@ -120,7 +120,7 @@ int wsm_release_tx_buffer(struct cw1200_common *priv, int count) priv->hw_bufs_used -= count; if (WARN_ON(priv->hw_bufs_used < 0)) ret = -1; - else if (hw_bufs_used >= priv->wsm_caps.numInpChBufs - 1) + else if (hw_bufs_used >= priv->wsm_caps.numInpChBufs) ret = 1; if (!priv->hw_bufs_used) wake_up_interruptible(&priv->hw_bufs_used_wq); @@ -363,9 +363,7 @@ tx: /* HACK! One buffer is reserved for control path */ BUG_ON(priv->hw_bufs_used > priv->wsm_caps.numInpChBufs); tx_allowed = - priv->hw_bufs_used + 1 < priv->wsm_caps.numInpChBufs; - if (unlikely(!tx_allowed && priv->wsm_cmd.ptr)) - tx_allowed = 1; + priv->hw_bufs_used < priv->wsm_caps.numInpChBufs; if (tx && tx_allowed) { size_t tx_len; diff --git a/drivers/staging/cw1200/debug.c b/drivers/staging/cw1200/debug.c index b4c2da23135..13c4570372f 100644 --- a/drivers/staging/cw1200/debug.c +++ b/drivers/staging/cw1200/debug.c @@ -253,7 +253,10 @@ static int cw1200_status_show(struct seq_file *seq, void *v) d->rx); seq_printf(seq, "AGG RXed: %d\n", d->rx_agg); - + seq_printf(seq, "TX miss: %d\n", + d->tx_cache_miss); + seq_printf(seq, "TX copy: %d\n", + d->tx_copy); seq_printf(seq, "Scan: %s\n", atomic_read(&priv->scan.in_progress) ? "active" : "idle"); seq_printf(seq, "Led state: 0x%.2X\n", diff --git a/drivers/staging/cw1200/debug.h b/drivers/staging/cw1200/debug.h index a19083a49b9..e7fc4d2daef 100644 --- a/drivers/staging/cw1200/debug.h +++ b/drivers/staging/cw1200/debug.h @@ -13,6 +13,8 @@ struct cw1200_debug_priv { int rx_agg; int tx_multi; int tx_multi_frames; + int tx_cache_miss; + int tx_copy; }; int cw1200_debug_init(struct cw1200_common *priv); @@ -45,6 +47,16 @@ static inline void cw1200_debug_rxed_agg(struct cw1200_common *priv) ++priv->debug->rx_agg; } +static inline void cw1200_debug_tx_cache_miss(struct cw1200_common *priv) +{ + ++priv->debug->tx_cache_miss; +} + +static inline void cw1200_debug_tx_copy(struct cw1200_common *priv) +{ + ++priv->debug->tx_copy; +} + #else /* CONFIG_CW1200_DEBUGFS */ static inline int cw1200_debug_init(struct cw1200_common *priv) @@ -77,6 +89,14 @@ static inline void cw1200_debug_rxed_agg(struct cw1200_common *priv) { } +static inline void cw1200_debug_tx_cache_miss(struct cw1200_common *priv) +{ +} + +static inline void cw1200_debug_tx_copy(struct cw1200_common *priv) +{ +} + #endif /* CONFIG_CW1200_DEBUGFS */ #endif /* CW1200_DEBUG_H_INCLUDED */ diff --git a/drivers/staging/cw1200/txrx.c b/drivers/staging/cw1200/txrx.c index eb2802af318..8616d1d2ffe 100644 --- a/drivers/staging/cw1200/txrx.c +++ b/drivers/staging/cw1200/txrx.c @@ -323,6 +323,7 @@ static int tx_policy_upload(struct cw1200_common *priv) } } spin_unlock_bh(&cache->lock); + cw1200_debug_tx_cache_miss(priv); tx_policy_printk(KERN_DEBUG "[TX policy] Upload %d policies\n", arg.hdr.numTxRatePolicies); return wsm_set_tx_rate_retry_policy(priv, &arg); @@ -501,6 +502,7 @@ int cw1200_tx(struct ieee80211_hw *dev, struct sk_buff *skb) p = skb_push(skb, offset); memmove(p, &p[offset], skb->len - offset); skb_trim(skb, skb->len - offset); + cw1200_debug_tx_copy(priv); } if (ieee80211_is_action(hdr->frame_control)) @@ -647,7 +649,7 @@ void cw1200_rx_cb(struct cw1200_common *priv, if (unlikely(priv->mode == NL80211_IFTYPE_UNSPECIFIED)) { /* STA is stopped. */ - return; + goto drop; } if (unlikely(arg->status)) { @@ -656,17 +658,18 @@ void cw1200_rx_cb(struct cw1200_common *priv, hdr->flag |= RX_FLAG_MMIC_ERROR; } else if (arg->status == WSM_STATUS_NO_KEY_FOUND) { txrx_printk(KERN_DEBUG "[RX] No key found.\n"); - return; + goto drop; } else { txrx_printk(KERN_DEBUG "[RX] Receive failure: %d.\n", arg->status); - return; + goto drop; } } if (skb->len < sizeof(struct ieee80211_hdr_3addr)) { - wiphy_warn(priv->hw->wiphy, "Mailformed SDU rx'ed.\n"); - return; + wiphy_warn(priv->hw->wiphy, "Mailformed SDU rx'ed. " + "Size is lesser than IEEE header.\n"); + goto drop; } frame_control = *(__le16*)skb->data; @@ -691,13 +694,47 @@ void cw1200_rx_cb(struct cw1200_common *priv, hdr->antenna = 0; if (WSM_RX_STATUS_ENCRYPTION(arg->flags)) { - hdr->flag |= RX_FLAG_DECRYPTED; - if (!arg->status && - (WSM_RX_STATUS_ENCRYPTION(arg->flags) == - WSM_RX_STATUS_TKIP)) { + size_t iv_len = 0, icv_len = 0; + size_t hdrlen = ieee80211_hdrlen(frame_control); + + hdr->flag |= RX_FLAG_DECRYPTED | RX_FLAG_IV_STRIPPED; + + /* Oops... There is no fast way to ask mac80211 about + * IV/ICV lengths. Even defineas are not exposed.*/ + switch (WSM_RX_STATUS_ENCRYPTION(arg->flags)) { + case WSM_RX_STATUS_WEP: + iv_len = 4 /* WEP_IV_LEN */; + icv_len = 4 /* WEP_ICV_LEN */; + break; + case WSM_RX_STATUS_TKIP: + iv_len = 8 /* TKIP_IV_LEN */; + icv_len = 4 /* TKIP_ICV_LEN */ + + 8 /*MICHAEL_MIC_LEN*/; hdr->flag |= RX_FLAG_MMIC_STRIPPED; - skb_trim(skb, skb->len - 8 /*MICHAEL_MIC_LEN*/); + break; + case WSM_RX_STATUS_AES: + iv_len = 8 /* CCMP_HDR_LEN */; + icv_len = 8 /* CCMP_MIC_LEN */; + break; + case WSM_RX_STATUS_WAPI: + iv_len = 18 /* WAPI_HDR_LEN */; + icv_len = 16 /* WAPI_MIC_LEN */; + break; + default: + WARN_ON("Unknown encryption type"); + goto drop; } + + if (skb->len < hdrlen + iv_len + icv_len) { + wiphy_warn(priv->hw->wiphy, "Mailformed SDU rx'ed. " + "Size is lesser than crypto headers.\n"); + goto drop; + } + + /* Remove IV, ICV and MIC */ + skb_trim(skb, skb->len - icv_len); + memmove(skb->data + iv_len, skb->data, hdrlen); + skb_pull(skb, iv_len); } cw1200_debug_rxed(priv); @@ -714,6 +751,11 @@ void cw1200_rx_cb(struct cw1200_common *priv, * system performance. */ ieee80211_rx_irqsafe(priv->hw, skb); *skb_p = NULL; + return; + +drop: + /* TODO: update failure counters */ + return; } /* ******************************************************************** */ |