aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net
diff options
context:
space:
mode:
authorFelix Fietkau <nbd@openwrt.org>2013-10-11 17:30:52 -0400
committerJohn W. Linville <linville@tuxdriver.com>2013-10-14 13:39:58 -0400
commit1a04d59d3ec982689552077172893b6836def984 (patch)
tree7973659757e31fa83614ac2c503a984876548fbe /drivers/net
parent50d60c6322f14e32bc11635732c54db1447fd3f5 (diff)
ath9k: use a separate data structure for rx buffers
There's no shared code for handling both rx and tx buffers, and tx buffers require a lot more metadata than rx buffers. Using a separate data structure for rx reduces memory usage and improves cache footprint. Signed-off-by: Felix Fietkau <nbd@openwrt.org> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net')
-rw-r--r--drivers/net/wireless/ath/ath9k/ath9k.h10
-rw-r--r--drivers/net/wireless/ath/ath9k/init.c84
-rw-r--r--drivers/net/wireless/ath/ath9k/recv.c48
3 files changed, 92 insertions, 50 deletions
diff --git a/drivers/net/wireless/ath/ath9k/ath9k.h b/drivers/net/wireless/ath/ath9k/ath9k.h
index 8878f2dada2d..83c045549db4 100644
--- a/drivers/net/wireless/ath/ath9k/ath9k.h
+++ b/drivers/net/wireless/ath/ath9k/ath9k.h
@@ -207,6 +207,14 @@ struct ath_frame_info {
207 u8 baw_tracked : 1; 207 u8 baw_tracked : 1;
208}; 208};
209 209
210struct ath_rxbuf {
211 struct list_head list;
212 struct sk_buff *bf_mpdu;
213 void *bf_desc;
214 dma_addr_t bf_daddr;
215 dma_addr_t bf_buf_addr;
216};
217
210struct ath_buf_state { 218struct ath_buf_state {
211 u8 bf_type; 219 u8 bf_type;
212 u8 bfs_paprd; 220 u8 bfs_paprd;
@@ -307,7 +315,7 @@ struct ath_rx {
307 struct ath_descdma rxdma; 315 struct ath_descdma rxdma;
308 struct ath_rx_edma rx_edma[ATH9K_RX_QUEUE_MAX]; 316 struct ath_rx_edma rx_edma[ATH9K_RX_QUEUE_MAX];
309 317
310 struct ath_buf *buf_hold; 318 struct ath_rxbuf *buf_hold;
311 struct sk_buff *frag; 319 struct sk_buff *frag;
312 320
313 u32 ampdu_ref; 321 u32 ampdu_ref;
diff --git a/drivers/net/wireless/ath/ath9k/init.c b/drivers/net/wireless/ath/ath9k/init.c
index e3d11c41a145..2306f5788675 100644
--- a/drivers/net/wireless/ath/ath9k/init.c
+++ b/drivers/net/wireless/ath/ath9k/init.c
@@ -347,7 +347,6 @@ int ath_descdma_setup(struct ath_softc *sc, struct ath_descdma *dd,
347{ 347{
348 struct ath_common *common = ath9k_hw_common(sc->sc_ah); 348 struct ath_common *common = ath9k_hw_common(sc->sc_ah);
349 u8 *ds; 349 u8 *ds;
350 struct ath_buf *bf;
351 int i, bsize, desc_len; 350 int i, bsize, desc_len;
352 351
353 ath_dbg(common, CONFIG, "%s DMA: %u buffers %u desc/buf\n", 352 ath_dbg(common, CONFIG, "%s DMA: %u buffers %u desc/buf\n",
@@ -399,33 +398,68 @@ int ath_descdma_setup(struct ath_softc *sc, struct ath_descdma *dd,
399 ito64(dd->dd_desc_paddr), /*XXX*/(u32) dd->dd_desc_len); 398 ito64(dd->dd_desc_paddr), /*XXX*/(u32) dd->dd_desc_len);
400 399
401 /* allocate buffers */ 400 /* allocate buffers */
402 bsize = sizeof(struct ath_buf) * nbuf; 401 if (is_tx) {
403 bf = devm_kzalloc(sc->dev, bsize, GFP_KERNEL); 402 struct ath_buf *bf;
404 if (!bf) 403
405 return -ENOMEM; 404 bsize = sizeof(struct ath_buf) * nbuf;
405 bf = devm_kzalloc(sc->dev, bsize, GFP_KERNEL);
406 if (!bf)
407 return -ENOMEM;
408
409 for (i = 0; i < nbuf; i++, bf++, ds += (desc_len * ndesc)) {
410 bf->bf_desc = ds;
411 bf->bf_daddr = DS2PHYS(dd, ds);
412
413 if (!(sc->sc_ah->caps.hw_caps &
414 ATH9K_HW_CAP_4KB_SPLITTRANS)) {
415 /*
416 * Skip descriptor addresses which can cause 4KB
417 * boundary crossing (addr + length) with a 32 dword
418 * descriptor fetch.
419 */
420 while (ATH_DESC_4KB_BOUND_CHECK(bf->bf_daddr)) {
421 BUG_ON((caddr_t) bf->bf_desc >=
422 ((caddr_t) dd->dd_desc +
423 dd->dd_desc_len));
424
425 ds += (desc_len * ndesc);
426 bf->bf_desc = ds;
427 bf->bf_daddr = DS2PHYS(dd, ds);
428 }
429 }
430 list_add_tail(&bf->list, head);
431 }
432 } else {
433 struct ath_rxbuf *bf;
434
435 bsize = sizeof(struct ath_rxbuf) * nbuf;
436 bf = devm_kzalloc(sc->dev, bsize, GFP_KERNEL);
437 if (!bf)
438 return -ENOMEM;
406 439
407 for (i = 0; i < nbuf; i++, bf++, ds += (desc_len * ndesc)) { 440 for (i = 0; i < nbuf; i++, bf++, ds += (desc_len * ndesc)) {
408 bf->bf_desc = ds; 441 bf->bf_desc = ds;
409 bf->bf_daddr = DS2PHYS(dd, ds); 442 bf->bf_daddr = DS2PHYS(dd, ds);
410 443
411 if (!(sc->sc_ah->caps.hw_caps & 444 if (!(sc->sc_ah->caps.hw_caps &
412 ATH9K_HW_CAP_4KB_SPLITTRANS)) { 445 ATH9K_HW_CAP_4KB_SPLITTRANS)) {
413 /* 446 /*
414 * Skip descriptor addresses which can cause 4KB 447 * Skip descriptor addresses which can cause 4KB
415 * boundary crossing (addr + length) with a 32 dword 448 * boundary crossing (addr + length) with a 32 dword
416 * descriptor fetch. 449 * descriptor fetch.
417 */ 450 */
418 while (ATH_DESC_4KB_BOUND_CHECK(bf->bf_daddr)) { 451 while (ATH_DESC_4KB_BOUND_CHECK(bf->bf_daddr)) {
419 BUG_ON((caddr_t) bf->bf_desc >= 452 BUG_ON((caddr_t) bf->bf_desc >=
420 ((caddr_t) dd->dd_desc + 453 ((caddr_t) dd->dd_desc +
421 dd->dd_desc_len)); 454 dd->dd_desc_len));
422 455
423 ds += (desc_len * ndesc); 456 ds += (desc_len * ndesc);
424 bf->bf_desc = ds; 457 bf->bf_desc = ds;
425 bf->bf_daddr = DS2PHYS(dd, ds); 458 bf->bf_daddr = DS2PHYS(dd, ds);
459 }
426 } 460 }
461 list_add_tail(&bf->list, head);
427 } 462 }
428 list_add_tail(&bf->list, head);
429 } 463 }
430 return 0; 464 return 0;
431} 465}
diff --git a/drivers/net/wireless/ath/ath9k/recv.c b/drivers/net/wireless/ath/ath9k/recv.c
index 4ee472a5a4e4..a05164166de8 100644
--- a/drivers/net/wireless/ath/ath9k/recv.c
+++ b/drivers/net/wireless/ath/ath9k/recv.c
@@ -19,7 +19,7 @@
19#include "ath9k.h" 19#include "ath9k.h"
20#include "ar9003_mac.h" 20#include "ar9003_mac.h"
21 21
22#define SKB_CB_ATHBUF(__skb) (*((struct ath_buf **)__skb->cb)) 22#define SKB_CB_ATHBUF(__skb) (*((struct ath_rxbuf **)__skb->cb))
23 23
24static inline bool ath9k_check_auto_sleep(struct ath_softc *sc) 24static inline bool ath9k_check_auto_sleep(struct ath_softc *sc)
25{ 25{
@@ -35,7 +35,7 @@ static inline bool ath9k_check_auto_sleep(struct ath_softc *sc)
35 * buffer (or rx fifo). This can incorrectly acknowledge packets 35 * buffer (or rx fifo). This can incorrectly acknowledge packets
36 * to a sender if last desc is self-linked. 36 * to a sender if last desc is self-linked.
37 */ 37 */
38static void ath_rx_buf_link(struct ath_softc *sc, struct ath_buf *bf) 38static void ath_rx_buf_link(struct ath_softc *sc, struct ath_rxbuf *bf)
39{ 39{
40 struct ath_hw *ah = sc->sc_ah; 40 struct ath_hw *ah = sc->sc_ah;
41 struct ath_common *common = ath9k_hw_common(ah); 41 struct ath_common *common = ath9k_hw_common(ah);
@@ -68,7 +68,7 @@ static void ath_rx_buf_link(struct ath_softc *sc, struct ath_buf *bf)
68 sc->rx.rxlink = &ds->ds_link; 68 sc->rx.rxlink = &ds->ds_link;
69} 69}
70 70
71static void ath_rx_buf_relink(struct ath_softc *sc, struct ath_buf *bf) 71static void ath_rx_buf_relink(struct ath_softc *sc, struct ath_rxbuf *bf)
72{ 72{
73 if (sc->rx.buf_hold) 73 if (sc->rx.buf_hold)
74 ath_rx_buf_link(sc, sc->rx.buf_hold); 74 ath_rx_buf_link(sc, sc->rx.buf_hold);
@@ -112,13 +112,13 @@ static bool ath_rx_edma_buf_link(struct ath_softc *sc,
112 struct ath_hw *ah = sc->sc_ah; 112 struct ath_hw *ah = sc->sc_ah;
113 struct ath_rx_edma *rx_edma; 113 struct ath_rx_edma *rx_edma;
114 struct sk_buff *skb; 114 struct sk_buff *skb;
115 struct ath_buf *bf; 115 struct ath_rxbuf *bf;
116 116
117 rx_edma = &sc->rx.rx_edma[qtype]; 117 rx_edma = &sc->rx.rx_edma[qtype];
118 if (skb_queue_len(&rx_edma->rx_fifo) >= rx_edma->rx_fifo_hwsize) 118 if (skb_queue_len(&rx_edma->rx_fifo) >= rx_edma->rx_fifo_hwsize)
119 return false; 119 return false;
120 120
121 bf = list_first_entry(&sc->rx.rxbuf, struct ath_buf, list); 121 bf = list_first_entry(&sc->rx.rxbuf, struct ath_rxbuf, list);
122 list_del_init(&bf->list); 122 list_del_init(&bf->list);
123 123
124 skb = bf->bf_mpdu; 124 skb = bf->bf_mpdu;
@@ -138,7 +138,7 @@ static void ath_rx_addbuffer_edma(struct ath_softc *sc,
138 enum ath9k_rx_qtype qtype) 138 enum ath9k_rx_qtype qtype)
139{ 139{
140 struct ath_common *common = ath9k_hw_common(sc->sc_ah); 140 struct ath_common *common = ath9k_hw_common(sc->sc_ah);
141 struct ath_buf *bf, *tbf; 141 struct ath_rxbuf *bf, *tbf;
142 142
143 if (list_empty(&sc->rx.rxbuf)) { 143 if (list_empty(&sc->rx.rxbuf)) {
144 ath_dbg(common, QUEUE, "No free rx buf available\n"); 144 ath_dbg(common, QUEUE, "No free rx buf available\n");
@@ -154,7 +154,7 @@ static void ath_rx_addbuffer_edma(struct ath_softc *sc,
154static void ath_rx_remove_buffer(struct ath_softc *sc, 154static void ath_rx_remove_buffer(struct ath_softc *sc,
155 enum ath9k_rx_qtype qtype) 155 enum ath9k_rx_qtype qtype)
156{ 156{
157 struct ath_buf *bf; 157 struct ath_rxbuf *bf;
158 struct ath_rx_edma *rx_edma; 158 struct ath_rx_edma *rx_edma;
159 struct sk_buff *skb; 159 struct sk_buff *skb;
160 160
@@ -171,7 +171,7 @@ static void ath_rx_edma_cleanup(struct ath_softc *sc)
171{ 171{
172 struct ath_hw *ah = sc->sc_ah; 172 struct ath_hw *ah = sc->sc_ah;
173 struct ath_common *common = ath9k_hw_common(ah); 173 struct ath_common *common = ath9k_hw_common(ah);
174 struct ath_buf *bf; 174 struct ath_rxbuf *bf;
175 175
176 ath_rx_remove_buffer(sc, ATH9K_RX_QUEUE_LP); 176 ath_rx_remove_buffer(sc, ATH9K_RX_QUEUE_LP);
177 ath_rx_remove_buffer(sc, ATH9K_RX_QUEUE_HP); 177 ath_rx_remove_buffer(sc, ATH9K_RX_QUEUE_HP);
@@ -199,7 +199,7 @@ static int ath_rx_edma_init(struct ath_softc *sc, int nbufs)
199 struct ath_common *common = ath9k_hw_common(sc->sc_ah); 199 struct ath_common *common = ath9k_hw_common(sc->sc_ah);
200 struct ath_hw *ah = sc->sc_ah; 200 struct ath_hw *ah = sc->sc_ah;
201 struct sk_buff *skb; 201 struct sk_buff *skb;
202 struct ath_buf *bf; 202 struct ath_rxbuf *bf;
203 int error = 0, i; 203 int error = 0, i;
204 u32 size; 204 u32 size;
205 205
@@ -211,7 +211,7 @@ static int ath_rx_edma_init(struct ath_softc *sc, int nbufs)
211 ath_rx_edma_init_queue(&sc->rx.rx_edma[ATH9K_RX_QUEUE_HP], 211 ath_rx_edma_init_queue(&sc->rx.rx_edma[ATH9K_RX_QUEUE_HP],
212 ah->caps.rx_hp_qdepth); 212 ah->caps.rx_hp_qdepth);
213 213
214 size = sizeof(struct ath_buf) * nbufs; 214 size = sizeof(struct ath_rxbuf) * nbufs;
215 bf = devm_kzalloc(sc->dev, size, GFP_KERNEL); 215 bf = devm_kzalloc(sc->dev, size, GFP_KERNEL);
216 if (!bf) 216 if (!bf)
217 return -ENOMEM; 217 return -ENOMEM;
@@ -271,7 +271,7 @@ int ath_rx_init(struct ath_softc *sc, int nbufs)
271{ 271{
272 struct ath_common *common = ath9k_hw_common(sc->sc_ah); 272 struct ath_common *common = ath9k_hw_common(sc->sc_ah);
273 struct sk_buff *skb; 273 struct sk_buff *skb;
274 struct ath_buf *bf; 274 struct ath_rxbuf *bf;
275 int error = 0; 275 int error = 0;
276 276
277 spin_lock_init(&sc->sc_pcu_lock); 277 spin_lock_init(&sc->sc_pcu_lock);
@@ -332,7 +332,7 @@ void ath_rx_cleanup(struct ath_softc *sc)
332 struct ath_hw *ah = sc->sc_ah; 332 struct ath_hw *ah = sc->sc_ah;
333 struct ath_common *common = ath9k_hw_common(ah); 333 struct ath_common *common = ath9k_hw_common(ah);
334 struct sk_buff *skb; 334 struct sk_buff *skb;
335 struct ath_buf *bf; 335 struct ath_rxbuf *bf;
336 336
337 if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) { 337 if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) {
338 ath_rx_edma_cleanup(sc); 338 ath_rx_edma_cleanup(sc);
@@ -427,7 +427,7 @@ u32 ath_calcrxfilter(struct ath_softc *sc)
427int ath_startrecv(struct ath_softc *sc) 427int ath_startrecv(struct ath_softc *sc)
428{ 428{
429 struct ath_hw *ah = sc->sc_ah; 429 struct ath_hw *ah = sc->sc_ah;
430 struct ath_buf *bf, *tbf; 430 struct ath_rxbuf *bf, *tbf;
431 431
432 if (ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) { 432 if (ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) {
433 ath_edma_start_recv(sc); 433 ath_edma_start_recv(sc);
@@ -447,7 +447,7 @@ int ath_startrecv(struct ath_softc *sc)
447 if (list_empty(&sc->rx.rxbuf)) 447 if (list_empty(&sc->rx.rxbuf))
448 goto start_recv; 448 goto start_recv;
449 449
450 bf = list_first_entry(&sc->rx.rxbuf, struct ath_buf, list); 450 bf = list_first_entry(&sc->rx.rxbuf, struct ath_rxbuf, list);
451 ath9k_hw_putrxbuf(ah, bf->bf_daddr); 451 ath9k_hw_putrxbuf(ah, bf->bf_daddr);
452 ath9k_hw_rxena(ah); 452 ath9k_hw_rxena(ah);
453 453
@@ -603,13 +603,13 @@ static void ath_rx_ps(struct ath_softc *sc, struct sk_buff *skb, bool mybeacon)
603static bool ath_edma_get_buffers(struct ath_softc *sc, 603static bool ath_edma_get_buffers(struct ath_softc *sc,
604 enum ath9k_rx_qtype qtype, 604 enum ath9k_rx_qtype qtype,
605 struct ath_rx_status *rs, 605 struct ath_rx_status *rs,
606 struct ath_buf **dest) 606 struct ath_rxbuf **dest)
607{ 607{
608 struct ath_rx_edma *rx_edma = &sc->rx.rx_edma[qtype]; 608 struct ath_rx_edma *rx_edma = &sc->rx.rx_edma[qtype];
609 struct ath_hw *ah = sc->sc_ah; 609 struct ath_hw *ah = sc->sc_ah;
610 struct ath_common *common = ath9k_hw_common(ah); 610 struct ath_common *common = ath9k_hw_common(ah);
611 struct sk_buff *skb; 611 struct sk_buff *skb;
612 struct ath_buf *bf; 612 struct ath_rxbuf *bf;
613 int ret; 613 int ret;
614 614
615 skb = skb_peek(&rx_edma->rx_fifo); 615 skb = skb_peek(&rx_edma->rx_fifo);
@@ -653,11 +653,11 @@ static bool ath_edma_get_buffers(struct ath_softc *sc,
653 return true; 653 return true;
654} 654}
655 655
656static struct ath_buf *ath_edma_get_next_rx_buf(struct ath_softc *sc, 656static struct ath_rxbuf *ath_edma_get_next_rx_buf(struct ath_softc *sc,
657 struct ath_rx_status *rs, 657 struct ath_rx_status *rs,
658 enum ath9k_rx_qtype qtype) 658 enum ath9k_rx_qtype qtype)
659{ 659{
660 struct ath_buf *bf = NULL; 660 struct ath_rxbuf *bf = NULL;
661 661
662 while (ath_edma_get_buffers(sc, qtype, rs, &bf)) { 662 while (ath_edma_get_buffers(sc, qtype, rs, &bf)) {
663 if (!bf) 663 if (!bf)
@@ -668,13 +668,13 @@ static struct ath_buf *ath_edma_get_next_rx_buf(struct ath_softc *sc,
668 return NULL; 668 return NULL;
669} 669}
670 670
671static struct ath_buf *ath_get_next_rx_buf(struct ath_softc *sc, 671static struct ath_rxbuf *ath_get_next_rx_buf(struct ath_softc *sc,
672 struct ath_rx_status *rs) 672 struct ath_rx_status *rs)
673{ 673{
674 struct ath_hw *ah = sc->sc_ah; 674 struct ath_hw *ah = sc->sc_ah;
675 struct ath_common *common = ath9k_hw_common(ah); 675 struct ath_common *common = ath9k_hw_common(ah);
676 struct ath_desc *ds; 676 struct ath_desc *ds;
677 struct ath_buf *bf; 677 struct ath_rxbuf *bf;
678 int ret; 678 int ret;
679 679
680 if (list_empty(&sc->rx.rxbuf)) { 680 if (list_empty(&sc->rx.rxbuf)) {
@@ -682,7 +682,7 @@ static struct ath_buf *ath_get_next_rx_buf(struct ath_softc *sc,
682 return NULL; 682 return NULL;
683 } 683 }
684 684
685 bf = list_first_entry(&sc->rx.rxbuf, struct ath_buf, list); 685 bf = list_first_entry(&sc->rx.rxbuf, struct ath_rxbuf, list);
686 if (bf == sc->rx.buf_hold) 686 if (bf == sc->rx.buf_hold)
687 return NULL; 687 return NULL;
688 688
@@ -702,7 +702,7 @@ static struct ath_buf *ath_get_next_rx_buf(struct ath_softc *sc,
702 ret = ath9k_hw_rxprocdesc(ah, ds, rs); 702 ret = ath9k_hw_rxprocdesc(ah, ds, rs);
703 if (ret == -EINPROGRESS) { 703 if (ret == -EINPROGRESS) {
704 struct ath_rx_status trs; 704 struct ath_rx_status trs;
705 struct ath_buf *tbf; 705 struct ath_rxbuf *tbf;
706 struct ath_desc *tds; 706 struct ath_desc *tds;
707 707
708 memset(&trs, 0, sizeof(trs)); 708 memset(&trs, 0, sizeof(trs));
@@ -711,7 +711,7 @@ static struct ath_buf *ath_get_next_rx_buf(struct ath_softc *sc,
711 return NULL; 711 return NULL;
712 } 712 }
713 713
714 tbf = list_entry(bf->list.next, struct ath_buf, list); 714 tbf = list_entry(bf->list.next, struct ath_rxbuf, list);
715 715
716 /* 716 /*
717 * On some hardware the descriptor status words could 717 * On some hardware the descriptor status words could
@@ -1315,7 +1315,7 @@ static void ath9k_apply_ampdu_details(struct ath_softc *sc,
1315 1315
1316int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp) 1316int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp)
1317{ 1317{
1318 struct ath_buf *bf; 1318 struct ath_rxbuf *bf;
1319 struct sk_buff *skb = NULL, *requeue_skb, *hdr_skb; 1319 struct sk_buff *skb = NULL, *requeue_skb, *hdr_skb;
1320 struct ieee80211_rx_status *rxs; 1320 struct ieee80211_rx_status *rxs;
1321 struct ath_hw *ah = sc->sc_ah; 1321 struct ath_hw *ah = sc->sc_ah;