Loading drivers/scsi/isci/host.c +11 −11 Original line number Diff line number Diff line Loading @@ -2696,18 +2696,18 @@ enum sci_status sci_controller_terminate_request(struct isci_host *ihost, __func__, ihost->sm.current_state_id); return SCI_FAILURE_INVALID_STATE; } status = sci_io_request_terminate(ireq); if (status != SCI_SUCCESS) return status; /* * Utilize the original post context command and or in the POST_TC_ABORT * request sub-type. if ((status == SCI_SUCCESS) && !test_bit(IREQ_PENDING_ABORT, &ireq->flags) && !test_and_set_bit(IREQ_TC_ABORT_POSTED, &ireq->flags)) { /* Utilize the original post context command and or in the * POST_TC_ABORT request sub-type. */ sci_controller_post_request(ihost, ireq->post_context | SCU_CONTEXT_COMMAND_REQUEST_POST_TC_ABORT); return SCI_SUCCESS; sci_controller_post_request( ihost, ireq->post_context | SCU_CONTEXT_COMMAND_REQUEST_POST_TC_ABORT); } return status; } /** Loading drivers/scsi/isci/remote_device.c +95 −11 Original line number Diff line number Diff line Loading @@ -133,6 +133,50 @@ static void isci_remote_device_ready(struct isci_host *ihost, struct isci_remote wake_up(&ihost->eventq); } static enum sci_status sci_remote_device_suspend( struct isci_remote_device *idev) { return sci_remote_node_context_suspend( &idev->rnc, SCI_SOFTWARE_SUSPENSION, SCI_SOFTWARE_SUSPEND_EXPECTED_EVENT, NULL, NULL); } enum sci_status isci_remote_device_suspend( struct isci_host *ihost, struct isci_remote_device *idev) { enum sci_status status; unsigned long flags; spin_lock_irqsave(&ihost->scic_lock, flags); if (isci_lookup_device(idev->domain_dev) == NULL) { spin_unlock_irqrestore(&ihost->scic_lock, flags); status = SCI_FAILURE; } else { status = sci_remote_device_suspend(idev); spin_unlock_irqrestore(&ihost->scic_lock, flags); if (status == SCI_SUCCESS) { wait_event(ihost->eventq, test_bit(IDEV_TXRX_SUSPENDED, &idev->flags) || !test_bit(IDEV_ALLOCATED, &idev->flags)); status = test_bit(IDEV_TXRX_SUSPENDED, &idev->flags) ? SCI_SUCCESS : SCI_FAILURE; dev_dbg(&ihost->pdev->dev, "%s: idev=%p, wait done, device is %s\n", __func__, idev, test_bit(IDEV_TXRX_SUSPENDED, &idev->flags) ? "<suspended>" : "<deallocated!>"); } isci_put_device(idev); } return status; } /* called once the remote node context is ready to be freed. * The remote device can now report that its stop operation is complete. none */ Loading @@ -144,7 +188,9 @@ static void rnc_destruct_done(void *_dev) sci_change_state(&idev->sm, SCI_DEV_STOPPED); } static enum sci_status sci_remote_device_terminate_requests(struct isci_remote_device *idev) static enum sci_status sci_remote_device_terminate_requests_checkabort( struct isci_remote_device *idev, int check_abort_pending) { struct isci_host *ihost = idev->owning_port->owning_controller; enum sci_status status = SCI_SUCCESS; Loading @@ -155,7 +201,9 @@ static enum sci_status sci_remote_device_terminate_requests(struct isci_remote_d enum sci_status s; if (!test_bit(IREQ_ACTIVE, &ireq->flags) || ireq->target_device != idev) (ireq->target_device != idev) || (check_abort_pending && !test_bit(IREQ_PENDING_ABORT, &ireq->flags))) continue; s = sci_controller_terminate_request(ihost, idev, ireq); Loading @@ -166,6 +214,12 @@ static enum sci_status sci_remote_device_terminate_requests(struct isci_remote_d return status; } enum sci_status sci_remote_device_terminate_requests( struct isci_remote_device *idev) { return sci_remote_device_terminate_requests_checkabort(idev, 0); } enum sci_status sci_remote_device_stop(struct isci_remote_device *idev, u32 timeout) { Loading Loading @@ -265,14 +319,6 @@ enum sci_status sci_remote_device_reset_complete(struct isci_remote_device *idev return SCI_SUCCESS; } enum sci_status sci_remote_device_suspend(struct isci_remote_device *idev) { return sci_remote_node_context_suspend(&idev->rnc, SCI_SOFTWARE_SUSPENSION, SCI_SOFTWARE_SUSPEND_EXPECTED_EVENT, NULL, NULL); } enum sci_status sci_remote_device_frame_handler(struct isci_remote_device *idev, u32 frame_index) { Loading Loading @@ -1413,3 +1459,41 @@ int isci_remote_device_found(struct domain_device *dev) return status == SCI_SUCCESS ? 0 : -ENODEV; } enum sci_status isci_remote_device_reset( struct isci_remote_device *idev) { struct isci_host *ihost = dev_to_ihost(idev->domain_dev); unsigned long flags; enum sci_status status; /* Wait for the device suspend. */ status = isci_remote_device_suspend(ihost, idev); if (status != SCI_SUCCESS) { dev_dbg(&ihost->pdev->dev, "%s: isci_remote_device_suspend(%p) returned %d!\n", __func__, idev, status); return status; } spin_lock_irqsave(&ihost->scic_lock, flags); status = sci_remote_device_reset(idev); spin_unlock_irqrestore(&ihost->scic_lock, flags); if (status != SCI_SUCCESS) { dev_dbg(&ihost->pdev->dev, "%s: sci_remote_device_reset(%p) returned %d!\n", __func__, idev, status); } return status; } int isci_remote_device_is_safe_to_abort( struct isci_remote_device *idev) { return sci_remote_node_context_is_safe_to_abort(&idev->rnc); } enum sci_status sci_remote_device_abort_requests_pending_abort( struct isci_remote_device *idev) { return sci_remote_device_terminate_requests_checkabort(idev, 1); } drivers/scsi/isci/remote_device.h +10 −0 Original line number Diff line number Diff line Loading @@ -85,6 +85,7 @@ struct isci_remote_device { #define IDEV_GONE 3 #define IDEV_IO_READY 4 #define IDEV_IO_NCQERROR 5 #define IDEV_TXRX_SUSPENDED 6 unsigned long flags; struct kref kref; struct isci_port *isci_port; Loading Loading @@ -335,4 +336,13 @@ void sci_remote_device_post_request( struct isci_remote_device *idev, u32 request); enum sci_status sci_remote_device_terminate_requests( struct isci_remote_device *idev); int isci_remote_device_is_safe_to_abort( struct isci_remote_device *idev); enum sci_status sci_remote_device_abort_requests_pending_abort( struct isci_remote_device *idev); #endif /* !defined(_ISCI_REMOTE_DEVICE_H_) */ drivers/scsi/isci/remote_node_context.c +56 −0 Original line number Diff line number Diff line Loading @@ -268,6 +268,8 @@ static void sci_remote_node_context_invalidating_state_enter(struct sci_base_sta { struct sci_remote_node_context *rnc = container_of(sm, typeof(*rnc), sm); /* Terminate outstanding requests pending abort. */ sci_remote_device_abort_requests_pending_abort(rnc_to_dev(rnc)); sci_remote_node_context_invalidate_context_buffer(rnc); } Loading Loading @@ -312,10 +314,28 @@ static void sci_remote_node_context_tx_suspended_state_enter(struct sci_base_sta static void sci_remote_node_context_tx_rx_suspended_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; set_bit(IDEV_TXRX_SUSPENDED, &idev->flags); /* Terminate outstanding requests pending abort. */ sci_remote_device_abort_requests_pending_abort(idev); wake_up(&ihost->eventq); sci_remote_node_context_continue_state_transitions(rnc); } static void sci_remote_node_context_tx_rx_suspended_state_exit( 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); clear_bit(IDEV_TXRX_SUSPENDED, &idev->flags); } static void sci_remote_node_context_await_suspend_state_exit( struct sci_base_state_machine *sm) { Loading Loading @@ -346,6 +366,8 @@ static const struct sci_base_state sci_remote_node_context_state_table[] = { }, [SCI_RNC_TX_RX_SUSPENDED] = { .enter_state = sci_remote_node_context_tx_rx_suspended_state_enter, .exit_state = sci_remote_node_context_tx_rx_suspended_state_exit, }, [SCI_RNC_AWAIT_SUSPENSION] = { .exit_state = sci_remote_node_context_await_suspend_state_exit, Loading Loading @@ -515,6 +537,13 @@ enum sci_status sci_remote_node_context_suspend( struct isci_remote_device *idev = rnc_to_dev(sci_rnc); enum sci_status status = SCI_FAILURE_INVALID_STATE; dev_dbg(scirdev_to_dev(idev), "%s: current state %d, current suspend_type %x dest state %d," " arg suspend_reason %d, arg suspend_type %x", __func__, state, sci_rnc->suspend_type, sci_rnc->destination_state, suspend_reason, suspend_type); /* Disable automatic state continuations if explicitly suspending. */ if (suspend_reason == SCI_SOFTWARE_SUSPENSION) sci_rnc->destination_state Loading Loading @@ -546,7 +575,10 @@ enum sci_status sci_remote_node_context_suspend( sci_rnc->suspend_type = suspend_type; if (status == SCI_SUCCESS) { /* Already in the destination state? */ struct isci_host *ihost = idev->owning_port->owning_controller; sci_remote_node_context_notify_user(sci_rnc); wake_up_all(&ihost->eventq); /* Let observers look. */ return SCI_SUCCESS; } if (suspend_reason == SCI_SOFTWARE_SUSPENSION) { Loading Loading @@ -661,3 +693,27 @@ enum sci_status sci_remote_node_context_start_task(struct sci_remote_node_contex return SCI_FAILURE_INVALID_STATE; } } int sci_remote_node_context_is_safe_to_abort( struct sci_remote_node_context *sci_rnc) { enum scis_sds_remote_node_context_states state; state = sci_rnc->sm.current_state_id; switch (state) { case SCI_RNC_INVALIDATING: case SCI_RNC_TX_RX_SUSPENDED: return 1; case SCI_RNC_POSTING: case SCI_RNC_RESUMING: case SCI_RNC_READY: case SCI_RNC_TX_SUSPENDED: case SCI_RNC_AWAIT_SUSPENSION: case SCI_RNC_INITIAL: return 0; default: dev_warn(scirdev_to_dev(rnc_to_dev(sci_rnc)), "%s: invalid state %d\n", __func__, state); return 0; } } drivers/scsi/isci/remote_node_context.h +2 −0 Original line number Diff line number Diff line Loading @@ -214,5 +214,7 @@ enum sci_status sci_remote_node_context_start_task(struct sci_remote_node_contex struct isci_request *ireq); enum sci_status sci_remote_node_context_start_io(struct sci_remote_node_context *sci_rnc, struct isci_request *ireq); int sci_remote_node_context_is_safe_to_abort( struct sci_remote_node_context *sci_rnc); #endif /* _SCIC_SDS_REMOTE_NODE_CONTEXT_H_ */ Loading
drivers/scsi/isci/host.c +11 −11 Original line number Diff line number Diff line Loading @@ -2696,18 +2696,18 @@ enum sci_status sci_controller_terminate_request(struct isci_host *ihost, __func__, ihost->sm.current_state_id); return SCI_FAILURE_INVALID_STATE; } status = sci_io_request_terminate(ireq); if (status != SCI_SUCCESS) return status; /* * Utilize the original post context command and or in the POST_TC_ABORT * request sub-type. if ((status == SCI_SUCCESS) && !test_bit(IREQ_PENDING_ABORT, &ireq->flags) && !test_and_set_bit(IREQ_TC_ABORT_POSTED, &ireq->flags)) { /* Utilize the original post context command and or in the * POST_TC_ABORT request sub-type. */ sci_controller_post_request(ihost, ireq->post_context | SCU_CONTEXT_COMMAND_REQUEST_POST_TC_ABORT); return SCI_SUCCESS; sci_controller_post_request( ihost, ireq->post_context | SCU_CONTEXT_COMMAND_REQUEST_POST_TC_ABORT); } return status; } /** Loading
drivers/scsi/isci/remote_device.c +95 −11 Original line number Diff line number Diff line Loading @@ -133,6 +133,50 @@ static void isci_remote_device_ready(struct isci_host *ihost, struct isci_remote wake_up(&ihost->eventq); } static enum sci_status sci_remote_device_suspend( struct isci_remote_device *idev) { return sci_remote_node_context_suspend( &idev->rnc, SCI_SOFTWARE_SUSPENSION, SCI_SOFTWARE_SUSPEND_EXPECTED_EVENT, NULL, NULL); } enum sci_status isci_remote_device_suspend( struct isci_host *ihost, struct isci_remote_device *idev) { enum sci_status status; unsigned long flags; spin_lock_irqsave(&ihost->scic_lock, flags); if (isci_lookup_device(idev->domain_dev) == NULL) { spin_unlock_irqrestore(&ihost->scic_lock, flags); status = SCI_FAILURE; } else { status = sci_remote_device_suspend(idev); spin_unlock_irqrestore(&ihost->scic_lock, flags); if (status == SCI_SUCCESS) { wait_event(ihost->eventq, test_bit(IDEV_TXRX_SUSPENDED, &idev->flags) || !test_bit(IDEV_ALLOCATED, &idev->flags)); status = test_bit(IDEV_TXRX_SUSPENDED, &idev->flags) ? SCI_SUCCESS : SCI_FAILURE; dev_dbg(&ihost->pdev->dev, "%s: idev=%p, wait done, device is %s\n", __func__, idev, test_bit(IDEV_TXRX_SUSPENDED, &idev->flags) ? "<suspended>" : "<deallocated!>"); } isci_put_device(idev); } return status; } /* called once the remote node context is ready to be freed. * The remote device can now report that its stop operation is complete. none */ Loading @@ -144,7 +188,9 @@ static void rnc_destruct_done(void *_dev) sci_change_state(&idev->sm, SCI_DEV_STOPPED); } static enum sci_status sci_remote_device_terminate_requests(struct isci_remote_device *idev) static enum sci_status sci_remote_device_terminate_requests_checkabort( struct isci_remote_device *idev, int check_abort_pending) { struct isci_host *ihost = idev->owning_port->owning_controller; enum sci_status status = SCI_SUCCESS; Loading @@ -155,7 +201,9 @@ static enum sci_status sci_remote_device_terminate_requests(struct isci_remote_d enum sci_status s; if (!test_bit(IREQ_ACTIVE, &ireq->flags) || ireq->target_device != idev) (ireq->target_device != idev) || (check_abort_pending && !test_bit(IREQ_PENDING_ABORT, &ireq->flags))) continue; s = sci_controller_terminate_request(ihost, idev, ireq); Loading @@ -166,6 +214,12 @@ static enum sci_status sci_remote_device_terminate_requests(struct isci_remote_d return status; } enum sci_status sci_remote_device_terminate_requests( struct isci_remote_device *idev) { return sci_remote_device_terminate_requests_checkabort(idev, 0); } enum sci_status sci_remote_device_stop(struct isci_remote_device *idev, u32 timeout) { Loading Loading @@ -265,14 +319,6 @@ enum sci_status sci_remote_device_reset_complete(struct isci_remote_device *idev return SCI_SUCCESS; } enum sci_status sci_remote_device_suspend(struct isci_remote_device *idev) { return sci_remote_node_context_suspend(&idev->rnc, SCI_SOFTWARE_SUSPENSION, SCI_SOFTWARE_SUSPEND_EXPECTED_EVENT, NULL, NULL); } enum sci_status sci_remote_device_frame_handler(struct isci_remote_device *idev, u32 frame_index) { Loading Loading @@ -1413,3 +1459,41 @@ int isci_remote_device_found(struct domain_device *dev) return status == SCI_SUCCESS ? 0 : -ENODEV; } enum sci_status isci_remote_device_reset( struct isci_remote_device *idev) { struct isci_host *ihost = dev_to_ihost(idev->domain_dev); unsigned long flags; enum sci_status status; /* Wait for the device suspend. */ status = isci_remote_device_suspend(ihost, idev); if (status != SCI_SUCCESS) { dev_dbg(&ihost->pdev->dev, "%s: isci_remote_device_suspend(%p) returned %d!\n", __func__, idev, status); return status; } spin_lock_irqsave(&ihost->scic_lock, flags); status = sci_remote_device_reset(idev); spin_unlock_irqrestore(&ihost->scic_lock, flags); if (status != SCI_SUCCESS) { dev_dbg(&ihost->pdev->dev, "%s: sci_remote_device_reset(%p) returned %d!\n", __func__, idev, status); } return status; } int isci_remote_device_is_safe_to_abort( struct isci_remote_device *idev) { return sci_remote_node_context_is_safe_to_abort(&idev->rnc); } enum sci_status sci_remote_device_abort_requests_pending_abort( struct isci_remote_device *idev) { return sci_remote_device_terminate_requests_checkabort(idev, 1); }
drivers/scsi/isci/remote_device.h +10 −0 Original line number Diff line number Diff line Loading @@ -85,6 +85,7 @@ struct isci_remote_device { #define IDEV_GONE 3 #define IDEV_IO_READY 4 #define IDEV_IO_NCQERROR 5 #define IDEV_TXRX_SUSPENDED 6 unsigned long flags; struct kref kref; struct isci_port *isci_port; Loading Loading @@ -335,4 +336,13 @@ void sci_remote_device_post_request( struct isci_remote_device *idev, u32 request); enum sci_status sci_remote_device_terminate_requests( struct isci_remote_device *idev); int isci_remote_device_is_safe_to_abort( struct isci_remote_device *idev); enum sci_status sci_remote_device_abort_requests_pending_abort( struct isci_remote_device *idev); #endif /* !defined(_ISCI_REMOTE_DEVICE_H_) */
drivers/scsi/isci/remote_node_context.c +56 −0 Original line number Diff line number Diff line Loading @@ -268,6 +268,8 @@ static void sci_remote_node_context_invalidating_state_enter(struct sci_base_sta { struct sci_remote_node_context *rnc = container_of(sm, typeof(*rnc), sm); /* Terminate outstanding requests pending abort. */ sci_remote_device_abort_requests_pending_abort(rnc_to_dev(rnc)); sci_remote_node_context_invalidate_context_buffer(rnc); } Loading Loading @@ -312,10 +314,28 @@ static void sci_remote_node_context_tx_suspended_state_enter(struct sci_base_sta static void sci_remote_node_context_tx_rx_suspended_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; set_bit(IDEV_TXRX_SUSPENDED, &idev->flags); /* Terminate outstanding requests pending abort. */ sci_remote_device_abort_requests_pending_abort(idev); wake_up(&ihost->eventq); sci_remote_node_context_continue_state_transitions(rnc); } static void sci_remote_node_context_tx_rx_suspended_state_exit( 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); clear_bit(IDEV_TXRX_SUSPENDED, &idev->flags); } static void sci_remote_node_context_await_suspend_state_exit( struct sci_base_state_machine *sm) { Loading Loading @@ -346,6 +366,8 @@ static const struct sci_base_state sci_remote_node_context_state_table[] = { }, [SCI_RNC_TX_RX_SUSPENDED] = { .enter_state = sci_remote_node_context_tx_rx_suspended_state_enter, .exit_state = sci_remote_node_context_tx_rx_suspended_state_exit, }, [SCI_RNC_AWAIT_SUSPENSION] = { .exit_state = sci_remote_node_context_await_suspend_state_exit, Loading Loading @@ -515,6 +537,13 @@ enum sci_status sci_remote_node_context_suspend( struct isci_remote_device *idev = rnc_to_dev(sci_rnc); enum sci_status status = SCI_FAILURE_INVALID_STATE; dev_dbg(scirdev_to_dev(idev), "%s: current state %d, current suspend_type %x dest state %d," " arg suspend_reason %d, arg suspend_type %x", __func__, state, sci_rnc->suspend_type, sci_rnc->destination_state, suspend_reason, suspend_type); /* Disable automatic state continuations if explicitly suspending. */ if (suspend_reason == SCI_SOFTWARE_SUSPENSION) sci_rnc->destination_state Loading Loading @@ -546,7 +575,10 @@ enum sci_status sci_remote_node_context_suspend( sci_rnc->suspend_type = suspend_type; if (status == SCI_SUCCESS) { /* Already in the destination state? */ struct isci_host *ihost = idev->owning_port->owning_controller; sci_remote_node_context_notify_user(sci_rnc); wake_up_all(&ihost->eventq); /* Let observers look. */ return SCI_SUCCESS; } if (suspend_reason == SCI_SOFTWARE_SUSPENSION) { Loading Loading @@ -661,3 +693,27 @@ enum sci_status sci_remote_node_context_start_task(struct sci_remote_node_contex return SCI_FAILURE_INVALID_STATE; } } int sci_remote_node_context_is_safe_to_abort( struct sci_remote_node_context *sci_rnc) { enum scis_sds_remote_node_context_states state; state = sci_rnc->sm.current_state_id; switch (state) { case SCI_RNC_INVALIDATING: case SCI_RNC_TX_RX_SUSPENDED: return 1; case SCI_RNC_POSTING: case SCI_RNC_RESUMING: case SCI_RNC_READY: case SCI_RNC_TX_SUSPENDED: case SCI_RNC_AWAIT_SUSPENSION: case SCI_RNC_INITIAL: return 0; default: dev_warn(scirdev_to_dev(rnc_to_dev(sci_rnc)), "%s: invalid state %d\n", __func__, state); return 0; } }
drivers/scsi/isci/remote_node_context.h +2 −0 Original line number Diff line number Diff line Loading @@ -214,5 +214,7 @@ enum sci_status sci_remote_node_context_start_task(struct sci_remote_node_contex struct isci_request *ireq); enum sci_status sci_remote_node_context_start_io(struct sci_remote_node_context *sci_rnc, struct isci_request *ireq); int sci_remote_node_context_is_safe_to_abort( struct sci_remote_node_context *sci_rnc); #endif /* _SCIC_SDS_REMOTE_NODE_CONTEXT_H_ */