From 3d148bc9a617fa1dbab0c4b785511c8f646f08a4 Mon Sep 17 00:00:00 2001 From: Chris Wright Date: Mon, 27 Feb 2006 14:03:42 -0800 Subject: [PATCH] Add IB fix for http://article.gmane.org/gmane.linux.drivers.openib/21118, fwd from Roland. --- ...thca-max_inline_data-handling-tweaks.patch | 139 ++++++++++++++++++ queue/series | 1 + 2 files changed, 140 insertions(+) create mode 100644 queue/ib-mthca-max_inline_data-handling-tweaks.patch diff --git a/queue/ib-mthca-max_inline_data-handling-tweaks.patch b/queue/ib-mthca-max_inline_data-handling-tweaks.patch new file mode 100644 index 00000000000..d4026d39009 --- /dev/null +++ b/queue/ib-mthca-max_inline_data-handling-tweaks.patch @@ -0,0 +1,139 @@ +From stable-bounces@linux.kernel.org Mon Feb 27 13:48:39 2006 +Date: Mon, 27 Feb 2006 13:44:40 -0800 +From: Roland Dreier +To: stable@kernel.org +Cc: +Subject: [PATCH] IB/mthca: max_inline_data handling tweaks + +From: Jack Morgenstein + +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 +Signed-off-by: Michael S. Tsirkin +Signed-off-by: Roland Dreier +Signed-off-by: Chris Wright +--- + + 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; + diff --git a/queue/series b/queue/series index 06fcea1f3cb..944403a1928 100644 --- a/queue/series +++ b/queue/series @@ -36,3 +36,4 @@ sd-fix-memory-corruption-with-broken-mode-page-headers.patch sbp2-fix-another-deadlock-after-disconnection.patch xfs-ftruncate-bug-could-expose-stale-data.patch normal-user-can-panic-nfs-client-with-direct-i-o.patch +ib-mthca-max_inline_data-handling-tweaks.patch -- 2.47.3