diff options
author | Nick Nunley <nicholasx.d.nunley@intel.com> | 2010-05-04 17:58:07 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2010-05-06 00:30:12 -0400 |
commit | 2873957df0ead5b53fa00fddfb52ca3df38af4a9 (patch) | |
tree | 3332fef2c0b6ac1877299ab171ce7a316a786301 /drivers/net/igb | |
parent | a84afa40e07b6882ca46a7287d8ca4a8c5430f60 (diff) |
igb: reduce cache misses on tx cleanup
This patch reduces the number of skb cache misses in the
clean_tx_irq path, and results in an overall increase
in tx packet throughput.
Signed-off-by: Nicholas Nunley <nicholasx.d.nunley@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/igb')
-rw-r--r-- | drivers/net/igb/igb.h | 4 | ||||
-rw-r--r-- | drivers/net/igb/igb_main.c | 45 |
2 files changed, 22 insertions, 27 deletions
diff --git a/drivers/net/igb/igb.h b/drivers/net/igb/igb.h index 735ede9c7d75..6e63d9a7fc75 100644 --- a/drivers/net/igb/igb.h +++ b/drivers/net/igb/igb.h | |||
@@ -141,8 +141,10 @@ struct igb_buffer { | |||
141 | unsigned long time_stamp; | 141 | unsigned long time_stamp; |
142 | u16 length; | 142 | u16 length; |
143 | u16 next_to_watch; | 143 | u16 next_to_watch; |
144 | u16 mapped_as_page; | 144 | unsigned int bytecount; |
145 | u16 gso_segs; | 145 | u16 gso_segs; |
146 | union skb_shared_tx shtx; | ||
147 | u8 mapped_as_page; | ||
146 | }; | 148 | }; |
147 | /* RX */ | 149 | /* RX */ |
148 | struct { | 150 | struct { |
diff --git a/drivers/net/igb/igb_main.c b/drivers/net/igb/igb_main.c index 438737d58688..589cf4a6427a 100644 --- a/drivers/net/igb/igb_main.c +++ b/drivers/net/igb/igb_main.c | |||
@@ -3899,34 +3899,33 @@ static inline int igb_tx_map_adv(struct igb_ring *tx_ring, struct sk_buff *skb, | |||
3899 | { | 3899 | { |
3900 | struct igb_buffer *buffer_info; | 3900 | struct igb_buffer *buffer_info; |
3901 | struct device *dev = tx_ring->dev; | 3901 | struct device *dev = tx_ring->dev; |
3902 | unsigned int len = skb_headlen(skb); | 3902 | unsigned int hlen = skb_headlen(skb); |
3903 | unsigned int count = 0, i; | 3903 | unsigned int count = 0, i; |
3904 | unsigned int f; | 3904 | unsigned int f; |
3905 | u16 gso_segs = skb_shinfo(skb)->gso_segs ?: 1; | ||
3905 | 3906 | ||
3906 | i = tx_ring->next_to_use; | 3907 | i = tx_ring->next_to_use; |
3907 | 3908 | ||
3908 | buffer_info = &tx_ring->buffer_info[i]; | 3909 | buffer_info = &tx_ring->buffer_info[i]; |
3909 | BUG_ON(len >= IGB_MAX_DATA_PER_TXD); | 3910 | BUG_ON(hlen >= IGB_MAX_DATA_PER_TXD); |
3910 | buffer_info->length = len; | 3911 | buffer_info->length = hlen; |
3911 | /* set time_stamp *before* dma to help avoid a possible race */ | 3912 | /* set time_stamp *before* dma to help avoid a possible race */ |
3912 | buffer_info->time_stamp = jiffies; | 3913 | buffer_info->time_stamp = jiffies; |
3913 | buffer_info->next_to_watch = i; | 3914 | buffer_info->next_to_watch = i; |
3914 | buffer_info->dma = dma_map_single(dev, skb->data, len, | 3915 | buffer_info->dma = dma_map_single(dev, skb->data, hlen, |
3915 | DMA_TO_DEVICE); | 3916 | DMA_TO_DEVICE); |
3916 | if (dma_mapping_error(dev, buffer_info->dma)) | 3917 | if (dma_mapping_error(dev, buffer_info->dma)) |
3917 | goto dma_error; | 3918 | goto dma_error; |
3918 | 3919 | ||
3919 | for (f = 0; f < skb_shinfo(skb)->nr_frags; f++) { | 3920 | for (f = 0; f < skb_shinfo(skb)->nr_frags; f++) { |
3920 | struct skb_frag_struct *frag; | 3921 | struct skb_frag_struct *frag = &skb_shinfo(skb)->frags[f]; |
3922 | unsigned int len = frag->size; | ||
3921 | 3923 | ||
3922 | count++; | 3924 | count++; |
3923 | i++; | 3925 | i++; |
3924 | if (i == tx_ring->count) | 3926 | if (i == tx_ring->count) |
3925 | i = 0; | 3927 | i = 0; |
3926 | 3928 | ||
3927 | frag = &skb_shinfo(skb)->frags[f]; | ||
3928 | len = frag->size; | ||
3929 | |||
3930 | buffer_info = &tx_ring->buffer_info[i]; | 3929 | buffer_info = &tx_ring->buffer_info[i]; |
3931 | BUG_ON(len >= IGB_MAX_DATA_PER_TXD); | 3930 | BUG_ON(len >= IGB_MAX_DATA_PER_TXD); |
3932 | buffer_info->length = len; | 3931 | buffer_info->length = len; |
@@ -3944,7 +3943,10 @@ static inline int igb_tx_map_adv(struct igb_ring *tx_ring, struct sk_buff *skb, | |||
3944 | } | 3943 | } |
3945 | 3944 | ||
3946 | tx_ring->buffer_info[i].skb = skb; | 3945 | tx_ring->buffer_info[i].skb = skb; |
3947 | tx_ring->buffer_info[i].gso_segs = skb_shinfo(skb)->gso_segs ?: 1; | 3946 | tx_ring->buffer_info[i].shtx = skb_shinfo(skb)->tx_flags; |
3947 | /* multiply data chunks by size of headers */ | ||
3948 | tx_ring->buffer_info[i].bytecount = ((gso_segs - 1) * hlen) + skb->len; | ||
3949 | tx_ring->buffer_info[i].gso_segs = gso_segs; | ||
3948 | tx_ring->buffer_info[first].next_to_watch = i; | 3950 | tx_ring->buffer_info[first].next_to_watch = i; |
3949 | 3951 | ||
3950 | return ++count; | 3952 | return ++count; |
@@ -5288,22 +5290,21 @@ static void igb_systim_to_hwtstamp(struct igb_adapter *adapter, | |||
5288 | /** | 5290 | /** |
5289 | * igb_tx_hwtstamp - utility function which checks for TX time stamp | 5291 | * igb_tx_hwtstamp - utility function which checks for TX time stamp |
5290 | * @q_vector: pointer to q_vector containing needed info | 5292 | * @q_vector: pointer to q_vector containing needed info |
5291 | * @skb: packet that was just sent | 5293 | * @buffer: pointer to igb_buffer structure |
5292 | * | 5294 | * |
5293 | * If we were asked to do hardware stamping and such a time stamp is | 5295 | * If we were asked to do hardware stamping and such a time stamp is |
5294 | * available, then it must have been for this skb here because we only | 5296 | * available, then it must have been for this skb here because we only |
5295 | * allow only one such packet into the queue. | 5297 | * allow only one such packet into the queue. |
5296 | */ | 5298 | */ |
5297 | static void igb_tx_hwtstamp(struct igb_q_vector *q_vector, struct sk_buff *skb) | 5299 | static void igb_tx_hwtstamp(struct igb_q_vector *q_vector, struct igb_buffer *buffer_info) |
5298 | { | 5300 | { |
5299 | struct igb_adapter *adapter = q_vector->adapter; | 5301 | struct igb_adapter *adapter = q_vector->adapter; |
5300 | union skb_shared_tx *shtx = skb_tx(skb); | ||
5301 | struct e1000_hw *hw = &adapter->hw; | 5302 | struct e1000_hw *hw = &adapter->hw; |
5302 | struct skb_shared_hwtstamps shhwtstamps; | 5303 | struct skb_shared_hwtstamps shhwtstamps; |
5303 | u64 regval; | 5304 | u64 regval; |
5304 | 5305 | ||
5305 | /* if skb does not support hw timestamp or TX stamp not valid exit */ | 5306 | /* if skb does not support hw timestamp or TX stamp not valid exit */ |
5306 | if (likely(!shtx->hardware) || | 5307 | if (likely(!buffer_info->shtx.hardware) || |
5307 | !(rd32(E1000_TSYNCTXCTL) & E1000_TSYNCTXCTL_VALID)) | 5308 | !(rd32(E1000_TSYNCTXCTL) & E1000_TSYNCTXCTL_VALID)) |
5308 | return; | 5309 | return; |
5309 | 5310 | ||
@@ -5311,7 +5312,7 @@ static void igb_tx_hwtstamp(struct igb_q_vector *q_vector, struct sk_buff *skb) | |||
5311 | regval |= (u64)rd32(E1000_TXSTMPH) << 32; | 5312 | regval |= (u64)rd32(E1000_TXSTMPH) << 32; |
5312 | 5313 | ||
5313 | igb_systim_to_hwtstamp(adapter, &shhwtstamps, regval); | 5314 | igb_systim_to_hwtstamp(adapter, &shhwtstamps, regval); |
5314 | skb_tstamp_tx(skb, &shhwtstamps); | 5315 | skb_tstamp_tx(buffer_info->skb, &shhwtstamps); |
5315 | } | 5316 | } |
5316 | 5317 | ||
5317 | /** | 5318 | /** |
@@ -5326,7 +5327,6 @@ static bool igb_clean_tx_irq(struct igb_q_vector *q_vector) | |||
5326 | struct net_device *netdev = tx_ring->netdev; | 5327 | struct net_device *netdev = tx_ring->netdev; |
5327 | struct e1000_hw *hw = &adapter->hw; | 5328 | struct e1000_hw *hw = &adapter->hw; |
5328 | struct igb_buffer *buffer_info; | 5329 | struct igb_buffer *buffer_info; |
5329 | struct sk_buff *skb; | ||
5330 | union e1000_adv_tx_desc *tx_desc, *eop_desc; | 5330 | union e1000_adv_tx_desc *tx_desc, *eop_desc; |
5331 | unsigned int total_bytes = 0, total_packets = 0; | 5331 | unsigned int total_bytes = 0, total_packets = 0; |
5332 | unsigned int i, eop, count = 0; | 5332 | unsigned int i, eop, count = 0; |
@@ -5342,19 +5342,12 @@ static bool igb_clean_tx_irq(struct igb_q_vector *q_vector) | |||
5342 | tx_desc = E1000_TX_DESC_ADV(*tx_ring, i); | 5342 | tx_desc = E1000_TX_DESC_ADV(*tx_ring, i); |
5343 | buffer_info = &tx_ring->buffer_info[i]; | 5343 | buffer_info = &tx_ring->buffer_info[i]; |
5344 | cleaned = (i == eop); | 5344 | cleaned = (i == eop); |
5345 | skb = buffer_info->skb; | ||
5346 | 5345 | ||
5347 | if (skb) { | 5346 | if (buffer_info->skb) { |
5348 | unsigned int segs, bytecount; | 5347 | total_bytes += buffer_info->bytecount; |
5349 | /* gso_segs is currently only valid for tcp */ | 5348 | /* gso_segs is currently only valid for tcp */ |
5350 | segs = buffer_info->gso_segs; | 5349 | total_packets += buffer_info->gso_segs; |
5351 | /* multiply data chunks by size of headers */ | 5350 | igb_tx_hwtstamp(q_vector, buffer_info); |
5352 | bytecount = ((segs - 1) * skb_headlen(skb)) + | ||
5353 | skb->len; | ||
5354 | total_packets += segs; | ||
5355 | total_bytes += bytecount; | ||
5356 | |||
5357 | igb_tx_hwtstamp(q_vector, skb); | ||
5358 | } | 5351 | } |
5359 | 5352 | ||
5360 | igb_unmap_and_free_tx_resource(tx_ring, buffer_info); | 5353 | igb_unmap_and_free_tx_resource(tx_ring, buffer_info); |