diff options
author | Dmitry Tarnyagin <dmitry.tarnyagin@stericsson.com> | 2012-02-29 15:14:40 +0100 |
---|---|---|
committer | Philippe Langlais <philippe.langlais@stericsson.com> | 2012-05-22 11:06:40 +0200 |
commit | d5b4e118d8a74faa340db6d2d0585234778399d9 (patch) | |
tree | 6bac19ee6dfb6cae76ee55058f734c642a4464a8 | |
parent | b55d18dd740545779e0f6d305f498133281854e4 (diff) |
cw1200: Drop frames from locked queue.
The driver locks queues when no TX policies are available. Higher
layer should not send any frames and wait until queue is unlocked again.
It does not work well with injected frames from certification test engine,
leading to BUG_ON in the code.
The patch changes BUG_ON to WARN_ON_ONCE and implements a fallback
(drops the frame) in this case.
ST-Ericsson ID: 355166
Change-Id: Iab8c66d2511afd42bd119c3f776581f0b05dcf51
Signed-off-by: Dmitry Tarnyagin <dmitry.tarnyagin@stericsson.com>
Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/37447
Reviewed-by: Bartosz MARKOWSKI <bartosz.markowski@tieto.com>
Tested-by: Bartosz MARKOWSKI <bartosz.markowski@tieto.com>
-rw-r--r-- | drivers/staging/cw1200/txrx.c | 16 |
1 files changed, 12 insertions, 4 deletions
diff --git a/drivers/staging/cw1200/txrx.c b/drivers/staging/cw1200/txrx.c index 5b5d484e0ce..a754f6a53cd 100644 --- a/drivers/staging/cw1200/txrx.c +++ b/drivers/staging/cw1200/txrx.c @@ -235,7 +235,10 @@ static int tx_policy_get(struct cw1200_common *priv, tx_policy_build(priv, &wanted, rates, count); spin_lock_bh(&cache->lock); - BUG_ON(list_empty(&cache->free)); + if (WARN_ON_ONCE(list_empty(&cache->free))) { + spin_unlock_bh(&cache->lock); + return CW1200_INVALID_RATE_ID; + } idx = tx_policy_find(cache, &wanted); if (idx >= 0) { tx_policy_printk(KERN_DEBUG "[TX policy] Used TX policy: %d\n", @@ -635,7 +638,7 @@ cw1200_tx_h_bt(struct cw1200_common *priv, wsm->flags |= priority << 1; } -static void +static int cw1200_tx_h_rate_policy(struct cw1200_common *priv, struct cw1200_txinfo *t, struct wsm_tx *wsm) @@ -655,7 +658,9 @@ cw1200_tx_h_rate_policy(struct cw1200_common *priv, t->txpriv.rate_id = tx_policy_get(priv, t->tx_info->control.rates, IEEE80211_TX_MAX_RATES, &tx_policy_renew); - wsm->flags = t->txpriv.rate_id << 4; + if (t->txpriv.rate_id == CW1200_INVALID_RATE_ID) + return -EFAULT; + wsm->flags |= t->txpriv.rate_id << 4; if (tx_policy_renew) { tx_policy_printk(KERN_DEBUG "[TX] TX policy renew.\n"); @@ -668,6 +673,7 @@ cw1200_tx_h_rate_policy(struct cw1200_common *priv, cw1200_tx_queues_lock(priv); queue_work(priv->workqueue, &priv->tx_policy_upload_work); } + return 0; } static bool @@ -752,7 +758,9 @@ void cw1200_tx(struct ieee80211_hw *dev, struct sk_buff *skb) } wsm->flags |= flags; cw1200_tx_h_bt(priv, &t, wsm); - cw1200_tx_h_rate_policy(priv, &t, wsm); + ret = cw1200_tx_h_rate_policy(priv, &t, wsm); + if (ret) + goto drop; spin_lock_bh(&priv->ps_state_lock); { |