diff options
author | Alexander Duyck <alexander.h.duyck@intel.com> | 2009-02-06 18:15:04 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2009-02-07 05:43:01 -0500 |
commit | 69d3ca5357bb93bb3a139c5d90077407f8828bd1 (patch) | |
tree | 462944f1fc5fab09b8fa2c3d632e3c875aeeba31 /drivers/net/igb/igb_main.c | |
parent | 3e450669cc7060d56d886f53e31182f5fef103c7 (diff) |
igb: optimize/refactor receive path
While cleaning up the skb_over panic with small frames I found there was
room for improvement in the ordering of operations within the rx receive
flow. These changes will place the prefetch for the next descriptor to a
point earlier in the rx path.
Signed-off-by: Alexander Duyck <alexander.h.duyck@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/igb_main.c')
-rw-r--r-- | drivers/net/igb/igb_main.c | 44 |
1 files changed, 22 insertions, 22 deletions
diff --git a/drivers/net/igb/igb_main.c b/drivers/net/igb/igb_main.c index 8b80fe343435..21f0c229b64e 100644 --- a/drivers/net/igb/igb_main.c +++ b/drivers/net/igb/igb_main.c | |||
@@ -3803,6 +3803,7 @@ static bool igb_clean_rx_irq_adv(struct igb_ring *rx_ring, | |||
3803 | unsigned int total_bytes = 0, total_packets = 0; | 3803 | unsigned int total_bytes = 0, total_packets = 0; |
3804 | 3804 | ||
3805 | i = rx_ring->next_to_clean; | 3805 | i = rx_ring->next_to_clean; |
3806 | buffer_info = &rx_ring->buffer_info[i]; | ||
3806 | rx_desc = E1000_RX_DESC_ADV(*rx_ring, i); | 3807 | rx_desc = E1000_RX_DESC_ADV(*rx_ring, i); |
3807 | staterr = le32_to_cpu(rx_desc->wb.upper.status_error); | 3808 | staterr = le32_to_cpu(rx_desc->wb.upper.status_error); |
3808 | 3809 | ||
@@ -3810,25 +3811,22 @@ static bool igb_clean_rx_irq_adv(struct igb_ring *rx_ring, | |||
3810 | if (*work_done >= budget) | 3811 | if (*work_done >= budget) |
3811 | break; | 3812 | break; |
3812 | (*work_done)++; | 3813 | (*work_done)++; |
3813 | buffer_info = &rx_ring->buffer_info[i]; | ||
3814 | 3814 | ||
3815 | /* HW will not DMA in data larger than the given buffer, even | 3815 | skb = buffer_info->skb; |
3816 | * if it parses the (NFS, of course) header to be larger. In | 3816 | prefetch(skb->data - NET_IP_ALIGN); |
3817 | * that case, it fills the header buffer and spills the rest | 3817 | buffer_info->skb = NULL; |
3818 | * into the page. | 3818 | |
3819 | */ | 3819 | i++; |
3820 | hlen = (le16_to_cpu(rx_desc->wb.lower.lo_dword.hdr_info) & | 3820 | if (i == rx_ring->count) |
3821 | E1000_RXDADV_HDRBUFLEN_MASK) >> E1000_RXDADV_HDRBUFLEN_SHIFT; | 3821 | i = 0; |
3822 | if (hlen > adapter->rx_ps_hdr_size) | 3822 | next_rxd = E1000_RX_DESC_ADV(*rx_ring, i); |
3823 | hlen = adapter->rx_ps_hdr_size; | 3823 | prefetch(next_rxd); |
3824 | next_buffer = &rx_ring->buffer_info[i]; | ||
3824 | 3825 | ||
3825 | length = le16_to_cpu(rx_desc->wb.upper.length); | 3826 | length = le16_to_cpu(rx_desc->wb.upper.length); |
3826 | cleaned = true; | 3827 | cleaned = true; |
3827 | cleaned_count++; | 3828 | cleaned_count++; |
3828 | 3829 | ||
3829 | skb = buffer_info->skb; | ||
3830 | prefetch(skb->data - NET_IP_ALIGN); | ||
3831 | buffer_info->skb = NULL; | ||
3832 | if (!adapter->rx_ps_hdr_size) { | 3830 | if (!adapter->rx_ps_hdr_size) { |
3833 | pci_unmap_single(pdev, buffer_info->dma, | 3831 | pci_unmap_single(pdev, buffer_info->dma, |
3834 | adapter->rx_buffer_len + | 3832 | adapter->rx_buffer_len + |
@@ -3838,6 +3836,16 @@ static bool igb_clean_rx_irq_adv(struct igb_ring *rx_ring, | |||
3838 | goto send_up; | 3836 | goto send_up; |
3839 | } | 3837 | } |
3840 | 3838 | ||
3839 | /* HW will not DMA in data larger than the given buffer, even | ||
3840 | * if it parses the (NFS, of course) header to be larger. In | ||
3841 | * that case, it fills the header buffer and spills the rest | ||
3842 | * into the page. | ||
3843 | */ | ||
3844 | hlen = (le16_to_cpu(rx_desc->wb.lower.lo_dword.hdr_info) & | ||
3845 | E1000_RXDADV_HDRBUFLEN_MASK) >> E1000_RXDADV_HDRBUFLEN_SHIFT; | ||
3846 | if (hlen > adapter->rx_ps_hdr_size) | ||
3847 | hlen = adapter->rx_ps_hdr_size; | ||
3848 | |||
3841 | if (!skb_shinfo(skb)->nr_frags) { | 3849 | if (!skb_shinfo(skb)->nr_frags) { |
3842 | pci_unmap_single(pdev, buffer_info->dma, | 3850 | pci_unmap_single(pdev, buffer_info->dma, |
3843 | adapter->rx_ps_hdr_size + | 3851 | adapter->rx_ps_hdr_size + |
@@ -3867,13 +3875,6 @@ static bool igb_clean_rx_irq_adv(struct igb_ring *rx_ring, | |||
3867 | 3875 | ||
3868 | skb->truesize += length; | 3876 | skb->truesize += length; |
3869 | } | 3877 | } |
3870 | send_up: | ||
3871 | i++; | ||
3872 | if (i == rx_ring->count) | ||
3873 | i = 0; | ||
3874 | next_rxd = E1000_RX_DESC_ADV(*rx_ring, i); | ||
3875 | prefetch(next_rxd); | ||
3876 | next_buffer = &rx_ring->buffer_info[i]; | ||
3877 | 3878 | ||
3878 | if (!(staterr & E1000_RXD_STAT_EOP)) { | 3879 | if (!(staterr & E1000_RXD_STAT_EOP)) { |
3879 | buffer_info->skb = next_buffer->skb; | 3880 | buffer_info->skb = next_buffer->skb; |
@@ -3882,7 +3883,7 @@ send_up: | |||
3882 | next_buffer->dma = 0; | 3883 | next_buffer->dma = 0; |
3883 | goto next_desc; | 3884 | goto next_desc; |
3884 | } | 3885 | } |
3885 | 3886 | send_up: | |
3886 | if (staterr & E1000_RXDEXT_ERR_FRAME_ERR_MASK) { | 3887 | if (staterr & E1000_RXDEXT_ERR_FRAME_ERR_MASK) { |
3887 | dev_kfree_skb_irq(skb); | 3888 | dev_kfree_skb_irq(skb); |
3888 | goto next_desc; | 3889 | goto next_desc; |
@@ -3909,7 +3910,6 @@ next_desc: | |||
3909 | /* use prefetched values */ | 3910 | /* use prefetched values */ |
3910 | rx_desc = next_rxd; | 3911 | rx_desc = next_rxd; |
3911 | buffer_info = next_buffer; | 3912 | buffer_info = next_buffer; |
3912 | |||
3913 | staterr = le32_to_cpu(rx_desc->wb.upper.status_error); | 3913 | staterr = le32_to_cpu(rx_desc->wb.upper.status_error); |
3914 | } | 3914 | } |
3915 | 3915 | ||