#include <linux/kthread.h>
#include <linux/spinlock.h>
#include <linux/async.h>
+#include <linux/slab.h>
#include <scsi/scsi.h>
#include <scsi/scsi_cmnd.h>
"REPORT LUNS maximum number of LUNS received (should be"
" between 1 and 16384)");
-static unsigned int scsi_inq_timeout = SCSI_TIMEOUT/HZ+3;
+static unsigned int scsi_inq_timeout = SCSI_TIMEOUT/HZ + 18;
module_param_named(inq_timeout, scsi_inq_timeout, uint, S_IRUGO|S_IWUSR);
MODULE_PARM_DESC(inq_timeout,
"Timeout (in seconds) waiting for devices to answer INQUIRY."
- " Default is 5. Some non-compliant devices need more.");
+ " Default is 20. Some devices may need more; most need less.");
/* This lock protects only this list */
static DEFINE_SPINLOCK(async_scan_lock);
spin_unlock(&async_scan_lock);
kfree(data);
- /* Synchronize async operations globally */
- async_synchronize_full();
return 0;
}
sdev->model = scsi_null_device_strs;
sdev->rev = scsi_null_device_strs;
sdev->host = shost;
+ sdev->queue_ramp_up_period = SCSI_DEFAULT_RAMP_UP_PERIOD;
sdev->id = starget->id;
sdev->lun = lun;
sdev->channel = starget->channel;
out_device_destroy:
scsi_device_set_state(sdev, SDEV_DEL);
transport_destroy_device(&sdev->sdev_gendev);
+ put_device(&sdev->sdev_dev);
put_device(&sdev->sdev_gendev);
out:
if (display_failure_msg)
starget->reap_ref = 1;
dev->parent = get_device(parent);
dev_set_name(dev, "target%d:%d:%d", shost->host_no, channel, id);
-#ifndef CONFIG_SYSFS_DEPRECATED
dev->bus = &scsi_bus_type;
-#endif
dev->type = &scsi_target_type;
starget->id = id;
starget->channel = channel;
INIT_LIST_HEAD(&starget->devices);
starget->state = STARGET_CREATED;
starget->scsi_level = SCSI_2;
+ starget->max_target_blocked = SCSI_DEFAULT_TARGET_BLOCKED;
retry:
spin_lock_irqsave(shost->host_lock, flags);
found_target->reap_ref++;
spin_unlock_irqrestore(shost->host_lock, flags);
if (found_target->state != STARGET_DEL) {
- put_device(parent);
- kfree(starget);
+ put_device(dev);
return found_target;
}
/* Unfortunately, we found a dying target; need to
struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
unsigned long flags;
enum scsi_target_state state;
- int empty;
+ int empty = 0;
spin_lock_irqsave(shost->host_lock, flags);
state = starget->state;
- empty = --starget->reap_ref == 0 &&
- list_empty(&starget->devices) ? 1 : 0;
+ if (--starget->reap_ref == 0 && list_empty(&starget->devices)) {
+ empty = 1;
+ starget->state = STARGET_DEL;
+ }
spin_unlock_irqrestore(shost->host_lock, flags);
if (!empty)
return;
BUG_ON(state == STARGET_DEL);
- starget->state = STARGET_DEL;
if (state == STARGET_CREATED)
scsi_target_destroy(starget);
else
case TYPE_ENCLOSURE:
case TYPE_COMM:
case TYPE_RAID:
+ case TYPE_OSD:
sdev->writeable = 1;
break;
case TYPE_ROM:
* broken RA4x00 Compaq Disk Array
*/
if (*bflags & BLIST_MAX_512)
- blk_queue_max_sectors(sdev->request_queue, 512);
+ blk_queue_max_hw_sectors(sdev->request_queue, 512);
/*
* Some devices may not want to have a start command automatically
}
}
+ sdev->max_queue_depth = sdev->queue_depth;
+
/*
* Ok, the device is now all set up, we can
* register it and tell the rest of the kernel
return SCSI_SCAN_LUN_PRESENT;
}
-static inline void scsi_destroy_sdev(struct scsi_device *sdev)
-{
- scsi_device_set_state(sdev, SDEV_DEL);
- if (sdev->host->hostt->slave_destroy)
- sdev->host->hostt->slave_destroy(sdev);
- transport_destroy_device(&sdev->sdev_gendev);
- put_device(&sdev->sdev_gendev);
-}
-
#ifdef CONFIG_SCSI_LOGGING
/**
* scsi_inq_str - print INQUIRY data from min to max index, strip trailing whitespace
}
}
} else
- scsi_destroy_sdev(sdev);
+ __scsi_remove_device(sdev);
out:
return res;
}
}
/**
- * scsilun_to_int: convert a scsi_lun to an int
+ * scsilun_to_int - convert a scsi_lun to an int
* @scsilun: struct scsi_lun to be converted.
*
* Description:
EXPORT_SYMBOL(scsilun_to_int);
/**
- * int_to_scsilun: reverts an int into a scsi_lun
+ * int_to_scsilun - reverts an int into a scsi_lun
* @lun: integer to be reverted
* @scsilun: struct scsi_lun to be set.
*
sdev = scsi_alloc_sdev(starget, 0, NULL);
if (!sdev)
return 0;
- if (scsi_device_get(sdev))
+ if (scsi_device_get(sdev)) {
+ __scsi_remove_device(sdev);
return 0;
+ }
}
sprintf(devname, "host %d channel %d id %d",
/*
* the sdev we used didn't appear in the report luns scan
*/
- scsi_destroy_sdev(sdev);
+ __scsi_remove_device(sdev);
return ret;
}
starget = scsi_alloc_target(parent, channel, id);
if (!starget)
return ERR_PTR(-ENOMEM);
+ scsi_autopm_get_target(starget);
mutex_lock(&shost->scan_mutex);
if (!shost->async_scan)
scsi_complete_async_scans();
- if (scsi_host_scan_allowed(shost))
+ if (scsi_host_scan_allowed(shost) && scsi_autopm_get_host(shost) == 0) {
scsi_probe_and_add_lun(starget, lun, NULL, &sdev, 1, hostdata);
+ scsi_autopm_put_host(shost);
+ }
mutex_unlock(&shost->scan_mutex);
+ scsi_autopm_put_target(starget);
scsi_target_reap(starget);
put_device(&starget->dev);
starget = scsi_alloc_target(parent, channel, id);
if (!starget)
return;
+ scsi_autopm_get_target(starget);
if (lun != SCAN_WILD_CARD) {
/*
}
out_reap:
+ scsi_autopm_put_target(starget);
/* now determine if the target has any children at all
* and if not, nuke it */
scsi_target_reap(starget);
if (!shost->async_scan)
scsi_complete_async_scans();
- if (scsi_host_scan_allowed(shost))
+ if (scsi_host_scan_allowed(shost) && scsi_autopm_get_host(shost) == 0) {
__scsi_scan_target(parent, channel, id, lun, rescan);
+ scsi_autopm_put_host(shost);
+ }
mutex_unlock(&shost->scan_mutex);
}
EXPORT_SYMBOL(scsi_scan_target);
if (!shost->async_scan)
scsi_complete_async_scans();
- if (scsi_host_scan_allowed(shost)) {
+ if (scsi_host_scan_allowed(shost) && scsi_autopm_get_host(shost) == 0) {
if (channel == SCAN_WILD_CARD)
for (channel = 0; channel <= shost->max_channel;
channel++)
rescan);
else
scsi_scan_channel(shost, channel, id, lun, rescan);
+ scsi_autopm_put_host(shost);
}
mutex_unlock(&shost->scan_mutex);
shost_for_each_device(sdev, shost) {
if (!scsi_host_scan_allowed(shost) ||
scsi_sysfs_add_sdev(sdev) != 0)
- scsi_destroy_sdev(sdev);
+ __scsi_remove_device(sdev);
}
}
static int do_scan_async(void *_data)
{
struct async_scan_data *data = _data;
- do_scsi_scan_host(data->shost);
+ struct Scsi_Host *shost = data->shost;
+
+ do_scsi_scan_host(shost);
scsi_finish_async_scan(data);
+ scsi_autopm_put_host(shost);
return 0;
}
if (strncmp(scsi_scan_type, "none", 4) == 0)
return;
+ if (scsi_autopm_get_host(shost) < 0)
+ return;
data = scsi_prep_async_scan(shost);
if (!data) {
do_scsi_scan_host(shost);
+ scsi_autopm_put_host(shost);
return;
}
p = kthread_run(do_scan_async, data, "scsi_scan_%d", shost->host_no);
if (IS_ERR(p))
do_scan_async(data);
+ /* scsi_autopm_put_host(shost) is called in do_scan_async() */
}
EXPORT_SYMBOL(scsi_scan_host);
spin_unlock_irqrestore(shost->host_lock, flags);
}
-/*
- * Function: scsi_get_host_dev()
- *
- * Purpose: Create a scsi_device that points to the host adapter itself.
- *
- * Arguments: SHpnt - Host that needs a scsi_device
+/**
+ * scsi_get_host_dev - Create a scsi_device that points to the host adapter itself
+ * @shost: Host that needs a scsi_device
*
* Lock status: None assumed.
*
*
* Note - this device is not accessible from any high-level
* drivers (including generics), which is probably not
- * optimal. We can add hooks later to attach
+ * optimal. We can add hooks later to attach.
*/
struct scsi_device *scsi_get_host_dev(struct Scsi_Host *shost)
{
goto out;
sdev = scsi_alloc_sdev(starget, 0, NULL);
- if (sdev) {
- sdev->sdev_gendev.parent = get_device(&starget->dev);
+ if (sdev)
sdev->borken = 0;
- } else
+ else
scsi_target_reap(starget);
put_device(&starget->dev);
out:
}
EXPORT_SYMBOL(scsi_get_host_dev);
-/*
- * Function: scsi_free_host_dev()
- *
- * Purpose: Free a scsi_device that points to the host adapter itself.
- *
- * Arguments: SHpnt - Host that needs a scsi_device
+/**
+ * scsi_free_host_dev - Free a scsi_device that points to the host adapter itself
+ * @sdev: Host device to be freed
*
* Lock status: None assumed.
*
* Returns: Nothing
- *
- * Notes:
*/
void scsi_free_host_dev(struct scsi_device *sdev)
{
BUG_ON(sdev->id != sdev->host->this_id);
- scsi_destroy_sdev(sdev);
+ __scsi_remove_device(sdev);
}
EXPORT_SYMBOL(scsi_free_host_dev);