Commit 0cce165e authored by Jeff Skirvin's avatar Jeff Skirvin Committed by Dan Williams

isci: Wait for RNC resumption before leaving the abort path.

In the case of TMF execution, or device resets, wait for the RNC to fully
resume before returning to the caller.  This ensures that the remote
device will not fail I/O requests while waiting for the RNC resumption to
complete.
Signed-off-by: default avatarJeff Skirvin <jeffrey.d.skirvin@intel.com>
Signed-off-by: default avatarDan Williams <dan.j.williams@intel.com>
parent d76689e4
...@@ -1289,6 +1289,48 @@ enum sci_status sci_remote_device_resume( ...@@ -1289,6 +1289,48 @@ enum sci_status sci_remote_device_resume(
return status; return status;
} }
static void isci_remote_device_resume_from_abort_complete(void *cbparam)
{
struct isci_remote_device *idev = cbparam;
struct isci_host *ihost = idev->owning_port->owning_controller;
scics_sds_remote_node_context_callback abort_resume_cb =
idev->abort_resume_cb;
dev_dbg(scirdev_to_dev(idev), "%s: passing-along resume: %p\n",
__func__, abort_resume_cb);
if (abort_resume_cb != NULL) {
idev->abort_resume_cb = NULL;
abort_resume_cb(idev->abort_resume_cbparam);
}
clear_bit(IDEV_ABORT_PATH_RESUME_PENDING, &idev->flags);
wake_up(&ihost->eventq);
}
void isci_remote_device_wait_for_resume_from_abort(
struct isci_host *ihost,
struct isci_remote_device *idev)
{
dev_dbg(scirdev_to_dev(idev), "%s: starting resume wait: %p\n",
__func__, idev);
#define MAX_RESUME_MSECS 5
if (!wait_event_timeout(ihost->eventq,
(!test_bit(IDEV_ABORT_PATH_RESUME_PENDING,
&idev->flags)
|| test_bit(IDEV_STOP_PENDING, &idev->flags)),
msecs_to_jiffies(MAX_RESUME_MSECS))) {
dev_warn(scirdev_to_dev(idev), "%s: #### Timeout waiting for "
"resume: %p\n", __func__, idev);
}
clear_bit(IDEV_ABORT_PATH_RESUME_PENDING, &idev->flags);
dev_dbg(scirdev_to_dev(idev), "%s: resume wait done: %p\n",
__func__, idev);
}
enum sci_status isci_remote_device_resume_from_abort( enum sci_status isci_remote_device_resume_from_abort(
struct isci_host *ihost, struct isci_host *ihost,
struct isci_remote_device *idev) struct isci_remote_device *idev)
...@@ -1300,12 +1342,18 @@ enum sci_status isci_remote_device_resume_from_abort( ...@@ -1300,12 +1342,18 @@ enum sci_status isci_remote_device_resume_from_abort(
/* Preserve any current resume callbacks, for instance from other /* Preserve any current resume callbacks, for instance from other
* resumptions. * resumptions.
*/ */
idev->abort_resume_cb = idev->rnc.user_callback;
idev->abort_resume_cbparam = idev->rnc.user_cookie;
set_bit(IDEV_ABORT_PATH_RESUME_PENDING, &idev->flags);
clear_bit(IDEV_ABORT_PATH_ACTIVE, &idev->flags); clear_bit(IDEV_ABORT_PATH_ACTIVE, &idev->flags);
status = sci_remote_device_resume(idev, idev->rnc.user_callback, status = sci_remote_device_resume(
idev->rnc.user_cookie); idev, isci_remote_device_resume_from_abort_complete,
idev);
spin_unlock_irqrestore(&ihost->scic_lock, flags); spin_unlock_irqrestore(&ihost->scic_lock, flags);
isci_remote_device_wait_for_resume_from_abort(ihost, idev);
return status; return status;
} }
/** /**
* sci_remote_device_start() - This method will start the supplied remote * sci_remote_device_start() - This method will start the supplied remote
* device. This method enables normal IO requests to flow through to the * device. This method enables normal IO requests to flow through to the
......
...@@ -87,6 +87,7 @@ struct isci_remote_device { ...@@ -87,6 +87,7 @@ struct isci_remote_device {
#define IDEV_IO_NCQERROR 5 #define IDEV_IO_NCQERROR 5
#define IDEV_RNC_LLHANG_ENABLED 6 #define IDEV_RNC_LLHANG_ENABLED 6
#define IDEV_ABORT_PATH_ACTIVE 7 #define IDEV_ABORT_PATH_ACTIVE 7
#define IDEV_ABORT_PATH_RESUME_PENDING 8
unsigned long flags; unsigned long flags;
struct kref kref; struct kref kref;
struct isci_port *isci_port; struct isci_port *isci_port;
...@@ -101,6 +102,8 @@ struct isci_remote_device { ...@@ -101,6 +102,8 @@ struct isci_remote_device {
u32 started_request_count; u32 started_request_count;
struct isci_request *working_request; struct isci_request *working_request;
u32 not_ready_reason; u32 not_ready_reason;
scics_sds_remote_node_context_callback abort_resume_cb;
void *abort_resume_cbparam;
}; };
#define ISCI_REMOTE_DEVICE_START_TIMEOUT 5000 #define ISCI_REMOTE_DEVICE_START_TIMEOUT 5000
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment