|
@@ -679,24 +679,20 @@ static void ahci_save_initial_config(struct pci_dev *pdev,
|
|
|
|
|
|
/* cross check port_map and cap.n_ports */
|
|
|
if (port_map) {
|
|
|
- u32 tmp_port_map = port_map;
|
|
|
- int n_ports = ahci_nr_ports(cap);
|
|
|
+ int map_ports = 0;
|
|
|
|
|
|
- for (i = 0; i < AHCI_MAX_PORTS && n_ports; i++) {
|
|
|
- if (tmp_port_map & (1 << i)) {
|
|
|
- n_ports--;
|
|
|
- tmp_port_map &= ~(1 << i);
|
|
|
- }
|
|
|
- }
|
|
|
+ for (i = 0; i < AHCI_MAX_PORTS; i++)
|
|
|
+ if (port_map & (1 << i))
|
|
|
+ map_ports++;
|
|
|
|
|
|
- /* If n_ports and port_map are inconsistent, whine and
|
|
|
- * clear port_map and let it be generated from n_ports.
|
|
|
+ /* If PI has more ports than n_ports, whine, clear
|
|
|
+ * port_map and let it be generated from n_ports.
|
|
|
*/
|
|
|
- if (n_ports || tmp_port_map) {
|
|
|
+ if (map_ports > ahci_nr_ports(cap)) {
|
|
|
dev_printk(KERN_WARNING, &pdev->dev,
|
|
|
- "nr_ports (%u) and implemented port map "
|
|
|
- "(0x%x) don't match, using nr_ports\n",
|
|
|
- ahci_nr_ports(cap), port_map);
|
|
|
+ "implemented port map (0x%x) contains more "
|
|
|
+ "ports than nr_ports (%u), using nr_ports\n",
|
|
|
+ port_map, ahci_nr_ports(cap));
|
|
|
port_map = 0;
|
|
|
}
|
|
|
}
|
|
@@ -2201,7 +2197,7 @@ static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
|
|
|
struct device *dev = &pdev->dev;
|
|
|
struct ahci_host_priv *hpriv;
|
|
|
struct ata_host *host;
|
|
|
- int i, rc;
|
|
|
+ int n_ports, i, rc;
|
|
|
|
|
|
VPRINTK("ENTER\n");
|
|
|
|
|
@@ -2255,7 +2251,14 @@ static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
|
|
|
if (hpriv->cap & HOST_CAP_PMP)
|
|
|
pi.flags |= ATA_FLAG_PMP;
|
|
|
|
|
|
- host = ata_host_alloc_pinfo(&pdev->dev, ppi, fls(hpriv->port_map));
|
|
|
+ /* CAP.NP sometimes indicate the index of the last enabled
|
|
|
+ * port, at other times, that of the last possible port, so
|
|
|
+ * determining the maximum port number requires looking at
|
|
|
+ * both CAP.NP and port_map.
|
|
|
+ */
|
|
|
+ n_ports = max(ahci_nr_ports(hpriv->cap), fls(hpriv->port_map));
|
|
|
+
|
|
|
+ host = ata_host_alloc_pinfo(&pdev->dev, ppi, n_ports);
|
|
|
if (!host)
|
|
|
return -ENOMEM;
|
|
|
host->iomap = pcim_iomap_table(pdev);
|