diff options
author | Jack Morgenstein <jackm@mellanox.co.il> | 2006-01-06 16:11:07 -0500 |
---|---|---|
committer | Roland Dreier <rolandd@cisco.com> | 2006-01-06 16:11:07 -0500 |
commit | 5ceb74557c71465cf8f6fda050aac00e53f9ad3d (patch) | |
tree | 8cd77012ee081d45926731306339977da61a4926 /drivers/infiniband/hw | |
parent | 0d3b525fff40475e58dab9176740d2efc5f37838 (diff) |
IB/mthca: multiple fixes for multicast group handling
Multicast group management fixes:
. Fix leak of mailbox memory in error handling on multicast group operations.
. Free AMGM indices at detach and in attach error handling.
. Fix amount to shift for aligning next_gid_index in mailbox: it
starts at bit 6, not bit 5.
. Allocate AMGM index after end of MGM table, in the range num_mgms to
multicast table size - 1. Add some BUG_ON checks to catch cases
where the index falls in the MGM hash area.
. Initialize the list of QPs in a newly-allocated group from AMGM to 0
This is necessary since when a group is moved from AMGM to MGM (in the
case where the MGM entry has been emptied of QPs), the AMGM entry is
not reset to 0 (and we don't want an extra command to do that).
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_mcg.c | 54 |
1 files changed, 35 insertions, 19 deletions
diff --git a/drivers/infiniband/hw/mthca/mthca_mcg.c b/drivers/infiniband/hw/mthca/mthca_mcg.c index 2fc449da418d..77bc6c746f43 100644 --- a/drivers/infiniband/hw/mthca/mthca_mcg.c +++ b/drivers/infiniband/hw/mthca/mthca_mcg.c | |||
@@ -111,7 +111,8 @@ static int find_mgm(struct mthca_dev *dev, | |||
111 | goto out; | 111 | goto out; |
112 | if (status) { | 112 | if (status) { |
113 | mthca_err(dev, "READ_MGM returned status %02x\n", status); | 113 | mthca_err(dev, "READ_MGM returned status %02x\n", status); |
114 | return -EINVAL; | 114 | err = -EINVAL; |
115 | goto out; | ||
115 | } | 116 | } |
116 | 117 | ||
117 | if (!memcmp(mgm->gid, zero_gid, 16)) { | 118 | if (!memcmp(mgm->gid, zero_gid, 16)) { |
@@ -126,7 +127,7 @@ static int find_mgm(struct mthca_dev *dev, | |||
126 | goto out; | 127 | goto out; |
127 | 128 | ||
128 | *prev = *index; | 129 | *prev = *index; |
129 | *index = be32_to_cpu(mgm->next_gid_index) >> 5; | 130 | *index = be32_to_cpu(mgm->next_gid_index) >> 6; |
130 | } while (*index); | 131 | } while (*index); |
131 | 132 | ||
132 | *index = -1; | 133 | *index = -1; |
@@ -153,8 +154,10 @@ int mthca_multicast_attach(struct ib_qp *ibqp, union ib_gid *gid, u16 lid) | |||
153 | return PTR_ERR(mailbox); | 154 | return PTR_ERR(mailbox); |
154 | mgm = mailbox->buf; | 155 | mgm = mailbox->buf; |
155 | 156 | ||
156 | if (down_interruptible(&dev->mcg_table.sem)) | 157 | if (down_interruptible(&dev->mcg_table.sem)) { |
157 | return -EINTR; | 158 | err = -EINTR; |
159 | goto err_sem; | ||
160 | } | ||
158 | 161 | ||
159 | err = find_mgm(dev, gid->raw, mailbox, &hash, &prev, &index); | 162 | err = find_mgm(dev, gid->raw, mailbox, &hash, &prev, &index); |
160 | if (err) | 163 | if (err) |
@@ -181,9 +184,8 @@ int mthca_multicast_attach(struct ib_qp *ibqp, union ib_gid *gid, u16 lid) | |||
181 | err = -EINVAL; | 184 | err = -EINVAL; |
182 | goto out; | 185 | goto out; |
183 | } | 186 | } |
184 | 187 | memset(mgm, 0, sizeof *mgm); | |
185 | memcpy(mgm->gid, gid->raw, 16); | 188 | memcpy(mgm->gid, gid->raw, 16); |
186 | mgm->next_gid_index = 0; | ||
187 | } | 189 | } |
188 | 190 | ||
189 | for (i = 0; i < MTHCA_QP_PER_MGM; ++i) | 191 | for (i = 0; i < MTHCA_QP_PER_MGM; ++i) |
@@ -209,6 +211,7 @@ int mthca_multicast_attach(struct ib_qp *ibqp, union ib_gid *gid, u16 lid) | |||
209 | if (status) { | 211 | if (status) { |
210 | mthca_err(dev, "WRITE_MGM returned status %02x\n", status); | 212 | mthca_err(dev, "WRITE_MGM returned status %02x\n", status); |
211 | err = -EINVAL; | 213 | err = -EINVAL; |
214 | goto out; | ||
212 | } | 215 | } |
213 | 216 | ||
214 | if (!link) | 217 | if (!link) |
@@ -223,7 +226,7 @@ int mthca_multicast_attach(struct ib_qp *ibqp, union ib_gid *gid, u16 lid) | |||
223 | goto out; | 226 | goto out; |
224 | } | 227 | } |
225 | 228 | ||
226 | mgm->next_gid_index = cpu_to_be32(index << 5); | 229 | mgm->next_gid_index = cpu_to_be32(index << 6); |
227 | 230 | ||
228 | err = mthca_WRITE_MGM(dev, prev, mailbox, &status); | 231 | err = mthca_WRITE_MGM(dev, prev, mailbox, &status); |
229 | if (err) | 232 | if (err) |
@@ -234,7 +237,12 @@ int mthca_multicast_attach(struct ib_qp *ibqp, union ib_gid *gid, u16 lid) | |||
234 | } | 237 | } |
235 | 238 | ||
236 | out: | 239 | out: |
240 | if (err && link && index != -1) { | ||
241 | BUG_ON(index < dev->limits.num_mgms); | ||
242 | mthca_free(&dev->mcg_table.alloc, index); | ||
243 | } | ||
237 | up(&dev->mcg_table.sem); | 244 | up(&dev->mcg_table.sem); |
245 | err_sem: | ||
238 | mthca_free_mailbox(dev, mailbox); | 246 | mthca_free_mailbox(dev, mailbox); |
239 | return err; | 247 | return err; |
240 | } | 248 | } |
@@ -255,8 +263,10 @@ int mthca_multicast_detach(struct ib_qp *ibqp, union ib_gid *gid, u16 lid) | |||
255 | return PTR_ERR(mailbox); | 263 | return PTR_ERR(mailbox); |
256 | mgm = mailbox->buf; | 264 | mgm = mailbox->buf; |
257 | 265 | ||
258 | if (down_interruptible(&dev->mcg_table.sem)) | 266 | if (down_interruptible(&dev->mcg_table.sem)) { |
259 | return -EINTR; | 267 | err = -EINTR; |
268 | goto err_sem; | ||
269 | } | ||
260 | 270 | ||
261 | err = find_mgm(dev, gid->raw, mailbox, &hash, &prev, &index); | 271 | err = find_mgm(dev, gid->raw, mailbox, &hash, &prev, &index); |
262 | if (err) | 272 | if (err) |
@@ -305,13 +315,11 @@ int mthca_multicast_detach(struct ib_qp *ibqp, union ib_gid *gid, u16 lid) | |||
305 | if (i != 1) | 315 | if (i != 1) |
306 | goto out; | 316 | goto out; |
307 | 317 | ||
308 | goto out; | ||
309 | |||
310 | if (prev == -1) { | 318 | if (prev == -1) { |
311 | /* Remove entry from MGM */ | 319 | /* Remove entry from MGM */ |
312 | if (be32_to_cpu(mgm->next_gid_index) >> 5) { | 320 | int amgm_index_to_free = be32_to_cpu(mgm->next_gid_index) >> 6; |
313 | err = mthca_READ_MGM(dev, | 321 | if (amgm_index_to_free) { |
314 | be32_to_cpu(mgm->next_gid_index) >> 5, | 322 | err = mthca_READ_MGM(dev, amgm_index_to_free, |
315 | mailbox, &status); | 323 | mailbox, &status); |
316 | if (err) | 324 | if (err) |
317 | goto out; | 325 | goto out; |
@@ -332,9 +340,13 @@ int mthca_multicast_detach(struct ib_qp *ibqp, union ib_gid *gid, u16 lid) | |||
332 | err = -EINVAL; | 340 | err = -EINVAL; |
333 | goto out; | 341 | goto out; |
334 | } | 342 | } |
343 | if (amgm_index_to_free) { | ||
344 | BUG_ON(amgm_index_to_free < dev->limits.num_mgms); | ||
345 | mthca_free(&dev->mcg_table.alloc, amgm_index_to_free); | ||
346 | } | ||
335 | } else { | 347 | } else { |
336 | /* Remove entry from AMGM */ | 348 | /* Remove entry from AMGM */ |
337 | index = be32_to_cpu(mgm->next_gid_index) >> 5; | 349 | int curr_next_index = be32_to_cpu(mgm->next_gid_index) >> 6; |
338 | err = mthca_READ_MGM(dev, prev, mailbox, &status); | 350 | err = mthca_READ_MGM(dev, prev, mailbox, &status); |
339 | if (err) | 351 | if (err) |
340 | goto out; | 352 | goto out; |
@@ -344,7 +356,7 @@ int mthca_multicast_detach(struct ib_qp *ibqp, union ib_gid *gid, u16 lid) | |||
344 | goto out; | 356 | goto out; |
345 | } | 357 | } |
346 | 358 | ||
347 | mgm->next_gid_index = cpu_to_be32(index << 5); | 359 | mgm->next_gid_index = cpu_to_be32(curr_next_index << 6); |
348 | 360 | ||
349 | err = mthca_WRITE_MGM(dev, prev, mailbox, &status); | 361 | err = mthca_WRITE_MGM(dev, prev, mailbox, &status); |
350 | if (err) | 362 | if (err) |
@@ -354,10 +366,13 @@ int mthca_multicast_detach(struct ib_qp *ibqp, union ib_gid *gid, u16 lid) | |||
354 | err = -EINVAL; | 366 | err = -EINVAL; |
355 | goto out; | 367 | goto out; |
356 | } | 368 | } |
369 | BUG_ON(index < dev->limits.num_mgms); | ||
370 | mthca_free(&dev->mcg_table.alloc, index); | ||
357 | } | 371 | } |
358 | 372 | ||
359 | out: | 373 | out: |
360 | up(&dev->mcg_table.sem); | 374 | up(&dev->mcg_table.sem); |
375 | err_sem: | ||
361 | mthca_free_mailbox(dev, mailbox); | 376 | mthca_free_mailbox(dev, mailbox); |
362 | return err; | 377 | return err; |
363 | } | 378 | } |
@@ -365,11 +380,12 @@ int mthca_multicast_detach(struct ib_qp *ibqp, union ib_gid *gid, u16 lid) | |||
365 | int __devinit mthca_init_mcg_table(struct mthca_dev *dev) | 380 | int __devinit mthca_init_mcg_table(struct mthca_dev *dev) |
366 | { | 381 | { |
367 | int err; | 382 | int err; |
383 | int table_size = dev->limits.num_mgms + dev->limits.num_amgms; | ||
368 | 384 | ||
369 | err = mthca_alloc_init(&dev->mcg_table.alloc, | 385 | err = mthca_alloc_init(&dev->mcg_table.alloc, |
370 | dev->limits.num_amgms, | 386 | table_size, |
371 | dev->limits.num_amgms - 1, | 387 | table_size - 1, |
372 | 0); | 388 | dev->limits.num_mgms); |
373 | if (err) | 389 | if (err) |
374 | return err; | 390 | return err; |
375 | 391 | ||