libata-pmp-prep: implement sata_async_notification()
[safe/jmp/linux-2.6] / drivers / ata / libata-core.c
index 2116f27..8b08e7b 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 };
@@ -1392,6 +1390,7 @@ unsigned ata_exec_internal_sg(struct ata_device *dev,
        struct ata_queued_cmd *qc;
        unsigned int tag, preempted_tag;
        u32 preempted_sactive, preempted_qc_active;
+       int preempted_nr_active_links;
        DECLARE_COMPLETION_ONSTACK(wait);
        unsigned long flags;
        unsigned int err_mask;
@@ -1430,9 +1429,11 @@ unsigned ata_exec_internal_sg(struct ata_device *dev,
        preempted_tag = link->active_tag;
        preempted_sactive = link->sactive;
        preempted_qc_active = ap->qc_active;
+       preempted_nr_active_links = ap->nr_active_links;
        link->active_tag = ATA_TAG_POISON;
        link->sactive = 0;
        ap->qc_active = 0;
+       ap->nr_active_links = 0;
 
        /* prepare & issue qc */
        qc->tf = *tf;
@@ -1511,6 +1512,7 @@ unsigned ata_exec_internal_sg(struct ata_device *dev,
        link->active_tag = preempted_tag;
        link->sactive = preempted_sactive;
        ap->qc_active = preempted_qc_active;
+       ap->nr_active_links = preempted_nr_active_links;
 
        /* XXX - Some LLDDs (sata_mv) disable port on command failure.
         * Until those drivers are fixed, we detect the condition
@@ -2012,7 +2014,9 @@ 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 = "";
+               u32 sntf;
 
                rc = atapi_cdb_len(id);
                if ((rc < 12) || (rc > ATAPI_CDB_LEN)) {
@@ -2024,20 +2028,26 @@ int ata_dev_configure(struct ata_device *dev)
                }
                dev->cdb_len = (unsigned int) rc;
 
-               /*
-                * check to see if this ATAPI device supports
-                * Asynchronous Notification
+               /* Enable ATAPI AN if both the host and device have
+                * the support.  If PMP is attached, SNTF is required
+                * to enable ATAPI AN to discern between PHY status
+                * changed notifications and ATAPI ANs.
                 */
-               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) &&
+                   (!ap->nr_pmp_links ||
+                    sata_scr_read(&ap->link, SCR_NOTIFICATION, &sntf) == 0)) {
+                       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)) {
@@ -2048,10 +2058,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 */
@@ -2844,7 +2854,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;
@@ -3748,6 +3758,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
@@ -3759,7 +3770,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;
@@ -3767,6 +3779,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)
@@ -4333,6 +4354,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
  *
@@ -5365,10 +5416,19 @@ void __ata_qc_complete(struct ata_queued_cmd *qc)
                ata_sg_clean(qc);
 
        /* command should be marked inactive atomically with qc completion */
-       if (qc->tf.protocol == ATA_PROT_NCQ)
+       if (qc->tf.protocol == ATA_PROT_NCQ) {
                link->sactive &= ~(1 << qc->tag);
-       else
+               if (!link->sactive)
+                       ap->nr_active_links--;
+       } else {
                link->active_tag = ATA_TAG_POISON;
+               ap->nr_active_links--;
+       }
+
+       /* clear exclusive status */
+       if (unlikely(qc->flags & ATA_QCFLAG_CLEAR_EXCL &&
+                    ap->excl_link == link))
+               ap->excl_link = NULL;
 
        /* atapi: mark qc as inactive to prevent the interrupt handler
         * from completing the command twice later, before the error handler
@@ -5547,9 +5607,14 @@ void ata_qc_issue(struct ata_queued_cmd *qc)
 
        if (qc->tf.protocol == ATA_PROT_NCQ) {
                WARN_ON(link->sactive & (1 << qc->tag));
+
+               if (!link->sactive)
+                       ap->nr_active_links++;
                link->sactive |= 1 << qc->tag;
        } else {
                WARN_ON(link->sactive);
+
+               ap->nr_active_links++;
                link->active_tag = qc->tag;
        }
 
@@ -6205,7 +6270,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;
 
@@ -6240,7 +6305,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;
@@ -7098,6 +7163,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);
@@ -7186,6 +7252,7 @@ EXPORT_SYMBOL_GPL(ata_port_schedule_eh);
 EXPORT_SYMBOL_GPL(ata_link_abort);
 EXPORT_SYMBOL_GPL(ata_port_abort);
 EXPORT_SYMBOL_GPL(ata_port_freeze);
+EXPORT_SYMBOL_GPL(sata_async_notification);
 EXPORT_SYMBOL_GPL(ata_eh_freeze_port);
 EXPORT_SYMBOL_GPL(ata_eh_thaw_port);
 EXPORT_SYMBOL_GPL(ata_eh_qc_complete);