summaryrefslogtreecommitdiff
path: root/drivers/scsi
diff options
context:
space:
mode:
authorGreg Felix <gregfelixlkml@gmail.com>2005-07-28 15:54:15 -0400
committerJeff Garzik <jgarzik@pobox.com>2005-07-28 15:54:15 -0400
commit7b6dbd6872ca1d0c03dc0e0a7108d79c8dafa793 (patch)
tree54160c4c0aa0970d3daa8b9a8f40c7a31f9527fe /drivers/scsi
parent6b6a93c6876ea1c530d5d3f68e3678093a27fab0 (diff)
downloadlinux-3.10-7b6dbd6872ca1d0c03dc0e0a7108d79c8dafa793.tar.gz
linux-3.10-7b6dbd6872ca1d0c03dc0e0a7108d79c8dafa793.tar.bz2
linux-3.10-7b6dbd6872ca1d0c03dc0e0a7108d79c8dafa793.zip
libata: Check PCI sub-class code before disabling AHCI
This patch adds functionality to check the PCI sub-class code of an AHCI capable device before disabling AHCI. It fixes a bug where an ICH7 sata controller is being setup by the BIOS as sub-class 1 (ide) and the AHCI control registers weren't being initialized, thus causing an IO error in piix_disable_ahci(). Signed-off-by: Gregory Felix <greg.felix@gmail.com>
Diffstat (limited to 'drivers/scsi')
-rw-r--r--drivers/scsi/ata_piix.c19
1 files changed, 13 insertions, 6 deletions
diff --git a/drivers/scsi/ata_piix.c b/drivers/scsi/ata_piix.c
index 3be54643925..a2cfade2c1c 100644
--- a/drivers/scsi/ata_piix.c
+++ b/drivers/scsi/ata_piix.c
@@ -38,6 +38,7 @@ enum {
PIIX_IOCFG = 0x54, /* IDE I/O configuration register */
ICH5_PMR = 0x90, /* port mapping register */
ICH5_PCS = 0x92, /* port control and status */
+ PIIX_SCC = 0x0A, /* sub-class code register */
PIIX_FLAG_AHCI = (1 << 28), /* AHCI possible */
PIIX_FLAG_CHECKINTR = (1 << 29), /* make sure PCI INTx enabled */
@@ -62,6 +63,8 @@ enum {
ich6_sata_rm = 4,
ich7_sata = 5,
esb2_sata = 6,
+
+ PIIX_AHCI_DEVICE = 6,
};
static int piix_init_one (struct pci_dev *pdev,
@@ -574,11 +577,11 @@ static int piix_disable_ahci(struct pci_dev *pdev)
addr = pci_resource_start(pdev, AHCI_PCI_BAR);
if (!addr || !pci_resource_len(pdev, AHCI_PCI_BAR))
return 0;
-
+
mmio = ioremap(addr, 64);
if (!mmio)
return -ENOMEM;
-
+
tmp = readl(mmio + AHCI_GLOBAL_CTL);
if (tmp & AHCI_ENABLE) {
tmp &= ~AHCI_ENABLE;
@@ -588,7 +591,7 @@ static int piix_disable_ahci(struct pci_dev *pdev)
if (tmp & AHCI_ENABLE)
rc = -EIO;
}
-
+
iounmap(mmio);
return rc;
}
@@ -626,9 +629,13 @@ static int piix_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
port_info[1] = NULL;
if (port_info[0]->host_flags & PIIX_FLAG_AHCI) {
- int rc = piix_disable_ahci(pdev);
- if (rc)
- return rc;
+ u8 tmp;
+ pci_read_config_byte(pdev, PIIX_SCC, &tmp);
+ if (tmp == PIIX_AHCI_DEVICE) {
+ int rc = piix_disable_ahci(pdev);
+ if (rc)
+ return rc;
+ }
}
if (port_info[0]->host_flags & PIIX_FLAG_COMBINED) {