[scsi] Make SCSI command issuing partially asynchronous
authorMichael Brown <mcb30@etherboot.org>
Tue, 7 Jul 2009 22:00:11 +0000 (23:00 +0100)
committerMichael Brown <mcb30@etherboot.org>
Fri, 17 Jul 2009 22:00:09 +0000 (23:00 +0100)
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
src/include/gpxe/iscsi.h
src/include/gpxe/scsi.h
src/net/tcp/iscsi.c

index 5431233..d6511c9 100644 (file)
@@ -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;
index 9185d62..469911d 100644 (file)
@@ -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
index 115fd3f..fbdde8d 100644 (file)
@@ -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 );
index 943bdef..0f7b0de 100644 (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 ) {
 
        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,