diff options
Diffstat (limited to 'drivers/scsi/scsi_scan.c')
-rw-r--r-- | drivers/scsi/scsi_scan.c | 20 |
1 files changed, 16 insertions, 4 deletions
diff --git a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c index 31d05ab0b2fc..fd9e281c3bfe 100644 --- a/drivers/scsi/scsi_scan.c +++ b/drivers/scsi/scsi_scan.c | |||
@@ -266,6 +266,18 @@ static struct scsi_target *__scsi_find_target(struct device *parent, | |||
266 | return found_starget; | 266 | return found_starget; |
267 | } | 267 | } |
268 | 268 | ||
269 | /** | ||
270 | * scsi_alloc_target - allocate a new or find an existing target | ||
271 | * @parent: parent of the target (need not be a scsi host) | ||
272 | * @channel: target channel number (zero if no channels) | ||
273 | * @id: target id number | ||
274 | * | ||
275 | * Return an existing target if one exists, provided it hasn't already | ||
276 | * gone into STARGET_DEL state, otherwise allocate a new target. | ||
277 | * | ||
278 | * The target is returned with an incremented reference, so the caller | ||
279 | * is responsible for both reaping and doing a last put | ||
280 | */ | ||
269 | static struct scsi_target *scsi_alloc_target(struct device *parent, | 281 | static struct scsi_target *scsi_alloc_target(struct device *parent, |
270 | int channel, uint id) | 282 | int channel, uint id) |
271 | { | 283 | { |
@@ -331,14 +343,15 @@ static struct scsi_target *scsi_alloc_target(struct device *parent, | |||
331 | return NULL; | 343 | return NULL; |
332 | } | 344 | } |
333 | } | 345 | } |
346 | get_device(dev); | ||
334 | 347 | ||
335 | return starget; | 348 | return starget; |
336 | 349 | ||
337 | found: | 350 | found: |
338 | found_target->reap_ref++; | 351 | found_target->reap_ref++; |
339 | spin_unlock_irqrestore(shost->host_lock, flags); | 352 | spin_unlock_irqrestore(shost->host_lock, flags); |
340 | put_device(parent); | ||
341 | if (found_target->state != STARGET_DEL) { | 353 | if (found_target->state != STARGET_DEL) { |
354 | put_device(parent); | ||
342 | kfree(starget); | 355 | kfree(starget); |
343 | return found_target; | 356 | return found_target; |
344 | } | 357 | } |
@@ -1341,7 +1354,6 @@ struct scsi_device *__scsi_add_device(struct Scsi_Host *shost, uint channel, | |||
1341 | if (!starget) | 1354 | if (!starget) |
1342 | return ERR_PTR(-ENOMEM); | 1355 | return ERR_PTR(-ENOMEM); |
1343 | 1356 | ||
1344 | get_device(&starget->dev); | ||
1345 | mutex_lock(&shost->scan_mutex); | 1357 | mutex_lock(&shost->scan_mutex); |
1346 | if (scsi_host_scan_allowed(shost)) | 1358 | if (scsi_host_scan_allowed(shost)) |
1347 | scsi_probe_and_add_lun(starget, lun, NULL, &sdev, 1, hostdata); | 1359 | scsi_probe_and_add_lun(starget, lun, NULL, &sdev, 1, hostdata); |
@@ -1400,7 +1412,6 @@ static void __scsi_scan_target(struct device *parent, unsigned int channel, | |||
1400 | if (!starget) | 1412 | if (!starget) |
1401 | return; | 1413 | return; |
1402 | 1414 | ||
1403 | get_device(&starget->dev); | ||
1404 | if (lun != SCAN_WILD_CARD) { | 1415 | if (lun != SCAN_WILD_CARD) { |
1405 | /* | 1416 | /* |
1406 | * Scan for a specific host/chan/id/lun. | 1417 | * Scan for a specific host/chan/id/lun. |
@@ -1582,7 +1593,8 @@ struct scsi_device *scsi_get_host_dev(struct Scsi_Host *shost) | |||
1582 | if (sdev) { | 1593 | if (sdev) { |
1583 | sdev->sdev_gendev.parent = get_device(&starget->dev); | 1594 | sdev->sdev_gendev.parent = get_device(&starget->dev); |
1584 | sdev->borken = 0; | 1595 | sdev->borken = 0; |
1585 | } | 1596 | } else |
1597 | scsi_target_reap(starget); | ||
1586 | put_device(&starget->dev); | 1598 | put_device(&starget->dev); |
1587 | out: | 1599 | out: |
1588 | mutex_unlock(&shost->scan_mutex); | 1600 | mutex_unlock(&shost->scan_mutex); |