--- /dev/null
+Index: madwifi-trunk-r3776/ath/if_ath.c
+===================================================================
+--- madwifi-trunk-r3776.orig/ath/if_ath.c 2008-07-17 02:23:00.000000000 +0200
++++ madwifi-trunk-r3776/ath/if_ath.c 2008-07-17 02:28:06.000000000 +0200
+@@ -3334,7 +3334,6 @@
+ struct ath_softc *sc = dev->priv;
+ struct ieee80211_node *ni = NULL;
+ struct ath_buf *bf = NULL;
+- struct ether_header *eh;
+ ath_bufhead bf_head;
+ struct ath_buf *tbf;
+ struct sk_buff *tskb;
+@@ -3349,6 +3348,7 @@
+ */
+ int requeue = 0;
+ #ifdef ATH_SUPERG_FF
++ struct ether_header *eh;
+ unsigned int pktlen;
+ struct ieee80211com *ic = &sc->sc_ic;
+ struct ath_txq *txq = NULL;
+Index: madwifi-trunk-r3776/net80211/ieee80211_output.c
+===================================================================
+--- madwifi-trunk-r3776.orig/net80211/ieee80211_output.c 2008-07-17 00:21:29.000000000 +0200
++++ madwifi-trunk-r3776/net80211/ieee80211_output.c 2008-07-17 02:35:10.000000000 +0200
+@@ -280,7 +280,7 @@
+ * normal vap. */
+ if (vap->iv_xrvap && (ni == vap->iv_bss) &&
+ vap->iv_xrvap->iv_sta_assoc) {
+- struct sk_buff *skb1 = skb_copy(skb, GFP_ATOMIC);
++ struct sk_buff *skb1 = skb_clone(skb, GFP_ATOMIC);
+ if (skb1) {
+ memset(SKB_CB(skb1), 0, sizeof(struct ieee80211_cb));
+ #ifdef IEEE80211_DEBUG_REFCNT
+@@ -561,7 +561,7 @@
+ struct ieee80211_key *key, struct sk_buff *skb, int ismulticast)
+ {
+ /* XXX pre-calculate per node? */
+- int need_headroom = LLC_SNAPFRAMELEN + hdrsize + IEEE80211_ADDR_LEN;
++ int need_headroom = LLC_SNAPFRAMELEN + hdrsize;
+ int need_tailroom = 0;
+ #ifdef ATH_SUPERG_FF
+ int isff = ATH_FF_MAGIC_PRESENT(skb);
+@@ -603,109 +603,56 @@
+ need_tailroom += cip->ic_miclen;
+ }
+
+- if (skb_shared(skb)) {
+- /* Take our own reference to the node in the clone */
+- ieee80211_ref_node(SKB_NI(skb));
+- /* Unshare the node, decrementing users in the old skb */
+- skb = skb_unshare(skb, GFP_ATOMIC);
++ need_headroom -= skb_headroom(skb);
++ if (isff)
++ need_tailroom -= skb_tailroom(skb2);
++ else
++ need_tailroom -= skb_tailroom(skb);
++
++ if (need_headroom < 0)
++ need_headroom = 0;
++ if (need_tailroom < 0)
++ need_tailroom = 0;
++
++ if (skb_cloned(skb) || (need_headroom > 0) ||
++ (!isff && (need_tailroom > 0))) {
++
++ if (pskb_expand_head(skb, need_headroom, need_tailroom, GFP_ATOMIC)) {
++ IEEE80211_DPRINTF(vap, IEEE80211_MSG_OUTPUT,
++ "%s: cannot expand storage (tail)\n", __func__);
++ goto error;
++ }
+ }
+
+ #ifdef ATH_SUPERG_FF
+ if (isff) {
+- if (skb == NULL) {
+- IEEE80211_DPRINTF(vap, IEEE80211_MSG_OUTPUT,
+- "%s: cannot unshare for encapsulation\n",
+- __func__);
+- vap->iv_stats.is_tx_nobuf++;
+- ieee80211_dev_kfree_skb(&skb2);
+-
+- return NULL;
+- }
++ inter_headroom -= skb_headroom(skb2);
++ if (inter_headroom < 0)
++ inter_headroom = 0;
++ if ((skb_cloned(skb2) ||
++ (inter_headroom > 0) || (need_tailroom > 0))) {
+
+- /* first skb header */
+- if (skb_headroom(skb) < need_headroom) {
+- struct sk_buff *tmp = skb;
+- skb = skb_realloc_headroom(skb, need_headroom);
+- if (skb == NULL) {
++ if (pskb_expand_head(skb2, inter_headroom,
++ need_tailroom, GFP_ATOMIC)) {
+ IEEE80211_DPRINTF(vap, IEEE80211_MSG_OUTPUT,
+- "%s: cannot expand storage (head1)\n",
+- __func__);
+- vap->iv_stats.is_tx_nobuf++;
+- ieee80211_dev_kfree_skb(&skb2);
+- return NULL;
+- } else
+- ieee80211_skb_copy_noderef(tmp, skb);
+- ieee80211_dev_kfree_skb(&tmp);
+- /* NB: cb[] area was copied, but not next ptr. must do that
+- * prior to return on success. */
+- }
+-
+- /* second skb with header and tail adjustments possible */
+- if (skb_tailroom(skb2) < need_tailroom) {
+- int n = 0;
+- if (inter_headroom > skb_headroom(skb2))
+- n = inter_headroom - skb_headroom(skb2);
+- if (pskb_expand_head(skb2, n,
+- need_tailroom - skb_tailroom(skb2), GFP_ATOMIC)) {
+- ieee80211_dev_kfree_skb(&skb2);
+- IEEE80211_DPRINTF(vap, IEEE80211_MSG_OUTPUT,
+- "%s: cannot expand storage (tail2)\n",
+- __func__);
+- vap->iv_stats.is_tx_nobuf++;
+- /* this shouldn't happen, but don't send first ff either */
+- ieee80211_dev_kfree_skb(&skb);
++ "%s: cannot expand storage (tail)\n", __func__);
++ goto error;
+ }
+- } else if (skb_headroom(skb2) < inter_headroom) {
+- struct sk_buff *tmp = skb2;
+-
+- skb2 = skb_realloc_headroom(skb2, inter_headroom);
+- if (skb2 == NULL) {
+- IEEE80211_DPRINTF(vap, IEEE80211_MSG_OUTPUT,
+- "%s: cannot expand storage (head2)\n",
+- __func__);
+- vap->iv_stats.is_tx_nobuf++;
+- /* this shouldn't happen, but don't send first ff either */
+- ieee80211_dev_kfree_skb(&skb);
+- skb = NULL;
+- } else
+- ieee80211_skb_copy_noderef(tmp, skb);
+- ieee80211_dev_kfree_skb(&tmp);
+ }
+- if (skb) {
+- skb->next = skb2;
+- }
+- return skb;
++ skb->next = skb2;
+ }
+ #endif /* ATH_SUPERG_FF */
+- if (skb == NULL) {
+- IEEE80211_DPRINTF(vap, IEEE80211_MSG_OUTPUT,
+- "%s: cannot unshare for encapsulation\n", __func__);
+- vap->iv_stats.is_tx_nobuf++;
+- } else if (skb_tailroom(skb) < need_tailroom) {
+- int n = 0;
+- if (need_headroom > skb_headroom(skb))
+- n = need_headroom - skb_headroom(skb);
+- if (pskb_expand_head(skb, n, need_tailroom -
+- skb_tailroom(skb), GFP_ATOMIC)) {
+- IEEE80211_DPRINTF(vap, IEEE80211_MSG_OUTPUT,
+- "%s: cannot expand storage (tail)\n", __func__);
+- vap->iv_stats.is_tx_nobuf++;
+- ieee80211_dev_kfree_skb(&skb);
+- }
+- } else if (skb_headroom(skb) < need_headroom) {
+- struct sk_buff *tmp = skb;
+- skb = skb_realloc_headroom(skb, need_headroom);
+- /* Increment reference count after copy */
+- if (skb == NULL) {
+- IEEE80211_DPRINTF(vap, IEEE80211_MSG_OUTPUT,
+- "%s: cannot expand storage (head)\n", __func__);
+- vap->iv_stats.is_tx_nobuf++;
+- } else
+- ieee80211_skb_copy_noderef(tmp, skb);
+- ieee80211_dev_kfree_skb(&tmp);
+- }
+
+ return skb;
++
++error:
++ vap->iv_stats.is_tx_nobuf++;
++ ieee80211_dev_kfree_skb(&skb);
++#ifdef ATH_SUPERG_FF
++ if (skb2)
++ ieee80211_dev_kfree_skb(&skb2);
++#endif
++ return NULL;
+ }
+
+ #define KEY_UNDEFINED(k) ((k).wk_cipher == &ieee80211_cipher_none)
+Index: madwifi-trunk-r3776/net80211/ieee80211_input.c
+===================================================================
+--- madwifi-trunk-r3776.orig/net80211/ieee80211_input.c 2008-07-17 02:20:52.000000000 +0200
++++ madwifi-trunk-r3776/net80211/ieee80211_input.c 2008-07-17 02:30:28.000000000 +0200
+@@ -713,7 +713,7 @@
+ /* ether_type must be length as FF frames are always LLC/SNAP encap'd */
+ frame_len = ntohs(eh_tmp->ether_type);
+
+- skb1 = skb_copy(skb, GFP_ATOMIC);
++ skb1 = skb_clone(skb, GFP_ATOMIC);
+ if (skb1 == NULL)
+ goto err;
+ ieee80211_skb_copy_noderef(skb, skb1);
+@@ -1118,7 +1118,7 @@
+
+ if (ETHER_IS_MULTICAST(eh->ether_dhost) && !netif_queue_stopped(dev)) {
+ /* Create a SKB for the BSS to send out. */
+- skb1 = skb_copy(skb, GFP_ATOMIC);
++ skb1 = skb_clone(skb, GFP_ATOMIC);
+ if (skb1)
+ SKB_NI(skb1) = ieee80211_ref_node(vap->iv_bss);
+ }
+@@ -2265,7 +2265,7 @@
+ if (filter_type && ((vap->app_filter & filter_type) == filter_type)) {
+ struct sk_buff *skb1;
+
+- skb1 = skb_copy(skb, GFP_ATOMIC);
++ skb1 = skb_clone(skb, GFP_ATOMIC);
+ if (skb1 == NULL)
+ return;
+ /* We duplicate the reference after skb_copy */