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