b/drivers/scsi/megaraid/megaraid_sas.h
@@ -2291,6 +2291,7 @@ struct megasas_instance {
u8 adapter_type;
bool consistent_mask_64bit;
bool support_nvme_passthru;
+ bool use_threaded_interrupts;
};
struct MR_LD_VF_MAP {
u32 size;
@@ -2534,6 +2535,7 @@ void megasas_return_mfi_mpt_pthr(struct
megasas_instance *instance,
int megasas_reset_fusion(struct Scsi_Host *shost, int reason);
int megasas_task_abort_fusion(struct scsi_cmnd *scmd);
int megasas_reset_target_fusion(struct scsi_cmnd *scmd);
+irqreturn_t megasas_irq_check_fusion(int irq, void *devp);
u32 mega_mod64(u64 dividend, u32 divisor);
int megasas_alloc_fusion_context(struct megasas_instance *instance);
void megasas_free_fusion_context(struct megasas_instance *instance);
b/drivers/scsi/megaraid/megaraid_sas_base.c
@@ -5029,6 +5029,7 @@ int megasas_set_crash_dump_params(struct
megasas_instance *instance,
struct pci_dev *pdev;
pdev = instance->pdev;
+ instance->use_threaded_interrupts = 0;
instance->irq_context[0].instance = instance;
instance->irq_context[0].MSIxIndex = 0;
if (request_irq(pci_irq_vector(pdev, 0),
@@ -5054,7 +5055,7 @@ int megasas_set_crash_dump_params(struct
megasas_instance *instance,
static int
megasas_setup_irqs_msix(struct megasas_instance *instance, u8 is_probe)
{
- int i, j;
+ int i, j, cpu, ret;
struct pci_dev *pdev;
pdev = instance->pdev;
@@ -5063,9 +5064,18 @@ int megasas_set_crash_dump_params(struct
megasas_instance *instance,
for (i = 0; i < instance->msix_vectors; i++) {
instance->irq_context[i].instance = instance;
instance->irq_context[i].MSIxIndex = i;
- if (request_irq(pci_irq_vector(pdev, i),
- instance->instancet->service_isr, 0, "megasas",
- &instance->irq_context[i])) {
+ if (instance->use_threaded_interrupts)
+ ret = request_threaded_irq(pci_irq_vector(pdev, i),
+ megasas_irq_check_fusion,
+ instance->instancet->service_isr, 0, "megasas",
+ &instance->irq_context[i]);
+
+ else
+ ret = request_irq(pci_irq_vector(pdev, i),
+ instance->instancet->service_isr, 0, "megasas",
+ &instance->irq_context[i]);
+
+ if (ret) {
dev_err(&instance->pdev->dev,
"Failed to register IRQ for vector %d.\n", i);
for (j = 0; j < i; j++)
@@ -5326,6 +5336,8 @@ static int megasas_init_fw(struct
megasas_instance *instance)
instance->msix_vectors);
} else /* MFI adapters */
instance->msix_vectors = 1;
+
+ instance->use_threaded_interrupts = 1;
/* Don't bother allocating more MSI-X vectors than cpus */
instance->msix_vectors = min(instance->msix_vectors,
(unsigned int)num_online_cpus());
b/drivers/scsi/megaraid/megaraid_sas_fusion.c
@@ -3525,7 +3525,7 @@ irqreturn_t megasas_isr_fusion(int irq, void *devp)
{
struct megasas_irq_context *irq_context = devp;
struct megasas_instance *instance = irq_context->instance;
- u32 mfiStatus, fw_state, dma_state;
+ u32 mfiStatus, fw_state, dma_state, i;
if (instance->mask_interrupts)
return IRQ_NONE;
@@ -3542,33 +3542,39 @@ irqreturn_t megasas_isr_fusion(int irq, void *devp)
return IRQ_HANDLED;
}
- if (!complete_cmd_fusion(instance, irq_context->MSIxIndex)) {
- instance->instancet->clear_intr(instance->reg_set);
- /* If we didn't complete any commands, check for FW fault */
- fw_state = instance->instancet->read_fw_status_reg(
- instance->reg_set) & MFI_STATE_MASK;
- dma_state = instance->instancet->read_fw_status_reg
- (instance->reg_set) & MFI_STATE_DMADONE;
- if (instance->crash_dump_drv_support &&
- instance->crash_dump_app_support) {
- /* Start collecting crash, if DMA bit is done */
- if ((fw_state == MFI_STATE_FAULT) && dma_state)
- schedule_work(&instance->crash_init);
- else if (fw_state == MFI_STATE_FAULT) {
- if (instance->unload == 0)
- schedule_work(&instance->work_init);
- }
- } else if (fw_state == MFI_STATE_FAULT) {
- dev_warn(&instance->pdev->dev, "Iop2SysDoorbellInt"
- "for scsi%d\n", instance->host->host_no);
- if (instance->unload == 0)
- schedule_work(&instance->work_init);
+ if (instance->use_threaded_interrupts &&
+ atomic_read(&instance->fw_outstanding) > 1024) {
+ disable_irq_nosync(pci_irq_vector(instance->pdev,
irq_context->MSIxIndex));
+ for (i = 0; i < 100; i++) {
+ complete_cmd_fusion(instance, irq_context->MSIxIndex);
+ usleep_range(1 , 11);
}
+ enable_irq(pci_irq_vector(instance->pdev, irq_context->MSIxIndex));
+ return IRQ_HANDLED;
+ } else {
+ return complete_cmd_fusion(instance, irq_context->MSIxIndex)
? IRQ_HANDLED : IRQ_NONE;
}
return IRQ_HANDLED;
}
+
+/*
+ * megasas_irq_check_fusion:
+ * For threaded interrupts, this handler will be called
+ * and its job is to invoke core ISR- megasas_isr_fusion.
+ */
+irqreturn_t megasas_irq_check_fusion(int irq, void *devp)
+{
+ struct megasas_irq_context *irq_context = devp;
+ struct megasas_instance *instance = irq_context->instance;
+
+ if (instance->mask_interrupts)
+ return IRQ_NONE;
+
+ return IRQ_WAKE_THREAD;
+}
+
/**
Create Threaded ISR if possible. Driver will do interrupt polling if work load is high based on host busy (or it can be some other trigger.). Signed-off-by: Kashyap Desai < kashyap.desai@broadcom.com> --- * build_mpt_mfi_pass_thru - builds a cmd fo MFI Pass thru * @instance: Adapter soft state