aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/isci
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/scsi/isci')
-rw-r--r--drivers/scsi/isci/remote_device.c52
-rw-r--r--drivers/scsi/isci/remote_device.h3
2 files changed, 53 insertions, 2 deletions
diff --git a/drivers/scsi/isci/remote_device.c b/drivers/scsi/isci/remote_device.c
index adeda64e512a..37e9bdead6f6 100644
--- a/drivers/scsi/isci/remote_device.c
+++ b/drivers/scsi/isci/remote_device.c
@@ -1289,6 +1289,48 @@ enum sci_status sci_remote_device_resume(
1289 return status; 1289 return status;
1290} 1290}
1291 1291
1292static void isci_remote_device_resume_from_abort_complete(void *cbparam)
1293{
1294 struct isci_remote_device *idev = cbparam;
1295 struct isci_host *ihost = idev->owning_port->owning_controller;
1296 scics_sds_remote_node_context_callback abort_resume_cb =
1297 idev->abort_resume_cb;
1298
1299 dev_dbg(scirdev_to_dev(idev), "%s: passing-along resume: %p\n",
1300 __func__, abort_resume_cb);
1301
1302 if (abort_resume_cb != NULL) {
1303 idev->abort_resume_cb = NULL;
1304 abort_resume_cb(idev->abort_resume_cbparam);
1305 }
1306 clear_bit(IDEV_ABORT_PATH_RESUME_PENDING, &idev->flags);
1307 wake_up(&ihost->eventq);
1308}
1309
1310
1311void isci_remote_device_wait_for_resume_from_abort(
1312 struct isci_host *ihost,
1313 struct isci_remote_device *idev)
1314{
1315 dev_dbg(scirdev_to_dev(idev), "%s: starting resume wait: %p\n",
1316 __func__, idev);
1317
1318 #define MAX_RESUME_MSECS 5
1319 if (!wait_event_timeout(ihost->eventq,
1320 (!test_bit(IDEV_ABORT_PATH_RESUME_PENDING,
1321 &idev->flags)
1322 || test_bit(IDEV_STOP_PENDING, &idev->flags)),
1323 msecs_to_jiffies(MAX_RESUME_MSECS))) {
1324
1325 dev_warn(scirdev_to_dev(idev), "%s: #### Timeout waiting for "
1326 "resume: %p\n", __func__, idev);
1327 }
1328 clear_bit(IDEV_ABORT_PATH_RESUME_PENDING, &idev->flags);
1329
1330 dev_dbg(scirdev_to_dev(idev), "%s: resume wait done: %p\n",
1331 __func__, idev);
1332}
1333
1292enum sci_status isci_remote_device_resume_from_abort( 1334enum sci_status isci_remote_device_resume_from_abort(
1293 struct isci_host *ihost, 1335 struct isci_host *ihost,
1294 struct isci_remote_device *idev) 1336 struct isci_remote_device *idev)
@@ -1300,12 +1342,18 @@ enum sci_status isci_remote_device_resume_from_abort(
1300 /* Preserve any current resume callbacks, for instance from other 1342 /* Preserve any current resume callbacks, for instance from other
1301 * resumptions. 1343 * resumptions.
1302 */ 1344 */
1345 idev->abort_resume_cb = idev->rnc.user_callback;
1346 idev->abort_resume_cbparam = idev->rnc.user_cookie;
1347 set_bit(IDEV_ABORT_PATH_RESUME_PENDING, &idev->flags);
1303 clear_bit(IDEV_ABORT_PATH_ACTIVE, &idev->flags); 1348 clear_bit(IDEV_ABORT_PATH_ACTIVE, &idev->flags);
1304 status = sci_remote_device_resume(idev, idev->rnc.user_callback, 1349 status = sci_remote_device_resume(
1305 idev->rnc.user_cookie); 1350 idev, isci_remote_device_resume_from_abort_complete,
1351 idev);
1306 spin_unlock_irqrestore(&ihost->scic_lock, flags); 1352 spin_unlock_irqrestore(&ihost->scic_lock, flags);
1353 isci_remote_device_wait_for_resume_from_abort(ihost, idev);
1307 return status; 1354 return status;
1308} 1355}
1356
1309/** 1357/**
1310 * sci_remote_device_start() - This method will start the supplied remote 1358 * sci_remote_device_start() - This method will start the supplied remote
1311 * device. This method enables normal IO requests to flow through to the 1359 * device. This method enables normal IO requests to flow through to the
diff --git a/drivers/scsi/isci/remote_device.h b/drivers/scsi/isci/remote_device.h
index 53564c35cf24..ff34c4e8c1b1 100644
--- a/drivers/scsi/isci/remote_device.h
+++ b/drivers/scsi/isci/remote_device.h
@@ -87,6 +87,7 @@ struct isci_remote_device {
87 #define IDEV_IO_NCQERROR 5 87 #define IDEV_IO_NCQERROR 5
88 #define IDEV_RNC_LLHANG_ENABLED 6 88 #define IDEV_RNC_LLHANG_ENABLED 6
89 #define IDEV_ABORT_PATH_ACTIVE 7 89 #define IDEV_ABORT_PATH_ACTIVE 7
90 #define IDEV_ABORT_PATH_RESUME_PENDING 8
90 unsigned long flags; 91 unsigned long flags;
91 struct kref kref; 92 struct kref kref;
92 struct isci_port *isci_port; 93 struct isci_port *isci_port;
@@ -101,6 +102,8 @@ struct isci_remote_device {
101 u32 started_request_count; 102 u32 started_request_count;
102 struct isci_request *working_request; 103 struct isci_request *working_request;
103 u32 not_ready_reason; 104 u32 not_ready_reason;
105 scics_sds_remote_node_context_callback abort_resume_cb;
106 void *abort_resume_cbparam;
104}; 107};
105 108
106#define ISCI_REMOTE_DEVICE_START_TIMEOUT 5000 109#define ISCI_REMOTE_DEVICE_START_TIMEOUT 5000