summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--drivers/ata/sata_mv.c37
1 files changed, 22 insertions, 15 deletions
diff --git a/drivers/ata/sata_mv.c b/drivers/ata/sata_mv.c
index fb3288bbd9fb..0c25f52249df 100644
--- a/drivers/ata/sata_mv.c
+++ b/drivers/ata/sata_mv.c
@@ -1565,14 +1565,26 @@ static void mv_qc_prep_iie(struct ata_queued_cmd *qc)
*/
static unsigned int mv_qc_issue(struct ata_queued_cmd *qc)
{
+ static int limit_warnings = 10;
struct ata_port *ap = qc->ap;
void __iomem *port_mmio = mv_ap_base(ap);
struct mv_port_priv *pp = ap->private_data;
u32 in_index;
+ unsigned int port_irqs = DONE_IRQ | ERR_IRQ;
+
+ switch (qc->tf.protocol) {
+ case ATA_PROT_DMA:
+ case ATA_PROT_NCQ:
+ mv_start_edma(ap, port_mmio, pp, qc->tf.protocol);
+ pp->req_idx = (pp->req_idx + 1) & MV_MAX_Q_DEPTH_MASK;
+ in_index = pp->req_idx << EDMA_REQ_Q_PTR_SHIFT;
+
+ /* Write the request in pointer to kick the EDMA to life */
+ writelfl((pp->crqb_dma & EDMA_REQ_Q_BASE_LO_MASK) | in_index,
+ port_mmio + EDMA_REQ_Q_IN_PTR_OFS);
+ return 0;
- if ((qc->tf.protocol != ATA_PROT_DMA) &&
- (qc->tf.protocol != ATA_PROT_NCQ)) {
- static int limit_warnings = 10;
+ case ATA_PROT_PIO:
/*
* Errata SATA#16, SATA#24: warn if multiple DRQs expected.
*
@@ -1590,27 +1602,22 @@ static unsigned int mv_qc_issue(struct ata_queued_cmd *qc)
": attempting PIO w/multiple DRQ: "
"this may fail due to h/w errata\n");
}
+ /* drop through */
+ case ATAPI_PROT_PIO:
+ port_irqs = ERR_IRQ; /* leave DONE_IRQ masked for PIO */
+ /* drop through */
+ default:
/*
* We're about to send a non-EDMA capable command to the
* port. Turn off EDMA so there won't be problems accessing
* shadow block, etc registers.
*/
mv_stop_edma(ap);
- mv_enable_port_irqs(ap, ERR_IRQ);
+ mv_edma_cfg(ap, 0, 0);
+ mv_clear_and_enable_port_irqs(ap, mv_ap_base(ap), port_irqs);
mv_pmp_select(ap, qc->dev->link->pmp);
return ata_sff_qc_issue(qc);
}
-
- mv_start_edma(ap, port_mmio, pp, qc->tf.protocol);
-
- pp->req_idx = (pp->req_idx + 1) & MV_MAX_Q_DEPTH_MASK;
- in_index = pp->req_idx << EDMA_REQ_Q_PTR_SHIFT;
-
- /* and write the request in pointer to kick the EDMA to life */
- writelfl((pp->crqb_dma & EDMA_REQ_Q_BASE_LO_MASK) | in_index,
- port_mmio + EDMA_REQ_Q_IN_PTR_OFS);
-
- return 0;
}
static struct ata_queued_cmd *mv_get_active_qc(struct ata_port *ap)