11da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 21da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * scsi_scan.c 31da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 41da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Copyright (C) 2000 Eric Youngdale, 51da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Copyright (C) 2002 Patrick Mansfield 61da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 71da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * The general scanning/probing algorithm is as follows, exceptions are 81da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * made to it depending on device specific flags, compilation options, and 91da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * global variable (boot or module load time) settings. 101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * A specific LUN is scanned via an INQUIRY command; if the LUN has a 12f64a181d898e0518d5ae90c4870069510de977e1Christoph Hellwig * device attached, a scsi_device is allocated and setup for it. 131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * For every id of every channel on the given host: 151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Scan LUN 0; if the target responds to LUN 0 (even if there is no 171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * device or storage attached to LUN 0): 181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * If LUN 0 has a device attached, allocate and setup a 20f64a181d898e0518d5ae90c4870069510de977e1Christoph Hellwig * scsi_device for it. 211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * If target is SCSI-3 or up, issue a REPORT LUN, and scan 231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * all of the LUNs returned by the REPORT LUN; else, 241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * sequentially scan LUNs up until some maximum is reached, 251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * or a LUN is seen that cannot have a device attached to it. 261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/module.h> 291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/moduleparam.h> 301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/init.h> 311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/blkdev.h> 323e082a910d217b2e7b186077ebf5a1126a68c62fMatthew Wilcox#include <linux/delay.h> 333e082a910d217b2e7b186077ebf5a1126a68c62fMatthew Wilcox#include <linux/kthread.h> 343e082a910d217b2e7b186077ebf5a1126a68c62fMatthew Wilcox#include <linux/spinlock.h> 354ace92fc112c6069b4fcb95a31d3142d4a43ff2aArjan van de Ven#include <linux/async.h> 365a0e3ad6af8660be21ca98a971cd00f331318c05Tejun Heo#include <linux/slab.h> 371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <scsi/scsi.h> 39beb40487508290f5d6565598c60a3f44261beef2Christoph Hellwig#include <scsi/scsi_cmnd.h> 401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <scsi/scsi_device.h> 411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <scsi/scsi_driver.h> 421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <scsi/scsi_devinfo.h> 431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <scsi/scsi_host.h> 441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <scsi/scsi_transport.h> 451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <scsi/scsi_eh.h> 461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include "scsi_priv.h" 481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include "scsi_logging.h" 491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define ALLOC_FAILURE_MSG KERN_ERR "%s: Allocation failure during" \ 511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds " SCSI scanning, some SCSI devices might not be configured\n" 521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Default timeout 551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define SCSI_TIMEOUT (2*HZ) 571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 59405ae7d381302468ecc803f2148a2ae40a04c999Robert P. J. Day * Prefix values for the SCSI id's (stored in sysfs name field) 601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define SCSI_UID_SER_NUM 'S' 621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define SCSI_UID_UNKNOWN 'Z' 631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Return values of some of the scanning functions. 661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * SCSI_SCAN_NO_RESPONSE: no valid response received from the target, this 681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * includes allocation or general failures preventing IO from being sent. 691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * SCSI_SCAN_TARGET_PRESENT: target responded, but no device is available 711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * on the given LUN. 721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * SCSI_SCAN_LUN_PRESENT: target responded, and a device is available on a 741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * given LUN. 751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define SCSI_SCAN_NO_RESPONSE 0 771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define SCSI_SCAN_TARGET_PRESENT 1 781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define SCSI_SCAN_LUN_PRESENT 2 791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 800ad78200baf1f85a21e6b26c225717ad80980d8fArjan van de Venstatic const char *scsi_null_device_strs = "nullnullnullnull"; 811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define MAX_SCSI_LUNS 512 831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef CONFIG_SCSI_MULTI_LUN 851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic unsigned int max_scsi_luns = MAX_SCSI_LUNS; 861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#else 871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic unsigned int max_scsi_luns = 1; 881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9010f4b89a0f0586a67f57efb2f5d12fffbb371490Masatake YAMATOmodule_param_named(max_luns, max_scsi_luns, uint, S_IRUGO|S_IWUSR); 911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_PARM_DESC(max_luns, 921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "last scsi LUN (should be between 1 and 2^32-1)"); 931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9421db1882f79a1ad5977cae6766376a63f60ec414Matthew Wilcox#ifdef CONFIG_SCSI_SCAN_ASYNC 9521db1882f79a1ad5977cae6766376a63f60ec414Matthew Wilcox#define SCSI_SCAN_TYPE_DEFAULT "async" 9621db1882f79a1ad5977cae6766376a63f60ec414Matthew Wilcox#else 9721db1882f79a1ad5977cae6766376a63f60ec414Matthew Wilcox#define SCSI_SCAN_TYPE_DEFAULT "sync" 9821db1882f79a1ad5977cae6766376a63f60ec414Matthew Wilcox#endif 9921db1882f79a1ad5977cae6766376a63f60ec414Matthew Wilcox 10021db1882f79a1ad5977cae6766376a63f60ec414Matthew Wilcoxstatic char scsi_scan_type[6] = SCSI_SCAN_TYPE_DEFAULT; 1013e082a910d217b2e7b186077ebf5a1126a68c62fMatthew Wilcox 1023e082a910d217b2e7b186077ebf5a1126a68c62fMatthew Wilcoxmodule_param_string(scan, scsi_scan_type, sizeof(scsi_scan_type), S_IRUGO); 1033e082a910d217b2e7b186077ebf5a1126a68c62fMatthew WilcoxMODULE_PARM_DESC(scan, "sync, async or none"); 1043e082a910d217b2e7b186077ebf5a1126a68c62fMatthew Wilcox 1051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 1061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * max_scsi_report_luns: the maximum number of LUNS that will be 1071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * returned from the REPORT LUNS command. 8 times this value must 1081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * be allocated. In theory this could be up to an 8 byte value, but 1091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * in practice, the maximum number of LUNs suppored by any device 1101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * is about 16k. 1111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 1121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic unsigned int max_scsi_report_luns = 511; 1131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 11410f4b89a0f0586a67f57efb2f5d12fffbb371490Masatake YAMATOmodule_param_named(max_report_luns, max_scsi_report_luns, uint, S_IRUGO|S_IWUSR); 1151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_PARM_DESC(max_report_luns, 1161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "REPORT LUNS maximum number of LUNS received (should be" 1171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds " between 1 and 16384)"); 1181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 11914faf12f7df8404c3e8e54baad8d178c327a2f87Alan Sternstatic unsigned int scsi_inq_timeout = SCSI_TIMEOUT/HZ + 18; 1201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 12110f4b89a0f0586a67f57efb2f5d12fffbb371490Masatake YAMATOmodule_param_named(inq_timeout, scsi_inq_timeout, uint, S_IRUGO|S_IWUSR); 1221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_PARM_DESC(inq_timeout, 1231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "Timeout (in seconds) waiting for devices to answer INQUIRY." 12414faf12f7df8404c3e8e54baad8d178c327a2f87Alan Stern " Default is 20. Some devices may need more; most need less."); 1251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1266b7f123f378743d739377871c0cbfbaf28c7d25aMatthew Wilcox/* This lock protects only this list */ 1273e082a910d217b2e7b186077ebf5a1126a68c62fMatthew Wilcoxstatic DEFINE_SPINLOCK(async_scan_lock); 1283e082a910d217b2e7b186077ebf5a1126a68c62fMatthew Wilcoxstatic LIST_HEAD(scanning_hosts); 1293e082a910d217b2e7b186077ebf5a1126a68c62fMatthew Wilcox 1303e082a910d217b2e7b186077ebf5a1126a68c62fMatthew Wilcoxstruct async_scan_data { 1313e082a910d217b2e7b186077ebf5a1126a68c62fMatthew Wilcox struct list_head list; 1323e082a910d217b2e7b186077ebf5a1126a68c62fMatthew Wilcox struct Scsi_Host *shost; 1333e082a910d217b2e7b186077ebf5a1126a68c62fMatthew Wilcox struct completion prev_finished; 1343e082a910d217b2e7b186077ebf5a1126a68c62fMatthew Wilcox}; 1353e082a910d217b2e7b186077ebf5a1126a68c62fMatthew Wilcox 1363e082a910d217b2e7b186077ebf5a1126a68c62fMatthew Wilcox/** 1373e082a910d217b2e7b186077ebf5a1126a68c62fMatthew Wilcox * scsi_complete_async_scans - Wait for asynchronous scans to complete 1383e082a910d217b2e7b186077ebf5a1126a68c62fMatthew Wilcox * 1398bcc24127be12967588db0ad0e614be937ee1d5aMatthew Wilcox * When this function returns, any host which started scanning before 1408bcc24127be12967588db0ad0e614be937ee1d5aMatthew Wilcox * this function was called will have finished its scan. Hosts which 1418bcc24127be12967588db0ad0e614be937ee1d5aMatthew Wilcox * started scanning after this function was called may or may not have 1428bcc24127be12967588db0ad0e614be937ee1d5aMatthew Wilcox * finished. 1433e082a910d217b2e7b186077ebf5a1126a68c62fMatthew Wilcox */ 1443e082a910d217b2e7b186077ebf5a1126a68c62fMatthew Wilcoxint scsi_complete_async_scans(void) 1453e082a910d217b2e7b186077ebf5a1126a68c62fMatthew Wilcox{ 1463e082a910d217b2e7b186077ebf5a1126a68c62fMatthew Wilcox struct async_scan_data *data; 1473e082a910d217b2e7b186077ebf5a1126a68c62fMatthew Wilcox 1483e082a910d217b2e7b186077ebf5a1126a68c62fMatthew Wilcox do { 1493e082a910d217b2e7b186077ebf5a1126a68c62fMatthew Wilcox if (list_empty(&scanning_hosts)) 1503e082a910d217b2e7b186077ebf5a1126a68c62fMatthew Wilcox return 0; 1513e082a910d217b2e7b186077ebf5a1126a68c62fMatthew Wilcox /* If we can't get memory immediately, that's OK. Just 1523e082a910d217b2e7b186077ebf5a1126a68c62fMatthew Wilcox * sleep a little. Even if we never get memory, the async 1533e082a910d217b2e7b186077ebf5a1126a68c62fMatthew Wilcox * scans will finish eventually. 1543e082a910d217b2e7b186077ebf5a1126a68c62fMatthew Wilcox */ 1553e082a910d217b2e7b186077ebf5a1126a68c62fMatthew Wilcox data = kmalloc(sizeof(*data), GFP_KERNEL); 1563e082a910d217b2e7b186077ebf5a1126a68c62fMatthew Wilcox if (!data) 1573e082a910d217b2e7b186077ebf5a1126a68c62fMatthew Wilcox msleep(1); 1583e082a910d217b2e7b186077ebf5a1126a68c62fMatthew Wilcox } while (!data); 1593e082a910d217b2e7b186077ebf5a1126a68c62fMatthew Wilcox 1603e082a910d217b2e7b186077ebf5a1126a68c62fMatthew Wilcox data->shost = NULL; 1613e082a910d217b2e7b186077ebf5a1126a68c62fMatthew Wilcox init_completion(&data->prev_finished); 1623e082a910d217b2e7b186077ebf5a1126a68c62fMatthew Wilcox 1633e082a910d217b2e7b186077ebf5a1126a68c62fMatthew Wilcox spin_lock(&async_scan_lock); 1643e082a910d217b2e7b186077ebf5a1126a68c62fMatthew Wilcox /* Check that there's still somebody else on the list */ 1653e082a910d217b2e7b186077ebf5a1126a68c62fMatthew Wilcox if (list_empty(&scanning_hosts)) 1663e082a910d217b2e7b186077ebf5a1126a68c62fMatthew Wilcox goto done; 1673e082a910d217b2e7b186077ebf5a1126a68c62fMatthew Wilcox list_add_tail(&data->list, &scanning_hosts); 1683e082a910d217b2e7b186077ebf5a1126a68c62fMatthew Wilcox spin_unlock(&async_scan_lock); 1693e082a910d217b2e7b186077ebf5a1126a68c62fMatthew Wilcox 1703e082a910d217b2e7b186077ebf5a1126a68c62fMatthew Wilcox printk(KERN_INFO "scsi: waiting for bus probes to complete ...\n"); 1713e082a910d217b2e7b186077ebf5a1126a68c62fMatthew Wilcox wait_for_completion(&data->prev_finished); 1723e082a910d217b2e7b186077ebf5a1126a68c62fMatthew Wilcox 1733e082a910d217b2e7b186077ebf5a1126a68c62fMatthew Wilcox spin_lock(&async_scan_lock); 1743e082a910d217b2e7b186077ebf5a1126a68c62fMatthew Wilcox list_del(&data->list); 1758bcc24127be12967588db0ad0e614be937ee1d5aMatthew Wilcox if (!list_empty(&scanning_hosts)) { 1768bcc24127be12967588db0ad0e614be937ee1d5aMatthew Wilcox struct async_scan_data *next = list_entry(scanning_hosts.next, 1778bcc24127be12967588db0ad0e614be937ee1d5aMatthew Wilcox struct async_scan_data, list); 1788bcc24127be12967588db0ad0e614be937ee1d5aMatthew Wilcox complete(&next->prev_finished); 1798bcc24127be12967588db0ad0e614be937ee1d5aMatthew Wilcox } 1803e082a910d217b2e7b186077ebf5a1126a68c62fMatthew Wilcox done: 1813e082a910d217b2e7b186077ebf5a1126a68c62fMatthew Wilcox spin_unlock(&async_scan_lock); 1823e082a910d217b2e7b186077ebf5a1126a68c62fMatthew Wilcox 1833e082a910d217b2e7b186077ebf5a1126a68c62fMatthew Wilcox kfree(data); 1843e082a910d217b2e7b186077ebf5a1126a68c62fMatthew Wilcox return 0; 1853e082a910d217b2e7b186077ebf5a1126a68c62fMatthew Wilcox} 1863e082a910d217b2e7b186077ebf5a1126a68c62fMatthew Wilcox 1873e082a910d217b2e7b186077ebf5a1126a68c62fMatthew Wilcox/* Only exported for the benefit of scsi_wait_scan */ 1883e082a910d217b2e7b186077ebf5a1126a68c62fMatthew WilcoxEXPORT_SYMBOL_GPL(scsi_complete_async_scans); 1893e082a910d217b2e7b186077ebf5a1126a68c62fMatthew Wilcox 190f2f027c6e9912840020be8b78f037d5c8ac665e0Hugh Dickins#ifndef MODULE 191f2f027c6e9912840020be8b78f037d5c8ac665e0Hugh Dickins/* 192f2f027c6e9912840020be8b78f037d5c8ac665e0Hugh Dickins * For async scanning we need to wait for all the scans to complete before 193f2f027c6e9912840020be8b78f037d5c8ac665e0Hugh Dickins * trying to mount the root fs. Otherwise non-modular drivers may not be ready 194f2f027c6e9912840020be8b78f037d5c8ac665e0Hugh Dickins * yet. 195f2f027c6e9912840020be8b78f037d5c8ac665e0Hugh Dickins */ 196f2f027c6e9912840020be8b78f037d5c8ac665e0Hugh Dickinslate_initcall(scsi_complete_async_scans); 197f2f027c6e9912840020be8b78f037d5c8ac665e0Hugh Dickins#endif 198f2f027c6e9912840020be8b78f037d5c8ac665e0Hugh Dickins 1991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/** 2001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * scsi_unlock_floptical - unlock device via a special MODE SENSE command 201392160335c798bbe94ab3aae6ea0c85d32b81bbcJames Bottomley * @sdev: scsi device to send command to 2021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @result: area to store the result of the MODE SENSE 2031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 2041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Description: 205392160335c798bbe94ab3aae6ea0c85d32b81bbcJames Bottomley * Send a vendor specific MODE SENSE (not a MODE SELECT) command. 2061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Called for BLIST_KEY devices. 2071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds **/ 208392160335c798bbe94ab3aae6ea0c85d32b81bbcJames Bottomleystatic void scsi_unlock_floptical(struct scsi_device *sdev, 2091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned char *result) 2101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned char scsi_cmd[MAX_COMMAND_SIZE]; 2121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk(KERN_NOTICE "scsi: unlocking floptical drive\n"); 2141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds scsi_cmd[0] = MODE_SENSE; 2151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds scsi_cmd[1] = 0; 2161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds scsi_cmd[2] = 0x2e; 2171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds scsi_cmd[3] = 0; 218392160335c798bbe94ab3aae6ea0c85d32b81bbcJames Bottomley scsi_cmd[4] = 0x2a; /* size */ 2191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds scsi_cmd[5] = 0; 220392160335c798bbe94ab3aae6ea0c85d32b81bbcJames Bottomley scsi_execute_req(sdev, scsi_cmd, DMA_FROM_DEVICE, result, 0x2a, NULL, 221f4f4e47e4af6b02dd1c425b931c65d0165356e33FUJITA Tomonori SCSI_TIMEOUT, 3, NULL); 2221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/** 2251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * scsi_alloc_sdev - allocate and setup a scsi_Device 226eb44820c28bc9a042e1157b41c677018a8fdfc74Rob Landley * @starget: which target to allocate a &scsi_device for 227eb44820c28bc9a042e1157b41c677018a8fdfc74Rob Landley * @lun: which lun 228eb44820c28bc9a042e1157b41c677018a8fdfc74Rob Landley * @hostdata: usually NULL and set by ->slave_alloc instead 2291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 2301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Description: 2311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Allocate, initialize for io, and return a pointer to a scsi_Device. 2321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Stores the @shost, @channel, @id, and @lun in the scsi_Device, and 2331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * adds scsi_Device to the appropriate list. 2341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 2351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Return value: 2361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * scsi_Device pointer, or NULL on failure. 2371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds **/ 2381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct scsi_device *scsi_alloc_sdev(struct scsi_target *starget, 2391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned int lun, void *hostdata) 2401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct scsi_device *sdev; 2421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int display_failure_msg = 1, ret; 2431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct Scsi_Host *shost = dev_to_shost(starget->dev.parent); 244a341cd0f6a0fde1f85fec9aa8f81f824ea4a3f92Jeff Garzik extern void scsi_evt_thread(struct work_struct *work); 2459937a5e2f32892db0dbeefc2b3bc74b3ae3ea9c7Jens Axboe extern void scsi_requeue_run_queue(struct work_struct *work); 2461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 24724669f75a3231fa37444977c92d1f4838bec1233Jes Sorensen sdev = kzalloc(sizeof(*sdev) + shost->transportt->device_size, 2481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds GFP_ATOMIC); 2491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!sdev) 2501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto out; 2511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sdev->vendor = scsi_null_device_strs; 2531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sdev->model = scsi_null_device_strs; 2541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sdev->rev = scsi_null_device_strs; 2551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sdev->host = shost; 2564a84067dbfce436b81779e585bf712b02ceee552Vasu Dev sdev->queue_ramp_up_period = SCSI_DEFAULT_RAMP_UP_PERIOD; 2571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sdev->id = starget->id; 2581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sdev->lun = lun; 2591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sdev->channel = starget->channel; 2601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sdev->sdev_state = SDEV_CREATED; 2611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds INIT_LIST_HEAD(&sdev->siblings); 2621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds INIT_LIST_HEAD(&sdev->same_target_siblings); 2631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds INIT_LIST_HEAD(&sdev->cmd_list); 2641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds INIT_LIST_HEAD(&sdev->starved_entry); 265a341cd0f6a0fde1f85fec9aa8f81f824ea4a3f92Jeff Garzik INIT_LIST_HEAD(&sdev->event_list); 2661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_lock_init(&sdev->list_lock); 267a341cd0f6a0fde1f85fec9aa8f81f824ea4a3f92Jeff Garzik INIT_WORK(&sdev->event_work, scsi_evt_thread); 2689937a5e2f32892db0dbeefc2b3bc74b3ae3ea9c7Jens Axboe INIT_WORK(&sdev->requeue_work, scsi_requeue_run_queue); 2691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sdev->sdev_gendev.parent = get_device(&starget->dev); 2711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sdev->sdev_target = starget; 2721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* usually NULL and set by ->slave_alloc instead */ 2741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sdev->hostdata = hostdata; 2751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* if the device needs this changing, it may do so in the 2771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * slave_configure function */ 2781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sdev->max_device_blocked = SCSI_DEFAULT_DEVICE_BLOCKED; 2791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 2811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Some low level driver could use device->type 2821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 2831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sdev->type = -1; 2841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 2861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Assume that the device will have handshaking problems, 2871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * and then fix this field later if it turns out it 2881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * doesn't 2891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 2901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sdev->borken = 1; 2911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sdev->request_queue = scsi_alloc_queue(sdev); 2931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!sdev->request_queue) { 2941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* release fn is set up in scsi_sysfs_device_initialise, so 2951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * have to free and put manually here */ 2961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds put_device(&starget->dev); 29793f56089898a1b27fc0c89b5c1c748291353f679Dave Jones kfree(sdev); 2981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto out; 2991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 30009ac46c429464c919d04bb737b27edd84d944f02Tejun Heo WARN_ON_ONCE(!blk_get_queue(sdev->request_queue)); 3011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sdev->request_queue->queuedata = sdev; 3021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds scsi_adjust_queue_depth(sdev, 0, sdev->host->cmd_per_lun); 3031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds scsi_sysfs_device_initialize(sdev); 3051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (shost->hostt->slave_alloc) { 3071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ret = shost->hostt->slave_alloc(sdev); 3081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (ret) { 3091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 3101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * if LLDD reports slave not present, don't clutter 3111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * console with alloc failure messages 3121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 3131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (ret == -ENXIO) 3141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds display_failure_msg = 0; 3151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto out_device_destroy; 3161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return sdev; 3201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsout_device_destroy: 3224e6c82b3614a18740ef63109d58743a359266dafJames Bottomley __scsi_remove_device(sdev); 3231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsout: 3241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (display_failure_msg) 325cadbd4a5e36dde7e6c49b587b2c419103c0b7218Harvey Harrison printk(ALLOC_FAILURE_MSG, __func__); 3261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return NULL; 3271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 3281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 329643eb2d932c97a0583381629d632d486934cf7eeJames Bottomleystatic void scsi_target_destroy(struct scsi_target *starget) 330643eb2d932c97a0583381629d632d486934cf7eeJames Bottomley{ 331643eb2d932c97a0583381629d632d486934cf7eeJames Bottomley struct device *dev = &starget->dev; 332643eb2d932c97a0583381629d632d486934cf7eeJames Bottomley struct Scsi_Host *shost = dev_to_shost(dev->parent); 333643eb2d932c97a0583381629d632d486934cf7eeJames Bottomley unsigned long flags; 334643eb2d932c97a0583381629d632d486934cf7eeJames Bottomley 335643eb2d932c97a0583381629d632d486934cf7eeJames Bottomley transport_destroy_device(dev); 336643eb2d932c97a0583381629d632d486934cf7eeJames Bottomley spin_lock_irqsave(shost->host_lock, flags); 337643eb2d932c97a0583381629d632d486934cf7eeJames Bottomley if (shost->hostt->target_destroy) 338643eb2d932c97a0583381629d632d486934cf7eeJames Bottomley shost->hostt->target_destroy(starget); 339643eb2d932c97a0583381629d632d486934cf7eeJames Bottomley list_del_init(&starget->siblings); 340643eb2d932c97a0583381629d632d486934cf7eeJames Bottomley spin_unlock_irqrestore(shost->host_lock, flags); 341643eb2d932c97a0583381629d632d486934cf7eeJames Bottomley put_device(dev); 342643eb2d932c97a0583381629d632d486934cf7eeJames Bottomley} 343643eb2d932c97a0583381629d632d486934cf7eeJames Bottomley 3441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void scsi_target_dev_release(struct device *dev) 3451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 3461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct device *parent = dev->parent; 3471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct scsi_target *starget = to_scsi_target(dev); 348a283bd37d00e92e8874ca6325ae071691d4db388James Bottomley 3491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds kfree(starget); 3501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds put_device(parent); 3511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 3521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 353453cd0f3ff3bf25d86c96e62d271ba238f06d5ffAdrian Bunkstatic struct device_type scsi_target_type = { 354b0ed43360fdca227048d88a08290365cb681c1a8Hannes Reinecke .name = "scsi_target", 355b0ed43360fdca227048d88a08290365cb681c1a8Hannes Reinecke .release = scsi_target_dev_release, 356b0ed43360fdca227048d88a08290365cb681c1a8Hannes Reinecke}; 357b0ed43360fdca227048d88a08290365cb681c1a8Hannes Reinecke 3581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint scsi_is_target_device(const struct device *dev) 3591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 360b0ed43360fdca227048d88a08290365cb681c1a8Hannes Reinecke return dev->type == &scsi_target_type; 3611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 3621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsEXPORT_SYMBOL(scsi_is_target_device); 3631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct scsi_target *__scsi_find_target(struct device *parent, 3651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int channel, uint id) 3661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 3671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct scsi_target *starget, *found_starget = NULL; 3681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct Scsi_Host *shost = dev_to_shost(parent); 3691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 3701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Search for an existing target for this sdev. 3711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 3721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds list_for_each_entry(starget, &shost->__targets, siblings) { 3731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (starget->id == id && 3741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds starget->channel == channel) { 3751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds found_starget = starget; 3761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 3771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (found_starget) 3801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds get_device(&found_starget->dev); 3811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return found_starget; 3831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 3841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 385884d25cc4fda20908fd4ef93dbb41d817984b68bJames Bottomley/** 386884d25cc4fda20908fd4ef93dbb41d817984b68bJames Bottomley * scsi_alloc_target - allocate a new or find an existing target 387884d25cc4fda20908fd4ef93dbb41d817984b68bJames Bottomley * @parent: parent of the target (need not be a scsi host) 388884d25cc4fda20908fd4ef93dbb41d817984b68bJames Bottomley * @channel: target channel number (zero if no channels) 389884d25cc4fda20908fd4ef93dbb41d817984b68bJames Bottomley * @id: target id number 390884d25cc4fda20908fd4ef93dbb41d817984b68bJames Bottomley * 391884d25cc4fda20908fd4ef93dbb41d817984b68bJames Bottomley * Return an existing target if one exists, provided it hasn't already 392884d25cc4fda20908fd4ef93dbb41d817984b68bJames Bottomley * gone into STARGET_DEL state, otherwise allocate a new target. 393884d25cc4fda20908fd4ef93dbb41d817984b68bJames Bottomley * 394884d25cc4fda20908fd4ef93dbb41d817984b68bJames Bottomley * The target is returned with an incremented reference, so the caller 395884d25cc4fda20908fd4ef93dbb41d817984b68bJames Bottomley * is responsible for both reaping and doing a last put 396884d25cc4fda20908fd4ef93dbb41d817984b68bJames Bottomley */ 3971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct scsi_target *scsi_alloc_target(struct device *parent, 3981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int channel, uint id) 3991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 4001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct Scsi_Host *shost = dev_to_shost(parent); 4011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct device *dev = NULL; 4021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long flags; 4031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds const int size = sizeof(struct scsi_target) 4041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds + shost->transportt->target_size; 4055c44cd2afad3f7b015542187e147a820600172f1James.Smart@Emulex.Com struct scsi_target *starget; 4061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct scsi_target *found_target; 40732f95792500794a0a7cce266b7dafb2bee323bf8Brian King int error; 4081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 40924669f75a3231fa37444977c92d1f4838bec1233Jes Sorensen starget = kzalloc(size, GFP_KERNEL); 4101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!starget) { 411cadbd4a5e36dde7e6c49b587b2c419103c0b7218Harvey Harrison printk(KERN_ERR "%s: allocation failure\n", __func__); 4121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return NULL; 4131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 4141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev = &starget->dev; 4151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds device_initialize(dev); 4161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds starget->reap_ref = 1; 4171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev->parent = get_device(parent); 41871610f55fa4db63dbf5385929a47c9fb2451f332Kay Sievers dev_set_name(dev, "target%d:%d:%d", shost->host_no, channel, id); 419b0ed43360fdca227048d88a08290365cb681c1a8Hannes Reinecke dev->bus = &scsi_bus_type; 420b0ed43360fdca227048d88a08290365cb681c1a8Hannes Reinecke dev->type = &scsi_target_type; 4211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds starget->id = id; 4221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds starget->channel = channel; 423f0c0a376d0fcd4c5579ecf5e95f88387cba85211Mike Christie starget->can_queue = 0; 4241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds INIT_LIST_HEAD(&starget->siblings); 4251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds INIT_LIST_HEAD(&starget->devices); 426643eb2d932c97a0583381629d632d486934cf7eeJames Bottomley starget->state = STARGET_CREATED; 4277c9d6f16f50d3aeb780e4f103a1ba8b35d9ae803Alan Stern starget->scsi_level = SCSI_2; 428c53a284f8be23735dc6b53929640a987055f2933Edward Goggin starget->max_target_blocked = SCSI_DEFAULT_TARGET_BLOCKED; 429ffedb4522571ac170f941678d138a31bc0884ab4James Bottomley retry: 4301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_lock_irqsave(shost->host_lock, flags); 4311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds found_target = __scsi_find_target(parent, channel, id); 4331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (found_target) 4341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto found; 4351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds list_add_tail(&starget->siblings, &shost->__targets); 4371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_unlock_irqrestore(shost->host_lock, flags); 4381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* allocate and add */ 439a283bd37d00e92e8874ca6325ae071691d4db388James Bottomley transport_setup_device(dev); 440a283bd37d00e92e8874ca6325ae071691d4db388James Bottomley if (shost->hostt->target_alloc) { 44132f95792500794a0a7cce266b7dafb2bee323bf8Brian King error = shost->hostt->target_alloc(starget); 442a283bd37d00e92e8874ca6325ae071691d4db388James Bottomley 443a283bd37d00e92e8874ca6325ae071691d4db388James Bottomley if(error) { 444a283bd37d00e92e8874ca6325ae071691d4db388James Bottomley dev_printk(KERN_ERR, dev, "target allocation failed, error %d\n", error); 445a283bd37d00e92e8874ca6325ae071691d4db388James Bottomley /* don't want scsi_target_reap to do the final 446a283bd37d00e92e8874ca6325ae071691d4db388James Bottomley * put because it will be under the host lock */ 447643eb2d932c97a0583381629d632d486934cf7eeJames Bottomley scsi_target_destroy(starget); 448a283bd37d00e92e8874ca6325ae071691d4db388James Bottomley return NULL; 449a283bd37d00e92e8874ca6325ae071691d4db388James Bottomley } 450a283bd37d00e92e8874ca6325ae071691d4db388James Bottomley } 451884d25cc4fda20908fd4ef93dbb41d817984b68bJames Bottomley get_device(dev); 452a283bd37d00e92e8874ca6325ae071691d4db388James Bottomley 4531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return starget; 4541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds found: 4561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds found_target->reap_ref++; 4571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_unlock_irqrestore(shost->host_lock, flags); 458ffedb4522571ac170f941678d138a31bc0884ab4James Bottomley if (found_target->state != STARGET_DEL) { 45912fb8c1574d7d0c262d2f4c667047889c4f27ebeAlan Stern put_device(dev); 460ffedb4522571ac170f941678d138a31bc0884ab4James Bottomley return found_target; 461ffedb4522571ac170f941678d138a31bc0884ab4James Bottomley } 462ffedb4522571ac170f941678d138a31bc0884ab4James Bottomley /* Unfortunately, we found a dying target; need to 463ffedb4522571ac170f941678d138a31bc0884ab4James Bottomley * wait until it's dead before we can get a new one */ 464ffedb4522571ac170f941678d138a31bc0884ab4James Bottomley put_device(&found_target->dev); 465ffedb4522571ac170f941678d138a31bc0884ab4James Bottomley flush_scheduled_work(); 466ffedb4522571ac170f941678d138a31bc0884ab4James Bottomley goto retry; 4671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 4681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 46965f27f38446e1976cc98fd3004b110fedcddd189David Howellsstatic void scsi_target_reap_usercontext(struct work_struct *work) 47065110b2168950a19cc78b5027ed18cb811fbdae8James Bottomley{ 47165f27f38446e1976cc98fd3004b110fedcddd189David Howells struct scsi_target *starget = 47265f27f38446e1976cc98fd3004b110fedcddd189David Howells container_of(work, struct scsi_target, ew.work); 473863a930a40eb7f2d18534c2c166b22582f5c6cfdJames Bottomley 474ffedb4522571ac170f941678d138a31bc0884ab4James Bottomley transport_remove_device(&starget->dev); 475ffedb4522571ac170f941678d138a31bc0884ab4James Bottomley device_del(&starget->dev); 476643eb2d932c97a0583381629d632d486934cf7eeJames Bottomley scsi_target_destroy(starget); 477863a930a40eb7f2d18534c2c166b22582f5c6cfdJames Bottomley} 478863a930a40eb7f2d18534c2c166b22582f5c6cfdJames Bottomley 4791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/** 4801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * scsi_target_reap - check to see if target is in use and destroy if not 4811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @starget: target to be checked 4821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 4831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * This is used after removing a LUN or doing a last put of the target 4841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * it checks atomically that nothing is using the target and removes 4851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * it if so. 4861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 4871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid scsi_target_reap(struct scsi_target *starget) 4881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 489ffedb4522571ac170f941678d138a31bc0884ab4James Bottomley struct Scsi_Host *shost = dev_to_shost(starget->dev.parent); 490ffedb4522571ac170f941678d138a31bc0884ab4James Bottomley unsigned long flags; 491643eb2d932c97a0583381629d632d486934cf7eeJames Bottomley enum scsi_target_state state; 492f9e8894ae5157796dd69249c56062042d02a431dAlan Stern int empty = 0; 493ffedb4522571ac170f941678d138a31bc0884ab4James Bottomley 494ffedb4522571ac170f941678d138a31bc0884ab4James Bottomley spin_lock_irqsave(shost->host_lock, flags); 495643eb2d932c97a0583381629d632d486934cf7eeJames Bottomley state = starget->state; 496f9e8894ae5157796dd69249c56062042d02a431dAlan Stern if (--starget->reap_ref == 0 && list_empty(&starget->devices)) { 497f9e8894ae5157796dd69249c56062042d02a431dAlan Stern empty = 1; 498f9e8894ae5157796dd69249c56062042d02a431dAlan Stern starget->state = STARGET_DEL; 499f9e8894ae5157796dd69249c56062042d02a431dAlan Stern } 500643eb2d932c97a0583381629d632d486934cf7eeJames Bottomley spin_unlock_irqrestore(shost->host_lock, flags); 501ffedb4522571ac170f941678d138a31bc0884ab4James Bottomley 502643eb2d932c97a0583381629d632d486934cf7eeJames Bottomley if (!empty) 503ffedb4522571ac170f941678d138a31bc0884ab4James Bottomley return; 504ffedb4522571ac170f941678d138a31bc0884ab4James Bottomley 505643eb2d932c97a0583381629d632d486934cf7eeJames Bottomley BUG_ON(state == STARGET_DEL); 506643eb2d932c97a0583381629d632d486934cf7eeJames Bottomley if (state == STARGET_CREATED) 507643eb2d932c97a0583381629d632d486934cf7eeJames Bottomley scsi_target_destroy(starget); 508643eb2d932c97a0583381629d632d486934cf7eeJames Bottomley else 509643eb2d932c97a0583381629d632d486934cf7eeJames Bottomley execute_in_process_context(scsi_target_reap_usercontext, 510643eb2d932c97a0583381629d632d486934cf7eeJames Bottomley &starget->ew); 5111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 5121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/** 514e5b3cd42960a10c1bc3701d4f00767463c88ec9dAlan Stern * sanitize_inquiry_string - remove non-graphical chars from an INQUIRY result string 515e5b3cd42960a10c1bc3701d4f00767463c88ec9dAlan Stern * @s: INQUIRY result string to sanitize 516e5b3cd42960a10c1bc3701d4f00767463c88ec9dAlan Stern * @len: length of the string 517e5b3cd42960a10c1bc3701d4f00767463c88ec9dAlan Stern * 518e5b3cd42960a10c1bc3701d4f00767463c88ec9dAlan Stern * Description: 519e5b3cd42960a10c1bc3701d4f00767463c88ec9dAlan Stern * The SCSI spec says that INQUIRY vendor, product, and revision 520e5b3cd42960a10c1bc3701d4f00767463c88ec9dAlan Stern * strings must consist entirely of graphic ASCII characters, 521e5b3cd42960a10c1bc3701d4f00767463c88ec9dAlan Stern * padded on the right with spaces. Since not all devices obey 522e5b3cd42960a10c1bc3701d4f00767463c88ec9dAlan Stern * this rule, we will replace non-graphic or non-ASCII characters 523e5b3cd42960a10c1bc3701d4f00767463c88ec9dAlan Stern * with spaces. Exception: a NUL character is interpreted as a 524e5b3cd42960a10c1bc3701d4f00767463c88ec9dAlan Stern * string terminator, so all the following characters are set to 525e5b3cd42960a10c1bc3701d4f00767463c88ec9dAlan Stern * spaces. 526e5b3cd42960a10c1bc3701d4f00767463c88ec9dAlan Stern **/ 527e5b3cd42960a10c1bc3701d4f00767463c88ec9dAlan Sternstatic void sanitize_inquiry_string(unsigned char *s, int len) 528e5b3cd42960a10c1bc3701d4f00767463c88ec9dAlan Stern{ 529e5b3cd42960a10c1bc3701d4f00767463c88ec9dAlan Stern int terminated = 0; 530e5b3cd42960a10c1bc3701d4f00767463c88ec9dAlan Stern 531e5b3cd42960a10c1bc3701d4f00767463c88ec9dAlan Stern for (; len > 0; (--len, ++s)) { 532e5b3cd42960a10c1bc3701d4f00767463c88ec9dAlan Stern if (*s == 0) 533e5b3cd42960a10c1bc3701d4f00767463c88ec9dAlan Stern terminated = 1; 534e5b3cd42960a10c1bc3701d4f00767463c88ec9dAlan Stern if (terminated || *s < 0x20 || *s > 0x7e) 535e5b3cd42960a10c1bc3701d4f00767463c88ec9dAlan Stern *s = ' '; 536e5b3cd42960a10c1bc3701d4f00767463c88ec9dAlan Stern } 537e5b3cd42960a10c1bc3701d4f00767463c88ec9dAlan Stern} 538e5b3cd42960a10c1bc3701d4f00767463c88ec9dAlan Stern 539e5b3cd42960a10c1bc3701d4f00767463c88ec9dAlan Stern/** 5401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * scsi_probe_lun - probe a single LUN using a SCSI INQUIRY 541392160335c798bbe94ab3aae6ea0c85d32b81bbcJames Bottomley * @sdev: scsi_device to probe 5421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @inq_result: area to store the INQUIRY result 543392160335c798bbe94ab3aae6ea0c85d32b81bbcJames Bottomley * @result_len: len of inq_result 5441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @bflags: store any bflags found here 5451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 5461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Description: 547392160335c798bbe94ab3aae6ea0c85d32b81bbcJames Bottomley * Probe the lun associated with @req using a standard SCSI INQUIRY; 5481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 549392160335c798bbe94ab3aae6ea0c85d32b81bbcJames Bottomley * If the INQUIRY is successful, zero is returned and the 5501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * INQUIRY data is in @inq_result; the scsi_level and INQUIRY length 551f64a181d898e0518d5ae90c4870069510de977e1Christoph Hellwig * are copied to the scsi_device any flags value is stored in *@bflags. 5521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds **/ 553e5b3cd42960a10c1bc3701d4f00767463c88ec9dAlan Sternstatic int scsi_probe_lun(struct scsi_device *sdev, unsigned char *inq_result, 554392160335c798bbe94ab3aae6ea0c85d32b81bbcJames Bottomley int result_len, int *bflags) 5551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 5561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned char scsi_cmd[MAX_COMMAND_SIZE]; 5571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int first_inquiry_len, try_inquiry_len, next_inquiry_len; 5581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int response_len = 0; 559392160335c798bbe94ab3aae6ea0c85d32b81bbcJames Bottomley int pass, count, result; 5601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct scsi_sense_hdr sshdr; 5611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *bflags = 0; 5631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Perform up to 3 passes. The first pass uses a conservative 5651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * transfer length of 36 unless sdev->inquiry_len specifies a 5661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * different value. */ 5671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds first_inquiry_len = sdev->inquiry_len ? sdev->inquiry_len : 36; 5681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds try_inquiry_len = first_inquiry_len; 5691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pass = 1; 5701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds next_pass: 5729ccfc756a70d454dfa82f48897e2883560c01a0eJames Bottomley SCSI_LOG_SCAN_BUS(3, sdev_printk(KERN_INFO, sdev, 5739ccfc756a70d454dfa82f48897e2883560c01a0eJames Bottomley "scsi scan: INQUIRY pass %d length %d\n", 5749ccfc756a70d454dfa82f48897e2883560c01a0eJames Bottomley pass, try_inquiry_len)); 5751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Each pass gets up to three chances to ignore Unit Attention */ 5771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (count = 0; count < 3; ++count) { 5785cd3bbfad088f86bde3e0f038ff4dd5bb0ac5290FUJITA Tomonori int resid; 5795cd3bbfad088f86bde3e0f038ff4dd5bb0ac5290FUJITA Tomonori 5801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds memset(scsi_cmd, 0, 6); 5811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds scsi_cmd[0] = INQUIRY; 5821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds scsi_cmd[4] = (unsigned char) try_inquiry_len; 5831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds memset(inq_result, 0, try_inquiry_len); 585392160335c798bbe94ab3aae6ea0c85d32b81bbcJames Bottomley 586392160335c798bbe94ab3aae6ea0c85d32b81bbcJames Bottomley result = scsi_execute_req(sdev, scsi_cmd, DMA_FROM_DEVICE, 587ea73a9f23906c374b697cd5b0d64f6dceced63deJames Bottomley inq_result, try_inquiry_len, &sshdr, 588f4f4e47e4af6b02dd1c425b931c65d0165356e33FUJITA Tomonori HZ / 2 + HZ * scsi_inq_timeout, 3, 5895cd3bbfad088f86bde3e0f038ff4dd5bb0ac5290FUJITA Tomonori &resid); 5901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds SCSI_LOG_SCAN_BUS(3, printk(KERN_INFO "scsi scan: INQUIRY %s " 5921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "with code 0x%x\n", 593392160335c798bbe94ab3aae6ea0c85d32b81bbcJames Bottomley result ? "failed" : "successful", result)); 5941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 595392160335c798bbe94ab3aae6ea0c85d32b81bbcJames Bottomley if (result) { 5961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 5971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * not-ready to ready transition [asc/ascq=0x28/0x0] 5981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * or power-on, reset [asc/ascq=0x29/0x0], continue. 5991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * INQUIRY should not yield UNIT_ATTENTION 6001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * but many buggy devices do so anyway. 6011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 602392160335c798bbe94ab3aae6ea0c85d32b81bbcJames Bottomley if ((driver_byte(result) & DRIVER_SENSE) && 603ea73a9f23906c374b697cd5b0d64f6dceced63deJames Bottomley scsi_sense_valid(&sshdr)) { 6041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if ((sshdr.sense_key == UNIT_ATTENTION) && 6051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ((sshdr.asc == 0x28) || 6061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (sshdr.asc == 0x29)) && 6071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (sshdr.ascq == 0)) 6081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds continue; 6091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 6105cd3bbfad088f86bde3e0f038ff4dd5bb0ac5290FUJITA Tomonori } else { 6115cd3bbfad088f86bde3e0f038ff4dd5bb0ac5290FUJITA Tomonori /* 6125cd3bbfad088f86bde3e0f038ff4dd5bb0ac5290FUJITA Tomonori * if nothing was transferred, we try 6135cd3bbfad088f86bde3e0f038ff4dd5bb0ac5290FUJITA Tomonori * again. It's a workaround for some USB 6145cd3bbfad088f86bde3e0f038ff4dd5bb0ac5290FUJITA Tomonori * devices. 6155cd3bbfad088f86bde3e0f038ff4dd5bb0ac5290FUJITA Tomonori */ 6165cd3bbfad088f86bde3e0f038ff4dd5bb0ac5290FUJITA Tomonori if (resid == try_inquiry_len) 6175cd3bbfad088f86bde3e0f038ff4dd5bb0ac5290FUJITA Tomonori continue; 6181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 6191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 6201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 6211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 622392160335c798bbe94ab3aae6ea0c85d32b81bbcJames Bottomley if (result == 0) { 623e5b3cd42960a10c1bc3701d4f00767463c88ec9dAlan Stern sanitize_inquiry_string(&inq_result[8], 8); 624e5b3cd42960a10c1bc3701d4f00767463c88ec9dAlan Stern sanitize_inquiry_string(&inq_result[16], 16); 625e5b3cd42960a10c1bc3701d4f00767463c88ec9dAlan Stern sanitize_inquiry_string(&inq_result[32], 4); 626e5b3cd42960a10c1bc3701d4f00767463c88ec9dAlan Stern 627e5b3cd42960a10c1bc3701d4f00767463c88ec9dAlan Stern response_len = inq_result[4] + 5; 6281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (response_len > 255) 6291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds response_len = first_inquiry_len; /* sanity */ 6301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 6321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Get any flags for this device. 6331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 634f64a181d898e0518d5ae90c4870069510de977e1Christoph Hellwig * XXX add a bflags to scsi_device, and replace the 635f64a181d898e0518d5ae90c4870069510de977e1Christoph Hellwig * corresponding bit fields in scsi_device, so bflags 6361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * need not be passed as an argument. 6371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 6381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *bflags = scsi_get_device_flags(sdev, &inq_result[8], 6391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds &inq_result[16]); 6401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* When the first pass succeeds we gain information about 6421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * what larger transfer lengths might work. */ 6431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (pass == 1) { 6441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (BLIST_INQUIRY_36 & *bflags) 6451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds next_inquiry_len = 36; 6461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else if (BLIST_INQUIRY_58 & *bflags) 6471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds next_inquiry_len = 58; 6481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else if (sdev->inquiry_len) 6491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds next_inquiry_len = sdev->inquiry_len; 6501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else 6511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds next_inquiry_len = response_len; 6521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* If more data is available perform the second pass */ 6541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (next_inquiry_len > try_inquiry_len) { 6551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds try_inquiry_len = next_inquiry_len; 6561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pass = 2; 6571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto next_pass; 6581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 6591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 6601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else if (pass == 2) { 6621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk(KERN_INFO "scsi scan: %d byte inquiry failed. " 6631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "Consider BLIST_INQUIRY_36 for this device\n", 6641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds try_inquiry_len); 6651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* If this pass failed, the third pass goes back and transfers 6671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * the same amount as we successfully got in the first pass. */ 6681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds try_inquiry_len = first_inquiry_len; 6691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pass = 3; 6701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto next_pass; 6711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 6721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* If the last transfer attempt got an error, assume the 6741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * peripheral doesn't exist or is dead. */ 675392160335c798bbe94ab3aae6ea0c85d32b81bbcJames Bottomley if (result) 676392160335c798bbe94ab3aae6ea0c85d32b81bbcJames Bottomley return -EIO; 6771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Don't report any more data than the device says is valid */ 6791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sdev->inquiry_len = min(try_inquiry_len, response_len); 6801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 6821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * XXX Abort if the response length is less than 36? If less than 6831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 32, the lookup of the device flags (above) could be invalid, 6841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * and it would be possible to take an incorrect action - we do 6851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * not want to hang because of a short INQUIRY. On the flip side, 6861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * if the device is spun down or becoming ready (and so it gives a 6871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * short INQUIRY), an abort here prevents any further use of the 6881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * device, including spin up. 6891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 690e423ee31db92d4e298c137814a4341e1cd05739eAlan Stern * On the whole, the best approach seems to be to assume the first 691e423ee31db92d4e298c137814a4341e1cd05739eAlan Stern * 36 bytes are valid no matter what the device says. That's 692e423ee31db92d4e298c137814a4341e1cd05739eAlan Stern * better than copying < 36 bytes to the inquiry-result buffer 693e423ee31db92d4e298c137814a4341e1cd05739eAlan Stern * and displaying garbage for the Vendor, Product, or Revision 694e423ee31db92d4e298c137814a4341e1cd05739eAlan Stern * strings. 695e423ee31db92d4e298c137814a4341e1cd05739eAlan Stern */ 696e423ee31db92d4e298c137814a4341e1cd05739eAlan Stern if (sdev->inquiry_len < 36) { 697e423ee31db92d4e298c137814a4341e1cd05739eAlan Stern printk(KERN_INFO "scsi scan: INQUIRY result too short (%d)," 698e423ee31db92d4e298c137814a4341e1cd05739eAlan Stern " using 36\n", sdev->inquiry_len); 699e423ee31db92d4e298c137814a4341e1cd05739eAlan Stern sdev->inquiry_len = 36; 700e423ee31db92d4e298c137814a4341e1cd05739eAlan Stern } 701e423ee31db92d4e298c137814a4341e1cd05739eAlan Stern 702e423ee31db92d4e298c137814a4341e1cd05739eAlan Stern /* 7031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Related to the above issue: 7041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 7051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * XXX Devices (disk or all?) should be sent a TEST UNIT READY, 7061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * and if not ready, sent a START_STOP to start (maybe spin up) and 7071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * then send the INQUIRY again, since the INQUIRY can change after 7081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * a device is initialized. 7091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 7101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Ideally, start a device if explicitly asked to do so. This 7111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * assumes that a device is spun up on power on, spun down on 7121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * request, and then spun up on request. 7131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 7141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 7161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * The scanning code needs to know the scsi_level, even if no 7171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * device is attached at LUN 0 (SCSI_SCAN_TARGET_PRESENT) so 7181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * non-zero LUNs can be scanned. 7191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 7201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sdev->scsi_level = inq_result[2] & 0x07; 7211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (sdev->scsi_level >= 2 || 7221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (sdev->scsi_level == 1 && (inq_result[3] & 0x0f) == 1)) 7231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sdev->scsi_level++; 7246f3a20242db2597312c50abc11f1e747c5d2326aJames Bottomley sdev->sdev_target->scsi_level = sdev->scsi_level; 7251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 726392160335c798bbe94ab3aae6ea0c85d32b81bbcJames Bottomley return 0; 7271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 7281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/** 730f64a181d898e0518d5ae90c4870069510de977e1Christoph Hellwig * scsi_add_lun - allocate and fully initialze a scsi_device 7316d877688ef411313c94aa3c83c7473fbec6db32cMatthew Wilcox * @sdev: holds information to be stored in the new scsi_device 7321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @inq_result: holds the result of a previous INQUIRY to the LUN 7331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @bflags: black/white list flag 7346d877688ef411313c94aa3c83c7473fbec6db32cMatthew Wilcox * @async: 1 if this device is being scanned asynchronously 7351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 7361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Description: 7376d877688ef411313c94aa3c83c7473fbec6db32cMatthew Wilcox * Initialize the scsi_device @sdev. Optionally set fields based 7386d877688ef411313c94aa3c83c7473fbec6db32cMatthew Wilcox * on values in *@bflags. 7391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 7401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Return: 741f64a181d898e0518d5ae90c4870069510de977e1Christoph Hellwig * SCSI_SCAN_NO_RESPONSE: could not allocate or setup a scsi_device 742f64a181d898e0518d5ae90c4870069510de977e1Christoph Hellwig * SCSI_SCAN_LUN_PRESENT: a new scsi_device was allocated and initialized 7431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds **/ 744e5b3cd42960a10c1bc3701d4f00767463c88ec9dAlan Sternstatic int scsi_add_lun(struct scsi_device *sdev, unsigned char *inq_result, 7453e082a910d217b2e7b186077ebf5a1126a68c62fMatthew Wilcox int *bflags, int async) 7461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 7476f4267e3bd1211b3d09130e626b0b3d885077610James Bottomley int ret; 7486f4267e3bd1211b3d09130e626b0b3d885077610James Bottomley 7491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 7501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * XXX do not save the inquiry, since it can change underneath us, 7511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * save just vendor/model/rev. 7521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 7531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Rather than save it and have an ioctl that retrieves the saved 7541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * value, have an ioctl that executes the same INQUIRY code used 7551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * in scsi_probe_lun, let user level programs doing INQUIRY 7561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * scanning run at their own risk, or supply a user level program 7571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * that can correctly scan. 7581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 75909123d230a294cd3b860f4ea042235b988277f0aAlan Stern 76009123d230a294cd3b860f4ea042235b988277f0aAlan Stern /* 76109123d230a294cd3b860f4ea042235b988277f0aAlan Stern * Copy at least 36 bytes of INQUIRY data, so that we don't 76209123d230a294cd3b860f4ea042235b988277f0aAlan Stern * dereference unallocated memory when accessing the Vendor, 76309123d230a294cd3b860f4ea042235b988277f0aAlan Stern * Product, and Revision strings. Badly behaved devices may set 76409123d230a294cd3b860f4ea042235b988277f0aAlan Stern * the INQUIRY Additional Length byte to a small value, indicating 76509123d230a294cd3b860f4ea042235b988277f0aAlan Stern * these strings are invalid, but often they contain plausible data 76609123d230a294cd3b860f4ea042235b988277f0aAlan Stern * nonetheless. It doesn't matter if the device sent < 36 bytes 76709123d230a294cd3b860f4ea042235b988277f0aAlan Stern * total, since scsi_probe_lun() initializes inq_result with 0s. 76809123d230a294cd3b860f4ea042235b988277f0aAlan Stern */ 76909123d230a294cd3b860f4ea042235b988277f0aAlan Stern sdev->inquiry = kmemdup(inq_result, 77009123d230a294cd3b860f4ea042235b988277f0aAlan Stern max_t(size_t, sdev->inquiry_len, 36), 77109123d230a294cd3b860f4ea042235b988277f0aAlan Stern GFP_ATOMIC); 77209123d230a294cd3b860f4ea042235b988277f0aAlan Stern if (sdev->inquiry == NULL) 7731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return SCSI_SCAN_NO_RESPONSE; 7741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sdev->vendor = (char *) (sdev->inquiry + 8); 7761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sdev->model = (char *) (sdev->inquiry + 16); 7771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sdev->rev = (char *) (sdev->inquiry + 32); 7781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (*bflags & BLIST_ISROM) { 7806d877688ef411313c94aa3c83c7473fbec6db32cMatthew Wilcox sdev->type = TYPE_ROM; 7816d877688ef411313c94aa3c83c7473fbec6db32cMatthew Wilcox sdev->removable = 1; 7826d877688ef411313c94aa3c83c7473fbec6db32cMatthew Wilcox } else { 7836d877688ef411313c94aa3c83c7473fbec6db32cMatthew Wilcox sdev->type = (inq_result[0] & 0x1f); 7846d877688ef411313c94aa3c83c7473fbec6db32cMatthew Wilcox sdev->removable = (inq_result[1] & 0x80) >> 7; 7856d877688ef411313c94aa3c83c7473fbec6db32cMatthew Wilcox } 7861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7876d877688ef411313c94aa3c83c7473fbec6db32cMatthew Wilcox switch (sdev->type) { 788ddaf6fc85459d161c39a70a2cf9e04343dafe47fJames Bottomley case TYPE_RBC: 7891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case TYPE_TAPE: 7901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case TYPE_DISK: 7911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case TYPE_PRINTER: 7921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case TYPE_MOD: 7931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case TYPE_PROCESSOR: 7941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case TYPE_SCANNER: 7951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case TYPE_MEDIUM_CHANGER: 7961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case TYPE_ENCLOSURE: 7971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case TYPE_COMM: 7984d7db04a7a69099accd84984a78c64d2178252f1James Bottomley case TYPE_RAID: 79982443a58d361123d418033e9e32ac29a842fce68Boaz Harrosh case TYPE_OSD: 8001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sdev->writeable = 1; 8011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 8021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case TYPE_ROM: 803ddaf6fc85459d161c39a70a2cf9e04343dafe47fJames Bottomley case TYPE_WORM: 8041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sdev->writeable = 0; 8051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 8061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds default: 8071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk(KERN_INFO "scsi: unknown device type %d\n", sdev->type); 8081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 8091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8106d877688ef411313c94aa3c83c7473fbec6db32cMatthew Wilcox if (sdev->type == TYPE_RBC || sdev->type == TYPE_ROM) { 8116d877688ef411313c94aa3c83c7473fbec6db32cMatthew Wilcox /* RBC and MMC devices can return SCSI-3 compliance and yet 8126d877688ef411313c94aa3c83c7473fbec6db32cMatthew Wilcox * still not support REPORT LUNS, so make them act as 8136d877688ef411313c94aa3c83c7473fbec6db32cMatthew Wilcox * BLIST_NOREPORTLUN unless BLIST_REPORTLUN2 is 8146d877688ef411313c94aa3c83c7473fbec6db32cMatthew Wilcox * specifically set */ 8156d877688ef411313c94aa3c83c7473fbec6db32cMatthew Wilcox if ((*bflags & BLIST_REPORTLUN2) == 0) 8166d877688ef411313c94aa3c83c7473fbec6db32cMatthew Wilcox *bflags |= BLIST_NOREPORTLUN; 8176d877688ef411313c94aa3c83c7473fbec6db32cMatthew Wilcox } 8186d877688ef411313c94aa3c83c7473fbec6db32cMatthew Wilcox 8191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 8201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * For a peripheral qualifier (PQ) value of 1 (001b), the SCSI 8211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * spec says: The device server is capable of supporting the 8221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * specified peripheral device type on this logical unit. However, 8231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * the physical device is not currently connected to this logical 8241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * unit. 8251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 8261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * The above is vague, as it implies that we could treat 001 and 8271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 011 the same. Stay compatible with previous code, and create a 828f64a181d898e0518d5ae90c4870069510de977e1Christoph Hellwig * scsi_device for a PQ of 1 8291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 8301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Don't set the device offline here; rather let the upper 8311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * level drivers eval the PQ to decide whether they should 8321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * attach. So remove ((inq_result[0] >> 5) & 7) == 1 check. 8331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 8341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sdev->inq_periph_qual = (inq_result[0] >> 5) & 7; 8361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sdev->lockable = sdev->removable; 8371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sdev->soft_reset = (inq_result[7] & 1) && ((inq_result[3] & 7) == 2); 8381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8396d877688ef411313c94aa3c83c7473fbec6db32cMatthew Wilcox if (sdev->scsi_level >= SCSI_3 || 8406d877688ef411313c94aa3c83c7473fbec6db32cMatthew Wilcox (sdev->inquiry_len > 56 && inq_result[56] & 0x04)) 8411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sdev->ppr = 1; 8421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (inq_result[7] & 0x60) 8431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sdev->wdtr = 1; 8441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (inq_result[7] & 0x10) 8451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sdev->sdtr = 1; 8461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 84719ac0db3e22de3b00cc4aadc7efbad0420c7aa08James Bottomley sdev_printk(KERN_NOTICE, sdev, "%s %.8s %.16s %.4s PQ: %d " 8484ff36718ede26ee2da73f2dae94d71e2b06845fcMatthew Wilcox "ANSI: %d%s\n", scsi_device_type(sdev->type), 8494ff36718ede26ee2da73f2dae94d71e2b06845fcMatthew Wilcox sdev->vendor, sdev->model, sdev->rev, 8504ff36718ede26ee2da73f2dae94d71e2b06845fcMatthew Wilcox sdev->inq_periph_qual, inq_result[2] & 0x07, 8514ff36718ede26ee2da73f2dae94d71e2b06845fcMatthew Wilcox (inq_result[3] & 0x0f) == 1 ? " CCS" : ""); 8524ff36718ede26ee2da73f2dae94d71e2b06845fcMatthew Wilcox 8531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if ((sdev->scsi_level >= SCSI_2) && (inq_result[7] & 2) && 8541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds !(*bflags & BLIST_NOTQ)) 8551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sdev->tagged_supported = 1; 8566d877688ef411313c94aa3c83c7473fbec6db32cMatthew Wilcox 8571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 8581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Some devices (Texel CD ROM drives) have handshaking problems 8591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * when used with the Seagate controllers. borken is initialized 8601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * to 1, and then set it to 0 here. 8611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 8621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if ((*bflags & BLIST_BORKEN) == 0) 8631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sdev->borken = 0; 8641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8656d877688ef411313c94aa3c83c7473fbec6db32cMatthew Wilcox if (*bflags & BLIST_NO_ULD_ATTACH) 8666d877688ef411313c94aa3c83c7473fbec6db32cMatthew Wilcox sdev->no_uld_attach = 1; 8676d877688ef411313c94aa3c83c7473fbec6db32cMatthew Wilcox 8681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 8691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Apparently some really broken devices (contrary to the SCSI 8701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * standards) need to be selected without asserting ATN 8711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 8721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (*bflags & BLIST_SELECT_NO_ATN) 8731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sdev->select_no_atn = 1; 8741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 8764d7db04a7a69099accd84984a78c64d2178252f1James Bottomley * Maximum 512 sector transfer length 8774d7db04a7a69099accd84984a78c64d2178252f1James Bottomley * broken RA4x00 Compaq Disk Array 8784d7db04a7a69099accd84984a78c64d2178252f1James Bottomley */ 8794d7db04a7a69099accd84984a78c64d2178252f1James Bottomley if (*bflags & BLIST_MAX_512) 880086fa5ff0854c676ec333760f4c0154b3b242616Martin K. Petersen blk_queue_max_hw_sectors(sdev->request_queue, 512); 8814d7db04a7a69099accd84984a78c64d2178252f1James Bottomley 8824d7db04a7a69099accd84984a78c64d2178252f1James Bottomley /* 8831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Some devices may not want to have a start command automatically 8841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * issued when a device is added. 8851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 8861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (*bflags & BLIST_NOSTARTONADD) 8871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sdev->no_start_on_add = 1; 8881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (*bflags & BLIST_SINGLELUN) 89025d7c363f2663fe399e623c9bd819258c9760bdcTony Battersby scsi_target(sdev)->single_lun = 1; 8911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sdev->use_10_for_rw = 1; 8931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (*bflags & BLIST_MS_SKIP_PAGE_08) 8951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sdev->skip_ms_page_8 = 1; 8961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (*bflags & BLIST_MS_SKIP_PAGE_3F) 8981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sdev->skip_ms_page_3f = 1; 8991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (*bflags & BLIST_USE_10_BYTE_MS) 9011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sdev->use_10_for_ms = 1; 9021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* set the device running here so that slave configure 9041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * may do I/O */ 9056f4267e3bd1211b3d09130e626b0b3d885077610James Bottomley ret = scsi_device_set_state(sdev, SDEV_RUNNING); 9066f4267e3bd1211b3d09130e626b0b3d885077610James Bottomley if (ret) { 9076f4267e3bd1211b3d09130e626b0b3d885077610James Bottomley ret = scsi_device_set_state(sdev, SDEV_BLOCK); 9086f4267e3bd1211b3d09130e626b0b3d885077610James Bottomley 9096f4267e3bd1211b3d09130e626b0b3d885077610James Bottomley if (ret) { 9106f4267e3bd1211b3d09130e626b0b3d885077610James Bottomley sdev_printk(KERN_ERR, sdev, 9116f4267e3bd1211b3d09130e626b0b3d885077610James Bottomley "in wrong state %s to complete scan\n", 9126f4267e3bd1211b3d09130e626b0b3d885077610James Bottomley scsi_device_state_name(sdev->sdev_state)); 9136f4267e3bd1211b3d09130e626b0b3d885077610James Bottomley return SCSI_SCAN_NO_RESPONSE; 9146f4267e3bd1211b3d09130e626b0b3d885077610James Bottomley } 9156f4267e3bd1211b3d09130e626b0b3d885077610James Bottomley } 9161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (*bflags & BLIST_MS_192_BYTES_FOR_3F) 9181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sdev->use_192_bytes_for_3f = 1; 9191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (*bflags & BLIST_NOT_LOCKABLE) 9211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sdev->lockable = 0; 9221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (*bflags & BLIST_RETRY_HWERROR) 9241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sdev->retry_hwerror = 1; 9251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds transport_configure_device(&sdev->sdev_gendev); 9271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 928938050916f57f08e20595b1fa1c1e57c2fbf7243Christoph Hellwig if (sdev->host->hostt->slave_configure) { 9296f4267e3bd1211b3d09130e626b0b3d885077610James Bottomley ret = sdev->host->hostt->slave_configure(sdev); 930938050916f57f08e20595b1fa1c1e57c2fbf7243Christoph Hellwig if (ret) { 931938050916f57f08e20595b1fa1c1e57c2fbf7243Christoph Hellwig /* 932938050916f57f08e20595b1fa1c1e57c2fbf7243Christoph Hellwig * if LLDD reports slave not present, don't clutter 933938050916f57f08e20595b1fa1c1e57c2fbf7243Christoph Hellwig * console with alloc failure messages 934938050916f57f08e20595b1fa1c1e57c2fbf7243Christoph Hellwig */ 935938050916f57f08e20595b1fa1c1e57c2fbf7243Christoph Hellwig if (ret != -ENXIO) { 936938050916f57f08e20595b1fa1c1e57c2fbf7243Christoph Hellwig sdev_printk(KERN_ERR, sdev, 937938050916f57f08e20595b1fa1c1e57c2fbf7243Christoph Hellwig "failed to configure device\n"); 938938050916f57f08e20595b1fa1c1e57c2fbf7243Christoph Hellwig } 939938050916f57f08e20595b1fa1c1e57c2fbf7243Christoph Hellwig return SCSI_SCAN_NO_RESPONSE; 940938050916f57f08e20595b1fa1c1e57c2fbf7243Christoph Hellwig } 941938050916f57f08e20595b1fa1c1e57c2fbf7243Christoph Hellwig } 9421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9434a84067dbfce436b81779e585bf712b02ceee552Vasu Dev sdev->max_queue_depth = sdev->queue_depth; 9444a84067dbfce436b81779e585bf712b02ceee552Vasu Dev 9451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 9461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Ok, the device is now all set up, we can 9471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * register it and tell the rest of the kernel 9481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * about it. 9491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 9503e082a910d217b2e7b186077ebf5a1126a68c62fMatthew Wilcox if (!async && scsi_sysfs_add_sdev(sdev) != 0) 951b24b1033451fcc87087a692fc47ca45daebd51acAlan Stern return SCSI_SCAN_NO_RESPONSE; 9521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return SCSI_SCAN_LUN_PRESENT; 9541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 9551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 956c5f2e6404c65e8380c9ba80a7d58a27d2642743bAndrew Morton#ifdef CONFIG_SCSI_LOGGING 9576c7154c97e20c0ea28547240dc86731c0cee1b2fKurt Garloff/** 958eb44820c28bc9a042e1157b41c677018a8fdfc74Rob Landley * scsi_inq_str - print INQUIRY data from min to max index, strip trailing whitespace 9596c7154c97e20c0ea28547240dc86731c0cee1b2fKurt Garloff * @buf: Output buffer with at least end-first+1 bytes of space 9606c7154c97e20c0ea28547240dc86731c0cee1b2fKurt Garloff * @inq: Inquiry buffer (input) 9616c7154c97e20c0ea28547240dc86731c0cee1b2fKurt Garloff * @first: Offset of string into inq 9626c7154c97e20c0ea28547240dc86731c0cee1b2fKurt Garloff * @end: Index after last character in inq 9636c7154c97e20c0ea28547240dc86731c0cee1b2fKurt Garloff */ 964c5f2e6404c65e8380c9ba80a7d58a27d2642743bAndrew Mortonstatic unsigned char *scsi_inq_str(unsigned char *buf, unsigned char *inq, 9656c7154c97e20c0ea28547240dc86731c0cee1b2fKurt Garloff unsigned first, unsigned end) 9666c7154c97e20c0ea28547240dc86731c0cee1b2fKurt Garloff{ 9676c7154c97e20c0ea28547240dc86731c0cee1b2fKurt Garloff unsigned term = 0, idx; 968c5f2e6404c65e8380c9ba80a7d58a27d2642743bAndrew Morton 969c5f2e6404c65e8380c9ba80a7d58a27d2642743bAndrew Morton for (idx = 0; idx + first < end && idx + first < inq[4] + 5; idx++) { 970c5f2e6404c65e8380c9ba80a7d58a27d2642743bAndrew Morton if (inq[idx+first] > ' ') { 9716c7154c97e20c0ea28547240dc86731c0cee1b2fKurt Garloff buf[idx] = inq[idx+first]; 9726c7154c97e20c0ea28547240dc86731c0cee1b2fKurt Garloff term = idx+1; 9736c7154c97e20c0ea28547240dc86731c0cee1b2fKurt Garloff } else { 9746c7154c97e20c0ea28547240dc86731c0cee1b2fKurt Garloff buf[idx] = ' '; 9756c7154c97e20c0ea28547240dc86731c0cee1b2fKurt Garloff } 9766c7154c97e20c0ea28547240dc86731c0cee1b2fKurt Garloff } 9776c7154c97e20c0ea28547240dc86731c0cee1b2fKurt Garloff buf[term] = 0; 9786c7154c97e20c0ea28547240dc86731c0cee1b2fKurt Garloff return buf; 9796c7154c97e20c0ea28547240dc86731c0cee1b2fKurt Garloff} 980c5f2e6404c65e8380c9ba80a7d58a27d2642743bAndrew Morton#endif 9816f3a20242db2597312c50abc11f1e747c5d2326aJames Bottomley 9821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/** 9831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * scsi_probe_and_add_lun - probe a LUN, if a LUN is found add it 9841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @starget: pointer to target device structure 9851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @lun: LUN of target device 9861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @bflagsp: store bflags here if not NULL 987eb44820c28bc9a042e1157b41c677018a8fdfc74Rob Landley * @sdevp: probe the LUN corresponding to this scsi_device 988eb44820c28bc9a042e1157b41c677018a8fdfc74Rob Landley * @rescan: if nonzero skip some code only needed on first scan 989eb44820c28bc9a042e1157b41c677018a8fdfc74Rob Landley * @hostdata: passed to scsi_alloc_sdev() 9901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 9911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Description: 9921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Call scsi_probe_lun, if a LUN with an attached device is found, 9931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * allocate and set it up by calling scsi_add_lun. 9941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 9951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Return: 996f64a181d898e0518d5ae90c4870069510de977e1Christoph Hellwig * SCSI_SCAN_NO_RESPONSE: could not allocate or setup a scsi_device 9971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * SCSI_SCAN_TARGET_PRESENT: target responded, but no device is 9981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * attached at the LUN 999f64a181d898e0518d5ae90c4870069510de977e1Christoph Hellwig * SCSI_SCAN_LUN_PRESENT: a new scsi_device was allocated and initialized 10001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds **/ 10011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int scsi_probe_and_add_lun(struct scsi_target *starget, 10021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds uint lun, int *bflagsp, 10031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct scsi_device **sdevp, int rescan, 10041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds void *hostdata) 10051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 10061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct scsi_device *sdev; 10071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned char *result; 1008392160335c798bbe94ab3aae6ea0c85d32b81bbcJames Bottomley int bflags, res = SCSI_SCAN_NO_RESPONSE, result_len = 256; 10091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct Scsi_Host *shost = dev_to_shost(starget->dev.parent); 10101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 10121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * The rescan flag is used as an optimization, the first scan of a 10131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * host adapter calls into here with rescan == 0. 10141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 10156f3a20242db2597312c50abc11f1e747c5d2326aJames Bottomley sdev = scsi_device_lookup_by_target(starget, lun); 10166f3a20242db2597312c50abc11f1e747c5d2326aJames Bottomley if (sdev) { 10170f1d87a2acb8fd1f2ef8af109a785123ddc1a6cbJames Bottomley if (rescan || !scsi_device_created(sdev)) { 10181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds SCSI_LOG_SCAN_BUS(3, printk(KERN_INFO 10191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "scsi scan: device exists on %s\n", 102071610f55fa4db63dbf5385929a47c9fb2451f332Kay Sievers dev_name(&sdev->sdev_gendev))); 10211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (sdevp) 10221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *sdevp = sdev; 10231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else 10241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds scsi_device_put(sdev); 10251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (bflagsp) 10271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *bflagsp = scsi_get_device_flags(sdev, 10281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sdev->vendor, 10291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sdev->model); 10301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return SCSI_SCAN_LUN_PRESENT; 10311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 10326f3a20242db2597312c50abc11f1e747c5d2326aJames Bottomley scsi_device_put(sdev); 10336f3a20242db2597312c50abc11f1e747c5d2326aJames Bottomley } else 10346f3a20242db2597312c50abc11f1e747c5d2326aJames Bottomley sdev = scsi_alloc_sdev(starget, lun, hostdata); 10351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!sdev) 10361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto out; 1037392160335c798bbe94ab3aae6ea0c85d32b81bbcJames Bottomley 1038392160335c798bbe94ab3aae6ea0c85d32b81bbcJames Bottomley result = kmalloc(result_len, GFP_ATOMIC | 1039bc86120a85ebf553180946e8854d1993f074e9f5Al Viro ((shost->unchecked_isa_dma) ? __GFP_DMA : 0)); 10401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!result) 1041392160335c798bbe94ab3aae6ea0c85d32b81bbcJames Bottomley goto out_free_sdev; 10421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1043392160335c798bbe94ab3aae6ea0c85d32b81bbcJames Bottomley if (scsi_probe_lun(sdev, result, result_len, &bflags)) 10441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto out_free_result; 10451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10464186ab1973758190916703eb8889ebe8002c5c8fKurt Garloff if (bflagsp) 10474186ab1973758190916703eb8889ebe8002c5c8fKurt Garloff *bflagsp = bflags; 10481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 10491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * result contains valid SCSI INQUIRY data. 10501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 105113f7e5acc8b329080672c13f05f252ace5b79825Kurt Garloff if (((result[0] >> 5) == 3) && !(bflags & BLIST_ATTACH_PQ3)) { 10521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 10531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * For a Peripheral qualifier 3 (011b), the SCSI 10541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * spec says: The device server is not capable of 10551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * supporting a physical device on this logical 10561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * unit. 10571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 10581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * For disks, this implies that there is no 10591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * logical disk configured at sdev->lun, but there 10601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * is a target id responding. 10611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 10626c7154c97e20c0ea28547240dc86731c0cee1b2fKurt Garloff SCSI_LOG_SCAN_BUS(2, sdev_printk(KERN_INFO, sdev, "scsi scan:" 10636c7154c97e20c0ea28547240dc86731c0cee1b2fKurt Garloff " peripheral qualifier of 3, device not" 10646c7154c97e20c0ea28547240dc86731c0cee1b2fKurt Garloff " added\n")) 10656c7154c97e20c0ea28547240dc86731c0cee1b2fKurt Garloff if (lun == 0) { 1066c5f2e6404c65e8380c9ba80a7d58a27d2642743bAndrew Morton SCSI_LOG_SCAN_BUS(1, { 1067c5f2e6404c65e8380c9ba80a7d58a27d2642743bAndrew Morton unsigned char vend[9]; 1068c5f2e6404c65e8380c9ba80a7d58a27d2642743bAndrew Morton unsigned char mod[17]; 1069c5f2e6404c65e8380c9ba80a7d58a27d2642743bAndrew Morton 1070c5f2e6404c65e8380c9ba80a7d58a27d2642743bAndrew Morton sdev_printk(KERN_INFO, sdev, 10716c7154c97e20c0ea28547240dc86731c0cee1b2fKurt Garloff "scsi scan: consider passing scsi_mod." 10723424a65d717ca87ce11acfb03cfd2f713886bfb4Kurt Garloff "dev_flags=%s:%s:0x240 or 0x1000240\n", 10736c7154c97e20c0ea28547240dc86731c0cee1b2fKurt Garloff scsi_inq_str(vend, result, 8, 16), 1074c5f2e6404c65e8380c9ba80a7d58a27d2642743bAndrew Morton scsi_inq_str(mod, result, 16, 32)); 1075c5f2e6404c65e8380c9ba80a7d58a27d2642743bAndrew Morton }); 1076643eb2d932c97a0583381629d632d486934cf7eeJames Bottomley 10776c7154c97e20c0ea28547240dc86731c0cee1b2fKurt Garloff } 1078643eb2d932c97a0583381629d632d486934cf7eeJames Bottomley 10791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds res = SCSI_SCAN_TARGET_PRESENT; 10801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto out_free_result; 10811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 10821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10831bfc5d9d5eb8e1a2efacc306bc55c248ed259a8eAlan Stern /* 108484961f28e9d13a4b193d0c8545f3c060c1890ff3dave wysochanski * Some targets may set slight variations of PQ and PDT to signal 108584961f28e9d13a4b193d0c8545f3c060c1890ff3dave wysochanski * that no LUN is present, so don't add sdev in these cases. 108684961f28e9d13a4b193d0c8545f3c060c1890ff3dave wysochanski * Two specific examples are: 108784961f28e9d13a4b193d0c8545f3c060c1890ff3dave wysochanski * 1) NetApp targets: return PQ=1, PDT=0x1f 108884961f28e9d13a4b193d0c8545f3c060c1890ff3dave wysochanski * 2) USB UFI: returns PDT=0x1f, with the PQ bits being "reserved" 108984961f28e9d13a4b193d0c8545f3c060c1890ff3dave wysochanski * in the UFI 1.0 spec (we cannot rely on reserved bits). 109084961f28e9d13a4b193d0c8545f3c060c1890ff3dave wysochanski * 109184961f28e9d13a4b193d0c8545f3c060c1890ff3dave wysochanski * References: 109284961f28e9d13a4b193d0c8545f3c060c1890ff3dave wysochanski * 1) SCSI SPC-3, pp. 145-146 109384961f28e9d13a4b193d0c8545f3c060c1890ff3dave wysochanski * PQ=1: "A peripheral device having the specified peripheral 109484961f28e9d13a4b193d0c8545f3c060c1890ff3dave wysochanski * device type is not connected to this logical unit. However, the 109584961f28e9d13a4b193d0c8545f3c060c1890ff3dave wysochanski * device server is capable of supporting the specified peripheral 109684961f28e9d13a4b193d0c8545f3c060c1890ff3dave wysochanski * device type on this logical unit." 109784961f28e9d13a4b193d0c8545f3c060c1890ff3dave wysochanski * PDT=0x1f: "Unknown or no device type" 109884961f28e9d13a4b193d0c8545f3c060c1890ff3dave wysochanski * 2) USB UFI 1.0, p. 20 109984961f28e9d13a4b193d0c8545f3c060c1890ff3dave wysochanski * PDT=00h Direct-access device (floppy) 110084961f28e9d13a4b193d0c8545f3c060c1890ff3dave wysochanski * PDT=1Fh none (no FDD connected to the requested logical unit) 11011bfc5d9d5eb8e1a2efacc306bc55c248ed259a8eAlan Stern */ 110284961f28e9d13a4b193d0c8545f3c060c1890ff3dave wysochanski if (((result[0] >> 5) == 1 || starget->pdt_1f_for_no_lun) && 110301b291bd66564b4bd826326af6bd0b6d17e99439James Bottomley (result[0] & 0x1f) == 0x1f && 110401b291bd66564b4bd826326af6bd0b6d17e99439James Bottomley !scsi_is_wlun(lun)) { 11051bfc5d9d5eb8e1a2efacc306bc55c248ed259a8eAlan Stern SCSI_LOG_SCAN_BUS(3, printk(KERN_INFO 11061bfc5d9d5eb8e1a2efacc306bc55c248ed259a8eAlan Stern "scsi scan: peripheral device type" 11071bfc5d9d5eb8e1a2efacc306bc55c248ed259a8eAlan Stern " of 31, no device added\n")); 11081bfc5d9d5eb8e1a2efacc306bc55c248ed259a8eAlan Stern res = SCSI_SCAN_TARGET_PRESENT; 11091bfc5d9d5eb8e1a2efacc306bc55c248ed259a8eAlan Stern goto out_free_result; 11101bfc5d9d5eb8e1a2efacc306bc55c248ed259a8eAlan Stern } 11111bfc5d9d5eb8e1a2efacc306bc55c248ed259a8eAlan Stern 11123e082a910d217b2e7b186077ebf5a1126a68c62fMatthew Wilcox res = scsi_add_lun(sdev, result, &bflags, shost->async_scan); 11131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (res == SCSI_SCAN_LUN_PRESENT) { 11141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (bflags & BLIST_KEY) { 11151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sdev->lockable = 0; 1116392160335c798bbe94ab3aae6ea0c85d32b81bbcJames Bottomley scsi_unlock_floptical(sdev, result); 11171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 11181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 11191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 11201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds out_free_result: 11211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds kfree(result); 11221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds out_free_sdev: 11231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (res == SCSI_SCAN_LUN_PRESENT) { 11241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (sdevp) { 1125b70d37bf61f278f9d9adf17c52af6b2d0ae7800cAlan Stern if (scsi_device_get(sdev) == 0) { 1126b70d37bf61f278f9d9adf17c52af6b2d0ae7800cAlan Stern *sdevp = sdev; 1127b70d37bf61f278f9d9adf17c52af6b2d0ae7800cAlan Stern } else { 1128b70d37bf61f278f9d9adf17c52af6b2d0ae7800cAlan Stern __scsi_remove_device(sdev); 1129b70d37bf61f278f9d9adf17c52af6b2d0ae7800cAlan Stern res = SCSI_SCAN_NO_RESPONSE; 1130b70d37bf61f278f9d9adf17c52af6b2d0ae7800cAlan Stern } 11311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 11326f3a20242db2597312c50abc11f1e747c5d2326aJames Bottomley } else 1133860dc73608a091e0b325218acc2701709d5f221aJames Bottomley __scsi_remove_device(sdev); 11341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds out: 11351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return res; 11361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 11371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 11381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/** 11391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * scsi_sequential_lun_scan - sequentially scan a SCSI target 11401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @starget: pointer to target structure to scan 11411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @bflags: black/white list flag for LUN 0 1142eb44820c28bc9a042e1157b41c677018a8fdfc74Rob Landley * @scsi_level: Which version of the standard does this device adhere to 1143eb44820c28bc9a042e1157b41c677018a8fdfc74Rob Landley * @rescan: passed to scsi_probe_add_lun() 11441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 11451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Description: 11461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Generally, scan from LUN 1 (LUN 0 is assumed to already have been 11471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * scanned) to some maximum lun until a LUN is found with no device 11481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * attached. Use the bflags to figure out any oddities. 11491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 11501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Modifies sdevscan->lun. 11511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds **/ 11521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void scsi_sequential_lun_scan(struct scsi_target *starget, 11534186ab1973758190916703eb8889ebe8002c5c8fKurt Garloff int bflags, int scsi_level, int rescan) 11541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 11551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned int sparse_lun, lun, max_dev_lun; 11561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct Scsi_Host *shost = dev_to_shost(starget->dev.parent); 11571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 11581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds SCSI_LOG_SCAN_BUS(3, printk(KERN_INFO "scsi scan: Sequential scan of" 115971610f55fa4db63dbf5385929a47c9fb2451f332Kay Sievers "%s\n", dev_name(&starget->dev))); 11601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 11611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds max_dev_lun = min(max_scsi_luns, shost->max_lun); 11621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 11631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * If this device is known to support sparse multiple units, 11641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * override the other settings, and scan all of them. Normally, 11651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * SCSI-3 devices should be scanned via the REPORT LUNS. 11661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 11671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (bflags & BLIST_SPARSELUN) { 11681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds max_dev_lun = shost->max_lun; 11691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sparse_lun = 1; 11701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else 11711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sparse_lun = 0; 11721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 11731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 11741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * If less than SCSI_1_CSS, and no special lun scaning, stop 11751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * scanning; this matches 2.4 behaviour, but could just be a bug 11761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * (to continue scanning a SCSI_1_CSS device). 11771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 11781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * This test is broken. We might not have any device on lun0 for 11791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * a sparselun device, and if that's the case then how would we 11801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * know the real scsi_level, eh? It might make sense to just not 11811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * scan any SCSI_1 device for non-0 luns, but that check would best 11821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * go into scsi_alloc_sdev() and just have it return null when asked 11831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * to alloc an sdev for lun > 0 on an already found SCSI_1 device. 11841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 11851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if ((sdevscan->scsi_level < SCSI_1_CCS) && 11861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ((bflags & (BLIST_FORCELUN | BLIST_SPARSELUN | BLIST_MAX5LUN)) 11871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds == 0)) 11881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return; 11891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 11901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 11911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * If this device is known to support multiple units, override 11921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * the other settings, and scan all of them. 11931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 11941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (bflags & BLIST_FORCELUN) 11951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds max_dev_lun = shost->max_lun; 11961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 11971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * REGAL CDC-4X: avoid hang after LUN 4 11981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 11991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (bflags & BLIST_MAX5LUN) 12001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds max_dev_lun = min(5U, max_dev_lun); 12011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 12021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Do not scan SCSI-2 or lower device past LUN 7, unless 12031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * BLIST_LARGELUN. 12041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 12051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (scsi_level < SCSI_3 && !(bflags & BLIST_LARGELUN)) 12061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds max_dev_lun = min(8U, max_dev_lun); 12071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 12081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 12091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * We have already scanned LUN 0, so start at LUN 1. Keep scanning 12101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * until we reach the max, or no LUN is found and we are not 12111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * sparse_lun. 12121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 12131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (lun = 1; lun < max_dev_lun; ++lun) 12141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if ((scsi_probe_and_add_lun(starget, lun, NULL, NULL, rescan, 12151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds NULL) != SCSI_SCAN_LUN_PRESENT) && 12161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds !sparse_lun) 12171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return; 12181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 12191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 12201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/** 12219f6aa5750de30b1ba35f6cb8de50c17b4fb59cabRandy Dunlap * scsilun_to_int - convert a scsi_lun to an int 12221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @scsilun: struct scsi_lun to be converted. 12231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 12241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Description: 12251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Convert @scsilun from a struct scsi_lun to a four byte host byte-ordered 12261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * integer, and return the result. The caller must check for 12271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * truncation before using this function. 12281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 12291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Notes: 12301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * The struct scsi_lun is assumed to be four levels, with each level 12311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * effectively containing a SCSI byte-ordered (big endian) short; the 12321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * addressing bits of each level are ignored (the highest two bits). 12331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * For a description of the LUN format, post SCSI-3 see the SCSI 12341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Architecture Model, for SCSI-3 see the SCSI Controller Commands. 12351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 12361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Given a struct scsi_lun of: 0a 04 0b 03 00 00 00 00, this function returns 12371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * the integer: 0x0b030a04 12381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds **/ 1239462b7859a07c9c2b060fa2b5b1d49f8b33706d4eChristof Schmittint scsilun_to_int(struct scsi_lun *scsilun) 12401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 12411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int i; 12421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned int lun; 12431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 12441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds lun = 0; 12451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (i = 0; i < sizeof(lun); i += 2) 12461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds lun = lun | (((scsilun->scsi_lun[i] << 8) | 12471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds scsilun->scsi_lun[i + 1]) << (i * 8)); 12481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return lun; 12491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1250462b7859a07c9c2b060fa2b5b1d49f8b33706d4eChristof SchmittEXPORT_SYMBOL(scsilun_to_int); 12511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 12521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/** 12539f6aa5750de30b1ba35f6cb8de50c17b4fb59cabRandy Dunlap * int_to_scsilun - reverts an int into a scsi_lun 1254eb44820c28bc9a042e1157b41c677018a8fdfc74Rob Landley * @lun: integer to be reverted 12552f4701d8274c8663f5c50323dc72fefa24b55091James.Smart@Emulex.Com * @scsilun: struct scsi_lun to be set. 12562f4701d8274c8663f5c50323dc72fefa24b55091James.Smart@Emulex.Com * 12572f4701d8274c8663f5c50323dc72fefa24b55091James.Smart@Emulex.Com * Description: 12582f4701d8274c8663f5c50323dc72fefa24b55091James.Smart@Emulex.Com * Reverts the functionality of the scsilun_to_int, which packed 12592f4701d8274c8663f5c50323dc72fefa24b55091James.Smart@Emulex.Com * an 8-byte lun value into an int. This routine unpacks the int 12602f4701d8274c8663f5c50323dc72fefa24b55091James.Smart@Emulex.Com * back into the lun value. 12612f4701d8274c8663f5c50323dc72fefa24b55091James.Smart@Emulex.Com * Note: the scsilun_to_int() routine does not truly handle all 12622f4701d8274c8663f5c50323dc72fefa24b55091James.Smart@Emulex.Com * 8bytes of the lun value. This functions restores only as much 12632f4701d8274c8663f5c50323dc72fefa24b55091James.Smart@Emulex.Com * as was set by the routine. 12642f4701d8274c8663f5c50323dc72fefa24b55091James.Smart@Emulex.Com * 12652f4701d8274c8663f5c50323dc72fefa24b55091James.Smart@Emulex.Com * Notes: 12662f4701d8274c8663f5c50323dc72fefa24b55091James.Smart@Emulex.Com * Given an integer : 0x0b030a04, this function returns a 12672f4701d8274c8663f5c50323dc72fefa24b55091James.Smart@Emulex.Com * scsi_lun of : struct scsi_lun of: 0a 04 0b 03 00 00 00 00 12682f4701d8274c8663f5c50323dc72fefa24b55091James.Smart@Emulex.Com * 12692f4701d8274c8663f5c50323dc72fefa24b55091James.Smart@Emulex.Com **/ 12702f4701d8274c8663f5c50323dc72fefa24b55091James.Smart@Emulex.Comvoid int_to_scsilun(unsigned int lun, struct scsi_lun *scsilun) 12712f4701d8274c8663f5c50323dc72fefa24b55091James.Smart@Emulex.Com{ 12722f4701d8274c8663f5c50323dc72fefa24b55091James.Smart@Emulex.Com int i; 12732f4701d8274c8663f5c50323dc72fefa24b55091James.Smart@Emulex.Com 12742f4701d8274c8663f5c50323dc72fefa24b55091James.Smart@Emulex.Com memset(scsilun->scsi_lun, 0, sizeof(scsilun->scsi_lun)); 12752f4701d8274c8663f5c50323dc72fefa24b55091James.Smart@Emulex.Com 12762f4701d8274c8663f5c50323dc72fefa24b55091James.Smart@Emulex.Com for (i = 0; i < sizeof(lun); i += 2) { 12772f4701d8274c8663f5c50323dc72fefa24b55091James.Smart@Emulex.Com scsilun->scsi_lun[i] = (lun >> 8) & 0xFF; 12782f4701d8274c8663f5c50323dc72fefa24b55091James.Smart@Emulex.Com scsilun->scsi_lun[i+1] = lun & 0xFF; 12792f4701d8274c8663f5c50323dc72fefa24b55091James.Smart@Emulex.Com lun = lun >> 16; 12802f4701d8274c8663f5c50323dc72fefa24b55091James.Smart@Emulex.Com } 12812f4701d8274c8663f5c50323dc72fefa24b55091James.Smart@Emulex.Com} 12822f4701d8274c8663f5c50323dc72fefa24b55091James.Smart@Emulex.ComEXPORT_SYMBOL(int_to_scsilun); 12832f4701d8274c8663f5c50323dc72fefa24b55091James.Smart@Emulex.Com 12842f4701d8274c8663f5c50323dc72fefa24b55091James.Smart@Emulex.Com/** 12851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * scsi_report_lun_scan - Scan using SCSI REPORT LUN results 1286eb44820c28bc9a042e1157b41c677018a8fdfc74Rob Landley * @starget: which target 1287eb44820c28bc9a042e1157b41c677018a8fdfc74Rob Landley * @bflags: Zero or a mix of BLIST_NOLUN, BLIST_REPORTLUN2, or BLIST_NOREPORTLUN 1288eb44820c28bc9a042e1157b41c677018a8fdfc74Rob Landley * @rescan: nonzero if we can skip code only needed on first scan 12891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 12901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Description: 1291eb44820c28bc9a042e1157b41c677018a8fdfc74Rob Landley * Fast scanning for modern (SCSI-3) devices by sending a REPORT LUN command. 1292eb44820c28bc9a042e1157b41c677018a8fdfc74Rob Landley * Scan the resulting list of LUNs by calling scsi_probe_and_add_lun. 12931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 1294eb44820c28bc9a042e1157b41c677018a8fdfc74Rob Landley * If BLINK_REPORTLUN2 is set, scan a target that supports more than 8 1295eb44820c28bc9a042e1157b41c677018a8fdfc74Rob Landley * LUNs even if it's older than SCSI-3. 1296eb44820c28bc9a042e1157b41c677018a8fdfc74Rob Landley * If BLIST_NOREPORTLUN is set, return 1 always. 1297eb44820c28bc9a042e1157b41c677018a8fdfc74Rob Landley * If BLIST_NOLUN is set, return 0 always. 129809b6b51b0b6c1b9bb61815baf205e4d74c89ff04Alan Stern * If starget->no_report_luns is set, return 1 always. 12991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 13001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Return: 13011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 0: scan completed (or no memory, so further scanning is futile) 1302eb44820c28bc9a042e1157b41c677018a8fdfc74Rob Landley * 1: could not scan with REPORT LUN 13031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds **/ 13046f3a20242db2597312c50abc11f1e747c5d2326aJames Bottomleystatic int scsi_report_lun_scan(struct scsi_target *starget, int bflags, 13051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int rescan) 13061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 13071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds char devname[64]; 13081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned char scsi_cmd[MAX_COMMAND_SIZE]; 13091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned int length; 13101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned int lun; 13111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned int num_luns; 13121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned int retries; 1313392160335c798bbe94ab3aae6ea0c85d32b81bbcJames Bottomley int result; 13141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct scsi_lun *lunp, *lun_data; 13151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u8 *data; 13161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct scsi_sense_hdr sshdr; 13176f3a20242db2597312c50abc11f1e747c5d2326aJames Bottomley struct scsi_device *sdev; 13186f3a20242db2597312c50abc11f1e747c5d2326aJames Bottomley struct Scsi_Host *shost = dev_to_shost(&starget->dev); 13192ef8919830a262f10fb5e4a685e95f71a64bce6cAlan Stern int ret = 0; 13201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 13211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 13221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Only support SCSI-3 and up devices if BLIST_NOREPORTLUN is not set. 13231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Also allow SCSI-2 if BLIST_REPORTLUN2 is set and host adapter does 13241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * support more than 8 LUNs. 132509b6b51b0b6c1b9bb61815baf205e4d74c89ff04Alan Stern * Don't attempt if the target doesn't support REPORT LUNS. 13261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 13274d7db04a7a69099accd84984a78c64d2178252f1James Bottomley if (bflags & BLIST_NOREPORTLUN) 13284d7db04a7a69099accd84984a78c64d2178252f1James Bottomley return 1; 13294d7db04a7a69099accd84984a78c64d2178252f1James Bottomley if (starget->scsi_level < SCSI_2 && 13304d7db04a7a69099accd84984a78c64d2178252f1James Bottomley starget->scsi_level != SCSI_UNKNOWN) 13314d7db04a7a69099accd84984a78c64d2178252f1James Bottomley return 1; 13324d7db04a7a69099accd84984a78c64d2178252f1James Bottomley if (starget->scsi_level < SCSI_3 && 13334d7db04a7a69099accd84984a78c64d2178252f1James Bottomley (!(bflags & BLIST_REPORTLUN2) || shost->max_lun <= 8)) 13341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 1; 13351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (bflags & BLIST_NOLUN) 13361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 133709b6b51b0b6c1b9bb61815baf205e4d74c89ff04Alan Stern if (starget->no_report_luns) 133809b6b51b0b6c1b9bb61815baf205e4d74c89ff04Alan Stern return 1; 13391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 13406f3a20242db2597312c50abc11f1e747c5d2326aJames Bottomley if (!(sdev = scsi_device_lookup_by_target(starget, 0))) { 13416f3a20242db2597312c50abc11f1e747c5d2326aJames Bottomley sdev = scsi_alloc_sdev(starget, 0, NULL); 13426f3a20242db2597312c50abc11f1e747c5d2326aJames Bottomley if (!sdev) 13436f3a20242db2597312c50abc11f1e747c5d2326aJames Bottomley return 0; 134475f8ee8e01a6c96652f27da40d4bdac9e2e485f0Alan Stern if (scsi_device_get(sdev)) { 134575f8ee8e01a6c96652f27da40d4bdac9e2e485f0Alan Stern __scsi_remove_device(sdev); 13466f3a20242db2597312c50abc11f1e747c5d2326aJames Bottomley return 0; 134775f8ee8e01a6c96652f27da40d4bdac9e2e485f0Alan Stern } 13486f3a20242db2597312c50abc11f1e747c5d2326aJames Bottomley } 13496f3a20242db2597312c50abc11f1e747c5d2326aJames Bottomley 13501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sprintf(devname, "host %d channel %d id %d", 13516f3a20242db2597312c50abc11f1e747c5d2326aJames Bottomley shost->host_no, sdev->channel, sdev->id); 13521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 13531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 13541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Allocate enough to hold the header (the same size as one scsi_lun) 13551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * plus the max number of luns we are requesting. 13561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 13571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Reallocating and trying again (with the exact amount we need) 13581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * would be nice, but then we need to somehow limit the size 13591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * allocated based on the available memory and the limits of 13601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * kmalloc - we don't want a kmalloc() failure of a huge value to 13611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * prevent us from finding any LUNs on this target. 13621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 13631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds length = (max_scsi_report_luns + 1) * sizeof(struct scsi_lun); 13641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds lun_data = kmalloc(length, GFP_ATOMIC | 13651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (sdev->host->unchecked_isa_dma ? __GFP_DMA : 0)); 13666f3a20242db2597312c50abc11f1e747c5d2326aJames Bottomley if (!lun_data) { 1367cadbd4a5e36dde7e6c49b587b2c419103c0b7218Harvey Harrison printk(ALLOC_FAILURE_MSG, __func__); 1368392160335c798bbe94ab3aae6ea0c85d32b81bbcJames Bottomley goto out; 13696f3a20242db2597312c50abc11f1e747c5d2326aJames Bottomley } 13701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 13711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds scsi_cmd[0] = REPORT_LUNS; 13721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 13731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 13741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * bytes 1 - 5: reserved, set to zero. 13751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 13761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds memset(&scsi_cmd[1], 0, 5); 13771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 13781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 13791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * bytes 6 - 9: length of the command. 13801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 13811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds scsi_cmd[6] = (unsigned char) (length >> 24) & 0xff; 13821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds scsi_cmd[7] = (unsigned char) (length >> 16) & 0xff; 13831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds scsi_cmd[8] = (unsigned char) (length >> 8) & 0xff; 13841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds scsi_cmd[9] = (unsigned char) length & 0xff; 13851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 13861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds scsi_cmd[10] = 0; /* reserved */ 13871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds scsi_cmd[11] = 0; /* control */ 13881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 13891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 13901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * We can get a UNIT ATTENTION, for example a power on/reset, so 13911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * retry a few times (like sd.c does for TEST UNIT READY). 13921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Experience shows some combinations of adapter/devices get at 13931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * least two power on/resets. 13941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 13951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Illegal requests (for devices that do not support REPORT LUNS) 13961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * should come through as a check condition, and will not generate 13971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * a retry. 13981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 13991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (retries = 0; retries < 3; retries++) { 14001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds SCSI_LOG_SCAN_BUS(3, printk (KERN_INFO "scsi scan: Sending" 14011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds " REPORT LUNS to %s (try %d)\n", devname, 14021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds retries)); 1403392160335c798bbe94ab3aae6ea0c85d32b81bbcJames Bottomley 1404392160335c798bbe94ab3aae6ea0c85d32b81bbcJames Bottomley result = scsi_execute_req(sdev, scsi_cmd, DMA_FROM_DEVICE, 1405ea73a9f23906c374b697cd5b0d64f6dceced63deJames Bottomley lun_data, length, &sshdr, 1406f4f4e47e4af6b02dd1c425b931c65d0165356e33FUJITA Tomonori SCSI_TIMEOUT + 4 * HZ, 3, NULL); 1407392160335c798bbe94ab3aae6ea0c85d32b81bbcJames Bottomley 14081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds SCSI_LOG_SCAN_BUS(3, printk (KERN_INFO "scsi scan: REPORT LUNS" 1409392160335c798bbe94ab3aae6ea0c85d32b81bbcJames Bottomley " %s (try %d) result 0x%x\n", result 1410392160335c798bbe94ab3aae6ea0c85d32b81bbcJames Bottomley ? "failed" : "successful", retries, result)); 1411392160335c798bbe94ab3aae6ea0c85d32b81bbcJames Bottomley if (result == 0) 14121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 1413ea73a9f23906c374b697cd5b0d64f6dceced63deJames Bottomley else if (scsi_sense_valid(&sshdr)) { 14141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (sshdr.sense_key != UNIT_ATTENTION) 14151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 14161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 14171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 14181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1419392160335c798bbe94ab3aae6ea0c85d32b81bbcJames Bottomley if (result) { 14201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 14211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * The device probably does not support a REPORT LUN command 14221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 14232ef8919830a262f10fb5e4a685e95f71a64bce6cAlan Stern ret = 1; 14242ef8919830a262f10fb5e4a685e95f71a64bce6cAlan Stern goto out_err; 14251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 14261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 14271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 14281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Get the length from the first four bytes of lun_data. 14291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 14301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds data = (u8 *) lun_data->scsi_lun; 14311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds length = ((data[0] << 24) | (data[1] << 16) | 14321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (data[2] << 8) | (data[3] << 0)); 14331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 14341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds num_luns = (length / sizeof(struct scsi_lun)); 14351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (num_luns > max_scsi_report_luns) { 14361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk(KERN_WARNING "scsi: On %s only %d (max_scsi_report_luns)" 14371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds " of %d luns reported, try increasing" 14381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds " max_scsi_report_luns.\n", devname, 14391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds max_scsi_report_luns, num_luns); 14401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds num_luns = max_scsi_report_luns; 14411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 14421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 14433bf743e7c891d8be8295650b7a6a9b5af083b096Jeff Garzik SCSI_LOG_SCAN_BUS(3, sdev_printk (KERN_INFO, sdev, 14443bf743e7c891d8be8295650b7a6a9b5af083b096Jeff Garzik "scsi scan: REPORT LUN scan\n")); 14451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 14461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 14471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Scan the luns in lun_data. The entry at offset 0 is really 14481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * the header, so start at 1 and go up to and including num_luns. 14491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 14501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (lunp = &lun_data[1]; lunp <= &lun_data[num_luns]; lunp++) { 14511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds lun = scsilun_to_int(lunp); 14521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 14531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 14541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Check if the unused part of lunp is non-zero, and so 14551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * does not fit in lun. 14561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 14571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (memcmp(&lunp->scsi_lun[sizeof(lun)], "\0\0\0\0", 4)) { 14581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int i; 14591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 14601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 14611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Output an error displaying the LUN in byte order, 14621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * this differs from what linux would print for the 14631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * integer LUN value. 14641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 14651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk(KERN_WARNING "scsi: %s lun 0x", devname); 14661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds data = (char *)lunp->scsi_lun; 14671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (i = 0; i < sizeof(struct scsi_lun); i++) 14681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk("%02x", data[i]); 14691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk(" has a LUN larger than currently supported.\n"); 14701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else if (lun > sdev->host->max_lun) { 14711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk(KERN_WARNING "scsi: %s lun%d has a LUN larger" 14721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds " than allowed by the host adapter\n", 14731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds devname, lun); 14741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 14751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int res; 14761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 14771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds res = scsi_probe_and_add_lun(starget, 14781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds lun, NULL, NULL, rescan, NULL); 14791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (res == SCSI_SCAN_NO_RESPONSE) { 14801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 14811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Got some results, but now none, abort. 14821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 14833bf743e7c891d8be8295650b7a6a9b5af083b096Jeff Garzik sdev_printk(KERN_ERR, sdev, 14843bf743e7c891d8be8295650b7a6a9b5af083b096Jeff Garzik "Unexpected response" 14853bf743e7c891d8be8295650b7a6a9b5af083b096Jeff Garzik " from lun %d while scanning, scan" 14863bf743e7c891d8be8295650b7a6a9b5af083b096Jeff Garzik " aborted\n", lun); 14871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 14881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 14891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 14901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 14911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 14922ef8919830a262f10fb5e4a685e95f71a64bce6cAlan Stern out_err: 14931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds kfree(lun_data); 14941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds out: 14956f3a20242db2597312c50abc11f1e747c5d2326aJames Bottomley scsi_device_put(sdev); 14960f1d87a2acb8fd1f2ef8af109a785123ddc1a6cbJames Bottomley if (scsi_device_created(sdev)) 14976f3a20242db2597312c50abc11f1e747c5d2326aJames Bottomley /* 14986f3a20242db2597312c50abc11f1e747c5d2326aJames Bottomley * the sdev we used didn't appear in the report luns scan 14996f3a20242db2597312c50abc11f1e747c5d2326aJames Bottomley */ 1500860dc73608a091e0b325218acc2701709d5f221aJames Bottomley __scsi_remove_device(sdev); 15012ef8919830a262f10fb5e4a685e95f71a64bce6cAlan Stern return ret; 15021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 15031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 15041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstruct scsi_device *__scsi_add_device(struct Scsi_Host *shost, uint channel, 15051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds uint id, uint lun, void *hostdata) 15061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1507a97a83a06b44d4d1cb01191423caf9813a150b95Matthew Wilcox struct scsi_device *sdev = ERR_PTR(-ENODEV); 15081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct device *parent = &shost->shost_gendev; 1509e02f3f59225d8c3b2a0ad0dc941a09865e27da61Christoph Hellwig struct scsi_target *starget; 15101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1511938e2ac0b7ac72d264783b0b548eb6078c295294Matthew Wilcox if (strncmp(scsi_scan_type, "none", 4) == 0) 1512938e2ac0b7ac72d264783b0b548eb6078c295294Matthew Wilcox return ERR_PTR(-ENODEV); 1513938e2ac0b7ac72d264783b0b548eb6078c295294Matthew Wilcox 1514e02f3f59225d8c3b2a0ad0dc941a09865e27da61Christoph Hellwig starget = scsi_alloc_target(parent, channel, id); 15151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!starget) 15161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return ERR_PTR(-ENOMEM); 1517bc4f24014de58f045f169742701a6598884d93dbAlan Stern scsi_autopm_get_target(starget); 15181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 15190b9506723826c68b50fa33e345700ddcac1bed36Arjan van de Ven mutex_lock(&shost->scan_mutex); 15206b7f123f378743d739377871c0cbfbaf28c7d25aMatthew Wilcox if (!shost->async_scan) 15216b7f123f378743d739377871c0cbfbaf28c7d25aMatthew Wilcox scsi_complete_async_scans(); 15226b7f123f378743d739377871c0cbfbaf28c7d25aMatthew Wilcox 1523bc4f24014de58f045f169742701a6598884d93dbAlan Stern if (scsi_host_scan_allowed(shost) && scsi_autopm_get_host(shost) == 0) { 1524a97a83a06b44d4d1cb01191423caf9813a150b95Matthew Wilcox scsi_probe_and_add_lun(starget, lun, NULL, &sdev, 1, hostdata); 1525bc4f24014de58f045f169742701a6598884d93dbAlan Stern scsi_autopm_put_host(shost); 1526bc4f24014de58f045f169742701a6598884d93dbAlan Stern } 15270b9506723826c68b50fa33e345700ddcac1bed36Arjan van de Ven mutex_unlock(&shost->scan_mutex); 1528bc4f24014de58f045f169742701a6598884d93dbAlan Stern scsi_autopm_put_target(starget); 15291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds scsi_target_reap(starget); 15301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds put_device(&starget->dev); 15311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 15321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return sdev; 15331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 15341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsEXPORT_SYMBOL(__scsi_add_device); 15351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1536146f7262ee0ec7fc6882f06e5fcb13883308073cJames Bottomleyint scsi_add_device(struct Scsi_Host *host, uint channel, 1537146f7262ee0ec7fc6882f06e5fcb13883308073cJames Bottomley uint target, uint lun) 1538146f7262ee0ec7fc6882f06e5fcb13883308073cJames Bottomley{ 1539146f7262ee0ec7fc6882f06e5fcb13883308073cJames Bottomley struct scsi_device *sdev = 1540146f7262ee0ec7fc6882f06e5fcb13883308073cJames Bottomley __scsi_add_device(host, channel, target, lun, NULL); 1541146f7262ee0ec7fc6882f06e5fcb13883308073cJames Bottomley if (IS_ERR(sdev)) 1542146f7262ee0ec7fc6882f06e5fcb13883308073cJames Bottomley return PTR_ERR(sdev); 1543146f7262ee0ec7fc6882f06e5fcb13883308073cJames Bottomley 1544146f7262ee0ec7fc6882f06e5fcb13883308073cJames Bottomley scsi_device_put(sdev); 1545146f7262ee0ec7fc6882f06e5fcb13883308073cJames Bottomley return 0; 1546146f7262ee0ec7fc6882f06e5fcb13883308073cJames Bottomley} 1547146f7262ee0ec7fc6882f06e5fcb13883308073cJames BottomleyEXPORT_SYMBOL(scsi_add_device); 1548146f7262ee0ec7fc6882f06e5fcb13883308073cJames Bottomley 15491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid scsi_rescan_device(struct device *dev) 15501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 15511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct scsi_driver *drv; 15521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 15531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!dev->driver) 15541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return; 15551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 15561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds drv = to_scsi_driver(dev->driver); 15571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (try_module_get(drv->owner)) { 15581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (drv->rescan) 15591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds drv->rescan(dev); 15601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds module_put(drv->owner); 15611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 15621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 15631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsEXPORT_SYMBOL(scsi_rescan_device); 15641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1565e517d3133f62c27b211f305a6dbd6f6ccac0db1bAlan Sternstatic void __scsi_scan_target(struct device *parent, unsigned int channel, 1566e517d3133f62c27b211f305a6dbd6f6ccac0db1bAlan Stern unsigned int id, unsigned int lun, int rescan) 15671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 15681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct Scsi_Host *shost = dev_to_shost(parent); 15691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int bflags = 0; 15701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int res; 15711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct scsi_target *starget; 15721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 15731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (shost->this_id == id) 15741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 15751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Don't scan the host adapter 15761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 15771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return; 15781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 15791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds starget = scsi_alloc_target(parent, channel, id); 15801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!starget) 15811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return; 1582bc4f24014de58f045f169742701a6598884d93dbAlan Stern scsi_autopm_get_target(starget); 15831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 15841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (lun != SCAN_WILD_CARD) { 15851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 15861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Scan for a specific host/chan/id/lun. 15871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 15881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds scsi_probe_and_add_lun(starget, lun, NULL, NULL, rescan, NULL); 15891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto out_reap; 15901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 15911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 15921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 15931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Scan LUN 0, if there is some response, scan further. Ideally, we 15941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * would not configure LUN 0 until all LUNs are scanned. 15951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 15966f3a20242db2597312c50abc11f1e747c5d2326aJames Bottomley res = scsi_probe_and_add_lun(starget, 0, &bflags, NULL, rescan, NULL); 15976f3a20242db2597312c50abc11f1e747c5d2326aJames Bottomley if (res == SCSI_SCAN_LUN_PRESENT || res == SCSI_SCAN_TARGET_PRESENT) { 15986f3a20242db2597312c50abc11f1e747c5d2326aJames Bottomley if (scsi_report_lun_scan(starget, bflags, rescan) != 0) 15991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 16001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * The REPORT LUN did not scan the target, 16011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * do a sequential scan. 16021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 16031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds scsi_sequential_lun_scan(starget, bflags, 16044186ab1973758190916703eb8889ebe8002c5c8fKurt Garloff starget->scsi_level, rescan); 16051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 16061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 16071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds out_reap: 1608bc4f24014de58f045f169742701a6598884d93dbAlan Stern scsi_autopm_put_target(starget); 16091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* now determine if the target has any children at all 16101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * and if not, nuke it */ 16111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds scsi_target_reap(starget); 16121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 16131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds put_device(&starget->dev); 16141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1615e517d3133f62c27b211f305a6dbd6f6ccac0db1bAlan Stern 1616e517d3133f62c27b211f305a6dbd6f6ccac0db1bAlan Stern/** 1617e59e4a09729b06a131de9042b2a5b05b7ad26174Randy Dunlap * scsi_scan_target - scan a target id, possibly including all LUNs on the target. 1618e517d3133f62c27b211f305a6dbd6f6ccac0db1bAlan Stern * @parent: host to scan 1619e517d3133f62c27b211f305a6dbd6f6ccac0db1bAlan Stern * @channel: channel to scan 1620e517d3133f62c27b211f305a6dbd6f6ccac0db1bAlan Stern * @id: target id to scan 1621e517d3133f62c27b211f305a6dbd6f6ccac0db1bAlan Stern * @lun: Specific LUN to scan or SCAN_WILD_CARD 1622e517d3133f62c27b211f305a6dbd6f6ccac0db1bAlan Stern * @rescan: passed to LUN scanning routines 1623e517d3133f62c27b211f305a6dbd6f6ccac0db1bAlan Stern * 1624e517d3133f62c27b211f305a6dbd6f6ccac0db1bAlan Stern * Description: 1625e517d3133f62c27b211f305a6dbd6f6ccac0db1bAlan Stern * Scan the target id on @parent, @channel, and @id. Scan at least LUN 0, 1626e517d3133f62c27b211f305a6dbd6f6ccac0db1bAlan Stern * and possibly all LUNs on the target id. 1627e517d3133f62c27b211f305a6dbd6f6ccac0db1bAlan Stern * 1628e517d3133f62c27b211f305a6dbd6f6ccac0db1bAlan Stern * First try a REPORT LUN scan, if that does not scan the target, do a 1629e517d3133f62c27b211f305a6dbd6f6ccac0db1bAlan Stern * sequential scan of LUNs on the target id. 1630e517d3133f62c27b211f305a6dbd6f6ccac0db1bAlan Stern **/ 1631e517d3133f62c27b211f305a6dbd6f6ccac0db1bAlan Sternvoid scsi_scan_target(struct device *parent, unsigned int channel, 1632e517d3133f62c27b211f305a6dbd6f6ccac0db1bAlan Stern unsigned int id, unsigned int lun, int rescan) 1633e517d3133f62c27b211f305a6dbd6f6ccac0db1bAlan Stern{ 1634e517d3133f62c27b211f305a6dbd6f6ccac0db1bAlan Stern struct Scsi_Host *shost = dev_to_shost(parent); 1635e517d3133f62c27b211f305a6dbd6f6ccac0db1bAlan Stern 163693b45af5c6b9d41bbe9da11442291ac4eefc15b4Matthew Wilcox if (strncmp(scsi_scan_type, "none", 4) == 0) 163793b45af5c6b9d41bbe9da11442291ac4eefc15b4Matthew Wilcox return; 163893b45af5c6b9d41bbe9da11442291ac4eefc15b4Matthew Wilcox 16396b7f123f378743d739377871c0cbfbaf28c7d25aMatthew Wilcox mutex_lock(&shost->scan_mutex); 16403e082a910d217b2e7b186077ebf5a1126a68c62fMatthew Wilcox if (!shost->async_scan) 16413e082a910d217b2e7b186077ebf5a1126a68c62fMatthew Wilcox scsi_complete_async_scans(); 16423e082a910d217b2e7b186077ebf5a1126a68c62fMatthew Wilcox 1643bc4f24014de58f045f169742701a6598884d93dbAlan Stern if (scsi_host_scan_allowed(shost) && scsi_autopm_get_host(shost) == 0) { 1644e517d3133f62c27b211f305a6dbd6f6ccac0db1bAlan Stern __scsi_scan_target(parent, channel, id, lun, rescan); 1645bc4f24014de58f045f169742701a6598884d93dbAlan Stern scsi_autopm_put_host(shost); 1646bc4f24014de58f045f169742701a6598884d93dbAlan Stern } 16470b9506723826c68b50fa33e345700ddcac1bed36Arjan van de Ven mutex_unlock(&shost->scan_mutex); 1648e517d3133f62c27b211f305a6dbd6f6ccac0db1bAlan Stern} 16491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsEXPORT_SYMBOL(scsi_scan_target); 16501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 16511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void scsi_scan_channel(struct Scsi_Host *shost, unsigned int channel, 16521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned int id, unsigned int lun, int rescan) 16531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 16541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds uint order_id; 16551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 16561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (id == SCAN_WILD_CARD) 16571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (id = 0; id < shost->max_id; ++id) { 16581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 16591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * XXX adapter drivers when possible (FCP, iSCSI) 16601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * could modify max_id to match the current max, 16611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * not the absolute max. 16621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 16631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * XXX add a shost id iterator, so for example, 16641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * the FC ID can be the same as a target id 16651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * without a huge overhead of sparse id's. 16661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 16671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (shost->reverse_ordering) 16681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 16691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Scan from high to low id. 16701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 16711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds order_id = shost->max_id - id - 1; 16721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else 16731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds order_id = id; 1674e517d3133f62c27b211f305a6dbd6f6ccac0db1bAlan Stern __scsi_scan_target(&shost->shost_gendev, channel, 1675e517d3133f62c27b211f305a6dbd6f6ccac0db1bAlan Stern order_id, lun, rescan); 16761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 16771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else 1678e517d3133f62c27b211f305a6dbd6f6ccac0db1bAlan Stern __scsi_scan_target(&shost->shost_gendev, channel, 1679e517d3133f62c27b211f305a6dbd6f6ccac0db1bAlan Stern id, lun, rescan); 16801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 16811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 16821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint scsi_scan_host_selected(struct Scsi_Host *shost, unsigned int channel, 16831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned int id, unsigned int lun, int rescan) 16841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 16853bf743e7c891d8be8295650b7a6a9b5af083b096Jeff Garzik SCSI_LOG_SCAN_BUS(3, shost_printk (KERN_INFO, shost, 16863bf743e7c891d8be8295650b7a6a9b5af083b096Jeff Garzik "%s: <%u:%u:%u>\n", 1687cadbd4a5e36dde7e6c49b587b2c419103c0b7218Harvey Harrison __func__, channel, id, lun)); 16881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 16891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (((channel != SCAN_WILD_CARD) && (channel > shost->max_channel)) || 1690091686d3b5569d2ec76b9e6dab7f3608b6f64497Amit Arora ((id != SCAN_WILD_CARD) && (id >= shost->max_id)) || 16911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ((lun != SCAN_WILD_CARD) && (lun > shost->max_lun))) 16921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EINVAL; 16931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 16940b9506723826c68b50fa33e345700ddcac1bed36Arjan van de Ven mutex_lock(&shost->scan_mutex); 16956b7f123f378743d739377871c0cbfbaf28c7d25aMatthew Wilcox if (!shost->async_scan) 16966b7f123f378743d739377871c0cbfbaf28c7d25aMatthew Wilcox scsi_complete_async_scans(); 16976b7f123f378743d739377871c0cbfbaf28c7d25aMatthew Wilcox 1698bc4f24014de58f045f169742701a6598884d93dbAlan Stern if (scsi_host_scan_allowed(shost) && scsi_autopm_get_host(shost) == 0) { 169982f29467a025f6a2192d281e97fca0be46e905ccMike Anderson if (channel == SCAN_WILD_CARD) 170082f29467a025f6a2192d281e97fca0be46e905ccMike Anderson for (channel = 0; channel <= shost->max_channel; 170182f29467a025f6a2192d281e97fca0be46e905ccMike Anderson channel++) 170282f29467a025f6a2192d281e97fca0be46e905ccMike Anderson scsi_scan_channel(shost, channel, id, lun, 170382f29467a025f6a2192d281e97fca0be46e905ccMike Anderson rescan); 170482f29467a025f6a2192d281e97fca0be46e905ccMike Anderson else 17051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds scsi_scan_channel(shost, channel, id, lun, rescan); 1706bc4f24014de58f045f169742701a6598884d93dbAlan Stern scsi_autopm_put_host(shost); 170782f29467a025f6a2192d281e97fca0be46e905ccMike Anderson } 17080b9506723826c68b50fa33e345700ddcac1bed36Arjan van de Ven mutex_unlock(&shost->scan_mutex); 17091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 17101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 17111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 17121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 17133e082a910d217b2e7b186077ebf5a1126a68c62fMatthew Wilcoxstatic void scsi_sysfs_add_devices(struct Scsi_Host *shost) 17143e082a910d217b2e7b186077ebf5a1126a68c62fMatthew Wilcox{ 17153e082a910d217b2e7b186077ebf5a1126a68c62fMatthew Wilcox struct scsi_device *sdev; 17163e082a910d217b2e7b186077ebf5a1126a68c62fMatthew Wilcox shost_for_each_device(sdev, shost) { 17176b7f123f378743d739377871c0cbfbaf28c7d25aMatthew Wilcox if (!scsi_host_scan_allowed(shost) || 17186b7f123f378743d739377871c0cbfbaf28c7d25aMatthew Wilcox scsi_sysfs_add_sdev(sdev) != 0) 1719860dc73608a091e0b325218acc2701709d5f221aJames Bottomley __scsi_remove_device(sdev); 17203e082a910d217b2e7b186077ebf5a1126a68c62fMatthew Wilcox } 17213e082a910d217b2e7b186077ebf5a1126a68c62fMatthew Wilcox} 17223e082a910d217b2e7b186077ebf5a1126a68c62fMatthew Wilcox 17233e082a910d217b2e7b186077ebf5a1126a68c62fMatthew Wilcox/** 17243e082a910d217b2e7b186077ebf5a1126a68c62fMatthew Wilcox * scsi_prep_async_scan - prepare for an async scan 17253e082a910d217b2e7b186077ebf5a1126a68c62fMatthew Wilcox * @shost: the host which will be scanned 17263e082a910d217b2e7b186077ebf5a1126a68c62fMatthew Wilcox * Returns: a cookie to be passed to scsi_finish_async_scan() 17273e082a910d217b2e7b186077ebf5a1126a68c62fMatthew Wilcox * 17283e082a910d217b2e7b186077ebf5a1126a68c62fMatthew Wilcox * Tells the midlayer this host is going to do an asynchronous scan. 17293e082a910d217b2e7b186077ebf5a1126a68c62fMatthew Wilcox * It reserves the host's position in the scanning list and ensures 17303e082a910d217b2e7b186077ebf5a1126a68c62fMatthew Wilcox * that other asynchronous scans started after this one won't affect the 17313e082a910d217b2e7b186077ebf5a1126a68c62fMatthew Wilcox * ordering of the discovered devices. 17323e082a910d217b2e7b186077ebf5a1126a68c62fMatthew Wilcox */ 17331aa8fab2acf1cb8b341131b726773fcff0abc707Matthew Wilcoxstatic struct async_scan_data *scsi_prep_async_scan(struct Scsi_Host *shost) 17343e082a910d217b2e7b186077ebf5a1126a68c62fMatthew Wilcox{ 17353e082a910d217b2e7b186077ebf5a1126a68c62fMatthew Wilcox struct async_scan_data *data; 17366b7f123f378743d739377871c0cbfbaf28c7d25aMatthew Wilcox unsigned long flags; 17373e082a910d217b2e7b186077ebf5a1126a68c62fMatthew Wilcox 17383e082a910d217b2e7b186077ebf5a1126a68c62fMatthew Wilcox if (strncmp(scsi_scan_type, "sync", 4) == 0) 17393e082a910d217b2e7b186077ebf5a1126a68c62fMatthew Wilcox return NULL; 17403e082a910d217b2e7b186077ebf5a1126a68c62fMatthew Wilcox 17413e082a910d217b2e7b186077ebf5a1126a68c62fMatthew Wilcox if (shost->async_scan) { 1742cadbd4a5e36dde7e6c49b587b2c419103c0b7218Harvey Harrison printk("%s called twice for host %d", __func__, 17433e082a910d217b2e7b186077ebf5a1126a68c62fMatthew Wilcox shost->host_no); 17443e082a910d217b2e7b186077ebf5a1126a68c62fMatthew Wilcox dump_stack(); 17453e082a910d217b2e7b186077ebf5a1126a68c62fMatthew Wilcox return NULL; 17463e082a910d217b2e7b186077ebf5a1126a68c62fMatthew Wilcox } 17473e082a910d217b2e7b186077ebf5a1126a68c62fMatthew Wilcox 17483e082a910d217b2e7b186077ebf5a1126a68c62fMatthew Wilcox data = kmalloc(sizeof(*data), GFP_KERNEL); 17493e082a910d217b2e7b186077ebf5a1126a68c62fMatthew Wilcox if (!data) 17503e082a910d217b2e7b186077ebf5a1126a68c62fMatthew Wilcox goto err; 17513e082a910d217b2e7b186077ebf5a1126a68c62fMatthew Wilcox data->shost = scsi_host_get(shost); 17523e082a910d217b2e7b186077ebf5a1126a68c62fMatthew Wilcox if (!data->shost) 17533e082a910d217b2e7b186077ebf5a1126a68c62fMatthew Wilcox goto err; 17543e082a910d217b2e7b186077ebf5a1126a68c62fMatthew Wilcox init_completion(&data->prev_finished); 17553e082a910d217b2e7b186077ebf5a1126a68c62fMatthew Wilcox 17566b7f123f378743d739377871c0cbfbaf28c7d25aMatthew Wilcox mutex_lock(&shost->scan_mutex); 17576b7f123f378743d739377871c0cbfbaf28c7d25aMatthew Wilcox spin_lock_irqsave(shost->host_lock, flags); 17583e082a910d217b2e7b186077ebf5a1126a68c62fMatthew Wilcox shost->async_scan = 1; 17596b7f123f378743d739377871c0cbfbaf28c7d25aMatthew Wilcox spin_unlock_irqrestore(shost->host_lock, flags); 17606b7f123f378743d739377871c0cbfbaf28c7d25aMatthew Wilcox mutex_unlock(&shost->scan_mutex); 17616b7f123f378743d739377871c0cbfbaf28c7d25aMatthew Wilcox 17626b7f123f378743d739377871c0cbfbaf28c7d25aMatthew Wilcox spin_lock(&async_scan_lock); 17633e082a910d217b2e7b186077ebf5a1126a68c62fMatthew Wilcox if (list_empty(&scanning_hosts)) 17643e082a910d217b2e7b186077ebf5a1126a68c62fMatthew Wilcox complete(&data->prev_finished); 17653e082a910d217b2e7b186077ebf5a1126a68c62fMatthew Wilcox list_add_tail(&data->list, &scanning_hosts); 17663e082a910d217b2e7b186077ebf5a1126a68c62fMatthew Wilcox spin_unlock(&async_scan_lock); 17673e082a910d217b2e7b186077ebf5a1126a68c62fMatthew Wilcox 17683e082a910d217b2e7b186077ebf5a1126a68c62fMatthew Wilcox return data; 17693e082a910d217b2e7b186077ebf5a1126a68c62fMatthew Wilcox 17703e082a910d217b2e7b186077ebf5a1126a68c62fMatthew Wilcox err: 17713e082a910d217b2e7b186077ebf5a1126a68c62fMatthew Wilcox kfree(data); 17723e082a910d217b2e7b186077ebf5a1126a68c62fMatthew Wilcox return NULL; 17733e082a910d217b2e7b186077ebf5a1126a68c62fMatthew Wilcox} 17743e082a910d217b2e7b186077ebf5a1126a68c62fMatthew Wilcox 17753e082a910d217b2e7b186077ebf5a1126a68c62fMatthew Wilcox/** 17763e082a910d217b2e7b186077ebf5a1126a68c62fMatthew Wilcox * scsi_finish_async_scan - asynchronous scan has finished 17773e082a910d217b2e7b186077ebf5a1126a68c62fMatthew Wilcox * @data: cookie returned from earlier call to scsi_prep_async_scan() 17783e082a910d217b2e7b186077ebf5a1126a68c62fMatthew Wilcox * 17793e082a910d217b2e7b186077ebf5a1126a68c62fMatthew Wilcox * All the devices currently attached to this host have been found. 17803e082a910d217b2e7b186077ebf5a1126a68c62fMatthew Wilcox * This function announces all the devices it has found to the rest 17813e082a910d217b2e7b186077ebf5a1126a68c62fMatthew Wilcox * of the system. 17823e082a910d217b2e7b186077ebf5a1126a68c62fMatthew Wilcox */ 17831aa8fab2acf1cb8b341131b726773fcff0abc707Matthew Wilcoxstatic void scsi_finish_async_scan(struct async_scan_data *data) 17843e082a910d217b2e7b186077ebf5a1126a68c62fMatthew Wilcox{ 17853e082a910d217b2e7b186077ebf5a1126a68c62fMatthew Wilcox struct Scsi_Host *shost; 17866b7f123f378743d739377871c0cbfbaf28c7d25aMatthew Wilcox unsigned long flags; 17873e082a910d217b2e7b186077ebf5a1126a68c62fMatthew Wilcox 17883e082a910d217b2e7b186077ebf5a1126a68c62fMatthew Wilcox if (!data) 17893e082a910d217b2e7b186077ebf5a1126a68c62fMatthew Wilcox return; 17903e082a910d217b2e7b186077ebf5a1126a68c62fMatthew Wilcox 17913e082a910d217b2e7b186077ebf5a1126a68c62fMatthew Wilcox shost = data->shost; 17926b7f123f378743d739377871c0cbfbaf28c7d25aMatthew Wilcox 17936b7f123f378743d739377871c0cbfbaf28c7d25aMatthew Wilcox mutex_lock(&shost->scan_mutex); 17946b7f123f378743d739377871c0cbfbaf28c7d25aMatthew Wilcox 17953e082a910d217b2e7b186077ebf5a1126a68c62fMatthew Wilcox if (!shost->async_scan) { 1796cadbd4a5e36dde7e6c49b587b2c419103c0b7218Harvey Harrison printk("%s called twice for host %d", __func__, 17973e082a910d217b2e7b186077ebf5a1126a68c62fMatthew Wilcox shost->host_no); 17983e082a910d217b2e7b186077ebf5a1126a68c62fMatthew Wilcox dump_stack(); 1799773e82f6cdb026282ff7d26aaac291a5fa84ee3aJulia Lawall mutex_unlock(&shost->scan_mutex); 18003e082a910d217b2e7b186077ebf5a1126a68c62fMatthew Wilcox return; 18013e082a910d217b2e7b186077ebf5a1126a68c62fMatthew Wilcox } 18023e082a910d217b2e7b186077ebf5a1126a68c62fMatthew Wilcox 18033e082a910d217b2e7b186077ebf5a1126a68c62fMatthew Wilcox wait_for_completion(&data->prev_finished); 18043e082a910d217b2e7b186077ebf5a1126a68c62fMatthew Wilcox 18053e082a910d217b2e7b186077ebf5a1126a68c62fMatthew Wilcox scsi_sysfs_add_devices(shost); 18063e082a910d217b2e7b186077ebf5a1126a68c62fMatthew Wilcox 18076b7f123f378743d739377871c0cbfbaf28c7d25aMatthew Wilcox spin_lock_irqsave(shost->host_lock, flags); 18083e082a910d217b2e7b186077ebf5a1126a68c62fMatthew Wilcox shost->async_scan = 0; 18096b7f123f378743d739377871c0cbfbaf28c7d25aMatthew Wilcox spin_unlock_irqrestore(shost->host_lock, flags); 18106b7f123f378743d739377871c0cbfbaf28c7d25aMatthew Wilcox 18116b7f123f378743d739377871c0cbfbaf28c7d25aMatthew Wilcox mutex_unlock(&shost->scan_mutex); 18126b7f123f378743d739377871c0cbfbaf28c7d25aMatthew Wilcox 18136b7f123f378743d739377871c0cbfbaf28c7d25aMatthew Wilcox spin_lock(&async_scan_lock); 18143e082a910d217b2e7b186077ebf5a1126a68c62fMatthew Wilcox list_del(&data->list); 18153e082a910d217b2e7b186077ebf5a1126a68c62fMatthew Wilcox if (!list_empty(&scanning_hosts)) { 18163e082a910d217b2e7b186077ebf5a1126a68c62fMatthew Wilcox struct async_scan_data *next = list_entry(scanning_hosts.next, 18173e082a910d217b2e7b186077ebf5a1126a68c62fMatthew Wilcox struct async_scan_data, list); 18183e082a910d217b2e7b186077ebf5a1126a68c62fMatthew Wilcox complete(&next->prev_finished); 18193e082a910d217b2e7b186077ebf5a1126a68c62fMatthew Wilcox } 18203e082a910d217b2e7b186077ebf5a1126a68c62fMatthew Wilcox spin_unlock(&async_scan_lock); 18213e082a910d217b2e7b186077ebf5a1126a68c62fMatthew Wilcox 1822267a6ad4aefaafbde607804c60945bcf97f91c1bHuajun Li scsi_autopm_put_host(shost); 18233e082a910d217b2e7b186077ebf5a1126a68c62fMatthew Wilcox scsi_host_put(shost); 18243e082a910d217b2e7b186077ebf5a1126a68c62fMatthew Wilcox kfree(data); 18253e082a910d217b2e7b186077ebf5a1126a68c62fMatthew Wilcox} 18263e082a910d217b2e7b186077ebf5a1126a68c62fMatthew Wilcox 18271aa8fab2acf1cb8b341131b726773fcff0abc707Matthew Wilcoxstatic void do_scsi_scan_host(struct Scsi_Host *shost) 18283e082a910d217b2e7b186077ebf5a1126a68c62fMatthew Wilcox{ 18291aa8fab2acf1cb8b341131b726773fcff0abc707Matthew Wilcox if (shost->hostt->scan_finished) { 18301aa8fab2acf1cb8b341131b726773fcff0abc707Matthew Wilcox unsigned long start = jiffies; 18311aa8fab2acf1cb8b341131b726773fcff0abc707Matthew Wilcox if (shost->hostt->scan_start) 18321aa8fab2acf1cb8b341131b726773fcff0abc707Matthew Wilcox shost->hostt->scan_start(shost); 18331aa8fab2acf1cb8b341131b726773fcff0abc707Matthew Wilcox 18341aa8fab2acf1cb8b341131b726773fcff0abc707Matthew Wilcox while (!shost->hostt->scan_finished(shost, jiffies - start)) 18351aa8fab2acf1cb8b341131b726773fcff0abc707Matthew Wilcox msleep(10); 18361aa8fab2acf1cb8b341131b726773fcff0abc707Matthew Wilcox } else { 18371aa8fab2acf1cb8b341131b726773fcff0abc707Matthew Wilcox scsi_scan_host_selected(shost, SCAN_WILD_CARD, SCAN_WILD_CARD, 18383e082a910d217b2e7b186077ebf5a1126a68c62fMatthew Wilcox SCAN_WILD_CARD, 0); 18391aa8fab2acf1cb8b341131b726773fcff0abc707Matthew Wilcox } 18401aa8fab2acf1cb8b341131b726773fcff0abc707Matthew Wilcox} 18413e082a910d217b2e7b186077ebf5a1126a68c62fMatthew Wilcox 18421aa8fab2acf1cb8b341131b726773fcff0abc707Matthew Wilcoxstatic int do_scan_async(void *_data) 18431aa8fab2acf1cb8b341131b726773fcff0abc707Matthew Wilcox{ 18441aa8fab2acf1cb8b341131b726773fcff0abc707Matthew Wilcox struct async_scan_data *data = _data; 1845bc4f24014de58f045f169742701a6598884d93dbAlan Stern struct Scsi_Host *shost = data->shost; 1846bc4f24014de58f045f169742701a6598884d93dbAlan Stern 1847bc4f24014de58f045f169742701a6598884d93dbAlan Stern do_scsi_scan_host(shost); 18483e082a910d217b2e7b186077ebf5a1126a68c62fMatthew Wilcox scsi_finish_async_scan(data); 18493e082a910d217b2e7b186077ebf5a1126a68c62fMatthew Wilcox return 0; 18503e082a910d217b2e7b186077ebf5a1126a68c62fMatthew Wilcox} 18513e082a910d217b2e7b186077ebf5a1126a68c62fMatthew Wilcox 18521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/** 18531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * scsi_scan_host - scan the given adapter 18541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @shost: adapter to scan 18551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds **/ 18561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid scsi_scan_host(struct Scsi_Host *shost) 18571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1858a57b1fccdfa65b78481f5e651833d979e545de04Matthew Wilcox struct task_struct *p; 18593e082a910d217b2e7b186077ebf5a1126a68c62fMatthew Wilcox struct async_scan_data *data; 18603e082a910d217b2e7b186077ebf5a1126a68c62fMatthew Wilcox 18613e082a910d217b2e7b186077ebf5a1126a68c62fMatthew Wilcox if (strncmp(scsi_scan_type, "none", 4) == 0) 18623e082a910d217b2e7b186077ebf5a1126a68c62fMatthew Wilcox return; 1863bc4f24014de58f045f169742701a6598884d93dbAlan Stern if (scsi_autopm_get_host(shost) < 0) 1864bc4f24014de58f045f169742701a6598884d93dbAlan Stern return; 18653e082a910d217b2e7b186077ebf5a1126a68c62fMatthew Wilcox 18663e082a910d217b2e7b186077ebf5a1126a68c62fMatthew Wilcox data = scsi_prep_async_scan(shost); 18673e082a910d217b2e7b186077ebf5a1126a68c62fMatthew Wilcox if (!data) { 18681aa8fab2acf1cb8b341131b726773fcff0abc707Matthew Wilcox do_scsi_scan_host(shost); 1869bc4f24014de58f045f169742701a6598884d93dbAlan Stern scsi_autopm_put_host(shost); 18703e082a910d217b2e7b186077ebf5a1126a68c62fMatthew Wilcox return; 18713e082a910d217b2e7b186077ebf5a1126a68c62fMatthew Wilcox } 18721aa8fab2acf1cb8b341131b726773fcff0abc707Matthew Wilcox 1873a57b1fccdfa65b78481f5e651833d979e545de04Matthew Wilcox p = kthread_run(do_scan_async, data, "scsi_scan_%d", shost->host_no); 1874801678c5a3b4c79236970bcca27c733f5559e0d1Hirofumi Nakagawa if (IS_ERR(p)) 1875a57b1fccdfa65b78481f5e651833d979e545de04Matthew Wilcox do_scan_async(data); 1876267a6ad4aefaafbde607804c60945bcf97f91c1bHuajun Li /* scsi_autopm_put_host(shost) is called in scsi_finish_async_scan() */ 18771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 18781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsEXPORT_SYMBOL(scsi_scan_host); 18791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 18801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid scsi_forget_host(struct Scsi_Host *shost) 18811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1882a64358db1253b35d508a411e80a3ad23b859ec88Alan Stern struct scsi_device *sdev; 18831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long flags; 18841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1885a64358db1253b35d508a411e80a3ad23b859ec88Alan Stern restart: 18861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_lock_irqsave(shost->host_lock, flags); 1887a64358db1253b35d508a411e80a3ad23b859ec88Alan Stern list_for_each_entry(sdev, &shost->__devices, siblings) { 1888a64358db1253b35d508a411e80a3ad23b859ec88Alan Stern if (sdev->sdev_state == SDEV_DEL) 1889a64358db1253b35d508a411e80a3ad23b859ec88Alan Stern continue; 18901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_unlock_irqrestore(shost->host_lock, flags); 1891a64358db1253b35d508a411e80a3ad23b859ec88Alan Stern __scsi_remove_device(sdev); 1892a64358db1253b35d508a411e80a3ad23b859ec88Alan Stern goto restart; 18931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 18941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_unlock_irqrestore(shost->host_lock, flags); 18951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 18961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 18979f6aa5750de30b1ba35f6cb8de50c17b4fb59cabRandy Dunlap/** 18989f6aa5750de30b1ba35f6cb8de50c17b4fb59cabRandy Dunlap * scsi_get_host_dev - Create a scsi_device that points to the host adapter itself 18999f6aa5750de30b1ba35f6cb8de50c17b4fb59cabRandy Dunlap * @shost: Host that needs a scsi_device 19001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 19011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Lock status: None assumed. 19021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 1903f64a181d898e0518d5ae90c4870069510de977e1Christoph Hellwig * Returns: The scsi_device or NULL 19041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 19051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Notes: 1906f64a181d898e0518d5ae90c4870069510de977e1Christoph Hellwig * Attach a single scsi_device to the Scsi_Host - this should 19071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * be made to look like a "pseudo-device" that points to the 19081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * HA itself. 19091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 19101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Note - this device is not accessible from any high-level 19111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * drivers (including generics), which is probably not 19129f6aa5750de30b1ba35f6cb8de50c17b4fb59cabRandy Dunlap * optimal. We can add hooks later to attach. 19131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 19141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstruct scsi_device *scsi_get_host_dev(struct Scsi_Host *shost) 19151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1916e517d3133f62c27b211f305a6dbd6f6ccac0db1bAlan Stern struct scsi_device *sdev = NULL; 19171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct scsi_target *starget; 19181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 19190b9506723826c68b50fa33e345700ddcac1bed36Arjan van de Ven mutex_lock(&shost->scan_mutex); 1920e517d3133f62c27b211f305a6dbd6f6ccac0db1bAlan Stern if (!scsi_host_scan_allowed(shost)) 1921e517d3133f62c27b211f305a6dbd6f6ccac0db1bAlan Stern goto out; 19221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds starget = scsi_alloc_target(&shost->shost_gendev, 0, shost->this_id); 19231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!starget) 1924e517d3133f62c27b211f305a6dbd6f6ccac0db1bAlan Stern goto out; 19251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 19261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sdev = scsi_alloc_sdev(starget, 0, NULL); 1927d5469119f0098881ab7f991990ef4f81ef13a194Alan Stern if (sdev) 19281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sdev->borken = 0; 1929d5469119f0098881ab7f991990ef4f81ef13a194Alan Stern else 1930884d25cc4fda20908fd4ef93dbb41d817984b68bJames Bottomley scsi_target_reap(starget); 19311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds put_device(&starget->dev); 1932e517d3133f62c27b211f305a6dbd6f6ccac0db1bAlan Stern out: 19330b9506723826c68b50fa33e345700ddcac1bed36Arjan van de Ven mutex_unlock(&shost->scan_mutex); 19341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return sdev; 19351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 19361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsEXPORT_SYMBOL(scsi_get_host_dev); 19371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 19389f6aa5750de30b1ba35f6cb8de50c17b4fb59cabRandy Dunlap/** 19399f6aa5750de30b1ba35f6cb8de50c17b4fb59cabRandy Dunlap * scsi_free_host_dev - Free a scsi_device that points to the host adapter itself 19409f6aa5750de30b1ba35f6cb8de50c17b4fb59cabRandy Dunlap * @sdev: Host device to be freed 19411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 19421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Lock status: None assumed. 19431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 19441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Returns: Nothing 19451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 19461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid scsi_free_host_dev(struct scsi_device *sdev) 19471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 19481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds BUG_ON(sdev->id != sdev->host->this_id); 19491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1950860dc73608a091e0b325218acc2701709d5f221aJames Bottomley __scsi_remove_device(sdev); 19511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 19521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsEXPORT_SYMBOL(scsi_free_host_dev); 19531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1954