[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.
pull/1/head
Michael Brown 2009-07-07 23:00:11 +01:00
parent 51172783e2
commit 1d8d8ef2c8
4 changed files with 33 additions and 30 deletions

View File

@ -23,6 +23,7 @@ FILE_LICENCE ( GPL2_OR_LATER );
#include <byteswap.h> #include <byteswap.h>
#include <errno.h> #include <errno.h>
#include <gpxe/blockdev.h> #include <gpxe/blockdev.h>
#include <gpxe/process.h>
#include <gpxe/scsi.h> #include <gpxe/scsi.h>
/** @file /** @file
@ -57,11 +58,22 @@ static int scsi_command ( struct scsi_device *scsi,
/* Clear sense response code before issuing command */ /* Clear sense response code before issuing command */
command->sense_response = 0; command->sense_response = 0;
/* Flag command as in-progress */
command->rc = -EINPROGRESS;
/* Issue SCSI command */ /* Issue SCSI command */
if ( ( rc = scsi->command ( scsi, command ) ) != 0 ) { if ( ( rc = scsi->command ( scsi, command ) ) != 0 ) {
/* Something went wrong with the issuing mechanism, /* Something went wrong with the issuing mechanism */
* (rather than with the command itself) 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", DBG ( "SCSI %p " SCSI_CDB_FORMAT " err %s\n",
scsi, SCSI_CDB_DATA ( command->cdb ), strerror ( rc ) ); scsi, SCSI_CDB_DATA ( command->cdb ), strerror ( rc ) );
return rc; return rc;

View File

@ -614,11 +614,6 @@ struct iscsi_session {
* Set to NULL when command is complete. * Set to NULL when command is complete.
*/ */
struct scsi_command *command; struct scsi_command *command;
/** SCSI command return code
*
* Set to -EINPROGRESS while command is processing.
*/
int rc;
/** Instant return code /** Instant return code
* *
* Set to a non-zero value if all requests should return * Set to a non-zero value if all requests should return

View File

@ -236,6 +236,8 @@ struct scsi_command {
uint8_t status; uint8_t status;
/** SCSI sense response code */ /** SCSI sense response code */
uint8_t sense_response; uint8_t sense_response;
/** Command status code */
int rc;
}; };
/** A SCSI device */ /** A SCSI device */
@ -256,10 +258,11 @@ struct scsi_device {
* @ret rc Return status code * @ret rc Return status code
* *
* Note that a successful return status code indicates only * Note that a successful return status code indicates only
* that the SCSI command completed. The caller must check the * that the SCSI command was issued. The caller must check
* status field in the command structure to see if, for * the status field in the command structure to see when the
* example, the device returned CHECK CONDITION or some other * command completes and whether, for example, the device
* non-success status code. * returned CHECK CONDITION or some other non-success status
* code.
*/ */
int ( * command ) ( struct scsi_device *scsi, int ( * command ) ( struct scsi_device *scsi,
struct scsi_command *command ); struct scsi_command *command );

View File

@ -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 ) { static void iscsi_scsi_done ( struct iscsi_session *iscsi, int rc ) {
assert ( iscsi->tx_state == ISCSI_TX_IDLE ); assert ( iscsi->tx_state == ISCSI_TX_IDLE );
assert ( iscsi->command != NULL );
iscsi->command->rc = rc;
iscsi->command = NULL; 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 ); container_of ( scsi->backend, struct iscsi_session, refcnt );
int rc; int rc;
/* Abort immediately if we have a recorded permanent failure */
if ( iscsi->instant_rc )
return iscsi->instant_rc;
/* Record SCSI command */ /* Record SCSI command */
iscsi->command = 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 */ /* Issue command or open connection as appropriate */
if ( iscsi->status ) { if ( iscsi->status ) {
iscsi_start_command ( iscsi ); iscsi_start_command ( iscsi );
} else { } else {
if ( ( rc = iscsi_open_connection ( iscsi ) ) != 0 ) if ( ( rc = iscsi_open_connection ( iscsi ) ) != 0 ) {
goto done; iscsi->command = NULL;
return rc;
}
} }
/* Wait for command to complete */ return 0;
iscsi->rc = -EINPROGRESS;
while ( iscsi->rc == -EINPROGRESS )
step();
rc = iscsi->rc;
done:
iscsi->command = NULL;
return rc;
} }
static int iscsi_detached_command ( struct scsi_device *scsi __unused, static int iscsi_detached_command ( struct scsi_device *scsi __unused,