]> pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - drivers/ata/sata_mv.c
pm2fb: change option mode to mode_option
[linux-2.6-omap-h63xx.git] / drivers / ata / sata_mv.c
index 944359256959f6f82c6c31e7cca594d51fdb4cb2..26a6337195b3681587d2025a9a97519f01bf8ca1 100644 (file)
  */
 
 /*
-  sata_mv TODO list:
-
-  1) Needs a full errata audit for all chipsets.  I implemented most
-  of the errata workarounds found in the Marvell vendor driver, but
-  I distinctly remember a couple workarounds (one related to PCI-X)
-  are still needed.
-
-  2) Improve/fix IRQ and error handling sequences.
-
-  3) ATAPI support (Marvell claims the 60xx/70xx chips can do it).
-
-  4) Think about TCQ support here, and for libata in general
-  with controllers that suppport it via host-queuing hardware
-  (a software-only implementation could be a nightmare).
-
-  5) Investigate problems with PCI Message Signalled Interrupts (MSI).
-
-  6) Cache frequently-accessed registers in mv_port_priv to reduce overhead.
-
-  7) Fix/reenable hot plug/unplug (should happen as a side-effect of (2) above).
-
-  8) Develop a low-power-consumption strategy, and implement it.
-
-  9) [Experiment, low priority] See if ATAPI can be supported using
-  "unknown FIS" or "vendor-specific FIS" support, or something creative
-  like that.
-
-  10) [Experiment, low priority] Investigate interrupt coalescing.
-  Quite often, especially with PCI Message Signalled Interrupts (MSI),
-  the overhead reduced by interrupt mitigation is quite often not
-  worth the latency cost.
-
-  11) [Experiment, Marvell value added] Is it possible to use target
-  mode to cross-connect two Linux boxes with Marvell cards?  If so,
-  creating LibATA target mode support would be very interesting.
-
-  Target mode, for those without docs, is the ability to directly
-  connect two SATA controllers.
-
-*/
+ * sata_mv TODO list:
+ *
+ * --> Errata workaround for NCQ device errors.
+ *
+ * --> More errata workarounds for PCI-X.
+ *
+ * --> Complete a full errata audit for all chipsets to identify others.
+ *
+ * --> ATAPI support (Marvell claims the 60xx/70xx chips can do it).
+ *
+ * --> Investigate problems with PCI Message Signalled Interrupts (MSI).
+ *
+ * --> Cache frequently-accessed registers in mv_port_priv to reduce overhead.
+ *
+ * --> Develop a low-power-consumption strategy, and implement it.
+ *
+ * --> [Experiment, low priority] Investigate interrupt coalescing.
+ *       Quite often, especially with PCI Message Signalled Interrupts (MSI),
+ *       the overhead reduced by interrupt mitigation is quite often not
+ *       worth the latency cost.
+ *
+ * --> [Experiment, Marvell value added] Is it possible to use target
+ *       mode to cross-connect two Linux boxes with Marvell cards?  If so,
+ *       creating LibATA target mode support would be very interesting.
+ *
+ *       Target mode, for those without docs, is the ability to directly
+ *       connect two SATA ports.
+ */
 
 #include <linux/kernel.h>
 #include <linux/module.h>
