aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorBartlomiej Zolnierkiewicz <bzolnier@gmail.com>2008-07-23 13:55:57 -0400
committerBartlomiej Zolnierkiewicz <bzolnier@gmail.com>2008-07-23 13:55:57 -0400
commit8cdf310025bff8c5ef78564f525a8f347952237b (patch)
treedc2f999834e4c8f2d347dc7248ca7f067968c34e /drivers
parente0d0020788543febd10ab933bde0fa181b627f4f (diff)
ide: fix IDE port slots reservation and freeing (take 2)
* Make ide_find_port_slot() return port slot index. * Add ide_free_port_slot() helper. * Move ide_init_port_data() call and error printk() from ide_find_port_slot() to ide_host_alloc_all(). * Make ide_{find,free}_port_slot() take ide_cfg_mtx mutex and convert them use ide_indexes bitmap to keep track of reserved port slots. * Don't set hwif->chipset in ide_host_alloc_all() as it is no longer necessary. v2: * Pass the correct slot index to ide_init_port_data(). Signed-off-by: Bartlomiej Zolnierkiewicz <bzolnier@gmail.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/ide/ide-probe.c87
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
1473static 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
1480static ide_hwif_t *ide_find_port_slot(const struct ide_port_info *d) 1482static 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
1522out_found: 1520static 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
1527struct ide_host *ide_host_alloc_all(const struct ide_port_info *d, 1527struct 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
1696void ide_host_remove(struct ide_host *host) 1703void 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);