diff options
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 a7d56687bfca..417d5f167aa2 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: |