net/mlx4_en: Remove ethtool flow steering rules before releasing QPs
[sfrench/cifs-2.6.git] / drivers / net / ethernet / mellanox / mlx4 / en_netdev.c
index 217e618fd7129f39a1aa1f0f484353f6e018854f..f278b10ef7140a6e195056e11a12075de02afabc 100644 (file)
@@ -565,34 +565,38 @@ static void mlx4_en_put_qp(struct mlx4_en_priv *priv)
        struct mlx4_en_dev *mdev = priv->mdev;
        struct mlx4_dev *dev = mdev->dev;
        int qpn = priv->base_qpn;
-       u64 mac = mlx4_en_mac_to_u64(priv->dev->dev_addr);
-
-       en_dbg(DRV, priv, "Registering MAC: %pM for deleting\n",
-              priv->dev->dev_addr);
-       mlx4_unregister_mac(dev, priv->port, mac);
+       u64 mac;
 
-       if (dev->caps.steering_mode != MLX4_STEERING_MODE_A0) {
+       if (dev->caps.steering_mode == MLX4_STEERING_MODE_A0) {
+               mac = mlx4_en_mac_to_u64(priv->dev->dev_addr);
+               en_dbg(DRV, priv, "Registering MAC: %pM for deleting\n",
+                      priv->dev->dev_addr);
+               mlx4_unregister_mac(dev, priv->port, mac);
+       } else {
                struct mlx4_mac_entry *entry;
                struct hlist_node *tmp;
                struct hlist_head *bucket;
-               unsigned int mac_hash;
+               unsigned int i;
 
-               mac_hash = priv->dev->dev_addr[MLX4_EN_MAC_HASH_IDX];
-               bucket = &priv->mac_hash[mac_hash];
-               hlist_for_each_entry_safe(entry, tmp, bucket, hlist) {
-                       if (ether_addr_equal_64bits(entry->mac,
-                                                   priv->dev->dev_addr)) {
-                               en_dbg(DRV, priv, "Releasing qp: port %d, MAC %pM, qpn %d\n",
-                                      priv->port, priv->dev->dev_addr, qpn);
+               for (i = 0; i < MLX4_EN_MAC_HASH_SIZE; ++i) {
+                       bucket = &priv->mac_hash[i];
+                       hlist_for_each_entry_safe(entry, tmp, bucket, hlist) {
+                               mac = mlx4_en_mac_to_u64(entry->mac);
+                               en_dbg(DRV, priv, "Registering MAC: %pM for deleting\n",
+                                      entry->mac);
                                mlx4_en_uc_steer_release(priv, entry->mac,
                                                         qpn, entry->reg_id);
-                               mlx4_qp_release_range(dev, qpn, 1);
 
+                               mlx4_unregister_mac(dev, priv->port, mac);
                                hlist_del_rcu(&entry->hlist);
                                kfree_rcu(entry, rcu);
-                               break;
                        }
                }
+
+               en_dbg(DRV, priv, "Releasing qp: port %d, qpn %d\n",
+                      priv->port, qpn);
+               mlx4_qp_release_range(dev, qpn, 1);
+               priv->flags &= ~MLX4_EN_FLAG_FORCE_PROMISC;
        }
 }
 
@@ -1633,6 +1637,17 @@ void mlx4_en_stop_port(struct net_device *dev, int detach)
        /* Flush multicast filter */
        mlx4_SET_MCAST_FLTR(mdev->dev, priv->port, 0, 1, MLX4_MCAST_CONFIG);
 
+       /* Remove flow steering rules for the port*/
+       if (mdev->dev->caps.steering_mode ==
+           MLX4_STEERING_MODE_DEVICE_MANAGED) {
+               ASSERT_RTNL();
+               list_for_each_entry_safe(flow, tmp_flow,
+                                        &priv->ethtool_list, list) {
+                       mlx4_flow_detach(mdev->dev, flow->id);
+                       list_del(&flow->list);
+               }
+       }
+
        mlx4_en_destroy_drop_qp(priv);
 
        /* Free TX Rings */
@@ -1653,17 +1668,6 @@ void mlx4_en_stop_port(struct net_device *dev, int detach)
        if (!(mdev->dev->caps.flags2 & MLX4_DEV_CAP_FLAGS2_REASSIGN_MAC_EN))
                mdev->mac_removed[priv->port] = 1;
 
-       /* Remove flow steering rules for the port*/
-       if (mdev->dev->caps.steering_mode ==
-           MLX4_STEERING_MODE_DEVICE_MANAGED) {
-               ASSERT_RTNL();
-               list_for_each_entry_safe(flow, tmp_flow,
-                                        &priv->ethtool_list, list) {
-                       mlx4_flow_detach(mdev->dev, flow->id);
-                       list_del(&flow->list);
-               }
-       }
-
        /* Free RX Rings */
        for (i = 0; i < priv->rx_ring_num; i++) {
                mlx4_en_deactivate_rx_ring(priv, &priv->rx_ring[i]);
@@ -1829,9 +1833,11 @@ int mlx4_en_alloc_resources(struct mlx4_en_priv *priv)
        }
 
 #ifdef CONFIG_RFS_ACCEL
-       priv->dev->rx_cpu_rmap = alloc_irq_cpu_rmap(priv->mdev->dev->caps.comp_pool);
-       if (!priv->dev->rx_cpu_rmap)
-               goto err;
+       if (priv->mdev->dev->caps.comp_pool) {
+               priv->dev->rx_cpu_rmap = alloc_irq_cpu_rmap(priv->mdev->dev->caps.comp_pool);
+               if (!priv->dev->rx_cpu_rmap)
+                       goto err;
+       }
 #endif
 
        return 0;