aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net
diff options
context:
space:
mode:
authorGovindarajulu Varadarajan <_govind@gmx.com>2014-09-02 17:47:19 -0400
committerDavid S. Miller <davem@davemloft.net>2014-09-05 15:12:20 -0400
commita03bb56e67c357980dae886683733dab5583dc14 (patch)
tree787611409812bc85e37ebdbd09a86aa309b61f7b /drivers/net
parente020836d953eb1ce5b9221b32f4613646a4d5772 (diff)
enic: implement rx_copybreak
Calling dma_map_single()/dma_unmap_single() is quite expensive compared to copying a small packet. So let's copy short frames and keep the buffers mapped. Signed-off-by: Govindarajulu Varadarajan <_govind@gmx.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net')
-rw-r--r--drivers/net/ethernet/cisco/enic/enic.h1
-rw-r--r--drivers/net/ethernet/cisco/enic/enic_main.c50
2 files changed, 48 insertions, 3 deletions
diff --git a/drivers/net/ethernet/cisco/enic/enic.h b/drivers/net/ethernet/cisco/enic/enic.h
index 962510f391df..5ba5ad071bb6 100644
--- a/drivers/net/ethernet/cisco/enic/enic.h
+++ b/drivers/net/ethernet/cisco/enic/enic.h
@@ -186,6 +186,7 @@ struct enic {
186 ____cacheline_aligned struct vnic_cq cq[ENIC_CQ_MAX]; 186 ____cacheline_aligned struct vnic_cq cq[ENIC_CQ_MAX];
187 unsigned int cq_count; 187 unsigned int cq_count;
188 struct enic_rfs_flw_tbl rfs_h; 188 struct enic_rfs_flw_tbl rfs_h;
189 u32 rx_copybreak;
189}; 190};
190 191
191static inline struct device *enic_get_dev(struct enic *enic) 192static inline struct device *enic_get_dev(struct enic *enic)
diff --git a/drivers/net/ethernet/cisco/enic/enic_main.c b/drivers/net/ethernet/cisco/enic/enic_main.c
index c8832bc1c5f7..929bfe70080a 100644
--- a/drivers/net/ethernet/cisco/enic/enic_main.c
+++ b/drivers/net/ethernet/cisco/enic/enic_main.c
@@ -66,6 +66,8 @@
66#define PCI_DEVICE_ID_CISCO_VIC_ENET_DYN 0x0044 /* enet dynamic vnic */ 66#define PCI_DEVICE_ID_CISCO_VIC_ENET_DYN 0x0044 /* enet dynamic vnic */
67#define PCI_DEVICE_ID_CISCO_VIC_ENET_VF 0x0071 /* enet SRIOV VF */ 67#define PCI_DEVICE_ID_CISCO_VIC_ENET_VF 0x0071 /* enet SRIOV VF */
68 68
69#define RX_COPYBREAK_DEFAULT 256
70
69/* Supported devices */ 71/* Supported devices */
70static const struct pci_device_id enic_id_table[] = { 72static const struct pci_device_id enic_id_table[] = {
71 { PCI_VDEVICE(CISCO, PCI_DEVICE_ID_CISCO_VIC_ENET) }, 73 { PCI_VDEVICE(CISCO, PCI_DEVICE_ID_CISCO_VIC_ENET) },
@@ -924,6 +926,7 @@ static void enic_free_rq_buf(struct vnic_rq *rq, struct vnic_rq_buf *buf)
924 pci_unmap_single(enic->pdev, buf->dma_addr, 926 pci_unmap_single(enic->pdev, buf->dma_addr,
925 buf->len, PCI_DMA_FROMDEVICE); 927 buf->len, PCI_DMA_FROMDEVICE);
926 dev_kfree_skb_any(buf->os_buf); 928 dev_kfree_skb_any(buf->os_buf);
929 buf->os_buf = NULL;
927} 930}
928 931
929static int enic_rq_alloc_buf(struct vnic_rq *rq) 932static int enic_rq_alloc_buf(struct vnic_rq *rq)
@@ -934,7 +937,24 @@ static int enic_rq_alloc_buf(struct vnic_rq *rq)
934 unsigned int len = netdev->mtu + VLAN_ETH_HLEN; 937 unsigned int len = netdev->mtu + VLAN_ETH_HLEN;
935 unsigned int os_buf_index = 0; 938 unsigned int os_buf_index = 0;
936 dma_addr_t dma_addr; 939 dma_addr_t dma_addr;
940 struct vnic_rq_buf *buf = rq->to_use;
941
942 if (buf->os_buf) {
943 buf = buf->next;
944 rq->to_use = buf;
945 rq->ring.desc_avail--;
946 if ((buf->index & VNIC_RQ_RETURN_RATE) == 0) {
947 /* Adding write memory barrier prevents compiler and/or
948 * CPU reordering, thus avoiding descriptor posting
949 * before descriptor is initialized. Otherwise, hardware
950 * can read stale descriptor fields.
951 */
952 wmb();
953 iowrite32(buf->index, &rq->ctrl->posted_index);
954 }
937 955
956 return 0;
957 }
938 skb = netdev_alloc_skb_ip_align(netdev, len); 958 skb = netdev_alloc_skb_ip_align(netdev, len);
939 if (!skb) 959 if (!skb)
940 return -ENOMEM; 960 return -ENOMEM;
@@ -957,6 +977,25 @@ static void enic_intr_update_pkt_size(struct vnic_rx_bytes_counter *pkt_size,
957 pkt_size->small_pkt_bytes_cnt += pkt_len; 977 pkt_size->small_pkt_bytes_cnt += pkt_len;
958} 978}
959 979
980static bool enic_rxcopybreak(struct net_device *netdev, struct sk_buff **skb,
981 struct vnic_rq_buf *buf, u16 len)
982{
983 struct enic *enic = netdev_priv(netdev);
984 struct sk_buff *new_skb;
985
986 if (len > enic->rx_copybreak)
987 return false;
988 new_skb = netdev_alloc_skb_ip_align(netdev, len);
989 if (!new_skb)
990 return false;
991 pci_dma_sync_single_for_cpu(enic->pdev, buf->dma_addr, len,
992 DMA_FROM_DEVICE);
993 memcpy(new_skb->data, (*skb)->data, len);
994 *skb = new_skb;
995
996 return true;
997}
998
960static void enic_rq_indicate_buf(struct vnic_rq *rq, 999static void enic_rq_indicate_buf(struct vnic_rq *rq,
961 struct cq_desc *cq_desc, struct vnic_rq_buf *buf, 1000 struct cq_desc *cq_desc, struct vnic_rq_buf *buf,
962 int skipped, void *opaque) 1001 int skipped, void *opaque)
@@ -978,9 +1017,6 @@ static void enic_rq_indicate_buf(struct vnic_rq *rq,
978 return; 1017 return;
979 1018
980 skb = buf->os_buf; 1019 skb = buf->os_buf;
981 prefetch(skb->data - NET_IP_ALIGN);
982 pci_unmap_single(enic->pdev, buf->dma_addr,
983 buf->len, PCI_DMA_FROMDEVICE);
984 1020
985 cq_enet_rq_desc_dec((struct cq_enet_rq_desc *)cq_desc, 1021 cq_enet_rq_desc_dec((struct cq_enet_rq_desc *)cq_desc,
986 &type, &color, &q_number, &completed_index, 1022 &type, &color, &q_number, &completed_index,
@@ -1011,6 +1047,13 @@ static void enic_rq_indicate_buf(struct vnic_rq *rq,
1011 /* Good receive 1047 /* Good receive
1012 */ 1048 */
1013 1049
1050 if (!enic_rxcopybreak(netdev, &skb, buf, bytes_written)) {
1051 buf->os_buf = NULL;
1052 pci_unmap_single(enic->pdev, buf->dma_addr, buf->len,
1053 PCI_DMA_FROMDEVICE);
1054 }
1055 prefetch(skb->data - NET_IP_ALIGN);
1056
1014 skb_put(skb, bytes_written); 1057 skb_put(skb, bytes_written);
1015 skb->protocol = eth_type_trans(skb, netdev); 1058 skb->protocol = eth_type_trans(skb, netdev);
1016 skb_record_rx_queue(skb, q_number); 1059 skb_record_rx_queue(skb, q_number);
@@ -2531,6 +2574,7 @@ static int enic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
2531 dev_err(dev, "Cannot register net device, aborting\n"); 2574 dev_err(dev, "Cannot register net device, aborting\n");
2532 goto err_out_dev_deinit; 2575 goto err_out_dev_deinit;
2533 } 2576 }
2577 enic->rx_copybreak = RX_COPYBREAK_DEFAULT;
2534 2578
2535 return 0; 2579 return 0;
2536 2580