Merge remote-tracking branch 'remotes/aosp/android-3.0' into develop-3.0
[firefly-linux-kernel-4.4.55.git] / drivers / ata / sata_nv.c
index cb89ef8d99d94468ed2cfba330f19b65d413d524..f173ef3bfc10c1fdc9a4d85794d763df13bd8d7a 100644 (file)
@@ -539,7 +539,7 @@ struct nv_pi_priv {
 static const struct ata_port_info nv_port_info[] = {
        /* generic */
        {
-               .flags          = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY,
+               .flags          = ATA_FLAG_SATA,
                .pio_mask       = NV_PIO_MASK,
                .mwdma_mask     = NV_MWDMA_MASK,
                .udma_mask      = NV_UDMA_MASK,
@@ -548,7 +548,7 @@ static const struct ata_port_info nv_port_info[] = {
        },
        /* nforce2/3 */
        {
-               .flags          = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY,
+               .flags          = ATA_FLAG_SATA,
                .pio_mask       = NV_PIO_MASK,
                .mwdma_mask     = NV_MWDMA_MASK,
                .udma_mask      = NV_UDMA_MASK,
@@ -557,7 +557,7 @@ static const struct ata_port_info nv_port_info[] = {
        },
        /* ck804 */
        {
-               .flags          = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY,
+               .flags          = ATA_FLAG_SATA,
                .pio_mask       = NV_PIO_MASK,
                .mwdma_mask     = NV_MWDMA_MASK,
                .udma_mask      = NV_UDMA_MASK,
@@ -566,8 +566,7 @@ static const struct ata_port_info nv_port_info[] = {
        },
        /* ADMA */
        {
-               .flags          = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
-                                 ATA_FLAG_MMIO | ATA_FLAG_NCQ,
+               .flags          = ATA_FLAG_SATA | ATA_FLAG_NCQ,
                .pio_mask       = NV_PIO_MASK,
                .mwdma_mask     = NV_MWDMA_MASK,
                .udma_mask      = NV_UDMA_MASK,
@@ -576,7 +575,7 @@ static const struct ata_port_info nv_port_info[] = {
        },
        /* MCP5x */
        {
-               .flags          = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY,
+               .flags          = ATA_FLAG_SATA,
                .pio_mask       = NV_PIO_MASK,
                .mwdma_mask     = NV_MWDMA_MASK,
                .udma_mask      = NV_UDMA_MASK,
@@ -585,8 +584,7 @@ static const struct ata_port_info nv_port_info[] = {
        },
        /* SWNCQ */
        {
-               .flags          = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
-                                 ATA_FLAG_NCQ,
+               .flags          = ATA_FLAG_SATA | ATA_FLAG_NCQ,
                .pio_mask       = NV_PIO_MASK,
                .mwdma_mask     = NV_MWDMA_MASK,
                .udma_mask      = NV_UDMA_MASK,
@@ -873,29 +871,11 @@ static int nv_adma_check_cpb(struct ata_port *ap, int cpb_num, int force_err)
                        ata_port_freeze(ap);
                else
                        ata_port_abort(ap);
-               return 1;
+               return -1;
        }
 
-       if (likely(flags & NV_CPB_RESP_DONE)) {
-               struct ata_queued_cmd *qc = ata_qc_from_tag(ap, cpb_num);
-               VPRINTK("CPB flags done, flags=0x%x\n", flags);
-               if (likely(qc)) {
-                       DPRINTK("Completing qc from tag %d\n", cpb_num);
-                       ata_qc_complete(qc);
-               } else {
-                       struct ata_eh_info *ehi = &ap->link.eh_info;
-                       /* Notifier bits set without a command may indicate the drive
-                          is misbehaving. Raise host state machine violation on this
-                          condition. */
-                       ata_port_printk(ap, KERN_ERR,
-                                       "notifier for tag %d with no cmd?\n",
-                                       cpb_num);
-                       ehi->err_mask |= AC_ERR_HSM;
-                       ehi->action |= ATA_EH_RESET;
-                       ata_port_freeze(ap);
-                       return 1;
-               }
-       }
+       if (likely(flags & NV_CPB_RESP_DONE))
+               return 1;
        return 0;
 }
 
@@ -1018,6 +998,7 @@ static irqreturn_t nv_adma_interrupt(int irq, void *dev_instance)
                              NV_ADMA_STAT_CPBERR |
                              NV_ADMA_STAT_CMD_COMPLETE)) {
                        u32 check_commands = notifier_clears[i];
+                       u32 done_mask = 0;
                        int pos, rc;
 
                        if (status & NV_ADMA_STAT_CPBERR) {
@@ -1034,10 +1015,13 @@ static irqreturn_t nv_adma_interrupt(int irq, void *dev_instance)
                                pos--;
                                rc = nv_adma_check_cpb(ap, pos,
                                                notifier_error & (1 << pos));
-                               if (unlikely(rc))
+                               if (rc > 0)
+                                       done_mask |= 1 << pos;
+                               else if (unlikely(rc < 0))
                                        check_commands = 0;
                                check_commands &= ~(1 << pos);
                        }
+                       ata_qc_complete_multiple(ap, ap->qc_active ^ done_mask);
                }
        }
 
@@ -2132,13 +2116,12 @@ static int nv_swncq_sdbfis(struct ata_port *ap)
        struct ata_eh_info *ehi = &ap->link.eh_info;
        u32 sactive;
        u32 done_mask;
-       int i;
        u8 host_stat;
        u8 lack_dhfis = 0;
 
        host_stat = ap->ops->bmdma_status(ap);
        if (unlikely(host_stat & ATA_DMA_ERR)) {
-               /* error when transfering data to/from memory */
+               /* error when transferring data to/from memory */
                ata_ehi_clear_desc(ehi);
                ata_ehi_push_desc(ehi, "BMDMA stat 0x%x", host_stat);
                ehi->err_mask |= AC_ERR_HOST_BUS;
@@ -2152,27 +2135,11 @@ static int nv_swncq_sdbfis(struct ata_port *ap)
        sactive = readl(pp->sactive_block);
        done_mask = pp->qc_active ^ sactive;
 
-       if (unlikely(done_mask & sactive)) {
-               ata_ehi_clear_desc(ehi);
-               ata_ehi_push_desc(ehi, "illegal SWNCQ:qc_active transition"
-                                 "(%08x->%08x)", pp->qc_active, sactive);
-               ehi->err_mask |= AC_ERR_HSM;
-               ehi->action |= ATA_EH_RESET;
-               return -EINVAL;
-       }
-       for (i = 0; i < ATA_MAX_QUEUE; i++) {
-               if (!(done_mask & (1 << i)))
-                       continue;
-
-               qc = ata_qc_from_tag(ap, i);
-               if (qc) {
-                       ata_qc_complete(qc);
-                       pp->qc_active &= ~(1 << i);
-                       pp->dhfis_bits &= ~(1 << i);
-                       pp->dmafis_bits &= ~(1 << i);
-                       pp->sdbfis_bits |= (1 << i);
-               }
-       }
+       pp->qc_active &= ~done_mask;
+       pp->dhfis_bits &= ~done_mask;
+       pp->dmafis_bits &= ~done_mask;
+       pp->sdbfis_bits |= done_mask;
+       ata_qc_complete_multiple(ap, ap->qc_active ^ done_mask);
 
        if (!ap->qc_active) {
                DPRINTK("over\n");