11da177e4SLinus Torvalds /* 21da177e4SLinus Torvalds * scsi_scan.c 31da177e4SLinus Torvalds * 41da177e4SLinus Torvalds * Copyright (C) 2000 Eric Youngdale, 51da177e4SLinus Torvalds * Copyright (C) 2002 Patrick Mansfield 61da177e4SLinus Torvalds * 71da177e4SLinus Torvalds * The general scanning/probing algorithm is as follows, exceptions are 81da177e4SLinus Torvalds * made to it depending on device specific flags, compilation options, and 91da177e4SLinus Torvalds * global variable (boot or module load time) settings. 101da177e4SLinus Torvalds * 111da177e4SLinus Torvalds * A specific LUN is scanned via an INQUIRY command; if the LUN has a 12f64a181dSChristoph Hellwig * device attached, a scsi_device is allocated and setup for it. 131da177e4SLinus Torvalds * 141da177e4SLinus Torvalds * For every id of every channel on the given host: 151da177e4SLinus Torvalds * 161da177e4SLinus Torvalds * Scan LUN 0; if the target responds to LUN 0 (even if there is no 171da177e4SLinus Torvalds * device or storage attached to LUN 0): 181da177e4SLinus Torvalds * 191da177e4SLinus Torvalds * If LUN 0 has a device attached, allocate and setup a 20f64a181dSChristoph Hellwig * scsi_device for it. 211da177e4SLinus Torvalds * 221da177e4SLinus Torvalds * If target is SCSI-3 or up, issue a REPORT LUN, and scan 231da177e4SLinus Torvalds * all of the LUNs returned by the REPORT LUN; else, 241da177e4SLinus Torvalds * sequentially scan LUNs up until some maximum is reached, 251da177e4SLinus Torvalds * or a LUN is seen that cannot have a device attached to it. 261da177e4SLinus Torvalds */ 271da177e4SLinus Torvalds 281da177e4SLinus Torvalds #include <linux/config.h> 291da177e4SLinus Torvalds #include <linux/module.h> 301da177e4SLinus Torvalds #include <linux/moduleparam.h> 311da177e4SLinus Torvalds #include <linux/init.h> 321da177e4SLinus Torvalds #include <linux/blkdev.h> 331da177e4SLinus Torvalds #include <asm/semaphore.h> 341da177e4SLinus Torvalds 351da177e4SLinus Torvalds #include <scsi/scsi.h> 36beb40487SChristoph Hellwig #include <scsi/scsi_cmnd.h> 371da177e4SLinus Torvalds #include <scsi/scsi_device.h> 381da177e4SLinus Torvalds #include <scsi/scsi_driver.h> 391da177e4SLinus Torvalds #include <scsi/scsi_devinfo.h> 401da177e4SLinus Torvalds #include <scsi/scsi_host.h> 411da177e4SLinus Torvalds #include <scsi/scsi_transport.h> 421da177e4SLinus Torvalds #include <scsi/scsi_eh.h> 431da177e4SLinus Torvalds 441da177e4SLinus Torvalds #include "scsi_priv.h" 451da177e4SLinus Torvalds #include "scsi_logging.h" 461da177e4SLinus Torvalds 471da177e4SLinus Torvalds #define ALLOC_FAILURE_MSG KERN_ERR "%s: Allocation failure during" \ 481da177e4SLinus Torvalds " SCSI scanning, some SCSI devices might not be configured\n" 491da177e4SLinus Torvalds 501da177e4SLinus Torvalds /* 511da177e4SLinus Torvalds * Default timeout 521da177e4SLinus Torvalds */ 531da177e4SLinus Torvalds #define SCSI_TIMEOUT (2*HZ) 541da177e4SLinus Torvalds 551da177e4SLinus Torvalds /* 561da177e4SLinus Torvalds * Prefix values for the SCSI id's (stored in driverfs name field) 571da177e4SLinus Torvalds */ 581da177e4SLinus Torvalds #define SCSI_UID_SER_NUM 'S' 591da177e4SLinus Torvalds #define SCSI_UID_UNKNOWN 'Z' 601da177e4SLinus Torvalds 611da177e4SLinus Torvalds /* 621da177e4SLinus Torvalds * Return values of some of the scanning functions. 631da177e4SLinus Torvalds * 641da177e4SLinus Torvalds * SCSI_SCAN_NO_RESPONSE: no valid response received from the target, this 651da177e4SLinus Torvalds * includes allocation or general failures preventing IO from being sent. 661da177e4SLinus Torvalds * 671da177e4SLinus Torvalds * SCSI_SCAN_TARGET_PRESENT: target responded, but no device is available 681da177e4SLinus Torvalds * on the given LUN. 691da177e4SLinus Torvalds * 701da177e4SLinus Torvalds * SCSI_SCAN_LUN_PRESENT: target responded, and a device is available on a 711da177e4SLinus Torvalds * given LUN. 721da177e4SLinus Torvalds */ 731da177e4SLinus Torvalds #define SCSI_SCAN_NO_RESPONSE 0 741da177e4SLinus Torvalds #define SCSI_SCAN_TARGET_PRESENT 1 751da177e4SLinus Torvalds #define SCSI_SCAN_LUN_PRESENT 2 761da177e4SLinus Torvalds 770ad78200SArjan van de Ven static const char *scsi_null_device_strs = "nullnullnullnull"; 781da177e4SLinus Torvalds 791da177e4SLinus Torvalds #define MAX_SCSI_LUNS 512 801da177e4SLinus Torvalds 811da177e4SLinus Torvalds #ifdef CONFIG_SCSI_MULTI_LUN 821da177e4SLinus Torvalds static unsigned int max_scsi_luns = MAX_SCSI_LUNS; 831da177e4SLinus Torvalds #else 841da177e4SLinus Torvalds static unsigned int max_scsi_luns = 1; 851da177e4SLinus Torvalds #endif 861da177e4SLinus Torvalds 871da177e4SLinus Torvalds module_param_named(max_luns, max_scsi_luns, int, S_IRUGO|S_IWUSR); 881da177e4SLinus Torvalds MODULE_PARM_DESC(max_luns, 891da177e4SLinus Torvalds "last scsi LUN (should be between 1 and 2^32-1)"); 901da177e4SLinus Torvalds 911da177e4SLinus Torvalds /* 921da177e4SLinus Torvalds * max_scsi_report_luns: the maximum number of LUNS that will be 931da177e4SLinus Torvalds * returned from the REPORT LUNS command. 8 times this value must 941da177e4SLinus Torvalds * be allocated. In theory this could be up to an 8 byte value, but 951da177e4SLinus Torvalds * in practice, the maximum number of LUNs suppored by any device 961da177e4SLinus Torvalds * is about 16k. 971da177e4SLinus Torvalds */ 981da177e4SLinus Torvalds static unsigned int max_scsi_report_luns = 511; 991da177e4SLinus Torvalds 1001da177e4SLinus Torvalds module_param_named(max_report_luns, max_scsi_report_luns, int, S_IRUGO|S_IWUSR); 1011da177e4SLinus Torvalds MODULE_PARM_DESC(max_report_luns, 1021da177e4SLinus Torvalds "REPORT LUNS maximum number of LUNS received (should be" 1031da177e4SLinus Torvalds " between 1 and 16384)"); 1041da177e4SLinus Torvalds 1051da177e4SLinus Torvalds static unsigned int scsi_inq_timeout = SCSI_TIMEOUT/HZ+3; 1061da177e4SLinus Torvalds 1071da177e4SLinus Torvalds module_param_named(inq_timeout, scsi_inq_timeout, int, S_IRUGO|S_IWUSR); 1081da177e4SLinus Torvalds MODULE_PARM_DESC(inq_timeout, 1091da177e4SLinus Torvalds "Timeout (in seconds) waiting for devices to answer INQUIRY." 1101da177e4SLinus Torvalds " Default is 5. Some non-compliant devices need more."); 1111da177e4SLinus Torvalds 1121da177e4SLinus Torvalds /** 1131da177e4SLinus Torvalds * scsi_unlock_floptical - unlock device via a special MODE SENSE command 11439216033SJames Bottomley * @sdev: scsi device to send command to 1151da177e4SLinus Torvalds * @result: area to store the result of the MODE SENSE 1161da177e4SLinus Torvalds * 1171da177e4SLinus Torvalds * Description: 11839216033SJames Bottomley * Send a vendor specific MODE SENSE (not a MODE SELECT) command. 1191da177e4SLinus Torvalds * Called for BLIST_KEY devices. 1201da177e4SLinus Torvalds **/ 12139216033SJames Bottomley static void scsi_unlock_floptical(struct scsi_device *sdev, 1221da177e4SLinus Torvalds unsigned char *result) 1231da177e4SLinus Torvalds { 1241da177e4SLinus Torvalds unsigned char scsi_cmd[MAX_COMMAND_SIZE]; 1251da177e4SLinus Torvalds 1261da177e4SLinus Torvalds printk(KERN_NOTICE "scsi: unlocking floptical drive\n"); 1271da177e4SLinus Torvalds scsi_cmd[0] = MODE_SENSE; 1281da177e4SLinus Torvalds scsi_cmd[1] = 0; 1291da177e4SLinus Torvalds scsi_cmd[2] = 0x2e; 1301da177e4SLinus Torvalds scsi_cmd[3] = 0; 1311da177e4SLinus Torvalds scsi_cmd[4] = 0x2a; /* size */ 1321da177e4SLinus Torvalds scsi_cmd[5] = 0; 13339216033SJames Bottomley scsi_execute_req(sdev, scsi_cmd, DMA_FROM_DEVICE, result, 0x2a, NULL, 13439216033SJames Bottomley SCSI_TIMEOUT, 3); 1351da177e4SLinus Torvalds } 1361da177e4SLinus Torvalds 1371da177e4SLinus Torvalds /** 1381da177e4SLinus Torvalds * print_inquiry - printk the inquiry information 1391da177e4SLinus Torvalds * @inq_result: printk this SCSI INQUIRY 1401da177e4SLinus Torvalds * 1411da177e4SLinus Torvalds * Description: 1421da177e4SLinus Torvalds * printk the vendor, model, and other information found in the 1431da177e4SLinus Torvalds * INQUIRY data in @inq_result. 1441da177e4SLinus Torvalds * 1451da177e4SLinus Torvalds * Notes: 1461da177e4SLinus Torvalds * Remove this, and replace with a hotplug event that logs any 1471da177e4SLinus Torvalds * relevant information. 1481da177e4SLinus Torvalds **/ 1491da177e4SLinus Torvalds static void print_inquiry(unsigned char *inq_result) 1501da177e4SLinus Torvalds { 1511da177e4SLinus Torvalds int i; 1521da177e4SLinus Torvalds 1531da177e4SLinus Torvalds printk(KERN_NOTICE " Vendor: "); 1541da177e4SLinus Torvalds for (i = 8; i < 16; i++) 1551da177e4SLinus Torvalds if (inq_result[i] >= 0x20 && i < inq_result[4] + 5) 1561da177e4SLinus Torvalds printk("%c", inq_result[i]); 1571da177e4SLinus Torvalds else 1581da177e4SLinus Torvalds printk(" "); 1591da177e4SLinus Torvalds 1601da177e4SLinus Torvalds printk(" Model: "); 1611da177e4SLinus Torvalds for (i = 16; i < 32; i++) 1621da177e4SLinus Torvalds if (inq_result[i] >= 0x20 && i < inq_result[4] + 5) 1631da177e4SLinus Torvalds printk("%c", inq_result[i]); 1641da177e4SLinus Torvalds else 1651da177e4SLinus Torvalds printk(" "); 1661da177e4SLinus Torvalds 1671da177e4SLinus Torvalds printk(" Rev: "); 1681da177e4SLinus Torvalds for (i = 32; i < 36; i++) 1691da177e4SLinus Torvalds if (inq_result[i] >= 0x20 && i < inq_result[4] + 5) 1701da177e4SLinus Torvalds printk("%c", inq_result[i]); 1711da177e4SLinus Torvalds else 1721da177e4SLinus Torvalds printk(" "); 1731da177e4SLinus Torvalds 1741da177e4SLinus Torvalds printk("\n"); 1751da177e4SLinus Torvalds 1761da177e4SLinus Torvalds i = inq_result[0] & 0x1f; 1771da177e4SLinus Torvalds 1781da177e4SLinus Torvalds printk(KERN_NOTICE " Type: %s ", 1791da177e4SLinus Torvalds i < 1801da177e4SLinus Torvalds MAX_SCSI_DEVICE_CODE ? scsi_device_types[i] : 1811da177e4SLinus Torvalds "Unknown "); 1821da177e4SLinus Torvalds printk(" ANSI SCSI revision: %02x", 1831da177e4SLinus Torvalds inq_result[2] & 0x07); 1841da177e4SLinus Torvalds if ((inq_result[2] & 0x07) == 1 && (inq_result[3] & 0x0f) == 1) 1851da177e4SLinus Torvalds printk(" CCS\n"); 1861da177e4SLinus Torvalds else 1871da177e4SLinus Torvalds printk("\n"); 1881da177e4SLinus Torvalds } 1891da177e4SLinus Torvalds 1901da177e4SLinus Torvalds /** 1911da177e4SLinus Torvalds * scsi_alloc_sdev - allocate and setup a scsi_Device 1921da177e4SLinus Torvalds * 1931da177e4SLinus Torvalds * Description: 1941da177e4SLinus Torvalds * Allocate, initialize for io, and return a pointer to a scsi_Device. 1951da177e4SLinus Torvalds * Stores the @shost, @channel, @id, and @lun in the scsi_Device, and 1961da177e4SLinus Torvalds * adds scsi_Device to the appropriate list. 1971da177e4SLinus Torvalds * 1981da177e4SLinus Torvalds * Return value: 1991da177e4SLinus Torvalds * scsi_Device pointer, or NULL on failure. 2001da177e4SLinus Torvalds **/ 2011da177e4SLinus Torvalds static struct scsi_device *scsi_alloc_sdev(struct scsi_target *starget, 2021da177e4SLinus Torvalds unsigned int lun, void *hostdata) 2031da177e4SLinus Torvalds { 2041da177e4SLinus Torvalds struct scsi_device *sdev; 2051da177e4SLinus Torvalds int display_failure_msg = 1, ret; 2061da177e4SLinus Torvalds struct Scsi_Host *shost = dev_to_shost(starget->dev.parent); 2071da177e4SLinus Torvalds 20824669f75SJes Sorensen sdev = kzalloc(sizeof(*sdev) + shost->transportt->device_size, 2091da177e4SLinus Torvalds GFP_ATOMIC); 2101da177e4SLinus Torvalds if (!sdev) 2111da177e4SLinus Torvalds goto out; 2121da177e4SLinus Torvalds 2131da177e4SLinus Torvalds sdev->vendor = scsi_null_device_strs; 2141da177e4SLinus Torvalds sdev->model = scsi_null_device_strs; 2151da177e4SLinus Torvalds sdev->rev = scsi_null_device_strs; 2161da177e4SLinus Torvalds sdev->host = shost; 2171da177e4SLinus Torvalds sdev->id = starget->id; 2181da177e4SLinus Torvalds sdev->lun = lun; 2191da177e4SLinus Torvalds sdev->channel = starget->channel; 2201da177e4SLinus Torvalds sdev->sdev_state = SDEV_CREATED; 2211da177e4SLinus Torvalds INIT_LIST_HEAD(&sdev->siblings); 2221da177e4SLinus Torvalds INIT_LIST_HEAD(&sdev->same_target_siblings); 2231da177e4SLinus Torvalds INIT_LIST_HEAD(&sdev->cmd_list); 2241da177e4SLinus Torvalds INIT_LIST_HEAD(&sdev->starved_entry); 2251da177e4SLinus Torvalds spin_lock_init(&sdev->list_lock); 2261da177e4SLinus Torvalds 2271da177e4SLinus Torvalds sdev->sdev_gendev.parent = get_device(&starget->dev); 2281da177e4SLinus Torvalds sdev->sdev_target = starget; 2291da177e4SLinus Torvalds 2301da177e4SLinus Torvalds /* usually NULL and set by ->slave_alloc instead */ 2311da177e4SLinus Torvalds sdev->hostdata = hostdata; 2321da177e4SLinus Torvalds 2331da177e4SLinus Torvalds /* if the device needs this changing, it may do so in the 2341da177e4SLinus Torvalds * slave_configure function */ 2351da177e4SLinus Torvalds sdev->max_device_blocked = SCSI_DEFAULT_DEVICE_BLOCKED; 2361da177e4SLinus Torvalds 2371da177e4SLinus Torvalds /* 2381da177e4SLinus Torvalds * Some low level driver could use device->type 2391da177e4SLinus Torvalds */ 2401da177e4SLinus Torvalds sdev->type = -1; 2411da177e4SLinus Torvalds 2421da177e4SLinus Torvalds /* 2431da177e4SLinus Torvalds * Assume that the device will have handshaking problems, 2441da177e4SLinus Torvalds * and then fix this field later if it turns out it 2451da177e4SLinus Torvalds * doesn't 2461da177e4SLinus Torvalds */ 2471da177e4SLinus Torvalds sdev->borken = 1; 2481da177e4SLinus Torvalds 2491da177e4SLinus Torvalds sdev->request_queue = scsi_alloc_queue(sdev); 2501da177e4SLinus Torvalds if (!sdev->request_queue) { 2511da177e4SLinus Torvalds /* release fn is set up in scsi_sysfs_device_initialise, so 2521da177e4SLinus Torvalds * have to free and put manually here */ 2531da177e4SLinus Torvalds put_device(&starget->dev); 25493f56089SDave Jones kfree(sdev); 2551da177e4SLinus Torvalds goto out; 2561da177e4SLinus Torvalds } 2571da177e4SLinus Torvalds 2581da177e4SLinus Torvalds sdev->request_queue->queuedata = sdev; 2591da177e4SLinus Torvalds scsi_adjust_queue_depth(sdev, 0, sdev->host->cmd_per_lun); 2601da177e4SLinus Torvalds 2611da177e4SLinus Torvalds scsi_sysfs_device_initialize(sdev); 2621da177e4SLinus Torvalds 2631da177e4SLinus Torvalds if (shost->hostt->slave_alloc) { 2641da177e4SLinus Torvalds ret = shost->hostt->slave_alloc(sdev); 2651da177e4SLinus Torvalds if (ret) { 2661da177e4SLinus Torvalds /* 2671da177e4SLinus Torvalds * if LLDD reports slave not present, don't clutter 2681da177e4SLinus Torvalds * console with alloc failure messages 2691da177e4SLinus Torvalds */ 2701da177e4SLinus Torvalds if (ret == -ENXIO) 2711da177e4SLinus Torvalds display_failure_msg = 0; 2721da177e4SLinus Torvalds goto out_device_destroy; 2731da177e4SLinus Torvalds } 2741da177e4SLinus Torvalds } 2751da177e4SLinus Torvalds 2761da177e4SLinus Torvalds return sdev; 2771da177e4SLinus Torvalds 2781da177e4SLinus Torvalds out_device_destroy: 2791da177e4SLinus Torvalds transport_destroy_device(&sdev->sdev_gendev); 2801da177e4SLinus Torvalds put_device(&sdev->sdev_gendev); 2811da177e4SLinus Torvalds out: 2821da177e4SLinus Torvalds if (display_failure_msg) 2831da177e4SLinus Torvalds printk(ALLOC_FAILURE_MSG, __FUNCTION__); 2841da177e4SLinus Torvalds return NULL; 2851da177e4SLinus Torvalds } 2861da177e4SLinus Torvalds 2871da177e4SLinus Torvalds static void scsi_target_dev_release(struct device *dev) 2881da177e4SLinus Torvalds { 2891da177e4SLinus Torvalds struct device *parent = dev->parent; 2901da177e4SLinus Torvalds struct scsi_target *starget = to_scsi_target(dev); 291a283bd37SJames Bottomley 2921da177e4SLinus Torvalds kfree(starget); 2931da177e4SLinus Torvalds put_device(parent); 2941da177e4SLinus Torvalds } 2951da177e4SLinus Torvalds 2961da177e4SLinus Torvalds int scsi_is_target_device(const struct device *dev) 2971da177e4SLinus Torvalds { 2981da177e4SLinus Torvalds return dev->release == scsi_target_dev_release; 2991da177e4SLinus Torvalds } 3001da177e4SLinus Torvalds EXPORT_SYMBOL(scsi_is_target_device); 3011da177e4SLinus Torvalds 3021da177e4SLinus Torvalds static struct scsi_target *__scsi_find_target(struct device *parent, 3031da177e4SLinus Torvalds int channel, uint id) 3041da177e4SLinus Torvalds { 3051da177e4SLinus Torvalds struct scsi_target *starget, *found_starget = NULL; 3061da177e4SLinus Torvalds struct Scsi_Host *shost = dev_to_shost(parent); 3071da177e4SLinus Torvalds /* 3081da177e4SLinus Torvalds * Search for an existing target for this sdev. 3091da177e4SLinus Torvalds */ 3101da177e4SLinus Torvalds list_for_each_entry(starget, &shost->__targets, siblings) { 3111da177e4SLinus Torvalds if (starget->id == id && 3121da177e4SLinus Torvalds starget->channel == channel) { 3131da177e4SLinus Torvalds found_starget = starget; 3141da177e4SLinus Torvalds break; 3151da177e4SLinus Torvalds } 3161da177e4SLinus Torvalds } 3171da177e4SLinus Torvalds if (found_starget) 3181da177e4SLinus Torvalds get_device(&found_starget->dev); 3191da177e4SLinus Torvalds 3201da177e4SLinus Torvalds return found_starget; 3211da177e4SLinus Torvalds } 3221da177e4SLinus Torvalds 3231da177e4SLinus Torvalds static struct scsi_target *scsi_alloc_target(struct device *parent, 3241da177e4SLinus Torvalds int channel, uint id) 3251da177e4SLinus Torvalds { 3261da177e4SLinus Torvalds struct Scsi_Host *shost = dev_to_shost(parent); 3271da177e4SLinus Torvalds struct device *dev = NULL; 3281da177e4SLinus Torvalds unsigned long flags; 3291da177e4SLinus Torvalds const int size = sizeof(struct scsi_target) 3301da177e4SLinus Torvalds + shost->transportt->target_size; 3315c44cd2aSJames.Smart@Emulex.Com struct scsi_target *starget; 3321da177e4SLinus Torvalds struct scsi_target *found_target; 33332f95792SBrian King int error; 3341da177e4SLinus Torvalds 33524669f75SJes Sorensen starget = kzalloc(size, GFP_KERNEL); 3361da177e4SLinus Torvalds if (!starget) { 3371da177e4SLinus Torvalds printk(KERN_ERR "%s: allocation failure\n", __FUNCTION__); 3381da177e4SLinus Torvalds return NULL; 3391da177e4SLinus Torvalds } 3401da177e4SLinus Torvalds dev = &starget->dev; 3411da177e4SLinus Torvalds device_initialize(dev); 3421da177e4SLinus Torvalds starget->reap_ref = 1; 3431da177e4SLinus Torvalds dev->parent = get_device(parent); 3441da177e4SLinus Torvalds dev->release = scsi_target_dev_release; 3451da177e4SLinus Torvalds sprintf(dev->bus_id, "target%d:%d:%d", 3461da177e4SLinus Torvalds shost->host_no, channel, id); 3471da177e4SLinus Torvalds starget->id = id; 3481da177e4SLinus Torvalds starget->channel = channel; 3491da177e4SLinus Torvalds INIT_LIST_HEAD(&starget->siblings); 3501da177e4SLinus Torvalds INIT_LIST_HEAD(&starget->devices); 351ffedb452SJames Bottomley starget->state = STARGET_RUNNING; 352ffedb452SJames Bottomley retry: 3531da177e4SLinus Torvalds spin_lock_irqsave(shost->host_lock, flags); 3541da177e4SLinus Torvalds 3551da177e4SLinus Torvalds found_target = __scsi_find_target(parent, channel, id); 3561da177e4SLinus Torvalds if (found_target) 3571da177e4SLinus Torvalds goto found; 3581da177e4SLinus Torvalds 3591da177e4SLinus Torvalds list_add_tail(&starget->siblings, &shost->__targets); 3601da177e4SLinus Torvalds spin_unlock_irqrestore(shost->host_lock, flags); 3611da177e4SLinus Torvalds /* allocate and add */ 362a283bd37SJames Bottomley transport_setup_device(dev); 36332f95792SBrian King error = device_add(dev); 36432f95792SBrian King if (error) { 36532f95792SBrian King dev_err(dev, "target device_add failed, error %d\n", error); 36632f95792SBrian King spin_lock_irqsave(shost->host_lock, flags); 36732f95792SBrian King list_del_init(&starget->siblings); 36832f95792SBrian King spin_unlock_irqrestore(shost->host_lock, flags); 36932f95792SBrian King transport_destroy_device(dev); 37032f95792SBrian King put_device(parent); 37132f95792SBrian King kfree(starget); 37232f95792SBrian King return NULL; 37332f95792SBrian King } 374a283bd37SJames Bottomley transport_add_device(dev); 375a283bd37SJames Bottomley if (shost->hostt->target_alloc) { 37632f95792SBrian King error = shost->hostt->target_alloc(starget); 377a283bd37SJames Bottomley 378a283bd37SJames Bottomley if(error) { 379a283bd37SJames Bottomley dev_printk(KERN_ERR, dev, "target allocation failed, error %d\n", error); 380a283bd37SJames Bottomley /* don't want scsi_target_reap to do the final 381a283bd37SJames Bottomley * put because it will be under the host lock */ 382a283bd37SJames Bottomley get_device(dev); 383a283bd37SJames Bottomley scsi_target_reap(starget); 384a283bd37SJames Bottomley put_device(dev); 385a283bd37SJames Bottomley return NULL; 386a283bd37SJames Bottomley } 387a283bd37SJames Bottomley } 388a283bd37SJames Bottomley 3891da177e4SLinus Torvalds return starget; 3901da177e4SLinus Torvalds 3911da177e4SLinus Torvalds found: 3921da177e4SLinus Torvalds found_target->reap_ref++; 3931da177e4SLinus Torvalds spin_unlock_irqrestore(shost->host_lock, flags); 3941da177e4SLinus Torvalds put_device(parent); 395ffedb452SJames Bottomley if (found_target->state != STARGET_DEL) { 3961da177e4SLinus Torvalds kfree(starget); 3971da177e4SLinus Torvalds return found_target; 3981da177e4SLinus Torvalds } 399ffedb452SJames Bottomley /* Unfortunately, we found a dying target; need to 400ffedb452SJames Bottomley * wait until it's dead before we can get a new one */ 401ffedb452SJames Bottomley put_device(&found_target->dev); 402ffedb452SJames Bottomley flush_scheduled_work(); 403ffedb452SJames Bottomley goto retry; 404ffedb452SJames Bottomley } 4051da177e4SLinus Torvalds 40665110b21SJames Bottomley static void scsi_target_reap_usercontext(void *data) 40765110b21SJames Bottomley { 40865110b21SJames Bottomley struct scsi_target *starget = data; 409863a930aSJames Bottomley struct Scsi_Host *shost = dev_to_shost(starget->dev.parent); 410863a930aSJames Bottomley unsigned long flags; 411863a930aSJames Bottomley 41204333393SJames Bottomley transport_remove_device(&starget->dev); 413863a930aSJames Bottomley device_del(&starget->dev); 41404333393SJames Bottomley transport_destroy_device(&starget->dev); 415ffedb452SJames Bottomley spin_lock_irqsave(shost->host_lock, flags); 416a50a5e37SMike Anderson if (shost->hostt->target_destroy) 417a50a5e37SMike Anderson shost->hostt->target_destroy(starget); 418ffedb452SJames Bottomley list_del_init(&starget->siblings); 419863a930aSJames Bottomley spin_unlock_irqrestore(shost->host_lock, flags); 420ffedb452SJames Bottomley put_device(&starget->dev); 421863a930aSJames Bottomley } 422863a930aSJames Bottomley 4231da177e4SLinus Torvalds /** 4241da177e4SLinus Torvalds * scsi_target_reap - check to see if target is in use and destroy if not 4251da177e4SLinus Torvalds * 4261da177e4SLinus Torvalds * @starget: target to be checked 4271da177e4SLinus Torvalds * 4281da177e4SLinus Torvalds * This is used after removing a LUN or doing a last put of the target 4291da177e4SLinus Torvalds * it checks atomically that nothing is using the target and removes 4301da177e4SLinus Torvalds * it if so. 4311da177e4SLinus Torvalds */ 4321da177e4SLinus Torvalds void scsi_target_reap(struct scsi_target *starget) 4331da177e4SLinus Torvalds { 434ffedb452SJames Bottomley struct Scsi_Host *shost = dev_to_shost(starget->dev.parent); 435ffedb452SJames Bottomley unsigned long flags; 436ffedb452SJames Bottomley 437ffedb452SJames Bottomley spin_lock_irqsave(shost->host_lock, flags); 438ffedb452SJames Bottomley 439ffedb452SJames Bottomley if (--starget->reap_ref == 0 && list_empty(&starget->devices)) { 440ffedb452SJames Bottomley BUG_ON(starget->state == STARGET_DEL); 441ffedb452SJames Bottomley starget->state = STARGET_DEL; 442ffedb452SJames Bottomley spin_unlock_irqrestore(shost->host_lock, flags); 443ffedb452SJames Bottomley execute_in_process_context(scsi_target_reap_usercontext, 444ffedb452SJames Bottomley starget, &starget->ew); 445ffedb452SJames Bottomley return; 446ffedb452SJames Bottomley 447ffedb452SJames Bottomley } 448ffedb452SJames Bottomley spin_unlock_irqrestore(shost->host_lock, flags); 449ffedb452SJames Bottomley 450ffedb452SJames Bottomley return; 4511da177e4SLinus Torvalds } 4521da177e4SLinus Torvalds 4531da177e4SLinus Torvalds /** 4541da177e4SLinus Torvalds * scsi_probe_lun - probe a single LUN using a SCSI INQUIRY 45539216033SJames Bottomley * @sdev: scsi_device to probe 4561da177e4SLinus Torvalds * @inq_result: area to store the INQUIRY result 45739216033SJames Bottomley * @result_len: len of inq_result 4581da177e4SLinus Torvalds * @bflags: store any bflags found here 4591da177e4SLinus Torvalds * 4601da177e4SLinus Torvalds * Description: 46139216033SJames Bottomley * Probe the lun associated with @req using a standard SCSI INQUIRY; 4621da177e4SLinus Torvalds * 46339216033SJames Bottomley * If the INQUIRY is successful, zero is returned and the 4641da177e4SLinus Torvalds * INQUIRY data is in @inq_result; the scsi_level and INQUIRY length 465f64a181dSChristoph Hellwig * are copied to the scsi_device any flags value is stored in *@bflags. 4661da177e4SLinus Torvalds **/ 46739216033SJames Bottomley static int scsi_probe_lun(struct scsi_device *sdev, char *inq_result, 46839216033SJames Bottomley int result_len, int *bflags) 4691da177e4SLinus Torvalds { 4701da177e4SLinus Torvalds unsigned char scsi_cmd[MAX_COMMAND_SIZE]; 4711da177e4SLinus Torvalds int first_inquiry_len, try_inquiry_len, next_inquiry_len; 4721da177e4SLinus Torvalds int response_len = 0; 47339216033SJames Bottomley int pass, count, result; 4741da177e4SLinus Torvalds struct scsi_sense_hdr sshdr; 4751da177e4SLinus Torvalds 4761da177e4SLinus Torvalds *bflags = 0; 4771da177e4SLinus Torvalds 4781da177e4SLinus Torvalds /* Perform up to 3 passes. The first pass uses a conservative 4791da177e4SLinus Torvalds * transfer length of 36 unless sdev->inquiry_len specifies a 4801da177e4SLinus Torvalds * different value. */ 4811da177e4SLinus Torvalds first_inquiry_len = sdev->inquiry_len ? sdev->inquiry_len : 36; 4821da177e4SLinus Torvalds try_inquiry_len = first_inquiry_len; 4831da177e4SLinus Torvalds pass = 1; 4841da177e4SLinus Torvalds 4851da177e4SLinus Torvalds next_pass: 4869ccfc756SJames Bottomley SCSI_LOG_SCAN_BUS(3, sdev_printk(KERN_INFO, sdev, 4879ccfc756SJames Bottomley "scsi scan: INQUIRY pass %d length %d\n", 4889ccfc756SJames Bottomley pass, try_inquiry_len)); 4891da177e4SLinus Torvalds 4901da177e4SLinus Torvalds /* Each pass gets up to three chances to ignore Unit Attention */ 4911da177e4SLinus Torvalds for (count = 0; count < 3; ++count) { 4921da177e4SLinus Torvalds memset(scsi_cmd, 0, 6); 4931da177e4SLinus Torvalds scsi_cmd[0] = INQUIRY; 4941da177e4SLinus Torvalds scsi_cmd[4] = (unsigned char) try_inquiry_len; 4951da177e4SLinus Torvalds 4961da177e4SLinus Torvalds memset(inq_result, 0, try_inquiry_len); 49739216033SJames Bottomley 49839216033SJames Bottomley result = scsi_execute_req(sdev, scsi_cmd, DMA_FROM_DEVICE, 499ea73a9f2SJames Bottomley inq_result, try_inquiry_len, &sshdr, 5001da177e4SLinus Torvalds HZ / 2 + HZ * scsi_inq_timeout, 3); 5011da177e4SLinus Torvalds 5021da177e4SLinus Torvalds SCSI_LOG_SCAN_BUS(3, printk(KERN_INFO "scsi scan: INQUIRY %s " 5031da177e4SLinus Torvalds "with code 0x%x\n", 50439216033SJames Bottomley result ? "failed" : "successful", result)); 5051da177e4SLinus Torvalds 50639216033SJames Bottomley if (result) { 5071da177e4SLinus Torvalds /* 5081da177e4SLinus Torvalds * not-ready to ready transition [asc/ascq=0x28/0x0] 5091da177e4SLinus Torvalds * or power-on, reset [asc/ascq=0x29/0x0], continue. 5101da177e4SLinus Torvalds * INQUIRY should not yield UNIT_ATTENTION 5111da177e4SLinus Torvalds * but many buggy devices do so anyway. 5121da177e4SLinus Torvalds */ 51339216033SJames Bottomley if ((driver_byte(result) & DRIVER_SENSE) && 514ea73a9f2SJames Bottomley scsi_sense_valid(&sshdr)) { 5151da177e4SLinus Torvalds if ((sshdr.sense_key == UNIT_ATTENTION) && 5161da177e4SLinus Torvalds ((sshdr.asc == 0x28) || 5171da177e4SLinus Torvalds (sshdr.asc == 0x29)) && 5181da177e4SLinus Torvalds (sshdr.ascq == 0)) 5191da177e4SLinus Torvalds continue; 5201da177e4SLinus Torvalds } 5211da177e4SLinus Torvalds } 5221da177e4SLinus Torvalds break; 5231da177e4SLinus Torvalds } 5241da177e4SLinus Torvalds 52539216033SJames Bottomley if (result == 0) { 5261da177e4SLinus Torvalds response_len = (unsigned char) inq_result[4] + 5; 5271da177e4SLinus Torvalds if (response_len > 255) 5281da177e4SLinus Torvalds response_len = first_inquiry_len; /* sanity */ 5291da177e4SLinus Torvalds 5301da177e4SLinus Torvalds /* 5311da177e4SLinus Torvalds * Get any flags for this device. 5321da177e4SLinus Torvalds * 533f64a181dSChristoph Hellwig * XXX add a bflags to scsi_device, and replace the 534f64a181dSChristoph Hellwig * corresponding bit fields in scsi_device, so bflags 5351da177e4SLinus Torvalds * need not be passed as an argument. 5361da177e4SLinus Torvalds */ 5371da177e4SLinus Torvalds *bflags = scsi_get_device_flags(sdev, &inq_result[8], 5381da177e4SLinus Torvalds &inq_result[16]); 5391da177e4SLinus Torvalds 5401da177e4SLinus Torvalds /* When the first pass succeeds we gain information about 5411da177e4SLinus Torvalds * what larger transfer lengths might work. */ 5421da177e4SLinus Torvalds if (pass == 1) { 5431da177e4SLinus Torvalds if (BLIST_INQUIRY_36 & *bflags) 5441da177e4SLinus Torvalds next_inquiry_len = 36; 5451da177e4SLinus Torvalds else if (BLIST_INQUIRY_58 & *bflags) 5461da177e4SLinus Torvalds next_inquiry_len = 58; 5471da177e4SLinus Torvalds else if (sdev->inquiry_len) 5481da177e4SLinus Torvalds next_inquiry_len = sdev->inquiry_len; 5491da177e4SLinus Torvalds else 5501da177e4SLinus Torvalds next_inquiry_len = response_len; 5511da177e4SLinus Torvalds 5521da177e4SLinus Torvalds /* If more data is available perform the second pass */ 5531da177e4SLinus Torvalds if (next_inquiry_len > try_inquiry_len) { 5541da177e4SLinus Torvalds try_inquiry_len = next_inquiry_len; 5551da177e4SLinus Torvalds pass = 2; 5561da177e4SLinus Torvalds goto next_pass; 5571da177e4SLinus Torvalds } 5581da177e4SLinus Torvalds } 5591da177e4SLinus Torvalds 5601da177e4SLinus Torvalds } else if (pass == 2) { 5611da177e4SLinus Torvalds printk(KERN_INFO "scsi scan: %d byte inquiry failed. " 5621da177e4SLinus Torvalds "Consider BLIST_INQUIRY_36 for this device\n", 5631da177e4SLinus Torvalds try_inquiry_len); 5641da177e4SLinus Torvalds 5651da177e4SLinus Torvalds /* If this pass failed, the third pass goes back and transfers 5661da177e4SLinus Torvalds * the same amount as we successfully got in the first pass. */ 5671da177e4SLinus Torvalds try_inquiry_len = first_inquiry_len; 5681da177e4SLinus Torvalds pass = 3; 5691da177e4SLinus Torvalds goto next_pass; 5701da177e4SLinus Torvalds } 5711da177e4SLinus Torvalds 5721da177e4SLinus Torvalds /* If the last transfer attempt got an error, assume the 5731da177e4SLinus Torvalds * peripheral doesn't exist or is dead. */ 57439216033SJames Bottomley if (result) 57539216033SJames Bottomley return -EIO; 5761da177e4SLinus Torvalds 5771da177e4SLinus Torvalds /* Don't report any more data than the device says is valid */ 5781da177e4SLinus Torvalds sdev->inquiry_len = min(try_inquiry_len, response_len); 5791da177e4SLinus Torvalds 5801da177e4SLinus Torvalds /* 5811da177e4SLinus Torvalds * XXX Abort if the response length is less than 36? If less than 5821da177e4SLinus Torvalds * 32, the lookup of the device flags (above) could be invalid, 5831da177e4SLinus Torvalds * and it would be possible to take an incorrect action - we do 5841da177e4SLinus Torvalds * not want to hang because of a short INQUIRY. On the flip side, 5851da177e4SLinus Torvalds * if the device is spun down or becoming ready (and so it gives a 5861da177e4SLinus Torvalds * short INQUIRY), an abort here prevents any further use of the 5871da177e4SLinus Torvalds * device, including spin up. 5881da177e4SLinus Torvalds * 5891da177e4SLinus Torvalds * Related to the above issue: 5901da177e4SLinus Torvalds * 5911da177e4SLinus Torvalds * XXX Devices (disk or all?) should be sent a TEST UNIT READY, 5921da177e4SLinus Torvalds * and if not ready, sent a START_STOP to start (maybe spin up) and 5931da177e4SLinus Torvalds * then send the INQUIRY again, since the INQUIRY can change after 5941da177e4SLinus Torvalds * a device is initialized. 5951da177e4SLinus Torvalds * 5961da177e4SLinus Torvalds * Ideally, start a device if explicitly asked to do so. This 5971da177e4SLinus Torvalds * assumes that a device is spun up on power on, spun down on 5981da177e4SLinus Torvalds * request, and then spun up on request. 5991da177e4SLinus Torvalds */ 6001da177e4SLinus Torvalds 6011da177e4SLinus Torvalds /* 6021da177e4SLinus Torvalds * The scanning code needs to know the scsi_level, even if no 6031da177e4SLinus Torvalds * device is attached at LUN 0 (SCSI_SCAN_TARGET_PRESENT) so 6041da177e4SLinus Torvalds * non-zero LUNs can be scanned. 6051da177e4SLinus Torvalds */ 6061da177e4SLinus Torvalds sdev->scsi_level = inq_result[2] & 0x07; 6071da177e4SLinus Torvalds if (sdev->scsi_level >= 2 || 6081da177e4SLinus Torvalds (sdev->scsi_level == 1 && (inq_result[3] & 0x0f) == 1)) 6091da177e4SLinus Torvalds sdev->scsi_level++; 6106f3a2024SJames Bottomley sdev->sdev_target->scsi_level = sdev->scsi_level; 6111da177e4SLinus Torvalds 61239216033SJames Bottomley return 0; 6131da177e4SLinus Torvalds } 6141da177e4SLinus Torvalds 6151da177e4SLinus Torvalds /** 616f64a181dSChristoph Hellwig * scsi_add_lun - allocate and fully initialze a scsi_device 617f64a181dSChristoph Hellwig * @sdevscan: holds information to be stored in the new scsi_device 618f64a181dSChristoph Hellwig * @sdevnew: store the address of the newly allocated scsi_device 6191da177e4SLinus Torvalds * @inq_result: holds the result of a previous INQUIRY to the LUN 6201da177e4SLinus Torvalds * @bflags: black/white list flag 6211da177e4SLinus Torvalds * 6221da177e4SLinus Torvalds * Description: 623f64a181dSChristoph Hellwig * Allocate and initialize a scsi_device matching sdevscan. Optionally 6241da177e4SLinus Torvalds * set fields based on values in *@bflags. If @sdevnew is not 625f64a181dSChristoph Hellwig * NULL, store the address of the new scsi_device in *@sdevnew (needed 6261da177e4SLinus Torvalds * when scanning a particular LUN). 6271da177e4SLinus Torvalds * 6281da177e4SLinus Torvalds * Return: 629f64a181dSChristoph Hellwig * SCSI_SCAN_NO_RESPONSE: could not allocate or setup a scsi_device 630f64a181dSChristoph Hellwig * SCSI_SCAN_LUN_PRESENT: a new scsi_device was allocated and initialized 6311da177e4SLinus Torvalds **/ 6321da177e4SLinus Torvalds static int scsi_add_lun(struct scsi_device *sdev, char *inq_result, int *bflags) 6331da177e4SLinus Torvalds { 6341da177e4SLinus Torvalds /* 6351da177e4SLinus Torvalds * XXX do not save the inquiry, since it can change underneath us, 6361da177e4SLinus Torvalds * save just vendor/model/rev. 6371da177e4SLinus Torvalds * 6381da177e4SLinus Torvalds * Rather than save it and have an ioctl that retrieves the saved 6391da177e4SLinus Torvalds * value, have an ioctl that executes the same INQUIRY code used 6401da177e4SLinus Torvalds * in scsi_probe_lun, let user level programs doing INQUIRY 6411da177e4SLinus Torvalds * scanning run at their own risk, or supply a user level program 6421da177e4SLinus Torvalds * that can correctly scan. 6431da177e4SLinus Torvalds */ 6441da177e4SLinus Torvalds sdev->inquiry = kmalloc(sdev->inquiry_len, GFP_ATOMIC); 6451da177e4SLinus Torvalds if (sdev->inquiry == NULL) { 6461da177e4SLinus Torvalds return SCSI_SCAN_NO_RESPONSE; 6471da177e4SLinus Torvalds } 6481da177e4SLinus Torvalds 6491da177e4SLinus Torvalds memcpy(sdev->inquiry, inq_result, sdev->inquiry_len); 6501da177e4SLinus Torvalds sdev->vendor = (char *) (sdev->inquiry + 8); 6511da177e4SLinus Torvalds sdev->model = (char *) (sdev->inquiry + 16); 6521da177e4SLinus Torvalds sdev->rev = (char *) (sdev->inquiry + 32); 6531da177e4SLinus Torvalds 6541da177e4SLinus Torvalds if (*bflags & BLIST_ISROM) { 6551da177e4SLinus Torvalds /* 6561da177e4SLinus Torvalds * It would be better to modify sdev->type, and set 6571da177e4SLinus Torvalds * sdev->removable, but then the print_inquiry() output 6581da177e4SLinus Torvalds * would not show TYPE_ROM; if print_inquiry() is removed 6591da177e4SLinus Torvalds * the issue goes away. 6601da177e4SLinus Torvalds */ 6611da177e4SLinus Torvalds inq_result[0] = TYPE_ROM; 6621da177e4SLinus Torvalds inq_result[1] |= 0x80; /* removable */ 6631da177e4SLinus Torvalds } else if (*bflags & BLIST_NO_ULD_ATTACH) 6641da177e4SLinus Torvalds sdev->no_uld_attach = 1; 6651da177e4SLinus Torvalds 6661da177e4SLinus Torvalds switch (sdev->type = (inq_result[0] & 0x1f)) { 6671da177e4SLinus Torvalds case TYPE_TAPE: 6681da177e4SLinus Torvalds case TYPE_DISK: 6691da177e4SLinus Torvalds case TYPE_PRINTER: 6701da177e4SLinus Torvalds case TYPE_MOD: 6711da177e4SLinus Torvalds case TYPE_PROCESSOR: 6721da177e4SLinus Torvalds case TYPE_SCANNER: 6731da177e4SLinus Torvalds case TYPE_MEDIUM_CHANGER: 6741da177e4SLinus Torvalds case TYPE_ENCLOSURE: 6751da177e4SLinus Torvalds case TYPE_COMM: 6764d7db04aSJames Bottomley case TYPE_RAID: 677631e8a13SAl Viro case TYPE_RBC: 6781da177e4SLinus Torvalds sdev->writeable = 1; 6791da177e4SLinus Torvalds break; 6801da177e4SLinus Torvalds case TYPE_WORM: 6811da177e4SLinus Torvalds case TYPE_ROM: 6821da177e4SLinus Torvalds sdev->writeable = 0; 6831da177e4SLinus Torvalds break; 6841da177e4SLinus Torvalds default: 6851da177e4SLinus Torvalds printk(KERN_INFO "scsi: unknown device type %d\n", sdev->type); 6861da177e4SLinus Torvalds } 6871da177e4SLinus Torvalds 6881da177e4SLinus Torvalds print_inquiry(inq_result); 6891da177e4SLinus Torvalds 6901da177e4SLinus Torvalds /* 6911da177e4SLinus Torvalds * For a peripheral qualifier (PQ) value of 1 (001b), the SCSI 6921da177e4SLinus Torvalds * spec says: The device server is capable of supporting the 6931da177e4SLinus Torvalds * specified peripheral device type on this logical unit. However, 6941da177e4SLinus Torvalds * the physical device is not currently connected to this logical 6951da177e4SLinus Torvalds * unit. 6961da177e4SLinus Torvalds * 6971da177e4SLinus Torvalds * The above is vague, as it implies that we could treat 001 and 6981da177e4SLinus Torvalds * 011 the same. Stay compatible with previous code, and create a 699f64a181dSChristoph Hellwig * scsi_device for a PQ of 1 7001da177e4SLinus Torvalds * 7011da177e4SLinus Torvalds * Don't set the device offline here; rather let the upper 7021da177e4SLinus Torvalds * level drivers eval the PQ to decide whether they should 7031da177e4SLinus Torvalds * attach. So remove ((inq_result[0] >> 5) & 7) == 1 check. 7041da177e4SLinus Torvalds */ 7051da177e4SLinus Torvalds 7061da177e4SLinus Torvalds sdev->inq_periph_qual = (inq_result[0] >> 5) & 7; 7071da177e4SLinus Torvalds sdev->removable = (0x80 & inq_result[1]) >> 7; 7081da177e4SLinus Torvalds sdev->lockable = sdev->removable; 7091da177e4SLinus Torvalds sdev->soft_reset = (inq_result[7] & 1) && ((inq_result[3] & 7) == 2); 7101da177e4SLinus Torvalds 7111da177e4SLinus Torvalds if (sdev->scsi_level >= SCSI_3 || (sdev->inquiry_len > 56 && 7121da177e4SLinus Torvalds inq_result[56] & 0x04)) 7131da177e4SLinus Torvalds sdev->ppr = 1; 7141da177e4SLinus Torvalds if (inq_result[7] & 0x60) 7151da177e4SLinus Torvalds sdev->wdtr = 1; 7161da177e4SLinus Torvalds if (inq_result[7] & 0x10) 7171da177e4SLinus Torvalds sdev->sdtr = 1; 7181da177e4SLinus Torvalds 7191da177e4SLinus Torvalds /* 7205e3c34c1SGreg KH * End sysfs code. 7211da177e4SLinus Torvalds */ 7221da177e4SLinus Torvalds 7231da177e4SLinus Torvalds if ((sdev->scsi_level >= SCSI_2) && (inq_result[7] & 2) && 7241da177e4SLinus Torvalds !(*bflags & BLIST_NOTQ)) 7251da177e4SLinus Torvalds sdev->tagged_supported = 1; 7261da177e4SLinus Torvalds /* 7271da177e4SLinus Torvalds * Some devices (Texel CD ROM drives) have handshaking problems 7281da177e4SLinus Torvalds * when used with the Seagate controllers. borken is initialized 7291da177e4SLinus Torvalds * to 1, and then set it to 0 here. 7301da177e4SLinus Torvalds */ 7311da177e4SLinus Torvalds if ((*bflags & BLIST_BORKEN) == 0) 7321da177e4SLinus Torvalds sdev->borken = 0; 7331da177e4SLinus Torvalds 7341da177e4SLinus Torvalds /* 7351da177e4SLinus Torvalds * Apparently some really broken devices (contrary to the SCSI 7361da177e4SLinus Torvalds * standards) need to be selected without asserting ATN 7371da177e4SLinus Torvalds */ 7381da177e4SLinus Torvalds if (*bflags & BLIST_SELECT_NO_ATN) 7391da177e4SLinus Torvalds sdev->select_no_atn = 1; 7401da177e4SLinus Torvalds 7411da177e4SLinus Torvalds /* 7424d7db04aSJames Bottomley * Maximum 512 sector transfer length 7434d7db04aSJames Bottomley * broken RA4x00 Compaq Disk Array 7444d7db04aSJames Bottomley */ 7454d7db04aSJames Bottomley if (*bflags & BLIST_MAX_512) 7464d7db04aSJames Bottomley blk_queue_max_sectors(sdev->request_queue, 512); 7474d7db04aSJames Bottomley 7484d7db04aSJames Bottomley /* 7491da177e4SLinus Torvalds * Some devices may not want to have a start command automatically 7501da177e4SLinus Torvalds * issued when a device is added. 7511da177e4SLinus Torvalds */ 7521da177e4SLinus Torvalds if (*bflags & BLIST_NOSTARTONADD) 7531da177e4SLinus Torvalds sdev->no_start_on_add = 1; 7541da177e4SLinus Torvalds 7551da177e4SLinus Torvalds if (*bflags & BLIST_SINGLELUN) 7561da177e4SLinus Torvalds sdev->single_lun = 1; 7571da177e4SLinus Torvalds 7581da177e4SLinus Torvalds 7591da177e4SLinus Torvalds sdev->use_10_for_rw = 1; 7601da177e4SLinus Torvalds 7611da177e4SLinus Torvalds if (*bflags & BLIST_MS_SKIP_PAGE_08) 7621da177e4SLinus Torvalds sdev->skip_ms_page_8 = 1; 7631da177e4SLinus Torvalds 7641da177e4SLinus Torvalds if (*bflags & BLIST_MS_SKIP_PAGE_3F) 7651da177e4SLinus Torvalds sdev->skip_ms_page_3f = 1; 7661da177e4SLinus Torvalds 7671da177e4SLinus Torvalds if (*bflags & BLIST_USE_10_BYTE_MS) 7681da177e4SLinus Torvalds sdev->use_10_for_ms = 1; 7691da177e4SLinus Torvalds 7701da177e4SLinus Torvalds /* set the device running here so that slave configure 7711da177e4SLinus Torvalds * may do I/O */ 7721da177e4SLinus Torvalds scsi_device_set_state(sdev, SDEV_RUNNING); 7731da177e4SLinus Torvalds 7741da177e4SLinus Torvalds if (*bflags & BLIST_MS_192_BYTES_FOR_3F) 7751da177e4SLinus Torvalds sdev->use_192_bytes_for_3f = 1; 7761da177e4SLinus Torvalds 7771da177e4SLinus Torvalds if (*bflags & BLIST_NOT_LOCKABLE) 7781da177e4SLinus Torvalds sdev->lockable = 0; 7791da177e4SLinus Torvalds 7801da177e4SLinus Torvalds if (*bflags & BLIST_RETRY_HWERROR) 7811da177e4SLinus Torvalds sdev->retry_hwerror = 1; 7821da177e4SLinus Torvalds 7831da177e4SLinus Torvalds transport_configure_device(&sdev->sdev_gendev); 7841da177e4SLinus Torvalds 78593805091SChristoph Hellwig if (sdev->host->hostt->slave_configure) { 78693805091SChristoph Hellwig int ret = sdev->host->hostt->slave_configure(sdev); 78793805091SChristoph Hellwig if (ret) { 78893805091SChristoph Hellwig /* 78993805091SChristoph Hellwig * if LLDD reports slave not present, don't clutter 79093805091SChristoph Hellwig * console with alloc failure messages 79193805091SChristoph Hellwig */ 79293805091SChristoph Hellwig if (ret != -ENXIO) { 79393805091SChristoph Hellwig sdev_printk(KERN_ERR, sdev, 79493805091SChristoph Hellwig "failed to configure device\n"); 79593805091SChristoph Hellwig } 79693805091SChristoph Hellwig return SCSI_SCAN_NO_RESPONSE; 79793805091SChristoph Hellwig } 79893805091SChristoph Hellwig } 7991da177e4SLinus Torvalds 8001da177e4SLinus Torvalds /* 8011da177e4SLinus Torvalds * Ok, the device is now all set up, we can 8021da177e4SLinus Torvalds * register it and tell the rest of the kernel 8031da177e4SLinus Torvalds * about it. 8041da177e4SLinus Torvalds */ 805b24b1033SAlan Stern if (scsi_sysfs_add_sdev(sdev) != 0) 806b24b1033SAlan Stern return SCSI_SCAN_NO_RESPONSE; 8071da177e4SLinus Torvalds 8081da177e4SLinus Torvalds return SCSI_SCAN_LUN_PRESENT; 8091da177e4SLinus Torvalds } 8101da177e4SLinus Torvalds 8116f3a2024SJames Bottomley static inline void scsi_destroy_sdev(struct scsi_device *sdev) 8126f3a2024SJames Bottomley { 813*309bd271SBrian King scsi_device_set_state(sdev, SDEV_DEL); 8146f3a2024SJames Bottomley if (sdev->host->hostt->slave_destroy) 8156f3a2024SJames Bottomley sdev->host->hostt->slave_destroy(sdev); 8166f3a2024SJames Bottomley transport_destroy_device(&sdev->sdev_gendev); 8176f3a2024SJames Bottomley put_device(&sdev->sdev_gendev); 8186f3a2024SJames Bottomley } 8196f3a2024SJames Bottomley 820c5f2e640Sakpm@osdl.org #ifdef CONFIG_SCSI_LOGGING 8216c7154c9SKurt Garloff /** 8226c7154c9SKurt Garloff * scsi_inq_str - print INQUIRY data from min to max index, 8236c7154c9SKurt Garloff * strip trailing whitespace 8246c7154c9SKurt Garloff * @buf: Output buffer with at least end-first+1 bytes of space 8256c7154c9SKurt Garloff * @inq: Inquiry buffer (input) 8266c7154c9SKurt Garloff * @first: Offset of string into inq 8276c7154c9SKurt Garloff * @end: Index after last character in inq 8286c7154c9SKurt Garloff */ 8296c7154c9SKurt Garloff static unsigned char *scsi_inq_str(unsigned char *buf, unsigned char *inq, 8306c7154c9SKurt Garloff unsigned first, unsigned end) 8316c7154c9SKurt Garloff { 8326c7154c9SKurt Garloff unsigned term = 0, idx; 833c5f2e640Sakpm@osdl.org 834c5f2e640Sakpm@osdl.org for (idx = 0; idx + first < end && idx + first < inq[4] + 5; idx++) { 835c5f2e640Sakpm@osdl.org if (inq[idx+first] > ' ') { 8366c7154c9SKurt Garloff buf[idx] = inq[idx+first]; 8376c7154c9SKurt Garloff term = idx+1; 8386c7154c9SKurt Garloff } else { 8396c7154c9SKurt Garloff buf[idx] = ' '; 8406c7154c9SKurt Garloff } 8416c7154c9SKurt Garloff } 8426c7154c9SKurt Garloff buf[term] = 0; 8436c7154c9SKurt Garloff return buf; 8446c7154c9SKurt Garloff } 845c5f2e640Sakpm@osdl.org #endif 8466f3a2024SJames Bottomley 8471da177e4SLinus Torvalds /** 8481da177e4SLinus Torvalds * scsi_probe_and_add_lun - probe a LUN, if a LUN is found add it 8491da177e4SLinus Torvalds * @starget: pointer to target device structure 8501da177e4SLinus Torvalds * @lun: LUN of target device 851f64a181dSChristoph Hellwig * @sdevscan: probe the LUN corresponding to this scsi_device 852f64a181dSChristoph Hellwig * @sdevnew: store the value of any new scsi_device allocated 8531da177e4SLinus Torvalds * @bflagsp: store bflags here if not NULL 8541da177e4SLinus Torvalds * 8551da177e4SLinus Torvalds * Description: 8561da177e4SLinus Torvalds * Call scsi_probe_lun, if a LUN with an attached device is found, 8571da177e4SLinus Torvalds * allocate and set it up by calling scsi_add_lun. 8581da177e4SLinus Torvalds * 8591da177e4SLinus Torvalds * Return: 860f64a181dSChristoph Hellwig * SCSI_SCAN_NO_RESPONSE: could not allocate or setup a scsi_device 8611da177e4SLinus Torvalds * SCSI_SCAN_TARGET_PRESENT: target responded, but no device is 8621da177e4SLinus Torvalds * attached at the LUN 863f64a181dSChristoph Hellwig * SCSI_SCAN_LUN_PRESENT: a new scsi_device was allocated and initialized 8641da177e4SLinus Torvalds **/ 8651da177e4SLinus Torvalds static int scsi_probe_and_add_lun(struct scsi_target *starget, 8661da177e4SLinus Torvalds uint lun, int *bflagsp, 8671da177e4SLinus Torvalds struct scsi_device **sdevp, int rescan, 8681da177e4SLinus Torvalds void *hostdata) 8691da177e4SLinus Torvalds { 8701da177e4SLinus Torvalds struct scsi_device *sdev; 8711da177e4SLinus Torvalds unsigned char *result; 87239216033SJames Bottomley int bflags, res = SCSI_SCAN_NO_RESPONSE, result_len = 256; 8731da177e4SLinus Torvalds struct Scsi_Host *shost = dev_to_shost(starget->dev.parent); 8741da177e4SLinus Torvalds 8751da177e4SLinus Torvalds /* 8761da177e4SLinus Torvalds * The rescan flag is used as an optimization, the first scan of a 8771da177e4SLinus Torvalds * host adapter calls into here with rescan == 0. 8781da177e4SLinus Torvalds */ 8791da177e4SLinus Torvalds sdev = scsi_device_lookup_by_target(starget, lun); 8801da177e4SLinus Torvalds if (sdev) { 8816f3a2024SJames Bottomley if (rescan || sdev->sdev_state != SDEV_CREATED) { 8821da177e4SLinus Torvalds SCSI_LOG_SCAN_BUS(3, printk(KERN_INFO 8831da177e4SLinus Torvalds "scsi scan: device exists on %s\n", 8841da177e4SLinus Torvalds sdev->sdev_gendev.bus_id)); 8851da177e4SLinus Torvalds if (sdevp) 8861da177e4SLinus Torvalds *sdevp = sdev; 8871da177e4SLinus Torvalds else 8881da177e4SLinus Torvalds scsi_device_put(sdev); 8891da177e4SLinus Torvalds 8901da177e4SLinus Torvalds if (bflagsp) 8911da177e4SLinus Torvalds *bflagsp = scsi_get_device_flags(sdev, 8921da177e4SLinus Torvalds sdev->vendor, 8931da177e4SLinus Torvalds sdev->model); 8941da177e4SLinus Torvalds return SCSI_SCAN_LUN_PRESENT; 8951da177e4SLinus Torvalds } 8966f3a2024SJames Bottomley scsi_device_put(sdev); 8976f3a2024SJames Bottomley } else 8981da177e4SLinus Torvalds sdev = scsi_alloc_sdev(starget, lun, hostdata); 8991da177e4SLinus Torvalds if (!sdev) 9001da177e4SLinus Torvalds goto out; 90139216033SJames Bottomley 90239216033SJames Bottomley result = kmalloc(result_len, GFP_ATOMIC | 903bc86120aSAl Viro ((shost->unchecked_isa_dma) ? __GFP_DMA : 0)); 9041da177e4SLinus Torvalds if (!result) 90539216033SJames Bottomley goto out_free_sdev; 9061da177e4SLinus Torvalds 90739216033SJames Bottomley if (scsi_probe_lun(sdev, result, result_len, &bflags)) 9081da177e4SLinus Torvalds goto out_free_result; 9091da177e4SLinus Torvalds 9104186ab19SKurt Garloff if (bflagsp) 9114186ab19SKurt Garloff *bflagsp = bflags; 9121da177e4SLinus Torvalds /* 9131da177e4SLinus Torvalds * result contains valid SCSI INQUIRY data. 9141da177e4SLinus Torvalds */ 91513f7e5acSKurt Garloff if (((result[0] >> 5) == 3) && !(bflags & BLIST_ATTACH_PQ3)) { 9161da177e4SLinus Torvalds /* 9171da177e4SLinus Torvalds * For a Peripheral qualifier 3 (011b), the SCSI 9181da177e4SLinus Torvalds * spec says: The device server is not capable of 9191da177e4SLinus Torvalds * supporting a physical device on this logical 9201da177e4SLinus Torvalds * unit. 9211da177e4SLinus Torvalds * 9221da177e4SLinus Torvalds * For disks, this implies that there is no 9231da177e4SLinus Torvalds * logical disk configured at sdev->lun, but there 9241da177e4SLinus Torvalds * is a target id responding. 9251da177e4SLinus Torvalds */ 9266c7154c9SKurt Garloff SCSI_LOG_SCAN_BUS(2, sdev_printk(KERN_INFO, sdev, "scsi scan:" 9276c7154c9SKurt Garloff " peripheral qualifier of 3, device not" 9286c7154c9SKurt Garloff " added\n")) 9296c7154c9SKurt Garloff if (lun == 0) { 930c5f2e640Sakpm@osdl.org SCSI_LOG_SCAN_BUS(1, { 931c5f2e640Sakpm@osdl.org unsigned char vend[9]; 932c5f2e640Sakpm@osdl.org unsigned char mod[17]; 933c5f2e640Sakpm@osdl.org 934c5f2e640Sakpm@osdl.org sdev_printk(KERN_INFO, sdev, 9356c7154c9SKurt Garloff "scsi scan: consider passing scsi_mod." 9366c7154c9SKurt Garloff "dev_flags=%s:%s:0x240 or 0x800240\n", 9376c7154c9SKurt Garloff scsi_inq_str(vend, result, 8, 16), 938c5f2e640Sakpm@osdl.org scsi_inq_str(mod, result, 16, 32)); 939c5f2e640Sakpm@osdl.org }); 9406c7154c9SKurt Garloff } 9416c7154c9SKurt Garloff 9421da177e4SLinus Torvalds res = SCSI_SCAN_TARGET_PRESENT; 9431da177e4SLinus Torvalds goto out_free_result; 9441da177e4SLinus Torvalds } 9451da177e4SLinus Torvalds 9461bfc5d9dSAlan Stern /* 9471bfc5d9dSAlan Stern * Non-standard SCSI targets may set the PDT to 0x1f (unknown or 9481bfc5d9dSAlan Stern * no device type) instead of using the Peripheral Qualifier to 9491bfc5d9dSAlan Stern * indicate that no LUN is present. For example, USB UFI does this. 9501bfc5d9dSAlan Stern */ 9511bfc5d9dSAlan Stern if (starget->pdt_1f_for_no_lun && (result[0] & 0x1f) == 0x1f) { 9521bfc5d9dSAlan Stern SCSI_LOG_SCAN_BUS(3, printk(KERN_INFO 9531bfc5d9dSAlan Stern "scsi scan: peripheral device type" 9541bfc5d9dSAlan Stern " of 31, no device added\n")); 9551bfc5d9dSAlan Stern res = SCSI_SCAN_TARGET_PRESENT; 9561bfc5d9dSAlan Stern goto out_free_result; 9571bfc5d9dSAlan Stern } 9581bfc5d9dSAlan Stern 9591da177e4SLinus Torvalds res = scsi_add_lun(sdev, result, &bflags); 9601da177e4SLinus Torvalds if (res == SCSI_SCAN_LUN_PRESENT) { 9611da177e4SLinus Torvalds if (bflags & BLIST_KEY) { 9621da177e4SLinus Torvalds sdev->lockable = 0; 96339216033SJames Bottomley scsi_unlock_floptical(sdev, result); 9641da177e4SLinus Torvalds } 9651da177e4SLinus Torvalds } 9661da177e4SLinus Torvalds 9671da177e4SLinus Torvalds out_free_result: 9681da177e4SLinus Torvalds kfree(result); 9691da177e4SLinus Torvalds out_free_sdev: 9701da177e4SLinus Torvalds if (res == SCSI_SCAN_LUN_PRESENT) { 9711da177e4SLinus Torvalds if (sdevp) { 972b70d37bfSAlan Stern if (scsi_device_get(sdev) == 0) { 9731da177e4SLinus Torvalds *sdevp = sdev; 974b70d37bfSAlan Stern } else { 975b70d37bfSAlan Stern __scsi_remove_device(sdev); 976b70d37bfSAlan Stern res = SCSI_SCAN_NO_RESPONSE; 977b70d37bfSAlan Stern } 9781da177e4SLinus Torvalds } 9796f3a2024SJames Bottomley } else 9806f3a2024SJames Bottomley scsi_destroy_sdev(sdev); 9811da177e4SLinus Torvalds out: 9821da177e4SLinus Torvalds return res; 9831da177e4SLinus Torvalds } 9841da177e4SLinus Torvalds 9851da177e4SLinus Torvalds /** 9861da177e4SLinus Torvalds * scsi_sequential_lun_scan - sequentially scan a SCSI target 9871da177e4SLinus Torvalds * @starget: pointer to target structure to scan 9881da177e4SLinus Torvalds * @bflags: black/white list flag for LUN 0 9891da177e4SLinus Torvalds * 9901da177e4SLinus Torvalds * Description: 9911da177e4SLinus Torvalds * Generally, scan from LUN 1 (LUN 0 is assumed to already have been 9921da177e4SLinus Torvalds * scanned) to some maximum lun until a LUN is found with no device 9931da177e4SLinus Torvalds * attached. Use the bflags to figure out any oddities. 9941da177e4SLinus Torvalds * 9951da177e4SLinus Torvalds * Modifies sdevscan->lun. 9961da177e4SLinus Torvalds **/ 9971da177e4SLinus Torvalds static void scsi_sequential_lun_scan(struct scsi_target *starget, 9984186ab19SKurt Garloff int bflags, int scsi_level, int rescan) 9991da177e4SLinus Torvalds { 10001da177e4SLinus Torvalds unsigned int sparse_lun, lun, max_dev_lun; 10011da177e4SLinus Torvalds struct Scsi_Host *shost = dev_to_shost(starget->dev.parent); 10021da177e4SLinus Torvalds 10031da177e4SLinus Torvalds SCSI_LOG_SCAN_BUS(3, printk(KERN_INFO "scsi scan: Sequential scan of" 10041da177e4SLinus Torvalds "%s\n", starget->dev.bus_id)); 10051da177e4SLinus Torvalds 10061da177e4SLinus Torvalds max_dev_lun = min(max_scsi_luns, shost->max_lun); 10071da177e4SLinus Torvalds /* 10081da177e4SLinus Torvalds * If this device is known to support sparse multiple units, 10091da177e4SLinus Torvalds * override the other settings, and scan all of them. Normally, 10101da177e4SLinus Torvalds * SCSI-3 devices should be scanned via the REPORT LUNS. 10111da177e4SLinus Torvalds */ 10121da177e4SLinus Torvalds if (bflags & BLIST_SPARSELUN) { 10131da177e4SLinus Torvalds max_dev_lun = shost->max_lun; 10141da177e4SLinus Torvalds sparse_lun = 1; 10151da177e4SLinus Torvalds } else 10161da177e4SLinus Torvalds sparse_lun = 0; 10171da177e4SLinus Torvalds 10181da177e4SLinus Torvalds /* 10191da177e4SLinus Torvalds * If less than SCSI_1_CSS, and no special lun scaning, stop 10201da177e4SLinus Torvalds * scanning; this matches 2.4 behaviour, but could just be a bug 10211da177e4SLinus Torvalds * (to continue scanning a SCSI_1_CSS device). 10221da177e4SLinus Torvalds * 10231da177e4SLinus Torvalds * This test is broken. We might not have any device on lun0 for 10241da177e4SLinus Torvalds * a sparselun device, and if that's the case then how would we 10251da177e4SLinus Torvalds * know the real scsi_level, eh? It might make sense to just not 10261da177e4SLinus Torvalds * scan any SCSI_1 device for non-0 luns, but that check would best 10271da177e4SLinus Torvalds * go into scsi_alloc_sdev() and just have it return null when asked 10281da177e4SLinus Torvalds * to alloc an sdev for lun > 0 on an already found SCSI_1 device. 10291da177e4SLinus Torvalds * 10301da177e4SLinus Torvalds if ((sdevscan->scsi_level < SCSI_1_CCS) && 10311da177e4SLinus Torvalds ((bflags & (BLIST_FORCELUN | BLIST_SPARSELUN | BLIST_MAX5LUN)) 10321da177e4SLinus Torvalds == 0)) 10331da177e4SLinus Torvalds return; 10341da177e4SLinus Torvalds */ 10351da177e4SLinus Torvalds /* 10361da177e4SLinus Torvalds * If this device is known to support multiple units, override 10371da177e4SLinus Torvalds * the other settings, and scan all of them. 10381da177e4SLinus Torvalds */ 10391da177e4SLinus Torvalds if (bflags & BLIST_FORCELUN) 10401da177e4SLinus Torvalds max_dev_lun = shost->max_lun; 10411da177e4SLinus Torvalds /* 10421da177e4SLinus Torvalds * REGAL CDC-4X: avoid hang after LUN 4 10431da177e4SLinus Torvalds */ 10441da177e4SLinus Torvalds if (bflags & BLIST_MAX5LUN) 10451da177e4SLinus Torvalds max_dev_lun = min(5U, max_dev_lun); 10461da177e4SLinus Torvalds /* 10471da177e4SLinus Torvalds * Do not scan SCSI-2 or lower device past LUN 7, unless 10481da177e4SLinus Torvalds * BLIST_LARGELUN. 10491da177e4SLinus Torvalds */ 10501da177e4SLinus Torvalds if (scsi_level < SCSI_3 && !(bflags & BLIST_LARGELUN)) 10511da177e4SLinus Torvalds max_dev_lun = min(8U, max_dev_lun); 10521da177e4SLinus Torvalds 10531da177e4SLinus Torvalds /* 10541da177e4SLinus Torvalds * We have already scanned LUN 0, so start at LUN 1. Keep scanning 10551da177e4SLinus Torvalds * until we reach the max, or no LUN is found and we are not 10561da177e4SLinus Torvalds * sparse_lun. 10571da177e4SLinus Torvalds */ 10581da177e4SLinus Torvalds for (lun = 1; lun < max_dev_lun; ++lun) 10591da177e4SLinus Torvalds if ((scsi_probe_and_add_lun(starget, lun, NULL, NULL, rescan, 10601da177e4SLinus Torvalds NULL) != SCSI_SCAN_LUN_PRESENT) && 10611da177e4SLinus Torvalds !sparse_lun) 10621da177e4SLinus Torvalds return; 10631da177e4SLinus Torvalds } 10641da177e4SLinus Torvalds 10651da177e4SLinus Torvalds /** 10661da177e4SLinus Torvalds * scsilun_to_int: convert a scsi_lun to an int 10671da177e4SLinus Torvalds * @scsilun: struct scsi_lun to be converted. 10681da177e4SLinus Torvalds * 10691da177e4SLinus Torvalds * Description: 10701da177e4SLinus Torvalds * Convert @scsilun from a struct scsi_lun to a four byte host byte-ordered 10711da177e4SLinus Torvalds * integer, and return the result. The caller must check for 10721da177e4SLinus Torvalds * truncation before using this function. 10731da177e4SLinus Torvalds * 10741da177e4SLinus Torvalds * Notes: 10751da177e4SLinus Torvalds * The struct scsi_lun is assumed to be four levels, with each level 10761da177e4SLinus Torvalds * effectively containing a SCSI byte-ordered (big endian) short; the 10771da177e4SLinus Torvalds * addressing bits of each level are ignored (the highest two bits). 10781da177e4SLinus Torvalds * For a description of the LUN format, post SCSI-3 see the SCSI 10791da177e4SLinus Torvalds * Architecture Model, for SCSI-3 see the SCSI Controller Commands. 10801da177e4SLinus Torvalds * 10811da177e4SLinus Torvalds * Given a struct scsi_lun of: 0a 04 0b 03 00 00 00 00, this function returns 10821da177e4SLinus Torvalds * the integer: 0x0b030a04 10831da177e4SLinus Torvalds **/ 10841da177e4SLinus Torvalds static int scsilun_to_int(struct scsi_lun *scsilun) 10851da177e4SLinus Torvalds { 10861da177e4SLinus Torvalds int i; 10871da177e4SLinus Torvalds unsigned int lun; 10881da177e4SLinus Torvalds 10891da177e4SLinus Torvalds lun = 0; 10901da177e4SLinus Torvalds for (i = 0; i < sizeof(lun); i += 2) 10911da177e4SLinus Torvalds lun = lun | (((scsilun->scsi_lun[i] << 8) | 10921da177e4SLinus Torvalds scsilun->scsi_lun[i + 1]) << (i * 8)); 10931da177e4SLinus Torvalds return lun; 10941da177e4SLinus Torvalds } 10951da177e4SLinus Torvalds 10961da177e4SLinus Torvalds /** 10972f4701d8SJames.Smart@Emulex.Com * int_to_scsilun: reverts an int into a scsi_lun 10982f4701d8SJames.Smart@Emulex.Com * @int: integer to be reverted 10992f4701d8SJames.Smart@Emulex.Com * @scsilun: struct scsi_lun to be set. 11002f4701d8SJames.Smart@Emulex.Com * 11012f4701d8SJames.Smart@Emulex.Com * Description: 11022f4701d8SJames.Smart@Emulex.Com * Reverts the functionality of the scsilun_to_int, which packed 11032f4701d8SJames.Smart@Emulex.Com * an 8-byte lun value into an int. This routine unpacks the int 11042f4701d8SJames.Smart@Emulex.Com * back into the lun value. 11052f4701d8SJames.Smart@Emulex.Com * Note: the scsilun_to_int() routine does not truly handle all 11062f4701d8SJames.Smart@Emulex.Com * 8bytes of the lun value. This functions restores only as much 11072f4701d8SJames.Smart@Emulex.Com * as was set by the routine. 11082f4701d8SJames.Smart@Emulex.Com * 11092f4701d8SJames.Smart@Emulex.Com * Notes: 11102f4701d8SJames.Smart@Emulex.Com * Given an integer : 0x0b030a04, this function returns a 11112f4701d8SJames.Smart@Emulex.Com * scsi_lun of : struct scsi_lun of: 0a 04 0b 03 00 00 00 00 11122f4701d8SJames.Smart@Emulex.Com * 11132f4701d8SJames.Smart@Emulex.Com **/ 11142f4701d8SJames.Smart@Emulex.Com void int_to_scsilun(unsigned int lun, struct scsi_lun *scsilun) 11152f4701d8SJames.Smart@Emulex.Com { 11162f4701d8SJames.Smart@Emulex.Com int i; 11172f4701d8SJames.Smart@Emulex.Com 11182f4701d8SJames.Smart@Emulex.Com memset(scsilun->scsi_lun, 0, sizeof(scsilun->scsi_lun)); 11192f4701d8SJames.Smart@Emulex.Com 11202f4701d8SJames.Smart@Emulex.Com for (i = 0; i < sizeof(lun); i += 2) { 11212f4701d8SJames.Smart@Emulex.Com scsilun->scsi_lun[i] = (lun >> 8) & 0xFF; 11222f4701d8SJames.Smart@Emulex.Com scsilun->scsi_lun[i+1] = lun & 0xFF; 11232f4701d8SJames.Smart@Emulex.Com lun = lun >> 16; 11242f4701d8SJames.Smart@Emulex.Com } 11252f4701d8SJames.Smart@Emulex.Com } 11262f4701d8SJames.Smart@Emulex.Com EXPORT_SYMBOL(int_to_scsilun); 11272f4701d8SJames.Smart@Emulex.Com 11282f4701d8SJames.Smart@Emulex.Com /** 11291da177e4SLinus Torvalds * scsi_report_lun_scan - Scan using SCSI REPORT LUN results 1130f64a181dSChristoph Hellwig * @sdevscan: scan the host, channel, and id of this scsi_device 11311da177e4SLinus Torvalds * 11321da177e4SLinus Torvalds * Description: 11331da177e4SLinus Torvalds * If @sdevscan is for a SCSI-3 or up device, send a REPORT LUN 11341da177e4SLinus Torvalds * command, and scan the resulting list of LUNs by calling 11351da177e4SLinus Torvalds * scsi_probe_and_add_lun. 11361da177e4SLinus Torvalds * 11371da177e4SLinus Torvalds * Modifies sdevscan->lun. 11381da177e4SLinus Torvalds * 11391da177e4SLinus Torvalds * Return: 11401da177e4SLinus Torvalds * 0: scan completed (or no memory, so further scanning is futile) 11411da177e4SLinus Torvalds * 1: no report lun scan, or not configured 11421da177e4SLinus Torvalds **/ 11436f3a2024SJames Bottomley static int scsi_report_lun_scan(struct scsi_target *starget, int bflags, 11441da177e4SLinus Torvalds int rescan) 11451da177e4SLinus Torvalds { 11461da177e4SLinus Torvalds char devname[64]; 11471da177e4SLinus Torvalds unsigned char scsi_cmd[MAX_COMMAND_SIZE]; 11481da177e4SLinus Torvalds unsigned int length; 11491da177e4SLinus Torvalds unsigned int lun; 11501da177e4SLinus Torvalds unsigned int num_luns; 11511da177e4SLinus Torvalds unsigned int retries; 115239216033SJames Bottomley int result; 11531da177e4SLinus Torvalds struct scsi_lun *lunp, *lun_data; 11541da177e4SLinus Torvalds u8 *data; 11551da177e4SLinus Torvalds struct scsi_sense_hdr sshdr; 11566f3a2024SJames Bottomley struct scsi_device *sdev; 11576f3a2024SJames Bottomley struct Scsi_Host *shost = dev_to_shost(&starget->dev); 11582ef89198SAlan Stern int ret = 0; 11591da177e4SLinus Torvalds 11601da177e4SLinus Torvalds /* 11611da177e4SLinus Torvalds * Only support SCSI-3 and up devices if BLIST_NOREPORTLUN is not set. 11621da177e4SLinus Torvalds * Also allow SCSI-2 if BLIST_REPORTLUN2 is set and host adapter does 11631da177e4SLinus Torvalds * support more than 8 LUNs. 11641da177e4SLinus Torvalds */ 11654d7db04aSJames Bottomley if (bflags & BLIST_NOREPORTLUN) 11664d7db04aSJames Bottomley return 1; 11674d7db04aSJames Bottomley if (starget->scsi_level < SCSI_2 && 11684d7db04aSJames Bottomley starget->scsi_level != SCSI_UNKNOWN) 11694d7db04aSJames Bottomley return 1; 11704d7db04aSJames Bottomley if (starget->scsi_level < SCSI_3 && 11714d7db04aSJames Bottomley (!(bflags & BLIST_REPORTLUN2) || shost->max_lun <= 8)) 11721da177e4SLinus Torvalds return 1; 11731da177e4SLinus Torvalds if (bflags & BLIST_NOLUN) 11741da177e4SLinus Torvalds return 0; 11751da177e4SLinus Torvalds 11766f3a2024SJames Bottomley if (!(sdev = scsi_device_lookup_by_target(starget, 0))) { 11776f3a2024SJames Bottomley sdev = scsi_alloc_sdev(starget, 0, NULL); 11786f3a2024SJames Bottomley if (!sdev) 11796f3a2024SJames Bottomley return 0; 11806f3a2024SJames Bottomley if (scsi_device_get(sdev)) 11816f3a2024SJames Bottomley return 0; 11826f3a2024SJames Bottomley } 11836f3a2024SJames Bottomley 11841da177e4SLinus Torvalds sprintf(devname, "host %d channel %d id %d", 11856f3a2024SJames Bottomley shost->host_no, sdev->channel, sdev->id); 11861da177e4SLinus Torvalds 11871da177e4SLinus Torvalds /* 11881da177e4SLinus Torvalds * Allocate enough to hold the header (the same size as one scsi_lun) 11891da177e4SLinus Torvalds * plus the max number of luns we are requesting. 11901da177e4SLinus Torvalds * 11911da177e4SLinus Torvalds * Reallocating and trying again (with the exact amount we need) 11921da177e4SLinus Torvalds * would be nice, but then we need to somehow limit the size 11931da177e4SLinus Torvalds * allocated based on the available memory and the limits of 11941da177e4SLinus Torvalds * kmalloc - we don't want a kmalloc() failure of a huge value to 11951da177e4SLinus Torvalds * prevent us from finding any LUNs on this target. 11961da177e4SLinus Torvalds */ 11971da177e4SLinus Torvalds length = (max_scsi_report_luns + 1) * sizeof(struct scsi_lun); 11981da177e4SLinus Torvalds lun_data = kmalloc(length, GFP_ATOMIC | 11991da177e4SLinus Torvalds (sdev->host->unchecked_isa_dma ? __GFP_DMA : 0)); 12006f3a2024SJames Bottomley if (!lun_data) { 12016f3a2024SJames Bottomley printk(ALLOC_FAILURE_MSG, __FUNCTION__); 120239216033SJames Bottomley goto out; 12036f3a2024SJames Bottomley } 12041da177e4SLinus Torvalds 12051da177e4SLinus Torvalds scsi_cmd[0] = REPORT_LUNS; 12061da177e4SLinus Torvalds 12071da177e4SLinus Torvalds /* 12081da177e4SLinus Torvalds * bytes 1 - 5: reserved, set to zero. 12091da177e4SLinus Torvalds */ 12101da177e4SLinus Torvalds memset(&scsi_cmd[1], 0, 5); 12111da177e4SLinus Torvalds 12121da177e4SLinus Torvalds /* 12131da177e4SLinus Torvalds * bytes 6 - 9: length of the command. 12141da177e4SLinus Torvalds */ 12151da177e4SLinus Torvalds scsi_cmd[6] = (unsigned char) (length >> 24) & 0xff; 12161da177e4SLinus Torvalds scsi_cmd[7] = (unsigned char) (length >> 16) & 0xff; 12171da177e4SLinus Torvalds scsi_cmd[8] = (unsigned char) (length >> 8) & 0xff; 12181da177e4SLinus Torvalds scsi_cmd[9] = (unsigned char) length & 0xff; 12191da177e4SLinus Torvalds 12201da177e4SLinus Torvalds scsi_cmd[10] = 0; /* reserved */ 12211da177e4SLinus Torvalds scsi_cmd[11] = 0; /* control */ 12221da177e4SLinus Torvalds 12231da177e4SLinus Torvalds /* 12241da177e4SLinus Torvalds * We can get a UNIT ATTENTION, for example a power on/reset, so 12251da177e4SLinus Torvalds * retry a few times (like sd.c does for TEST UNIT READY). 12261da177e4SLinus Torvalds * Experience shows some combinations of adapter/devices get at 12271da177e4SLinus Torvalds * least two power on/resets. 12281da177e4SLinus Torvalds * 12291da177e4SLinus Torvalds * Illegal requests (for devices that do not support REPORT LUNS) 12301da177e4SLinus Torvalds * should come through as a check condition, and will not generate 12311da177e4SLinus Torvalds * a retry. 12321da177e4SLinus Torvalds */ 12331da177e4SLinus Torvalds for (retries = 0; retries < 3; retries++) { 12341da177e4SLinus Torvalds SCSI_LOG_SCAN_BUS(3, printk (KERN_INFO "scsi scan: Sending" 12351da177e4SLinus Torvalds " REPORT LUNS to %s (try %d)\n", devname, 12361da177e4SLinus Torvalds retries)); 123739216033SJames Bottomley 123839216033SJames Bottomley result = scsi_execute_req(sdev, scsi_cmd, DMA_FROM_DEVICE, 1239ea73a9f2SJames Bottomley lun_data, length, &sshdr, 12401da177e4SLinus Torvalds SCSI_TIMEOUT + 4 * HZ, 3); 124139216033SJames Bottomley 12421da177e4SLinus Torvalds SCSI_LOG_SCAN_BUS(3, printk (KERN_INFO "scsi scan: REPORT LUNS" 124339216033SJames Bottomley " %s (try %d) result 0x%x\n", result 124439216033SJames Bottomley ? "failed" : "successful", retries, result)); 124539216033SJames Bottomley if (result == 0) 12461da177e4SLinus Torvalds break; 1247ea73a9f2SJames Bottomley else if (scsi_sense_valid(&sshdr)) { 12481da177e4SLinus Torvalds if (sshdr.sense_key != UNIT_ATTENTION) 12491da177e4SLinus Torvalds break; 12501da177e4SLinus Torvalds } 12511da177e4SLinus Torvalds } 12521da177e4SLinus Torvalds 125339216033SJames Bottomley if (result) { 12541da177e4SLinus Torvalds /* 12551da177e4SLinus Torvalds * The device probably does not support a REPORT LUN command 12561da177e4SLinus Torvalds */ 12572ef89198SAlan Stern ret = 1; 12582ef89198SAlan Stern goto out_err; 12591da177e4SLinus Torvalds } 12601da177e4SLinus Torvalds 12611da177e4SLinus Torvalds /* 12621da177e4SLinus Torvalds * Get the length from the first four bytes of lun_data. 12631da177e4SLinus Torvalds */ 12641da177e4SLinus Torvalds data = (u8 *) lun_data->scsi_lun; 12651da177e4SLinus Torvalds length = ((data[0] << 24) | (data[1] << 16) | 12661da177e4SLinus Torvalds (data[2] << 8) | (data[3] << 0)); 12671da177e4SLinus Torvalds 12681da177e4SLinus Torvalds num_luns = (length / sizeof(struct scsi_lun)); 12691da177e4SLinus Torvalds if (num_luns > max_scsi_report_luns) { 12701da177e4SLinus Torvalds printk(KERN_WARNING "scsi: On %s only %d (max_scsi_report_luns)" 12711da177e4SLinus Torvalds " of %d luns reported, try increasing" 12721da177e4SLinus Torvalds " max_scsi_report_luns.\n", devname, 12731da177e4SLinus Torvalds max_scsi_report_luns, num_luns); 12741da177e4SLinus Torvalds num_luns = max_scsi_report_luns; 12751da177e4SLinus Torvalds } 12761da177e4SLinus Torvalds 12773bf743e7SJeff Garzik SCSI_LOG_SCAN_BUS(3, sdev_printk (KERN_INFO, sdev, 12783bf743e7SJeff Garzik "scsi scan: REPORT LUN scan\n")); 12791da177e4SLinus Torvalds 12801da177e4SLinus Torvalds /* 12811da177e4SLinus Torvalds * Scan the luns in lun_data. The entry at offset 0 is really 12821da177e4SLinus Torvalds * the header, so start at 1 and go up to and including num_luns. 12831da177e4SLinus Torvalds */ 12841da177e4SLinus Torvalds for (lunp = &lun_data[1]; lunp <= &lun_data[num_luns]; lunp++) { 12851da177e4SLinus Torvalds lun = scsilun_to_int(lunp); 12861da177e4SLinus Torvalds 12871da177e4SLinus Torvalds /* 12881da177e4SLinus Torvalds * Check if the unused part of lunp is non-zero, and so 12891da177e4SLinus Torvalds * does not fit in lun. 12901da177e4SLinus Torvalds */ 12911da177e4SLinus Torvalds if (memcmp(&lunp->scsi_lun[sizeof(lun)], "\0\0\0\0", 4)) { 12921da177e4SLinus Torvalds int i; 12931da177e4SLinus Torvalds 12941da177e4SLinus Torvalds /* 12951da177e4SLinus Torvalds * Output an error displaying the LUN in byte order, 12961da177e4SLinus Torvalds * this differs from what linux would print for the 12971da177e4SLinus Torvalds * integer LUN value. 12981da177e4SLinus Torvalds */ 12991da177e4SLinus Torvalds printk(KERN_WARNING "scsi: %s lun 0x", devname); 13001da177e4SLinus Torvalds data = (char *)lunp->scsi_lun; 13011da177e4SLinus Torvalds for (i = 0; i < sizeof(struct scsi_lun); i++) 13021da177e4SLinus Torvalds printk("%02x", data[i]); 13031da177e4SLinus Torvalds printk(" has a LUN larger than currently supported.\n"); 13041da177e4SLinus Torvalds } else if (lun > sdev->host->max_lun) { 13051da177e4SLinus Torvalds printk(KERN_WARNING "scsi: %s lun%d has a LUN larger" 13061da177e4SLinus Torvalds " than allowed by the host adapter\n", 13071da177e4SLinus Torvalds devname, lun); 13081da177e4SLinus Torvalds } else { 13091da177e4SLinus Torvalds int res; 13101da177e4SLinus Torvalds 13111da177e4SLinus Torvalds res = scsi_probe_and_add_lun(starget, 13121da177e4SLinus Torvalds lun, NULL, NULL, rescan, NULL); 13131da177e4SLinus Torvalds if (res == SCSI_SCAN_NO_RESPONSE) { 13141da177e4SLinus Torvalds /* 13151da177e4SLinus Torvalds * Got some results, but now none, abort. 13161da177e4SLinus Torvalds */ 13173bf743e7SJeff Garzik sdev_printk(KERN_ERR, sdev, 13183bf743e7SJeff Garzik "Unexpected response" 13193bf743e7SJeff Garzik " from lun %d while scanning, scan" 13203bf743e7SJeff Garzik " aborted\n", lun); 13211da177e4SLinus Torvalds break; 13221da177e4SLinus Torvalds } 13231da177e4SLinus Torvalds } 13241da177e4SLinus Torvalds } 13251da177e4SLinus Torvalds 13262ef89198SAlan Stern out_err: 13271da177e4SLinus Torvalds kfree(lun_data); 13281da177e4SLinus Torvalds out: 13296f3a2024SJames Bottomley scsi_device_put(sdev); 13306f3a2024SJames Bottomley if (sdev->sdev_state == SDEV_CREATED) 13311da177e4SLinus Torvalds /* 13326f3a2024SJames Bottomley * the sdev we used didn't appear in the report luns scan 13331da177e4SLinus Torvalds */ 13346f3a2024SJames Bottomley scsi_destroy_sdev(sdev); 13352ef89198SAlan Stern return ret; 13361da177e4SLinus Torvalds } 13371da177e4SLinus Torvalds 13381da177e4SLinus Torvalds struct scsi_device *__scsi_add_device(struct Scsi_Host *shost, uint channel, 13391da177e4SLinus Torvalds uint id, uint lun, void *hostdata) 13401da177e4SLinus Torvalds { 1341a97a83a0SMatthew Wilcox struct scsi_device *sdev = ERR_PTR(-ENODEV); 13421da177e4SLinus Torvalds struct device *parent = &shost->shost_gendev; 1343e02f3f59SChristoph Hellwig struct scsi_target *starget; 13441da177e4SLinus Torvalds 1345e02f3f59SChristoph Hellwig starget = scsi_alloc_target(parent, channel, id); 13461da177e4SLinus Torvalds if (!starget) 13471da177e4SLinus Torvalds return ERR_PTR(-ENOMEM); 13481da177e4SLinus Torvalds 1349c92715b3SNathan Lynch get_device(&starget->dev); 13500b950672SArjan van de Ven mutex_lock(&shost->scan_mutex); 1351a97a83a0SMatthew Wilcox if (scsi_host_scan_allowed(shost)) 1352a97a83a0SMatthew Wilcox scsi_probe_and_add_lun(starget, lun, NULL, &sdev, 1, hostdata); 13530b950672SArjan van de Ven mutex_unlock(&shost->scan_mutex); 13541da177e4SLinus Torvalds scsi_target_reap(starget); 13551da177e4SLinus Torvalds put_device(&starget->dev); 13561da177e4SLinus Torvalds 13571da177e4SLinus Torvalds return sdev; 13581da177e4SLinus Torvalds } 13591da177e4SLinus Torvalds EXPORT_SYMBOL(__scsi_add_device); 13601da177e4SLinus Torvalds 1361146f7262SJames Bottomley int scsi_add_device(struct Scsi_Host *host, uint channel, 1362146f7262SJames Bottomley uint target, uint lun) 1363146f7262SJames Bottomley { 1364146f7262SJames Bottomley struct scsi_device *sdev = 1365146f7262SJames Bottomley __scsi_add_device(host, channel, target, lun, NULL); 1366146f7262SJames Bottomley if (IS_ERR(sdev)) 1367146f7262SJames Bottomley return PTR_ERR(sdev); 1368146f7262SJames Bottomley 1369146f7262SJames Bottomley scsi_device_put(sdev); 1370146f7262SJames Bottomley return 0; 1371146f7262SJames Bottomley } 1372146f7262SJames Bottomley EXPORT_SYMBOL(scsi_add_device); 1373146f7262SJames Bottomley 13741da177e4SLinus Torvalds void scsi_rescan_device(struct device *dev) 13751da177e4SLinus Torvalds { 13761da177e4SLinus Torvalds struct scsi_driver *drv; 13771da177e4SLinus Torvalds 13781da177e4SLinus Torvalds if (!dev->driver) 13791da177e4SLinus Torvalds return; 13801da177e4SLinus Torvalds 13811da177e4SLinus Torvalds drv = to_scsi_driver(dev->driver); 13821da177e4SLinus Torvalds if (try_module_get(drv->owner)) { 13831da177e4SLinus Torvalds if (drv->rescan) 13841da177e4SLinus Torvalds drv->rescan(dev); 13851da177e4SLinus Torvalds module_put(drv->owner); 13861da177e4SLinus Torvalds } 13871da177e4SLinus Torvalds } 13881da177e4SLinus Torvalds EXPORT_SYMBOL(scsi_rescan_device); 13891da177e4SLinus Torvalds 1390e517d313SAlan Stern static void __scsi_scan_target(struct device *parent, unsigned int channel, 13911da177e4SLinus Torvalds unsigned int id, unsigned int lun, int rescan) 13921da177e4SLinus Torvalds { 13931da177e4SLinus Torvalds struct Scsi_Host *shost = dev_to_shost(parent); 13941da177e4SLinus Torvalds int bflags = 0; 13951da177e4SLinus Torvalds int res; 13961da177e4SLinus Torvalds struct scsi_target *starget; 13971da177e4SLinus Torvalds 13981da177e4SLinus Torvalds if (shost->this_id == id) 13991da177e4SLinus Torvalds /* 14001da177e4SLinus Torvalds * Don't scan the host adapter 14011da177e4SLinus Torvalds */ 14021da177e4SLinus Torvalds return; 14031da177e4SLinus Torvalds 14041da177e4SLinus Torvalds starget = scsi_alloc_target(parent, channel, id); 14051da177e4SLinus Torvalds if (!starget) 14061da177e4SLinus Torvalds return; 14071da177e4SLinus Torvalds 14081da177e4SLinus Torvalds get_device(&starget->dev); 14091da177e4SLinus Torvalds if (lun != SCAN_WILD_CARD) { 14101da177e4SLinus Torvalds /* 14111da177e4SLinus Torvalds * Scan for a specific host/chan/id/lun. 14121da177e4SLinus Torvalds */ 14131da177e4SLinus Torvalds scsi_probe_and_add_lun(starget, lun, NULL, NULL, rescan, NULL); 14141da177e4SLinus Torvalds goto out_reap; 14151da177e4SLinus Torvalds } 14161da177e4SLinus Torvalds 14171da177e4SLinus Torvalds /* 14181da177e4SLinus Torvalds * Scan LUN 0, if there is some response, scan further. Ideally, we 14191da177e4SLinus Torvalds * would not configure LUN 0 until all LUNs are scanned. 14201da177e4SLinus Torvalds */ 14216f3a2024SJames Bottomley res = scsi_probe_and_add_lun(starget, 0, &bflags, NULL, rescan, NULL); 14226f3a2024SJames Bottomley if (res == SCSI_SCAN_LUN_PRESENT || res == SCSI_SCAN_TARGET_PRESENT) { 14236f3a2024SJames Bottomley if (scsi_report_lun_scan(starget, bflags, rescan) != 0) 14241da177e4SLinus Torvalds /* 14251da177e4SLinus Torvalds * The REPORT LUN did not scan the target, 14261da177e4SLinus Torvalds * do a sequential scan. 14271da177e4SLinus Torvalds */ 14281da177e4SLinus Torvalds scsi_sequential_lun_scan(starget, bflags, 14294186ab19SKurt Garloff starget->scsi_level, rescan); 14301da177e4SLinus Torvalds } 14311da177e4SLinus Torvalds 14321da177e4SLinus Torvalds out_reap: 14331da177e4SLinus Torvalds /* now determine if the target has any children at all 14341da177e4SLinus Torvalds * and if not, nuke it */ 14351da177e4SLinus Torvalds scsi_target_reap(starget); 14361da177e4SLinus Torvalds 14371da177e4SLinus Torvalds put_device(&starget->dev); 14381da177e4SLinus Torvalds } 1439e517d313SAlan Stern 1440e517d313SAlan Stern /** 1441e517d313SAlan Stern * scsi_scan_target - scan a target id, possibly including all LUNs on the 1442e517d313SAlan Stern * target. 1443e517d313SAlan Stern * @parent: host to scan 1444e517d313SAlan Stern * @channel: channel to scan 1445e517d313SAlan Stern * @id: target id to scan 1446e517d313SAlan Stern * @lun: Specific LUN to scan or SCAN_WILD_CARD 1447e517d313SAlan Stern * @rescan: passed to LUN scanning routines 1448e517d313SAlan Stern * 1449e517d313SAlan Stern * Description: 1450e517d313SAlan Stern * Scan the target id on @parent, @channel, and @id. Scan at least LUN 0, 1451e517d313SAlan Stern * and possibly all LUNs on the target id. 1452e517d313SAlan Stern * 1453e517d313SAlan Stern * First try a REPORT LUN scan, if that does not scan the target, do a 1454e517d313SAlan Stern * sequential scan of LUNs on the target id. 1455e517d313SAlan Stern **/ 1456e517d313SAlan Stern void scsi_scan_target(struct device *parent, unsigned int channel, 1457e517d313SAlan Stern unsigned int id, unsigned int lun, int rescan) 1458e517d313SAlan Stern { 1459e517d313SAlan Stern struct Scsi_Host *shost = dev_to_shost(parent); 1460e517d313SAlan Stern 14610b950672SArjan van de Ven mutex_lock(&shost->scan_mutex); 1462e517d313SAlan Stern if (scsi_host_scan_allowed(shost)) 1463e517d313SAlan Stern __scsi_scan_target(parent, channel, id, lun, rescan); 14640b950672SArjan van de Ven mutex_unlock(&shost->scan_mutex); 1465e517d313SAlan Stern } 14661da177e4SLinus Torvalds EXPORT_SYMBOL(scsi_scan_target); 14671da177e4SLinus Torvalds 14681da177e4SLinus Torvalds static void scsi_scan_channel(struct Scsi_Host *shost, unsigned int channel, 14691da177e4SLinus Torvalds unsigned int id, unsigned int lun, int rescan) 14701da177e4SLinus Torvalds { 14711da177e4SLinus Torvalds uint order_id; 14721da177e4SLinus Torvalds 14731da177e4SLinus Torvalds if (id == SCAN_WILD_CARD) 14741da177e4SLinus Torvalds for (id = 0; id < shost->max_id; ++id) { 14751da177e4SLinus Torvalds /* 14761da177e4SLinus Torvalds * XXX adapter drivers when possible (FCP, iSCSI) 14771da177e4SLinus Torvalds * could modify max_id to match the current max, 14781da177e4SLinus Torvalds * not the absolute max. 14791da177e4SLinus Torvalds * 14801da177e4SLinus Torvalds * XXX add a shost id iterator, so for example, 14811da177e4SLinus Torvalds * the FC ID can be the same as a target id 14821da177e4SLinus Torvalds * without a huge overhead of sparse id's. 14831da177e4SLinus Torvalds */ 14841da177e4SLinus Torvalds if (shost->reverse_ordering) 14851da177e4SLinus Torvalds /* 14861da177e4SLinus Torvalds * Scan from high to low id. 14871da177e4SLinus Torvalds */ 14881da177e4SLinus Torvalds order_id = shost->max_id - id - 1; 14891da177e4SLinus Torvalds else 14901da177e4SLinus Torvalds order_id = id; 1491e517d313SAlan Stern __scsi_scan_target(&shost->shost_gendev, channel, 1492e517d313SAlan Stern order_id, lun, rescan); 14931da177e4SLinus Torvalds } 14941da177e4SLinus Torvalds else 1495e517d313SAlan Stern __scsi_scan_target(&shost->shost_gendev, channel, 1496e517d313SAlan Stern id, lun, rescan); 14971da177e4SLinus Torvalds } 14981da177e4SLinus Torvalds 14991da177e4SLinus Torvalds int scsi_scan_host_selected(struct Scsi_Host *shost, unsigned int channel, 15001da177e4SLinus Torvalds unsigned int id, unsigned int lun, int rescan) 15011da177e4SLinus Torvalds { 15023bf743e7SJeff Garzik SCSI_LOG_SCAN_BUS(3, shost_printk (KERN_INFO, shost, 15033bf743e7SJeff Garzik "%s: <%u:%u:%u>\n", 15043bf743e7SJeff Garzik __FUNCTION__, channel, id, lun)); 15051da177e4SLinus Torvalds 15061da177e4SLinus Torvalds if (((channel != SCAN_WILD_CARD) && (channel > shost->max_channel)) || 1507091686d3SAmit Arora ((id != SCAN_WILD_CARD) && (id >= shost->max_id)) || 15081da177e4SLinus Torvalds ((lun != SCAN_WILD_CARD) && (lun > shost->max_lun))) 15091da177e4SLinus Torvalds return -EINVAL; 15101da177e4SLinus Torvalds 15110b950672SArjan van de Ven mutex_lock(&shost->scan_mutex); 151282f29467SMike Anderson if (scsi_host_scan_allowed(shost)) { 15131da177e4SLinus Torvalds if (channel == SCAN_WILD_CARD) 151482f29467SMike Anderson for (channel = 0; channel <= shost->max_channel; 151582f29467SMike Anderson channel++) 151682f29467SMike Anderson scsi_scan_channel(shost, channel, id, lun, 151782f29467SMike Anderson rescan); 15181da177e4SLinus Torvalds else 15191da177e4SLinus Torvalds scsi_scan_channel(shost, channel, id, lun, rescan); 152082f29467SMike Anderson } 15210b950672SArjan van de Ven mutex_unlock(&shost->scan_mutex); 15221da177e4SLinus Torvalds 15231da177e4SLinus Torvalds return 0; 15241da177e4SLinus Torvalds } 15251da177e4SLinus Torvalds 15261da177e4SLinus Torvalds /** 15271da177e4SLinus Torvalds * scsi_scan_host - scan the given adapter 15281da177e4SLinus Torvalds * @shost: adapter to scan 15291da177e4SLinus Torvalds **/ 15301da177e4SLinus Torvalds void scsi_scan_host(struct Scsi_Host *shost) 15311da177e4SLinus Torvalds { 15321da177e4SLinus Torvalds scsi_scan_host_selected(shost, SCAN_WILD_CARD, SCAN_WILD_CARD, 15331da177e4SLinus Torvalds SCAN_WILD_CARD, 0); 15341da177e4SLinus Torvalds } 15351da177e4SLinus Torvalds EXPORT_SYMBOL(scsi_scan_host); 15361da177e4SLinus Torvalds 15371da177e4SLinus Torvalds void scsi_forget_host(struct Scsi_Host *shost) 15381da177e4SLinus Torvalds { 1539a64358dbSAlan Stern struct scsi_device *sdev; 15401da177e4SLinus Torvalds unsigned long flags; 15411da177e4SLinus Torvalds 1542a64358dbSAlan Stern restart: 15431da177e4SLinus Torvalds spin_lock_irqsave(shost->host_lock, flags); 1544a64358dbSAlan Stern list_for_each_entry(sdev, &shost->__devices, siblings) { 1545a64358dbSAlan Stern if (sdev->sdev_state == SDEV_DEL) 1546a64358dbSAlan Stern continue; 15471da177e4SLinus Torvalds spin_unlock_irqrestore(shost->host_lock, flags); 1548a64358dbSAlan Stern __scsi_remove_device(sdev); 1549a64358dbSAlan Stern goto restart; 15501da177e4SLinus Torvalds } 15511da177e4SLinus Torvalds spin_unlock_irqrestore(shost->host_lock, flags); 15521da177e4SLinus Torvalds } 15531da177e4SLinus Torvalds 15541da177e4SLinus Torvalds /* 15551da177e4SLinus Torvalds * Function: scsi_get_host_dev() 15561da177e4SLinus Torvalds * 1557f64a181dSChristoph Hellwig * Purpose: Create a scsi_device that points to the host adapter itself. 15581da177e4SLinus Torvalds * 1559f64a181dSChristoph Hellwig * Arguments: SHpnt - Host that needs a scsi_device 15601da177e4SLinus Torvalds * 15611da177e4SLinus Torvalds * Lock status: None assumed. 15621da177e4SLinus Torvalds * 1563f64a181dSChristoph Hellwig * Returns: The scsi_device or NULL 15641da177e4SLinus Torvalds * 15651da177e4SLinus Torvalds * Notes: 1566f64a181dSChristoph Hellwig * Attach a single scsi_device to the Scsi_Host - this should 15671da177e4SLinus Torvalds * be made to look like a "pseudo-device" that points to the 15681da177e4SLinus Torvalds * HA itself. 15691da177e4SLinus Torvalds * 15701da177e4SLinus Torvalds * Note - this device is not accessible from any high-level 15711da177e4SLinus Torvalds * drivers (including generics), which is probably not 15721da177e4SLinus Torvalds * optimal. We can add hooks later to attach 15731da177e4SLinus Torvalds */ 15741da177e4SLinus Torvalds struct scsi_device *scsi_get_host_dev(struct Scsi_Host *shost) 15751da177e4SLinus Torvalds { 1576e517d313SAlan Stern struct scsi_device *sdev = NULL; 15771da177e4SLinus Torvalds struct scsi_target *starget; 15781da177e4SLinus Torvalds 15790b950672SArjan van de Ven mutex_lock(&shost->scan_mutex); 1580e517d313SAlan Stern if (!scsi_host_scan_allowed(shost)) 1581e517d313SAlan Stern goto out; 15821da177e4SLinus Torvalds starget = scsi_alloc_target(&shost->shost_gendev, 0, shost->this_id); 15831da177e4SLinus Torvalds if (!starget) 1584e517d313SAlan Stern goto out; 15851da177e4SLinus Torvalds 15861da177e4SLinus Torvalds sdev = scsi_alloc_sdev(starget, 0, NULL); 15871da177e4SLinus Torvalds if (sdev) { 15881da177e4SLinus Torvalds sdev->sdev_gendev.parent = get_device(&starget->dev); 15891da177e4SLinus Torvalds sdev->borken = 0; 15901da177e4SLinus Torvalds } 15911da177e4SLinus Torvalds put_device(&starget->dev); 1592e517d313SAlan Stern out: 15930b950672SArjan van de Ven mutex_unlock(&shost->scan_mutex); 15941da177e4SLinus Torvalds return sdev; 15951da177e4SLinus Torvalds } 15961da177e4SLinus Torvalds EXPORT_SYMBOL(scsi_get_host_dev); 15971da177e4SLinus Torvalds 15981da177e4SLinus Torvalds /* 15991da177e4SLinus Torvalds * Function: scsi_free_host_dev() 16001da177e4SLinus Torvalds * 16011da177e4SLinus Torvalds * Purpose: Free a scsi_device that points to the host adapter itself. 16021da177e4SLinus Torvalds * 1603f64a181dSChristoph Hellwig * Arguments: SHpnt - Host that needs a scsi_device 16041da177e4SLinus Torvalds * 16051da177e4SLinus Torvalds * Lock status: None assumed. 16061da177e4SLinus Torvalds * 16071da177e4SLinus Torvalds * Returns: Nothing 16081da177e4SLinus Torvalds * 16091da177e4SLinus Torvalds * Notes: 16101da177e4SLinus Torvalds */ 16111da177e4SLinus Torvalds void scsi_free_host_dev(struct scsi_device *sdev) 16121da177e4SLinus Torvalds { 16131da177e4SLinus Torvalds BUG_ON(sdev->id != sdev->host->this_id); 16141da177e4SLinus Torvalds 16156f3a2024SJames Bottomley scsi_destroy_sdev(sdev); 16161da177e4SLinus Torvalds } 16171da177e4SLinus Torvalds EXPORT_SYMBOL(scsi_free_host_dev); 16181da177e4SLinus Torvalds 1619