net/mlx5: Packet pacing enhancement
authorBodong Wang <bodong@mellanox.com>
Mon, 19 Mar 2018 13:10:29 +0000 (15:10 +0200)
committerJason Gunthorpe <jgg@mellanox.com>
Mon, 19 Mar 2018 17:54:41 +0000 (11:54 -0600)
Add two new parameters: max_burst_sz and typical_pkt_size (both
in bytes) to rate limit configurations.

max_burst_sz: The device will schedule bursts of packets for an
SQ connected to this rate, smaller than or equal to this value.
Value 0x0 indicates packet bursts will be limited to the device
defaults. This field should be used if bursts of packets must be
strictly kept under a certain value.

typical_pkt_size: When the rate limit is intended for a stream of
similar packets, stating the typical packet size can improve the
accuracy of the rate limiter. The expected packet size will be
the same for all SQs associated with the same rate limit index.

Ethernet driver is updated according to this change, but these two
parameters will be kept as 0 due to lacking of proper way to get the
configurations from user space which requires to change
ndo_set_tx_maxrate interface.

Signed-off-by: Bodong Wang <bodong@mellanox.com>
Reviewed-by: Daniel Jurgens <danielj@mellanox.com>
Reviewed-by: Yishai Hadas <yishaih@mellanox.com>
Signed-off-by: Leon Romanovsky <leonro@mellanox.com>
Signed-off-by: Jason Gunthorpe <jgg@mellanox.com>
drivers/net/ethernet/mellanox/mlx5/core/en_main.c
drivers/net/ethernet/mellanox/mlx5/core/rl.c
include/linux/mlx5/driver.h
include/linux/mlx5/mlx5_ifc.h

index 47bab842c5eea8656a68002440d616c7c94c4611..2ee4ffbddd5f4166b6d12ea3adf1234bc57aac9e 100644 (file)
@@ -1195,10 +1195,13 @@ static void mlx5e_close_txqsq(struct mlx5e_txqsq *sq)
 {
        struct mlx5e_channel *c = sq->channel;
        struct mlx5_core_dev *mdev = c->mdev;
+       struct mlx5_rate_limit rl = {0};
 
        mlx5e_destroy_sq(mdev, sq->sqn);
-       if (sq->rate_limit)
-               mlx5_rl_remove_rate(mdev, sq->rate_limit);
+       if (sq->rate_limit) {
+               rl.rate = sq->rate_limit;
+               mlx5_rl_remove_rate(mdev, &rl);
+       }
        mlx5e_free_txqsq_descs(sq);
        mlx5e_free_txqsq(sq);
 }
