]> www.pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - drivers/ata/libata-core.c
libata: fix Seagate NCQ+FLUSH blacklist
[linux-2.6-omap-h63xx.git] / drivers / ata / libata-core.c
index 82af7011f2ddd137e2a601ae95c704a4219ada9e..bc6695e3c8482927e5b6de7ae4017c9884bea4a8 100644 (file)
@@ -612,7 +612,7 @@ u64 ata_tf_read_block(struct ata_taskfile *tf, struct ata_device *dev)
                if (tf->flags & ATA_TFLAG_LBA48) {
                        block |= (u64)tf->hob_lbah << 40;
                        block |= (u64)tf->hob_lbam << 32;
-                       block |= tf->hob_lbal << 24;
+                       block |= (u64)tf->hob_lbal << 24;
                } else
                        block |= (tf->device & 0xf) << 24;
 
@@ -1712,6 +1712,8 @@ unsigned ata_exec_internal_sg(struct ata_device *dev,
        else
                tag = 0;
 
+       if (test_and_set_bit(tag, &ap->qc_allocated))
+               BUG();
        qc = __ata_qc_from_tag(ap, tag);
 
        qc->tag = tag;
@@ -2490,6 +2492,13 @@ int ata_dev_configure(struct ata_device *dev)
                }
        }
 
+       if ((dev->horkage & ATA_HORKAGE_FIRMWARE_WARN) && print_info) {
+               ata_dev_printk(dev, KERN_WARNING, "WARNING: device requires "
+                              "firmware update to be fully functional.\n");
+               ata_dev_printk(dev, KERN_WARNING, "         contact the vendor "
+                              "or visit http://ata.wiki.kernel.org.\n");
+       }
+
        return 0;
 
 err_out_nosup:
