Skip to content

Commit

Permalink
wl12xx: 1281/1283 support - Add dummy packet support
Browse files Browse the repository at this point in the history
Support sending dummy packet to wl128x FW as results of
dummy packet event. That is part of dynamic TX mem blocks mechanism.

Only send dummy packet when not in AP mode.

[Even though the DUMMY_PACKET_EVENT_ID and the
STA_REMOVE_COMPLETE_EVENT_ID events are defined to the same value, we
need to treat them separately in the code.  Keep the check and enable
STA_REMOVE_COMPLETE_EVENT_ID for AP mode and DUMMY_PACKET_EVENT_ID for
STA.  Moved one warning to a cleaner place.  Use WL1271_TID_MGMT for
dummy packets -- Luca]

Signed-off-by: Shahar Levi <shahar_levi@ti.com>
Reviewed-by: Luciano Coelho <coelho@ti.com>
Signed-off-by: Luciano Coelho <coelho@ti.com>
  • Loading branch information
Shahar Levi authored and Luciano Coelho committed Apr 19, 2011
1 parent ae77ecc commit ae47c45
Show file tree
Hide file tree
Showing 7 changed files with 116 additions and 21 deletions.
2 changes: 2 additions & 0 deletions drivers/net/wireless/wl12xx/boot.c
Original file line number Diff line number Diff line change
Expand Up @@ -482,6 +482,8 @@ static int wl1271_boot_run_firmware(struct wl1271 *wl)

if (wl->bss_type == BSS_TYPE_AP_BSS)
wl->event_mask |= STA_REMOVE_COMPLETE_EVENT_ID;
else
wl->event_mask |= DUMMY_PACKET_EVENT_ID;

ret = wl1271_event_unmask(wl);
if (ret < 0) {
Expand Down
6 changes: 6 additions & 0 deletions drivers/net/wireless/wl12xx/event.c
Original file line number Diff line number Diff line change
Expand Up @@ -228,6 +228,12 @@ static int wl1271_event_process(struct wl1271 *wl, struct event_mailbox *mbox)
wl1271_event_rssi_trigger(wl, mbox);
}

if ((vector & DUMMY_PACKET_EVENT_ID) && !is_ap) {
wl1271_debug(DEBUG_EVENT, "DUMMY_PACKET_ID_EVENT_ID");
if (wl->vif)
wl1271_tx_dummy_packet(wl);
}

if (wl->vif && beacon_loss)
ieee80211_connection_loss(wl->vif);

Expand Down
5 changes: 4 additions & 1 deletion drivers/net/wireless/wl12xx/event.h
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,10 @@ enum {
BSS_LOSE_EVENT_ID = BIT(18),
REGAINED_BSS_EVENT_ID = BIT(19),
ROAMING_TRIGGER_MAX_TX_RETRY_EVENT_ID = BIT(20),
STA_REMOVE_COMPLETE_EVENT_ID = BIT(21), /* AP */
/* STA: dummy paket for dynamic mem blocks */
DUMMY_PACKET_EVENT_ID = BIT(21),
/* AP: STA remove complete */
STA_REMOVE_COMPLETE_EVENT_ID = BIT(21),
SOFT_GEMINI_SENSE_EVENT_ID = BIT(22),
SOFT_GEMINI_PREDICTION_EVENT_ID = BIT(23),
SOFT_GEMINI_AVALANCHE_EVENT_ID = BIT(24),
Expand Down
1 change: 1 addition & 0 deletions drivers/net/wireless/wl12xx/io.h
Original file line number Diff line number Diff line change
Expand Up @@ -170,5 +170,6 @@ struct ieee80211_hw *wl1271_alloc_hw(void);
int wl1271_free_hw(struct wl1271 *wl);
irqreturn_t wl1271_irq(int irq, void *data);
bool wl1271_set_block_size(struct wl1271 *wl);
int wl1271_tx_dummy_packet(struct wl1271 *wl);

#endif
42 changes: 42 additions & 0 deletions drivers/net/wireless/wl12xx/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -1174,6 +1174,48 @@ static void wl1271_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
spin_unlock_irqrestore(&wl->wl_lock, flags);
}

#define TX_DUMMY_PACKET_SIZE 1400
int wl1271_tx_dummy_packet(struct wl1271 *wl)
{
struct sk_buff *skb = NULL;
struct ieee80211_hdr_3addr *hdr;
int ret = 0;

skb = dev_alloc_skb(
sizeof(struct wl1271_tx_hw_descr) + sizeof(*hdr) +
TX_DUMMY_PACKET_SIZE);
if (!skb) {
wl1271_warning("failed to allocate buffer for dummy packet");
ret = -ENOMEM;
goto out;
}

skb_reserve(skb, sizeof(struct wl1271_tx_hw_descr));

hdr = (struct ieee80211_hdr_3addr *) skb_put(skb, sizeof(*hdr));
memset(hdr, 0, sizeof(*hdr));
hdr->frame_control = cpu_to_le16(IEEE80211_FTYPE_DATA |
IEEE80211_FCTL_TODS |
IEEE80211_STYPE_NULLFUNC);

memcpy(hdr->addr1, wl->bssid, ETH_ALEN);
memcpy(hdr->addr2, wl->mac_addr, ETH_ALEN);
memcpy(hdr->addr3, wl->bssid, ETH_ALEN);

skb_put(skb, TX_DUMMY_PACKET_SIZE);

memset(skb->data, 0, TX_DUMMY_PACKET_SIZE);

skb->pkt_type = TX_PKT_TYPE_DUMMY_REQ;
/* CONF_TX_AC_VO */
skb->queue_mapping = 0;

wl1271_op_tx(wl->hw, skb);

out:
return ret;
}

