ahci: Add Marvell 88se91a2 device id
[pandora-kernel.git] / drivers / ata / libata-core.c
index c04ad68..4e9beff 100644 (file)
@@ -1598,6 +1598,12 @@ unsigned ata_exec_internal_sg(struct ata_device *dev,
        qc->tf = *tf;
        if (cdb)
                memcpy(qc->cdb, cdb, ATAPI_CDB_LEN);
+
+       /* some SATA bridges need us to indicate data xfer direction */
+       if (tf->protocol == ATAPI_PROT_DMA && (dev->flags & ATA_DFLAG_DMADIR) &&
+           dma_dir == DMA_FROM_DEVICE)
+               qc->tf.feature |= ATAPI_DMADIR;
+
        qc->flags |= ATA_QCFLAG_RESULT_TF;
        qc->dma_dir = dma_dir;
        if (dma_dir != DMA_NONE) {
@@ -2182,6 +2188,16 @@ int ata_dev_configure(struct ata_device *dev)
        if (rc)
                return rc;
 
+       /* some WD SATA-1 drives have issues with LPM, turn on NOLPM for them */
+       if ((dev->horkage & ATA_HORKAGE_WD_BROKEN_LPM) &&
+           (id[76] & 0xe) == 0x2)
+               dev->horkage |= ATA_HORKAGE_NOLPM;
+
+       if (dev->horkage & ATA_HORKAGE_NOLPM) {
+               ata_dev_warn(dev, "LPM support broken, forcing max_power\n");
+               dev->link->ap->target_lpm_policy = ATA_LPM_MAX_POWER;
+       }
+
        /* let ACPI work its magic */
        rc = ata_acpi_on_devcfg(dev);
        if (rc)
@@ -2401,6 +2417,9 @@ int ata_dev_configure(struct ata_device *dev)
                dev->max_sectors = min_t(unsigned int, ATA_MAX_SECTORS_128,
                                         dev->max_sectors);
 
+       if (dev->horkage & ATA_HORKAGE_MAX_SEC_LBA48)
+               dev->max_sectors = ATA_MAX_SECTORS_LBA48;
+
        if (ap->ops->dev_config)
                ap->ops->dev_config(dev);
 
@@ -2529,6 +2548,7 @@ int ata_bus_probe(struct ata_port *ap)
                 * bus as we may be talking too fast.
                 */
                dev->pio_mode = XFER_PIO_0;
+               dev->dma_mode = 0xff;
 
                /* If the controller has a pio mode setup function
                 * then use it to set the chipset to rights. Don't
@@ -4056,6 +4076,8 @@ 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 },
+       { "Slimtype DVD A  DS8A8SH", NULL,      ATA_HORKAGE_MAX_SEC_LBA48 },
+       { "Slimtype DVD A  DS8A9SH", NULL,      ATA_HORKAGE_MAX_SEC_LBA48 },
 
        /* Devices we expect to fail diagnostics */
 
@@ -4085,6 +4107,11 @@ static const struct ata_blacklist_entry ata_device_blacklist [] = {
        { "ST3320[68]13AS",     "SD1[5-9]",     ATA_HORKAGE_NONCQ |
                                                ATA_HORKAGE_FIRMWARE_WARN },
 
+       /* drives which fail FPDMA_AA activation (some may freeze afterwards) */
+       { "ST1000LM024 HN-M101MBB", "2AR10001", ATA_HORKAGE_BROKEN_FPDMA_AA },
+       { "ST1000LM024 HN-M101MBB", "2BA30001", ATA_HORKAGE_BROKEN_FPDMA_AA },
+       { "VB0250EAVER",        "HPG7",         ATA_HORKAGE_BROKEN_FPDMA_AA },
+
        /* Blacklist entries taken from Silicon Image 3124/3132
           Windows driver .inf file - also several Linux problem reports */
        { "HTS541060G9SA00",    "MB3OC60D",     ATA_HORKAGE_NONCQ, },
@@ -4118,6 +4145,7 @@ static const struct ata_blacklist_entry ata_device_blacklist [] = {
 
        /* Devices which aren't very happy with higher link speeds */
        { "WD My Book",                 NULL,   ATA_HORKAGE_1_5_GBPS, },
+       { "Seagate FreeAgent GoFlex",   NULL,   ATA_HORKAGE_1_5_GBPS, },
 
        /*
         * Devices which choke on SETXFER.  Applies only if both the
@@ -4127,6 +4155,26 @@ static const struct ata_blacklist_entry ata_device_blacklist [] = {
        { "PIONEER DVD-RW  DVR-212D",   NULL,   ATA_HORKAGE_NOSETXFER },
        { "PIONEER DVD-RW  DVR-216D",   NULL,   ATA_HORKAGE_NOSETXFER },
 
+       /* devices that don't properly handle TRIM commands */
+       { "SuperSSpeed S238*",          NULL,   ATA_HORKAGE_NOTRIM, },
+
+       /*
+        * Some WD SATA-I drives spin up and down erratically when the link
+        * is put into the slumber mode.  We don't have full list of the
+        * affected devices.  Disable LPM if the device matches one of the
+        * known prefixes and is SATA-1.  As a side effect LPM partial is
+        * lost too.
+        *
+        * https://bugzilla.kernel.org/show_bug.cgi?id=57211
+        */
+       { "WDC WD800JD-*",              NULL,   ATA_HORKAGE_WD_BROKEN_LPM },
+       { "WDC WD1200JD-*",             NULL,   ATA_HORKAGE_WD_BROKEN_LPM },
+       { "WDC WD1600JD-*",             NULL,   ATA_HORKAGE_WD_BROKEN_LPM },
+       { "WDC WD2000JD-*",             NULL,   ATA_HORKAGE_WD_BROKEN_LPM },
+       { "WDC WD2500JD-*",             NULL,   ATA_HORKAGE_WD_BROKEN_LPM },
+       { "WDC WD3000JD-*",             NULL,   ATA_HORKAGE_WD_BROKEN_LPM },
+       { "WDC WD3200JD-*",             NULL,   ATA_HORKAGE_WD_BROKEN_LPM },
+
        /* End Marker */
        { }
 };
@@ -4414,7 +4462,8 @@ static unsigned int ata_dev_set_xfermode(struct ata_device *dev)
        else /* In the ancient relic department - skip all of this */
                return 0;
 
-       err_mask = ata_exec_internal(dev, &tf, NULL, DMA_NONE, NULL, 0, 0);
+       /* On some disks, this command causes spin-up, so we need longer timeout */
+       err_mask = ata_exec_internal(dev, &tf, NULL, DMA_NONE, NULL, 0, 15000);
 
        DPRINTK("EXIT, err_mask=%x\n", err_mask);
        return err_mask;
@@ -4667,6 +4716,10 @@ void swap_buf_le16(u16 *buf, unsigned int buf_words)
  *     ata_qc_new - Request an available ATA command, for queueing
  *     @ap: target port
  *
+ *     Some ATA host controllers may implement a queue depth which is less
+ *     than ATA_MAX_QUEUE. So we shouldn't allocate a tag which is beyond
+ *     the hardware limitation.
+ *
  *     LOCKING:
  *     None.
  */
@@ -4674,21 +4727,30 @@ void swap_buf_le16(u16 *buf, unsigned int buf_words)
 static struct ata_queued_cmd *ata_qc_new(struct ata_port *ap)
 {
        struct ata_queued_cmd *qc = NULL;
-       unsigned int i;
+       unsigned int max_queue = ap->host->n_tags;
+       unsigned int i, tag;
 
        /* 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);
+       for (i = 0, tag = ap->last_tag + 1; i < max_queue; i++, tag++) {
+               if (ap->flags & ATA_FLAG_LOWTAG)
+                       tag = i;
+               else
+                       tag = tag < max_queue ? tag : 0;
+
+               /* the last tag is reserved for internal command. */
+               if (tag == ATA_TAG_INTERNAL)
+                       continue;
+
+               if (!test_and_set_bit(tag, &ap->qc_allocated)) {
+                       qc = __ata_qc_from_tag(ap, tag);
+                       qc->tag = tag;
+                       ap->last_tag = tag;
                        break;
                }
-
-       if (qc)
-               qc->tag = i;
+       }
 
        return qc;
 }
@@ -5869,6 +5931,7 @@ void ata_host_init(struct ata_host *host, struct device *dev,
 {
        spin_lock_init(&host->lock);
        mutex_init(&host->eh_mutex);
+       host->n_tags = ATA_MAX_QUEUE - 1;
        host->dev = dev;
        host->flags = flags;
        host->ops = ops;
@@ -5949,6 +6012,8 @@ int ata_host_register(struct ata_host *host, struct scsi_host_template *sht)
 {
        int i, rc;
 
+       host->n_tags = clamp(sht->can_queue, 1, ATA_MAX_QUEUE - 1);
+
        /* host must have been started */
        if (!(host->flags & ATA_HOST_STARTED)) {
                dev_err(host->dev, "BUG: trying to register unstarted host\n");
@@ -6315,6 +6380,7 @@ static int __init ata_parse_force_one(char **cur,
                { "nohrst",     .lflags         = ATA_LFLAG_NO_HRST },
                { "nosrst",     .lflags         = ATA_LFLAG_NO_SRST },
                { "norst",      .lflags         = ATA_LFLAG_NO_HRST | ATA_LFLAG_NO_SRST },
+               { "disable",    .horkage_on     = ATA_HORKAGE_DISABLE },
        };
        char *start = *cur, *p = *cur;
        char *id, *val, *endp;
@@ -6554,6 +6620,38 @@ u32 ata_wait_register(struct ata_port *ap, void __iomem *reg, u32 mask, u32 val,
        return tmp;
 }
 
+/**
+ *     sata_lpm_ignore_phy_events - test if PHY event should be ignored
+ *     @link: Link receiving the event
+ *
+ *     Test whether the received PHY event has to be ignored or not.
+ *
+ *     LOCKING:
+ *     None:
+ *
+ *     RETURNS:
+ *     True if the event has to be ignored.
+ */
+bool sata_lpm_ignore_phy_events(struct ata_link *link)
+{
+       unsigned long lpm_timeout = link->last_lpm_change +
+                                   msecs_to_jiffies(ATA_TMOUT_SPURIOUS_PHY);
+
+       /* if LPM is enabled, PHYRDY doesn't mean anything */
+       if (link->lpm_policy > ATA_LPM_MAX_POWER)
+               return true;
+
+       /* ignore the first PHY event after the LPM policy changed
+        * as it is might be spurious
+        */
+       if ((link->flags & ATA_LFLAG_CHANGED) &&
+           time_before(jiffies, lpm_timeout))
+               return true;
+
+       return false;
+}
+EXPORT_SYMBOL_GPL(sata_lpm_ignore_phy_events);
+
 /*
  * Dummy port_ops
  */