1219820Sjeff/*
2219820Sjeff * Copyright (c) 2005 Voltaire Inc.  All rights reserved.
3219820Sjeff * Copyright (c) 2002-2005, Network Appliance, Inc. All rights reserved.
4219820Sjeff * Copyright (c) 1999-2005, Mellanox Technologies, Inc. All rights reserved.
5219820Sjeff * Copyright (c) 2005-2006 Intel Corporation.  All rights reserved.
6219820Sjeff *
7219820Sjeff * This software is available to you under a choice of one of two
8219820Sjeff * licenses.  You may choose to be licensed under the terms of the GNU
9219820Sjeff * General Public License (GPL) Version 2, available from the file
10219820Sjeff * COPYING in the main directory of this source tree, or the
11219820Sjeff * OpenIB.org BSD license below:
12219820Sjeff *
13219820Sjeff *     Redistribution and use in source and binary forms, with or
14219820Sjeff *     without modification, are permitted provided that the following
15219820Sjeff *     conditions are met:
16219820Sjeff *
17219820Sjeff *      - Redistributions of source code must retain the above
18219820Sjeff *        copyright notice, this list of conditions and the following
19219820Sjeff *        disclaimer.
20219820Sjeff *
21219820Sjeff *      - Redistributions in binary form must reproduce the above
22219820Sjeff *        copyright notice, this list of conditions and the following
23219820Sjeff *        disclaimer in the documentation and/or other materials
24219820Sjeff *        provided with the distribution.
25219820Sjeff *
26219820Sjeff * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
27219820Sjeff * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
28219820Sjeff * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
29219820Sjeff * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
30219820Sjeff * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
31219820Sjeff * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
32219820Sjeff * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
33219820Sjeff * SOFTWARE.
34219820Sjeff */
35219820Sjeff
36219820Sjeff#include <linux/completion.h>
37219820Sjeff#include <linux/in.h>
38219820Sjeff#include <linux/in6.h>
39219820Sjeff#include <linux/mutex.h>
40219820Sjeff#include <linux/random.h>
41219820Sjeff#include <linux/idr.h>
42219820Sjeff#include <linux/inetdevice.h>
43219820Sjeff
44219820Sjeff#include <net/tcp.h>
45219820Sjeff#include <net/ipv6.h>
46219820Sjeff
47219820Sjeff#include <rdma/rdma_cm.h>
48219820Sjeff#include <rdma/rdma_cm_ib.h>
49219820Sjeff#include <rdma/ib_cache.h>
50219820Sjeff#include <rdma/ib_cm.h>
51219820Sjeff#include <rdma/ib_sa.h>
52219820Sjeff#include <rdma/iw_cm.h>
53219820Sjeff
54219820SjeffMODULE_AUTHOR("Sean Hefty");
55219820SjeffMODULE_DESCRIPTION("Generic RDMA CM Agent");
56219820SjeffMODULE_LICENSE("Dual BSD/GPL");
57219820Sjeff
58219820Sjeffstatic int tavor_quirk = 0;
59219820Sjeffmodule_param_named(tavor_quirk, tavor_quirk, int, 0644);
60219820SjeffMODULE_PARM_DESC(tavor_quirk, "Tavor performance quirk: limit MTU to 1K if > 0");
61219820Sjeff
62252555Snpint unify_tcp_port_space = 1;
63219820Sjeffmodule_param(unify_tcp_port_space, int, 0644);
64219820SjeffMODULE_PARM_DESC(unify_tcp_port_space, "Unify the host TCP and RDMA port "
65252555Snp		 "space allocation (default=1)");
66219820Sjeff
67219820Sjeff#define CMA_CM_RESPONSE_TIMEOUT 20
68219820Sjeff#define CMA_MAX_CM_RETRIES 15
69219820Sjeff#define CMA_CM_MRA_SETTING (IB_CM_MRA_FLAG_DELAY | 24)
70219820Sjeff#define IBOE_PACKET_LIFETIME 18
71219820Sjeff
72219820Sjeffstatic int cma_response_timeout = CMA_CM_RESPONSE_TIMEOUT;
73219820Sjeffmodule_param_named(cma_response_timeout, cma_response_timeout, int, 0644);
74219820SjeffMODULE_PARM_DESC(cma_response_timeout, "CMA_CM_RESPONSE_TIMEOUT default=20");
75219820Sjeff
76219820Sjeffstatic int def_prec2sl = 3;
77219820Sjeffmodule_param_named(def_prec2sl, def_prec2sl, int, 0644);
78219820SjeffMODULE_PARM_DESC(def_prec2sl, "Default value for SL priority with RoCE. Valid values 0 - 7");
79219820Sjeff
80219820Sjeffstatic void cma_add_one(struct ib_device *device);
81219820Sjeffstatic void cma_remove_one(struct ib_device *device);
82219820Sjeff
83219820Sjeffstatic struct ib_client cma_client = {
84219820Sjeff	.name   = "cma",
85219820Sjeff	.add    = cma_add_one,
86219820Sjeff	.remove = cma_remove_one
87219820Sjeff};
88219820Sjeff
89219820Sjeffstatic struct ib_sa_client sa_client;
90219820Sjeffstatic struct rdma_addr_client addr_client;
91219820Sjeffstatic LIST_HEAD(dev_list);
92219820Sjeffstatic LIST_HEAD(listen_any_list);
93219820Sjeffstatic DEFINE_MUTEX(lock);
94219820Sjeffstatic struct workqueue_struct *cma_wq;
95219820Sjeffstatic DEFINE_IDR(sdp_ps);
96219820Sjeffstatic DEFINE_IDR(tcp_ps);
97219820Sjeffstatic DEFINE_IDR(udp_ps);
98219820Sjeffstatic DEFINE_IDR(ipoib_ps);
99239748Sjhb#if defined(INET)
100219820Sjeffstatic int next_port;
101239748Sjhb#endif
102219820Sjeff
103219820Sjeffstruct cma_device {
104219820Sjeff	struct list_head	list;
105219820Sjeff	struct ib_device	*device;
106219820Sjeff	struct completion	comp;
107219820Sjeff	atomic_t		refcount;
108219820Sjeff	struct list_head	id_list;
109219820Sjeff};
110219820Sjeff
111219820Sjeffenum cma_state {
112219820Sjeff	CMA_IDLE,
113219820Sjeff	CMA_ADDR_QUERY,
114219820Sjeff	CMA_ADDR_RESOLVED,
115219820Sjeff	CMA_ROUTE_QUERY,
116219820Sjeff	CMA_ROUTE_RESOLVED,
117219820Sjeff	CMA_CONNECT,
118219820Sjeff	CMA_DISCONNECT,
119219820Sjeff	CMA_ADDR_BOUND,
120219820Sjeff	CMA_LISTEN,
121219820Sjeff	CMA_DEVICE_REMOVAL,
122219820Sjeff	CMA_DESTROYING
123219820Sjeff};
124219820Sjeff
125219820Sjeffstruct rdma_bind_list {
126219820Sjeff	struct idr		*ps;
127219820Sjeff	struct hlist_head	owners;
128219820Sjeff	unsigned short		port;
129219820Sjeff};
130219820Sjeff
131219820Sjeff/*
132219820Sjeff * Device removal can occur at anytime, so we need extra handling to
133219820Sjeff * serialize notifying the user of device removal with other callbacks.
134219820Sjeff * We do this by disabling removal notification while a callback is in process,
135219820Sjeff * and reporting it after the callback completes.
136219820Sjeff */
137219820Sjeffstruct rdma_id_private {
138219820Sjeff	struct rdma_cm_id	id;
139219820Sjeff
140219820Sjeff	struct rdma_bind_list	*bind_list;
141219820Sjeff	struct socket		*sock;
142219820Sjeff	struct hlist_node	node;
143219820Sjeff	struct list_head	list; /* listen_any_list or cma_device.list */
144219820Sjeff	struct list_head	listen_list; /* per device listens */
145219820Sjeff	struct cma_device	*cma_dev;
146219820Sjeff	struct list_head	mc_list;
147219820Sjeff
148219820Sjeff	int			internal_id;
149219820Sjeff	enum cma_state		state;
150219820Sjeff	spinlock_t		lock;
151219820Sjeff	struct mutex		qp_mutex;
152219820Sjeff
153219820Sjeff	struct completion	comp;
154219820Sjeff	atomic_t		refcount;
155219820Sjeff	struct mutex		handler_mutex;
156219820Sjeff
157219820Sjeff	int			backlog;
158219820Sjeff	int			timeout_ms;
159219820Sjeff	struct ib_sa_query	*query;
160219820Sjeff	int			query_id;
161219820Sjeff	union {
162219820Sjeff		struct ib_cm_id	*ib;
163219820Sjeff		struct iw_cm_id	*iw;
164219820Sjeff	} cm_id;
165219820Sjeff
166219820Sjeff	u32			seq_num;
167219820Sjeff	u32			qkey;
168219820Sjeff	u32			qp_num;
169219820Sjeff	u8			srq;
170219820Sjeff	u8			tos;
171219820Sjeff};
172219820Sjeff
173219820Sjeffstruct cma_multicast {
174219820Sjeff	struct rdma_id_private *id_priv;
175219820Sjeff	union {
176219820Sjeff		struct ib_sa_multicast *ib;
177219820Sjeff	} multicast;
178219820Sjeff	struct list_head	list;
179219820Sjeff	void			*context;
180219820Sjeff	struct sockaddr_storage	addr;
181219820Sjeff	struct kref		mcref;
182219820Sjeff};
183219820Sjeff
184219820Sjeffstruct cma_work {
185219820Sjeff	struct work_struct	work;
186219820Sjeff	struct rdma_id_private	*id;
187219820Sjeff	enum cma_state		old_state;
188219820Sjeff	enum cma_state		new_state;
189219820Sjeff	struct rdma_cm_event	event;
190219820Sjeff};
191219820Sjeff
192219820Sjeffstruct cma_ndev_work {
193219820Sjeff	struct work_struct	work;
194219820Sjeff	struct rdma_id_private	*id;
195219820Sjeff	struct rdma_cm_event	event;
196219820Sjeff};
197219820Sjeff
198219820Sjeffstruct iboe_mcast_work {
199219820Sjeff	struct work_struct	 work;
200219820Sjeff	struct rdma_id_private	*id;
201219820Sjeff	struct cma_multicast	*mc;
202219820Sjeff};
203219820Sjeff
204219820Sjeffunion cma_ip_addr {
205219820Sjeff	struct in6_addr ip6;
206219820Sjeff	struct {
207219820Sjeff		__be32 pad[3];
208219820Sjeff		__be32 addr;
209219820Sjeff	} ip4;
210219820Sjeff};
211219820Sjeff
212219820Sjeffstruct cma_hdr {
213219820Sjeff	u8 cma_version;
214219820Sjeff	u8 ip_version;	/* IP version: 7:4 */
215219820Sjeff	__be16 port;
216219820Sjeff	union cma_ip_addr src_addr;
217219820Sjeff	union cma_ip_addr dst_addr;
218219820Sjeff};
219219820Sjeff
220219820Sjeffstruct sdp_hh {
221219820Sjeff	u8 bsdh[16];
222219820Sjeff	u8 sdp_version; /* Major version: 7:4 */
223219820Sjeff	u8 ip_version;	/* IP version: 7:4 */
224219820Sjeff	u8 sdp_specific1[10];
225219820Sjeff	__be16 port;
226219820Sjeff	__be16 sdp_specific2;
227219820Sjeff	union cma_ip_addr src_addr;
228219820Sjeff	union cma_ip_addr dst_addr;
229219820Sjeff};
230219820Sjeff
231219820Sjeffstruct sdp_hah {
232219820Sjeff	u8 bsdh[16];
233219820Sjeff	u8 sdp_version;
234219820Sjeff};
235219820Sjeff
236219820Sjeff#define CMA_VERSION 0x00
237219820Sjeff#define SDP_MAJ_VERSION 0x2
238219820Sjeff
239219820Sjeffstatic int cma_comp(struct rdma_id_private *id_priv, enum cma_state comp)
240219820Sjeff{
241219820Sjeff	unsigned long flags;
242219820Sjeff	int ret;
243219820Sjeff
244219820Sjeff	spin_lock_irqsave(&id_priv->lock, flags);
245219820Sjeff	ret = (id_priv->state == comp);
246219820Sjeff	spin_unlock_irqrestore(&id_priv->lock, flags);
247219820Sjeff	return ret;
248219820Sjeff}
249219820Sjeff
250219820Sjeffstatic int cma_comp_exch(struct rdma_id_private *id_priv,
251219820Sjeff			 enum cma_state comp, enum cma_state exch)
252219820Sjeff{
253219820Sjeff	unsigned long flags;
254219820Sjeff	int ret;
255219820Sjeff
256219820Sjeff	spin_lock_irqsave(&id_priv->lock, flags);
257219820Sjeff	if ((ret = (id_priv->state == comp)))
258219820Sjeff		id_priv->state = exch;
259219820Sjeff	spin_unlock_irqrestore(&id_priv->lock, flags);
260219820Sjeff	return ret;
261219820Sjeff}
262219820Sjeff
263219820Sjeffstatic enum cma_state cma_exch(struct rdma_id_private *id_priv,
264219820Sjeff			       enum cma_state exch)
265219820Sjeff{
266219820Sjeff	unsigned long flags;
267219820Sjeff	enum cma_state old;
268219820Sjeff
269219820Sjeff	spin_lock_irqsave(&id_priv->lock, flags);
270219820Sjeff	old = id_priv->state;
271219820Sjeff	id_priv->state = exch;
272219820Sjeff	spin_unlock_irqrestore(&id_priv->lock, flags);
273219820Sjeff	return old;
274219820Sjeff}
275219820Sjeff
276219820Sjeffstatic inline u8 cma_get_ip_ver(struct cma_hdr *hdr)
277219820Sjeff{
278219820Sjeff	return hdr->ip_version >> 4;
279219820Sjeff}
280219820Sjeff
281219820Sjeffstatic inline void cma_set_ip_ver(struct cma_hdr *hdr, u8 ip_ver)
282219820Sjeff{
283219820Sjeff	hdr->ip_version = (ip_ver << 4) | (hdr->ip_version & 0xF);
284219820Sjeff}
285219820Sjeff
286219820Sjeffstatic inline u8 sdp_get_majv(u8 sdp_version)
287219820Sjeff{
288219820Sjeff	return sdp_version >> 4;
289219820Sjeff}
290219820Sjeff
291219820Sjeffstatic inline u8 sdp_get_ip_ver(struct sdp_hh *hh)
292219820Sjeff{
293219820Sjeff	return hh->ip_version >> 4;
294219820Sjeff}
295219820Sjeff
296219820Sjeffstatic inline void sdp_set_ip_ver(struct sdp_hh *hh, u8 ip_ver)
297219820Sjeff{
298219820Sjeff	hh->ip_version = (ip_ver << 4) | (hh->ip_version & 0xF);
299219820Sjeff}
300219820Sjeff
301219820Sjeffstatic inline int cma_is_ud_ps(enum rdma_port_space ps)
302219820Sjeff{
303219820Sjeff	return (ps == RDMA_PS_UDP || ps == RDMA_PS_IPOIB);
304219820Sjeff}
305219820Sjeff
306219820Sjeffstatic void cma_attach_to_dev(struct rdma_id_private *id_priv,
307219820Sjeff			      struct cma_device *cma_dev)
308219820Sjeff{
309219820Sjeff	atomic_inc(&cma_dev->refcount);
310219820Sjeff	id_priv->cma_dev = cma_dev;
311219820Sjeff	id_priv->id.device = cma_dev->device;
312219820Sjeff	id_priv->id.route.addr.dev_addr.transport =
313219820Sjeff		rdma_node_get_transport(cma_dev->device->node_type);
314219820Sjeff	list_add_tail(&id_priv->list, &cma_dev->id_list);
315219820Sjeff}
316219820Sjeff
317219820Sjeffstatic inline void cma_deref_dev(struct cma_device *cma_dev)
318219820Sjeff{
319219820Sjeff	if (atomic_dec_and_test(&cma_dev->refcount))
320219820Sjeff		complete(&cma_dev->comp);
321219820Sjeff}
322219820Sjeff
323219820Sjeffstatic inline void release_mc(struct kref *kref)
324219820Sjeff{
325219820Sjeff	struct cma_multicast *mc = container_of(kref, struct cma_multicast, mcref);
326219820Sjeff
327219820Sjeff	kfree(mc->multicast.ib);
328219820Sjeff	kfree(mc);
329219820Sjeff}
330219820Sjeff
331219820Sjeffstatic void cma_detach_from_dev(struct rdma_id_private *id_priv)
332219820Sjeff{
333219820Sjeff	list_del(&id_priv->list);
334219820Sjeff	cma_deref_dev(id_priv->cma_dev);
335219820Sjeff	id_priv->cma_dev = NULL;
336219820Sjeff}
337219820Sjeff
338219820Sjeffstatic int cma_set_qkey(struct rdma_id_private *id_priv)
339219820Sjeff{
340219820Sjeff	struct ib_sa_mcmember_rec rec;
341219820Sjeff	int ret = 0;
342219820Sjeff
343219820Sjeff	if (id_priv->qkey)
344219820Sjeff		return 0;
345219820Sjeff
346219820Sjeff	switch (id_priv->id.ps) {
347219820Sjeff	case RDMA_PS_UDP:
348219820Sjeff		id_priv->qkey = RDMA_UDP_QKEY;
349219820Sjeff		break;
350219820Sjeff	case RDMA_PS_IPOIB:
351219820Sjeff		ib_addr_get_mgid(&id_priv->id.route.addr.dev_addr, &rec.mgid);
352219820Sjeff		ret = ib_sa_get_mcmember_rec(id_priv->id.device,
353219820Sjeff					     id_priv->id.port_num, &rec.mgid,
354219820Sjeff					     &rec);
355219820Sjeff		if (!ret)
356219820Sjeff			id_priv->qkey = be32_to_cpu(rec.qkey);
357219820Sjeff		break;
358219820Sjeff	default:
359219820Sjeff		break;
360219820Sjeff	}
361219820Sjeff	return ret;
362219820Sjeff}
363219820Sjeff
364219820Sjeffstatic int cma_acquire_dev(struct rdma_id_private *id_priv)
365219820Sjeff{
366219820Sjeff	struct rdma_dev_addr *dev_addr = &id_priv->id.route.addr.dev_addr;
367219820Sjeff	struct cma_device *cma_dev;
368219820Sjeff	union ib_gid gid;
369219820Sjeff	int ret = -ENODEV;
370219820Sjeff
371219820Sjeff	if (dev_addr->dev_type != ARPHRD_INFINIBAND) {
372219820Sjeff		iboe_addr_get_sgid(dev_addr, &gid);
373219820Sjeff		list_for_each_entry(cma_dev, &dev_list, list) {
374219820Sjeff			ret = ib_find_cached_gid(cma_dev->device, &gid,
375219820Sjeff						 &id_priv->id.port_num, NULL);
376219820Sjeff			if (!ret)
377219820Sjeff				goto out;
378219820Sjeff		}
379219820Sjeff	}
380219820Sjeff
381219820Sjeff	memcpy(&gid, dev_addr->src_dev_addr +
382219820Sjeff	       rdma_addr_gid_offset(dev_addr), sizeof gid);
383219820Sjeff	list_for_each_entry(cma_dev, &dev_list, list) {
384219820Sjeff		ret = ib_find_cached_gid(cma_dev->device, &gid,
385219820Sjeff					 &id_priv->id.port_num, NULL);
386219820Sjeff		if (!ret)
387219820Sjeff			break;
388219820Sjeff	}
389219820Sjeff
390219820Sjeffout:
391219820Sjeff	if (!ret)
392219820Sjeff		cma_attach_to_dev(id_priv, cma_dev);
393219820Sjeff
394219820Sjeff	return ret;
395219820Sjeff}
396219820Sjeff
397219820Sjeffstatic void cma_deref_id(struct rdma_id_private *id_priv)
398219820Sjeff{
399219820Sjeff	if (atomic_dec_and_test(&id_priv->refcount))
400219820Sjeff		complete(&id_priv->comp);
401219820Sjeff}
402219820Sjeff
403219820Sjeffstatic int cma_disable_callback(struct rdma_id_private *id_priv,
404219820Sjeff			      enum cma_state state)
405219820Sjeff{
406219820Sjeff	mutex_lock(&id_priv->handler_mutex);
407219820Sjeff	if (id_priv->state != state) {
408219820Sjeff		mutex_unlock(&id_priv->handler_mutex);
409219820Sjeff		return -EINVAL;
410219820Sjeff	}
411219820Sjeff	return 0;
412219820Sjeff}
413219820Sjeff
414219820Sjeffstatic int cma_has_cm_dev(struct rdma_id_private *id_priv)
415219820Sjeff{
416219820Sjeff	return (id_priv->id.device && id_priv->cm_id.ib);
417219820Sjeff}
418219820Sjeff
419219820Sjeffstruct rdma_cm_id *rdma_create_id(rdma_cm_event_handler event_handler,
420219820Sjeff				  void *context, enum rdma_port_space ps)
421219820Sjeff{
422219820Sjeff	struct rdma_id_private *id_priv;
423219820Sjeff
424219820Sjeff	id_priv = kzalloc(sizeof *id_priv, GFP_KERNEL);
425219820Sjeff	if (!id_priv)
426219820Sjeff		return ERR_PTR(-ENOMEM);
427219820Sjeff
428219820Sjeff	id_priv->state = CMA_IDLE;
429219820Sjeff	id_priv->id.context = context;
430219820Sjeff	id_priv->id.event_handler = event_handler;
431219820Sjeff	id_priv->id.ps = ps;
432219820Sjeff	spin_lock_init(&id_priv->lock);
433219820Sjeff	mutex_init(&id_priv->qp_mutex);
434219820Sjeff	init_completion(&id_priv->comp);
435219820Sjeff	atomic_set(&id_priv->refcount, 1);
436219820Sjeff	mutex_init(&id_priv->handler_mutex);
437219820Sjeff	INIT_LIST_HEAD(&id_priv->listen_list);
438219820Sjeff	INIT_LIST_HEAD(&id_priv->mc_list);
439219820Sjeff	get_random_bytes(&id_priv->seq_num, sizeof id_priv->seq_num);
440219820Sjeff
441219820Sjeff	return &id_priv->id;
442219820Sjeff}
443219820SjeffEXPORT_SYMBOL(rdma_create_id);
444219820Sjeff
445219820Sjeffstatic int cma_init_ud_qp(struct rdma_id_private *id_priv, struct ib_qp *qp)
446219820Sjeff{
447219820Sjeff	struct ib_qp_attr qp_attr;
448219820Sjeff	int qp_attr_mask, ret;
449219820Sjeff
450219820Sjeff	qp_attr.qp_state = IB_QPS_INIT;
451219820Sjeff	ret = rdma_init_qp_attr(&id_priv->id, &qp_attr, &qp_attr_mask);
452219820Sjeff	if (ret)
453219820Sjeff		return ret;
454219820Sjeff
455219820Sjeff	ret = ib_modify_qp(qp, &qp_attr, qp_attr_mask);
456219820Sjeff	if (ret)
457219820Sjeff		return ret;
458219820Sjeff
459219820Sjeff	qp_attr.qp_state = IB_QPS_RTR;
460219820Sjeff	ret = ib_modify_qp(qp, &qp_attr, IB_QP_STATE);
461219820Sjeff	if (ret)
462219820Sjeff		return ret;
463219820Sjeff
464219820Sjeff	qp_attr.qp_state = IB_QPS_RTS;
465219820Sjeff	qp_attr.sq_psn = 0;
466219820Sjeff	ret = ib_modify_qp(qp, &qp_attr, IB_QP_STATE | IB_QP_SQ_PSN);
467219820Sjeff
468219820Sjeff	return ret;
469219820Sjeff}
470219820Sjeff
471219820Sjeffstatic int cma_init_conn_qp(struct rdma_id_private *id_priv, struct ib_qp *qp)
472219820Sjeff{
473219820Sjeff	struct ib_qp_attr qp_attr;
474219820Sjeff	int qp_attr_mask, ret;
475219820Sjeff
476219820Sjeff	qp_attr.qp_state = IB_QPS_INIT;
477219820Sjeff	ret = rdma_init_qp_attr(&id_priv->id, &qp_attr, &qp_attr_mask);
478219820Sjeff	if (ret)
479219820Sjeff		return ret;
480219820Sjeff
481219820Sjeff	return ib_modify_qp(qp, &qp_attr, qp_attr_mask);
482219820Sjeff}
483219820Sjeff
484219820Sjeffint rdma_create_qp(struct rdma_cm_id *id, struct ib_pd *pd,
485219820Sjeff		   struct ib_qp_init_attr *qp_init_attr)
486219820Sjeff{
487219820Sjeff	struct rdma_id_private *id_priv;
488219820Sjeff	struct ib_qp *qp;
489219820Sjeff	int ret;
490219820Sjeff
491219820Sjeff	id_priv = container_of(id, struct rdma_id_private, id);
492219820Sjeff	if (id->device != pd->device)
493219820Sjeff		return -EINVAL;
494219820Sjeff
495219820Sjeff	qp = ib_create_qp(pd, qp_init_attr);
496219820Sjeff	if (IS_ERR(qp))
497219820Sjeff		return PTR_ERR(qp);
498219820Sjeff
499219820Sjeff	if (cma_is_ud_ps(id_priv->id.ps))
500219820Sjeff		ret = cma_init_ud_qp(id_priv, qp);
501219820Sjeff	else
502219820Sjeff		ret = cma_init_conn_qp(id_priv, qp);
503219820Sjeff	if (ret)
504219820Sjeff		goto err;
505219820Sjeff
506219820Sjeff	id->qp = qp;
507219820Sjeff	id_priv->qp_num = qp->qp_num;
508219820Sjeff	id_priv->srq = (qp->srq != NULL);
509219820Sjeff	return 0;
510219820Sjefferr:
511219820Sjeff	ib_destroy_qp(qp);
512219820Sjeff	return ret;
513219820Sjeff}
514219820SjeffEXPORT_SYMBOL(rdma_create_qp);
515219820Sjeff
516219820Sjeffvoid rdma_destroy_qp(struct rdma_cm_id *id)
517219820Sjeff{
518219820Sjeff	struct rdma_id_private *id_priv;
519219820Sjeff
520219820Sjeff	id_priv = container_of(id, struct rdma_id_private, id);
521219820Sjeff	mutex_lock(&id_priv->qp_mutex);
522219820Sjeff	ib_destroy_qp(id_priv->id.qp);
523219820Sjeff	id_priv->id.qp = NULL;
524219820Sjeff	mutex_unlock(&id_priv->qp_mutex);
525219820Sjeff}
526219820SjeffEXPORT_SYMBOL(rdma_destroy_qp);
527219820Sjeff
528219820Sjeffstatic int cma_modify_qp_rtr(struct rdma_id_private *id_priv,
529219820Sjeff			     struct rdma_conn_param *conn_param)
530219820Sjeff{
531219820Sjeff	struct ib_qp_attr qp_attr;
532219820Sjeff	int qp_attr_mask, ret;
533219820Sjeff
534219820Sjeff	mutex_lock(&id_priv->qp_mutex);
535219820Sjeff	if (!id_priv->id.qp) {
536219820Sjeff		ret = 0;
537219820Sjeff		goto out;
538219820Sjeff	}
539219820Sjeff
540219820Sjeff	/* Need to update QP attributes from default values. */
541219820Sjeff	qp_attr.qp_state = IB_QPS_INIT;
542219820Sjeff	ret = rdma_init_qp_attr(&id_priv->id, &qp_attr, &qp_attr_mask);
543219820Sjeff	if (ret)
544219820Sjeff		goto out;
545219820Sjeff
546219820Sjeff	ret = ib_modify_qp(id_priv->id.qp, &qp_attr, qp_attr_mask);
547219820Sjeff	if (ret)
548219820Sjeff		goto out;
549219820Sjeff
550219820Sjeff	qp_attr.qp_state = IB_QPS_RTR;
551219820Sjeff	ret = rdma_init_qp_attr(&id_priv->id, &qp_attr, &qp_attr_mask);
552219820Sjeff	if (ret)
553219820Sjeff		goto out;
554219820Sjeff
555219820Sjeff	if (conn_param)
556219820Sjeff		qp_attr.max_dest_rd_atomic = conn_param->responder_resources;
557219820Sjeff	ret = ib_modify_qp(id_priv->id.qp, &qp_attr, qp_attr_mask);
558219820Sjeffout:
559219820Sjeff	mutex_unlock(&id_priv->qp_mutex);
560219820Sjeff	return ret;
561219820Sjeff}
562219820Sjeff
563219820Sjeffstatic int cma_modify_qp_rts(struct rdma_id_private *id_priv,
564219820Sjeff			     struct rdma_conn_param *conn_param)
565219820Sjeff{
566219820Sjeff	struct ib_qp_attr qp_attr;
567219820Sjeff	int qp_attr_mask, ret;
568219820Sjeff
569219820Sjeff	mutex_lock(&id_priv->qp_mutex);
570219820Sjeff	if (!id_priv->id.qp) {
571219820Sjeff		ret = 0;
572219820Sjeff		goto out;
573219820Sjeff	}
574219820Sjeff
575219820Sjeff	qp_attr.qp_state = IB_QPS_RTS;
576219820Sjeff	ret = rdma_init_qp_attr(&id_priv->id, &qp_attr, &qp_attr_mask);
577219820Sjeff	if (ret)
578219820Sjeff		goto out;
579219820Sjeff
580219820Sjeff	if (conn_param)
581219820Sjeff		qp_attr.max_rd_atomic = conn_param->initiator_depth;
582219820Sjeff	ret = ib_modify_qp(id_priv->id.qp, &qp_attr, qp_attr_mask);
583219820Sjeffout:
584219820Sjeff	mutex_unlock(&id_priv->qp_mutex);
585219820Sjeff	return ret;
586219820Sjeff}
587219820Sjeff
588219820Sjeffstatic int cma_modify_qp_err(struct rdma_id_private *id_priv)
589219820Sjeff{
590219820Sjeff	struct ib_qp_attr qp_attr;
591219820Sjeff	int ret;
592219820Sjeff
593219820Sjeff	mutex_lock(&id_priv->qp_mutex);
594219820Sjeff	if (!id_priv->id.qp) {
595219820Sjeff		ret = 0;
596219820Sjeff		goto out;
597219820Sjeff	}
598219820Sjeff
599219820Sjeff	qp_attr.qp_state = IB_QPS_ERR;
600219820Sjeff	ret = ib_modify_qp(id_priv->id.qp, &qp_attr, IB_QP_STATE);
601219820Sjeffout:
602219820Sjeff	mutex_unlock(&id_priv->qp_mutex);
603219820Sjeff	return ret;
604219820Sjeff}
605219820Sjeff
606219820Sjeffstatic int cma_ib_init_qp_attr(struct rdma_id_private *id_priv,
607219820Sjeff			       struct ib_qp_attr *qp_attr, int *qp_attr_mask)
608219820Sjeff{
609219820Sjeff	struct rdma_dev_addr *dev_addr = &id_priv->id.route.addr.dev_addr;
610219820Sjeff	int ret;
611219820Sjeff	u16 pkey;
612219820Sjeff
613219820Sjeff	if (rdma_port_get_link_layer(id_priv->id.device, id_priv->id.port_num) ==
614219820Sjeff	    IB_LINK_LAYER_INFINIBAND)
615219820Sjeff		pkey = ib_addr_get_pkey(dev_addr);
616219820Sjeff	else
617219820Sjeff		pkey = 0xffff;
618219820Sjeff
619219820Sjeff	ret = ib_find_cached_pkey(id_priv->id.device, id_priv->id.port_num,
620219820Sjeff				  pkey, &qp_attr->pkey_index);
621219820Sjeff	if (ret)
622219820Sjeff		return ret;
623219820Sjeff
624219820Sjeff	qp_attr->port_num = id_priv->id.port_num;
625219820Sjeff	*qp_attr_mask = IB_QP_STATE | IB_QP_PKEY_INDEX | IB_QP_PORT;
626219820Sjeff
627219820Sjeff	if (cma_is_ud_ps(id_priv->id.ps)) {
628219820Sjeff		ret = cma_set_qkey(id_priv);
629219820Sjeff		if (ret)
630219820Sjeff			return ret;
631219820Sjeff
632219820Sjeff		qp_attr->qkey = id_priv->qkey;
633219820Sjeff		*qp_attr_mask |= IB_QP_QKEY;
634219820Sjeff	} else {
635219820Sjeff		qp_attr->qp_access_flags = 0;
636219820Sjeff		*qp_attr_mask |= IB_QP_ACCESS_FLAGS;
637219820Sjeff	}
638219820Sjeff	return 0;
639219820Sjeff}
640219820Sjeff
641219820Sjeffint rdma_init_qp_attr(struct rdma_cm_id *id, struct ib_qp_attr *qp_attr,
642219820Sjeff		       int *qp_attr_mask)
643219820Sjeff{
644219820Sjeff	struct rdma_id_private *id_priv;
645219820Sjeff	int ret = 0;
646219820Sjeff
647219820Sjeff	id_priv = container_of(id, struct rdma_id_private, id);
648219820Sjeff	switch (rdma_node_get_transport(id_priv->id.device->node_type)) {
649219820Sjeff	case RDMA_TRANSPORT_IB:
650219820Sjeff		if (!id_priv->cm_id.ib || cma_is_ud_ps(id_priv->id.ps))
651219820Sjeff			ret = cma_ib_init_qp_attr(id_priv, qp_attr, qp_attr_mask);
652219820Sjeff		else
653219820Sjeff			ret = ib_cm_init_qp_attr(id_priv->cm_id.ib, qp_attr,
654219820Sjeff						 qp_attr_mask);
655219820Sjeff		if (qp_attr->qp_state == IB_QPS_RTR)
656219820Sjeff			qp_attr->rq_psn = id_priv->seq_num;
657219820Sjeff		break;
658219820Sjeff	case RDMA_TRANSPORT_IWARP:
659219820Sjeff		if (!id_priv->cm_id.iw) {
660219820Sjeff			qp_attr->qp_access_flags = 0;
661219820Sjeff			*qp_attr_mask = IB_QP_STATE | IB_QP_ACCESS_FLAGS;
662219820Sjeff		} else
663219820Sjeff			ret = iw_cm_init_qp_attr(id_priv->cm_id.iw, qp_attr,
664219820Sjeff						 qp_attr_mask);
665219820Sjeff		break;
666219820Sjeff	default:
667219820Sjeff		ret = -ENOSYS;
668219820Sjeff		break;
669219820Sjeff	}
670219820Sjeff
671219820Sjeff	return ret;
672219820Sjeff}
673219820SjeffEXPORT_SYMBOL(rdma_init_qp_attr);
674219820Sjeff
675219820Sjeffstatic inline int cma_zero_addr(struct sockaddr *addr)
676219820Sjeff{
677219820Sjeff	struct in6_addr *ip6;
678219820Sjeff
679219820Sjeff	if (addr->sa_family == AF_INET)
680219820Sjeff		return ipv4_is_zeronet(
681219820Sjeff			((struct sockaddr_in *)addr)->sin_addr.s_addr);
682219820Sjeff	else {
683219820Sjeff		ip6 = &((struct sockaddr_in6 *) addr)->sin6_addr;
684219820Sjeff		return (ip6->s6_addr32[0] | ip6->s6_addr32[1] |
685219820Sjeff			ip6->s6_addr32[2] | ip6->s6_addr32[3]) == 0;
686219820Sjeff	}
687219820Sjeff}
688219820Sjeff
689219820Sjeffstatic inline int cma_loopback_addr(struct sockaddr *addr)
690219820Sjeff{
691219820Sjeff	if (addr->sa_family == AF_INET)
692219820Sjeff		return ipv4_is_loopback(
693219820Sjeff			((struct sockaddr_in *) addr)->sin_addr.s_addr);
694219820Sjeff	else
695219820Sjeff		return ipv6_addr_loopback(
696219820Sjeff			&((struct sockaddr_in6 *) addr)->sin6_addr);
697219820Sjeff}
698219820Sjeff
699219820Sjeffstatic inline int cma_any_addr(struct sockaddr *addr)
700219820Sjeff{
701219820Sjeff	return cma_zero_addr(addr) || cma_loopback_addr(addr);
702219820Sjeff}
703219820Sjeff
704219820Sjeffstatic inline __be16 cma_port(struct sockaddr *addr)
705219820Sjeff{
706219820Sjeff	if (addr->sa_family == AF_INET)
707219820Sjeff		return ((struct sockaddr_in *) addr)->sin_port;
708219820Sjeff	else
709219820Sjeff		return ((struct sockaddr_in6 *) addr)->sin6_port;
710219820Sjeff}
711219820Sjeff
712219820Sjeffstatic inline int cma_any_port(struct sockaddr *addr)
713219820Sjeff{
714219820Sjeff	return !cma_port(addr);
715219820Sjeff}
716219820Sjeff
717219820Sjeffstatic int cma_get_net_info(void *hdr, enum rdma_port_space ps,
718219820Sjeff			    u8 *ip_ver, __be16 *port,
719219820Sjeff			    union cma_ip_addr **src, union cma_ip_addr **dst)
720219820Sjeff{
721219820Sjeff	switch (ps) {
722219820Sjeff	case RDMA_PS_SDP:
723219820Sjeff		if (sdp_get_majv(((struct sdp_hh *) hdr)->sdp_version) !=
724219820Sjeff		    SDP_MAJ_VERSION)
725219820Sjeff			return -EINVAL;
726219820Sjeff
727219820Sjeff		*ip_ver	= sdp_get_ip_ver(hdr);
728219820Sjeff		*port	= ((struct sdp_hh *) hdr)->port;
729219820Sjeff		*src	= &((struct sdp_hh *) hdr)->src_addr;
730219820Sjeff		*dst	= &((struct sdp_hh *) hdr)->dst_addr;
731219820Sjeff		break;
732219820Sjeff	default:
733219820Sjeff		if (((struct cma_hdr *) hdr)->cma_version != CMA_VERSION)
734219820Sjeff			return -EINVAL;
735219820Sjeff
736219820Sjeff		*ip_ver	= cma_get_ip_ver(hdr);
737219820Sjeff		*port	= ((struct cma_hdr *) hdr)->port;
738219820Sjeff		*src	= &((struct cma_hdr *) hdr)->src_addr;
739219820Sjeff		*dst	= &((struct cma_hdr *) hdr)->dst_addr;
740219820Sjeff		break;
741219820Sjeff	}
742219820Sjeff
743219820Sjeff	if (*ip_ver != 4 && *ip_ver != 6)
744219820Sjeff		return -EINVAL;
745219820Sjeff	return 0;
746219820Sjeff}
747219820Sjeff
748219820Sjeffstatic void cma_save_net_info(struct rdma_addr *addr,
749219820Sjeff			      struct rdma_addr *listen_addr,
750219820Sjeff			      u8 ip_ver, __be16 port,
751219820Sjeff			      union cma_ip_addr *src, union cma_ip_addr *dst)
752219820Sjeff{
753219820Sjeff	struct sockaddr_in *listen4, *ip4;
754219820Sjeff	struct sockaddr_in6 *listen6, *ip6;
755219820Sjeff
756219820Sjeff	switch (ip_ver) {
757219820Sjeff	case 4:
758219820Sjeff		listen4 = (struct sockaddr_in *) &listen_addr->src_addr;
759219820Sjeff		ip4 = (struct sockaddr_in *) &addr->src_addr;
760219820Sjeff		ip4->sin_family = listen4->sin_family;
761219820Sjeff		ip4->sin_addr.s_addr = dst->ip4.addr;
762219820Sjeff		ip4->sin_port = listen4->sin_port;
763219820Sjeff
764219820Sjeff		ip4 = (struct sockaddr_in *) &addr->dst_addr;
765219820Sjeff		ip4->sin_family = listen4->sin_family;
766219820Sjeff		ip4->sin_addr.s_addr = src->ip4.addr;
767219820Sjeff		ip4->sin_port = port;
768219820Sjeff		break;
769219820Sjeff	case 6:
770219820Sjeff		listen6 = (struct sockaddr_in6 *) &listen_addr->src_addr;
771219820Sjeff		ip6 = (struct sockaddr_in6 *) &addr->src_addr;
772219820Sjeff		ip6->sin6_family = listen6->sin6_family;
773219820Sjeff		ip6->sin6_addr = dst->ip6;
774219820Sjeff		ip6->sin6_port = listen6->sin6_port;
775219820Sjeff
776219820Sjeff		ip6 = (struct sockaddr_in6 *) &addr->dst_addr;
777219820Sjeff		ip6->sin6_family = listen6->sin6_family;
778219820Sjeff		ip6->sin6_addr = src->ip6;
779219820Sjeff		ip6->sin6_port = port;
780219820Sjeff		break;
781219820Sjeff	default:
782219820Sjeff		break;
783219820Sjeff	}
784219820Sjeff}
785219820Sjeff
786219820Sjeffstatic inline int cma_user_data_offset(enum rdma_port_space ps)
787219820Sjeff{
788219820Sjeff	switch (ps) {
789219820Sjeff	case RDMA_PS_SDP:
790219820Sjeff		return 0;
791219820Sjeff	default:
792219820Sjeff		return sizeof(struct cma_hdr);
793219820Sjeff	}
794219820Sjeff}
795219820Sjeff
796219820Sjeffstatic void cma_cancel_route(struct rdma_id_private *id_priv)
797219820Sjeff{
798219820Sjeff	switch (rdma_port_get_link_layer(id_priv->id.device, id_priv->id.port_num)) {
799219820Sjeff	case IB_LINK_LAYER_INFINIBAND:
800219820Sjeff		if (id_priv->query)
801219820Sjeff			ib_sa_cancel_query(id_priv->query_id, id_priv->query);
802219820Sjeff		break;
803219820Sjeff	default:
804219820Sjeff		break;
805219820Sjeff	}
806219820Sjeff}
807219820Sjeff
808219820Sjeffstatic void cma_cancel_listens(struct rdma_id_private *id_priv)
809219820Sjeff{
810219820Sjeff	struct rdma_id_private *dev_id_priv;
811219820Sjeff
812219820Sjeff	/*
813219820Sjeff	 * Remove from listen_any_list to prevent added devices from spawning
814219820Sjeff	 * additional listen requests.
815219820Sjeff	 */
816219820Sjeff	mutex_lock(&lock);
817219820Sjeff	list_del(&id_priv->list);
818219820Sjeff
819219820Sjeff	while (!list_empty(&id_priv->listen_list)) {
820219820Sjeff		dev_id_priv = list_entry(id_priv->listen_list.next,
821219820Sjeff					 struct rdma_id_private, listen_list);
822219820Sjeff		/* sync with device removal to avoid duplicate destruction */
823219820Sjeff		list_del_init(&dev_id_priv->list);
824219820Sjeff		list_del(&dev_id_priv->listen_list);
825219820Sjeff		mutex_unlock(&lock);
826219820Sjeff
827219820Sjeff		rdma_destroy_id(&dev_id_priv->id);
828219820Sjeff		mutex_lock(&lock);
829219820Sjeff	}
830219820Sjeff	mutex_unlock(&lock);
831219820Sjeff}
832219820Sjeff
833219820Sjeffstatic void cma_cancel_operation(struct rdma_id_private *id_priv,
834219820Sjeff				 enum cma_state state)
835219820Sjeff{
836219820Sjeff	switch (state) {
837219820Sjeff	case CMA_ADDR_QUERY:
838219820Sjeff		rdma_addr_cancel(&id_priv->id.route.addr.dev_addr);
839219820Sjeff		break;
840219820Sjeff	case CMA_ROUTE_QUERY:
841219820Sjeff		cma_cancel_route(id_priv);
842219820Sjeff		break;
843219820Sjeff	case CMA_LISTEN:
844219820Sjeff		if (cma_any_addr((struct sockaddr *) &id_priv->id.route.addr.src_addr)
845219820Sjeff				&& !id_priv->cma_dev)
846219820Sjeff			cma_cancel_listens(id_priv);
847219820Sjeff		break;
848219820Sjeff	default:
849219820Sjeff		break;
850219820Sjeff	}
851219820Sjeff}
852219820Sjeff
853219820Sjeffstatic void cma_release_port(struct rdma_id_private *id_priv)
854219820Sjeff{
855219820Sjeff	struct rdma_bind_list *bind_list = id_priv->bind_list;
856219820Sjeff
857219820Sjeff	if (!bind_list)
858219820Sjeff		return;
859219820Sjeff
860219820Sjeff	mutex_lock(&lock);
861219820Sjeff	hlist_del(&id_priv->node);
862219820Sjeff	if (hlist_empty(&bind_list->owners)) {
863219820Sjeff		idr_remove(bind_list->ps, bind_list->port);
864219820Sjeff		kfree(bind_list);
865219820Sjeff	}
866219820Sjeff	mutex_unlock(&lock);
867219820Sjeff	if (id_priv->sock)
868219820Sjeff		sock_release(id_priv->sock);
869219820Sjeff}
870219820Sjeff
871219820Sjeffstatic void cma_leave_mc_groups(struct rdma_id_private *id_priv)
872219820Sjeff{
873219820Sjeff	struct cma_multicast *mc;
874219820Sjeff
875219820Sjeff	while (!list_empty(&id_priv->mc_list)) {
876219820Sjeff		mc = container_of(id_priv->mc_list.next,
877219820Sjeff				  struct cma_multicast, list);
878219820Sjeff		list_del(&mc->list);
879219820Sjeff		switch (rdma_port_get_link_layer(id_priv->cma_dev->device, id_priv->id.port_num)) {
880219820Sjeff		case IB_LINK_LAYER_INFINIBAND:
881219820Sjeff			ib_sa_free_multicast(mc->multicast.ib);
882219820Sjeff			kfree(mc);
883219820Sjeff			break;
884219820Sjeff		case IB_LINK_LAYER_ETHERNET:
885219820Sjeff			kref_put(&mc->mcref, release_mc);
886219820Sjeff			break;
887219820Sjeff		default:
888219820Sjeff			break;
889219820Sjeff		}
890219820Sjeff	}
891219820Sjeff}
892219820Sjeff
893219820Sjeffvoid rdma_destroy_id(struct rdma_cm_id *id)
894219820Sjeff{
895219820Sjeff	struct rdma_id_private *id_priv;
896219820Sjeff	enum cma_state state;
897219820Sjeff
898219820Sjeff	id_priv = container_of(id, struct rdma_id_private, id);
899219820Sjeff	state = cma_exch(id_priv, CMA_DESTROYING);
900219820Sjeff	cma_cancel_operation(id_priv, state);
901219820Sjeff
902219820Sjeff	mutex_lock(&lock);
903219820Sjeff	if (id_priv->cma_dev) {
904219820Sjeff		mutex_unlock(&lock);
905219820Sjeff		switch (rdma_node_get_transport(id_priv->id.device->node_type)) {
906219820Sjeff		case RDMA_TRANSPORT_IB:
907219820Sjeff			if (id_priv->cm_id.ib && !IS_ERR(id_priv->cm_id.ib))
908219820Sjeff				ib_destroy_cm_id(id_priv->cm_id.ib);
909219820Sjeff			break;
910219820Sjeff		case RDMA_TRANSPORT_IWARP:
911219820Sjeff			if (id_priv->cm_id.iw && !IS_ERR(id_priv->cm_id.iw))
912219820Sjeff				iw_destroy_cm_id(id_priv->cm_id.iw);
913219820Sjeff			break;
914219820Sjeff		default:
915219820Sjeff			break;
916219820Sjeff		}
917219820Sjeff		cma_leave_mc_groups(id_priv);
918219820Sjeff		mutex_lock(&lock);
919219820Sjeff		cma_detach_from_dev(id_priv);
920219820Sjeff	}
921219820Sjeff	mutex_unlock(&lock);
922219820Sjeff
923219820Sjeff	cma_release_port(id_priv);
924219820Sjeff	cma_deref_id(id_priv);
925219820Sjeff	wait_for_completion(&id_priv->comp);
926219820Sjeff
927219820Sjeff	if (id_priv->internal_id)
928219820Sjeff		cma_deref_id(id_priv->id.context);
929219820Sjeff
930219820Sjeff	kfree(id_priv->id.route.path_rec);
931219820Sjeff	kfree(id_priv);
932219820Sjeff}
933219820SjeffEXPORT_SYMBOL(rdma_destroy_id);
934219820Sjeff
935219820Sjeffstatic int cma_rep_recv(struct rdma_id_private *id_priv)
936219820Sjeff{
937219820Sjeff	int ret;
938219820Sjeff
939219820Sjeff	ret = cma_modify_qp_rtr(id_priv, NULL);
940219820Sjeff	if (ret)
941219820Sjeff		goto reject;
942219820Sjeff
943219820Sjeff	ret = cma_modify_qp_rts(id_priv, NULL);
944219820Sjeff	if (ret)
945219820Sjeff		goto reject;
946219820Sjeff
947219820Sjeff	ret = ib_send_cm_rtu(id_priv->cm_id.ib, NULL, 0);
948219820Sjeff	if (ret)
949219820Sjeff		goto reject;
950219820Sjeff
951219820Sjeff	return 0;
952219820Sjeffreject:
953219820Sjeff	cma_modify_qp_err(id_priv);
954219820Sjeff	ib_send_cm_rej(id_priv->cm_id.ib, IB_CM_REJ_CONSUMER_DEFINED,
955219820Sjeff		       NULL, 0, NULL, 0);
956219820Sjeff	return ret;
957219820Sjeff}
958219820Sjeff
959219820Sjeffstatic int cma_verify_rep(struct rdma_id_private *id_priv, void *data)
960219820Sjeff{
961219820Sjeff	if (id_priv->id.ps == RDMA_PS_SDP &&
962219820Sjeff	    sdp_get_majv(((struct sdp_hah *) data)->sdp_version) !=
963219820Sjeff	    SDP_MAJ_VERSION)
964219820Sjeff		return -EINVAL;
965219820Sjeff
966219820Sjeff	return 0;
967219820Sjeff}
968219820Sjeff
969219820Sjeffstatic void cma_set_rep_event_data(struct rdma_cm_event *event,
970219820Sjeff				   struct ib_cm_rep_event_param *rep_data,
971219820Sjeff				   void *private_data)
972219820Sjeff{
973219820Sjeff	event->param.conn.private_data = private_data;
974219820Sjeff	event->param.conn.private_data_len = IB_CM_REP_PRIVATE_DATA_SIZE;
975219820Sjeff	event->param.conn.responder_resources = rep_data->responder_resources;
976219820Sjeff	event->param.conn.initiator_depth = rep_data->initiator_depth;
977219820Sjeff	event->param.conn.flow_control = rep_data->flow_control;
978219820Sjeff	event->param.conn.rnr_retry_count = rep_data->rnr_retry_count;
979219820Sjeff	event->param.conn.srq = rep_data->srq;
980219820Sjeff	event->param.conn.qp_num = rep_data->remote_qpn;
981219820Sjeff}
982219820Sjeff
983219820Sjeffstatic int cma_ib_handler(struct ib_cm_id *cm_id, struct ib_cm_event *ib_event)
984219820Sjeff{
985219820Sjeff	struct rdma_id_private *id_priv = cm_id->context;
986219820Sjeff	struct rdma_cm_event event;
987219820Sjeff	int ret = 0;
988219820Sjeff
989219820Sjeff	if ((ib_event->event != IB_CM_TIMEWAIT_EXIT &&
990219820Sjeff		cma_disable_callback(id_priv, CMA_CONNECT)) ||
991219820Sjeff	    (ib_event->event == IB_CM_TIMEWAIT_EXIT &&
992219820Sjeff		cma_disable_callback(id_priv, CMA_DISCONNECT)))
993219820Sjeff		return 0;
994219820Sjeff
995219820Sjeff	memset(&event, 0, sizeof event);
996219820Sjeff	switch (ib_event->event) {
997219820Sjeff	case IB_CM_REQ_ERROR:
998219820Sjeff	case IB_CM_REP_ERROR:
999219820Sjeff		event.event = RDMA_CM_EVENT_UNREACHABLE;
1000219820Sjeff		event.status = -ETIMEDOUT;
1001219820Sjeff		break;
1002219820Sjeff	case IB_CM_REP_RECEIVED:
1003219820Sjeff		event.status = cma_verify_rep(id_priv, ib_event->private_data);
1004219820Sjeff		if (event.status)
1005219820Sjeff			event.event = RDMA_CM_EVENT_CONNECT_ERROR;
1006219820Sjeff		else if (id_priv->id.qp && id_priv->id.ps != RDMA_PS_SDP) {
1007219820Sjeff			event.status = cma_rep_recv(id_priv);
1008219820Sjeff			event.event = event.status ? RDMA_CM_EVENT_CONNECT_ERROR :
1009219820Sjeff						     RDMA_CM_EVENT_ESTABLISHED;
1010219820Sjeff		} else
1011219820Sjeff			event.event = RDMA_CM_EVENT_CONNECT_RESPONSE;
1012219820Sjeff		cma_set_rep_event_data(&event, &ib_event->param.rep_rcvd,
1013219820Sjeff				       ib_event->private_data);
1014219820Sjeff		break;
1015219820Sjeff	case IB_CM_RTU_RECEIVED:
1016219820Sjeff	case IB_CM_USER_ESTABLISHED:
1017219820Sjeff		event.event = RDMA_CM_EVENT_ESTABLISHED;
1018219820Sjeff		break;
1019219820Sjeff	case IB_CM_DREQ_ERROR:
1020219820Sjeff		event.status = -ETIMEDOUT; /* fall through */
1021219820Sjeff	case IB_CM_DREQ_RECEIVED:
1022219820Sjeff	case IB_CM_DREP_RECEIVED:
1023219820Sjeff		if (!cma_comp_exch(id_priv, CMA_CONNECT, CMA_DISCONNECT))
1024219820Sjeff			goto out;
1025219820Sjeff		event.event = RDMA_CM_EVENT_DISCONNECTED;
1026219820Sjeff		break;
1027219820Sjeff	case IB_CM_TIMEWAIT_EXIT:
1028219820Sjeff		event.event = RDMA_CM_EVENT_TIMEWAIT_EXIT;
1029219820Sjeff		break;
1030219820Sjeff	case IB_CM_MRA_RECEIVED:
1031219820Sjeff		/* ignore event */
1032219820Sjeff		goto out;
1033219820Sjeff	case IB_CM_REJ_RECEIVED:
1034219820Sjeff		cma_modify_qp_err(id_priv);
1035219820Sjeff		event.status = ib_event->param.rej_rcvd.reason;
1036219820Sjeff		event.event = RDMA_CM_EVENT_REJECTED;
1037219820Sjeff		event.param.conn.private_data = ib_event->private_data;
1038219820Sjeff		event.param.conn.private_data_len = IB_CM_REJ_PRIVATE_DATA_SIZE;
1039219820Sjeff		break;
1040219820Sjeff	default:
1041219820Sjeff		printk(KERN_ERR "RDMA CMA: unexpected IB CM event: %d\n",
1042219820Sjeff		       ib_event->event);
1043219820Sjeff		goto out;
1044219820Sjeff	}
1045219820Sjeff
1046219820Sjeff	ret = id_priv->id.event_handler(&id_priv->id, &event);
1047219820Sjeff	if (ret) {
1048219820Sjeff		/* Destroy the CM ID by returning a non-zero value. */
1049219820Sjeff		id_priv->cm_id.ib = NULL;
1050219820Sjeff		cma_exch(id_priv, CMA_DESTROYING);
1051219820Sjeff		mutex_unlock(&id_priv->handler_mutex);
1052219820Sjeff		rdma_destroy_id(&id_priv->id);
1053219820Sjeff		return ret;
1054219820Sjeff	}
1055219820Sjeffout:
1056219820Sjeff	mutex_unlock(&id_priv->handler_mutex);
1057219820Sjeff	return ret;
1058219820Sjeff}
1059219820Sjeff
1060219820Sjeffstatic struct rdma_id_private *cma_new_conn_id(struct rdma_cm_id *listen_id,
1061219820Sjeff					       struct ib_cm_event *ib_event)
1062219820Sjeff{
1063219820Sjeff	struct rdma_id_private *id_priv;
1064219820Sjeff	struct rdma_cm_id *id;
1065219820Sjeff	struct rdma_route *rt;
1066219820Sjeff	union cma_ip_addr *src, *dst;
1067219820Sjeff	__be16 port;
1068219820Sjeff	u8 ip_ver;
1069219820Sjeff	int ret;
1070219820Sjeff
1071219820Sjeff	if (cma_get_net_info(ib_event->private_data, listen_id->ps,
1072219820Sjeff			     &ip_ver, &port, &src, &dst))
1073219820Sjeff		goto err;
1074219820Sjeff
1075219820Sjeff	id = rdma_create_id(listen_id->event_handler, listen_id->context,
1076219820Sjeff			    listen_id->ps);
1077219820Sjeff	if (IS_ERR(id))
1078219820Sjeff		goto err;
1079219820Sjeff
1080219820Sjeff	cma_save_net_info(&id->route.addr, &listen_id->route.addr,
1081219820Sjeff			  ip_ver, port, src, dst);
1082219820Sjeff
1083219820Sjeff	rt = &id->route;
1084219820Sjeff	rt->num_paths = ib_event->param.req_rcvd.alternate_path ? 2 : 1;
1085219820Sjeff	rt->path_rec = kmalloc(sizeof *rt->path_rec * rt->num_paths,
1086219820Sjeff			       GFP_KERNEL);
1087219820Sjeff	if (!rt->path_rec)
1088219820Sjeff		goto destroy_id;
1089219820Sjeff
1090219820Sjeff	rt->path_rec[0] = *ib_event->param.req_rcvd.primary_path;
1091219820Sjeff	if (rt->num_paths == 2)
1092219820Sjeff		rt->path_rec[1] = *ib_event->param.req_rcvd.alternate_path;
1093219820Sjeff
1094219820Sjeff	if (cma_any_addr((struct sockaddr *) &rt->addr.src_addr)) {
1095219820Sjeff		rt->addr.dev_addr.dev_type = ARPHRD_INFINIBAND;
1096219820Sjeff		rdma_addr_set_sgid(&rt->addr.dev_addr, &rt->path_rec[0].sgid);
1097219820Sjeff		ib_addr_set_pkey(&rt->addr.dev_addr, rt->path_rec[0].pkey);
1098219820Sjeff	} else {
1099219820Sjeff		ret = rdma_translate_ip((struct sockaddr *) &rt->addr.src_addr,
1100219820Sjeff					&rt->addr.dev_addr);
1101219820Sjeff		if (ret)
1102219820Sjeff			goto destroy_id;
1103219820Sjeff	}
1104219820Sjeff	rdma_addr_set_dgid(&rt->addr.dev_addr, &rt->path_rec[0].dgid);
1105219820Sjeff
1106219820Sjeff	id_priv = container_of(id, struct rdma_id_private, id);
1107219820Sjeff	id_priv->state = CMA_CONNECT;
1108219820Sjeff	return id_priv;
1109219820Sjeff
1110219820Sjeffdestroy_id:
1111219820Sjeff	rdma_destroy_id(id);
1112219820Sjefferr:
1113219820Sjeff	return NULL;
1114219820Sjeff}
1115219820Sjeff
1116219820Sjeffstatic struct rdma_id_private *cma_new_udp_id(struct rdma_cm_id *listen_id,
1117219820Sjeff					      struct ib_cm_event *ib_event)
1118219820Sjeff{
1119219820Sjeff	struct rdma_id_private *id_priv;
1120219820Sjeff	struct rdma_cm_id *id;
1121219820Sjeff	union cma_ip_addr *src, *dst;
1122219820Sjeff	__be16 port;
1123219820Sjeff	u8 ip_ver;
1124219820Sjeff	int ret;
1125219820Sjeff
1126219820Sjeff	id = rdma_create_id(listen_id->event_handler, listen_id->context,
1127219820Sjeff			    listen_id->ps);
1128219820Sjeff	if (IS_ERR(id))
1129219820Sjeff		return NULL;
1130219820Sjeff
1131219820Sjeff
1132219820Sjeff	if (cma_get_net_info(ib_event->private_data, listen_id->ps,
1133219820Sjeff			     &ip_ver, &port, &src, &dst))
1134219820Sjeff		goto err;
1135219820Sjeff
1136219820Sjeff	cma_save_net_info(&id->route.addr, &listen_id->route.addr,
1137219820Sjeff			  ip_ver, port, src, dst);
1138219820Sjeff
1139219820Sjeff	if (!cma_any_addr((struct sockaddr *) &id->route.addr.src_addr)) {
1140219820Sjeff		ret = rdma_translate_ip((struct sockaddr *) &id->route.addr.src_addr,
1141219820Sjeff					&id->route.addr.dev_addr);
1142219820Sjeff		if (ret)
1143219820Sjeff			goto err;
1144219820Sjeff	}
1145219820Sjeff
1146219820Sjeff	id_priv = container_of(id, struct rdma_id_private, id);
1147219820Sjeff	id_priv->state = CMA_CONNECT;
1148219820Sjeff	return id_priv;
1149219820Sjefferr:
1150219820Sjeff	rdma_destroy_id(id);
1151219820Sjeff	return NULL;
1152219820Sjeff}
1153219820Sjeff
1154219820Sjeffstatic void cma_set_req_event_data(struct rdma_cm_event *event,
1155219820Sjeff				   struct ib_cm_req_event_param *req_data,
1156219820Sjeff				   void *private_data, int offset)
1157219820Sjeff{
1158219820Sjeff	event->param.conn.private_data = private_data + offset;
1159219820Sjeff	event->param.conn.private_data_len = IB_CM_REQ_PRIVATE_DATA_SIZE - offset;
1160219820Sjeff	event->param.conn.responder_resources = req_data->responder_resources;
1161219820Sjeff	event->param.conn.initiator_depth = req_data->initiator_depth;
1162219820Sjeff	event->param.conn.flow_control = req_data->flow_control;
1163219820Sjeff	event->param.conn.retry_count = req_data->retry_count;
1164219820Sjeff	event->param.conn.rnr_retry_count = req_data->rnr_retry_count;
1165219820Sjeff	event->param.conn.srq = req_data->srq;
1166219820Sjeff	event->param.conn.qp_num = req_data->remote_qpn;
1167219820Sjeff}
1168219820Sjeff
1169219820Sjeffstatic int cma_req_handler(struct ib_cm_id *cm_id, struct ib_cm_event *ib_event)
1170219820Sjeff{
1171219820Sjeff	struct rdma_id_private *listen_id, *conn_id;
1172219820Sjeff	struct rdma_cm_event event;
1173219820Sjeff	int offset, ret;
1174219820Sjeff
1175219820Sjeff	listen_id = cm_id->context;
1176219820Sjeff	if (cma_disable_callback(listen_id, CMA_LISTEN))
1177219820Sjeff		return -ECONNABORTED;
1178219820Sjeff
1179219820Sjeff	memset(&event, 0, sizeof event);
1180219820Sjeff	offset = cma_user_data_offset(listen_id->id.ps);
1181219820Sjeff	event.event = RDMA_CM_EVENT_CONNECT_REQUEST;
1182219820Sjeff	if (cma_is_ud_ps(listen_id->id.ps)) {
1183219820Sjeff		conn_id = cma_new_udp_id(&listen_id->id, ib_event);
1184219820Sjeff		event.param.ud.private_data = ib_event->private_data + offset;
1185219820Sjeff		event.param.ud.private_data_len =
1186219820Sjeff				IB_CM_SIDR_REQ_PRIVATE_DATA_SIZE - offset;
1187219820Sjeff	} else {
1188219820Sjeff		conn_id = cma_new_conn_id(&listen_id->id, ib_event);
1189219820Sjeff		cma_set_req_event_data(&event, &ib_event->param.req_rcvd,
1190219820Sjeff				       ib_event->private_data, offset);
1191219820Sjeff	}
1192219820Sjeff	if (!conn_id) {
1193219820Sjeff		ret = -ENOMEM;
1194219820Sjeff		goto out;
1195219820Sjeff	}
1196219820Sjeff
1197219820Sjeff	mutex_lock_nested(&conn_id->handler_mutex, SINGLE_DEPTH_NESTING);
1198219820Sjeff	mutex_lock(&lock);
1199219820Sjeff	ret = cma_acquire_dev(conn_id);
1200219820Sjeff	mutex_unlock(&lock);
1201219820Sjeff	if (ret)
1202219820Sjeff		goto release_conn_id;
1203219820Sjeff
1204219820Sjeff	conn_id->cm_id.ib = cm_id;
1205219820Sjeff	cm_id->context = conn_id;
1206219820Sjeff	cm_id->cm_handler = cma_ib_handler;
1207219820Sjeff
1208219820Sjeff	ret = conn_id->id.event_handler(&conn_id->id, &event);
1209219820Sjeff	if (!ret) {
1210219820Sjeff		/*
1211219820Sjeff		 * Acquire mutex to prevent user executing rdma_destroy_id()
1212219820Sjeff		 * while we're accessing the cm_id.
1213219820Sjeff		 */
1214219820Sjeff		mutex_lock(&lock);
1215219820Sjeff		if (cma_comp(conn_id, CMA_CONNECT) &&
1216219820Sjeff		    !cma_is_ud_ps(conn_id->id.ps))
1217219820Sjeff			ib_send_cm_mra(cm_id, CMA_CM_MRA_SETTING, NULL, 0);
1218219820Sjeff		mutex_unlock(&lock);
1219219820Sjeff		mutex_unlock(&conn_id->handler_mutex);
1220219820Sjeff		goto out;
1221219820Sjeff	}
1222219820Sjeff
1223219820Sjeff	/* Destroy the CM ID by returning a non-zero value. */
1224219820Sjeff	conn_id->cm_id.ib = NULL;
1225219820Sjeff
1226219820Sjeffrelease_conn_id:
1227219820Sjeff	cma_exch(conn_id, CMA_DESTROYING);
1228219820Sjeff	mutex_unlock(&conn_id->handler_mutex);
1229219820Sjeff	rdma_destroy_id(&conn_id->id);
1230219820Sjeff
1231219820Sjeffout:
1232219820Sjeff	mutex_unlock(&listen_id->handler_mutex);
1233219820Sjeff	return ret;
1234219820Sjeff}
1235219820Sjeff
1236219820Sjeffstatic __be64 cma_get_service_id(enum rdma_port_space ps, struct sockaddr *addr)
1237219820Sjeff{
1238219820Sjeff	return cpu_to_be64(((u64)ps << 16) + be16_to_cpu(cma_port(addr)));
1239219820Sjeff}
1240219820Sjeff
1241219820Sjeffstatic void cma_set_compare_data(enum rdma_port_space ps, struct sockaddr *addr,
1242219820Sjeff				 struct ib_cm_compare_data *compare)
1243219820Sjeff{
1244219820Sjeff	struct cma_hdr *cma_data, *cma_mask;
1245219820Sjeff	struct sdp_hh *sdp_data, *sdp_mask;
1246219820Sjeff	__be32 ip4_addr;
1247239748Sjhb#ifdef INET6
1248219820Sjeff	struct in6_addr ip6_addr;
1249239748Sjhb#endif
1250219820Sjeff
1251219820Sjeff	memset(compare, 0, sizeof *compare);
1252219820Sjeff	cma_data = (void *) compare->data;
1253219820Sjeff	cma_mask = (void *) compare->mask;
1254219820Sjeff	sdp_data = (void *) compare->data;
1255219820Sjeff	sdp_mask = (void *) compare->mask;
1256219820Sjeff
1257219820Sjeff	switch (addr->sa_family) {
1258219820Sjeff	case AF_INET:
1259219820Sjeff		ip4_addr = ((struct sockaddr_in *) addr)->sin_addr.s_addr;
1260219820Sjeff		if (ps == RDMA_PS_SDP) {
1261219820Sjeff			sdp_set_ip_ver(sdp_data, 4);
1262219820Sjeff			sdp_set_ip_ver(sdp_mask, 0xF);
1263219820Sjeff			sdp_data->dst_addr.ip4.addr = ip4_addr;
1264219820Sjeff			sdp_mask->dst_addr.ip4.addr = htonl(~0);
1265219820Sjeff		} else {
1266219820Sjeff			cma_set_ip_ver(cma_data, 4);
1267219820Sjeff			cma_set_ip_ver(cma_mask, 0xF);
1268219820Sjeff			cma_data->dst_addr.ip4.addr = ip4_addr;
1269219820Sjeff			cma_mask->dst_addr.ip4.addr = htonl(~0);
1270219820Sjeff		}
1271219820Sjeff		break;
1272219820Sjeff#ifdef INET6
1273219820Sjeff	case AF_INET6:
1274219820Sjeff		ip6_addr = ((struct sockaddr_in6 *) addr)->sin6_addr;
1275219820Sjeff		if (ps == RDMA_PS_SDP) {
1276219820Sjeff			sdp_set_ip_ver(sdp_data, 6);
1277219820Sjeff			sdp_set_ip_ver(sdp_mask, 0xF);
1278219820Sjeff			sdp_data->dst_addr.ip6 = ip6_addr;
1279219820Sjeff			memset(&sdp_mask->dst_addr.ip6, 0xFF,
1280219820Sjeff			       sizeof sdp_mask->dst_addr.ip6);
1281219820Sjeff		} else {
1282219820Sjeff			cma_set_ip_ver(cma_data, 6);
1283219820Sjeff			cma_set_ip_ver(cma_mask, 0xF);
1284219820Sjeff			cma_data->dst_addr.ip6 = ip6_addr;
1285219820Sjeff			memset(&cma_mask->dst_addr.ip6, 0xFF,
1286219820Sjeff			       sizeof cma_mask->dst_addr.ip6);
1287219820Sjeff		}
1288219820Sjeff		break;
1289219820Sjeff#endif
1290219820Sjeff	default:
1291219820Sjeff		break;
1292219820Sjeff	}
1293219820Sjeff}
1294219820Sjeff
1295219820Sjeffstatic int cma_iw_handler(struct iw_cm_id *iw_id, struct iw_cm_event *iw_event)
1296219820Sjeff{
1297219820Sjeff	struct rdma_id_private *id_priv = iw_id->context;
1298219820Sjeff	struct rdma_cm_event event;
1299219820Sjeff	struct sockaddr_in *sin;
1300219820Sjeff	int ret = 0;
1301219820Sjeff
1302219820Sjeff	if (cma_disable_callback(id_priv, CMA_CONNECT))
1303219820Sjeff		return 0;
1304219820Sjeff
1305219820Sjeff	memset(&event, 0, sizeof event);
1306219820Sjeff	switch (iw_event->event) {
1307219820Sjeff	case IW_CM_EVENT_CLOSE:
1308219820Sjeff		event.event = RDMA_CM_EVENT_DISCONNECTED;
1309219820Sjeff		break;
1310219820Sjeff	case IW_CM_EVENT_CONNECT_REPLY:
1311219820Sjeff		sin = (struct sockaddr_in *) &id_priv->id.route.addr.src_addr;
1312219820Sjeff		*sin = iw_event->local_addr;
1313219820Sjeff		sin = (struct sockaddr_in *) &id_priv->id.route.addr.dst_addr;
1314219820Sjeff		*sin = iw_event->remote_addr;
1315243375Sdim		switch ((int)iw_event->status) {
1316219820Sjeff		case 0:
1317219820Sjeff			event.event = RDMA_CM_EVENT_ESTABLISHED;
1318219820Sjeff			break;
1319219820Sjeff		case -ECONNRESET:
1320219820Sjeff		case -ECONNREFUSED:
1321219820Sjeff			event.event = RDMA_CM_EVENT_REJECTED;
1322219820Sjeff			break;
1323219820Sjeff		case -ETIMEDOUT:
1324219820Sjeff			event.event = RDMA_CM_EVENT_UNREACHABLE;
1325219820Sjeff			break;
1326219820Sjeff		default:
1327219820Sjeff			event.event = RDMA_CM_EVENT_CONNECT_ERROR;
1328219820Sjeff			break;
1329219820Sjeff		}
1330219820Sjeff		break;
1331219820Sjeff	case IW_CM_EVENT_ESTABLISHED:
1332219820Sjeff		event.event = RDMA_CM_EVENT_ESTABLISHED;
1333219820Sjeff		break;
1334219820Sjeff	default:
1335219820Sjeff		BUG_ON(1);
1336219820Sjeff	}
1337219820Sjeff
1338219820Sjeff	event.status = iw_event->status;
1339219820Sjeff	event.param.conn.private_data = iw_event->private_data;
1340219820Sjeff	event.param.conn.private_data_len = iw_event->private_data_len;
1341219820Sjeff	ret = id_priv->id.event_handler(&id_priv->id, &event);
1342219820Sjeff	if (ret) {
1343219820Sjeff		/* Destroy the CM ID by returning a non-zero value. */
1344219820Sjeff		id_priv->cm_id.iw = NULL;
1345219820Sjeff		cma_exch(id_priv, CMA_DESTROYING);
1346219820Sjeff		mutex_unlock(&id_priv->handler_mutex);
1347219820Sjeff		rdma_destroy_id(&id_priv->id);
1348219820Sjeff		return ret;
1349219820Sjeff	}
1350219820Sjeff
1351219820Sjeff	mutex_unlock(&id_priv->handler_mutex);
1352219820Sjeff	return ret;
1353219820Sjeff}
1354219820Sjeff
1355219820Sjeffstatic int iw_conn_req_handler(struct iw_cm_id *cm_id,
1356219820Sjeff			       struct iw_cm_event *iw_event)
1357219820Sjeff{
1358219820Sjeff	struct rdma_cm_id *new_cm_id;
1359219820Sjeff	struct rdma_id_private *listen_id, *conn_id;
1360219820Sjeff	struct sockaddr_in *sin;
1361219820Sjeff	struct net_device *dev = NULL;
1362219820Sjeff	struct rdma_cm_event event;
1363219820Sjeff	int ret;
1364219820Sjeff	struct ib_device_attr attr;
1365219820Sjeff
1366219820Sjeff	listen_id = cm_id->context;
1367219820Sjeff	if (cma_disable_callback(listen_id, CMA_LISTEN))
1368219820Sjeff		return -ECONNABORTED;
1369219820Sjeff
1370219820Sjeff	/* Create a new RDMA id for the new IW CM ID */
1371219820Sjeff	new_cm_id = rdma_create_id(listen_id->id.event_handler,
1372219820Sjeff				   listen_id->id.context,
1373219820Sjeff				   RDMA_PS_TCP);
1374219820Sjeff	if (IS_ERR(new_cm_id)) {
1375219820Sjeff		ret = -ENOMEM;
1376219820Sjeff		goto out;
1377219820Sjeff	}
1378219820Sjeff	conn_id = container_of(new_cm_id, struct rdma_id_private, id);
1379219820Sjeff	mutex_lock_nested(&conn_id->handler_mutex, SINGLE_DEPTH_NESTING);
1380219820Sjeff	conn_id->state = CMA_CONNECT;
1381219820Sjeff
1382219820Sjeff	dev = ip_dev_find(NULL, iw_event->local_addr.sin_addr.s_addr);
1383219820Sjeff	if (!dev) {
1384219820Sjeff		ret = -EADDRNOTAVAIL;
1385219820Sjeff		mutex_unlock(&conn_id->handler_mutex);
1386219820Sjeff		rdma_destroy_id(new_cm_id);
1387219820Sjeff		goto out;
1388219820Sjeff	}
1389219820Sjeff	ret = rdma_copy_addr(&conn_id->id.route.addr.dev_addr, dev, NULL);
1390219820Sjeff	if (ret) {
1391219820Sjeff		mutex_unlock(&conn_id->handler_mutex);
1392219820Sjeff		rdma_destroy_id(new_cm_id);
1393219820Sjeff		goto out;
1394219820Sjeff	}
1395219820Sjeff
1396219820Sjeff	mutex_lock(&lock);
1397219820Sjeff	ret = cma_acquire_dev(conn_id);
1398219820Sjeff	mutex_unlock(&lock);
1399219820Sjeff	if (ret) {
1400219820Sjeff		mutex_unlock(&conn_id->handler_mutex);
1401219820Sjeff		rdma_destroy_id(new_cm_id);
1402219820Sjeff		goto out;
1403219820Sjeff	}
1404219820Sjeff
1405219820Sjeff	conn_id->cm_id.iw = cm_id;
1406219820Sjeff	cm_id->context = conn_id;
1407219820Sjeff	cm_id->cm_handler = cma_iw_handler;
1408219820Sjeff
1409219820Sjeff	sin = (struct sockaddr_in *) &new_cm_id->route.addr.src_addr;
1410219820Sjeff	*sin = iw_event->local_addr;
1411219820Sjeff	sin = (struct sockaddr_in *) &new_cm_id->route.addr.dst_addr;
1412219820Sjeff	*sin = iw_event->remote_addr;
1413219820Sjeff
1414219820Sjeff	ret = ib_query_device(conn_id->id.device, &attr);
1415219820Sjeff	if (ret) {
1416219820Sjeff		mutex_unlock(&conn_id->handler_mutex);
1417219820Sjeff		rdma_destroy_id(new_cm_id);
1418219820Sjeff		goto out;
1419219820Sjeff	}
1420219820Sjeff
1421219820Sjeff	memset(&event, 0, sizeof event);
1422219820Sjeff	event.event = RDMA_CM_EVENT_CONNECT_REQUEST;
1423219820Sjeff	event.param.conn.private_data = iw_event->private_data;
1424219820Sjeff	event.param.conn.private_data_len = iw_event->private_data_len;
1425219820Sjeff	event.param.conn.initiator_depth = attr.max_qp_init_rd_atom;
1426219820Sjeff	event.param.conn.responder_resources = attr.max_qp_rd_atom;
1427219820Sjeff	ret = conn_id->id.event_handler(&conn_id->id, &event);
1428219820Sjeff	if (ret) {
1429219820Sjeff		/* User wants to destroy the CM ID */
1430219820Sjeff		conn_id->cm_id.iw = NULL;
1431219820Sjeff		cma_exch(conn_id, CMA_DESTROYING);
1432219820Sjeff		mutex_unlock(&conn_id->handler_mutex);
1433219820Sjeff		rdma_destroy_id(&conn_id->id);
1434219820Sjeff		goto out;
1435219820Sjeff	}
1436219820Sjeff
1437219820Sjeff	mutex_unlock(&conn_id->handler_mutex);
1438219820Sjeff
1439219820Sjeffout:
1440219820Sjeff	if (dev)
1441219820Sjeff		dev_put(dev);
1442219820Sjeff	mutex_unlock(&listen_id->handler_mutex);
1443219820Sjeff	return ret;
1444219820Sjeff}
1445219820Sjeff
1446219820Sjeffstatic int cma_ib_listen(struct rdma_id_private *id_priv)
1447219820Sjeff{
1448219820Sjeff	struct ib_cm_compare_data compare_data;
1449219820Sjeff	struct sockaddr *addr;
1450219820Sjeff	__be64 svc_id;
1451219820Sjeff	int ret;
1452219820Sjeff
1453219820Sjeff	id_priv->cm_id.ib = ib_create_cm_id(id_priv->id.device, cma_req_handler,
1454219820Sjeff					    id_priv);
1455219820Sjeff	if (IS_ERR(id_priv->cm_id.ib))
1456219820Sjeff		return PTR_ERR(id_priv->cm_id.ib);
1457219820Sjeff
1458219820Sjeff	addr = (struct sockaddr *) &id_priv->id.route.addr.src_addr;
1459219820Sjeff	svc_id = cma_get_service_id(id_priv->id.ps, addr);
1460219820Sjeff	if (cma_any_addr(addr))
1461219820Sjeff		ret = ib_cm_listen(id_priv->cm_id.ib, svc_id, 0, NULL);
1462219820Sjeff	else {
1463219820Sjeff		cma_set_compare_data(id_priv->id.ps, addr, &compare_data);
1464219820Sjeff		ret = ib_cm_listen(id_priv->cm_id.ib, svc_id, 0, &compare_data);
1465219820Sjeff	}
1466219820Sjeff
1467219820Sjeff	if (ret) {
1468219820Sjeff		ib_destroy_cm_id(id_priv->cm_id.ib);
1469219820Sjeff		id_priv->cm_id.ib = NULL;
1470219820Sjeff	}
1471219820Sjeff
1472219820Sjeff	return ret;
1473219820Sjeff}
1474219820Sjeff
1475219820Sjeffstatic int cma_iw_listen(struct rdma_id_private *id_priv, int backlog)
1476219820Sjeff{
1477219820Sjeff	int ret;
1478219820Sjeff	struct sockaddr_in *sin;
1479219820Sjeff
1480219820Sjeff	id_priv->cm_id.iw = iw_create_cm_id(id_priv->id.device,
1481252555Snp					    id_priv->sock,
1482219820Sjeff					    iw_conn_req_handler,
1483219820Sjeff					    id_priv);
1484219820Sjeff	if (IS_ERR(id_priv->cm_id.iw))
1485219820Sjeff		return PTR_ERR(id_priv->cm_id.iw);
1486219820Sjeff
1487219820Sjeff	sin = (struct sockaddr_in *) &id_priv->id.route.addr.src_addr;
1488219820Sjeff	id_priv->cm_id.iw->local_addr = *sin;
1489219820Sjeff
1490219820Sjeff	ret = iw_cm_listen(id_priv->cm_id.iw, backlog);
1491219820Sjeff
1492219820Sjeff	if (ret) {
1493219820Sjeff		iw_destroy_cm_id(id_priv->cm_id.iw);
1494219820Sjeff		id_priv->cm_id.iw = NULL;
1495219820Sjeff	}
1496219820Sjeff
1497219820Sjeff	return ret;
1498219820Sjeff}
1499219820Sjeff
1500219820Sjeffstatic int cma_listen_handler(struct rdma_cm_id *id,
1501219820Sjeff			      struct rdma_cm_event *event)
1502219820Sjeff{
1503219820Sjeff	struct rdma_id_private *id_priv = id->context;
1504219820Sjeff
1505219820Sjeff	id->context = id_priv->id.context;
1506219820Sjeff	id->event_handler = id_priv->id.event_handler;
1507219820Sjeff	return id_priv->id.event_handler(id, event);
1508219820Sjeff}
1509219820Sjeff
1510219820Sjeffstatic void cma_listen_on_dev(struct rdma_id_private *id_priv,
1511219820Sjeff			      struct cma_device *cma_dev)
1512219820Sjeff{
1513219820Sjeff	struct rdma_id_private *dev_id_priv;
1514219820Sjeff	struct rdma_cm_id *id;
1515219820Sjeff	int ret;
1516219820Sjeff
1517219820Sjeff	id = rdma_create_id(cma_listen_handler, id_priv, id_priv->id.ps);
1518219820Sjeff	if (IS_ERR(id))
1519219820Sjeff		return;
1520219820Sjeff
1521219820Sjeff	dev_id_priv = container_of(id, struct rdma_id_private, id);
1522219820Sjeff
1523219820Sjeff	dev_id_priv->state = CMA_ADDR_BOUND;
1524219820Sjeff	memcpy(&id->route.addr.src_addr, &id_priv->id.route.addr.src_addr,
1525219820Sjeff	       ip_addr_size((struct sockaddr *) &id_priv->id.route.addr.src_addr));
1526219820Sjeff
1527219820Sjeff	cma_attach_to_dev(dev_id_priv, cma_dev);
1528219820Sjeff	list_add_tail(&dev_id_priv->listen_list, &id_priv->listen_list);
1529219820Sjeff	atomic_inc(&id_priv->refcount);
1530219820Sjeff	dev_id_priv->internal_id = 1;
1531219820Sjeff
1532219820Sjeff	ret = rdma_listen(id, id_priv->backlog);
1533219820Sjeff	if (ret)
1534219820Sjeff		printk(KERN_WARNING "RDMA CMA: cma_listen_on_dev, error %d, "
1535219820Sjeff		       "listening on device %s\n", ret, cma_dev->device->name);
1536219820Sjeff}
1537219820Sjeff
1538219820Sjeffstatic void cma_listen_on_all(struct rdma_id_private *id_priv)
1539219820Sjeff{
1540219820Sjeff	struct cma_device *cma_dev;
1541219820Sjeff
1542219820Sjeff	mutex_lock(&lock);
1543219820Sjeff	list_add_tail(&id_priv->list, &listen_any_list);
1544219820Sjeff	list_for_each_entry(cma_dev, &dev_list, list)
1545219820Sjeff		cma_listen_on_dev(id_priv, cma_dev);
1546219820Sjeff	mutex_unlock(&lock);
1547219820Sjeff}
1548219820Sjeff
1549219820Sjeffint rdma_listen(struct rdma_cm_id *id, int backlog)
1550219820Sjeff{
1551219820Sjeff	struct rdma_id_private *id_priv;
1552219820Sjeff	int ret;
1553219820Sjeff
1554219820Sjeff	id_priv = container_of(id, struct rdma_id_private, id);
1555219820Sjeff	if (id_priv->state == CMA_IDLE) {
1556219820Sjeff		((struct sockaddr *) &id->route.addr.src_addr)->sa_family = AF_INET;
1557219820Sjeff		ret = rdma_bind_addr(id, (struct sockaddr *) &id->route.addr.src_addr);
1558219820Sjeff		if (ret)
1559219820Sjeff			return ret;
1560219820Sjeff	}
1561219820Sjeff
1562219820Sjeff	if (!cma_comp_exch(id_priv, CMA_ADDR_BOUND, CMA_LISTEN))
1563219820Sjeff		return -EINVAL;
1564219820Sjeff
1565219820Sjeff	id_priv->backlog = backlog;
1566219820Sjeff	if (id->device) {
1567219820Sjeff		switch (rdma_node_get_transport(id->device->node_type)) {
1568219820Sjeff		case RDMA_TRANSPORT_IB:
1569219820Sjeff			ret = cma_ib_listen(id_priv);
1570219820Sjeff			if (ret)
1571219820Sjeff				goto err;
1572219820Sjeff			break;
1573219820Sjeff		case RDMA_TRANSPORT_IWARP:
1574219820Sjeff			ret = cma_iw_listen(id_priv, backlog);
1575219820Sjeff			if (ret)
1576219820Sjeff				goto err;
1577219820Sjeff			break;
1578219820Sjeff		default:
1579219820Sjeff			ret = -ENOSYS;
1580219820Sjeff			goto err;
1581219820Sjeff		}
1582219820Sjeff	} else
1583219820Sjeff		cma_listen_on_all(id_priv);
1584219820Sjeff
1585219820Sjeff	return 0;
1586219820Sjefferr:
1587219820Sjeff	id_priv->backlog = 0;
1588219820Sjeff	cma_comp_exch(id_priv, CMA_LISTEN, CMA_ADDR_BOUND);
1589219820Sjeff	return ret;
1590219820Sjeff}
1591219820SjeffEXPORT_SYMBOL(rdma_listen);
1592219820Sjeff
1593219820Sjeffvoid rdma_set_service_type(struct rdma_cm_id *id, int tos)
1594219820Sjeff{
1595219820Sjeff	struct rdma_id_private *id_priv;
1596219820Sjeff
1597219820Sjeff	id_priv = container_of(id, struct rdma_id_private, id);
1598219820Sjeff	id_priv->tos = (u8) tos;
1599219820Sjeff}
1600219820SjeffEXPORT_SYMBOL(rdma_set_service_type);
1601219820Sjeff
1602219820Sjeffstatic void cma_query_handler(int status, struct ib_sa_path_rec *path_rec,
1603219820Sjeff			      void *context)
1604219820Sjeff{
1605219820Sjeff	struct cma_work *work = context;
1606219820Sjeff	struct rdma_route *route;
1607219820Sjeff
1608219820Sjeff	route = &work->id->id.route;
1609219820Sjeff
1610219820Sjeff	if (!status) {
1611219820Sjeff		route->num_paths = 1;
1612219820Sjeff		*route->path_rec = *path_rec;
1613219820Sjeff	} else {
1614219820Sjeff		work->old_state = CMA_ROUTE_QUERY;
1615219820Sjeff		work->new_state = CMA_ADDR_RESOLVED;
1616219820Sjeff		work->event.event = RDMA_CM_EVENT_ROUTE_ERROR;
1617219820Sjeff		work->event.status = status;
1618219820Sjeff	}
1619219820Sjeff
1620219820Sjeff	queue_work(cma_wq, &work->work);
1621219820Sjeff}
1622219820Sjeff
1623219820Sjeffstatic int cma_query_ib_route(struct rdma_id_private *id_priv, int timeout_ms,
1624219820Sjeff			      struct cma_work *work)
1625219820Sjeff{
1626219820Sjeff	struct rdma_addr *addr = &id_priv->id.route.addr;
1627219820Sjeff	struct ib_sa_path_rec path_rec;
1628219820Sjeff	ib_sa_comp_mask comp_mask;
1629219820Sjeff	struct sockaddr_in6 *sin6;
1630219820Sjeff
1631219820Sjeff	memset(&path_rec, 0, sizeof path_rec);
1632219820Sjeff	rdma_addr_get_sgid(&addr->dev_addr, &path_rec.sgid);
1633219820Sjeff	rdma_addr_get_dgid(&addr->dev_addr, &path_rec.dgid);
1634219820Sjeff	path_rec.pkey = cpu_to_be16(ib_addr_get_pkey(&addr->dev_addr));
1635219820Sjeff	path_rec.numb_path = 1;
1636219820Sjeff	path_rec.reversible = 1;
1637219820Sjeff	path_rec.service_id = cma_get_service_id(id_priv->id.ps,
1638219820Sjeff							(struct sockaddr *) &addr->dst_addr);
1639219820Sjeff
1640219820Sjeff	comp_mask = IB_SA_PATH_REC_DGID | IB_SA_PATH_REC_SGID |
1641219820Sjeff		    IB_SA_PATH_REC_PKEY | IB_SA_PATH_REC_NUMB_PATH |
1642219820Sjeff		    IB_SA_PATH_REC_REVERSIBLE | IB_SA_PATH_REC_SERVICE_ID;
1643219820Sjeff
1644219820Sjeff	if (addr->src_addr.ss_family == AF_INET) {
1645219820Sjeff		path_rec.qos_class = cpu_to_be16((u16) id_priv->tos);
1646219820Sjeff		comp_mask |= IB_SA_PATH_REC_QOS_CLASS;
1647219820Sjeff	} else {
1648219820Sjeff		sin6 = (struct sockaddr_in6 *) &addr->src_addr;
1649219820Sjeff		path_rec.traffic_class = (u8) (be32_to_cpu(sin6->sin6_flowinfo) >> 20);
1650219820Sjeff		comp_mask |= IB_SA_PATH_REC_TRAFFIC_CLASS;
1651219820Sjeff	}
1652219820Sjeff
1653219820Sjeff	if (tavor_quirk) {
1654219820Sjeff		path_rec.mtu_selector = IB_SA_LT;
1655219820Sjeff		path_rec.mtu = IB_MTU_2048;
1656219820Sjeff	}
1657219820Sjeff
1658219820Sjeff	id_priv->query_id = ib_sa_path_rec_get(&sa_client, id_priv->id.device,
1659219820Sjeff					       id_priv->id.port_num, &path_rec,
1660219820Sjeff					       comp_mask, timeout_ms,
1661219820Sjeff					       GFP_KERNEL, cma_query_handler,
1662219820Sjeff					       work, &id_priv->query);
1663219820Sjeff
1664219820Sjeff	return (id_priv->query_id < 0) ? id_priv->query_id : 0;
1665219820Sjeff}
1666219820Sjeff
1667219820Sjeffstatic void cma_work_handler(struct work_struct *_work)
1668219820Sjeff{
1669219820Sjeff	struct cma_work *work = container_of(_work, struct cma_work, work);
1670219820Sjeff	struct rdma_id_private *id_priv = work->id;
1671219820Sjeff	int destroy = 0;
1672219820Sjeff
1673219820Sjeff	mutex_lock(&id_priv->handler_mutex);
1674219820Sjeff	if (!cma_comp_exch(id_priv, work->old_state, work->new_state))
1675219820Sjeff		goto out;
1676219820Sjeff
1677219820Sjeff	if (id_priv->id.event_handler(&id_priv->id, &work->event)) {
1678219820Sjeff		cma_exch(id_priv, CMA_DESTROYING);
1679219820Sjeff		destroy = 1;
1680219820Sjeff	}
1681219820Sjeffout:
1682219820Sjeff	mutex_unlock(&id_priv->handler_mutex);
1683219820Sjeff	cma_deref_id(id_priv);
1684219820Sjeff	if (destroy)
1685219820Sjeff		rdma_destroy_id(&id_priv->id);
1686219820Sjeff	kfree(work);
1687219820Sjeff}
1688219820Sjeff
1689219820Sjeffstatic void cma_ndev_work_handler(struct work_struct *_work)
1690219820Sjeff{
1691219820Sjeff	struct cma_ndev_work *work = container_of(_work, struct cma_ndev_work, work);
1692219820Sjeff	struct rdma_id_private *id_priv = work->id;
1693219820Sjeff	int destroy = 0;
1694219820Sjeff
1695219820Sjeff	mutex_lock(&id_priv->handler_mutex);
1696219820Sjeff	if (id_priv->state == CMA_DESTROYING ||
1697219820Sjeff	    id_priv->state == CMA_DEVICE_REMOVAL)
1698219820Sjeff		goto out;
1699219820Sjeff
1700219820Sjeff	if (id_priv->id.event_handler(&id_priv->id, &work->event)) {
1701219820Sjeff		cma_exch(id_priv, CMA_DESTROYING);
1702219820Sjeff		destroy = 1;
1703219820Sjeff	}
1704219820Sjeff
1705219820Sjeffout:
1706219820Sjeff	mutex_unlock(&id_priv->handler_mutex);
1707219820Sjeff	cma_deref_id(id_priv);
1708219820Sjeff	if (destroy)
1709219820Sjeff		rdma_destroy_id(&id_priv->id);
1710219820Sjeff	kfree(work);
1711219820Sjeff}
1712219820Sjeff
1713219820Sjeffstatic int cma_resolve_ib_route(struct rdma_id_private *id_priv, int timeout_ms)
1714219820Sjeff{
1715219820Sjeff	struct rdma_route *route = &id_priv->id.route;
1716219820Sjeff	struct cma_work *work;
1717219820Sjeff	int ret;
1718219820Sjeff
1719219820Sjeff	work = kzalloc(sizeof *work, GFP_KERNEL);
1720219820Sjeff	if (!work)
1721219820Sjeff		return -ENOMEM;
1722219820Sjeff
1723219820Sjeff	work->id = id_priv;
1724219820Sjeff	INIT_WORK(&work->work, cma_work_handler);
1725219820Sjeff	work->old_state = CMA_ROUTE_QUERY;
1726219820Sjeff	work->new_state = CMA_ROUTE_RESOLVED;
1727219820Sjeff	work->event.event = RDMA_CM_EVENT_ROUTE_RESOLVED;
1728219820Sjeff
1729219820Sjeff	route->path_rec = kmalloc(sizeof *route->path_rec, GFP_KERNEL);
1730219820Sjeff	if (!route->path_rec) {
1731219820Sjeff		ret = -ENOMEM;
1732219820Sjeff		goto err1;
1733219820Sjeff	}
1734219820Sjeff
1735219820Sjeff	ret = cma_query_ib_route(id_priv, timeout_ms, work);
1736219820Sjeff	if (ret)
1737219820Sjeff		goto err2;
1738219820Sjeff
1739219820Sjeff	return 0;
1740219820Sjefferr2:
1741219820Sjeff	kfree(route->path_rec);
1742219820Sjeff	route->path_rec = NULL;
1743219820Sjefferr1:
1744219820Sjeff	kfree(work);
1745219820Sjeff	return ret;
1746219820Sjeff}
1747219820Sjeff
1748219820Sjeffint rdma_set_ib_paths(struct rdma_cm_id *id,
1749219820Sjeff		      struct ib_sa_path_rec *path_rec, int num_paths)
1750219820Sjeff{
1751219820Sjeff	struct rdma_id_private *id_priv;
1752219820Sjeff	int ret;
1753219820Sjeff
1754219820Sjeff	id_priv = container_of(id, struct rdma_id_private, id);
1755219820Sjeff	if (!cma_comp_exch(id_priv, CMA_ADDR_RESOLVED, CMA_ROUTE_RESOLVED))
1756219820Sjeff		return -EINVAL;
1757219820Sjeff
1758219820Sjeff	id->route.path_rec = kmalloc(sizeof *path_rec * num_paths, GFP_KERNEL);
1759219820Sjeff	if (!id->route.path_rec) {
1760219820Sjeff		ret = -ENOMEM;
1761219820Sjeff		goto err;
1762219820Sjeff	}
1763219820Sjeff
1764219820Sjeff	memcpy(id->route.path_rec, path_rec, sizeof *path_rec * num_paths);
1765219820Sjeff	return 0;
1766219820Sjefferr:
1767219820Sjeff	cma_comp_exch(id_priv, CMA_ROUTE_RESOLVED, CMA_ADDR_RESOLVED);
1768219820Sjeff	return ret;
1769219820Sjeff}
1770219820SjeffEXPORT_SYMBOL(rdma_set_ib_paths);
1771219820Sjeff
1772219820Sjeffstatic int cma_resolve_iw_route(struct rdma_id_private *id_priv, int timeout_ms)
1773219820Sjeff{
1774219820Sjeff	struct cma_work *work;
1775219820Sjeff
1776219820Sjeff	work = kzalloc(sizeof *work, GFP_KERNEL);
1777219820Sjeff	if (!work)
1778219820Sjeff		return -ENOMEM;
1779219820Sjeff
1780219820Sjeff	work->id = id_priv;
1781219820Sjeff	INIT_WORK(&work->work, cma_work_handler);
1782219820Sjeff	work->old_state = CMA_ROUTE_QUERY;
1783219820Sjeff	work->new_state = CMA_ROUTE_RESOLVED;
1784219820Sjeff	work->event.event = RDMA_CM_EVENT_ROUTE_RESOLVED;
1785219820Sjeff	queue_work(cma_wq, &work->work);
1786219820Sjeff	return 0;
1787219820Sjeff}
1788219820Sjeff
1789219820Sjeffstatic u8 tos_to_sl(u8 tos)
1790219820Sjeff{
1791219820Sjeff	return def_prec2sl & 7;
1792219820Sjeff}
1793219820Sjeff
1794219820Sjeffstatic int cma_resolve_iboe_route(struct rdma_id_private *id_priv)
1795219820Sjeff{
1796219820Sjeff	struct rdma_route *route = &id_priv->id.route;
1797219820Sjeff	struct rdma_addr *addr = &route->addr;
1798219820Sjeff	struct cma_work *work;
1799219820Sjeff	int ret;
1800219820Sjeff	struct sockaddr_in *src_addr = (struct sockaddr_in *)&route->addr.src_addr;
1801219820Sjeff	struct sockaddr_in *dst_addr = (struct sockaddr_in *)&route->addr.dst_addr;
1802219820Sjeff	struct net_device *ndev = NULL;
1803219820Sjeff	u16 vid;
1804219820Sjeff
1805219820Sjeff	if (src_addr->sin_family != dst_addr->sin_family)
1806219820Sjeff		return -EINVAL;
1807219820Sjeff
1808219820Sjeff	work = kzalloc(sizeof *work, GFP_KERNEL);
1809219820Sjeff	if (!work)
1810219820Sjeff		return -ENOMEM;
1811219820Sjeff
1812219820Sjeff	work->id = id_priv;
1813219820Sjeff	INIT_WORK(&work->work, cma_work_handler);
1814219820Sjeff
1815219820Sjeff	route->path_rec = kzalloc(sizeof *route->path_rec, GFP_KERNEL);
1816219820Sjeff	if (!route->path_rec) {
1817219820Sjeff		ret = -ENOMEM;
1818219820Sjeff		goto err1;
1819219820Sjeff	}
1820219820Sjeff
1821219820Sjeff	route->num_paths = 1;
1822219820Sjeff
1823219820Sjeff	if (addr->dev_addr.bound_dev_if)
1824219820Sjeff		ndev = dev_get_by_index(&init_net, addr->dev_addr.bound_dev_if);
1825219820Sjeff	if (!ndev) {
1826219820Sjeff		ret = -ENODEV;
1827219820Sjeff		goto err2;
1828219820Sjeff	}
1829219820Sjeff
1830219820Sjeff	vid = rdma_vlan_dev_vlan_id(ndev);
1831219820Sjeff
1832219820Sjeff	iboe_mac_vlan_to_ll(&route->path_rec->sgid, addr->dev_addr.src_dev_addr, vid);
1833219820Sjeff	iboe_mac_vlan_to_ll(&route->path_rec->dgid, addr->dev_addr.dst_dev_addr, vid);
1834219820Sjeff
1835219820Sjeff	route->path_rec->hop_limit = 1;
1836219820Sjeff	route->path_rec->reversible = 1;
1837219820Sjeff	route->path_rec->pkey = cpu_to_be16(0xffff);
1838219820Sjeff	route->path_rec->mtu_selector = IB_SA_EQ;
1839219820Sjeff	route->path_rec->sl = tos_to_sl(id_priv->tos);
1840219820Sjeff
1841219820Sjeff#ifdef __linux__
1842219820Sjeff	route->path_rec->mtu = iboe_get_mtu(ndev->mtu);
1843219820Sjeff#else
1844219820Sjeff	route->path_rec->mtu = iboe_get_mtu(ndev->if_mtu);
1845219820Sjeff#endif
1846219820Sjeff	route->path_rec->rate_selector = IB_SA_EQ;
1847219820Sjeff	route->path_rec->rate = iboe_get_rate(ndev);
1848219820Sjeff	dev_put(ndev);
1849219820Sjeff	route->path_rec->packet_life_time_selector = IB_SA_EQ;
1850219820Sjeff	route->path_rec->packet_life_time = IBOE_PACKET_LIFETIME;
1851219820Sjeff	if (!route->path_rec->mtu) {
1852219820Sjeff		ret = -EINVAL;
1853219820Sjeff		goto err2;
1854219820Sjeff	}
1855219820Sjeff
1856219820Sjeff	work->old_state = CMA_ROUTE_QUERY;
1857219820Sjeff	work->new_state = CMA_ROUTE_RESOLVED;
1858219820Sjeff	work->event.event = RDMA_CM_EVENT_ROUTE_RESOLVED;
1859219820Sjeff	work->event.status = 0;
1860219820Sjeff
1861219820Sjeff	queue_work(cma_wq, &work->work);
1862219820Sjeff
1863219820Sjeff	return 0;
1864219820Sjeff
1865219820Sjefferr2:
1866219820Sjeff	kfree(route->path_rec);
1867219820Sjeff	route->path_rec = NULL;
1868219820Sjefferr1:
1869219820Sjeff	kfree(work);
1870219820Sjeff	return ret;
1871219820Sjeff}
1872219820Sjeff
1873219820Sjeffint rdma_resolve_route(struct rdma_cm_id *id, int timeout_ms)
1874219820Sjeff{
1875219820Sjeff	struct rdma_id_private *id_priv;
1876219820Sjeff	int ret;
1877219820Sjeff
1878219820Sjeff	id_priv = container_of(id, struct rdma_id_private, id);
1879219820Sjeff	if (!cma_comp_exch(id_priv, CMA_ADDR_RESOLVED, CMA_ROUTE_QUERY))
1880219820Sjeff		return -EINVAL;
1881219820Sjeff
1882219820Sjeff	atomic_inc(&id_priv->refcount);
1883219820Sjeff	switch (rdma_node_get_transport(id->device->node_type)) {
1884219820Sjeff	case RDMA_TRANSPORT_IB:
1885219820Sjeff		switch (rdma_port_get_link_layer(id->device, id->port_num)) {
1886219820Sjeff		case IB_LINK_LAYER_INFINIBAND:
1887219820Sjeff			ret = cma_resolve_ib_route(id_priv, timeout_ms);
1888219820Sjeff			break;
1889219820Sjeff		case IB_LINK_LAYER_ETHERNET:
1890219820Sjeff			ret = cma_resolve_iboe_route(id_priv);
1891219820Sjeff			break;
1892219820Sjeff		default:
1893219820Sjeff			ret = -ENOSYS;
1894219820Sjeff		}
1895219820Sjeff		break;
1896219820Sjeff	case RDMA_TRANSPORT_IWARP:
1897219820Sjeff		ret = cma_resolve_iw_route(id_priv, timeout_ms);
1898219820Sjeff		break;
1899219820Sjeff	default:
1900219820Sjeff		ret = -ENOSYS;
1901219820Sjeff		break;
1902219820Sjeff	}
1903219820Sjeff	if (ret)
1904219820Sjeff		goto err;
1905219820Sjeff
1906219820Sjeff	return 0;
1907219820Sjefferr:
1908219820Sjeff	cma_comp_exch(id_priv, CMA_ROUTE_QUERY, CMA_ADDR_RESOLVED);
1909219820Sjeff	cma_deref_id(id_priv);
1910219820Sjeff	return ret;
1911219820Sjeff}
1912219820SjeffEXPORT_SYMBOL(rdma_resolve_route);
1913219820Sjeff
1914219820Sjeffstatic int cma_bind_loopback(struct rdma_id_private *id_priv)
1915219820Sjeff{
1916219820Sjeff	struct cma_device *cma_dev;
1917219820Sjeff	struct ib_port_attr port_attr;
1918219820Sjeff	union ib_gid gid;
1919219820Sjeff	u16 pkey;
1920219820Sjeff	int ret;
1921219820Sjeff	u8 p;
1922219820Sjeff
1923219820Sjeff	mutex_lock(&lock);
1924219820Sjeff	if (list_empty(&dev_list)) {
1925219820Sjeff		ret = -ENODEV;
1926219820Sjeff		goto out;
1927219820Sjeff	}
1928219820Sjeff	list_for_each_entry(cma_dev, &dev_list, list)
1929219820Sjeff		for (p = 1; p <= cma_dev->device->phys_port_cnt; ++p)
1930219820Sjeff			if (!ib_query_port(cma_dev->device, p, &port_attr) &&
1931219820Sjeff			    port_attr.state == IB_PORT_ACTIVE)
1932219820Sjeff				goto port_found;
1933219820Sjeff
1934219820Sjeff	p = 1;
1935219820Sjeff	cma_dev = list_entry(dev_list.next, struct cma_device, list);
1936219820Sjeff
1937219820Sjeffport_found:
1938219820Sjeff	ret = ib_get_cached_gid(cma_dev->device, p, 0, &gid);
1939219820Sjeff	if (ret)
1940219820Sjeff		goto out;
1941219820Sjeff
1942219820Sjeff	ret = ib_get_cached_pkey(cma_dev->device, p, 0, &pkey);
1943219820Sjeff	if (ret)
1944219820Sjeff		goto out;
1945219820Sjeff
1946219820Sjeff	id_priv->id.route.addr.dev_addr.dev_type =
1947219820Sjeff		(rdma_port_get_link_layer(cma_dev->device, p) == IB_LINK_LAYER_INFINIBAND) ?
1948219820Sjeff		ARPHRD_INFINIBAND : ARPHRD_ETHER;
1949219820Sjeff
1950219820Sjeff	rdma_addr_set_sgid(&id_priv->id.route.addr.dev_addr, &gid);
1951219820Sjeff	ib_addr_set_pkey(&id_priv->id.route.addr.dev_addr, pkey);
1952219820Sjeff	id_priv->id.port_num = p;
1953219820Sjeff	cma_attach_to_dev(id_priv, cma_dev);
1954219820Sjeffout:
1955219820Sjeff	mutex_unlock(&lock);
1956219820Sjeff	return ret;
1957219820Sjeff}
1958219820Sjeff
1959219820Sjeffstatic void addr_handler(int status, struct sockaddr *src_addr,
1960219820Sjeff			 struct rdma_dev_addr *dev_addr, void *context)
1961219820Sjeff{
1962219820Sjeff	struct rdma_id_private *id_priv = context;
1963219820Sjeff	struct rdma_cm_event event;
1964219820Sjeff
1965219820Sjeff	memset(&event, 0, sizeof event);
1966219820Sjeff	mutex_lock(&id_priv->handler_mutex);
1967219820Sjeff
1968219820Sjeff	/*
1969219820Sjeff	 * Grab mutex to block rdma_destroy_id() from removing the device while
1970219820Sjeff	 * we're trying to acquire it.
1971219820Sjeff	 */
1972219820Sjeff	mutex_lock(&lock);
1973219820Sjeff	if (!cma_comp_exch(id_priv, CMA_ADDR_QUERY, CMA_ADDR_RESOLVED)) {
1974219820Sjeff		mutex_unlock(&lock);
1975219820Sjeff		goto out;
1976219820Sjeff	}
1977219820Sjeff
1978219820Sjeff	if (!status && !id_priv->cma_dev)
1979219820Sjeff		status = cma_acquire_dev(id_priv);
1980219820Sjeff	mutex_unlock(&lock);
1981219820Sjeff
1982219820Sjeff	if (status) {
1983219820Sjeff		if (!cma_comp_exch(id_priv, CMA_ADDR_RESOLVED, CMA_ADDR_BOUND))
1984219820Sjeff			goto out;
1985219820Sjeff		event.event = RDMA_CM_EVENT_ADDR_ERROR;
1986219820Sjeff		event.status = status;
1987219820Sjeff	} else {
1988219820Sjeff		memcpy(&id_priv->id.route.addr.src_addr, src_addr,
1989219820Sjeff		       ip_addr_size(src_addr));
1990219820Sjeff		event.event = RDMA_CM_EVENT_ADDR_RESOLVED;
1991219820Sjeff	}
1992219820Sjeff
1993219820Sjeff	if (id_priv->id.event_handler(&id_priv->id, &event)) {
1994219820Sjeff		cma_exch(id_priv, CMA_DESTROYING);
1995219820Sjeff		mutex_unlock(&id_priv->handler_mutex);
1996219820Sjeff		cma_deref_id(id_priv);
1997219820Sjeff		rdma_destroy_id(&id_priv->id);
1998219820Sjeff		return;
1999219820Sjeff	}
2000219820Sjeffout:
2001219820Sjeff	mutex_unlock(&id_priv->handler_mutex);
2002219820Sjeff	cma_deref_id(id_priv);
2003219820Sjeff}
2004219820Sjeff
2005219820Sjeffstatic int cma_resolve_loopback(struct rdma_id_private *id_priv)
2006219820Sjeff{
2007219820Sjeff	struct cma_work *work;
2008219820Sjeff	struct sockaddr *src, *dst;
2009219820Sjeff	union ib_gid gid;
2010219820Sjeff	int ret;
2011219820Sjeff
2012219820Sjeff	work = kzalloc(sizeof *work, GFP_KERNEL);
2013219820Sjeff	if (!work)
2014219820Sjeff		return -ENOMEM;
2015219820Sjeff
2016219820Sjeff	if (!id_priv->cma_dev) {
2017219820Sjeff		ret = cma_bind_loopback(id_priv);
2018219820Sjeff		if (ret)
2019219820Sjeff			goto err;
2020219820Sjeff	}
2021219820Sjeff
2022219820Sjeff	rdma_addr_get_sgid(&id_priv->id.route.addr.dev_addr, &gid);
2023219820Sjeff	rdma_addr_set_dgid(&id_priv->id.route.addr.dev_addr, &gid);
2024219820Sjeff
2025219820Sjeff	src = (struct sockaddr *) &id_priv->id.route.addr.src_addr;
2026219820Sjeff	if (cma_zero_addr(src)) {
2027219820Sjeff		dst = (struct sockaddr *) &id_priv->id.route.addr.dst_addr;
2028219820Sjeff		if ((src->sa_family = dst->sa_family) == AF_INET) {
2029219820Sjeff			((struct sockaddr_in *) src)->sin_addr.s_addr =
2030219820Sjeff				((struct sockaddr_in *) dst)->sin_addr.s_addr;
2031219820Sjeff		} else {
2032219820Sjeff			ipv6_addr_copy(&((struct sockaddr_in6 *) src)->sin6_addr,
2033219820Sjeff				       &((struct sockaddr_in6 *) dst)->sin6_addr);
2034219820Sjeff		}
2035219820Sjeff	}
2036219820Sjeff
2037219820Sjeff	work->id = id_priv;
2038219820Sjeff	INIT_WORK(&work->work, cma_work_handler);
2039219820Sjeff	work->old_state = CMA_ADDR_QUERY;
2040219820Sjeff	work->new_state = CMA_ADDR_RESOLVED;
2041219820Sjeff	work->event.event = RDMA_CM_EVENT_ADDR_RESOLVED;
2042219820Sjeff	queue_work(cma_wq, &work->work);
2043219820Sjeff	return 0;
2044219820Sjefferr:
2045219820Sjeff	kfree(work);
2046219820Sjeff	return ret;
2047219820Sjeff}
2048219820Sjeff
2049219820Sjeffstatic int cma_bind_addr(struct rdma_cm_id *id, struct sockaddr *src_addr,
2050219820Sjeff			 struct sockaddr *dst_addr)
2051219820Sjeff{
2052219820Sjeff	if (!src_addr || !src_addr->sa_family) {
2053219820Sjeff		src_addr = (struct sockaddr *) &id->route.addr.src_addr;
2054219820Sjeff		if ((src_addr->sa_family = dst_addr->sa_family) == AF_INET6) {
2055219820Sjeff			((struct sockaddr_in6 *) src_addr)->sin6_scope_id =
2056219820Sjeff				((struct sockaddr_in6 *) dst_addr)->sin6_scope_id;
2057219820Sjeff		}
2058219820Sjeff	}
2059252555Snp	if (!cma_any_addr(src_addr))
2060252555Snp		return rdma_bind_addr(id, src_addr);
2061252555Snp	else {
2062252555Snp		struct sockaddr_in addr_in;
2063252555Snp
2064252555Snp        	memset(&addr_in, 0, sizeof addr_in);
2065252555Snp        	addr_in.sin_family = dst_addr->sa_family;
2066252555Snp        	addr_in.sin_len = sizeof addr_in;
2067252555Snp        	return rdma_bind_addr(id, (struct sockaddr *) &addr_in);
2068252555Snp	}
2069219820Sjeff}
2070219820Sjeff
2071219820Sjeffint rdma_resolve_addr(struct rdma_cm_id *id, struct sockaddr *src_addr,
2072219820Sjeff		      struct sockaddr *dst_addr, int timeout_ms)
2073219820Sjeff{
2074219820Sjeff	struct rdma_id_private *id_priv;
2075219820Sjeff	int ret;
2076219820Sjeff
2077219820Sjeff	id_priv = container_of(id, struct rdma_id_private, id);
2078219820Sjeff	if (id_priv->state == CMA_IDLE) {
2079219820Sjeff		ret = cma_bind_addr(id, src_addr, dst_addr);
2080219820Sjeff		if (ret)
2081219820Sjeff			return ret;
2082219820Sjeff	}
2083219820Sjeff
2084219820Sjeff	if (!cma_comp_exch(id_priv, CMA_ADDR_BOUND, CMA_ADDR_QUERY))
2085219820Sjeff		return -EINVAL;
2086219820Sjeff
2087219820Sjeff	atomic_inc(&id_priv->refcount);
2088219820Sjeff	memcpy(&id->route.addr.dst_addr, dst_addr, ip_addr_size(dst_addr));
2089219820Sjeff	if (cma_any_addr(dst_addr))
2090219820Sjeff		ret = cma_resolve_loopback(id_priv);
2091219820Sjeff	else
2092219820Sjeff		ret = rdma_resolve_ip(&addr_client, (struct sockaddr *) &id->route.addr.src_addr,
2093219820Sjeff				      dst_addr, &id->route.addr.dev_addr,
2094219820Sjeff				      timeout_ms, addr_handler, id_priv);
2095219820Sjeff	if (ret)
2096219820Sjeff		goto err;
2097219820Sjeff
2098219820Sjeff	return 0;
2099219820Sjefferr:
2100219820Sjeff	cma_comp_exch(id_priv, CMA_ADDR_QUERY, CMA_ADDR_BOUND);
2101219820Sjeff	cma_deref_id(id_priv);
2102219820Sjeff	return ret;
2103219820Sjeff}
2104219820SjeffEXPORT_SYMBOL(rdma_resolve_addr);
2105219820Sjeff
2106219820Sjeffstatic void cma_bind_port(struct rdma_bind_list *bind_list,
2107219820Sjeff			  struct rdma_id_private *id_priv)
2108219820Sjeff{
2109219820Sjeff	struct sockaddr_in *sin;
2110219820Sjeff
2111219820Sjeff	sin = (struct sockaddr_in *) &id_priv->id.route.addr.src_addr;
2112219820Sjeff	sin->sin_port = htons(bind_list->port);
2113219820Sjeff	id_priv->bind_list = bind_list;
2114219820Sjeff	hlist_add_head(&id_priv->node, &bind_list->owners);
2115219820Sjeff}
2116219820Sjeff
2117219820Sjeffstatic int cma_alloc_port(struct idr *ps, struct rdma_id_private *id_priv,
2118219820Sjeff			  unsigned short snum)
2119219820Sjeff{
2120219820Sjeff	struct rdma_bind_list *bind_list;
2121219820Sjeff	int port, ret;
2122219820Sjeff
2123219820Sjeff	bind_list = kzalloc(sizeof *bind_list, GFP_KERNEL);
2124219820Sjeff	if (!bind_list)
2125219820Sjeff		return -ENOMEM;
2126219820Sjeff
2127219820Sjeff	do {
2128219820Sjeff		ret = idr_get_new_above(ps, bind_list, snum, &port);
2129219820Sjeff	} while ((ret == -EAGAIN) && idr_pre_get(ps, GFP_KERNEL));
2130219820Sjeff
2131219820Sjeff	if (ret)
2132219820Sjeff		goto err1;
2133219820Sjeff
2134219820Sjeff	if (port != snum) {
2135219820Sjeff		ret = -EADDRNOTAVAIL;
2136219820Sjeff		goto err2;
2137219820Sjeff	}
2138219820Sjeff
2139219820Sjeff	bind_list->ps = ps;
2140219820Sjeff	bind_list->port = (unsigned short) port;
2141219820Sjeff	cma_bind_port(bind_list, id_priv);
2142219820Sjeff	return 0;
2143219820Sjefferr2:
2144219820Sjeff	idr_remove(ps, port);
2145219820Sjefferr1:
2146219820Sjeff	kfree(bind_list);
2147219820Sjeff	return ret;
2148219820Sjeff}
2149219820Sjeff
2150219820Sjeffstatic int cma_alloc_any_port(struct idr *ps, struct rdma_id_private *id_priv)
2151219820Sjeff{
2152239748Sjhb#if defined(INET)
2153219820Sjeff	struct rdma_bind_list *bind_list;
2154219820Sjeff	int port, ret, low, high;
2155219820Sjeff
2156219820Sjeff	bind_list = kzalloc(sizeof *bind_list, GFP_KERNEL);
2157219820Sjeff	if (!bind_list)
2158219820Sjeff		return -ENOMEM;
2159219820Sjeff
2160219820Sjeffretry:
2161219820Sjeff	/* FIXME: add proper port randomization per like inet_csk_get_port */
2162219820Sjeff	do {
2163219820Sjeff		ret = idr_get_new_above(ps, bind_list, next_port, &port);
2164219820Sjeff	} while ((ret == -EAGAIN) && idr_pre_get(ps, GFP_KERNEL));
2165219820Sjeff
2166219820Sjeff	if (ret)
2167219820Sjeff		goto err1;
2168219820Sjeff
2169219820Sjeff	inet_get_local_port_range(&low, &high);
2170219820Sjeff	if (port > high) {
2171219820Sjeff		if (next_port != low) {
2172219820Sjeff			idr_remove(ps, port);
2173219820Sjeff			next_port = low;
2174219820Sjeff			goto retry;
2175219820Sjeff		}
2176219820Sjeff		ret = -EADDRNOTAVAIL;
2177219820Sjeff		goto err2;
2178219820Sjeff	}
2179219820Sjeff
2180219820Sjeff	if (port == high)
2181219820Sjeff		next_port = low;
2182219820Sjeff	else
2183219820Sjeff		next_port = port + 1;
2184219820Sjeff
2185219820Sjeff	bind_list->ps = ps;
2186219820Sjeff	bind_list->port = (unsigned short) port;
2187219820Sjeff	cma_bind_port(bind_list, id_priv);
2188219820Sjeff	return 0;
2189219820Sjefferr2:
2190219820Sjeff	idr_remove(ps, port);
2191219820Sjefferr1:
2192219820Sjeff	kfree(bind_list);
2193219820Sjeff	return ret;
2194239748Sjhb#else
2195239748Sjhb	return -ENOSPC;
2196239748Sjhb#endif
2197219820Sjeff}
2198219820Sjeff
2199219820Sjeffstatic int cma_use_port(struct idr *ps, struct rdma_id_private *id_priv)
2200219820Sjeff{
2201219820Sjeff	struct rdma_id_private *cur_id;
2202219820Sjeff	struct sockaddr_in *sin, *cur_sin;
2203219820Sjeff	struct rdma_bind_list *bind_list;
2204219820Sjeff	struct hlist_node *node;
2205219820Sjeff	unsigned short snum;
2206219820Sjeff
2207219820Sjeff	sin = (struct sockaddr_in *) &id_priv->id.route.addr.src_addr;
2208219820Sjeff	snum = ntohs(sin->sin_port);
2209219820Sjeff#ifdef __linux__
2210219820Sjeff	if (snum < PROT_SOCK && !capable(CAP_NET_BIND_SERVICE))
2211219820Sjeff		return -EACCES;
2212219820Sjeff#endif
2213219820Sjeff
2214219820Sjeff	bind_list = idr_find(ps, snum);
2215219820Sjeff	if (!bind_list)
2216219820Sjeff		return cma_alloc_port(ps, id_priv, snum);
2217219820Sjeff
2218219820Sjeff	/*
2219219820Sjeff	 * We don't support binding to any address if anyone is bound to
2220219820Sjeff	 * a specific address on the same port.
2221219820Sjeff	 */
2222219820Sjeff	if (cma_any_addr((struct sockaddr *) &id_priv->id.route.addr.src_addr))
2223219820Sjeff		return -EADDRNOTAVAIL;
2224219820Sjeff
2225219820Sjeff	hlist_for_each_entry(cur_id, node, &bind_list->owners, node) {
2226219820Sjeff		if (cma_any_addr((struct sockaddr *) &cur_id->id.route.addr.src_addr))
2227219820Sjeff			return -EADDRNOTAVAIL;
2228219820Sjeff
2229219820Sjeff		cur_sin = (struct sockaddr_in *) &cur_id->id.route.addr.src_addr;
2230219820Sjeff		if (sin->sin_addr.s_addr == cur_sin->sin_addr.s_addr)
2231219820Sjeff			return -EADDRINUSE;
2232219820Sjeff	}
2233219820Sjeff
2234219820Sjeff	cma_bind_port(bind_list, id_priv);
2235219820Sjeff	return 0;
2236219820Sjeff}
2237219820Sjeff
2238219820Sjeffstatic int cma_get_tcp_port(struct rdma_id_private *id_priv)
2239219820Sjeff{
2240219820Sjeff	int ret;
2241219820Sjeff	int size;
2242219820Sjeff	struct socket *sock;
2243219820Sjeff
2244219820Sjeff	ret = sock_create_kern(AF_INET, SOCK_STREAM, IPPROTO_TCP, &sock);
2245219820Sjeff	if (ret)
2246219820Sjeff		return ret;
2247219820Sjeff#ifdef __linux__
2248219820Sjeff	ret = sock->ops->bind(sock,
2249219820Sjeff			(struct sockaddr *) &id_priv->id.route.addr.src_addr,
2250219820Sjeff			ip_addr_size((struct sockaddr *) &id_priv->id.route.addr.src_addr));
2251219820Sjeff#else
2252219820Sjeff	ret = -sobind(sock,
2253219820Sjeff			(struct sockaddr *)&id_priv->id.route.addr.src_addr,
2254219820Sjeff			curthread);
2255219820Sjeff#endif
2256219820Sjeff	if (ret) {
2257219820Sjeff		sock_release(sock);
2258219820Sjeff		return ret;
2259219820Sjeff	}
2260252555Snp
2261219820Sjeff	size = ip_addr_size((struct sockaddr *) &id_priv->id.route.addr.src_addr);
2262219820Sjeff	ret = sock_getname(sock,
2263219820Sjeff			(struct sockaddr *) &id_priv->id.route.addr.src_addr,
2264219820Sjeff			&size, 0);
2265219820Sjeff	if (ret) {
2266219820Sjeff		sock_release(sock);
2267219820Sjeff		return ret;
2268219820Sjeff	}
2269252555Snp
2270219820Sjeff	id_priv->sock = sock;
2271219820Sjeff	return 0;
2272219820Sjeff}
2273219820Sjeff
2274219820Sjeffstatic int cma_get_port(struct rdma_id_private *id_priv)
2275219820Sjeff{
2276219820Sjeff	struct idr *ps;
2277219820Sjeff	int ret;
2278219820Sjeff
2279219820Sjeff	switch (id_priv->id.ps) {
2280219820Sjeff	case RDMA_PS_SDP:
2281219820Sjeff		ps = &sdp_ps;
2282219820Sjeff		break;
2283219820Sjeff	case RDMA_PS_TCP:
2284219820Sjeff		ps = &tcp_ps;
2285219820Sjeff		if (unify_tcp_port_space) {
2286219820Sjeff			ret = cma_get_tcp_port(id_priv);
2287219820Sjeff			if (ret)
2288219820Sjeff				goto out;
2289219820Sjeff		}
2290219820Sjeff		break;
2291219820Sjeff	case RDMA_PS_UDP:
2292219820Sjeff		ps = &udp_ps;
2293219820Sjeff		break;
2294219820Sjeff	case RDMA_PS_IPOIB:
2295219820Sjeff		ps = &ipoib_ps;
2296219820Sjeff		break;
2297219820Sjeff	default:
2298219820Sjeff		return -EPROTONOSUPPORT;
2299219820Sjeff	}
2300219820Sjeff
2301219820Sjeff	mutex_lock(&lock);
2302219820Sjeff	if (cma_any_port((struct sockaddr *) &id_priv->id.route.addr.src_addr))
2303219820Sjeff		ret = cma_alloc_any_port(ps, id_priv);
2304219820Sjeff	else
2305219820Sjeff		ret = cma_use_port(ps, id_priv);
2306219820Sjeff	mutex_unlock(&lock);
2307219820Sjeffout:
2308219820Sjeff	return ret;
2309219820Sjeff}
2310219820Sjeff
2311219820Sjeffstatic int cma_check_linklocal(struct rdma_dev_addr *dev_addr,
2312219820Sjeff			       struct sockaddr *addr)
2313219820Sjeff{
2314219820Sjeff#if defined(INET6)
2315219820Sjeff	struct sockaddr_in6 *sin6;
2316219820Sjeff
2317219820Sjeff	if (addr->sa_family != AF_INET6)
2318219820Sjeff		return 0;
2319219820Sjeff
2320219820Sjeff	sin6 = (struct sockaddr_in6 *) addr;
2321219820Sjeff#ifdef __linux__
2322219820Sjeff	if ((ipv6_addr_type(&sin6->sin6_addr) & IPV6_ADDR_LINKLOCAL) &&
2323219820Sjeff#else
2324219820Sjeff	if (IN6_IS_SCOPE_LINKLOCAL(&sin6->sin6_addr) &&
2325219820Sjeff#endif
2326219820Sjeff	    !sin6->sin6_scope_id)
2327219820Sjeff			return -EINVAL;
2328219820Sjeff
2329219820Sjeff	dev_addr->bound_dev_if = sin6->sin6_scope_id;
2330219820Sjeff#endif
2331219820Sjeff	return 0;
2332219820Sjeff}
2333219820Sjeff
2334219820Sjeffint rdma_bind_addr(struct rdma_cm_id *id, struct sockaddr *addr)
2335219820Sjeff{
2336219820Sjeff	struct rdma_id_private *id_priv;
2337219820Sjeff	int ret;
2338219820Sjeff
2339219820Sjeff	if (addr->sa_family != AF_INET && addr->sa_family != AF_INET6)
2340219820Sjeff		return -EAFNOSUPPORT;
2341219820Sjeff
2342219820Sjeff	id_priv = container_of(id, struct rdma_id_private, id);
2343219820Sjeff	if (!cma_comp_exch(id_priv, CMA_IDLE, CMA_ADDR_BOUND))
2344219820Sjeff		return -EINVAL;
2345219820Sjeff
2346219820Sjeff	ret = cma_check_linklocal(&id->route.addr.dev_addr, addr);
2347219820Sjeff	if (ret)
2348219820Sjeff		goto err1;
2349219820Sjeff
2350219820Sjeff	if (!cma_any_addr(addr)) {
2351219820Sjeff		ret = rdma_translate_ip(addr, &id->route.addr.dev_addr);
2352219820Sjeff		if (ret)
2353219820Sjeff			goto err1;
2354219820Sjeff
2355219820Sjeff		mutex_lock(&lock);
2356219820Sjeff		ret = cma_acquire_dev(id_priv);
2357219820Sjeff		mutex_unlock(&lock);
2358219820Sjeff		if (ret)
2359219820Sjeff			goto err1;
2360219820Sjeff	}
2361219820Sjeff
2362219820Sjeff	memcpy(&id->route.addr.src_addr, addr, ip_addr_size(addr));
2363219820Sjeff	ret = cma_get_port(id_priv);
2364219820Sjeff	if (ret)
2365219820Sjeff		goto err2;
2366219820Sjeff
2367219820Sjeff	return 0;
2368219820Sjefferr2:
2369219820Sjeff	if (id_priv->cma_dev) {
2370219820Sjeff		mutex_lock(&lock);
2371219820Sjeff		cma_detach_from_dev(id_priv);
2372219820Sjeff		mutex_unlock(&lock);
2373219820Sjeff	}
2374219820Sjefferr1:
2375219820Sjeff	cma_comp_exch(id_priv, CMA_ADDR_BOUND, CMA_IDLE);
2376219820Sjeff	return ret;
2377219820Sjeff}
2378219820SjeffEXPORT_SYMBOL(rdma_bind_addr);
2379219820Sjeff
2380219820Sjeffstatic int cma_format_hdr(void *hdr, enum rdma_port_space ps,
2381219820Sjeff			  struct rdma_route *route)
2382219820Sjeff{
2383219820Sjeff	struct cma_hdr *cma_hdr;
2384219820Sjeff	struct sdp_hh *sdp_hdr;
2385219820Sjeff
2386219820Sjeff	if (route->addr.src_addr.ss_family == AF_INET) {
2387219820Sjeff		struct sockaddr_in *src4, *dst4;
2388219820Sjeff
2389219820Sjeff		src4 = (struct sockaddr_in *) &route->addr.src_addr;
2390219820Sjeff		dst4 = (struct sockaddr_in *) &route->addr.dst_addr;
2391219820Sjeff
2392219820Sjeff		switch (ps) {
2393219820Sjeff		case RDMA_PS_SDP:
2394219820Sjeff			sdp_hdr = hdr;
2395219820Sjeff			if (sdp_get_majv(sdp_hdr->sdp_version) != SDP_MAJ_VERSION)
2396219820Sjeff				return -EINVAL;
2397219820Sjeff			sdp_set_ip_ver(sdp_hdr, 4);
2398219820Sjeff			sdp_hdr->src_addr.ip4.addr = src4->sin_addr.s_addr;
2399219820Sjeff			sdp_hdr->dst_addr.ip4.addr = dst4->sin_addr.s_addr;
2400219820Sjeff			sdp_hdr->port = src4->sin_port;
2401219820Sjeff			break;
2402219820Sjeff		default:
2403219820Sjeff			cma_hdr = hdr;
2404219820Sjeff			cma_hdr->cma_version = CMA_VERSION;
2405219820Sjeff			cma_set_ip_ver(cma_hdr, 4);
2406219820Sjeff			cma_hdr->src_addr.ip4.addr = src4->sin_addr.s_addr;
2407219820Sjeff			cma_hdr->dst_addr.ip4.addr = dst4->sin_addr.s_addr;
2408219820Sjeff			cma_hdr->port = src4->sin_port;
2409219820Sjeff			break;
2410219820Sjeff		}
2411219820Sjeff	} else {
2412219820Sjeff		struct sockaddr_in6 *src6, *dst6;
2413219820Sjeff
2414219820Sjeff		src6 = (struct sockaddr_in6 *) &route->addr.src_addr;
2415219820Sjeff		dst6 = (struct sockaddr_in6 *) &route->addr.dst_addr;
2416219820Sjeff
2417219820Sjeff		switch (ps) {
2418219820Sjeff		case RDMA_PS_SDP:
2419219820Sjeff			sdp_hdr = hdr;
2420219820Sjeff			if (sdp_get_majv(sdp_hdr->sdp_version) != SDP_MAJ_VERSION)
2421219820Sjeff				return -EINVAL;
2422219820Sjeff			sdp_set_ip_ver(sdp_hdr, 6);
2423219820Sjeff			sdp_hdr->src_addr.ip6 = src6->sin6_addr;
2424219820Sjeff			sdp_hdr->dst_addr.ip6 = dst6->sin6_addr;
2425219820Sjeff			sdp_hdr->port = src6->sin6_port;
2426219820Sjeff			break;
2427219820Sjeff		default:
2428219820Sjeff			cma_hdr = hdr;
2429219820Sjeff			cma_hdr->cma_version = CMA_VERSION;
2430219820Sjeff			cma_set_ip_ver(cma_hdr, 6);
2431219820Sjeff			cma_hdr->src_addr.ip6 = src6->sin6_addr;
2432219820Sjeff			cma_hdr->dst_addr.ip6 = dst6->sin6_addr;
2433219820Sjeff			cma_hdr->port = src6->sin6_port;
2434219820Sjeff			break;
2435219820Sjeff		}
2436219820Sjeff	}
2437219820Sjeff	return 0;
2438219820Sjeff}
2439219820Sjeff
2440219820Sjeffstatic int cma_sidr_rep_handler(struct ib_cm_id *cm_id,
2441219820Sjeff				struct ib_cm_event *ib_event)
2442219820Sjeff{
2443219820Sjeff	struct rdma_id_private *id_priv = cm_id->context;
2444219820Sjeff	struct rdma_cm_event event;
2445219820Sjeff	struct ib_cm_sidr_rep_event_param *rep = &ib_event->param.sidr_rep_rcvd;
2446219820Sjeff	int ret = 0;
2447219820Sjeff
2448219820Sjeff	if (cma_disable_callback(id_priv, CMA_CONNECT))
2449219820Sjeff		return 0;
2450219820Sjeff
2451219820Sjeff	memset(&event, 0, sizeof event);
2452219820Sjeff	switch (ib_event->event) {
2453219820Sjeff	case IB_CM_SIDR_REQ_ERROR:
2454219820Sjeff		event.event = RDMA_CM_EVENT_UNREACHABLE;
2455219820Sjeff		event.status = -ETIMEDOUT;
2456219820Sjeff		break;
2457219820Sjeff	case IB_CM_SIDR_REP_RECEIVED:
2458219820Sjeff		event.param.ud.private_data = ib_event->private_data;
2459219820Sjeff		event.param.ud.private_data_len = IB_CM_SIDR_REP_PRIVATE_DATA_SIZE;
2460219820Sjeff		if (rep->status != IB_SIDR_SUCCESS) {
2461219820Sjeff			event.event = RDMA_CM_EVENT_UNREACHABLE;
2462219820Sjeff			event.status = ib_event->param.sidr_rep_rcvd.status;
2463219820Sjeff			break;
2464219820Sjeff		}
2465219820Sjeff		ret = cma_set_qkey(id_priv);
2466219820Sjeff		if (ret) {
2467219820Sjeff			event.event = RDMA_CM_EVENT_ADDR_ERROR;
2468219820Sjeff			event.status = -EINVAL;
2469219820Sjeff			break;
2470219820Sjeff		}
2471219820Sjeff		if (id_priv->qkey != rep->qkey) {
2472219820Sjeff			event.event = RDMA_CM_EVENT_UNREACHABLE;
2473219820Sjeff			event.status = -EINVAL;
2474219820Sjeff			break;
2475219820Sjeff		}
2476219820Sjeff		ib_init_ah_from_path(id_priv->id.device, id_priv->id.port_num,
2477219820Sjeff				     id_priv->id.route.path_rec,
2478219820Sjeff				     &event.param.ud.ah_attr);
2479219820Sjeff		event.param.ud.qp_num = rep->qpn;
2480219820Sjeff		event.param.ud.qkey = rep->qkey;
2481219820Sjeff		event.event = RDMA_CM_EVENT_ESTABLISHED;
2482219820Sjeff		event.status = 0;
2483219820Sjeff		break;
2484219820Sjeff	default:
2485219820Sjeff		printk(KERN_ERR "RDMA CMA: unexpected IB CM event: %d\n",
2486219820Sjeff		       ib_event->event);
2487219820Sjeff		goto out;
2488219820Sjeff	}
2489219820Sjeff
2490219820Sjeff	ret = id_priv->id.event_handler(&id_priv->id, &event);
2491219820Sjeff	if (ret) {
2492219820Sjeff		/* Destroy the CM ID by returning a non-zero value. */
2493219820Sjeff		id_priv->cm_id.ib = NULL;
2494219820Sjeff		cma_exch(id_priv, CMA_DESTROYING);
2495219820Sjeff		mutex_unlock(&id_priv->handler_mutex);
2496219820Sjeff		rdma_destroy_id(&id_priv->id);
2497219820Sjeff		return ret;
2498219820Sjeff	}
2499219820Sjeffout:
2500219820Sjeff	mutex_unlock(&id_priv->handler_mutex);
2501219820Sjeff	return ret;
2502219820Sjeff}
2503219820Sjeff
2504219820Sjeffstatic int cma_resolve_ib_udp(struct rdma_id_private *id_priv,
2505219820Sjeff			      struct rdma_conn_param *conn_param)
2506219820Sjeff{
2507219820Sjeff	struct ib_cm_sidr_req_param req;
2508219820Sjeff	struct rdma_route *route;
2509219820Sjeff	int ret;
2510219820Sjeff
2511219820Sjeff	req.private_data_len = sizeof(struct cma_hdr) +
2512219820Sjeff			       conn_param->private_data_len;
2513219820Sjeff	req.private_data = kzalloc(req.private_data_len, GFP_ATOMIC);
2514219820Sjeff	if (!req.private_data)
2515219820Sjeff		return -ENOMEM;
2516219820Sjeff
2517219820Sjeff	if (conn_param->private_data && conn_param->private_data_len)
2518219820Sjeff		memcpy((void *) req.private_data + sizeof(struct cma_hdr),
2519219820Sjeff		       conn_param->private_data, conn_param->private_data_len);
2520219820Sjeff
2521219820Sjeff	route = &id_priv->id.route;
2522219820Sjeff	ret = cma_format_hdr((void *) req.private_data, id_priv->id.ps, route);
2523219820Sjeff	if (ret)
2524219820Sjeff		goto out;
2525219820Sjeff
2526219820Sjeff	id_priv->cm_id.ib = ib_create_cm_id(id_priv->id.device,
2527219820Sjeff					    cma_sidr_rep_handler, id_priv);
2528219820Sjeff	if (IS_ERR(id_priv->cm_id.ib)) {
2529219820Sjeff		ret = PTR_ERR(id_priv->cm_id.ib);
2530219820Sjeff		goto out;
2531219820Sjeff	}
2532219820Sjeff
2533219820Sjeff	req.path = route->path_rec;
2534219820Sjeff	req.service_id = cma_get_service_id(id_priv->id.ps,
2535219820Sjeff					    (struct sockaddr *) &route->addr.dst_addr);
2536219820Sjeff	req.timeout_ms = 1 << (cma_response_timeout - 8);
2537219820Sjeff	req.max_cm_retries = CMA_MAX_CM_RETRIES;
2538219820Sjeff
2539219820Sjeff	ret = ib_send_cm_sidr_req(id_priv->cm_id.ib, &req);
2540219820Sjeff	if (ret) {
2541219820Sjeff		ib_destroy_cm_id(id_priv->cm_id.ib);
2542219820Sjeff		id_priv->cm_id.ib = NULL;
2543219820Sjeff	}
2544219820Sjeffout:
2545219820Sjeff	kfree(req.private_data);
2546219820Sjeff	return ret;
2547219820Sjeff}
2548219820Sjeff
2549219820Sjeffstatic int cma_connect_ib(struct rdma_id_private *id_priv,
2550219820Sjeff			  struct rdma_conn_param *conn_param)
2551219820Sjeff{
2552219820Sjeff	struct ib_cm_req_param req;
2553219820Sjeff	struct rdma_route *route;
2554219820Sjeff	void *private_data;
2555219820Sjeff	int offset, ret;
2556219820Sjeff
2557219820Sjeff	memset(&req, 0, sizeof req);
2558219820Sjeff	offset = cma_user_data_offset(id_priv->id.ps);
2559219820Sjeff	req.private_data_len = offset + conn_param->private_data_len;
2560219820Sjeff	private_data = kzalloc(req.private_data_len, GFP_ATOMIC);
2561219820Sjeff	if (!private_data)
2562219820Sjeff		return -ENOMEM;
2563219820Sjeff
2564219820Sjeff	if (conn_param->private_data && conn_param->private_data_len)
2565219820Sjeff		memcpy(private_data + offset, conn_param->private_data,
2566219820Sjeff		       conn_param->private_data_len);
2567219820Sjeff
2568219820Sjeff	id_priv->cm_id.ib = ib_create_cm_id(id_priv->id.device, cma_ib_handler,
2569219820Sjeff					    id_priv);
2570219820Sjeff	if (IS_ERR(id_priv->cm_id.ib)) {
2571219820Sjeff		ret = PTR_ERR(id_priv->cm_id.ib);
2572219820Sjeff		goto out;
2573219820Sjeff	}
2574219820Sjeff
2575219820Sjeff	route = &id_priv->id.route;
2576219820Sjeff	ret = cma_format_hdr(private_data, id_priv->id.ps, route);
2577219820Sjeff	if (ret)
2578219820Sjeff		goto out;
2579219820Sjeff	req.private_data = private_data;
2580219820Sjeff
2581219820Sjeff	req.primary_path = &route->path_rec[0];
2582219820Sjeff	if (route->num_paths == 2)
2583219820Sjeff		req.alternate_path = &route->path_rec[1];
2584219820Sjeff
2585219820Sjeff	req.service_id = cma_get_service_id(id_priv->id.ps,
2586219820Sjeff					    (struct sockaddr *) &route->addr.dst_addr);
2587219820Sjeff	req.qp_num = id_priv->qp_num;
2588219820Sjeff	req.qp_type = IB_QPT_RC;
2589219820Sjeff	req.starting_psn = id_priv->seq_num;
2590219820Sjeff	req.responder_resources = conn_param->responder_resources;
2591219820Sjeff	req.initiator_depth = conn_param->initiator_depth;
2592219820Sjeff	req.flow_control = conn_param->flow_control;
2593219820Sjeff	req.retry_count = conn_param->retry_count;
2594219820Sjeff	req.rnr_retry_count = conn_param->rnr_retry_count;
2595219820Sjeff       req.remote_cm_response_timeout = cma_response_timeout;
2596219820Sjeff       req.local_cm_response_timeout = cma_response_timeout;
2597219820Sjeff	req.max_cm_retries = CMA_MAX_CM_RETRIES;
2598219820Sjeff	req.srq = id_priv->srq ? 1 : 0;
2599219820Sjeff
2600219820Sjeff	ret = ib_send_cm_req(id_priv->cm_id.ib, &req);
2601219820Sjeffout:
2602219820Sjeff	if (ret && !IS_ERR(id_priv->cm_id.ib)) {
2603219820Sjeff		ib_destroy_cm_id(id_priv->cm_id.ib);
2604219820Sjeff		id_priv->cm_id.ib = NULL;
2605219820Sjeff	}
2606219820Sjeff
2607219820Sjeff	kfree(private_data);
2608219820Sjeff	return ret;
2609219820Sjeff}
2610219820Sjeff
2611219820Sjeffstatic int cma_connect_iw(struct rdma_id_private *id_priv,
2612219820Sjeff			  struct rdma_conn_param *conn_param)
2613219820Sjeff{
2614219820Sjeff	struct iw_cm_id *cm_id;
2615219820Sjeff	struct sockaddr_in* sin;
2616219820Sjeff	int ret;
2617219820Sjeff	struct iw_cm_conn_param iw_param;
2618219820Sjeff
2619252555Snp	cm_id = iw_create_cm_id(id_priv->id.device, id_priv->sock,
2620252555Snp				cma_iw_handler, id_priv);
2621219820Sjeff	if (IS_ERR(cm_id)) {
2622219820Sjeff		ret = PTR_ERR(cm_id);
2623219820Sjeff		goto out;
2624219820Sjeff	}
2625219820Sjeff
2626219820Sjeff	id_priv->cm_id.iw = cm_id;
2627219820Sjeff
2628219820Sjeff	sin = (struct sockaddr_in*) &id_priv->id.route.addr.src_addr;
2629219820Sjeff	cm_id->local_addr = *sin;
2630219820Sjeff
2631219820Sjeff	sin = (struct sockaddr_in*) &id_priv->id.route.addr.dst_addr;
2632219820Sjeff	cm_id->remote_addr = *sin;
2633219820Sjeff
2634219820Sjeff	ret = cma_modify_qp_rtr(id_priv, conn_param);
2635219820Sjeff	if (ret)
2636219820Sjeff		goto out;
2637219820Sjeff
2638219820Sjeff	iw_param.ord = conn_param->initiator_depth;
2639219820Sjeff	iw_param.ird = conn_param->responder_resources;
2640219820Sjeff	iw_param.private_data = conn_param->private_data;
2641219820Sjeff	iw_param.private_data_len = conn_param->private_data_len;
2642219820Sjeff	if (id_priv->id.qp)
2643219820Sjeff		iw_param.qpn = id_priv->qp_num;
2644219820Sjeff	else
2645219820Sjeff		iw_param.qpn = conn_param->qp_num;
2646219820Sjeff	ret = iw_cm_connect(cm_id, &iw_param);
2647219820Sjeffout:
2648219820Sjeff	if (ret && !IS_ERR(cm_id)) {
2649219820Sjeff		iw_destroy_cm_id(cm_id);
2650219820Sjeff		id_priv->cm_id.iw = NULL;
2651219820Sjeff	}
2652219820Sjeff	return ret;
2653219820Sjeff}
2654219820Sjeff
2655219820Sjeffint rdma_connect(struct rdma_cm_id *id, struct rdma_conn_param *conn_param)
2656219820Sjeff{
2657219820Sjeff	struct rdma_id_private *id_priv;
2658219820Sjeff	int ret;
2659219820Sjeff
2660219820Sjeff	id_priv = container_of(id, struct rdma_id_private, id);
2661219820Sjeff	if (!cma_comp_exch(id_priv, CMA_ROUTE_RESOLVED, CMA_CONNECT))
2662219820Sjeff		return -EINVAL;
2663219820Sjeff
2664219820Sjeff	if (!id->qp) {
2665219820Sjeff		id_priv->qp_num = conn_param->qp_num;
2666219820Sjeff		id_priv->srq = conn_param->srq;
2667219820Sjeff	}
2668219820Sjeff
2669219820Sjeff	switch (rdma_node_get_transport(id->device->node_type)) {
2670219820Sjeff	case RDMA_TRANSPORT_IB:
2671219820Sjeff		if (cma_is_ud_ps(id->ps))
2672219820Sjeff			ret = cma_resolve_ib_udp(id_priv, conn_param);
2673219820Sjeff		else
2674219820Sjeff			ret = cma_connect_ib(id_priv, conn_param);
2675219820Sjeff		break;
2676219820Sjeff	case RDMA_TRANSPORT_IWARP:
2677219820Sjeff		ret = cma_connect_iw(id_priv, conn_param);
2678219820Sjeff		break;
2679219820Sjeff	default:
2680219820Sjeff		ret = -ENOSYS;
2681219820Sjeff		break;
2682219820Sjeff	}
2683219820Sjeff	if (ret)
2684219820Sjeff		goto err;
2685219820Sjeff
2686219820Sjeff	return 0;
2687219820Sjefferr:
2688219820Sjeff	cma_comp_exch(id_priv, CMA_CONNECT, CMA_ROUTE_RESOLVED);
2689219820Sjeff	return ret;
2690219820Sjeff}
2691219820SjeffEXPORT_SYMBOL(rdma_connect);
2692219820Sjeff
2693219820Sjeffstatic int cma_accept_ib(struct rdma_id_private *id_priv,
2694219820Sjeff			 struct rdma_conn_param *conn_param)
2695219820Sjeff{
2696219820Sjeff	struct ib_cm_rep_param rep;
2697219820Sjeff	int ret;
2698219820Sjeff
2699219820Sjeff	ret = cma_modify_qp_rtr(id_priv, conn_param);
2700219820Sjeff	if (ret)
2701219820Sjeff		goto out;
2702219820Sjeff
2703219820Sjeff	ret = cma_modify_qp_rts(id_priv, conn_param);
2704219820Sjeff	if (ret)
2705219820Sjeff		goto out;
2706219820Sjeff
2707219820Sjeff	memset(&rep, 0, sizeof rep);
2708219820Sjeff	rep.qp_num = id_priv->qp_num;
2709219820Sjeff	rep.starting_psn = id_priv->seq_num;
2710219820Sjeff	rep.private_data = conn_param->private_data;
2711219820Sjeff	rep.private_data_len = conn_param->private_data_len;
2712219820Sjeff	rep.responder_resources = conn_param->responder_resources;
2713219820Sjeff	rep.initiator_depth = conn_param->initiator_depth;
2714219820Sjeff	rep.failover_accepted = 0;
2715219820Sjeff	rep.flow_control = conn_param->flow_control;
2716219820Sjeff	rep.rnr_retry_count = conn_param->rnr_retry_count;
2717219820Sjeff	rep.srq = id_priv->srq ? 1 : 0;
2718219820Sjeff
2719219820Sjeff	ret = ib_send_cm_rep(id_priv->cm_id.ib, &rep);
2720219820Sjeffout:
2721219820Sjeff	return ret;
2722219820Sjeff}
2723219820Sjeff
2724219820Sjeffstatic int cma_accept_iw(struct rdma_id_private *id_priv,
2725219820Sjeff		  struct rdma_conn_param *conn_param)
2726219820Sjeff{
2727219820Sjeff	struct iw_cm_conn_param iw_param;
2728219820Sjeff	int ret;
2729219820Sjeff
2730219820Sjeff	ret = cma_modify_qp_rtr(id_priv, conn_param);
2731219820Sjeff	if (ret)
2732219820Sjeff		return ret;
2733219820Sjeff
2734219820Sjeff	iw_param.ord = conn_param->initiator_depth;
2735219820Sjeff	iw_param.ird = conn_param->responder_resources;
2736219820Sjeff	iw_param.private_data = conn_param->private_data;
2737219820Sjeff	iw_param.private_data_len = conn_param->private_data_len;
2738219820Sjeff	if (id_priv->id.qp) {
2739219820Sjeff		iw_param.qpn = id_priv->qp_num;
2740219820Sjeff	} else
2741219820Sjeff		iw_param.qpn = conn_param->qp_num;
2742219820Sjeff
2743219820Sjeff	return iw_cm_accept(id_priv->cm_id.iw, &iw_param);
2744219820Sjeff}
2745219820Sjeff
2746219820Sjeffstatic int cma_send_sidr_rep(struct rdma_id_private *id_priv,
2747219820Sjeff			     enum ib_cm_sidr_status status,
2748219820Sjeff			     const void *private_data, int private_data_len)
2749219820Sjeff{
2750219820Sjeff	struct ib_cm_sidr_rep_param rep;
2751219820Sjeff	int ret;
2752219820Sjeff
2753219820Sjeff	memset(&rep, 0, sizeof rep);
2754219820Sjeff	rep.status = status;
2755219820Sjeff	if (status == IB_SIDR_SUCCESS) {
2756219820Sjeff		ret = cma_set_qkey(id_priv);
2757219820Sjeff		if (ret)
2758219820Sjeff			return ret;
2759219820Sjeff		rep.qp_num = id_priv->qp_num;
2760219820Sjeff		rep.qkey = id_priv->qkey;
2761219820Sjeff	}
2762219820Sjeff	rep.private_data = private_data;
2763219820Sjeff	rep.private_data_len = private_data_len;
2764219820Sjeff
2765219820Sjeff	return ib_send_cm_sidr_rep(id_priv->cm_id.ib, &rep);
2766219820Sjeff}
2767219820Sjeff
2768219820Sjeffint rdma_accept(struct rdma_cm_id *id, struct rdma_conn_param *conn_param)
2769219820Sjeff{
2770219820Sjeff	struct rdma_id_private *id_priv;
2771219820Sjeff	int ret;
2772219820Sjeff
2773219820Sjeff	id_priv = container_of(id, struct rdma_id_private, id);
2774219820Sjeff	if (!cma_comp(id_priv, CMA_CONNECT))
2775219820Sjeff		return -EINVAL;
2776219820Sjeff
2777219820Sjeff	if (!id->qp && conn_param) {
2778219820Sjeff		id_priv->qp_num = conn_param->qp_num;
2779219820Sjeff		id_priv->srq = conn_param->srq;
2780219820Sjeff	}
2781219820Sjeff
2782219820Sjeff	switch (rdma_node_get_transport(id->device->node_type)) {
2783219820Sjeff	case RDMA_TRANSPORT_IB:
2784219820Sjeff		if (cma_is_ud_ps(id->ps))
2785219820Sjeff			ret = cma_send_sidr_rep(id_priv, IB_SIDR_SUCCESS,
2786219820Sjeff						conn_param->private_data,
2787219820Sjeff						conn_param->private_data_len);
2788219820Sjeff		else if (conn_param)
2789219820Sjeff			ret = cma_accept_ib(id_priv, conn_param);
2790219820Sjeff		else
2791219820Sjeff			ret = cma_rep_recv(id_priv);
2792219820Sjeff		break;
2793219820Sjeff	case RDMA_TRANSPORT_IWARP:
2794219820Sjeff		ret = cma_accept_iw(id_priv, conn_param);
2795219820Sjeff		break;
2796219820Sjeff	default:
2797219820Sjeff		ret = -ENOSYS;
2798219820Sjeff		break;
2799219820Sjeff	}
2800219820Sjeff
2801219820Sjeff	if (ret)
2802219820Sjeff		goto reject;
2803219820Sjeff
2804219820Sjeff	return 0;
2805219820Sjeffreject:
2806219820Sjeff	cma_modify_qp_err(id_priv);
2807219820Sjeff	rdma_reject(id, NULL, 0);
2808219820Sjeff	return ret;
2809219820Sjeff}
2810219820SjeffEXPORT_SYMBOL(rdma_accept);
2811219820Sjeff
2812219820Sjeffint rdma_notify(struct rdma_cm_id *id, enum ib_event_type event)
2813219820Sjeff{
2814219820Sjeff	struct rdma_id_private *id_priv;
2815219820Sjeff	int ret;
2816219820Sjeff
2817219820Sjeff	id_priv = container_of(id, struct rdma_id_private, id);
2818219820Sjeff	if (!cma_has_cm_dev(id_priv))
2819219820Sjeff		return -EINVAL;
2820219820Sjeff
2821219820Sjeff	switch (id->device->node_type) {
2822219820Sjeff	case RDMA_NODE_IB_CA:
2823219820Sjeff		ret = ib_cm_notify(id_priv->cm_id.ib, event);
2824219820Sjeff		break;
2825219820Sjeff	default:
2826219820Sjeff		ret = 0;
2827219820Sjeff		break;
2828219820Sjeff	}
2829219820Sjeff	return ret;
2830219820Sjeff}
2831219820SjeffEXPORT_SYMBOL(rdma_notify);
2832219820Sjeff
2833219820Sjeffint rdma_reject(struct rdma_cm_id *id, const void *private_data,
2834219820Sjeff		u8 private_data_len)
2835219820Sjeff{
2836219820Sjeff	struct rdma_id_private *id_priv;
2837219820Sjeff	int ret;
2838219820Sjeff
2839219820Sjeff	id_priv = container_of(id, struct rdma_id_private, id);
2840219820Sjeff	if (!cma_has_cm_dev(id_priv))
2841219820Sjeff		return -EINVAL;
2842219820Sjeff
2843219820Sjeff	switch (rdma_node_get_transport(id->device->node_type)) {
2844219820Sjeff	case RDMA_TRANSPORT_IB:
2845219820Sjeff		if (cma_is_ud_ps(id->ps))
2846219820Sjeff			ret = cma_send_sidr_rep(id_priv, IB_SIDR_REJECT,
2847219820Sjeff						private_data, private_data_len);
2848219820Sjeff		else
2849219820Sjeff			ret = ib_send_cm_rej(id_priv->cm_id.ib,
2850219820Sjeff					     IB_CM_REJ_CONSUMER_DEFINED, NULL,
2851219820Sjeff					     0, private_data, private_data_len);
2852219820Sjeff		break;
2853219820Sjeff	case RDMA_TRANSPORT_IWARP:
2854219820Sjeff		ret = iw_cm_reject(id_priv->cm_id.iw,
2855219820Sjeff				   private_data, private_data_len);
2856219820Sjeff		break;
2857219820Sjeff	default:
2858219820Sjeff		ret = -ENOSYS;
2859219820Sjeff		break;
2860219820Sjeff	}
2861219820Sjeff	return ret;
2862219820Sjeff}
2863219820SjeffEXPORT_SYMBOL(rdma_reject);
2864219820Sjeff
2865219820Sjeffint rdma_disconnect(struct rdma_cm_id *id)
2866219820Sjeff{
2867219820Sjeff	struct rdma_id_private *id_priv;
2868219820Sjeff	int ret;
2869219820Sjeff
2870219820Sjeff	id_priv = container_of(id, struct rdma_id_private, id);
2871219820Sjeff	if (!cma_has_cm_dev(id_priv))
2872219820Sjeff		return -EINVAL;
2873219820Sjeff
2874219820Sjeff	switch (rdma_node_get_transport(id->device->node_type)) {
2875219820Sjeff	case RDMA_TRANSPORT_IB:
2876219820Sjeff		ret = cma_modify_qp_err(id_priv);
2877219820Sjeff		if (ret)
2878219820Sjeff			goto out;
2879219820Sjeff		/* Initiate or respond to a disconnect. */
2880219820Sjeff		if (ib_send_cm_dreq(id_priv->cm_id.ib, NULL, 0))
2881219820Sjeff			ib_send_cm_drep(id_priv->cm_id.ib, NULL, 0);
2882219820Sjeff		break;
2883219820Sjeff	case RDMA_TRANSPORT_IWARP:
2884219820Sjeff		ret = iw_cm_disconnect(id_priv->cm_id.iw, 0);
2885219820Sjeff		break;
2886219820Sjeff	default:
2887219820Sjeff		ret = -EINVAL;
2888219820Sjeff		break;
2889219820Sjeff	}
2890219820Sjeffout:
2891219820Sjeff	return ret;
2892219820Sjeff}
2893219820SjeffEXPORT_SYMBOL(rdma_disconnect);
2894219820Sjeff
2895219820Sjeffstatic int cma_ib_mc_handler(int status, struct ib_sa_multicast *multicast)
2896219820Sjeff{
2897219820Sjeff	struct rdma_id_private *id_priv;
2898219820Sjeff	struct cma_multicast *mc = multicast->context;
2899219820Sjeff	struct rdma_cm_event event;
2900219820Sjeff	int ret;
2901219820Sjeff
2902219820Sjeff	id_priv = mc->id_priv;
2903219820Sjeff	if (cma_disable_callback(id_priv, CMA_ADDR_BOUND) &&
2904219820Sjeff	    cma_disable_callback(id_priv, CMA_ADDR_RESOLVED))
2905219820Sjeff		return 0;
2906219820Sjeff
2907219820Sjeff	mutex_lock(&id_priv->qp_mutex);
2908219820Sjeff	if (!status && id_priv->id.qp)
2909219820Sjeff		status = ib_attach_mcast(id_priv->id.qp, &multicast->rec.mgid,
2910219820Sjeff					 multicast->rec.mlid);
2911219820Sjeff	mutex_unlock(&id_priv->qp_mutex);
2912219820Sjeff
2913219820Sjeff	memset(&event, 0, sizeof event);
2914219820Sjeff	event.status = status;
2915219820Sjeff	event.param.ud.private_data = mc->context;
2916219820Sjeff	if (!status) {
2917219820Sjeff		event.event = RDMA_CM_EVENT_MULTICAST_JOIN;
2918219820Sjeff		ib_init_ah_from_mcmember(id_priv->id.device,
2919219820Sjeff					 id_priv->id.port_num, &multicast->rec,
2920219820Sjeff					 &event.param.ud.ah_attr);
2921219820Sjeff		event.param.ud.qp_num = 0xFFFFFF;
2922219820Sjeff		event.param.ud.qkey = be32_to_cpu(multicast->rec.qkey);
2923219820Sjeff	} else
2924219820Sjeff		event.event = RDMA_CM_EVENT_MULTICAST_ERROR;
2925219820Sjeff
2926219820Sjeff	ret = id_priv->id.event_handler(&id_priv->id, &event);
2927219820Sjeff	if (ret) {
2928219820Sjeff		cma_exch(id_priv, CMA_DESTROYING);
2929219820Sjeff		mutex_unlock(&id_priv->handler_mutex);
2930219820Sjeff		rdma_destroy_id(&id_priv->id);
2931219820Sjeff		return 0;
2932219820Sjeff	}
2933219820Sjeff
2934219820Sjeff	mutex_unlock(&id_priv->handler_mutex);
2935219820Sjeff	return 0;
2936219820Sjeff}
2937219820Sjeff
2938219820Sjeffstatic void cma_set_mgid(struct rdma_id_private *id_priv,
2939219820Sjeff			 struct sockaddr *addr, union ib_gid *mgid)
2940219820Sjeff{
2941239748Sjhb#if defined(INET) || defined(INET6)
2942219820Sjeff	unsigned char mc_map[MAX_ADDR_LEN];
2943219820Sjeff	struct rdma_dev_addr *dev_addr = &id_priv->id.route.addr.dev_addr;
2944239748Sjhb#endif
2945239748Sjhb#ifdef INET
2946219820Sjeff	struct sockaddr_in *sin = (struct sockaddr_in *) addr;
2947239748Sjhb#endif
2948239748Sjhb#ifdef INET6
2949219820Sjeff	struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *) addr;
2950239748Sjhb#endif
2951219820Sjeff
2952219820Sjeff	if (cma_any_addr(addr)) {
2953219820Sjeff		memset(mgid, 0, sizeof *mgid);
2954239748Sjhb#ifdef INET6
2955219820Sjeff	} else if ((addr->sa_family == AF_INET6) &&
2956219820Sjeff		   ((be32_to_cpu(sin6->sin6_addr.s6_addr32[0]) & 0xFFF0FFFF) ==
2957219820Sjeff								 0xFF10A01B)) {
2958219820Sjeff		/* IPv6 address is an SA assigned MGID. */
2959219820Sjeff		memcpy(mgid, &sin6->sin6_addr, sizeof *mgid);
2960219820Sjeff	} else if ((addr->sa_family == AF_INET6)) {
2961219820Sjeff		ipv6_ib_mc_map(&sin6->sin6_addr, dev_addr->broadcast, mc_map);
2962219820Sjeff		if (id_priv->id.ps == RDMA_PS_UDP)
2963219820Sjeff			mc_map[7] = 0x01;	/* Use RDMA CM signature */
2964219820Sjeff		*mgid = *(union ib_gid *) (mc_map + 4);
2965239748Sjhb#endif
2966239748Sjhb#ifdef INET
2967219820Sjeff	} else {
2968219820Sjeff		ip_ib_mc_map(sin->sin_addr.s_addr, dev_addr->broadcast, mc_map);
2969219820Sjeff		if (id_priv->id.ps == RDMA_PS_UDP)
2970219820Sjeff			mc_map[7] = 0x01;	/* Use RDMA CM signature */
2971219820Sjeff		*mgid = *(union ib_gid *) (mc_map + 4);
2972239748Sjhb#endif
2973219820Sjeff	}
2974219820Sjeff}
2975219820Sjeff
2976219820Sjeffstatic int cma_join_ib_multicast(struct rdma_id_private *id_priv,
2977219820Sjeff				 struct cma_multicast *mc)
2978219820Sjeff{
2979219820Sjeff	struct ib_sa_mcmember_rec rec;
2980219820Sjeff	struct rdma_dev_addr *dev_addr = &id_priv->id.route.addr.dev_addr;
2981219820Sjeff	ib_sa_comp_mask comp_mask;
2982219820Sjeff	int ret;
2983219820Sjeff
2984219820Sjeff	ib_addr_get_mgid(dev_addr, &rec.mgid);
2985219820Sjeff	ret = ib_sa_get_mcmember_rec(id_priv->id.device, id_priv->id.port_num,
2986219820Sjeff				     &rec.mgid, &rec);
2987219820Sjeff	if (ret)
2988219820Sjeff		return ret;
2989219820Sjeff
2990219820Sjeff	cma_set_mgid(id_priv, (struct sockaddr *) &mc->addr, &rec.mgid);
2991219820Sjeff	if (id_priv->id.ps == RDMA_PS_UDP)
2992219820Sjeff		rec.qkey = cpu_to_be32(RDMA_UDP_QKEY);
2993219820Sjeff	rdma_addr_get_sgid(dev_addr, &rec.port_gid);
2994219820Sjeff	rec.pkey = cpu_to_be16(ib_addr_get_pkey(dev_addr));
2995219820Sjeff	rec.join_state = 1;
2996219820Sjeff
2997219820Sjeff	comp_mask = IB_SA_MCMEMBER_REC_MGID | IB_SA_MCMEMBER_REC_PORT_GID |
2998219820Sjeff		    IB_SA_MCMEMBER_REC_PKEY | IB_SA_MCMEMBER_REC_JOIN_STATE |
2999219820Sjeff		    IB_SA_MCMEMBER_REC_QKEY | IB_SA_MCMEMBER_REC_SL |
3000219820Sjeff		    IB_SA_MCMEMBER_REC_FLOW_LABEL |
3001219820Sjeff		    IB_SA_MCMEMBER_REC_TRAFFIC_CLASS;
3002219820Sjeff
3003219820Sjeff	if (id_priv->id.ps == RDMA_PS_IPOIB)
3004219820Sjeff		comp_mask |= IB_SA_MCMEMBER_REC_RATE |
3005219820Sjeff			     IB_SA_MCMEMBER_REC_RATE_SELECTOR;
3006219820Sjeff
3007219820Sjeff	mc->multicast.ib = ib_sa_join_multicast(&sa_client, id_priv->id.device,
3008219820Sjeff						id_priv->id.port_num, &rec,
3009219820Sjeff						comp_mask, GFP_KERNEL,
3010219820Sjeff						cma_ib_mc_handler, mc);
3011219820Sjeff	if (IS_ERR(mc->multicast.ib))
3012219820Sjeff		return PTR_ERR(mc->multicast.ib);
3013219820Sjeff
3014219820Sjeff	return 0;
3015219820Sjeff}
3016219820Sjeff
3017219820Sjeff
3018219820Sjeffstatic void iboe_mcast_work_handler(struct work_struct *work)
3019219820Sjeff{
3020219820Sjeff	struct iboe_mcast_work *mw = container_of(work, struct iboe_mcast_work, work);
3021219820Sjeff	struct cma_multicast *mc = mw->mc;
3022219820Sjeff	struct ib_sa_multicast *m = mc->multicast.ib;
3023219820Sjeff
3024219820Sjeff	mc->multicast.ib->context = mc;
3025219820Sjeff	cma_ib_mc_handler(0, m);
3026219820Sjeff	kref_put(&mc->mcref, release_mc);
3027219820Sjeff	kfree(mw);
3028219820Sjeff}
3029219820Sjeff
3030219820Sjeffstatic void cma_iboe_set_mgid(struct sockaddr *addr, union ib_gid *mgid)
3031219820Sjeff{
3032219820Sjeff	struct sockaddr_in *sin = (struct sockaddr_in *)addr;
3033219820Sjeff	struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)addr;
3034219820Sjeff
3035219820Sjeff	if (cma_any_addr(addr)) {
3036219820Sjeff		memset(mgid, 0, sizeof *mgid);
3037219820Sjeff	} else if (addr->sa_family == AF_INET6)
3038219820Sjeff		memcpy(mgid, &sin6->sin6_addr, sizeof *mgid);
3039219820Sjeff	else {
3040219820Sjeff		mgid->raw[0] = 0xff;
3041219820Sjeff		mgid->raw[1] = 0x0e;
3042219820Sjeff		mgid->raw[2] = 0;
3043219820Sjeff		mgid->raw[3] = 0;
3044219820Sjeff		mgid->raw[4] = 0;
3045219820Sjeff		mgid->raw[5] = 0;
3046219820Sjeff		mgid->raw[6] = 0;
3047219820Sjeff		mgid->raw[7] = 0;
3048219820Sjeff		mgid->raw[8] = 0;
3049219820Sjeff		mgid->raw[9] = 0;
3050219820Sjeff		mgid->raw[10] = 0xff;
3051219820Sjeff		mgid->raw[11] = 0xff;
3052219820Sjeff		*(__be32 *)(&mgid->raw[12]) = sin->sin_addr.s_addr;
3053219820Sjeff	}
3054219820Sjeff}
3055219820Sjeff
3056219820Sjeffstatic int cma_iboe_join_multicast(struct rdma_id_private *id_priv,
3057219820Sjeff				   struct cma_multicast *mc)
3058219820Sjeff{
3059219820Sjeff	struct iboe_mcast_work *work;
3060219820Sjeff	struct rdma_dev_addr *dev_addr = &id_priv->id.route.addr.dev_addr;
3061219820Sjeff	int err;
3062219820Sjeff	struct sockaddr *addr = (struct sockaddr *)&mc->addr;
3063219820Sjeff	struct net_device *ndev = NULL;
3064219820Sjeff
3065219820Sjeff	if (cma_zero_addr((struct sockaddr *)&mc->addr))
3066219820Sjeff		return -EINVAL;
3067219820Sjeff
3068219820Sjeff	work = kzalloc(sizeof *work, GFP_KERNEL);
3069219820Sjeff	if (!work)
3070219820Sjeff		return -ENOMEM;
3071219820Sjeff
3072219820Sjeff	mc->multicast.ib = kzalloc(sizeof(struct ib_sa_multicast), GFP_KERNEL);
3073219820Sjeff	if (!mc->multicast.ib) {
3074219820Sjeff		err = -ENOMEM;
3075219820Sjeff		goto out1;
3076219820Sjeff	}
3077219820Sjeff
3078219820Sjeff	cma_iboe_set_mgid(addr, &mc->multicast.ib->rec.mgid);
3079219820Sjeff
3080219820Sjeff	mc->multicast.ib->rec.pkey = cpu_to_be16(0xffff);
3081219820Sjeff	if (id_priv->id.ps == RDMA_PS_UDP)
3082219820Sjeff		mc->multicast.ib->rec.qkey = cpu_to_be32(RDMA_UDP_QKEY);
3083219820Sjeff
3084219820Sjeff	if (dev_addr->bound_dev_if)
3085219820Sjeff		ndev = dev_get_by_index(&init_net, dev_addr->bound_dev_if);
3086219820Sjeff	if (!ndev) {
3087219820Sjeff		err = -ENODEV;
3088219820Sjeff		goto out2;
3089219820Sjeff	}
3090219820Sjeff
3091219820Sjeff	mc->multicast.ib->rec.rate = iboe_get_rate(ndev);
3092219820Sjeff	mc->multicast.ib->rec.hop_limit = 1;
3093219820Sjeff#ifdef __linux__
3094219820Sjeff	mc->multicast.ib->rec.mtu = iboe_get_mtu(ndev->mtu);
3095219820Sjeff#else
3096219820Sjeff	mc->multicast.ib->rec.mtu = iboe_get_mtu(ndev->if_mtu);
3097219820Sjeff#endif
3098219820Sjeff	dev_put(ndev);
3099219820Sjeff	if (!mc->multicast.ib->rec.mtu) {
3100219820Sjeff		err = -EINVAL;
3101219820Sjeff		goto out2;
3102219820Sjeff	}
3103219820Sjeff	iboe_addr_get_sgid(dev_addr, &mc->multicast.ib->rec.port_gid);
3104219820Sjeff	work->id = id_priv;
3105219820Sjeff	work->mc = mc;
3106219820Sjeff	INIT_WORK(&work->work, iboe_mcast_work_handler);
3107219820Sjeff	kref_get(&mc->mcref);
3108219820Sjeff	queue_work(cma_wq, &work->work);
3109219820Sjeff
3110219820Sjeff	return 0;
3111219820Sjeff
3112219820Sjeffout2:
3113219820Sjeff	kfree(mc->multicast.ib);
3114219820Sjeffout1:
3115219820Sjeff	kfree(work);
3116219820Sjeff	return err;
3117219820Sjeff}
3118219820Sjeff
3119219820Sjeffint rdma_join_multicast(struct rdma_cm_id *id, struct sockaddr *addr,
3120219820Sjeff			void *context)
3121219820Sjeff{
3122219820Sjeff	struct rdma_id_private *id_priv;
3123219820Sjeff	struct cma_multicast *mc;
3124219820Sjeff	int ret;
3125219820Sjeff
3126219820Sjeff	id_priv = container_of(id, struct rdma_id_private, id);
3127219820Sjeff	if (!cma_comp(id_priv, CMA_ADDR_BOUND) &&
3128219820Sjeff	    !cma_comp(id_priv, CMA_ADDR_RESOLVED))
3129219820Sjeff		return -EINVAL;
3130219820Sjeff
3131219820Sjeff	mc = kmalloc(sizeof *mc, GFP_KERNEL);
3132219820Sjeff	if (!mc)
3133219820Sjeff		return -ENOMEM;
3134219820Sjeff
3135219820Sjeff	memcpy(&mc->addr, addr, ip_addr_size(addr));
3136219820Sjeff	mc->context = context;
3137219820Sjeff	mc->id_priv = id_priv;
3138219820Sjeff
3139219820Sjeff	spin_lock(&id_priv->lock);
3140219820Sjeff	list_add(&mc->list, &id_priv->mc_list);
3141219820Sjeff	spin_unlock(&id_priv->lock);
3142219820Sjeff
3143219820Sjeff	switch (rdma_node_get_transport(id->device->node_type)) {
3144219820Sjeff	case RDMA_TRANSPORT_IB:
3145219820Sjeff		switch (rdma_port_get_link_layer(id->device, id->port_num)) {
3146219820Sjeff		case IB_LINK_LAYER_INFINIBAND:
3147219820Sjeff			ret = cma_join_ib_multicast(id_priv, mc);
3148219820Sjeff			break;
3149219820Sjeff		case IB_LINK_LAYER_ETHERNET:
3150219820Sjeff			kref_init(&mc->mcref);
3151219820Sjeff			ret = cma_iboe_join_multicast(id_priv, mc);
3152219820Sjeff			break;
3153219820Sjeff		default:
3154219820Sjeff			ret = -EINVAL;
3155219820Sjeff		}
3156219820Sjeff		break;
3157219820Sjeff	default:
3158219820Sjeff		ret = -ENOSYS;
3159219820Sjeff		break;
3160219820Sjeff	}
3161219820Sjeff
3162219820Sjeff	if (ret) {
3163219820Sjeff		spin_lock_irq(&id_priv->lock);
3164219820Sjeff		list_del(&mc->list);
3165219820Sjeff		spin_unlock_irq(&id_priv->lock);
3166219820Sjeff		kfree(mc);
3167219820Sjeff	}
3168219820Sjeff
3169219820Sjeff	return ret;
3170219820Sjeff}
3171219820SjeffEXPORT_SYMBOL(rdma_join_multicast);
3172219820Sjeff
3173219820Sjeffvoid rdma_leave_multicast(struct rdma_cm_id *id, struct sockaddr *addr)
3174219820Sjeff{
3175219820Sjeff	struct rdma_id_private *id_priv;
3176219820Sjeff	struct cma_multicast *mc;
3177219820Sjeff
3178219820Sjeff	id_priv = container_of(id, struct rdma_id_private, id);
3179219820Sjeff	spin_lock_irq(&id_priv->lock);
3180219820Sjeff	list_for_each_entry(mc, &id_priv->mc_list, list) {
3181219820Sjeff		if (!memcmp(&mc->addr, addr, ip_addr_size(addr))) {
3182219820Sjeff			list_del(&mc->list);
3183219820Sjeff			spin_unlock_irq(&id_priv->lock);
3184219820Sjeff
3185219820Sjeff			if (id->qp)
3186219820Sjeff				ib_detach_mcast(id->qp,
3187219820Sjeff						&mc->multicast.ib->rec.mgid,
3188219820Sjeff						mc->multicast.ib->rec.mlid);
3189219820Sjeff			if (rdma_node_get_transport(id_priv->cma_dev->device->node_type) == RDMA_TRANSPORT_IB) {
3190219820Sjeff				switch (rdma_port_get_link_layer(id->device, id->port_num)) {
3191219820Sjeff				case IB_LINK_LAYER_INFINIBAND:
3192219820Sjeff					ib_sa_free_multicast(mc->multicast.ib);
3193219820Sjeff					kfree(mc);
3194219820Sjeff					break;
3195219820Sjeff				case IB_LINK_LAYER_ETHERNET:
3196219820Sjeff					kref_put(&mc->mcref, release_mc);
3197219820Sjeff					break;
3198219820Sjeff				default:
3199219820Sjeff					break;
3200219820Sjeff				}
3201219820Sjeff			}
3202219820Sjeff			return;
3203219820Sjeff		}
3204219820Sjeff	}
3205219820Sjeff	spin_unlock_irq(&id_priv->lock);
3206219820Sjeff}
3207219820SjeffEXPORT_SYMBOL(rdma_leave_multicast);
3208219820Sjeff
3209219820Sjeffstatic int cma_netdev_change(struct net_device *ndev, struct rdma_id_private *id_priv)
3210219820Sjeff{
3211219820Sjeff	struct rdma_dev_addr *dev_addr;
3212219820Sjeff	struct cma_ndev_work *work;
3213219820Sjeff
3214219820Sjeff	dev_addr = &id_priv->id.route.addr.dev_addr;
3215219820Sjeff
3216219820Sjeff#ifdef __linux__
3217219820Sjeff	if ((dev_addr->bound_dev_if == ndev->ifindex) &&
3218219820Sjeff	    memcmp(dev_addr->src_dev_addr, ndev->dev_addr, ndev->addr_len)) {
3219219820Sjeff		printk(KERN_INFO "RDMA CM addr change for ndev %s used by id %p\n",
3220219820Sjeff		       ndev->name, &id_priv->id);
3221219820Sjeff#else
3222219820Sjeff	if ((dev_addr->bound_dev_if == ndev->if_index) &&
3223219820Sjeff	    memcmp(dev_addr->src_dev_addr, IF_LLADDR(ndev), ndev->if_addrlen)) {
3224219820Sjeff		printk(KERN_INFO "RDMA CM addr change for ndev %s used by id %p\n",
3225219820Sjeff		       ndev->if_xname, &id_priv->id);
3226219820Sjeff#endif
3227219820Sjeff		work = kzalloc(sizeof *work, GFP_KERNEL);
3228219820Sjeff		if (!work)
3229219820Sjeff			return -ENOMEM;
3230219820Sjeff
3231219820Sjeff		INIT_WORK(&work->work, cma_ndev_work_handler);
3232219820Sjeff		work->id = id_priv;
3233219820Sjeff		work->event.event = RDMA_CM_EVENT_ADDR_CHANGE;
3234219820Sjeff		atomic_inc(&id_priv->refcount);
3235219820Sjeff		queue_work(cma_wq, &work->work);
3236219820Sjeff	}
3237219820Sjeff
3238219820Sjeff	return 0;
3239219820Sjeff}
3240219820Sjeff
3241219820Sjeffstatic int cma_netdev_callback(struct notifier_block *self, unsigned long event,
3242219820Sjeff			       void *ctx)
3243219820Sjeff{
3244219820Sjeff	struct net_device *ndev = (struct net_device *)ctx;
3245219820Sjeff	struct cma_device *cma_dev;
3246219820Sjeff	struct rdma_id_private *id_priv;
3247219820Sjeff	int ret = NOTIFY_DONE;
3248219820Sjeff
3249219820Sjeff#ifdef __linux__
3250219820Sjeff	if (dev_net(ndev) != &init_net)
3251219820Sjeff		return NOTIFY_DONE;
3252219820Sjeff
3253219820Sjeff	if (event != NETDEV_BONDING_FAILOVER)
3254219820Sjeff		return NOTIFY_DONE;
3255219820Sjeff
3256219820Sjeff	if (!(ndev->flags & IFF_MASTER) || !(ndev->priv_flags & IFF_BONDING))
3257219820Sjeff		return NOTIFY_DONE;
3258219820Sjeff#else
3259219820Sjeff	if (event != NETDEV_DOWN && event != NETDEV_UNREGISTER)
3260219820Sjeff		return NOTIFY_DONE;
3261219820Sjeff#endif
3262219820Sjeff
3263219820Sjeff	mutex_lock(&lock);
3264219820Sjeff	list_for_each_entry(cma_dev, &dev_list, list)
3265219820Sjeff		list_for_each_entry(id_priv, &cma_dev->id_list, list) {
3266219820Sjeff			ret = cma_netdev_change(ndev, id_priv);
3267219820Sjeff			if (ret)
3268219820Sjeff				goto out;
3269219820Sjeff		}
3270219820Sjeff
3271219820Sjeffout:
3272219820Sjeff	mutex_unlock(&lock);
3273219820Sjeff	return ret;
3274219820Sjeff}
3275219820Sjeff
3276219820Sjeffstatic struct notifier_block cma_nb = {
3277219820Sjeff	.notifier_call = cma_netdev_callback
3278219820Sjeff};
3279219820Sjeff
3280219820Sjeffstatic void cma_add_one(struct ib_device *device)
3281219820Sjeff{
3282219820Sjeff	struct cma_device *cma_dev;
3283219820Sjeff	struct rdma_id_private *id_priv;
3284219820Sjeff
3285219820Sjeff	cma_dev = kmalloc(sizeof *cma_dev, GFP_KERNEL);
3286219820Sjeff	if (!cma_dev)
3287219820Sjeff		return;
3288219820Sjeff
3289219820Sjeff	cma_dev->device = device;
3290219820Sjeff
3291219820Sjeff	init_completion(&cma_dev->comp);
3292219820Sjeff	atomic_set(&cma_dev->refcount, 1);
3293219820Sjeff	INIT_LIST_HEAD(&cma_dev->id_list);
3294219820Sjeff	ib_set_client_data(device, &cma_client, cma_dev);
3295219820Sjeff
3296219820Sjeff	mutex_lock(&lock);
3297219820Sjeff	list_add_tail(&cma_dev->list, &dev_list);
3298219820Sjeff	list_for_each_entry(id_priv, &listen_any_list, list)
3299219820Sjeff		cma_listen_on_dev(id_priv, cma_dev);
3300219820Sjeff	mutex_unlock(&lock);
3301219820Sjeff}
3302219820Sjeff
3303219820Sjeffstatic int cma_remove_id_dev(struct rdma_id_private *id_priv)
3304219820Sjeff{
3305219820Sjeff	struct rdma_cm_event event;
3306219820Sjeff	enum cma_state state;
3307219820Sjeff	int ret = 0;
3308219820Sjeff
3309219820Sjeff	/* Record that we want to remove the device */
3310219820Sjeff	state = cma_exch(id_priv, CMA_DEVICE_REMOVAL);
3311219820Sjeff	if (state == CMA_DESTROYING)
3312219820Sjeff		return 0;
3313219820Sjeff
3314219820Sjeff	cma_cancel_operation(id_priv, state);
3315219820Sjeff	mutex_lock(&id_priv->handler_mutex);
3316219820Sjeff
3317219820Sjeff	/* Check for destruction from another callback. */
3318219820Sjeff	if (!cma_comp(id_priv, CMA_DEVICE_REMOVAL))
3319219820Sjeff		goto out;
3320219820Sjeff
3321219820Sjeff	memset(&event, 0, sizeof event);
3322219820Sjeff	event.event = RDMA_CM_EVENT_DEVICE_REMOVAL;
3323219820Sjeff	ret = id_priv->id.event_handler(&id_priv->id, &event);
3324219820Sjeffout:
3325219820Sjeff	mutex_unlock(&id_priv->handler_mutex);
3326219820Sjeff	return ret;
3327219820Sjeff}
3328219820Sjeff
3329219820Sjeffstatic void cma_process_remove(struct cma_device *cma_dev)
3330219820Sjeff{
3331219820Sjeff	struct rdma_id_private *id_priv;
3332219820Sjeff	int ret;
3333219820Sjeff
3334219820Sjeff	mutex_lock(&lock);
3335219820Sjeff	while (!list_empty(&cma_dev->id_list)) {
3336219820Sjeff		id_priv = list_entry(cma_dev->id_list.next,
3337219820Sjeff				     struct rdma_id_private, list);
3338219820Sjeff
3339219820Sjeff		list_del(&id_priv->listen_list);
3340219820Sjeff		list_del_init(&id_priv->list);
3341219820Sjeff		atomic_inc(&id_priv->refcount);
3342219820Sjeff		mutex_unlock(&lock);
3343219820Sjeff
3344219820Sjeff		ret = id_priv->internal_id ? 1 : cma_remove_id_dev(id_priv);
3345219820Sjeff		cma_deref_id(id_priv);
3346219820Sjeff		if (ret)
3347219820Sjeff			rdma_destroy_id(&id_priv->id);
3348219820Sjeff
3349219820Sjeff		mutex_lock(&lock);
3350219820Sjeff	}
3351219820Sjeff	mutex_unlock(&lock);
3352219820Sjeff
3353219820Sjeff	cma_deref_dev(cma_dev);
3354219820Sjeff	wait_for_completion(&cma_dev->comp);
3355219820Sjeff}
3356219820Sjeff
3357219820Sjeffstatic void cma_remove_one(struct ib_device *device)
3358219820Sjeff{
3359219820Sjeff	struct cma_device *cma_dev;
3360219820Sjeff
3361219820Sjeff	cma_dev = ib_get_client_data(device, &cma_client);
3362219820Sjeff	if (!cma_dev)
3363219820Sjeff		return;
3364219820Sjeff
3365219820Sjeff	mutex_lock(&lock);
3366219820Sjeff	list_del(&cma_dev->list);
3367219820Sjeff	mutex_unlock(&lock);
3368219820Sjeff
3369219820Sjeff	cma_process_remove(cma_dev);
3370219820Sjeff	kfree(cma_dev);
3371219820Sjeff}
3372219820Sjeff
3373219820Sjeffstatic int cma_init(void)
3374219820Sjeff{
3375239748Sjhb	int ret;
3376239748Sjhb#if defined(INET)
3377239748Sjhb	int low, high, remaining;
3378219820Sjeff
3379219820Sjeff	get_random_bytes(&next_port, sizeof next_port);
3380219820Sjeff	inet_get_local_port_range(&low, &high);
3381219820Sjeff	remaining = (high - low) + 1;
3382219820Sjeff	next_port = ((unsigned int) next_port % remaining) + low;
3383239748Sjhb#endif
3384219820Sjeff
3385219820Sjeff	cma_wq = create_singlethread_workqueue("rdma_cm");
3386219820Sjeff	if (!cma_wq)
3387219820Sjeff		return -ENOMEM;
3388219820Sjeff
3389219820Sjeff	ib_sa_register_client(&sa_client);
3390219820Sjeff	rdma_addr_register_client(&addr_client);
3391219820Sjeff	register_netdevice_notifier(&cma_nb);
3392219820Sjeff
3393219820Sjeff	ret = ib_register_client(&cma_client);
3394219820Sjeff	if (ret)
3395219820Sjeff		goto err;
3396219820Sjeff	return 0;
3397219820Sjeff
3398219820Sjefferr:
3399219820Sjeff	unregister_netdevice_notifier(&cma_nb);
3400219820Sjeff	rdma_addr_unregister_client(&addr_client);
3401219820Sjeff	ib_sa_unregister_client(&sa_client);
3402219820Sjeff	destroy_workqueue(cma_wq);
3403219820Sjeff	return ret;
3404219820Sjeff}
3405219820Sjeff
3406219820Sjeffstatic void cma_cleanup(void)
3407219820Sjeff{
3408219820Sjeff	ib_unregister_client(&cma_client);
3409219820Sjeff	unregister_netdevice_notifier(&cma_nb);
3410219820Sjeff	rdma_addr_unregister_client(&addr_client);
3411219820Sjeff	ib_sa_unregister_client(&sa_client);
3412219820Sjeff	destroy_workqueue(cma_wq);
3413219820Sjeff	idr_destroy(&sdp_ps);
3414219820Sjeff	idr_destroy(&tcp_ps);
3415219820Sjeff	idr_destroy(&udp_ps);
3416219820Sjeff	idr_destroy(&ipoib_ps);
3417219820Sjeff}
3418219820Sjeff
3419219820Sjeffmodule_init(cma_init);
3420219820Sjeffmodule_exit(cma_cleanup);
3421