diff options
author | Jeff Skirvin <jeffrey.d.skirvin@intel.com> | 2012-03-09 01:41:52 -0500 |
---|---|---|
committer | Dan Williams <dan.j.williams@intel.com> | 2012-05-17 17:33:37 -0400 |
commit | 83884014eaaa68834ced39d1c75f1bc20d618ec0 (patch) | |
tree | 1a54f8c3b64b95938d0499412a37c780ecb84c5f /drivers/scsi/isci | |
parent | 23ec2aa947e83d0a172220f361166b8224875221 (diff) |
isci: Remote device stop also suspends the RNC and terminates I/O.
Fixing the remote device state machine to suspend and terminate
all outstanding I/O before the device stopped state is reached.
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/remote_device.c | 23 |
1 files changed, 11 insertions, 12 deletions
diff --git a/drivers/scsi/isci/remote_device.c b/drivers/scsi/isci/remote_device.c index f40d429d2cc0..3048e02aeb7b 100644 --- a/drivers/scsi/isci/remote_device.c +++ b/drivers/scsi/isci/remote_device.c | |||
@@ -263,13 +263,15 @@ enum sci_status sci_remote_device_stop(struct isci_remote_device *idev, | |||
263 | case SCI_SMP_DEV_IDLE: | 263 | case SCI_SMP_DEV_IDLE: |
264 | case SCI_SMP_DEV_CMD: | 264 | case SCI_SMP_DEV_CMD: |
265 | sci_change_state(sm, SCI_DEV_STOPPING); | 265 | sci_change_state(sm, SCI_DEV_STOPPING); |
266 | if (idev->started_request_count == 0) { | 266 | if (idev->started_request_count == 0) |
267 | sci_remote_node_context_destruct(&idev->rnc, | 267 | sci_remote_node_context_destruct(&idev->rnc, |
268 | rnc_destruct_done, idev); | 268 | rnc_destruct_done, |
269 | return SCI_SUCCESS; | 269 | idev); |
270 | } else | 270 | else { |
271 | return sci_remote_device_terminate_requests(idev); | 271 | sci_remote_device_suspend(idev); |
272 | break; | 272 | sci_remote_device_terminate_requests(idev); |
273 | } | ||
274 | return SCI_SUCCESS; | ||
273 | case SCI_DEV_STOPPING: | 275 | case SCI_DEV_STOPPING: |
274 | /* All requests should have been terminated, but if there is an | 276 | /* All requests should have been terminated, but if there is an |
275 | * attempt to stop a device already in the stopping state, then | 277 | * attempt to stop a device already in the stopping state, then |
@@ -1403,14 +1405,8 @@ enum sci_status isci_remote_device_stop(struct isci_host *ihost, struct isci_rem | |||
1403 | spin_lock_irqsave(&ihost->scic_lock, flags); | 1405 | spin_lock_irqsave(&ihost->scic_lock, flags); |
1404 | idev->domain_dev->lldd_dev = NULL; /* disable new lookups */ | 1406 | idev->domain_dev->lldd_dev = NULL; /* disable new lookups */ |
1405 | set_bit(IDEV_GONE, &idev->flags); | 1407 | set_bit(IDEV_GONE, &idev->flags); |
1406 | spin_unlock_irqrestore(&ihost->scic_lock, flags); | ||
1407 | |||
1408 | /* Kill all outstanding requests. */ | ||
1409 | isci_remote_device_nuke_requests(ihost, idev); | ||
1410 | 1408 | ||
1411 | set_bit(IDEV_STOP_PENDING, &idev->flags); | 1409 | set_bit(IDEV_STOP_PENDING, &idev->flags); |
1412 | |||
1413 | spin_lock_irqsave(&ihost->scic_lock, flags); | ||
1414 | status = sci_remote_device_stop(idev, 50); | 1410 | status = sci_remote_device_stop(idev, 50); |
1415 | spin_unlock_irqrestore(&ihost->scic_lock, flags); | 1411 | spin_unlock_irqrestore(&ihost->scic_lock, flags); |
1416 | 1412 | ||
@@ -1420,6 +1416,9 @@ enum sci_status isci_remote_device_stop(struct isci_host *ihost, struct isci_rem | |||
1420 | else | 1416 | else |
1421 | wait_for_device_stop(ihost, idev); | 1417 | wait_for_device_stop(ihost, idev); |
1422 | 1418 | ||
1419 | dev_dbg(&ihost->pdev->dev, | ||
1420 | "%s: isci_device = %p, waiting done.\n", __func__, idev); | ||
1421 | |||
1423 | return status; | 1422 | return status; |
1424 | } | 1423 | } |
1425 | 1424 | ||