diff options
author | Jack Morgenstein <jackm@mellanox.co.il> | 2006-01-06 15:57:30 -0500 |
---|---|---|
committer | Roland Dreier <rolandd@cisco.com> | 2006-01-06 15:57:30 -0500 |
commit | 5b3bc7a68171138d52b1b62012c37ac888895460 (patch) | |
tree | 63960e2e3f8db5bbe7ef5c9d64e1c5ea3a9124f5 /drivers/infiniband/hw | |
parent | 466200562ccd80f728f7ef602d2b97b4fdedd566 (diff) |
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: Jack Morgenstein <jackm@mellanox.co.il>
Signed-off-by: Michael S. Tsirkin <mst@mellanox.co.il>
Signed-off-by: Roland Dreier <rolandd@cisco.com>
Diffstat (limited to 'drivers/infiniband/hw')
-rw-r--r-- | drivers/infiniband/hw/mthca/mthca_qp.c | 62 |
1 files changed, 36 insertions, 26 deletions
diff --git a/drivers/infiniband/hw/mthca/mthca_qp.c b/drivers/infiniband/hw/mthca/mthca_qp.c index ea45fa400fab..fd60cf3a5ba3 100644 --- a/drivers/infiniband/hw/mthca/mthca_qp.c +++ b/drivers/infiniband/hw/mthca/mthca_qp.c | |||
@@ -890,18 +890,13 @@ int mthca_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, int attr_mask) | |||
890 | return err; | 890 | return err; |
891 | } | 891 | } |
892 | 892 | ||
893 | static void mthca_adjust_qp_caps(struct mthca_dev *dev, | 893 | static int mthca_max_data_size(struct mthca_dev *dev, struct mthca_qp *qp, int desc_sz) |
894 | struct mthca_pd *pd, | ||
895 | struct mthca_qp *qp) | ||
896 | { | 894 | { |
897 | int max_data_size; | ||
898 | |||
899 | /* | 895 | /* |
900 | * Calculate the maximum size of WQE s/g segments, excluding | 896 | * Calculate the maximum size of WQE s/g segments, excluding |
901 | * the next segment and other non-data segments. | 897 | * the next segment and other non-data segments. |
902 | */ | 898 | */ |
903 | max_data_size = min(dev->limits.max_desc_sz, 1 << qp->sq.wqe_shift) - | 899 | int max_data_size = desc_sz - sizeof (struct mthca_next_seg); |
904 | sizeof (struct mthca_next_seg); | ||
905 | 900 | ||
906 | switch (qp->transport) { | 901 | switch (qp->transport) { |
907 | case MLX: | 902 | case MLX: |
@@ -920,11 +915,24 @@ static void mthca_adjust_qp_caps(struct mthca_dev *dev, | |||
920 | break; | 915 | break; |
921 | } | 916 | } |
922 | 917 | ||
918 | return max_data_size; | ||
919 | } | ||
920 | |||
921 | static inline int mthca_max_inline_data(struct mthca_pd *pd, int max_data_size) | ||
922 | { | ||
923 | /* We don't support inline data for kernel QPs (yet). */ | 923 | /* We don't support inline data for kernel QPs (yet). */ |
924 | if (!pd->ibpd.uobject) | 924 | return pd->ibpd.uobject ? max_data_size - MTHCA_INLINE_HEADER_SIZE : 0; |
925 | qp->max_inline_data = 0; | 925 | } |
926 | else | 926 | |
927 | qp->max_inline_data = max_data_size - MTHCA_INLINE_HEADER_SIZE; | 927 | static void mthca_adjust_qp_caps(struct mthca_dev *dev, |
928 | struct mthca_pd *pd, | ||
929 | struct mthca_qp *qp) | ||
930 | { | ||
931 | int max_data_size = mthca_max_data_size(dev, qp, | ||
932 | min(dev->limits.max_desc_sz, | ||
933 | 1 << qp->sq.wqe_shift)); | ||
934 | |||
935 | qp->max_inline_data = mthca_max_inline_data(pd, max_data_size); | ||
928 | 936 | ||
929 | qp->sq.max_gs = min_t(int, dev->limits.max_sg, | 937 | qp->sq.max_gs = min_t(int, dev->limits.max_sg, |
930 | max_data_size / sizeof (struct mthca_data_seg)); | 938 | max_data_size / sizeof (struct mthca_data_seg)); |
@@ -1191,13 +1199,23 @@ static int mthca_alloc_qp_common(struct mthca_dev *dev, | |||
1191 | } | 1199 | } |
1192 | 1200 | ||
1193 | static int mthca_set_qp_size(struct mthca_dev *dev, struct ib_qp_cap *cap, | 1201 | static int mthca_set_qp_size(struct mthca_dev *dev, struct ib_qp_cap *cap, |
1194 | struct mthca_qp *qp) | 1202 | struct mthca_pd *pd, struct mthca_qp *qp) |
1195 | { | 1203 | { |
1204 | int max_data_size = mthca_max_data_size(dev, qp, dev->limits.max_desc_sz); | ||
1205 | |||
1196 | /* Sanity check QP size before proceeding */ | 1206 | /* Sanity check QP size before proceeding */ |
1197 | if (cap->max_send_wr > dev->limits.max_wqes || | 1207 | if (cap->max_send_wr > dev->limits.max_wqes || |
1198 | cap->max_recv_wr > dev->limits.max_wqes || | 1208 | cap->max_recv_wr > dev->limits.max_wqes || |
1199 | cap->max_send_sge > dev->limits.max_sg || | 1209 | cap->max_send_sge > dev->limits.max_sg || |
1200 | cap->max_recv_sge > dev->limits.max_sg) | 1210 | cap->max_recv_sge > dev->limits.max_sg || |
1211 | cap->max_inline_data > mthca_max_inline_data(pd, max_data_size)) | ||
1212 | return -EINVAL; | ||
1213 | |||
1214 | /* | ||
1215 | * For MLX transport we need 2 extra S/G entries: | ||
1216 | * one for the header and one for the checksum at the end | ||
1217 | */ | ||
1218 | if (qp->transport == MLX && cap->max_recv_sge + 2 > dev->limits.max_sg) | ||
1201 | return -EINVAL; | 1219 | return -EINVAL; |
1202 | 1220 | ||
1203 | if (mthca_is_memfree(dev)) { | 1221 | 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 | MTHCA_INLINE_CHUNK_SIZE) / | 1234 | MTHCA_INLINE_CHUNK_SIZE) / |
1217 | sizeof (struct mthca_data_seg)); | 1235 | sizeof (struct mthca_data_seg)); |
1218 | 1236 | ||
1219 | /* | ||
1220 | * For MLX transport we need 2 extra S/G entries: | ||
1221 | * one for the header and one for the checksum at the end | ||
1222 | */ | ||
1223 | if ((qp->transport == MLX && qp->sq.max_gs + 2 > dev->limits.max_sg) || | ||
1224 | qp->sq.max_gs > dev->limits.max_sg || qp->rq.max_gs > dev->limits.max_sg) | ||
1225 | return -EINVAL; | ||
1226 | |||
1227 | return 0; | 1237 | return 0; |
1228 | } | 1238 | } |
1229 | 1239 | ||
@@ -1238,7 +1248,7 @@ int mthca_alloc_qp(struct mthca_dev *dev, | |||
1238 | { | 1248 | { |
1239 | int err; | 1249 | int err; |
1240 | 1250 | ||
1241 | err = mthca_set_qp_size(dev, cap, qp); | 1251 | err = mthca_set_qp_size(dev, cap, pd, qp); |
1242 | if (err) | 1252 | if (err) |
1243 | return err; | 1253 | return err; |
1244 | 1254 | ||
@@ -1281,7 +1291,7 @@ int mthca_alloc_sqp(struct mthca_dev *dev, | |||
1281 | u32 mqpn = qpn * 2 + dev->qp_table.sqp_start + port - 1; | 1291 | u32 mqpn = qpn * 2 + dev->qp_table.sqp_start + port - 1; |
1282 | int err; | 1292 | int err; |
1283 | 1293 | ||
1284 | err = mthca_set_qp_size(dev, cap, &sqp->qp); | 1294 | err = mthca_set_qp_size(dev, cap, pd, &sqp->qp); |
1285 | if (err) | 1295 | if (err) |
1286 | return err; | 1296 | return err; |
1287 | 1297 | ||