|
|
1.1 root 1: /*
2: * Copyright (C) 2007 Michael Brown <[email protected]>.
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 <ipxe/list.h>
30: #include <ipxe/errortab.h>
31: #include <ipxe/if_arp.h>
32: #include <ipxe/netdevice.h>
33: #include <ipxe/iobuf.h>
34: #include <ipxe/process.h>
35: #include <ipxe/infiniband.h>
36: #include <ipxe/ib_mi.h>
37: #include <ipxe/ib_sma.h>
38:
39: /** @file
40: *
41: * Infiniband protocol
42: *
43: */
44:
45: /** List of Infiniband devices */
46: struct list_head ib_devices = LIST_HEAD_INIT ( ib_devices );
47:
48: /** List of open Infiniband devices, in reverse order of opening */
49: static struct list_head open_ib_devices = LIST_HEAD_INIT ( open_ib_devices );
50:
51: /* Disambiguate the various possible EINPROGRESSes */
52: #define EINPROGRESS_INIT __einfo_error ( EINFO_EINPROGRESS_INIT )
53: #define EINFO_EINPROGRESS_INIT __einfo_uniqify \
54: ( EINFO_EINPROGRESS, 0x01, "Initialising" )
55: #define EINPROGRESS_ARMED __einfo_error ( EINFO_EINPROGRESS_ARMED )
56: #define EINFO_EINPROGRESS_ARMED __einfo_uniqify \
57: ( EINFO_EINPROGRESS, 0x02, "Armed" )
58:
59: /** Human-readable message for the link statuses */
60: struct errortab infiniband_errors[] __errortab = {
61: __einfo_errortab ( EINFO_EINPROGRESS_INIT ),
62: __einfo_errortab ( EINFO_EINPROGRESS_ARMED ),
63: };
64:
65: /***************************************************************************
66: *
67: * Completion queues
68: *
69: ***************************************************************************
70: */
71:
72: /**
73: * Create completion queue
74: *
75: * @v ibdev Infiniband device
76: * @v num_cqes Number of completion queue entries
77: * @v op Completion queue operations
78: * @ret cq New completion queue
79: */
80: struct ib_completion_queue *
81: ib_create_cq ( struct ib_device *ibdev, unsigned int num_cqes,
82: struct ib_completion_queue_operations *op ) {
83: struct ib_completion_queue *cq;
84: int rc;
85:
86: DBGC ( ibdev, "IBDEV %p creating completion queue\n", ibdev );
87:
88: /* Allocate and initialise data structure */
89: cq = zalloc ( sizeof ( *cq ) );
90: if ( ! cq )
91: goto err_alloc_cq;
92: cq->ibdev = ibdev;
93: list_add ( &cq->list, &ibdev->cqs );
94: cq->num_cqes = num_cqes;
95: INIT_LIST_HEAD ( &cq->work_queues );
96: cq->op = op;
97:
98: /* Perform device-specific initialisation and get CQN */
99: if ( ( rc = ibdev->op->create_cq ( ibdev, cq ) ) != 0 ) {
100: DBGC ( ibdev, "IBDEV %p could not initialise completion "
101: "queue: %s\n", ibdev, strerror ( rc ) );
102: goto err_dev_create_cq;
103: }
104:
105: DBGC ( ibdev, "IBDEV %p created %d-entry completion queue %p (%p) "
106: "with CQN %#lx\n", ibdev, num_cqes, cq,
107: ib_cq_get_drvdata ( cq ), cq->cqn );
108: return cq;
109:
110: ibdev->op->destroy_cq ( ibdev, cq );
111: err_dev_create_cq:
112: list_del ( &cq->list );
113: free ( cq );
114: err_alloc_cq:
115: return NULL;
116: }
117:
118: /**
119: * Destroy completion queue
120: *
121: * @v ibdev Infiniband device
122: * @v cq Completion queue
123: */
124: void ib_destroy_cq ( struct ib_device *ibdev,
125: struct ib_completion_queue *cq ) {
126: DBGC ( ibdev, "IBDEV %p destroying completion queue %#lx\n",
127: ibdev, cq->cqn );
128: assert ( list_empty ( &cq->work_queues ) );
129: ibdev->op->destroy_cq ( ibdev, cq );
130: list_del ( &cq->list );
131: free ( cq );
132: }
133:
134: /**
135: * Poll completion queue
136: *
137: * @v ibdev Infiniband device
138: * @v cq Completion queue
139: */
140: void ib_poll_cq ( struct ib_device *ibdev,
141: struct ib_completion_queue *cq ) {
142: struct ib_work_queue *wq;
143:
144: /* Poll completion queue */
145: ibdev->op->poll_cq ( ibdev, cq );
146:
147: /* Refill receive work queues */
148: list_for_each_entry ( wq, &cq->work_queues, list ) {
149: if ( ! wq->is_send )
150: ib_refill_recv ( ibdev, wq->qp );
151: }
152: }
153:
154: /***************************************************************************
155: *
156: * Work queues
157: *
158: ***************************************************************************
159: */
160:
161: /**
162: * Create queue pair
163: *
164: * @v ibdev Infiniband device
165: * @v type Queue pair type
166: * @v num_send_wqes Number of send work queue entries
167: * @v send_cq Send completion queue
168: * @v num_recv_wqes Number of receive work queue entries
169: * @v recv_cq Receive completion queue
170: * @ret qp Queue pair
171: *
172: * The queue pair will be left in the INIT state; you must call
173: * ib_modify_qp() before it is ready to use for sending and receiving.
174: */
175: struct ib_queue_pair * ib_create_qp ( struct ib_device *ibdev,
176: enum ib_queue_pair_type type,
177: unsigned int num_send_wqes,
178: struct ib_completion_queue *send_cq,
179: unsigned int num_recv_wqes,
180: struct ib_completion_queue *recv_cq ) {
181: struct ib_queue_pair *qp;
182: size_t total_size;
183: int rc;
184:
185: DBGC ( ibdev, "IBDEV %p creating queue pair\n", ibdev );
186:
187: /* Allocate and initialise data structure */
188: total_size = ( sizeof ( *qp ) +
189: ( num_send_wqes * sizeof ( qp->send.iobufs[0] ) ) +
190: ( num_recv_wqes * sizeof ( qp->recv.iobufs[0] ) ) );
191: qp = zalloc ( total_size );
192: if ( ! qp )
193: goto err_alloc_qp;
194: qp->ibdev = ibdev;
195: list_add ( &qp->list, &ibdev->qps );
196: qp->type = type;
197: qp->send.qp = qp;
198: qp->send.is_send = 1;
199: qp->send.cq = send_cq;
200: list_add ( &qp->send.list, &send_cq->work_queues );
201: qp->send.psn = ( random() & 0xffffffUL );
202: qp->send.num_wqes = num_send_wqes;
203: qp->send.iobufs = ( ( ( void * ) qp ) + sizeof ( *qp ) );
204: qp->recv.qp = qp;
205: qp->recv.cq = recv_cq;
206: list_add ( &qp->recv.list, &recv_cq->work_queues );
207: qp->recv.psn = ( random() & 0xffffffUL );
208: qp->recv.num_wqes = num_recv_wqes;
209: qp->recv.iobufs = ( ( ( void * ) qp ) + sizeof ( *qp ) +
210: ( num_send_wqes * sizeof ( qp->send.iobufs[0] ) ));
211: INIT_LIST_HEAD ( &qp->mgids );
212:
213: /* Perform device-specific initialisation and get QPN */
214: if ( ( rc = ibdev->op->create_qp ( ibdev, qp ) ) != 0 ) {
215: DBGC ( ibdev, "IBDEV %p could not initialise queue pair: "
216: "%s\n", ibdev, strerror ( rc ) );
217: goto err_dev_create_qp;
218: }
219: DBGC ( ibdev, "IBDEV %p created queue pair %p (%p) with QPN %#lx\n",
220: ibdev, qp, ib_qp_get_drvdata ( qp ), qp->qpn );
221: DBGC ( ibdev, "IBDEV %p QPN %#lx has %d send entries at [%p,%p)\n",
222: ibdev, qp->qpn, num_send_wqes, qp->send.iobufs,
223: qp->recv.iobufs );
224: DBGC ( ibdev, "IBDEV %p QPN %#lx has %d receive entries at [%p,%p)\n",
225: ibdev, qp->qpn, num_recv_wqes, qp->recv.iobufs,
226: ( ( ( void * ) qp ) + total_size ) );
227:
228: /* Calculate externally-visible QPN */
229: switch ( type ) {
230: case IB_QPT_SMI:
231: qp->ext_qpn = IB_QPN_SMI;
232: break;
233: case IB_QPT_GSI:
234: qp->ext_qpn = IB_QPN_GSI;
235: break;
236: default:
237: qp->ext_qpn = qp->qpn;
238: break;
239: }
240: if ( qp->ext_qpn != qp->qpn ) {
241: DBGC ( ibdev, "IBDEV %p QPN %#lx has external QPN %#lx\n",
242: ibdev, qp->qpn, qp->ext_qpn );
243: }
244:
245: return qp;
246:
247: ibdev->op->destroy_qp ( ibdev, qp );
248: err_dev_create_qp:
249: list_del ( &qp->send.list );
250: list_del ( &qp->recv.list );
251: list_del ( &qp->list );
252: free ( qp );
253: err_alloc_qp:
254: return NULL;
255: }
256:
257: /**
258: * Modify queue pair
259: *
260: * @v ibdev Infiniband device
261: * @v qp Queue pair
262: * @v av New address vector, if applicable
263: * @ret rc Return status code
264: */
265: int ib_modify_qp ( struct ib_device *ibdev, struct ib_queue_pair *qp ) {
266: int rc;
267:
268: DBGC ( ibdev, "IBDEV %p modifying QPN %#lx\n", ibdev, qp->qpn );
269:
270: if ( ( rc = ibdev->op->modify_qp ( ibdev, qp ) ) != 0 ) {
271: DBGC ( ibdev, "IBDEV %p could not modify QPN %#lx: %s\n",
272: ibdev, qp->qpn, strerror ( rc ) );
273: return rc;
274: }
275:
276: return 0;
277: }
278:
279: /**
280: * Destroy queue pair
281: *
282: * @v ibdev Infiniband device
283: * @v qp Queue pair
284: */
285: void ib_destroy_qp ( struct ib_device *ibdev, struct ib_queue_pair *qp ) {
286: struct io_buffer *iobuf;
287: unsigned int i;
288:
289: DBGC ( ibdev, "IBDEV %p destroying QPN %#lx\n",
290: ibdev, qp->qpn );
291:
292: assert ( list_empty ( &qp->mgids ) );
293:
294: /* Perform device-specific destruction */
295: ibdev->op->destroy_qp ( ibdev, qp );
296:
297: /* Complete any remaining I/O buffers with errors */
298: for ( i = 0 ; i < qp->send.num_wqes ; i++ ) {
299: if ( ( iobuf = qp->send.iobufs[i] ) != NULL )
300: ib_complete_send ( ibdev, qp, iobuf, -ECANCELED );
301: }
302: for ( i = 0 ; i < qp->recv.num_wqes ; i++ ) {
303: if ( ( iobuf = qp->recv.iobufs[i] ) != NULL ) {
304: ib_complete_recv ( ibdev, qp, NULL, iobuf,
305: -ECANCELED );
306: }
307: }
308:
309: /* Remove work queues from completion queue */
310: list_del ( &qp->send.list );
311: list_del ( &qp->recv.list );
312:
313: /* Free QP */
314: list_del ( &qp->list );
315: free ( qp );
316: }
317:
318: /**
319: * Find queue pair by QPN
320: *
321: * @v ibdev Infiniband device
322: * @v qpn Queue pair number
323: * @ret qp Queue pair, or NULL
324: */
325: struct ib_queue_pair * ib_find_qp_qpn ( struct ib_device *ibdev,
326: unsigned long qpn ) {
327: struct ib_queue_pair *qp;
328:
329: list_for_each_entry ( qp, &ibdev->qps, list ) {
330: if ( ( qpn == qp->qpn ) || ( qpn == qp->ext_qpn ) )
331: return qp;
332: }
333: return NULL;
334: }
335:
336: /**
337: * Find queue pair by multicast GID
338: *
339: * @v ibdev Infiniband device
340: * @v gid Multicast GID
341: * @ret qp Queue pair, or NULL
342: */
343: struct ib_queue_pair * ib_find_qp_mgid ( struct ib_device *ibdev,
344: union ib_gid *gid ) {
345: struct ib_queue_pair *qp;
346: struct ib_multicast_gid *mgid;
347:
348: list_for_each_entry ( qp, &ibdev->qps, list ) {
349: list_for_each_entry ( mgid, &qp->mgids, list ) {
350: if ( memcmp ( &mgid->gid, gid,
351: sizeof ( mgid->gid ) ) == 0 ) {
352: return qp;
353: }
354: }
355: }
356: return NULL;
357: }
358:
359: /**
360: * Find work queue belonging to completion queue
361: *
362: * @v cq Completion queue
363: * @v qpn Queue pair number
364: * @v is_send Find send work queue (rather than receive)
365: * @ret wq Work queue, or NULL if not found
366: */
367: struct ib_work_queue * ib_find_wq ( struct ib_completion_queue *cq,
368: unsigned long qpn, int is_send ) {
369: struct ib_work_queue *wq;
370:
371: list_for_each_entry ( wq, &cq->work_queues, list ) {
372: if ( ( wq->qp->qpn == qpn ) && ( wq->is_send == is_send ) )
373: return wq;
374: }
375: return NULL;
376: }
377:
378: /**
379: * Post send work queue entry
380: *
381: * @v ibdev Infiniband device
382: * @v qp Queue pair
383: * @v av Address vector
384: * @v iobuf I/O buffer
385: * @ret rc Return status code
386: */
387: int ib_post_send ( struct ib_device *ibdev, struct ib_queue_pair *qp,
388: struct ib_address_vector *av,
389: struct io_buffer *iobuf ) {
390: struct ib_address_vector av_copy;
391: int rc;
392:
393: /* Check queue fill level */
394: if ( qp->send.fill >= qp->send.num_wqes ) {
395: DBGC ( ibdev, "IBDEV %p QPN %#lx send queue full\n",
396: ibdev, qp->qpn );
397: return -ENOBUFS;
398: }
399:
400: /* Use default address vector if none specified */
401: if ( ! av )
402: av = &qp->av;
403:
404: /* Make modifiable copy of address vector */
405: memcpy ( &av_copy, av, sizeof ( av_copy ) );
406: av = &av_copy;
407:
408: /* Fill in optional parameters in address vector */
409: if ( ! av->qkey )
410: av->qkey = qp->qkey;
411: if ( ! av->rate )
412: av->rate = IB_RATE_2_5;
413:
414: /* Post to hardware */
415: if ( ( rc = ibdev->op->post_send ( ibdev, qp, av, iobuf ) ) != 0 ) {
416: DBGC ( ibdev, "IBDEV %p QPN %#lx could not post send WQE: "
417: "%s\n", ibdev, qp->qpn, strerror ( rc ) );
418: return rc;
419: }
420:
421: qp->send.fill++;
422: return 0;
423: }
424:
425: /**
426: * Post receive work queue entry
427: *
428: * @v ibdev Infiniband device
429: * @v qp Queue pair
430: * @v iobuf I/O buffer
431: * @ret rc Return status code
432: */
433: int ib_post_recv ( struct ib_device *ibdev, struct ib_queue_pair *qp,
434: struct io_buffer *iobuf ) {
435: int rc;
436:
437: /* Check packet length */
438: if ( iob_tailroom ( iobuf ) < IB_MAX_PAYLOAD_SIZE ) {
439: DBGC ( ibdev, "IBDEV %p QPN %#lx wrong RX buffer size (%zd)\n",
440: ibdev, qp->qpn, iob_tailroom ( iobuf ) );
441: return -EINVAL;
442: }
443:
444: /* Check queue fill level */
445: if ( qp->recv.fill >= qp->recv.num_wqes ) {
446: DBGC ( ibdev, "IBDEV %p QPN %#lx receive queue full\n",
447: ibdev, qp->qpn );
448: return -ENOBUFS;
449: }
450:
451: /* Post to hardware */
452: if ( ( rc = ibdev->op->post_recv ( ibdev, qp, iobuf ) ) != 0 ) {
453: DBGC ( ibdev, "IBDEV %p QPN %#lx could not post receive WQE: "
454: "%s\n", ibdev, qp->qpn, strerror ( rc ) );
455: return rc;
456: }
457:
458: qp->recv.fill++;
459: return 0;
460: }
461:
462: /**
463: * Complete send work queue entry
464: *
465: * @v ibdev Infiniband device
466: * @v qp Queue pair
467: * @v iobuf I/O buffer
468: * @v rc Completion status code
469: */
470: void ib_complete_send ( struct ib_device *ibdev, struct ib_queue_pair *qp,
471: struct io_buffer *iobuf, int rc ) {
472:
473: if ( qp->send.cq->op->complete_send ) {
474: qp->send.cq->op->complete_send ( ibdev, qp, iobuf, rc );
475: } else {
476: free_iob ( iobuf );
477: }
478: qp->send.fill--;
479: }
480:
481: /**
482: * Complete receive work queue entry
483: *
484: * @v ibdev Infiniband device
485: * @v qp Queue pair
486: * @v av Address vector, or NULL
487: * @v iobuf I/O buffer
488: * @v rc Completion status code
489: */
490: void ib_complete_recv ( struct ib_device *ibdev, struct ib_queue_pair *qp,
491: struct ib_address_vector *av,
492: struct io_buffer *iobuf, int rc ) {
493:
494: if ( qp->recv.cq->op->complete_recv ) {
495: qp->recv.cq->op->complete_recv ( ibdev, qp, av, iobuf, rc );
496: } else {
497: free_iob ( iobuf );
498: }
499: qp->recv.fill--;
500: }
501:
502: /**
503: * Refill receive work queue
504: *
505: * @v ibdev Infiniband device
506: * @v qp Queue pair
507: */
508: void ib_refill_recv ( struct ib_device *ibdev, struct ib_queue_pair *qp ) {
509: struct io_buffer *iobuf;
510: int rc;
511:
512: /* Keep filling while unfilled entries remain */
513: while ( qp->recv.fill < qp->recv.num_wqes ) {
514:
515: /* Allocate I/O buffer */
516: iobuf = alloc_iob ( IB_MAX_PAYLOAD_SIZE );
517: if ( ! iobuf ) {
518: /* Non-fatal; we will refill on next attempt */
519: return;
520: }
521:
522: /* Post I/O buffer */
523: if ( ( rc = ib_post_recv ( ibdev, qp, iobuf ) ) != 0 ) {
524: DBGC ( ibdev, "IBDEV %p could not refill: %s\n",
525: ibdev, strerror ( rc ) );
526: free_iob ( iobuf );
527: /* Give up */
528: return;
529: }
530: }
531: }
532:
533: /***************************************************************************
534: *
535: * Link control
536: *
537: ***************************************************************************
538: */
539:
540: /**
541: * Get link state
542: *
543: * @v ibdev Infiniband device
544: * @ret rc Link status code
545: */
546: int ib_link_rc ( struct ib_device *ibdev ) {
547: switch ( ibdev->port_state ) {
548: case IB_PORT_STATE_DOWN: return -ENOTCONN;
549: case IB_PORT_STATE_INIT: return -EINPROGRESS_INIT;
550: case IB_PORT_STATE_ARMED: return -EINPROGRESS_ARMED;
551: case IB_PORT_STATE_ACTIVE: return 0;
552: default: return -EINVAL;
553: }
554: }
555:
556: /**
557: * Textual representation of Infiniband link state
558: *
559: * @v ibdev Infiniband device
560: * @ret link_text Link state text
561: */
562: static const char * ib_link_state_text ( struct ib_device *ibdev ) {
563: switch ( ibdev->port_state ) {
564: case IB_PORT_STATE_DOWN: return "DOWN";
565: case IB_PORT_STATE_INIT: return "INIT";
566: case IB_PORT_STATE_ARMED: return "ARMED";
567: case IB_PORT_STATE_ACTIVE: return "ACTIVE";
568: default: return "UNKNOWN";
569: }
570: }
571:
572: /**
573: * Notify drivers of Infiniband device or link state change
574: *
575: * @v ibdev Infiniband device
576: */
577: static void ib_notify ( struct ib_device *ibdev ) {
578: struct ib_driver *driver;
579:
580: for_each_table_entry ( driver, IB_DRIVERS )
581: driver->notify ( ibdev );
582: }
583:
584: /**
585: * Notify of Infiniband link state change
586: *
587: * @v ibdev Infiniband device
588: */
589: void ib_link_state_changed ( struct ib_device *ibdev ) {
590:
591: DBGC ( ibdev, "IBDEV %p link state is %s\n",
592: ibdev, ib_link_state_text ( ibdev ) );
593:
594: /* Notify drivers of link state change */
595: ib_notify ( ibdev );
596: }
597:
598: /**
599: * Open port
600: *
601: * @v ibdev Infiniband device
602: * @ret rc Return status code
603: */
604: int ib_open ( struct ib_device *ibdev ) {
605: int rc;
606:
607: /* Increment device open request counter */
608: if ( ibdev->open_count++ > 0 ) {
609: /* Device was already open; do nothing */
610: return 0;
611: }
612:
613: /* Create subnet management interface */
614: ibdev->smi = ib_create_mi ( ibdev, IB_QPT_SMI );
615: if ( ! ibdev->smi ) {
616: DBGC ( ibdev, "IBDEV %p could not create SMI\n", ibdev );
617: rc = -ENOMEM;
618: goto err_create_smi;
619: }
620:
621: /* Create subnet management agent */
622: if ( ( rc = ib_create_sma ( ibdev, ibdev->smi ) ) != 0 ) {
623: DBGC ( ibdev, "IBDEV %p could not create SMA: %s\n",
624: ibdev, strerror ( rc ) );
625: goto err_create_sma;
626: }
627:
628: /* Create general services interface */
629: ibdev->gsi = ib_create_mi ( ibdev, IB_QPT_GSI );
630: if ( ! ibdev->gsi ) {
631: DBGC ( ibdev, "IBDEV %p could not create GSI\n", ibdev );
632: rc = -ENOMEM;
633: goto err_create_gsi;
634: }
635:
636: /* Open device */
637: if ( ( rc = ibdev->op->open ( ibdev ) ) != 0 ) {
638: DBGC ( ibdev, "IBDEV %p could not open: %s\n",
639: ibdev, strerror ( rc ) );
640: goto err_open;
641: }
642:
643: /* Add to head of open devices list */
644: list_add ( &ibdev->open_list, &open_ib_devices );
645:
646: /* Notify drivers of device state change */
647: ib_notify ( ibdev );
648:
649: assert ( ibdev->open_count == 1 );
650: return 0;
651:
652: ibdev->op->close ( ibdev );
653: err_open:
654: ib_destroy_mi ( ibdev, ibdev->gsi );
655: err_create_gsi:
656: ib_destroy_sma ( ibdev, ibdev->smi );
657: err_create_sma:
658: ib_destroy_mi ( ibdev, ibdev->smi );
659: err_create_smi:
660: assert ( ibdev->open_count == 1 );
661: ibdev->open_count = 0;
662: return rc;
663: }
664:
665: /**
666: * Close port
667: *
668: * @v ibdev Infiniband device
669: */
670: void ib_close ( struct ib_device *ibdev ) {
671:
672: /* Decrement device open request counter */
673: ibdev->open_count--;
674:
675: /* Close device if this was the last remaining requested opening */
676: if ( ibdev->open_count == 0 ) {
677: ib_notify ( ibdev );
678: list_del ( &ibdev->open_list );
679: ib_destroy_mi ( ibdev, ibdev->gsi );
680: ib_destroy_sma ( ibdev, ibdev->smi );
681: ib_destroy_mi ( ibdev, ibdev->smi );
682: ibdev->op->close ( ibdev );
683: }
684: }
685:
686: /***************************************************************************
687: *
688: * Multicast
689: *
690: ***************************************************************************
691: */
692:
693: /**
694: * Attach to multicast group
695: *
696: * @v ibdev Infiniband device
697: * @v qp Queue pair
698: * @v gid Multicast GID
699: * @ret rc Return status code
700: *
701: * Note that this function handles only the local device's attachment
702: * to the multicast GID; it does not issue the relevant MADs to join
703: * the multicast group on the subnet.
704: */
705: int ib_mcast_attach ( struct ib_device *ibdev, struct ib_queue_pair *qp,
706: union ib_gid *gid ) {
707: struct ib_multicast_gid *mgid;
708: int rc;
709:
710: /* Add to software multicast GID list */
711: mgid = zalloc ( sizeof ( *mgid ) );
712: if ( ! mgid ) {
713: rc = -ENOMEM;
714: goto err_alloc_mgid;
715: }
716: memcpy ( &mgid->gid, gid, sizeof ( mgid->gid ) );
717: list_add ( &mgid->list, &qp->mgids );
718:
719: /* Add to hardware multicast GID list */
720: if ( ( rc = ibdev->op->mcast_attach ( ibdev, qp, gid ) ) != 0 )
721: goto err_dev_mcast_attach;
722:
723: return 0;
724:
725: err_dev_mcast_attach:
726: list_del ( &mgid->list );
727: free ( mgid );
728: err_alloc_mgid:
729: return rc;
730: }
731:
732: /**
733: * Detach from multicast group
734: *
735: * @v ibdev Infiniband device
736: * @v qp Queue pair
737: * @v gid Multicast GID
738: */
739: void ib_mcast_detach ( struct ib_device *ibdev, struct ib_queue_pair *qp,
740: union ib_gid *gid ) {
741: struct ib_multicast_gid *mgid;
742:
743: /* Remove from hardware multicast GID list */
744: ibdev->op->mcast_detach ( ibdev, qp, gid );
745:
746: /* Remove from software multicast GID list */
747: list_for_each_entry ( mgid, &qp->mgids, list ) {
748: if ( memcmp ( &mgid->gid, gid, sizeof ( mgid->gid ) ) == 0 ) {
749: list_del ( &mgid->list );
750: free ( mgid );
751: break;
752: }
753: }
754: }
755:
756: /***************************************************************************
757: *
758: * Miscellaneous
759: *
760: ***************************************************************************
761: */
762:
763: /**
764: * Count Infiniband HCA ports
765: *
766: * @v ibdev Infiniband device
767: * @ret num_ports Number of ports
768: */
769: int ib_count_ports ( struct ib_device *ibdev ) {
770: struct ib_device *tmp;
771: int num_ports = 0;
772:
773: /* Search for IB devices with the same physical device to
774: * identify port count.
775: */
776: for_each_ibdev ( tmp ) {
777: if ( tmp->dev == ibdev->dev )
778: num_ports++;
779: }
780: return num_ports;
781: }
782:
783: /**
784: * Set port information
785: *
786: * @v ibdev Infiniband device
787: * @v mad Set port information MAD
788: */
789: int ib_set_port_info ( struct ib_device *ibdev, union ib_mad *mad ) {
790: int rc;
791:
792: /* Adapters with embedded SMAs do not need to support this method */
793: if ( ! ibdev->op->set_port_info ) {
794: DBGC ( ibdev, "IBDEV %p does not support setting port "
795: "information\n", ibdev );
796: return -ENOTSUP;
797: }
798:
799: if ( ( rc = ibdev->op->set_port_info ( ibdev, mad ) ) != 0 ) {
800: DBGC ( ibdev, "IBDEV %p could not set port information: %s\n",
801: ibdev, strerror ( rc ) );
802: return rc;
803: }
804:
805: return 0;
806: };
807:
808: /**
809: * Set partition key table
810: *
811: * @v ibdev Infiniband device
812: * @v mad Set partition key table MAD
813: */
814: int ib_set_pkey_table ( struct ib_device *ibdev, union ib_mad *mad ) {
815: int rc;
816:
817: /* Adapters with embedded SMAs do not need to support this method */
818: if ( ! ibdev->op->set_pkey_table ) {
819: DBGC ( ibdev, "IBDEV %p does not support setting partition "
820: "key table\n", ibdev );
821: return -ENOTSUP;
822: }
823:
824: if ( ( rc = ibdev->op->set_pkey_table ( ibdev, mad ) ) != 0 ) {
825: DBGC ( ibdev, "IBDEV %p could not set partition key table: "
826: "%s\n", ibdev, strerror ( rc ) );
827: return rc;
828: }
829:
830: return 0;
831: };
832:
833: /***************************************************************************
834: *
835: * Event queues
836: *
837: ***************************************************************************
838: */
839:
840: /**
841: * Poll event queue
842: *
843: * @v ibdev Infiniband device
844: */
845: void ib_poll_eq ( struct ib_device *ibdev ) {
846: struct ib_completion_queue *cq;
847:
848: /* Poll device's event queue */
849: ibdev->op->poll_eq ( ibdev );
850:
851: /* Poll all completion queues */
852: list_for_each_entry ( cq, &ibdev->cqs, list )
853: ib_poll_cq ( ibdev, cq );
854: }
855:
856: /**
857: * Single-step the Infiniband event queue
858: *
859: * @v process Infiniband event queue process
860: */
861: static void ib_step ( struct process *process __unused ) {
862: struct ib_device *ibdev;
863:
864: for_each_ibdev ( ibdev )
865: ib_poll_eq ( ibdev );
866: }
867:
868: /** Infiniband event queue process */
869: struct process ib_process __permanent_process = {
870: .list = LIST_HEAD_INIT ( ib_process.list ),
871: .step = ib_step,
872: };
873:
874: /***************************************************************************
875: *
876: * Infiniband device creation/destruction
877: *
878: ***************************************************************************
879: */
880:
881: /**
882: * Allocate Infiniband device
883: *
884: * @v priv_size Size of driver private data area
885: * @ret ibdev Infiniband device, or NULL
886: */
887: struct ib_device * alloc_ibdev ( size_t priv_size ) {
888: struct ib_device *ibdev;
889: void *drv_priv;
890: size_t total_len;
891:
892: total_len = ( sizeof ( *ibdev ) + priv_size );
893: ibdev = zalloc ( total_len );
894: if ( ibdev ) {
895: drv_priv = ( ( ( void * ) ibdev ) + sizeof ( *ibdev ) );
896: ib_set_drvdata ( ibdev, drv_priv );
897: INIT_LIST_HEAD ( &ibdev->list );
898: INIT_LIST_HEAD ( &ibdev->open_list );
899: INIT_LIST_HEAD ( &ibdev->cqs );
900: INIT_LIST_HEAD ( &ibdev->qps );
901: ibdev->port_state = IB_PORT_STATE_DOWN;
902: ibdev->lid = IB_LID_NONE;
903: ibdev->pkey = IB_PKEY_DEFAULT;
904: }
905: return ibdev;
906: }
907:
908: /**
909: * Register Infiniband device
910: *
911: * @v ibdev Infiniband device
912: * @ret rc Return status code
913: */
914: int register_ibdev ( struct ib_device *ibdev ) {
915: struct ib_driver *driver;
916: int rc;
917:
918: /* Add to device list */
919: ibdev_get ( ibdev );
920: list_add_tail ( &ibdev->list, &ib_devices );
921: DBGC ( ibdev, "IBDEV %p registered (phys %s)\n", ibdev,
922: ibdev->dev->name );
923:
924: /* Probe device */
925: for_each_table_entry ( driver, IB_DRIVERS ) {
926: if ( ( rc = driver->probe ( ibdev ) ) != 0 ) {
927: DBGC ( ibdev, "IBDEV %p could not add %s device: %s\n",
928: ibdev, driver->name, strerror ( rc ) );
929: goto err_probe;
930: }
931: }
932:
933: return 0;
934:
935: err_probe:
936: for_each_table_entry_continue_reverse ( driver, IB_DRIVERS )
937: driver->remove ( ibdev );
938: list_del ( &ibdev->list );
939: ibdev_put ( ibdev );
940: return rc;
941: }
942:
943: /**
944: * Unregister Infiniband device
945: *
946: * @v ibdev Infiniband device
947: */
948: void unregister_ibdev ( struct ib_device *ibdev ) {
949: struct ib_driver *driver;
950:
951: /* Remove device */
952: for_each_table_entry_reverse ( driver, IB_DRIVERS )
953: driver->remove ( ibdev );
954:
955: /* Remove from device list */
956: list_del ( &ibdev->list );
957: ibdev_put ( ibdev );
958: DBGC ( ibdev, "IBDEV %p unregistered\n", ibdev );
959: }
960:
961: /**
962: * Find Infiniband device by GID
963: *
964: * @v gid GID
965: * @ret ibdev Infiniband device, or NULL
966: */
967: struct ib_device * find_ibdev ( union ib_gid *gid ) {
968: struct ib_device *ibdev;
969:
970: for_each_ibdev ( ibdev ) {
971: if ( memcmp ( gid, &ibdev->gid, sizeof ( *gid ) ) == 0 )
972: return ibdev;
973: }
974: return NULL;
975: }
976:
977: /**
978: * Get most recently opened Infiniband device
979: *
980: * @ret ibdev Most recently opened Infiniband device, or NULL
981: */
982: struct ib_device * last_opened_ibdev ( void ) {
983: struct ib_device *ibdev;
984:
985: ibdev = list_first_entry ( &open_ib_devices, struct ib_device,
986: open_list );
987: if ( ! ibdev )
988: return NULL;
989:
990: assert ( ibdev->open_count != 0 );
991: return ibdev;
992: }
993:
994: /* Drag in IPoIB */
995: REQUIRE_OBJECT ( ipoib );
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.