diff options
| -rw-r--r-- | drivers/scsi/scsi_scan.c | 48 |
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 | ||
| 403 | struct work_queue_wrapper { | ||
| 404 | struct work_struct work; | ||
| 405 | struct scsi_target *starget; | ||
| 406 | }; | ||
| 407 | |||
| 408 | static 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 | */ |
| 412 | void scsi_target_reap(struct scsi_target *starget) | 441 | void 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 | /** |
