aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/ata/ahci.c
diff options
context:
space:
mode:
authorTejun Heo <htejun@gmail.com>2006-11-01 04:00:24 -0500
committerJeff Garzik <jeff@garzik.org>2006-12-01 22:41:30 -0500
commitad616ffbda8caf3ce76d2b43027e789d732abf48 (patch)
treebcfccbde197833dd4062564793e8a17ff45837cc /drivers/ata/ahci.c
parentb6103f6d1659e2024776bc759d28613fb36344a8 (diff)
[PATCH] ahci: update ahci-vt8251 reset sequence
ahci-vt8251 * requires hardreset after PHY status change * doesn't clear BSY on signature FIS after hardreset * needs SError cleared for the port to operate after hardreset This patch implements ahci_vt8251_hardreset() and sets ATA_FLAG_HRST_TO_RESUME to handle the above behaviors. This fixes EH including hotplug on vt8251. Signed-off-by: Tejun Heo <htejun@gmail.com> Signed-off-by: Jeff Garzik <jeff@garzik.org>
Diffstat (limited to 'drivers/ata/ahci.c')
-rw-r--r--drivers/ata/ahci.c78
1 files changed, 76 insertions, 2 deletions
diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c
index 413270b2c794..8a1f4f059a43 100644
--- a/drivers/ata/ahci.c
+++ b/drivers/ata/ahci.c
@@ -215,6 +215,7 @@ static u8 ahci_check_status(struct ata_port *ap);
215static void ahci_freeze(struct ata_port *ap); 215static void ahci_freeze(struct ata_port *ap);
216static void ahci_thaw(struct ata_port *ap); 216static void ahci_thaw(struct ata_port *ap);
217static void ahci_error_handler(struct ata_port *ap); 217static void ahci_error_handler(struct ata_port *ap);
218static void ahci_vt8251_error_handler(struct ata_port *ap);
218static void ahci_post_internal_cmd(struct ata_queued_cmd *qc); 219static void ahci_post_internal_cmd(struct ata_queued_cmd *qc);
219static int ahci_port_suspend(struct ata_port *ap, pm_message_t mesg); 220static int ahci_port_suspend(struct ata_port *ap, pm_message_t mesg);
220static int ahci_port_resume(struct ata_port *ap); 221static int ahci_port_resume(struct ata_port *ap);
@@ -274,6 +275,37 @@ static const struct ata_port_operations ahci_ops = {
274 .port_stop = ahci_port_stop, 275 .port_stop = ahci_port_stop,
275}; 276};
276 277
278static const struct ata_port_operations ahci_vt8251_ops = {
279 .port_disable = ata_port_disable,
280
281 .check_status = ahci_check_status,
282 .check_altstatus = ahci_check_status,
283 .dev_select = ata_noop_dev_select,
284
285 .tf_read = ahci_tf_read,
286
287 .qc_prep = ahci_qc_prep,
288 .qc_issue = ahci_qc_issue,
289
290 .irq_handler = ahci_interrupt,
291 .irq_clear = ahci_irq_clear,
292
293 .scr_read = ahci_scr_read,
294 .scr_write = ahci_scr_write,
295
296 .freeze = ahci_freeze,
297 .thaw = ahci_thaw,
298
299 .error_handler = ahci_vt8251_error_handler,
300 .post_internal_cmd = ahci_post_internal_cmd,
301
302 .port_suspend = ahci_port_suspend,
303 .port_resume = ahci_port_resume,
304
305 .port_start = ahci_port_start,
306 .port_stop = ahci_port_stop,
307};
308
277static const struct ata_port_info ahci_port_info[] = { 309static const struct ata_port_info ahci_port_info[] = {
278 /* board_ahci */ 310 /* board_ahci */
279 { 311 {
@@ -290,10 +322,11 @@ static const struct ata_port_info ahci_port_info[] = {
290 .sht = &ahci_sht, 322 .sht = &ahci_sht,
291 .flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY | 323 .flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
292 ATA_FLAG_MMIO | ATA_FLAG_PIO_DMA | 324 ATA_FLAG_MMIO | ATA_FLAG_PIO_DMA |
293 ATA_FLAG_SKIP_D2H_BSY | AHCI_FLAG_NO_NCQ, 325 ATA_FLAG_SKIP_D2H_BSY |
326 ATA_FLAG_HRST_TO_RESUME | AHCI_FLAG_NO_NCQ,
294 .pio_mask = 0x1f, /* pio0-4 */ 327 .pio_mask = 0x1f, /* pio0-4 */
295 .udma_mask = 0x7f, /* udma0-6 ; FIXME */ 328 .udma_mask = 0x7f, /* udma0-6 ; FIXME */
296 .port_ops = &ahci_ops, 329 .port_ops = &ahci_vt8251_ops,
297 }, 330 },
298 /* board_ahci_ign_iferr */ 331 /* board_ahci_ign_iferr */
299 { 332 {
@@ -864,6 +897,31 @@ static int ahci_hardreset(struct ata_port *ap, unsigned int *class)
864 return rc; 897 return rc;
865} 898}
866 899
900static int ahci_vt8251_hardreset(struct ata_port *ap, unsigned int *class)
901{
902 void __iomem *mmio = ap->host->mmio_base;
903 void __iomem *port_mmio = ahci_port_base(mmio, ap->port_no);
904 int rc;
905
906 DPRINTK("ENTER\n");
907
908 ahci_stop_engine(port_mmio);
909
910 rc = sata_port_hardreset(ap, sata_ehc_deb_timing(&ap->eh_context));
911
912 /* vt8251 needs SError cleared for the port to operate */
913 ahci_scr_write(ap, SCR_ERROR, ahci_scr_read(ap, SCR_ERROR));
914
915 ahci_start_engine(port_mmio);
916
917 DPRINTK("EXIT, rc=%d, class=%u\n", rc, *class);
918
919 /* vt8251 doesn't clear BSY on signature FIS reception,
920 * request follow-up softreset.
921 */
922 return rc ?: -EAGAIN;
923}
924
867static void ahci_postreset(struct ata_port *ap, unsigned int *class) 925static void ahci_postreset(struct ata_port *ap, unsigned int *class)
868{ 926{
869 void __iomem *port_mmio = (void __iomem *) ap->ioaddr.cmd_addr; 927 void __iomem *port_mmio = (void __iomem *) ap->ioaddr.cmd_addr;
@@ -1187,6 +1245,22 @@ static void ahci_error_handler(struct ata_port *ap)
1187 ahci_postreset); 1245 ahci_postreset);
1188} 1246}
1189 1247
1248static void ahci_vt8251_error_handler(struct ata_port *ap)
1249{
1250 void __iomem *mmio = ap->host->mmio_base;
1251 void __iomem *port_mmio = ahci_port_base(mmio, ap->port_no);
1252
1253 if (!(ap->pflags & ATA_PFLAG_FROZEN)) {
1254 /* restart engine */
1255 ahci_stop_engine(port_mmio);
1256 ahci_start_engine(port_mmio);
1257 }
1258
1259 /* perform recovery */
1260 ata_do_eh(ap, ata_std_prereset, ahci_softreset, ahci_vt8251_hardreset,
1261 ahci_postreset);
1262}
1263
1190static void ahci_post_internal_cmd(struct ata_queued_cmd *qc) 1264static void ahci_post_internal_cmd(struct ata_queued_cmd *qc)
1191{ 1265{
1192 struct ata_port *ap = qc->ap; 1266 struct ata_port *ap = qc->ap;