Commit c8e858fe authored by adam radford's avatar adam radford Committed by James Bottomley

[SCSI] megaraid_sas: Add multiple MSI-X vector/multiple reply queue support

Signed-off-by: default avatarAdam Radford <aradford@gmail.com>
Signed-off-by: default avatarJames Bottomley <JBottomley@Parallels.com>
parent 36807e67
...@@ -757,6 +757,7 @@ struct megasas_ctrl_info { ...@@ -757,6 +757,7 @@ struct megasas_ctrl_info {
#define MEGASAS_INT_CMDS 32 #define MEGASAS_INT_CMDS 32
#define MEGASAS_SKINNY_INT_CMDS 5 #define MEGASAS_SKINNY_INT_CMDS 5
#define MEGASAS_MAX_MSIX_QUEUES 16
/* /*
* FW can accept both 32 and 64 bit SGLs. We want to allocate 32/64 bit * FW can accept both 32 and 64 bit SGLs. We want to allocate 32/64 bit
* SGLs based on the size of dma_addr_t * SGLs based on the size of dma_addr_t
...@@ -1278,6 +1279,11 @@ struct megasas_aen_event { ...@@ -1278,6 +1279,11 @@ struct megasas_aen_event {
struct megasas_instance *instance; struct megasas_instance *instance;
}; };
struct megasas_irq_context {
struct megasas_instance *instance;
u32 MSIxIndex;
};
struct megasas_instance { struct megasas_instance {
u32 *producer; u32 *producer;
...@@ -1351,8 +1357,9 @@ struct megasas_instance { ...@@ -1351,8 +1357,9 @@ struct megasas_instance {
/* Ptr to hba specific information */ /* Ptr to hba specific information */
void *ctrl_context; void *ctrl_context;
u8 msi_flag; unsigned int msix_vectors;
struct msix_entry msixentry; struct msix_entry msixentry[MEGASAS_MAX_MSIX_QUEUES];
struct megasas_irq_context irq_context[MEGASAS_MAX_MSIX_QUEUES];
u64 map_id; u64 map_id;
struct megasas_cmd *map_update_cmd; struct megasas_cmd *map_update_cmd;
unsigned long bar; unsigned long bar;
......
...@@ -2536,7 +2536,7 @@ megasas_deplete_reply_queue(struct megasas_instance *instance, ...@@ -2536,7 +2536,7 @@ megasas_deplete_reply_queue(struct megasas_instance *instance,
instance->reg_set) instance->reg_set)
) == 0) { ) == 0) {
/* Hardware may not set outbound_intr_status in MSI-X mode */ /* Hardware may not set outbound_intr_status in MSI-X mode */
if (!instance->msi_flag) if (!instance->msix_vectors)
return IRQ_NONE; return IRQ_NONE;
} }
...@@ -2594,16 +2594,14 @@ megasas_deplete_reply_queue(struct megasas_instance *instance, ...@@ -2594,16 +2594,14 @@ megasas_deplete_reply_queue(struct megasas_instance *instance,
*/ */
static irqreturn_t megasas_isr(int irq, void *devp) static irqreturn_t megasas_isr(int irq, void *devp)
{ {
struct megasas_instance *instance; struct megasas_irq_context *irq_context = devp;
struct megasas_instance *instance = irq_context->instance;
unsigned long flags; unsigned long flags;
irqreturn_t rc; irqreturn_t rc;
if (atomic_read( if (atomic_read(&instance->fw_reset_no_pci_access))
&(((struct megasas_instance *)devp)->fw_reset_no_pci_access)))
return IRQ_HANDLED; return IRQ_HANDLED;
instance = (struct megasas_instance *)devp;
spin_lock_irqsave(&instance->hba_lock, flags); spin_lock_irqsave(&instance->hba_lock, flags);
rc = megasas_deplete_reply_queue(instance, DID_OK); rc = megasas_deplete_reply_queue(instance, DID_OK);
spin_unlock_irqrestore(&instance->hba_lock, flags); spin_unlock_irqrestore(&instance->hba_lock, flags);
...@@ -3488,6 +3486,7 @@ static int megasas_init_fw(struct megasas_instance *instance) ...@@ -3488,6 +3486,7 @@ static int megasas_init_fw(struct megasas_instance *instance)
struct megasas_register_set __iomem *reg_set; struct megasas_register_set __iomem *reg_set;
struct megasas_ctrl_info *ctrl_info; struct megasas_ctrl_info *ctrl_info;
unsigned long bar_list; unsigned long bar_list;
int i;
/* Find first memory bar */ /* Find first memory bar */
bar_list = pci_select_bars(instance->pdev, IORESOURCE_MEM); bar_list = pci_select_bars(instance->pdev, IORESOURCE_MEM);
...@@ -3541,9 +3540,33 @@ static int megasas_init_fw(struct megasas_instance *instance) ...@@ -3541,9 +3540,33 @@ static int megasas_init_fw(struct megasas_instance *instance)
/* Check if MSI-X is supported while in ready state */ /* Check if MSI-X is supported while in ready state */
msix_enable = (instance->instancet->read_fw_status_reg(reg_set) & msix_enable = (instance->instancet->read_fw_status_reg(reg_set) &
0x4000000) >> 0x1a; 0x4000000) >> 0x1a;
if (msix_enable && !msix_disable && if (msix_enable && !msix_disable) {
!pci_enable_msix(instance->pdev, &instance->msixentry, 1)) /* Check max MSI-X vectors */
instance->msi_flag = 1; if ((instance->pdev->device == PCI_DEVICE_ID_LSI_FUSION) ||
(instance->pdev->device == PCI_DEVICE_ID_LSI_INVADER)) {
instance->msix_vectors = (readl(&instance->reg_set->
outbound_scratch_pad_2
) & 0x1F) + 1;
} else
instance->msix_vectors = 1;
/* Don't bother allocating more MSI-X vectors than cpus */
instance->msix_vectors = min(instance->msix_vectors,
(unsigned int)num_online_cpus());
for (i = 0; i < instance->msix_vectors; i++)
instance->msixentry[i].entry = i;
i = pci_enable_msix(instance->pdev, instance->msixentry,
instance->msix_vectors);
if (i >= 0) {
if (i) {
if (!pci_enable_msix(instance->pdev,
instance->msixentry, i))
instance->msix_vectors = i;
else
instance->msix_vectors = 0;
}
} else
instance->msix_vectors = 0;
}
/* Get operational params, sge flags, send init cmd to controller */ /* Get operational params, sge flags, send init cmd to controller */
if (instance->instancet->init_adapter(instance)) if (instance->instancet->init_adapter(instance))
...@@ -3958,7 +3981,7 @@ megasas_set_dma_mask(struct pci_dev *pdev) ...@@ -3958,7 +3981,7 @@ megasas_set_dma_mask(struct pci_dev *pdev)
static int __devinit static int __devinit
megasas_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) megasas_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
{ {
int rval, pos; int rval, pos, i, j;
struct Scsi_Host *host; struct Scsi_Host *host;
struct megasas_instance *instance; struct megasas_instance *instance;
u16 control = 0; u16 control = 0;
...@@ -4126,11 +4149,32 @@ megasas_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) ...@@ -4126,11 +4149,32 @@ megasas_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
/* /*
* Register IRQ * Register IRQ
*/ */
if (request_irq(instance->msi_flag ? instance->msixentry.vector : if (instance->msix_vectors) {
pdev->irq, instance->instancet->service_isr, for (i = 0 ; i < instance->msix_vectors; i++) {
IRQF_SHARED, "megasas", instance)) { instance->irq_context[i].instance = instance;
printk(KERN_DEBUG "megasas: Failed to register IRQ\n"); instance->irq_context[i].MSIxIndex = i;
goto fail_irq; if (request_irq(instance->msixentry[i].vector,
instance->instancet->service_isr, 0,
"megasas",
&instance->irq_context[i])) {
printk(KERN_DEBUG "megasas: Failed to "
"register IRQ for vector %d.\n", i);
for (j = 0 ; j < i ; j++)
free_irq(
instance->msixentry[j].vector,
&instance->irq_context[j]);
goto fail_irq;
}
}
} else {
instance->irq_context[0].instance = instance;
instance->irq_context[0].MSIxIndex = 0;
if (request_irq(pdev->irq, instance->instancet->service_isr,
IRQF_SHARED, "megasas",
&instance->irq_context[0])) {
printk(KERN_DEBUG "megasas: Failed to register IRQ\n");
goto fail_irq;
}
} }
instance->instancet->enable_intr(instance->reg_set); instance->instancet->enable_intr(instance->reg_set);
...@@ -4174,8 +4218,12 @@ megasas_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) ...@@ -4174,8 +4218,12 @@ megasas_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
pci_set_drvdata(pdev, NULL); pci_set_drvdata(pdev, NULL);
instance->instancet->disable_intr(instance->reg_set); instance->instancet->disable_intr(instance->reg_set);
free_irq(instance->msi_flag ? instance->msixentry.vector : if (instance->msix_vectors)
instance->pdev->irq, instance); for (i = 0 ; i < instance->msix_vectors; i++)
free_irq(instance->msixentry[i].vector,
&instance->irq_context[i]);
else
free_irq(instance->pdev->irq, &instance->irq_context[0]);
fail_irq: fail_irq:
if ((instance->pdev->device == PCI_DEVICE_ID_LSI_FUSION) || if ((instance->pdev->device == PCI_DEVICE_ID_LSI_FUSION) ||
(instance->pdev->device == PCI_DEVICE_ID_LSI_INVADER)) (instance->pdev->device == PCI_DEVICE_ID_LSI_INVADER))
...@@ -4183,7 +4231,7 @@ megasas_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) ...@@ -4183,7 +4231,7 @@ megasas_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
else else
megasas_release_mfi(instance); megasas_release_mfi(instance);
fail_init_mfi: fail_init_mfi:
if (instance->msi_flag) if (instance->msix_vectors)
pci_disable_msix(instance->pdev); pci_disable_msix(instance->pdev);
fail_alloc_dma_buf: fail_alloc_dma_buf:
if (instance->evt_detail) if (instance->evt_detail)
...@@ -4299,6 +4347,7 @@ megasas_suspend(struct pci_dev *pdev, pm_message_t state) ...@@ -4299,6 +4347,7 @@ megasas_suspend(struct pci_dev *pdev, pm_message_t state)
{ {
struct Scsi_Host *host; struct Scsi_Host *host;
struct megasas_instance *instance; struct megasas_instance *instance;
int i;
instance = pci_get_drvdata(pdev); instance = pci_get_drvdata(pdev);
host = instance->host; host = instance->host;
...@@ -4322,9 +4371,14 @@ megasas_suspend(struct pci_dev *pdev, pm_message_t state) ...@@ -4322,9 +4371,14 @@ megasas_suspend(struct pci_dev *pdev, pm_message_t state)
pci_set_drvdata(instance->pdev, instance); pci_set_drvdata(instance->pdev, instance);
instance->instancet->disable_intr(instance->reg_set); instance->instancet->disable_intr(instance->reg_set);
free_irq(instance->msi_flag ? instance->msixentry.vector :
instance->pdev->irq, instance); if (instance->msix_vectors)
if (instance->msi_flag) for (i = 0 ; i < instance->msix_vectors; i++)
free_irq(instance->msixentry[i].vector,
&instance->irq_context[i]);
else
free_irq(instance->pdev->irq, &instance->irq_context[0]);
if (instance->msix_vectors)
pci_disable_msix(instance->pdev); pci_disable_msix(instance->pdev);
pci_save_state(pdev); pci_save_state(pdev);
...@@ -4342,7 +4396,7 @@ megasas_suspend(struct pci_dev *pdev, pm_message_t state) ...@@ -4342,7 +4396,7 @@ megasas_suspend(struct pci_dev *pdev, pm_message_t state)
static int static int
megasas_resume(struct pci_dev *pdev) megasas_resume(struct pci_dev *pdev)
{ {
int rval; int rval, i, j;
struct Scsi_Host *host; struct Scsi_Host *host;
struct megasas_instance *instance; struct megasas_instance *instance;
...@@ -4380,8 +4434,9 @@ megasas_resume(struct pci_dev *pdev) ...@@ -4380,8 +4434,9 @@ megasas_resume(struct pci_dev *pdev)
goto fail_ready_state; goto fail_ready_state;
/* Now re-enable MSI-X */ /* Now re-enable MSI-X */
if (instance->msi_flag) if (instance->msix_vectors)
pci_enable_msix(instance->pdev, &instance->msixentry, 1); pci_enable_msix(instance->pdev, instance->msixentry,
instance->msix_vectors);
switch (instance->pdev->device) { switch (instance->pdev->device) {
case PCI_DEVICE_ID_LSI_FUSION: case PCI_DEVICE_ID_LSI_FUSION:
...@@ -4411,11 +4466,32 @@ megasas_resume(struct pci_dev *pdev) ...@@ -4411,11 +4466,32 @@ megasas_resume(struct pci_dev *pdev)
/* /*
* Register IRQ * Register IRQ
*/ */
if (request_irq(instance->msi_flag ? instance->msixentry.vector : if (instance->msix_vectors) {
pdev->irq, instance->instancet->service_isr, for (i = 0 ; i < instance->msix_vectors; i++) {
IRQF_SHARED, "megasas", instance)) { instance->irq_context[i].instance = instance;
printk(KERN_ERR "megasas: Failed to register IRQ\n"); instance->irq_context[i].MSIxIndex = i;
goto fail_irq; if (request_irq(instance->msixentry[i].vector,
instance->instancet->service_isr, 0,
"megasas",
&instance->irq_context[i])) {
printk(KERN_DEBUG "megasas: Failed to "
"register IRQ for vector %d.\n", i);
for (j = 0 ; j < i ; j++)
free_irq(
instance->msixentry[j].vector,
&instance->irq_context[j]);
goto fail_irq;
}
}
} else {
instance->irq_context[0].instance = instance;
instance->irq_context[0].MSIxIndex = 0;
if (request_irq(pdev->irq, instance->instancet->service_isr,
IRQF_SHARED, "megasas",
&instance->irq_context[0])) {
printk(KERN_DEBUG "megasas: Failed to register IRQ\n");
goto fail_irq;
}
} }
instance->instancet->enable_intr(instance->reg_set); instance->instancet->enable_intr(instance->reg_set);
...@@ -4512,9 +4588,13 @@ static void __devexit megasas_detach_one(struct pci_dev *pdev) ...@@ -4512,9 +4588,13 @@ static void __devexit megasas_detach_one(struct pci_dev *pdev)
instance->instancet->disable_intr(instance->reg_set); instance->instancet->disable_intr(instance->reg_set);
free_irq(instance->msi_flag ? instance->msixentry.vector : if (instance->msix_vectors)
instance->pdev->irq, instance); for (i = 0 ; i < instance->msix_vectors; i++)
if (instance->msi_flag) free_irq(instance->msixentry[i].vector,
&instance->irq_context[i]);
else
free_irq(instance->pdev->irq, &instance->irq_context[0]);
if (instance->msix_vectors)
pci_disable_msix(instance->pdev); pci_disable_msix(instance->pdev);
switch (instance->pdev->device) { switch (instance->pdev->device) {
...@@ -4560,14 +4640,20 @@ static void __devexit megasas_detach_one(struct pci_dev *pdev) ...@@ -4560,14 +4640,20 @@ static void __devexit megasas_detach_one(struct pci_dev *pdev)
*/ */
static void megasas_shutdown(struct pci_dev *pdev) static void megasas_shutdown(struct pci_dev *pdev)
{ {
int i;
struct megasas_instance *instance = pci_get_drvdata(pdev); struct megasas_instance *instance = pci_get_drvdata(pdev);
instance->unload = 1; instance->unload = 1;
megasas_flush_cache(instance); megasas_flush_cache(instance);
megasas_shutdown_controller(instance, MR_DCMD_CTRL_SHUTDOWN); megasas_shutdown_controller(instance, MR_DCMD_CTRL_SHUTDOWN);
instance->instancet->disable_intr(instance->reg_set); instance->instancet->disable_intr(instance->reg_set);
free_irq(instance->msi_flag ? instance->msixentry.vector : if (instance->msix_vectors)
instance->pdev->irq, instance); for (i = 0 ; i < instance->msix_vectors; i++)
if (instance->msi_flag) free_irq(instance->msixentry[i].vector,
&instance->irq_context[i]);
else
free_irq(instance->pdev->irq, &instance->irq_context[0]);
if (instance->msix_vectors)
pci_disable_msix(instance->pdev); pci_disable_msix(instance->pdev);
} }
......
...@@ -385,7 +385,7 @@ static int megasas_create_frame_pool_fusion(struct megasas_instance *instance) ...@@ -385,7 +385,7 @@ static int megasas_create_frame_pool_fusion(struct megasas_instance *instance)
int int
megasas_alloc_cmds_fusion(struct megasas_instance *instance) megasas_alloc_cmds_fusion(struct megasas_instance *instance)
{ {
int i, j; int i, j, count;
u32 max_cmd, io_frames_sz; u32 max_cmd, io_frames_sz;
struct fusion_context *fusion; struct fusion_context *fusion;
struct megasas_cmd_fusion *cmd; struct megasas_cmd_fusion *cmd;
...@@ -409,9 +409,10 @@ megasas_alloc_cmds_fusion(struct megasas_instance *instance) ...@@ -409,9 +409,10 @@ megasas_alloc_cmds_fusion(struct megasas_instance *instance)
goto fail_req_desc; goto fail_req_desc;
} }
count = instance->msix_vectors > 0 ? instance->msix_vectors : 1;
fusion->reply_frames_desc_pool = fusion->reply_frames_desc_pool =
pci_pool_create("reply_frames pool", instance->pdev, pci_pool_create("reply_frames pool", instance->pdev,
fusion->reply_alloc_sz, 16, 0); fusion->reply_alloc_sz * count, 16, 0);
if (!fusion->reply_frames_desc_pool) { if (!fusion->reply_frames_desc_pool) {
printk(KERN_ERR "megasas; Could not allocate memory for " printk(KERN_ERR "megasas; Could not allocate memory for "
...@@ -430,7 +431,7 @@ megasas_alloc_cmds_fusion(struct megasas_instance *instance) ...@@ -430,7 +431,7 @@ megasas_alloc_cmds_fusion(struct megasas_instance *instance)
} }
reply_desc = fusion->reply_frames_desc; reply_desc = fusion->reply_frames_desc;
for (i = 0; i < fusion->reply_q_depth; i++, reply_desc++) for (i = 0; i < fusion->reply_q_depth * count; i++, reply_desc++)
reply_desc->Words = ULLONG_MAX; reply_desc->Words = ULLONG_MAX;
io_frames_sz = fusion->io_frames_alloc_sz; io_frames_sz = fusion->io_frames_alloc_sz;
...@@ -633,7 +634,9 @@ megasas_ioc_init_fusion(struct megasas_instance *instance) ...@@ -633,7 +634,9 @@ megasas_ioc_init_fusion(struct megasas_instance *instance)
fusion->reply_frames_desc_phys; fusion->reply_frames_desc_phys;
IOCInitMessage->SystemRequestFrameBaseAddress = IOCInitMessage->SystemRequestFrameBaseAddress =
fusion->io_request_frames_phys; fusion->io_request_frames_phys;
/* Set to 0 for none or 1 MSI-X vectors */
IOCInitMessage->HostMSIxVectors = (instance->msix_vectors > 0 ?
instance->msix_vectors : 0);
init_frame = (struct megasas_init_frame *)cmd->frame; init_frame = (struct megasas_init_frame *)cmd->frame;
memset(init_frame, 0, MEGAMFI_FRAME_SIZE); memset(init_frame, 0, MEGAMFI_FRAME_SIZE);
...@@ -877,7 +880,7 @@ megasas_init_adapter_fusion(struct megasas_instance *instance) ...@@ -877,7 +880,7 @@ megasas_init_adapter_fusion(struct megasas_instance *instance)
struct megasas_register_set __iomem *reg_set; struct megasas_register_set __iomem *reg_set;
struct fusion_context *fusion; struct fusion_context *fusion;
u32 max_cmd; u32 max_cmd;
int i = 0; int i = 0, count;
fusion = instance->ctrl_context; fusion = instance->ctrl_context;
...@@ -929,7 +932,9 @@ megasas_init_adapter_fusion(struct megasas_instance *instance) ...@@ -929,7 +932,9 @@ megasas_init_adapter_fusion(struct megasas_instance *instance)
(MEGA_MPI2_RAID_DEFAULT_IO_FRAME_SIZE - (MEGA_MPI2_RAID_DEFAULT_IO_FRAME_SIZE -
sizeof(union MPI2_SGE_IO_UNION))/16; sizeof(union MPI2_SGE_IO_UNION))/16;
fusion->last_reply_idx = 0; count = instance->msix_vectors > 0 ? instance->msix_vectors : 1;
for (i = 0 ; i < count; i++)
fusion->last_reply_idx[i] = 0;
/* /*
* Allocate memory for descriptors * Allocate memory for descriptors
...@@ -1421,6 +1426,12 @@ megasas_build_ldio_fusion(struct megasas_instance *instance, ...@@ -1421,6 +1426,12 @@ megasas_build_ldio_fusion(struct megasas_instance *instance,
fp_possible = io_info.fpOkForIo; fp_possible = io_info.fpOkForIo;
} }
/* Use 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 ?
smp_processor_id() % instance->msix_vectors : 0;
if (fp_possible) { if (fp_possible) {
megasas_set_pd_lba(io_request, scp->cmd_len, &io_info, scp, megasas_set_pd_lba(io_request, scp->cmd_len, &io_info, scp,
local_map_ptr, start_lba_lo); local_map_ptr, start_lba_lo);
...@@ -1691,7 +1702,7 @@ megasas_build_and_issue_cmd_fusion(struct megasas_instance *instance, ...@@ -1691,7 +1702,7 @@ megasas_build_and_issue_cmd_fusion(struct megasas_instance *instance,
* Completes all commands that is in reply descriptor queue * Completes all commands that is in reply descriptor queue
*/ */
int int
complete_cmd_fusion(struct megasas_instance *instance) complete_cmd_fusion(struct megasas_instance *instance, u32 MSIxIndex)
{ {
union MPI2_REPLY_DESCRIPTORS_UNION *desc; union MPI2_REPLY_DESCRIPTORS_UNION *desc;
struct MPI2_SCSI_IO_SUCCESS_REPLY_DESCRIPTOR *reply_desc; struct MPI2_SCSI_IO_SUCCESS_REPLY_DESCRIPTOR *reply_desc;
...@@ -1711,7 +1722,9 @@ complete_cmd_fusion(struct megasas_instance *instance) ...@@ -1711,7 +1722,9 @@ complete_cmd_fusion(struct megasas_instance *instance)
return IRQ_HANDLED; return IRQ_HANDLED;
desc = fusion->reply_frames_desc; desc = fusion->reply_frames_desc;
desc += fusion->last_reply_idx; desc += ((MSIxIndex * fusion->reply_alloc_sz)/
sizeof(union MPI2_REPLY_DESCRIPTORS_UNION)) +
fusion->last_reply_idx[MSIxIndex];
reply_desc = (struct MPI2_SCSI_IO_SUCCESS_REPLY_DESCRIPTOR *)desc; reply_desc = (struct MPI2_SCSI_IO_SUCCESS_REPLY_DESCRIPTOR *)desc;
...@@ -1784,16 +1797,19 @@ complete_cmd_fusion(struct megasas_instance *instance) ...@@ -1784,16 +1797,19 @@ complete_cmd_fusion(struct megasas_instance *instance)
break; break;
} }
fusion->last_reply_idx++; fusion->last_reply_idx[MSIxIndex]++;
if (fusion->last_reply_idx >= fusion->reply_q_depth) if (fusion->last_reply_idx[MSIxIndex] >=
fusion->last_reply_idx = 0; fusion->reply_q_depth)
fusion->last_reply_idx[MSIxIndex] = 0;
desc->Words = ULLONG_MAX; desc->Words = ULLONG_MAX;
num_completed++; num_completed++;
/* Get the next reply descriptor */ /* Get the next reply descriptor */
if (!fusion->last_reply_idx) if (!fusion->last_reply_idx[MSIxIndex])
desc = fusion->reply_frames_desc; desc = fusion->reply_frames_desc +
((MSIxIndex * fusion->reply_alloc_sz)/
sizeof(union MPI2_REPLY_DESCRIPTORS_UNION));
else else
desc++; desc++;
...@@ -1813,7 +1829,7 @@ complete_cmd_fusion(struct megasas_instance *instance) ...@@ -1813,7 +1829,7 @@ complete_cmd_fusion(struct megasas_instance *instance)
return IRQ_NONE; return IRQ_NONE;
wmb(); wmb();
writel(fusion->last_reply_idx, writel((MSIxIndex << 24) | fusion->last_reply_idx[MSIxIndex],
&instance->reg_set->reply_post_host_index); &instance->reg_set->reply_post_host_index);
megasas_check_and_restore_queue_depth(instance); megasas_check_and_restore_queue_depth(instance);
return IRQ_HANDLED; return IRQ_HANDLED;
...@@ -1831,6 +1847,9 @@ megasas_complete_cmd_dpc_fusion(unsigned long instance_addr) ...@@ -1831,6 +1847,9 @@ megasas_complete_cmd_dpc_fusion(unsigned long instance_addr)
struct megasas_instance *instance = struct megasas_instance *instance =
(struct megasas_instance *)instance_addr; (struct megasas_instance *)instance_addr;
unsigned long flags; unsigned long flags;
u32 count, MSIxIndex;
count = instance->msix_vectors > 0 ? instance->msix_vectors : 1;
/* If we have already declared adapter dead, donot complete cmds */ /* If we have already declared adapter dead, donot complete cmds */
spin_lock_irqsave(&instance->hba_lock, flags); spin_lock_irqsave(&instance->hba_lock, flags);
...@@ -1841,7 +1860,8 @@ megasas_complete_cmd_dpc_fusion(unsigned long instance_addr) ...@@ -1841,7 +1860,8 @@ megasas_complete_cmd_dpc_fusion(unsigned long instance_addr)
spin_unlock_irqrestore(&instance->hba_lock, flags); spin_unlock_irqrestore(&instance->hba_lock, flags);
spin_lock_irqsave(&instance->completion_lock, flags); spin_lock_irqsave(&instance->completion_lock, flags);
complete_cmd_fusion(instance); for (MSIxIndex = 0 ; MSIxIndex < count; MSIxIndex++)
complete_cmd_fusion(instance, MSIxIndex);
spin_unlock_irqrestore(&instance->completion_lock, flags); spin_unlock_irqrestore(&instance->completion_lock, flags);
} }
...@@ -1850,10 +1870,11 @@ megasas_complete_cmd_dpc_fusion(unsigned long instance_addr) ...@@ -1850,10 +1870,11 @@ megasas_complete_cmd_dpc_fusion(unsigned long instance_addr)
*/ */
irqreturn_t megasas_isr_fusion(int irq, void *devp) irqreturn_t megasas_isr_fusion(int irq, void *devp)
{ {
struct megasas_instance *instance = (struct megasas_instance *)devp; struct megasas_irq_context *irq_context = devp;
struct megasas_instance *instance = irq_context->instance;
u32 mfiStatus, fw_state; u32 mfiStatus, fw_state;
if (!instance->msi_flag) { if (!instance->msix_vectors) {
mfiStatus = instance->instancet->clear_intr(instance->reg_set); mfiStatus = instance->instancet->clear_intr(instance->reg_set);
if (!mfiStatus) if (!mfiStatus)
return IRQ_NONE; return IRQ_NONE;
...@@ -1865,7 +1886,7 @@ irqreturn_t megasas_isr_fusion(int irq, void *devp) ...@@ -1865,7 +1886,7 @@ irqreturn_t megasas_isr_fusion(int irq, void *devp)
return IRQ_HANDLED; return IRQ_HANDLED;
} }
if (!complete_cmd_fusion(instance)) { if (!complete_cmd_fusion(instance, irq_context->MSIxIndex)) {
instance->instancet->clear_intr(instance->reg_set); instance->instancet->clear_intr(instance->reg_set);
/* If we didn't complete any commands, check for FW fault */ /* If we didn't complete any commands, check for FW fault */
fw_state = instance->instancet->read_fw_status_reg( fw_state = instance->instancet->read_fw_status_reg(
...@@ -2081,14 +2102,16 @@ int megasas_wait_for_outstanding_fusion(struct megasas_instance *instance) ...@@ -2081,14 +2102,16 @@ int megasas_wait_for_outstanding_fusion(struct megasas_instance *instance)
void megasas_reset_reply_desc(struct megasas_instance *instance) void megasas_reset_reply_desc(struct megasas_instance *instance)
{ {
int i; int i, count;
struct fusion_context *fusion; struct fusion_context *fusion;
union MPI2_REPLY_DESCRIPTORS_UNION *reply_desc; union MPI2_REPLY_DESCRIPTORS_UNION *reply_desc;
fusion = instance->ctrl_context; fusion = instance->ctrl_context;
fusion->last_reply_idx = 0; count = instance->msix_vectors > 0 ? instance->msix_vectors : 1;
for (i = 0 ; i < count ; i++)
fusion->last_reply_idx[i] = 0;
reply_desc = fusion->reply_frames_desc; reply_desc = fusion->reply_frames_desc;
for (i = 0 ; i < fusion->reply_q_depth; i++, reply_desc++) for (i = 0 ; i < fusion->reply_q_depth * count; i++, reply_desc++)
reply_desc->Words = ULLONG_MAX; reply_desc->Words = ULLONG_MAX;
} }
......
...@@ -43,6 +43,7 @@ ...@@ -43,6 +43,7 @@
#define HOST_DIAG_WRITE_ENABLE 0x80 #define HOST_DIAG_WRITE_ENABLE 0x80
#define HOST_DIAG_RESET_ADAPTER 0x4 #define HOST_DIAG_RESET_ADAPTER 0x4
#define MEGASAS_FUSION_MAX_RESET_TRIES 3 #define MEGASAS_FUSION_MAX_RESET_TRIES 3
#define MAX_MSIX_QUEUES_FUSION 16
/* Invader defines */ /* Invader defines */
#define MPI2_TYPE_CUDA 0x2 #define MPI2_TYPE_CUDA 0x2
...@@ -673,7 +674,7 @@ struct fusion_context { ...@@ -673,7 +674,7 @@ struct fusion_context {
union MPI2_REPLY_DESCRIPTORS_UNION *reply_frames_desc; union MPI2_REPLY_DESCRIPTORS_UNION *reply_frames_desc;
struct dma_pool *reply_frames_desc_pool; struct dma_pool *reply_frames_desc_pool;
u16 last_reply_idx; u16 last_reply_idx[MAX_MSIX_QUEUES_FUSION];
u32 reply_q_depth; u32 reply_q_depth;
u32 request_alloc_sz; u32 request_alloc_sz;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment