Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs-2.6
[safe/jmp/linux-2.6] / drivers / ata / libata-sff.c
index 6a103b3..efa4a18 100644 (file)
 
 #include "libata.h"
 
+static struct workqueue_struct *ata_sff_wq;
+
 const struct ata_port_operations ata_sff_port_ops = {
        .inherits               = &ata_base_port_ops,
 
-       .qc_prep                = ata_sff_qc_prep,
+       .qc_prep                = ata_noop_qc_prep,
        .qc_issue               = ata_sff_qc_issue,
        .qc_fill_rtf            = ata_sff_qc_fill_rtf,
 
@@ -54,7 +56,6 @@ const struct ata_port_operations ata_sff_port_ops = {
        .hardreset              = sata_sff_hardreset,
        .postreset              = ata_sff_postreset,
        .error_handler          = ata_sff_error_handler,
-       .post_internal_cmd      = ata_sff_post_internal_cmd,
 
        .sff_dev_select         = ata_sff_dev_select,
        .sff_check_status       = ata_sff_check_status,
@@ -62,7 +63,6 @@ const struct ata_port_operations ata_sff_port_ops = {
        .sff_tf_read            = ata_sff_tf_read,
        .sff_exec_command       = ata_sff_exec_command,
        .sff_data_xfer          = ata_sff_data_xfer,
-       .sff_irq_clear          = ata_sff_irq_clear,
        .sff_drain_fifo         = ata_sff_drain_fifo,
 
        .lost_interrupt         = ata_sff_lost_interrupt,
@@ -70,149 +70,6 @@ const struct ata_port_operations ata_sff_port_ops = {
 EXPORT_SYMBOL_GPL(ata_sff_port_ops);
 
 /**
- *     ata_fill_sg - Fill PCI IDE PRD table
- *     @qc: Metadata associated with taskfile to be transferred
- *
- *     Fill PCI IDE PRD (scatter-gather) table with segments
- *     associated with the current disk command.
- *
- *     LOCKING:
- *     spin_lock_irqsave(host lock)
- *
- */
-static void ata_fill_sg(struct ata_queued_cmd *qc)
-{
-       struct ata_port *ap = qc->ap;
-       struct scatterlist *sg;
-       unsigned int si, pi;
-
-       pi = 0;
-       for_each_sg(qc->sg, sg, qc->n_elem, si) {
-               u32 addr, offset;
-               u32 sg_len, len;
-
-               /* determine if physical DMA addr spans 64K boundary.
-                * Note h/w doesn't support 64-bit, so we unconditionally
-                * truncate dma_addr_t to u32.
-                */
-               addr = (u32) sg_dma_address(sg);
-               sg_len = sg_dma_len(sg);
-
-               while (sg_len) {
-                       offset = addr & 0xffff;
-                       len = sg_len;
-                       if ((offset + sg_len) > 0x10000)
-                               len = 0x10000 - offset;
-
-                       ap->prd[pi].addr = cpu_to_le32(addr);
-                       ap->prd[pi].flags_len = cpu_to_le32(len & 0xffff);
-                       VPRINTK("PRD[%u] = (0x%X, 0x%X)\n", pi, addr, len);
-
-                       pi++;
-                       sg_len -= len;
-                       addr += len;
-               }
-       }
-
-       ap->prd[pi - 1].flags_len |= cpu_to_le32(ATA_PRD_EOT);
-}
-
-/**
- *     ata_fill_sg_dumb - Fill PCI IDE PRD table
- *     @qc: Metadata associated with taskfile to be transferred
- *
- *     Fill PCI IDE PRD (scatter-gather) table with segments
- *     associated with the current disk command. Perform the fill
- *     so that we avoid writing any length 64K records for
- *     controllers that don't follow the spec.
- *
- *     LOCKING:
- *     spin_lock_irqsave(host lock)
- *
- */
-static void ata_fill_sg_dumb(struct ata_queued_cmd *qc)
-{
-       struct ata_port *ap = qc->ap;
-       struct scatterlist *sg;
-       unsigned int si, pi;
-
-       pi = 0;
-       for_each_sg(qc->sg, sg, qc->n_elem, si) {
-               u32 addr, offset;
-               u32 sg_len, len, blen;
-
-               /* determine if physical DMA addr spans 64K boundary.
-                * Note h/w doesn't support 64-bit, so we unconditionally
-                * truncate dma_addr_t to u32.
-                */
-               addr = (u32) sg_dma_address(sg);
-               sg_len = sg_dma_len(sg);
-
-               while (sg_len) {
-                       offset = addr & 0xffff;
-                       len = sg_len;
-                       if ((offset + sg_len) > 0x10000)
-                               len = 0x10000 - offset;
-
-                       blen = len & 0xffff;
-                       ap->prd[pi].addr = cpu_to_le32(addr);
-                       if (blen == 0) {
-                               /* Some PATA chipsets like the CS5530 can't
-                                  cope with 0x0000 meaning 64K as the spec
-                                  says */
-                               ap->prd[pi].flags_len = cpu_to_le32(0x8000);
-                               blen = 0x8000;
-                               ap->prd[++pi].addr = cpu_to_le32(addr + 0x8000);
-                       }
-                       ap->prd[pi].flags_len = cpu_to_le32(blen);
-                       VPRINTK("PRD[%u] = (0x%X, 0x%X)\n", pi, addr, len);
-
-                       pi++;
-                       sg_len -= len;
-                       addr += len;
-               }
-       }
-
-       ap->prd[pi - 1].flags_len |= cpu_to_le32(ATA_PRD_EOT);
-}
-
-/**
- *     ata_sff_qc_prep - Prepare taskfile for submission
- *     @qc: Metadata associated with taskfile to be prepared
- *
- *     Prepare ATA taskfile for submission.
- *
- *     LOCKING:
- *     spin_lock_irqsave(host lock)
- */
-void ata_sff_qc_prep(struct ata_queued_cmd *qc)
-{
-       if (!(qc->flags & ATA_QCFLAG_DMAMAP))
-               return;
-
-       ata_fill_sg(qc);
-}
-EXPORT_SYMBOL_GPL(ata_sff_qc_prep);
-
-/**
- *     ata_sff_dumb_qc_prep - Prepare taskfile for submission
- *     @qc: Metadata associated with taskfile to be prepared
- *
- *     Prepare ATA taskfile for submission.
- *
- *     LOCKING:
- *     spin_lock_irqsave(host lock)
- */
-void ata_sff_dumb_qc_prep(struct ata_queued_cmd *qc)
-{
-       if (!(qc->flags & ATA_QCFLAG_DMAMAP))
-               return;
-
-       ata_fill_sg_dumb(qc);
-}
-EXPORT_SYMBOL_GPL(ata_sff_dumb_qc_prep);
-
-/**
  *     ata_sff_check_status - Read device status reg & clear interrupt
  *     @ap: port where the device is
  *
@@ -537,33 +394,12 @@ void ata_sff_irq_on(struct ata_port *ap)
                ata_sff_set_devctl(ap, ap->ctl);
        ata_wait_idle(ap);
 
-       ap->ops->sff_irq_clear(ap);
+       if (ap->ops->sff_irq_clear)
+               ap->ops->sff_irq_clear(ap);
 }
 EXPORT_SYMBOL_GPL(ata_sff_irq_on);
 
 /**
- *     ata_sff_irq_clear - Clear PCI IDE BMDMA interrupt.
- *     @ap: Port associated with this ATA transaction.
- *
- *     Clear interrupt and error flags in DMA status register.
- *
- *     May be used as the irq_clear() entry in ata_port_operations.
- *
- *     LOCKING:
- *     spin_lock_irqsave(host lock)
- */
-void ata_sff_irq_clear(struct ata_port *ap)
-{
-       void __iomem *mmio = ap->ioaddr.bmdma_addr;
-
-       if (!mmio)
-               return;
-
-       iowrite8(ioread8(mmio + ATA_DMA_STATUS), mmio + ATA_DMA_STATUS);
-}
-EXPORT_SYMBOL_GPL(ata_sff_irq_clear);
-
-/**
  *     ata_sff_tf_load - send taskfile registers to host controller
  *     @ap: Port to which output is sent
  *     @tf: ATA taskfile register set
@@ -962,11 +798,15 @@ static void atapi_send_cdb(struct ata_port *ap, struct ata_queued_cmd *qc)
        case ATAPI_PROT_NODATA:
                ap->hsm_task_state = HSM_ST_LAST;
                break;
+#ifdef CONFIG_ATA_BMDMA
        case ATAPI_PROT_DMA:
                ap->hsm_task_state = HSM_ST_LAST;
                /* initiate bmdma */
                ap->ops->bmdma_start(qc);
                break;
+#endif /* CONFIG_ATA_BMDMA */
+       default:
+               BUG();
        }
 }
 
@@ -1293,7 +1133,7 @@ fsm_start:
                if (in_wq)
                        spin_unlock_irqrestore(ap->lock, flags);
 
-               /* if polling, ata_pio_task() handles the rest.
+               /* if polling, ata_sff_pio_task() handles the rest.
                 * otherwise, interrupt handler takes over from here.
                 */
                break;
@@ -1458,14 +1298,38 @@ fsm_start:
 }
 EXPORT_SYMBOL_GPL(ata_sff_hsm_move);
 
-void ata_pio_task(struct work_struct *work)
+void ata_sff_queue_pio_task(struct ata_port *ap, unsigned long delay)
+{
+       /* may fail if ata_sff_flush_pio_task() in progress */
+       queue_delayed_work(ata_sff_wq, &ap->sff_pio_task,
+                          msecs_to_jiffies(delay));
+}
+EXPORT_SYMBOL_GPL(ata_sff_queue_pio_task);
+
+void ata_sff_flush_pio_task(struct ata_port *ap)
+{
+       DPRINTK("ENTER\n");
+
+       cancel_rearming_delayed_work(&ap->sff_pio_task);
+       ap->hsm_task_state = HSM_ST_IDLE;
+
+       if (ata_msg_ctl(ap))
+               ata_port_printk(ap, KERN_DEBUG, "%s: EXIT\n", __func__);
+}
+
+static void ata_sff_pio_task(struct work_struct *work)
 {
        struct ata_port *ap =
-               container_of(work, struct ata_port, port_task.work);
-       struct ata_queued_cmd *qc = ap->port_task_data;
+               container_of(work, struct ata_port, sff_pio_task.work);
+       struct ata_queued_cmd *qc;
        u8 status;
        int poll_next;
 
+       /* qc can be NULL if timeout occurred */
+       qc = ata_qc_from_tag(ap, ap->link.active_tag);
+       if (!qc)
+               return;
+
 fsm_start:
        WARN_ON_ONCE(ap->hsm_task_state == HSM_ST_IDLE);
 
@@ -1481,7 +1345,7 @@ fsm_start:
                msleep(2);
                status = ata_sff_busy_wait(ap, ATA_BUSY, 10);
                if (status & ATA_BUSY) {
-                       ata_pio_queue_task(ap, qc, ATA_SHORT_PAUSE);
+                       ata_sff_queue_pio_task(ap, ATA_SHORT_PAUSE);
                        return;
                }
        }
@@ -1497,15 +1361,11 @@ fsm_start:
 }
 
 /**
- *     ata_sff_qc_issue - issue taskfile to device in proto-dependent manner
+ *     ata_sff_qc_issue - issue taskfile to a SFF controller
  *     @qc: command to issue to device
  *
- *     Using various libata functions and hooks, this function
- *     starts an ATA command.  ATA commands are grouped into
- *     classes called "protocols", and issuing each type of protocol
- *     is slightly different.
- *
- *     May be used as the qc_issue() entry in ata_port_operations.
+ *     This function issues a PIO or NODATA command to a SFF
+ *     controller.
  *
  *     LOCKING:
  *     spin_lock_irqsave(host lock)
@@ -1520,23 +1380,8 @@ unsigned int ata_sff_qc_issue(struct ata_queued_cmd *qc)
        /* Use polling pio if the LLD doesn't handle
         * interrupt driven pio and atapi CDB interrupt.
         */
