summaryrefslogtreecommitdiffstats
path: root/src/drivers/block
diff options
context:
space:
mode:
authorMichael Brown2009-01-30 14:32:53 +0100
committerMichael Brown2009-01-30 14:32:53 +0100
commitb111bdfb000b22a41961ae9d3d2920a9c43d84f8 (patch)
treeeac14eac2f1201e4a1874fede5c0efebf014801e /src/drivers/block
parent[ui] Allow Ctrl-C to cancel wait for net device link-up (diff)
downloadipxe-b111bdfb000b22a41961ae9d3d2920a9c43d84f8.tar.gz
ipxe-b111bdfb000b22a41961ae9d3d2920a9c43d84f8.tar.xz
ipxe-b111bdfb000b22a41961ae9d3d2920a9c43d84f8.zip
[scsi] Cope with targets that send multiple CHECK CONDITIONS at power-on
Some targets send a spurious CHECK CONDITION message in response to the first SCSI command. We issue (and ignore the status of) an arbitary harmless SCSI command (a READ CAPACITY (10)) in order to draw out this response. The Solaris Comstar target seems to send more than one spurious CHECK CONDITION response. Attempt up to SCSI_MAX_DUMMY_READ_CAP dummy READ CAPACITY (10) commands before assuming that error responses are meaningful. Problem reported by Kristof Van Doorsselaere <kvandoor@aserver.com> and Shiva Shankar <802.11e@gmail.com>.
Diffstat (limited to 'src/drivers/block')
-rw-r--r--src/drivers/block/scsi.c24
1 files changed, 19 insertions, 5 deletions
diff --git a/src/drivers/block/scsi.c b/src/drivers/block/scsi.c
index 9ff47f89..71d22040 100644
--- a/src/drivers/block/scsi.c
+++ b/src/drivers/block/scsi.c
@@ -29,6 +29,13 @@
*
*/
+/** Maximum number of dummy "read capacity (10)" operations
+ *
+ * These are issued at connection setup to draw out various useless
+ * power-on messages.
+ */
+#define SCSI_MAX_DUMMY_READ_CAP 10
+
static inline __attribute__ (( always_inline )) struct scsi_device *
block_to_scsi ( struct block_device *blockdev ) {
return container_of ( blockdev, struct scsi_device, blockdev );
@@ -250,14 +257,21 @@ static struct block_device_operations scsi_operations_10 = {
* CAPACITY call to determine the block size and total device size.
*/
int init_scsidev ( struct scsi_device *scsi ) {
+ unsigned int i;
int rc;
- /* Issue a theoretically extraneous READ CAPACITY (10)
- * command, solely in order to draw out the "CHECK CONDITION
- * (power-on occurred)" that some dumb targets insist on
- * sending as an error at start of day.
+ /* Issue some theoretically extraneous READ CAPACITY (10)
+ * commands, solely in order to draw out the "CHECK CONDITION
+ * (power-on occurred)", "CHECK CONDITION (reported LUNs data
+ * has changed)" etc. that some dumb targets insist on sending
+ * as an error at start of day. The precise command that we
+ * use is unimportant; we just need to provide the target with
+ * an opportunity to send its responses.
*/
- scsi_read_capacity_10 ( &scsi->blockdev );
+ for ( i = 0 ; i < SCSI_MAX_DUMMY_READ_CAP ; i++ ) {
+ if ( ( rc = scsi_read_capacity_10 ( &scsi->blockdev ) ) == 0 )
+ break;
+ }
/* Try READ CAPACITY (10), which is a mandatory command, first. */
scsi->blockdev.op = &scsi_operations_10;