aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/infiniband/hw
diff options
context:
space:
mode:
authorJack Morgenstein <jackm@mellanox.co.il>2006-01-06 16:11:07 -0500
committerRoland Dreier <rolandd@cisco.com>2006-01-06 16:11:07 -0500
commit5ceb74557c71465cf8f6fda050aac00e53f9ad3d (patch)
tree8cd77012ee081d45926731306339977da61a4926 /drivers/infiniband/hw
parent0d3b525fff40475e58dab9176740d2efc5f37838 (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.c54
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)
365int __devinit mthca_init_mcg_table(struct mthca_dev *dev) 380int __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