summaryrefslogtreecommitdiff
path: root/drivers/scsi/isci/task.c
diff options
context:
space:
mode:
authorDan Williams <dan.j.williams@intel.com>2011-06-16 11:26:12 -0700
committerDan Williams <dan.j.williams@intel.com>2011-07-03 04:04:51 -0700
commitf2088267514b39af1a94409168101527769a911c (patch)
tree9155ce7eb3edf40ecdabc690bff34622ecea1294 /drivers/scsi/isci/task.c
parent209fae14fabfd48525e5630bebbbd4ca15090c60 (diff)
isci: kill isci_remote_device_change_state()
Now that "stopping/stopped" are one in the same and signalled by a NULL device pointer the rest of the device status infrastructure can be removed (->status and ->state_lock). The "not ready for i/o state" is replaced with a state flag, and is evaluated under scic_lock so that we don't see transients from taking the device reference to submitting the i/o. This also fixes a potential leakage of can_queue slots in the rare case that SAS_TASK_ABORTED is set at submission. Signed-off-by: Dan Williams <dan.j.williams@intel.com>
Diffstat (limited to 'drivers/scsi/isci/task.c')
-rw-r--r--drivers/scsi/isci/task.c68
1 files changed, 22 insertions, 46 deletions
diff --git a/drivers/scsi/isci/task.c b/drivers/scsi/isci/task.c
index dd5e9de1ffb5..c313bc16c218 100644
--- a/drivers/scsi/isci/task.c
+++ b/drivers/scsi/isci/task.c
@@ -147,10 +147,10 @@ int isci_task_execute_task(struct sas_task *task, int num, gfp_t gfp_flags)
{
struct isci_host *ihost = dev_to_ihost(task->dev);
struct isci_remote_device *idev;
+ enum sci_status status;
unsigned long flags;
+ bool io_ready;
int ret;
- enum sci_status status;
- enum isci_status device_status;
dev_dbg(&ihost->pdev->dev, "%s: num=%d\n", __func__, num);
@@ -163,64 +163,40 @@ int isci_task_execute_task(struct sas_task *task, int num, gfp_t gfp_flags)
}
for_each_sas_task(num, task) {
- dev_dbg(&ihost->pdev->dev,
- "task = %p, num = %d; dev = %p; cmd = %p\n",
- task, num, task->dev, task->uldd_task);
spin_lock_irqsave(&ihost->scic_lock, flags);
idev = isci_lookup_device(task->dev);
+ io_ready = idev ? test_bit(IDEV_IO_READY, &idev->flags) : 0;
spin_unlock_irqrestore(&ihost->scic_lock, flags);
- if (idev)
- device_status = idev->status;
- else
- device_status = isci_freed;
-
- /* From this point onward, any process that needs to guarantee
- * that there is no kernel I/O being started will have to wait
- * for the quiesce spinlock.
- */
-
- if (device_status != isci_ready_for_io) {
+ dev_dbg(&ihost->pdev->dev,
+ "task: %p, num: %d dev: %p idev: %p:%#lx cmd = %p\n",
+ task, num, task->dev, idev, idev ? idev->flags : 0,
+ task->uldd_task);
- /* Forces a retry from scsi mid layer. */
- dev_dbg(&ihost->pdev->dev,
- "%s: task %p: isci_host->status = %d, "
- "device = %p; device_status = 0x%x\n\n",
- __func__,
- task,
- isci_host_get_state(ihost),
- idev,
- device_status);
-
- if (device_status == isci_ready) {
- /* Indicate QUEUE_FULL so that the scsi midlayer
- * retries.
- */
- isci_task_refuse(ihost, task,
- SAS_TASK_COMPLETE,
- SAS_QUEUE_FULL);
- } else {
- /* Else, the device is going down. */
- isci_task_refuse(ihost, task,
- SAS_TASK_UNDELIVERED,
- SAS_DEVICE_UNKNOWN);
- }
+ if (!idev) {
+ isci_task_refuse(ihost, task, SAS_TASK_UNDELIVERED,
+ SAS_DEVICE_UNKNOWN);
+ isci_host_can_dequeue(ihost, 1);
+ } else if (!io_ready) {
+ /* Indicate QUEUE_FULL so that the scsi midlayer
+ * retries.
+ */
+ isci_task_refuse(ihost, task, SAS_TASK_COMPLETE,
+ SAS_QUEUE_FULL);
isci_host_can_dequeue(ihost, 1);
} else {
/* There is a device and it's ready for I/O. */
spin_lock_irqsave(&task->task_state_lock, flags);
if (task->task_state_flags & SAS_TASK_STATE_ABORTED) {
-
+ /* The I/O was aborted. */
spin_unlock_irqrestore(&task->task_state_lock,
flags);
isci_task_refuse(ihost, task,
SAS_TASK_UNDELIVERED,
SAM_STAT_TASK_ABORTED);
-
- /* The I/O was aborted. */
-
+ isci_host_can_dequeue(ihost, 1);
} else {
task->task_state_flags |= SAS_TASK_AT_INITIATOR;
spin_unlock_irqrestore(&task->task_state_lock, flags);
@@ -323,11 +299,11 @@ int isci_task_execute_tmf(struct isci_host *ihost,
/* sanity check, return TMF_RESP_FUNC_FAILED
* if the device is not there and ready.
*/
- if (!isci_device || isci_device->status != isci_ready_for_io) {
+ if (!isci_device || !test_bit(IDEV_IO_READY, &isci_device->flags)) {
dev_dbg(&ihost->pdev->dev,
- "%s: isci_device = %p not ready (%d)\n",
+ "%s: isci_device = %p not ready (%#lx)\n",
__func__,
- isci_device, isci_device->status);
+ isci_device, isci_device ? isci_device->flags : 0);
return TMF_RESP_FUNC_FAILED;
} else
dev_dbg(&ihost->pdev->dev,