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