int display_failure_msg = 1, ret;
struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
- sdev = kmalloc(sizeof(*sdev) + shost->transportt->device_size,
+ sdev = kzalloc(sizeof(*sdev) + shost->transportt->device_size,
GFP_ATOMIC);
if (!sdev)
goto out;
- memset(sdev, 0, sizeof(*sdev));
sdev->vendor = scsi_null_device_strs;
sdev->model = scsi_null_device_strs;
sdev->rev = scsi_null_device_strs;
/* release fn is set up in scsi_sysfs_device_initialise, so
* have to free and put manually here */
put_device(&starget->dev);
+ kfree(sdev);
goto out;
}
struct scsi_target *found_target;
int error;
- starget = kmalloc(size, GFP_KERNEL);
+ starget = kzalloc(size, GFP_KERNEL);
if (!starget) {
printk(KERN_ERR "%s: allocation failure\n", __FUNCTION__);
return NULL;
}
- memset(starget, 0, size);
dev = &starget->dev;
device_initialize(dev);
starget->reap_ref = 1;
case TYPE_MEDIUM_CHANGER:
case TYPE_ENCLOSURE:
case TYPE_COMM:
+ case TYPE_RAID:
case TYPE_RBC:
sdev->writeable = 1;
break;
if (inq_result[7] & 0x10)
sdev->sdtr = 1;
- sprintf(sdev->devfs_name, "scsi/host%d/bus%d/target%d/lun%d",
- sdev->host->host_no, sdev->channel,
- sdev->id, sdev->lun);
-
/*
- * End driverfs/devfs code.
+ * End sysfs code.
*/
if ((sdev->scsi_level >= SCSI_2) && (inq_result[7] & 2) &&
sdev->select_no_atn = 1;
/*
+ * Maximum 512 sector transfer length
+ * broken RA4x00 Compaq Disk Array
+ */
+ if (*bflags & BLIST_MAX_512)
+ blk_queue_max_sectors(sdev->request_queue, 512);
+
+ /*
* Some devices may not want to have a start command automatically
* issued when a device is added.
*/
put_device(&sdev->sdev_gendev);
}
-#ifdef CONFIG_SCSI_LOGGING
-/**
- * scsi_inq_str - print INQUIRY data from min to max index,
- * strip trailing whitespace
- * @buf: Output buffer with at least end-first+1 bytes of space
- * @inq: Inquiry buffer (input)
- * @first: Offset of string into inq
- * @end: Index after last character in inq
- */
-static unsigned char *scsi_inq_str(unsigned char *buf, unsigned char *inq,
- unsigned first, unsigned end)
-{
- unsigned term = 0, idx;
-
- for (idx = 0; idx + first < end && idx + first < inq[4] + 5; idx++) {
- if (inq[idx+first] > ' ') {
- buf[idx] = inq[idx+first];
- term = idx+1;
- } else {
- buf[idx] = ' ';
- }
- }
- buf[term] = 0;
- return buf;
-}
-#endif
/**
* scsi_probe_and_add_lun - probe a LUN, if a LUN is found add it
if (scsi_probe_lun(sdev, result, result_len, &bflags))
goto out_free_result;
- if (bflagsp)
- *bflagsp = bflags;
/*
* result contains valid SCSI INQUIRY data.
*/
- if (((result[0] >> 5) == 3) && !(bflags & BLIST_ATTACH_PQ3)) {
+ if ((result[0] >> 5) == 3) {
/*
* For a Peripheral qualifier 3 (011b), the SCSI
* spec says: The device server is not capable of
* logical disk configured at sdev->lun, but there
* is a target id responding.
*/
- SCSI_LOG_SCAN_BUS(2, sdev_printk(KERN_INFO, sdev, "scsi scan:"
- " peripheral qualifier of 3, device not"
- " added\n"))
- if (lun == 0) {
- SCSI_LOG_SCAN_BUS(1, {
- unsigned char vend[9];
- unsigned char mod[17];
-
- sdev_printk(KERN_INFO, sdev,
- "scsi scan: consider passing scsi_mod."
- "dev_flags=%s:%s:0x240 or 0x1000240\n",
- scsi_inq_str(vend, result, 8, 16),
- scsi_inq_str(mod, result, 16, 32));
- });
- }
-
+ SCSI_LOG_SCAN_BUS(3, printk(KERN_INFO
+ "scsi scan: peripheral qualifier of 3,"
+ " no device added\n"));
+ res = SCSI_SCAN_TARGET_PRESENT;
+ goto out_free_result;
+ }
+
+ /*
+ * Non-standard SCSI targets may set the PDT to 0x1f (unknown or
+ * no device type) instead of using the Peripheral Qualifier to
+ * indicate that no LUN is present. For example, USB UFI does this.
+ */
+ if (starget->pdt_1f_for_no_lun && (result[0] & 0x1f) == 0x1f) {
+ SCSI_LOG_SCAN_BUS(3, printk(KERN_INFO
+ "scsi scan: peripheral device type"
+ " of 31, no device added\n"));
res = SCSI_SCAN_TARGET_PRESENT;
goto out_free_result;
}
sdev->lockable = 0;
scsi_unlock_floptical(sdev, result);
}
+ if (bflagsp)
+ *bflagsp = bflags;
}
out_free_result:
* scsi_sequential_lun_scan - sequentially scan a SCSI target
* @starget: pointer to target structure to scan
* @bflags: black/white list flag for LUN 0
+ * @lun0_res: result of scanning LUN 0
*
* Description:
* Generally, scan from LUN 1 (LUN 0 is assumed to already have been
* Modifies sdevscan->lun.
**/
static void scsi_sequential_lun_scan(struct scsi_target *starget,
- int bflags, int scsi_level, int rescan)
+ int bflags, int lun0_res, int scsi_level,
+ int rescan)
{
unsigned int sparse_lun, lun, max_dev_lun;
struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
sparse_lun = 0;
/*
+ * If not sparse lun and no device attached at LUN 0 do not scan
+ * any further.
+ */
+ if (!sparse_lun && (lun0_res != SCSI_SCAN_LUN_PRESENT))
+ return;
+
+ /*
* If less than SCSI_1_CSS, and no special lun scaning, stop
* scanning; this matches 2.4 behaviour, but could just be a bug
* (to continue scanning a SCSI_1_CSS device).
* Also allow SCSI-2 if BLIST_REPORTLUN2 is set and host adapter does
* support more than 8 LUNs.
*/
- if ((bflags & BLIST_NOREPORTLUN) ||
- starget->scsi_level < SCSI_2 ||
- (starget->scsi_level < SCSI_3 &&
- (!(bflags & BLIST_REPORTLUN2) || shost->max_lun <= 8)) )
+ if (bflags & BLIST_NOREPORTLUN)
+ return 1;
+ if (starget->scsi_level < SCSI_2 &&
+ starget->scsi_level != SCSI_UNKNOWN)
+ return 1;
+ if (starget->scsi_level < SCSI_3 &&
+ (!(bflags & BLIST_REPORTLUN2) || shost->max_lun <= 8))
return 1;
if (bflags & BLIST_NOLUN)
return 0;
struct scsi_device *__scsi_add_device(struct Scsi_Host *shost, uint channel,
uint id, uint lun, void *hostdata)
{
- struct scsi_device *sdev;
+ struct scsi_device *sdev = ERR_PTR(-ENODEV);
struct device *parent = &shost->shost_gendev;
- int res;
struct scsi_target *starget;
starget = scsi_alloc_target(parent, channel, id);
get_device(&starget->dev);
mutex_lock(&shost->scan_mutex);
- if (scsi_host_scan_allowed(shost)) {
- res = scsi_probe_and_add_lun(starget, lun, NULL, &sdev, 1,
- hostdata);
- if (res != SCSI_SCAN_LUN_PRESENT)
- sdev = ERR_PTR(-ENODEV);
- }
+ if (scsi_host_scan_allowed(shost))
+ scsi_probe_and_add_lun(starget, lun, NULL, &sdev, 1, hostdata);
mutex_unlock(&shost->scan_mutex);
scsi_target_reap(starget);
put_device(&starget->dev);
* do a sequential scan.
*/
scsi_sequential_lun_scan(starget, bflags,
- starget->scsi_level, rescan);
+ res, starget->scsi_level, rescan);
}
out_reap: