]> err.no Git - linux-2.6/blobdiff - drivers/ata/libata-core.c
libata: drop ata_dev_select() from ata_dev_read_id
[linux-2.6] / drivers / ata / libata-core.c
index 4fbcce758b04deb227729ebd6b445009cb37777a..7860d9f60ae458d310483cca4ffb9444b1a9d4ea 100644 (file)
@@ -74,6 +74,65 @@ const unsigned long sata_deb_timing_normal[]         = {   5,  100, 2000 };
 const unsigned long sata_deb_timing_hotplug[]          = {  25,  500, 2000 };
 const unsigned long sata_deb_timing_long[]             = { 100, 2000, 5000 };
 
+const struct ata_port_operations ata_base_port_ops = {
+       .irq_clear              = ata_noop_irq_clear,
+       .prereset               = ata_std_prereset,
+       .hardreset              = sata_std_hardreset,
+       .postreset              = ata_std_postreset,
+       .error_handler          = ata_std_error_handler,
+};
+
+const struct ata_port_operations sata_port_ops = {
+       .inherits               = &ata_base_port_ops,
+
+       .qc_defer               = ata_std_qc_defer,
+       .dev_select             = ata_noop_dev_select,
+};
+
+const struct ata_port_operations sata_pmp_port_ops = {
+       .inherits               = &sata_port_ops,
+
+       .pmp_prereset           = sata_pmp_std_prereset,
+       .pmp_hardreset          = sata_pmp_std_hardreset,
+       .pmp_postreset          = sata_pmp_std_postreset,
+       .error_handler          = sata_pmp_error_handler,
+};
+
+const struct ata_port_operations ata_sff_port_ops = {
+       .inherits               = &ata_base_port_ops,
+
+       .qc_prep                = ata_qc_prep,
+       .qc_issue               = ata_qc_issue_prot,
+
+       .freeze                 = ata_bmdma_freeze,
+       .thaw                   = ata_bmdma_thaw,
+       .softreset              = ata_std_softreset,
+       .error_handler          = ata_bmdma_error_handler,
+       .post_internal_cmd      = ata_bmdma_post_internal_cmd,
+
+       .dev_select             = ata_std_dev_select,
+       .check_status           = ata_check_status,
+       .tf_load                = ata_tf_load,
+       .tf_read                = ata_tf_read,
+       .exec_command           = ata_exec_command,
+       .data_xfer              = ata_data_xfer,
+       .irq_on                 = ata_irq_on,
+
+       .port_start             = ata_sff_port_start,
+};
+
+const struct ata_port_operations ata_bmdma_port_ops = {
+       .inherits               = &ata_sff_port_ops,
+
+       .mode_filter            = ata_pci_default_filter,
+
+       .bmdma_setup            = ata_bmdma_setup,
+       .bmdma_start            = ata_bmdma_start,
+       .bmdma_stop             = ata_bmdma_stop,
+       .bmdma_status           = ata_bmdma_status,
+       .irq_clear              = ata_bmdma_irq_clear,
+};
+
 static unsigned int ata_dev_init_params(struct ata_device *dev,
                                        u16 heads, u16 sectors);
 static unsigned int ata_dev_set_xfermode(struct ata_device *dev);
@@ -106,7 +165,8 @@ static struct ata_force_ent *ata_force_tbl;
 static int ata_force_tbl_size;
 
 static char ata_force_param_buf[PAGE_SIZE] __initdata;
-module_param_string(force, ata_force_param_buf, sizeof(ata_force_param_buf), 0444);
+/* param_buf is thrown away after initialization, disallow read */
+module_param_string(force, ata_force_param_buf, sizeof(ata_force_param_buf), 0);
 MODULE_PARM_DESC(force, "Force ATA configurations including cable type, link speed and transfer mode (see Documentation/kernel-parameters.txt for details)");
 
 int atapi_enabled = 1;
@@ -324,6 +384,44 @@ static void ata_force_horkage(struct ata_device *dev)
        }
 }
 
