Commit c10340ac authored by Jeff Garzik's avatar Jeff Garzik

[libata] sata_svw: Disable ATAPI DMA on current boards (errata workaround)

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: default avatarAnantha Subramanyam <ananth@broadcom.com>
Signed-off-by: default avatarJeff Garzik <jeff@garzik.org>
parent da02d2a1
...@@ -56,6 +56,8 @@ ...@@ -56,6 +56,8 @@
#define DRV_VERSION "2.0" #define DRV_VERSION "2.0"
enum { enum {
K2_FLAG_NO_ATAPI_DMA = (1 << 29),
/* Taskfile registers offsets */ /* Taskfile registers offsets */
K2_SATA_TF_CMD_OFFSET = 0x00, K2_SATA_TF_CMD_OFFSET = 0x00,
K2_SATA_TF_DATA_OFFSET = 0x00, K2_SATA_TF_DATA_OFFSET = 0x00,
...@@ -83,11 +85,33 @@ enum { ...@@ -83,11 +85,33 @@ enum {
/* Port stride */ /* Port stride */
K2_SATA_PORT_OFFSET = 0x100, 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 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) static u32 k2_sata_scr_read (struct ata_port *ap, unsigned int sc_reg)
{ {
if (sc_reg > SCR_CONTROL) if (sc_reg > SCR_CONTROL)
...@@ -313,6 +337,7 @@ static const struct ata_port_operations k2_sata_ops = { ...@@ -313,6 +337,7 @@ static const struct ata_port_operations k2_sata_ops = {
.check_status = k2_stat_check_status, .check_status = k2_stat_check_status,
.exec_command = ata_exec_command, .exec_command = ata_exec_command,
.dev_select = ata_std_dev_select, .dev_select = ata_std_dev_select,
.check_atapi_dma = k2_sata_check_atapi_dma,
.bmdma_setup = k2_bmdma_setup_mmio, .bmdma_setup = k2_bmdma_setup_mmio,
.bmdma_start = k2_bmdma_start_mmio, .bmdma_start = k2_bmdma_start_mmio,
.bmdma_stop = ata_bmdma_stop, .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 ...@@ -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; struct ata_probe_ent *probe_ent = NULL;
unsigned long base; unsigned long base;
void __iomem *mmio_base; void __iomem *mmio_base;
const struct k2_board_info *board_info =
&k2_board_info[ent->driver_data];
int pci_dev_busy = 0; int pci_dev_busy = 0;
int rc; int rc;
int i; int i;
...@@ -424,7 +451,7 @@ static int k2_sata_init_one (struct pci_dev *pdev, const struct pci_device_id *e ...@@ -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->sht = &k2_sata_sht;
probe_ent->port_flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY | 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->port_ops = &k2_sata_ops;
probe_ent->n_ports = 4; probe_ent->n_ports = 4;
probe_ent->irq = pdev->irq; 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 ...@@ -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 */ /* different controllers have different number of ports - currently 4 or 8 */
/* All ports are on the same function. Multi-function device is no /* All ports are on the same function. Multi-function device is no
* longer available. This should not be seen in any system. */ * 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); k2_sata_setup_port(&probe_ent->port[i], base + i * K2_SATA_PORT_OFFSET);
pci_set_master(pdev); pci_set_master(pdev);
...@@ -469,11 +496,11 @@ static int k2_sata_init_one (struct pci_dev *pdev, const struct pci_device_id *e ...@@ -469,11 +496,11 @@ static int k2_sata_init_one (struct pci_dev *pdev, const struct pci_device_id *e
* controller * controller
* */ * */
static const struct pci_device_id k2_sata_pci_tbl[] = { static const struct pci_device_id k2_sata_pci_tbl[] = {
{ PCI_VDEVICE(SERVERWORKS, 0x0240), 4 }, { PCI_VDEVICE(SERVERWORKS, 0x0240), board_svw4 },
{ PCI_VDEVICE(SERVERWORKS, 0x0241), 4 }, { PCI_VDEVICE(SERVERWORKS, 0x0241), board_svw4 },
{ PCI_VDEVICE(SERVERWORKS, 0x0242), 8 }, { PCI_VDEVICE(SERVERWORKS, 0x0242), board_svw8 },
{ PCI_VDEVICE(SERVERWORKS, 0x024a), 4 }, { PCI_VDEVICE(SERVERWORKS, 0x024a), board_svw4 },
{ PCI_VDEVICE(SERVERWORKS, 0x024b), 4 }, { PCI_VDEVICE(SERVERWORKS, 0x024b), board_svw4 },
{ } { }
}; };
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment