diff --git a/drivers/scsi/megaraid/megaraid_sas.h b/drivers/scsi/megaraid/megaraid_sas.h index de7631c10065731015738e8a3352265b0ea7a7dc..ba6503f37756312d9d0d1d2da23ae0e79180f1a6 100644 --- a/drivers/scsi/megaraid/megaraid_sas.h +++ b/drivers/scsi/megaraid/megaraid_sas.h @@ -197,6 +197,7 @@ enum MFI_CMD_OP { MFI_CMD_ABORT = 0x6, MFI_CMD_SMP = 0x7, MFI_CMD_STP = 0x8, + MFI_CMD_NVME = 0x9, MFI_CMD_OP_COUNT, MFI_CMD_INVALID = 0xff }; @@ -1352,7 +1353,13 @@ struct megasas_ctrl_info { struct { #if defined(__BIG_ENDIAN_BITFIELD) - u16 reserved:8; + u16 reserved:2; + u16 support_nvme_passthru:1; + u16 support_pl_debug_info:1; + u16 support_flash_comp_info:1; + u16 support_host_info:1; + u16 support_dual_fw_update:1; + u16 support_ssc_rev3:1; u16 fw_swaps_bbu_vpd_info:1; u16 support_pd_map_target_id:1; u16 support_ses_ctrl_in_multipathcfg:1; @@ -1377,7 +1384,19 @@ struct megasas_ctrl_info { * provide the data in little endian order */ u16 fw_swaps_bbu_vpd_info:1; - u16 reserved:8; + u16 support_ssc_rev3:1; + /* FW supports CacheCade 3.0, only one SSCD creation allowed */ + u16 support_dual_fw_update:1; + /* FW supports dual firmware update feature */ + u16 support_host_info:1; + /* FW supports MR_DCMD_CTRL_HOST_INFO_SET/GET */ + u16 support_flash_comp_info:1; + /* FW supports MR_DCMD_CTRL_FLASH_COMP_INFO_GET */ + u16 support_pl_debug_info:1; + /* FW supports retrieval of PL debug information through apps */ + u16 support_nvme_passthru:1; + /* FW supports NVMe passthru commands */ + u16 reserved:2; #endif } adapter_operations4; u8 pad[0x800 - 0x7FE]; /* 0x7FE pad to 2K for expansion */ @@ -1630,7 +1649,8 @@ union megasas_sgl_frame { typedef union _MFI_CAPABILITIES { struct { #if defined(__BIG_ENDIAN_BITFIELD) - u32 reserved:18; + u32 reserved:17; + u32 support_nvme_passthru:1; u32 support_64bit_mode:1; u32 support_pd_map_target_id:1; u32 support_qd_throttling:1; @@ -1660,7 +1680,8 @@ typedef union _MFI_CAPABILITIES { u32 support_qd_throttling:1; u32 support_pd_map_target_id:1; u32 support_64bit_mode:1; - u32 reserved:18; + u32 support_nvme_passthru:1; + u32 reserved:17; #endif } mfi_capabilities; __le32 reg; @@ -2268,6 +2289,7 @@ struct megasas_instance { u32 nvme_page_size; u8 adapter_type; bool consistent_mask_64bit; + bool support_nvme_passthru; }; struct MR_LD_VF_MAP { u32 size; diff --git a/drivers/scsi/megaraid/megaraid_sas_base.c b/drivers/scsi/megaraid/megaraid_sas_base.c index d92279eec8f80a909524ad25b8ad7c162a1830fd..0f1d88f272becdbb0754f2ffe32b73af1b5a5096 100644 --- a/drivers/scsi/megaraid/megaraid_sas_base.c +++ b/drivers/scsi/megaraid/megaraid_sas_base.c @@ -181,6 +181,7 @@ static DECLARE_WAIT_QUEUE_HEAD(megasas_poll_wait); static u32 support_poll_for_event; u32 megasas_dbg_lvl; static u32 support_device_change; +static bool support_nvme_encapsulation; /* define lock for aen poll */ spinlock_t poll_aen_lock; @@ -3334,6 +3335,7 @@ megasas_complete_cmd(struct megasas_instance *instance, struct megasas_cmd *cmd, case MFI_CMD_SMP: case MFI_CMD_STP: + case MFI_CMD_NVME: megasas_complete_int_cmd(instance, cmd); break; @@ -4721,6 +4723,8 @@ megasas_get_ctrl_info(struct megasas_instance *instance) ci->adapterOperations3.useSeqNumJbodFP; instance->support_morethan256jbod = ci->adapter_operations4.support_pd_map_target_id; + instance->support_nvme_passthru = + ci->adapter_operations4.support_nvme_passthru; /*Check whether controller is iMR or MR */ instance->is_imr = (ci->memory_size ? 0 : 1); @@ -4737,6 +4741,8 @@ megasas_get_ctrl_info(struct megasas_instance *instance) instance->disableOnlineCtrlReset ? "Disabled" : "Enabled"); dev_info(&instance->pdev->dev, "Secure JBOD support\t: %s\n", instance->secure_jbod_support ? "Yes" : "No"); + dev_info(&instance->pdev->dev, "NVMe passthru support\t: %s\n", + instance->support_nvme_passthru ? "Yes" : "No"); break; case DCMD_TIMEOUT: @@ -7110,7 +7116,9 @@ megasas_mgmt_fw_ioctl(struct megasas_instance *instance, return -EINVAL; } - if (ioc->frame.hdr.cmd >= MFI_CMD_OP_COUNT) { + if ((ioc->frame.hdr.cmd >= MFI_CMD_OP_COUNT) || + ((ioc->frame.hdr.cmd == MFI_CMD_NVME) && + !instance->support_nvme_passthru)) { dev_err(&instance->pdev->dev, "Received invalid ioctl command 0x%x\n", ioc->frame.hdr.cmd); @@ -7580,6 +7588,14 @@ static ssize_t dbg_lvl_store(struct device_driver *dd, const char *buf, } static DRIVER_ATTR_RW(dbg_lvl); +static ssize_t +support_nvme_encapsulation_show(struct device_driver *dd, char *buf) +{ + return sprintf(buf, "%u\n", support_nvme_encapsulation); +} + +static DRIVER_ATTR_RO(support_nvme_encapsulation); + static inline void megasas_remove_scsi_device(struct scsi_device *sdev) { sdev_printk(KERN_INFO, sdev, "SCSI device is removed\n"); @@ -7768,6 +7784,7 @@ static int __init megasas_init(void) support_poll_for_event = 2; support_device_change = 1; + support_nvme_encapsulation = true; memset(&megasas_mgmt_info, 0, sizeof(megasas_mgmt_info)); @@ -7817,8 +7834,17 @@ static int __init megasas_init(void) if (rval) goto err_dcf_support_device_change; + rval = driver_create_file(&megasas_pci_driver.driver, + &driver_attr_support_nvme_encapsulation); + if (rval) + goto err_dcf_support_nvme_encapsulation; + return rval; +err_dcf_support_nvme_encapsulation: + driver_remove_file(&megasas_pci_driver.driver, + &driver_attr_support_device_change); + err_dcf_support_device_change: driver_remove_file(&megasas_pci_driver.driver, &driver_attr_dbg_lvl); @@ -7851,6 +7877,8 @@ static void __exit megasas_exit(void) driver_remove_file(&megasas_pci_driver.driver, &driver_attr_release_date); driver_remove_file(&megasas_pci_driver.driver, &driver_attr_version); + driver_remove_file(&megasas_pci_driver.driver, + &driver_attr_support_nvme_encapsulation); pci_unregister_driver(&megasas_pci_driver); unregister_chrdev(megasas_mgmt_majorno, "megaraid_sas_ioctl"); diff --git a/drivers/scsi/megaraid/megaraid_sas_fusion.c b/drivers/scsi/megaraid/megaraid_sas_fusion.c index 97fae28c8374bb00cb0c5a7965df7b70e10f54c8..073ced07e662bc11bd00cdfc9d6214ec3a6a0b8e 100644 --- a/drivers/scsi/megaraid/megaraid_sas_fusion.c +++ b/drivers/scsi/megaraid/megaraid_sas_fusion.c @@ -1079,6 +1079,7 @@ megasas_ioc_init_fusion(struct megasas_instance *instance) drv_ops->mfi_capabilities.support_qd_throttling = 1; drv_ops->mfi_capabilities.support_pd_map_target_id = 1; + drv_ops->mfi_capabilities.support_nvme_passthru = 1; if (instance->consistent_mask_64bit) drv_ops->mfi_capabilities.support_64bit_mode = 1; @@ -3993,7 +3994,13 @@ void megasas_refire_mgmt_cmd(struct megasas_instance *instance) result = RETURN_CMD; break; + case MFI_CMD_NVME: + if (!instance->support_nvme_passthru) { + cmd_mfi->frame->hdr.cmd_status = MFI_STAT_INVALID_CMD; + result = COMPLETE_CMD; + } + break; default: break; }