Annotation of qemu/roms/ipxe/src/net/infiniband.c, revision 1.1.1.1

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

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.