summaryrefslogtreecommitdiffstats
path: root/drivers/scsi/isci
diff options
context:
space:
mode:
authorJeff Skirvin <jeffrey.d.skirvin@intel.com>2012-03-08 22:41:54 -0800
committerDan Williams <dan.j.williams@intel.com>2012-05-17 14:33:38 -0700
commit14aaa9f0a318bd04cbb9d822524b817e95d8b343 (patch)
tree5f6292ec671d0993c1df51586dea4fb7750d1cd9 /drivers/scsi/isci
parentd80ecd5726ce49b5da457d562804b40f0183e8f7 (diff)
isci: Redesign device suspension, abort, cleanup.
This commit changes the means by which outstanding I/Os are handled for cleanup. The likelihood is that this commit will be broken into smaller pieces, however that will be a later revision. Among the changes: - All completion structures have been removed from the tmf and abort paths. - Now using one completed I/O list, with the I/O completed in host bit being used to select error or normal callback paths. 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')
-rw-r--r--drivers/scsi/isci/host.c86
-rw-r--r--drivers/scsi/isci/host.h1
-rw-r--r--drivers/scsi/isci/init.c1
-rw-r--r--drivers/scsi/isci/remote_device.c255
-rw-r--r--drivers/scsi/isci/remote_device.h15
-rw-r--r--drivers/scsi/isci/remote_node_context.c23
-rw-r--r--drivers/scsi/isci/remote_node_context.h4
-rw-r--r--drivers/scsi/isci/request.c509
-rw-r--r--drivers/scsi/isci/request.h108
-rw-r--r--drivers/scsi/isci/task.c758
-rw-r--r--drivers/scsi/isci/task.h132
11 files changed, 418 insertions, 1474 deletions
diff --git a/drivers/scsi/isci/host.c b/drivers/scsi/isci/host.c
index d241b5722eb3..25d537e2f5c4 100644
--- a/drivers/scsi/isci/host.c
+++ b/drivers/scsi/isci/host.c
@@ -1089,33 +1089,25 @@ void isci_host_completion_routine(unsigned long data)
{
struct isci_host *ihost = (struct isci_host *)data;
struct list_head completed_request_list;
- struct list_head errored_request_list;
struct list_head *current_position;
struct list_head *next_position;
struct isci_request *request;
- struct isci_request *next_request;
struct sas_task *task;
u16 active;
INIT_LIST_HEAD(&completed_request_list);
- INIT_LIST_HEAD(&errored_request_list);
spin_lock_irq(&ihost->scic_lock);
sci_controller_completion_handler(ihost);
/* Take the lists of completed I/Os from the host. */
-
list_splice_init(&ihost->requests_to_complete,
&completed_request_list);
- /* Take the list of errored I/Os from the host. */
- list_splice_init(&ihost->requests_to_errorback,
- &errored_request_list);
-
spin_unlock_irq(&ihost->scic_lock);
- /* Process any completions in the lists. */
+ /* Process any completions in the list. */
list_for_each_safe(current_position, next_position,
&completed_request_list) {
@@ -1123,23 +1115,30 @@ void isci_host_completion_routine(unsigned long data)
completed_node);
task = isci_request_access_task(request);
- /* Normal notification (task_done) */
- dev_dbg(&ihost->pdev->dev,
- "%s: Normal - request/task = %p/%p\n",
- __func__,
- request,
- task);
/* Return the task to libsas */
if (task != NULL) {
task->lldd_task = NULL;
- if (!(task->task_state_flags & SAS_TASK_STATE_ABORTED)) {
-
- /* If the task is already in the abort path,
- * the task_done callback cannot be called.
- */
- task->task_done(task);
+ if (!test_bit(IREQ_ABORT_PATH_ACTIVE, &request->flags) &&
+ !(task->task_state_flags & SAS_TASK_STATE_ABORTED)) {
+ if (test_bit(IREQ_COMPLETE_IN_TARGET,
+ &request->flags)) {
+
+ /* Normal notification (task_done) */
+ dev_dbg(&ihost->pdev->dev, "%s: Normal"
+ " - request/task = %p/%p\n",
+ __func__, request, task);
+
+ task->task_done(task);
+ } else {
+ dev_warn(&ihost->pdev->dev,
+ "%s: Error - request/task"
+ " = %p/%p\n",
+ __func__, request, task);
+
+ sas_task_abort(task);
+ }
}
}
@@ -1147,44 +1146,6 @@ void isci_host_completion_routine(unsigned long data)
isci_free_tag(ihost, request->io_tag);
spin_unlock_irq(&ihost->scic_lock);
}
- list_for_each_entry_safe(request, next_request, &errored_request_list,
- completed_node) {
-
- task = isci_request_access_task(request);
-
- /* Use sas_task_abort */
- dev_warn(&ihost->pdev->dev,
- "%s: Error - request/task = %p/%p\n",
- __func__,
- request,
- task);
-
- if (task != NULL) {
-
- /* Put the task into the abort path if it's not there
- * already.
- */
- if (!(task->task_state_flags & SAS_TASK_STATE_ABORTED))
- sas_task_abort(task);
-
- } else {
- /* This is a case where the request has completed with a
- * status such that it needed further target servicing,
- * but the sas_task reference has already been removed
- * from the request. Since it was errored, it was not
- * being aborted, so there is nothing to do except free
- * it.
- */
-
- spin_lock_irq(&ihost->scic_lock);
- /* Remove the request from the remote device's list
- * of pending requests.
- */
- list_del_init(&request->dev_node);
- isci_free_tag(ihost, request->io_tag);
- spin_unlock_irq(&ihost->scic_lock);
- }
- }
/* the coalesence timeout doubles at each encoding step, so
* update it based on the ilog2 value of the outstanding requests
@@ -2345,7 +2306,6 @@ static int sci_controller_dma_alloc(struct isci_host *ihost)
ireq->tc = &ihost->task_context_table[i];
ireq->owning_controller = ihost;
- spin_lock_init(&ireq->state_lock);
ireq->request_daddr = dma;
ireq->isci_host = ihost;
ihost->reqs[i] = ireq;
@@ -2697,6 +2657,10 @@ enum sci_status sci_controller_terminate_request(struct isci_host *ihost,
return SCI_FAILURE_INVALID_STATE;
}
status = sci_io_request_terminate(ireq);
+
+ dev_dbg(&ihost->pdev->dev, "%s: status=%d; ireq=%p; flags=%lx\n",
+ __func__, status, ireq, ireq->flags);
+
if ((status == SCI_SUCCESS) &&
!test_bit(IREQ_PENDING_ABORT, &ireq->flags) &&
!test_and_set_bit(IREQ_TC_ABORT_POSTED, &ireq->flags)) {
@@ -2739,6 +2703,8 @@ enum sci_status sci_controller_complete_io(struct isci_host *ihost,
index = ISCI_TAG_TCI(ireq->io_tag);
clear_bit(IREQ_ACTIVE, &ireq->flags);
+ if (test_bit(IREQ_ABORT_PATH_ACTIVE, &ireq->flags))
+ wake_up_all(&ihost->eventq);
return SCI_SUCCESS;
default:
dev_warn(&ihost->pdev->dev, "%s invalid state: %d\n",
diff --git a/drivers/scsi/isci/host.h b/drivers/scsi/isci/host.h
index 7272a0a375f2..eaa13c0be09a 100644
--- a/drivers/scsi/isci/host.h
+++ b/drivers/scsi/isci/host.h
@@ -205,7 +205,6 @@ struct isci_host {
wait_queue_head_t eventq;
struct tasklet_struct completion_tasklet;
struct list_head requests_to_complete;
- struct list_head requests_to_errorback;
spinlock_t scic_lock;
struct isci_request *reqs[SCI_MAX_IO_REQUESTS];
struct isci_remote_device devices[SCI_MAX_REMOTE_DEVICES];
diff --git a/drivers/scsi/isci/init.c b/drivers/scsi/isci/init.c
index 9e1c83e425ed..39f12703b893 100644
--- a/drivers/scsi/isci/init.c
+++ b/drivers/scsi/isci/init.c
@@ -556,7 +556,6 @@ static struct isci_host *isci_host_alloc(struct pci_dev *pdev, int id)
}
INIT_LIST_HEAD(&ihost->requests_to_complete);
- INIT_LIST_HEAD(&ihost->requests_to_errorback);
for (i = 0; i < SCI_MAX_PORTS; i++) {
struct isci_port *iport = &ihost->ports[i];
diff --git a/drivers/scsi/isci/remote_device.c b/drivers/scsi/isci/remote_device.c
index 3048e02aeb7b..c47304cea45d 100644
--- a/drivers/scsi/isci/remote_device.c
+++ b/drivers/scsi/isci/remote_device.c
@@ -81,49 +81,6 @@ static enum sci_status sci_remote_device_suspend(struct isci_remote_device *idev
}
/**
- * isci_remote_device_not_ready() - This function is called by the ihost when
- * the remote device is not ready. We mark the isci device as ready (not
- * "ready_for_io") and signal the waiting proccess.
- * @isci_host: This parameter specifies the isci host object.
- * @isci_device: This parameter specifies the remote device
- *
- * sci_lock is held on entrance to this function.
- */
-static void isci_remote_device_not_ready(struct isci_host *ihost,
- struct isci_remote_device *idev, u32 reason)
-{
- struct isci_request *ireq;
-
- dev_dbg(&ihost->pdev->dev,
- "%s: isci_device = %p\n", __func__, idev);
-
- switch (reason) {
- case SCIC_REMOTE_DEVICE_NOT_READY_STOP_REQUESTED:
- set_bit(IDEV_GONE, &idev->flags);
- break;
- case SCIC_REMOTE_DEVICE_NOT_READY_SATA_SDB_ERROR_FIS_RECEIVED:
- set_bit(IDEV_IO_NCQERROR, &idev->flags);
-
- /* Suspend the remote device so the I/O can be terminated. */
- sci_remote_device_suspend(idev);
-
- /* Kill all outstanding requests for the device. */
- list_for_each_entry(ireq, &idev->reqs_in_process, dev_node) {
-
- dev_dbg(&ihost->pdev->dev,
- "%s: isci_device = %p request = %p\n",
- __func__, idev, ireq);
-
- sci_controller_terminate_request(ihost, idev, ireq);
- }
- /* Fall through into the default case... */
- default:
- clear_bit(IDEV_IO_READY, &idev->flags);
- break;
- }
-}
-
-/**
* isci_remote_device_ready() - This function is called by the ihost when the
* remote device is ready. We mark the isci device as ready and signal the
* waiting proccess.
@@ -142,49 +99,121 @@ static void isci_remote_device_ready(struct isci_host *ihost, struct isci_remote
wake_up(&ihost->eventq);
}
-static int isci_remote_device_suspendcheck(struct isci_remote_device *idev)
+static enum sci_status sci_remote_device_terminate_req(
+ struct isci_host *ihost,
+ struct isci_remote_device *idev,
+ int check_abort,
+ struct isci_request *ireq)
+{
+ dev_dbg(&ihost->pdev->dev,
+ "%s: idev=%p; flags=%lx; req=%p; req target=%p\n",
+ __func__, idev, idev->flags, ireq, ireq->target_device);
+
+ if (!test_bit(IREQ_ACTIVE, &ireq->flags) ||
+ (ireq->target_device != idev) ||
+ (check_abort && !test_bit(IREQ_PENDING_ABORT, &ireq->flags)))
+ return SCI_SUCCESS;
+
+ set_bit(IREQ_ABORT_PATH_ACTIVE, &ireq->flags);
+
+ return sci_controller_terminate_request(ihost, idev, ireq);
+}
+
+static enum sci_status sci_remote_device_terminate_reqs_checkabort(
+ struct isci_remote_device *idev,
+ int chk)
{
- return test_bit(IDEV_TXRX_SUSPENDED, &idev->flags)
- || !test_bit(IDEV_ALLOCATED, &idev->flags);
+ struct isci_host *ihost = idev->owning_port->owning_controller;
+ enum sci_status status = SCI_SUCCESS;
+ u32 i;
+
+ for (i = 0; i < SCI_MAX_IO_REQUESTS; i++) {
+ struct isci_request *ireq = ihost->reqs[i];
+ enum sci_status s;
+
+ s = sci_remote_device_terminate_req(ihost, idev, chk, ireq);
+ if (s != SCI_SUCCESS)
+ status = s;
+ }
+ return status;
}
-enum sci_status isci_remote_device_suspend(
+enum sci_status isci_remote_device_terminate_requests(
struct isci_host *ihost,
- struct isci_remote_device *idev)
+ struct isci_remote_device *idev,
+ struct isci_request *ireq)
{
- enum sci_status status;
+ enum sci_status status = SCI_SUCCESS;
unsigned long flags;
spin_lock_irqsave(&ihost->scic_lock, flags);
- if (isci_get_device(idev->domain_dev) == NULL) {
+ if (isci_get_device(idev) == NULL) {
+ dev_dbg(&ihost->pdev->dev, "%s: failed isci_get_device(idev=%p)\n",
+ __func__, idev);
spin_unlock_irqrestore(&ihost->scic_lock, flags);
status = SCI_FAILURE;
} else {
- status = sci_remote_device_suspend(idev);
- spin_unlock_irqrestore(&ihost->scic_lock, flags);
- if (status == SCI_SUCCESS) {
- dev_dbg(&ihost->pdev->dev,
- "%s: idev=%p, about to wait\n",
- __func__, idev);
- wait_event(ihost->eventq,
- isci_remote_device_suspendcheck(idev));
- status = test_bit(IDEV_TXRX_SUSPENDED, &idev->flags)
- ? SCI_SUCCESS : SCI_FAILURE;
- dev_dbg(&ihost->pdev->dev,
- "%s: idev=%p, wait done, device is %s\n",
- __func__, idev,
- test_bit(IDEV_TXRX_SUSPENDED, &idev->flags)
- ? "<suspended>" : "<deallocated!>");
+ dev_dbg(&ihost->pdev->dev,
+ "%s: idev=%p, ireq=%p; started_request_count=%d, "
+ "about to wait\n",
+ __func__, idev, ireq, idev->started_request_count);
+ if (ireq) {
+ /* Terminate a specific TC. */
+ sci_remote_device_terminate_req(ihost, idev, 0, ireq);
+ spin_unlock_irqrestore(&ihost->scic_lock, flags);
+ wait_event(ihost->eventq, !test_bit(IREQ_ACTIVE,
+ &ireq->flags));
- } else
- dev_dbg(scirdev_to_dev(idev),
- "%s: sci_remote_device_suspend failed, "
- "status = %d\n", __func__, status);
+ } else {
+ /* Terminate all TCs. */
+ sci_remote_device_terminate_requests(idev);
+ spin_unlock_irqrestore(&ihost->scic_lock, flags);
+ wait_event(ihost->eventq,
+ idev->started_request_count == 0);
+ }
+ dev_dbg(&ihost->pdev->dev, "%s: idev=%p, wait done\n",
+ __func__, idev);
isci_put_device(idev);
}
return status;
}
+/**
+* isci_remote_device_not_ready() - This function is called by the ihost when
+* the remote device is not ready. We mark the isci device as ready (not
+* "ready_for_io") and signal the waiting proccess.
+* @isci_host: This parameter specifies the isci host object.
+* @isci_device: This parameter specifies the remote device
+*
+* sci_lock is held on entrance to this function.
+*/
+static void isci_remote_device_not_ready(struct isci_host *ihost,
+ struct isci_remote_device *idev,
+ u32 reason)
+{
+ dev_dbg(&ihost->pdev->dev,
+ "%s: isci_device = %p\n", __func__, idev);
+
+ switch (reason) {
+ case SCIC_REMOTE_DEVICE_NOT_READY_STOP_REQUESTED:
+ set_bit(IDEV_GONE, &idev->flags);
+ break;
+ case SCIC_REMOTE_DEVICE_NOT_READY_SATA_SDB_ERROR_FIS_RECEIVED:
+ set_bit(IDEV_IO_NCQERROR, &idev->flags);
+
+ /* Suspend the remote device so the I/O can be terminated. */
+ sci_remote_device_suspend(idev);
+
+ /* Kill all outstanding requests for the device. */
+ sci_remote_device_terminate_requests(idev);
+
+ /* Fall through into the default case... */
+ default:
+ clear_bit(IDEV_IO_READY, &idev->flags);
+ break;
+ }
+}
+
/* called once the remote node context is ready to be freed.
* The remote device can now report that its stop operation is complete. none
*/
@@ -196,36 +225,10 @@ static void rnc_destruct_done(void *_dev)
sci_change_state(&idev->sm, SCI_DEV_STOPPED);
}
-static enum sci_status sci_remote_device_terminate_requests_checkabort(
- struct isci_remote_device *idev,
- int check_abort_pending)
-{
- struct isci_host *ihost = idev->owning_port->owning_controller;
- enum sci_status status = SCI_SUCCESS;
- u32 i;
-
- for (i = 0; i < SCI_MAX_IO_REQUESTS; i++) {
- struct isci_request *ireq = ihost->reqs[i];
- enum sci_status s;
-
- if (!test_bit(IREQ_ACTIVE, &ireq->flags) ||
- (ireq->target_device != idev) ||
- (check_abort_pending && !test_bit(IREQ_PENDING_ABORT,
- &ireq->flags)))
- continue;
-
- s = sci_controller_terminate_request(ihost, idev, ireq);
- if (s != SCI_SUCCESS)
- status = s;
- }
-
- return status;
-}
-
enum sci_status sci_remote_device_terminate_requests(
struct isci_remote_device *idev)
{
- return sci_remote_device_terminate_requests_checkabort(idev, 0);
+ return sci_remote_device_terminate_reqs_checkabort(idev, 0);
}
enum sci_status sci_remote_device_stop(struct isci_remote_device *idev,
@@ -771,10 +774,6 @@ enum sci_status sci_remote_device_start_task(struct isci_host *ihost,
if (status != SCI_SUCCESS)
return status;
- status = sci_remote_node_context_start_task(&idev->rnc, ireq);
- if (status != SCI_SUCCESS)
- goto out;
-
status = sci_request_start(ireq);
if (status != SCI_SUCCESS)
goto out;
@@ -796,8 +795,9 @@ enum sci_status sci_remote_device_start_task(struct isci_host *ihost,
sci_remote_node_context_suspend(
&idev->rnc, SCI_SOFTWARE_SUSPENSION,
SCI_SOFTWARE_SUSPEND_EXPECTED_EVENT, NULL, NULL);
- sci_remote_node_context_resume(
- &idev->rnc, sci_remote_device_continue_request, idev);
+
+ status = sci_remote_node_context_start_task(&idev->rnc, ireq,
+ sci_remote_device_continue_request, idev);
out:
sci_remote_device_start_request(idev, ireq, status);
@@ -811,7 +811,9 @@ enum sci_status sci_remote_device_start_task(struct isci_host *ihost,
if (status != SCI_SUCCESS)
return status;
- status = sci_remote_node_context_start_task(&idev->rnc, ireq);
+ /* Resume the RNC as needed: */
+ status = sci_remote_node_context_start_task(&idev->rnc, ireq,
+ NULL, NULL);
if (status != SCI_SUCCESS)
break;
@@ -1322,20 +1324,6 @@ static enum sci_status isci_remote_device_construct(struct isci_port *iport,
return status;
}
-void isci_remote_device_nuke_requests(struct isci_host *ihost, struct isci_remote_device *idev)
-{
- DECLARE_COMPLETION_ONSTACK(aborted_task_completion);
-
- dev_dbg(&ihost->pdev->dev,
- "%s: idev = %p\n", __func__, idev);
-
- /* Cleanup all requests pending for this device. */
- isci_terminate_pending_requests(ihost, idev);
-
- dev_dbg(&ihost->pdev->dev,
- "%s: idev = %p, done\n", __func__, idev);
-}
-
/**
* This function builds the isci_remote_device when a libsas dev_found message
* is received.
@@ -1495,32 +1483,28 @@ int isci_remote_device_found(struct domain_device *dev)
return status == SCI_SUCCESS ? 0 : -ENODEV;
}
-enum sci_status isci_remote_device_reset(
+enum sci_status isci_remote_device_suspend_terminate(
struct isci_host *ihost,
- struct isci_remote_device *idev)
+ struct isci_remote_device *idev,
+ struct isci_request *ireq)
{
unsigned long flags;
enum sci_status status;
- /* Put the device into a reset state so the suspension will not
- * automatically resume.
- */
+ /* Put the device into suspension. */
spin_lock_irqsave(&ihost->scic_lock, flags);
- status = sci_remote_device_reset(idev);
+ sci_remote_device_suspend(idev);
spin_unlock_irqrestore(&ihost->scic_lock, flags);
- if (status != SCI_SUCCESS) {
- dev_dbg(&ihost->pdev->dev,
- "%s: sci_remote_device_reset(%p) returned %d!\n",
- __func__, idev, status);
- return status;
- }
- /* Wait for the device suspend. */
- status = isci_remote_device_suspend(ihost, idev);
- if (status != SCI_SUCCESS) {
+
+ /* Terminate and wait for the completions. */
+ status = isci_remote_device_terminate_requests(ihost, idev, ireq);
+ if (status != SCI_SUCCESS)
dev_dbg(&ihost->pdev->dev,
- "%s: isci_remote_device_suspend(%p) returned %d!\n",
+ "%s: isci_remote_device_terminate_requests(%p) "
+ "returned %d!\n",
__func__, idev, status);
- }
+
+ /* NOTE: RNC resumption is left to the caller! */
return status;
}
@@ -1533,7 +1517,7 @@ int isci_remote_device_is_safe_to_abort(
enum sci_status sci_remote_device_abort_requests_pending_abort(
struct isci_remote_device *idev)
{
- return sci_remote_device_terminate_requests_checkabort(idev, 1);
+ return sci_remote_device_terminate_reqs_checkabort(idev, 1);
}
enum sci_status isci_remote_device_reset_complete(
@@ -1545,7 +1529,6 @@ enum sci_status isci_remote_device_reset_complete(
spin_lock_irqsave(&ihost->scic_lock, flags);
status = sci_remote_device_reset_complete(idev);
- sci_remote_device_resume(idev, NULL, NULL);
spin_unlock_irqrestore(&ihost->scic_lock, flags);
return status;
diff --git a/drivers/scsi/isci/remote_device.h b/drivers/scsi/isci/remote_device.h
index a6a376e200ef..da43698e9eba 100644
--- a/drivers/scsi/isci/remote_device.h
+++ b/drivers/scsi/isci/remote_device.h
@@ -85,7 +85,6 @@ struct isci_remote_device {
#define IDEV_GONE 3
#define IDEV_IO_READY 4
#define IDEV_IO_NCQERROR 5
- #define IDEV_TXRX_SUSPENDED 6
unsigned long flags;
struct kref kref;
struct isci_port *isci_port;
@@ -107,10 +106,8 @@ struct isci_remote_device {
/* device reference routines must be called under sci_lock */
static inline struct isci_remote_device *isci_get_device(
- struct domain_device *dev)
+ struct isci_remote_device *idev)
{
- struct isci_remote_device *idev = dev->lldd_dev;
-
if (idev)
kref_get(&idev->kref);
return idev;
@@ -378,4 +375,14 @@ enum sci_status isci_remote_device_reset(
enum sci_status isci_remote_device_reset_complete(
struct isci_host *ihost,
struct isci_remote_device *idev);
+
+enum sci_status isci_remote_device_suspend_terminate(
+ struct isci_host *ihost,
+ struct isci_remote_device *idev,
+ struct isci_request *ireq);
+
+enum sci_status isci_remote_device_terminate_requests(
+ struct isci_host *ihost,
+ struct isci_remote_device *idev,
+ struct isci_request *ireq);
#endif /* !defined(_ISCI_REMOTE_DEVICE_H_) */
diff --git a/drivers/scsi/isci/remote_node_context.c b/drivers/scsi/isci/remote_node_context.c
index 7a8347e51767..feeca17f0f13 100644
--- a/drivers/scsi/isci/remote_node_context.c
+++ b/drivers/scsi/isci/remote_node_context.c
@@ -317,8 +317,6 @@ static void sci_remote_node_context_tx_rx_suspended_state_enter(struct sci_base_
struct isci_remote_device *idev = rnc_to_dev(rnc);
struct isci_host *ihost = idev->owning_port->owning_controller;
- set_bit(IDEV_TXRX_SUSPENDED, &idev->flags);
-
/* Terminate outstanding requests pending abort. */
sci_remote_device_abort_requests_pending_abort(idev);
@@ -326,16 +324,6 @@ static void sci_remote_node_context_tx_rx_suspended_state_enter(struct sci_base_
sci_remote_node_context_continue_state_transitions(rnc);
}
-static void sci_remote_node_context_tx_rx_suspended_state_exit(
- struct sci_base_state_machine *sm)
-{
- struct sci_remote_node_context *rnc
- = container_of(sm, typeof(*rnc), sm);
- struct isci_remote_device *idev = rnc_to_dev(rnc);
-
- clear_bit(IDEV_TXRX_SUSPENDED, &idev->flags);
-}
-
static void sci_remote_node_context_await_suspend_state_exit(
struct sci_base_state_machine *sm)
{
@@ -366,8 +354,6 @@ static const struct sci_base_state sci_remote_node_context_state_table[] = {
},
[SCI_RNC_TX_RX_SUSPENDED] = {
.enter_state = sci_remote_node_context_tx_rx_suspended_state_enter,
- .exit_state
- = sci_remote_node_context_tx_rx_suspended_state_exit,
},
[SCI_RNC_AWAIT_SUSPENSION] = {
.exit_state = sci_remote_node_context_await_suspend_state_exit,
@@ -671,8 +657,11 @@ enum sci_status sci_remote_node_context_start_io(struct sci_remote_node_context
}
}
-enum sci_status sci_remote_node_context_start_task(struct sci_remote_node_context *sci_rnc,
- struct isci_request *ireq)
+enum sci_status sci_remote_node_context_start_task(
+ struct sci_remote_node_context *sci_rnc,
+ struct isci_request *ireq,
+ scics_sds_remote_node_context_callback cb_fn,
+ void *cb_p)
{
enum scis_sds_remote_node_context_states state;
@@ -684,7 +673,7 @@ enum sci_status sci_remote_node_context_start_task(struct sci_remote_node_contex
return SCI_SUCCESS;
case SCI_RNC_TX_SUSPENDED:
case SCI_RNC_TX_RX_SUSPENDED:
- sci_remote_node_context_resume(sci_rnc, NULL, NULL);
+ sci_remote_node_context_resume(sci_rnc, cb_fn, cb_p);
return SCI_SUCCESS;
default:
dev_warn(scirdev_to_dev(rnc_to_dev(sci_rnc)),
diff --git a/drivers/scsi/isci/remote_node_context.h b/drivers/scsi/isci/remote_node_context.h
index 5ddf88b53133..2870af14edab 100644
--- a/drivers/scsi/isci/remote_node_context.h
+++ b/drivers/scsi/isci/remote_node_context.h
@@ -211,7 +211,9 @@ enum sci_status sci_remote_node_context_resume(struct sci_remote_node_context *s
scics_sds_remote_node_context_callback cb_fn,
void *cb_p);
enum sci_status sci_remote_node_context_start_task(struct sci_remote_node_context *sci_rnc,
- struct isci_request *ireq);
+ struct isci_request *ireq,
+ scics_sds_remote_node_context_callback cb_fn,
+ void *cb_p);
enum sci_status sci_remote_node_context_start_io(struct sci_remote_node_context *sci_rnc,
struct isci_request *ireq);
int sci_remote_node_context_is_safe_to_abort(
diff --git a/drivers/scsi/isci/request.c b/drivers/scsi/isci/request.c
index 1f314d0d71d5..f4e80f31423c 100644
--- a/drivers/scsi/isci/request.c
+++ b/drivers/scsi/isci/request.c
@@ -2491,9 +2491,6 @@ static void isci_request_process_response_iu(
* @request: This parameter is the completed isci_request object.
* @response_ptr: This parameter specifies the service response for the I/O.
* @status_ptr: This parameter specifies the exec status for the I/O.
- * @complete_to_host_ptr: This parameter specifies the action to be taken by
- * the LLDD with respect to completing this request or forcing an abort
- * condition on the I/O.
* @open_rej_reason: This parameter specifies the encoded reason for the
* abandon-class reject.
*
@@ -2504,14 +2501,12 @@ static void isci_request_set_open_reject_status(
struct sas_task *task,
enum service_response *response_ptr,
enum exec_status *status_ptr,
- enum isci_completion_selection *complete_to_host_ptr,
enum sas_open_rej_reason open_rej_reason)
{
/* Task in the target is done. */
set_bit(IREQ_COMPLETE_IN_TARGET, &request->flags);
*response_ptr = SAS_TASK_UNDELIVERED;
*status_ptr = SAS_OPEN_REJECT;
- *complete_to_host_ptr = isci_perform_normal_io_completion;
task->task_status.open_rej_reason = open_rej_reason;
}
@@ -2521,9 +2516,6 @@ static void isci_request_set_open_reject_status(
* @request: This parameter is the completed isci_request object.
* @response_ptr: This parameter specifies the service response for the I/O.
* @status_ptr: This parameter specifies the exec status for the I/O.
- * @complete_to_host_ptr: This parameter specifies the action to be taken by
- * the LLDD with respect to completing this request or forcing an abort
- * condition on the I/O.
*
* none.
*/
@@ -2532,8 +2524,7 @@ static void isci_request_handle_controller_specific_errors(
struct isci_request *request,
struct sas_task *task,
enum service_response *response_ptr,
- enum exec_status *status_ptr,
- enum isci_completion_selection *complete_to_host_ptr)
+ enum exec_status *status_ptr)
{
unsigned int cstatus;
@@ -2574,9 +2565,6 @@ static void isci_request_handle_controller_specific_errors(
*status_ptr = SAS_ABORTED_TASK;
set_bit(IREQ_COMPLETE_IN_TARGET, &request->flags);
-
- *complete_to_host_ptr =
- isci_perform_normal_io_completion;
} else {
/* Task in the target is not done. */
*response_ptr = SAS_TASK_UNDELIVERED;
@@ -2587,9 +2575,6 @@ static void isci_request_handle_controller_specific_errors(
*status_ptr = SAM_STAT_TASK_ABORTED;
clear_bit(IREQ_COMPLETE_IN_TARGET, &request->flags);
-
- *complete_to_host_ptr =
- isci_perform_error_io_completion;
}
break;
@@ -2618,8 +2603,6 @@ static void isci_request_handle_controller_specific_errors(
*status_ptr = SAS_ABORTED_TASK;
set_bit(IREQ_COMPLETE_IN_TARGET, &request->flags);
-
- *complete_to_host_ptr = isci_perform_normal_io_completion;
break;
@@ -2630,7 +2613,7 @@ static void isci_request_handle_controller_specific_errors(
isci_request_set_open_reject_status(
request, task, response_ptr, status_ptr,
- complete_to_host_ptr, SAS_OREJ_WRONG_DEST);
+ SAS_OREJ_WRONG_DEST);
break;
case SCU_TASK_OPEN_REJECT_ZONE_VIOLATION:
@@ -2640,56 +2623,56 @@ static void isci_request_handle_controller_specific_errors(
*/
isci_request_set_open_reject_status(
request, task, response_ptr, status_ptr,
- complete_to_host_ptr, SAS_OREJ_RESV_AB0);
+ SAS_OREJ_RESV_AB0);
break;
case SCU_TASK_OPEN_REJECT_RESERVED_ABANDON_1:
isci_request_set_open_reject_status(
request, task, response_ptr, status_ptr,
- complete_to_host_ptr, SAS_OREJ_RESV_AB1);
+ SAS_OREJ_RESV_AB1);
break;
case SCU_TASK_OPEN_REJECT_RESERVED_ABANDON_2:
isci_request_set_open_reject_status(
request, task, response_ptr, status_ptr,
- complete_to_host_ptr, SAS_OREJ_RESV_AB2);
+ SAS_OREJ_RESV_AB2);
break;
case SCU_TASK_OPEN_REJECT_RESERVED_ABANDON_3:
isci_request_set_open_reject_status(
request, task, response_ptr, status_ptr,
- complete_to_host_ptr, SAS_OREJ_RESV_AB3);
+ SAS_OREJ_RESV_AB3);
break;
case SCU_TASK_OPEN_REJECT_BAD_DESTINATION:
isci_request_set_open_reject_status(
request, task, response_ptr, status_ptr,
- complete_to_host_ptr, SAS_OREJ_BAD_DEST);
+ SAS_OREJ_BAD_DEST);
break;
case SCU_TASK_OPEN_REJECT_STP_RESOURCES_BUSY:
isci_request_set_open_reject_status(
request, task, response_ptr, status_ptr,
- complete_to_host_ptr, SAS_OREJ_STP_NORES);
+ SAS_OREJ_STP_NORES);
break;
case SCU_TASK_OPEN_REJECT_PROTOCOL_NOT_SUPPORTED:
isci_request_set_open_reject_status(
request, task, response_ptr, status_ptr,
- complete_to_host_ptr, SAS_OREJ_EPROTO);
+ SAS_OREJ_EPROTO);
break;
case SCU_TASK_OPEN_REJECT_CONNECTION_RATE_NOT_SUPPORTED:
isci_request_set_open_reject_status(
request, task, response_ptr, status_ptr,
- complete_to_host_ptr, SAS_OREJ_CONN_RATE);
+ SAS_OREJ_CONN_RATE);
break;
case SCU_TASK_DONE_LL_R_ERR:
@@ -2721,95 +2704,12 @@ static void isci_request_handle_controller_specific_errors(
*response_ptr = SAS_TASK_UNDELIVERED;
*status_ptr = SAM_STAT_TASK_ABORTED;
- if (task->task_proto == SAS_PROTOCOL_SMP) {
+ if (task->task_proto == SAS_PROTOCOL_SMP)
set_bit(IREQ_COMPLETE_IN_TARGET, &request->flags);
-
- *complete_to_host_ptr = isci_perform_normal_io_completion;
- } else {
+ else
clear_bit(IREQ_COMPLETE_IN_TARGET, &request->flags);
-
- *complete_to_host_ptr = isci_perform_error_io_completion;
- }
- break;
- }
-}
-
-/**
- * isci_task_save_for_upper_layer_completion() - This function saves the
- * request for later completion to the upper layer driver.
- * @host: This parameter is a pointer to the host on which the the request
- * should be queued (either as an error or success).
- * @request: This parameter is the completed request.
- * @response: This parameter is the response code for the completed task.
- * @status: This parameter is the status code for the completed task.
- *
- * none.
- */
-static void isci_task_save_for_upper_layer_completion(
- struct isci_host *host,
- struct isci_request *request,
- enum service_response response,
- enum exec_status status,
- enum isci_completion_selection task_notification_selection)
-{
- struct sas_task *task = isci_request_access_task(request);
-
- task_notification_selection
- = isci_task_set_completion_status(task, response, status,
- task_notification_selection);
-
- /* Tasks aborted specifically by a call to the lldd_abort_task
- * function should not be completed to the host in the regular path.
- */
- switch (task_notification_selection) {
-
- case isci_perform_normal_io_completion:
- /* Normal notification (task_done) */
-
- /* Add to the completed list. */
- list_add(&request->completed_node,
- &host->requests_to_complete);
-
- /* Take the request off the device's pending request list. */
- list_del_init(&request->dev_node);
- break;
-
- case isci_perform_aborted_io_completion:
- /* No notification to libsas because this request is
- * already in the abort path.
- */
- /* Wake up whatever process was waiting for this
- * request to complete.
- */
- WARN_ON(request->io_request_completion == NULL);
-
- if (request->io_request_completion != NULL) {
-
- /* Signal whoever is waiting that this
- * request is complete.
- */
- complete(request->io_request_completion);
- }
- break;
-
- case isci_perform_error_io_completion:
- /* Use sas_task_abort */
- /* Add to the aborted list. */
- list_add(&request->completed_node,
- &host->requests_to_errorback);
- break;
-
- default:
- /* Add to the error to libsas list. */
- list_add(&request->completed_node,
- &host->requests_to_errorback);
break;
}
- dev_dbg(&host->pdev->dev,
- "%s: %d - task = %p, response=%d (%d), status=%d (%d)\n",
- __func__, task_notification_selection, task,
- (task) ? task->task_status.resp : 0, response,
- (task) ? task->task_status.stat : 0, status);
}
static void isci_process_stp_response(struct sas_task *task, struct dev_to_host_fis *fis)
@@ -2844,9 +2744,6 @@ static void isci_request_io_request_complete(struct isci_host *ihost,
struct isci_remote_device *idev = request->target_device;
enum service_response response = SAS_TASK_UNDELIVERED;
enum exec_status status = SAS_ABORTED_TASK;
- enum isci_request_status request_status;
- enum isci_completion_selection complete_to_host
- = isci_perform_normal_io_completion;
dev_dbg(&ihost->pdev->dev,
"%s: request = %p, task = %p,\n"
@@ -2857,282 +2754,158 @@ static void isci_request_io_request_complete(struct isci_host *ihost,
task->data_dir,
completion_status);
- spin_lock(&request->state_lock);
- request_status = request->status;
-
- /* Decode the request status. Note that if the request has been
- * aborted by a task management function, we don't care
- * what the status is.
- */
- switch (request_status) {
-
- case aborted:
- /* "aborted" indicates that the request was aborted by a task
- * management function, since once a task management request is
- * perfomed by the device, the request only completes because
- * of the subsequent driver terminate.
- *
- * Aborted also means an external thread is explicitly managing
- * this request, so that we do not complete it up the stack.