-       if (ap->flags & ATA_FLAG_PIO_POLLING) {
-               switch (qc->tf.protocol) {
-               case ATA_PROT_PIO:
-               case ATA_PROT_NODATA:
-               case ATAPI_PROT_PIO:
-               case ATAPI_PROT_NODATA:
-                       qc->tf.flags |= ATA_TFLAG_POLLING;
-                       break;
-               case ATAPI_PROT_DMA:
-                       if (qc->dev->flags & ATA_DFLAG_CDB_INTR)
-                               /* see ata_dma_blacklisted() */
-                               BUG();
-                       break;
-               default:
-                       break;
-               }
-       }
+       if (ap->flags & ATA_FLAG_PIO_POLLING)
+               qc->tf.flags |= ATA_TFLAG_POLLING;
 
        /* select the device */
        ata_dev_select(ap, qc->dev->devno, 1, 0);
@@ -1551,17 +1396,8 @@ unsigned int ata_sff_qc_issue(struct ata_queued_cmd *qc)
                ap->hsm_task_state = HSM_ST_LAST;
 
                if (qc->tf.flags & ATA_TFLAG_POLLING)
-                       ata_pio_queue_task(ap, qc, 0);
-
-               break;
-
-       case ATA_PROT_DMA:
-               WARN_ON_ONCE(qc->tf.flags & ATA_TFLAG_POLLING);
+                       ata_sff_queue_pio_task(ap, 0);
 
-               ap->ops->sff_tf_load(ap, &qc->tf);  /* load tf registers */
-               ap->ops->bmdma_setup(qc);           /* set up bmdma */
-               ap->ops->bmdma_start(qc);           /* initiate bmdma */
-               ap->hsm_task_state = HSM_ST_LAST;
                break;
 
        case ATA_PROT_PIO:
