isci: unify remote_device frame_handlers
Implement all states in scic_sds_remote_device_frame() and delete the state handler. Reported-by: Christoph Hellwig <hch@lst.de> Signed-off-by: Dan Williams <dan.j.williams@intel.com>
This commit is contained in:
parent
e622571f0f
commit
01bec7788d
@ -277,20 +277,96 @@ enum sci_status scic_sds_remote_device_suspend(struct scic_sds_remote_device *sc
|
|||||||
suspend_type, NULL, NULL);
|
suspend_type, NULL, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
enum sci_status scic_sds_remote_device_frame_handler(struct scic_sds_remote_device *sci_dev,
|
||||||
*
|
u32 frame_index)
|
||||||
* @sci_dev: The remote device for which the event handling is being
|
|
||||||
* requested.
|
|
||||||
* @frame_index: This is the frame index that is being processed.
|
|
||||||
*
|
|
||||||
* This method invokes the frame handler for the remote device state machine
|
|
||||||
* enum sci_status
|
|
||||||
*/
|
|
||||||
enum sci_status scic_sds_remote_device_frame_handler(
|
|
||||||
struct scic_sds_remote_device *sci_dev,
|
|
||||||
u32 frame_index)
|
|
||||||
{
|
{
|
||||||
return sci_dev->state_handlers->frame_handler(sci_dev, frame_index);
|
struct sci_base_state_machine *sm = &sci_dev->state_machine;
|
||||||
|
enum scic_sds_remote_device_states state = sm->current_state_id;
|
||||||
|
struct scic_sds_controller *scic = sci_dev->owning_port->owning_controller;
|
||||||
|
enum sci_status status;
|
||||||
|
|
||||||
|
switch (state) {
|
||||||
|
case SCI_BASE_REMOTE_DEVICE_STATE_INITIAL:
|
||||||
|
case SCI_BASE_REMOTE_DEVICE_STATE_STOPPED:
|
||||||
|
case SCI_BASE_REMOTE_DEVICE_STATE_STARTING:
|
||||||
|
case SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_IDLE:
|
||||||
|
case SCIC_SDS_SMP_REMOTE_DEVICE_READY_SUBSTATE_IDLE:
|
||||||
|
case SCI_BASE_REMOTE_DEVICE_STATE_FINAL:
|
||||||
|
default:
|
||||||
|
dev_warn(scirdev_to_dev(sci_dev), "%s: in wrong state: %d\n",
|
||||||
|
__func__, state);
|
||||||
|
/* Return the frame back to the controller */
|
||||||
|
scic_sds_controller_release_frame(scic, frame_index);
|
||||||
|
return SCI_FAILURE_INVALID_STATE;
|
||||||
|
case SCI_BASE_REMOTE_DEVICE_STATE_READY:
|
||||||
|
case SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ_ERROR:
|
||||||
|
case SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_AWAIT_RESET:
|
||||||
|
case SCI_BASE_REMOTE_DEVICE_STATE_STOPPING:
|
||||||
|
case SCI_BASE_REMOTE_DEVICE_STATE_FAILED:
|
||||||
|
case SCI_BASE_REMOTE_DEVICE_STATE_RESETTING: {
|
||||||
|
struct scic_sds_request *sci_req;
|
||||||
|
struct sci_ssp_frame_header *hdr;
|
||||||
|
|
||||||
|
status = scic_sds_unsolicited_frame_control_get_header(&scic->uf_control,
|
||||||
|
frame_index,
|
||||||
|
(void **)&hdr);
|
||||||
|
if (status != SCI_SUCCESS)
|
||||||
|
return status;
|
||||||
|
|
||||||
|
sci_req = scic_sds_controller_get_io_request_from_tag(scic, hdr->tag);
|
||||||
|
if (sci_req && sci_req->target_device == sci_dev) {
|
||||||
|
/* The IO request is now in charge of releasing the frame */
|
||||||
|
status = sci_req->state_handlers->frame_handler(sci_req,
|
||||||
|
frame_index);
|
||||||
|
} else {
|
||||||
|
/* We could not map this tag to a valid IO
|
||||||
|
* request Just toss the frame and continue
|
||||||
|
*/
|
||||||
|
scic_sds_controller_release_frame(scic, frame_index);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ: {
|
||||||
|
struct sata_fis_header *hdr;
|
||||||
|
|
||||||
|
status = scic_sds_unsolicited_frame_control_get_header(&scic->uf_control,
|
||||||
|
frame_index,
|
||||||
|
(void **)&hdr);
|
||||||
|
if (status != SCI_SUCCESS)
|
||||||
|
return status;
|
||||||
|
|
||||||
|
if (hdr->fis_type == SATA_FIS_TYPE_SETDEVBITS &&
|
||||||
|
(hdr->status & ATA_STATUS_REG_ERROR_BIT)) {
|
||||||
|
sci_dev->not_ready_reason = SCIC_REMOTE_DEVICE_NOT_READY_SATA_SDB_ERROR_FIS_RECEIVED;
|
||||||
|
|
||||||
|
/* TODO Check sactive and complete associated IO if any. */
|
||||||
|
sci_base_state_machine_change_state(sm, SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ_ERROR);
|
||||||
|
} else if (hdr->fis_type == SATA_FIS_TYPE_REGD2H &&
|
||||||
|
(hdr->status & ATA_STATUS_REG_ERROR_BIT)) {
|
||||||
|
/*
|
||||||
|
* Some devices return D2H FIS when an NCQ error is detected.
|
||||||
|
* Treat this like an SDB error FIS ready reason.
|
||||||
|
*/
|
||||||
|
sci_dev->not_ready_reason = SCIC_REMOTE_DEVICE_NOT_READY_SATA_SDB_ERROR_FIS_RECEIVED;
|
||||||
|
sci_base_state_machine_change_state(&sci_dev->state_machine,
|
||||||
|
SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ_ERROR);
|
||||||
|
} else
|
||||||
|
status = SCI_FAILURE;
|
||||||
|
|
||||||
|
scic_sds_controller_release_frame(scic, frame_index);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_CMD:
|
||||||
|
case SCIC_SDS_SMP_REMOTE_DEVICE_READY_SUBSTATE_CMD:
|
||||||
|
/* The device does not process any UF received from the hardware while
|
||||||
|
* in this state. All unsolicited frames are forwarded to the io request
|
||||||
|
* object.
|
||||||
|
*/
|
||||||
|
status = scic_sds_io_request_frame_handler(sci_dev->working_request, frame_index);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool is_remote_device_ready(struct scic_sds_remote_device *sci_dev)
|
static bool is_remote_device_ready(struct scic_sds_remote_device *sci_dev)
|
||||||
@ -720,136 +796,6 @@ static void remote_device_resume_done(void *_dev)
|
|||||||
SCI_BASE_REMOTE_DEVICE_STATE_READY);
|
SCI_BASE_REMOTE_DEVICE_STATE_READY);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @device: The struct scic_sds_remote_device which is then cast into a
|
|
||||||
* struct scic_sds_remote_device.
|
|
||||||
* @frame_index: The frame index for which the struct scic_sds_controller wants this
|
|
||||||
* device object to process.
|
|
||||||
*
|
|
||||||
* This method is the default unsolicited frame handler. It logs a warning,
|
|
||||||
* releases the frame and returns a failure. enum sci_status
|
|
||||||
* SCI_FAILURE_INVALID_STATE
|
|
||||||
*/
|
|
||||||
static enum sci_status scic_sds_remote_device_default_frame_handler(
|
|
||||||
struct scic_sds_remote_device *sci_dev,
|
|
||||||
u32 frame_index)
|
|
||||||
{
|
|
||||||
dev_warn(scirdev_to_dev(sci_dev),
|
|
||||||
"%s: SCIC Remote Device requested to handle frame %x "
|
|
||||||
"while in wrong state %d\n",
|
|
||||||
__func__,
|
|
||||||
frame_index,
|
|
||||||
sci_base_state_machine_get_state(
|
|
||||||
&sci_dev->state_machine));
|
|
||||||
|
|
||||||
/* Return the frame back to the controller */
|
|
||||||
scic_sds_controller_release_frame(
|
|
||||||
scic_sds_remote_device_get_controller(sci_dev), frame_index
|
|
||||||
);
|
|
||||||
|
|
||||||
return SCI_FAILURE_INVALID_STATE;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @device: The struct scic_sds_remote_device which is then cast into a
|
|
||||||
* struct scic_sds_remote_device.
|
|
||||||
* @frame_index: The frame index for which the struct scic_sds_controller wants this
|
|
||||||
* device object to process.
|
|
||||||
*
|
|
||||||
* This method is a general ssp frame handler. In most cases the device object
|
|
||||||
* needs to route the unsolicited frame processing to the io request object.
|
|
||||||
* This method decodes the tag for the io request object and routes the
|
|
||||||
* unsolicited frame to that object. enum sci_status SCI_FAILURE_INVALID_STATE
|
|
||||||
*/
|
|
||||||
static enum sci_status scic_sds_remote_device_general_frame_handler(
|
|
||||||
struct scic_sds_remote_device *sci_dev,
|
|
||||||
u32 frame_index)
|
|
||||||
{
|
|
||||||
enum sci_status result;
|
|
||||||
struct sci_ssp_frame_header *frame_header;
|
|
||||||
struct scic_sds_request *io_request;
|
|
||||||
|
|
||||||
result = scic_sds_unsolicited_frame_control_get_header(
|
|
||||||
&(scic_sds_remote_device_get_controller(sci_dev)->uf_control),
|
|
||||||
frame_index,
|
|
||||||
(void **)&frame_header
|
|
||||||
);
|
|
||||||
|
|
||||||
if (SCI_SUCCESS == result) {
|
|
||||||
io_request = scic_sds_controller_get_io_request_from_tag(
|
|
||||||
scic_sds_remote_device_get_controller(sci_dev), frame_header->tag);
|
|
||||||
|
|
||||||
if ((io_request == NULL)
|
|
||||||
|| (io_request->target_device != sci_dev)) {
|
|
||||||
/*
|
|
||||||
* We could not map this tag to a valid IO request
|
|
||||||
* Just toss the frame and continue */
|
|
||||||
scic_sds_controller_release_frame(
|
|
||||||
scic_sds_remote_device_get_controller(sci_dev), frame_index
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
/* The IO request is now in charge of releasing the frame */
|
|
||||||
result = io_request->state_handlers->frame_handler(
|
|
||||||
io_request, frame_index);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
static enum sci_status scic_sds_stp_remote_device_ready_ncq_substate_frame_handler(struct scic_sds_remote_device *sci_dev,
|
|
||||||
u32 frame_index)
|
|
||||||
{
|
|
||||||
enum sci_status status;
|
|
||||||
struct sata_fis_header *frame_header;
|
|
||||||
struct scic_sds_controller *scic = sci_dev->owning_port->owning_controller;
|
|
||||||
|
|
||||||
status = scic_sds_unsolicited_frame_control_get_header(&scic->uf_control,
|
|
||||||
frame_index,
|
|
||||||
(void **)&frame_header);
|
|
||||||
if (status != SCI_SUCCESS)
|
|
||||||
return status;
|
|
||||||
|
|
||||||
if (frame_header->fis_type == SATA_FIS_TYPE_SETDEVBITS &&
|
|
||||||
(frame_header->status & ATA_STATUS_REG_ERROR_BIT)) {
|
|
||||||
sci_dev->not_ready_reason = SCIC_REMOTE_DEVICE_NOT_READY_SATA_SDB_ERROR_FIS_RECEIVED;
|
|
||||||
|
|
||||||
/* TODO Check sactive and complete associated IO if any. */
|
|
||||||
|
|
||||||
sci_base_state_machine_change_state(&sci_dev->state_machine,
|
|
||||||
SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ_ERROR);
|
|
||||||
} else if (frame_header->fis_type == SATA_FIS_TYPE_REGD2H &&
|
|
||||||
(frame_header->status & ATA_STATUS_REG_ERROR_BIT)) {
|
|
||||||
/*
|
|
||||||
* Some devices return D2H FIS when an NCQ error is detected.
|
|
||||||
* Treat this like an SDB error FIS ready reason.
|
|
||||||
*/
|
|
||||||
sci_dev->not_ready_reason = SCIC_REMOTE_DEVICE_NOT_READY_SATA_SDB_ERROR_FIS_RECEIVED;
|
|
||||||
|
|
||||||
sci_base_state_machine_change_state(&sci_dev->state_machine,
|
|
||||||
SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ_ERROR);
|
|
||||||
} else
|
|
||||||
status = SCI_FAILURE;
|
|
||||||
|
|
||||||
scic_sds_controller_release_frame(scic, frame_index);
|
|
||||||
|
|
||||||
return status;
|
|
||||||
}
|
|
||||||
|
|
||||||
static enum sci_status scic_sds_stp_remote_device_ready_cmd_substate_frame_handler(
|
|
||||||
struct scic_sds_remote_device *sci_dev,
|
|
||||||
u32 frame_index)
|
|
||||||
{
|
|
||||||
/* The device doe not process any UF received from the hardware while
|
|
||||||
* in this state. All unsolicited frames are forwarded to the io
|
|
||||||
* request object.
|
|
||||||
*/
|
|
||||||
return scic_sds_io_request_frame_handler(sci_dev->working_request,
|
|
||||||
frame_index);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void scic_sds_stp_remote_device_ready_idle_substate_resume_complete_handler(void *_dev)
|
static void scic_sds_stp_remote_device_ready_idle_substate_resume_complete_handler(void *_dev)
|
||||||
{
|
{
|
||||||
struct scic_sds_remote_device *sci_dev = _dev;
|
struct scic_sds_remote_device *sci_dev = _dev;
|
||||||
@ -863,69 +809,36 @@ static void scic_sds_stp_remote_device_ready_idle_substate_resume_complete_handl
|
|||||||
isci_remote_device_ready(scic->ihost, idev);
|
isci_remote_device_ready(scic->ihost, idev);
|
||||||
}
|
}
|
||||||
|
|
||||||
static enum sci_status scic_sds_smp_remote_device_ready_cmd_substate_frame_handler(
|
|
||||||
struct scic_sds_remote_device *sci_dev,
|
|
||||||
u32 frame_index)
|
|
||||||
{
|
|
||||||
enum sci_status status;
|
|
||||||
|
|
||||||
/* The device does not process any UF received from the hardware while
|
|
||||||
* in this state. All unsolicited frames are forwarded to the io request
|
|
||||||
* object.
|
|
||||||
*/
|
|
||||||
status = scic_sds_io_request_frame_handler(
|
|
||||||
sci_dev->working_request,
|
|
||||||
frame_index
|
|
||||||
);
|
|
||||||
|
|
||||||
return status;
|
|
||||||
}
|
|
||||||
|
|
||||||
static const struct scic_sds_remote_device_state_handler scic_sds_remote_device_state_handler_table[] = {
|
static const struct scic_sds_remote_device_state_handler scic_sds_remote_device_state_handler_table[] = {
|
||||||
[SCI_BASE_REMOTE_DEVICE_STATE_INITIAL] = {
|
[SCI_BASE_REMOTE_DEVICE_STATE_INITIAL] = {
|
||||||
.frame_handler = scic_sds_remote_device_default_frame_handler
|
|
||||||
},
|
},
|
||||||
[SCI_BASE_REMOTE_DEVICE_STATE_STOPPED] = {
|
[SCI_BASE_REMOTE_DEVICE_STATE_STOPPED] = {
|
||||||
.frame_handler = scic_sds_remote_device_default_frame_handler
|
|
||||||
},
|
},
|
||||||
[SCI_BASE_REMOTE_DEVICE_STATE_STARTING] = {
|
[SCI_BASE_REMOTE_DEVICE_STATE_STARTING] = {
|
||||||
.frame_handler = scic_sds_remote_device_default_frame_handler
|
|
||||||
},
|
},
|
||||||
[SCI_BASE_REMOTE_DEVICE_STATE_READY] = {
|
[SCI_BASE_REMOTE_DEVICE_STATE_READY] = {
|
||||||
.frame_handler = scic_sds_remote_device_general_frame_handler,
|
|
||||||
},
|
},
|
||||||
[SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_IDLE] = {
|
[SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_IDLE] = {
|
||||||
.frame_handler = scic_sds_remote_device_default_frame_handler
|
|
||||||
},
|
},
|
||||||
[SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_CMD] = {
|
[SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_CMD] = {
|
||||||
.frame_handler = scic_sds_stp_remote_device_ready_cmd_substate_frame_handler
|
|
||||||
},
|
},
|
||||||
[SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ] = {
|
[SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ] = {
|
||||||
.frame_handler = scic_sds_stp_remote_device_ready_ncq_substate_frame_handler
|
|
||||||
},
|
},
|
||||||
[SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ_ERROR] = {
|
[SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ_ERROR] = {
|
||||||
.frame_handler = scic_sds_remote_device_general_frame_handler
|
|
||||||
},
|
},
|
||||||
[SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_AWAIT_RESET] = {
|
[SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_AWAIT_RESET] = {
|
||||||
.frame_handler = scic_sds_remote_device_general_frame_handler
|
|
||||||
},
|
},
|
||||||
[SCIC_SDS_SMP_REMOTE_DEVICE_READY_SUBSTATE_IDLE] = {
|
[SCIC_SDS_SMP_REMOTE_DEVICE_READY_SUBSTATE_IDLE] = {
|
||||||
.frame_handler = scic_sds_remote_device_default_frame_handler
|
|
||||||
},
|
},
|
||||||
[SCIC_SDS_SMP_REMOTE_DEVICE_READY_SUBSTATE_CMD] = {
|
[SCIC_SDS_SMP_REMOTE_DEVICE_READY_SUBSTATE_CMD] = {
|
||||||
.frame_handler = scic_sds_smp_remote_device_ready_cmd_substate_frame_handler
|
|
||||||
},
|
},
|
||||||
[SCI_BASE_REMOTE_DEVICE_STATE_STOPPING] = {
|
[SCI_BASE_REMOTE_DEVICE_STATE_STOPPING] = {
|
||||||
.frame_handler = scic_sds_remote_device_general_frame_handler
|
|
||||||
},
|
},
|
||||||
[SCI_BASE_REMOTE_DEVICE_STATE_FAILED] = {
|
[SCI_BASE_REMOTE_DEVICE_STATE_FAILED] = {
|
||||||
.frame_handler = scic_sds_remote_device_general_frame_handler
|
|
||||||
},
|
},
|
||||||
[SCI_BASE_REMOTE_DEVICE_STATE_RESETTING] = {
|
[SCI_BASE_REMOTE_DEVICE_STATE_RESETTING] = {
|
||||||
.frame_handler = scic_sds_remote_device_general_frame_handler
|
|
||||||
},
|
},
|
||||||
[SCI_BASE_REMOTE_DEVICE_STATE_FINAL] = {
|
[SCI_BASE_REMOTE_DEVICE_STATE_FINAL] = {
|
||||||
.frame_handler = scic_sds_remote_device_default_frame_handler
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -386,7 +386,6 @@ typedef void (*scic_sds_remote_device_ready_not_ready_handler_t)(
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
struct scic_sds_remote_device_state_handler {
|
struct scic_sds_remote_device_state_handler {
|
||||||
scic_sds_remote_device_frame_handler_t frame_handler;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
Loading…
x
Reference in New Issue
Block a user