diff options
-rw-r--r-- | drivers/staging/cw1200/queue.c | 8 | ||||
-rw-r--r-- | drivers/staging/cw1200/sta.c | 56 | ||||
-rw-r--r-- | drivers/staging/cw1200/wsm.c | 11 | ||||
-rw-r--r-- | drivers/staging/cw1200/wsm.h | 11 |
4 files changed, 59 insertions, 27 deletions
diff --git a/drivers/staging/cw1200/queue.c b/drivers/staging/cw1200/queue.c index f81e46cd4f4..4140981eed1 100644 --- a/drivers/staging/cw1200/queue.c +++ b/drivers/staging/cw1200/queue.c @@ -319,7 +319,7 @@ int cw1200_queue_requeue(struct cw1200_queue *queue, u32 packetID) item->packetID = cw1200_queue_make_packet_id( queue_generation, queue_id, item_generation, item_id); wsm->packetID = __cpu_to_le32(item->packetID); - list_move_tail(&item->head, &queue->queue); + list_move(&item->head, &queue->queue); } spin_unlock_bh(&queue->lock); return ret; @@ -330,8 +330,8 @@ int cw1200_queue_requeue_all(struct cw1200_queue *queue) struct cw1200_queue_stats *stats = queue->stats; spin_lock_bh(&queue->lock); while (!list_empty(&queue->pending)) { - struct cw1200_queue_item *item = list_first_entry( - &queue->pending, struct cw1200_queue_item, head); + struct cw1200_queue_item *item = list_entry( + queue->pending.prev, struct cw1200_queue_item, head); struct wsm_tx *wsm = (struct wsm_tx *)item->skb->data; --queue->num_pending; @@ -347,7 +347,7 @@ int cw1200_queue_requeue_all(struct cw1200_queue *queue) queue->generation, queue->queue_id, item->generation, item - queue->pool); wsm->packetID = __cpu_to_le32(item->packetID); - list_move_tail(&item->head, &queue->queue); + list_move(&item->head, &queue->queue); } spin_unlock_bh(&queue->lock); diff --git a/drivers/staging/cw1200/sta.c b/drivers/staging/cw1200/sta.c index 9cb801acefb..4923e9dd22f 100644 --- a/drivers/staging/cw1200/sta.c +++ b/drivers/staging/cw1200/sta.c @@ -922,31 +922,45 @@ 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 u8 *frame = (u8 *)&wsm[1]; - const u8 *bssid = &frame[4]; /* AP SSID in a 802.11 frame */ + const struct ieee80211_hdr *frame = (struct ieee80211_hdr *)&wsm[1]; + const u8 *bssid = &frame->addr1[0]; /* AP SSID in a 802.11 frame */ struct cfg80211_bss *bss; - const u8 *ssidie; - const u8 *dtimie; + const u8 *ssidie = NULL; + const u8 *dtimie = NULL; const struct ieee80211_tim_ie *tim = NULL; - u8 queueId = wsm_queue_id_to_linux(wsm->queueId); + u8 queueId; + bool action; + + BUG_ON(!wsm); + BUG_ON(!priv->channel); + + queueId = wsm_queue_id_to_linux(wsm->queueId); + action = ieee80211_is_action(frame->frame_control); + + if (unlikely(priv->join_status == CW1200_JOIN_STATUS_STA)) { + wsm_lock_tx(priv); + cw1200_unjoin_work(&priv->unjoin_work); + } cancel_delayed_work_sync(&priv->join_timeout); bss = cfg80211_get_bss(priv->hw->wiphy, NULL, bssid, NULL, 0, 0, 0); - if (!bss) { + if (!bss && !action) { priv->join_pending_frame = NULL; cw1200_queue_remove(&priv->tx_queue[queueId], priv, __le32_to_cpu(wsm->packetID)); + wsm_unlock_tx(priv); return; + } else if (bss) { + ssidie = cfg80211_find_ie(WLAN_EID_SSID, + bss->information_elements, + bss->len_information_elements); + dtimie = cfg80211_find_ie(WLAN_EID_TIM, + bss->information_elements, + bss->len_information_elements); + if (dtimie) + tim = (struct ieee80211_tim_ie *)&dtimie[2]; } - ssidie = cfg80211_find_ie(WLAN_EID_SSID, - bss->information_elements, - bss->len_information_elements); - dtimie = cfg80211_find_ie(WLAN_EID_TIM, - bss->information_elements, - bss->len_information_elements); - if (dtimie) - tim = (struct ieee80211_tim_ie *)&dtimie[2]; mutex_lock(&priv->conf_mutex); { @@ -969,9 +983,16 @@ void cw1200_join_work(struct work_struct *work) join.dtimPeriod); } + if (action) { + join.probeForJoin = 0; + join.flags |= WSM_JOIN_FLAGS_UNSYNCRONIZED | + WSM_JOIN_FLAGS_FORCE; + } else { + WARN_ON(wsm_set_block_ack_policy(priv, + priv->ba_tid_mask, priv->ba_tid_mask)); + } + priv->join_pending_frame = NULL; - BUG_ON(!wsm); - BUG_ON(!priv->channel); join.channelNumber = priv->channel->hw_value; join.band = (priv->channel->band == IEEE80211_BAND_5GHZ) ? @@ -989,9 +1010,6 @@ void cw1200_join_work(struct work_struct *work) wsm_flush_tx(priv); - WARN_ON(wsm_set_block_ack_policy(priv, - priv->ba_tid_mask, priv->ba_tid_mask)); - /* Queue unjoin if not associated in 3 sec. */ queue_delayed_work(priv->workqueue, &priv->join_timeout, 3 * HZ); diff --git a/drivers/staging/cw1200/wsm.c b/drivers/staging/cw1200/wsm.c index 6f40934ed8f..4db5129394e 100644 --- a/drivers/staging/cw1200/wsm.c +++ b/drivers/staging/cw1200/wsm.c @@ -1260,7 +1260,14 @@ static bool wsm_handle_tx_data(struct cw1200_common *priv, sizeof(priv->join_bssid)))) { if (ieee80211_is_auth(fctl)) action = doJoin; - else + else if (ieee80211_is_probe_req(fctl)) + action = doTx; + else if (ieee80211_is_action(fctl)) { + if (priv->join_status) + action = doTx; + else + action = doJoin; + } else action = doDrop; } break; @@ -1344,8 +1351,6 @@ static bool wsm_handle_tx_data(struct cw1200_common *priv, * in FW: it can't do RX/TX before "join". * "Join" here is not an association, * but just a syncronization between AP and STA. - * BTW that means device can't receive frames - * in monitor mode. * priv->join_status is used only in bh thread and does * not require protection */ wsm_printk(KERN_DEBUG "[WSM] Issue join command.\n"); diff --git a/drivers/staging/cw1200/wsm.h b/drivers/staging/cw1200/wsm.h index 8a861f918ad..55792c4b3c8 100644 --- a/drivers/staging/cw1200/wsm.h +++ b/drivers/staging/cw1200/wsm.h @@ -284,7 +284,16 @@ struct cw1200_common; /* Join flags */ /* Unsynchronized */ -#define WSM_JOIN_FLAGS_UNSYNCRONIZED (1) +#define WSM_JOIN_FLAGS_UNSYNCRONIZED BIT(0) +/* The BSS owner is a P2P GO */ +#define WSM_JOIN_FLAGS_P2P_GO BIT(1) +/* Force to join BSS with the BSSID and the + * SSID specified without waiting for beacons. The + * ProbeForJoin parameter is ignored. */ +#define WSM_JOIN_FLAGS_FORCE BIT(2) +/* Give probe request/response higher + * priority over the BT traffic */ +#define WSM_JOIN_FLAGS_PRIO BIT(3) /* Key types */ #define WSM_KEY_TYPE_WEP_DEFAULT (0) |