diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2013-07-04 12:30:30 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2013-07-04 12:30:30 -0700 |
commit | 84cbd7222b2b00dcddef3103203986b3d59c836a (patch) | |
tree | cdbe55ec410f853d4d532ed3252334cb110d5985 /drivers/scsi/megaraid/megaraid_sas_fusion.c | |
parent | 80cc38b16389849a6e06441ace4530f6b2497c3c (diff) | |
parent | a3fda7dd5179989dd0ead820dcebd13f956ddec1 (diff) | |
download | op-kernel-dev-84cbd7222b2b00dcddef3103203986b3d59c836a.zip op-kernel-dev-84cbd7222b2b00dcddef3103203986b3d59c836a.tar.gz |
Merge tag 'scsi-misc' of git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi
Pull first round of SCSI updates from James Bottomley:
"The patch set is mostly driver updates (usf, zfcp, lpfc, mpt2sas,
megaraid_sas, bfa, ipr) and a few bug fixes. Also of note is that the
Buslogic driver has been rewritten to a better coding style and 64 bit
support added. We also removed the libsas limitation on 16 bytes for
the command size (currently no drivers make use of this)"
* tag 'scsi-misc' of git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi: (101 commits)
[SCSI] megaraid: minor cut and paste error fixed.
[SCSI] ufshcd-pltfrm: remove unnecessary dma_set_coherent_mask() call
[SCSI] ufs: fix register address in UIC error interrupt handling
[SCSI] ufshcd-pltfrm: add missing empty slot in ufs_of_match[]
[SCSI] ufs: use devres functions for ufshcd
[SCSI] ufs: Fix the response UPIU length setting
[SCSI] ufs: rework link start-up process
[SCSI] ufs: remove version check before IS reg clear
[SCSI] ufs: amend interrupt configuration
[SCSI] ufs: wrap the i/o access operations
[SCSI] storvsc: Update the storage protocol to win8 level
[SCSI] storvsc: Increase the value of scsi timeout for storvsc devices
[SCSI] MAINTAINERS: Add myself as the maintainer for BusLogic SCSI driver
[SCSI] BusLogic: Port driver to 64-bit.
[SCSI] BusLogic: Fix style issues
[SCSI] libiscsi: Added new boot entries in the session sysfs
[SCSI] aacraid: Fix for arrays are going offline in the system. System hangs
[SCSI] ipr: IOA Status Code(IOASC) update
[SCSI] sd: Update WRITE SAME heuristics
[SCSI] fnic: potential dead lock in fnic_is_abts_pending()
...
Diffstat (limited to 'drivers/scsi/megaraid/megaraid_sas_fusion.c')
-rw-r--r-- | drivers/scsi/megaraid/megaraid_sas_fusion.c | 148 |
1 files changed, 127 insertions, 21 deletions
diff --git a/drivers/scsi/megaraid/megaraid_sas_fusion.c b/drivers/scsi/megaraid/megaraid_sas_fusion.c index a7d5668..417d5f1 100644 --- a/drivers/scsi/megaraid/megaraid_sas_fusion.c +++ b/drivers/scsi/megaraid/megaraid_sas_fusion.c @@ -86,8 +86,6 @@ u16 MR_GetLDTgtId(u32 ld, struct MR_FW_RAID_MAP_ALL *map); void megasas_check_and_restore_queue_depth(struct megasas_instance *instance); -u8 MR_ValidateMapInfo(struct MR_FW_RAID_MAP_ALL *map, - struct LD_LOAD_BALANCE_INFO *lbInfo); u16 get_updated_dev_handle(struct LD_LOAD_BALANCE_INFO *lbInfo, struct IO_REQUEST_INFO *in_info); int megasas_transition_to_ready(struct megasas_instance *instance, int ocr); @@ -101,8 +99,10 @@ extern int resetwaittime; * @regs: MFI register set */ 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 */ writel(~0, ®s->outbound_intr_status); readl(®s->outbound_intr_status); @@ -111,6 +111,7 @@ megasas_enable_intr_fusion(struct megasas_register_set __iomem *regs) /* Dummy readl to force pci flush */ readl(®s->outbound_intr_mask); + instance->mask_interrupts = 0; } /** @@ -118,10 +119,13 @@ megasas_enable_intr_fusion(struct megasas_register_set __iomem *regs) * @regs: MFI register set */ void -megasas_disable_intr_fusion(struct megasas_register_set __iomem *regs) +megasas_disable_intr_fusion(struct megasas_instance *instance) { u32 mask = 0xFFFFFFFF; u32 status; + struct megasas_register_set __iomem *regs; + regs = instance->reg_set; + instance->mask_interrupts = 1; writel(mask, ®s->outbound_intr_mask); /* Dummy readl to force pci flush */ @@ -643,6 +647,12 @@ megasas_ioc_init_fusion(struct megasas_instance *instance) init_frame->cmd = MFI_CMD_INIT; 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->data_xfer_len = sizeof(struct MPI2_IOC_INIT_REQUEST); @@ -657,7 +667,7 @@ megasas_ioc_init_fusion(struct megasas_instance *instance) /* * 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) { if (readl(&instance->reg_set->doorbell) & 1) @@ -770,8 +780,7 @@ megasas_get_map_info(struct megasas_instance *instance) fusion->fast_path_io = 0; if (!megasas_get_ld_map_info(instance)) { - if (MR_ValidateMapInfo(fusion->ld_map[(instance->map_id & 1)], - fusion->load_balance_info)) { + if (MR_ValidateMapInfo(instance)) { fusion->fast_path_io = 1; return 0; } @@ -864,6 +873,66 @@ megasas_sync_map_info(struct megasas_instance *instance) return ret; } +/* + * meagasas_display_intel_branding - Display branding string + * @instance: per adapter object + * + * Return nothing. + */ +static void +megasas_display_intel_branding(struct megasas_instance *instance) +{ + if (instance->pdev->subsystem_vendor != PCI_VENDOR_ID_INTEL) + return; + + switch (instance->pdev->device) { + case PCI_DEVICE_ID_LSI_INVADER: + switch (instance->pdev->subsystem_device) { + case MEGARAID_INTEL_RS3DC080_SSDID: + dev_info(&instance->pdev->dev, "scsi host %d: %s\n", + instance->host->host_no, + MEGARAID_INTEL_RS3DC080_BRANDING); + break; + case MEGARAID_INTEL_RS3DC040_SSDID: + dev_info(&instance->pdev->dev, "scsi host %d: %s\n", + instance->host->host_no, + MEGARAID_INTEL_RS3DC040_BRANDING); + break; + case MEGARAID_INTEL_RS3SC008_SSDID: + dev_info(&instance->pdev->dev, "scsi host %d: %s\n", + instance->host->host_no, + MEGARAID_INTEL_RS3SC008_BRANDING); + break; + case MEGARAID_INTEL_RS3MC044_SSDID: + dev_info(&instance->pdev->dev, "scsi host %d: %s\n", + instance->host->host_no, + MEGARAID_INTEL_RS3MC044_BRANDING); + break; + default: + break; + } + break; + case PCI_DEVICE_ID_LSI_FURY: + switch (instance->pdev->subsystem_device) { + case MEGARAID_INTEL_RS3WC080_SSDID: + dev_info(&instance->pdev->dev, "scsi host %d: %s\n", + instance->host->host_no, + MEGARAID_INTEL_RS3WC080_BRANDING); + break; + case MEGARAID_INTEL_RS3WC040_SSDID: + dev_info(&instance->pdev->dev, "scsi host %d: %s\n", + instance->host->host_no, + MEGARAID_INTEL_RS3WC040_BRANDING); + break; + default: + break; + } + break; + default: + break; + } +} + /** * megasas_init_adapter_fusion - Initializes the FW * @instance: Adapter soft state @@ -944,6 +1013,8 @@ megasas_init_adapter_fusion(struct megasas_instance *instance) if (megasas_ioc_init_fusion(instance)) goto fail_ioc_init; + megasas_display_intel_branding(instance); + instance->flag_ieee = 1; fusion->map_sz = sizeof(struct MR_FW_RAID_MAP) + @@ -1071,7 +1142,8 @@ megasas_make_sgl_fusion(struct megasas_instance *instance, fusion = instance->ctrl_context; - if (instance->pdev->device == PCI_DEVICE_ID_LSI_INVADER) { + if ((instance->pdev->device == PCI_DEVICE_ID_LSI_INVADER) || + (instance->pdev->device == PCI_DEVICE_ID_LSI_FURY)) { struct MPI25_IEEE_SGE_CHAIN64 *sgl_ptr_end = sgl_ptr; sgl_ptr_end += fusion->max_sge_in_main_msg - 1; sgl_ptr_end->Flags = 0; @@ -1088,7 +1160,8 @@ megasas_make_sgl_fusion(struct megasas_instance *instance, sgl_ptr->Length = sg_dma_len(os_sgl); sgl_ptr->Address = sg_dma_address(os_sgl); sgl_ptr->Flags = 0; - if (instance->pdev->device == PCI_DEVICE_ID_LSI_INVADER) { + if ((instance->pdev->device == PCI_DEVICE_ID_LSI_INVADER) || + (instance->pdev->device == PCI_DEVICE_ID_LSI_FURY)) { if (i == sge_count - 1) sgl_ptr->Flags = IEEE_SGE_FLAGS_END_OF_LIST; } @@ -1100,8 +1173,10 @@ megasas_make_sgl_fusion(struct megasas_instance *instance, (sge_count > fusion->max_sge_in_main_msg)) { struct MPI25_IEEE_SGE_CHAIN64 *sg_chain; - if (instance->pdev->device == - PCI_DEVICE_ID_LSI_INVADER) { + if ((instance->pdev->device == + PCI_DEVICE_ID_LSI_INVADER) || + (instance->pdev->device == + PCI_DEVICE_ID_LSI_FURY)) { if ((cmd->io_request->IoFlags & MPI25_SAS_DEVICE0_FLAGS_ENABLED_FAST_PATH) != MPI25_SAS_DEVICE0_FLAGS_ENABLED_FAST_PATH) @@ -1117,8 +1192,10 @@ megasas_make_sgl_fusion(struct megasas_instance *instance, sg_chain = sgl_ptr; /* Prepare chain element */ sg_chain->NextChainOffset = 0; - if (instance->pdev->device == - PCI_DEVICE_ID_LSI_INVADER) + if ((instance->pdev->device == + PCI_DEVICE_ID_LSI_INVADER) || + (instance->pdev->device == + PCI_DEVICE_ID_LSI_FURY)) sg_chain->Flags = IEEE_SGE_FLAGS_CHAIN_ELEMENT; else sg_chain->Flags = @@ -1434,7 +1511,8 @@ megasas_build_ldio_fusion(struct megasas_instance *instance, cmd->request_desc->SCSIIO.RequestFlags = (MPI2_REQ_DESCRIPT_FLAGS_HIGH_PRIORITY << MEGASAS_REQ_DESCRIPT_FLAGS_TYPE_SHIFT); - if (instance->pdev->device == PCI_DEVICE_ID_LSI_INVADER) { + if ((instance->pdev->device == PCI_DEVICE_ID_LSI_INVADER) || + (instance->pdev->device == PCI_DEVICE_ID_LSI_FURY)) { if (io_request->RaidContext.regLockFlags == REGION_TYPE_UNUSED) cmd->request_desc->SCSIIO.RequestFlags = @@ -1465,7 +1543,8 @@ megasas_build_ldio_fusion(struct megasas_instance *instance, cmd->request_desc->SCSIIO.RequestFlags = (MEGASAS_REQ_DESCRIPT_FLAGS_LD_IO << MEGASAS_REQ_DESCRIPT_FLAGS_TYPE_SHIFT); - if (instance->pdev->device == PCI_DEVICE_ID_LSI_INVADER) { + if ((instance->pdev->device == PCI_DEVICE_ID_LSI_INVADER) || + (instance->pdev->device == PCI_DEVICE_ID_LSI_FURY)) { if (io_request->RaidContext.regLockFlags == REGION_TYPE_UNUSED) cmd->request_desc->SCSIIO.RequestFlags = @@ -1522,11 +1601,27 @@ megasas_build_dcdb_fusion(struct megasas_instance *instance, io_request->RaidContext.RAIDFlags = MR_RAID_FLAGS_IO_SUB_TYPE_SYSTEM_PD << MR_RAID_CTX_RAID_FLAGS_IO_SUB_TYPE_SHIFT; + if ((instance->pdev->device == PCI_DEVICE_ID_LSI_INVADER) || + (instance->pdev->device == PCI_DEVICE_ID_LSI_FURY)) + io_request->IoFlags |= + MPI25_SAS_DEVICE0_FLAGS_ENABLED_FAST_PATH; cmd->request_desc->SCSIIO.RequestFlags = (MPI2_REQ_DESCRIPT_FLAGS_HIGH_PRIORITY << MEGASAS_REQ_DESCRIPT_FLAGS_TYPE_SHIFT); cmd->request_desc->SCSIIO.DevHandle = local_map_ptr->raidMap.devHndlInfo[device_id].curDevHdl; + /* + * If the command is for the tape device, set the + * FP timeout to the os layer timeout value. + */ + if (scmd->device->type == TYPE_TAPE) { + if ((scmd->request->timeout / HZ) > 0xFFFF) + io_request->RaidContext.timeoutValue = + 0xFFFF; + else + io_request->RaidContext.timeoutValue = + scmd->request->timeout / HZ; + } } else { io_request->Function = MEGASAS_MPI2_FUNCTION_LD_IO_REQUEST; io_request->DevHandle = device_id; @@ -1825,8 +1920,15 @@ complete_cmd_fusion(struct megasas_instance *instance, u32 MSIxIndex) return IRQ_NONE; wmb(); - writel((MSIxIndex << 24) | fusion->last_reply_idx[MSIxIndex], - &instance->reg_set->reply_post_host_index); + if ((instance->pdev->device == PCI_DEVICE_ID_LSI_INVADER) || + (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); return IRQ_HANDLED; } @@ -1868,6 +1970,9 @@ irqreturn_t megasas_isr_fusion(int irq, void *devp) struct megasas_instance *instance = irq_context->instance; u32 mfiStatus, fw_state; + if (instance->mask_interrupts) + return IRQ_NONE; + if (!instance->msix_vectors) { mfiStatus = instance->instancet->clear_intr(instance->reg_set); if (!mfiStatus) @@ -1929,7 +2034,8 @@ build_mpt_mfi_pass_thru(struct megasas_instance *instance, fusion = instance->ctrl_context; io_req = cmd->io_request; - if (instance->pdev->device == PCI_DEVICE_ID_LSI_INVADER) { + if ((instance->pdev->device == PCI_DEVICE_ID_LSI_INVADER) || + (instance->pdev->device == PCI_DEVICE_ID_LSI_FURY)) { struct MPI25_IEEE_SGE_CHAIN64 *sgl_ptr_end = (struct MPI25_IEEE_SGE_CHAIN64 *)&io_req->SGL; sgl_ptr_end += fusion->max_sge_in_main_msg - 1; @@ -2132,7 +2238,7 @@ int megasas_reset_fusion(struct Scsi_Host *shost) mutex_lock(&instance->reset_mutex); set_bit(MEGASAS_FUSION_IN_RESET, &instance->reset_flags); instance->adprecovery = MEGASAS_ADPRESET_SM_INFAULT; - instance->instancet->disable_intr(instance->reg_set); + instance->instancet->disable_intr(instance); msleep(1000); /* First try waiting for commands to complete */ @@ -2256,7 +2362,7 @@ int megasas_reset_fusion(struct Scsi_Host *shost) 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; /* Re-fire management commands */ @@ -2318,7 +2424,7 @@ int megasas_reset_fusion(struct Scsi_Host *shost) retval = FAILED; } else { 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; } out: |