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

1.1       root        1: /*
                      2:  * Copyright (C) 2006 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 <stddef.h>
                     22: #include <string.h>
                     23: #include <stdio.h>
                     24: #include <stdlib.h>
                     25: #include <errno.h>
                     26: #include <assert.h>
                     27: #include <byteswap.h>
                     28: #include <ipxe/list.h>
                     29: #include <ipxe/if_ether.h>
                     30: #include <ipxe/iobuf.h>
                     31: #include <ipxe/uaccess.h>
                     32: #include <ipxe/netdevice.h>
                     33: #include <ipxe/features.h>
                     34: #include <ipxe/interface.h>
                     35: #include <ipxe/xfer.h>
                     36: #include <ipxe/uri.h>
                     37: #include <ipxe/open.h>
                     38: #include <ipxe/ata.h>
                     39: #include <ipxe/device.h>
                     40: #include <ipxe/aoe.h>
                     41: 
                     42: /** @file
                     43:  *
                     44:  * AoE protocol
                     45:  *
                     46:  */
                     47: 
                     48: FEATURE ( FEATURE_PROTOCOL, "AoE", DHCP_EB_FEATURE_AOE, 1 );
                     49: 
                     50: struct net_protocol aoe_protocol __net_protocol;
                     51: 
                     52: /******************************************************************************
                     53:  *
                     54:  * AoE devices and commands
                     55:  *
                     56:  ******************************************************************************
                     57:  */
                     58: 
                     59: /** List of all AoE devices */
                     60: static LIST_HEAD ( aoe_devices );
                     61: 
                     62: /** List of active AoE commands */
                     63: static LIST_HEAD ( aoe_commands );
                     64: 
                     65: /** An AoE device */
                     66: struct aoe_device {
                     67:        /** Reference counter */
                     68:        struct refcnt refcnt;
                     69: 
                     70:        /** Network device */
                     71:        struct net_device *netdev;
                     72:        /** ATA command issuing interface */
                     73:        struct interface ata;
                     74: 
                     75:        /** Major number */
                     76:        uint16_t major;
                     77:        /** Minor number */
                     78:        uint8_t minor;
                     79:        /** Target MAC address */
                     80:        uint8_t target[MAX_LL_ADDR_LEN];
                     81: 
                     82:        /** Saved timeout value */
                     83:        unsigned long timeout;
                     84: 
                     85:        /** Configuration command interface */
                     86:        struct interface config;
                     87:        /** Device is configued */
                     88:        int configured;
                     89: };
                     90: 
                     91: /** An AoE command */
                     92: struct aoe_command {
                     93:        /** Reference count */
                     94:        struct refcnt refcnt;
                     95:        /** AOE device */
                     96:        struct aoe_device *aoedev;
                     97:        /** List of active commands */
                     98:        struct list_head list;
                     99: 
                    100:        /** ATA command interface */
                    101:        struct interface ata;
                    102: 
                    103:        /** ATA command */
                    104:        struct ata_cmd command;
                    105:        /** Command type */
                    106:        struct aoe_command_type *type;
                    107:        /** Command tag */
                    108:        uint32_t tag;
                    109: 
                    110:        /** Retransmission timer */
                    111:        struct retry_timer timer;
                    112: };
                    113: 
                    114: /** An AoE command type */
                    115: struct aoe_command_type {
                    116:        /**
                    117:         * Calculate length of AoE command IU
                    118:         *
                    119:         * @v aoecmd            AoE command
                    120:         * @ret len             Length of command IU
                    121:         */
                    122:        size_t ( * cmd_len ) ( struct aoe_command *aoecmd );
                    123:        /**
                    124:         * Build AoE command IU
                    125:         *
                    126:         * @v aoecmd            AoE command
                    127:         * @v data              Command IU
                    128:         * @v len               Length of command IU
                    129:         */
                    130:        void ( * cmd ) ( struct aoe_command *aoecmd, void *data, size_t len );
                    131:        /**
                    132:         * Handle AoE response IU
                    133:         *
                    134:         * @v aoecmd            AoE command
                    135:         * @v data              Response IU
                    136:         * @v len               Length of response IU
                    137:         * @v ll_source         Link-layer source address
                    138:         * @ret rc              Return status code
                    139:         */
                    140:        int ( * rsp ) ( struct aoe_command *aoecmd, const void *data,
                    141:                        size_t len, const void *ll_source );
                    142: };
                    143: 
                    144: /**
                    145:  * Get reference to AoE device
                    146:  *
                    147:  * @v aoedev           AoE device
                    148:  * @ret aoedev         AoE device
                    149:  */
                    150: static inline __attribute__ (( always_inline )) struct aoe_device *
                    151: aoedev_get ( struct aoe_device *aoedev ) {
                    152:        ref_get ( &aoedev->refcnt );
                    153:        return aoedev;
                    154: }
                    155: 
                    156: /**
                    157:  * Drop reference to AoE device
                    158:  *
                    159:  * @v aoedev           AoE device
                    160:  */
                    161: static inline __attribute__ (( always_inline )) void
                    162: aoedev_put ( struct aoe_device *aoedev ) {
                    163:        ref_put ( &aoedev->refcnt );
                    164: }
                    165: 
                    166: /**
                    167:  * Get reference to AoE command
                    168:  *
                    169:  * @v aoecmd           AoE command
                    170:  * @ret aoecmd         AoE command
                    171:  */
                    172: static inline __attribute__ (( always_inline )) struct aoe_command *
                    173: aoecmd_get ( struct aoe_command *aoecmd ) {
                    174:        ref_get ( &aoecmd->refcnt );
                    175:        return aoecmd;
                    176: }
                    177: 
                    178: /**
                    179:  * Drop reference to AoE command
                    180:  *
                    181:  * @v aoecmd           AoE command
                    182:  */
                    183: static inline __attribute__ (( always_inline )) void
                    184: aoecmd_put ( struct aoe_command *aoecmd ) {
                    185:        ref_put ( &aoecmd->refcnt );
                    186: }
                    187: 
                    188: /**
                    189:  * Name AoE device
                    190:  *
                    191:  * @v aoedev           AoE device
                    192:  * @ret name           AoE device name
                    193:  */
                    194: static const char * aoedev_name ( struct aoe_device *aoedev ) {
                    195:        static char buf[16];
                    196: 
                    197:        snprintf ( buf, sizeof ( buf ), "%s/e%d.%d", aoedev->netdev->name,
                    198:                   aoedev->major, aoedev->minor );
                    199:        return buf;
                    200: }
                    201: 
                    202: /**
                    203:  * Free AoE command
                    204:  *
                    205:  * @v refcnt           Reference counter
                    206:  */
                    207: static void aoecmd_free ( struct refcnt *refcnt ) {
                    208:        struct aoe_command *aoecmd =
                    209:                container_of ( refcnt, struct aoe_command, refcnt );
                    210: 
                    211:        assert ( ! timer_running ( &aoecmd->timer ) );
                    212:        assert ( list_empty ( &aoecmd->list ) );
                    213: 
                    214:        aoedev_put ( aoecmd->aoedev );
                    215:        free ( aoecmd );
                    216: }
                    217: 
                    218: /**
                    219:  * Close AoE command
                    220:  *
                    221:  * @v aoecmd           AoE command
                    222:  * @v rc               Reason for close
                    223:  */
                    224: static void aoecmd_close ( struct aoe_command *aoecmd, int rc ) {
                    225:        struct aoe_device *aoedev = aoecmd->aoedev;
                    226: 
                    227:        /* Stop timer */
                    228:        stop_timer ( &aoecmd->timer );
                    229: 
                    230:        /* Preserve the timeout value for subsequent commands */
                    231:        aoedev->timeout = aoecmd->timer.timeout;
                    232: 
                    233:        /* Remove from list of commands */
                    234:        if ( ! list_empty ( &aoecmd->list ) ) {
                    235:                list_del ( &aoecmd->list );
                    236:                INIT_LIST_HEAD ( &aoecmd->list );
                    237:                aoecmd_put ( aoecmd );
                    238:        }
                    239: 
                    240:        /* Shut down interfaces */
                    241:        intf_shutdown ( &aoecmd->ata, rc );
                    242: }
                    243: 
                    244: /**
                    245:  * Transmit AoE command request
                    246:  *
                    247:  * @v aoecmd           AoE command
                    248:  * @ret rc             Return status code
                    249:  */
                    250: static int aoecmd_tx ( struct aoe_command *aoecmd ) {
                    251:        struct aoe_device *aoedev = aoecmd->aoedev;
                    252:        struct net_device *netdev = aoedev->netdev;
                    253:        struct io_buffer *iobuf;
                    254:        struct aoehdr *aoehdr;
                    255:        size_t cmd_len;
                    256:        int rc;
                    257: 
                    258:        /* Sanity check */
                    259:        assert ( netdev != NULL );
                    260: 
                    261:        /* If we are transmitting anything that requires a response,
                    262:          * start the retransmission timer.  Do this before attempting
                    263:          * to allocate the I/O buffer, in case allocation itself
                    264:          * fails.
                    265:          */
                    266:        start_timer ( &aoecmd->timer );
                    267: 
                    268:        /* Create outgoing I/O buffer */
                    269:        cmd_len = aoecmd->type->cmd_len ( aoecmd );
                    270:        iobuf = alloc_iob ( MAX_LL_HEADER_LEN + cmd_len );
                    271:        if ( ! iobuf )
                    272:                return -ENOMEM;
                    273:        iob_reserve ( iobuf, MAX_LL_HEADER_LEN );
                    274:        aoehdr = iob_put ( iobuf, cmd_len );
                    275: 
                    276:        /* Fill AoE header */
                    277:        memset ( aoehdr, 0, sizeof ( *aoehdr ) );
                    278:        aoehdr->ver_flags = AOE_VERSION;
                    279:        aoehdr->major = htons ( aoedev->major );
                    280:        aoehdr->minor = aoedev->minor;
                    281:        aoehdr->tag = htonl ( aoecmd->tag );
                    282:        aoecmd->type->cmd ( aoecmd, iobuf->data, iob_len ( iobuf ) );
                    283: 
                    284:        /* Send packet */
                    285:        if ( ( rc = net_tx ( iobuf, netdev, &aoe_protocol, aoedev->target,
                    286:                             netdev->ll_addr ) ) != 0 ) {
                    287:                DBGC ( aoedev, "AoE %s/%08x could not transmit: %s\n",
                    288:                       aoedev_name ( aoedev ), aoecmd->tag,
                    289:                       strerror ( rc ) );
                    290:                return rc;
                    291:        }
                    292: 
                    293:        return 0;
                    294: }
                    295: 
                    296: /**
                    297:  * Receive AoE command response
                    298:  *
                    299:  * @v aoecmd           AoE command
                    300:  * @v iobuf            I/O buffer
                    301:  * @v ll_source                Link-layer source address
                    302:  * @ret rc             Return status code
                    303:  */
                    304: static int aoecmd_rx ( struct aoe_command *aoecmd, struct io_buffer *iobuf,
                    305:                       const void *ll_source ) {
                    306:        struct aoe_device *aoedev = aoecmd->aoedev;
                    307:        struct aoehdr *aoehdr = iobuf->data;
                    308:        int rc;
                    309: 
                    310:        /* Sanity check */
                    311:        if ( iob_len ( iobuf ) < sizeof ( *aoehdr ) ) {
                    312:                DBGC ( aoedev, "AoE %s/%08x received underlength response "
                    313:                       "(%zd bytes)\n", aoedev_name ( aoedev ),
                    314:                       aoecmd->tag, iob_len ( iobuf ) );
                    315:                rc = -EINVAL;
                    316:                goto done;
                    317:        }
                    318:        if ( ( ntohs ( aoehdr->major ) != aoedev->major ) ||
                    319:             ( aoehdr->minor != aoedev->minor ) ) {
                    320:                DBGC ( aoedev, "AoE %s/%08x received response for incorrect "
                    321:                       "device e%d.%d\n", aoedev_name ( aoedev ), aoecmd->tag,
                    322:                       ntohs ( aoehdr->major ), aoehdr->minor );
                    323:                rc = -EINVAL;
                    324:                goto done;
                    325:        }
                    326: 
                    327:        /* Catch command failures */
                    328:        if ( aoehdr->ver_flags & AOE_FL_ERROR ) {
                    329:                DBGC ( aoedev, "AoE %s/%08x terminated in error\n",
                    330:                       aoedev_name ( aoedev ), aoecmd->tag );
                    331:                aoecmd_close ( aoecmd, -EIO );
                    332:                rc = -EIO;
                    333:                goto done;
                    334:        }
                    335: 
                    336:        /* Hand off to command completion handler */
                    337:        if ( ( rc = aoecmd->type->rsp ( aoecmd, iobuf->data, iob_len ( iobuf ),
                    338:                                        ll_source ) ) != 0 )
                    339:                goto done;
                    340: 
                    341:  done:
                    342:        /* Free I/O buffer */
                    343:        free_iob ( iobuf );
                    344: 
                    345:        /* Terminate command */
                    346:        aoecmd_close ( aoecmd, rc );
                    347: 
                    348:        return rc;
                    349: }
                    350: 
                    351: /**
                    352:  * Handle AoE retry timer expiry
                    353:  *
                    354:  * @v timer            AoE retry timer
                    355:  * @v fail             Failure indicator
                    356:  */
                    357: static void aoecmd_expired ( struct retry_timer *timer, int fail ) {
                    358:        struct aoe_command *aoecmd =
                    359:                container_of ( timer, struct aoe_command, timer );
                    360: 
                    361:        if ( fail ) {
                    362:                aoecmd_close ( aoecmd, -ETIMEDOUT );
                    363:        } else {
                    364:                aoecmd_tx ( aoecmd );
                    365:        }
                    366: }
                    367: 
                    368: /**
                    369:  * Calculate length of AoE ATA command IU
                    370:  *
                    371:  * @v aoecmd           AoE command
                    372:  * @ret len            Length of command IU
                    373:  */
                    374: static size_t aoecmd_ata_cmd_len ( struct aoe_command *aoecmd ) {
                    375:        struct ata_cmd *command = &aoecmd->command;
                    376: 
                    377:        return ( sizeof ( struct aoehdr ) + sizeof ( struct aoeata ) +
                    378:                 command->data_out_len );
                    379: }
                    380: 
                    381: /**
                    382:  * Build AoE ATA command IU
                    383:  *
                    384:  * @v aoecmd           AoE command
                    385:  * @v data             Command IU
                    386:  * @v len              Length of command IU
                    387:  */
                    388: static void aoecmd_ata_cmd ( struct aoe_command *aoecmd,
                    389:                             void *data, size_t len ) {
                    390:        struct aoe_device *aoedev = aoecmd->aoedev;
                    391:        struct ata_cmd *command = &aoecmd->command;
                    392:        struct aoehdr *aoehdr = data;
                    393:        struct aoeata *aoeata = &aoehdr->payload[0].ata;
                    394: 
                    395:        /* Sanity check */
                    396:        linker_assert ( AOE_FL_DEV_HEAD == ATA_DEV_SLAVE, __fix_ata_h__ );
                    397:        assert ( len == ( sizeof ( *aoehdr ) + sizeof ( *aoeata ) +
                    398:                          command->data_out_len ) );
                    399: 
                    400:        /* Build IU */
                    401:        aoehdr->command = AOE_CMD_ATA;
                    402:        memset ( aoeata, 0, sizeof ( *aoeata ) );
                    403:        aoeata->aflags = ( ( command->cb.lba48 ? AOE_FL_EXTENDED : 0 ) |
                    404:                           ( command->cb.device & ATA_DEV_SLAVE ) |
                    405:                           ( command->data_out_len ? AOE_FL_WRITE : 0 ) );
                    406:        aoeata->err_feat = command->cb.err_feat.bytes.cur;
                    407:        aoeata->count = command->cb.count.native;
                    408:        aoeata->cmd_stat = command->cb.cmd_stat;
                    409:        aoeata->lba.u64 = cpu_to_le64 ( command->cb.lba.native );
                    410:        if ( ! command->cb.lba48 )
                    411:                aoeata->lba.bytes[3] |=
                    412:                        ( command->cb.device & ATA_DEV_MASK );
                    413:        copy_from_user ( aoeata->data, command->data_out, 0,
                    414:                         command->data_out_len );
                    415: 
                    416:        DBGC2 ( aoedev, "AoE %s/%08x ATA cmd %02x:%02x:%02x:%02x:%08llx",
                    417:                aoedev_name ( aoedev ), aoecmd->tag, aoeata->aflags,
                    418:                aoeata->err_feat, aoeata->count, aoeata->cmd_stat,
                    419:                aoeata->lba.u64 );
                    420:        if ( command->data_out_len )
                    421:                DBGC2 ( aoedev, " out %04zx", command->data_out_len );
                    422:        if ( command->data_in_len )
                    423:                DBGC2 ( aoedev, " in %04zx", command->data_in_len );
                    424:        DBGC2 ( aoedev, "\n" );
                    425: }
                    426: 
                    427: /**
                    428:  * Handle AoE ATA response IU
                    429:  *
                    430:  * @v aoecmd           AoE command
                    431:  * @v data             Response IU
                    432:  * @v len              Length of response IU
                    433:  * @v ll_source                Link-layer source address
                    434:  * @ret rc             Return status code
                    435:  */
                    436: static int aoecmd_ata_rsp ( struct aoe_command *aoecmd, const void *data,
                    437:                            size_t len, const void *ll_source __unused ) {
                    438:        struct aoe_device *aoedev = aoecmd->aoedev;
                    439:        struct ata_cmd *command = &aoecmd->command;
                    440:        const struct aoehdr *aoehdr = data;
                    441:        const struct aoeata *aoeata = &aoehdr->payload[0].ata;
                    442:        size_t data_len;
                    443: 
                    444:        /* Sanity check */
                    445:        if ( len < ( sizeof ( *aoehdr ) + sizeof ( *aoeata ) ) ) {
                    446:                DBGC ( aoedev, "AoE %s/%08x received underlength ATA response "
                    447:                       "(%zd bytes)\n", aoedev_name ( aoedev ),
                    448:                       aoecmd->tag, len );
                    449:                return -EINVAL;
                    450:        }
                    451:        data_len = ( len - ( sizeof ( *aoehdr ) + sizeof ( *aoeata ) ) );
                    452:        DBGC2 ( aoedev, "AoE %s/%08x ATA rsp %02x in %04zx\n",
                    453:                aoedev_name ( aoedev ), aoecmd->tag, aoeata->cmd_stat,
                    454:                data_len );
                    455: 
                    456:        /* Check for command failure */
                    457:        if ( aoeata->cmd_stat & ATA_STAT_ERR ) {
                    458:                DBGC ( aoedev, "AoE %s/%08x status %02x\n",
                    459:                       aoedev_name ( aoedev ), aoecmd->tag, aoeata->cmd_stat );
                    460:                return -EIO;
                    461:        }
                    462: 
                    463:        /* Check data-in length is sufficient.  (There may be trailing
                    464:         * garbage due to Ethernet minimum-frame-size padding.)
                    465:         */
                    466:        if ( data_len < command->data_in_len ) {
                    467:                DBGC ( aoedev, "AoE %s/%08x data-in underrun (received %zd, "
                    468:                       "expected %zd)\n", aoedev_name ( aoedev ), aoecmd->tag,
                    469:                       data_len, command->data_in_len );
                    470:                return -ERANGE;
                    471:        }
                    472: 
                    473:        /* Copy out data payload */
                    474:        copy_to_user ( command->data_in, 0, aoeata->data,
                    475:                       command->data_in_len );
                    476: 
                    477:        return 0;
                    478: }
                    479: 
                    480: /** AoE ATA command */
                    481: static struct aoe_command_type aoecmd_ata = {
                    482:        .cmd_len = aoecmd_ata_cmd_len,
                    483:        .cmd = aoecmd_ata_cmd,
                    484:        .rsp = aoecmd_ata_rsp,
                    485: };
                    486: 
                    487: /**
                    488:  * Calculate length of AoE configuration command IU
                    489:  *
                    490:  * @v aoecmd           AoE command
                    491:  * @ret len            Length of command IU
                    492:  */
                    493: static size_t aoecmd_cfg_cmd_len ( struct aoe_command *aoecmd __unused ) {
                    494:        return ( sizeof ( struct aoehdr ) + sizeof ( struct aoecfg ) );
                    495: }
                    496: 
                    497: /**
                    498:  * Build AoE configuration command IU
                    499:  *
                    500:  * @v aoecmd           AoE command
                    501:  * @v data             Command IU
                    502:  * @v len              Length of command IU
                    503:  */
                    504: static void aoecmd_cfg_cmd ( struct aoe_command *aoecmd,
                    505:                             void *data, size_t len ) {
                    506:        struct aoe_device *aoedev = aoecmd->aoedev;
                    507:        struct aoehdr *aoehdr = data;
                    508:        struct aoecfg *aoecfg = &aoehdr->payload[0].cfg;
                    509: 
                    510:        /* Sanity check */
                    511:        assert ( len == ( sizeof ( *aoehdr ) + sizeof ( *aoecfg ) ) );
                    512: 
                    513:        /* Build IU */
                    514:        aoehdr->command = AOE_CMD_CONFIG;
                    515:        memset ( aoecfg, 0, sizeof ( *aoecfg ) );
                    516: 
                    517:        DBGC ( aoedev, "AoE %s/%08x CONFIG cmd\n",
                    518:               aoedev_name ( aoedev ), aoecmd->tag );
                    519: }
                    520: 
                    521: /**
                    522:  * Handle AoE configuration response IU
                    523:  *
                    524:  * @v aoecmd           AoE command
                    525:  * @v data             Response IU
                    526:  * @v len              Length of response IU
                    527:  * @v ll_source                Link-layer source address
                    528:  * @ret rc             Return status code
                    529:  */
                    530: static int aoecmd_cfg_rsp ( struct aoe_command *aoecmd, const void *data,
                    531:                            size_t len, const void *ll_source ) {
                    532:        struct aoe_device *aoedev = aoecmd->aoedev;
                    533:        struct ll_protocol *ll_protocol = aoedev->netdev->ll_protocol;
                    534:        const struct aoehdr *aoehdr = data;
                    535:        const struct aoecfg *aoecfg = &aoehdr->payload[0].cfg;
                    536: 
                    537:        /* Sanity check */
                    538:        if ( len < ( sizeof ( *aoehdr ) + sizeof ( *aoecfg ) ) ) {
                    539:                DBGC ( aoedev, "AoE %s/%08x received underlength "
                    540:                       "configuration response (%zd bytes)\n",
                    541:                       aoedev_name ( aoedev ), aoecmd->tag, len );
                    542:                return -EINVAL;
                    543:        }
                    544:        DBGC ( aoedev, "AoE %s/%08x CONFIG rsp buf %04x fw %04x scnt %02x\n",
                    545:               aoedev_name ( aoedev ), aoecmd->tag, ntohs ( aoecfg->bufcnt ),
                    546:               aoecfg->fwver, aoecfg->scnt );
                    547: 
                    548:        /* Record target MAC address */
                    549:        memcpy ( aoedev->target, ll_source, ll_protocol->ll_addr_len );
                    550:        DBGC ( aoedev, "AoE %s has MAC address %s\n",
                    551:               aoedev_name ( aoedev ), ll_protocol->ntoa ( aoedev->target ) );
                    552: 
                    553:        return 0;
                    554: }
                    555: 
                    556: /** AoE configuration command */
                    557: static struct aoe_command_type aoecmd_cfg = {
                    558:        .cmd_len = aoecmd_cfg_cmd_len,
                    559:        .cmd = aoecmd_cfg_cmd,
                    560:        .rsp = aoecmd_cfg_rsp,
                    561: };
                    562: 
                    563: /** AoE command ATA interface operations */
                    564: static struct interface_operation aoecmd_ata_op[] = {
                    565:        INTF_OP ( intf_close, struct aoe_command *, aoecmd_close ),
                    566: };
                    567: 
                    568: /** AoE command ATA interface descriptor */
                    569: static struct interface_descriptor aoecmd_ata_desc =
                    570:        INTF_DESC ( struct aoe_command, ata, aoecmd_ata_op );
                    571: 
                    572: /**
                    573:  * Identify AoE command by tag
                    574:  *
                    575:  * @v tag              Command tag
                    576:  * @ret aoecmd         AoE command, or NULL
                    577:  */
                    578: static struct aoe_command * aoecmd_find_tag ( uint32_t tag ) {
                    579:        struct aoe_command *aoecmd;
                    580: 
                    581:        list_for_each_entry ( aoecmd, &aoe_commands, list ) {
                    582:                if ( aoecmd->tag == tag )
                    583:                        return aoecmd;
                    584:        }
                    585:        return NULL;
                    586: }
                    587: 
                    588: /**
                    589:  * Choose an AoE command tag
                    590:  *
                    591:  * @ret tag            New tag, or negative error
                    592:  */
                    593: static int aoecmd_new_tag ( void ) {
                    594:        static uint16_t tag_idx;
                    595:        unsigned int i;
                    596: 
                    597:        for ( i = 0 ; i < 65536 ; i++ ) {
                    598:                tag_idx++;
                    599:                if ( aoecmd_find_tag ( tag_idx ) == NULL )
                    600:                        return ( AOE_TAG_MAGIC | tag_idx );
                    601:        }
                    602:        return -EADDRINUSE;
                    603: }
                    604: 
                    605: /**
                    606:  * Create AoE command
                    607:  *
                    608:  * @v aoedev           AoE device
                    609:  * @v type             AoE command type
                    610:  * @ret aoecmd         AoE command
                    611:  */
                    612: static struct aoe_command * aoecmd_create ( struct aoe_device *aoedev,
                    613:                                            struct aoe_command_type *type ) {
                    614:        struct aoe_command *aoecmd;
                    615:        int tag;
                    616: 
                    617:        /* Allocate command tag */
                    618:        tag = aoecmd_new_tag();
                    619:        if ( tag < 0 )
                    620:                return NULL;
                    621: 
                    622:        /* Allocate and initialise structure */
                    623:        aoecmd = zalloc ( sizeof ( *aoecmd ) );
                    624:        if ( ! aoecmd )
                    625:                return NULL;
                    626:        ref_init ( &aoecmd->refcnt, aoecmd_free );
                    627:        list_add ( &aoecmd->list, &aoe_commands );
                    628:        intf_init ( &aoecmd->ata, &aoecmd_ata_desc, &aoecmd->refcnt );
                    629:        timer_init ( &aoecmd->timer, aoecmd_expired, &aoecmd->refcnt );
                    630:        aoecmd->aoedev = aoedev_get ( aoedev );
                    631:        aoecmd->type = type;
                    632:        aoecmd->tag = tag;
                    633: 
                    634:        /* Preserve timeout from last completed command */
                    635:        aoecmd->timer.timeout = aoedev->timeout;
                    636: 
                    637:        /* Return already mortalised.  (Reference is held by command list.) */
                    638:        return aoecmd;
                    639: }
                    640: 
                    641: /**
                    642:  * Issue AoE ATA command
                    643:  *
                    644:  * @v aoedev           AoE device
                    645:  * @v parent           Parent interface
                    646:  * @v command          ATA command
                    647:  * @ret tag            Command tag, or negative error
                    648:  */
                    649: static int aoedev_ata_command ( struct aoe_device *aoedev,
                    650:                                struct interface *parent,
                    651:                                struct ata_cmd *command ) {
                    652:        struct net_device *netdev = aoedev->netdev;
                    653:        struct aoe_command *aoecmd;
                    654: 
                    655:        /* Fail immediately if net device is closed */
                    656:        if ( ! netdev_is_open ( netdev ) ) {
                    657:                DBGC ( aoedev, "AoE %s cannot issue command while net device "
                    658:                       "is closed\n", aoedev_name ( aoedev ) );
                    659:                return -EWOULDBLOCK;
                    660:        }
                    661: 
                    662:        /* Create command */
                    663:        aoecmd = aoecmd_create ( aoedev, &aoecmd_ata );
                    664:        if ( ! aoecmd )
                    665:                return -ENOMEM;
                    666:        memcpy ( &aoecmd->command, command, sizeof ( aoecmd->command ) );
                    667: 
                    668:        /* Attempt to send command.  Allow failures to be handled by
                    669:         * the retry timer.
                    670:         */
                    671:        aoecmd_tx ( aoecmd );
                    672: 
                    673:        /* Attach to parent interface, leave reference with command
                    674:         * list, and return.
                    675:         */
                    676:        intf_plug_plug ( &aoecmd->ata, parent );
                    677:        return aoecmd->tag;
                    678: }
                    679: 
                    680: /**
                    681:  * Issue AoE configuration command
                    682:  *
                    683:  * @v aoedev           AoE device
                    684:  * @v parent           Parent interface
                    685:  * @ret tag            Command tag, or negative error
                    686:  */
                    687: static int aoedev_cfg_command ( struct aoe_device *aoedev,
                    688:                                struct interface *parent ) {
                    689:        struct aoe_command *aoecmd;
                    690: 
                    691:        /* Create command */
                    692:        aoecmd = aoecmd_create ( aoedev, &aoecmd_cfg );
                    693:        if ( ! aoecmd )
                    694:                return -ENOMEM;
                    695: 
                    696:        /* Attempt to send command.  Allow failures to be handled by
                    697:         * the retry timer.
                    698:         */
                    699:        aoecmd_tx ( aoecmd );
                    700: 
                    701:        /* Attach to parent interface, leave reference with command
                    702:         * list, and return.
                    703:         */
                    704:        intf_plug_plug ( &aoecmd->ata, parent );
                    705:        return aoecmd->tag;
                    706: }
                    707: 
                    708: /**
                    709:  * Free AoE device
                    710:  *
                    711:  * @v refcnt           Reference count
                    712:  */
                    713: static void aoedev_free ( struct refcnt *refcnt ) {
                    714:        struct aoe_device *aoedev =
                    715:                container_of ( refcnt, struct aoe_device, refcnt );
                    716: 
                    717:        netdev_put ( aoedev->netdev );
                    718:        free ( aoedev );
                    719: }
                    720: 
                    721: /**
                    722:  * Close AoE device
                    723:  *
                    724:  * @v aoedev           AoE device
                    725:  * @v rc               Reason for close
                    726:  */
                    727: static void aoedev_close ( struct aoe_device *aoedev, int rc ) {
                    728:        struct aoe_command *aoecmd;
                    729:        struct aoe_command *tmp;
                    730: 
                    731:        /* Shut down interfaces */
                    732:        intf_shutdown ( &aoedev->ata, rc );
                    733:        intf_shutdown ( &aoedev->config, rc );
                    734: 
                    735:        /* Shut down any active commands */
                    736:        list_for_each_entry_safe ( aoecmd, tmp, &aoe_commands, list ) {
                    737:                if ( aoecmd->aoedev != aoedev )
                    738:                        continue;
                    739:                aoecmd_get ( aoecmd );
                    740:                aoecmd_close ( aoecmd, rc );
                    741:                aoecmd_put ( aoecmd );
                    742:        }
                    743: }
                    744: 
                    745: /**
                    746:  * Check AoE device flow-control window
                    747:  *
                    748:  * @v aoedev           AoE device
                    749:  * @ret len            Length of window
                    750:  */
                    751: static size_t aoedev_window ( struct aoe_device *aoedev ) {
                    752:        return ( aoedev->configured ? ~( ( size_t ) 0 ) : 0 );
                    753: }
                    754: 
                    755: /**
                    756:  * Handle AoE device configuration completion
                    757:  *
                    758:  * @v aoedev           AoE device
                    759:  * @v rc               Reason for completion
                    760:  */
                    761: static void aoedev_config_done ( struct aoe_device *aoedev, int rc ) {
                    762: 
                    763:        /* Shut down interface */
                    764:        intf_shutdown ( &aoedev->config, rc );
                    765: 
                    766:        /* Close device on failure */
                    767:        if ( rc != 0 ) {
                    768:                aoedev_close ( aoedev, rc );
                    769:                return;
                    770:        }
                    771: 
                    772:        /* Mark device as configured */
                    773:        aoedev->configured = 1;
                    774:        xfer_window_changed ( &aoedev->ata );
                    775: }
                    776: 
                    777: /**
                    778:  * Identify device underlying AoE device
                    779:  *
                    780:  * @v aoedev           AoE device
                    781:  * @ret device         Underlying device
                    782:  */
                    783: static struct device * aoedev_identify_device ( struct aoe_device *aoedev ) {
                    784:        return aoedev->netdev->dev;
                    785: }
                    786: 
                    787: /**
                    788:  * Describe AoE device in an ACPI table
                    789:  *
                    790:  * @v aoedev           AoE device
                    791:  * @v acpi             ACPI table
                    792:  * @v len              Length of ACPI table
                    793:  * @ret rc             Return status code
                    794:  */
                    795: static int aoedev_describe ( struct aoe_device *aoedev,
                    796:                             struct acpi_description_header *acpi,
                    797:                             size_t len ) {
                    798:        struct abft_table *abft =
                    799:                container_of ( acpi, struct abft_table, acpi );
                    800: 
                    801:        /* Sanity check */
                    802:        if ( len < sizeof ( *abft ) )
                    803:                return -ENOBUFS;
                    804: 
                    805:        /* Populate table */
                    806:        abft->acpi.signature = cpu_to_le32 ( ABFT_SIG );
                    807:        abft->acpi.length = cpu_to_le32 ( sizeof ( *abft ) );
                    808:        abft->acpi.revision = 1;
                    809:        abft->shelf = cpu_to_le16 ( aoedev->major );
                    810:        abft->slot = aoedev->minor;
                    811:        memcpy ( abft->mac, aoedev->netdev->ll_addr, sizeof ( abft->mac ) );
                    812: 
                    813:        return 0;
                    814: }
                    815: 
                    816: /** AoE device ATA interface operations */
                    817: static struct interface_operation aoedev_ata_op[] = {
                    818:        INTF_OP ( ata_command, struct aoe_device *, aoedev_ata_command ),
                    819:        INTF_OP ( xfer_window, struct aoe_device *, aoedev_window ),
                    820:        INTF_OP ( intf_close, struct aoe_device *, aoedev_close ),
                    821:        INTF_OP ( acpi_describe, struct aoe_device *, aoedev_describe ),
                    822:        INTF_OP ( identify_device, struct aoe_device *,
                    823:                  aoedev_identify_device ),
                    824: };
                    825: 
                    826: /** AoE device ATA interface descriptor */
                    827: static struct interface_descriptor aoedev_ata_desc =
                    828:        INTF_DESC ( struct aoe_device, ata, aoedev_ata_op );
                    829: 
                    830: /** AoE device configuration interface operations */
                    831: static struct interface_operation aoedev_config_op[] = {
                    832:        INTF_OP ( intf_close, struct aoe_device *, aoedev_config_done ),
                    833: };
                    834: 
                    835: /** AoE device configuration interface descriptor */
                    836: static struct interface_descriptor aoedev_config_desc =
                    837:        INTF_DESC ( struct aoe_device, config, aoedev_config_op );
                    838: 
                    839: /**
                    840:  * Open AoE device
                    841:  *
                    842:  * @v parent           Parent interface
                    843:  * @v netdev           Network device
                    844:  * @v major            Device major number
                    845:  * @v minor            Device minor number
                    846:  * @ret rc             Return status code
                    847:  */
                    848: static int aoedev_open ( struct interface *parent, struct net_device *netdev,
                    849:                         unsigned int major, unsigned int minor ) {
                    850:        struct aoe_device *aoedev;
                    851:        int rc;
                    852: 
                    853:        /* Allocate and initialise structure */
                    854:        aoedev = zalloc ( sizeof ( *aoedev ) );
                    855:        if ( ! aoedev ) {
                    856:                rc = -ENOMEM;
                    857:                goto err_zalloc;
                    858:        }
                    859:        ref_init ( &aoedev->refcnt, aoedev_free );
                    860:        intf_init ( &aoedev->ata, &aoedev_ata_desc, &aoedev->refcnt );
                    861:        intf_init ( &aoedev->config, &aoedev_config_desc, &aoedev->refcnt );
                    862:        aoedev->netdev = netdev_get ( netdev );
                    863:        aoedev->major = major;
                    864:        aoedev->minor = minor;
                    865:        memcpy ( aoedev->target, netdev->ll_broadcast,
                    866:                 netdev->ll_protocol->ll_addr_len );
                    867: 
                    868:        /* Initiate configuration */
                    869:        if ( ( rc = aoedev_cfg_command ( aoedev, &aoedev->config ) ) < 0 ) {
                    870:                DBGC ( aoedev, "AoE %s could not initiate configuration: %s\n",
                    871:                       aoedev_name ( aoedev ), strerror ( rc ) );
                    872:                goto err_config;
                    873:        }
                    874: 
                    875:        /* Attach ATA device to parent interface */
                    876:        if ( ( rc = ata_open ( parent, &aoedev->ata, ATA_DEV_MASTER,
                    877:                               AOE_MAX_COUNT ) ) != 0 ) {
                    878:                DBGC ( aoedev, "AoE %s could not create ATA device: %s\n",
                    879:                       aoedev_name ( aoedev ), strerror ( rc ) );
                    880:                goto err_ata_open;
                    881:        }
                    882: 
                    883:        /* Mortalise self and return */
                    884:        ref_put ( &aoedev->refcnt );
                    885:        return 0;
                    886: 
                    887:  err_ata_open:
                    888:  err_config:
                    889:        aoedev_close ( aoedev, rc );
                    890:        ref_put ( &aoedev->refcnt );
                    891:  err_zalloc:
                    892:        return rc;
                    893: }
                    894: 
                    895: /******************************************************************************
                    896:  *
                    897:  * AoE network protocol
                    898:  *
                    899:  ******************************************************************************
                    900:  */
                    901: 
                    902: /**
                    903:  * Process incoming AoE packets
                    904:  *
                    905:  * @v iobuf            I/O buffer
                    906:  * @v netdev           Network device
                    907:  * @v ll_dest          Link-layer destination address
                    908:  * @v ll_source                Link-layer source address
                    909:  * @ret rc             Return status code
                    910:  *
                    911:  */
                    912: static int aoe_rx ( struct io_buffer *iobuf,
                    913:                    struct net_device *netdev __unused,
                    914:                    const void *ll_dest __unused,
                    915:                    const void *ll_source ) {
                    916:        struct aoehdr *aoehdr = iobuf->data;
                    917:        struct aoe_command *aoecmd;
                    918:        int rc;
                    919: 
                    920:        /* Sanity check */
                    921:        if ( iob_len ( iobuf ) < sizeof ( *aoehdr ) ) {
                    922:                DBG ( "AoE received underlength packet (%zd bytes)\n",
                    923:                      iob_len ( iobuf ) );
                    924:                rc = -EINVAL;
                    925:                goto err_sanity;
                    926:        }
                    927:        if ( ( aoehdr->ver_flags & AOE_VERSION_MASK ) != AOE_VERSION ) {
                    928:                DBG ( "AoE received packet for unsupported protocol version "
                    929:                      "%02x\n", ( aoehdr->ver_flags & AOE_VERSION_MASK ) );
                    930:                rc = -EPROTONOSUPPORT;
                    931:                goto err_sanity;
                    932:        }
                    933:        if ( ! ( aoehdr->ver_flags & AOE_FL_RESPONSE ) ) {
                    934:                DBG ( "AoE received request packet\n" );
                    935:                rc = -EOPNOTSUPP;
                    936:                goto err_sanity;
                    937:        }
                    938: 
                    939:        /* Demultiplex amongst active AoE commands */
                    940:        aoecmd = aoecmd_find_tag ( ntohl ( aoehdr->tag ) );
                    941:        if ( ! aoecmd ) {
                    942:                DBG ( "AoE received packet for unused tag %08x\n",
                    943:                      ntohl ( aoehdr->tag ) );
                    944:                rc = -ENOENT;
                    945:                goto err_demux;
                    946:        }
                    947: 
                    948:        /* Pass received frame to command */
                    949:        aoecmd_get ( aoecmd );
                    950:        if ( ( rc = aoecmd_rx ( aoecmd, iob_disown ( iobuf ),
                    951:                                ll_source ) ) != 0 )
                    952:                goto err_rx;
                    953: 
                    954:  err_rx:
                    955:        aoecmd_put ( aoecmd );
                    956:  err_demux:
                    957:  err_sanity:
                    958:        free_iob ( iobuf );
                    959:        return rc;
                    960: }
                    961: 
                    962: /** AoE protocol */
                    963: struct net_protocol aoe_protocol __net_protocol = {
                    964:        .name = "AoE",
                    965:        .net_proto = htons ( ETH_P_AOE ),
                    966:        .rx = aoe_rx,
                    967: };
                    968: 
                    969: /******************************************************************************
                    970:  *
                    971:  * AoE URIs
                    972:  *
                    973:  ******************************************************************************
                    974:  */
                    975: 
                    976: /**
                    977:  * Parse AoE URI
                    978:  *
                    979:  * @v uri              URI
                    980:  * @ret major          Major device number
                    981:  * @ret minor          Minor device number
                    982:  * @ret rc             Return status code
                    983:  *
                    984:  * An AoE URI has the form "aoe:e<major>.<minor>".
                    985:  */
                    986: static int aoe_parse_uri ( struct uri *uri, unsigned int *major,
                    987:                           unsigned int *minor ) {
                    988:        const char *ptr;
                    989:        char *end;
                    990: 
                    991:        /* Check for URI with opaque portion */
                    992:        if ( ! uri->opaque )
                    993:                return -EINVAL;
                    994:        ptr = uri->opaque;
                    995: 
                    996:        /* Check for initial 'e' */
                    997:        if ( *ptr != 'e' )
                    998:                return -EINVAL;
                    999:        ptr++;
                   1000: 
                   1001:        /* Parse major device number */
                   1002:        *major = strtoul ( ptr, &end, 10 );
                   1003:        if ( *end != '.' )
                   1004:                return -EINVAL;
                   1005:        ptr = ( end + 1 );
                   1006: 
                   1007:        /* Parse minor device number */
                   1008:        *minor = strtoul ( ptr, &end, 10 );
                   1009:        if ( *end )
                   1010:                return -EINVAL;
                   1011: 
                   1012:        return 0;
                   1013: }
                   1014: 
                   1015: /**
                   1016:  * Open AoE URI
                   1017:  *
                   1018:  * @v parent           Parent interface
                   1019:  * @v uri              URI
                   1020:  * @ret rc             Return status code
                   1021:  */
                   1022: static int aoe_open ( struct interface *parent, struct uri *uri ) {
                   1023:        struct net_device *netdev;
                   1024:        unsigned int major;
                   1025:        unsigned int minor;
                   1026:        int rc;
                   1027: 
                   1028:        /* Identify network device.  This is something of a hack, but
                   1029:         * the AoE URI scheme that has been in use for some time now
                   1030:         * provides no way to specify a particular device.
                   1031:         */
                   1032:        netdev = last_opened_netdev();
                   1033:        if ( ! netdev ) {
                   1034:                DBG ( "AoE cannot identify network device\n" );
                   1035:                return -ENODEV;
                   1036:        }
                   1037: 
                   1038:        /* Parse URI */
                   1039:        if ( ( rc = aoe_parse_uri ( uri, &major, &minor ) ) != 0 ) {
                   1040:                DBG ( "AoE cannot parse URI\n" );
                   1041:                return rc;
                   1042:        }
                   1043: 
                   1044:        /* Open AoE device */
                   1045:        if ( ( rc = aoedev_open ( parent, netdev, major, minor ) ) != 0 )
                   1046:                return rc;
                   1047: 
                   1048:        return 0;
                   1049: }
                   1050: 
                   1051: /** AoE URI opener */
                   1052: struct uri_opener aoe_uri_opener __uri_opener = {
                   1053:        .scheme = "aoe",
                   1054:        .open = aoe_open,
                   1055: };

unix.superglobalmegacorp.com

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