libata-pmp-prep: implement ops->qc_defer()
[safe/jmp/linux-2.6] / drivers / ata / libata-core.c
index c7614bd..b666f51 100644 (file)
@@ -59,8 +59,6 @@
 
 #include "libata.h"
 
-#define DRV_VERSION    "2.21"  /* must be exactly four chars */
-
 
 /* debounce timing parameters in msecs { interval, duration, timeout } */
 const unsigned long sata_deb_timing_normal[]           = {   5,  100, 2000 };
@@ -701,8 +699,8 @@ unsigned int ata_dev_classify(const struct ata_taskfile *tf)
 
 /**
  *     ata_dev_try_classify - Parse returned ATA device signature
- *     @ap: ATA channel to examine
- *     @device: Device to examine (starting at zero)
+ *     @dev: ATA device to classify (starting at zero)
+ *     @present: device seems present
  *     @r_err: Value of error register on completion
  *
  *     After an event -- SRST, E.D.D., or SATA COMRESET -- occurs,
@@ -720,15 +718,15 @@ unsigned int ata_dev_classify(const struct ata_taskfile *tf)
  *     RETURNS:
  *     Device type - %ATA_DEV_ATA, %ATA_DEV_ATAPI or %ATA_DEV_NONE.
  */
-
-unsigned int
-ata_dev_try_classify(struct ata_port *ap, unsigned int device, u8 *r_err)
+unsigned int ata_dev_try_classify(struct ata_device *dev, int present,
+                                 u8 *r_err)
 {
+       struct ata_port *ap = dev->link->ap;
        struct ata_taskfile tf;
        unsigned int class;
        u8 err;
 
-       ap->ops->dev_select(ap, device);
+       ap->ops->dev_select(ap, dev->devno);
 
        memset(&tf, 0, sizeof(tf));
 
@@ -738,12 +736,12 @@ ata_dev_try_classify(struct ata_port *ap, unsigned int device, u8 *r_err)
                *r_err = err;
 
        /* see if device passed diags: if master then continue and warn later */
-       if (err == 0 && device == 0)
+       if (err == 0 && dev->devno == 0)
                /* diagnostic fail : do nothing _YET_ */
-               ap->link.device[device].horkage |= ATA_HORKAGE_DIAGNOSTIC;
+               dev->horkage |= ATA_HORKAGE_DIAGNOSTIC;
        else if (err == 1)
                /* do nothing */ ;
-       else if ((device == 0) && (err == 0x81))
+       else if ((dev->devno == 0) && (err == 0x81))
                /* do nothing */ ;
        else
                return ATA_DEV_NONE;
@@ -751,10 +749,20 @@ ata_dev_try_classify(struct ata_port *ap, unsigned int device, u8 *r_err)
        /* determine if device is ATA or ATAPI */
        class = ata_dev_classify(&tf);
 
-       if (class == ATA_DEV_UNKNOWN)
-               return ATA_DEV_NONE;
-       if ((class == ATA_DEV_ATA) && (ata_chk_status(ap) == 0))
-               return ATA_DEV_NONE;
+       if (class == ATA_DEV_UNKNOWN) {
+               /* If the device failed diagnostic, it's likely to
+                * have reported incorrect device signature too.
+                * Assume ATA device if the device seems present but
+                * device signature is invalid with diagnostic
+                * failure.
+                */
+               if (present && (dev->horkage & ATA_HORKAGE_DIAGNOSTIC))
+                       class = ATA_DEV_ATA;
+               else
+                       class = ATA_DEV_NONE;
+       } else if ((class == ATA_DEV_ATA) && (ata_chk_status(ap) == 0))
+               class = ATA_DEV_NONE;
+
        return class;
 }
 
@@ -915,7 +923,6 @@ static int ata_read_native_max_address(struct ata_device *dev, u64 *max_sectors)
  *     ata_set_max_sectors - Set max sectors
  *     @dev: target device
  *     @new_sectors: new max sectors value to set for the device
