]> CyberLeo.Net >> Repos - FreeBSD/releng/9.2.git/blob - sys/contrib/rdma/rdma_iwcm.c
- Copy stable/9 to releng/9.2 as part of the 9.2-RELEASE cycle.
[FreeBSD/releng/9.2.git] / sys / contrib / rdma / rdma_iwcm.c
1 /*
2  * Copyright (c) 2004, 2005 Intel Corporation.  All rights reserved.
3  * Copyright (c) 2004 Topspin Corporation.  All rights reserved.
4  * Copyright (c) 2004, 2005 Voltaire Corporation.  All rights reserved.
5  * Copyright (c) 2005 Sun Microsystems, Inc. All rights reserved.
6  * Copyright (c) 2005 Open Grid Computing, Inc. All rights reserved.
7  * Copyright (c) 2005 Network Appliance, Inc. All rights reserved.
8  *
9  * This software is available to you under a choice of one of two
10  * licenses.  You may choose to be licensed under the terms of the GNU
11  * General Public License (GPL) Version 2, available from the file
12  * COPYING in the main directory of this source tree, or the
13  * OpenIB.org BSD license below:
14  *
15  *     Redistribution and use in source and binary forms, with or
16  *     without modification, are permitted provided that the following
17  *     conditions are met:
18  *
19  *      - Redistributions of source code must retain the above
20  *        copyright notice, this list of conditions and the following
21  *        disclaimer.
22  *
23  *      - Redistributions in binary form must reproduce the above
24  *        copyright notice, this list of conditions and the following
25  *        disclaimer in the documentation and/or other materials
26  *        provided with the distribution.
27  *
28  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
29  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
30  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
31  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
32  * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
33  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
34  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
35  * SOFTWARE.
36  *
37  */
38
39 #include <sys/cdefs.h>
40 __FBSDID("$FreeBSD$");
41
42 #include <sys/types.h>
43 #include <sys/param.h>
44 #include <sys/systm.h>
45 #include <sys/proc.h>
46 #include <sys/kernel.h>
47 #include <sys/libkern.h>
48 #include <sys/socket.h>
49 #include <sys/socketvar.h>
50 #include <sys/module.h>
51 #include <sys/lock.h>
52 #include <sys/mutex.h>
53 #include <sys/rwlock.h>
54 #include <sys/queue.h>
55 #include <sys/taskqueue.h>
56 #include <sys/priv.h>
57 #include <sys/syslog.h>
58 #include <sys/malloc.h>
59
60 #include <netinet/in.h>
61 #include <netinet/in_pcb.h>
62
63 #include <contrib/rdma/iw_cm.h>
64
65 enum iw_cm_state {
66         IW_CM_STATE_IDLE,             /* unbound, inactive */
67         IW_CM_STATE_LISTEN,           /* listen waiting for connect */
68         IW_CM_STATE_CONN_RECV,        /* inbound waiting for user accept */
69         IW_CM_STATE_CONN_SENT,        /* outbound waiting for peer accept */
70         IW_CM_STATE_ESTABLISHED,      /* established */
71         IW_CM_STATE_CLOSING,          /* disconnect */
72         IW_CM_STATE_DESTROYING        /* object being deleted */
73 };
74
75 struct iwcm_id_private {
76         struct iw_cm_id id;
77         enum iw_cm_state state;
78         unsigned long flags;
79         struct ib_qp *qp;
80         void * destroy_comp;
81         void * connect_wait;
82         TAILQ_HEAD(, iwcm_work) work_list;
83         struct mtx lock;
84         volatile int refcount;
85         TAILQ_HEAD(, iwcm_work) work_free_list;
86 };
87
88 #define IWCM_F_CALLBACK_DESTROY   1
89 #define IWCM_F_CONNECT_WAIT       2
90
91 static struct taskqueue *iwcm_wq;
92 struct iwcm_work {
93         struct task task;
94         struct iwcm_id_private *cm_id;
95         TAILQ_ENTRY(iwcm_work) list;
96         struct iw_cm_event event;
97         TAILQ_ENTRY(iwcm_work) free_list;
98 };
99
100 /*
101  * The following services provide a mechanism for pre-allocating iwcm_work
102  * elements.  The design pre-allocates them  based on the cm_id type:
103  *      LISTENING IDS:  Get enough elements preallocated to handle the
104  *                      listen backlog.
105  *      ACTIVE IDS:     4: CONNECT_REPLY, ESTABLISHED, DISCONNECT, CLOSE
106  *      PASSIVE IDS:    3: ESTABLISHED, DISCONNECT, CLOSE
107  *
108  * Allocating them in connect and listen avoids having to deal
109  * with allocation failures on the event upcall from the provider (which
110  * is called in the interrupt context).
111  *
112  * One exception is when creating the cm_id for incoming connection requests.
113  * There are two cases:
114  * 1) in the event upcall, cm_event_handler(), for a listening cm_id.  If
115  *    the backlog is exceeded, then no more connection request events will
116  *    be processed.  cm_event_handler() returns ENOMEM in this case.  Its up
117  *    to the provider to reject the connection request.
118  * 2) in the connection request workqueue handler, cm_conn_req_handler().
119  *    If work elements cannot be allocated for the new connect request cm_id,
120  *    then IWCM will call the provider reject method.  This is ok since
121  *    cm_conn_req_handler() runs in the workqueue thread context.
122  */
123
124 static struct iwcm_work *get_work(struct iwcm_id_private *cm_id_priv)
125 {
126         struct iwcm_work *work;
127
128         if (TAILQ_EMPTY(&cm_id_priv->work_free_list))
129                 return NULL;
130         work = TAILQ_FIRST(&cm_id_priv->work_free_list);
131         TAILQ_REMOVE(&cm_id_priv->work_free_list, work, free_list);
132         return work;
133 }
134
135 static void put_work(struct iwcm_work *work)
136 {
137         TAILQ_INSERT_HEAD(&work->cm_id->work_free_list, work, free_list);
138 }
139
140 static void dealloc_work_entries(struct iwcm_id_private *cm_id_priv)
141 {
142         struct iwcm_work *e, *tmp;
143
144         TAILQ_FOREACH_SAFE(e, &cm_id_priv->work_free_list, free_list, tmp)
145                 free(e, M_DEVBUF);
146 }
147
148 static int alloc_work_entries(struct iwcm_id_private *cm_id_priv, int count)
149 {
150         struct iwcm_work *work;
151
152         PANIC_IF(!TAILQ_EMPTY(&cm_id_priv->work_free_list));
153         while (count--) {
154                 work = malloc(sizeof(struct iwcm_work), M_DEVBUF, M_NOWAIT);
155                 if (!work) {
156                         dealloc_work_entries(cm_id_priv);
157                         return (ENOMEM);
158                 }
159                 work->cm_id = cm_id_priv;
160                 put_work(work);
161         }
162         return 0;
163 }
164
165 /*
166  * Save private data from incoming connection requests to
167  * iw_cm_event, so the low level driver doesn't have to. Adjust
168  * the event ptr to point to the local copy.
169  */
170 static int copy_private_data(struct iw_cm_event *event)
171 {
172         void *p;
173
174         p = malloc(event->private_data_len, M_DEVBUF, M_NOWAIT);
175         if (!p)
176                 return (ENOMEM);
177         bcopy(event->private_data, p, event->private_data_len);
178         event->private_data = p;
179         return 0;
180 }
181
182 static void free_cm_id(struct iwcm_id_private *cm_id_priv)
183 {
184         dealloc_work_entries(cm_id_priv);
185         free(cm_id_priv, M_DEVBUF);
186 }
187
188 /*
189  * Release a reference on cm_id. If the last reference is being
190  * released, enable the waiting thread (in iw_destroy_cm_id) to
191  * get woken up, and return 1 if a thread is already waiting.
192  */
193 static int iwcm_deref_id(struct iwcm_id_private *cm_id_priv)
194 {
195         mtx_lock(&cm_id_priv->lock);
196         PANIC_IF(atomic_load_acq_int(&cm_id_priv->refcount)==0);
197         if (atomic_fetchadd_int(&cm_id_priv->refcount, -1) == 1) {
198                 PANIC_IF(!TAILQ_EMPTY(&cm_id_priv->work_list));
199                 wakeup(&cm_id_priv->destroy_comp);
200                 mtx_unlock(&cm_id_priv->lock);
201                 return 1;
202         }
203         mtx_unlock(&cm_id_priv->lock);
204
205         return 0;
206 }
207
208 static void add_ref(struct iw_cm_id *cm_id)
209 {
210         struct iwcm_id_private *cm_id_priv;
211         cm_id_priv = container_of(cm_id, struct iwcm_id_private, id);
212         mtx_lock(&cm_id_priv->lock);
213         atomic_add_int(&cm_id_priv->refcount, 1);
214         mtx_unlock(&cm_id_priv->lock);
215 }
216
217 static void rem_ref(struct iw_cm_id *cm_id)
218 {
219         struct iwcm_id_private *cm_id_priv;
220         cm_id_priv = container_of(cm_id, struct iwcm_id_private, id);
221         if (iwcm_deref_id(cm_id_priv) &&
222             isset(&cm_id_priv->flags, IWCM_F_CALLBACK_DESTROY)) {
223                 PANIC_IF(!TAILQ_EMPTY(&cm_id_priv->work_list));
224                 free_cm_id(cm_id_priv);
225         }
226 }
227
228 static int cm_event_handler(struct iw_cm_id *cm_id, struct iw_cm_event *event);
229
230 struct iw_cm_id *iw_create_cm_id(struct ib_device *device,
231                                  struct socket *so,
232                                  iw_cm_handler cm_handler,
233                                  void *context)
234 {
235         struct iwcm_id_private *cm_id_priv;
236
237         KASSERT(so, ("iw_create_cm_id called with NULL socket!"));
238         cm_id_priv = malloc(sizeof(*cm_id_priv), M_DEVBUF, M_NOWAIT);
239         if (!cm_id_priv)
240                 return ERR_PTR(ENOMEM);
241         bzero(cm_id_priv, sizeof *cm_id_priv);
242
243         cm_id_priv->state = IW_CM_STATE_IDLE;
244         cm_id_priv->id.device = device;
245         cm_id_priv->id.cm_handler = cm_handler;
246         cm_id_priv->id.context = context;
247         cm_id_priv->id.event_handler = cm_event_handler;
248         cm_id_priv->id.add_ref = add_ref;
249         cm_id_priv->id.rem_ref = rem_ref;
250         cm_id_priv->id.so = so;
251         mtx_init(&cm_id_priv->lock, "cm_id_priv", NULL, MTX_DUPOK|MTX_DEF);
252         atomic_store_rel_int(&cm_id_priv->refcount, 1);
253         TAILQ_INIT(&cm_id_priv->work_list);
254         TAILQ_INIT(&cm_id_priv->work_free_list);
255
256         return &cm_id_priv->id;
257 }
258
259
260 static int iwcm_modify_qp_err(struct ib_qp *qp)
261 {
262         struct ib_qp_attr qp_attr;
263
264         if (!qp)
265                 return (EINVAL);
266
267         qp_attr.qp_state = IB_QPS_ERR;
268         return ib_modify_qp(qp, &qp_attr, IB_QP_STATE);
269 }
270
271 /*
272  * This is really the RDMAC CLOSING state. It is most similar to the
273  * IB SQD QP state.
274  */
275 static int iwcm_modify_qp_sqd(struct ib_qp *qp)
276 {
277         struct ib_qp_attr qp_attr;
278
279         PANIC_IF(qp == NULL);
280         qp_attr.qp_state = IB_QPS_SQD;
281         return ib_modify_qp(qp, &qp_attr, IB_QP_STATE);
282 }
283
284 /*
285  * CM_ID <-- CLOSING
286  *
287  * Block if a passive or active connection is currently being processed. Then
288  * process the event as follows:
289  * - If we are ESTABLISHED, move to CLOSING and modify the QP state
290  *   based on the abrupt flag
291  * - If the connection is already in the CLOSING or IDLE state, the peer is
292  *   disconnecting concurrently with us and we've already seen the
293  *   DISCONNECT event -- ignore the request and return 0
294  * - Disconnect on a listening endpoint returns EINVAL
295  */
296 int iw_cm_disconnect(struct iw_cm_id *cm_id, int abrupt)
297 {
298         struct iwcm_id_private *cm_id_priv;
299         int ret = 0;
300         struct ib_qp *qp = NULL;
301
302         cm_id_priv = container_of(cm_id, struct iwcm_id_private, id);
303         /* Wait if we're currently in a connect or accept downcall */
304         mtx_lock(&cm_id_priv->lock);
305         if (isset(&cm_id_priv->flags, IWCM_F_CONNECT_WAIT))
306                 msleep(&cm_id_priv->connect_wait, &cm_id_priv->lock, 0, "iwcm connect1", 0);
307
308         switch (cm_id_priv->state) {
309         case IW_CM_STATE_ESTABLISHED:
310                 cm_id_priv->state = IW_CM_STATE_CLOSING;
311
312                 /* QP could be <nul> for user-mode client */
313                 if (cm_id_priv->qp)
314                         qp = cm_id_priv->qp;
315                 else
316                         ret = EINVAL;
317                 break;
318         case IW_CM_STATE_LISTEN:
319                 ret = EINVAL;
320                 break;
321         case IW_CM_STATE_CLOSING:
322                 /* remote peer closed first */
323         case IW_CM_STATE_IDLE:
324                 /* accept or connect returned !0 */
325                 break;
326         case IW_CM_STATE_CONN_RECV:
327                 /*
328                  * App called disconnect before/without calling accept after
329                  * connect_request event delivered.
330                  */
331                 break;
332         case IW_CM_STATE_CONN_SENT:
333                 /* Can only get here if wait above fails */
334         default:
335                 panic("just cuz");
336         }
337         mtx_unlock(&cm_id_priv->lock);
338
339         if (qp) {
340                 if (abrupt)
341                         ret = iwcm_modify_qp_err(qp);
342                 else
343                         ret = iwcm_modify_qp_sqd(qp);
344
345                 /*
346                  * If both sides are disconnecting the QP could
347                  * already be in ERR or SQD states
348                  */
349                 ret = 0;
350         }
351
352         return ret;
353 }
354
355 /*
356  * CM_ID <-- DESTROYING
357  *
358  * Clean up all resources associated with the connection and release
359  * the initial reference taken by iw_create_cm_id.
360  */
361 static void destroy_cm_id(struct iw_cm_id *cm_id)
362 {
363         struct iwcm_id_private *cm_id_priv;
364         int ret;
365
366         cm_id_priv = container_of(cm_id, struct iwcm_id_private, id);
367         /*
368          * Wait if we're currently in a connect or accept downcall. A
369          * listening endpoint should never block here.
370          */
371         mtx_lock(&cm_id_priv->lock);
372         if (isset(&cm_id_priv->flags, IWCM_F_CONNECT_WAIT))
373                 msleep(&cm_id_priv->connect_wait, &cm_id_priv->lock, 0, "iwcm connect2", 0);
374
375         switch (cm_id_priv->state) {
376         case IW_CM_STATE_LISTEN:
377                 cm_id_priv->state = IW_CM_STATE_DESTROYING;
378                 mtx_unlock(&cm_id_priv->lock);
379                 /* destroy the listening endpoint */
380                 ret = cm_id->device->iwcm->destroy_listen(cm_id);
381                 mtx_lock(&cm_id_priv->lock);
382                 break;
383         case IW_CM_STATE_ESTABLISHED:
384                 cm_id_priv->state = IW_CM_STATE_DESTROYING;
385                 mtx_unlock(&cm_id_priv->lock);
386                 /* Abrupt close of the connection */
387                 (void)iwcm_modify_qp_err(cm_id_priv->qp);
388                 mtx_lock(&cm_id_priv->lock);
389                 break;
390         case IW_CM_STATE_IDLE:
391         case IW_CM_STATE_CLOSING:
392                 cm_id_priv->state = IW_CM_STATE_DESTROYING;
393                 break;
394         case IW_CM_STATE_CONN_RECV:
395                 /*
396                  * App called destroy before/without calling accept after
397                  * receiving connection request event notification or
398                  * returned non zero from the event callback function.
399                  * In either case, must tell the provider to reject.
400                  */
401                 cm_id_priv->state = IW_CM_STATE_DESTROYING;
402                 break;
403         case IW_CM_STATE_CONN_SENT:
404         case IW_CM_STATE_DESTROYING:
405         default:
406                 panic("just cuz");
407                 break;
408         }
409         if (cm_id_priv->qp) {
410                 cm_id_priv->id.device->iwcm->rem_ref(cm_id_priv->qp);
411                 cm_id_priv->qp = NULL;
412         }
413         mtx_unlock(&cm_id_priv->lock);
414
415         (void)iwcm_deref_id(cm_id_priv);
416 }
417
418 /*
419  * This function is only called by the application thread and cannot
420  * be called by the event thread. The function will wait for all
421  * references to be released on the cm_id and then free the cm_id
422  * object.
423  */
424 void iw_destroy_cm_id(struct iw_cm_id *cm_id)
425 {
426         struct iwcm_id_private *cm_id_priv;
427
428         cm_id_priv = container_of(cm_id, struct iwcm_id_private, id);
429         PANIC_IF(isset(&cm_id_priv->flags, IWCM_F_CALLBACK_DESTROY));
430
431         destroy_cm_id(cm_id);
432
433         mtx_lock(&cm_id_priv->lock);
434         if (atomic_load_acq_int(&cm_id_priv->refcount))
435                 msleep(&cm_id_priv->destroy_comp, &cm_id_priv->lock, 0, "iwcm destroy", 0);
436         mtx_unlock(&cm_id_priv->lock);
437
438         free_cm_id(cm_id_priv);
439 }
440
441 /*
442  * CM_ID <-- LISTEN
443  *
444  * Start listening for connect requests. Generates one CONNECT_REQUEST
445  * event for each inbound connect request.
446  */
447 int iw_cm_listen(struct iw_cm_id *cm_id, int backlog)
448 {
449         struct iwcm_id_private *cm_id_priv;
450         int ret;
451
452         cm_id_priv = container_of(cm_id, struct iwcm_id_private, id);
453
454         ret = alloc_work_entries(cm_id_priv, backlog);
455         if (ret)
456                 return ret;
457
458         mtx_lock(&cm_id_priv->lock);
459         switch (cm_id_priv->state) {
460         case IW_CM_STATE_IDLE:
461                 cm_id_priv->state = IW_CM_STATE_LISTEN;
462                 mtx_unlock(&cm_id_priv->lock);
463                 ret = cm_id->device->iwcm->create_listen(cm_id, backlog);
464                 if (ret)
465                         cm_id_priv->state = IW_CM_STATE_IDLE;
466                 mtx_lock(&cm_id_priv->lock);
467                 break;
468         default:
469                 ret = EINVAL;
470         }
471         mtx_unlock(&cm_id_priv->lock);
472
473         return ret;
474 }
475
476 /*
477  * CM_ID <-- IDLE
478  *
479  * Rejects an inbound connection request. No events are generated.
480  */
481 int iw_cm_reject(struct iw_cm_id *cm_id,
482                  const void *private_data,
483                  u8 private_data_len)
484 {
485         struct iwcm_id_private *cm_id_priv;
486         int ret;
487
488         cm_id_priv = container_of(cm_id, struct iwcm_id_private, id);
489         setbit(&cm_id_priv->flags, IWCM_F_CONNECT_WAIT);
490
491         mtx_lock(&cm_id_priv->lock);
492         if (cm_id_priv->state != IW_CM_STATE_CONN_RECV) {
493                 clrbit(&cm_id_priv->flags, IWCM_F_CONNECT_WAIT);
494                 wakeup(&cm_id_priv->connect_wait);
495                 mtx_unlock(&cm_id_priv->lock);
496                 return (EINVAL);
497         }
498         cm_id_priv->state = IW_CM_STATE_IDLE;
499         mtx_unlock(&cm_id_priv->lock);
500
501         ret = cm_id->device->iwcm->reject(cm_id, private_data,
502                                           private_data_len);
503
504         mtx_lock(&cm_id_priv->lock);
505         clrbit(&cm_id_priv->flags, IWCM_F_CONNECT_WAIT);
506         wakeup(&cm_id_priv->connect_wait);
507         mtx_unlock(&cm_id_priv->lock);
508
509         return ret;
510 }
511
512 /*
513  * CM_ID <-- ESTABLISHED
514  *
515  * Accepts an inbound connection request and generates an ESTABLISHED
516  * event. Callers of iw_cm_disconnect and iw_destroy_cm_id will block
517  * until the ESTABLISHED event is received from the provider.
518  */
519 int iw_cm_accept(struct iw_cm_id *cm_id,
520                  struct iw_cm_conn_param *iw_param)
521 {
522         struct iwcm_id_private *cm_id_priv;
523         struct ib_qp *qp;
524         int ret;
525
526         cm_id_priv = container_of(cm_id, struct iwcm_id_private, id);
527         setbit(&cm_id_priv->flags, IWCM_F_CONNECT_WAIT);
528
529         mtx_lock(&cm_id_priv->lock);
530         if (cm_id_priv->state != IW_CM_STATE_CONN_RECV) {
531                 clrbit(&cm_id_priv->flags, IWCM_F_CONNECT_WAIT);
532                 wakeup(&cm_id_priv->connect_wait);
533                 mtx_unlock(&cm_id_priv->lock);
534                 
535                 return (EINVAL);
536         }
537         /* Get the ib_qp given the QPN */
538         qp = cm_id->device->iwcm->get_qp(cm_id->device, iw_param->qpn);
539         if (!qp) {
540                 mtx_unlock(&cm_id_priv->lock);
541                 return (EINVAL);
542         }
543         cm_id->device->iwcm->add_ref(qp);
544         cm_id_priv->qp = qp;
545         mtx_unlock(&cm_id_priv->lock);
546
547         ret = cm_id->device->iwcm->accept(cm_id, iw_param);
548         if (ret) {
549                 /* An error on accept precludes provider events */
550                 PANIC_IF(cm_id_priv->state != IW_CM_STATE_CONN_RECV);
551                 cm_id_priv->state = IW_CM_STATE_IDLE;
552                 mtx_lock(&cm_id_priv->lock);
553                 if (cm_id_priv->qp) {
554                         cm_id->device->iwcm->rem_ref(qp);
555                         cm_id_priv->qp = NULL;
556                 }
557                 clrbit(&cm_id_priv->flags, IWCM_F_CONNECT_WAIT);
558                 wakeup(&cm_id_priv->connect_wait);
559                 mtx_unlock(&cm_id_priv->lock);
560         }
561
562         return ret;
563 }
564
565 /*
566  * Active Side: CM_ID <-- CONN_SENT
567  *
568  * If successful, results in the generation of a CONNECT_REPLY
569  * event. iw_cm_disconnect and iw_cm_destroy will block until the
570  * CONNECT_REPLY event is received from the provider.
571  */
572 int iw_cm_connect(struct iw_cm_id *cm_id, struct iw_cm_conn_param *iw_param)
573 {
574         struct iwcm_id_private *cm_id_priv;
575         int ret;
576         struct ib_qp *qp;
577
578         cm_id_priv = container_of(cm_id, struct iwcm_id_private, id);
579
580         ret = alloc_work_entries(cm_id_priv, 4);
581         if (ret)
582                 return ret;
583
584         setbit(&cm_id_priv->flags, IWCM_F_CONNECT_WAIT);
585         mtx_lock(&cm_id_priv->lock);
586
587         if (cm_id_priv->state != IW_CM_STATE_IDLE) {
588                 clrbit(&cm_id_priv->flags, IWCM_F_CONNECT_WAIT); 
589                 wakeup(&cm_id_priv->connect_wait);
590                 mtx_unlock(&cm_id_priv->lock);
591                 
592                 return (EINVAL);
593         }
594
595         /* Get the ib_qp given the QPN */
596         qp = cm_id->device->iwcm->get_qp(cm_id->device, iw_param->qpn);
597         if (!qp) {
598                 mtx_unlock(&cm_id_priv->lock);
599                 return (EINVAL);
600         }
601         cm_id->device->iwcm->add_ref(qp);
602         cm_id_priv->qp = qp;
603         cm_id_priv->state = IW_CM_STATE_CONN_SENT;
604         mtx_unlock(&cm_id_priv->lock);
605
606         ret = cm_id->device->iwcm->connect(cm_id, iw_param);
607         if (ret) {
608                 mtx_lock(&cm_id_priv->lock);
609                 if (cm_id_priv->qp) {
610                         cm_id->device->iwcm->rem_ref(qp);
611                         cm_id_priv->qp = NULL;
612                 }
613                 PANIC_IF(cm_id_priv->state != IW_CM_STATE_CONN_SENT);
614                 cm_id_priv->state = IW_CM_STATE_IDLE;
615                 clrbit(&cm_id_priv->flags, IWCM_F_CONNECT_WAIT);
616                 wakeup(&cm_id_priv->connect_wait);
617                 mtx_unlock(&cm_id_priv->lock);
618                 
619         }
620
621         return ret;
622 }
623
624 /*
625  * Passive Side: new CM_ID <-- CONN_RECV
626  *
627  * Handles an inbound connect request. The function creates a new
628  * iw_cm_id to represent the new connection and inherits the client
629  * callback function and other attributes from the listening parent.
630  *
631  * The work item contains a pointer to the listen_cm_id and the event. The
632  * listen_cm_id contains the client cm_handler, context and
633  * device. These are copied when the device is cloned. The event
634  * contains the new four tuple.
635  *
636  * An error on the child should not affect the parent, so this
637  * function does not return a value.
638  */
639 static void cm_conn_req_handler(struct iwcm_id_private *listen_id_priv,
640                                 struct iw_cm_event *iw_event)
641 {
642         struct iw_cm_id *cm_id;
643         struct iwcm_id_private *cm_id_priv;
644         int ret;
645
646         /*
647          * The provider should never generate a connection request
648          * event with a bad status.
649          */
650         PANIC_IF(iw_event->status);
651
652         /*
653          * We could be destroying the listening id. If so, ignore this
654          * upcall.
655          */
656         mtx_lock(&listen_id_priv->lock);
657         if (listen_id_priv->state != IW_CM_STATE_LISTEN) {
658                 mtx_unlock(&listen_id_priv->lock);
659                 goto out;
660         }
661         mtx_unlock(&listen_id_priv->lock);
662
663         cm_id = iw_create_cm_id(listen_id_priv->id.device,
664                                 iw_event->so,
665                                 listen_id_priv->id.cm_handler,
666                                 listen_id_priv->id.context);
667         /* If the cm_id could not be created, ignore the request */
668         if (IS_ERR(cm_id))
669                 goto out;
670
671         cm_id->provider_data = iw_event->provider_data;
672         cm_id->local_addr = iw_event->local_addr;
673         cm_id->remote_addr = iw_event->remote_addr;
674
675         cm_id_priv = container_of(cm_id, struct iwcm_id_private, id);
676         cm_id_priv->state = IW_CM_STATE_CONN_RECV;
677
678         ret = alloc_work_entries(cm_id_priv, 3);
679         if (ret) {
680                 iw_cm_reject(cm_id, NULL, 0);
681                 iw_destroy_cm_id(cm_id);
682                 goto out;
683         }
684
685         /* Call the client CM handler */
686         ret = cm_id->cm_handler(cm_id, iw_event);
687         if (ret) {
688                 iw_cm_reject(cm_id, NULL, 0);
689                 setbit(&cm_id_priv->flags, IWCM_F_CALLBACK_DESTROY);
690                 
691                 destroy_cm_id(cm_id);
692                 if (atomic_load_acq_int(&cm_id_priv->refcount)==0)
693                         free_cm_id(cm_id_priv);
694         }
695
696 out:
697         if (iw_event->private_data_len)
698                 free(iw_event->private_data, M_DEVBUF);
699 }
700
701 /*
702  * Passive Side: CM_ID <-- ESTABLISHED
703  *
704  * The provider generated an ESTABLISHED event which means that
705  * the MPA negotion has completed successfully and we are now in MPA
706  * FPDU mode.
707  *
708  * This event can only be received in the CONN_RECV state. If the
709  * remote peer closed, the ESTABLISHED event would be received followed
710  * by the CLOSE event. If the app closes, it will block until we wake
711  * it up after processing this event.
712  */
713 static int cm_conn_est_handler(struct iwcm_id_private *cm_id_priv,
714                                struct iw_cm_event *iw_event)
715 {
716         int ret;
717
718         mtx_lock(&cm_id_priv->lock);
719
720         /*
721          * We clear the CONNECT_WAIT bit here to allow the callback
722          * function to call iw_cm_disconnect. Calling iw_destroy_cm_id
723          * from a callback handler is not allowed.
724          */
725         clrbit(&cm_id_priv->flags, IWCM_F_CONNECT_WAIT);
726         PANIC_IF(cm_id_priv->state != IW_CM_STATE_CONN_RECV);
727         cm_id_priv->state = IW_CM_STATE_ESTABLISHED;
728         ret = cm_id_priv->id.cm_handler(&cm_id_priv->id, iw_event);
729         wakeup(&cm_id_priv->connect_wait);
730         mtx_unlock(&cm_id_priv->lock);
731
732         return ret;
733 }
734
735 /*
736  * Active Side: CM_ID <-- ESTABLISHED
737  *
738  * The app has called connect and is waiting for the established event to
739  * post it's requests to the server. This event will wake up anyone
740  * blocked in iw_cm_disconnect or iw_destroy_id.
741  */
742 static int cm_conn_rep_handler(struct iwcm_id_private *cm_id_priv,
743                                struct iw_cm_event *iw_event)
744 {
745         int ret;
746
747         mtx_lock(&cm_id_priv->lock);
748         /*
749          * Clear the connect wait bit so a callback function calling
750          * iw_cm_disconnect will not wait and deadlock this thread
751          */
752         clrbit(&cm_id_priv->flags, IWCM_F_CONNECT_WAIT);
753         PANIC_IF(cm_id_priv->state != IW_CM_STATE_CONN_SENT);
754         if (iw_event->status == IW_CM_EVENT_STATUS_ACCEPTED) {
755                 cm_id_priv->id.local_addr = iw_event->local_addr;
756                 cm_id_priv->id.remote_addr = iw_event->remote_addr;
757                 cm_id_priv->state = IW_CM_STATE_ESTABLISHED;
758         } else {
759                 /* REJECTED or RESET */
760                 cm_id_priv->id.device->iwcm->rem_ref(cm_id_priv->qp);
761                 cm_id_priv->qp = NULL;
762                 cm_id_priv->state = IW_CM_STATE_IDLE;
763         }
764         mtx_unlock(&cm_id_priv->lock);
765         ret = cm_id_priv->id.cm_handler(&cm_id_priv->id, iw_event);
766
767         mtx_lock(&cm_id_priv->lock);
768         if (iw_event->private_data_len)
769                 free(iw_event->private_data, M_DEVBUF);
770
771         /* Wake up waiters on connect complete */
772         wakeup(&cm_id_priv->connect_wait);
773         mtx_unlock(&cm_id_priv->lock);
774
775         return ret;
776 }
777
778 /*
779  * CM_ID <-- CLOSING
780  *
781  * If in the ESTABLISHED state, move to CLOSING.
782  */
783 static void cm_disconnect_handler(struct iwcm_id_private *cm_id_priv,
784                                   struct iw_cm_event *iw_event)
785 {
786
787         mtx_lock(&cm_id_priv->lock);
788         if (cm_id_priv->state == IW_CM_STATE_ESTABLISHED)
789                 cm_id_priv->state = IW_CM_STATE_CLOSING;
790         mtx_unlock(&cm_id_priv->lock);
791 }
792
793 /*
794  * CM_ID <-- IDLE
795  *
796  * If in the ESTBLISHED or CLOSING states, the QP will have have been
797  * moved by the provider to the ERR state. Disassociate the CM_ID from
798  * the QP,  move to IDLE, and remove the 'connected' reference.
799  *
800  * If in some other state, the cm_id was destroyed asynchronously.
801  * This is the last reference that will result in waking up
802  * the app thread blocked in iw_destroy_cm_id.
803  */
804 static int cm_close_handler(struct iwcm_id_private *cm_id_priv,
805                                   struct iw_cm_event *iw_event)
806 {
807         int ret = 0;
808         mtx_lock(&cm_id_priv->lock);
809
810         if (cm_id_priv->qp) {
811                 cm_id_priv->id.device->iwcm->rem_ref(cm_id_priv->qp);
812                 cm_id_priv->qp = NULL;
813         }
814         switch (cm_id_priv->state) {
815         case IW_CM_STATE_ESTABLISHED:
816         case IW_CM_STATE_CLOSING:
817                 cm_id_priv->state = IW_CM_STATE_IDLE;
818                 mtx_unlock(&cm_id_priv->lock);
819                 ret = cm_id_priv->id.cm_handler(&cm_id_priv->id, iw_event);
820                 mtx_lock(&cm_id_priv->lock);
821                 break;
822         case IW_CM_STATE_DESTROYING:
823                 break;
824         default:
825                 panic("just cuz");
826         }
827         mtx_unlock(&cm_id_priv->lock);
828
829         return ret;
830 }
831
832 static int process_event(struct iwcm_id_private *cm_id_priv,
833                          struct iw_cm_event *iw_event)
834 {
835         int ret = 0;
836
837         switch (iw_event->event) {
838         case IW_CM_EVENT_CONNECT_REQUEST:
839                 cm_conn_req_handler(cm_id_priv, iw_event);
840                 break;
841         case IW_CM_EVENT_CONNECT_REPLY:
842                 ret = cm_conn_rep_handler(cm_id_priv, iw_event);
843                 break;
844         case IW_CM_EVENT_ESTABLISHED:
845                 ret = cm_conn_est_handler(cm_id_priv, iw_event);
846                 break;
847         case IW_CM_EVENT_DISCONNECT:
848                 cm_disconnect_handler(cm_id_priv, iw_event);
849                 break;
850         case IW_CM_EVENT_CLOSE:
851                 ret = cm_close_handler(cm_id_priv, iw_event);
852                 break;
853         default:
854                 panic("just cuz");
855         }
856
857         return ret;
858 }
859
860 /*
861  * Process events on the work_list for the cm_id. If the callback
862  * function requests that the cm_id be deleted, a flag is set in the
863  * cm_id flags to indicate that when the last reference is
864  * removed, the cm_id is to be destroyed. This is necessary to
865  * distinguish between an object that will be destroyed by the app
866  * thread asleep on the destroy_comp list vs. an object destroyed
867  * here synchronously when the last reference is removed.
868  */
869 static void cm_work_handler(void *context, int pending)
870 {
871         struct iwcm_work *work = context;
872         struct iw_cm_event levent;
873         struct iwcm_id_private *cm_id_priv = work->cm_id;
874         int empty;
875         int ret = 0;
876
877         mtx_lock(&cm_id_priv->lock);
878         empty = TAILQ_EMPTY(&cm_id_priv->work_list);
879         while (!empty) {
880                 work = TAILQ_FIRST(&cm_id_priv->work_list);
881                 TAILQ_REMOVE(&cm_id_priv->work_list, work, list);
882                 empty = TAILQ_EMPTY(&cm_id_priv->work_list);
883                 levent = work->event;
884                 put_work(work);
885                 mtx_unlock(&cm_id_priv->lock);
886
887                 ret = process_event(cm_id_priv, &levent);
888                 if (ret) {
889                         setbit(&cm_id_priv->flags, IWCM_F_CALLBACK_DESTROY);
890                         destroy_cm_id(&cm_id_priv->id);
891                 }
892                 PANIC_IF(atomic_load_acq_int(&cm_id_priv->refcount)==0);
893                 if (iwcm_deref_id(cm_id_priv)) {
894                         if (isset(&cm_id_priv->flags,
895                                 IWCM_F_CALLBACK_DESTROY)) {
896                                 PANIC_IF(!TAILQ_EMPTY(&cm_id_priv->work_list));
897                                 free_cm_id(cm_id_priv);
898                         }
899                         return;
900                 }
901                 mtx_lock(&cm_id_priv->lock);
902         }
903         mtx_unlock(&cm_id_priv->lock);
904 }
905
906 /*
907  * This function is called on interrupt context. Schedule events on
908  * the iwcm_wq thread to allow callback functions to downcall into
909  * the CM and/or block.  Events are queued to a per-CM_ID
910  * work_list. If this is the first event on the work_list, the work
911  * element is also queued on the iwcm_wq thread.
912  *
913  * Each event holds a reference on the cm_id. Until the last posted
914  * event has been delivered and processed, the cm_id cannot be
915  * deleted.
916  *
917  * Returns:
918  *            0 - the event was handled.
919  *      ENOMEM  - the event was not handled due to lack of resources.
920  */
921 static int cm_event_handler(struct iw_cm_id *cm_id,
922                              struct iw_cm_event *iw_event)
923 {
924         struct iwcm_work *work;
925         struct iwcm_id_private *cm_id_priv;
926         int ret = 0;
927
928         cm_id_priv = container_of(cm_id, struct iwcm_id_private, id);
929
930         mtx_lock(&cm_id_priv->lock);
931         work = get_work(cm_id_priv);
932         if (!work) {
933                 ret = ENOMEM;
934                 goto out;
935         }
936
937         TASK_INIT(&work->task, 0, cm_work_handler, work);
938         work->cm_id = cm_id_priv;
939         work->event = *iw_event;
940
941         if ((work->event.event == IW_CM_EVENT_CONNECT_REQUEST ||
942              work->event.event == IW_CM_EVENT_CONNECT_REPLY) &&
943             work->event.private_data_len) {
944                 ret = copy_private_data(&work->event);
945                 if (ret) {
946                         put_work(work);
947                         goto out;
948                 }
949         }
950
951         atomic_add_acq_int(&cm_id_priv->refcount, 1);
952         if (TAILQ_EMPTY(&cm_id_priv->work_list)) {
953                 TAILQ_INSERT_TAIL(&cm_id_priv->work_list, work, list);
954                 taskqueue_enqueue(iwcm_wq, &work->task);
955         } else
956                 TAILQ_INSERT_TAIL(&cm_id_priv->work_list, work, list);
957 out:
958         mtx_unlock(&cm_id_priv->lock);
959         return ret;
960 }
961
962 static int iwcm_init_qp_init_attr(struct iwcm_id_private *cm_id_priv,
963                                   struct ib_qp_attr *qp_attr,
964                                   int *qp_attr_mask)
965 {
966         int ret;
967
968         mtx_lock(&cm_id_priv->lock);
969         switch (cm_id_priv->state) {
970         case IW_CM_STATE_IDLE:
971         case IW_CM_STATE_CONN_SENT:
972         case IW_CM_STATE_CONN_RECV:
973         case IW_CM_STATE_ESTABLISHED:
974                 *qp_attr_mask = IB_QP_STATE | IB_QP_ACCESS_FLAGS;
975                 qp_attr->qp_access_flags = IB_ACCESS_LOCAL_WRITE |
976                                            IB_ACCESS_REMOTE_WRITE|
977                                            IB_ACCESS_REMOTE_READ;
978                 ret = 0;
979                 break;
980         default:
981                 ret = EINVAL;
982                 break;
983         }
984         mtx_unlock(&cm_id_priv->lock);
985         return ret;
986 }
987
988 static int iwcm_init_qp_rts_attr(struct iwcm_id_private *cm_id_priv,
989                                   struct ib_qp_attr *qp_attr,
990                                   int *qp_attr_mask)
991 {
992         int ret;
993
994         mtx_lock(&cm_id_priv->lock);
995         switch (cm_id_priv->state) {
996         case IW_CM_STATE_IDLE:
997         case IW_CM_STATE_CONN_SENT:
998         case IW_CM_STATE_CONN_RECV:
999         case IW_CM_STATE_ESTABLISHED:
1000                 *qp_attr_mask = 0;
1001                 ret = 0;
1002                 break;
1003         default:
1004                 ret = EINVAL;
1005                 break;
1006         }
1007         mtx_unlock(&cm_id_priv->lock);
1008         return ret;
1009 }
1010
1011 int iw_cm_init_qp_attr(struct iw_cm_id *cm_id,
1012                        struct ib_qp_attr *qp_attr,
1013                        int *qp_attr_mask)
1014 {
1015         struct iwcm_id_private *cm_id_priv;
1016         int ret;
1017
1018         cm_id_priv = container_of(cm_id, struct iwcm_id_private, id);
1019         switch (qp_attr->qp_state) {
1020         case IB_QPS_INIT:
1021         case IB_QPS_RTR:
1022                 ret = iwcm_init_qp_init_attr(cm_id_priv,
1023                                              qp_attr, qp_attr_mask);
1024                 break;
1025         case IB_QPS_RTS:
1026                 ret = iwcm_init_qp_rts_attr(cm_id_priv,
1027                                             qp_attr, qp_attr_mask);
1028                 break;
1029         default:
1030                 ret = EINVAL;
1031                 break;
1032         }
1033         return ret;
1034 }
1035
1036 static int iw_cm_init(void)
1037 {
1038         iwcm_wq = taskqueue_create("iw_cm_wq", M_NOWAIT, taskqueue_thread_enqueue, &iwcm_wq);
1039         if (!iwcm_wq)
1040                 return (ENOMEM);
1041
1042         taskqueue_start_threads(&iwcm_wq, 1, PI_NET, "iw_cm_wq thread");
1043         return 0;
1044 }
1045
1046 static void iw_cm_cleanup(void)
1047 {
1048         taskqueue_free(iwcm_wq);
1049 }
1050
1051 static int 
1052 iw_cm_load(module_t mod, int cmd, void *arg)
1053 {
1054         int err = 0;
1055
1056         switch (cmd) {
1057         case MOD_LOAD:
1058                 printf("Loading rdma_iwcm.\n");
1059
1060                 iw_cm_init();
1061                 break;
1062         case MOD_QUIESCE:
1063                 break;
1064         case MOD_UNLOAD:
1065                 printf("Unloading rdma_iwcm.\n");
1066                 iw_cm_cleanup();
1067                 break;
1068         case MOD_SHUTDOWN:
1069                 break;
1070         default:
1071                 err = EOPNOTSUPP;
1072                 break;
1073         }
1074
1075         return (err);
1076 }
1077
1078 static moduledata_t mod_data = {
1079         "rdma_iwcm",
1080         iw_cm_load,
1081         0
1082 };
1083
1084 MODULE_VERSION(rdma_iwcm, 1);
1085 MODULE_DEPEND(rdma_iwcm, rdma_core, 1, 1, 1);
1086 DECLARE_MODULE(rdma_iwcm, mod_data, SI_SUB_EXEC, SI_ORDER_ANY);