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 | |
| 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>
| -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 | ||
