Browse Source

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>
Dan Williams 14 years ago
parent
commit
01bec7788d
2 changed files with 89 additions and 177 deletions
  1. 89 176
      drivers/scsi/isci/remote_device.c
  2. 0 1
      drivers/scsi/isci/remote_device.h

+ 89 - 176
drivers/scsi/isci/remote_device.c

@@ -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
 	}
 };
 

+ 0 - 1
drivers/scsi/isci/remote_device.h

@@ -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;
 };
 
 /**