diff --git a/drivers/net/wireless/ath/Kconfig b/drivers/net/wireless/ath/Kconfig
index 253b95a264b1c99775a513e4462842e79d120f16..11ded150b932e0ca30792200708d1f5703aa6f22 100644
--- a/drivers/net/wireless/ath/Kconfig
+++ b/drivers/net/wireless/ath/Kconfig
@@ -5,9 +5,7 @@ menuconfig ATH_COMMON
 	---help---
 	  This will enable the support for the Atheros wireless drivers.
 	  ath5k, ath9k and ar9170 drivers share some common code, this option
-	  enables the common ath.ko module which currently shares just common
-	  regulatory EEPROM helpers but will likely be extended later to share
-	  more between modules.
+	  enables the common ath.ko module which shares common helpers.
 
 	  For more information and documentation on this module you can visit:
 
diff --git a/drivers/net/wireless/ath/ath.h b/drivers/net/wireless/ath/ath.h
new file mode 100644
index 0000000000000000000000000000000000000000..e284cd3ac6d41894f65f54a7e1f63bce87de0b01
--- /dev/null
+++ b/drivers/net/wireless/ath/ath.h
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2008-2009 Atheros Communications Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef ATH_H
+#define ATH_H
+
+#include <linux/skbuff.h>
+
+struct ath_common {
+	u16 cachelsz;
+};
+
+struct sk_buff *ath_rxbuf_alloc(struct ath_common *common,
+				u32 len,
+				gfp_t gfp_mask);
+
+#endif /* ATH_H */
diff --git a/drivers/net/wireless/ath/ath9k/ath9k.h b/drivers/net/wireless/ath/ath9k/ath9k.h
index 7a5a157e15c458418522516fe5f6a5887d6bc31b..2fd663c01b8ed476ccbd4afe08b91a6a5d480464 100644
--- a/drivers/net/wireless/ath/ath9k/ath9k.h
+++ b/drivers/net/wireless/ath/ath9k/ath9k.h
@@ -25,6 +25,7 @@
 #include "hw.h"
 #include "rc.h"
 #include "debug.h"
+#include "../ath.h"
 
 struct ath_node;
 
@@ -532,6 +533,8 @@ struct ath_softc {
 	struct ieee80211_hw *hw;
 	struct device *dev;
 
+	struct ath_common common;
+
 	spinlock_t wiphy_lock; /* spinlock to protect ath_wiphy data */
 	struct ath_wiphy *pri_wiphy;
 	struct ath_wiphy **sec_wiphy; /* secondary wiphys (virtual radios); may
@@ -564,7 +567,6 @@ struct ath_softc {
 	u32 sc_flags; /* SC_OP_* */
 	u16 curtxpow;
 	u16 curaid;
-	u16 cachelsz;
 	u8 nbcnvifs;
 	u16 nvifs;
 	u8 tx_chainmask;
diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c
index efe2e856397cf33e80645577bc18e1207ec74f94..b29d0ff74514eb250f86259c05f460ff09106963 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)
 	 */
 	ath_read_cachesize(sc, &csz);
 	/* XXX assert csz is non-zero */
-	sc->cachelsz = csz << 2;	/* convert to bytes */
+	sc->common.cachelsz = csz << 2;	/* convert to bytes */
 
 	ah = kzalloc(sizeof(struct ath_hw), GFP_KERNEL);
 	if (!ah) {
diff --git a/drivers/net/wireless/ath/ath9k/recv.c b/drivers/net/wireless/ath/ath9k/recv.c
index 1a08c694fe5d0edcdbf4b4fceb2643ddc0f1ba51..61dbdd22744452d5a03999aa7b0ac9f7bdabcede 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)
 	return (tsf & ~0x7fff) | rstamp;
 }
 
