1219820Sjeff/*
2219820Sjeff * Copyright (c) 2004-2007 Intel Corporation.  All rights reserved.
3219820Sjeff * Copyright (c) 2004 Topspin Corporation.  All rights reserved.
4219820Sjeff * Copyright (c) 2004, 2005 Voltaire Corporation.  All rights reserved.
5219820Sjeff * Copyright (c) 2005 Sun Microsystems, Inc. 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/dma-mapping.h>
38219820Sjeff#include <linux/device.h>
39219820Sjeff#include <linux/err.h>
40219820Sjeff#include <linux/idr.h>
41219820Sjeff#include <linux/interrupt.h>
42219820Sjeff#include <linux/random.h>
43219820Sjeff#include <linux/rbtree.h>
44219820Sjeff#include <linux/spinlock.h>
45219820Sjeff#include <linux/sysfs.h>
46219820Sjeff#include <linux/workqueue.h>
47219820Sjeff#include <linux/kdev_t.h>
48271127Shselasky#include <linux/string.h>
49219820Sjeff
50271127Shselasky#include <asm/atomic-long.h>
51271127Shselasky
52219820Sjeff#include <rdma/ib_cache.h>
53219820Sjeff#include <rdma/ib_cm.h>
54219820Sjeff#include "cm_msgs.h"
55219820Sjeff
56219820SjeffMODULE_AUTHOR("Sean Hefty");
57219820SjeffMODULE_DESCRIPTION("InfiniBand CM");
58219820SjeffMODULE_LICENSE("Dual BSD/GPL");
59219820Sjeff
60219820Sjeff#define PFX    "ib_cm: "
61219820Sjeff
62219820Sjeff/*
63219820Sjeff * Limit CM message timeouts to something reasonable:
64219820Sjeff * 8 seconds per message, with up to 15 retries
65219820Sjeff */
66219820Sjeffstatic int max_timeout = 21;
67219820Sjeffmodule_param(max_timeout, int, 0644);
68219820SjeffMODULE_PARM_DESC(max_timeout, "Maximum IB CM per message timeout "
69219820Sjeff                             "(default=21, or ~8 seconds)");
70219820Sjeff
71219820Sjeffstatic void cm_add_one(struct ib_device *device);
72219820Sjeffstatic void cm_remove_one(struct ib_device *device);
73219820Sjeff
74219820Sjeffstatic struct ib_client cm_client = {
75219820Sjeff	.name   = "cm",
76219820Sjeff	.add    = cm_add_one,
77219820Sjeff	.remove = cm_remove_one
78219820Sjeff};
79219820Sjeff
80219820Sjeffstatic struct ib_cm {
81219820Sjeff	spinlock_t lock;
82219820Sjeff	struct list_head device_list;
83219820Sjeff	rwlock_t device_lock;
84219820Sjeff	struct rb_root listen_service_table;
85219820Sjeff	u64 listen_service_id;
86219820Sjeff	/* struct rb_root peer_service_table; todo: fix peer to peer */
87219820Sjeff	struct rb_root remote_qp_table;
88219820Sjeff	struct rb_root remote_id_table;
89219820Sjeff	struct rb_root remote_sidr_table;
90219820Sjeff	struct idr local_id_table;
91219820Sjeff	__be32 random_id_operand;
92219820Sjeff	struct list_head timewait_list;
93219820Sjeff	struct workqueue_struct *wq;
94219820Sjeff} cm;
95219820Sjeff
96219820Sjeff/* Counter indexes ordered by attribute ID */
97219820Sjeffenum {
98219820Sjeff	CM_REQ_COUNTER,
99219820Sjeff	CM_MRA_COUNTER,
100219820Sjeff	CM_REJ_COUNTER,
101219820Sjeff	CM_REP_COUNTER,
102219820Sjeff	CM_RTU_COUNTER,
103219820Sjeff	CM_DREQ_COUNTER,
104219820Sjeff	CM_DREP_COUNTER,
105219820Sjeff	CM_SIDR_REQ_COUNTER,
106219820Sjeff	CM_SIDR_REP_COUNTER,
107219820Sjeff	CM_LAP_COUNTER,
108219820Sjeff	CM_APR_COUNTER,
109219820Sjeff	CM_ATTR_COUNT,
110219820Sjeff	CM_ATTR_ID_OFFSET = 0x0010,
111219820Sjeff};
112219820Sjeff
113219820Sjeffenum {
114219820Sjeff	CM_XMIT,
115219820Sjeff	CM_XMIT_RETRIES,
116219820Sjeff	CM_RECV,
117219820Sjeff	CM_RECV_DUPLICATES,
118219820Sjeff	CM_COUNTER_GROUPS
119219820Sjeff};
120219820Sjeff
121219820Sjeffstatic char const counter_group_names[CM_COUNTER_GROUPS]
122219820Sjeff				     [sizeof("cm_rx_duplicates")] = {
123219820Sjeff	"cm_tx_msgs", "cm_tx_retries",
124219820Sjeff	"cm_rx_msgs", "cm_rx_duplicates"
125219820Sjeff};
126219820Sjeff
127219820Sjeffstruct cm_counter_group {
128219820Sjeff	struct kobject obj;
129219820Sjeff	atomic_long_t counter[CM_ATTR_COUNT];
130219820Sjeff};
131219820Sjeff
132219820Sjeffstruct cm_counter_attribute {
133219820Sjeff	struct attribute attr;
134219820Sjeff	int index;
135219820Sjeff};
136219820Sjeff
137219820Sjeff#define CM_COUNTER_ATTR(_name, _index) \
138219820Sjeffstruct cm_counter_attribute cm_##_name##_counter_attr = { \
139219820Sjeff	.attr = { .name = __stringify(_name), .mode = 0444 }, \
140219820Sjeff	.index = _index \
141219820Sjeff}
142219820Sjeff
143219820Sjeffstatic CM_COUNTER_ATTR(req, CM_REQ_COUNTER);
144219820Sjeffstatic CM_COUNTER_ATTR(mra, CM_MRA_COUNTER);
145219820Sjeffstatic CM_COUNTER_ATTR(rej, CM_REJ_COUNTER);
146219820Sjeffstatic CM_COUNTER_ATTR(rep, CM_REP_COUNTER);
147219820Sjeffstatic CM_COUNTER_ATTR(rtu, CM_RTU_COUNTER);
148219820Sjeffstatic CM_COUNTER_ATTR(dreq, CM_DREQ_COUNTER);
149219820Sjeffstatic CM_COUNTER_ATTR(drep, CM_DREP_COUNTER);
150219820Sjeffstatic CM_COUNTER_ATTR(sidr_req, CM_SIDR_REQ_COUNTER);
151219820Sjeffstatic CM_COUNTER_ATTR(sidr_rep, CM_SIDR_REP_COUNTER);
152219820Sjeffstatic CM_COUNTER_ATTR(lap, CM_LAP_COUNTER);
153219820Sjeffstatic CM_COUNTER_ATTR(apr, CM_APR_COUNTER);
154219820Sjeff
155219820Sjeffstatic struct attribute *cm_counter_default_attrs[] = {
156219820Sjeff	&cm_req_counter_attr.attr,
157219820Sjeff	&cm_mra_counter_attr.attr,
158219820Sjeff	&cm_rej_counter_attr.attr,
159219820Sjeff	&cm_rep_counter_attr.attr,
160219820Sjeff	&cm_rtu_counter_attr.attr,
161219820Sjeff	&cm_dreq_counter_attr.attr,
162219820Sjeff	&cm_drep_counter_attr.attr,
163219820Sjeff	&cm_sidr_req_counter_attr.attr,
164219820Sjeff	&cm_sidr_rep_counter_attr.attr,
165219820Sjeff	&cm_lap_counter_attr.attr,
166219820Sjeff	&cm_apr_counter_attr.attr,
167219820Sjeff	NULL
168219820Sjeff};
169219820Sjeff
170219820Sjeffstruct cm_port {
171219820Sjeff	struct cm_device *cm_dev;
172219820Sjeff	struct ib_mad_agent *mad_agent;
173219820Sjeff	struct kobject port_obj;
174219820Sjeff	u8 port_num;
175219820Sjeff	struct cm_counter_group counter_group[CM_COUNTER_GROUPS];
176219820Sjeff};
177219820Sjeff
178219820Sjeffstruct cm_device {
179219820Sjeff	struct list_head list;
180219820Sjeff	struct ib_device *ib_device;
181219820Sjeff	struct device *device;
182219820Sjeff	u8 ack_delay;
183219820Sjeff	struct cm_port *port[0];
184219820Sjeff};
185219820Sjeff
186219820Sjeffstruct cm_av {
187219820Sjeff	struct cm_port *port;
188219820Sjeff	union ib_gid dgid;
189219820Sjeff	struct ib_ah_attr ah_attr;
190219820Sjeff	u16 pkey_index;
191219820Sjeff	u8 timeout;
192219820Sjeff};
193219820Sjeff
194219820Sjeffstruct cm_work {
195219820Sjeff	struct delayed_work work;
196219820Sjeff	struct list_head list;
197219820Sjeff	struct cm_port *port;
198219820Sjeff	struct ib_mad_recv_wc *mad_recv_wc;	/* Received MADs */
199219820Sjeff	__be32 local_id;			/* Established / timewait */
200219820Sjeff	__be32 remote_id;
201219820Sjeff	struct ib_cm_event cm_event;
202219820Sjeff	struct ib_sa_path_rec path[0];
203219820Sjeff};
204219820Sjeff
205219820Sjeffstruct cm_timewait_info {
206219820Sjeff	struct cm_work work;			/* Must be first. */
207219820Sjeff	struct list_head list;
208219820Sjeff	struct rb_node remote_qp_node;
209219820Sjeff	struct rb_node remote_id_node;
210219820Sjeff	__be64 remote_ca_guid;
211219820Sjeff	__be32 remote_qpn;
212219820Sjeff	u8 inserted_remote_qp;
213219820Sjeff	u8 inserted_remote_id;
214219820Sjeff};
215219820Sjeff
216219820Sjeffstruct cm_id_private {
217219820Sjeff	struct ib_cm_id	id;
218219820Sjeff
219219820Sjeff	struct rb_node service_node;
220219820Sjeff	struct rb_node sidr_id_node;
221219820Sjeff	spinlock_t lock;	/* Do not acquire inside cm.lock */
222219820Sjeff	struct completion comp;
223219820Sjeff	atomic_t refcount;
224219820Sjeff
225219820Sjeff	struct ib_mad_send_buf *msg;
226219820Sjeff	struct cm_timewait_info *timewait_info;
227219820Sjeff	/* todo: use alternate port on send failure */
228219820Sjeff	struct cm_av av;
229219820Sjeff	struct cm_av alt_av;
230219820Sjeff	struct ib_cm_compare_data *compare_data;
231219820Sjeff
232219820Sjeff	void *private_data;
233219820Sjeff	__be64 tid;
234219820Sjeff	__be32 local_qpn;
235219820Sjeff	__be32 remote_qpn;
236219820Sjeff	enum ib_qp_type qp_type;
237219820Sjeff	__be32 sq_psn;
238219820Sjeff	__be32 rq_psn;
239219820Sjeff	int timeout_ms;
240219820Sjeff	enum ib_mtu path_mtu;
241219820Sjeff	__be16 pkey;
242219820Sjeff	u8 private_data_len;
243219820Sjeff	u8 max_cm_retries;
244219820Sjeff	u8 peer_to_peer;
245219820Sjeff	u8 responder_resources;
246219820Sjeff	u8 initiator_depth;
247219820Sjeff	u8 retry_count;
248219820Sjeff	u8 rnr_retry_count;
249219820Sjeff	u8 service_timeout;
250219820Sjeff	u8 target_ack_delay;
251219820Sjeff
252219820Sjeff	struct list_head work_list;
253219820Sjeff	atomic_t work_count;
254219820Sjeff};
255219820Sjeff
256219820Sjeffstatic void cm_work_handler(struct work_struct *work);
257219820Sjeff
258219820Sjeffstatic inline void cm_deref_id(struct cm_id_private *cm_id_priv)
259219820Sjeff{
260219820Sjeff	if (atomic_dec_and_test(&cm_id_priv->refcount))
261219820Sjeff		complete(&cm_id_priv->comp);
262219820Sjeff}
263219820Sjeff
264219820Sjeffstatic int cm_alloc_msg(struct cm_id_private *cm_id_priv,
265219820Sjeff			struct ib_mad_send_buf **msg)
266219820Sjeff{
267219820Sjeff	struct ib_mad_agent *mad_agent;
268219820Sjeff	struct ib_mad_send_buf *m;
269219820Sjeff	struct ib_ah *ah;
270219820Sjeff
271219820Sjeff	mad_agent = cm_id_priv->av.port->mad_agent;
272219820Sjeff	ah = ib_create_ah(mad_agent->qp->pd, &cm_id_priv->av.ah_attr);
273219820Sjeff	if (IS_ERR(ah))
274219820Sjeff		return PTR_ERR(ah);
275219820Sjeff
276219820Sjeff	m = ib_create_send_mad(mad_agent, cm_id_priv->id.remote_cm_qpn,
277219820Sjeff			       cm_id_priv->av.pkey_index,
278219820Sjeff			       0, IB_MGMT_MAD_HDR, IB_MGMT_MAD_DATA,
279219820Sjeff			       GFP_ATOMIC);
280219820Sjeff	if (IS_ERR(m)) {
281219820Sjeff		ib_destroy_ah(ah);
282219820Sjeff		return PTR_ERR(m);
283219820Sjeff	}
284219820Sjeff
285219820Sjeff	/* Timeout set by caller if response is expected. */
286219820Sjeff	m->ah = ah;
287219820Sjeff	m->retries = cm_id_priv->max_cm_retries;
288219820Sjeff
289219820Sjeff	atomic_inc(&cm_id_priv->refcount);
290219820Sjeff	m->context[0] = cm_id_priv;
291219820Sjeff	*msg = m;
292219820Sjeff	return 0;
293219820Sjeff}
294219820Sjeff
295219820Sjeffstatic int cm_alloc_response_msg(struct cm_port *port,
296219820Sjeff				 struct ib_mad_recv_wc *mad_recv_wc,
297219820Sjeff				 struct ib_mad_send_buf **msg)
298219820Sjeff{
299219820Sjeff	struct ib_mad_send_buf *m;
300219820Sjeff	struct ib_ah *ah;
301219820Sjeff
302219820Sjeff	ah = ib_create_ah_from_wc(port->mad_agent->qp->pd, mad_recv_wc->wc,
303219820Sjeff				  mad_recv_wc->recv_buf.grh, port->port_num);
304219820Sjeff	if (IS_ERR(ah))
305219820Sjeff		return PTR_ERR(ah);
306219820Sjeff
307219820Sjeff	m = ib_create_send_mad(port->mad_agent, 1, mad_recv_wc->wc->pkey_index,
308219820Sjeff			       0, IB_MGMT_MAD_HDR, IB_MGMT_MAD_DATA,
309219820Sjeff			       GFP_ATOMIC);
310219820Sjeff	if (IS_ERR(m)) {
311219820Sjeff		ib_destroy_ah(ah);
312219820Sjeff		return PTR_ERR(m);
313219820Sjeff	}
314219820Sjeff	m->ah = ah;
315219820Sjeff	*msg = m;
316219820Sjeff	return 0;
317219820Sjeff}
318219820Sjeff
319219820Sjeffstatic void cm_free_msg(struct ib_mad_send_buf *msg)
320219820Sjeff{
321219820Sjeff	ib_destroy_ah(msg->ah);
322219820Sjeff	if (msg->context[0])
323219820Sjeff		cm_deref_id(msg->context[0]);
324219820Sjeff	ib_free_send_mad(msg);
325219820Sjeff}
326219820Sjeff
327219820Sjeffstatic void * cm_copy_private_data(const void *private_data,
328219820Sjeff				   u8 private_data_len)
329219820Sjeff{
330219820Sjeff	void *data;
331219820Sjeff
332219820Sjeff	if (!private_data || !private_data_len)
333219820Sjeff		return NULL;
334219820Sjeff
335219820Sjeff	data = kmemdup(private_data, private_data_len, GFP_KERNEL);
336219820Sjeff	if (!data)
337219820Sjeff		return ERR_PTR(-ENOMEM);
338219820Sjeff
339219820Sjeff	return data;
340219820Sjeff}
341219820Sjeff
342219820Sjeffstatic void cm_set_private_data(struct cm_id_private *cm_id_priv,
343219820Sjeff				 void *private_data, u8 private_data_len)
344219820Sjeff{
345219820Sjeff	if (cm_id_priv->private_data && cm_id_priv->private_data_len)
346219820Sjeff		kfree(cm_id_priv->private_data);
347219820Sjeff
348219820Sjeff	cm_id_priv->private_data = private_data;
349219820Sjeff	cm_id_priv->private_data_len = private_data_len;
350219820Sjeff}
351219820Sjeff
352219820Sjeffstatic void cm_init_av_for_response(struct cm_port *port, struct ib_wc *wc,
353219820Sjeff				    struct ib_grh *grh, struct cm_av *av)
354219820Sjeff{
355219820Sjeff	av->port = port;
356219820Sjeff	av->pkey_index = wc->pkey_index;
357219820Sjeff	ib_init_ah_from_wc(port->cm_dev->ib_device, port->port_num, wc,
358219820Sjeff			   grh, &av->ah_attr);
359219820Sjeff}
360219820Sjeff
361219820Sjeffstatic int cm_init_av_by_path(struct ib_sa_path_rec *path, struct cm_av *av)
362219820Sjeff{
363219820Sjeff	struct cm_device *cm_dev;
364219820Sjeff	struct cm_port *port = NULL;
365219820Sjeff	unsigned long flags;
366219820Sjeff	int ret;
367219820Sjeff	u8 p;
368219820Sjeff
369219820Sjeff	read_lock_irqsave(&cm.device_lock, flags);
370219820Sjeff	list_for_each_entry(cm_dev, &cm.device_list, list) {
371219820Sjeff		if (!ib_find_cached_gid(cm_dev->ib_device, &path->sgid,
372219820Sjeff					&p, NULL)) {
373219820Sjeff			port = cm_dev->port[p-1];
374219820Sjeff			break;
375219820Sjeff		}
376219820Sjeff	}
377219820Sjeff	read_unlock_irqrestore(&cm.device_lock, flags);
378219820Sjeff
379219820Sjeff	if (!port)
380219820Sjeff		return -EINVAL;
381219820Sjeff
382219820Sjeff	ret = ib_find_cached_pkey(cm_dev->ib_device, port->port_num,
383219820Sjeff				  be16_to_cpu(path->pkey), &av->pkey_index);
384219820Sjeff	if (ret)
385219820Sjeff		return ret;
386219820Sjeff
387219820Sjeff	av->port = port;
388219820Sjeff	ib_init_ah_from_path(cm_dev->ib_device, port->port_num, path,
389219820Sjeff			     &av->ah_attr);
390219820Sjeff	av->timeout = path->packet_life_time + 1;
391219820Sjeff	return 0;
392219820Sjeff}
393219820Sjeff
394219820Sjeffstatic int cm_alloc_id(struct cm_id_private *cm_id_priv)
395219820Sjeff{
396219820Sjeff	unsigned long flags;
397219820Sjeff	int ret, id;
398219820Sjeff	static int next_id;
399219820Sjeff
400219820Sjeff	do {
401219820Sjeff		spin_lock_irqsave(&cm.lock, flags);
402219820Sjeff		ret = idr_get_new_above(&cm.local_id_table, cm_id_priv,
403219820Sjeff					next_id, &id);
404219820Sjeff		if (!ret)
405219820Sjeff			next_id = ((unsigned) id + 1) & MAX_ID_MASK;
406219820Sjeff		spin_unlock_irqrestore(&cm.lock, flags);
407219820Sjeff	} while( (ret == -EAGAIN) && idr_pre_get(&cm.local_id_table, GFP_KERNEL) );
408219820Sjeff
409219820Sjeff	cm_id_priv->id.local_id = (__force __be32)id ^ cm.random_id_operand;
410219820Sjeff	return ret;
411219820Sjeff}
412219820Sjeff
413219820Sjeffstatic void cm_free_id(__be32 local_id)
414219820Sjeff{
415219820Sjeff	spin_lock_irq(&cm.lock);
416219820Sjeff	idr_remove(&cm.local_id_table,
417219820Sjeff		   (__force int) (local_id ^ cm.random_id_operand));
418219820Sjeff	spin_unlock_irq(&cm.lock);
419219820Sjeff}
420219820Sjeff
421219820Sjeffstatic struct cm_id_private * cm_get_id(__be32 local_id, __be32 remote_id)
422219820Sjeff{
423219820Sjeff	struct cm_id_private *cm_id_priv;
424219820Sjeff
425219820Sjeff	cm_id_priv = idr_find(&cm.local_id_table,
426219820Sjeff			      (__force int) (local_id ^ cm.random_id_operand));
427219820Sjeff	if (cm_id_priv) {
428219820Sjeff		if (cm_id_priv->id.remote_id == remote_id)
429219820Sjeff			atomic_inc(&cm_id_priv->refcount);
430219820Sjeff		else
431219820Sjeff			cm_id_priv = NULL;
432219820Sjeff	}
433219820Sjeff
434219820Sjeff	return cm_id_priv;
435219820Sjeff}
436219820Sjeff
437219820Sjeffstatic struct cm_id_private * cm_acquire_id(__be32 local_id, __be32 remote_id)
438219820Sjeff{
439219820Sjeff	struct cm_id_private *cm_id_priv;
440219820Sjeff
441219820Sjeff	spin_lock_irq(&cm.lock);
442219820Sjeff	cm_id_priv = cm_get_id(local_id, remote_id);
443219820Sjeff	spin_unlock_irq(&cm.lock);
444219820Sjeff
445219820Sjeff	return cm_id_priv;
446219820Sjeff}
447219820Sjeff
448219820Sjeffstatic void cm_mask_copy(u8 *dst, u8 *src, u8 *mask)
449219820Sjeff{
450219820Sjeff	int i;
451219820Sjeff
452219820Sjeff	for (i = 0; i < IB_CM_COMPARE_SIZE / sizeof(unsigned long); i++)
453219820Sjeff		((unsigned long *) dst)[i] = ((unsigned long *) src)[i] &
454219820Sjeff					     ((unsigned long *) mask)[i];
455219820Sjeff}
456219820Sjeff
457219820Sjeffstatic int cm_compare_data(struct ib_cm_compare_data *src_data,
458219820Sjeff			   struct ib_cm_compare_data *dst_data)
459219820Sjeff{
460219820Sjeff	u8 src[IB_CM_COMPARE_SIZE];
461219820Sjeff	u8 dst[IB_CM_COMPARE_SIZE];
462219820Sjeff
463219820Sjeff	if (!src_data || !dst_data)
464219820Sjeff		return 0;
465219820Sjeff
466219820Sjeff	cm_mask_copy(src, src_data->data, dst_data->mask);
467219820Sjeff	cm_mask_copy(dst, dst_data->data, src_data->mask);
468219820Sjeff	return memcmp(src, dst, IB_CM_COMPARE_SIZE);
469219820Sjeff}
470219820Sjeff
471219820Sjeffstatic int cm_compare_private_data(u8 *private_data,
472219820Sjeff				   struct ib_cm_compare_data *dst_data)
473219820Sjeff{
474219820Sjeff	u8 src[IB_CM_COMPARE_SIZE];
475219820Sjeff
476219820Sjeff	if (!dst_data)
477219820Sjeff		return 0;
478219820Sjeff
479219820Sjeff	cm_mask_copy(src, private_data, dst_data->mask);
480219820Sjeff	return memcmp(src, dst_data->data, IB_CM_COMPARE_SIZE);
481219820Sjeff}
482219820Sjeff
483219820Sjeff/*
484219820Sjeff * Trivial helpers to strip endian annotation and compare; the
485219820Sjeff * endianness doesn't actually matter since we just need a stable
486219820Sjeff * order for the RB tree.
487219820Sjeff */
488219820Sjeffstatic int be32_lt(__be32 a, __be32 b)
489219820Sjeff{
490219820Sjeff	return (__force u32) a < (__force u32) b;
491219820Sjeff}
492219820Sjeff
493219820Sjeffstatic int be32_gt(__be32 a, __be32 b)
494219820Sjeff{
495219820Sjeff	return (__force u32) a > (__force u32) b;
496219820Sjeff}
497219820Sjeff
498219820Sjeffstatic int be64_lt(__be64 a, __be64 b)
499219820Sjeff{
500219820Sjeff	return (__force u64) a < (__force u64) b;
501219820Sjeff}
502219820Sjeff
503219820Sjeffstatic int be64_gt(__be64 a, __be64 b)
504219820Sjeff{
505219820Sjeff	return (__force u64) a > (__force u64) b;
506219820Sjeff}
507219820Sjeff
508219820Sjeffstatic struct cm_id_private * cm_insert_listen(struct cm_id_private *cm_id_priv)
509219820Sjeff{
510219820Sjeff	struct rb_node **link = &cm.listen_service_table.rb_node;
511219820Sjeff	struct rb_node *parent = NULL;
512219820Sjeff	struct cm_id_private *cur_cm_id_priv;
513219820Sjeff	__be64 service_id = cm_id_priv->id.service_id;
514219820Sjeff	__be64 service_mask = cm_id_priv->id.service_mask;
515219820Sjeff	int data_cmp;
516219820Sjeff
517219820Sjeff	while (*link) {
518219820Sjeff		parent = *link;
519219820Sjeff		cur_cm_id_priv = rb_entry(parent, struct cm_id_private,
520219820Sjeff					  service_node);
521219820Sjeff		data_cmp = cm_compare_data(cm_id_priv->compare_data,
522219820Sjeff					   cur_cm_id_priv->compare_data);
523219820Sjeff		if ((cur_cm_id_priv->id.service_mask & service_id) ==
524219820Sjeff		    (service_mask & cur_cm_id_priv->id.service_id) &&
525219820Sjeff		    (cm_id_priv->id.device == cur_cm_id_priv->id.device) &&
526219820Sjeff		    !data_cmp)
527219820Sjeff			return cur_cm_id_priv;
528219820Sjeff
529219820Sjeff		if (cm_id_priv->id.device < cur_cm_id_priv->id.device)
530219820Sjeff			link = &(*link)->rb_left;
531219820Sjeff		else if (cm_id_priv->id.device > cur_cm_id_priv->id.device)
532219820Sjeff			link = &(*link)->rb_right;
533219820Sjeff		else if (be64_lt(service_id, cur_cm_id_priv->id.service_id))
534219820Sjeff			link = &(*link)->rb_left;
535219820Sjeff		else if (be64_gt(service_id, cur_cm_id_priv->id.service_id))
536219820Sjeff			link = &(*link)->rb_right;
537219820Sjeff		else if (data_cmp < 0)
538219820Sjeff			link = &(*link)->rb_left;
539219820Sjeff		else
540219820Sjeff			link = &(*link)->rb_right;
541219820Sjeff	}
542219820Sjeff	rb_link_node(&cm_id_priv->service_node, parent, link);
543219820Sjeff	rb_insert_color(&cm_id_priv->service_node, &cm.listen_service_table);
544219820Sjeff	return NULL;
545219820Sjeff}
546219820Sjeff
547219820Sjeffstatic struct cm_id_private * cm_find_listen(struct ib_device *device,
548219820Sjeff					     __be64 service_id,
549219820Sjeff					     u8 *private_data)
550219820Sjeff{
551219820Sjeff	struct rb_node *node = cm.listen_service_table.rb_node;
552219820Sjeff	struct cm_id_private *cm_id_priv;
553219820Sjeff	int data_cmp;
554219820Sjeff
555219820Sjeff	while (node) {
556219820Sjeff		cm_id_priv = rb_entry(node, struct cm_id_private, service_node);
557219820Sjeff		data_cmp = cm_compare_private_data(private_data,
558219820Sjeff						   cm_id_priv->compare_data);
559219820Sjeff		if ((cm_id_priv->id.service_mask & service_id) ==
560219820Sjeff		     cm_id_priv->id.service_id &&
561219820Sjeff		    (cm_id_priv->id.device == device) && !data_cmp)
562219820Sjeff			return cm_id_priv;
563219820Sjeff
564219820Sjeff		if (device < cm_id_priv->id.device)
565219820Sjeff			node = node->rb_left;
566219820Sjeff		else if (device > cm_id_priv->id.device)
567219820Sjeff			node = node->rb_right;
568219820Sjeff		else if (be64_lt(service_id, cm_id_priv->id.service_id))
569219820Sjeff			node = node->rb_left;
570219820Sjeff		else if (be64_gt(service_id, cm_id_priv->id.service_id))
571219820Sjeff			node = node->rb_right;
572219820Sjeff		else if (data_cmp < 0)
573219820Sjeff			node = node->rb_left;
574219820Sjeff		else
575219820Sjeff			node = node->rb_right;
576219820Sjeff	}
577219820Sjeff	return NULL;
578219820Sjeff}
579219820Sjeff
580219820Sjeffstatic struct cm_timewait_info * cm_insert_remote_id(struct cm_timewait_info
581219820Sjeff						     *timewait_info)
582219820Sjeff{
583219820Sjeff	struct rb_node **link = &cm.remote_id_table.rb_node;
584219820Sjeff	struct rb_node *parent = NULL;
585219820Sjeff	struct cm_timewait_info *cur_timewait_info;
586219820Sjeff	__be64 remote_ca_guid = timewait_info->remote_ca_guid;
587219820Sjeff	__be32 remote_id = timewait_info->work.remote_id;
588219820Sjeff
589219820Sjeff	while (*link) {
590219820Sjeff		parent = *link;
591219820Sjeff		cur_timewait_info = rb_entry(parent, struct cm_timewait_info,
592219820Sjeff					     remote_id_node);
593219820Sjeff		if (be32_lt(remote_id, cur_timewait_info->work.remote_id))
594219820Sjeff			link = &(*link)->rb_left;
595219820Sjeff		else if (be32_gt(remote_id, cur_timewait_info->work.remote_id))
596219820Sjeff			link = &(*link)->rb_right;
597219820Sjeff		else if (be64_lt(remote_ca_guid, cur_timewait_info->remote_ca_guid))
598219820Sjeff			link = &(*link)->rb_left;
599219820Sjeff		else if (be64_gt(remote_ca_guid, cur_timewait_info->remote_ca_guid))
600219820Sjeff			link = &(*link)->rb_right;
601219820Sjeff		else
602219820Sjeff			return cur_timewait_info;
603219820Sjeff	}
604219820Sjeff	timewait_info->inserted_remote_id = 1;
605219820Sjeff	rb_link_node(&timewait_info->remote_id_node, parent, link);
606219820Sjeff	rb_insert_color(&timewait_info->remote_id_node, &cm.remote_id_table);
607219820Sjeff	return NULL;
608219820Sjeff}
609219820Sjeff
610219820Sjeffstatic struct cm_timewait_info * cm_find_remote_id(__be64 remote_ca_guid,
611219820Sjeff						   __be32 remote_id)
612219820Sjeff{
613219820Sjeff	struct rb_node *node = cm.remote_id_table.rb_node;
614219820Sjeff	struct cm_timewait_info *timewait_info;
615219820Sjeff
616219820Sjeff	while (node) {
617219820Sjeff		timewait_info = rb_entry(node, struct cm_timewait_info,
618219820Sjeff					 remote_id_node);
619219820Sjeff		if (be32_lt(remote_id, timewait_info->work.remote_id))
620219820Sjeff			node = node->rb_left;
621219820Sjeff		else if (be32_gt(remote_id, timewait_info->work.remote_id))
622219820Sjeff			node = node->rb_right;
623219820Sjeff		else if (be64_lt(remote_ca_guid, timewait_info->remote_ca_guid))
624219820Sjeff			node = node->rb_left;
625219820Sjeff		else if (be64_gt(remote_ca_guid, timewait_info->remote_ca_guid))
626219820Sjeff			node = node->rb_right;
627219820Sjeff		else
628219820Sjeff			return timewait_info;
629219820Sjeff	}
630219820Sjeff	return NULL;
631219820Sjeff}
632219820Sjeff
633219820Sjeffstatic struct cm_timewait_info * cm_insert_remote_qpn(struct cm_timewait_info
634219820Sjeff						      *timewait_info)
635219820Sjeff{
636219820Sjeff	struct rb_node **link = &cm.remote_qp_table.rb_node;
637219820Sjeff	struct rb_node *parent = NULL;
638219820Sjeff	struct cm_timewait_info *cur_timewait_info;
639219820Sjeff	__be64 remote_ca_guid = timewait_info->remote_ca_guid;
640219820Sjeff	__be32 remote_qpn = timewait_info->remote_qpn;
641219820Sjeff
642219820Sjeff	while (*link) {
643219820Sjeff		parent = *link;
644219820Sjeff		cur_timewait_info = rb_entry(parent, struct cm_timewait_info,
645219820Sjeff					     remote_qp_node);
646219820Sjeff		if (be32_lt(remote_qpn, cur_timewait_info->remote_qpn))
647219820Sjeff			link = &(*link)->rb_left;
648219820Sjeff		else if (be32_gt(remote_qpn, cur_timewait_info->remote_qpn))
649219820Sjeff			link = &(*link)->rb_right;
650219820Sjeff		else if (be64_lt(remote_ca_guid, cur_timewait_info->remote_ca_guid))
651219820Sjeff			link = &(*link)->rb_left;
652219820Sjeff		else if (be64_gt(remote_ca_guid, cur_timewait_info->remote_ca_guid))
653219820Sjeff			link = &(*link)->rb_right;
654219820Sjeff		else
655219820Sjeff			return cur_timewait_info;
656219820Sjeff	}
657219820Sjeff	timewait_info->inserted_remote_qp = 1;
658219820Sjeff	rb_link_node(&timewait_info->remote_qp_node, parent, link);
659219820Sjeff	rb_insert_color(&timewait_info->remote_qp_node, &cm.remote_qp_table);
660219820Sjeff	return NULL;
661219820Sjeff}
662219820Sjeff
663219820Sjeffstatic struct cm_id_private * cm_insert_remote_sidr(struct cm_id_private
664219820Sjeff						    *cm_id_priv)
665219820Sjeff{
666219820Sjeff	struct rb_node **link = &cm.remote_sidr_table.rb_node;
667219820Sjeff	struct rb_node *parent = NULL;
668219820Sjeff	struct cm_id_private *cur_cm_id_priv;
669219820Sjeff	union ib_gid *port_gid = &cm_id_priv->av.dgid;
670219820Sjeff	__be32 remote_id = cm_id_priv->id.remote_id;
671219820Sjeff
672219820Sjeff	while (*link) {
673219820Sjeff		parent = *link;
674219820Sjeff		cur_cm_id_priv = rb_entry(parent, struct cm_id_private,
675219820Sjeff					  sidr_id_node);
676219820Sjeff		if (be32_lt(remote_id, cur_cm_id_priv->id.remote_id))
677219820Sjeff			link = &(*link)->rb_left;
678219820Sjeff		else if (be32_gt(remote_id, cur_cm_id_priv->id.remote_id))
679219820Sjeff			link = &(*link)->rb_right;
680219820Sjeff		else {
681219820Sjeff			int cmp;
682219820Sjeff			cmp = memcmp(port_gid, &cur_cm_id_priv->av.dgid,
683219820Sjeff				     sizeof *port_gid);
684219820Sjeff			if (cmp < 0)
685219820Sjeff				link = &(*link)->rb_left;
686219820Sjeff			else if (cmp > 0)
687219820Sjeff				link = &(*link)->rb_right;
688219820Sjeff			else
689219820Sjeff				return cur_cm_id_priv;
690219820Sjeff		}
691219820Sjeff	}
692219820Sjeff	rb_link_node(&cm_id_priv->sidr_id_node, parent, link);
693219820Sjeff	rb_insert_color(&cm_id_priv->sidr_id_node, &cm.remote_sidr_table);
694219820Sjeff	return NULL;
695219820Sjeff}
696219820Sjeff
697219820Sjeffstatic void cm_reject_sidr_req(struct cm_id_private *cm_id_priv,
698219820Sjeff			       enum ib_cm_sidr_status status)
699219820Sjeff{
700219820Sjeff	struct ib_cm_sidr_rep_param param;
701219820Sjeff
702219820Sjeff	memset(&param, 0, sizeof param);
703219820Sjeff	param.status = status;
704219820Sjeff	ib_send_cm_sidr_rep(&cm_id_priv->id, &param);
705219820Sjeff}
706219820Sjeff
707219820Sjeffstruct ib_cm_id *ib_create_cm_id(struct ib_device *device,
708219820Sjeff				 ib_cm_handler cm_handler,
709219820Sjeff				 void *context)
710219820Sjeff{
711219820Sjeff	struct cm_id_private *cm_id_priv;
712219820Sjeff	int ret;
713219820Sjeff
714219820Sjeff	cm_id_priv = kzalloc(sizeof *cm_id_priv, GFP_KERNEL);
715219820Sjeff	if (!cm_id_priv)
716219820Sjeff		return ERR_PTR(-ENOMEM);
717219820Sjeff
718219820Sjeff	cm_id_priv->id.state = IB_CM_IDLE;
719219820Sjeff	cm_id_priv->id.device = device;
720219820Sjeff	cm_id_priv->id.cm_handler = cm_handler;
721219820Sjeff	cm_id_priv->id.context = context;
722219820Sjeff	cm_id_priv->id.remote_cm_qpn = 1;
723219820Sjeff	ret = cm_alloc_id(cm_id_priv);
724219820Sjeff	if (ret)
725219820Sjeff		goto error;
726219820Sjeff
727219820Sjeff	spin_lock_init(&cm_id_priv->lock);
728219820Sjeff	init_completion(&cm_id_priv->comp);
729219820Sjeff	INIT_LIST_HEAD(&cm_id_priv->work_list);
730219820Sjeff	atomic_set(&cm_id_priv->work_count, -1);
731219820Sjeff	atomic_set(&cm_id_priv->refcount, 1);
732219820Sjeff	return &cm_id_priv->id;
733219820Sjeff
734219820Sjefferror:
735219820Sjeff	kfree(cm_id_priv);
736219820Sjeff	return ERR_PTR(-ENOMEM);
737219820Sjeff}
738219820SjeffEXPORT_SYMBOL(ib_create_cm_id);
739219820Sjeff
740219820Sjeffstatic struct cm_work * cm_dequeue_work(struct cm_id_private *cm_id_priv)
741219820Sjeff{
742219820Sjeff	struct cm_work *work;
743219820Sjeff
744219820Sjeff	if (list_empty(&cm_id_priv->work_list))
745219820Sjeff		return NULL;
746219820Sjeff
747219820Sjeff	work = list_entry(cm_id_priv->work_list.next, struct cm_work, list);
748219820Sjeff	list_del(&work->list);
749219820Sjeff	return work;
750219820Sjeff}
751219820Sjeff
752219820Sjeffstatic void cm_free_work(struct cm_work *work)
753219820Sjeff{
754219820Sjeff	if (work->mad_recv_wc)
755219820Sjeff		ib_free_recv_mad(work->mad_recv_wc);
756219820Sjeff	kfree(work);
757219820Sjeff}
758219820Sjeff
759219820Sjeffstatic inline int cm_convert_to_ms(int iba_time)
760219820Sjeff{
761219820Sjeff	/* approximate conversion to ms from 4.096us x 2^iba_time */
762219820Sjeff	return 1 << max(iba_time - 8, 0);
763219820Sjeff}
764219820Sjeff
765219820Sjeff/*
766219820Sjeff * calculate: 4.096x2^ack_timeout = 4.096x2^ack_delay + 2x4.096x2^life_time
767219820Sjeff * Because of how ack_timeout is stored, adding one doubles the timeout.
768219820Sjeff * To avoid large timeouts, select the max(ack_delay, life_time + 1), and
769219820Sjeff * increment it (round up) only if the other is within 50%.
770219820Sjeff */
771219820Sjeffstatic u8 cm_ack_timeout(u8 ca_ack_delay, u8 packet_life_time)
772219820Sjeff{
773219820Sjeff	int ack_timeout = packet_life_time + 1;
774219820Sjeff
775219820Sjeff	if (ack_timeout >= ca_ack_delay)
776219820Sjeff		ack_timeout += (ca_ack_delay >= (ack_timeout - 1));
777219820Sjeff	else
778219820Sjeff		ack_timeout = ca_ack_delay +
779219820Sjeff			      (ack_timeout >= (ca_ack_delay - 1));
780219820Sjeff
781219820Sjeff	return min(31, ack_timeout);
782219820Sjeff}
783219820Sjeff
784219820Sjeffstatic void cm_cleanup_timewait(struct cm_timewait_info *timewait_info)
785219820Sjeff{
786219820Sjeff	if (timewait_info->inserted_remote_id) {
787219820Sjeff		rb_erase(&timewait_info->remote_id_node, &cm.remote_id_table);
788219820Sjeff		timewait_info->inserted_remote_id = 0;
789219820Sjeff	}
790219820Sjeff
791219820Sjeff	if (timewait_info->inserted_remote_qp) {
792219820Sjeff		rb_erase(&timewait_info->remote_qp_node, &cm.remote_qp_table);
793219820Sjeff		timewait_info->inserted_remote_qp = 0;
794219820Sjeff	}
795219820Sjeff}
796219820Sjeff
797219820Sjeffstatic struct cm_timewait_info * cm_create_timewait_info(__be32 local_id)
798219820Sjeff{
799219820Sjeff	struct cm_timewait_info *timewait_info;
800219820Sjeff
801219820Sjeff	timewait_info = kzalloc(sizeof *timewait_info, GFP_KERNEL);
802219820Sjeff	if (!timewait_info)
803219820Sjeff		return ERR_PTR(-ENOMEM);
804219820Sjeff
805219820Sjeff	timewait_info->work.local_id = local_id;
806219820Sjeff	INIT_DELAYED_WORK(&timewait_info->work.work, cm_work_handler);
807219820Sjeff	timewait_info->work.cm_event.event = IB_CM_TIMEWAIT_EXIT;
808219820Sjeff	return timewait_info;
809219820Sjeff}
810219820Sjeff
811219820Sjeffstatic void cm_enter_timewait(struct cm_id_private *cm_id_priv)
812219820Sjeff{
813219820Sjeff	int wait_time;
814219820Sjeff	unsigned long flags;
815219820Sjeff
816219820Sjeff	spin_lock_irqsave(&cm.lock, flags);
817219820Sjeff	cm_cleanup_timewait(cm_id_priv->timewait_info);
818219820Sjeff	list_add_tail(&cm_id_priv->timewait_info->list, &cm.timewait_list);
819219820Sjeff	spin_unlock_irqrestore(&cm.lock, flags);
820219820Sjeff
821219820Sjeff	/*
822219820Sjeff	 * The cm_id could be destroyed by the user before we exit timewait.
823219820Sjeff	 * To protect against this, we search for the cm_id after exiting
824219820Sjeff	 * timewait before notifying the user that we've exited timewait.
825219820Sjeff	 */
826219820Sjeff	cm_id_priv->id.state = IB_CM_TIMEWAIT;
827219820Sjeff	wait_time = cm_convert_to_ms(cm_id_priv->av.timeout);
828219820Sjeff	queue_delayed_work(cm.wq, &cm_id_priv->timewait_info->work.work,
829219820Sjeff			   msecs_to_jiffies(wait_time));
830219820Sjeff	cm_id_priv->timewait_info = NULL;
831219820Sjeff}
832219820Sjeff
833219820Sjeffstatic void cm_reset_to_idle(struct cm_id_private *cm_id_priv)
834219820Sjeff{
835219820Sjeff	unsigned long flags;
836219820Sjeff
837219820Sjeff	cm_id_priv->id.state = IB_CM_IDLE;
838219820Sjeff	if (cm_id_priv->timewait_info) {
839219820Sjeff		spin_lock_irqsave(&cm.lock, flags);
840219820Sjeff		cm_cleanup_timewait(cm_id_priv->timewait_info);
841219820Sjeff		spin_unlock_irqrestore(&cm.lock, flags);
842219820Sjeff		kfree(cm_id_priv->timewait_info);
843219820Sjeff		cm_id_priv->timewait_info = NULL;
844219820Sjeff	}
845219820Sjeff}
846219820Sjeff
847219820Sjeffstatic void cm_destroy_id(struct ib_cm_id *cm_id, int err)
848219820Sjeff{
849219820Sjeff	struct cm_id_private *cm_id_priv;
850219820Sjeff	struct cm_work *work;
851219820Sjeff
852219820Sjeff	cm_id_priv = container_of(cm_id, struct cm_id_private, id);
853219820Sjeffretest:
854219820Sjeff	spin_lock_irq(&cm_id_priv->lock);
855219820Sjeff	switch (cm_id->state) {
856219820Sjeff	case IB_CM_LISTEN:
857219820Sjeff		cm_id->state = IB_CM_IDLE;
858219820Sjeff		spin_unlock_irq(&cm_id_priv->lock);
859219820Sjeff		spin_lock_irq(&cm.lock);
860219820Sjeff		rb_erase(&cm_id_priv->service_node, &cm.listen_service_table);
861219820Sjeff		spin_unlock_irq(&cm.lock);
862219820Sjeff		break;
863219820Sjeff	case IB_CM_SIDR_REQ_SENT:
864219820Sjeff		cm_id->state = IB_CM_IDLE;
865219820Sjeff		ib_cancel_mad(cm_id_priv->av.port->mad_agent, cm_id_priv->msg);
866219820Sjeff		spin_unlock_irq(&cm_id_priv->lock);
867219820Sjeff		break;
868219820Sjeff	case IB_CM_SIDR_REQ_RCVD:
869219820Sjeff		spin_unlock_irq(&cm_id_priv->lock);
870219820Sjeff		cm_reject_sidr_req(cm_id_priv, IB_SIDR_REJECT);
871219820Sjeff		break;
872219820Sjeff	case IB_CM_REQ_SENT:
873219820Sjeff		ib_cancel_mad(cm_id_priv->av.port->mad_agent, cm_id_priv->msg);
874219820Sjeff		spin_unlock_irq(&cm_id_priv->lock);
875219820Sjeff		ib_send_cm_rej(cm_id, IB_CM_REJ_TIMEOUT,
876219820Sjeff			       &cm_id_priv->id.device->node_guid,
877219820Sjeff			       sizeof cm_id_priv->id.device->node_guid,
878219820Sjeff			       NULL, 0);
879219820Sjeff		break;
880219820Sjeff	case IB_CM_REQ_RCVD:
881219820Sjeff		if (err == -ENOMEM) {
882219820Sjeff			/* Do not reject to allow future retries. */
883219820Sjeff			cm_reset_to_idle(cm_id_priv);
884219820Sjeff			spin_unlock_irq(&cm_id_priv->lock);
885219820Sjeff		} else {
886219820Sjeff			spin_unlock_irq(&cm_id_priv->lock);
887219820Sjeff			ib_send_cm_rej(cm_id, IB_CM_REJ_CONSUMER_DEFINED,
888219820Sjeff				       NULL, 0, NULL, 0);
889219820Sjeff		}
890219820Sjeff		break;
891219820Sjeff	case IB_CM_MRA_REQ_RCVD:
892219820Sjeff	case IB_CM_REP_SENT:
893219820Sjeff	case IB_CM_MRA_REP_RCVD:
894219820Sjeff		ib_cancel_mad(cm_id_priv->av.port->mad_agent, cm_id_priv->msg);
895219820Sjeff		/* Fall through */
896219820Sjeff	case IB_CM_MRA_REQ_SENT:
897219820Sjeff	case IB_CM_REP_RCVD:
898219820Sjeff	case IB_CM_MRA_REP_SENT:
899219820Sjeff		spin_unlock_irq(&cm_id_priv->lock);
900219820Sjeff		ib_send_cm_rej(cm_id, IB_CM_REJ_CONSUMER_DEFINED,
901219820Sjeff			       NULL, 0, NULL, 0);
902219820Sjeff		break;
903219820Sjeff	case IB_CM_ESTABLISHED:
904219820Sjeff		spin_unlock_irq(&cm_id_priv->lock);
905219820Sjeff		ib_send_cm_dreq(cm_id, NULL, 0);
906219820Sjeff		goto retest;
907219820Sjeff	case IB_CM_DREQ_SENT:
908219820Sjeff		ib_cancel_mad(cm_id_priv->av.port->mad_agent, cm_id_priv->msg);
909219820Sjeff		cm_enter_timewait(cm_id_priv);
910219820Sjeff		spin_unlock_irq(&cm_id_priv->lock);
911219820Sjeff		break;
912219820Sjeff	case IB_CM_DREQ_RCVD:
913219820Sjeff		spin_unlock_irq(&cm_id_priv->lock);
914219820Sjeff		ib_send_cm_drep(cm_id, NULL, 0);
915219820Sjeff		break;
916219820Sjeff	default:
917219820Sjeff		spin_unlock_irq(&cm_id_priv->lock);
918219820Sjeff		break;
919219820Sjeff	}
920219820Sjeff
921219820Sjeff	cm_free_id(cm_id->local_id);
922219820Sjeff	cm_deref_id(cm_id_priv);
923219820Sjeff	wait_for_completion(&cm_id_priv->comp);
924219820Sjeff	while ((work = cm_dequeue_work(cm_id_priv)) != NULL)
925219820Sjeff		cm_free_work(work);
926219820Sjeff	kfree(cm_id_priv->compare_data);
927219820Sjeff	kfree(cm_id_priv->private_data);
928219820Sjeff	kfree(cm_id_priv);
929219820Sjeff}
930219820Sjeff
931219820Sjeffvoid ib_destroy_cm_id(struct ib_cm_id *cm_id)
932219820Sjeff{
933219820Sjeff	cm_destroy_id(cm_id, 0);
934219820Sjeff}
935219820SjeffEXPORT_SYMBOL(ib_destroy_cm_id);
936219820Sjeff
937219820Sjeffint ib_cm_listen(struct ib_cm_id *cm_id, __be64 service_id, __be64 service_mask,
938219820Sjeff		 struct ib_cm_compare_data *compare_data)
939219820Sjeff{
940219820Sjeff	struct cm_id_private *cm_id_priv, *cur_cm_id_priv;
941219820Sjeff	unsigned long flags;
942219820Sjeff	int ret = 0;
943219820Sjeff
944219820Sjeff	service_mask = service_mask ? service_mask : ~cpu_to_be64(0);
945219820Sjeff	service_id &= service_mask;
946219820Sjeff	if ((service_id & IB_SERVICE_ID_AGN_MASK) == IB_CM_ASSIGN_SERVICE_ID &&
947219820Sjeff	    (service_id != IB_CM_ASSIGN_SERVICE_ID))
948219820Sjeff		return -EINVAL;
949219820Sjeff
950219820Sjeff	cm_id_priv = container_of(cm_id, struct cm_id_private, id);
951219820Sjeff	if (cm_id->state != IB_CM_IDLE)
952219820Sjeff		return -EINVAL;
953219820Sjeff
954219820Sjeff	if (compare_data) {
955219820Sjeff		cm_id_priv->compare_data = kzalloc(sizeof *compare_data,
956219820Sjeff						   GFP_KERNEL);
957219820Sjeff		if (!cm_id_priv->compare_data)
958219820Sjeff			return -ENOMEM;
959219820Sjeff		cm_mask_copy(cm_id_priv->compare_data->data,
960219820Sjeff			     compare_data->data, compare_data->mask);
961219820Sjeff		memcpy(cm_id_priv->compare_data->mask, compare_data->mask,
962219820Sjeff		       IB_CM_COMPARE_SIZE);
963219820Sjeff	}
964219820Sjeff
965219820Sjeff	cm_id->state = IB_CM_LISTEN;
966219820Sjeff
967219820Sjeff	spin_lock_irqsave(&cm.lock, flags);
968219820Sjeff	if (service_id == IB_CM_ASSIGN_SERVICE_ID) {
969219820Sjeff		cm_id->service_id = cpu_to_be64(cm.listen_service_id++);
970219820Sjeff		cm_id->service_mask = ~cpu_to_be64(0);
971219820Sjeff	} else {
972219820Sjeff		cm_id->service_id = service_id;
973219820Sjeff		cm_id->service_mask = service_mask;
974219820Sjeff	}
975219820Sjeff	cur_cm_id_priv = cm_insert_listen(cm_id_priv);
976219820Sjeff	spin_unlock_irqrestore(&cm.lock, flags);
977219820Sjeff
978219820Sjeff	if (cur_cm_id_priv) {
979219820Sjeff		cm_id->state = IB_CM_IDLE;
980219820Sjeff		kfree(cm_id_priv->compare_data);
981219820Sjeff		cm_id_priv->compare_data = NULL;
982219820Sjeff		ret = -EBUSY;
983219820Sjeff	}
984219820Sjeff	return ret;
985219820Sjeff}
986219820SjeffEXPORT_SYMBOL(ib_cm_listen);
987219820Sjeff
988219820Sjeffstatic __be64 cm_form_tid(struct cm_id_private *cm_id_priv,
989219820Sjeff			  enum cm_msg_sequence msg_seq)
990219820Sjeff{
991219820Sjeff	u64 hi_tid, low_tid;
992219820Sjeff
993219820Sjeff	hi_tid   = ((u64) cm_id_priv->av.port->mad_agent->hi_tid) << 32;
994219820Sjeff	low_tid  = (u64) ((__force u32)cm_id_priv->id.local_id |
995219820Sjeff			  (msg_seq << 30));
996219820Sjeff	return cpu_to_be64(hi_tid | low_tid);
997219820Sjeff}
998219820Sjeff
999219820Sjeffstatic void cm_format_mad_hdr(struct ib_mad_hdr *hdr,
1000219820Sjeff			      __be16 attr_id, __be64 tid)
1001219820Sjeff{
1002219820Sjeff	hdr->base_version  = IB_MGMT_BASE_VERSION;
1003219820Sjeff	hdr->mgmt_class	   = IB_MGMT_CLASS_CM;
1004219820Sjeff	hdr->class_version = IB_CM_CLASS_VERSION;
1005219820Sjeff	hdr->method	   = IB_MGMT_METHOD_SEND;
1006219820Sjeff	hdr->attr_id	   = attr_id;
1007219820Sjeff	hdr->tid	   = tid;
1008219820Sjeff}
1009219820Sjeff
1010219820Sjeffstatic void cm_format_req(struct cm_req_msg *req_msg,
1011219820Sjeff			  struct cm_id_private *cm_id_priv,
1012219820Sjeff			  struct ib_cm_req_param *param)
1013219820Sjeff{
1014219820Sjeff	struct ib_sa_path_rec *pri_path = param->primary_path;
1015219820Sjeff	struct ib_sa_path_rec *alt_path = param->alternate_path;
1016219820Sjeff
1017219820Sjeff	cm_format_mad_hdr(&req_msg->hdr, CM_REQ_ATTR_ID,
1018219820Sjeff			  cm_form_tid(cm_id_priv, CM_MSG_SEQUENCE_REQ));
1019219820Sjeff
1020219820Sjeff	req_msg->local_comm_id = cm_id_priv->id.local_id;
1021219820Sjeff	req_msg->service_id = param->service_id;
1022219820Sjeff	req_msg->local_ca_guid = cm_id_priv->id.device->node_guid;
1023219820Sjeff	cm_req_set_local_qpn(req_msg, cpu_to_be32(param->qp_num));
1024219820Sjeff	cm_req_set_resp_res(req_msg, param->responder_resources);
1025219820Sjeff	cm_req_set_init_depth(req_msg, param->initiator_depth);
1026219820Sjeff	cm_req_set_remote_resp_timeout(req_msg,
1027219820Sjeff				       param->remote_cm_response_timeout);
1028219820Sjeff       if (param->remote_cm_response_timeout > (u8) max_timeout) {
1029219820Sjeff               printk(KERN_WARNING PFX "req remote_cm_response_timeout %d > "
1030219820Sjeff                      "%d, decreasing\n", param->remote_cm_response_timeout,
1031219820Sjeff                      max_timeout);
1032219820Sjeff               cm_req_set_remote_resp_timeout(req_msg, (u8) max_timeout);
1033219820Sjeff       }
1034219820Sjeff	cm_req_set_qp_type(req_msg, param->qp_type);
1035219820Sjeff	cm_req_set_flow_ctrl(req_msg, param->flow_control);
1036219820Sjeff	cm_req_set_starting_psn(req_msg, cpu_to_be32(param->starting_psn));
1037219820Sjeff	cm_req_set_local_resp_timeout(req_msg,
1038219820Sjeff				      param->local_cm_response_timeout);
1039219820Sjeff       if (param->local_cm_response_timeout > (u8) max_timeout) {
1040219820Sjeff               printk(KERN_WARNING PFX "req local_cm_response_timeout %d > "
1041219820Sjeff                      "%d, decreasing\n", param->local_cm_response_timeout,
1042219820Sjeff                      max_timeout);
1043219820Sjeff               cm_req_set_local_resp_timeout(req_msg, (u8) max_timeout);
1044219820Sjeff       }
1045219820Sjeff	cm_req_set_retry_count(req_msg, param->retry_count);
1046219820Sjeff	req_msg->pkey = param->primary_path->pkey;
1047219820Sjeff	cm_req_set_path_mtu(req_msg, param->primary_path->mtu);
1048219820Sjeff	cm_req_set_rnr_retry_count(req_msg, param->rnr_retry_count);
1049219820Sjeff	cm_req_set_max_cm_retries(req_msg, param->max_cm_retries);
1050219820Sjeff	cm_req_set_srq(req_msg, param->srq);
1051219820Sjeff
1052219820Sjeff	if (pri_path->hop_limit <= 1) {
1053219820Sjeff		req_msg->primary_local_lid = pri_path->slid;
1054219820Sjeff		req_msg->primary_remote_lid = pri_path->dlid;
1055219820Sjeff	} else {
1056219820Sjeff		/* Work-around until there's a way to obtain remote LID info */
1057219820Sjeff		req_msg->primary_local_lid = IB_LID_PERMISSIVE;
1058219820Sjeff		req_msg->primary_remote_lid = IB_LID_PERMISSIVE;
1059219820Sjeff	}
1060219820Sjeff	req_msg->primary_local_gid = pri_path->sgid;
1061219820Sjeff	req_msg->primary_remote_gid = pri_path->dgid;
1062219820Sjeff	cm_req_set_primary_flow_label(req_msg, pri_path->flow_label);
1063219820Sjeff	cm_req_set_primary_packet_rate(req_msg, pri_path->rate);
1064219820Sjeff	req_msg->primary_traffic_class = pri_path->traffic_class;
1065219820Sjeff	req_msg->primary_hop_limit = pri_path->hop_limit;
1066219820Sjeff	cm_req_set_primary_sl(req_msg, pri_path->sl);
1067219820Sjeff	cm_req_set_primary_subnet_local(req_msg, (pri_path->hop_limit <= 1));
1068219820Sjeff	cm_req_set_primary_local_ack_timeout(req_msg,
1069219820Sjeff		cm_ack_timeout(cm_id_priv->av.port->cm_dev->ack_delay,
1070219820Sjeff			       pri_path->packet_life_time));
1071219820Sjeff
1072219820Sjeff	if (alt_path) {
1073219820Sjeff		if (alt_path->hop_limit <= 1) {
1074219820Sjeff			req_msg->alt_local_lid = alt_path->slid;
1075219820Sjeff			req_msg->alt_remote_lid = alt_path->dlid;
1076219820Sjeff		} else {
1077219820Sjeff			req_msg->alt_local_lid = IB_LID_PERMISSIVE;
1078219820Sjeff			req_msg->alt_remote_lid = IB_LID_PERMISSIVE;
1079219820Sjeff		}
1080219820Sjeff		req_msg->alt_local_gid = alt_path->sgid;
1081219820Sjeff		req_msg->alt_remote_gid = alt_path->dgid;
1082219820Sjeff		cm_req_set_alt_flow_label(req_msg,
1083219820Sjeff					  alt_path->flow_label);
1084219820Sjeff		cm_req_set_alt_packet_rate(req_msg, alt_path->rate);
1085219820Sjeff		req_msg->alt_traffic_class = alt_path->traffic_class;
1086219820Sjeff		req_msg->alt_hop_limit = alt_path->hop_limit;
1087219820Sjeff		cm_req_set_alt_sl(req_msg, alt_path->sl);
1088219820Sjeff		cm_req_set_alt_subnet_local(req_msg, (alt_path->hop_limit <= 1));
1089219820Sjeff		cm_req_set_alt_local_ack_timeout(req_msg,
1090219820Sjeff			cm_ack_timeout(cm_id_priv->av.port->cm_dev->ack_delay,
1091219820Sjeff				       alt_path->packet_life_time));
1092219820Sjeff	}
1093219820Sjeff
1094219820Sjeff	if (param->private_data && param->private_data_len)
1095219820Sjeff		memcpy(req_msg->private_data, param->private_data,
1096219820Sjeff		       param->private_data_len);
1097219820Sjeff}
1098219820Sjeff
1099219820Sjeffstatic int cm_validate_req_param(struct ib_cm_req_param *param)
1100219820Sjeff{
1101219820Sjeff	/* peer-to-peer not supported */
1102219820Sjeff	if (param->peer_to_peer)
1103219820Sjeff		return -EINVAL;
1104219820Sjeff
1105219820Sjeff	if (!param->primary_path)
1106219820Sjeff		return -EINVAL;
1107219820Sjeff
1108219820Sjeff	if (param->qp_type != IB_QPT_RC && param->qp_type != IB_QPT_UC)
1109219820Sjeff		return -EINVAL;
1110219820Sjeff
1111219820Sjeff	if (param->private_data &&
1112219820Sjeff	    param->private_data_len > IB_CM_REQ_PRIVATE_DATA_SIZE)
1113219820Sjeff		return -EINVAL;
1114219820Sjeff
1115219820Sjeff	if (param->alternate_path &&
1116219820Sjeff	    (param->alternate_path->pkey != param->primary_path->pkey ||
1117219820Sjeff	     param->alternate_path->mtu != param->primary_path->mtu))
1118219820Sjeff		return -EINVAL;
1119219820Sjeff
1120219820Sjeff	return 0;
1121219820Sjeff}
1122219820Sjeff
1123219820Sjeffint ib_send_cm_req(struct ib_cm_id *cm_id,
1124219820Sjeff		   struct ib_cm_req_param *param)
1125219820Sjeff{
1126219820Sjeff	struct cm_id_private *cm_id_priv;
1127219820Sjeff	struct cm_req_msg *req_msg;
1128219820Sjeff	unsigned long flags;
1129219820Sjeff	int ret;
1130219820Sjeff
1131219820Sjeff	ret = cm_validate_req_param(param);
1132219820Sjeff	if (ret)
1133219820Sjeff		return ret;
1134219820Sjeff
1135219820Sjeff	/* Verify that we're not in timewait. */
1136219820Sjeff	cm_id_priv = container_of(cm_id, struct cm_id_private, id);
1137219820Sjeff	spin_lock_irqsave(&cm_id_priv->lock, flags);
1138219820Sjeff	if (cm_id->state != IB_CM_IDLE) {
1139219820Sjeff		spin_unlock_irqrestore(&cm_id_priv->lock, flags);
1140219820Sjeff		ret = -EINVAL;
1141219820Sjeff		goto out;
1142219820Sjeff	}
1143219820Sjeff	spin_unlock_irqrestore(&cm_id_priv->lock, flags);
1144219820Sjeff
1145219820Sjeff	cm_id_priv->timewait_info = cm_create_timewait_info(cm_id_priv->
1146219820Sjeff							    id.local_id);
1147219820Sjeff	if (IS_ERR(cm_id_priv->timewait_info)) {
1148219820Sjeff		ret = PTR_ERR(cm_id_priv->timewait_info);
1149219820Sjeff		goto out;
1150219820Sjeff	}
1151219820Sjeff
1152219820Sjeff	ret = cm_init_av_by_path(param->primary_path, &cm_id_priv->av);
1153219820Sjeff	if (ret)
1154219820Sjeff		goto error1;
1155219820Sjeff	if (param->alternate_path) {
1156219820Sjeff		ret = cm_init_av_by_path(param->alternate_path,
1157219820Sjeff					 &cm_id_priv->alt_av);
1158219820Sjeff		if (ret)
1159219820Sjeff			goto error1;
1160219820Sjeff	}
1161219820Sjeff	cm_id->service_id = param->service_id;
1162219820Sjeff	cm_id->service_mask = ~cpu_to_be64(0);
1163219820Sjeff	cm_id_priv->timeout_ms = cm_convert_to_ms(
1164219820Sjeff				    param->primary_path->packet_life_time) * 2 +
1165219820Sjeff				 cm_convert_to_ms(
1166219820Sjeff				    param->remote_cm_response_timeout);
1167219820Sjeff       if (cm_id_priv->timeout_ms > cm_convert_to_ms(max_timeout)) {
1168219820Sjeff               printk(KERN_WARNING PFX "req timeout_ms %d > %d, decreasing\n",
1169219820Sjeff                      cm_id_priv->timeout_ms, cm_convert_to_ms(max_timeout));
1170219820Sjeff               cm_id_priv->timeout_ms = cm_convert_to_ms(max_timeout);
1171219820Sjeff       }
1172219820Sjeff	cm_id_priv->max_cm_retries = param->max_cm_retries;
1173219820Sjeff	cm_id_priv->initiator_depth = param->initiator_depth;
1174219820Sjeff	cm_id_priv->responder_resources = param->responder_resources;
1175219820Sjeff	cm_id_priv->retry_count = param->retry_count;
1176219820Sjeff	cm_id_priv->path_mtu = param->primary_path->mtu;
1177219820Sjeff	cm_id_priv->pkey = param->primary_path->pkey;
1178219820Sjeff	cm_id_priv->qp_type = param->qp_type;
1179219820Sjeff
1180219820Sjeff	ret = cm_alloc_msg(cm_id_priv, &cm_id_priv->msg);
1181219820Sjeff	if (ret)
1182219820Sjeff		goto error1;
1183219820Sjeff
1184219820Sjeff	req_msg = (struct cm_req_msg *) cm_id_priv->msg->mad;
1185219820Sjeff	cm_format_req(req_msg, cm_id_priv, param);
1186219820Sjeff	cm_id_priv->tid = req_msg->hdr.tid;
1187219820Sjeff	cm_id_priv->msg->timeout_ms = cm_id_priv->timeout_ms;
1188219820Sjeff	cm_id_priv->msg->context[1] = (void *) (unsigned long) IB_CM_REQ_SENT;
1189219820Sjeff
1190219820Sjeff	cm_id_priv->local_qpn = cm_req_get_local_qpn(req_msg);
1191219820Sjeff	cm_id_priv->rq_psn = cm_req_get_starting_psn(req_msg);
1192219820Sjeff
1193219820Sjeff	spin_lock_irqsave(&cm_id_priv->lock, flags);
1194219820Sjeff	ret = ib_post_send_mad(cm_id_priv->msg, NULL);
1195219820Sjeff	if (ret) {
1196219820Sjeff		spin_unlock_irqrestore(&cm_id_priv->lock, flags);
1197219820Sjeff		goto error2;
1198219820Sjeff	}
1199219820Sjeff	BUG_ON(cm_id->state != IB_CM_IDLE);
1200219820Sjeff	cm_id->state = IB_CM_REQ_SENT;
1201219820Sjeff	spin_unlock_irqrestore(&cm_id_priv->lock, flags);
1202219820Sjeff	return 0;
1203219820Sjeff
1204219820Sjefferror2:	cm_free_msg(cm_id_priv->msg);
1205219820Sjefferror1:	kfree(cm_id_priv->timewait_info);
1206219820Sjeffout:	return ret;
1207219820Sjeff}
1208219820SjeffEXPORT_SYMBOL(ib_send_cm_req);
1209219820Sjeff
1210219820Sjeffstatic int cm_issue_rej(struct cm_port *port,
1211219820Sjeff			struct ib_mad_recv_wc *mad_recv_wc,
1212219820Sjeff			enum ib_cm_rej_reason reason,
1213219820Sjeff			enum cm_msg_response msg_rejected,
1214219820Sjeff			void *ari, u8 ari_length)
1215219820Sjeff{
1216219820Sjeff	struct ib_mad_send_buf *msg = NULL;
1217219820Sjeff	struct cm_rej_msg *rej_msg, *rcv_msg;
1218219820Sjeff	int ret;
1219219820Sjeff
1220219820Sjeff	ret = cm_alloc_response_msg(port, mad_recv_wc, &msg);
1221219820Sjeff	if (ret)
1222219820Sjeff		return ret;
1223219820Sjeff
1224219820Sjeff	/* We just need common CM header information.  Cast to any message. */
1225219820Sjeff	rcv_msg = (struct cm_rej_msg *) mad_recv_wc->recv_buf.mad;
1226219820Sjeff	rej_msg = (struct cm_rej_msg *) msg->mad;
1227219820Sjeff
1228219820Sjeff	cm_format_mad_hdr(&rej_msg->hdr, CM_REJ_ATTR_ID, rcv_msg->hdr.tid);
1229219820Sjeff	rej_msg->remote_comm_id = rcv_msg->local_comm_id;
1230219820Sjeff	rej_msg->local_comm_id = rcv_msg->remote_comm_id;
1231219820Sjeff	cm_rej_set_msg_rejected(rej_msg, msg_rejected);
1232219820Sjeff	rej_msg->reason = cpu_to_be16(reason);
1233219820Sjeff
1234219820Sjeff	if (ari && ari_length) {
1235219820Sjeff		cm_rej_set_reject_info_len(rej_msg, ari_length);
1236219820Sjeff		memcpy(rej_msg->ari, ari, ari_length);
1237219820Sjeff	}
1238219820Sjeff
1239219820Sjeff	ret = ib_post_send_mad(msg, NULL);
1240219820Sjeff	if (ret)
1241219820Sjeff		cm_free_msg(msg);
1242219820Sjeff
1243219820Sjeff	return ret;
1244219820Sjeff}
1245219820Sjeff
1246219820Sjeffstatic inline int cm_is_active_peer(__be64 local_ca_guid, __be64 remote_ca_guid,
1247219820Sjeff				    __be32 local_qpn, __be32 remote_qpn)
1248219820Sjeff{
1249219820Sjeff	return (be64_to_cpu(local_ca_guid) > be64_to_cpu(remote_ca_guid) ||
1250219820Sjeff		((local_ca_guid == remote_ca_guid) &&
1251219820Sjeff		 (be32_to_cpu(local_qpn) > be32_to_cpu(remote_qpn))));
1252219820Sjeff}
1253219820Sjeff
1254219820Sjeffstatic void cm_format_paths_from_req(struct cm_req_msg *req_msg,
1255219820Sjeff					    struct ib_sa_path_rec *primary_path,
1256219820Sjeff					    struct ib_sa_path_rec *alt_path)
1257219820Sjeff{
1258219820Sjeff	memset(primary_path, 0, sizeof *primary_path);
1259219820Sjeff	primary_path->dgid = req_msg->primary_local_gid;
1260219820Sjeff	primary_path->sgid = req_msg->primary_remote_gid;
1261219820Sjeff	primary_path->dlid = req_msg->primary_local_lid;
1262219820Sjeff	primary_path->slid = req_msg->primary_remote_lid;
1263219820Sjeff	primary_path->flow_label = cm_req_get_primary_flow_label(req_msg);
1264219820Sjeff	primary_path->hop_limit = req_msg->primary_hop_limit;
1265219820Sjeff	primary_path->traffic_class = req_msg->primary_traffic_class;
1266219820Sjeff	primary_path->reversible = 1;
1267219820Sjeff	primary_path->pkey = req_msg->pkey;
1268219820Sjeff	primary_path->sl = cm_req_get_primary_sl(req_msg);
1269219820Sjeff	primary_path->mtu_selector = IB_SA_EQ;
1270219820Sjeff	primary_path->mtu = cm_req_get_path_mtu(req_msg);
1271219820Sjeff	primary_path->rate_selector = IB_SA_EQ;
1272219820Sjeff	primary_path->rate = cm_req_get_primary_packet_rate(req_msg);
1273219820Sjeff	primary_path->packet_life_time_selector = IB_SA_EQ;
1274219820Sjeff	primary_path->packet_life_time =
1275219820Sjeff		cm_req_get_primary_local_ack_timeout(req_msg);
1276219820Sjeff	primary_path->packet_life_time -= (primary_path->packet_life_time > 0);
1277219820Sjeff
1278219820Sjeff	if (req_msg->alt_local_lid) {
1279219820Sjeff		memset(alt_path, 0, sizeof *alt_path);
1280219820Sjeff		alt_path->dgid = req_msg->alt_local_gid;
1281219820Sjeff		alt_path->sgid = req_msg->alt_remote_gid;
1282219820Sjeff		alt_path->dlid = req_msg->alt_local_lid;
1283219820Sjeff		alt_path->slid = req_msg->alt_remote_lid;
1284219820Sjeff		alt_path->flow_label = cm_req_get_alt_flow_label(req_msg);
1285219820Sjeff		alt_path->hop_limit = req_msg->alt_hop_limit;
1286219820Sjeff		alt_path->traffic_class = req_msg->alt_traffic_class;
1287219820Sjeff		alt_path->reversible = 1;
1288219820Sjeff		alt_path->pkey = req_msg->pkey;
1289219820Sjeff		alt_path->sl = cm_req_get_alt_sl(req_msg);
1290219820Sjeff		alt_path->mtu_selector = IB_SA_EQ;
1291219820Sjeff		alt_path->mtu = cm_req_get_path_mtu(req_msg);
1292219820Sjeff		alt_path->rate_selector = IB_SA_EQ;
1293219820Sjeff		alt_path->rate = cm_req_get_alt_packet_rate(req_msg);
1294219820Sjeff		alt_path->packet_life_time_selector = IB_SA_EQ;
1295219820Sjeff		alt_path->packet_life_time =
1296219820Sjeff			cm_req_get_alt_local_ack_timeout(req_msg);
1297219820Sjeff		alt_path->packet_life_time -= (alt_path->packet_life_time > 0);
1298219820Sjeff	}
1299219820Sjeff}
1300219820Sjeff
1301219820Sjeffstatic void cm_format_req_event(struct cm_work *work,
1302219820Sjeff				struct cm_id_private *cm_id_priv,
1303219820Sjeff				struct ib_cm_id *listen_id)
1304219820Sjeff{
1305219820Sjeff	struct cm_req_msg *req_msg;
1306219820Sjeff	struct ib_cm_req_event_param *param;
1307219820Sjeff
1308219820Sjeff	req_msg = (struct cm_req_msg *)work->mad_recv_wc->recv_buf.mad;
1309219820Sjeff	param = &work->cm_event.param.req_rcvd;
1310219820Sjeff	param->listen_id = listen_id;
1311219820Sjeff	param->port = cm_id_priv->av.port->port_num;
1312219820Sjeff	param->primary_path = &work->path[0];
1313219820Sjeff	if (req_msg->alt_local_lid)
1314219820Sjeff		param->alternate_path = &work->path[1];
1315219820Sjeff	else
1316219820Sjeff		param->alternate_path = NULL;
1317219820Sjeff	param->remote_ca_guid = req_msg->local_ca_guid;
1318219820Sjeff	param->remote_qkey = be32_to_cpu(req_msg->local_qkey);
1319219820Sjeff	param->remote_qpn = be32_to_cpu(cm_req_get_local_qpn(req_msg));
1320219820Sjeff	param->qp_type = cm_req_get_qp_type(req_msg);
1321219820Sjeff	param->starting_psn = be32_to_cpu(cm_req_get_starting_psn(req_msg));
1322219820Sjeff	param->responder_resources = cm_req_get_init_depth(req_msg);
1323219820Sjeff	param->initiator_depth = cm_req_get_resp_res(req_msg);
1324219820Sjeff	param->local_cm_response_timeout =
1325219820Sjeff					cm_req_get_remote_resp_timeout(req_msg);
1326219820Sjeff	param->flow_control = cm_req_get_flow_ctrl(req_msg);
1327219820Sjeff	param->remote_cm_response_timeout =
1328219820Sjeff					cm_req_get_local_resp_timeout(req_msg);
1329219820Sjeff	param->retry_count = cm_req_get_retry_count(req_msg);
1330219820Sjeff	param->rnr_retry_count = cm_req_get_rnr_retry_count(req_msg);
1331219820Sjeff	param->srq = cm_req_get_srq(req_msg);
1332219820Sjeff	work->cm_event.private_data = &req_msg->private_data;
1333219820Sjeff}
1334219820Sjeff
1335219820Sjeffstatic void cm_process_work(struct cm_id_private *cm_id_priv,
1336219820Sjeff			    struct cm_work *work)
1337219820Sjeff{
1338219820Sjeff	int ret;
1339219820Sjeff
1340219820Sjeff	/* We will typically only have the current event to report. */
1341219820Sjeff	ret = cm_id_priv->id.cm_handler(&cm_id_priv->id, &work->cm_event);
1342219820Sjeff	cm_free_work(work);
1343219820Sjeff
1344219820Sjeff	while (!ret && !atomic_add_negative(-1, &cm_id_priv->work_count)) {
1345219820Sjeff		spin_lock_irq(&cm_id_priv->lock);
1346219820Sjeff		work = cm_dequeue_work(cm_id_priv);
1347219820Sjeff		spin_unlock_irq(&cm_id_priv->lock);
1348219820Sjeff		BUG_ON(!work);
1349219820Sjeff		ret = cm_id_priv->id.cm_handler(&cm_id_priv->id,
1350219820Sjeff						&work->cm_event);
1351219820Sjeff		cm_free_work(work);
1352219820Sjeff	}
1353219820Sjeff	cm_deref_id(cm_id_priv);
1354219820Sjeff	if (ret)
1355219820Sjeff		cm_destroy_id(&cm_id_priv->id, ret);
1356219820Sjeff}
1357219820Sjeff
1358219820Sjeffstatic void cm_format_mra(struct cm_mra_msg *mra_msg,
1359219820Sjeff			  struct cm_id_private *cm_id_priv,
1360219820Sjeff			  enum cm_msg_response msg_mraed, u8 service_timeout,
1361219820Sjeff			  const void *private_data, u8 private_data_len)
1362219820Sjeff{
1363219820Sjeff	cm_format_mad_hdr(&mra_msg->hdr, CM_MRA_ATTR_ID, cm_id_priv->tid);
1364219820Sjeff	cm_mra_set_msg_mraed(mra_msg, msg_mraed);
1365219820Sjeff	mra_msg->local_comm_id = cm_id_priv->id.local_id;
1366219820Sjeff	mra_msg->remote_comm_id = cm_id_priv->id.remote_id;
1367219820Sjeff	cm_mra_set_service_timeout(mra_msg, service_timeout);
1368219820Sjeff
1369219820Sjeff	if (private_data && private_data_len)
1370219820Sjeff		memcpy(mra_msg->private_data, private_data, private_data_len);
1371219820Sjeff}
1372219820Sjeff
1373219820Sjeffstatic void cm_format_rej(struct cm_rej_msg *rej_msg,
1374219820Sjeff			  struct cm_id_private *cm_id_priv,
1375219820Sjeff			  enum ib_cm_rej_reason reason,
1376219820Sjeff			  void *ari,
1377219820Sjeff			  u8 ari_length,
1378219820Sjeff			  const void *private_data,
1379219820Sjeff			  u8 private_data_len)
1380219820Sjeff{
1381219820Sjeff	cm_format_mad_hdr(&rej_msg->hdr, CM_REJ_ATTR_ID, cm_id_priv->tid);
1382219820Sjeff	rej_msg->remote_comm_id = cm_id_priv->id.remote_id;
1383219820Sjeff
1384219820Sjeff	switch(cm_id_priv->id.state) {
1385219820Sjeff	case IB_CM_REQ_RCVD:
1386219820Sjeff		rej_msg->local_comm_id = 0;
1387219820Sjeff		cm_rej_set_msg_rejected(rej_msg, CM_MSG_RESPONSE_REQ);
1388219820Sjeff		break;
1389219820Sjeff	case IB_CM_MRA_REQ_SENT:
1390219820Sjeff		rej_msg->local_comm_id = cm_id_priv->id.local_id;
1391219820Sjeff		cm_rej_set_msg_rejected(rej_msg, CM_MSG_RESPONSE_REQ);
1392219820Sjeff		break;
1393219820Sjeff	case IB_CM_REP_RCVD:
1394219820Sjeff	case IB_CM_MRA_REP_SENT:
1395219820Sjeff		rej_msg->local_comm_id = cm_id_priv->id.local_id;
1396219820Sjeff		cm_rej_set_msg_rejected(rej_msg, CM_MSG_RESPONSE_REP);
1397219820Sjeff		break;
1398219820Sjeff	default:
1399219820Sjeff		rej_msg->local_comm_id = cm_id_priv->id.local_id;
1400219820Sjeff		cm_rej_set_msg_rejected(rej_msg, CM_MSG_RESPONSE_OTHER);
1401219820Sjeff		break;
1402219820Sjeff	}
1403219820Sjeff
1404219820Sjeff	rej_msg->reason = cpu_to_be16(reason);
1405219820Sjeff	if (ari && ari_length) {
1406219820Sjeff		cm_rej_set_reject_info_len(rej_msg, ari_length);
1407219820Sjeff		memcpy(rej_msg->ari, ari, ari_length);
1408219820Sjeff	}
1409219820Sjeff
1410219820Sjeff	if (private_data && private_data_len)
1411219820Sjeff		memcpy(rej_msg->private_data, private_data, private_data_len);
1412219820Sjeff}
1413219820Sjeff
1414219820Sjeffstatic void cm_dup_req_handler(struct cm_work *work,
1415219820Sjeff			       struct cm_id_private *cm_id_priv)
1416219820Sjeff{
1417219820Sjeff	struct ib_mad_send_buf *msg = NULL;
1418219820Sjeff	int ret;
1419219820Sjeff
1420219820Sjeff	atomic_long_inc(&work->port->counter_group[CM_RECV_DUPLICATES].
1421219820Sjeff			counter[CM_REQ_COUNTER]);
1422219820Sjeff
1423219820Sjeff	/* Quick state check to discard duplicate REQs. */
1424219820Sjeff	if (cm_id_priv->id.state == IB_CM_REQ_RCVD)
1425219820Sjeff		return;
1426219820Sjeff
1427219820Sjeff	ret = cm_alloc_response_msg(work->port, work->mad_recv_wc, &msg);
1428219820Sjeff	if (ret)
1429219820Sjeff		return;
1430219820Sjeff
1431219820Sjeff	spin_lock_irq(&cm_id_priv->lock);
1432219820Sjeff	switch (cm_id_priv->id.state) {
1433219820Sjeff	case IB_CM_MRA_REQ_SENT:
1434219820Sjeff		cm_format_mra((struct cm_mra_msg *) msg->mad, cm_id_priv,
1435219820Sjeff			      CM_MSG_RESPONSE_REQ, cm_id_priv->service_timeout,
1436219820Sjeff			      cm_id_priv->private_data,
1437219820Sjeff			      cm_id_priv->private_data_len);
1438219820Sjeff		break;
1439219820Sjeff	case IB_CM_TIMEWAIT:
1440219820Sjeff		cm_format_rej((struct cm_rej_msg *) msg->mad, cm_id_priv,
1441219820Sjeff			      IB_CM_REJ_STALE_CONN, NULL, 0, NULL, 0);
1442219820Sjeff		break;
1443219820Sjeff	default:
1444219820Sjeff		goto unlock;
1445219820Sjeff	}
1446219820Sjeff	spin_unlock_irq(&cm_id_priv->lock);
1447219820Sjeff
1448219820Sjeff	ret = ib_post_send_mad(msg, NULL);
1449219820Sjeff	if (ret)
1450219820Sjeff		goto free;
1451219820Sjeff	return;
1452219820Sjeff
1453219820Sjeffunlock:	spin_unlock_irq(&cm_id_priv->lock);
1454219820Sjefffree:	cm_free_msg(msg);
1455219820Sjeff}
1456219820Sjeff
1457219820Sjeffstatic struct cm_id_private * cm_match_req(struct cm_work *work,
1458219820Sjeff					   struct cm_id_private *cm_id_priv)
1459219820Sjeff{
1460219820Sjeff	struct cm_id_private *listen_cm_id_priv, *cur_cm_id_priv;
1461219820Sjeff	struct cm_timewait_info *timewait_info;
1462219820Sjeff	struct cm_req_msg *req_msg;
1463219820Sjeff
1464219820Sjeff	req_msg = (struct cm_req_msg *)work->mad_recv_wc->recv_buf.mad;
1465219820Sjeff
1466219820Sjeff	/* Check for possible duplicate REQ. */
1467219820Sjeff	spin_lock_irq(&cm.lock);
1468219820Sjeff	timewait_info = cm_insert_remote_id(cm_id_priv->timewait_info);
1469219820Sjeff	if (timewait_info) {
1470219820Sjeff		cur_cm_id_priv = cm_get_id(timewait_info->work.local_id,
1471219820Sjeff					   timewait_info->work.remote_id);
1472219820Sjeff		spin_unlock_irq(&cm.lock);
1473219820Sjeff		if (cur_cm_id_priv) {
1474219820Sjeff			cm_dup_req_handler(work, cur_cm_id_priv);
1475219820Sjeff			cm_deref_id(cur_cm_id_priv);
1476219820Sjeff		}
1477219820Sjeff		return NULL;
1478219820Sjeff	}
1479219820Sjeff
1480219820Sjeff	/* Check for stale connections. */
1481219820Sjeff	timewait_info = cm_insert_remote_qpn(cm_id_priv->timewait_info);
1482219820Sjeff	if (timewait_info) {
1483219820Sjeff		cm_cleanup_timewait(cm_id_priv->timewait_info);
1484219820Sjeff		spin_unlock_irq(&cm.lock);
1485219820Sjeff		cm_issue_rej(work->port, work->mad_recv_wc,
1486219820Sjeff			     IB_CM_REJ_STALE_CONN, CM_MSG_RESPONSE_REQ,
1487219820Sjeff			     NULL, 0);
1488219820Sjeff		return NULL;
1489219820Sjeff	}
1490219820Sjeff
1491219820Sjeff	/* Find matching listen request. */
1492219820Sjeff	listen_cm_id_priv = cm_find_listen(cm_id_priv->id.device,
1493219820Sjeff					   req_msg->service_id,
1494219820Sjeff					   req_msg->private_data);
1495219820Sjeff	if (!listen_cm_id_priv) {
1496219820Sjeff		cm_cleanup_timewait(cm_id_priv->timewait_info);
1497219820Sjeff		spin_unlock_irq(&cm.lock);
1498219820Sjeff		cm_issue_rej(work->port, work->mad_recv_wc,
1499219820Sjeff			     IB_CM_REJ_INVALID_SERVICE_ID, CM_MSG_RESPONSE_REQ,
1500219820Sjeff			     NULL, 0);
1501219820Sjeff		goto out;
1502219820Sjeff	}
1503219820Sjeff	atomic_inc(&listen_cm_id_priv->refcount);
1504219820Sjeff	atomic_inc(&cm_id_priv->refcount);
1505219820Sjeff	cm_id_priv->id.state = IB_CM_REQ_RCVD;
1506219820Sjeff	atomic_inc(&cm_id_priv->work_count);
1507219820Sjeff	spin_unlock_irq(&cm.lock);
1508219820Sjeffout:
1509219820Sjeff	return listen_cm_id_priv;
1510219820Sjeff}
1511219820Sjeff
1512219820Sjeff/*
1513219820Sjeff * Work-around for inter-subnet connections.  If the LIDs are permissive,
1514219820Sjeff * we need to override the LID/SL data in the REQ with the LID information
1515219820Sjeff * in the work completion.
1516219820Sjeff */
1517219820Sjeffstatic void cm_process_routed_req(struct cm_req_msg *req_msg, struct ib_wc *wc)
1518219820Sjeff{
1519219820Sjeff	if (!cm_req_get_primary_subnet_local(req_msg)) {
1520219820Sjeff		if (req_msg->primary_local_lid == IB_LID_PERMISSIVE) {
1521219820Sjeff			req_msg->primary_local_lid = cpu_to_be16(wc->slid);
1522219820Sjeff			cm_req_set_primary_sl(req_msg, wc->sl);
1523219820Sjeff		}
1524219820Sjeff
1525219820Sjeff		if (req_msg->primary_remote_lid == IB_LID_PERMISSIVE)
1526219820Sjeff			req_msg->primary_remote_lid = cpu_to_be16(wc->dlid_path_bits);
1527219820Sjeff	}
1528219820Sjeff
1529219820Sjeff	if (!cm_req_get_alt_subnet_local(req_msg)) {
1530219820Sjeff		if (req_msg->alt_local_lid == IB_LID_PERMISSIVE) {
1531219820Sjeff			req_msg->alt_local_lid = cpu_to_be16(wc->slid);
1532219820Sjeff			cm_req_set_alt_sl(req_msg, wc->sl);
1533219820Sjeff		}
1534219820Sjeff
1535219820Sjeff		if (req_msg->alt_remote_lid == IB_LID_PERMISSIVE)
1536219820Sjeff			req_msg->alt_remote_lid = cpu_to_be16(wc->dlid_path_bits);
1537219820Sjeff	}
1538219820Sjeff}
1539219820Sjeff
1540219820Sjeffstatic int cm_req_handler(struct cm_work *work)
1541219820Sjeff{
1542219820Sjeff	struct ib_cm_id *cm_id;
1543219820Sjeff	struct cm_id_private *cm_id_priv, *listen_cm_id_priv;
1544219820Sjeff	struct cm_req_msg *req_msg;
1545219820Sjeff	int ret;
1546219820Sjeff
1547219820Sjeff	req_msg = (struct cm_req_msg *)work->mad_recv_wc->recv_buf.mad;
1548219820Sjeff
1549219820Sjeff	cm_id = ib_create_cm_id(work->port->cm_dev->ib_device, NULL, NULL);
1550219820Sjeff	if (IS_ERR(cm_id))
1551219820Sjeff		return PTR_ERR(cm_id);
1552219820Sjeff
1553219820Sjeff	cm_id_priv = container_of(cm_id, struct cm_id_private, id);
1554219820Sjeff	cm_id_priv->id.remote_id = req_msg->local_comm_id;
1555219820Sjeff	cm_init_av_for_response(work->port, work->mad_recv_wc->wc,
1556219820Sjeff				work->mad_recv_wc->recv_buf.grh,
1557219820Sjeff				&cm_id_priv->av);
1558219820Sjeff	cm_id_priv->timewait_info = cm_create_timewait_info(cm_id_priv->
1559219820Sjeff							    id.local_id);
1560219820Sjeff	if (IS_ERR(cm_id_priv->timewait_info)) {
1561219820Sjeff		ret = PTR_ERR(cm_id_priv->timewait_info);
1562219820Sjeff		goto destroy;
1563219820Sjeff	}
1564219820Sjeff	cm_id_priv->timewait_info->work.remote_id = req_msg->local_comm_id;
1565219820Sjeff	cm_id_priv->timewait_info->remote_ca_guid = req_msg->local_ca_guid;
1566219820Sjeff	cm_id_priv->timewait_info->remote_qpn = cm_req_get_local_qpn(req_msg);
1567219820Sjeff
1568219820Sjeff	listen_cm_id_priv = cm_match_req(work, cm_id_priv);
1569219820Sjeff	if (!listen_cm_id_priv) {
1570219820Sjeff		ret = -EINVAL;
1571219820Sjeff		kfree(cm_id_priv->timewait_info);
1572219820Sjeff		goto destroy;
1573219820Sjeff	}
1574219820Sjeff
1575219820Sjeff	cm_id_priv->id.cm_handler = listen_cm_id_priv->id.cm_handler;
1576219820Sjeff	cm_id_priv->id.context = listen_cm_id_priv->id.context;
1577219820Sjeff	cm_id_priv->id.service_id = req_msg->service_id;
1578219820Sjeff	cm_id_priv->id.service_mask = ~cpu_to_be64(0);
1579219820Sjeff
1580219820Sjeff	cm_process_routed_req(req_msg, work->mad_recv_wc->wc);
1581219820Sjeff	cm_format_paths_from_req(req_msg, &work->path[0], &work->path[1]);
1582219820Sjeff	ret = cm_init_av_by_path(&work->path[0], &cm_id_priv->av);
1583219820Sjeff	if (ret) {
1584219820Sjeff		ib_get_cached_gid(work->port->cm_dev->ib_device,
1585219820Sjeff				  work->port->port_num, 0, &work->path[0].sgid);
1586219820Sjeff		ib_send_cm_rej(cm_id, IB_CM_REJ_INVALID_GID,
1587219820Sjeff			       &work->path[0].sgid, sizeof work->path[0].sgid,
1588219820Sjeff			       NULL, 0);
1589219820Sjeff		goto rejected;
1590219820Sjeff	}
1591219820Sjeff	if (req_msg->alt_local_lid) {
1592219820Sjeff		ret = cm_init_av_by_path(&work->path[1], &cm_id_priv->alt_av);
1593219820Sjeff		if (ret) {
1594219820Sjeff			ib_send_cm_rej(cm_id, IB_CM_REJ_INVALID_ALT_GID,
1595219820Sjeff				       &work->path[0].sgid,
1596219820Sjeff				       sizeof work->path[0].sgid, NULL, 0);
1597219820Sjeff			goto rejected;
1598219820Sjeff		}
1599219820Sjeff	}
1600219820Sjeff	cm_id_priv->tid = req_msg->hdr.tid;
1601219820Sjeff	cm_id_priv->timeout_ms = cm_convert_to_ms(
1602219820Sjeff					cm_req_get_local_resp_timeout(req_msg));
1603219820Sjeff       if (cm_req_get_local_resp_timeout(req_msg) > (u8) max_timeout) {
1604219820Sjeff               printk(KERN_WARNING PFX "rcvd cm_local_resp_timeout %d > %d, "
1605219820Sjeff                      "decreasing used timeout_ms\n",
1606219820Sjeff                      cm_req_get_local_resp_timeout(req_msg), max_timeout);
1607219820Sjeff               cm_id_priv->timeout_ms = cm_convert_to_ms(max_timeout);
1608219820Sjeff       }
1609219820Sjeff
1610219820Sjeff	cm_id_priv->max_cm_retries = cm_req_get_max_cm_retries(req_msg);
1611219820Sjeff	cm_id_priv->remote_qpn = cm_req_get_local_qpn(req_msg);
1612219820Sjeff	cm_id_priv->initiator_depth = cm_req_get_resp_res(req_msg);
1613219820Sjeff	cm_id_priv->responder_resources = cm_req_get_init_depth(req_msg);
1614219820Sjeff	cm_id_priv->path_mtu = cm_req_get_path_mtu(req_msg);
1615219820Sjeff	cm_id_priv->pkey = req_msg->pkey;
1616219820Sjeff	cm_id_priv->sq_psn = cm_req_get_starting_psn(req_msg);
1617219820Sjeff	cm_id_priv->retry_count = cm_req_get_retry_count(req_msg);
1618219820Sjeff	cm_id_priv->rnr_retry_count = cm_req_get_rnr_retry_count(req_msg);
1619219820Sjeff	cm_id_priv->qp_type = cm_req_get_qp_type(req_msg);
1620219820Sjeff
1621219820Sjeff	cm_format_req_event(work, cm_id_priv, &listen_cm_id_priv->id);
1622219820Sjeff	cm_process_work(cm_id_priv, work);
1623219820Sjeff	cm_deref_id(listen_cm_id_priv);
1624219820Sjeff	return 0;
1625219820Sjeff
1626219820Sjeffrejected:
1627219820Sjeff	atomic_dec(&cm_id_priv->refcount);
1628219820Sjeff	cm_deref_id(listen_cm_id_priv);
1629219820Sjeffdestroy:
1630219820Sjeff	ib_destroy_cm_id(cm_id);
1631219820Sjeff	return ret;
1632219820Sjeff}
1633219820Sjeff
1634219820Sjeffstatic void cm_format_rep(struct cm_rep_msg *rep_msg,
1635219820Sjeff			  struct cm_id_private *cm_id_priv,
1636219820Sjeff			  struct ib_cm_rep_param *param)
1637219820Sjeff{
1638219820Sjeff	cm_format_mad_hdr(&rep_msg->hdr, CM_REP_ATTR_ID, cm_id_priv->tid);
1639219820Sjeff	rep_msg->local_comm_id = cm_id_priv->id.local_id;
1640219820Sjeff	rep_msg->remote_comm_id = cm_id_priv->id.remote_id;
1641219820Sjeff	cm_rep_set_local_qpn(rep_msg, cpu_to_be32(param->qp_num));
1642219820Sjeff	cm_rep_set_starting_psn(rep_msg, cpu_to_be32(param->starting_psn));
1643219820Sjeff	rep_msg->resp_resources = param->responder_resources;
1644219820Sjeff	rep_msg->initiator_depth = param->initiator_depth;
1645219820Sjeff	cm_rep_set_target_ack_delay(rep_msg,
1646219820Sjeff				    cm_id_priv->av.port->cm_dev->ack_delay);
1647219820Sjeff	cm_rep_set_failover(rep_msg, param->failover_accepted);
1648219820Sjeff	cm_rep_set_flow_ctrl(rep_msg, param->flow_control);
1649219820Sjeff	cm_rep_set_rnr_retry_count(rep_msg, param->rnr_retry_count);
1650219820Sjeff	cm_rep_set_srq(rep_msg, param->srq);
1651219820Sjeff	rep_msg->local_ca_guid = cm_id_priv->id.device->node_guid;
1652219820Sjeff
1653219820Sjeff	if (param->private_data && param->private_data_len)
1654219820Sjeff		memcpy(rep_msg->private_data, param->private_data,
1655219820Sjeff		       param->private_data_len);
1656219820Sjeff}
1657219820Sjeff
1658219820Sjeffint ib_send_cm_rep(struct ib_cm_id *cm_id,
1659219820Sjeff		   struct ib_cm_rep_param *param)
1660219820Sjeff{
1661219820Sjeff	struct cm_id_private *cm_id_priv;
1662219820Sjeff	struct ib_mad_send_buf *msg;
1663219820Sjeff	struct cm_rep_msg *rep_msg;
1664219820Sjeff	unsigned long flags;
1665219820Sjeff	int ret;
1666219820Sjeff
1667219820Sjeff	if (param->private_data &&
1668219820Sjeff	    param->private_data_len > IB_CM_REP_PRIVATE_DATA_SIZE)
1669219820Sjeff		return -EINVAL;
1670219820Sjeff
1671219820Sjeff	cm_id_priv = container_of(cm_id, struct cm_id_private, id);
1672219820Sjeff	spin_lock_irqsave(&cm_id_priv->lock, flags);
1673219820Sjeff	if (cm_id->state != IB_CM_REQ_RCVD &&
1674219820Sjeff	    cm_id->state != IB_CM_MRA_REQ_SENT) {
1675219820Sjeff		ret = -EINVAL;
1676219820Sjeff		goto out;
1677219820Sjeff	}
1678219820Sjeff
1679219820Sjeff	ret = cm_alloc_msg(cm_id_priv, &msg);
1680219820Sjeff	if (ret)
1681219820Sjeff		goto out;
1682219820Sjeff
1683219820Sjeff	rep_msg = (struct cm_rep_msg *) msg->mad;
1684219820Sjeff	cm_format_rep(rep_msg, cm_id_priv, param);
1685219820Sjeff	msg->timeout_ms = cm_id_priv->timeout_ms;
1686219820Sjeff	msg->context[1] = (void *) (unsigned long) IB_CM_REP_SENT;
1687219820Sjeff
1688219820Sjeff	ret = ib_post_send_mad(msg, NULL);
1689219820Sjeff	if (ret) {
1690219820Sjeff		spin_unlock_irqrestore(&cm_id_priv->lock, flags);
1691219820Sjeff		cm_free_msg(msg);
1692219820Sjeff		return ret;
1693219820Sjeff	}
1694219820Sjeff
1695219820Sjeff	cm_id->state = IB_CM_REP_SENT;
1696219820Sjeff	cm_id_priv->msg = msg;
1697219820Sjeff	cm_id_priv->initiator_depth = param->initiator_depth;
1698219820Sjeff	cm_id_priv->responder_resources = param->responder_resources;
1699219820Sjeff	cm_id_priv->rq_psn = cm_rep_get_starting_psn(rep_msg);
1700219820Sjeff	cm_id_priv->local_qpn = cm_rep_get_local_qpn(rep_msg);
1701219820Sjeff
1702219820Sjeffout:	spin_unlock_irqrestore(&cm_id_priv->lock, flags);
1703219820Sjeff	return ret;
1704219820Sjeff}
1705219820SjeffEXPORT_SYMBOL(ib_send_cm_rep);
1706219820Sjeff
1707219820Sjeffstatic void cm_format_rtu(struct cm_rtu_msg *rtu_msg,
1708219820Sjeff			  struct cm_id_private *cm_id_priv,
1709219820Sjeff			  const void *private_data,
1710219820Sjeff			  u8 private_data_len)
1711219820Sjeff{
1712219820Sjeff	cm_format_mad_hdr(&rtu_msg->hdr, CM_RTU_ATTR_ID, cm_id_priv->tid);
1713219820Sjeff	rtu_msg->local_comm_id = cm_id_priv->id.local_id;
1714219820Sjeff	rtu_msg->remote_comm_id = cm_id_priv->id.remote_id;
1715219820Sjeff
1716219820Sjeff	if (private_data && private_data_len)
1717219820Sjeff		memcpy(rtu_msg->private_data, private_data, private_data_len);
1718219820Sjeff}
1719219820Sjeff
1720219820Sjeffint ib_send_cm_rtu(struct ib_cm_id *cm_id,
1721219820Sjeff		   const void *private_data,
1722219820Sjeff		   u8 private_data_len)
1723219820Sjeff{
1724219820Sjeff	struct cm_id_private *cm_id_priv;
1725219820Sjeff	struct ib_mad_send_buf *msg;
1726219820Sjeff	unsigned long flags;
1727219820Sjeff	void *data;
1728219820Sjeff	int ret;
1729219820Sjeff
1730219820Sjeff	if (private_data && private_data_len > IB_CM_RTU_PRIVATE_DATA_SIZE)
1731219820Sjeff		return -EINVAL;
1732219820Sjeff
1733219820Sjeff	data = cm_copy_private_data(private_data, private_data_len);
1734219820Sjeff	if (IS_ERR(data))
1735219820Sjeff		return PTR_ERR(data);
1736219820Sjeff
1737219820Sjeff	cm_id_priv = container_of(cm_id, struct cm_id_private, id);
1738219820Sjeff	spin_lock_irqsave(&cm_id_priv->lock, flags);
1739219820Sjeff	if (cm_id->state != IB_CM_REP_RCVD &&
1740219820Sjeff	    cm_id->state != IB_CM_MRA_REP_SENT) {
1741219820Sjeff		ret = -EINVAL;
1742219820Sjeff		goto error;
1743219820Sjeff	}
1744219820Sjeff
1745219820Sjeff	ret = cm_alloc_msg(cm_id_priv, &msg);
1746219820Sjeff	if (ret)
1747219820Sjeff		goto error;
1748219820Sjeff
1749219820Sjeff	cm_format_rtu((struct cm_rtu_msg *) msg->mad, cm_id_priv,
1750219820Sjeff		      private_data, private_data_len);
1751219820Sjeff
1752219820Sjeff	ret = ib_post_send_mad(msg, NULL);
1753219820Sjeff	if (ret) {
1754219820Sjeff		spin_unlock_irqrestore(&cm_id_priv->lock, flags);
1755219820Sjeff		cm_free_msg(msg);
1756219820Sjeff		kfree(data);
1757219820Sjeff		return ret;
1758219820Sjeff	}
1759219820Sjeff
1760219820Sjeff	cm_id->state = IB_CM_ESTABLISHED;
1761219820Sjeff	cm_set_private_data(cm_id_priv, data, private_data_len);
1762219820Sjeff	spin_unlock_irqrestore(&cm_id_priv->lock, flags);
1763219820Sjeff	return 0;
1764219820Sjeff
1765219820Sjefferror:	spin_unlock_irqrestore(&cm_id_priv->lock, flags);
1766219820Sjeff	kfree(data);
1767219820Sjeff	return ret;
1768219820Sjeff}
1769219820SjeffEXPORT_SYMBOL(ib_send_cm_rtu);
1770219820Sjeff
1771219820Sjeffstatic void cm_format_rep_event(struct cm_work *work)
1772219820Sjeff{
1773219820Sjeff	struct cm_rep_msg *rep_msg;
1774219820Sjeff	struct ib_cm_rep_event_param *param;
1775219820Sjeff
1776219820Sjeff	rep_msg = (struct cm_rep_msg *)work->mad_recv_wc->recv_buf.mad;
1777219820Sjeff	param = &work->cm_event.param.rep_rcvd;
1778219820Sjeff	param->remote_ca_guid = rep_msg->local_ca_guid;
1779219820Sjeff	param->remote_qkey = be32_to_cpu(rep_msg->local_qkey);
1780219820Sjeff	param->remote_qpn = be32_to_cpu(cm_rep_get_local_qpn(rep_msg));
1781219820Sjeff	param->starting_psn = be32_to_cpu(cm_rep_get_starting_psn(rep_msg));
1782219820Sjeff	param->responder_resources = rep_msg->initiator_depth;
1783219820Sjeff	param->initiator_depth = rep_msg->resp_resources;
1784219820Sjeff	param->target_ack_delay = cm_rep_get_target_ack_delay(rep_msg);
1785219820Sjeff	param->failover_accepted = cm_rep_get_failover(rep_msg);
1786219820Sjeff	param->flow_control = cm_rep_get_flow_ctrl(rep_msg);
1787219820Sjeff	param->rnr_retry_count = cm_rep_get_rnr_retry_count(rep_msg);
1788219820Sjeff	param->srq = cm_rep_get_srq(rep_msg);
1789219820Sjeff	work->cm_event.private_data = &rep_msg->private_data;
1790219820Sjeff}
1791219820Sjeff
1792219820Sjeffstatic void cm_dup_rep_handler(struct cm_work *work)
1793219820Sjeff{
1794219820Sjeff	struct cm_id_private *cm_id_priv;
1795219820Sjeff	struct cm_rep_msg *rep_msg;
1796219820Sjeff	struct ib_mad_send_buf *msg = NULL;
1797219820Sjeff	int ret;
1798219820Sjeff
1799219820Sjeff	rep_msg = (struct cm_rep_msg *) work->mad_recv_wc->recv_buf.mad;
1800219820Sjeff	cm_id_priv = cm_acquire_id(rep_msg->remote_comm_id,
1801219820Sjeff				   rep_msg->local_comm_id);
1802219820Sjeff	if (!cm_id_priv)
1803219820Sjeff		return;
1804219820Sjeff
1805219820Sjeff	atomic_long_inc(&work->port->counter_group[CM_RECV_DUPLICATES].
1806219820Sjeff			counter[CM_REP_COUNTER]);
1807219820Sjeff	ret = cm_alloc_response_msg(work->port, work->mad_recv_wc, &msg);
1808219820Sjeff	if (ret)
1809219820Sjeff		goto deref;
1810219820Sjeff
1811219820Sjeff	spin_lock_irq(&cm_id_priv->lock);
1812219820Sjeff	if (cm_id_priv->id.state == IB_CM_ESTABLISHED)
1813219820Sjeff		cm_format_rtu((struct cm_rtu_msg *) msg->mad, cm_id_priv,
1814219820Sjeff			      cm_id_priv->private_data,
1815219820Sjeff			      cm_id_priv->private_data_len);
1816219820Sjeff	else if (cm_id_priv->id.state == IB_CM_MRA_REP_SENT)
1817219820Sjeff		cm_format_mra((struct cm_mra_msg *) msg->mad, cm_id_priv,
1818219820Sjeff			      CM_MSG_RESPONSE_REP, cm_id_priv->service_timeout,
1819219820Sjeff			      cm_id_priv->private_data,
1820219820Sjeff			      cm_id_priv->private_data_len);
1821219820Sjeff	else
1822219820Sjeff		goto unlock;
1823219820Sjeff	spin_unlock_irq(&cm_id_priv->lock);
1824219820Sjeff
1825219820Sjeff	ret = ib_post_send_mad(msg, NULL);
1826219820Sjeff	if (ret)
1827219820Sjeff		goto free;
1828219820Sjeff	goto deref;
1829219820Sjeff
1830219820Sjeffunlock:	spin_unlock_irq(&cm_id_priv->lock);
1831219820Sjefffree:	cm_free_msg(msg);
1832219820Sjeffderef:	cm_deref_id(cm_id_priv);
1833219820Sjeff}
1834219820Sjeff
1835219820Sjeffstatic int cm_rep_handler(struct cm_work *work)
1836219820Sjeff{
1837219820Sjeff	struct cm_id_private *cm_id_priv;
1838219820Sjeff	struct cm_rep_msg *rep_msg;
1839219820Sjeff	int ret;
1840219820Sjeff
1841219820Sjeff	rep_msg = (struct cm_rep_msg *)work->mad_recv_wc->recv_buf.mad;
1842219820Sjeff	cm_id_priv = cm_acquire_id(rep_msg->remote_comm_id, 0);
1843219820Sjeff	if (!cm_id_priv) {
1844219820Sjeff		cm_dup_rep_handler(work);
1845219820Sjeff		return -EINVAL;
1846219820Sjeff	}
1847219820Sjeff
1848219820Sjeff	cm_format_rep_event(work);
1849219820Sjeff
1850219820Sjeff	spin_lock_irq(&cm_id_priv->lock);
1851219820Sjeff	switch (cm_id_priv->id.state) {
1852219820Sjeff	case IB_CM_REQ_SENT:
1853219820Sjeff	case IB_CM_MRA_REQ_RCVD:
1854219820Sjeff		break;
1855219820Sjeff	default:
1856219820Sjeff		spin_unlock_irq(&cm_id_priv->lock);
1857219820Sjeff		ret = -EINVAL;
1858219820Sjeff		goto error;
1859219820Sjeff	}
1860219820Sjeff
1861219820Sjeff	cm_id_priv->timewait_info->work.remote_id = rep_msg->local_comm_id;
1862219820Sjeff	cm_id_priv->timewait_info->remote_ca_guid = rep_msg->local_ca_guid;
1863219820Sjeff	cm_id_priv->timewait_info->remote_qpn = cm_rep_get_local_qpn(rep_msg);
1864219820Sjeff
1865219820Sjeff	spin_lock(&cm.lock);
1866219820Sjeff	/* Check for duplicate REP. */
1867219820Sjeff	if (cm_insert_remote_id(cm_id_priv->timewait_info)) {
1868219820Sjeff		spin_unlock(&cm.lock);
1869219820Sjeff		spin_unlock_irq(&cm_id_priv->lock);
1870219820Sjeff		ret = -EINVAL;
1871219820Sjeff		goto error;
1872219820Sjeff	}
1873219820Sjeff	/* Check for a stale connection. */
1874219820Sjeff	if (cm_insert_remote_qpn(cm_id_priv->timewait_info)) {
1875219820Sjeff		rb_erase(&cm_id_priv->timewait_info->remote_id_node,
1876219820Sjeff			 &cm.remote_id_table);
1877219820Sjeff		cm_id_priv->timewait_info->inserted_remote_id = 0;
1878219820Sjeff		spin_unlock(&cm.lock);
1879219820Sjeff		spin_unlock_irq(&cm_id_priv->lock);
1880219820Sjeff		cm_issue_rej(work->port, work->mad_recv_wc,
1881219820Sjeff			     IB_CM_REJ_STALE_CONN, CM_MSG_RESPONSE_REP,
1882219820Sjeff			     NULL, 0);
1883219820Sjeff		ret = -EINVAL;
1884219820Sjeff		goto error;
1885219820Sjeff	}
1886219820Sjeff	spin_unlock(&cm.lock);
1887219820Sjeff
1888219820Sjeff	cm_id_priv->id.state = IB_CM_REP_RCVD;
1889219820Sjeff	cm_id_priv->id.remote_id = rep_msg->local_comm_id;
1890219820Sjeff	cm_id_priv->remote_qpn = cm_rep_get_local_qpn(rep_msg);
1891219820Sjeff	cm_id_priv->initiator_depth = rep_msg->resp_resources;
1892219820Sjeff	cm_id_priv->responder_resources = rep_msg->initiator_depth;
1893219820Sjeff	cm_id_priv->sq_psn = cm_rep_get_starting_psn(rep_msg);
1894219820Sjeff	cm_id_priv->rnr_retry_count = cm_rep_get_rnr_retry_count(rep_msg);
1895219820Sjeff	cm_id_priv->target_ack_delay = cm_rep_get_target_ack_delay(rep_msg);
1896219820Sjeff	cm_id_priv->av.timeout =
1897219820Sjeff			cm_ack_timeout(cm_id_priv->target_ack_delay,
1898219820Sjeff				       cm_id_priv->av.timeout - 1);
1899219820Sjeff	cm_id_priv->alt_av.timeout =
1900219820Sjeff			cm_ack_timeout(cm_id_priv->target_ack_delay,
1901219820Sjeff				       cm_id_priv->alt_av.timeout - 1);
1902219820Sjeff
1903219820Sjeff	/* todo: handle peer_to_peer */
1904219820Sjeff
1905219820Sjeff	ib_cancel_mad(cm_id_priv->av.port->mad_agent, cm_id_priv->msg);
1906219820Sjeff	ret = atomic_inc_and_test(&cm_id_priv->work_count);
1907219820Sjeff	if (!ret)
1908219820Sjeff		list_add_tail(&work->list, &cm_id_priv->work_list);
1909219820Sjeff	spin_unlock_irq(&cm_id_priv->lock);
1910219820Sjeff
1911219820Sjeff	if (ret)
1912219820Sjeff		cm_process_work(cm_id_priv, work);
1913219820Sjeff	else
1914219820Sjeff		cm_deref_id(cm_id_priv);
1915219820Sjeff	return 0;
1916219820Sjeff
1917219820Sjefferror:
1918219820Sjeff	cm_deref_id(cm_id_priv);
1919219820Sjeff	return ret;
1920219820Sjeff}
1921219820Sjeff
1922219820Sjeffstatic int cm_establish_handler(struct cm_work *work)
1923219820Sjeff{
1924219820Sjeff	struct cm_id_private *cm_id_priv;
1925219820Sjeff	int ret;
1926219820Sjeff
1927219820Sjeff	/* See comment in cm_establish about lookup. */
1928219820Sjeff	cm_id_priv = cm_acquire_id(work->local_id, work->remote_id);
1929219820Sjeff	if (!cm_id_priv)
1930219820Sjeff		return -EINVAL;
1931219820Sjeff
1932219820Sjeff	spin_lock_irq(&cm_id_priv->lock);
1933219820Sjeff	if (cm_id_priv->id.state != IB_CM_ESTABLISHED) {
1934219820Sjeff		spin_unlock_irq(&cm_id_priv->lock);
1935219820Sjeff		goto out;
1936219820Sjeff	}
1937219820Sjeff
1938219820Sjeff	ib_cancel_mad(cm_id_priv->av.port->mad_agent, cm_id_priv->msg);
1939219820Sjeff	ret = atomic_inc_and_test(&cm_id_priv->work_count);
1940219820Sjeff	if (!ret)
1941219820Sjeff		list_add_tail(&work->list, &cm_id_priv->work_list);
1942219820Sjeff	spin_unlock_irq(&cm_id_priv->lock);
1943219820Sjeff
1944219820Sjeff	if (ret)
1945219820Sjeff		cm_process_work(cm_id_priv, work);
1946219820Sjeff	else
1947219820Sjeff		cm_deref_id(cm_id_priv);
1948219820Sjeff	return 0;
1949219820Sjeffout:
1950219820Sjeff	cm_deref_id(cm_id_priv);
1951219820Sjeff	return -EINVAL;
1952219820Sjeff}
1953219820Sjeff
1954219820Sjeffstatic int cm_rtu_handler(struct cm_work *work)
1955219820Sjeff{
1956219820Sjeff	struct cm_id_private *cm_id_priv;
1957219820Sjeff	struct cm_rtu_msg *rtu_msg;
1958219820Sjeff	int ret;
1959219820Sjeff
1960219820Sjeff	rtu_msg = (struct cm_rtu_msg *)work->mad_recv_wc->recv_buf.mad;
1961219820Sjeff	cm_id_priv = cm_acquire_id(rtu_msg->remote_comm_id,
1962219820Sjeff				   rtu_msg->local_comm_id);
1963219820Sjeff	if (!cm_id_priv)
1964219820Sjeff		return -EINVAL;
1965219820Sjeff
1966219820Sjeff	work->cm_event.private_data = &rtu_msg->private_data;
1967219820Sjeff
1968219820Sjeff	spin_lock_irq(&cm_id_priv->lock);
1969219820Sjeff	if (cm_id_priv->id.state != IB_CM_REP_SENT &&
1970219820Sjeff	    cm_id_priv->id.state != IB_CM_MRA_REP_RCVD) {
1971219820Sjeff		spin_unlock_irq(&cm_id_priv->lock);
1972219820Sjeff		atomic_long_inc(&work->port->counter_group[CM_RECV_DUPLICATES].
1973219820Sjeff				counter[CM_RTU_COUNTER]);
1974219820Sjeff		goto out;
1975219820Sjeff	}
1976219820Sjeff	cm_id_priv->id.state = IB_CM_ESTABLISHED;
1977219820Sjeff
1978219820Sjeff	ib_cancel_mad(cm_id_priv->av.port->mad_agent, cm_id_priv->msg);
1979219820Sjeff	ret = atomic_inc_and_test(&cm_id_priv->work_count);
1980219820Sjeff	if (!ret)
1981219820Sjeff		list_add_tail(&work->list, &cm_id_priv->work_list);
1982219820Sjeff	spin_unlock_irq(&cm_id_priv->lock);
1983219820Sjeff
1984219820Sjeff	if (ret)
1985219820Sjeff		cm_process_work(cm_id_priv, work);
1986219820Sjeff	else
1987219820Sjeff		cm_deref_id(cm_id_priv);
1988219820Sjeff	return 0;
1989219820Sjeffout:
1990219820Sjeff	cm_deref_id(cm_id_priv);
1991219820Sjeff	return -EINVAL;
1992219820Sjeff}
1993219820Sjeff
1994219820Sjeffstatic void cm_format_dreq(struct cm_dreq_msg *dreq_msg,
1995219820Sjeff			  struct cm_id_private *cm_id_priv,
1996219820Sjeff			  const void *private_data,
1997219820Sjeff			  u8 private_data_len)
1998219820Sjeff{
1999219820Sjeff	cm_format_mad_hdr(&dreq_msg->hdr, CM_DREQ_ATTR_ID,
2000219820Sjeff			  cm_form_tid(cm_id_priv, CM_MSG_SEQUENCE_DREQ));
2001219820Sjeff	dreq_msg->local_comm_id = cm_id_priv->id.local_id;
2002219820Sjeff	dreq_msg->remote_comm_id = cm_id_priv->id.remote_id;
2003219820Sjeff	cm_dreq_set_remote_qpn(dreq_msg, cm_id_priv->remote_qpn);
2004219820Sjeff
2005219820Sjeff	if (private_data && private_data_len)
2006219820Sjeff		memcpy(dreq_msg->private_data, private_data, private_data_len);
2007219820Sjeff}
2008219820Sjeff
2009219820Sjeffint ib_send_cm_dreq(struct ib_cm_id *cm_id,
2010219820Sjeff		    const void *private_data,
2011219820Sjeff		    u8 private_data_len)
2012219820Sjeff{
2013219820Sjeff	struct cm_id_private *cm_id_priv;
2014219820Sjeff	struct ib_mad_send_buf *msg;
2015219820Sjeff	unsigned long flags;
2016219820Sjeff	int ret;
2017219820Sjeff
2018219820Sjeff	if (private_data && private_data_len > IB_CM_DREQ_PRIVATE_DATA_SIZE)
2019219820Sjeff		return -EINVAL;
2020219820Sjeff
2021219820Sjeff	cm_id_priv = container_of(cm_id, struct cm_id_private, id);
2022219820Sjeff	spin_lock_irqsave(&cm_id_priv->lock, flags);
2023219820Sjeff	if (cm_id->state != IB_CM_ESTABLISHED) {
2024219820Sjeff		ret = -EINVAL;
2025219820Sjeff		goto out;
2026219820Sjeff	}
2027219820Sjeff
2028219820Sjeff	ret = cm_alloc_msg(cm_id_priv, &msg);
2029219820Sjeff	if (ret) {
2030219820Sjeff		cm_enter_timewait(cm_id_priv);
2031219820Sjeff		goto out;
2032219820Sjeff	}
2033219820Sjeff
2034219820Sjeff	cm_format_dreq((struct cm_dreq_msg *) msg->mad, cm_id_priv,
2035219820Sjeff		       private_data, private_data_len);
2036219820Sjeff	msg->timeout_ms = cm_id_priv->timeout_ms;
2037219820Sjeff	msg->context[1] = (void *) (unsigned long) IB_CM_DREQ_SENT;
2038219820Sjeff
2039219820Sjeff	ret = ib_post_send_mad(msg, NULL);
2040219820Sjeff	if (ret) {
2041219820Sjeff		cm_enter_timewait(cm_id_priv);
2042219820Sjeff		spin_unlock_irqrestore(&cm_id_priv->lock, flags);
2043219820Sjeff		cm_free_msg(msg);
2044219820Sjeff		return ret;
2045219820Sjeff	}
2046219820Sjeff
2047219820Sjeff	cm_id->state = IB_CM_DREQ_SENT;
2048219820Sjeff	cm_id_priv->msg = msg;
2049219820Sjeffout:	spin_unlock_irqrestore(&cm_id_priv->lock, flags);
2050219820Sjeff	return ret;
2051219820Sjeff}
2052219820SjeffEXPORT_SYMBOL(ib_send_cm_dreq);
2053219820Sjeff
2054219820Sjeffstatic void cm_format_drep(struct cm_drep_msg *drep_msg,
2055219820Sjeff			  struct cm_id_private *cm_id_priv,
2056219820Sjeff			  const void *private_data,
2057219820Sjeff			  u8 private_data_len)
2058219820Sjeff{
2059219820Sjeff	cm_format_mad_hdr(&drep_msg->hdr, CM_DREP_ATTR_ID, cm_id_priv->tid);
2060219820Sjeff	drep_msg->local_comm_id = cm_id_priv->id.local_id;
2061219820Sjeff	drep_msg->remote_comm_id = cm_id_priv->id.remote_id;
2062219820Sjeff
2063219820Sjeff	if (private_data && private_data_len)
2064219820Sjeff		memcpy(drep_msg->private_data, private_data, private_data_len);
2065219820Sjeff}
2066219820Sjeff
2067219820Sjeffint ib_send_cm_drep(struct ib_cm_id *cm_id,
2068219820Sjeff		    const void *private_data,
2069219820Sjeff		    u8 private_data_len)
2070219820Sjeff{
2071219820Sjeff	struct cm_id_private *cm_id_priv;
2072219820Sjeff	struct ib_mad_send_buf *msg;
2073219820Sjeff	unsigned long flags;
2074219820Sjeff	void *data;
2075219820Sjeff	int ret;
2076219820Sjeff
2077219820Sjeff	if (private_data && private_data_len > IB_CM_DREP_PRIVATE_DATA_SIZE)
2078219820Sjeff		return -EINVAL;
2079219820Sjeff
2080219820Sjeff	data = cm_copy_private_data(private_data, private_data_len);
2081219820Sjeff	if (IS_ERR(data))
2082219820Sjeff		return PTR_ERR(data);
2083219820Sjeff
2084219820Sjeff	cm_id_priv = container_of(cm_id, struct cm_id_private, id);
2085219820Sjeff	spin_lock_irqsave(&cm_id_priv->lock, flags);
2086219820Sjeff	if (cm_id->state != IB_CM_DREQ_RCVD) {
2087219820Sjeff		spin_unlock_irqrestore(&cm_id_priv->lock, flags);
2088219820Sjeff		kfree(data);
2089219820Sjeff		return -EINVAL;
2090219820Sjeff	}
2091219820Sjeff
2092219820Sjeff	cm_set_private_data(cm_id_priv, data, private_data_len);
2093219820Sjeff	cm_enter_timewait(cm_id_priv);
2094219820Sjeff
2095219820Sjeff	ret = cm_alloc_msg(cm_id_priv, &msg);
2096219820Sjeff	if (ret)
2097219820Sjeff		goto out;
2098219820Sjeff
2099219820Sjeff	cm_format_drep((struct cm_drep_msg *) msg->mad, cm_id_priv,
2100219820Sjeff		       private_data, private_data_len);
2101219820Sjeff
2102219820Sjeff	ret = ib_post_send_mad(msg, NULL);
2103219820Sjeff	if (ret) {
2104219820Sjeff		spin_unlock_irqrestore(&cm_id_priv->lock, flags);
2105219820Sjeff		cm_free_msg(msg);
2106219820Sjeff		return ret;
2107219820Sjeff	}
2108219820Sjeff
2109219820Sjeffout:	spin_unlock_irqrestore(&cm_id_priv->lock, flags);
2110219820Sjeff	return ret;
2111219820Sjeff}
2112219820SjeffEXPORT_SYMBOL(ib_send_cm_drep);
2113219820Sjeff
2114219820Sjeffstatic int cm_issue_drep(struct cm_port *port,
2115219820Sjeff			 struct ib_mad_recv_wc *mad_recv_wc)
2116219820Sjeff{
2117219820Sjeff	struct ib_mad_send_buf *msg = NULL;
2118219820Sjeff	struct cm_dreq_msg *dreq_msg;
2119219820Sjeff	struct cm_drep_msg *drep_msg;
2120219820Sjeff	int ret;
2121219820Sjeff
2122219820Sjeff	ret = cm_alloc_response_msg(port, mad_recv_wc, &msg);
2123219820Sjeff	if (ret)
2124219820Sjeff		return ret;
2125219820Sjeff
2126219820Sjeff	dreq_msg = (struct cm_dreq_msg *) mad_recv_wc->recv_buf.mad;
2127219820Sjeff	drep_msg = (struct cm_drep_msg *) msg->mad;
2128219820Sjeff
2129219820Sjeff	cm_format_mad_hdr(&drep_msg->hdr, CM_DREP_ATTR_ID, dreq_msg->hdr.tid);
2130219820Sjeff	drep_msg->remote_comm_id = dreq_msg->local_comm_id;
2131219820Sjeff	drep_msg->local_comm_id = dreq_msg->remote_comm_id;
2132219820Sjeff
2133219820Sjeff	ret = ib_post_send_mad(msg, NULL);
2134219820Sjeff	if (ret)
2135219820Sjeff		cm_free_msg(msg);
2136219820Sjeff
2137219820Sjeff	return ret;
2138219820Sjeff}
2139219820Sjeff
2140219820Sjeffstatic int cm_dreq_handler(struct cm_work *work)
2141219820Sjeff{
2142219820Sjeff	struct cm_id_private *cm_id_priv;
2143219820Sjeff	struct cm_dreq_msg *dreq_msg;
2144219820Sjeff	struct ib_mad_send_buf *msg = NULL;
2145219820Sjeff	int ret;
2146219820Sjeff
2147219820Sjeff	dreq_msg = (struct cm_dreq_msg *)work->mad_recv_wc->recv_buf.mad;
2148219820Sjeff	cm_id_priv = cm_acquire_id(dreq_msg->remote_comm_id,
2149219820Sjeff				   dreq_msg->local_comm_id);
2150219820Sjeff	if (!cm_id_priv) {
2151219820Sjeff		atomic_long_inc(&work->port->counter_group[CM_RECV_DUPLICATES].
2152219820Sjeff				counter[CM_DREQ_COUNTER]);
2153219820Sjeff		cm_issue_drep(work->port, work->mad_recv_wc);
2154219820Sjeff		return -EINVAL;
2155219820Sjeff	}
2156219820Sjeff
2157219820Sjeff	work->cm_event.private_data = &dreq_msg->private_data;
2158219820Sjeff
2159219820Sjeff	spin_lock_irq(&cm_id_priv->lock);
2160219820Sjeff	if (cm_id_priv->local_qpn != cm_dreq_get_remote_qpn(dreq_msg))
2161219820Sjeff		goto unlock;
2162219820Sjeff
2163219820Sjeff	switch (cm_id_priv->id.state) {
2164219820Sjeff	case IB_CM_REP_SENT:
2165219820Sjeff	case IB_CM_DREQ_SENT:
2166219820Sjeff		ib_cancel_mad(cm_id_priv->av.port->mad_agent, cm_id_priv->msg);
2167219820Sjeff		break;
2168219820Sjeff	case IB_CM_ESTABLISHED:
2169219820Sjeff	case IB_CM_MRA_REP_RCVD:
2170219820Sjeff		break;
2171219820Sjeff	case IB_CM_TIMEWAIT:
2172219820Sjeff		atomic_long_inc(&work->port->counter_group[CM_RECV_DUPLICATES].
2173219820Sjeff				counter[CM_DREQ_COUNTER]);
2174219820Sjeff		if (cm_alloc_response_msg(work->port, work->mad_recv_wc, &msg))
2175219820Sjeff			goto unlock;
2176219820Sjeff
2177219820Sjeff		cm_format_drep((struct cm_drep_msg *) msg->mad, cm_id_priv,
2178219820Sjeff			       cm_id_priv->private_data,
2179219820Sjeff			       cm_id_priv->private_data_len);
2180219820Sjeff		spin_unlock_irq(&cm_id_priv->lock);
2181219820Sjeff
2182219820Sjeff		if (ib_post_send_mad(msg, NULL))
2183219820Sjeff			cm_free_msg(msg);
2184219820Sjeff		goto deref;
2185219820Sjeff	case IB_CM_DREQ_RCVD:
2186219820Sjeff		atomic_long_inc(&work->port->counter_group[CM_RECV_DUPLICATES].
2187219820Sjeff				counter[CM_DREQ_COUNTER]);
2188219820Sjeff		goto unlock;
2189219820Sjeff	default:
2190219820Sjeff		goto unlock;
2191219820Sjeff	}
2192219820Sjeff	cm_id_priv->id.state = IB_CM_DREQ_RCVD;
2193219820Sjeff	cm_id_priv->tid = dreq_msg->hdr.tid;
2194219820Sjeff	ret = atomic_inc_and_test(&cm_id_priv->work_count);
2195219820Sjeff	if (!ret)
2196219820Sjeff		list_add_tail(&work->list, &cm_id_priv->work_list);
2197219820Sjeff	spin_unlock_irq(&cm_id_priv->lock);
2198219820Sjeff
2199219820Sjeff	if (ret)
2200219820Sjeff		cm_process_work(cm_id_priv, work);
2201219820Sjeff	else
2202219820Sjeff		cm_deref_id(cm_id_priv);
2203219820Sjeff	return 0;
2204219820Sjeff
2205219820Sjeffunlock:	spin_unlock_irq(&cm_id_priv->lock);
2206219820Sjeffderef:	cm_deref_id(cm_id_priv);
2207219820Sjeff	return -EINVAL;
2208219820Sjeff}
2209219820Sjeff
2210219820Sjeffstatic int cm_drep_handler(struct cm_work *work)
2211219820Sjeff{
2212219820Sjeff	struct cm_id_private *cm_id_priv;
2213219820Sjeff	struct cm_drep_msg *drep_msg;
2214219820Sjeff	int ret;
2215219820Sjeff
2216219820Sjeff	drep_msg = (struct cm_drep_msg *)work->mad_recv_wc->recv_buf.mad;
2217219820Sjeff	cm_id_priv = cm_acquire_id(drep_msg->remote_comm_id,
2218219820Sjeff				   drep_msg->local_comm_id);
2219219820Sjeff	if (!cm_id_priv)
2220219820Sjeff		return -EINVAL;
2221219820Sjeff
2222219820Sjeff	work->cm_event.private_data = &drep_msg->private_data;
2223219820Sjeff
2224219820Sjeff	spin_lock_irq(&cm_id_priv->lock);
2225219820Sjeff	if (cm_id_priv->id.state != IB_CM_DREQ_SENT &&
2226219820Sjeff	    cm_id_priv->id.state != IB_CM_DREQ_RCVD) {
2227219820Sjeff		spin_unlock_irq(&cm_id_priv->lock);
2228219820Sjeff		goto out;
2229219820Sjeff	}
2230219820Sjeff	cm_enter_timewait(cm_id_priv);
2231219820Sjeff
2232219820Sjeff	ib_cancel_mad(cm_id_priv->av.port->mad_agent, cm_id_priv->msg);
2233219820Sjeff	ret = atomic_inc_and_test(&cm_id_priv->work_count);
2234219820Sjeff	if (!ret)
2235219820Sjeff		list_add_tail(&work->list, &cm_id_priv->work_list);
2236219820Sjeff	spin_unlock_irq(&cm_id_priv->lock);
2237219820Sjeff
2238219820Sjeff	if (ret)
2239219820Sjeff		cm_process_work(cm_id_priv, work);
2240219820Sjeff	else
2241219820Sjeff		cm_deref_id(cm_id_priv);
2242219820Sjeff	return 0;
2243219820Sjeffout:
2244219820Sjeff	cm_deref_id(cm_id_priv);
2245219820Sjeff	return -EINVAL;
2246219820Sjeff}
2247219820Sjeff
2248219820Sjeffint ib_send_cm_rej(struct ib_cm_id *cm_id,
2249219820Sjeff		   enum ib_cm_rej_reason reason,
2250219820Sjeff		   void *ari,
2251219820Sjeff		   u8 ari_length,
2252219820Sjeff		   const void *private_data,
2253219820Sjeff		   u8 private_data_len)
2254219820Sjeff{
2255219820Sjeff	struct cm_id_private *cm_id_priv;
2256219820Sjeff	struct ib_mad_send_buf *msg;
2257219820Sjeff	unsigned long flags;
2258219820Sjeff	int ret;
2259219820Sjeff
2260219820Sjeff	if ((private_data && private_data_len > IB_CM_REJ_PRIVATE_DATA_SIZE) ||
2261219820Sjeff	    (ari && ari_length > IB_CM_REJ_ARI_LENGTH))
2262219820Sjeff		return -EINVAL;
2263219820Sjeff
2264219820Sjeff	cm_id_priv = container_of(cm_id, struct cm_id_private, id);
2265219820Sjeff
2266219820Sjeff	spin_lock_irqsave(&cm_id_priv->lock, flags);
2267219820Sjeff	switch (cm_id->state) {
2268219820Sjeff	case IB_CM_REQ_SENT:
2269219820Sjeff	case IB_CM_MRA_REQ_RCVD:
2270219820Sjeff	case IB_CM_REQ_RCVD:
2271219820Sjeff	case IB_CM_MRA_REQ_SENT:
2272219820Sjeff	case IB_CM_REP_RCVD:
2273219820Sjeff	case IB_CM_MRA_REP_SENT:
2274219820Sjeff		ret = cm_alloc_msg(cm_id_priv, &msg);
2275219820Sjeff		if (!ret)
2276219820Sjeff			cm_format_rej((struct cm_rej_msg *) msg->mad,
2277219820Sjeff				      cm_id_priv, reason, ari, ari_length,
2278219820Sjeff				      private_data, private_data_len);
2279219820Sjeff
2280219820Sjeff		cm_reset_to_idle(cm_id_priv);
2281219820Sjeff		break;
2282219820Sjeff	case IB_CM_REP_SENT:
2283219820Sjeff	case IB_CM_MRA_REP_RCVD:
2284219820Sjeff		ret = cm_alloc_msg(cm_id_priv, &msg);
2285219820Sjeff		if (!ret)
2286219820Sjeff			cm_format_rej((struct cm_rej_msg *) msg->mad,
2287219820Sjeff				      cm_id_priv, reason, ari, ari_length,
2288219820Sjeff				      private_data, private_data_len);
2289219820Sjeff
2290219820Sjeff		cm_enter_timewait(cm_id_priv);
2291219820Sjeff		break;
2292219820Sjeff	default:
2293219820Sjeff		ret = -EINVAL;
2294219820Sjeff		goto out;
2295219820Sjeff	}
2296219820Sjeff
2297219820Sjeff	if (ret)
2298219820Sjeff		goto out;
2299219820Sjeff
2300219820Sjeff	ret = ib_post_send_mad(msg, NULL);
2301219820Sjeff	if (ret)
2302219820Sjeff		cm_free_msg(msg);
2303219820Sjeff
2304219820Sjeffout:	spin_unlock_irqrestore(&cm_id_priv->lock, flags);
2305219820Sjeff	return ret;
2306219820Sjeff}
2307219820SjeffEXPORT_SYMBOL(ib_send_cm_rej);
2308219820Sjeff
2309219820Sjeffstatic void cm_format_rej_event(struct cm_work *work)
2310219820Sjeff{
2311219820Sjeff	struct cm_rej_msg *rej_msg;
2312219820Sjeff	struct ib_cm_rej_event_param *param;
2313219820Sjeff
2314219820Sjeff	rej_msg = (struct cm_rej_msg *)work->mad_recv_wc->recv_buf.mad;
2315219820Sjeff	param = &work->cm_event.param.rej_rcvd;
2316219820Sjeff	param->ari = rej_msg->ari;
2317219820Sjeff	param->ari_length = cm_rej_get_reject_info_len(rej_msg);
2318219820Sjeff	param->reason = __be16_to_cpu(rej_msg->reason);
2319219820Sjeff	work->cm_event.private_data = &rej_msg->private_data;
2320219820Sjeff}
2321219820Sjeff
2322219820Sjeffstatic struct cm_id_private * cm_acquire_rejected_id(struct cm_rej_msg *rej_msg)
2323219820Sjeff{
2324219820Sjeff	struct cm_timewait_info *timewait_info;
2325219820Sjeff	struct cm_id_private *cm_id_priv;
2326219820Sjeff	__be32 remote_id;
2327219820Sjeff
2328219820Sjeff	remote_id = rej_msg->local_comm_id;
2329219820Sjeff
2330219820Sjeff	if (__be16_to_cpu(rej_msg->reason) == IB_CM_REJ_TIMEOUT) {
2331219820Sjeff		spin_lock_irq(&cm.lock);
2332219820Sjeff		timewait_info = cm_find_remote_id( *((__be64 *) rej_msg->ari),
2333219820Sjeff						  remote_id);
2334219820Sjeff		if (!timewait_info) {
2335219820Sjeff			spin_unlock_irq(&cm.lock);
2336219820Sjeff			return NULL;
2337219820Sjeff		}
2338219820Sjeff		cm_id_priv = idr_find(&cm.local_id_table, (__force int)
2339219820Sjeff				      (timewait_info->work.local_id ^
2340219820Sjeff				       cm.random_id_operand));
2341219820Sjeff		if (cm_id_priv) {
2342219820Sjeff			if (cm_id_priv->id.remote_id == remote_id)
2343219820Sjeff				atomic_inc(&cm_id_priv->refcount);
2344219820Sjeff			else
2345219820Sjeff				cm_id_priv = NULL;
2346219820Sjeff		}
2347219820Sjeff		spin_unlock_irq(&cm.lock);
2348219820Sjeff	} else if (cm_rej_get_msg_rejected(rej_msg) == CM_MSG_RESPONSE_REQ)
2349219820Sjeff		cm_id_priv = cm_acquire_id(rej_msg->remote_comm_id, 0);
2350219820Sjeff	else
2351219820Sjeff		cm_id_priv = cm_acquire_id(rej_msg->remote_comm_id, remote_id);
2352219820Sjeff
2353219820Sjeff	return cm_id_priv;
2354219820Sjeff}
2355219820Sjeff
2356219820Sjeffstatic int cm_rej_handler(struct cm_work *work)
2357219820Sjeff{
2358219820Sjeff	struct cm_id_private *cm_id_priv;
2359219820Sjeff	struct cm_rej_msg *rej_msg;
2360219820Sjeff	int ret;
2361219820Sjeff
2362219820Sjeff	rej_msg = (struct cm_rej_msg *)work->mad_recv_wc->recv_buf.mad;
2363219820Sjeff	cm_id_priv = cm_acquire_rejected_id(rej_msg);
2364219820Sjeff	if (!cm_id_priv)
2365219820Sjeff		return -EINVAL;
2366219820Sjeff
2367219820Sjeff	cm_format_rej_event(work);
2368219820Sjeff
2369219820Sjeff	spin_lock_irq(&cm_id_priv->lock);
2370219820Sjeff	switch (cm_id_priv->id.state) {
2371219820Sjeff	case IB_CM_REQ_SENT:
2372219820Sjeff	case IB_CM_MRA_REQ_RCVD:
2373219820Sjeff	case IB_CM_REP_SENT:
2374219820Sjeff	case IB_CM_MRA_REP_RCVD:
2375219820Sjeff		ib_cancel_mad(cm_id_priv->av.port->mad_agent, cm_id_priv->msg);
2376219820Sjeff		/* fall through */
2377219820Sjeff	case IB_CM_REQ_RCVD:
2378219820Sjeff	case IB_CM_MRA_REQ_SENT:
2379219820Sjeff		if (__be16_to_cpu(rej_msg->reason) == IB_CM_REJ_STALE_CONN)
2380219820Sjeff			cm_enter_timewait(cm_id_priv);
2381219820Sjeff		else
2382219820Sjeff			cm_reset_to_idle(cm_id_priv);
2383219820Sjeff		break;
2384219820Sjeff	case IB_CM_DREQ_SENT:
2385219820Sjeff		ib_cancel_mad(cm_id_priv->av.port->mad_agent, cm_id_priv->msg);
2386219820Sjeff		/* fall through */
2387219820Sjeff	case IB_CM_REP_RCVD:
2388219820Sjeff	case IB_CM_MRA_REP_SENT:
2389219820Sjeff	case IB_CM_ESTABLISHED:
2390219820Sjeff		cm_enter_timewait(cm_id_priv);
2391219820Sjeff		break;
2392219820Sjeff	default:
2393219820Sjeff		spin_unlock_irq(&cm_id_priv->lock);
2394219820Sjeff		ret = -EINVAL;
2395219820Sjeff		goto out;
2396219820Sjeff	}
2397219820Sjeff
2398219820Sjeff	ret = atomic_inc_and_test(&cm_id_priv->work_count);
2399219820Sjeff	if (!ret)
2400219820Sjeff		list_add_tail(&work->list, &cm_id_priv->work_list);
2401219820Sjeff	spin_unlock_irq(&cm_id_priv->lock);
2402219820Sjeff
2403219820Sjeff	if (ret)
2404219820Sjeff		cm_process_work(cm_id_priv, work);
2405219820Sjeff	else
2406219820Sjeff		cm_deref_id(cm_id_priv);
2407219820Sjeff	return 0;
2408219820Sjeffout:
2409219820Sjeff	cm_deref_id(cm_id_priv);
2410219820Sjeff	return -EINVAL;
2411219820Sjeff}
2412219820Sjeff
2413219820Sjeffint ib_send_cm_mra(struct ib_cm_id *cm_id,
2414219820Sjeff		   u8 service_timeout,
2415219820Sjeff		   const void *private_data,
2416219820Sjeff		   u8 private_data_len)
2417219820Sjeff{
2418219820Sjeff	struct cm_id_private *cm_id_priv;
2419219820Sjeff	struct ib_mad_send_buf *msg;
2420219820Sjeff	enum ib_cm_state cm_state;
2421219820Sjeff	enum ib_cm_lap_state lap_state;
2422219820Sjeff	enum cm_msg_response msg_response;
2423219820Sjeff	void *data;
2424219820Sjeff	unsigned long flags;
2425219820Sjeff	int ret;
2426219820Sjeff
2427219820Sjeff	if (private_data && private_data_len > IB_CM_MRA_PRIVATE_DATA_SIZE)
2428219820Sjeff		return -EINVAL;
2429219820Sjeff
2430219820Sjeff	data = cm_copy_private_data(private_data, private_data_len);
2431219820Sjeff	if (IS_ERR(data))
2432219820Sjeff		return PTR_ERR(data);
2433219820Sjeff
2434219820Sjeff	cm_id_priv = container_of(cm_id, struct cm_id_private, id);
2435219820Sjeff
2436219820Sjeff	spin_lock_irqsave(&cm_id_priv->lock, flags);
2437219820Sjeff	switch(cm_id_priv->id.state) {
2438219820Sjeff	case IB_CM_REQ_RCVD:
2439219820Sjeff		cm_state = IB_CM_MRA_REQ_SENT;
2440219820Sjeff		lap_state = cm_id->lap_state;
2441219820Sjeff		msg_response = CM_MSG_RESPONSE_REQ;
2442219820Sjeff		break;
2443219820Sjeff	case IB_CM_REP_RCVD:
2444219820Sjeff		cm_state = IB_CM_MRA_REP_SENT;
2445219820Sjeff		lap_state = cm_id->lap_state;
2446219820Sjeff		msg_response = CM_MSG_RESPONSE_REP;
2447219820Sjeff		break;
2448219820Sjeff	case IB_CM_ESTABLISHED:
2449219820Sjeff		if (cm_id->lap_state == IB_CM_LAP_RCVD) {
2450219820Sjeff			cm_state = cm_id->state;
2451219820Sjeff			lap_state = IB_CM_MRA_LAP_SENT;
2452219820Sjeff			msg_response = CM_MSG_RESPONSE_OTHER;
2453219820Sjeff			break;
2454219820Sjeff		}
2455219820Sjeff	default:
2456219820Sjeff		ret = -EINVAL;
2457219820Sjeff		goto error1;
2458219820Sjeff	}
2459219820Sjeff
2460219820Sjeff	if (!(service_timeout & IB_CM_MRA_FLAG_DELAY)) {
2461219820Sjeff		ret = cm_alloc_msg(cm_id_priv, &msg);
2462219820Sjeff		if (ret)
2463219820Sjeff			goto error1;
2464219820Sjeff
2465219820Sjeff		cm_format_mra((struct cm_mra_msg *) msg->mad, cm_id_priv,
2466219820Sjeff			      msg_response, service_timeout,
2467219820Sjeff			      private_data, private_data_len);
2468219820Sjeff		ret = ib_post_send_mad(msg, NULL);
2469219820Sjeff		if (ret)
2470219820Sjeff			goto error2;
2471219820Sjeff	}
2472219820Sjeff
2473219820Sjeff	cm_id->state = cm_state;
2474219820Sjeff	cm_id->lap_state = lap_state;
2475219820Sjeff	cm_id_priv->service_timeout = service_timeout;
2476219820Sjeff	cm_set_private_data(cm_id_priv, data, private_data_len);
2477219820Sjeff	spin_unlock_irqrestore(&cm_id_priv->lock, flags);
2478219820Sjeff	return 0;
2479219820Sjeff
2480219820Sjefferror1:	spin_unlock_irqrestore(&cm_id_priv->lock, flags);
2481219820Sjeff	kfree(data);
2482219820Sjeff	return ret;
2483219820Sjeff
2484219820Sjefferror2:	spin_unlock_irqrestore(&cm_id_priv->lock, flags);
2485219820Sjeff	kfree(data);
2486219820Sjeff	cm_free_msg(msg);
2487219820Sjeff	return ret;
2488219820Sjeff}
2489219820SjeffEXPORT_SYMBOL(ib_send_cm_mra);
2490219820Sjeff
2491219820Sjeffstatic struct cm_id_private * cm_acquire_mraed_id(struct cm_mra_msg *mra_msg)
2492219820Sjeff{
2493219820Sjeff	switch (cm_mra_get_msg_mraed(mra_msg)) {
2494219820Sjeff	case CM_MSG_RESPONSE_REQ:
2495219820Sjeff		return cm_acquire_id(mra_msg->remote_comm_id, 0);
2496219820Sjeff	case CM_MSG_RESPONSE_REP:
2497219820Sjeff	case CM_MSG_RESPONSE_OTHER:
2498219820Sjeff		return cm_acquire_id(mra_msg->remote_comm_id,
2499219820Sjeff				     mra_msg->local_comm_id);
2500219820Sjeff	default:
2501219820Sjeff		return NULL;
2502219820Sjeff	}
2503219820Sjeff}
2504219820Sjeff
2505219820Sjeffstatic int cm_mra_handler(struct cm_work *work)
2506219820Sjeff{
2507219820Sjeff	struct cm_id_private *cm_id_priv;
2508219820Sjeff	struct cm_mra_msg *mra_msg;
2509219820Sjeff	int timeout, ret;
2510219820Sjeff
2511219820Sjeff	mra_msg = (struct cm_mra_msg *)work->mad_recv_wc->recv_buf.mad;
2512219820Sjeff	cm_id_priv = cm_acquire_mraed_id(mra_msg);
2513219820Sjeff	if (!cm_id_priv)
2514219820Sjeff		return -EINVAL;
2515219820Sjeff
2516219820Sjeff	work->cm_event.private_data = &mra_msg->private_data;
2517219820Sjeff	work->cm_event.param.mra_rcvd.service_timeout =
2518219820Sjeff					cm_mra_get_service_timeout(mra_msg);
2519219820Sjeff	timeout = cm_convert_to_ms(cm_mra_get_service_timeout(mra_msg)) +
2520219820Sjeff		  cm_convert_to_ms(cm_id_priv->av.timeout);
2521219820Sjeff       if (timeout > cm_convert_to_ms(max_timeout)) {
2522219820Sjeff               printk(KERN_WARNING PFX "calculated mra timeout %d > %d, "
2523219820Sjeff                      "decreasing used timeout_ms\n", timeout,
2524219820Sjeff                      cm_convert_to_ms(max_timeout));
2525219820Sjeff               timeout = cm_convert_to_ms(max_timeout);
2526219820Sjeff       }
2527219820Sjeff
2528219820Sjeff	spin_lock_irq(&cm_id_priv->lock);
2529219820Sjeff	switch (cm_id_priv->id.state) {
2530219820Sjeff	case IB_CM_REQ_SENT:
2531219820Sjeff		if (cm_mra_get_msg_mraed(mra_msg) != CM_MSG_RESPONSE_REQ ||
2532219820Sjeff		    ib_modify_mad(cm_id_priv->av.port->mad_agent,
2533219820Sjeff				  cm_id_priv->msg, timeout))
2534219820Sjeff			goto out;
2535219820Sjeff		cm_id_priv->id.state = IB_CM_MRA_REQ_RCVD;
2536219820Sjeff		break;
2537219820Sjeff	case IB_CM_REP_SENT:
2538219820Sjeff		if (cm_mra_get_msg_mraed(mra_msg) != CM_MSG_RESPONSE_REP ||
2539219820Sjeff		    ib_modify_mad(cm_id_priv->av.port->mad_agent,
2540219820Sjeff				  cm_id_priv->msg, timeout))
2541219820Sjeff			goto out;
2542219820Sjeff		cm_id_priv->id.state = IB_CM_MRA_REP_RCVD;
2543219820Sjeff		break;
2544219820Sjeff	case IB_CM_ESTABLISHED:
2545219820Sjeff		if (cm_mra_get_msg_mraed(mra_msg) != CM_MSG_RESPONSE_OTHER ||
2546219820Sjeff		    cm_id_priv->id.lap_state != IB_CM_LAP_SENT ||
2547219820Sjeff		    ib_modify_mad(cm_id_priv->av.port->mad_agent,
2548219820Sjeff				  cm_id_priv->msg, timeout)) {
2549219820Sjeff			if (cm_id_priv->id.lap_state == IB_CM_MRA_LAP_RCVD)
2550219820Sjeff				atomic_long_inc(&work->port->
2551219820Sjeff						counter_group[CM_RECV_DUPLICATES].
2552219820Sjeff						counter[CM_MRA_COUNTER]);
2553219820Sjeff			goto out;
2554219820Sjeff		}
2555219820Sjeff		cm_id_priv->id.lap_state = IB_CM_MRA_LAP_RCVD;
2556219820Sjeff		break;
2557219820Sjeff	case IB_CM_MRA_REQ_RCVD:
2558219820Sjeff	case IB_CM_MRA_REP_RCVD:
2559219820Sjeff		atomic_long_inc(&work->port->counter_group[CM_RECV_DUPLICATES].
2560219820Sjeff				counter[CM_MRA_COUNTER]);
2561219820Sjeff		/* fall through */
2562219820Sjeff	default:
2563219820Sjeff		goto out;
2564219820Sjeff	}
2565219820Sjeff
2566219820Sjeff	cm_id_priv->msg->context[1] = (void *) (unsigned long)
2567219820Sjeff				      cm_id_priv->id.state;
2568219820Sjeff	ret = atomic_inc_and_test(&cm_id_priv->work_count);
2569219820Sjeff	if (!ret)
2570219820Sjeff		list_add_tail(&work->list, &cm_id_priv->work_list);
2571219820Sjeff	spin_unlock_irq(&cm_id_priv->lock);
2572219820Sjeff
2573219820Sjeff	if (ret)
2574219820Sjeff		cm_process_work(cm_id_priv, work);
2575219820Sjeff	else
2576219820Sjeff		cm_deref_id(cm_id_priv);
2577219820Sjeff	return 0;
2578219820Sjeffout:
2579219820Sjeff	spin_unlock_irq(&cm_id_priv->lock);
2580219820Sjeff	cm_deref_id(cm_id_priv);
2581219820Sjeff	return -EINVAL;
2582219820Sjeff}
2583219820Sjeff
2584219820Sjeffstatic void cm_format_lap(struct cm_lap_msg *lap_msg,
2585219820Sjeff			  struct cm_id_private *cm_id_priv,
2586219820Sjeff			  struct ib_sa_path_rec *alternate_path,
2587219820Sjeff			  const void *private_data,
2588219820Sjeff			  u8 private_data_len)
2589219820Sjeff{
2590219820Sjeff	cm_format_mad_hdr(&lap_msg->hdr, CM_LAP_ATTR_ID,
2591219820Sjeff			  cm_form_tid(cm_id_priv, CM_MSG_SEQUENCE_LAP));
2592219820Sjeff	lap_msg->local_comm_id = cm_id_priv->id.local_id;
2593219820Sjeff	lap_msg->remote_comm_id = cm_id_priv->id.remote_id;
2594219820Sjeff	cm_lap_set_remote_qpn(lap_msg, cm_id_priv->remote_qpn);
2595219820Sjeff	/* todo: need remote CM response timeout */
2596219820Sjeff	cm_lap_set_remote_resp_timeout(lap_msg, 0x1F);
2597219820Sjeff	lap_msg->alt_local_lid = alternate_path->slid;
2598219820Sjeff	lap_msg->alt_remote_lid = alternate_path->dlid;
2599219820Sjeff	lap_msg->alt_local_gid = alternate_path->sgid;
2600219820Sjeff	lap_msg->alt_remote_gid = alternate_path->dgid;
2601219820Sjeff	cm_lap_set_flow_label(lap_msg, alternate_path->flow_label);
2602219820Sjeff	cm_lap_set_traffic_class(lap_msg, alternate_path->traffic_class);
2603219820Sjeff	lap_msg->alt_hop_limit = alternate_path->hop_limit;
2604219820Sjeff	cm_lap_set_packet_rate(lap_msg, alternate_path->rate);
2605219820Sjeff	cm_lap_set_sl(lap_msg, alternate_path->sl);
2606219820Sjeff	cm_lap_set_subnet_local(lap_msg, 1); /* local only... */
2607219820Sjeff	cm_lap_set_local_ack_timeout(lap_msg,
2608219820Sjeff		cm_ack_timeout(cm_id_priv->av.port->cm_dev->ack_delay,
2609219820Sjeff			       alternate_path->packet_life_time));
2610219820Sjeff
2611219820Sjeff	if (private_data && private_data_len)
2612219820Sjeff		memcpy(lap_msg->private_data, private_data, private_data_len);
2613219820Sjeff}
2614219820Sjeff
2615219820Sjeffint ib_send_cm_lap(struct ib_cm_id *cm_id,
2616219820Sjeff		   struct ib_sa_path_rec *alternate_path,
2617219820Sjeff		   const void *private_data,
2618219820Sjeff		   u8 private_data_len)
2619219820Sjeff{
2620219820Sjeff	struct cm_id_private *cm_id_priv;
2621219820Sjeff	struct ib_mad_send_buf *msg;
2622219820Sjeff	unsigned long flags;
2623219820Sjeff	int ret;
2624219820Sjeff
2625219820Sjeff	if (private_data && private_data_len > IB_CM_LAP_PRIVATE_DATA_SIZE)
2626219820Sjeff		return -EINVAL;
2627219820Sjeff
2628219820Sjeff	cm_id_priv = container_of(cm_id, struct cm_id_private, id);
2629219820Sjeff	spin_lock_irqsave(&cm_id_priv->lock, flags);
2630219820Sjeff	if (cm_id->state != IB_CM_ESTABLISHED ||
2631219820Sjeff	    (cm_id->lap_state != IB_CM_LAP_UNINIT &&
2632219820Sjeff	     cm_id->lap_state != IB_CM_LAP_IDLE)) {
2633219820Sjeff		ret = -EINVAL;
2634219820Sjeff		goto out;
2635219820Sjeff	}
2636219820Sjeff
2637219820Sjeff	ret = cm_init_av_by_path(alternate_path, &cm_id_priv->alt_av);
2638219820Sjeff	if (ret)
2639219820Sjeff		goto out;
2640219820Sjeff	cm_id_priv->alt_av.timeout =
2641219820Sjeff			cm_ack_timeout(cm_id_priv->target_ack_delay,
2642219820Sjeff				       cm_id_priv->alt_av.timeout - 1);
2643219820Sjeff
2644219820Sjeff	ret = cm_alloc_msg(cm_id_priv, &msg);
2645219820Sjeff	if (ret)
2646219820Sjeff		goto out;
2647219820Sjeff
2648219820Sjeff	cm_format_lap((struct cm_lap_msg *) msg->mad, cm_id_priv,
2649219820Sjeff		      alternate_path, private_data, private_data_len);
2650219820Sjeff	msg->timeout_ms = cm_id_priv->timeout_ms;
2651219820Sjeff	msg->context[1] = (void *) (unsigned long) IB_CM_ESTABLISHED;
2652219820Sjeff
2653219820Sjeff	ret = ib_post_send_mad(msg, NULL);
2654219820Sjeff	if (ret) {
2655219820Sjeff		spin_unlock_irqrestore(&cm_id_priv->lock, flags);
2656219820Sjeff		cm_free_msg(msg);
2657219820Sjeff		return ret;
2658219820Sjeff	}
2659219820Sjeff
2660219820Sjeff	cm_id->lap_state = IB_CM_LAP_SENT;
2661219820Sjeff	cm_id_priv->msg = msg;
2662219820Sjeff
2663219820Sjeffout:	spin_unlock_irqrestore(&cm_id_priv->lock, flags);
2664219820Sjeff	return ret;
2665219820Sjeff}
2666219820SjeffEXPORT_SYMBOL(ib_send_cm_lap);
2667219820Sjeff
2668219820Sjeffstatic void cm_format_path_from_lap(struct cm_id_private *cm_id_priv,
2669219820Sjeff				    struct ib_sa_path_rec *path,
2670219820Sjeff				    struct cm_lap_msg *lap_msg)
2671219820Sjeff{
2672219820Sjeff	memset(path, 0, sizeof *path);
2673219820Sjeff	path->dgid = lap_msg->alt_local_gid;
2674219820Sjeff	path->sgid = lap_msg->alt_remote_gid;
2675219820Sjeff	path->dlid = lap_msg->alt_local_lid;
2676219820Sjeff	path->slid = lap_msg->alt_remote_lid;
2677219820Sjeff	path->flow_label = cm_lap_get_flow_label(lap_msg);
2678219820Sjeff	path->hop_limit = lap_msg->alt_hop_limit;
2679219820Sjeff	path->traffic_class = cm_lap_get_traffic_class(lap_msg);
2680219820Sjeff	path->reversible = 1;
2681219820Sjeff	path->pkey = cm_id_priv->pkey;
2682219820Sjeff	path->sl = cm_lap_get_sl(lap_msg);
2683219820Sjeff	path->mtu_selector = IB_SA_EQ;
2684219820Sjeff	path->mtu = cm_id_priv->path_mtu;
2685219820Sjeff	path->rate_selector = IB_SA_EQ;
2686219820Sjeff	path->rate = cm_lap_get_packet_rate(lap_msg);
2687219820Sjeff	path->packet_life_time_selector = IB_SA_EQ;
2688219820Sjeff	path->packet_life_time = cm_lap_get_local_ack_timeout(lap_msg);
2689219820Sjeff	path->packet_life_time -= (path->packet_life_time > 0);
2690219820Sjeff}
2691219820Sjeff
2692219820Sjeffstatic int cm_lap_handler(struct cm_work *work)
2693219820Sjeff{
2694219820Sjeff	struct cm_id_private *cm_id_priv;
2695219820Sjeff	struct cm_lap_msg *lap_msg;
2696219820Sjeff	struct ib_cm_lap_event_param *param;
2697219820Sjeff	struct ib_mad_send_buf *msg = NULL;
2698219820Sjeff	int ret;
2699219820Sjeff
2700219820Sjeff	/* todo: verify LAP request and send reject APR if invalid. */
2701219820Sjeff	lap_msg = (struct cm_lap_msg *)work->mad_recv_wc->recv_buf.mad;
2702219820Sjeff	cm_id_priv = cm_acquire_id(lap_msg->remote_comm_id,
2703219820Sjeff				   lap_msg->local_comm_id);
2704219820Sjeff	if (!cm_id_priv)
2705219820Sjeff		return -EINVAL;
2706219820Sjeff
2707219820Sjeff	param = &work->cm_event.param.lap_rcvd;
2708219820Sjeff	param->alternate_path = &work->path[0];
2709219820Sjeff	cm_format_path_from_lap(cm_id_priv, param->alternate_path, lap_msg);
2710219820Sjeff	work->cm_event.private_data = &lap_msg->private_data;
2711219820Sjeff
2712219820Sjeff	spin_lock_irq(&cm_id_priv->lock);
2713219820Sjeff	if (cm_id_priv->id.state != IB_CM_ESTABLISHED)
2714219820Sjeff		goto unlock;
2715219820Sjeff
2716219820Sjeff	switch (cm_id_priv->id.lap_state) {
2717219820Sjeff	case IB_CM_LAP_UNINIT:
2718219820Sjeff	case IB_CM_LAP_IDLE:
2719219820Sjeff		break;
2720219820Sjeff	case IB_CM_MRA_LAP_SENT:
2721219820Sjeff		atomic_long_inc(&work->port->counter_group[CM_RECV_DUPLICATES].
2722219820Sjeff				counter[CM_LAP_COUNTER]);
2723219820Sjeff		if (cm_alloc_response_msg(work->port, work->mad_recv_wc, &msg))
2724219820Sjeff			goto unlock;
2725219820Sjeff
2726219820Sjeff		cm_format_mra((struct cm_mra_msg *) msg->mad, cm_id_priv,
2727219820Sjeff			      CM_MSG_RESPONSE_OTHER,
2728219820Sjeff			      cm_id_priv->service_timeout,
2729219820Sjeff			      cm_id_priv->private_data,
2730219820Sjeff			      cm_id_priv->private_data_len);
2731219820Sjeff		spin_unlock_irq(&cm_id_priv->lock);
2732219820Sjeff
2733219820Sjeff		if (ib_post_send_mad(msg, NULL))
2734219820Sjeff			cm_free_msg(msg);
2735219820Sjeff		goto deref;
2736219820Sjeff	case IB_CM_LAP_RCVD:
2737219820Sjeff		atomic_long_inc(&work->port->counter_group[CM_RECV_DUPLICATES].
2738219820Sjeff				counter[CM_LAP_COUNTER]);
2739219820Sjeff		goto unlock;
2740219820Sjeff	default:
2741219820Sjeff		goto unlock;
2742219820Sjeff	}
2743219820Sjeff
2744219820Sjeff	cm_id_priv->id.lap_state = IB_CM_LAP_RCVD;
2745219820Sjeff	cm_id_priv->tid = lap_msg->hdr.tid;
2746219820Sjeff	cm_init_av_for_response(work->port, work->mad_recv_wc->wc,
2747219820Sjeff				work->mad_recv_wc->recv_buf.grh,
2748219820Sjeff				&cm_id_priv->av);
2749219820Sjeff	cm_init_av_by_path(param->alternate_path, &cm_id_priv->alt_av);
2750219820Sjeff	ret = atomic_inc_and_test(&cm_id_priv->work_count);
2751219820Sjeff	if (!ret)
2752219820Sjeff		list_add_tail(&work->list, &cm_id_priv->work_list);
2753219820Sjeff	spin_unlock_irq(&cm_id_priv->lock);
2754219820Sjeff
2755219820Sjeff	if (ret)
2756219820Sjeff		cm_process_work(cm_id_priv, work);
2757219820Sjeff	else
2758219820Sjeff		cm_deref_id(cm_id_priv);
2759219820Sjeff	return 0;
2760219820Sjeff
2761219820Sjeffunlock:	spin_unlock_irq(&cm_id_priv->lock);
2762219820Sjeffderef:	cm_deref_id(cm_id_priv);
2763219820Sjeff	return -EINVAL;
2764219820Sjeff}
2765219820Sjeff
2766219820Sjeffstatic void cm_format_apr(struct cm_apr_msg *apr_msg,
2767219820Sjeff			  struct cm_id_private *cm_id_priv,
2768219820Sjeff			  enum ib_cm_apr_status status,
2769219820Sjeff			  void *info,
2770219820Sjeff			  u8 info_length,
2771219820Sjeff			  const void *private_data,
2772219820Sjeff			  u8 private_data_len)
2773219820Sjeff{
2774219820Sjeff	cm_format_mad_hdr(&apr_msg->hdr, CM_APR_ATTR_ID, cm_id_priv->tid);
2775219820Sjeff	apr_msg->local_comm_id = cm_id_priv->id.local_id;
2776219820Sjeff	apr_msg->remote_comm_id = cm_id_priv->id.remote_id;
2777219820Sjeff	apr_msg->ap_status = (u8) status;
2778219820Sjeff
2779219820Sjeff	if (info && info_length) {
2780219820Sjeff		apr_msg->info_length = info_length;
2781219820Sjeff		memcpy(apr_msg->info, info, info_length);
2782219820Sjeff	}
2783219820Sjeff
2784219820Sjeff	if (private_data && private_data_len)
2785219820Sjeff		memcpy(apr_msg->private_data, private_data, private_data_len);
2786219820Sjeff}
2787219820Sjeff
2788219820Sjeffint ib_send_cm_apr(struct ib_cm_id *cm_id,
2789219820Sjeff		   enum ib_cm_apr_status status,
2790219820Sjeff		   void *info,
2791219820Sjeff		   u8 info_length,
2792219820Sjeff		   const void *private_data,
2793219820Sjeff		   u8 private_data_len)
2794219820Sjeff{
2795219820Sjeff	struct cm_id_private *cm_id_priv;
2796219820Sjeff	struct ib_mad_send_buf *msg;
2797219820Sjeff	unsigned long flags;
2798219820Sjeff	int ret;
2799219820Sjeff
2800219820Sjeff	if ((private_data && private_data_len > IB_CM_APR_PRIVATE_DATA_SIZE) ||
2801219820Sjeff	    (info && info_length > IB_CM_APR_INFO_LENGTH))
2802219820Sjeff		return -EINVAL;
2803219820Sjeff
2804219820Sjeff	cm_id_priv = container_of(cm_id, struct cm_id_private, id);
2805219820Sjeff	spin_lock_irqsave(&cm_id_priv->lock, flags);
2806219820Sjeff	if (cm_id->state != IB_CM_ESTABLISHED ||
2807219820Sjeff	    (cm_id->lap_state != IB_CM_LAP_RCVD &&
2808219820Sjeff	     cm_id->lap_state != IB_CM_MRA_LAP_SENT)) {
2809219820Sjeff		ret = -EINVAL;
2810219820Sjeff		goto out;
2811219820Sjeff	}
2812219820Sjeff
2813219820Sjeff	ret = cm_alloc_msg(cm_id_priv, &msg);
2814219820Sjeff	if (ret)
2815219820Sjeff		goto out;
2816219820Sjeff
2817219820Sjeff	cm_format_apr((struct cm_apr_msg *) msg->mad, cm_id_priv, status,
2818219820Sjeff		      info, info_length, private_data, private_data_len);
2819219820Sjeff	ret = ib_post_send_mad(msg, NULL);
2820219820Sjeff	if (ret) {
2821219820Sjeff		spin_unlock_irqrestore(&cm_id_priv->lock, flags);
2822219820Sjeff		cm_free_msg(msg);
2823219820Sjeff		return ret;
2824219820Sjeff	}
2825219820Sjeff
2826219820Sjeff	cm_id->lap_state = IB_CM_LAP_IDLE;
2827219820Sjeffout:	spin_unlock_irqrestore(&cm_id_priv->lock, flags);
2828219820Sjeff	return ret;
2829219820Sjeff}
2830219820SjeffEXPORT_SYMBOL(ib_send_cm_apr);
2831219820Sjeff
2832219820Sjeffstatic int cm_apr_handler(struct cm_work *work)
2833219820Sjeff{
2834219820Sjeff	struct cm_id_private *cm_id_priv;
2835219820Sjeff	struct cm_apr_msg *apr_msg;
2836219820Sjeff	int ret;
2837219820Sjeff
2838219820Sjeff	apr_msg = (struct cm_apr_msg *)work->mad_recv_wc->recv_buf.mad;
2839219820Sjeff	cm_id_priv = cm_acquire_id(apr_msg->remote_comm_id,
2840219820Sjeff				   apr_msg->local_comm_id);
2841219820Sjeff	if (!cm_id_priv)
2842219820Sjeff		return -EINVAL; /* Unmatched reply. */
2843219820Sjeff
2844219820Sjeff	work->cm_event.param.apr_rcvd.ap_status = apr_msg->ap_status;
2845219820Sjeff	work->cm_event.param.apr_rcvd.apr_info = &apr_msg->info;
2846219820Sjeff	work->cm_event.param.apr_rcvd.info_len = apr_msg->info_length;
2847219820Sjeff	work->cm_event.private_data = &apr_msg->private_data;
2848219820Sjeff
2849219820Sjeff	spin_lock_irq(&cm_id_priv->lock);
2850219820Sjeff	if (cm_id_priv->id.state != IB_CM_ESTABLISHED ||
2851219820Sjeff	    (cm_id_priv->id.lap_state != IB_CM_LAP_SENT &&
2852219820Sjeff	     cm_id_priv->id.lap_state != IB_CM_MRA_LAP_RCVD)) {
2853219820Sjeff		spin_unlock_irq(&cm_id_priv->lock);
2854219820Sjeff		goto out;
2855219820Sjeff	}
2856219820Sjeff	cm_id_priv->id.lap_state = IB_CM_LAP_IDLE;
2857219820Sjeff	ib_cancel_mad(cm_id_priv->av.port->mad_agent, cm_id_priv->msg);
2858219820Sjeff	cm_id_priv->msg = NULL;
2859219820Sjeff
2860219820Sjeff	ret = atomic_inc_and_test(&cm_id_priv->work_count);
2861219820Sjeff	if (!ret)
2862219820Sjeff		list_add_tail(&work->list, &cm_id_priv->work_list);
2863219820Sjeff	spin_unlock_irq(&cm_id_priv->lock);
2864219820Sjeff
2865219820Sjeff	if (ret)
2866219820Sjeff		cm_process_work(cm_id_priv, work);
2867219820Sjeff	else
2868219820Sjeff		cm_deref_id(cm_id_priv);
2869219820Sjeff	return 0;
2870219820Sjeffout:
2871219820Sjeff	cm_deref_id(cm_id_priv);
2872219820Sjeff	return -EINVAL;
2873219820Sjeff}
2874219820Sjeff
2875219820Sjeffstatic int cm_timewait_handler(struct cm_work *work)
2876219820Sjeff{
2877219820Sjeff	struct cm_timewait_info *timewait_info;
2878219820Sjeff	struct cm_id_private *cm_id_priv;
2879219820Sjeff	int ret;
2880219820Sjeff
2881219820Sjeff	timewait_info = (struct cm_timewait_info *)work;
2882219820Sjeff	spin_lock_irq(&cm.lock);
2883219820Sjeff	list_del(&timewait_info->list);
2884219820Sjeff	spin_unlock_irq(&cm.lock);
2885219820Sjeff
2886219820Sjeff	cm_id_priv = cm_acquire_id(timewait_info->work.local_id,
2887219820Sjeff				   timewait_info->work.remote_id);
2888219820Sjeff	if (!cm_id_priv)
2889219820Sjeff		return -EINVAL;
2890219820Sjeff
2891219820Sjeff	spin_lock_irq(&cm_id_priv->lock);
2892219820Sjeff	if (cm_id_priv->id.state != IB_CM_TIMEWAIT ||
2893219820Sjeff	    cm_id_priv->remote_qpn != timewait_info->remote_qpn) {
2894219820Sjeff		spin_unlock_irq(&cm_id_priv->lock);
2895219820Sjeff		goto out;
2896219820Sjeff	}
2897219820Sjeff	cm_id_priv->id.state = IB_CM_IDLE;
2898219820Sjeff	ret = atomic_inc_and_test(&cm_id_priv->work_count);
2899219820Sjeff	if (!ret)
2900219820Sjeff		list_add_tail(&work->list, &cm_id_priv->work_list);
2901219820Sjeff	spin_unlock_irq(&cm_id_priv->lock);
2902219820Sjeff
2903219820Sjeff	if (ret)
2904219820Sjeff		cm_process_work(cm_id_priv, work);
2905219820Sjeff	else
2906219820Sjeff		cm_deref_id(cm_id_priv);
2907219820Sjeff	return 0;
2908219820Sjeffout:
2909219820Sjeff	cm_deref_id(cm_id_priv);
2910219820Sjeff	return -EINVAL;
2911219820Sjeff}
2912219820Sjeff
2913219820Sjeffstatic void cm_format_sidr_req(struct cm_sidr_req_msg *sidr_req_msg,
2914219820Sjeff			       struct cm_id_private *cm_id_priv,
2915219820Sjeff			       struct ib_cm_sidr_req_param *param)
2916219820Sjeff{
2917219820Sjeff	cm_format_mad_hdr(&sidr_req_msg->hdr, CM_SIDR_REQ_ATTR_ID,
2918219820Sjeff			  cm_form_tid(cm_id_priv, CM_MSG_SEQUENCE_SIDR));
2919219820Sjeff	sidr_req_msg->request_id = cm_id_priv->id.local_id;
2920219820Sjeff	sidr_req_msg->pkey = param->path->pkey;
2921219820Sjeff	sidr_req_msg->service_id = param->service_id;
2922219820Sjeff
2923219820Sjeff	if (param->private_data && param->private_data_len)
2924219820Sjeff		memcpy(sidr_req_msg->private_data, param->private_data,
2925219820Sjeff		       param->private_data_len);
2926219820Sjeff}
2927219820Sjeff
2928219820Sjeffint ib_send_cm_sidr_req(struct ib_cm_id *cm_id,
2929219820Sjeff			struct ib_cm_sidr_req_param *param)
2930219820Sjeff{
2931219820Sjeff	struct cm_id_private *cm_id_priv;
2932219820Sjeff	struct ib_mad_send_buf *msg;
2933219820Sjeff	unsigned long flags;
2934219820Sjeff	int ret;
2935219820Sjeff
2936219820Sjeff	if (!param->path || (param->private_data &&
2937219820Sjeff	     param->private_data_len > IB_CM_SIDR_REQ_PRIVATE_DATA_SIZE))
2938219820Sjeff		return -EINVAL;
2939219820Sjeff
2940219820Sjeff	cm_id_priv = container_of(cm_id, struct cm_id_private, id);
2941219820Sjeff	ret = cm_init_av_by_path(param->path, &cm_id_priv->av);
2942219820Sjeff	if (ret)
2943219820Sjeff		goto out;
2944219820Sjeff
2945219820Sjeff	cm_id->service_id = param->service_id;
2946219820Sjeff	cm_id->service_mask = ~cpu_to_be64(0);
2947219820Sjeff	cm_id_priv->timeout_ms = param->timeout_ms;
2948219820Sjeff       if (cm_id_priv->timeout_ms > cm_convert_to_ms(max_timeout)) {
2949219820Sjeff               printk(KERN_WARNING PFX "sidr req timeout_ms %d > %d, "
2950219820Sjeff                      "decreasing used timeout_ms\n", param->timeout_ms,
2951219820Sjeff                      cm_convert_to_ms(max_timeout));
2952219820Sjeff               cm_id_priv->timeout_ms = cm_convert_to_ms(max_timeout);
2953219820Sjeff       }
2954219820Sjeff	cm_id_priv->max_cm_retries = param->max_cm_retries;
2955219820Sjeff	ret = cm_alloc_msg(cm_id_priv, &msg);
2956219820Sjeff	if (ret)
2957219820Sjeff		goto out;
2958219820Sjeff
2959219820Sjeff	cm_format_sidr_req((struct cm_sidr_req_msg *) msg->mad, cm_id_priv,
2960219820Sjeff			   param);
2961219820Sjeff	msg->timeout_ms = cm_id_priv->timeout_ms;
2962219820Sjeff	msg->context[1] = (void *) (unsigned long) IB_CM_SIDR_REQ_SENT;
2963219820Sjeff
2964219820Sjeff	spin_lock_irqsave(&cm_id_priv->lock, flags);
2965219820Sjeff	if (cm_id->state == IB_CM_IDLE)
2966219820Sjeff		ret = ib_post_send_mad(msg, NULL);
2967219820Sjeff	else
2968219820Sjeff		ret = -EINVAL;
2969219820Sjeff
2970219820Sjeff	if (ret) {
2971219820Sjeff		spin_unlock_irqrestore(&cm_id_priv->lock, flags);
2972219820Sjeff		cm_free_msg(msg);
2973219820Sjeff		goto out;
2974219820Sjeff	}
2975219820Sjeff	cm_id->state = IB_CM_SIDR_REQ_SENT;
2976219820Sjeff	cm_id_priv->msg = msg;
2977219820Sjeff	spin_unlock_irqrestore(&cm_id_priv->lock, flags);
2978219820Sjeffout:
2979219820Sjeff	return ret;
2980219820Sjeff}
2981219820SjeffEXPORT_SYMBOL(ib_send_cm_sidr_req);
2982219820Sjeff
2983219820Sjeffstatic void cm_format_sidr_req_event(struct cm_work *work,
2984219820Sjeff				     struct ib_cm_id *listen_id)
2985219820Sjeff{
2986219820Sjeff	struct cm_sidr_req_msg *sidr_req_msg;
2987219820Sjeff	struct ib_cm_sidr_req_event_param *param;
2988219820Sjeff
2989219820Sjeff	sidr_req_msg = (struct cm_sidr_req_msg *)
2990219820Sjeff				work->mad_recv_wc->recv_buf.mad;
2991219820Sjeff	param = &work->cm_event.param.sidr_req_rcvd;
2992219820Sjeff	param->pkey = __be16_to_cpu(sidr_req_msg->pkey);
2993219820Sjeff	param->listen_id = listen_id;
2994219820Sjeff	param->port = work->port->port_num;
2995219820Sjeff	work->cm_event.private_data = &sidr_req_msg->private_data;
2996219820Sjeff}
2997219820Sjeff
2998219820Sjeffstatic int cm_sidr_req_handler(struct cm_work *work)
2999219820Sjeff{
3000219820Sjeff	struct ib_cm_id *cm_id;
3001219820Sjeff	struct cm_id_private *cm_id_priv, *cur_cm_id_priv;
3002219820Sjeff	struct cm_sidr_req_msg *sidr_req_msg;
3003219820Sjeff	struct ib_wc *wc;
3004219820Sjeff
3005219820Sjeff	cm_id = ib_create_cm_id(work->port->cm_dev->ib_device, NULL, NULL);
3006219820Sjeff	if (IS_ERR(cm_id))
3007219820Sjeff		return PTR_ERR(cm_id);
3008219820Sjeff	cm_id_priv = container_of(cm_id, struct cm_id_private, id);
3009219820Sjeff
3010219820Sjeff	/* Record SGID/SLID and request ID for lookup. */
3011219820Sjeff	sidr_req_msg = (struct cm_sidr_req_msg *)
3012219820Sjeff				work->mad_recv_wc->recv_buf.mad;
3013219820Sjeff	wc = work->mad_recv_wc->wc;
3014219820Sjeff	cm_id_priv->av.dgid.global.subnet_prefix = cpu_to_be64(wc->slid);
3015219820Sjeff	cm_id_priv->av.dgid.global.interface_id = 0;
3016219820Sjeff	cm_init_av_for_response(work->port, work->mad_recv_wc->wc,
3017219820Sjeff				work->mad_recv_wc->recv_buf.grh,
3018219820Sjeff				&cm_id_priv->av);
3019219820Sjeff	cm_id_priv->id.remote_id = sidr_req_msg->request_id;
3020219820Sjeff	cm_id_priv->tid = sidr_req_msg->hdr.tid;
3021219820Sjeff	atomic_inc(&cm_id_priv->work_count);
3022219820Sjeff
3023219820Sjeff	spin_lock_irq(&cm.lock);
3024219820Sjeff	cur_cm_id_priv = cm_insert_remote_sidr(cm_id_priv);
3025219820Sjeff	if (cur_cm_id_priv) {
3026219820Sjeff		spin_unlock_irq(&cm.lock);
3027219820Sjeff		atomic_long_inc(&work->port->counter_group[CM_RECV_DUPLICATES].
3028219820Sjeff				counter[CM_SIDR_REQ_COUNTER]);
3029219820Sjeff		goto out; /* Duplicate message. */
3030219820Sjeff	}
3031219820Sjeff	cm_id_priv->id.state = IB_CM_SIDR_REQ_RCVD;
3032219820Sjeff	cur_cm_id_priv = cm_find_listen(cm_id->device,
3033219820Sjeff					sidr_req_msg->service_id,
3034219820Sjeff					sidr_req_msg->private_data);
3035219820Sjeff	if (!cur_cm_id_priv) {
3036219820Sjeff		spin_unlock_irq(&cm.lock);
3037219820Sjeff		cm_reject_sidr_req(cm_id_priv, IB_SIDR_UNSUPPORTED);
3038219820Sjeff		goto out; /* No match. */
3039219820Sjeff	}
3040219820Sjeff	atomic_inc(&cur_cm_id_priv->refcount);
3041219820Sjeff	spin_unlock_irq(&cm.lock);
3042219820Sjeff
3043219820Sjeff	cm_id_priv->id.cm_handler = cur_cm_id_priv->id.cm_handler;
3044219820Sjeff	cm_id_priv->id.context = cur_cm_id_priv->id.context;
3045219820Sjeff	cm_id_priv->id.service_id = sidr_req_msg->service_id;
3046219820Sjeff	cm_id_priv->id.service_mask = ~cpu_to_be64(0);
3047219820Sjeff
3048219820Sjeff	cm_format_sidr_req_event(work, &cur_cm_id_priv->id);
3049219820Sjeff	cm_process_work(cm_id_priv, work);
3050219820Sjeff	cm_deref_id(cur_cm_id_priv);
3051219820Sjeff	return 0;
3052219820Sjeffout:
3053219820Sjeff	ib_destroy_cm_id(&cm_id_priv->id);
3054219820Sjeff	return -EINVAL;
3055219820Sjeff}
3056219820Sjeff
3057219820Sjeffstatic void cm_format_sidr_rep(struct cm_sidr_rep_msg *sidr_rep_msg,
3058219820Sjeff			       struct cm_id_private *cm_id_priv,
3059219820Sjeff			       struct ib_cm_sidr_rep_param *param)
3060219820Sjeff{
3061219820Sjeff	cm_format_mad_hdr(&sidr_rep_msg->hdr, CM_SIDR_REP_ATTR_ID,
3062219820Sjeff			  cm_id_priv->tid);
3063219820Sjeff	sidr_rep_msg->request_id = cm_id_priv->id.remote_id;
3064219820Sjeff	sidr_rep_msg->status = param->status;
3065219820Sjeff	cm_sidr_rep_set_qpn(sidr_rep_msg, cpu_to_be32(param->qp_num));
3066219820Sjeff	sidr_rep_msg->service_id = cm_id_priv->id.service_id;
3067219820Sjeff	sidr_rep_msg->qkey = cpu_to_be32(param->qkey);
3068219820Sjeff
3069219820Sjeff	if (param->info && param->info_length)
3070219820Sjeff		memcpy(sidr_rep_msg->info, param->info, param->info_length);
3071219820Sjeff
3072219820Sjeff	if (param->private_data && param->private_data_len)
3073219820Sjeff		memcpy(sidr_rep_msg->private_data, param->private_data,
3074219820Sjeff		       param->private_data_len);
3075219820Sjeff}
3076219820Sjeff
3077219820Sjeffint ib_send_cm_sidr_rep(struct ib_cm_id *cm_id,
3078219820Sjeff			struct ib_cm_sidr_rep_param *param)
3079219820Sjeff{
3080219820Sjeff	struct cm_id_private *cm_id_priv;
3081219820Sjeff	struct ib_mad_send_buf *msg;
3082219820Sjeff	unsigned long flags;
3083219820Sjeff	int ret;
3084219820Sjeff
3085219820Sjeff	if ((param->info && param->info_length > IB_CM_SIDR_REP_INFO_LENGTH) ||
3086219820Sjeff	    (param->private_data &&
3087219820Sjeff	     param->private_data_len > IB_CM_SIDR_REP_PRIVATE_DATA_SIZE))
3088219820Sjeff		return -EINVAL;
3089219820Sjeff
3090219820Sjeff	cm_id_priv = container_of(cm_id, struct cm_id_private, id);
3091219820Sjeff	spin_lock_irqsave(&cm_id_priv->lock, flags);
3092219820Sjeff	if (cm_id->state != IB_CM_SIDR_REQ_RCVD) {
3093219820Sjeff		ret = -EINVAL;
3094219820Sjeff		goto error;
3095219820Sjeff	}
3096219820Sjeff
3097219820Sjeff	ret = cm_alloc_msg(cm_id_priv, &msg);
3098219820Sjeff	if (ret)
3099219820Sjeff		goto error;
3100219820Sjeff
3101219820Sjeff	cm_format_sidr_rep((struct cm_sidr_rep_msg *) msg->mad, cm_id_priv,
3102219820Sjeff			   param);
3103219820Sjeff	ret = ib_post_send_mad(msg, NULL);
3104219820Sjeff	if (ret) {
3105219820Sjeff		spin_unlock_irqrestore(&cm_id_priv->lock, flags);
3106219820Sjeff		cm_free_msg(msg);
3107219820Sjeff		return ret;
3108219820Sjeff	}
3109219820Sjeff	cm_id->state = IB_CM_IDLE;
3110219820Sjeff	spin_unlock_irqrestore(&cm_id_priv->lock, flags);
3111219820Sjeff
3112219820Sjeff	spin_lock_irqsave(&cm.lock, flags);
3113219820Sjeff	rb_erase(&cm_id_priv->sidr_id_node, &cm.remote_sidr_table);
3114219820Sjeff	spin_unlock_irqrestore(&cm.lock, flags);
3115219820Sjeff	return 0;
3116219820Sjeff
3117219820Sjefferror:	spin_unlock_irqrestore(&cm_id_priv->lock, flags);
3118219820Sjeff	return ret;
3119219820Sjeff}
3120219820SjeffEXPORT_SYMBOL(ib_send_cm_sidr_rep);
3121219820Sjeff
3122219820Sjeffstatic void cm_format_sidr_rep_event(struct cm_work *work)
3123219820Sjeff{
3124219820Sjeff	struct cm_sidr_rep_msg *sidr_rep_msg;
3125219820Sjeff	struct ib_cm_sidr_rep_event_param *param;
3126219820Sjeff
3127219820Sjeff	sidr_rep_msg = (struct cm_sidr_rep_msg *)
3128219820Sjeff				work->mad_recv_wc->recv_buf.mad;
3129219820Sjeff	param = &work->cm_event.param.sidr_rep_rcvd;
3130219820Sjeff	param->status = sidr_rep_msg->status;
3131219820Sjeff	param->qkey = be32_to_cpu(sidr_rep_msg->qkey);
3132219820Sjeff	param->qpn = be32_to_cpu(cm_sidr_rep_get_qpn(sidr_rep_msg));
3133219820Sjeff	param->info = &sidr_rep_msg->info;
3134219820Sjeff	param->info_len = sidr_rep_msg->info_length;
3135219820Sjeff	work->cm_event.private_data = &sidr_rep_msg->private_data;
3136219820Sjeff}
3137219820Sjeff
3138219820Sjeffstatic int cm_sidr_rep_handler(struct cm_work *work)
3139219820Sjeff{
3140219820Sjeff	struct cm_sidr_rep_msg *sidr_rep_msg;
3141219820Sjeff	struct cm_id_private *cm_id_priv;
3142219820Sjeff
3143219820Sjeff	sidr_rep_msg = (struct cm_sidr_rep_msg *)
3144219820Sjeff				work->mad_recv_wc->recv_buf.mad;
3145219820Sjeff	cm_id_priv = cm_acquire_id(sidr_rep_msg->request_id, 0);
3146219820Sjeff	if (!cm_id_priv)
3147219820Sjeff		return -EINVAL; /* Unmatched reply. */
3148219820Sjeff
3149219820Sjeff	spin_lock_irq(&cm_id_priv->lock);
3150219820Sjeff	if (cm_id_priv->id.state != IB_CM_SIDR_REQ_SENT) {
3151219820Sjeff		spin_unlock_irq(&cm_id_priv->lock);
3152219820Sjeff		goto out;
3153219820Sjeff	}
3154219820Sjeff	cm_id_priv->id.state = IB_CM_IDLE;
3155219820Sjeff	ib_cancel_mad(cm_id_priv->av.port->mad_agent, cm_id_priv->msg);
3156219820Sjeff	spin_unlock_irq(&cm_id_priv->lock);
3157219820Sjeff
3158219820Sjeff	cm_format_sidr_rep_event(work);
3159219820Sjeff	cm_process_work(cm_id_priv, work);
3160219820Sjeff	return 0;
3161219820Sjeffout:
3162219820Sjeff	cm_deref_id(cm_id_priv);
3163219820Sjeff	return -EINVAL;
3164219820Sjeff}
3165219820Sjeff
3166219820Sjeffstatic void cm_process_send_error(struct ib_mad_send_buf *msg,
3167219820Sjeff				  enum ib_wc_status wc_status)
3168219820Sjeff{
3169219820Sjeff	struct cm_id_private *cm_id_priv;
3170219820Sjeff	struct ib_cm_event cm_event;
3171219820Sjeff	enum ib_cm_state state;
3172219820Sjeff	int ret;
3173219820Sjeff
3174219820Sjeff	memset(&cm_event, 0, sizeof cm_event);
3175219820Sjeff	cm_id_priv = msg->context[0];
3176219820Sjeff
3177219820Sjeff	/* Discard old sends or ones without a response. */
3178219820Sjeff	spin_lock_irq(&cm_id_priv->lock);
3179219820Sjeff	state = (enum ib_cm_state) (unsigned long) msg->context[1];
3180219820Sjeff	if (msg != cm_id_priv->msg || state != cm_id_priv->id.state)
3181219820Sjeff		goto discard;
3182219820Sjeff
3183219820Sjeff	switch (state) {
3184219820Sjeff	case IB_CM_REQ_SENT:
3185219820Sjeff	case IB_CM_MRA_REQ_RCVD:
3186219820Sjeff		cm_reset_to_idle(cm_id_priv);
3187219820Sjeff		cm_event.event = IB_CM_REQ_ERROR;
3188219820Sjeff		break;
3189219820Sjeff	case IB_CM_REP_SENT:
3190219820Sjeff	case IB_CM_MRA_REP_RCVD:
3191219820Sjeff		cm_reset_to_idle(cm_id_priv);
3192219820Sjeff		cm_event.event = IB_CM_REP_ERROR;
3193219820Sjeff		break;
3194219820Sjeff	case IB_CM_DREQ_SENT:
3195219820Sjeff		cm_enter_timewait(cm_id_priv);
3196219820Sjeff		cm_event.event = IB_CM_DREQ_ERROR;
3197219820Sjeff		break;
3198219820Sjeff	case IB_CM_SIDR_REQ_SENT:
3199219820Sjeff		cm_id_priv->id.state = IB_CM_IDLE;
3200219820Sjeff		cm_event.event = IB_CM_SIDR_REQ_ERROR;
3201219820Sjeff		break;
3202219820Sjeff	default:
3203219820Sjeff		goto discard;
3204219820Sjeff	}
3205219820Sjeff	spin_unlock_irq(&cm_id_priv->lock);
3206219820Sjeff	cm_event.param.send_status = wc_status;
3207219820Sjeff
3208219820Sjeff	/* No other events can occur on the cm_id at this point. */
3209219820Sjeff	ret = cm_id_priv->id.cm_handler(&cm_id_priv->id, &cm_event);
3210219820Sjeff	cm_free_msg(msg);
3211219820Sjeff	if (ret)
3212219820Sjeff		ib_destroy_cm_id(&cm_id_priv->id);
3213219820Sjeff	return;
3214219820Sjeffdiscard:
3215219820Sjeff	spin_unlock_irq(&cm_id_priv->lock);
3216219820Sjeff	cm_free_msg(msg);
3217219820Sjeff}
3218219820Sjeff
3219219820Sjeffstatic void cm_send_handler(struct ib_mad_agent *mad_agent,
3220219820Sjeff			    struct ib_mad_send_wc *mad_send_wc)
3221219820Sjeff{
3222219820Sjeff	struct ib_mad_send_buf *msg = mad_send_wc->send_buf;
3223219820Sjeff	struct cm_port *port;
3224219820Sjeff	u16 attr_index;
3225219820Sjeff
3226219820Sjeff	port = mad_agent->context;
3227219820Sjeff	attr_index = be16_to_cpu(((struct ib_mad_hdr *)
3228219820Sjeff				  msg->mad)->attr_id) - CM_ATTR_ID_OFFSET;
3229219820Sjeff
3230219820Sjeff	/*
3231219820Sjeff	 * If the send was in response to a received message (context[0] is not
3232219820Sjeff	 * set to a cm_id), and is not a REJ, then it is a send that was
3233219820Sjeff	 * manually retried.
3234219820Sjeff	 */
3235219820Sjeff	if (!msg->context[0] && (attr_index != CM_REJ_COUNTER))
3236219820Sjeff		msg->retries = 1;
3237219820Sjeff
3238219820Sjeff	atomic_long_add(1 + msg->retries,
3239219820Sjeff			&port->counter_group[CM_XMIT].counter[attr_index]);
3240219820Sjeff	if (msg->retries)
3241219820Sjeff		atomic_long_add(msg->retries,
3242219820Sjeff				&port->counter_group[CM_XMIT_RETRIES].
3243219820Sjeff				counter[attr_index]);
3244219820Sjeff
3245219820Sjeff	switch (mad_send_wc->status) {
3246219820Sjeff	case IB_WC_SUCCESS:
3247219820Sjeff	case IB_WC_WR_FLUSH_ERR:
3248219820Sjeff		cm_free_msg(msg);
3249219820Sjeff		break;
3250219820Sjeff	default:
3251219820Sjeff		if (msg->context[0] && msg->context[1])
3252219820Sjeff			cm_process_send_error(msg, mad_send_wc->status);
3253219820Sjeff		else
3254219820Sjeff			cm_free_msg(msg);
3255219820Sjeff		break;
3256219820Sjeff	}
3257219820Sjeff}
3258219820Sjeff
3259219820Sjeffstatic void cm_work_handler(struct work_struct *_work)
3260219820Sjeff{
3261219820Sjeff	struct cm_work *work = container_of(_work, struct cm_work, work.work);
3262219820Sjeff	int ret;
3263219820Sjeff
3264219820Sjeff	switch (work->cm_event.event) {
3265219820Sjeff	case IB_CM_REQ_RECEIVED:
3266219820Sjeff		ret = cm_req_handler(work);
3267219820Sjeff		break;
3268219820Sjeff	case IB_CM_MRA_RECEIVED:
3269219820Sjeff		ret = cm_mra_handler(work);
3270219820Sjeff		break;
3271219820Sjeff	case IB_CM_REJ_RECEIVED:
3272219820Sjeff		ret = cm_rej_handler(work);
3273219820Sjeff		break;
3274219820Sjeff	case IB_CM_REP_RECEIVED:
3275219820Sjeff		ret = cm_rep_handler(work);
3276219820Sjeff		break;
3277219820Sjeff	case IB_CM_RTU_RECEIVED:
3278219820Sjeff		ret = cm_rtu_handler(work);
3279219820Sjeff		break;
3280219820Sjeff	case IB_CM_USER_ESTABLISHED:
3281219820Sjeff		ret = cm_establish_handler(work);
3282219820Sjeff		break;
3283219820Sjeff	case IB_CM_DREQ_RECEIVED:
3284219820Sjeff		ret = cm_dreq_handler(work);
3285219820Sjeff		break;
3286219820Sjeff	case IB_CM_DREP_RECEIVED:
3287219820Sjeff		ret = cm_drep_handler(work);
3288219820Sjeff		break;
3289219820Sjeff	case IB_CM_SIDR_REQ_RECEIVED:
3290219820Sjeff		ret = cm_sidr_req_handler(work);
3291219820Sjeff		break;
3292219820Sjeff	case IB_CM_SIDR_REP_RECEIVED:
3293219820Sjeff		ret = cm_sidr_rep_handler(work);
3294219820Sjeff		break;
3295219820Sjeff	case IB_CM_LAP_RECEIVED:
3296219820Sjeff		ret = cm_lap_handler(work);
3297219820Sjeff		break;
3298219820Sjeff	case IB_CM_APR_RECEIVED:
3299219820Sjeff		ret = cm_apr_handler(work);
3300219820Sjeff		break;
3301219820Sjeff	case IB_CM_TIMEWAIT_EXIT:
3302219820Sjeff		ret = cm_timewait_handler(work);
3303219820Sjeff		break;
3304219820Sjeff	default:
3305219820Sjeff		ret = -EINVAL;
3306219820Sjeff		break;
3307219820Sjeff	}
3308219820Sjeff	if (ret)
3309219820Sjeff		cm_free_work(work);
3310219820Sjeff}
3311219820Sjeff
3312219820Sjeffstatic int cm_establish(struct ib_cm_id *cm_id)
3313219820Sjeff{
3314219820Sjeff	struct cm_id_private *cm_id_priv;
3315219820Sjeff	struct cm_work *work;
3316219820Sjeff	unsigned long flags;
3317219820Sjeff	int ret = 0;
3318219820Sjeff
3319219820Sjeff	work = kmalloc(sizeof *work, GFP_ATOMIC);
3320219820Sjeff	if (!work)
3321219820Sjeff		return -ENOMEM;
3322219820Sjeff
3323219820Sjeff	cm_id_priv = container_of(cm_id, struct cm_id_private, id);
3324219820Sjeff	spin_lock_irqsave(&cm_id_priv->lock, flags);
3325219820Sjeff	switch (cm_id->state)
3326219820Sjeff	{
3327219820Sjeff	case IB_CM_REP_SENT:
3328219820Sjeff	case IB_CM_MRA_REP_RCVD:
3329219820Sjeff		cm_id->state = IB_CM_ESTABLISHED;
3330219820Sjeff		break;
3331219820Sjeff	case IB_CM_ESTABLISHED:
3332219820Sjeff		ret = -EISCONN;
3333219820Sjeff		break;
3334219820Sjeff	default:
3335219820Sjeff		ret = -EINVAL;
3336219820Sjeff		break;
3337219820Sjeff	}
3338219820Sjeff	spin_unlock_irqrestore(&cm_id_priv->lock, flags);
3339219820Sjeff
3340219820Sjeff	if (ret) {
3341219820Sjeff		kfree(work);
3342219820Sjeff		goto out;
3343219820Sjeff	}
3344219820Sjeff
3345219820Sjeff	/*
3346219820Sjeff	 * The CM worker thread may try to destroy the cm_id before it
3347219820Sjeff	 * can execute this work item.  To prevent potential deadlock,
3348219820Sjeff	 * we need to find the cm_id once we're in the context of the
3349219820Sjeff	 * worker thread, rather than holding a reference on it.
3350219820Sjeff	 */
3351219820Sjeff	INIT_DELAYED_WORK(&work->work, cm_work_handler);
3352219820Sjeff	work->local_id = cm_id->local_id;
3353219820Sjeff	work->remote_id = cm_id->remote_id;
3354219820Sjeff	work->mad_recv_wc = NULL;
3355219820Sjeff	work->cm_event.event = IB_CM_USER_ESTABLISHED;
3356219820Sjeff	queue_delayed_work(cm.wq, &work->work, 0);
3357219820Sjeffout:
3358219820Sjeff	return ret;
3359219820Sjeff}
3360219820Sjeff
3361219820Sjeffstatic int cm_migrate(struct ib_cm_id *cm_id)
3362219820Sjeff{
3363219820Sjeff	struct cm_id_private *cm_id_priv;
3364219820Sjeff	unsigned long flags;
3365219820Sjeff	int ret = 0;
3366219820Sjeff
3367219820Sjeff	cm_id_priv = container_of(cm_id, struct cm_id_private, id);
3368219820Sjeff	spin_lock_irqsave(&cm_id_priv->lock, flags);
3369219820Sjeff	if (cm_id->state == IB_CM_ESTABLISHED &&
3370219820Sjeff	    (cm_id->lap_state == IB_CM_LAP_UNINIT ||
3371219820Sjeff	     cm_id->lap_state == IB_CM_LAP_IDLE)) {
3372219820Sjeff		cm_id->lap_state = IB_CM_LAP_IDLE;
3373219820Sjeff		cm_id_priv->av = cm_id_priv->alt_av;
3374219820Sjeff	} else
3375219820Sjeff		ret = -EINVAL;
3376219820Sjeff	spin_unlock_irqrestore(&cm_id_priv->lock, flags);
3377219820Sjeff
3378219820Sjeff	return ret;
3379219820Sjeff}
3380219820Sjeff
3381219820Sjeffint ib_cm_notify(struct ib_cm_id *cm_id, enum ib_event_type event)
3382219820Sjeff{
3383219820Sjeff	int ret;
3384219820Sjeff
3385219820Sjeff	switch (event) {
3386219820Sjeff	case IB_EVENT_COMM_EST:
3387219820Sjeff		ret = cm_establish(cm_id);
3388219820Sjeff		break;
3389219820Sjeff	case IB_EVENT_PATH_MIG:
3390219820Sjeff		ret = cm_migrate(cm_id);
3391219820Sjeff		break;
3392219820Sjeff	default:
3393219820Sjeff		ret = -EINVAL;
3394219820Sjeff	}
3395219820Sjeff	return ret;
3396219820Sjeff}
3397219820SjeffEXPORT_SYMBOL(ib_cm_notify);
3398219820Sjeff
3399219820Sjeffstatic void cm_recv_handler(struct ib_mad_agent *mad_agent,
3400219820Sjeff			    struct ib_mad_recv_wc *mad_recv_wc)
3401219820Sjeff{
3402219820Sjeff	struct cm_port *port = mad_agent->context;
3403219820Sjeff	struct cm_work *work;
3404219820Sjeff	enum ib_cm_event_type event;
3405219820Sjeff	u16 attr_id;
3406219820Sjeff	int paths = 0;
3407219820Sjeff
3408219820Sjeff	switch (mad_recv_wc->recv_buf.mad->mad_hdr.attr_id) {
3409219820Sjeff	case CM_REQ_ATTR_ID:
3410219820Sjeff		paths = 1 + (((struct cm_req_msg *) mad_recv_wc->recv_buf.mad)->
3411219820Sjeff						    alt_local_lid != 0);
3412219820Sjeff		event = IB_CM_REQ_RECEIVED;
3413219820Sjeff		break;
3414219820Sjeff	case CM_MRA_ATTR_ID:
3415219820Sjeff		event = IB_CM_MRA_RECEIVED;
3416219820Sjeff		break;
3417219820Sjeff	case CM_REJ_ATTR_ID:
3418219820Sjeff		event = IB_CM_REJ_RECEIVED;
3419219820Sjeff		break;
3420219820Sjeff	case CM_REP_ATTR_ID:
3421219820Sjeff		event = IB_CM_REP_RECEIVED;
3422219820Sjeff		break;
3423219820Sjeff	case CM_RTU_ATTR_ID:
3424219820Sjeff		event = IB_CM_RTU_RECEIVED;
3425219820Sjeff		break;
3426219820Sjeff	case CM_DREQ_ATTR_ID:
3427219820Sjeff		event = IB_CM_DREQ_RECEIVED;
3428219820Sjeff		break;
3429219820Sjeff	case CM_DREP_ATTR_ID:
3430219820Sjeff		event = IB_CM_DREP_RECEIVED;
3431219820Sjeff		break;
3432219820Sjeff	case CM_SIDR_REQ_ATTR_ID:
3433219820Sjeff		event = IB_CM_SIDR_REQ_RECEIVED;
3434219820Sjeff		break;
3435219820Sjeff	case CM_SIDR_REP_ATTR_ID:
3436219820Sjeff		event = IB_CM_SIDR_REP_RECEIVED;
3437219820Sjeff		break;
3438219820Sjeff	case CM_LAP_ATTR_ID:
3439219820Sjeff		paths = 1;
3440219820Sjeff		event = IB_CM_LAP_RECEIVED;
3441219820Sjeff		break;
3442219820Sjeff	case CM_APR_ATTR_ID:
3443219820Sjeff		event = IB_CM_APR_RECEIVED;
3444219820Sjeff		break;
3445219820Sjeff	default:
3446219820Sjeff		ib_free_recv_mad(mad_recv_wc);
3447219820Sjeff		return;
3448219820Sjeff	}
3449219820Sjeff
3450219820Sjeff	attr_id = be16_to_cpu(mad_recv_wc->recv_buf.mad->mad_hdr.attr_id);
3451219820Sjeff	atomic_long_inc(&port->counter_group[CM_RECV].
3452219820Sjeff			counter[attr_id - CM_ATTR_ID_OFFSET]);
3453219820Sjeff
3454219820Sjeff	work = kmalloc(sizeof *work + sizeof(struct ib_sa_path_rec) * paths,
3455219820Sjeff		       GFP_KERNEL);
3456219820Sjeff	if (!work) {
3457219820Sjeff		ib_free_recv_mad(mad_recv_wc);
3458219820Sjeff		return;
3459219820Sjeff	}
3460219820Sjeff
3461219820Sjeff	INIT_DELAYED_WORK(&work->work, cm_work_handler);
3462219820Sjeff	work->cm_event.event = event;
3463219820Sjeff	work->mad_recv_wc = mad_recv_wc;
3464219820Sjeff	work->port = port;
3465219820Sjeff	queue_delayed_work(cm.wq, &work->work, 0);
3466219820Sjeff}
3467219820Sjeff
3468219820Sjeffstatic int cm_init_qp_init_attr(struct cm_id_private *cm_id_priv,
3469219820Sjeff				struct ib_qp_attr *qp_attr,
3470219820Sjeff				int *qp_attr_mask)
3471219820Sjeff{
3472219820Sjeff	unsigned long flags;
3473219820Sjeff	int ret;
3474219820Sjeff
3475219820Sjeff	spin_lock_irqsave(&cm_id_priv->lock, flags);
3476219820Sjeff	switch (cm_id_priv->id.state) {
3477219820Sjeff	case IB_CM_REQ_SENT:
3478219820Sjeff	case IB_CM_MRA_REQ_RCVD:
3479219820Sjeff	case IB_CM_REQ_RCVD:
3480219820Sjeff	case IB_CM_MRA_REQ_SENT:
3481219820Sjeff	case IB_CM_REP_RCVD:
3482219820Sjeff	case IB_CM_MRA_REP_SENT:
3483219820Sjeff	case IB_CM_REP_SENT:
3484219820Sjeff	case IB_CM_MRA_REP_RCVD:
3485219820Sjeff	case IB_CM_ESTABLISHED:
3486219820Sjeff		*qp_attr_mask = IB_QP_STATE | IB_QP_ACCESS_FLAGS |
3487219820Sjeff				IB_QP_PKEY_INDEX | IB_QP_PORT;
3488219820Sjeff		qp_attr->qp_access_flags = IB_ACCESS_REMOTE_WRITE;
3489219820Sjeff		if (cm_id_priv->responder_resources)
3490219820Sjeff			qp_attr->qp_access_flags |= IB_ACCESS_REMOTE_READ |
3491219820Sjeff						    IB_ACCESS_REMOTE_ATOMIC;
3492219820Sjeff		qp_attr->pkey_index = cm_id_priv->av.pkey_index;
3493219820Sjeff		qp_attr->port_num = cm_id_priv->av.port->port_num;
3494219820Sjeff		ret = 0;
3495219820Sjeff		break;
3496219820Sjeff	default:
3497219820Sjeff		ret = -EINVAL;
3498219820Sjeff		break;
3499219820Sjeff	}
3500219820Sjeff	spin_unlock_irqrestore(&cm_id_priv->lock, flags);
3501219820Sjeff	return ret;
3502219820Sjeff}
3503219820Sjeff
3504219820Sjeffstatic int cm_init_qp_rtr_attr(struct cm_id_private *cm_id_priv,
3505219820Sjeff			       struct ib_qp_attr *qp_attr,
3506219820Sjeff			       int *qp_attr_mask)
3507219820Sjeff{
3508219820Sjeff	unsigned long flags;
3509219820Sjeff	int ret;
3510219820Sjeff
3511219820Sjeff	spin_lock_irqsave(&cm_id_priv->lock, flags);
3512219820Sjeff	switch (cm_id_priv->id.state) {
3513219820Sjeff	case IB_CM_REQ_RCVD:
3514219820Sjeff	case IB_CM_MRA_REQ_SENT:
3515219820Sjeff	case IB_CM_REP_RCVD:
3516219820Sjeff	case IB_CM_MRA_REP_SENT:
3517219820Sjeff	case IB_CM_REP_SENT:
3518219820Sjeff	case IB_CM_MRA_REP_RCVD:
3519219820Sjeff	case IB_CM_ESTABLISHED:
3520219820Sjeff		*qp_attr_mask = IB_QP_STATE | IB_QP_AV | IB_QP_PATH_MTU |
3521219820Sjeff				IB_QP_DEST_QPN | IB_QP_RQ_PSN;
3522219820Sjeff		qp_attr->ah_attr = cm_id_priv->av.ah_attr;
3523219820Sjeff		qp_attr->path_mtu = cm_id_priv->path_mtu;
3524219820Sjeff		qp_attr->dest_qp_num = be32_to_cpu(cm_id_priv->remote_qpn);
3525219820Sjeff		qp_attr->rq_psn = be32_to_cpu(cm_id_priv->rq_psn);
3526219820Sjeff		if (cm_id_priv->qp_type == IB_QPT_RC) {
3527219820Sjeff			*qp_attr_mask |= IB_QP_MAX_DEST_RD_ATOMIC |
3528219820Sjeff					 IB_QP_MIN_RNR_TIMER;
3529219820Sjeff			qp_attr->max_dest_rd_atomic =
3530219820Sjeff					cm_id_priv->responder_resources;
3531219820Sjeff			qp_attr->min_rnr_timer = 0;
3532219820Sjeff		}
3533219820Sjeff		if (cm_id_priv->alt_av.ah_attr.dlid) {
3534219820Sjeff			*qp_attr_mask |= IB_QP_ALT_PATH;
3535219820Sjeff			qp_attr->alt_port_num = cm_id_priv->alt_av.port->port_num;
3536219820Sjeff			qp_attr->alt_pkey_index = cm_id_priv->alt_av.pkey_index;
3537219820Sjeff			qp_attr->alt_timeout = cm_id_priv->alt_av.timeout;
3538219820Sjeff			qp_attr->alt_ah_attr = cm_id_priv->alt_av.ah_attr;
3539219820Sjeff		}
3540219820Sjeff		ret = 0;
3541219820Sjeff		break;
3542219820Sjeff	default:
3543219820Sjeff		ret = -EINVAL;
3544219820Sjeff		break;
3545219820Sjeff	}
3546219820Sjeff	spin_unlock_irqrestore(&cm_id_priv->lock, flags);
3547219820Sjeff	return ret;
3548219820Sjeff}
3549219820Sjeff
3550219820Sjeffstatic int cm_init_qp_rts_attr(struct cm_id_private *cm_id_priv,
3551219820Sjeff			       struct ib_qp_attr *qp_attr,
3552219820Sjeff			       int *qp_attr_mask)
3553219820Sjeff{
3554219820Sjeff	unsigned long flags;
3555219820Sjeff	int ret;
3556219820Sjeff
3557219820Sjeff	spin_lock_irqsave(&cm_id_priv->lock, flags);
3558219820Sjeff	switch (cm_id_priv->id.state) {
3559219820Sjeff	/* Allow transition to RTS before sending REP */
3560219820Sjeff	case IB_CM_REQ_RCVD:
3561219820Sjeff	case IB_CM_MRA_REQ_SENT:
3562219820Sjeff
3563219820Sjeff	case IB_CM_REP_RCVD:
3564219820Sjeff	case IB_CM_MRA_REP_SENT:
3565219820Sjeff	case IB_CM_REP_SENT:
3566219820Sjeff	case IB_CM_MRA_REP_RCVD:
3567219820Sjeff	case IB_CM_ESTABLISHED:
3568219820Sjeff		if (cm_id_priv->id.lap_state == IB_CM_LAP_UNINIT) {
3569219820Sjeff			*qp_attr_mask = IB_QP_STATE | IB_QP_SQ_PSN;
3570219820Sjeff			qp_attr->sq_psn = be32_to_cpu(cm_id_priv->sq_psn);
3571219820Sjeff			if (cm_id_priv->qp_type == IB_QPT_RC) {
3572219820Sjeff				*qp_attr_mask |= IB_QP_TIMEOUT | IB_QP_RETRY_CNT |
3573219820Sjeff						 IB_QP_RNR_RETRY |
3574219820Sjeff						 IB_QP_MAX_QP_RD_ATOMIC;
3575219820Sjeff				qp_attr->timeout = cm_id_priv->av.timeout;
3576219820Sjeff				qp_attr->retry_cnt = cm_id_priv->retry_count;
3577219820Sjeff				qp_attr->rnr_retry = cm_id_priv->rnr_retry_count;
3578219820Sjeff				qp_attr->max_rd_atomic =
3579219820Sjeff					cm_id_priv->initiator_depth;
3580219820Sjeff			}
3581219820Sjeff			if (cm_id_priv->alt_av.ah_attr.dlid) {
3582219820Sjeff				*qp_attr_mask |= IB_QP_PATH_MIG_STATE;
3583219820Sjeff				qp_attr->path_mig_state = IB_MIG_REARM;
3584219820Sjeff			}
3585219820Sjeff		} else {
3586219820Sjeff			*qp_attr_mask = IB_QP_ALT_PATH | IB_QP_PATH_MIG_STATE;
3587219820Sjeff			qp_attr->alt_port_num = cm_id_priv->alt_av.port->port_num;
3588219820Sjeff			qp_attr->alt_pkey_index = cm_id_priv->alt_av.pkey_index;
3589219820Sjeff			qp_attr->alt_timeout = cm_id_priv->alt_av.timeout;
3590219820Sjeff			qp_attr->alt_ah_attr = cm_id_priv->alt_av.ah_attr;
3591219820Sjeff			qp_attr->path_mig_state = IB_MIG_REARM;
3592219820Sjeff		}
3593219820Sjeff		ret = 0;
3594219820Sjeff		break;
3595219820Sjeff	default:
3596219820Sjeff		ret = -EINVAL;
3597219820Sjeff		break;
3598219820Sjeff	}
3599219820Sjeff	spin_unlock_irqrestore(&cm_id_priv->lock, flags);
3600219820Sjeff	return ret;
3601219820Sjeff}
3602219820Sjeff
3603219820Sjeffint ib_cm_init_qp_attr(struct ib_cm_id *cm_id,
3604219820Sjeff		       struct ib_qp_attr *qp_attr,
3605219820Sjeff		       int *qp_attr_mask)
3606219820Sjeff{
3607219820Sjeff	struct cm_id_private *cm_id_priv;
3608219820Sjeff	int ret;
3609219820Sjeff
3610219820Sjeff	cm_id_priv = container_of(cm_id, struct cm_id_private, id);
3611219820Sjeff	switch (qp_attr->qp_state) {
3612219820Sjeff	case IB_QPS_INIT:
3613219820Sjeff		ret = cm_init_qp_init_attr(cm_id_priv, qp_attr, qp_attr_mask);
3614219820Sjeff		break;
3615219820Sjeff	case IB_QPS_RTR:
3616219820Sjeff		ret = cm_init_qp_rtr_attr(cm_id_priv, qp_attr, qp_attr_mask);
3617219820Sjeff		break;
3618219820Sjeff	case IB_QPS_RTS:
3619219820Sjeff		ret = cm_init_qp_rts_attr(cm_id_priv, qp_attr, qp_attr_mask);
3620219820Sjeff		break;
3621219820Sjeff	default:
3622219820Sjeff		ret = -EINVAL;
3623219820Sjeff		break;
3624219820Sjeff	}
3625219820Sjeff	return ret;
3626219820Sjeff}
3627219820SjeffEXPORT_SYMBOL(ib_cm_init_qp_attr);
3628219820Sjeff
3629219820Sjeffstatic void cm_get_ack_delay(struct cm_device *cm_dev)
3630219820Sjeff{
3631219820Sjeff	struct ib_device_attr attr;
3632219820Sjeff
3633219820Sjeff	if (ib_query_device(cm_dev->ib_device, &attr))
3634219820Sjeff		cm_dev->ack_delay = 0; /* acks will rely on packet life time */
3635219820Sjeff	else
3636219820Sjeff		cm_dev->ack_delay = attr.local_ca_ack_delay;
3637219820Sjeff}
3638219820Sjeff
3639219820Sjeffstatic ssize_t cm_show_counter(struct kobject *obj, struct attribute *attr,
3640219820Sjeff			       char *buf)
3641219820Sjeff{
3642219820Sjeff	struct cm_counter_group *group;
3643219820Sjeff	struct cm_counter_attribute *cm_attr;
3644219820Sjeff
3645219820Sjeff	group = container_of(obj, struct cm_counter_group, obj);
3646219820Sjeff	cm_attr = container_of(attr, struct cm_counter_attribute, attr);
3647219820Sjeff
3648219820Sjeff	return sprintf(buf, "%ld\n",
3649219820Sjeff		       atomic_long_read(&group->counter[cm_attr->index]));
3650219820Sjeff}
3651219820Sjeff
3652219820Sjeffstatic struct sysfs_ops cm_counter_ops = {
3653219820Sjeff	.show = cm_show_counter
3654219820Sjeff};
3655219820Sjeff
3656219820Sjeffstatic struct kobj_type cm_counter_obj_type = {
3657219820Sjeff	.sysfs_ops = &cm_counter_ops,
3658219820Sjeff	.default_attrs = cm_counter_default_attrs
3659219820Sjeff};
3660219820Sjeff
3661219820Sjeffstatic void cm_release_port_obj(struct kobject *obj)
3662219820Sjeff{
3663219820Sjeff	struct cm_port *cm_port;
3664219820Sjeff
3665219820Sjeff	cm_port = container_of(obj, struct cm_port, port_obj);
3666219820Sjeff	kfree(cm_port);
3667219820Sjeff}
3668219820Sjeff
3669219820Sjeffstatic struct kobj_type cm_port_obj_type = {
3670219820Sjeff	.release = cm_release_port_obj
3671219820Sjeff};
3672219820Sjeff
3673219820Sjeffstruct class cm_class = {
3674219820Sjeff	.name    = "infiniband_cm",
3675219820Sjeff};
3676219820SjeffEXPORT_SYMBOL(cm_class);
3677219820Sjeff
3678219820Sjeffstatic int cm_create_port_fs(struct cm_port *port)
3679219820Sjeff{
3680219820Sjeff	int i, ret;
3681219820Sjeff
3682219820Sjeff	ret = kobject_init_and_add(&port->port_obj, &cm_port_obj_type,
3683219820Sjeff				   &port->cm_dev->device->kobj,
3684219820Sjeff				   "%d", port->port_num);
3685219820Sjeff	if (ret) {
3686219820Sjeff		kfree(port);
3687219820Sjeff		return ret;
3688219820Sjeff	}
3689219820Sjeff
3690219820Sjeff	for (i = 0; i < CM_COUNTER_GROUPS; i++) {
3691219820Sjeff		ret = kobject_init_and_add(&port->counter_group[i].obj,
3692219820Sjeff					   &cm_counter_obj_type,
3693219820Sjeff					   &port->port_obj,
3694219820Sjeff					   "%s", counter_group_names[i]);
3695219820Sjeff		if (ret)
3696219820Sjeff			goto error;
3697219820Sjeff	}
3698219820Sjeff
3699219820Sjeff	return 0;
3700219820Sjeff
3701219820Sjefferror:
3702219820Sjeff	while (i--)
3703219820Sjeff		kobject_put(&port->counter_group[i].obj);
3704219820Sjeff	kobject_put(&port->port_obj);
3705219820Sjeff	return ret;
3706219820Sjeff
3707219820Sjeff}
3708219820Sjeff
3709219820Sjeffstatic void cm_remove_port_fs(struct cm_port *port)
3710219820Sjeff{
3711219820Sjeff	int i;
3712219820Sjeff
3713219820Sjeff	for (i = 0; i < CM_COUNTER_GROUPS; i++)
3714219820Sjeff		kobject_put(&port->counter_group[i].obj);
3715219820Sjeff
3716219820Sjeff	kobject_put(&port->port_obj);
3717219820Sjeff}
3718219820Sjeff
3719219820Sjeffstatic void cm_add_one(struct ib_device *ib_device)
3720219820Sjeff{
3721219820Sjeff	struct cm_device *cm_dev;
3722219820Sjeff	struct cm_port *port;
3723219820Sjeff	struct ib_mad_reg_req reg_req = {
3724219820Sjeff		.mgmt_class = IB_MGMT_CLASS_CM,
3725219820Sjeff		.mgmt_class_version = IB_CM_CLASS_VERSION
3726219820Sjeff	};
3727219820Sjeff	struct ib_port_modify port_modify = {
3728219820Sjeff		.set_port_cap_mask = IB_PORT_CM_SUP
3729219820Sjeff	};
3730219820Sjeff	unsigned long flags;
3731219820Sjeff	int ret;
3732219820Sjeff	u8 i;
3733219820Sjeff
3734219820Sjeff	if (rdma_node_get_transport(ib_device->node_type) != RDMA_TRANSPORT_IB)
3735219820Sjeff		return;
3736219820Sjeff
3737219820Sjeff	cm_dev = kzalloc(sizeof(*cm_dev) + sizeof(*port) *
3738219820Sjeff			 ib_device->phys_port_cnt, GFP_KERNEL);
3739219820Sjeff	if (!cm_dev)
3740219820Sjeff		return;
3741219820Sjeff
3742219820Sjeff	cm_dev->ib_device = ib_device;
3743219820Sjeff	cm_get_ack_delay(cm_dev);
3744219820Sjeff
3745219820Sjeff	cm_dev->device = device_create(&cm_class, &ib_device->dev,
3746219820Sjeff				       MKDEV(0, 0), NULL,
3747219820Sjeff				       "%s", ib_device->name);
3748219820Sjeff	if (!cm_dev->device) {
3749219820Sjeff		kfree(cm_dev);
3750219820Sjeff		return;
3751219820Sjeff	}
3752219820Sjeff
3753219820Sjeff	set_bit(IB_MGMT_METHOD_SEND, reg_req.method_mask);
3754219820Sjeff	for (i = 1; i <= ib_device->phys_port_cnt; i++) {
3755219820Sjeff		port = kzalloc(sizeof *port, GFP_KERNEL);
3756219820Sjeff		if (!port)
3757219820Sjeff			goto error1;
3758219820Sjeff
3759219820Sjeff		cm_dev->port[i-1] = port;
3760219820Sjeff		port->cm_dev = cm_dev;
3761219820Sjeff		port->port_num = i;
3762219820Sjeff
3763219820Sjeff		ret = cm_create_port_fs(port);
3764219820Sjeff		if (ret)
3765219820Sjeff			goto error1;
3766219820Sjeff
3767219820Sjeff		port->mad_agent = ib_register_mad_agent(ib_device, i,
3768219820Sjeff							IB_QPT_GSI,
3769219820Sjeff							&reg_req,
3770219820Sjeff							0,
3771219820Sjeff							cm_send_handler,
3772219820Sjeff							cm_recv_handler,
3773219820Sjeff							port);
3774219820Sjeff		if (IS_ERR(port->mad_agent))
3775219820Sjeff			goto error2;
3776219820Sjeff
3777219820Sjeff		ret = ib_modify_port(ib_device, i, 0, &port_modify);
3778219820Sjeff		if (ret)
3779219820Sjeff			goto error3;
3780219820Sjeff	}
3781219820Sjeff	ib_set_client_data(ib_device, &cm_client, cm_dev);
3782219820Sjeff
3783219820Sjeff	write_lock_irqsave(&cm.device_lock, flags);
3784219820Sjeff	list_add_tail(&cm_dev->list, &cm.device_list);
3785219820Sjeff	write_unlock_irqrestore(&cm.device_lock, flags);
3786219820Sjeff	return;
3787219820Sjeff
3788219820Sjefferror3:
3789219820Sjeff	ib_unregister_mad_agent(port->mad_agent);
3790219820Sjefferror2:
3791219820Sjeff	cm_remove_port_fs(port);
3792219820Sjefferror1:
3793219820Sjeff	port_modify.set_port_cap_mask = 0;
3794219820Sjeff	port_modify.clr_port_cap_mask = IB_PORT_CM_SUP;
3795219820Sjeff	while (--i) {
3796219820Sjeff		port = cm_dev->port[i-1];
3797219820Sjeff		ib_modify_port(ib_device, port->port_num, 0, &port_modify);
3798219820Sjeff		ib_unregister_mad_agent(port->mad_agent);
3799219820Sjeff		cm_remove_port_fs(port);
3800219820Sjeff	}
3801219820Sjeff	device_unregister(cm_dev->device);
3802219820Sjeff	kfree(cm_dev);
3803219820Sjeff}
3804219820Sjeff
3805219820Sjeffstatic void cm_remove_one(struct ib_device *ib_device)
3806219820Sjeff{
3807219820Sjeff	struct cm_device *cm_dev;
3808219820Sjeff	struct cm_port *port;
3809219820Sjeff	struct ib_port_modify port_modify = {
3810219820Sjeff		.clr_port_cap_mask = IB_PORT_CM_SUP
3811219820Sjeff	};
3812219820Sjeff	unsigned long flags;
3813219820Sjeff	int i;
3814219820Sjeff
3815219820Sjeff	cm_dev = ib_get_client_data(ib_device, &cm_client);
3816219820Sjeff	if (!cm_dev)
3817219820Sjeff		return;
3818219820Sjeff
3819219820Sjeff	write_lock_irqsave(&cm.device_lock, flags);
3820219820Sjeff	list_del(&cm_dev->list);
3821219820Sjeff	write_unlock_irqrestore(&cm.device_lock, flags);
3822219820Sjeff
3823219820Sjeff	for (i = 1; i <= ib_device->phys_port_cnt; i++) {
3824219820Sjeff		port = cm_dev->port[i-1];
3825219820Sjeff		ib_modify_port(ib_device, port->port_num, 0, &port_modify);
3826219820Sjeff		ib_unregister_mad_agent(port->mad_agent);
3827219820Sjeff		flush_workqueue(cm.wq);
3828219820Sjeff		cm_remove_port_fs(port);
3829219820Sjeff	}
3830219820Sjeff	device_unregister(cm_dev->device);
3831219820Sjeff	kfree(cm_dev);
3832219820Sjeff}
3833219820Sjeff
3834219820Sjeffstatic int __init ib_cm_init(void)
3835219820Sjeff{
3836219820Sjeff	int ret;
3837219820Sjeff
3838219820Sjeff	memset(&cm, 0, sizeof cm);
3839219820Sjeff	INIT_LIST_HEAD(&cm.device_list);
3840219820Sjeff	rwlock_init(&cm.device_lock);
3841219820Sjeff	spin_lock_init(&cm.lock);
3842219820Sjeff	cm.listen_service_table = RB_ROOT;
3843219820Sjeff	cm.listen_service_id = be64_to_cpu(IB_CM_ASSIGN_SERVICE_ID);
3844219820Sjeff	cm.remote_id_table = RB_ROOT;
3845219820Sjeff	cm.remote_qp_table = RB_ROOT;
3846219820Sjeff	cm.remote_sidr_table = RB_ROOT;
3847219820Sjeff	idr_init(&cm.local_id_table);
3848219820Sjeff	get_random_bytes(&cm.random_id_operand, sizeof cm.random_id_operand);
3849219820Sjeff	idr_pre_get(&cm.local_id_table, GFP_KERNEL);
3850219820Sjeff	INIT_LIST_HEAD(&cm.timewait_list);
3851219820Sjeff
3852219820Sjeff	ret = class_register(&cm_class);
3853219820Sjeff	if (ret)
3854219820Sjeff		return -ENOMEM;
3855219820Sjeff
3856219820Sjeff	cm.wq = create_workqueue("ib_cm");
3857219820Sjeff	if (!cm.wq) {
3858219820Sjeff		ret = -ENOMEM;
3859219820Sjeff		goto error1;
3860219820Sjeff	}
3861219820Sjeff
3862219820Sjeff	ret = ib_register_client(&cm_client);
3863219820Sjeff	if (ret)
3864219820Sjeff		goto error2;
3865219820Sjeff
3866219820Sjeff	return 0;
3867219820Sjefferror2:
3868219820Sjeff	destroy_workqueue(cm.wq);
3869219820Sjefferror1:
3870219820Sjeff	class_unregister(&cm_class);
3871219820Sjeff	return ret;
3872219820Sjeff}
3873219820Sjeff
3874219820Sjeffstatic void __exit ib_cm_cleanup(void)
3875219820Sjeff{
3876219820Sjeff	struct cm_timewait_info *timewait_info, *tmp;
3877219820Sjeff
3878219820Sjeff	spin_lock_irq(&cm.lock);
3879219820Sjeff	list_for_each_entry(timewait_info, &cm.timewait_list, list)
3880219820Sjeff		cancel_delayed_work(&timewait_info->work.work);
3881219820Sjeff	spin_unlock_irq(&cm.lock);
3882219820Sjeff
3883219820Sjeff	ib_unregister_client(&cm_client);
3884219820Sjeff	destroy_workqueue(cm.wq);
3885219820Sjeff
3886219820Sjeff	list_for_each_entry_safe(timewait_info, tmp, &cm.timewait_list, list) {
3887219820Sjeff		list_del(&timewait_info->list);
3888219820Sjeff		kfree(timewait_info);
3889219820Sjeff	}
3890219820Sjeff
3891219820Sjeff	class_unregister(&cm_class);
3892219820Sjeff	idr_destroy(&cm.local_id_table);
3893219820Sjeff}
3894219820Sjeff
3895219820Sjeffmodule_init_order(ib_cm_init, SI_ORDER_SECOND);
3896271127Shselaskymodule_exit_order(ib_cm_cleanup, SI_ORDER_FIRST);
3897219820Sjeff
3898