Add basic support for handling/reporting error interrupts.
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
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) {
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;
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(
= 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;
}
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,
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;
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,