lkml.org 
[lkml]   [2006]   [Feb]   [27]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    Date
    From
    Subject[patch 39/39] [PATCH] IB/mthca: max_inline_data handling tweaks
    -stable review patch.  If anyone has any objections, please let us know.
    ------------------

    Fix a case where copying max_inline_data from a successful create_qp
    capabilities output to create_qp input could cause EINVAL error:

    mthca_set_qp_size must check max_inline_data directly against
    max_desc_sz; checking qp->sq.max_gs is wrong since max_inline_data
    depends on the qp type and does not involve max_sg.

    Signed-off-by: Jack Morgenstein <jackm@mellanox.co.il>
    Signed-off-by: "Michael S. Tsirkin" <mst@mellanox.co.il>
    Signed-off-by: Roland Dreier <rolandd@cisco.com>
    Signed-off-by: Chris Wright <chrisw@sous-sol.org>
    ---
    fixes http://article.gmane.org/gmane.linux.drivers.openib/21118

    drivers/infiniband/hw/mthca/mthca_qp.c | 62 +++++++++++++++++++--------------
    1 files changed, 36 insertions(+), 26 deletions(-)

    --- linux-2.6.15.4.orig/drivers/infiniband/hw/mthca/mthca_qp.c
    +++ linux-2.6.15.4/drivers/infiniband/hw/mthca/mthca_qp.c
    @@ -885,18 +885,13 @@ int mthca_modify_qp(struct ib_qp *ibqp,
    return err;
    }

    -static void mthca_adjust_qp_caps(struct mthca_dev *dev,
    - struct mthca_pd *pd,
    - struct mthca_qp *qp)
    +static int mthca_max_data_size(struct mthca_dev *dev, struct mthca_qp *qp, int desc_sz)
    {
    - int max_data_size;
    -
    /*
    * Calculate the maximum size of WQE s/g segments, excluding
    * the next segment and other non-data segments.
    */
    - max_data_size = min(dev->limits.max_desc_sz, 1 << qp->sq.wqe_shift) -
    - sizeof (struct mthca_next_seg);
    + int max_data_size = desc_sz - sizeof (struct mthca_next_seg);

    switch (qp->transport) {
    case MLX:
    @@ -915,11 +910,24 @@ static void mthca_adjust_qp_caps(struct
    break;
    }

    + return max_data_size;
    +}
    +
    +static inline int mthca_max_inline_data(struct mthca_pd *pd, int max_data_size)
    +{
    /* We don't support inline data for kernel QPs (yet). */
    - if (!pd->ibpd.uobject)
    - qp->max_inline_data = 0;
    - else
    - qp->max_inline_data = max_data_size - MTHCA_INLINE_HEADER_SIZE;
    + return pd->ibpd.uobject ? max_data_size - MTHCA_INLINE_HEADER_SIZE : 0;
    +}
    +
    +static void mthca_adjust_qp_caps(struct mthca_dev *dev,
    + struct mthca_pd *pd,
    + struct mthca_qp *qp)
    +{
    + int max_data_size = mthca_max_data_size(dev, qp,
    + min(dev->limits.max_desc_sz,
    + 1 << qp->sq.wqe_shift));
    +
    + qp->max_inline_data = mthca_max_inline_data(pd, max_data_size);

    qp->sq.max_gs = min_t(int, dev->limits.max_sg,
    max_data_size / sizeof (struct mthca_data_seg));
    @@ -1186,13 +1194,23 @@ static int mthca_alloc_qp_common(struct
    }

    static int mthca_set_qp_size(struct mthca_dev *dev, struct ib_qp_cap *cap,
    - struct mthca_qp *qp)
    + struct mthca_pd *pd, struct mthca_qp *qp)
    {
    + int max_data_size = mthca_max_data_size(dev, qp, dev->limits.max_desc_sz);
    +
    /* Sanity check QP size before proceeding */
    - if (cap->max_send_wr > dev->limits.max_wqes ||
    - cap->max_recv_wr > dev->limits.max_wqes ||
    - cap->max_send_sge > dev->limits.max_sg ||
    - cap->max_recv_sge > dev->limits.max_sg)
    + if (cap->max_send_wr > dev->limits.max_wqes ||
    + cap->max_recv_wr > dev->limits.max_wqes ||
    + cap->max_send_sge > dev->limits.max_sg ||
    + cap->max_recv_sge > dev->limits.max_sg ||
    + cap->max_inline_data > mthca_max_inline_data(pd, max_data_size))
    + return -EINVAL;
    +
    + /*
    + * For MLX transport we need 2 extra S/G entries:
    + * one for the header and one for the checksum at the end
    + */
    + if (qp->transport == MLX && cap->max_recv_sge + 2 > dev->limits.max_sg)
    return -EINVAL;

    if (mthca_is_memfree(dev)) {
    @@ -1211,14 +1229,6 @@ static int mthca_set_qp_size(struct mthc
    MTHCA_INLINE_CHUNK_SIZE) /
    sizeof (struct mthca_data_seg));

    - /*
    - * For MLX transport we need 2 extra S/G entries:
    - * one for the header and one for the checksum at the end
    - */
    - if ((qp->transport == MLX && qp->sq.max_gs + 2 > dev->limits.max_sg) ||
    - qp->sq.max_gs > dev->limits.max_sg || qp->rq.max_gs > dev->limits.max_sg)
    - return -EINVAL;
    -
    return 0;
    }

    @@ -1233,7 +1243,7 @@ int mthca_alloc_qp(struct mthca_dev *dev
    {
    int err;

    - err = mthca_set_qp_size(dev, cap, qp);
    + err = mthca_set_qp_size(dev, cap, pd, qp);
    if (err)
    return err;

    @@ -1276,7 +1286,7 @@ int mthca_alloc_sqp(struct mthca_dev *de
    u32 mqpn = qpn * 2 + dev->qp_table.sqp_start + port - 1;
    int err;

    - err = mthca_set_qp_size(dev, cap, &sqp->qp);
    + err = mthca_set_qp_size(dev, cap, pd, &sqp->qp);
    if (err)
    return err;

    --
    -
    To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
    the body of a message to majordomo@vger.kernel.org
    More majordomo info at http://vger.kernel.org/majordomo-info.html
    Please read the FAQ at http://www.tux.org/lkml/

    \
     
     \ /
      Last update: 2006-02-27 23:42    [W:3.614 / U:0.008 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site