aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/mlx4
diff options
context:
space:
mode:
authorYevgeny Petrilin <yevgenyp@mellanox.co.il>2010-08-23 23:46:46 -0400
committerDavid S. Miller <davem@davemloft.net>2010-08-24 18:00:42 -0400
commitfa37a9586f92051de03a13e55e5ec3880bb6783e (patch)
treef87f49668aa13e65fba708b3cf30658332a54edf /drivers/net/mlx4
parent0533943c5c45cce2e26432bf0a6b8e114757c897 (diff)
mlx4_en: Moving to work with GRO
Signed-off-by: Yevgeny Petrilin <yevgenyp@mellanox.co.il> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/mlx4')
-rw-r--r--drivers/net/mlx4/en_ethtool.c56
-rw-r--r--drivers/net/mlx4/en_netdev.c2
-rw-r--r--drivers/net/mlx4/en_rx.c66
-rw-r--r--drivers/net/mlx4/en_tx.c1
-rw-r--r--drivers/net/mlx4/mlx4_en.h5
5 files changed, 17 insertions, 113 deletions
diff --git a/drivers/net/mlx4/en_ethtool.c b/drivers/net/mlx4/en_ethtool.c
index c5551f2cf260..01634a3efe85 100644
--- a/drivers/net/mlx4/en_ethtool.c
+++ b/drivers/net/mlx4/en_ethtool.c
@@ -39,21 +39,6 @@
39#include "en_port.h" 39#include "en_port.h"
40 40
41 41
42static void mlx4_en_update_lro_stats(struct mlx4_en_priv *priv)
43{
44 int i;
45
46 priv->port_stats.lro_aggregated = 0;
47 priv->port_stats.lro_flushed = 0;
48 priv->port_stats.lro_no_desc = 0;
49
50 for (i = 0; i < priv->rx_ring_num; i++) {
51 priv->port_stats.lro_aggregated += priv->rx_ring[i].lro.stats.aggregated;
52 priv->port_stats.lro_flushed += priv->rx_ring[i].lro.stats.flushed;
53 priv->port_stats.lro_no_desc += priv->rx_ring[i].lro.stats.no_desc;
54 }
55}
56
57static void 42static void
58mlx4_en_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *drvinfo) 43mlx4_en_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *drvinfo)
59{ 44{
@@ -112,7 +97,7 @@ static const char main_strings[][ETH_GSTRING_LEN] = {
112 "tx_heartbeat_errors", "tx_window_errors", 97 "tx_heartbeat_errors", "tx_window_errors",
113 98
114 /* port statistics */ 99 /* port statistics */
115 "lro_aggregated", "lro_flushed", "lro_no_desc", "tso_packets", 100 "tso_packets",
116 "queue_stopped", "wake_queue", "tx_timeout", "rx_alloc_failed", 101 "queue_stopped", "wake_queue", "tx_timeout", "rx_alloc_failed",
117 "rx_csum_good", "rx_csum_none", "tx_chksum_offload", 102 "rx_csum_good", "rx_csum_none", "tx_chksum_offload",
118 103
@@ -122,7 +107,7 @@ static const char main_strings[][ETH_GSTRING_LEN] = {
122 "tx_prio_1", "tx_prio_2", "tx_prio_3", "tx_prio_4", "tx_prio_5", 107 "tx_prio_1", "tx_prio_2", "tx_prio_3", "tx_prio_4", "tx_prio_5",
123 "tx_prio_6", "tx_prio_7", 108 "tx_prio_6", "tx_prio_7",
124}; 109};
125#define NUM_MAIN_STATS 21 110#define NUM_MAIN_STATS 18
126#define NUM_ALL_STATS (NUM_MAIN_STATS + NUM_PORT_STATS + NUM_PKT_STATS + NUM_PERF_STATS) 111#define NUM_ALL_STATS (NUM_MAIN_STATS + NUM_PORT_STATS + NUM_PKT_STATS + NUM_PERF_STATS)
127 112
128static const char mlx4_en_test_names[][ETH_GSTRING_LEN]= { 113static const char mlx4_en_test_names[][ETH_GSTRING_LEN]= {
@@ -174,8 +159,6 @@ static void mlx4_en_get_ethtool_stats(struct net_device *dev,
174 159
175 spin_lock_bh(&priv->stats_lock); 160 spin_lock_bh(&priv->stats_lock);
176 161
177 mlx4_en_update_lro_stats(priv);
178
179 for (i = 0; i < NUM_MAIN_STATS; i++) 162 for (i = 0; i < NUM_MAIN_STATS; i++)
180 data[index++] = ((unsigned long *) &priv->stats)[i]; 163 data[index++] = ((unsigned long *) &priv->stats)[i];
181 for (i = 0; i < NUM_PORT_STATS; i++) 164 for (i = 0; i < NUM_PORT_STATS; i++)
@@ -439,40 +422,6 @@ static void mlx4_en_get_ringparam(struct net_device *dev,
439 param->tx_pending = priv->tx_ring[0].size; 422 param->tx_pending = priv->tx_ring[0].size;
440} 423}
441 424
442static int mlx4_ethtool_op_set_flags(struct net_device *dev, u32 data)
443{
444 struct mlx4_en_priv *priv = netdev_priv(dev);
445 struct mlx4_en_dev *mdev = priv->mdev;
446 int rc = 0;
447 int changed = 0;
448
449 if (data & ~ETH_FLAG_LRO)
450 return -EOPNOTSUPP;
451
452 if (data & ETH_FLAG_LRO) {
453 if (!(dev->features & NETIF_F_LRO))
454 changed = 1;
455 } else if (dev->features & NETIF_F_LRO) {
456 changed = 1;
457 }
458
459 if (changed) {
460 if (netif_running(dev)) {
461 mutex_lock(&mdev->state_lock);
462 mlx4_en_stop_port(dev);
463 }
464 dev->features ^= NETIF_F_LRO;
465 if (netif_running(dev)) {
466 rc = mlx4_en_start_port(dev);
467 if (rc)
468 en_err(priv, "Failed to restart port\n");
469 mutex_unlock(&mdev->state_lock);
470 }
471 }
472
473 return rc;
474}
475
476const struct ethtool_ops mlx4_en_ethtool_ops = { 425const struct ethtool_ops mlx4_en_ethtool_ops = {
477 .get_drvinfo = mlx4_en_get_drvinfo, 426 .get_drvinfo = mlx4_en_get_drvinfo,
478 .get_settings = mlx4_en_get_settings, 427 .get_settings = mlx4_en_get_settings,
@@ -502,7 +451,6 @@ const struct ethtool_ops mlx4_en_ethtool_ops = {
502 .get_ringparam = mlx4_en_get_ringparam, 451 .get_ringparam = mlx4_en_get_ringparam,
503 .set_ringparam = mlx4_en_set_ringparam, 452 .set_ringparam = mlx4_en_set_ringparam,
504 .get_flags = ethtool_op_get_flags, 453 .get_flags = ethtool_op_get_flags,
505 .set_flags = mlx4_ethtool_op_set_flags,
506}; 454};
507 455
508 456
diff --git a/drivers/net/mlx4/en_netdev.c b/drivers/net/mlx4/en_netdev.c
index 242366ca0793..411bda581c04 100644
--- a/drivers/net/mlx4/en_netdev.c
+++ b/drivers/net/mlx4/en_netdev.c
@@ -1047,7 +1047,7 @@ int mlx4_en_init_netdev(struct mlx4_en_dev *mdev, int port,
1047 dev->features |= NETIF_F_HW_VLAN_TX | 1047 dev->features |= NETIF_F_HW_VLAN_TX |
1048 NETIF_F_HW_VLAN_RX | 1048 NETIF_F_HW_VLAN_RX |
1049 NETIF_F_HW_VLAN_FILTER; 1049 NETIF_F_HW_VLAN_FILTER;
1050 dev->features |= NETIF_F_LRO; 1050 dev->features |= NETIF_F_GRO;
1051 if (mdev->LSO_support) { 1051 if (mdev->LSO_support) {
1052 dev->features |= NETIF_F_TSO; 1052 dev->features |= NETIF_F_TSO;
1053 dev->features |= NETIF_F_TSO6; 1053 dev->features |= NETIF_F_TSO6;
diff --git a/drivers/net/mlx4/en_rx.c b/drivers/net/mlx4/en_rx.c
index e2126c76d1dc..cb7ff00ce6de 100644
--- a/drivers/net/mlx4/en_rx.c
+++ b/drivers/net/mlx4/en_rx.c
@@ -42,18 +42,6 @@
42#include "mlx4_en.h" 42#include "mlx4_en.h"
43 43
44 44
45static int mlx4_en_get_frag_header(struct skb_frag_struct *frags, void **mac_hdr,
46 void **ip_hdr, void **tcpudp_hdr,
47 u64 *hdr_flags, void *priv)
48{
49 *mac_hdr = page_address(frags->page) + frags->page_offset;
50 *ip_hdr = *mac_hdr + ETH_HLEN;
51 *tcpudp_hdr = (struct tcphdr *)(*ip_hdr + sizeof(struct iphdr));
52 *hdr_flags = LRO_IPV4 | LRO_TCP;
53
54 return 0;
55}
56
57static int mlx4_en_alloc_frag(struct mlx4_en_priv *priv, 45static int mlx4_en_alloc_frag(struct mlx4_en_priv *priv,
58 struct mlx4_en_rx_desc *rx_desc, 46 struct mlx4_en_rx_desc *rx_desc,
59 struct skb_frag_struct *skb_frags, 47 struct skb_frag_struct *skb_frags,
@@ -312,24 +300,6 @@ int mlx4_en_create_rx_ring(struct mlx4_en_priv *priv,
312 } 300 }
313 ring->buf = ring->wqres.buf.direct.buf; 301 ring->buf = ring->wqres.buf.direct.buf;
314 302
315 /* Configure lro mngr */
316 memset(&ring->lro, 0, sizeof(struct net_lro_mgr));
317 ring->lro.dev = priv->dev;
318 ring->lro.features = LRO_F_NAPI;
319 ring->lro.frag_align_pad = NET_IP_ALIGN;
320 ring->lro.ip_summed = CHECKSUM_UNNECESSARY;
321 ring->lro.ip_summed_aggr = CHECKSUM_UNNECESSARY;
322 ring->lro.max_desc = MLX4_EN_MAX_LRO_DESCRIPTORS;
323 ring->lro.max_aggr = MAX_SKB_FRAGS;
324 ring->lro.lro_arr = kcalloc(MLX4_EN_MAX_LRO_DESCRIPTORS,
325 sizeof(struct net_lro_desc),
326 GFP_KERNEL);
327 if (!ring->lro.lro_arr) {
328 en_err(priv, "Failed to allocate lro array\n");
329 goto err_map;
330 }
331 ring->lro.get_frag_header = mlx4_en_get_frag_header;
332
333 return 0; 303 return 0;
334 304
335err_map: 305err_map:
@@ -412,7 +382,6 @@ void mlx4_en_destroy_rx_ring(struct mlx4_en_priv *priv,
412{ 382{
413 struct mlx4_en_dev *mdev = priv->mdev; 383 struct mlx4_en_dev *mdev = priv->mdev;
414 384
415 kfree(ring->lro.lro_arr);
416 mlx4_en_unmap_buffer(&ring->wqres.buf); 385 mlx4_en_unmap_buffer(&ring->wqres.buf);
417 mlx4_free_hwq_res(mdev->dev, &ring->wqres, ring->buf_size + TXBB_SIZE); 386 mlx4_free_hwq_res(mdev->dev, &ring->wqres, ring->buf_size + TXBB_SIZE);
418 vfree(ring->rx_info); 387 vfree(ring->rx_info);
@@ -563,7 +532,6 @@ int mlx4_en_process_rx_cq(struct net_device *dev, struct mlx4_en_cq *cq, int bud
563 struct mlx4_cqe *cqe; 532 struct mlx4_cqe *cqe;
564 struct mlx4_en_rx_ring *ring = &priv->rx_ring[cq->ring]; 533 struct mlx4_en_rx_ring *ring = &priv->rx_ring[cq->ring];
565 struct skb_frag_struct *skb_frags; 534 struct skb_frag_struct *skb_frags;
566 struct skb_frag_struct lro_frags[MLX4_EN_MAX_RX_FRAGS];
567 struct mlx4_en_rx_desc *rx_desc; 535 struct mlx4_en_rx_desc *rx_desc;
568 struct sk_buff *skb; 536 struct sk_buff *skb;
569 int index; 537 int index;
@@ -623,37 +591,33 @@ int mlx4_en_process_rx_cq(struct net_device *dev, struct mlx4_en_cq *cq, int bud
623 * - TCP/IP (v4) 591 * - TCP/IP (v4)
624 * - without IP options 592 * - without IP options
625 * - not an IP fragment */ 593 * - not an IP fragment */
626 if (mlx4_en_can_lro(cqe->status) && 594 if (dev->features & NETIF_F_GRO) {
627 dev->features & NETIF_F_LRO) { 595 struct sk_buff *gro_skb = napi_get_frags(&cq->napi);
628 596
629 nr = mlx4_en_complete_rx_desc( 597 nr = mlx4_en_complete_rx_desc(
630 priv, rx_desc, 598 priv, rx_desc,
631 skb_frags, lro_frags, 599 skb_frags, skb_shinfo(gro_skb)->frags,
632 ring->page_alloc, length); 600 ring->page_alloc, length);
633 if (!nr) 601 if (!nr)
634 goto next; 602 goto next;
635 603
604 skb_shinfo(gro_skb)->nr_frags = nr;
605 gro_skb->len = length;
606 gro_skb->data_len = length;
607 gro_skb->truesize += length;
608 gro_skb->ip_summed = CHECKSUM_UNNECESSARY;
609
636 if (priv->vlgrp && (cqe->vlan_my_qpn & 610 if (priv->vlgrp && (cqe->vlan_my_qpn &
637 cpu_to_be32(MLX4_CQE_VLAN_PRESENT_MASK))) { 611 cpu_to_be32(MLX4_CQE_VLAN_PRESENT_MASK)))
638 lro_vlan_hwaccel_receive_frags( 612 vlan_gro_frags(&cq->napi, priv->vlgrp, be16_to_cpu(cqe->sl_vid));
639 &ring->lro, lro_frags, 613 else
640 length, length, 614 napi_gro_frags(&cq->napi);
641 priv->vlgrp,
642 be16_to_cpu(cqe->sl_vid),
643 NULL, 0);
644 } else
645 lro_receive_frags(&ring->lro,
646 lro_frags,
647 length,
648 length,
649 NULL, 0);
650 615
651 goto next; 616 goto next;
652 } 617 }
653 618
654 /* LRO not possible, complete processing here */ 619 /* LRO not possible, complete processing here */
655 ip_summed = CHECKSUM_UNNECESSARY; 620 ip_summed = CHECKSUM_UNNECESSARY;
656 INC_PERF_COUNTER(priv->pstats.lro_misses);
657 } else { 621 } else {
658 ip_summed = CHECKSUM_NONE; 622 ip_summed = CHECKSUM_NONE;
659 priv->port_stats.rx_chksum_none++; 623 priv->port_stats.rx_chksum_none++;
@@ -694,14 +658,10 @@ next:
694 if (++polled == budget) { 658 if (++polled == budget) {
695 /* We are here because we reached the NAPI budget - 659 /* We are here because we reached the NAPI budget -
696 * flush only pending LRO sessions */ 660 * flush only pending LRO sessions */
697 lro_flush_all(&ring->lro);
698 goto out; 661 goto out;
699 } 662 }
700 } 663 }
701 664
702 /* If CQ is empty flush all LRO sessions unconditionally */
703 lro_flush_all(&ring->lro);
704
705out: 665out:
706 AVG_PERF_COUNTER(priv->pstats.rx_coal_avg, polled); 666 AVG_PERF_COUNTER(priv->pstats.rx_coal_avg, polled);
707 mlx4_cq_set_ci(&cq->mcq); 667 mlx4_cq_set_ci(&cq->mcq);
diff --git a/drivers/net/mlx4/en_tx.c b/drivers/net/mlx4/en_tx.c
index b875f9c38848..98dd620042a8 100644
--- a/drivers/net/mlx4/en_tx.c
+++ b/drivers/net/mlx4/en_tx.c
@@ -38,6 +38,7 @@
38#include <linux/skbuff.h> 38#include <linux/skbuff.h>
39#include <linux/if_vlan.h> 39#include <linux/if_vlan.h>
40#include <linux/vmalloc.h> 40#include <linux/vmalloc.h>
41#include <linux/tcp.h>
41 42
42#include "mlx4_en.h" 43#include "mlx4_en.h"
43 44
diff --git a/drivers/net/mlx4/mlx4_en.h b/drivers/net/mlx4/mlx4_en.h
index 4036a053ee32..7d4ddb9a2bec 100644
--- a/drivers/net/mlx4/mlx4_en.h
+++ b/drivers/net/mlx4/mlx4_en.h
@@ -38,7 +38,6 @@
38#include <linux/list.h> 38#include <linux/list.h>
39#include <linux/mutex.h> 39#include <linux/mutex.h>
40#include <linux/netdevice.h> 40#include <linux/netdevice.h>
41#include <linux/inet_lro.h>
42 41
43#include <linux/mlx4/device.h> 42#include <linux/mlx4/device.h>
44#include <linux/mlx4/qp.h> 43#include <linux/mlx4/qp.h>
@@ -254,7 +253,6 @@ struct mlx4_en_rx_desc {
254struct mlx4_en_rx_ring { 253struct mlx4_en_rx_ring {
255 struct mlx4_hwq_resources wqres; 254 struct mlx4_hwq_resources wqres;
256 struct mlx4_en_rx_alloc page_alloc[MLX4_EN_MAX_RX_FRAGS]; 255 struct mlx4_en_rx_alloc page_alloc[MLX4_EN_MAX_RX_FRAGS];
257 struct net_lro_mgr lro;
258 u32 size ; /* number of Rx descs*/ 256 u32 size ; /* number of Rx descs*/
259 u32 actual_size; 257 u32 actual_size;
260 u32 size_mask; 258 u32 size_mask;
@@ -379,9 +377,6 @@ struct mlx4_en_pkt_stats {
379}; 377};
380 378
381struct mlx4_en_port_stats { 379struct mlx4_en_port_stats {
382 unsigned long lro_aggregated;
383 unsigned long lro_flushed;
384 unsigned long lro_no_desc;
385 unsigned long tso_packets; 380 unsigned long tso_packets;
386 unsigned long queue_stopped; 381 unsigned long queue_stopped;
387 unsigned long wake_queue; 382 unsigned long wake_queue;