aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDan Williams <dan.j.williams@intel.com>2011-05-01 19:51:11 -0400
committerDan Williams <dan.j.williams@intel.com>2011-07-03 07:04:45 -0400
commit01bec7788db9d1bb2c594d1f1916096ce6299f38 (patch)
treede75e6656eac1b75cef1f9b897fddc53c179313d
parente622571f0f05986b23eba566b73b3abeb5d847d3 (diff)
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>
-rw-r--r--drivers/scsi/isci/remote_device.c265
-rw-r--r--drivers/scsi/isci/remote_device.h1
2 files changed, 89 insertions, 177 deletions
diff --git a/drivers/scsi/isci/remote_device.c b/drivers/scsi/isci/remote_device.c
index 53f4ecfddce..0295349b40e 100644
--- a/drivers/scsi/isci/remote_device.c
+++ b/drivers/scsi/isci/remote_device.c
@@ -277,20 +277,96 @@ enum sci_status scic_sds_remote_device_suspend(struct scic_sds_remote_device *sc
277 suspend_type, NULL, NULL); 277 suspend_type, NULL, NULL);
278} 278}
279 279
280/** 280enum sci_status scic_sds_remote_device_frame_handler(struct scic_sds_remote_device *sci_dev,
281 * 281 u32 frame_index)
282 * @sci_dev: The remote device for which the event handling is being
283 * requested.
284 * @frame_index: This is the frame index that is being processed.
285 *
286 * This method invokes the frame handler for the remote device state machine
287 * enum sci_status
288 */
289enum sci_status scic_sds_remote_device_frame_handler(
290 struct scic_sds_remote_device *sci_dev,
291 u32 frame_index)
292{ 282{
293 return sci_dev->state_handlers->frame_handler(sci_dev, frame_index); 283 struct sci_base_state_machine *sm = &sci_dev->state_machine;
284 enum scic_sds_remote_device_states state = sm->current_state_id;
285 struct scic_sds_controller *scic = sci_dev->owning_port->owning_controller;
286 enum sci_status status;
287
288 switch (state) {
289 case SCI_BASE_REMOTE_DEVICE_STATE_INITIAL:
290 case SCI_BASE_REMOTE_DEVICE_STATE_STOPPED:
291 case SCI_BASE_REMOTE_DEVICE_STATE_STARTING:
292 case SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_IDLE:
293 case SCIC_SDS_SMP_REMOTE_DEVICE_READY_SUBSTATE_IDLE:
294 case SCI_BASE_REMOTE_DEVICE_STATE_FINAL:
295 default:
296 dev_warn(scirdev_to_dev(sci_dev), "%s: in wrong state: %d\n",
297 __func__, state);
298 /* Return the frame back to the controller */
299 scic_sds_controller_release_frame(scic, frame_index);
300 return SCI_FAILURE_INVALID_STATE;
301 case SCI_BASE_REMOTE_DEVICE_STATE_READY:
302 case SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ_ERROR:
303 case SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_AWAIT_RESET:
304 case SCI_BASE_REMOTE_DEVICE_STATE_STOPPING:
305 case SCI_BASE_REMOTE_DEVICE_STATE_FAILED:
306 case SCI_BASE_REMOTE_DEVICE_STATE_RESETTING: {
307 struct scic_sds_request *sci_req;
308 struct sci_ssp_frame_header *hdr;
309
310 status = scic_sds_unsolicited_frame_control_get_header(&scic->uf_control,
311 frame_index,
312 (void **)&hdr);
313 if (status != SCI_SUCCESS)
314 return status;
315
316 sci_req = scic_sds_controller_get_io_request_from_tag(scic, hdr->tag);
317 if (sci_req && sci_req->target_device == sci_dev) {
318 /* The IO request is now in charge of releasing the frame */
319 status = sci_req->state_handlers->frame_handler(sci_req,
320 frame_index);
321 } else {
322 /* We could not map this tag to a valid IO
323 * request Just toss the frame and continue
324 */
325 scic_sds_controller_release_frame(scic, frame_index);
326 }
327 break;
328 }
329 case SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ: {
330 struct sata_fis_header *hdr;
331
332 status = scic_sds_unsolicited_frame_control_get_header(&scic->uf_control,
333 frame_index,
334 (void **)&hdr);
335 if (status != SCI_SUCCESS)
336 return status;
337
338 if (hdr->fis_type == SATA_FIS_TYPE_SETDEVBITS &&
339 (hdr->status & ATA_STATUS_REG_ERROR_BIT)) {
340 sci_dev->not_ready_reason = SCIC_REMOTE_DEVICE_NOT_READY_SATA_SDB_ERROR_FIS_RECEIVED;
341
342 /* TODO Check sactive and complete associated IO if any. */
343 sci_base_state_machine_change_state(sm, SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ_ERROR);
344 } else if (hdr->fis_type == SATA_FIS_TYPE_REGD2H &&
345 (hdr->status & ATA_STATUS_REG_ERROR_BIT)) {
346 /*
347 * Some devices return D2H FIS when an NCQ error is detected.
348 * Treat this like an SDB error FIS ready reason.
349 */
350 sci_dev->not_ready_reason = SCIC_REMOTE_DEVICE_NOT_READY_SATA_SDB_ERROR_FIS_RECEIVED;
351 sci_base_state_machine_change_state(&sci_dev->state_machine,
352 SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ_ERROR);
353 } else
354 status = SCI_FAILURE;
355
356 scic_sds_controller_release_frame(scic, frame_index);
357 break;
358 }
359 case SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_CMD:
360 case SCIC_SDS_SMP_REMOTE_DEVICE_READY_SUBSTATE_CMD:
361 /* The device does not process any UF received from the hardware while
362 * in this state. All unsolicited frames are forwarded to the io request
363 * object.
364 */
365 status = scic_sds_io_request_frame_handler(sci_dev->working_request, frame_index);
366 break;
367 }
368
369 return status;
294} 370}
295 371
296static bool is_remote_device_ready(struct scic_sds_remote_device *sci_dev) 372static bool is_remote_device_ready(struct scic_sds_remote_device *sci_dev)
@@ -720,136 +796,6 @@ static void remote_device_resume_done(void *_dev)
720 SCI_BASE_REMOTE_DEVICE_STATE_READY); 796 SCI_BASE_REMOTE_DEVICE_STATE_READY);
721} 797}
722 798
723/**
724 *
725 * @device: The struct scic_sds_remote_device which is then cast into a
726 * struct scic_sds_remote_device.
727 * @frame_index: The frame index for which the struct scic_sds_controller wants this
728 * device object to process.
729 *
730 * This method is the default unsolicited frame handler. It logs a warning,
731 * releases the frame and returns a failure. enum sci_status
732 * SCI_FAILURE_INVALID_STATE
733 */
734static enum sci_status scic_sds_remote_device_default_frame_handler(
735 struct scic_sds_remote_device *sci_dev,
736 u32 frame_index)
737{
738 dev_warn(scirdev_to_dev(sci_dev),
739 "%s: SCIC Remote Device requested to handle frame %x "
740 "while in wrong state %d\n",
741 __func__,
742 frame_index,
743 sci_base_state_machine_get_state(
744 &sci_dev->state_machine));
745
746 /* Return the frame back to the controller */
747 scic_sds_controller_release_frame(
748 scic_sds_remote_device_get_controller(sci_dev), frame_index
749 );
750
751 return SCI_FAILURE_INVALID_STATE;
752}
753
754/**
755 *
756 * @device: The struct scic_sds_remote_device which is then cast into a
757 * struct scic_sds_remote_device.
758 * @frame_index: The frame index for which the struct scic_sds_controller wants this
759 * device object to process.
760 *
761 * This method is a general ssp frame handler. In most cases the device object
762 * needs to route the unsolicited frame processing to the io request object.
763 * This method decodes the tag for the io request object and routes the
764 * unsolicited frame to that object. enum sci_status SCI_FAILURE_INVALID_STATE
765 */
766static enum sci_status scic_sds_remote_device_general_frame_handler(
767 struct scic_sds_remote_device *sci_dev,
768 u32 frame_index)
769{
770 enum sci_status result;
771 struct sci_ssp_frame_header *frame_header;
772 struct scic_sds_request *io_request;
773
774 result = scic_sds_unsolicited_frame_control_get_header(
775 &(scic_sds_remote_device_get_controller(sci_dev)->uf_control),
776 frame_index,
777 (void **)&frame_header
778 );
779
780 if (SCI_SUCCESS == result) {
781 io_request = scic_sds_controller_get_io_request_from_tag(
782 scic_sds_remote_device_get_controller(sci_dev), frame_header->tag);
783
784 if ((io_request == NULL)
785 || (io_request->target_device != sci_dev)) {
786 /*
787 * We could not map this tag to a valid IO request
788 * Just toss the frame and continue */
789 scic_sds_controller_release_frame(
790 scic_sds_remote_device_get_controller(sci_dev), frame_index
791 );
792 } else {
793 /* The IO request is now in charge of releasing the frame */
794 result = io_request->state_handlers->frame_handler(
795 io_request, frame_index);
796 }
797 }
798
799 return result;
800}
801
802static enum sci_status scic_sds_stp_remote_device_ready_ncq_substate_frame_handler(struct scic_sds_remote_device *sci_dev,
803 u32 frame_index)
804{
805 enum sci_status status;
806 struct sata_fis_header *frame_header;
807 struct scic_sds_controller *scic = sci_dev->owning_port->owning_controller;
808
809 status = scic_sds_unsolicited_frame_control_get_header(&scic->uf_control,
810 frame_index,
811 (void **)&frame_header);
812 if (status != SCI_SUCCESS)
813 return status;
814
815 if (frame_header->fis_type == SATA_FIS_TYPE_SETDEVBITS &&
816 (frame_header->status & ATA_STATUS_REG_ERROR_BIT)) {
817 sci_dev->not_ready_reason = SCIC_REMOTE_DEVICE_NOT_READY_SATA_SDB_ERROR_FIS_RECEIVED;
818
819 /* TODO Check sactive and complete associated IO if any. */
820
821 sci_base_state_machine_change_state(&sci_dev->state_machine,
822 SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ_ERROR);
823 } else if (frame_header->fis_type == SATA_FIS_TYPE_REGD2H &&
824 (frame_header->status & ATA_STATUS_REG_ERROR_BIT)) {
825 /*
826 * Some devices return D2H FIS when an NCQ error is detected.
827 * Treat this like an SDB error FIS ready reason.
828 */
829 sci_dev->not_ready_reason = SCIC_REMOTE_DEVICE_NOT_READY_SATA_SDB_ERROR_FIS_RECEIVED;
830
831 sci_base_state_machine_change_state(&sci_dev->state_machine,
832 SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ_ERROR);
833 } else
834 status = SCI_FAILURE;
835
836 scic_sds_controller_release_frame(scic, frame_index);
837
838 return status;
839}
840
841static enum sci_status scic_sds_stp_remote_device_ready_cmd_substate_frame_handler(
842 struct scic_sds_remote_device *sci_dev,
843 u32 frame_index)
844{
845 /* The device doe not process any UF received from the hardware while
846 * in this state. All unsolicited frames are forwarded to the io
847 * request object.
848 */
849 return scic_sds_io_request_frame_handler(sci_dev->working_request,
850 frame_index);
851}
852
853static void scic_sds_stp_remote_device_ready_idle_substate_resume_complete_handler(void *_dev) 799static void scic_sds_stp_remote_device_ready_idle_substate_resume_complete_handler(void *_dev)
854{ 800{
855 struct scic_sds_remote_device *sci_dev = _dev; 801 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
863 isci_remote_device_ready(scic->ihost, idev); 809 isci_remote_device_ready(scic->ihost, idev);
864} 810}
865 811
866static enum sci_status scic_sds_smp_remote_device_ready_cmd_substate_frame_handler(
867 struct scic_sds_remote_device *sci_dev,
868 u32 frame_index)
869{
870 enum sci_status status;
871
872 /* The device does not process any UF received from the hardware while
873 * in this state. All unsolicited frames are forwarded to the io request
874 * object.
875 */
876 status = scic_sds_io_request_frame_handler(
877 sci_dev->working_request,
878 frame_index
879 );
880
881 return status;
882}
883
884static const struct scic_sds_remote_device_state_handler scic_sds_remote_device_state_handler_table[] = { 812static const struct scic_sds_remote_device_state_handler scic_sds_remote_device_state_handler_table[] = {
885 [SCI_BASE_REMOTE_DEVICE_STATE_INITIAL] = { 813 [SCI_BASE_REMOTE_DEVICE_STATE_INITIAL] = {
886 .frame_handler = scic_sds_remote_device_default_frame_handler
887 }, 814 },
888 [SCI_BASE_REMOTE_DEVICE_STATE_STOPPED] = { 815 [SCI_BASE_REMOTE_DEVICE_STATE_STOPPED] = {
889 .frame_handler = scic_sds_remote_device_default_frame_handler
890 }, 816 },
891 [SCI_BASE_REMOTE_DEVICE_STATE_STARTING] = { 817 [SCI_BASE_REMOTE_DEVICE_STATE_STARTING] = {
892 .frame_handler = scic_sds_remote_device_default_frame_handler
893 }, 818 },
894 [SCI_BASE_REMOTE_DEVICE_STATE_READY] = { 819 [SCI_BASE_REMOTE_DEVICE_STATE_READY] = {
895 .frame_handler = scic_sds_remote_device_general_frame_handler,
896 }, 820 },
897 [SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_IDLE] = { 821 [SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_IDLE] = {
898 .frame_handler = scic_sds_remote_device_default_frame_handler
899 }, 822 },
900 [SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_CMD] = { 823 [SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_CMD] = {
901 .frame_handler = scic_sds_stp_remote_device_ready_cmd_substate_frame_handler
902 }, 824 },
903 [SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ] = { 825 [SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ] = {
904 .frame_handler = scic_sds_stp_remote_device_ready_ncq_substate_frame_handler
905 }, 826 },
906 [SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ_ERROR] = { 827 [SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ_ERROR] = {
907 .frame_handler = scic_sds_remote_device_general_frame_handler
908 }, 828 },
909 [SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_AWAIT_RESET] = { 829 [SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_AWAIT_RESET] = {
910 .frame_handler = scic_sds_remote_device_general_frame_handler
911 }, 830 },
912 [SCIC_SDS_SMP_REMOTE_DEVICE_READY_SUBSTATE_IDLE] = { 831 [SCIC_SDS_SMP_REMOTE_DEVICE_READY_SUBSTATE_IDLE] = {
913 .frame_handler = scic_sds_remote_device_default_frame_handler
914 }, 832 },
915 [SCIC_SDS_SMP_REMOTE_DEVICE_READY_SUBSTATE_CMD] = { 833 [SCIC_SDS_SMP_REMOTE_DEVICE_READY_SUBSTATE_CMD] = {
916 .frame_handler = scic_sds_smp_remote_device_ready_cmd_substate_frame_handler
917 }, 834 },
918 [SCI_BASE_REMOTE_DEVICE_STATE_STOPPING] = { 835 [SCI_BASE_REMOTE_DEVICE_STATE_STOPPING] = {
919 .frame_handler = scic_sds_remote_device_general_frame_handler
920 }, 836 },
921 [SCI_BASE_REMOTE_DEVICE_STATE_FAILED] = { 837 [SCI_BASE_REMOTE_DEVICE_STATE_FAILED] = {
922 .frame_handler = scic_sds_remote_device_general_frame_handler
923 }, 838 },
924 [SCI_BASE_REMOTE_DEVICE_STATE_RESETTING] = { 839 [SCI_BASE_REMOTE_DEVICE_STATE_RESETTING] = {
925 .frame_handler = scic_sds_remote_device_general_frame_handler
926 }, 840 },
927 [SCI_BASE_REMOTE_DEVICE_STATE_FINAL] = { 841 [SCI_BASE_REMOTE_DEVICE_STATE_FINAL] = {
928 .frame_handler = scic_sds_remote_device_default_frame_handler
929 } 842 }
930}; 843};
931 844
diff --git a/drivers/scsi/isci/remote_device.h b/drivers/scsi/isci/remote_device.h
index e376ec2ff36..1577b126aed 100644
--- a/drivers/scsi/isci/remote_device.h
+++ b/drivers/scsi/isci/remote_device.h
@@ -386,7 +386,6 @@ typedef void (*scic_sds_remote_device_ready_not_ready_handler_t)(
386 * 386 *
387 */ 387 */
388struct scic_sds_remote_device_state_handler { 388struct scic_sds_remote_device_state_handler {
389 scic_sds_remote_device_frame_handler_t frame_handler;
390}; 389};
391 390
392/** 391/**