diff options
Diffstat (limited to 'drivers/net/e1000/e1000_main.c')
-rw-r--r-- | drivers/net/e1000/e1000_main.c | 30 |
1 files changed, 30 insertions, 0 deletions
diff --git a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c index 431b03ee077e..d641fbc7a6e1 100644 --- a/drivers/net/e1000/e1000_main.c +++ b/drivers/net/e1000/e1000_main.c | |||
@@ -3757,6 +3757,35 @@ e1000_clean_rx_irq_ps(struct e1000_adapter *adapter, | |||
3757 | /* Good Receive */ | 3757 | /* Good Receive */ |
3758 | skb_put(skb, length); | 3758 | skb_put(skb, length); |
3759 | 3759 | ||
3760 | { | ||
3761 | /* this looks ugly, but it seems compiler issues make it | ||
3762 | more efficient than reusing j */ | ||
3763 | int l1 = le16_to_cpu(rx_desc->wb.upper.length[0]); | ||
3764 | |||
3765 | /* page alloc/put takes too long and effects small packet | ||
3766 | * throughput, so unsplit small packets and save the alloc/put*/ | ||
3767 | if (l1 && ((length + l1) < E1000_CB_LENGTH)) { | ||
3768 | u8 *vaddr; | ||
3769 | /* there is no documentation about how to call | ||
3770 | * kmap_atomic, so we can't hold the mapping | ||
3771 | * very long */ | ||
3772 | pci_dma_sync_single_for_cpu(pdev, | ||
3773 | ps_page_dma->ps_page_dma[0], | ||
3774 | PAGE_SIZE, | ||
3775 | PCI_DMA_FROMDEVICE); | ||
3776 | vaddr = kmap_atomic(ps_page->ps_page[0], | ||
3777 | KM_SKB_DATA_SOFTIRQ); | ||
3778 | memcpy(skb->tail, vaddr, l1); | ||
3779 | kunmap_atomic(vaddr, KM_SKB_DATA_SOFTIRQ); | ||
3780 | pci_dma_sync_single_for_device(pdev, | ||
3781 | ps_page_dma->ps_page_dma[0], | ||
3782 | PAGE_SIZE, PCI_DMA_FROMDEVICE); | ||
3783 | skb_put(skb, l1); | ||
3784 | length += l1; | ||
3785 | goto copydone; | ||
3786 | } /* if */ | ||
3787 | } | ||
3788 | |||
3760 | for (j = 0; j < adapter->rx_ps_pages; j++) { | 3789 | for (j = 0; j < adapter->rx_ps_pages; j++) { |
3761 | if (!(length = le16_to_cpu(rx_desc->wb.upper.length[j]))) | 3790 | if (!(length = le16_to_cpu(rx_desc->wb.upper.length[j]))) |
3762 | break; | 3791 | break; |
@@ -3771,6 +3800,7 @@ e1000_clean_rx_irq_ps(struct e1000_adapter *adapter, | |||
3771 | skb->data_len += length; | 3800 | skb->data_len += length; |
3772 | } | 3801 | } |
3773 | 3802 | ||
3803 | copydone: | ||
3774 | e1000_rx_checksum(adapter, staterr, | 3804 | e1000_rx_checksum(adapter, staterr, |
3775 | rx_desc->wb.lower.hi_dword.csum_ip.csum, skb); | 3805 | rx_desc->wb.lower.hi_dword.csum_ip.csum, skb); |
3776 | skb->protocol = eth_type_trans(skb, netdev); | 3806 | skb->protocol = eth_type_trans(skb, netdev); |