gfp_t priority);
 extern struct sk_buff *skb_copy(const struct sk_buff *skb,
                                gfp_t priority);
-extern struct sk_buff *pskb_copy(struct sk_buff *skb,
-                                gfp_t gfp_mask);
+extern struct sk_buff *__pskb_copy(struct sk_buff *skb,
+                                int headroom, gfp_t gfp_mask);
+
 extern int            pskb_expand_head(struct sk_buff *skb,
                                        int nhead, int ntail,
                                        gfp_t gfp_mask);
                            frag->page_offset + offset, size, dir);
 }
 
+static inline struct sk_buff *pskb_copy(struct sk_buff *skb,
+                                       gfp_t gfp_mask)
+{
+       return __pskb_copy(skb, skb_headroom(skb), gfp_mask);
+}
+
 /**
  *     skb_clone_writable - is the header of a clone writable
  *     @skb: buffer to check
 
 EXPORT_SYMBOL(skb_copy);
 
 /**
- *     pskb_copy       -       create copy of an sk_buff with private head.
+ *     __pskb_copy     -       create copy of an sk_buff with private head.
  *     @skb: buffer to copy
+ *     @headroom: headroom of new skb
  *     @gfp_mask: allocation priority
  *
  *     Make a copy of both an &sk_buff and part of its data, located
  *     The returned buffer has a reference count of 1.
  */
 
-struct sk_buff *pskb_copy(struct sk_buff *skb, gfp_t gfp_mask)
+struct sk_buff *__pskb_copy(struct sk_buff *skb, int headroom, gfp_t gfp_mask)
 {
-       unsigned int size = skb_end_pointer(skb) - skb->head;
+       unsigned int size = skb_headlen(skb) + headroom;
        struct sk_buff *n = alloc_skb(size, gfp_mask);
 
        if (!n)
                goto out;
 
        /* Set the data pointer */
-       skb_reserve(n, skb_headroom(skb));
+       skb_reserve(n, headroom);
        /* Set the tail pointer and length */
        skb_put(n, skb_headlen(skb));
        /* Copy the bytes */
 out:
        return n;
 }
-EXPORT_SYMBOL(pskb_copy);
+EXPORT_SYMBOL(__pskb_copy);
 
 /**
  *     pskb_expand_head - reallocate header of &sk_buff
 
         */
        TCP_SKB_CB(skb)->when = tcp_time_stamp;
 
-       err = tcp_transmit_skb(sk, skb, 1, GFP_ATOMIC);
+       /* make sure skb->data is aligned on arches that require it */
+       if (unlikely(NET_IP_ALIGN && ((unsigned long)skb->data & 3))) {
+               struct sk_buff *nskb = __pskb_copy(skb, MAX_TCP_HEADER,
+                                                  GFP_ATOMIC);
+               err = nskb ? tcp_transmit_skb(sk, nskb, 0, GFP_ATOMIC) :
+                            -ENOBUFS;
+       } else {
+               err = tcp_transmit_skb(sk, skb, 1, GFP_ATOMIC);
+       }
 
        if (err == 0) {
                /* Update global TCP statistics. */