Gitweb:     
http://git.kernel.org/git/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h=d92e74d353345d19f762e9501a50b0a5f43f7ba8
Commit:     d92e74d353345d19f762e9501a50b0a5f43f7ba8
Parent:     0522b2869d89b095bf417c8cc6fa404842e91903
Author:     Alan Cox <[EMAIL PROTECTED]>
AuthorDate: Thu Jun 7 16:19:15 2007 +0100
Committer:  Jeff Garzik <[EMAIL PROTECTED]>
CommitDate: Sat Jun 9 22:40:28 2007 -0400

    libata-core/sff: Fix multiple assumptions about DMA
    
    The ata IRQ ack functions are only used when debugging. Unfortunately
    almost every controller that calls them can cause crashes in some
    configurations as there are missing checks for bmdma presence.
    
    In addition ata_port_start insists of installing DMA buffers and pad
    buffers for controllers regardless. The SFF controllers actually need to
    make that decision dynamically at controller setup time and all need the
    same helper - so we add ata_sff_port_start. Future patches will switch
    the SFF drivers to use this.
    
    Signed-off-by: Alan Cox <[EMAIL PROTECTED]>
    Signed-off-by: Jeff Garzik <[EMAIL PROTECTED]>
---
 drivers/ata/libata-core.c |    1 +
 drivers/ata/libata-sff.c  |   37 +++++++++++++++++++++++++++++--------
 include/linux/libata.h    |    1 +
 3 files changed, 31 insertions(+), 8 deletions(-)

diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c
index bf8d3b8..85283c0 100644
--- a/drivers/ata/libata-core.c
+++ b/drivers/ata/libata-core.c
@@ -6826,6 +6826,7 @@ EXPORT_SYMBOL_GPL(ata_check_status);
 EXPORT_SYMBOL_GPL(ata_altstatus);
 EXPORT_SYMBOL_GPL(ata_exec_command);
 EXPORT_SYMBOL_GPL(ata_port_start);
+EXPORT_SYMBOL_GPL(ata_sff_port_start);
 EXPORT_SYMBOL_GPL(ata_interrupt);
 EXPORT_SYMBOL_GPL(ata_do_set_mode);
 EXPORT_SYMBOL_GPL(ata_data_xfer);
diff --git a/drivers/ata/libata-sff.c b/drivers/ata/libata-sff.c
index e35d134..ce84805 100644
--- a/drivers/ata/libata-sff.c
+++ b/drivers/ata/libata-sff.c
@@ -80,25 +80,25 @@ u8 ata_dummy_irq_on (struct ata_port *ap)   { return 0; }
 u8 ata_irq_ack(struct ata_port *ap, unsigned int chk_drq)
 {
        unsigned int bits = chk_drq ? ATA_BUSY | ATA_DRQ : ATA_BUSY;
-       u8 host_stat, post_stat, status;
+       u8 host_stat = 0, post_stat = 0, status;
 
        status = ata_busy_wait(ap, bits, 1000);
        if (status & bits)
                if (ata_msg_err(ap))
                        printk(KERN_ERR "abnormal status 0x%X\n", status);
 
-       /* get controller status; clear intr, err bits */
-       host_stat = ioread8(ap->ioaddr.bmdma_addr + ATA_DMA_STATUS);
-       iowrite8(host_stat | ATA_DMA_INTR | ATA_DMA_ERR,
-                ap->ioaddr.bmdma_addr + ATA_DMA_STATUS);
-
-       post_stat = ioread8(ap->ioaddr.bmdma_addr + ATA_DMA_STATUS);
+       if (ap->ioaddr.bmdma_addr) {
+               /* get controller status; clear intr, err bits */
+               host_stat = ioread8(ap->ioaddr.bmdma_addr + ATA_DMA_STATUS);
+               iowrite8(host_stat | ATA_DMA_INTR | ATA_DMA_ERR,
+                        ap->ioaddr.bmdma_addr + ATA_DMA_STATUS);
 
+               post_stat = ioread8(ap->ioaddr.bmdma_addr + ATA_DMA_STATUS);
+       }
        if (ata_msg_intr(ap))
                printk(KERN_INFO "%s: irq ack: host_stat 0x%X, new host_stat 
0x%X, drv_stat 0x%X\n",
                        __FUNCTION__,
                        host_stat, post_stat, status);
-
        return status;
 }
 
@@ -516,6 +516,27 @@ void ata_bmdma_post_internal_cmd(struct ata_queued_cmd *qc)
                ata_bmdma_stop(qc);
 }
 
+/**
+ *     ata_sff_port_start - Set port up for dma.
+ *     @ap: Port to initialize
+ *
+ *     Called just after data structures for each port are
+ *     initialized.  Allocates space for PRD table if the device
+ *     is DMA capable SFF.
+ *
+ *     May be used as the port_start() entry in ata_port_operations.
+ *
+ *     LOCKING:
+ *     Inherited from caller.
+ */
+
+int ata_sff_port_start(struct ata_port *ap)
+{
+       if (ap->ioaddr.bmdma_addr)
+               return ata_port_start(ap);
+       return 0;
+}
+
 #ifdef CONFIG_PCI
 
 static int ata_resources_present(struct pci_dev *pdev, int port)
diff --git a/include/linux/libata.h b/include/linux/libata.h
index a6a3113..745c4f9 100644
--- a/include/linux/libata.h
+++ b/include/linux/libata.h
@@ -753,6 +753,7 @@ extern u8 ata_check_status(struct ata_port *ap);
 extern u8 ata_altstatus(struct ata_port *ap);
 extern void ata_exec_command(struct ata_port *ap, const struct ata_taskfile 
*tf);
 extern int ata_port_start (struct ata_port *ap);
+extern int ata_sff_port_start (struct ata_port *ap);
 extern irqreturn_t ata_interrupt (int irq, void *dev_instance);
 extern void ata_data_xfer(struct ata_device *adev, unsigned char *buf,
                          unsigned int buflen, int write_data);
-
To unsubscribe from this list: send the line "unsubscribe git-commits-head" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to