Commit 5b3bc7a6 authored by Jack Morgenstein's avatar Jack Morgenstein Committed by Roland Dreier

IB/mthca: max_inline_data handling tweaks

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: default avatarJack Morgenstein <jackm@mellanox.co.il>
Signed-off-by: default avatarMichael S. Tsirkin <mst@mellanox.co.il>
Signed-off-by: default avatarRoland Dreier <rolandd@cisco.com>
parent 46620056
...@@ -890,18 +890,13 @@ int mthca_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, int attr_mask) ...@@ -890,18 +890,13 @@ int mthca_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, int attr_mask)
return err; return err;
} }
static void mthca_adjust_qp_caps(struct mthca_dev *dev, static int mthca_max_data_size(struct mthca_dev *dev, struct mthca_qp *qp, int desc_sz)
struct mthca_pd *pd,
struct mthca_qp *qp)
{ {
int max_data_size;
/* /*
* Calculate the maximum size of WQE s/g segments, excluding * Calculate the maximum size of WQE s/g segments, excluding
* the next segment and other non-data segments. * the next segment and other non-data segments.
*/ */
max_data_size = min(dev->limits.max_desc_sz, 1 << qp->sq.wqe_shift) - int max_data_size = desc_sz - sizeof (struct mthca_next_seg);
sizeof (struct mthca_next_seg);
switch (qp->transport) { switch (qp->transport) {
case MLX: case MLX:
...@@ -920,11 +915,24 @@ static void mthca_adjust_qp_caps(struct mthca_dev *dev, ...@@ -920,11 +915,24 @@ static void mthca_adjust_qp_caps(struct mthca_dev *dev,
break; 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). */ /* We don't support inline data for kernel QPs (yet). */
if (!pd->ibpd.uobject) return pd->ibpd.uobject ? max_data_size - MTHCA_INLINE_HEADER_SIZE : 0;
qp->max_inline_data = 0; }
else
qp->max_inline_data = max_data_size - MTHCA_INLINE_HEADER_SIZE; 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, qp->sq.max_gs = min_t(int, dev->limits.max_sg,
max_data_size / sizeof (struct mthca_data_seg)); max_data_size / sizeof (struct mthca_data_seg));
...@@ -1191,13 +1199,23 @@ static int mthca_alloc_qp_common(struct mthca_dev *dev, ...@@ -1191,13 +1199,23 @@ static int mthca_alloc_qp_common(struct mthca_dev *dev,
} }
static int mthca_set_qp_size(struct mthca_dev *dev, struct ib_qp_cap *cap, 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 */ /* Sanity check QP size before proceeding */
if (cap->max_send_wr > dev->limits.max_wqes || if (cap->max_send_wr > dev->limits.max_wqes ||
cap->max_recv_wr > dev->limits.max_wqes || cap->max_recv_wr > dev->limits.max_wqes ||
cap->max_send_sge > dev->limits.max_sg || cap->max_send_sge > dev->limits.max_sg ||
cap->max_recv_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; return -EINVAL;
if (mthca_is_memfree(dev)) { if (mthca_is_memfree(dev)) {
...@@ -1216,14 +1234,6 @@ static int mthca_set_qp_size(struct mthca_dev *dev, struct ib_qp_cap *cap, ...@@ -1216,14 +1234,6 @@ static int mthca_set_qp_size(struct mthca_dev *dev, struct ib_qp_cap *cap,
MTHCA_INLINE_CHUNK_SIZE) / MTHCA_INLINE_CHUNK_SIZE) /
sizeof (struct mthca_data_seg)); 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; return 0;
} }
...@@ -1238,7 +1248,7 @@ int mthca_alloc_qp(struct mthca_dev *dev, ...@@ -1238,7 +1248,7 @@ int mthca_alloc_qp(struct mthca_dev *dev,
{ {
int err; int err;
err = mthca_set_qp_size(dev, cap, qp); err = mthca_set_qp_size(dev, cap, pd, qp);
if (err) if (err)
return err; return err;
...@@ -1281,7 +1291,7 @@ int mthca_alloc_sqp(struct mthca_dev *dev, ...@@ -1281,7 +1291,7 @@ int mthca_alloc_sqp(struct mthca_dev *dev,
u32 mqpn = qpn * 2 + dev->qp_table.sqp_start + port - 1; u32 mqpn = qpn * 2 + dev->qp_table.sqp_start + port - 1;
int err; int err;
err = mthca_set_qp_size(dev, cap, &sqp->qp); err = mthca_set_qp_size(dev, cap, pd, &sqp->qp);
if (err) if (err)
return err; return err;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment