diff options
Diffstat (limited to 'drivers/ata/ahci.c')
-rw-r--r-- | drivers/ata/ahci.c | 35 |
1 files changed, 19 insertions, 16 deletions
diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c index 27c8d56111c2..29e71bddd6ff 100644 --- a/drivers/ata/ahci.c +++ b/drivers/ata/ahci.c | |||
@@ -679,24 +679,20 @@ static void ahci_save_initial_config(struct pci_dev *pdev, | |||
679 | 679 | ||
680 | /* cross check port_map and cap.n_ports */ | 680 | /* cross check port_map and cap.n_ports */ |
681 | if (port_map) { | 681 | if (port_map) { |
682 | u32 tmp_port_map = port_map; | 682 | int map_ports = 0; |
683 | int n_ports = ahci_nr_ports(cap); | ||
684 | 683 | ||
685 | for (i = 0; i < AHCI_MAX_PORTS && n_ports; i++) { | 684 | for (i = 0; i < AHCI_MAX_PORTS; i++) |
686 | if (tmp_port_map & (1 << i)) { | 685 | if (port_map & (1 << i)) |
687 | n_ports--; | 686 | map_ports++; |
688 | tmp_port_map &= ~(1 << i); | ||
689 | } | ||
690 | } | ||
691 | 687 | ||
692 | /* If n_ports and port_map are inconsistent, whine and | 688 | /* If PI has more ports than n_ports, whine, clear |
693 | * clear port_map and let it be generated from n_ports. | 689 | * port_map and let it be generated from n_ports. |
694 | */ | 690 | */ |
695 | if (n_ports || tmp_port_map) { | 691 | if (map_ports > ahci_nr_ports(cap)) { |
696 | dev_printk(KERN_WARNING, &pdev->dev, | 692 | dev_printk(KERN_WARNING, &pdev->dev, |
697 | "nr_ports (%u) and implemented port map " | 693 | "implemented port map (0x%x) contains more " |
698 | "(0x%x) don't match, using nr_ports\n", | 694 | "ports than nr_ports (%u), using nr_ports\n", |
699 | ahci_nr_ports(cap), port_map); | 695 | port_map, ahci_nr_ports(cap)); |
700 | port_map = 0; | 696 | port_map = 0; |
701 | } | 697 | } |
702 | } | 698 | } |
@@ -2201,7 +2197,7 @@ static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
2201 | struct device *dev = &pdev->dev; | 2197 | struct device *dev = &pdev->dev; |
2202 | struct ahci_host_priv *hpriv; | 2198 | struct ahci_host_priv *hpriv; |
2203 | struct ata_host *host; | 2199 | struct ata_host *host; |
2204 | int i, rc; | 2200 | int n_ports, i, rc; |
2205 | 2201 | ||
2206 | VPRINTK("ENTER\n"); | 2202 | VPRINTK("ENTER\n"); |
2207 | 2203 | ||
@@ -2255,7 +2251,14 @@ static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
2255 | if (hpriv->cap & HOST_CAP_PMP) | 2251 | if (hpriv->cap & HOST_CAP_PMP) |
2256 | pi.flags |= ATA_FLAG_PMP; | 2252 | pi.flags |= ATA_FLAG_PMP; |
2257 | 2253 | ||
2258 | host = ata_host_alloc_pinfo(&pdev->dev, ppi, fls(hpriv->port_map)); | 2254 | /* CAP.NP sometimes indicate the index of the last enabled |
2255 | * port, at other times, that of the last possible port, so | ||
2256 | * determining the maximum port number requires looking at | ||
2257 | * both CAP.NP and port_map. | ||
2258 | */ | ||
2259 | n_ports = max(ahci_nr_ports(hpriv->cap), fls(hpriv->port_map)); | ||
2260 | |||
2261 | host = ata_host_alloc_pinfo(&pdev->dev, ppi, n_ports); | ||
2259 | if (!host) | 2262 | if (!host) |
2260 | return -ENOMEM; | 2263 | return -ENOMEM; |
2261 | host->iomap = pcim_iomap_table(pdev); | 2264 | host->iomap = pcim_iomap_table(pdev); |