sata_mv rearrange mv_config_fbs
authorMark Lord <liml@rtr.ca>
Fri, 2 May 2008 06:11:45 +0000 (02:11 -0400)
committerJeff Garzik <jgarzik@redhat.com>
Tue, 6 May 2008 15:37:40 +0000 (11:37 -0400)
Rearrange mv_config_fbs() to more closely follow the (corrected) datasheet
recommendations for NCQ and FIS-based switching (FBS).

Also, maintain a port flag to let us know when FBS is enabled.
We will make more use of that flag later in this patch series.

Signed-off-by: Mark Lord <mlord@pobox.com>
Signed-off-by: Jeff Garzik <jgarzik@redhat.com>
drivers/ata/sata_mv.c

index fbccf21..e4d411c 100644 (file)
@@ -366,6 +366,7 @@ enum {
        /* Port private flags (pp_flags) */
        MV_PP_FLAG_EDMA_EN      = (1 << 0),     /* is EDMA engine enabled? */
        MV_PP_FLAG_NCQ_EN       = (1 << 1),     /* is EDMA set up for NCQ? */
+       MV_PP_FLAG_FBS_EN       = (1 << 2),     /* is EDMA set up for FBS? */
 };
 
 #define IS_GEN_I(hpriv) ((hpriv)->hp_flags & MV_HP_GEN_I)
@@ -1129,26 +1130,31 @@ static int mv_qc_defer(struct ata_queued_cmd *qc)
        return ATA_DEFER_PORT;
 }
 
-static void mv_config_fbs(void __iomem *port_mmio, int enable_fbs)
+static void mv_config_fbs(void __iomem *port_mmio, int want_ncq, int want_fbs)
 {
-       u32 old_fiscfg, new_fiscfg, old_ltmode, new_ltmode;
-       /*
-        * Various bit settings required for operation
-        * in FIS-based switching (fbs) mode on GenIIe:
-        */
-       old_fiscfg = readl(port_mmio + FISCFG_OFS);
-       old_ltmode = readl(port_mmio + LTMODE_OFS);
-       if (enable_fbs) {
-               new_fiscfg = old_fiscfg |  FISCFG_SINGLE_SYNC;
-               new_ltmode = old_ltmode |  LTMODE_BIT8;
-       } else { /* disable fbs */
-               new_fiscfg = old_fiscfg & ~FISCFG_SINGLE_SYNC;
-               new_ltmode = old_ltmode & ~LTMODE_BIT8;
+       u32 new_fiscfg, old_fiscfg;
+       u32 new_ltmode, old_ltmode;
+       u32 new_haltcond, old_haltcond;
+
+       old_fiscfg   = readl(port_mmio + FISCFG_OFS);
+       old_ltmode   = readl(port_mmio + LTMODE_OFS);
+       old_haltcond = readl(port_mmio + EDMA_HALTCOND_OFS);
+
+       new_fiscfg   = old_fiscfg & ~(FISCFG_SINGLE_SYNC | FISCFG_WAIT_DEV_ERR);
+       new_ltmode   = old_ltmode & ~LTMODE_BIT8;
+       new_haltcond = old_haltcond | EDMA_ERR_DEV;
+
+       if (want_fbs) {
+               new_fiscfg = old_fiscfg | FISCFG_SINGLE_SYNC;
+               new_ltmode = old_ltmode | LTMODE_BIT8;
        }
+
        if (new_fiscfg != old_fiscfg)
                writelfl(new_fiscfg, port_mmio + FISCFG_OFS);
        if (new_ltmode != old_ltmode)
                writelfl(new_ltmode, port_mmio + LTMODE_OFS);
+       if (new_haltcond != old_haltcond)
+               writelfl(new_haltcond, port_mmio + EDMA_HALTCOND_OFS);
 }
 
 static void mv_60x1_errata_sata25(struct ata_port *ap, int want_ncq)
@@ -1175,6 +1181,7 @@ static void mv_edma_cfg(struct ata_port *ap, int want_ncq)
 
        /* set up non-NCQ EDMA configuration */
        cfg = EDMA_CFG_Q_DEPTH;         /* always 0x1f for *all* chips */
+       pp->pp_flags &= ~MV_PP_FLAG_FBS_EN;
 
        if (IS_GEN_I(hpriv))
                cfg |= (1 << 8);        /* enab config burst size mask */
@@ -1184,19 +1191,30 @@ static void mv_edma_cfg(struct ata_port *ap, int want_ncq)
                mv_60x1_errata_sata25(ap, want_ncq);
 
        } else if (IS_GEN_IIE(hpriv)) {
+               int want_fbs = sata_pmp_attached(ap);
+               /*
+                * Possible future enhancement:
+                *
+                * The chip can use FBS with non-NCQ, if we allow it,
+                * But first we need to have the error handling in place
+                * for this mode (datasheet section 7.3.15.4.2.3).
+                * So disallow non-NCQ FBS for now.
+                */
+               want_fbs &= want_ncq;
+
+               mv_config_fbs(port_mmio, want_ncq, want_fbs);
+
+               if (want_fbs) {
+                       pp->pp_flags |= MV_PP_FLAG_FBS_EN;
+                       cfg |= EDMA_CFG_EDMA_FBS; /* FIS-based switching */
+               }
+
                cfg |= (1 << 23);       /* do not mask PM field in rx'd FIS */
                cfg |= (1 << 22);       /* enab 4-entry host queue cache */
                if (HAS_PCI(ap->host))
                        cfg |= (1 << 18);       /* enab early completion */
                if (hpriv->hp_flags & MV_HP_CUT_THROUGH)
                        cfg |= (1 << 17); /* enab cut-thru (dis stor&forwrd) */
-
-               if (want_ncq && sata_pmp_attached(ap)) {
-                       cfg |= EDMA_CFG_EDMA_FBS; /* FIS-based switching */
-                       mv_config_fbs(port_mmio, 1);
-               } else {
-                       mv_config_fbs(port_mmio, 0);
-               }
        }
 
        if (want_ncq) {