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); |