|
|
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: };
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.