Skip to content

Commit

Permalink
igb: Do not use header split, instead receive all frames into a singl…
Browse files Browse the repository at this point in the history
…e buffer

This change makes it so that we no longer use header split.  The idea is to
reduce partial cache line writes by hardware when handling frames larger
then header size.  We can compensate for the extra overhead of having to
memcpy the header buffer by avoiding the cache misses seen by leaving an
full skb allocated and sitting on the ring.

Signed-off-by: Alexander Duyck <alexander.h.duyck@intel.com>
Tested-by: Aaron Brown <aaron.f.brown@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
  • Loading branch information
Alexander Duyck authored and Jeff Kirsher committed Oct 19, 2012
1 parent b534550 commit 1a1c225
Show file tree
Hide file tree
Showing 3 changed files with 312 additions and 152 deletions.
13 changes: 5 additions & 8 deletions drivers/net/ethernet/intel/igb/igb.h
Original file line number Diff line number Diff line change
Expand Up @@ -174,11 +174,9 @@ struct igb_tx_buffer {
};

struct igb_rx_buffer {
struct sk_buff *skb;
dma_addr_t dma;
struct page *page;
dma_addr_t page_dma;
u32 page_offset;
unsigned int page_offset;
};

struct igb_tx_queue_stats {
Expand Down Expand Up @@ -251,6 +249,7 @@ struct igb_ring {
};
/* RX */
struct {
struct sk_buff *skb;
struct igb_rx_queue_stats rx_stats;
struct u64_stats_sync rx_syncp;
};
Expand Down Expand Up @@ -451,13 +450,11 @@ static inline void igb_ptp_rx_hwtstamp(struct igb_q_vector *q_vector,
union e1000_adv_rx_desc *rx_desc,
struct sk_buff *skb)
{
if (igb_test_staterr(rx_desc, E1000_RXDADV_STAT_TSIP)) {
igb_ptp_rx_pktstamp(q_vector, skb->data, skb);
skb_pull(skb, IGB_TS_HDR_LEN);
} else if (igb_test_staterr(rx_desc, E1000_RXDADV_STAT_TS)) {
if (igb_test_staterr(rx_desc, E1000_RXDADV_STAT_TS) &&
!igb_test_staterr(rx_desc, E1000_RXDADV_STAT_TSIP))
igb_ptp_rx_rgtstamp(q_vector, skb);
}
}

extern int igb_ptp_hwtstamp_ioctl(struct net_device *netdev,
struct ifreq *ifr, int cmd);
#endif /* CONFIG_IGB_PTP */
Expand Down
31 changes: 20 additions & 11 deletions drivers/net/ethernet/intel/igb/igb_ethtool.c
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
#include <linux/sched.h>
#include <linux/slab.h>
#include <linux/pm_runtime.h>
#include <linux/highmem.h>

#include "igb.h"

Expand Down Expand Up @@ -1685,16 +1686,24 @@ static void igb_create_lbtest_frame(struct sk_buff *skb,
memset(&skb->data[frame_size + 12], 0xAF, 1);
}

static int igb_check_lbtest_frame(struct sk_buff *skb, unsigned int frame_size)
static int igb_check_lbtest_frame(struct igb_rx_buffer *rx_buffer,
unsigned int frame_size)
{
frame_size /= 2;
if (*(skb->data + 3) == 0xFF) {
if ((*(skb->data + frame_size + 10) == 0xBE) &&
(*(skb->data + frame_size + 12) == 0xAF)) {
return 0;
}
}
return 13;
unsigned char *data;
bool match = true;

frame_size >>= 1;

data = kmap(rx_buffer->page) + rx_buffer->page_offset;

if (data[3] != 0xFF ||
data[frame_size + 10] != 0xBE ||
data[frame_size + 12] != 0xAF)
match = false;

kunmap(rx_buffer->page);

return match;
}

static int igb_clean_test_rings(struct igb_ring *rx_ring,
Expand All @@ -1720,12 +1729,12 @@ static int igb_clean_test_rings(struct igb_ring *rx_ring,
/* unmap rx buffer, will be remapped by alloc_rx_buffers */
dma_unmap_single(rx_ring->dev,
rx_buffer_info->dma,
IGB_RX_HDR_LEN,
PAGE_SIZE / 2,
DMA_FROM_DEVICE);
rx_buffer_info->dma = 0;

/* verify contents of skb */
if (!igb_check_lbtest_frame(rx_buffer_info->skb, size))
if (igb_check_lbtest_frame(rx_buffer_info, size))
count++;

/* unmap buffer on tx side */
Expand Down
Loading

0 comments on commit 1a1c225

Please sign in to comment.