aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBen Hutchings <bhutchings@solarflare.com>2013-11-28 13:58:11 -0500
committerBen Hutchings <bhutchings@solarflare.com>2013-12-12 17:07:12 -0500
commit2ccd0b192534b1dc6af45ffb81faa44b7ae416bf (patch)
tree297f8c256708bb77f60b3f4259dc5758f488826e
parent9ec0659595c8020f1efa55aa00870e8773f8ee89 (diff)
sfc: Copy RX prefix into skb head area in efx_rx_mk_skb()
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>
-rw-r--r--drivers/net/ethernet/sfc/net_driver.h9
-rw-r--r--drivers/net/ethernet/sfc/rx.c10
2 files changed, 7 insertions, 12 deletions
diff --git a/drivers/net/ethernet/sfc/net_driver.h b/drivers/net/ethernet/sfc/net_driver.h
index 01ffbe849683..1a3e4972c68f 100644
--- a/drivers/net/ethernet/sfc/net_driver.h
+++ b/drivers/net/ethernet/sfc/net_driver.h
@@ -521,15 +521,6 @@ enum nic_state {
521 STATE_RECOVERY = 3, /* device recovering from PCI error */ 521 STATE_RECOVERY = 3, /* device recovering from PCI error */
522}; 522};
523 523
524/*
525 * Alignment of the skb->head which wraps a page-allocated RX buffer
526 *
527 * The skb allocated to wrap an rx_buffer can have this alignment. Since
528 * the data is memcpy'd from the rx_buf, it does not need to be equal to
529 * NET_IP_ALIGN.
530 */
531#define EFX_PAGE_SKB_ALIGN 2
532
533/* Forward declaration */ 524/* Forward declaration */
534struct efx_nic; 525struct efx_nic;
535 526
diff --git a/drivers/net/ethernet/sfc/rx.c b/drivers/net/ethernet/sfc/rx.c
index 8671bc199a9d..d12abc543975 100644
--- a/drivers/net/ethernet/sfc/rx.c
+++ b/drivers/net/ethernet/sfc/rx.c
@@ -476,14 +476,18 @@ static struct sk_buff *efx_rx_mk_skb(struct efx_channel *channel,
476 struct sk_buff *skb; 476 struct sk_buff *skb;
477 477
478 /* Allocate an SKB to store the headers */ 478 /* Allocate an SKB to store the headers */
479 skb = netdev_alloc_skb(efx->net_dev, hdr_len + EFX_PAGE_SKB_ALIGN); 479 skb = netdev_alloc_skb(efx->net_dev,
480 efx->rx_ip_align + efx->rx_prefix_size +
481 hdr_len);
480 if (unlikely(skb == NULL)) 482 if (unlikely(skb == NULL))
481 return NULL; 483 return NULL;
482 484
483 EFX_BUG_ON_PARANOID(rx_buf->len < hdr_len); 485 EFX_BUG_ON_PARANOID(rx_buf->len < hdr_len);
484 486
485 skb_reserve(skb, EFX_PAGE_SKB_ALIGN); 487 memcpy(skb->data + efx->rx_ip_align, eh - efx->rx_prefix_size,
486 memcpy(__skb_put(skb, hdr_len), eh, hdr_len); 488 efx->rx_prefix_size + hdr_len);
489 skb_reserve(skb, efx->rx_ip_align + efx->rx_prefix_size);
490 __skb_put(skb, hdr_len);
487 491
488 /* Append the remaining page(s) onto the frag list */ 492 /* Append the remaining page(s) onto the frag list */
489 if (rx_buf->len > hdr_len) { 493 if (rx_buf->len > hdr_len) {