diff --git a/drivers/scsi/isci/core/scic_controller.h b/drivers/scsi/isci/core/scic_controller.h index 1d459d6af21b..481e0de5148b 100644 --- a/drivers/scsi/isci/core/scic_controller.h +++ b/drivers/scsi/isci/core/scic_controller.h @@ -80,62 +80,6 @@ enum sci_controller_mode { }; -/** - * enum _SCIC_INTERRUPT_TYPE - This enumeration depicts the various types of - * interrupts that are potentially supported by a SCI Core implementation. - * - * - */ -enum scic_interrupt_type { - SCIC_LEGACY_LINE_INTERRUPT_TYPE, - SCIC_MSIX_INTERRUPT_TYPE, - - /** - * This enumeration value indicates the use of polling. - */ - SCIC_NO_INTERRUPTS - -}; - -/** - * This method is called by the SCI user in order to have the SCI - * implementation handle the interrupt. This method performs minimal - * processing to allow for streamlined interrupt time usage. - * - * SCIC_CONTROLLER_INTERRUPT_HANDLER true: returned if there is an interrupt to - * process and it was processed. false: returned if no interrupt was processed. - */ -typedef bool (*SCIC_CONTROLLER_INTERRUPT_HANDLER)( - struct scic_sds_controller *controller - ); - -/** - * This method is called by the SCI user to process completions generated as a - * result of a previously handled interrupt. This method will result in the - * completion of IO requests and handling of other controller generated - * events. This method should be called some time after the interrupt - * handler. - * - * Most, if not all, of the user callback APIs are invoked from within this - * API. As a result, the user should be cognizent of the operating level at - * which they invoke this API. - */ -typedef void (*SCIC_CONTROLLER_COMPLETION_HANDLER)( - struct scic_sds_controller *controller - ); - -/** - * struct scic_controller_handler_methods - This structure contains an - * interrupt handler and completion handler function pointers. - * - * - */ -struct scic_controller_handler_methods { - SCIC_CONTROLLER_INTERRUPT_HANDLER interrupt_handler; - SCIC_CONTROLLER_COMPLETION_HANDLER completion_handler; - -}; - /** * scic_controller_construct() - This method will attempt to construct a * controller object utilizing the supplied parameter information. @@ -176,47 +120,6 @@ void scic_controller_enable_interrupts( void scic_controller_disable_interrupts( struct scic_sds_controller *controller); -/** - * scic_controller_get_handler_methods() - This method will return provide - * function pointers for the interrupt handler and completion handler. The - * interrupt handler is expected to be invoked at interrupt time. The - * completion handler is scheduled to run as a result of the interrupt - * handler. The completion handler performs the bulk work for processing - * silicon events. - * @interrupt_type: This parameter informs the core which type of - * interrupt/completion methods are being requested. These are the types: - * SCIC_LEGACY_LINE_INTERRUPT_TYPE, SCIC_MSIX_INTERRUPT_TYPE, - * SCIC_NO_INTERRUPTS (POLLING) - * @message_count: This parameter informs the core the number of MSI-X messages - * to be utilized. This parameter must be 0 when requesting legacy line - * based handlers. - * @handler_methods: The caller provides a pointer to a buffer of type - * struct scic_controller_handler_methods. The size depends on the combination of - * the interrupt_type and message_count input parameters: - * SCIC_LEGACY_LINE_INTERRUPT_TYPE: - size = - * sizeof(struct scic_controller_handler_methods) SCIC_MSIX_INTERRUPT_TYPE: - * sizeof(struct scic_controller_handler_methods) - * @handler_methods: SCIC fills out the caller's buffer with the appropriate - * interrupt and completion handlers based on the info provided in the - * interrupt_type and message_count input parameters. For - * SCIC_LEGACY_LINE_INTERRUPT_TYPE, the buffer receives a single - * struct scic_controller_handler_methods element regardless that the - * message_count parameter is zero. For SCIC_MSIX_INTERRUPT_TYPE, the buffer - * receives an array of elements of type struct scic_controller_handler_methods - * where the array size is equivalent to the message_count parameter. The - * array is zero-relative where entry zero corresponds to message-vector - * zero, entry one corresponds to message-vector one, and so forth. - * - * Indicate if the handler retrieval operation was successful. SCI_SUCCESS This - * value is returned if retrieval succeeded. - * SCI_FAILURE_UNSUPPORTED_MESSAGE_COUNT This value is returned if the user - * supplied an unsupported number of MSI-X messages. For legacy line interrupts - * the only valid value is 0. - */ -enum sci_status scic_controller_get_handler_methods( - enum scic_interrupt_type interrupt_type, - u16 message_count, - struct scic_controller_handler_methods *handler_methods); /** * scic_controller_initialize() - This method will initialize the controller diff --git a/drivers/scsi/isci/core/scic_sds_controller.c b/drivers/scsi/isci/core/scic_sds_controller.c index 7ea36624f568..53861ccbd593 100644 --- a/drivers/scsi/isci/core/scic_sds_controller.c +++ b/drivers/scsi/isci/core/scic_sds_controller.c @@ -1564,340 +1564,6 @@ static void scic_sds_controller_process_completions( } -/** - * This method is a private routine for processing the completion queue entries. - * @this_controller: - * - */ -static void scic_sds_controller_transitioned_process_completions( - struct scic_sds_controller *this_controller) -{ - u32 completion_count = 0; - u32 completion_entry; - u32 get_index; - u32 get_cycle; - u32 event_index; - u32 event_cycle; - - dev_dbg(scic_to_dev(this_controller), - "%s: completion queue begining get:0x%08x\n", - __func__, - this_controller->completion_queue_get); - - /* Get the component parts of the completion queue */ - get_index = NORMALIZE_GET_POINTER(this_controller->completion_queue_get); - get_cycle = SMU_CQGR_CYCLE_BIT & this_controller->completion_queue_get; - - event_index = NORMALIZE_EVENT_POINTER(this_controller->completion_queue_get); - event_cycle = SMU_CQGR_EVENT_CYCLE_BIT & this_controller->completion_queue_get; - - while ( - NORMALIZE_GET_POINTER_CYCLE_BIT(get_cycle) - == COMPLETION_QUEUE_CYCLE_BIT( - this_controller->completion_queue[get_index]) - ) { - completion_count++; - - completion_entry = this_controller->completion_queue[get_index]; - INCREMENT_COMPLETION_QUEUE_GET(this_controller, get_index, get_cycle); - - dev_dbg(scic_to_dev(this_controller), - "%s: completion queue entry:0x%08x\n", - __func__, - completion_entry); - - switch (SCU_GET_COMPLETION_TYPE(completion_entry)) { - case SCU_COMPLETION_TYPE_TASK: - scic_sds_controller_task_completion(this_controller, completion_entry); - break; - - case SCU_COMPLETION_TYPE_NOTIFY: - case SCU_COMPLETION_TYPE_EVENT: - /* - * Presently we do the same thing with a notify event that we - * do with the other event codes. */ - INCREMENT_EVENT_QUEUE_GET(this_controller, event_index, event_cycle); - /* Fall-through */ - - case SCU_COMPLETION_TYPE_SDMA: - case SCU_COMPLETION_TYPE_UFI: - default: - dev_warn(scic_to_dev(this_controller), - "%s: SCIC Controller ignoring completion type " - "%x\n", - __func__, - completion_entry); - break; - } - } - - /* Update the get register if we completed one or more entries */ - if (completion_count > 0) { - this_controller->completion_queue_get = - SMU_CQGR_GEN_BIT(ENABLE) - | SMU_CQGR_GEN_BIT(EVENT_ENABLE) - | event_cycle | SMU_CQGR_GEN_VAL(EVENT_POINTER, event_index) - | get_cycle | SMU_CQGR_GEN_VAL(POINTER, get_index); - - SMU_CQGR_WRITE(this_controller, this_controller->completion_queue_get); - } - - dev_dbg(scic_to_dev(this_controller), - "%s: completion queue ending get:0x%08x\n", - __func__, - this_controller->completion_queue_get); -} - -/* - * ****************************************************************************- - * * SCIC SDS Controller Interrupt and Completion functions - * ****************************************************************************- */ - -/** - * This method provides standard (common) processing of interrupts for polling - * and legacy based interrupts. - * @controller: - * @interrupt_status: - * - * This method returns a boolean (bool) indication as to whether an completions - * are pending to be processed. true if an interrupt is to be processed false - * if no interrupt was pending - */ -static bool scic_sds_controller_standard_interrupt_handler( - struct scic_sds_controller *this_controller, - u32 interrupt_status) -{ - bool is_completion_needed = false; - - if ((interrupt_status & SMU_ISR_QUEUE_ERROR) || - ((interrupt_status & SMU_ISR_QUEUE_SUSPEND) && - (!scic_sds_controller_completion_queue_has_entries( - this_controller)))) { - /* - * We have a fatal error on the read of the completion queue bar - * OR - * We have a fatal error there is nothing in the completion queue - * but we have a report from the hardware that the queue is full - * / @todo how do we request the a controller reset */ - is_completion_needed = true; - this_controller->encountered_fatal_error = true; - } - - if (scic_sds_controller_completion_queue_has_entries(this_controller)) { - is_completion_needed = true; - } - - return is_completion_needed; -} - -/** - * This is the method provided to handle polling for interrupts for the - * controller object. - * - * bool true if an interrupt is to be processed false if no interrupt was - * pending - */ -static bool scic_sds_controller_polling_interrupt_handler( - struct scic_sds_controller *scic) -{ - u32 interrupt_status; - - /* - * In INTERRUPT_POLLING_MODE we exit the interrupt handler if the - * hardware indicates nothing is pending. Since we are not being - * called from a real interrupt, we don't want to confuse the hardware - * by servicing the completion queue before the hardware indicates it - * is ready. We'll simply wait for another polling interval and check - * again. - */ - interrupt_status = SMU_ISR_READ(scic); - if ((interrupt_status & - (SMU_ISR_COMPLETION | - SMU_ISR_QUEUE_ERROR | - SMU_ISR_QUEUE_SUSPEND)) == 0) { - return false; - } - - return scic_sds_controller_standard_interrupt_handler( - scic, interrupt_status); -} - -/** - * This is the method provided to handle completions when interrupt polling is - * in use. - */ -static void scic_sds_controller_polling_completion_handler( - struct scic_sds_controller *scic) -{ - if (scic->encountered_fatal_error == true) { - dev_err(scic_to_dev(scic), - "%s: SCIC Controller has encountered a fatal error.\n", - __func__); - - sci_base_state_machine_change_state( - scic_sds_controller_get_base_state_machine(scic), - SCI_BASE_CONTROLLER_STATE_FAILED); - } else if (scic_sds_controller_completion_queue_has_entries(scic)) { - if (scic->restrict_completions == false) - scic_sds_controller_process_completions(scic); - else - scic_sds_controller_transitioned_process_completions( - scic); - } - - /* - * The interrupt handler does not adjust the CQ's - * get pointer. So, SCU's INTx pin stays asserted during the - * interrupt handler even though it tries to clear the interrupt - * source. Therefore, the completion handler must ensure that the - * interrupt source is cleared. Otherwise, we get a spurious - * interrupt for which the interrupt handler will not issue a - * corresponding completion event. Also, we unmask interrupts. - */ - SMU_ISR_WRITE( - scic, - (u32)(SMU_ISR_COMPLETION | SMU_ISR_QUEUE_ERROR | SMU_ISR_QUEUE_SUSPEND) - ); -} - -/** - * This is the method provided to handle legacy interrupts for the controller - * object. - * - * bool true if an interrupt is processed false if no interrupt was processed - */ -static bool scic_sds_controller_legacy_interrupt_handler( - struct scic_sds_controller *scic) -{ - u32 interrupt_status; - bool is_completion_needed; - - interrupt_status = SMU_ISR_READ(scic); - is_completion_needed = scic_sds_controller_standard_interrupt_handler( - scic, interrupt_status); - - return is_completion_needed; -} - - -/** - * This is the method provided to handle legacy completions it is expected that - * the SCI User will call this completion handler anytime the interrupt - * handler reports that it has handled an interrupt. - */ -static void scic_sds_controller_legacy_completion_handler( - struct scic_sds_controller *scic) -{ - scic_sds_controller_polling_completion_handler(scic); - SMU_IMR_WRITE(scic, 0x00000000); -} - -/** - * This is the method provided to handle an MSIX interrupt message when there - * is just a single MSIX message being provided by the hardware. This mode - * of operation is single vector mode. - * - * bool true if an interrupt is processed false if no interrupt was processed - */ -static bool scic_sds_controller_single_vector_interrupt_handler( - struct scic_sds_controller *scic) -{ - u32 interrupt_status; - - /* - * Mask the interrupts - * There is a race in the hardware that could cause us not to be notified - * of an interrupt completion if we do not take this step. We will unmask - * the interrupts in the completion routine. */ - SMU_IMR_WRITE(scic, 0xFFFFFFFF); - - interrupt_status = SMU_ISR_READ(scic); - interrupt_status &= (SMU_ISR_QUEUE_ERROR | SMU_ISR_QUEUE_SUSPEND); - - if ((interrupt_status == 0) && - scic_sds_controller_completion_queue_has_entries(scic)) { - /* - * There is at least one completion queue entry to process so we can - * return a success and ignore for now the case of an error interrupt */ - SMU_ISR_WRITE(scic, SMU_ISR_COMPLETION); - return true; - } - - if (interrupt_status != 0) { - /* - * There is an error interrupt pending so let it through and handle - * in the callback */ - return true; - } - - /* - * Clear any offending interrupts since we could not find any to handle - * and unmask them all */ - SMU_ISR_WRITE(scic, 0x00000000); - SMU_IMR_WRITE(scic, 0x00000000); - - return false; -} - -/** - * This is the method provided to handle completions for a single MSIX message. - */ -static void scic_sds_controller_single_vector_completion_handler( - struct scic_sds_controller *scic) -{ - u32 interrupt_status; - - interrupt_status = SMU_ISR_READ(scic); - interrupt_status &= (SMU_ISR_QUEUE_ERROR | SMU_ISR_QUEUE_SUSPEND); - - if (interrupt_status & SMU_ISR_QUEUE_ERROR) { - dev_err(scic_to_dev(scic), - "%s: SCIC Controller has encountered a fatal error.\n", - __func__); - - /* - * We have a fatal condition and must reset the controller - * Leave the interrupt mask in place and get the controller reset */ - sci_base_state_machine_change_state( - scic_sds_controller_get_base_state_machine(scic), - SCI_BASE_CONTROLLER_STATE_FAILED); - return; - } - - if ((interrupt_status & SMU_ISR_QUEUE_SUSPEND) && - !scic_sds_controller_completion_queue_has_entries(scic)) { - dev_err(scic_to_dev(scic), - "%s: SCIC Controller has encountered a fatal error.\n", - __func__); - - /* - * We have a fatal condtion and must reset the controller - * Leave the interrupt mask in place and get the controller reset */ - sci_base_state_machine_change_state( - scic_sds_controller_get_base_state_machine(scic), - SCI_BASE_CONTROLLER_STATE_FAILED); - return; - } - - if (scic_sds_controller_completion_queue_has_entries(scic)) { - scic_sds_controller_process_completions(scic); - - /* - * We dont care which interrupt got us to processing the completion queu - * so clear them both. */ - SMU_ISR_WRITE( - scic, - (SMU_ISR_COMPLETION | SMU_ISR_QUEUE_SUSPEND)); - } - - SMU_IMR_WRITE(scic, 0x00000000); -} - -/** - * This is the method provided to handle a MSIX message for a normal completion. - * - * bool true if an interrupt is processed false if no interrupt was processed - */ bool scic_sds_controller_isr(struct scic_sds_controller *scic) { if (scic_sds_controller_completion_queue_has_entries(scic)) { @@ -1920,10 +1586,6 @@ bool scic_sds_controller_isr(struct scic_sds_controller *scic) return false; } -/** - * This is the method provided to handle the completions for a normal MSIX - * message. - */ void scic_sds_controller_completion_handler(struct scic_sds_controller *scic) { /* Empty out the completion queue */ @@ -1994,14 +1656,6 @@ void scic_sds_controller_error_handler(struct scic_sds_controller *scic) } -/* - * ****************************************************************************- - * * SCIC SDS Controller External Methods - * ****************************************************************************- */ - -/** - * This method returns the sizeof the SCIC SDS Controller Object - */ u32 scic_sds_controller_get_object_size(void) { return sizeof(struct scic_sds_controller); @@ -2535,72 +2189,6 @@ enum sci_status scic_controller_reset( return status; } -/* --------------------------------------------------------------------------- */ - -enum sci_status scic_controller_get_handler_methods( - enum scic_interrupt_type interrupt_type, - u16 message_count, - struct scic_controller_handler_methods *handler_methods) -{ - enum sci_status status = SCI_FAILURE_UNSUPPORTED_MESSAGE_COUNT; - - switch (interrupt_type) { - case SCIC_LEGACY_LINE_INTERRUPT_TYPE: - if (message_count == 0) { - handler_methods[0].interrupt_handler - = scic_sds_controller_legacy_interrupt_handler; - handler_methods[0].completion_handler - = scic_sds_controller_legacy_completion_handler; - - status = SCI_SUCCESS; - } - break; - - case SCIC_MSIX_INTERRUPT_TYPE: - if (message_count == 1) { - handler_methods[0].interrupt_handler - = scic_sds_controller_single_vector_interrupt_handler; - handler_methods[0].completion_handler - = scic_sds_controller_single_vector_completion_handler; - - status = SCI_SUCCESS; - } else if (message_count == 2) { - handler_methods[0].interrupt_handler - = scic_sds_controller_isr; - handler_methods[0].completion_handler - = scic_sds_controller_completion_handler; - - handler_methods[1].interrupt_handler - = scic_sds_controller_error_isr; - handler_methods[1].completion_handler - = scic_sds_controller_error_handler; - - status = SCI_SUCCESS; - } - break; - - case SCIC_NO_INTERRUPTS: - if (message_count == 0) { - - handler_methods[0].interrupt_handler - = scic_sds_controller_polling_interrupt_handler; - handler_methods[0].completion_handler - = scic_sds_controller_polling_completion_handler; - - status = SCI_SUCCESS; - } - break; - - default: - status = SCI_FAILURE_INVALID_PARAMETER_VALUE; - break; - } - - return status; -} - -/* --------------------------------------------------------------------------- */ - enum sci_io_status scic_controller_start_io( struct scic_sds_controller *scic, struct scic_sds_remote_device *remote_device, diff --git a/drivers/scsi/isci/core/scic_sds_controller.h b/drivers/scsi/isci/core/scic_sds_controller.h index cce0da6a6a3d..3e0477d62a5b 100644 --- a/drivers/scsi/isci/core/scic_sds_controller.h +++ b/drivers/scsi/isci/core/scic_sds_controller.h @@ -335,19 +335,6 @@ struct scic_sds_controller { */ struct scic_sds_unsolicited_frame_control uf_control; - /** - * This field records the fact that the controller has encountered a fatal - * error and must be reset. - */ - bool encountered_fatal_error; - - /** - * This field specifies that the controller should ignore - * completion processing for non-fastpath events. This will - * cause the completions to be thrown away. - */ - bool restrict_completions; - /* Phy Startup Data */ /** * This field is the driver timer handle for controller phy request startup. diff --git a/drivers/scsi/isci/core/scic_user_callback.h b/drivers/scsi/isci/core/scic_user_callback.h index ec4eb278cd5f..d1a3cb885bc7 100644 --- a/drivers/scsi/isci/core/scic_user_callback.h +++ b/drivers/scsi/isci/core/scic_user_callback.h @@ -86,9 +86,8 @@ struct scic_sds_controller; * occurs for the created timer. * * The "timer_callback" method should be executed in a mutually exlusive manner - * from the controller completion handler handler (refer to - * scic_controller_get_handler_methods()). This method returns a handle to a - * timer object created by the user. The handle will be utilized for all + * from the controller completion handler handler. This method returns a handle + * to a timer object created by the user. The handle will be utilized for all * further interactions relating to this timer. */ void *scic_cb_timer_create(