From 92f4f0f544a6a75979bace0c43fee9c4fb95830c Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Fri, 18 Feb 2011 09:25:11 -0800 Subject: [PATCH] isci: implement error isr Add basic support for handling/reporting error interrupts. Signed-off-by: Dan Williams --- drivers/scsi/isci/core/scic_sds_controller.c | 26 +++++--------------- drivers/scsi/isci/host.c | 16 ++++++++++++ drivers/scsi/isci/init.c | 10 ++++++-- drivers/scsi/isci/isci.h | 3 +++ 4 files changed, 33 insertions(+), 22 deletions(-) diff --git a/drivers/scsi/isci/core/scic_sds_controller.c b/drivers/scsi/isci/core/scic_sds_controller.c index cd8017f048c..7ea36624f56 100644 --- a/drivers/scsi/isci/core/scic_sds_controller.c +++ b/drivers/scsi/isci/core/scic_sds_controller.c @@ -1937,18 +1937,12 @@ void scic_sds_controller_completion_handler(struct scic_sds_controller *scic) SMU_IMR_WRITE(scic, 0x00000000); } -/** - * This is the method provided to handle the error MSIX message interrupt. - * This is the normal operating mode for the hardware if MSIX is enabled. - * - * bool true if an interrupt is processed false if no interrupt was processed - */ -static bool scic_sds_controller_error_vector_interrupt_handler( - struct scic_sds_controller *scic) +bool scic_sds_controller_error_isr(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 != 0) { @@ -1970,12 +1964,7 @@ static bool scic_sds_controller_error_vector_interrupt_handler( return false; } -/** - * This is the method provided to handle the error completions when the - * hardware is using two MSIX messages. - */ -static void scic_sds_controller_error_vector_completion_handler( - struct scic_sds_controller *scic) +void scic_sds_controller_error_handler(struct scic_sds_controller *scic) { u32 interrupt_status; @@ -1988,10 +1977,7 @@ static void scic_sds_controller_error_vector_completion_handler( SMU_ISR_WRITE(scic, SMU_ISR_QUEUE_SUSPEND); } else { - dev_err(scic_to_dev(scic), - "%s: SCIC Controller reports CRC error on completion " - "ISR %x\n", - __func__, + dev_err(scic_to_dev(scic), "%s: status: %#x\n", __func__, interrupt_status); sci_base_state_machine_change_state( @@ -2585,9 +2571,9 @@ enum sci_status scic_controller_get_handler_methods( = scic_sds_controller_completion_handler; handler_methods[1].interrupt_handler - = scic_sds_controller_error_vector_interrupt_handler; + = scic_sds_controller_error_isr; handler_methods[1].completion_handler - = scic_sds_controller_error_vector_completion_handler; + = scic_sds_controller_error_handler; status = SCI_SUCCESS; } diff --git a/drivers/scsi/isci/host.c b/drivers/scsi/isci/host.c index 7f351a35e87..cb2e3f9558e 100644 --- a/drivers/scsi/isci/host.c +++ b/drivers/scsi/isci/host.c @@ -85,11 +85,27 @@ irqreturn_t isci_intx_isr(int vec, void *data) if (scic_sds_controller_isr(scic)) { tasklet_schedule(&ihost->completion_tasklet); ret = IRQ_HANDLED; + } else if (scic_sds_controller_error_isr(scic)) { + spin_lock(&ihost->scic_lock); + scic_sds_controller_error_handler(scic); + spin_unlock(&ihost->scic_lock); + ret = IRQ_HANDLED; } } + return ret; } +irqreturn_t isci_error_isr(int vec, void *data) +{ + struct isci_host *ihost = data; + struct scic_sds_controller *scic = ihost->core_controller; + + if (scic_sds_controller_error_isr(scic)) + scic_sds_controller_error_handler(scic); + + return IRQ_HANDLED; +} /** * isci_host_start_complete() - This function is called by the core library, diff --git a/drivers/scsi/isci/init.c b/drivers/scsi/isci/init.c index f2bd92b8113..4d6decb6d08 100644 --- a/drivers/scsi/isci/init.c +++ b/drivers/scsi/isci/init.c @@ -330,11 +330,17 @@ static int isci_setup_interrupts(struct pci_dev *pdev) int id = i / SCI_NUM_MSI_X_INT; struct msix_entry *msix = &pci_info->msix_entries[i]; struct isci_host *isci_host = isci_host_by_id(pdev, id); + irq_handler_t isr; + + /* odd numbered vectors are error interrupts */ + if (i & 1) + isr = isci_error_isr; + else + isr = isci_msix_isr; BUG_ON(!isci_host); - /* @todo: need to handle error case. */ - err = devm_request_irq(&pdev->dev, msix->vector, isci_msix_isr, 0, + err = devm_request_irq(&pdev->dev, msix->vector, isr, 0, DRV_NAME"-msix", isci_host); if (!err) continue; diff --git a/drivers/scsi/isci/isci.h b/drivers/scsi/isci/isci.h index 3dc0f6c2117..39efd5f2720 100644 --- a/drivers/scsi/isci/isci.h +++ b/drivers/scsi/isci/isci.h @@ -115,9 +115,12 @@ struct isci_firmware { irqreturn_t isci_msix_isr(int vec, void *data); irqreturn_t isci_intx_isr(int vec, void *data); +irqreturn_t isci_error_isr(int vec, void *data); bool scic_sds_controller_isr(struct scic_sds_controller *scic); void scic_sds_controller_completion_handler(struct scic_sds_controller *scic); +bool scic_sds_controller_error_isr(struct scic_sds_controller *scic); +void scic_sds_controller_error_handler(struct scic_sds_controller *scic); enum sci_status isci_parse_oem_parameters( union scic_oem_parameters *oem_params, -- 2.34.1