diff options
author | Dan Williams <dan.j.williams@intel.com> | 2011-02-18 09:25:11 -0800 |
---|---|---|
committer | Dan Williams <dan.j.williams@intel.com> | 2011-07-03 03:55:27 -0700 |
commit | 92f4f0f544a6a75979bace0c43fee9c4fb95830c (patch) | |
tree | bf1c8d9e4fff6af6004b4e5bd1dc17b2f299911e /drivers | |
parent | 77950f51f5299c1b4f4fa4a19974128da720d199 (diff) |
isci: implement error isr
Add basic support for handling/reporting error interrupts.
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/scsi/isci/core/scic_sds_controller.c | 26 | ||||
-rw-r--r-- | drivers/scsi/isci/host.c | 16 | ||||
-rw-r--r-- | drivers/scsi/isci/init.c | 10 | ||||
-rw-r--r-- | 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 cd8017f048c1..7ea36624f568 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 7f351a35e87b..cb2e3f9558e9 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 f2bd92b81136..4d6decb6d08c 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 3dc0f6c21174..39efd5f27200 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, |