aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMichael Brown <mcb30@etherboot.org>2009-07-07 23:00:11 +0100
committerMichael Brown <mcb30@etherboot.org>2009-07-17 23:00:09 +0100
commit1d8d8ef2c8e6bd951416941a42e3e6302238330a (patch)
tree521e7ff15194ef417bb99f941fb3f200af349a29
parent51172783e2211bc90017d14bafec5d2eb4080694 (diff)
downloadipxe-1d8d8ef2c8e6bd951416941a42e3e6302238330a.tar.gz
[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.
-rw-r--r--src/drivers/block/scsi.c18
-rw-r--r--src/include/gpxe/iscsi.h5
-rw-r--r--src/include/gpxe/scsi.h11
-rw-r--r--src/net/tcp/iscsi.c29
4 files changed, 33 insertions, 30 deletions
diff --git a/src/drivers/block/scsi.c b/src/drivers/block/scsi.c
index 5431233f9..d6511c97b 100644
--- a/src/drivers/block/scsi.c
+++ b/src/drivers/block/scsi.c
@@ -23,6 +23,7 @@ FILE_LICENCE ( GPL2_OR_LATER );
#include <byteswap.h>
#include <errno.h>
#include <gpxe/blockdev.h>
+#include <gpxe/process.h>
#include <gpxe/scsi.h>
/** @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 9185d6240..469911dfb 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 115fd3fe2..fbdde8dcb 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 943bdefc1..0f7b0de59 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,