aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/ata/sata_promise.c
diff options
context:
space:
mode:
authorMikael Pettersson <mikpe@it.uu.se>2006-12-06 18:06:51 -0500
committerJeff Garzik <jeff@garzik.org>2006-12-07 07:25:01 -0500
commit25b93d81b9abe3b786bdf3396d728bb13b0a911c (patch)
tree2a24c462ec7fa0b3599926d3187434ea6db41ed5 /drivers/ata/sata_promise.c
parente3472cbe5c10a91c737405cd706142787736392c (diff)
[PATCH] sata_promise: new EH conversion, take 2
This patch converts sata_promise to use new-style libata error handling on Promise SATA chips, for both SATA and PATA ports. * ATA_FLAG_SRST is no longer set * ->phy_reset is no longer set as it is unused when ->error_handler is present, and pdc_sata_phy_reset() has been removed * pdc_freeze() masks interrupts and halts DMA via PDC_CTLSTAT * pdc_thaw() clears interrupt status in PDC_INT_SEQMASK and then unmasks interrupts in PDC_CTLSTAT * pdc_error_handler() reinitialises the port if it isn't frozen, and then invokes ata_do_eh() with standard {s,}ata reset methods * pdc_post_internal_cmd() resets the port in case of errors * the PATA-only 20619 chip continues to use old-style EH: not by necessity but simply because I don't have documentation for it or any way to test it Since the previous version pdc_error_handler() has been rewritten and it now mostly matches ahci and sata_sil24. In case anyone wonders: the call to pdc_reset_port() isn't a heavy-duty reset, it's a light-weight reset to quickly put a port into a sane state. The discussion about the PCI flushes in pdc_freeze() and pdc_thaw() seemed to end with a consensus that the flushes are OK and not obviously redundant, so I decided to keep them for now. This patch was prepared against 2.6.19-git7, but it also applies to 2.6.19 + libata #upstream, with or without the revised sata_promise cleanup patch I recently submitted. This patch does conflict with the #promise-sata-pata patch: this patch removes pdc_sata_phy_reset() while #promise-sata-pata modifies it. The correct patch resolution is to remove the function. Tested on 2037x and 2057x chips, with PATA patches on top and disks on both SATA and PATA ports. Signed-off-by: Mikael Pettersson <mikpe@it.uu.se> Signed-off-by: Jeff Garzik <jeff@garzik.org>
Diffstat (limited to 'drivers/ata/sata_promise.c')
-rw-r--r--drivers/ata/sata_promise.c80
1 files changed, 68 insertions, 12 deletions
diff --git a/drivers/ata/sata_promise.c b/drivers/ata/sata_promise.c
index 6f7bc5b0ef4a..f055874a6ec5 100644
--- a/drivers/ata/sata_promise.c
+++ b/drivers/ata/sata_promise.c
@@ -71,9 +71,12 @@ enum {
71 71
72 PDC_HAS_PATA = (1 << 1), /* PDC20375/20575 has PATA */ 72 PDC_HAS_PATA = (1 << 1), /* PDC20375/20575 has PATA */
73 73
74 /* PDC_CTLSTAT bit definitions */
75 PDC_DMA_ENABLE = (1 << 7),
76 PDC_IRQ_DISABLE = (1 << 10),
74 PDC_RESET = (1 << 11), /* HDMA reset */ 77 PDC_RESET = (1 << 11), /* HDMA reset */
75 78
76 PDC_COMMON_FLAGS = ATA_FLAG_NO_LEGACY | ATA_FLAG_SRST | 79 PDC_COMMON_FLAGS = ATA_FLAG_NO_LEGACY |
77 ATA_FLAG_MMIO | ATA_FLAG_NO_ATAPI | 80 ATA_FLAG_MMIO | ATA_FLAG_NO_ATAPI |
78 ATA_FLAG_PIO_POLLING, 81 ATA_FLAG_PIO_POLLING,
79 82
@@ -99,13 +102,16 @@ static void pdc_eng_timeout(struct ata_port *ap);
99static int pdc_port_start(struct ata_port *ap); 102static int pdc_port_start(struct ata_port *ap);
100static void pdc_port_stop(struct ata_port *ap); 103static void pdc_port_stop(struct ata_port *ap);
101static void pdc_pata_phy_reset(struct ata_port *ap); 104static void pdc_pata_phy_reset(struct ata_port *ap);
102static void pdc_sata_phy_reset(struct ata_port *ap);
103static void pdc_qc_prep(struct ata_queued_cmd *qc); 105static void pdc_qc_prep(struct ata_queued_cmd *qc);
104static void pdc_tf_load_mmio(struct ata_port *ap, const struct ata_taskfile *tf); 106static void pdc_tf_load_mmio(struct ata_port *ap, const struct ata_taskfile *tf);
105static void pdc_exec_command_mmio(struct ata_port *ap, const struct ata_taskfile *tf); 107static void pdc_exec_command_mmio(struct ata_port *ap, const struct ata_taskfile *tf);
106static void pdc_irq_clear(struct ata_port *ap); 108static void pdc_irq_clear(struct ata_port *ap);
107static unsigned int pdc_qc_issue_prot(struct ata_queued_cmd *qc); 109static unsigned int pdc_qc_issue_prot(struct ata_queued_cmd *qc);
108static void pdc_host_stop(struct ata_host *host); 110static void pdc_host_stop(struct ata_host *host);
111static void pdc_freeze(struct ata_port *ap);
112static void pdc_thaw(struct ata_port *ap);
113static void pdc_error_handler(struct ata_port *ap);
114static void pdc_post_internal_cmd(struct ata_queued_cmd *qc);
109 115
110 116
111static struct scsi_host_template pdc_ata_sht = { 117static struct scsi_host_template pdc_ata_sht = {
@@ -134,11 +140,12 @@ static const struct ata_port_operations pdc_sata_ops = {
134 .exec_command = pdc_exec_command_mmio, 140 .exec_command = pdc_exec_command_mmio,
135 .dev_select = ata_std_dev_select, 141 .dev_select = ata_std_dev_select,
136 142
137 .phy_reset = pdc_sata_phy_reset,
138
139 .qc_prep = pdc_qc_prep, 143 .qc_prep = pdc_qc_prep,
140 .qc_issue = pdc_qc_issue_prot, 144 .qc_issue = pdc_qc_issue_prot,
141 .eng_timeout = pdc_eng_timeout, 145 .freeze = pdc_freeze,
146 .thaw = pdc_thaw,
147 .error_handler = pdc_error_handler,
148 .post_internal_cmd = pdc_post_internal_cmd,
142 .data_xfer = ata_mmio_data_xfer, 149 .data_xfer = ata_mmio_data_xfer,
143 .irq_handler = pdc_interrupt, 150 .irq_handler = pdc_interrupt,
144 .irq_clear = pdc_irq_clear, 151 .irq_clear = pdc_irq_clear,
@@ -196,7 +203,7 @@ static const struct ata_port_info pdc_port_info[] = {
196 /* board_20619 */ 203 /* board_20619 */
197 { 204 {
198 .sht = &pdc_ata_sht, 205 .sht = &pdc_ata_sht,
199 .flags = PDC_COMMON_FLAGS | ATA_FLAG_SLAVE_POSS, 206 .flags = PDC_COMMON_FLAGS | ATA_FLAG_SRST | ATA_FLAG_SLAVE_POSS,
200 .pio_mask = 0x1f, /* pio0-4 */ 207 .pio_mask = 0x1f, /* pio0-4 */
201 .mwdma_mask = 0x07, /* mwdma0-2 */ 208 .mwdma_mask = 0x07, /* mwdma0-2 */
202 .udma_mask = 0x7f, /* udma0-6 ; FIXME */ 209 .udma_mask = 0x7f, /* udma0-6 ; FIXME */
@@ -346,12 +353,6 @@ static void pdc_reset_port(struct ata_port *ap)
346 readl(mmio); /* flush */ 353 readl(mmio); /* flush */
347} 354}
348 355
349static void pdc_sata_phy_reset(struct ata_port *ap)
350{
351 pdc_reset_port(ap);
352 sata_phy_reset(ap);
353}
354
355static void pdc_pata_cbl_detect(struct ata_port *ap) 356static void pdc_pata_cbl_detect(struct ata_port *ap)
356{ 357{
357 u8 tmp; 358 u8 tmp;
@@ -419,6 +420,61 @@ static void pdc_qc_prep(struct ata_queued_cmd *qc)
419 } 420 }
420} 421}
421 422
423static void pdc_freeze(struct ata_port *ap)
424{
425 void __iomem *mmio = (void __iomem *) ap->ioaddr.cmd_addr;
426 u32 tmp;
427
428 tmp = readl(mmio + PDC_CTLSTAT);
429 tmp |= PDC_IRQ_DISABLE;
430 tmp &= ~PDC_DMA_ENABLE;
431 writel(tmp, mmio + PDC_CTLSTAT);
432 readl(mmio + PDC_CTLSTAT); /* flush */
433}
434
435static void pdc_thaw(struct ata_port *ap)
436{
437 void __iomem *mmio = (void __iomem *) ap->ioaddr.cmd_addr;
438 u32 tmp;
439
440 /* clear IRQ */
441 readl(mmio + PDC_INT_SEQMASK);
442
443 /* turn IRQ back on */
444 tmp = readl(mmio + PDC_CTLSTAT);
445 tmp &= ~PDC_IRQ_DISABLE;
446 writel(tmp, mmio + PDC_CTLSTAT);
447 readl(mmio + PDC_CTLSTAT); /* flush */
448}
449
450static void pdc_error_handler(struct ata_port *ap)
451{
452 ata_reset_fn_t hardreset;
453
454 if (!(ap->pflags & ATA_PFLAG_FROZEN))
455 pdc_reset_port(ap);
456
457 hardreset = NULL;
458 if (sata_scr_valid(ap))
459 hardreset = sata_std_hardreset;
460
461 /* perform recovery */
462 ata_do_eh(ap, ata_std_prereset, ata_std_softreset, hardreset,
463 ata_std_postreset);
464}
465
466static void pdc_post_internal_cmd(struct ata_queued_cmd *qc)
467{
468 struct ata_port *ap = qc->ap;
469
470 if (qc->flags & ATA_QCFLAG_FAILED)
471 qc->err_mask |= AC_ERR_OTHER;
472
473 /* make DMA engine forget about the failed command */
474 if (qc->err_mask)
475 pdc_reset_port(ap);
476}
477
422static void pdc_eng_timeout(struct ata_port *ap) 478static void pdc_eng_timeout(struct ata_port *ap)
423{ 479{
424 struct ata_host *host = ap->host; 480 struct ata_host *host = ap->host;