diff options
author | Yevgeny Petrilin <yevgenyp@mellanox.co.il> | 2011-03-22 18:37:52 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2011-03-23 15:24:18 -0400 |
commit | 1fb9876e9bf895ea4127ff17180f1b2ab37771b6 (patch) | |
tree | 4d26408ec346531ee99e01c0c397c73e782cacef /drivers/net | |
parent | 0b7ca5a928e2271bbc225e9e1ac1f22e9fbee54f (diff) |
mlx4_en: using new mlx4 interrupt scheme
Each RX ring will have its own interrupt vector, and TX rings will share one
(we mostly use polling for TX completions).
The vectors are assigned first time device is opened, and its name includes
the interface name and ring number.
Signed-off-by: Markuze Alex <markuze@mellanox.co.il>
Signed-off-by: Yevgeny Petrilin <yevgenyp@mellanox.co.il>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net')
-rw-r--r-- | drivers/net/mlx4/en_cq.c | 38 | ||||
-rw-r--r-- | drivers/net/mlx4/en_ethtool.c | 2 | ||||
-rw-r--r-- | drivers/net/mlx4/en_main.c | 20 | ||||
-rw-r--r-- | drivers/net/mlx4/en_netdev.c | 18 | ||||
-rw-r--r-- | drivers/net/mlx4/mlx4_en.h | 7 |
5 files changed, 62 insertions, 23 deletions
diff --git a/drivers/net/mlx4/en_cq.c b/drivers/net/mlx4/en_cq.c index 21786ad4455e..ec4b6d047fe0 100644 --- a/drivers/net/mlx4/en_cq.c +++ b/drivers/net/mlx4/en_cq.c | |||
@@ -51,13 +51,10 @@ int mlx4_en_create_cq(struct mlx4_en_priv *priv, | |||
51 | int err; | 51 | int err; |
52 | 52 | ||
53 | cq->size = entries; | 53 | cq->size = entries; |
54 | if (mode == RX) { | 54 | if (mode == RX) |
55 | cq->buf_size = cq->size * sizeof(struct mlx4_cqe); | 55 | cq->buf_size = cq->size * sizeof(struct mlx4_cqe); |
56 | cq->vector = ring % mdev->dev->caps.num_comp_vectors; | 56 | else |
57 | } else { | ||
58 | cq->buf_size = sizeof(struct mlx4_cqe); | 57 | cq->buf_size = sizeof(struct mlx4_cqe); |
59 | cq->vector = 0; | ||
60 | } | ||
61 | 58 | ||
62 | cq->ring = ring; | 59 | cq->ring = ring; |
63 | cq->is_tx = mode; | 60 | cq->is_tx = mode; |
@@ -80,7 +77,8 @@ int mlx4_en_create_cq(struct mlx4_en_priv *priv, | |||
80 | int mlx4_en_activate_cq(struct mlx4_en_priv *priv, struct mlx4_en_cq *cq) | 77 | int mlx4_en_activate_cq(struct mlx4_en_priv *priv, struct mlx4_en_cq *cq) |
81 | { | 78 | { |
82 | struct mlx4_en_dev *mdev = priv->mdev; | 79 | struct mlx4_en_dev *mdev = priv->mdev; |
83 | int err; | 80 | int err = 0; |
81 | char name[25]; | ||
84 | 82 | ||
85 | cq->dev = mdev->pndev[priv->port]; | 83 | cq->dev = mdev->pndev[priv->port]; |
86 | cq->mcq.set_ci_db = cq->wqres.db.db; | 84 | cq->mcq.set_ci_db = cq->wqres.db.db; |
@@ -89,6 +87,29 @@ int mlx4_en_activate_cq(struct mlx4_en_priv *priv, struct mlx4_en_cq *cq) | |||
89 | *cq->mcq.arm_db = 0; | 87 | *cq->mcq.arm_db = 0; |
90 | memset(cq->buf, 0, cq->buf_size); | 88 | memset(cq->buf, 0, cq->buf_size); |
91 | 89 | ||
90 | if (cq->is_tx == RX) { | ||
91 | if (mdev->dev->caps.comp_pool) { | ||
92 | if (!cq->vector) { | ||
93 | sprintf(name , "%s-rx-%d", priv->dev->name, cq->ring); | ||
94 | if (mlx4_assign_eq(mdev->dev, name, &cq->vector)) { | ||
95 | cq->vector = (cq->ring + 1 + priv->port) % | ||
96 | mdev->dev->caps.num_comp_vectors; | ||
97 | mlx4_warn(mdev, "Failed Assigning an EQ to " | ||
98 | "%s_rx-%d ,Falling back to legacy EQ's\n", | ||
99 | priv->dev->name, cq->ring); | ||
100 | } | ||
101 | } | ||
102 | } else { | ||
103 | cq->vector = (cq->ring + 1 + priv->port) % | ||
104 | mdev->dev->caps.num_comp_vectors; | ||
105 | } | ||
106 | } else { | ||
107 | if (!cq->vector || !mdev->dev->caps.comp_pool) { | ||
108 | /*Fallback to legacy pool in case of error*/ | ||
109 | cq->vector = 0; | ||
110 | } | ||
111 | } | ||
112 | |||
92 | if (!cq->is_tx) | 113 | if (!cq->is_tx) |
93 | cq->size = priv->rx_ring[cq->ring].actual_size; | 114 | cq->size = priv->rx_ring[cq->ring].actual_size; |
94 | 115 | ||
@@ -112,12 +133,15 @@ int mlx4_en_activate_cq(struct mlx4_en_priv *priv, struct mlx4_en_cq *cq) | |||
112 | return 0; | 133 | return 0; |
113 | } | 134 | } |
114 | 135 | ||
115 | void mlx4_en_destroy_cq(struct mlx4_en_priv *priv, struct mlx4_en_cq *cq) | 136 | void mlx4_en_destroy_cq(struct mlx4_en_priv *priv, struct mlx4_en_cq *cq, |
137 | bool reserve_vectors) | ||
116 | { | 138 | { |
117 | struct mlx4_en_dev *mdev = priv->mdev; | 139 | struct mlx4_en_dev *mdev = priv->mdev; |
118 | 140 | ||
119 | mlx4_en_unmap_buffer(&cq->wqres.buf); | 141 | mlx4_en_unmap_buffer(&cq->wqres.buf); |
120 | mlx4_free_hwq_res(mdev->dev, &cq->wqres, cq->buf_size); | 142 | mlx4_free_hwq_res(mdev->dev, &cq->wqres, cq->buf_size); |
143 | if (priv->mdev->dev->caps.comp_pool && cq->vector && !reserve_vectors) | ||
144 | mlx4_release_eq(priv->mdev->dev, cq->vector); | ||
121 | cq->buf_size = 0; | 145 | cq->buf_size = 0; |
122 | cq->buf = NULL; | 146 | cq->buf = NULL; |
123 | } | 147 | } |
diff --git a/drivers/net/mlx4/en_ethtool.c b/drivers/net/mlx4/en_ethtool.c index 056152b3ff58..8cfe8586ed2d 100644 --- a/drivers/net/mlx4/en_ethtool.c +++ b/drivers/net/mlx4/en_ethtool.c | |||
@@ -388,7 +388,7 @@ static int mlx4_en_set_ringparam(struct net_device *dev, | |||
388 | mlx4_en_stop_port(dev); | 388 | mlx4_en_stop_port(dev); |
389 | } | 389 | } |
390 | 390 | ||
391 | mlx4_en_free_resources(priv); | 391 | mlx4_en_free_resources(priv, true); |
392 | 392 | ||
393 | priv->prof->tx_ring_size = tx_size; | 393 | priv->prof->tx_ring_size = tx_size; |
394 | priv->prof->rx_ring_size = rx_size; | 394 | priv->prof->rx_ring_size = rx_size; |
diff --git a/drivers/net/mlx4/en_main.c b/drivers/net/mlx4/en_main.c index 1ff6ca6466ed..29aaa4303991 100644 --- a/drivers/net/mlx4/en_main.c +++ b/drivers/net/mlx4/en_main.c | |||
@@ -241,16 +241,18 @@ static void *mlx4_en_add(struct mlx4_dev *dev) | |||
241 | mlx4_foreach_port(i, dev, MLX4_PORT_TYPE_ETH) | 241 | mlx4_foreach_port(i, dev, MLX4_PORT_TYPE_ETH) |
242 | mdev->port_cnt++; | 242 | mdev->port_cnt++; |
243 | 243 | ||
244 | /* If we did not receive an explicit number of Rx rings, default to | ||
245 | * the number of completion vectors populated by the mlx4_core */ | ||
246 | mlx4_foreach_port(i, dev, MLX4_PORT_TYPE_ETH) { | 244 | mlx4_foreach_port(i, dev, MLX4_PORT_TYPE_ETH) { |
247 | mlx4_info(mdev, "Using %d tx rings for port:%d\n", | 245 | if (!dev->caps.comp_pool) { |
248 | mdev->profile.prof[i].tx_ring_num, i); | 246 | mdev->profile.prof[i].rx_ring_num = |
249 | mdev->profile.prof[i].rx_ring_num = min_t(int, | 247 | rounddown_pow_of_two(max_t(int, MIN_RX_RINGS, |
250 | roundup_pow_of_two(dev->caps.num_comp_vectors), | 248 | min_t(int, |
251 | MAX_RX_RINGS); | 249 | dev->caps.num_comp_vectors, |
252 | mlx4_info(mdev, "Defaulting to %d rx rings for port:%d\n", | 250 | MAX_RX_RINGS))); |
253 | mdev->profile.prof[i].rx_ring_num, i); | 251 | } else { |
252 | mdev->profile.prof[i].rx_ring_num = rounddown_pow_of_two( | ||
253 | min_t(int, dev->caps.comp_pool/ | ||
254 | dev->caps.num_ports - 1 , MAX_MSIX_P_PORT - 1)); | ||
255 | } | ||
254 | } | 256 | } |
255 | 257 | ||
256 | /* Create our own workqueue for reset/multicast tasks | 258 | /* Create our own workqueue for reset/multicast tasks |
diff --git a/drivers/net/mlx4/en_netdev.c b/drivers/net/mlx4/en_netdev.c index 5727bf5ad452..f6ed315b4b89 100644 --- a/drivers/net/mlx4/en_netdev.c +++ b/drivers/net/mlx4/en_netdev.c | |||
@@ -557,6 +557,7 @@ int mlx4_en_start_port(struct net_device *dev) | |||
557 | int err = 0; | 557 | int err = 0; |
558 | int i; | 558 | int i; |
559 | int j; | 559 | int j; |
560 | char name[32]; | ||
560 | 561 | ||
561 | if (priv->port_up) { | 562 | if (priv->port_up) { |
562 | en_dbg(DRV, priv, "start port called while port already up\n"); | 563 | en_dbg(DRV, priv, "start port called while port already up\n"); |
@@ -601,10 +602,19 @@ int mlx4_en_start_port(struct net_device *dev) | |||
601 | goto cq_err; | 602 | goto cq_err; |
602 | } | 603 | } |
603 | 604 | ||
605 | if (mdev->dev->caps.comp_pool && !priv->tx_vector) { | ||
606 | sprintf(name , "%s-tx", priv->dev->name); | ||
607 | if (mlx4_assign_eq(mdev->dev , name, &priv->tx_vector)) { | ||
608 | mlx4_warn(mdev, "Failed Assigning an EQ to " | ||
609 | "%s_tx ,Falling back to legacy " | ||
610 | "EQ's\n", priv->dev->name); | ||
611 | } | ||
612 | } | ||
604 | /* Configure tx cq's and rings */ | 613 | /* Configure tx cq's and rings */ |
605 | for (i = 0; i < priv->tx_ring_num; i++) { | 614 | for (i = 0; i < priv->tx_ring_num; i++) { |
606 | /* Configure cq */ | 615 | /* Configure cq */ |
607 | cq = &priv->tx_cq[i]; | 616 | cq = &priv->tx_cq[i]; |
617 | cq->vector = priv->tx_vector; | ||
608 | err = mlx4_en_activate_cq(priv, cq); | 618 | err = mlx4_en_activate_cq(priv, cq); |
609 | if (err) { | 619 | if (err) { |
610 | en_err(priv, "Failed allocating Tx CQ\n"); | 620 | en_err(priv, "Failed allocating Tx CQ\n"); |
@@ -819,7 +829,7 @@ static int mlx4_en_close(struct net_device *dev) | |||
819 | return 0; | 829 | return 0; |
820 | } | 830 | } |
821 | 831 | ||
822 | void mlx4_en_free_resources(struct mlx4_en_priv *priv) | 832 | void mlx4_en_free_resources(struct mlx4_en_priv *priv, bool reserve_vectors) |
823 | { | 833 | { |
824 | int i; | 834 | int i; |
825 | 835 | ||
@@ -827,14 +837,14 @@ void mlx4_en_free_resources(struct mlx4_en_priv *priv) | |||
827 | if (priv->tx_ring[i].tx_info) | 837 | if (priv->tx_ring[i].tx_info) |
828 | mlx4_en_destroy_tx_ring(priv, &priv->tx_ring[i]); | 838 | mlx4_en_destroy_tx_ring(priv, &priv->tx_ring[i]); |
829 | if (priv->tx_cq[i].buf) | 839 | if (priv->tx_cq[i].buf) |
830 | mlx4_en_destroy_cq(priv, &priv->tx_cq[i]); | 840 | mlx4_en_destroy_cq(priv, &priv->tx_cq[i], reserve_vectors); |
831 | } | 841 | } |
832 | 842 | ||
833 | for (i = 0; i < priv->rx_ring_num; i++) { | 843 | for (i = 0; i < priv->rx_ring_num; i++) { |
834 | if (priv->rx_ring[i].rx_info) | 844 | if (priv->rx_ring[i].rx_info) |
835 | mlx4_en_destroy_rx_ring(priv, &priv->rx_ring[i]); | 845 | mlx4_en_destroy_rx_ring(priv, &priv->rx_ring[i]); |
836 | if (priv->rx_cq[i].buf) | 846 | if (priv->rx_cq[i].buf) |
837 | mlx4_en_destroy_cq(priv, &priv->rx_cq[i]); | 847 | mlx4_en_destroy_cq(priv, &priv->rx_cq[i], reserve_vectors); |
838 | } | 848 | } |
839 | } | 849 | } |
840 | 850 | ||
@@ -896,7 +906,7 @@ void mlx4_en_destroy_netdev(struct net_device *dev) | |||
896 | mdev->pndev[priv->port] = NULL; | 906 | mdev->pndev[priv->port] = NULL; |
897 | mutex_unlock(&mdev->state_lock); | 907 | mutex_unlock(&mdev->state_lock); |
898 | 908 | ||
899 | mlx4_en_free_resources(priv); | 909 | mlx4_en_free_resources(priv, false); |
900 | free_netdev(dev); | 910 | free_netdev(dev); |
901 | } | 911 | } |
902 | 912 | ||
diff --git a/drivers/net/mlx4/mlx4_en.h b/drivers/net/mlx4/mlx4_en.h index 5387c4e9f295..2db245fcd84b 100644 --- a/drivers/net/mlx4/mlx4_en.h +++ b/drivers/net/mlx4/mlx4_en.h | |||
@@ -62,6 +62,7 @@ | |||
62 | #define MLX4_EN_PAGE_SHIFT 12 | 62 | #define MLX4_EN_PAGE_SHIFT 12 |
63 | #define MLX4_EN_PAGE_SIZE (1 << MLX4_EN_PAGE_SHIFT) | 63 | #define MLX4_EN_PAGE_SIZE (1 << MLX4_EN_PAGE_SHIFT) |
64 | #define MAX_RX_RINGS 16 | 64 | #define MAX_RX_RINGS 16 |
65 | #define MIN_RX_RINGS 4 | ||
65 | #define TXBB_SIZE 64 | 66 | #define TXBB_SIZE 64 |
66 | #define HEADROOM (2048 / TXBB_SIZE + 1) | 67 | #define HEADROOM (2048 / TXBB_SIZE + 1) |
67 | #define STAMP_STRIDE 64 | 68 | #define STAMP_STRIDE 64 |
@@ -462,6 +463,7 @@ struct mlx4_en_priv { | |||
462 | u16 log_rx_info; | 463 | u16 log_rx_info; |
463 | 464 | ||
464 | struct mlx4_en_tx_ring tx_ring[MAX_TX_RINGS]; | 465 | struct mlx4_en_tx_ring tx_ring[MAX_TX_RINGS]; |
466 | int tx_vector; | ||
465 | struct mlx4_en_rx_ring rx_ring[MAX_RX_RINGS]; | 467 | struct mlx4_en_rx_ring rx_ring[MAX_RX_RINGS]; |
466 | struct mlx4_en_cq tx_cq[MAX_TX_RINGS]; | 468 | struct mlx4_en_cq tx_cq[MAX_TX_RINGS]; |
467 | struct mlx4_en_cq rx_cq[MAX_RX_RINGS]; | 469 | struct mlx4_en_cq rx_cq[MAX_RX_RINGS]; |
@@ -487,12 +489,13 @@ int mlx4_en_init_netdev(struct mlx4_en_dev *mdev, int port, | |||
487 | int mlx4_en_start_port(struct net_device *dev); | 489 | int mlx4_en_start_port(struct net_device *dev); |
488 | void mlx4_en_stop_port(struct net_device *dev); | 490 | void mlx4_en_stop_port(struct net_device *dev); |
489 | 491 | ||
490 | void mlx4_en_free_resources(struct mlx4_en_priv *priv); | 492 | void mlx4_en_free_resources(struct mlx4_en_priv *priv, bool reserve_vectors); |
491 | int mlx4_en_alloc_resources(struct mlx4_en_priv *priv); | 493 | int mlx4_en_alloc_resources(struct mlx4_en_priv *priv); |
492 | 494 | ||
493 | int mlx4_en_create_cq(struct mlx4_en_priv *priv, struct mlx4_en_cq *cq, | 495 | int mlx4_en_create_cq(struct mlx4_en_priv *priv, struct mlx4_en_cq *cq, |
494 | int entries, int ring, enum cq_type mode); | 496 | int entries, int ring, enum cq_type mode); |
495 | void mlx4_en_destroy_cq(struct mlx4_en_priv *priv, struct mlx4_en_cq *cq); | 497 | void mlx4_en_destroy_cq(struct mlx4_en_priv *priv, struct mlx4_en_cq *cq, |
498 | bool reserve_vectors); | ||
496 | int mlx4_en_activate_cq(struct mlx4_en_priv *priv, struct mlx4_en_cq *cq); | 499 | int mlx4_en_activate_cq(struct mlx4_en_priv *priv, struct mlx4_en_cq *cq); |
497 | void mlx4_en_deactivate_cq(struct mlx4_en_priv *priv, struct mlx4_en_cq *cq); | 500 | void mlx4_en_deactivate_cq(struct mlx4_en_priv *priv, struct mlx4_en_cq *cq); |
498 | int mlx4_en_set_cq_moder(struct mlx4_en_priv *priv, struct mlx4_en_cq *cq); | 501 | int mlx4_en_set_cq_moder(struct mlx4_en_priv *priv, struct mlx4_en_cq *cq); |