aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLuis R. Rodriguez <lrodriguez@atheros.com>2009-08-12 12:56:59 -0400
committerJohn W. Linville <linville@tuxdriver.com>2009-08-14 09:14:05 -0400
commitd15dd3e5d74186a3b0a4db271b440bbdc0f6da36 (patch)
tree782cad60e7caa4330f23ef141cc2aec25663097e
parent5ef5da0ff2fc4f04c856f4ce9a757e318a02ad06 (diff)
ath: add common ath_rxbuf_alloc() and make ath9k use it
Turns out ath5k and ath9k can share the same helper to allocates RX skbs. We allocate skbs aligned to the cache line size. This requirement seems to have come from AR5210; when this was not done it seems sometimes we'd get bogus data. I'm also told it may have been a performance enhancement consideration. In the end I can't be sure we can remove this on new hardware so just keep this and start sharing it through ath.ko. Make ath9k start using this, ath5k is next. Signed-off-by: Luis R. Rodriguez <lrodriguez@atheros.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
-rw-r--r--drivers/net/wireless/ath/Kconfig4
-rw-r--r--drivers/net/wireless/ath/ath.h30
-rw-r--r--drivers/net/wireless/ath/ath9k/ath9k.h4
-rw-r--r--drivers/net/wireless/ath/ath9k/main.c2
-rw-r--r--drivers/net/wireless/ath/ath9k/recv.c40
-rw-r--r--drivers/net/wireless/ath/main.c36
6 files changed, 75 insertions, 41 deletions
diff --git a/drivers/net/wireless/ath/Kconfig b/drivers/net/wireless/ath/Kconfig
index 253b95a264b1..11ded150b932 100644
--- a/drivers/net/wireless/ath/Kconfig
+++ b/drivers/net/wireless/ath/Kconfig
@@ -5,9 +5,7 @@ menuconfig ATH_COMMON
5 ---help--- 5 ---help---
6 This will enable the support for the Atheros wireless drivers. 6 This will enable the support for the Atheros wireless drivers.
7 ath5k, ath9k and ar9170 drivers share some common code, this option 7 ath5k, ath9k and ar9170 drivers share some common code, this option
8 enables the common ath.ko module which currently shares just common 8 enables the common ath.ko module which shares common helpers.
9 regulatory EEPROM helpers but will likely be extended later to share
10 more between modules.
11 9
12 For more information and documentation on this module you can visit: 10 For more information and documentation on this module you can visit:
13 11
diff --git a/drivers/net/wireless/ath/ath.h b/drivers/net/wireless/ath/ath.h
new file mode 100644
index 000000000000..e284cd3ac6d4
--- /dev/null
+++ b/drivers/net/wireless/ath/ath.h
@@ -0,0 +1,30 @@
1/*
2 * Copyright (c) 2008-2009 Atheros Communications Inc.
3 *
4 * Permission to use, copy, modify, and/or distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
7 *
8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15 */
16
17#ifndef ATH_H
18#define ATH_H
19
20#include <linux/skbuff.h>
21
22struct ath_common {
23 u16 cachelsz;
24};
25
26struct sk_buff *ath_rxbuf_alloc(struct ath_common *common,
27 u32 len,
28 gfp_t gfp_mask);
29
30#endif /* ATH_H */
diff --git a/drivers/net/wireless/ath/ath9k/ath9k.h b/drivers/net/wireless/ath/ath9k/ath9k.h
index 7a5a157e15c4..2fd663c01b8e 100644
--- a/drivers/net/wireless/ath/ath9k/ath9k.h
+++ b/drivers/net/wireless/ath/ath9k/ath9k.h
@@ -25,6 +25,7 @@
25#include "hw.h" 25#include "hw.h"
26#include "rc.h" 26#include "rc.h"
27#include "debug.h" 27#include "debug.h"
28#include "../ath.h"
28 29
29struct ath_node; 30struct ath_node;
30 31
@@ -532,6 +533,8 @@ struct ath_softc {
532 struct ieee80211_hw *hw; 533 struct ieee80211_hw *hw;
533 struct device *dev; 534 struct device *dev;
534 535
536 struct ath_common common;
537
535 spinlock_t wiphy_lock; /* spinlock to protect ath_wiphy data */ 538 spinlock_t wiphy_lock; /* spinlock to protect ath_wiphy data */
536 struct ath_wiphy *pri_wiphy; 539 struct ath_wiphy *pri_wiphy;
537 struct ath_wiphy **sec_wiphy; /* secondary wiphys (virtual radios); may 540 struct ath_wiphy **sec_wiphy; /* secondary wiphys (virtual radios); may
@@ -564,7 +567,6 @@ struct ath_softc {
564 u32 sc_flags; /* SC_OP_* */ 567 u32 sc_flags; /* SC_OP_* */
565 u16 curtxpow; 568 u16 curtxpow;
566 u16 curaid; 569 u16 curaid;
567 u16 cachelsz;
568 u8 nbcnvifs; 570 u8 nbcnvifs;
569 u16 nvifs; 571 u16 nvifs;
570 u8 tx_chainmask; 572 u8 tx_chainmask;
diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c
index efe2e856397c..b29d0ff74514 100644
--- a/drivers/net/wireless/ath/ath9k/main.c
+++ b/drivers/net/wireless/ath/ath9k/main.c
@@ -1327,7 +1327,7 @@ static int ath_init_softc(u16 devid, struct ath_softc *sc)
1327 */ 1327 */
1328 ath_read_cachesize(sc, &csz); 1328 ath_read_cachesize(sc, &csz);
1329 /* XXX assert csz is non-zero */ 1329 /* XXX assert csz is non-zero */
1330 sc->cachelsz = csz << 2; /* convert to bytes */ 1330 sc->common.cachelsz = csz << 2; /* convert to bytes */
1331 1331
1332 ah = kzalloc(sizeof(struct ath_hw), GFP_KERNEL); 1332 ah = kzalloc(sizeof(struct ath_hw), GFP_KERNEL);
1333 if (!ah) { 1333 if (!ah) {
diff --git a/drivers/net/wireless/ath/ath9k/recv.c b/drivers/net/wireless/ath/ath9k/recv.c
index 1a08c694fe5d..61dbdd227444 100644
--- a/drivers/net/wireless/ath/ath9k/recv.c
+++ b/drivers/net/wireless/ath/ath9k/recv.c
@@ -100,38 +100,6 @@ static u64 ath_extend_tsf(struct ath_softc *sc, u32 rstamp)
100 return (tsf & ~0x7fff) | rstamp; 100 return (tsf & ~0x7fff) | rstamp;
101} 101}
102 102
103static struct sk_buff *ath_rxbuf_alloc(struct ath_softc *sc, u32 len, gfp_t gfp_mask)
104{
105 struct sk_buff *skb;
106 u32 off;
107
108 /*
109 * Cache-line-align. This is important (for the
110 * 5210 at least) as not doing so causes bogus data
111 * in rx'd frames.
112 */
113
114 /* Note: the kernel can allocate a value greater than
115 * what we ask it to give us. We really only need 4 KB as that
116 * is this hardware supports and in fact we need at least 3849
117 * as that is the MAX AMSDU size this hardware supports.
118 * Unfortunately this means we may get 8 KB here from the
119 * kernel... and that is actually what is observed on some
120 * systems :( */
121 skb = __dev_alloc_skb(len + sc->cachelsz - 1, gfp_mask);
122 if (skb != NULL) {
123 off = ((unsigned long) skb->data) % sc->cachelsz;
124 if (off != 0)
125 skb_reserve(skb, sc->cachelsz - off);
126 } else {
127 DPRINTF(sc, ATH_DBG_FATAL,
128 "skbuff alloc of size %u failed\n", len);
129 return NULL;
130 }
131
132 return skb;
133}
134
135/* 103/*
136 * For Decrypt or Demic errors, we only mark packet status here and always push 104 * For Decrypt or Demic errors, we only mark packet status here and always push
137 * up the frame up to let mac80211 handle the actual error case, be it no 105 * up the frame up to let mac80211 handle the actual error case, be it no
@@ -336,10 +304,10 @@ int ath_rx_init(struct ath_softc *sc, int nbufs)
336 spin_lock_init(&sc->rx.rxbuflock); 304 spin_lock_init(&sc->rx.rxbuflock);
337 305
338 sc->rx.bufsize = roundup(IEEE80211_MAX_MPDU_LEN, 306 sc->rx.bufsize = roundup(IEEE80211_MAX_MPDU_LEN,
339 min(sc->cachelsz, (u16)64)); 307 min(sc->common.cachelsz, (u16)64));
340 308
341 DPRINTF(sc, ATH_DBG_CONFIG, "cachelsz %u rxbufsize %u\n", 309 DPRINTF(sc, ATH_DBG_CONFIG, "cachelsz %u rxbufsize %u\n",
342 sc->cachelsz, sc->rx.bufsize); 310 sc->common.cachelsz, sc->rx.bufsize);
343 311
344 /* Initialize rx descriptors */ 312 /* Initialize rx descriptors */
345 313
@@ -352,7 +320,7 @@ int ath_rx_init(struct ath_softc *sc, int nbufs)
352 } 320 }
353 321
354 list_for_each_entry(bf, &sc->rx.rxbuf, list) { 322 list_for_each_entry(bf, &sc->rx.rxbuf, list) {
355 skb = ath_rxbuf_alloc(sc, sc->rx.bufsize, GFP_KERNEL); 323 skb = ath_rxbuf_alloc(&sc->common, sc->rx.bufsize, GFP_KERNEL);
356 if (skb == NULL) { 324 if (skb == NULL) {
357 error = -ENOMEM; 325 error = -ENOMEM;
358 goto err; 326 goto err;
@@ -777,7 +745,7 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush)
777 745
778 /* Ensure we always have an skb to requeue once we are done 746 /* Ensure we always have an skb to requeue once we are done
779 * processing the current buffer's skb */ 747 * processing the current buffer's skb */
780 requeue_skb = ath_rxbuf_alloc(sc, sc->rx.bufsize, GFP_ATOMIC); 748 requeue_skb = ath_rxbuf_alloc(&sc->common, sc->rx.bufsize, GFP_ATOMIC);
781 749
782 /* If there is no memory we ignore the current RX'd frame, 750 /* If there is no memory we ignore the current RX'd frame,
783 * tell hardware it can give us a new frame using the old 751 * tell hardware it can give us a new frame using the old
diff --git a/drivers/net/wireless/ath/main.c b/drivers/net/wireless/ath/main.c
index 9949b11cb151..487193f1de1a 100644
--- a/drivers/net/wireless/ath/main.c
+++ b/drivers/net/wireless/ath/main.c
@@ -17,6 +17,42 @@
17#include <linux/kernel.h> 17#include <linux/kernel.h>
18#include <linux/module.h> 18#include <linux/module.h>
19 19
20#include "ath.h"
21
20MODULE_AUTHOR("Atheros Communications"); 22MODULE_AUTHOR("Atheros Communications");
21MODULE_DESCRIPTION("Shared library for Atheros wireless LAN cards."); 23MODULE_DESCRIPTION("Shared library for Atheros wireless LAN cards.");
22MODULE_LICENSE("Dual BSD/GPL"); 24MODULE_LICENSE("Dual BSD/GPL");
25
26struct sk_buff *ath_rxbuf_alloc(struct ath_common *common,
27 u32 len,
28 gfp_t gfp_mask)
29{
30 struct sk_buff *skb;
31 u32 off;
32
33 /*
34 * Cache-line-align. This is important (for the
35 * 5210 at least) as not doing so causes bogus data
36 * in rx'd frames.
37 */
38
39 /* Note: the kernel can allocate a value greater than
40 * what we ask it to give us. We really only need 4 KB as that
41 * is this hardware supports and in fact we need at least 3849
42 * as that is the MAX AMSDU size this hardware supports.
43 * Unfortunately this means we may get 8 KB here from the
44 * kernel... and that is actually what is observed on some
45 * systems :( */
46 skb = __dev_alloc_skb(len + common->cachelsz - 1, gfp_mask);
47 if (skb != NULL) {
48 off = ((unsigned long) skb->data) % common->cachelsz;
49 if (off != 0)
50 skb_reserve(skb, common->cachelsz - off);
51 } else {
52 printk(KERN_ERR "skbuff alloc of size %u failed\n", len);
53 return NULL;
54 }
55
56 return skb;
57}
58EXPORT_SYMBOL(ath_rxbuf_alloc);