diff options
Diffstat (limited to 'drivers/ide/ide-probe.c')
-rw-r--r-- | drivers/ide/ide-probe.c | 94 |
1 files changed, 69 insertions, 25 deletions
diff --git a/drivers/ide/ide-probe.c b/drivers/ide/ide-probe.c index c588066295db..84a89561ec0f 100644 --- a/drivers/ide/ide-probe.c +++ b/drivers/ide/ide-probe.c | |||
@@ -1477,7 +1477,7 @@ static int ide_sysfs_register_port(ide_hwif_t *hwif) | |||
1477 | * Return the new hwif. If we are out of free slots return NULL. | 1477 | * Return the new hwif. If we are out of free slots return NULL. |
1478 | */ | 1478 | */ |
1479 | 1479 | ||
1480 | ide_hwif_t *ide_find_port_slot(const struct ide_port_info *d) | 1480 | static ide_hwif_t *ide_find_port_slot(const struct ide_port_info *d) |
1481 | { | 1481 | { |
1482 | ide_hwif_t *hwif; | 1482 | ide_hwif_t *hwif; |
1483 | int i; | 1483 | int i; |
@@ -1523,14 +1523,63 @@ out_found: | |||
1523 | ide_init_port_data(hwif, i); | 1523 | ide_init_port_data(hwif, i); |
1524 | return hwif; | 1524 | return hwif; |
1525 | } | 1525 | } |
1526 | EXPORT_SYMBOL_GPL(ide_find_port_slot); | ||
1527 | 1526 | ||
1528 | int ide_device_add_all(u8 *idx, const struct ide_port_info *d, hw_regs_t **hws) | 1527 | struct ide_host *ide_host_alloc_all(const struct ide_port_info *d, |
1528 | hw_regs_t **hws) | ||
1529 | { | ||
1530 | struct ide_host *host; | ||
1531 | int i; | ||
1532 | |||
1533 | host = kzalloc(sizeof(*host), GFP_KERNEL); | ||
1534 | if (host == NULL) | ||
1535 | return NULL; | ||
1536 | |||
1537 | for (i = 0; i < MAX_HWIFS; i++) { | ||
1538 | ide_hwif_t *hwif; | ||
1539 | |||
1540 | if (hws[i] == NULL) | ||
1541 | continue; | ||
1542 | |||
1543 | hwif = ide_find_port_slot(d); | ||
1544 | if (hwif) { | ||
1545 | hwif->chipset = hws[i]->chipset; | ||
1546 | |||
1547 | host->ports[i] = hwif; | ||
1548 | host->n_ports++; | ||
1549 | } | ||
1550 | } | ||
1551 | |||
1552 | if (host->n_ports == 0) { | ||
1553 | kfree(host); | ||
1554 | return NULL; | ||
1555 | } | ||
1556 | |||
1557 | return host; | ||
1558 | } | ||
1559 | EXPORT_SYMBOL_GPL(ide_host_alloc_all); | ||
1560 | |||
1561 | struct ide_host *ide_host_alloc(const struct ide_port_info *d, hw_regs_t **hws) | ||
1562 | { | ||
1563 | hw_regs_t *hws_all[MAX_HWIFS]; | ||
1564 | int i; | ||
1565 | |||
1566 | for (i = 0; i < MAX_HWIFS; i++) | ||
1567 | hws_all[i] = (i < 4) ? hws[i] : NULL; | ||
1568 | |||
1569 | return ide_host_alloc_all(d, hws_all); | ||
1570 | } | ||
1571 | EXPORT_SYMBOL_GPL(ide_host_alloc); | ||
1572 | |||
1573 | int ide_host_register(struct ide_host *host, const struct ide_port_info *d, | ||
1574 | hw_regs_t **hws) | ||
1529 | { | 1575 | { |
1530 | ide_hwif_t *hwif, *mate = NULL; | 1576 | ide_hwif_t *hwif, *mate = NULL; |
1577 | u8 idx[MAX_HWIFS]; | ||
1531 | int i, rc = 0; | 1578 | int i, rc = 0; |
1532 | 1579 | ||
1533 | for (i = 0; i < MAX_HWIFS; i++) { | 1580 | for (i = 0; i < MAX_HWIFS; i++) { |
1581 | idx[i] = host->ports[i] ? host->ports[i]->index : 0xff; | ||
1582 | |||
1534 | if (idx[i] == 0xff) { | 1583 | if (idx[i] == 0xff) { |
1535 | mate = NULL; | 1584 | mate = NULL; |
1536 | continue; | 1585 | continue; |
@@ -1626,22 +1675,20 @@ int ide_device_add_all(u8 *idx, const struct ide_port_info *d, hw_regs_t **hws) | |||
1626 | 1675 | ||
1627 | return rc; | 1676 | return rc; |
1628 | } | 1677 | } |
1629 | EXPORT_SYMBOL_GPL(ide_device_add_all); | 1678 | EXPORT_SYMBOL_GPL(ide_host_register); |
1630 | 1679 | ||
1631 | int ide_device_add(u8 *idx, const struct ide_port_info *d, hw_regs_t **hws) | 1680 | void ide_host_remove(struct ide_host *host) |
1632 | { | 1681 | { |
1633 | hw_regs_t *hws_all[MAX_HWIFS]; | ||
1634 | u8 idx_all[MAX_HWIFS]; | ||
1635 | int i; | 1682 | int i; |
1636 | 1683 | ||
1637 | for (i = 0; i < MAX_HWIFS; i++) { | 1684 | for (i = 0; i < MAX_HWIFS; i++) { |
1638 | hws_all[i] = (i < 4) ? hws[i] : NULL; | 1685 | if (host->ports[i]) |
1639 | idx_all[i] = (i < 4) ? idx[i] : 0xff; | 1686 | ide_unregister(host->ports[i]); |
1640 | } | 1687 | } |
1641 | 1688 | ||
1642 | return ide_device_add_all(idx_all, d, hws_all); | 1689 | kfree(host); |
1643 | } | 1690 | } |
1644 | EXPORT_SYMBOL_GPL(ide_device_add); | 1691 | EXPORT_SYMBOL_GPL(ide_host_remove); |
1645 | 1692 | ||
1646 | void ide_port_scan(ide_hwif_t *hwif) | 1693 | void ide_port_scan(ide_hwif_t *hwif) |
1647 | { | 1694 | { |
@@ -1662,11 +1709,10 @@ void ide_port_scan(ide_hwif_t *hwif) | |||
1662 | } | 1709 | } |
1663 | EXPORT_SYMBOL_GPL(ide_port_scan); | 1710 | EXPORT_SYMBOL_GPL(ide_port_scan); |
1664 | 1711 | ||
1665 | static void ide_legacy_init_one(u8 *idx, hw_regs_t **hws, hw_regs_t *hw, | 1712 | static void ide_legacy_init_one(hw_regs_t **hws, hw_regs_t *hw, |
1666 | u8 port_no, const struct ide_port_info *d, | 1713 | u8 port_no, const struct ide_port_info *d, |
1667 | unsigned long config) | 1714 | unsigned long config) |
1668 | { | 1715 | { |
1669 | ide_hwif_t *hwif; | ||
1670 | unsigned long base, ctl; | 1716 | unsigned long base, ctl; |
1671 | int irq; | 1717 | int irq; |
1672 | 1718 | ||
@@ -1698,31 +1744,29 @@ static void ide_legacy_init_one(u8 *idx, hw_regs_t **hws, hw_regs_t *hw, | |||
1698 | hw->chipset = d->chipset; | 1744 | hw->chipset = d->chipset; |
1699 | hw->config = config; | 1745 | hw->config = config; |
1700 | 1746 | ||
1701 | hwif = ide_find_port_slot(d); | 1747 | hws[port_no] = hw; |
1702 | if (hwif) { | ||
1703 | hwif->chipset = hw->chipset; | ||
1704 | |||
1705 | hws[port_no] = hw; | ||
1706 | idx[port_no] = hwif->index; | ||
1707 | } | ||
1708 | } | 1748 | } |
1709 | 1749 | ||
1710 | int ide_legacy_device_add(const struct ide_port_info *d, unsigned long config) | 1750 | int ide_legacy_device_add(const struct ide_port_info *d, unsigned long config) |
1711 | { | 1751 | { |
1712 | u8 idx[4] = { 0xff, 0xff, 0xff, 0xff }; | 1752 | struct ide_host *host; |
1713 | hw_regs_t hw[2], *hws[] = { NULL, NULL, NULL, NULL }; | 1753 | hw_regs_t hw[2], *hws[] = { NULL, NULL, NULL, NULL }; |
1714 | 1754 | ||
1715 | memset(&hw, 0, sizeof(hw)); | 1755 | memset(&hw, 0, sizeof(hw)); |
1716 | 1756 | ||
1717 | if ((d->host_flags & IDE_HFLAG_QD_2ND_PORT) == 0) | 1757 | if ((d->host_flags & IDE_HFLAG_QD_2ND_PORT) == 0) |
1718 | ide_legacy_init_one(idx, hws, &hw[0], 0, d, config); | 1758 | ide_legacy_init_one(hws, &hw[0], 0, d, config); |
1719 | ide_legacy_init_one(idx, hws, &hw[1], 1, d, config); | 1759 | ide_legacy_init_one(hws, &hw[1], 1, d, config); |
1720 | 1760 | ||
1721 | if (idx[0] == 0xff && idx[1] == 0xff && | 1761 | if (hws[0] == NULL && hws[1] == NULL && |
1722 | (d->host_flags & IDE_HFLAG_SINGLE)) | 1762 | (d->host_flags & IDE_HFLAG_SINGLE)) |
1723 | return -ENOENT; | 1763 | return -ENOENT; |
1724 | 1764 | ||
1725 | ide_device_add(idx, d, hws); | 1765 | host = ide_host_alloc(d, hws); |
1766 | if (host == NULL) | ||
1767 | return -ENOMEM; | ||
1768 | |||
1769 | ide_host_register(host, d, hws); | ||
1726 | 1770 | ||
1727 | return 0; | 1771 | return 0; |
1728 | } | 1772 | } |