aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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