diff options
author | Yevgeny Petrilin <yevgenyp@mellanox.co.il> | 2011-03-22 18:38:31 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2011-03-23 15:24:22 -0400 |
commit | 1679200f91da6a054b06954c9bd3eeed29b6731f (patch) | |
tree | a447268debe479a257cfff4c7e5e86151eef6583 /drivers/net/mlx4/en_netdev.c | |
parent | b12d93d63c3217f0ec923ff938b12a744e242ffa (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>
Diffstat (limited to 'drivers/net/mlx4/en_netdev.c')
-rw-r--r-- | drivers/net/mlx4/en_netdev.c | 133 |
1 files changed, 106 insertions, 27 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 | } |
320 | out: | 374 | out: |
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 | ||
689 | mac_err: | ||
690 | mlx4_unregister_mac(mdev->dev, priv->port, priv->mac_index); | ||
691 | tx_err: | 752 | tx_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); |
759 | mac_err: | ||
760 | mlx4_unregister_mac(mdev->dev, priv->port, priv->base_qpn); | ||
698 | cq_err: | 761 | cq_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 */ |