summaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorAlan <alan@lxorguk.ukuu.org.uk>2007-01-08 12:10:05 +0000
committerJeff Garzik <jeff@garzik.org>2007-02-09 17:39:30 -0500
commit4112e16a7c606a80810d22d55bfc742eaa61fecb (patch)
treec48274decc14c4d71dd99f9c3f93087698e767f4 /drivers
parentd73f30e1c9a9af14757fa5bf4014343926047156 (diff)
downloadkernel-crypto-4112e16a7c606a80810d22d55bfc742eaa61fecb.tar.gz
kernel-crypto-4112e16a7c606a80810d22d55bfc742eaa61fecb.tar.xz
kernel-crypto-4112e16a7c606a80810d22d55bfc742eaa61fecb.zip
libata-sff: Don't try and activate channels which are not in use
An ATA controller in native mode may have one or more channels disabled and not assigned resources. In that case the existing code crashes trying to access I/O ports 0-7. Add the neccessary check. Signed-off-by: Alan Cox <alan@redhat.com> Signed-off-by: Jeff Garzik <jeff@garzik.org>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/ata/libata-sff.c22
1 files changed, 22 insertions, 0 deletions
diff --git a/drivers/ata/libata-sff.c b/drivers/ata/libata-sff.c
index 12c88c58803..cfa9ed179d9 100644
--- a/drivers/ata/libata-sff.c
+++ b/drivers/ata/libata-sff.c
@@ -832,6 +832,21 @@ void ata_bmdma_post_internal_cmd(struct ata_queued_cmd *qc)
}
#ifdef CONFIG_PCI
+
+static int ata_resources_present(struct pci_dev *pdev, int port)
+{
+ int i;
+
+ /* Check the PCI resources for this channel are enabled */
+ port = port * 2;
+ for (i = 0; i < 2; i ++) {
+ if (pci_resource_start(pdev, port + i) == 0 ||
+ pci_resource_len(pdev, port + i) == 0)
+ return 0;
+ }
+ return 1;
+}
+
/**
* ata_pci_init_native_mode - Initialize native-mode driver
* @pdev: pci device to be initialized
@@ -863,6 +878,13 @@ ata_pci_init_native_mode(struct pci_dev *pdev, struct ata_port_info **port, int
probe_ent->irq = pdev->irq;
probe_ent->irq_flags = IRQF_SHARED;
+
+ /* Discard disabled ports. Some controllers show their
+ unused channels this way */
+ if (ata_resources_present(pdev, 0) == 0)
+ ports &= ~ATA_PORT_PRIMARY;
+ if (ata_resources_present(pdev, 1) == 0)
+ ports &= ~ATA_PORT_SECONDARY;
if (ports & ATA_PORT_PRIMARY) {
probe_ent->port[p].cmd_addr = pci_resource_start(pdev, 0);