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

1.1       root        1: /*
                      2:  * Copyright (C) 2009 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 <string.h>
                     24: #include <byteswap.h>
                     25: #include <errno.h>
                     26: #include <ipxe/infiniband.h>
                     27: #include <ipxe/ib_mi.h>
                     28: #include <ipxe/ib_pathrec.h>
                     29: 
                     30: /** @file
                     31:  *
                     32:  * Infiniband path lookups
                     33:  *
                     34:  */
                     35: 
                     36: /**
                     37:  * Handle path transaction completion
                     38:  *
                     39:  * @v ibdev            Infiniband device
                     40:  * @v mi               Management interface
                     41:  * @v madx             Management transaction
                     42:  * @v rc               Status code
                     43:  * @v mad              Received MAD (or NULL on error)
                     44:  * @v av               Source address vector (or NULL on error)
                     45:  */
                     46: static void ib_path_complete ( struct ib_device *ibdev,
                     47:                               struct ib_mad_interface *mi,
                     48:                               struct ib_mad_transaction *madx,
                     49:                               int rc, union ib_mad *mad,
                     50:                               struct ib_address_vector *av __unused ) {
                     51:        struct ib_path *path = ib_madx_get_ownerdata ( madx );
                     52:        union ib_gid *dgid = &path->av.gid;
                     53:        struct ib_path_record *pathrec = &mad->sa.sa_data.path_record;
                     54: 
                     55:        /* Report failures */
                     56:        if ( ( rc == 0 ) && ( mad->hdr.status != htons ( IB_MGMT_STATUS_OK ) ))
                     57:                rc = -ENETUNREACH;
                     58:        if ( rc != 0 ) {
                     59:                DBGC ( ibdev, "IBDEV %p path lookup for " IB_GID_FMT
                     60:                       " failed: %s\n",
                     61:                       ibdev, IB_GID_ARGS ( dgid ), strerror ( rc ) );
                     62:                goto out;
                     63:        }
                     64: 
                     65:        /* Extract values from MAD */
                     66:        path->av.lid = ntohs ( pathrec->dlid );
                     67:        path->av.sl = ( pathrec->reserved__sl & 0x0f );
                     68:        path->av.rate = ( pathrec->rate_selector__rate & 0x3f );
                     69:        DBGC ( ibdev, "IBDEV %p path to " IB_GID_FMT " is %04x sl %d rate "
                     70:               "%d\n", ibdev, IB_GID_ARGS ( dgid ), path->av.lid, path->av.sl,
                     71:               path->av.rate );
                     72: 
                     73:  out:
                     74:        /* Destroy the completed transaction */
                     75:        ib_destroy_madx ( ibdev, mi, madx );
                     76:        path->madx = NULL;
                     77: 
                     78:        /* Hand off to upper completion handler */
                     79:        path->op->complete ( ibdev, path, rc, &path->av );
                     80: }
                     81: 
                     82: /** Path transaction completion operations */
                     83: static struct ib_mad_transaction_operations ib_path_op = {
                     84:        .complete = ib_path_complete,
                     85: };
                     86: 
                     87: /**
                     88:  * Create path
                     89:  *
                     90:  * @v ibdev            Infiniband device
                     91:  * @v av               Address vector to complete
                     92:  * @v op               Path operations
                     93:  * @ret path           Path
                     94:  */
                     95: struct ib_path *
                     96: ib_create_path ( struct ib_device *ibdev, struct ib_address_vector *av,
                     97:                 struct ib_path_operations *op ) {
                     98:        struct ib_path *path;
                     99:        union ib_mad mad;
                    100:        struct ib_mad_sa *sa = &mad.sa;
                    101: 
                    102:        /* Allocate and initialise structure */
                    103:        path = zalloc ( sizeof ( *path ) );
                    104:        if ( ! path )
                    105:                goto err_alloc_path;
                    106:        path->ibdev = ibdev;
                    107:        memcpy ( &path->av, av, sizeof ( path->av ) );
                    108:        path->op = op;
                    109: 
                    110:        /* Construct path request */
                    111:        memset ( sa, 0, sizeof ( *sa ) );
                    112:        sa->mad_hdr.mgmt_class = IB_MGMT_CLASS_SUBN_ADM;
                    113:        sa->mad_hdr.class_version = IB_SA_CLASS_VERSION;
                    114:        sa->mad_hdr.method = IB_MGMT_METHOD_GET;
                    115:        sa->mad_hdr.attr_id = htons ( IB_SA_ATTR_PATH_REC );
                    116:        sa->sa_hdr.comp_mask[1] =
                    117:                htonl ( IB_SA_PATH_REC_DGID | IB_SA_PATH_REC_SGID );
                    118:        memcpy ( &sa->sa_data.path_record.dgid, &path->av.gid,
                    119:                 sizeof ( sa->sa_data.path_record.dgid ) );
                    120:        memcpy ( &sa->sa_data.path_record.sgid, &ibdev->gid,
                    121:                 sizeof ( sa->sa_data.path_record.sgid ) );
                    122: 
                    123:        /* Create management transaction */
                    124:        path->madx = ib_create_madx ( ibdev, ibdev->gsi, &mad, NULL,
                    125:                                      &ib_path_op );
                    126:        if ( ! path->madx )
                    127:                goto err_create_madx;
                    128:        ib_madx_set_ownerdata ( path->madx, path );
                    129: 
                    130:        return path;
                    131: 
                    132:        ib_destroy_madx ( ibdev, ibdev->gsi, path->madx );
                    133:  err_create_madx:
                    134:        free ( path );
                    135:  err_alloc_path:
                    136:        return NULL;
                    137: }
                    138: 
                    139: /**
                    140:  * Destroy path
                    141:  *
                    142:  * @v ibdev            Infiniband device
                    143:  * @v path             Path
                    144:  */
                    145: void ib_destroy_path ( struct ib_device *ibdev, struct ib_path *path ) {
                    146: 
                    147:        if ( path->madx )
                    148:                ib_destroy_madx ( ibdev, ibdev->gsi, path->madx );
                    149:        free ( path );
                    150: }
                    151: 
                    152: /** Number of path cache entries
                    153:  *
                    154:  * Must be a power of two.
                    155:  */
                    156: #define IB_NUM_CACHED_PATHS 4
                    157: 
                    158: /** A cached path */
                    159: struct ib_cached_path {
                    160:        /** Path */
                    161:        struct ib_path *path;
                    162: };
                    163: 
                    164: /** Path cache */
                    165: static struct ib_cached_path ib_path_cache[IB_NUM_CACHED_PATHS];
                    166: 
                    167: /** Oldest path cache entry index */
                    168: static unsigned int ib_path_cache_idx;
                    169: 
                    170: /**
                    171:  * Find path cache entry
                    172:  *
                    173:  * @v ibdev            Infiniband device
                    174:  * @v dgid             Destination GID
                    175:  * @ret path           Path cache entry, or NULL
                    176:  */
                    177: static struct ib_cached_path *
                    178: ib_find_path_cache_entry ( struct ib_device *ibdev, union ib_gid *dgid ) {
                    179:        struct ib_cached_path *cached;
                    180:        unsigned int i;
                    181: 
                    182:        for ( i = 0 ; i < IB_NUM_CACHED_PATHS ; i++ ) {
                    183:                cached = &ib_path_cache[i];
                    184:                if ( ! cached->path )
                    185:                        continue;
                    186:                if ( cached->path->ibdev != ibdev )
                    187:                        continue;
                    188:                if ( memcmp ( &cached->path->av.gid, dgid,
                    189:                              sizeof ( cached->path->av.gid ) ) != 0 )
                    190:                        continue;
                    191:                return cached;
                    192:        }
                    193: 
                    194:        return NULL;
                    195: }
                    196: 
                    197: /**
                    198:  * Handle cached path transaction completion
                    199:  *
                    200:  * @v ibdev            Infiniband device
                    201:  * @v path             Path
                    202:  * @v rc               Status code
                    203:  * @v av               Address vector, or NULL on error
                    204:  */
                    205: static void ib_cached_path_complete ( struct ib_device *ibdev,
                    206:                                      struct ib_path *path, int rc,
                    207:                                      struct ib_address_vector *av __unused ) {
                    208:        struct ib_cached_path *cached = ib_path_get_ownerdata ( path );
                    209: 
                    210:        /* If the transaction failed, erase the cache entry */
                    211:        if ( rc != 0 ) {
                    212:                /* Destroy the old cache entry */
                    213:                ib_destroy_path ( ibdev, path );
                    214:                memset ( cached, 0, sizeof ( *cached ) );
                    215:                return;
                    216:        }
                    217: 
                    218:        /* Do not destroy the completed transaction; we still need to
                    219:         * refer to the resolved path.
                    220:         */
                    221: }
                    222: 
                    223: /** Cached path transaction completion operations */
                    224: static struct ib_path_operations ib_cached_path_op = {
                    225:        .complete = ib_cached_path_complete,
                    226: };
                    227: 
                    228: /**
                    229:  * Resolve path
                    230:  *
                    231:  * @v ibdev            Infiniband device
                    232:  * @v av               Address vector to complete
                    233:  * @ret rc             Return status code
                    234:  *
                    235:  * This provides a non-transactional way to resolve a path, via a
                    236:  * cache similar to ARP.
                    237:  */
                    238: int ib_resolve_path ( struct ib_device *ibdev, struct ib_address_vector *av ) {
                    239:        union ib_gid *gid = &av->gid;
                    240:        struct ib_cached_path *cached;
                    241:        unsigned int cache_idx;
                    242: 
                    243:        /* Sanity check */
                    244:        if ( ! av->gid_present ) {
                    245:                DBGC ( ibdev, "IBDEV %p attempt to look up path without GID\n",
                    246:                       ibdev );
                    247:                return -EINVAL;
                    248:        }
                    249: 
                    250:        /* Look in cache for a matching entry */
                    251:        cached = ib_find_path_cache_entry ( ibdev, gid );
                    252:        if ( cached && cached->path->av.lid ) {
                    253:                /* Populated entry found */
                    254:                av->lid = cached->path->av.lid;
                    255:                av->rate = cached->path->av.rate;
                    256:                av->sl = cached->path->av.sl;
                    257:                DBGC2 ( ibdev, "IBDEV %p cache hit for " IB_GID_FMT "\n",
                    258:                        ibdev, IB_GID_ARGS ( gid ) );
                    259:                return 0;
                    260:        }
                    261:        DBGC ( ibdev, "IBDEV %p cache miss for " IB_GID_FMT "%s\n", ibdev,
                    262:               IB_GID_ARGS ( gid ), ( cached ? " (in progress)" : "" ) );
                    263: 
                    264:        /* If lookup is already in progress, do nothing */
                    265:        if ( cached )
                    266:                return -ENOENT;
                    267: 
                    268:        /* Locate a new cache entry to use */
                    269:        cache_idx = ( (ib_path_cache_idx++) % IB_NUM_CACHED_PATHS );
                    270:        cached = &ib_path_cache[cache_idx];
                    271: 
                    272:        /* Destroy the old cache entry */
                    273:        if ( cached->path )
                    274:                ib_destroy_path ( ibdev, cached->path );
                    275:        memset ( cached, 0, sizeof ( *cached ) );
                    276: 
                    277:        /* Create new path */
                    278:        cached->path = ib_create_path ( ibdev, av, &ib_cached_path_op );
                    279:        if ( ! cached->path ) {
                    280:                DBGC ( ibdev, "IBDEV %p could not create path\n",
                    281:                       ibdev );
                    282:                return -ENOMEM;
                    283:        }
                    284:        ib_path_set_ownerdata ( cached->path, cached );
                    285: 
                    286:        /* Not found yet */
                    287:        return -ENOENT;
                    288: }

unix.superglobalmegacorp.com

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