Commit d46a3ad6 authored by Sumit.Saxena@lsi.com's avatar Sumit.Saxena@lsi.com Committed by James Bottomley

[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: default avatarSumit Saxena <sumit.saxena@lsi.com>
Signed-off-by: default avatarKashyap Desai <kashyap.desai@lsi.com>
Signed-off-by: default avatarJames Bottomley <JBottomley@Parallels.com>
parent 5d0d908d
...@@ -786,7 +786,7 @@ struct megasas_ctrl_info { ...@@ -786,7 +786,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 #define MEGASAS_MAX_MSIX_QUEUES 128
/* /*
* 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
...@@ -811,6 +811,11 @@ struct megasas_ctrl_info { ...@@ -811,6 +811,11 @@ struct megasas_ctrl_info {
#define MFI_1068_PCSR_OFFSET 0x84 #define MFI_1068_PCSR_OFFSET 0x84
#define MFI_1068_FW_HANDSHAKE_OFFSET 0x64 #define MFI_1068_FW_HANDSHAKE_OFFSET 0x64
#define MFI_1068_FW_READY 0xDDDD0000 #define MFI_1068_FW_READY 0xDDDD0000
#define MR_MAX_REPLY_QUEUES_OFFSET 0X0000001F
#define MR_MAX_REPLY_QUEUES_EXT_OFFSET 0X003FC000
#define MR_MAX_REPLY_QUEUES_EXT_OFFSET_SHIFT 14
#define MR_MAX_MSIX_REG_ARRAY 16
/* /*
* register set for both 1068 and 1078 controllers * register set for both 1068 and 1078 controllers
* structure extended for 1078 registers * structure extended for 1078 registers
...@@ -920,6 +925,15 @@ union megasas_sgl_frame { ...@@ -920,6 +925,15 @@ union megasas_sgl_frame {
} __attribute__ ((packed)); } __attribute__ ((packed));
typedef union _MFI_CAPABILITIES {
struct {
u32 support_fp_remote_lun:1;
u32 support_additional_msix:1;
u32 reserved:30;
} mfi_capabilities;
u32 reg;
} MFI_CAPABILITIES;
struct megasas_init_frame { struct megasas_init_frame {
u8 cmd; /*00h */ u8 cmd; /*00h */
...@@ -927,7 +941,7 @@ struct megasas_init_frame { ...@@ -927,7 +941,7 @@ struct megasas_init_frame {
u8 cmd_status; /*02h */ u8 cmd_status; /*02h */
u8 reserved_1; /*03h */ u8 reserved_1; /*03h */
u32 reserved_2; /*04h */ MFI_CAPABILITIES driver_operations; /*04h*/
u32 context; /*08h */ u32 context; /*08h */
u32 pad_0; /*0Ch */ u32 pad_0; /*0Ch */
...@@ -1324,7 +1338,7 @@ struct megasas_instance { ...@@ -1324,7 +1338,7 @@ struct megasas_instance {
unsigned long base_addr; unsigned long base_addr;
struct megasas_register_set __iomem *reg_set; struct megasas_register_set __iomem *reg_set;
u32 *reply_post_host_index_addr[MR_MAX_MSIX_REG_ARRAY];
struct megasas_pd_list pd_list[MEGASAS_MAX_PD]; struct megasas_pd_list pd_list[MEGASAS_MAX_PD];
u8 ld_ids[MEGASAS_MAX_LD_IDS]; u8 ld_ids[MEGASAS_MAX_LD_IDS];
s8 init_id; s8 init_id;
...@@ -1393,6 +1407,7 @@ struct megasas_instance { ...@@ -1393,6 +1407,7 @@ struct megasas_instance {
long reset_flags; long reset_flags;
struct mutex reset_mutex; struct mutex reset_mutex;
int throttlequeuedepth; int throttlequeuedepth;
u8 mask_interrupts;
}; };
enum { enum {
...@@ -1408,8 +1423,8 @@ struct megasas_instance_template { ...@@ -1408,8 +1423,8 @@ struct megasas_instance_template {
void (*fire_cmd)(struct megasas_instance *, dma_addr_t, \ void (*fire_cmd)(struct megasas_instance *, dma_addr_t, \
u32, struct megasas_register_set __iomem *); u32, struct megasas_register_set __iomem *);
void (*enable_intr)(struct megasas_register_set __iomem *) ; void (*enable_intr)(struct megasas_instance *);
void (*disable_intr)(struct megasas_register_set __iomem *); void (*disable_intr)(struct megasas_instance *);
int (*clear_intr)(struct megasas_register_set __iomem *); int (*clear_intr)(struct megasas_register_set __iomem *);
......
...@@ -244,8 +244,10 @@ megasas_return_cmd(struct megasas_instance *instance, struct megasas_cmd *cmd) ...@@ -244,8 +244,10 @@ megasas_return_cmd(struct megasas_instance *instance, struct megasas_cmd *cmd)
* @regs: MFI register set * @regs: MFI register set
*/ */
static inline void static inline void
megasas_enable_intr_xscale(struct megasas_register_set __iomem * regs) megasas_enable_intr_xscale(struct megasas_instance *instance)
{ {
struct megasas_register_set __iomem *regs;
regs = instance->reg_set;
writel(0, &(regs)->outbound_intr_mask); writel(0, &(regs)->outbound_intr_mask);
/* Dummy readl to force pci flush */ /* Dummy readl to force pci flush */
...@@ -257,9 +259,11 @@ megasas_enable_intr_xscale(struct megasas_register_set __iomem * regs) ...@@ -257,9 +259,11 @@ megasas_enable_intr_xscale(struct megasas_register_set __iomem * regs)
* @regs: MFI register set * @regs: MFI register set
*/ */
static inline void static inline void
megasas_disable_intr_xscale(struct megasas_register_set __iomem * regs) megasas_disable_intr_xscale(struct megasas_instance *instance)
{ {
struct megasas_register_set __iomem *regs;
u32 mask = 0x1f; u32 mask = 0x1f;
regs = instance->reg_set;
writel(mask, &regs->outbound_intr_mask); writel(mask, &regs->outbound_intr_mask);
/* Dummy readl to force pci flush */ /* Dummy readl to force pci flush */
readl(&regs->outbound_intr_mask); readl(&regs->outbound_intr_mask);
...@@ -413,8 +417,10 @@ static struct megasas_instance_template megasas_instance_template_xscale = { ...@@ -413,8 +417,10 @@ static struct megasas_instance_template megasas_instance_template_xscale = {
* @regs: MFI register set * @regs: MFI register set
*/ */
static inline void static inline void
megasas_enable_intr_ppc(struct megasas_register_set __iomem * regs) megasas_enable_intr_ppc(struct megasas_instance *instance)
{ {
struct megasas_register_set __iomem *regs;
regs = instance->reg_set;
writel(0xFFFFFFFF, &(regs)->outbound_doorbell_clear); writel(0xFFFFFFFF, &(regs)->outbound_doorbell_clear);
writel(~0x80000000, &(regs)->outbound_intr_mask); writel(~0x80000000, &(regs)->outbound_intr_mask);
...@@ -428,9 +434,11 @@ megasas_enable_intr_ppc(struct megasas_register_set __iomem * regs) ...@@ -428,9 +434,11 @@ megasas_enable_intr_ppc(struct megasas_register_set __iomem * regs)
* @regs: MFI register set * @regs: MFI register set
*/ */
static inline void static inline void
megasas_disable_intr_ppc(struct megasas_register_set __iomem * regs) megasas_disable_intr_ppc(struct megasas_instance *instance)
{ {
struct megasas_register_set __iomem *regs;
u32 mask = 0xFFFFFFFF; u32 mask = 0xFFFFFFFF;
regs = instance->reg_set;
writel(mask, &regs->outbound_intr_mask); writel(mask, &regs->outbound_intr_mask);
/* Dummy readl to force pci flush */ /* Dummy readl to force pci flush */
readl(&regs->outbound_intr_mask); readl(&regs->outbound_intr_mask);
...@@ -531,8 +539,10 @@ static struct megasas_instance_template megasas_instance_template_ppc = { ...@@ -531,8 +539,10 @@ static struct megasas_instance_template megasas_instance_template_ppc = {
* @regs: MFI register set * @regs: MFI register set
*/ */
static inline void static inline void
megasas_enable_intr_skinny(struct megasas_register_set __iomem *regs) megasas_enable_intr_skinny(struct megasas_instance *instance)
{ {
struct megasas_register_set __iomem *regs;
regs = instance->reg_set;
writel(0xFFFFFFFF, &(regs)->outbound_intr_mask); writel(0xFFFFFFFF, &(regs)->outbound_intr_mask);
writel(~MFI_SKINNY_ENABLE_INTERRUPT_MASK, &(regs)->outbound_intr_mask); 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,9 +556,11 @@ megasas_enable_intr_skinny(struct megasas_register_set __iomem *regs)
* @regs: MFI register set * @regs: MFI register set
*/ */
static inline void static inline void
megasas_disable_intr_skinny(struct megasas_register_set __iomem *regs) megasas_disable_intr_skinny(struct megasas_instance *instance)
{ {
struct megasas_register_set __iomem *regs;
u32 mask = 0xFFFFFFFF; u32 mask = 0xFFFFFFFF;
regs = instance->reg_set;
writel(mask, &regs->outbound_intr_mask); writel(mask, &regs->outbound_intr_mask);
/* Dummy readl to force pci flush */ /* Dummy readl to force pci flush */
readl(&regs->outbound_intr_mask); readl(&regs->outbound_intr_mask);
...@@ -666,8 +678,10 @@ static struct megasas_instance_template megasas_instance_template_skinny = { ...@@ -666,8 +678,10 @@ static struct megasas_instance_template megasas_instance_template_skinny = {
* @regs: MFI register set * @regs: MFI register set
*/ */
static inline void static inline void
megasas_enable_intr_gen2(struct megasas_register_set __iomem *regs) megasas_enable_intr_gen2(struct megasas_instance *instance)
{ {
struct megasas_register_set __iomem *regs;
regs = instance->reg_set;
writel(0xFFFFFFFF, &(regs)->outbound_doorbell_clear); writel(0xFFFFFFFF, &(regs)->outbound_doorbell_clear);
/* write ~0x00000005 (4 & 1) to the intr mask*/ /* write ~0x00000005 (4 & 1) to the intr mask*/
...@@ -682,9 +696,11 @@ megasas_enable_intr_gen2(struct megasas_register_set __iomem *regs) ...@@ -682,9 +696,11 @@ megasas_enable_intr_gen2(struct megasas_register_set __iomem *regs)
* @regs: MFI register set * @regs: MFI register set
*/ */
static inline void static inline void
megasas_disable_intr_gen2(struct megasas_register_set __iomem *regs) megasas_disable_intr_gen2(struct megasas_instance *instance)
{ {
struct megasas_register_set __iomem *regs;
u32 mask = 0xFFFFFFFF; u32 mask = 0xFFFFFFFF;
regs = instance->reg_set;
writel(mask, &regs->outbound_intr_mask); writel(mask, &regs->outbound_intr_mask);
/* Dummy readl to force pci flush */ /* Dummy readl to force pci flush */
readl(&regs->outbound_intr_mask); readl(&regs->outbound_intr_mask);
...@@ -1707,7 +1723,7 @@ void megasas_do_ocr(struct megasas_instance *instance) ...@@ -1707,7 +1723,7 @@ void megasas_do_ocr(struct megasas_instance *instance)
(instance->pdev->device == PCI_DEVICE_ID_LSI_VERDE_ZCR)) { (instance->pdev->device == PCI_DEVICE_ID_LSI_VERDE_ZCR)) {
*instance->consumer = MEGASAS_ADPRESET_INPROG_SIGN; *instance->consumer = MEGASAS_ADPRESET_INPROG_SIGN;
} }
instance->instancet->disable_intr(instance->reg_set); instance->instancet->disable_intr(instance);
instance->adprecovery = MEGASAS_ADPRESET_SM_INFAULT; instance->adprecovery = MEGASAS_ADPRESET_SM_INFAULT;
instance->issuepend_done = 0; instance->issuepend_done = 0;
...@@ -2490,7 +2506,7 @@ process_fw_state_change_wq(struct work_struct *work) ...@@ -2490,7 +2506,7 @@ process_fw_state_change_wq(struct work_struct *work)
printk(KERN_NOTICE "megaraid_sas: FW detected to be in fault" printk(KERN_NOTICE "megaraid_sas: FW detected to be in fault"
"state, restarting it...\n"); "state, restarting it...\n");
instance->instancet->disable_intr(instance->reg_set); instance->instancet->disable_intr(instance);
atomic_set(&instance->fw_outstanding, 0); atomic_set(&instance->fw_outstanding, 0);
atomic_set(&instance->fw_reset_no_pci_access, 1); atomic_set(&instance->fw_reset_no_pci_access, 1);
...@@ -2531,7 +2547,7 @@ process_fw_state_change_wq(struct work_struct *work) ...@@ -2531,7 +2547,7 @@ process_fw_state_change_wq(struct work_struct *work)
spin_lock_irqsave(&instance->hba_lock, flags); spin_lock_irqsave(&instance->hba_lock, flags);
instance->adprecovery = MEGASAS_HBA_OPERATIONAL; instance->adprecovery = MEGASAS_HBA_OPERATIONAL;
spin_unlock_irqrestore(&instance->hba_lock, flags); spin_unlock_irqrestore(&instance->hba_lock, flags);
instance->instancet->enable_intr(instance->reg_set); instance->instancet->enable_intr(instance);
megasas_issue_pending_cmds_again(instance); megasas_issue_pending_cmds_again(instance);
instance->issuepend_done = 1; instance->issuepend_done = 1;
...@@ -2594,7 +2610,7 @@ megasas_deplete_reply_queue(struct megasas_instance *instance, ...@@ -2594,7 +2610,7 @@ megasas_deplete_reply_queue(struct megasas_instance *instance,
} }
instance->instancet->disable_intr(instance->reg_set); instance->instancet->disable_intr(instance);
instance->adprecovery = MEGASAS_ADPRESET_SM_INFAULT; instance->adprecovery = MEGASAS_ADPRESET_SM_INFAULT;
instance->issuepend_done = 0; instance->issuepend_done = 0;
...@@ -2728,7 +2744,7 @@ megasas_transition_to_ready(struct megasas_instance *instance, int ocr) ...@@ -2728,7 +2744,7 @@ megasas_transition_to_ready(struct megasas_instance *instance, int ocr)
/* /*
* Bring it to READY state; assuming max wait 10 secs * Bring it to READY state; assuming max wait 10 secs
*/ */
instance->instancet->disable_intr(instance->reg_set); instance->instancet->disable_intr(instance);
if ((instance->pdev->device == if ((instance->pdev->device ==
PCI_DEVICE_ID_LSI_SAS0073SKINNY) || PCI_DEVICE_ID_LSI_SAS0073SKINNY) ||
(instance->pdev->device == (instance->pdev->device ==
...@@ -3374,7 +3390,7 @@ megasas_issue_init_mfi(struct megasas_instance *instance) ...@@ -3374,7 +3390,7 @@ megasas_issue_init_mfi(struct megasas_instance *instance)
/* /*
* disable the intr before firing the init frame to FW * disable the intr before firing the init frame to FW
*/ */
instance->instancet->disable_intr(instance->reg_set); instance->instancet->disable_intr(instance);
/* /*
* Issue the init frame in polled mode * Issue the init frame in polled mode
...@@ -3481,11 +3497,11 @@ static int megasas_init_fw(struct megasas_instance *instance) ...@@ -3481,11 +3497,11 @@ static int megasas_init_fw(struct megasas_instance *instance)
{ {
u32 max_sectors_1; u32 max_sectors_1;
u32 max_sectors_2; u32 max_sectors_2;
u32 tmp_sectors, msix_enable; u32 tmp_sectors, msix_enable, scratch_pad_2;
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; int i, loop, fw_msix_count = 0;
/* 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);
...@@ -3537,21 +3553,49 @@ static int megasas_init_fw(struct megasas_instance *instance) ...@@ -3537,21 +3553,49 @@ static int megasas_init_fw(struct megasas_instance *instance)
if (megasas_transition_to_ready(instance, 0)) if (megasas_transition_to_ready(instance, 0))
goto fail_ready_state; goto fail_ready_state;
/*
* MSI-X host index 0 is common for all adapter.
* It is used for all MPT based Adapters.
*/
instance->reply_post_host_index_addr[0] =
(u32 *)((u8 *)instance->reg_set +
MPI2_REPLY_POST_HOST_INDEX_OFFSET);
/* 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) {
scratch_pad_2 = readl
(&instance->reg_set->outbound_scratch_pad_2);
/* Check max MSI-X vectors */ /* Check max MSI-X vectors */
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->msix_vectors = (scratch_pad_2
(instance->pdev->device == PCI_DEVICE_ID_LSI_FURY)) { & MR_MAX_REPLY_QUEUES_OFFSET) + 1;
instance->msix_vectors = (readl(&instance->reg_set-> fw_msix_count = instance->msix_vectors;
outbound_scratch_pad_2
) & 0x1F) + 1;
if (msix_vectors) if (msix_vectors)
instance->msix_vectors = instance->msix_vectors =
min(msix_vectors, min(msix_vectors,
instance->msix_vectors); instance->msix_vectors);
} else if ((instance->pdev->device == PCI_DEVICE_ID_LSI_INVADER)
|| (instance->pdev->device == PCI_DEVICE_ID_LSI_FURY)) {
/* Invader/Fury supports more than 8 MSI-X */
instance->msix_vectors = ((scratch_pad_2
& MR_MAX_REPLY_QUEUES_EXT_OFFSET)
>> MR_MAX_REPLY_QUEUES_EXT_OFFSET_SHIFT) + 1;
fw_msix_count = instance->msix_vectors;
/* Save 1-15 reply post index address to local memory
* Index 0 is already saved from reg offset
* MPI2_REPLY_POST_HOST_INDEX_OFFSET
*/
for (loop = 1; loop < MR_MAX_MSIX_REG_ARRAY; loop++) {
instance->reply_post_host_index_addr[loop] =
(u32 *)((u8 *)instance->reg_set +
MPI2_SUP_REPLY_POST_HOST_INDEX_OFFSET
+ (loop * 0x10));
}
if (msix_vectors)
instance->msix_vectors = min(msix_vectors,
instance->msix_vectors);
} else } else
instance->msix_vectors = 1; instance->msix_vectors = 1;
/* Don't bother allocating more MSI-X vectors than cpus */ /* Don't bother allocating more MSI-X vectors than cpus */
...@@ -3571,6 +3615,12 @@ static int megasas_init_fw(struct megasas_instance *instance) ...@@ -3571,6 +3615,12 @@ static int megasas_init_fw(struct megasas_instance *instance)
} }
} else } else
instance->msix_vectors = 0; instance->msix_vectors = 0;
dev_info(&instance->pdev->dev, "[scsi%d]: FW supports"
"<%d> MSIX vector,Online CPUs: <%d>,"
"Current MSIX <%d>\n", instance->host->host_no,
fw_msix_count, (unsigned int)num_online_cpus(),
instance->msix_vectors);
} }
/* Get operational params, sge flags, send init cmd to controller */ /* Get operational params, sge flags, send init cmd to controller */
...@@ -4166,6 +4216,7 @@ static int megasas_probe_one(struct pci_dev *pdev, ...@@ -4166,6 +4216,7 @@ static int megasas_probe_one(struct pci_dev *pdev,
if (megasas_init_fw(instance)) if (megasas_init_fw(instance))
goto fail_init_mfi; goto fail_init_mfi;
retry_irq_register:
/* /*
* Register IRQ * Register IRQ
*/ */
...@@ -4183,7 +4234,9 @@ static int megasas_probe_one(struct pci_dev *pdev, ...@@ -4183,7 +4234,9 @@ static int megasas_probe_one(struct pci_dev *pdev,
free_irq( free_irq(
instance->msixentry[j].vector, instance->msixentry[j].vector,
&instance->irq_context[j]); &instance->irq_context[j]);
goto fail_irq; /* Retry irq register for IO_APIC */
instance->msix_vectors = 0;
goto retry_irq_register;
} }
} }
} else { } else {
...@@ -4197,7 +4250,7 @@ static int megasas_probe_one(struct pci_dev *pdev, ...@@ -4197,7 +4250,7 @@ static int megasas_probe_one(struct pci_dev *pdev,
} }
} }
instance->instancet->enable_intr(instance->reg_set); instance->instancet->enable_intr(instance);
/* /*
* Store instance in PCI softstate * Store instance in PCI softstate
...@@ -4237,7 +4290,7 @@ static int megasas_probe_one(struct pci_dev *pdev, ...@@ -4237,7 +4290,7 @@ static int megasas_probe_one(struct pci_dev *pdev,
megasas_mgmt_info.max_index--; megasas_mgmt_info.max_index--;
pci_set_drvdata(pdev, NULL); pci_set_drvdata(pdev, NULL);
instance->instancet->disable_intr(instance->reg_set); instance->instancet->disable_intr(instance);
if (instance->msix_vectors) if (instance->msix_vectors)
for (i = 0 ; i < instance->msix_vectors; i++) for (i = 0 ; i < instance->msix_vectors; i++)
free_irq(instance->msixentry[i].vector, free_irq(instance->msixentry[i].vector,
...@@ -4387,7 +4440,7 @@ megasas_suspend(struct pci_dev *pdev, pm_message_t state) ...@@ -4387,7 +4440,7 @@ megasas_suspend(struct pci_dev *pdev, pm_message_t state)
tasklet_kill(&instance->isr_tasklet); tasklet_kill(&instance->isr_tasklet);
pci_set_drvdata(instance->pdev, instance); pci_set_drvdata(instance->pdev, instance);
instance->instancet->disable_intr(instance->reg_set); instance->instancet->disable_intr(instance);
if (instance->msix_vectors) if (instance->msix_vectors)
for (i = 0 ; i < instance->msix_vectors; i++) for (i = 0 ; i < instance->msix_vectors; i++)
...@@ -4512,7 +4565,7 @@ megasas_resume(struct pci_dev *pdev) ...@@ -4512,7 +4565,7 @@ megasas_resume(struct pci_dev *pdev)
} }
} }
instance->instancet->enable_intr(instance->reg_set); instance->instancet->enable_intr(instance);
instance->unload = 0; instance->unload = 0;
/* /*
...@@ -4594,7 +4647,7 @@ static void megasas_detach_one(struct pci_dev *pdev) ...@@ -4594,7 +4647,7 @@ static void megasas_detach_one(struct pci_dev *pdev)
pci_set_drvdata(instance->pdev, NULL); pci_set_drvdata(instance->pdev, NULL);
instance->instancet->disable_intr(instance->reg_set); instance->instancet->disable_intr(instance);
if (instance->msix_vectors) if (instance->msix_vectors)
for (i = 0 ; i < instance->msix_vectors; i++) for (i = 0 ; i < instance->msix_vectors; i++)
...@@ -4654,7 +4707,7 @@ static void megasas_shutdown(struct pci_dev *pdev) ...@@ -4654,7 +4707,7 @@ static void megasas_shutdown(struct pci_dev *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);
if (instance->msix_vectors) if (instance->msix_vectors)
for (i = 0 ; i < instance->msix_vectors; i++) for (i = 0 ; i < instance->msix_vectors; i++)
free_irq(instance->msixentry[i].vector, free_irq(instance->msixentry[i].vector,
......
...@@ -101,8 +101,10 @@ extern int resetwaittime; ...@@ -101,8 +101,10 @@ extern int resetwaittime;
* @regs: MFI register set * @regs: MFI register set
*/ */
void void
megasas_enable_intr_fusion(struct megasas_register_set __iomem *regs) megasas_enable_intr_fusion(struct megasas_instance *instance)
{ {
struct megasas_register_set __iomem *regs;
regs = instance->reg_set;
/* For Thunderbolt/Invader also clear intr on enable */ /* For Thunderbolt/Invader also clear intr on enable */
writel(~0, &regs->outbound_intr_status); writel(~0, &regs->outbound_intr_status);
readl(&regs->outbound_intr_status); readl(&regs->outbound_intr_status);
...@@ -111,6 +113,7 @@ megasas_enable_intr_fusion(struct megasas_register_set __iomem *regs) ...@@ -111,6 +113,7 @@ megasas_enable_intr_fusion(struct megasas_register_set __iomem *regs)
/* Dummy readl to force pci flush */ /* Dummy readl to force pci flush */
readl(&regs->outbound_intr_mask); readl(&regs->outbound_intr_mask);
instance->mask_interrupts = 0;
} }
/** /**
...@@ -118,10 +121,13 @@ megasas_enable_intr_fusion(struct megasas_register_set __iomem *regs) ...@@ -118,10 +121,13 @@ megasas_enable_intr_fusion(struct megasas_register_set __iomem *regs)
* @regs: MFI register set * @regs: MFI register set
*/ */
void void
megasas_disable_intr_fusion(struct megasas_register_set __iomem *regs) megasas_disable_intr_fusion(struct megasas_instance *instance)
{ {
u32 mask = 0xFFFFFFFF; u32 mask = 0xFFFFFFFF;
u32 status; u32 status;
struct megasas_register_set __iomem *regs;
regs = instance->reg_set;
instance->mask_interrupts = 1;
writel(mask, &regs->outbound_intr_mask); writel(mask, &regs->outbound_intr_mask);
/* Dummy readl to force pci flush */ /* Dummy readl to force pci flush */
...@@ -643,6 +649,12 @@ megasas_ioc_init_fusion(struct megasas_instance *instance) ...@@ -643,6 +649,12 @@ megasas_ioc_init_fusion(struct megasas_instance *instance)
init_frame->cmd = MFI_CMD_INIT; init_frame->cmd = MFI_CMD_INIT;
init_frame->cmd_status = 0xFF; init_frame->cmd_status = 0xFF;
/* driver support Extended MSIX */
if ((instance->pdev->device == PCI_DEVICE_ID_LSI_INVADER) ||
(instance->pdev->device == PCI_DEVICE_ID_LSI_FURY))
init_frame->driver_operations.
mfi_capabilities.support_additional_msix = 1;
init_frame->queue_info_new_phys_addr_lo = ioc_init_handle; init_frame->queue_info_new_phys_addr_lo = ioc_init_handle;
init_frame->data_xfer_len = sizeof(struct MPI2_IOC_INIT_REQUEST); init_frame->data_xfer_len = sizeof(struct MPI2_IOC_INIT_REQUEST);
...@@ -657,7 +669,7 @@ megasas_ioc_init_fusion(struct megasas_instance *instance) ...@@ -657,7 +669,7 @@ megasas_ioc_init_fusion(struct megasas_instance *instance)
/* /*
* disable the intr before firing the init frame * disable the intr before firing the init frame
*/ */
instance->instancet->disable_intr(instance->reg_set); instance->instancet->disable_intr(instance);
for (i = 0; i < (10 * 1000); i += 20) { for (i = 0; i < (10 * 1000); i += 20) {
if (readl(&instance->reg_set->doorbell) & 1) if (readl(&instance->reg_set->doorbell) & 1)
...@@ -1911,8 +1923,15 @@ complete_cmd_fusion(struct megasas_instance *instance, u32 MSIxIndex) ...@@ -1911,8 +1923,15 @@ complete_cmd_fusion(struct megasas_instance *instance, u32 MSIxIndex)
return IRQ_NONE; return IRQ_NONE;
wmb(); wmb();
writel((MSIxIndex << 24) | fusion->last_reply_idx[MSIxIndex], if ((instance->pdev->device == PCI_DEVICE_ID_LSI_INVADER) ||
&instance->reg_set->reply_post_host_index); (instance->pdev->device == PCI_DEVICE_ID_LSI_FURY))
writel(((MSIxIndex & 0x7) << 24) |
fusion->last_reply_idx[MSIxIndex],
instance->reply_post_host_index_addr[MSIxIndex/8]);
else
writel((MSIxIndex << 24) |
fusion->last_reply_idx[MSIxIndex],
instance->reply_post_host_index_addr[0]);
megasas_check_and_restore_queue_depth(instance); megasas_check_and_restore_queue_depth(instance);
return IRQ_HANDLED; return IRQ_HANDLED;
} }
...@@ -1954,6 +1973,9 @@ irqreturn_t megasas_isr_fusion(int irq, void *devp) ...@@ -1954,6 +1973,9 @@ irqreturn_t megasas_isr_fusion(int irq, void *devp)
struct megasas_instance *instance = irq_context->instance; struct megasas_instance *instance = irq_context->instance;
u32 mfiStatus, fw_state; u32 mfiStatus, fw_state;
if (instance->mask_interrupts)
return IRQ_NONE;
if (!instance->msix_vectors) { if (!instance->msix_vectors) {
mfiStatus = instance->instancet->clear_intr(instance->reg_set); mfiStatus = instance->instancet->clear_intr(instance->reg_set);
if (!mfiStatus) if (!mfiStatus)
...@@ -2219,7 +2241,7 @@ int megasas_reset_fusion(struct Scsi_Host *shost) ...@@ -2219,7 +2241,7 @@ int megasas_reset_fusion(struct Scsi_Host *shost)
mutex_lock(&instance->reset_mutex); mutex_lock(&instance->reset_mutex);
set_bit(MEGASAS_FUSION_IN_RESET, &instance->reset_flags); set_bit(MEGASAS_FUSION_IN_RESET, &instance->reset_flags);
instance->adprecovery = MEGASAS_ADPRESET_SM_INFAULT; instance->adprecovery = MEGASAS_ADPRESET_SM_INFAULT;
instance->instancet->disable_intr(instance->reg_set); instance->instancet->disable_intr(instance);
msleep(1000); msleep(1000);
/* First try waiting for commands to complete */ /* First try waiting for commands to complete */
...@@ -2343,7 +2365,7 @@ int megasas_reset_fusion(struct Scsi_Host *shost) ...@@ -2343,7 +2365,7 @@ int megasas_reset_fusion(struct Scsi_Host *shost)
clear_bit(MEGASAS_FUSION_IN_RESET, clear_bit(MEGASAS_FUSION_IN_RESET,
&instance->reset_flags); &instance->reset_flags);
instance->instancet->enable_intr(instance->reg_set); instance->instancet->enable_intr(instance);
instance->adprecovery = MEGASAS_HBA_OPERATIONAL; instance->adprecovery = MEGASAS_HBA_OPERATIONAL;
/* Re-fire management commands */ /* Re-fire management commands */
...@@ -2405,7 +2427,7 @@ int megasas_reset_fusion(struct Scsi_Host *shost) ...@@ -2405,7 +2427,7 @@ int megasas_reset_fusion(struct Scsi_Host *shost)
retval = FAILED; retval = FAILED;
} else { } else {
clear_bit(MEGASAS_FUSION_IN_RESET, &instance->reset_flags); clear_bit(MEGASAS_FUSION_IN_RESET, &instance->reset_flags);
instance->instancet->enable_intr(instance->reg_set); instance->instancet->enable_intr(instance);
instance->adprecovery = MEGASAS_HBA_OPERATIONAL; instance->adprecovery = MEGASAS_HBA_OPERATIONAL;
} }
out: out:
......
...@@ -43,7 +43,7 @@ ...@@ -43,7 +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 #define MAX_MSIX_QUEUES_FUSION 128
/* Invader defines */ /* Invader defines */
#define MPI2_TYPE_CUDA 0x2 #define MPI2_TYPE_CUDA 0x2
...@@ -62,6 +62,9 @@ ...@@ -62,6 +62,9 @@
#define MEGASAS_RD_WR_PROTECT_CHECK_ALL 0x20 #define MEGASAS_RD_WR_PROTECT_CHECK_ALL 0x20
#define MEGASAS_RD_WR_PROTECT_CHECK_NONE 0x60 #define MEGASAS_RD_WR_PROTECT_CHECK_NONE 0x60
#define MPI2_SUP_REPLY_POST_HOST_INDEX_OFFSET (0x0000030C)
#define MPI2_REPLY_POST_HOST_INDEX_OFFSET (0x0000006C)
/* /*
* Raid context flags * Raid context flags
*/ */
......
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