net/mlx4_en: Disable blueflame using ethtool private flags
authorAmir Vadai <amirv@mellanox.com>
Tue, 22 Jul 2014 12:44:10 +0000 (15:44 +0300)
committerDavid S. Miller <davem@davemloft.net>
Wed, 23 Jul 2014 02:53:14 +0000 (19:53 -0700)
Enable the user to turn off the hardware feature called BlueFlame.
Since it is something specific to mlx4_en hardware, we control
the feature via ethtool private flags.

Signed-off-by: Amir Vadai <amirv@mellanox.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/ethernet/mellanox/mlx4/en_ethtool.c
drivers/net/ethernet/mellanox/mlx4/en_netdev.c
drivers/net/ethernet/mellanox/mlx4/en_tx.c
drivers/net/ethernet/mellanox/mlx4/mlx4_en.h

index 68d763d2d030d578e38ba970ea9a744a5bad4248..50e85cc1d61f4f964c582a74f40717de87064042 100644 (file)
@@ -98,6 +98,10 @@ mlx4_en_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *drvinfo)
        drvinfo->eedump_len = 0;
 }
 
+static const char mlx4_en_priv_flags[][ETH_GSTRING_LEN] = {
+       "blueflame",
+};
+
 static const char main_strings[][ETH_GSTRING_LEN] = {
        "rx_packets", "tx_packets", "rx_bytes", "tx_bytes", "rx_errors",
        "tx_errors", "rx_dropped", "tx_dropped", "multicast", "collisions",
@@ -235,6 +239,8 @@ static int mlx4_en_get_sset_count(struct net_device *dev, int sset)
        case ETH_SS_TEST:
                return MLX4_EN_NUM_SELF_TEST - !(priv->mdev->dev->caps.flags
                                        & MLX4_DEV_CAP_FLAG_UC_LOOPBACK) * 2;
+       case ETH_SS_PRIV_FLAGS:
+               return ARRAY_SIZE(mlx4_en_priv_flags);
        default:
                return -EOPNOTSUPP;
        }
@@ -358,6 +364,12 @@ static void mlx4_en_get_strings(struct net_device *dev,
 #endif
                }
                break;
+       case ETH_SS_PRIV_FLAGS:
+               for (i = 0; i < ARRAY_SIZE(mlx4_en_priv_flags); i++)
+                       strcpy(data + i * ETH_GSTRING_LEN,
+                              mlx4_en_priv_flags[i]);
+               break;
+
        }
 }
 
@@ -1209,6 +1221,49 @@ static int mlx4_en_get_ts_info(struct net_device *dev,
        return ret;
 }
 
