|
@@ -1159,16 +1159,31 @@ static void nv_adma_fill_sg(struct ata_queued_cmd *qc, struct nv_adma_cpb *cpb)
|
|
|
cpb->next_aprd = cpu_to_le64(((u64)(pp->aprd_dma + NV_ADMA_SGTBL_SZ * qc->tag)));
|
|
|
}
|
|
|
|
|
|
+static int nv_adma_use_reg_mode(struct ata_queued_cmd *qc)
|
|
|
+{
|
|
|
+ struct nv_adma_port_priv *pp = qc->ap->private_data;
|
|
|
+
|
|
|
+ /* ADMA engine can only be used for non-ATAPI DMA commands,
|
|
|
+ or interrupt-driven no-data commands. */
|
|
|
+ if((pp->flags & NV_ADMA_ATAPI_SETUP_COMPLETE) ||
|
|
|
+ (qc->tf.flags & ATA_TFLAG_POLLING))
|
|
|
+ return 1;
|
|
|
+
|
|
|
+ if((qc->flags & ATA_QCFLAG_DMAMAP) ||
|
|
|
+ (qc->tf.protocol == ATA_PROT_NODATA))
|
|
|
+ return 0;
|
|
|
+
|
|
|
+ return 1;
|
|
|
+}
|
|
|
+
|
|
|
static void nv_adma_qc_prep(struct ata_queued_cmd *qc)
|
|
|
{
|
|
|
struct nv_adma_port_priv *pp = qc->ap->private_data;
|
|
|
struct nv_adma_cpb *cpb = &pp->cpb[qc->tag];
|
|
|
u8 ctl_flags = NV_CPB_CTL_CPB_VALID |
|
|
|
- NV_CPB_CTL_APRD_VALID |
|
|
|
NV_CPB_CTL_IEN;
|
|
|
|
|
|
- if (!(qc->flags & ATA_QCFLAG_DMAMAP) ||
|
|
|
- (pp->flags & NV_ADMA_ATAPI_SETUP_COMPLETE)) {
|
|
|
+ if (nv_adma_use_reg_mode(qc)) {
|
|
|
nv_adma_register_mode(qc->ap);
|
|
|
ata_qc_prep(qc);
|
|
|
return;
|
|
@@ -1188,7 +1203,11 @@ static void nv_adma_qc_prep(struct ata_queued_cmd *qc)
|
|
|
|
|
|
nv_adma_tf_to_cpb(&qc->tf, cpb->tf);
|
|
|
|
|
|
- nv_adma_fill_sg(qc, cpb);
|
|
|
+ if(qc->flags & ATA_QCFLAG_DMAMAP) {
|
|
|
+ nv_adma_fill_sg(qc, cpb);
|
|
|
+ ctl_flags |= NV_CPB_CTL_APRD_VALID;
|
|
|
+ } else
|
|
|
+ memset(&cpb->aprd[0], 0, sizeof(struct nv_adma_prd) * 5);
|
|
|
|
|
|
/* Be paranoid and don't let the device see NV_CPB_CTL_CPB_VALID until we are
|
|
|
finished filling in all of the contents */
|
|
@@ -1203,10 +1222,9 @@ static unsigned int nv_adma_qc_issue(struct ata_queued_cmd *qc)
|
|
|
|
|
|
VPRINTK("ENTER\n");
|
|
|
|
|
|
- if (!(qc->flags & ATA_QCFLAG_DMAMAP) ||
|
|
|
- (pp->flags & NV_ADMA_ATAPI_SETUP_COMPLETE)) {
|
|
|
+ if (nv_adma_use_reg_mode(qc)) {
|
|
|
/* use ATA register mode */
|
|
|
- VPRINTK("no dmamap or ATAPI, using ATA register mode: 0x%lx\n", qc->flags);
|
|
|
+ VPRINTK("using ATA register mode: 0x%lx\n", qc->flags);
|
|
|
nv_adma_register_mode(qc->ap);
|
|
|
return ata_qc_issue_prot(qc);
|
|
|
} else
|