@@ -300,9 +288,7 @@ enum {
        EDMA_ERR_IRQ_TRANSIENT  = EDMA_ERR_LNK_CTRL_RX_0 |
                                  EDMA_ERR_LNK_CTRL_RX_1 |
                                  EDMA_ERR_LNK_CTRL_RX_3 |
-                                 EDMA_ERR_LNK_CTRL_TX |
-                                /* temporary, until we fix hotplug: */
-                                (EDMA_ERR_DEV_DCON | EDMA_ERR_DEV_CON),
+                                 EDMA_ERR_LNK_CTRL_TX,
 
        EDMA_EH_FREEZE          = EDMA_ERR_D_PAR |
                                  EDMA_ERR_PRD_PAR |
@@ -1523,13 +1509,11 @@ static void mv_unexpected_intr(struct ata_port *ap)
 /**
  *      mv_err_intr - Handle error interrupts on the port
  *      @ap: ATA channel to manipulate
- *      @reset_allowed: bool: 0 == don't trigger from reset here
+ *      @qc: affected command (non-NCQ), or NULL
  *
- *      In most cases, just clear the interrupt and move on.  However,
- *      some cases require an eDMA reset, which also performs a COMRESET.
- *      The SERR case requires a clear of pending errors in the SATA
- *      SERROR register.  Finally, if the port disabled DMA,
- *      update our cached copy to match.
+ *      Most cases require a full reset of the chip's state machine,
+ *      which also performs a COMRESET.
+ *      Also, if the port disabled DMA, update our cached copy to match.
  *
  *      LOCKING:
  *      Inherited from caller.
@@ -1540,21 +1524,18 @@ static void mv_err_intr(struct ata_port *ap, struct ata_queued_cmd *qc)
        u32 edma_err_cause, eh_freeze_mask, serr = 0;
        struct mv_port_priv *pp = ap->private_data;
        struct mv_host_priv *hpriv = ap->host->private_data;
-       unsigned int edma_enabled = (pp->pp_flags & MV_PP_FLAG_EDMA_EN);
        unsigned int action = 0, err_mask = 0;
        struct ata_eh_info *ehi = &ap->link.eh_info;
 
        ata_ehi_clear_desc(ehi);
 
-       if (!edma_enabled) {
-               /* just a guess: do we need to do this? should we
-                * expand this, and do it in all cases?
-                */
-               sata_scr_read(&ap->link, SCR_ERROR, &serr);
-               sata_scr_write_flush(&ap->link, SCR_ERROR, serr);
-       }
-
+       /*
+        * Read and clear the err_cause bits.  This won't actually
+        * clear for some errors (eg. SError), but we will be doing
+        * a hard reset in those cases regardless, which *will* clear it.
+        */
        edma_err_cause = readl(port_mmio + EDMA_ERR_IRQ_CAUSE_OFS);
+       writelfl(~edma_err_cause, port_mmio + EDMA_ERR_IRQ_CAUSE_OFS);
 
        ata_ehi_push_desc(ehi, "edma_err_cause=%08x", edma_err_cause);
 
@@ -1594,16 +1575,19 @@ static void mv_err_intr(struct ata_port *ap, struct ata_queued_cmd *qc)
                        ata_ehi_push_desc(ehi, "EDMA self-disable");
                }
                if (edma_err_cause & EDMA_ERR_SERR) {
-                       sata_scr_read(&ap->link, SCR_ERROR, &serr);
-                       sata_scr_write_flush(&ap->link, SCR_ERROR, serr);
-                       err_mask = AC_ERR_ATA_BUS;
+                       /*
+                        * Ensure that we read our own SCR, not a pmp link SCR:
+                        */
+                       ap->ops->scr_read(ap, SCR_ERROR, &serr);
+                       /*
+                        * Don't clear SError here; leave it for libata-eh:
+                        */
+                       ata_ehi_push_desc(ehi, "SError=%08x", serr);
+                       err_mask |= AC_ERR_ATA_BUS;
                        action |= ATA_EH_RESET;
                }
        }
 
-       /* Clear EDMA now that SERR cleanup done */
-       writelfl(~edma_err_cause, port_mmio + EDMA_ERR_IRQ_CAUSE_OFS);
-
        if (!err_mask) {
                err_mask = AC_ERR_OTHER;
                action |= ATA_EH_RESET;
@@ -2126,13 +2110,6 @@ static int mv6_reset_hc(struct mv_host_priv *hpriv, void __iomem *mmio,
                printk(KERN_ERR DRV_NAME ": can't clear global reset\n");
                rc = 1;
        }
-       /*
-        * Temporary: wait 3 seconds before port-probing can happen,
-        * so that we don't miss finding sleepy SilXXXX port-multipliers.
-        * This can go away once hotplug is fully/correctly implemented.
-        */
-       if (rc == 0)
-               msleep(3000);
 done:
        return rc;
 }