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.c88
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}
1261EXPORT_SYMBOL(__scsi_add_device); 1265EXPORT_SYMBOL(__scsi_add_device);
1262 1266
1267int 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}
1278EXPORT_SYMBOL(scsi_add_device);
1279
1263void scsi_rescan_device(struct device *dev) 1280void 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}
1277EXPORT_SYMBOL(scsi_rescan_device); 1294EXPORT_SYMBOL(scsi_rescan_device);
1278 1295
1279/** 1296static 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 **/
1298void 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 **/
1374void 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}
1361EXPORT_SYMBOL(scsi_scan_target); 1384EXPORT_SYMBOL(scsi_scan_target);
1362 1385
1363static void scsi_scan_channel(struct Scsi_Host *shost, unsigned int channel, 1386static 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
1392int scsi_scan_host_selected(struct Scsi_Host *shost, unsigned int channel, 1417int 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 */
1485struct scsi_device *scsi_get_host_dev(struct Scsi_Host *shost) 1510struct 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}
1502EXPORT_SYMBOL(scsi_get_host_dev); 1532EXPORT_SYMBOL(scsi_get_host_dev);