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