@@ -1573,20 +1409,21 @@ unsigned int ata_sff_qc_issue(struct ata_queued_cmd *qc)
                if (qc->tf.flags & ATA_TFLAG_WRITE) {
                        /* PIO data out protocol */
                        ap->hsm_task_state = HSM_ST_FIRST;
-                       ata_pio_queue_task(ap, qc, 0);
+                       ata_sff_queue_pio_task(ap, 0);
 
-                       /* always send first data block using
-                        * the ata_pio_task() codepath.
+                       /* always send first data block using the
+                        * ata_sff_pio_task() codepath.
                         */
                } else {
                        /* PIO data in protocol */
                        ap->hsm_task_state = HSM_ST;
 
                        if (qc->tf.flags & ATA_TFLAG_POLLING)
-                               ata_pio_queue_task(ap, qc, 0);
+                               ata_sff_queue_pio_task(ap, 0);
 
-                       /* if polling, ata_pio_task() handles the rest.
-                        * otherwise, interrupt handler takes over from here.
+                       /* if polling, ata_sff_pio_task() handles the
+                        * rest.  otherwise, interrupt handler takes
+                        * over from here.
                         */
                }
 
@@ -1604,19 +1441,7 @@ unsigned int ata_sff_qc_issue(struct ata_queued_cmd *qc)
                /* send cdb by polling if no cdb interrupt */
                if ((!(qc->dev->flags & ATA_DFLAG_CDB_INTR)) ||
                    (qc->tf.flags & ATA_TFLAG_POLLING))
-                       ata_pio_queue_task(ap, qc, 0);
-               break;
-
-       case ATAPI_PROT_DMA:
-               WARN_ON_ONCE(qc->tf.flags & ATA_TFLAG_POLLING);
-
-               ap->ops->sff_tf_load(ap, &qc->tf);  /* load tf registers */
-               ap->ops->bmdma_setup(qc);           /* set up bmdma */
-               ap->hsm_task_state = HSM_ST_FIRST;
-
-               /* send cdb by polling if no cdb interrupt */
-               if (!(qc->dev->flags & ATA_DFLAG_CDB_INTR))
-                       ata_pio_queue_task(ap, qc, 0);
+                       ata_sff_queue_pio_task(ap, 0);
                break;
 
        default:
@@ -1648,27 +1473,27 @@ bool ata_sff_qc_fill_rtf(struct ata_queued_cmd *qc)
 }
 EXPORT_SYMBOL_GPL(ata_sff_qc_fill_rtf);
 
-/**
- *     ata_sff_host_intr - Handle host interrupt for given (port, task)
- *     @ap: Port on which interrupt arrived (possibly...)
- *     @qc: Taskfile currently active in engine
- *
- *     Handle host interrupt for given queued command.  Currently,
- *     only DMA interrupts are handled.  All other commands are
- *     handled via polling with interrupts disabled (nIEN bit).
- *
- *     LOCKING:
- *     spin_lock_irqsave(host lock)
- *
- *     RETURNS:
- *     One if interrupt was handled, zero if not (shared irq).
- */
-unsigned int ata_sff_host_intr(struct ata_port *ap,
-                                     struct ata_queued_cmd *qc)
+static unsigned int ata_sff_idle_irq(struct ata_port *ap)
 {
-       struct ata_eh_info *ehi = &ap->link.eh_info;
-       u8 status, host_stat = 0;
-       bool bmdma_stopped = false;
+       ap->stats.idle_irq++;
+
+#ifdef ATA_IRQ_TRAP
+       if ((ap->stats.idle_irq % 1000) == 0) {
+               ap->ops->sff_check_status(ap);
+               if (ap->ops->sff_irq_clear)
+                       ap->ops->sff_irq_clear(ap);
+               ata_port_printk(ap, KERN_WARNING, "irq trap\n");
+               return 1;
+       }
+#endif
+       return 0;       /* irq not handled */
+}
+
+static unsigned int __ata_sff_port_intr(struct ata_port *ap,
+                                       struct ata_queued_cmd *qc,
+                                       bool hsmv_on_idle)
+{
+       u8 status;
 
        VPRINTK("ata%u: protocol %d task_state %d\n",
                ap->print_id, qc->tf.protocol, ap->hsm_task_state);
@@ -1685,90 +1510,56 @@ unsigned int ata_sff_host_intr(struct ata_port *ap,
                 * need to check ata_is_atapi(qc->tf.protocol) again.
                 */
                if (!(qc->dev->flags & ATA_DFLAG_CDB_INTR))
-                       goto idle_irq;
-               break;
-       case HSM_ST_LAST:
-               if (qc->tf.protocol == ATA_PROT_DMA ||
-                   qc->tf.protocol == ATAPI_PROT_DMA) {
-                       /* check status of DMA engine */
-                       host_stat = ap->ops->bmdma_status(ap);
-                       VPRINTK("ata%u: host_stat 0x%X\n",
-                               ap->print_id, host_stat);
-
-                       /* if it's not our irq... */
-                       if (!(host_stat & ATA_DMA_INTR))
-                               goto idle_irq;
-
-                       /* before we do anything else, clear DMA-Start bit */
-                       ap->ops->bmdma_stop(qc);
-                       bmdma_stopped = true;
-
-                       if (unlikely(host_stat & ATA_DMA_ERR)) {
-                               /* error when transfering data to/from memory */
-                               qc->err_mask |= AC_ERR_HOST_BUS;
-                               ap->hsm_task_state = HSM_ST_ERR;
-                       }
-               }
+                       return ata_sff_idle_irq(ap);
                break;
        case HSM_ST:
+       case HSM_ST_LAST:
                break;
        default:
-               goto idle_irq;
+               return ata_sff_idle_irq(ap);
        }
 
-
        /* check main status, clearing INTRQ if needed */
        status = ata_sff_irq_status(ap);
        if (status & ATA_BUSY) {
-               if (bmdma_stopped) {
+               if (hsmv_on_idle) {
                        /* BMDMA engine is already stopped, we're screwed */
                        qc->err_mask |= AC_ERR_HSM;
                        ap->hsm_task_state = HSM_ST_ERR;
                } else
-                       goto idle_irq;
+                       return ata_sff_idle_irq(ap);
        }
 
        /* clear irq events */
-       ap->ops->sff_irq_clear(ap);
+       if (ap->ops->sff_irq_clear)
+               ap->ops->sff_irq_clear(ap);
 
        ata_sff_hsm_move(ap, qc, status, 0);
 
-       if (unlikely(qc->err_mask) && (qc->tf.protocol == ATA_PROT_DMA ||
-                                      qc->tf.protocol == ATAPI_PROT_DMA))
-               ata_ehi_push_desc(ehi, "BMDMA stat 0x%x", host_stat);
-
        return 1;       /* irq handled */
-
-idle_irq:
-       ap->stats.idle_irq++;
-
-#ifdef ATA_IRQ_TRAP
-       if ((ap->stats.idle_irq % 1000) == 0) {
-               ap->ops->sff_check_status(ap);
-               ap->ops->sff_irq_clear(ap);
-               ata_port_printk(ap, KERN_WARNING, "irq trap\n");
-               return 1;
-       }
-#endif
-       return 0;       /* irq not handled */
 }
-EXPORT_SYMBOL_GPL(ata_sff_host_intr);
 
 /**
- *     ata_sff_interrupt - Default ATA host interrupt handler
- *     @irq: irq line (unused)
- *     @dev_instance: pointer to our ata_host information structure
+ *     ata_sff_port_intr - Handle SFF port interrupt
+ *     @ap: Port on which interrupt arrived (possibly...)
+ *     @qc: Taskfile currently active in engine
  *
- *     Default interrupt handler for PCI IDE devices.  Calls
- *     ata_sff_host_intr() for each port that is not disabled.
+ *     Handle port interrupt for given queued command.
  *
  *     LOCKING:
- *     Obtains host lock during operation.
+ *     spin_lock_irqsave(host lock)
  *
  *     RETURNS:
- *     IRQ_NONE or IRQ_HANDLED.
+ *     One if interrupt was handled, zero if not (shared irq).
  */
-irqreturn_t ata_sff_interrupt(int irq, void *dev_instance)
+unsigned int ata_sff_port_intr(struct ata_port *ap, struct ata_queued_cmd *qc)
+{
+       return __ata_sff_port_intr(ap, qc, false);
+}
+EXPORT_SYMBOL_GPL(ata_sff_port_intr);
+
+static inline irqreturn_t __ata_sff_interrupt(int irq, void *dev_instance,
+       unsigned int (*port_intr)(struct ata_port *, struct ata_queued_cmd *))
 {
        struct ata_host *host = dev_instance;
        bool retried = false;
@@ -1788,7 +1579,7 @@ retry:
                qc = ata_qc_from_tag(ap, ap->link.active_tag);
                if (qc) {
                        if (!(qc->tf.flags & ATA_TFLAG_POLLING))
-                               handled |= ata_sff_host_intr(ap, qc);
+                               handled |= port_intr(ap, qc);
                        else
                                polling |= 1 << i;
                } else
@@ -1815,7 +1606,8 @@ retry:
 
                        if (idle & (1 << i)) {
                                ap->ops->sff_check_status(ap);
-                               ap->ops->sff_irq_clear(ap);
+                               if (ap->ops->sff_irq_clear)
+                                       ap->ops->sff_irq_clear(ap);
                        } else {
                                /* clear INTRQ and check if BUSY cleared */
                                if (!(ap->ops->sff_check_status(ap) & ATA_BUSY))
@@ -1837,16 +1629,35 @@ retry:
 
        return IRQ_RETVAL(handled);
 }
-EXPORT_SYMBOL_GPL(ata_sff_interrupt);
 
 /**
- *     ata_sff_lost_interrupt  -       Check for an apparent lost interrupt
- *     @ap: port that appears to have timed out
+ *     ata_sff_interrupt - Default SFF ATA host interrupt handler
+ *     @irq: irq line (unused)
+ *     @dev_instance: pointer to our ata_host information structure
  *
- *     Called from the libata error handlers when the core code suspects
- *     an interrupt has been lost. If it has complete anything we can and
- *     then return. Interface must support altstatus for this faster
- *     recovery to occur.
+ *     Default interrupt handler for PCI IDE devices.  Calls
+ *     ata_sff_port_intr() for each port that is not disabled.
+ *
+ *     LOCKING:
+ *     Obtains host lock during operation.
+ *
+ *     RETURNS:
+ *     IRQ_NONE or IRQ_HANDLED.
+ */
+irqreturn_t ata_sff_interrupt(int irq, void *dev_instance)
+{
+       return __ata_sff_interrupt(irq, dev_instance, ata_sff_port_intr);
+}
+EXPORT_SYMBOL_GPL(ata_sff_interrupt);
+
+/**
+ *     ata_sff_lost_interrupt  -       Check for an apparent lost interrupt
+ *     @ap: port that appears to have timed out
+ *
+ *     Called from the libata error handlers when the core code suspects
+ *     an interrupt has been lost. If it has complete anything we can and
+ *     then return. Interface must support altstatus for this faster
+ *     recovery to occur.
  *
  *     Locking:
  *     Caller holds host lock
@@ -1874,7 +1685,7 @@ void ata_sff_lost_interrupt(struct ata_port *ap)
                                                                status);
        /* Run the host interrupt logic as if the interrupt had not been
           lost */
-       ata_sff_host_intr(ap, qc);
+       ata_sff_port_intr(ap, qc);
 }
 EXPORT_SYMBOL_GPL(ata_sff_lost_interrupt);
 
@@ -1901,7 +1712,8 @@ void ata_sff_freeze(struct ata_port *ap)
         */
        ap->ops->sff_check_status(ap);
 
-       ap->ops->sff_irq_clear(ap);
+       if (ap->ops->sff_irq_clear)
+               ap->ops->sff_irq_clear(ap);
 }
 EXPORT_SYMBOL_GPL(ata_sff_freeze);
 
