ide: fix IDE port slots reservation and freeing (take 2)
PATCH 1/1 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 <[email protected]>
---
replacement patch
drivers/ide/ide-probe.c | 87 +++++++++++++++++++++++++++--------------------- 1 file changed, 50 insertions(+), 37 deletions(-)
drivers/ide/ide-probe.c +50 -37
@@ -1474,18 +1474,20 @@ static int ide_sysfs_register_port(ide_hreturn rc; } +static unsigned int ide_indexes; +/** -* ide_find_port_slot - find free ide_hwifs[] slot +* ide_find_port_slot - find free port slot * @d: IDE port info * -* Return the new hwif. If we are out of free slots return NULL. +* Return the new port slot index or -ENOENT if we are out of free slots. */ -static ide_hwif_t *ide_find_port_slot (const struct ide_port_info *d) +static int ide_find_port_slot (const struct ide_port_info *d) { -ide_hwif_t *hwif; -int i; +int idx = -ENOENT ;u8 bootable = (d && (d->host_flags &IDE_HFLAG_NON_BOOTABLE )) ?0 :1 ; +u8 i = (d && (d->host_flags &IDE_HFLAG_QD_2ND_PORT )) ?1 :0 ;;/* * Claim an unassigned slot.
@@ -1497,35 +1499,33 @@ static ide_hwif_t *ide_find_port_slot(co* Unless there is a bootable card that does not use the standard * ports 0x1f0/0x170 (the ide0/ide1 defaults). */ -if (bootable) { - i = (d && (d->host_flags &IDE_HFLAG_QD_2ND_PORT )) ?1 :0 ; - -for (; i <MAX_HWIFS ; i++) { - hwif = &ide_hwifs[i]; -if (hwif->chipset == ide_unknown) - goto out_found; - } +mutex_lock (&ide_cfg_mtx); +if (MAX_HWIFS ==1 ) { +if (ide_indexes ==0 && i ==0 ) + idx =1 ; }else { -for (i =2 ; i <MAX_HWIFS ; i++) { - hwif = &ide_hwifs[i]; -if (hwif->chipset == ide_unknown) - goto out_found; - } -for (i =0 ; i <2 && i <MAX_HWIFS ; i++) { - hwif = &ide_hwifs[i]; -if (hwif->chipset == ide_unknown) - goto out_found; +if (bootable) { +if ((ide_indexes | i) != (1 <<MAX_HWIFS ) -1 ) + idx =ffz (ide_indexes | i); + }else { +if ((ide_indexes |3 ) != (1 <<MAX_HWIFS ) -1 ) + idx =ffz (ide_indexes |3 ); +else if ((ide_indexes &3 ) !=3 ) + idx =ffz (ide_indexes); } } +if (idx >=0 ) + ide_indexes |= (1 << idx); +mutex_unlock (&ide_cfg_mtx); -printk (KERN_ERR "%s: no free slot for interface\n" , - d ? d->name :"ide" ); - -return NULL ; +return idx; +} -out_found: -ide_init_port_data (hwif, i); -return hwif; +static void ide_free_port_slot (int idx) +{ +mutex_lock (&ide_cfg_mtx); + ide_indexes &= ~(1 << idx); +mutex_unlock (&ide_cfg_mtx); } struct ide_host *ide_host_alloc_all(const struct ide_port_info *d,
@@ -1540,17 +1540,24 @@ struct ide_host *ide_host_alloc_all(consfor (i =0 ; i <MAX_HWIFS ; i++) {ide_hwif_t *hwif; +int idx;if (hws[i] ==NULL )continue ; - hwif =ide_find_port_slot (d); -if (hwif) { - hwif->chipset = hws[i]->chipset; - - host->ports[i] = hwif; - host->n_ports++; + idx =ide_find_port_slot (d); +if (idx <0 ) { +printk (KERN_ERR "%s: no free slot for interface\n" , + d ? d->name :"ide" ); +continue ; } + + hwif = &ide_hwifs[idx]; + +ide_init_port_data (hwif, idx); + + host->ports[i] = hwif; + host->n_ports++; }if (host->n_ports ==0 ) {
@@ -1699,11 +1706,17 @@ EXPORT_SYMBOL_GPL(ide_host_add);void ide_host_remove (struct ide_host *host) { +ide_hwif_t *hwif;int i;for (i =0 ; i <MAX_HWIFS ; i++) { -if (host->ports[i]) -ide_unregister (host->ports[i]); + hwif = host->ports[i]; + +if (hwif ==NULL ) +continue ; + +ide_unregister (hwif); +ide_free_port_slot (hwif->index); }kfree (host);