176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/*
276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * Copyright (C) 2009 Fen Systems Ltd <mbrown@fensystems.co.uk>.
376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * All rights reserved.
476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *
576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * Redistribution and use in source and binary forms, with or without
676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * modification, are permitted provided that the following conditions
776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * are met:
876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *
976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *   Redistributions of source code must retain the above copyright
1076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *   notice, this list of conditions and the following disclaimer.
1176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *
1276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *   Redistributions in binary form must reproduce the above copyright
1376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *   notice, this list of conditions and the following disclaimer in
1476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *   the documentation and/or other materials provided with the
1576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *   distribution.
1676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *
1776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
1876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
1976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
2076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
2176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
2276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
2376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
2476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
2676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
2776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
2876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * OF THE POSSIBILITY OF SUCH DAMAGE.
2976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman */
3076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
3176d05dc695b06c4e987bb8078f78032441e1430cGreg HartmanFILE_LICENCE ( BSD2 );
3276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
3376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#include <stdlib.h>
3476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#include <errno.h>
3576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#include <gpxe/srp.h>
3676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#include <gpxe/infiniband.h>
3776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#include <gpxe/ib_cmrc.h>
3876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#include <gpxe/ib_srp.h>
3976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
4076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/**
4176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * @file
4276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *
4376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * SCSI RDMA Protocol over Infiniband
4476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *
4576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman */
4676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
4776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/* Disambiguate the various possible EINVALs */
4876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#define EINVAL_BYTE_STRING_LEN ( EINVAL | EUNIQ_01 )
4976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#define EINVAL_BYTE_STRING ( EINVAL | EUNIQ_02 )
5076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#define EINVAL_INTEGER ( EINVAL | EUNIQ_03 )
5176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#define EINVAL_RP_TOO_SHORT ( EINVAL | EUNIQ_04 )
5276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
5376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/** IB SRP parse flags */
5476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanenum ib_srp_parse_flags {
5576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	IB_SRP_PARSE_REQUIRED = 0x0000,
5676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	IB_SRP_PARSE_OPTIONAL = 0x8000,
5776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	IB_SRP_PARSE_FLAG_MASK = 0xf000,
5876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman};
5976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
6076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/** IB SRP root path parameters */
6176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstruct ib_srp_root_path {
6276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	/** SCSI LUN */
6376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	struct scsi_lun *lun;
6476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	/** SRP port IDs */
6576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	struct srp_port_ids *port_ids;
6676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	/** IB SRP parameters */
6776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	struct ib_srp_parameters *ib;
6876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman};
6976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
7076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/**
7176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * Parse IB SRP root path byte-string value
7276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *
7376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * @v rp_comp		Root path component string
7476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * @v default_value	Default value to use if component string is empty
7576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * @ret value		Value
7676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman */
7776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic int ib_srp_parse_byte_string ( const char *rp_comp, uint8_t *bytes,
7876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman				      unsigned int size_flags ) {
7976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	size_t size = ( size_flags & ~IB_SRP_PARSE_FLAG_MASK );
8076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	size_t rp_comp_len = strlen ( rp_comp );
8176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	char buf[3];
8276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	char *buf_end;
8376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
8476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	/* Allow optional components to be empty */
8576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	if ( ( rp_comp_len == 0 ) &&
8676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	     ( size_flags & IB_SRP_PARSE_OPTIONAL ) )
8776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman		return 0;
8876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
8976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	/* Check string length */
9076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	if ( rp_comp_len != ( 2 * size ) )
9176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman		return -EINVAL_BYTE_STRING_LEN;
9276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
9376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	/* Parse byte string */
9476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	for ( ; size ; size--, rp_comp += 2, bytes++ ) {
9576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman		memcpy ( buf, rp_comp, 2 );
9676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman		buf[2] = '\0';
9776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman		*bytes = strtoul ( buf, &buf_end, 16 );
9876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman		if ( buf_end != &buf[2] )
9976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman			return -EINVAL_BYTE_STRING;
10076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	}
10176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	return 0;
10276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman}
10376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
10476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/**
10576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * Parse IB SRP root path integer value
10676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *
10776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * @v rp_comp		Root path component string
10876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * @v default_value	Default value to use if component string is empty
10976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * @ret value		Value
11076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman */
11176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic int ib_srp_parse_integer ( const char *rp_comp, int default_value ) {
11276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	int value;
11376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	char *end;
11476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
11576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	value = strtoul ( rp_comp, &end, 16 );
11676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	if ( *end )
11776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman		return -EINVAL_INTEGER;
11876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
11976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	if ( end == rp_comp )
12076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman		return default_value;
12176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
12276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	return value;
12376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman}
12476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
12576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/**
12676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * Parse IB SRP root path literal component
12776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *
12876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * @v rp_comp		Root path component string
12976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * @v rp		IB SRP root path
13076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * @ret rc		Return status code
13176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman */
13276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic int ib_srp_parse_literal ( const char *rp_comp __unused,
13376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman				  struct ib_srp_root_path *rp __unused ) {
13476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	/* Ignore */
13576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	return 0;
13676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman}
13776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
13876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/**
13976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * Parse IB SRP root path source GID
14076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *
14176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * @v rp_comp		Root path component string
14276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * @v rp		IB SRP root path
14376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * @ret rc		Return status code
14476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman */
14576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic int ib_srp_parse_sgid ( const char *rp_comp,
14676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman			       struct ib_srp_root_path *rp ) {
14776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	struct ib_device *ibdev;
14876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
14976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	/* Default to the GID of the last opened Infiniband device */
15076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	if ( ( ibdev = last_opened_ibdev() ) != NULL )
15176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman		memcpy ( &rp->ib->sgid, &ibdev->gid, sizeof ( rp->ib->sgid ) );
15276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
15376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	return ib_srp_parse_byte_string ( rp_comp, rp->ib->sgid.u.bytes,
15476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman					  ( sizeof ( rp->ib->sgid ) |
15576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman					    IB_SRP_PARSE_OPTIONAL ) );
15676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman}
15776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
15876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/**
15976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * Parse IB SRP root path initiator identifier extension
16076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *
16176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * @v rp_comp		Root path component string
16276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * @v rp		IB SRP root path
16376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * @ret rc		Return status code
16476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman */
16576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic int ib_srp_parse_initiator_id_ext ( const char *rp_comp,
16676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman					   struct ib_srp_root_path *rp ) {
16776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	struct ib_srp_initiator_port_id *port_id =
16876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman		ib_srp_initiator_port_id ( rp->port_ids );
16976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
17076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	return ib_srp_parse_byte_string ( rp_comp, port_id->id_ext.u.bytes,
17176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman					  ( sizeof ( port_id->id_ext ) |
17276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman					    IB_SRP_PARSE_OPTIONAL ) );
17376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman}
17476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
17576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/**
17676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * Parse IB SRP root path initiator HCA GUID
17776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *
17876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * @v rp_comp		Root path component string
17976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * @v rp		IB SRP root path
18076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * @ret rc		Return status code
18176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman */
18276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic int ib_srp_parse_initiator_hca_guid ( const char *rp_comp,
18376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman					     struct ib_srp_root_path *rp ) {
18476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	struct ib_srp_initiator_port_id *port_id =
18576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman		ib_srp_initiator_port_id ( rp->port_ids );
18676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
18776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	/* Default to the GUID portion of the source GID */
18876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	memcpy ( &port_id->hca_guid, &rp->ib->sgid.u.half[1],
18976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman		 sizeof ( port_id->hca_guid ) );
19076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
19176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	return ib_srp_parse_byte_string ( rp_comp, port_id->hca_guid.u.bytes,
19276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman					  ( sizeof ( port_id->hca_guid ) |
19376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman					    IB_SRP_PARSE_OPTIONAL ) );
19476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman}
19576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
19676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/**
19776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * Parse IB SRP root path destination GID
19876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *
19976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * @v rp_comp		Root path component string
20076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * @v rp		IB SRP root path
20176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * @ret rc		Return status code
20276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman */
20376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic int ib_srp_parse_dgid ( const char *rp_comp,
20476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman			       struct ib_srp_root_path *rp ) {
20576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	return ib_srp_parse_byte_string ( rp_comp, rp->ib->dgid.u.bytes,
20676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman					  ( sizeof ( rp->ib->dgid ) |
20776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman					    IB_SRP_PARSE_REQUIRED ) );
20876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman}
20976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
21076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/**
21176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * Parse IB SRP root path partition key
21276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *
21376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * @v rp_comp		Root path component string
21476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * @v rp		IB SRP root path
21576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * @ret rc		Return status code
21676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman */
21776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic int ib_srp_parse_pkey ( const char *rp_comp,
21876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman			       struct ib_srp_root_path *rp ) {
21976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	int pkey;
22076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
22176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	if ( ( pkey = ib_srp_parse_integer ( rp_comp, IB_PKEY_DEFAULT ) ) < 0 )
22276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman		return pkey;
22376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	rp->ib->pkey = pkey;
22476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	return 0;
22576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman}
22676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
22776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/**
22876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * Parse IB SRP root path service ID
22976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *
23076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * @v rp_comp		Root path component string
23176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * @v rp		IB SRP root path
23276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * @ret rc		Return status code
23376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman */
23476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic int ib_srp_parse_service_id ( const char *rp_comp,
23576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman				     struct ib_srp_root_path *rp ) {
23676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	return ib_srp_parse_byte_string ( rp_comp, rp->ib->service_id.u.bytes,
23776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman					  ( sizeof ( rp->ib->service_id ) |
23876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman					    IB_SRP_PARSE_REQUIRED ) );
23976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman}
24076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
24176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/**
24276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * Parse IB SRP root path LUN
24376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *
24476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * @v rp_comp		Root path component string
24576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * @v rp		IB SRP root path
24676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * @ret rc		Return status code
24776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman */
24876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic int ib_srp_parse_lun ( const char *rp_comp,
24976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman			      struct ib_srp_root_path *rp ) {
25076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	return scsi_parse_lun ( rp_comp, rp->lun );
25176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman}
25276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
25376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/**
25476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * Parse IB SRP root path target identifier extension
25576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *
25676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * @v rp_comp		Root path component string
25776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * @v rp		IB SRP root path
25876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * @ret rc		Return status code
25976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman */
26076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic int ib_srp_parse_target_id_ext ( const char *rp_comp,
26176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman					struct ib_srp_root_path *rp ) {
26276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	struct ib_srp_target_port_id *port_id =
26376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman		ib_srp_target_port_id ( rp->port_ids );
26476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
26576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	return ib_srp_parse_byte_string ( rp_comp, port_id->id_ext.u.bytes,
26676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman					  ( sizeof ( port_id->id_ext ) |
26776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman					    IB_SRP_PARSE_REQUIRED ) );
26876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman}
26976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
27076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/**
27176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * Parse IB SRP root path target I/O controller GUID
27276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *
27376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * @v rp_comp		Root path component string
27476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * @v rp		IB SRP root path
27576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * @ret rc		Return status code
27676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman */
27776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic int ib_srp_parse_target_ioc_guid ( const char *rp_comp,
27876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman					  struct ib_srp_root_path *rp ) {
27976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	struct ib_srp_target_port_id *port_id =
28076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman		ib_srp_target_port_id ( rp->port_ids );
28176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
28276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	return ib_srp_parse_byte_string ( rp_comp, port_id->ioc_guid.u.bytes,
28376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman					  ( sizeof ( port_id->ioc_guid ) |
28476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman					    IB_SRP_PARSE_REQUIRED ) );
28576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman}
28676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
28776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/** IB SRP root path component parser */
28876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstruct ib_srp_root_path_parser {
28976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	/**
29076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	 * Parse IB SRP root path component
29176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	 *
29276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	 * @v rp_comp		Root path component string
29376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	 * @v rp		IB SRP root path
29476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	 * @ret rc		Return status code
29576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	 */
29676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	int ( * parse ) ( const char *rp_comp, struct ib_srp_root_path *rp );
29776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman};
29876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
29976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/** IB SRP root path components */
30076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic struct ib_srp_root_path_parser ib_srp_rp_parser[] = {
30176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	{ ib_srp_parse_literal },
30276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	{ ib_srp_parse_sgid },
30376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	{ ib_srp_parse_initiator_id_ext },
30476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	{ ib_srp_parse_initiator_hca_guid },
30576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	{ ib_srp_parse_dgid },
30676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	{ ib_srp_parse_pkey },
30776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	{ ib_srp_parse_service_id },
30876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	{ ib_srp_parse_lun },
30976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	{ ib_srp_parse_target_id_ext },
31076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	{ ib_srp_parse_target_ioc_guid },
31176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman};
31276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
31376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/** Number of IB SRP root path components */
31476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#define IB_SRP_NUM_RP_COMPONENTS \
31576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	( sizeof ( ib_srp_rp_parser ) / sizeof ( ib_srp_rp_parser[0] ) )
31676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
31776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/**
31876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * Parse IB SRP root path
31976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *
32076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * @v srp		SRP device
32176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * @v rp_string		Root path
32276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * @ret rc		Return status code
32376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman */
32476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic int ib_srp_parse_root_path ( struct srp_device *srp,
32576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman				    const char *rp_string ) {
32676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	struct ib_srp_parameters *ib_params = ib_srp_params ( srp );
32776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	struct ib_srp_root_path rp = {
32876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman		.lun = &srp->lun,
32976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman		.port_ids = &srp->port_ids,
33076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman		.ib = ib_params,
33176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	};
33276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	char rp_string_copy[ strlen ( rp_string ) + 1 ];
33376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	char *rp_comp[IB_SRP_NUM_RP_COMPONENTS];
33476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	char *rp_string_tmp = rp_string_copy;
33576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	unsigned int i = 0;
33676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	int rc;
33776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
33876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	/* Split root path into component parts */
33976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	strcpy ( rp_string_copy, rp_string );
34076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	while ( 1 ) {
34176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman		rp_comp[i++] = rp_string_tmp;
34276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman		if ( i == IB_SRP_NUM_RP_COMPONENTS )
34376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman			break;
34476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman		for ( ; *rp_string_tmp != ':' ; rp_string_tmp++ ) {
34576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman			if ( ! *rp_string_tmp ) {
34676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman				DBGC ( srp, "SRP %p root path \"%s\" too "
34776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman				       "short\n", srp, rp_string );
34876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman				return -EINVAL_RP_TOO_SHORT;
34976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman			}
35076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman		}
35176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman		*(rp_string_tmp++) = '\0';
35276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	}
35376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
35476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	/* Parse root path components */
35576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	for ( i = 0 ; i < IB_SRP_NUM_RP_COMPONENTS ; i++ ) {
35676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman		if ( ( rc = ib_srp_rp_parser[i].parse ( rp_comp[i],
35776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman							&rp ) ) != 0 ) {
35876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman			DBGC ( srp, "SRP %p could not parse \"%s\" in root "
35976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman			       "path \"%s\": %s\n", srp, rp_comp[i],
36076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman			       rp_string, strerror ( rc ) );
36176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman			return rc;
36276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman		}
36376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	}
36476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
36576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	return 0;
36676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman}
36776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
36876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/**
36976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * Connect IB SRP session
37076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *
37176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * @v srp		SRP device
37276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * @ret rc		Return status code
37376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman */
37476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic int ib_srp_connect ( struct srp_device *srp ) {
37576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	struct ib_srp_parameters *ib_params = ib_srp_params ( srp );
37676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	struct ib_device *ibdev;
37776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	int rc;
37876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
37976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	/* Identify Infiniband device */
38076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	ibdev = find_ibdev ( &ib_params->sgid );
38176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	if ( ! ibdev ) {
38276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman		DBGC ( srp, "SRP %p could not identify Infiniband device\n",
38376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman		       srp );
38476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman		return -ENODEV;
38576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	}
38676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
38776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	/* Configure remaining SRP parameters */
38876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	srp->memory_handle = ibdev->rdma_key;
38976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
39076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	/* Open CMRC socket */
39176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	if ( ( rc = ib_cmrc_open ( &srp->socket, ibdev, &ib_params->dgid,
39276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman				   &ib_params->service_id ) ) != 0 ) {
39376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman		DBGC ( srp, "SRP %p could not open CMRC socket: %s\n",
39476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman		       srp, strerror ( rc ) );
39576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman		return rc;
39676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	}
39776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
39876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	return 0;
39976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman}
40076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
40176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/** IB SRP transport type */
40276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstruct srp_transport_type ib_srp_transport = {
40376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	.priv_len = sizeof ( struct ib_srp_parameters ),
40476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	.parse_root_path = ib_srp_parse_root_path,
40576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	.connect = ib_srp_connect,
40676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman};
407