SGE_DRD                 = (1 << 29), /* discard data read (/dev/null)
                                                data address ignored */
 
+       SIL24_MAX_CMDS          = 31,
+
        /* board id */
        BID_SIL3124             = 0,
        BID_SIL3132             = 1,
 
        /* host flags */
        SIL24_COMMON_FLAGS      = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
-                                 ATA_FLAG_MMIO | ATA_FLAG_PIO_DMA,
+                                 ATA_FLAG_MMIO | ATA_FLAG_PIO_DMA |
+                                 ATA_FLAG_NCQ,
        SIL24_FLAG_PCIX_IRQ_WOC = (1 << 24), /* IRQ loss errata on PCI-X */
 
        IRQ_STAT_4PORTS         = 0xf,
        .name                   = DRV_NAME,
        .ioctl                  = ata_scsi_ioctl,
        .queuecommand           = ata_scsi_queuecmd,
-       .can_queue              = ATA_DEF_QUEUE,
+       .change_queue_depth     = ata_scsi_change_queue_depth,
+       .can_queue              = SIL24_MAX_CMDS,
        .this_id                = ATA_SHT_THIS_ID,
        .sg_tablesize           = LIBATA_MAX_PRD,
        .cmd_per_lun            = ATA_SHT_CMD_PER_LUN,
        },
 };
 
+static int sil24_tag(int tag)
+{
+       if (unlikely(ata_tag_internal(tag)))
+               return 0;
+       return tag;
+}
+
 static void sil24_dev_config(struct ata_port *ap, struct ata_device *dev)
 {
        void __iomem *port = (void __iomem *)ap->ioaddr.cmd_addr;
 {
        struct ata_port *ap = qc->ap;
        struct sil24_port_priv *pp = ap->private_data;
-       union sil24_cmd_block *cb = pp->cmd_block + qc->tag;
+       union sil24_cmd_block *cb;
        struct sil24_prb *prb;
        struct sil24_sge *sge;
        u16 ctrl = 0;
 
+       cb = &pp->cmd_block[sil24_tag(qc->tag)];
+
        switch (qc->tf.protocol) {
        case ATA_PROT_PIO:
        case ATA_PROT_DMA:
+       case ATA_PROT_NCQ:
        case ATA_PROT_NODATA:
                prb = &cb->ata.prb;
                sge = cb->ata.sge;
 static unsigned int sil24_qc_issue(struct ata_queued_cmd *qc)
 {
        struct ata_port *ap = qc->ap;
-       void __iomem *port = (void __iomem *)ap->ioaddr.cmd_addr;
        struct sil24_port_priv *pp = ap->private_data;
-       dma_addr_t paddr = pp->cmd_block_dma + qc->tag * sizeof(*pp->cmd_block);
+       void __iomem *port = (void __iomem *)ap->ioaddr.cmd_addr;
+       unsigned int tag = sil24_tag(qc->tag);
+       dma_addr_t paddr;
+       void __iomem *activate;
 
-       writel((u32)paddr, port + PORT_CMD_ACTIVATE);
-       writel((u64)paddr >> 32, port + PORT_CMD_ACTIVATE + 4);
+       paddr = pp->cmd_block_dma + tag * sizeof(*pp->cmd_block);
+       activate = port + PORT_CMD_ACTIVATE + tag * 8;
+
+       writel((u32)paddr, activate);
+       writel((u64)paddr >> 32, activate + 4);
 
        return 0;
 }
                /* record error info */
                qc = ata_qc_from_tag(ap, ap->active_tag);
                if (qc) {
-                       int tag = qc->tag;
-                       if (unlikely(ata_tag_internal(tag)))
-                               tag = 0;
                        sil24_update_tf(ap);
                        qc->err_mask |= err_mask;
                } else
                ata_port_abort(ap);
 }
 
+static void sil24_finish_qc(struct ata_queued_cmd *qc)
+{
+       if (qc->flags & ATA_QCFLAG_RESULT_TF)
+               sil24_update_tf(qc->ap);
+}
+
 static inline void sil24_host_intr(struct ata_port *ap)
 {
        void __iomem *port = (void __iomem *)ap->ioaddr.cmd_addr;
-       struct ata_queued_cmd *qc;
-       u32 slot_stat;
+       u32 slot_stat, qc_active;
+       int rc;
 
        slot_stat = readl(port + PORT_SLOT_STAT);
 
        if (ap->flags & SIL24_FLAG_PCIX_IRQ_WOC)
                writel(PORT_IRQ_COMPLETE, port + PORT_IRQ_STAT);
 
-       qc = ata_qc_from_tag(ap, ap->active_tag);
-       if (qc) {
-               if (qc->flags & ATA_QCFLAG_RESULT_TF)
-                       sil24_update_tf(ap);
-               ata_qc_complete(qc);
+       qc_active = slot_stat & ~HOST_SSTAT_ATTN;
+       rc = ata_qc_complete_multiple(ap, qc_active, sil24_finish_qc);
+       if (rc > 0)
+               return;
+       if (rc < 0) {
+               struct ata_eh_info *ehi = &ap->eh_info;
+               ehi->err_mask |= AC_ERR_HSM;
+               ehi->action |= ATA_EH_SOFTRESET;
+               ata_port_freeze(ap);
                return;
        }
 
        if (ata_ratelimit())
                ata_port_printk(ap, KERN_INFO, "spurious interrupt "
-                       "(slot_stat 0x%x active_tag %d)\n",
-                       slot_stat, ap->active_tag);
+                       "(slot_stat 0x%x active_tag %d sactive 0x%x)\n",
+                       slot_stat, ap->active_tag, ap->sactive);
 }
 
 static irqreturn_t sil24_interrupt(int irq, void *dev_instance, struct pt_regs *regs)
 
 static inline void sil24_cblk_free(struct sil24_port_priv *pp, struct device *dev)
 {
-       const size_t cb_size = sizeof(*pp->cmd_block);
+       const size_t cb_size = sizeof(*pp->cmd_block) * SIL24_MAX_CMDS;
 
        dma_free_coherent(dev, cb_size, pp->cmd_block, pp->cmd_block_dma);
 }
        struct device *dev = ap->host_set->dev;
        struct sil24_port_priv *pp;
        union sil24_cmd_block *cb;
-       size_t cb_size = sizeof(*cb);
+       size_t cb_size = sizeof(*cb) * SIL24_MAX_CMDS;
        dma_addr_t cb_dma;
        int rc = -ENOMEM;