2 * Copyright (C) 2007 Michael Brown <mbrown@fensystems.co.uk>.
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.
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.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19 * You can also choose to distribute this program under the terms of
20 * the Unmodified Binary Distribution Licence (as given in the file
21 * COPYING.UBDL), provided that you have satisfied its requirements.
24 FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
34 #include <ipxe/list.h>
35 #include <ipxe/errortab.h>
36 #include <ipxe/if_arp.h>
37 #include <ipxe/netdevice.h>
38 #include <ipxe/iobuf.h>
39 #include <ipxe/process.h>
40 #include <ipxe/infiniband.h>
41 #include <ipxe/ib_mi.h>
42 #include <ipxe/ib_sma.h>
50 /** List of Infiniband devices */
51 struct list_head ib_devices = LIST_HEAD_INIT ( ib_devices );
53 /** List of open Infiniband devices, in reverse order of opening */
54 static struct list_head open_ib_devices = LIST_HEAD_INIT ( open_ib_devices );
56 /* Disambiguate the various possible EINPROGRESSes */
57 #define EINPROGRESS_INIT __einfo_error ( EINFO_EINPROGRESS_INIT )
58 #define EINFO_EINPROGRESS_INIT __einfo_uniqify \
59 ( EINFO_EINPROGRESS, 0x01, "Initialising" )
60 #define EINPROGRESS_ARMED __einfo_error ( EINFO_EINPROGRESS_ARMED )
61 #define EINFO_EINPROGRESS_ARMED __einfo_uniqify \
62 ( EINFO_EINPROGRESS, 0x02, "Armed" )
64 /** Human-readable message for the link statuses */
65 struct errortab infiniband_errors[] __errortab = {
66 __einfo_errortab ( EINFO_EINPROGRESS_INIT ),
67 __einfo_errortab ( EINFO_EINPROGRESS_ARMED ),
70 /***************************************************************************
74 ***************************************************************************
78 * Create completion queue
80 * @v ibdev Infiniband device
81 * @v num_cqes Number of completion queue entries
82 * @v op Completion queue operations
83 * @ret cq New completion queue
85 struct ib_completion_queue *
86 ib_create_cq ( struct ib_device *ibdev, unsigned int num_cqes,
87 struct ib_completion_queue_operations *op ) {
88 struct ib_completion_queue *cq;
91 DBGC ( ibdev, "IBDEV %p creating completion queue\n", ibdev );
93 /* Allocate and initialise data structure */
94 cq = zalloc ( sizeof ( *cq ) );
98 list_add ( &cq->list, &ibdev->cqs );
99 cq->num_cqes = num_cqes;
100 INIT_LIST_HEAD ( &cq->work_queues );
103 /* Perform device-specific initialisation and get CQN */
104 if ( ( rc = ibdev->op->create_cq ( ibdev, cq ) ) != 0 ) {
105 DBGC ( ibdev, "IBDEV %p could not initialise completion "
106 "queue: %s\n", ibdev, strerror ( rc ) );
107 goto err_dev_create_cq;
110 DBGC ( ibdev, "IBDEV %p created %d-entry completion queue %p (%p) "
111 "with CQN %#lx\n", ibdev, num_cqes, cq,
112 ib_cq_get_drvdata ( cq ), cq->cqn );
115 ibdev->op->destroy_cq ( ibdev, cq );
117 list_del ( &cq->list );
124 * Destroy completion queue
126 * @v ibdev Infiniband device
127 * @v cq Completion queue
129 void ib_destroy_cq ( struct ib_device *ibdev,
130 struct ib_completion_queue *cq ) {
131 DBGC ( ibdev, "IBDEV %p destroying completion queue %#lx\n",
133 assert ( list_empty ( &cq->work_queues ) );
134 ibdev->op->destroy_cq ( ibdev, cq );
135 list_del ( &cq->list );
140 * Poll completion queue
142 * @v ibdev Infiniband device
143 * @v cq Completion queue
145 void ib_poll_cq ( struct ib_device *ibdev,
146 struct ib_completion_queue *cq ) {
147 struct ib_work_queue *wq;
149 /* Poll completion queue */
150 ibdev->op->poll_cq ( ibdev, cq );
152 /* Refill receive work queues */
153 list_for_each_entry ( wq, &cq->work_queues, list ) {
155 ib_refill_recv ( ibdev, wq->qp );
159 /***************************************************************************
163 ***************************************************************************
169 * @v ibdev Infiniband device
170 * @v type Queue pair type
171 * @v num_send_wqes Number of send work queue entries
172 * @v send_cq Send completion queue
173 * @v num_recv_wqes Number of receive work queue entries
174 * @v recv_cq Receive completion queue
175 * @v op Queue pair operations
178 * The queue pair will be left in the INIT state; you must call
179 * ib_modify_qp() before it is ready to use for sending and receiving.
181 struct ib_queue_pair * ib_create_qp ( struct ib_device *ibdev,
182 enum ib_queue_pair_type type,
183 unsigned int num_send_wqes,
184 struct ib_completion_queue *send_cq,
185 unsigned int num_recv_wqes,
186 struct ib_completion_queue *recv_cq,
187 struct ib_queue_pair_operations *op ) {
188 struct ib_queue_pair *qp;
192 DBGC ( ibdev, "IBDEV %p creating queue pair\n", ibdev );
194 /* Allocate and initialise data structure */
195 total_size = ( sizeof ( *qp ) +
196 ( num_send_wqes * sizeof ( qp->send.iobufs[0] ) ) +
197 ( num_recv_wqes * sizeof ( qp->recv.iobufs[0] ) ) );
198 qp = zalloc ( total_size );
202 list_add ( &qp->list, &ibdev->qps );
205 qp->send.is_send = 1;
206 qp->send.cq = send_cq;
207 list_add ( &qp->send.list, &send_cq->work_queues );
208 qp->send.psn = ( random() & 0xffffffUL );
209 qp->send.num_wqes = num_send_wqes;
210 qp->send.iobufs = ( ( ( void * ) qp ) + sizeof ( *qp ) );
212 qp->recv.cq = recv_cq;
213 list_add ( &qp->recv.list, &recv_cq->work_queues );
214 qp->recv.psn = ( random() & 0xffffffUL );
215 qp->recv.num_wqes = num_recv_wqes;
216 qp->recv.iobufs = ( ( ( void * ) qp ) + sizeof ( *qp ) +
217 ( num_send_wqes * sizeof ( qp->send.iobufs[0] ) ));
218 INIT_LIST_HEAD ( &qp->mgids );
221 /* Perform device-specific initialisation and get QPN */
222 if ( ( rc = ibdev->op->create_qp ( ibdev, qp ) ) != 0 ) {
223 DBGC ( ibdev, "IBDEV %p could not initialise queue pair: "
224 "%s\n", ibdev, strerror ( rc ) );
225 goto err_dev_create_qp;
227 DBGC ( ibdev, "IBDEV %p created queue pair %p (%p) with QPN %#lx\n",
228 ibdev, qp, ib_qp_get_drvdata ( qp ), qp->qpn );
229 DBGC ( ibdev, "IBDEV %p QPN %#lx has %d send entries at [%p,%p)\n",
230 ibdev, qp->qpn, num_send_wqes, qp->send.iobufs,
232 DBGC ( ibdev, "IBDEV %p QPN %#lx has %d receive entries at [%p,%p)\n",
233 ibdev, qp->qpn, num_recv_wqes, qp->recv.iobufs,
234 ( ( ( void * ) qp ) + total_size ) );
236 /* Calculate externally-visible QPN */
239 qp->ext_qpn = IB_QPN_SMI;
242 qp->ext_qpn = IB_QPN_GSI;
245 qp->ext_qpn = qp->qpn;
248 if ( qp->ext_qpn != qp->qpn ) {
249 DBGC ( ibdev, "IBDEV %p QPN %#lx has external QPN %#lx\n",
250 ibdev, qp->qpn, qp->ext_qpn );
255 ibdev->op->destroy_qp ( ibdev, qp );
257 list_del ( &qp->send.list );
258 list_del ( &qp->recv.list );
259 list_del ( &qp->list );
268 * @v ibdev Infiniband device
270 * @ret rc Return status code
272 int ib_modify_qp ( struct ib_device *ibdev, struct ib_queue_pair *qp ) {
275 DBGC ( ibdev, "IBDEV %p modifying QPN %#lx\n", ibdev, qp->qpn );
277 if ( ( rc = ibdev->op->modify_qp ( ibdev, qp ) ) != 0 ) {
278 DBGC ( ibdev, "IBDEV %p could not modify QPN %#lx: %s\n",
279 ibdev, qp->qpn, strerror ( rc ) );
289 * @v ibdev Infiniband device
292 void ib_destroy_qp ( struct ib_device *ibdev, struct ib_queue_pair *qp ) {
293 struct io_buffer *iobuf;
296 DBGC ( ibdev, "IBDEV %p destroying QPN %#lx\n",
299 assert ( list_empty ( &qp->mgids ) );
301 /* Perform device-specific destruction */
302 ibdev->op->destroy_qp ( ibdev, qp );
304 /* Complete any remaining I/O buffers with errors */
305 for ( i = 0 ; i < qp->send.num_wqes ; i++ ) {
306 if ( ( iobuf = qp->send.iobufs[i] ) != NULL )
307 ib_complete_send ( ibdev, qp, iobuf, -ECANCELED );
309 for ( i = 0 ; i < qp->recv.num_wqes ; i++ ) {
310 if ( ( iobuf = qp->recv.iobufs[i] ) != NULL ) {
311 ib_complete_recv ( ibdev, qp, NULL, NULL, iobuf,
316 /* Remove work queues from completion queue */
317 list_del ( &qp->send.list );
318 list_del ( &qp->recv.list );
321 list_del ( &qp->list );
326 * Find queue pair by QPN
328 * @v ibdev Infiniband device
329 * @v qpn Queue pair number
330 * @ret qp Queue pair, or NULL
332 struct ib_queue_pair * ib_find_qp_qpn ( struct ib_device *ibdev,
333 unsigned long qpn ) {
334 struct ib_queue_pair *qp;
336 list_for_each_entry ( qp, &ibdev->qps, list ) {
337 if ( ( qpn == qp->qpn ) || ( qpn == qp->ext_qpn ) )
344 * Find queue pair by multicast GID
346 * @v ibdev Infiniband device
347 * @v gid Multicast GID
348 * @ret qp Queue pair, or NULL
350 struct ib_queue_pair * ib_find_qp_mgid ( struct ib_device *ibdev,
351 union ib_gid *gid ) {
352 struct ib_queue_pair *qp;
353 struct ib_multicast_gid *mgid;
355 list_for_each_entry ( qp, &ibdev->qps, list ) {
356 list_for_each_entry ( mgid, &qp->mgids, list ) {
357 if ( memcmp ( &mgid->gid, gid,
358 sizeof ( mgid->gid ) ) == 0 ) {
367 * Find work queue belonging to completion queue
369 * @v cq Completion queue
370 * @v qpn Queue pair number
371 * @v is_send Find send work queue (rather than receive)
372 * @ret wq Work queue, or NULL if not found
374 struct ib_work_queue * ib_find_wq ( struct ib_completion_queue *cq,
375 unsigned long qpn, int is_send ) {
376 struct ib_work_queue *wq;
378 list_for_each_entry ( wq, &cq->work_queues, list ) {
379 if ( ( wq->qp->qpn == qpn ) && ( wq->is_send == is_send ) )
386 * Post send work queue entry
388 * @v ibdev Infiniband device
390 * @v dest Destination address vector
391 * @v iobuf I/O buffer
392 * @ret rc Return status code
394 int ib_post_send ( struct ib_device *ibdev, struct ib_queue_pair *qp,
395 struct ib_address_vector *dest,
396 struct io_buffer *iobuf ) {
397 struct ib_address_vector dest_copy;
400 /* Check queue fill level */
401 if ( qp->send.fill >= qp->send.num_wqes ) {
402 DBGC ( ibdev, "IBDEV %p QPN %#lx send queue full\n",
407 /* Use default address vector if none specified */
411 /* Make modifiable copy of address vector */
412 memcpy ( &dest_copy, dest, sizeof ( dest_copy ) );
415 /* Fill in optional parameters in address vector */
417 dest->qkey = qp->qkey;
419 dest->rate = IB_RATE_2_5;
421 /* Post to hardware */
422 if ( ( rc = ibdev->op->post_send ( ibdev, qp, dest, iobuf ) ) != 0 ) {
423 DBGC ( ibdev, "IBDEV %p QPN %#lx could not post send WQE: "
424 "%s\n", ibdev, qp->qpn, strerror ( rc ) );
433 * Post receive work queue entry
435 * @v ibdev Infiniband device
437 * @v iobuf I/O buffer
438 * @ret rc Return status code
440 int ib_post_recv ( struct ib_device *ibdev, struct ib_queue_pair *qp,
441 struct io_buffer *iobuf ) {
444 /* Check packet length */
445 if ( iob_tailroom ( iobuf ) < IB_MAX_PAYLOAD_SIZE ) {
446 DBGC ( ibdev, "IBDEV %p QPN %#lx wrong RX buffer size (%zd)\n",
447 ibdev, qp->qpn, iob_tailroom ( iobuf ) );
451 /* Check queue fill level */
452 if ( qp->recv.fill >= qp->recv.num_wqes ) {
453 DBGC ( ibdev, "IBDEV %p QPN %#lx receive queue full\n",
458 /* Post to hardware */
459 if ( ( rc = ibdev->op->post_recv ( ibdev, qp, iobuf ) ) != 0 ) {
460 DBGC ( ibdev, "IBDEV %p QPN %#lx could not post receive WQE: "
461 "%s\n", ibdev, qp->qpn, strerror ( rc ) );
470 * Complete send work queue entry
472 * @v ibdev Infiniband device
474 * @v iobuf I/O buffer
475 * @v rc Completion status code
477 void ib_complete_send ( struct ib_device *ibdev, struct ib_queue_pair *qp,
478 struct io_buffer *iobuf, int rc ) {
480 if ( qp->send.cq->op->complete_send ) {
481 qp->send.cq->op->complete_send ( ibdev, qp, iobuf, rc );
489 * Complete receive work queue entry
491 * @v ibdev Infiniband device
493 * @v dest Destination address vector, or NULL
494 * @v source Source address vector, or NULL
495 * @v iobuf I/O buffer
496 * @v rc Completion status code
498 void ib_complete_recv ( struct ib_device *ibdev, struct ib_queue_pair *qp,
499 struct ib_address_vector *dest,
500 struct ib_address_vector *source,
501 struct io_buffer *iobuf, int rc ) {
503 if ( qp->recv.cq->op->complete_recv ) {
504 qp->recv.cq->op->complete_recv ( ibdev, qp, dest, source,
513 * Refill receive work queue
515 * @v ibdev Infiniband device
518 void ib_refill_recv ( struct ib_device *ibdev, struct ib_queue_pair *qp ) {
519 struct io_buffer *iobuf;
522 /* Keep filling while unfilled entries remain */
523 while ( qp->recv.fill < qp->recv.num_wqes ) {
525 /* Allocate I/O buffer */
526 iobuf = qp->op->alloc_iob ( IB_MAX_PAYLOAD_SIZE );
528 /* Non-fatal; we will refill on next attempt */
532 /* Post I/O buffer */
533 if ( ( rc = ib_post_recv ( ibdev, qp, iobuf ) ) != 0 ) {
534 DBGC ( ibdev, "IBDEV %p could not refill: %s\n",
535 ibdev, strerror ( rc ) );
543 /***************************************************************************
547 ***************************************************************************
553 * @v ibdev Infiniband device
554 * @ret rc Link status code
556 int ib_link_rc ( struct ib_device *ibdev ) {
557 switch ( ibdev->port_state ) {
558 case IB_PORT_STATE_DOWN: return -ENOTCONN;
559 case IB_PORT_STATE_INIT: return -EINPROGRESS_INIT;
560 case IB_PORT_STATE_ARMED: return -EINPROGRESS_ARMED;
561 case IB_PORT_STATE_ACTIVE: return 0;
562 default: return -EINVAL;
567 * Textual representation of Infiniband link state
569 * @v ibdev Infiniband device
570 * @ret link_text Link state text
572 static const char * ib_link_state_text ( struct ib_device *ibdev ) {
573 switch ( ibdev->port_state ) {
574 case IB_PORT_STATE_DOWN: return "DOWN";
575 case IB_PORT_STATE_INIT: return "INIT";
576 case IB_PORT_STATE_ARMED: return "ARMED";
577 case IB_PORT_STATE_ACTIVE: return "ACTIVE";
578 default: return "UNKNOWN";
583 * Notify drivers of Infiniband device or link state change
585 * @v ibdev Infiniband device
587 static void ib_notify ( struct ib_device *ibdev ) {
588 struct ib_driver *driver;
590 for_each_table_entry ( driver, IB_DRIVERS )
591 driver->notify ( ibdev );
595 * Notify of Infiniband link state change
597 * @v ibdev Infiniband device
599 void ib_link_state_changed ( struct ib_device *ibdev ) {
601 DBGC ( ibdev, "IBDEV %p link state is %s\n",
602 ibdev, ib_link_state_text ( ibdev ) );
604 /* Notify drivers of link state change */
611 * @v ibdev Infiniband device
612 * @ret rc Return status code
614 int ib_open ( struct ib_device *ibdev ) {
617 /* Increment device open request counter */
618 if ( ibdev->open_count++ > 0 ) {
619 /* Device was already open; do nothing */
624 if ( ( rc = ibdev->op->open ( ibdev ) ) != 0 ) {
625 DBGC ( ibdev, "IBDEV %p could not open: %s\n",
626 ibdev, strerror ( rc ) );
630 /* Create subnet management interface */
631 ibdev->smi = ib_create_mi ( ibdev, IB_QPT_SMI );
632 if ( ! ibdev->smi ) {
633 DBGC ( ibdev, "IBDEV %p could not create SMI\n", ibdev );
638 /* Create subnet management agent */
639 if ( ( rc = ib_create_sma ( ibdev, ibdev->smi ) ) != 0 ) {
640 DBGC ( ibdev, "IBDEV %p could not create SMA: %s\n",
641 ibdev, strerror ( rc ) );
645 /* Create general services interface */
646 ibdev->gsi = ib_create_mi ( ibdev, IB_QPT_GSI );
647 if ( ! ibdev->gsi ) {
648 DBGC ( ibdev, "IBDEV %p could not create GSI\n", ibdev );
653 /* Add to head of open devices list */
654 list_add ( &ibdev->open_list, &open_ib_devices );
656 /* Notify drivers of device state change */
659 assert ( ibdev->open_count == 1 );
662 ib_destroy_mi ( ibdev, ibdev->gsi );
664 ib_destroy_sma ( ibdev, ibdev->smi );
666 ib_destroy_mi ( ibdev, ibdev->smi );
668 ibdev->op->close ( ibdev );
670 assert ( ibdev->open_count == 1 );
671 ibdev->open_count = 0;
678 * @v ibdev Infiniband device
680 void ib_close ( struct ib_device *ibdev ) {
682 /* Decrement device open request counter */
685 /* Close device if this was the last remaining requested opening */
686 if ( ibdev->open_count == 0 ) {
688 list_del ( &ibdev->open_list );
689 ib_destroy_mi ( ibdev, ibdev->gsi );
690 ib_destroy_sma ( ibdev, ibdev->smi );
691 ib_destroy_mi ( ibdev, ibdev->smi );
692 ibdev->op->close ( ibdev );
693 ibdev->port_state = IB_PORT_STATE_DOWN;
697 /***************************************************************************
701 ***************************************************************************
705 * Attach to multicast group
707 * @v ibdev Infiniband device
709 * @v gid Multicast GID
710 * @ret rc Return status code
712 * Note that this function handles only the local device's attachment
713 * to the multicast GID; it does not issue the relevant MADs to join
714 * the multicast group on the subnet.
716 int ib_mcast_attach ( struct ib_device *ibdev, struct ib_queue_pair *qp,
717 union ib_gid *gid ) {
718 struct ib_multicast_gid *mgid;
722 assert ( qp != NULL );
724 /* Add to software multicast GID list */
725 mgid = zalloc ( sizeof ( *mgid ) );
730 memcpy ( &mgid->gid, gid, sizeof ( mgid->gid ) );
731 list_add ( &mgid->list, &qp->mgids );
733 /* Add to hardware multicast GID list */
734 if ( ( rc = ibdev->op->mcast_attach ( ibdev, qp, gid ) ) != 0 )
735 goto err_dev_mcast_attach;
739 err_dev_mcast_attach:
740 list_del ( &mgid->list );
747 * Detach from multicast group
749 * @v ibdev Infiniband device
751 * @v gid Multicast GID
753 void ib_mcast_detach ( struct ib_device *ibdev, struct ib_queue_pair *qp,
754 union ib_gid *gid ) {
755 struct ib_multicast_gid *mgid;
758 assert ( qp != NULL );
760 /* Remove from hardware multicast GID list */
761 ibdev->op->mcast_detach ( ibdev, qp, gid );
763 /* Remove from software multicast GID list */
764 list_for_each_entry ( mgid, &qp->mgids, list ) {
765 if ( memcmp ( &mgid->gid, gid, sizeof ( mgid->gid ) ) == 0 ) {
766 list_del ( &mgid->list );
773 /***************************************************************************
777 ***************************************************************************
781 * Count Infiniband HCA ports
783 * @v ibdev Infiniband device
784 * @ret num_ports Number of ports
786 int ib_count_ports ( struct ib_device *ibdev ) {
787 struct ib_device *tmp;
790 /* Search for IB devices with the same physical device to
791 * identify port count.
793 for_each_ibdev ( tmp ) {
794 if ( tmp->dev == ibdev->dev )
801 * Set port information
803 * @v ibdev Infiniband device
804 * @v mad Set port information MAD
806 int ib_set_port_info ( struct ib_device *ibdev, union ib_mad *mad ) {
809 /* Adapters with embedded SMAs do not need to support this method */
810 if ( ! ibdev->op->set_port_info ) {
811 DBGC ( ibdev, "IBDEV %p does not support setting port "
812 "information\n", ibdev );
816 if ( ( rc = ibdev->op->set_port_info ( ibdev, mad ) ) != 0 ) {
817 DBGC ( ibdev, "IBDEV %p could not set port information: %s\n",
818 ibdev, strerror ( rc ) );
826 * Set partition key table
828 * @v ibdev Infiniband device
829 * @v mad Set partition key table MAD
831 int ib_set_pkey_table ( struct ib_device *ibdev, union ib_mad *mad ) {
834 /* Adapters with embedded SMAs do not need to support this method */
835 if ( ! ibdev->op->set_pkey_table ) {
836 DBGC ( ibdev, "IBDEV %p does not support setting partition "
837 "key table\n", ibdev );
841 if ( ( rc = ibdev->op->set_pkey_table ( ibdev, mad ) ) != 0 ) {
842 DBGC ( ibdev, "IBDEV %p could not set partition key table: "
843 "%s\n", ibdev, strerror ( rc ) );
850 /***************************************************************************
854 ***************************************************************************
860 * @v ibdev Infiniband device
862 void ib_poll_eq ( struct ib_device *ibdev ) {
863 struct ib_completion_queue *cq;
865 /* Poll device's event queue */
866 ibdev->op->poll_eq ( ibdev );
868 /* Poll all completion queues */
869 list_for_each_entry ( cq, &ibdev->cqs, list )
870 ib_poll_cq ( ibdev, cq );
874 * Single-step the Infiniband event queue
876 * @v process Infiniband event queue process
878 static void ib_step ( struct process *process __unused ) {
879 struct ib_device *ibdev;
881 list_for_each_entry ( ibdev, &open_ib_devices, open_list )
882 ib_poll_eq ( ibdev );
885 /** Infiniband event queue process */
886 PERMANENT_PROCESS ( ib_process, ib_step );
888 /***************************************************************************
890 * Infiniband device creation/destruction
892 ***************************************************************************
896 * Allocate Infiniband device
898 * @v priv_size Size of driver private data area
899 * @ret ibdev Infiniband device, or NULL
901 struct ib_device * alloc_ibdev ( size_t priv_size ) {
902 struct ib_device *ibdev;
906 total_len = ( sizeof ( *ibdev ) + priv_size );
907 ibdev = zalloc ( total_len );
909 drv_priv = ( ( ( void * ) ibdev ) + sizeof ( *ibdev ) );
910 ib_set_drvdata ( ibdev, drv_priv );
911 INIT_LIST_HEAD ( &ibdev->list );
912 INIT_LIST_HEAD ( &ibdev->open_list );
913 INIT_LIST_HEAD ( &ibdev->cqs );
914 INIT_LIST_HEAD ( &ibdev->qps );
915 ibdev->port_state = IB_PORT_STATE_DOWN;
916 ibdev->lid = IB_LID_NONE;
917 ibdev->pkey = IB_PKEY_DEFAULT;
923 * Register Infiniband device
925 * @v ibdev Infiniband device
926 * @ret rc Return status code
928 int register_ibdev ( struct ib_device *ibdev ) {
929 struct ib_driver *driver;
932 /* Add to device list */
934 list_add_tail ( &ibdev->list, &ib_devices );
935 DBGC ( ibdev, "IBDEV %p registered (phys %s)\n", ibdev,
939 for_each_table_entry ( driver, IB_DRIVERS ) {
940 if ( ( rc = driver->probe ( ibdev ) ) != 0 ) {
941 DBGC ( ibdev, "IBDEV %p could not add %s device: %s\n",
942 ibdev, driver->name, strerror ( rc ) );
950 for_each_table_entry_continue_reverse ( driver, IB_DRIVERS )
951 driver->remove ( ibdev );
952 list_del ( &ibdev->list );
958 * Unregister Infiniband device
960 * @v ibdev Infiniband device
962 void unregister_ibdev ( struct ib_device *ibdev ) {
963 struct ib_driver *driver;
966 for_each_table_entry_reverse ( driver, IB_DRIVERS )
967 driver->remove ( ibdev );
969 /* Remove from device list */
970 list_del ( &ibdev->list );
972 DBGC ( ibdev, "IBDEV %p unregistered\n", ibdev );
976 * Find Infiniband device by GID
979 * @ret ibdev Infiniband device, or NULL
981 struct ib_device * find_ibdev ( union ib_gid *gid ) {
982 struct ib_device *ibdev;
984 for_each_ibdev ( ibdev ) {
985 if ( memcmp ( gid, &ibdev->gid, sizeof ( *gid ) ) == 0 )
992 * Get most recently opened Infiniband device
994 * @ret ibdev Most recently opened Infiniband device, or NULL
996 struct ib_device * last_opened_ibdev ( void ) {
997 struct ib_device *ibdev;
999 ibdev = list_first_entry ( &open_ib_devices, struct ib_device,
1004 assert ( ibdev->open_count != 0 );
1008 /* Drag in objects via register_ibdev() */
1009 REQUIRING_SYMBOL ( register_ibdev );
1011 /* Drag in Infiniband configuration */
1012 REQUIRE_OBJECT ( config_infiniband );
1015 REQUIRE_OBJECT ( ipoib );