@@ -4024,6 +4033,7 @@ static const struct ata_blacklist_entry ata_device_blacklist [] = {
 
        /* Weird ATAPI devices */
        { "TORiSAN DVD-ROM DRD-N216", NULL,     ATA_HORKAGE_MAX_SEC_128 },
+       { "QUANTUM DAT    DAT72-000", NULL,     ATA_HORKAGE_ATAPI_MOD16_DMA },
 
        /* Devices we expect to fail diagnostics */
 
@@ -4039,6 +4049,73 @@ static const struct ata_blacklist_entry ata_device_blacklist [] = {
        { "ST380817AS",         "3.42",         ATA_HORKAGE_NONCQ },
        { "ST3160023AS",        "3.42",         ATA_HORKAGE_NONCQ },
 
+       /* Seagate NCQ + FLUSH CACHE firmware bug */
+       { "ST31500341AS",       "SD15",         ATA_HORKAGE_NONCQ |
+                                               ATA_HORKAGE_FIRMWARE_WARN },
+       { "ST31500341AS",       "SD16",         ATA_HORKAGE_NONCQ |
+                                               ATA_HORKAGE_FIRMWARE_WARN },
+       { "ST31500341AS",       "SD17",         ATA_HORKAGE_NONCQ |
+                                               ATA_HORKAGE_FIRMWARE_WARN },
+       { "ST31500341AS",       "SD18",         ATA_HORKAGE_NONCQ |
+                                               ATA_HORKAGE_FIRMWARE_WARN },
+       { "ST31500341AS",       "SD19",         ATA_HORKAGE_NONCQ |
+                                               ATA_HORKAGE_FIRMWARE_WARN },
+
+       { "ST31000333AS",       "SD15",         ATA_HORKAGE_NONCQ |
+                                               ATA_HORKAGE_FIRMWARE_WARN },
+       { "ST31000333AS",       "SD16",         ATA_HORKAGE_NONCQ |
+                                               ATA_HORKAGE_FIRMWARE_WARN },
+       { "ST31000333AS",       "SD17",         ATA_HORKAGE_NONCQ |
+                                               ATA_HORKAGE_FIRMWARE_WARN },
+       { "ST31000333AS",       "SD18",         ATA_HORKAGE_NONCQ |
+                                               ATA_HORKAGE_FIRMWARE_WARN },
+       { "ST31000333AS",       "SD19",         ATA_HORKAGE_NONCQ |
+                                               ATA_HORKAGE_FIRMWARE_WARN },
+
+       { "ST3640623AS",        "SD15",         ATA_HORKAGE_NONCQ |
+                                               ATA_HORKAGE_FIRMWARE_WARN },
+       { "ST3640623AS",        "SD16",         ATA_HORKAGE_NONCQ |
+                                               ATA_HORKAGE_FIRMWARE_WARN },
+       { "ST3640623AS",        "SD17",         ATA_HORKAGE_NONCQ |
+                                               ATA_HORKAGE_FIRMWARE_WARN },
+       { "ST3640623AS",        "SD18",         ATA_HORKAGE_NONCQ |
+                                               ATA_HORKAGE_FIRMWARE_WARN },
+       { "ST3640623AS",        "SD19",         ATA_HORKAGE_NONCQ |
+                                               ATA_HORKAGE_FIRMWARE_WARN },
+
+       { "ST3640323AS",        "SD15",         ATA_HORKAGE_NONCQ |
+                                               ATA_HORKAGE_FIRMWARE_WARN },
+       { "ST3640323AS",        "SD16",         ATA_HORKAGE_NONCQ |
+                                               ATA_HORKAGE_FIRMWARE_WARN },
+       { "ST3640323AS",        "SD17",         ATA_HORKAGE_NONCQ |
+                                               ATA_HORKAGE_FIRMWARE_WARN },
+       { "ST3640323AS",        "SD18",         ATA_HORKAGE_NONCQ |
+                                               ATA_HORKAGE_FIRMWARE_WARN },
+       { "ST3640323AS",        "SD19",         ATA_HORKAGE_NONCQ |
+                                               ATA_HORKAGE_FIRMWARE_WARN },
+
+       { "ST3320813AS",        "SD15",         ATA_HORKAGE_NONCQ |
+                                               ATA_HORKAGE_FIRMWARE_WARN },
+       { "ST3320813AS",        "SD16",         ATA_HORKAGE_NONCQ |
+                                               ATA_HORKAGE_FIRMWARE_WARN },
+       { "ST3320813AS",        "SD17",         ATA_HORKAGE_NONCQ |
+                                               ATA_HORKAGE_FIRMWARE_WARN },
+       { "ST3320813AS",        "SD18",         ATA_HORKAGE_NONCQ |
+                                               ATA_HORKAGE_FIRMWARE_WARN },
+       { "ST3320813AS",        "SD19",         ATA_HORKAGE_NONCQ |
+                                               ATA_HORKAGE_FIRMWARE_WARN },
+
+       { "ST3320613AS",        "SD15",         ATA_HORKAGE_NONCQ |
+                                               ATA_HORKAGE_FIRMWARE_WARN },
+       { "ST3320613AS",        "SD16",         ATA_HORKAGE_NONCQ |
+                                               ATA_HORKAGE_FIRMWARE_WARN },
+       { "ST3320613AS",        "SD17",         ATA_HORKAGE_NONCQ |
+                                               ATA_HORKAGE_FIRMWARE_WARN },
+       { "ST3320613AS",        "SD18",         ATA_HORKAGE_NONCQ |
+                                               ATA_HORKAGE_FIRMWARE_WARN },
+       { "ST3320613AS",        "SD19",         ATA_HORKAGE_NONCQ |
+                                               ATA_HORKAGE_FIRMWARE_WARN },
+
        /* Blacklist entries taken from Silicon Image 3124/3132
           Windows driver .inf file - also several Linux problem reports */
        { "HTS541060G9SA00",    "MB3OC60D",     ATA_HORKAGE_NONCQ, },
@@ -4444,7 +4521,8 @@ int atapi_check_dma(struct ata_queued_cmd *qc)
        /* Don't allow DMA if it isn't multiple of 16 bytes.  Quite a
         * few ATAPI devices choke on such DMA requests.
         */
-       if (unlikely(qc->nbytes & 15))
+       if (!(qc->dev->horkage & ATA_HORKAGE_ATAPI_MOD16_DMA) &&
+           unlikely(qc->nbytes & 15))
                return 1;
 
        if (ap->ops->check_atapi_dma)
@@ -4560,6 +4638,37 @@ void swap_buf_le16(u16 *buf, unsigned int buf_words)
 #endif /* __BIG_ENDIAN */
 }
 
+/**
+ *     ata_qc_new - Request an available ATA command, for queueing
+ *     @ap: Port associated with device @dev
+ *     @dev: Device from whom we request an available command structure
+ *
+ *     LOCKING:
+ *     None.
+ */
+
+static struct ata_queued_cmd *ata_qc_new(struct ata_port *ap)
+{
+       struct ata_queued_cmd *qc = NULL;
+       unsigned int i;
+
+       /* no command while frozen */
+       if (unlikely(ap->pflags & ATA_PFLAG_FROZEN))
+               return NULL;
+
+       /* the last tag is reserved for internal command. */
+       for (i = 0; i < ATA_MAX_QUEUE - 1; i++)
+               if (!test_and_set_bit(i, &ap->qc_allocated)) {
+                       qc = __ata_qc_from_tag(ap, i);
+                       break;
+               }
+
+       if (qc)
+               qc->tag = i;
+
+       return qc;
+}
+
 /**
  *     ata_qc_new_init - Request an available ATA command, and initialize it
  *     @dev: Device from whom we request an available command structure
@@ -4569,20 +4678,16 @@ void swap_buf_le16(u16 *buf, unsigned int buf_words)
  *     None.
  */
 
-struct ata_queued_cmd *ata_qc_new_init(struct ata_device *dev, int tag)
+struct ata_queued_cmd *ata_qc_new_init(struct ata_device *dev)
 {
        struct ata_port *ap = dev->link->ap;
        struct ata_queued_cmd *qc;
 
-       if (unlikely(ap->pflags & ATA_PFLAG_FROZEN))
-               return NULL;
-
-       qc = __ata_qc_from_tag(ap, tag);
+       qc = ata_qc_new(ap);
        if (qc) {
                qc->scsicmd = NULL;
                qc->ap = ap;
                qc->dev = dev;
-               qc->tag = tag;
 
                ata_qc_reinit(qc);
        }
@@ -4590,6 +4695,31 @@ struct ata_queued_cmd *ata_qc_new_init(struct ata_device *dev, int tag)
        return qc;
 }
 
+/**
+ *     ata_qc_free - free unused ata_queued_cmd
+ *     @qc: Command to complete
+ *
+ *     Designed to free unused ata_queued_cmd object
+ *     in case something prevents using it.
+ *
+ *     LOCKING:
+ *     spin_lock_irqsave(host lock)
+ */
+void ata_qc_free(struct ata_queued_cmd *qc)
+{
+       struct ata_port *ap = qc->ap;
+       unsigned int tag;
+
+       WARN_ON(qc == NULL);    /* ata_qc_from_tag _might_ return NULL */
+
+       qc->flags = 0;
+       tag = qc->tag;
+       if (likely(ata_tag_valid(tag))) {
+               qc->tag = ATA_TAG_POISON;
+               clear_bit(tag, &ap->qc_allocated);
+       }
+}
+
 void __ata_qc_complete(struct ata_queued_cmd *qc)
 {
        struct ata_port *ap = qc->ap;
@@ -5934,7 +6064,7 @@ static void ata_port_detach(struct ata_port *ap)
         * to us.  Restore SControl and disable all existing devices.
         */
        __ata_port_for_each_link(link, ap) {
-               sata_scr_write(link, SCR_CONTROL, link->saved_scontrol);
+               sata_scr_write(link, SCR_CONTROL, link->saved_scontrol & 0xff0);
                ata_link_for_each_dev(dev, link)
                        ata_dev_disable(dev);
        }