summaryrefslogtreecommitdiff
path: root/drivers/staging/cw1200/sta.c
diff options
context:
space:
mode:
authorDmitry Tarnyagin <dmitry.tarnyagin@stericsson.com>2011-10-10 23:20:13 +0200
committerPhilippe LANGLAIS <philippe.langlais@stericsson.com>2011-10-13 10:25:09 +0200
commit7a2de54ab4a67e97bc1a4fac9b84eb6c307f9488 (patch)
tree1001141bce26ea659b625841c687823b9d53a1a7 /drivers/staging/cw1200/sta.c
parent98a9d7c86ef2ff6df10008dbb93a8139a79a9f33 (diff)
cw1200: Requeue special frames.
Some frames require special handling in wsm, for example offchannel, wep, join... Requeue for offchannel and wep frames was missing, leading to queue entry leakage and unexpected drop of frames. Fix implements requeue for special frames. Change-Id: Iba5c41496f898e30b4261db3888bba384504df50 Signed-off-by: Dmitry Tarnyagin <dmitry.tarnyagin@stericsson.com> Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/33596 Reviewed-by: Bartosz MARKOWSKI <bartosz.markowski@tieto.com> Reviewed-by: Philippe LANGLAIS <philippe.langlais@stericsson.com>
Diffstat (limited to 'drivers/staging/cw1200/sta.c')
-rw-r--r--drivers/staging/cw1200/sta.c47
1 files changed, 33 insertions, 14 deletions
diff --git a/drivers/staging/cw1200/sta.c b/drivers/staging/cw1200/sta.c
index 2ddbc1aa2b0..908294c8a93 100644
--- a/drivers/staging/cw1200/sta.c
+++ b/drivers/staging/cw1200/sta.c
@@ -725,14 +725,19 @@ void cw1200_wep_key_work(struct work_struct *work)
{
struct cw1200_common *priv =
container_of(work, struct cw1200_common, wep_key_work);
+ u8 queueId = cw1200_queue_get_queue_id(priv->pending_frame_id);
+ struct cw1200_queue *queue = &priv->tx_queue[queueId];
__le32 wep_default_key_id = __cpu_to_le32(
priv->wep_default_key_id);
+ BUG_ON(queueId >= 4);
+
sta_printk(KERN_DEBUG "[STA] Setting default WEP key: %d\n",
priv->wep_default_key_id);
wsm_flush_tx(priv);
WARN_ON(wsm_write_mib(priv, WSM_MIB_ID_DOT11_WEP_DEFAULT_KEY_ID,
&wep_default_key_id, sizeof(wep_default_key_id)));
+ cw1200_queue_requeue(queue, priv->pending_frame_id);
wsm_unlock_tx(priv);
}
@@ -1096,15 +1101,22 @@ void cw1200_offchannel_work(struct work_struct *work)
{
struct cw1200_common *priv =
container_of(work, struct cw1200_common, offchannel_work);
+ u8 queueId = cw1200_queue_get_queue_id(priv->pending_frame_id);
+ struct cw1200_queue *queue = &priv->tx_queue[queueId];
+ BUG_ON(queueId >= 4);
BUG_ON(!priv->channel);
mutex_lock(&priv->conf_mutex);
- if (!priv->join_status) {
+ if (likely(!priv->join_status)) {
wsm_flush_tx(priv);
cw1200_update_listening(priv, true);
cw1200_update_filtering(priv);
}
+ if (unlikely(!priv->join_status))
+ cw1200_queue_remove(queue, priv->pending_frame_id);
+ else
+ cw1200_queue_requeue(queue, priv->pending_frame_id);
mutex_unlock(&priv->conf_mutex);
wsm_unlock_tx(priv);
}
@@ -1113,20 +1125,31 @@ void cw1200_join_work(struct work_struct *work)
{
struct cw1200_common *priv =
container_of(work, struct cw1200_common, join_work);
- const struct wsm_tx *wsm = priv->join_pending_frame;
- const struct ieee80211_hdr *frame = (struct ieee80211_hdr *)&wsm[1];
- const u8 *bssid = &frame->addr1[0]; /* AP SSID in a 802.11 frame */
+ u8 queueId = cw1200_queue_get_queue_id(priv->pending_frame_id);
+ struct cw1200_queue *queue = &priv->tx_queue[queueId];
+ const struct cw1200_txpriv *txpriv = NULL;
+ struct sk_buff *skb = NULL;
+ const struct wsm_tx *wsm;
+ const struct ieee80211_hdr *frame;
+ const u8 *bssid;
struct cfg80211_bss *bss;
const u8 *ssidie;
const u8 *dtimie;
const struct ieee80211_tim_ie *tim = NULL;
- u8 queueId;
+
+ BUG_ON(queueId >= 4);
+ if (cw1200_queue_get_skb(queue, priv->pending_frame_id,
+ &skb, &txpriv)) {
+ wsm_unlock_tx(priv);
+ return;
+ }
+ wsm = (struct wsm_tx *)&skb->data[0];
+ frame = (struct ieee80211_hdr *)&skb->data[txpriv->offset];
+ bssid = &frame->addr1[0]; /* AP SSID in a 802.11 frame */
BUG_ON(!wsm);
BUG_ON(!priv->channel);
- queueId = wsm_queue_id_to_linux(wsm->queueId);
-
if (unlikely(priv->join_status)) {
wsm_lock_tx(priv);
cw1200_unjoin_work(&priv->unjoin_work);
@@ -1134,12 +1157,10 @@ void cw1200_join_work(struct work_struct *work)
cancel_delayed_work_sync(&priv->join_timeout);
- priv->join_pending_frame = NULL;
bss = cfg80211_get_bss(priv->hw->wiphy, priv->channel,
bssid, NULL, 0, 0, 0);
if (!bss) {
- cw1200_queue_remove(&priv->tx_queue[queueId],
- __le32_to_cpu(wsm->packetID));
+ cw1200_queue_remove(queue, priv->pending_frame_id);
wsm_unlock_tx(priv);
return;
}
@@ -1213,16 +1234,14 @@ void cw1200_join_work(struct work_struct *work)
if (wsm_join(priv, &join)) {
memset(&priv->join_bssid[0],
0, sizeof(priv->join_bssid));
- cw1200_queue_remove(&priv->tx_queue[queueId],
- __le32_to_cpu(wsm->packetID));
+ cw1200_queue_remove(queue, priv->pending_frame_id);
cancel_delayed_work_sync(&priv->join_timeout);
cw1200_update_listening(priv, priv->listening);
} else {
/* Upload keys */
WARN_ON(cw1200_upload_keys(priv));
WARN_ON(wsm_keep_alive_period(priv, 30 /* sec */));
- cw1200_queue_requeue(&priv->tx_queue[queueId],
- __le32_to_cpu(wsm->packetID));
+ cw1200_queue_requeue(queue, priv->pending_frame_id);
priv->join_status = CW1200_JOIN_STATUS_STA;
}
WARN_ON(wsm_set_block_ack_policy(priv,