[PATCH] libata CHS: reread device identify info (revise #6)
authorAlbert Lee <albertcc@tw.ibm.com>
Wed, 12 Oct 2005 07:09:42 +0000 (15:09 +0800)
committerJeff Garzik <jgarzik@pobox.com>
Tue, 18 Oct 2005 21:16:14 +0000 (17:16 -0400)
problem:
      id[53-58] might be changed after initializing device CHS settings.

changes:
    - call ata_dev_reread_id() to reread the identify device info,
      after initializing device CHS settings.

Signed-off-by: Albert Lee <albertcc@tw.ibm.com>
============
Signed-off-by: Jeff Garzik <jgarzik@pobox.com>
drivers/scsi/libata-core.c

index 19d3d717faf67d22ad9d007bb77fa1aa73538ae8..175d4646333d88dd512ac7873bbc8cb4e80f9d0b 100644 (file)
@@ -63,6 +63,7 @@
 static unsigned int ata_busy_sleep (struct ata_port *ap,
                                    unsigned long tmout_pat,
                                    unsigned long tmout);
+static void ata_dev_reread_id(struct ata_port *ap, struct ata_device *dev);
 static void ata_dev_init_params(struct ata_port *ap, struct ata_device *dev);
 static void ata_set_mode(struct ata_port *ap);
 static void ata_dev_set_xfermode(struct ata_port *ap, struct ata_device *dev);
@@ -1240,9 +1241,15 @@ retry:
                 * anything else..
                 * Some drives were very specific about that exact sequence.
                 */
-               if (major_version < 4 || (!ata_id_has_lba(dev->id)))
+               if (major_version < 4 || (!ata_id_has_lba(dev->id))) {
                        ata_dev_init_params(ap, dev);
 
+                       /* current CHS translation info (id[53-58]) might be
+                        * changed. reread the identify device info.
+                        */
+                       ata_dev_reread_id(ap, dev);
+               }
+
                if (ata_id_has_lba(dev->id)) {
                        dev->flags |= ATA_DFLAG_LBA;
 
@@ -2150,6 +2157,62 @@ static void ata_dev_set_xfermode(struct ata_port *ap, struct ata_device *dev)
        DPRINTK("EXIT\n");
 }
 
+/**
+ *     ata_dev_reread_id - Reread the device identify device info
+ *     @ap: port where the device is
+ *     @dev: device to reread the identify device info
+ *
+ *     LOCKING:
+ */
+
+static void ata_dev_reread_id(struct ata_port *ap, struct ata_device *dev)
+{
+       DECLARE_COMPLETION(wait);
+       struct ata_queued_cmd *qc;
+       unsigned long flags;
+       int rc;
+
+       qc = ata_qc_new_init(ap, dev);
+       BUG_ON(qc == NULL);
+
+       ata_sg_init_one(qc, dev->id, sizeof(dev->id));
+       qc->dma_dir = DMA_FROM_DEVICE;
+
+       if (dev->class == ATA_DEV_ATA) {
+               qc->tf.command = ATA_CMD_ID_ATA;
+               DPRINTK("do ATA identify\n");
+       } else {
+               qc->tf.command = ATA_CMD_ID_ATAPI;
+               DPRINTK("do ATAPI identify\n");
+       }
+
+       qc->tf.flags |= ATA_TFLAG_DEVICE;
+       qc->tf.protocol = ATA_PROT_PIO;
+       qc->nsect = 1;
+
+       qc->waiting = &wait;
+       qc->complete_fn = ata_qc_complete_noop;
+
+       spin_lock_irqsave(&ap->host_set->lock, flags);
+       rc = ata_qc_issue(qc);
+       spin_unlock_irqrestore(&ap->host_set->lock, flags);
+
+       if (rc)
+               goto err_out;
+
+       wait_for_completion(&wait);
+
+       swap_buf_le16(dev->id, ATA_ID_WORDS);
+
+       ata_dump_id(dev);
+
+       DPRINTK("EXIT\n");
+
+       return;
+err_out:
+       ata_port_disable(ap);
+}
+
 /**
  *     ata_dev_init_params - Issue INIT DEV PARAMS command
  *     @ap: Port associated with device @dev