aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/mlx4
diff options
context:
space:
mode:
authorYevgeny Petrilin <yevgenyp@mellanox.co.il>2009-06-01 19:24:07 -0400
committerDavid S. Miller <davem@davemloft.net>2009-06-02 05:29:06 -0400
commitf813cad836ab14b764cfe76f42a3b50bb9677b30 (patch)
treeccaafb7bcaa72e737fb8939e0c556f2466bb0d7d /drivers/net/mlx4
parent3db36fb2c88d68ee28d20845d5bb805ea9a7f6d8 (diff)
mlx4_en: multiqueue support
By default the driver opens 8 TX queues (defined by MLX4_EN_NUM_TX_RINGS). If the driver is configured to support Per Priority Flow Control, we open 8 additional TX rings. dev->real_num_tx_queues is always set to be MLX4_EN_NUM_TX_RINGS. The mlx4_en_select_queue() function uses standard hashing (skb_tx_hash) in case that PPFC is not supported or the skb contain a vlan tag, otherwise the queue is selected according to vlan priority. 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_main.c9
-rw-r--r--drivers/net/mlx4/en_netdev.c7
-rw-r--r--drivers/net/mlx4/en_tx.c74
-rw-r--r--drivers/net/mlx4/mlx4_en.h9
4 files changed, 28 insertions, 71 deletions
diff --git a/drivers/net/mlx4/en_main.c b/drivers/net/mlx4/en_main.c
index b510000d8391..9ed4a158f895 100644
--- a/drivers/net/mlx4/en_main.c
+++ b/drivers/net/mlx4/en_main.c
@@ -93,13 +93,8 @@ static int mlx4_en_get_profile(struct mlx4_en_dev *mdev)
93 params->prof[i].tx_ppp = pfctx; 93 params->prof[i].tx_ppp = pfctx;
94 params->prof[i].tx_ring_size = MLX4_EN_DEF_TX_RING_SIZE; 94 params->prof[i].tx_ring_size = MLX4_EN_DEF_TX_RING_SIZE;
95 params->prof[i].rx_ring_size = MLX4_EN_DEF_RX_RING_SIZE; 95 params->prof[i].rx_ring_size = MLX4_EN_DEF_RX_RING_SIZE;
96 } 96 params->prof[i].tx_ring_num = MLX4_EN_NUM_TX_RINGS +
97 if (pfcrx || pfctx) { 97 (!!pfcrx) * MLX4_EN_NUM_PPP_RINGS;
98 params->prof[1].tx_ring_num = MLX4_EN_TX_RING_NUM;
99 params->prof[2].tx_ring_num = MLX4_EN_TX_RING_NUM;
100 } else {
101 params->prof[1].tx_ring_num = 1;
102 params->prof[2].tx_ring_num = 1;
103 } 98 }
104 99
105 return 0; 100 return 0;
diff --git a/drivers/net/mlx4/en_netdev.c b/drivers/net/mlx4/en_netdev.c
index 16a634ffbcdf..37e4d30cbf04 100644
--- a/drivers/net/mlx4/en_netdev.c
+++ b/drivers/net/mlx4/en_netdev.c
@@ -934,6 +934,7 @@ static const struct net_device_ops mlx4_netdev_ops = {
934 .ndo_open = mlx4_en_open, 934 .ndo_open = mlx4_en_open,
935 .ndo_stop = mlx4_en_close, 935 .ndo_stop = mlx4_en_close,
936 .ndo_start_xmit = mlx4_en_xmit, 936 .ndo_start_xmit = mlx4_en_xmit,
937 .ndo_select_queue = mlx4_en_select_queue,
937 .ndo_get_stats = mlx4_en_get_stats, 938 .ndo_get_stats = mlx4_en_get_stats,
938 .ndo_set_multicast_list = mlx4_en_set_multicast, 939 .ndo_set_multicast_list = mlx4_en_set_multicast,
939 .ndo_set_mac_address = mlx4_en_set_mac, 940 .ndo_set_mac_address = mlx4_en_set_mac,
@@ -956,7 +957,7 @@ int mlx4_en_init_netdev(struct mlx4_en_dev *mdev, int port,
956 int i; 957 int i;
957 int err; 958 int err;
958 959
959 dev = alloc_etherdev(sizeof(struct mlx4_en_priv)); 960 dev = alloc_etherdev_mq(sizeof(struct mlx4_en_priv), prof->tx_ring_num);
960 if (dev == NULL) { 961 if (dev == NULL) {
961 mlx4_err(mdev, "Net device allocation failed\n"); 962 mlx4_err(mdev, "Net device allocation failed\n");
962 return -ENOMEM; 963 return -ENOMEM;
@@ -1018,14 +1019,12 @@ int mlx4_en_init_netdev(struct mlx4_en_dev *mdev, int port,
1018 } 1019 }
1019 priv->allocated = 1; 1020 priv->allocated = 1;
1020 1021
1021 /* Populate Tx priority mappings */
1022 mlx4_en_set_prio_map(priv, priv->tx_prio_map, prof->tx_ring_num);
1023
1024 /* 1022 /*
1025 * Initialize netdev entry points 1023 * Initialize netdev entry points
1026 */ 1024 */
1027 dev->netdev_ops = &mlx4_netdev_ops; 1025 dev->netdev_ops = &mlx4_netdev_ops;
1028 dev->watchdog_timeo = MLX4_EN_WATCHDOG_TIMEOUT; 1026 dev->watchdog_timeo = MLX4_EN_WATCHDOG_TIMEOUT;
1027 dev->real_num_tx_queues = MLX4_EN_NUM_TX_RINGS;
1029 1028
1030 SET_ETHTOOL_OPS(dev, &mlx4_en_ethtool_ops); 1029 SET_ETHTOOL_OPS(dev, &mlx4_en_ethtool_ops);
1031 1030
diff --git a/drivers/net/mlx4/en_tx.c b/drivers/net/mlx4/en_tx.c
index 95703f90c1b9..3719d1ac3950 100644
--- a/drivers/net/mlx4/en_tx.c
+++ b/drivers/net/mlx4/en_tx.c
@@ -297,34 +297,6 @@ int mlx4_en_free_tx_buf(struct net_device *dev, struct mlx4_en_tx_ring *ring)
297 return cnt; 297 return cnt;
298} 298}
299 299
300void mlx4_en_set_prio_map(struct mlx4_en_priv *priv, u16 *prio_map, u32 ring_num)
301{
302 int block = 8 / ring_num;
303 int extra = 8 - (block * ring_num);
304 int num = 0;
305 u16 ring = 1;
306 int prio;
307
308 if (ring_num == 1) {
309 for (prio = 0; prio < 8; prio++)
310 prio_map[prio] = 0;
311 return;
312 }
313
314 for (prio = 0; prio < 8; prio++) {
315 if (extra && (num == block + 1)) {
316 ring++;
317 num = 0;
318 extra--;
319 } else if (!extra && (num == block)) {
320 ring++;
321 num = 0;
322 }
323 prio_map[prio] = ring;
324 en_dbg(DRV, priv, " prio:%d --> ring:%d\n", prio, ring);
325 num++;
326 }
327}
328 300
329static void mlx4_en_process_tx_cq(struct net_device *dev, struct mlx4_en_cq *cq) 301static void mlx4_en_process_tx_cq(struct net_device *dev, struct mlx4_en_cq *cq)
330{ 302{
@@ -386,18 +358,8 @@ static void mlx4_en_process_tx_cq(struct net_device *dev, struct mlx4_en_cq *cq)
386 if (unlikely(ring->blocked)) { 358 if (unlikely(ring->blocked)) {
387 if ((u32) (ring->prod - ring->cons) <= 359 if ((u32) (ring->prod - ring->cons) <=
388 ring->size - HEADROOM - MAX_DESC_TXBBS) { 360 ring->size - HEADROOM - MAX_DESC_TXBBS) {
389
390 /* TODO: support multiqueue netdevs. Currently, we block
391 * when *any* ring is full. Note that:
392 * - 2 Tx rings can unblock at the same time and call
393 * netif_wake_queue(), which is OK since this
394 * operation is idempotent.
395 * - We might wake the queue just after another ring
396 * stopped it. This is no big deal because the next
397 * transmission on that ring would stop the queue.
398 */
399 ring->blocked = 0; 361 ring->blocked = 0;
400 netif_wake_queue(dev); 362 netif_tx_wake_queue(netdev_get_tx_queue(dev, cq->ring));
401 priv->port_stats.wake_queue++; 363 priv->port_stats.wake_queue++;
402 } 364 }
403 } 365 }
@@ -616,21 +578,20 @@ static void build_inline_wqe(struct mlx4_en_tx_desc *tx_desc, struct sk_buff *sk
616 tx_desc->ctrl.fence_size = (real_size / 16) & 0x3f; 578 tx_desc->ctrl.fence_size = (real_size / 16) & 0x3f;
617} 579}
618 580
619static int get_vlan_info(struct mlx4_en_priv *priv, struct sk_buff *skb, 581u16 mlx4_en_select_queue(struct net_device *dev, struct sk_buff *skb)
620 u16 *vlan_tag)
621{ 582{
622 int tx_ind; 583 struct mlx4_en_priv *priv = netdev_priv(dev);
584 u16 vlan_tag = 0;
623 585
624 /* Obtain VLAN information if present */ 586 /* If we support per priority flow control and the packet contains
625 if (priv->vlgrp && vlan_tx_tag_present(skb)) { 587 * a vlan tag, send the packet to the TX ring assigned to that priority
626 *vlan_tag = vlan_tx_tag_get(skb); 588 */
627 /* Set the Tx ring to use according to vlan priority */ 589 if (priv->prof->rx_ppp && priv->vlgrp && vlan_tx_tag_present(skb)) {
628 tx_ind = priv->tx_prio_map[*vlan_tag >> 13]; 590 vlan_tag = vlan_tx_tag_get(skb);
629 } else { 591 return MLX4_EN_NUM_TX_RINGS + (vlan_tag >> 13);
630 *vlan_tag = 0;
631 tx_ind = 0;
632 } 592 }
633 return tx_ind; 593
594 return skb_tx_hash(dev, skb);
634} 595}
635 596
636int mlx4_en_xmit(struct sk_buff *skb, struct net_device *dev) 597int mlx4_en_xmit(struct sk_buff *skb, struct net_device *dev)
@@ -650,7 +611,7 @@ int mlx4_en_xmit(struct sk_buff *skb, struct net_device *dev)
650 dma_addr_t dma; 611 dma_addr_t dma;
651 u32 index; 612 u32 index;
652 __be32 op_own; 613 __be32 op_own;
653 u16 vlan_tag; 614 u16 vlan_tag = 0;
654 int i; 615 int i;
655 int lso_header_size; 616 int lso_header_size;
656 void *fragptr; 617 void *fragptr;
@@ -673,15 +634,16 @@ int mlx4_en_xmit(struct sk_buff *skb, struct net_device *dev)
673 return NETDEV_TX_OK; 634 return NETDEV_TX_OK;
674 } 635 }
675 636
676 tx_ind = get_vlan_info(priv, skb, &vlan_tag); 637 tx_ind = skb->queue_mapping;
677 ring = &priv->tx_ring[tx_ind]; 638 ring = &priv->tx_ring[tx_ind];
639 if (priv->vlgrp && vlan_tx_tag_present(skb))
640 vlan_tag = vlan_tx_tag_get(skb);
678 641
679 /* Check available TXBBs And 2K spare for prefetch */ 642 /* Check available TXBBs And 2K spare for prefetch */
680 if (unlikely(((int)(ring->prod - ring->cons)) > 643 if (unlikely(((int)(ring->prod - ring->cons)) >
681 ring->size - HEADROOM - MAX_DESC_TXBBS)) { 644 ring->size - HEADROOM - MAX_DESC_TXBBS)) {
682 /* every full Tx ring stops queue. 645 /* every full Tx ring stops queue */
683 * TODO: implement multi-queue support (per-queue stop) */ 646 netif_tx_stop_queue(netdev_get_tx_queue(dev, tx_ind));
684 netif_stop_queue(dev);
685 ring->blocked = 1; 647 ring->blocked = 1;
686 priv->port_stats.queue_stopped++; 648 priv->port_stats.queue_stopped++;
687 649
diff --git a/drivers/net/mlx4/mlx4_en.h b/drivers/net/mlx4/mlx4_en.h
index fcbfcfc11568..4de8db00809d 100644
--- a/drivers/net/mlx4/mlx4_en.h
+++ b/drivers/net/mlx4/mlx4_en.h
@@ -139,8 +139,10 @@ enum {
139#define MLX4_EN_MIN_RX_SIZE (MLX4_EN_ALLOC_SIZE / SMP_CACHE_BYTES) 139#define MLX4_EN_MIN_RX_SIZE (MLX4_EN_ALLOC_SIZE / SMP_CACHE_BYTES)
140#define MLX4_EN_MIN_TX_SIZE (4096 / TXBB_SIZE) 140#define MLX4_EN_MIN_TX_SIZE (4096 / TXBB_SIZE)
141 141
142#define MLX4_EN_TX_RING_NUM 9 142#define MLX4_EN_SMALL_PKT_SIZE 64
143#define MLX4_EN_DEF_TX_RING_SIZE 1024 143#define MLX4_EN_NUM_TX_RINGS 8
144#define MLX4_EN_NUM_PPP_RINGS 8
145#define MLX4_EN_DEF_TX_RING_SIZE 512
144#define MLX4_EN_DEF_RX_RING_SIZE 1024 146#define MLX4_EN_DEF_RX_RING_SIZE 1024
145 147
146/* Target number of packets to coalesce with interrupt moderation */ 148/* Target number of packets to coalesce with interrupt moderation */
@@ -478,7 +480,6 @@ struct mlx4_en_priv {
478 int base_qpn; 480 int base_qpn;
479 481
480 struct mlx4_en_rss_map rss_map; 482 struct mlx4_en_rss_map rss_map;
481 u16 tx_prio_map[8];
482 u32 flags; 483 u32 flags;
483#define MLX4_EN_FLAG_PROMISC 0x1 484#define MLX4_EN_FLAG_PROMISC 0x1
484 u32 tx_ring_num; 485 u32 tx_ring_num;
@@ -526,6 +527,7 @@ int mlx4_en_arm_cq(struct mlx4_en_priv *priv, struct mlx4_en_cq *cq);
526 527
527void mlx4_en_poll_tx_cq(unsigned long data); 528void mlx4_en_poll_tx_cq(unsigned long data);
528void mlx4_en_tx_irq(struct mlx4_cq *mcq); 529void mlx4_en_tx_irq(struct mlx4_cq *mcq);
530u16 mlx4_en_select_queue(struct net_device *dev, struct sk_buff *skb);
529int mlx4_en_xmit(struct sk_buff *skb, struct net_device *dev); 531int mlx4_en_xmit(struct sk_buff *skb, struct net_device *dev);
530 532
531int mlx4_en_create_tx_ring(struct mlx4_en_priv *priv, struct mlx4_en_tx_ring *ring, 533int mlx4_en_create_tx_ring(struct mlx4_en_priv *priv, struct mlx4_en_tx_ring *ring,
@@ -560,7 +562,6 @@ void mlx4_en_calc_rx_buf(struct net_device *dev);
560void mlx4_en_set_default_rss_map(struct mlx4_en_priv *priv, 562void mlx4_en_set_default_rss_map(struct mlx4_en_priv *priv,
561 struct mlx4_en_rss_map *rss_map, 563 struct mlx4_en_rss_map *rss_map,
562 int num_entries, int num_rings); 564 int num_entries, int num_rings);
563void mlx4_en_set_prio_map(struct mlx4_en_priv *priv, u16 *prio_map, u32 ring_num);
564int mlx4_en_config_rss_steer(struct mlx4_en_priv *priv); 565int mlx4_en_config_rss_steer(struct mlx4_en_priv *priv);
565void mlx4_en_release_rss_steer(struct mlx4_en_priv *priv); 566void mlx4_en_release_rss_steer(struct mlx4_en_priv *priv);
566int mlx4_en_free_tx_buf(struct net_device *dev, struct mlx4_en_tx_ring *ring); 567int mlx4_en_free_tx_buf(struct net_device *dev, struct mlx4_en_tx_ring *ring);