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
);