summaryrefslogtreecommitdiffstats
path: root/drivers/scsi/megaraid/megaraid_sas_base.c
diff options
context:
space:
mode:
authorSumit.Saxena@lsi.com2013-05-22 09:04:14 +0200
committerJames Bottomley2013-06-25 02:46:31 +0200
commitd46a3ad679c7232b72b21c6d0ca047dc4a68063f (patch)
treecae11de87870963d335838e24b01814081e0cbf8 /drivers/scsi/megaraid/megaraid_sas_base.c
parent[SCSI] megaraid_sas: Set IoFlags to enable Fast Path for JBODs for 12 Gb/s co... (diff)
downloadkernel-qcow2-linux-d46a3ad679c7232b72b21c6d0ca047dc4a68063f.tar.gz
kernel-qcow2-linux-d46a3ad679c7232b72b21c6d0ca047dc4a68063f.tar.xz
kernel-qcow2-linux-d46a3ad679c7232b72b21c6d0ca047dc4a68063f.zip
[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/megaraid_sas_base.c')
-rw-r--r--drivers/scsi/megaraid/megaraid_sas_base.c111
1 files changed, 82 insertions, 29 deletions
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)
* @regs: MFI register set
*/
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);
/* Dummy readl to force pci flush */
@@ -257,9 +259,11 @@ megasas_enable_intr_xscale(struct megasas_register_set __iomem * regs)
* @regs: MFI register set
*/
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;
+ regs = instance->reg_set;
writel(mask, &regs->outbound_intr_mask);
/* Dummy readl to force pci flush */
readl(&regs->outbound_intr_mask);
@@ -413,8 +417,10 @@ static struct megasas_instance_template megasas_instance_template_xscale = {
* @regs: MFI register set
*/
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(~0x80000000, &(regs)->outbound_intr_mask);
@@ -428,9 +434,11 @@ megasas_enable_intr_ppc(struct megasas_register_set __iomem * regs)
* @regs: MFI register set
*/
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;
+ regs = instance->reg_set;
writel(mask, &regs->outbound_intr_mask);
/* Dummy readl to force pci flush */
readl(&regs->outbound_intr_mask);
@@ -531,8 +539,10 @@ static struct megasas_instance_template megasas_instance_template_ppc = {
* @regs: MFI register set
*/
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(~MFI_SKINNY_ENABLE_INTERRUPT_MASK, &(regs)->outbound_intr_mask);
@@ -546,9 +556,11 @@ megasas_enable_intr_skinny(struct megasas_register_set __iomem *regs)
* @regs: MFI register set
*/
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;
+ regs = instance->reg_set;
writel(mask, &regs->outbound_intr_mask);
/* Dummy readl to force pci flush */
readl(&regs->outbound_intr_mask);
@@ -666,8 +678,10 @@ static struct megasas_instance_template megasas_instance_template_skinny = {
* @regs: MFI register set
*/
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);
/* write ~0x00000005 (4 & 1) to the intr mask*/
@@ -682,9 +696,11 @@ megasas_enable_intr_gen2(struct megasas_register_set __iomem *regs)
* @regs: MFI register set
*/
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;
+ regs = instance->reg_set;
writel(mask, &regs->outbound_intr_mask);
/* Dummy readl to force pci flush */
readl(&regs->outbound_intr_mask);
@@ -1707,7 +1723,7 @@ void megasas_do_ocr(struct megasas_instance *instance)
(instance->pdev->device == PCI_DEVICE_ID_LSI_VERDE_ZCR)) {
*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->issuepend_done = 0;
@@ -2490,7 +2506,7 @@ process_fw_state_change_wq(struct work_struct *work)
printk(KERN_NOTICE "megaraid_sas: FW detected to be in fault"
"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_reset_no_pci_access, 1);
@@ -2531,7 +2547,7 @@ process_fw_state_change_wq(struct work_struct *work)
spin_lock_irqsave(&instance->hba_lock, flags);
instance->adprecovery = MEGASAS_HBA_OPERATIONAL;
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);
instance->issuepend_done = 1;
@@ -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->issuepend_done = 0;
@@ -2728,7 +2744,7 @@ megasas_transition_to_ready(struct megasas_instance *instance, int ocr)
/*
* 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 ==
PCI_DEVICE_ID_LSI_SAS0073SKINNY) ||
(instance->pdev->device ==
@@ -3374,7 +3390,7 @@ megasas_issue_init_mfi(struct megasas_instance *instance)
/*
* 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
@@ -3481,11 +3497,11 @@ static int megasas_init_fw(struct megasas_instance *instance)
{
u32 max_sectors_1;
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_ctrl_info *ctrl_info;
unsigned long bar_list;
- int i;
+ int i, loop, fw_msix_count = 0;
/* Find first memory bar */
bar_list = pci_select_bars(instance->pdev, IORESOURCE_MEM);
@@ -3537,21 +3553,49 @@ static int megasas_init_fw(struct megasas_instance *instance)
if (megasas_transition_to_ready(instance, 0))
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 */
msix_enable = (instance->instancet->read_fw_status_reg(reg_set) &
0x4000000) >> 0x1a;
if (msix_enable && !msix_disable) {
+ scratch_pad_2 = readl
+ (&instance->reg_set->outbound_scratch_pad_2);
/* Check max MSI-X vectors */
- if ((instance->pdev->device == PCI_DEVICE_ID_LSI_FUSION) ||
- (instance->pdev->device == PCI_DEVICE_ID_LSI_INVADER) ||
- (instance->pdev->device == PCI_DEVICE_ID_LSI_FURY)) {
- instance->msix_vectors = (readl(&instance->reg_set->
- outbound_scratch_pad_2
- ) & 0x1F) + 1;
+ if (instance->pdev->device == PCI_DEVICE_ID_LSI_FUSION) {
+ instance->msix_vectors = (scratch_pad_2
+ & MR_MAX_REPLY_QUEUES_OFFSET) + 1;
+ fw_msix_count = instance->msix_vectors;
if (msix_vectors)
instance->msix_vectors =
min(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
instance->msix_vectors = 1;
/* Don't bother allocating more MSI-X vectors than cpus */
@@ -3571,6 +3615,12 @@ static int megasas_init_fw(struct megasas_instance *instance)
}
} else
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 */
@@ -4166,6 +4216,7 @@ static int megasas_probe_one(struct pci_dev *pdev,
if (megasas_init_fw(instance))
goto fail_init_mfi;
+retry_irq_register:
/*
* Register IRQ
*/
@@ -4183,7 +4234,9 @@ static int megasas_probe_one(struct pci_dev *pdev,
free_irq(
instance->msixentry[j].vector,
&instance->irq_context[j]);
- goto fail_irq;
+ /* Retry irq register for IO_APIC */
+ instance->msix_vectors = 0;
+ goto retry_irq_register;
}
}
} else {
@@ -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
@@ -4237,7 +4290,7 @@ static int megasas_probe_one(struct pci_dev *pdev,
megasas_mgmt_info.max_index--;
pci_set_drvdata(pdev, NULL);
- instance->instancet->disable_intr(instance->reg_set);
+ instance->instancet->disable_intr(instance);
if (instance->msix_vectors)
for (i = 0 ; i < instance->msix_vectors; i++)
free_irq(instance->msixentry[i].vector,
@@ -4387,7 +4440,7 @@ megasas_suspend(struct pci_dev *pdev, pm_message_t state)
tasklet_kill(&instance->isr_tasklet);
pci_set_drvdata(instance->pdev, instance);
- instance->instancet->disable_intr(instance->reg_set);
+ instance->instancet->disable_intr(instance);
if (instance->msix_vectors)
for (i = 0 ; i < instance->msix_vectors; i++)
@@ -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;
/*
@@ -4594,7 +4647,7 @@ static void megasas_detach_one(struct pci_dev *pdev)
pci_set_drvdata(instance->pdev, NULL);
- instance->instancet->disable_intr(instance->reg_set);
+ instance->instancet->disable_intr(instance);
if (instance->msix_vectors)
for (i = 0 ; i < instance->msix_vectors; i++)
@@ -4654,7 +4707,7 @@ static void megasas_shutdown(struct pci_dev *pdev)
instance->unload = 1;
megasas_flush_cache(instance);
megasas_shutdown_controller(instance, MR_DCMD_CTRL_SHUTDOWN);
- instance->instancet->disable_intr(instance->reg_set);
+ instance->instancet->disable_intr(instance);
if (instance->msix_vectors)
for (i = 0 ; i < instance->msix_vectors; i++)
free_irq(instance->msixentry[i].vector,