From 1d8d8ef2c8e6bd951416941a42e3e6302238330a Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Tue, 7 Jul 2009 23:00:11 +0100 Subject: [PATCH] [scsi] Make SCSI command issuing partially asynchronous Move the icky call to step() from iscsi.c to scsi.c; this takes it at least one step further away from where it really doesn't belong. --- src/drivers/block/scsi.c | 18 +++++++++++++++--- src/include/gpxe/iscsi.h | 5 ----- src/include/gpxe/scsi.h | 11 +++++++---- src/net/tcp/iscsi.c | 29 +++++++++++------------------ 4 files changed, 33 insertions(+), 30 deletions(-) diff --git a/src/drivers/block/scsi.c b/src/drivers/block/scsi.c index 5431233f..d6511c97 100644 --- a/src/drivers/block/scsi.c +++ b/src/drivers/block/scsi.c @@ -23,6 +23,7 @@ FILE_LICENCE ( GPL2_OR_LATER ); #include #include #include +#include #include /** @file @@ -57,11 +58,22 @@ static int scsi_command ( struct scsi_device *scsi, /* Clear sense response code before issuing command */ command->sense_response = 0; + /* Flag command as in-progress */ + command->rc = -EINPROGRESS; + /* Issue SCSI command */ if ( ( rc = scsi->command ( scsi, command ) ) != 0 ) { - /* Something went wrong with the issuing mechanism, - * (rather than with the command itself) - */ + /* Something went wrong with the issuing mechanism */ + DBG ( "SCSI %p " SCSI_CDB_FORMAT " err %s\n", + scsi, SCSI_CDB_DATA ( command->cdb ), strerror ( rc ) ); + return rc; + } + + /* Wait for command to complete */ + while ( command->rc == -EINPROGRESS ) + step(); + if ( ( rc = command->rc ) != 0 ) { + /* Something went wrong with the command execution */ DBG ( "SCSI %p " SCSI_CDB_FORMAT " err %s\n", scsi, SCSI_CDB_DATA ( command->cdb ), strerror ( rc ) ); return rc; diff --git a/src/include/gpxe/iscsi.h b/src/include/gpxe/iscsi.h index 9185d624..469911df 100644 --- a/src/include/gpxe/iscsi.h +++ b/src/include/gpxe/iscsi.h @@ -614,11 +614,6 @@ struct iscsi_session { * Set to NULL when command is complete. */ struct scsi_command *command; - /** SCSI command return code - * - * Set to -EINPROGRESS while command is processing. - */ - int rc; /** Instant return code * * Set to a non-zero value if all requests should return diff --git a/src/include/gpxe/scsi.h b/src/include/gpxe/scsi.h index 115fd3fe..fbdde8dc 100644 --- a/src/include/gpxe/scsi.h +++ b/src/include/gpxe/scsi.h @@ -236,6 +236,8 @@ struct scsi_command { uint8_t status; /** SCSI sense response code */ uint8_t sense_response; + /** Command status code */ + int rc; }; /** A SCSI device */ @@ -256,10 +258,11 @@ struct scsi_device { * @ret rc Return status code * * Note that a successful return status code indicates only - * that the SCSI command completed. The caller must check the - * status field in the command structure to see if, for - * example, the device returned CHECK CONDITION or some other - * non-success status code. + * that the SCSI command was issued. The caller must check + * the status field in the command structure to see when the + * command completes and whether, for example, the device + * returned CHECK CONDITION or some other non-success status + * code. */ int ( * command ) ( struct scsi_device *scsi, struct scsi_command *command ); diff --git a/src/net/tcp/iscsi.c b/src/net/tcp/iscsi.c index 943bdefc..0f7b0de5 100644 --- a/src/net/tcp/iscsi.c +++ b/src/net/tcp/iscsi.c @@ -182,9 +182,10 @@ static void iscsi_close_connection ( struct iscsi_session *iscsi, int rc ) { static void iscsi_scsi_done ( struct iscsi_session *iscsi, int rc ) { assert ( iscsi->tx_state == ISCSI_TX_IDLE ); + assert ( iscsi->command != NULL ); + iscsi->command->rc = rc; iscsi->command = NULL; - iscsi->rc = rc; } /**************************************************************************** @@ -1550,32 +1551,24 @@ static int iscsi_command ( struct scsi_device *scsi, container_of ( scsi->backend, struct iscsi_session, refcnt ); int rc; + /* Abort immediately if we have a recorded permanent failure */ + if ( iscsi->instant_rc ) + return iscsi->instant_rc; + /* Record SCSI command */ iscsi->command = command; - /* Abort immediately if we have a recorded permanent failure */ - if ( iscsi->instant_rc ) { - rc = iscsi->instant_rc; - goto done; - } - /* Issue command or open connection as appropriate */ if ( iscsi->status ) { iscsi_start_command ( iscsi ); } else { - if ( ( rc = iscsi_open_connection ( iscsi ) ) != 0 ) - goto done; + if ( ( rc = iscsi_open_connection ( iscsi ) ) != 0 ) { + iscsi->command = NULL; + return rc; + } } - /* Wait for command to complete */ - iscsi->rc = -EINPROGRESS; - while ( iscsi->rc == -EINPROGRESS ) - step(); - rc = iscsi->rc; - - done: - iscsi->command = NULL; - return rc; + return 0; } static int iscsi_detached_command ( struct scsi_device *scsi __unused,