aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/scsi_scan.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/scsi/scsi_scan.c')
-rw-r--r--drivers/scsi/scsi_scan.c52
1 files changed, 39 insertions, 13 deletions
diff --git a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c
index 374853df9cca..4e6709f448e1 100644
--- a/drivers/scsi/scsi_scan.c
+++ b/drivers/scsi/scsi_scan.c
@@ -266,8 +266,6 @@ static struct scsi_device *scsi_alloc_sdev(struct scsi_target *starget,
266 /* 266 /*
267 * if LLDD reports slave not present, don't clutter 267 * if LLDD reports slave not present, don't clutter
268 * console with alloc failure messages 268 * console with alloc failure messages
269
270
271 */ 269 */
272 if (ret == -ENXIO) 270 if (ret == -ENXIO)
273 display_failure_msg = 0; 271 display_failure_msg = 0;
@@ -279,7 +277,6 @@ static struct scsi_device *scsi_alloc_sdev(struct scsi_target *starget,
279 277
280out_device_destroy: 278out_device_destroy:
281 transport_destroy_device(&sdev->sdev_gendev); 279 transport_destroy_device(&sdev->sdev_gendev);
282 scsi_free_queue(sdev->request_queue);
283 put_device(&sdev->sdev_gendev); 280 put_device(&sdev->sdev_gendev);
284out: 281out:
285 if (display_failure_msg) 282 if (display_failure_msg)
@@ -403,6 +400,36 @@ static struct scsi_target *scsi_alloc_target(struct device *parent,
403 return found_target; 400 return found_target;
404} 401}
405 402
403struct work_queue_wrapper {
404 struct work_struct work;
405 struct scsi_target *starget;
406};
407
408static void scsi_target_reap_work(void *data) {
409 struct work_queue_wrapper *wqw = (struct work_queue_wrapper *)data;
410 struct scsi_target *starget = wqw->starget;
411 struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
412 unsigned long flags;
413
414 kfree(wqw);
415
416 spin_lock_irqsave(shost->host_lock, flags);
417
418 if (--starget->reap_ref == 0 && list_empty(&starget->devices)) {
419 list_del_init(&starget->siblings);
420 spin_unlock_irqrestore(shost->host_lock, flags);
421 transport_remove_device(&starget->dev);
422 device_del(&starget->dev);
423 transport_destroy_device(&starget->dev);
424 put_device(&starget->dev);
425 return;
426
427 }
428 spin_unlock_irqrestore(shost->host_lock, flags);
429
430 return;
431}
432
406/** 433/**
407 * scsi_target_reap - check to see if target is in use and destroy if not 434 * scsi_target_reap - check to see if target is in use and destroy if not
408 * 435 *
@@ -414,19 +441,18 @@ static struct scsi_target *scsi_alloc_target(struct device *parent,
414 */ 441 */
415void scsi_target_reap(struct scsi_target *starget) 442void scsi_target_reap(struct scsi_target *starget)
416{ 443{
417 struct Scsi_Host *shost = dev_to_shost(starget->dev.parent); 444 struct work_queue_wrapper *wqw =
418 unsigned long flags; 445 kzalloc(sizeof(struct work_queue_wrapper), GFP_ATOMIC);
419 spin_lock_irqsave(shost->host_lock, flags);
420 446
421 if (--starget->reap_ref == 0 && list_empty(&starget->devices)) { 447 if (!wqw) {
422 list_del_init(&starget->siblings); 448 starget_printk(KERN_ERR, starget,
423 spin_unlock_irqrestore(shost->host_lock, flags); 449 "Failed to allocate memory in scsi_reap_target()\n");
424 device_del(&starget->dev);
425 transport_unregister_device(&starget->dev);
426 put_device(&starget->dev);
427 return; 450 return;
428 } 451 }
429 spin_unlock_irqrestore(shost->host_lock, flags); 452
453 INIT_WORK(&wqw->work, scsi_target_reap_work, wqw);
454 wqw->starget = starget;
455 schedule_work(&wqw->work);
430} 456}
431 457
432/** 458/**