aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/ata
diff options
context:
space:
mode:
authorTejun Heo <htejun@gmail.com>2007-03-18 09:26:53 -0400
committerJeff Garzik <jeff@garzik.org>2007-04-28 14:16:01 -0400
commit17199b187b5d9a22f2ec835c9fdb38302501b918 (patch)
treeae381abed721e382c2bb031a89acd8098e4aeb15 /drivers/ata
parentd447df140d0f07a02bd221cb42eb0b61bce16042 (diff)
ahci: move port_map handling to ahci_save_initial_config()
Move cross checking between port_map and cap.n_ports into ahci_save_initial_config(). After save_initial_config is done, hpriv->port_map is always setup properly. Tested on JMB363, ICH7 and ICH8 (with dummy ports). Signed-off-by: Tejun Heo <htejun@gmail.com> Signed-off-by: Jeff Garzik <jeff@garzik.org>
Diffstat (limited to 'drivers/ata')
-rw-r--r--drivers/ata/ahci.c57
1 files changed, 30 insertions, 27 deletions
diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c
index c31b66366326..fb9f69252939 100644
--- a/drivers/ata/ahci.c
+++ b/drivers/ata/ahci.c
@@ -498,6 +498,7 @@ static void ahci_save_initial_config(struct ata_probe_ent *probe_ent)
498 struct ahci_host_priv *hpriv = probe_ent->private_data; 498 struct ahci_host_priv *hpriv = probe_ent->private_data;
499 void __iomem *mmio = probe_ent->iomap[AHCI_PCI_BAR]; 499 void __iomem *mmio = probe_ent->iomap[AHCI_PCI_BAR];
500 u32 cap, port_map; 500 u32 cap, port_map;
501 int i;
501 502
502 /* Values prefixed with saved_ are written back to host after 503 /* Values prefixed with saved_ are written back to host after
503 * reset. Values without are used for driver operation. 504 * reset. Values without are used for driver operation.
@@ -515,6 +516,31 @@ static void ahci_save_initial_config(struct ata_probe_ent *probe_ent)
515 hpriv->saved_port_map = port_map; 516 hpriv->saved_port_map = port_map;
516 } 517 }
517 518
519 /* cross check port_map and cap.n_ports */
520 if (probe_ent->port_flags & AHCI_FLAG_HONOR_PI) {
521 u32 tmp_port_map = port_map;
522 int n_ports = ahci_nr_ports(cap);
523
524 for (i = 0; i < AHCI_MAX_PORTS && n_ports; i++) {
525 if (tmp_port_map & (1 << i)) {
526 n_ports--;
527 tmp_port_map &= ~(1 << i);
528 }
529 }
530
531 /* Whine if inconsistent. No need to update cap.
532 * port_map is used to determine number of ports.
533 */
534 if (n_ports || tmp_port_map)
535 dev_printk(KERN_WARNING, probe_ent->dev,
536 "nr_ports (%u) and implemented port map "
537 "(0x%x) don't match\n",
538 ahci_nr_ports(cap), port_map);
539 } else {
540 /* fabricate port_map from cap.nr_ports */
541 port_map = (1 << ahci_nr_ports(cap)) - 1;
542 }
543
518 /* record values to use during operation */ 544 /* record values to use during operation */
519 hpriv->cap = cap; 545 hpriv->cap = cap;
520 hpriv->port_map = port_map; 546 hpriv->port_map = port_map;
@@ -1589,41 +1615,18 @@ static int ahci_host_init(struct ata_probe_ent *probe_ent)
1589 struct ahci_host_priv *hpriv = probe_ent->private_data; 1615 struct ahci_host_priv *hpriv = probe_ent->private_data;
1590 struct pci_dev *pdev = to_pci_dev(probe_ent->dev); 1616 struct pci_dev *pdev = to_pci_dev(probe_ent->dev);
1591 void __iomem *mmio = probe_ent->iomap[AHCI_PCI_BAR]; 1617 void __iomem *mmio = probe_ent->iomap[AHCI_PCI_BAR];
1592 unsigned int i, cap_n_ports, using_dac; 1618 unsigned int i, using_dac;
1593 int rc; 1619 int rc;
1594 1620
1595 rc = ahci_reset_controller(mmio, pdev, hpriv); 1621 rc = ahci_reset_controller(mmio, pdev, hpriv);
1596 if (rc) 1622 if (rc)
1597 return rc; 1623 return rc;
1598 1624
1599 cap_n_ports = ahci_nr_ports(hpriv->cap); 1625 probe_ent->n_ports = fls(hpriv->port_map);
1626 probe_ent->dummy_port_mask = ~hpriv->port_map;
1600 1627
1601 VPRINTK("cap 0x%x port_map 0x%x n_ports %d\n", 1628 VPRINTK("cap 0x%x port_map 0x%x n_ports %d\n",
1602 hpriv->cap, hpriv->port_map, cap_n_ports); 1629 hpriv->cap, hpriv->port_map, probe_ent->n_ports);
1603
1604 if (probe_ent->port_flags & AHCI_FLAG_HONOR_PI) {
1605 unsigned int n_ports = cap_n_ports;
1606 u32 port_map = hpriv->port_map;
1607 int max_port = 0;
1608
1609 for (i = 0; i < AHCI_MAX_PORTS && n_ports; i++) {
1610 if (port_map & (1 << i)) {
1611 n_ports--;
1612 port_map &= ~(1 << i);
1613 max_port = i;
1614 } else
1615 probe_ent->dummy_port_mask |= 1 << i;
1616 }
1617
1618 if (n_ports || port_map)
1619 dev_printk(KERN_WARNING, &pdev->dev,
1620 "nr_ports (%u) and implemented port map "
1621 "(0x%x) don't match\n",
1622 cap_n_ports, hpriv->port_map);
1623
1624 probe_ent->n_ports = max_port + 1;
1625 } else
1626 probe_ent->n_ports = cap_n_ports;
1627 1630
1628 using_dac = hpriv->cap & HOST_CAP_64; 1631 using_dac = hpriv->cap & HOST_CAP_64;
1629 if (using_dac && 1632 if (using_dac &&