sfc: Copy RX prefix into skb head area in efx_rx_mk_skb()
authorBen Hutchings <bhutchings@solarflare.com>
Thu, 28 Nov 2013 18:58:11 +0000 (18:58 +0000)
committerBen Hutchings <bhutchings@solarflare.com>
Thu, 12 Dec 2013 22:07:12 +0000 (22:07 +0000)
We can potentially pull the entire packet contents into the head area
and then free the page it was in.  In order to read an inline
timestamp safely, we need to copy the prefix into the head area as
well.

Signed-off-by: Ben Hutchings <bhutchings@solarflare.com>
drivers/net/ethernet/sfc/net_driver.h
drivers/net/ethernet/sfc/rx.c

index 01ffbe84968304fffd4867ed53260d92dbb5b036..1a3e4972c68f6eabe032215642e69ec4b4e45357 100644 (file)
@@ -521,15 +521,6 @@ enum nic_state {
        STATE_RECOVERY = 3,     /* device recovering from PCI error */
 };
 
-/*
- * Alignment of the skb->head which wraps a page-allocated RX buffer
- *
- * The skb allocated to wrap an rx_buffer can have this alignment. Since
- * the data is memcpy'd from the rx_buf, it does not need to be equal to
- * NET_IP_ALIGN.
- */
-#define EFX_PAGE_SKB_ALIGN 2
-
 /* Forward declaration */
 struct efx_nic;
 
index 8671bc199a9d03d26876203cb0e9eb596790b291..d12abc5439750fbba2da2d8af3b1b7a917550c98 100644 (file)
@@ -476,14 +476,18 @@ static struct sk_buff *efx_rx_mk_skb(struct efx_channel *channel,
        struct sk_buff *skb;
 
        /* Allocate an SKB to store the headers */
-       skb = netdev_alloc_skb(efx->net_dev, hdr_len + EFX_PAGE_SKB_ALIGN);
+       skb = netdev_alloc_skb(efx->net_dev,
+                              efx->rx_ip_align + efx->rx_prefix_size +
+                              hdr_len);
        if (unlikely(skb == NULL))
                return NULL;
 
        EFX_BUG_ON_PARANOID(rx_buf->len < hdr_len);
 
-       skb_reserve(skb, EFX_PAGE_SKB_ALIGN);
-       memcpy(__skb_put(skb, hdr_len), eh, hdr_len);
+       memcpy(skb->data + efx->rx_ip_align, eh - efx->rx_prefix_size,
+              efx->rx_prefix_size + hdr_len);
+       skb_reserve(skb, efx->rx_ip_align + efx->rx_prefix_size);
+       __skb_put(skb, hdr_len);
 
        /* Append the remaining page(s) onto the frag list */
        if (rx_buf->len > hdr_len) {