*
  *     Writes a packet as immediate data into a Tx descriptor.  The packet
  *     contains a work request at its beginning.  We must write the packet
- *     carefully so the SGE doesn't read accidentally before it's written in
- *     its entirety.
+ *     carefully so the SGE doesn't read it accidentally before it's written
+ *     in its entirety.
  */
 static inline void write_imm(struct tx_desc *d, struct sk_buff *skb,
                             unsigned int len, unsigned int gen)
        struct work_request_hdr *from = (struct work_request_hdr *)skb->data;
        struct work_request_hdr *to = (struct work_request_hdr *)d;
 
-       memcpy(&to[1], &from[1], len - sizeof(*from));
+       if (likely(!skb->data_len))
+               memcpy(&to[1], &from[1], len - sizeof(*from));
+       else
+               skb_copy_bits(skb, sizeof(*from), &to[1], len - sizeof(*from));
+
        to->wr_hi = from->wr_hi | htonl(F_WR_SOP | F_WR_EOP |
                                        V_WR_BCNTLFLT(len & 7));
        wmb();
 
 static inline int immediate(const struct sk_buff *skb)
 {
-       return skb->len <= WR_LEN && !skb->data_len;
+       return skb->len <= WR_LEN;
 }
 
 /**
  */
 static inline unsigned int calc_tx_descs_ofld(const struct sk_buff *skb)
 {
-       unsigned int flits, cnt = skb_shinfo(skb)->nr_frags;
+       unsigned int flits, cnt;
 
-       if (skb->len <= WR_LEN && cnt == 0)
+       if (skb->len <= WR_LEN)
                return 1;       /* packet fits as immediate data */
 
        flits = skb_transport_offset(skb) / 8;  /* headers */
+       cnt = skb_shinfo(skb)->nr_frags;
        if (skb->tail != skb->transport_header)
                cnt++;
        return flits_to_desc(flits + sgl_len(cnt));