[scsi] Cope with targets that send multiple CHECK CONDITIONS at power-on
authorMichael Brown <mcb30@etherboot.org>
Fri, 30 Jan 2009 13:32:53 +0000 (13:32 +0000)
committerMichael Brown <mcb30@etherboot.org>
Fri, 30 Jan 2009 13:32:53 +0000 (13:32 +0000)
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>.

src/drivers/block/scsi.c

index 9ff47f8..71d2204 100644 (file)
  *
  */
 
+/** 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;