Skip to content

Commit 31c15a2

Browse files
dnlsndavem330
authored andcommitted
e1000: save skb counts in TX to avoid cache misses
Virtual Machines with emulated e1000 network adapter running on Parallels' server were seeing kernel panics due to the e1000 driver dereferencing an unexpected NULL pointer retrieved from buffer_info->skb. The problem has been addressed for the e1000e driver, but not for the e1000. Since the two drivers share similar code in the affected area, a port of the following e1000e driver commit solves the issue for the e1000 driver: commit 9ed318d Author: Tom Herbert <therbert@google.com> Date: Wed May 5 14:02:27 2010 +0000 e1000e: save skb counts in TX to avoid cache misses In e1000_tx_map, precompute number of segements and bytecounts which are derived from fields in skb; these are stored in buffer_info. When cleaning tx in e1000_clean_tx_irq use the values in the associated buffer_info for statistics counting, this eliminates cache misses on skb fields. Signed-off-by: Dean Nelson <dnelson@redhat.com> Acked-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com> Signed-off-by: David S. Miller <davem@davemloft.net>
1 parent 363437f commit 31c15a2

File tree

2 files changed

+11
-9
lines changed

2 files changed

+11
-9
lines changed

drivers/net/ethernet/intel/e1000/e1000.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -150,6 +150,8 @@ struct e1000_buffer {
150150
unsigned long time_stamp;
151151
u16 length;
152152
u16 next_to_watch;
153+
unsigned int segs;
154+
unsigned int bytecount;
153155
u16 mapped_as_page;
154156
};
155157

drivers/net/ethernet/intel/e1000/e1000_main.c

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2848,7 +2848,7 @@ static int e1000_tx_map(struct e1000_adapter *adapter,
28482848
struct e1000_buffer *buffer_info;
28492849
unsigned int len = skb_headlen(skb);
28502850
unsigned int offset = 0, size, count = 0, i;
2851-
unsigned int f;
2851+
unsigned int f, bytecount, segs;
28522852

28532853
i = tx_ring->next_to_use;
28542854

@@ -2949,7 +2949,13 @@ static int e1000_tx_map(struct e1000_adapter *adapter,
29492949
}
29502950
}
29512951

2952+
segs = skb_shinfo(skb)->gso_segs ?: 1;
2953+
/* multiply data chunks by size of headers */
2954+
bytecount = ((segs - 1) * skb_headlen(skb)) + skb->len;
2955+
29522956
tx_ring->buffer_info[i].skb = skb;
2957+
tx_ring->buffer_info[i].segs = segs;
2958+
tx_ring->buffer_info[i].bytecount = bytecount;
29532959
tx_ring->buffer_info[first].next_to_watch = i;
29542960

29552961
return count;
@@ -3623,14 +3629,8 @@ static bool e1000_clean_tx_irq(struct e1000_adapter *adapter,
36233629
cleaned = (i == eop);
36243630

36253631
if (cleaned) {
3626-
struct sk_buff *skb = buffer_info->skb;
3627-
unsigned int segs, bytecount;
3628-
segs = skb_shinfo(skb)->gso_segs ?: 1;
3629-
/* multiply data chunks by size of headers */
3630-
bytecount = ((segs - 1) * skb_headlen(skb)) +
3631-
skb->len;
3632-
total_tx_packets += segs;
3633-
total_tx_bytes += bytecount;
3632+
total_tx_packets += buffer_info->segs;
3633+
total_tx_bytes += buffer_info->bytecount;
36343634
}
36353635
e1000_unmap_and_free_tx_resource(adapter, buffer_info);
36363636
tx_desc->upper.data = 0;

0 commit comments

Comments
 (0)