OSDN Git Service

net/mlx5: Fix QP fragmented buffer allocation
authorTariq Toukan <tariqt@mellanox.com>
Sun, 8 Jul 2018 09:14:59 +0000 (12:14 +0300)
committerSaeed Mahameed <saeedm@mellanox.com>
Thu, 19 Jul 2018 01:16:58 +0000 (18:16 -0700)
Fix bad alignment of SQ buffer in fragmented QP allocation.
It should start directly after RQ buffer ends.

Take special care of the end case where the RQ buffer does not occupy
a whole page. RQ size is a power of two, so would be the case only for
small RQ sizes (RQ size < PAGE_SIZE).

Fix wrong assignments for sqb->size (mistakenly assigned RQ size),
and for npages value of RQ and SQ.

Fixes: 3a2f70331226 ("net/mlx5: Use order-0 allocations for all WQ types")
Signed-off-by: Tariq Toukan <tariqt@mellanox.com>
Signed-off-by: Saeed Mahameed <saeedm@mellanox.com>
drivers/net/ethernet/mellanox/mlx5/core/alloc.c
drivers/net/ethernet/mellanox/mlx5/core/wq.c
include/linux/mlx5/driver.h

index 323ffe8..456f300 100644 (file)
@@ -123,7 +123,7 @@ int mlx5_frag_buf_alloc_node(struct mlx5_core_dev *dev, int size,
        int i;
 
        buf->size = size;
-       buf->npages = 1 << get_order(size);
+       buf->npages = DIV_ROUND_UP(size, PAGE_SIZE);
        buf->page_shift = PAGE_SHIFT;
        buf->frags = kcalloc(buf->npages, sizeof(struct mlx5_buf_list),
                             GFP_KERNEL);
index b97bb72..86478a6 100644 (file)
@@ -113,35 +113,45 @@ err_db_free:
        return err;
 }
 
-static void mlx5e_qp_set_frag_buf(struct mlx5_frag_buf *buf,
-                                 struct mlx5_wq_qp *qp)
+static void mlx5_qp_set_frag_buf(struct mlx5_frag_buf *buf,
+                                struct mlx5_wq_qp *qp)
 {
+       struct mlx5_frag_buf_ctrl *sq_fbc;
        struct mlx5_frag_buf *rqb, *sqb;
 
-       rqb = &qp->rq.fbc.frag_buf;
+       rqb  = &qp->rq.fbc.frag_buf;
        *rqb = *buf;
        rqb->size   = mlx5_wq_cyc_get_byte_size(&qp->rq);
-       rqb->npages = 1 << get_order(rqb->size);
+       rqb->npages = DIV_ROUND_UP(rqb->size, PAGE_SIZE);
 
-       sqb = &qp->sq.fbc.frag_buf;
-       *sqb = *buf;
-       sqb->size   = mlx5_wq_cyc_get_byte_size(&qp->rq);
-       sqb->npages = 1 << get_order(sqb->size);
+       sq_fbc = &qp->sq.fbc;
+       sqb    = &sq_fbc->frag_buf;
+       *sqb   = *buf;
+       sqb->size   = mlx5_wq_cyc_get_byte_size(&qp->sq);
+       sqb->npages = DIV_ROUND_UP(sqb->size, PAGE_SIZE);
        sqb->frags += rqb->npages; /* first part is for the rq */
+       if (sq_fbc->strides_offset)
+               sqb->frags--;
 }
 
 int mlx5_wq_qp_create(struct mlx5_core_dev *mdev, struct mlx5_wq_param *param,
                      void *qpc, struct mlx5_wq_qp *wq,
                      struct mlx5_wq_ctrl *wq_ctrl)
 {
+       u32 sq_strides_offset;
        int err;
 
        mlx5_fill_fbc(MLX5_GET(qpc, qpc, log_rq_stride) + 4,
                      MLX5_GET(qpc, qpc, log_rq_size),
                      &wq->rq.fbc);
-       mlx5_fill_fbc(ilog2(MLX5_SEND_WQE_BB),
-                     MLX5_GET(qpc, qpc, log_sq_size),
-                     &wq->sq.fbc);
+
+       sq_strides_offset =
+               ((wq->rq.fbc.frag_sz_m1 + 1) % PAGE_SIZE) / MLX5_SEND_WQE_BB;
+
+       mlx5_fill_fbc_offset(ilog2(MLX5_SEND_WQE_BB),
+                            MLX5_GET(qpc, qpc, log_sq_size),
+                            sq_strides_offset,
+                            &wq->sq.fbc);
 
        err = mlx5_db_alloc_node(mdev, &wq_ctrl->db, param->db_numa_node);
        if (err) {
@@ -156,7 +166,7 @@ int mlx5_wq_qp_create(struct mlx5_core_dev *mdev, struct mlx5_wq_param *param,
                goto err_db_free;
        }
 
-       mlx5e_qp_set_frag_buf(&wq_ctrl->buf, wq);
+       mlx5_qp_set_frag_buf(&wq_ctrl->buf, wq);
 
        wq->rq.db  = &wq_ctrl->db.db[MLX5_RCV_DBR];
        wq->sq.db  = &wq_ctrl->db.db[MLX5_SND_DBR];
index 80cbb7f..8395792 100644 (file)
@@ -358,6 +358,7 @@ struct mlx5_frag_buf_ctrl {
        struct mlx5_frag_buf    frag_buf;
        u32                     sz_m1;
        u32                     frag_sz_m1;
+       u32                     strides_offset;
        u8                      log_sz;
        u8                      log_stride;
        u8                      log_frag_strides;
@@ -983,14 +984,22 @@ static inline u32 mlx5_base_mkey(const u32 key)
        return key & 0xffffff00u;
 }
 
-static inline void mlx5_fill_fbc(u8 log_stride, u8 log_sz,
-                                struct mlx5_frag_buf_ctrl *fbc)
+static inline void mlx5_fill_fbc_offset(u8 log_stride, u8 log_sz,
+                                       u32 strides_offset,
+                                       struct mlx5_frag_buf_ctrl *fbc)
 {
        fbc->log_stride = log_stride;
        fbc->log_sz     = log_sz;
        fbc->sz_m1      = (1 << fbc->log_sz) - 1;
        fbc->log_frag_strides = PAGE_SHIFT - fbc->log_stride;
        fbc->frag_sz_m1 = (1 << fbc->log_frag_strides) - 1;
+       fbc->strides_offset = strides_offset;
+}
+
+static inline void mlx5_fill_fbc(u8 log_stride, u8 log_sz,
+                                struct mlx5_frag_buf_ctrl *fbc)
+{
+       mlx5_fill_fbc_offset(log_stride, log_sz, 0, fbc);
 }
 
 static inline void mlx5_core_init_cq_frag_buf(struct mlx5_frag_buf_ctrl *fbc,
@@ -1004,7 +1013,10 @@ static inline void mlx5_core_init_cq_frag_buf(struct mlx5_frag_buf_ctrl *fbc,
 static inline void *mlx5_frag_buf_get_wqe(struct mlx5_frag_buf_ctrl *fbc,
                                          u32 ix)
 {
-       unsigned int frag = (ix >> fbc->log_frag_strides);
+       unsigned int frag;
+
+       ix  += fbc->strides_offset;
+       frag = ix >> fbc->log_frag_strides;
 
        return fbc->frag_buf.frags[frag].buf +
                ((fbc->frag_sz_m1 & ix) << fbc->log_stride);