From: Ben Collins After doing a large round of debugging and fixups for ieee1394, I started getting really aggrivated with the way that the scsi layer allocates host numbers by forever incrementing from the last one. Before too long, I was getting scsi137, etc. Not only did it look bad, it was bad. Cdrecord only scans bus 0-15, which means after a few hotplugs with your USB or Firewire CD/DVD recorder, you wont be able to burn to it. Yes, I know cdrecord needs to be fixed aswell, but I've had my fill of trying to convince the author of anything, so I wont be sending him a patch. This patch enables first-fit allocation of host numbers. It will pick the lowest available number first. --- 25-akpm/drivers/scsi/hosts.c | 30 ++++++++++++++++++++++++++++-- 1 files changed, 28 insertions(+), 2 deletions(-) diff -puN drivers/scsi/hosts.c~scsi-host-allocation-fix drivers/scsi/hosts.c --- 25/drivers/scsi/hosts.c~scsi-host-allocation-fix Fri Feb 27 14:11:47 2004 +++ 25-akpm/drivers/scsi/hosts.c Fri Feb 27 14:29:01 2004 @@ -30,6 +30,7 @@ #include #include #include +#include #include #include "scsi.h" @@ -37,9 +38,26 @@ #include "scsi_priv.h" #include "scsi_logging.h" +static DECLARE_MUTEX(host_num_lock); +static struct idr allocated_hosts; -static int scsi_host_next_hn; /* host_no for next new host */ +static int alloc_host_no(void) +{ + int ret = -ENOMEM; + + down(&host_num_lock); + if (idr_pre_get(&allocated_hosts, GFP_KERNEL)) + ret = idr_get_new(&allocated_hosts, NULL); + up(&host_num_lock); + return ret; +} +static void free_host_no(int host_no) +{ + down(&host_num_lock); + idr_remove(&allocated_hosts, host_no); + up(&host_num_lock); +} static void scsi_host_cls_release(struct class_device *class_dev) { @@ -163,9 +181,11 @@ static void scsi_host_dev_release(struct */ if (parent) put_device(parent); + free_host_no(shost->host_no); kfree(shost); } + /** * scsi_host_alloc - register a scsi host adapter instance. * @sht: pointer to scsi host template @@ -184,6 +204,7 @@ struct Scsi_Host *scsi_host_alloc(struct struct Scsi_Host *shost; int gfp_mask = GFP_KERNEL, rval; DECLARE_COMPLETION(complete); + int host_no; if (sht->unchecked_isa_dma && privsize) gfp_mask |= __GFP_DMA; @@ -214,7 +235,6 @@ struct Scsi_Host *scsi_host_alloc(struct init_MUTEX(&shost->scan_mutex); - shost->host_no = scsi_host_next_hn++; /* XXX(hch): still racy */ shost->dma_channel = 0xff; /* These three are default values which can be overridden */ @@ -259,6 +279,11 @@ struct Scsi_Host *scsi_host_alloc(struct else shost->dma_boundary = 0xffffffff; + host_no = alloc_host_no(); + if (host_no < 0) + goto fail_kfree; + shost->host_no = host_no; + rval = scsi_setup_command_freelist(shost); if (rval) goto fail_kfree; @@ -361,6 +386,7 @@ void scsi_host_put(struct Scsi_Host *sho int scsi_init_hosts(void) { + idr_init(&allocated_hosts); return class_register(&shost_class); } _