Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

Jack Morgenstein and committed by
Roland Dreier
5ceb7455 0d3b525f

+35 -19
+35 -19
drivers/infiniband/hw/mthca/mthca_mcg.c
··· 111 111 goto out; 112 112 if (status) { 113 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 118 if (!memcmp(mgm->gid, zero_gid, 16)) { ··· 127 126 goto out; 128 127 129 128 *prev = *index; 130 - *index = be32_to_cpu(mgm->next_gid_index) >> 5; 129 + *index = be32_to_cpu(mgm->next_gid_index) >> 6; 131 130 } while (*index); 132 131 133 132 *index = -1; ··· 154 153 return PTR_ERR(mailbox); 155 154 mgm = mailbox->buf; 156 155 157 - if (down_interruptible(&dev->mcg_table.sem)) 158 - return -EINTR; 156 + if (down_interruptible(&dev->mcg_table.sem)) { 157 + err = -EINTR; 158 + goto err_sem; 159 + } 159 160 160 161 err = find_mgm(dev, gid->raw, mailbox, &hash, &prev, &index); 161 162 if (err) ··· 184 181 err = -EINVAL; 185 182 goto out; 186 183 } 187 - 184 + memset(mgm, 0, sizeof *mgm); 188 185 memcpy(mgm->gid, gid->raw, 16); 189 - mgm->next_gid_index = 0; 190 186 } 191 187 192 188 for (i = 0; i < MTHCA_QP_PER_MGM; ++i) ··· 211 209 if (status) { 212 210 mthca_err(dev, "WRITE_MGM returned status %02x\n", status); 213 211 err = -EINVAL; 212 + goto out; 214 213 } 215 214 216 215 if (!link) ··· 226 223 goto out; 227 224 } 228 225 229 - mgm->next_gid_index = cpu_to_be32(index << 5); 226 + mgm->next_gid_index = cpu_to_be32(index << 6); 230 227 231 228 err = mthca_WRITE_MGM(dev, prev, mailbox, &status); 232 229 if (err) ··· 237 234 } 238 235 239 236 out: 237 + if (err && link && index != -1) { 238 + BUG_ON(index < dev->limits.num_mgms); 239 + mthca_free(&dev->mcg_table.alloc, index); 240 + } 240 241 up(&dev->mcg_table.sem); 242 + err_sem: 241 243 mthca_free_mailbox(dev, mailbox); 242 244 return err; 243 245 } ··· 263 255 return PTR_ERR(mailbox); 264 256 mgm = mailbox->buf; 265 257 266 - if (down_interruptible(&dev->mcg_table.sem)) 267 - return -EINTR; 258 + if (down_interruptible(&dev->mcg_table.sem)) { 259 + err = -EINTR; 260 + goto err_sem; 261 + } 268 262 269 263 err = find_mgm(dev, gid->raw, mailbox, &hash, &prev, &index); 270 264 if (err) ··· 315 305 if (i != 1) 316 306 goto out; 317 307 318 - goto out; 319 - 320 308 if (prev == -1) { 321 309 /* Remove entry from MGM */ 322 - if (be32_to_cpu(mgm->next_gid_index) >> 5) { 323 - err = mthca_READ_MGM(dev, 324 - be32_to_cpu(mgm->next_gid_index) >> 5, 310 + int amgm_index_to_free = be32_to_cpu(mgm->next_gid_index) >> 6; 311 + if (amgm_index_to_free) { 312 + err = mthca_READ_MGM(dev, amgm_index_to_free, 325 313 mailbox, &status); 326 314 if (err) 327 315 goto out; ··· 340 332 err = -EINVAL; 341 333 goto out; 342 334 } 335 + if (amgm_index_to_free) { 336 + BUG_ON(amgm_index_to_free < dev->limits.num_mgms); 337 + mthca_free(&dev->mcg_table.alloc, amgm_index_to_free); 338 + } 343 339 } else { 344 340 /* Remove entry from AMGM */ 345 - index = be32_to_cpu(mgm->next_gid_index) >> 5; 341 + int curr_next_index = be32_to_cpu(mgm->next_gid_index) >> 6; 346 342 err = mthca_READ_MGM(dev, prev, mailbox, &status); 347 343 if (err) 348 344 goto out; ··· 356 344 goto out; 357 345 } 358 346 359 - mgm->next_gid_index = cpu_to_be32(index << 5); 347 + mgm->next_gid_index = cpu_to_be32(curr_next_index << 6); 360 348 361 349 err = mthca_WRITE_MGM(dev, prev, mailbox, &status); 362 350 if (err) ··· 366 354 err = -EINVAL; 367 355 goto out; 368 356 } 357 + BUG_ON(index < dev->limits.num_mgms); 358 + mthca_free(&dev->mcg_table.alloc, index); 369 359 } 370 360 371 361 out: 372 362 up(&dev->mcg_table.sem); 363 + err_sem: 373 364 mthca_free_mailbox(dev, mailbox); 374 365 return err; 375 366 } ··· 380 365 int __devinit mthca_init_mcg_table(struct mthca_dev *dev) 381 366 { 382 367 int err; 368 + int table_size = dev->limits.num_mgms + dev->limits.num_amgms; 383 369 384 370 err = mthca_alloc_init(&dev->mcg_table.alloc, 385 - dev->limits.num_amgms, 386 - dev->limits.num_amgms - 1, 387 - 0); 371 + table_size, 372 + table_size - 1, 373 + dev->limits.num_mgms); 388 374 if (err) 389 375 return err; 390 376