libata-sff: Don't try and activate channels which are not in use
authorAlan <alan@lxorguk.ukuu.org.uk>
Mon, 8 Jan 2007 12:10:05 +0000 (12:10 +0000)
committerJeff Garzik <jeff@garzik.org>
Fri, 9 Feb 2007 22:39:30 +0000 (17:39 -0500)
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>
drivers/ata/libata-sff.c

index 12c88c5..cfa9ed1 100644 (file)
@@ -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);