diff options
author | Jack Morgenstein <jackm@mellanox.co.il> | 2005-10-10 16:48:07 -0400 |
---|---|---|
committer | Roland Dreier <rolandd@cisco.com> | 2005-10-17 18:20:29 -0400 |
commit | efaae8f71f3088cc73c9e5ceabbd314aa82ac768 (patch) | |
tree | b19084ae0a9dc6837cb2837cbd21386c9f1b2e0e /drivers/infiniband | |
parent | 4ab6fb7e5b3d34b65a1c3473d80d9d1a462d3a49 (diff) |
[IB] mthca: Better limit checking and reporting
Check the sizes of CQs, QPs and SRQs when creating objects, and fail
instead of creating too-big queues. Also return real limits instead
of just plausible-sounding values from mthca_query_device().
Signed-off-by: Jack Morgenstein <jackm@mellanox.co.il>
Signed-off-by: Roland Dreier <rolandd@cisco.com>
Diffstat (limited to 'drivers/infiniband')
-rw-r--r-- | drivers/infiniband/hw/mthca/mthca_cmd.c | 6 | ||||
-rw-r--r-- | drivers/infiniband/hw/mthca/mthca_dev.h | 6 | ||||
-rw-r--r-- | drivers/infiniband/hw/mthca/mthca_main.c | 9 | ||||
-rw-r--r-- | drivers/infiniband/hw/mthca/mthca_mcg.c | 4 | ||||
-rw-r--r-- | drivers/infiniband/hw/mthca/mthca_provider.c | 18 | ||||
-rw-r--r-- | drivers/infiniband/hw/mthca/mthca_qp.c | 6 | ||||
-rw-r--r-- | drivers/infiniband/hw/mthca/mthca_srq.c | 3 |
7 files changed, 40 insertions, 12 deletions
diff --git a/drivers/infiniband/hw/mthca/mthca_cmd.c b/drivers/infiniband/hw/mthca/mthca_cmd.c index f6a8ac026557..1bd7dc8f778c 100644 --- a/drivers/infiniband/hw/mthca/mthca_cmd.c +++ b/drivers/infiniband/hw/mthca/mthca_cmd.c | |||
@@ -933,9 +933,9 @@ int mthca_QUERY_DEV_LIM(struct mthca_dev *dev, | |||
933 | goto out; | 933 | goto out; |
934 | 934 | ||
935 | MTHCA_GET(field, outbox, QUERY_DEV_LIM_MAX_SRQ_SZ_OFFSET); | 935 | MTHCA_GET(field, outbox, QUERY_DEV_LIM_MAX_SRQ_SZ_OFFSET); |
936 | dev_lim->max_srq_sz = 1 << field; | 936 | dev_lim->max_srq_sz = (1 << field) - 1; |
937 | MTHCA_GET(field, outbox, QUERY_DEV_LIM_MAX_QP_SZ_OFFSET); | 937 | MTHCA_GET(field, outbox, QUERY_DEV_LIM_MAX_QP_SZ_OFFSET); |
938 | dev_lim->max_qp_sz = 1 << field; | 938 | dev_lim->max_qp_sz = (1 << field) - 1; |
939 | MTHCA_GET(field, outbox, QUERY_DEV_LIM_RSVD_QP_OFFSET); | 939 | MTHCA_GET(field, outbox, QUERY_DEV_LIM_RSVD_QP_OFFSET); |
940 | dev_lim->reserved_qps = 1 << (field & 0xf); | 940 | dev_lim->reserved_qps = 1 << (field & 0xf); |
941 | MTHCA_GET(field, outbox, QUERY_DEV_LIM_MAX_QP_OFFSET); | 941 | MTHCA_GET(field, outbox, QUERY_DEV_LIM_MAX_QP_OFFSET); |
@@ -1045,6 +1045,8 @@ int mthca_QUERY_DEV_LIM(struct mthca_dev *dev, | |||
1045 | dev_lim->max_pds, dev_lim->reserved_pds, dev_lim->reserved_uars); | 1045 | dev_lim->max_pds, dev_lim->reserved_pds, dev_lim->reserved_uars); |
1046 | mthca_dbg(dev, "Max QP/MCG: %d, reserved MGMs: %d\n", | 1046 | mthca_dbg(dev, "Max QP/MCG: %d, reserved MGMs: %d\n", |
1047 | dev_lim->max_pds, dev_lim->reserved_mgms); | 1047 | dev_lim->max_pds, dev_lim->reserved_mgms); |
1048 | mthca_dbg(dev, "Max CQEs: %d, max WQEs: %d, max SRQ WQEs: %d\n", | ||
1049 | dev_lim->max_cq_sz, dev_lim->max_qp_sz, dev_lim->max_srq_sz); | ||
1048 | 1050 | ||
1049 | mthca_dbg(dev, "Flags: %08x\n", dev_lim->flags); | 1051 | mthca_dbg(dev, "Flags: %08x\n", dev_lim->flags); |
1050 | 1052 | ||
diff --git a/drivers/infiniband/hw/mthca/mthca_dev.h b/drivers/infiniband/hw/mthca/mthca_dev.h index 6e18c128af42..f106bac0f925 100644 --- a/drivers/infiniband/hw/mthca/mthca_dev.h +++ b/drivers/infiniband/hw/mthca/mthca_dev.h | |||
@@ -83,6 +83,8 @@ enum { | |||
83 | /* Arbel FW gives us these, but we need them for Tavor */ | 83 | /* Arbel FW gives us these, but we need them for Tavor */ |
84 | MTHCA_MPT_ENTRY_SIZE = 0x40, | 84 | MTHCA_MPT_ENTRY_SIZE = 0x40, |
85 | MTHCA_MTT_SEG_SIZE = 0x40, | 85 | MTHCA_MTT_SEG_SIZE = 0x40, |
86 | |||
87 | MTHCA_QP_PER_MGM = 4 * (MTHCA_MGM_ENTRY_SIZE / 16 - 2) | ||
86 | }; | 88 | }; |
87 | 89 | ||
88 | enum { | 90 | enum { |
@@ -128,12 +130,16 @@ struct mthca_limits { | |||
128 | int num_uars; | 130 | int num_uars; |
129 | int max_sg; | 131 | int max_sg; |
130 | int num_qps; | 132 | int num_qps; |
133 | int max_wqes; | ||
134 | int max_qp_init_rdma; | ||
131 | int reserved_qps; | 135 | int reserved_qps; |
132 | int num_srqs; | 136 | int num_srqs; |
137 | int max_srq_wqes; | ||
133 | int reserved_srqs; | 138 | int reserved_srqs; |
134 | int num_eecs; | 139 | int num_eecs; |
135 | int reserved_eecs; | 140 | int reserved_eecs; |
136 | int num_cqs; | 141 | int num_cqs; |
142 | int max_cqes; | ||
137 | int reserved_cqs; | 143 | int reserved_cqs; |
138 | int num_eqs; | 144 | int num_eqs; |
139 | int reserved_eqs; | 145 | int reserved_eqs; |
diff --git a/drivers/infiniband/hw/mthca/mthca_main.c b/drivers/infiniband/hw/mthca/mthca_main.c index 576e7fcd053c..7c35abec81ea 100644 --- a/drivers/infiniband/hw/mthca/mthca_main.c +++ b/drivers/infiniband/hw/mthca/mthca_main.c | |||
@@ -162,9 +162,18 @@ static int __devinit mthca_dev_lim(struct mthca_dev *mdev, struct mthca_dev_lim | |||
162 | mdev->limits.pkey_table_len = dev_lim->max_pkeys; | 162 | mdev->limits.pkey_table_len = dev_lim->max_pkeys; |
163 | mdev->limits.local_ca_ack_delay = dev_lim->local_ca_ack_delay; | 163 | mdev->limits.local_ca_ack_delay = dev_lim->local_ca_ack_delay; |
164 | mdev->limits.max_sg = dev_lim->max_sg; | 164 | mdev->limits.max_sg = dev_lim->max_sg; |
165 | mdev->limits.max_wqes = dev_lim->max_qp_sz; | ||
166 | mdev->limits.max_qp_init_rdma = dev_lim->max_requester_per_qp; | ||
165 | mdev->limits.reserved_qps = dev_lim->reserved_qps; | 167 | mdev->limits.reserved_qps = dev_lim->reserved_qps; |
168 | mdev->limits.max_srq_wqes = dev_lim->max_srq_sz; | ||
166 | mdev->limits.reserved_srqs = dev_lim->reserved_srqs; | 169 | mdev->limits.reserved_srqs = dev_lim->reserved_srqs; |
167 | mdev->limits.reserved_eecs = dev_lim->reserved_eecs; | 170 | mdev->limits.reserved_eecs = dev_lim->reserved_eecs; |
171 | /* | ||
172 | * Subtract 1 from the limit because we need to allocate a | ||
173 | * spare CQE so the HCA HW can tell the difference between an | ||
174 | * empty CQ and a full CQ. | ||
175 | */ | ||
176 | mdev->limits.max_cqes = dev_lim->max_cq_sz - 1; | ||
168 | mdev->limits.reserved_cqs = dev_lim->reserved_cqs; | 177 | mdev->limits.reserved_cqs = dev_lim->reserved_cqs; |
169 | mdev->limits.reserved_eqs = dev_lim->reserved_eqs; | 178 | mdev->limits.reserved_eqs = dev_lim->reserved_eqs; |
170 | mdev->limits.reserved_mtts = dev_lim->reserved_mtts; | 179 | mdev->limits.reserved_mtts = dev_lim->reserved_mtts; |
diff --git a/drivers/infiniband/hw/mthca/mthca_mcg.c b/drivers/infiniband/hw/mthca/mthca_mcg.c index a2707605f4c8..9a0612a9d304 100644 --- a/drivers/infiniband/hw/mthca/mthca_mcg.c +++ b/drivers/infiniband/hw/mthca/mthca_mcg.c | |||
@@ -37,10 +37,6 @@ | |||
37 | #include "mthca_dev.h" | 37 | #include "mthca_dev.h" |
38 | #include "mthca_cmd.h" | 38 | #include "mthca_cmd.h" |
39 | 39 | ||
40 | enum { | ||
41 | MTHCA_QP_PER_MGM = 4 * (MTHCA_MGM_ENTRY_SIZE / 16 - 2) | ||
42 | }; | ||
43 | |||
44 | struct mthca_mgm { | 40 | struct mthca_mgm { |
45 | __be32 next_gid_index; | 41 | __be32 next_gid_index; |
46 | u32 reserved[3]; | 42 | u32 reserved[3]; |
diff --git a/drivers/infiniband/hw/mthca/mthca_provider.c b/drivers/infiniband/hw/mthca/mthca_provider.c index 53b29a0841bf..46864d18827d 100644 --- a/drivers/infiniband/hw/mthca/mthca_provider.c +++ b/drivers/infiniband/hw/mthca/mthca_provider.c | |||
@@ -90,17 +90,26 @@ static int mthca_query_device(struct ib_device *ibdev, | |||
90 | 90 | ||
91 | props->max_mr_size = ~0ull; | 91 | props->max_mr_size = ~0ull; |
92 | props->max_qp = mdev->limits.num_qps - mdev->limits.reserved_qps; | 92 | props->max_qp = mdev->limits.num_qps - mdev->limits.reserved_qps; |
93 | props->max_qp_wr = 0xffff; | 93 | props->max_qp_wr = mdev->limits.max_wqes; |
94 | props->max_sge = mdev->limits.max_sg; | 94 | props->max_sge = mdev->limits.max_sg; |
95 | props->max_cq = mdev->limits.num_cqs - mdev->limits.reserved_cqs; | 95 | props->max_cq = mdev->limits.num_cqs - mdev->limits.reserved_cqs; |
96 | props->max_cqe = 0xffff; | 96 | props->max_cqe = mdev->limits.max_cqes; |
97 | props->max_mr = mdev->limits.num_mpts - mdev->limits.reserved_mrws; | 97 | props->max_mr = mdev->limits.num_mpts - mdev->limits.reserved_mrws; |
98 | props->max_pd = mdev->limits.num_pds - mdev->limits.reserved_pds; | 98 | props->max_pd = mdev->limits.num_pds - mdev->limits.reserved_pds; |
99 | props->max_qp_rd_atom = 1 << mdev->qp_table.rdb_shift; | 99 | props->max_qp_rd_atom = 1 << mdev->qp_table.rdb_shift; |
100 | props->max_qp_init_rd_atom = 1 << mdev->qp_table.rdb_shift; | 100 | props->max_qp_init_rd_atom = mdev->limits.max_qp_init_rdma; |
101 | props->max_res_rd_atom = props->max_qp_rd_atom * props->max_qp; | ||
102 | props->max_srq = mdev->limits.num_srqs - mdev->limits.reserved_srqs; | ||
103 | props->max_srq_wr = mdev->limits.max_srq_wqes; | ||
104 | props->max_srq_sge = mdev->limits.max_sg; | ||
101 | props->local_ca_ack_delay = mdev->limits.local_ca_ack_delay; | 105 | props->local_ca_ack_delay = mdev->limits.local_ca_ack_delay; |
102 | props->atomic_cap = mdev->limits.flags & DEV_LIM_FLAG_ATOMIC ? | 106 | props->atomic_cap = mdev->limits.flags & DEV_LIM_FLAG_ATOMIC ? |
103 | IB_ATOMIC_HCA : IB_ATOMIC_NONE; | 107 | IB_ATOMIC_HCA : IB_ATOMIC_NONE; |
108 | props->max_pkeys = mdev->limits.pkey_table_len; | ||
109 | props->max_mcast_grp = mdev->limits.num_mgms + mdev->limits.num_amgms; | ||
110 | props->max_mcast_qp_attach = MTHCA_QP_PER_MGM; | ||
111 | props->max_total_mcast_qp_attach = props->max_mcast_qp_attach * | ||
112 | props->max_mcast_grp; | ||
104 | 113 | ||
105 | err = 0; | 114 | err = 0; |
106 | out: | 115 | out: |
@@ -640,6 +649,9 @@ static struct ib_cq *mthca_create_cq(struct ib_device *ibdev, int entries, | |||
640 | int nent; | 649 | int nent; |
641 | int err; | 650 | int err; |
642 | 651 | ||
652 | if (entries < 1 || entries > to_mdev(ibdev)->limits.max_cqes) | ||
653 | return ERR_PTR(-EINVAL); | ||
654 | |||
643 | if (context) { | 655 | if (context) { |
644 | if (ib_copy_from_udata(&ucmd, udata, sizeof ucmd)) | 656 | if (ib_copy_from_udata(&ucmd, udata, sizeof ucmd)) |
645 | return ERR_PTR(-EFAULT); | 657 | return ERR_PTR(-EFAULT); |
diff --git a/drivers/infiniband/hw/mthca/mthca_qp.c b/drivers/infiniband/hw/mthca/mthca_qp.c index 5fa00669f9b8..2ee0a2b0fd4b 100644 --- a/drivers/infiniband/hw/mthca/mthca_qp.c +++ b/drivers/infiniband/hw/mthca/mthca_qp.c | |||
@@ -1112,8 +1112,10 @@ static int mthca_set_qp_size(struct mthca_dev *dev, struct ib_qp_cap *cap, | |||
1112 | struct mthca_qp *qp) | 1112 | struct mthca_qp *qp) |
1113 | { | 1113 | { |
1114 | /* Sanity check QP size before proceeding */ | 1114 | /* Sanity check QP size before proceeding */ |
1115 | if (cap->max_send_wr > 65536 || cap->max_recv_wr > 65536 || | 1115 | if (cap->max_send_wr > dev->limits.max_wqes || |
1116 | cap->max_send_sge > 64 || cap->max_recv_sge > 64) | 1116 | cap->max_recv_wr > dev->limits.max_wqes || |
1117 | cap->max_send_sge > dev->limits.max_sg || | ||
1118 | cap->max_recv_sge > dev->limits.max_sg) | ||
1117 | return -EINVAL; | 1119 | return -EINVAL; |
1118 | 1120 | ||
1119 | if (mthca_is_memfree(dev)) { | 1121 | if (mthca_is_memfree(dev)) { |
diff --git a/drivers/infiniband/hw/mthca/mthca_srq.c b/drivers/infiniband/hw/mthca/mthca_srq.c index e464321a7aa7..64f70aa1b3c0 100644 --- a/drivers/infiniband/hw/mthca/mthca_srq.c +++ b/drivers/infiniband/hw/mthca/mthca_srq.c | |||
@@ -186,7 +186,8 @@ int mthca_alloc_srq(struct mthca_dev *dev, struct mthca_pd *pd, | |||
186 | int err; | 186 | int err; |
187 | 187 | ||
188 | /* Sanity check SRQ size before proceeding */ | 188 | /* Sanity check SRQ size before proceeding */ |
189 | if (attr->max_wr > 16 << 20 || attr->max_sge > 64) | 189 | if (attr->max_wr > dev->limits.max_srq_wqes || |
190 | attr->max_sge > dev->limits.max_sg) | ||
190 | return -EINVAL; | 191 | return -EINVAL; |
191 | 192 | ||
192 | srq->max = attr->max_wr; | 193 | srq->max = attr->max_wr; |