aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/scsi')
-rw-r--r--drivers/scsi/scsi_scan.c48
1 files changed, 38 insertions, 10 deletions
diff --git a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c
index 94e5167f260d..e36c21e06d31 100644
--- a/drivers/scsi/scsi_scan.c
+++ b/drivers/scsi/scsi_scan.c
@@ -400,6 +400,35 @@ 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 device_del(&starget->dev);
422 transport_unregister_device(&starget->dev);
423 put_device(&starget->dev);
424 return;
425
426 }
427 spin_unlock_irqrestore(shost->host_lock, flags);
428
429 return;
430}
431
403/** 432/**
404 * scsi_target_reap - check to see if target is in use and destroy if not 433 * scsi_target_reap - check to see if target is in use and destroy if not
405 * 434 *
@@ -411,19 +440,18 @@ static struct scsi_target *scsi_alloc_target(struct device *parent,
411 */ 440 */
412void scsi_target_reap(struct scsi_target *starget) 441void scsi_target_reap(struct scsi_target *starget)
413{ 442{
414 struct Scsi_Host *shost = dev_to_shost(starget->dev.parent); 443 struct work_queue_wrapper *wqw =
415 unsigned long flags; 444 kzalloc(sizeof(struct work_queue_wrapper), GFP_ATOMIC);
416 spin_lock_irqsave(shost->host_lock, flags);
417 445
418 if (--starget->reap_ref == 0 && list_empty(&starget->devices)) { 446 if (!wqw) {
419 list_del_init(&starget->siblings); 447 starget_printk(KERN_ERR, starget,
420 spin_unlock_irqrestore(shost->host_lock, flags); 448 "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; 449 return;
425 } 450 }
426 spin_unlock_irqrestore(shost->host_lock, flags); 451
452 INIT_WORK(&wqw->work, scsi_target_reap_work, wqw);
453 wqw->starget = starget;
454 schedule_work(&wqw->work);
427} 455}
428 456
429/** 457/**