diff options
Diffstat (limited to 'drivers/ide')
-rw-r--r-- | drivers/ide/ide-probe.c | 87 |
1 files changed, 50 insertions, 37 deletions
diff --git a/drivers/ide/ide-probe.c b/drivers/ide/ide-probe.c index 32261282371a..fdf00cde9fce 100644 --- a/drivers/ide/ide-probe.c +++ b/drivers/ide/ide-probe.c | |||
@@ -1470,18 +1470,20 @@ static int ide_sysfs_register_port(ide_hwif_t *hwif) | |||
1470 | return rc; | 1470 | return rc; |
1471 | } | 1471 | } |
1472 | 1472 | ||
1473 | static unsigned int ide_indexes; | ||
1474 | |||
1473 | /** | 1475 | /** |
1474 | * ide_find_port_slot - find free ide_hwifs[] slot | 1476 | * ide_find_port_slot - find free port slot |
1475 | * @d: IDE port info | 1477 | * @d: IDE port info |
1476 | * | 1478 | * |
1477 | * Return the new hwif. If we are out of free slots return NULL. | 1479 | * Return the new port slot index or -ENOENT if we are out of free slots. |
1478 | */ | 1480 | */ |
1479 | 1481 | ||
1480 | static ide_hwif_t *ide_find_port_slot(const struct ide_port_info *d) | 1482 | static int ide_find_port_slot(const struct ide_port_info *d) |
1481 | { | 1483 | { |
1482 | ide_hwif_t *hwif; | 1484 | int idx = -ENOENT; |
1483 | int i; | ||
1484 | u8 bootable = (d && (d->host_flags & IDE_HFLAG_NON_BOOTABLE)) ? 0 : 1; | 1485 | u8 bootable = (d && (d->host_flags & IDE_HFLAG_NON_BOOTABLE)) ? 0 : 1; |
1486 | u8 i = (d && (d->host_flags & IDE_HFLAG_QD_2ND_PORT)) ? 1 : 0;; | ||
1485 | 1487 | ||
1486 | /* | 1488 | /* |
1487 | * Claim an unassigned slot. | 1489 | * Claim an unassigned slot. |
@@ -1493,35 +1495,33 @@ static ide_hwif_t *ide_find_port_slot(const struct ide_port_info *d) | |||
1493 | * Unless there is a bootable card that does not use the standard | 1495 | * Unless there is a bootable card that does not use the standard |
1494 | * ports 0x1f0/0x170 (the ide0/ide1 defaults). | 1496 | * ports 0x1f0/0x170 (the ide0/ide1 defaults). |
1495 | */ | 1497 | */ |
1496 | if (bootable) { | 1498 | mutex_lock(&ide_cfg_mtx); |
1497 | i = (d && (d->host_flags & IDE_HFLAG_QD_2ND_PORT)) ? 1 : 0; | 1499 | if (MAX_HWIFS == 1) { |
1498 | 1500 | if (ide_indexes == 0 && i == 0) | |
1499 | for (; i < MAX_HWIFS; i++) { | 1501 | idx = 1; |
1500 | hwif = &ide_hwifs[i]; | ||
1501 | if (hwif->chipset == ide_unknown) | ||
1502 | goto out_found; | ||
1503 | } | ||
1504 | } else { | 1502 | } else { |
1505 | for (i = 2; i < MAX_HWIFS; i++) { | 1503 | if (bootable) { |
1506 | hwif = &ide_hwifs[i]; | 1504 | if ((ide_indexes | i) != (1 << MAX_HWIFS) - 1) |
1507 | if (hwif->chipset == ide_unknown) | 1505 | idx = ffz(ide_indexes | i); |
1508 | goto out_found; | 1506 | } else { |
1509 | } | 1507 | if ((ide_indexes | 3) != (1 << MAX_HWIFS) - 1) |
1510 | for (i = 0; i < 2 && i < MAX_HWIFS; i++) { | 1508 | idx = ffz(ide_indexes | 3); |
1511 | hwif = &ide_hwifs[i]; | 1509 | else if ((ide_indexes & 3) != 3) |
1512 | if (hwif->chipset == ide_unknown) | 1510 | idx = ffz(ide_indexes); |
1513 | goto out_found; | ||
1514 | } | 1511 | } |
1515 | } | 1512 | } |
1513 | if (idx >= 0) | ||
1514 | ide_indexes |= (1 << idx); | ||
1515 | mutex_unlock(&ide_cfg_mtx); | ||
1516 | 1516 | ||
1517 | printk(KERN_ERR "%s: no free slot for interface\n", | 1517 | return idx; |
1518 | d ? d->name : "ide"); | 1518 | } |
1519 | |||
1520 | return NULL; | ||
1521 | 1519 | ||
1522 | out_found: | 1520 | static void ide_free_port_slot(int idx) |
1523 | ide_init_port_data(hwif, i); | 1521 | { |
1524 | return hwif; | 1522 | mutex_lock(&ide_cfg_mtx); |
1523 | ide_indexes &= ~(1 << idx); | ||
1524 | mutex_unlock(&ide_cfg_mtx); | ||
1525 | } | 1525 | } |
1526 | 1526 | ||
1527 | struct ide_host *ide_host_alloc_all(const struct ide_port_info *d, | 1527 | struct ide_host *ide_host_alloc_all(const struct ide_port_info *d, |
@@ -1536,17 +1536,24 @@ struct ide_host *ide_host_alloc_all(const struct ide_port_info *d, | |||
1536 | 1536 | ||
1537 | for (i = 0; i < MAX_HWIFS; i++) { | 1537 | for (i = 0; i < MAX_HWIFS; i++) { |
1538 | ide_hwif_t *hwif; | 1538 | ide_hwif_t *hwif; |
1539 | int idx; | ||
1539 | 1540 | ||
1540 | if (hws[i] == NULL) | 1541 | if (hws[i] == NULL) |
1541 | continue; | 1542 | continue; |
1542 | 1543 | ||
1543 | hwif = ide_find_port_slot(d); | 1544 | idx = ide_find_port_slot(d); |
1544 | if (hwif) { | 1545 | if (idx < 0) { |
1545 | hwif->chipset = hws[i]->chipset; | 1546 | printk(KERN_ERR "%s: no free slot for interface\n", |
1546 | 1547 | d ? d->name : "ide"); | |
1547 | host->ports[i] = hwif; | 1548 | continue; |
1548 | host->n_ports++; | ||
1549 | } | 1549 | } |
1550 | |||
1551 | hwif = &ide_hwifs[idx]; | ||
1552 | |||
1553 | ide_init_port_data(hwif, idx); | ||
1554 | |||
1555 | host->ports[i] = hwif; | ||
1556 | host->n_ports++; | ||
1550 | } | 1557 | } |
1551 | 1558 | ||
1552 | if (host->n_ports == 0) { | 1559 | if (host->n_ports == 0) { |
@@ -1695,11 +1702,17 @@ EXPORT_SYMBOL_GPL(ide_host_add); | |||
1695 | 1702 | ||
1696 | void ide_host_remove(struct ide_host *host) | 1703 | void ide_host_remove(struct ide_host *host) |
1697 | { | 1704 | { |
1705 | ide_hwif_t *hwif; | ||
1698 | int i; | 1706 | int i; |
1699 | 1707 | ||
1700 | for (i = 0; i < MAX_HWIFS; i++) { | 1708 | for (i = 0; i < MAX_HWIFS; i++) { |
1701 | if (host->ports[i]) | 1709 | hwif = host->ports[i]; |
1702 | ide_unregister(host->ports[i]); | 1710 | |
1711 | if (hwif == NULL) | ||
1712 | continue; | ||
1713 | |||
1714 | ide_unregister(hwif); | ||
1715 | ide_free_port_slot(hwif->index); | ||
1703 | } | 1716 | } |
1704 | 1717 | ||
1705 | kfree(host); | 1718 | kfree(host); |