[libata] sata_svw: Disable ATAPI DMA on current boards (errata workaround)
authorJeff Garzik <jeff@garzik.org>
Thu, 14 Dec 2006 22:04:33 +0000 (17:04 -0500)
committerJeff Garzik <jeff@garzik.org>
Sat, 16 Dec 2006 15:12:50 +0000 (10:12 -0500)
Current Broadcom/Serverworks SATA boards (including Apple K2 SATA)
have problems with ATAPI DMA, so it is disabled.  ATAPI PIO, ATA PIO,
and ATA DMA continue to work just fine.

Acked-by: Anantha Subramanyam <ananth@broadcom.com>
Signed-off-by: Jeff Garzik <jeff@garzik.org>
drivers/ata/sata_svw.c

index db32d15..d89c959 100644 (file)
@@ -56,6 +56,8 @@
 #define DRV_VERSION    "2.0"
 
 enum {
+       K2_FLAG_NO_ATAPI_DMA            = (1 << 29),
+
        /* Taskfile registers offsets */
        K2_SATA_TF_CMD_OFFSET           = 0x00,
        K2_SATA_TF_DATA_OFFSET          = 0x00,
@@ -83,11 +85,33 @@ enum {
 
        /* Port stride */
        K2_SATA_PORT_OFFSET             = 0x100,
+
+       board_svw4                      = 0,
+       board_svw8                      = 1,
+};
+
+static const struct k2_board_info {
+       unsigned int            n_ports;
+       unsigned long           port_flags;
+} k2_board_info[] = {
+       /* board_svw4 */
+       { 4, K2_FLAG_NO_ATAPI_DMA },
+
+       /* board_svw8 */
+       { 8, K2_FLAG_NO_ATAPI_DMA },
 };
 
 static u8 k2_stat_check_status(struct ata_port *ap);
 
 
+static int k2_sata_check_atapi_dma(struct ata_queued_cmd *qc)
+{
+       if (qc->ap->flags & K2_FLAG_NO_ATAPI_DMA)
+               return -1;      /* ATAPI DMA not supported */
+
+       return 0;
+}
+
 static u32 k2_sata_scr_read (struct ata_port *ap, unsigned int sc_reg)
 {
        if (sc_reg > SCR_CONTROL)
@@ -313,6 +337,7 @@ static const struct ata_port_operations k2_sata_ops = {
        .check_status           = k2_stat_check_status,
        .exec_command           = ata_exec_command,
        .dev_select             = ata_std_dev_select,
+       .check_atapi_dma        = k2_sata_check_atapi_dma,
        .bmdma_setup            = k2_bmdma_setup_mmio,
        .bmdma_start            = k2_bmdma_start_mmio,
        .bmdma_stop             = ata_bmdma_stop,
@@ -359,6 +384,8 @@ static int k2_sata_init_one (struct pci_dev *pdev, const struct pci_device_id *e
        struct ata_probe_ent *probe_ent = NULL;
        unsigned long base;
        void __iomem *mmio_base;
+       const struct k2_board_info *board_info =
+                       &k2_board_info[ent->driver_data];
        int pci_dev_busy = 0;
        int rc;
        int i;
@@ -424,7 +451,7 @@ static int k2_sata_init_one (struct pci_dev *pdev, const struct pci_device_id *e
 
        probe_ent->sht = &k2_sata_sht;
        probe_ent->port_flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
-                               ATA_FLAG_MMIO;
+                               ATA_FLAG_MMIO | board_info->port_flags;
        probe_ent->port_ops = &k2_sata_ops;
        probe_ent->n_ports = 4;
        probe_ent->irq = pdev->irq;
@@ -441,7 +468,7 @@ static int k2_sata_init_one (struct pci_dev *pdev, const struct pci_device_id *e
        /* different controllers have different number of ports - currently 4 or 8 */
        /* All ports are on the same function. Multi-function device is no
         * longer available. This should not be seen in any system. */
-       for (i = 0; i < ent->driver_data; i++)
+       for (i = 0; i < board_info->n_ports; i++)
                k2_sata_setup_port(&probe_ent->port[i], base + i * K2_SATA_PORT_OFFSET);
 
        pci_set_master(pdev);
@@ -469,11 +496,11 @@ err_out:
  * controller
  * */
 static const struct pci_device_id k2_sata_pci_tbl[] = {
-       { PCI_VDEVICE(SERVERWORKS, 0x0240), 4 },
-       { PCI_VDEVICE(SERVERWORKS, 0x0241), 4 },
-       { PCI_VDEVICE(SERVERWORKS, 0x0242), 8 },
-       { PCI_VDEVICE(SERVERWORKS, 0x024a), 4 },
-       { PCI_VDEVICE(SERVERWORKS, 0x024b), 4 },
+       { PCI_VDEVICE(SERVERWORKS, 0x0240), board_svw4 },
+       { PCI_VDEVICE(SERVERWORKS, 0x0241), board_svw4 },
+       { PCI_VDEVICE(SERVERWORKS, 0x0242), board_svw8 },
+       { PCI_VDEVICE(SERVERWORKS, 0x024a), board_svw4 },
+       { PCI_VDEVICE(SERVERWORKS, 0x024b), board_svw4 },
 
        { }
 };