aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorEliad Peller <eliad@wizery.com>2011-10-10 04:12:55 -0400
committerLuciano Coelho <coelho@ti.com>2011-10-11 08:04:22 -0400
commita32d0cdfcb7e5d41f210e13cbc78dc86a5a85a08 (patch)
tree6dffb8d33f576a6c38d65c15cf9fc52c6601b989 /drivers
parent87627214738fcfd44803e90193f9f2f4583ce68b (diff)
wl12xx: support multiple vifs in the tx path
Pass the wlvif associated with each skb as param. Note that dummy packet doesn't belong to any particular vif, so we pass NULL in this case. Signed-off-by: Eliad Peller <eliad@wizery.com> Signed-off-by: Luciano Coelho <coelho@ti.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/net/wireless/wl12xx/main.c6
-rw-r--r--drivers/net/wireless/wl12xx/tx.c79
-rw-r--r--drivers/net/wireless/wl12xx/tx.h2
3 files changed, 52 insertions, 35 deletions
diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c
index 56d592398677..0623f5dc02ca 100644
--- a/drivers/net/wireless/wl12xx/main.c
+++ b/drivers/net/wireless/wl12xx/main.c
@@ -993,7 +993,7 @@ irqreturn_t wl1271_irq(int irq, void *cookie)
993 * In order to avoid starvation of the TX path, 993 * In order to avoid starvation of the TX path,
994 * call the work function directly. 994 * call the work function directly.
995 */ 995 */
996 wl1271_tx_work_locked(wl, wl->vif); 996 wl1271_tx_work_locked(wl);
997 } else { 997 } else {
998 spin_unlock_irqrestore(&wl->wl_lock, flags); 998 spin_unlock_irqrestore(&wl->wl_lock, flags);
999 } 999 }
@@ -1537,7 +1537,7 @@ int wl1271_tx_dummy_packet(struct wl1271 *wl)
1537 1537
1538 /* The FW is low on RX memory blocks, so send the dummy packet asap */ 1538 /* The FW is low on RX memory blocks, so send the dummy packet asap */
1539 if (!test_bit(WL1271_FLAG_FW_TX_BUSY, &wl->flags)) 1539 if (!test_bit(WL1271_FLAG_FW_TX_BUSY, &wl->flags))
1540 wl1271_tx_work_locked(wl, wl->vif); 1540 wl1271_tx_work_locked(wl);
1541 1541
1542 /* 1542 /*
1543 * If the FW TX is busy, TX work will be scheduled by the threaded 1543 * If the FW TX is busy, TX work will be scheduled by the threaded
@@ -2413,7 +2413,7 @@ static int wl1271_op_config(struct ieee80211_hw *hw, u32 changed)
2413 ((wl->band != conf->channel->band) || 2413 ((wl->band != conf->channel->band) ||
2414 (wl->channel != channel))) { 2414 (wl->channel != channel))) {
2415 /* send all pending packets */ 2415 /* send all pending packets */
2416 wl1271_tx_work_locked(wl, vif); 2416 wl1271_tx_work_locked(wl);
2417 wl->band = conf->channel->band; 2417 wl->band = conf->channel->band;
2418 wl->channel = channel; 2418 wl->channel = channel;
2419 2419
diff --git a/drivers/net/wireless/wl12xx/tx.c b/drivers/net/wireless/wl12xx/tx.c
index 6c0135b27820..c7be15186c4a 100644
--- a/drivers/net/wireless/wl12xx/tx.c
+++ b/drivers/net/wireless/wl12xx/tx.c
@@ -210,17 +210,17 @@ static unsigned int wl12xx_calc_packet_alignment(struct wl1271 *wl,
210 return ALIGN(packet_length, WL1271_TX_ALIGN_TO); 210 return ALIGN(packet_length, WL1271_TX_ALIGN_TO);
211} 211}
212 212
213static int wl1271_tx_allocate(struct wl1271 *wl, struct ieee80211_vif *vif, 213static int wl1271_tx_allocate(struct wl1271 *wl, struct wl12xx_vif *wlvif,
214 struct sk_buff *skb, u32 extra, u32 buf_offset, 214 struct sk_buff *skb, u32 extra, u32 buf_offset,
215 u8 hlid) 215 u8 hlid)
216{ 216{
217 struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif);
218 struct wl1271_tx_hw_descr *desc; 217 struct wl1271_tx_hw_descr *desc;
219 u32 total_len = skb->len + sizeof(struct wl1271_tx_hw_descr) + extra; 218 u32 total_len = skb->len + sizeof(struct wl1271_tx_hw_descr) + extra;
220 u32 len; 219 u32 len;
221 u32 total_blocks; 220 u32 total_blocks;
222 int id, ret = -EBUSY, ac; 221 int id, ret = -EBUSY, ac;
223 u32 spare_blocks = wl->tx_spare_blocks; 222 u32 spare_blocks = wl->tx_spare_blocks;
223 bool is_dummy = false;
224 224
225 if (buf_offset + total_len > WL1271_AGGR_BUFFER_SIZE) 225 if (buf_offset + total_len > WL1271_AGGR_BUFFER_SIZE)
226 return -EAGAIN; 226 return -EAGAIN;
@@ -235,8 +235,10 @@ static int wl1271_tx_allocate(struct wl1271 *wl, struct ieee80211_vif *vif,
235 len = wl12xx_calc_packet_alignment(wl, total_len); 235 len = wl12xx_calc_packet_alignment(wl, total_len);
236 236
237 /* in case of a dummy packet, use default amount of spare mem blocks */ 237 /* in case of a dummy packet, use default amount of spare mem blocks */
238 if (unlikely(wl12xx_is_dummy_packet(wl, skb))) 238 if (unlikely(wl12xx_is_dummy_packet(wl, skb))) {
239 is_dummy = true;
239 spare_blocks = TX_HW_BLOCK_SPARE_DEFAULT; 240 spare_blocks = TX_HW_BLOCK_SPARE_DEFAULT;
241 }
240 242
241 total_blocks = (len + TX_HW_BLOCK_SIZE - 1) / TX_HW_BLOCK_SIZE + 243 total_blocks = (len + TX_HW_BLOCK_SIZE - 1) / TX_HW_BLOCK_SIZE +
242 spare_blocks; 244 spare_blocks;
@@ -261,7 +263,7 @@ static int wl1271_tx_allocate(struct wl1271 *wl, struct ieee80211_vif *vif,
261 ac = wl1271_tx_get_queue(skb_get_queue_mapping(skb)); 263 ac = wl1271_tx_get_queue(skb_get_queue_mapping(skb));
262 wl->tx_allocated_pkts[ac]++; 264 wl->tx_allocated_pkts[ac]++;
263 265
264 if (wlvif->bss_type == BSS_TYPE_AP_BSS && 266 if (!is_dummy && wlvif->bss_type == BSS_TYPE_AP_BSS &&
265 test_bit(hlid, wlvif->ap.sta_hlid_map)) 267 test_bit(hlid, wlvif->ap.sta_hlid_map))
266 wl->links[hlid].allocated_pkts++; 268 wl->links[hlid].allocated_pkts++;
267 269
@@ -277,16 +279,16 @@ static int wl1271_tx_allocate(struct wl1271 *wl, struct ieee80211_vif *vif,
277 return ret; 279 return ret;
278} 280}
279 281
280static void wl1271_tx_fill_hdr(struct wl1271 *wl, struct ieee80211_vif *vif, 282static void wl1271_tx_fill_hdr(struct wl1271 *wl, struct wl12xx_vif *wlvif,
281 struct sk_buff *skb, u32 extra, 283 struct sk_buff *skb, u32 extra,
282 struct ieee80211_tx_info *control, u8 hlid) 284 struct ieee80211_tx_info *control, u8 hlid)
283{ 285{
284 struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif);
285 struct timespec ts; 286 struct timespec ts;
286 struct wl1271_tx_hw_descr *desc; 287 struct wl1271_tx_hw_descr *desc;
287 int aligned_len, ac, rate_idx; 288 int aligned_len, ac, rate_idx;
288 s64 hosttime; 289 s64 hosttime;
289 u16 tx_attr; 290 u16 tx_attr;
291 bool is_dummy;
290 292
291 desc = (struct wl1271_tx_hw_descr *) skb->data; 293 desc = (struct wl1271_tx_hw_descr *) skb->data;
292 294
@@ -303,7 +305,8 @@ static void wl1271_tx_fill_hdr(struct wl1271 *wl, struct ieee80211_vif *vif,
303 hosttime = (timespec_to_ns(&ts) >> 10); 305 hosttime = (timespec_to_ns(&ts) >> 10);
304 desc->start_time = cpu_to_le32(hosttime - wl->time_offset); 306 desc->start_time = cpu_to_le32(hosttime - wl->time_offset);
305 307
306 if (wlvif->bss_type != BSS_TYPE_AP_BSS) 308 is_dummy = wl12xx_is_dummy_packet(wl, skb);
309 if (is_dummy || wlvif->bss_type != BSS_TYPE_AP_BSS)
307 desc->life_time = cpu_to_le16(TX_HW_MGMT_PKT_LIFETIME_TU); 310 desc->life_time = cpu_to_le16(TX_HW_MGMT_PKT_LIFETIME_TU);
308 else 311 else
309 desc->life_time = cpu_to_le16(TX_HW_AP_MODE_PKT_LIFETIME_TU); 312 desc->life_time = cpu_to_le16(TX_HW_AP_MODE_PKT_LIFETIME_TU);
@@ -312,7 +315,7 @@ static void wl1271_tx_fill_hdr(struct wl1271 *wl, struct ieee80211_vif *vif,
312 ac = wl1271_tx_get_queue(skb_get_queue_mapping(skb)); 315 ac = wl1271_tx_get_queue(skb_get_queue_mapping(skb));
313 desc->tid = skb->priority; 316 desc->tid = skb->priority;
314 317
315 if (wl12xx_is_dummy_packet(wl, skb)) { 318 if (is_dummy) {
316 /* 319 /*
317 * FW expects the dummy packet to have an invalid session id - 320 * FW expects the dummy packet to have an invalid session id -
318 * any session id that is different than the one set in the join 321 * any session id that is different than the one set in the join
@@ -329,7 +332,9 @@ static void wl1271_tx_fill_hdr(struct wl1271 *wl, struct ieee80211_vif *vif,
329 } 332 }
330 333
331 desc->hlid = hlid; 334 desc->hlid = hlid;
332 if (wlvif->bss_type != BSS_TYPE_AP_BSS) { 335 if (is_dummy)
336 rate_idx = 0;
337 else if (wlvif->bss_type != BSS_TYPE_AP_BSS) {
333 /* if the packets are destined for AP (have a STA entry) 338 /* if the packets are destined for AP (have a STA entry)
334 send them with AP rate policies, otherwise use default 339 send them with AP rate policies, otherwise use default
335 basic rates */ 340 basic rates */
@@ -383,12 +388,10 @@ static void wl1271_tx_fill_hdr(struct wl1271 *wl, struct ieee80211_vif *vif,
383} 388}
384 389
385/* caller must hold wl->mutex */ 390/* caller must hold wl->mutex */
386static int wl1271_prepare_tx_frame(struct wl1271 *wl, struct sk_buff *skb, 391static int wl1271_prepare_tx_frame(struct wl1271 *wl, struct wl12xx_vif *wlvif,
387 u32 buf_offset) 392 struct sk_buff *skb, u32 buf_offset)
388{ 393{
389 struct ieee80211_tx_info *info; 394 struct ieee80211_tx_info *info;
390 struct ieee80211_vif *vif;
391 struct wl12xx_vif *wlvif;
392 u32 extra = 0; 395 u32 extra = 0;
393 int ret = 0; 396 int ret = 0;
394 u32 total_len; 397 u32 total_len;
@@ -402,11 +405,6 @@ static int wl1271_prepare_tx_frame(struct wl1271 *wl, struct sk_buff *skb,
402 405
403 /* TODO: handle dummy packets on multi-vifs */ 406 /* TODO: handle dummy packets on multi-vifs */
404 is_dummy = wl12xx_is_dummy_packet(wl, skb); 407 is_dummy = wl12xx_is_dummy_packet(wl, skb);
405 if (is_dummy)
406 info->control.vif = wl->vif;
407
408 vif = info->control.vif;
409 wlvif = wl12xx_vif_to_data(vif);
410 408
411 if (info->control.hw_key && 409 if (info->control.hw_key &&
412 info->control.hw_key->cipher == WLAN_CIPHER_SUITE_TKIP) 410 info->control.hw_key->cipher == WLAN_CIPHER_SUITE_TKIP)
@@ -433,13 +431,13 @@ static int wl1271_prepare_tx_frame(struct wl1271 *wl, struct sk_buff *skb,
433 return -EINVAL; 431 return -EINVAL;
434 } 432 }
435 433
436 ret = wl1271_tx_allocate(wl, vif, skb, extra, buf_offset, hlid); 434 ret = wl1271_tx_allocate(wl, wlvif, skb, extra, buf_offset, hlid);
437 if (ret < 0) 435 if (ret < 0)
438 return ret; 436 return ret;
439 437
440 wl1271_tx_fill_hdr(wl, vif, skb, extra, info, hlid); 438 wl1271_tx_fill_hdr(wl, wlvif, skb, extra, info, hlid);
441 439
442 if (wlvif->bss_type == BSS_TYPE_AP_BSS && !is_dummy) { 440 if (!is_dummy && wlvif->bss_type == BSS_TYPE_AP_BSS) {
443 wl1271_tx_ap_update_inconnection_sta(wl, skb); 441 wl1271_tx_ap_update_inconnection_sta(wl, skb);
444 wl1271_tx_regulate_link(wl, wlvif, hlid); 442 wl1271_tx_regulate_link(wl, wlvif, hlid);
445 } 443 }
@@ -589,13 +587,19 @@ static struct sk_buff *wl12xx_vif_skb_dequeue(struct wl1271 *wl,
589 return skb; 587 return skb;
590} 588}
591 589
592static struct sk_buff *wl1271_skb_dequeue(struct wl1271 *wl, 590static struct sk_buff *wl1271_skb_dequeue(struct wl1271 *wl)
593 struct wl12xx_vif *wlvif)
594{ 591{
595 unsigned long flags; 592 unsigned long flags;
593 struct wl12xx_vif *wlvif;
596 struct sk_buff *skb = NULL; 594 struct sk_buff *skb = NULL;
597 595
598 skb = wl12xx_vif_skb_dequeue(wl, wlvif); 596 /* TODO: rememeber last vif and consider it */
597 wl12xx_for_each_wlvif(wl, wlvif) {
598 skb = wl12xx_vif_skb_dequeue(wl, wlvif);
599 if (skb)
600 break;
601 }
602
599 if (!skb && 603 if (!skb &&
600 test_and_clear_bit(WL1271_FLAG_DUMMY_PACKET_PENDING, &wl->flags)) { 604 test_and_clear_bit(WL1271_FLAG_DUMMY_PACKET_PENDING, &wl->flags)) {
601 int q; 605 int q;
@@ -639,24 +643,35 @@ static bool wl1271_tx_is_data_present(struct sk_buff *skb)
639 return ieee80211_is_data_present(hdr->frame_control); 643 return ieee80211_is_data_present(hdr->frame_control);
640} 644}
641 645
642void wl1271_tx_work_locked(struct wl1271 *wl, struct ieee80211_vif *vif) 646void wl1271_tx_work_locked(struct wl1271 *wl)
643{ 647{
644 struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif); 648 struct wl12xx_vif *wlvif;
645 struct sk_buff *skb; 649 struct sk_buff *skb;
646 u32 buf_offset = 0; 650 u32 buf_offset = 0;
647 bool sent_packets = false; 651 bool sent_packets = false;
648 bool had_data = false; 652 bool had_data = false;
649 bool is_ap = (wlvif->bss_type == BSS_TYPE_AP_BSS); 653 /* TODO: save bitmap of relevant stations */
654 bool is_sta = false;
650 int ret; 655 int ret;
651 656
652 if (unlikely(wl->state == WL1271_STATE_OFF)) 657 if (unlikely(wl->state == WL1271_STATE_OFF))
653 return; 658 return;
654 659
655 while ((skb = wl1271_skb_dequeue(wl, wlvif))) { 660 while ((skb = wl1271_skb_dequeue(wl))) {
661 wlvif = NULL;
662 if (!wl12xx_is_dummy_packet(wl, skb)) {
663 struct ieee80211_tx_info *info;
664 struct ieee80211_vif *vif;
665
666 info = IEEE80211_SKB_CB(skb);
667 vif = info->control.vif;
668 wlvif = wl12xx_vif_to_data(vif);
669 }
670
656 if (wl1271_tx_is_data_present(skb)) 671 if (wl1271_tx_is_data_present(skb))
657 had_data = true; 672 had_data = true;
658 673
659 ret = wl1271_prepare_tx_frame(wl, skb, buf_offset); 674 ret = wl1271_prepare_tx_frame(wl, wlvif, skb, buf_offset);
660 if (ret == -EAGAIN) { 675 if (ret == -EAGAIN) {
661 /* 676 /*
662 * Aggregation buffer is full. 677 * Aggregation buffer is full.
@@ -683,6 +698,8 @@ void wl1271_tx_work_locked(struct wl1271 *wl, struct ieee80211_vif *vif)
683 } 698 }
684 buf_offset += ret; 699 buf_offset += ret;
685 wl->tx_packets_count++; 700 wl->tx_packets_count++;
701 if (wlvif && wlvif->bss_type == BSS_TYPE_STA_BSS)
702 is_sta = true;
686 } 703 }
687 704
688out_ack: 705out_ack:
@@ -702,7 +719,7 @@ out_ack:
702 719
703 wl1271_handle_tx_low_watermark(wl); 720 wl1271_handle_tx_low_watermark(wl);
704 } 721 }
705 if (!is_ap && wl->conf.rx_streaming.interval && had_data && 722 if (is_sta && wl->conf.rx_streaming.interval && had_data &&
706 (wl->conf.rx_streaming.always || 723 (wl->conf.rx_streaming.always ||
707 test_bit(WL1271_FLAG_SOFT_GEMINI, &wl->flags))) { 724 test_bit(WL1271_FLAG_SOFT_GEMINI, &wl->flags))) {
708 u32 timeout = wl->conf.rx_streaming.duration; 725 u32 timeout = wl->conf.rx_streaming.duration;
@@ -727,7 +744,7 @@ void wl1271_tx_work(struct work_struct *work)
727 if (ret < 0) 744 if (ret < 0)
728 goto out; 745 goto out;
729 746
730 wl1271_tx_work_locked(wl, wl->vif); 747 wl1271_tx_work_locked(wl);
731 748
732 wl1271_ps_elp_sleep(wl); 749 wl1271_ps_elp_sleep(wl);
733out: 750out:
diff --git a/drivers/net/wireless/wl12xx/tx.h b/drivers/net/wireless/wl12xx/tx.h
index 050a04792600..fe29ff524e9a 100644
--- a/drivers/net/wireless/wl12xx/tx.h
+++ b/drivers/net/wireless/wl12xx/tx.h
@@ -204,7 +204,7 @@ static inline int wl1271_tx_total_queue_count(struct wl1271 *wl)
204} 204}
205 205
206void wl1271_tx_work(struct work_struct *work); 206void wl1271_tx_work(struct work_struct *work);
207void wl1271_tx_work_locked(struct wl1271 *wl, struct ieee80211_vif *vif); 207void wl1271_tx_work_locked(struct wl1271 *wl);
208void wl1271_tx_complete(struct wl1271 *wl); 208void wl1271_tx_complete(struct wl1271 *wl);
209void wl12xx_tx_reset_wlvif(struct wl1271 *wl, struct wl12xx_vif *wlvif); 209void wl12xx_tx_reset_wlvif(struct wl1271 *wl, struct wl12xx_vif *wlvif);
210void wl12xx_tx_reset(struct wl1271 *wl, bool reset_tx_queues); 210void wl12xx_tx_reset(struct wl1271 *wl, bool reset_tx_queues);