From 6ba1eb776461375481bb2ad93febf7802cf0714e Mon Sep 17 00:00:00 2001 From: Majd Dibbiny Date: Mon, 19 Sep 2016 18:32:22 +0300 Subject: [PATCH] IB/mlx4: Scatter CQs to different EQs If the user does not request a specific comp vector, use a weight based algorithm to set the EQ. Orabug: 24705943 Signed-off-by: Majd Dibbiny Signed-off-by: Santosh Shilimkar --- drivers/infiniband/hw/mlx4/cq.c | 12 ++++++-- drivers/infiniband/hw/mlx4/mlx4_ib.h | 2 ++ drivers/net/ethernet/mellanox/mlx4/eq.c | 34 +++++++++++++++++++++++ drivers/net/ethernet/mellanox/mlx4/mlx4.h | 1 + include/linux/mlx4/device.h | 1 + include/linux/mlx4/driver.h | 3 ++ 6 files changed, 51 insertions(+), 2 deletions(-) diff --git a/drivers/infiniband/hw/mlx4/cq.c b/drivers/infiniband/hw/mlx4/cq.c index 50418728e6798..e10fa915fb9fd 100644 --- a/drivers/infiniband/hw/mlx4/cq.c +++ b/drivers/infiniband/hw/mlx4/cq.c @@ -231,8 +231,12 @@ struct ib_cq *mlx4_ib_create_cq(struct ib_device *ibdev, int entries, int vector uar = &dev->priv_uar; } - if (dev->eq_table) - vector = dev->eq_table[vector % ibdev->num_comp_vectors]; + if (dev->eq_table) { + vector = dev->eq_table[mlx4_choose_vector(dev->dev, vector, + ibdev->num_comp_vectors)]; + } + + cq->vector = vector; err = mlx4_cq_alloc(dev->dev, entries, &cq->buf.mtt, uar, cq->db.dma, &cq->mcq, vector, 0, 0); @@ -254,6 +258,8 @@ struct ib_cq *mlx4_ib_create_cq(struct ib_device *ibdev, int entries, int vector return &cq->ibcq; err_dbmap: + mlx4_release_vector(dev->dev, cq->vector); + if (context) mlx4_ib_db_unmap_user(to_mucontext(context), &cq->db); @@ -481,6 +487,8 @@ int mlx4_ib_destroy_cq(struct ib_cq *cq) mlx4_db_free(dev->dev, &mcq->db); } + mlx4_release_vector(dev->dev, mcq->vector); + kfree(mcq); return 0; diff --git a/drivers/infiniband/hw/mlx4/mlx4_ib.h b/drivers/infiniband/hw/mlx4/mlx4_ib.h index 31ea8862c2b06..5c50b4bbe0875 100644 --- a/drivers/infiniband/hw/mlx4/mlx4_ib.h +++ b/drivers/infiniband/hw/mlx4/mlx4_ib.h @@ -46,6 +46,7 @@ #include #include +#include #define MLX4_IB_DRV_NAME "mlx4_ib" @@ -121,6 +122,7 @@ struct mlx4_ib_cq { /* List of qps that it serves.*/ struct list_head send_qp_list; struct list_head recv_qp_list; + int vector; }; struct mlx4_ib_mr { diff --git a/drivers/net/ethernet/mellanox/mlx4/eq.c b/drivers/net/ethernet/mellanox/mlx4/eq.c index fba236ee10599..f47eb06df9ce7 100644 --- a/drivers/net/ethernet/mellanox/mlx4/eq.c +++ b/drivers/net/ethernet/mellanox/mlx4/eq.c @@ -1147,6 +1147,7 @@ int mlx4_init_eq_table(struct mlx4_dev *dev) int err; int i; + spin_lock_init(&dev->eq_accounting_lock); priv->eq_table.uar_map = kcalloc(mlx4_num_eq_uar(dev), sizeof *priv->eq_table.uar_map, GFP_KERNEL); @@ -1447,3 +1448,36 @@ void mlx4_release_eq(struct mlx4_dev *dev, int vec) } EXPORT_SYMBOL(mlx4_release_eq); +int mlx4_choose_vector(struct mlx4_dev *dev, int vector, int num_comp) +{ + struct mlx4_eq *chosen; + int k; + + if (vector || smp_processor_id() == (vector % num_online_cpus())) { + spin_lock(&dev->eq_accounting_lock); + mlx4_priv(dev)->eq_table.eq[vector].ncqs++; + spin_unlock(&dev->eq_accounting_lock); + } else { + spin_lock(&dev->eq_accounting_lock); + chosen = &mlx4_priv(dev)->eq_table.eq[0]; + for (k = 0; k < num_comp; k++) { + if (mlx4_priv(dev)->eq_table.eq[k].ncqs < chosen->ncqs) { + chosen = &mlx4_priv(dev)->eq_table.eq[k]; + vector = k; + } + } + chosen->ncqs++; + spin_unlock(&dev->eq_accounting_lock); + } + + return vector; +} +EXPORT_SYMBOL(mlx4_choose_vector); + +void mlx4_release_vector(struct mlx4_dev *dev, int vector) +{ + spin_lock(&dev->eq_accounting_lock); + mlx4_priv(dev)->eq_table.eq[vector].ncqs--; + spin_unlock(&dev->eq_accounting_lock); +} +EXPORT_SYMBOL(mlx4_release_vector); diff --git a/drivers/net/ethernet/mellanox/mlx4/mlx4.h b/drivers/net/ethernet/mellanox/mlx4/mlx4.h index 7370460bebc7d..9cc1a8cee0fd6 100644 --- a/drivers/net/ethernet/mellanox/mlx4/mlx4.h +++ b/drivers/net/ethernet/mellanox/mlx4/mlx4.h @@ -391,6 +391,7 @@ struct mlx4_eq { struct mlx4_buf_list *page_list; struct mlx4_mtt mtt; struct mlx4_eq_tasklet tasklet_ctx; + u32 ncqs; }; struct mlx4_slave_eqe { diff --git a/include/linux/mlx4/device.h b/include/linux/mlx4/device.h index a2d538fff462f..76f276ed676a1 100644 --- a/include/linux/mlx4/device.h +++ b/include/linux/mlx4/device.h @@ -832,6 +832,7 @@ struct mlx4_dev { u64 regid_promisc_array[MLX4_MAX_PORTS + 1]; u64 regid_allmulti_array[MLX4_MAX_PORTS + 1]; struct mlx4_vf_dev *dev_vfs; + spinlock_t eq_accounting_lock; }; struct mlx4_eqe { diff --git a/include/linux/mlx4/driver.h b/include/linux/mlx4/driver.h index 9553a73d2049e..c6cd046fd5ddc 100644 --- a/include/linux/mlx4/driver.h +++ b/include/linux/mlx4/driver.h @@ -95,4 +95,7 @@ static inline u64 mlx4_mac_to_u64(u8 *addr) return mac; } +int mlx4_choose_vector(struct mlx4_dev *dev, int vector, int num_comp); +void mlx4_release_vector(struct mlx4_dev *dev, int vector); + #endif /* MLX4_DRIVER_H */ -- 2.50.1