mirror of https://gitee.com/openkylin/linux.git
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);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @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)
|
||||
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;
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
Loading…
Reference in New Issue