4.14-stable review patch. If anyone has any objections, please let me know. ------------------ From: Ming Lei <ming.lei@xxxxxxxxxx> commit adbe552349f2d1e48357a00e564d26135e586634 upstream. Since commit 84676c1f21e8 ("genirq/affinity: assign vectors to all possible CPUs") we could end up with an MSI-X vector that did not have any online CPUs mapped. This would lead to I/O hangs since there was no CPU to receive the completion. Retrieve IRQ affinity information using pci_irq_get_affinity() and use this mapping to choose a reply queue. [mkp: tweaked commit desc] Cc: Hannes Reinecke <hare@xxxxxxx> Cc: "Martin K. Petersen" <martin.petersen@xxxxxxxxxx>, Cc: James Bottomley <james.bottomley@xxxxxxxxxxxxxxxxxxxxx>, Cc: Christoph Hellwig <hch@xxxxxx>, Cc: Don Brace <don.brace@xxxxxxxxxxxxx> Cc: Kashyap Desai <kashyap.desai@xxxxxxxxxxxx> Cc: Laurence Oberman <loberman@xxxxxxxxxx> Cc: Mike Snitzer <snitzer@xxxxxxxxxx> Cc: Meelis Roos <mroos@xxxxxxxx> Cc: Artem Bityutskiy <artem.bityutskiy@xxxxxxxxx> Fixes: 84676c1f21e8 ("genirq/affinity: assign vectors to all possible CPUs") Signed-off-by: Ming Lei <ming.lei@xxxxxxxxxx> Acked-by: Kashyap Desai <kashyap.desai@xxxxxxxxxxxx> Tested-by: Kashyap Desai <kashyap.desai@xxxxxxxxxxxx> Reviewed-by: Christoph Hellwig <hch@xxxxxx> Tested-by: Artem Bityutskiy <artem.bityutskiy@xxxxxxxxx> Signed-off-by: Martin K. Petersen <martin.petersen@xxxxxxxxxx> Signed-off-by: Greg Kroah-Hartman <gregkh@xxxxxxxxxxxxxxxxxxx> --- drivers/scsi/megaraid/megaraid_sas.h | 1 drivers/scsi/megaraid/megaraid_sas_base.c | 39 +++++++++++++++++++++++++--- drivers/scsi/megaraid/megaraid_sas_fusion.c | 12 ++------ 3 files changed, 41 insertions(+), 11 deletions(-) --- a/drivers/scsi/megaraid/megaraid_sas.h +++ b/drivers/scsi/megaraid/megaraid_sas.h @@ -2099,6 +2099,7 @@ enum MR_PD_TYPE { struct megasas_instance { + unsigned int *reply_map; __le32 *producer; dma_addr_t producer_h; __le32 *consumer; --- a/drivers/scsi/megaraid/megaraid_sas_base.c +++ b/drivers/scsi/megaraid/megaraid_sas_base.c @@ -5138,6 +5138,26 @@ skip_alloc: instance->use_seqnum_jbod_fp = false; } +static void megasas_setup_reply_map(struct megasas_instance *instance) +{ + const struct cpumask *mask; + unsigned int queue, cpu; + + for (queue = 0; queue < instance->msix_vectors; queue++) { + mask = pci_irq_get_affinity(instance->pdev, queue); + if (!mask) + goto fallback; + + for_each_cpu(cpu, mask) + instance->reply_map[cpu] = queue; + } + return; + +fallback: + for_each_possible_cpu(cpu) + instance->reply_map[cpu] = cpu % instance->msix_vectors; +} + /** * megasas_init_fw - Initializes the FW * @instance: Adapter soft state @@ -5303,6 +5323,8 @@ static int megasas_init_fw(struct megasa goto fail_setup_irqs; } + megasas_setup_reply_map(instance); + dev_info(&instance->pdev->dev, "firmware supports msix\t: (%d)", fw_msix_count); dev_info(&instance->pdev->dev, @@ -6046,20 +6068,29 @@ static inline int megasas_alloc_mfi_ctrl */ static int megasas_alloc_ctrl_mem(struct megasas_instance *instance) { + instance->reply_map = kzalloc(sizeof(unsigned int) * nr_cpu_ids, + GFP_KERNEL); + if (!instance->reply_map) + return -ENOMEM; + switch (instance->adapter_type) { case MFI_SERIES: if (megasas_alloc_mfi_ctrl_mem(instance)) - return -ENOMEM; + goto fail; break; case VENTURA_SERIES: case THUNDERBOLT_SERIES: case INVADER_SERIES: if (megasas_alloc_fusion_context(instance)) - return -ENOMEM; + goto fail; break; } return 0; + fail: + kfree(instance->reply_map); + instance->reply_map = NULL; + return -ENOMEM; } /* @@ -6071,6 +6102,7 @@ static int megasas_alloc_ctrl_mem(struct */ static inline void megasas_free_ctrl_mem(struct megasas_instance *instance) { + kfree(instance->reply_map); if (instance->adapter_type == MFI_SERIES) { if (instance->producer) pci_free_consistent(instance->pdev, sizeof(u32), @@ -6342,7 +6374,6 @@ fail_alloc_dma_buf: instance->tgt_prop_h); megasas_free_ctrl_mem(instance); scsi_host_put(host); - fail_alloc_instance: fail_set_dma_mask: pci_disable_device(pdev); @@ -6548,6 +6579,8 @@ megasas_resume(struct pci_dev *pdev) if (rval < 0) goto fail_reenable_msix; + megasas_setup_reply_map(instance); + if (instance->adapter_type != MFI_SERIES) { megasas_reset_reply_desc(instance); if (megasas_ioc_init_fusion(instance)) { --- a/drivers/scsi/megaraid/megaraid_sas_fusion.c +++ b/drivers/scsi/megaraid/megaraid_sas_fusion.c @@ -2341,11 +2341,8 @@ megasas_build_ldio_fusion(struct megasas fp_possible = (io_info.fpOkForIo > 0) ? true : false; } - /* Use raw_smp_processor_id() for now until cmd->request->cpu is CPU - id by default, not CPU group id, otherwise all MSI-X queues won't - be utilized */ - cmd->request_desc->SCSIIO.MSIxIndex = instance->msix_vectors ? - raw_smp_processor_id() % instance->msix_vectors : 0; + cmd->request_desc->SCSIIO.MSIxIndex = + instance->reply_map[raw_smp_processor_id()]; praid_context = &io_request->RaidContext; @@ -2667,10 +2664,9 @@ megasas_build_syspd_fusion(struct megasa } cmd->request_desc->SCSIIO.DevHandle = io_request->DevHandle; - cmd->request_desc->SCSIIO.MSIxIndex = - instance->msix_vectors ? - (raw_smp_processor_id() % instance->msix_vectors) : 0; + cmd->request_desc->SCSIIO.MSIxIndex = + instance->reply_map[raw_smp_processor_id()]; if (!fp_possible) { /* system pd firmware path */