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 *);
......
This diff is collapsed.
...@@ -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