Add qemu 2.4.0
[kvmfornfv.git] / qemu / roms / ipxe / src / net / infiniband.c
1 /*
2  * Copyright (C) 2007 Michael Brown <mbrown@fensystems.co.uk>.
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License as
6  * published by the Free Software Foundation; either version 2 of the
7  * License, or any later version.
8  *
9  * This program is distributed in the hope that it will be useful, but
10  * WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
17  * 02110-1301, USA.
18  */
19
20 FILE_LICENCE ( GPL2_OR_LATER );
21
22 #include <stdint.h>
23 #include <stdlib.h>
24 #include <stdio.h>
25 #include <string.h>
26 #include <unistd.h>
27 #include <byteswap.h>
28 #include <errno.h>
29 #include <assert.h>
30 #include <ipxe/list.h>
31 #include <ipxe/errortab.h>
32 #include <ipxe/if_arp.h>
33 #include <ipxe/netdevice.h>
34 #include <ipxe/iobuf.h>
35 #include <ipxe/process.h>
36 #include <ipxe/infiniband.h>
37 #include <ipxe/ib_mi.h>
38 #include <ipxe/ib_sma.h>
39
40 /** @file
41  *
42  * Infiniband protocol
43  *
44  */
45
46 /** List of Infiniband devices */
47 struct list_head ib_devices = LIST_HEAD_INIT ( ib_devices );
48
49 /** List of open Infiniband devices, in reverse order of opening */
50 static struct list_head open_ib_devices = LIST_HEAD_INIT ( open_ib_devices );
51
52 /* Disambiguate the various possible EINPROGRESSes */
53 #define EINPROGRESS_INIT __einfo_error ( EINFO_EINPROGRESS_INIT )
54 #define EINFO_EINPROGRESS_INIT __einfo_uniqify \
55         ( EINFO_EINPROGRESS, 0x01, "Initialising" )
56 #define EINPROGRESS_ARMED __einfo_error ( EINFO_EINPROGRESS_ARMED )
57 #define EINFO_EINPROGRESS_ARMED __einfo_uniqify \
58         ( EINFO_EINPROGRESS, 0x02, "Armed" )
59
60 /** Human-readable message for the link statuses */
61 struct errortab infiniband_errors[] __errortab = {
62         __einfo_errortab ( EINFO_EINPROGRESS_INIT ),
63         __einfo_errortab ( EINFO_EINPROGRESS_ARMED ),
64 };
65
66 /***************************************************************************
67  *
68  * Completion queues
69  *
70  ***************************************************************************
71  */
72
73 /**
74  * Create completion queue
75  *
76  * @v ibdev             Infiniband device
77  * @v num_cqes          Number of completion queue entries
78  * @v op                Completion queue operations
79  * @ret cq              New completion queue
80  */
81 struct ib_completion_queue *
82 ib_create_cq ( struct ib_device *ibdev, unsigned int num_cqes,
83                struct ib_completion_queue_operations *op ) {
84         struct ib_completion_queue *cq;
85         int rc;
86
87         DBGC ( ibdev, "IBDEV %p creating completion queue\n", ibdev );
88
89         /* Allocate and initialise data structure */
90         cq = zalloc ( sizeof ( *cq ) );
91         if ( ! cq )
92                 goto err_alloc_cq;
93         cq->ibdev = ibdev;
94         list_add ( &cq->list, &ibdev->cqs );
95         cq->num_cqes = num_cqes;
96         INIT_LIST_HEAD ( &cq->work_queues );
97         cq->op = op;
98
99         /* Perform device-specific initialisation and get CQN */
100         if ( ( rc = ibdev->op->create_cq ( ibdev, cq ) ) != 0 ) {
101                 DBGC ( ibdev, "IBDEV %p could not initialise completion "
102                        "queue: %s\n", ibdev, strerror ( rc ) );
103                 goto err_dev_create_cq;
104         }
105
106         DBGC ( ibdev, "IBDEV %p created %d-entry completion queue %p (%p) "
107                "with CQN %#lx\n", ibdev, num_cqes, cq,
108                ib_cq_get_drvdata ( cq ), cq->cqn );
109         return cq;
110
111         ibdev->op->destroy_cq ( ibdev, cq );
112  err_dev_create_cq:
113         list_del ( &cq->list );
114         free ( cq );
115  err_alloc_cq:
116         return NULL;
117 }
118
119 /**
120  * Destroy completion queue
121  *
122  * @v ibdev             Infiniband device
123  * @v cq                Completion queue
124  */
125 void ib_destroy_cq ( struct ib_device *ibdev,
126                      struct ib_completion_queue *cq ) {
127         DBGC ( ibdev, "IBDEV %p destroying completion queue %#lx\n",
128                ibdev, cq->cqn );
129         assert ( list_empty ( &cq->work_queues ) );
130         ibdev->op->destroy_cq ( ibdev, cq );
131         list_del ( &cq->list );
132         free ( cq );
133 }
134
135 /**
136  * Poll completion queue
137  *
138  * @v ibdev             Infiniband device
139  * @v cq                Completion queue
140  */
141 void ib_poll_cq ( struct ib_device *ibdev,
142                   struct ib_completion_queue *cq ) {
143         struct ib_work_queue *wq;
144
145         /* Poll completion queue */
146         ibdev->op->poll_cq ( ibdev, cq );
147
148         /* Refill receive work queues */
149         list_for_each_entry ( wq, &cq->work_queues, list ) {
150                 if ( ! wq->is_send )
151                         ib_refill_recv ( ibdev, wq->qp );
152         }
153 }
154
155 /***************************************************************************
156  *
157  * Work queues
158  *
159  ***************************************************************************
160  */
161
162 /**
163  * Create queue pair
164  *
165  * @v ibdev             Infiniband device
166  * @v type              Queue pair type
167  * @v num_send_wqes     Number of send work queue entries
168  * @v send_cq           Send completion queue
169  * @v num_recv_wqes     Number of receive work queue entries
170  * @v recv_cq           Receive completion queue
171  * @v op                Queue pair operations
172  * @ret qp              Queue pair
173  *
174  * The queue pair will be left in the INIT state; you must call
175  * ib_modify_qp() before it is ready to use for sending and receiving.
176  */
177 struct ib_queue_pair * ib_create_qp ( struct ib_device *ibdev,
178                                       enum ib_queue_pair_type type,
179                                       unsigned int num_send_wqes,
180                                       struct ib_completion_queue *send_cq,
181                                       unsigned int num_recv_wqes,
182                                       struct ib_completion_queue *recv_cq,
183                                       struct ib_queue_pair_operations *op ) {
184         struct ib_queue_pair *qp;
185         size_t total_size;
186         int rc;
187
188         DBGC ( ibdev, "IBDEV %p creating queue pair\n", ibdev );
189
190         /* Allocate and initialise data structure */
191         total_size = ( sizeof ( *qp ) +
192                        ( num_send_wqes * sizeof ( qp->send.iobufs[0] ) ) +
193                        ( num_recv_wqes * sizeof ( qp->recv.iobufs[0] ) ) );
194         qp = zalloc ( total_size );
195         if ( ! qp )
196                 goto err_alloc_qp;
197         qp->ibdev = ibdev;
198         list_add ( &qp->list, &ibdev->qps );
199         qp->type = type;
200         qp->send.qp = qp;
201         qp->send.is_send = 1;
202         qp->send.cq = send_cq;
203         list_add ( &qp->send.list, &send_cq->work_queues );
204         qp->send.psn = ( random() & 0xffffffUL );
205         qp->send.num_wqes = num_send_wqes;
206         qp->send.iobufs = ( ( ( void * ) qp ) + sizeof ( *qp ) );
207         qp->recv.qp = qp;
208         qp->recv.cq = recv_cq;
209         list_add ( &qp->recv.list, &recv_cq->work_queues );
210         qp->recv.psn = ( random() & 0xffffffUL );
211         qp->recv.num_wqes = num_recv_wqes;
212         qp->recv.iobufs = ( ( ( void * ) qp ) + sizeof ( *qp ) +
213                             ( num_send_wqes * sizeof ( qp->send.iobufs[0] ) ));
214         INIT_LIST_HEAD ( &qp->mgids );
215         qp->op = op;
216
217         /* Perform device-specific initialisation and get QPN */
218         if ( ( rc = ibdev->op->create_qp ( ibdev, qp ) ) != 0 ) {
219                 DBGC ( ibdev, "IBDEV %p could not initialise queue pair: "
220                        "%s\n", ibdev, strerror ( rc ) );
221                 goto err_dev_create_qp;
222         }
223         DBGC ( ibdev, "IBDEV %p created queue pair %p (%p) with QPN %#lx\n",
224                ibdev, qp, ib_qp_get_drvdata ( qp ), qp->qpn );
225         DBGC ( ibdev, "IBDEV %p QPN %#lx has %d send entries at [%p,%p)\n",
226                ibdev, qp->qpn, num_send_wqes, qp->send.iobufs,
227                qp->recv.iobufs );
228         DBGC ( ibdev, "IBDEV %p QPN %#lx has %d receive entries at [%p,%p)\n",
229                ibdev, qp->qpn, num_recv_wqes, qp->recv.iobufs,
230                ( ( ( void * ) qp ) + total_size ) );
231
232         /* Calculate externally-visible QPN */
233         switch ( type ) {
234         case IB_QPT_SMI:
235                 qp->ext_qpn = IB_QPN_SMI;
236                 break;
237         case IB_QPT_GSI:
238                 qp->ext_qpn = IB_QPN_GSI;
239                 break;
240         default:
241                 qp->ext_qpn = qp->qpn;
242                 break;
243         }
244         if ( qp->ext_qpn != qp->qpn ) {
245                 DBGC ( ibdev, "IBDEV %p QPN %#lx has external QPN %#lx\n",
246                        ibdev, qp->qpn, qp->ext_qpn );
247         }
248
249         return qp;
250
251         ibdev->op->destroy_qp ( ibdev, qp );
252  err_dev_create_qp:
253         list_del ( &qp->send.list );
254         list_del ( &qp->recv.list );
255         list_del ( &qp->list );
256         free ( qp );
257  err_alloc_qp:
258         return NULL;
259 }
260
261 /**
262  * Modify queue pair
263  *
264  * @v ibdev             Infiniband device
265  * @v qp                Queue pair
266  * @ret rc              Return status code
267  */
268 int ib_modify_qp ( struct ib_device *ibdev, struct ib_queue_pair *qp ) {
269         int rc;
270
271         DBGC ( ibdev, "IBDEV %p modifying QPN %#lx\n", ibdev, qp->qpn );
272
273         if ( ( rc = ibdev->op->modify_qp ( ibdev, qp ) ) != 0 ) {
274                 DBGC ( ibdev, "IBDEV %p could not modify QPN %#lx: %s\n",
275                        ibdev, qp->qpn, strerror ( rc ) );
276                 return rc;
277         }
278
279         return 0;
280 }
281
282 /**
283  * Destroy queue pair
284  *
285  * @v ibdev             Infiniband device
286  * @v qp                Queue pair
287  */
288 void ib_destroy_qp ( struct ib_device *ibdev, struct ib_queue_pair *qp ) {
289         struct io_buffer *iobuf;
290         unsigned int i;
291
292         DBGC ( ibdev, "IBDEV %p destroying QPN %#lx\n",
293                ibdev, qp->qpn );
294
295         assert ( list_empty ( &qp->mgids ) );
296
297         /* Perform device-specific destruction */
298         ibdev->op->destroy_qp ( ibdev, qp );
299
300         /* Complete any remaining I/O buffers with errors */
301         for ( i = 0 ; i < qp->send.num_wqes ; i++ ) {
302                 if ( ( iobuf = qp->send.iobufs[i] ) != NULL )
303                         ib_complete_send ( ibdev, qp, iobuf, -ECANCELED );
304         }
305         for ( i = 0 ; i < qp->recv.num_wqes ; i++ ) {
306                 if ( ( iobuf = qp->recv.iobufs[i] ) != NULL ) {
307                         ib_complete_recv ( ibdev, qp, NULL, NULL, iobuf,
308                                            -ECANCELED );
309                 }
310         }
311
312         /* Remove work queues from completion queue */
313         list_del ( &qp->send.list );
314         list_del ( &qp->recv.list );
315
316         /* Free QP */
317         list_del ( &qp->list );
318         free ( qp );
319 }
320
321 /**
322  * Find queue pair by QPN
323  *
324  * @v ibdev             Infiniband device
325  * @v qpn               Queue pair number
326  * @ret qp              Queue pair, or NULL
327  */
328 struct ib_queue_pair * ib_find_qp_qpn ( struct ib_device *ibdev,
329                                         unsigned long qpn ) {
330         struct ib_queue_pair *qp;
331
332         list_for_each_entry ( qp, &ibdev->qps, list ) {
333                 if ( ( qpn == qp->qpn ) || ( qpn == qp->ext_qpn ) )
334                         return qp;
335         }
336         return NULL;
337 }
338
339 /**
340  * Find queue pair by multicast GID
341  *
342  * @v ibdev             Infiniband device
343  * @v gid               Multicast GID
344  * @ret qp              Queue pair, or NULL
345  */
346 struct ib_queue_pair * ib_find_qp_mgid ( struct ib_device *ibdev,
347                                          union ib_gid *gid ) {
348         struct ib_queue_pair *qp;
349         struct ib_multicast_gid *mgid;
350
351         list_for_each_entry ( qp, &ibdev->qps, list ) {
352                 list_for_each_entry ( mgid, &qp->mgids, list ) {
353                         if ( memcmp ( &mgid->gid, gid,
354                                       sizeof ( mgid->gid ) ) == 0 ) {
355                                 return qp;
356                         }
357                 }
358         }
359         return NULL;
360 }
361
362 /**
363  * Find work queue belonging to completion queue
364  *
365  * @v cq                Completion queue
366  * @v qpn               Queue pair number
367  * @v is_send           Find send work queue (rather than receive)
368  * @ret wq              Work queue, or NULL if not found
369  */
370 struct ib_work_queue * ib_find_wq ( struct ib_completion_queue *cq,
371                                     unsigned long qpn, int is_send ) {
372         struct ib_work_queue *wq;
373
374         list_for_each_entry ( wq, &cq->work_queues, list ) {
375                 if ( ( wq->qp->qpn == qpn ) && ( wq->is_send == is_send ) )
376                         return wq;
377         }
378         return NULL;
379 }
380
381 /**
382  * Post send work queue entry
383  *
384  * @v ibdev             Infiniband device
385  * @v qp                Queue pair
386  * @v dest              Destination address vector
387  * @v iobuf             I/O buffer
388  * @ret rc              Return status code
389  */
390 int ib_post_send ( struct ib_device *ibdev, struct ib_queue_pair *qp,
391                    struct ib_address_vector *dest,
392                    struct io_buffer *iobuf ) {
393         struct ib_address_vector dest_copy;
394         int rc;
395
396         /* Check queue fill level */
397         if ( qp->send.fill >= qp->send.num_wqes ) {
398                 DBGC ( ibdev, "IBDEV %p QPN %#lx send queue full\n",
399                        ibdev, qp->qpn );
400                 return -ENOBUFS;
401         }
402
403         /* Use default address vector if none specified */
404         if ( ! dest )
405                 dest = &qp->av;
406
407         /* Make modifiable copy of address vector */
408         memcpy ( &dest_copy, dest, sizeof ( dest_copy ) );
409         dest = &dest_copy;
410
411         /* Fill in optional parameters in address vector */
412         if ( ! dest->qkey )
413                 dest->qkey = qp->qkey;
414         if ( ! dest->rate )
415                 dest->rate = IB_RATE_2_5;
416
417         /* Post to hardware */
418         if ( ( rc = ibdev->op->post_send ( ibdev, qp, dest, iobuf ) ) != 0 ) {
419                 DBGC ( ibdev, "IBDEV %p QPN %#lx could not post send WQE: "
420                        "%s\n", ibdev, qp->qpn, strerror ( rc ) );
421                 return rc;
422         }
423
424         qp->send.fill++;
425         return 0;
426 }
427
428 /**
429  * Post receive work queue entry
430  *
431  * @v ibdev             Infiniband device
432  * @v qp                Queue pair
433  * @v iobuf             I/O buffer
434  * @ret rc              Return status code
435  */
436 int ib_post_recv ( struct ib_device *ibdev, struct ib_queue_pair *qp,
437                    struct io_buffer *iobuf ) {
438         int rc;
439
440         /* Check packet length */
441         if ( iob_tailroom ( iobuf ) < IB_MAX_PAYLOAD_SIZE ) {
442                 DBGC ( ibdev, "IBDEV %p QPN %#lx wrong RX buffer size (%zd)\n",
443                        ibdev, qp->qpn, iob_tailroom ( iobuf ) );
444                 return -EINVAL;
445         }
446
447         /* Check queue fill level */
448         if ( qp->recv.fill >= qp->recv.num_wqes ) {
449                 DBGC ( ibdev, "IBDEV %p QPN %#lx receive queue full\n",
450                        ibdev, qp->qpn );
451                 return -ENOBUFS;
452         }
453
454         /* Post to hardware */
455         if ( ( rc = ibdev->op->post_recv ( ibdev, qp, iobuf ) ) != 0 ) {
456                 DBGC ( ibdev, "IBDEV %p QPN %#lx could not post receive WQE: "
457                        "%s\n", ibdev, qp->qpn, strerror ( rc ) );
458                 return rc;
459         }
460
461         qp->recv.fill++;
462         return 0;
463 }
464
465 /**
466  * Complete send work queue entry
467  *
468  * @v ibdev             Infiniband device
469  * @v qp                Queue pair
470  * @v iobuf             I/O buffer
471  * @v rc                Completion status code
472  */
473 void ib_complete_send ( struct ib_device *ibdev, struct ib_queue_pair *qp,
474                         struct io_buffer *iobuf, int rc ) {
475
476         if ( qp->send.cq->op->complete_send ) {
477                 qp->send.cq->op->complete_send ( ibdev, qp, iobuf, rc );
478         } else {
479                 free_iob ( iobuf );
480         }
481         qp->send.fill--;
482 }
483
484 /**
485  * Complete receive work queue entry
486  *
487  * @v ibdev             Infiniband device
488  * @v qp                Queue pair
489  * @v dest              Destination address vector, or NULL
490  * @v source            Source address vector, or NULL
491  * @v iobuf             I/O buffer
492  * @v rc                Completion status code
493  */
494 void ib_complete_recv ( struct ib_device *ibdev, struct ib_queue_pair *qp,
495                         struct ib_address_vector *dest,
496                         struct ib_address_vector *source,
497                         struct io_buffer *iobuf, int rc ) {
498
499         if ( qp->recv.cq->op->complete_recv ) {
500                 qp->recv.cq->op->complete_recv ( ibdev, qp, dest, source,
501                                                  iobuf, rc );
502         } else {
503                 free_iob ( iobuf );
504         }
505         qp->recv.fill--;
506 }
507
508 /**
509  * Refill receive work queue
510  *
511  * @v ibdev             Infiniband device
512  * @v qp                Queue pair
513  */
514 void ib_refill_recv ( struct ib_device *ibdev, struct ib_queue_pair *qp ) {
515         struct io_buffer *iobuf;
516         int rc;
517
518         /* Keep filling while unfilled entries remain */
519         while ( qp->recv.fill < qp->recv.num_wqes ) {
520
521                 /* Allocate I/O buffer */
522                 iobuf = qp->op->alloc_iob ( IB_MAX_PAYLOAD_SIZE );
523                 if ( ! iobuf ) {
524                         /* Non-fatal; we will refill on next attempt */
525                         return;
526                 }
527
528                 /* Post I/O buffer */
529                 if ( ( rc = ib_post_recv ( ibdev, qp, iobuf ) ) != 0 ) {
530                         DBGC ( ibdev, "IBDEV %p could not refill: %s\n",
531                                ibdev, strerror ( rc ) );
532                         free_iob ( iobuf );
533                         /* Give up */
534                         return;
535                 }
536         }
537 }
538
539 /***************************************************************************
540  *
541  * Link control
542  *
543  ***************************************************************************
544  */
545
546 /**
547  * Get link state
548  *
549  * @v ibdev             Infiniband device
550  * @ret rc              Link status code
551  */
552 int ib_link_rc ( struct ib_device *ibdev ) {
553         switch ( ibdev->port_state ) {
554         case IB_PORT_STATE_DOWN:        return -ENOTCONN;
555         case IB_PORT_STATE_INIT:        return -EINPROGRESS_INIT;
556         case IB_PORT_STATE_ARMED:       return -EINPROGRESS_ARMED;
557         case IB_PORT_STATE_ACTIVE:      return 0;
558         default:                        return -EINVAL;
559         }
560 }
561
562 /**
563  * Textual representation of Infiniband link state
564  *
565  * @v ibdev             Infiniband device
566  * @ret link_text       Link state text
567  */
568 static const char * ib_link_state_text ( struct ib_device *ibdev ) {
569         switch ( ibdev->port_state ) {
570         case IB_PORT_STATE_DOWN:        return "DOWN";
571         case IB_PORT_STATE_INIT:        return "INIT";
572         case IB_PORT_STATE_ARMED:       return "ARMED";
573         case IB_PORT_STATE_ACTIVE:      return "ACTIVE";
574         default:                        return "UNKNOWN";
575         }
576 }
577
578 /**
579  * Notify drivers of Infiniband device or link state change
580  *
581  * @v ibdev             Infiniband device
582  */
583 static void ib_notify ( struct ib_device *ibdev ) {
584         struct ib_driver *driver;
585
586         for_each_table_entry ( driver, IB_DRIVERS )
587                 driver->notify ( ibdev );
588 }
589
590 /**
591  * Notify of Infiniband link state change
592  *
593  * @v ibdev             Infiniband device
594  */
595 void ib_link_state_changed ( struct ib_device *ibdev ) {
596
597         DBGC ( ibdev, "IBDEV %p link state is %s\n",
598                ibdev, ib_link_state_text ( ibdev ) );
599
600         /* Notify drivers of link state change */
601         ib_notify ( ibdev );
602 }
603
604 /**
605  * Open port
606  *
607  * @v ibdev             Infiniband device
608  * @ret rc              Return status code
609  */
610 int ib_open ( struct ib_device *ibdev ) {
611         int rc;
612
613         /* Increment device open request counter */
614         if ( ibdev->open_count++ > 0 ) {
615                 /* Device was already open; do nothing */
616                 return 0;
617         }
618
619         /* Open device */
620         if ( ( rc = ibdev->op->open ( ibdev ) ) != 0 ) {
621                 DBGC ( ibdev, "IBDEV %p could not open: %s\n",
622                        ibdev, strerror ( rc ) );
623                 goto err_open;
624         }
625
626         /* Create subnet management interface */
627         ibdev->smi = ib_create_mi ( ibdev, IB_QPT_SMI );
628         if ( ! ibdev->smi ) {
629                 DBGC ( ibdev, "IBDEV %p could not create SMI\n", ibdev );
630                 rc = -ENOMEM;
631                 goto err_create_smi;
632         }
633
634         /* Create subnet management agent */
635         if ( ( rc = ib_create_sma ( ibdev, ibdev->smi ) ) != 0 ) {
636                 DBGC ( ibdev, "IBDEV %p could not create SMA: %s\n",
637                        ibdev, strerror ( rc ) );
638                 goto err_create_sma;
639         }
640
641         /* Create general services interface */
642         ibdev->gsi = ib_create_mi ( ibdev, IB_QPT_GSI );
643         if ( ! ibdev->gsi ) {
644                 DBGC ( ibdev, "IBDEV %p could not create GSI\n", ibdev );
645                 rc = -ENOMEM;
646                 goto err_create_gsi;
647         }
648
649         /* Add to head of open devices list */
650         list_add ( &ibdev->open_list, &open_ib_devices );
651
652         /* Notify drivers of device state change */
653         ib_notify ( ibdev );
654
655         assert ( ibdev->open_count == 1 );
656         return 0;
657
658         ib_destroy_mi ( ibdev, ibdev->gsi );
659  err_create_gsi:
660         ib_destroy_sma ( ibdev, ibdev->smi );
661  err_create_sma:
662         ib_destroy_mi ( ibdev, ibdev->smi );
663  err_create_smi:
664         ibdev->op->close ( ibdev );
665  err_open:
666         assert ( ibdev->open_count == 1 );
667         ibdev->open_count = 0;
668         return rc;
669 }
670
671 /**
672  * Close port
673  *
674  * @v ibdev             Infiniband device
675  */
676 void ib_close ( struct ib_device *ibdev ) {
677
678         /* Decrement device open request counter */
679         ibdev->open_count--;
680
681         /* Close device if this was the last remaining requested opening */
682         if ( ibdev->open_count == 0 ) {
683                 ib_notify ( ibdev );
684                 list_del ( &ibdev->open_list );
685                 ib_destroy_mi ( ibdev, ibdev->gsi );
686                 ib_destroy_sma ( ibdev, ibdev->smi );
687                 ib_destroy_mi ( ibdev, ibdev->smi );
688                 ibdev->op->close ( ibdev );
689                 ibdev->port_state = IB_PORT_STATE_DOWN;
690         }
691 }
692
693 /***************************************************************************
694  *
695  * Multicast
696  *
697  ***************************************************************************
698  */
699
700 /**
701  * Attach to multicast group
702  *
703  * @v ibdev             Infiniband device
704  * @v qp                Queue pair
705  * @v gid               Multicast GID
706  * @ret rc              Return status code
707  *
708  * Note that this function handles only the local device's attachment
709  * to the multicast GID; it does not issue the relevant MADs to join
710  * the multicast group on the subnet.
711  */
712 int ib_mcast_attach ( struct ib_device *ibdev, struct ib_queue_pair *qp,
713                       union ib_gid *gid ) {
714         struct ib_multicast_gid *mgid;
715         int rc;
716
717         /* Add to software multicast GID list */
718         mgid = zalloc ( sizeof ( *mgid ) );
719         if ( ! mgid ) {
720                 rc = -ENOMEM;
721                 goto err_alloc_mgid;
722         }
723         memcpy ( &mgid->gid, gid, sizeof ( mgid->gid ) );
724         list_add ( &mgid->list, &qp->mgids );
725
726         /* Add to hardware multicast GID list */
727         if ( ( rc = ibdev->op->mcast_attach ( ibdev, qp, gid ) ) != 0 )
728                 goto err_dev_mcast_attach;
729
730         return 0;
731
732  err_dev_mcast_attach:
733         list_del ( &mgid->list );
734         free ( mgid );
735  err_alloc_mgid:
736         return rc;
737 }
738
739 /**
740  * Detach from multicast group
741  *
742  * @v ibdev             Infiniband device
743  * @v qp                Queue pair
744  * @v gid               Multicast GID
745  */
746 void ib_mcast_detach ( struct ib_device *ibdev, struct ib_queue_pair *qp,
747                        union ib_gid *gid ) {
748         struct ib_multicast_gid *mgid;
749
750         /* Remove from hardware multicast GID list */
751         ibdev->op->mcast_detach ( ibdev, qp, gid );
752
753         /* Remove from software multicast GID list */
754         list_for_each_entry ( mgid, &qp->mgids, list ) {
755                 if ( memcmp ( &mgid->gid, gid, sizeof ( mgid->gid ) ) == 0 ) {
756                         list_del ( &mgid->list );
757                         free ( mgid );
758                         break;
759                 }
760         }
761 }
762
763 /***************************************************************************
764  *
765  * Miscellaneous
766  *
767  ***************************************************************************
768  */
769
770 /**
771  * Count Infiniband HCA ports
772  *
773  * @v ibdev             Infiniband device
774  * @ret num_ports       Number of ports
775  */
776 int ib_count_ports ( struct ib_device *ibdev ) {
777         struct ib_device *tmp;
778         int num_ports = 0;
779
780         /* Search for IB devices with the same physical device to
781          * identify port count.
782          */
783         for_each_ibdev ( tmp ) {
784                 if ( tmp->dev == ibdev->dev )
785                         num_ports++;
786         }
787         return num_ports;
788 }
789
790 /**
791  * Set port information
792  *
793  * @v ibdev             Infiniband device
794  * @v mad               Set port information MAD
795  */
796 int ib_set_port_info ( struct ib_device *ibdev, union ib_mad *mad ) {
797         int rc;
798
799         /* Adapters with embedded SMAs do not need to support this method */
800         if ( ! ibdev->op->set_port_info ) {
801                 DBGC ( ibdev, "IBDEV %p does not support setting port "
802                        "information\n", ibdev );
803                 return -ENOTSUP;
804         }
805
806         if ( ( rc = ibdev->op->set_port_info ( ibdev, mad ) ) != 0 ) {
807                 DBGC ( ibdev, "IBDEV %p could not set port information: %s\n",
808                        ibdev, strerror ( rc ) );
809                 return rc;
810         }
811
812         return 0;
813 };
814
815 /**
816  * Set partition key table
817  *
818  * @v ibdev             Infiniband device
819  * @v mad               Set partition key table MAD
820  */
821 int ib_set_pkey_table ( struct ib_device *ibdev, union ib_mad *mad ) {
822         int rc;
823
824         /* Adapters with embedded SMAs do not need to support this method */
825         if ( ! ibdev->op->set_pkey_table ) {
826                 DBGC ( ibdev, "IBDEV %p does not support setting partition "
827                        "key table\n", ibdev );
828                 return -ENOTSUP;
829         }
830
831         if ( ( rc = ibdev->op->set_pkey_table ( ibdev, mad ) ) != 0 ) {
832                 DBGC ( ibdev, "IBDEV %p could not set partition key table: "
833                        "%s\n", ibdev, strerror ( rc ) );
834                 return rc;
835         }
836
837         return 0;
838 };
839
840 /***************************************************************************
841  *
842  * Event queues
843  *
844  ***************************************************************************
845  */
846
847 /**
848  * Poll event queue
849  *
850  * @v ibdev             Infiniband device
851  */
852 void ib_poll_eq ( struct ib_device *ibdev ) {
853         struct ib_completion_queue *cq;
854
855         /* Poll device's event queue */
856         ibdev->op->poll_eq ( ibdev );
857
858         /* Poll all completion queues */
859         list_for_each_entry ( cq, &ibdev->cqs, list )
860                 ib_poll_cq ( ibdev, cq );
861 }
862
863 /**
864  * Single-step the Infiniband event queue
865  *
866  * @v process           Infiniband event queue process
867  */
868 static void ib_step ( struct process *process __unused ) {
869         struct ib_device *ibdev;
870
871         list_for_each_entry ( ibdev, &open_ib_devices, open_list )
872                 ib_poll_eq ( ibdev );
873 }
874
875 /** Infiniband event queue process */
876 PERMANENT_PROCESS ( ib_process, ib_step );
877
878 /***************************************************************************
879  *
880  * Infiniband device creation/destruction
881  *
882  ***************************************************************************
883  */
884
885 /**
886  * Allocate Infiniband device
887  *
888  * @v priv_size         Size of driver private data area
889  * @ret ibdev           Infiniband device, or NULL
890  */
891 struct ib_device * alloc_ibdev ( size_t priv_size ) {
892         struct ib_device *ibdev;
893         void *drv_priv;
894         size_t total_len;
895
896         total_len = ( sizeof ( *ibdev ) + priv_size );
897         ibdev = zalloc ( total_len );
898         if ( ibdev ) {
899                 drv_priv = ( ( ( void * ) ibdev ) + sizeof ( *ibdev ) );
900                 ib_set_drvdata ( ibdev, drv_priv );
901                 INIT_LIST_HEAD ( &ibdev->list );
902                 INIT_LIST_HEAD ( &ibdev->open_list );
903                 INIT_LIST_HEAD ( &ibdev->cqs );
904                 INIT_LIST_HEAD ( &ibdev->qps );
905                 ibdev->port_state = IB_PORT_STATE_DOWN;
906                 ibdev->lid = IB_LID_NONE;
907                 ibdev->pkey = IB_PKEY_DEFAULT;
908         }
909         return ibdev;
910 }
911
912 /**
913  * Register Infiniband device
914  *
915  * @v ibdev             Infiniband device
916  * @ret rc              Return status code
917  */
918 int register_ibdev ( struct ib_device *ibdev ) {
919         struct ib_driver *driver;
920         int rc;
921
922         /* Add to device list */
923         ibdev_get ( ibdev );
924         list_add_tail ( &ibdev->list, &ib_devices );
925         DBGC ( ibdev, "IBDEV %p registered (phys %s)\n", ibdev,
926                ibdev->dev->name );
927
928         /* Probe device */
929         for_each_table_entry ( driver, IB_DRIVERS ) {
930                 if ( ( rc = driver->probe ( ibdev ) ) != 0 ) {
931                         DBGC ( ibdev, "IBDEV %p could not add %s device: %s\n",
932                                ibdev, driver->name, strerror ( rc ) );
933                         goto err_probe;
934                 }
935         }
936
937         return 0;
938
939  err_probe:
940         for_each_table_entry_continue_reverse ( driver, IB_DRIVERS )
941                 driver->remove ( ibdev );
942         list_del ( &ibdev->list );
943         ibdev_put ( ibdev );
944         return rc;
945 }
946
947 /**
948  * Unregister Infiniband device
949  *
950  * @v ibdev             Infiniband device
951  */
952 void unregister_ibdev ( struct ib_device *ibdev ) {
953         struct ib_driver *driver;
954
955         /* Remove device */
956         for_each_table_entry_reverse ( driver, IB_DRIVERS )
957                 driver->remove ( ibdev );
958
959         /* Remove from device list */
960         list_del ( &ibdev->list );
961         ibdev_put ( ibdev );
962         DBGC ( ibdev, "IBDEV %p unregistered\n", ibdev );
963 }
964
965 /**
966  * Find Infiniband device by GID
967  *
968  * @v gid               GID
969  * @ret ibdev           Infiniband device, or NULL
970  */
971 struct ib_device * find_ibdev ( union ib_gid *gid ) {
972         struct ib_device *ibdev;
973
974         for_each_ibdev ( ibdev ) {
975                 if ( memcmp ( gid, &ibdev->gid, sizeof ( *gid ) ) == 0 )
976                         return ibdev;
977         }
978         return NULL;
979 }
980
981 /**
982  * Get most recently opened Infiniband device
983  *
984  * @ret ibdev           Most recently opened Infiniband device, or NULL
985  */
986 struct ib_device * last_opened_ibdev ( void ) {
987         struct ib_device *ibdev;
988
989         ibdev = list_first_entry ( &open_ib_devices, struct ib_device,
990                                    open_list );
991         if ( ! ibdev )
992                 return NULL;
993
994         assert ( ibdev->open_count != 0 );
995         return ibdev;
996 }
997
998 /* Drag in IPoIB */
999 REQUIRE_OBJECT ( ipoib );