aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/infiniband
diff options
context:
space:
mode:
authorAmir Vadai <amirv@mellanox.co.il>2012-08-03 04:40:47 -0400
committerRoland Dreier <roland@purestorage.com>2012-09-30 23:33:36 -0400
commit3cf69cc8dbebf15b99deb342ea422105ae9c2774 (patch)
tree44147d3daafc44b3ff4cd1a4b0fe75876535e09e /drivers/infiniband
parentb9c5d6a643589ad39064f652938baa698f0e884a (diff)
IB/mlx4: Add CM paravirtualization
In CM para-virtualization: 1. Incoming requests are steered to the correct vHCA according to the embedded GID. 2. Communication IDs on outgoing requests are replaced by a globally unique ID, generated by the PPF, since there is no synchronization of ID generation between guests (and so these IDs are not guaranteed to be globally unique). The guest's comm ID is stored, and is returned to the response MAD when it arrives. Signed-off-by: Amir Vadai <amirv@mellanox.co.il> Signed-off-by: Jack Morgenstein <jackm@dev.mellanox.co.il> Signed-off-by: Roland Dreier <roland@purestorage.com>
Diffstat (limited to 'drivers/infiniband')
-rw-r--r--drivers/infiniband/hw/mlx4/Makefile2
-rw-r--r--drivers/infiniband/hw/mlx4/cm.c437
-rw-r--r--drivers/infiniband/hw/mlx4/mad.c16
-rw-r--r--drivers/infiniband/hw/mlx4/mlx4_ib.h15
4 files changed, 468 insertions, 2 deletions
diff --git a/drivers/infiniband/hw/mlx4/Makefile b/drivers/infiniband/hw/mlx4/Makefile
index 20d627d1f046..bf0aa901c313 100644
--- a/drivers/infiniband/hw/mlx4/Makefile
+++ b/drivers/infiniband/hw/mlx4/Makefile
@@ -1,3 +1,3 @@
1obj-$(CONFIG_MLX4_INFINIBAND) += mlx4_ib.o 1obj-$(CONFIG_MLX4_INFINIBAND) += mlx4_ib.o
2 2
3mlx4_ib-y := ah.o cq.o doorbell.o mad.o main.o mr.o qp.o srq.o mcg.o 3mlx4_ib-y := ah.o cq.o doorbell.o mad.o main.o mr.o qp.o srq.o mcg.o cm.o
diff --git a/drivers/infiniband/hw/mlx4/cm.c b/drivers/infiniband/hw/mlx4/cm.c
new file mode 100644
index 000000000000..e25e4dafb8a8
--- /dev/null
+++ b/drivers/infiniband/hw/mlx4/cm.c
@@ -0,0 +1,437 @@
1/*
2 * Copyright (c) 2012 Mellanox Technologies. All rights reserved.
3 *
4 * This software is available to you under a choice of one of two
5 * licenses. You may choose to be licensed under the terms of the GNU
6 * General Public License (GPL) Version 2, available from the file
7 * COPYING in the main directory of this source tree, or the
8 * OpenIB.org BSD license below:
9 *
10 * Redistribution and use in source and binary forms, with or
11 * without modification, are permitted provided that the following
12 * conditions are met:
13 *
14 * - Redistributions of source code must retain the above
15 * copyright notice, this list of conditions and the following
16 * disclaimer.
17 *
18 * - Redistributions in binary form must reproduce the above
19 * copyright notice, this list of conditions and the following
20 * disclaimer in the documentation and/or other materials
21 * provided with the distribution.
22 *
23 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
24 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
25 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
26 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
27 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
28 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
29 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
30 * SOFTWARE.
31 */
32
33#include <rdma/ib_mad.h>
34
35#include <linux/mlx4/cmd.h>
36#include <linux/rbtree.h>
37#include <linux/idr.h>
38#include <rdma/ib_cm.h>
39
40#include "mlx4_ib.h"
41
42#define CM_CLEANUP_CACHE_TIMEOUT (5 * HZ)
43
44struct id_map_entry {
45 struct rb_node node;
46
47 u32 sl_cm_id;
48 u32 pv_cm_id;
49 int slave_id;
50 int scheduled_delete;
51 struct mlx4_ib_dev *dev;
52
53 struct list_head list;
54 struct delayed_work timeout;
55};
56
57struct cm_generic_msg {
58 struct ib_mad_hdr hdr;
59
60 __be32 local_comm_id;
61 __be32 remote_comm_id;
62};
63
64struct cm_req_msg {
65 unsigned char unused[0x60];
66 union ib_gid primary_path_sgid;
67};
68
69
70static void set_local_comm_id(struct ib_mad *mad, u32 cm_id)
71{
72 struct cm_generic_msg *msg = (struct cm_generic_msg *)mad;
73 msg->local_comm_id = cpu_to_be32(cm_id);
74}
75
76static u32 get_local_comm_id(struct ib_mad *mad)
77{
78 struct cm_generic_msg *msg = (struct cm_generic_msg *)mad;
79
80 return be32_to_cpu(msg->local_comm_id);
81}
82
83static void set_remote_comm_id(struct ib_mad *mad, u32 cm_id)
84{
85 struct cm_generic_msg *msg = (struct cm_generic_msg *)mad;
86 msg->remote_comm_id = cpu_to_be32(cm_id);
87}
88
89static u32 get_remote_comm_id(struct ib_mad *mad)
90{
91 struct cm_generic_msg *msg = (struct cm_generic_msg *)mad;
92
93 return be32_to_cpu(msg->remote_comm_id);
94}
95
96static union ib_gid gid_from_req_msg(struct ib_device *ibdev, struct ib_mad *mad)
97{
98 struct cm_req_msg *msg = (struct cm_req_msg *)mad;
99
100 return msg->primary_path_sgid;
101}
102
103/* Lock should be taken before called */
104static struct id_map_entry *
105id_map_find_by_sl_id(struct ib_device *ibdev, u32 slave_id, u32 sl_cm_id)
106{
107 struct rb_root *sl_id_map = &to_mdev(ibdev)->sriov.sl_id_map;
108 struct rb_node *node = sl_id_map->rb_node;
109
110 while (node) {
111 struct id_map_entry *id_map_entry =
112 rb_entry(node, struct id_map_entry, node);
113
114 if (id_map_entry->sl_cm_id > sl_cm_id)
115 node = node->rb_left;
116 else if (id_map_entry->sl_cm_id < sl_cm_id)
117 node = node->rb_right;
118 else if (id_map_entry->slave_id > slave_id)
119 node = node->rb_left;
120 else if (id_map_entry->slave_id < slave_id)
121 node = node->rb_right;
122 else
123 return id_map_entry;
124 }
125 return NULL;
126}
127
128static void id_map_ent_timeout(struct work_struct *work)
129{
130 struct delayed_work *delay = to_delayed_work(work);
131 struct id_map_entry *ent = container_of(delay, struct id_map_entry, timeout);
132 struct id_map_entry *db_ent, *found_ent;
133 struct mlx4_ib_dev *dev = ent->dev;
134 struct mlx4_ib_sriov *sriov = &dev->sriov;
135 struct rb_root *sl_id_map = &sriov->sl_id_map;
136 int pv_id = (int) ent->pv_cm_id;
137
138 spin_lock(&sriov->id_map_lock);
139 db_ent = (struct id_map_entry *)idr_find(&sriov->pv_id_table, pv_id);
140 if (!db_ent)
141 goto out;
142 found_ent = id_map_find_by_sl_id(&dev->ib_dev, ent->slave_id, ent->sl_cm_id);
143 if (found_ent && found_ent == ent)
144 rb_erase(&found_ent->node, sl_id_map);
145 idr_remove(&sriov->pv_id_table, pv_id);
146
147out:
148 list_del(&ent->list);
149 spin_unlock(&sriov->id_map_lock);
150 kfree(ent);
151}
152
153static void id_map_find_del(struct ib_device *ibdev, int pv_cm_id)
154{
155 struct mlx4_ib_sriov *sriov = &to_mdev(ibdev)->sriov;
156 struct rb_root *sl_id_map = &sriov->sl_id_map;
157 struct id_map_entry *ent, *found_ent;
158
159 spin_lock(&sriov->id_map_lock);
160 ent = (struct id_map_entry *)idr_find(&sriov->pv_id_table, pv_cm_id);
161 if (!ent)
162 goto out;
163 found_ent = id_map_find_by_sl_id(ibdev, ent->slave_id, ent->sl_cm_id);
164 if (found_ent && found_ent == ent)
165 rb_erase(&found_ent->node, sl_id_map);
166 idr_remove(&sriov->pv_id_table, pv_cm_id);
167out:
168 spin_unlock(&sriov->id_map_lock);
169}
170
171static void sl_id_map_add(struct ib_device *ibdev, struct id_map_entry *new)
172{
173 struct rb_root *sl_id_map = &to_mdev(ibdev)->sriov.sl_id_map;
174 struct rb_node **link = &sl_id_map->rb_node, *parent = NULL;
175 struct id_map_entry *ent;
176 int slave_id = new->slave_id;
177 int sl_cm_id = new->sl_cm_id;
178
179 ent = id_map_find_by_sl_id(ibdev, slave_id, sl_cm_id);
180 if (ent) {
181 pr_debug("overriding existing sl_id_map entry (cm_id = %x)\n",
182 sl_cm_id);
183
184 rb_replace_node(&ent->node, &new->node, sl_id_map);
185 return;
186 }
187
188 /* Go to the bottom of the tree */
189 while (*link) {
190 parent = *link;
191 ent = rb_entry(parent, struct id_map_entry, node);
192
193 if (ent->sl_cm_id > sl_cm_id || (ent->sl_cm_id == sl_cm_id && ent->slave_id > slave_id))
194 link = &(*link)->rb_left;
195 else
196 link = &(*link)->rb_right;
197 }
198
199 rb_link_node(&new->node, parent, link);
200 rb_insert_color(&new->node, sl_id_map);
201}
202
203static struct id_map_entry *
204id_map_alloc(struct ib_device *ibdev, int slave_id, u32 sl_cm_id)
205{
206 int ret, id;
207 static int next_id;
208 struct id_map_entry *ent;
209 struct mlx4_ib_sriov *sriov = &to_mdev(ibdev)->sriov;
210
211 ent = kmalloc(sizeof (struct id_map_entry), GFP_KERNEL);
212 if (!ent) {
213 mlx4_ib_warn(ibdev, "Couldn't allocate id cache entry - out of memory\n");
214 return ERR_PTR(-ENOMEM);
215 }
216
217 ent->sl_cm_id = sl_cm_id;
218 ent->slave_id = slave_id;
219 ent->scheduled_delete = 0;
220 ent->dev = to_mdev(ibdev);
221 INIT_DELAYED_WORK(&ent->timeout, id_map_ent_timeout);
222
223 do {
224 spin_lock(&to_mdev(ibdev)->sriov.id_map_lock);
225 ret = idr_get_new_above(&sriov->pv_id_table, ent,
226 next_id, &id);
227 if (!ret) {
228 next_id = ((unsigned) id + 1) & MAX_ID_MASK;
229 ent->pv_cm_id = (u32)id;
230 sl_id_map_add(ibdev, ent);
231 }
232
233 spin_unlock(&sriov->id_map_lock);
234 } while (ret == -EAGAIN && idr_pre_get(&sriov->pv_id_table, GFP_KERNEL));
235 /*the function idr_get_new_above can return -ENOSPC, so don't insert in that case.*/
236 if (!ret) {
237 spin_lock(&sriov->id_map_lock);
238 list_add_tail(&ent->list, &sriov->cm_list);
239 spin_unlock(&sriov->id_map_lock);
240 return ent;
241 }
242 /*error flow*/
243 kfree(ent);
244 mlx4_ib_warn(ibdev, "No more space in the idr (err:0x%x)\n", ret);
245 return ERR_PTR(-ENOMEM);
246}
247
248static struct id_map_entry *
249id_map_get(struct ib_device *ibdev, int *pv_cm_id, int sl_cm_id, int slave_id)
250{
251 struct id_map_entry *ent;
252 struct mlx4_ib_sriov *sriov = &to_mdev(ibdev)->sriov;
253
254 spin_lock(&sriov->id_map_lock);
255 if (*pv_cm_id == -1) {
256 ent = id_map_find_by_sl_id(ibdev, sl_cm_id, slave_id);
257 if (ent)
258 *pv_cm_id = (int) ent->pv_cm_id;
259 } else
260 ent = (struct id_map_entry *)idr_find(&sriov->pv_id_table, *pv_cm_id);
261 spin_unlock(&sriov->id_map_lock);
262
263 return ent;
264}
265
266static void schedule_delayed(struct ib_device *ibdev, struct id_map_entry *id)
267{
268 struct mlx4_ib_sriov *sriov = &to_mdev(ibdev)->sriov;
269 unsigned long flags;
270
271 spin_lock_irqsave(&sriov->going_down_lock, flags);
272 spin_lock(&sriov->id_map_lock);
273 /*make sure that there is no schedule inside the scheduled work.*/
274 if (!sriov->is_going_down) {
275 id->scheduled_delete = 1;
276 schedule_delayed_work(&id->timeout, CM_CLEANUP_CACHE_TIMEOUT);
277 }
278 spin_unlock(&sriov->id_map_lock);
279 spin_unlock_irqrestore(&sriov->going_down_lock, flags);
280}
281
282int mlx4_ib_multiplex_cm_handler(struct ib_device *ibdev, int port, int slave_id,
283 struct ib_mad *mad)
284{
285 struct id_map_entry *id;
286 u32 sl_cm_id;
287 int pv_cm_id = -1;
288
289 sl_cm_id = get_local_comm_id(mad);
290
291 if (mad->mad_hdr.attr_id == CM_REQ_ATTR_ID ||
292 mad->mad_hdr.attr_id == CM_REP_ATTR_ID) {
293 id = id_map_alloc(ibdev, slave_id, sl_cm_id);
294 if (IS_ERR(id)) {
295 mlx4_ib_warn(ibdev, "%s: id{slave: %d, sl_cm_id: 0x%x} Failed to id_map_alloc\n",
296 __func__, slave_id, sl_cm_id);
297 return PTR_ERR(id);
298 }
299 } else if (mad->mad_hdr.attr_id == CM_REJ_ATTR_ID) {
300 return 0;
301 } else {
302 id = id_map_get(ibdev, &pv_cm_id, slave_id, sl_cm_id);
303 }
304
305 if (!id) {
306 pr_debug("id{slave: %d, sl_cm_id: 0x%x} is NULL!\n",
307 slave_id, sl_cm_id);
308 return -EINVAL;
309 }
310
311 set_local_comm_id(mad, id->pv_cm_id);
312
313 if (mad->mad_hdr.attr_id == CM_DREQ_ATTR_ID)
314 schedule_delayed(ibdev, id);
315 else if (mad->mad_hdr.attr_id == CM_DREP_ATTR_ID)
316 id_map_find_del(ibdev, pv_cm_id);
317
318 return 0;
319}
320
321int mlx4_ib_demux_cm_handler(struct ib_device *ibdev, int port, int *slave,
322 struct ib_mad *mad)
323{
324 u32 pv_cm_id;
325 struct id_map_entry *id;
326
327 if (mad->mad_hdr.attr_id == CM_REQ_ATTR_ID) {
328 union ib_gid gid;
329
330 gid = gid_from_req_msg(ibdev, mad);
331 *slave = mlx4_ib_find_real_gid(ibdev, port, gid.global.interface_id);
332 if (*slave < 0) {
333 mlx4_ib_warn(ibdev, "failed matching slave_id by gid (0x%llx)\n",
334 gid.global.interface_id);
335 return -ENOENT;
336 }
337 return 0;
338 }
339
340 pv_cm_id = get_remote_comm_id(mad);
341 id = id_map_get(ibdev, (int *)&pv_cm_id, -1, -1);
342
343 if (!id) {
344 pr_debug("Couldn't find an entry for pv_cm_id 0x%x\n", pv_cm_id);
345 return -ENOENT;
346 }
347
348 *slave = id->slave_id;
349 set_remote_comm_id(mad, id->sl_cm_id);
350
351 if (mad->mad_hdr.attr_id == CM_DREQ_ATTR_ID)
352 schedule_delayed(ibdev, id);
353 else if (mad->mad_hdr.attr_id == CM_REJ_ATTR_ID ||
354 mad->mad_hdr.attr_id == CM_DREP_ATTR_ID) {
355 id_map_find_del(ibdev, (int) pv_cm_id);
356 }
357
358 return 0;
359}
360
361void mlx4_ib_cm_paravirt_init(struct mlx4_ib_dev *dev)
362{
363 spin_lock_init(&dev->sriov.id_map_lock);
364 INIT_LIST_HEAD(&dev->sriov.cm_list);
365 dev->sriov.sl_id_map = RB_ROOT;
366 idr_init(&dev->sriov.pv_id_table);
367 idr_pre_get(&dev->sriov.pv_id_table, GFP_KERNEL);
368}
369
370/* slave = -1 ==> all slaves */
371/* TBD -- call paravirt clean for single slave. Need for slave RESET event */
372void mlx4_ib_cm_paravirt_clean(struct mlx4_ib_dev *dev, int slave)
373{
374 struct mlx4_ib_sriov *sriov = &dev->sriov;
375 struct rb_root *sl_id_map = &sriov->sl_id_map;
376 struct list_head lh;
377 struct rb_node *nd;
378 int need_flush = 1;
379 struct id_map_entry *map, *tmp_map;
380 /* cancel all delayed work queue entries */
381 INIT_LIST_HEAD(&lh);
382 spin_lock(&sriov->id_map_lock);
383 list_for_each_entry_safe(map, tmp_map, &dev->sriov.cm_list, list) {
384 if (slave < 0 || slave == map->slave_id) {
385 if (map->scheduled_delete)
386 need_flush &= !!cancel_delayed_work(&map->timeout);
387 }
388 }
389
390 spin_unlock(&sriov->id_map_lock);
391
392 if (!need_flush)
393 flush_scheduled_work(); /* make sure all timers were flushed */
394
395 /* now, remove all leftover entries from databases*/
396 spin_lock(&sriov->id_map_lock);
397 if (slave < 0) {
398 while (rb_first(sl_id_map)) {
399 struct id_map_entry *ent =
400 rb_entry(rb_first(sl_id_map),
401 struct id_map_entry, node);
402
403 rb_erase(&ent->node, sl_id_map);
404 idr_remove(&sriov->pv_id_table, (int) ent->pv_cm_id);
405 }
406 list_splice_init(&dev->sriov.cm_list, &lh);
407 } else {
408 /* first, move nodes belonging to slave to db remove list */
409 nd = rb_first(sl_id_map);
410 while (nd) {
411 struct id_map_entry *ent =
412 rb_entry(nd, struct id_map_entry, node);
413 nd = rb_next(nd);
414 if (ent->slave_id == slave)
415 list_move_tail(&ent->list, &lh);
416 }
417 /* remove those nodes from databases */
418 list_for_each_entry_safe(map, tmp_map, &lh, list) {
419 rb_erase(&map->node, sl_id_map);
420 idr_remove(&sriov->pv_id_table, (int) map->pv_cm_id);
421 }
422
423 /* add remaining nodes from cm_list */
424 list_for_each_entry_safe(map, tmp_map, &dev->sriov.cm_list, list) {
425 if (slave == map->slave_id)
426 list_move_tail(&map->list, &lh);
427 }
428 }
429
430 spin_unlock(&sriov->id_map_lock);
431
432 /* free any map entries left behind due to cancel_delayed_work above */
433 list_for_each_entry_safe(map, tmp_map, &lh, list) {
434 list_del(&map->list);
435 kfree(map);
436 }
437}
diff --git a/drivers/infiniband/hw/mlx4/mad.c b/drivers/infiniband/hw/mlx4/mad.c
index 29ed3b43e4a6..2f13894299ee 100644
--- a/drivers/infiniband/hw/mlx4/mad.c
+++ b/drivers/infiniband/hw/mlx4/mad.c
@@ -544,6 +544,10 @@ static int mlx4_ib_demux_mad(struct ib_device *ibdev, u8 port,
544 (struct ib_sa_mad *) mad)) 544 (struct ib_sa_mad *) mad))
545 return 0; 545 return 0;
546 break; 546 break;
547 case IB_MGMT_CLASS_CM:
548 if (mlx4_ib_demux_cm_handler(ibdev, port, &slave, mad))
549 return 0;
550 break;
547 case IB_MGMT_CLASS_DEVICE_MGMT: 551 case IB_MGMT_CLASS_DEVICE_MGMT:
548 if (mad->mad_hdr.method != IB_MGMT_METHOD_GET_RESP) 552 if (mad->mad_hdr.method != IB_MGMT_METHOD_GET_RESP)
549 return 0; 553 return 0;
@@ -1076,6 +1080,11 @@ static void mlx4_ib_multiplex_mad(struct mlx4_ib_demux_pv_ctx *ctx, struct ib_wc
1076 (struct ib_sa_mad *) &tunnel->mad)) 1080 (struct ib_sa_mad *) &tunnel->mad))
1077 return; 1081 return;
1078 break; 1082 break;
1083 case IB_MGMT_CLASS_CM:
1084 if (mlx4_ib_multiplex_cm_handler(ctx->ib_dev, ctx->port, slave,
1085 (struct ib_mad *) &tunnel->mad))
1086 return;
1087 break;
1079 case IB_MGMT_CLASS_DEVICE_MGMT: 1088 case IB_MGMT_CLASS_DEVICE_MGMT:
1080 if (tunnel->mad.mad_hdr.method != IB_MGMT_METHOD_GET && 1089 if (tunnel->mad.mad_hdr.method != IB_MGMT_METHOD_GET &&
1081 tunnel->mad.mad_hdr.method != IB_MGMT_METHOD_SET) 1090 tunnel->mad.mad_hdr.method != IB_MGMT_METHOD_SET)
@@ -1790,6 +1799,7 @@ int mlx4_ib_init_sriov(struct mlx4_ib_dev *dev)
1790 1799
1791 dev->sriov.is_going_down = 0; 1800 dev->sriov.is_going_down = 0;
1792 spin_lock_init(&dev->sriov.going_down_lock); 1801 spin_lock_init(&dev->sriov.going_down_lock);
1802 mlx4_ib_cm_paravirt_init(dev);
1793 1803
1794 mlx4_ib_warn(&dev->ib_dev, "multi-function enabled\n"); 1804 mlx4_ib_warn(&dev->ib_dev, "multi-function enabled\n");
1795 1805
@@ -1818,6 +1828,7 @@ demux_err:
1818 mlx4_ib_free_demux_ctx(&dev->sriov.demux[i]); 1828 mlx4_ib_free_demux_ctx(&dev->sriov.demux[i]);
1819 --i; 1829 --i;
1820 } 1830 }
1831 mlx4_ib_cm_paravirt_clean(dev, -1);
1821 1832
1822 return err; 1833 return err;
1823} 1834}
@@ -1833,7 +1844,7 @@ void mlx4_ib_close_sriov(struct mlx4_ib_dev *dev)
1833 spin_lock_irqsave(&dev->sriov.going_down_lock, flags); 1844 spin_lock_irqsave(&dev->sriov.going_down_lock, flags);
1834 dev->sriov.is_going_down = 1; 1845 dev->sriov.is_going_down = 1;
1835 spin_unlock_irqrestore(&dev->sriov.going_down_lock, flags); 1846 spin_unlock_irqrestore(&dev->sriov.going_down_lock, flags);
1836 if (mlx4_is_master(dev->dev)) 1847 if (mlx4_is_master(dev->dev)) {
1837 for (i = 0; i < dev->num_ports; i++) { 1848 for (i = 0; i < dev->num_ports; i++) {
1838 flush_workqueue(dev->sriov.demux[i].ud_wq); 1849 flush_workqueue(dev->sriov.demux[i].ud_wq);
1839 mlx4_ib_free_sqp_ctx(dev->sriov.sqps[i]); 1850 mlx4_ib_free_sqp_ctx(dev->sriov.sqps[i]);
@@ -1841,4 +1852,7 @@ void mlx4_ib_close_sriov(struct mlx4_ib_dev *dev)
1841 dev->sriov.sqps[i] = NULL; 1852 dev->sriov.sqps[i] = NULL;
1842 mlx4_ib_free_demux_ctx(&dev->sriov.demux[i]); 1853 mlx4_ib_free_demux_ctx(&dev->sriov.demux[i]);
1843 } 1854 }
1855
1856 mlx4_ib_cm_paravirt_clean(dev, -1);
1857 }
1844} 1858}
diff --git a/drivers/infiniband/hw/mlx4/mlx4_ib.h b/drivers/infiniband/hw/mlx4/mlx4_ib.h
index 01ba9f1692b1..7476e2439f6b 100644
--- a/drivers/infiniband/hw/mlx4/mlx4_ib.h
+++ b/drivers/infiniband/hw/mlx4/mlx4_ib.h
@@ -348,6 +348,12 @@ struct mlx4_ib_sriov {
348 * it may be called from interrupt context.*/ 348 * it may be called from interrupt context.*/
349 spinlock_t going_down_lock; 349 spinlock_t going_down_lock;
350 int is_going_down; 350 int is_going_down;
351
352 /* CM paravirtualization fields */
353 struct list_head cm_list;
354 spinlock_t id_map_lock;
355 struct rb_root sl_id_map;
356 struct idr pv_id_table;
351}; 357};
352 358
353struct mlx4_ib_iboe { 359struct mlx4_ib_iboe {
@@ -591,4 +597,13 @@ int mlx4_ib_send_to_wire(struct mlx4_ib_dev *dev, int slave, u8 port,
591 u32 qkey, struct ib_ah_attr *attr, struct ib_mad *mad); 597 u32 qkey, struct ib_ah_attr *attr, struct ib_mad *mad);
592__be64 mlx4_ib_get_new_demux_tid(struct mlx4_ib_demux_ctx *ctx); 598__be64 mlx4_ib_get_new_demux_tid(struct mlx4_ib_demux_ctx *ctx);
593 599
600int mlx4_ib_demux_cm_handler(struct ib_device *ibdev, int port, int *slave,
601 struct ib_mad *mad);
602
603int mlx4_ib_multiplex_cm_handler(struct ib_device *ibdev, int port, int slave_id,
604 struct ib_mad *mad);
605
606void mlx4_ib_cm_paravirt_init(struct mlx4_ib_dev *dev);
607void mlx4_ib_cm_paravirt_clean(struct mlx4_ib_dev *dev, int slave_id);
608
594#endif /* MLX4_IB_H */ 609#endif /* MLX4_IB_H */