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 2081da177e4SLinus Torvalds sdev = kmalloc(sizeof(*sdev) + shost->transportt->device_size, 2091da177e4SLinus Torvalds GFP_ATOMIC); 2101da177e4SLinus Torvalds if (!sdev) 2111da177e4SLinus Torvalds goto out; 2121da177e4SLinus Torvalds 2131da177e4SLinus Torvalds memset(sdev, 0, sizeof(*sdev)); 2141da177e4SLinus Torvalds sdev->vendor = scsi_null_device_strs; 2151da177e4SLinus Torvalds sdev->model = scsi_null_device_strs; 2161da177e4SLinus Torvalds sdev->rev = scsi_null_device_strs; 2171da177e4SLinus Torvalds sdev->host = shost; 2181da177e4SLinus Torvalds sdev->id = starget->id; 2191da177e4SLinus Torvalds sdev->lun = lun; 2201da177e4SLinus Torvalds sdev->channel = starget->channel; 2211da177e4SLinus Torvalds sdev->sdev_state = SDEV_CREATED; 2221da177e4SLinus Torvalds INIT_LIST_HEAD(&sdev->siblings); 2231da177e4SLinus Torvalds INIT_LIST_HEAD(&sdev->same_target_siblings); 2241da177e4SLinus Torvalds INIT_LIST_HEAD(&sdev->cmd_list); 2251da177e4SLinus Torvalds INIT_LIST_HEAD(&sdev->starved_entry); 2261da177e4SLinus Torvalds spin_lock_init(&sdev->list_lock); 2271da177e4SLinus Torvalds 2281da177e4SLinus Torvalds sdev->sdev_gendev.parent = get_device(&starget->dev); 2291da177e4SLinus Torvalds sdev->sdev_target = starget; 2301da177e4SLinus Torvalds 2311da177e4SLinus Torvalds /* usually NULL and set by ->slave_alloc instead */ 2321da177e4SLinus Torvalds sdev->hostdata = hostdata; 2331da177e4SLinus Torvalds 2341da177e4SLinus Torvalds /* if the device needs this changing, it may do so in the 2351da177e4SLinus Torvalds * slave_configure function */ 2361da177e4SLinus Torvalds sdev->max_device_blocked = SCSI_DEFAULT_DEVICE_BLOCKED; 2371da177e4SLinus Torvalds 2381da177e4SLinus Torvalds /* 2391da177e4SLinus Torvalds * Some low level driver could use device->type 2401da177e4SLinus Torvalds */ 2411da177e4SLinus Torvalds sdev->type = -1; 2421da177e4SLinus Torvalds 2431da177e4SLinus Torvalds /* 2441da177e4SLinus Torvalds * Assume that the device will have handshaking problems, 2451da177e4SLinus Torvalds * and then fix this field later if it turns out it 2461da177e4SLinus Torvalds * doesn't 2471da177e4SLinus Torvalds */ 2481da177e4SLinus Torvalds sdev->borken = 1; 2491da177e4SLinus Torvalds 2501da177e4SLinus Torvalds sdev->request_queue = scsi_alloc_queue(sdev); 2511da177e4SLinus Torvalds if (!sdev->request_queue) { 2521da177e4SLinus Torvalds /* release fn is set up in scsi_sysfs_device_initialise, so 2531da177e4SLinus Torvalds * have to free and put manually here */ 2541da177e4SLinus Torvalds put_device(&starget->dev); 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 struct Scsi_Host *shost = dev_to_shost(parent); 292a283bd37SJames Bottomley 293a283bd37SJames Bottomley if (shost->hostt->target_destroy) 294a283bd37SJames Bottomley shost->hostt->target_destroy(starget); 2951da177e4SLinus Torvalds kfree(starget); 2961da177e4SLinus Torvalds put_device(parent); 2971da177e4SLinus Torvalds } 2981da177e4SLinus Torvalds 2991da177e4SLinus Torvalds int scsi_is_target_device(const struct device *dev) 3001da177e4SLinus Torvalds { 3011da177e4SLinus Torvalds return dev->release == scsi_target_dev_release; 3021da177e4SLinus Torvalds } 3031da177e4SLinus Torvalds EXPORT_SYMBOL(scsi_is_target_device); 3041da177e4SLinus Torvalds 3051da177e4SLinus Torvalds static struct scsi_target *__scsi_find_target(struct device *parent, 3061da177e4SLinus Torvalds int channel, uint id) 3071da177e4SLinus Torvalds { 3081da177e4SLinus Torvalds struct scsi_target *starget, *found_starget = NULL; 3091da177e4SLinus Torvalds struct Scsi_Host *shost = dev_to_shost(parent); 3101da177e4SLinus Torvalds /* 3111da177e4SLinus Torvalds * Search for an existing target for this sdev. 3121da177e4SLinus Torvalds */ 3131da177e4SLinus Torvalds list_for_each_entry(starget, &shost->__targets, siblings) { 3141da177e4SLinus Torvalds if (starget->id == id && 3151da177e4SLinus Torvalds starget->channel == channel) { 3161da177e4SLinus Torvalds found_starget = starget; 3171da177e4SLinus Torvalds break; 3181da177e4SLinus Torvalds } 3191da177e4SLinus Torvalds } 3201da177e4SLinus Torvalds if (found_starget) 3211da177e4SLinus Torvalds get_device(&found_starget->dev); 3221da177e4SLinus Torvalds 3231da177e4SLinus Torvalds return found_starget; 3241da177e4SLinus Torvalds } 3251da177e4SLinus Torvalds 3261da177e4SLinus Torvalds static struct scsi_target *scsi_alloc_target(struct device *parent, 3271da177e4SLinus Torvalds int channel, uint id) 3281da177e4SLinus Torvalds { 3291da177e4SLinus Torvalds struct Scsi_Host *shost = dev_to_shost(parent); 3301da177e4SLinus Torvalds struct device *dev = NULL; 3311da177e4SLinus Torvalds unsigned long flags; 3321da177e4SLinus Torvalds const int size = sizeof(struct scsi_target) 3331da177e4SLinus Torvalds + shost->transportt->target_size; 3345c44cd2aSJames.Smart@Emulex.Com struct scsi_target *starget; 3351da177e4SLinus Torvalds struct scsi_target *found_target; 3361da177e4SLinus Torvalds 3375c44cd2aSJames.Smart@Emulex.Com starget = kmalloc(size, GFP_KERNEL); 3381da177e4SLinus Torvalds if (!starget) { 3391da177e4SLinus Torvalds printk(KERN_ERR "%s: allocation failure\n", __FUNCTION__); 3401da177e4SLinus Torvalds return NULL; 3411da177e4SLinus Torvalds } 3421da177e4SLinus Torvalds memset(starget, 0, size); 3431da177e4SLinus Torvalds dev = &starget->dev; 3441da177e4SLinus Torvalds device_initialize(dev); 3451da177e4SLinus Torvalds starget->reap_ref = 1; 3461da177e4SLinus Torvalds dev->parent = get_device(parent); 3471da177e4SLinus Torvalds dev->release = scsi_target_dev_release; 3481da177e4SLinus Torvalds sprintf(dev->bus_id, "target%d:%d:%d", 3491da177e4SLinus Torvalds shost->host_no, channel, id); 3501da177e4SLinus Torvalds starget->id = id; 3511da177e4SLinus Torvalds starget->channel = channel; 3521da177e4SLinus Torvalds INIT_LIST_HEAD(&starget->siblings); 3531da177e4SLinus Torvalds INIT_LIST_HEAD(&starget->devices); 3541da177e4SLinus Torvalds spin_lock_irqsave(shost->host_lock, flags); 3551da177e4SLinus Torvalds 3561da177e4SLinus Torvalds found_target = __scsi_find_target(parent, channel, id); 3571da177e4SLinus Torvalds if (found_target) 3581da177e4SLinus Torvalds goto found; 3591da177e4SLinus Torvalds 3601da177e4SLinus Torvalds list_add_tail(&starget->siblings, &shost->__targets); 3611da177e4SLinus Torvalds spin_unlock_irqrestore(shost->host_lock, flags); 3621da177e4SLinus Torvalds /* allocate and add */ 363a283bd37SJames Bottomley transport_setup_device(dev); 364a283bd37SJames Bottomley device_add(dev); 365a283bd37SJames Bottomley transport_add_device(dev); 366a283bd37SJames Bottomley if (shost->hostt->target_alloc) { 367a283bd37SJames Bottomley int error = shost->hostt->target_alloc(starget); 368a283bd37SJames Bottomley 369a283bd37SJames Bottomley if(error) { 370a283bd37SJames Bottomley dev_printk(KERN_ERR, dev, "target allocation failed, error %d\n", error); 371a283bd37SJames Bottomley /* don't want scsi_target_reap to do the final 372a283bd37SJames Bottomley * put because it will be under the host lock */ 373a283bd37SJames Bottomley get_device(dev); 374a283bd37SJames Bottomley scsi_target_reap(starget); 375a283bd37SJames Bottomley put_device(dev); 376a283bd37SJames Bottomley return NULL; 377a283bd37SJames Bottomley } 378a283bd37SJames Bottomley } 379a283bd37SJames Bottomley 3801da177e4SLinus Torvalds return starget; 3811da177e4SLinus Torvalds 3821da177e4SLinus Torvalds found: 3831da177e4SLinus Torvalds found_target->reap_ref++; 3841da177e4SLinus Torvalds spin_unlock_irqrestore(shost->host_lock, flags); 3851da177e4SLinus Torvalds put_device(parent); 3861da177e4SLinus Torvalds kfree(starget); 3871da177e4SLinus Torvalds return found_target; 3881da177e4SLinus Torvalds } 3891da177e4SLinus Torvalds 39065110b21SJames Bottomley static void scsi_target_reap_usercontext(void *data) 39165110b21SJames Bottomley { 39265110b21SJames Bottomley struct scsi_target *starget = data; 393863a930aSJames Bottomley struct Scsi_Host *shost = dev_to_shost(starget->dev.parent); 394863a930aSJames Bottomley unsigned long flags; 395863a930aSJames Bottomley 396863a930aSJames Bottomley spin_lock_irqsave(shost->host_lock, flags); 397863a930aSJames Bottomley 398863a930aSJames Bottomley if (--starget->reap_ref == 0 && list_empty(&starget->devices)) { 399863a930aSJames Bottomley list_del_init(&starget->siblings); 400863a930aSJames Bottomley spin_unlock_irqrestore(shost->host_lock, flags); 40104333393SJames Bottomley transport_remove_device(&starget->dev); 402863a930aSJames Bottomley device_del(&starget->dev); 40304333393SJames Bottomley transport_destroy_device(&starget->dev); 404863a930aSJames Bottomley put_device(&starget->dev); 405863a930aSJames Bottomley return; 406863a930aSJames Bottomley 407863a930aSJames Bottomley } 408863a930aSJames Bottomley spin_unlock_irqrestore(shost->host_lock, flags); 409863a930aSJames Bottomley 410863a930aSJames Bottomley return; 411863a930aSJames Bottomley } 412863a930aSJames Bottomley 4131da177e4SLinus Torvalds /** 4141da177e4SLinus Torvalds * scsi_target_reap - check to see if target is in use and destroy if not 4151da177e4SLinus Torvalds * 4161da177e4SLinus Torvalds * @starget: target to be checked 4171da177e4SLinus Torvalds * 4181da177e4SLinus Torvalds * This is used after removing a LUN or doing a last put of the target 4191da177e4SLinus Torvalds * it checks atomically that nothing is using the target and removes 4201da177e4SLinus Torvalds * it if so. 4211da177e4SLinus Torvalds */ 4221da177e4SLinus Torvalds void scsi_target_reap(struct scsi_target *starget) 4231da177e4SLinus Torvalds { 42465110b21SJames Bottomley scsi_execute_in_process_context(scsi_target_reap_usercontext, starget); 4251da177e4SLinus Torvalds } 4261da177e4SLinus Torvalds 4271da177e4SLinus Torvalds /** 4281da177e4SLinus Torvalds * scsi_probe_lun - probe a single LUN using a SCSI INQUIRY 42939216033SJames Bottomley * @sdev: scsi_device to probe 4301da177e4SLinus Torvalds * @inq_result: area to store the INQUIRY result 43139216033SJames Bottomley * @result_len: len of inq_result 4321da177e4SLinus Torvalds * @bflags: store any bflags found here 4331da177e4SLinus Torvalds * 4341da177e4SLinus Torvalds * Description: 43539216033SJames Bottomley * Probe the lun associated with @req using a standard SCSI INQUIRY; 4361da177e4SLinus Torvalds * 43739216033SJames Bottomley * If the INQUIRY is successful, zero is returned and the 4381da177e4SLinus Torvalds * INQUIRY data is in @inq_result; the scsi_level and INQUIRY length 439f64a181dSChristoph Hellwig * are copied to the scsi_device any flags value is stored in *@bflags. 4401da177e4SLinus Torvalds **/ 44139216033SJames Bottomley static int scsi_probe_lun(struct scsi_device *sdev, char *inq_result, 44239216033SJames Bottomley int result_len, int *bflags) 4431da177e4SLinus Torvalds { 4441da177e4SLinus Torvalds unsigned char scsi_cmd[MAX_COMMAND_SIZE]; 4451da177e4SLinus Torvalds int first_inquiry_len, try_inquiry_len, next_inquiry_len; 4461da177e4SLinus Torvalds int response_len = 0; 44739216033SJames Bottomley int pass, count, result; 4481da177e4SLinus Torvalds struct scsi_sense_hdr sshdr; 4491da177e4SLinus Torvalds 4501da177e4SLinus Torvalds *bflags = 0; 4511da177e4SLinus Torvalds 4521da177e4SLinus Torvalds /* Perform up to 3 passes. The first pass uses a conservative 4531da177e4SLinus Torvalds * transfer length of 36 unless sdev->inquiry_len specifies a 4541da177e4SLinus Torvalds * different value. */ 4551da177e4SLinus Torvalds first_inquiry_len = sdev->inquiry_len ? sdev->inquiry_len : 36; 4561da177e4SLinus Torvalds try_inquiry_len = first_inquiry_len; 4571da177e4SLinus Torvalds pass = 1; 4581da177e4SLinus Torvalds 4591da177e4SLinus Torvalds next_pass: 4609ccfc756SJames Bottomley SCSI_LOG_SCAN_BUS(3, sdev_printk(KERN_INFO, sdev, 4619ccfc756SJames Bottomley "scsi scan: INQUIRY pass %d length %d\n", 4629ccfc756SJames Bottomley pass, try_inquiry_len)); 4631da177e4SLinus Torvalds 4641da177e4SLinus Torvalds /* Each pass gets up to three chances to ignore Unit Attention */ 4651da177e4SLinus Torvalds for (count = 0; count < 3; ++count) { 4661da177e4SLinus Torvalds memset(scsi_cmd, 0, 6); 4671da177e4SLinus Torvalds scsi_cmd[0] = INQUIRY; 4681da177e4SLinus Torvalds scsi_cmd[4] = (unsigned char) try_inquiry_len; 4691da177e4SLinus Torvalds 4701da177e4SLinus Torvalds memset(inq_result, 0, try_inquiry_len); 47139216033SJames Bottomley 47239216033SJames Bottomley result = scsi_execute_req(sdev, scsi_cmd, DMA_FROM_DEVICE, 473ea73a9f2SJames Bottomley inq_result, try_inquiry_len, &sshdr, 4741da177e4SLinus Torvalds HZ / 2 + HZ * scsi_inq_timeout, 3); 4751da177e4SLinus Torvalds 4761da177e4SLinus Torvalds SCSI_LOG_SCAN_BUS(3, printk(KERN_INFO "scsi scan: INQUIRY %s " 4771da177e4SLinus Torvalds "with code 0x%x\n", 47839216033SJames Bottomley result ? "failed" : "successful", result)); 4791da177e4SLinus Torvalds 48039216033SJames Bottomley if (result) { 4811da177e4SLinus Torvalds /* 4821da177e4SLinus Torvalds * not-ready to ready transition [asc/ascq=0x28/0x0] 4831da177e4SLinus Torvalds * or power-on, reset [asc/ascq=0x29/0x0], continue. 4841da177e4SLinus Torvalds * INQUIRY should not yield UNIT_ATTENTION 4851da177e4SLinus Torvalds * but many buggy devices do so anyway. 4861da177e4SLinus Torvalds */ 48739216033SJames Bottomley if ((driver_byte(result) & DRIVER_SENSE) && 488ea73a9f2SJames Bottomley scsi_sense_valid(&sshdr)) { 4891da177e4SLinus Torvalds if ((sshdr.sense_key == UNIT_ATTENTION) && 4901da177e4SLinus Torvalds ((sshdr.asc == 0x28) || 4911da177e4SLinus Torvalds (sshdr.asc == 0x29)) && 4921da177e4SLinus Torvalds (sshdr.ascq == 0)) 4931da177e4SLinus Torvalds continue; 4941da177e4SLinus Torvalds } 4951da177e4SLinus Torvalds } 4961da177e4SLinus Torvalds break; 4971da177e4SLinus Torvalds } 4981da177e4SLinus Torvalds 49939216033SJames Bottomley if (result == 0) { 5001da177e4SLinus Torvalds response_len = (unsigned char) inq_result[4] + 5; 5011da177e4SLinus Torvalds if (response_len > 255) 5021da177e4SLinus Torvalds response_len = first_inquiry_len; /* sanity */ 5031da177e4SLinus Torvalds 5041da177e4SLinus Torvalds /* 5051da177e4SLinus Torvalds * Get any flags for this device. 5061da177e4SLinus Torvalds * 507f64a181dSChristoph Hellwig * XXX add a bflags to scsi_device, and replace the 508f64a181dSChristoph Hellwig * corresponding bit fields in scsi_device, so bflags 5091da177e4SLinus Torvalds * need not be passed as an argument. 5101da177e4SLinus Torvalds */ 5111da177e4SLinus Torvalds *bflags = scsi_get_device_flags(sdev, &inq_result[8], 5121da177e4SLinus Torvalds &inq_result[16]); 5131da177e4SLinus Torvalds 5141da177e4SLinus Torvalds /* When the first pass succeeds we gain information about 5151da177e4SLinus Torvalds * what larger transfer lengths might work. */ 5161da177e4SLinus Torvalds if (pass == 1) { 5171da177e4SLinus Torvalds if (BLIST_INQUIRY_36 & *bflags) 5181da177e4SLinus Torvalds next_inquiry_len = 36; 5191da177e4SLinus Torvalds else if (BLIST_INQUIRY_58 & *bflags) 5201da177e4SLinus Torvalds next_inquiry_len = 58; 5211da177e4SLinus Torvalds else if (sdev->inquiry_len) 5221da177e4SLinus Torvalds next_inquiry_len = sdev->inquiry_len; 5231da177e4SLinus Torvalds else 5241da177e4SLinus Torvalds next_inquiry_len = response_len; 5251da177e4SLinus Torvalds 5261da177e4SLinus Torvalds /* If more data is available perform the second pass */ 5271da177e4SLinus Torvalds if (next_inquiry_len > try_inquiry_len) { 5281da177e4SLinus Torvalds try_inquiry_len = next_inquiry_len; 5291da177e4SLinus Torvalds pass = 2; 5301da177e4SLinus Torvalds goto next_pass; 5311da177e4SLinus Torvalds } 5321da177e4SLinus Torvalds } 5331da177e4SLinus Torvalds 5341da177e4SLinus Torvalds } else if (pass == 2) { 5351da177e4SLinus Torvalds printk(KERN_INFO "scsi scan: %d byte inquiry failed. " 5361da177e4SLinus Torvalds "Consider BLIST_INQUIRY_36 for this device\n", 5371da177e4SLinus Torvalds try_inquiry_len); 5381da177e4SLinus Torvalds 5391da177e4SLinus Torvalds /* If this pass failed, the third pass goes back and transfers 5401da177e4SLinus Torvalds * the same amount as we successfully got in the first pass. */ 5411da177e4SLinus Torvalds try_inquiry_len = first_inquiry_len; 5421da177e4SLinus Torvalds pass = 3; 5431da177e4SLinus Torvalds goto next_pass; 5441da177e4SLinus Torvalds } 5451da177e4SLinus Torvalds 5461da177e4SLinus Torvalds /* If the last transfer attempt got an error, assume the 5471da177e4SLinus Torvalds * peripheral doesn't exist or is dead. */ 54839216033SJames Bottomley if (result) 54939216033SJames Bottomley return -EIO; 5501da177e4SLinus Torvalds 5511da177e4SLinus Torvalds /* Don't report any more data than the device says is valid */ 5521da177e4SLinus Torvalds sdev->inquiry_len = min(try_inquiry_len, response_len); 5531da177e4SLinus Torvalds 5541da177e4SLinus Torvalds /* 5551da177e4SLinus Torvalds * XXX Abort if the response length is less than 36? If less than 5561da177e4SLinus Torvalds * 32, the lookup of the device flags (above) could be invalid, 5571da177e4SLinus Torvalds * and it would be possible to take an incorrect action - we do 5581da177e4SLinus Torvalds * not want to hang because of a short INQUIRY. On the flip side, 5591da177e4SLinus Torvalds * if the device is spun down or becoming ready (and so it gives a 5601da177e4SLinus Torvalds * short INQUIRY), an abort here prevents any further use of the 5611da177e4SLinus Torvalds * device, including spin up. 5621da177e4SLinus Torvalds * 5631da177e4SLinus Torvalds * Related to the above issue: 5641da177e4SLinus Torvalds * 5651da177e4SLinus Torvalds * XXX Devices (disk or all?) should be sent a TEST UNIT READY, 5661da177e4SLinus Torvalds * and if not ready, sent a START_STOP to start (maybe spin up) and 5671da177e4SLinus Torvalds * then send the INQUIRY again, since the INQUIRY can change after 5681da177e4SLinus Torvalds * a device is initialized. 5691da177e4SLinus Torvalds * 5701da177e4SLinus Torvalds * Ideally, start a device if explicitly asked to do so. This 5711da177e4SLinus Torvalds * assumes that a device is spun up on power on, spun down on 5721da177e4SLinus Torvalds * request, and then spun up on request. 5731da177e4SLinus Torvalds */ 5741da177e4SLinus Torvalds 5751da177e4SLinus Torvalds /* 5761da177e4SLinus Torvalds * The scanning code needs to know the scsi_level, even if no 5771da177e4SLinus Torvalds * device is attached at LUN 0 (SCSI_SCAN_TARGET_PRESENT) so 5781da177e4SLinus Torvalds * non-zero LUNs can be scanned. 5791da177e4SLinus Torvalds */ 5801da177e4SLinus Torvalds sdev->scsi_level = inq_result[2] & 0x07; 5811da177e4SLinus Torvalds if (sdev->scsi_level >= 2 || 5821da177e4SLinus Torvalds (sdev->scsi_level == 1 && (inq_result[3] & 0x0f) == 1)) 5831da177e4SLinus Torvalds sdev->scsi_level++; 5846f3a2024SJames Bottomley sdev->sdev_target->scsi_level = sdev->scsi_level; 5851da177e4SLinus Torvalds 58639216033SJames Bottomley return 0; 5871da177e4SLinus Torvalds } 5881da177e4SLinus Torvalds 5891da177e4SLinus Torvalds /** 590f64a181dSChristoph Hellwig * scsi_add_lun - allocate and fully initialze a scsi_device 591f64a181dSChristoph Hellwig * @sdevscan: holds information to be stored in the new scsi_device 592f64a181dSChristoph Hellwig * @sdevnew: store the address of the newly allocated scsi_device 5931da177e4SLinus Torvalds * @inq_result: holds the result of a previous INQUIRY to the LUN 5941da177e4SLinus Torvalds * @bflags: black/white list flag 5951da177e4SLinus Torvalds * 5961da177e4SLinus Torvalds * Description: 597f64a181dSChristoph Hellwig * Allocate and initialize a scsi_device matching sdevscan. Optionally 5981da177e4SLinus Torvalds * set fields based on values in *@bflags. If @sdevnew is not 599f64a181dSChristoph Hellwig * NULL, store the address of the new scsi_device in *@sdevnew (needed 6001da177e4SLinus Torvalds * when scanning a particular LUN). 6011da177e4SLinus Torvalds * 6021da177e4SLinus Torvalds * Return: 603f64a181dSChristoph Hellwig * SCSI_SCAN_NO_RESPONSE: could not allocate or setup a scsi_device 604f64a181dSChristoph Hellwig * SCSI_SCAN_LUN_PRESENT: a new scsi_device was allocated and initialized 6051da177e4SLinus Torvalds **/ 6061da177e4SLinus Torvalds static int scsi_add_lun(struct scsi_device *sdev, char *inq_result, int *bflags) 6071da177e4SLinus Torvalds { 6081da177e4SLinus Torvalds /* 6091da177e4SLinus Torvalds * XXX do not save the inquiry, since it can change underneath us, 6101da177e4SLinus Torvalds * save just vendor/model/rev. 6111da177e4SLinus Torvalds * 6121da177e4SLinus Torvalds * Rather than save it and have an ioctl that retrieves the saved 6131da177e4SLinus Torvalds * value, have an ioctl that executes the same INQUIRY code used 6141da177e4SLinus Torvalds * in scsi_probe_lun, let user level programs doing INQUIRY 6151da177e4SLinus Torvalds * scanning run at their own risk, or supply a user level program 6161da177e4SLinus Torvalds * that can correctly scan. 6171da177e4SLinus Torvalds */ 6181da177e4SLinus Torvalds sdev->inquiry = kmalloc(sdev->inquiry_len, GFP_ATOMIC); 6191da177e4SLinus Torvalds if (sdev->inquiry == NULL) { 6201da177e4SLinus Torvalds return SCSI_SCAN_NO_RESPONSE; 6211da177e4SLinus Torvalds } 6221da177e4SLinus Torvalds 6231da177e4SLinus Torvalds memcpy(sdev->inquiry, inq_result, sdev->inquiry_len); 6241da177e4SLinus Torvalds sdev->vendor = (char *) (sdev->inquiry + 8); 6251da177e4SLinus Torvalds sdev->model = (char *) (sdev->inquiry + 16); 6261da177e4SLinus Torvalds sdev->rev = (char *) (sdev->inquiry + 32); 6271da177e4SLinus Torvalds 6281da177e4SLinus Torvalds if (*bflags & BLIST_ISROM) { 6291da177e4SLinus Torvalds /* 6301da177e4SLinus Torvalds * It would be better to modify sdev->type, and set 6311da177e4SLinus Torvalds * sdev->removable, but then the print_inquiry() output 6321da177e4SLinus Torvalds * would not show TYPE_ROM; if print_inquiry() is removed 6331da177e4SLinus Torvalds * the issue goes away. 6341da177e4SLinus Torvalds */ 6351da177e4SLinus Torvalds inq_result[0] = TYPE_ROM; 6361da177e4SLinus Torvalds inq_result[1] |= 0x80; /* removable */ 6371da177e4SLinus Torvalds } else if (*bflags & BLIST_NO_ULD_ATTACH) 6381da177e4SLinus Torvalds sdev->no_uld_attach = 1; 6391da177e4SLinus Torvalds 6401da177e4SLinus Torvalds switch (sdev->type = (inq_result[0] & 0x1f)) { 6411da177e4SLinus Torvalds case TYPE_TAPE: 6421da177e4SLinus Torvalds case TYPE_DISK: 6431da177e4SLinus Torvalds case TYPE_PRINTER: 6441da177e4SLinus Torvalds case TYPE_MOD: 6451da177e4SLinus Torvalds case TYPE_PROCESSOR: 6461da177e4SLinus Torvalds case TYPE_SCANNER: 6471da177e4SLinus Torvalds case TYPE_MEDIUM_CHANGER: 6481da177e4SLinus Torvalds case TYPE_ENCLOSURE: 6491da177e4SLinus Torvalds case TYPE_COMM: 650631e8a13SAl Viro case TYPE_RBC: 6511da177e4SLinus Torvalds sdev->writeable = 1; 6521da177e4SLinus Torvalds break; 6531da177e4SLinus Torvalds case TYPE_WORM: 6541da177e4SLinus Torvalds case TYPE_ROM: 6551da177e4SLinus Torvalds sdev->writeable = 0; 6561da177e4SLinus Torvalds break; 6571da177e4SLinus Torvalds default: 6581da177e4SLinus Torvalds printk(KERN_INFO "scsi: unknown device type %d\n", sdev->type); 6591da177e4SLinus Torvalds } 6601da177e4SLinus Torvalds 6611da177e4SLinus Torvalds print_inquiry(inq_result); 6621da177e4SLinus Torvalds 6631da177e4SLinus Torvalds /* 6641da177e4SLinus Torvalds * For a peripheral qualifier (PQ) value of 1 (001b), the SCSI 6651da177e4SLinus Torvalds * spec says: The device server is capable of supporting the 6661da177e4SLinus Torvalds * specified peripheral device type on this logical unit. However, 6671da177e4SLinus Torvalds * the physical device is not currently connected to this logical 6681da177e4SLinus Torvalds * unit. 6691da177e4SLinus Torvalds * 6701da177e4SLinus Torvalds * The above is vague, as it implies that we could treat 001 and 6711da177e4SLinus Torvalds * 011 the same. Stay compatible with previous code, and create a 672f64a181dSChristoph Hellwig * scsi_device for a PQ of 1 6731da177e4SLinus Torvalds * 6741da177e4SLinus Torvalds * Don't set the device offline here; rather let the upper 6751da177e4SLinus Torvalds * level drivers eval the PQ to decide whether they should 6761da177e4SLinus Torvalds * attach. So remove ((inq_result[0] >> 5) & 7) == 1 check. 6771da177e4SLinus Torvalds */ 6781da177e4SLinus Torvalds 6791da177e4SLinus Torvalds sdev->inq_periph_qual = (inq_result[0] >> 5) & 7; 6801da177e4SLinus Torvalds sdev->removable = (0x80 & inq_result[1]) >> 7; 6811da177e4SLinus Torvalds sdev->lockable = sdev->removable; 6821da177e4SLinus Torvalds sdev->soft_reset = (inq_result[7] & 1) && ((inq_result[3] & 7) == 2); 6831da177e4SLinus Torvalds 6841da177e4SLinus Torvalds if (sdev->scsi_level >= SCSI_3 || (sdev->inquiry_len > 56 && 6851da177e4SLinus Torvalds inq_result[56] & 0x04)) 6861da177e4SLinus Torvalds sdev->ppr = 1; 6871da177e4SLinus Torvalds if (inq_result[7] & 0x60) 6881da177e4SLinus Torvalds sdev->wdtr = 1; 6891da177e4SLinus Torvalds if (inq_result[7] & 0x10) 6901da177e4SLinus Torvalds sdev->sdtr = 1; 6911da177e4SLinus Torvalds 6921da177e4SLinus Torvalds sprintf(sdev->devfs_name, "scsi/host%d/bus%d/target%d/lun%d", 6931da177e4SLinus Torvalds sdev->host->host_no, sdev->channel, 6941da177e4SLinus Torvalds sdev->id, sdev->lun); 6951da177e4SLinus Torvalds 6961da177e4SLinus Torvalds /* 6971da177e4SLinus Torvalds * End driverfs/devfs code. 6981da177e4SLinus Torvalds */ 6991da177e4SLinus Torvalds 7001da177e4SLinus Torvalds if ((sdev->scsi_level >= SCSI_2) && (inq_result[7] & 2) && 7011da177e4SLinus Torvalds !(*bflags & BLIST_NOTQ)) 7021da177e4SLinus Torvalds sdev->tagged_supported = 1; 7031da177e4SLinus Torvalds /* 7041da177e4SLinus Torvalds * Some devices (Texel CD ROM drives) have handshaking problems 7051da177e4SLinus Torvalds * when used with the Seagate controllers. borken is initialized 7061da177e4SLinus Torvalds * to 1, and then set it to 0 here. 7071da177e4SLinus Torvalds */ 7081da177e4SLinus Torvalds if ((*bflags & BLIST_BORKEN) == 0) 7091da177e4SLinus Torvalds sdev->borken = 0; 7101da177e4SLinus Torvalds 7111da177e4SLinus Torvalds /* 7121da177e4SLinus Torvalds * Apparently some really broken devices (contrary to the SCSI 7131da177e4SLinus Torvalds * standards) need to be selected without asserting ATN 7141da177e4SLinus Torvalds */ 7151da177e4SLinus Torvalds if (*bflags & BLIST_SELECT_NO_ATN) 7161da177e4SLinus Torvalds sdev->select_no_atn = 1; 7171da177e4SLinus Torvalds 7181da177e4SLinus Torvalds /* 7191da177e4SLinus Torvalds * Some devices may not want to have a start command automatically 7201da177e4SLinus Torvalds * issued when a device is added. 7211da177e4SLinus Torvalds */ 7221da177e4SLinus Torvalds if (*bflags & BLIST_NOSTARTONADD) 7231da177e4SLinus Torvalds sdev->no_start_on_add = 1; 7241da177e4SLinus Torvalds 7251da177e4SLinus Torvalds if (*bflags & BLIST_SINGLELUN) 7261da177e4SLinus Torvalds sdev->single_lun = 1; 7271da177e4SLinus Torvalds 7281da177e4SLinus Torvalds 7291da177e4SLinus Torvalds sdev->use_10_for_rw = 1; 7301da177e4SLinus Torvalds 7311da177e4SLinus Torvalds if (*bflags & BLIST_MS_SKIP_PAGE_08) 7321da177e4SLinus Torvalds sdev->skip_ms_page_8 = 1; 7331da177e4SLinus Torvalds 7341da177e4SLinus Torvalds if (*bflags & BLIST_MS_SKIP_PAGE_3F) 7351da177e4SLinus Torvalds sdev->skip_ms_page_3f = 1; 7361da177e4SLinus Torvalds 7371da177e4SLinus Torvalds if (*bflags & BLIST_USE_10_BYTE_MS) 7381da177e4SLinus Torvalds sdev->use_10_for_ms = 1; 7391da177e4SLinus Torvalds 7401da177e4SLinus Torvalds /* set the device running here so that slave configure 7411da177e4SLinus Torvalds * may do I/O */ 7421da177e4SLinus Torvalds scsi_device_set_state(sdev, SDEV_RUNNING); 7431da177e4SLinus Torvalds 7441da177e4SLinus Torvalds if (*bflags & BLIST_MS_192_BYTES_FOR_3F) 7451da177e4SLinus Torvalds sdev->use_192_bytes_for_3f = 1; 7461da177e4SLinus Torvalds 7471da177e4SLinus Torvalds if (*bflags & BLIST_NOT_LOCKABLE) 7481da177e4SLinus Torvalds sdev->lockable = 0; 7491da177e4SLinus Torvalds 7501da177e4SLinus Torvalds if (*bflags & BLIST_RETRY_HWERROR) 7511da177e4SLinus Torvalds sdev->retry_hwerror = 1; 7521da177e4SLinus Torvalds 7531da177e4SLinus Torvalds transport_configure_device(&sdev->sdev_gendev); 7541da177e4SLinus Torvalds 755*93805091SChristoph Hellwig if (sdev->host->hostt->slave_configure) { 756*93805091SChristoph Hellwig int ret = sdev->host->hostt->slave_configure(sdev); 757*93805091SChristoph Hellwig if (ret) { 758*93805091SChristoph Hellwig /* 759*93805091SChristoph Hellwig * if LLDD reports slave not present, don't clutter 760*93805091SChristoph Hellwig * console with alloc failure messages 761*93805091SChristoph Hellwig */ 762*93805091SChristoph Hellwig if (ret != -ENXIO) { 763*93805091SChristoph Hellwig sdev_printk(KERN_ERR, sdev, 764*93805091SChristoph Hellwig "failed to configure device\n"); 765*93805091SChristoph Hellwig } 766*93805091SChristoph Hellwig return SCSI_SCAN_NO_RESPONSE; 767*93805091SChristoph Hellwig } 768*93805091SChristoph Hellwig } 7691da177e4SLinus Torvalds 7701da177e4SLinus Torvalds /* 7711da177e4SLinus Torvalds * Ok, the device is now all set up, we can 7721da177e4SLinus Torvalds * register it and tell the rest of the kernel 7731da177e4SLinus Torvalds * about it. 7741da177e4SLinus Torvalds */ 775b24b1033SAlan Stern if (scsi_sysfs_add_sdev(sdev) != 0) 776b24b1033SAlan Stern return SCSI_SCAN_NO_RESPONSE; 7771da177e4SLinus Torvalds 7781da177e4SLinus Torvalds return SCSI_SCAN_LUN_PRESENT; 7791da177e4SLinus Torvalds } 7801da177e4SLinus Torvalds 7816f3a2024SJames Bottomley static inline void scsi_destroy_sdev(struct scsi_device *sdev) 7826f3a2024SJames Bottomley { 7836f3a2024SJames Bottomley if (sdev->host->hostt->slave_destroy) 7846f3a2024SJames Bottomley sdev->host->hostt->slave_destroy(sdev); 7856f3a2024SJames Bottomley transport_destroy_device(&sdev->sdev_gendev); 7866f3a2024SJames Bottomley put_device(&sdev->sdev_gendev); 7876f3a2024SJames Bottomley } 7886f3a2024SJames Bottomley 7896f3a2024SJames Bottomley 7901da177e4SLinus Torvalds /** 7911da177e4SLinus Torvalds * scsi_probe_and_add_lun - probe a LUN, if a LUN is found add it 7921da177e4SLinus Torvalds * @starget: pointer to target device structure 7931da177e4SLinus Torvalds * @lun: LUN of target device 794f64a181dSChristoph Hellwig * @sdevscan: probe the LUN corresponding to this scsi_device 795f64a181dSChristoph Hellwig * @sdevnew: store the value of any new scsi_device allocated 7961da177e4SLinus Torvalds * @bflagsp: store bflags here if not NULL 7971da177e4SLinus Torvalds * 7981da177e4SLinus Torvalds * Description: 7991da177e4SLinus Torvalds * Call scsi_probe_lun, if a LUN with an attached device is found, 8001da177e4SLinus Torvalds * allocate and set it up by calling scsi_add_lun. 8011da177e4SLinus Torvalds * 8021da177e4SLinus Torvalds * Return: 803f64a181dSChristoph Hellwig * SCSI_SCAN_NO_RESPONSE: could not allocate or setup a scsi_device 8041da177e4SLinus Torvalds * SCSI_SCAN_TARGET_PRESENT: target responded, but no device is 8051da177e4SLinus Torvalds * attached at the LUN 806f64a181dSChristoph Hellwig * SCSI_SCAN_LUN_PRESENT: a new scsi_device was allocated and initialized 8071da177e4SLinus Torvalds **/ 8081da177e4SLinus Torvalds static int scsi_probe_and_add_lun(struct scsi_target *starget, 8091da177e4SLinus Torvalds uint lun, int *bflagsp, 8101da177e4SLinus Torvalds struct scsi_device **sdevp, int rescan, 8111da177e4SLinus Torvalds void *hostdata) 8121da177e4SLinus Torvalds { 8131da177e4SLinus Torvalds struct scsi_device *sdev; 8141da177e4SLinus Torvalds unsigned char *result; 81539216033SJames Bottomley int bflags, res = SCSI_SCAN_NO_RESPONSE, result_len = 256; 8161da177e4SLinus Torvalds struct Scsi_Host *shost = dev_to_shost(starget->dev.parent); 8171da177e4SLinus Torvalds 8181da177e4SLinus Torvalds /* 8191da177e4SLinus Torvalds * The rescan flag is used as an optimization, the first scan of a 8201da177e4SLinus Torvalds * host adapter calls into here with rescan == 0. 8211da177e4SLinus Torvalds */ 8221da177e4SLinus Torvalds sdev = scsi_device_lookup_by_target(starget, lun); 8231da177e4SLinus Torvalds if (sdev) { 8246f3a2024SJames Bottomley if (rescan || sdev->sdev_state != SDEV_CREATED) { 8251da177e4SLinus Torvalds SCSI_LOG_SCAN_BUS(3, printk(KERN_INFO 8261da177e4SLinus Torvalds "scsi scan: device exists on %s\n", 8271da177e4SLinus Torvalds sdev->sdev_gendev.bus_id)); 8281da177e4SLinus Torvalds if (sdevp) 8291da177e4SLinus Torvalds *sdevp = sdev; 8301da177e4SLinus Torvalds else 8311da177e4SLinus Torvalds scsi_device_put(sdev); 8321da177e4SLinus Torvalds 8331da177e4SLinus Torvalds if (bflagsp) 8341da177e4SLinus Torvalds *bflagsp = scsi_get_device_flags(sdev, 8351da177e4SLinus Torvalds sdev->vendor, 8361da177e4SLinus Torvalds sdev->model); 8371da177e4SLinus Torvalds return SCSI_SCAN_LUN_PRESENT; 8381da177e4SLinus Torvalds } 8396f3a2024SJames Bottomley scsi_device_put(sdev); 8406f3a2024SJames Bottomley } else 8411da177e4SLinus Torvalds sdev = scsi_alloc_sdev(starget, lun, hostdata); 8421da177e4SLinus Torvalds if (!sdev) 8431da177e4SLinus Torvalds goto out; 84439216033SJames Bottomley 84539216033SJames Bottomley result = kmalloc(result_len, GFP_ATOMIC | 846bc86120aSAl Viro ((shost->unchecked_isa_dma) ? __GFP_DMA : 0)); 8471da177e4SLinus Torvalds if (!result) 84839216033SJames Bottomley goto out_free_sdev; 8491da177e4SLinus Torvalds 85039216033SJames Bottomley if (scsi_probe_lun(sdev, result, result_len, &bflags)) 8511da177e4SLinus Torvalds goto out_free_result; 8521da177e4SLinus Torvalds 8531da177e4SLinus Torvalds /* 8541da177e4SLinus Torvalds * result contains valid SCSI INQUIRY data. 8551da177e4SLinus Torvalds */ 8561da177e4SLinus Torvalds if ((result[0] >> 5) == 3) { 8571da177e4SLinus Torvalds /* 8581da177e4SLinus Torvalds * For a Peripheral qualifier 3 (011b), the SCSI 8591da177e4SLinus Torvalds * spec says: The device server is not capable of 8601da177e4SLinus Torvalds * supporting a physical device on this logical 8611da177e4SLinus Torvalds * unit. 8621da177e4SLinus Torvalds * 8631da177e4SLinus Torvalds * For disks, this implies that there is no 8641da177e4SLinus Torvalds * logical disk configured at sdev->lun, but there 8651da177e4SLinus Torvalds * is a target id responding. 8661da177e4SLinus Torvalds */ 8671da177e4SLinus Torvalds SCSI_LOG_SCAN_BUS(3, printk(KERN_INFO 8681da177e4SLinus Torvalds "scsi scan: peripheral qualifier of 3," 8691da177e4SLinus Torvalds " no device added\n")); 8701da177e4SLinus Torvalds res = SCSI_SCAN_TARGET_PRESENT; 8711da177e4SLinus Torvalds goto out_free_result; 8721da177e4SLinus Torvalds } 8731da177e4SLinus Torvalds 8741da177e4SLinus Torvalds res = scsi_add_lun(sdev, result, &bflags); 8751da177e4SLinus Torvalds if (res == SCSI_SCAN_LUN_PRESENT) { 8761da177e4SLinus Torvalds if (bflags & BLIST_KEY) { 8771da177e4SLinus Torvalds sdev->lockable = 0; 87839216033SJames Bottomley scsi_unlock_floptical(sdev, result); 8791da177e4SLinus Torvalds } 8801da177e4SLinus Torvalds if (bflagsp) 8811da177e4SLinus Torvalds *bflagsp = bflags; 8821da177e4SLinus Torvalds } 8831da177e4SLinus Torvalds 8841da177e4SLinus Torvalds out_free_result: 8851da177e4SLinus Torvalds kfree(result); 8861da177e4SLinus Torvalds out_free_sdev: 8871da177e4SLinus Torvalds if (res == SCSI_SCAN_LUN_PRESENT) { 8881da177e4SLinus Torvalds if (sdevp) { 889b70d37bfSAlan Stern if (scsi_device_get(sdev) == 0) { 8901da177e4SLinus Torvalds *sdevp = sdev; 891b70d37bfSAlan Stern } else { 892b70d37bfSAlan Stern __scsi_remove_device(sdev); 893b70d37bfSAlan Stern res = SCSI_SCAN_NO_RESPONSE; 894b70d37bfSAlan Stern } 8951da177e4SLinus Torvalds } 8966f3a2024SJames Bottomley } else 8976f3a2024SJames Bottomley scsi_destroy_sdev(sdev); 8981da177e4SLinus Torvalds out: 8991da177e4SLinus Torvalds return res; 9001da177e4SLinus Torvalds } 9011da177e4SLinus Torvalds 9021da177e4SLinus Torvalds /** 9031da177e4SLinus Torvalds * scsi_sequential_lun_scan - sequentially scan a SCSI target 9041da177e4SLinus Torvalds * @starget: pointer to target structure to scan 9051da177e4SLinus Torvalds * @bflags: black/white list flag for LUN 0 9061da177e4SLinus Torvalds * @lun0_res: result of scanning LUN 0 9071da177e4SLinus Torvalds * 9081da177e4SLinus Torvalds * Description: 9091da177e4SLinus Torvalds * Generally, scan from LUN 1 (LUN 0 is assumed to already have been 9101da177e4SLinus Torvalds * scanned) to some maximum lun until a LUN is found with no device 9111da177e4SLinus Torvalds * attached. Use the bflags to figure out any oddities. 9121da177e4SLinus Torvalds * 9131da177e4SLinus Torvalds * Modifies sdevscan->lun. 9141da177e4SLinus Torvalds **/ 9151da177e4SLinus Torvalds static void scsi_sequential_lun_scan(struct scsi_target *starget, 9161da177e4SLinus Torvalds int bflags, int lun0_res, int scsi_level, 9171da177e4SLinus Torvalds int rescan) 9181da177e4SLinus Torvalds { 9191da177e4SLinus Torvalds unsigned int sparse_lun, lun, max_dev_lun; 9201da177e4SLinus Torvalds struct Scsi_Host *shost = dev_to_shost(starget->dev.parent); 9211da177e4SLinus Torvalds 9221da177e4SLinus Torvalds SCSI_LOG_SCAN_BUS(3, printk(KERN_INFO "scsi scan: Sequential scan of" 9231da177e4SLinus Torvalds "%s\n", starget->dev.bus_id)); 9241da177e4SLinus Torvalds 9251da177e4SLinus Torvalds max_dev_lun = min(max_scsi_luns, shost->max_lun); 9261da177e4SLinus Torvalds /* 9271da177e4SLinus Torvalds * If this device is known to support sparse multiple units, 9281da177e4SLinus Torvalds * override the other settings, and scan all of them. Normally, 9291da177e4SLinus Torvalds * SCSI-3 devices should be scanned via the REPORT LUNS. 9301da177e4SLinus Torvalds */ 9311da177e4SLinus Torvalds if (bflags & BLIST_SPARSELUN) { 9321da177e4SLinus Torvalds max_dev_lun = shost->max_lun; 9331da177e4SLinus Torvalds sparse_lun = 1; 9341da177e4SLinus Torvalds } else 9351da177e4SLinus Torvalds sparse_lun = 0; 9361da177e4SLinus Torvalds 9371da177e4SLinus Torvalds /* 9381da177e4SLinus Torvalds * If not sparse lun and no device attached at LUN 0 do not scan 9391da177e4SLinus Torvalds * any further. 9401da177e4SLinus Torvalds */ 9411da177e4SLinus Torvalds if (!sparse_lun && (lun0_res != SCSI_SCAN_LUN_PRESENT)) 9421da177e4SLinus Torvalds return; 9431da177e4SLinus Torvalds 9441da177e4SLinus Torvalds /* 9451da177e4SLinus Torvalds * If less than SCSI_1_CSS, and no special lun scaning, stop 9461da177e4SLinus Torvalds * scanning; this matches 2.4 behaviour, but could just be a bug 9471da177e4SLinus Torvalds * (to continue scanning a SCSI_1_CSS device). 9481da177e4SLinus Torvalds * 9491da177e4SLinus Torvalds * This test is broken. We might not have any device on lun0 for 9501da177e4SLinus Torvalds * a sparselun device, and if that's the case then how would we 9511da177e4SLinus Torvalds * know the real scsi_level, eh? It might make sense to just not 9521da177e4SLinus Torvalds * scan any SCSI_1 device for non-0 luns, but that check would best 9531da177e4SLinus Torvalds * go into scsi_alloc_sdev() and just have it return null when asked 9541da177e4SLinus Torvalds * to alloc an sdev for lun > 0 on an already found SCSI_1 device. 9551da177e4SLinus Torvalds * 9561da177e4SLinus Torvalds if ((sdevscan->scsi_level < SCSI_1_CCS) && 9571da177e4SLinus Torvalds ((bflags & (BLIST_FORCELUN | BLIST_SPARSELUN | BLIST_MAX5LUN)) 9581da177e4SLinus Torvalds == 0)) 9591da177e4SLinus Torvalds return; 9601da177e4SLinus Torvalds */ 9611da177e4SLinus Torvalds /* 9621da177e4SLinus Torvalds * If this device is known to support multiple units, override 9631da177e4SLinus Torvalds * the other settings, and scan all of them. 9641da177e4SLinus Torvalds */ 9651da177e4SLinus Torvalds if (bflags & BLIST_FORCELUN) 9661da177e4SLinus Torvalds max_dev_lun = shost->max_lun; 9671da177e4SLinus Torvalds /* 9681da177e4SLinus Torvalds * REGAL CDC-4X: avoid hang after LUN 4 9691da177e4SLinus Torvalds */ 9701da177e4SLinus Torvalds if (bflags & BLIST_MAX5LUN) 9711da177e4SLinus Torvalds max_dev_lun = min(5U, max_dev_lun); 9721da177e4SLinus Torvalds /* 9731da177e4SLinus Torvalds * Do not scan SCSI-2 or lower device past LUN 7, unless 9741da177e4SLinus Torvalds * BLIST_LARGELUN. 9751da177e4SLinus Torvalds */ 9761da177e4SLinus Torvalds if (scsi_level < SCSI_3 && !(bflags & BLIST_LARGELUN)) 9771da177e4SLinus Torvalds max_dev_lun = min(8U, max_dev_lun); 9781da177e4SLinus Torvalds 9791da177e4SLinus Torvalds /* 9801da177e4SLinus Torvalds * We have already scanned LUN 0, so start at LUN 1. Keep scanning 9811da177e4SLinus Torvalds * until we reach the max, or no LUN is found and we are not 9821da177e4SLinus Torvalds * sparse_lun. 9831da177e4SLinus Torvalds */ 9841da177e4SLinus Torvalds for (lun = 1; lun < max_dev_lun; ++lun) 9851da177e4SLinus Torvalds if ((scsi_probe_and_add_lun(starget, lun, NULL, NULL, rescan, 9861da177e4SLinus Torvalds NULL) != SCSI_SCAN_LUN_PRESENT) && 9871da177e4SLinus Torvalds !sparse_lun) 9881da177e4SLinus Torvalds return; 9891da177e4SLinus Torvalds } 9901da177e4SLinus Torvalds 9911da177e4SLinus Torvalds /** 9921da177e4SLinus Torvalds * scsilun_to_int: convert a scsi_lun to an int 9931da177e4SLinus Torvalds * @scsilun: struct scsi_lun to be converted. 9941da177e4SLinus Torvalds * 9951da177e4SLinus Torvalds * Description: 9961da177e4SLinus Torvalds * Convert @scsilun from a struct scsi_lun to a four byte host byte-ordered 9971da177e4SLinus Torvalds * integer, and return the result. The caller must check for 9981da177e4SLinus Torvalds * truncation before using this function. 9991da177e4SLinus Torvalds * 10001da177e4SLinus Torvalds * Notes: 10011da177e4SLinus Torvalds * The struct scsi_lun is assumed to be four levels, with each level 10021da177e4SLinus Torvalds * effectively containing a SCSI byte-ordered (big endian) short; the 10031da177e4SLinus Torvalds * addressing bits of each level are ignored (the highest two bits). 10041da177e4SLinus Torvalds * For a description of the LUN format, post SCSI-3 see the SCSI 10051da177e4SLinus Torvalds * Architecture Model, for SCSI-3 see the SCSI Controller Commands. 10061da177e4SLinus Torvalds * 10071da177e4SLinus Torvalds * Given a struct scsi_lun of: 0a 04 0b 03 00 00 00 00, this function returns 10081da177e4SLinus Torvalds * the integer: 0x0b030a04 10091da177e4SLinus Torvalds **/ 10101da177e4SLinus Torvalds static int scsilun_to_int(struct scsi_lun *scsilun) 10111da177e4SLinus Torvalds { 10121da177e4SLinus Torvalds int i; 10131da177e4SLinus Torvalds unsigned int lun; 10141da177e4SLinus Torvalds 10151da177e4SLinus Torvalds lun = 0; 10161da177e4SLinus Torvalds for (i = 0; i < sizeof(lun); i += 2) 10171da177e4SLinus Torvalds lun = lun | (((scsilun->scsi_lun[i] << 8) | 10181da177e4SLinus Torvalds scsilun->scsi_lun[i + 1]) << (i * 8)); 10191da177e4SLinus Torvalds return lun; 10201da177e4SLinus Torvalds } 10211da177e4SLinus Torvalds 10221da177e4SLinus Torvalds /** 10232f4701d8SJames.Smart@Emulex.Com * int_to_scsilun: reverts an int into a scsi_lun 10242f4701d8SJames.Smart@Emulex.Com * @int: integer to be reverted 10252f4701d8SJames.Smart@Emulex.Com * @scsilun: struct scsi_lun to be set. 10262f4701d8SJames.Smart@Emulex.Com * 10272f4701d8SJames.Smart@Emulex.Com * Description: 10282f4701d8SJames.Smart@Emulex.Com * Reverts the functionality of the scsilun_to_int, which packed 10292f4701d8SJames.Smart@Emulex.Com * an 8-byte lun value into an int. This routine unpacks the int 10302f4701d8SJames.Smart@Emulex.Com * back into the lun value. 10312f4701d8SJames.Smart@Emulex.Com * Note: the scsilun_to_int() routine does not truly handle all 10322f4701d8SJames.Smart@Emulex.Com * 8bytes of the lun value. This functions restores only as much 10332f4701d8SJames.Smart@Emulex.Com * as was set by the routine. 10342f4701d8SJames.Smart@Emulex.Com * 10352f4701d8SJames.Smart@Emulex.Com * Notes: 10362f4701d8SJames.Smart@Emulex.Com * Given an integer : 0x0b030a04, this function returns a 10372f4701d8SJames.Smart@Emulex.Com * scsi_lun of : struct scsi_lun of: 0a 04 0b 03 00 00 00 00 10382f4701d8SJames.Smart@Emulex.Com * 10392f4701d8SJames.Smart@Emulex.Com **/ 10402f4701d8SJames.Smart@Emulex.Com void int_to_scsilun(unsigned int lun, struct scsi_lun *scsilun) 10412f4701d8SJames.Smart@Emulex.Com { 10422f4701d8SJames.Smart@Emulex.Com int i; 10432f4701d8SJames.Smart@Emulex.Com 10442f4701d8SJames.Smart@Emulex.Com memset(scsilun->scsi_lun, 0, sizeof(scsilun->scsi_lun)); 10452f4701d8SJames.Smart@Emulex.Com 10462f4701d8SJames.Smart@Emulex.Com for (i = 0; i < sizeof(lun); i += 2) { 10472f4701d8SJames.Smart@Emulex.Com scsilun->scsi_lun[i] = (lun >> 8) & 0xFF; 10482f4701d8SJames.Smart@Emulex.Com scsilun->scsi_lun[i+1] = lun & 0xFF; 10492f4701d8SJames.Smart@Emulex.Com lun = lun >> 16; 10502f4701d8SJames.Smart@Emulex.Com } 10512f4701d8SJames.Smart@Emulex.Com } 10522f4701d8SJames.Smart@Emulex.Com EXPORT_SYMBOL(int_to_scsilun); 10532f4701d8SJames.Smart@Emulex.Com 10542f4701d8SJames.Smart@Emulex.Com /** 10551da177e4SLinus Torvalds * scsi_report_lun_scan - Scan using SCSI REPORT LUN results 1056f64a181dSChristoph Hellwig * @sdevscan: scan the host, channel, and id of this scsi_device 10571da177e4SLinus Torvalds * 10581da177e4SLinus Torvalds * Description: 10591da177e4SLinus Torvalds * If @sdevscan is for a SCSI-3 or up device, send a REPORT LUN 10601da177e4SLinus Torvalds * command, and scan the resulting list of LUNs by calling 10611da177e4SLinus Torvalds * scsi_probe_and_add_lun. 10621da177e4SLinus Torvalds * 10631da177e4SLinus Torvalds * Modifies sdevscan->lun. 10641da177e4SLinus Torvalds * 10651da177e4SLinus Torvalds * Return: 10661da177e4SLinus Torvalds * 0: scan completed (or no memory, so further scanning is futile) 10671da177e4SLinus Torvalds * 1: no report lun scan, or not configured 10681da177e4SLinus Torvalds **/ 10696f3a2024SJames Bottomley static int scsi_report_lun_scan(struct scsi_target *starget, int bflags, 10701da177e4SLinus Torvalds int rescan) 10711da177e4SLinus Torvalds { 10721da177e4SLinus Torvalds char devname[64]; 10731da177e4SLinus Torvalds unsigned char scsi_cmd[MAX_COMMAND_SIZE]; 10741da177e4SLinus Torvalds unsigned int length; 10751da177e4SLinus Torvalds unsigned int lun; 10761da177e4SLinus Torvalds unsigned int num_luns; 10771da177e4SLinus Torvalds unsigned int retries; 107839216033SJames Bottomley int result; 10791da177e4SLinus Torvalds struct scsi_lun *lunp, *lun_data; 10801da177e4SLinus Torvalds u8 *data; 10811da177e4SLinus Torvalds struct scsi_sense_hdr sshdr; 10826f3a2024SJames Bottomley struct scsi_device *sdev; 10836f3a2024SJames Bottomley struct Scsi_Host *shost = dev_to_shost(&starget->dev); 10842ef89198SAlan Stern int ret = 0; 10851da177e4SLinus Torvalds 10861da177e4SLinus Torvalds /* 10871da177e4SLinus Torvalds * Only support SCSI-3 and up devices if BLIST_NOREPORTLUN is not set. 10881da177e4SLinus Torvalds * Also allow SCSI-2 if BLIST_REPORTLUN2 is set and host adapter does 10891da177e4SLinus Torvalds * support more than 8 LUNs. 10901da177e4SLinus Torvalds */ 10911da177e4SLinus Torvalds if ((bflags & BLIST_NOREPORTLUN) || 10926f3a2024SJames Bottomley starget->scsi_level < SCSI_2 || 10936f3a2024SJames Bottomley (starget->scsi_level < SCSI_3 && 10946f3a2024SJames Bottomley (!(bflags & BLIST_REPORTLUN2) || shost->max_lun <= 8)) ) 10951da177e4SLinus Torvalds return 1; 10961da177e4SLinus Torvalds if (bflags & BLIST_NOLUN) 10971da177e4SLinus Torvalds return 0; 10981da177e4SLinus Torvalds 10996f3a2024SJames Bottomley if (!(sdev = scsi_device_lookup_by_target(starget, 0))) { 11006f3a2024SJames Bottomley sdev = scsi_alloc_sdev(starget, 0, NULL); 11016f3a2024SJames Bottomley if (!sdev) 11026f3a2024SJames Bottomley return 0; 11036f3a2024SJames Bottomley if (scsi_device_get(sdev)) 11046f3a2024SJames Bottomley return 0; 11056f3a2024SJames Bottomley } 11066f3a2024SJames Bottomley 11071da177e4SLinus Torvalds sprintf(devname, "host %d channel %d id %d", 11086f3a2024SJames Bottomley shost->host_no, sdev->channel, sdev->id); 11091da177e4SLinus Torvalds 11101da177e4SLinus Torvalds /* 11111da177e4SLinus Torvalds * Allocate enough to hold the header (the same size as one scsi_lun) 11121da177e4SLinus Torvalds * plus the max number of luns we are requesting. 11131da177e4SLinus Torvalds * 11141da177e4SLinus Torvalds * Reallocating and trying again (with the exact amount we need) 11151da177e4SLinus Torvalds * would be nice, but then we need to somehow limit the size 11161da177e4SLinus Torvalds * allocated based on the available memory and the limits of 11171da177e4SLinus Torvalds * kmalloc - we don't want a kmalloc() failure of a huge value to 11181da177e4SLinus Torvalds * prevent us from finding any LUNs on this target. 11191da177e4SLinus Torvalds */ 11201da177e4SLinus Torvalds length = (max_scsi_report_luns + 1) * sizeof(struct scsi_lun); 11211da177e4SLinus Torvalds lun_data = kmalloc(length, GFP_ATOMIC | 11221da177e4SLinus Torvalds (sdev->host->unchecked_isa_dma ? __GFP_DMA : 0)); 11236f3a2024SJames Bottomley if (!lun_data) { 11246f3a2024SJames Bottomley printk(ALLOC_FAILURE_MSG, __FUNCTION__); 112539216033SJames Bottomley goto out; 11266f3a2024SJames Bottomley } 11271da177e4SLinus Torvalds 11281da177e4SLinus Torvalds scsi_cmd[0] = REPORT_LUNS; 11291da177e4SLinus Torvalds 11301da177e4SLinus Torvalds /* 11311da177e4SLinus Torvalds * bytes 1 - 5: reserved, set to zero. 11321da177e4SLinus Torvalds */ 11331da177e4SLinus Torvalds memset(&scsi_cmd[1], 0, 5); 11341da177e4SLinus Torvalds 11351da177e4SLinus Torvalds /* 11361da177e4SLinus Torvalds * bytes 6 - 9: length of the command. 11371da177e4SLinus Torvalds */ 11381da177e4SLinus Torvalds scsi_cmd[6] = (unsigned char) (length >> 24) & 0xff; 11391da177e4SLinus Torvalds scsi_cmd[7] = (unsigned char) (length >> 16) & 0xff; 11401da177e4SLinus Torvalds scsi_cmd[8] = (unsigned char) (length >> 8) & 0xff; 11411da177e4SLinus Torvalds scsi_cmd[9] = (unsigned char) length & 0xff; 11421da177e4SLinus Torvalds 11431da177e4SLinus Torvalds scsi_cmd[10] = 0; /* reserved */ 11441da177e4SLinus Torvalds scsi_cmd[11] = 0; /* control */ 11451da177e4SLinus Torvalds 11461da177e4SLinus Torvalds /* 11471da177e4SLinus Torvalds * We can get a UNIT ATTENTION, for example a power on/reset, so 11481da177e4SLinus Torvalds * retry a few times (like sd.c does for TEST UNIT READY). 11491da177e4SLinus Torvalds * Experience shows some combinations of adapter/devices get at 11501da177e4SLinus Torvalds * least two power on/resets. 11511da177e4SLinus Torvalds * 11521da177e4SLinus Torvalds * Illegal requests (for devices that do not support REPORT LUNS) 11531da177e4SLinus Torvalds * should come through as a check condition, and will not generate 11541da177e4SLinus Torvalds * a retry. 11551da177e4SLinus Torvalds */ 11561da177e4SLinus Torvalds for (retries = 0; retries < 3; retries++) { 11571da177e4SLinus Torvalds SCSI_LOG_SCAN_BUS(3, printk (KERN_INFO "scsi scan: Sending" 11581da177e4SLinus Torvalds " REPORT LUNS to %s (try %d)\n", devname, 11591da177e4SLinus Torvalds retries)); 116039216033SJames Bottomley 116139216033SJames Bottomley result = scsi_execute_req(sdev, scsi_cmd, DMA_FROM_DEVICE, 1162ea73a9f2SJames Bottomley lun_data, length, &sshdr, 11631da177e4SLinus Torvalds SCSI_TIMEOUT + 4 * HZ, 3); 116439216033SJames Bottomley 11651da177e4SLinus Torvalds SCSI_LOG_SCAN_BUS(3, printk (KERN_INFO "scsi scan: REPORT LUNS" 116639216033SJames Bottomley " %s (try %d) result 0x%x\n", result 116739216033SJames Bottomley ? "failed" : "successful", retries, result)); 116839216033SJames Bottomley if (result == 0) 11691da177e4SLinus Torvalds break; 1170ea73a9f2SJames Bottomley else if (scsi_sense_valid(&sshdr)) { 11711da177e4SLinus Torvalds if (sshdr.sense_key != UNIT_ATTENTION) 11721da177e4SLinus Torvalds break; 11731da177e4SLinus Torvalds } 11741da177e4SLinus Torvalds } 11751da177e4SLinus Torvalds 117639216033SJames Bottomley if (result) { 11771da177e4SLinus Torvalds /* 11781da177e4SLinus Torvalds * The device probably does not support a REPORT LUN command 11791da177e4SLinus Torvalds */ 11802ef89198SAlan Stern ret = 1; 11812ef89198SAlan Stern goto out_err; 11821da177e4SLinus Torvalds } 11831da177e4SLinus Torvalds 11841da177e4SLinus Torvalds /* 11851da177e4SLinus Torvalds * Get the length from the first four bytes of lun_data. 11861da177e4SLinus Torvalds */ 11871da177e4SLinus Torvalds data = (u8 *) lun_data->scsi_lun; 11881da177e4SLinus Torvalds length = ((data[0] << 24) | (data[1] << 16) | 11891da177e4SLinus Torvalds (data[2] << 8) | (data[3] << 0)); 11901da177e4SLinus Torvalds 11911da177e4SLinus Torvalds num_luns = (length / sizeof(struct scsi_lun)); 11921da177e4SLinus Torvalds if (num_luns > max_scsi_report_luns) { 11931da177e4SLinus Torvalds printk(KERN_WARNING "scsi: On %s only %d (max_scsi_report_luns)" 11941da177e4SLinus Torvalds " of %d luns reported, try increasing" 11951da177e4SLinus Torvalds " max_scsi_report_luns.\n", devname, 11961da177e4SLinus Torvalds max_scsi_report_luns, num_luns); 11971da177e4SLinus Torvalds num_luns = max_scsi_report_luns; 11981da177e4SLinus Torvalds } 11991da177e4SLinus Torvalds 12003bf743e7SJeff Garzik SCSI_LOG_SCAN_BUS(3, sdev_printk (KERN_INFO, sdev, 12013bf743e7SJeff Garzik "scsi scan: REPORT LUN scan\n")); 12021da177e4SLinus Torvalds 12031da177e4SLinus Torvalds /* 12041da177e4SLinus Torvalds * Scan the luns in lun_data. The entry at offset 0 is really 12051da177e4SLinus Torvalds * the header, so start at 1 and go up to and including num_luns. 12061da177e4SLinus Torvalds */ 12071da177e4SLinus Torvalds for (lunp = &lun_data[1]; lunp <= &lun_data[num_luns]; lunp++) { 12081da177e4SLinus Torvalds lun = scsilun_to_int(lunp); 12091da177e4SLinus Torvalds 12101da177e4SLinus Torvalds /* 12111da177e4SLinus Torvalds * Check if the unused part of lunp is non-zero, and so 12121da177e4SLinus Torvalds * does not fit in lun. 12131da177e4SLinus Torvalds */ 12141da177e4SLinus Torvalds if (memcmp(&lunp->scsi_lun[sizeof(lun)], "\0\0\0\0", 4)) { 12151da177e4SLinus Torvalds int i; 12161da177e4SLinus Torvalds 12171da177e4SLinus Torvalds /* 12181da177e4SLinus Torvalds * Output an error displaying the LUN in byte order, 12191da177e4SLinus Torvalds * this differs from what linux would print for the 12201da177e4SLinus Torvalds * integer LUN value. 12211da177e4SLinus Torvalds */ 12221da177e4SLinus Torvalds printk(KERN_WARNING "scsi: %s lun 0x", devname); 12231da177e4SLinus Torvalds data = (char *)lunp->scsi_lun; 12241da177e4SLinus Torvalds for (i = 0; i < sizeof(struct scsi_lun); i++) 12251da177e4SLinus Torvalds printk("%02x", data[i]); 12261da177e4SLinus Torvalds printk(" has a LUN larger than currently supported.\n"); 12271da177e4SLinus Torvalds } else if (lun > sdev->host->max_lun) { 12281da177e4SLinus Torvalds printk(KERN_WARNING "scsi: %s lun%d has a LUN larger" 12291da177e4SLinus Torvalds " than allowed by the host adapter\n", 12301da177e4SLinus Torvalds devname, lun); 12311da177e4SLinus Torvalds } else { 12321da177e4SLinus Torvalds int res; 12331da177e4SLinus Torvalds 12341da177e4SLinus Torvalds res = scsi_probe_and_add_lun(starget, 12351da177e4SLinus Torvalds lun, NULL, NULL, rescan, NULL); 12361da177e4SLinus Torvalds if (res == SCSI_SCAN_NO_RESPONSE) { 12371da177e4SLinus Torvalds /* 12381da177e4SLinus Torvalds * Got some results, but now none, abort. 12391da177e4SLinus Torvalds */ 12403bf743e7SJeff Garzik sdev_printk(KERN_ERR, sdev, 12413bf743e7SJeff Garzik "Unexpected response" 12423bf743e7SJeff Garzik " from lun %d while scanning, scan" 12433bf743e7SJeff Garzik " aborted\n", lun); 12441da177e4SLinus Torvalds break; 12451da177e4SLinus Torvalds } 12461da177e4SLinus Torvalds } 12471da177e4SLinus Torvalds } 12481da177e4SLinus Torvalds 12492ef89198SAlan Stern out_err: 12501da177e4SLinus Torvalds kfree(lun_data); 12511da177e4SLinus Torvalds out: 12526f3a2024SJames Bottomley scsi_device_put(sdev); 12536f3a2024SJames Bottomley if (sdev->sdev_state == SDEV_CREATED) 12541da177e4SLinus Torvalds /* 12556f3a2024SJames Bottomley * the sdev we used didn't appear in the report luns scan 12561da177e4SLinus Torvalds */ 12576f3a2024SJames Bottomley scsi_destroy_sdev(sdev); 12582ef89198SAlan Stern return ret; 12591da177e4SLinus Torvalds } 12601da177e4SLinus Torvalds 12611da177e4SLinus Torvalds struct scsi_device *__scsi_add_device(struct Scsi_Host *shost, uint channel, 12621da177e4SLinus Torvalds uint id, uint lun, void *hostdata) 12631da177e4SLinus Torvalds { 12641da177e4SLinus Torvalds struct scsi_device *sdev; 12651da177e4SLinus Torvalds struct device *parent = &shost->shost_gendev; 12661da177e4SLinus Torvalds int res; 1267e02f3f59SChristoph Hellwig struct scsi_target *starget; 12681da177e4SLinus Torvalds 1269e02f3f59SChristoph Hellwig starget = scsi_alloc_target(parent, channel, id); 12701da177e4SLinus Torvalds if (!starget) 12711da177e4SLinus Torvalds return ERR_PTR(-ENOMEM); 12721da177e4SLinus Torvalds 1273c92715b3SNathan Lynch get_device(&starget->dev); 12740b950672SArjan van de Ven mutex_lock(&shost->scan_mutex); 127582f29467SMike Anderson if (scsi_host_scan_allowed(shost)) { 127682f29467SMike Anderson res = scsi_probe_and_add_lun(starget, lun, NULL, &sdev, 1, 127782f29467SMike Anderson hostdata); 12781da177e4SLinus Torvalds if (res != SCSI_SCAN_LUN_PRESENT) 12791da177e4SLinus Torvalds sdev = ERR_PTR(-ENODEV); 128082f29467SMike Anderson } 12810b950672SArjan van de Ven mutex_unlock(&shost->scan_mutex); 12821da177e4SLinus Torvalds scsi_target_reap(starget); 12831da177e4SLinus Torvalds put_device(&starget->dev); 12841da177e4SLinus Torvalds 12851da177e4SLinus Torvalds return sdev; 12861da177e4SLinus Torvalds } 12871da177e4SLinus Torvalds EXPORT_SYMBOL(__scsi_add_device); 12881da177e4SLinus Torvalds 1289146f7262SJames Bottomley int scsi_add_device(struct Scsi_Host *host, uint channel, 1290146f7262SJames Bottomley uint target, uint lun) 1291146f7262SJames Bottomley { 1292146f7262SJames Bottomley struct scsi_device *sdev = 1293146f7262SJames Bottomley __scsi_add_device(host, channel, target, lun, NULL); 1294146f7262SJames Bottomley if (IS_ERR(sdev)) 1295146f7262SJames Bottomley return PTR_ERR(sdev); 1296146f7262SJames Bottomley 1297146f7262SJames Bottomley scsi_device_put(sdev); 1298146f7262SJames Bottomley return 0; 1299146f7262SJames Bottomley } 1300146f7262SJames Bottomley EXPORT_SYMBOL(scsi_add_device); 1301146f7262SJames Bottomley 13021da177e4SLinus Torvalds void scsi_rescan_device(struct device *dev) 13031da177e4SLinus Torvalds { 13041da177e4SLinus Torvalds struct scsi_driver *drv; 13051da177e4SLinus Torvalds 13061da177e4SLinus Torvalds if (!dev->driver) 13071da177e4SLinus Torvalds return; 13081da177e4SLinus Torvalds 13091da177e4SLinus Torvalds drv = to_scsi_driver(dev->driver); 13101da177e4SLinus Torvalds if (try_module_get(drv->owner)) { 13111da177e4SLinus Torvalds if (drv->rescan) 13121da177e4SLinus Torvalds drv->rescan(dev); 13131da177e4SLinus Torvalds module_put(drv->owner); 13141da177e4SLinus Torvalds } 13151da177e4SLinus Torvalds } 13161da177e4SLinus Torvalds EXPORT_SYMBOL(scsi_rescan_device); 13171da177e4SLinus Torvalds 1318e517d313SAlan Stern static void __scsi_scan_target(struct device *parent, unsigned int channel, 13191da177e4SLinus Torvalds unsigned int id, unsigned int lun, int rescan) 13201da177e4SLinus Torvalds { 13211da177e4SLinus Torvalds struct Scsi_Host *shost = dev_to_shost(parent); 13221da177e4SLinus Torvalds int bflags = 0; 13231da177e4SLinus Torvalds int res; 13241da177e4SLinus Torvalds struct scsi_target *starget; 13251da177e4SLinus Torvalds 13261da177e4SLinus Torvalds if (shost->this_id == id) 13271da177e4SLinus Torvalds /* 13281da177e4SLinus Torvalds * Don't scan the host adapter 13291da177e4SLinus Torvalds */ 13301da177e4SLinus Torvalds return; 13311da177e4SLinus Torvalds 13321da177e4SLinus Torvalds starget = scsi_alloc_target(parent, channel, id); 13331da177e4SLinus Torvalds if (!starget) 13341da177e4SLinus Torvalds return; 13351da177e4SLinus Torvalds 13361da177e4SLinus Torvalds get_device(&starget->dev); 13371da177e4SLinus Torvalds if (lun != SCAN_WILD_CARD) { 13381da177e4SLinus Torvalds /* 13391da177e4SLinus Torvalds * Scan for a specific host/chan/id/lun. 13401da177e4SLinus Torvalds */ 13411da177e4SLinus Torvalds scsi_probe_and_add_lun(starget, lun, NULL, NULL, rescan, NULL); 13421da177e4SLinus Torvalds goto out_reap; 13431da177e4SLinus Torvalds } 13441da177e4SLinus Torvalds 13451da177e4SLinus Torvalds /* 13461da177e4SLinus Torvalds * Scan LUN 0, if there is some response, scan further. Ideally, we 13471da177e4SLinus Torvalds * would not configure LUN 0 until all LUNs are scanned. 13481da177e4SLinus Torvalds */ 13496f3a2024SJames Bottomley res = scsi_probe_and_add_lun(starget, 0, &bflags, NULL, rescan, NULL); 13506f3a2024SJames Bottomley if (res == SCSI_SCAN_LUN_PRESENT || res == SCSI_SCAN_TARGET_PRESENT) { 13516f3a2024SJames Bottomley if (scsi_report_lun_scan(starget, bflags, rescan) != 0) 13521da177e4SLinus Torvalds /* 13531da177e4SLinus Torvalds * The REPORT LUN did not scan the target, 13541da177e4SLinus Torvalds * do a sequential scan. 13551da177e4SLinus Torvalds */ 13561da177e4SLinus Torvalds scsi_sequential_lun_scan(starget, bflags, 13576f3a2024SJames Bottomley res, starget->scsi_level, rescan); 13581da177e4SLinus Torvalds } 13591da177e4SLinus Torvalds 13601da177e4SLinus Torvalds out_reap: 13611da177e4SLinus Torvalds /* now determine if the target has any children at all 13621da177e4SLinus Torvalds * and if not, nuke it */ 13631da177e4SLinus Torvalds scsi_target_reap(starget); 13641da177e4SLinus Torvalds 13651da177e4SLinus Torvalds put_device(&starget->dev); 13661da177e4SLinus Torvalds } 1367e517d313SAlan Stern 1368e517d313SAlan Stern /** 1369e517d313SAlan Stern * scsi_scan_target - scan a target id, possibly including all LUNs on the 1370e517d313SAlan Stern * target. 1371e517d313SAlan Stern * @parent: host to scan 1372e517d313SAlan Stern * @channel: channel to scan 1373e517d313SAlan Stern * @id: target id to scan 1374e517d313SAlan Stern * @lun: Specific LUN to scan or SCAN_WILD_CARD 1375e517d313SAlan Stern * @rescan: passed to LUN scanning routines 1376e517d313SAlan Stern * 1377e517d313SAlan Stern * Description: 1378e517d313SAlan Stern * Scan the target id on @parent, @channel, and @id. Scan at least LUN 0, 1379e517d313SAlan Stern * and possibly all LUNs on the target id. 1380e517d313SAlan Stern * 1381e517d313SAlan Stern * First try a REPORT LUN scan, if that does not scan the target, do a 1382e517d313SAlan Stern * sequential scan of LUNs on the target id. 1383e517d313SAlan Stern **/ 1384e517d313SAlan Stern void scsi_scan_target(struct device *parent, unsigned int channel, 1385e517d313SAlan Stern unsigned int id, unsigned int lun, int rescan) 1386e517d313SAlan Stern { 1387e517d313SAlan Stern struct Scsi_Host *shost = dev_to_shost(parent); 1388e517d313SAlan Stern 13890b950672SArjan van de Ven mutex_lock(&shost->scan_mutex); 1390e517d313SAlan Stern if (scsi_host_scan_allowed(shost)) 1391e517d313SAlan Stern __scsi_scan_target(parent, channel, id, lun, rescan); 13920b950672SArjan van de Ven mutex_unlock(&shost->scan_mutex); 1393e517d313SAlan Stern } 13941da177e4SLinus Torvalds EXPORT_SYMBOL(scsi_scan_target); 13951da177e4SLinus Torvalds 13961da177e4SLinus Torvalds static void scsi_scan_channel(struct Scsi_Host *shost, unsigned int channel, 13971da177e4SLinus Torvalds unsigned int id, unsigned int lun, int rescan) 13981da177e4SLinus Torvalds { 13991da177e4SLinus Torvalds uint order_id; 14001da177e4SLinus Torvalds 14011da177e4SLinus Torvalds if (id == SCAN_WILD_CARD) 14021da177e4SLinus Torvalds for (id = 0; id < shost->max_id; ++id) { 14031da177e4SLinus Torvalds /* 14041da177e4SLinus Torvalds * XXX adapter drivers when possible (FCP, iSCSI) 14051da177e4SLinus Torvalds * could modify max_id to match the current max, 14061da177e4SLinus Torvalds * not the absolute max. 14071da177e4SLinus Torvalds * 14081da177e4SLinus Torvalds * XXX add a shost id iterator, so for example, 14091da177e4SLinus Torvalds * the FC ID can be the same as a target id 14101da177e4SLinus Torvalds * without a huge overhead of sparse id's. 14111da177e4SLinus Torvalds */ 14121da177e4SLinus Torvalds if (shost->reverse_ordering) 14131da177e4SLinus Torvalds /* 14141da177e4SLinus Torvalds * Scan from high to low id. 14151da177e4SLinus Torvalds */ 14161da177e4SLinus Torvalds order_id = shost->max_id - id - 1; 14171da177e4SLinus Torvalds else 14181da177e4SLinus Torvalds order_id = id; 1419e517d313SAlan Stern __scsi_scan_target(&shost->shost_gendev, channel, 1420e517d313SAlan Stern order_id, lun, rescan); 14211da177e4SLinus Torvalds } 14221da177e4SLinus Torvalds else 1423e517d313SAlan Stern __scsi_scan_target(&shost->shost_gendev, channel, 1424e517d313SAlan Stern id, lun, rescan); 14251da177e4SLinus Torvalds } 14261da177e4SLinus Torvalds 14271da177e4SLinus Torvalds int scsi_scan_host_selected(struct Scsi_Host *shost, unsigned int channel, 14281da177e4SLinus Torvalds unsigned int id, unsigned int lun, int rescan) 14291da177e4SLinus Torvalds { 14303bf743e7SJeff Garzik SCSI_LOG_SCAN_BUS(3, shost_printk (KERN_INFO, shost, 14313bf743e7SJeff Garzik "%s: <%u:%u:%u>\n", 14323bf743e7SJeff Garzik __FUNCTION__, channel, id, lun)); 14331da177e4SLinus Torvalds 14341da177e4SLinus Torvalds if (((channel != SCAN_WILD_CARD) && (channel > shost->max_channel)) || 14351da177e4SLinus Torvalds ((id != SCAN_WILD_CARD) && (id > shost->max_id)) || 14361da177e4SLinus Torvalds ((lun != SCAN_WILD_CARD) && (lun > shost->max_lun))) 14371da177e4SLinus Torvalds return -EINVAL; 14381da177e4SLinus Torvalds 14390b950672SArjan van de Ven mutex_lock(&shost->scan_mutex); 144082f29467SMike Anderson if (scsi_host_scan_allowed(shost)) { 14411da177e4SLinus Torvalds if (channel == SCAN_WILD_CARD) 144282f29467SMike Anderson for (channel = 0; channel <= shost->max_channel; 144382f29467SMike Anderson channel++) 144482f29467SMike Anderson scsi_scan_channel(shost, channel, id, lun, 144582f29467SMike Anderson rescan); 14461da177e4SLinus Torvalds else 14471da177e4SLinus Torvalds scsi_scan_channel(shost, channel, id, lun, rescan); 144882f29467SMike Anderson } 14490b950672SArjan van de Ven mutex_unlock(&shost->scan_mutex); 14501da177e4SLinus Torvalds 14511da177e4SLinus Torvalds return 0; 14521da177e4SLinus Torvalds } 14531da177e4SLinus Torvalds 14541da177e4SLinus Torvalds /** 14551da177e4SLinus Torvalds * scsi_scan_host - scan the given adapter 14561da177e4SLinus Torvalds * @shost: adapter to scan 14571da177e4SLinus Torvalds **/ 14581da177e4SLinus Torvalds void scsi_scan_host(struct Scsi_Host *shost) 14591da177e4SLinus Torvalds { 14601da177e4SLinus Torvalds scsi_scan_host_selected(shost, SCAN_WILD_CARD, SCAN_WILD_CARD, 14611da177e4SLinus Torvalds SCAN_WILD_CARD, 0); 14621da177e4SLinus Torvalds } 14631da177e4SLinus Torvalds EXPORT_SYMBOL(scsi_scan_host); 14641da177e4SLinus Torvalds 14651da177e4SLinus Torvalds void scsi_forget_host(struct Scsi_Host *shost) 14661da177e4SLinus Torvalds { 1467a64358dbSAlan Stern struct scsi_device *sdev; 14681da177e4SLinus Torvalds unsigned long flags; 14691da177e4SLinus Torvalds 1470a64358dbSAlan Stern restart: 14711da177e4SLinus Torvalds spin_lock_irqsave(shost->host_lock, flags); 1472a64358dbSAlan Stern list_for_each_entry(sdev, &shost->__devices, siblings) { 1473a64358dbSAlan Stern if (sdev->sdev_state == SDEV_DEL) 1474a64358dbSAlan Stern continue; 14751da177e4SLinus Torvalds spin_unlock_irqrestore(shost->host_lock, flags); 1476a64358dbSAlan Stern __scsi_remove_device(sdev); 1477a64358dbSAlan Stern goto restart; 14781da177e4SLinus Torvalds } 14791da177e4SLinus Torvalds spin_unlock_irqrestore(shost->host_lock, flags); 14801da177e4SLinus Torvalds } 14811da177e4SLinus Torvalds 14821da177e4SLinus Torvalds /* 14831da177e4SLinus Torvalds * Function: scsi_get_host_dev() 14841da177e4SLinus Torvalds * 1485f64a181dSChristoph Hellwig * Purpose: Create a scsi_device that points to the host adapter itself. 14861da177e4SLinus Torvalds * 1487f64a181dSChristoph Hellwig * Arguments: SHpnt - Host that needs a scsi_device 14881da177e4SLinus Torvalds * 14891da177e4SLinus Torvalds * Lock status: None assumed. 14901da177e4SLinus Torvalds * 1491f64a181dSChristoph Hellwig * Returns: The scsi_device or NULL 14921da177e4SLinus Torvalds * 14931da177e4SLinus Torvalds * Notes: 1494f64a181dSChristoph Hellwig * Attach a single scsi_device to the Scsi_Host - this should 14951da177e4SLinus Torvalds * be made to look like a "pseudo-device" that points to the 14961da177e4SLinus Torvalds * HA itself. 14971da177e4SLinus Torvalds * 14981da177e4SLinus Torvalds * Note - this device is not accessible from any high-level 14991da177e4SLinus Torvalds * drivers (including generics), which is probably not 15001da177e4SLinus Torvalds * optimal. We can add hooks later to attach 15011da177e4SLinus Torvalds */ 15021da177e4SLinus Torvalds struct scsi_device *scsi_get_host_dev(struct Scsi_Host *shost) 15031da177e4SLinus Torvalds { 1504e517d313SAlan Stern struct scsi_device *sdev = NULL; 15051da177e4SLinus Torvalds struct scsi_target *starget; 15061da177e4SLinus Torvalds 15070b950672SArjan van de Ven mutex_lock(&shost->scan_mutex); 1508e517d313SAlan Stern if (!scsi_host_scan_allowed(shost)) 1509e517d313SAlan Stern goto out; 15101da177e4SLinus Torvalds starget = scsi_alloc_target(&shost->shost_gendev, 0, shost->this_id); 15111da177e4SLinus Torvalds if (!starget) 1512e517d313SAlan Stern goto out; 15131da177e4SLinus Torvalds 15141da177e4SLinus Torvalds sdev = scsi_alloc_sdev(starget, 0, NULL); 15151da177e4SLinus Torvalds if (sdev) { 15161da177e4SLinus Torvalds sdev->sdev_gendev.parent = get_device(&starget->dev); 15171da177e4SLinus Torvalds sdev->borken = 0; 15181da177e4SLinus Torvalds } 15191da177e4SLinus Torvalds put_device(&starget->dev); 1520e517d313SAlan Stern out: 15210b950672SArjan van de Ven mutex_unlock(&shost->scan_mutex); 15221da177e4SLinus Torvalds return sdev; 15231da177e4SLinus Torvalds } 15241da177e4SLinus Torvalds EXPORT_SYMBOL(scsi_get_host_dev); 15251da177e4SLinus Torvalds 15261da177e4SLinus Torvalds /* 15271da177e4SLinus Torvalds * Function: scsi_free_host_dev() 15281da177e4SLinus Torvalds * 15291da177e4SLinus Torvalds * Purpose: Free a scsi_device that points to the host adapter itself. 15301da177e4SLinus Torvalds * 1531f64a181dSChristoph Hellwig * Arguments: SHpnt - Host that needs a scsi_device 15321da177e4SLinus Torvalds * 15331da177e4SLinus Torvalds * Lock status: None assumed. 15341da177e4SLinus Torvalds * 15351da177e4SLinus Torvalds * Returns: Nothing 15361da177e4SLinus Torvalds * 15371da177e4SLinus Torvalds * Notes: 15381da177e4SLinus Torvalds */ 15391da177e4SLinus Torvalds void scsi_free_host_dev(struct scsi_device *sdev) 15401da177e4SLinus Torvalds { 15411da177e4SLinus Torvalds BUG_ON(sdev->id != sdev->host->this_id); 15421da177e4SLinus Torvalds 15436f3a2024SJames Bottomley scsi_destroy_sdev(sdev); 15441da177e4SLinus Torvalds } 15451da177e4SLinus Torvalds EXPORT_SYMBOL(scsi_free_host_dev); 15461da177e4SLinus Torvalds 1547