Skip to content

Commit

Permalink
isci: Don't wait for an RNC suspend if it's being destroyed.
Browse files Browse the repository at this point in the history
Make sure that the wait for suspend can handle the RNC destruction case.

Signed-off-by: Jeff Skirvin <jeffrey.d.skirvin@intel.com>
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
  • Loading branch information
Jeff Skirvin authored and Dan Williams committed May 17, 2012
1 parent c5457a8 commit 1f05388
Show file tree
Hide file tree
Showing 3 changed files with 28 additions and 4 deletions.
20 changes: 16 additions & 4 deletions drivers/scsi/isci/remote_device.c
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,12 @@ static bool isci_compare_suspendcount(
u32 localcount)
{
smp_rmb();
return localcount != idev->rnc.suspend_count;

/* Check for a change in the suspend count, or the RNC
* being destroyed.
*/
return (localcount != idev->rnc.suspend_count)
|| sci_remote_node_context_is_being_destroyed(&idev->rnc);
}

static bool isci_check_reqterm(
Expand Down Expand Up @@ -1380,7 +1385,8 @@ enum sci_status isci_remote_device_resume_from_abort(
struct isci_remote_device *idev)
{
unsigned long flags;
enum sci_status status;
enum sci_status status = SCI_SUCCESS;
int destroyed;

spin_lock_irqsave(&ihost->scic_lock, flags);
/* Preserve any current resume callbacks, for instance from other
Expand All @@ -1390,11 +1396,17 @@ enum sci_status isci_remote_device_resume_from_abort(
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);
status = sci_remote_device_resume(
destroyed = sci_remote_node_context_is_being_destroyed(&idev->rnc);
if (!destroyed)
status = sci_remote_device_resume(
idev, isci_remote_device_resume_from_abort_complete,
idev);
spin_unlock_irqrestore(&ihost->scic_lock, flags);
isci_remote_device_wait_for_resume_from_abort(ihost, idev);
if (!destroyed)
isci_remote_device_wait_for_resume_from_abort(ihost, idev);
else
clear_bit(IDEV_ABORT_PATH_RESUME_PENDING, &idev->flags);

return status;
}

Expand Down
5 changes: 5 additions & 0 deletions drivers/scsi/isci/remote_node_context.c
Original file line number Diff line number Diff line change
Expand Up @@ -270,13 +270,18 @@ static void sci_remote_node_context_invalidate_context_buffer(struct sci_remote_
static void sci_remote_node_context_initial_state_enter(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);
struct isci_host *ihost = idev->owning_port->owning_controller;

/* Check to see if we have gotten back to the initial state because
* someone requested to destroy the remote node context object.
*/
if (sm->previous_state_id == SCI_RNC_INVALIDATING) {
rnc->destination_state = RNC_DEST_UNSPECIFIED;
sci_remote_node_context_notify_user(rnc);

smp_wmb();
wake_up(&ihost->eventq);
}
}

Expand Down
7 changes: 7 additions & 0 deletions drivers/scsi/isci/remote_node_context.h
Original file line number Diff line number Diff line change
Expand Up @@ -226,4 +226,11 @@ enum sci_status sci_remote_node_context_start_io(struct sci_remote_node_context
int sci_remote_node_context_is_safe_to_abort(
struct sci_remote_node_context *sci_rnc);

static inline bool sci_remote_node_context_is_being_destroyed(
struct sci_remote_node_context *sci_rnc)
{
return ((sci_rnc->sm.current_state_id == SCI_RNC_INVALIDATING)
&& (sci_rnc->destination_state == RNC_DEST_FINAL))
|| (sci_rnc->sm.current_state_id == SCI_RNC_INITIAL);
}
#endif /* _SCIC_SDS_REMOTE_NODE_CONTEXT_H_ */

0 comments on commit 1f05388

Please sign in to comment.