- *     @res_sectors: result max sectors
  *
  *     Set max sectors of @dev to @new_sectors.
  *
@@ -924,8 +931,7 @@ static int ata_read_native_max_address(struct ata_device *dev, u64 *max_sectors)
  *     previous non-volatile SET_MAX) by the drive.  -EIO on other
  *     errors.
  */
-static int ata_set_max_sectors(struct ata_device *dev, u64 new_sectors,
-                              u64 *res_sectors)
+static int ata_set_max_sectors(struct ata_device *dev, u64 new_sectors)
 {
        unsigned int err_mask;
        struct ata_taskfile tf;
@@ -964,11 +970,6 @@ static int ata_set_max_sectors(struct ata_device *dev, u64 new_sectors,
                return -EIO;
        }
 
-       if (lba48)
-               *res_sectors = ata_tf_to_lba48(&tf);
-       else
-               *res_sectors = ata_tf_to_lba(&tf);
-
        return 0;
 }
 
@@ -979,41 +980,93 @@ static int ata_set_max_sectors(struct ata_device *dev, u64 new_sectors,
  *     Read the size of an LBA28 or LBA48 disk with HPA features and resize
  *     it if required to the full size of the media. The caller must check
  *     the drive has the HPA feature set enabled.
+ *
+ *     RETURNS:
+ *     0 on success, -errno on failure.
  */
-
-static u64 ata_hpa_resize(struct ata_device *dev)
+static int ata_hpa_resize(struct ata_device *dev)
 {
-       u64 sectors = dev->n_sectors;
-       u64 hpa_sectors;
+       struct ata_eh_context *ehc = &dev->link->eh_context;
+       int print_info = ehc->i.flags & ATA_EHI_PRINTINFO;
+       u64 sectors = ata_id_n_sectors(dev->id);
+       u64 native_sectors;
        int rc;
 
-       rc = ata_read_native_max_address(dev, &hpa_sectors);
-       if (rc)
+       /* do we need to do it? */
+       if (dev->class != ATA_DEV_ATA ||
+           !ata_id_has_lba(dev->id) || !ata_id_hpa_enabled(dev->id) ||
+           (dev->horkage & ATA_HORKAGE_BROKEN_HPA))
                return 0;
 
-       if (hpa_sectors > sectors) {
-               ata_dev_printk(dev, KERN_INFO,
-                       "Host Protected Area detected:\n"
-                       "\tcurrent size: %lld sectors\n"
-                       "\tnative size: %lld sectors\n",
-                       (long long)sectors, (long long)hpa_sectors);
-
-               if (ata_ignore_hpa) {
-                       rc = ata_set_max_sectors(dev, hpa_sectors, &hpa_sectors);
-
-                       if (rc == 0) {
-                               ata_dev_printk(dev, KERN_INFO, "native size "
-                                       "increased to %lld sectors\n",
-                                       (long long)hpa_sectors);
-                               return hpa_sectors;
-                       }
+       /* read native max address */
+       rc = ata_read_native_max_address(dev, &native_sectors);
+       if (rc) {
+               /* If HPA isn't going to be unlocked, skip HPA
+                * resizing from the next try.
+                */
+               if (!ata_ignore_hpa) {
+                       ata_dev_printk(dev, KERN_WARNING, "HPA support seems "
+                                      "broken, will skip HPA handling\n");
+                       dev->horkage |= ATA_HORKAGE_BROKEN_HPA;
+
+                       /* we can continue if device aborted the command */
+                       if (rc == -EACCES)
+                               rc = 0;
                }
-       } else if (hpa_sectors < sectors)
-               ata_dev_printk(dev, KERN_WARNING, "%s 1: hpa sectors (%lld) "
-                              "is smaller than sectors (%lld)\n", __FUNCTION__,
-                              (long long)hpa_sectors, (long long)sectors);
 
-       return sectors;
+               return rc;
+       }
+
+       /* nothing to do? */
+       if (native_sectors <= sectors || !ata_ignore_hpa) {
+               if (!print_info || native_sectors == sectors)
+                       return 0;
+
+               if (native_sectors > sectors)
+                       ata_dev_printk(dev, KERN_INFO,
+                               "HPA detected: current %llu, native %llu\n",
+                               (unsigned long long)sectors,
+                               (unsigned long long)native_sectors);
+               else if (native_sectors < sectors)
+                       ata_dev_printk(dev, KERN_WARNING,
+                               "native sectors (%llu) is smaller than "
+                               "sectors (%llu)\n",
+                               (unsigned long long)native_sectors,
+                               (unsigned long long)sectors);
+               return 0;
+       }
+
+       /* let's unlock HPA */
+       rc = ata_set_max_sectors(dev, native_sectors);
+       if (rc == -EACCES) {
+               /* if device aborted the command, skip HPA resizing */
+               ata_dev_printk(dev, KERN_WARNING, "device aborted resize "
+                              "(%llu -> %llu), skipping HPA handling\n",
+                              (unsigned long long)sectors,
+                              (unsigned long long)native_sectors);
+               dev->horkage |= ATA_HORKAGE_BROKEN_HPA;
+               return 0;
+       } else if (rc)
+               return rc;
+
+       /* re-read IDENTIFY data */
+       rc = ata_dev_reread_id(dev, 0);
+       if (rc) {
+               ata_dev_printk(dev, KERN_ERR, "failed to re-read IDENTIFY "
+                              "data after HPA resizing\n");
+               return rc;
+       }
+
+       if (print_info) {
+               u64 new_sectors = ata_id_n_sectors(dev->id);
+               ata_dev_printk(dev, KERN_INFO,
+                       "HPA unlocked: %llu -> %llu, native %llu\n",
+                       (unsigned long long)sectors,
+                       (unsigned long long)new_sectors,
+                       (unsigned long long)native_sectors);
+       }
+
+       return 0;
 }
 
 /**
@@ -1837,6 +1890,11 @@ int ata_dev_configure(struct ata_device *dev)
        if (rc)
                return rc;
 
+       /* massage HPA, do it early as it might change IDENTIFY data */
+       rc = ata_hpa_resize(dev);
+       if (rc)
+               return rc;
+
        /* print device capabilities */
        if (ata_msg_probe(ap))
                ata_dev_printk(dev, KERN_DEBUG,
@@ -1904,10 +1962,6 @@ int ata_dev_configure(struct ata_device *dev)
                                        dev->flags |= ATA_DFLAG_FLUSH_EXT;
                        }
 
-                       if (!(dev->horkage & ATA_HORKAGE_BROKEN_HPA) &&
-                           ata_id_hpa_enabled(dev->id))
-                               dev->n_sectors = ata_hpa_resize(dev);
-
                        /* config NCQ */
                        ata_dev_config_ncq(dev, ncq_desc, sizeof(ncq_desc));
 
@@ -1956,7 +2010,8 @@ int ata_dev_configure(struct ata_device *dev)
 
        /* ATAPI-specific feature tests */
        else if (dev->class == ATA_DEV_ATAPI) {
-               char *cdb_intr_string = "";
+               const char *cdb_intr_string = "";
+               const char *atapi_an_string = "";
 
                rc = atapi_cdb_len(id);
                if ((rc < 12) || (rc > ATAPI_CDB_LEN)) {
@@ -1972,16 +2027,19 @@ int ata_dev_configure(struct ata_device *dev)
                 * check to see if this ATAPI device supports
                 * Asynchronous Notification
                 */
-               if ((ap->flags & ATA_FLAG_AN) && ata_id_has_AN(id)) {
-                       int err;
+               if ((ap->flags & ATA_FLAG_AN) && ata_id_has_atapi_AN(id)) {
+                       unsigned int err_mask;
+
                        /* issue SET feature command to turn this on */
-                       err = ata_dev_set_AN(dev, SETFEATURES_SATA_ENABLE);
-                       if (err)
+                       err_mask = ata_dev_set_AN(dev, SETFEATURES_SATA_ENABLE);
+                       if (err_mask)
                                ata_dev_printk(dev, KERN_ERR,
-                                               "unable to set AN, err %x\n",
-                                               err);
-                       else
+                                       "failed to enable ATAPI AN "
+                                       "(err_mask=0x%x)\n", err_mask);
+                       else {
                                dev->flags |= ATA_DFLAG_AN;
+                               atapi_an_string = ", ATAPI AN";
+                       }
                }
 
                if (ata_id_cdb_intr(dev->id)) {
@@ -1992,10 +2050,10 @@ int ata_dev_configure(struct ata_device *dev)
                /* print device info to dmesg */
                if (ata_msg_drv(ap) && print_info)
                        ata_dev_printk(dev, KERN_INFO,
-                                      "ATAPI: %s, %s, max %s%s\n",
+                                      "ATAPI: %s, %s, max %s%s%s\n",
                                       modelbuf, fwrevbuf,
                                       ata_mode_string(xfer_mask),
-                                      cdb_intr_string);
+                                      cdb_intr_string, atapi_an_string);
        }
 
        /* determine max_sectors */
@@ -2788,7 +2846,7 @@ static int ata_dev_set_mode(struct ata_device *dev)
        }
 
        ehc->i.flags |= ATA_EHI_POST_SETMODE;
-       rc = ata_dev_revalidate(dev, 0);
+       rc = ata_dev_revalidate(dev, ATA_DEV_UNKNOWN, 0);
        ehc->i.flags &= ~ATA_EHI_POST_SETMODE;
        if (rc)
                return rc;
@@ -3192,9 +3250,9 @@ void ata_bus_reset(struct ata_port *ap)
        /*
         * determine by signature whether we have ATA or ATAPI devices
         */
-       device[0].class = ata_dev_try_classify(ap, 0, &err);
+       device[0].class = ata_dev_try_classify(&device[0], dev0, &err);
        if ((slave_possible) && (err != 0x81))
-               device[1].class = ata_dev_try_classify(ap, 1, &err);
+               device[1].class = ata_dev_try_classify(&device[1], dev1, &err);
 
        /* is double-select really necessary? */
        if (device[1].class != ATA_DEV_NONE)
@@ -3433,9 +3491,11 @@ int ata_std_softreset(struct ata_link *link, unsigned int *classes,
        }
 
        /* determine by signature whether we have ATA or ATAPI devices */
-       classes[0] = ata_dev_try_classify(ap, 0, &err);
+       classes[0] = ata_dev_try_classify(&link->device[0],
+                                         devmask & (1 << 0), &err);
        if (slave_possible && err != 0x81)
-               classes[1] = ata_dev_try_classify(ap, 1, &err);
+               classes[1] = ata_dev_try_classify(&link->device[1],
+                                                 devmask & (1 << 1), &err);
 
  out:
        DPRINTK("EXIT, classes[0]=%u [1]=%u\n", classes[0], classes[1]);
@@ -3554,7 +3614,7 @@ int sata_std_hardreset(struct ata_link *link, unsigned int *class,
 
        ap->ops->dev_select(ap, 0);     /* probably unnecessary */
 
-       *class = ata_dev_try_classify(ap, 0, NULL);
+       *class = ata_dev_try_classify(link->device, 1, NULL);
 
        DPRINTK("EXIT, class=%u\n", *class);
        return 0;
@@ -3690,6 +3750,7 @@ int ata_dev_reread_id(struct ata_device *dev, unsigned int readid_flags)
 /**
  *     ata_dev_revalidate - Revalidate ATA device
  *     @dev: device to revalidate
+ *     @new_class: new class code
  *     @readid_flags: read ID flags
  *
  *     Re-read IDENTIFY page, make sure @dev is still attached to the
@@ -3701,7 +3762,8 @@ int ata_dev_reread_id(struct ata_device *dev, unsigned int readid_flags)
  *     RETURNS:
  *     0 on success, negative errno otherwise
  */
-int ata_dev_revalidate(struct ata_device *dev, unsigned int readid_flags)
+int ata_dev_revalidate(struct ata_device *dev, unsigned int new_class,
+                      unsigned int readid_flags)
 {
        u64 n_sectors = dev->n_sectors;
        int rc;
@@ -3709,6 +3771,15 @@ int ata_dev_revalidate(struct ata_device *dev, unsigned int readid_flags)
        if (!ata_dev_enabled(dev))
                return -ENODEV;
 
+       /* fail early if !ATA && !ATAPI to avoid issuing [P]IDENTIFY to PMP */
+       if (ata_class_enabled(new_class) &&
+           new_class != ATA_DEV_ATA && new_class != ATA_DEV_ATAPI) {
+               ata_dev_printk(dev, KERN_INFO, "class mismatch %u != %u\n",
+                              dev->class, new_class);
+               rc = -ENODEV;
+               goto fail;
+       }
+
        /* re-read ID */
        rc = ata_dev_reread_id(dev, readid_flags);
        if (rc)
@@ -4275,6 +4346,36 @@ int ata_check_atapi_dma(struct ata_queued_cmd *qc)
 }
 
 /**
+ *     ata_std_qc_defer - Check whether a qc needs to be deferred
+ *     @qc: ATA command in question
+ *
+ *     Non-NCQ commands cannot run with any other command, NCQ or
+ *     not.  As upper layer only knows the queue depth, we are
+ *     responsible for maintaining exclusion.  This function checks
+ *     whether a new command @qc can be issued.
+ *
+ *     LOCKING:
+ *     spin_lock_irqsave(host lock)
+ *
+ *     RETURNS:
+ *     ATA_DEFER_* if deferring is needed, 0 otherwise.
+ */
+int ata_std_qc_defer(struct ata_queued_cmd *qc)
+{
+       struct ata_link *link = qc->dev->link;
+
+       if (qc->tf.protocol == ATA_PROT_NCQ) {
+               if (!ata_tag_valid(link->active_tag))
+                       return 0;
+       } else {
+               if (!ata_tag_valid(link->active_tag) && !link->sactive)
+                       return 0;
+       }
+
+       return ATA_DEFER_LINK;
+}
+
+/**
  *     ata_qc_prep - Prepare taskfile for submission
  *     @qc: Metadata associated with taskfile to be prepared
  *
@@ -6147,7 +6248,7 @@ void ata_dev_init(struct ata_device *dev)
  *     LOCKING:
  *     Kernel thread context (may sleep)
  */
-static void ata_link_init(struct ata_port *ap, struct ata_link *link, int pmp)
+void ata_link_init(struct ata_port *ap, struct ata_link *link, int pmp)
 {
        int i;
 
@@ -6182,7 +6283,7 @@ static void ata_link_init(struct ata_port *ap, struct ata_link *link, int pmp)
  *     RETURNS:
  *     0 on success, -errno on failure.
  */
-static int sata_link_init_spd(struct ata_link *link)
+int sata_link_init_spd(struct ata_link *link)
 {
        u32 scontrol, spd;
        int rc;
@@ -7040,6 +7141,7 @@ EXPORT_SYMBOL_GPL(ata_interrupt);
 EXPORT_SYMBOL_GPL(ata_do_set_mode);
 EXPORT_SYMBOL_GPL(ata_data_xfer);
 EXPORT_SYMBOL_GPL(ata_data_xfer_noirq);
+EXPORT_SYMBOL_GPL(ata_std_qc_defer);
 EXPORT_SYMBOL_GPL(ata_qc_prep);
 EXPORT_SYMBOL_GPL(ata_dumb_qc_prep);
 EXPORT_SYMBOL_GPL(ata_noop_qc_prep);