+/**
+ *     atapi_cmd_type - Determine ATAPI command type from SCSI opcode
+ *     @opcode: SCSI opcode
+ *
+ *     Determine ATAPI command type from @opcode.
+ *
+ *     LOCKING:
+ *     None.
+ *
+ *     RETURNS:
+ *     ATAPI_{READ|WRITE|READ_CD|PASS_THRU|MISC}
+ */
+int atapi_cmd_type(u8 opcode)
+{
+       switch (opcode) {
+       case GPCMD_READ_10:
+       case GPCMD_READ_12:
+               return ATAPI_READ;
+
+       case GPCMD_WRITE_10:
+       case GPCMD_WRITE_12:
+       case GPCMD_WRITE_AND_VERIFY_10:
+               return ATAPI_WRITE;
+
+       case GPCMD_READ_CD:
+       case GPCMD_READ_CD_MSF:
+               return ATAPI_READ_CD;
+
+       case ATA_16:
+       case ATA_12:
+               if (atapi_passthru16)
+                       return ATAPI_PASS_THRU;
+               /* fall thru */
+       default:
+               return ATAPI_MISC;
+       }
+}
+
 /**
  *     ata_tf_to_fis - Convert ATA taskfile to SATA FIS structure
  *     @tf: Taskfile to convert
@@ -971,7 +1069,7 @@ static void ata_dev_disable_pm(struct ata_device *dev)
 void ata_lpm_schedule(struct ata_port *ap, enum link_pm policy)
 {
        ap->pm_policy = policy;
-       ap->link.eh_info.action |= ATA_EHI_LPM;
+       ap->link.eh_info.action |= ATA_EH_LPM;
        ap->link.eh_info.flags |= ATA_EHI_NO_AUTOPSY;
        ata_port_schedule_eh(ap);
 }
@@ -1415,12 +1513,12 @@ static int ata_hpa_resize(struct ata_device *dev)
        /* 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 device aborted the command or HPA isn't going to
+                * be unlocked, skip HPA resizing.
                 */
-               if (!ata_ignore_hpa) {
+               if (rc == -EACCES || !ata_ignore_hpa) {
                        ata_dev_printk(dev, KERN_WARNING, "HPA support seems "
-                                      "broken, will skip HPA handling\n");
+                                      "broken, skipping HPA handling\n");
                        dev->horkage |= ATA_HORKAGE_BROKEN_HPA;
 
                        /* we can continue if device aborted the command */
@@ -1719,7 +1817,7 @@ void ata_port_flush_task(struct ata_port *ap)
        cancel_rearming_delayed_work(&ap->port_task);
 
        if (ata_msg_ctl(ap))
-               ata_port_printk(ap, KERN_DEBUG, "%s: EXIT\n", __FUNCTION__);
+               ata_port_printk(ap, KERN_DEBUG, "%s: EXIT\n", __func__);
 }
 
 static void ata_qc_complete_internal(struct ata_queued_cmd *qc)
