When a driver requested additional header room through the extra_tx_headroom field, the stack should respect that and make sure that all frames that are being send to the stack actually have that extra header room.
Signed-off-by Ivo van Doorn <[EMAIL PROTECTED]> --- diff -rU3 dscape/net/d80211/ieee80211.c dscape.hdr/net/d80211/ieee80211.c --- dscape/net/d80211/ieee80211.c 2007-02-05 16:20:04.000000000 +0100 +++ dscape.hdr/net/d80211/ieee80211.c 2007-02-05 16:24:01.000000000 +0100 @@ -472,10 +472,9 @@ /* reserve enough extra head and tail room for possible * encryption */ -#define IEEE80211_ENCRYPT_HEADROOM 8 -#define IEEE80211_ENCRYPT_TAILROOM 12 frag = frags[i] = - dev_alloc_skb(frag_threshold + + dev_alloc_skb(tx->local->hw.extra_tx_headroom + + frag_threshold + IEEE80211_ENCRYPT_HEADROOM + IEEE80211_ENCRYPT_TAILROOM); if (!frag) @@ -483,7 +482,8 @@ /* Make sure that all fragments use the same priority so * that they end up using the same TX queue */ frag->priority = first->priority; - skb_reserve(frag, IEEE80211_ENCRYPT_HEADROOM); + skb_reserve(frag, tx->local->hw.extra_tx_headroom + + IEEE80211_ENCRYPT_HEADROOM); fhdr = (struct ieee80211_hdr *) skb_put(frag, hdrlen); memcpy(fhdr, first->data, hdrlen); if (i == num_fragm - 2) @@ -858,10 +858,13 @@ hdr_len = ieee80211_get_hdrlen(old_hdr->frame_control); - tx->u.tx.rts_frame = dev_alloc_skb(hdr_len); + tx->u.tx.rts_frame = dev_alloc_skb(hdr_len + + tx->local->hw.extra_tx_headroom); if (!tx->u.tx.rts_frame) return TXRX_DROP; + skb_reserve(tx->u.tx.rts_frame, tx->local->hw.extra_tx_headroom); + new_hdr = (struct ieee80211_hdr*)skb_put(tx->u.tx.rts_frame, hdr_len); memcpy(new_hdr, old_hdr, hdr_len); @@ -1427,6 +1430,7 @@ struct ieee80211_tx_packet_data *pkt_data; struct net_device *odev = NULL; struct ieee80211_sub_if_data *osdata; + int headroom; int ret; /* @@ -1451,6 +1455,15 @@ } osdata = IEEE80211_DEV_TO_SUB_IF(odev); + headroom = osdata->local->hw.extra_tx_headroom + + IEEE80211_ENCRYPT_HEADROOM; + if (skb_headroom(skb) < headroom) { + if (pskb_expand_head(skb, headroom, 0, GFP_ATOMIC)) { + dev_kfree_skb(skb); + return 0; + } + } + control.ifindex = odev->ifindex; control.type = osdata->type; if (pkt_data->req_tx_status) @@ -1680,6 +1693,14 @@ return 0; } + if (skb_headroom(skb) < sdata->local->hw.extra_tx_headroom) { + if (pskb_expand_head(skb, + sdata->local->hw.extra_tx_headroom, 0, GFP_ATOMIC)) { + dev_kfree_skb(skb); + return 0; + } + } + hdr = (struct ieee80211_hdr *) skb->data; fc = le16_to_cpu(hdr->frame_control); @@ -1813,10 +1834,12 @@ bh_len = ap->beacon_head_len; bt_len = ap->beacon_tail_len; - skb = dev_alloc_skb(bh_len + bt_len + 256 /* maximum TIM len */); + skb = dev_alloc_skb(local->hw.extra_tx_headroom + + bh_len + bt_len + 256 /* maximum TIM len */); if (!skb) return NULL; + skb_reserve(skb, local->hw.extra_tx_headroom); memcpy(skb_put(skb, bh_len), b_head, bh_len); if (hw->flags & IEEE80211_HW_SOFTWARE_SEQUENCE) diff -rU3 dscape/net/d80211/ieee80211_i.h dscape.hdr/net/d80211/ieee80211_i.h --- dscape/net/d80211/ieee80211_i.h 2007-02-05 16:20:01.000000000 +0100 +++ dscape.hdr/net/d80211/ieee80211_i.h 2007-02-05 16:24:19.000000000 +0100 @@ -49,6 +49,9 @@ * frame can be up to about 2 kB long. */ #define TOTAL_MAX_TX_BUFFER 512 +/* Required encryption head and tailroom */ +#define IEEE80211_ENCRYPT_HEADROOM 8 +#define IEEE80211_ENCRYPT_TAILROOM 12 /* IEEE 802.11 (Ch. 9.5 Defragmentation) requires support for concurrent * reception of at least three fragmented frames. This limit can be increased diff -rU3 dscape/net/d80211/ieee80211_scan.c dscape.hdr/net/d80211/ieee80211_scan.c --- dscape/net/d80211/ieee80211_scan.c 2007-02-05 16:18:41.000000000 +0100 +++ dscape.hdr/net/d80211/ieee80211_scan.c 2007-02-05 16:24:49.000000000 +0100 @@ -280,7 +280,7 @@ { struct ieee80211_hdr hdr; u16 fc; - int len = 10; + int len = 10 + local->hw.extra_tx_headroom; struct rate_control_extra extra; /* Only initialize passive scanning if the hardware supports it */ @@ -309,6 +309,7 @@ "passive scan\n", local->mdev->name); return; } + skb_reserve(local->scan.skb, local->hw.extra_tx_headroom); fc = IEEE80211_FTYPE_CTL | IEEE80211_STYPE_CTS; hdr.frame_control = cpu_to_le16(fc); diff -rU3 dscape/net/d80211/ieee80211_sta.c dscape.hdr/net/d80211/ieee80211_sta.c --- dscape/net/d80211/ieee80211_sta.c 2007-02-05 16:18:41.000000000 +0100 +++ dscape.hdr/net/d80211/ieee80211_sta.c 2007-02-05 16:27:29.000000000 +0100 @@ -415,15 +415,18 @@ int transaction, u8 *extra, size_t extra_len, int encrypt) { + struct ieee80211_local *local = dev->ieee80211_ptr; struct sk_buff *skb; struct ieee80211_mgmt *mgmt; - skb = dev_alloc_skb(sizeof(*mgmt) + 6 + extra_len); + skb = dev_alloc_skb(local->hw.extra_tx_headroom + + sizeof(*mgmt) + 6 + extra_len); if (!skb) { printk(KERN_DEBUG "%s: failed to allocate buffer for auth " "frame\n", dev->name); return; } + skb_reserve(skb, local->hw.extra_tx_headroom); mgmt = (struct ieee80211_mgmt *) skb_put(skb, 24 + 6); memset(mgmt, 0, 24 + 6); @@ -478,13 +481,15 @@ struct ieee80211_sta_bss *bss; int wmm = 0; - skb = dev_alloc_skb(sizeof(*mgmt) + 200 + ifsta->extra_ie_len + + skb = dev_alloc_skb(local->hw.extra_tx_headroom + + sizeof(*mgmt) + 200 + ifsta->extra_ie_len + ifsta->ssid_len); if (!skb) { printk(KERN_DEBUG "%s: failed to allocate buffer for assoc " "frame\n", dev->name); return; } + skb_reserve(skb, local->hw.extra_tx_headroom); capab = ifsta->capab; if (local->hw.conf.phymode == MODE_IEEE80211G) { @@ -585,15 +590,17 @@ static void ieee80211_send_deauth(struct net_device *dev, struct ieee80211_if_sta *ifsta, u16 reason) { + struct ieee80211_local *local = dev->ieee80211_ptr; struct sk_buff *skb; struct ieee80211_mgmt *mgmt; - skb = dev_alloc_skb(sizeof(*mgmt)); + skb = dev_alloc_skb(local->hw.extra_tx_headroom + sizeof(*mgmt)); if (!skb) { printk(KERN_DEBUG "%s: failed to allocate buffer for deauth " "frame\n", dev->name); return; } + skb_reserve(skb, local->hw.extra_tx_headroom); mgmt = (struct ieee80211_mgmt *) skb_put(skb, 24); memset(mgmt, 0, 24); @@ -612,15 +619,17 @@ static void ieee80211_send_disassoc(struct net_device *dev, struct ieee80211_if_sta *ifsta, u16 reason) { + struct ieee80211_local *local = dev->ieee80211_ptr; struct sk_buff *skb; struct ieee80211_mgmt *mgmt; - skb = dev_alloc_skb(sizeof(*mgmt)); + skb = dev_alloc_skb(local->hw.extra_tx_headroom + sizeof(*mgmt)); if (!skb) { printk(KERN_DEBUG "%s: failed to allocate buffer for disassoc " "frame\n", dev->name); return; } + skb_reserve(skb, local->hw.extra_tx_headroom); mgmt = (struct ieee80211_mgmt *) skb_put(skb, 24); memset(mgmt, 0, 24); @@ -758,12 +767,13 @@ u8 *pos, *supp_rates, *esupp_rates = NULL; int i; - skb = dev_alloc_skb(sizeof(*mgmt) + 200); + skb = dev_alloc_skb(local->hw.extra_tx_headroom + sizeof(*mgmt) + 200); if (!skb) { printk(KERN_DEBUG "%s: failed to allocate buffer for probe " "request\n", dev->name); return; } + skb_reserve(skb, local->hw.extra_tx_headroom); mgmt = (struct ieee80211_mgmt *) skb_put(skb, 24); memset(mgmt, 0, 24); @@ -2007,6 +2017,8 @@ if (!skb) break; + skb_reserve(skb, local->hw.extra_tx_headroom); + mgmt = (struct ieee80211_mgmt *) skb_put(skb, 24 + sizeof(mgmt->u.beacon)); memset(mgmt, 0, 24 + sizeof(mgmt->u.beacon)); - To unsubscribe from this list: send the line "unsubscribe netdev" in the body of a message to [EMAIL PROTECTED] More majordomo info at http://vger.kernel.org/majordomo-info.html