scsi: megaraid_sas: fix selection of reply queue
Since commit84676c1f21
("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@suse.de> Cc: "Martin K. Petersen" <martin.petersen@oracle.com>, Cc: James Bottomley <james.bottomley@hansenpartnership.com>, Cc: Christoph Hellwig <hch@lst.de>, Cc: Don Brace <don.brace@microsemi.com> Cc: Kashyap Desai <kashyap.desai@broadcom.com> Cc: Laurence Oberman <loberman@redhat.com> Cc: Mike Snitzer <snitzer@redhat.com> Cc: Meelis Roos <mroos@linux.ee> Cc: Artem Bityutskiy <artem.bityutskiy@intel.com> Fixes:84676c1f21
("genirq/affinity: assign vectors to all possible CPUs") Signed-off-by: Ming Lei <ming.lei@redhat.com> Acked-by: Kashyap Desai <kashyap.desai@broadcom.com> Tested-by: Kashyap Desai <kashyap.desai@broadcom.com> Reviewed-by: Christoph Hellwig <hch@lst.de> Tested-by: Artem Bityutskiy <artem.bityutskiy@intel.com> Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
This commit is contained in:
parent
8b834bff1b
commit
adbe552349
@ -2128,6 +2128,7 @@ enum MR_PD_TYPE {
|
|||||||
|
|
||||||
struct megasas_instance {
|
struct megasas_instance {
|
||||||
|
|
||||||
|
unsigned int *reply_map;
|
||||||
__le32 *producer;
|
__le32 *producer;
|
||||||
dma_addr_t producer_h;
|
dma_addr_t producer_h;
|
||||||
__le32 *consumer;
|
__le32 *consumer;
|
||||||
|
@ -5165,6 +5165,26 @@ skip_alloc:
|
|||||||
instance->use_seqnum_jbod_fp = false;
|
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
|
* megasas_init_fw - Initializes the FW
|
||||||
* @instance: Adapter soft state
|
* @instance: Adapter soft state
|
||||||
@ -5343,6 +5363,8 @@ static int megasas_init_fw(struct megasas_instance *instance)
|
|||||||
goto fail_setup_irqs;
|
goto fail_setup_irqs;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
megasas_setup_reply_map(instance);
|
||||||
|
|
||||||
dev_info(&instance->pdev->dev,
|
dev_info(&instance->pdev->dev,
|
||||||
"firmware supports msix\t: (%d)", fw_msix_count);
|
"firmware supports msix\t: (%d)", fw_msix_count);
|
||||||
dev_info(&instance->pdev->dev,
|
dev_info(&instance->pdev->dev,
|
||||||
@ -6123,20 +6145,29 @@ static inline int megasas_alloc_mfi_ctrl_mem(struct megasas_instance *instance)
|
|||||||
*/
|
*/
|
||||||
static int megasas_alloc_ctrl_mem(struct megasas_instance *instance)
|
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) {
|
switch (instance->adapter_type) {
|
||||||
case MFI_SERIES:
|
case MFI_SERIES:
|
||||||
if (megasas_alloc_mfi_ctrl_mem(instance))
|
if (megasas_alloc_mfi_ctrl_mem(instance))
|
||||||
return -ENOMEM;
|
goto fail;
|
||||||
break;
|
break;
|
||||||
case VENTURA_SERIES:
|
case VENTURA_SERIES:
|
||||||
case THUNDERBOLT_SERIES:
|
case THUNDERBOLT_SERIES:
|
||||||
case INVADER_SERIES:
|
case INVADER_SERIES:
|
||||||
if (megasas_alloc_fusion_context(instance))
|
if (megasas_alloc_fusion_context(instance))
|
||||||
return -ENOMEM;
|
goto fail;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
fail:
|
||||||
|
kfree(instance->reply_map);
|
||||||
|
instance->reply_map = NULL;
|
||||||
|
return -ENOMEM;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -6148,6 +6179,7 @@ static int megasas_alloc_ctrl_mem(struct megasas_instance *instance)
|
|||||||
*/
|
*/
|
||||||
static inline void megasas_free_ctrl_mem(struct megasas_instance *instance)
|
static inline void megasas_free_ctrl_mem(struct megasas_instance *instance)
|
||||||
{
|
{
|
||||||
|
kfree(instance->reply_map);
|
||||||
if (instance->adapter_type == MFI_SERIES) {
|
if (instance->adapter_type == MFI_SERIES) {
|
||||||
if (instance->producer)
|
if (instance->producer)
|
||||||
pci_free_consistent(instance->pdev, sizeof(u32),
|
pci_free_consistent(instance->pdev, sizeof(u32),
|
||||||
@ -6540,7 +6572,6 @@ fail_io_attach:
|
|||||||
pci_free_irq_vectors(instance->pdev);
|
pci_free_irq_vectors(instance->pdev);
|
||||||
fail_init_mfi:
|
fail_init_mfi:
|
||||||
scsi_host_put(host);
|
scsi_host_put(host);
|
||||||
|
|
||||||
fail_alloc_instance:
|
fail_alloc_instance:
|
||||||
pci_disable_device(pdev);
|
pci_disable_device(pdev);
|
||||||
|
|
||||||
@ -6746,6 +6777,8 @@ megasas_resume(struct pci_dev *pdev)
|
|||||||
if (rval < 0)
|
if (rval < 0)
|
||||||
goto fail_reenable_msix;
|
goto fail_reenable_msix;
|
||||||
|
|
||||||
|
megasas_setup_reply_map(instance);
|
||||||
|
|
||||||
if (instance->adapter_type != MFI_SERIES) {
|
if (instance->adapter_type != MFI_SERIES) {
|
||||||
megasas_reset_reply_desc(instance);
|
megasas_reset_reply_desc(instance);
|
||||||
if (megasas_ioc_init_fusion(instance)) {
|
if (megasas_ioc_init_fusion(instance)) {
|
||||||
|
@ -2641,11 +2641,8 @@ megasas_build_ldio_fusion(struct megasas_instance *instance,
|
|||||||
fp_possible = (io_info.fpOkForIo > 0) ? true : false;
|
fp_possible = (io_info.fpOkForIo > 0) ? true : false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Use raw_smp_processor_id() for now until cmd->request->cpu is CPU
|
cmd->request_desc->SCSIIO.MSIxIndex =
|
||||||
id by default, not CPU group id, otherwise all MSI-X queues won't
|
instance->reply_map[raw_smp_processor_id()];
|
||||||
be utilized */
|
|
||||||
cmd->request_desc->SCSIIO.MSIxIndex = instance->msix_vectors ?
|
|
||||||
raw_smp_processor_id() % instance->msix_vectors : 0;
|
|
||||||
|
|
||||||
praid_context = &io_request->RaidContext;
|
praid_context = &io_request->RaidContext;
|
||||||
|
|
||||||
@ -2971,10 +2968,9 @@ megasas_build_syspd_fusion(struct megasas_instance *instance,
|
|||||||
}
|
}
|
||||||
|
|
||||||
cmd->request_desc->SCSIIO.DevHandle = io_request->DevHandle;
|
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) {
|
if (!fp_possible) {
|
||||||
/* system pd firmware path */
|
/* system pd firmware path */
|
||||||
|
Loading…
Reference in New Issue
Block a user