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.c49
1 files changed, 39 insertions, 10 deletions
diff --git a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c
index 94e5167f260d..4e6709f448e1 100644
--- a/drivers/scsi/scsi_scan.c
+++ b/drivers/scsi/scsi_scan.c
@@ -400,6 +400,36 @@ static struct scsi_target *scsi_alloc_target(struct device *parent,
400 return found_target; 400 return found_target;
401} 401}
402 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
403/** 433/**
404 * 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
405 * 435 *
@@ -411,19 +441,18 @@ static struct scsi_target *scsi_alloc_target(struct device *parent,
411 */ 441 */
412void scsi_target_reap(struct scsi_target *starget) 442void scsi_target_reap(struct scsi_target *starget)
413{ 443{
414 struct Scsi_Host *shost = dev_to_shost(starget->dev.parent); 444 struct work_queue_wrapper *wqw =
415 unsigned long flags; 445 kzalloc(sizeof(struct work_queue_wrapper), GFP_ATOMIC);
416 spin_lock_irqsave(shost->host_lock, flags);
417 446
418 if (--starget->reap_ref == 0 && list_empty(&starget->devices)) { 447 if (!wqw) {
419 list_del_init(&starget->siblings); 448 starget_printk(KERN_ERR, starget,
420 spin_unlock_irqrestore(shost->host_lock, flags); 449 "Failed to allocate memory in scsi_reap_target()\n");
421 device_del(&starget->dev);
422 transport_unregister_device(&starget->dev);
423 put_device(&starget->dev);
424 return; 450 return;
425 } 451 }
426 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);
427} 456}
428 457
429/** 458/**