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.c106
1 files changed, 68 insertions, 38 deletions
diff --git a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c
index f9ecc3dea7df..f14945996ede 100644
--- a/drivers/scsi/scsi_scan.c
+++ b/drivers/scsi/scsi_scan.c
@@ -205,12 +205,11 @@ static struct scsi_device *scsi_alloc_sdev(struct scsi_target *starget,
205 int display_failure_msg = 1, ret; 205 int display_failure_msg = 1, ret;
206 struct Scsi_Host *shost = dev_to_shost(starget->dev.parent); 206 struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
207 207
208 sdev = kmalloc(sizeof(*sdev) + shost->transportt->device_size, 208 sdev = kzalloc(sizeof(*sdev) + shost->transportt->device_size,
209 GFP_ATOMIC); 209 GFP_ATOMIC);
210 if (!sdev) 210 if (!sdev)
211 goto out; 211 goto out;
212 212
213 memset(sdev, 0, sizeof(*sdev));
214 sdev->vendor = scsi_null_device_strs; 213 sdev->vendor = scsi_null_device_strs;
215 sdev->model = scsi_null_device_strs; 214 sdev->model = scsi_null_device_strs;
216 sdev->rev = scsi_null_device_strs; 215 sdev->rev = scsi_null_device_strs;
@@ -252,6 +251,7 @@ static struct scsi_device *scsi_alloc_sdev(struct scsi_target *starget,
252 /* release fn is set up in scsi_sysfs_device_initialise, so 251 /* release fn is set up in scsi_sysfs_device_initialise, so
253 * have to free and put manually here */ 252 * have to free and put manually here */
254 put_device(&starget->dev); 253 put_device(&starget->dev);
254 kfree(sdev);
255 goto out; 255 goto out;
256 } 256 }
257 257
@@ -288,10 +288,7 @@ static void scsi_target_dev_release(struct device *dev)
288{ 288{
289 struct device *parent = dev->parent; 289 struct device *parent = dev->parent;
290 struct scsi_target *starget = to_scsi_target(dev); 290 struct scsi_target *starget = to_scsi_target(dev);
291 struct Scsi_Host *shost = dev_to_shost(parent);
292 291
293 if (shost->hostt->target_destroy)
294 shost->hostt->target_destroy(starget);
295 kfree(starget); 292 kfree(starget);
296 put_device(parent); 293 put_device(parent);
297} 294}
@@ -333,13 +330,13 @@ static struct scsi_target *scsi_alloc_target(struct device *parent,
333 + shost->transportt->target_size; 330 + shost->transportt->target_size;
334 struct scsi_target *starget; 331 struct scsi_target *starget;
335 struct scsi_target *found_target; 332 struct scsi_target *found_target;
333 int error;
336 334
337 starget = kmalloc(size, GFP_KERNEL); 335 starget = kzalloc(size, GFP_KERNEL);
338 if (!starget) { 336 if (!starget) {
339 printk(KERN_ERR "%s: allocation failure\n", __FUNCTION__); 337 printk(KERN_ERR "%s: allocation failure\n", __FUNCTION__);
340 return NULL; 338 return NULL;
341 } 339 }
342 memset(starget, 0, size);
343 dev = &starget->dev; 340 dev = &starget->dev;
344 device_initialize(dev); 341 device_initialize(dev);
345 starget->reap_ref = 1; 342 starget->reap_ref = 1;
@@ -351,6 +348,8 @@ static struct scsi_target *scsi_alloc_target(struct device *parent,
351 starget->channel = channel; 348 starget->channel = channel;
352 INIT_LIST_HEAD(&starget->siblings); 349 INIT_LIST_HEAD(&starget->siblings);
353 INIT_LIST_HEAD(&starget->devices); 350 INIT_LIST_HEAD(&starget->devices);
351 starget->state = STARGET_RUNNING;
352 retry:
354 spin_lock_irqsave(shost->host_lock, flags); 353 spin_lock_irqsave(shost->host_lock, flags);
355 354
356 found_target = __scsi_find_target(parent, channel, id); 355 found_target = __scsi_find_target(parent, channel, id);
@@ -361,10 +360,20 @@ static struct scsi_target *scsi_alloc_target(struct device *parent,
361 spin_unlock_irqrestore(shost->host_lock, flags); 360 spin_unlock_irqrestore(shost->host_lock, flags);
362 /* allocate and add */ 361 /* allocate and add */
363 transport_setup_device(dev); 362 transport_setup_device(dev);
364 device_add(dev); 363 error = device_add(dev);
364 if (error) {
365 dev_err(dev, "target device_add failed, error %d\n", error);
366 spin_lock_irqsave(shost->host_lock, flags);
367 list_del_init(&starget->siblings);
368 spin_unlock_irqrestore(shost->host_lock, flags);
369 transport_destroy_device(dev);
370 put_device(parent);
371 kfree(starget);
372 return NULL;
373 }
365 transport_add_device(dev); 374 transport_add_device(dev);
366 if (shost->hostt->target_alloc) { 375 if (shost->hostt->target_alloc) {
367 int error = shost->hostt->target_alloc(starget); 376 error = shost->hostt->target_alloc(starget);
368 377
369 if(error) { 378 if(error) {
370 dev_printk(KERN_ERR, dev, "target allocation failed, error %d\n", error); 379 dev_printk(KERN_ERR, dev, "target allocation failed, error %d\n", error);
@@ -383,8 +392,15 @@ static struct scsi_target *scsi_alloc_target(struct device *parent,
383 found_target->reap_ref++; 392 found_target->reap_ref++;
384 spin_unlock_irqrestore(shost->host_lock, flags); 393 spin_unlock_irqrestore(shost->host_lock, flags);
385 put_device(parent); 394 put_device(parent);
386 kfree(starget); 395 if (found_target->state != STARGET_DEL) {
387 return found_target; 396 kfree(starget);
397 return found_target;
398 }
399 /* Unfortunately, we found a dying target; need to
400 * wait until it's dead before we can get a new one */
401 put_device(&found_target->dev);
402 flush_scheduled_work();
403 goto retry;
388} 404}
389 405
390static void scsi_target_reap_usercontext(void *data) 406static void scsi_target_reap_usercontext(void *data)
@@ -393,21 +409,15 @@ static void scsi_target_reap_usercontext(void *data)
393 struct Scsi_Host *shost = dev_to_shost(starget->dev.parent); 409 struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
394 unsigned long flags; 410 unsigned long flags;
395 411
412 transport_remove_device(&starget->dev);
413 device_del(&starget->dev);
414 transport_destroy_device(&starget->dev);
396 spin_lock_irqsave(shost->host_lock, flags); 415 spin_lock_irqsave(shost->host_lock, flags);
397 416 if (shost->hostt->target_destroy)
398 if (--starget->reap_ref == 0 && list_empty(&starget->devices)) { 417 shost->hostt->target_destroy(starget);
399 list_del_init(&starget->siblings); 418 list_del_init(&starget->siblings);
400 spin_unlock_irqrestore(shost->host_lock, flags);
401 transport_remove_device(&starget->dev);
402 device_del(&starget->dev);
403 transport_destroy_device(&starget->dev);
404 put_device(&starget->dev);
405 return;
406
407 }
408 spin_unlock_irqrestore(shost->host_lock, flags); 419 spin_unlock_irqrestore(shost->host_lock, flags);
409 420 put_device(&starget->dev);
410 return;
411} 421}
412 422
413/** 423/**
@@ -421,7 +431,23 @@ static void scsi_target_reap_usercontext(void *data)
421 */ 431 */
422void scsi_target_reap(struct scsi_target *starget) 432void scsi_target_reap(struct scsi_target *starget)
423{ 433{
424 scsi_execute_in_process_context(scsi_target_reap_usercontext, starget); 434 struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
435 unsigned long flags;
436
437 spin_lock_irqsave(shost->host_lock, flags);
438
439 if (--starget->reap_ref == 0 && list_empty(&starget->devices)) {
440 BUG_ON(starget->state == STARGET_DEL);
441 starget->state = STARGET_DEL;
442 spin_unlock_irqrestore(shost->host_lock, flags);
443 execute_in_process_context(scsi_target_reap_usercontext,
444 starget, &starget->ew);
445 return;
446
447 }
448 spin_unlock_irqrestore(shost->host_lock, flags);
449
450 return;
425} 451}
426 452
427/** 453/**
@@ -689,12 +715,8 @@ static int scsi_add_lun(struct scsi_device *sdev, char *inq_result, int *bflags)
689 if (inq_result[7] & 0x10) 715 if (inq_result[7] & 0x10)
690 sdev->sdtr = 1; 716 sdev->sdtr = 1;
691 717
692 sprintf(sdev->devfs_name, "scsi/host%d/bus%d/target%d/lun%d",
693 sdev->host->host_no, sdev->channel,
694 sdev->id, sdev->lun);
695
696 /* 718 /*
697 * End driverfs/devfs code. 719 * End sysfs code.
698 */ 720 */
699 721
700 if ((sdev->scsi_level >= SCSI_2) && (inq_result[7] & 2) && 722 if ((sdev->scsi_level >= SCSI_2) && (inq_result[7] & 2) &&
@@ -871,6 +893,19 @@ static int scsi_probe_and_add_lun(struct scsi_target *starget,
871 goto out_free_result; 893 goto out_free_result;
872 } 894 }
873 895
896 /*
897 * Non-standard SCSI targets may set the PDT to 0x1f (unknown or
898 * no device type) instead of using the Peripheral Qualifier to
899 * indicate that no LUN is present. For example, USB UFI does this.
900 */
901 if (starget->pdt_1f_for_no_lun && (result[0] & 0x1f) == 0x1f) {
902 SCSI_LOG_SCAN_BUS(3, printk(KERN_INFO
903 "scsi scan: peripheral device type"
904 " of 31, no device added\n"));
905 res = SCSI_SCAN_TARGET_PRESENT;
906 goto out_free_result;
907 }
908
874 res = scsi_add_lun(sdev, result, &bflags); 909 res = scsi_add_lun(sdev, result, &bflags);
875 if (res == SCSI_SCAN_LUN_PRESENT) { 910 if (res == SCSI_SCAN_LUN_PRESENT) {
876 if (bflags & BLIST_KEY) { 911 if (bflags & BLIST_KEY) {
@@ -1261,9 +1296,8 @@ static int scsi_report_lun_scan(struct scsi_target *starget, int bflags,
1261struct scsi_device *__scsi_add_device(struct Scsi_Host *shost, uint channel, 1296struct scsi_device *__scsi_add_device(struct Scsi_Host *shost, uint channel,
1262 uint id, uint lun, void *hostdata) 1297 uint id, uint lun, void *hostdata)
1263{ 1298{
1264 struct scsi_device *sdev; 1299 struct scsi_device *sdev = ERR_PTR(-ENODEV);
1265 struct device *parent = &shost->shost_gendev; 1300 struct device *parent = &shost->shost_gendev;
1266 int res;
1267 struct scsi_target *starget; 1301 struct scsi_target *starget;
1268 1302
1269 starget = scsi_alloc_target(parent, channel, id); 1303 starget = scsi_alloc_target(parent, channel, id);
@@ -1272,12 +1306,8 @@ struct scsi_device *__scsi_add_device(struct Scsi_Host *shost, uint channel,
1272 1306
1273 get_device(&starget->dev); 1307 get_device(&starget->dev);
1274 mutex_lock(&shost->scan_mutex); 1308 mutex_lock(&shost->scan_mutex);
1275 if (scsi_host_scan_allowed(shost)) { 1309 if (scsi_host_scan_allowed(shost))
1276 res = scsi_probe_and_add_lun(starget, lun, NULL, &sdev, 1, 1310 scsi_probe_and_add_lun(starget, lun, NULL, &sdev, 1, hostdata);
1277 hostdata);
1278 if (res != SCSI_SCAN_LUN_PRESENT)
1279 sdev = ERR_PTR(-ENODEV);
1280 }
1281 mutex_unlock(&shost->scan_mutex); 1311 mutex_unlock(&shost->scan_mutex);
1282 scsi_target_reap(starget); 1312 scsi_target_reap(starget);
1283 put_device(&starget->dev); 1313 put_device(&starget->dev);