@@ -1918,7 +1730,8 @@ void ata_sff_thaw(struct ata_port *ap)
 {
        /* clear & re-enable interrupts */
        ap->ops->sff_check_status(ap);
-       ap->ops->sff_irq_clear(ap);
+       if (ap->ops->sff_irq_clear)
+               ap->ops->sff_irq_clear(ap);
        ata_sff_irq_on(ap);
 }
 EXPORT_SYMBOL_GPL(ata_sff_thaw);
@@ -2334,7 +2147,7 @@ void ata_sff_drain_fifo(struct ata_queued_cmd *qc)
 EXPORT_SYMBOL_GPL(ata_sff_drain_fifo);
 
 /**
- *     ata_sff_error_handler - Stock error handler for BMDMA controller
+ *     ata_sff_error_handler - Stock error handler for SFF controller
  *     @ap: port to handle error for
  *
  *     Stock error handler for SFF controller.  It can handle both
@@ -2351,66 +2164,32 @@ void ata_sff_error_handler(struct ata_port *ap)
        ata_reset_fn_t hardreset = ap->ops->hardreset;
        struct ata_queued_cmd *qc;
        unsigned long flags;
-       bool thaw = false;
 
        qc = __ata_qc_from_tag(ap, ap->link.active_tag);
        if (qc && !(qc->flags & ATA_QCFLAG_FAILED))
                qc = NULL;
 
-       /* reset PIO HSM and stop DMA engine */
        spin_lock_irqsave(ap->lock, flags);
 
