X-Git-Url: https://err.no/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=drivers%2Fscsi%2Fhosts.c;h=fed0b02ebc1d35ecba7c19b534956edf939eb7a6;hb=04489eeb02a40bc15029886cef7285ada3ab0de6;hp=4e811ca3270e96ff8aba1c46d0c731cd01df35f8;hpb=f7120a4f75168df3c02efacd10403a4ba0bcb29d;p=linux-2.6 diff --git a/drivers/scsi/hosts.c b/drivers/scsi/hosts.c index 4e811ca327..fed0b02ebc 100644 --- a/drivers/scsi/hosts.c +++ b/drivers/scsi/hosts.c @@ -199,9 +199,13 @@ int scsi_add_host(struct Scsi_Host *shost, struct device *dev) if (!shost->can_queue) { printk(KERN_ERR "%s: can_queue = 0 no longer supported\n", sht->name); - goto out; + goto fail; } + error = scsi_setup_command_freelist(shost); + if (error) + goto fail; + if (!shost->shost_gendev.parent) shost->shost_gendev.parent = dev ? dev : &platform_bus; @@ -228,8 +232,8 @@ int scsi_add_host(struct Scsi_Host *shost, struct device *dev) } if (shost->transportt->create_work_queue) { - snprintf(shost->work_q_name, KOBJ_NAME_LEN, "scsi_wq_%d", - shost->host_no); + snprintf(shost->work_q_name, sizeof(shost->work_q_name), + "scsi_wq_%d", shost->host_no); shost->work_q = create_singlethread_workqueue( shost->work_q_name); if (!shost->work_q) { @@ -255,6 +259,8 @@ int scsi_add_host(struct Scsi_Host *shost, struct device *dev) out_del_gendev: device_del(&shost->shost_gendev); out: + scsi_destroy_command_freelist(shost); + fail: return error; } EXPORT_SYMBOL(scsi_add_host); @@ -284,7 +290,7 @@ static void scsi_host_dev_release(struct device *dev) kfree(shost); } -struct device_type scsi_host_type = { +static struct device_type scsi_host_type = { .name = "scsi_host", .release = scsi_host_dev_release, }; @@ -381,10 +387,6 @@ struct Scsi_Host *scsi_host_alloc(struct scsi_host_template *sht, int privsize) else shost->dma_boundary = 0xffffffff; - rval = scsi_setup_command_freelist(shost); - if (rval) - goto fail_kfree; - device_initialize(&shost->shost_gendev); snprintf(shost->shost_gendev.bus_id, BUS_ID_SIZE, "host%d", shost->host_no); @@ -404,14 +406,12 @@ struct Scsi_Host *scsi_host_alloc(struct scsi_host_template *sht, int privsize) "scsi_eh_%d", shost->host_no); if (IS_ERR(shost->ehandler)) { rval = PTR_ERR(shost->ehandler); - goto fail_destroy_freelist; + goto fail_kfree; } scsi_proc_hostdir_add(shost->hostt); return shost; - fail_destroy_freelist: - scsi_destroy_command_freelist(shost); fail_kfree: kfree(shost); return NULL; @@ -456,16 +456,22 @@ static int __scsi_host_match(struct device *dev, void *data) * * Return value: * A pointer to located Scsi_Host or NULL. + * + * The caller must do a scsi_host_put() to drop the reference + * that scsi_host_get() took. The put_device() below dropped + * the reference from class_find_device(). **/ struct Scsi_Host *scsi_host_lookup(unsigned short hostnum) { struct device *cdev; struct Scsi_Host *shost = ERR_PTR(-ENXIO); - cdev = class_find_device(&shost_class, &hostnum, __scsi_host_match); - if (cdev) + cdev = class_find_device(&shost_class, NULL, &hostnum, + __scsi_host_match); + if (cdev) { shost = scsi_host_get(class_to_shost(cdev)); - + put_device(cdev); + } return shost; } EXPORT_SYMBOL(scsi_host_lookup);