diff options
Diffstat (limited to 'drivers/ata')
-rw-r--r-- | drivers/ata/sata_sil24.c | 76 |
1 files changed, 56 insertions, 20 deletions
diff --git a/drivers/ata/sata_sil24.c b/drivers/ata/sata_sil24.c index 5f8afa950043..e6fe4c424a62 100644 --- a/drivers/ata/sata_sil24.c +++ b/drivers/ata/sata_sil24.c | |||
@@ -531,16 +531,60 @@ static int sil24_init_port(struct ata_port *ap) | |||
531 | return 0; | 531 | return 0; |
532 | } | 532 | } |
533 | 533 | ||
534 | static int sil24_softreset(struct ata_port *ap, unsigned int *class, | 534 | static int sil24_exec_polled_cmd(struct ata_port *ap, int pmp, |
535 | unsigned long deadline) | 535 | const struct ata_taskfile *tf, |
536 | int is_cmd, u32 ctrl, | ||
537 | unsigned long timeout_msec) | ||
536 | { | 538 | { |
537 | void __iomem *port = ap->ioaddr.cmd_addr; | 539 | void __iomem *port = ap->ioaddr.cmd_addr; |
538 | struct sil24_port_priv *pp = ap->private_data; | 540 | struct sil24_port_priv *pp = ap->private_data; |
539 | struct sil24_prb *prb = &pp->cmd_block[0].ata.prb; | 541 | struct sil24_prb *prb = &pp->cmd_block[0].ata.prb; |
540 | dma_addr_t paddr = pp->cmd_block_dma; | 542 | dma_addr_t paddr = pp->cmd_block_dma; |
543 | u32 irq_enabled, irq_mask, irq_stat; | ||
544 | int rc; | ||
545 | |||
546 | prb->ctrl = cpu_to_le16(ctrl); | ||
547 | ata_tf_to_fis(tf, pmp, is_cmd, prb->fis); | ||
548 | |||
549 | /* temporarily plug completion and error interrupts */ | ||
550 | irq_enabled = readl(port + PORT_IRQ_ENABLE_SET); | ||
551 | writel(PORT_IRQ_COMPLETE | PORT_IRQ_ERROR, port + PORT_IRQ_ENABLE_CLR); | ||
552 | |||
553 | writel((u32)paddr, port + PORT_CMD_ACTIVATE); | ||
554 | writel((u64)paddr >> 32, port + PORT_CMD_ACTIVATE + 4); | ||
555 | |||
556 | irq_mask = (PORT_IRQ_COMPLETE | PORT_IRQ_ERROR) << PORT_IRQ_RAW_SHIFT; | ||
557 | irq_stat = ata_wait_register(port + PORT_IRQ_STAT, irq_mask, 0x0, | ||
558 | 10, timeout_msec); | ||
559 | |||
560 | writel(irq_mask, port + PORT_IRQ_STAT); /* clear IRQs */ | ||
561 | irq_stat >>= PORT_IRQ_RAW_SHIFT; | ||
562 | |||
563 | if (irq_stat & PORT_IRQ_COMPLETE) | ||
564 | rc = 0; | ||
565 | else { | ||
566 | /* force port into known state */ | ||
567 | sil24_init_port(ap); | ||
568 | |||
569 | if (irq_stat & PORT_IRQ_ERROR) | ||
570 | rc = -EIO; | ||
571 | else | ||
572 | rc = -EBUSY; | ||
573 | } | ||
574 | |||
575 | /* restore IRQ enabled */ | ||
576 | writel(irq_enabled, port + PORT_IRQ_ENABLE_SET); | ||
577 | |||
578 | return rc; | ||
579 | } | ||
580 | |||
581 | static int sil24_softreset(struct ata_port *ap, unsigned int *class, | ||
582 | unsigned long deadline) | ||
583 | { | ||
584 | unsigned long timeout_msec = 0; | ||
541 | struct ata_taskfile tf; | 585 | struct ata_taskfile tf; |
542 | u32 mask, irq_stat; | ||
543 | const char *reason; | 586 | const char *reason; |
587 | int rc; | ||
544 | 588 | ||
545 | DPRINTK("ENTER\n"); | 589 | DPRINTK("ENTER\n"); |
546 | 590 | ||
@@ -557,24 +601,16 @@ static int sil24_softreset(struct ata_port *ap, unsigned int *class, | |||
557 | } | 601 | } |
558 | 602 | ||
559 | /* do SRST */ | 603 | /* do SRST */ |
560 | prb->ctrl = cpu_to_le16(PRB_CTRL_SRST); | 604 | if (time_after(deadline, jiffies)) |
561 | prb->fis[1] = 0; /* no PMP yet */ | 605 | timeout_msec = jiffies_to_msecs(deadline - jiffies); |
562 | 606 | ||
563 | writel((u32)paddr, port + PORT_CMD_ACTIVATE); | 607 | ata_tf_init(ap->device, &tf); /* doesn't really matter */ |
564 | writel((u64)paddr >> 32, port + PORT_CMD_ACTIVATE + 4); | 608 | rc = sil24_exec_polled_cmd(ap, 0, &tf, 0, PRB_CTRL_SRST, timeout_msec); |
565 | 609 | if (rc == -EBUSY) { | |
566 | mask = (PORT_IRQ_COMPLETE | PORT_IRQ_ERROR) << PORT_IRQ_RAW_SHIFT; | 610 | reason = "timeout"; |
567 | irq_stat = ata_wait_register(port + PORT_IRQ_STAT, mask, 0x0, | 611 | goto err; |
568 | 100, jiffies_to_msecs(deadline - jiffies)); | 612 | } else if (rc) { |
569 | 613 | reason = "SRST command error"; | |
570 | writel(irq_stat, port + PORT_IRQ_STAT); /* clear IRQs */ | ||
571 | irq_stat >>= PORT_IRQ_RAW_SHIFT; | ||
572 | |||
573 | if (!(irq_stat & PORT_IRQ_COMPLETE)) { | ||
574 | if (irq_stat & PORT_IRQ_ERROR) | ||
575 | reason = "SRST command error"; | ||
576 | else | ||
577 | reason = "timeout"; | ||
578 | goto err; | 614 | goto err; |
579 | } | 615 | } |
580 | 616 | ||