summaryrefslogtreecommitdiff
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.c26
1 files changed, 23 insertions, 3 deletions
diff --git a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c
index cca772624ae7..9fa209097e3b 100644
--- a/drivers/scsi/scsi_scan.c
+++ b/drivers/scsi/scsi_scan.c
@@ -293,6 +293,10 @@ static void scsi_target_dev_release(struct device *dev)
{
struct device *parent = dev->parent;
struct scsi_target *starget = to_scsi_target(dev);
+ struct Scsi_Host *shost = dev_to_shost(parent);
+
+ if (shost->hostt->target_destroy)
+ shost->hostt->target_destroy(starget);
kfree(starget);
put_device(parent);
}
@@ -360,9 +364,23 @@ static struct scsi_target *scsi_alloc_target(struct device *parent,
list_add_tail(&starget->siblings, &shost->__targets);
spin_unlock_irqrestore(shost->host_lock, flags);
/* allocate and add */
- transport_setup_device(&starget->dev);
- device_add(&starget->dev);
- transport_add_device(&starget->dev);
+ transport_setup_device(dev);
+ device_add(dev);
+ transport_add_device(dev);
+ if (shost->hostt->target_alloc) {
+ int error = shost->hostt->target_alloc(starget);
+
+ if(error) {
+ dev_printk(KERN_ERR, dev, "target allocation failed, error %d\n", error);
+ /* don't want scsi_target_reap to do the final
+ * put because it will be under the host lock */
+ get_device(dev);
+ scsi_target_reap(starget);
+ put_device(dev);
+ return NULL;
+ }
+ }
+
return starget;
found:
@@ -625,6 +643,7 @@ static int scsi_add_lun(struct scsi_device *sdev, char *inq_result, int *bflags)
case TYPE_MEDIUM_CHANGER:
case TYPE_ENCLOSURE:
case TYPE_COMM:
+ case TYPE_RBC:
sdev->writeable = 1;
break;
case TYPE_WORM:
@@ -1197,6 +1216,7 @@ struct scsi_device *__scsi_add_device(struct Scsi_Host *shost, uint channel,
if (!starget)
return ERR_PTR(-ENOMEM);
+ get_device(&starget->dev);
down(&shost->scan_mutex);
res = scsi_probe_and_add_lun(starget, lun, NULL, &sdev, 1, hostdata);
if (res != SCSI_SCAN_LUN_PRESENT)