USB: serial: ftdi_sio: Add support for new Xsens devices
[firefly-linux-kernel-4.4.55.git] / drivers / ata / libata-core.c
index 8cacd1693f030d74e7e838e1ccc7459cb26d85c5..ca7c23d58a038c17c3799c3b75e2156e04024d8a 100644 (file)
@@ -2199,6 +2199,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[ATA_ID_SATA_CAPABILITY] & 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)
@@ -4142,6 +4152,7 @@ static const struct ata_blacklist_entry ata_device_blacklist [] = {
 
        /* Seagate Momentus SpinPoint M8 seem to have FPMDA_AA issues */
        { "ST1000LM024 HN-M101MBB", "2AR10001", ATA_HORKAGE_BROKEN_FPDMA_AA },
+       { "ST1000LM024 HN-M101MBB", "2BA30001", ATA_HORKAGE_BROKEN_FPDMA_AA },
 
        /* Blacklist entries taken from Silicon Image 3124/3132
           Windows driver .inf file - also several Linux problem reports */
@@ -4189,6 +4200,23 @@ 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 },
 
+       /*
+        * 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 */
        { }
 };
@@ -4730,6 +4758,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.
  */
@@ -4737,21 +4769,27 @@ 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++) {
+               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;
 }
@@ -6040,6 +6078,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->ops = ops;
 }
@@ -6121,6 +6160,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");
@@ -6267,6 +6308,8 @@ int ata_host_activate(struct ata_host *host, int irq,
 static void ata_port_detach(struct ata_port *ap)
 {
        unsigned long flags;
+       struct ata_link *link;
+       struct ata_device *dev;
 
        if (!ap->ops->error_handler)
                goto skip_eh;
@@ -6286,6 +6329,13 @@ static void ata_port_detach(struct ata_port *ap)
        cancel_delayed_work_sync(&ap->hotplug_task);
 
  skip_eh:
+       /* clean up zpodd on port removal */
+       ata_for_each_link(link, ap, HOST_FIRST) {
+               ata_for_each_dev(dev, link, ALL) {
+                       if (zpodd_dev_enabled(dev))
+                               zpodd_exit(dev);
+               }
+       }
        if (ap->pmp_link) {
                int i;
                for (i = 0; i < SATA_PMP_MAX_PORTS; i++)