11da177e4SLinus Torvalds /* 21da177e4SLinus Torvalds * Copyright (c) 2004 Topspin Communications. All rights reserved. 31da177e4SLinus Torvalds * 41da177e4SLinus Torvalds * This software is available to you under a choice of one of two 51da177e4SLinus Torvalds * licenses. You may choose to be licensed under the terms of the GNU 61da177e4SLinus Torvalds * General Public License (GPL) Version 2, available from the file 71da177e4SLinus Torvalds * COPYING in the main directory of this source tree, or the 81da177e4SLinus Torvalds * OpenIB.org BSD license below: 91da177e4SLinus Torvalds * 101da177e4SLinus Torvalds * Redistribution and use in source and binary forms, with or 111da177e4SLinus Torvalds * without modification, are permitted provided that the following 121da177e4SLinus Torvalds * conditions are met: 131da177e4SLinus Torvalds * 141da177e4SLinus Torvalds * - Redistributions of source code must retain the above 151da177e4SLinus Torvalds * copyright notice, this list of conditions and the following 161da177e4SLinus Torvalds * disclaimer. 171da177e4SLinus Torvalds * 181da177e4SLinus Torvalds * - Redistributions in binary form must reproduce the above 191da177e4SLinus Torvalds * copyright notice, this list of conditions and the following 201da177e4SLinus Torvalds * disclaimer in the documentation and/or other materials 211da177e4SLinus Torvalds * provided with the distribution. 221da177e4SLinus Torvalds * 231da177e4SLinus Torvalds * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 241da177e4SLinus Torvalds * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 251da177e4SLinus Torvalds * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 261da177e4SLinus Torvalds * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 271da177e4SLinus Torvalds * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 281da177e4SLinus Torvalds * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 291da177e4SLinus Torvalds * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 301da177e4SLinus Torvalds * SOFTWARE. 311da177e4SLinus Torvalds * 321da177e4SLinus Torvalds * $Id: mthca_mcg.c 1349 2004-12-16 21:09:43Z roland $ 331da177e4SLinus Torvalds */ 341da177e4SLinus Torvalds 354e57b681STim Schmielau #include <linux/string.h> 364e57b681STim Schmielau #include <linux/slab.h> 371da177e4SLinus Torvalds 381da177e4SLinus Torvalds #include "mthca_dev.h" 391da177e4SLinus Torvalds #include "mthca_cmd.h" 401da177e4SLinus Torvalds 411da177e4SLinus Torvalds struct mthca_mgm { 4297f52eb4SSean Hefty __be32 next_gid_index; 431da177e4SLinus Torvalds u32 reserved[3]; 441da177e4SLinus Torvalds u8 gid[16]; 4597f52eb4SSean Hefty __be32 qp[MTHCA_QP_PER_MGM]; 461da177e4SLinus Torvalds }; 471da177e4SLinus Torvalds 481da177e4SLinus Torvalds static const u8 zero_gid[16]; /* automatically initialized to 0 */ 491da177e4SLinus Torvalds 501da177e4SLinus Torvalds /* 511da177e4SLinus Torvalds * Caller must hold MCG table semaphore. gid and mgm parameters must 521da177e4SLinus Torvalds * be properly aligned for command interface. 531da177e4SLinus Torvalds * 541da177e4SLinus Torvalds * Returns 0 unless a firmware command error occurs. 551da177e4SLinus Torvalds * 561da177e4SLinus Torvalds * If GID is found in MGM or MGM is empty, *index = *hash, *prev = -1 571da177e4SLinus Torvalds * and *mgm holds MGM entry. 581da177e4SLinus Torvalds * 591da177e4SLinus Torvalds * if GID is found in AMGM, *index = index in AMGM, *prev = index of 601da177e4SLinus Torvalds * previous entry in hash chain and *mgm holds AMGM entry. 611da177e4SLinus Torvalds * 621da177e4SLinus Torvalds * If no AMGM exists for given gid, *index = -1, *prev = index of last 631da177e4SLinus Torvalds * entry in hash chain and *mgm holds end of hash chain. 641da177e4SLinus Torvalds */ 651da177e4SLinus Torvalds static int find_mgm(struct mthca_dev *dev, 66ed878458SRoland Dreier u8 *gid, struct mthca_mailbox *mgm_mailbox, 671da177e4SLinus Torvalds u16 *hash, int *prev, int *index) 681da177e4SLinus Torvalds { 69ed878458SRoland Dreier struct mthca_mailbox *mailbox; 70ed878458SRoland Dreier struct mthca_mgm *mgm = mgm_mailbox->buf; 711da177e4SLinus Torvalds u8 *mgid; 721da177e4SLinus Torvalds int err; 731da177e4SLinus Torvalds u8 status; 741da177e4SLinus Torvalds 75ed878458SRoland Dreier mailbox = mthca_alloc_mailbox(dev, GFP_KERNEL); 76ed878458SRoland Dreier if (IS_ERR(mailbox)) 771da177e4SLinus Torvalds return -ENOMEM; 78ed878458SRoland Dreier mgid = mailbox->buf; 791da177e4SLinus Torvalds 801da177e4SLinus Torvalds memcpy(mgid, gid, 16); 811da177e4SLinus Torvalds 82ed878458SRoland Dreier err = mthca_MGID_HASH(dev, mailbox, hash, &status); 831da177e4SLinus Torvalds if (err) 841da177e4SLinus Torvalds goto out; 851da177e4SLinus Torvalds if (status) { 861da177e4SLinus Torvalds mthca_err(dev, "MGID_HASH returned status %02x\n", status); 871da177e4SLinus Torvalds err = -EINVAL; 881da177e4SLinus Torvalds goto out; 891da177e4SLinus Torvalds } 901da177e4SLinus Torvalds 911da177e4SLinus Torvalds if (0) 921da177e4SLinus Torvalds mthca_dbg(dev, "Hash for %04x:%04x:%04x:%04x:" 931da177e4SLinus Torvalds "%04x:%04x:%04x:%04x is %04x\n", 9497f52eb4SSean Hefty be16_to_cpu(((__be16 *) gid)[0]), 9597f52eb4SSean Hefty be16_to_cpu(((__be16 *) gid)[1]), 9697f52eb4SSean Hefty be16_to_cpu(((__be16 *) gid)[2]), 9797f52eb4SSean Hefty be16_to_cpu(((__be16 *) gid)[3]), 9897f52eb4SSean Hefty be16_to_cpu(((__be16 *) gid)[4]), 9997f52eb4SSean Hefty be16_to_cpu(((__be16 *) gid)[5]), 10097f52eb4SSean Hefty be16_to_cpu(((__be16 *) gid)[6]), 10197f52eb4SSean Hefty be16_to_cpu(((__be16 *) gid)[7]), 1021da177e4SLinus Torvalds *hash); 1031da177e4SLinus Torvalds 1041da177e4SLinus Torvalds *index = *hash; 1051da177e4SLinus Torvalds *prev = -1; 1061da177e4SLinus Torvalds 1071da177e4SLinus Torvalds do { 108ed878458SRoland Dreier err = mthca_READ_MGM(dev, *index, mgm_mailbox, &status); 1091da177e4SLinus Torvalds if (err) 1101da177e4SLinus Torvalds goto out; 1111da177e4SLinus Torvalds if (status) { 1121da177e4SLinus Torvalds mthca_err(dev, "READ_MGM returned status %02x\n", status); 1135ceb7455SJack Morgenstein err = -EINVAL; 1145ceb7455SJack Morgenstein goto out; 1151da177e4SLinus Torvalds } 1161da177e4SLinus Torvalds 1171da177e4SLinus Torvalds if (!memcmp(mgm->gid, zero_gid, 16)) { 1181da177e4SLinus Torvalds if (*index != *hash) { 1191da177e4SLinus Torvalds mthca_err(dev, "Found zero MGID in AMGM.\n"); 1201da177e4SLinus Torvalds err = -EINVAL; 1211da177e4SLinus Torvalds } 1221da177e4SLinus Torvalds goto out; 1231da177e4SLinus Torvalds } 1241da177e4SLinus Torvalds 1251da177e4SLinus Torvalds if (!memcmp(mgm->gid, gid, 16)) 1261da177e4SLinus Torvalds goto out; 1271da177e4SLinus Torvalds 1281da177e4SLinus Torvalds *prev = *index; 1295ceb7455SJack Morgenstein *index = be32_to_cpu(mgm->next_gid_index) >> 6; 1301da177e4SLinus Torvalds } while (*index); 1311da177e4SLinus Torvalds 1321da177e4SLinus Torvalds *index = -1; 1331da177e4SLinus Torvalds 1341da177e4SLinus Torvalds out: 135ed878458SRoland Dreier mthca_free_mailbox(dev, mailbox); 1361da177e4SLinus Torvalds return err; 1371da177e4SLinus Torvalds } 1381da177e4SLinus Torvalds 1391da177e4SLinus Torvalds int mthca_multicast_attach(struct ib_qp *ibqp, union ib_gid *gid, u16 lid) 1401da177e4SLinus Torvalds { 1411da177e4SLinus Torvalds struct mthca_dev *dev = to_mdev(ibqp->device); 142ed878458SRoland Dreier struct mthca_mailbox *mailbox; 1431da177e4SLinus Torvalds struct mthca_mgm *mgm; 1441da177e4SLinus Torvalds u16 hash; 1451da177e4SLinus Torvalds int index, prev; 1461da177e4SLinus Torvalds int link = 0; 1471da177e4SLinus Torvalds int i; 1481da177e4SLinus Torvalds int err; 1491da177e4SLinus Torvalds u8 status; 1501da177e4SLinus Torvalds 151ed878458SRoland Dreier mailbox = mthca_alloc_mailbox(dev, GFP_KERNEL); 152ed878458SRoland Dreier if (IS_ERR(mailbox)) 153ed878458SRoland Dreier return PTR_ERR(mailbox); 154ed878458SRoland Dreier mgm = mailbox->buf; 1551da177e4SLinus Torvalds 156fd9cfdd1SRoland Dreier mutex_lock(&dev->mcg_table.mutex); 1571da177e4SLinus Torvalds 158ed878458SRoland Dreier err = find_mgm(dev, gid->raw, mailbox, &hash, &prev, &index); 1591da177e4SLinus Torvalds if (err) 1601da177e4SLinus Torvalds goto out; 1611da177e4SLinus Torvalds 1621da177e4SLinus Torvalds if (index != -1) { 1631da177e4SLinus Torvalds if (!memcmp(mgm->gid, zero_gid, 16)) 1641da177e4SLinus Torvalds memcpy(mgm->gid, gid->raw, 16); 1651da177e4SLinus Torvalds } else { 1661da177e4SLinus Torvalds link = 1; 1671da177e4SLinus Torvalds 1681da177e4SLinus Torvalds index = mthca_alloc(&dev->mcg_table.alloc); 1691da177e4SLinus Torvalds if (index == -1) { 1701da177e4SLinus Torvalds mthca_err(dev, "No AMGM entries left\n"); 1711da177e4SLinus Torvalds err = -ENOMEM; 1721da177e4SLinus Torvalds goto out; 1731da177e4SLinus Torvalds } 1741da177e4SLinus Torvalds 175ed878458SRoland Dreier err = mthca_READ_MGM(dev, index, mailbox, &status); 1761da177e4SLinus Torvalds if (err) 1771da177e4SLinus Torvalds goto out; 1781da177e4SLinus Torvalds if (status) { 1791da177e4SLinus Torvalds mthca_err(dev, "READ_MGM returned status %02x\n", status); 1801da177e4SLinus Torvalds err = -EINVAL; 1811da177e4SLinus Torvalds goto out; 1821da177e4SLinus Torvalds } 1835ceb7455SJack Morgenstein memset(mgm, 0, sizeof *mgm); 1841da177e4SLinus Torvalds memcpy(mgm->gid, gid->raw, 16); 1851da177e4SLinus Torvalds } 1861da177e4SLinus Torvalds 1871da177e4SLinus Torvalds for (i = 0; i < MTHCA_QP_PER_MGM; ++i) 1887150bf8aSJack Morgenstein if (mgm->qp[i] == cpu_to_be32(ibqp->qp_num | (1 << 31))) { 1897150bf8aSJack Morgenstein mthca_dbg(dev, "QP %06x already a member of MGM\n", 1907150bf8aSJack Morgenstein ibqp->qp_num); 1917150bf8aSJack Morgenstein err = 0; 1927150bf8aSJack Morgenstein goto out; 1937150bf8aSJack Morgenstein } else if (!(mgm->qp[i] & cpu_to_be32(1 << 31))) { 1941da177e4SLinus Torvalds mgm->qp[i] = cpu_to_be32(ibqp->qp_num | (1 << 31)); 1951da177e4SLinus Torvalds break; 1961da177e4SLinus Torvalds } 1971da177e4SLinus Torvalds 1981da177e4SLinus Torvalds if (i == MTHCA_QP_PER_MGM) { 1991da177e4SLinus Torvalds mthca_err(dev, "MGM at index %x is full.\n", index); 2001da177e4SLinus Torvalds err = -ENOMEM; 2011da177e4SLinus Torvalds goto out; 2021da177e4SLinus Torvalds } 2031da177e4SLinus Torvalds 204ed878458SRoland Dreier err = mthca_WRITE_MGM(dev, index, mailbox, &status); 2051da177e4SLinus Torvalds if (err) 2061da177e4SLinus Torvalds goto out; 2071da177e4SLinus Torvalds if (status) { 2081da177e4SLinus Torvalds mthca_err(dev, "WRITE_MGM returned status %02x\n", status); 2091da177e4SLinus Torvalds err = -EINVAL; 2105ceb7455SJack Morgenstein goto out; 2111da177e4SLinus Torvalds } 2121da177e4SLinus Torvalds 2131da177e4SLinus Torvalds if (!link) 2141da177e4SLinus Torvalds goto out; 2151da177e4SLinus Torvalds 216ed878458SRoland Dreier err = mthca_READ_MGM(dev, prev, mailbox, &status); 2171da177e4SLinus Torvalds if (err) 2181da177e4SLinus Torvalds goto out; 2191da177e4SLinus Torvalds if (status) { 2201da177e4SLinus Torvalds mthca_err(dev, "READ_MGM returned status %02x\n", status); 2211da177e4SLinus Torvalds err = -EINVAL; 2221da177e4SLinus Torvalds goto out; 2231da177e4SLinus Torvalds } 2241da177e4SLinus Torvalds 2255ceb7455SJack Morgenstein mgm->next_gid_index = cpu_to_be32(index << 6); 2261da177e4SLinus Torvalds 227ed878458SRoland Dreier err = mthca_WRITE_MGM(dev, prev, mailbox, &status); 2281da177e4SLinus Torvalds if (err) 2291da177e4SLinus Torvalds goto out; 2301da177e4SLinus Torvalds if (status) { 2311da177e4SLinus Torvalds mthca_err(dev, "WRITE_MGM returned status %02x\n", status); 2321da177e4SLinus Torvalds err = -EINVAL; 2331da177e4SLinus Torvalds } 2341da177e4SLinus Torvalds 2351da177e4SLinus Torvalds out: 2365ceb7455SJack Morgenstein if (err && link && index != -1) { 2375ceb7455SJack Morgenstein BUG_ON(index < dev->limits.num_mgms); 2385ceb7455SJack Morgenstein mthca_free(&dev->mcg_table.alloc, index); 2395ceb7455SJack Morgenstein } 240fd9cfdd1SRoland Dreier mutex_unlock(&dev->mcg_table.mutex); 241e3aa31c5SMichael S. Tsirkin 242ed878458SRoland Dreier mthca_free_mailbox(dev, mailbox); 2431da177e4SLinus Torvalds return err; 2441da177e4SLinus Torvalds } 2451da177e4SLinus Torvalds 2461da177e4SLinus Torvalds int mthca_multicast_detach(struct ib_qp *ibqp, union ib_gid *gid, u16 lid) 2471da177e4SLinus Torvalds { 2481da177e4SLinus Torvalds struct mthca_dev *dev = to_mdev(ibqp->device); 249ed878458SRoland Dreier struct mthca_mailbox *mailbox; 2501da177e4SLinus Torvalds struct mthca_mgm *mgm; 2511da177e4SLinus Torvalds u16 hash; 2521da177e4SLinus Torvalds int prev, index; 2531da177e4SLinus Torvalds int i, loc; 2541da177e4SLinus Torvalds int err; 2551da177e4SLinus Torvalds u8 status; 2561da177e4SLinus Torvalds 257ed878458SRoland Dreier mailbox = mthca_alloc_mailbox(dev, GFP_KERNEL); 258ed878458SRoland Dreier if (IS_ERR(mailbox)) 259ed878458SRoland Dreier return PTR_ERR(mailbox); 260ed878458SRoland Dreier mgm = mailbox->buf; 2611da177e4SLinus Torvalds 262fd9cfdd1SRoland Dreier mutex_lock(&dev->mcg_table.mutex); 2631da177e4SLinus Torvalds 264ed878458SRoland Dreier err = find_mgm(dev, gid->raw, mailbox, &hash, &prev, &index); 2651da177e4SLinus Torvalds if (err) 2661da177e4SLinus Torvalds goto out; 2671da177e4SLinus Torvalds 2681da177e4SLinus Torvalds if (index == -1) { 2691da177e4SLinus Torvalds mthca_err(dev, "MGID %04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x " 2701da177e4SLinus Torvalds "not found\n", 27197f52eb4SSean Hefty be16_to_cpu(((__be16 *) gid->raw)[0]), 27297f52eb4SSean Hefty be16_to_cpu(((__be16 *) gid->raw)[1]), 27397f52eb4SSean Hefty be16_to_cpu(((__be16 *) gid->raw)[2]), 27497f52eb4SSean Hefty be16_to_cpu(((__be16 *) gid->raw)[3]), 27597f52eb4SSean Hefty be16_to_cpu(((__be16 *) gid->raw)[4]), 27697f52eb4SSean Hefty be16_to_cpu(((__be16 *) gid->raw)[5]), 27797f52eb4SSean Hefty be16_to_cpu(((__be16 *) gid->raw)[6]), 27897f52eb4SSean Hefty be16_to_cpu(((__be16 *) gid->raw)[7])); 2791da177e4SLinus Torvalds err = -EINVAL; 2801da177e4SLinus Torvalds goto out; 2811da177e4SLinus Torvalds } 2821da177e4SLinus Torvalds 2831da177e4SLinus Torvalds for (loc = -1, i = 0; i < MTHCA_QP_PER_MGM; ++i) { 2841da177e4SLinus Torvalds if (mgm->qp[i] == cpu_to_be32(ibqp->qp_num | (1 << 31))) 2851da177e4SLinus Torvalds loc = i; 2861da177e4SLinus Torvalds if (!(mgm->qp[i] & cpu_to_be32(1 << 31))) 2871da177e4SLinus Torvalds break; 2881da177e4SLinus Torvalds } 2891da177e4SLinus Torvalds 2901da177e4SLinus Torvalds if (loc == -1) { 2911da177e4SLinus Torvalds mthca_err(dev, "QP %06x not found in MGM\n", ibqp->qp_num); 2921da177e4SLinus Torvalds err = -EINVAL; 2931da177e4SLinus Torvalds goto out; 2941da177e4SLinus Torvalds } 2951da177e4SLinus Torvalds 2961da177e4SLinus Torvalds mgm->qp[loc] = mgm->qp[i - 1]; 2971da177e4SLinus Torvalds mgm->qp[i - 1] = 0; 2981da177e4SLinus Torvalds 299ed878458SRoland Dreier err = mthca_WRITE_MGM(dev, index, mailbox, &status); 3001da177e4SLinus Torvalds if (err) 3011da177e4SLinus Torvalds goto out; 3021da177e4SLinus Torvalds if (status) { 3031da177e4SLinus Torvalds mthca_err(dev, "WRITE_MGM returned status %02x\n", status); 3041da177e4SLinus Torvalds err = -EINVAL; 3051da177e4SLinus Torvalds goto out; 3061da177e4SLinus Torvalds } 3071da177e4SLinus Torvalds 3081da177e4SLinus Torvalds if (i != 1) 3091da177e4SLinus Torvalds goto out; 3101da177e4SLinus Torvalds 3111da177e4SLinus Torvalds if (prev == -1) { 3121da177e4SLinus Torvalds /* Remove entry from MGM */ 3135ceb7455SJack Morgenstein int amgm_index_to_free = be32_to_cpu(mgm->next_gid_index) >> 6; 3145ceb7455SJack Morgenstein if (amgm_index_to_free) { 3155ceb7455SJack Morgenstein err = mthca_READ_MGM(dev, amgm_index_to_free, 316ed878458SRoland Dreier mailbox, &status); 3171da177e4SLinus Torvalds if (err) 3181da177e4SLinus Torvalds goto out; 3191da177e4SLinus Torvalds if (status) { 3201da177e4SLinus Torvalds mthca_err(dev, "READ_MGM returned status %02x\n", 3211da177e4SLinus Torvalds status); 3221da177e4SLinus Torvalds err = -EINVAL; 3231da177e4SLinus Torvalds goto out; 3241da177e4SLinus Torvalds } 3251da177e4SLinus Torvalds } else 3261da177e4SLinus Torvalds memset(mgm->gid, 0, 16); 3271da177e4SLinus Torvalds 328ed878458SRoland Dreier err = mthca_WRITE_MGM(dev, index, mailbox, &status); 3291da177e4SLinus Torvalds if (err) 3301da177e4SLinus Torvalds goto out; 3311da177e4SLinus Torvalds if (status) { 3321da177e4SLinus Torvalds mthca_err(dev, "WRITE_MGM returned status %02x\n", status); 3331da177e4SLinus Torvalds err = -EINVAL; 3341da177e4SLinus Torvalds goto out; 3351da177e4SLinus Torvalds } 3365ceb7455SJack Morgenstein if (amgm_index_to_free) { 3375ceb7455SJack Morgenstein BUG_ON(amgm_index_to_free < dev->limits.num_mgms); 3385ceb7455SJack Morgenstein mthca_free(&dev->mcg_table.alloc, amgm_index_to_free); 3395ceb7455SJack Morgenstein } 3401da177e4SLinus Torvalds } else { 3411da177e4SLinus Torvalds /* Remove entry from AMGM */ 3425ceb7455SJack Morgenstein int curr_next_index = be32_to_cpu(mgm->next_gid_index) >> 6; 343ed878458SRoland Dreier err = mthca_READ_MGM(dev, prev, mailbox, &status); 3441da177e4SLinus Torvalds if (err) 3451da177e4SLinus Torvalds goto out; 3461da177e4SLinus Torvalds if (status) { 3471da177e4SLinus Torvalds mthca_err(dev, "READ_MGM returned status %02x\n", status); 3481da177e4SLinus Torvalds err = -EINVAL; 3491da177e4SLinus Torvalds goto out; 3501da177e4SLinus Torvalds } 3511da177e4SLinus Torvalds 3525ceb7455SJack Morgenstein mgm->next_gid_index = cpu_to_be32(curr_next_index << 6); 3531da177e4SLinus Torvalds 354ed878458SRoland Dreier err = mthca_WRITE_MGM(dev, prev, mailbox, &status); 3551da177e4SLinus Torvalds if (err) 3561da177e4SLinus Torvalds goto out; 3571da177e4SLinus Torvalds if (status) { 3581da177e4SLinus Torvalds mthca_err(dev, "WRITE_MGM returned status %02x\n", status); 3591da177e4SLinus Torvalds err = -EINVAL; 3601da177e4SLinus Torvalds goto out; 3611da177e4SLinus Torvalds } 3625ceb7455SJack Morgenstein BUG_ON(index < dev->limits.num_mgms); 3635ceb7455SJack Morgenstein mthca_free(&dev->mcg_table.alloc, index); 3641da177e4SLinus Torvalds } 3651da177e4SLinus Torvalds 3661da177e4SLinus Torvalds out: 367fd9cfdd1SRoland Dreier mutex_unlock(&dev->mcg_table.mutex); 368e3aa31c5SMichael S. Tsirkin 369ed878458SRoland Dreier mthca_free_mailbox(dev, mailbox); 3701da177e4SLinus Torvalds return err; 3711da177e4SLinus Torvalds } 3721da177e4SLinus Torvalds 373f4f3d0f0SRoland Dreier int mthca_init_mcg_table(struct mthca_dev *dev) 3741da177e4SLinus Torvalds { 3751da177e4SLinus Torvalds int err; 3765ceb7455SJack Morgenstein int table_size = dev->limits.num_mgms + dev->limits.num_amgms; 3771da177e4SLinus Torvalds 3781da177e4SLinus Torvalds err = mthca_alloc_init(&dev->mcg_table.alloc, 3795ceb7455SJack Morgenstein table_size, 3805ceb7455SJack Morgenstein table_size - 1, 3815ceb7455SJack Morgenstein dev->limits.num_mgms); 3821da177e4SLinus Torvalds if (err) 3831da177e4SLinus Torvalds return err; 3841da177e4SLinus Torvalds 385fd9cfdd1SRoland Dreier mutex_init(&dev->mcg_table.mutex); 3861da177e4SLinus Torvalds 3871da177e4SLinus Torvalds return 0; 3881da177e4SLinus Torvalds } 3891da177e4SLinus Torvalds 390e1f7868cSRoland Dreier void mthca_cleanup_mcg_table(struct mthca_dev *dev) 3911da177e4SLinus Torvalds { 3921da177e4SLinus Torvalds mthca_alloc_cleanup(&dev->mcg_table.alloc); 3931da177e4SLinus Torvalds } 394