aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorYevgeny Petrilin <yevgenyp@mellanox.co.il>2011-03-22 18:38:31 -0400
committerDavid S. Miller <davem@davemloft.net>2011-03-23 15:24:22 -0400
commit1679200f91da6a054b06954c9bd3eeed29b6731f (patch)
treea447268debe479a257cfff4c7e5e86151eef6583
parentb12d93d63c3217f0ec923ff938b12a744e242ffa (diff)
mlx4_en: Enabling new steering
The mlx4_en module now uses the new steering mechanism. The RX packets are now steered through the MCG table instead of Mac table for unicast, and default entry for multicast. The feature is enabled through INIT_HCA Signed-off-by: Yevgeny Petrilin <yevgenyp@mellanox.co.il> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--drivers/net/mlx4/en_netdev.c133
-rw-r--r--drivers/net/mlx4/en_port.c11
-rw-r--r--drivers/net/mlx4/en_port.h19
-rw-r--r--drivers/net/mlx4/en_rx.c11
-rw-r--r--drivers/net/mlx4/fw.c3
-rw-r--r--drivers/net/mlx4/mlx4.h6
-rw-r--r--drivers/net/mlx4/mlx4_en.h1
-rw-r--r--drivers/net/mlx4/port.c165
-rw-r--r--include/linux/mlx4/device.h12
9 files changed, 300 insertions, 61 deletions
diff --git a/drivers/net/mlx4/en_netdev.c b/drivers/net/mlx4/en_netdev.c
index f6ed315b4b89..08e680100db8 100644
--- a/drivers/net/mlx4/en_netdev.c
+++ b/drivers/net/mlx4/en_netdev.c
@@ -156,9 +156,8 @@ static void mlx4_en_do_set_mac(struct work_struct *work)
156 mutex_lock(&mdev->state_lock); 156 mutex_lock(&mdev->state_lock);
157 if (priv->port_up) { 157 if (priv->port_up) {
158 /* Remove old MAC and insert the new one */ 158 /* Remove old MAC and insert the new one */
159 mlx4_unregister_mac(mdev->dev, priv->port, priv->mac_index); 159 err = mlx4_replace_mac(mdev->dev, priv->port,
160 err = mlx4_register_mac(mdev->dev, priv->port, 160 priv->base_qpn, priv->mac, 0);
161 priv->mac, &priv->mac_index);
162 if (err) 161 if (err)
163 en_err(priv, "Failed changing HW MAC address\n"); 162 en_err(priv, "Failed changing HW MAC address\n");
164 } else 163 } else
@@ -214,6 +213,7 @@ static void mlx4_en_do_set_multicast(struct work_struct *work)
214 struct mlx4_en_dev *mdev = priv->mdev; 213 struct mlx4_en_dev *mdev = priv->mdev;
215 struct net_device *dev = priv->dev; 214 struct net_device *dev = priv->dev;
216 u64 mcast_addr = 0; 215 u64 mcast_addr = 0;
216 u8 mc_list[16] = {0};
217 int err; 217 int err;
218 218
219 mutex_lock(&mdev->state_lock); 219 mutex_lock(&mdev->state_lock);
@@ -239,8 +239,12 @@ static void mlx4_en_do_set_multicast(struct work_struct *work)
239 priv->flags |= MLX4_EN_FLAG_PROMISC; 239 priv->flags |= MLX4_EN_FLAG_PROMISC;
240 240
241 /* Enable promiscouos mode */ 241 /* Enable promiscouos mode */
242 err = mlx4_SET_PORT_qpn_calc(mdev->dev, priv->port, 242 if (!mdev->dev->caps.vep_uc_steering)
243 priv->base_qpn, 1); 243 err = mlx4_SET_PORT_qpn_calc(mdev->dev, priv->port,
244 priv->base_qpn, 1);
245 else
246 err = mlx4_unicast_promisc_add(mdev->dev, priv->base_qpn,
247 priv->port);
244 if (err) 248 if (err)
245 en_err(priv, "Failed enabling " 249 en_err(priv, "Failed enabling "
246 "promiscous mode\n"); 250 "promiscous mode\n");
@@ -252,10 +256,21 @@ static void mlx4_en_do_set_multicast(struct work_struct *work)
252 en_err(priv, "Failed disabling " 256 en_err(priv, "Failed disabling "
253 "multicast filter\n"); 257 "multicast filter\n");
254 258
255 /* Disable port VLAN filter */ 259 /* Add the default qp number as multicast promisc */
256 err = mlx4_SET_VLAN_FLTR(mdev->dev, priv->port, NULL); 260 if (!(priv->flags & MLX4_EN_FLAG_MC_PROMISC)) {
257 if (err) 261 err = mlx4_multicast_promisc_add(mdev->dev, priv->base_qpn,
258 en_err(priv, "Failed disabling VLAN filter\n"); 262 priv->port);
263 if (err)
264 en_err(priv, "Failed entering multicast promisc mode\n");
265 priv->flags |= MLX4_EN_FLAG_MC_PROMISC;
266 }
267
268 if (priv->vlgrp) {
269 /* Disable port VLAN filter */
270 err = mlx4_SET_VLAN_FLTR(mdev->dev, priv->port, NULL);
271 if (err)
272 en_err(priv, "Failed disabling VLAN filter\n");
273 }
259 } 274 }
260 goto out; 275 goto out;
261 } 276 }
@@ -270,11 +285,24 @@ static void mlx4_en_do_set_multicast(struct work_struct *work)
270 priv->flags &= ~MLX4_EN_FLAG_PROMISC; 285 priv->flags &= ~MLX4_EN_FLAG_PROMISC;
271 286
272 /* Disable promiscouos mode */ 287 /* Disable promiscouos mode */
273 err = mlx4_SET_PORT_qpn_calc(mdev->dev, priv->port, 288 if (!mdev->dev->caps.vep_uc_steering)
274 priv->base_qpn, 0); 289 err = mlx4_SET_PORT_qpn_calc(mdev->dev, priv->port,
290 priv->base_qpn, 0);
291 else
292 err = mlx4_unicast_promisc_remove(mdev->dev, priv->base_qpn,
293 priv->port);
275 if (err) 294 if (err)
276 en_err(priv, "Failed disabling promiscous mode\n"); 295 en_err(priv, "Failed disabling promiscous mode\n");
277 296
297 /* Disable Multicast promisc */
298 if (priv->flags & MLX4_EN_FLAG_MC_PROMISC) {
299 err = mlx4_multicast_promisc_remove(mdev->dev, priv->base_qpn,
300 priv->port);
301 if (err)
302 en_err(priv, "Failed disabling multicast promiscous mode\n");
303 priv->flags &= ~MLX4_EN_FLAG_MC_PROMISC;
304 }
305
278 /* Enable port VLAN filter */ 306 /* Enable port VLAN filter */
279 err = mlx4_SET_VLAN_FLTR(mdev->dev, priv->port, priv->vlgrp); 307 err = mlx4_SET_VLAN_FLTR(mdev->dev, priv->port, priv->vlgrp);
280 if (err) 308 if (err)
@@ -287,14 +315,38 @@ static void mlx4_en_do_set_multicast(struct work_struct *work)
287 0, MLX4_MCAST_DISABLE); 315 0, MLX4_MCAST_DISABLE);
288 if (err) 316 if (err)
289 en_err(priv, "Failed disabling multicast filter\n"); 317 en_err(priv, "Failed disabling multicast filter\n");
318
319 /* Add the default qp number as multicast promisc */
320 if (!(priv->flags & MLX4_EN_FLAG_MC_PROMISC)) {
321 err = mlx4_multicast_promisc_add(mdev->dev, priv->base_qpn,
322 priv->port);
323 if (err)
324 en_err(priv, "Failed entering multicast promisc mode\n");
325 priv->flags |= MLX4_EN_FLAG_MC_PROMISC;
326 }
290 } else { 327 } else {
291 int i; 328 int i;
329 /* Disable Multicast promisc */
330 if (priv->flags & MLX4_EN_FLAG_MC_PROMISC) {
331 err = mlx4_multicast_promisc_remove(mdev->dev, priv->base_qpn,
332 priv->port);
333 if (err)
334 en_err(priv, "Failed disabling multicast promiscous mode\n");
335 priv->flags &= ~MLX4_EN_FLAG_MC_PROMISC;
336 }
292 337
293 err = mlx4_SET_MCAST_FLTR(mdev->dev, priv->port, 0, 338 err = mlx4_SET_MCAST_FLTR(mdev->dev, priv->port, 0,
294 0, MLX4_MCAST_DISABLE); 339 0, MLX4_MCAST_DISABLE);
295 if (err) 340 if (err)
296 en_err(priv, "Failed disabling multicast filter\n"); 341 en_err(priv, "Failed disabling multicast filter\n");
297 342
343 /* Detach our qp from all the multicast addresses */
344 for (i = 0; i < priv->mc_addrs_cnt; i++) {
345 memcpy(&mc_list[10], priv->mc_addrs + i * ETH_ALEN, ETH_ALEN);
346 mc_list[5] = priv->port;
347 mlx4_multicast_detach(mdev->dev, &priv->rss_map.indir_qp,
348 mc_list, MLX4_PROT_ETH);
349 }
298 /* Flush mcast filter and init it with broadcast address */ 350 /* Flush mcast filter and init it with broadcast address */
299 mlx4_SET_MCAST_FLTR(mdev->dev, priv->port, ETH_BCAST, 351 mlx4_SET_MCAST_FLTR(mdev->dev, priv->port, ETH_BCAST,
300 1, MLX4_MCAST_CONFIG); 352 1, MLX4_MCAST_CONFIG);
@@ -307,6 +359,10 @@ static void mlx4_en_do_set_multicast(struct work_struct *work)
307 for (i = 0; i < priv->mc_addrs_cnt; i++) { 359 for (i = 0; i < priv->mc_addrs_cnt; i++) {
308 mcast_addr = 360 mcast_addr =
309 mlx4_en_mac_to_u64(priv->mc_addrs + i * ETH_ALEN); 361 mlx4_en_mac_to_u64(priv->mc_addrs + i * ETH_ALEN);
362 memcpy(&mc_list[10], priv->mc_addrs + i * ETH_ALEN, ETH_ALEN);
363 mc_list[5] = priv->port;
364 mlx4_multicast_attach(mdev->dev, &priv->rss_map.indir_qp,
365 mc_list, 0, MLX4_PROT_ETH);
310 mlx4_SET_MCAST_FLTR(mdev->dev, priv->port, 366 mlx4_SET_MCAST_FLTR(mdev->dev, priv->port,
311 mcast_addr, 0, MLX4_MCAST_CONFIG); 367 mcast_addr, 0, MLX4_MCAST_CONFIG);
312 } 368 }
@@ -314,8 +370,6 @@ static void mlx4_en_do_set_multicast(struct work_struct *work)
314 0, MLX4_MCAST_ENABLE); 370 0, MLX4_MCAST_ENABLE);
315 if (err) 371 if (err)
316 en_err(priv, "Failed enabling multicast filter\n"); 372 en_err(priv, "Failed enabling multicast filter\n");
317
318 mlx4_en_clear_list(dev);
319 } 373 }
320out: 374out:
321 mutex_unlock(&mdev->state_lock); 375 mutex_unlock(&mdev->state_lock);
@@ -557,6 +611,7 @@ int mlx4_en_start_port(struct net_device *dev)
557 int err = 0; 611 int err = 0;
558 int i; 612 int i;
559 int j; 613 int j;
614 u8 mc_list[16] = {0};
560 char name[32]; 615 char name[32];
561 616
562 if (priv->port_up) { 617 if (priv->port_up) {
@@ -596,10 +651,20 @@ int mlx4_en_start_port(struct net_device *dev)
596 ++rx_index; 651 ++rx_index;
597 } 652 }
598 653
654 /* Set port mac number */
655 en_dbg(DRV, priv, "Setting mac for port %d\n", priv->port);
656 err = mlx4_register_mac(mdev->dev, priv->port,
657 priv->mac, &priv->base_qpn, 0);
658 if (err) {
659 en_err(priv, "Failed setting port mac\n");
660 goto cq_err;
661 }
662 mdev->mac_removed[priv->port] = 0;
663
599 err = mlx4_en_config_rss_steer(priv); 664 err = mlx4_en_config_rss_steer(priv);
600 if (err) { 665 if (err) {
601 en_err(priv, "Failed configuring rss steering\n"); 666 en_err(priv, "Failed configuring rss steering\n");
602 goto cq_err; 667 goto mac_err;
603 } 668 }
604 669
605 if (mdev->dev->caps.comp_pool && !priv->tx_vector) { 670 if (mdev->dev->caps.comp_pool && !priv->tx_vector) {
@@ -661,24 +726,22 @@ int mlx4_en_start_port(struct net_device *dev)
661 en_err(priv, "Failed setting default qp numbers\n"); 726 en_err(priv, "Failed setting default qp numbers\n");
662 goto tx_err; 727 goto tx_err;
663 } 728 }
664 /* Set port mac number */
665 en_dbg(DRV, priv, "Setting mac for port %d\n", priv->port);
666 err = mlx4_register_mac(mdev->dev, priv->port,
667 priv->mac, &priv->mac_index);
668 if (err) {
669 en_err(priv, "Failed setting port mac\n");
670 goto tx_err;
671 }
672 mdev->mac_removed[priv->port] = 0;
673 729
674 /* Init port */ 730 /* Init port */
675 en_dbg(HW, priv, "Initializing port\n"); 731 en_dbg(HW, priv, "Initializing port\n");
676 err = mlx4_INIT_PORT(mdev->dev, priv->port); 732 err = mlx4_INIT_PORT(mdev->dev, priv->port);
677 if (err) { 733 if (err) {
678 en_err(priv, "Failed Initializing port\n"); 734 en_err(priv, "Failed Initializing port\n");
679 goto mac_err; 735 goto tx_err;
680 } 736 }
681 737
738 /* Attach rx QP to bradcast address */
739 memset(&mc_list[10], 0xff, ETH_ALEN);
740 mc_list[5] = priv->port;
741 if (mlx4_multicast_attach(mdev->dev, &priv->rss_map.indir_qp, mc_list,
742 0, MLX4_PROT_ETH))
743 mlx4_warn(mdev, "Failed Attaching Broadcast\n");
744
682 /* Schedule multicast task to populate multicast list */ 745 /* Schedule multicast task to populate multicast list */
683 queue_work(mdev->workqueue, &priv->mcast_task); 746 queue_work(mdev->workqueue, &priv->mcast_task);
684 747
@@ -686,8 +749,6 @@ int mlx4_en_start_port(struct net_device *dev)
686 netif_tx_start_all_queues(dev); 749 netif_tx_start_all_queues(dev);
687 return 0; 750 return 0;
688 751
689mac_err:
690 mlx4_unregister_mac(mdev->dev, priv->port, priv->mac_index);
691tx_err: 752tx_err:
692 while (tx_index--) { 753 while (tx_index--) {
693 mlx4_en_deactivate_tx_ring(priv, &priv->tx_ring[tx_index]); 754 mlx4_en_deactivate_tx_ring(priv, &priv->tx_ring[tx_index]);
@@ -695,6 +756,8 @@ tx_err:
695 } 756 }
696 757
697 mlx4_en_release_rss_steer(priv); 758 mlx4_en_release_rss_steer(priv);
759mac_err:
760 mlx4_unregister_mac(mdev->dev, priv->port, priv->base_qpn);
698cq_err: 761cq_err:
699 while (rx_index--) 762 while (rx_index--)
700 mlx4_en_deactivate_cq(priv, &priv->rx_cq[rx_index]); 763 mlx4_en_deactivate_cq(priv, &priv->rx_cq[rx_index]);
@@ -710,6 +773,7 @@ void mlx4_en_stop_port(struct net_device *dev)
710 struct mlx4_en_priv *priv = netdev_priv(dev); 773 struct mlx4_en_priv *priv = netdev_priv(dev);
711 struct mlx4_en_dev *mdev = priv->mdev; 774 struct mlx4_en_dev *mdev = priv->mdev;
712 int i; 775 int i;
776 u8 mc_list[16] = {0};
713 777
714 if (!priv->port_up) { 778 if (!priv->port_up) {
715 en_dbg(DRV, priv, "stop port called while port already down\n"); 779 en_dbg(DRV, priv, "stop port called while port already down\n");
@@ -724,8 +788,23 @@ void mlx4_en_stop_port(struct net_device *dev)
724 /* Set port as not active */ 788 /* Set port as not active */
725 priv->port_up = false; 789 priv->port_up = false;
726 790
791 /* Detach All multicasts */
792 memset(&mc_list[10], 0xff, ETH_ALEN);
793 mc_list[5] = priv->port;
794 mlx4_multicast_detach(mdev->dev, &priv->rss_map.indir_qp, mc_list,
795 MLX4_PROT_ETH);
796 for (i = 0; i < priv->mc_addrs_cnt; i++) {
797 memcpy(&mc_list[10], priv->mc_addrs + i * ETH_ALEN, ETH_ALEN);
798 mc_list[5] = priv->port;
799 mlx4_multicast_detach(mdev->dev, &priv->rss_map.indir_qp,
800 mc_list, MLX4_PROT_ETH);
801 }
802 mlx4_en_clear_list(dev);
803 /* Flush multicast filter */
804 mlx4_SET_MCAST_FLTR(mdev->dev, priv->port, 0, 1, MLX4_MCAST_CONFIG);
805
727 /* Unregister Mac address for the port */ 806 /* Unregister Mac address for the port */
728 mlx4_unregister_mac(mdev->dev, priv->port, priv->mac_index); 807 mlx4_unregister_mac(mdev->dev, priv->port, priv->base_qpn);
729 mdev->mac_removed[priv->port] = 1; 808 mdev->mac_removed[priv->port] = 1;
730 809
731 /* Free TX Rings */ 810 /* Free TX Rings */
diff --git a/drivers/net/mlx4/en_port.c b/drivers/net/mlx4/en_port.c
index a2b0bc4ada5d..f2a4f5dd313d 100644
--- a/drivers/net/mlx4/en_port.c
+++ b/drivers/net/mlx4/en_port.c
@@ -119,6 +119,10 @@ int mlx4_SET_PORT_qpn_calc(struct mlx4_dev *dev, u8 port, u32 base_qpn,
119 struct mlx4_set_port_rqp_calc_context *context; 119 struct mlx4_set_port_rqp_calc_context *context;
120 int err; 120 int err;
121 u32 in_mod; 121 u32 in_mod;
122 u32 m_promisc = (dev->caps.vep_mc_steering) ? MCAST_DIRECT : MCAST_DEFAULT;
123
124 if (dev->caps.vep_mc_steering && dev->caps.vep_uc_steering)
125 return 0;
122 126
123 mailbox = mlx4_alloc_cmd_mailbox(dev); 127 mailbox = mlx4_alloc_cmd_mailbox(dev);
124 if (IS_ERR(mailbox)) 128 if (IS_ERR(mailbox))
@@ -127,8 +131,11 @@ int mlx4_SET_PORT_qpn_calc(struct mlx4_dev *dev, u8 port, u32 base_qpn,
127 memset(context, 0, sizeof *context); 131 memset(context, 0, sizeof *context);
128 132
129 context->base_qpn = cpu_to_be32(base_qpn); 133 context->base_qpn = cpu_to_be32(base_qpn);
130 context->promisc = cpu_to_be32(promisc << SET_PORT_PROMISC_EN_SHIFT | base_qpn); 134 context->n_mac = 0x7;
131 context->mcast = cpu_to_be32(1 << SET_PORT_PROMISC_MODE_SHIFT | base_qpn); 135 context->promisc = cpu_to_be32(promisc << SET_PORT_PROMISC_SHIFT |
136 base_qpn);
137 context->mcast = cpu_to_be32(m_promisc << SET_PORT_MC_PROMISC_SHIFT |
138 base_qpn);
132 context->intra_no_vlan = 0; 139 context->intra_no_vlan = 0;
133 context->no_vlan = MLX4_NO_VLAN_IDX; 140 context->no_vlan = MLX4_NO_VLAN_IDX;
134 context->intra_vlan_miss = 0; 141 context->intra_vlan_miss = 0;
diff --git a/drivers/net/mlx4/en_port.h b/drivers/net/mlx4/en_port.h
index 092e814b1981..e3d73e41c567 100644
--- a/drivers/net/mlx4/en_port.h
+++ b/drivers/net/mlx4/en_port.h
@@ -36,8 +36,8 @@
36 36
37 37
38#define SET_PORT_GEN_ALL_VALID 0x7 38#define SET_PORT_GEN_ALL_VALID 0x7
39#define SET_PORT_PROMISC_EN_SHIFT 31 39#define SET_PORT_PROMISC_SHIFT 31
40#define SET_PORT_PROMISC_MODE_SHIFT 30 40#define SET_PORT_MC_PROMISC_SHIFT 30
41 41
42enum { 42enum {
43 MLX4_CMD_SET_VLAN_FLTR = 0x47, 43 MLX4_CMD_SET_VLAN_FLTR = 0x47,
@@ -45,6 +45,12 @@ enum {
45 MLX4_CMD_DUMP_ETH_STATS = 0x49, 45 MLX4_CMD_DUMP_ETH_STATS = 0x49,
46}; 46};
47 47
48enum {
49 MCAST_DIRECT_ONLY = 0,
50 MCAST_DIRECT = 1,
51 MCAST_DEFAULT = 2
52};
53
48struct mlx4_set_port_general_context { 54struct mlx4_set_port_general_context {
49 u8 reserved[3]; 55 u8 reserved[3];
50 u8 flags; 56 u8 flags;
@@ -60,14 +66,17 @@ struct mlx4_set_port_general_context {
60 66
61struct mlx4_set_port_rqp_calc_context { 67struct mlx4_set_port_rqp_calc_context {
62 __be32 base_qpn; 68 __be32 base_qpn;
63 __be32 flags; 69 u8 rererved;
64 u8 reserved[3]; 70 u8 n_mac;
71 u8 n_vlan;
72 u8 n_prio;
73 u8 reserved2[3];
65 u8 mac_miss; 74 u8 mac_miss;
66 u8 intra_no_vlan; 75 u8 intra_no_vlan;
67 u8 no_vlan; 76 u8 no_vlan;
68 u8 intra_vlan_miss; 77 u8 intra_vlan_miss;
69 u8 vlan_miss; 78 u8 vlan_miss;
70 u8 reserved2[3]; 79 u8 reserved3[3];
71 u8 no_vlan_prio; 80 u8 no_vlan_prio;
72 __be32 promisc; 81 __be32 promisc;
73 __be32 mcast; 82 __be32 mcast;
diff --git a/drivers/net/mlx4/en_rx.c b/drivers/net/mlx4/en_rx.c
index 570f2508fb30..05998ee297c9 100644
--- a/drivers/net/mlx4/en_rx.c
+++ b/drivers/net/mlx4/en_rx.c
@@ -845,16 +845,10 @@ int mlx4_en_config_rss_steer(struct mlx4_en_priv *priv)
845 } 845 }
846 846
847 /* Configure RSS indirection qp */ 847 /* Configure RSS indirection qp */
848 err = mlx4_qp_reserve_range(mdev->dev, 1, 1, &priv->base_qpn);
849 if (err) {
850 en_err(priv, "Failed to reserve range for RSS "
851 "indirection qp\n");
852 goto rss_err;
853 }
854 err = mlx4_qp_alloc(mdev->dev, priv->base_qpn, &rss_map->indir_qp); 848 err = mlx4_qp_alloc(mdev->dev, priv->base_qpn, &rss_map->indir_qp);
855 if (err) { 849 if (err) {
856 en_err(priv, "Failed to allocate RSS indirection QP\n"); 850 en_err(priv, "Failed to allocate RSS indirection QP\n");
857 goto reserve_err; 851 goto rss_err;
858 } 852 }
859 rss_map->indir_qp.event = mlx4_en_sqp_event; 853 rss_map->indir_qp.event = mlx4_en_sqp_event;
860 mlx4_en_fill_qp_context(priv, 0, 0, 0, 1, priv->base_qpn, 854 mlx4_en_fill_qp_context(priv, 0, 0, 0, 1, priv->base_qpn,
@@ -881,8 +875,6 @@ indir_err:
881 MLX4_QP_STATE_RST, NULL, 0, 0, &rss_map->indir_qp); 875 MLX4_QP_STATE_RST, NULL, 0, 0, &rss_map->indir_qp);
882 mlx4_qp_remove(mdev->dev, &rss_map->indir_qp); 876 mlx4_qp_remove(mdev->dev, &rss_map->indir_qp);
883 mlx4_qp_free(mdev->dev, &rss_map->indir_qp); 877 mlx4_qp_free(mdev->dev, &rss_map->indir_qp);
884reserve_err:
885 mlx4_qp_release_range(mdev->dev, priv->base_qpn, 1);
886rss_err: 878rss_err:
887 for (i = 0; i < good_qps; i++) { 879 for (i = 0; i < good_qps; i++) {
888 mlx4_qp_modify(mdev->dev, NULL, rss_map->state[i], 880 mlx4_qp_modify(mdev->dev, NULL, rss_map->state[i],
@@ -904,7 +896,6 @@ void mlx4_en_release_rss_steer(struct mlx4_en_priv *priv)
904 MLX4_QP_STATE_RST, NULL, 0, 0, &rss_map->indir_qp); 896 MLX4_QP_STATE_RST, NULL, 0, 0, &rss_map->indir_qp);
905 mlx4_qp_remove(mdev->dev, &rss_map->indir_qp); 897 mlx4_qp_remove(mdev->dev, &rss_map->indir_qp);
906 mlx4_qp_free(mdev->dev, &rss_map->indir_qp); 898 mlx4_qp_free(mdev->dev, &rss_map->indir_qp);
907 mlx4_qp_release_range(mdev->dev, priv->base_qpn, 1);
908 899
909 for (i = 0; i < priv->rx_ring_num; i++) { 900 for (i = 0; i < priv->rx_ring_num; i++) {
910 mlx4_qp_modify(mdev->dev, NULL, rss_map->state[i], 901 mlx4_qp_modify(mdev->dev, NULL, rss_map->state[i],
diff --git a/drivers/net/mlx4/fw.c b/drivers/net/mlx4/fw.c
index 7813913b6d0f..67a209ba939d 100644
--- a/drivers/net/mlx4/fw.c
+++ b/drivers/net/mlx4/fw.c
@@ -740,6 +740,7 @@ int mlx4_INIT_HCA(struct mlx4_dev *dev, struct mlx4_init_hca_param *param)
740#define INIT_HCA_MC_BASE_OFFSET (INIT_HCA_MCAST_OFFSET + 0x00) 740#define INIT_HCA_MC_BASE_OFFSET (INIT_HCA_MCAST_OFFSET + 0x00)
741#define INIT_HCA_LOG_MC_ENTRY_SZ_OFFSET (INIT_HCA_MCAST_OFFSET + 0x12) 741#define INIT_HCA_LOG_MC_ENTRY_SZ_OFFSET (INIT_HCA_MCAST_OFFSET + 0x12)
742#define INIT_HCA_LOG_MC_HASH_SZ_OFFSET (INIT_HCA_MCAST_OFFSET + 0x16) 742#define INIT_HCA_LOG_MC_HASH_SZ_OFFSET (INIT_HCA_MCAST_OFFSET + 0x16)
743#define INIT_HCA_UC_STEERING_OFFSET (INIT_HCA_MCAST_OFFSET + 0x18)
743#define INIT_HCA_LOG_MC_TABLE_SZ_OFFSET (INIT_HCA_MCAST_OFFSET + 0x1b) 744#define INIT_HCA_LOG_MC_TABLE_SZ_OFFSET (INIT_HCA_MCAST_OFFSET + 0x1b)
744#define INIT_HCA_TPT_OFFSET 0x0f0 745#define INIT_HCA_TPT_OFFSET 0x0f0
745#define INIT_HCA_DMPT_BASE_OFFSET (INIT_HCA_TPT_OFFSET + 0x00) 746#define INIT_HCA_DMPT_BASE_OFFSET (INIT_HCA_TPT_OFFSET + 0x00)
@@ -800,6 +801,8 @@ int mlx4_INIT_HCA(struct mlx4_dev *dev, struct mlx4_init_hca_param *param)
800 MLX4_PUT(inbox, param->mc_base, INIT_HCA_MC_BASE_OFFSET); 801 MLX4_PUT(inbox, param->mc_base, INIT_HCA_MC_BASE_OFFSET);
801 MLX4_PUT(inbox, param->log_mc_entry_sz, INIT_HCA_LOG_MC_ENTRY_SZ_OFFSET); 802 MLX4_PUT(inbox, param->log_mc_entry_sz, INIT_HCA_LOG_MC_ENTRY_SZ_OFFSET);
802 MLX4_PUT(inbox, param->log_mc_hash_sz, INIT_HCA_LOG_MC_HASH_SZ_OFFSET); 803 MLX4_PUT(inbox, param->log_mc_hash_sz, INIT_HCA_LOG_MC_HASH_SZ_OFFSET);
804 if (dev->caps.vep_mc_steering)
805 MLX4_PUT(inbox, (u8) (1 << 3), INIT_HCA_UC_STEERING_OFFSET);
803 MLX4_PUT(inbox, param->log_mc_table_sz, INIT_HCA_LOG_MC_TABLE_SZ_OFFSET); 806 MLX4_PUT(inbox, param->log_mc_table_sz, INIT_HCA_LOG_MC_TABLE_SZ_OFFSET);
804 807
805 /* TPT attributes */ 808 /* TPT attributes */
diff --git a/drivers/net/mlx4/mlx4.h b/drivers/net/mlx4/mlx4.h
index 1513a91b4bd4..d8bb4418581b 100644
--- a/drivers/net/mlx4/mlx4.h
+++ b/drivers/net/mlx4/mlx4.h
@@ -286,6 +286,10 @@ struct mlx4_vlan_table {
286 int max; 286 int max;
287}; 287};
288 288
289struct mlx4_mac_entry {
290 u64 mac;
291};
292
289struct mlx4_port_info { 293struct mlx4_port_info {
290 struct mlx4_dev *dev; 294 struct mlx4_dev *dev;
291 int port; 295 int port;
@@ -293,7 +297,9 @@ struct mlx4_port_info {
293 struct device_attribute port_attr; 297 struct device_attribute port_attr;
294 enum mlx4_port_type tmp_type; 298 enum mlx4_port_type tmp_type;
295 struct mlx4_mac_table mac_table; 299 struct mlx4_mac_table mac_table;
300 struct radix_tree_root mac_tree;
296 struct mlx4_vlan_table vlan_table; 301 struct mlx4_vlan_table vlan_table;
302 int base_qpn;
297}; 303};
298 304
299struct mlx4_sense { 305struct mlx4_sense {
diff --git a/drivers/net/mlx4/mlx4_en.h b/drivers/net/mlx4/mlx4_en.h
index ad4df66750bc..5a2c56023668 100644
--- a/drivers/net/mlx4/mlx4_en.h
+++ b/drivers/net/mlx4/mlx4_en.h
@@ -458,6 +458,7 @@ struct mlx4_en_priv {
458 struct mlx4_en_rss_map rss_map; 458 struct mlx4_en_rss_map rss_map;
459 u32 flags; 459 u32 flags;
460#define MLX4_EN_FLAG_PROMISC 0x1 460#define MLX4_EN_FLAG_PROMISC 0x1
461#define MLX4_EN_FLAG_MC_PROMISC 0x2
461 u32 tx_ring_num; 462 u32 tx_ring_num;
462 u32 rx_ring_num; 463 u32 rx_ring_num;
463 u32 rx_skb_size; 464 u32 rx_skb_size;
diff --git a/drivers/net/mlx4/port.c b/drivers/net/mlx4/port.c
index 451339559bdc..eca7d8596f87 100644
--- a/drivers/net/mlx4/port.c
+++ b/drivers/net/mlx4/port.c
@@ -90,12 +90,79 @@ static int mlx4_set_port_mac_table(struct mlx4_dev *dev, u8 port,
90 return err; 90 return err;
91} 91}
92 92
93int mlx4_register_mac(struct mlx4_dev *dev, u8 port, u64 mac, int *index) 93static int mlx4_uc_steer_add(struct mlx4_dev *dev, u8 port,
94 u64 mac, int *qpn, u8 reserve)
94{ 95{
95 struct mlx4_mac_table *table = &mlx4_priv(dev)->port[port].mac_table; 96 struct mlx4_qp qp;
97 u8 gid[16] = {0};
98 int err;
99
100 if (reserve) {
101 err = mlx4_qp_reserve_range(dev, 1, 1, qpn);
102 if (err) {
103 mlx4_err(dev, "Failed to reserve qp for mac registration\n");
104 return err;
105 }
106 }
107 qp.qpn = *qpn;
108
109 mac &= 0xffffffffffffULL;
110 mac = cpu_to_be64(mac << 16);
111 memcpy(&gid[10], &mac, ETH_ALEN);
112 gid[5] = port;
113 gid[7] = MLX4_UC_STEER << 1;
114
115 err = mlx4_qp_attach_common(dev, &qp, gid, 0,
116 MLX4_PROT_ETH, MLX4_UC_STEER);
117 if (err && reserve)
118 mlx4_qp_release_range(dev, *qpn, 1);
119
120 return err;
121}
122
123static void mlx4_uc_steer_release(struct mlx4_dev *dev, u8 port,
124 u64 mac, int qpn, u8 free)
125{
126 struct mlx4_qp qp;
127 u8 gid[16] = {0};
128
129 qp.qpn = qpn;
130 mac &= 0xffffffffffffULL;
131 mac = cpu_to_be64(mac << 16);
132 memcpy(&gid[10], &mac, ETH_ALEN);
133 gid[5] = port;
134 gid[7] = MLX4_UC_STEER << 1;
135
136 mlx4_qp_detach_common(dev, &qp, gid, MLX4_PROT_ETH, MLX4_UC_STEER);
137 if (free)
138 mlx4_qp_release_range(dev, qpn, 1);
139}
140
141int mlx4_register_mac(struct mlx4_dev *dev, u8 port, u64 mac, int *qpn, u8 wrap)
142{
143 struct mlx4_port_info *info = &mlx4_priv(dev)->port[port];
144 struct mlx4_mac_table *table = &info->mac_table;
145 struct mlx4_mac_entry *entry;
96 int i, err = 0; 146 int i, err = 0;
97 int free = -1; 147 int free = -1;
98 148
149 if (dev->caps.vep_uc_steering) {
150 err = mlx4_uc_steer_add(dev, port, mac, qpn, 1);
151 if (!err) {
152 entry = kmalloc(sizeof *entry, GFP_KERNEL);
153 if (!entry) {
154 mlx4_uc_steer_release(dev, port, mac, *qpn, 1);
155 return -ENOMEM;
156 }
157 entry->mac = mac;
158 err = radix_tree_insert(&info->mac_tree, *qpn, entry);
159 if (err) {
160 mlx4_uc_steer_release(dev, port, mac, *qpn, 1);
161 return err;
162 }
163 } else
164 return err;
165 }
99 mlx4_dbg(dev, "Registering MAC: 0x%llx\n", (unsigned long long) mac); 166 mlx4_dbg(dev, "Registering MAC: 0x%llx\n", (unsigned long long) mac);
100 mutex_lock(&table->mutex); 167 mutex_lock(&table->mutex);
101 for (i = 0; i < MLX4_MAX_MAC_NUM - 1; i++) { 168 for (i = 0; i < MLX4_MAX_MAC_NUM - 1; i++) {
@@ -106,7 +173,6 @@ int mlx4_register_mac(struct mlx4_dev *dev, u8 port, u64 mac, int *index)
106 173
107 if (mac == (MLX4_MAC_MASK & be64_to_cpu(table->entries[i]))) { 174 if (mac == (MLX4_MAC_MASK & be64_to_cpu(table->entries[i]))) {
108 /* MAC already registered, increase refernce count */ 175 /* MAC already registered, increase refernce count */
109 *index = i;
110 ++table->refs[i]; 176 ++table->refs[i];
111 goto out; 177 goto out;
112 } 178 }
@@ -137,7 +203,8 @@ int mlx4_register_mac(struct mlx4_dev *dev, u8 port, u64 mac, int *index)
137 goto out; 203 goto out;
138 } 204 }
139 205
140 *index = free; 206 if (!dev->caps.vep_uc_steering)
207 *qpn = info->base_qpn + free;
141 ++table->total; 208 ++table->total;
142out: 209out:
143 mutex_unlock(&table->mutex); 210 mutex_unlock(&table->mutex);
@@ -145,20 +212,52 @@ out:
145} 212}
146EXPORT_SYMBOL_GPL(mlx4_register_mac); 213EXPORT_SYMBOL_GPL(mlx4_register_mac);
147 214
148void mlx4_unregister_mac(struct mlx4_dev *dev, u8 port, int index) 215static int validate_index(struct mlx4_dev *dev,
216 struct mlx4_mac_table *table, int index)
149{ 217{
150 struct mlx4_mac_table *table = &mlx4_priv(dev)->port[port].mac_table; 218 int err = 0;
151 219
152 mutex_lock(&table->mutex); 220 if (index < 0 || index >= table->max || !table->entries[index]) {
153 if (!table->refs[index]) { 221 mlx4_warn(dev, "No valid Mac entry for the given index\n");
154 mlx4_warn(dev, "No MAC entry for index %d\n", index); 222 err = -EINVAL;
155 goto out;
156 } 223 }
157 if (--table->refs[index]) { 224 return err;
158 mlx4_warn(dev, "Have more references for index %d," 225}
159 "no need to modify MAC table\n", index); 226
160 goto out; 227static int find_index(struct mlx4_dev *dev,
228 struct mlx4_mac_table *table, u64 mac)
229{
230 int i;
231 for (i = 0; i < MLX4_MAX_MAC_NUM; i++) {
232 if (mac == (MLX4_MAC_MASK & be64_to_cpu(table->entries[i])))
233 return i;
161 } 234 }
235 /* Mac not found */
236 return -EINVAL;
237}
238
239void mlx4_unregister_mac(struct mlx4_dev *dev, u8 port, int qpn)
240{
241 struct mlx4_port_info *info = &mlx4_priv(dev)->port[port];
242 struct mlx4_mac_table *table = &info->mac_table;
243 int index = qpn - info->base_qpn;
244 struct mlx4_mac_entry *entry;
245
246 if (dev->caps.vep_uc_steering) {
247 entry = radix_tree_lookup(&info->mac_tree, qpn);
248 if (entry) {
249 mlx4_uc_steer_release(dev, port, entry->mac, qpn, 1);
250 radix_tree_delete(&info->mac_tree, qpn);
251 index = find_index(dev, table, entry->mac);
252 kfree(entry);
253 }
254 }
255
256 mutex_lock(&table->mutex);
257
258 if (validate_index(dev, table, index))
259 goto out;
260
162 table->entries[index] = 0; 261 table->entries[index] = 0;
163 mlx4_set_port_mac_table(dev, port, table->entries); 262 mlx4_set_port_mac_table(dev, port, table->entries);
164 --table->total; 263 --table->total;
@@ -167,6 +266,44 @@ out:
167} 266}
168EXPORT_SYMBOL_GPL(mlx4_unregister_mac); 267EXPORT_SYMBOL_GPL(mlx4_unregister_mac);
169 268
269int mlx4_replace_mac(struct mlx4_dev *dev, u8 port, int qpn, u64 new_mac, u8 wrap)
270{
271 struct mlx4_port_info *info = &mlx4_priv(dev)->port[port];
272 struct mlx4_mac_table *table = &info->mac_table;
273 int index = qpn - info->base_qpn;
274 struct mlx4_mac_entry *entry;
275 int err;
276
277 if (dev->caps.vep_uc_steering) {
278 entry = radix_tree_lookup(&info->mac_tree, qpn);
279 if (!entry)
280 return -EINVAL;
281 index = find_index(dev, table, entry->mac);
282 mlx4_uc_steer_release(dev, port, entry->mac, qpn, 0);
283 entry->mac = new_mac;
284 err = mlx4_uc_steer_add(dev, port, entry->mac, &qpn, 0);
285 if (err || index < 0)
286 return err;
287 }
288
289 mutex_lock(&table->mutex);
290
291 err = validate_index(dev, table, index);
292 if (err)
293 goto out;
294
295 table->entries[index] = cpu_to_be64(new_mac | MLX4_MAC_VALID);
296
297 err = mlx4_set_port_mac_table(dev, port, table->entries);
298 if (unlikely(err)) {
299 mlx4_err(dev, "Failed adding MAC: 0x%llx\n", (unsigned long long) new_mac);
300 table->entries[index] = 0;
301 }
302out:
303 mutex_unlock(&table->mutex);
304 return err;
305}
306EXPORT_SYMBOL_GPL(mlx4_replace_mac);
170static int mlx4_set_port_vlan_table(struct mlx4_dev *dev, u8 port, 307static int mlx4_set_port_vlan_table(struct mlx4_dev *dev, u8 port,
171 __be32 *entries) 308 __be32 *entries)
172{ 309{
diff --git a/include/linux/mlx4/device.h b/include/linux/mlx4/device.h
index ebda939b9fc3..56fa5e1cd6d4 100644
--- a/include/linux/mlx4/device.h
+++ b/include/linux/mlx4/device.h
@@ -525,9 +525,15 @@ int mlx4_multicast_attach(struct mlx4_dev *dev, struct mlx4_qp *qp, u8 gid[16],
525 int block_mcast_loopback, enum mlx4_protocol protocol); 525 int block_mcast_loopback, enum mlx4_protocol protocol);
526int mlx4_multicast_detach(struct mlx4_dev *dev, struct mlx4_qp *qp, u8 gid[16], 526int mlx4_multicast_detach(struct mlx4_dev *dev, struct mlx4_qp *qp, u8 gid[16],
527 enum mlx4_protocol protocol); 527 enum mlx4_protocol protocol);
528 528int mlx4_multicast_promisc_add(struct mlx4_dev *dev, u32 qpn, u8 port);
529int mlx4_register_mac(struct mlx4_dev *dev, u8 port, u64 mac, int *index); 529int mlx4_multicast_promisc_remove(struct mlx4_dev *dev, u32 qpn, u8 port);
530void mlx4_unregister_mac(struct mlx4_dev *dev, u8 port, int index); 530int mlx4_unicast_promisc_add(struct mlx4_dev *dev, u32 qpn, u8 port);
531int mlx4_unicast_promisc_remove(struct mlx4_dev *dev, u32 qpn, u8 port);
532int mlx4_SET_MCAST_FLTR(struct mlx4_dev *dev, u8 port, u64 mac, u64 clear, u8 mode);
533
534int mlx4_register_mac(struct mlx4_dev *dev, u8 port, u64 mac, int *qpn, u8 wrap);
535void mlx4_unregister_mac(struct mlx4_dev *dev, u8 port, int qpn);
536int mlx4_replace_mac(struct mlx4_dev *dev, u8 port, int qpn, u64 new_mac, u8 wrap);
531 537
532int mlx4_find_cached_vlan(struct mlx4_dev *dev, u8 port, u16 vid, int *idx); 538int mlx4_find_cached_vlan(struct mlx4_dev *dev, u8 port, u16 vid, int *idx);
533int mlx4_register_vlan(struct mlx4_dev *dev, u8 port, u16 vlan, int *index); 539int mlx4_register_vlan(struct mlx4_dev *dev, u8 port, u16 vlan, int *index);