diff options
-rw-r--r-- | drivers/net/mlx4/en_netdev.c | 133 | ||||
-rw-r--r-- | drivers/net/mlx4/en_port.c | 11 | ||||
-rw-r--r-- | drivers/net/mlx4/en_port.h | 19 | ||||
-rw-r--r-- | drivers/net/mlx4/en_rx.c | 11 | ||||
-rw-r--r-- | drivers/net/mlx4/fw.c | 3 | ||||
-rw-r--r-- | drivers/net/mlx4/mlx4.h | 6 | ||||
-rw-r--r-- | drivers/net/mlx4/mlx4_en.h | 1 | ||||
-rw-r--r-- | drivers/net/mlx4/port.c | 165 | ||||
-rw-r--r-- | include/linux/mlx4/device.h | 12 |
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 | } |
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 */ |
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 | ||
42 | enum { | 42 | enum { |
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 | ||
48 | enum { | ||
49 | MCAST_DIRECT_ONLY = 0, | ||
50 | MCAST_DIRECT = 1, | ||
51 | MCAST_DEFAULT = 2 | ||
52 | }; | ||
53 | |||
48 | struct mlx4_set_port_general_context { | 54 | struct 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 | ||
61 | struct mlx4_set_port_rqp_calc_context { | 67 | struct 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); |
884 | reserve_err: | ||
885 | mlx4_qp_release_range(mdev->dev, priv->base_qpn, 1); | ||
886 | rss_err: | 878 | rss_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 | ||
289 | struct mlx4_mac_entry { | ||
290 | u64 mac; | ||
291 | }; | ||
292 | |||
289 | struct mlx4_port_info { | 293 | struct 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 | ||
299 | struct mlx4_sense { | 305 | struct 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 | ||
93 | int mlx4_register_mac(struct mlx4_dev *dev, u8 port, u64 mac, int *index) | 93 | static 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 | |||
123 | static 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 | |||
141 | int 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; |
142 | out: | 209 | out: |
143 | mutex_unlock(&table->mutex); | 210 | mutex_unlock(&table->mutex); |
@@ -145,20 +212,52 @@ out: | |||
145 | } | 212 | } |
146 | EXPORT_SYMBOL_GPL(mlx4_register_mac); | 213 | EXPORT_SYMBOL_GPL(mlx4_register_mac); |
147 | 214 | ||
148 | void mlx4_unregister_mac(struct mlx4_dev *dev, u8 port, int index) | 215 | static 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; | 227 | static 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 | |||
239 | void 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 | } |
168 | EXPORT_SYMBOL_GPL(mlx4_unregister_mac); | 267 | EXPORT_SYMBOL_GPL(mlx4_unregister_mac); |
169 | 268 | ||
269 | int 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 | } | ||
302 | out: | ||
303 | mutex_unlock(&table->mutex); | ||
304 | return err; | ||
305 | } | ||
306 | EXPORT_SYMBOL_GPL(mlx4_replace_mac); | ||
170 | static int mlx4_set_port_vlan_table(struct mlx4_dev *dev, u8 port, | 307 | static 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); |
526 | int mlx4_multicast_detach(struct mlx4_dev *dev, struct mlx4_qp *qp, u8 gid[16], | 526 | int 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 | 528 | int mlx4_multicast_promisc_add(struct mlx4_dev *dev, u32 qpn, u8 port); | |
529 | int mlx4_register_mac(struct mlx4_dev *dev, u8 port, u64 mac, int *index); | 529 | int mlx4_multicast_promisc_remove(struct mlx4_dev *dev, u32 qpn, u8 port); |
530 | void mlx4_unregister_mac(struct mlx4_dev *dev, u8 port, int index); | 530 | int mlx4_unicast_promisc_add(struct mlx4_dev *dev, u32 qpn, u8 port); |
531 | int mlx4_unicast_promisc_remove(struct mlx4_dev *dev, u32 qpn, u8 port); | ||
532 | int mlx4_SET_MCAST_FLTR(struct mlx4_dev *dev, u8 port, u64 mac, u64 clear, u8 mode); | ||
533 | |||
534 | int mlx4_register_mac(struct mlx4_dev *dev, u8 port, u64 mac, int *qpn, u8 wrap); | ||
535 | void mlx4_unregister_mac(struct mlx4_dev *dev, u8 port, int qpn); | ||
536 | int mlx4_replace_mac(struct mlx4_dev *dev, u8 port, int qpn, u64 new_mac, u8 wrap); | ||
531 | 537 | ||
532 | int mlx4_find_cached_vlan(struct mlx4_dev *dev, u8 port, u16 vid, int *idx); | 538 | int mlx4_find_cached_vlan(struct mlx4_dev *dev, u8 port, u16 vid, int *idx); |
533 | int mlx4_register_vlan(struct mlx4_dev *dev, u8 port, u16 vlan, int *index); | 539 | int mlx4_register_vlan(struct mlx4_dev *dev, u8 port, u16 vlan, int *index); |