david/ipxe
david
/
ipxe
Archived
1
0
Fork 0

[fc] Do not use the command reference number in FCP_CMND IUs

The FCP command reference number is intended to be used for
controlling precise delivery of FCP commands, rather than being an
essentially arbitrary tag field (as with iSCSI and SRP).

Use the Fibre Channel local exchange ID as the tag for FCP commands,
instead of the FCP command reference.  The local exchange ID does not
appear within the FCP IU itself, but does appear within the FC frame
header; debug traces can therefore still be correlated with packet
captures.

Reported-by: Hadar Hen Zion <hadarh@mellanox.co.il>
Signed-off-by: Michael Brown <mcb30@ipxe.org>
This commit is contained in:
Michael Brown 2010-10-19 18:35:46 +01:00
parent 4995ffa438
commit b0e434280e
3 changed files with 65 additions and 62 deletions

View File

@ -703,7 +703,7 @@ static struct fc_exchange * fc_xchg_create ( struct fc_port *port,
* @v parent Interface to which to attach * @v parent Interface to which to attach
* @v port Fibre Channel port * @v port Fibre Channel port
* @v peer_port_id Peer port ID * @v peer_port_id Peer port ID
* @ret rc Return status code * @ret xchg_id Exchange ID, or negative error
*/ */
int fc_xchg_originate ( struct interface *parent, struct fc_port *port, int fc_xchg_originate ( struct interface *parent, struct fc_port *port,
struct fc_port_id *peer_port_id, unsigned int type ) { struct fc_port_id *peer_port_id, unsigned int type ) {
@ -722,7 +722,7 @@ int fc_xchg_originate ( struct interface *parent, struct fc_port *port,
/* Attach to parent interface and return */ /* Attach to parent interface and return */
intf_plug_plug ( &xchg->ulp, parent ); intf_plug_plug ( &xchg->ulp, parent );
return 0; return xchg->xchg_id;
} }
/** /**

View File

@ -265,6 +265,7 @@ static struct interface_descriptor fc_els_job_desc =
static void fc_els_step ( struct process *process ) { static void fc_els_step ( struct process *process ) {
struct fc_els *els = struct fc_els *els =
container_of ( process, struct fc_els, process ); container_of ( process, struct fc_els, process );
int xchg_id;
int rc; int rc;
/* Sanity check */ /* Sanity check */
@ -274,9 +275,10 @@ static void fc_els_step ( struct process *process ) {
process_del ( &els->process ); process_del ( &els->process );
/* Create exchange */ /* Create exchange */
if ( ( rc = fc_xchg_originate ( &els->xchg, els->port, if ( ( xchg_id = fc_xchg_originate ( &els->xchg, els->port,
&els->peer_port_id, &els->peer_port_id,
FC_TYPE_ELS ) ) != 0 ) { FC_TYPE_ELS ) ) < 0 ) {
rc = xchg_id;
DBGC ( els, FCELS_FMT " could not create exchange: %s\n", DBGC ( els, FCELS_FMT " could not create exchange: %s\n",
FCELS_ARGS ( els ), strerror ( rc ) ); FCELS_ARGS ( els ), strerror ( rc ) );
fc_els_close ( els, rc ); fc_els_close ( els, rc );

View File

@ -187,8 +187,8 @@ struct fcp_command {
size_t offset; size_t offset;
/** Length of data remaining to be sent within this IU */ /** Length of data remaining to be sent within this IU */
size_t remaining; size_t remaining;
/** Command reference */ /** Exchange ID */
uint8_t ref; uint16_t xchg_id;
}; };
/** /**
@ -285,8 +285,8 @@ static void fcpcmd_close ( struct fcp_command *fcpcmd, int rc ) {
struct fcp_device *fcpdev = fcpcmd->fcpdev; struct fcp_device *fcpdev = fcpcmd->fcpdev;
if ( rc != 0 ) { if ( rc != 0 ) {
DBGC ( fcpdev, "FCP %p ref %02x closed: %s\n", DBGC ( fcpdev, "FCP %p xchg %04x closed: %s\n",
fcpdev, fcpcmd->ref, strerror ( rc ) ); fcpdev, fcpcmd->xchg_id, strerror ( rc ) );
} }
/* Stop sending */ /* Stop sending */
@ -325,16 +325,16 @@ static int fcpcmd_send_cmnd ( struct fcp_command *fcpcmd ) {
/* Sanity check */ /* Sanity check */
if ( command->data_in_len && command->data_out_len ) { if ( command->data_in_len && command->data_out_len ) {
DBGC ( fcpdev, "FCP %p ref %02x cannot handle bidirectional " DBGC ( fcpdev, "FCP %p xchg %04x cannot handle bidirectional "
"command\n", fcpdev, fcpcmd->ref ); "command\n", fcpdev, fcpcmd->xchg_id );
return -ENOTSUP; return -ENOTSUP;
} }
/* Allocate I/O buffer */ /* Allocate I/O buffer */
iobuf = xfer_alloc_iob ( &fcpcmd->xchg, sizeof ( *cmnd ) ); iobuf = xfer_alloc_iob ( &fcpcmd->xchg, sizeof ( *cmnd ) );
if ( ! iobuf ) { if ( ! iobuf ) {
DBGC ( fcpdev, "FCP %p ref %02x cannot allocate command IU\n", DBGC ( fcpdev, "FCP %p xchg %04x cannot allocate command IU\n",
fcpdev, fcpcmd->ref ); fcpdev, fcpcmd->xchg_id );
return -ENOMEM; return -ENOMEM;
} }
@ -342,7 +342,6 @@ static int fcpcmd_send_cmnd ( struct fcp_command *fcpcmd ) {
cmnd = iob_put ( iobuf, sizeof ( *cmnd ) ); cmnd = iob_put ( iobuf, sizeof ( *cmnd ) );
memset ( cmnd, 0, sizeof ( *cmnd ) ); memset ( cmnd, 0, sizeof ( *cmnd ) );
memcpy ( &cmnd->lun, &command->lun, sizeof ( cmnd->lun ) ); memcpy ( &cmnd->lun, &command->lun, sizeof ( cmnd->lun ) );
cmnd->ref = fcpcmd->ref;
assert ( ! ( command->data_in_len && command->data_out_len ) ); assert ( ! ( command->data_in_len && command->data_out_len ) );
if ( command->data_in_len ) if ( command->data_in_len )
cmnd->dirn |= FCP_CMND_RDDATA; cmnd->dirn |= FCP_CMND_RDDATA;
@ -352,8 +351,8 @@ static int fcpcmd_send_cmnd ( struct fcp_command *fcpcmd ) {
cmnd->len = htonl ( command->data_in_len + command->data_out_len ); cmnd->len = htonl ( command->data_in_len + command->data_out_len );
memset ( &meta, 0, sizeof ( meta ) ); memset ( &meta, 0, sizeof ( meta ) );
meta.flags = ( XFER_FL_CMD_STAT | XFER_FL_OVER ); meta.flags = ( XFER_FL_CMD_STAT | XFER_FL_OVER );
DBGC2 ( fcpdev, "FCP %p ref %02x CMND " SCSI_CDB_FORMAT " %04x\n", DBGC2 ( fcpdev, "FCP %p xchg %04x CMND " SCSI_CDB_FORMAT " %04x\n",
fcpdev, fcpcmd->ref, SCSI_CDB_DATA ( cmnd->cdb ), fcpdev, fcpcmd->xchg_id, SCSI_CDB_DATA ( cmnd->cdb ),
ntohl ( cmnd->len ) ); ntohl ( cmnd->len ) );
/* No further data to send within this IU */ /* No further data to send within this IU */
@ -362,8 +361,8 @@ static int fcpcmd_send_cmnd ( struct fcp_command *fcpcmd ) {
/* Send command IU frame */ /* Send command IU frame */
if ( ( rc = xfer_deliver ( &fcpcmd->xchg, iob_disown ( iobuf ), if ( ( rc = xfer_deliver ( &fcpcmd->xchg, iob_disown ( iobuf ),
&meta ) ) != 0 ) { &meta ) ) != 0 ) {
DBGC ( fcpdev, "FCP %p ref %02x cannot deliver command IU: " DBGC ( fcpdev, "FCP %p xchg %04x cannot deliver command IU: "
"%s\n", fcpdev, fcpcmd->ref, strerror ( rc ) ); "%s\n", fcpdev, fcpcmd->xchg_id, strerror ( rc ) );
return rc; return rc;
} }
@ -389,27 +388,27 @@ static int fcpcmd_recv_rddata ( struct fcp_command *fcpcmd,
/* Sanity checks */ /* Sanity checks */
if ( ! ( meta->flags & XFER_FL_ABS_OFFSET ) ) { if ( ! ( meta->flags & XFER_FL_ABS_OFFSET ) ) {
DBGC ( fcpdev, "FCP %p ref %02x read data missing offset\n", DBGC ( fcpdev, "FCP %p xchg %04x read data missing offset\n",
fcpdev, fcpcmd->ref ); fcpdev, fcpcmd->xchg_id );
rc = -ERANGE_READ_DATA_ORDERING; rc = -ERANGE_READ_DATA_ORDERING;
goto done; goto done;
} }
if ( offset != fcpcmd->offset ) { if ( offset != fcpcmd->offset ) {
DBGC ( fcpdev, "FCP %p ref %02x read data out of order " DBGC ( fcpdev, "FCP %p xchg %04x read data out of order "
"(expected %zd, received %zd)\n", "(expected %zd, received %zd)\n",
fcpdev, fcpcmd->ref, fcpcmd->offset, offset ); fcpdev, fcpcmd->xchg_id, fcpcmd->offset, offset );
rc = -ERANGE_READ_DATA_ORDERING; rc = -ERANGE_READ_DATA_ORDERING;
goto done; goto done;
} }
if ( ( offset + len ) > command->data_in_len ) { if ( ( offset + len ) > command->data_in_len ) {
DBGC ( fcpdev, "FCP %p ref %02x read data overrun (max %zd, " DBGC ( fcpdev, "FCP %p xchg %04x read data overrun (max %zd, "
"received %zd)\n", fcpdev, fcpcmd->ref, "received %zd)\n", fcpdev, fcpcmd->xchg_id,
command->data_in_len, ( offset + len ) ); command->data_in_len, ( offset + len ) );
rc = -ERANGE_READ_DATA_OVERRUN; rc = -ERANGE_READ_DATA_OVERRUN;
goto done; goto done;
} }
DBGC2 ( fcpdev, "FCP %p ref %02x RDDATA [%08zx,%08zx)\n", DBGC2 ( fcpdev, "FCP %p xchg %04x RDDATA [%08zx,%08zx)\n",
fcpdev, fcpcmd->ref, offset, ( offset + len ) ); fcpdev, fcpcmd->xchg_id, offset, ( offset + len ) );
/* Copy to user buffer */ /* Copy to user buffer */
copy_to_user ( command->data_in, offset, iobuf->data, len ); copy_to_user ( command->data_in, offset, iobuf->data, len );
@ -443,13 +442,13 @@ static int fcpcmd_send_wrdata ( struct fcp_command *fcpcmd ) {
/* Sanity checks */ /* Sanity checks */
if ( len == 0 ) { if ( len == 0 ) {
DBGC ( fcpdev, "FCP %p ref %02x write data stuck\n", DBGC ( fcpdev, "FCP %p xchg %04x write data stuck\n",
fcpdev, fcpcmd->ref ); fcpdev, fcpcmd->xchg_id );
return -ERANGE_WRITE_DATA_STUCK; return -ERANGE_WRITE_DATA_STUCK;
} }
if ( ( fcpcmd->offset + len ) > command->data_out_len ) { if ( ( fcpcmd->offset + len ) > command->data_out_len ) {
DBGC ( fcpdev, "FCP %p ref %02x write data overrun (max %zd, " DBGC ( fcpdev, "FCP %p xchg %04x write data overrun (max %zd, "
"requested %zd)\n", fcpdev, fcpcmd->ref, "requested %zd)\n", fcpdev, fcpcmd->xchg_id,
command->data_out_len, ( fcpcmd->offset + len ) ); command->data_out_len, ( fcpcmd->offset + len ) );
return -ERANGE_WRITE_DATA_OVERRUN; return -ERANGE_WRITE_DATA_OVERRUN;
} }
@ -457,8 +456,8 @@ static int fcpcmd_send_wrdata ( struct fcp_command *fcpcmd ) {
/* Allocate I/O buffer */ /* Allocate I/O buffer */
iobuf = xfer_alloc_iob ( &fcpcmd->xchg, len ); iobuf = xfer_alloc_iob ( &fcpcmd->xchg, len );
if ( ! iobuf ) { if ( ! iobuf ) {
DBGC ( fcpdev, "FCP %p ref %02x cannot allocate write data IU " DBGC ( fcpdev, "FCP %p xchg %04x cannot allocate write data "
"for %zd bytes\n", fcpdev, fcpcmd->ref, len ); "IU for %zd bytes\n", fcpdev, fcpcmd->xchg_id, len );
return -ENOMEM; return -ENOMEM;
} }
@ -468,8 +467,8 @@ static int fcpcmd_send_wrdata ( struct fcp_command *fcpcmd ) {
memset ( &meta, 0, sizeof ( meta ) ); memset ( &meta, 0, sizeof ( meta ) );
meta.flags = ( XFER_FL_RESPONSE | XFER_FL_ABS_OFFSET ); meta.flags = ( XFER_FL_RESPONSE | XFER_FL_ABS_OFFSET );
meta.offset = fcpcmd->offset; meta.offset = fcpcmd->offset;
DBGC2 ( fcpdev, "FCP %p ref %02x WRDATA [%08zx,%04zx)\n", DBGC2 ( fcpdev, "FCP %p xchg %04x WRDATA [%08zx,%04zx)\n",
fcpdev, fcpcmd->ref, fcpcmd->offset, fcpdev, fcpcmd->xchg_id, fcpcmd->offset,
( fcpcmd->offset + iob_len ( iobuf ) ) ); ( fcpcmd->offset + iob_len ( iobuf ) ) );
/* Calculate amount of data remaining to be sent within this IU */ /* Calculate amount of data remaining to be sent within this IU */
@ -485,8 +484,8 @@ static int fcpcmd_send_wrdata ( struct fcp_command *fcpcmd ) {
/* Send data IU frame */ /* Send data IU frame */
if ( ( rc = xfer_deliver ( &fcpcmd->xchg, iob_disown ( iobuf ), if ( ( rc = xfer_deliver ( &fcpcmd->xchg, iob_disown ( iobuf ),
&meta ) ) != 0 ) { &meta ) ) != 0 ) {
DBGC ( fcpdev, "FCP %p ref %02x cannot deliver write data IU: " DBGC ( fcpdev, "FCP %p xchg %04x cannot deliver write data "
"%s\n", fcpdev, fcpcmd->ref, strerror ( rc ) ); "IU: %s\n", fcpdev, fcpcmd->xchg_id, strerror ( rc ) );
return rc; return rc;
} }
@ -510,23 +509,23 @@ static int fcpcmd_recv_xfer_rdy ( struct fcp_command *fcpcmd,
/* Sanity checks */ /* Sanity checks */
if ( iob_len ( iobuf ) != sizeof ( *xfer_rdy ) ) { if ( iob_len ( iobuf ) != sizeof ( *xfer_rdy ) ) {
DBGC ( fcpdev, "FCP %p ref %02x received invalid transfer " DBGC ( fcpdev, "FCP %p xchg %04x received invalid transfer "
"ready IU:\n", fcpdev, fcpcmd->ref ); "ready IU:\n", fcpdev, fcpcmd->xchg_id );
DBGC_HDA ( fcpdev, 0, iobuf->data, iob_len ( iobuf ) ); DBGC_HDA ( fcpdev, 0, iobuf->data, iob_len ( iobuf ) );
rc = -EINVAL; rc = -EINVAL;
goto done; goto done;
} }
if ( ntohl ( xfer_rdy->offset ) != fcpcmd->offset ) { if ( ntohl ( xfer_rdy->offset ) != fcpcmd->offset ) {
/* We do not advertise out-of-order delivery */ /* We do not advertise out-of-order delivery */
DBGC ( fcpdev, "FCP %p ref %02x cannot support out-of-order " DBGC ( fcpdev, "FCP %p xchg %04x cannot support out-of-order "
"delivery (expected %zd, requested %d)\n", "delivery (expected %zd, requested %d)\n",
fcpdev, fcpcmd->ref, fcpcmd->offset, fcpdev, fcpcmd->xchg_id, fcpcmd->offset,
ntohl ( xfer_rdy->offset ) ); ntohl ( xfer_rdy->offset ) );
rc = -EINVAL; rc = -EINVAL;
goto done; goto done;
} }
DBGC2 ( fcpdev, "FCP %p ref %02x XFER_RDY [%08x,%08x)\n", DBGC2 ( fcpdev, "FCP %p xchg %04x XFER_RDY [%08x,%08x)\n",
fcpdev, fcpcmd->ref, ntohl ( xfer_rdy->offset ), fcpdev, fcpcmd->xchg_id, ntohl ( xfer_rdy->offset ),
( ntohl ( xfer_rdy->offset ) + ntohl ( xfer_rdy->len ) ) ); ( ntohl ( xfer_rdy->offset ) + ntohl ( xfer_rdy->len ) ) );
/* Start sending requested data */ /* Start sending requested data */
@ -562,28 +561,28 @@ static int fcpcmd_recv_rsp ( struct fcp_command *fcpcmd,
( iob_len ( iobuf ) < ( sizeof ( *rsp ) + ( iob_len ( iobuf ) < ( sizeof ( *rsp ) +
fcp_rsp_response_data_len ( rsp ) + fcp_rsp_response_data_len ( rsp ) +
fcp_rsp_sense_data_len ( rsp ) ) ) ) { fcp_rsp_sense_data_len ( rsp ) ) ) ) {
DBGC ( fcpdev, "FCP %p ref %02x received invalid response " DBGC ( fcpdev, "FCP %p xchg %04x received invalid response "
"IU:\n", fcpdev, fcpcmd->ref ); "IU:\n", fcpdev, fcpcmd->xchg_id );
DBGC_HDA ( fcpdev, 0, iobuf->data, iob_len ( iobuf ) ); DBGC_HDA ( fcpdev, 0, iobuf->data, iob_len ( iobuf ) );
rc = -EINVAL; rc = -EINVAL;
goto done; goto done;
} }
DBGC2 ( fcpdev, "FCP %p ref %02x RSP stat %02x resid %08x flags %02x" DBGC2 ( fcpdev, "FCP %p xchg %04x RSP stat %02x resid %08x flags %02x"
"%s%s%s%s\n", fcpdev, fcpcmd->ref, rsp->status, "%s%s%s%s\n", fcpdev, fcpcmd->xchg_id, rsp->status,
ntohl ( rsp->residual ), rsp->flags, ntohl ( rsp->residual ), rsp->flags,
( ( rsp->flags & FCP_RSP_RESPONSE_LEN_VALID ) ? " resp" : "" ), ( ( rsp->flags & FCP_RSP_RESPONSE_LEN_VALID ) ? " resp" : "" ),
( ( rsp->flags & FCP_RSP_SENSE_LEN_VALID ) ? " sense" : "" ), ( ( rsp->flags & FCP_RSP_SENSE_LEN_VALID ) ? " sense" : "" ),
( ( rsp->flags & FCP_RSP_RESIDUAL_OVERRUN ) ? " over" : "" ), ( ( rsp->flags & FCP_RSP_RESIDUAL_OVERRUN ) ? " over" : "" ),
( ( rsp->flags & FCP_RSP_RESIDUAL_UNDERRUN ) ? " under" : "" )); ( ( rsp->flags & FCP_RSP_RESIDUAL_UNDERRUN ) ? " under" : "" ));
if ( fcp_rsp_response_data ( rsp ) ) { if ( fcp_rsp_response_data ( rsp ) ) {
DBGC2 ( fcpdev, "FCP %p ref %02x response data:\n", DBGC2 ( fcpdev, "FCP %p xchg %04x response data:\n",
fcpdev, fcpcmd->ref ); fcpdev, fcpcmd->xchg_id );
DBGC2_HDA ( fcpdev, 0, fcp_rsp_response_data ( rsp ), DBGC2_HDA ( fcpdev, 0, fcp_rsp_response_data ( rsp ),
fcp_rsp_response_data_len ( rsp ) ); fcp_rsp_response_data_len ( rsp ) );
} }
if ( fcp_rsp_sense_data ( rsp ) ) { if ( fcp_rsp_sense_data ( rsp ) ) {
DBGC2 ( fcpdev, "FCP %p ref %02x sense data:\n", DBGC2 ( fcpdev, "FCP %p xchg %04x sense data:\n",
fcpdev, fcpcmd->ref ); fcpdev, fcpcmd->xchg_id );
DBGC2_HDA ( fcpdev, 0, fcp_rsp_sense_data ( rsp ), DBGC2_HDA ( fcpdev, 0, fcp_rsp_sense_data ( rsp ),
fcp_rsp_sense_data_len ( rsp ) ); fcp_rsp_sense_data_len ( rsp ) );
} }
@ -592,8 +591,8 @@ static int fcpcmd_recv_rsp ( struct fcp_command *fcpcmd,
if ( ( rsp->status == 0 ) && if ( ( rsp->status == 0 ) &&
( fcpcmd->offset != ( command->data_in_len + ( fcpcmd->offset != ( command->data_in_len +
command->data_out_len ) ) ) { command->data_out_len ) ) ) {
DBGC ( fcpdev, "FCP %p ref %02x data underrun (expected %zd, " DBGC ( fcpdev, "FCP %p xchg %04x data underrun (expected %zd, "
"got %zd)\n", fcpdev, fcpcmd->ref, "got %zd)\n", fcpdev, fcpcmd->xchg_id,
( command->data_in_len + command->data_out_len ), ( command->data_in_len + command->data_out_len ),
fcpcmd->offset ); fcpcmd->offset );
rc = -ERANGE_DATA_UNDERRUN; rc = -ERANGE_DATA_UNDERRUN;
@ -642,8 +641,8 @@ static int fcpcmd_recv_unknown ( struct fcp_command *fcpcmd,
struct xfer_metadata *meta __unused ) { struct xfer_metadata *meta __unused ) {
struct fcp_device *fcpdev = fcpcmd->fcpdev; struct fcp_device *fcpdev = fcpcmd->fcpdev;
DBGC ( fcpdev, "FCP %p ref %02x received unknown IU:\n", DBGC ( fcpdev, "FCP %p xchg %04x received unknown IU:\n",
fcpdev, fcpcmd->ref ); fcpdev, fcpcmd->xchg_id );
DBGC_HDA ( fcpdev, 0, iobuf->data, iob_len ( iobuf ) ); DBGC_HDA ( fcpdev, 0, iobuf->data, iob_len ( iobuf ) );
free_iob ( iobuf ); free_iob ( iobuf );
return -EINVAL; return -EINVAL;
@ -738,8 +737,8 @@ static int fcpdev_scsi_command ( struct fcp_device *fcpdev,
struct interface *parent, struct interface *parent,
struct scsi_cmd *command ) { struct scsi_cmd *command ) {
struct fcp_prli_service_parameters *param = fcpdev->ulp->param; struct fcp_prli_service_parameters *param = fcpdev->ulp->param;
static uint8_t ref = 0;
struct fcp_command *fcpcmd; struct fcp_command *fcpcmd;
int xchg_id;
int rc; int rc;
/* Check link */ /* Check link */
@ -772,16 +771,18 @@ static int fcpdev_scsi_command ( struct fcp_device *fcpdev,
fcpcmd->fcpdev = fcpdev_get ( fcpdev ); fcpcmd->fcpdev = fcpdev_get ( fcpdev );
list_add ( &fcpcmd->list, &fcpdev->fcpcmds ); list_add ( &fcpcmd->list, &fcpdev->fcpcmds );
memcpy ( &fcpcmd->command, command, sizeof ( fcpcmd->command ) ); memcpy ( &fcpcmd->command, command, sizeof ( fcpcmd->command ) );
fcpcmd->ref = ref++; /* Not used for demultiplexing, only for debug */
/* Create new exchange */ /* Create new exchange */
if ( ( rc = fc_xchg_originate ( &fcpcmd->xchg, fcpdev->ulp->peer->port, if ( ( xchg_id = fc_xchg_originate ( &fcpcmd->xchg,
&fcpdev->ulp->peer->port_id, fcpdev->ulp->peer->port,
FC_TYPE_FCP ) ) != 0 ) { &fcpdev->ulp->peer->port_id,
DBGC ( fcpdev, "FCP %p ref %02x could not create exchange: " FC_TYPE_FCP ) ) < 0 ) {
"%s\n", fcpdev, fcpcmd->ref, strerror ( rc ) ); rc = xchg_id;
DBGC ( fcpdev, "FCP %p xchg %04x could not create exchange: "
"%s\n", fcpdev, fcpcmd->xchg_id, strerror ( rc ) );
goto err_xchg_originate; goto err_xchg_originate;
} }
fcpcmd->xchg_id = xchg_id;
/* Start sending command IU */ /* Start sending command IU */
fcpcmd_start_send ( fcpcmd, fcpcmd_send_cmnd ); fcpcmd_start_send ( fcpcmd, fcpcmd_send_cmnd );
@ -789,7 +790,7 @@ static int fcpdev_scsi_command ( struct fcp_device *fcpdev,
/* Attach to parent interface, mortalise self, and return */ /* Attach to parent interface, mortalise self, and return */
intf_plug_plug ( &fcpcmd->scsi, parent ); intf_plug_plug ( &fcpcmd->scsi, parent );
ref_put ( &fcpcmd->refcnt ); ref_put ( &fcpcmd->refcnt );
return ( FCP_TAG_MAGIC | fcpcmd->ref ); return ( FCP_TAG_MAGIC | fcpcmd->xchg_id );
err_xchg_originate: err_xchg_originate:
fcpcmd_close ( fcpcmd, rc ); fcpcmd_close ( fcpcmd, rc );