@@ -1528,6 +1531,7 @@ static int mlx5e_set_sq_maxrate(struct net_device *dev,
        struct mlx5e_priv *priv = netdev_priv(dev);
        struct mlx5_core_dev *mdev = priv->mdev;
        struct mlx5e_modify_sq_param msp = {0};
+       struct mlx5_rate_limit rl = {0};
        u16 rl_index = 0;
        int err;
 
@@ -1535,14 +1539,17 @@ static int mlx5e_set_sq_maxrate(struct net_device *dev,
                /* nothing to do */
                return 0;
 
-       if (sq->rate_limit)
+       if (sq->rate_limit) {
+               rl.rate = sq->rate_limit;
                /* remove current rl index to free space to next ones */
-               mlx5_rl_remove_rate(mdev, sq->rate_limit);
+               mlx5_rl_remove_rate(mdev, &rl);
+       }
 
        sq->rate_limit = 0;
 
        if (rate) {
-               err = mlx5_rl_add_rate(mdev, rate, &rl_index);
+               rl.rate = rate;
+               err = mlx5_rl_add_rate(mdev, &rl_index, &rl);
                if (err) {
                        netdev_err(dev, "Failed configuring rate %u: %d\n",
                                   rate, err);
@@ -1560,7 +1567,7 @@ static int mlx5e_set_sq_maxrate(struct net_device *dev,
                           rate, err);
                /* remove the rate from the table */
                if (rate)
-                       mlx5_rl_remove_rate(mdev, rate);
+                       mlx5_rl_remove_rate(mdev, &rl);
                return err;
        }
 
index d3c33e9eea7292412974802c4c38ded8898ed55c..bc86dffdc43c524574412b53345ea948acc2e446 100644 (file)
@@ -107,16 +107,16 @@ int mlx5_destroy_scheduling_element_cmd(struct mlx5_core_dev *dev, u8 hierarchy,
  * If the table is full, return NULL
  */
 static struct mlx5_rl_entry *find_rl_entry(struct mlx5_rl_table *table,
-                                          u32 rate)
+                                          struct mlx5_rate_limit *rl)
 {
        struct mlx5_rl_entry *ret_entry = NULL;
        bool empty_found = false;
        int i;
 
        for (i = 0; i < table->max_size; i++) {
-               if (table->rl_entry[i].rate == rate)
+               if (mlx5_rl_are_equal(&table->rl_entry[i].rl, rl))
                        return &table->rl_entry[i];
-               if (!empty_found && !table->rl_entry[i].rate) {
+               if (!empty_found && !table->rl_entry[i].rl.rate) {
                        empty_found = true;
                        ret_entry = &table->rl_entry[i];
                }
@@ -126,7 +126,8 @@ static struct mlx5_rl_entry *find_rl_entry(struct mlx5_rl_table *table,
 }
 
 static int mlx5_set_pp_rate_limit_cmd(struct mlx5_core_dev *dev,
-                                  u32 rate, u16 index)
+                                     u16 index,
+                                     struct mlx5_rate_limit *rl)
 {
        u32 in[MLX5_ST_SZ_DW(set_pp_rate_limit_in)]   = {0};
        u32 out[MLX5_ST_SZ_DW(set_pp_rate_limit_out)] = {0};
@@ -134,7 +135,9 @@ static int mlx5_set_pp_rate_limit_cmd(struct mlx5_core_dev *dev,
        MLX5_SET(set_pp_rate_limit_in, in, opcode,
                 MLX5_CMD_OP_SET_PP_RATE_LIMIT);
        MLX5_SET(set_pp_rate_limit_in, in, rate_limit_index, index);
-       MLX5_SET(set_pp_rate_limit_in, in, rate_limit, rate);
+       MLX5_SET(set_pp_rate_limit_in, in, rate_limit, rl->rate);
+       MLX5_SET(set_pp_rate_limit_in, in, burst_upper_bound, rl->max_burst_sz);
+       MLX5_SET(set_pp_rate_limit_in, in, typical_packet_size, rl->typical_pkt_sz);
        return mlx5_cmd_exec(dev, in, sizeof(in), out, sizeof(out));
 }
 
@@ -146,7 +149,17 @@ bool mlx5_rl_is_in_range(struct mlx5_core_dev *dev, u32 rate)
 }
 EXPORT_SYMBOL(mlx5_rl_is_in_range);
 
-int mlx5_rl_add_rate(struct mlx5_core_dev *dev, u32 rate, u16 *index)
+bool mlx5_rl_are_equal(struct mlx5_rate_limit *rl_0,
+                      struct mlx5_rate_limit *rl_1)
+{
+       return ((rl_0->rate == rl_1->rate) &&
+               (rl_0->max_burst_sz == rl_1->max_burst_sz) &&
+               (rl_0->typical_pkt_sz == rl_1->typical_pkt_sz));
+}
+EXPORT_SYMBOL(mlx5_rl_are_equal);
+
+int mlx5_rl_add_rate(struct mlx5_core_dev *dev, u16 *index,
+                    struct mlx5_rate_limit *rl)
 {
        struct mlx5_rl_table *table = &dev->priv.rl_table;
        struct mlx5_rl_entry *entry;
@@ -154,14 +167,14 @@ int mlx5_rl_add_rate(struct mlx5_core_dev *dev, u32 rate, u16 *index)
 
        mutex_lock(&table->rl_lock);
 
-       if (!rate || !mlx5_rl_is_in_range(dev, rate)) {
+       if (!rl->rate || !mlx5_rl_is_in_range(dev, rl->rate)) {
                mlx5_core_err(dev, "Invalid rate: %u, should be %u to %u\n",
-                             rate, table->min_rate, table->max_rate);
+                             rl->rate, table->min_rate, table->max_rate);
                err = -EINVAL;
                goto out;
        }
 
-       entry = find_rl_entry(table, rate);
+       entry = find_rl_entry(table, rl);
        if (!entry) {
                mlx5_core_err(dev, "Max number of %u rates reached\n",
                              table->max_size);
@@ -173,13 +186,15 @@ int mlx5_rl_add_rate(struct mlx5_core_dev *dev, u32 rate, u16 *index)
                entry->refcount++;
        } else {
                /* new rate limit */
-               err = mlx5_set_pp_rate_limit_cmd(dev, rate, entry->index);
+               err = mlx5_set_pp_rate_limit_cmd(dev, entry->index, rl);
                if (err) {
-                       mlx5_core_err(dev, "Failed configuring rate: %u (%d)\n",
-                                     rate, err);
+                       mlx5_core_err(dev, "Failed configuring rate limit(err %d): \
+                                     rate %u, max_burst_sz %u, typical_pkt_sz %u\n",
+                                     err, rl->rate, rl->max_burst_sz,
+                                     rl->typical_pkt_sz);
                        goto out;
                }
-               entry->rate = rate;
+               entry->rl = *rl;
                entry->refcount = 1;
        }
        *index = entry->index;
@@ -190,27 +205,30 @@ out:
 }
 EXPORT_SYMBOL(mlx5_rl_add_rate);
 
-void mlx5_rl_remove_rate(struct mlx5_core_dev *dev, u32 rate)
+void mlx5_rl_remove_rate(struct mlx5_core_dev *dev, struct mlx5_rate_limit *rl)
 {
        struct mlx5_rl_table *table = &dev->priv.rl_table;
        struct mlx5_rl_entry *entry = NULL;
+       struct mlx5_rate_limit reset_rl = {0};
 
        /* 0 is a reserved value for unlimited rate */
-       if (rate == 0)
+       if (rl->rate == 0)
                return;
 
        mutex_lock(&table->rl_lock);
-       entry = find_rl_entry(table, rate);
+       entry = find_rl_entry(table, rl);
        if (!entry || !entry->refcount) {
-               mlx5_core_warn(dev, "Rate %u is not configured\n", rate);
+               mlx5_core_warn(dev, "Rate %u, max_burst_sz %u typical_pkt_sz %u \
+                              are not configured\n",
+                              rl->rate, rl->max_burst_sz, rl->typical_pkt_sz);
                goto out;
        }
 
        entry->refcount--;
        if (!entry->refcount) {
                /* need to remove rate */
-               mlx5_set_pp_rate_limit_cmd(dev, 0, entry->index);
-               entry->rate = 0;
+               mlx5_set_pp_rate_limit_cmd(dev, entry->index, &reset_rl);
+               entry->rl = reset_rl;
        }
 
 out:
@@ -257,13 +275,14 @@ int mlx5_init_rl_table(struct mlx5_core_dev *dev)
 void mlx5_cleanup_rl_table(struct mlx5_core_dev *dev)
 {
        struct mlx5_rl_table *table = &dev->priv.rl_table;
+       struct mlx5_rate_limit rl = {0};
        int i;
 
        /* Clear all configured rates */
        for (i = 0; i < table->max_size; i++)
-               if (table->rl_entry[i].rate)
-                       mlx5_set_pp_rate_limit_cmd(dev, 0,
-                                                  table->rl_entry[i].index);
+               if (table->rl_entry[i].rl.rate)
+                       mlx5_set_pp_rate_limit_cmd(dev, table->rl_entry[i].index,
+                                                  &rl);
 
        kfree(dev->priv.rl_table.rl_entry);
 }
index cded85ab6fe4556b2279df83084da174cce1c3d0..767d193c269aef28465476b91e85862a4e64715c 100644 (file)
@@ -591,8 +591,14 @@ struct mlx5_eswitch;
 struct mlx5_lag;
 struct mlx5_pagefault;
 
+struct mlx5_rate_limit {
+       u32                     rate;
+       u32                     max_burst_sz;
+       u16                     typical_pkt_sz;
+};
+
 struct mlx5_rl_entry {
-       u32                     rate;
+       struct mlx5_rate_limit  rl;
        u16                     index;
        u16                     refcount;
 };
@@ -1107,9 +1113,12 @@ int mlx5_core_page_fault_resume(struct mlx5_core_dev *dev, u32 token,
 
 int mlx5_init_rl_table(struct mlx5_core_dev *dev);
 void mlx5_cleanup_rl_table(struct mlx5_core_dev *dev);
-int mlx5_rl_add_rate(struct mlx5_core_dev *dev, u32 rate, u16 *index);
-void mlx5_rl_remove_rate(struct mlx5_core_dev *dev, u32 rate);
+int mlx5_rl_add_rate(struct mlx5_core_dev *dev, u16 *index,
+                    struct mlx5_rate_limit *rl);
+void mlx5_rl_remove_rate(struct mlx5_core_dev *dev, struct mlx5_rate_limit *rl);
 bool mlx5_rl_is_in_range(struct mlx5_core_dev *dev, u32 rate);
+bool mlx5_rl_are_equal(struct mlx5_rate_limit *rl_0,
+                      struct mlx5_rate_limit *rl_1);
 int mlx5_alloc_bfreg(struct mlx5_core_dev *mdev, struct mlx5_sq_bfreg *bfreg,
                     bool map_wc, bool fast_path);
 void mlx5_free_bfreg(struct mlx5_core_dev *mdev, struct mlx5_sq_bfreg *bfreg);
index 14ad84afe8babec960d406ce646a03f3cfc7dc9e..c63bbdc3550369a5bb73809ef131c6791dc68a6d 100644 (file)
@@ -571,7 +571,10 @@ struct mlx5_ifc_qos_cap_bits {
        u8         esw_scheduling[0x1];
        u8         esw_bw_share[0x1];
        u8         esw_rate_limit[0x1];
-       u8         reserved_at_4[0x1c];
+       u8         reserved_at_4[0x1];
+       u8         packet_pacing_burst_bound[0x1];
+       u8         packet_pacing_typical_size[0x1];
+       u8         reserved_at_7[0x19];
 
        u8         reserved_at_20[0x20];
 
@@ -7313,7 +7316,12 @@ struct mlx5_ifc_set_pp_rate_limit_in_bits {
 
        u8         rate_limit[0x20];
 
-       u8         reserved_at_a0[0x160];
+       u8         burst_upper_bound[0x20];
+
+       u8         reserved_at_c0[0x10];
+       u8         typical_packet_size[0x10];
+
+       u8         reserved_at_e0[0x120];
 };
 
 struct mlx5_ifc_access_register_out_bits {