ahci: clean up board IDs
[safe/jmp/linux-2.6] / drivers / ata / libata-core.c
index 22ff51b..49cffb6 100644 (file)
@@ -58,6 +58,7 @@
 #include <linux/io.h>
 #include <linux/async.h>
 #include <linux/log2.h>
+#include <linux/slab.h>
 #include <scsi/scsi.h>
 #include <scsi/scsi_cmnd.h>
 #include <scsi/scsi_host.h>
@@ -1493,6 +1494,7 @@ static int ata_hpa_resize(struct ata_device *dev)
 {
        struct ata_eh_context *ehc = &dev->link->eh_context;
        int print_info = ehc->i.flags & ATA_EHI_PRINTINFO;
+       bool unlock_hpa = ata_ignore_hpa || dev->flags & ATA_DFLAG_UNLOCK_HPA;
        u64 sectors = ata_id_n_sectors(dev->id);
        u64 native_sectors;
        int rc;
@@ -1509,7 +1511,7 @@ static int ata_hpa_resize(struct ata_device *dev)
                /* If device aborted the command or HPA isn't going to
                 * be unlocked, skip HPA resizing.
                 */
-               if (rc == -EACCES || !ata_ignore_hpa) {
+               if (rc == -EACCES || !unlock_hpa) {
                        ata_dev_printk(dev, KERN_WARNING, "HPA support seems "
                                       "broken, skipping HPA handling\n");
                        dev->horkage |= ATA_HORKAGE_BROKEN_HPA;
@@ -1524,7 +1526,7 @@ static int ata_hpa_resize(struct ata_device *dev)
        dev->n_native_sectors = native_sectors;
 
        /* nothing to do? */
-       if (native_sectors <= sectors || !ata_ignore_hpa) {
+       if (native_sectors <= sectors || !unlock_hpa) {
                if (!print_info || native_sectors == sectors)
                        return 0;
 
@@ -2232,7 +2234,7 @@ retry:
                 * Some drives were very specific about that exact sequence.
                 *
                 * Note that ATA4 says lba is mandatory so the second check
-                * shoud never trigger.
+                * should never trigger.
                 */
                if (ata_id_major_version(id) < 4 || !ata_id_has_lba(id)) {
                        err_mask = ata_dev_init_params(dev, id[3], id[6]);
@@ -3211,6 +3213,7 @@ const struct ata_timing *ata_timing_find_mode(u8 xfer_mode)
 int ata_timing_compute(struct ata_device *adev, unsigned short speed,
                       struct ata_timing *t, int T, int UT)
 {
+       const u16 *id = adev->id;
        const struct ata_timing *s;
        struct ata_timing p;
 
@@ -3228,14 +3231,18 @@ int ata_timing_compute(struct ata_device *adev, unsigned short speed,
         * PIO/MW_DMA cycle timing.
         */
 
-       if (adev->id[ATA_ID_FIELD_VALID] & 2) { /* EIDE drive */
+       if (id[ATA_ID_FIELD_VALID] & 2) {       /* EIDE drive */
                memset(&p, 0, sizeof(p));
+
                if (speed >= XFER_PIO_0 && speed <= XFER_SW_DMA_0) {
-                       if (speed <= XFER_PIO_2) p.cycle = p.cyc8b = adev->id[ATA_ID_EIDE_PIO];
-                                           else p.cycle = p.cyc8b = adev->id[ATA_ID_EIDE_PIO_IORDY];
-               } else if (speed >= XFER_MW_DMA_0 && speed <= XFER_MW_DMA_2) {
-                       p.cycle = adev->id[ATA_ID_EIDE_DMA_MIN];
-               }
+                       if (speed <= XFER_PIO_2)
+                               p.cycle = p.cyc8b = id[ATA_ID_EIDE_PIO];
+                       else if ((speed <= XFER_PIO_4) ||
+                                (speed == XFER_PIO_5 && !ata_id_is_cfa(id)))
+                               p.cycle = p.cyc8b = id[ATA_ID_EIDE_PIO_IORDY];
+               } else if (speed >= XFER_MW_DMA_0 && speed <= XFER_MW_DMA_2)
+                       p.cycle = id[ATA_ID_EIDE_DMA_MIN];
+
                ata_timing_merge(&p, t, t, ATA_TIMING_CYCLE | ATA_TIMING_CYC8B);
        }
 
@@ -3790,21 +3797,45 @@ int sata_link_debounce(struct ata_link *link, const unsigned long *params,
 int sata_link_resume(struct ata_link *link, const unsigned long *params,
                     unsigned long deadline)
 {
+       int tries = ATA_LINK_RESUME_TRIES;
        u32 scontrol, serror;
        int rc;
 
        if ((rc = sata_scr_read(link, SCR_CONTROL, &scontrol)))
                return rc;
 
-       scontrol = (scontrol & 0x0f0) | 0x300;
+       /*
+        * Writes to SControl sometimes get ignored under certain
+        * controllers (ata_piix SIDPR).  Make sure DET actually is
+        * cleared.
+        */
+       do {
+               scontrol = (scontrol & 0x0f0) | 0x300;
+               if ((rc = sata_scr_write(link, SCR_CONTROL, scontrol)))
+                       return rc;
+               /*
+                * Some PHYs react badly if SStatus is pounded
+                * immediately after resuming.  Delay 200ms before
+                * debouncing.
+                */
+               msleep(200);
 
-       if ((rc = sata_scr_write(link, SCR_CONTROL, scontrol)))
-               return rc;
+               /* is SControl restored correctly? */
+               if ((rc = sata_scr_read(link, SCR_CONTROL, &scontrol)))
+                       return rc;
+       } while ((scontrol & 0xf0f) != 0x300 && --tries);
 
-       /* Some PHYs react badly if SStatus is pounded immediately
-        * after resuming.  Delay 200ms before debouncing.
-        */
-       msleep(200);
+       if ((scontrol & 0xf0f) != 0x300) {
+               ata_link_printk(link, KERN_ERR,
+                               "failed to resume link (SControl %X)\n",
+                               scontrol);
+               return 0;
+       }
+
+       if (tries < ATA_LINK_RESUME_TRIES)
+               ata_link_printk(link, KERN_WARNING,
+                               "link resume succeeded after %d retries\n",
+                               ATA_LINK_RESUME_TRIES - tries);
 
        if ((rc = sata_link_debounce(link, params, deadline)))
                return rc;
@@ -4156,36 +4187,51 @@ int ata_dev_revalidate(struct ata_device *dev, unsigned int new_class,
                goto fail;
 
        /* verify n_sectors hasn't changed */
-       if (dev->class == ATA_DEV_ATA && n_sectors &&
-           dev->n_sectors != n_sectors) {
-               ata_dev_printk(dev, KERN_WARNING, "n_sectors mismatch "
-                              "%llu != %llu\n",
-                              (unsigned long long)n_sectors,
-                              (unsigned long long)dev->n_sectors);
-               /*
-                * Something could have caused HPA to be unlocked
-                * involuntarily.  If n_native_sectors hasn't changed
-                * and the new size matches it, keep the device.
-                */
-               if (dev->n_native_sectors == n_native_sectors &&
-                   dev->n_sectors > n_sectors &&
-                   dev->n_sectors == n_native_sectors) {
-                       ata_dev_printk(dev, KERN_WARNING,
-                                      "new n_sectors matches native, probably "
-                                      "late HPA unlock, continuing\n");
-                       /* keep using the old n_sectors */
-                       dev->n_sectors = n_sectors;
-               } else {
-                       /* restore original n_[native]_sectors and fail */
-                       dev->n_native_sectors = n_native_sectors;
-                       dev->n_sectors = n_sectors;
-                       rc = -ENODEV;
-                       goto fail;
-               }
+       if (dev->class != ATA_DEV_ATA || !n_sectors ||
+           dev->n_sectors == n_sectors)
+               return 0;
+
+       /* n_sectors has changed */
+       ata_dev_printk(dev, KERN_WARNING, "n_sectors mismatch %llu != %llu\n",
+                      (unsigned long long)n_sectors,
+                      (unsigned long long)dev->n_sectors);
+
+       /*
+        * Something could have caused HPA to be unlocked
+        * involuntarily.  If n_native_sectors hasn't changed and the
+        * new size matches it, keep the device.
+        */
+       if (dev->n_native_sectors == n_native_sectors &&
+           dev->n_sectors > n_sectors && dev->n_sectors == n_native_sectors) {
+               ata_dev_printk(dev, KERN_WARNING,
+                              "new n_sectors matches native, probably "
+                              "late HPA unlock, continuing\n");
+               /* keep using the old n_sectors */
+               dev->n_sectors = n_sectors;
+               return 0;
        }
 
-       return 0;
+       /*
+        * Some BIOSes boot w/o HPA but resume w/ HPA locked.  Try
+        * unlocking HPA in those cases.
+        *
+        * https://bugzilla.kernel.org/show_bug.cgi?id=15396
+        */
+       if (dev->n_native_sectors == n_native_sectors &&
+           dev->n_sectors < n_sectors && n_sectors == n_native_sectors &&
+           !(dev->horkage & ATA_HORKAGE_BROKEN_HPA)) {
+               ata_dev_printk(dev, KERN_WARNING,
+                              "old n_sectors matches native, probably "
+                              "late HPA lock, will try to unlock HPA\n");
+               /* try unlocking HPA */
+               dev->flags |= ATA_DFLAG_UNLOCK_HPA;
+               rc = -EIO;
+       } else
+               rc = -ENODEV;
 
+       /* restore original n_[native_]sectors and fail */
+       dev->n_native_sectors = n_native_sectors;
+       dev->n_sectors = n_sectors;
  fail:
        ata_dev_printk(dev, KERN_ERR, "revalidation failed (errno=%d)\n", rc);
        return rc;
@@ -4324,6 +4370,9 @@ static const struct ata_blacklist_entry ata_device_blacklist [] = {
        { "HTS541080G9SA00",    "MB4OC60D",     ATA_HORKAGE_NONCQ, },
        { "HTS541010G9SA00",    "MBZOC60D",     ATA_HORKAGE_NONCQ, },
 
+       /* https://bugzilla.kernel.org/show_bug.cgi?id=15573 */
+       { "C300-CTFDDAC128MAG", "0001",         ATA_HORKAGE_NONCQ, },
+
        /* devices which puke on READ_NATIVE_MAX */
        { "HDS724040KLSA80",    "KFAOA20N",     ATA_HORKAGE_BROKEN_HPA, },
        { "WDC WD3200JD-00KLB0", "WD-WCAMR1130137", ATA_HORKAGE_BROKEN_HPA },