diff options
Diffstat (limited to 'drivers/scsi/megaraid')
-rw-r--r-- | drivers/scsi/megaraid/megaraid_sas.h | 11 | ||||
-rw-r--r-- | drivers/scsi/megaraid/megaraid_sas_base.c | 156 | ||||
-rw-r--r-- | drivers/scsi/megaraid/megaraid_sas_fusion.c | 65 | ||||
-rw-r--r-- | drivers/scsi/megaraid/megaraid_sas_fusion.h | 3 |
4 files changed, 176 insertions, 59 deletions
diff --git a/drivers/scsi/megaraid/megaraid_sas.h b/drivers/scsi/megaraid/megaraid_sas.h index 6b3562554937..9ffb92daa58b 100644 --- a/drivers/scsi/megaraid/megaraid_sas.h +++ b/drivers/scsi/megaraid/megaraid_sas.h | |||
@@ -757,6 +757,7 @@ struct megasas_ctrl_info { | |||
757 | #define MEGASAS_INT_CMDS 32 | 757 | #define MEGASAS_INT_CMDS 32 |
758 | #define MEGASAS_SKINNY_INT_CMDS 5 | 758 | #define MEGASAS_SKINNY_INT_CMDS 5 |
759 | 759 | ||
760 | #define MEGASAS_MAX_MSIX_QUEUES 16 | ||
760 | /* | 761 | /* |
761 | * FW can accept both 32 and 64 bit SGLs. We want to allocate 32/64 bit | 762 | * FW can accept both 32 and 64 bit SGLs. We want to allocate 32/64 bit |
762 | * SGLs based on the size of dma_addr_t | 763 | * SGLs based on the size of dma_addr_t |
@@ -1278,6 +1279,11 @@ struct megasas_aen_event { | |||
1278 | struct megasas_instance *instance; | 1279 | struct megasas_instance *instance; |
1279 | }; | 1280 | }; |
1280 | 1281 | ||
1282 | struct megasas_irq_context { | ||
1283 | struct megasas_instance *instance; | ||
1284 | u32 MSIxIndex; | ||
1285 | }; | ||
1286 | |||
1281 | struct megasas_instance { | 1287 | struct megasas_instance { |
1282 | 1288 | ||
1283 | u32 *producer; | 1289 | u32 *producer; |
@@ -1351,8 +1357,9 @@ struct megasas_instance { | |||
1351 | 1357 | ||
1352 | /* Ptr to hba specific information */ | 1358 | /* Ptr to hba specific information */ |
1353 | void *ctrl_context; | 1359 | void *ctrl_context; |
1354 | u8 msi_flag; | 1360 | unsigned int msix_vectors; |
1355 | struct msix_entry msixentry; | 1361 | struct msix_entry msixentry[MEGASAS_MAX_MSIX_QUEUES]; |
1362 | struct megasas_irq_context irq_context[MEGASAS_MAX_MSIX_QUEUES]; | ||
1356 | u64 map_id; | 1363 | u64 map_id; |
1357 | struct megasas_cmd *map_update_cmd; | 1364 | struct megasas_cmd *map_update_cmd; |
1358 | unsigned long bar; | 1365 | unsigned long bar; |
diff --git a/drivers/scsi/megaraid/megaraid_sas_base.c b/drivers/scsi/megaraid/megaraid_sas_base.c index f2cf768c896d..ec09d5c2ed90 100644 --- a/drivers/scsi/megaraid/megaraid_sas_base.c +++ b/drivers/scsi/megaraid/megaraid_sas_base.c | |||
@@ -2536,7 +2536,7 @@ megasas_deplete_reply_queue(struct megasas_instance *instance, | |||
2536 | instance->reg_set) | 2536 | instance->reg_set) |
2537 | ) == 0) { | 2537 | ) == 0) { |
2538 | /* Hardware may not set outbound_intr_status in MSI-X mode */ | 2538 | /* Hardware may not set outbound_intr_status in MSI-X mode */ |
2539 | if (!instance->msi_flag) | 2539 | if (!instance->msix_vectors) |
2540 | return IRQ_NONE; | 2540 | return IRQ_NONE; |
2541 | } | 2541 | } |
2542 | 2542 | ||
@@ -2594,16 +2594,14 @@ megasas_deplete_reply_queue(struct megasas_instance *instance, | |||
2594 | */ | 2594 | */ |
2595 | static irqreturn_t megasas_isr(int irq, void *devp) | 2595 | static irqreturn_t megasas_isr(int irq, void *devp) |
2596 | { | 2596 | { |
2597 | struct megasas_instance *instance; | 2597 | struct megasas_irq_context *irq_context = devp; |
2598 | struct megasas_instance *instance = irq_context->instance; | ||
2598 | unsigned long flags; | 2599 | unsigned long flags; |
2599 | irqreturn_t rc; | 2600 | irqreturn_t rc; |
2600 | 2601 | ||
2601 | if (atomic_read( | 2602 | if (atomic_read(&instance->fw_reset_no_pci_access)) |
2602 | &(((struct megasas_instance *)devp)->fw_reset_no_pci_access))) | ||
2603 | return IRQ_HANDLED; | 2603 | return IRQ_HANDLED; |
2604 | 2604 | ||
2605 | instance = (struct megasas_instance *)devp; | ||
2606 | |||
2607 | spin_lock_irqsave(&instance->hba_lock, flags); | 2605 | spin_lock_irqsave(&instance->hba_lock, flags); |
2608 | rc = megasas_deplete_reply_queue(instance, DID_OK); | 2606 | rc = megasas_deplete_reply_queue(instance, DID_OK); |
2609 | spin_unlock_irqrestore(&instance->hba_lock, flags); | 2607 | spin_unlock_irqrestore(&instance->hba_lock, flags); |
@@ -3488,6 +3486,7 @@ static int megasas_init_fw(struct megasas_instance *instance) | |||
3488 | struct megasas_register_set __iomem *reg_set; | 3486 | struct megasas_register_set __iomem *reg_set; |
3489 | struct megasas_ctrl_info *ctrl_info; | 3487 | struct megasas_ctrl_info *ctrl_info; |
3490 | unsigned long bar_list; | 3488 | unsigned long bar_list; |
3489 | int i; | ||
3491 | 3490 | ||
3492 | /* Find first memory bar */ | 3491 | /* Find first memory bar */ |
3493 | bar_list = pci_select_bars(instance->pdev, IORESOURCE_MEM); | 3492 | bar_list = pci_select_bars(instance->pdev, IORESOURCE_MEM); |
@@ -3541,9 +3540,33 @@ static int megasas_init_fw(struct megasas_instance *instance) | |||
3541 | /* Check if MSI-X is supported while in ready state */ | 3540 | /* Check if MSI-X is supported while in ready state */ |
3542 | msix_enable = (instance->instancet->read_fw_status_reg(reg_set) & | 3541 | msix_enable = (instance->instancet->read_fw_status_reg(reg_set) & |
3543 | 0x4000000) >> 0x1a; | 3542 | 0x4000000) >> 0x1a; |
3544 | if (msix_enable && !msix_disable && | 3543 | if (msix_enable && !msix_disable) { |
3545 | !pci_enable_msix(instance->pdev, &instance->msixentry, 1)) | 3544 | /* Check max MSI-X vectors */ |
3546 | instance->msi_flag = 1; | 3545 | if ((instance->pdev->device == PCI_DEVICE_ID_LSI_FUSION) || |
3546 | (instance->pdev->device == PCI_DEVICE_ID_LSI_INVADER)) { | ||
3547 | instance->msix_vectors = (readl(&instance->reg_set-> | ||
3548 | outbound_scratch_pad_2 | ||
3549 | ) & 0x1F) + 1; | ||
3550 | } else | ||
3551 | instance->msix_vectors = 1; | ||
3552 | /* Don't bother allocating more MSI-X vectors than cpus */ | ||
3553 | instance->msix_vectors = min(instance->msix_vectors, | ||
3554 | (unsigned int)num_online_cpus()); | ||
3555 | for (i = 0; i < instance->msix_vectors; i++) | ||
3556 | instance->msixentry[i].entry = i; | ||
3557 | i = pci_enable_msix(instance->pdev, instance->msixentry, | ||
3558 | instance->msix_vectors); | ||
3559 | if (i >= 0) { | ||
3560 | if (i) { | ||
3561 | if (!pci_enable_msix(instance->pdev, | ||
3562 | instance->msixentry, i)) | ||
3563 | instance->msix_vectors = i; | ||
3564 | else | ||
3565 | instance->msix_vectors = 0; | ||
3566 | } | ||
3567 | } else | ||
3568 | instance->msix_vectors = 0; | ||
3569 | } | ||
3547 | 3570 | ||
3548 | /* Get operational params, sge flags, send init cmd to controller */ | 3571 | /* Get operational params, sge flags, send init cmd to controller */ |
3549 | if (instance->instancet->init_adapter(instance)) | 3572 | if (instance->instancet->init_adapter(instance)) |
@@ -3958,7 +3981,7 @@ fail_set_dma_mask: | |||
3958 | static int __devinit | 3981 | static int __devinit |
3959 | megasas_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) | 3982 | megasas_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) |
3960 | { | 3983 | { |
3961 | int rval, pos; | 3984 | int rval, pos, i, j; |
3962 | struct Scsi_Host *host; | 3985 | struct Scsi_Host *host; |
3963 | struct megasas_instance *instance; | 3986 | struct megasas_instance *instance; |
3964 | u16 control = 0; | 3987 | u16 control = 0; |
@@ -4126,11 +4149,32 @@ megasas_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) | |||
4126 | /* | 4149 | /* |
4127 | * Register IRQ | 4150 | * Register IRQ |
4128 | */ | 4151 | */ |
4129 | if (request_irq(instance->msi_flag ? instance->msixentry.vector : | 4152 | if (instance->msix_vectors) { |
4130 | pdev->irq, instance->instancet->service_isr, | 4153 | for (i = 0 ; i < instance->msix_vectors; i++) { |
4131 | IRQF_SHARED, "megasas", instance)) { | 4154 | instance->irq_context[i].instance = instance; |
4132 | printk(KERN_DEBUG "megasas: Failed to register IRQ\n"); | 4155 | instance->irq_context[i].MSIxIndex = i; |
4133 | goto fail_irq; | 4156 | if (request_irq(instance->msixentry[i].vector, |
4157 | instance->instancet->service_isr, 0, | ||
4158 | "megasas", | ||
4159 | &instance->irq_context[i])) { | ||
4160 | printk(KERN_DEBUG "megasas: Failed to " | ||
4161 | "register IRQ for vector %d.\n", i); | ||
4162 | for (j = 0 ; j < i ; j++) | ||
4163 | free_irq( | ||
4164 | instance->msixentry[j].vector, | ||
4165 | &instance->irq_context[j]); | ||
4166 | goto fail_irq; | ||
4167 | } | ||
4168 | } | ||
4169 | } else { | ||
4170 | instance->irq_context[0].instance = instance; | ||
4171 | instance->irq_context[0].MSIxIndex = 0; | ||
4172 | if (request_irq(pdev->irq, instance->instancet->service_isr, | ||
4173 | IRQF_SHARED, "megasas", | ||
4174 | &instance->irq_context[0])) { | ||
4175 | printk(KERN_DEBUG "megasas: Failed to register IRQ\n"); | ||
4176 | goto fail_irq; | ||
4177 | } | ||
4134 | } | 4178 | } |
4135 | 4179 | ||
4136 | instance->instancet->enable_intr(instance->reg_set); | 4180 | 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 | 4218 | ||
4175 | pci_set_drvdata(pdev, NULL); | 4219 | pci_set_drvdata(pdev, NULL); |
4176 | instance->instancet->disable_intr(instance->reg_set); | 4220 | instance->instancet->disable_intr(instance->reg_set); |
4177 | free_irq(instance->msi_flag ? instance->msixentry.vector : | 4221 | if (instance->msix_vectors) |
4178 | instance->pdev->irq, instance); | 4222 | for (i = 0 ; i < instance->msix_vectors; i++) |
4223 | free_irq(instance->msixentry[i].vector, | ||
4224 | &instance->irq_context[i]); | ||
4225 | else | ||
4226 | free_irq(instance->pdev->irq, &instance->irq_context[0]); | ||
4179 | fail_irq: | 4227 | fail_irq: |
4180 | if ((instance->pdev->device == PCI_DEVICE_ID_LSI_FUSION) || | 4228 | if ((instance->pdev->device == PCI_DEVICE_ID_LSI_FUSION) || |
4181 | (instance->pdev->device == PCI_DEVICE_ID_LSI_INVADER)) | 4229 | (instance->pdev->device == PCI_DEVICE_ID_LSI_INVADER)) |
@@ -4183,7 +4231,7 @@ fail_irq: | |||
4183 | else | 4231 | else |
4184 | megasas_release_mfi(instance); | 4232 | megasas_release_mfi(instance); |
4185 | fail_init_mfi: | 4233 | fail_init_mfi: |
4186 | if (instance->msi_flag) | 4234 | if (instance->msix_vectors) |
4187 | pci_disable_msix(instance->pdev); | 4235 | pci_disable_msix(instance->pdev); |
4188 | fail_alloc_dma_buf: | 4236 | fail_alloc_dma_buf: |
4189 | if (instance->evt_detail) | 4237 | if (instance->evt_detail) |
@@ -4299,6 +4347,7 @@ megasas_suspend(struct pci_dev *pdev, pm_message_t state) | |||
4299 | { | 4347 | { |
4300 | struct Scsi_Host *host; | 4348 | struct Scsi_Host *host; |
4301 | struct megasas_instance *instance; | 4349 | struct megasas_instance *instance; |
4350 | int i; | ||
4302 | 4351 | ||
4303 | instance = pci_get_drvdata(pdev); | 4352 | instance = pci_get_drvdata(pdev); |
4304 | host = instance->host; | 4353 | host = instance->host; |
@@ -4322,9 +4371,14 @@ megasas_suspend(struct pci_dev *pdev, pm_message_t state) | |||
4322 | 4371 | ||
4323 | pci_set_drvdata(instance->pdev, instance); | 4372 | pci_set_drvdata(instance->pdev, instance); |
4324 | instance->instancet->disable_intr(instance->reg_set); | 4373 | instance->instancet->disable_intr(instance->reg_set); |
4325 | free_irq(instance->msi_flag ? instance->msixentry.vector : | 4374 | |
4326 | instance->pdev->irq, instance); | 4375 | if (instance->msix_vectors) |
4327 | if (instance->msi_flag) | 4376 | for (i = 0 ; i < instance->msix_vectors; i++) |
4377 | free_irq(instance->msixentry[i].vector, | ||
4378 | &instance->irq_context[i]); | ||
4379 | else | ||
4380 | free_irq(instance->pdev->irq, &instance->irq_context[0]); | ||
4381 | if (instance->msix_vectors) | ||
4328 | pci_disable_msix(instance->pdev); | 4382 | pci_disable_msix(instance->pdev); |
4329 | 4383 | ||
4330 | pci_save_state(pdev); | 4384 | pci_save_state(pdev); |
@@ -4342,7 +4396,7 @@ megasas_suspend(struct pci_dev *pdev, pm_message_t state) | |||
4342 | static int | 4396 | static int |
4343 | megasas_resume(struct pci_dev *pdev) | 4397 | megasas_resume(struct pci_dev *pdev) |
4344 | { | 4398 | { |
4345 | int rval; | 4399 | int rval, i, j; |
4346 | struct Scsi_Host *host; | 4400 | struct Scsi_Host *host; |
4347 | struct megasas_instance *instance; | 4401 | struct megasas_instance *instance; |
4348 | 4402 | ||
@@ -4380,8 +4434,9 @@ megasas_resume(struct pci_dev *pdev) | |||
4380 | goto fail_ready_state; | 4434 | goto fail_ready_state; |
4381 | 4435 | ||
4382 | /* Now re-enable MSI-X */ | 4436 | /* Now re-enable MSI-X */ |
4383 | if (instance->msi_flag) | 4437 | if (instance->msix_vectors) |
4384 | pci_enable_msix(instance->pdev, &instance->msixentry, 1); | 4438 | pci_enable_msix(instance->pdev, instance->msixentry, |
4439 | instance->msix_vectors); | ||
4385 | 4440 | ||
4386 | switch (instance->pdev->device) { | 4441 | switch (instance->pdev->device) { |
4387 | case PCI_DEVICE_ID_LSI_FUSION: | 4442 | case PCI_DEVICE_ID_LSI_FUSION: |
@@ -4411,11 +4466,32 @@ megasas_resume(struct pci_dev *pdev) | |||
4411 | /* | 4466 | /* |
4412 | * Register IRQ | 4467 | * Register IRQ |
4413 | */ | 4468 | */ |
4414 | if (request_irq(instance->msi_flag ? instance->msixentry.vector : | 4469 | if (instance->msix_vectors) { |
4415 | pdev->irq, instance->instancet->service_isr, | 4470 | for (i = 0 ; i < instance->msix_vectors; i++) { |
4416 | IRQF_SHARED, "megasas", instance)) { | 4471 | instance->irq_context[i].instance = instance; |
4417 | printk(KERN_ERR "megasas: Failed to register IRQ\n"); | 4472 | instance->irq_context[i].MSIxIndex = i; |
4418 | goto fail_irq; | 4473 | if (request_irq(instance->msixentry[i].vector, |
4474 | instance->instancet->service_isr, 0, | ||
4475 | "megasas", | ||
4476 | &instance->irq_context[i])) { | ||
4477 | printk(KERN_DEBUG "megasas: Failed to " | ||
4478 | "register IRQ for vector %d.\n", i); | ||
4479 | for (j = 0 ; j < i ; j++) | ||
4480 | free_irq( | ||
4481 | instance->msixentry[j].vector, | ||
4482 | &instance->irq_context[j]); | ||
4483 | goto fail_irq; | ||
4484 | } | ||
4485 | } | ||
4486 | } else { | ||
4487 | instance->irq_context[0].instance = instance; | ||
4488 | instance->irq_context[0].MSIxIndex = 0; | ||
4489 | if (request_irq(pdev->irq, instance->instancet->service_isr, | ||
4490 | IRQF_SHARED, "megasas", | ||
4491 | &instance->irq_context[0])) { | ||
4492 | printk(KERN_DEBUG "megasas: Failed to register IRQ\n"); | ||
4493 | goto fail_irq; | ||
4494 | } | ||
4419 | } | 4495 | } |
4420 | 4496 | ||
4421 | instance->instancet->enable_intr(instance->reg_set); | 4497 | instance->instancet->enable_intr(instance->reg_set); |
@@ -4512,9 +4588,13 @@ static void __devexit megasas_detach_one(struct pci_dev *pdev) | |||
4512 | 4588 | ||
4513 | instance->instancet->disable_intr(instance->reg_set); | 4589 | instance->instancet->disable_intr(instance->reg_set); |
4514 | 4590 | ||
4515 | free_irq(instance->msi_flag ? instance->msixentry.vector : | 4591 | if (instance->msix_vectors) |
4516 | instance->pdev->irq, instance); | 4592 | for (i = 0 ; i < instance->msix_vectors; i++) |
4517 | if (instance->msi_flag) | 4593 | free_irq(instance->msixentry[i].vector, |
4594 | &instance->irq_context[i]); | ||
4595 | else | ||
4596 | free_irq(instance->pdev->irq, &instance->irq_context[0]); | ||
4597 | if (instance->msix_vectors) | ||
4518 | pci_disable_msix(instance->pdev); | 4598 | pci_disable_msix(instance->pdev); |
4519 | 4599 | ||
4520 | switch (instance->pdev->device) { | 4600 | switch (instance->pdev->device) { |
@@ -4560,14 +4640,20 @@ static void __devexit megasas_detach_one(struct pci_dev *pdev) | |||
4560 | */ | 4640 | */ |
4561 | static void megasas_shutdown(struct pci_dev *pdev) | 4641 | static void megasas_shutdown(struct pci_dev *pdev) |
4562 | { | 4642 | { |
4643 | int i; | ||
4563 | struct megasas_instance *instance = pci_get_drvdata(pdev); | 4644 | struct megasas_instance *instance = pci_get_drvdata(pdev); |
4645 | |||
4564 | instance->unload = 1; | 4646 | instance->unload = 1; |
4565 | megasas_flush_cache(instance); | 4647 | megasas_flush_cache(instance); |
4566 | megasas_shutdown_controller(instance, MR_DCMD_CTRL_SHUTDOWN); | 4648 | megasas_shutdown_controller(instance, MR_DCMD_CTRL_SHUTDOWN); |
4567 | instance->instancet->disable_intr(instance->reg_set); | 4649 | instance->instancet->disable_intr(instance->reg_set); |
4568 | free_irq(instance->msi_flag ? instance->msixentry.vector : | 4650 | if (instance->msix_vectors) |
4569 | instance->pdev->irq, instance); | 4651 | for (i = 0 ; i < instance->msix_vectors; i++) |
4570 | if (instance->msi_flag) | 4652 | free_irq(instance->msixentry[i].vector, |
4653 | &instance->irq_context[i]); | ||
4654 | else | ||
4655 | free_irq(instance->pdev->irq, &instance->irq_context[0]); | ||
4656 | if (instance->msix_vectors) | ||
4571 | pci_disable_msix(instance->pdev); | 4657 | pci_disable_msix(instance->pdev); |
4572 | } | 4658 | } |
4573 | 4659 | ||
diff --git a/drivers/scsi/megaraid/megaraid_sas_fusion.c b/drivers/scsi/megaraid/megaraid_sas_fusion.c index ad6bd061a0f8..bfd87fab39aa 100644 --- a/drivers/scsi/megaraid/megaraid_sas_fusion.c +++ b/drivers/scsi/megaraid/megaraid_sas_fusion.c | |||
@@ -385,7 +385,7 @@ static int megasas_create_frame_pool_fusion(struct megasas_instance *instance) | |||
385 | int | 385 | int |
386 | megasas_alloc_cmds_fusion(struct megasas_instance *instance) | 386 | megasas_alloc_cmds_fusion(struct megasas_instance *instance) |
387 | { | 387 | { |
388 | int i, j; | 388 | int i, j, count; |
389 | u32 max_cmd, io_frames_sz; | 389 | u32 max_cmd, io_frames_sz; |
390 | struct fusion_context *fusion; | 390 | struct fusion_context *fusion; |
391 | struct megasas_cmd_fusion *cmd; | 391 | struct megasas_cmd_fusion *cmd; |
@@ -409,9 +409,10 @@ megasas_alloc_cmds_fusion(struct megasas_instance *instance) | |||
409 | goto fail_req_desc; | 409 | goto fail_req_desc; |
410 | } | 410 | } |
411 | 411 | ||
412 | count = instance->msix_vectors > 0 ? instance->msix_vectors : 1; | ||
412 | fusion->reply_frames_desc_pool = | 413 | fusion->reply_frames_desc_pool = |
413 | pci_pool_create("reply_frames pool", instance->pdev, | 414 | pci_pool_create("reply_frames pool", instance->pdev, |
414 | fusion->reply_alloc_sz, 16, 0); | 415 | fusion->reply_alloc_sz * count, 16, 0); |
415 | 416 | ||
416 | if (!fusion->reply_frames_desc_pool) { | 417 | if (!fusion->reply_frames_desc_pool) { |
417 | printk(KERN_ERR "megasas; Could not allocate memory for " | 418 | printk(KERN_ERR "megasas; Could not allocate memory for " |
@@ -430,7 +431,7 @@ megasas_alloc_cmds_fusion(struct megasas_instance *instance) | |||
430 | } | 431 | } |
431 | 432 | ||
432 | reply_desc = fusion->reply_frames_desc; | 433 | reply_desc = fusion->reply_frames_desc; |
433 | for (i = 0; i < fusion->reply_q_depth; i++, reply_desc++) | 434 | for (i = 0; i < fusion->reply_q_depth * count; i++, reply_desc++) |
434 | reply_desc->Words = ULLONG_MAX; | 435 | reply_desc->Words = ULLONG_MAX; |
435 | 436 | ||
436 | io_frames_sz = fusion->io_frames_alloc_sz; | 437 | io_frames_sz = fusion->io_frames_alloc_sz; |
@@ -633,7 +634,9 @@ megasas_ioc_init_fusion(struct megasas_instance *instance) | |||
633 | fusion->reply_frames_desc_phys; | 634 | fusion->reply_frames_desc_phys; |
634 | IOCInitMessage->SystemRequestFrameBaseAddress = | 635 | IOCInitMessage->SystemRequestFrameBaseAddress = |
635 | fusion->io_request_frames_phys; | 636 | fusion->io_request_frames_phys; |
636 | 637 | /* Set to 0 for none or 1 MSI-X vectors */ | |
638 | IOCInitMessage->HostMSIxVectors = (instance->msix_vectors > 0 ? | ||
639 | instance->msix_vectors : 0); | ||
637 | init_frame = (struct megasas_init_frame *)cmd->frame; | 640 | init_frame = (struct megasas_init_frame *)cmd->frame; |
638 | memset(init_frame, 0, MEGAMFI_FRAME_SIZE); | 641 | memset(init_frame, 0, MEGAMFI_FRAME_SIZE); |
639 | 642 | ||
@@ -877,7 +880,7 @@ megasas_init_adapter_fusion(struct megasas_instance *instance) | |||
877 | struct megasas_register_set __iomem *reg_set; | 880 | struct megasas_register_set __iomem *reg_set; |
878 | struct fusion_context *fusion; | 881 | struct fusion_context *fusion; |
879 | u32 max_cmd; | 882 | u32 max_cmd; |
880 | int i = 0; | 883 | int i = 0, count; |
881 | 884 | ||
882 | fusion = instance->ctrl_context; | 885 | fusion = instance->ctrl_context; |
883 | 886 | ||
@@ -929,7 +932,9 @@ megasas_init_adapter_fusion(struct megasas_instance *instance) | |||
929 | (MEGA_MPI2_RAID_DEFAULT_IO_FRAME_SIZE - | 932 | (MEGA_MPI2_RAID_DEFAULT_IO_FRAME_SIZE - |
930 | sizeof(union MPI2_SGE_IO_UNION))/16; | 933 | sizeof(union MPI2_SGE_IO_UNION))/16; |
931 | 934 | ||
932 | fusion->last_reply_idx = 0; | 935 | count = instance->msix_vectors > 0 ? instance->msix_vectors : 1; |
936 | for (i = 0 ; i < count; i++) | ||
937 | fusion->last_reply_idx[i] = 0; | ||
933 | 938 | ||
934 | /* | 939 | /* |
935 | * Allocate memory for descriptors | 940 | * Allocate memory for descriptors |
@@ -1421,6 +1426,12 @@ megasas_build_ldio_fusion(struct megasas_instance *instance, | |||
1421 | fp_possible = io_info.fpOkForIo; | 1426 | fp_possible = io_info.fpOkForIo; |
1422 | } | 1427 | } |
1423 | 1428 | ||
1429 | /* Use smp_processor_id() for now until cmd->request->cpu is CPU | ||
1430 | id by default, not CPU group id, otherwise all MSI-X queues won't | ||
1431 | be utilized */ | ||
1432 | cmd->request_desc->SCSIIO.MSIxIndex = instance->msix_vectors ? | ||
1433 | smp_processor_id() % instance->msix_vectors : 0; | ||
1434 | |||
1424 | if (fp_possible) { | 1435 | if (fp_possible) { |
1425 | megasas_set_pd_lba(io_request, scp->cmd_len, &io_info, scp, | 1436 | megasas_set_pd_lba(io_request, scp->cmd_len, &io_info, scp, |
1426 | local_map_ptr, start_lba_lo); | 1437 | local_map_ptr, start_lba_lo); |
@@ -1691,7 +1702,7 @@ megasas_build_and_issue_cmd_fusion(struct megasas_instance *instance, | |||
1691 | * Completes all commands that is in reply descriptor queue | 1702 | * Completes all commands that is in reply descriptor queue |
1692 | */ | 1703 | */ |
1693 | int | 1704 | int |
1694 | complete_cmd_fusion(struct megasas_instance *instance) | 1705 | complete_cmd_fusion(struct megasas_instance *instance, u32 MSIxIndex) |
1695 | { | 1706 | { |
1696 | union MPI2_REPLY_DESCRIPTORS_UNION *desc; | 1707 | union MPI2_REPLY_DESCRIPTORS_UNION *desc; |
1697 | struct MPI2_SCSI_IO_SUCCESS_REPLY_DESCRIPTOR *reply_desc; | 1708 | struct MPI2_SCSI_IO_SUCCESS_REPLY_DESCRIPTOR *reply_desc; |
@@ -1711,7 +1722,9 @@ complete_cmd_fusion(struct megasas_instance *instance) | |||
1711 | return IRQ_HANDLED; | 1722 | return IRQ_HANDLED; |
1712 | 1723 | ||
1713 | desc = fusion->reply_frames_desc; | 1724 | desc = fusion->reply_frames_desc; |
1714 | desc += fusion->last_reply_idx; | 1725 | desc += ((MSIxIndex * fusion->reply_alloc_sz)/ |
1726 | sizeof(union MPI2_REPLY_DESCRIPTORS_UNION)) + | ||
1727 | fusion->last_reply_idx[MSIxIndex]; | ||
1715 | 1728 | ||
1716 | reply_desc = (struct MPI2_SCSI_IO_SUCCESS_REPLY_DESCRIPTOR *)desc; | 1729 | reply_desc = (struct MPI2_SCSI_IO_SUCCESS_REPLY_DESCRIPTOR *)desc; |
1717 | 1730 | ||
@@ -1784,16 +1797,19 @@ complete_cmd_fusion(struct megasas_instance *instance) | |||
1784 | break; | 1797 | break; |
1785 | } | 1798 | } |
1786 | 1799 | ||
1787 | fusion->last_reply_idx++; | 1800 | fusion->last_reply_idx[MSIxIndex]++; |
1788 | if (fusion->last_reply_idx >= fusion->reply_q_depth) | 1801 | if (fusion->last_reply_idx[MSIxIndex] >= |
1789 | fusion->last_reply_idx = 0; | 1802 | fusion->reply_q_depth) |
1803 | fusion->last_reply_idx[MSIxIndex] = 0; | ||
1790 | 1804 | ||
1791 | desc->Words = ULLONG_MAX; | 1805 | desc->Words = ULLONG_MAX; |
1792 | num_completed++; | 1806 | num_completed++; |
1793 | 1807 | ||
1794 | /* Get the next reply descriptor */ | 1808 | /* Get the next reply descriptor */ |
1795 | if (!fusion->last_reply_idx) | 1809 | if (!fusion->last_reply_idx[MSIxIndex]) |
1796 | desc = fusion->reply_frames_desc; | 1810 | desc = fusion->reply_frames_desc + |
1811 | ((MSIxIndex * fusion->reply_alloc_sz)/ | ||
1812 | sizeof(union MPI2_REPLY_DESCRIPTORS_UNION)); | ||
1797 | else | 1813 | else |
1798 | desc++; | 1814 | desc++; |
1799 | 1815 | ||
@@ -1813,7 +1829,7 @@ complete_cmd_fusion(struct megasas_instance *instance) | |||
1813 | return IRQ_NONE; | 1829 | return IRQ_NONE; |
1814 | 1830 | ||
1815 | wmb(); | 1831 | wmb(); |
1816 | writel(fusion->last_reply_idx, | 1832 | writel((MSIxIndex << 24) | fusion->last_reply_idx[MSIxIndex], |
1817 | &instance->reg_set->reply_post_host_index); | 1833 | &instance->reg_set->reply_post_host_index); |
1818 | megasas_check_and_restore_queue_depth(instance); | 1834 | megasas_check_and_restore_queue_depth(instance); |
1819 | return IRQ_HANDLED; | 1835 | return IRQ_HANDLED; |
@@ -1831,6 +1847,9 @@ megasas_complete_cmd_dpc_fusion(unsigned long instance_addr) | |||
1831 | struct megasas_instance *instance = | 1847 | struct megasas_instance *instance = |
1832 | (struct megasas_instance *)instance_addr; | 1848 | (struct megasas_instance *)instance_addr; |
1833 | unsigned long flags; | 1849 | unsigned long flags; |
1850 | u32 count, MSIxIndex; | ||
1851 | |||
1852 | count = instance->msix_vectors > 0 ? instance->msix_vectors : 1; | ||
1834 | 1853 | ||
1835 | /* If we have already declared adapter dead, donot complete cmds */ | 1854 | /* If we have already declared adapter dead, donot complete cmds */ |
1836 | spin_lock_irqsave(&instance->hba_lock, flags); | 1855 | spin_lock_irqsave(&instance->hba_lock, flags); |
@@ -1841,7 +1860,8 @@ megasas_complete_cmd_dpc_fusion(unsigned long instance_addr) | |||
1841 | spin_unlock_irqrestore(&instance->hba_lock, flags); | 1860 | spin_unlock_irqrestore(&instance->hba_lock, flags); |
1842 | 1861 | ||
1843 | spin_lock_irqsave(&instance->completion_lock, flags); | 1862 | spin_lock_irqsave(&instance->completion_lock, flags); |
1844 | complete_cmd_fusion(instance); | 1863 | for (MSIxIndex = 0 ; MSIxIndex < count; MSIxIndex++) |
1864 | complete_cmd_fusion(instance, MSIxIndex); | ||
1845 | spin_unlock_irqrestore(&instance->completion_lock, flags); | 1865 | spin_unlock_irqrestore(&instance->completion_lock, flags); |
1846 | } | 1866 | } |
1847 | 1867 | ||
@@ -1850,10 +1870,11 @@ megasas_complete_cmd_dpc_fusion(unsigned long instance_addr) | |||
1850 | */ | 1870 | */ |
1851 | irqreturn_t megasas_isr_fusion(int irq, void *devp) | 1871 | irqreturn_t megasas_isr_fusion(int irq, void *devp) |
1852 | { | 1872 | { |
1853 | struct megasas_instance *instance = (struct megasas_instance *)devp; | 1873 | struct megasas_irq_context *irq_context = devp; |
1874 | struct megasas_instance *instance = irq_context->instance; | ||
1854 | u32 mfiStatus, fw_state; | 1875 | u32 mfiStatus, fw_state; |
1855 | 1876 | ||
1856 | if (!instance->msi_flag) { | 1877 | if (!instance->msix_vectors) { |
1857 | mfiStatus = instance->instancet->clear_intr(instance->reg_set); | 1878 | mfiStatus = instance->instancet->clear_intr(instance->reg_set); |
1858 | if (!mfiStatus) | 1879 | if (!mfiStatus) |
1859 | return IRQ_NONE; | 1880 | return IRQ_NONE; |
@@ -1865,7 +1886,7 @@ irqreturn_t megasas_isr_fusion(int irq, void *devp) | |||
1865 | return IRQ_HANDLED; | 1886 | return IRQ_HANDLED; |
1866 | } | 1887 | } |
1867 | 1888 | ||
1868 | if (!complete_cmd_fusion(instance)) { | 1889 | if (!complete_cmd_fusion(instance, irq_context->MSIxIndex)) { |
1869 | instance->instancet->clear_intr(instance->reg_set); | 1890 | instance->instancet->clear_intr(instance->reg_set); |
1870 | /* If we didn't complete any commands, check for FW fault */ | 1891 | /* If we didn't complete any commands, check for FW fault */ |
1871 | fw_state = instance->instancet->read_fw_status_reg( | 1892 | fw_state = instance->instancet->read_fw_status_reg( |
@@ -2081,14 +2102,16 @@ out: | |||
2081 | 2102 | ||
2082 | void megasas_reset_reply_desc(struct megasas_instance *instance) | 2103 | void megasas_reset_reply_desc(struct megasas_instance *instance) |
2083 | { | 2104 | { |
2084 | int i; | 2105 | int i, count; |
2085 | struct fusion_context *fusion; | 2106 | struct fusion_context *fusion; |
2086 | union MPI2_REPLY_DESCRIPTORS_UNION *reply_desc; | 2107 | union MPI2_REPLY_DESCRIPTORS_UNION *reply_desc; |
2087 | 2108 | ||
2088 | fusion = instance->ctrl_context; | 2109 | fusion = instance->ctrl_context; |
2089 | fusion->last_reply_idx = 0; | 2110 | count = instance->msix_vectors > 0 ? instance->msix_vectors : 1; |
2111 | for (i = 0 ; i < count ; i++) | ||
2112 | fusion->last_reply_idx[i] = 0; | ||
2090 | reply_desc = fusion->reply_frames_desc; | 2113 | reply_desc = fusion->reply_frames_desc; |
2091 | for (i = 0 ; i < fusion->reply_q_depth; i++, reply_desc++) | 2114 | for (i = 0 ; i < fusion->reply_q_depth * count; i++, reply_desc++) |
2092 | reply_desc->Words = ULLONG_MAX; | 2115 | reply_desc->Words = ULLONG_MAX; |
2093 | } | 2116 | } |
2094 | 2117 | ||
diff --git a/drivers/scsi/megaraid/megaraid_sas_fusion.h b/drivers/scsi/megaraid/megaraid_sas_fusion.h index 9556c08490b2..088c9f91da95 100644 --- a/drivers/scsi/megaraid/megaraid_sas_fusion.h +++ b/drivers/scsi/megaraid/megaraid_sas_fusion.h | |||
@@ -43,6 +43,7 @@ | |||
43 | #define HOST_DIAG_WRITE_ENABLE 0x80 | 43 | #define HOST_DIAG_WRITE_ENABLE 0x80 |
44 | #define HOST_DIAG_RESET_ADAPTER 0x4 | 44 | #define HOST_DIAG_RESET_ADAPTER 0x4 |
45 | #define MEGASAS_FUSION_MAX_RESET_TRIES 3 | 45 | #define MEGASAS_FUSION_MAX_RESET_TRIES 3 |
46 | #define MAX_MSIX_QUEUES_FUSION 16 | ||
46 | 47 | ||
47 | /* Invader defines */ | 48 | /* Invader defines */ |
48 | #define MPI2_TYPE_CUDA 0x2 | 49 | #define MPI2_TYPE_CUDA 0x2 |
@@ -673,7 +674,7 @@ struct fusion_context { | |||
673 | union MPI2_REPLY_DESCRIPTORS_UNION *reply_frames_desc; | 674 | union MPI2_REPLY_DESCRIPTORS_UNION *reply_frames_desc; |
674 | struct dma_pool *reply_frames_desc_pool; | 675 | struct dma_pool *reply_frames_desc_pool; |
675 | 676 | ||
676 | u16 last_reply_idx; | 677 | u16 last_reply_idx[MAX_MSIX_QUEUES_FUSION]; |
677 | 678 | ||
678 | u32 reply_q_depth; | 679 | u32 reply_q_depth; |
679 | u32 request_alloc_sz; | 680 | u32 request_alloc_sz; |