-       ap->hsm_task_state = HSM_ST_IDLE;
-
-       if (ap->ioaddr.bmdma_addr &&
-           qc && (qc->tf.protocol == ATA_PROT_DMA ||
-                  qc->tf.protocol == ATAPI_PROT_DMA)) {
-               u8 host_stat;
-
-               host_stat = ap->ops->bmdma_status(ap);
-
-               /* BMDMA controllers indicate host bus error by
-                * setting DMA_ERR bit and timing out.  As it wasn't
-                * really a timeout event, adjust error mask and
-                * cancel frozen state.
-                */
-               if (qc->err_mask == AC_ERR_TIMEOUT
-                                               && (host_stat & ATA_DMA_ERR)) {
-                       qc->err_mask = AC_ERR_HOST_BUS;
-                       thaw = true;
-               }
-
-               ap->ops->bmdma_stop(qc);
-
-               /* if we're gonna thaw, make sure IRQ is clear */
-               if (thaw) {
-                       ap->ops->sff_check_status(ap);
-                       ap->ops->sff_irq_clear(ap);
-
-                       spin_unlock_irqrestore(ap->lock, flags);
-                       ata_eh_thaw_port(ap);
-                       spin_lock_irqsave(ap->lock, flags);
-               }
-       }
-
-       /* We *MUST* do FIFO draining before we issue a reset as several
-        * devices helpfully clear their internal state and will lock solid
-        * if we touch the data port post reset. Pass qc in case anyone wants
-        *  to do different PIO/DMA recovery or has per command fixups
+       /*
+        * We *MUST* do FIFO draining before we issue a reset as
+        * several devices helpfully clear their internal state and
+        * will lock solid if we touch the data port post reset. Pass
+        * qc in case anyone wants to do different PIO/DMA recovery or
+        * has per command fixups
         */
        if (ap->ops->sff_drain_fifo)
                ap->ops->sff_drain_fifo(qc);
 
        spin_unlock_irqrestore(ap->lock, flags);
 
-       /* PIO and DMA engines have been stopped, perform recovery */
-
-       /* Ignore ata_sff_softreset if ctl isn't accessible and
-        * built-in hardresets if SCR access isn't available.
-        */
+       /* ignore ata_sff_softreset if ctl isn't accessible */
        if (softreset == ata_sff_softreset && !ap->ioaddr.ctl_addr)
                softreset = NULL;
-       if (ata_is_builtin_hardreset(hardreset) && !sata_scr_valid(&ap->link))
+
+       /* ignore built-in hardresets if SCR access is not available */
+       if ((hardreset == sata_std_hardreset ||
+            hardreset == sata_sff_hardreset) && !sata_scr_valid(&ap->link))
                hardreset = NULL;
 
        ata_do_eh(ap, ap->ops->prereset, softreset, hardreset,
@@ -2419,29 +2198,6 @@ void ata_sff_error_handler(struct ata_port *ap)
 EXPORT_SYMBOL_GPL(ata_sff_error_handler);
 
 /**
- *     ata_sff_post_internal_cmd - Stock post_internal_cmd for SFF controller
- *     @qc: internal command to clean up
- *
- *     LOCKING:
- *     Kernel thread context (may sleep)
- */
-void ata_sff_post_internal_cmd(struct ata_queued_cmd *qc)
-{
-       struct ata_port *ap = qc->ap;
-       unsigned long flags;
-
-       spin_lock_irqsave(ap->lock, flags);
-
-       ap->hsm_task_state = HSM_ST_IDLE;
-
-       if (ap->ioaddr.bmdma_addr)
-               ap->ops->bmdma_stop(qc);
-
-       spin_unlock_irqrestore(ap->lock, flags);
-}
-EXPORT_SYMBOL_GPL(ata_sff_post_internal_cmd);
-
-/**
  *     ata_sff_std_ports - initialize ioaddr with standard port offsets.
  *     @ioaddr: IO address structure to be initialized
  *
@@ -2563,13 +2319,13 @@ int ata_pci_sff_init_host(struct ata_host *host)
 EXPORT_SYMBOL_GPL(ata_pci_sff_init_host);
 
 /**
- *     ata_pci_sff_prepare_host - helper to prepare native PCI ATA host
+ *     ata_pci_sff_prepare_host - helper to prepare PCI PIO-only SFF ATA host
  *     @pdev: target PCI device
  *     @ppi: array of port_info, must be enough for two ports
  *     @r_host: out argument for the initialized ATA host
  *
- *     Helper to allocate ATA host for @pdev, acquire all native PCI
- *     resources and initialize it accordingly in one go.
+ *     Helper to allocate PIO-only SFF ATA host for @pdev, acquire
+ *     all PCI resources and initialize it accordingly in one go.
  *
  *     LOCKING:
  *     Inherited from calling layer (may sleep).
@@ -2599,9 +2355,6 @@ int ata_pci_sff_prepare_host(struct pci_dev *pdev,
        if (rc)
                goto err_out;
 
-       /* init DMA related stuff */
-       ata_pci_bmdma_init(host);
-
        devres_remove_group(&pdev->dev, NULL);
        *r_host = host;
        return 0;
@@ -2706,8 +2459,21 @@ out:
 }
 EXPORT_SYMBOL_GPL(ata_pci_sff_activate_host);
 
