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.c84
1 files changed, 44 insertions, 40 deletions
diff --git a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c
index e67c14e31bab..fcd7455ffc39 100644
--- a/drivers/scsi/scsi_scan.c
+++ b/drivers/scsi/scsi_scan.c
@@ -322,6 +322,21 @@ out:
322 return NULL; 322 return NULL;
323} 323}
324 324
325static void scsi_target_destroy(struct scsi_target *starget)
326{
327 struct device *dev = &starget->dev;
328 struct Scsi_Host *shost = dev_to_shost(dev->parent);
329 unsigned long flags;
330
331 transport_destroy_device(dev);
332 spin_lock_irqsave(shost->host_lock, flags);
333 if (shost->hostt->target_destroy)
334 shost->hostt->target_destroy(starget);
335 list_del_init(&starget->siblings);
336 spin_unlock_irqrestore(shost->host_lock, flags);
337 put_device(dev);
338}
339
325static void scsi_target_dev_release(struct device *dev) 340static void scsi_target_dev_release(struct device *dev)
326{ 341{
327 struct device *parent = dev->parent; 342 struct device *parent = dev->parent;
@@ -331,9 +346,14 @@ static void scsi_target_dev_release(struct device *dev)
331 put_device(parent); 346 put_device(parent);
332} 347}
333 348
349struct device_type scsi_target_type = {
350 .name = "scsi_target",
351 .release = scsi_target_dev_release,
352};
353
334int scsi_is_target_device(const struct device *dev) 354int scsi_is_target_device(const struct device *dev)
335{ 355{
336 return dev->release == scsi_target_dev_release; 356 return dev->type == &scsi_target_type;
337} 357}
338EXPORT_SYMBOL(scsi_is_target_device); 358EXPORT_SYMBOL(scsi_is_target_device);
339 359
@@ -391,14 +411,17 @@ static struct scsi_target *scsi_alloc_target(struct device *parent,
391 device_initialize(dev); 411 device_initialize(dev);
392 starget->reap_ref = 1; 412 starget->reap_ref = 1;
393 dev->parent = get_device(parent); 413 dev->parent = get_device(parent);
394 dev->release = scsi_target_dev_release;
395 sprintf(dev->bus_id, "target%d:%d:%d", 414 sprintf(dev->bus_id, "target%d:%d:%d",
396 shost->host_no, channel, id); 415 shost->host_no, channel, id);
416#ifndef CONFIG_SYSFS_DEPRECATED
417 dev->bus = &scsi_bus_type;
418#endif
419 dev->type = &scsi_target_type;
397 starget->id = id; 420 starget->id = id;
398 starget->channel = channel; 421 starget->channel = channel;
399 INIT_LIST_HEAD(&starget->siblings); 422 INIT_LIST_HEAD(&starget->siblings);
400 INIT_LIST_HEAD(&starget->devices); 423 INIT_LIST_HEAD(&starget->devices);
401 starget->state = STARGET_RUNNING; 424 starget->state = STARGET_CREATED;
402 starget->scsi_level = SCSI_2; 425 starget->scsi_level = SCSI_2;
403 retry: 426 retry:
404 spin_lock_irqsave(shost->host_lock, flags); 427 spin_lock_irqsave(shost->host_lock, flags);
@@ -411,18 +434,6 @@ static struct scsi_target *scsi_alloc_target(struct device *parent,
411 spin_unlock_irqrestore(shost->host_lock, flags); 434 spin_unlock_irqrestore(shost->host_lock, flags);
412 /* allocate and add */ 435 /* allocate and add */
413 transport_setup_device(dev); 436 transport_setup_device(dev);
414 error = device_add(dev);
415 if (error) {
416 dev_err(dev, "target device_add failed, error %d\n", error);
417 spin_lock_irqsave(shost->host_lock, flags);
418 list_del_init(&starget->siblings);
419 spin_unlock_irqrestore(shost->host_lock, flags);
420 transport_destroy_device(dev);
421 put_device(parent);
422 kfree(starget);
423 return NULL;
424 }
425 transport_add_device(dev);
426 if (shost->hostt->target_alloc) { 437 if (shost->hostt->target_alloc) {
427 error = shost->hostt->target_alloc(starget); 438 error = shost->hostt->target_alloc(starget);
428 439
@@ -430,9 +441,7 @@ static struct scsi_target *scsi_alloc_target(struct device *parent,
430 dev_printk(KERN_ERR, dev, "target allocation failed, error %d\n", error); 441 dev_printk(KERN_ERR, dev, "target allocation failed, error %d\n", error);
431 /* don't want scsi_target_reap to do the final 442 /* don't want scsi_target_reap to do the final
432 * put because it will be under the host lock */ 443 * put because it will be under the host lock */
433 get_device(dev); 444 scsi_target_destroy(starget);
434 scsi_target_reap(starget);
435 put_device(dev);
436 return NULL; 445 return NULL;
437 } 446 }
438 } 447 }
@@ -459,18 +468,10 @@ static void scsi_target_reap_usercontext(struct work_struct *work)
459{ 468{
460 struct scsi_target *starget = 469 struct scsi_target *starget =
461 container_of(work, struct scsi_target, ew.work); 470 container_of(work, struct scsi_target, ew.work);
462 struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
463 unsigned long flags;
464 471
465 transport_remove_device(&starget->dev); 472 transport_remove_device(&starget->dev);
466 device_del(&starget->dev); 473 device_del(&starget->dev);
467 transport_destroy_device(&starget->dev); 474 scsi_target_destroy(starget);
468 spin_lock_irqsave(shost->host_lock, flags);
469 if (shost->hostt->target_destroy)
470 shost->hostt->target_destroy(starget);
471 list_del_init(&starget->siblings);
472 spin_unlock_irqrestore(shost->host_lock, flags);
473 put_device(&starget->dev);
474} 475}
475 476
476/** 477/**
@@ -485,21 +486,25 @@ void scsi_target_reap(struct scsi_target *starget)
485{ 486{
486 struct Scsi_Host *shost = dev_to_shost(starget->dev.parent); 487 struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
487 unsigned long flags; 488 unsigned long flags;
489 enum scsi_target_state state;
490 int empty;
488 491
489 spin_lock_irqsave(shost->host_lock, flags); 492 spin_lock_irqsave(shost->host_lock, flags);
493 state = starget->state;
494 empty = --starget->reap_ref == 0 &&
495 list_empty(&starget->devices) ? 1 : 0;
496 spin_unlock_irqrestore(shost->host_lock, flags);
490 497
491 if (--starget->reap_ref == 0 && list_empty(&starget->devices)) { 498 if (!empty)
492 BUG_ON(starget->state == STARGET_DEL);
493 starget->state = STARGET_DEL;
494 spin_unlock_irqrestore(shost->host_lock, flags);
495 execute_in_process_context(scsi_target_reap_usercontext,
496 &starget->ew);
497 return; 499 return;
498 500
499 } 501 BUG_ON(state == STARGET_DEL);
500 spin_unlock_irqrestore(shost->host_lock, flags); 502 starget->state = STARGET_DEL;
501 503 if (state == STARGET_CREATED)
502 return; 504 scsi_target_destroy(starget);
505 else
506 execute_in_process_context(scsi_target_reap_usercontext,
507 &starget->ew);
503} 508}
504 509
505/** 510/**
@@ -1048,8 +1053,9 @@ static int scsi_probe_and_add_lun(struct scsi_target *starget,
1048 scsi_inq_str(vend, result, 8, 16), 1053 scsi_inq_str(vend, result, 8, 16),
1049 scsi_inq_str(mod, result, 16, 32)); 1054 scsi_inq_str(mod, result, 16, 32));
1050 }); 1055 });
1056
1051 } 1057 }
1052 1058
1053 res = SCSI_SCAN_TARGET_PRESENT; 1059 res = SCSI_SCAN_TARGET_PRESENT;
1054 goto out_free_result; 1060 goto out_free_result;
1055 } 1061 }
@@ -1489,7 +1495,6 @@ struct scsi_device *__scsi_add_device(struct Scsi_Host *shost, uint channel,
1489 if (scsi_host_scan_allowed(shost)) 1495 if (scsi_host_scan_allowed(shost))
1490 scsi_probe_and_add_lun(starget, lun, NULL, &sdev, 1, hostdata); 1496 scsi_probe_and_add_lun(starget, lun, NULL, &sdev, 1, hostdata);
1491 mutex_unlock(&shost->scan_mutex); 1497 mutex_unlock(&shost->scan_mutex);
1492 transport_configure_device(&starget->dev);
1493 scsi_target_reap(starget); 1498 scsi_target_reap(starget);
1494 put_device(&starget->dev); 1499 put_device(&starget->dev);
1495 1500
@@ -1570,7 +1575,6 @@ static void __scsi_scan_target(struct device *parent, unsigned int channel,
1570 out_reap: 1575 out_reap:
1571 /* now determine if the target has any children at all 1576 /* now determine if the target has any children at all
1572 * and if not, nuke it */ 1577 * and if not, nuke it */
1573 transport_configure_device(&starget->dev);
1574 scsi_target_reap(starget); 1578 scsi_target_reap(starget);
1575 1579
1576 put_device(&starget->dev); 1580 put_device(&starget->dev);