diff options
author | Mark Lord <liml@rtr.ca> | 2008-05-02 02:11:45 -0400 |
---|---|---|
committer | Jeff Garzik <jgarzik@redhat.com> | 2008-05-06 11:37:40 -0400 |
commit | 00f42eabb204c68fa64ef72de834e74aca15c81f (patch) | |
tree | 01a1383b2356c5a03f1af43b960596b923bed2aa | |
parent | dd2890f60f8e15f14c8eb132779b2f15c49d1203 (diff) |
sata_mv rearrange mv_config_fbs
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>
-rw-r--r-- | drivers/ata/sata_mv.c | 60 |
1 files changed, 39 insertions, 21 deletions
diff --git a/drivers/ata/sata_mv.c b/drivers/ata/sata_mv.c index fbccf215d501..e4d411cec79a 100644 --- a/drivers/ata/sata_mv.c +++ b/drivers/ata/sata_mv.c | |||
@@ -366,6 +366,7 @@ enum { | |||
366 | /* Port private flags (pp_flags) */ | 366 | /* Port private flags (pp_flags) */ |
367 | MV_PP_FLAG_EDMA_EN = (1 << 0), /* is EDMA engine enabled? */ | 367 | MV_PP_FLAG_EDMA_EN = (1 << 0), /* is EDMA engine enabled? */ |
368 | MV_PP_FLAG_NCQ_EN = (1 << 1), /* is EDMA set up for NCQ? */ | 368 | MV_PP_FLAG_NCQ_EN = (1 << 1), /* is EDMA set up for NCQ? */ |
369 | MV_PP_FLAG_FBS_EN = (1 << 2), /* is EDMA set up for FBS? */ | ||
369 | }; | 370 | }; |
370 | 371 | ||
371 | #define IS_GEN_I(hpriv) ((hpriv)->hp_flags & MV_HP_GEN_I) | 372 | #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) | |||
1129 | return ATA_DEFER_PORT; | 1130 | return ATA_DEFER_PORT; |
1130 | } | 1131 | } |
1131 | 1132 | ||
1132 | static void mv_config_fbs(void __iomem *port_mmio, int enable_fbs) | 1133 | static void mv_config_fbs(void __iomem *port_mmio, int want_ncq, int want_fbs) |
1133 | { | 1134 | { |
1134 | u32 old_fiscfg, new_fiscfg, old_ltmode, new_ltmode; | 1135 | u32 new_fiscfg, old_fiscfg; |
1135 | /* | 1136 | u32 new_ltmode, old_ltmode; |
1136 | * Various bit settings required for operation | 1137 | u32 new_haltcond, old_haltcond; |
1137 | * in FIS-based switching (fbs) mode on GenIIe: | 1138 | |
1138 | */ | 1139 | old_fiscfg = readl(port_mmio + FISCFG_OFS); |
1139 | old_fiscfg = readl(port_mmio + FISCFG_OFS); | 1140 | old_ltmode = readl(port_mmio + LTMODE_OFS); |
1140 | old_ltmode = readl(port_mmio + LTMODE_OFS); | 1141 | old_haltcond = readl(port_mmio + EDMA_HALTCOND_OFS); |
1141 | if (enable_fbs) { | 1142 | |
1142 | new_fiscfg = old_fiscfg | FISCFG_SINGLE_SYNC; | 1143 | new_fiscfg = old_fiscfg & ~(FISCFG_SINGLE_SYNC | FISCFG_WAIT_DEV_ERR); |
1143 | new_ltmode = old_ltmode | LTMODE_BIT8; | 1144 | new_ltmode = old_ltmode & ~LTMODE_BIT8; |
1144 | } else { /* disable fbs */ | 1145 | new_haltcond = old_haltcond | EDMA_ERR_DEV; |
1145 | new_fiscfg = old_fiscfg & ~FISCFG_SINGLE_SYNC; | 1146 | |
1146 | new_ltmode = old_ltmode & ~LTMODE_BIT8; | 1147 | if (want_fbs) { |
1148 | new_fiscfg = old_fiscfg | FISCFG_SINGLE_SYNC; | ||
1149 | new_ltmode = old_ltmode | LTMODE_BIT8; | ||
1147 | } | 1150 | } |
1151 | |||
1148 | if (new_fiscfg != old_fiscfg) | 1152 | if (new_fiscfg != old_fiscfg) |
1149 | writelfl(new_fiscfg, port_mmio + FISCFG_OFS); | 1153 | writelfl(new_fiscfg, port_mmio + FISCFG_OFS); |
1150 | if (new_ltmode != old_ltmode) | 1154 | if (new_ltmode != old_ltmode) |
1151 | writelfl(new_ltmode, port_mmio + LTMODE_OFS); | 1155 | writelfl(new_ltmode, port_mmio + LTMODE_OFS); |
1156 | if (new_haltcond != old_haltcond) | ||
1157 | writelfl(new_haltcond, port_mmio + EDMA_HALTCOND_OFS); | ||
1152 | } | 1158 | } |
1153 | 1159 | ||
1154 | static void mv_60x1_errata_sata25(struct ata_port *ap, int want_ncq) | 1160 | 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) | |||
1175 | 1181 | ||
1176 | /* set up non-NCQ EDMA configuration */ | 1182 | /* set up non-NCQ EDMA configuration */ |
1177 | cfg = EDMA_CFG_Q_DEPTH; /* always 0x1f for *all* chips */ | 1183 | cfg = EDMA_CFG_Q_DEPTH; /* always 0x1f for *all* chips */ |
1184 | pp->pp_flags &= ~MV_PP_FLAG_FBS_EN; | ||
1178 | 1185 | ||
1179 | if (IS_GEN_I(hpriv)) | 1186 | if (IS_GEN_I(hpriv)) |
1180 | cfg |= (1 << 8); /* enab config burst size mask */ | 1187 | cfg |= (1 << 8); /* enab config burst size mask */ |
@@ -1184,19 +1191,30 @@ static void mv_edma_cfg(struct ata_port *ap, int want_ncq) | |||
1184 | mv_60x1_errata_sata25(ap, want_ncq); | 1191 | mv_60x1_errata_sata25(ap, want_ncq); |
1185 | 1192 | ||
1186 | } else if (IS_GEN_IIE(hpriv)) { | 1193 | } else if (IS_GEN_IIE(hpriv)) { |
1194 | int want_fbs = sata_pmp_attached(ap); | ||
1195 | /* | ||
1196 | * Possible future enhancement: | ||
1197 | * | ||
1198 | * The chip can use FBS with non-NCQ, if we allow it, | ||
1199 | * But first we need to have the error handling in place | ||
1200 | * for this mode (datasheet section 7.3.15.4.2.3). | ||
1201 | * So disallow non-NCQ FBS for now. | ||
1202 | */ | ||
1203 | want_fbs &= want_ncq; | ||
1204 | |||
1205 | mv_config_fbs(port_mmio, want_ncq, want_fbs); | ||
1206 | |||
1207 | if (want_fbs) { | ||
1208 | pp->pp_flags |= MV_PP_FLAG_FBS_EN; | ||
1209 | cfg |= EDMA_CFG_EDMA_FBS; /* FIS-based switching */ | ||
1210 | } | ||
1211 | |||
1187 | cfg |= (1 << 23); /* do not mask PM field in rx'd FIS */ | 1212 | cfg |= (1 << 23); /* do not mask PM field in rx'd FIS */ |
1188 | cfg |= (1 << 22); /* enab 4-entry host queue cache */ | 1213 | cfg |= (1 << 22); /* enab 4-entry host queue cache */ |
1189 | if (HAS_PCI(ap->host)) | 1214 | if (HAS_PCI(ap->host)) |
1190 | cfg |= (1 << 18); /* enab early completion */ | 1215 | cfg |= (1 << 18); /* enab early completion */ |
1191 | if (hpriv->hp_flags & MV_HP_CUT_THROUGH) | 1216 | if (hpriv->hp_flags & MV_HP_CUT_THROUGH) |
1192 | cfg |= (1 << 17); /* enab cut-thru (dis stor&forwrd) */ | 1217 | cfg |= (1 << 17); /* enab cut-thru (dis stor&forwrd) */ |
1193 | |||
1194 | if (want_ncq && sata_pmp_attached(ap)) { | ||
1195 | cfg |= EDMA_CFG_EDMA_FBS; /* FIS-based switching */ | ||
1196 | mv_config_fbs(port_mmio, 1); | ||
1197 | } else { | ||
1198 | mv_config_fbs(port_mmio, 0); | ||
1199 | } | ||
1200 | } | 1218 | } |
1201 | 1219 | ||
1202 | if (want_ncq) { | 1220 | if (want_ncq) { |