diff options
author | Tejun Heo <htejun@gmail.com> | 2007-03-18 09:26:53 -0400 |
---|---|---|
committer | Jeff Garzik <jeff@garzik.org> | 2007-04-28 14:16:01 -0400 |
commit | 17199b187b5d9a22f2ec835c9fdb38302501b918 (patch) | |
tree | ae381abed721e382c2bb031a89acd8098e4aeb15 /drivers/ata/ahci.c | |
parent | d447df140d0f07a02bd221cb42eb0b61bce16042 (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/ahci.c')
-rw-r--r-- | drivers/ata/ahci.c | 57 |
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 && |