[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: Anantha Subramanyam <ananth@broadcom.com> Signed-off-by: Jeff Garzik <jeff@garzik.org>
This commit is contained in:
parent
da02d2a16e
commit
c10340aca2
1 changed files with 34 additions and 7 deletions
|
@ -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 {
|
||||||
|
|
||||||
/* 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 = {
|
||||||
.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
|
||||||
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
|
||||||
|
|
||||||
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
|
||||||
/* 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
|
||||||
* 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 },
|
||||||
|
|
||||||
{ }
|
{ }
|
||||||
};
|
};
|
||||||
|
|
Loading…
Add table
Reference in a new issue