return err;
 }
 
-static inline struct txfcb *gfar_add_fcb(struct sk_buff *skb)
+static inline struct txfcb *gfar_add_fcb(struct sk_buff **skbp)
 {
-       struct txfcb *fcb = (struct txfcb *)skb_push (skb, GMAC_FCB_LEN);
-
+       struct txfcb *fcb;
+       struct sk_buff *skb = *skbp;
+
+       if (unlikely(skb_headroom(skb) < GMAC_FCB_LEN)) {
+               struct sk_buff *old_skb = skb;
+               skb = skb_realloc_headroom(old_skb, GMAC_FCB_LEN);
+               if (!skb)
+                       return NULL;
+               dev_kfree_skb_any(old_skb);
+       }
+       fcb = (struct txfcb *)skb_push(skb, GMAC_FCB_LEN);
        cacheable_memzero(fcb, GMAC_FCB_LEN);
 
        return fcb;
 
        /* Set up checksumming */
        if (CHECKSUM_PARTIAL == skb->ip_summed) {
-               fcb = gfar_add_fcb(skb);
-               lstatus |= BD_LFLAG(TXBD_TOE);
-               gfar_tx_checksum(skb, fcb);
+               fcb = gfar_add_fcb(&skb);
+               if (likely(fcb != NULL)) {
+                       lstatus |= BD_LFLAG(TXBD_TOE);
+                       gfar_tx_checksum(skb, fcb);
+               }
        }
 
        if (priv->vlgrp && vlan_tx_tag_present(skb)) {
-               if (unlikely(NULL == fcb)) {
-                       fcb = gfar_add_fcb(skb);
+               if (unlikely(NULL == fcb))
+                       fcb = gfar_add_fcb(&skb);
+               if (likely(fcb != NULL)) {
                        lstatus |= BD_LFLAG(TXBD_TOE);
+                       gfar_tx_vlan(skb, fcb);
                }
-
-               gfar_tx_vlan(skb, fcb);
        }
 
        /* setup the TxBD length and buffer pointer for the first BD */