-static struct sk_buff *ath_rxbuf_alloc(struct ath_softc *sc, u32 len, gfp_t gfp_mask)
-{
-	struct sk_buff *skb;
-	u32 off;
-
-	/*
-	 * Cache-line-align.  This is important (for the
-	 * 5210 at least) as not doing so causes bogus data
-	 * in rx'd frames.
-	 */
-
-	/* Note: the kernel can allocate a value greater than
-	 * what we ask it to give us. We really only need 4 KB as that
-	 * is this hardware supports and in fact we need at least 3849
-	 * as that is the MAX AMSDU size this hardware supports.
-	 * Unfortunately this means we may get 8 KB here from the
-	 * kernel... and that is actually what is observed on some
-	 * systems :( */
-	skb = __dev_alloc_skb(len + sc->cachelsz - 1, gfp_mask);
-	if (skb != NULL) {
-		off = ((unsigned long) skb->data) % sc->cachelsz;
-		if (off != 0)
-			skb_reserve(skb, sc->cachelsz - off);
-	} else {
-		DPRINTF(sc, ATH_DBG_FATAL,
-			"skbuff alloc of size %u failed\n", len);
-		return NULL;
-	}
-
-	return skb;
-}
-
 /*
  * For Decrypt or Demic errors, we only mark packet status here and always push
  * 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)
 	spin_lock_init(&sc->rx.rxbuflock);
 
 	sc->rx.bufsize = roundup(IEEE80211_MAX_MPDU_LEN,
-				 min(sc->cachelsz, (u16)64));
+				 min(sc->common.cachelsz, (u16)64));
 
 	DPRINTF(sc, ATH_DBG_CONFIG, "cachelsz %u rxbufsize %u\n",
-		sc->cachelsz, sc->rx.bufsize);
+		sc->common.cachelsz, sc->rx.bufsize);
 
 	/* Initialize rx descriptors */
 
@@ -352,7 +320,7 @@ int ath_rx_init(struct ath_softc *sc, int nbufs)
 	}
 
 	list_for_each_entry(bf, &sc->rx.rxbuf, list) {
-		skb = ath_rxbuf_alloc(sc, sc->rx.bufsize, GFP_KERNEL);
+		skb = ath_rxbuf_alloc(&sc->common, sc->rx.bufsize, GFP_KERNEL);
 		if (skb == NULL) {
 			error = -ENOMEM;
 			goto err;
@@ -777,7 +745,7 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush)
 
 		/* Ensure we always have an skb to requeue once we are done
 		 * processing the current buffer's skb */
-		requeue_skb = ath_rxbuf_alloc(sc, sc->rx.bufsize, GFP_ATOMIC);
+		requeue_skb = ath_rxbuf_alloc(&sc->common, sc->rx.bufsize, GFP_ATOMIC);
 
 		/* If there is no memory we ignore the current RX'd frame,
 		 * 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 9949b11cb151a32f4ce06d43ed7feb791271f050..487193f1de1a6b0ac70e04dcfd0575a0ac091bb8 100644
--- a/drivers/net/wireless/ath/main.c
+++ b/drivers/net/wireless/ath/main.c
@@ -17,6 +17,42 @@
 #include <linux/kernel.h>
 #include <linux/module.h>
 
+#include "ath.h"
+
 MODULE_AUTHOR("Atheros Communications");
 MODULE_DESCRIPTION("Shared library for Atheros wireless LAN cards.");
 MODULE_LICENSE("Dual BSD/GPL");
+
+struct sk_buff *ath_rxbuf_alloc(struct ath_common *common,
+				u32 len,
+				gfp_t gfp_mask)
+{
+	struct sk_buff *skb;
+	u32 off;
+
+	/*
+	 * Cache-line-align.  This is important (for the
+	 * 5210 at least) as not doing so causes bogus data
+	 * in rx'd frames.
+	 */
+
+	/* Note: the kernel can allocate a value greater than
+	 * what we ask it to give us. We really only need 4 KB as that
+	 * is this hardware supports and in fact we need at least 3849
+	 * as that is the MAX AMSDU size this hardware supports.
+	 * Unfortunately this means we may get 8 KB here from the
+	 * kernel... and that is actually what is observed on some
+	 * systems :( */
+	skb = __dev_alloc_skb(len + common->cachelsz - 1, gfp_mask);
+	if (skb != NULL) {
+		off = ((unsigned long) skb->data) % common->cachelsz;
+		if (off != 0)
+			skb_reserve(skb, common->cachelsz - off);
+	} else {
+		printk(KERN_ERR "skbuff alloc of size %u failed\n", len);
+		return NULL;
+	}
+
+	return skb;
+}
+EXPORT_SYMBOL(ath_rxbuf_alloc);