aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/ata/pdc_adma.c82
1 files changed, 67 insertions, 15 deletions
diff --git a/drivers/ata/pdc_adma.c b/drivers/ata/pdc_adma.c
index 5c79271401af..c95c1bf7df37 100644
--- a/drivers/ata/pdc_adma.c
+++ b/drivers/ata/pdc_adma.c
@@ -92,6 +92,8 @@ enum {
92 92
93 /* CPB bits */ 93 /* CPB bits */
94 cDONE = (1 << 0), 94 cDONE = (1 << 0),
95 cATERR = (1 << 3),
96
95 cVLD = (1 << 0), 97 cVLD = (1 << 0),
96 cDAT = (1 << 2), 98 cDAT = (1 << 2),
97 cIEN = (1 << 3), 99 cIEN = (1 << 3),
@@ -131,14 +133,15 @@ static int adma_ata_init_one (struct pci_dev *pdev,
131static int adma_port_start(struct ata_port *ap); 133static int adma_port_start(struct ata_port *ap);
132static void adma_host_stop(struct ata_host *host); 134static void adma_host_stop(struct ata_host *host);
133static void adma_port_stop(struct ata_port *ap); 135static void adma_port_stop(struct ata_port *ap);
134static void adma_phy_reset(struct ata_port *ap);
135static void adma_qc_prep(struct ata_queued_cmd *qc); 136static void adma_qc_prep(struct ata_queued_cmd *qc);
136static unsigned int adma_qc_issue(struct ata_queued_cmd *qc); 137static unsigned int adma_qc_issue(struct ata_queued_cmd *qc);
137static int adma_check_atapi_dma(struct ata_queued_cmd *qc); 138static int adma_check_atapi_dma(struct ata_queued_cmd *qc);
138static void adma_bmdma_stop(struct ata_queued_cmd *qc); 139static void adma_bmdma_stop(struct ata_queued_cmd *qc);
139static u8 adma_bmdma_status(struct ata_port *ap); 140static u8 adma_bmdma_status(struct ata_port *ap);
140static void adma_irq_clear(struct ata_port *ap); 141static void adma_irq_clear(struct ata_port *ap);
141static void adma_eng_timeout(struct ata_port *ap); 142static void adma_freeze(struct ata_port *ap);
143static void adma_thaw(struct ata_port *ap);
144static void adma_error_handler(struct ata_port *ap);
142 145
143static struct scsi_host_template adma_ata_sht = { 146static struct scsi_host_template adma_ata_sht = {
144 .module = THIS_MODULE, 147 .module = THIS_MODULE,
@@ -165,12 +168,13 @@ static const struct ata_port_operations adma_ata_ops = {
165 .exec_command = ata_exec_command, 168 .exec_command = ata_exec_command,
166 .check_status = ata_check_status, 169 .check_status = ata_check_status,
167 .dev_select = ata_std_dev_select, 170 .dev_select = ata_std_dev_select,
168 .phy_reset = adma_phy_reset,
169 .check_atapi_dma = adma_check_atapi_dma, 171 .check_atapi_dma = adma_check_atapi_dma,
170 .data_xfer = ata_data_xfer, 172 .data_xfer = ata_data_xfer,
171 .qc_prep = adma_qc_prep, 173 .qc_prep = adma_qc_prep,
172 .qc_issue = adma_qc_issue, 174 .qc_issue = adma_qc_issue,
173 .eng_timeout = adma_eng_timeout, 175 .freeze = adma_freeze,
176 .thaw = adma_thaw,
177 .error_handler = adma_error_handler,
174 .irq_clear = adma_irq_clear, 178 .irq_clear = adma_irq_clear,
175 .irq_on = ata_irq_on, 179 .irq_on = ata_irq_on,
176 .irq_ack = ata_irq_ack, 180 .irq_ack = ata_irq_ack,
@@ -184,7 +188,7 @@ static const struct ata_port_operations adma_ata_ops = {
184static struct ata_port_info adma_port_info[] = { 188static struct ata_port_info adma_port_info[] = {
185 /* board_1841_idx */ 189 /* board_1841_idx */
186 { 190 {
187 .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST | 191 .flags = ATA_FLAG_SLAVE_POSS |
188 ATA_FLAG_NO_LEGACY | ATA_FLAG_MMIO | 192 ATA_FLAG_NO_LEGACY | ATA_FLAG_MMIO |
189 ATA_FLAG_PIO_POLLING, 193 ATA_FLAG_PIO_POLLING,
190 .pio_mask = 0x10, /* pio4 */ 194 .pio_mask = 0x10, /* pio4 */
@@ -273,24 +277,41 @@ static inline void adma_enter_reg_mode(struct ata_port *ap)
273 readb(chan + ADMA_STATUS); /* flush */ 277 readb(chan + ADMA_STATUS); /* flush */
274} 278}
275 279
276static void adma_phy_reset(struct ata_port *ap) 280static void adma_freeze(struct ata_port *ap)
277{ 281{
278 struct adma_port_priv *pp = ap->private_data; 282 void __iomem *chan = ADMA_PORT_REGS(ap);
283
284 /* mask/clear ATA interrupts */
285 writeb(ATA_NIEN, ap->ioaddr.ctl_addr);
286 ata_check_status(ap);
287
288 /* reset ADMA to idle state */
289 writew(aPIOMD4 | aNIEN | aRSTADM, chan + ADMA_CONTROL);
290 udelay(2);
291 writew(aPIOMD4 | aNIEN, chan + ADMA_CONTROL);
292 udelay(2);
293}
279 294
280 pp->state = adma_state_idle; 295static void adma_thaw(struct ata_port *ap)
296{
281 adma_reinit_engine(ap); 297 adma_reinit_engine(ap);
282 ata_port_probe(ap);
283 ata_bus_reset(ap);
284} 298}
285 299
286static void adma_eng_timeout(struct ata_port *ap) 300static int adma_prereset(struct ata_port *ap, unsigned long deadline)
287{ 301{
288 struct adma_port_priv *pp = ap->private_data; 302 struct adma_port_priv *pp = ap->private_data;
289 303
290 if (pp->state != adma_state_idle) /* healthy paranoia */ 304 if (pp->state != adma_state_idle) /* healthy paranoia */
291 pp->state = adma_state_mmio; 305 pp->state = adma_state_mmio;
292 adma_reinit_engine(ap); 306 adma_reinit_engine(ap);
293 ata_eng_timeout(ap); 307
308 return ata_std_prereset(ap, deadline);
309}
310
311static void adma_error_handler(struct ata_port *ap)
312{
313 ata_do_eh(ap, adma_prereset, ata_std_softreset, NULL,
314 ata_std_postreset);
294} 315}
295 316
296static int adma_fill_sg(struct ata_queued_cmd *qc) 317static int adma_fill_sg(struct ata_queued_cmd *qc)
@@ -466,12 +487,31 @@ static inline unsigned int adma_intr_pkt(struct ata_host *host)
466 continue; 487 continue;
467 qc = ata_qc_from_tag(ap, ap->active_tag); 488 qc = ata_qc_from_tag(ap, ap->active_tag);
468 if (qc && (!(qc->tf.flags & ATA_TFLAG_POLLING))) { 489 if (qc && (!(qc->tf.flags & ATA_TFLAG_POLLING))) {
469 if ((status & (aPERR | aPSD | aUIRQ))) 490 if (status & aPERR)
491 qc->err_mask |= AC_ERR_HOST_BUS;
492 else if ((status & (aPSD | aUIRQ)))
470 qc->err_mask |= AC_ERR_OTHER; 493 qc->err_mask |= AC_ERR_OTHER;
494
495 if (pp->pkt[0] & cATERR)
496 qc->err_mask |= AC_ERR_DEV;
471 else if (pp->pkt[0] != cDONE) 497 else if (pp->pkt[0] != cDONE)
472 qc->err_mask |= AC_ERR_OTHER; 498 qc->err_mask |= AC_ERR_OTHER;
473 499
474 ata_qc_complete(qc); 500 if (!qc->err_mask)
501 ata_qc_complete(qc);
502 else {
503 struct ata_eh_info *ehi = &ap->eh_info;
504 ata_ehi_clear_desc(ehi);
505 ata_ehi_push_desc(ehi,
506 "ADMA-status 0x%02X", status);
507 ata_ehi_push_desc(ehi,
508 "pkt[0] 0x%02X", pp->pkt[0]);
509
510 if (qc->err_mask == AC_ERR_DEV)
511 ata_port_abort(ap);
512 else
513 ata_port_freeze(ap);
514 }
475 } 515 }
476 } 516 }
477 return handled; 517 return handled;
@@ -502,7 +542,19 @@ static inline unsigned int adma_intr_mmio(struct ata_host *host)
502 /* complete taskfile transaction */ 542 /* complete taskfile transaction */
503 pp->state = adma_state_idle; 543 pp->state = adma_state_idle;
504 qc->err_mask |= ac_err_mask(status); 544 qc->err_mask |= ac_err_mask(status);
505 ata_qc_complete(qc); 545 if (!qc->err_mask)
546 ata_qc_complete(qc);
547 else {
548 struct ata_eh_info *ehi = &ap->eh_info;
549 ata_ehi_clear_desc(ehi);
550 ata_ehi_push_desc(ehi,
551 "status 0x%02X", status);
552
553 if (qc->err_mask == AC_ERR_DEV)
554 ata_port_abort(ap);
555 else
556 ata_port_freeze(ap);
557 }
506 handled = 1; 558 handled = 1;
507 } 559 }
508 } 560 }