|
|
1.1 ! root 1: /* ! 2: * Copyright (C) 2009 Fen Systems Ltd <[email protected]>. ! 3: * All rights reserved. ! 4: * ! 5: * Redistribution and use in source and binary forms, with or without ! 6: * modification, are permitted provided that the following conditions ! 7: * are met: ! 8: * ! 9: * Redistributions of source code must retain the above copyright ! 10: * notice, this list of conditions and the following disclaimer. ! 11: * ! 12: * Redistributions in binary form must reproduce the above copyright ! 13: * notice, this list of conditions and the following disclaimer in ! 14: * the documentation and/or other materials provided with the ! 15: * distribution. ! 16: * ! 17: * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ! 18: * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ! 19: * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS ! 20: * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE ! 21: * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, ! 22: * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES ! 23: * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR ! 24: * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ! 25: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, ! 26: * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ! 27: * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED ! 28: * OF THE POSSIBILITY OF SUCH DAMAGE. ! 29: */ ! 30: ! 31: FILE_LICENCE ( BSD2 ); ! 32: ! 33: #include <stdlib.h> ! 34: #include <errno.h> ! 35: #include <ipxe/interface.h> ! 36: #include <ipxe/uri.h> ! 37: #include <ipxe/open.h> ! 38: #include <ipxe/base16.h> ! 39: #include <ipxe/acpi.h> ! 40: #include <ipxe/srp.h> ! 41: #include <ipxe/infiniband.h> ! 42: #include <ipxe/ib_cmrc.h> ! 43: #include <ipxe/ib_srp.h> ! 44: ! 45: /** ! 46: * @file ! 47: * ! 48: * SCSI RDMA Protocol over Infiniband ! 49: * ! 50: */ ! 51: ! 52: /* Disambiguate the various possible EINVALs */ ! 53: #define EINVAL_BYTE_STRING_LEN __einfo_error ( EINFO_EINVAL_BYTE_STRING_LEN ) ! 54: #define EINFO_EINVAL_BYTE_STRING_LEN __einfo_uniqify \ ! 55: ( EINFO_EINVAL, 0x01, "Invalid byte string length" ) ! 56: #define EINVAL_INTEGER __einfo_error ( EINFO_EINVAL_INTEGER ) ! 57: #define EINFO_EINVAL_INTEGER __einfo_uniqify \ ! 58: ( EINFO_EINVAL, 0x03, "Invalid integer" ) ! 59: #define EINVAL_RP_TOO_SHORT __einfo_error ( EINFO_EINVAL_RP_TOO_SHORT ) ! 60: #define EINFO_EINVAL_RP_TOO_SHORT __einfo_uniqify \ ! 61: ( EINFO_EINVAL, 0x04, "Root path too short" ) ! 62: ! 63: /****************************************************************************** ! 64: * ! 65: * IB SRP devices ! 66: * ! 67: ****************************************************************************** ! 68: */ ! 69: ! 70: /** An Infiniband SRP device */ ! 71: struct ib_srp_device { ! 72: /** Reference count */ ! 73: struct refcnt refcnt; ! 74: ! 75: /** SRP transport interface */ ! 76: struct interface srp; ! 77: /** CMRC interface */ ! 78: struct interface cmrc; ! 79: ! 80: /** Infiniband device */ ! 81: struct ib_device *ibdev; ! 82: ! 83: /** Destination GID (for boot firmware table) */ ! 84: union ib_gid dgid; ! 85: /** Service ID (for boot firmware table) */ ! 86: union ib_guid service_id; ! 87: }; ! 88: ! 89: /** ! 90: * Free IB SRP device ! 91: * ! 92: * @v refcnt Reference count ! 93: */ ! 94: static void ib_srp_free ( struct refcnt *refcnt ) { ! 95: struct ib_srp_device *ib_srp = ! 96: container_of ( refcnt, struct ib_srp_device, refcnt ); ! 97: ! 98: ibdev_put ( ib_srp->ibdev ); ! 99: free ( ib_srp ); ! 100: } ! 101: ! 102: /** ! 103: * Close IB SRP device ! 104: * ! 105: * @v ib_srp IB SRP device ! 106: * @v rc Reason for close ! 107: */ ! 108: static void ib_srp_close ( struct ib_srp_device *ib_srp, int rc ) { ! 109: ! 110: /* Shut down interfaces */ ! 111: intf_shutdown ( &ib_srp->cmrc, rc ); ! 112: intf_shutdown ( &ib_srp->srp, rc ); ! 113: } ! 114: ! 115: /** ! 116: * Describe IB SRP device in an ACPI table ! 117: * ! 118: * @v srpdev SRP device ! 119: * @v acpi ACPI table ! 120: * @v len Length of ACPI table ! 121: * @ret rc Return status code ! 122: */ ! 123: static int ib_srp_describe ( struct ib_srp_device *ib_srp, ! 124: struct acpi_description_header *acpi, ! 125: size_t len ) { ! 126: struct ib_device *ibdev = ib_srp->ibdev; ! 127: struct sbft_table *sbft = ! 128: container_of ( acpi, struct sbft_table, acpi ); ! 129: struct sbft_ib_subtable *ib_sbft; ! 130: size_t used; ! 131: ! 132: /* Sanity check */ ! 133: if ( acpi->signature != SBFT_SIG ) ! 134: return -EINVAL; ! 135: ! 136: /* Append IB subtable to existing table */ ! 137: used = le32_to_cpu ( sbft->acpi.length ); ! 138: sbft->ib_offset = cpu_to_le16 ( used ); ! 139: ib_sbft = ( ( ( void * ) sbft ) + used ); ! 140: used += sizeof ( *ib_sbft ); ! 141: if ( used > len ) ! 142: return -ENOBUFS; ! 143: sbft->acpi.length = cpu_to_le32 ( used ); ! 144: ! 145: /* Populate subtable */ ! 146: memcpy ( &ib_sbft->sgid, &ibdev->gid, sizeof ( ib_sbft->sgid ) ); ! 147: memcpy ( &ib_sbft->dgid, &ib_srp->dgid, sizeof ( ib_sbft->dgid ) ); ! 148: memcpy ( &ib_sbft->service_id, &ib_srp->service_id, ! 149: sizeof ( ib_sbft->service_id ) ); ! 150: ib_sbft->pkey = cpu_to_le16 ( ibdev->pkey ); ! 151: ! 152: return 0; ! 153: } ! 154: ! 155: /** IB SRP CMRC interface operations */ ! 156: static struct interface_operation ib_srp_cmrc_op[] = { ! 157: INTF_OP ( intf_close, struct ib_srp_device *, ib_srp_close ), ! 158: }; ! 159: ! 160: /** IB SRP CMRC interface descriptor */ ! 161: static struct interface_descriptor ib_srp_cmrc_desc = ! 162: INTF_DESC_PASSTHRU ( struct ib_srp_device, cmrc, ib_srp_cmrc_op, srp ); ! 163: ! 164: /** IB SRP SRP interface operations */ ! 165: static struct interface_operation ib_srp_srp_op[] = { ! 166: INTF_OP ( acpi_describe, struct ib_srp_device *, ib_srp_describe ), ! 167: INTF_OP ( intf_close, struct ib_srp_device *, ib_srp_close ), ! 168: }; ! 169: ! 170: /** IB SRP SRP interface descriptor */ ! 171: static struct interface_descriptor ib_srp_srp_desc = ! 172: INTF_DESC_PASSTHRU ( struct ib_srp_device, srp, ib_srp_srp_op, cmrc ); ! 173: ! 174: /** ! 175: * Open IB SRP device ! 176: * ! 177: * @v block Block control interface ! 178: * @v ibdev Infiniband device ! 179: * @v dgid Destination GID ! 180: * @v service_id Service ID ! 181: * @v initiator Initiator port ID ! 182: * @v target Target port ID ! 183: * @v lun SCSI LUN ! 184: * @ret rc Return status code ! 185: */ ! 186: static int ib_srp_open ( struct interface *block, struct ib_device *ibdev, ! 187: union ib_gid *dgid, union ib_guid *service_id, ! 188: union srp_port_id *initiator, ! 189: union srp_port_id *target, struct scsi_lun *lun ) { ! 190: struct ib_srp_device *ib_srp; ! 191: int rc; ! 192: ! 193: /* Allocate and initialise structure */ ! 194: ib_srp = zalloc ( sizeof ( *ib_srp ) ); ! 195: if ( ! ib_srp ) { ! 196: rc = -ENOMEM; ! 197: goto err_zalloc; ! 198: } ! 199: ref_init ( &ib_srp->refcnt, ib_srp_free ); ! 200: intf_init ( &ib_srp->srp, &ib_srp_srp_desc, &ib_srp->refcnt ); ! 201: intf_init ( &ib_srp->cmrc, &ib_srp_cmrc_desc, &ib_srp->refcnt ); ! 202: ib_srp->ibdev = ibdev_get ( ibdev ); ! 203: DBGC ( ib_srp, "IBSRP %p for " IB_GID_FMT " " IB_GUID_FMT "\n", ! 204: ib_srp, IB_GID_ARGS ( dgid ), IB_GUID_ARGS ( service_id ) ); ! 205: ! 206: /* Preserve parameters required for boot firmware table */ ! 207: memcpy ( &ib_srp->dgid, dgid, sizeof ( ib_srp->dgid ) ); ! 208: memcpy ( &ib_srp->service_id, service_id, ! 209: sizeof ( ib_srp->service_id ) ); ! 210: ! 211: /* Open CMRC socket */ ! 212: if ( ( rc = ib_cmrc_open ( &ib_srp->cmrc, ibdev, dgid, ! 213: service_id ) ) != 0 ) { ! 214: DBGC ( ib_srp, "IBSRP %p could not open CMRC socket: %s\n", ! 215: ib_srp, strerror ( rc ) ); ! 216: goto err_cmrc_open; ! 217: } ! 218: ! 219: /* Attach SRP device to parent interface */ ! 220: if ( ( rc = srp_open ( block, &ib_srp->srp, initiator, target, ! 221: ibdev->rdma_key, lun ) ) != 0 ) { ! 222: DBGC ( ib_srp, "IBSRP %p could not create SRP device: %s\n", ! 223: ib_srp, strerror ( rc ) ); ! 224: goto err_srp_open; ! 225: } ! 226: ! 227: /* Mortalise self and return */ ! 228: ref_put ( &ib_srp->refcnt ); ! 229: return 0; ! 230: ! 231: err_srp_open: ! 232: err_cmrc_open: ! 233: ib_srp_close ( ib_srp, rc ); ! 234: ref_put ( &ib_srp->refcnt ); ! 235: err_zalloc: ! 236: return rc; ! 237: } ! 238: ! 239: /****************************************************************************** ! 240: * ! 241: * IB SRP URIs ! 242: * ! 243: ****************************************************************************** ! 244: */ ! 245: ! 246: /** IB SRP parse flags */ ! 247: enum ib_srp_parse_flags { ! 248: IB_SRP_PARSE_REQUIRED = 0x0000, ! 249: IB_SRP_PARSE_OPTIONAL = 0x8000, ! 250: IB_SRP_PARSE_FLAG_MASK = 0xf000, ! 251: }; ! 252: ! 253: /** IB SRP root path parameters */ ! 254: struct ib_srp_root_path { ! 255: /** Source GID */ ! 256: union ib_gid sgid; ! 257: /** Initiator port ID */ ! 258: union ib_srp_initiator_port_id initiator; ! 259: /** Destination GID */ ! 260: union ib_gid dgid; ! 261: /** Partition key */ ! 262: uint16_t pkey; ! 263: /** Service ID */ ! 264: union ib_guid service_id; ! 265: /** SCSI LUN */ ! 266: struct scsi_lun lun; ! 267: /** Target port ID */ ! 268: union ib_srp_target_port_id target; ! 269: }; ! 270: ! 271: /** ! 272: * Parse IB SRP root path byte-string value ! 273: * ! 274: * @v rp_comp Root path component string ! 275: * @v default_value Default value to use if component string is empty ! 276: * @ret value Value ! 277: */ ! 278: static int ib_srp_parse_byte_string ( const char *rp_comp, uint8_t *bytes, ! 279: unsigned int size_flags ) { ! 280: size_t size = ( size_flags & ~IB_SRP_PARSE_FLAG_MASK ); ! 281: size_t rp_comp_len = strlen ( rp_comp ); ! 282: int decoded_size; ! 283: ! 284: /* Allow optional components to be empty */ ! 285: if ( ( rp_comp_len == 0 ) && ! 286: ( size_flags & IB_SRP_PARSE_OPTIONAL ) ) ! 287: return 0; ! 288: ! 289: /* Check string length */ ! 290: if ( rp_comp_len != ( 2 * size ) ) ! 291: return -EINVAL_BYTE_STRING_LEN; ! 292: ! 293: /* Parse byte string */ ! 294: decoded_size = base16_decode ( rp_comp, bytes ); ! 295: if ( decoded_size < 0 ) ! 296: return decoded_size; ! 297: ! 298: return 0; ! 299: } ! 300: ! 301: /** ! 302: * Parse IB SRP root path integer value ! 303: * ! 304: * @v rp_comp Root path component string ! 305: * @v default_value Default value to use if component string is empty ! 306: * @ret value Value ! 307: */ ! 308: static int ib_srp_parse_integer ( const char *rp_comp, int default_value ) { ! 309: int value; ! 310: char *end; ! 311: ! 312: value = strtoul ( rp_comp, &end, 16 ); ! 313: if ( *end ) ! 314: return -EINVAL_INTEGER; ! 315: ! 316: if ( end == rp_comp ) ! 317: return default_value; ! 318: ! 319: return value; ! 320: } ! 321: ! 322: /** ! 323: * Parse IB SRP root path source GID ! 324: * ! 325: * @v rp_comp Root path component string ! 326: * @v rp IB SRP root path ! 327: * @ret rc Return status code ! 328: */ ! 329: static int ib_srp_parse_sgid ( const char *rp_comp, ! 330: struct ib_srp_root_path *rp ) { ! 331: struct ib_device *ibdev; ! 332: ! 333: /* Default to the GID of the last opened Infiniband device */ ! 334: if ( ( ibdev = last_opened_ibdev() ) != NULL ) ! 335: memcpy ( &rp->sgid, &ibdev->gid, sizeof ( rp->sgid ) ); ! 336: ! 337: return ib_srp_parse_byte_string ( rp_comp, rp->sgid.bytes, ! 338: ( sizeof ( rp->sgid ) | ! 339: IB_SRP_PARSE_OPTIONAL ) ); ! 340: } ! 341: ! 342: /** ! 343: * Parse IB SRP root path initiator identifier extension ! 344: * ! 345: * @v rp_comp Root path component string ! 346: * @v rp IB SRP root path ! 347: * @ret rc Return status code ! 348: */ ! 349: static int ib_srp_parse_initiator_id_ext ( const char *rp_comp, ! 350: struct ib_srp_root_path *rp ) { ! 351: union ib_srp_initiator_port_id *port_id = &rp->initiator; ! 352: ! 353: return ib_srp_parse_byte_string ( rp_comp, port_id->ib.id_ext.bytes, ! 354: ( sizeof ( port_id->ib.id_ext ) | ! 355: IB_SRP_PARSE_OPTIONAL ) ); ! 356: } ! 357: ! 358: /** ! 359: * Parse IB SRP root path initiator HCA GUID ! 360: * ! 361: * @v rp_comp Root path component string ! 362: * @v rp IB SRP root path ! 363: * @ret rc Return status code ! 364: */ ! 365: static int ib_srp_parse_initiator_hca_guid ( const char *rp_comp, ! 366: struct ib_srp_root_path *rp ) { ! 367: union ib_srp_initiator_port_id *port_id = &rp->initiator; ! 368: ! 369: /* Default to the GUID portion of the source GID */ ! 370: memcpy ( &port_id->ib.hca_guid, &rp->sgid.s.guid, ! 371: sizeof ( port_id->ib.hca_guid ) ); ! 372: ! 373: return ib_srp_parse_byte_string ( rp_comp, port_id->ib.hca_guid.bytes, ! 374: ( sizeof ( port_id->ib.hca_guid ) | ! 375: IB_SRP_PARSE_OPTIONAL ) ); ! 376: } ! 377: ! 378: /** ! 379: * Parse IB SRP root path destination GID ! 380: * ! 381: * @v rp_comp Root path component string ! 382: * @v rp IB SRP root path ! 383: * @ret rc Return status code ! 384: */ ! 385: static int ib_srp_parse_dgid ( const char *rp_comp, ! 386: struct ib_srp_root_path *rp ) { ! 387: return ib_srp_parse_byte_string ( rp_comp, rp->dgid.bytes, ! 388: ( sizeof ( rp->dgid ) | ! 389: IB_SRP_PARSE_REQUIRED ) ); ! 390: } ! 391: ! 392: /** ! 393: * Parse IB SRP root path partition key ! 394: * ! 395: * @v rp_comp Root path component string ! 396: * @v rp IB SRP root path ! 397: * @ret rc Return status code ! 398: */ ! 399: static int ib_srp_parse_pkey ( const char *rp_comp, ! 400: struct ib_srp_root_path *rp ) { ! 401: int pkey; ! 402: ! 403: if ( ( pkey = ib_srp_parse_integer ( rp_comp, IB_PKEY_DEFAULT ) ) < 0 ) ! 404: return pkey; ! 405: rp->pkey = pkey; ! 406: return 0; ! 407: } ! 408: ! 409: /** ! 410: * Parse IB SRP root path service ID ! 411: * ! 412: * @v rp_comp Root path component string ! 413: * @v rp IB SRP root path ! 414: * @ret rc Return status code ! 415: */ ! 416: static int ib_srp_parse_service_id ( const char *rp_comp, ! 417: struct ib_srp_root_path *rp ) { ! 418: return ib_srp_parse_byte_string ( rp_comp, rp->service_id.bytes, ! 419: ( sizeof ( rp->service_id ) | ! 420: IB_SRP_PARSE_REQUIRED ) ); ! 421: } ! 422: ! 423: /** ! 424: * Parse IB SRP root path LUN ! 425: * ! 426: * @v rp_comp Root path component string ! 427: * @v rp IB SRP root path ! 428: * @ret rc Return status code ! 429: */ ! 430: static int ib_srp_parse_lun ( const char *rp_comp, ! 431: struct ib_srp_root_path *rp ) { ! 432: return scsi_parse_lun ( rp_comp, &rp->lun ); ! 433: } ! 434: ! 435: /** ! 436: * Parse IB SRP root path target identifier extension ! 437: * ! 438: * @v rp_comp Root path component string ! 439: * @v rp IB SRP root path ! 440: * @ret rc Return status code ! 441: */ ! 442: static int ib_srp_parse_target_id_ext ( const char *rp_comp, ! 443: struct ib_srp_root_path *rp ) { ! 444: union ib_srp_target_port_id *port_id = &rp->target; ! 445: ! 446: return ib_srp_parse_byte_string ( rp_comp, port_id->ib.id_ext.bytes, ! 447: ( sizeof ( port_id->ib.id_ext ) | ! 448: IB_SRP_PARSE_REQUIRED ) ); ! 449: } ! 450: ! 451: /** ! 452: * Parse IB SRP root path target I/O controller GUID ! 453: * ! 454: * @v rp_comp Root path component string ! 455: * @v rp IB SRP root path ! 456: * @ret rc Return status code ! 457: */ ! 458: static int ib_srp_parse_target_ioc_guid ( const char *rp_comp, ! 459: struct ib_srp_root_path *rp ) { ! 460: union ib_srp_target_port_id *port_id = &rp->target; ! 461: ! 462: return ib_srp_parse_byte_string ( rp_comp, port_id->ib.ioc_guid.bytes, ! 463: ( sizeof ( port_id->ib.ioc_guid ) | ! 464: IB_SRP_PARSE_REQUIRED ) ); ! 465: } ! 466: ! 467: /** IB SRP root path component parser */ ! 468: struct ib_srp_root_path_parser { ! 469: /** ! 470: * Parse IB SRP root path component ! 471: * ! 472: * @v rp_comp Root path component string ! 473: * @v rp IB SRP root path ! 474: * @ret rc Return status code ! 475: */ ! 476: int ( * parse ) ( const char *rp_comp, struct ib_srp_root_path *rp ); ! 477: }; ! 478: ! 479: /** IB SRP root path components */ ! 480: static struct ib_srp_root_path_parser ib_srp_rp_parser[] = { ! 481: { ib_srp_parse_sgid }, ! 482: { ib_srp_parse_initiator_id_ext }, ! 483: { ib_srp_parse_initiator_hca_guid }, ! 484: { ib_srp_parse_dgid }, ! 485: { ib_srp_parse_pkey }, ! 486: { ib_srp_parse_service_id }, ! 487: { ib_srp_parse_lun }, ! 488: { ib_srp_parse_target_id_ext }, ! 489: { ib_srp_parse_target_ioc_guid }, ! 490: }; ! 491: ! 492: /** Number of IB SRP root path components */ ! 493: #define IB_SRP_NUM_RP_COMPONENTS \ ! 494: ( sizeof ( ib_srp_rp_parser ) / sizeof ( ib_srp_rp_parser[0] ) ) ! 495: ! 496: /** ! 497: * Parse IB SRP root path ! 498: * ! 499: * @v rp_string Root path string ! 500: * @v rp IB SRP root path ! 501: * @ret rc Return status code ! 502: */ ! 503: static int ib_srp_parse_root_path ( const char *rp_string, ! 504: struct ib_srp_root_path *rp ) { ! 505: struct ib_srp_root_path_parser *parser; ! 506: char rp_string_copy[ strlen ( rp_string ) + 1 ]; ! 507: char *rp_comp[IB_SRP_NUM_RP_COMPONENTS]; ! 508: char *rp_string_tmp = rp_string_copy; ! 509: unsigned int i = 0; ! 510: int rc; ! 511: ! 512: /* Split root path into component parts */ ! 513: strcpy ( rp_string_copy, rp_string ); ! 514: while ( 1 ) { ! 515: rp_comp[i++] = rp_string_tmp; ! 516: if ( i == IB_SRP_NUM_RP_COMPONENTS ) ! 517: break; ! 518: for ( ; *rp_string_tmp != ':' ; rp_string_tmp++ ) { ! 519: if ( ! *rp_string_tmp ) { ! 520: DBG ( "IBSRP root path \"%s\" too short\n", ! 521: rp_string ); ! 522: return -EINVAL_RP_TOO_SHORT; ! 523: } ! 524: } ! 525: *(rp_string_tmp++) = '\0'; ! 526: } ! 527: ! 528: /* Parse root path components */ ! 529: for ( i = 0 ; i < IB_SRP_NUM_RP_COMPONENTS ; i++ ) { ! 530: parser = &ib_srp_rp_parser[i]; ! 531: if ( ( rc = parser->parse ( rp_comp[i], rp ) ) != 0 ) { ! 532: DBG ( "IBSRP could not parse \"%s\" in root path " ! 533: "\"%s\": %s\n", rp_comp[i], rp_string, ! 534: strerror ( rc ) ); ! 535: return rc; ! 536: } ! 537: } ! 538: ! 539: return 0; ! 540: } ! 541: ! 542: /** ! 543: * Open IB SRP URI ! 544: * ! 545: * @v parent Parent interface ! 546: * @v uri URI ! 547: * @ret rc Return status code ! 548: */ ! 549: static int ib_srp_open_uri ( struct interface *parent, struct uri *uri ) { ! 550: struct ib_srp_root_path rp; ! 551: struct ib_device *ibdev; ! 552: int rc; ! 553: ! 554: /* Parse URI */ ! 555: if ( ! uri->opaque ) ! 556: return -EINVAL; ! 557: memset ( &rp, 0, sizeof ( rp ) ); ! 558: if ( ( rc = ib_srp_parse_root_path ( uri->opaque, &rp ) ) != 0 ) ! 559: return rc; ! 560: ! 561: /* Identify Infiniband device */ ! 562: ibdev = find_ibdev ( &rp.sgid ); ! 563: if ( ! ibdev ) { ! 564: DBG ( "IBSRP could not identify Infiniband device\n" ); ! 565: return -ENODEV; ! 566: } ! 567: ! 568: /* Open IB SRP device */ ! 569: if ( ( rc = ib_srp_open ( parent, ibdev, &rp.dgid, &rp.service_id, ! 570: &rp.initiator.srp, &rp.target.srp, ! 571: &rp.lun ) ) != 0 ) ! 572: return rc; ! 573: ! 574: return 0; ! 575: } ! 576: ! 577: /** IB SRP URI opener */ ! 578: struct uri_opener ib_srp_uri_opener __uri_opener = { ! 579: .scheme = "ib_srp", ! 580: .open = ib_srp_open_uri, ! 581: };
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.