diff options
Diffstat (limited to 'drivers/scsi/scsi_scan.c')
| -rw-r--r-- | drivers/scsi/scsi_scan.c | 88 |
1 files changed, 59 insertions, 29 deletions
diff --git a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c index 19c9a232a754..b86f170fa8ed 100644 --- a/drivers/scsi/scsi_scan.c +++ b/drivers/scsi/scsi_scan.c | |||
| @@ -870,8 +870,12 @@ static int scsi_probe_and_add_lun(struct scsi_target *starget, | |||
| 870 | out_free_sdev: | 870 | out_free_sdev: |
| 871 | if (res == SCSI_SCAN_LUN_PRESENT) { | 871 | if (res == SCSI_SCAN_LUN_PRESENT) { |
| 872 | if (sdevp) { | 872 | if (sdevp) { |
| 873 | scsi_device_get(sdev); | 873 | if (scsi_device_get(sdev) == 0) { |
| 874 | *sdevp = sdev; | 874 | *sdevp = sdev; |
| 875 | } else { | ||
| 876 | __scsi_remove_device(sdev); | ||
| 877 | res = SCSI_SCAN_NO_RESPONSE; | ||
| 878 | } | ||
| 875 | } | 879 | } |
| 876 | } else { | 880 | } else { |
| 877 | if (sdev->host->hostt->slave_destroy) | 881 | if (sdev->host->hostt->slave_destroy) |
| @@ -1260,6 +1264,19 @@ struct scsi_device *__scsi_add_device(struct Scsi_Host *shost, uint channel, | |||
| 1260 | } | 1264 | } |
| 1261 | EXPORT_SYMBOL(__scsi_add_device); | 1265 | EXPORT_SYMBOL(__scsi_add_device); |
| 1262 | 1266 | ||
| 1267 | int scsi_add_device(struct Scsi_Host *host, uint channel, | ||
| 1268 | uint target, uint lun) | ||
| 1269 | { | ||
| 1270 | struct scsi_device *sdev = | ||
| 1271 | __scsi_add_device(host, channel, target, lun, NULL); | ||
| 1272 | if (IS_ERR(sdev)) | ||
| 1273 | return PTR_ERR(sdev); | ||
| 1274 | |||
| 1275 | scsi_device_put(sdev); | ||
| 1276 | return 0; | ||
| 1277 | } | ||
| 1278 | EXPORT_SYMBOL(scsi_add_device); | ||
| 1279 | |||
| 1263 | void scsi_rescan_device(struct device *dev) | 1280 | void scsi_rescan_device(struct device *dev) |
| 1264 | { | 1281 | { |
| 1265 | struct scsi_driver *drv; | 1282 | struct scsi_driver *drv; |
| @@ -1276,27 +1293,8 @@ void scsi_rescan_device(struct device *dev) | |||
| 1276 | } | 1293 | } |
| 1277 | EXPORT_SYMBOL(scsi_rescan_device); | 1294 | EXPORT_SYMBOL(scsi_rescan_device); |
| 1278 | 1295 | ||
| 1279 | /** | 1296 | static void __scsi_scan_target(struct device *parent, unsigned int channel, |
| 1280 | * scsi_scan_target - scan a target id, possibly including all LUNs on the | 1297 | unsigned int id, unsigned int lun, int rescan) |
| 1281 | * target. | ||
| 1282 | * @sdevsca: Scsi_Device handle for scanning | ||
| 1283 | * @shost: host to scan | ||
| 1284 | * @channel: channel to scan | ||
| 1285 | * @id: target id to scan | ||
| 1286 | * | ||
| 1287 | * Description: | ||
| 1288 | * Scan the target id on @shost, @channel, and @id. Scan at least LUN | ||
| 1289 | * 0, and possibly all LUNs on the target id. | ||
| 1290 | * | ||
| 1291 | * Use the pre-allocated @sdevscan as a handle for the scanning. This | ||
| 1292 | * function sets sdevscan->host, sdevscan->id and sdevscan->lun; the | ||
| 1293 | * scanning functions modify sdevscan->lun. | ||
| 1294 | * | ||
| 1295 | * First try a REPORT LUN scan, if that does not scan the target, do a | ||
| 1296 | * sequential scan of LUNs on the target id. | ||
| 1297 | **/ | ||
| 1298 | void scsi_scan_target(struct device *parent, unsigned int channel, | ||
| 1299 | unsigned int id, unsigned int lun, int rescan) | ||
| 1300 | { | 1298 | { |
| 1301 | struct Scsi_Host *shost = dev_to_shost(parent); | 1299 | struct Scsi_Host *shost = dev_to_shost(parent); |
| 1302 | int bflags = 0; | 1300 | int bflags = 0; |
| @@ -1310,9 +1308,7 @@ void scsi_scan_target(struct device *parent, unsigned int channel, | |||
| 1310 | */ | 1308 | */ |
| 1311 | return; | 1309 | return; |
| 1312 | 1310 | ||
| 1313 | |||
| 1314 | starget = scsi_alloc_target(parent, channel, id); | 1311 | starget = scsi_alloc_target(parent, channel, id); |
| 1315 | |||
| 1316 | if (!starget) | 1312 | if (!starget) |
| 1317 | return; | 1313 | return; |
| 1318 | 1314 | ||
| @@ -1358,6 +1354,33 @@ void scsi_scan_target(struct device *parent, unsigned int channel, | |||
| 1358 | 1354 | ||
| 1359 | put_device(&starget->dev); | 1355 | put_device(&starget->dev); |
| 1360 | } | 1356 | } |
| 1357 | |||
| 1358 | /** | ||
| 1359 | * scsi_scan_target - scan a target id, possibly including all LUNs on the | ||
| 1360 | * target. | ||
| 1361 | * @parent: host to scan | ||
| 1362 | * @channel: channel to scan | ||
| 1363 | * @id: target id to scan | ||
| 1364 | * @lun: Specific LUN to scan or SCAN_WILD_CARD | ||
| 1365 | * @rescan: passed to LUN scanning routines | ||
| 1366 | * | ||
| 1367 | * Description: | ||
| 1368 | * Scan the target id on @parent, @channel, and @id. Scan at least LUN 0, | ||
| 1369 | * and possibly all LUNs on the target id. | ||
| 1370 | * | ||
| 1371 | * First try a REPORT LUN scan, if that does not scan the target, do a | ||
| 1372 | * sequential scan of LUNs on the target id. | ||
| 1373 | **/ | ||
| 1374 | void scsi_scan_target(struct device *parent, unsigned int channel, | ||
| 1375 | unsigned int id, unsigned int lun, int rescan) | ||
| 1376 | { | ||
| 1377 | struct Scsi_Host *shost = dev_to_shost(parent); | ||
| 1378 | |||
| 1379 | down(&shost->scan_mutex); | ||
| 1380 | if (scsi_host_scan_allowed(shost)) | ||
| 1381 | __scsi_scan_target(parent, channel, id, lun, rescan); | ||
| 1382 | up(&shost->scan_mutex); | ||
| 1383 | } | ||
| 1361 | EXPORT_SYMBOL(scsi_scan_target); | 1384 | EXPORT_SYMBOL(scsi_scan_target); |
| 1362 | 1385 | ||
| 1363 | static void scsi_scan_channel(struct Scsi_Host *shost, unsigned int channel, | 1386 | static void scsi_scan_channel(struct Scsi_Host *shost, unsigned int channel, |
| @@ -1383,10 +1406,12 @@ static void scsi_scan_channel(struct Scsi_Host *shost, unsigned int channel, | |||
| 1383 | order_id = shost->max_id - id - 1; | 1406 | order_id = shost->max_id - id - 1; |
| 1384 | else | 1407 | else |
| 1385 | order_id = id; | 1408 | order_id = id; |
| 1386 | scsi_scan_target(&shost->shost_gendev, channel, order_id, lun, rescan); | 1409 | __scsi_scan_target(&shost->shost_gendev, channel, |
| 1410 | order_id, lun, rescan); | ||
| 1387 | } | 1411 | } |
| 1388 | else | 1412 | else |
| 1389 | scsi_scan_target(&shost->shost_gendev, channel, id, lun, rescan); | 1413 | __scsi_scan_target(&shost->shost_gendev, channel, |
| 1414 | id, lun, rescan); | ||
| 1390 | } | 1415 | } |
| 1391 | 1416 | ||
| 1392 | int scsi_scan_host_selected(struct Scsi_Host *shost, unsigned int channel, | 1417 | int scsi_scan_host_selected(struct Scsi_Host *shost, unsigned int channel, |
| @@ -1484,12 +1509,15 @@ void scsi_forget_host(struct Scsi_Host *shost) | |||
| 1484 | */ | 1509 | */ |
| 1485 | struct scsi_device *scsi_get_host_dev(struct Scsi_Host *shost) | 1510 | struct scsi_device *scsi_get_host_dev(struct Scsi_Host *shost) |
| 1486 | { | 1511 | { |
| 1487 | struct scsi_device *sdev; | 1512 | struct scsi_device *sdev = NULL; |
| 1488 | struct scsi_target *starget; | 1513 | struct scsi_target *starget; |
| 1489 | 1514 | ||
| 1515 | down(&shost->scan_mutex); | ||
| 1516 | if (!scsi_host_scan_allowed(shost)) | ||
| 1517 | goto out; | ||
| 1490 | starget = scsi_alloc_target(&shost->shost_gendev, 0, shost->this_id); | 1518 | starget = scsi_alloc_target(&shost->shost_gendev, 0, shost->this_id); |
| 1491 | if (!starget) | 1519 | if (!starget) |
| 1492 | return NULL; | 1520 | goto out; |
| 1493 | 1521 | ||
| 1494 | sdev = scsi_alloc_sdev(starget, 0, NULL); | 1522 | sdev = scsi_alloc_sdev(starget, 0, NULL); |
| 1495 | if (sdev) { | 1523 | if (sdev) { |
| @@ -1497,6 +1525,8 @@ struct scsi_device *scsi_get_host_dev(struct Scsi_Host *shost) | |||
| 1497 | sdev->borken = 0; | 1525 | sdev->borken = 0; |
| 1498 | } | 1526 | } |
| 1499 | put_device(&starget->dev); | 1527 | put_device(&starget->dev); |
| 1528 | out: | ||
| 1529 | up(&shost->scan_mutex); | ||
| 1500 | return sdev; | 1530 | return sdev; |
| 1501 | } | 1531 | } |
| 1502 | EXPORT_SYMBOL(scsi_get_host_dev); | 1532 | EXPORT_SYMBOL(scsi_get_host_dev); |
