xref: /linux/drivers/infiniband/core/cma.c (revision 5fd571cbc13db113bda26c20673e1ec54bfd26b4)
1e51060f0SSean Hefty /*
2e51060f0SSean Hefty  * Copyright (c) 2005 Voltaire Inc.  All rights reserved.
3e51060f0SSean Hefty  * Copyright (c) 2002-2005, Network Appliance, Inc. All rights reserved.
4e51060f0SSean Hefty  * Copyright (c) 1999-2005, Mellanox Technologies, Inc. All rights reserved.
5e51060f0SSean Hefty  * Copyright (c) 2005-2006 Intel Corporation.  All rights reserved.
6e51060f0SSean Hefty  *
7e51060f0SSean Hefty  * This Software is licensed under one of the following licenses:
8e51060f0SSean Hefty  *
9e51060f0SSean Hefty  * 1) under the terms of the "Common Public License 1.0" a copy of which is
10e51060f0SSean Hefty  *    available from the Open Source Initiative, see
11e51060f0SSean Hefty  *    http://www.opensource.org/licenses/cpl.php.
12e51060f0SSean Hefty  *
13e51060f0SSean Hefty  * 2) under the terms of the "The BSD License" a copy of which is
14e51060f0SSean Hefty  *    available from the Open Source Initiative, see
15e51060f0SSean Hefty  *    http://www.opensource.org/licenses/bsd-license.php.
16e51060f0SSean Hefty  *
17e51060f0SSean Hefty  * 3) under the terms of the "GNU General Public License (GPL) Version 2" a
18e51060f0SSean Hefty  *    copy of which is available from the Open Source Initiative, see
19e51060f0SSean Hefty  *    http://www.opensource.org/licenses/gpl-license.php.
20e51060f0SSean Hefty  *
21e51060f0SSean Hefty  * Licensee has the right to choose one of the above licenses.
22e51060f0SSean Hefty  *
23e51060f0SSean Hefty  * Redistributions of source code must retain the above copyright
24e51060f0SSean Hefty  * notice and one of the license notices.
25e51060f0SSean Hefty  *
26e51060f0SSean Hefty  * Redistributions in binary form must reproduce both the above copyright
27e51060f0SSean Hefty  * notice, one of the license notices in the documentation
28e51060f0SSean Hefty  * and/or other materials provided with the distribution.
29e51060f0SSean Hefty  *
30e51060f0SSean Hefty  */
31e51060f0SSean Hefty 
32e51060f0SSean Hefty #include <linux/completion.h>
33e51060f0SSean Hefty #include <linux/in.h>
34e51060f0SSean Hefty #include <linux/in6.h>
35e51060f0SSean Hefty #include <linux/mutex.h>
36e51060f0SSean Hefty #include <linux/random.h>
37e51060f0SSean Hefty #include <linux/idr.h>
38e51060f0SSean Hefty 
39e51060f0SSean Hefty #include <net/tcp.h>
40e51060f0SSean Hefty 
41e51060f0SSean Hefty #include <rdma/rdma_cm.h>
42e51060f0SSean Hefty #include <rdma/rdma_cm_ib.h>
43e51060f0SSean Hefty #include <rdma/ib_cache.h>
44e51060f0SSean Hefty #include <rdma/ib_cm.h>
45e51060f0SSean Hefty #include <rdma/ib_sa.h>
46e51060f0SSean Hefty 
47e51060f0SSean Hefty MODULE_AUTHOR("Sean Hefty");
48e51060f0SSean Hefty MODULE_DESCRIPTION("Generic RDMA CM Agent");
49e51060f0SSean Hefty MODULE_LICENSE("Dual BSD/GPL");
50e51060f0SSean Hefty 
51e51060f0SSean Hefty #define CMA_CM_RESPONSE_TIMEOUT 20
52e51060f0SSean Hefty #define CMA_MAX_CM_RETRIES 3
53e51060f0SSean Hefty 
54e51060f0SSean Hefty static void cma_add_one(struct ib_device *device);
55e51060f0SSean Hefty static void cma_remove_one(struct ib_device *device);
56e51060f0SSean Hefty 
57e51060f0SSean Hefty static struct ib_client cma_client = {
58e51060f0SSean Hefty 	.name   = "cma",
59e51060f0SSean Hefty 	.add    = cma_add_one,
60e51060f0SSean Hefty 	.remove = cma_remove_one
61e51060f0SSean Hefty };
62e51060f0SSean Hefty 
63e51060f0SSean Hefty static LIST_HEAD(dev_list);
64e51060f0SSean Hefty static LIST_HEAD(listen_any_list);
65e51060f0SSean Hefty static DEFINE_MUTEX(lock);
66e51060f0SSean Hefty static struct workqueue_struct *cma_wq;
67e51060f0SSean Hefty static DEFINE_IDR(sdp_ps);
68e51060f0SSean Hefty static DEFINE_IDR(tcp_ps);
69e51060f0SSean Hefty 
70e51060f0SSean Hefty struct cma_device {
71e51060f0SSean Hefty 	struct list_head	list;
72e51060f0SSean Hefty 	struct ib_device	*device;
73e51060f0SSean Hefty 	__be64			node_guid;
74e51060f0SSean Hefty 	struct completion	comp;
75e51060f0SSean Hefty 	atomic_t		refcount;
76e51060f0SSean Hefty 	struct list_head	id_list;
77e51060f0SSean Hefty };
78e51060f0SSean Hefty 
79e51060f0SSean Hefty enum cma_state {
80e51060f0SSean Hefty 	CMA_IDLE,
81e51060f0SSean Hefty 	CMA_ADDR_QUERY,
82e51060f0SSean Hefty 	CMA_ADDR_RESOLVED,
83e51060f0SSean Hefty 	CMA_ROUTE_QUERY,
84e51060f0SSean Hefty 	CMA_ROUTE_RESOLVED,
85e51060f0SSean Hefty 	CMA_CONNECT,
86e51060f0SSean Hefty 	CMA_DISCONNECT,
87e51060f0SSean Hefty 	CMA_ADDR_BOUND,
88e51060f0SSean Hefty 	CMA_LISTEN,
89e51060f0SSean Hefty 	CMA_DEVICE_REMOVAL,
90e51060f0SSean Hefty 	CMA_DESTROYING
91e51060f0SSean Hefty };
92e51060f0SSean Hefty 
93e51060f0SSean Hefty struct rdma_bind_list {
94e51060f0SSean Hefty 	struct idr		*ps;
95e51060f0SSean Hefty 	struct hlist_head	owners;
96e51060f0SSean Hefty 	unsigned short		port;
97e51060f0SSean Hefty };
98e51060f0SSean Hefty 
99e51060f0SSean Hefty /*
100e51060f0SSean Hefty  * Device removal can occur at anytime, so we need extra handling to
101e51060f0SSean Hefty  * serialize notifying the user of device removal with other callbacks.
102e51060f0SSean Hefty  * We do this by disabling removal notification while a callback is in process,
103e51060f0SSean Hefty  * and reporting it after the callback completes.
104e51060f0SSean Hefty  */
105e51060f0SSean Hefty struct rdma_id_private {
106e51060f0SSean Hefty 	struct rdma_cm_id	id;
107e51060f0SSean Hefty 
108e51060f0SSean Hefty 	struct rdma_bind_list	*bind_list;
109e51060f0SSean Hefty 	struct hlist_node	node;
110e51060f0SSean Hefty 	struct list_head	list;
111e51060f0SSean Hefty 	struct list_head	listen_list;
112e51060f0SSean Hefty 	struct cma_device	*cma_dev;
113e51060f0SSean Hefty 
114e51060f0SSean Hefty 	enum cma_state		state;
115e51060f0SSean Hefty 	spinlock_t		lock;
116e51060f0SSean Hefty 	struct completion	comp;
117e51060f0SSean Hefty 	atomic_t		refcount;
118e51060f0SSean Hefty 	wait_queue_head_t	wait_remove;
119e51060f0SSean Hefty 	atomic_t		dev_remove;
120e51060f0SSean Hefty 
121e51060f0SSean Hefty 	int			backlog;
122e51060f0SSean Hefty 	int			timeout_ms;
123e51060f0SSean Hefty 	struct ib_sa_query	*query;
124e51060f0SSean Hefty 	int			query_id;
125e51060f0SSean Hefty 	union {
126e51060f0SSean Hefty 		struct ib_cm_id	*ib;
127e51060f0SSean Hefty 	} cm_id;
128e51060f0SSean Hefty 
129e51060f0SSean Hefty 	u32			seq_num;
130e51060f0SSean Hefty 	u32			qp_num;
131e51060f0SSean Hefty 	enum ib_qp_type		qp_type;
132e51060f0SSean Hefty 	u8			srq;
133e51060f0SSean Hefty };
134e51060f0SSean Hefty 
135e51060f0SSean Hefty struct cma_work {
136e51060f0SSean Hefty 	struct work_struct	work;
137e51060f0SSean Hefty 	struct rdma_id_private	*id;
138e51060f0SSean Hefty 	enum cma_state		old_state;
139e51060f0SSean Hefty 	enum cma_state		new_state;
140e51060f0SSean Hefty 	struct rdma_cm_event	event;
141e51060f0SSean Hefty };
142e51060f0SSean Hefty 
143e51060f0SSean Hefty union cma_ip_addr {
144e51060f0SSean Hefty 	struct in6_addr ip6;
145e51060f0SSean Hefty 	struct {
146e51060f0SSean Hefty 		__u32 pad[3];
147e51060f0SSean Hefty 		__u32 addr;
148e51060f0SSean Hefty 	} ip4;
149e51060f0SSean Hefty };
150e51060f0SSean Hefty 
151e51060f0SSean Hefty struct cma_hdr {
152e51060f0SSean Hefty 	u8 cma_version;
153e51060f0SSean Hefty 	u8 ip_version;	/* IP version: 7:4 */
154e51060f0SSean Hefty 	__u16 port;
155e51060f0SSean Hefty 	union cma_ip_addr src_addr;
156e51060f0SSean Hefty 	union cma_ip_addr dst_addr;
157e51060f0SSean Hefty };
158e51060f0SSean Hefty 
159e51060f0SSean Hefty struct sdp_hh {
160e51060f0SSean Hefty 	u8 bsdh[16];
161e51060f0SSean Hefty 	u8 sdp_version; /* Major version: 7:4 */
162e51060f0SSean Hefty 	u8 ip_version;	/* IP version: 7:4 */
163e51060f0SSean Hefty 	u8 sdp_specific1[10];
164e51060f0SSean Hefty 	__u16 port;
165e51060f0SSean Hefty 	__u16 sdp_specific2;
166e51060f0SSean Hefty 	union cma_ip_addr src_addr;
167e51060f0SSean Hefty 	union cma_ip_addr dst_addr;
168e51060f0SSean Hefty };
169e51060f0SSean Hefty 
170e51060f0SSean Hefty struct sdp_hah {
171e51060f0SSean Hefty 	u8 bsdh[16];
172e51060f0SSean Hefty 	u8 sdp_version;
173e51060f0SSean Hefty };
174e51060f0SSean Hefty 
175e51060f0SSean Hefty #define CMA_VERSION 0x00
176e51060f0SSean Hefty #define SDP_MAJ_VERSION 0x2
177e51060f0SSean Hefty 
178e51060f0SSean Hefty static int cma_comp(struct rdma_id_private *id_priv, enum cma_state comp)
179e51060f0SSean Hefty {
180e51060f0SSean Hefty 	unsigned long flags;
181e51060f0SSean Hefty 	int ret;
182e51060f0SSean Hefty 
183e51060f0SSean Hefty 	spin_lock_irqsave(&id_priv->lock, flags);
184e51060f0SSean Hefty 	ret = (id_priv->state == comp);
185e51060f0SSean Hefty 	spin_unlock_irqrestore(&id_priv->lock, flags);
186e51060f0SSean Hefty 	return ret;
187e51060f0SSean Hefty }
188e51060f0SSean Hefty 
189e51060f0SSean Hefty static int cma_comp_exch(struct rdma_id_private *id_priv,
190e51060f0SSean Hefty 			 enum cma_state comp, enum cma_state exch)
191e51060f0SSean Hefty {
192e51060f0SSean Hefty 	unsigned long flags;
193e51060f0SSean Hefty 	int ret;
194e51060f0SSean Hefty 
195e51060f0SSean Hefty 	spin_lock_irqsave(&id_priv->lock, flags);
196e51060f0SSean Hefty 	if ((ret = (id_priv->state == comp)))
197e51060f0SSean Hefty 		id_priv->state = exch;
198e51060f0SSean Hefty 	spin_unlock_irqrestore(&id_priv->lock, flags);
199e51060f0SSean Hefty 	return ret;
200e51060f0SSean Hefty }
201e51060f0SSean Hefty 
202e51060f0SSean Hefty static enum cma_state cma_exch(struct rdma_id_private *id_priv,
203e51060f0SSean Hefty 			       enum cma_state exch)
204e51060f0SSean Hefty {
205e51060f0SSean Hefty 	unsigned long flags;
206e51060f0SSean Hefty 	enum cma_state old;
207e51060f0SSean Hefty 
208e51060f0SSean Hefty 	spin_lock_irqsave(&id_priv->lock, flags);
209e51060f0SSean Hefty 	old = id_priv->state;
210e51060f0SSean Hefty 	id_priv->state = exch;
211e51060f0SSean Hefty 	spin_unlock_irqrestore(&id_priv->lock, flags);
212e51060f0SSean Hefty 	return old;
213e51060f0SSean Hefty }
214e51060f0SSean Hefty 
215e51060f0SSean Hefty static inline u8 cma_get_ip_ver(struct cma_hdr *hdr)
216e51060f0SSean Hefty {
217e51060f0SSean Hefty 	return hdr->ip_version >> 4;
218e51060f0SSean Hefty }
219e51060f0SSean Hefty 
220e51060f0SSean Hefty static inline void cma_set_ip_ver(struct cma_hdr *hdr, u8 ip_ver)
221e51060f0SSean Hefty {
222e51060f0SSean Hefty 	hdr->ip_version = (ip_ver << 4) | (hdr->ip_version & 0xF);
223e51060f0SSean Hefty }
224e51060f0SSean Hefty 
225e51060f0SSean Hefty static inline u8 sdp_get_majv(u8 sdp_version)
226e51060f0SSean Hefty {
227e51060f0SSean Hefty 	return sdp_version >> 4;
228e51060f0SSean Hefty }
229e51060f0SSean Hefty 
230e51060f0SSean Hefty static inline u8 sdp_get_ip_ver(struct sdp_hh *hh)
231e51060f0SSean Hefty {
232e51060f0SSean Hefty 	return hh->ip_version >> 4;
233e51060f0SSean Hefty }
234e51060f0SSean Hefty 
235e51060f0SSean Hefty static inline void sdp_set_ip_ver(struct sdp_hh *hh, u8 ip_ver)
236e51060f0SSean Hefty {
237e51060f0SSean Hefty 	hh->ip_version = (ip_ver << 4) | (hh->ip_version & 0xF);
238e51060f0SSean Hefty }
239e51060f0SSean Hefty 
240e51060f0SSean Hefty static void cma_attach_to_dev(struct rdma_id_private *id_priv,
241e51060f0SSean Hefty 			      struct cma_device *cma_dev)
242e51060f0SSean Hefty {
243e51060f0SSean Hefty 	atomic_inc(&cma_dev->refcount);
244e51060f0SSean Hefty 	id_priv->cma_dev = cma_dev;
245e51060f0SSean Hefty 	id_priv->id.device = cma_dev->device;
246e51060f0SSean Hefty 	list_add_tail(&id_priv->list, &cma_dev->id_list);
247e51060f0SSean Hefty }
248e51060f0SSean Hefty 
249e51060f0SSean Hefty static inline void cma_deref_dev(struct cma_device *cma_dev)
250e51060f0SSean Hefty {
251e51060f0SSean Hefty 	if (atomic_dec_and_test(&cma_dev->refcount))
252e51060f0SSean Hefty 		complete(&cma_dev->comp);
253e51060f0SSean Hefty }
254e51060f0SSean Hefty 
255e51060f0SSean Hefty static void cma_detach_from_dev(struct rdma_id_private *id_priv)
256e51060f0SSean Hefty {
257e51060f0SSean Hefty 	list_del(&id_priv->list);
258e51060f0SSean Hefty 	cma_deref_dev(id_priv->cma_dev);
259e51060f0SSean Hefty 	id_priv->cma_dev = NULL;
260e51060f0SSean Hefty }
261e51060f0SSean Hefty 
262e51060f0SSean Hefty static int cma_acquire_ib_dev(struct rdma_id_private *id_priv)
263e51060f0SSean Hefty {
264e51060f0SSean Hefty 	struct cma_device *cma_dev;
265e51060f0SSean Hefty 	union ib_gid *gid;
266e51060f0SSean Hefty 	int ret = -ENODEV;
267e51060f0SSean Hefty 
268e51060f0SSean Hefty 	gid = ib_addr_get_sgid(&id_priv->id.route.addr.dev_addr);
269e51060f0SSean Hefty 
270e51060f0SSean Hefty 	mutex_lock(&lock);
271e51060f0SSean Hefty 	list_for_each_entry(cma_dev, &dev_list, list) {
272e51060f0SSean Hefty 		ret = ib_find_cached_gid(cma_dev->device, gid,
273e51060f0SSean Hefty 					 &id_priv->id.port_num, NULL);
274e51060f0SSean Hefty 		if (!ret) {
275e51060f0SSean Hefty 			cma_attach_to_dev(id_priv, cma_dev);
276e51060f0SSean Hefty 			break;
277e51060f0SSean Hefty 		}
278e51060f0SSean Hefty 	}
279e51060f0SSean Hefty 	mutex_unlock(&lock);
280e51060f0SSean Hefty 	return ret;
281e51060f0SSean Hefty }
282e51060f0SSean Hefty 
283e51060f0SSean Hefty static int cma_acquire_dev(struct rdma_id_private *id_priv)
284e51060f0SSean Hefty {
285e51060f0SSean Hefty 	switch (id_priv->id.route.addr.dev_addr.dev_type) {
286e51060f0SSean Hefty 	case IB_NODE_CA:
287e51060f0SSean Hefty 		return cma_acquire_ib_dev(id_priv);
288e51060f0SSean Hefty 	default:
289e51060f0SSean Hefty 		return -ENODEV;
290e51060f0SSean Hefty 	}
291e51060f0SSean Hefty }
292e51060f0SSean Hefty 
293e51060f0SSean Hefty static void cma_deref_id(struct rdma_id_private *id_priv)
294e51060f0SSean Hefty {
295e51060f0SSean Hefty 	if (atomic_dec_and_test(&id_priv->refcount))
296e51060f0SSean Hefty 		complete(&id_priv->comp);
297e51060f0SSean Hefty }
298e51060f0SSean Hefty 
299e51060f0SSean Hefty static void cma_release_remove(struct rdma_id_private *id_priv)
300e51060f0SSean Hefty {
301e51060f0SSean Hefty 	if (atomic_dec_and_test(&id_priv->dev_remove))
302e51060f0SSean Hefty 		wake_up(&id_priv->wait_remove);
303e51060f0SSean Hefty }
304e51060f0SSean Hefty 
305e51060f0SSean Hefty struct rdma_cm_id *rdma_create_id(rdma_cm_event_handler event_handler,
306e51060f0SSean Hefty 				  void *context, enum rdma_port_space ps)
307e51060f0SSean Hefty {
308e51060f0SSean Hefty 	struct rdma_id_private *id_priv;
309e51060f0SSean Hefty 
310e51060f0SSean Hefty 	id_priv = kzalloc(sizeof *id_priv, GFP_KERNEL);
311e51060f0SSean Hefty 	if (!id_priv)
312e51060f0SSean Hefty 		return ERR_PTR(-ENOMEM);
313e51060f0SSean Hefty 
314e51060f0SSean Hefty 	id_priv->state = CMA_IDLE;
315e51060f0SSean Hefty 	id_priv->id.context = context;
316e51060f0SSean Hefty 	id_priv->id.event_handler = event_handler;
317e51060f0SSean Hefty 	id_priv->id.ps = ps;
318e51060f0SSean Hefty 	spin_lock_init(&id_priv->lock);
319e51060f0SSean Hefty 	init_completion(&id_priv->comp);
320e51060f0SSean Hefty 	atomic_set(&id_priv->refcount, 1);
321e51060f0SSean Hefty 	init_waitqueue_head(&id_priv->wait_remove);
322e51060f0SSean Hefty 	atomic_set(&id_priv->dev_remove, 0);
323e51060f0SSean Hefty 	INIT_LIST_HEAD(&id_priv->listen_list);
324e51060f0SSean Hefty 	get_random_bytes(&id_priv->seq_num, sizeof id_priv->seq_num);
325e51060f0SSean Hefty 
326e51060f0SSean Hefty 	return &id_priv->id;
327e51060f0SSean Hefty }
328e51060f0SSean Hefty EXPORT_SYMBOL(rdma_create_id);
329e51060f0SSean Hefty 
330e51060f0SSean Hefty static int cma_init_ib_qp(struct rdma_id_private *id_priv, struct ib_qp *qp)
331e51060f0SSean Hefty {
332e51060f0SSean Hefty 	struct ib_qp_attr qp_attr;
333e51060f0SSean Hefty 	struct rdma_dev_addr *dev_addr;
334e51060f0SSean Hefty 	int ret;
335e51060f0SSean Hefty 
336e51060f0SSean Hefty 	dev_addr = &id_priv->id.route.addr.dev_addr;
337e51060f0SSean Hefty 	ret = ib_find_cached_pkey(id_priv->id.device, id_priv->id.port_num,
338e51060f0SSean Hefty 				  ib_addr_get_pkey(dev_addr),
339e51060f0SSean Hefty 				  &qp_attr.pkey_index);
340e51060f0SSean Hefty 	if (ret)
341e51060f0SSean Hefty 		return ret;
342e51060f0SSean Hefty 
343e51060f0SSean Hefty 	qp_attr.qp_state = IB_QPS_INIT;
344e51060f0SSean Hefty 	qp_attr.qp_access_flags = IB_ACCESS_LOCAL_WRITE;
345e51060f0SSean Hefty 	qp_attr.port_num = id_priv->id.port_num;
346e51060f0SSean Hefty 	return ib_modify_qp(qp, &qp_attr, IB_QP_STATE | IB_QP_ACCESS_FLAGS |
347e51060f0SSean Hefty 					  IB_QP_PKEY_INDEX | IB_QP_PORT);
348e51060f0SSean Hefty }
349e51060f0SSean Hefty 
350e51060f0SSean Hefty int rdma_create_qp(struct rdma_cm_id *id, struct ib_pd *pd,
351e51060f0SSean Hefty 		   struct ib_qp_init_attr *qp_init_attr)
352e51060f0SSean Hefty {
353e51060f0SSean Hefty 	struct rdma_id_private *id_priv;
354e51060f0SSean Hefty 	struct ib_qp *qp;
355e51060f0SSean Hefty 	int ret;
356e51060f0SSean Hefty 
357e51060f0SSean Hefty 	id_priv = container_of(id, struct rdma_id_private, id);
358e51060f0SSean Hefty 	if (id->device != pd->device)
359e51060f0SSean Hefty 		return -EINVAL;
360e51060f0SSean Hefty 
361e51060f0SSean Hefty 	qp = ib_create_qp(pd, qp_init_attr);
362e51060f0SSean Hefty 	if (IS_ERR(qp))
363e51060f0SSean Hefty 		return PTR_ERR(qp);
364e51060f0SSean Hefty 
365e51060f0SSean Hefty 	switch (id->device->node_type) {
366e51060f0SSean Hefty 	case IB_NODE_CA:
367e51060f0SSean Hefty 		ret = cma_init_ib_qp(id_priv, qp);
368e51060f0SSean Hefty 		break;
369e51060f0SSean Hefty 	default:
370e51060f0SSean Hefty 		ret = -ENOSYS;
371e51060f0SSean Hefty 		break;
372e51060f0SSean Hefty 	}
373e51060f0SSean Hefty 
374e51060f0SSean Hefty 	if (ret)
375e51060f0SSean Hefty 		goto err;
376e51060f0SSean Hefty 
377e51060f0SSean Hefty 	id->qp = qp;
378e51060f0SSean Hefty 	id_priv->qp_num = qp->qp_num;
379e51060f0SSean Hefty 	id_priv->qp_type = qp->qp_type;
380e51060f0SSean Hefty 	id_priv->srq = (qp->srq != NULL);
381e51060f0SSean Hefty 	return 0;
382e51060f0SSean Hefty err:
383e51060f0SSean Hefty 	ib_destroy_qp(qp);
384e51060f0SSean Hefty 	return ret;
385e51060f0SSean Hefty }
386e51060f0SSean Hefty EXPORT_SYMBOL(rdma_create_qp);
387e51060f0SSean Hefty 
388e51060f0SSean Hefty void rdma_destroy_qp(struct rdma_cm_id *id)
389e51060f0SSean Hefty {
390e51060f0SSean Hefty 	ib_destroy_qp(id->qp);
391e51060f0SSean Hefty }
392e51060f0SSean Hefty EXPORT_SYMBOL(rdma_destroy_qp);
393e51060f0SSean Hefty 
394e51060f0SSean Hefty static int cma_modify_qp_rtr(struct rdma_cm_id *id)
395e51060f0SSean Hefty {
396e51060f0SSean Hefty 	struct ib_qp_attr qp_attr;
397e51060f0SSean Hefty 	int qp_attr_mask, ret;
398e51060f0SSean Hefty 
399e51060f0SSean Hefty 	if (!id->qp)
400e51060f0SSean Hefty 		return 0;
401e51060f0SSean Hefty 
402e51060f0SSean Hefty 	/* Need to update QP attributes from default values. */
403e51060f0SSean Hefty 	qp_attr.qp_state = IB_QPS_INIT;
404e51060f0SSean Hefty 	ret = rdma_init_qp_attr(id, &qp_attr, &qp_attr_mask);
405e51060f0SSean Hefty 	if (ret)
406e51060f0SSean Hefty 		return ret;
407e51060f0SSean Hefty 
408e51060f0SSean Hefty 	ret = ib_modify_qp(id->qp, &qp_attr, qp_attr_mask);
409e51060f0SSean Hefty 	if (ret)
410e51060f0SSean Hefty 		return ret;
411e51060f0SSean Hefty 
412e51060f0SSean Hefty 	qp_attr.qp_state = IB_QPS_RTR;
413e51060f0SSean Hefty 	ret = rdma_init_qp_attr(id, &qp_attr, &qp_attr_mask);
414e51060f0SSean Hefty 	if (ret)
415e51060f0SSean Hefty 		return ret;
416e51060f0SSean Hefty 
417e51060f0SSean Hefty 	return ib_modify_qp(id->qp, &qp_attr, qp_attr_mask);
418e51060f0SSean Hefty }
419e51060f0SSean Hefty 
420e51060f0SSean Hefty static int cma_modify_qp_rts(struct rdma_cm_id *id)
421e51060f0SSean Hefty {
422e51060f0SSean Hefty 	struct ib_qp_attr qp_attr;
423e51060f0SSean Hefty 	int qp_attr_mask, ret;
424e51060f0SSean Hefty 
425e51060f0SSean Hefty 	if (!id->qp)
426e51060f0SSean Hefty 		return 0;
427e51060f0SSean Hefty 
428e51060f0SSean Hefty 	qp_attr.qp_state = IB_QPS_RTS;
429e51060f0SSean Hefty 	ret = rdma_init_qp_attr(id, &qp_attr, &qp_attr_mask);
430e51060f0SSean Hefty 	if (ret)
431e51060f0SSean Hefty 		return ret;
432e51060f0SSean Hefty 
433e51060f0SSean Hefty 	return ib_modify_qp(id->qp, &qp_attr, qp_attr_mask);
434e51060f0SSean Hefty }
435e51060f0SSean Hefty 
436e51060f0SSean Hefty static int cma_modify_qp_err(struct rdma_cm_id *id)
437e51060f0SSean Hefty {
438e51060f0SSean Hefty 	struct ib_qp_attr qp_attr;
439e51060f0SSean Hefty 
440e51060f0SSean Hefty 	if (!id->qp)
441e51060f0SSean Hefty 		return 0;
442e51060f0SSean Hefty 
443e51060f0SSean Hefty 	qp_attr.qp_state = IB_QPS_ERR;
444e51060f0SSean Hefty 	return ib_modify_qp(id->qp, &qp_attr, IB_QP_STATE);
445e51060f0SSean Hefty }
446e51060f0SSean Hefty 
447e51060f0SSean Hefty int rdma_init_qp_attr(struct rdma_cm_id *id, struct ib_qp_attr *qp_attr,
448e51060f0SSean Hefty 		       int *qp_attr_mask)
449e51060f0SSean Hefty {
450e51060f0SSean Hefty 	struct rdma_id_private *id_priv;
451e51060f0SSean Hefty 	int ret;
452e51060f0SSean Hefty 
453e51060f0SSean Hefty 	id_priv = container_of(id, struct rdma_id_private, id);
454e51060f0SSean Hefty 	switch (id_priv->id.device->node_type) {
455e51060f0SSean Hefty 	case IB_NODE_CA:
456e51060f0SSean Hefty 		ret = ib_cm_init_qp_attr(id_priv->cm_id.ib, qp_attr,
457e51060f0SSean Hefty 					 qp_attr_mask);
458e51060f0SSean Hefty 		if (qp_attr->qp_state == IB_QPS_RTR)
459e51060f0SSean Hefty 			qp_attr->rq_psn = id_priv->seq_num;
460e51060f0SSean Hefty 		break;
461e51060f0SSean Hefty 	default:
462e51060f0SSean Hefty 		ret = -ENOSYS;
463e51060f0SSean Hefty 		break;
464e51060f0SSean Hefty 	}
465e51060f0SSean Hefty 
466e51060f0SSean Hefty 	return ret;
467e51060f0SSean Hefty }
468e51060f0SSean Hefty EXPORT_SYMBOL(rdma_init_qp_attr);
469e51060f0SSean Hefty 
470e51060f0SSean Hefty static inline int cma_zero_addr(struct sockaddr *addr)
471e51060f0SSean Hefty {
472e51060f0SSean Hefty 	struct in6_addr *ip6;
473e51060f0SSean Hefty 
474e51060f0SSean Hefty 	if (addr->sa_family == AF_INET)
475e51060f0SSean Hefty 		return ZERONET(((struct sockaddr_in *) addr)->sin_addr.s_addr);
476e51060f0SSean Hefty 	else {
477e51060f0SSean Hefty 		ip6 = &((struct sockaddr_in6 *) addr)->sin6_addr;
478e51060f0SSean Hefty 		return (ip6->s6_addr32[0] | ip6->s6_addr32[1] |
479*5fd571cbSEric Sesterhenn 			ip6->s6_addr32[2] | ip6->s6_addr32[3]) == 0;
480e51060f0SSean Hefty 	}
481e51060f0SSean Hefty }
482e51060f0SSean Hefty 
483e51060f0SSean Hefty static inline int cma_loopback_addr(struct sockaddr *addr)
484e51060f0SSean Hefty {
485e51060f0SSean Hefty 	return LOOPBACK(((struct sockaddr_in *) addr)->sin_addr.s_addr);
486e51060f0SSean Hefty }
487e51060f0SSean Hefty 
488e51060f0SSean Hefty static inline int cma_any_addr(struct sockaddr *addr)
489e51060f0SSean Hefty {
490e51060f0SSean Hefty 	return cma_zero_addr(addr) || cma_loopback_addr(addr);
491e51060f0SSean Hefty }
492e51060f0SSean Hefty 
493e51060f0SSean Hefty static inline int cma_any_port(struct sockaddr *addr)
494e51060f0SSean Hefty {
495e51060f0SSean Hefty 	return !((struct sockaddr_in *) addr)->sin_port;
496e51060f0SSean Hefty }
497e51060f0SSean Hefty 
498e51060f0SSean Hefty static int cma_get_net_info(void *hdr, enum rdma_port_space ps,
499e51060f0SSean Hefty 			    u8 *ip_ver, __u16 *port,
500e51060f0SSean Hefty 			    union cma_ip_addr **src, union cma_ip_addr **dst)
501e51060f0SSean Hefty {
502e51060f0SSean Hefty 	switch (ps) {
503e51060f0SSean Hefty 	case RDMA_PS_SDP:
504e51060f0SSean Hefty 		if (sdp_get_majv(((struct sdp_hh *) hdr)->sdp_version) !=
505e51060f0SSean Hefty 		    SDP_MAJ_VERSION)
506e51060f0SSean Hefty 			return -EINVAL;
507e51060f0SSean Hefty 
508e51060f0SSean Hefty 		*ip_ver	= sdp_get_ip_ver(hdr);
509e51060f0SSean Hefty 		*port	= ((struct sdp_hh *) hdr)->port;
510e51060f0SSean Hefty 		*src	= &((struct sdp_hh *) hdr)->src_addr;
511e51060f0SSean Hefty 		*dst	= &((struct sdp_hh *) hdr)->dst_addr;
512e51060f0SSean Hefty 		break;
513e51060f0SSean Hefty 	default:
514e51060f0SSean Hefty 		if (((struct cma_hdr *) hdr)->cma_version != CMA_VERSION)
515e51060f0SSean Hefty 			return -EINVAL;
516e51060f0SSean Hefty 
517e51060f0SSean Hefty 		*ip_ver	= cma_get_ip_ver(hdr);
518e51060f0SSean Hefty 		*port	= ((struct cma_hdr *) hdr)->port;
519e51060f0SSean Hefty 		*src	= &((struct cma_hdr *) hdr)->src_addr;
520e51060f0SSean Hefty 		*dst	= &((struct cma_hdr *) hdr)->dst_addr;
521e51060f0SSean Hefty 		break;
522e51060f0SSean Hefty 	}
523e51060f0SSean Hefty 
524e51060f0SSean Hefty 	if (*ip_ver != 4 && *ip_ver != 6)
525e51060f0SSean Hefty 		return -EINVAL;
526e51060f0SSean Hefty 	return 0;
527e51060f0SSean Hefty }
528e51060f0SSean Hefty 
529e51060f0SSean Hefty static void cma_save_net_info(struct rdma_addr *addr,
530e51060f0SSean Hefty 			      struct rdma_addr *listen_addr,
531e51060f0SSean Hefty 			      u8 ip_ver, __u16 port,
532e51060f0SSean Hefty 			      union cma_ip_addr *src, union cma_ip_addr *dst)
533e51060f0SSean Hefty {
534e51060f0SSean Hefty 	struct sockaddr_in *listen4, *ip4;
535e51060f0SSean Hefty 	struct sockaddr_in6 *listen6, *ip6;
536e51060f0SSean Hefty 
537e51060f0SSean Hefty 	switch (ip_ver) {
538e51060f0SSean Hefty 	case 4:
539e51060f0SSean Hefty 		listen4 = (struct sockaddr_in *) &listen_addr->src_addr;
540e51060f0SSean Hefty 		ip4 = (struct sockaddr_in *) &addr->src_addr;
541e51060f0SSean Hefty 		ip4->sin_family = listen4->sin_family;
542e51060f0SSean Hefty 		ip4->sin_addr.s_addr = dst->ip4.addr;
543e51060f0SSean Hefty 		ip4->sin_port = listen4->sin_port;
544e51060f0SSean Hefty 
545e51060f0SSean Hefty 		ip4 = (struct sockaddr_in *) &addr->dst_addr;
546e51060f0SSean Hefty 		ip4->sin_family = listen4->sin_family;
547e51060f0SSean Hefty 		ip4->sin_addr.s_addr = src->ip4.addr;
548e51060f0SSean Hefty 		ip4->sin_port = port;
549e51060f0SSean Hefty 		break;
550e51060f0SSean Hefty 	case 6:
551e51060f0SSean Hefty 		listen6 = (struct sockaddr_in6 *) &listen_addr->src_addr;
552e51060f0SSean Hefty 		ip6 = (struct sockaddr_in6 *) &addr->src_addr;
553e51060f0SSean Hefty 		ip6->sin6_family = listen6->sin6_family;
554e51060f0SSean Hefty 		ip6->sin6_addr = dst->ip6;
555e51060f0SSean Hefty 		ip6->sin6_port = listen6->sin6_port;
556e51060f0SSean Hefty 
557e51060f0SSean Hefty 		ip6 = (struct sockaddr_in6 *) &addr->dst_addr;
558e51060f0SSean Hefty 		ip6->sin6_family = listen6->sin6_family;
559e51060f0SSean Hefty 		ip6->sin6_addr = src->ip6;
560e51060f0SSean Hefty 		ip6->sin6_port = port;
561e51060f0SSean Hefty 		break;
562e51060f0SSean Hefty 	default:
563e51060f0SSean Hefty 		break;
564e51060f0SSean Hefty 	}
565e51060f0SSean Hefty }
566e51060f0SSean Hefty 
567e51060f0SSean Hefty static inline int cma_user_data_offset(enum rdma_port_space ps)
568e51060f0SSean Hefty {
569e51060f0SSean Hefty 	switch (ps) {
570e51060f0SSean Hefty 	case RDMA_PS_SDP:
571e51060f0SSean Hefty 		return 0;
572e51060f0SSean Hefty 	default:
573e51060f0SSean Hefty 		return sizeof(struct cma_hdr);
574e51060f0SSean Hefty 	}
575e51060f0SSean Hefty }
576e51060f0SSean Hefty 
577e51060f0SSean Hefty static int cma_notify_user(struct rdma_id_private *id_priv,
578e51060f0SSean Hefty 			   enum rdma_cm_event_type type, int status,
579e51060f0SSean Hefty 			   void *data, u8 data_len)
580e51060f0SSean Hefty {
581e51060f0SSean Hefty 	struct rdma_cm_event event;
582e51060f0SSean Hefty 
583e51060f0SSean Hefty 	event.event = type;
584e51060f0SSean Hefty 	event.status = status;
585e51060f0SSean Hefty 	event.private_data = data;
586e51060f0SSean Hefty 	event.private_data_len = data_len;
587e51060f0SSean Hefty 
588e51060f0SSean Hefty 	return id_priv->id.event_handler(&id_priv->id, &event);
589e51060f0SSean Hefty }
590e51060f0SSean Hefty 
591e51060f0SSean Hefty static void cma_cancel_route(struct rdma_id_private *id_priv)
592e51060f0SSean Hefty {
593e51060f0SSean Hefty 	switch (id_priv->id.device->node_type) {
594e51060f0SSean Hefty 	case IB_NODE_CA:
595e51060f0SSean Hefty 		if (id_priv->query)
596e51060f0SSean Hefty 			ib_sa_cancel_query(id_priv->query_id, id_priv->query);
597e51060f0SSean Hefty 		break;
598e51060f0SSean Hefty 	default:
599e51060f0SSean Hefty 		break;
600e51060f0SSean Hefty 	}
601e51060f0SSean Hefty }
602e51060f0SSean Hefty 
603e51060f0SSean Hefty static inline int cma_internal_listen(struct rdma_id_private *id_priv)
604e51060f0SSean Hefty {
605e51060f0SSean Hefty 	return (id_priv->state == CMA_LISTEN) && id_priv->cma_dev &&
606e51060f0SSean Hefty 	       cma_any_addr(&id_priv->id.route.addr.src_addr);
607e51060f0SSean Hefty }
608e51060f0SSean Hefty 
609e51060f0SSean Hefty static void cma_destroy_listen(struct rdma_id_private *id_priv)
610e51060f0SSean Hefty {
611e51060f0SSean Hefty 	cma_exch(id_priv, CMA_DESTROYING);
612e51060f0SSean Hefty 
613e51060f0SSean Hefty 	if (id_priv->cma_dev) {
614e51060f0SSean Hefty 		switch (id_priv->id.device->node_type) {
615e51060f0SSean Hefty 		case IB_NODE_CA:
616e51060f0SSean Hefty 	 		if (id_priv->cm_id.ib && !IS_ERR(id_priv->cm_id.ib))
617e51060f0SSean Hefty 				ib_destroy_cm_id(id_priv->cm_id.ib);
618e51060f0SSean Hefty 			break;
619e51060f0SSean Hefty 		default:
620e51060f0SSean Hefty 			break;
621e51060f0SSean Hefty 		}
622e51060f0SSean Hefty 		cma_detach_from_dev(id_priv);
623e51060f0SSean Hefty 	}
624e51060f0SSean Hefty 	list_del(&id_priv->listen_list);
625e51060f0SSean Hefty 
626e51060f0SSean Hefty 	cma_deref_id(id_priv);
627e51060f0SSean Hefty 	wait_for_completion(&id_priv->comp);
628e51060f0SSean Hefty 
629e51060f0SSean Hefty 	kfree(id_priv);
630e51060f0SSean Hefty }
631e51060f0SSean Hefty 
632e51060f0SSean Hefty static void cma_cancel_listens(struct rdma_id_private *id_priv)
633e51060f0SSean Hefty {
634e51060f0SSean Hefty 	struct rdma_id_private *dev_id_priv;
635e51060f0SSean Hefty 
636e51060f0SSean Hefty 	mutex_lock(&lock);
637e51060f0SSean Hefty 	list_del(&id_priv->list);
638e51060f0SSean Hefty 
639e51060f0SSean Hefty 	while (!list_empty(&id_priv->listen_list)) {
640e51060f0SSean Hefty 		dev_id_priv = list_entry(id_priv->listen_list.next,
641e51060f0SSean Hefty 					 struct rdma_id_private, listen_list);
642e51060f0SSean Hefty 		cma_destroy_listen(dev_id_priv);
643e51060f0SSean Hefty 	}
644e51060f0SSean Hefty 	mutex_unlock(&lock);
645e51060f0SSean Hefty }
646e51060f0SSean Hefty 
647e51060f0SSean Hefty static void cma_cancel_operation(struct rdma_id_private *id_priv,
648e51060f0SSean Hefty 				 enum cma_state state)
649e51060f0SSean Hefty {
650e51060f0SSean Hefty 	switch (state) {
651e51060f0SSean Hefty 	case CMA_ADDR_QUERY:
652e51060f0SSean Hefty 		rdma_addr_cancel(&id_priv->id.route.addr.dev_addr);
653e51060f0SSean Hefty 		break;
654e51060f0SSean Hefty 	case CMA_ROUTE_QUERY:
655e51060f0SSean Hefty 		cma_cancel_route(id_priv);
656e51060f0SSean Hefty 		break;
657e51060f0SSean Hefty 	case CMA_LISTEN:
658e51060f0SSean Hefty 		if (cma_any_addr(&id_priv->id.route.addr.src_addr) &&
659e51060f0SSean Hefty 		    !id_priv->cma_dev)
660e51060f0SSean Hefty 			cma_cancel_listens(id_priv);
661e51060f0SSean Hefty 		break;
662e51060f0SSean Hefty 	default:
663e51060f0SSean Hefty 		break;
664e51060f0SSean Hefty 	}
665e51060f0SSean Hefty }
666e51060f0SSean Hefty 
667e51060f0SSean Hefty static void cma_release_port(struct rdma_id_private *id_priv)
668e51060f0SSean Hefty {
669e51060f0SSean Hefty 	struct rdma_bind_list *bind_list = id_priv->bind_list;
670e51060f0SSean Hefty 
671e51060f0SSean Hefty 	if (!bind_list)
672e51060f0SSean Hefty 		return;
673e51060f0SSean Hefty 
674e51060f0SSean Hefty 	mutex_lock(&lock);
675e51060f0SSean Hefty 	hlist_del(&id_priv->node);
676e51060f0SSean Hefty 	if (hlist_empty(&bind_list->owners)) {
677e51060f0SSean Hefty 		idr_remove(bind_list->ps, bind_list->port);
678e51060f0SSean Hefty 		kfree(bind_list);
679e51060f0SSean Hefty 	}
680e51060f0SSean Hefty 	mutex_unlock(&lock);
681e51060f0SSean Hefty }
682e51060f0SSean Hefty 
683e51060f0SSean Hefty void rdma_destroy_id(struct rdma_cm_id *id)
684e51060f0SSean Hefty {
685e51060f0SSean Hefty 	struct rdma_id_private *id_priv;
686e51060f0SSean Hefty 	enum cma_state state;
687e51060f0SSean Hefty 
688e51060f0SSean Hefty 	id_priv = container_of(id, struct rdma_id_private, id);
689e51060f0SSean Hefty 	state = cma_exch(id_priv, CMA_DESTROYING);
690e51060f0SSean Hefty 	cma_cancel_operation(id_priv, state);
691e51060f0SSean Hefty 
692e51060f0SSean Hefty 	if (id_priv->cma_dev) {
693e51060f0SSean Hefty 		switch (id->device->node_type) {
694e51060f0SSean Hefty 		case IB_NODE_CA:
695e51060f0SSean Hefty 	 		if (id_priv->cm_id.ib && !IS_ERR(id_priv->cm_id.ib))
696e51060f0SSean Hefty 				ib_destroy_cm_id(id_priv->cm_id.ib);
697e51060f0SSean Hefty 			break;
698e51060f0SSean Hefty 		default:
699e51060f0SSean Hefty 			break;
700e51060f0SSean Hefty 		}
701e51060f0SSean Hefty 	  	mutex_lock(&lock);
702e51060f0SSean Hefty 		cma_detach_from_dev(id_priv);
703e51060f0SSean Hefty 		mutex_unlock(&lock);
704e51060f0SSean Hefty 	}
705e51060f0SSean Hefty 
706e51060f0SSean Hefty 	cma_release_port(id_priv);
707e51060f0SSean Hefty 	cma_deref_id(id_priv);
708e51060f0SSean Hefty 	wait_for_completion(&id_priv->comp);
709e51060f0SSean Hefty 
710e51060f0SSean Hefty 	kfree(id_priv->id.route.path_rec);
711e51060f0SSean Hefty 	kfree(id_priv);
712e51060f0SSean Hefty }
713e51060f0SSean Hefty EXPORT_SYMBOL(rdma_destroy_id);
714e51060f0SSean Hefty 
715e51060f0SSean Hefty static int cma_rep_recv(struct rdma_id_private *id_priv)
716e51060f0SSean Hefty {
717e51060f0SSean Hefty 	int ret;
718e51060f0SSean Hefty 
719e51060f0SSean Hefty 	ret = cma_modify_qp_rtr(&id_priv->id);
720e51060f0SSean Hefty 	if (ret)
721e51060f0SSean Hefty 		goto reject;
722e51060f0SSean Hefty 
723e51060f0SSean Hefty 	ret = cma_modify_qp_rts(&id_priv->id);
724e51060f0SSean Hefty 	if (ret)
725e51060f0SSean Hefty 		goto reject;
726e51060f0SSean Hefty 
727e51060f0SSean Hefty 	ret = ib_send_cm_rtu(id_priv->cm_id.ib, NULL, 0);
728e51060f0SSean Hefty 	if (ret)
729e51060f0SSean Hefty 		goto reject;
730e51060f0SSean Hefty 
731e51060f0SSean Hefty 	return 0;
732e51060f0SSean Hefty reject:
733e51060f0SSean Hefty 	cma_modify_qp_err(&id_priv->id);
734e51060f0SSean Hefty 	ib_send_cm_rej(id_priv->cm_id.ib, IB_CM_REJ_CONSUMER_DEFINED,
735e51060f0SSean Hefty 		       NULL, 0, NULL, 0);
736e51060f0SSean Hefty 	return ret;
737e51060f0SSean Hefty }
738e51060f0SSean Hefty 
739e51060f0SSean Hefty static int cma_verify_rep(struct rdma_id_private *id_priv, void *data)
740e51060f0SSean Hefty {
741e51060f0SSean Hefty 	if (id_priv->id.ps == RDMA_PS_SDP &&
742e51060f0SSean Hefty 	    sdp_get_majv(((struct sdp_hah *) data)->sdp_version) !=
743e51060f0SSean Hefty 	    SDP_MAJ_VERSION)
744e51060f0SSean Hefty 		return -EINVAL;
745e51060f0SSean Hefty 
746e51060f0SSean Hefty 	return 0;
747e51060f0SSean Hefty }
748e51060f0SSean Hefty 
749e51060f0SSean Hefty static int cma_rtu_recv(struct rdma_id_private *id_priv)
750e51060f0SSean Hefty {
751e51060f0SSean Hefty 	int ret;
752e51060f0SSean Hefty 
753e51060f0SSean Hefty 	ret = cma_modify_qp_rts(&id_priv->id);
754e51060f0SSean Hefty 	if (ret)
755e51060f0SSean Hefty 		goto reject;
756e51060f0SSean Hefty 
757e51060f0SSean Hefty 	return 0;
758e51060f0SSean Hefty reject:
759e51060f0SSean Hefty 	cma_modify_qp_err(&id_priv->id);
760e51060f0SSean Hefty 	ib_send_cm_rej(id_priv->cm_id.ib, IB_CM_REJ_CONSUMER_DEFINED,
761e51060f0SSean Hefty 		       NULL, 0, NULL, 0);
762e51060f0SSean Hefty 	return ret;
763e51060f0SSean Hefty }
764e51060f0SSean Hefty 
765e51060f0SSean Hefty static int cma_ib_handler(struct ib_cm_id *cm_id, struct ib_cm_event *ib_event)
766e51060f0SSean Hefty {
767e51060f0SSean Hefty 	struct rdma_id_private *id_priv = cm_id->context;
768e51060f0SSean Hefty 	enum rdma_cm_event_type event;
769e51060f0SSean Hefty 	u8 private_data_len = 0;
770e51060f0SSean Hefty 	int ret = 0, status = 0;
771e51060f0SSean Hefty 
772e51060f0SSean Hefty 	atomic_inc(&id_priv->dev_remove);
773e51060f0SSean Hefty 	if (!cma_comp(id_priv, CMA_CONNECT))
774e51060f0SSean Hefty 		goto out;
775e51060f0SSean Hefty 
776e51060f0SSean Hefty 	switch (ib_event->event) {
777e51060f0SSean Hefty 	case IB_CM_REQ_ERROR:
778e51060f0SSean Hefty 	case IB_CM_REP_ERROR:
779e51060f0SSean Hefty 		event = RDMA_CM_EVENT_UNREACHABLE;
780e51060f0SSean Hefty 		status = -ETIMEDOUT;
781e51060f0SSean Hefty 		break;
782e51060f0SSean Hefty 	case IB_CM_REP_RECEIVED:
783e51060f0SSean Hefty 		status = cma_verify_rep(id_priv, ib_event->private_data);
784e51060f0SSean Hefty 		if (status)
785e51060f0SSean Hefty 			event = RDMA_CM_EVENT_CONNECT_ERROR;
786e51060f0SSean Hefty 		else if (id_priv->id.qp && id_priv->id.ps != RDMA_PS_SDP) {
787e51060f0SSean Hefty 			status = cma_rep_recv(id_priv);
788e51060f0SSean Hefty 			event = status ? RDMA_CM_EVENT_CONNECT_ERROR :
789e51060f0SSean Hefty 					 RDMA_CM_EVENT_ESTABLISHED;
790e51060f0SSean Hefty 		} else
791e51060f0SSean Hefty 			event = RDMA_CM_EVENT_CONNECT_RESPONSE;
792e51060f0SSean Hefty 		private_data_len = IB_CM_REP_PRIVATE_DATA_SIZE;
793e51060f0SSean Hefty 		break;
794e51060f0SSean Hefty 	case IB_CM_RTU_RECEIVED:
795e51060f0SSean Hefty 		status = cma_rtu_recv(id_priv);
796e51060f0SSean Hefty 		event = status ? RDMA_CM_EVENT_CONNECT_ERROR :
797e51060f0SSean Hefty 				 RDMA_CM_EVENT_ESTABLISHED;
798e51060f0SSean Hefty 		break;
799e51060f0SSean Hefty 	case IB_CM_DREQ_ERROR:
800e51060f0SSean Hefty 		status = -ETIMEDOUT; /* fall through */
801e51060f0SSean Hefty 	case IB_CM_DREQ_RECEIVED:
802e51060f0SSean Hefty 	case IB_CM_DREP_RECEIVED:
803e51060f0SSean Hefty 		if (!cma_comp_exch(id_priv, CMA_CONNECT, CMA_DISCONNECT))
804e51060f0SSean Hefty 			goto out;
805e51060f0SSean Hefty 		event = RDMA_CM_EVENT_DISCONNECTED;
806e51060f0SSean Hefty 		break;
807e51060f0SSean Hefty 	case IB_CM_TIMEWAIT_EXIT:
808e51060f0SSean Hefty 	case IB_CM_MRA_RECEIVED:
809e51060f0SSean Hefty 		/* ignore event */
810e51060f0SSean Hefty 		goto out;
811e51060f0SSean Hefty 	case IB_CM_REJ_RECEIVED:
812e51060f0SSean Hefty 		cma_modify_qp_err(&id_priv->id);
813e51060f0SSean Hefty 		status = ib_event->param.rej_rcvd.reason;
814e51060f0SSean Hefty 		event = RDMA_CM_EVENT_REJECTED;
815e51060f0SSean Hefty 		break;
816e51060f0SSean Hefty 	default:
817e51060f0SSean Hefty 		printk(KERN_ERR "RDMA CMA: unexpected IB CM event: %d",
818e51060f0SSean Hefty 		       ib_event->event);
819e51060f0SSean Hefty 		goto out;
820e51060f0SSean Hefty 	}
821e51060f0SSean Hefty 
822e51060f0SSean Hefty 	ret = cma_notify_user(id_priv, event, status, ib_event->private_data,
823e51060f0SSean Hefty 			      private_data_len);
824e51060f0SSean Hefty 	if (ret) {
825e51060f0SSean Hefty 		/* Destroy the CM ID by returning a non-zero value. */
826e51060f0SSean Hefty 		id_priv->cm_id.ib = NULL;
827e51060f0SSean Hefty 		cma_exch(id_priv, CMA_DESTROYING);
828e51060f0SSean Hefty 		cma_release_remove(id_priv);
829e51060f0SSean Hefty 		rdma_destroy_id(&id_priv->id);
830e51060f0SSean Hefty 		return ret;
831e51060f0SSean Hefty 	}
832e51060f0SSean Hefty out:
833e51060f0SSean Hefty 	cma_release_remove(id_priv);
834e51060f0SSean Hefty 	return ret;
835e51060f0SSean Hefty }
836e51060f0SSean Hefty 
837e51060f0SSean Hefty static struct rdma_id_private *cma_new_id(struct rdma_cm_id *listen_id,
838e51060f0SSean Hefty 					  struct ib_cm_event *ib_event)
839e51060f0SSean Hefty {
840e51060f0SSean Hefty 	struct rdma_id_private *id_priv;
841e51060f0SSean Hefty 	struct rdma_cm_id *id;
842e51060f0SSean Hefty 	struct rdma_route *rt;
843e51060f0SSean Hefty 	union cma_ip_addr *src, *dst;
844e51060f0SSean Hefty 	__u16 port;
845e51060f0SSean Hefty 	u8 ip_ver;
846e51060f0SSean Hefty 
847e51060f0SSean Hefty 	id = rdma_create_id(listen_id->event_handler, listen_id->context,
848e51060f0SSean Hefty 			    listen_id->ps);
849e51060f0SSean Hefty 	if (IS_ERR(id))
850e51060f0SSean Hefty 		return NULL;
851e51060f0SSean Hefty 
852e51060f0SSean Hefty 	rt = &id->route;
853e51060f0SSean Hefty 	rt->num_paths = ib_event->param.req_rcvd.alternate_path ? 2 : 1;
854e51060f0SSean Hefty 	rt->path_rec = kmalloc(sizeof *rt->path_rec * rt->num_paths, GFP_KERNEL);
855e51060f0SSean Hefty 	if (!rt->path_rec)
856e51060f0SSean Hefty 		goto err;
857e51060f0SSean Hefty 
858e51060f0SSean Hefty 	if (cma_get_net_info(ib_event->private_data, listen_id->ps,
859e51060f0SSean Hefty 			     &ip_ver, &port, &src, &dst))
860e51060f0SSean Hefty 		goto err;
861e51060f0SSean Hefty 
862e51060f0SSean Hefty 	cma_save_net_info(&id->route.addr, &listen_id->route.addr,
863e51060f0SSean Hefty 			  ip_ver, port, src, dst);
864e51060f0SSean Hefty 	rt->path_rec[0] = *ib_event->param.req_rcvd.primary_path;
865e51060f0SSean Hefty 	if (rt->num_paths == 2)
866e51060f0SSean Hefty 		rt->path_rec[1] = *ib_event->param.req_rcvd.alternate_path;
867e51060f0SSean Hefty 
868e51060f0SSean Hefty 	ib_addr_set_sgid(&rt->addr.dev_addr, &rt->path_rec[0].sgid);
869e51060f0SSean Hefty 	ib_addr_set_dgid(&rt->addr.dev_addr, &rt->path_rec[0].dgid);
870e51060f0SSean Hefty 	ib_addr_set_pkey(&rt->addr.dev_addr, be16_to_cpu(rt->path_rec[0].pkey));
871e51060f0SSean Hefty 	rt->addr.dev_addr.dev_type = IB_NODE_CA;
872e51060f0SSean Hefty 
873e51060f0SSean Hefty 	id_priv = container_of(id, struct rdma_id_private, id);
874e51060f0SSean Hefty 	id_priv->state = CMA_CONNECT;
875e51060f0SSean Hefty 	return id_priv;
876e51060f0SSean Hefty err:
877e51060f0SSean Hefty 	rdma_destroy_id(id);
878e51060f0SSean Hefty 	return NULL;
879e51060f0SSean Hefty }
880e51060f0SSean Hefty 
881e51060f0SSean Hefty static int cma_req_handler(struct ib_cm_id *cm_id, struct ib_cm_event *ib_event)
882e51060f0SSean Hefty {
883e51060f0SSean Hefty 	struct rdma_id_private *listen_id, *conn_id;
884e51060f0SSean Hefty 	int offset, ret;
885e51060f0SSean Hefty 
886e51060f0SSean Hefty 	listen_id = cm_id->context;
887e51060f0SSean Hefty 	atomic_inc(&listen_id->dev_remove);
888e51060f0SSean Hefty 	if (!cma_comp(listen_id, CMA_LISTEN)) {
889e51060f0SSean Hefty 		ret = -ECONNABORTED;
890e51060f0SSean Hefty 		goto out;
891e51060f0SSean Hefty 	}
892e51060f0SSean Hefty 
893e51060f0SSean Hefty 	conn_id = cma_new_id(&listen_id->id, ib_event);
894e51060f0SSean Hefty 	if (!conn_id) {
895e51060f0SSean Hefty 		ret = -ENOMEM;
896e51060f0SSean Hefty 		goto out;
897e51060f0SSean Hefty 	}
898e51060f0SSean Hefty 
899e51060f0SSean Hefty 	atomic_inc(&conn_id->dev_remove);
900e51060f0SSean Hefty 	ret = cma_acquire_ib_dev(conn_id);
901e51060f0SSean Hefty 	if (ret) {
902e51060f0SSean Hefty 		ret = -ENODEV;
903e51060f0SSean Hefty 		cma_release_remove(conn_id);
904e51060f0SSean Hefty 		rdma_destroy_id(&conn_id->id);
905e51060f0SSean Hefty 		goto out;
906e51060f0SSean Hefty 	}
907e51060f0SSean Hefty 
908e51060f0SSean Hefty 	conn_id->cm_id.ib = cm_id;
909e51060f0SSean Hefty 	cm_id->context = conn_id;
910e51060f0SSean Hefty 	cm_id->cm_handler = cma_ib_handler;
911e51060f0SSean Hefty 
912e51060f0SSean Hefty 	offset = cma_user_data_offset(listen_id->id.ps);
913e51060f0SSean Hefty 	ret = cma_notify_user(conn_id, RDMA_CM_EVENT_CONNECT_REQUEST, 0,
914e51060f0SSean Hefty 			      ib_event->private_data + offset,
915e51060f0SSean Hefty 			      IB_CM_REQ_PRIVATE_DATA_SIZE - offset);
916e51060f0SSean Hefty 	if (ret) {
917e51060f0SSean Hefty 		/* Destroy the CM ID by returning a non-zero value. */
918e51060f0SSean Hefty 		conn_id->cm_id.ib = NULL;
919e51060f0SSean Hefty 		cma_exch(conn_id, CMA_DESTROYING);
920e51060f0SSean Hefty 		cma_release_remove(conn_id);
921e51060f0SSean Hefty 		rdma_destroy_id(&conn_id->id);
922e51060f0SSean Hefty 	}
923e51060f0SSean Hefty out:
924e51060f0SSean Hefty 	cma_release_remove(listen_id);
925e51060f0SSean Hefty 	return ret;
926e51060f0SSean Hefty }
927e51060f0SSean Hefty 
928e51060f0SSean Hefty static __be64 cma_get_service_id(enum rdma_port_space ps, struct sockaddr *addr)
929e51060f0SSean Hefty {
930e51060f0SSean Hefty 	return cpu_to_be64(((u64)ps << 16) +
931e51060f0SSean Hefty 	       be16_to_cpu(((struct sockaddr_in *) addr)->sin_port));
932e51060f0SSean Hefty }
933e51060f0SSean Hefty 
934e51060f0SSean Hefty static void cma_set_compare_data(enum rdma_port_space ps, struct sockaddr *addr,
935e51060f0SSean Hefty 				 struct ib_cm_compare_data *compare)
936e51060f0SSean Hefty {
937e51060f0SSean Hefty 	struct cma_hdr *cma_data, *cma_mask;
938e51060f0SSean Hefty 	struct sdp_hh *sdp_data, *sdp_mask;
939e51060f0SSean Hefty 	__u32 ip4_addr;
940e51060f0SSean Hefty 	struct in6_addr ip6_addr;
941e51060f0SSean Hefty 
942e51060f0SSean Hefty 	memset(compare, 0, sizeof *compare);
943e51060f0SSean Hefty 	cma_data = (void *) compare->data;
944e51060f0SSean Hefty 	cma_mask = (void *) compare->mask;
945e51060f0SSean Hefty 	sdp_data = (void *) compare->data;
946e51060f0SSean Hefty 	sdp_mask = (void *) compare->mask;
947e51060f0SSean Hefty 
948e51060f0SSean Hefty 	switch (addr->sa_family) {
949e51060f0SSean Hefty 	case AF_INET:
950e51060f0SSean Hefty 		ip4_addr = ((struct sockaddr_in *) addr)->sin_addr.s_addr;
951e51060f0SSean Hefty 		if (ps == RDMA_PS_SDP) {
952e51060f0SSean Hefty 			sdp_set_ip_ver(sdp_data, 4);
953e51060f0SSean Hefty 			sdp_set_ip_ver(sdp_mask, 0xF);
954e51060f0SSean Hefty 			sdp_data->dst_addr.ip4.addr = ip4_addr;
955e51060f0SSean Hefty 			sdp_mask->dst_addr.ip4.addr = ~0;
956e51060f0SSean Hefty 		} else {
957e51060f0SSean Hefty 			cma_set_ip_ver(cma_data, 4);
958e51060f0SSean Hefty 			cma_set_ip_ver(cma_mask, 0xF);
959e51060f0SSean Hefty 			cma_data->dst_addr.ip4.addr = ip4_addr;
960e51060f0SSean Hefty 			cma_mask->dst_addr.ip4.addr = ~0;
961e51060f0SSean Hefty 		}
962e51060f0SSean Hefty 		break;
963e51060f0SSean Hefty 	case AF_INET6:
964e51060f0SSean Hefty 		ip6_addr = ((struct sockaddr_in6 *) addr)->sin6_addr;
965e51060f0SSean Hefty 		if (ps == RDMA_PS_SDP) {
966e51060f0SSean Hefty 			sdp_set_ip_ver(sdp_data, 6);
967e51060f0SSean Hefty 			sdp_set_ip_ver(sdp_mask, 0xF);
968e51060f0SSean Hefty 			sdp_data->dst_addr.ip6 = ip6_addr;
969e51060f0SSean Hefty 			memset(&sdp_mask->dst_addr.ip6, 0xFF,
970e51060f0SSean Hefty 			       sizeof sdp_mask->dst_addr.ip6);
971e51060f0SSean Hefty 		} else {
972e51060f0SSean Hefty 			cma_set_ip_ver(cma_data, 6);
973e51060f0SSean Hefty 			cma_set_ip_ver(cma_mask, 0xF);
974e51060f0SSean Hefty 			cma_data->dst_addr.ip6 = ip6_addr;
975e51060f0SSean Hefty 			memset(&cma_mask->dst_addr.ip6, 0xFF,
976e51060f0SSean Hefty 			       sizeof cma_mask->dst_addr.ip6);
977e51060f0SSean Hefty 		}
978e51060f0SSean Hefty 		break;
979e51060f0SSean Hefty 	default:
980e51060f0SSean Hefty 		break;
981e51060f0SSean Hefty 	}
982e51060f0SSean Hefty }
983e51060f0SSean Hefty 
984e51060f0SSean Hefty static int cma_ib_listen(struct rdma_id_private *id_priv)
985e51060f0SSean Hefty {
986e51060f0SSean Hefty 	struct ib_cm_compare_data compare_data;
987e51060f0SSean Hefty 	struct sockaddr *addr;
988e51060f0SSean Hefty 	__be64 svc_id;
989e51060f0SSean Hefty 	int ret;
990e51060f0SSean Hefty 
991e51060f0SSean Hefty 	id_priv->cm_id.ib = ib_create_cm_id(id_priv->id.device, cma_req_handler,
992e51060f0SSean Hefty 					    id_priv);
993e51060f0SSean Hefty 	if (IS_ERR(id_priv->cm_id.ib))
994e51060f0SSean Hefty 		return PTR_ERR(id_priv->cm_id.ib);
995e51060f0SSean Hefty 
996e51060f0SSean Hefty 	addr = &id_priv->id.route.addr.src_addr;
997e51060f0SSean Hefty 	svc_id = cma_get_service_id(id_priv->id.ps, addr);
998e51060f0SSean Hefty 	if (cma_any_addr(addr))
999e51060f0SSean Hefty 		ret = ib_cm_listen(id_priv->cm_id.ib, svc_id, 0, NULL);
1000e51060f0SSean Hefty 	else {
1001e51060f0SSean Hefty 		cma_set_compare_data(id_priv->id.ps, addr, &compare_data);
1002e51060f0SSean Hefty 		ret = ib_cm_listen(id_priv->cm_id.ib, svc_id, 0, &compare_data);
1003e51060f0SSean Hefty 	}
1004e51060f0SSean Hefty 
1005e51060f0SSean Hefty 	if (ret) {
1006e51060f0SSean Hefty 		ib_destroy_cm_id(id_priv->cm_id.ib);
1007e51060f0SSean Hefty 		id_priv->cm_id.ib = NULL;
1008e51060f0SSean Hefty 	}
1009e51060f0SSean Hefty 
1010e51060f0SSean Hefty 	return ret;
1011e51060f0SSean Hefty }
1012e51060f0SSean Hefty 
1013e51060f0SSean Hefty static int cma_listen_handler(struct rdma_cm_id *id,
1014e51060f0SSean Hefty 			      struct rdma_cm_event *event)
1015e51060f0SSean Hefty {
1016e51060f0SSean Hefty 	struct rdma_id_private *id_priv = id->context;
1017e51060f0SSean Hefty 
1018e51060f0SSean Hefty 	id->context = id_priv->id.context;
1019e51060f0SSean Hefty 	id->event_handler = id_priv->id.event_handler;
1020e51060f0SSean Hefty 	return id_priv->id.event_handler(id, event);
1021e51060f0SSean Hefty }
1022e51060f0SSean Hefty 
1023e51060f0SSean Hefty static void cma_listen_on_dev(struct rdma_id_private *id_priv,
1024e51060f0SSean Hefty 			      struct cma_device *cma_dev)
1025e51060f0SSean Hefty {
1026e51060f0SSean Hefty 	struct rdma_id_private *dev_id_priv;
1027e51060f0SSean Hefty 	struct rdma_cm_id *id;
1028e51060f0SSean Hefty 	int ret;
1029e51060f0SSean Hefty 
1030e51060f0SSean Hefty 	id = rdma_create_id(cma_listen_handler, id_priv, id_priv->id.ps);
1031e51060f0SSean Hefty 	if (IS_ERR(id))
1032e51060f0SSean Hefty 		return;
1033e51060f0SSean Hefty 
1034e51060f0SSean Hefty 	dev_id_priv = container_of(id, struct rdma_id_private, id);
1035e51060f0SSean Hefty 
1036e51060f0SSean Hefty 	dev_id_priv->state = CMA_ADDR_BOUND;
1037e51060f0SSean Hefty 	memcpy(&id->route.addr.src_addr, &id_priv->id.route.addr.src_addr,
1038e51060f0SSean Hefty 	       ip_addr_size(&id_priv->id.route.addr.src_addr));
1039e51060f0SSean Hefty 
1040e51060f0SSean Hefty 	cma_attach_to_dev(dev_id_priv, cma_dev);
1041e51060f0SSean Hefty 	list_add_tail(&dev_id_priv->listen_list, &id_priv->listen_list);
1042e51060f0SSean Hefty 
1043e51060f0SSean Hefty 	ret = rdma_listen(id, id_priv->backlog);
1044e51060f0SSean Hefty 	if (ret)
1045e51060f0SSean Hefty 		goto err;
1046e51060f0SSean Hefty 
1047e51060f0SSean Hefty 	return;
1048e51060f0SSean Hefty err:
1049e51060f0SSean Hefty 	cma_destroy_listen(dev_id_priv);
1050e51060f0SSean Hefty }
1051e51060f0SSean Hefty 
1052e51060f0SSean Hefty static void cma_listen_on_all(struct rdma_id_private *id_priv)
1053e51060f0SSean Hefty {
1054e51060f0SSean Hefty 	struct cma_device *cma_dev;
1055e51060f0SSean Hefty 
1056e51060f0SSean Hefty 	mutex_lock(&lock);
1057e51060f0SSean Hefty 	list_add_tail(&id_priv->list, &listen_any_list);
1058e51060f0SSean Hefty 	list_for_each_entry(cma_dev, &dev_list, list)
1059e51060f0SSean Hefty 		cma_listen_on_dev(id_priv, cma_dev);
1060e51060f0SSean Hefty 	mutex_unlock(&lock);
1061e51060f0SSean Hefty }
1062e51060f0SSean Hefty 
1063e51060f0SSean Hefty static int cma_bind_any(struct rdma_cm_id *id, sa_family_t af)
1064e51060f0SSean Hefty {
1065e51060f0SSean Hefty 	struct sockaddr_in addr_in;
1066e51060f0SSean Hefty 
1067e51060f0SSean Hefty 	memset(&addr_in, 0, sizeof addr_in);
1068e51060f0SSean Hefty 	addr_in.sin_family = af;
1069e51060f0SSean Hefty 	return rdma_bind_addr(id, (struct sockaddr *) &addr_in);
1070e51060f0SSean Hefty }
1071e51060f0SSean Hefty 
1072e51060f0SSean Hefty int rdma_listen(struct rdma_cm_id *id, int backlog)
1073e51060f0SSean Hefty {
1074e51060f0SSean Hefty 	struct rdma_id_private *id_priv;
1075e51060f0SSean Hefty 	int ret;
1076e51060f0SSean Hefty 
1077e51060f0SSean Hefty 	id_priv = container_of(id, struct rdma_id_private, id);
1078e51060f0SSean Hefty 	if (id_priv->state == CMA_IDLE) {
1079e51060f0SSean Hefty 		ret = cma_bind_any(id, AF_INET);
1080e51060f0SSean Hefty 		if (ret)
1081e51060f0SSean Hefty 			return ret;
1082e51060f0SSean Hefty 	}
1083e51060f0SSean Hefty 
1084e51060f0SSean Hefty 	if (!cma_comp_exch(id_priv, CMA_ADDR_BOUND, CMA_LISTEN))
1085e51060f0SSean Hefty 		return -EINVAL;
1086e51060f0SSean Hefty 
1087e51060f0SSean Hefty 	id_priv->backlog = backlog;
1088e51060f0SSean Hefty 	if (id->device) {
1089e51060f0SSean Hefty 		switch (id->device->node_type) {
1090e51060f0SSean Hefty 		case IB_NODE_CA:
1091e51060f0SSean Hefty 			ret = cma_ib_listen(id_priv);
1092e51060f0SSean Hefty 			if (ret)
1093e51060f0SSean Hefty 				goto err;
1094e51060f0SSean Hefty 			break;
1095e51060f0SSean Hefty 		default:
1096e51060f0SSean Hefty 			ret = -ENOSYS;
1097e51060f0SSean Hefty 			goto err;
1098e51060f0SSean Hefty 		}
1099e51060f0SSean Hefty 	} else
1100e51060f0SSean Hefty 		cma_listen_on_all(id_priv);
1101e51060f0SSean Hefty 
1102e51060f0SSean Hefty 	return 0;
1103e51060f0SSean Hefty err:
1104e51060f0SSean Hefty 	id_priv->backlog = 0;
1105e51060f0SSean Hefty 	cma_comp_exch(id_priv, CMA_LISTEN, CMA_ADDR_BOUND);
1106e51060f0SSean Hefty 	return ret;
1107e51060f0SSean Hefty }
1108e51060f0SSean Hefty EXPORT_SYMBOL(rdma_listen);
1109e51060f0SSean Hefty 
1110e51060f0SSean Hefty static void cma_query_handler(int status, struct ib_sa_path_rec *path_rec,
1111e51060f0SSean Hefty 			      void *context)
1112e51060f0SSean Hefty {
1113e51060f0SSean Hefty 	struct cma_work *work = context;
1114e51060f0SSean Hefty 	struct rdma_route *route;
1115e51060f0SSean Hefty 
1116e51060f0SSean Hefty 	route = &work->id->id.route;
1117e51060f0SSean Hefty 
1118e51060f0SSean Hefty 	if (!status) {
1119e51060f0SSean Hefty 		route->num_paths = 1;
1120e51060f0SSean Hefty 		*route->path_rec = *path_rec;
1121e51060f0SSean Hefty 	} else {
1122e51060f0SSean Hefty 		work->old_state = CMA_ROUTE_QUERY;
1123e51060f0SSean Hefty 		work->new_state = CMA_ADDR_RESOLVED;
1124e51060f0SSean Hefty 		work->event.event = RDMA_CM_EVENT_ROUTE_ERROR;
1125e51060f0SSean Hefty 	}
1126e51060f0SSean Hefty 
1127e51060f0SSean Hefty 	queue_work(cma_wq, &work->work);
1128e51060f0SSean Hefty }
1129e51060f0SSean Hefty 
1130e51060f0SSean Hefty static int cma_query_ib_route(struct rdma_id_private *id_priv, int timeout_ms,
1131e51060f0SSean Hefty 			      struct cma_work *work)
1132e51060f0SSean Hefty {
1133e51060f0SSean Hefty 	struct rdma_dev_addr *addr = &id_priv->id.route.addr.dev_addr;
1134e51060f0SSean Hefty 	struct ib_sa_path_rec path_rec;
1135e51060f0SSean Hefty 
1136e51060f0SSean Hefty 	memset(&path_rec, 0, sizeof path_rec);
1137e51060f0SSean Hefty 	path_rec.sgid = *ib_addr_get_sgid(addr);
1138e51060f0SSean Hefty 	path_rec.dgid = *ib_addr_get_dgid(addr);
1139e51060f0SSean Hefty 	path_rec.pkey = cpu_to_be16(ib_addr_get_pkey(addr));
1140e51060f0SSean Hefty 	path_rec.numb_path = 1;
1141e51060f0SSean Hefty 
1142e51060f0SSean Hefty 	id_priv->query_id = ib_sa_path_rec_get(id_priv->id.device,
1143e51060f0SSean Hefty 				id_priv->id.port_num, &path_rec,
1144e51060f0SSean Hefty 				IB_SA_PATH_REC_DGID | IB_SA_PATH_REC_SGID |
1145e51060f0SSean Hefty 				IB_SA_PATH_REC_PKEY | IB_SA_PATH_REC_NUMB_PATH,
1146e51060f0SSean Hefty 				timeout_ms, GFP_KERNEL,
1147e51060f0SSean Hefty 				cma_query_handler, work, &id_priv->query);
1148e51060f0SSean Hefty 
1149e51060f0SSean Hefty 	return (id_priv->query_id < 0) ? id_priv->query_id : 0;
1150e51060f0SSean Hefty }
1151e51060f0SSean Hefty 
1152e51060f0SSean Hefty static void cma_work_handler(void *data)
1153e51060f0SSean Hefty {
1154e51060f0SSean Hefty 	struct cma_work *work = data;
1155e51060f0SSean Hefty 	struct rdma_id_private *id_priv = work->id;
1156e51060f0SSean Hefty 	int destroy = 0;
1157e51060f0SSean Hefty 
1158e51060f0SSean Hefty 	atomic_inc(&id_priv->dev_remove);
1159e51060f0SSean Hefty 	if (!cma_comp_exch(id_priv, work->old_state, work->new_state))
1160e51060f0SSean Hefty 		goto out;
1161e51060f0SSean Hefty 
1162e51060f0SSean Hefty 	if (id_priv->id.event_handler(&id_priv->id, &work->event)) {
1163e51060f0SSean Hefty 		cma_exch(id_priv, CMA_DESTROYING);
1164e51060f0SSean Hefty 		destroy = 1;
1165e51060f0SSean Hefty 	}
1166e51060f0SSean Hefty out:
1167e51060f0SSean Hefty 	cma_release_remove(id_priv);
1168e51060f0SSean Hefty 	cma_deref_id(id_priv);
1169e51060f0SSean Hefty 	if (destroy)
1170e51060f0SSean Hefty 		rdma_destroy_id(&id_priv->id);
1171e51060f0SSean Hefty 	kfree(work);
1172e51060f0SSean Hefty }
1173e51060f0SSean Hefty 
1174e51060f0SSean Hefty static int cma_resolve_ib_route(struct rdma_id_private *id_priv, int timeout_ms)
1175e51060f0SSean Hefty {
1176e51060f0SSean Hefty 	struct rdma_route *route = &id_priv->id.route;
1177e51060f0SSean Hefty 	struct cma_work *work;
1178e51060f0SSean Hefty 	int ret;
1179e51060f0SSean Hefty 
1180e51060f0SSean Hefty 	work = kzalloc(sizeof *work, GFP_KERNEL);
1181e51060f0SSean Hefty 	if (!work)
1182e51060f0SSean Hefty 		return -ENOMEM;
1183e51060f0SSean Hefty 
1184e51060f0SSean Hefty 	work->id = id_priv;
1185e51060f0SSean Hefty 	INIT_WORK(&work->work, cma_work_handler, work);
1186e51060f0SSean Hefty 	work->old_state = CMA_ROUTE_QUERY;
1187e51060f0SSean Hefty 	work->new_state = CMA_ROUTE_RESOLVED;
1188e51060f0SSean Hefty 	work->event.event = RDMA_CM_EVENT_ROUTE_RESOLVED;
1189e51060f0SSean Hefty 
1190e51060f0SSean Hefty 	route->path_rec = kmalloc(sizeof *route->path_rec, GFP_KERNEL);
1191e51060f0SSean Hefty 	if (!route->path_rec) {
1192e51060f0SSean Hefty 		ret = -ENOMEM;
1193e51060f0SSean Hefty 		goto err1;
1194e51060f0SSean Hefty 	}
1195e51060f0SSean Hefty 
1196e51060f0SSean Hefty 	ret = cma_query_ib_route(id_priv, timeout_ms, work);
1197e51060f0SSean Hefty 	if (ret)
1198e51060f0SSean Hefty 		goto err2;
1199e51060f0SSean Hefty 
1200e51060f0SSean Hefty 	return 0;
1201e51060f0SSean Hefty err2:
1202e51060f0SSean Hefty 	kfree(route->path_rec);
1203e51060f0SSean Hefty 	route->path_rec = NULL;
1204e51060f0SSean Hefty err1:
1205e51060f0SSean Hefty 	kfree(work);
1206e51060f0SSean Hefty 	return ret;
1207e51060f0SSean Hefty }
1208e51060f0SSean Hefty 
1209e51060f0SSean Hefty int rdma_set_ib_paths(struct rdma_cm_id *id,
1210e51060f0SSean Hefty 		      struct ib_sa_path_rec *path_rec, int num_paths)
1211e51060f0SSean Hefty {
1212e51060f0SSean Hefty 	struct rdma_id_private *id_priv;
1213e51060f0SSean Hefty 	int ret;
1214e51060f0SSean Hefty 
1215e51060f0SSean Hefty 	id_priv = container_of(id, struct rdma_id_private, id);
1216e51060f0SSean Hefty 	if (!cma_comp_exch(id_priv, CMA_ADDR_RESOLVED, CMA_ROUTE_RESOLVED))
1217e51060f0SSean Hefty 		return -EINVAL;
1218e51060f0SSean Hefty 
1219e51060f0SSean Hefty 	id->route.path_rec = kmalloc(sizeof *path_rec * num_paths, GFP_KERNEL);
1220e51060f0SSean Hefty 	if (!id->route.path_rec) {
1221e51060f0SSean Hefty 		ret = -ENOMEM;
1222e51060f0SSean Hefty 		goto err;
1223e51060f0SSean Hefty 	}
1224e51060f0SSean Hefty 
1225e51060f0SSean Hefty 	memcpy(id->route.path_rec, path_rec, sizeof *path_rec * num_paths);
1226e51060f0SSean Hefty 	return 0;
1227e51060f0SSean Hefty err:
1228e51060f0SSean Hefty 	cma_comp_exch(id_priv, CMA_ROUTE_RESOLVED, CMA_ADDR_RESOLVED);
1229e51060f0SSean Hefty 	return ret;
1230e51060f0SSean Hefty }
1231e51060f0SSean Hefty EXPORT_SYMBOL(rdma_set_ib_paths);
1232e51060f0SSean Hefty 
1233e51060f0SSean Hefty int rdma_resolve_route(struct rdma_cm_id *id, int timeout_ms)
1234e51060f0SSean Hefty {
1235e51060f0SSean Hefty 	struct rdma_id_private *id_priv;
1236e51060f0SSean Hefty 	int ret;
1237e51060f0SSean Hefty 
1238e51060f0SSean Hefty 	id_priv = container_of(id, struct rdma_id_private, id);
1239e51060f0SSean Hefty 	if (!cma_comp_exch(id_priv, CMA_ADDR_RESOLVED, CMA_ROUTE_QUERY))
1240e51060f0SSean Hefty 		return -EINVAL;
1241e51060f0SSean Hefty 
1242e51060f0SSean Hefty 	atomic_inc(&id_priv->refcount);
1243e51060f0SSean Hefty 	switch (id->device->node_type) {
1244e51060f0SSean Hefty 	case IB_NODE_CA:
1245e51060f0SSean Hefty 		ret = cma_resolve_ib_route(id_priv, timeout_ms);
1246e51060f0SSean Hefty 		break;
1247e51060f0SSean Hefty 	default:
1248e51060f0SSean Hefty 		ret = -ENOSYS;
1249e51060f0SSean Hefty 		break;
1250e51060f0SSean Hefty 	}
1251e51060f0SSean Hefty 	if (ret)
1252e51060f0SSean Hefty 		goto err;
1253e51060f0SSean Hefty 
1254e51060f0SSean Hefty 	return 0;
1255e51060f0SSean Hefty err:
1256e51060f0SSean Hefty 	cma_comp_exch(id_priv, CMA_ROUTE_QUERY, CMA_ADDR_RESOLVED);
1257e51060f0SSean Hefty 	cma_deref_id(id_priv);
1258e51060f0SSean Hefty 	return ret;
1259e51060f0SSean Hefty }
1260e51060f0SSean Hefty EXPORT_SYMBOL(rdma_resolve_route);
1261e51060f0SSean Hefty 
1262e51060f0SSean Hefty static int cma_bind_loopback(struct rdma_id_private *id_priv)
1263e51060f0SSean Hefty {
1264e51060f0SSean Hefty 	struct cma_device *cma_dev;
1265e51060f0SSean Hefty 	struct ib_port_attr port_attr;
1266e51060f0SSean Hefty 	union ib_gid *gid;
1267e51060f0SSean Hefty 	u16 pkey;
1268e51060f0SSean Hefty 	int ret;
1269e51060f0SSean Hefty 	u8 p;
1270e51060f0SSean Hefty 
1271e51060f0SSean Hefty 	mutex_lock(&lock);
1272e51060f0SSean Hefty 	list_for_each_entry(cma_dev, &dev_list, list)
1273e51060f0SSean Hefty 		for (p = 1; p <= cma_dev->device->phys_port_cnt; ++p)
1274e51060f0SSean Hefty 			if (!ib_query_port (cma_dev->device, p, &port_attr) &&
1275e51060f0SSean Hefty 			    port_attr.state == IB_PORT_ACTIVE)
1276e51060f0SSean Hefty 				goto port_found;
1277e51060f0SSean Hefty 
1278e51060f0SSean Hefty 	if (!list_empty(&dev_list)) {
1279e51060f0SSean Hefty 		p = 1;
1280e51060f0SSean Hefty 		cma_dev = list_entry(dev_list.next, struct cma_device, list);
1281e51060f0SSean Hefty 	} else {
1282e51060f0SSean Hefty 		ret = -ENODEV;
1283e51060f0SSean Hefty 		goto out;
1284e51060f0SSean Hefty 	}
1285e51060f0SSean Hefty 
1286e51060f0SSean Hefty port_found:
1287e51060f0SSean Hefty 	gid = ib_addr_get_sgid(&id_priv->id.route.addr.dev_addr);
1288e51060f0SSean Hefty 	ret = ib_get_cached_gid(cma_dev->device, p, 0, gid);
1289e51060f0SSean Hefty 	if (ret)
1290e51060f0SSean Hefty 		goto out;
1291e51060f0SSean Hefty 
1292e51060f0SSean Hefty 	ret = ib_get_cached_pkey(cma_dev->device, p, 0, &pkey);
1293e51060f0SSean Hefty 	if (ret)
1294e51060f0SSean Hefty 		goto out;
1295e51060f0SSean Hefty 
1296e51060f0SSean Hefty 	ib_addr_set_pkey(&id_priv->id.route.addr.dev_addr, pkey);
1297e51060f0SSean Hefty 	id_priv->id.port_num = p;
1298e51060f0SSean Hefty 	cma_attach_to_dev(id_priv, cma_dev);
1299e51060f0SSean Hefty out:
1300e51060f0SSean Hefty 	mutex_unlock(&lock);
1301e51060f0SSean Hefty 	return ret;
1302e51060f0SSean Hefty }
1303e51060f0SSean Hefty 
1304e51060f0SSean Hefty static void addr_handler(int status, struct sockaddr *src_addr,
1305e51060f0SSean Hefty 			 struct rdma_dev_addr *dev_addr, void *context)
1306e51060f0SSean Hefty {
1307e51060f0SSean Hefty 	struct rdma_id_private *id_priv = context;
1308e51060f0SSean Hefty 	enum rdma_cm_event_type event;
1309e51060f0SSean Hefty 
1310e51060f0SSean Hefty 	atomic_inc(&id_priv->dev_remove);
1311e51060f0SSean Hefty 	if (!id_priv->cma_dev && !status)
1312e51060f0SSean Hefty 		status = cma_acquire_dev(id_priv);
1313e51060f0SSean Hefty 
1314e51060f0SSean Hefty 	if (status) {
1315e51060f0SSean Hefty 		if (!cma_comp_exch(id_priv, CMA_ADDR_QUERY, CMA_ADDR_BOUND))
1316e51060f0SSean Hefty 			goto out;
1317e51060f0SSean Hefty 		event = RDMA_CM_EVENT_ADDR_ERROR;
1318e51060f0SSean Hefty 	} else {
1319e51060f0SSean Hefty 		if (!cma_comp_exch(id_priv, CMA_ADDR_QUERY, CMA_ADDR_RESOLVED))
1320e51060f0SSean Hefty 			goto out;
1321e51060f0SSean Hefty 		memcpy(&id_priv->id.route.addr.src_addr, src_addr,
1322e51060f0SSean Hefty 		       ip_addr_size(src_addr));
1323e51060f0SSean Hefty 		event = RDMA_CM_EVENT_ADDR_RESOLVED;
1324e51060f0SSean Hefty 	}
1325e51060f0SSean Hefty 
1326e51060f0SSean Hefty 	if (cma_notify_user(id_priv, event, status, NULL, 0)) {
1327e51060f0SSean Hefty 		cma_exch(id_priv, CMA_DESTROYING);
1328e51060f0SSean Hefty 		cma_release_remove(id_priv);
1329e51060f0SSean Hefty 		cma_deref_id(id_priv);
1330e51060f0SSean Hefty 		rdma_destroy_id(&id_priv->id);
1331e51060f0SSean Hefty 		return;
1332e51060f0SSean Hefty 	}
1333e51060f0SSean Hefty out:
1334e51060f0SSean Hefty 	cma_release_remove(id_priv);
1335e51060f0SSean Hefty 	cma_deref_id(id_priv);
1336e51060f0SSean Hefty }
1337e51060f0SSean Hefty 
1338e51060f0SSean Hefty static int cma_resolve_loopback(struct rdma_id_private *id_priv)
1339e51060f0SSean Hefty {
1340e51060f0SSean Hefty 	struct cma_work *work;
1341e51060f0SSean Hefty 	struct sockaddr_in *src_in, *dst_in;
1342e51060f0SSean Hefty 	int ret;
1343e51060f0SSean Hefty 
1344e51060f0SSean Hefty 	work = kzalloc(sizeof *work, GFP_KERNEL);
1345e51060f0SSean Hefty 	if (!work)
1346e51060f0SSean Hefty 		return -ENOMEM;
1347e51060f0SSean Hefty 
1348e51060f0SSean Hefty 	if (!id_priv->cma_dev) {
1349e51060f0SSean Hefty 		ret = cma_bind_loopback(id_priv);
1350e51060f0SSean Hefty 		if (ret)
1351e51060f0SSean Hefty 			goto err;
1352e51060f0SSean Hefty 	}
1353e51060f0SSean Hefty 
1354e51060f0SSean Hefty 	ib_addr_set_dgid(&id_priv->id.route.addr.dev_addr,
1355e51060f0SSean Hefty 			 ib_addr_get_sgid(&id_priv->id.route.addr.dev_addr));
1356e51060f0SSean Hefty 
1357e51060f0SSean Hefty 	if (cma_zero_addr(&id_priv->id.route.addr.src_addr)) {
1358e51060f0SSean Hefty 		src_in = (struct sockaddr_in *)&id_priv->id.route.addr.src_addr;
1359e51060f0SSean Hefty 		dst_in = (struct sockaddr_in *)&id_priv->id.route.addr.dst_addr;
1360e51060f0SSean Hefty 		src_in->sin_family = dst_in->sin_family;
1361e51060f0SSean Hefty 		src_in->sin_addr.s_addr = dst_in->sin_addr.s_addr;
1362e51060f0SSean Hefty 	}
1363e51060f0SSean Hefty 
1364e51060f0SSean Hefty 	work->id = id_priv;
1365e51060f0SSean Hefty 	INIT_WORK(&work->work, cma_work_handler, work);
1366e51060f0SSean Hefty 	work->old_state = CMA_ADDR_QUERY;
1367e51060f0SSean Hefty 	work->new_state = CMA_ADDR_RESOLVED;
1368e51060f0SSean Hefty 	work->event.event = RDMA_CM_EVENT_ADDR_RESOLVED;
1369e51060f0SSean Hefty 	queue_work(cma_wq, &work->work);
1370e51060f0SSean Hefty 	return 0;
1371e51060f0SSean Hefty err:
1372e51060f0SSean Hefty 	kfree(work);
1373e51060f0SSean Hefty 	return ret;
1374e51060f0SSean Hefty }
1375e51060f0SSean Hefty 
1376e51060f0SSean Hefty static int cma_bind_addr(struct rdma_cm_id *id, struct sockaddr *src_addr,
1377e51060f0SSean Hefty 			 struct sockaddr *dst_addr)
1378e51060f0SSean Hefty {
1379e51060f0SSean Hefty 	if (src_addr && src_addr->sa_family)
1380e51060f0SSean Hefty 		return rdma_bind_addr(id, src_addr);
1381e51060f0SSean Hefty 	else
1382e51060f0SSean Hefty 		return cma_bind_any(id, dst_addr->sa_family);
1383e51060f0SSean Hefty }
1384e51060f0SSean Hefty 
1385e51060f0SSean Hefty int rdma_resolve_addr(struct rdma_cm_id *id, struct sockaddr *src_addr,
1386e51060f0SSean Hefty 		      struct sockaddr *dst_addr, int timeout_ms)
1387e51060f0SSean Hefty {
1388e51060f0SSean Hefty 	struct rdma_id_private *id_priv;
1389e51060f0SSean Hefty 	int ret;
1390e51060f0SSean Hefty 
1391e51060f0SSean Hefty 	id_priv = container_of(id, struct rdma_id_private, id);
1392e51060f0SSean Hefty 	if (id_priv->state == CMA_IDLE) {
1393e51060f0SSean Hefty 		ret = cma_bind_addr(id, src_addr, dst_addr);
1394e51060f0SSean Hefty 		if (ret)
1395e51060f0SSean Hefty 			return ret;
1396e51060f0SSean Hefty 	}
1397e51060f0SSean Hefty 
1398e51060f0SSean Hefty 	if (!cma_comp_exch(id_priv, CMA_ADDR_BOUND, CMA_ADDR_QUERY))
1399e51060f0SSean Hefty 		return -EINVAL;
1400e51060f0SSean Hefty 
1401e51060f0SSean Hefty 	atomic_inc(&id_priv->refcount);
1402e51060f0SSean Hefty 	memcpy(&id->route.addr.dst_addr, dst_addr, ip_addr_size(dst_addr));
1403e51060f0SSean Hefty 	if (cma_any_addr(dst_addr))
1404e51060f0SSean Hefty 		ret = cma_resolve_loopback(id_priv);
1405e51060f0SSean Hefty 	else
1406e51060f0SSean Hefty 		ret = rdma_resolve_ip(&id->route.addr.src_addr, dst_addr,
1407e51060f0SSean Hefty 				      &id->route.addr.dev_addr,
1408e51060f0SSean Hefty 				      timeout_ms, addr_handler, id_priv);
1409e51060f0SSean Hefty 	if (ret)
1410e51060f0SSean Hefty 		goto err;
1411e51060f0SSean Hefty 
1412e51060f0SSean Hefty 	return 0;
1413e51060f0SSean Hefty err:
1414e51060f0SSean Hefty 	cma_comp_exch(id_priv, CMA_ADDR_QUERY, CMA_ADDR_BOUND);
1415e51060f0SSean Hefty 	cma_deref_id(id_priv);
1416e51060f0SSean Hefty 	return ret;
1417e51060f0SSean Hefty }
1418e51060f0SSean Hefty EXPORT_SYMBOL(rdma_resolve_addr);
1419e51060f0SSean Hefty 
1420e51060f0SSean Hefty static void cma_bind_port(struct rdma_bind_list *bind_list,
1421e51060f0SSean Hefty 			  struct rdma_id_private *id_priv)
1422e51060f0SSean Hefty {
1423e51060f0SSean Hefty 	struct sockaddr_in *sin;
1424e51060f0SSean Hefty 
1425e51060f0SSean Hefty 	sin = (struct sockaddr_in *) &id_priv->id.route.addr.src_addr;
1426e51060f0SSean Hefty 	sin->sin_port = htons(bind_list->port);
1427e51060f0SSean Hefty 	id_priv->bind_list = bind_list;
1428e51060f0SSean Hefty 	hlist_add_head(&id_priv->node, &bind_list->owners);
1429e51060f0SSean Hefty }
1430e51060f0SSean Hefty 
1431e51060f0SSean Hefty static int cma_alloc_port(struct idr *ps, struct rdma_id_private *id_priv,
1432e51060f0SSean Hefty 			  unsigned short snum)
1433e51060f0SSean Hefty {
1434e51060f0SSean Hefty 	struct rdma_bind_list *bind_list;
1435e51060f0SSean Hefty 	int port, start, ret;
1436e51060f0SSean Hefty 
1437e51060f0SSean Hefty 	bind_list = kzalloc(sizeof *bind_list, GFP_KERNEL);
1438e51060f0SSean Hefty 	if (!bind_list)
1439e51060f0SSean Hefty 		return -ENOMEM;
1440e51060f0SSean Hefty 
1441e51060f0SSean Hefty 	start = snum ? snum : sysctl_local_port_range[0];
1442e51060f0SSean Hefty 
1443e51060f0SSean Hefty 	do {
1444e51060f0SSean Hefty 		ret = idr_get_new_above(ps, bind_list, start, &port);
1445e51060f0SSean Hefty 	} while ((ret == -EAGAIN) && idr_pre_get(ps, GFP_KERNEL));
1446e51060f0SSean Hefty 
1447e51060f0SSean Hefty 	if (ret)
1448e51060f0SSean Hefty 		goto err;
1449e51060f0SSean Hefty 
1450e51060f0SSean Hefty 	if ((snum && port != snum) ||
1451e51060f0SSean Hefty 	    (!snum && port > sysctl_local_port_range[1])) {
1452e51060f0SSean Hefty 		idr_remove(ps, port);
1453e51060f0SSean Hefty 		ret = -EADDRNOTAVAIL;
1454e51060f0SSean Hefty 		goto err;
1455e51060f0SSean Hefty 	}
1456e51060f0SSean Hefty 
1457e51060f0SSean Hefty 	bind_list->ps = ps;
1458e51060f0SSean Hefty 	bind_list->port = (unsigned short) port;
1459e51060f0SSean Hefty 	cma_bind_port(bind_list, id_priv);
1460e51060f0SSean Hefty 	return 0;
1461e51060f0SSean Hefty err:
1462e51060f0SSean Hefty 	kfree(bind_list);
1463e51060f0SSean Hefty 	return ret;
1464e51060f0SSean Hefty }
1465e51060f0SSean Hefty 
1466e51060f0SSean Hefty static int cma_use_port(struct idr *ps, struct rdma_id_private *id_priv)
1467e51060f0SSean Hefty {
1468e51060f0SSean Hefty 	struct rdma_id_private *cur_id;
1469e51060f0SSean Hefty 	struct sockaddr_in *sin, *cur_sin;
1470e51060f0SSean Hefty 	struct rdma_bind_list *bind_list;
1471e51060f0SSean Hefty 	struct hlist_node *node;
1472e51060f0SSean Hefty 	unsigned short snum;
1473e51060f0SSean Hefty 
1474e51060f0SSean Hefty 	sin = (struct sockaddr_in *) &id_priv->id.route.addr.src_addr;
1475e51060f0SSean Hefty 	snum = ntohs(sin->sin_port);
1476e51060f0SSean Hefty 	if (snum < PROT_SOCK && !capable(CAP_NET_BIND_SERVICE))
1477e51060f0SSean Hefty 		return -EACCES;
1478e51060f0SSean Hefty 
1479e51060f0SSean Hefty 	bind_list = idr_find(ps, snum);
1480e51060f0SSean Hefty 	if (!bind_list)
1481e51060f0SSean Hefty 		return cma_alloc_port(ps, id_priv, snum);
1482e51060f0SSean Hefty 
1483e51060f0SSean Hefty 	/*
1484e51060f0SSean Hefty 	 * We don't support binding to any address if anyone is bound to
1485e51060f0SSean Hefty 	 * a specific address on the same port.
1486e51060f0SSean Hefty 	 */
1487e51060f0SSean Hefty 	if (cma_any_addr(&id_priv->id.route.addr.src_addr))
1488e51060f0SSean Hefty 		return -EADDRNOTAVAIL;
1489e51060f0SSean Hefty 
1490e51060f0SSean Hefty 	hlist_for_each_entry(cur_id, node, &bind_list->owners, node) {
1491e51060f0SSean Hefty 		if (cma_any_addr(&cur_id->id.route.addr.src_addr))
1492e51060f0SSean Hefty 			return -EADDRNOTAVAIL;
1493e51060f0SSean Hefty 
1494e51060f0SSean Hefty 		cur_sin = (struct sockaddr_in *) &cur_id->id.route.addr.src_addr;
1495e51060f0SSean Hefty 		if (sin->sin_addr.s_addr == cur_sin->sin_addr.s_addr)
1496e51060f0SSean Hefty 			return -EADDRINUSE;
1497e51060f0SSean Hefty 	}
1498e51060f0SSean Hefty 
1499e51060f0SSean Hefty 	cma_bind_port(bind_list, id_priv);
1500e51060f0SSean Hefty 	return 0;
1501e51060f0SSean Hefty }
1502e51060f0SSean Hefty 
1503e51060f0SSean Hefty static int cma_get_port(struct rdma_id_private *id_priv)
1504e51060f0SSean Hefty {
1505e51060f0SSean Hefty 	struct idr *ps;
1506e51060f0SSean Hefty 	int ret;
1507e51060f0SSean Hefty 
1508e51060f0SSean Hefty 	switch (id_priv->id.ps) {
1509e51060f0SSean Hefty 	case RDMA_PS_SDP:
1510e51060f0SSean Hefty 		ps = &sdp_ps;
1511e51060f0SSean Hefty 		break;
1512e51060f0SSean Hefty 	case RDMA_PS_TCP:
1513e51060f0SSean Hefty 		ps = &tcp_ps;
1514e51060f0SSean Hefty 		break;
1515e51060f0SSean Hefty 	default:
1516e51060f0SSean Hefty 		return -EPROTONOSUPPORT;
1517e51060f0SSean Hefty 	}
1518e51060f0SSean Hefty 
1519e51060f0SSean Hefty 	mutex_lock(&lock);
1520e51060f0SSean Hefty 	if (cma_any_port(&id_priv->id.route.addr.src_addr))
1521e51060f0SSean Hefty 		ret = cma_alloc_port(ps, id_priv, 0);
1522e51060f0SSean Hefty 	else
1523e51060f0SSean Hefty 		ret = cma_use_port(ps, id_priv);
1524e51060f0SSean Hefty 	mutex_unlock(&lock);
1525e51060f0SSean Hefty 
1526e51060f0SSean Hefty 	return ret;
1527e51060f0SSean Hefty }
1528e51060f0SSean Hefty 
1529e51060f0SSean Hefty int rdma_bind_addr(struct rdma_cm_id *id, struct sockaddr *addr)
1530e51060f0SSean Hefty {
1531e51060f0SSean Hefty 	struct rdma_id_private *id_priv;
1532e51060f0SSean Hefty 	int ret;
1533e51060f0SSean Hefty 
1534e51060f0SSean Hefty 	if (addr->sa_family != AF_INET)
1535e51060f0SSean Hefty 		return -EAFNOSUPPORT;
1536e51060f0SSean Hefty 
1537e51060f0SSean Hefty 	id_priv = container_of(id, struct rdma_id_private, id);
1538e51060f0SSean Hefty 	if (!cma_comp_exch(id_priv, CMA_IDLE, CMA_ADDR_BOUND))
1539e51060f0SSean Hefty 		return -EINVAL;
1540e51060f0SSean Hefty 
1541e51060f0SSean Hefty 	if (!cma_any_addr(addr)) {
1542e51060f0SSean Hefty 		ret = rdma_translate_ip(addr, &id->route.addr.dev_addr);
1543e51060f0SSean Hefty 		if (!ret)
1544e51060f0SSean Hefty 			ret = cma_acquire_dev(id_priv);
1545e51060f0SSean Hefty 		if (ret)
1546e51060f0SSean Hefty 			goto err;
1547e51060f0SSean Hefty 	}
1548e51060f0SSean Hefty 
1549e51060f0SSean Hefty 	memcpy(&id->route.addr.src_addr, addr, ip_addr_size(addr));
1550e51060f0SSean Hefty 	ret = cma_get_port(id_priv);
1551e51060f0SSean Hefty 	if (ret)
1552e51060f0SSean Hefty 		goto err;
1553e51060f0SSean Hefty 
1554e51060f0SSean Hefty 	return 0;
1555e51060f0SSean Hefty err:
1556e51060f0SSean Hefty 	cma_comp_exch(id_priv, CMA_ADDR_BOUND, CMA_IDLE);
1557e51060f0SSean Hefty 	return ret;
1558e51060f0SSean Hefty }
1559e51060f0SSean Hefty EXPORT_SYMBOL(rdma_bind_addr);
1560e51060f0SSean Hefty 
1561e51060f0SSean Hefty static int cma_format_hdr(void *hdr, enum rdma_port_space ps,
1562e51060f0SSean Hefty 			  struct rdma_route *route)
1563e51060f0SSean Hefty {
1564e51060f0SSean Hefty 	struct sockaddr_in *src4, *dst4;
1565e51060f0SSean Hefty 	struct cma_hdr *cma_hdr;
1566e51060f0SSean Hefty 	struct sdp_hh *sdp_hdr;
1567e51060f0SSean Hefty 
1568e51060f0SSean Hefty 	src4 = (struct sockaddr_in *) &route->addr.src_addr;
1569e51060f0SSean Hefty 	dst4 = (struct sockaddr_in *) &route->addr.dst_addr;
1570e51060f0SSean Hefty 
1571e51060f0SSean Hefty 	switch (ps) {
1572e51060f0SSean Hefty 	case RDMA_PS_SDP:
1573e51060f0SSean Hefty 		sdp_hdr = hdr;
1574e51060f0SSean Hefty 		if (sdp_get_majv(sdp_hdr->sdp_version) != SDP_MAJ_VERSION)
1575e51060f0SSean Hefty 			return -EINVAL;
1576e51060f0SSean Hefty 		sdp_set_ip_ver(sdp_hdr, 4);
1577e51060f0SSean Hefty 		sdp_hdr->src_addr.ip4.addr = src4->sin_addr.s_addr;
1578e51060f0SSean Hefty 		sdp_hdr->dst_addr.ip4.addr = dst4->sin_addr.s_addr;
1579e51060f0SSean Hefty 		sdp_hdr->port = src4->sin_port;
1580e51060f0SSean Hefty 		break;
1581e51060f0SSean Hefty 	default:
1582e51060f0SSean Hefty 		cma_hdr = hdr;
1583e51060f0SSean Hefty 		cma_hdr->cma_version = CMA_VERSION;
1584e51060f0SSean Hefty 		cma_set_ip_ver(cma_hdr, 4);
1585e51060f0SSean Hefty 		cma_hdr->src_addr.ip4.addr = src4->sin_addr.s_addr;
1586e51060f0SSean Hefty 		cma_hdr->dst_addr.ip4.addr = dst4->sin_addr.s_addr;
1587e51060f0SSean Hefty 		cma_hdr->port = src4->sin_port;
1588e51060f0SSean Hefty 		break;
1589e51060f0SSean Hefty 	}
1590e51060f0SSean Hefty 	return 0;
1591e51060f0SSean Hefty }
1592e51060f0SSean Hefty 
1593e51060f0SSean Hefty static int cma_connect_ib(struct rdma_id_private *id_priv,
1594e51060f0SSean Hefty 			  struct rdma_conn_param *conn_param)
1595e51060f0SSean Hefty {
1596e51060f0SSean Hefty 	struct ib_cm_req_param req;
1597e51060f0SSean Hefty 	struct rdma_route *route;
1598e51060f0SSean Hefty 	void *private_data;
1599e51060f0SSean Hefty 	int offset, ret;
1600e51060f0SSean Hefty 
1601e51060f0SSean Hefty 	memset(&req, 0, sizeof req);
1602e51060f0SSean Hefty 	offset = cma_user_data_offset(id_priv->id.ps);
1603e51060f0SSean Hefty 	req.private_data_len = offset + conn_param->private_data_len;
1604e51060f0SSean Hefty 	private_data = kzalloc(req.private_data_len, GFP_ATOMIC);
1605e51060f0SSean Hefty 	if (!private_data)
1606e51060f0SSean Hefty 		return -ENOMEM;
1607e51060f0SSean Hefty 
1608e51060f0SSean Hefty 	if (conn_param->private_data && conn_param->private_data_len)
1609e51060f0SSean Hefty 		memcpy(private_data + offset, conn_param->private_data,
1610e51060f0SSean Hefty 		       conn_param->private_data_len);
1611e51060f0SSean Hefty 
1612e51060f0SSean Hefty 	id_priv->cm_id.ib = ib_create_cm_id(id_priv->id.device, cma_ib_handler,
1613e51060f0SSean Hefty 					    id_priv);
1614e51060f0SSean Hefty 	if (IS_ERR(id_priv->cm_id.ib)) {
1615e51060f0SSean Hefty 		ret = PTR_ERR(id_priv->cm_id.ib);
1616e51060f0SSean Hefty 		goto out;
1617e51060f0SSean Hefty 	}
1618e51060f0SSean Hefty 
1619e51060f0SSean Hefty 	route = &id_priv->id.route;
1620e51060f0SSean Hefty 	ret = cma_format_hdr(private_data, id_priv->id.ps, route);
1621e51060f0SSean Hefty 	if (ret)
1622e51060f0SSean Hefty 		goto out;
1623e51060f0SSean Hefty 	req.private_data = private_data;
1624e51060f0SSean Hefty 
1625e51060f0SSean Hefty 	req.primary_path = &route->path_rec[0];
1626e51060f0SSean Hefty 	if (route->num_paths == 2)
1627e51060f0SSean Hefty 		req.alternate_path = &route->path_rec[1];
1628e51060f0SSean Hefty 
1629e51060f0SSean Hefty 	req.service_id = cma_get_service_id(id_priv->id.ps,
1630e51060f0SSean Hefty 					    &route->addr.dst_addr);
1631e51060f0SSean Hefty 	req.qp_num = id_priv->qp_num;
1632e51060f0SSean Hefty 	req.qp_type = id_priv->qp_type;
1633e51060f0SSean Hefty 	req.starting_psn = id_priv->seq_num;
1634e51060f0SSean Hefty 	req.responder_resources = conn_param->responder_resources;
1635e51060f0SSean Hefty 	req.initiator_depth = conn_param->initiator_depth;
1636e51060f0SSean Hefty 	req.flow_control = conn_param->flow_control;
1637e51060f0SSean Hefty 	req.retry_count = conn_param->retry_count;
1638e51060f0SSean Hefty 	req.rnr_retry_count = conn_param->rnr_retry_count;
1639e51060f0SSean Hefty 	req.remote_cm_response_timeout = CMA_CM_RESPONSE_TIMEOUT;
1640e51060f0SSean Hefty 	req.local_cm_response_timeout = CMA_CM_RESPONSE_TIMEOUT;
1641e51060f0SSean Hefty 	req.max_cm_retries = CMA_MAX_CM_RETRIES;
1642e51060f0SSean Hefty 	req.srq = id_priv->srq ? 1 : 0;
1643e51060f0SSean Hefty 
1644e51060f0SSean Hefty 	ret = ib_send_cm_req(id_priv->cm_id.ib, &req);
1645e51060f0SSean Hefty out:
1646e51060f0SSean Hefty 	kfree(private_data);
1647e51060f0SSean Hefty 	return ret;
1648e51060f0SSean Hefty }
1649e51060f0SSean Hefty 
1650e51060f0SSean Hefty int rdma_connect(struct rdma_cm_id *id, struct rdma_conn_param *conn_param)
1651e51060f0SSean Hefty {
1652e51060f0SSean Hefty 	struct rdma_id_private *id_priv;
1653e51060f0SSean Hefty 	int ret;
1654e51060f0SSean Hefty 
1655e51060f0SSean Hefty 	id_priv = container_of(id, struct rdma_id_private, id);
1656e51060f0SSean Hefty 	if (!cma_comp_exch(id_priv, CMA_ROUTE_RESOLVED, CMA_CONNECT))
1657e51060f0SSean Hefty 		return -EINVAL;
1658e51060f0SSean Hefty 
1659e51060f0SSean Hefty 	if (!id->qp) {
1660e51060f0SSean Hefty 		id_priv->qp_num = conn_param->qp_num;
1661e51060f0SSean Hefty 		id_priv->qp_type = conn_param->qp_type;
1662e51060f0SSean Hefty 		id_priv->srq = conn_param->srq;
1663e51060f0SSean Hefty 	}
1664e51060f0SSean Hefty 
1665e51060f0SSean Hefty 	switch (id->device->node_type) {
1666e51060f0SSean Hefty 	case IB_NODE_CA:
1667e51060f0SSean Hefty 		ret = cma_connect_ib(id_priv, conn_param);
1668e51060f0SSean Hefty 		break;
1669e51060f0SSean Hefty 	default:
1670e51060f0SSean Hefty 		ret = -ENOSYS;
1671e51060f0SSean Hefty 		break;
1672e51060f0SSean Hefty 	}
1673e51060f0SSean Hefty 	if (ret)
1674e51060f0SSean Hefty 		goto err;
1675e51060f0SSean Hefty 
1676e51060f0SSean Hefty 	return 0;
1677e51060f0SSean Hefty err:
1678e51060f0SSean Hefty 	cma_comp_exch(id_priv, CMA_CONNECT, CMA_ROUTE_RESOLVED);
1679e51060f0SSean Hefty 	return ret;
1680e51060f0SSean Hefty }
1681e51060f0SSean Hefty EXPORT_SYMBOL(rdma_connect);
1682e51060f0SSean Hefty 
1683e51060f0SSean Hefty static int cma_accept_ib(struct rdma_id_private *id_priv,
1684e51060f0SSean Hefty 			 struct rdma_conn_param *conn_param)
1685e51060f0SSean Hefty {
1686e51060f0SSean Hefty 	struct ib_cm_rep_param rep;
1687e51060f0SSean Hefty 	int ret;
1688e51060f0SSean Hefty 
1689e51060f0SSean Hefty 	ret = cma_modify_qp_rtr(&id_priv->id);
1690e51060f0SSean Hefty 	if (ret)
1691e51060f0SSean Hefty 		return ret;
1692e51060f0SSean Hefty 
1693e51060f0SSean Hefty 	memset(&rep, 0, sizeof rep);
1694e51060f0SSean Hefty 	rep.qp_num = id_priv->qp_num;
1695e51060f0SSean Hefty 	rep.starting_psn = id_priv->seq_num;
1696e51060f0SSean Hefty 	rep.private_data = conn_param->private_data;
1697e51060f0SSean Hefty 	rep.private_data_len = conn_param->private_data_len;
1698e51060f0SSean Hefty 	rep.responder_resources = conn_param->responder_resources;
1699e51060f0SSean Hefty 	rep.initiator_depth = conn_param->initiator_depth;
1700e51060f0SSean Hefty 	rep.target_ack_delay = CMA_CM_RESPONSE_TIMEOUT;
1701e51060f0SSean Hefty 	rep.failover_accepted = 0;
1702e51060f0SSean Hefty 	rep.flow_control = conn_param->flow_control;
1703e51060f0SSean Hefty 	rep.rnr_retry_count = conn_param->rnr_retry_count;
1704e51060f0SSean Hefty 	rep.srq = id_priv->srq ? 1 : 0;
1705e51060f0SSean Hefty 
1706e51060f0SSean Hefty 	return ib_send_cm_rep(id_priv->cm_id.ib, &rep);
1707e51060f0SSean Hefty }
1708e51060f0SSean Hefty 
1709e51060f0SSean Hefty int rdma_accept(struct rdma_cm_id *id, struct rdma_conn_param *conn_param)
1710e51060f0SSean Hefty {
1711e51060f0SSean Hefty 	struct rdma_id_private *id_priv;
1712e51060f0SSean Hefty 	int ret;
1713e51060f0SSean Hefty 
1714e51060f0SSean Hefty 	id_priv = container_of(id, struct rdma_id_private, id);
1715e51060f0SSean Hefty 	if (!cma_comp(id_priv, CMA_CONNECT))
1716e51060f0SSean Hefty 		return -EINVAL;
1717e51060f0SSean Hefty 
1718e51060f0SSean Hefty 	if (!id->qp && conn_param) {
1719e51060f0SSean Hefty 		id_priv->qp_num = conn_param->qp_num;
1720e51060f0SSean Hefty 		id_priv->qp_type = conn_param->qp_type;
1721e51060f0SSean Hefty 		id_priv->srq = conn_param->srq;
1722e51060f0SSean Hefty 	}
1723e51060f0SSean Hefty 
1724e51060f0SSean Hefty 	switch (id->device->node_type) {
1725e51060f0SSean Hefty 	case IB_NODE_CA:
1726e51060f0SSean Hefty 		if (conn_param)
1727e51060f0SSean Hefty 			ret = cma_accept_ib(id_priv, conn_param);
1728e51060f0SSean Hefty 		else
1729e51060f0SSean Hefty 			ret = cma_rep_recv(id_priv);
1730e51060f0SSean Hefty 		break;
1731e51060f0SSean Hefty 	default:
1732e51060f0SSean Hefty 		ret = -ENOSYS;
1733e51060f0SSean Hefty 		break;
1734e51060f0SSean Hefty 	}
1735e51060f0SSean Hefty 
1736e51060f0SSean Hefty 	if (ret)
1737e51060f0SSean Hefty 		goto reject;
1738e51060f0SSean Hefty 
1739e51060f0SSean Hefty 	return 0;
1740e51060f0SSean Hefty reject:
1741e51060f0SSean Hefty 	cma_modify_qp_err(id);
1742e51060f0SSean Hefty 	rdma_reject(id, NULL, 0);
1743e51060f0SSean Hefty 	return ret;
1744e51060f0SSean Hefty }
1745e51060f0SSean Hefty EXPORT_SYMBOL(rdma_accept);
1746e51060f0SSean Hefty 
1747e51060f0SSean Hefty int rdma_reject(struct rdma_cm_id *id, const void *private_data,
1748e51060f0SSean Hefty 		u8 private_data_len)
1749e51060f0SSean Hefty {
1750e51060f0SSean Hefty 	struct rdma_id_private *id_priv;
1751e51060f0SSean Hefty 	int ret;
1752e51060f0SSean Hefty 
1753e51060f0SSean Hefty 	id_priv = container_of(id, struct rdma_id_private, id);
1754e51060f0SSean Hefty 	if (!cma_comp(id_priv, CMA_CONNECT))
1755e51060f0SSean Hefty 		return -EINVAL;
1756e51060f0SSean Hefty 
1757e51060f0SSean Hefty 	switch (id->device->node_type) {
1758e51060f0SSean Hefty 	case IB_NODE_CA:
1759e51060f0SSean Hefty 		ret = ib_send_cm_rej(id_priv->cm_id.ib,
1760e51060f0SSean Hefty 				     IB_CM_REJ_CONSUMER_DEFINED, NULL, 0,
1761e51060f0SSean Hefty 				     private_data, private_data_len);
1762e51060f0SSean Hefty 		break;
1763e51060f0SSean Hefty 	default:
1764e51060f0SSean Hefty 		ret = -ENOSYS;
1765e51060f0SSean Hefty 		break;
1766e51060f0SSean Hefty 	}
1767e51060f0SSean Hefty 	return ret;
1768e51060f0SSean Hefty }
1769e51060f0SSean Hefty EXPORT_SYMBOL(rdma_reject);
1770e51060f0SSean Hefty 
1771e51060f0SSean Hefty int rdma_disconnect(struct rdma_cm_id *id)
1772e51060f0SSean Hefty {
1773e51060f0SSean Hefty 	struct rdma_id_private *id_priv;
1774e51060f0SSean Hefty 	int ret;
1775e51060f0SSean Hefty 
1776e51060f0SSean Hefty 	id_priv = container_of(id, struct rdma_id_private, id);
1777e51060f0SSean Hefty 	if (!cma_comp(id_priv, CMA_CONNECT) &&
1778e51060f0SSean Hefty 	    !cma_comp(id_priv, CMA_DISCONNECT))
1779e51060f0SSean Hefty 		return -EINVAL;
1780e51060f0SSean Hefty 
1781e51060f0SSean Hefty 	ret = cma_modify_qp_err(id);
1782e51060f0SSean Hefty 	if (ret)
1783e51060f0SSean Hefty 		goto out;
1784e51060f0SSean Hefty 
1785e51060f0SSean Hefty 	switch (id->device->node_type) {
1786e51060f0SSean Hefty 	case IB_NODE_CA:
1787e51060f0SSean Hefty 		/* Initiate or respond to a disconnect. */
1788e51060f0SSean Hefty 		if (ib_send_cm_dreq(id_priv->cm_id.ib, NULL, 0))
1789e51060f0SSean Hefty 			ib_send_cm_drep(id_priv->cm_id.ib, NULL, 0);
1790e51060f0SSean Hefty 		break;
1791e51060f0SSean Hefty 	default:
1792e51060f0SSean Hefty 		break;
1793e51060f0SSean Hefty 	}
1794e51060f0SSean Hefty out:
1795e51060f0SSean Hefty 	return ret;
1796e51060f0SSean Hefty }
1797e51060f0SSean Hefty EXPORT_SYMBOL(rdma_disconnect);
1798e51060f0SSean Hefty 
1799e51060f0SSean Hefty static void cma_add_one(struct ib_device *device)
1800e51060f0SSean Hefty {
1801e51060f0SSean Hefty 	struct cma_device *cma_dev;
1802e51060f0SSean Hefty 	struct rdma_id_private *id_priv;
1803e51060f0SSean Hefty 
1804e51060f0SSean Hefty 	cma_dev = kmalloc(sizeof *cma_dev, GFP_KERNEL);
1805e51060f0SSean Hefty 	if (!cma_dev)
1806e51060f0SSean Hefty 		return;
1807e51060f0SSean Hefty 
1808e51060f0SSean Hefty 	cma_dev->device = device;
1809e51060f0SSean Hefty 	cma_dev->node_guid = device->node_guid;
1810e51060f0SSean Hefty 	if (!cma_dev->node_guid)
1811e51060f0SSean Hefty 		goto err;
1812e51060f0SSean Hefty 
1813e51060f0SSean Hefty 	init_completion(&cma_dev->comp);
1814e51060f0SSean Hefty 	atomic_set(&cma_dev->refcount, 1);
1815e51060f0SSean Hefty 	INIT_LIST_HEAD(&cma_dev->id_list);
1816e51060f0SSean Hefty 	ib_set_client_data(device, &cma_client, cma_dev);
1817e51060f0SSean Hefty 
1818e51060f0SSean Hefty 	mutex_lock(&lock);
1819e51060f0SSean Hefty 	list_add_tail(&cma_dev->list, &dev_list);
1820e51060f0SSean Hefty 	list_for_each_entry(id_priv, &listen_any_list, list)
1821e51060f0SSean Hefty 		cma_listen_on_dev(id_priv, cma_dev);
1822e51060f0SSean Hefty 	mutex_unlock(&lock);
1823e51060f0SSean Hefty 	return;
1824e51060f0SSean Hefty err:
1825e51060f0SSean Hefty 	kfree(cma_dev);
1826e51060f0SSean Hefty }
1827e51060f0SSean Hefty 
1828e51060f0SSean Hefty static int cma_remove_id_dev(struct rdma_id_private *id_priv)
1829e51060f0SSean Hefty {
1830e51060f0SSean Hefty 	enum cma_state state;
1831e51060f0SSean Hefty 
1832e51060f0SSean Hefty 	/* Record that we want to remove the device */
1833e51060f0SSean Hefty 	state = cma_exch(id_priv, CMA_DEVICE_REMOVAL);
1834e51060f0SSean Hefty 	if (state == CMA_DESTROYING)
1835e51060f0SSean Hefty 		return 0;
1836e51060f0SSean Hefty 
1837e51060f0SSean Hefty 	cma_cancel_operation(id_priv, state);
1838e51060f0SSean Hefty 	wait_event(id_priv->wait_remove, !atomic_read(&id_priv->dev_remove));
1839e51060f0SSean Hefty 
1840e51060f0SSean Hefty 	/* Check for destruction from another callback. */
1841e51060f0SSean Hefty 	if (!cma_comp(id_priv, CMA_DEVICE_REMOVAL))
1842e51060f0SSean Hefty 		return 0;
1843e51060f0SSean Hefty 
1844e51060f0SSean Hefty 	return cma_notify_user(id_priv, RDMA_CM_EVENT_DEVICE_REMOVAL,
1845e51060f0SSean Hefty 			       0, NULL, 0);
1846e51060f0SSean Hefty }
1847e51060f0SSean Hefty 
1848e51060f0SSean Hefty static void cma_process_remove(struct cma_device *cma_dev)
1849e51060f0SSean Hefty {
1850e51060f0SSean Hefty 	struct list_head remove_list;
1851e51060f0SSean Hefty 	struct rdma_id_private *id_priv;
1852e51060f0SSean Hefty 	int ret;
1853e51060f0SSean Hefty 
1854e51060f0SSean Hefty 	INIT_LIST_HEAD(&remove_list);
1855e51060f0SSean Hefty 
1856e51060f0SSean Hefty 	mutex_lock(&lock);
1857e51060f0SSean Hefty 	while (!list_empty(&cma_dev->id_list)) {
1858e51060f0SSean Hefty 		id_priv = list_entry(cma_dev->id_list.next,
1859e51060f0SSean Hefty 				     struct rdma_id_private, list);
1860e51060f0SSean Hefty 
1861e51060f0SSean Hefty 		if (cma_internal_listen(id_priv)) {
1862e51060f0SSean Hefty 			cma_destroy_listen(id_priv);
1863e51060f0SSean Hefty 			continue;
1864e51060f0SSean Hefty 		}
1865e51060f0SSean Hefty 
1866e51060f0SSean Hefty 		list_del(&id_priv->list);
1867e51060f0SSean Hefty 		list_add_tail(&id_priv->list, &remove_list);
1868e51060f0SSean Hefty 		atomic_inc(&id_priv->refcount);
1869e51060f0SSean Hefty 		mutex_unlock(&lock);
1870e51060f0SSean Hefty 
1871e51060f0SSean Hefty 		ret = cma_remove_id_dev(id_priv);
1872e51060f0SSean Hefty 		cma_deref_id(id_priv);
1873e51060f0SSean Hefty 		if (ret)
1874e51060f0SSean Hefty 			rdma_destroy_id(&id_priv->id);
1875e51060f0SSean Hefty 
1876e51060f0SSean Hefty 		mutex_lock(&lock);
1877e51060f0SSean Hefty 	}
1878e51060f0SSean Hefty 	mutex_unlock(&lock);
1879e51060f0SSean Hefty 
1880e51060f0SSean Hefty 	cma_deref_dev(cma_dev);
1881e51060f0SSean Hefty 	wait_for_completion(&cma_dev->comp);
1882e51060f0SSean Hefty }
1883e51060f0SSean Hefty 
1884e51060f0SSean Hefty static void cma_remove_one(struct ib_device *device)
1885e51060f0SSean Hefty {
1886e51060f0SSean Hefty 	struct cma_device *cma_dev;
1887e51060f0SSean Hefty 
1888e51060f0SSean Hefty 	cma_dev = ib_get_client_data(device, &cma_client);
1889e51060f0SSean Hefty 	if (!cma_dev)
1890e51060f0SSean Hefty 		return;
1891e51060f0SSean Hefty 
1892e51060f0SSean Hefty 	mutex_lock(&lock);
1893e51060f0SSean Hefty 	list_del(&cma_dev->list);
1894e51060f0SSean Hefty 	mutex_unlock(&lock);
1895e51060f0SSean Hefty 
1896e51060f0SSean Hefty 	cma_process_remove(cma_dev);
1897e51060f0SSean Hefty 	kfree(cma_dev);
1898e51060f0SSean Hefty }
1899e51060f0SSean Hefty 
1900e51060f0SSean Hefty static int cma_init(void)
1901e51060f0SSean Hefty {
1902e51060f0SSean Hefty 	int ret;
1903e51060f0SSean Hefty 
1904e51060f0SSean Hefty 	cma_wq = create_singlethread_workqueue("rdma_cm_wq");
1905e51060f0SSean Hefty 	if (!cma_wq)
1906e51060f0SSean Hefty 		return -ENOMEM;
1907e51060f0SSean Hefty 
1908e51060f0SSean Hefty 	ret = ib_register_client(&cma_client);
1909e51060f0SSean Hefty 	if (ret)
1910e51060f0SSean Hefty 		goto err;
1911e51060f0SSean Hefty 	return 0;
1912e51060f0SSean Hefty 
1913e51060f0SSean Hefty err:
1914e51060f0SSean Hefty 	destroy_workqueue(cma_wq);
1915e51060f0SSean Hefty 	return ret;
1916e51060f0SSean Hefty }
1917e51060f0SSean Hefty 
1918e51060f0SSean Hefty static void cma_cleanup(void)
1919e51060f0SSean Hefty {
1920e51060f0SSean Hefty 	ib_unregister_client(&cma_client);
1921e51060f0SSean Hefty 	destroy_workqueue(cma_wq);
1922e51060f0SSean Hefty 	idr_destroy(&sdp_ps);
1923e51060f0SSean Hefty 	idr_destroy(&tcp_ps);
1924e51060f0SSean Hefty }
1925e51060f0SSean Hefty 
1926e51060f0SSean Hefty module_init(cma_init);
1927e51060f0SSean Hefty module_exit(cma_cleanup);
1928