diff options
author | Sumit.Saxena@lsi.com <Sumit.Saxena@lsi.com> | 2013-05-22 03:04:14 -0400 |
---|---|---|
committer | James Bottomley <JBottomley@Parallels.com> | 2013-06-24 20:46:31 -0400 |
commit | d46a3ad679c7232b72b21c6d0ca047dc4a68063f (patch) | |
tree | cae11de87870963d335838e24b01814081e0cbf8 /drivers/scsi/megaraid | |
parent | 5d0d908d4481187070cc94664417ab347f15d1fe (diff) |
[SCSI] megaraid_sas: Add support for Extended MSI-x vectors for 12Gb/s controller
This Driver will use more than 8 MSI-x support provided by Invader/Fury max
upto 128 MSI-x.
[jejb: fix checkpatch warning]
Signed-off-by: Sumit Saxena <sumit.saxena@lsi.com>
Signed-off-by: Kashyap Desai <kashyap.desai@lsi.com>
Signed-off-by: James Bottomley <JBottomley@Parallels.com>
Diffstat (limited to 'drivers/scsi/megaraid')
-rw-r--r-- | drivers/scsi/megaraid/megaraid_sas.h | 25 | ||||
-rw-r--r-- | drivers/scsi/megaraid/megaraid_sas_base.c | 111 | ||||
-rw-r--r-- | drivers/scsi/megaraid/megaraid_sas_fusion.c | 38 | ||||
-rw-r--r-- | drivers/scsi/megaraid/megaraid_sas_fusion.h | 5 |
4 files changed, 136 insertions, 43 deletions
diff --git a/drivers/scsi/megaraid/megaraid_sas.h b/drivers/scsi/megaraid/megaraid_sas.h index 9504b519e121..2371e5ca2a5b 100644 --- a/drivers/scsi/megaraid/megaraid_sas.h +++ b/drivers/scsi/megaraid/megaraid_sas.h | |||
@@ -786,7 +786,7 @@ struct megasas_ctrl_info { | |||
786 | #define MEGASAS_INT_CMDS 32 | 786 | #define MEGASAS_INT_CMDS 32 |
787 | #define MEGASAS_SKINNY_INT_CMDS 5 | 787 | #define MEGASAS_SKINNY_INT_CMDS 5 |
788 | 788 | ||
789 | #define MEGASAS_MAX_MSIX_QUEUES 16 | 789 | #define MEGASAS_MAX_MSIX_QUEUES 128 |
790 | /* | 790 | /* |
791 | * FW can accept both 32 and 64 bit SGLs. We want to allocate 32/64 bit | 791 | * FW can accept both 32 and 64 bit SGLs. We want to allocate 32/64 bit |
792 | * SGLs based on the size of dma_addr_t | 792 | * SGLs based on the size of dma_addr_t |
@@ -811,6 +811,11 @@ struct megasas_ctrl_info { | |||
811 | #define MFI_1068_PCSR_OFFSET 0x84 | 811 | #define MFI_1068_PCSR_OFFSET 0x84 |
812 | #define MFI_1068_FW_HANDSHAKE_OFFSET 0x64 | 812 | #define MFI_1068_FW_HANDSHAKE_OFFSET 0x64 |
813 | #define MFI_1068_FW_READY 0xDDDD0000 | 813 | #define MFI_1068_FW_READY 0xDDDD0000 |
814 | |||
815 | #define MR_MAX_REPLY_QUEUES_OFFSET 0X0000001F | ||
816 | #define MR_MAX_REPLY_QUEUES_EXT_OFFSET 0X003FC000 | ||
817 | #define MR_MAX_REPLY_QUEUES_EXT_OFFSET_SHIFT 14 | ||
818 | #define MR_MAX_MSIX_REG_ARRAY 16 | ||
814 | /* | 819 | /* |
815 | * register set for both 1068 and 1078 controllers | 820 | * register set for both 1068 and 1078 controllers |
816 | * structure extended for 1078 registers | 821 | * structure extended for 1078 registers |
@@ -920,6 +925,15 @@ union megasas_sgl_frame { | |||
920 | 925 | ||
921 | } __attribute__ ((packed)); | 926 | } __attribute__ ((packed)); |
922 | 927 | ||
928 | typedef union _MFI_CAPABILITIES { | ||
929 | struct { | ||
930 | u32 support_fp_remote_lun:1; | ||
931 | u32 support_additional_msix:1; | ||
932 | u32 reserved:30; | ||
933 | } mfi_capabilities; | ||
934 | u32 reg; | ||
935 | } MFI_CAPABILITIES; | ||
936 | |||
923 | struct megasas_init_frame { | 937 | struct megasas_init_frame { |
924 | 938 | ||
925 | u8 cmd; /*00h */ | 939 | u8 cmd; /*00h */ |
@@ -927,7 +941,7 @@ struct megasas_init_frame { | |||
927 | u8 cmd_status; /*02h */ | 941 | u8 cmd_status; /*02h */ |
928 | 942 | ||
929 | u8 reserved_1; /*03h */ | 943 | u8 reserved_1; /*03h */ |
930 | u32 reserved_2; /*04h */ | 944 | MFI_CAPABILITIES driver_operations; /*04h*/ |
931 | 945 | ||
932 | u32 context; /*08h */ | 946 | u32 context; /*08h */ |
933 | u32 pad_0; /*0Ch */ | 947 | u32 pad_0; /*0Ch */ |
@@ -1324,7 +1338,7 @@ struct megasas_instance { | |||
1324 | 1338 | ||
1325 | unsigned long base_addr; | 1339 | unsigned long base_addr; |
1326 | struct megasas_register_set __iomem *reg_set; | 1340 | struct megasas_register_set __iomem *reg_set; |
1327 | 1341 | u32 *reply_post_host_index_addr[MR_MAX_MSIX_REG_ARRAY]; | |
1328 | struct megasas_pd_list pd_list[MEGASAS_MAX_PD]; | 1342 | struct megasas_pd_list pd_list[MEGASAS_MAX_PD]; |
1329 | u8 ld_ids[MEGASAS_MAX_LD_IDS]; | 1343 | u8 ld_ids[MEGASAS_MAX_LD_IDS]; |
1330 | s8 init_id; | 1344 | s8 init_id; |
@@ -1393,6 +1407,7 @@ struct megasas_instance { | |||
1393 | long reset_flags; | 1407 | long reset_flags; |
1394 | struct mutex reset_mutex; | 1408 | struct mutex reset_mutex; |
1395 | int throttlequeuedepth; | 1409 | int throttlequeuedepth; |
1410 | u8 mask_interrupts; | ||
1396 | }; | 1411 | }; |
1397 | 1412 | ||
1398 | enum { | 1413 | enum { |
@@ -1408,8 +1423,8 @@ struct megasas_instance_template { | |||
1408 | void (*fire_cmd)(struct megasas_instance *, dma_addr_t, \ | 1423 | void (*fire_cmd)(struct megasas_instance *, dma_addr_t, \ |
1409 | u32, struct megasas_register_set __iomem *); | 1424 | u32, struct megasas_register_set __iomem *); |
1410 | 1425 | ||
1411 | void (*enable_intr)(struct megasas_register_set __iomem *) ; | 1426 | void (*enable_intr)(struct megasas_instance *); |
1412 | void (*disable_intr)(struct megasas_register_set __iomem *); | 1427 | void (*disable_intr)(struct megasas_instance *); |
1413 | 1428 | ||
1414 | int (*clear_intr)(struct megasas_register_set __iomem *); | 1429 | int (*clear_intr)(struct megasas_register_set __iomem *); |
1415 | 1430 | ||
diff --git a/drivers/scsi/megaraid/megaraid_sas_base.c b/drivers/scsi/megaraid/megaraid_sas_base.c index 63108d7849a4..11f1c940a2aa 100644 --- a/drivers/scsi/megaraid/megaraid_sas_base.c +++ b/drivers/scsi/megaraid/megaraid_sas_base.c | |||
@@ -244,8 +244,10 @@ megasas_return_cmd(struct megasas_instance *instance, struct megasas_cmd *cmd) | |||
244 | * @regs: MFI register set | 244 | * @regs: MFI register set |
245 | */ | 245 | */ |
246 | static inline void | 246 | static inline void |
247 | megasas_enable_intr_xscale(struct megasas_register_set __iomem * regs) | 247 | megasas_enable_intr_xscale(struct megasas_instance *instance) |
248 | { | 248 | { |
249 | struct megasas_register_set __iomem *regs; | ||
250 | regs = instance->reg_set; | ||
249 | writel(0, &(regs)->outbound_intr_mask); | 251 | writel(0, &(regs)->outbound_intr_mask); |
250 | 252 | ||
251 | /* Dummy readl to force pci flush */ | 253 | /* Dummy readl to force pci flush */ |
@@ -257,9 +259,11 @@ megasas_enable_intr_xscale(struct megasas_register_set __iomem * regs) | |||
257 | * @regs: MFI register set | 259 | * @regs: MFI register set |
258 | */ | 260 | */ |
259 | static inline void | 261 | static inline void |
260 | megasas_disable_intr_xscale(struct megasas_register_set __iomem * regs) | 262 | megasas_disable_intr_xscale(struct megasas_instance *instance) |
261 | { | 263 | { |
264 | struct megasas_register_set __iomem *regs; | ||
262 | u32 mask = 0x1f; | 265 | u32 mask = 0x1f; |
266 | regs = instance->reg_set; | ||
263 | writel(mask, ®s->outbound_intr_mask); | 267 | writel(mask, ®s->outbound_intr_mask); |
264 | /* Dummy readl to force pci flush */ | 268 | /* Dummy readl to force pci flush */ |
265 | readl(®s->outbound_intr_mask); | 269 | readl(®s->outbound_intr_mask); |
@@ -413,8 +417,10 @@ static struct megasas_instance_template megasas_instance_template_xscale = { | |||
413 | * @regs: MFI register set | 417 | * @regs: MFI register set |
414 | */ | 418 | */ |
415 | static inline void | 419 | static inline void |
416 | megasas_enable_intr_ppc(struct megasas_register_set __iomem * regs) | 420 | megasas_enable_intr_ppc(struct megasas_instance *instance) |
417 | { | 421 | { |
422 | struct megasas_register_set __iomem *regs; | ||
423 | regs = instance->reg_set; | ||
418 | writel(0xFFFFFFFF, &(regs)->outbound_doorbell_clear); | 424 | writel(0xFFFFFFFF, &(regs)->outbound_doorbell_clear); |
419 | 425 | ||
420 | writel(~0x80000000, &(regs)->outbound_intr_mask); | 426 | writel(~0x80000000, &(regs)->outbound_intr_mask); |
@@ -428,9 +434,11 @@ megasas_enable_intr_ppc(struct megasas_register_set __iomem * regs) | |||
428 | * @regs: MFI register set | 434 | * @regs: MFI register set |
429 | */ | 435 | */ |
430 | static inline void | 436 | static inline void |
431 | megasas_disable_intr_ppc(struct megasas_register_set __iomem * regs) | 437 | megasas_disable_intr_ppc(struct megasas_instance *instance) |
432 | { | 438 | { |
439 | struct megasas_register_set __iomem *regs; | ||
433 | u32 mask = 0xFFFFFFFF; | 440 | u32 mask = 0xFFFFFFFF; |
441 | regs = instance->reg_set; | ||
434 | writel(mask, ®s->outbound_intr_mask); | 442 | writel(mask, ®s->outbound_intr_mask); |
435 | /* Dummy readl to force pci flush */ | 443 | /* Dummy readl to force pci flush */ |
436 | readl(®s->outbound_intr_mask); | 444 | readl(®s->outbound_intr_mask); |
@@ -531,8 +539,10 @@ static struct megasas_instance_template megasas_instance_template_ppc = { | |||
531 | * @regs: MFI register set | 539 | * @regs: MFI register set |
532 | */ | 540 | */ |
533 | static inline void | 541 | static inline void |
534 | megasas_enable_intr_skinny(struct megasas_register_set __iomem *regs) | 542 | megasas_enable_intr_skinny(struct megasas_instance *instance) |
535 | { | 543 | { |
544 | struct megasas_register_set __iomem *regs; | ||
545 | regs = instance->reg_set; | ||
536 | writel(0xFFFFFFFF, &(regs)->outbound_intr_mask); | 546 | writel(0xFFFFFFFF, &(regs)->outbound_intr_mask); |
537 | 547 | ||
538 | writel(~MFI_SKINNY_ENABLE_INTERRUPT_MASK, &(regs)->outbound_intr_mask); | 548 | writel(~MFI_SKINNY_ENABLE_INTERRUPT_MASK, &(regs)->outbound_intr_mask); |
@@ -546,9 +556,11 @@ megasas_enable_intr_skinny(struct megasas_register_set __iomem *regs) | |||
546 | * @regs: MFI register set | 556 | * @regs: MFI register set |
547 | */ | 557 | */ |
548 | static inline void | 558 | static inline void |
549 | megasas_disable_intr_skinny(struct megasas_register_set __iomem *regs) | 559 | megasas_disable_intr_skinny(struct megasas_instance *instance) |
550 | { | 560 | { |
561 | struct megasas_register_set __iomem *regs; | ||
551 | u32 mask = 0xFFFFFFFF; | 562 | u32 mask = 0xFFFFFFFF; |
563 | regs = instance->reg_set; | ||
552 | writel(mask, ®s->outbound_intr_mask); | 564 | writel(mask, ®s->outbound_intr_mask); |
553 | /* Dummy readl to force pci flush */ | 565 | /* Dummy readl to force pci flush */ |
554 | readl(®s->outbound_intr_mask); | 566 | readl(®s->outbound_intr_mask); |
@@ -666,8 +678,10 @@ static struct megasas_instance_template megasas_instance_template_skinny = { | |||
666 | * @regs: MFI register set | 678 | * @regs: MFI register set |
667 | */ | 679 | */ |
668 | static inline void | 680 | static inline void |
669 | megasas_enable_intr_gen2(struct megasas_register_set __iomem *regs) | 681 | megasas_enable_intr_gen2(struct megasas_instance *instance) |
670 | { | 682 | { |
683 | struct megasas_register_set __iomem *regs; | ||
684 | regs = instance->reg_set; | ||
671 | writel(0xFFFFFFFF, &(regs)->outbound_doorbell_clear); | 685 | writel(0xFFFFFFFF, &(regs)->outbound_doorbell_clear); |
672 | 686 | ||
673 | /* write ~0x00000005 (4 & 1) to the intr mask*/ | 687 | /* write ~0x00000005 (4 & 1) to the intr mask*/ |
@@ -682,9 +696,11 @@ megasas_enable_intr_gen2(struct megasas_register_set __iomem *regs) | |||
682 | * @regs: MFI register set | 696 | * @regs: MFI register set |
683 | */ | 697 | */ |
684 | static inline void | 698 | static inline void |
685 | megasas_disable_intr_gen2(struct megasas_register_set __iomem *regs) | 699 | megasas_disable_intr_gen2(struct megasas_instance *instance) |
686 | { | 700 | { |
701 | struct megasas_register_set __iomem *regs; | ||
687 | u32 mask = 0xFFFFFFFF; | 702 | u32 mask = 0xFFFFFFFF; |
703 | regs = instance->reg_set; | ||
688 | writel(mask, ®s->outbound_intr_mask); | 704 | writel(mask, ®s->outbound_intr_mask); |
689 | /* Dummy readl to force pci flush */ | 705 | /* Dummy readl to force pci flush */ |
690 | readl(®s->outbound_intr_mask); | 706 | readl(®s->outbound_intr_mask); |
@@ -1707,7 +1723,7 @@ void megasas_do_ocr(struct megasas_instance *instance) | |||
1707 | (instance->pdev->device == PCI_DEVICE_ID_LSI_VERDE_ZCR)) { | 1723 | (instance->pdev->device == PCI_DEVICE_ID_LSI_VERDE_ZCR)) { |
1708 | *instance->consumer = MEGASAS_ADPRESET_INPROG_SIGN; | 1724 | *instance->consumer = MEGASAS_ADPRESET_INPROG_SIGN; |
1709 | } | 1725 | } |
1710 | instance->instancet->disable_intr(instance->reg_set); | 1726 | instance->instancet->disable_intr(instance); |
1711 | instance->adprecovery = MEGASAS_ADPRESET_SM_INFAULT; | 1727 | instance->adprecovery = MEGASAS_ADPRESET_SM_INFAULT; |
1712 | instance->issuepend_done = 0; | 1728 | instance->issuepend_done = 0; |
1713 | 1729 | ||
@@ -2490,7 +2506,7 @@ process_fw_state_change_wq(struct work_struct *work) | |||
2490 | printk(KERN_NOTICE "megaraid_sas: FW detected to be in fault" | 2506 | printk(KERN_NOTICE "megaraid_sas: FW detected to be in fault" |
2491 | "state, restarting it...\n"); | 2507 | "state, restarting it...\n"); |
2492 | 2508 | ||
2493 | instance->instancet->disable_intr(instance->reg_set); | 2509 | instance->instancet->disable_intr(instance); |
2494 | atomic_set(&instance->fw_outstanding, 0); | 2510 | atomic_set(&instance->fw_outstanding, 0); |
2495 | 2511 | ||
2496 | atomic_set(&instance->fw_reset_no_pci_access, 1); | 2512 | atomic_set(&instance->fw_reset_no_pci_access, 1); |
@@ -2531,7 +2547,7 @@ process_fw_state_change_wq(struct work_struct *work) | |||
2531 | spin_lock_irqsave(&instance->hba_lock, flags); | 2547 | spin_lock_irqsave(&instance->hba_lock, flags); |
2532 | instance->adprecovery = MEGASAS_HBA_OPERATIONAL; | 2548 | instance->adprecovery = MEGASAS_HBA_OPERATIONAL; |
2533 | spin_unlock_irqrestore(&instance->hba_lock, flags); | 2549 | spin_unlock_irqrestore(&instance->hba_lock, flags); |
2534 | instance->instancet->enable_intr(instance->reg_set); | 2550 | instance->instancet->enable_intr(instance); |
2535 | 2551 | ||
2536 | megasas_issue_pending_cmds_again(instance); | 2552 | megasas_issue_pending_cmds_again(instance); |
2537 | instance->issuepend_done = 1; | 2553 | instance->issuepend_done = 1; |
@@ -2594,7 +2610,7 @@ megasas_deplete_reply_queue(struct megasas_instance *instance, | |||
2594 | } | 2610 | } |
2595 | 2611 | ||
2596 | 2612 | ||
2597 | instance->instancet->disable_intr(instance->reg_set); | 2613 | instance->instancet->disable_intr(instance); |
2598 | instance->adprecovery = MEGASAS_ADPRESET_SM_INFAULT; | 2614 | instance->adprecovery = MEGASAS_ADPRESET_SM_INFAULT; |
2599 | instance->issuepend_done = 0; | 2615 | instance->issuepend_done = 0; |
2600 | 2616 | ||
@@ -2728,7 +2744,7 @@ megasas_transition_to_ready(struct megasas_instance *instance, int ocr) | |||
2728 | /* | 2744 | /* |
2729 | * Bring it to READY state; assuming max wait 10 secs | 2745 | * Bring it to READY state; assuming max wait 10 secs |
2730 | */ | 2746 | */ |
2731 | instance->instancet->disable_intr(instance->reg_set); | 2747 | instance->instancet->disable_intr(instance); |
2732 | if ((instance->pdev->device == | 2748 | if ((instance->pdev->device == |
2733 | PCI_DEVICE_ID_LSI_SAS0073SKINNY) || | 2749 | PCI_DEVICE_ID_LSI_SAS0073SKINNY) || |
2734 | (instance->pdev->device == | 2750 | (instance->pdev->device == |
@@ -3374,7 +3390,7 @@ megasas_issue_init_mfi(struct megasas_instance *instance) | |||
3374 | /* | 3390 | /* |
3375 | * disable the intr before firing the init frame to FW | 3391 | * disable the intr before firing the init frame to FW |
3376 | */ | 3392 | */ |
3377 | instance->instancet->disable_intr(instance->reg_set); | 3393 | instance->instancet->disable_intr(instance); |
3378 | 3394 | ||
3379 | /* | 3395 | /* |
3380 | * Issue the init frame in polled mode | 3396 | * Issue the init frame in polled mode |
@@ -3481,11 +3497,11 @@ static int megasas_init_fw(struct megasas_instance *instance) | |||
3481 | { | 3497 | { |
3482 | u32 max_sectors_1; | 3498 | u32 max_sectors_1; |
3483 | u32 max_sectors_2; | 3499 | u32 max_sectors_2; |
3484 | u32 tmp_sectors, msix_enable; | 3500 | u32 tmp_sectors, msix_enable, scratch_pad_2; |
3485 | struct megasas_register_set __iomem *reg_set; | 3501 | struct megasas_register_set __iomem *reg_set; |
3486 | struct megasas_ctrl_info *ctrl_info; | 3502 | struct megasas_ctrl_info *ctrl_info; |
3487 | unsigned long bar_list; | 3503 | unsigned long bar_list; |
3488 | int i; | 3504 | int i, loop, fw_msix_count = 0; |
3489 | 3505 | ||
3490 | /* Find first memory bar */ | 3506 | /* Find first memory bar */ |
3491 | bar_list = pci_select_bars(instance->pdev, IORESOURCE_MEM); | 3507 | bar_list = pci_select_bars(instance->pdev, IORESOURCE_MEM); |
@@ -3537,21 +3553,49 @@ static int megasas_init_fw(struct megasas_instance *instance) | |||
3537 | if (megasas_transition_to_ready(instance, 0)) | 3553 | if (megasas_transition_to_ready(instance, 0)) |
3538 | goto fail_ready_state; | 3554 | goto fail_ready_state; |
3539 | 3555 | ||
3556 | /* | ||
3557 | * MSI-X host index 0 is common for all adapter. | ||
3558 | * It is used for all MPT based Adapters. | ||
3559 | */ | ||
3560 | instance->reply_post_host_index_addr[0] = | ||
3561 | (u32 *)((u8 *)instance->reg_set + | ||
3562 | MPI2_REPLY_POST_HOST_INDEX_OFFSET); | ||
3563 | |||
3540 | /* Check if MSI-X is supported while in ready state */ | 3564 | /* Check if MSI-X is supported while in ready state */ |
3541 | msix_enable = (instance->instancet->read_fw_status_reg(reg_set) & | 3565 | msix_enable = (instance->instancet->read_fw_status_reg(reg_set) & |
3542 | 0x4000000) >> 0x1a; | 3566 | 0x4000000) >> 0x1a; |
3543 | if (msix_enable && !msix_disable) { | 3567 | if (msix_enable && !msix_disable) { |
3568 | scratch_pad_2 = readl | ||
3569 | (&instance->reg_set->outbound_scratch_pad_2); | ||
3544 | /* Check max MSI-X vectors */ | 3570 | /* Check max MSI-X vectors */ |
3545 | if ((instance->pdev->device == PCI_DEVICE_ID_LSI_FUSION) || | 3571 | if (instance->pdev->device == PCI_DEVICE_ID_LSI_FUSION) { |
3546 | (instance->pdev->device == PCI_DEVICE_ID_LSI_INVADER) || | 3572 | instance->msix_vectors = (scratch_pad_2 |
3547 | (instance->pdev->device == PCI_DEVICE_ID_LSI_FURY)) { | 3573 | & MR_MAX_REPLY_QUEUES_OFFSET) + 1; |
3548 | instance->msix_vectors = (readl(&instance->reg_set-> | 3574 | fw_msix_count = instance->msix_vectors; |
3549 | outbound_scratch_pad_2 | ||
3550 | ) & 0x1F) + 1; | ||
3551 | if (msix_vectors) | 3575 | if (msix_vectors) |
3552 | instance->msix_vectors = | 3576 | instance->msix_vectors = |
3553 | min(msix_vectors, | 3577 | min(msix_vectors, |
3554 | instance->msix_vectors); | 3578 | instance->msix_vectors); |
3579 | } else if ((instance->pdev->device == PCI_DEVICE_ID_LSI_INVADER) | ||
3580 | || (instance->pdev->device == PCI_DEVICE_ID_LSI_FURY)) { | ||
3581 | /* Invader/Fury supports more than 8 MSI-X */ | ||
3582 | instance->msix_vectors = ((scratch_pad_2 | ||
3583 | & MR_MAX_REPLY_QUEUES_EXT_OFFSET) | ||
3584 | >> MR_MAX_REPLY_QUEUES_EXT_OFFSET_SHIFT) + 1; | ||
3585 | fw_msix_count = instance->msix_vectors; | ||
3586 | /* Save 1-15 reply post index address to local memory | ||
3587 | * Index 0 is already saved from reg offset | ||
3588 | * MPI2_REPLY_POST_HOST_INDEX_OFFSET | ||
3589 | */ | ||
3590 | for (loop = 1; loop < MR_MAX_MSIX_REG_ARRAY; loop++) { | ||
3591 | instance->reply_post_host_index_addr[loop] = | ||
3592 | (u32 *)((u8 *)instance->reg_set + | ||
3593 | MPI2_SUP_REPLY_POST_HOST_INDEX_OFFSET | ||
3594 | + (loop * 0x10)); | ||
3595 | } | ||
3596 | if (msix_vectors) | ||
3597 | instance->msix_vectors = min(msix_vectors, | ||
3598 | instance->msix_vectors); | ||
3555 | } else | 3599 | } else |
3556 | instance->msix_vectors = 1; | 3600 | instance->msix_vectors = 1; |
3557 | /* Don't bother allocating more MSI-X vectors than cpus */ | 3601 | /* Don't bother allocating more MSI-X vectors than cpus */ |
@@ -3571,6 +3615,12 @@ static int megasas_init_fw(struct megasas_instance *instance) | |||
3571 | } | 3615 | } |
3572 | } else | 3616 | } else |
3573 | instance->msix_vectors = 0; | 3617 | instance->msix_vectors = 0; |
3618 | |||
3619 | dev_info(&instance->pdev->dev, "[scsi%d]: FW supports" | ||
3620 | "<%d> MSIX vector,Online CPUs: <%d>," | ||
3621 | "Current MSIX <%d>\n", instance->host->host_no, | ||
3622 | fw_msix_count, (unsigned int)num_online_cpus(), | ||
3623 | instance->msix_vectors); | ||
3574 | } | 3624 | } |
3575 | 3625 | ||
3576 | /* Get operational params, sge flags, send init cmd to controller */ | 3626 | /* Get operational params, sge flags, send init cmd to controller */ |
@@ -4166,6 +4216,7 @@ static int megasas_probe_one(struct pci_dev *pdev, | |||
4166 | if (megasas_init_fw(instance)) | 4216 | if (megasas_init_fw(instance)) |
4167 | goto fail_init_mfi; | 4217 | goto fail_init_mfi; |
4168 | 4218 | ||
4219 | retry_irq_register: | ||
4169 | /* | 4220 | /* |
4170 | * Register IRQ | 4221 | * Register IRQ |
4171 | */ | 4222 | */ |
@@ -4183,7 +4234,9 @@ static int megasas_probe_one(struct pci_dev *pdev, | |||
4183 | free_irq( | 4234 | free_irq( |
4184 | instance->msixentry[j].vector, | 4235 | instance->msixentry[j].vector, |
4185 | &instance->irq_context[j]); | 4236 | &instance->irq_context[j]); |
4186 | goto fail_irq; | 4237 | /* Retry irq register for IO_APIC */ |
4238 | instance->msix_vectors = 0; | ||
4239 | goto retry_irq_register; | ||
4187 | } | 4240 | } |
4188 | } | 4241 | } |
4189 | } else { | 4242 | } else { |
@@ -4197,7 +4250,7 @@ static int megasas_probe_one(struct pci_dev *pdev, | |||
4197 | } | 4250 | } |
4198 | } | 4251 | } |
4199 | 4252 | ||
4200 | instance->instancet->enable_intr(instance->reg_set); | 4253 | instance->instancet->enable_intr(instance); |
4201 | 4254 | ||
4202 | /* | 4255 | /* |
4203 | * Store instance in PCI softstate | 4256 | * Store instance in PCI softstate |
@@ -4237,7 +4290,7 @@ static int megasas_probe_one(struct pci_dev *pdev, | |||
4237 | megasas_mgmt_info.max_index--; | 4290 | megasas_mgmt_info.max_index--; |
4238 | 4291 | ||
4239 | pci_set_drvdata(pdev, NULL); | 4292 | pci_set_drvdata(pdev, NULL); |
4240 | instance->instancet->disable_intr(instance->reg_set); | 4293 | instance->instancet->disable_intr(instance); |
4241 | if (instance->msix_vectors) | 4294 | if (instance->msix_vectors) |
4242 | for (i = 0 ; i < instance->msix_vectors; i++) | 4295 | for (i = 0 ; i < instance->msix_vectors; i++) |
4243 | free_irq(instance->msixentry[i].vector, | 4296 | free_irq(instance->msixentry[i].vector, |
@@ -4387,7 +4440,7 @@ megasas_suspend(struct pci_dev *pdev, pm_message_t state) | |||
4387 | tasklet_kill(&instance->isr_tasklet); | 4440 | tasklet_kill(&instance->isr_tasklet); |
4388 | 4441 | ||
4389 | pci_set_drvdata(instance->pdev, instance); | 4442 | pci_set_drvdata(instance->pdev, instance); |
4390 | instance->instancet->disable_intr(instance->reg_set); | 4443 | instance->instancet->disable_intr(instance); |
4391 | 4444 | ||
4392 | if (instance->msix_vectors) | 4445 | if (instance->msix_vectors) |
4393 | for (i = 0 ; i < instance->msix_vectors; i++) | 4446 | for (i = 0 ; i < instance->msix_vectors; i++) |
@@ -4512,7 +4565,7 @@ megasas_resume(struct pci_dev *pdev) | |||
4512 | } | 4565 | } |
4513 | } | 4566 | } |
4514 | 4567 | ||
4515 | instance->instancet->enable_intr(instance->reg_set); | 4568 | instance->instancet->enable_intr(instance); |
4516 | instance->unload = 0; | 4569 | instance->unload = 0; |
4517 | 4570 | ||
4518 | /* | 4571 | /* |
@@ -4594,7 +4647,7 @@ static void megasas_detach_one(struct pci_dev *pdev) | |||
4594 | 4647 | ||
4595 | pci_set_drvdata(instance->pdev, NULL); | 4648 | pci_set_drvdata(instance->pdev, NULL); |
4596 | 4649 | ||
4597 | instance->instancet->disable_intr(instance->reg_set); | 4650 | instance->instancet->disable_intr(instance); |
4598 | 4651 | ||
4599 | if (instance->msix_vectors) | 4652 | if (instance->msix_vectors) |
4600 | for (i = 0 ; i < instance->msix_vectors; i++) | 4653 | for (i = 0 ; i < instance->msix_vectors; i++) |
@@ -4654,7 +4707,7 @@ static void megasas_shutdown(struct pci_dev *pdev) | |||
4654 | instance->unload = 1; | 4707 | instance->unload = 1; |
4655 | megasas_flush_cache(instance); | 4708 | megasas_flush_cache(instance); |
4656 | megasas_shutdown_controller(instance, MR_DCMD_CTRL_SHUTDOWN); | 4709 | megasas_shutdown_controller(instance, MR_DCMD_CTRL_SHUTDOWN); |
4657 | instance->instancet->disable_intr(instance->reg_set); | 4710 | instance->instancet->disable_intr(instance); |
4658 | if (instance->msix_vectors) | 4711 | if (instance->msix_vectors) |
4659 | for (i = 0 ; i < instance->msix_vectors; i++) | 4712 | for (i = 0 ; i < instance->msix_vectors; i++) |
4660 | free_irq(instance->msixentry[i].vector, | 4713 | free_irq(instance->msixentry[i].vector, |
diff --git a/drivers/scsi/megaraid/megaraid_sas_fusion.c b/drivers/scsi/megaraid/megaraid_sas_fusion.c index c60f478c5aac..748b8ac5e1c3 100644 --- a/drivers/scsi/megaraid/megaraid_sas_fusion.c +++ b/drivers/scsi/megaraid/megaraid_sas_fusion.c | |||
@@ -101,8 +101,10 @@ extern int resetwaittime; | |||
101 | * @regs: MFI register set | 101 | * @regs: MFI register set |
102 | */ | 102 | */ |
103 | void | 103 | void |
104 | megasas_enable_intr_fusion(struct megasas_register_set __iomem *regs) | 104 | megasas_enable_intr_fusion(struct megasas_instance *instance) |
105 | { | 105 | { |
106 | struct megasas_register_set __iomem *regs; | ||
107 | regs = instance->reg_set; | ||
106 | /* For Thunderbolt/Invader also clear intr on enable */ | 108 | /* For Thunderbolt/Invader also clear intr on enable */ |
107 | writel(~0, ®s->outbound_intr_status); | 109 | writel(~0, ®s->outbound_intr_status); |
108 | readl(®s->outbound_intr_status); | 110 | readl(®s->outbound_intr_status); |
@@ -111,6 +113,7 @@ megasas_enable_intr_fusion(struct megasas_register_set __iomem *regs) | |||
111 | 113 | ||
112 | /* Dummy readl to force pci flush */ | 114 | /* Dummy readl to force pci flush */ |
113 | readl(®s->outbound_intr_mask); | 115 | readl(®s->outbound_intr_mask); |
116 | instance->mask_interrupts = 0; | ||
114 | } | 117 | } |
115 | 118 | ||
116 | /** | 119 | /** |
@@ -118,10 +121,13 @@ megasas_enable_intr_fusion(struct megasas_register_set __iomem *regs) | |||
118 | * @regs: MFI register set | 121 | * @regs: MFI register set |
119 | */ | 122 | */ |
120 | void | 123 | void |
121 | megasas_disable_intr_fusion(struct megasas_register_set __iomem *regs) | 124 | megasas_disable_intr_fusion(struct megasas_instance *instance) |
122 | { | 125 | { |
123 | u32 mask = 0xFFFFFFFF; | 126 | u32 mask = 0xFFFFFFFF; |
124 | u32 status; | 127 | u32 status; |
128 | struct megasas_register_set __iomem *regs; | ||
129 | regs = instance->reg_set; | ||
130 | instance->mask_interrupts = 1; | ||
125 | 131 | ||
126 | writel(mask, ®s->outbound_intr_mask); | 132 | writel(mask, ®s->outbound_intr_mask); |
127 | /* Dummy readl to force pci flush */ | 133 | /* Dummy readl to force pci flush */ |
@@ -643,6 +649,12 @@ megasas_ioc_init_fusion(struct megasas_instance *instance) | |||
643 | init_frame->cmd = MFI_CMD_INIT; | 649 | init_frame->cmd = MFI_CMD_INIT; |
644 | init_frame->cmd_status = 0xFF; | 650 | init_frame->cmd_status = 0xFF; |
645 | 651 | ||
652 | /* driver support Extended MSIX */ | ||
653 | if ((instance->pdev->device == PCI_DEVICE_ID_LSI_INVADER) || | ||
654 | (instance->pdev->device == PCI_DEVICE_ID_LSI_FURY)) | ||
655 | init_frame->driver_operations. | ||
656 | mfi_capabilities.support_additional_msix = 1; | ||
657 | |||
646 | init_frame->queue_info_new_phys_addr_lo = ioc_init_handle; | 658 | init_frame->queue_info_new_phys_addr_lo = ioc_init_handle; |
647 | init_frame->data_xfer_len = sizeof(struct MPI2_IOC_INIT_REQUEST); | 659 | init_frame->data_xfer_len = sizeof(struct MPI2_IOC_INIT_REQUEST); |
648 | 660 | ||
@@ -657,7 +669,7 @@ megasas_ioc_init_fusion(struct megasas_instance *instance) | |||
657 | /* | 669 | /* |
658 | * disable the intr before firing the init frame | 670 | * disable the intr before firing the init frame |
659 | */ | 671 | */ |
660 | instance->instancet->disable_intr(instance->reg_set); | 672 | instance->instancet->disable_intr(instance); |
661 | 673 | ||
662 | for (i = 0; i < (10 * 1000); i += 20) { | 674 | for (i = 0; i < (10 * 1000); i += 20) { |
663 | if (readl(&instance->reg_set->doorbell) & 1) | 675 | if (readl(&instance->reg_set->doorbell) & 1) |
@@ -1911,8 +1923,15 @@ complete_cmd_fusion(struct megasas_instance *instance, u32 MSIxIndex) | |||
1911 | return IRQ_NONE; | 1923 | return IRQ_NONE; |
1912 | 1924 | ||
1913 | wmb(); | 1925 | wmb(); |
1914 | writel((MSIxIndex << 24) | fusion->last_reply_idx[MSIxIndex], | 1926 | if ((instance->pdev->device == PCI_DEVICE_ID_LSI_INVADER) || |
1915 | &instance->reg_set->reply_post_host_index); | 1927 | (instance->pdev->device == PCI_DEVICE_ID_LSI_FURY)) |
1928 | writel(((MSIxIndex & 0x7) << 24) | | ||
1929 | fusion->last_reply_idx[MSIxIndex], | ||
1930 | instance->reply_post_host_index_addr[MSIxIndex/8]); | ||
1931 | else | ||
1932 | writel((MSIxIndex << 24) | | ||
1933 | fusion->last_reply_idx[MSIxIndex], | ||
1934 | instance->reply_post_host_index_addr[0]); | ||
1916 | megasas_check_and_restore_queue_depth(instance); | 1935 | megasas_check_and_restore_queue_depth(instance); |
1917 | return IRQ_HANDLED; | 1936 | return IRQ_HANDLED; |
1918 | } | 1937 | } |
@@ -1954,6 +1973,9 @@ irqreturn_t megasas_isr_fusion(int irq, void *devp) | |||
1954 | struct megasas_instance *instance = irq_context->instance; | 1973 | struct megasas_instance *instance = irq_context->instance; |
1955 | u32 mfiStatus, fw_state; | 1974 | u32 mfiStatus, fw_state; |
1956 | 1975 | ||
1976 | if (instance->mask_interrupts) | ||
1977 | return IRQ_NONE; | ||
1978 | |||
1957 | if (!instance->msix_vectors) { | 1979 | if (!instance->msix_vectors) { |
1958 | mfiStatus = instance->instancet->clear_intr(instance->reg_set); | 1980 | mfiStatus = instance->instancet->clear_intr(instance->reg_set); |
1959 | if (!mfiStatus) | 1981 | if (!mfiStatus) |
@@ -2219,7 +2241,7 @@ int megasas_reset_fusion(struct Scsi_Host *shost) | |||
2219 | mutex_lock(&instance->reset_mutex); | 2241 | mutex_lock(&instance->reset_mutex); |
2220 | set_bit(MEGASAS_FUSION_IN_RESET, &instance->reset_flags); | 2242 | set_bit(MEGASAS_FUSION_IN_RESET, &instance->reset_flags); |
2221 | instance->adprecovery = MEGASAS_ADPRESET_SM_INFAULT; | 2243 | instance->adprecovery = MEGASAS_ADPRESET_SM_INFAULT; |
2222 | instance->instancet->disable_intr(instance->reg_set); | 2244 | instance->instancet->disable_intr(instance); |
2223 | msleep(1000); | 2245 | msleep(1000); |
2224 | 2246 | ||
2225 | /* First try waiting for commands to complete */ | 2247 | /* First try waiting for commands to complete */ |
@@ -2343,7 +2365,7 @@ int megasas_reset_fusion(struct Scsi_Host *shost) | |||
2343 | 2365 | ||
2344 | clear_bit(MEGASAS_FUSION_IN_RESET, | 2366 | clear_bit(MEGASAS_FUSION_IN_RESET, |
2345 | &instance->reset_flags); | 2367 | &instance->reset_flags); |
2346 | instance->instancet->enable_intr(instance->reg_set); | 2368 | instance->instancet->enable_intr(instance); |
2347 | instance->adprecovery = MEGASAS_HBA_OPERATIONAL; | 2369 | instance->adprecovery = MEGASAS_HBA_OPERATIONAL; |
2348 | 2370 | ||
2349 | /* Re-fire management commands */ | 2371 | /* Re-fire management commands */ |
@@ -2405,7 +2427,7 @@ int megasas_reset_fusion(struct Scsi_Host *shost) | |||
2405 | retval = FAILED; | 2427 | retval = FAILED; |
2406 | } else { | 2428 | } else { |
2407 | clear_bit(MEGASAS_FUSION_IN_RESET, &instance->reset_flags); | 2429 | clear_bit(MEGASAS_FUSION_IN_RESET, &instance->reset_flags); |
2408 | instance->instancet->enable_intr(instance->reg_set); | 2430 | instance->instancet->enable_intr(instance); |
2409 | instance->adprecovery = MEGASAS_HBA_OPERATIONAL; | 2431 | instance->adprecovery = MEGASAS_HBA_OPERATIONAL; |
2410 | } | 2432 | } |
2411 | out: | 2433 | out: |
diff --git a/drivers/scsi/megaraid/megaraid_sas_fusion.h b/drivers/scsi/megaraid/megaraid_sas_fusion.h index f68a3cd11d5d..004c18e408c1 100644 --- a/drivers/scsi/megaraid/megaraid_sas_fusion.h +++ b/drivers/scsi/megaraid/megaraid_sas_fusion.h | |||
@@ -43,7 +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 | #define MAX_MSIX_QUEUES_FUSION 128 |
47 | 47 | ||
48 | /* Invader defines */ | 48 | /* Invader defines */ |
49 | #define MPI2_TYPE_CUDA 0x2 | 49 | #define MPI2_TYPE_CUDA 0x2 |
@@ -62,6 +62,9 @@ | |||
62 | #define MEGASAS_RD_WR_PROTECT_CHECK_ALL 0x20 | 62 | #define MEGASAS_RD_WR_PROTECT_CHECK_ALL 0x20 |
63 | #define MEGASAS_RD_WR_PROTECT_CHECK_NONE 0x60 | 63 | #define MEGASAS_RD_WR_PROTECT_CHECK_NONE 0x60 |
64 | 64 | ||
65 | #define MPI2_SUP_REPLY_POST_HOST_INDEX_OFFSET (0x0000030C) | ||
66 | #define MPI2_REPLY_POST_HOST_INDEX_OFFSET (0x0000006C) | ||
67 | |||
65 | /* | 68 | /* |
66 | * Raid context flags | 69 | * Raid context flags |
67 | */ | 70 | */ |