a0dfc5b35e19d297fb84467c29303309ffb14c7a
[people/peper/gpxe.git] / 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., 675 Mass Ave, Cambridge, MA 02139, USA.
17  */
18
19 FILE_LICENCE ( GPL2_OR_LATER );
20
21 #include <stdint.h>
22 #include <stdlib.h>
23 #include <stdio.h>
24 #include <string.h>
25 #include <unistd.h>
26 #include <byteswap.h>
27 #include <errno.h>
28 #include <assert.h>
29 #include <gpxe/list.h>
30 #include <gpxe/if_arp.h>
31 #include <gpxe/netdevice.h>
32 #include <gpxe/iobuf.h>
33 #include <gpxe/ipoib.h>
34 #include <gpxe/process.h>
35 #include <gpxe/infiniband.h>
36 #include <gpxe/ib_mi.h>
37 #include <gpxe/ib_sma.h>
38 #include <gpxe/ib_gma.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 /***************************************************************************
50  *
51  * Completion queues
52  *
53  ***************************************************************************
54  */
55
56 /**
57  * Create completion queue
58  *
59  * @v ibdev             Infiniband device
60  * @v num_cqes          Number of completion queue entries
61  * @v op                Completion queue operations
62  * @ret cq              New completion queue
63  */
64 struct ib_completion_queue *
65 ib_create_cq ( struct ib_device *ibdev, unsigned int num_cqes,
66                struct ib_completion_queue_operations *op ) {
67         struct ib_completion_queue *cq;
68         int rc;
69
70         DBGC ( ibdev, "IBDEV %p creating completion queue\n", ibdev );
71
72         /* Allocate and initialise data structure */
73         cq = zalloc ( sizeof ( *cq ) );
74         if ( ! cq )
75                 goto err_alloc_cq;
76         cq->ibdev = ibdev;
77         list_add ( &cq->list, &ibdev->cqs );
78         cq->num_cqes = num_cqes;
79         INIT_LIST_HEAD ( &cq->work_queues );
80         cq->op = op;
81
82         /* Perform device-specific initialisation and get CQN */
83         if ( ( rc = ibdev->op->create_cq ( ibdev, cq ) ) != 0 ) {
84                 DBGC ( ibdev, "IBDEV %p could not initialise completion "
85                        "queue: %s\n", ibdev, strerror ( rc ) );
86                 goto err_dev_create_cq;
87         }
88
89         DBGC ( ibdev, "IBDEV %p created %d-entry completion queue %p (%p) "
90                "with CQN %#lx\n", ibdev, num_cqes, cq,
91                ib_cq_get_drvdata ( cq ), cq->cqn );
92         return cq;
93
94         ibdev->op->destroy_cq ( ibdev, cq );
95  err_dev_create_cq:
96         list_del ( &cq->list );
97         free ( cq );
98  err_alloc_cq:
99         return NULL;
100 }
101
102 /**
103  * Destroy completion queue
104  *
105  * @v ibdev             Infiniband device
106  * @v cq                Completion queue
107  */
108 void ib_destroy_cq ( struct ib_device *ibdev,
109                      struct ib_completion_queue *cq ) {
110         DBGC ( ibdev, "IBDEV %p destroying completion queue %#lx\n",
111                ibdev, cq->cqn );
112         assert ( list_empty ( &cq->work_queues ) );
113         ibdev->op->destroy_cq ( ibdev, cq );
114         list_del ( &cq->list );
115         free ( cq );
116 }
117
118 /**
119  * Poll completion queue
120  *
121  * @v ibdev             Infiniband device
122  * @v cq                Completion queue
123  */
124 void ib_poll_cq ( struct ib_device *ibdev,
125                   struct ib_completion_queue *cq ) {
126         struct ib_work_queue *wq;
127
128         /* Poll completion queue */
129         ibdev->op->poll_cq ( ibdev, cq );
130
131         /* Refill receive work queues */
132         list_for_each_entry ( wq, &cq->work_queues, list ) {
133                 if ( ! wq->is_send )
134                         ib_refill_recv ( ibdev, wq->qp );
135         }
136 }
137
138 /***************************************************************************
139  *
140  * Work queues
141  *
142  ***************************************************************************
143  */
144
145 /**
146  * Create queue pair
147  *
148  * @v ibdev             Infiniband device
149  * @v type              Queue pair type
150  * @v num_send_wqes     Number of send work queue entries
151  * @v send_cq           Send completion queue
152  * @v num_recv_wqes     Number of receive work queue entries
153  * @v recv_cq           Receive completion queue
154  * @ret qp              Queue pair
155  *
156  * The queue pair will be left in the INIT state; you must call
157  * ib_modify_qp() before it is ready to use for sending and receiving.
158  */
159 struct ib_queue_pair * ib_create_qp ( struct ib_device *ibdev,
160                                       enum ib_queue_pair_type type,
161                                       unsigned int num_send_wqes,
162                                       struct ib_completion_queue *send_cq,
163                                       unsigned int num_recv_wqes,
164                                       struct ib_completion_queue *recv_cq ) {
165         struct ib_queue_pair *qp;
166         size_t total_size;
167         int rc;
168
169         DBGC ( ibdev, "IBDEV %p creating queue pair\n", ibdev );
170
171         /* Allocate and initialise data structure */
172         total_size = ( sizeof ( *qp ) +
173                        ( num_send_wqes * sizeof ( qp->send.iobufs[0] ) ) +
174                        ( num_recv_wqes * sizeof ( qp->recv.iobufs[0] ) ) );
175         qp = zalloc ( total_size );
176         if ( ! qp )
177                 goto err_alloc_qp;
178         qp->ibdev = ibdev;
179         list_add ( &qp->list, &ibdev->qps );
180         qp->type = type;
181         qp->send.qp = qp;
182         qp->send.is_send = 1;
183         qp->send.cq = send_cq;
184         list_add ( &qp->send.list, &send_cq->work_queues );
185         qp->send.psn = ( random() & 0xffffffUL );
186         qp->send.num_wqes = num_send_wqes;
187         qp->send.iobufs = ( ( ( void * ) qp ) + sizeof ( *qp ) );
188         qp->recv.qp = qp;
189         qp->recv.cq = recv_cq;
190         list_add ( &qp->recv.list, &recv_cq->work_queues );
191         qp->recv.psn = ( random() & 0xffffffUL );
192         qp->recv.num_wqes = num_recv_wqes;
193         qp->recv.iobufs = ( ( ( void * ) qp ) + sizeof ( *qp ) +
194                             ( num_send_wqes * sizeof ( qp->send.iobufs[0] ) ));
195         INIT_LIST_HEAD ( &qp->mgids );
196
197         /* Perform device-specific initialisation and get QPN */
198         if ( ( rc = ibdev->op->create_qp ( ibdev, qp ) ) != 0 ) {
199                 DBGC ( ibdev, "IBDEV %p could not initialise queue pair: "
200                        "%s\n", ibdev, strerror ( rc ) );
201                 goto err_dev_create_qp;
202         }
203         DBGC ( ibdev, "IBDEV %p created queue pair %p (%p) with QPN %#lx\n",
204                ibdev, qp, ib_qp_get_drvdata ( qp ), qp->qpn );
205         DBGC ( ibdev, "IBDEV %p QPN %#lx has %d send entries at [%p,%p)\n",
206                ibdev, qp->qpn, num_send_wqes, qp->send.iobufs,
207                qp->recv.iobufs );
208         DBGC ( ibdev, "IBDEV %p QPN %#lx has %d receive entries at [%p,%p)\n",
209                ibdev, qp->qpn, num_recv_wqes, qp->recv.iobufs,
210                ( ( ( void * ) qp ) + total_size ) );
211
212         /* Calculate externally-visible QPN */
213         switch ( type ) {
214         case IB_QPT_SMI:
215                 qp->ext_qpn = IB_QPN_SMI;
216                 break;
217         case IB_QPT_GSI:
218                 qp->ext_qpn = IB_QPN_GSI;
219                 break;
220         default:
221                 qp->ext_qpn = qp->qpn;
222                 break;
223         }
224         if ( qp->ext_qpn != qp->qpn ) {
225                 DBGC ( ibdev, "IBDEV %p QPN %#lx has external QPN %#lx\n",
226                        ibdev, qp->qpn, qp->ext_qpn );
227         }
228
229         return qp;
230
231         ibdev->op->destroy_qp ( ibdev, qp );
232  err_dev_create_qp:
233         list_del ( &qp->send.list );
234         list_del ( &qp->recv.list );
235         list_del ( &qp->list );
236         free ( qp );
237  err_alloc_qp:
238         return NULL;
239 }
240
241 /**
242  * Modify queue pair
243  *
244  * @v ibdev             Infiniband device
245  * @v qp                Queue pair
246  * @v av                New address vector, if applicable
247  * @ret rc              Return status code
248  */
249 int ib_modify_qp ( struct ib_device *ibdev, struct ib_queue_pair *qp ) {
250         int rc;
251
252         DBGC ( ibdev, "IBDEV %p modifying QPN %#lx\n", ibdev, qp->qpn );
253
254         if ( ( rc = ibdev->op->modify_qp ( ibdev, qp ) ) != 0 ) {
255                 DBGC ( ibdev, "IBDEV %p could not modify QPN %#lx: %s\n",
256                        ibdev, qp->qpn, strerror ( rc ) );
257                 return rc;
258         }
259
260         return 0;
261 }
262
263 /**
264  * Destroy queue pair
265  *
266  * @v ibdev             Infiniband device
267  * @v qp                Queue pair
268  */
269 void ib_destroy_qp ( struct ib_device *ibdev, struct ib_queue_pair *qp ) {
270         struct io_buffer *iobuf;
271         unsigned int i;
272
273         DBGC ( ibdev, "IBDEV %p destroying QPN %#lx\n",
274                ibdev, qp->qpn );
275
276         assert ( list_empty ( &qp->mgids ) );
277
278         /* Perform device-specific destruction */
279         ibdev->op->destroy_qp ( ibdev, qp );
280
281         /* Complete any remaining I/O buffers with errors */
282         for ( i = 0 ; i < qp->send.num_wqes ; i++ ) {
283                 if ( ( iobuf = qp->send.iobufs[i] ) != NULL )
284                         ib_complete_send ( ibdev, qp, iobuf, -ECANCELED );
285         }
286         for ( i = 0 ; i < qp->recv.num_wqes ; i++ ) {
287                 if ( ( iobuf = qp->recv.iobufs[i] ) != NULL ) {
288                         ib_complete_recv ( ibdev, qp, NULL, iobuf,
289                                            -ECANCELED );
290                 }
291         }
292
293         /* Remove work queues from completion queue */
294         list_del ( &qp->send.list );
295         list_del ( &qp->recv.list );
296
297         /* Free QP */
298         list_del ( &qp->list );
299         free ( qp );
300 }
301
302 /**
303  * Find queue pair by QPN
304  *
305  * @v ibdev             Infiniband device
306  * @v qpn               Queue pair number
307  * @ret qp              Queue pair, or NULL
308  */
309 struct ib_queue_pair * ib_find_qp_qpn ( struct ib_device *ibdev,
310                                         unsigned long qpn ) {
311         struct ib_queue_pair *qp;
312
313         list_for_each_entry ( qp, &ibdev->qps, list ) {
314                 if ( ( qpn == qp->qpn ) || ( qpn == qp->ext_qpn ) )
315                         return qp;
316         }
317         return NULL;
318 }
319
320 /**
321  * Find queue pair by multicast GID
322  *
323  * @v ibdev             Infiniband device
324  * @v gid               Multicast GID
325  * @ret qp              Queue pair, or NULL
326  */
327 struct ib_queue_pair * ib_find_qp_mgid ( struct ib_device *ibdev,
328                                          struct ib_gid *gid ) {
329         struct ib_queue_pair *qp;
330         struct ib_multicast_gid *mgid;
331
332         list_for_each_entry ( qp, &ibdev->qps, list ) {
333                 list_for_each_entry ( mgid, &qp->mgids, list ) {
334                         if ( memcmp ( &mgid->gid, gid,
335                                       sizeof ( mgid->gid ) ) == 0 ) {
336                                 return qp;
337                         }
338                 }
339         }
340         return NULL;
341 }
342
343 /**
344  * Find work queue belonging to completion queue
345  *
346  * @v cq                Completion queue
347  * @v qpn               Queue pair number
348  * @v is_send           Find send work queue (rather than receive)
349  * @ret wq              Work queue, or NULL if not found
350  */
351 struct ib_work_queue * ib_find_wq ( struct ib_completion_queue *cq,
352                                     unsigned long qpn, int is_send ) {
353         struct ib_work_queue *wq;
354
355         list_for_each_entry ( wq, &cq->work_queues, list ) {
356                 if ( ( wq->qp->qpn == qpn ) && ( wq->is_send == is_send ) )
357                         return wq;
358         }
359         return NULL;
360 }
361
362 /**
363  * Post send work queue entry
364  *
365  * @v ibdev             Infiniband device
366  * @v qp                Queue pair
367  * @v av                Address vector
368  * @v iobuf             I/O buffer
369  * @ret rc              Return status code
370  */
371 int ib_post_send ( struct ib_device *ibdev, struct ib_queue_pair *qp,
372                    struct ib_address_vector *av,
373                    struct io_buffer *iobuf ) {
374         struct ib_address_vector av_copy;
375         int rc;
376
377         /* Check queue fill level */
378         if ( qp->send.fill >= qp->send.num_wqes ) {
379                 DBGC ( ibdev, "IBDEV %p QPN %#lx send queue full\n",
380                        ibdev, qp->qpn );
381                 return -ENOBUFS;
382         }
383
384         /* Use default address vector if none specified */
385         if ( ! av )
386                 av = &qp->av;
387
388         /* Make modifiable copy of address vector */
389         memcpy ( &av_copy, av, sizeof ( av_copy ) );
390         av = &av_copy;
391
392         /* Fill in optional parameters in address vector */
393         if ( ! av->qkey )
394                 av->qkey = qp->qkey;
395         if ( ! av->rate )
396                 av->rate = IB_RATE_2_5;
397
398         /* Post to hardware */
399         if ( ( rc = ibdev->op->post_send ( ibdev, qp, av, iobuf ) ) != 0 ) {
400                 DBGC ( ibdev, "IBDEV %p QPN %#lx could not post send WQE: "
401                        "%s\n", ibdev, qp->qpn, strerror ( rc ) );
402                 return rc;
403         }
404
405         qp->send.fill++;
406         return 0;
407 }
408
409 /**
410  * Post receive work queue entry
411  *
412  * @v ibdev             Infiniband device
413  * @v qp                Queue pair
414  * @v iobuf             I/O buffer
415  * @ret rc              Return status code
416  */
417 int ib_post_recv ( struct ib_device *ibdev, struct ib_queue_pair *qp,
418                    struct io_buffer *iobuf ) {
419         int rc;
420
421         /* Check packet length */
422         if ( iob_tailroom ( iobuf ) < IB_MAX_PAYLOAD_SIZE ) {
423                 DBGC ( ibdev, "IBDEV %p QPN %#lx wrong RX buffer size (%zd)\n",
424                        ibdev, qp->qpn, iob_tailroom ( iobuf ) );
425                 return -EINVAL;
426         }
427
428         /* Check queue fill level */
429         if ( qp->recv.fill >= qp->recv.num_wqes ) {
430                 DBGC ( ibdev, "IBDEV %p QPN %#lx receive queue full\n",
431                        ibdev, qp->qpn );
432                 return -ENOBUFS;
433         }
434
435         /* Post to hardware */
436         if ( ( rc = ibdev->op->post_recv ( ibdev, qp, iobuf ) ) != 0 ) {
437                 DBGC ( ibdev, "IBDEV %p QPN %#lx could not post receive WQE: "
438                        "%s\n", ibdev, qp->qpn, strerror ( rc ) );
439                 return rc;
440         }
441
442         qp->recv.fill++;
443         return 0;
444 }
445
446 /**
447  * Complete send work queue entry
448  *
449  * @v ibdev             Infiniband device
450  * @v qp                Queue pair
451  * @v iobuf             I/O buffer
452  * @v rc                Completion status code
453  */
454 void ib_complete_send ( struct ib_device *ibdev, struct ib_queue_pair *qp,
455                         struct io_buffer *iobuf, int rc ) {
456
457         if ( qp->send.cq->op->complete_send ) {
458                 qp->send.cq->op->complete_send ( ibdev, qp, iobuf, rc );
459         } else {
460                 free_iob ( iobuf );
461         }
462         qp->send.fill--;
463 }
464
465 /**
466  * Complete receive work queue entry
467  *
468  * @v ibdev             Infiniband device
469  * @v qp                Queue pair
470  * @v av                Address vector
471  * @v iobuf             I/O buffer
472  * @v rc                Completion status code
473  */
474 void ib_complete_recv ( struct ib_device *ibdev, struct ib_queue_pair *qp,
475                         struct ib_address_vector *av,
476                         struct io_buffer *iobuf, int rc ) {
477
478         if ( qp->recv.cq->op->complete_recv ) {
479                 qp->recv.cq->op->complete_recv ( ibdev, qp, av, iobuf, rc );
480         } else {
481                 free_iob ( iobuf );
482         }
483         qp->recv.fill--;
484 }
485
486 /**
487  * Refill receive work queue
488  *
489  * @v ibdev             Infiniband device
490  * @v qp                Queue pair
491  */
492 void ib_refill_recv ( struct ib_device *ibdev, struct ib_queue_pair *qp ) {
493         struct io_buffer *iobuf;
494         int rc;
495
496         /* Keep filling while unfilled entries remain */
497         while ( qp->recv.fill < qp->recv.num_wqes ) {
498
499                 /* Allocate I/O buffer */
500                 iobuf = alloc_iob ( IB_MAX_PAYLOAD_SIZE );
501                 if ( ! iobuf ) {
502                         /* Non-fatal; we will refill on next attempt */
503                         return;
504                 }
505
506                 /* Post I/O buffer */
507                 if ( ( rc = ib_post_recv ( ibdev, qp, iobuf ) ) != 0 ) {
508                         DBGC ( ibdev, "IBDEV %p could not refill: %s\n",
509                                ibdev, strerror ( rc ) );
510                         free_iob ( iobuf );
511                         /* Give up */
512                         return;
513                 }
514         }
515 }
516
517 /***************************************************************************
518  *
519  * Link control
520  *
521  ***************************************************************************
522  */
523
524 /**
525  * Open port
526  *
527  * @v ibdev             Infiniband device
528  * @ret rc              Return status code
529  */
530 int ib_open ( struct ib_device *ibdev ) {
531         int rc;
532
533         /* Increment device open request counter */
534         if ( ibdev->open_count++ > 0 ) {
535                 /* Device was already open; do nothing */
536                 return 0;
537         }
538
539         /* Create subnet management interface */
540         ibdev->smi = ib_create_mi ( ibdev, IB_QPT_SMI );
541         if ( ! ibdev->smi ) {
542                 DBGC ( ibdev, "IBDEV %p could not create SMI\n", ibdev );
543                 rc = -ENOMEM;
544                 goto err_create_smi;
545         }
546
547         /* Create subnet management agent */
548         if ( ( rc = ib_create_sma ( ibdev, ibdev->smi ) ) != 0 ) {
549                 DBGC ( ibdev, "IBDEV %p could not create SMA: %s\n",
550                        ibdev, strerror ( rc ) );
551                 goto err_create_sma;
552         }
553
554         /* Create general management agent */
555         ibdev->gma = ib_create_gma ( ibdev, IB_QPT_GSI );
556         if ( ! ibdev->gma ) {
557                 DBGC ( ibdev, "IBDEV %p could not create GMA\n", ibdev );
558                 rc = -ENOMEM;
559                 goto err_create_gma;
560         }
561
562         /* Open device */
563         if ( ( rc = ibdev->op->open ( ibdev ) ) != 0 ) {
564                 DBGC ( ibdev, "IBDEV %p could not open: %s\n",
565                        ibdev, strerror ( rc ) );
566                 goto err_open;
567         }
568
569         assert ( ibdev->open_count == 1 );
570         return 0;
571
572         ibdev->op->close ( ibdev );
573  err_open:
574         ib_destroy_gma ( ibdev->gma );
575  err_create_gma:
576         ib_destroy_sma ( ibdev, ibdev->smi );
577  err_create_sma:
578         ib_destroy_mi ( ibdev, ibdev->smi );
579  err_create_smi:
580         assert ( ibdev->open_count == 1 );
581         ibdev->open_count = 0;
582         return rc;
583 }
584
585 /**
586  * Close port
587  *
588  * @v ibdev             Infiniband device
589  */
590 void ib_close ( struct ib_device *ibdev ) {
591
592         /* Decrement device open request counter */
593         ibdev->open_count--;
594
595         /* Close device if this was the last remaining requested opening */
596         if ( ibdev->open_count == 0 ) {
597                 ib_destroy_gma ( ibdev->gma );
598                 ib_destroy_sma ( ibdev, ibdev->smi );
599                 ib_destroy_mi ( ibdev, ibdev->smi );
600                 ibdev->op->close ( ibdev );
601         }
602 }
603
604 /***************************************************************************
605  *
606  * Multicast
607  *
608  ***************************************************************************
609  */
610
611 /**
612  * Attach to multicast group
613  *
614  * @v ibdev             Infiniband device
615  * @v qp                Queue pair
616  * @v gid               Multicast GID
617  * @ret rc              Return status code
618  *
619  * Note that this function handles only the local device's attachment
620  * to the multicast GID; it does not issue the relevant MADs to join
621  * the multicast group on the subnet.
622  */
623 int ib_mcast_attach ( struct ib_device *ibdev, struct ib_queue_pair *qp,
624                       struct ib_gid *gid ) {
625         struct ib_multicast_gid *mgid;
626         int rc;
627
628         /* Add to software multicast GID list */
629         mgid = zalloc ( sizeof ( *mgid ) );
630         if ( ! mgid ) {
631                 rc = -ENOMEM;
632                 goto err_alloc_mgid;
633         }
634         memcpy ( &mgid->gid, gid, sizeof ( mgid->gid ) );
635         list_add ( &mgid->list, &qp->mgids );
636
637         /* Add to hardware multicast GID list */
638         if ( ( rc = ibdev->op->mcast_attach ( ibdev, qp, gid ) ) != 0 )
639                 goto err_dev_mcast_attach;
640
641         return 0;
642
643  err_dev_mcast_attach:
644         list_del ( &mgid->list );
645         free ( mgid );
646  err_alloc_mgid:
647         return rc;
648 }
649
650 /**
651  * Detach from multicast group
652  *
653  * @v ibdev             Infiniband device
654  * @v qp                Queue pair
655  * @v gid               Multicast GID
656  */
657 void ib_mcast_detach ( struct ib_device *ibdev, struct ib_queue_pair *qp,
658                        struct ib_gid *gid ) {
659         struct ib_multicast_gid *mgid;
660
661         /* Remove from hardware multicast GID list */
662         ibdev->op->mcast_detach ( ibdev, qp, gid );
663
664         /* Remove from software multicast GID list */
665         list_for_each_entry ( mgid, &qp->mgids, list ) {
666                 if ( memcmp ( &mgid->gid, gid, sizeof ( mgid->gid ) ) == 0 ) {
667                         list_del ( &mgid->list );
668                         free ( mgid );
669                         break;
670                 }
671         }
672 }
673
674 /***************************************************************************
675  *
676  * Miscellaneous
677  *
678  ***************************************************************************
679  */
680
681 /**
682  * Get Infiniband HCA information
683  *
684  * @v ibdev             Infiniband device
685  * @ret hca_guid        HCA GUID
686  * @ret num_ports       Number of ports
687  */
688 int ib_get_hca_info ( struct ib_device *ibdev,
689                       struct ib_gid_half *hca_guid ) {
690         struct ib_device *tmp;
691         int num_ports = 0;
692
693         /* Search for IB devices with the same physical device to
694          * identify port count and a suitable Node GUID.
695          */
696         for_each_ibdev ( tmp ) {
697                 if ( tmp->dev != ibdev->dev )
698                         continue;
699                 if ( num_ports == 0 ) {
700                         memcpy ( hca_guid, &tmp->gid.u.half[1],
701                                  sizeof ( *hca_guid ) );
702                 }
703                 num_ports++;
704         }
705         return num_ports;
706 }
707
708 /**
709  * Set port information
710  *
711  * @v ibdev             Infiniband device
712  * @v mad               Set port information MAD
713  */
714 int ib_set_port_info ( struct ib_device *ibdev, union ib_mad *mad ) {
715         int rc;
716
717         /* Adapters with embedded SMAs do not need to support this method */
718         if ( ! ibdev->op->set_port_info ) {
719                 DBGC ( ibdev, "IBDEV %p does not support setting port "
720                        "information\n", ibdev );
721                 return -ENOTSUP;
722         }
723
724         if ( ( rc = ibdev->op->set_port_info ( ibdev, mad ) ) != 0 ) {
725                 DBGC ( ibdev, "IBDEV %p could not set port information: %s\n",
726                        ibdev, strerror ( rc ) );
727                 return rc;
728         }
729
730         return 0;
731 };
732
733 /**
734  * Set partition key table
735  *
736  * @v ibdev             Infiniband device
737  * @v mad               Set partition key table MAD
738  */
739 int ib_set_pkey_table ( struct ib_device *ibdev, union ib_mad *mad ) {
740         int rc;
741
742         /* Adapters with embedded SMAs do not need to support this method */
743         if ( ! ibdev->op->set_pkey_table ) {
744                 DBGC ( ibdev, "IBDEV %p does not support setting partition "
745                        "key table\n", ibdev );
746                 return -ENOTSUP;
747         }
748
749         if ( ( rc = ibdev->op->set_pkey_table ( ibdev, mad ) ) != 0 ) {
750                 DBGC ( ibdev, "IBDEV %p could not set partition key table: "
751                        "%s\n", ibdev, strerror ( rc ) );
752                 return rc;
753         }
754
755         return 0;
756 };
757
758 /***************************************************************************
759  *
760  * Event queues
761  *
762  ***************************************************************************
763  */
764
765 /**
766  * Handle Infiniband link state change
767  *
768  * @v ibdev             Infiniband device
769  */
770 void ib_link_state_changed ( struct ib_device *ibdev ) {
771
772         /* Notify IPoIB of link state change */
773         ipoib_link_state_changed ( ibdev );
774 }
775
776 /**
777  * Poll event queue
778  *
779  * @v ibdev             Infiniband device
780  */
781 void ib_poll_eq ( struct ib_device *ibdev ) {
782         struct ib_completion_queue *cq;
783
784         /* Poll device's event queue */
785         ibdev->op->poll_eq ( ibdev );
786
787         /* Poll all completion queues */
788         list_for_each_entry ( cq, &ibdev->cqs, list )
789                 ib_poll_cq ( ibdev, cq );
790 }
791
792 /**
793  * Single-step the Infiniband event queue
794  *
795  * @v process           Infiniband event queue process
796  */
797 static void ib_step ( struct process *process __unused ) {
798         struct ib_device *ibdev;
799
800         for_each_ibdev ( ibdev )
801                 ib_poll_eq ( ibdev );
802 }
803
804 /** Infiniband event queue process */
805 struct process ib_process __permanent_process = {
806         .step = ib_step,
807 };
808
809 /***************************************************************************
810  *
811  * Infiniband device creation/destruction
812  *
813  ***************************************************************************
814  */
815
816 /**
817  * Allocate Infiniband device
818  *
819  * @v priv_size         Size of driver private data area
820  * @ret ibdev           Infiniband device, or NULL
821  */
822 struct ib_device * alloc_ibdev ( size_t priv_size ) {
823         struct ib_device *ibdev;
824         void *drv_priv;
825         size_t total_len;
826
827         total_len = ( sizeof ( *ibdev ) + priv_size );
828         ibdev = zalloc ( total_len );
829         if ( ibdev ) {
830                 drv_priv = ( ( ( void * ) ibdev ) + sizeof ( *ibdev ) );
831                 ib_set_drvdata ( ibdev, drv_priv );
832                 INIT_LIST_HEAD ( &ibdev->cqs );
833                 INIT_LIST_HEAD ( &ibdev->qps );
834                 ibdev->lid = IB_LID_NONE;
835                 ibdev->pkey = IB_PKEY_NONE;
836         }
837         return ibdev;
838 }
839
840 /**
841  * Register Infiniband device
842  *
843  * @v ibdev             Infiniband device
844  * @ret rc              Return status code
845  */
846 int register_ibdev ( struct ib_device *ibdev ) {
847         int rc;
848
849         /* Add to device list */
850         ibdev_get ( ibdev );
851         list_add_tail ( &ibdev->list, &ib_devices );
852
853         /* Add IPoIB device */
854         if ( ( rc = ipoib_probe ( ibdev ) ) != 0 ) {
855                 DBGC ( ibdev, "IBDEV %p could not add IPoIB device: %s\n",
856                        ibdev, strerror ( rc ) );
857                 goto err_ipoib_probe;
858         }
859
860         DBGC ( ibdev, "IBDEV %p registered (phys %s)\n", ibdev,
861                ibdev->dev->name );
862         return 0;
863
864  err_ipoib_probe:
865         list_del ( &ibdev->list );
866         ibdev_put ( ibdev );
867         return rc;
868 }
869
870 /**
871  * Unregister Infiniband device
872  *
873  * @v ibdev             Infiniband device
874  */
875 void unregister_ibdev ( struct ib_device *ibdev ) {
876
877         /* Close device */
878         ipoib_remove ( ibdev );
879
880         /* Remove from device list */
881         list_del ( &ibdev->list );
882         ibdev_put ( ibdev );
883         DBGC ( ibdev, "IBDEV %p unregistered\n", ibdev );
884 }