net/mlx4: Allocate VPPs for each port on PF init
authorIdo Shamay <idos@mellanox.com>
Thu, 2 Apr 2015 13:31:14 +0000 (16:31 +0300)
committerDavid S. Miller <davem@davemloft.net>
Thu, 2 Apr 2015 20:25:02 +0000 (16:25 -0400)
Initialization of granular Qos per VF mechanism.

Query the port availible VPPs and allocates those on all supported
priorities in an equal share. Allocation is done only in SRIOV mode,
when the feature is supported by the device and port type is Ethernet.

Allocation currently is done only on the default priority 0.

Signed-off-by: Ido Shamay <idos@mellanox.com>
Signed-off-by: Or Gerlitz <ogerlitz@mellanox.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/ethernet/mellanox/mlx4/cmd.c
drivers/net/ethernet/mellanox/mlx4/fw_qos.h
drivers/net/ethernet/mellanox/mlx4/mlx4.h

index af95231ba3e2b27c6b92e1b582cb393ac6f8708f..7d3c64275b75d5fb3f389e287d89ce7a9901e866 100644 (file)
@@ -1883,6 +1883,63 @@ static int mlx4_master_immediate_activate_vlan_qos(struct mlx4_priv *priv,
        return 0;
 }
 
+static void mlx4_set_default_port_qos(struct mlx4_dev *dev, int port)
+{
+       struct mlx4_qos_manager *port_qos_ctl;
+       struct mlx4_priv *priv = mlx4_priv(dev);
+
+       port_qos_ctl = &priv->mfunc.master.qos_ctl[port];
+       bitmap_zero(port_qos_ctl->priority_bm, MLX4_NUM_UP);
+
+       /* Enable only default prio at PF init routine */
+       set_bit(MLX4_DEFAULT_QOS_PRIO, port_qos_ctl->priority_bm);
+}
+
+static void mlx4_allocate_port_vpps(struct mlx4_dev *dev, int port)
+{
+       int i;
+       int err;
+       int num_vfs;
+       u16 availible_vpp;
+       u8 vpp_param[MLX4_NUM_UP];
+       struct mlx4_qos_manager *port_qos;
+       struct mlx4_priv *priv = mlx4_priv(dev);
+
+       err = mlx4_ALLOCATE_VPP_get(dev, port, &availible_vpp, vpp_param);
+       if (err) {
+               mlx4_info(dev, "Failed query availible VPPs\n");
+               return;
+       }
+
+       port_qos = &priv->mfunc.master.qos_ctl[port];
+       num_vfs = (availible_vpp /
+                  bitmap_weight(port_qos->priority_bm, MLX4_NUM_UP));
+
+       for (i = 0; i < MLX4_NUM_UP; i++) {
+               if (test_bit(i, port_qos->priority_bm))
+                       vpp_param[i] = num_vfs;
+       }
+
+       err = mlx4_ALLOCATE_VPP_set(dev, port, vpp_param);
+       if (err) {
+               mlx4_info(dev, "Failed allocating VPPs\n");
+               return;
+       }
+
+       /* Query actual allocated VPP, just to make sure */
+       err = mlx4_ALLOCATE_VPP_get(dev, port, &availible_vpp, vpp_param);
+       if (err) {
+               mlx4_info(dev, "Failed query availible VPPs\n");
+               return;
+       }
+
+       port_qos->num_of_qos_vfs = num_vfs;
+       mlx4_dbg(dev, "Port %d Availible VPPs %d\n", port, availible_vpp);
+
+       for (i = 0; i < MLX4_NUM_UP; i++)
+               mlx4_dbg(dev, "Port %d UP %d Allocated %d VPPs\n", port, i,
+                        vpp_param[i]);
+}
 
 static int mlx4_master_activate_admin_state(struct mlx4_priv *priv, int slave)
 {
@@ -2288,6 +2345,15 @@ int mlx4_multi_func_init(struct mlx4_dev *dev)
                        spin_lock_init(&s_state->lock);
                }
 
+               if (dev->caps.flags2 & MLX4_DEV_CAP_FLAG2_QOS_VPP) {
+                       for (port = 1; port <= dev->caps.num_ports; port++) {
+                               if (mlx4_is_eth(dev, port)) {
+                                       mlx4_set_default_port_qos(dev, port);
+                                       mlx4_allocate_port_vpps(dev, port);
+                               }
+                       }
+               }
+
                memset(&priv->mfunc.master.cmd_eqe, 0, dev->caps.eqe_size);
                priv->mfunc.master.cmd_eqe.type = MLX4_EVENT_TYPE_CMD;
                INIT_WORK(&priv->mfunc.master.comm_work,
index b3fffafff06231bf0038033ad1d2df8d07af1eeb..4a5320f79094fa7b897251a641842a572e4101eb 100644 (file)
@@ -41,6 +41,9 @@
 #define MLX4_NUM_UP 8
 #define MLX4_NUM_TC 8
 
+/* Default supported priorities for VPP allocation */
+#define MLX4_DEFAULT_QOS_PRIO (0)
+
 struct mlx4_vport_qos_param {
        u32 bw_share;
        u32 max_avg_bw;
index 9e5236b1b5f80c0f6831b3288c09ce1e4e0ac707..1add698dba5b676df1dd66e7d97943e1476d98e9 100644 (file)
@@ -50,6 +50,7 @@
 #include <linux/mlx4/driver.h>
 #include <linux/mlx4/doorbell.h>
 #include <linux/mlx4/cmd.h>
+#include "fw_qos.h"
 
 #define DRV_NAME       "mlx4_core"
 #define PFX            DRV_NAME ": "
@@ -553,6 +554,11 @@ struct mlx4_slave_event_eq {
        struct mlx4_eqe event_eqe[SLAVE_EVENT_EQ_SIZE];
 };
 
+struct mlx4_qos_manager {
+       int num_of_qos_vfs;
+       DECLARE_BITMAP(priority_bm, MLX4_NUM_UP);
+};
+
 struct mlx4_master_qp0_state {
        int proxy_qp0_active;
        int qp0_active;
@@ -577,6 +583,7 @@ struct mlx4_mfunc_master_ctx {
        struct mlx4_eqe         cmd_eqe;
        struct mlx4_slave_event_eq slave_eq;
        struct mutex            gen_eqe_mutex[MLX4_MFUNC_MAX];
+       struct mlx4_qos_manager qos_ctl[MLX4_MAX_PORTS + 1];
 };
 
 struct mlx4_mfunc {