+int mlx4_en_set_priv_flags(struct net_device *dev, u32 flags)
+{
+       struct mlx4_en_priv *priv = netdev_priv(dev);
+       bool bf_enabled_new = !!(flags & MLX4_EN_PRIV_FLAGS_BLUEFLAME);
+       bool bf_enabled_old = !!(priv->pflags & MLX4_EN_PRIV_FLAGS_BLUEFLAME);
+       int i;
+
+       if (bf_enabled_new == bf_enabled_old)
+               return 0; /* Nothing to do */
+
+       if (bf_enabled_new) {
+               bool bf_supported = true;
+
+               for (i = 0; i < priv->tx_ring_num; i++)
+                       bf_supported &= priv->tx_ring[i]->bf_alloced;
+
+               if (!bf_supported) {
+                       en_err(priv, "BlueFlame is not supported\n");
+                       return -EINVAL;
+               }
+
+               priv->pflags |= MLX4_EN_PRIV_FLAGS_BLUEFLAME;
+       } else {
+               priv->pflags &= ~MLX4_EN_PRIV_FLAGS_BLUEFLAME;
+       }
+
+       for (i = 0; i < priv->tx_ring_num; i++)
+               priv->tx_ring[i]->bf_enabled = bf_enabled_new;
+
+       en_info(priv, "BlueFlame %s\n",
+               bf_enabled_new ?  "Enabled" : "Disabled");
+
+       return 0;
+}
+
+u32 mlx4_en_get_priv_flags(struct net_device *dev)
+{
+       struct mlx4_en_priv *priv = netdev_priv(dev);
+
+       return priv->pflags;
+}
+
+
 const struct ethtool_ops mlx4_en_ethtool_ops = {
        .get_drvinfo = mlx4_en_get_drvinfo,
        .get_settings = mlx4_en_get_settings,
@@ -1236,6 +1291,8 @@ const struct ethtool_ops mlx4_en_ethtool_ops = {
        .get_channels = mlx4_en_get_channels,
        .set_channels = mlx4_en_set_channels,
        .get_ts_info = mlx4_en_get_ts_info,
+       .set_priv_flags = mlx4_en_set_priv_flags,
+       .get_priv_flags = mlx4_en_get_priv_flags,
 };
 
 
index 82708bd5c339af556f1b3b539d5c885e70972aac..bb536aa613f483434f35c4bde31ae36ab9ced290 100644 (file)
@@ -2465,6 +2465,7 @@ int mlx4_en_init_netdev(struct mlx4_en_dev *mdev, int port,
        priv->port = port;
        priv->port_up = false;
        priv->flags = prof->flags;
+       priv->pflags = MLX4_EN_PRIV_FLAGS_BLUEFLAME;
        priv->ctrl_flags = cpu_to_be32(MLX4_WQE_CTRL_CQ_UPDATE |
                        MLX4_WQE_CTRL_SOLICITED);
        priv->num_tx_rings_p_up = mdev->profile.num_tx_rings_p_up;
index 5045bab596338c390277255ed33a9a5ff8939c5a..dae3da6d8dd08979e4a4ba3f0f3c7413f10198cd 100644 (file)
@@ -126,8 +126,13 @@ int mlx4_en_create_tx_ring(struct mlx4_en_priv *priv,
                ring->bf.uar = &mdev->priv_uar;
                ring->bf.uar->map = mdev->uar_map;
                ring->bf_enabled = false;
-       } else
-               ring->bf_enabled = true;
+               ring->bf_alloced = false;
+               priv->pflags &= ~MLX4_EN_PRIV_FLAGS_BLUEFLAME;
+       } else {
+               ring->bf_alloced = true;
+               ring->bf_enabled = !!(priv->pflags &
+                                     MLX4_EN_PRIV_FLAGS_BLUEFLAME);
+       }
 
        ring->hwtstamp_tx_type = priv->hwtstamp_config.tx_type;
        ring->queue_index = queue_index;
@@ -161,7 +166,7 @@ void mlx4_en_destroy_tx_ring(struct mlx4_en_priv *priv,
        struct mlx4_en_tx_ring *ring = *pring;
        en_dbg(DRV, priv, "Destroying tx ring, qpn: %d\n", ring->qpn);
 
-       if (ring->bf_enabled)
+       if (ring->bf_alloced)
                mlx4_bf_free(mdev->dev, &ring->bf);
        mlx4_qp_remove(mdev->dev, &ring->qp);
        mlx4_qp_free(mdev->dev, &ring->qp);
@@ -195,7 +200,7 @@ int mlx4_en_activate_tx_ring(struct mlx4_en_priv *priv,
 
        mlx4_en_fill_qp_context(priv, ring->size, ring->stride, 1, 0, ring->qpn,
                                ring->cqn, user_prio, &ring->context);
-       if (ring->bf_enabled)
+       if (ring->bf_alloced)
                ring->context.usr_page = cpu_to_be32(ring->bf.uar->index);
 
        err = mlx4_qp_to_ready(mdev->dev, &ring->wqres.mtt, &ring->context,
index 2b19dd1f2c5d76da0972401734c584d678261a6a..54c277412e424cf7aefa818375b8b9cbbd4782e3 100644 (file)
@@ -93,6 +93,8 @@
  * OS related constants and tunables
  */
 
+#define MLX4_EN_PRIV_FLAGS_BLUEFLAME 1
+
 #define MLX4_EN_WATCHDOG_TIMEOUT       (15 * HZ)
 
 /* Use the maximum between 16384 and a single page */
@@ -278,6 +280,7 @@ struct mlx4_en_tx_ring {
        unsigned long wake_queue;
        struct mlx4_bf bf;
        bool bf_enabled;
+       bool bf_alloced;
        struct netdev_queue *tx_queue;
        int hwtstamp_tx_type;
        int inline_thold;
@@ -592,6 +595,8 @@ struct mlx4_en_priv {
 #endif
        u64 tunnel_reg_id;
        __be16 vxlan_port;
+
+       u32 pflags;
 };
 
 enum mlx4_en_wol {