1*33ec1ccbSHans Petter Selasky /*
2*33ec1ccbSHans Petter Selasky * Copyright (c) 2004 Topspin Communications. All rights reserved.
3*33ec1ccbSHans Petter Selasky *
4*33ec1ccbSHans Petter Selasky * This software is available to you under a choice of one of two
5*33ec1ccbSHans Petter Selasky * licenses. You may choose to be licensed under the terms of the GNU
6*33ec1ccbSHans Petter Selasky * General Public License (GPL) Version 2, available from the file
7*33ec1ccbSHans Petter Selasky * COPYING in the main directory of this source tree, or the
8*33ec1ccbSHans Petter Selasky * OpenIB.org BSD license below:
9*33ec1ccbSHans Petter Selasky *
10*33ec1ccbSHans Petter Selasky * Redistribution and use in source and binary forms, with or
11*33ec1ccbSHans Petter Selasky * without modification, are permitted provided that the following
12*33ec1ccbSHans Petter Selasky * conditions are met:
13*33ec1ccbSHans Petter Selasky *
14*33ec1ccbSHans Petter Selasky * - Redistributions of source code must retain the above
15*33ec1ccbSHans Petter Selasky * copyright notice, this list of conditions and the following
16*33ec1ccbSHans Petter Selasky * disclaimer.
17*33ec1ccbSHans Petter Selasky *
18*33ec1ccbSHans Petter Selasky * - Redistributions in binary form must reproduce the above
19*33ec1ccbSHans Petter Selasky * copyright notice, this list of conditions and the following
20*33ec1ccbSHans Petter Selasky * disclaimer in the documentation and/or other materials
21*33ec1ccbSHans Petter Selasky * provided with the distribution.
22*33ec1ccbSHans Petter Selasky *
23*33ec1ccbSHans Petter Selasky * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
24*33ec1ccbSHans Petter Selasky * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
25*33ec1ccbSHans Petter Selasky * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
26*33ec1ccbSHans Petter Selasky * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
27*33ec1ccbSHans Petter Selasky * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
28*33ec1ccbSHans Petter Selasky * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
29*33ec1ccbSHans Petter Selasky * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
30*33ec1ccbSHans Petter Selasky * SOFTWARE.
31*33ec1ccbSHans Petter Selasky */
32*33ec1ccbSHans Petter Selasky
33*33ec1ccbSHans Petter Selasky #include <linux/string.h>
34*33ec1ccbSHans Petter Selasky #include <linux/gfp.h>
35*33ec1ccbSHans Petter Selasky
36*33ec1ccbSHans Petter Selasky #include "mthca_dev.h"
37*33ec1ccbSHans Petter Selasky #include "mthca_cmd.h"
38*33ec1ccbSHans Petter Selasky
39*33ec1ccbSHans Petter Selasky struct mthca_mgm {
40*33ec1ccbSHans Petter Selasky __be32 next_gid_index;
41*33ec1ccbSHans Petter Selasky u32 reserved[3];
42*33ec1ccbSHans Petter Selasky u8 gid[16];
43*33ec1ccbSHans Petter Selasky __be32 qp[MTHCA_QP_PER_MGM];
44*33ec1ccbSHans Petter Selasky };
45*33ec1ccbSHans Petter Selasky
46*33ec1ccbSHans Petter Selasky static const u8 zero_gid[16]; /* automatically initialized to 0 */
47*33ec1ccbSHans Petter Selasky
48*33ec1ccbSHans Petter Selasky /*
49*33ec1ccbSHans Petter Selasky * Caller must hold MCG table semaphore. gid and mgm parameters must
50*33ec1ccbSHans Petter Selasky * be properly aligned for command interface.
51*33ec1ccbSHans Petter Selasky *
52*33ec1ccbSHans Petter Selasky * Returns 0 unless a firmware command error occurs.
53*33ec1ccbSHans Petter Selasky *
54*33ec1ccbSHans Petter Selasky * If GID is found in MGM or MGM is empty, *index = *hash, *prev = -1
55*33ec1ccbSHans Petter Selasky * and *mgm holds MGM entry.
56*33ec1ccbSHans Petter Selasky *
57*33ec1ccbSHans Petter Selasky * if GID is found in AMGM, *index = index in AMGM, *prev = index of
58*33ec1ccbSHans Petter Selasky * previous entry in hash chain and *mgm holds AMGM entry.
59*33ec1ccbSHans Petter Selasky *
60*33ec1ccbSHans Petter Selasky * If no AMGM exists for given gid, *index = -1, *prev = index of last
61*33ec1ccbSHans Petter Selasky * entry in hash chain and *mgm holds end of hash chain.
62*33ec1ccbSHans Petter Selasky */
find_mgm(struct mthca_dev * dev,u8 * gid,struct mthca_mailbox * mgm_mailbox,u16 * hash,int * prev,int * index)63*33ec1ccbSHans Petter Selasky static int find_mgm(struct mthca_dev *dev,
64*33ec1ccbSHans Petter Selasky u8 *gid, struct mthca_mailbox *mgm_mailbox,
65*33ec1ccbSHans Petter Selasky u16 *hash, int *prev, int *index)
66*33ec1ccbSHans Petter Selasky {
67*33ec1ccbSHans Petter Selasky struct mthca_mailbox *mailbox;
68*33ec1ccbSHans Petter Selasky struct mthca_mgm *mgm = mgm_mailbox->buf;
69*33ec1ccbSHans Petter Selasky u8 *mgid;
70*33ec1ccbSHans Petter Selasky int err;
71*33ec1ccbSHans Petter Selasky
72*33ec1ccbSHans Petter Selasky mailbox = mthca_alloc_mailbox(dev, GFP_KERNEL);
73*33ec1ccbSHans Petter Selasky if (IS_ERR(mailbox))
74*33ec1ccbSHans Petter Selasky return -ENOMEM;
75*33ec1ccbSHans Petter Selasky mgid = mailbox->buf;
76*33ec1ccbSHans Petter Selasky
77*33ec1ccbSHans Petter Selasky memcpy(mgid, gid, 16);
78*33ec1ccbSHans Petter Selasky
79*33ec1ccbSHans Petter Selasky err = mthca_MGID_HASH(dev, mailbox, hash);
80*33ec1ccbSHans Petter Selasky if (err) {
81*33ec1ccbSHans Petter Selasky mthca_err(dev, "MGID_HASH failed (%d)\n", err);
82*33ec1ccbSHans Petter Selasky goto out;
83*33ec1ccbSHans Petter Selasky }
84*33ec1ccbSHans Petter Selasky
85*33ec1ccbSHans Petter Selasky if (0)
86*33ec1ccbSHans Petter Selasky mthca_dbg(dev, "Hash for %pI6 is %04x\n", gid, *hash);
87*33ec1ccbSHans Petter Selasky
88*33ec1ccbSHans Petter Selasky *index = *hash;
89*33ec1ccbSHans Petter Selasky *prev = -1;
90*33ec1ccbSHans Petter Selasky
91*33ec1ccbSHans Petter Selasky do {
92*33ec1ccbSHans Petter Selasky err = mthca_READ_MGM(dev, *index, mgm_mailbox);
93*33ec1ccbSHans Petter Selasky if (err) {
94*33ec1ccbSHans Petter Selasky mthca_err(dev, "READ_MGM failed (%d)\n", err);
95*33ec1ccbSHans Petter Selasky goto out;
96*33ec1ccbSHans Petter Selasky }
97*33ec1ccbSHans Petter Selasky
98*33ec1ccbSHans Petter Selasky if (!memcmp(mgm->gid, zero_gid, 16)) {
99*33ec1ccbSHans Petter Selasky if (*index != *hash) {
100*33ec1ccbSHans Petter Selasky mthca_err(dev, "Found zero MGID in AMGM.\n");
101*33ec1ccbSHans Petter Selasky err = -EINVAL;
102*33ec1ccbSHans Petter Selasky }
103*33ec1ccbSHans Petter Selasky goto out;
104*33ec1ccbSHans Petter Selasky }
105*33ec1ccbSHans Petter Selasky
106*33ec1ccbSHans Petter Selasky if (!memcmp(mgm->gid, gid, 16))
107*33ec1ccbSHans Petter Selasky goto out;
108*33ec1ccbSHans Petter Selasky
109*33ec1ccbSHans Petter Selasky *prev = *index;
110*33ec1ccbSHans Petter Selasky *index = be32_to_cpu(mgm->next_gid_index) >> 6;
111*33ec1ccbSHans Petter Selasky } while (*index);
112*33ec1ccbSHans Petter Selasky
113*33ec1ccbSHans Petter Selasky *index = -1;
114*33ec1ccbSHans Petter Selasky
115*33ec1ccbSHans Petter Selasky out:
116*33ec1ccbSHans Petter Selasky mthca_free_mailbox(dev, mailbox);
117*33ec1ccbSHans Petter Selasky return err;
118*33ec1ccbSHans Petter Selasky }
119*33ec1ccbSHans Petter Selasky
mthca_multicast_attach(struct ib_qp * ibqp,union ib_gid * gid,u16 lid)120*33ec1ccbSHans Petter Selasky int mthca_multicast_attach(struct ib_qp *ibqp, union ib_gid *gid, u16 lid)
121*33ec1ccbSHans Petter Selasky {
122*33ec1ccbSHans Petter Selasky struct mthca_dev *dev = to_mdev(ibqp->device);
123*33ec1ccbSHans Petter Selasky struct mthca_mailbox *mailbox;
124*33ec1ccbSHans Petter Selasky struct mthca_mgm *mgm;
125*33ec1ccbSHans Petter Selasky u16 hash;
126*33ec1ccbSHans Petter Selasky int index, prev;
127*33ec1ccbSHans Petter Selasky int link = 0;
128*33ec1ccbSHans Petter Selasky int i;
129*33ec1ccbSHans Petter Selasky int err;
130*33ec1ccbSHans Petter Selasky
131*33ec1ccbSHans Petter Selasky mailbox = mthca_alloc_mailbox(dev, GFP_KERNEL);
132*33ec1ccbSHans Petter Selasky if (IS_ERR(mailbox))
133*33ec1ccbSHans Petter Selasky return PTR_ERR(mailbox);
134*33ec1ccbSHans Petter Selasky mgm = mailbox->buf;
135*33ec1ccbSHans Petter Selasky
136*33ec1ccbSHans Petter Selasky mutex_lock(&dev->mcg_table.mutex);
137*33ec1ccbSHans Petter Selasky
138*33ec1ccbSHans Petter Selasky err = find_mgm(dev, gid->raw, mailbox, &hash, &prev, &index);
139*33ec1ccbSHans Petter Selasky if (err)
140*33ec1ccbSHans Petter Selasky goto out;
141*33ec1ccbSHans Petter Selasky
142*33ec1ccbSHans Petter Selasky if (index != -1) {
143*33ec1ccbSHans Petter Selasky if (!memcmp(mgm->gid, zero_gid, 16))
144*33ec1ccbSHans Petter Selasky memcpy(mgm->gid, gid->raw, 16);
145*33ec1ccbSHans Petter Selasky } else {
146*33ec1ccbSHans Petter Selasky link = 1;
147*33ec1ccbSHans Petter Selasky
148*33ec1ccbSHans Petter Selasky index = mthca_alloc(&dev->mcg_table.alloc);
149*33ec1ccbSHans Petter Selasky if (index == -1) {
150*33ec1ccbSHans Petter Selasky mthca_err(dev, "No AMGM entries left\n");
151*33ec1ccbSHans Petter Selasky err = -ENOMEM;
152*33ec1ccbSHans Petter Selasky goto out;
153*33ec1ccbSHans Petter Selasky }
154*33ec1ccbSHans Petter Selasky
155*33ec1ccbSHans Petter Selasky err = mthca_READ_MGM(dev, index, mailbox);
156*33ec1ccbSHans Petter Selasky if (err) {
157*33ec1ccbSHans Petter Selasky mthca_err(dev, "READ_MGM failed (%d)\n", err);
158*33ec1ccbSHans Petter Selasky goto out;
159*33ec1ccbSHans Petter Selasky }
160*33ec1ccbSHans Petter Selasky memset(mgm, 0, sizeof *mgm);
161*33ec1ccbSHans Petter Selasky memcpy(mgm->gid, gid->raw, 16);
162*33ec1ccbSHans Petter Selasky }
163*33ec1ccbSHans Petter Selasky
164*33ec1ccbSHans Petter Selasky for (i = 0; i < MTHCA_QP_PER_MGM; ++i)
165*33ec1ccbSHans Petter Selasky if (mgm->qp[i] == cpu_to_be32(ibqp->qp_num | (1 << 31))) {
166*33ec1ccbSHans Petter Selasky mthca_dbg(dev, "QP %06x already a member of MGM\n",
167*33ec1ccbSHans Petter Selasky ibqp->qp_num);
168*33ec1ccbSHans Petter Selasky err = 0;
169*33ec1ccbSHans Petter Selasky goto out;
170*33ec1ccbSHans Petter Selasky } else if (!(mgm->qp[i] & cpu_to_be32(1 << 31))) {
171*33ec1ccbSHans Petter Selasky mgm->qp[i] = cpu_to_be32(ibqp->qp_num | (1 << 31));
172*33ec1ccbSHans Petter Selasky break;
173*33ec1ccbSHans Petter Selasky }
174*33ec1ccbSHans Petter Selasky
175*33ec1ccbSHans Petter Selasky if (i == MTHCA_QP_PER_MGM) {
176*33ec1ccbSHans Petter Selasky mthca_err(dev, "MGM at index %x is full.\n", index);
177*33ec1ccbSHans Petter Selasky err = -ENOMEM;
178*33ec1ccbSHans Petter Selasky goto out;
179*33ec1ccbSHans Petter Selasky }
180*33ec1ccbSHans Petter Selasky
181*33ec1ccbSHans Petter Selasky err = mthca_WRITE_MGM(dev, index, mailbox);
182*33ec1ccbSHans Petter Selasky if (err) {
183*33ec1ccbSHans Petter Selasky mthca_err(dev, "WRITE_MGM failed %d\n", err);
184*33ec1ccbSHans Petter Selasky err = -EINVAL;
185*33ec1ccbSHans Petter Selasky goto out;
186*33ec1ccbSHans Petter Selasky }
187*33ec1ccbSHans Petter Selasky
188*33ec1ccbSHans Petter Selasky if (!link)
189*33ec1ccbSHans Petter Selasky goto out;
190*33ec1ccbSHans Petter Selasky
191*33ec1ccbSHans Petter Selasky err = mthca_READ_MGM(dev, prev, mailbox);
192*33ec1ccbSHans Petter Selasky if (err) {
193*33ec1ccbSHans Petter Selasky mthca_err(dev, "READ_MGM failed %d\n", err);
194*33ec1ccbSHans Petter Selasky goto out;
195*33ec1ccbSHans Petter Selasky }
196*33ec1ccbSHans Petter Selasky
197*33ec1ccbSHans Petter Selasky mgm->next_gid_index = cpu_to_be32(index << 6);
198*33ec1ccbSHans Petter Selasky
199*33ec1ccbSHans Petter Selasky err = mthca_WRITE_MGM(dev, prev, mailbox);
200*33ec1ccbSHans Petter Selasky if (err)
201*33ec1ccbSHans Petter Selasky mthca_err(dev, "WRITE_MGM returned %d\n", err);
202*33ec1ccbSHans Petter Selasky
203*33ec1ccbSHans Petter Selasky out:
204*33ec1ccbSHans Petter Selasky if (err && link && index != -1) {
205*33ec1ccbSHans Petter Selasky BUG_ON(index < dev->limits.num_mgms);
206*33ec1ccbSHans Petter Selasky mthca_free(&dev->mcg_table.alloc, index);
207*33ec1ccbSHans Petter Selasky }
208*33ec1ccbSHans Petter Selasky mutex_unlock(&dev->mcg_table.mutex);
209*33ec1ccbSHans Petter Selasky
210*33ec1ccbSHans Petter Selasky mthca_free_mailbox(dev, mailbox);
211*33ec1ccbSHans Petter Selasky return err;
212*33ec1ccbSHans Petter Selasky }
213*33ec1ccbSHans Petter Selasky
mthca_multicast_detach(struct ib_qp * ibqp,union ib_gid * gid,u16 lid)214*33ec1ccbSHans Petter Selasky int mthca_multicast_detach(struct ib_qp *ibqp, union ib_gid *gid, u16 lid)
215*33ec1ccbSHans Petter Selasky {
216*33ec1ccbSHans Petter Selasky struct mthca_dev *dev = to_mdev(ibqp->device);
217*33ec1ccbSHans Petter Selasky struct mthca_mailbox *mailbox;
218*33ec1ccbSHans Petter Selasky struct mthca_mgm *mgm;
219*33ec1ccbSHans Petter Selasky u16 hash;
220*33ec1ccbSHans Petter Selasky int prev, index;
221*33ec1ccbSHans Petter Selasky int i, loc;
222*33ec1ccbSHans Petter Selasky int err;
223*33ec1ccbSHans Petter Selasky
224*33ec1ccbSHans Petter Selasky mailbox = mthca_alloc_mailbox(dev, GFP_KERNEL);
225*33ec1ccbSHans Petter Selasky if (IS_ERR(mailbox))
226*33ec1ccbSHans Petter Selasky return PTR_ERR(mailbox);
227*33ec1ccbSHans Petter Selasky mgm = mailbox->buf;
228*33ec1ccbSHans Petter Selasky
229*33ec1ccbSHans Petter Selasky mutex_lock(&dev->mcg_table.mutex);
230*33ec1ccbSHans Petter Selasky
231*33ec1ccbSHans Petter Selasky err = find_mgm(dev, gid->raw, mailbox, &hash, &prev, &index);
232*33ec1ccbSHans Petter Selasky if (err)
233*33ec1ccbSHans Petter Selasky goto out;
234*33ec1ccbSHans Petter Selasky
235*33ec1ccbSHans Petter Selasky if (index == -1) {
236*33ec1ccbSHans Petter Selasky mthca_err(dev, "MGID %pI6 not found\n", gid->raw);
237*33ec1ccbSHans Petter Selasky err = -EINVAL;
238*33ec1ccbSHans Petter Selasky goto out;
239*33ec1ccbSHans Petter Selasky }
240*33ec1ccbSHans Petter Selasky
241*33ec1ccbSHans Petter Selasky for (loc = -1, i = 0; i < MTHCA_QP_PER_MGM; ++i) {
242*33ec1ccbSHans Petter Selasky if (mgm->qp[i] == cpu_to_be32(ibqp->qp_num | (1 << 31)))
243*33ec1ccbSHans Petter Selasky loc = i;
244*33ec1ccbSHans Petter Selasky if (!(mgm->qp[i] & cpu_to_be32(1 << 31)))
245*33ec1ccbSHans Petter Selasky break;
246*33ec1ccbSHans Petter Selasky }
247*33ec1ccbSHans Petter Selasky
248*33ec1ccbSHans Petter Selasky if (loc == -1) {
249*33ec1ccbSHans Petter Selasky mthca_err(dev, "QP %06x not found in MGM\n", ibqp->qp_num);
250*33ec1ccbSHans Petter Selasky err = -EINVAL;
251*33ec1ccbSHans Petter Selasky goto out;
252*33ec1ccbSHans Petter Selasky }
253*33ec1ccbSHans Petter Selasky
254*33ec1ccbSHans Petter Selasky mgm->qp[loc] = mgm->qp[i - 1];
255*33ec1ccbSHans Petter Selasky mgm->qp[i - 1] = 0;
256*33ec1ccbSHans Petter Selasky
257*33ec1ccbSHans Petter Selasky err = mthca_WRITE_MGM(dev, index, mailbox);
258*33ec1ccbSHans Petter Selasky if (err) {
259*33ec1ccbSHans Petter Selasky mthca_err(dev, "WRITE_MGM returned %d\n", err);
260*33ec1ccbSHans Petter Selasky goto out;
261*33ec1ccbSHans Petter Selasky }
262*33ec1ccbSHans Petter Selasky
263*33ec1ccbSHans Petter Selasky if (i != 1)
264*33ec1ccbSHans Petter Selasky goto out;
265*33ec1ccbSHans Petter Selasky
266*33ec1ccbSHans Petter Selasky if (prev == -1) {
267*33ec1ccbSHans Petter Selasky /* Remove entry from MGM */
268*33ec1ccbSHans Petter Selasky int amgm_index_to_free = be32_to_cpu(mgm->next_gid_index) >> 6;
269*33ec1ccbSHans Petter Selasky if (amgm_index_to_free) {
270*33ec1ccbSHans Petter Selasky err = mthca_READ_MGM(dev, amgm_index_to_free,
271*33ec1ccbSHans Petter Selasky mailbox);
272*33ec1ccbSHans Petter Selasky if (err) {
273*33ec1ccbSHans Petter Selasky mthca_err(dev, "READ_MGM returned %d\n", err);
274*33ec1ccbSHans Petter Selasky goto out;
275*33ec1ccbSHans Petter Selasky }
276*33ec1ccbSHans Petter Selasky } else
277*33ec1ccbSHans Petter Selasky memset(mgm->gid, 0, 16);
278*33ec1ccbSHans Petter Selasky
279*33ec1ccbSHans Petter Selasky err = mthca_WRITE_MGM(dev, index, mailbox);
280*33ec1ccbSHans Petter Selasky if (err) {
281*33ec1ccbSHans Petter Selasky mthca_err(dev, "WRITE_MGM returned %d\n", err);
282*33ec1ccbSHans Petter Selasky goto out;
283*33ec1ccbSHans Petter Selasky }
284*33ec1ccbSHans Petter Selasky if (amgm_index_to_free) {
285*33ec1ccbSHans Petter Selasky BUG_ON(amgm_index_to_free < dev->limits.num_mgms);
286*33ec1ccbSHans Petter Selasky mthca_free(&dev->mcg_table.alloc, amgm_index_to_free);
287*33ec1ccbSHans Petter Selasky }
288*33ec1ccbSHans Petter Selasky } else {
289*33ec1ccbSHans Petter Selasky /* Remove entry from AMGM */
290*33ec1ccbSHans Petter Selasky int curr_next_index = be32_to_cpu(mgm->next_gid_index) >> 6;
291*33ec1ccbSHans Petter Selasky err = mthca_READ_MGM(dev, prev, mailbox);
292*33ec1ccbSHans Petter Selasky if (err) {
293*33ec1ccbSHans Petter Selasky mthca_err(dev, "READ_MGM returned %d\n", err);
294*33ec1ccbSHans Petter Selasky goto out;
295*33ec1ccbSHans Petter Selasky }
296*33ec1ccbSHans Petter Selasky
297*33ec1ccbSHans Petter Selasky mgm->next_gid_index = cpu_to_be32(curr_next_index << 6);
298*33ec1ccbSHans Petter Selasky
299*33ec1ccbSHans Petter Selasky err = mthca_WRITE_MGM(dev, prev, mailbox);
300*33ec1ccbSHans Petter Selasky if (err) {
301*33ec1ccbSHans Petter Selasky mthca_err(dev, "WRITE_MGM returned %d\n", err);
302*33ec1ccbSHans Petter Selasky goto out;
303*33ec1ccbSHans Petter Selasky }
304*33ec1ccbSHans Petter Selasky BUG_ON(index < dev->limits.num_mgms);
305*33ec1ccbSHans Petter Selasky mthca_free(&dev->mcg_table.alloc, index);
306*33ec1ccbSHans Petter Selasky }
307*33ec1ccbSHans Petter Selasky
308*33ec1ccbSHans Petter Selasky out:
309*33ec1ccbSHans Petter Selasky mutex_unlock(&dev->mcg_table.mutex);
310*33ec1ccbSHans Petter Selasky
311*33ec1ccbSHans Petter Selasky mthca_free_mailbox(dev, mailbox);
312*33ec1ccbSHans Petter Selasky return err;
313*33ec1ccbSHans Petter Selasky }
314*33ec1ccbSHans Petter Selasky
mthca_init_mcg_table(struct mthca_dev * dev)315*33ec1ccbSHans Petter Selasky int mthca_init_mcg_table(struct mthca_dev *dev)
316*33ec1ccbSHans Petter Selasky {
317*33ec1ccbSHans Petter Selasky int err;
318*33ec1ccbSHans Petter Selasky int table_size = dev->limits.num_mgms + dev->limits.num_amgms;
319*33ec1ccbSHans Petter Selasky
320*33ec1ccbSHans Petter Selasky err = mthca_alloc_init(&dev->mcg_table.alloc,
321*33ec1ccbSHans Petter Selasky table_size,
322*33ec1ccbSHans Petter Selasky table_size - 1,
323*33ec1ccbSHans Petter Selasky dev->limits.num_mgms);
324*33ec1ccbSHans Petter Selasky if (err)
325*33ec1ccbSHans Petter Selasky return err;
326*33ec1ccbSHans Petter Selasky
327*33ec1ccbSHans Petter Selasky mutex_init(&dev->mcg_table.mutex);
328*33ec1ccbSHans Petter Selasky
329*33ec1ccbSHans Petter Selasky return 0;
330*33ec1ccbSHans Petter Selasky }
331*33ec1ccbSHans Petter Selasky
mthca_cleanup_mcg_table(struct mthca_dev * dev)332*33ec1ccbSHans Petter Selasky void mthca_cleanup_mcg_table(struct mthca_dev *dev)
333*33ec1ccbSHans Petter Selasky {
334*33ec1ccbSHans Petter Selasky mthca_alloc_cleanup(&dev->mcg_table.alloc);
335*33ec1ccbSHans Petter Selasky }
336