Commit 8102ce14 authored by mat.loikkanen@synopsys.com's avatar mat.loikkanen@synopsys.com Committed by Linus Torvalds

[libata] add ->bmdma_{stop,status} hooks

The timeout/error handling path was assuming that the hardware in
question was PCI IDE BMDMA-like, which is incorrect in a few cases.

Turn direct function calls into two new hooks.
parent 9a7a579e
...@@ -138,6 +138,8 @@ static struct ata_port_operations piix_pata_ops = { ...@@ -138,6 +138,8 @@ static struct ata_port_operations piix_pata_ops = {
.bmdma_setup = ata_bmdma_setup, .bmdma_setup = ata_bmdma_setup,
.bmdma_start = ata_bmdma_start, .bmdma_start = ata_bmdma_start,
.bmdma_stop = ata_bmdma_stop,
.bmdma_status = ata_bmdma_status,
.qc_prep = ata_qc_prep, .qc_prep = ata_qc_prep,
.qc_issue = ata_qc_issue_prot, .qc_issue = ata_qc_issue_prot,
...@@ -163,6 +165,8 @@ static struct ata_port_operations piix_sata_ops = { ...@@ -163,6 +165,8 @@ static struct ata_port_operations piix_sata_ops = {
.bmdma_setup = ata_bmdma_setup, .bmdma_setup = ata_bmdma_setup,
.bmdma_start = ata_bmdma_start, .bmdma_start = ata_bmdma_start,
.bmdma_stop = ata_bmdma_stop,
.bmdma_status = ata_bmdma_status,
.qc_prep = ata_qc_prep, .qc_prep = ata_qc_prep,
.qc_issue = ata_qc_issue_prot, .qc_issue = ata_qc_issue_prot,
......
...@@ -2601,10 +2601,10 @@ static void ata_qc_timeout(struct ata_queued_cmd *qc) ...@@ -2601,10 +2601,10 @@ static void ata_qc_timeout(struct ata_queued_cmd *qc)
case ATA_PROT_DMA: case ATA_PROT_DMA:
case ATA_PROT_ATAPI_DMA: case ATA_PROT_ATAPI_DMA:
host_stat = ata_bmdma_status(ap); host_stat = ap->ops->bmdma_status(ap);
/* before we do anything else, clear DMA-Start bit */ /* before we do anything else, clear DMA-Start bit */
ata_bmdma_stop(ap); ap->ops->bmdma_stop(ap);
/* fall through */ /* fall through */
...@@ -2613,7 +2613,7 @@ static void ata_qc_timeout(struct ata_queued_cmd *qc) ...@@ -2613,7 +2613,7 @@ static void ata_qc_timeout(struct ata_queued_cmd *qc)
drv_stat = ata_chk_status(ap); drv_stat = ata_chk_status(ap);
/* ack bmdma irq events */ /* ack bmdma irq events */
ata_bmdma_ack_irq(ap); ap->ops->irq_clear(ap);
printk(KERN_ERR "ata%u: command 0x%x timeout, stat 0x%x host_stat 0x%x\n", printk(KERN_ERR "ata%u: command 0x%x timeout, stat 0x%x host_stat 0x%x\n",
ap->id, qc->tf.command, drv_stat, host_stat); ap->id, qc->tf.command, drv_stat, host_stat);
...@@ -3042,7 +3042,43 @@ void ata_bmdma_setup(struct ata_queued_cmd *qc) ...@@ -3042,7 +3042,43 @@ void ata_bmdma_setup(struct ata_queued_cmd *qc)
void ata_bmdma_irq_clear(struct ata_port *ap) void ata_bmdma_irq_clear(struct ata_port *ap)
{ {
ata_bmdma_ack_irq(ap); if (ap->flags & ATA_FLAG_MMIO) {
void __iomem *mmio = ((void __iomem *) ap->ioaddr.bmdma_addr) + ATA_DMA_STATUS;
writeb(readb(mmio), mmio);
} else {
unsigned long addr = ap->ioaddr.bmdma_addr + ATA_DMA_STATUS;
outb(inb(addr), addr);
}
}
u8 ata_bmdma_status(struct ata_port *ap)
{
u8 host_stat;
if (ap->flags & ATA_FLAG_MMIO) {
void __iomem *mmio = (void __iomem *) ap->ioaddr.bmdma_addr;
host_stat = readb(mmio + ATA_DMA_STATUS);
} else
host_stat = inb(ap->ioaddr.bmdma_addr + ATA_DMA_STATUS);
return host_stat;
}
void ata_bmdma_stop(struct ata_port *ap)
{
if (ap->flags & ATA_FLAG_MMIO) {
void __iomem *mmio = (void __iomem *) ap->ioaddr.bmdma_addr;
/* clear start/stop bit */
writeb(readb(mmio + ATA_DMA_CMD) & ~ATA_DMA_START,
mmio + ATA_DMA_CMD);
} else {
/* clear start/stop bit */
outb(inb(ap->ioaddr.bmdma_addr + ATA_DMA_CMD) & ~ATA_DMA_START,
ap->ioaddr.bmdma_addr + ATA_DMA_CMD);
}
/* one-PIO-cycle guaranteed wait, per spec, for HDMA1:0 transition */
ata_altstatus(ap); /* dummy read */
} }
/** /**
...@@ -3072,7 +3108,7 @@ inline unsigned int ata_host_intr (struct ata_port *ap, ...@@ -3072,7 +3108,7 @@ inline unsigned int ata_host_intr (struct ata_port *ap,
case ATA_PROT_ATAPI_DMA: case ATA_PROT_ATAPI_DMA:
case ATA_PROT_ATAPI: case ATA_PROT_ATAPI:
/* check status of DMA engine */ /* check status of DMA engine */
host_stat = ata_bmdma_status(ap); host_stat = ap->ops->bmdma_status(ap);
VPRINTK("ata%u: host_stat 0x%X\n", ap->id, host_stat); VPRINTK("ata%u: host_stat 0x%X\n", ap->id, host_stat);
/* if it's not our irq... */ /* if it's not our irq... */
...@@ -3080,7 +3116,7 @@ inline unsigned int ata_host_intr (struct ata_port *ap, ...@@ -3080,7 +3116,7 @@ inline unsigned int ata_host_intr (struct ata_port *ap,
goto idle_irq; goto idle_irq;
/* before we do anything else, clear DMA-Start bit */ /* before we do anything else, clear DMA-Start bit */
ata_bmdma_stop(ap); ap->ops->bmdma_stop(ap);
/* fall through */ /* fall through */
...@@ -3099,7 +3135,7 @@ inline unsigned int ata_host_intr (struct ata_port *ap, ...@@ -3099,7 +3135,7 @@ inline unsigned int ata_host_intr (struct ata_port *ap,
ap->id, qc->tf.protocol, status); ap->id, qc->tf.protocol, status);
/* ack bmdma irq events */ /* ack bmdma irq events */
ata_bmdma_ack_irq(ap); ap->ops->irq_clear(ap);
/* complete taskfile transaction */ /* complete taskfile transaction */
ata_qc_complete(qc, status); ata_qc_complete(qc, status);
...@@ -3921,6 +3957,8 @@ EXPORT_SYMBOL_GPL(ata_qc_prep); ...@@ -3921,6 +3957,8 @@ EXPORT_SYMBOL_GPL(ata_qc_prep);
EXPORT_SYMBOL_GPL(ata_bmdma_setup); EXPORT_SYMBOL_GPL(ata_bmdma_setup);
EXPORT_SYMBOL_GPL(ata_bmdma_start); EXPORT_SYMBOL_GPL(ata_bmdma_start);
EXPORT_SYMBOL_GPL(ata_bmdma_irq_clear); EXPORT_SYMBOL_GPL(ata_bmdma_irq_clear);
EXPORT_SYMBOL_GPL(ata_bmdma_status);
EXPORT_SYMBOL_GPL(ata_bmdma_stop);
EXPORT_SYMBOL_GPL(ata_port_probe); EXPORT_SYMBOL_GPL(ata_port_probe);
EXPORT_SYMBOL_GPL(sata_phy_reset); EXPORT_SYMBOL_GPL(sata_phy_reset);
EXPORT_SYMBOL_GPL(__sata_phy_reset); EXPORT_SYMBOL_GPL(__sata_phy_reset);
......
...@@ -217,6 +217,8 @@ static struct ata_port_operations nv_ops = { ...@@ -217,6 +217,8 @@ static struct ata_port_operations nv_ops = {
.phy_reset = sata_phy_reset, .phy_reset = sata_phy_reset,
.bmdma_setup = ata_bmdma_setup, .bmdma_setup = ata_bmdma_setup,
.bmdma_start = ata_bmdma_start, .bmdma_start = ata_bmdma_start,
.bmdma_stop = ata_bmdma_stop,
.bmdma_status = ata_bmdma_status,
.qc_prep = ata_qc_prep, .qc_prep = ata_qc_prep,
.qc_issue = ata_qc_issue_prot, .qc_issue = ata_qc_issue_prot,
.eng_timeout = ata_eng_timeout, .eng_timeout = ata_eng_timeout,
......
...@@ -139,6 +139,8 @@ static struct ata_port_operations sil_ops = { ...@@ -139,6 +139,8 @@ static struct ata_port_operations sil_ops = {
.post_set_mode = sil_post_set_mode, .post_set_mode = sil_post_set_mode,
.bmdma_setup = ata_bmdma_setup, .bmdma_setup = ata_bmdma_setup,
.bmdma_start = ata_bmdma_start, .bmdma_start = ata_bmdma_start,
.bmdma_stop = ata_bmdma_stop,
.bmdma_status = ata_bmdma_status,
.qc_prep = ata_qc_prep, .qc_prep = ata_qc_prep,
.qc_issue = ata_qc_issue_prot, .qc_issue = ata_qc_issue_prot,
.eng_timeout = ata_eng_timeout, .eng_timeout = ata_eng_timeout,
......
...@@ -102,6 +102,8 @@ static struct ata_port_operations sis_ops = { ...@@ -102,6 +102,8 @@ static struct ata_port_operations sis_ops = {
.phy_reset = sata_phy_reset, .phy_reset = sata_phy_reset,
.bmdma_setup = ata_bmdma_setup, .bmdma_setup = ata_bmdma_setup,
.bmdma_start = ata_bmdma_start, .bmdma_start = ata_bmdma_start,
.bmdma_stop = ata_bmdma_stop,
.bmdma_status = ata_bmdma_status,
.qc_prep = ata_qc_prep, .qc_prep = ata_qc_prep,
.qc_issue = ata_qc_issue_prot, .qc_issue = ata_qc_issue_prot,
.eng_timeout = ata_eng_timeout, .eng_timeout = ata_eng_timeout,
......
...@@ -301,6 +301,8 @@ static struct ata_port_operations k2_sata_ops = { ...@@ -301,6 +301,8 @@ static struct ata_port_operations k2_sata_ops = {
.phy_reset = sata_phy_reset, .phy_reset = sata_phy_reset,
.bmdma_setup = k2_bmdma_setup_mmio, .bmdma_setup = k2_bmdma_setup_mmio,
.bmdma_start = k2_bmdma_start_mmio, .bmdma_start = k2_bmdma_start_mmio,
.bmdma_stop = ata_bmdma_stop,
.bmdma_status = ata_bmdma_status,
.qc_prep = ata_qc_prep, .qc_prep = ata_qc_prep,
.qc_issue = ata_qc_issue_prot, .qc_issue = ata_qc_issue_prot,
.eng_timeout = ata_eng_timeout, .eng_timeout = ata_eng_timeout,
......
...@@ -97,6 +97,8 @@ static struct ata_port_operations uli_ops = { ...@@ -97,6 +97,8 @@ static struct ata_port_operations uli_ops = {
.bmdma_setup = ata_bmdma_setup, .bmdma_setup = ata_bmdma_setup,
.bmdma_start = ata_bmdma_start, .bmdma_start = ata_bmdma_start,
.bmdma_stop = ata_bmdma_stop,
.bmdma_status = ata_bmdma_status,
.qc_prep = ata_qc_prep, .qc_prep = ata_qc_prep,
.qc_issue = ata_qc_issue_prot, .qc_issue = ata_qc_issue_prot,
......
...@@ -110,6 +110,9 @@ static struct ata_port_operations svia_sata_ops = { ...@@ -110,6 +110,9 @@ static struct ata_port_operations svia_sata_ops = {
.bmdma_setup = ata_bmdma_setup, .bmdma_setup = ata_bmdma_setup,
.bmdma_start = ata_bmdma_start, .bmdma_start = ata_bmdma_start,
.bmdma_stop = ata_bmdma_stop,
.bmdma_status = ata_bmdma_status,
.qc_prep = ata_qc_prep, .qc_prep = ata_qc_prep,
.qc_issue = ata_qc_issue_prot, .qc_issue = ata_qc_issue_prot,
......
...@@ -217,6 +217,8 @@ static struct ata_port_operations vsc_sata_ops = { ...@@ -217,6 +217,8 @@ static struct ata_port_operations vsc_sata_ops = {
.phy_reset = sata_phy_reset, .phy_reset = sata_phy_reset,
.bmdma_setup = ata_bmdma_setup, .bmdma_setup = ata_bmdma_setup,
.bmdma_start = ata_bmdma_start, .bmdma_start = ata_bmdma_start,
.bmdma_stop = ata_bmdma_stop,
.bmdma_status = ata_bmdma_status,
.qc_prep = ata_qc_prep, .qc_prep = ata_qc_prep,
.qc_issue = ata_qc_issue_prot, .qc_issue = ata_qc_issue_prot,
.eng_timeout = ata_eng_timeout, .eng_timeout = ata_eng_timeout,
......
...@@ -360,6 +360,9 @@ struct ata_port_operations { ...@@ -360,6 +360,9 @@ struct ata_port_operations {
void (*port_stop) (struct ata_port *ap); void (*port_stop) (struct ata_port *ap);
void (*host_stop) (struct ata_host_set *host_set); void (*host_stop) (struct ata_host_set *host_set);
void (*bmdma_stop) (struct ata_port *ap);
u8 (*bmdma_status) (struct ata_port *ap);
}; };
struct ata_port_info { struct ata_port_info {
...@@ -415,6 +418,8 @@ extern void ata_dev_id_string(u16 *id, unsigned char *s, ...@@ -415,6 +418,8 @@ extern void ata_dev_id_string(u16 *id, unsigned char *s,
unsigned int ofs, unsigned int len); unsigned int ofs, unsigned int len);
extern void ata_bmdma_setup (struct ata_queued_cmd *qc); extern void ata_bmdma_setup (struct ata_queued_cmd *qc);
extern void ata_bmdma_start (struct ata_queued_cmd *qc); extern void ata_bmdma_start (struct ata_queued_cmd *qc);
extern void ata_bmdma_stop(struct ata_port *ap);
extern u8 ata_bmdma_status(struct ata_port *ap);
extern void ata_bmdma_irq_clear(struct ata_port *ap); extern void ata_bmdma_irq_clear(struct ata_port *ap);
extern void ata_qc_complete(struct ata_queued_cmd *qc, u8 drv_stat); extern void ata_qc_complete(struct ata_queued_cmd *qc, u8 drv_stat);
extern void ata_eng_timeout(struct ata_port *ap); extern void ata_eng_timeout(struct ata_port *ap);
...@@ -595,46 +600,6 @@ static inline unsigned int sata_dev_present(struct ata_port *ap) ...@@ -595,46 +600,6 @@ static inline unsigned int sata_dev_present(struct ata_port *ap)
return ((scr_read(ap, SCR_STATUS) & 0xf) == 0x3) ? 1 : 0; return ((scr_read(ap, SCR_STATUS) & 0xf) == 0x3) ? 1 : 0;
} }
static inline void ata_bmdma_stop(struct ata_port *ap)
{
if (ap->flags & ATA_FLAG_MMIO) {
void __iomem *mmio = (void __iomem *) ap->ioaddr.bmdma_addr;
/* clear start/stop bit */
writeb(readb(mmio + ATA_DMA_CMD) & ~ATA_DMA_START,
mmio + ATA_DMA_CMD);
} else {
/* clear start/stop bit */
outb(inb(ap->ioaddr.bmdma_addr + ATA_DMA_CMD) & ~ATA_DMA_START,
ap->ioaddr.bmdma_addr + ATA_DMA_CMD);
}
/* one-PIO-cycle guaranteed wait, per spec, for HDMA1:0 transition */
ata_altstatus(ap); /* dummy read */
}
static inline void ata_bmdma_ack_irq(struct ata_port *ap)
{
if (ap->flags & ATA_FLAG_MMIO) {
void __iomem *mmio = ((void __iomem *) ap->ioaddr.bmdma_addr) + ATA_DMA_STATUS;
writeb(readb(mmio), mmio);
} else {
unsigned long addr = ap->ioaddr.bmdma_addr + ATA_DMA_STATUS;
outb(inb(addr), addr);
}
}
static inline u8 ata_bmdma_status(struct ata_port *ap)
{
u8 host_stat;
if (ap->flags & ATA_FLAG_MMIO) {
void __iomem *mmio = (void __iomem *) ap->ioaddr.bmdma_addr;
host_stat = readb(mmio + ATA_DMA_STATUS);
} else
host_stat = inb(ap->ioaddr.bmdma_addr + ATA_DMA_STATUS);
return host_stat;
}
static inline int ata_try_flush_cache(struct ata_device *dev) static inline int ata_try_flush_cache(struct ata_device *dev)
{ {
return ata_id_wcache_enabled(dev->id) || return ata_id_wcache_enabled(dev->id) ||
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment