mirror of https://github.com/ipxe/ipxe.git
[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
parent
51172783e2
commit
1d8d8ef2c8
|
@ -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;
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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 );
|
||||||
|
|
|
@ -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,
|
||||||
|
|
Loading…
Reference in New Issue