static struct notifier_block wl1271_dev_notifier = {
.notifier_call = wl1271_dev_notify,
};
Expand Down
75 changes: 55 additions & 20 deletions drivers/net/wireless/wl12xx/tx.c
Original file line number Diff line number Diff line change
Expand Up @@ -215,13 +215,29 @@ static void wl1271_tx_fill_hdr(struct wl1271 *wl, struct sk_buff *skb,
else
desc->life_time = cpu_to_le16(TX_HW_AP_MODE_PKT_LIFETIME_TU);

/* configure the tx attributes */
tx_attr = wl->session_counter << TX_HW_ATTR_OFST_SESSION_COUNTER;

/* queue (we use same identifiers for tid's and ac's */
ac = wl1271_tx_get_queue(skb_get_queue_mapping(skb));
desc->tid = ac;

if (skb->pkt_type == TX_PKT_TYPE_DUMMY_REQ) {
/*
* FW expects the dummy packet to have an invalid session id -
* any session id that is different than the one set in the join
*/
tx_attr = ((~wl->session_counter) <<
TX_HW_ATTR_OFST_SESSION_COUNTER) &
TX_HW_ATTR_SESSION_COUNTER;

tx_attr |= TX_HW_ATTR_TX_DUMMY_REQ;

/* Dummy packets require the TID to be management */
desc->tid = WL1271_TID_MGMT;
} else {
/* configure the tx attributes */
tx_attr =
wl->session_counter << TX_HW_ATTR_OFST_SESSION_COUNTER;
}

if (wl->bss_type != BSS_TYPE_AP_BSS) {
desc->aid = hlid;

Expand Down Expand Up @@ -587,6 +603,12 @@ static void wl1271_tx_complete_packet(struct wl1271 *wl,
skb = wl->tx_frames[id];
info = IEEE80211_SKB_CB(skb);

if (skb->pkt_type == TX_PKT_TYPE_DUMMY_REQ) {
dev_kfree_skb(skb);
wl1271_free_tx_id(wl, id);
return;
}

/* update the TX status info */
if (result->status == TX_SUCCESS) {
if (!(info->flags & IEEE80211_TX_CTL_NO_ACK))
Expand Down Expand Up @@ -716,10 +738,15 @@ void wl1271_tx_reset(struct wl1271 *wl)
while ((skb = skb_dequeue(&wl->tx_queue[i]))) {
wl1271_debug(DEBUG_TX, "freeing skb 0x%p",
skb);
info = IEEE80211_SKB_CB(skb);
info->status.rates[0].idx = -1;
info->status.rates[0].count = 0;
ieee80211_tx_status(wl->hw, skb);

if (skb->pkt_type == TX_PKT_TYPE_DUMMY_REQ) {
dev_kfree_skb(skb);
} else {
info = IEEE80211_SKB_CB(skb);
info->status.rates[0].idx = -1;
info->status.rates[0].count = 0;
ieee80211_tx_status(wl->hw, skb);
}
}
}
}
Expand All @@ -740,21 +767,29 @@ void wl1271_tx_reset(struct wl1271 *wl)
wl1271_free_tx_id(wl, i);
wl1271_debug(DEBUG_TX, "freeing skb 0x%p", skb);

/* Remove private headers before passing the skb to mac80211 */
info = IEEE80211_SKB_CB(skb);
skb_pull(skb, sizeof(struct wl1271_tx_hw_descr));
if (info->control.hw_key &&
info->control.hw_key->cipher == WLAN_CIPHER_SUITE_TKIP) {
int hdrlen = ieee80211_get_hdrlen_from_skb(skb);
memmove(skb->data + WL1271_TKIP_IV_SPACE, skb->data,
hdrlen);
skb_pull(skb, WL1271_TKIP_IV_SPACE);
}
if (skb->pkt_type == TX_PKT_TYPE_DUMMY_REQ) {
dev_kfree_skb(skb);
} else {
/*
* Remove private headers before passing the skb to
* mac80211
*/
info = IEEE80211_SKB_CB(skb);
skb_pull(skb, sizeof(struct wl1271_tx_hw_descr));
if (info->control.hw_key &&
info->control.hw_key->cipher ==
WLAN_CIPHER_SUITE_TKIP) {
int hdrlen = ieee80211_get_hdrlen_from_skb(skb);
memmove(skb->data + WL1271_TKIP_IV_SPACE,
skb->data, hdrlen);
skb_pull(skb, WL1271_TKIP_IV_SPACE);
}

info->status.rates[0].idx = -1;
info->status.rates[0].count = 0;
info->status.rates[0].idx = -1;
info->status.rates[0].count = 0;

ieee80211_tx_status(wl->hw, skb);
ieee80211_tx_status(wl->hw, skb);
}
}
}

Expand Down
6 changes: 6 additions & 0 deletions drivers/net/wireless/wl12xx/tx.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,9 @@
BIT(8) | BIT(9))
#define TX_HW_ATTR_LAST_WORD_PAD (BIT(10) | BIT(11))
#define TX_HW_ATTR_TX_CMPLT_REQ BIT(12)
#define TX_HW_ATTR_TX_DUMMY_REQ BIT(13)

#define TX_PKT_TYPE_DUMMY_REQ 5

#define TX_HW_ATTR_OFST_SAVE_RETRIES 0
#define TX_HW_ATTR_OFST_HEADER_PAD 1
Expand All @@ -55,6 +58,9 @@
#define WL1271_TX_ALIGN_TO 4
#define WL1271_TKIP_IV_SPACE 4

/* Used for management frames and dummy packets */
#define WL1271_TID_MGMT 7

struct wl127x_tx_mem {
/*
* Number of extra memory blocks to allocate for this packet
Expand Down

0 comments on commit ae47c45

Please sign in to comment.