@@ -2056,9 +2154,8 @@ int ata_dev_read_id(struct ata_device *dev, unsigned int *p_class,
        int rc;
 
        if (ata_msg_ctl(ap))
-               ata_dev_printk(dev, KERN_DEBUG, "%s: ENTER\n", __FUNCTION__);
+               ata_dev_printk(dev, KERN_DEBUG, "%s: ENTER\n", __func__);
 
-       ata_dev_select(ap, dev->devno, 1, 1); /* select device 0/1 */
  retry:
        ata_tf_init(dev, &tf);
 
@@ -2091,24 +2188,34 @@ int ata_dev_read_id(struct ata_device *dev, unsigned int *p_class,
                                     id, sizeof(id[0]) * ATA_ID_WORDS, 0);
        if (err_mask) {
                if (err_mask & AC_ERR_NODEV_HINT) {
-                       DPRINTK("ata%u.%d: NODEV after polling detection\n",
-                               ap->print_id, dev->devno);
+                       ata_dev_printk(dev, KERN_DEBUG,
+                                      "NODEV after polling detection\n");
                        return -ENOENT;
                }
 
-               /* Device or controller might have reported the wrong
-                * device class.  Give a shot at the other IDENTIFY if
-                * the current one is aborted by the device.
-                */
-               if (may_fallback &&
-                   (err_mask == AC_ERR_DEV) && (tf.feature & ATA_ABORTED)) {
-                       may_fallback = 0;
+               if ((err_mask == AC_ERR_DEV) && (tf.feature & ATA_ABORTED)) {
+                       /* Device or controller might have reported
+                        * the wrong device class.  Give a shot at the
+                        * other IDENTIFY if the current one is
+                        * aborted by the device.
+                        */
+                       if (may_fallback) {
+                               may_fallback = 0;
 
-                       if (class == ATA_DEV_ATA)
-                               class = ATA_DEV_ATAPI;
-                       else
-                               class = ATA_DEV_ATA;
-                       goto retry;
+                               if (class == ATA_DEV_ATA)
+                                       class = ATA_DEV_ATAPI;
+                               else
+                                       class = ATA_DEV_ATA;
+                               goto retry;
+                       }
+
+                       /* Control reaches here iff the device aborted
+                        * both flavors of IDENTIFYs which happens
+                        * sometimes with phantom devices.
+                        */
+                       ata_dev_printk(dev, KERN_DEBUG,
+                                      "both IDENTIFYs aborted, assuming NODEV\n");
+                       return -ENOENT;
                }
 
                rc = -EIO;
@@ -2253,12 +2360,12 @@ int ata_dev_configure(struct ata_device *dev)
 
        if (!ata_dev_enabled(dev) && ata_msg_info(ap)) {
                ata_dev_printk(dev, KERN_INFO, "%s: ENTER/EXIT -- nodev\n",
-                              __FUNCTION__);
+                              __func__);
                return 0;
        }
 
        if (ata_msg_probe(ap))
-               ata_dev_printk(dev, KERN_DEBUG, "%s: ENTER\n", __FUNCTION__);
+               ata_dev_printk(dev, KERN_DEBUG, "%s: ENTER\n", __func__);
 
        /* set horkage */
        dev->horkage |= ata_dev_blacklisted(dev);
@@ -2279,7 +2386,7 @@ int ata_dev_configure(struct ata_device *dev)
                ata_dev_printk(dev, KERN_DEBUG,
                               "%s: cfg 49:%04x 82:%04x 83:%04x 84:%04x "
                               "85:%04x 86:%04x 87:%04x 88:%04x\n",
-                              __FUNCTION__,
+                              __func__,
                               id[49], id[82], id[83], id[84],
                               id[85], id[86], id[87], id[88]);
 
@@ -2511,13 +2618,13 @@ int ata_dev_configure(struct ata_device *dev)
 
        if (ata_msg_probe(ap))
                ata_dev_printk(dev, KERN_DEBUG, "%s: EXIT, drv_stat = 0x%x\n",
-                       __FUNCTION__, ata_chk_status(ap));
+                       __func__, ata_chk_status(ap));
        return 0;
 
 err_out_nosup:
        if (ata_msg_probe(ap))
                ata_dev_printk(dev, KERN_DEBUG,
-                              "%s: EXIT, err\n", __FUNCTION__);
+                              "%s: EXIT, err\n", __func__);
        return rc;
 }
 
@@ -2649,7 +2756,7 @@ int ata_bus_probe(struct ata_port *ap)
           specific sequence bass-ackwards so that PDIAG- is released by
           the slave device */
 
-       ata_link_for_each_dev(dev, &ap->link) {
+       ata_link_for_each_dev_reverse(dev, &ap->link) {
                if (tries[dev->devno])
                        dev->class = classes[dev->devno];
 
@@ -3900,17 +4007,6 @@ int ata_std_prereset(struct ata_link *link, unsigned long deadline)
        const unsigned long *timing = sata_ehc_deb_timing(ehc);
        int rc;
 
-       /* handle link resume */
-       if ((ehc->i.flags & ATA_EHI_RESUME_LINK) &&
-           (link->flags & ATA_LFLAG_HRST_TO_RESUME))
-               ehc->i.action |= ATA_EH_HARDRESET;
-
-       /* Some PMPs don't work with only SRST, force hardreset if PMP
-        * is supported.
-        */
-       if (ap->flags & ATA_FLAG_PMP)
-               ehc->i.action |= ATA_EH_HARDRESET;
-
        /* if we're about to do hardreset, nothing more to do */
        if (ehc->i.action & ATA_EH_HARDRESET)
                return 0;
@@ -3924,10 +4020,8 @@ int ata_std_prereset(struct ata_link *link, unsigned long deadline)
                                        "link for reset (errno=%d)\n", rc);
        }
 
