diff options
author | Jeff Skirvin <jeffrey.d.skirvin@intel.com> | 2011-03-31 16:10:36 -0400 |
---|---|---|
committer | Dan Williams <dan.j.williams@intel.com> | 2011-07-03 07:00:36 -0400 |
commit | ce4f75def3999fbe454da9aa733ed322bc671b06 (patch) | |
tree | 363f8b709731c55d99b316ae0be2705f144b036a /drivers/scsi/isci/request.c | |
parent | f219f010a355487638bf2fff4724a420e7158fd2 (diff) |
isci: Free host lock for SATA/STP abort escalation at submission time.
In the case of I/O requests that fail at submit time because of a
pending reset condition, the host lock for SATA/STP devices must be
managed for any SCSI-initiated I/O before sas_task_abort is called.
Signed-off-by: Jeff Skirvin <jeffrey.d.skirvin@intel.com>
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
Diffstat (limited to 'drivers/scsi/isci/request.c')
-rw-r--r-- | drivers/scsi/isci/request.c | 60 |
1 files changed, 30 insertions, 30 deletions
diff --git a/drivers/scsi/isci/request.c b/drivers/scsi/isci/request.c index c6ce9d0c50c2..946caaeb66c6 100644 --- a/drivers/scsi/isci/request.c +++ b/drivers/scsi/isci/request.c | |||
@@ -53,6 +53,7 @@ | |||
53 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 53 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
54 | */ | 54 | */ |
55 | 55 | ||
56 | #include <scsi/sas_ata.h> | ||
56 | #include "isci.h" | 57 | #include "isci.h" |
57 | #include "scic_remote_device.h" | 58 | #include "scic_remote_device.h" |
58 | #include "scic_io_request.h" | 59 | #include "scic_io_request.h" |
@@ -356,33 +357,6 @@ int isci_request_alloc_tmf( | |||
356 | } | 357 | } |
357 | 358 | ||
358 | /** | 359 | /** |
359 | * isci_request_signal_device_reset() - This function will set the "device | ||
360 | * needs target reset" flag in the given sas_tasks' task_state_flags, and | ||
361 | * then cause the task to be added into the SCSI error handler queue which | ||
362 | * will eventually be escalated to a target reset. | ||
363 | * | ||
364 | * | ||
365 | */ | ||
366 | static void isci_request_signal_device_reset( | ||
367 | struct isci_request *isci_request) | ||
368 | { | ||
369 | unsigned long flags; | ||
370 | struct sas_task *task = isci_request_access_task(isci_request); | ||
371 | |||
372 | dev_dbg(&isci_request->isci_host->pdev->dev, | ||
373 | "%s: request=%p, task=%p\n", __func__, isci_request, task); | ||
374 | |||
375 | spin_lock_irqsave(&task->task_state_lock, flags); | ||
376 | task->task_state_flags |= SAS_TASK_NEED_DEV_RESET; | ||
377 | spin_unlock_irqrestore(&task->task_state_lock, flags); | ||
378 | |||
379 | /* Cause this task to be scheduled in the SCSI error handler | ||
380 | * thread. | ||
381 | */ | ||
382 | sas_task_abort(task); | ||
383 | } | ||
384 | |||
385 | /** | ||
386 | * isci_request_execute() - This function allocates the isci_request object, | 360 | * isci_request_execute() - This function allocates the isci_request object, |
387 | * all fills in some common fields. | 361 | * all fills in some common fields. |
388 | * @isci_host: This parameter specifies the ISCI host object | 362 | * @isci_host: This parameter specifies the ISCI host object |
@@ -453,11 +427,18 @@ int isci_request_execute( | |||
453 | /* Save the tag for possible task mgmt later. */ | 427 | /* Save the tag for possible task mgmt later. */ |
454 | request->io_tag = scic_io_request_get_io_tag( | 428 | request->io_tag = scic_io_request_get_io_tag( |
455 | request->sci_request_handle); | 429 | request->sci_request_handle); |
430 | } else { | ||
431 | /* The request did not really start in the | ||
432 | * hardware, so clear the request handle | ||
433 | * here so no terminations will be done. | ||
434 | */ | ||
435 | request->sci_request_handle = NULL; | ||
456 | } | 436 | } |
437 | |||
457 | } else | 438 | } else |
458 | dev_warn(&isci_host->pdev->dev, | 439 | dev_warn(&isci_host->pdev->dev, |
459 | "%s: failed request start\n", | 440 | "%s: failed request start (0x%x)\n", |
460 | __func__); | 441 | __func__, status); |
461 | 442 | ||
462 | spin_unlock_irqrestore(&isci_host->scic_lock, flags); | 443 | spin_unlock_irqrestore(&isci_host->scic_lock, flags); |
463 | 444 | ||
@@ -467,7 +448,26 @@ int isci_request_execute( | |||
467 | * handler thread to work on this I/O and that | 448 | * handler thread to work on this I/O and that |
468 | * we want a device reset. | 449 | * we want a device reset. |
469 | */ | 450 | */ |
470 | isci_request_signal_device_reset(request); | 451 | spin_lock_irqsave(&task->task_state_lock, flags); |
452 | task->task_state_flags |= SAS_TASK_NEED_DEV_RESET; | ||
453 | spin_unlock_irqrestore(&task->task_state_lock, flags); | ||
454 | |||
455 | /* Cause this task to be scheduled in the SCSI error handler | ||
456 | * thread. | ||
457 | */ | ||
458 | if (dev_is_sata(task->dev)) { | ||
459 | /* Since we are still in the submit path, and since | ||
460 | * libsas takes the host lock on behalf of SATA | ||
461 | * devices before I/O starts, we need to unlock | ||
462 | * before we can put the task in the error path. | ||
463 | */ | ||
464 | raw_local_irq_save(flags); | ||
465 | spin_unlock(isci_host->shost->host_lock); | ||
466 | sas_task_abort(task); | ||
467 | spin_lock(isci_host->shost->host_lock); | ||
468 | raw_local_irq_restore(flags); | ||
469 | } else | ||
470 | sas_task_abort(task); | ||
471 | 471 | ||
472 | /* Change the status, since we are holding | 472 | /* Change the status, since we are holding |
473 | * the I/O until it is managed by the SCSI | 473 | * the I/O until it is managed by the SCSI |