diff options
author | Dan Williams <dan.j.williams@intel.com> | 2011-05-01 19:51:11 -0400 |
---|---|---|
committer | Dan Williams <dan.j.williams@intel.com> | 2011-07-03 07:04:45 -0400 |
commit | 01bec7788db9d1bb2c594d1f1916096ce6299f38 (patch) | |
tree | de75e6656eac1b75cef1f9b897fddc53c179313d | |
parent | e622571f0f05986b23eba566b73b3abeb5d847d3 (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.c | 265 | ||||
-rw-r--r-- | drivers/scsi/isci/remote_device.h | 1 |
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 | /** | 280 | enum 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 | */ | ||
289 | enum 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 | ||
296 | static bool is_remote_device_ready(struct scic_sds_remote_device *sci_dev) | 372 | 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) | |||
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 | */ | ||
734 | static 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 | */ | ||
766 | static 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 | |||
802 | static 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 | |||
841 | static 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 | |||
853 | static void scic_sds_stp_remote_device_ready_idle_substate_resume_complete_handler(void *_dev) | 799 | static 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 | ||
866 | static 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 | |||
884 | static const struct scic_sds_remote_device_state_handler scic_sds_remote_device_state_handler_table[] = { | 812 | static 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 | */ |
388 | struct scic_sds_remote_device_state_handler { | 388 | struct scic_sds_remote_device_state_handler { |
389 | scic_sds_remote_device_frame_handler_t frame_handler; | ||
390 | }; | 389 | }; |
391 | 390 | ||
392 | /** | 391 | /** |