-       /* Wait for !BSY if the controller can wait for the first D2H
-        * Reg FIS and we don't know that no device is attached.
-        */
-       if (!(link->flags & ATA_LFLAG_SKIP_D2H_BSY) && !ata_link_offline(link)) {
+       /* wait for !BSY if we don't know that no device is attached */
+       if (!ata_link_offline(link)) {
                rc = ata_wait_ready(ap, deadline);
                if (rc && rc != -ENODEV) {
                        ata_link_printk(link, KERN_WARNING, "device not ready "
@@ -6006,9 +6100,9 @@ void ata_qc_issue(struct ata_queued_cmd *qc)
                if (ata_sg_setup(qc))
                        goto sg_err;
 
-       /* if device is sleeping, schedule softreset and abort the link */
+       /* if device is sleeping, schedule reset and abort the link */
        if (unlikely(qc->dev->flags & ATA_DFLAG_SLEEPING)) {
-               link->eh_info.action |= ATA_EH_SOFTRESET;
+               link->eh_info.action |= ATA_EH_RESET;
                ata_ehi_push_desc(&link->eh_info, "waking up from sleep");
                ata_link_abort(link);
                return;
@@ -6585,7 +6679,7 @@ int ata_host_suspend(struct ata_host *host, pm_message_t mesg)
  */
 void ata_host_resume(struct ata_host *host)
 {
-       ata_host_request_pm(host, PMSG_ON, ATA_EH_SOFTRESET,
+       ata_host_request_pm(host, PMSG_ON, ATA_EH_RESET,
                            ATA_EHI_NO_AUTOPSY | ATA_EHI_QUIET, 0);
        host->dev->power.power_state = PMSG_ON;
 
@@ -6910,8 +7004,6 @@ struct ata_host *ata_host_alloc_pinfo(struct device *dev,
 
                if (!host->ops && (pi->port_ops != &ata_dummy_port_ops))
                        host->ops = pi->port_ops;
-               if (!host->private_data && pi->private_data)
-                       host->private_data = pi->private_data;
        }
 
        return host;
@@ -6935,6 +7027,56 @@ static void ata_host_stop(struct device *gendev, void *res)
                host->ops->host_stop(host);
 }
 
+/**
+ *     ata_finalize_port_ops - finalize ata_port_operations
+ *     @ops: ata_port_operations to finalize
+ *
+ *     An ata_port_operations can inherit from another ops and that
+ *     ops can again inherit from another.  This can go on as many
+ *     times as necessary as long as there is no loop in the
+ *     inheritance chain.
+ *
+ *     Ops tables are finalized when the host is started.  NULL or
+ *     unspecified entries are inherited from the closet ancestor
+ *     which has the method and the entry is populated with it.
+ *     After finalization, the ops table directly points to all the
+ *     methods and ->inherits is no longer necessary and cleared.
+ *
+ *     Using ATA_OP_NULL, inheriting ops can force a method to NULL.
+ *
+ *     LOCKING:
+ *     None.
+ */
+static void ata_finalize_port_ops(struct ata_port_operations *ops)
+{
+       static spinlock_t lock = SPIN_LOCK_UNLOCKED;
+       const struct ata_port_operations *cur;
+       void **begin = (void **)ops;
+       void **end = (void **)&ops->inherits;
+       void **pp;
+
+       if (!ops || !ops->inherits)
+               return;
+
+       spin_lock(&lock);
+
+       for (cur = ops->inherits; cur; cur = cur->inherits) {
+               void **inherit = (void **)cur;
+
+               for (pp = begin; pp < end; pp++, inherit++)
+                       if (!*pp)
+                               *pp = *inherit;
+       }
+
+       for (pp = begin; pp < end; pp++)
+               if (IS_ERR(*pp))
+                       *pp = NULL;
+
+       ops->inherits = NULL;
+
+       spin_unlock(&lock);
+}
+
 /**
  *     ata_host_start - start and freeze ports of an ATA host
  *     @host: ATA host to start ports for
@@ -6960,9 +7102,13 @@ int ata_host_start(struct ata_host *host)
        if (host->flags & ATA_HOST_STARTED)
                return 0;
 
+       ata_finalize_port_ops(host->ops);
+
        for (i = 0; i < host->n_ports; i++) {
                struct ata_port *ap = host->ports[i];
 
+               ata_finalize_port_ops(ap->ops);
+
                if (!host->ops && !ata_port_is_dummy(ap))
                        host->ops = ap->ops;
 
@@ -7024,7 +7170,7 @@ int ata_host_start(struct ata_host *host)
  */
 /* KILLME - the only user left is ipr */
 void ata_host_init(struct ata_host *host, struct device *dev,
-                  unsigned long flags, const struct ata_port_operations *ops)
+                  unsigned long flags, struct ata_port_operations *ops)
 {
        spin_lock_init(&host->lock);
        host->dev = dev;
@@ -7120,9 +7266,8 @@ int ata_host_register(struct ata_host *host, struct scsi_host_template *sht)
                        /* kick EH for boot probing */
                        spin_lock_irqsave(ap->lock, flags);
 
-                       ehi->probe_mask =
-                               (1 << ata_link_max_devices(&ap->link)) - 1;
-                       ehi->action |= ATA_EH_SOFTRESET;
+                       ehi->probe_mask |= ATA_ALL_DEVICES;
+                       ehi->action |= ATA_EH_RESET;
                        ehi->flags |= ATA_EHI_NO_AUTOPSY | ATA_EHI_QUIET;
 
                        ap->pflags &= ~ATA_PFLAG_INITIALIZING;
@@ -7714,7 +7859,7 @@ static unsigned int ata_dummy_qc_issue(struct ata_queued_cmd *qc)
        return AC_ERR_SYSTEM;
 }
 
-const struct ata_port_operations ata_dummy_port_ops = {
+struct ata_port_operations ata_dummy_port_ops = {
        .check_status           = ata_dummy_check_status,
        .check_altstatus        = ata_dummy_check_status,
        .dev_select             = ata_noop_dev_select,
@@ -7742,6 +7887,11 @@ const struct ata_port_info ata_dummy_port_info = {
 EXPORT_SYMBOL_GPL(sata_deb_timing_normal);
 EXPORT_SYMBOL_GPL(sata_deb_timing_hotplug);
 EXPORT_SYMBOL_GPL(sata_deb_timing_long);
+EXPORT_SYMBOL_GPL(ata_base_port_ops);
+EXPORT_SYMBOL_GPL(sata_port_ops);
+EXPORT_SYMBOL_GPL(sata_pmp_port_ops);
+EXPORT_SYMBOL_GPL(ata_sff_port_ops);
+EXPORT_SYMBOL_GPL(ata_bmdma_port_ops);
 EXPORT_SYMBOL_GPL(ata_dummy_port_ops);
 EXPORT_SYMBOL_GPL(ata_dummy_port_info);
 EXPORT_SYMBOL_GPL(ata_std_bios_param);
@@ -7763,6 +7913,7 @@ EXPORT_SYMBOL_GPL(ata_tf_read);
 EXPORT_SYMBOL_GPL(ata_noop_dev_select);
 EXPORT_SYMBOL_GPL(ata_std_dev_select);
 EXPORT_SYMBOL_GPL(sata_print_link_status);
+EXPORT_SYMBOL_GPL(atapi_cmd_type);
 EXPORT_SYMBOL_GPL(ata_tf_to_fis);
 EXPORT_SYMBOL_GPL(ata_tf_from_fis);
 EXPORT_SYMBOL_GPL(ata_pack_xfermask);
@@ -7788,11 +7939,11 @@ EXPORT_SYMBOL_GPL(ata_noop_qc_prep);
 EXPORT_SYMBOL_GPL(ata_bmdma_setup);
 EXPORT_SYMBOL_GPL(ata_bmdma_start);
 EXPORT_SYMBOL_GPL(ata_bmdma_irq_clear);
+EXPORT_SYMBOL_GPL(ata_noop_irq_clear);
 EXPORT_SYMBOL_GPL(ata_bmdma_status);
 EXPORT_SYMBOL_GPL(ata_bmdma_stop);
 EXPORT_SYMBOL_GPL(ata_bmdma_freeze);
 EXPORT_SYMBOL_GPL(ata_bmdma_thaw);
-EXPORT_SYMBOL_GPL(ata_bmdma_drive_eh);
 EXPORT_SYMBOL_GPL(ata_bmdma_error_handler);
 EXPORT_SYMBOL_GPL(ata_bmdma_post_internal_cmd);
 EXPORT_SYMBOL_GPL(ata_port_probe);
@@ -7862,7 +8013,7 @@ EXPORT_SYMBOL_GPL(sata_pmp_qc_defer_cmd_switch);
 EXPORT_SYMBOL_GPL(sata_pmp_std_prereset);
 EXPORT_SYMBOL_GPL(sata_pmp_std_hardreset);
 EXPORT_SYMBOL_GPL(sata_pmp_std_postreset);
-EXPORT_SYMBOL_GPL(sata_pmp_do_eh);
+EXPORT_SYMBOL_GPL(sata_pmp_error_handler);
 
 EXPORT_SYMBOL_GPL(__ata_ehi_push_desc);
 EXPORT_SYMBOL_GPL(ata_ehi_push_desc);
@@ -7881,6 +8032,7 @@ EXPORT_SYMBOL_GPL(ata_eh_thaw_port);
 EXPORT_SYMBOL_GPL(ata_eh_qc_complete);
 EXPORT_SYMBOL_GPL(ata_eh_qc_retry);
 EXPORT_SYMBOL_GPL(ata_do_eh);
+EXPORT_SYMBOL_GPL(ata_std_error_handler);
 EXPORT_SYMBOL_GPL(ata_irq_on);
 EXPORT_SYMBOL_GPL(ata_dev_try_classify);