summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
authorDan Williams <dan.j.williams@intel.com>2011-02-18 09:25:11 -0800
committerDan Williams <dan.j.williams@intel.com>2011-07-03 03:55:27 -0700
commit92f4f0f544a6a75979bace0c43fee9c4fb95830c (patch)
treebf1c8d9e4fff6af6004b4e5bd1dc17b2f299911e /drivers
parent77950f51f5299c1b4f4fa4a19974128da720d199 (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.c26
-rw-r--r--drivers/scsi/isci/host.c16
-rw-r--r--drivers/scsi/isci/init.c10
-rw-r--r--drivers/scsi/isci/isci.h3
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,