diff options
Diffstat (limited to 'drivers/scsi/isci')
-rw-r--r-- | drivers/scsi/isci/remote_device.c | 52 | ||||
-rw-r--r-- | drivers/scsi/isci/remote_device.h | 3 |
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 | ||
1292 | static 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 | |||
1311 | void 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 | |||
1292 | enum sci_status isci_remote_device_resume_from_abort( | 1334 | enum 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 |