aboutsummaryrefslogtreecommitdiffstats
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
parent6b6a93c6876ea1c530d5d3f68e3678093a27fab0 (diff)
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>
-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 3be546439252..a2cfade2c1c6 100644
--- a/drivers/scsi/ata_piix.c
+++ b/drivers/scsi/ata_piix.c
@@ -38,6 +38,7 @@ enum {
38 PIIX_IOCFG = 0x54, /* IDE I/O configuration register */ 38 PIIX_IOCFG = 0x54, /* IDE I/O configuration register */
39 ICH5_PMR = 0x90, /* port mapping register */ 39 ICH5_PMR = 0x90, /* port mapping register */
40 ICH5_PCS = 0x92, /* port control and status */ 40 ICH5_PCS = 0x92, /* port control and status */
41 PIIX_SCC = 0x0A, /* sub-class code register */
41 42
42 PIIX_FLAG_AHCI = (1 << 28), /* AHCI possible */ 43 PIIX_FLAG_AHCI = (1 << 28), /* AHCI possible */
43 PIIX_FLAG_CHECKINTR = (1 << 29), /* make sure PCI INTx enabled */ 44 PIIX_FLAG_CHECKINTR = (1 << 29), /* make sure PCI INTx enabled */
@@ -62,6 +63,8 @@ enum {
62 ich6_sata_rm = 4, 63 ich6_sata_rm = 4,
63 ich7_sata = 5, 64 ich7_sata = 5,
64 esb2_sata = 6, 65 esb2_sata = 6,
66
67 PIIX_AHCI_DEVICE = 6,
65}; 68};
66 69
67static int piix_init_one (struct pci_dev *pdev, 70static int piix_init_one (struct pci_dev *pdev,
@@ -574,11 +577,11 @@ static int piix_disable_ahci(struct pci_dev *pdev)
574 addr = pci_resource_start(pdev, AHCI_PCI_BAR); 577 addr = pci_resource_start(pdev, AHCI_PCI_BAR);
575 if (!addr || !pci_resource_len(pdev, AHCI_PCI_BAR)) 578 if (!addr || !pci_resource_len(pdev, AHCI_PCI_BAR))
576 return 0; 579 return 0;
577 580
578 mmio = ioremap(addr, 64); 581 mmio = ioremap(addr, 64);
579 if (!mmio) 582 if (!mmio)
580 return -ENOMEM; 583 return -ENOMEM;
581 584
582 tmp = readl(mmio + AHCI_GLOBAL_CTL); 585 tmp = readl(mmio + AHCI_GLOBAL_CTL);
583 if (tmp & AHCI_ENABLE) { 586 if (tmp & AHCI_ENABLE) {
584 tmp &= ~AHCI_ENABLE; 587 tmp &= ~AHCI_ENABLE;
@@ -588,7 +591,7 @@ static int piix_disable_ahci(struct pci_dev *pdev)
588 if (tmp & AHCI_ENABLE) 591 if (tmp & AHCI_ENABLE)
589 rc = -EIO; 592 rc = -EIO;
590 } 593 }
591 594
592 iounmap(mmio); 595 iounmap(mmio);
593 return rc; 596 return rc;
594} 597}
@@ -626,9 +629,13 @@ static int piix_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
626 port_info[1] = NULL; 629 port_info[1] = NULL;
627 630
628 if (port_info[0]->host_flags & PIIX_FLAG_AHCI) { 631 if (port_info[0]->host_flags & PIIX_FLAG_AHCI) {
629 int rc = piix_disable_ahci(pdev); 632 u8 tmp;
630 if (rc) 633 pci_read_config_byte(pdev, PIIX_SCC, &tmp);
631 return rc; 634 if (tmp == PIIX_AHCI_DEVICE) {
635 int rc = piix_disable_ahci(pdev);
636 if (rc)
637 return rc;
638 }
632 } 639 }
633 640
634 if (port_info[0]->host_flags & PIIX_FLAG_COMBINED) { 641 if (port_info[0]->host_flags & PIIX_FLAG_COMBINED) {