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