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> 361da177e4SLinus Torvalds #include <scsi/scsi_device.h> 371da177e4SLinus Torvalds #include <scsi/scsi_driver.h> 381da177e4SLinus Torvalds #include <scsi/scsi_devinfo.h> 391da177e4SLinus Torvalds #include <scsi/scsi_host.h> 401da177e4SLinus Torvalds #include <scsi/scsi_request.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); 2541da177e4SLinus Torvalds goto out; 2551da177e4SLinus Torvalds } 2561da177e4SLinus Torvalds 2571da177e4SLinus Torvalds sdev->request_queue->queuedata = sdev; 2581da177e4SLinus Torvalds scsi_adjust_queue_depth(sdev, 0, sdev->host->cmd_per_lun); 2591da177e4SLinus Torvalds 2601da177e4SLinus Torvalds scsi_sysfs_device_initialize(sdev); 2611da177e4SLinus Torvalds 2621da177e4SLinus Torvalds if (shost->hostt->slave_alloc) { 2631da177e4SLinus Torvalds ret = shost->hostt->slave_alloc(sdev); 2641da177e4SLinus Torvalds if (ret) { 2651da177e4SLinus Torvalds /* 2661da177e4SLinus Torvalds * if LLDD reports slave not present, don't clutter 2671da177e4SLinus Torvalds * console with alloc failure messages 2681da177e4SLinus Torvalds */ 2691da177e4SLinus Torvalds if (ret == -ENXIO) 2701da177e4SLinus Torvalds display_failure_msg = 0; 2711da177e4SLinus Torvalds goto out_device_destroy; 2721da177e4SLinus Torvalds } 2731da177e4SLinus Torvalds } 2741da177e4SLinus Torvalds 2751da177e4SLinus Torvalds return sdev; 2761da177e4SLinus Torvalds 2771da177e4SLinus Torvalds out_device_destroy: 2781da177e4SLinus Torvalds transport_destroy_device(&sdev->sdev_gendev); 2791da177e4SLinus Torvalds put_device(&sdev->sdev_gendev); 2801da177e4SLinus Torvalds out: 2811da177e4SLinus Torvalds if (display_failure_msg) 2821da177e4SLinus Torvalds printk(ALLOC_FAILURE_MSG, __FUNCTION__); 2831da177e4SLinus Torvalds return NULL; 2841da177e4SLinus Torvalds } 2851da177e4SLinus Torvalds 2861da177e4SLinus Torvalds static void scsi_target_dev_release(struct device *dev) 2871da177e4SLinus Torvalds { 2881da177e4SLinus Torvalds struct device *parent = dev->parent; 2891da177e4SLinus Torvalds struct scsi_target *starget = to_scsi_target(dev); 290a283bd37SJames Bottomley struct Scsi_Host *shost = dev_to_shost(parent); 291a283bd37SJames Bottomley 292a283bd37SJames Bottomley if (shost->hostt->target_destroy) 293a283bd37SJames Bottomley shost->hostt->target_destroy(starget); 2941da177e4SLinus Torvalds kfree(starget); 2951da177e4SLinus Torvalds put_device(parent); 2961da177e4SLinus Torvalds } 2971da177e4SLinus Torvalds 2981da177e4SLinus Torvalds int scsi_is_target_device(const struct device *dev) 2991da177e4SLinus Torvalds { 3001da177e4SLinus Torvalds return dev->release == scsi_target_dev_release; 3011da177e4SLinus Torvalds } 3021da177e4SLinus Torvalds EXPORT_SYMBOL(scsi_is_target_device); 3031da177e4SLinus Torvalds 3041da177e4SLinus Torvalds static struct scsi_target *__scsi_find_target(struct device *parent, 3051da177e4SLinus Torvalds int channel, uint id) 3061da177e4SLinus Torvalds { 3071da177e4SLinus Torvalds struct scsi_target *starget, *found_starget = NULL; 3081da177e4SLinus Torvalds struct Scsi_Host *shost = dev_to_shost(parent); 3091da177e4SLinus Torvalds /* 3101da177e4SLinus Torvalds * Search for an existing target for this sdev. 3111da177e4SLinus Torvalds */ 3121da177e4SLinus Torvalds list_for_each_entry(starget, &shost->__targets, siblings) { 3131da177e4SLinus Torvalds if (starget->id == id && 3141da177e4SLinus Torvalds starget->channel == channel) { 3151da177e4SLinus Torvalds found_starget = starget; 3161da177e4SLinus Torvalds break; 3171da177e4SLinus Torvalds } 3181da177e4SLinus Torvalds } 3191da177e4SLinus Torvalds if (found_starget) 3201da177e4SLinus Torvalds get_device(&found_starget->dev); 3211da177e4SLinus Torvalds 3221da177e4SLinus Torvalds return found_starget; 3231da177e4SLinus Torvalds } 3241da177e4SLinus Torvalds 3251da177e4SLinus Torvalds static struct scsi_target *scsi_alloc_target(struct device *parent, 3261da177e4SLinus Torvalds int channel, uint id) 3271da177e4SLinus Torvalds { 3281da177e4SLinus Torvalds struct Scsi_Host *shost = dev_to_shost(parent); 3291da177e4SLinus Torvalds struct device *dev = NULL; 3301da177e4SLinus Torvalds unsigned long flags; 3311da177e4SLinus Torvalds const int size = sizeof(struct scsi_target) 3321da177e4SLinus Torvalds + shost->transportt->target_size; 3335c44cd2aSJames.Smart@Emulex.Com struct scsi_target *starget; 3341da177e4SLinus Torvalds struct scsi_target *found_target; 3351da177e4SLinus Torvalds 33624669f75SJes Sorensen starget = kzalloc(size, GFP_KERNEL); 3371da177e4SLinus Torvalds if (!starget) { 3381da177e4SLinus Torvalds printk(KERN_ERR "%s: allocation failure\n", __FUNCTION__); 3391da177e4SLinus Torvalds return NULL; 3401da177e4SLinus Torvalds } 3411da177e4SLinus Torvalds dev = &starget->dev; 3421da177e4SLinus Torvalds device_initialize(dev); 3431da177e4SLinus Torvalds starget->reap_ref = 1; 3441da177e4SLinus Torvalds dev->parent = get_device(parent); 3451da177e4SLinus Torvalds dev->release = scsi_target_dev_release; 3461da177e4SLinus Torvalds sprintf(dev->bus_id, "target%d:%d:%d", 3471da177e4SLinus Torvalds shost->host_no, channel, id); 3481da177e4SLinus Torvalds starget->id = id; 3491da177e4SLinus Torvalds starget->channel = channel; 3501da177e4SLinus Torvalds INIT_LIST_HEAD(&starget->siblings); 3511da177e4SLinus Torvalds INIT_LIST_HEAD(&starget->devices); 3521da177e4SLinus Torvalds spin_lock_irqsave(shost->host_lock, flags); 3531da177e4SLinus Torvalds 3541da177e4SLinus Torvalds found_target = __scsi_find_target(parent, channel, id); 3551da177e4SLinus Torvalds if (found_target) 3561da177e4SLinus Torvalds goto found; 3571da177e4SLinus Torvalds 3581da177e4SLinus Torvalds list_add_tail(&starget->siblings, &shost->__targets); 3591da177e4SLinus Torvalds spin_unlock_irqrestore(shost->host_lock, flags); 3601da177e4SLinus Torvalds /* allocate and add */ 361a283bd37SJames Bottomley transport_setup_device(dev); 362a283bd37SJames Bottomley device_add(dev); 363a283bd37SJames Bottomley transport_add_device(dev); 364a283bd37SJames Bottomley if (shost->hostt->target_alloc) { 365a283bd37SJames Bottomley int error = shost->hostt->target_alloc(starget); 366a283bd37SJames Bottomley 367a283bd37SJames Bottomley if(error) { 368a283bd37SJames Bottomley dev_printk(KERN_ERR, dev, "target allocation failed, error %d\n", error); 369a283bd37SJames Bottomley /* don't want scsi_target_reap to do the final 370a283bd37SJames Bottomley * put because it will be under the host lock */ 371a283bd37SJames Bottomley get_device(dev); 372a283bd37SJames Bottomley scsi_target_reap(starget); 373a283bd37SJames Bottomley put_device(dev); 374a283bd37SJames Bottomley return NULL; 375a283bd37SJames Bottomley } 376a283bd37SJames Bottomley } 377a283bd37SJames Bottomley 3781da177e4SLinus Torvalds return starget; 3791da177e4SLinus Torvalds 3801da177e4SLinus Torvalds found: 3811da177e4SLinus Torvalds found_target->reap_ref++; 3821da177e4SLinus Torvalds spin_unlock_irqrestore(shost->host_lock, flags); 3831da177e4SLinus Torvalds put_device(parent); 3841da177e4SLinus Torvalds kfree(starget); 3851da177e4SLinus Torvalds return found_target; 3861da177e4SLinus Torvalds } 3871da177e4SLinus Torvalds 38865110b21SJames Bottomley static void scsi_target_reap_usercontext(void *data) 38965110b21SJames Bottomley { 39065110b21SJames Bottomley struct scsi_target *starget = data; 391863a930aSJames Bottomley struct Scsi_Host *shost = dev_to_shost(starget->dev.parent); 392863a930aSJames Bottomley unsigned long flags; 393863a930aSJames Bottomley 394863a930aSJames Bottomley spin_lock_irqsave(shost->host_lock, flags); 395863a930aSJames Bottomley 396863a930aSJames Bottomley if (--starget->reap_ref == 0 && list_empty(&starget->devices)) { 397863a930aSJames Bottomley list_del_init(&starget->siblings); 398863a930aSJames Bottomley spin_unlock_irqrestore(shost->host_lock, flags); 39904333393SJames Bottomley transport_remove_device(&starget->dev); 400863a930aSJames Bottomley device_del(&starget->dev); 40104333393SJames Bottomley transport_destroy_device(&starget->dev); 402863a930aSJames Bottomley put_device(&starget->dev); 403863a930aSJames Bottomley return; 404863a930aSJames Bottomley 405863a930aSJames Bottomley } 406863a930aSJames Bottomley spin_unlock_irqrestore(shost->host_lock, flags); 407863a930aSJames Bottomley 408863a930aSJames Bottomley return; 409863a930aSJames Bottomley } 410863a930aSJames Bottomley 4111da177e4SLinus Torvalds /** 4121da177e4SLinus Torvalds * scsi_target_reap - check to see if target is in use and destroy if not 4131da177e4SLinus Torvalds * 4141da177e4SLinus Torvalds * @starget: target to be checked 4151da177e4SLinus Torvalds * 4161da177e4SLinus Torvalds * This is used after removing a LUN or doing a last put of the target 4171da177e4SLinus Torvalds * it checks atomically that nothing is using the target and removes 4181da177e4SLinus Torvalds * it if so. 4191da177e4SLinus Torvalds */ 4201da177e4SLinus Torvalds void scsi_target_reap(struct scsi_target *starget) 4211da177e4SLinus Torvalds { 42265110b21SJames Bottomley scsi_execute_in_process_context(scsi_target_reap_usercontext, starget); 4231da177e4SLinus Torvalds } 4241da177e4SLinus Torvalds 4251da177e4SLinus Torvalds /** 4261da177e4SLinus Torvalds * scsi_probe_lun - probe a single LUN using a SCSI INQUIRY 42739216033SJames Bottomley * @sdev: scsi_device to probe 4281da177e4SLinus Torvalds * @inq_result: area to store the INQUIRY result 42939216033SJames Bottomley * @result_len: len of inq_result 4301da177e4SLinus Torvalds * @bflags: store any bflags found here 4311da177e4SLinus Torvalds * 4321da177e4SLinus Torvalds * Description: 43339216033SJames Bottomley * Probe the lun associated with @req using a standard SCSI INQUIRY; 4341da177e4SLinus Torvalds * 43539216033SJames Bottomley * If the INQUIRY is successful, zero is returned and the 4361da177e4SLinus Torvalds * INQUIRY data is in @inq_result; the scsi_level and INQUIRY length 437f64a181dSChristoph Hellwig * are copied to the scsi_device any flags value is stored in *@bflags. 4381da177e4SLinus Torvalds **/ 43939216033SJames Bottomley static int scsi_probe_lun(struct scsi_device *sdev, char *inq_result, 44039216033SJames Bottomley int result_len, int *bflags) 4411da177e4SLinus Torvalds { 4421da177e4SLinus Torvalds unsigned char scsi_cmd[MAX_COMMAND_SIZE]; 4431da177e4SLinus Torvalds int first_inquiry_len, try_inquiry_len, next_inquiry_len; 4441da177e4SLinus Torvalds int response_len = 0; 44539216033SJames Bottomley int pass, count, result; 4461da177e4SLinus Torvalds struct scsi_sense_hdr sshdr; 4471da177e4SLinus Torvalds 4481da177e4SLinus Torvalds *bflags = 0; 4491da177e4SLinus Torvalds 4501da177e4SLinus Torvalds /* Perform up to 3 passes. The first pass uses a conservative 4511da177e4SLinus Torvalds * transfer length of 36 unless sdev->inquiry_len specifies a 4521da177e4SLinus Torvalds * different value. */ 4531da177e4SLinus Torvalds first_inquiry_len = sdev->inquiry_len ? sdev->inquiry_len : 36; 4541da177e4SLinus Torvalds try_inquiry_len = first_inquiry_len; 4551da177e4SLinus Torvalds pass = 1; 4561da177e4SLinus Torvalds 4571da177e4SLinus Torvalds next_pass: 4589ccfc756SJames Bottomley SCSI_LOG_SCAN_BUS(3, sdev_printk(KERN_INFO, sdev, 4599ccfc756SJames Bottomley "scsi scan: INQUIRY pass %d length %d\n", 4609ccfc756SJames Bottomley pass, try_inquiry_len)); 4611da177e4SLinus Torvalds 4621da177e4SLinus Torvalds /* Each pass gets up to three chances to ignore Unit Attention */ 4631da177e4SLinus Torvalds for (count = 0; count < 3; ++count) { 4641da177e4SLinus Torvalds memset(scsi_cmd, 0, 6); 4651da177e4SLinus Torvalds scsi_cmd[0] = INQUIRY; 4661da177e4SLinus Torvalds scsi_cmd[4] = (unsigned char) try_inquiry_len; 4671da177e4SLinus Torvalds 4681da177e4SLinus Torvalds memset(inq_result, 0, try_inquiry_len); 46939216033SJames Bottomley 47039216033SJames Bottomley result = scsi_execute_req(sdev, scsi_cmd, DMA_FROM_DEVICE, 471ea73a9f2SJames Bottomley inq_result, try_inquiry_len, &sshdr, 4721da177e4SLinus Torvalds HZ / 2 + HZ * scsi_inq_timeout, 3); 4731da177e4SLinus Torvalds 4741da177e4SLinus Torvalds SCSI_LOG_SCAN_BUS(3, printk(KERN_INFO "scsi scan: INQUIRY %s " 4751da177e4SLinus Torvalds "with code 0x%x\n", 47639216033SJames Bottomley result ? "failed" : "successful", result)); 4771da177e4SLinus Torvalds 47839216033SJames Bottomley if (result) { 4791da177e4SLinus Torvalds /* 4801da177e4SLinus Torvalds * not-ready to ready transition [asc/ascq=0x28/0x0] 4811da177e4SLinus Torvalds * or power-on, reset [asc/ascq=0x29/0x0], continue. 4821da177e4SLinus Torvalds * INQUIRY should not yield UNIT_ATTENTION 4831da177e4SLinus Torvalds * but many buggy devices do so anyway. 4841da177e4SLinus Torvalds */ 48539216033SJames Bottomley if ((driver_byte(result) & DRIVER_SENSE) && 486ea73a9f2SJames Bottomley scsi_sense_valid(&sshdr)) { 4871da177e4SLinus Torvalds if ((sshdr.sense_key == UNIT_ATTENTION) && 4881da177e4SLinus Torvalds ((sshdr.asc == 0x28) || 4891da177e4SLinus Torvalds (sshdr.asc == 0x29)) && 4901da177e4SLinus Torvalds (sshdr.ascq == 0)) 4911da177e4SLinus Torvalds continue; 4921da177e4SLinus Torvalds } 4931da177e4SLinus Torvalds } 4941da177e4SLinus Torvalds break; 4951da177e4SLinus Torvalds } 4961da177e4SLinus Torvalds 49739216033SJames Bottomley if (result == 0) { 4981da177e4SLinus Torvalds response_len = (unsigned char) inq_result[4] + 5; 4991da177e4SLinus Torvalds if (response_len > 255) 5001da177e4SLinus Torvalds response_len = first_inquiry_len; /* sanity */ 5011da177e4SLinus Torvalds 5021da177e4SLinus Torvalds /* 5031da177e4SLinus Torvalds * Get any flags for this device. 5041da177e4SLinus Torvalds * 505f64a181dSChristoph Hellwig * XXX add a bflags to scsi_device, and replace the 506f64a181dSChristoph Hellwig * corresponding bit fields in scsi_device, so bflags 5071da177e4SLinus Torvalds * need not be passed as an argument. 5081da177e4SLinus Torvalds */ 5091da177e4SLinus Torvalds *bflags = scsi_get_device_flags(sdev, &inq_result[8], 5101da177e4SLinus Torvalds &inq_result[16]); 5111da177e4SLinus Torvalds 5121da177e4SLinus Torvalds /* When the first pass succeeds we gain information about 5131da177e4SLinus Torvalds * what larger transfer lengths might work. */ 5141da177e4SLinus Torvalds if (pass == 1) { 5151da177e4SLinus Torvalds if (BLIST_INQUIRY_36 & *bflags) 5161da177e4SLinus Torvalds next_inquiry_len = 36; 5171da177e4SLinus Torvalds else if (BLIST_INQUIRY_58 & *bflags) 5181da177e4SLinus Torvalds next_inquiry_len = 58; 5191da177e4SLinus Torvalds else if (sdev->inquiry_len) 5201da177e4SLinus Torvalds next_inquiry_len = sdev->inquiry_len; 5211da177e4SLinus Torvalds else 5221da177e4SLinus Torvalds next_inquiry_len = response_len; 5231da177e4SLinus Torvalds 5241da177e4SLinus Torvalds /* If more data is available perform the second pass */ 5251da177e4SLinus Torvalds if (next_inquiry_len > try_inquiry_len) { 5261da177e4SLinus Torvalds try_inquiry_len = next_inquiry_len; 5271da177e4SLinus Torvalds pass = 2; 5281da177e4SLinus Torvalds goto next_pass; 5291da177e4SLinus Torvalds } 5301da177e4SLinus Torvalds } 5311da177e4SLinus Torvalds 5321da177e4SLinus Torvalds } else if (pass == 2) { 5331da177e4SLinus Torvalds printk(KERN_INFO "scsi scan: %d byte inquiry failed. " 5341da177e4SLinus Torvalds "Consider BLIST_INQUIRY_36 for this device\n", 5351da177e4SLinus Torvalds try_inquiry_len); 5361da177e4SLinus Torvalds 5371da177e4SLinus Torvalds /* If this pass failed, the third pass goes back and transfers 5381da177e4SLinus Torvalds * the same amount as we successfully got in the first pass. */ 5391da177e4SLinus Torvalds try_inquiry_len = first_inquiry_len; 5401da177e4SLinus Torvalds pass = 3; 5411da177e4SLinus Torvalds goto next_pass; 5421da177e4SLinus Torvalds } 5431da177e4SLinus Torvalds 5441da177e4SLinus Torvalds /* If the last transfer attempt got an error, assume the 5451da177e4SLinus Torvalds * peripheral doesn't exist or is dead. */ 54639216033SJames Bottomley if (result) 54739216033SJames Bottomley return -EIO; 5481da177e4SLinus Torvalds 5491da177e4SLinus Torvalds /* Don't report any more data than the device says is valid */ 5501da177e4SLinus Torvalds sdev->inquiry_len = min(try_inquiry_len, response_len); 5511da177e4SLinus Torvalds 5521da177e4SLinus Torvalds /* 5531da177e4SLinus Torvalds * XXX Abort if the response length is less than 36? If less than 5541da177e4SLinus Torvalds * 32, the lookup of the device flags (above) could be invalid, 5551da177e4SLinus Torvalds * and it would be possible to take an incorrect action - we do 5561da177e4SLinus Torvalds * not want to hang because of a short INQUIRY. On the flip side, 5571da177e4SLinus Torvalds * if the device is spun down or becoming ready (and so it gives a 5581da177e4SLinus Torvalds * short INQUIRY), an abort here prevents any further use of the 5591da177e4SLinus Torvalds * device, including spin up. 5601da177e4SLinus Torvalds * 5611da177e4SLinus Torvalds * Related to the above issue: 5621da177e4SLinus Torvalds * 5631da177e4SLinus Torvalds * XXX Devices (disk or all?) should be sent a TEST UNIT READY, 5641da177e4SLinus Torvalds * and if not ready, sent a START_STOP to start (maybe spin up) and 5651da177e4SLinus Torvalds * then send the INQUIRY again, since the INQUIRY can change after 5661da177e4SLinus Torvalds * a device is initialized. 5671da177e4SLinus Torvalds * 5681da177e4SLinus Torvalds * Ideally, start a device if explicitly asked to do so. This 5691da177e4SLinus Torvalds * assumes that a device is spun up on power on, spun down on 5701da177e4SLinus Torvalds * request, and then spun up on request. 5711da177e4SLinus Torvalds */ 5721da177e4SLinus Torvalds 5731da177e4SLinus Torvalds /* 5741da177e4SLinus Torvalds * The scanning code needs to know the scsi_level, even if no 5751da177e4SLinus Torvalds * device is attached at LUN 0 (SCSI_SCAN_TARGET_PRESENT) so 5761da177e4SLinus Torvalds * non-zero LUNs can be scanned. 5771da177e4SLinus Torvalds */ 5781da177e4SLinus Torvalds sdev->scsi_level = inq_result[2] & 0x07; 5791da177e4SLinus Torvalds if (sdev->scsi_level >= 2 || 5801da177e4SLinus Torvalds (sdev->scsi_level == 1 && (inq_result[3] & 0x0f) == 1)) 5811da177e4SLinus Torvalds sdev->scsi_level++; 5826f3a2024SJames Bottomley sdev->sdev_target->scsi_level = sdev->scsi_level; 5831da177e4SLinus Torvalds 58439216033SJames Bottomley return 0; 5851da177e4SLinus Torvalds } 5861da177e4SLinus Torvalds 5871da177e4SLinus Torvalds /** 588f64a181dSChristoph Hellwig * scsi_add_lun - allocate and fully initialze a scsi_device 589f64a181dSChristoph Hellwig * @sdevscan: holds information to be stored in the new scsi_device 590f64a181dSChristoph Hellwig * @sdevnew: store the address of the newly allocated scsi_device 5911da177e4SLinus Torvalds * @inq_result: holds the result of a previous INQUIRY to the LUN 5921da177e4SLinus Torvalds * @bflags: black/white list flag 5931da177e4SLinus Torvalds * 5941da177e4SLinus Torvalds * Description: 595f64a181dSChristoph Hellwig * Allocate and initialize a scsi_device matching sdevscan. Optionally 5961da177e4SLinus Torvalds * set fields based on values in *@bflags. If @sdevnew is not 597f64a181dSChristoph Hellwig * NULL, store the address of the new scsi_device in *@sdevnew (needed 5981da177e4SLinus Torvalds * when scanning a particular LUN). 5991da177e4SLinus Torvalds * 6001da177e4SLinus Torvalds * Return: 601f64a181dSChristoph Hellwig * SCSI_SCAN_NO_RESPONSE: could not allocate or setup a scsi_device 602f64a181dSChristoph Hellwig * SCSI_SCAN_LUN_PRESENT: a new scsi_device was allocated and initialized 6031da177e4SLinus Torvalds **/ 6041da177e4SLinus Torvalds static int scsi_add_lun(struct scsi_device *sdev, char *inq_result, int *bflags) 6051da177e4SLinus Torvalds { 6061da177e4SLinus Torvalds /* 6071da177e4SLinus Torvalds * XXX do not save the inquiry, since it can change underneath us, 6081da177e4SLinus Torvalds * save just vendor/model/rev. 6091da177e4SLinus Torvalds * 6101da177e4SLinus Torvalds * Rather than save it and have an ioctl that retrieves the saved 6111da177e4SLinus Torvalds * value, have an ioctl that executes the same INQUIRY code used 6121da177e4SLinus Torvalds * in scsi_probe_lun, let user level programs doing INQUIRY 6131da177e4SLinus Torvalds * scanning run at their own risk, or supply a user level program 6141da177e4SLinus Torvalds * that can correctly scan. 6151da177e4SLinus Torvalds */ 6161da177e4SLinus Torvalds sdev->inquiry = kmalloc(sdev->inquiry_len, GFP_ATOMIC); 6171da177e4SLinus Torvalds if (sdev->inquiry == NULL) { 6181da177e4SLinus Torvalds return SCSI_SCAN_NO_RESPONSE; 6191da177e4SLinus Torvalds } 6201da177e4SLinus Torvalds 6211da177e4SLinus Torvalds memcpy(sdev->inquiry, inq_result, sdev->inquiry_len); 6221da177e4SLinus Torvalds sdev->vendor = (char *) (sdev->inquiry + 8); 6231da177e4SLinus Torvalds sdev->model = (char *) (sdev->inquiry + 16); 6241da177e4SLinus Torvalds sdev->rev = (char *) (sdev->inquiry + 32); 6251da177e4SLinus Torvalds 6261da177e4SLinus Torvalds if (*bflags & BLIST_ISROM) { 6271da177e4SLinus Torvalds /* 6281da177e4SLinus Torvalds * It would be better to modify sdev->type, and set 6291da177e4SLinus Torvalds * sdev->removable, but then the print_inquiry() output 6301da177e4SLinus Torvalds * would not show TYPE_ROM; if print_inquiry() is removed 6311da177e4SLinus Torvalds * the issue goes away. 6321da177e4SLinus Torvalds */ 6331da177e4SLinus Torvalds inq_result[0] = TYPE_ROM; 6341da177e4SLinus Torvalds inq_result[1] |= 0x80; /* removable */ 6351da177e4SLinus Torvalds } else if (*bflags & BLIST_NO_ULD_ATTACH) 6361da177e4SLinus Torvalds sdev->no_uld_attach = 1; 6371da177e4SLinus Torvalds 6381da177e4SLinus Torvalds switch (sdev->type = (inq_result[0] & 0x1f)) { 6391da177e4SLinus Torvalds case TYPE_TAPE: 6401da177e4SLinus Torvalds case TYPE_DISK: 6411da177e4SLinus Torvalds case TYPE_PRINTER: 6421da177e4SLinus Torvalds case TYPE_MOD: 6431da177e4SLinus Torvalds case TYPE_PROCESSOR: 6441da177e4SLinus Torvalds case TYPE_SCANNER: 6451da177e4SLinus Torvalds case TYPE_MEDIUM_CHANGER: 6461da177e4SLinus Torvalds case TYPE_ENCLOSURE: 6471da177e4SLinus Torvalds case TYPE_COMM: 648631e8a13SAl Viro case TYPE_RBC: 6491da177e4SLinus Torvalds sdev->writeable = 1; 6501da177e4SLinus Torvalds break; 6511da177e4SLinus Torvalds case TYPE_WORM: 6521da177e4SLinus Torvalds case TYPE_ROM: 6531da177e4SLinus Torvalds sdev->writeable = 0; 6541da177e4SLinus Torvalds break; 6551da177e4SLinus Torvalds default: 6561da177e4SLinus Torvalds printk(KERN_INFO "scsi: unknown device type %d\n", sdev->type); 6571da177e4SLinus Torvalds } 6581da177e4SLinus Torvalds 6591da177e4SLinus Torvalds print_inquiry(inq_result); 6601da177e4SLinus Torvalds 6611da177e4SLinus Torvalds /* 6621da177e4SLinus Torvalds * For a peripheral qualifier (PQ) value of 1 (001b), the SCSI 6631da177e4SLinus Torvalds * spec says: The device server is capable of supporting the 6641da177e4SLinus Torvalds * specified peripheral device type on this logical unit. However, 6651da177e4SLinus Torvalds * the physical device is not currently connected to this logical 6661da177e4SLinus Torvalds * unit. 6671da177e4SLinus Torvalds * 6681da177e4SLinus Torvalds * The above is vague, as it implies that we could treat 001 and 6691da177e4SLinus Torvalds * 011 the same. Stay compatible with previous code, and create a 670f64a181dSChristoph Hellwig * scsi_device for a PQ of 1 6711da177e4SLinus Torvalds * 6721da177e4SLinus Torvalds * Don't set the device offline here; rather let the upper 6731da177e4SLinus Torvalds * level drivers eval the PQ to decide whether they should 6741da177e4SLinus Torvalds * attach. So remove ((inq_result[0] >> 5) & 7) == 1 check. 6751da177e4SLinus Torvalds */ 6761da177e4SLinus Torvalds 6771da177e4SLinus Torvalds sdev->inq_periph_qual = (inq_result[0] >> 5) & 7; 6781da177e4SLinus Torvalds sdev->removable = (0x80 & inq_result[1]) >> 7; 6791da177e4SLinus Torvalds sdev->lockable = sdev->removable; 6801da177e4SLinus Torvalds sdev->soft_reset = (inq_result[7] & 1) && ((inq_result[3] & 7) == 2); 6811da177e4SLinus Torvalds 6821da177e4SLinus Torvalds if (sdev->scsi_level >= SCSI_3 || (sdev->inquiry_len > 56 && 6831da177e4SLinus Torvalds inq_result[56] & 0x04)) 6841da177e4SLinus Torvalds sdev->ppr = 1; 6851da177e4SLinus Torvalds if (inq_result[7] & 0x60) 6861da177e4SLinus Torvalds sdev->wdtr = 1; 6871da177e4SLinus Torvalds if (inq_result[7] & 0x10) 6881da177e4SLinus Torvalds sdev->sdtr = 1; 6891da177e4SLinus Torvalds 6901da177e4SLinus Torvalds /* 691*5e3c34c1SGreg KH * End sysfs code. 6921da177e4SLinus Torvalds */ 6931da177e4SLinus Torvalds 6941da177e4SLinus Torvalds if ((sdev->scsi_level >= SCSI_2) && (inq_result[7] & 2) && 6951da177e4SLinus Torvalds !(*bflags & BLIST_NOTQ)) 6961da177e4SLinus Torvalds sdev->tagged_supported = 1; 6971da177e4SLinus Torvalds /* 6981da177e4SLinus Torvalds * Some devices (Texel CD ROM drives) have handshaking problems 6991da177e4SLinus Torvalds * when used with the Seagate controllers. borken is initialized 7001da177e4SLinus Torvalds * to 1, and then set it to 0 here. 7011da177e4SLinus Torvalds */ 7021da177e4SLinus Torvalds if ((*bflags & BLIST_BORKEN) == 0) 7031da177e4SLinus Torvalds sdev->borken = 0; 7041da177e4SLinus Torvalds 7051da177e4SLinus Torvalds /* 7061da177e4SLinus Torvalds * Apparently some really broken devices (contrary to the SCSI 7071da177e4SLinus Torvalds * standards) need to be selected without asserting ATN 7081da177e4SLinus Torvalds */ 7091da177e4SLinus Torvalds if (*bflags & BLIST_SELECT_NO_ATN) 7101da177e4SLinus Torvalds sdev->select_no_atn = 1; 7111da177e4SLinus Torvalds 7121da177e4SLinus Torvalds /* 7131da177e4SLinus Torvalds * Some devices may not want to have a start command automatically 7141da177e4SLinus Torvalds * issued when a device is added. 7151da177e4SLinus Torvalds */ 7161da177e4SLinus Torvalds if (*bflags & BLIST_NOSTARTONADD) 7171da177e4SLinus Torvalds sdev->no_start_on_add = 1; 7181da177e4SLinus Torvalds 7191da177e4SLinus Torvalds if (*bflags & BLIST_SINGLELUN) 7201da177e4SLinus Torvalds sdev->single_lun = 1; 7211da177e4SLinus Torvalds 7221da177e4SLinus Torvalds 7231da177e4SLinus Torvalds sdev->use_10_for_rw = 1; 7241da177e4SLinus Torvalds 7251da177e4SLinus Torvalds if (*bflags & BLIST_MS_SKIP_PAGE_08) 7261da177e4SLinus Torvalds sdev->skip_ms_page_8 = 1; 7271da177e4SLinus Torvalds 7281da177e4SLinus Torvalds if (*bflags & BLIST_MS_SKIP_PAGE_3F) 7291da177e4SLinus Torvalds sdev->skip_ms_page_3f = 1; 7301da177e4SLinus Torvalds 7311da177e4SLinus Torvalds if (*bflags & BLIST_USE_10_BYTE_MS) 7321da177e4SLinus Torvalds sdev->use_10_for_ms = 1; 7331da177e4SLinus Torvalds 7341da177e4SLinus Torvalds /* set the device running here so that slave configure 7351da177e4SLinus Torvalds * may do I/O */ 7361da177e4SLinus Torvalds scsi_device_set_state(sdev, SDEV_RUNNING); 7371da177e4SLinus Torvalds 7381da177e4SLinus Torvalds if (*bflags & BLIST_MS_192_BYTES_FOR_3F) 7391da177e4SLinus Torvalds sdev->use_192_bytes_for_3f = 1; 7401da177e4SLinus Torvalds 7411da177e4SLinus Torvalds if (*bflags & BLIST_NOT_LOCKABLE) 7421da177e4SLinus Torvalds sdev->lockable = 0; 7431da177e4SLinus Torvalds 7441da177e4SLinus Torvalds if (*bflags & BLIST_RETRY_HWERROR) 7451da177e4SLinus Torvalds sdev->retry_hwerror = 1; 7461da177e4SLinus Torvalds 7471da177e4SLinus Torvalds transport_configure_device(&sdev->sdev_gendev); 7481da177e4SLinus Torvalds 7491da177e4SLinus Torvalds if (sdev->host->hostt->slave_configure) 7501da177e4SLinus Torvalds sdev->host->hostt->slave_configure(sdev); 7511da177e4SLinus Torvalds 7521da177e4SLinus Torvalds /* 7531da177e4SLinus Torvalds * Ok, the device is now all set up, we can 7541da177e4SLinus Torvalds * register it and tell the rest of the kernel 7551da177e4SLinus Torvalds * about it. 7561da177e4SLinus Torvalds */ 757b24b1033SAlan Stern if (scsi_sysfs_add_sdev(sdev) != 0) 758b24b1033SAlan Stern return SCSI_SCAN_NO_RESPONSE; 7591da177e4SLinus Torvalds 7601da177e4SLinus Torvalds return SCSI_SCAN_LUN_PRESENT; 7611da177e4SLinus Torvalds } 7621da177e4SLinus Torvalds 7636f3a2024SJames Bottomley static inline void scsi_destroy_sdev(struct scsi_device *sdev) 7646f3a2024SJames Bottomley { 7656f3a2024SJames Bottomley if (sdev->host->hostt->slave_destroy) 7666f3a2024SJames Bottomley sdev->host->hostt->slave_destroy(sdev); 7676f3a2024SJames Bottomley transport_destroy_device(&sdev->sdev_gendev); 7686f3a2024SJames Bottomley put_device(&sdev->sdev_gendev); 7696f3a2024SJames Bottomley } 7706f3a2024SJames Bottomley 7716f3a2024SJames Bottomley 7721da177e4SLinus Torvalds /** 7731da177e4SLinus Torvalds * scsi_probe_and_add_lun - probe a LUN, if a LUN is found add it 7741da177e4SLinus Torvalds * @starget: pointer to target device structure 7751da177e4SLinus Torvalds * @lun: LUN of target device 776f64a181dSChristoph Hellwig * @sdevscan: probe the LUN corresponding to this scsi_device 777f64a181dSChristoph Hellwig * @sdevnew: store the value of any new scsi_device allocated 7781da177e4SLinus Torvalds * @bflagsp: store bflags here if not NULL 7791da177e4SLinus Torvalds * 7801da177e4SLinus Torvalds * Description: 7811da177e4SLinus Torvalds * Call scsi_probe_lun, if a LUN with an attached device is found, 7821da177e4SLinus Torvalds * allocate and set it up by calling scsi_add_lun. 7831da177e4SLinus Torvalds * 7841da177e4SLinus Torvalds * Return: 785f64a181dSChristoph Hellwig * SCSI_SCAN_NO_RESPONSE: could not allocate or setup a scsi_device 7861da177e4SLinus Torvalds * SCSI_SCAN_TARGET_PRESENT: target responded, but no device is 7871da177e4SLinus Torvalds * attached at the LUN 788f64a181dSChristoph Hellwig * SCSI_SCAN_LUN_PRESENT: a new scsi_device was allocated and initialized 7891da177e4SLinus Torvalds **/ 7901da177e4SLinus Torvalds static int scsi_probe_and_add_lun(struct scsi_target *starget, 7911da177e4SLinus Torvalds uint lun, int *bflagsp, 7921da177e4SLinus Torvalds struct scsi_device **sdevp, int rescan, 7931da177e4SLinus Torvalds void *hostdata) 7941da177e4SLinus Torvalds { 7951da177e4SLinus Torvalds struct scsi_device *sdev; 7961da177e4SLinus Torvalds unsigned char *result; 79739216033SJames Bottomley int bflags, res = SCSI_SCAN_NO_RESPONSE, result_len = 256; 7981da177e4SLinus Torvalds struct Scsi_Host *shost = dev_to_shost(starget->dev.parent); 7991da177e4SLinus Torvalds 8001da177e4SLinus Torvalds /* 8011da177e4SLinus Torvalds * The rescan flag is used as an optimization, the first scan of a 8021da177e4SLinus Torvalds * host adapter calls into here with rescan == 0. 8031da177e4SLinus Torvalds */ 8041da177e4SLinus Torvalds sdev = scsi_device_lookup_by_target(starget, lun); 8051da177e4SLinus Torvalds if (sdev) { 8066f3a2024SJames Bottomley if (rescan || sdev->sdev_state != SDEV_CREATED) { 8071da177e4SLinus Torvalds SCSI_LOG_SCAN_BUS(3, printk(KERN_INFO 8081da177e4SLinus Torvalds "scsi scan: device exists on %s\n", 8091da177e4SLinus Torvalds sdev->sdev_gendev.bus_id)); 8101da177e4SLinus Torvalds if (sdevp) 8111da177e4SLinus Torvalds *sdevp = sdev; 8121da177e4SLinus Torvalds else 8131da177e4SLinus Torvalds scsi_device_put(sdev); 8141da177e4SLinus Torvalds 8151da177e4SLinus Torvalds if (bflagsp) 8161da177e4SLinus Torvalds *bflagsp = scsi_get_device_flags(sdev, 8171da177e4SLinus Torvalds sdev->vendor, 8181da177e4SLinus Torvalds sdev->model); 8191da177e4SLinus Torvalds return SCSI_SCAN_LUN_PRESENT; 8201da177e4SLinus Torvalds } 8216f3a2024SJames Bottomley scsi_device_put(sdev); 8226f3a2024SJames Bottomley } else 8231da177e4SLinus Torvalds sdev = scsi_alloc_sdev(starget, lun, hostdata); 8241da177e4SLinus Torvalds if (!sdev) 8251da177e4SLinus Torvalds goto out; 82639216033SJames Bottomley 82739216033SJames Bottomley result = kmalloc(result_len, GFP_ATOMIC | 828bc86120aSAl Viro ((shost->unchecked_isa_dma) ? __GFP_DMA : 0)); 8291da177e4SLinus Torvalds if (!result) 83039216033SJames Bottomley goto out_free_sdev; 8311da177e4SLinus Torvalds 83239216033SJames Bottomley if (scsi_probe_lun(sdev, result, result_len, &bflags)) 8331da177e4SLinus Torvalds goto out_free_result; 8341da177e4SLinus Torvalds 8351da177e4SLinus Torvalds /* 8361da177e4SLinus Torvalds * result contains valid SCSI INQUIRY data. 8371da177e4SLinus Torvalds */ 8381da177e4SLinus Torvalds if ((result[0] >> 5) == 3) { 8391da177e4SLinus Torvalds /* 8401da177e4SLinus Torvalds * For a Peripheral qualifier 3 (011b), the SCSI 8411da177e4SLinus Torvalds * spec says: The device server is not capable of 8421da177e4SLinus Torvalds * supporting a physical device on this logical 8431da177e4SLinus Torvalds * unit. 8441da177e4SLinus Torvalds * 8451da177e4SLinus Torvalds * For disks, this implies that there is no 8461da177e4SLinus Torvalds * logical disk configured at sdev->lun, but there 8471da177e4SLinus Torvalds * is a target id responding. 8481da177e4SLinus Torvalds */ 8491da177e4SLinus Torvalds SCSI_LOG_SCAN_BUS(3, printk(KERN_INFO 8501da177e4SLinus Torvalds "scsi scan: peripheral qualifier of 3," 8511da177e4SLinus Torvalds " no device added\n")); 8521da177e4SLinus Torvalds res = SCSI_SCAN_TARGET_PRESENT; 8531da177e4SLinus Torvalds goto out_free_result; 8541da177e4SLinus Torvalds } 8551da177e4SLinus Torvalds 8561da177e4SLinus Torvalds res = scsi_add_lun(sdev, result, &bflags); 8571da177e4SLinus Torvalds if (res == SCSI_SCAN_LUN_PRESENT) { 8581da177e4SLinus Torvalds if (bflags & BLIST_KEY) { 8591da177e4SLinus Torvalds sdev->lockable = 0; 86039216033SJames Bottomley scsi_unlock_floptical(sdev, result); 8611da177e4SLinus Torvalds } 8621da177e4SLinus Torvalds if (bflagsp) 8631da177e4SLinus Torvalds *bflagsp = bflags; 8641da177e4SLinus Torvalds } 8651da177e4SLinus Torvalds 8661da177e4SLinus Torvalds out_free_result: 8671da177e4SLinus Torvalds kfree(result); 8681da177e4SLinus Torvalds out_free_sdev: 8691da177e4SLinus Torvalds if (res == SCSI_SCAN_LUN_PRESENT) { 8701da177e4SLinus Torvalds if (sdevp) { 871b70d37bfSAlan Stern if (scsi_device_get(sdev) == 0) { 8721da177e4SLinus Torvalds *sdevp = sdev; 873b70d37bfSAlan Stern } else { 874b70d37bfSAlan Stern __scsi_remove_device(sdev); 875b70d37bfSAlan Stern res = SCSI_SCAN_NO_RESPONSE; 876b70d37bfSAlan Stern } 8771da177e4SLinus Torvalds } 8786f3a2024SJames Bottomley } else 8796f3a2024SJames Bottomley scsi_destroy_sdev(sdev); 8801da177e4SLinus Torvalds out: 8811da177e4SLinus Torvalds return res; 8821da177e4SLinus Torvalds } 8831da177e4SLinus Torvalds 8841da177e4SLinus Torvalds /** 8851da177e4SLinus Torvalds * scsi_sequential_lun_scan - sequentially scan a SCSI target 8861da177e4SLinus Torvalds * @starget: pointer to target structure to scan 8871da177e4SLinus Torvalds * @bflags: black/white list flag for LUN 0 8881da177e4SLinus Torvalds * @lun0_res: result of scanning LUN 0 8891da177e4SLinus Torvalds * 8901da177e4SLinus Torvalds * Description: 8911da177e4SLinus Torvalds * Generally, scan from LUN 1 (LUN 0 is assumed to already have been 8921da177e4SLinus Torvalds * scanned) to some maximum lun until a LUN is found with no device 8931da177e4SLinus Torvalds * attached. Use the bflags to figure out any oddities. 8941da177e4SLinus Torvalds * 8951da177e4SLinus Torvalds * Modifies sdevscan->lun. 8961da177e4SLinus Torvalds **/ 8971da177e4SLinus Torvalds static void scsi_sequential_lun_scan(struct scsi_target *starget, 8981da177e4SLinus Torvalds int bflags, int lun0_res, int scsi_level, 8991da177e4SLinus Torvalds int rescan) 9001da177e4SLinus Torvalds { 9011da177e4SLinus Torvalds unsigned int sparse_lun, lun, max_dev_lun; 9021da177e4SLinus Torvalds struct Scsi_Host *shost = dev_to_shost(starget->dev.parent); 9031da177e4SLinus Torvalds 9041da177e4SLinus Torvalds SCSI_LOG_SCAN_BUS(3, printk(KERN_INFO "scsi scan: Sequential scan of" 9051da177e4SLinus Torvalds "%s\n", starget->dev.bus_id)); 9061da177e4SLinus Torvalds 9071da177e4SLinus Torvalds max_dev_lun = min(max_scsi_luns, shost->max_lun); 9081da177e4SLinus Torvalds /* 9091da177e4SLinus Torvalds * If this device is known to support sparse multiple units, 9101da177e4SLinus Torvalds * override the other settings, and scan all of them. Normally, 9111da177e4SLinus Torvalds * SCSI-3 devices should be scanned via the REPORT LUNS. 9121da177e4SLinus Torvalds */ 9131da177e4SLinus Torvalds if (bflags & BLIST_SPARSELUN) { 9141da177e4SLinus Torvalds max_dev_lun = shost->max_lun; 9151da177e4SLinus Torvalds sparse_lun = 1; 9161da177e4SLinus Torvalds } else 9171da177e4SLinus Torvalds sparse_lun = 0; 9181da177e4SLinus Torvalds 9191da177e4SLinus Torvalds /* 9201da177e4SLinus Torvalds * If not sparse lun and no device attached at LUN 0 do not scan 9211da177e4SLinus Torvalds * any further. 9221da177e4SLinus Torvalds */ 9231da177e4SLinus Torvalds if (!sparse_lun && (lun0_res != SCSI_SCAN_LUN_PRESENT)) 9241da177e4SLinus Torvalds return; 9251da177e4SLinus Torvalds 9261da177e4SLinus Torvalds /* 9271da177e4SLinus Torvalds * If less than SCSI_1_CSS, and no special lun scaning, stop 9281da177e4SLinus Torvalds * scanning; this matches 2.4 behaviour, but could just be a bug 9291da177e4SLinus Torvalds * (to continue scanning a SCSI_1_CSS device). 9301da177e4SLinus Torvalds * 9311da177e4SLinus Torvalds * This test is broken. We might not have any device on lun0 for 9321da177e4SLinus Torvalds * a sparselun device, and if that's the case then how would we 9331da177e4SLinus Torvalds * know the real scsi_level, eh? It might make sense to just not 9341da177e4SLinus Torvalds * scan any SCSI_1 device for non-0 luns, but that check would best 9351da177e4SLinus Torvalds * go into scsi_alloc_sdev() and just have it return null when asked 9361da177e4SLinus Torvalds * to alloc an sdev for lun > 0 on an already found SCSI_1 device. 9371da177e4SLinus Torvalds * 9381da177e4SLinus Torvalds if ((sdevscan->scsi_level < SCSI_1_CCS) && 9391da177e4SLinus Torvalds ((bflags & (BLIST_FORCELUN | BLIST_SPARSELUN | BLIST_MAX5LUN)) 9401da177e4SLinus Torvalds == 0)) 9411da177e4SLinus Torvalds return; 9421da177e4SLinus Torvalds */ 9431da177e4SLinus Torvalds /* 9441da177e4SLinus Torvalds * If this device is known to support multiple units, override 9451da177e4SLinus Torvalds * the other settings, and scan all of them. 9461da177e4SLinus Torvalds */ 9471da177e4SLinus Torvalds if (bflags & BLIST_FORCELUN) 9481da177e4SLinus Torvalds max_dev_lun = shost->max_lun; 9491da177e4SLinus Torvalds /* 9501da177e4SLinus Torvalds * REGAL CDC-4X: avoid hang after LUN 4 9511da177e4SLinus Torvalds */ 9521da177e4SLinus Torvalds if (bflags & BLIST_MAX5LUN) 9531da177e4SLinus Torvalds max_dev_lun = min(5U, max_dev_lun); 9541da177e4SLinus Torvalds /* 9551da177e4SLinus Torvalds * Do not scan SCSI-2 or lower device past LUN 7, unless 9561da177e4SLinus Torvalds * BLIST_LARGELUN. 9571da177e4SLinus Torvalds */ 9581da177e4SLinus Torvalds if (scsi_level < SCSI_3 && !(bflags & BLIST_LARGELUN)) 9591da177e4SLinus Torvalds max_dev_lun = min(8U, max_dev_lun); 9601da177e4SLinus Torvalds 9611da177e4SLinus Torvalds /* 9621da177e4SLinus Torvalds * We have already scanned LUN 0, so start at LUN 1. Keep scanning 9631da177e4SLinus Torvalds * until we reach the max, or no LUN is found and we are not 9641da177e4SLinus Torvalds * sparse_lun. 9651da177e4SLinus Torvalds */ 9661da177e4SLinus Torvalds for (lun = 1; lun < max_dev_lun; ++lun) 9671da177e4SLinus Torvalds if ((scsi_probe_and_add_lun(starget, lun, NULL, NULL, rescan, 9681da177e4SLinus Torvalds NULL) != SCSI_SCAN_LUN_PRESENT) && 9691da177e4SLinus Torvalds !sparse_lun) 9701da177e4SLinus Torvalds return; 9711da177e4SLinus Torvalds } 9721da177e4SLinus Torvalds 9731da177e4SLinus Torvalds /** 9741da177e4SLinus Torvalds * scsilun_to_int: convert a scsi_lun to an int 9751da177e4SLinus Torvalds * @scsilun: struct scsi_lun to be converted. 9761da177e4SLinus Torvalds * 9771da177e4SLinus Torvalds * Description: 9781da177e4SLinus Torvalds * Convert @scsilun from a struct scsi_lun to a four byte host byte-ordered 9791da177e4SLinus Torvalds * integer, and return the result. The caller must check for 9801da177e4SLinus Torvalds * truncation before using this function. 9811da177e4SLinus Torvalds * 9821da177e4SLinus Torvalds * Notes: 9831da177e4SLinus Torvalds * The struct scsi_lun is assumed to be four levels, with each level 9841da177e4SLinus Torvalds * effectively containing a SCSI byte-ordered (big endian) short; the 9851da177e4SLinus Torvalds * addressing bits of each level are ignored (the highest two bits). 9861da177e4SLinus Torvalds * For a description of the LUN format, post SCSI-3 see the SCSI 9871da177e4SLinus Torvalds * Architecture Model, for SCSI-3 see the SCSI Controller Commands. 9881da177e4SLinus Torvalds * 9891da177e4SLinus Torvalds * Given a struct scsi_lun of: 0a 04 0b 03 00 00 00 00, this function returns 9901da177e4SLinus Torvalds * the integer: 0x0b030a04 9911da177e4SLinus Torvalds **/ 9921da177e4SLinus Torvalds static int scsilun_to_int(struct scsi_lun *scsilun) 9931da177e4SLinus Torvalds { 9941da177e4SLinus Torvalds int i; 9951da177e4SLinus Torvalds unsigned int lun; 9961da177e4SLinus Torvalds 9971da177e4SLinus Torvalds lun = 0; 9981da177e4SLinus Torvalds for (i = 0; i < sizeof(lun); i += 2) 9991da177e4SLinus Torvalds lun = lun | (((scsilun->scsi_lun[i] << 8) | 10001da177e4SLinus Torvalds scsilun->scsi_lun[i + 1]) << (i * 8)); 10011da177e4SLinus Torvalds return lun; 10021da177e4SLinus Torvalds } 10031da177e4SLinus Torvalds 10041da177e4SLinus Torvalds /** 10052f4701d8SJames.Smart@Emulex.Com * int_to_scsilun: reverts an int into a scsi_lun 10062f4701d8SJames.Smart@Emulex.Com * @int: integer to be reverted 10072f4701d8SJames.Smart@Emulex.Com * @scsilun: struct scsi_lun to be set. 10082f4701d8SJames.Smart@Emulex.Com * 10092f4701d8SJames.Smart@Emulex.Com * Description: 10102f4701d8SJames.Smart@Emulex.Com * Reverts the functionality of the scsilun_to_int, which packed 10112f4701d8SJames.Smart@Emulex.Com * an 8-byte lun value into an int. This routine unpacks the int 10122f4701d8SJames.Smart@Emulex.Com * back into the lun value. 10132f4701d8SJames.Smart@Emulex.Com * Note: the scsilun_to_int() routine does not truly handle all 10142f4701d8SJames.Smart@Emulex.Com * 8bytes of the lun value. This functions restores only as much 10152f4701d8SJames.Smart@Emulex.Com * as was set by the routine. 10162f4701d8SJames.Smart@Emulex.Com * 10172f4701d8SJames.Smart@Emulex.Com * Notes: 10182f4701d8SJames.Smart@Emulex.Com * Given an integer : 0x0b030a04, this function returns a 10192f4701d8SJames.Smart@Emulex.Com * scsi_lun of : struct scsi_lun of: 0a 04 0b 03 00 00 00 00 10202f4701d8SJames.Smart@Emulex.Com * 10212f4701d8SJames.Smart@Emulex.Com **/ 10222f4701d8SJames.Smart@Emulex.Com void int_to_scsilun(unsigned int lun, struct scsi_lun *scsilun) 10232f4701d8SJames.Smart@Emulex.Com { 10242f4701d8SJames.Smart@Emulex.Com int i; 10252f4701d8SJames.Smart@Emulex.Com 10262f4701d8SJames.Smart@Emulex.Com memset(scsilun->scsi_lun, 0, sizeof(scsilun->scsi_lun)); 10272f4701d8SJames.Smart@Emulex.Com 10282f4701d8SJames.Smart@Emulex.Com for (i = 0; i < sizeof(lun); i += 2) { 10292f4701d8SJames.Smart@Emulex.Com scsilun->scsi_lun[i] = (lun >> 8) & 0xFF; 10302f4701d8SJames.Smart@Emulex.Com scsilun->scsi_lun[i+1] = lun & 0xFF; 10312f4701d8SJames.Smart@Emulex.Com lun = lun >> 16; 10322f4701d8SJames.Smart@Emulex.Com } 10332f4701d8SJames.Smart@Emulex.Com } 10342f4701d8SJames.Smart@Emulex.Com EXPORT_SYMBOL(int_to_scsilun); 10352f4701d8SJames.Smart@Emulex.Com 10362f4701d8SJames.Smart@Emulex.Com /** 10371da177e4SLinus Torvalds * scsi_report_lun_scan - Scan using SCSI REPORT LUN results 1038f64a181dSChristoph Hellwig * @sdevscan: scan the host, channel, and id of this scsi_device 10391da177e4SLinus Torvalds * 10401da177e4SLinus Torvalds * Description: 10411da177e4SLinus Torvalds * If @sdevscan is for a SCSI-3 or up device, send a REPORT LUN 10421da177e4SLinus Torvalds * command, and scan the resulting list of LUNs by calling 10431da177e4SLinus Torvalds * scsi_probe_and_add_lun. 10441da177e4SLinus Torvalds * 10451da177e4SLinus Torvalds * Modifies sdevscan->lun. 10461da177e4SLinus Torvalds * 10471da177e4SLinus Torvalds * Return: 10481da177e4SLinus Torvalds * 0: scan completed (or no memory, so further scanning is futile) 10491da177e4SLinus Torvalds * 1: no report lun scan, or not configured 10501da177e4SLinus Torvalds **/ 10516f3a2024SJames Bottomley static int scsi_report_lun_scan(struct scsi_target *starget, int bflags, 10521da177e4SLinus Torvalds int rescan) 10531da177e4SLinus Torvalds { 10541da177e4SLinus Torvalds char devname[64]; 10551da177e4SLinus Torvalds unsigned char scsi_cmd[MAX_COMMAND_SIZE]; 10561da177e4SLinus Torvalds unsigned int length; 10571da177e4SLinus Torvalds unsigned int lun; 10581da177e4SLinus Torvalds unsigned int num_luns; 10591da177e4SLinus Torvalds unsigned int retries; 106039216033SJames Bottomley int result; 10611da177e4SLinus Torvalds struct scsi_lun *lunp, *lun_data; 10621da177e4SLinus Torvalds u8 *data; 10631da177e4SLinus Torvalds struct scsi_sense_hdr sshdr; 10646f3a2024SJames Bottomley struct scsi_device *sdev; 10656f3a2024SJames Bottomley struct Scsi_Host *shost = dev_to_shost(&starget->dev); 10662ef89198SAlan Stern int ret = 0; 10671da177e4SLinus Torvalds 10681da177e4SLinus Torvalds /* 10691da177e4SLinus Torvalds * Only support SCSI-3 and up devices if BLIST_NOREPORTLUN is not set. 10701da177e4SLinus Torvalds * Also allow SCSI-2 if BLIST_REPORTLUN2 is set and host adapter does 10711da177e4SLinus Torvalds * support more than 8 LUNs. 10721da177e4SLinus Torvalds */ 10731da177e4SLinus Torvalds if ((bflags & BLIST_NOREPORTLUN) || 10746f3a2024SJames Bottomley starget->scsi_level < SCSI_2 || 10756f3a2024SJames Bottomley (starget->scsi_level < SCSI_3 && 10766f3a2024SJames Bottomley (!(bflags & BLIST_REPORTLUN2) || shost->max_lun <= 8)) ) 10771da177e4SLinus Torvalds return 1; 10781da177e4SLinus Torvalds if (bflags & BLIST_NOLUN) 10791da177e4SLinus Torvalds return 0; 10801da177e4SLinus Torvalds 10816f3a2024SJames Bottomley if (!(sdev = scsi_device_lookup_by_target(starget, 0))) { 10826f3a2024SJames Bottomley sdev = scsi_alloc_sdev(starget, 0, NULL); 10836f3a2024SJames Bottomley if (!sdev) 10846f3a2024SJames Bottomley return 0; 10856f3a2024SJames Bottomley if (scsi_device_get(sdev)) 10866f3a2024SJames Bottomley return 0; 10876f3a2024SJames Bottomley } 10886f3a2024SJames Bottomley 10891da177e4SLinus Torvalds sprintf(devname, "host %d channel %d id %d", 10906f3a2024SJames Bottomley shost->host_no, sdev->channel, sdev->id); 10911da177e4SLinus Torvalds 10921da177e4SLinus Torvalds /* 10931da177e4SLinus Torvalds * Allocate enough to hold the header (the same size as one scsi_lun) 10941da177e4SLinus Torvalds * plus the max number of luns we are requesting. 10951da177e4SLinus Torvalds * 10961da177e4SLinus Torvalds * Reallocating and trying again (with the exact amount we need) 10971da177e4SLinus Torvalds * would be nice, but then we need to somehow limit the size 10981da177e4SLinus Torvalds * allocated based on the available memory and the limits of 10991da177e4SLinus Torvalds * kmalloc - we don't want a kmalloc() failure of a huge value to 11001da177e4SLinus Torvalds * prevent us from finding any LUNs on this target. 11011da177e4SLinus Torvalds */ 11021da177e4SLinus Torvalds length = (max_scsi_report_luns + 1) * sizeof(struct scsi_lun); 11031da177e4SLinus Torvalds lun_data = kmalloc(length, GFP_ATOMIC | 11041da177e4SLinus Torvalds (sdev->host->unchecked_isa_dma ? __GFP_DMA : 0)); 11056f3a2024SJames Bottomley if (!lun_data) { 11066f3a2024SJames Bottomley printk(ALLOC_FAILURE_MSG, __FUNCTION__); 110739216033SJames Bottomley goto out; 11086f3a2024SJames Bottomley } 11091da177e4SLinus Torvalds 11101da177e4SLinus Torvalds scsi_cmd[0] = REPORT_LUNS; 11111da177e4SLinus Torvalds 11121da177e4SLinus Torvalds /* 11131da177e4SLinus Torvalds * bytes 1 - 5: reserved, set to zero. 11141da177e4SLinus Torvalds */ 11151da177e4SLinus Torvalds memset(&scsi_cmd[1], 0, 5); 11161da177e4SLinus Torvalds 11171da177e4SLinus Torvalds /* 11181da177e4SLinus Torvalds * bytes 6 - 9: length of the command. 11191da177e4SLinus Torvalds */ 11201da177e4SLinus Torvalds scsi_cmd[6] = (unsigned char) (length >> 24) & 0xff; 11211da177e4SLinus Torvalds scsi_cmd[7] = (unsigned char) (length >> 16) & 0xff; 11221da177e4SLinus Torvalds scsi_cmd[8] = (unsigned char) (length >> 8) & 0xff; 11231da177e4SLinus Torvalds scsi_cmd[9] = (unsigned char) length & 0xff; 11241da177e4SLinus Torvalds 11251da177e4SLinus Torvalds scsi_cmd[10] = 0; /* reserved */ 11261da177e4SLinus Torvalds scsi_cmd[11] = 0; /* control */ 11271da177e4SLinus Torvalds 11281da177e4SLinus Torvalds /* 11291da177e4SLinus Torvalds * We can get a UNIT ATTENTION, for example a power on/reset, so 11301da177e4SLinus Torvalds * retry a few times (like sd.c does for TEST UNIT READY). 11311da177e4SLinus Torvalds * Experience shows some combinations of adapter/devices get at 11321da177e4SLinus Torvalds * least two power on/resets. 11331da177e4SLinus Torvalds * 11341da177e4SLinus Torvalds * Illegal requests (for devices that do not support REPORT LUNS) 11351da177e4SLinus Torvalds * should come through as a check condition, and will not generate 11361da177e4SLinus Torvalds * a retry. 11371da177e4SLinus Torvalds */ 11381da177e4SLinus Torvalds for (retries = 0; retries < 3; retries++) { 11391da177e4SLinus Torvalds SCSI_LOG_SCAN_BUS(3, printk (KERN_INFO "scsi scan: Sending" 11401da177e4SLinus Torvalds " REPORT LUNS to %s (try %d)\n", devname, 11411da177e4SLinus Torvalds retries)); 114239216033SJames Bottomley 114339216033SJames Bottomley result = scsi_execute_req(sdev, scsi_cmd, DMA_FROM_DEVICE, 1144ea73a9f2SJames Bottomley lun_data, length, &sshdr, 11451da177e4SLinus Torvalds SCSI_TIMEOUT + 4 * HZ, 3); 114639216033SJames Bottomley 11471da177e4SLinus Torvalds SCSI_LOG_SCAN_BUS(3, printk (KERN_INFO "scsi scan: REPORT LUNS" 114839216033SJames Bottomley " %s (try %d) result 0x%x\n", result 114939216033SJames Bottomley ? "failed" : "successful", retries, result)); 115039216033SJames Bottomley if (result == 0) 11511da177e4SLinus Torvalds break; 1152ea73a9f2SJames Bottomley else if (scsi_sense_valid(&sshdr)) { 11531da177e4SLinus Torvalds if (sshdr.sense_key != UNIT_ATTENTION) 11541da177e4SLinus Torvalds break; 11551da177e4SLinus Torvalds } 11561da177e4SLinus Torvalds } 11571da177e4SLinus Torvalds 115839216033SJames Bottomley if (result) { 11591da177e4SLinus Torvalds /* 11601da177e4SLinus Torvalds * The device probably does not support a REPORT LUN command 11611da177e4SLinus Torvalds */ 11622ef89198SAlan Stern ret = 1; 11632ef89198SAlan Stern goto out_err; 11641da177e4SLinus Torvalds } 11651da177e4SLinus Torvalds 11661da177e4SLinus Torvalds /* 11671da177e4SLinus Torvalds * Get the length from the first four bytes of lun_data. 11681da177e4SLinus Torvalds */ 11691da177e4SLinus Torvalds data = (u8 *) lun_data->scsi_lun; 11701da177e4SLinus Torvalds length = ((data[0] << 24) | (data[1] << 16) | 11711da177e4SLinus Torvalds (data[2] << 8) | (data[3] << 0)); 11721da177e4SLinus Torvalds 11731da177e4SLinus Torvalds num_luns = (length / sizeof(struct scsi_lun)); 11741da177e4SLinus Torvalds if (num_luns > max_scsi_report_luns) { 11751da177e4SLinus Torvalds printk(KERN_WARNING "scsi: On %s only %d (max_scsi_report_luns)" 11761da177e4SLinus Torvalds " of %d luns reported, try increasing" 11771da177e4SLinus Torvalds " max_scsi_report_luns.\n", devname, 11781da177e4SLinus Torvalds max_scsi_report_luns, num_luns); 11791da177e4SLinus Torvalds num_luns = max_scsi_report_luns; 11801da177e4SLinus Torvalds } 11811da177e4SLinus Torvalds 11823bf743e7SJeff Garzik SCSI_LOG_SCAN_BUS(3, sdev_printk (KERN_INFO, sdev, 11833bf743e7SJeff Garzik "scsi scan: REPORT LUN scan\n")); 11841da177e4SLinus Torvalds 11851da177e4SLinus Torvalds /* 11861da177e4SLinus Torvalds * Scan the luns in lun_data. The entry at offset 0 is really 11871da177e4SLinus Torvalds * the header, so start at 1 and go up to and including num_luns. 11881da177e4SLinus Torvalds */ 11891da177e4SLinus Torvalds for (lunp = &lun_data[1]; lunp <= &lun_data[num_luns]; lunp++) { 11901da177e4SLinus Torvalds lun = scsilun_to_int(lunp); 11911da177e4SLinus Torvalds 11921da177e4SLinus Torvalds /* 11931da177e4SLinus Torvalds * Check if the unused part of lunp is non-zero, and so 11941da177e4SLinus Torvalds * does not fit in lun. 11951da177e4SLinus Torvalds */ 11961da177e4SLinus Torvalds if (memcmp(&lunp->scsi_lun[sizeof(lun)], "\0\0\0\0", 4)) { 11971da177e4SLinus Torvalds int i; 11981da177e4SLinus Torvalds 11991da177e4SLinus Torvalds /* 12001da177e4SLinus Torvalds * Output an error displaying the LUN in byte order, 12011da177e4SLinus Torvalds * this differs from what linux would print for the 12021da177e4SLinus Torvalds * integer LUN value. 12031da177e4SLinus Torvalds */ 12041da177e4SLinus Torvalds printk(KERN_WARNING "scsi: %s lun 0x", devname); 12051da177e4SLinus Torvalds data = (char *)lunp->scsi_lun; 12061da177e4SLinus Torvalds for (i = 0; i < sizeof(struct scsi_lun); i++) 12071da177e4SLinus Torvalds printk("%02x", data[i]); 12081da177e4SLinus Torvalds printk(" has a LUN larger than currently supported.\n"); 12091da177e4SLinus Torvalds } else if (lun > sdev->host->max_lun) { 12101da177e4SLinus Torvalds printk(KERN_WARNING "scsi: %s lun%d has a LUN larger" 12111da177e4SLinus Torvalds " than allowed by the host adapter\n", 12121da177e4SLinus Torvalds devname, lun); 12131da177e4SLinus Torvalds } else { 12141da177e4SLinus Torvalds int res; 12151da177e4SLinus Torvalds 12161da177e4SLinus Torvalds res = scsi_probe_and_add_lun(starget, 12171da177e4SLinus Torvalds lun, NULL, NULL, rescan, NULL); 12181da177e4SLinus Torvalds if (res == SCSI_SCAN_NO_RESPONSE) { 12191da177e4SLinus Torvalds /* 12201da177e4SLinus Torvalds * Got some results, but now none, abort. 12211da177e4SLinus Torvalds */ 12223bf743e7SJeff Garzik sdev_printk(KERN_ERR, sdev, 12233bf743e7SJeff Garzik "Unexpected response" 12243bf743e7SJeff Garzik " from lun %d while scanning, scan" 12253bf743e7SJeff Garzik " aborted\n", lun); 12261da177e4SLinus Torvalds break; 12271da177e4SLinus Torvalds } 12281da177e4SLinus Torvalds } 12291da177e4SLinus Torvalds } 12301da177e4SLinus Torvalds 12312ef89198SAlan Stern out_err: 12321da177e4SLinus Torvalds kfree(lun_data); 12331da177e4SLinus Torvalds out: 12346f3a2024SJames Bottomley scsi_device_put(sdev); 12356f3a2024SJames Bottomley if (sdev->sdev_state == SDEV_CREATED) 12361da177e4SLinus Torvalds /* 12376f3a2024SJames Bottomley * the sdev we used didn't appear in the report luns scan 12381da177e4SLinus Torvalds */ 12396f3a2024SJames Bottomley scsi_destroy_sdev(sdev); 12402ef89198SAlan Stern return ret; 12411da177e4SLinus Torvalds } 12421da177e4SLinus Torvalds 12431da177e4SLinus Torvalds struct scsi_device *__scsi_add_device(struct Scsi_Host *shost, uint channel, 12441da177e4SLinus Torvalds uint id, uint lun, void *hostdata) 12451da177e4SLinus Torvalds { 12461da177e4SLinus Torvalds struct scsi_device *sdev; 12471da177e4SLinus Torvalds struct device *parent = &shost->shost_gendev; 12481da177e4SLinus Torvalds int res; 1249e02f3f59SChristoph Hellwig struct scsi_target *starget; 12501da177e4SLinus Torvalds 1251e02f3f59SChristoph Hellwig starget = scsi_alloc_target(parent, channel, id); 12521da177e4SLinus Torvalds if (!starget) 12531da177e4SLinus Torvalds return ERR_PTR(-ENOMEM); 12541da177e4SLinus Torvalds 1255c92715b3SNathan Lynch get_device(&starget->dev); 12560b950672SArjan van de Ven mutex_lock(&shost->scan_mutex); 125782f29467SMike Anderson if (scsi_host_scan_allowed(shost)) { 125882f29467SMike Anderson res = scsi_probe_and_add_lun(starget, lun, NULL, &sdev, 1, 125982f29467SMike Anderson hostdata); 12601da177e4SLinus Torvalds if (res != SCSI_SCAN_LUN_PRESENT) 12611da177e4SLinus Torvalds sdev = ERR_PTR(-ENODEV); 126282f29467SMike Anderson } 12630b950672SArjan van de Ven mutex_unlock(&shost->scan_mutex); 12641da177e4SLinus Torvalds scsi_target_reap(starget); 12651da177e4SLinus Torvalds put_device(&starget->dev); 12661da177e4SLinus Torvalds 12671da177e4SLinus Torvalds return sdev; 12681da177e4SLinus Torvalds } 12691da177e4SLinus Torvalds EXPORT_SYMBOL(__scsi_add_device); 12701da177e4SLinus Torvalds 1271146f7262SJames Bottomley int scsi_add_device(struct Scsi_Host *host, uint channel, 1272146f7262SJames Bottomley uint target, uint lun) 1273146f7262SJames Bottomley { 1274146f7262SJames Bottomley struct scsi_device *sdev = 1275146f7262SJames Bottomley __scsi_add_device(host, channel, target, lun, NULL); 1276146f7262SJames Bottomley if (IS_ERR(sdev)) 1277146f7262SJames Bottomley return PTR_ERR(sdev); 1278146f7262SJames Bottomley 1279146f7262SJames Bottomley scsi_device_put(sdev); 1280146f7262SJames Bottomley return 0; 1281146f7262SJames Bottomley } 1282146f7262SJames Bottomley EXPORT_SYMBOL(scsi_add_device); 1283146f7262SJames Bottomley 12841da177e4SLinus Torvalds void scsi_rescan_device(struct device *dev) 12851da177e4SLinus Torvalds { 12861da177e4SLinus Torvalds struct scsi_driver *drv; 12871da177e4SLinus Torvalds 12881da177e4SLinus Torvalds if (!dev->driver) 12891da177e4SLinus Torvalds return; 12901da177e4SLinus Torvalds 12911da177e4SLinus Torvalds drv = to_scsi_driver(dev->driver); 12921da177e4SLinus Torvalds if (try_module_get(drv->owner)) { 12931da177e4SLinus Torvalds if (drv->rescan) 12941da177e4SLinus Torvalds drv->rescan(dev); 12951da177e4SLinus Torvalds module_put(drv->owner); 12961da177e4SLinus Torvalds } 12971da177e4SLinus Torvalds } 12981da177e4SLinus Torvalds EXPORT_SYMBOL(scsi_rescan_device); 12991da177e4SLinus Torvalds 1300e517d313SAlan Stern static void __scsi_scan_target(struct device *parent, unsigned int channel, 13011da177e4SLinus Torvalds unsigned int id, unsigned int lun, int rescan) 13021da177e4SLinus Torvalds { 13031da177e4SLinus Torvalds struct Scsi_Host *shost = dev_to_shost(parent); 13041da177e4SLinus Torvalds int bflags = 0; 13051da177e4SLinus Torvalds int res; 13061da177e4SLinus Torvalds struct scsi_target *starget; 13071da177e4SLinus Torvalds 13081da177e4SLinus Torvalds if (shost->this_id == id) 13091da177e4SLinus Torvalds /* 13101da177e4SLinus Torvalds * Don't scan the host adapter 13111da177e4SLinus Torvalds */ 13121da177e4SLinus Torvalds return; 13131da177e4SLinus Torvalds 13141da177e4SLinus Torvalds starget = scsi_alloc_target(parent, channel, id); 13151da177e4SLinus Torvalds if (!starget) 13161da177e4SLinus Torvalds return; 13171da177e4SLinus Torvalds 13181da177e4SLinus Torvalds get_device(&starget->dev); 13191da177e4SLinus Torvalds if (lun != SCAN_WILD_CARD) { 13201da177e4SLinus Torvalds /* 13211da177e4SLinus Torvalds * Scan for a specific host/chan/id/lun. 13221da177e4SLinus Torvalds */ 13231da177e4SLinus Torvalds scsi_probe_and_add_lun(starget, lun, NULL, NULL, rescan, NULL); 13241da177e4SLinus Torvalds goto out_reap; 13251da177e4SLinus Torvalds } 13261da177e4SLinus Torvalds 13271da177e4SLinus Torvalds /* 13281da177e4SLinus Torvalds * Scan LUN 0, if there is some response, scan further. Ideally, we 13291da177e4SLinus Torvalds * would not configure LUN 0 until all LUNs are scanned. 13301da177e4SLinus Torvalds */ 13316f3a2024SJames Bottomley res = scsi_probe_and_add_lun(starget, 0, &bflags, NULL, rescan, NULL); 13326f3a2024SJames Bottomley if (res == SCSI_SCAN_LUN_PRESENT || res == SCSI_SCAN_TARGET_PRESENT) { 13336f3a2024SJames Bottomley if (scsi_report_lun_scan(starget, bflags, rescan) != 0) 13341da177e4SLinus Torvalds /* 13351da177e4SLinus Torvalds * The REPORT LUN did not scan the target, 13361da177e4SLinus Torvalds * do a sequential scan. 13371da177e4SLinus Torvalds */ 13381da177e4SLinus Torvalds scsi_sequential_lun_scan(starget, bflags, 13396f3a2024SJames Bottomley res, starget->scsi_level, rescan); 13401da177e4SLinus Torvalds } 13411da177e4SLinus Torvalds 13421da177e4SLinus Torvalds out_reap: 13431da177e4SLinus Torvalds /* now determine if the target has any children at all 13441da177e4SLinus Torvalds * and if not, nuke it */ 13451da177e4SLinus Torvalds scsi_target_reap(starget); 13461da177e4SLinus Torvalds 13471da177e4SLinus Torvalds put_device(&starget->dev); 13481da177e4SLinus Torvalds } 1349e517d313SAlan Stern 1350e517d313SAlan Stern /** 1351e517d313SAlan Stern * scsi_scan_target - scan a target id, possibly including all LUNs on the 1352e517d313SAlan Stern * target. 1353e517d313SAlan Stern * @parent: host to scan 1354e517d313SAlan Stern * @channel: channel to scan 1355e517d313SAlan Stern * @id: target id to scan 1356e517d313SAlan Stern * @lun: Specific LUN to scan or SCAN_WILD_CARD 1357e517d313SAlan Stern * @rescan: passed to LUN scanning routines 1358e517d313SAlan Stern * 1359e517d313SAlan Stern * Description: 1360e517d313SAlan Stern * Scan the target id on @parent, @channel, and @id. Scan at least LUN 0, 1361e517d313SAlan Stern * and possibly all LUNs on the target id. 1362e517d313SAlan Stern * 1363e517d313SAlan Stern * First try a REPORT LUN scan, if that does not scan the target, do a 1364e517d313SAlan Stern * sequential scan of LUNs on the target id. 1365e517d313SAlan Stern **/ 1366e517d313SAlan Stern void scsi_scan_target(struct device *parent, unsigned int channel, 1367e517d313SAlan Stern unsigned int id, unsigned int lun, int rescan) 1368e517d313SAlan Stern { 1369e517d313SAlan Stern struct Scsi_Host *shost = dev_to_shost(parent); 1370e517d313SAlan Stern 13710b950672SArjan van de Ven mutex_lock(&shost->scan_mutex); 1372e517d313SAlan Stern if (scsi_host_scan_allowed(shost)) 1373e517d313SAlan Stern __scsi_scan_target(parent, channel, id, lun, rescan); 13740b950672SArjan van de Ven mutex_unlock(&shost->scan_mutex); 1375e517d313SAlan Stern } 13761da177e4SLinus Torvalds EXPORT_SYMBOL(scsi_scan_target); 13771da177e4SLinus Torvalds 13781da177e4SLinus Torvalds static void scsi_scan_channel(struct Scsi_Host *shost, unsigned int channel, 13791da177e4SLinus Torvalds unsigned int id, unsigned int lun, int rescan) 13801da177e4SLinus Torvalds { 13811da177e4SLinus Torvalds uint order_id; 13821da177e4SLinus Torvalds 13831da177e4SLinus Torvalds if (id == SCAN_WILD_CARD) 13841da177e4SLinus Torvalds for (id = 0; id < shost->max_id; ++id) { 13851da177e4SLinus Torvalds /* 13861da177e4SLinus Torvalds * XXX adapter drivers when possible (FCP, iSCSI) 13871da177e4SLinus Torvalds * could modify max_id to match the current max, 13881da177e4SLinus Torvalds * not the absolute max. 13891da177e4SLinus Torvalds * 13901da177e4SLinus Torvalds * XXX add a shost id iterator, so for example, 13911da177e4SLinus Torvalds * the FC ID can be the same as a target id 13921da177e4SLinus Torvalds * without a huge overhead of sparse id's. 13931da177e4SLinus Torvalds */ 13941da177e4SLinus Torvalds if (shost->reverse_ordering) 13951da177e4SLinus Torvalds /* 13961da177e4SLinus Torvalds * Scan from high to low id. 13971da177e4SLinus Torvalds */ 13981da177e4SLinus Torvalds order_id = shost->max_id - id - 1; 13991da177e4SLinus Torvalds else 14001da177e4SLinus Torvalds order_id = id; 1401e517d313SAlan Stern __scsi_scan_target(&shost->shost_gendev, channel, 1402e517d313SAlan Stern order_id, lun, rescan); 14031da177e4SLinus Torvalds } 14041da177e4SLinus Torvalds else 1405e517d313SAlan Stern __scsi_scan_target(&shost->shost_gendev, channel, 1406e517d313SAlan Stern id, lun, rescan); 14071da177e4SLinus Torvalds } 14081da177e4SLinus Torvalds 14091da177e4SLinus Torvalds int scsi_scan_host_selected(struct Scsi_Host *shost, unsigned int channel, 14101da177e4SLinus Torvalds unsigned int id, unsigned int lun, int rescan) 14111da177e4SLinus Torvalds { 14123bf743e7SJeff Garzik SCSI_LOG_SCAN_BUS(3, shost_printk (KERN_INFO, shost, 14133bf743e7SJeff Garzik "%s: <%u:%u:%u>\n", 14143bf743e7SJeff Garzik __FUNCTION__, channel, id, lun)); 14151da177e4SLinus Torvalds 14161da177e4SLinus Torvalds if (((channel != SCAN_WILD_CARD) && (channel > shost->max_channel)) || 14171da177e4SLinus Torvalds ((id != SCAN_WILD_CARD) && (id > shost->max_id)) || 14181da177e4SLinus Torvalds ((lun != SCAN_WILD_CARD) && (lun > shost->max_lun))) 14191da177e4SLinus Torvalds return -EINVAL; 14201da177e4SLinus Torvalds 14210b950672SArjan van de Ven mutex_lock(&shost->scan_mutex); 142282f29467SMike Anderson if (scsi_host_scan_allowed(shost)) { 14231da177e4SLinus Torvalds if (channel == SCAN_WILD_CARD) 142482f29467SMike Anderson for (channel = 0; channel <= shost->max_channel; 142582f29467SMike Anderson channel++) 142682f29467SMike Anderson scsi_scan_channel(shost, channel, id, lun, 142782f29467SMike Anderson rescan); 14281da177e4SLinus Torvalds else 14291da177e4SLinus Torvalds scsi_scan_channel(shost, channel, id, lun, rescan); 143082f29467SMike Anderson } 14310b950672SArjan van de Ven mutex_unlock(&shost->scan_mutex); 14321da177e4SLinus Torvalds 14331da177e4SLinus Torvalds return 0; 14341da177e4SLinus Torvalds } 14351da177e4SLinus Torvalds 14361da177e4SLinus Torvalds /** 14371da177e4SLinus Torvalds * scsi_scan_host - scan the given adapter 14381da177e4SLinus Torvalds * @shost: adapter to scan 14391da177e4SLinus Torvalds **/ 14401da177e4SLinus Torvalds void scsi_scan_host(struct Scsi_Host *shost) 14411da177e4SLinus Torvalds { 14421da177e4SLinus Torvalds scsi_scan_host_selected(shost, SCAN_WILD_CARD, SCAN_WILD_CARD, 14431da177e4SLinus Torvalds SCAN_WILD_CARD, 0); 14441da177e4SLinus Torvalds } 14451da177e4SLinus Torvalds EXPORT_SYMBOL(scsi_scan_host); 14461da177e4SLinus Torvalds 14471da177e4SLinus Torvalds void scsi_forget_host(struct Scsi_Host *shost) 14481da177e4SLinus Torvalds { 1449a64358dbSAlan Stern struct scsi_device *sdev; 14501da177e4SLinus Torvalds unsigned long flags; 14511da177e4SLinus Torvalds 1452a64358dbSAlan Stern restart: 14531da177e4SLinus Torvalds spin_lock_irqsave(shost->host_lock, flags); 1454a64358dbSAlan Stern list_for_each_entry(sdev, &shost->__devices, siblings) { 1455a64358dbSAlan Stern if (sdev->sdev_state == SDEV_DEL) 1456a64358dbSAlan Stern continue; 14571da177e4SLinus Torvalds spin_unlock_irqrestore(shost->host_lock, flags); 1458a64358dbSAlan Stern __scsi_remove_device(sdev); 1459a64358dbSAlan Stern goto restart; 14601da177e4SLinus Torvalds } 14611da177e4SLinus Torvalds spin_unlock_irqrestore(shost->host_lock, flags); 14621da177e4SLinus Torvalds } 14631da177e4SLinus Torvalds 14641da177e4SLinus Torvalds /* 14651da177e4SLinus Torvalds * Function: scsi_get_host_dev() 14661da177e4SLinus Torvalds * 1467f64a181dSChristoph Hellwig * Purpose: Create a scsi_device that points to the host adapter itself. 14681da177e4SLinus Torvalds * 1469f64a181dSChristoph Hellwig * Arguments: SHpnt - Host that needs a scsi_device 14701da177e4SLinus Torvalds * 14711da177e4SLinus Torvalds * Lock status: None assumed. 14721da177e4SLinus Torvalds * 1473f64a181dSChristoph Hellwig * Returns: The scsi_device or NULL 14741da177e4SLinus Torvalds * 14751da177e4SLinus Torvalds * Notes: 1476f64a181dSChristoph Hellwig * Attach a single scsi_device to the Scsi_Host - this should 14771da177e4SLinus Torvalds * be made to look like a "pseudo-device" that points to the 14781da177e4SLinus Torvalds * HA itself. 14791da177e4SLinus Torvalds * 14801da177e4SLinus Torvalds * Note - this device is not accessible from any high-level 14811da177e4SLinus Torvalds * drivers (including generics), which is probably not 14821da177e4SLinus Torvalds * optimal. We can add hooks later to attach 14831da177e4SLinus Torvalds */ 14841da177e4SLinus Torvalds struct scsi_device *scsi_get_host_dev(struct Scsi_Host *shost) 14851da177e4SLinus Torvalds { 1486e517d313SAlan Stern struct scsi_device *sdev = NULL; 14871da177e4SLinus Torvalds struct scsi_target *starget; 14881da177e4SLinus Torvalds 14890b950672SArjan van de Ven mutex_lock(&shost->scan_mutex); 1490e517d313SAlan Stern if (!scsi_host_scan_allowed(shost)) 1491e517d313SAlan Stern goto out; 14921da177e4SLinus Torvalds starget = scsi_alloc_target(&shost->shost_gendev, 0, shost->this_id); 14931da177e4SLinus Torvalds if (!starget) 1494e517d313SAlan Stern goto out; 14951da177e4SLinus Torvalds 14961da177e4SLinus Torvalds sdev = scsi_alloc_sdev(starget, 0, NULL); 14971da177e4SLinus Torvalds if (sdev) { 14981da177e4SLinus Torvalds sdev->sdev_gendev.parent = get_device(&starget->dev); 14991da177e4SLinus Torvalds sdev->borken = 0; 15001da177e4SLinus Torvalds } 15011da177e4SLinus Torvalds put_device(&starget->dev); 1502e517d313SAlan Stern out: 15030b950672SArjan van de Ven mutex_unlock(&shost->scan_mutex); 15041da177e4SLinus Torvalds return sdev; 15051da177e4SLinus Torvalds } 15061da177e4SLinus Torvalds EXPORT_SYMBOL(scsi_get_host_dev); 15071da177e4SLinus Torvalds 15081da177e4SLinus Torvalds /* 15091da177e4SLinus Torvalds * Function: scsi_free_host_dev() 15101da177e4SLinus Torvalds * 15111da177e4SLinus Torvalds * Purpose: Free a scsi_device that points to the host adapter itself. 15121da177e4SLinus Torvalds * 1513f64a181dSChristoph Hellwig * Arguments: SHpnt - Host that needs a scsi_device 15141da177e4SLinus Torvalds * 15151da177e4SLinus Torvalds * Lock status: None assumed. 15161da177e4SLinus Torvalds * 15171da177e4SLinus Torvalds * Returns: Nothing 15181da177e4SLinus Torvalds * 15191da177e4SLinus Torvalds * Notes: 15201da177e4SLinus Torvalds */ 15211da177e4SLinus Torvalds void scsi_free_host_dev(struct scsi_device *sdev) 15221da177e4SLinus Torvalds { 15231da177e4SLinus Torvalds BUG_ON(sdev->id != sdev->host->this_id); 15241da177e4SLinus Torvalds 15256f3a2024SJames Bottomley scsi_destroy_sdev(sdev); 15261da177e4SLinus Torvalds } 15271da177e4SLinus Torvalds EXPORT_SYMBOL(scsi_free_host_dev); 15281da177e4SLinus Torvalds 1529