+static const struct ata_port_info *ata_sff_find_valid_pi(
+                                       const struct ata_port_info * const *ppi)
+{
+       int i;
+
+       /* look up the first valid port_info */
+       for (i = 0; i < 2 && ppi[i]; i++)
+               if (ppi[i]->port_ops != &ata_dummy_port_ops)
+                       return ppi[i];
+
+       return NULL;
+}
+
 /**
- *     ata_pci_sff_init_one - Initialize/register PCI IDE host controller
+ *     ata_pci_sff_init_one - Initialize/register PIO-only PCI IDE controller
  *     @pdev: Controller to be initialized
  *     @ppi: array of port_info, must be enough for two ports
  *     @sht: scsi_host_template to use when registering the host
@@ -2716,11 +2482,7 @@ EXPORT_SYMBOL_GPL(ata_pci_sff_activate_host);
  *
  *     This is a helper function which can be called from a driver's
  *     xxx_init_one() probe function if the hardware uses traditional
- *     IDE taskfile registers.
- *
- *     This function calls pci_enable_device(), reserves its register
- *     regions, sets the dma mask, enables bus master mode, and calls
- *     ata_device_add()
+ *     IDE taskfile registers and is PIO only.
  *
  *     ASSUMPTION:
  *     Nobody makes a single channel controller that appears solely as
@@ -2737,20 +2499,13 @@ int ata_pci_sff_init_one(struct pci_dev *pdev,
                 struct scsi_host_template *sht, void *host_priv, int hflag)
 {
        struct device *dev = &pdev->dev;
-       const struct ata_port_info *pi = NULL;
+       const struct ata_port_info *pi;
        struct ata_host *host = NULL;
-       int i, rc;
+       int rc;
 
        DPRINTK("ENTER\n");
 
-       /* look up the first valid port_info */
-       for (i = 0; i < 2 && ppi[i]; i++) {
-               if (ppi[i]->port_ops != &ata_dummy_port_ops) {
-                       pi = ppi[i];
-                       break;
-               }
-       }
-
+       pi = ata_sff_find_valid_pi(ppi);
        if (!pi) {
                dev_printk(KERN_ERR, &pdev->dev,
                           "no valid port_info specified\n");
@@ -2771,7 +2526,6 @@ int ata_pci_sff_init_one(struct pci_dev *pdev,
        host->private_data = host_priv;
        host->flags |= hflag;
 
-       pci_set_master(pdev);
        rc = ata_pci_sff_activate_host(host, ata_sff_interrupt, sht);
 out:
        if (rc == 0)
@@ -2785,9 +2539,22 @@ EXPORT_SYMBOL_GPL(ata_pci_sff_init_one);
 
 #endif /* CONFIG_PCI */
 
+/*
+ *     BMDMA support
+ */
+
+#ifdef CONFIG_ATA_BMDMA
+
 const struct ata_port_operations ata_bmdma_port_ops = {
        .inherits               = &ata_sff_port_ops,
 
+       .error_handler          = ata_bmdma_error_handler,
+       .post_internal_cmd      = ata_bmdma_post_internal_cmd,
+
+       .qc_prep                = ata_bmdma_qc_prep,
+       .qc_issue               = ata_bmdma_qc_issue,
+
+       .sff_irq_clear          = ata_bmdma_irq_clear,
        .bmdma_setup            = ata_bmdma_setup,
        .bmdma_start            = ata_bmdma_start,
        .bmdma_stop             = ata_bmdma_stop,
@@ -2806,6 +2573,382 @@ const struct ata_port_operations ata_bmdma32_port_ops = {
 EXPORT_SYMBOL_GPL(ata_bmdma32_port_ops);
 
 /**
+ *     ata_bmdma_fill_sg - Fill PCI IDE PRD table
+ *     @qc: Metadata associated with taskfile to be transferred
+ *
+ *     Fill PCI IDE PRD (scatter-gather) table with segments
+ *     associated with the current disk command.
+ *
+ *     LOCKING:
+ *     spin_lock_irqsave(host lock)
+ *
+ */
+static void ata_bmdma_fill_sg(struct ata_queued_cmd *qc)
+{
+       struct ata_port *ap = qc->ap;
+       struct ata_bmdma_prd *prd = ap->bmdma_prd;
+       struct scatterlist *sg;
+       unsigned int si, pi;
+
+       pi = 0;
+       for_each_sg(qc->sg, sg, qc->n_elem, si) {
+               u32 addr, offset;
+               u32 sg_len, len;
+
+               /* determine if physical DMA addr spans 64K boundary.
+                * Note h/w doesn't support 64-bit, so we unconditionally
+                * truncate dma_addr_t to u32.
+                */
+               addr = (u32) sg_dma_address(sg);
+               sg_len = sg_dma_len(sg);
+
+               while (sg_len) {
+                       offset = addr & 0xffff;
+                       len = sg_len;
+                       if ((offset + sg_len) > 0x10000)
+                               len = 0x10000 - offset;
+
+                       prd[pi].addr = cpu_to_le32(addr);
+                       prd[pi].flags_len = cpu_to_le32(len & 0xffff);
+                       VPRINTK("PRD[%u] = (0x%X, 0x%X)\n", pi, addr, len);
+
+                       pi++;
+                       sg_len -= len;
+                       addr += len;
+               }
+       }
+
+       prd[pi - 1].flags_len |= cpu_to_le32(ATA_PRD_EOT);
+}
+
+/**
+ *     ata_bmdma_fill_sg_dumb - Fill PCI IDE PRD table
+ *     @qc: Metadata associated with taskfile to be transferred
+ *
+ *     Fill PCI IDE PRD (scatter-gather) table with segments
+ *     associated with the current disk command. Perform the fill
+ *     so that we avoid writing any length 64K records for
+ *     controllers that don't follow the spec.
+ *
+ *     LOCKING:
+ *     spin_lock_irqsave(host lock)
+ *
+ */
+static void ata_bmdma_fill_sg_dumb(struct ata_queued_cmd *qc)
+{
+       struct ata_port *ap = qc->ap;
+       struct ata_bmdma_prd *prd = ap->bmdma_prd;
+       struct scatterlist *sg;
+       unsigned int si, pi;
+
+       pi = 0;
+       for_each_sg(qc->sg, sg, qc->n_elem, si) {
+               u32 addr, offset;
+               u32 sg_len, len, blen;
+
+               /* determine if physical DMA addr spans 64K boundary.
+                * Note h/w doesn't support 64-bit, so we unconditionally
+                * truncate dma_addr_t to u32.
+                */
+               addr = (u32) sg_dma_address(sg);
+               sg_len = sg_dma_len(sg);
+
+               while (sg_len) {
+                       offset = addr & 0xffff;
+                       len = sg_len;
+                       if ((offset + sg_len) > 0x10000)
+                               len = 0x10000 - offset;
+
+                       blen = len & 0xffff;
+                       prd[pi].addr = cpu_to_le32(addr);
+                       if (blen == 0) {
+                               /* Some PATA chipsets like the CS5530 can't
+                                  cope with 0x0000 meaning 64K as the spec
+                                  says */
+                               prd[pi].flags_len = cpu_to_le32(0x8000);
+                               blen = 0x8000;
+                               prd[++pi].addr = cpu_to_le32(addr + 0x8000);
+                       }
+                       prd[pi].flags_len = cpu_to_le32(blen);
+                       VPRINTK("PRD[%u] = (0x%X, 0x%X)\n", pi, addr, len);
+
+                       pi++;
+                       sg_len -= len;
+                       addr += len;
+               }
+       }
+
+       prd[pi - 1].flags_len |= cpu_to_le32(ATA_PRD_EOT);
+}
+
+/**
+ *     ata_bmdma_qc_prep - Prepare taskfile for submission
+ *     @qc: Metadata associated with taskfile to be prepared
+ *
+ *     Prepare ATA taskfile for submission.
+ *
+ *     LOCKING:
+ *     spin_lock_irqsave(host lock)
+ */
+void ata_bmdma_qc_prep(struct ata_queued_cmd *qc)
+{
+       if (!(qc->flags & ATA_QCFLAG_DMAMAP))
+               return;
+
+       ata_bmdma_fill_sg(qc);
+}
+EXPORT_SYMBOL_GPL(ata_bmdma_qc_prep);
+
+/**
+ *     ata_bmdma_dumb_qc_prep - Prepare taskfile for submission
+ *     @qc: Metadata associated with taskfile to be prepared
+ *
+ *     Prepare ATA taskfile for submission.
+ *
+ *     LOCKING:
+ *     spin_lock_irqsave(host lock)
+ */
+void ata_bmdma_dumb_qc_prep(struct ata_queued_cmd *qc)
+{
+       if (!(qc->flags & ATA_QCFLAG_DMAMAP))
+               return;
+
+       ata_bmdma_fill_sg_dumb(qc);
+}
+EXPORT_SYMBOL_GPL(ata_bmdma_dumb_qc_prep);
+
+/**
+ *     ata_bmdma_qc_issue - issue taskfile to a BMDMA controller
+ *     @qc: command to issue to device
+ *
+ *     This function issues a PIO, NODATA or DMA command to a
+ *     SFF/BMDMA controller.  PIO and NODATA are handled by
+ *     ata_sff_qc_issue().
+ *
+ *     LOCKING:
+ *     spin_lock_irqsave(host lock)
+ *
+ *     RETURNS:
+ *     Zero on success, AC_ERR_* mask on failure
+ */
+unsigned int ata_bmdma_qc_issue(struct ata_queued_cmd *qc)
+{
+       struct ata_port *ap = qc->ap;
+
+       /* see ata_dma_blacklisted() */
+       BUG_ON((ap->flags & ATA_FLAG_PIO_POLLING) &&
+              qc->tf.protocol == ATAPI_PROT_DMA);
+
+       /* defer PIO handling to sff_qc_issue */
+       if (!ata_is_dma(qc->tf.protocol))
+               return ata_sff_qc_issue(qc);
+
+       /* select the device */
+       ata_dev_select(ap, qc->dev->devno, 1, 0);
+
+       /* start the command */
+       switch (qc->tf.protocol) {
+       case ATA_PROT_DMA:
+               WARN_ON_ONCE(qc->tf.flags & ATA_TFLAG_POLLING);
+
+               ap->ops->sff_tf_load(ap, &qc->tf);  /* load tf registers */
+               ap->ops->bmdma_setup(qc);           /* set up bmdma */
+               ap->ops->bmdma_start(qc);           /* initiate bmdma */
+               ap->hsm_task_state = HSM_ST_LAST;
+               break;
+
+       case ATAPI_PROT_DMA:
+               WARN_ON_ONCE(qc->tf.flags & ATA_TFLAG_POLLING);
+
+               ap->ops->sff_tf_load(ap, &qc->tf);  /* load tf registers */
+               ap->ops->bmdma_setup(qc);           /* set up bmdma */
+               ap->hsm_task_state = HSM_ST_FIRST;
+
+               /* send cdb by polling if no cdb interrupt */
+               if (!(qc->dev->flags & ATA_DFLAG_CDB_INTR))
+                       ata_sff_queue_pio_task(ap, 0);
+               break;
+
+       default:
+               WARN_ON(1);
+               return AC_ERR_SYSTEM;
+       }
+
+       return 0;
+}
+EXPORT_SYMBOL_GPL(ata_bmdma_qc_issue);
+
+/**
+ *     ata_bmdma_port_intr - Handle BMDMA port interrupt
+ *     @ap: Port on which interrupt arrived (possibly...)
+ *     @qc: Taskfile currently active in engine
+ *
+ *     Handle port interrupt for given queued command.
+ *
+ *     LOCKING:
+ *     spin_lock_irqsave(host lock)
+ *
+ *     RETURNS:
+ *     One if interrupt was handled, zero if not (shared irq).
+ */
+unsigned int ata_bmdma_port_intr(struct ata_port *ap, struct ata_queued_cmd *qc)
+{
+       struct ata_eh_info *ehi = &ap->link.eh_info;
+       u8 host_stat = 0;
+       bool bmdma_stopped = false;
+       unsigned int handled;
+
+       if (ap->hsm_task_state == HSM_ST_LAST && ata_is_dma(qc->tf.protocol)) {
+               /* check status of DMA engine */
+               host_stat = ap->ops->bmdma_status(ap);
+               VPRINTK("ata%u: host_stat 0x%X\n", ap->print_id, host_stat);
+
+               /* if it's not our irq... */
+               if (!(host_stat & ATA_DMA_INTR))
+                       return ata_sff_idle_irq(ap);
+
+               /* before we do anything else, clear DMA-Start bit */
+               ap->ops->bmdma_stop(qc);
+               bmdma_stopped = true;
+
+               if (unlikely(host_stat & ATA_DMA_ERR)) {
+                       /* error when transfering data to/from memory */
+                       qc->err_mask |= AC_ERR_HOST_BUS;
+                       ap->hsm_task_state = HSM_ST_ERR;
+               }
+       }
+
+       handled = __ata_sff_port_intr(ap, qc, bmdma_stopped);
+
+       if (unlikely(qc->err_mask) && ata_is_dma(qc->tf.protocol))
+               ata_ehi_push_desc(ehi, "BMDMA stat 0x%x", host_stat);
+
+       return handled;
+}
+EXPORT_SYMBOL_GPL(ata_bmdma_port_intr);
+
+/**
+ *     ata_bmdma_interrupt - Default BMDMA ATA host interrupt handler
+ *     @irq: irq line (unused)
+ *     @dev_instance: pointer to our ata_host information structure
+ *
+ *     Default interrupt handler for PCI IDE devices.  Calls
+ *     ata_bmdma_port_intr() for each port that is not disabled.
+ *
+ *     LOCKING:
+ *     Obtains host lock during operation.
+ *
+ *     RETURNS:
+ *     IRQ_NONE or IRQ_HANDLED.
+ */
+irqreturn_t ata_bmdma_interrupt(int irq, void *dev_instance)
+{
+       return __ata_sff_interrupt(irq, dev_instance, ata_bmdma_port_intr);
+}
+EXPORT_SYMBOL_GPL(ata_bmdma_interrupt);
+
+/**
+ *     ata_bmdma_error_handler - Stock error handler for BMDMA controller
+ *     @ap: port to handle error for
+ *
+ *     Stock error handler for BMDMA controller.  It can handle both
+ *     PATA and SATA controllers.  Most BMDMA controllers should be
+ *     able to use this EH as-is or with some added handling before
+ *     and after.
+ *
+ *     LOCKING:
+ *     Kernel thread context (may sleep)
+ */
+void ata_bmdma_error_handler(struct ata_port *ap)
+{
+       struct ata_queued_cmd *qc;
+       unsigned long flags;
+       bool thaw = false;
+
+       qc = __ata_qc_from_tag(ap, ap->link.active_tag);
+       if (qc && !(qc->flags & ATA_QCFLAG_FAILED))
+               qc = NULL;
+
+       /* reset PIO HSM and stop DMA engine */
+       spin_lock_irqsave(ap->lock, flags);
+
+       if (qc && ata_is_dma(qc->tf.protocol)) {
+               u8 host_stat;
+
+               host_stat = ap->ops->bmdma_status(ap);
+
+               /* BMDMA controllers indicate host bus error by
+                * setting DMA_ERR bit and timing out.  As it wasn't
+                * really a timeout event, adjust error mask and
+                * cancel frozen state.
+                */
+               if (qc->err_mask == AC_ERR_TIMEOUT && (host_stat & ATA_DMA_ERR)) {
+                       qc->err_mask = AC_ERR_HOST_BUS;
+                       thaw = true;
+               }
+
+               ap->ops->bmdma_stop(qc);
+
+               /* if we're gonna thaw, make sure IRQ is clear */
+               if (thaw) {
+                       ap->ops->sff_check_status(ap);
+                       if (ap->ops->sff_irq_clear)
+                               ap->ops->sff_irq_clear(ap);
+               }
+       }
+
+       spin_unlock_irqrestore(ap->lock, flags);
+
+       if (thaw)
+               ata_eh_thaw_port(ap);
+
+       ata_sff_error_handler(ap);
+}
+EXPORT_SYMBOL_GPL(ata_bmdma_error_handler);
+
+/**
+ *     ata_bmdma_post_internal_cmd - Stock post_internal_cmd for BMDMA
+ *     @qc: internal command to clean up
+ *
+ *     LOCKING:
+ *     Kernel thread context (may sleep)
+ */
+void ata_bmdma_post_internal_cmd(struct ata_queued_cmd *qc)
+{
+       struct ata_port *ap = qc->ap;
+       unsigned long flags;
+
+       if (ata_is_dma(qc->tf.protocol)) {
+               spin_lock_irqsave(ap->lock, flags);
+               ap->ops->bmdma_stop(qc);
+               spin_unlock_irqrestore(ap->lock, flags);
+       }
+}
+EXPORT_SYMBOL_GPL(ata_bmdma_post_internal_cmd);
+
+/**
+ *     ata_bmdma_irq_clear - Clear PCI IDE BMDMA interrupt.
+ *     @ap: Port associated with this ATA transaction.
+ *
+ *     Clear interrupt and error flags in DMA status register.
+ *
+ *     May be used as the irq_clear() entry in ata_port_operations.
+ *
+ *     LOCKING:
+ *     spin_lock_irqsave(host lock)
+ */
+void ata_bmdma_irq_clear(struct ata_port *ap)
+{
+       void __iomem *mmio = ap->ioaddr.bmdma_addr;
+
+       if (!mmio)
+               return;
+
+       iowrite8(ioread8(mmio + ATA_DMA_STATUS), mmio + ATA_DMA_STATUS);
+}
+EXPORT_SYMBOL_GPL(ata_bmdma_irq_clear);
+
+/**
  *     ata_bmdma_setup - Set up PCI IDE BMDMA transaction
  *     @qc: Info associated with this ATA transaction.
  *
@@ -2820,7 +2963,7 @@ void ata_bmdma_setup(struct ata_queued_cmd *qc)
 
        /* load PRD table addr. */
        mb();   /* make sure PRD table writes are visible to controller */
-       iowrite32(ap->prd_dma, ap->ioaddr.bmdma_addr + ATA_DMA_TABLE_OFS);
+       iowrite32(ap->bmdma_prd_dma, ap->ioaddr.bmdma_addr + ATA_DMA_TABLE_OFS);
 
        /* specify data direction, triple-check start bit is clear */
        dmactl = ioread8(ap->ioaddr.bmdma_addr + ATA_DMA_CMD);
@@ -2925,9 +3068,10 @@ EXPORT_SYMBOL_GPL(ata_bmdma_status);
 int ata_bmdma_port_start(struct ata_port *ap)
 {
        if (ap->mwdma_mask || ap->udma_mask) {
-               ap->prd = dmam_alloc_coherent(ap->host->dev, ATA_PRD_TBL_SZ,
-                                             &ap->prd_dma, GFP_KERNEL);
-               if (!ap->prd)
+               ap->bmdma_prd =
+                       dmam_alloc_coherent(ap->host->dev, ATA_PRD_TBL_SZ,
+                                           &ap->bmdma_prd_dma, GFP_KERNEL);
+               if (!ap->bmdma_prd)
                        return -ENOMEM;
        }
 
@@ -3060,7 +3204,100 @@ void ata_pci_bmdma_init(struct ata_host *host)
 }
 EXPORT_SYMBOL_GPL(ata_pci_bmdma_init);
 
+/**
+ *     ata_pci_bmdma_prepare_host - helper to prepare PCI BMDMA ATA host
+ *     @pdev: target PCI device
+ *     @ppi: array of port_info, must be enough for two ports
+ *     @r_host: out argument for the initialized ATA host
+ *
+ *     Helper to allocate BMDMA ATA host for @pdev, acquire all PCI
+ *     resources and initialize it accordingly in one go.
+ *
+ *     LOCKING:
+ *     Inherited from calling layer (may sleep).
+ *
+ *     RETURNS:
+ *     0 on success, -errno otherwise.
+ */
+int ata_pci_bmdma_prepare_host(struct pci_dev *pdev,
+                              const struct ata_port_info * const * ppi,
+                              struct ata_host **r_host)
+{
+       int rc;
+
+       rc = ata_pci_sff_prepare_host(pdev, ppi, r_host);
+       if (rc)
+               return rc;
+
+       ata_pci_bmdma_init(*r_host);
+       return 0;
+}
+EXPORT_SYMBOL_GPL(ata_pci_bmdma_prepare_host);
+
+/**
+ *     ata_pci_bmdma_init_one - Initialize/register BMDMA PCI IDE controller
+ *     @pdev: Controller to be initialized
+ *     @ppi: array of port_info, must be enough for two ports
+ *     @sht: scsi_host_template to use when registering the host
+ *     @host_priv: host private_data
+ *     @hflags: host flags
+ *
+ *     This function is similar to ata_pci_sff_init_one() but also
+ *     takes care of BMDMA initialization.
+ *
+ *     LOCKING:
+ *     Inherited from PCI layer (may sleep).
+ *
+ *     RETURNS:
+ *     Zero on success, negative on errno-based value on error.
+ */
+int ata_pci_bmdma_init_one(struct pci_dev *pdev,
+                          const struct ata_port_info * const * ppi,
+                          struct scsi_host_template *sht, void *host_priv,
+                          int hflags)
+{
+       struct device *dev = &pdev->dev;
+       const struct ata_port_info *pi;
+       struct ata_host *host = NULL;
+       int rc;
+
+       DPRINTK("ENTER\n");
+
+       pi = ata_sff_find_valid_pi(ppi);
+       if (!pi) {
+               dev_printk(KERN_ERR, &pdev->dev,
+                          "no valid port_info specified\n");
+               return -EINVAL;
+       }
+
+       if (!devres_open_group(dev, NULL, GFP_KERNEL))
+               return -ENOMEM;
+
+       rc = pcim_enable_device(pdev);
+       if (rc)
+               goto out;
+
+       /* prepare and activate BMDMA host */
+       rc = ata_pci_bmdma_prepare_host(pdev, ppi, &host);
+       if (rc)
+               goto out;
+       host->private_data = host_priv;
+       host->flags |= hflags;
+
+       pci_set_master(pdev);
+       rc = ata_pci_sff_activate_host(host, ata_bmdma_interrupt, sht);
+ out:
+       if (rc == 0)
+               devres_remove_group(&pdev->dev, NULL);
+       else
+               devres_release_group(&pdev->dev, NULL);
+
+       return rc;
+}
+EXPORT_SYMBOL_GPL(ata_pci_bmdma_init_one);
+
 #endif /* CONFIG_PCI */
+#endif /* CONFIG_ATA_BMDMA */
 
 /**
  *     ata_sff_port_init - Initialize SFF/BMDMA ATA port
@@ -3074,13 +3311,28 @@ EXPORT_SYMBOL_GPL(ata_pci_bmdma_init);
  */
 void ata_sff_port_init(struct ata_port *ap)
 {
+       INIT_DELAYED_WORK(&ap->sff_pio_task, ata_sff_pio_task);
+       ap->ctl = ATA_DEVCTL_OBS;
+       ap->last_ctl = 0xFF;
 }
 
 int __init ata_sff_init(void)
 {
+       /*
+        * FIXME: In UP case, there is only one workqueue thread and if you
+        * have more than one PIO device, latency is bloody awful, with
+        * occasional multi-second "hiccups" as one PIO device waits for
+        * another.  It's an ugly wart that users DO occasionally complain
+        * about; luckily most users have at most one PIO polled device.
+        */
+       ata_sff_wq = create_workqueue("ata_sff");
+       if (!ata_sff_wq)
+               return -ENOMEM;
+
        return 0;
 }
 
 void __exit ata_sff_exit(void)
 {
+       destroy_workqueue(ata_sff_wq);
 }