Commit 01bec778 authored by Dan Williams's avatar Dan Williams

isci: unify remote_device frame_handlers

Implement all states in scic_sds_remote_device_frame() and delete
the state handler.
Reported-by: default avatarChristoph Hellwig <hch@lst.de>
Signed-off-by: default avatarDan Williams <dan.j.williams@intel.com>
parent e622571f
......@@ -277,20 +277,96 @@ enum sci_status scic_sds_remote_device_suspend(struct scic_sds_remote_device *sc
suspend_type, NULL, NULL);
}
/**
*
* @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,
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)
......@@ -720,136 +796,6 @@ static void remote_device_resume_done(void *_dev)
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)
{
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);
}
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[] = {
[SCI_BASE_REMOTE_DEVICE_STATE_INITIAL] = {
.frame_handler = scic_sds_remote_device_default_frame_handler
},
[SCI_BASE_REMOTE_DEVICE_STATE_STOPPED] = {
.frame_handler = scic_sds_remote_device_default_frame_handler
},
[SCI_BASE_REMOTE_DEVICE_STATE_STARTING] = {
.frame_handler = scic_sds_remote_device_default_frame_handler
},
[SCI_BASE_REMOTE_DEVICE_STATE_READY] = {
.frame_handler = scic_sds_remote_device_general_frame_handler,
},
[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] = {
.frame_handler = scic_sds_stp_remote_device_ready_cmd_substate_frame_handler
},
[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] = {
.frame_handler = scic_sds_remote_device_general_frame_handler
},
[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] = {
.frame_handler = scic_sds_remote_device_default_frame_handler
},
[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] = {
.frame_handler = scic_sds_remote_device_general_frame_handler
},
[SCI_BASE_REMOTE_DEVICE_STATE_FAILED] = {
.frame_handler = scic_sds_remote_device_general_frame_handler
},
[SCI_BASE_REMOTE_DEVICE_STATE_RESETTING] = {
.frame_handler = scic_sds_remote_device_general_frame_handler
},
[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 {
scic_sds_remote_device_frame_handler_t frame_handler;
};
/**
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment