aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net
diff options
context:
space:
mode:
authorShahar Levi <shahar_levi@ti.com>2011-03-06 09:32:14 -0500
committerLuciano Coelho <coelho@ti.com>2011-04-19 09:49:01 -0400
commitae47c45fd02fdf88d57adc370e78e7a01e2bfcbc (patch)
tree3def0959f5332c2fd1279ffe898db0c554c1f819 /drivers/net
parentae77eccf04f8c36769bdba334e1bbcc7bb9d3644 (diff)
wl12xx: 1281/1283 support - Add dummy packet support
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>
Diffstat (limited to 'drivers/net')
-rw-r--r--drivers/net/wireless/wl12xx/boot.c2
-rw-r--r--drivers/net/wireless/wl12xx/event.c6
-rw-r--r--drivers/net/wireless/wl12xx/event.h5
-rw-r--r--drivers/net/wireless/wl12xx/io.h1
-rw-r--r--drivers/net/wireless/wl12xx/main.c42
-rw-r--r--drivers/net/wireless/wl12xx/tx.c75
-rw-r--r--drivers/net/wireless/wl12xx/tx.h6
7 files changed, 116 insertions, 21 deletions
diff --git a/drivers/net/wireless/wl12xx/boot.c b/drivers/net/wireless/wl12xx/boot.c
index 9d742c1e75a9..34bf2fe47dc7 100644
--- a/drivers/net/wireless/wl12xx/boot.c
+++ b/drivers/net/wireless/wl12xx/boot.c
@@ -482,6 +482,8 @@ static int wl1271_boot_run_firmware(struct wl1271 *wl)
482 482
483 if (wl->bss_type == BSS_TYPE_AP_BSS) 483 if (wl->bss_type == BSS_TYPE_AP_BSS)
484 wl->event_mask |= STA_REMOVE_COMPLETE_EVENT_ID; 484 wl->event_mask |= STA_REMOVE_COMPLETE_EVENT_ID;
485 else
486 wl->event_mask |= DUMMY_PACKET_EVENT_ID;
485 487
486 ret = wl1271_event_unmask(wl); 488 ret = wl1271_event_unmask(wl);
487 if (ret < 0) { 489 if (ret < 0) {
diff --git a/drivers/net/wireless/wl12xx/event.c b/drivers/net/wireless/wl12xx/event.c
index 1b170c5cc595..413d901985fe 100644
--- a/drivers/net/wireless/wl12xx/event.c
+++ b/drivers/net/wireless/wl12xx/event.c
@@ -228,6 +228,12 @@ static int wl1271_event_process(struct wl1271 *wl, struct event_mailbox *mbox)
228 wl1271_event_rssi_trigger(wl, mbox); 228 wl1271_event_rssi_trigger(wl, mbox);
229 } 229 }
230 230
231 if ((vector & DUMMY_PACKET_EVENT_ID) && !is_ap) {
232 wl1271_debug(DEBUG_EVENT, "DUMMY_PACKET_ID_EVENT_ID");
233 if (wl->vif)
234 wl1271_tx_dummy_packet(wl);
235 }
236
231 if (wl->vif && beacon_loss) 237 if (wl->vif && beacon_loss)
232 ieee80211_connection_loss(wl->vif); 238 ieee80211_connection_loss(wl->vif);
233 239
diff --git a/drivers/net/wireless/wl12xx/event.h b/drivers/net/wireless/wl12xx/event.h
index 0e80886f3031..b6cf06e565a4 100644
--- a/drivers/net/wireless/wl12xx/event.h
+++ b/drivers/net/wireless/wl12xx/event.h
@@ -59,7 +59,10 @@ enum {
59 BSS_LOSE_EVENT_ID = BIT(18), 59 BSS_LOSE_EVENT_ID = BIT(18),
60 REGAINED_BSS_EVENT_ID = BIT(19), 60 REGAINED_BSS_EVENT_ID = BIT(19),
61 ROAMING_TRIGGER_MAX_TX_RETRY_EVENT_ID = BIT(20), 61 ROAMING_TRIGGER_MAX_TX_RETRY_EVENT_ID = BIT(20),
62 STA_REMOVE_COMPLETE_EVENT_ID = BIT(21), /* AP */ 62 /* STA: dummy paket for dynamic mem blocks */
63 DUMMY_PACKET_EVENT_ID = BIT(21),
64 /* AP: STA remove complete */
65 STA_REMOVE_COMPLETE_EVENT_ID = BIT(21),
63 SOFT_GEMINI_SENSE_EVENT_ID = BIT(22), 66 SOFT_GEMINI_SENSE_EVENT_ID = BIT(22),
64 SOFT_GEMINI_PREDICTION_EVENT_ID = BIT(23), 67 SOFT_GEMINI_PREDICTION_EVENT_ID = BIT(23),
65 SOFT_GEMINI_AVALANCHE_EVENT_ID = BIT(24), 68 SOFT_GEMINI_AVALANCHE_EVENT_ID = BIT(24),
diff --git a/drivers/net/wireless/wl12xx/io.h b/drivers/net/wireless/wl12xx/io.h
index 84454f6d8169..e6199eb51936 100644
--- a/drivers/net/wireless/wl12xx/io.h
+++ b/drivers/net/wireless/wl12xx/io.h
@@ -170,5 +170,6 @@ struct ieee80211_hw *wl1271_alloc_hw(void);
170int wl1271_free_hw(struct wl1271 *wl); 170int wl1271_free_hw(struct wl1271 *wl);
171irqreturn_t wl1271_irq(int irq, void *data); 171irqreturn_t wl1271_irq(int irq, void *data);
172bool wl1271_set_block_size(struct wl1271 *wl); 172bool wl1271_set_block_size(struct wl1271 *wl);
173int wl1271_tx_dummy_packet(struct wl1271 *wl);
173 174
174#endif 175#endif
diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c
index 3c381ceadb98..54ac6757c39b 100644
--- a/drivers/net/wireless/wl12xx/main.c
+++ b/drivers/net/wireless/wl12xx/main.c
@@ -1174,6 +1174,48 @@ static void wl1271_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
1174 spin_unlock_irqrestore(&wl->wl_lock, flags); 1174 spin_unlock_irqrestore(&wl->wl_lock, flags);
1175} 1175}
1176 1176
1177#define TX_DUMMY_PACKET_SIZE 1400
1178int wl1271_tx_dummy_packet(struct wl1271 *wl)
1179{
1180 struct sk_buff *skb = NULL;
1181 struct ieee80211_hdr_3addr *hdr;
1182 int ret = 0;
1183
1184 skb = dev_alloc_skb(
1185 sizeof(struct wl1271_tx_hw_descr) + sizeof(*hdr) +
1186 TX_DUMMY_PACKET_SIZE);
1187 if (!skb) {
1188 wl1271_warning("failed to allocate buffer for dummy packet");
1189 ret = -ENOMEM;
1190 goto out;
1191 }
1192
1193 skb_reserve(skb, sizeof(struct wl1271_tx_hw_descr));
1194
1195 hdr = (struct ieee80211_hdr_3addr *) skb_put(skb, sizeof(*hdr));
1196 memset(hdr, 0, sizeof(*hdr));
1197 hdr->frame_control = cpu_to_le16(IEEE80211_FTYPE_DATA |
1198 IEEE80211_FCTL_TODS |
1199 IEEE80211_STYPE_NULLFUNC);
1200
1201 memcpy(hdr->addr1, wl->bssid, ETH_ALEN);
1202 memcpy(hdr->addr2, wl->mac_addr, ETH_ALEN);
1203 memcpy(hdr->addr3, wl->bssid, ETH_ALEN);
1204
1205 skb_put(skb, TX_DUMMY_PACKET_SIZE);
1206
1207 memset(skb->data, 0, TX_DUMMY_PACKET_SIZE);
1208
1209 skb->pkt_type = TX_PKT_TYPE_DUMMY_REQ;
1210 /* CONF_TX_AC_VO */
1211 skb->queue_mapping = 0;
1212
1213 wl1271_op_tx(wl->hw, skb);
1214
1215out:
1216 return ret;
1217}
1218
1177static struct notifier_block wl1271_dev_notifier = { 1219static struct notifier_block wl1271_dev_notifier = {
1178 .notifier_call = wl1271_dev_notify, 1220 .notifier_call = wl1271_dev_notify,
1179}; 1221};
diff --git a/drivers/net/wireless/wl12xx/tx.c b/drivers/net/wireless/wl12xx/tx.c
index afc8505abeb6..75222a681296 100644
--- a/drivers/net/wireless/wl12xx/tx.c
+++ b/drivers/net/wireless/wl12xx/tx.c
@@ -215,13 +215,29 @@ static void wl1271_tx_fill_hdr(struct wl1271 *wl, struct sk_buff *skb,
215 else 215 else
216 desc->life_time = cpu_to_le16(TX_HW_AP_MODE_PKT_LIFETIME_TU); 216 desc->life_time = cpu_to_le16(TX_HW_AP_MODE_PKT_LIFETIME_TU);
217 217
218 /* configure the tx attributes */
219 tx_attr = wl->session_counter << TX_HW_ATTR_OFST_SESSION_COUNTER;
220
221 /* queue (we use same identifiers for tid's and ac's */ 218 /* queue (we use same identifiers for tid's and ac's */
222 ac = wl1271_tx_get_queue(skb_get_queue_mapping(skb)); 219 ac = wl1271_tx_get_queue(skb_get_queue_mapping(skb));
223 desc->tid = ac; 220 desc->tid = ac;
224 221
222 if (skb->pkt_type == TX_PKT_TYPE_DUMMY_REQ) {
223 /*
224 * FW expects the dummy packet to have an invalid session id -
225 * any session id that is different than the one set in the join
226 */
227 tx_attr = ((~wl->session_counter) <<
228 TX_HW_ATTR_OFST_SESSION_COUNTER) &
229 TX_HW_ATTR_SESSION_COUNTER;
230
231 tx_attr |= TX_HW_ATTR_TX_DUMMY_REQ;
232
233 /* Dummy packets require the TID to be management */
234 desc->tid = WL1271_TID_MGMT;
235 } else {
236 /* configure the tx attributes */
237 tx_attr =
238 wl->session_counter << TX_HW_ATTR_OFST_SESSION_COUNTER;
239 }
240
225 if (wl->bss_type != BSS_TYPE_AP_BSS) { 241 if (wl->bss_type != BSS_TYPE_AP_BSS) {
226 desc->aid = hlid; 242 desc->aid = hlid;
227 243
@@ -587,6 +603,12 @@ static void wl1271_tx_complete_packet(struct wl1271 *wl,
587 skb = wl->tx_frames[id]; 603 skb = wl->tx_frames[id];
588 info = IEEE80211_SKB_CB(skb); 604 info = IEEE80211_SKB_CB(skb);
589 605
606 if (skb->pkt_type == TX_PKT_TYPE_DUMMY_REQ) {
607 dev_kfree_skb(skb);
608 wl1271_free_tx_id(wl, id);
609 return;
610 }
611
590 /* update the TX status info */ 612 /* update the TX status info */
591 if (result->status == TX_SUCCESS) { 613 if (result->status == TX_SUCCESS) {
592 if (!(info->flags & IEEE80211_TX_CTL_NO_ACK)) 614 if (!(info->flags & IEEE80211_TX_CTL_NO_ACK))
@@ -716,10 +738,15 @@ void wl1271_tx_reset(struct wl1271 *wl)
716 while ((skb = skb_dequeue(&wl->tx_queue[i]))) { 738 while ((skb = skb_dequeue(&wl->tx_queue[i]))) {
717 wl1271_debug(DEBUG_TX, "freeing skb 0x%p", 739 wl1271_debug(DEBUG_TX, "freeing skb 0x%p",
718 skb); 740 skb);
719 info = IEEE80211_SKB_CB(skb); 741
720 info->status.rates[0].idx = -1; 742 if (skb->pkt_type == TX_PKT_TYPE_DUMMY_REQ) {
721 info->status.rates[0].count = 0; 743 dev_kfree_skb(skb);
722 ieee80211_tx_status(wl->hw, skb); 744 } else {
745 info = IEEE80211_SKB_CB(skb);
746 info->status.rates[0].idx = -1;
747 info->status.rates[0].count = 0;
748 ieee80211_tx_status(wl->hw, skb);
749 }
723 } 750 }
724 } 751 }
725 } 752 }
@@ -740,21 +767,29 @@ void wl1271_tx_reset(struct wl1271 *wl)
740 wl1271_free_tx_id(wl, i); 767 wl1271_free_tx_id(wl, i);
741 wl1271_debug(DEBUG_TX, "freeing skb 0x%p", skb); 768 wl1271_debug(DEBUG_TX, "freeing skb 0x%p", skb);
742 769
743 /* Remove private headers before passing the skb to mac80211 */ 770 if (skb->pkt_type == TX_PKT_TYPE_DUMMY_REQ) {
744 info = IEEE80211_SKB_CB(skb); 771 dev_kfree_skb(skb);
745 skb_pull(skb, sizeof(struct wl1271_tx_hw_descr)); 772 } else {
746 if (info->control.hw_key && 773 /*
747 info->control.hw_key->cipher == WLAN_CIPHER_SUITE_TKIP) { 774 * Remove private headers before passing the skb to
748 int hdrlen = ieee80211_get_hdrlen_from_skb(skb); 775 * mac80211
749 memmove(skb->data + WL1271_TKIP_IV_SPACE, skb->data, 776 */
750 hdrlen); 777 info = IEEE80211_SKB_CB(skb);
751 skb_pull(skb, WL1271_TKIP_IV_SPACE); 778 skb_pull(skb, sizeof(struct wl1271_tx_hw_descr));
752 } 779 if (info->control.hw_key &&
780 info->control.hw_key->cipher ==
781 WLAN_CIPHER_SUITE_TKIP) {
782 int hdrlen = ieee80211_get_hdrlen_from_skb(skb);
783 memmove(skb->data + WL1271_TKIP_IV_SPACE,
784 skb->data, hdrlen);
785 skb_pull(skb, WL1271_TKIP_IV_SPACE);
786 }
753 787
754 info->status.rates[0].idx = -1; 788 info->status.rates[0].idx = -1;
755 info->status.rates[0].count = 0; 789 info->status.rates[0].count = 0;
756 790
757 ieee80211_tx_status(wl->hw, skb); 791 ieee80211_tx_status(wl->hw, skb);
792 }
758 } 793 }
759} 794}
760 795
diff --git a/drivers/net/wireless/wl12xx/tx.h b/drivers/net/wireless/wl12xx/tx.h
index e31317717ab2..6f45e9108d9a 100644
--- a/drivers/net/wireless/wl12xx/tx.h
+++ b/drivers/net/wireless/wl12xx/tx.h
@@ -41,6 +41,9 @@
41 BIT(8) | BIT(9)) 41 BIT(8) | BIT(9))
42#define TX_HW_ATTR_LAST_WORD_PAD (BIT(10) | BIT(11)) 42#define TX_HW_ATTR_LAST_WORD_PAD (BIT(10) | BIT(11))
43#define TX_HW_ATTR_TX_CMPLT_REQ BIT(12) 43#define TX_HW_ATTR_TX_CMPLT_REQ BIT(12)
44#define TX_HW_ATTR_TX_DUMMY_REQ BIT(13)
45
46#define TX_PKT_TYPE_DUMMY_REQ 5
44 47
45#define TX_HW_ATTR_OFST_SAVE_RETRIES 0 48#define TX_HW_ATTR_OFST_SAVE_RETRIES 0
46#define TX_HW_ATTR_OFST_HEADER_PAD 1 49#define TX_HW_ATTR_OFST_HEADER_PAD 1
@@ -55,6 +58,9 @@
55#define WL1271_TX_ALIGN_TO 4 58#define WL1271_TX_ALIGN_TO 4
56#define WL1271_TKIP_IV_SPACE 4 59#define WL1271_TKIP_IV_SPACE 4
57 60
61/* Used for management frames and dummy packets */
62#define WL1271_TID_MGMT 7
63
58struct wl127x_tx_mem { 64struct wl127x_tx_mem {
59 /* 65 /*
60 * Number of extra memory blocks to allocate for this packet 66 * Number of extra memory blocks to allocate for this packet