diff options
author | James Bottomley <James.Bottomley@HansenPartnership.com> | 2008-04-21 11:57:20 -0400 |
---|---|---|
committer | James Bottomley <James.Bottomley@HansenPartnership.com> | 2008-04-27 13:19:54 -0400 |
commit | 542bd1377a963070bc4a03ff7d2690ddf3920596 (patch) | |
tree | 81c70ca891f8a6c5ef84df211fd92ef0c86393d1 | |
parent | 582fb6c03a0e89d05e4efa8a3e4bd09d0942dadc (diff) |
[SCSI] fix SLUB WARN_ON
We're getting a WARN_ON from SLUB indicating that we're trying to free
caches with in-use objects. The root cause is a new dependency in the
command/sense free on unchecked_isa_dma. The WARN_ON is caused by
drivers which change this in their setup after the command/sense cache
is allocated.
The fix is to move the allocation of this cache into scsi_add_host()
so things like gdth have an opportunity to modify it between alloc and
add (but *not* after).
The true fix would be to move unchecked_isa_dma into the template and
out of the host, so it because a truly read only variable.
Signed-off-by: James Bottomley <James.Bottomley@HansenPartnership.com>
-rw-r--r-- | drivers/scsi/hosts.c | 16 |
1 files changed, 8 insertions, 8 deletions
diff --git a/drivers/scsi/hosts.c b/drivers/scsi/hosts.c index 4e811ca3270e..3690360d7a79 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) | |||
199 | if (!shost->can_queue) { | 199 | if (!shost->can_queue) { |
200 | printk(KERN_ERR "%s: can_queue = 0 no longer supported\n", | 200 | printk(KERN_ERR "%s: can_queue = 0 no longer supported\n", |
201 | sht->name); | 201 | sht->name); |
202 | goto out; | 202 | goto fail; |
203 | } | 203 | } |
204 | 204 | ||
205 | error = scsi_setup_command_freelist(shost); | ||
206 | if (error) | ||
207 | goto fail; | ||
208 | |||
205 | if (!shost->shost_gendev.parent) | 209 | if (!shost->shost_gendev.parent) |
206 | shost->shost_gendev.parent = dev ? dev : &platform_bus; | 210 | shost->shost_gendev.parent = dev ? dev : &platform_bus; |
207 | 211 | ||
@@ -255,6 +259,8 @@ int scsi_add_host(struct Scsi_Host *shost, struct device *dev) | |||
255 | out_del_gendev: | 259 | out_del_gendev: |
256 | device_del(&shost->shost_gendev); | 260 | device_del(&shost->shost_gendev); |
257 | out: | 261 | out: |
262 | scsi_destroy_command_freelist(shost); | ||
263 | fail: | ||
258 | return error; | 264 | return error; |
259 | } | 265 | } |
260 | EXPORT_SYMBOL(scsi_add_host); | 266 | EXPORT_SYMBOL(scsi_add_host); |
@@ -381,10 +387,6 @@ struct Scsi_Host *scsi_host_alloc(struct scsi_host_template *sht, int privsize) | |||
381 | else | 387 | else |
382 | shost->dma_boundary = 0xffffffff; | 388 | shost->dma_boundary = 0xffffffff; |
383 | 389 | ||
384 | rval = scsi_setup_command_freelist(shost); | ||
385 | if (rval) | ||
386 | goto fail_kfree; | ||
387 | |||
388 | device_initialize(&shost->shost_gendev); | 390 | device_initialize(&shost->shost_gendev); |
389 | snprintf(shost->shost_gendev.bus_id, BUS_ID_SIZE, "host%d", | 391 | snprintf(shost->shost_gendev.bus_id, BUS_ID_SIZE, "host%d", |
390 | shost->host_no); | 392 | shost->host_no); |
@@ -404,14 +406,12 @@ struct Scsi_Host *scsi_host_alloc(struct scsi_host_template *sht, int privsize) | |||
404 | "scsi_eh_%d", shost->host_no); | 406 | "scsi_eh_%d", shost->host_no); |
405 | if (IS_ERR(shost->ehandler)) { | 407 | if (IS_ERR(shost->ehandler)) { |
406 | rval = PTR_ERR(shost->ehandler); | 408 | rval = PTR_ERR(shost->ehandler); |
407 | goto fail_destroy_freelist; | 409 | goto fail_kfree; |
408 | } | 410 | } |
409 | 411 | ||
410 | scsi_proc_hostdir_add(shost->hostt); | 412 | scsi_proc_hostdir_add(shost->hostt); |
411 | return shost; | 413 | return shost; |
412 | 414 | ||
413 | fail_destroy_freelist: | ||
414 | scsi_destroy_command_freelist(shost); | ||
415 | fail_kfree: | 415 | fail_kfree: |
416 | kfree(shost); | 416 | kfree(shost); |
417 | return NULL; | 417 | return NULL; |