From patchwork Tue Sep 21 18:45:54 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Kashyap Desai X-Patchwork-Id: 12508633 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-20.1 required=3.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_CR_TRAILER,INCLUDES_PATCH,MAILING_LIST_MULTI,MIME_HEADER_CTYPE_ONLY, SPF_HELO_NONE,SPF_PASS,T_TVD_MIME_NO_HEADERS,URIBL_BLOCKED,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 9A751C433FE for ; Tue, 21 Sep 2021 18:46:44 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 70ADA6127B for ; Tue, 21 Sep 2021 18:46:44 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231371AbhIUSsB (ORCPT ); Tue, 21 Sep 2021 14:48:01 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:40202 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231171AbhIUSrm (ORCPT ); Tue, 21 Sep 2021 14:47:42 -0400 Received: from mail-pg1-x52b.google.com (mail-pg1-x52b.google.com [IPv6:2607:f8b0:4864:20::52b]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id D7939C061575 for ; Tue, 21 Sep 2021 11:46:12 -0700 (PDT) Received: by mail-pg1-x52b.google.com with SMTP id w8so1624pgf.5 for ; Tue, 21 Sep 2021 11:46:12 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=broadcom.com; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=NeFfzIlGsI0tUNukOCOJuiDmGBBBU526qFyPvHybGFU=; b=ZuqV7RFI34rOfYO65CvltYBDt2ncubT1F5nU4Z8DHTg2B5OeQ01S+kt4uURnKRirOb 2cJ9yNZjal5pjxlQiZ2Vy04LHxLp8M75/Hl9cgiliPouaSwnKCWqzhvDEvIBcZjnUCLn CM+V6pPRe5ewOOblTplxYGqvEfwr+j6tocGOs= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=NeFfzIlGsI0tUNukOCOJuiDmGBBBU526qFyPvHybGFU=; b=4uUhUOy58++WARq7BWCU+UOiRK6CCOG4RQxmkXzo4Oq4gbBGQynIh2cdmDh26frH6l 7zOS57sRYoHMM2Gskr8SQboLg83OkcBiJ2Ij/+HMhj9syw000AjBl8uldhPDJNaZVtrz n3EhVTsGZYnJXnZ972q5w/VuhC3FXeeU+MEMvsYXEave5i6um8tjEXOYrTygD+7XvNQz pkCbKXKXptQzrgGrprHBhcByPOw0VKMyHMVfHZ5gsmWVnevFdpFTTvb99NmAaDIlaR4y yQwK0FXs/tdDUh9HWrTiLmKt3s4k3g6XFmPEPRFu0LLd4mFfsaa9IUPhOCaQmMagfrx6 4+PQ== X-Gm-Message-State: AOAM533sBc02Q1wnB1UnYzAV42q+d+F17mGjT1ymlwAgBH48onjAA7od dlYgjt8rxCzYMStg5O18atwf23K7JzGeKyWbWBo3IWpR9/j0aB+S+C4v0kudA5gU70KFYVUmDLL a+LCusfhJajJ0H7RWHn6u6O4xpDX55lRezdk1XN+j9wOSd5o9NCeYmI9RdD9c39HAH24yv15Yl6 5aYDILO/iB X-Google-Smtp-Source: ABdhPJxShKJ/9C2ZK2Utmyodl+TJxxgz3lOOmHCiR3VqqLnOPelSqY7/lehwjZfO5looQwxDSicKBg== X-Received: by 2002:a63:3607:: with SMTP id d7mr29605156pga.438.1632249971139; Tue, 21 Sep 2021 11:46:11 -0700 (PDT) Received: from drv-bst-rhel8.dhcp.broadcom.net ([192.19.234.250]) by smtp.gmail.com with ESMTPSA id f144sm18258897pfa.24.2021.09.21.11.46.08 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 21 Sep 2021 11:46:10 -0700 (PDT) From: Kashyap Desai To: linux-scsi@vger.kernel.org Cc: jejb@linux.ibm.com, martin.petersen@oracle.com, steve.hagan@broadcom.com, mpi3mr-linuxdrv.pdl@broadcom.com, Kashyap Desai , sathya.prakash@broadcom.com Subject: [PATCH 1/7] mpi3mr: upgrade mpi30 Rev-V Date: Wed, 22 Sep 2021 00:15:54 +0530 Message-Id: <20210921184600.64427-2-kashyap.desai@broadcom.com> X-Mailer: git-send-email 2.18.1 In-Reply-To: <20210921184600.64427-1-kashyap.desai@broadcom.com> References: <20210921184600.64427-1-kashyap.desai@broadcom.com> Precedence: bulk List-ID: X-Mailing-List: linux-scsi@vger.kernel.org Signed-off-by: Kashyap Desai Cc: sathya.prakash@broadcom.com --- drivers/scsi/mpi3mr/mpi/mpi30_cnfg.h | 603 ++++++++++++++++++---- drivers/scsi/mpi3mr/mpi/mpi30_image.h | 59 ++- drivers/scsi/mpi3mr/mpi/mpi30_init.h | 15 +- drivers/scsi/mpi3mr/mpi/mpi30_ioc.h | 128 +++-- drivers/scsi/mpi3mr/mpi/mpi30_pci.h | 44 ++ drivers/scsi/mpi3mr/mpi/mpi30_sas.h | 14 + drivers/scsi/mpi3mr/mpi/mpi30_tool.h | 303 +++++++++++ drivers/scsi/mpi3mr/mpi/mpi30_transport.h | 31 +- drivers/scsi/mpi3mr/mpi3mr_fw.c | 9 +- drivers/scsi/mpi3mr/mpi3mr_os.c | 2 +- 10 files changed, 1052 insertions(+), 156 deletions(-) create mode 100644 drivers/scsi/mpi3mr/mpi/mpi30_pci.h create mode 100644 drivers/scsi/mpi3mr/mpi/mpi30_tool.h diff --git a/drivers/scsi/mpi3mr/mpi/mpi30_cnfg.h b/drivers/scsi/mpi3mr/mpi/mpi30_cnfg.h index d43bbecef651..5e1f6ced0e71 100644 --- a/drivers/scsi/mpi3mr/mpi/mpi30_cnfg.h +++ b/drivers/scsi/mpi3mr/mpi/mpi30_cnfg.h @@ -8,7 +8,7 @@ #define MPI3_CONFIG_PAGETYPE_IO_UNIT (0x00) #define MPI3_CONFIG_PAGETYPE_MANUFACTURING (0x01) #define MPI3_CONFIG_PAGETYPE_IOC (0x02) -#define MPI3_CONFIG_PAGETYPE_UEFI_BSD (0x03) +#define MPI3_CONFIG_PAGETYPE_DRIVER (0x03) #define MPI3_CONFIG_PAGETYPE_SECURITY (0x04) #define MPI3_CONFIG_PAGETYPE_ENCLOSURE (0x11) #define MPI3_CONFIG_PAGETYPE_DEVICE (0x12) @@ -181,8 +181,17 @@ struct mpi3_config_page_header { #define MPI3_SAS_HWRATE_MIN_RATE_6_0 (0x0a) #define MPI3_SAS_HWRATE_MIN_RATE_12_0 (0x0b) #define MPI3_SAS_HWRATE_MIN_RATE_22_5 (0x0c) -#define MPI3_SLOT_INVALID (0xffff) -#define MPI3_SLOT_INDEX_INVALID (0xffff) +#define MPI3_SLOT_INVALID (0xffff) +#define MPI3_SLOT_INDEX_INVALID (0xffff) +#define MPI3_LINK_CHANGE_COUNT_INVALID (0xffff) +#define MPI3_RATE_CHANGE_COUNT_INVALID (0xffff) +#define MPI3_TEMP_SENSOR_LOCATION_INTERNAL (0x0) +#define MPI3_TEMP_SENSOR_LOCATION_INLET (0x1) +#define MPI3_TEMP_SENSOR_LOCATION_OUTLET (0x2) +#define MPI3_TEMP_SENSOR_LOCATION_DRAM (0x3) +#define MPI3_MFGPAGE_VENDORID_BROADCOM (0x1000) +#define MPI3_MFGPAGE_DEVID_SAS4116 (0x00a5) +#define MPI3_MFGPAGE_DEVID_SAS4016 (0x00a7) struct mpi3_man_page0 { struct mpi3_config_page_header header; u8 chip_revision[8]; @@ -195,7 +204,7 @@ struct mpi3_man_page0 { __le32 reserved98; u8 oem; u8 sub_oem; - __le16 reserved9e; + __le16 flags; u8 board_mfg_day; u8 board_mfg_month; __le16 board_mfg_year; @@ -208,6 +217,8 @@ struct mpi3_man_page0 { }; #define MPI3_MAN0_PAGEVERSION (0x00) +#define MPI3_MAN0_FLAGS_SWITCH_PRESENT (0x0002) +#define MPI3_MAN0_FLAGS_EXPANDER_PRESENT (0x0001) #define MPI3_MAN1_VPD_SIZE (512) struct mpi3_man_page1 { struct mpi3_config_page_header header; @@ -236,7 +247,7 @@ struct mpi3_man_page5 { #define MPI3_MAN5_PAGEVERSION (0x00) struct mpi3_man6_gpio_entry { u8 function_code; - u8 reserved01; + u8 function_flags; __le16 flags; u8 param1; u8 param2; @@ -253,7 +264,6 @@ struct mpi3_man6_gpio_entry { #define MPI3_MAN6_GPIO_FUNCTION_PORT_STATUS_YELLOW (0x06) #define MPI3_MAN6_GPIO_FUNCTION_CABLE_MANAGEMENT (0x07) #define MPI3_MAN6_GPIO_FUNCTION_BKPLANE_MGMT_TYPE (0x08) -#define MPI3_MAN6_GPIO_FUNCTION_ISTWI_MUX_RESET (0x09) #define MPI3_MAN6_GPIO_FUNCTION_ISTWI_RESET (0x0a) #define MPI3_MAN6_GPIO_FUNCTION_BACKEND_PCIE_RESET (0x0b) #define MPI3_MAN6_GPIO_FUNCTION_GLOBAL_FAULT (0x0c) @@ -263,6 +273,10 @@ struct mpi3_man6_gpio_entry { #define MPI3_MAN6_GPIO_FUNCTION_CTRL_TYPE (0x10) #define MPI3_MAN6_GPIO_FUNCTION_LICENSE (0x11) #define MPI3_MAN6_GPIO_FUNCTION_REFCLK_CONTROL (0x12) +#define MPI3_MAN6_GPIO_FUNCTION_BACKEND_PCIE_RESET_CLAMP (0x13) +#define MPI3_MAN6_GPIO_ISTWI_RESET_FUNCTIONFLAGS_DEVSELECT_MASK (0x01) +#define MPI3_MAN6_GPIO_ISTWI_RESET_FUNCTIONFLAGS_DEVSELECT_ISTWI (0x00) +#define MPI3_MAN6_GPIO_ISTWI_RESET_FUNCTIONFLAGS_DEVSELECT_RECEPTACLEID (0x01) #define MPI3_MAN6_GPIO_EXTINT_PARAM1_FLAGS_SOURCE_MASK (0xf0) #define MPI3_MAN6_GPIO_EXTINT_PARAM1_FLAGS_SOURCE_GENERIC (0x00) #define MPI3_MAN6_GPIO_EXTINT_PARAM1_FLAGS_SOURCE_CABLE_MGMT (0x10) @@ -275,8 +289,6 @@ struct mpi3_man6_gpio_entry { #define MPI3_MAN6_GPIO_CABLE_MGMT_PARAM1_INTERFACE_MODULE_PRESENT (0x00) #define MPI3_MAN6_GPIO_CABLE_MGMT_PARAM1_INTERFACE_ACTIVE_CABLE_ENABLE (0x01) #define MPI3_MAN6_GPIO_CABLE_MGMT_PARAM1_INTERFACE_CABLE_MGMT_ENABLE (0x02) -#define MPI3_MAN6_GPIO_ISTWI_MUX_RESET_PARAM2_SPEC_MUX (0x00) -#define MPI3_MAN6_GPIO_ISTWI_MUX_RESET_PARAM2_ALL_MUXES (0x01) #define MPI3_MAN6_GPIO_LICENSE_PARAM1_TYPE_IBUTTON (0x00) #define MPI3_MAN6_GPIO_FLAGS_SLEW_RATE_MASK (0x0100) #define MPI3_MAN6_GPIO_FLAGS_SLEW_RATE_FAST_EDGE (0x0100) @@ -353,6 +365,7 @@ struct mpi3_man8_phy_info { __le32 reserved0c; }; +#define MPI3_MAN8_PHY_INFO_RECEPTACLE_ID_HOST_PHY (0xff) #ifndef MPI3_MAN8_PHY_INFO_MAX #define MPI3_MAN8_PHY_INFO_MAX (1) #endif @@ -373,20 +386,22 @@ struct mpi3_man9_rsrc_entry { }; enum mpi3_man9_resources { - MPI3_MAN9_RSRC_OUTSTANDING_REQS = 0, - MPI3_MAN9_RSRC_TARGET_CMDS = 1, - MPI3_MAN9_RSRC_SAS_TARGETS = 2, - MPI3_MAN9_RSRC_PCIE_TARGETS = 3, - MPI3_MAN9_RSRC_INITIATORS = 4, - MPI3_MAN9_RSRC_VDS = 5, - MPI3_MAN9_RSRC_ENCLOSURES = 6, - MPI3_MAN9_RSRC_ENCLOSURE_PHYS = 7, - MPI3_MAN9_RSRC_EXPANDERS = 8, - MPI3_MAN9_RSRC_PCIE_SWITCHES = 9, - MPI3_MAN9_RSRC_PDS = 10, - MPI3_MAN9_RSRC_HOST_PDS = 11, - MPI3_MAN9_RSRC_ADV_HOST_PDS = 12, - MPI3_MAN9_RSRC_RAID_PDS = 13, + MPI3_MAN9_RSRC_OUTSTANDING_REQS = 0, + MPI3_MAN9_RSRC_TARGET_CMDS = 1, + MPI3_MAN9_RSRC_RESERVED02 = 2, + MPI3_MAN9_RSRC_NVME = 3, + MPI3_MAN9_RSRC_INITIATORS = 4, + MPI3_MAN9_RSRC_VDS = 5, + MPI3_MAN9_RSRC_ENCLOSURES = 6, + MPI3_MAN9_RSRC_ENCLOSURE_PHYS = 7, + MPI3_MAN9_RSRC_EXPANDERS = 8, + MPI3_MAN9_RSRC_PCIE_SWITCHES = 9, + MPI3_MAN9_RSRC_RESERVED10 = 10, + MPI3_MAN9_RSRC_HOST_PD_DRIVES = 11, + MPI3_MAN9_RSRC_ADV_HOST_PD_DRIVES = 12, + MPI3_MAN9_RSRC_RAID_PD_DRIVES = 13, + MPI3_MAN9_RSRC_DRV_DIAG_BUF = 14, + MPI3_MAN9_RSRC_NAMESPACE_COUNT = 15, MPI3_MAN9_RSRC_NUM_RESOURCES }; @@ -402,6 +417,7 @@ enum mpi3_man9_resources { #define MPI3_MAN9_MIN_ENCLOSURES (0) #define MPI3_MAN9_MAX_ENCLOSURES (65535) #define MPI3_MAN9_MIN_ENCLOSURE_PHYS (0) +#define MPI3_MAN9_MIN_NAMESPACE_COUNT (1) #define MPI3_MAN9_MIN_EXPANDERS (0) #define MPI3_MAN9_MAX_EXPANDERS (65535) #define MPI3_MAN9_MIN_PCIE_SWITCHES (0) @@ -422,9 +438,14 @@ struct mpi3_man_page9 { struct mpi3_man10_istwi_ctrlr_entry { __le16 slave_address; __le16 flags; - __le32 reserved04; + u8 scl_low_override; + u8 scl_high_override; + __le16 reserved06; }; +#define MPI3_MAN10_ISTWI_CTRLR_FLAGS_BUS_SPEED_MASK (0x000c) +#define MPI3_MAN10_ISTWI_CTRLR_FLAGS_BUS_SPEED_100K (0x0000) +#define MPI3_MAN10_ISTWI_CTRLR_FLAGS_BUS_SPEED_400K (0x0004) #define MPI3_MAN10_ISTWI_CTRLR_FLAGS_SLAVE_ENABLED (0x0002) #define MPI3_MAN10_ISTWI_CTRLR_FLAGS_MASTER_ENABLED (0x0001) #ifndef MPI3_MAN10_ISTWI_CTRLR_MAX @@ -451,10 +472,13 @@ struct mpi3_man11_temp_sensor_device_format { u8 temp_channel[4]; }; -#define MPI3_MAN11_TEMP_SENSOR_TYPE_MAX6654 (0x00) -#define MPI3_MAN11_TEMP_SENSOR_TYPE_EMC1442 (0x01) -#define MPI3_MAN11_TEMP_SENSOR_TYPE_ADT7476 (0x02) -#define MPI3_MAN11_TEMP_SENSOR_CHANNEL_ENABLED (0x01) +#define MPI3_MAN11_TEMP_SENSOR_TYPE_MAX6654 (0x00) +#define MPI3_MAN11_TEMP_SENSOR_TYPE_EMC1442 (0x01) +#define MPI3_MAN11_TEMP_SENSOR_TYPE_ADT7476 (0x02) +#define MPI3_MAN11_TEMP_SENSOR_TYPE_SE97B (0x03) +#define MPI3_MAN11_TEMP_SENSOR_CHANNEL_LOCATION_MASK (0xe0) +#define MPI3_MAN11_TEMP_SENSOR_CHANNEL_LOCATION_SHIFT (5) +#define MPI3_MAN11_TEMP_SENSOR_CHANNEL_ENABLED (0x01) struct mpi3_man11_seeprom_device_format { u8 size; u8 page_write_size; @@ -495,31 +519,40 @@ struct mpi3_man11_bkplane_spec_ubm_format { #define MPI3_MAN11_BKPLANE_UBM_FLAGS_MAX_FRU_SHIFT (4) #define MPI3_MAN11_BKPLANE_UBM_FLAGS_POLL_INTERVAL_MASK (0x000f) #define MPI3_MAN11_BKPLANE_UBM_FLAGS_POLL_INTERVAL_SHIFT (0) -struct mpi3_man11_bkplane_spec_vpp_format { +struct mpi3_man11_bkplane_spec_non_ubm_format { __le16 flags; - __le16 reserved02; + u8 reserved02; + u8 type; }; -#define MPI3_MAN11_BKPLANE_VPP_FLAGS_REFCLK_POLICY_ALWAYS_ENABLED (0x0040) -#define MPI3_MAN11_BKPLANE_VPP_FLAGS_PRESENCE_DETECT_MASK (0x0030) -#define MPI3_MAN11_BKPLANE_VPP_FLAGS_PRESENCE_DETECT_GPIO (0x0000) -#define MPI3_MAN11_BKPLANE_VPP_FLAGS_PRESENCE_DETECT_REG (0x0010) -#define MPI3_MAN11_BKPLANE_VPP_FLAGS_POLL_INTERVAL_MASK (0x000f) -#define MPI3_MAN11_BKPLANE_VPP_FLAGS_POLL_INTERVAL_SHIFT (0) +#define MPI3_MAN11_BKPLANE_NON_UBM_FLAGS_GROUP_MASK (0xf000) +#define MPI3_MAN11_BKPLANE_NON_UBM_FLAGS_GROUP_SHIFT (12) +#define MPI3_MAN11_BKPLANE_NON_UBM_FLAGS_REFCLK_POLICY_ALWAYS_ENABLED (0x0200) +#define MPI3_MAN11_BKPLANE_NON_UBM_FLAGS_PRESENCE_DETECT_MASK (0x0030) +#define MPI3_MAN11_BKPLANE_NON_UBM_FLAGS_PRESENCE_DETECT_GPIO (0x0000) +#define MPI3_MAN11_BKPLANE_NON_UBM_FLAGS_PRESENCE_DETECT_REG (0x0010) +#define MPI3_MAN11_BKPLANE_NON_UBM_FLAGS_POLL_INTERVAL_MASK (0x000f) +#define MPI3_MAN11_BKPLANE_NON_UBM_FLAGS_POLL_INTERVAL_SHIFT (0) +#define MPI3_MAN11_BKPLANE_NON_UBM_TYPE_VPP (0x00) union mpi3_man11_bkplane_spec_format { - struct mpi3_man11_bkplane_spec_ubm_format ubm; - struct mpi3_man11_bkplane_spec_vpp_format vpp; + struct mpi3_man11_bkplane_spec_ubm_format ubm; + struct mpi3_man11_bkplane_spec_non_ubm_format non_ubm; }; struct mpi3_man11_bkplane_mgmt_device_format { u8 type; u8 receptacle_id; - __le16 reserved02; + u8 reset_info; + u8 reserved03; union mpi3_man11_bkplane_spec_format backplane_mgmt_specific; }; #define MPI3_MAN11_BKPLANE_MGMT_TYPE_UBM (0x00) -#define MPI3_MAN11_BKPLANE_MGMT_TYPE_VPP (0x01) +#define MPI3_MAN11_BKPLANE_MGMT_TYPE_NON_UBM (0x01) +#define MPI3_MAN11_BACKPLANE_RESETINFO_ASSERT_TIME_MASK (0xf0) +#define MPI3_MAN11_BACKPLANE_RESETINFO_ASSERT_TIME_SHIFT (4) +#define MPI3_MAN11_BACKPLANE_RESETINFO_READY_TIME_MASK (0x0f) +#define MPI3_MAN11_BACKPLANE_RESETINFO_READY_TIME_SHIFT (0) struct mpi3_man11_gas_gauge_device_format { u8 type; u8 reserved01[3]; @@ -527,6 +560,11 @@ struct mpi3_man11_gas_gauge_device_format { }; #define MPI3_MAN11_GAS_GAUGE_TYPE_STANDARD (0x00) +struct mpi3_man11_mgmt_ctrlr_device_format { + __le32 reserved00; + __le32 reserved04; +}; + union mpi3_man11_device_specific_format { struct mpi3_man11_mux_device_format mux; struct mpi3_man11_temp_sensor_device_format temp_sensor; @@ -535,6 +573,7 @@ union mpi3_man11_device_specific_format { struct mpi3_man11_cable_mgmt_device_format cable_mgmt; struct mpi3_man11_bkplane_mgmt_device_format bkplane_mgmt; struct mpi3_man11_gas_gauge_device_format gas_gauge; + struct mpi3_man11_mgmt_ctrlr_device_format mgmt_controller; __le32 words[2]; }; @@ -556,10 +595,8 @@ struct mpi3_man11_istwi_device_format { #define MPI3_MAN11_ISTWI_DEVTYPE_CABLE_MGMT (0x04) #define MPI3_MAN11_ISTWI_DEVTYPE_BACKPLANE_MGMT (0x05) #define MPI3_MAN11_ISTWI_DEVTYPE_GAS_GAUGE (0x06) +#define MPI3_MAN11_ISTWI_DEVTYPE_MGMT_CONTROLLER (0x07) #define MPI3_MAN11_ISTWI_FLAGS_MUX_PRESENT (0x01) -#define MPI3_MAN11_ISTWI_FLAGS_BUS_SPEED_MASK (0x06) -#define MPI3_MAN11_ISTWI_FLAGS_BUS_SPEED_100KHZ (0x00) -#define MPI3_MAN11_ISTWI_FLAGS_BUS_SPEED_400KHZ (0x02) #ifndef MPI3_MAN11_ISTWI_DEVICE_MAX #define MPI3_MAN11_ISTWI_DEVICE_MAX (1) #endif @@ -692,8 +729,8 @@ struct mpi3_man_page14 { #define MPI3_MAN14_FLAGS_AUTH_SESSION_REQ (0x01) #define MPI3_MAN14_FLAGS_AUTH_API_MASK (0x0e) #define MPI3_MAN14_FLAGS_AUTH_API_NONE (0x00) -#define MPI3_MAN14_FLAGS_AUTH_API_CEREBUS (0x02) -#define MPI3_MAN14_FLAGS_AUTH_API_DMTF_PMCI (0x04) +#define MPI3_MAN14_FLAGS_AUTH_API_CERBERUS (0x02) +#define MPI3_MAN14_FLAGS_AUTH_API_SPDM (0x04) #ifndef MPI3_MAN15_VERSION_RECORD_MAX #define MPI3_MAN15_VERSION_RECORD_MAX 1 #endif @@ -808,7 +845,7 @@ struct mpi3_io_unit_page1 { struct mpi3_config_page_header header; __le32 flags; u8 dmd_io_delay; - u8 dmd_report_pc_ie; + u8 dmd_report_pcie; u8 dmd_report_sata; u8 dmd_report_sas; }; @@ -844,26 +881,30 @@ struct mpi3_io_unit_page2 { #define MPI3_IOUNIT2_GPIO_SETTING_ON (0x0001) struct mpi3_io_unit3_sensor { __le16 flags; - __le16 reserved02; - __le16 threshold[4]; + u8 threshold_margin; + u8 reserved03; + __le16 threshold[3]; + __le16 reserved0a; __le32 reserved0c; __le32 reserved10; __le32 reserved14; }; -#define MPI3_IOUNIT3_SENSOR_FLAGS_T3_ENABLE (0x0008) -#define MPI3_IOUNIT3_SENSOR_FLAGS_T2_ENABLE (0x0004) -#define MPI3_IOUNIT3_SENSOR_FLAGS_T1_ENABLE (0x0002) -#define MPI3_IOUNIT3_SENSOR_FLAGS_T0_ENABLE (0x0001) +#define MPI3_IOUNIT3_SENSOR_FLAGS_FATAL_EVENT_ENABLED (0x0010) +#define MPI3_IOUNIT3_SENSOR_FLAGS_FATAL_ACTION_ENABLED (0x0008) +#define MPI3_IOUNIT3_SENSOR_FLAGS_CRITICAL_EVENT_ENABLED (0x0004) +#define MPI3_IOUNIT3_SENSOR_FLAGS_CRITICAL_ACTION_ENABLED (0x0002) +#define MPI3_IOUNIT3_SENSOR_FLAGS_WARNING_EVENT_ENABLED (0x0001) #ifndef MPI3_IO_UNIT3_SENSOR_MAX -#define MPI3_IO_UNIT3_SENSOR_MAX (1) +#define MPI3_IO_UNIT3_SENSOR_MAX (1) #endif struct mpi3_io_unit_page3 { struct mpi3_config_page_header header; __le32 reserved08; u8 num_sensors; - u8 polling_interval; - __le16 reserved0e; + u8 nominal_poll_interval; + u8 warning_poll_interval; + u8 reserved0f; struct mpi3_io_unit3_sensor sensor[MPI3_IO_UNIT3_SENSOR_MAX]; }; @@ -873,13 +914,19 @@ struct mpi3_io_unit4_sensor { __le16 reserved02; u8 flags; u8 reserved05[3]; - __le32 reserved08; + __le16 istwi_index; + u8 channel; + u8 reserved0b; __le32 reserved0c; }; +#define MPI3_IOUNIT4_SENSOR_FLAGS_LOC_MASK (0xe0) +#define MPI3_IOUNIT4_SENSOR_FLAGS_LOC_SHIFT (5) #define MPI3_IOUNIT4_SENSOR_FLAGS_TEMP_VALID (0x01) +#define MPI3_IOUNIT4_SENSOR_ISTWI_INDEX_INTERNAL (0xffff) +#define MPI3_IOUNIT4_SENSOR_CHANNEL_RESERVED (0xff) #ifndef MPI3_IO_UNIT4_SENSOR_MAX -#define MPI3_IO_UNIT4_SENSOR_MAX (1) +#define MPI3_IO_UNIT4_SENSOR_MAX (1) #endif struct mpi3_io_unit_page4 { struct mpi3_config_page_header header; @@ -906,8 +953,9 @@ struct mpi3_io_unit_page5 { struct mpi3_io_unit5_spinup_group spinup_group_parameters[4]; __le32 reserved18; __le32 reserved1c; - __le32 reserved20; - u8 reserved24; + __le16 device_shutdown; + __le16 reserved22; + u8 pcie_device_wait_time; u8 sata_device_wait_time; u8 spinup_encl_drive_count; u8 spinup_encl_delay; @@ -919,6 +967,22 @@ struct mpi3_io_unit_page5 { }; #define MPI3_IOUNIT5_PAGEVERSION (0x00) +#define MPI3_IOUNIT5_DEVICE_SHUTDOWN_NO_ACTION (0x00) +#define MPI3_IOUNIT5_DEVICE_SHUTDOWN_DIRECT_ATTACHED (0x01) +#define MPI3_IOUNIT5_DEVICE_SHUTDOWN_EXPANDER_ATTACHED (0x02) +#define MPI3_IOUNIT5_DEVICE_SHUTDOWN_SWITCH_ATTACHED (0x02) +#define MPI3_IOUNIT5_DEVICE_SHUTDOWN_DIRECT_AND_EXPANDER (0x03) +#define MPI3_IOUNIT5_DEVICE_SHUTDOWN_DIRECT_AND_SWITCH (0x03) +#define MPI3_IOUNIT5_DEVICE_SHUTDOWN_SATA_HDD_MASK (0x0300) +#define MPI3_IOUNIT5_DEVICE_SHUTDOWN_SATA_HDD_SHIFT (8) +#define MPI3_IOUNIT5_DEVICE_SHUTDOWN_SAS_HDD_MASK (0x00c0) +#define MPI3_IOUNIT5_DEVICE_SHUTDOWN_SAS_HDD_SHIFT (6) +#define MPI3_IOUNIT5_DEVICE_SHUTDOWN_NVME_SSD_MASK (0x0030) +#define MPI3_IOUNIT5_DEVICE_SHUTDOWN_NVME_SSD_SHIFT (4) +#define MPI3_IOUNIT5_DEVICE_SHUTDOWN_SATA_SSD_MASK (0x000c) +#define MPI3_IOUNIT5_DEVICE_SHUTDOWN_SATA_SSD_SHIFT (2) +#define MPI3_IOUNIT5_DEVICE_SHUTDOWN_SAS_SSD_MASK (0x0003) +#define MPI3_IOUNIT5_DEVICE_SHUTDOWN_SAA_SSD_SHIFT (0) #define MPI3_IOUNIT5_FLAGS_POWER_CAPABLE_SPINUP (0x02) #define MPI3_IOUNIT5_FLAGS_AUTO_PORT_ENABLE (0x01) #define MPI3_IOUNIT5_PHY_SPINUP_GROUP_MASK (0x03) @@ -1012,7 +1076,52 @@ struct mpi3_ioc_page2 { }; #define MPI3_IOC2_PAGEVERSION (0x00) -struct mpi3_uefibsd_page0 { +#define MPI3_DRIVER_FLAGS_ADMINRAIDPD_BLOCKED (0x0010) +#define MPI3_DRIVER_FLAGS_OOBRAIDPD_BLOCKED (0x0008) +#define MPI3_DRIVER_FLAGS_OOBRAIDVD_BLOCKED (0x0004) +#define MPI3_DRIVER_FLAGS_OOBADVHOSTPD_BLOCKED (0x0002) +#define MPI3_DRIVER_FLAGS_OOBHOSTPD_BLOCKED (0x0001) +struct mpi3_allowed_cmd_scsi { + __le16 service_action; + u8 operation_code; + u8 command_flags; +}; + +struct mpi3_allowed_cmd_ata { + u8 subcommand; + u8 reserved01; + u8 command; + u8 command_flags; +}; + +struct mpi3_allowed_cmd_nvme { + u8 reserved00; + u8 nvme_cmd_flags; + u8 op_code; + u8 command_flags; +}; + +#define MPI3_DRIVER_ALLOWEDCMD_NVMECMDFLAGS_SUBQ_TYPE_MASK (0x80) +#define MPI3_DRIVER_ALLOWEDCMD_NVMECMDFLAGS_SUBQ_TYPE_IO (0x00) +#define MPI3_DRIVER_ALLOWEDCMD_NVMECMDFLAGS_SUBQ_TYPE_ADMIN (0x80) +#define MPI3_DRIVER_ALLOWEDCMD_NVMECMDFLAGS_CMDSET_MASK (0x3f) +#define MPI3_DRIVER_ALLOWEDCMD_NVMECMDFLAGS_CMDSET_NVM (0x00) +union mpi3_allowed_cmd { + struct mpi3_allowed_cmd_scsi scsi; + struct mpi3_allowed_cmd_ata ata; + struct mpi3_allowed_cmd_nvme nvme; +}; + +#define MPI3_DRIVER_ALLOWEDCMD_CMDFLAGS_ADMINRAIDPD_BLOCKED (0x20) +#define MPI3_DRIVER_ALLOWEDCMD_CMDFLAGS_OOBRAIDPD_BLOCKED (0x10) +#define MPI3_DRIVER_ALLOWEDCMD_CMDFLAGS_OOBRAIDVD_BLOCKED (0x08) +#define MPI3_DRIVER_ALLOWEDCMD_CMDFLAGS_OOBADVHOSTPD_BLOCKED (0x04) +#define MPI3_DRIVER_ALLOWEDCMD_CMDFLAGS_OOBHOSTPD_BLOCKED (0x02) +#define MPI3_DRIVER_ALLOWEDCMD_CMDFLAGS_CHECKSUBCMD_ENABLED (0x01) +#ifndef MPI3_ALLOWED_CMDS_MAX +#define MPI3_ALLOWED_CMDS_MAX (1) +#endif +struct mpi3_driver_page0 { struct mpi3_config_page_header header; __le32 bsd_options; u8 ssu_timeout; @@ -1026,13 +1135,122 @@ struct mpi3_uefibsd_page0 { __le32 reserved18; }; -#define MPI3_UEFIBSD_PAGEVERSION (0x00) -#define MPI3_UEFIBSD_BSDOPTS_REGISTRATION_MASK (0x00000003) -#define MPI3_UEFIBSD_BSDOPTS_REGISTRATION_IOC_AND_DEVS (0x00000000) -#define MPI3_UEFIBSD_BSDOPTS_REGISTRATION_IOC_ONLY (0x00000001) -#define MPI3_UEFIBSD_BSDOPTS_REGISTRATION_NONE (0x00000002) -#define MPI3_UEFIBSD_BSDOPTS_DIS_HII_CONFIG_UTIL (0x00000004) -#define MPI3_UEFIBSD_BSDOPTS_EN_ADV_ADAPTER_CONFIG (0x00000008) +#define MPI3_DRIVER0_PAGEVERSION (0x00) +#define MPI3_DRIVER0_BSDOPTS_REGISTRATION_MASK (0x00000003) +#define MPI3_DRIVER0_BSDOPTS_REGISTRATION_IOC_AND_DEVS (0x00000000) +#define MPI3_DRIVER0_BSDOPTS_REGISTRATION_IOC_ONLY (0x00000001) +#define MPI3_DRIVER0_BSDOPTS_DIS_HII_CONFIG_UTIL (0x00000004) +#define MPI3_DRIVER0_BSDOPTS_EN_ADV_ADAPTER_CONFIG (0x00000008) +struct mpi3_driver_page1 { + struct mpi3_config_page_header header; + __le32 flags; + __le32 reserved0c; + __le16 host_diag_trace_max_size; + __le16 host_diag_trace_min_size; + __le16 host_diag_trace_decrement_size; + __le16 reserved16; + __le16 host_diag_fw_max_size; + __le16 host_diag_fw_min_size; + __le16 host_diag_fw_decrement_size; + __le16 reserved1e; + __le16 host_diag_driver_max_size; + __le16 host_diag_driver_min_size; + __le16 host_diag_driver_decrement_size; + __le16 reserved26; +}; + +#define MPI3_DRIVER1_PAGEVERSION (0x00) +#ifndef MPI3_DRIVER2_TRIGGER_MAX +#define MPI3_DRIVER2_TRIGGER_MAX (1) +#endif +struct mpi3_driver2_trigger_event { + u8 type; + u8 flags; + u8 reserved02; + u8 event; + __le32 reserved04[3]; +}; + +struct mpi3_driver2_trigger_scsi_sense { + u8 type; + u8 flags; + __le16 reserved02; + u8 ascq; + u8 asc; + u8 sense_key; + u8 reserved07; + __le32 reserved08[2]; +}; + +#define MPI3_DRIVER2_TRIGGER_SCSI_SENSE_ASCQ_MATCH_ALL (0xff) +#define MPI3_DRIVER2_TRIGGER_SCSI_SENSE_ASC_MATCH_ALL (0xff) +#define MPI3_DRIVER2_TRIGGER_SCSI_SENSE_SENSE_KEY_MATCH_ALL (0xff) +struct mpi3_driver2_trigger_reply { + u8 type; + u8 flags; + __le16 ioc_status; + __le32 ioc_log_info; + __le32 ioc_log_info_mask; + __le32 reserved0c; +}; + +#define MPI3_DRIVER2_TRIGGER_REPLY_IOCSTATUS_MATCH_ALL (0xffff) +union mpi3_driver2_trigger_element { + struct mpi3_driver2_trigger_event event; + struct mpi3_driver2_trigger_scsi_sense scsi_sense; + struct mpi3_driver2_trigger_reply reply; +}; + +#define MPI3_DRIVER2_TRIGGER_TYPE_EVENT (0x00) +#define MPI3_DRIVER2_TRIGGER_TYPE_SCSI_SENSE (0x01) +#define MPI3_DRIVER2_TRIGGER_TYPE_REPLY (0x02) +#define MPI3_DRIVER2_TRIGGER_FLAGS_DIAG_TRACE_RELEASE (0x02) +#define MPI3_DRIVER2_TRIGGER_FLAGS_DIAG_FW_RELEASE (0x01) +struct mpi3_driver_page2 { + struct mpi3_config_page_header header; + __le64 master_trigger; + __le32 reserved10[3]; + u8 num_triggers; + u8 reserved1d[3]; + union mpi3_driver2_trigger_element trigger[MPI3_DRIVER2_TRIGGER_MAX]; +}; + +#define MPI3_DRIVER2_PAGEVERSION (0x00) +#define MPI3_DRIVER2_MASTERTRIGGER_DIAG_TRACE_RELEASE (0x8000000000000000ULL) +#define MPI3_DRIVER2_MASTERTRIGGER_DIAG_FW_RELEASE (0x4000000000000000ULL) +#define MPI3_DRIVER2_MASTERTRIGGER_SNAPDUMP (0x2000000000000000ULL) +#define MPI3_DRIVER2_MASTERTRIGGER_DEVICE_REMOVAL_ENABLED (0x0000000000000004ULL) +#define MPI3_DRIVER2_MASTERTRIGGER_TASK_MANAGEMENT_ENABLED (0x0000000000000002ULL) +struct mpi3_driver_page10 { + struct mpi3_config_page_header header; + __le16 flags; + __le16 reserved0a; + u8 num_allowed_commands; + u8 reserved0d[3]; + union mpi3_allowed_cmd allowed_command[MPI3_ALLOWED_CMDS_MAX]; +}; + +#define MPI3_DRIVER10_PAGEVERSION (0x00) +struct mpi3_driver_page20 { + struct mpi3_config_page_header header; + __le16 flags; + __le16 reserved0a; + u8 num_allowed_commands; + u8 reserved0d[3]; + union mpi3_allowed_cmd allowed_command[MPI3_ALLOWED_CMDS_MAX]; +}; + +#define MPI3_DRIVER20_PAGEVERSION (0x00) +struct mpi3_driver_page30 { + struct mpi3_config_page_header header; + __le16 flags; + __le16 reserved0a; + u8 num_allowed_commands; + u8 reserved0d[3]; + union mpi3_allowed_cmd allowed_command[MPI3_ALLOWED_CMDS_MAX]; +}; + +#define MPI3_DRIVER30_PAGEVERSION (0x00) union mpi3_security_mac { __le32 dword[16]; __le16 word[32]; @@ -1102,7 +1320,7 @@ struct mpi3_security1_key_record { #define MPI3_SECURITY1_KEY_RECORD_CONSUMER_NOT_VALID (0x00) #define MPI3_SECURITY1_KEY_RECORD_CONSUMER_SAFESTORE (0x01) #define MPI3_SECURITY1_KEY_RECORD_CONSUMER_CERT_CHAIN (0x02) -#define MPI3_SECURITY1_KEY_RECORD_CONSUMER_AUTH_DEV_KEY (0x03) +#define MPI3_SECURITY1_KEY_RECORD_CONSUMER_DEVICE_KEY (0x03) #define MPI3_SECURITY1_KEY_RECORD_CONSUMER_CACHE_OFFLOAD (0x04) struct mpi3_security_page1 { struct mpi3_config_page_header header; @@ -1137,16 +1355,30 @@ struct mpi3_sas_io_unit_page0 { struct mpi3_config_page_header header; __le32 reserved08; u8 num_phys; - u8 reserved0d[3]; + u8 init_status; + __le16 reserved0e; struct mpi3_sas_io_unit0_phy_data phy_data[MPI3_SAS_IO_UNIT0_PHY_MAX]; }; -#define MPI3_SASIOUNIT0_PAGEVERSION (0x00) -#define MPI3_SASIOUNIT0_PORTFLAGS_DISC_IN_PROGRESS (0x08) -#define MPI3_SASIOUNIT0_PORTFLAGS_AUTO_PORT_CONFIG (0x01) -#define MPI3_SASIOUNIT0_PHYFLAGS_INIT_PERSIST_CONNECT (0x40) -#define MPI3_SASIOUNIT0_PHYFLAGS_TARG_PERSIST_CONNECT (0x20) -#define MPI3_SASIOUNIT0_PHYFLAGS_PHY_DISABLED (0x08) +#define MPI3_SASIOUNIT0_PAGEVERSION (0x00) +#define MPI3_SASIOUNIT0_INITSTATUS_NO_ERRORS (0x00) +#define MPI3_SASIOUNIT0_INITSTATUS_NEEDS_INITIALIZATION (0x01) +#define MPI3_SASIOUNIT0_INITSTATUS_NO_TARGETS_ALLOCATED (0x02) +#define MPI3_SASIOUNIT0_INITSTATUS_BAD_NUM_PHYS (0x04) +#define MPI3_SASIOUNIT0_INITSTATUS_UNSUPPORTED_CONFIG (0x05) +#define MPI3_SASIOUNIT0_INITSTATUS_HOST_PHYS_ENABLED (0x06) +#define MPI3_SASIOUNIT0_INITSTATUS_PRODUCT_SPECIFIC_MIN (0xf0) +#define MPI3_SASIOUNIT0_INITSTATUS_PRODUCT_SPECIFIC_MAX (0xff) +#define MPI3_SASIOUNIT0_PORTFLAGS_DISC_IN_PROGRESS (0x08) +#define MPI3_SASIOUNIT0_PORTFLAGS_AUTO_PORT_CONFIG_MASK (0x03) +#define MPI3_SASIOUNIT0_PORTFLAGS_AUTO_PORT_CONFIG_IOUNIT1 (0x00) +#define MPI3_SASIOUNIT0_PORTFLAGS_AUTO_PORT_CONFIG_DYNAMIC (0x01) +#define MPI3_SASIOUNIT0_PORTFLAGS_AUTO_PORT_CONFIG_BACKPLANE (0x02) +#define MPI3_SASIOUNIT0_PHYFLAGS_INIT_PERSIST_CONNECT (0x40) +#define MPI3_SASIOUNIT0_PHYFLAGS_TARG_PERSIST_CONNECT (0x20) +#define MPI3_SASIOUNIT0_PHYFLAGS_PHY_DISABLED (0x08) +#define MPI3_SASIOUNIT0_PHYFLAGS_VIRTUAL_PHY (0x02) +#define MPI3_SASIOUNIT0_PHYFLAGS_HOST_PHY (0x01) struct mpi3_sas_io_unit1_phy_data { u8 io_unit_port; u8 port_flags; @@ -1343,6 +1575,26 @@ struct mpi3_sas_expander_page1 { #define MPI3_SASEXPANDER1_DISCINFO_BAD_PHY_DISABLED (0x04) #define MPI3_SASEXPANDER1_DISCINFO_LINK_STATUS_CHANGE (0x02) #define MPI3_SASEXPANDER1_DISCINFO_NO_ROUTING_ENTRIES (0x01) +#ifndef MPI3_SASEXPANDER2_MAX_NUM_PHYS +#define MPI3_SASEXPANDER2_MAX_NUM_PHYS (1) +#endif +struct mpi3_sasexpander2_phy_element { + u8 link_change_count; + u8 reserved01; + __le16 rate_change_count; + __le32 reserved04; +}; + +struct mpi3_sas_expander_page2 { + struct mpi3_config_page_header header; + u8 num_phys; + u8 reserved09; + __le16 dev_handle; + __le32 reserved0c; + struct mpi3_sasexpander2_phy_element phy[MPI3_SASEXPANDER2_MAX_NUM_PHYS]; +}; + +#define MPI3_SASEXPANDER2_PAGEVERSION (0x00) struct mpi3_sas_port_page0 { struct mpi3_config_page_header header; u8 port_number; @@ -1510,6 +1762,14 @@ struct mpi3_sas_phy_page4 { #define MPI3_PCIE_NEG_LINK_RATE_8_0 (0x04) #define MPI3_PCIE_NEG_LINK_RATE_16_0 (0x05) #define MPI3_PCIE_NEG_LINK_RATE_32_0 (0x06) +#define MPI3_PCIE_ASPM_ENABLE_NONE (0x0) +#define MPI3_PCIE_ASPM_ENABLE_L0S (0x1) +#define MPI3_PCIE_ASPM_ENABLE_L1 (0x2) +#define MPI3_PCIE_ASPM_ENABLE_L0S_L1 (0x3) +#define MPI3_PCIE_ASPM_SUPPORT_NONE (0x0) +#define MPI3_PCIE_ASPM_SUPPORT_L0S (0x1) +#define MPI3_PCIE_ASPM_SUPPORT_L1 (0x2) +#define MPI3_PCIE_ASPM_SUPPORT_L0S_L1 (0x3) struct mpi3_pcie_io_unit0_phy_data { u8 link; u8 link_flags; @@ -1540,7 +1800,8 @@ struct mpi3_pcie_io_unit_page0 { __le32 reserved08; u8 num_phys; u8 init_status; - __le16 reserved0e; + u8 aspm; + u8 reserved0f; struct mpi3_pcie_io_unit0_phy_data phy_data[MPI3_PCIE_IO_UNIT0_PHY_MAX]; }; @@ -1556,6 +1817,14 @@ struct mpi3_pcie_io_unit_page0 { #define MPI3_PCIEIOUNIT0_INITSTATUS_BAD_CLOCKING_MODE (0x08) #define MPI3_PCIEIOUNIT0_INITSTATUS_PROD_SPEC_START (0xf0) #define MPI3_PCIEIOUNIT0_INITSTATUS_PROD_SPEC_END (0xff) +#define MPI3_PCIEIOUNIT0_ASPM_SWITCH_STATES_MASK (0xc0) +#define MPI3_PCIEIOUNIT0_ASPM_SWITCH_STATES_SHIFT (6) +#define MPI3_PCIEIOUNIT0_ASPM_DIRECT_STATES_MASK (0x30) +#define MPI3_PCIEIOUNIT0_ASPM_DIRECT_STATES_SHIFT (4) +#define MPI3_PCIEIOUNIT0_ASPM_SWITCH_SUPPORT_MASK (0x0c) +#define MPI3_PCIEIOUNIT0_ASPM_SWITCH_SUPPORT_SHIFT (2) +#define MPI3_PCIEIOUNIT0_ASPM_DIRECT_SUPPORT_MASK (0x03) +#define MPI3_PCIEIOUNIT0_ASPM_DIRECT_SUPPORT_SHIFT (0) struct mpi3_pcie_io_unit1_phy_data { u8 link; u8 link_flags; @@ -1569,16 +1838,16 @@ struct mpi3_pcie_io_unit1_phy_data { #define MPI3_PCIEIOUNIT1_LINKFLAGS_PCIE_CLK_MODE_DIS_SEPARATE_REFCLK (0x00) #define MPI3_PCIEIOUNIT1_LINKFLAGS_PCIE_CLK_MODE_EN_SRIS (0x01) #define MPI3_PCIEIOUNIT1_LINKFLAGS_PCIE_CLK_MODE_EN_SRNS (0x02) -#define MPI3_PCIEIOUNIT1_PHYFLAGS_PHY_DISABLE (0x08) -#define MPI3_PCIEIOUNIT1_MMLR_MAX_RATE_MASK (0xf0) -#define MPI3_PCIEIOUNIT1_MMLR_MAX_RATE_SHIFT (4) -#define MPI3_PCIEIOUNIT1_MMLR_MAX_RATE_2_5 (0x20) -#define MPI3_PCIEIOUNIT1_MMLR_MAX_RATE_5_0 (0x30) -#define MPI3_PCIEIOUNIT1_MMLR_MAX_RATE_8_0 (0x40) -#define MPI3_PCIEIOUNIT1_MMLR_MAX_RATE_16_0 (0x50) -#define MPI3_PCIEIOUNIT1_MMLR_MAX_RATE_32_0 (0x60) +#define MPI3_PCIEIOUNIT1_PHYFLAGS_PHY_DISABLE (0x08) +#define MPI3_PCIEIOUNIT1_MMLR_MAX_RATE_MASK (0xf0) +#define MPI3_PCIEIOUNIT1_MMLR_MAX_RATE_SHIFT (4) +#define MPI3_PCIEIOUNIT1_MMLR_MAX_RATE_2_5 (0x20) +#define MPI3_PCIEIOUNIT1_MMLR_MAX_RATE_5_0 (0x30) +#define MPI3_PCIEIOUNIT1_MMLR_MAX_RATE_8_0 (0x40) +#define MPI3_PCIEIOUNIT1_MMLR_MAX_RATE_16_0 (0x50) +#define MPI3_PCIEIOUNIT1_MMLR_MAX_RATE_32_0 (0x60) #ifndef MPI3_PCIE_IO_UNIT1_PHY_MAX -#define MPI3_PCIE_IO_UNIT1_PHY_MAX (1) +#define MPI3_PCIE_IO_UNIT1_PHY_MAX (1) #endif struct mpi3_pcie_io_unit_page1 { struct mpi3_config_page_header header; @@ -1586,21 +1855,66 @@ struct mpi3_pcie_io_unit_page1 { __le32 reserved0c; u8 num_phys; u8 reserved11; - __le16 reserved12; + u8 aspm; + u8 reserved13; struct mpi3_pcie_io_unit1_phy_data phy_data[MPI3_PCIE_IO_UNIT1_PHY_MAX]; }; -#define MPI3_PCIEIOUNIT1_PAGEVERSION (0x00) +#define MPI3_PCIEIOUNIT1_PAGEVERSION (0x00) +#define MPI3_PCIEIOUNIT1_CONTROL_FLAGS_LINK_OVERRIDE_DISABLE (0x80) +#define MPI3_PCIEIOUNIT1_CONTROL_FLAGS_CLOCK_OVERRIDE_DISABLE (0x40) +#define MPI3_PCIEIOUNIT1_CONTROL_FLAGS_CLOCK_OVERRIDE_MODE_MASK (0x30) +#define MPI3_PCIEIOUNIT1_CONTROL_FLAGS_CLOCK_OVERRIDE_MODE_SHIFT (4) +#define MPI3_PCIEIOUNIT1_CONTROL_FLAGS_CLOCK_OVERRIDE_MODE_SRIS_SRNS_DISABLED (0x00) +#define MPI3_PCIEIOUNIT1_CONTROL_FLAGS_CLOCK_OVERRIDE_MODE_SRIS_ENABLED (0x10) +#define MPI3_PCIEIOUNIT1_CONTROL_FLAGS_CLOCK_OVERRIDE_MODE_SRNS_ENABLED (0x20) +#define MPI3_PCIEIOUNIT1_CONTROL_FLAGS_LINK_RATE_OVERRIDE_MASK (0x0f) +#define MPI3_PCIEIOUNIT1_CONTROL_FLAGS_LINK_RATE_OVERRIDE_MAX_2_5 (0x02) +#define MPI3_PCIEIOUNIT1_CONTROL_FLAGS_LINK_RATE_OVERRIDE_MAX_5_0 (0x03) +#define MPI3_PCIEIOUNIT1_CONTROL_FLAGS_LINK_RATE_OVERRIDE_MAX_8_0 (0x04) +#define MPI3_PCIEIOUNIT1_CONTROL_FLAGS_LINK_RATE_OVERRIDE_MAX_16_0 (0x05) +#define MPI3_PCIEIOUNIT1_CONTROL_FLAGS_LINK_RATE_OVERRIDE_MAX_32_0 (0x06) +#define MPI3_PCIEIOUNIT1_ASPM_SWITCH_MASK (0x0c) +#define MPI3_PCIEIOUNIT1_ASPM_SWITCH_SHIFT (2) +#define MPI3_PCIEIOUNIT1_ASPM_DIRECT_MASK (0x03) +#define MPI3_PCIEIOUNIT1_ASPM_DIRECT_SHIFT (0) struct mpi3_pcie_io_unit_page2 { struct mpi3_config_page_header header; - __le16 nv_me_max_queue_depth; - __le16 reserved0a; - u8 nv_me_abort_to; + __le16 nvme_max_q_dx1; + __le16 nvme_max_q_dx2; + u8 nvme_abort_to; u8 reserved0d; - __le16 reserved0e; + __le16 nvme_max_q_dx4; }; #define MPI3_PCIEIOUNIT2_PAGEVERSION (0x00) +#define MPI3_PCIEIOUNIT3_ERROR_RECEIVER_ERROR (0) +#define MPI3_PCIEIOUNIT3_ERROR_RECOVERY (1) +#define MPI3_PCIEIOUNIT3_ERROR_CORRECTABLE_ERROR_MSG (2) +#define MPI3_PCIEIOUNIT3_ERROR_BAD_DLLP (3) +#define MPI3_PCIEIOUNIT3_ERROR_BAD_TLP (4) +#define MPI3_PCIEIOUNIT3_NUM_ERROR_INDEX (5) +struct mpi3_pcie_io_unit3_error { + __le16 threshold_count; + __le16 reserved02; +}; + +struct mpi3_pcie_io_unit_page3 { + struct mpi3_config_page_header header; + u8 threshold_window; + u8 threshold_action; + u8 escalation_count; + u8 escalation_action; + u8 num_errors; + u8 reserved0d[3]; + struct mpi3_pcie_io_unit3_error error[MPI3_PCIEIOUNIT3_NUM_ERROR_INDEX]; +}; + +#define MPI3_PCIEIOUNIT3_PAGEVERSION (0x00) +#define MPI3_PCIEIOUNIT3_ACTION_NO_ACTION (0x00) +#define MPI3_PCIEIOUNIT3_ACTION_HOT_RESET (0x01) +#define MPI3_PCIEIOUNIT3_ACTION_REDUCE_LINK_RATE_ONLY (0x02) +#define MPI3_PCIEIOUNIT3_ACTION_REDUCE_LINK_RATE_NO_ACCESS (0x03) struct mpi3_pcie_switch_page0 { struct mpi3_config_page_header header; u8 io_unit_port; @@ -1609,7 +1923,7 @@ struct mpi3_pcie_switch_page0 { __le16 dev_handle; __le16 parent_dev_handle; u8 num_ports; - u8 pc_ie_level; + u8 pcie_level; __le16 reserved12; __le32 reserved14; __le32 reserved18; @@ -1623,7 +1937,8 @@ struct mpi3_pcie_switch_page0 { struct mpi3_pcie_switch_page1 { struct mpi3_config_page_header header; u8 io_unit_port; - u8 reserved09[3]; + u8 flags; + __le16 reserved0a; u8 num_ports; u8 port_num; __le16 attached_dev_handle; @@ -1636,15 +1951,43 @@ struct mpi3_pcie_switch_page1 { }; #define MPI3_PCIESWITCH1_PAGEVERSION (0x00) +#define MPI3_PCIESWITCH1_FLAGS_ASPMSTATE_MASK (0x0c) +#define MPI3_PCIESWITCH1_FLAGS_ASPMSTATE_SHIFT (2) +#define MPI3_PCIESWITCH1_FLAGS_ASPMSUPPORT_MASK (0x03) +#define MPI3_PCIESWITCH1_FLAGS_ASPMSUPPORT_SHIFT (0) +#ifndef MPI3_PCIESWITCH2_MAX_NUM_PORTS +#define MPI3_PCIESWITCH2_MAX_NUM_PORTS (1) +#endif +struct mpi3_pcieswitch2_port_element { + __le16 link_change_count; + __le16 rate_change_count; + __le32 reserved04; +}; + +struct mpi3_pcie_switch_page2 { + struct mpi3_config_page_header header; + u8 num_ports; + u8 reserved09; + __le16 dev_handle; + __le32 reserved0c; + struct mpi3_pcieswitch2_port_element port[MPI3_PCIESWITCH2_MAX_NUM_PORTS]; +}; + +#define MPI3_PCIESWITCH2_PAGEVERSION (0x00) struct mpi3_pcie_link_page0 { struct mpi3_config_page_header header; u8 link; u8 reserved09[3]; - __le32 correctable_error_count; - __le16 n_fatal_error_count; - __le16 reserved12; - __le16 fatal_error_count; - __le16 reserved16; + __le32 reserved0c; + __le32 receiver_error_count; + __le32 recovery_count; + __le32 corr_error_msg_count; + __le32 non_fatal_error_msg_count; + __le32 fatal_error_msg_count; + __le32 non_fatal_error_count; + __le32 fatal_error_count; + __le32 bad_dllp_count; + __le32 bad_tlp_count; }; #define MPI3_PCIELINK0_PAGEVERSION (0x00) @@ -1654,11 +1997,12 @@ struct mpi3_enclosure_page0 { __le16 flags; __le16 enclosure_handle; __le16 num_slots; - __le16 start_slot; + __le16 reserved16; u8 io_unit_port; u8 enclosure_level; __le16 sep_dev_handle; - __le32 reserved1c; + u8 chassis_slot; + u8 reserved1d[3]; }; #define MPI3_ENCLOSURE0_PAGEVERSION (0x00) @@ -1666,6 +2010,7 @@ struct mpi3_enclosure_page0 { #define MPI3_ENCLS0_FLAGS_ENCL_TYPE_VIRTUAL (0x0000) #define MPI3_ENCLS0_FLAGS_ENCL_TYPE_SAS (0x4000) #define MPI3_ENCLS0_FLAGS_ENCL_TYPE_PCIE (0x8000) +#define MPI3_ENCLS0_FLAGS_CHASSIS_SLOT_VALID (0x0020) #define MPI3_ENCLS0_FLAGS_ENCL_DEV_PRESENT_MASK (0x0010) #define MPI3_ENCLS0_FLAGS_ENCL_DEV_NOT_FOUND (0x0000) #define MPI3_ENCLS0_FLAGS_ENCL_DEV_PRESENT (0x0010) @@ -1686,6 +2031,7 @@ struct mpi3_device0_sas_sata_format { u8 zone_group; }; +#define MPI3_DEVICE0_SASSATA_FLAGS_WRITE_SAME_UNMAP_NCQ (0x0400) #define MPI3_DEVICE0_SASSATA_FLAGS_SLUMBER_CAP (0x0200) #define MPI3_DEVICE0_SASSATA_FLAGS_PARTIAL_CAP (0x0100) #define MPI3_DEVICE0_SASSATA_FLAGS_ASYNC_NOTIFY (0x0080) @@ -1707,10 +2053,11 @@ struct mpi3_device0_pcie_format { __le32 maximum_data_transfer_size; __le32 capabilities; __le16 noiob; - u8 nv_me_abort_to; + u8 nvme_abort_to; u8 page_size; __le16 shutdown_latency; - __le16 reserved16; + u8 recovery_info; + u8 reserved17; }; #define MPI3_DEVICE0_PCIE_LINK_RATE_32_0_SUPP (0x10) @@ -1718,16 +2065,38 @@ struct mpi3_device0_pcie_format { #define MPI3_DEVICE0_PCIE_LINK_RATE_8_0_SUPP (0x04) #define MPI3_DEVICE0_PCIE_LINK_RATE_5_0_SUPP (0x02) #define MPI3_DEVICE0_PCIE_LINK_RATE_2_5_SUPP (0x01) -#define MPI3_DEVICE0_PCIE_DEVICE_INFO_TYPE_MASK (0x0003) +#define MPI3_DEVICE0_PCIE_DEVICE_INFO_TYPE_MASK (0x0007) #define MPI3_DEVICE0_PCIE_DEVICE_INFO_TYPE_NO_DEVICE (0x0000) #define MPI3_DEVICE0_PCIE_DEVICE_INFO_TYPE_NVME_DEVICE (0x0001) #define MPI3_DEVICE0_PCIE_DEVICE_INFO_TYPE_SWITCH_DEVICE (0x0002) #define MPI3_DEVICE0_PCIE_DEVICE_INFO_TYPE_SCSI_DEVICE (0x0003) +#define MPI3_DEVICE0_PCIE_DEVICE_INFO_ASPM_MASK (0x0030) +#define MPI3_DEVICE0_PCIE_DEVICE_INFO_ASPM_SHIFT (4) +#define MPI3_DEVICE0_PCIE_DEVICE_INFO_PITYPE_MASK (0x00c0) +#define MPI3_DEVICE0_PCIE_DEVICE_INFO_PITYPE_SHIFT (6) +#define MPI3_DEVICE0_PCIE_DEVICE_INFO_PITYPE_0 (0x0000) +#define MPI3_DEVICE0_PCIE_DEVICE_INFO_PITYPE_1 (0x0040) +#define MPI3_DEVICE0_PCIE_DEVICE_INFO_PITYPE_2 (0x0080) +#define MPI3_DEVICE0_PCIE_DEVICE_INFO_PITYPE_3 (0x00c0) +#define MPI3_DEVICE0_PCIE_CAP_SGL_EXTRA_LENGTH_SUPPORTED (0x00000020) #define MPI3_DEVICE0_PCIE_CAP_METADATA_SEPARATED (0x00000010) #define MPI3_DEVICE0_PCIE_CAP_SGL_DWORD_ALIGN_REQUIRED (0x00000008) -#define MPI3_DEVICE0_PCIE_CAP_NVME_SGL_ENABLED (0x00000004) +#define MPI3_DEVICE0_PCIE_CAP_SGL_FORMAT_SGL (0x00000004) +#define MPI3_DEVICE0_PCIE_CAP_SGL_FORMAT_PRP (0x00000000) #define MPI3_DEVICE0_PCIE_CAP_BIT_BUCKET_SGL_SUPP (0x00000002) #define MPI3_DEVICE0_PCIE_CAP_SGL_SUPP (0x00000001) +#define MPI3_DEVICE0_PCIE_CAP_ASPM_MASK (0x000000c0) +#define MPI3_DEVICE0_PCIE_CAP_ASPM_SHIFT (6) +#define MPI3_DEVICE0_PCIE_RECOVER_METHOD_MASK (0xe0) +#define MPI3_DEVICE0_PCIE_RECOVER_METHOD_NS_MGMT (0x00) +#define MPI3_DEVICE0_PCIE_RECOVER_METHOD_FORMAT (0x20) +#define MPI3_DEVICE0_PCIE_RECOVER_REASON_MASK (0x1f) +#define MPI3_DEVICE0_PCIE_RECOVER_REASON_NO_NS (0x00) +#define MPI3_DEVICE0_PCIE_RECOVER_REASON_NO_NSID_1 (0x01) +#define MPI3_DEVICE0_PCIE_RECOVER_REASON_TOO_MANY_NS (0x02) +#define MPI3_DEVICE0_PCIE_RECOVER_REASON_PROTECTION (0x03) +#define MPI3_DEVICE0_PCIE_RECOVER_REASON_METADATA_SZ (0x04) +#define MPI3_DEVICE0_PCIE_RECOVER_REASON_LBA_DATA_SZ (0x05) struct mpi3_device0_vd_format { u8 vd_state; u8 raid_level; @@ -1783,6 +2152,8 @@ struct mpi3_device_page0 { }; #define MPI3_DEVICE0_PAGEVERSION (0x00) +#define MPI3_DEVICE0_PARENT_INVALID (0xffff) +#define MPI3_DEVICE0_ENCLOSURE_HANDLE_NO_ENCLOSURE (0x0000) #define MPI3_DEVICE0_WWID_INVALID (0xffffffffffffffff) #define MPI3_DEVICE0_PERSISTENTID_INVALID (0xffff) #define MPI3_DEVICE0_IOUNITPORT_INVALID (0xff) @@ -1792,9 +2163,13 @@ struct mpi3_device_page0 { #define MPI3_DEVICE0_ASTATUS_DEVICE_BLOCKED (0x03) #define MPI3_DEVICE0_ASTATUS_UNAUTHORIZED (0x04) #define MPI3_DEVICE0_ASTATUS_DEVICE_MISSING_DELAY (0x05) +#define MPI3_DEVICE0_ASTATUS_PREPARE (0x06) +#define MPI3_DEVICE0_ASTATUS_SAFE_MODE (0x07) +#define MPI3_DEVICE0_ASTATUS_GENERIC_MAX (0x0f) #define MPI3_DEVICE0_ASTATUS_SAS_UNKNOWN (0x10) #define MPI3_DEVICE0_ASTATUS_ROUTE_NOT_ADDRESSABLE (0x11) #define MPI3_DEVICE0_ASTATUS_SMP_ERROR_NOT_ADDRESSABLE (0x12) +#define MPI3_DEVICE0_ASTATUS_SAS_MAX (0x1f) #define MPI3_DEVICE0_ASTATUS_SIF_UNKNOWN (0x20) #define MPI3_DEVICE0_ASTATUS_SIF_AFFILIATION_CONFLICT (0x21) #define MPI3_DEVICE0_ASTATUS_SIF_DIAG (0x22) @@ -1810,6 +2185,8 @@ struct mpi3_device_page0 { #define MPI3_DEVICE0_ASTATUS_PCIE_MEM_SPACE_ACCESS (0x31) #define MPI3_DEVICE0_ASTATUS_PCIE_UNSUPPORTED (0x32) #define MPI3_DEVICE0_ASTATUS_PCIE_MSIX_REQUIRED (0x33) +#define MPI3_DEVICE0_ASTATUS_PCIE_ECRC_REQUIRED (0x34) +#define MPI3_DEVICE0_ASTATUS_PCIE_MAX (0x3f) #define MPI3_DEVICE0_ASTATUS_NVME_UNKNOWN (0x40) #define MPI3_DEVICE0_ASTATUS_NVME_READY_TIMEOUT (0x41) #define MPI3_DEVICE0_ASTATUS_NVME_DEVCFG_UNSUPPORTED (0x42) @@ -1820,7 +2197,17 @@ struct mpi3_device_page0 { #define MPI3_DEVICE0_ASTATUS_NVME_GET_FEATURE_STAT_FAILED (0x47) #define MPI3_DEVICE0_ASTATUS_NVME_IDLE_TIMEOUT (0x48) #define MPI3_DEVICE0_ASTATUS_NVME_CTRL_FAILURE_STATUS (0x49) -#define MPI3_DEVICE0_ASTATUS_VD_UNKNOWN (0x50) +#define MPI3_DEVICE0_ASTATUS_NVME_INSUFFICIENT_POWER (0x4a) +#define MPI3_DEVICE0_ASTATUS_NVME_DOORBELL_STRIDE (0x4b) +#define MPI3_DEVICE0_ASTATUS_NVME_MEM_PAGE_MIN_SIZE (0x4c) +#define MPI3_DEVICE0_ASTATUS_NVME_MEMORY_ALLOCATION (0x4d) +#define MPI3_DEVICE0_ASTATUS_NVME_COMPLETION_TIME (0x4e) +#define MPI3_DEVICE0_ASTATUS_NVME_BAR (0x4f) +#define MPI3_DEVICE0_ASTATUS_NVME_NS_DESCRIPTOR (0x50) +#define MPI3_DEVICE0_ASTATUS_NVME_INCOMPATIBLE_SETTINGS (0x51) +#define MPI3_DEVICE0_ASTATUS_NVME_MAX (0x5f) +#define MPI3_DEVICE0_ASTATUS_VD_UNKNOWN (0x80) +#define MPI3_DEVICE0_ASTATUS_VD_MAX (0x8f) #define MPI3_DEVICE0_FLAGS_CONTROLLER_DEV_HANDLE (0x0080) #define MPI3_DEVICE0_FLAGS_HIDDEN (0x0008) #define MPI3_DEVICE0_FLAGS_ATT_METHOD_MASK (0x0006) @@ -1870,11 +2257,17 @@ struct mpi3_device_page1 { struct mpi3_config_page_header header; __le16 dev_handle; __le16 reserved0a; - __le32 reserved0c[12]; + __le16 link_change_count; + __le16 rate_change_count; + __le16 tm_count; + __le16 reserved12; + __le32 reserved14[10]; u8 reserved3c[3]; u8 device_form; union mpi3_device1_dev_spec_format device_specific; }; #define MPI3_DEVICE1_PAGEVERSION (0x00) +#define MPI3_DEVICE1_COUNTER_MAX (0xfffe) +#define MPI3_DEVICE1_COUNTER_INVALID (0xffff) #endif diff --git a/drivers/scsi/mpi3mr/mpi/mpi30_image.h b/drivers/scsi/mpi3mr/mpi/mpi30_image.h index 169e4f9b7b7c..c29b87de8e18 100644 --- a/drivers/scsi/mpi3mr/mpi/mpi30_image.h +++ b/drivers/scsi/mpi3mr/mpi/mpi30_image.h @@ -61,6 +61,8 @@ struct mpi3_component_image_header { #define MPI3_IMAGE_HEADER_SIGNATURE1_SPD (0x20445053) #define MPI3_IMAGE_HEADER_SIGNATURE1_GAS_GAUGE (0x20534147) #define MPI3_IMAGE_HEADER_SIGNATURE1_PBLP (0x504c4250) +#define MPI3_IMAGE_HEADER_SIGNATURE1_MANIFEST (0x464e414d) +#define MPI3_IMAGE_HEADER_SIGNATURE1_OEM (0x204d454f) #define MPI3_IMAGE_HEADER_SIGNATURE2_VALUE (0x50584546) #define MPI3_IMAGE_HEADER_FLAGS_DEVICE_KEY_BASIS_MASK (0x00000030) #define MPI3_IMAGE_HEADER_FLAGS_DEVICE_KEY_BASIS_CDI (0x00000000) @@ -94,6 +96,61 @@ struct mpi3_component_image_header { #define MPI3_IMAGE_HEADER_HASH_EXCLUSION_OFFSET (0x5c) #define MPI3_IMAGE_HEADER_NEXT_IMAGE_HEADER_OFFSET_OFFSET (0x7c) #define MPI3_IMAGE_HEADER_SIZE (0x100) +#ifndef MPI3_CI_MANIFEST_MPI_MAX +#define MPI3_CI_MANIFEST_MPI_MAX (1) +#endif +struct mpi3_ci_manifest_mpi_comp_image_ref { + __le32 signature1; + __le32 reserved04[3]; + struct mpi3_comp_image_version component_image_version; + __le32 component_image_version_string_offset; + __le32 crc; +}; + +struct mpi3_ci_manifest_mpi { + u8 manifest_type; + u8 reserved01[3]; + __le32 reserved04[3]; + u8 num_image_references; + u8 release_level; + __le16 reserved12; + __le16 reserved14; + __le16 flags; + __le32 reserved18[2]; + __le16 vendor_id; + __le16 device_id; + __le16 subsystem_vendor_id; + __le16 subsystem_id; + __le32 reserved28[2]; + union mpi3_version_union package_security_version; + __le32 reserved34; + struct mpi3_comp_image_version package_version; + __le32 package_version_string_offset; + __le32 package_build_date_string_offset; + __le32 package_build_time_string_offset; + __le32 reserved4c; + __le32 diag_authorization_identifier[16]; + struct mpi3_ci_manifest_mpi_comp_image_ref component_image_ref[MPI3_CI_MANIFEST_MPI_MAX]; +}; + +#define MPI3_CI_MANIFEST_MPI_RELEASE_LEVEL_DEV (0x00) +#define MPI3_CI_MANIFEST_MPI_RELEASE_LEVEL_PREALPHA (0x10) +#define MPI3_CI_MANIFEST_MPI_RELEASE_LEVEL_ALPHA (0x20) +#define MPI3_CI_MANIFEST_MPI_RELEASE_LEVEL_BETA (0x30) +#define MPI3_CI_MANIFEST_MPI_RELEASE_LEVEL_RC (0x40) +#define MPI3_CI_MANIFEST_MPI_RELEASE_LEVEL_GCA (0x50) +#define MPI3_CI_MANIFEST_MPI_RELEASE_LEVEL_POINT (0x60) +#define MPI3_CI_MANIFEST_MPI_FLAGS_DIAG_AUTHORIZATION (0x01) +#define MPI3_CI_MANIFEST_MPI_SUBSYSTEMID_IGNORED (0xffff) +#define MPI3_CI_MANIFEST_MPI_PKG_VER_STR_OFF_UNSPECIFIED (0x00000000) +#define MPI3_CI_MANIFEST_MPI_PKG_BUILD_DATE_STR_OFF_UNSPECIFIED (0x00000000) +#define MPI3_CI_MANIFEST_MPI_PKG_BUILD_TIME_STR_OFF_UNSPECIFIED (0x00000000) +union mpi3_ci_manifest { + struct mpi3_ci_manifest_mpi mpi; + __le32 dword[1]; +}; + +#define MPI3_CI_MANIFEST_TYPE_MPI (0x00) struct mpi3_extended_image_header { u8 image_type; u8 reserved01[3]; @@ -161,6 +218,7 @@ struct mpi3_encrypted_hash_entry { #define MPI3_HASH_ALGORITHM_SIZE_UNUSED (0x00) #define MPI3_HASH_ALGORITHM_SIZE_SHA256 (0x01) #define MPI3_HASH_ALGORITHM_SIZE_SHA512 (0x02) +#define MPI3_HASH_ALGORITHM_SIZE_SHA384 (0x03) #define MPI3_ENCRYPTION_ALGORITHM_UNUSED (0x00) #define MPI3_ENCRYPTION_ALGORITHM_RSA256 (0x01) #define MPI3_ENCRYPTION_ALGORITHM_RSA512 (0x02) @@ -178,7 +236,6 @@ struct mpi3_encrypted_key_with_hash_entry { u8 reserved03; __le32 reserved04; __le32 public_key[MPI3_PUBLIC_KEY_MAX]; - __le32 encrypted_hash[MPI3_ENCRYPTED_HASH_MAX]; }; #ifndef MPI3_ENCRYPTED_HASH_ENTRY_MAX diff --git a/drivers/scsi/mpi3mr/mpi/mpi30_init.h b/drivers/scsi/mpi3mr/mpi/mpi30_init.h index e02b6d3cfba2..7a208dc81d49 100644 --- a/drivers/scsi/mpi3mr/mpi/mpi30_init.h +++ b/drivers/scsi/mpi3mr/mpi/mpi30_init.h @@ -13,7 +13,7 @@ struct mpi3_scsi_io_cdb_eedp32 { __le32 transfer_length; }; -union mpi3_scso_io_cdb_union { +union mpi3_scsi_io_cdb_union { u8 cdb32[32]; struct mpi3_scsi_io_cdb_eedp32 eedp32; struct mpi3_sge_common sge; @@ -32,11 +32,12 @@ struct mpi3_scsi_io_request { __le32 skip_count; __le32 data_length; u8 lun[8]; - union mpi3_scso_io_cdb_union cdb; + union mpi3_scsi_io_cdb_union cdb; union mpi3_sge_union sgl[4]; }; #define MPI3_SCSIIO_MSGFLAGS_METASGL_VALID (0x80) +#define MPI3_SCSIIO_MSGFLAGS_DIVERT_TO_FIRMWARE (0x40) #define MPI3_SCSIIO_FLAGS_LARGE_CDB (0x60000000) #define MPI3_SCSIIO_FLAGS_CDB_16_OR_LESS (0x00000000) #define MPI3_SCSIIO_FLAGS_CDB_GREATER_THAN_16 (0x20000000) @@ -155,5 +156,13 @@ struct mpi3_scsi_task_mgmt_reply { __le32 reserved18; }; -#define MPI3_SCSITASKMGMT_RSPCODE_IO_QUEUED_ON_IOC (0x80) +#define MPI3_SCSITASKMGMT_RSPCODE_TM_COMPLETE (0x00) +#define MPI3_SCSITASKMGMT_RSPCODE_INVALID_FRAME (0x02) +#define MPI3_SCSITASKMGMT_RSPCODE_TM_FUNCTION_NOT_SUPPORTED (0x04) +#define MPI3_SCSITASKMGMT_RSPCODE_TM_FAILED (0x05) +#define MPI3_SCSITASKMGMT_RSPCODE_TM_SUCCEEDED (0x08) +#define MPI3_SCSITASKMGMT_RSPCODE_TM_INVALID_LUN (0x09) +#define MPI3_SCSITASKMGMT_RSPCODE_TM_OVERLAPPED_TAG (0x0a) +#define MPI3_SCSITASKMGMT_RSPCODE_IO_QUEUED_ON_IOC (0x80) +#define MPI3_SCSITASKMGMT_RSPCODE_TM_NVME_DENIED (0x81) #endif diff --git a/drivers/scsi/mpi3mr/mpi/mpi30_ioc.h b/drivers/scsi/mpi3mr/mpi/mpi30_ioc.h index 1af99a5382d5..bc56273778d3 100644 --- a/drivers/scsi/mpi3mr/mpi/mpi30_ioc.h +++ b/drivers/scsi/mpi3mr/mpi/mpi30_ioc.h @@ -29,10 +29,15 @@ struct mpi3_ioc_init_request { __le64 driver_information_address; }; -#define MPI3_WHOINIT_NOT_INITIALIZED (0x00) -#define MPI3_WHOINIT_ROM_BIOS (0x02) -#define MPI3_WHOINIT_HOST_DRIVER (0x03) -#define MPI3_WHOINIT_MANUFACTURER (0x04) +#define MPI3_IOCINIT_MSGFLAGS_HOSTMETADATA_MASK (0x03) +#define MPI3_IOCINIT_MSGFLAGS_HOSTMETADATA_NOT_USED (0x00) +#define MPI3_IOCINIT_MSGFLAGS_HOSTMETADATA_SEPARATED (0x01) +#define MPI3_IOCINIT_MSGFLAGS_HOSTMETADATA_INLINE (0x02) +#define MPI3_IOCINIT_MSGFLAGS_HOSTMETADATA_BOTH (0x03) +#define MPI3_WHOINIT_NOT_INITIALIZED (0x00) +#define MPI3_WHOINIT_ROM_BIOS (0x02) +#define MPI3_WHOINIT_HOST_DRIVER (0x03) +#define MPI3_WHOINIT_MANUFACTURER (0x04) struct mpi3_driver_info_layout { __le32 information_length; u8 driver_signature[12]; @@ -77,17 +82,17 @@ struct mpi3_ioc_facts_data { u8 sge_modifier_shift; u8 protocol_flags; __le16 max_sas_initiators; - __le16 max_sas_targets; + __le16 reserved2a; __le16 max_sas_expanders; __le16 max_enclosures; __le16 min_dev_handle; __le16 max_dev_handle; - __le16 max_pc_ie_switches; + __le16 max_pcie_switches; __le16 max_nvme; - __le16 max_pds; + __le16 reserved38; __le16 max_vds; __le16 max_host_pds; - __le16 max_advanced_host_pds; + __le16 max_adv_host_pds; __le16 max_raid_pds; __le16 max_posted_cmd_buffers; __le32 flags; @@ -97,26 +102,41 @@ struct mpi3_ioc_facts_data { __le16 reserved4e; __le32 diag_trace_size; __le32 diag_fw_size; + __le32 diag_driver_size; + u8 max_host_pd_ns_count; + u8 max_adv_host_pd_ns_count; + u8 max_raidpd_ns_count; + u8 reserved5f; }; -#define MPI3_IOCFACTS_CAPABILITY_ADVANCED_HOST_PD (0x00000010) +#define MPI3_IOCFACTS_CAPABILITY_NON_SUPERVISOR_MASK (0x80000000) +#define MPI3_IOCFACTS_CAPABILITY_SUPERVISOR_IOC (0x00000000) +#define MPI3_IOCFACTS_CAPABILITY_NON_SUPERVISOR_IOC (0x10000000) +#define MPI3_IOCFACTS_CAPABILITY_COMPLETE_RESET_CAPABLE (0x00000100) +#define MPI3_IOCFACTS_CAPABILITY_SEG_DIAG_TRACE_ENABLED (0x00000080) +#define MPI3_IOCFACTS_CAPABILITY_SEG_DIAG_FW_ENABLED (0x00000040) +#define MPI3_IOCFACTS_CAPABILITY_SEG_DIAG_DRIVER_ENABLED (0x00000020) +#define MPI3_IOCFACTS_CAPABILITY_ADVANCED_HOST_PD_ENABLED (0x00000010) #define MPI3_IOCFACTS_CAPABILITY_RAID_CAPABLE (0x00000008) -#define MPI3_IOCFACTS_CAPABILITY_COALESCE_CTRL_GRAN_MASK (0x00000001) -#define MPI3_IOCFACTS_CAPABILITY_COALESCE_CTRL_IOC_GRAN (0x00000000) -#define MPI3_IOCFACTS_CAPABILITY_COALESCE_CTRL_REPLY_Q_GRAN (0x00000001) +#define MPI3_IOCFACTS_CAPABILITY_MULTIPATH_ENABLED (0x00000002) +#define MPI3_IOCFACTS_CAPABILITY_COALESCE_CTRL_SUPPORTED (0x00000001) #define MPI3_IOCFACTS_PID_TYPE_MASK (0xf000) #define MPI3_IOCFACTS_PID_TYPE_SHIFT (12) #define MPI3_IOCFACTS_PID_PRODUCT_MASK (0x0f00) #define MPI3_IOCFACTS_PID_PRODUCT_SHIFT (8) #define MPI3_IOCFACTS_PID_FAMILY_MASK (0x00ff) #define MPI3_IOCFACTS_PID_FAMILY_SHIFT (0) +#define MPI3_IOCFACTS_EXCEPT_SECURITY_REKEY (0x2000) +#define MPI3_IOCFACTS_EXCEPT_SAS_DISABLED (0x1000) #define MPI3_IOCFACTS_EXCEPT_SAFE_MODE (0x0800) #define MPI3_IOCFACTS_EXCEPT_SECURITY_KEY_MASK (0x0700) #define MPI3_IOCFACTS_EXCEPT_SECURITY_KEY_NONE (0x0000) -#define MPI3_IOCFACTS_EXCEPT_SECURITY_KEY_LOCAL_VIA_RAID (0x0100) -#define MPI3_IOCFACTS_EXCEPT_SECURITY_KEY_LOCAL_VIA_OOB (0x0200) -#define MPI3_IOCFACTS_EXCEPT_SECURITY_KEY_EXT_VIA_RAID (0x0300) -#define MPI3_IOCFACTS_EXCEPT_SECURITY_KEY_EXT_VIA_OOB (0x0400) +#define MPI3_IOCFACTS_EXCEPT_SECURITY_KEY_LOCAL_VIA_MGMT (0x0100) +#define MPI3_IOCFACTS_EXCEPT_SECURITY_KEY_EXT_VIA_MGMT (0x0200) +#define MPI3_IOCFACTS_EXCEPT_SECURITY_KEY_DRIVE_EXT_VIA_MGMT (0x0300) +#define MPI3_IOCFACTS_EXCEPT_SECURITY_KEY_LOCAL_VIA_OOB (0x0400) +#define MPI3_IOCFACTS_EXCEPT_SECURITY_KEY_EXT_VIA_OOB (0x0500) +#define MPI3_IOCFACTS_EXCEPT_SECURITY_KEY_DRIVE_EXT_VIA_OOB (0x0600) #define MPI3_IOCFACTS_EXCEPT_PCIE_DISABLED (0x0080) #define MPI3_IOCFACTS_EXCEPT_PARTIAL_MEMORY_FAILURE (0x0040) #define MPI3_IOCFACTS_EXCEPT_MANUFACT_CHECKSUM_FAIL (0x0020) @@ -175,6 +195,7 @@ struct mpi3_create_request_queue_request { #define MPI3_CREATE_REQUEST_QUEUE_FLAGS_SEGMENTED_MASK (0x80) #define MPI3_CREATE_REQUEST_QUEUE_FLAGS_SEGMENTED_SEGMENTED (0x80) #define MPI3_CREATE_REQUEST_QUEUE_FLAGS_SEGMENTED_CONTIGUOUS (0x00) +#define MPI3_CREATE_REQUEST_QUEUE_SIZE_MINIMUM (2) struct mpi3_delete_request_queue_request { __le16 host_tag; u8 ioc_use_only02; @@ -210,6 +231,7 @@ struct mpi3_create_reply_queue_request { #define MPI3_CREATE_REPLY_QUEUE_FLAGS_INT_ENABLE_MASK (0x01) #define MPI3_CREATE_REPLY_QUEUE_FLAGS_INT_ENABLE_DISABLE (0x00) #define MPI3_CREATE_REPLY_QUEUE_FLAGS_INT_ENABLE_ENABLE (0x01) +#define MPI3_CREATE_REPLY_QUEUE_SIZE_MINIMUM (2) struct mpi3_delete_reply_queue_request { __le16 host_tag; u8 ioc_use_only02; @@ -255,7 +277,9 @@ struct mpi3_port_enable_request { #define MPI3_EVENT_SAS_DEVICE_DISCOVERY_ERROR (0x19) #define MPI3_EVENT_PCIE_TOPOLOGY_CHANGE_LIST (0x20) #define MPI3_EVENT_PCIE_ENUMERATION (0x22) +#define MPI3_EVENT_PCIE_ERROR_THRESHOLD (0x23) #define MPI3_EVENT_HARD_RESET_RECEIVED (0x40) +#define MPI3_EVENT_DIAGNOSTIC_BUFFER_STATUS_CHANGE (0x50) #define MPI3_EVENT_MIN_PRODUCT_SPECIFIC (0x60) #define MPI3_EVENT_MAX_PRODUCT_SPECIFIC (0x7f) #define MPI3_EVENT_NOTIFY_EVENTMASK_WORDS (4) @@ -311,10 +335,9 @@ struct mpi3_event_data_temp_threshold { __le32 reserved0c; }; -#define MPI3_EVENT_TEMP_THRESHOLD_STATUS_THRESHOLD3_EXCEEDED (0x0008) -#define MPI3_EVENT_TEMP_THRESHOLD_STATUS_THRESHOLD2_EXCEEDED (0x0004) -#define MPI3_EVENT_TEMP_THRESHOLD_STATUS_THRESHOLD1_EXCEEDED (0x0002) -#define MPI3_EVENT_TEMP_THRESHOLD_STATUS_THRESHOLD0_EXCEEDED (0x0001) +#define MPI3_EVENT_TEMP_THRESHOLD_STATUS_FATAL_THRESHOLD_EXCEEDED (0x0004) +#define MPI3_EVENT_TEMP_THRESHOLD_STATUS_CRITICAL_THRESHOLD_EXCEEDED (0x0002) +#define MPI3_EVENT_TEMP_THRESHOLD_STATUS_WARNING_THRESHOLD_EXCEEDED (0x0001) struct mpi3_event_data_cable_management { __le32 active_cable_power_requirement; u8 status; @@ -398,8 +421,10 @@ struct mpi3_event_data_sas_discovery { #define MPI3_SAS_DISC_STATUS_MAX_EXPANDERS_EXCEED (0x40000000) #define MPI3_SAS_DISC_STATUS_MAX_DEVICES_EXCEED (0x20000000) #define MPI3_SAS_DISC_STATUS_MAX_TOPO_PHYS_EXCEED (0x10000000) +#define MPI3_SAS_DISC_STATUS_INVALID_CEI (0x00010000) +#define MPI3_SAS_DISC_STATUS_FECEI_MISMATCH (0x00008000) #define MPI3_SAS_DISC_STATUS_MULTIPLE_DEVICES_IN_SLOT (0x00004000) -#define MPI3_SAS_DISC_STATUS_SLOT_COUNT_MISMATCH (0x00002000) +#define MPI3_SAS_DISC_STATUS_NECEI_MISMATCH (0x00002000) #define MPI3_SAS_DISC_STATUS_TOO_MANY_SLOTS (0x00001000) #define MPI3_SAS_DISC_STATUS_EXP_MULTI_SUBTRACTIVE (0x00000800) #define MPI3_SAS_DISC_STATUS_MULTI_PORT_DOMAIN (0x00000400) @@ -581,6 +606,20 @@ struct mpi3_event_data_pcie_topology_change_list { #define MPI3_EVENT_PCIE_TOPO_SS_NOT_RESPONDING (0x02) #define MPI3_EVENT_PCIE_TOPO_SS_RESPONDING (0x03) #define MPI3_EVENT_PCIE_TOPO_SS_DELAY_NOT_RESPONDING (0x04) +struct mpi3_event_data_pcie_error_threshold { + __le64 timestamp; + u8 reason_code; + u8 port; + __le16 switch_dev_handle; + u8 error; + u8 action; + __le16 threshold_count; + __le16 attached_dev_handle; + __le16 reserved12; +}; + +#define MPI3_EVENT_PCI_ERROR_RC_THRESHOLD_EXCEEDED (0x00) +#define MPI3_EVENT_PCI_ERROR_RC_ESCALATION (0x01) struct mpi3_event_data_sas_init_dev_status_change { u8 reason_code; u8 io_unit_port; @@ -604,6 +643,16 @@ struct mpi3_event_data_hard_reset_received { __le16 reserved02; }; +struct mpi3_event_data_diag_buffer_status_change { + u8 type; + u8 reason_code; + __le16 reserved02; + __le32 reserved04; +}; + +#define MPI3_EVENT_DIAG_BUFFER_STATUS_CHANGE_RC_RELEASED (0x01) +#define MPI3_EVENT_DIAG_BUFFER_STATUS_CHANGE_RC_PAUSED (0x02) +#define MPI3_EVENT_DIAG_BUFFER_STATUS_CHANGE_RC_RESUMED (0x03) #define MPI3_PEL_LOCALE_FLAGS_NON_BLOCKING_BOOT_EVENT (0x0200) #define MPI3_PEL_LOCALE_FLAGS_BLOCKING_BOOT_EVENT (0x0100) #define MPI3_PEL_LOCALE_FLAGS_PCIE (0x0080) @@ -645,21 +694,23 @@ struct mpi3_pel_seq { }; struct mpi3_pel_entry { + __le64 time_stamp; __le32 sequence_number; - __le32 time_stamp[2]; __le16 log_code; __le16 arg_type; __le16 locale; u8 class; - u8 reserved13; + u8 flags; u8 ext_num; u8 num_exts; u8 arg_data_size; - u8 fixed_format_size; + u8 fixed_format_strings_size; __le32 reserved18[2]; __le32 pel_info[24]; }; +#define MPI3_PEL_FLAGS_COMPLETE_RESET_NEEDED (0x02) +#define MPI3_PEL_FLAGS_ACK_NEEDED (0x01) struct mpi3_pel_list { __le32 log_count; __le32 reserved04; @@ -837,7 +888,10 @@ struct mpi3_pel_req_action_acknowledge { __le32 reserved10; }; -#define MPI3_PELACKNOWLEDGE_MSGFLAGS_SAFE_MODE_EXIT (0x01) +#define MPI3_PELACKNOWLEDGE_MSGFLAGS_SAFE_MODE_EXIT_MASK (0x03) +#define MPI3_PELACKNOWLEDGE_MSGFLAGS_SAFE_MODE_EXIT_NO_GUIDANCE (0x00) +#define MPI3_PELACKNOWLEDGE_MSGFLAGS_SAFE_MODE_EXIT_CONTINUE_OP (0x01) +#define MPI3_PELACKNOWLEDGE_MSGFLAGS_SAFE_MODE_EXIT_TRANSITION_TO_FAULT (0x02) struct mpi3_pel_reply { __le16 host_tag; u8 ioc_use_only02; @@ -885,6 +939,7 @@ struct mpi3_ci_download_request { #define MPI3_CI_DOWNLOAD_ACTION_ONLINE_ACTIVATION (0x02) #define MPI3_CI_DOWNLOAD_ACTION_OFFLINE_ACTIVATION (0x03) #define MPI3_CI_DOWNLOAD_ACTION_GET_STATUS (0x04) +#define MPI3_CI_DOWNLOAD_ACTION_CANCEL_OFFLINE_ACTIVATION (0x05) struct mpi3_ci_download_reply { __le16 host_tag; u8 ioc_use_only02; @@ -902,6 +957,7 @@ struct mpi3_ci_download_reply { }; #define MPI3_CI_DOWNLOAD_FLAGS_DOWNLOAD_IN_PROGRESS (0x80) +#define MPI3_CI_DOWNLOAD_FLAGS_OFFLINE_ACTIVATION_REQUIRED (0x20) #define MPI3_CI_DOWNLOAD_FLAGS_KEY_UPDATE_PENDING (0x10) #define MPI3_CI_DOWNLOAD_FLAGS_ACTIVATION_STATUS_MASK (0x0e) #define MPI3_CI_DOWNLOAD_FLAGS_ACTIVATION_STATUS_NOT_NEEDED (0x00) @@ -939,19 +995,28 @@ struct mpi3_ci_upload_request { #define MPI3_CTRL_OP_REMOVE_DEVICE (0x10) #define MPI3_CTRL_OP_CLOSE_PERSISTENT_CONNECTION (0x11) #define MPI3_CTRL_OP_HIDDEN_ACK (0x12) +#define MPI3_CTRL_OP_CLEAR_DEVICE_COUNTERS (0x13) #define MPI3_CTRL_OP_SAS_SEND_PRIMITIVE (0x20) -#define MPI3_CTRL_OP_SAS_CLEAR_ERROR_LOG (0x21) -#define MPI3_CTRL_OP_PCIE_CLEAR_ERROR_LOG (0x22) +#define MPI3_CTRL_OP_SAS_PHY_CONTROL (0x21) +#define MPI3_CTRL_OP_READ_INTERNAL_BUS (0x23) +#define MPI3_CTRL_OP_WRITE_INTERNAL_BUS (0x24) +#define MPI3_CTRL_OP_PCIE_LINK_CONTROL (0x30) #define MPI3_CTRL_OP_LOOKUP_MAPPING_PARAM8_LOOKUP_METHOD_INDEX (0x00) #define MPI3_CTRL_OP_UPDATE_TIMESTAMP_PARAM64_TIMESTAMP_INDEX (0x00) #define MPI3_CTRL_OP_REMOVE_DEVICE_PARAM16_DEVHANDLE_INDEX (0x00) #define MPI3_CTRL_OP_CLOSE_PERSIST_CONN_PARAM16_DEVHANDLE_INDEX (0x00) #define MPI3_CTRL_OP_HIDDEN_ACK_PARAM16_DEVHANDLE_INDEX (0x00) +#define MPI3_CTRL_OP_CLEAR_DEVICE_COUNTERS_PARAM16_DEVHANDLE_INDEX (0x00) #define MPI3_CTRL_OP_SAS_SEND_PRIM_PARAM8_PHY_INDEX (0x00) #define MPI3_CTRL_OP_SAS_SEND_PRIM_PARAM8_PRIMSEQ_INDEX (0x01) #define MPI3_CTRL_OP_SAS_SEND_PRIM_PARAM32_PRIMITIVE_INDEX (0x00) -#define MPI3_CTRL_OP_SAS_CLEAR_ERR_LOG_PARAM8_PHY_INDEX (0x00) -#define MPI3_CTRL_OP_PCIE_CLEAR_ERR_LOG_PARAM8_PHY_INDEX (0x00) +#define MPI3_CTRL_OP_SAS_PHY_CONTROL_PARAM8_ACTION_INDEX (0x00) +#define MPI3_CTRL_OP_SAS_PHY_CONTROL_PARAM8_PHY_INDEX (0x01) +#define MPI3_CTRL_OP_READ_INTERNAL_BUS_PARAM64_ADDRESS_INDEX (0x00) +#define MPI3_CTRL_OP_WRITE_INTERNAL_BUS_PARAM64_ADDRESS_INDEX (0x00) +#define MPI3_CTRL_OP_WRITE_INTERNAL_BUS_PARAM32_VALUE_INDEX (0x00) +#define MPI3_CTRL_OP_PCIE_LINK_CONTROL_PARAM8_ACTION_INDEX (0x00) +#define MPI3_CTRL_OP_PCIE_LINK_CONTROL_PARAM8_LINK_INDEX (0x01) #define MPI3_CTRL_LOOKUP_METHOD_WWID_ADDRESS (0x01) #define MPI3_CTRL_LOOKUP_METHOD_ENCLOSURE_SLOT (0x02) #define MPI3_CTRL_LOOKUP_METHOD_SAS_DEVICE_NAME (0x03) @@ -966,9 +1031,14 @@ struct mpi3_ci_upload_request { #define MPI3_CTRL_LOOKUP_METHOD_PERSISTID_PARAM16_PERSISTENT_ID_INDEX (1) #define MPI3_CTRL_LOOKUP_METHOD_VALUE16_DEVH_INDEX (0) #define MPI3_CTRL_GET_TIMESTAMP_VALUE64_TIMESTAMP_INDEX (0) +#define MPI3_CTRL_READ_INTERNAL_BUS_VALUE32_VALUE_INDEX (0) #define MPI3_CTRL_PRIMFLAGS_SINGLE (0x01) #define MPI3_CTRL_PRIMFLAGS_TRIPLE (0x03) #define MPI3_CTRL_PRIMFLAGS_REDUNDANT (0x06) +#define MPI3_CTRL_ACTION_NOP (0x00) +#define MPI3_CTRL_ACTION_LINK_RESET (0x01) +#define MPI3_CTRL_ACTION_HARD_RESET (0x02) +#define MPI3_CTRL_ACTION_CLEAR_ERROR_LOG (0x05) struct mpi3_iounit_control_request { __le16 host_tag; u8 ioc_use_only02; diff --git a/drivers/scsi/mpi3mr/mpi/mpi30_pci.h b/drivers/scsi/mpi3mr/mpi/mpi30_pci.h new file mode 100644 index 000000000000..dbfaf4137560 --- /dev/null +++ b/drivers/scsi/mpi3mr/mpi/mpi30_pci.h @@ -0,0 +1,44 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +/* + * Copyright 2016-2021 Broadcom Inc. All rights reserved. + * + */ +#ifndef MPI30_PCI_H +#define MPI30_PCI_H 1 +#ifndef MPI3_NVME_ENCAP_CMD_MAX +#define MPI3_NVME_ENCAP_CMD_MAX (1) +#endif +struct mpi3_nvme_encapsulated_request { + __le16 host_tag; + u8 ioc_use_only02; + u8 function; + __le16 ioc_use_only04; + u8 ioc_use_only06; + u8 msg_flags; + __le16 change_count; + __le16 dev_handle; + __le16 encapsulated_command_length; + __le16 flags; + __le32 reserved10[4]; + __le32 command[MPI3_NVME_ENCAP_CMD_MAX]; +}; + +#define MPI3_NVME_FLAGS_FORCE_ADMIN_ERR_REPLY_MASK (0x0002) +#define MPI3_NVME_FLAGS_FORCE_ADMIN_ERR_REPLY_FAIL_ONLY (0x0000) +#define MPI3_NVME_FLAGS_FORCE_ADMIN_ERR_REPLY_ALL (0x0002) +#define MPI3_NVME_FLAGS_SUBMISSIONQ_MASK (0x0001) +#define MPI3_NVME_FLAGS_SUBMISSIONQ_IO (0x0000) +#define MPI3_NVME_FLAGS_SUBMISSIONQ_ADMIN (0x0001) +struct mpi3_nvme_encapsulated_error_reply { + __le16 host_tag; + u8 ioc_use_only02; + u8 function; + __le16 ioc_use_only04; + u8 ioc_use_only06; + u8 msg_flags; + __le16 ioc_use_only08; + __le16 ioc_status; + __le32 ioc_log_info; + __le32 nvme_completion_entry[4]; +}; +#endif diff --git a/drivers/scsi/mpi3mr/mpi/mpi30_sas.h b/drivers/scsi/mpi3mr/mpi/mpi30_sas.h index ba5018702960..298d895e374b 100644 --- a/drivers/scsi/mpi3mr/mpi/mpi30_sas.h +++ b/drivers/scsi/mpi3mr/mpi/mpi30_sas.h @@ -30,4 +30,18 @@ struct mpi3_smp_passthrough_request { struct mpi3_sge_common request_sge; struct mpi3_sge_common response_sge; }; + +struct mpi3_smp_passthrough_reply { + __le16 host_tag; + u8 ioc_use_only02; + u8 function; + __le16 ioc_use_only04; + u8 ioc_use_only06; + u8 msg_flags; + __le16 ioc_use_only08; + __le16 ioc_status; + __le32 ioc_log_info; + __le16 response_data_length; + __le16 reserved12; +}; #endif diff --git a/drivers/scsi/mpi3mr/mpi/mpi30_tool.h b/drivers/scsi/mpi3mr/mpi/mpi30_tool.h new file mode 100644 index 000000000000..54164a248c21 --- /dev/null +++ b/drivers/scsi/mpi3mr/mpi/mpi30_tool.h @@ -0,0 +1,303 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +/* + * Copyright 2016-2021 Broadcom Inc. All rights reserved. + * + */ +#ifndef MPI30_TOOL_H +#define MPI30_TOOL_H 1 +struct mpi3_tool_clean_request { + __le16 host_tag; + u8 ioc_use_only02; + u8 function; + __le16 ioc_use_only04; + u8 ioc_use_only06; + u8 msg_flags; + __le16 change_count; + u8 tool; + u8 reserved0b; + __le32 area; +}; + +#define MPI3_TOOLBOX_TOOL_CLEAN (0x01) +#define MPI3_TOOLBOX_TOOL_ISTWI_READ_WRITE (0x02) +#define MPI3_TOOLBOX_TOOL_DIAGNOSTIC_CLI (0x03) +#define MPI3_TOOLBOX_TOOL_LANE_MARGINING (0x04) +#define MPI3_TOOLBOX_TOOL_RECOVER_DEVICE (0x05) +#define MPI3_TOOLBOX_TOOL_LOOPBACK (0x06) +#define MPI3_TOOLBOX_CLEAN_AREA_BIOS_BOOT_SERVICES (0x00000008) +#define MPI3_TOOLBOX_CLEAN_AREA_ALL_BUT_MFG (0x00000002) +#define MPI3_TOOLBOX_CLEAN_AREA_NVSTORE (0x00000001) +struct mpi3_tool_istwi_read_write_request { + __le16 host_tag; + u8 ioc_use_only02; + u8 function; + __le16 ioc_use_only04; + u8 ioc_use_only06; + u8 msg_flags; + __le16 change_count; + u8 tool; + u8 flags; + u8 dev_index; + u8 action; + __le16 reserved0e; + __le16 tx_data_length; + __le16 rx_data_length; + __le32 reserved14[3]; + struct mpi3_man11_istwi_device_format istwi_device; + union mpi3_sge_union sgl; +}; + +#define MPI3_TOOLBOX_ISTWI_FLAGS_AUTO_RESERVE_RELEASE (0x80) +#define MPI3_TOOLBOX_ISTWI_FLAGS_ADDRESS_MODE_MASK (0x04) +#define MPI3_TOOLBOX_ISTWI_FLAGS_ADDRESS_MODE_DEVINDEX (0x00) +#define MPI3_TOOLBOX_ISTWI_FLAGS_ADDRESS_MODE_DEVICE_FIELD (0x04) +#define MPI3_TOOLBOX_ISTWI_FLAGS_PAGE_ADDRESS_MASK (0x03) +#define MPI3_TOOLBOX_ISTWI_ACTION_RESERVE_BUS (0x00) +#define MPI3_TOOLBOX_ISTWI_ACTION_RELEASE_BUS (0x01) +#define MPI3_TOOLBOX_ISTWI_ACTION_RESET (0x02) +#define MPI3_TOOLBOX_ISTWI_ACTION_READ_DATA (0x03) +#define MPI3_TOOLBOX_ISTWI_ACTION_WRITE_DATA (0x04) +#define MPI3_TOOLBOX_ISTWI_ACTION_SEQUENCE (0x05) +struct mpi3_tool_istwi_read_write_reply { + __le16 host_tag; + u8 ioc_use_only02; + u8 function; + __le16 ioc_use_only04; + u8 ioc_use_only06; + u8 msg_flags; + __le16 ioc_use_only08; + __le16 ioc_status; + __le32 ioc_log_info; + __le16 istwi_status; + __le16 reserved12; + __le16 tx_data_count; + __le16 rx_data_count; +}; + +struct mpi3_tool_diagnostic_cli_request { + __le16 host_tag; + u8 ioc_use_only02; + u8 function; + __le16 ioc_use_only04; + u8 ioc_use_only06; + u8 msg_flags; + __le16 change_count; + u8 tool; + u8 reserved0b; + __le32 command_data_length; + __le32 response_data_length; + __le32 reserved14[3]; + union mpi3_sge_union sgl; +}; + +struct mpi3_tool_diagnostic_cli_reply { + __le16 host_tag; + u8 ioc_use_only02; + u8 function; + __le16 ioc_use_only04; + u8 ioc_use_only06; + u8 msg_flags; + __le16 ioc_use_only08; + __le16 ioc_status; + __le32 ioc_log_info; + __le32 returned_data_length; +}; + +struct mpi3_tool_lane_margin_request { + __le16 host_tag; + u8 ioc_use_only02; + u8 function; + __le16 ioc_use_only04; + u8 ioc_use_only06; + u8 msg_flags; + __le16 change_count; + u8 tool; + u8 reserved0b; + u8 action; + u8 switch_port; + __le16 dev_handle; + u8 start_lane; + u8 num_lanes; + __le16 reserved12; + __le32 reserved14[3]; + union mpi3_sge_union sgl; +}; + +#define MPI3_TOOLBOX_LM_ACTION_ENTER (0x00) +#define MPI3_TOOLBOX_LM_ACTION_EXIT (0x01) +#define MPI3_TOOLBOX_LM_ACTION_READ (0x02) +#define MPI3_TOOLBOX_LM_ACTION_WRITE (0x03) +struct mpi3_lane_margin_element { + __le16 control; + __le16 status; +}; + +struct mpi3_tool_lane_margin_reply { + __le16 host_tag; + u8 ioc_use_only02; + u8 function; + __le16 ioc_use_only04; + u8 ioc_use_only06; + u8 msg_flags; + __le16 ioc_use_only08; + __le16 ioc_status; + __le32 ioc_log_info; + __le32 returned_data_length; +}; + +struct mpi3_tool_recover_device_request { + __le16 host_tag; + u8 ioc_use_only02; + u8 function; + __le16 ioc_use_only04; + u8 ioc_use_only06; + u8 msg_flags; + __le16 change_count; + u8 tool; + u8 reserved0b; + u8 action; + u8 reserved0d; + __le16 dev_handle; +}; + +#define MPI3_TOOLBOX_RD_ACTION_START (0x01) +#define MPI3_TOOLBOX_RD_ACTION_GET_STATUS (0x02) +#define MPI3_TOOLBOX_RD_ACTION_ABORT (0x03) +struct mpi3_tool_recover_device_reply { + __le16 host_tag; + u8 ioc_use_only02; + u8 function; + __le16 ioc_use_only04; + u8 ioc_use_only06; + u8 msg_flags; + __le16 ioc_use_only08; + __le16 ioc_status; + __le32 ioc_log_info; + u8 status; + u8 reserved11; + __le16 reserved1c; +}; + +#define MPI3_TOOLBOX_RD_STATUS_NOT_NEEDED (0x01) +#define MPI3_TOOLBOX_RD_STATUS_NEEDED (0x02) +#define MPI3_TOOLBOX_RD_STATUS_IN_PROGRESS (0x03) +#define MPI3_TOOLBOX_RD_STATUS_ABORTING (0x04) +struct mpi3_tool_loopback_request { + __le16 host_tag; + u8 ioc_use_only02; + u8 function; + __le16 ioc_use_only04; + u8 ioc_use_only06; + u8 msg_flags; + __le16 change_count; + u8 tool; + u8 reserved0b; + __le32 reserved0c; + __le64 phys; +}; + +struct mpi3_tool_loopback_reply { + __le16 host_tag; + u8 ioc_use_only02; + u8 function; + __le16 ioc_use_only04; + u8 ioc_use_only06; + u8 msg_flags; + __le16 ioc_use_only08; + __le16 ioc_status; + __le32 reserved0c; + __le64 tested_phys; + __le64 failed_phys; +}; + +struct mpi3_diag_buffer_post_request { + __le16 host_tag; + u8 ioc_use_only02; + u8 function; + __le16 ioc_use_only04; + u8 ioc_use_only06; + u8 msg_flags; + __le16 change_count; + __le16 reserved0a; + u8 type; + u8 reserved0d; + __le16 reserved0e; + __le64 address; + __le32 length; + __le32 reserved1c; +}; + +#define MPI3_DIAG_BUFFER_POST_MSGFLAGS_SEGMENTED (0x01) +#define MPI3_DIAG_BUFFER_TYPE_TRACE (0x01) +#define MPI3_DIAG_BUFFER_TYPE_FW (0x02) +#define MPI3_DIAG_BUFFER_TYPE_DRIVER (0x10) +struct mpi3_driver_buffer_header { + __le32 signature; + __le16 header_size; + __le16 rtt_file_header_offset; + __le32 flags; + __le32 circular_buffer_size; + __le32 logical_buffer_end; + __le32 logical_buffer_start; + __le32 ioc_use_only18[2]; + __le32 reserved20[760]; + __le32 reserved_rttrace[256]; +}; + +#define MPI3_DRIVER_DIAG_BUFFER_HEADER_SIGNATURE_CIRCULAR (0x43495243) +#define MPI3_DRIVER_DIAG_BUFFER_HEADER_FLAGS_CIRCULAR_BUF_FORMAT_MASK (0x00000003) +#define MPI3_DRIVER_DIAG_BUFFER_HEADER_FLAGS_CIRCULAR_BUF_FORMAT_ASCII (0x00000000) +#define MPI3_DRIVER_DIAG_BUFFER_HEADER_FLAGS_CIRCULAR_BUF_FORMAT_RTTRACE (0x00000001) +struct mpi3_diag_buffer_manage_request { + __le16 host_tag; + u8 ioc_use_only02; + u8 function; + __le16 ioc_use_only04; + u8 ioc_use_only06; + u8 msg_flags; + __le16 change_count; + __le16 reserved0a; + u8 type; + u8 action; + __le16 reserved0e; +}; + +#define MPI3_DIAG_BUFFER_ACTION_RELEASE (0x01) +#define MPI3_DIAG_BUFFER_ACTION_PAUSE (0x02) +#define MPI3_DIAG_BUFFER_ACTION_RESUME (0x03) +struct mpi3_diag_buffer_upload_request { + __le16 host_tag; + u8 ioc_use_only02; + u8 function; + __le16 ioc_use_only04; + u8 ioc_use_only06; + u8 msg_flags; + __le16 change_count; + __le16 reserved0a; + u8 type; + u8 flags; + __le16 reserved0e; + __le64 context; + __le32 reserved18; + __le32 reserved1c; + union mpi3_sge_union sgl; +}; + +#define MPI3_DIAG_BUFFER_UPLOAD_FLAGS_FORMAT_MASK (0x01) +#define MPI3_DIAG_BUFFER_UPLOAD_FLAGS_FORMAT_DECODED (0x00) +#define MPI3_DIAG_BUFFER_UPLOAD_FLAGS_FORMAT_ENCODED (0x01) +struct mpi3_diag_buffer_upload_reply { + __le16 host_tag; + u8 ioc_use_only02; + u8 function; + __le16 ioc_use_only04; + u8 ioc_use_only06; + u8 msg_flags; + __le16 ioc_use_only08; + __le16 ioc_status; + __le32 ioc_log_info; + __le64 context; + __le32 returned_data_length; + __le32 reserved1c; +}; +#endif diff --git a/drivers/scsi/mpi3mr/mpi/mpi30_transport.h b/drivers/scsi/mpi3mr/mpi/mpi30_transport.h index 63e4e81d5397..6d550117ec2e 100644 --- a/drivers/scsi/mpi3mr/mpi/mpi30_transport.h +++ b/drivers/scsi/mpi3mr/mpi/mpi30_transport.h @@ -19,8 +19,8 @@ union mpi3_version_union { #define MPI3_VERSION_MAJOR (3) #define MPI3_VERSION_MINOR (0) -#define MPI3_VERSION_UNIT (0) -#define MPI3_VERSION_DEV (18) +#define MPI3_VERSION_UNIT (22) +#define MPI3_VERSION_DEV (0) struct mpi3_sysif_oper_queue_indexes { __le16 producer_index; __le16 reserved02; @@ -74,6 +74,7 @@ struct mpi3_sysif_registers { #define MPI3_SYSIF_IOC_INFO_HIGH_OFFSET (0x00000004) #define MPI3_SYSIF_IOC_INFO_LOW_TIMEOUT_MASK (0xff000000) #define MPI3_SYSIF_IOC_INFO_LOW_TIMEOUT_SHIFT (24) +#define MPI3_SYSIF_IOC_INFO_LOW_HCB_DISABLED (0x00000001) #define MPI3_SYSIF_IOC_CONFIG_OFFSET (0x00000014) #define MPI3_SYSIF_IOC_CONFIG_OPER_RPY_ENT_SZ (0x00f00000) #define MPI3_SYSIF_IOC_CONFIG_OPER_RPY_ENT_SZ_SHIFT (20) @@ -82,12 +83,13 @@ struct mpi3_sysif_registers { #define MPI3_SYSIF_IOC_CONFIG_SHUTDOWN_MASK (0x0000c000) #define MPI3_SYSIF_IOC_CONFIG_SHUTDOWN_NO (0x00000000) #define MPI3_SYSIF_IOC_CONFIG_SHUTDOWN_NORMAL (0x00004000) -#define MPI3_SYSIF_IOC_CONFIG_DEVICE_SHUTDOWN (0x00002000) +#define MPI3_SYSIF_IOC_CONFIG_DEVICE_SHUTDOWN_SEND_REQ (0x00002000) #define MPI3_SYSIF_IOC_CONFIG_DIAG_SAVE (0x00000010) #define MPI3_SYSIF_IOC_CONFIG_ENABLE_IOC (0x00000001) #define MPI3_SYSIF_IOC_STATUS_OFFSET (0x0000001c) #define MPI3_SYSIF_IOC_STATUS_RESET_HISTORY (0x00000010) #define MPI3_SYSIF_IOC_STATUS_SHUTDOWN_MASK (0x0000000c) +#define MPI3_SYSIF_IOC_STATUS_SHUTDOWN_SHIFT (0x00000002) #define MPI3_SYSIF_IOC_STATUS_SHUTDOWN_NONE (0x00000000) #define MPI3_SYSIF_IOC_STATUS_SHUTDOWN_IN_PROGRESS (0x00000004) #define MPI3_SYSIF_IOC_STATUS_SHUTDOWN_COMPLETE (0x00000008) @@ -107,9 +109,9 @@ struct mpi3_sysif_registers { #define MPI3_SYSIF_COALESCE_CONTROL_ENABLE_NO_CHANGE (0x00000000) #define MPI3_SYSIF_COALESCE_CONTROL_ENABLE_DISABLE (0x40000000) #define MPI3_SYSIF_COALESCE_CONTROL_ENABLE_ENABLE (0xc0000000) -#define MPI3_SYSIF_COALESCE_CONTROL_VALID (0x30000000) -#define MPI3_SYSIF_COALESCE_CONTROL_QUEUE_ID_MASK (0x00ff0000) -#define MPI3_SYSIF_COALESCE_CONTROL_QUEUE_ID_SHIFT (16) +#define MPI3_SYSIF_COALESCE_CONTROL_VALID (0x20000000) +#define MPI3_SYSIF_COALESCE_CONTROL_MSIX_IDX_MASK (0x01ff0000) +#define MPI3_SYSIF_COALESCE_CONTROL_MSIX_IDX_SHIFT (16) #define MPI3_SYSIF_COALESCE_CONTROL_TIMEOUT_MASK (0x0000ff00) #define MPI3_SYSIF_COALESCE_CONTROL_TIMEOUT_SHIFT (8) #define MPI3_SYSIF_COALESCE_CONTROL_DEPTH_MASK (0x000000ff) @@ -117,9 +119,9 @@ struct mpi3_sysif_registers { #define MPI3_SYSIF_ADMIN_REQ_Q_PI_OFFSET (0x00001000) #define MPI3_SYSIF_ADMIN_REPLY_Q_CI_OFFSET (0x00001004) #define MPI3_SYSIF_OPER_REQ_Q_PI_OFFSET (0x00001008) -#define MPI3_SYSIF_OPER_REQ_Q_N_PI_OFFSET(n) (MPI3_SYSIF_OPER_REQ_Q_PI_OFFSET + (((n) - 1) * 8)) +#define MPI3_SYSIF_OPER_REQ_Q_N_PI_OFFSET(N) (MPI3_SYSIF_OPER_REQ_Q_PI_OFFSET + (((N) - 1) * 8)) #define MPI3_SYSIF_OPER_REPLY_Q_CI_OFFSET (0x0000100c) -#define MPI3_SYSIF_OPER_REPLY_Q_N_CI_OFFSET(n) (MPI3_SYSIF_OPER_REPLY_Q_CI_OFFSET + (((n) - 1) * 8)) +#define MPI3_SYSIF_OPER_REPLY_Q_N_CI_OFFSET(N) (MPI3_SYSIF_OPER_REPLY_Q_CI_OFFSET + (((N) - 1) * 8)) #define MPI3_SYSIF_WRITE_SEQUENCE_OFFSET (0x00001c04) #define MPI3_SYSIF_WRITE_SEQUENCE_KEY_VALUE_MASK (0x0000000f) #define MPI3_SYSIF_WRITE_SEQUENCE_KEY_VALUE_FLUSH (0x0) @@ -133,7 +135,7 @@ struct mpi3_sysif_registers { #define MPI3_SYSIF_HOST_DIAG_RESET_ACTION_MASK (0x00000700) #define MPI3_SYSIF_HOST_DIAG_RESET_ACTION_NO_RESET (0x00000000) #define MPI3_SYSIF_HOST_DIAG_RESET_ACTION_SOFT_RESET (0x00000100) -#define MPI3_SYSIF_HOST_DIAG_RESET_ACTION_FLASH_RCVRY_RESET (0x00000200) +#define MPI3_SYSIF_HOST_DIAG_RESET_ACTION_HOST_CONTROL_BOOT_RESET (0x00000200) #define MPI3_SYSIF_HOST_DIAG_RESET_ACTION_COMPLETE_RESET (0x00000300) #define MPI3_SYSIF_HOST_DIAG_RESET_ACTION_DIAG_FAULT (0x00000700) #define MPI3_SYSIF_HOST_DIAG_SAVE_IN_PROGRESS (0x00000080) @@ -153,8 +155,9 @@ struct mpi3_sysif_registers { #define MPI3_SYSIF_FAULT_CODE_CI_ACTIVATION_RESET (0x0000f001) #define MPI3_SYSIF_FAULT_CODE_SOFT_RESET_IN_PROGRESS (0x0000f002) #define MPI3_SYSIF_FAULT_CODE_COMPLETE_RESET_NEEDED (0x0000f003) -#define MPI3_SYSIF_FAULT_CODE_SAFE_MODE_EXIT (0x0000f004) -#define MPI3_SYSIF_FAULT_CODE_FACTORY_RESET (0x0000f005) +#define MPI3_SYSIF_FAULT_CODE_SOFT_RESET_NEEDED (0x0000f004) +#define MPI3_SYSIF_FAULT_CODE_POWER_CYCLE_REQUIRED (0x0000f005) +#define MPI3_SYSIF_FAULT_CODE_TEMP_THRESHOLD_EXCEEDED (0x0000f006) #define MPI3_SYSIF_FAULT_INFO0_OFFSET (0x00001c14) #define MPI3_SYSIF_FAULT_INFO1_OFFSET (0x00001c18) #define MPI3_SYSIF_FAULT_INFO2_OFFSET (0x00001c1c) @@ -409,6 +412,8 @@ struct mpi3_default_reply { #define MPI3_IOCSTATUS_INVALID_STATE (0x0008) #define MPI3_IOCSTATUS_INSUFFICIENT_POWER (0x000a) #define MPI3_IOCSTATUS_INVALID_CHANGE_COUNT (0x000b) +#define MPI3_IOCSTATUS_ALLOWED_CMD_BLOCK (0x000c) +#define MPI3_IOCSTATUS_SUPERVISOR_ONLY (0x000d) #define MPI3_IOCSTATUS_FAILURE (0x001f) #define MPI3_IOCSTATUS_CONFIG_INVALID_ACTION (0x0020) #define MPI3_IOCSTATUS_CONFIG_INVALID_TYPE (0x0021) @@ -448,8 +453,10 @@ struct mpi3_default_reply { #define MPI3_IOCSTATUS_CI_UNSUPPORTED (0x00b0) #define MPI3_IOCSTATUS_CI_UPDATE_SEQUENCE (0x00b1) #define MPI3_IOCSTATUS_CI_VALIDATION_FAILED (0x00b2) -#define MPI3_IOCSTATUS_CI_UPDATE_PENDING (0x00b3) +#define MPI3_IOCSTATUS_CI_KEY_UPDATE_PENDING (0x00b3) +#define MPI3_IOCSTATUS_CI_KEY_UPDATE_NOT_POSSIBLE (0x00b4) #define MPI3_IOCSTATUS_SECURITY_KEY_REQUIRED (0x00c0) +#define MPI3_IOCSTATUS_SECURITY_VIOLATION (0x00c1) #define MPI3_IOCSTATUS_INVALID_QUEUE_ID (0x0f00) #define MPI3_IOCSTATUS_INVALID_QUEUE_SIZE (0x0f01) #define MPI3_IOCSTATUS_INVALID_MSIX_VECTOR (0x0f02) diff --git a/drivers/scsi/mpi3mr/mpi3mr_fw.c b/drivers/scsi/mpi3mr/mpi3mr_fw.c index 4a8316c6bd41..878a4963e2ad 100644 --- a/drivers/scsi/mpi3mr/mpi3mr_fw.c +++ b/drivers/scsi/mpi3mr/mpi3mr_fw.c @@ -2009,7 +2009,7 @@ static void mpi3mr_watchdog_work(struct work_struct *work) mpi3mr_print_fault_info(mrioc); mrioc->diagsave_timeout = 0; - if (fault == MPI3_SYSIF_FAULT_CODE_FACTORY_RESET) { + if (fault == MPI3_SYSIF_FAULT_CODE_POWER_CYCLE_REQUIRED) { ioc_info(mrioc, "Factory Reset fault occurred marking controller as unrecoverable" ); @@ -2374,14 +2374,13 @@ static void mpi3mr_process_factsdata(struct mpi3mr_ioc *mrioc, mrioc->facts.reply_sz = le16_to_cpu(facts_data->reply_frame_size) * 4; mrioc->facts.exceptions = le16_to_cpu(facts_data->ioc_exceptions); mrioc->facts.max_perids = le16_to_cpu(facts_data->max_persistent_id); - mrioc->facts.max_pds = le16_to_cpu(facts_data->max_pds); mrioc->facts.max_vds = le16_to_cpu(facts_data->max_vds); mrioc->facts.max_hpds = le16_to_cpu(facts_data->max_host_pds); - mrioc->facts.max_advhpds = le16_to_cpu(facts_data->max_advanced_host_pds); + mrioc->facts.max_advhpds = le16_to_cpu(facts_data->max_adv_host_pds); mrioc->facts.max_raidpds = le16_to_cpu(facts_data->max_raid_pds); mrioc->facts.max_nvme = le16_to_cpu(facts_data->max_nvme); mrioc->facts.max_pcie_switches = - le16_to_cpu(facts_data->max_pc_ie_switches); + le16_to_cpu(facts_data->max_pcie_switches); mrioc->facts.max_sasexpanders = le16_to_cpu(facts_data->max_sas_expanders); mrioc->facts.max_sasinitiators = @@ -3677,7 +3676,7 @@ static void mpi3mr_issue_ioc_shutdown(struct mpi3mr_ioc *mrioc) ioc_config = readl(&mrioc->sysif_regs->ioc_configuration); ioc_config |= MPI3_SYSIF_IOC_CONFIG_SHUTDOWN_NORMAL; - ioc_config |= MPI3_SYSIF_IOC_CONFIG_DEVICE_SHUTDOWN; + ioc_config |= MPI3_SYSIF_IOC_CONFIG_DEVICE_SHUTDOWN_SEND_REQ; writel(ioc_config, &mrioc->sysif_regs->ioc_configuration); diff --git a/drivers/scsi/mpi3mr/mpi3mr_os.c b/drivers/scsi/mpi3mr/mpi3mr_os.c index 2197988333fe..a17d2172bddf 100644 --- a/drivers/scsi/mpi3mr/mpi3mr_os.c +++ b/drivers/scsi/mpi3mr/mpi3mr_os.c @@ -860,7 +860,7 @@ static void mpi3mr_update_tgtdev(struct mpi3mr_ioc *mrioc, tgtdev->dev_spec.pcie_inf.reset_to = pcieinf->controller_reset_to; tgtdev->dev_spec.pcie_inf.abort_to = - pcieinf->nv_me_abort_to; + pcieinf->nvme_abort_to; } if (tgtdev->dev_spec.pcie_inf.mdts > (1024 * 1024)) tgtdev->dev_spec.pcie_inf.mdts = (1024 * 1024); From patchwork Tue Sep 21 18:45:55 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Kashyap Desai X-Patchwork-Id: 12508629 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-15.1 required=3.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_PATCH,MAILING_LIST_MULTI,MIME_HEADER_CTYPE_ONLY,SPF_HELO_NONE, SPF_PASS,T_TVD_MIME_NO_HEADERS,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 7E324C433EF for ; Tue, 21 Sep 2021 18:46:44 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 5B9196127A for ; Tue, 21 Sep 2021 18:46:44 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S233938AbhIUSsC (ORCPT ); Tue, 21 Sep 2021 14:48:02 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:40206 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231206AbhIUSrm (ORCPT ); Tue, 21 Sep 2021 14:47:42 -0400 Received: from mail-pf1-x431.google.com (mail-pf1-x431.google.com [IPv6:2607:f8b0:4864:20::431]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 4FD1EC061574 for ; Tue, 21 Sep 2021 11:46:14 -0700 (PDT) Received: by mail-pf1-x431.google.com with SMTP id e16so391637pfc.6 for ; Tue, 21 Sep 2021 11:46:14 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=broadcom.com; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=J/JXqm124fWrL5OM1ixbPBWDBv6y8m7UT+NPT1VGhJc=; b=df0KJBhCpeGkimCSjacXvmqoyTYylTy/+v+zyUS6u84TEZFMGFbITOy7DDeL1/3r7L rnXEEfRJXG/3b0p8tSdUGN6hrHtBYsFe06iDgvbj7iTkGP5o0Q6ZdfRkJxihSGzIWL+H NWHxZ2L6qU/LTM6T/jlBJK0BO7rVBqQuejO+c= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=J/JXqm124fWrL5OM1ixbPBWDBv6y8m7UT+NPT1VGhJc=; b=FmSEzvUi0iO28avm7cY7CbWRNAMQJgi6ULHPC8FIV/mDUN2ZvpQ2iH5cBYAwme/poA f37bYc9+riBCnU8hl6sNhUnPp02a0TXFZ41//OWMVHj2rYH1m5qViKyA31q7SP2xXuIE zKyqIfBWEL/17x0RbVLplOGRcafUmBih1kr8ByxFYO1ECexdOTp41ywRqxXFjVQJLN/c hDTqoumAWkxfXn+kRifBmOjPTmBkoCfE1Uueqf1YpaYrMzPlpC0jtPROLUJCASJ70awL 6pNyjbFZi3BUbskL57g8dUA95ZZzM071amJ1ndSYC+ZAQ3I4JvdBtMWXIeVNrIbLz5ZC qhcA== X-Gm-Message-State: AOAM5304EZE/x9DCXkZ6IULudojhtqGYZB9CdQW1A4g3AQ1IsaOKtCy2 0Js2/Zz/Zcztdo+bYoZ6YebytFHlY+fdvRNC3pdu5tGjBafIE4zWo/RrIqbSmP78bcqR5PF7K2m 8JhzSzCLnBJ62SdN42JDo5UjLpPEnhnQAukEq4Ij40qsZG0ORptWbM5WXiWw5s7mpzKxoJY/7II vOrGfAl8ET X-Google-Smtp-Source: ABdhPJxDoLJNASzoCXS834BGrJ72lqULqIHvMqqaRE0jOydtLpB860xqW0DVvLOFjWq+l4ZZcKVNfA== X-Received: by 2002:a62:7b4a:0:b0:439:2b2c:89f1 with SMTP id w71-20020a627b4a000000b004392b2c89f1mr31495434pfc.18.1632249973481; Tue, 21 Sep 2021 11:46:13 -0700 (PDT) Received: from drv-bst-rhel8.dhcp.broadcom.net ([192.19.234.250]) by smtp.gmail.com with ESMTPSA id f144sm18258897pfa.24.2021.09.21.11.46.11 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 21 Sep 2021 11:46:13 -0700 (PDT) From: Kashyap Desai To: linux-scsi@vger.kernel.org Cc: jejb@linux.ibm.com, martin.petersen@oracle.com, steve.hagan@broadcom.com, mpi3mr-linuxdrv.pdl@broadcom.com, Kashyap Desai Subject: [PATCH 2/7] miscdevice: adding support for MPI3MR_MINOR(243) Date: Wed, 22 Sep 2021 00:15:55 +0530 Message-Id: <20210921184600.64427-3-kashyap.desai@broadcom.com> X-Mailer: git-send-email 2.18.1 In-Reply-To: <20210921184600.64427-1-kashyap.desai@broadcom.com> References: <20210921184600.64427-1-kashyap.desai@broadcom.com> Precedence: bulk List-ID: X-Mailing-List: linux-scsi@vger.kernel.org --- include/linux/miscdevice.h | 1 + 1 file changed, 1 insertion(+) diff --git a/include/linux/miscdevice.h b/include/linux/miscdevice.h index 0676f18093f9..2d4d1502c1aa 100644 --- a/include/linux/miscdevice.h +++ b/include/linux/miscdevice.h @@ -71,6 +71,7 @@ #define USERIO_MINOR 240 #define VHOST_VSOCK_MINOR 241 #define RFKILL_MINOR 242 +#define MPI3MR_MINOR 243 #define MISC_DYNAMIC_MINOR 255 struct device; From patchwork Tue Sep 21 18:45:56 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Kashyap Desai X-Patchwork-Id: 12508637 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-20.1 required=3.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_CR_TRAILER,INCLUDES_PATCH,MAILING_LIST_MULTI,MIME_HEADER_CTYPE_ONLY, SPF_HELO_NONE,SPF_PASS,T_TVD_MIME_NO_HEADERS,URIBL_BLOCKED,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 33641C433EF for ; Tue, 21 Sep 2021 18:46:56 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 12E2561186 for ; Tue, 21 Sep 2021 18:46:56 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S233978AbhIUSsD (ORCPT ); Tue, 21 Sep 2021 14:48:03 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:40226 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231446AbhIUSrq (ORCPT ); Tue, 21 Sep 2021 14:47:46 -0400 Received: from mail-pl1-x62b.google.com (mail-pl1-x62b.google.com [IPv6:2607:f8b0:4864:20::62b]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id BFABAC061574 for ; Tue, 21 Sep 2021 11:46:17 -0700 (PDT) Received: by mail-pl1-x62b.google.com with SMTP id n18so23057plp.7 for ; Tue, 21 Sep 2021 11:46:17 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=broadcom.com; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=OwPy8zKfimZJx9Q6nVxwgwiPC8w/5O5PvtDTTl2lDPI=; b=UQ6z5717uPjJK/7CLP0jXw/FBFWR2iW47vH2vcSckbT9AMBVeMRALM1p0j2NS1Gjko Y9DL0LRwl/mrmjePDodhnpjJzC+qMcudLXliL66L4tUXmCxXtAKFolTheTte9mWjmV0s rNu3mdeEsvsB83RSn7RrLNRu8Y3cdlPbrDQKA= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=OwPy8zKfimZJx9Q6nVxwgwiPC8w/5O5PvtDTTl2lDPI=; b=hzEzkgdJmccItKyRWR5Ww3i/7mLZGDB+L0Bi/QHTMksj4vdV2Gc+XkSobj9XcaBUhU /QTAhvQgtgxVv2h1slfh42RRc0WMETKOsndAn+ZAyZB8lj7ztTfCoYOyd+hmkbp3Y/bE ZwFaL3CZ7mFruCvhqifwRjxaNCq/HJbVf00Sf044r0QF/cry91VZFV+PTVb85uW+ajIe mm9rMCeRfhg4HrsojShqc1Cmmc8vwf7B/+okWuhvnDWtlxaD2tmEquTROd3cNllD6feL RTaOhIBN+v6MljRoEAKoQIS7cuf/pTSlvrcFsP3HNJ8HMJmH2raSfYI4491pEWmiWkhX Y85g== X-Gm-Message-State: AOAM5317caokgMYbS9hsTuAqXq2vly9fr8nhUrIkWW8mY/AT+iNg+xRJ qIJmoPuNobRn2QyktvEQLFafKK+uhYlIXfzlGD1ynnNz32JAPxGECLT7jctLgknQOdcKhpdULof QM6vpJ6ZC5zmSVAvfw1jBXa4vpATE4IRTFOXBivb22BXT2lazHSM74RD3qF2xXdUseCrM/ewwsy rDw/cD96u/ X-Google-Smtp-Source: ABdhPJxM9nnx9LmE5So7j916Lx127/hnVa8CgWEoWlynJ46FPRQ+uQTlj1TlFu6bExVkkjqqdhuS5w== X-Received: by 2002:a17:90a:53:: with SMTP id 19mr6760513pjb.159.1632249976169; Tue, 21 Sep 2021 11:46:16 -0700 (PDT) Received: from drv-bst-rhel8.dhcp.broadcom.net ([192.19.234.250]) by smtp.gmail.com with ESMTPSA id f144sm18258897pfa.24.2021.09.21.11.46.13 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 21 Sep 2021 11:46:15 -0700 (PDT) From: Kashyap Desai To: linux-scsi@vger.kernel.org Cc: jejb@linux.ibm.com, martin.petersen@oracle.com, steve.hagan@broadcom.com, mpi3mr-linuxdrv.pdl@broadcom.com, Kashyap Desai , sathya.prakash@broadcom.com Subject: [PATCH 3/7] mpi3mr: controller management application support Date: Wed, 22 Sep 2021 00:15:56 +0530 Message-Id: <20210921184600.64427-4-kashyap.desai@broadcom.com> X-Mailer: git-send-email 2.18.1 In-Reply-To: <20210921184600.64427-1-kashyap.desai@broadcom.com> References: <20210921184600.64427-1-kashyap.desai@broadcom.com> Precedence: bulk List-ID: X-Mailing-List: linux-scsi@vger.kernel.org This patch series implements various IOCTL interfaces in the mpi3mr driver for supporting management applications developed specifically to manage the Avenger series of the RAID and I/O controllers and devices attached to those controllers Signed-off-by: Kashyap Desai Cc: sathya.prakash@broadcom.com --- drivers/scsi/mpi3mr/Makefile | 1 + drivers/scsi/mpi3mr/mpi3mr.h | 23 + drivers/scsi/mpi3mr/mpi3mr_app.c | 850 +++++++++++++++++++++++++++++++ drivers/scsi/mpi3mr/mpi3mr_app.h | 369 ++++++++++++++ drivers/scsi/mpi3mr/mpi3mr_fw.c | 24 + drivers/scsi/mpi3mr/mpi3mr_os.c | 9 +- 6 files changed, 1274 insertions(+), 2 deletions(-) create mode 100644 drivers/scsi/mpi3mr/mpi3mr_app.c create mode 100644 drivers/scsi/mpi3mr/mpi3mr_app.h diff --git a/drivers/scsi/mpi3mr/Makefile b/drivers/scsi/mpi3mr/Makefile index 7c2063e04c81..7c1f79186679 100644 --- a/drivers/scsi/mpi3mr/Makefile +++ b/drivers/scsi/mpi3mr/Makefile @@ -2,3 +2,4 @@ obj-m += mpi3mr.o mpi3mr-y += mpi3mr_os.o \ mpi3mr_fw.o \ + mpi3mr_app.o diff --git a/drivers/scsi/mpi3mr/mpi3mr.h b/drivers/scsi/mpi3mr/mpi3mr.h index 9787b53a2b59..5ae73927590c 100644 --- a/drivers/scsi/mpi3mr/mpi3mr.h +++ b/drivers/scsi/mpi3mr/mpi3mr.h @@ -538,6 +538,7 @@ struct mpi3mr_sdev_priv_data { * @ioc_status: IOC status from the firmware * @ioc_loginfo:IOC log info from the firmware * @is_waiting: Is the command issued in block mode + * @is_sense: Is Sense data present * @retry_count: Retry count for retriable commands * @host_tag: Host tag used by the command * @callback: Callback for non blocking commands @@ -553,6 +554,7 @@ struct mpi3mr_drv_cmd { u16 ioc_status; u32 ioc_loginfo; u8 is_waiting; + bool is_sense; u8 retry_count; u16 host_tag; @@ -679,6 +681,7 @@ struct scmd_priv { * @chain_bitmap_sz: Chain buffer allocator bitmap size * @chain_bitmap: Chain buffer allocator bitmap * @chain_buf_lock: Chain buffer list lock + * @ioctl_cmds: Command tracker for IOCTL command * @host_tm_cmds: Command tracker for task management commands * @dev_rmhs_cmds: Command tracker for device removal commands * @devrem_bitmap_sz: Device removal bitmap size @@ -690,6 +693,7 @@ struct scmd_priv { * @fault_dbg: Fault debug flag * @reset_in_progress: Reset in progress flag * @unrecoverable: Controller unrecoverable flag + * @block_ioctls: Block IOCTL flag * @reset_mutex: Controller reset mutex * @reset_waitq: Controller reset wait queue * @diagsave_timeout: Diagnostic information save timeout @@ -699,6 +703,9 @@ struct scmd_priv { * @driver_info: Driver, Kernel, OS information to firmware * @change_count: Topology change count * @op_reply_q_offset: Operational reply queue offset with MSIx + * @logdata_buf: Circular buffer to store log data entries + * @logdata_buf_idx: Index of entry in buffer to store + * @logdata_entry_sz: log data entry size */ struct mpi3mr_ioc { struct list_head list; @@ -803,6 +810,7 @@ struct mpi3mr_ioc { void *chain_bitmap; spinlock_t chain_buf_lock; + struct mpi3mr_drv_cmd ioctl_cmds; struct mpi3mr_drv_cmd host_tm_cmds; struct mpi3mr_drv_cmd dev_rmhs_cmds[MPI3MR_NUM_DEVRMCMD]; u16 devrem_bitmap_sz; @@ -815,6 +823,7 @@ struct mpi3mr_ioc { u8 fault_dbg; u8 reset_in_progress; u8 unrecoverable; + u8 block_ioctls; struct mutex reset_mutex; wait_queue_head_t reset_waitq; @@ -826,6 +835,10 @@ struct mpi3mr_ioc { struct mpi3_driver_info_layout driver_info; u16 change_count; u16 op_reply_q_offset; + + u8 *logdata_buf; + u16 logdata_buf_idx; + u16 logdata_entry_sz; }; /** @@ -889,6 +902,13 @@ void mpi3mr_repost_sense_buf(struct mpi3mr_ioc *mrioc, void mpi3mr_memset_buffers(struct mpi3mr_ioc *mrioc); void mpi3mr_os_handle_events(struct mpi3mr_ioc *mrioc, struct mpi3_event_notification_reply *event_reply); +struct mpi3mr_tgt_dev *mpi3mr_get_tgtdev_by_handle( + struct mpi3mr_ioc *mrioc, u16 handle); +struct mpi3mr_tgt_dev *mpi3mr_get_tgtdev_by_perst_id( + struct mpi3mr_ioc *mrioc, u16 persist_id); +struct mpi3mr_tgt_dev *mpi3mr_get_tgtdev_from_tgtpriv( + struct mpi3mr_ioc *mrioc, + struct mpi3mr_stgt_priv_data *tgt_priv); void mpi3mr_process_op_reply_desc(struct mpi3mr_ioc *mrioc, struct mpi3_default_reply_descriptor *reply_desc, u64 *reply_dma, u16 qidx); @@ -913,4 +933,7 @@ void mpi3mr_invalidate_devhandles(struct mpi3mr_ioc *mrioc); void mpi3mr_rfresh_tgtdevs(struct mpi3mr_ioc *mrioc); void mpi3mr_flush_delayed_rmhs_list(struct mpi3mr_ioc *mrioc); +void mpi3mr_app_init(void); +void mpi3mr_app_exit(void); + #endif /*MPI3MR_H_INCLUDED*/ diff --git a/drivers/scsi/mpi3mr/mpi3mr_app.c b/drivers/scsi/mpi3mr/mpi3mr_app.c new file mode 100644 index 000000000000..021615889dcd --- /dev/null +++ b/drivers/scsi/mpi3mr/mpi3mr_app.c @@ -0,0 +1,850 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Driver for Broadcom MPI3 Storage Controllers + * + * Copyright (C) 2017-2021 Broadcom Inc. + * (mailto: mpi3mr-linuxdrv.pdl@broadcom.com) + * + */ + +#include "mpi3mr.h" +#include "mpi3mr_app.h" + +static struct fasync_struct *mpi3mr_app_async_queue; + +/** + * mpi3mr_verify_adapter - verify adapter number is valid + * @ioc_number: Adapter number + * @mriocpp: Pointer to hold per adapter instance + * + * This function checks whether given adapter number matches + * with an adapter id in the driver's list and if so fills + * pointer to the per adapter instance in mriocpp else set that + * to NULL. + * + * Return: Nothing. + */ +static void mpi3mr_verify_adapter(int ioc_number, struct mpi3mr_ioc **mriocpp) +{ + struct mpi3mr_ioc *mrioc; + + spin_lock(&mrioc_list_lock); + list_for_each_entry(mrioc, &mrioc_list, list) { + if (mrioc->id != ioc_number) + continue; + spin_unlock(&mrioc_list_lock); + *mriocpp = mrioc; + return; + } + spin_unlock(&mrioc_list_lock); + *mriocpp = NULL; +} + +/** + * mpi3mr_get_all_tgt_info - Get all target information + * @mrioc: Adapter instance reference + * @data_in_buf: User buffer to copy the target information + * @data_in_sz: length of the user buffer. + * + * This function copies the driver managed target devices device + * handle, persistent ID, bus ID and taret ID to the user + * provided buffer for the specific controller. This function + * also provides the number of devices managed by the driver for + * the specific controller. + * + * Return: 0 on success and proper error codes on failure + */ +static long mpi3mr_get_all_tgt_info(struct mpi3mr_ioc *mrioc, + void __user *data_in_buf, uint32_t data_in_sz) +{ + long rval = 0, devmap_info_sz; + u16 num_devices = 0, i = 0; + unsigned long flags; + struct mpi3mr_tgt_dev *tgtdev; + struct mpi3mr_device_map_info *devmap_info = NULL; + struct mpi3mr_all_tgt_info __user *all_tgt_info = + (struct mpi3mr_all_tgt_info *)data_in_buf; + u32 min_entrylen, kern_entrylen = 0, usr_entrylen; + + if (data_in_sz < sizeof(u32)) { + dbgprint(mrioc, "failure at %s:%d/%s()!\n", + __FILE__, __LINE__, __func__); + return -EINVAL; + } + + devmap_info_sz = sizeof(struct mpi3mr_device_map_info); + + spin_lock_irqsave(&mrioc->tgtdev_lock, flags); + list_for_each_entry(tgtdev, &mrioc->tgtdev_list, list) + num_devices++; + spin_unlock_irqrestore(&mrioc->tgtdev_lock, flags); + + usr_entrylen = (data_in_sz - sizeof(u32)) / devmap_info_sz; + usr_entrylen *= devmap_info_sz; + + if (!num_devices || !usr_entrylen) + goto copy_usrbuf; + + devmap_info = kcalloc(num_devices, devmap_info_sz, GFP_KERNEL); + if (!devmap_info) + return -ENOMEM; + + kern_entrylen = num_devices * devmap_info_sz; + memset((u8 *)devmap_info, 0xFF, kern_entrylen); + spin_lock_irqsave(&mrioc->tgtdev_lock, flags); + list_for_each_entry(tgtdev, &mrioc->tgtdev_list, list) { + if (i >= num_devices) + break; + devmap_info[i].handle = tgtdev->dev_handle; + devmap_info[i].perst_id = tgtdev->perst_id; + if (tgtdev->host_exposed && tgtdev->starget) { + devmap_info[i].target_id = tgtdev->starget->id; + devmap_info[i].bus_id = tgtdev->starget->channel; + } + i++; + } + num_devices = i; + spin_unlock_irqrestore(&mrioc->tgtdev_lock, flags); + +copy_usrbuf: + if (copy_to_user(&all_tgt_info->num_devices, &num_devices, + sizeof(num_devices))) + rval = -EFAULT; + else { + min_entrylen = min(usr_entrylen, kern_entrylen); + if (min_entrylen && + copy_to_user(&all_tgt_info->dmi, + devmap_info, min_entrylen)) + rval = -EFAULT; + } + + kfree(devmap_info); + return rval; +} + +/** + * mpi3mr_enable_logdata - Handler for log data enable IOCTL + * @mrioc: Adapter instance reference + * @data_in_buf: User buffer to copy the max logdata entry count + * @data_in_sz: length of the user buffer. + * + * This function enables log data caching in the driver if not + * already enabled and return the maximum number of log data + * entries that can be cached in the driver. + * + * Return: 0 on success and proper error codes on failure + */ +static long mpi3mr_enable_logdata(struct mpi3mr_ioc *mrioc, + void __user *data_in_buf, uint32_t data_in_sz) +{ + struct mpi3mr_logdata_enable logdata_enable; + u16 entry_size; + + entry_size = mrioc->facts.reply_sz - + (sizeof(struct mpi3_event_notification_reply) - 4); + entry_size += MPI3MR_IOCTL_LOGDATA_ENTRY_HEADER_SZ; + logdata_enable.max_entries = MPI3MR_IOCTL_LOGDATA_MAX_ENTRIES; + + if (!mrioc->logdata_buf) { + mrioc->logdata_buf_idx = 0; + mrioc->logdata_entry_sz = entry_size; + mrioc->logdata_buf = + kcalloc(MPI3MR_IOCTL_LOGDATA_MAX_ENTRIES, + entry_size, GFP_KERNEL); + if (!mrioc->logdata_buf) + return -ENOMEM; + } + + if (copy_to_user(data_in_buf, &logdata_enable, sizeof(logdata_enable))) + return -EFAULT; + + return 0; +} + +/** + * mpi3mr_get_logdata - Handler for get log data IOCTL + * @mrioc: Adapter instance reference + * @data_in_buf: User buffer to copy the logdata entries + * @data_in_sz: length of the user buffer. + * + * This function copies the log data entries to the user buffer + * when log caching is enabled in the driver. + * + * Return: 0 on success and proper error codes on failure + */ +static long mpi3mr_get_logdata(struct mpi3mr_ioc *mrioc, + void __user *data_in_buf, uint32_t data_in_sz) +{ + u16 num_entries, sz, entry_sz; + + entry_sz = mrioc->logdata_entry_sz; + if ((!mrioc->logdata_buf) || (data_in_sz < entry_sz)) + return -EINVAL; + + num_entries = data_in_sz / entry_sz; + num_entries = min_t(int, num_entries, + MPI3MR_IOCTL_LOGDATA_MAX_ENTRIES); + sz = num_entries * entry_sz; + + if (copy_to_user(data_in_buf, mrioc->logdata_buf, sz)) + return -EFAULT; + + return 0; +} + +/** + * mpi3mr_get_change_count - Get topology change count + * @mrioc: Adapter instance reference + * @data_in_buf: User buffer to copy the change count + * @data_in_sz: length of the user buffer. + * + * This function copies the topology change count provided by the + * driver in events and cached in the driver to the user + * provided buffer for the specific controller. + * + * Return: 0 on success and proper error codes on failure + */ +static long mpi3mr_get_change_count(struct mpi3mr_ioc *mrioc, + void __user *data_in_buf, uint32_t data_in_sz) +{ + struct mpi3mr_change_count chgcnt; + + chgcnt.change_count = mrioc->change_count; + if (copy_to_user(data_in_buf, &chgcnt, sizeof(chgcnt))) + return -EFAULT; + + return 0; +} + +/** + * mpi3mr_ioctl_adp_reset - Issue controller reset + * @mrioc: Adapter instance reference + * @data_out_buf: User buffer with reset type + * @data_out_sz: length of the user buffer. + * + * This function identifies the user provided reset type and + * issues approporiate reset to the controller and.wait for that + * to complete and reinitialize the controller and then returns + * + * Return: 0 on success and proper error codes on failure + */ +static long mpi3mr_ioctl_adp_reset(struct mpi3mr_ioc *mrioc, + void __user *data_out_buf, uint32_t data_out_sz) +{ + long rval = 0; + struct mpi3mr_ioctl_adp_reset adpreset; + u8 save_snapdump; + + if (copy_from_user(&adpreset, data_out_buf, sizeof(adpreset))) + return -EFAULT; + + switch (adpreset.reset_type) { + case MPI3MR_IOCTL_ADPRESET_SOFT: + save_snapdump = 0; + break; + case MPI3MR_IOCTL_ADPRESET_DIAG_FAULT: + save_snapdump = 1; + break; + default: + dbgprint(mrioc, "%s: unknown reset_type(%d)\n", + __func__, adpreset.reset_type); + return -EINVAL; + } + + rval = mpi3mr_soft_reset_handler(mrioc, MPI3MR_RESET_FROM_IOCTL, + save_snapdump); + + if (rval) + dbgprint(mrioc, + "%s: reset handler returned error(%ld) for reset type %d\n", + __func__, rval, adpreset.reset_type); + + return rval; +} + +/** + * mpi3mr_populate_adpinfo - Get adapter info IOCTL handler + * @mrioc: Adapter instance reference + * @data_in_buf: User buffer to hold adapter information + * @data_in_sz: length of the user buffer. + * + * This function provides adapter information for the given + * controller + * + * Return: 0 on success and proper error codes on failure + */ +static long mpi3mr_populate_adpinfo(struct mpi3mr_ioc *mrioc, + void __user *data_in_buf, uint32_t data_in_sz) +{ + struct mpi3mr_adp_info adpinfo; + + memset(&adpinfo, 0, sizeof(adpinfo)); + adpinfo.adp_type = MPI3MR_IOCTL_ADPTYPE_AVGFAMILY; + adpinfo.pci_dev_id = mrioc->pdev->device; + adpinfo.pci_dev_hw_rev = mrioc->pdev->revision; + adpinfo.pci_subsys_dev_id = mrioc->pdev->subsystem_device; + adpinfo.pci_subsys_ven_id = mrioc->pdev->subsystem_vendor; + adpinfo.pci_bus = mrioc->pdev->bus->number; + adpinfo.pci_dev = PCI_SLOT(mrioc->pdev->devfn); + adpinfo.pci_func = PCI_FUNC(mrioc->pdev->devfn); + adpinfo.pci_seg_id = pci_domain_nr(mrioc->pdev->bus); + adpinfo.ioctl_ver = MPI3MR_IOCTL_VERSION; + memcpy((u8 *)&adpinfo.driver_info, (u8 *)&mrioc->driver_info, + sizeof(adpinfo.driver_info)); + + if (copy_to_user(data_in_buf, &adpinfo, sizeof(adpinfo))) + return -EFAULT; + + return 0; +} + +/** + * mpi3mr_ioctl_process_drv_cmds - Driver IOCTL handler + * @mrioc: Adapter instance reference + * @arg: User data payload buffer for the IOCTL + * + * This function is the top level handler for driver commands, + * this does basic validation of the buffer and identifies the + * opcode and switches to correct sub handler. + * + * Return: 0 on success and proper error codes on failure + */ +static long +mpi3mr_ioctl_process_drv_cmds(struct file *file, void __user *arg) +{ + long rval = 0; + struct mpi3mr_ioc *mrioc = NULL; + struct mpi3mr_ioctl_drv_cmd karg; + + if (copy_from_user(&karg, arg, sizeof(karg))) + return -EFAULT; + + mpi3mr_verify_adapter(karg.mrioc_id, &mrioc); + if (!mrioc) + return -ENODEV; + + if (file->f_flags & O_NONBLOCK) { + if (!mutex_trylock(&mrioc->ioctl_cmds.mutex)) + return -EAGAIN; + } else if (mutex_lock_interruptible(&mrioc->ioctl_cmds.mutex)) + return -ERESTARTSYS; + + switch (karg.opcode) { + case MPI3MR_DRVIOCTL_OPCODE_ADPINFO: + rval = mpi3mr_populate_adpinfo(mrioc, karg.data_in_buf, + karg.data_in_size); + break; + case MPI3MR_DRVIOCTL_OPCODE_ADPRESET: + rval = mpi3mr_ioctl_adp_reset(mrioc, karg.data_out_buf, + karg.data_out_size); + break; + case MPI3MR_DRVIOCTL_OPCODE_ALLTGTDEVINFO: + rval = mpi3mr_get_all_tgt_info(mrioc, karg.data_in_buf, + karg.data_in_size); + break; + case MPI3MR_DRVIOCTL_OPCODE_LOGDATAENABLE: + rval = mpi3mr_enable_logdata(mrioc, karg.data_in_buf, + karg.data_in_size); + break; + case MPI3MR_DRVIOCTL_OPCODE_GETLOGDATA: + rval = mpi3mr_get_logdata(mrioc, karg.data_in_buf, + karg.data_in_size); + break; + case MPI3MR_DRVIOCTL_OPCODE_GETCHGCNT: + rval = mpi3mr_get_change_count(mrioc, karg.data_in_buf, + karg.data_in_size); + break; + case MPI3MR_DRVIOCTL_OPCODE_UNKNOWN: + default: + rval = -EINVAL; + dbgprint(mrioc, "Unsupported drv ioctl opcode 0x%x\n", + karg.opcode); + break; + } + mutex_unlock(&mrioc->ioctl_cmds.mutex); + return rval; +} + +/** + * mpi3mr_ioctl_build_sgl - SGL consturction for MPI IOCTLs + * @mpi_req: MPI request + * @sgl_offset: offset to start SGL in the MPI request + * @dma_buffers: DMA address of the buffers to be placed in SGL + * @bufcnt: Number of DMA buffers + * @is_rmc: Does the buffer list has management command buffer + * @is_rmr: Does the buffer list has management response buffer + * @num_data_sges: Number of data buffers in the list + * + * This function places the DMA address of the given buffers in + * proper format as SGEs in the given MPI request. + * + * Return: Nothing + */ +static void mpi3mr_ioctl_build_sgl(u8 *mpi_req, uint32_t sgl_offset, + struct mpi3mr_buf_map *dma_buffers, + u8 bufcnt, bool is_rmc, bool is_rmr, u8 num_data_sges) +{ + u8 *sgl; + u8 sgl_flags, sgl_flags_last, count = 0; + struct mpi3_mgmt_passthrough_request *mgmt_pt_req; + struct mpi3mr_buf_map *dma_buff; + + sgl = (mpi_req + sgl_offset); + mgmt_pt_req = (struct mpi3_mgmt_passthrough_request *)mpi_req; + dma_buff = dma_buffers; + + sgl_flags = MPI3_SGE_FLAGS_ELEMENT_TYPE_SIMPLE | + MPI3_SGE_FLAGS_DLAS_SYSTEM | + MPI3_SGE_FLAGS_END_OF_BUFFER; + + sgl_flags_last = sgl_flags | MPI3_SGE_FLAGS_END_OF_LIST; + + if (is_rmc) { + mpi3mr_add_sg_single(&mgmt_pt_req->command_sgl, + sgl_flags_last, dma_buff->kern_buf_len, + dma_buff->kern_buf_dma); + sgl = (u8 *)dma_buff->kern_buf + dma_buff->user_buf_len; + dma_buff++; + count++; + if (is_rmr) { + mpi3mr_add_sg_single(&mgmt_pt_req->response_sgl, + sgl_flags_last, + dma_buff->kern_buf_len, + dma_buff->kern_buf_dma); + dma_buff++; + count++; + } else + mpi3mr_build_zero_len_sge(&mgmt_pt_req->response_sgl); + } + if (!num_data_sges) { + mpi3mr_build_zero_len_sge(sgl); + return; + } + for (; count < bufcnt; count++, dma_buff++) { + if (dma_buff->data_dir == DMA_BIDIRECTIONAL) + continue; + if (num_data_sges == 1 || !is_rmc) + mpi3mr_add_sg_single(sgl, sgl_flags_last, + dma_buff->kern_buf_len, + dma_buff->kern_buf_dma); + else + mpi3mr_add_sg_single(sgl, sgl_flags, + dma_buff->kern_buf_len, + dma_buff->kern_buf_dma); + sgl += sizeof(struct mpi3_sge_common); + num_data_sges--; + } +} + +/** + * mpi3mr_ioctl_process_mpt_cmds - MPI Pass through IOCTL handler + * @mrioc: Adapter instance reference + * @arg: User data payload buffer for the IOCTL + * + * This function is the top level handler for MPI Pass through + * IOCTL, this does basic validation of the input data buffers, + * identifies the given buffer types and MPI command, allocates + * DMAable memory for user given buffers, constructs SGL + * properly and passes the command to the firmware. + * + * Once the MPI command is completed the driver copies the data + * if any and reply, sense information to user provided buffers. + * If the command is timed out then issues controller reset + * prior to returning. + * + * Return: 0 on success and proper error codes on failure + */ +static long mpi3mr_ioctl_process_mpt_cmds(struct file *file, + void __user *arg) +{ + long rval = -EINVAL; + struct mpi3mr_ioc *mrioc = NULL; + struct mpi3mr_ioctl_mptcmd karg; + struct mpi3mr_ioctl_buf_entry_list *buffer_list = NULL; + struct mpi3mr_buf_entry *buf_entries = NULL; + struct mpi3mr_buf_map *dma_buffers = NULL, *dma_buff; + struct mpi3_request_header *mpi_header = NULL; + struct mpi3_status_reply_descriptor *status_desc; + struct mpi3mr_ioctl_reply_buf *ioctl_reply_buf = NULL; + u8 *mpi_req = NULL, *sense_buff_k = NULL; + u8 count, bufcnt, din_cnt = 0, dout_cnt = 0; + u8 erb_offset = 0xFF, reply_offset = 0xFF, sg_entries = 0; + bool invalid_be = false, is_rmcb = false, is_rmrb = false; + u32 tmplen; + + if (copy_from_user(&karg, arg, sizeof(karg))) + return -EFAULT; + + mpi3mr_verify_adapter(karg.mrioc_id, &mrioc); + if (!mrioc) + return -ENODEV; + + if (karg.timeout < MPI3MR_IOCTL_DEFAULT_TIMEOUT) + karg.timeout = MPI3MR_IOCTL_DEFAULT_TIMEOUT; + + if (!karg.buf_entry_list_size || !karg.mpi_msg_size) + return -EINVAL; + + if ((karg.mpi_msg_size * 4) > MPI3MR_ADMIN_REQ_FRAME_SZ) + return -EINVAL; + + mpi_req = kzalloc(MPI3MR_ADMIN_REQ_FRAME_SZ, GFP_KERNEL); + if (!mpi_req) + return -ENOMEM; + + mpi_header = (struct mpi3_request_header *)mpi_req; + + if (copy_from_user(mpi_req, karg.mpi_msg_buf, + (karg.mpi_msg_size * 4))) + goto out; + + buffer_list = kzalloc(karg.buf_entry_list_size, GFP_KERNEL); + if (!buffer_list) { + rval = -ENOMEM; + goto out; + } + + if (copy_from_user(buffer_list, karg.buf_entry_list, + karg.buf_entry_list_size)) { + rval = -EFAULT; + goto out; + } + + if (!buffer_list->num_of_entries) { + rval = -EINVAL; + goto out; + } + + bufcnt = buffer_list->num_of_entries; + dma_buffers = kzalloc((sizeof(struct mpi3mr_buf_map) * bufcnt), GFP_KERNEL); + if (!dma_buffers) { + rval = -ENOMEM; + goto out; + } + + buf_entries = buffer_list->buf_entry; + dma_buff = dma_buffers; + for (count = 0; count < bufcnt; count++, buf_entries++, dma_buff++) { + dma_buff->user_buf = buf_entries->buffer; + dma_buff->user_buf_len = buf_entries->buf_len; + + switch (buf_entries->buf_type) { + case MPI3MR_IOCTL_BUFTYPE_RAIDMGMT_CMD: + is_rmcb = true; + if (count != 0) + invalid_be = true; + dma_buff->data_dir = DMA_FROM_DEVICE; + break; + case MPI3MR_IOCTL_BUFTYPE_RAIDMGMT_RESP: + is_rmrb = true; + if (count != 1 || !is_rmcb) + invalid_be = true; + dma_buff->data_dir = DMA_TO_DEVICE; + break; + case MPI3MR_IOCTL_BUFTYPE_DATA_IN: + din_cnt++; + if ((din_cnt > 1) && !is_rmcb) + invalid_be = true; + dma_buff->data_dir = DMA_TO_DEVICE; + break; + case MPI3MR_IOCTL_BUFTYPE_DATA_OUT: + dout_cnt++; + if ((dout_cnt > 1) && !is_rmcb) + invalid_be = true; + dma_buff->data_dir = DMA_FROM_DEVICE; + break; + case MPI3MR_IOCTL_BUFTYPE_MPI_REPLY: + reply_offset = count; + dma_buff->data_dir = DMA_BIDIRECTIONAL; + break; + case MPI3MR_IOCTL_BUFTYPE_ERR_RESPONSE: + erb_offset = count; + dma_buff->data_dir = DMA_BIDIRECTIONAL; + break; + default: + invalid_be = true; + break; + } + if (invalid_be) + break; + } + if (invalid_be) { + rval = -EINVAL; + goto out; + } + + if (!is_rmcb && (dout_cnt || din_cnt)) { + sg_entries = dout_cnt + din_cnt; + if (((karg.mpi_msg_size * 4) + (sg_entries * + sizeof(struct mpi3_sge_common))) > MPI3MR_ADMIN_REQ_FRAME_SZ) { + rval = -EINVAL; + goto out; + } + } + + dma_buff = dma_buffers; + for (count = 0; count < bufcnt; count++, dma_buff++) { + dma_buff->kern_buf_len = dma_buff->user_buf_len; + if (is_rmcb && !count) + dma_buff->kern_buf_len += ((dout_cnt + din_cnt) * + sizeof(struct mpi3_sge_common)); + if ((count == reply_offset) || (count == erb_offset)) { + dma_buff->kern_buf_len = 0; + continue; + } + if (!dma_buff->kern_buf_len) + continue; + + dma_buff->kern_buf = dma_alloc_coherent(&mrioc->pdev->dev, + dma_buff->kern_buf_len, + &dma_buff->kern_buf_dma, + GFP_KERNEL); + if (!dma_buff->kern_buf) { + rval = -ENOMEM; + goto out; + } + if (dma_buff->data_dir == DMA_FROM_DEVICE) { + tmplen = min(dma_buff->kern_buf_len, + dma_buff->user_buf_len); + if (copy_from_user(dma_buff->kern_buf, + dma_buff->user_buf, tmplen)) { + rval = -EFAULT; + goto out; + } + } + } + if (erb_offset != 0xFF) { + sense_buff_k = kzalloc(MPI3MR_SENSE_BUF_SZ, GFP_KERNEL); + if (!sense_buff_k) { + rval = -ENOMEM; + goto out; + } + } + + if (mpi_header->function != MPI3_FUNCTION_NVME_ENCAPSULATED) + mpi3mr_ioctl_build_sgl(mpi_req, (karg.mpi_msg_size * 4), + dma_buffers, bufcnt, is_rmcb, + is_rmrb, (dout_cnt + din_cnt)); + + if (file->f_flags & O_NONBLOCK) { + if (!mutex_trylock(&mrioc->ioctl_cmds.mutex)) { + rval = -EAGAIN; + goto out; + } + } else if (mutex_lock_interruptible(&mrioc->ioctl_cmds.mutex)) { + rval = -ERESTARTSYS; + goto out; + } + if (mrioc->ioctl_cmds.state & MPI3MR_CMD_PENDING) { + rval = -EAGAIN; + dbgprint(mrioc, "%s command is in use\n", __func__); + mutex_unlock(&mrioc->ioctl_cmds.mutex); + goto out; + } + if (mrioc->reset_in_progress) { + dbgprint(mrioc, "%s reset in progress\n", __func__); + rval = -EAGAIN; + mutex_unlock(&mrioc->ioctl_cmds.mutex); + goto out; + } + if (mrioc->block_ioctls) { + dbgprint(mrioc, "%s IOCTLs are blocked\n", __func__); + rval = -EAGAIN; + mutex_unlock(&mrioc->ioctl_cmds.mutex); + goto out; + } + + mrioc->ioctl_cmds.state = MPI3MR_CMD_PENDING; + mrioc->ioctl_cmds.is_waiting = 1; + mrioc->ioctl_cmds.callback = NULL; + mrioc->ioctl_cmds.is_sense = false; + mrioc->ioctl_cmds.sensebuf = sense_buff_k; + memset(mrioc->ioctl_cmds.reply, 0, mrioc->facts.reply_sz); + mpi_header->host_tag = cpu_to_le16(MPI3MR_HOSTTAG_IOCTLCMDS); + init_completion(&mrioc->ioctl_cmds.done); + rval = mpi3mr_admin_request_post(mrioc, mpi_req, + MPI3MR_ADMIN_REQ_FRAME_SZ, 0); + if (rval) { + rval = -EAGAIN; + goto out_unlock; + } + wait_for_completion_timeout(&mrioc->ioctl_cmds.done, + (karg.timeout * HZ)); + if (!(mrioc->ioctl_cmds.state & MPI3MR_CMD_COMPLETE)) { + mrioc->ioctl_cmds.is_waiting = 0; + dbgprint(mrioc, "%s command timed out\n", __func__); + rval = -EFAULT; + mpi3mr_soft_reset_handler(mrioc, + MPI3MR_RESET_FROM_IOCTL_TIMEOUT, 1); + goto out_unlock; + } + + if ((mrioc->ioctl_cmds.ioc_status & MPI3_IOCSTATUS_STATUS_MASK) + != MPI3_IOCSTATUS_SUCCESS) { + dbgprint(mrioc, + "%s ioc_status(0x%04x) Loginfo(0x%08x)\n", __func__, + (mrioc->ioctl_cmds.ioc_status & MPI3_IOCSTATUS_STATUS_MASK), + mrioc->ioctl_cmds.ioc_loginfo); + } + + if ((reply_offset != 0xFF) && dma_buffers[reply_offset].user_buf_len) { + dma_buff = &dma_buffers[reply_offset]; + dma_buff->kern_buf_len = + (sizeof(struct mpi3mr_ioctl_reply_buf) - 1 + + mrioc->facts.reply_sz); + ioctl_reply_buf = kzalloc(dma_buff->kern_buf_len, GFP_KERNEL); + + if (!ioctl_reply_buf) { + rval = -ENOMEM; + goto out_unlock; + } + if (mrioc->ioctl_cmds.state & MPI3MR_CMD_REPLY_VALID) { + ioctl_reply_buf->mpi_reply_type = + MPI3MR_IOCTL_MPI_REPLY_BUFTYPE_ADDRESS; + memcpy(ioctl_reply_buf->ioctl_reply_buf, + mrioc->ioctl_cmds.reply, + mrioc->facts.reply_sz); + } else { + ioctl_reply_buf->mpi_reply_type = + MPI3MR_IOCTL_MPI_REPLY_BUFTYPE_STATUS; + status_desc = (struct mpi3_status_reply_descriptor *) + ioctl_reply_buf->ioctl_reply_buf; + status_desc->ioc_status = mrioc->ioctl_cmds.ioc_status; + status_desc->ioc_log_info = mrioc->ioctl_cmds.ioc_loginfo; + } + tmplen = min(dma_buff->kern_buf_len, dma_buff->user_buf_len); + if (copy_to_user(dma_buff->user_buf, ioctl_reply_buf, tmplen)) { + rval = -EFAULT; + goto out_unlock; + } + } + + if (erb_offset != 0xFF && mrioc->ioctl_cmds.sensebuf && + mrioc->ioctl_cmds.is_sense) { + dma_buff = &dma_buffers[erb_offset]; + tmplen = min_t(int, dma_buff->user_buf_len, + MPI3MR_SENSE_BUF_SZ); + if (copy_to_user(dma_buff->user_buf, sense_buff_k, tmplen)) { + rval = -EFAULT; + goto out_unlock; + } + } + + dma_buff = dma_buffers; + for (count = 0; count < bufcnt; count++, dma_buff++) { + if (dma_buff->data_dir == DMA_TO_DEVICE) { + tmplen = min(dma_buff->kern_buf_len, + dma_buff->user_buf_len); + if (copy_to_user(dma_buff->user_buf, + dma_buff->kern_buf, tmplen)) + rval = -EFAULT; + } + } + +out_unlock: + mrioc->ioctl_cmds.is_sense = false; + mrioc->ioctl_cmds.sensebuf = NULL; + mrioc->ioctl_cmds.state = MPI3MR_CMD_NOTUSED; + mutex_unlock(&mrioc->ioctl_cmds.mutex); +out: + kfree(sense_buff_k); + kfree(buffer_list); + kfree(mpi_req); + if (dma_buffers) { + dma_buff = dma_buffers; + for (count = 0; count < bufcnt; count++, dma_buff++) { + if (dma_buff->kern_buf && dma_buff->kern_buf_dma) + dma_free_coherent(&mrioc->pdev->dev, + dma_buff->kern_buf_len, + dma_buff->kern_buf, + dma_buff->kern_buf_dma); + } + kfree(dma_buffers); + } + kfree(ioctl_reply_buf); + return rval; +} + +/** + * mpi3mr_ioctl - Main IOCTL handler + * @file: File pointer + * @cmd: IOCTL command + * @arg: User data payload buffer for the IOCTL + * + * This is main IOCTL handler which checks the command type and + * executes proper sub handler specific for the command. + * + * Return: 0 on success and proper error codes on failure + */ +static long mpi3mr_ioctl(struct file *file, unsigned int cmd, + unsigned long arg) +{ + long rval = -EINVAL; + + switch (cmd) { + case MPI3MRDRVCMD: + if (_IOC_SIZE(cmd) == sizeof(struct mpi3mr_ioctl_drv_cmd)) + rval = mpi3mr_ioctl_process_drv_cmds(file, + (void __user *)arg); + break; + case MPI3MRMPTCMD: + if (_IOC_SIZE(cmd) == sizeof(struct mpi3mr_ioctl_mptcmd)) + rval = mpi3mr_ioctl_process_mpt_cmds(file, + (void __user *)arg); + break; + default: + pr_err("%s:Unsupported ioctl cmd (0x%08x)\n", __func__, cmd); + break; + } + return rval; +} + +/** + * mpi3mr_app_fasync - fasync callback + * @fd: File descriptor + * @filep: File pointer + * @mode: Mode + * + * Return: fasync_helper() returned value + */ +static int mpi3mr_app_fasync(int fd, struct file *filep, int mode) +{ + return fasync_helper(fd, filep, mode, &mpi3mr_app_async_queue); +} + +static const struct file_operations mpi3mr_app_fops = { + .owner = THIS_MODULE, + .unlocked_ioctl = mpi3mr_ioctl, + .fasync = mpi3mr_app_fasync, +}; + +static struct miscdevice mpi3mr_app_dev = { + .minor = MPI3MR_MINOR, + .name = MPI3MR_DEV_NAME, + .fops = &mpi3mr_app_fops, +}; + +/** + * mpi3mr_app_init - Character driver interface initializer + * + */ +void mpi3mr_app_init(void) +{ + mpi3mr_app_async_queue = NULL; + + if (misc_register(&mpi3mr_app_dev) < 0) + pr_err("%s can't register misc device [minor=%d]\n", + MPI3MR_DRIVER_NAME, MPI3MR_MINOR); +} + +/** + * mpi3mr_app_exit - Character driver interface cleanup function + * + */ +void mpi3mr_app_exit(void) +{ + misc_deregister(&mpi3mr_app_dev); +} + +MODULE_ALIAS_MISCDEV(MPI3MR_MINOR); +MODULE_ALIAS("devname:" MPI3MR_DEV_NAME); diff --git a/drivers/scsi/mpi3mr/mpi3mr_app.h b/drivers/scsi/mpi3mr/mpi3mr_app.h new file mode 100644 index 000000000000..ec714d210b9e --- /dev/null +++ b/drivers/scsi/mpi3mr/mpi3mr_app.h @@ -0,0 +1,369 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +/* + * Driver for Broadcom MPI3 Storage Controllers + * + * Copyright (C) 2017-2021 Broadcom Inc. + * (mailto: mpi3mr-linuxdrv.pdl@broadcom.com) + * + */ + +#ifndef MPI3MR_APP_INTFC_H_INCLUDED +#define MPI3MR_APP_INTFC_H_INCLUDED + +#ifdef __KERNEL__ +#include +#endif + +/*Definitions for IOCTL commands*/ +#define MPI3MR_DEV_NAME "mpi3mrctl" +#define MPI3MR_MAGIC_NUMBER 'B' + +#define MPI3MR_IOCTL_VERSION 0x05 + +#define MPI3MR_IOCTL_DEFAULT_TIMEOUT (60) /*seconds*/ + +#define MPI3MR_IOCTL_ADPTYPE_UNKNOWN 0 +#define MPI3MR_IOCTL_ADPTYPE_AVGFAMILY 1 + +#define MPI3MR_IOCTL_ADPRESET_UNKNOWN 0 +#define MPI3MR_IOCTL_ADPRESET_SOFT 1 +#define MPI3MR_IOCTL_ADPRESET_DIAG_FAULT 2 + +#define MPI3MR_IOCTL_LOGDATA_MAX_ENTRIES 400 +#define MPI3MR_IOCTL_LOGDATA_ENTRY_HEADER_SZ 4 + +#define MPI3MR_DRVIOCTL_OPCODE_UNKNOWN 0 +#define MPI3MR_DRVIOCTL_OPCODE_ADPINFO 1 +#define MPI3MR_DRVIOCTL_OPCODE_ADPRESET 2 +#define MPI3MR_DRVIOCTL_OPCODE_ALLTGTDEVINFO 4 +#define MPI3MR_DRVIOCTL_OPCODE_GETCHGCNT 5 +#define MPI3MR_DRVIOCTL_OPCODE_LOGDATAENABLE 6 +#define MPI3MR_DRVIOCTL_OPCODE_PELENABLE 7 +#define MPI3MR_DRVIOCTL_OPCODE_GETLOGDATA 8 +#define MPI3MR_DRVIOCTL_OPCODE_QUERY_HDB 9 +#define MPI3MR_DRVIOCTL_OPCODE_REPOST_HDB 10 +#define MPI3MR_DRVIOCTL_OPCODE_UPLOAD_HDB 11 +#define MPI3MR_DRVIOCTL_OPCODE_REFRESH_HDB_TRIGGERS 12 + + +#define MPI3MR_IOCTL_BUFTYPE_UNKNOWN 0 +#define MPI3MR_IOCTL_BUFTYPE_RAIDMGMT_CMD 1 +#define MPI3MR_IOCTL_BUFTYPE_RAIDMGMT_RESP 2 +#define MPI3MR_IOCTL_BUFTYPE_DATA_IN 3 +#define MPI3MR_IOCTL_BUFTYPE_DATA_OUT 4 +#define MPI3MR_IOCTL_BUFTYPE_MPI_REPLY 5 +#define MPI3MR_IOCTL_BUFTYPE_ERR_RESPONSE 6 + +#define MPI3MR_IOCTL_MPI_REPLY_BUFTYPE_UNKNOWN 0 +#define MPI3MR_IOCTL_MPI_REPLY_BUFTYPE_STATUS 1 +#define MPI3MR_IOCTL_MPI_REPLY_BUFTYPE_ADDRESS 2 + +#define MPI3MR_HDB_BUFTYPE_UNKNOWN 0 +#define MPI3MR_HDB_BUFTYPE_TRACE 1 +#define MPI3MR_HDB_BUFTYPE_FIRMWARE 2 +#define MPI3MR_HDB_BUFTYPE_RESERVED 3 + +#define MPI3MR_HDB_BUFSTATUS_UNKNOWN 0 +#define MPI3MR_HDB_BUFSTATUS_NOT_ALLOCATED 1 +#define MPI3MR_HDB_BUFSTATUS_POSTED_UNPAUSED 2 +#define MPI3MR_HDB_BUFSTATUS_POSTED_PAUSED 3 +#define MPI3MR_HDB_BUFSTATUS_RELEASED 4 + +#define MPI3MR_HDB_TRIGGER_TYPE_UNKNOWN 0 +#define MPI3MR_HDB_TRIGGER_TYPE_DIAGFAULT 1 +#define MPI3MR_HDB_TRIGGER_TYPE_ELEMENT 2 +#define MPI3MR_HDB_TRIGGER_TYPE_MASTER 3 + +/** + * struct mpi3mr_adp_info - Adapter information IOCTL + * data returned by the driver. + * + * @adp_type: Adapter type + * @rsvd1: Reserved + * @pci_dev_id: PCI device ID of the adapter + * @pci_dev_hw_rev: PCI revision of the adapter + * @pci_subsys_dev_id: PCI subsystem device ID of the adapter + * @pci_subsys_ven_id: PCI subsystem vendor ID of the adapter + * @pci_dev: PCI device + * @pci_func: PCI function + * @pci_bus: PCI bus + * @pci_seg_id: PCI segment ID + * @ioctl_ver: version of the IOCTL definition + * @rsvd2: Reserved + * @driver_info: Driver Information (Version/Name) + */ +struct mpi3mr_adp_info { + uint32_t adp_type; + uint32_t rsvd1; + uint32_t pci_dev_id; + uint32_t pci_dev_hw_rev; + uint32_t pci_subsys_dev_id; + uint32_t pci_subsys_ven_id; + uint32_t pci_dev:5; + uint32_t pci_func:3; + uint32_t pci_bus:24; + uint32_t pci_seg_id; + uint32_t ioctl_ver; + uint32_t rsvd2[3]; + struct mpi3_driver_info_layout driver_info; +}; + +/** + * struct mpi3mr_buf_map - local structure to + * track kernel and user buffers associated with an IOCTL + * structure. + * + * @user_buf: User buffer virtual address + * @kern_buf: Kernel buffer virtual address + * @kern_buf_dma: Kernel buffer DMA address + * @user_buf_len: User buffer length + * @kern_buf_len: Kernel buffer length + * @data_dir: Data direction. + */ +struct mpi3mr_buf_map { + void __user *user_buf; + void *kern_buf; + dma_addr_t kern_buf_dma; + u32 user_buf_len; + u32 kern_buf_len; + u8 data_dir; +}; + +/** + * struct mpi3mr_ioctl_adp_reset - Adapter reset IOCTL + * payload data to the driver. + * + * @reset_type: Reset type + * @rsvd1: Reserved + * @rsvd2: Reserved + */ +struct mpi3mr_ioctl_adp_reset { + uint8_t reset_type; + uint8_t rsvd1; + uint16_t rsvd2; +}; + +/** + * struct mpi3mr_change_count - Topology change count + * returned by the driver. + * + * @change_count: Topology change count + * @rsvd: Reserved + */ +struct mpi3mr_change_count { + uint16_t change_count; + uint16_t rsvd; +}; + +/** + * struct mpi3mr_device_map_info - Target device mapping + * information + * + * @handle: Firmware device handle + * @perst_id: Persistent ID assigned by the firmware + * @target_id: Target ID assigned by the driver + * @bus_id: Bus ID assigned by the driver + * @rsvd1: Reserved + * @rsvd2: Reserved + */ +struct mpi3mr_device_map_info { + uint16_t handle; + uint16_t perst_id; + uint32_t target_id; + uint8_t bus_id; + uint8_t rsvd1; + uint16_t rsvd2; +}; + +/** + * struct mpi3mr_all_tgt_info - Target device mapping + * information returned by the driver + * + * @num_devices: The number of devices in driver's inventory + * @rsvd1: Reserved + * @rsvd2: Reserved + * @dmi: Variable length array of mapping information of targets + */ +struct mpi3mr_all_tgt_info { + uint16_t num_devices; //The number of devices in driver's inventory + uint16_t rsvd1; + uint32_t rsvd2; + struct mpi3mr_device_map_info dmi[1]; //Variable length Array +}; + +/** + * struct mpi3mr_logdata_enable - Number of log data + * entries saved by the driver returned as payload data for + * enable logdata IOCTL by the driver. + * + * @max_entries: Number of log data entries cached by the driver + * @rsvd: Reserved + */ +struct mpi3mr_logdata_enable { + uint16_t max_entries; + uint16_t rsvd; +}; + +/** + * struct mpi3mr_ioctl_out_pel_enable - PEL enable IOCTL payload + * data to the driver. + * + * @pel_locale: PEL locale to the firmware + * @pel_class: PEL class to the firmware + * @rsvd: Reserved + */ +struct mpi3mr_ioctl_out_pel_enable { + uint16_t pel_locale; + uint8_t pel_class; + uint8_t rsvd; +}; + +/** + * struct mpi3mr_logdata_entry - Log data entry cached by the + * driver. + * + * @valid_entry: Is the entry valid + * @rsvd1: Reserved + * @rsvd2: Reserved + * @data: Log entry data of controller specific size + */ +struct mpi3mr_logdata_entry { + uint8_t valid_entry; + uint8_t rsvd1; + uint16_t rsvd2; + uint8_t data[1]; //Variable length Array +}; + +/** + * struct mpi3mr_ioctl_in_log_data - Log data entries saved by + * the driver returned as payload data for Get logdata IOCTL + * by the driver. + * + * @entry: Log data entry + */ +struct mpi3mr_ioctl_in_log_data { + struct mpi3mr_logdata_entry entry[1]; //Variable length Array +}; + + +/** + * struct mpi3mr_ioctl_drv_cmd - Generic IOCTL payload data + * structure for all driver specific IOCTLS . + * + * @mrioc_id: Controller ID + * @opcode: Driver IOCTL specific opcode + * @rsvd1: Reserved + * @rsvd2: Reserved + * @data_in_buf: User data buffer pointer of data from driver + * @data_out_buf: User data buffer pointer of data to driver + * @data_in_size: Data in buffer size + * @data_out_size: Data out buffer size + */ +struct mpi3mr_ioctl_drv_cmd { + uint8_t mrioc_id; + uint8_t opcode; + uint16_t rsvd1; + uint32_t rsvd2; +#ifdef __KERNEL__ + void __user *data_in_buf; + void __user *data_out_buf; +#else + void *data_in_buf; + void *data_out_buf; +#endif + uint32_t data_in_size; + uint32_t data_out_size; +}; + +/** + * struct mpi3mr_ioctl_reply_buf - MPI reply buffer returned + * for MPI Passthrough IOCTLs . + * + * @mpi_reply_type: Type of MPI reply + * @rsvd1: Reserved + * @rsvd2: Reserved + * @ioctl_reply_buf: Variable Length buffer based on mpirep type + */ +struct mpi3mr_ioctl_reply_buf { + uint8_t mpi_reply_type; + uint8_t rsvd1; + uint16_t rsvd2; + uint8_t ioctl_reply_buf[1]; /*Variable Length buffer based on mpirep type*/ +}; + + +/** + * struct mpi3mr_buf_entry - User buffer descriptor for MPI + * Passthrough IOCTLs. + * + * @buf_type: Buffer type + * @rsvd1: Reserved + * @rsvd2: Reserved + * @buf_len: Buffer length + * @buffer: User space buffer address + */ +struct mpi3mr_buf_entry { + uint8_t buf_type; + uint8_t rsvd1; + uint16_t rsvd2; + uint32_t buf_len; +#ifdef __KERNEL__ + void __user *buffer; +#else + void *buffer; +#endif +}; + +/** + * struct mpi3mr_ioctl_buf_entry_list - list of user buffer + * descriptor for MPI Passthrough IOCTLs. + * + * @num_of_entries: Number of buffer descriptors + * @rsvd1: Reserved + * @rsvd2: Reserved + * @rsvd3: Reserved + * @buf_entry: Variable length array of buffer descriptors + */ +struct mpi3mr_ioctl_buf_entry_list { + uint8_t num_of_entries; + uint8_t rsvd1; + uint16_t rsvd2; + uint32_t rsvd3; + struct mpi3mr_buf_entry buf_entry[1]; //Variable length Array +}; + +/** + * struct mpi3mr_ioctl_mptcmd - Generic IOCTL payload data + * structure for all MPI Passthrough IOCTLS . + * + * @mrioc_id: Controller ID + * @rsvd1: Reserved + * @timeout: MPI command timeout + * @rsvd2: Reserved + * @mpi_msg_size: MPI message size + * @mpi_msg_buf: MPI message + * @buf_entry_list: Buffer descriptor list + * @buf_entry_list_size: Buffer descriptor list size + */ +struct mpi3mr_ioctl_mptcmd { + uint8_t mrioc_id; + uint8_t rsvd1; + uint16_t timeout; + uint16_t rsvd2; + uint16_t mpi_msg_size; +#ifdef __KERNEL__ + void __user *mpi_msg_buf; + void __user *buf_entry_list; +#else + void *mpi_msg_buf; + void *buf_entry_list; +#endif + uint32_t buf_entry_list_size; +}; + +#define MPI3MRDRVCMD _IOWR(MPI3MR_MAGIC_NUMBER, 1, \ + struct mpi3mr_ioctl_drv_cmd) +#define MPI3MRMPTCMD _IOWR(MPI3MR_MAGIC_NUMBER, 2, \ + struct mpi3mr_ioctl_mptcmd) + +#endif diff --git a/drivers/scsi/mpi3mr/mpi3mr_fw.c b/drivers/scsi/mpi3mr/mpi3mr_fw.c index 878a4963e2ad..337cbb3ffaaa 100644 --- a/drivers/scsi/mpi3mr/mpi3mr_fw.c +++ b/drivers/scsi/mpi3mr/mpi3mr_fw.c @@ -287,6 +287,8 @@ mpi3mr_get_drv_cmd(struct mpi3mr_ioc *mrioc, u16 host_tag, switch (host_tag) { case MPI3MR_HOSTTAG_INITCMDS: return &mrioc->init_cmds; + case MPI3MR_HOSTTAG_IOCTLCMDS: + return &mrioc->ioctl_cmds; case MPI3MR_HOSTTAG_BLK_TMS: return &mrioc->host_tm_cmds; case MPI3MR_HOSTTAG_INVALID: @@ -371,6 +373,11 @@ static void mpi3mr_process_admin_reply_desc(struct mpi3mr_ioc *mrioc, memcpy((u8 *)cmdptr->reply, (u8 *)def_reply, mrioc->facts.reply_sz); } + if (sense_buf && cmdptr->sensebuf) { + cmdptr->is_sense = true; + memcpy(cmdptr->sensebuf, sense_buf, + MPI3MR_SENSE_BUF_SZ); + } if (cmdptr->is_waiting) { complete(&cmdptr->done); cmdptr->is_waiting = 0; @@ -2454,6 +2461,10 @@ static int mpi3mr_alloc_reply_sense_bufs(struct mpi3mr_ioc *mrioc) if (!mrioc->init_cmds.reply) goto out_failed; + mrioc->ioctl_cmds.reply = kzalloc(mrioc->facts.reply_sz, GFP_KERNEL); + if (!mrioc->ioctl_cmds.reply) + goto out_failed; + for (i = 0; i < MPI3MR_NUM_DEVRMCMD; i++) { mrioc->dev_rmhs_cmds[i].reply = kzalloc(mrioc->facts.reply_sz, GFP_KERNEL); @@ -3505,6 +3516,7 @@ void mpi3mr_memset_buffers(struct mpi3mr_ioc *mrioc) memset(mrioc->admin_reply_base, 0, mrioc->admin_reply_q_sz); memset(mrioc->init_cmds.reply, 0, sizeof(*mrioc->init_cmds.reply)); + memset(mrioc->ioctl_cmds.reply, 0, sizeof(*mrioc->ioctl_cmds.reply)); memset(mrioc->host_tm_cmds.reply, 0, sizeof(*mrioc->host_tm_cmds.reply)); for (i = 0; i < MPI3MR_NUM_DEVRMCMD; i++) @@ -3601,6 +3613,9 @@ static void mpi3mr_free_mem(struct mpi3mr_ioc *mrioc) kfree(mrioc->init_cmds.reply); mrioc->init_cmds.reply = NULL; + kfree(mrioc->ioctl_cmds.reply); + mrioc->ioctl_cmds.reply = NULL; + kfree(mrioc->host_tm_cmds.reply); mrioc->host_tm_cmds.reply = NULL; @@ -3644,6 +3659,9 @@ static void mpi3mr_free_mem(struct mpi3mr_ioc *mrioc) mrioc->admin_req_base, mrioc->admin_req_dma); mrioc->admin_req_base = NULL; } + + kfree(mrioc->logdata_buf); + mrioc->logdata_buf = NULL; } /** @@ -3788,6 +3806,10 @@ static void mpi3mr_flush_drv_cmds(struct mpi3mr_ioc *mrioc) cmdptr = &mrioc->init_cmds; mpi3mr_drv_cmd_comp_reset(mrioc, cmdptr); + + cmdptr = &mrioc->ioctl_cmds; + mpi3mr_drv_cmd_comp_reset(mrioc, cmdptr); + cmdptr = &mrioc->host_tm_cmds; mpi3mr_drv_cmd_comp_reset(mrioc, cmdptr); @@ -3875,6 +3897,7 @@ int mpi3mr_soft_reset_handler(struct mpi3mr_ioc *mrioc, return -1; } mrioc->reset_in_progress = 1; + mrioc->block_ioctls = 1; if ((!snapdump) && (reset_reason != MPI3MR_RESET_FROM_FAULT_WATCH) && (reset_reason != MPI3MR_RESET_FROM_CIACTIV_FAULT)) { @@ -3945,6 +3968,7 @@ int mpi3mr_soft_reset_handler(struct mpi3mr_ioc *mrioc, &mrioc->watchdog_work, msecs_to_jiffies(MPI3MR_WATCHDOG_INTERVAL)); spin_unlock_irqrestore(&mrioc->watchdog_lock, flags); + mrioc->block_ioctls = 0; } else { mpi3mr_issue_reset(mrioc, MPI3_SYSIF_HOST_DIAG_RESET_ACTION_DIAG_FAULT, reset_reason); diff --git a/drivers/scsi/mpi3mr/mpi3mr_os.c b/drivers/scsi/mpi3mr/mpi3mr_os.c index a17d2172bddf..cd53c4920207 100644 --- a/drivers/scsi/mpi3mr/mpi3mr_os.c +++ b/drivers/scsi/mpi3mr/mpi3mr_os.c @@ -537,7 +537,7 @@ static struct mpi3mr_tgt_dev *__mpi3mr_get_tgtdev_by_handle( * * Return: Target device reference. */ -static struct mpi3mr_tgt_dev *mpi3mr_get_tgtdev_by_handle( +struct mpi3mr_tgt_dev *mpi3mr_get_tgtdev_by_handle( struct mpi3mr_ioc *mrioc, u16 handle) { struct mpi3mr_tgt_dev *tgtdev; @@ -585,7 +585,7 @@ static struct mpi3mr_tgt_dev *__mpi3mr_get_tgtdev_by_perst_id( * * Return: Target device reference. */ -static struct mpi3mr_tgt_dev *mpi3mr_get_tgtdev_by_perst_id( +struct mpi3mr_tgt_dev *mpi3mr_get_tgtdev_by_perst_id( struct mpi3mr_ioc *mrioc, u16 persist_id) { struct mpi3mr_tgt_dev *tgtdev; @@ -3074,6 +3074,7 @@ static int mpi3mr_scan_finished(struct Scsi_Host *shost, ioc_info(mrioc, "%s :port enable: SUCCESS\n", __func__); mpi3mr_start_watchdog(mrioc); mrioc->is_driver_loading = 0; + mrioc->block_ioctls = 0; return 1; } @@ -3717,6 +3718,7 @@ mpi3mr_probe(struct pci_dev *pdev, const struct pci_device_id *id) mutex_init(&mrioc->reset_mutex); mpi3mr_init_drv_cmd(&mrioc->init_cmds, MPI3MR_HOSTTAG_INITCMDS); + mpi3mr_init_drv_cmd(&mrioc->ioctl_cmds, MPI3MR_HOSTTAG_IOCTLCMDS); mpi3mr_init_drv_cmd(&mrioc->host_tm_cmds, MPI3MR_HOSTTAG_BLK_TMS); for (i = 0; i < MPI3MR_NUM_DEVRMCMD; i++) @@ -3730,6 +3732,7 @@ mpi3mr_probe(struct pci_dev *pdev, const struct pci_device_id *id) mrioc->logging_level = logging_level; mrioc->shost = shost; mrioc->pdev = pdev; + mrioc->block_ioctls = 1; /* init shost parameters */ shost->max_cmd_len = MPI3MR_MAX_CDB_LENGTH; @@ -4006,6 +4009,7 @@ static int __init mpi3mr_init(void) pr_info("Loading %s version %s\n", MPI3MR_DRIVER_NAME, MPI3MR_DRIVER_VERSION); + mpi3mr_app_init(); ret_val = pci_register_driver(&mpi3mr_pci_driver); return ret_val; @@ -4021,6 +4025,7 @@ static void __exit mpi3mr_exit(void) pr_info("Unloading %s version %s\n", MPI3MR_DRIVER_NAME, MPI3MR_DRIVER_VERSION); + mpi3mr_app_exit(); pci_unregister_driver(&mpi3mr_pci_driver); } From patchwork Tue Sep 21 18:45:57 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Kashyap Desai X-Patchwork-Id: 12508635 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-20.1 required=3.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_CR_TRAILER,INCLUDES_PATCH,MAILING_LIST_MULTI,MIME_HEADER_CTYPE_ONLY, SPF_HELO_NONE,SPF_PASS,T_TVD_MIME_NO_HEADERS,URIBL_BLOCKED,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 3D194C433FE for ; Tue, 21 Sep 2021 18:46:56 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 234E560E73 for ; Tue, 21 Sep 2021 18:46:56 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S233992AbhIUSsE (ORCPT ); Tue, 21 Sep 2021 14:48:04 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:40232 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231615AbhIUSrs (ORCPT ); Tue, 21 Sep 2021 14:47:48 -0400 Received: from mail-pl1-x636.google.com (mail-pl1-x636.google.com [IPv6:2607:f8b0:4864:20::636]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 9B945C061575 for ; Tue, 21 Sep 2021 11:46:19 -0700 (PDT) Received: by mail-pl1-x636.google.com with SMTP id v2so19401plp.8 for ; Tue, 21 Sep 2021 11:46:19 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=broadcom.com; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=IRwb8F1kCJPVehyeKNF1oxDYX0cEfGAXG2qxbJN1ryQ=; b=CaG1p+byNuhCwQCSl2CPLJ8I9BnzsOt0yZ6amW/AuG0rfuoGIFIHFcN/bR1oeZuoFU 4/GdWaYxGgirXBT6SBYrKfJEUyT4T7oF/YAfJxQ7t4cXF98WJPH4B4lEg8vvz//0BOb0 SeOGaqGrJdbA5TruGTzGVnQ7DhUDHE21yKH0Y= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=IRwb8F1kCJPVehyeKNF1oxDYX0cEfGAXG2qxbJN1ryQ=; b=gPxL1axMfztZVLZ09BVICUEPUT6NEjBgX/TKTa1/FZ29sCcxR+nwWgkb6fMhP1+aQb VPTQjQXHyD00EDhH17ChCglAc5LUy9882j0ZSOh41WJbwTsCXOTAWWrB9xBYHsBtpYJK qmoTe4QMPXNIDDmq5GNwx79d8fsa7Jx9hNxCt0/y/fuF+BHDaVHqjLLg0XpMQR84YFPT k9n8pXQ6cvyhkHLNn74TBRP11dpeHLwYjMf+hL2nuzmJNn/NNbl3kNrKRHmVnxqCgw89 pl8ItbvNxhePH2BbGNpH4PERnITdF1oCXb8AlU3M0WgArO0bvudUJ1YIVYSiADLRzmYY fKOg== X-Gm-Message-State: AOAM531kmFolnPSOtlPwgqXRLhi1mUQbguTC85L3PbvMhzCaFIIl+dW8 Bj0pwYYTBipOH7bASCi9rBtC/e9WH3sWWy1AINXgX6qB2FNfTJpKPg34APUEjMeVj7Kq4Qt8EMJ VFuoKQPDTr1WHQ2KMXX/25/1GerMCAU/akRIzWU088x/mwYzCyZSH2DJlmfHgkkXkEMw5+EhJGn xgQIgLGtIa X-Google-Smtp-Source: ABdhPJyoE5xGhGCdVrAdaucjA20s/VkOw2O/zrQqc6hYF1rA5tD2KSJ/T/Nx0w164MTxCX4WQaEJrg== X-Received: by 2002:a17:902:a38b:b0:138:d329:27ac with SMTP id x11-20020a170902a38b00b00138d32927acmr28553126pla.7.1632249978720; Tue, 21 Sep 2021 11:46:18 -0700 (PDT) Received: from drv-bst-rhel8.dhcp.broadcom.net ([192.19.234.250]) by smtp.gmail.com with ESMTPSA id f144sm18258897pfa.24.2021.09.21.11.46.16 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 21 Sep 2021 11:46:18 -0700 (PDT) From: Kashyap Desai To: linux-scsi@vger.kernel.org Cc: jejb@linux.ibm.com, martin.petersen@oracle.com, steve.hagan@broadcom.com, mpi3mr-linuxdrv.pdl@broadcom.com, Kashyap Desai , sathya.prakash@broadcom.com Subject: [PATCH 4/7] mpi3mr: misc changes and use __builtin_return_address for debug Date: Wed, 22 Sep 2021 00:15:57 +0530 Message-Id: <20210921184600.64427-5-kashyap.desai@broadcom.com> X-Mailer: git-send-email 2.18.1 In-Reply-To: <20210921184600.64427-1-kashyap.desai@broadcom.com> References: <20210921184600.64427-1-kashyap.desai@broadcom.com> Precedence: bulk List-ID: X-Mailing-List: linux-scsi@vger.kernel.org No Functional changes. Some minor variable name changes. Use __builtin_return_address in some of the functions which are called from multiple callers. Doing this we can avoid multiple debug prints. Signed-off-by: Kashyap Desai Cc: sathya.prakash@broadcom.com --- drivers/scsi/mpi3mr/mpi3mr.h | 4 ++-- drivers/scsi/mpi3mr/mpi3mr_fw.c | 29 +++++++++++++++++------------ 2 files changed, 19 insertions(+), 14 deletions(-) diff --git a/drivers/scsi/mpi3mr/mpi3mr.h b/drivers/scsi/mpi3mr/mpi3mr.h index 5ae73927590c..391708c72563 100644 --- a/drivers/scsi/mpi3mr/mpi3mr.h +++ b/drivers/scsi/mpi3mr/mpi3mr.h @@ -121,7 +121,7 @@ extern int prot_mask; /* Definitions for Event replies and sense buffer allocated per controller */ #define MPI3MR_NUM_EVT_REPLIES 64 -#define MPI3MR_SENSEBUF_SZ 256 +#define MPI3MR_SENSE_BUF_SZ 256 #define MPI3MR_SENSEBUF_FACTOR 3 #define MPI3MR_CHAINBUF_FACTOR 3 #define MPI3MR_CHAINBUFDIX_FACTOR 2 @@ -263,7 +263,7 @@ struct mpi3mr_ioc_facts { u16 max_vds; u16 max_hpds; u16 max_advhpds; - u16 max_raidpds; + u16 max_raid_pds; u16 min_devhandle; u16 max_devhandle; u16 max_op_req_q; diff --git a/drivers/scsi/mpi3mr/mpi3mr_fw.c b/drivers/scsi/mpi3mr/mpi3mr_fw.c index 337cbb3ffaaa..7da07fe71cfe 100644 --- a/drivers/scsi/mpi3mr/mpi3mr_fw.c +++ b/drivers/scsi/mpi3mr/mpi3mr_fw.c @@ -1220,7 +1220,9 @@ int mpi3mr_admin_request_post(struct mpi3mr_ioc *mrioc, void *admin_req, u8 *areq_entry; if (mrioc->unrecoverable) { - ioc_err(mrioc, "%s : Unrecoverable controller\n", __func__); + ioc_err(mrioc, "%ps %s error: Unrecoverable controller\n", + __builtin_return_address(0), + __func__); return -EFAULT; } @@ -1230,12 +1232,16 @@ int mpi3mr_admin_request_post(struct mpi3mr_ioc *mrioc, void *admin_req, max_entries = mrioc->num_admin_req; if ((areq_ci == (areq_pi + 1)) || ((!areq_ci) && (areq_pi == (max_entries - 1)))) { - ioc_err(mrioc, "AdminReqQ full condition detected\n"); + ioc_err(mrioc, "%ps %s error: AdminReqQ full\n", + __builtin_return_address(0), + __func__); retval = -EAGAIN; goto out; } if (!ignore_reset && mrioc->reset_in_progress) { - ioc_err(mrioc, "AdminReqQ submit reset in progress\n"); + ioc_err(mrioc, "%ps %s error: AdminReqQ reset in progress\n", + __builtin_return_address(0), + __func__); retval = -EAGAIN; goto out; } @@ -2384,7 +2390,7 @@ static void mpi3mr_process_factsdata(struct mpi3mr_ioc *mrioc, mrioc->facts.max_vds = le16_to_cpu(facts_data->max_vds); mrioc->facts.max_hpds = le16_to_cpu(facts_data->max_host_pds); mrioc->facts.max_advhpds = le16_to_cpu(facts_data->max_adv_host_pds); - mrioc->facts.max_raidpds = le16_to_cpu(facts_data->max_raid_pds); + mrioc->facts.max_raid_pds = le16_to_cpu(facts_data->max_raid_pds); mrioc->facts.max_nvme = le16_to_cpu(facts_data->max_nvme); mrioc->facts.max_pcie_switches = le16_to_cpu(facts_data->max_pcie_switches); @@ -2421,10 +2427,9 @@ static void mpi3mr_process_factsdata(struct mpi3mr_ioc *mrioc, mrioc->facts.ioc_num, mrioc->facts.max_op_req_q, mrioc->facts.max_op_reply_q, mrioc->facts.max_devhandle); ioc_info(mrioc, - "maxreqs(%d), mindh(%d) maxPDs(%d) maxvectors(%d) maxperids(%d)\n", + "maxreqs(%d), mindh(%d) maxvectors(%d) maxperids(%d)\n", mrioc->facts.max_reqs, mrioc->facts.min_devhandle, - mrioc->facts.max_pds, mrioc->facts.max_msix_vectors, - mrioc->facts.max_perids); + mrioc->facts.max_msix_vectors, mrioc->facts.max_perids); ioc_info(mrioc, "SGEModMask 0x%x SGEModVal 0x%x SGEModShift 0x%x ", mrioc->facts.sge_mod_mask, mrioc->facts.sge_mod_value, mrioc->facts.sge_mod_shift); @@ -2527,7 +2532,7 @@ static int mpi3mr_alloc_reply_sense_bufs(struct mpi3mr_ioc *mrioc) goto out_failed; /* sense buffer pool, 4 byte align */ - sz = mrioc->num_sense_bufs * MPI3MR_SENSEBUF_SZ; + sz = mrioc->num_sense_bufs * MPI3MR_SENSE_BUF_SZ; mrioc->sense_buf_pool = dma_pool_create("sense_buf pool", &mrioc->pdev->dev, sz, 4, 0); if (!mrioc->sense_buf_pool) { @@ -2563,10 +2568,10 @@ static int mpi3mr_alloc_reply_sense_bufs(struct mpi3mr_ioc *mrioc) "reply_free_q pool(0x%p): depth(%d), frame_size(%d), pool_size(%d kB), reply_dma(0x%llx)\n", mrioc->reply_free_q, mrioc->reply_free_qsz, 8, (sz / 1024), (unsigned long long)mrioc->reply_free_q_dma); - sz = mrioc->num_sense_bufs * MPI3MR_SENSEBUF_SZ; + sz = mrioc->num_sense_bufs * MPI3MR_SENSE_BUF_SZ; ioc_info(mrioc, "sense_buf pool(0x%p): depth(%d), frame_size(%d), pool_size(%d kB), sense_dma(0x%llx)\n", - mrioc->sense_buf, mrioc->num_sense_bufs, MPI3MR_SENSEBUF_SZ, + mrioc->sense_buf, mrioc->num_sense_bufs, MPI3MR_SENSE_BUF_SZ, (sz / 1024), (unsigned long long)mrioc->sense_buf_dma); sz = mrioc->sense_buf_q_sz * 8; ioc_info(mrioc, @@ -2582,7 +2587,7 @@ static int mpi3mr_alloc_reply_sense_bufs(struct mpi3mr_ioc *mrioc) /* initialize Sense Buffer Queue */ for (i = 0, phy_addr = mrioc->sense_buf_dma; - i < mrioc->num_sense_bufs; i++, phy_addr += MPI3MR_SENSEBUF_SZ) + i < mrioc->num_sense_bufs; i++, phy_addr += MPI3MR_SENSE_BUF_SZ) mrioc->sense_buf_q[i] = cpu_to_le64(phy_addr); mrioc->sense_buf_q[i] = cpu_to_le64(0); return retval; @@ -2649,7 +2654,7 @@ static int mpi3mr_issue_iocinit(struct mpi3mr_ioc *mrioc) iocinit_req.reply_free_queue_depth = cpu_to_le16(mrioc->reply_free_qsz); iocinit_req.reply_free_queue_address = cpu_to_le64(mrioc->reply_free_q_dma); - iocinit_req.sense_buffer_length = cpu_to_le16(MPI3MR_SENSEBUF_SZ); + iocinit_req.sense_buffer_length = cpu_to_le16(MPI3MR_SENSE_BUF_SZ); iocinit_req.sense_buffer_free_queue_depth = cpu_to_le16(mrioc->sense_buf_q_sz); iocinit_req.sense_buffer_free_queue_address = From patchwork Tue Sep 21 18:45:58 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Kashyap Desai X-Patchwork-Id: 12508631 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-20.1 required=3.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_CR_TRAILER,INCLUDES_PATCH,MAILING_LIST_MULTI,MIME_HEADER_CTYPE_ONLY, SPF_HELO_NONE,SPF_PASS,T_TVD_MIME_NO_HEADERS,URIBL_BLOCKED,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id A6083C4332F for ; Tue, 21 Sep 2021 18:46:44 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 870B360E73 for ; Tue, 21 Sep 2021 18:46:44 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S233957AbhIUSsD (ORCPT ); Tue, 21 Sep 2021 14:48:03 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:40246 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230494AbhIUSrv (ORCPT ); Tue, 21 Sep 2021 14:47:51 -0400 Received: from mail-pf1-x429.google.com (mail-pf1-x429.google.com [IPv6:2607:f8b0:4864:20::429]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id AF314C061574 for ; Tue, 21 Sep 2021 11:46:22 -0700 (PDT) Received: by mail-pf1-x429.google.com with SMTP id y8so385139pfa.7 for ; Tue, 21 Sep 2021 11:46:22 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=broadcom.com; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=UFiHITzdJzMalW9fucFNnq1XWvVUw19IzNB1DVS7tqQ=; b=WD3l/v4zP560UzFRMCCJ02psfX2WrGBhEwUxhYc2oImXw7UmDZ8UuBBg1huSzaQEE1 prkfjUnfQb/u70uZUqFJdmQpSoJsUanFMp6RIdkz6pb3IIgxRwdSvBcqc3Tf4g13hs/w ZEUW4uUIrxPFs6UUr6q44S/uh8mbrTJggZRHA= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=UFiHITzdJzMalW9fucFNnq1XWvVUw19IzNB1DVS7tqQ=; b=mj9WiIwL3gTiJlMdDMwYoxA9DGbLMXn72wO5diFrrSKy4Gg4Tbhxaf7WvT/5tzRO3Y XAvHlw9PhAOX9JpGhAT4djsRcLECtTiHdMNm8strFcXDQXuJOBAy3ECm+gbQJlH0tUvX EttPi1I0moKs83BPexbCiRccyDWBB8DsAbjSi84I6QroKyO6m1hL6d7YHOSNlCiMPcOs WnOdUC3YhMvndxWCD+Pk2w71yz/4AiibRebuVEVxQIX+DcpJspJ6UdGnGAwRrYxSdh6O /EhGA6hXkvnwp7KmgYkyjF6OvPQOV2tlHvkgD7JYO9znsmvXVp1DifSko8IkAXnv6k8e 42Ug== X-Gm-Message-State: AOAM531xQmnuLEc1rgiQoz0643L4MlQdKJeWaEsVAlqavasM1KJdUAL5 U2fyrVBZhY3YHh7uO42kFBiWzQA2ruNPKu2wfTPQzEP10CtbGOQmlnwUMDCG9D00D3pvut3/dBs DxvTd/SAcnCSJ1VqQ4C6yCPy4fTCSeklkTMhea38Vvk7aDtHV6V8WGtyY8I1c1EfZVsHZTNNWl/ W6iw2Ewh6Q X-Google-Smtp-Source: ABdhPJwhMYQBT9JCjv3rBSVSVEkJD9RQQ7DV1DrjSnFcyk+CzaUTRsLXQnLNJmeziq++BzOOtvSopA== X-Received: by 2002:a63:d0d:: with SMTP id c13mr29248342pgl.294.1632249981351; Tue, 21 Sep 2021 11:46:21 -0700 (PDT) Received: from drv-bst-rhel8.dhcp.broadcom.net ([192.19.234.250]) by smtp.gmail.com with ESMTPSA id f144sm18258897pfa.24.2021.09.21.11.46.19 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 21 Sep 2021 11:46:20 -0700 (PDT) From: Kashyap Desai To: linux-scsi@vger.kernel.org Cc: jejb@linux.ibm.com, martin.petersen@oracle.com, steve.hagan@broadcom.com, mpi3mr-linuxdrv.pdl@broadcom.com, Kashyap Desai , sathya.prakash@broadcom.com Subject: [PATCH 5/7] mpi3mr: PEL support added Date: Wed, 22 Sep 2021 00:15:58 +0530 Message-Id: <20210921184600.64427-6-kashyap.desai@broadcom.com> X-Mailer: git-send-email 2.18.1 In-Reply-To: <20210921184600.64427-1-kashyap.desai@broadcom.com> References: <20210921184600.64427-1-kashyap.desai@broadcom.com> Precedence: bulk List-ID: X-Mailing-List: linux-scsi@vger.kernel.org This patch includes driver support for the management applications to enable the persistent event log notification with the controller and the driver will notify the application once a PEL entry is returned by the firmware through an AEN and the management applications will issue direct MPI Passthru calls to get the individual entries. Signed-off-by: Kashyap Desai Cc: sathya.prakash@broadcom.com --- drivers/scsi/mpi3mr/mpi3mr.h | 33 ++++ drivers/scsi/mpi3mr/mpi3mr_app.c | 205 ++++++++++++++++++++++ drivers/scsi/mpi3mr/mpi3mr_fw.c | 283 +++++++++++++++++++++++++++++++ drivers/scsi/mpi3mr/mpi3mr_os.c | 23 +++ 4 files changed, 544 insertions(+) diff --git a/drivers/scsi/mpi3mr/mpi3mr.h b/drivers/scsi/mpi3mr/mpi3mr.h index 391708c72563..6108fe562bed 100644 --- a/drivers/scsi/mpi3mr/mpi3mr.h +++ b/drivers/scsi/mpi3mr/mpi3mr.h @@ -88,6 +88,8 @@ extern int prot_mask; #define MPI3MR_HOSTTAG_INVALID 0xFFFF #define MPI3MR_HOSTTAG_INITCMDS 1 #define MPI3MR_HOSTTAG_IOCTLCMDS 2 +#define MPI3MR_HOSTTAG_PEL_ABORT 3 +#define MPI3MR_HOSTTAG_PEL_WAIT 4 #define MPI3MR_HOSTTAG_BLK_TMS 5 #define MPI3MR_NUM_DEVRMCMD 1 @@ -148,6 +150,7 @@ extern int prot_mask; #define MPI3MR_DEFAULT_MDTS (128 * 1024) /* Command retry count definitions */ #define MPI3MR_DEV_RMHS_RETRY_COUNT 3 +#define MPI3MR_PEL_RETRY_COUNT 3 /* Default target device queue depth */ #define MPI3MR_DEFAULT_SDEV_QD 32 @@ -702,6 +705,16 @@ struct scmd_priv { * @current_event: Firmware event currently in process * @driver_info: Driver, Kernel, OS information to firmware * @change_count: Topology change count + * @pel_enabled: Persistent Event Log(PEL) enabled or not + * @pel_abort_requested: PEL abort is requested or not + * @pel_class: PEL Class identifier + * @pel_locale: PEL Locale identifier + * @pel_cmds: Command tracker for PEL wait command + * @pel_abort_cmd: Command tracker for PEL abort command + * @pel_newest_seqnum: Newest PEL sequenece number + * @pel_seqnum_virt: PEL sequence number virtual address + * @pel_seqnum_dma: PEL sequence number DMA address + * @pel_seqnum_sz: PEL sequenece number size * @op_reply_q_offset: Operational reply queue offset with MSIx * @logdata_buf: Circular buffer to store log data entries * @logdata_buf_idx: Index of entry in buffer to store @@ -834,6 +847,17 @@ struct mpi3mr_ioc { struct mpi3mr_fwevt *current_event; struct mpi3_driver_info_layout driver_info; u16 change_count; + bool pel_enabled; + bool pel_abort_requested; + u8 pel_class; + u16 pel_locale; + struct mpi3mr_drv_cmd pel_cmds; + struct mpi3mr_drv_cmd pel_abort_cmd; + u32 pel_newest_seqnum; + void *pel_seqnum_virt; + dma_addr_t pel_seqnum_dma; + u32 pel_seqnum_sz; + u16 op_reply_q_offset; u8 *logdata_buf; @@ -851,6 +875,7 @@ struct mpi3mr_ioc { * @send_ack: Event acknowledgment required or not * @process_evt: Bottomhalf processing required or not * @evt_ctx: Event context to send in Ack + * @evt_data_size: size of the event data in bytes * @ref_count: kref count * @event_data: Actual MPI3 event data */ @@ -862,6 +887,7 @@ struct mpi3mr_fwevt { bool send_ack; bool process_evt; u32 evt_ctx; + u16 evt_data_size; struct kref ref_count; char event_data[0] __aligned(4); }; @@ -898,6 +924,8 @@ void *mpi3mr_get_reply_virt_addr(struct mpi3mr_ioc *mrioc, dma_addr_t phys_addr); void mpi3mr_repost_sense_buf(struct mpi3mr_ioc *mrioc, u64 sense_buf_dma); +void mpi3mr_pel_get_seqnum_complete(struct mpi3mr_ioc *mrioc, + struct mpi3mr_drv_cmd *drv_cmd); void mpi3mr_memset_buffers(struct mpi3mr_ioc *mrioc); void mpi3mr_os_handle_events(struct mpi3mr_ioc *mrioc, @@ -925,6 +953,8 @@ void mpi3mr_ioc_enable_intr(struct mpi3mr_ioc *mrioc); enum mpi3mr_iocstate mpi3mr_get_iocstate(struct mpi3mr_ioc *mrioc); int mpi3mr_send_event_ack(struct mpi3mr_ioc *mrioc, u8 event, u32 event_ctx); +int mpi3mr_pel_get_seqnum_post(struct mpi3mr_ioc *mrioc, + struct mpi3mr_drv_cmd *drv_cmd); void mpi3mr_wait_for_host_io(struct mpi3mr_ioc *mrioc, u32 timeout); void mpi3mr_cleanup_fwevt_list(struct mpi3mr_ioc *mrioc); @@ -935,5 +965,8 @@ void mpi3mr_flush_delayed_rmhs_list(struct mpi3mr_ioc *mrioc); void mpi3mr_app_init(void); void mpi3mr_app_exit(void); +void mpi3mr_app_send_aen(struct mpi3mr_ioc *mrioc); +void mpi3mr_app_save_logdata(struct mpi3mr_ioc *mrioc, char *event_data, + u16 event_data_size); #endif /*MPI3MR_H_INCLUDED*/ diff --git a/drivers/scsi/mpi3mr/mpi3mr_app.c b/drivers/scsi/mpi3mr/mpi3mr_app.c index 021615889dcd..f8e7d2713fe4 100644 --- a/drivers/scsi/mpi3mr/mpi3mr_app.c +++ b/drivers/scsi/mpi3mr/mpi3mr_app.c @@ -192,6 +192,157 @@ static long mpi3mr_get_logdata(struct mpi3mr_ioc *mrioc, return 0; } +/** + * mpi3mr_app_pel_abort - sends PEL abort request + * @mrioc: Adapter instance reference + * + * This function sends PEL abort request to the firmware through + * admin request queue. + * + * Return: 0 on success, Non-zero on failure + */ +static int mpi3mr_app_pel_abort(struct mpi3mr_ioc *mrioc) +{ + struct mpi3_pel_req_action_abort pel_abort_req; + struct mpi3_pel_reply *pel_reply; + int retval = 0; + u16 pe_log_status; + + if (mrioc->reset_in_progress || + mrioc->block_ioctls) { + dbgprint(mrioc, "%s: reset %d blocked ioctl %d\n", + __func__, mrioc->reset_in_progress, + mrioc->block_ioctls); + return -1; + } + + memset(&pel_abort_req, 0, sizeof(pel_abort_req)); + mutex_lock(&mrioc->pel_abort_cmd.mutex); + if (mrioc->pel_abort_cmd.state & MPI3MR_CMD_PENDING) { + dbgprint(mrioc, "%s: command is in use\n", __func__); + mutex_unlock(&mrioc->pel_abort_cmd.mutex); + return -1; + } + mrioc->pel_abort_cmd.state = MPI3MR_CMD_PENDING; + mrioc->pel_abort_cmd.is_waiting = 1; + mrioc->pel_abort_cmd.callback = NULL; + pel_abort_req.host_tag = cpu_to_le16(MPI3MR_HOSTTAG_PEL_ABORT); + pel_abort_req.function = MPI3_FUNCTION_PERSISTENT_EVENT_LOG; + pel_abort_req.action = MPI3_PEL_ACTION_ABORT; + pel_abort_req.abort_host_tag = cpu_to_le16(MPI3MR_HOSTTAG_PEL_WAIT); + + mrioc->pel_abort_requested = true; + init_completion(&mrioc->pel_abort_cmd.done); + retval = mpi3mr_admin_request_post(mrioc, &pel_abort_req, + sizeof(pel_abort_req), 0); + if (retval) { + mrioc->pel_abort_requested = false; + goto out_unlock; + } + + wait_for_completion_timeout(&mrioc->pel_abort_cmd.done, + (MPI3MR_INTADMCMD_TIMEOUT * HZ)); + if (!(mrioc->pel_abort_cmd.state & MPI3MR_CMD_COMPLETE)) { + mrioc->pel_abort_cmd.is_waiting = 0; + dbgprint(mrioc, "%s: command timedout\n", __func__); + if (!(mrioc->pel_abort_cmd.state & MPI3MR_CMD_RESET)) + mpi3mr_soft_reset_handler(mrioc, + MPI3MR_RESET_FROM_PELABORT_TIMEOUT, 1); + retval = -1; + goto out_unlock; + } + if ((mrioc->pel_abort_cmd.ioc_status & MPI3_IOCSTATUS_STATUS_MASK) + != MPI3_IOCSTATUS_SUCCESS) { + dbgprint(mrioc, + "%s: command failed, ioc_status(0x%04x) log_info(0x%08x)\n", + __func__, (mrioc->pel_abort_cmd.ioc_status & + MPI3_IOCSTATUS_STATUS_MASK), + mrioc->pel_abort_cmd.ioc_loginfo); + retval = -1; + goto out_unlock; + } + if (mrioc->pel_abort_cmd.state & MPI3MR_CMD_REPLY_VALID) { + pel_reply = (struct mpi3_pel_reply *)mrioc->pel_abort_cmd.reply; + pe_log_status = le16_to_cpu(pel_reply->pe_log_status); + if (pe_log_status != MPI3_PEL_STATUS_SUCCESS) { + dbgprint(mrioc, + "%s: command failed, pel_status(0x%04x)\n", + __func__, pe_log_status); + retval = -1; + } + } + +out_unlock: + mrioc->pel_abort_cmd.state = MPI3MR_CMD_NOTUSED; + mutex_unlock(&mrioc->pel_abort_cmd.mutex); + return retval; +} + +/** + * mpi3mr_app_pel_enable - Handler for PEL enable driver IOCTL + * @mrioc: Adapter instance reference + * @data_out_buf: User buffer containing PEL enable data + * @data_out_sz: length of the user buffer. + * + * This function is the handler for PEL enable driver IOCTL. + * Validates the application given class and locale and if + * requires aborts the existing PEL wait request and/or issues + * new PEL wait request to the firmware and returns. + * + * Return: 0 on success and proper error codes on failure. + */ +static long mpi3mr_app_pel_enable(struct mpi3mr_ioc *mrioc, + void __user *data_out_buf, uint32_t data_out_sz) +{ + long rval = 0; + struct mpi3mr_ioctl_out_pel_enable pel_enable; + u8 tmp_class; + u16 tmp_locale; + + if (copy_from_user(&pel_enable, data_out_buf, sizeof(pel_enable))) + return -EFAULT; + + if (pel_enable.pel_class > MPI3_PEL_CLASS_FAULT) { + dbgprint(mrioc, "%s: out of range class %d sent\n", + __func__, pel_enable.pel_class); + return -EINVAL; + } + + if (mrioc->pel_enabled) { + if ((mrioc->pel_class <= pel_enable.pel_class) && + !((mrioc->pel_locale & pel_enable.pel_locale) ^ + pel_enable.pel_locale)) + return 0; + + pel_enable.pel_locale |= mrioc->pel_locale; + if (mrioc->pel_class < pel_enable.pel_class) + pel_enable.pel_class = mrioc->pel_class; + + rval = mpi3mr_app_pel_abort(mrioc); + + if (rval) + return rval; + + } + + tmp_class = mrioc->pel_class; + tmp_locale = mrioc->pel_locale; + mrioc->pel_class = pel_enable.pel_class; + mrioc->pel_locale = pel_enable.pel_locale; + mrioc->pel_enabled = true; + rval = mpi3mr_pel_get_seqnum_post(mrioc, NULL); + if (rval) { + mrioc->pel_class = tmp_class; + mrioc->pel_locale = tmp_locale; + mrioc->pel_enabled = false; + dbgprint(mrioc, + "%s: pel get sequence number failed, status(%ld)\n", + __func__, rval); + } + + return rval; +} + /** * mpi3mr_get_change_count - Get topology change count * @mrioc: Adapter instance reference @@ -350,6 +501,10 @@ mpi3mr_ioctl_process_drv_cmds(struct file *file, void __user *arg) rval = mpi3mr_get_logdata(mrioc, karg.data_in_buf, karg.data_in_size); break; + case MPI3MR_DRVIOCTL_OPCODE_PELENABLE: + rval = mpi3mr_app_pel_enable(mrioc, karg.data_out_buf, + karg.data_out_size); + break; case MPI3MR_DRVIOCTL_OPCODE_GETCHGCNT: rval = mpi3mr_get_change_count(mrioc, karg.data_in_buf, karg.data_in_size); @@ -799,6 +954,56 @@ static long mpi3mr_ioctl(struct file *file, unsigned int cmd, return rval; } +/** + * mpi3mr_app_send_aen - Notify applications about an AEN + * @mrioc: Adapter instance reference + * + * Sends async signal SIGIO to indicate there is an async event + * from the firmware to the event monitoring applications. + * + * Return:Nothing + */ +void mpi3mr_app_send_aen(struct mpi3mr_ioc *mrioc) +{ + dbgprint(mrioc, "%s: invoked\n", __func__); + if (mpi3mr_app_async_queue) { + dbgprint(mrioc, "%s: sending signal\n", __func__); + kill_fasync(&mpi3mr_app_async_queue, SIGIO, POLL_IN); + } +} + +/** + * mpi3mr_app_save_logdata - Save Log Data events + * @mrioc: Adapter instance reference + * @event_data: event data associated with log data event + * @event_data_size: event data size to copy + * + * If log data event caching is enabled by the applicatiobns, + * then this function saves the log data in the circular queue + * and Sends async signal SIGIO to indicate there is an async + * event from the firmware to the event monitoring applications. + * + * Return:Nothing + */ +void mpi3mr_app_save_logdata(struct mpi3mr_ioc *mrioc, char *event_data, + u16 event_data_size) +{ + u32 index = mrioc->logdata_buf_idx, sz; + struct mpi3mr_logdata_entry *entry; + + if (!(mrioc->logdata_buf)) + return; + + entry = (struct mpi3mr_logdata_entry *) + (mrioc->logdata_buf + (index * mrioc->logdata_entry_sz)); + entry->valid_entry = 1; + sz = min(mrioc->logdata_entry_sz, event_data_size); + memcpy(entry->data, event_data, sz); + mrioc->logdata_buf_idx = + ((++index) % MPI3MR_IOCTL_LOGDATA_MAX_ENTRIES); + mpi3mr_app_send_aen(mrioc); +} + /** * mpi3mr_app_fasync - fasync callback * @fd: File descriptor diff --git a/drivers/scsi/mpi3mr/mpi3mr_fw.c b/drivers/scsi/mpi3mr/mpi3mr_fw.c index 7da07fe71cfe..b57b89df0519 100644 --- a/drivers/scsi/mpi3mr/mpi3mr_fw.c +++ b/drivers/scsi/mpi3mr/mpi3mr_fw.c @@ -25,6 +25,9 @@ static inline void mpi3mr_writeq(__u64 b, volatile void __iomem *addr) } #endif +static void mpi3mr_pel_wait_complete(struct mpi3mr_ioc *mrioc, + struct mpi3mr_drv_cmd *drv_cmd); + static inline bool mpi3mr_check_req_qfull(struct op_req_qinfo *op_req_q) { @@ -291,6 +294,10 @@ mpi3mr_get_drv_cmd(struct mpi3mr_ioc *mrioc, u16 host_tag, return &mrioc->ioctl_cmds; case MPI3MR_HOSTTAG_BLK_TMS: return &mrioc->host_tm_cmds; + case MPI3MR_HOSTTAG_PEL_ABORT: + return &mrioc->pel_abort_cmd; + case MPI3MR_HOSTTAG_PEL_WAIT: + return &mrioc->pel_cmds; case MPI3MR_HOSTTAG_INVALID: if (def_reply && def_reply->function == MPI3_FUNCTION_EVENT_NOTIFICATION) @@ -2481,6 +2488,14 @@ static int mpi3mr_alloc_reply_sense_bufs(struct mpi3mr_ioc *mrioc) if (!mrioc->host_tm_cmds.reply) goto out_failed; + mrioc->pel_cmds.reply = kzalloc(mrioc->facts.reply_sz, GFP_KERNEL); + if (!mrioc->pel_cmds.reply) + goto out_failed; + + mrioc->pel_abort_cmd.reply = kzalloc(mrioc->facts.reply_sz, GFP_KERNEL); + if (!mrioc->pel_abort_cmd.reply) + goto out_failed; + mrioc->dev_handle_bitmap_sz = mrioc->facts.max_devhandle / 8; if (mrioc->facts.max_devhandle % 8) mrioc->dev_handle_bitmap_sz++; @@ -3414,6 +3429,16 @@ int mpi3mr_init_ioc(struct mpi3mr_ioc *mrioc, u8 init_type) goto out_failed; } + if (!mrioc->pel_seqnum_virt) { + mrioc->pel_seqnum_sz = sizeof(struct mpi3_pel_seq); + mrioc->pel_seqnum_virt = dma_alloc_coherent(&mrioc->pdev->dev, + mrioc->pel_seqnum_sz, &mrioc->pel_seqnum_dma, + GFP_KERNEL); + if (!mrioc->pel_seqnum_virt) + goto out_failed; + } + + for (i = 0; i < MPI3_EVENT_NOTIFY_EVENTMASK_WORDS; i++) mrioc->event_masks[i] = -1; @@ -3524,6 +3549,10 @@ void mpi3mr_memset_buffers(struct mpi3mr_ioc *mrioc) memset(mrioc->ioctl_cmds.reply, 0, sizeof(*mrioc->ioctl_cmds.reply)); memset(mrioc->host_tm_cmds.reply, 0, sizeof(*mrioc->host_tm_cmds.reply)); + memset(mrioc->pel_cmds.reply, 0, + sizeof(*mrioc->pel_cmds.reply)); + memset(mrioc->pel_abort_cmd.reply, 0, + sizeof(*mrioc->pel_abort_cmd.reply)); for (i = 0; i < MPI3MR_NUM_DEVRMCMD; i++) memset(mrioc->dev_rmhs_cmds[i].reply, 0, sizeof(*mrioc->dev_rmhs_cmds[i].reply)); @@ -3624,6 +3653,12 @@ static void mpi3mr_free_mem(struct mpi3mr_ioc *mrioc) kfree(mrioc->host_tm_cmds.reply); mrioc->host_tm_cmds.reply = NULL; + kfree(mrioc->pel_cmds.reply); + mrioc->pel_cmds.reply = NULL; + + kfree(mrioc->pel_abort_cmd.reply); + mrioc->pel_abort_cmd.reply = NULL; + kfree(mrioc->removepend_bitmap); mrioc->removepend_bitmap = NULL; @@ -3665,6 +3700,12 @@ static void mpi3mr_free_mem(struct mpi3mr_ioc *mrioc) mrioc->admin_req_base = NULL; } + if (mrioc->pel_seqnum_virt) { + dma_free_coherent(&mrioc->pdev->dev, mrioc->pel_seqnum_sz, + mrioc->pel_seqnum_virt, mrioc->pel_seqnum_dma); + mrioc->pel_seqnum_virt = NULL; + } + kfree(mrioc->logdata_buf); mrioc->logdata_buf = NULL; } @@ -3822,6 +3863,13 @@ static void mpi3mr_flush_drv_cmds(struct mpi3mr_ioc *mrioc) cmdptr = &mrioc->dev_rmhs_cmds[i]; mpi3mr_drv_cmd_comp_reset(mrioc, cmdptr); } + + cmdptr = &mrioc->pel_cmds; + mpi3mr_drv_cmd_comp_reset(mrioc, cmdptr); + + cmdptr = &mrioc->pel_abort_cmd; + mpi3mr_drv_cmd_comp_reset(mrioc, cmdptr); + } /** @@ -3859,6 +3907,236 @@ int mpi3mr_diagfault_reset_handler(struct mpi3mr_ioc *mrioc, return retval; } +/** + * mpi3mr_pel_wait_post - Issue PEL Wait + * @mrioc: Adapter instance reference + * @drv_cmd: Internal command tracker + * + * Issue PEL Wait MPI request through admin queue and return. + * + * Return: Nothing. + */ +static void mpi3mr_pel_wait_post(struct mpi3mr_ioc *mrioc, + struct mpi3mr_drv_cmd *drv_cmd) +{ + struct mpi3_pel_req_action_wait pel_wait; + + mrioc->pel_abort_requested = false; + + memset(&pel_wait, 0, sizeof(pel_wait)); + drv_cmd->state = MPI3MR_CMD_PENDING; + drv_cmd->is_waiting = 0; + drv_cmd->callback = mpi3mr_pel_wait_complete; + drv_cmd->ioc_status = 0; + drv_cmd->ioc_loginfo = 0; + pel_wait.host_tag = cpu_to_le16(MPI3MR_HOSTTAG_PEL_WAIT); + pel_wait.function = MPI3_FUNCTION_PERSISTENT_EVENT_LOG; + pel_wait.action = MPI3_PEL_ACTION_WAIT; + pel_wait.starting_sequence_number = cpu_to_le32(mrioc->pel_newest_seqnum); + pel_wait.locale = cpu_to_le16(mrioc->pel_locale); + pel_wait.class = cpu_to_le16(mrioc->pel_class); + pel_wait.wait_time = MPI3_PEL_WAITTIME_INFINITE_WAIT; + ioc_info(mrioc, "Issuing PELWait: seqnum %d class %d locale 0x%08x\n", + mrioc->pel_newest_seqnum, mrioc->pel_class, mrioc->pel_locale); + + if (mpi3mr_admin_request_post(mrioc, &pel_wait, sizeof(pel_wait), 0)) + ioc_err(mrioc, "Issuing PELWait: Admin post failed\n"); + else { + drv_cmd->state = MPI3MR_CMD_NOTUSED; + drv_cmd->callback = NULL; + drv_cmd->retry_count = 0; + mrioc->pel_enabled = false; + } + + return; +} + +/** + * mpi3mr_pel_get_seqnum_post - Issue PEL Get Sequence number + * @mrioc: Adapter instance reference + * @drv_cmd: Internal command tracker + * + * Issue PEL get sequence number MPI request through admin queue + * and return. + * + * Return: 0 on success, non-zero on failure. + */ +int mpi3mr_pel_get_seqnum_post(struct mpi3mr_ioc *mrioc, + struct mpi3mr_drv_cmd *drv_cmd) +{ + struct mpi3_pel_req_action_get_sequence_numbers pel_getseq_req; + u8 sgl_flags = MPI3MR_SGEFLAGS_SYSTEM_SIMPLE_END_OF_LIST; + int retval = 0; + + memset(&pel_getseq_req, 0, sizeof(pel_getseq_req)); + mrioc->pel_cmds.state = MPI3MR_CMD_PENDING; + mrioc->pel_cmds.is_waiting = 0; + mrioc->pel_cmds.ioc_status = 0; + mrioc->pel_cmds.ioc_loginfo = 0; + mrioc->pel_cmds.callback = mpi3mr_pel_get_seqnum_complete; + pel_getseq_req.host_tag = cpu_to_le16(MPI3MR_HOSTTAG_PEL_WAIT); + pel_getseq_req.function = MPI3_FUNCTION_PERSISTENT_EVENT_LOG; + pel_getseq_req.action = MPI3_PEL_ACTION_GET_SEQNUM; + mpi3mr_add_sg_single(&pel_getseq_req.sgl, sgl_flags, + mrioc->pel_seqnum_sz, mrioc->pel_seqnum_dma); + + retval = mpi3mr_admin_request_post(mrioc, &pel_getseq_req, + sizeof(pel_getseq_req), 0); + if (retval) { + if (drv_cmd) { + drv_cmd->state = MPI3MR_CMD_NOTUSED; + drv_cmd->callback = NULL; + drv_cmd->retry_count = 0; + } + mrioc->pel_enabled = false; + } + + return retval; +} + +/** + * mpi3mr_pel_wait_complete - PELWait Completion callback + * @mrioc: Adapter instance reference + * @drv_cmd: Internal command tracker + * + * This is a callback handler for the PELWait request and + * firmware completes a PELWait request when it is aborted or a + * new PEL entry is available. This sends AEN to the application + * and if the PELwait completion is not due to PELAbort then + * this will send a request for new PEL Sequence number + * + * Return: Nothing. + */ +static void mpi3mr_pel_wait_complete(struct mpi3mr_ioc *mrioc, + struct mpi3mr_drv_cmd *drv_cmd) +{ + struct mpi3_pel_reply *pel_reply = NULL; + u16 ioc_status, pe_log_status; + bool do_retry = false; + + if (drv_cmd->state & MPI3MR_CMD_RESET) + goto cleanup_drv_cmd; + + ioc_status = drv_cmd->ioc_status & MPI3_IOCSTATUS_STATUS_MASK; + if (ioc_status != MPI3_IOCSTATUS_SUCCESS) { + ioc_err(mrioc, "%s: Failed ioc_status(0x%04x) Loginfo(0x%08x)\n", + __func__, ioc_status, drv_cmd->ioc_loginfo); + do_retry = true; + } + + if (drv_cmd->state & MPI3MR_CMD_REPLY_VALID) + pel_reply = (struct mpi3_pel_reply *)drv_cmd->reply; + + if (!pel_reply) { + ioc_err(mrioc, "%s: Failed No Reply\n", __func__); + goto out_failed; + } + + pe_log_status = le16_to_cpu(pel_reply->pe_log_status); + if ((pe_log_status != MPI3_PEL_STATUS_SUCCESS) && + (pe_log_status != MPI3_PEL_STATUS_ABORTED)) { + ioc_err(mrioc, "%s: Failed pe_log_status(0x%04x)\n", + __func__, pe_log_status); + do_retry = true; + } + + if (do_retry) { + if (drv_cmd->retry_count < MPI3MR_PEL_RETRY_COUNT) { + drv_cmd->retry_count++; + ioc_info(mrioc, "%s: retry=%d\n", + __func__, drv_cmd->retry_count); + mpi3mr_pel_wait_post(mrioc, drv_cmd); + return; + } + ioc_err(mrioc, "%s: failed after all retries\n", __func__); + goto out_failed; + } + mpi3mr_app_send_aen(mrioc); + if (!mrioc->pel_abort_requested) { + mrioc->pel_cmds.retry_count = 0; + mpi3mr_pel_get_seqnum_post(mrioc, &mrioc->pel_cmds); + } + + return; + +out_failed: + mrioc->pel_enabled = false; +cleanup_drv_cmd: + drv_cmd->state = MPI3MR_CMD_NOTUSED; + drv_cmd->callback = NULL; + drv_cmd->retry_count = 0; +} + +/** + * mpi3mr_pel_get_seqnum_complete - PELGetSeqNum Completion callback + * @mrioc: Adapter instance reference + * @drv_cmd: Internal command tracker + * + * This is a callback handler for the PEL get sequence number + * request and a new PEL wait request will be issued to the + * firmware from this + * + * Return: Nothing. + */ +void mpi3mr_pel_get_seqnum_complete(struct mpi3mr_ioc *mrioc, + struct mpi3mr_drv_cmd *drv_cmd) +{ + struct mpi3_pel_reply *pel_reply = NULL; + struct mpi3_pel_seq *pel_seqnum_virt; + u16 ioc_status; + bool do_retry = false; + + pel_seqnum_virt = (struct mpi3_pel_seq *)mrioc->pel_seqnum_virt; + + if (drv_cmd->state & MPI3MR_CMD_RESET) + goto cleanup_drv_cmd; + + ioc_status = drv_cmd->ioc_status & MPI3_IOCSTATUS_STATUS_MASK; + if (ioc_status != MPI3_IOCSTATUS_SUCCESS) { + ioc_err(mrioc, "%s: Failed ioc_status(0x%04x) Loginfo(0x%08x)\n", + __func__, ioc_status, drv_cmd->ioc_loginfo); + do_retry = true; + } + + if (drv_cmd->state & MPI3MR_CMD_REPLY_VALID) + pel_reply = (struct mpi3_pel_reply *)drv_cmd->reply; + if (!pel_reply) { + ioc_err(mrioc, "%s: Failed No Reply\n", __func__); + goto out_failed; + } + + if (le16_to_cpu(pel_reply->pe_log_status) != MPI3_PEL_STATUS_SUCCESS) { + ioc_err(mrioc, "%s: Failed pe_log_status(0x%04x)\n", __func__, + le16_to_cpu(pel_reply->pe_log_status)); + do_retry = true; + } + + if (do_retry) { + if (drv_cmd->retry_count < MPI3MR_PEL_RETRY_COUNT) { + drv_cmd->retry_count++; + ioc_info(mrioc, "%s: retry=%d\n", + __func__, drv_cmd->retry_count); + mpi3mr_pel_get_seqnum_post(mrioc, drv_cmd); + return; + } + + ioc_err(mrioc, "%s: failed after all retries\n", __func__); + goto out_failed; + } + mrioc->pel_newest_seqnum = le32_to_cpu(pel_seqnum_virt->newest) + 1; + drv_cmd->retry_count = 0; + mpi3mr_pel_wait_post(mrioc, drv_cmd); + + return; + +out_failed: + mrioc->pel_enabled = false; +cleanup_drv_cmd: + drv_cmd->state = MPI3MR_CMD_NOTUSED; + drv_cmd->callback = NULL; + drv_cmd->retry_count = 0; +} + /** * mpi3mr_soft_reset_handler - Reset the controller * @mrioc: Adapter instance reference @@ -3964,6 +4242,11 @@ int mpi3mr_soft_reset_handler(struct mpi3mr_ioc *mrioc, out: if (!retval) { mrioc->reset_in_progress = 0; + mrioc->pel_abort_requested = 0; + if (mrioc->pel_enabled) { + mrioc->pel_cmds.retry_count = 0; + mpi3mr_pel_get_seqnum_post(mrioc, &mrioc->pel_cmds); + } scsi_unblock_requests(mrioc->shost); mpi3mr_rfresh_tgtdevs(mrioc); mrioc->ts_update_counter = 0; diff --git a/drivers/scsi/mpi3mr/mpi3mr_os.c b/drivers/scsi/mpi3mr/mpi3mr_os.c index cd53c4920207..149ba3fdfceb 100644 --- a/drivers/scsi/mpi3mr/mpi3mr_os.c +++ b/drivers/scsi/mpi3mr/mpi3mr_os.c @@ -1255,6 +1255,23 @@ static void mpi3mr_pcietopochg_evt_bh(struct mpi3mr_ioc *mrioc, } } +/** + * mpi3mr_logdata_evt_bh - Log data event bottomhalf + * @mrioc: Adapter instance reference + * @fwevt: Firmware event reference + * + * Extracts the event data and calls application interfacing + * function to process the event further. + * + * Return: Nothing. + */ +static void mpi3mr_logdata_evt_bh(struct mpi3mr_ioc *mrioc, + struct mpi3mr_fwevt *fwevt) +{ + mpi3mr_app_save_logdata(mrioc, fwevt->event_data, + fwevt->evt_data_size); +} + /** * mpi3mr_fwevt_bh - Firmware event bottomhalf handler * @mrioc: Adapter instance reference @@ -1307,6 +1324,11 @@ static void mpi3mr_fwevt_bh(struct mpi3mr_ioc *mrioc, mpi3mr_pcietopochg_evt_bh(mrioc, fwevt); break; } + case MPI3_EVENT_LOG_DATA: + { + mpi3mr_logdata_evt_bh(mrioc, fwevt); + break; + } default: break; } @@ -1906,6 +1928,7 @@ void mpi3mr_os_handle_events(struct mpi3mr_ioc *mrioc, break; } case MPI3_EVENT_DEVICE_INFO_CHANGED: + case MPI3_EVENT_LOG_DATA: { process_evt_bh = 1; break; From patchwork Tue Sep 21 18:45:59 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Kashyap Desai X-Patchwork-Id: 12508639 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-20.1 required=3.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_CR_TRAILER,INCLUDES_PATCH,MAILING_LIST_MULTI,MIME_HEADER_CTYPE_ONLY, SPF_HELO_NONE,SPF_PASS,T_TVD_MIME_NO_HEADERS,URIBL_BLOCKED,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 9F254C433F5 for ; Tue, 21 Sep 2021 18:47:07 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 80A4561242 for ; Tue, 21 Sep 2021 18:47:07 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231145AbhIUSsY (ORCPT ); Tue, 21 Sep 2021 14:48:24 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:40254 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S233843AbhIUSrx (ORCPT ); Tue, 21 Sep 2021 14:47:53 -0400 Received: from mail-pg1-x534.google.com (mail-pg1-x534.google.com [IPv6:2607:f8b0:4864:20::534]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 06374C061574 for ; Tue, 21 Sep 2021 11:46:25 -0700 (PDT) Received: by mail-pg1-x534.google.com with SMTP id r2so21594876pgl.10 for ; Tue, 21 Sep 2021 11:46:25 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=broadcom.com; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=FKvw8mPjYe57ejHAU/LiNCgMnNofuXmB0TRl1fPTGd0=; b=A2dTxeJ/LJaEljYiRV5ViYLaqVlJIR5CZdPZJ3MXuPOIHTR9D8/zy4FOonEz+ZfWMw P6JeZwxaG2ymyPdC9Ul2ruqQlSshQa3EcK9k7INzP1BYu/AAdGWhd1bV1bMiBiVNuvRL tYUwN3513J2RArasCPmtTcTeuR2/klxeJmx2M= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=FKvw8mPjYe57ejHAU/LiNCgMnNofuXmB0TRl1fPTGd0=; b=363T867ZNN+3vqVV0mNrCwE+egnqaq3g3vI5cryMTCMZbxHgmuKnsj7h9jWfQd8Cci l/oyjMRWDbW8BYJnZdPUBmwuBwHWHTFbe2liUL3lMbBhPNyKPnEjGhSZPoLbzqg9fJ7k bobVxdAhJnszSn2ZuQGMlEvlv48/4Vt9vGKI7A4sLNgngAu8dKmDMndmdgK4LzMlQw3g syi2GaaLj4PN8zSz8LGh5Vpa5jy/JKhvDF3zVw+iKTLfMOwDJxbPdqt24o+wctVbHysu jCTWVLRgIzVnmtElZdZlySqHbzuoYwQv9cXWdsraTXQZedn0ojpclPjWzBj5YNlpTBwp rw6g== X-Gm-Message-State: AOAM533XG0rVG6NE7D075HDofe0e+cXgqq5qEHzBL8HIuQrmiV0qs3ug 33Cyu//3p+mSGLwl+84SLVltTGWnTXWjaEZbre39IePRMUmIM/VmJmoPUykjwtDPlroR/2WKME7 YeBmpCbtQn8BKlfWHczA9j2tVK7kcHPr709WjMVfYQLAnjpkJKI83fnB9MGI6W9aUufrJf45di5 C2aUCiTScR X-Google-Smtp-Source: ABdhPJwLVBbpSoYKEySIUZ/6F21BmXK/j/tldJFWwJuKp8KrmGNVcJsZcUWQNXLtmqj6C5Asjicg8Q== X-Received: by 2002:a63:4a18:: with SMTP id x24mr29277882pga.209.1632249983943; Tue, 21 Sep 2021 11:46:23 -0700 (PDT) Received: from drv-bst-rhel8.dhcp.broadcom.net ([192.19.234.250]) by smtp.gmail.com with ESMTPSA id f144sm18258897pfa.24.2021.09.21.11.46.21 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 21 Sep 2021 11:46:23 -0700 (PDT) From: Kashyap Desai To: linux-scsi@vger.kernel.org Cc: jejb@linux.ibm.com, martin.petersen@oracle.com, steve.hagan@broadcom.com, mpi3mr-linuxdrv.pdl@broadcom.com, Kashyap Desai , sathya.prakash@broadcom.com Subject: [PATCH 6/7] mpi3mr: nvme pass-through support Date: Wed, 22 Sep 2021 00:15:59 +0530 Message-Id: <20210921184600.64427-7-kashyap.desai@broadcom.com> X-Mailer: git-send-email 2.18.1 In-Reply-To: <20210921184600.64427-1-kashyap.desai@broadcom.com> References: <20210921184600.64427-1-kashyap.desai@broadcom.com> Precedence: bulk List-ID: X-Mailing-List: linux-scsi@vger.kernel.org This patch adds support in the mpi3mr drive for management applications to send an MPI3 EncapsulatedNVMe passthru commands to the NVMe devices attached to the avenger series of tri-mode controller. Since the NVMe drives are exposed as SCSI drives by the controller the standard NVMe applications cannot be used to interact with the drives and the command sets supported is also limited by the controller firmware. Special handling is required for MPI3 EncapsulatedNVMe passthru commands for PRP/SGL setup in the commands hence the additional changes. Signed-off-by: Kashyap Desai Cc: sathya.prakash@broadcom.com --- drivers/scsi/mpi3mr/mpi3mr.h | 8 + drivers/scsi/mpi3mr/mpi3mr_app.c | 346 ++++++++++++++++++++++++++++++- drivers/scsi/mpi3mr/mpi3mr_app.h | 27 +++ 3 files changed, 380 insertions(+), 1 deletion(-) diff --git a/drivers/scsi/mpi3mr/mpi3mr.h b/drivers/scsi/mpi3mr/mpi3mr.h index 6108fe562bed..289aaaec7ee2 100644 --- a/drivers/scsi/mpi3mr/mpi3mr.h +++ b/drivers/scsi/mpi3mr/mpi3mr.h @@ -45,6 +45,7 @@ #include "mpi/mpi30_init.h" #include "mpi/mpi30_ioc.h" #include "mpi/mpi30_sas.h" +#include "mpi/mpi30_pci.h" #include "mpi3mr_debug.h" /* Global list and lock for storing multiple adapters managed by the driver */ @@ -699,6 +700,9 @@ struct scmd_priv { * @block_ioctls: Block IOCTL flag * @reset_mutex: Controller reset mutex * @reset_waitq: Controller reset wait queue + * @prp_list_virt: NVMe encapsulated PRP list virtual base + * @prp_list_virt_dma: NVMe encapsulated PRP list DMA + * @prp_sz: NVME encapsulated PRP list size * @diagsave_timeout: Diagnostic information save timeout * @logging_level: Controller debug logging level * @flush_io_count: I/O count to flush after reset @@ -840,6 +844,10 @@ struct mpi3mr_ioc { struct mutex reset_mutex; wait_queue_head_t reset_waitq; + void *prp_list_virt; + dma_addr_t prp_list_virt_dma; + u32 prp_sz; + u16 diagsave_timeout; int logging_level; u16 flush_io_count; diff --git a/drivers/scsi/mpi3mr/mpi3mr_app.c b/drivers/scsi/mpi3mr/mpi3mr_app.c index f8e7d2713fe4..0ecdf02c10c5 100644 --- a/drivers/scsi/mpi3mr/mpi3mr_app.c +++ b/drivers/scsi/mpi3mr/mpi3mr_app.c @@ -591,6 +591,315 @@ static void mpi3mr_ioctl_build_sgl(u8 *mpi_req, uint32_t sgl_offset, } } +/** + * mpi3mr_get_nvme_data_fmt - returns the NVMe data format + * @nvme_encap_request: NVMe encapsulated MPI request + * + * This function returns the type of the data format specified + * in user provided NVMe command in NVMe encapsulated request. + * + * Return: Data format of the NVMe command (PRP/SGL etc) + */ +static u8 mpi3mr_get_nvme_data_fmt( + struct mpi3_nvme_encapsulated_request *nvme_encap_request) +{ + return (u8)((nvme_encap_request->command[0] & 0xc000) >> 14); +} + +/** + * mpi3mr_build_nvme_sgl - SGL constructor for NVME + * encapsulated request + * @mrioc: Adapter instance reference + * @nvme_encap_request: NVMe encapsulated MPI request + * @dma_buffers: DMA address of the buffers to be placed in sgl + * @bufcnt: Number of DMA buffers + * + * This function places the DMA address of the given buffers in + * proper format as SGEs in the given NVMe encapsulated request. + * + * Return: 0 on success, -1 on failure + */ +static int mpi3mr_build_nvme_sgl(struct mpi3mr_ioc *mrioc, + struct mpi3_nvme_encapsulated_request *nvme_encap_request, + struct mpi3mr_buf_map *dma_buffers, u8 bufcnt) +{ + struct mpi3mr_nvme_pt_sge *nvme_sgl; + u64 sgl_ptr, sgemod_mask, sgemod_val; + u8 count; + size_t length = 0; + struct mpi3mr_buf_map *dma_buff = dma_buffers; + + /* + * Not all commands require a data transfer. If no data, just return + * without constructing any sgl. + */ + for (count = 0; count < bufcnt; count++, dma_buff++) { + if ((dma_buff->data_dir == DMA_TO_DEVICE) || + (dma_buff->data_dir == DMA_FROM_DEVICE)) { + sgl_ptr = (u64)dma_buff->kern_buf_dma; + length = dma_buff->kern_buf_len; + break; + } + } + if (!length) + return 0; + + sgemod_mask = ((u64)((mrioc->facts.sge_mod_mask) << + mrioc->facts.sge_mod_shift) << 32); + sgemod_val = ((u64)(mrioc->facts.sge_mod_value) << + mrioc->facts.sge_mod_shift) << 32; + + if (sgl_ptr & sgemod_mask) { + dbgprint(mrioc, + "%s: SGL address collides with SGE modifier\n", + __func__); + return -1; + } + + sgl_ptr &= ~sgemod_mask; + sgl_ptr |= sgemod_val; + nvme_sgl = (struct mpi3mr_nvme_pt_sge *) + ((u8 *)(nvme_encap_request->command) + MPI3MR_NVME_CMD_SGL_OFFSET); + memset(nvme_sgl, 0, sizeof(struct mpi3mr_nvme_pt_sge)); + nvme_sgl->base_addr = sgl_ptr; + nvme_sgl->length = length; + + return 0; +} + +/** + * mpi3mr_build_nvme_prp - PRP constructor for NVME + * encapsulated request + * @mrioc: Adapter instance reference + * @nvme_encap_request: NVMe encapsulated MPI request + * @dma_buffers: DMA address of the buffers to be placed in SGL + * @bufcnt: Number of DMA buffers + * + * This function places the DMA address of the given buffers in + * proper format as PRP entries in the given NVMe encapsulated + * request. + * + * Return: 0 on success, -1 on failure + */ +static int mpi3mr_build_nvme_prp(struct mpi3mr_ioc *mrioc, + struct mpi3_nvme_encapsulated_request *nvme_encap_request, + struct mpi3mr_buf_map *dma_buffers, u8 bufcnt) +{ + int prp_size = MPI3MR_NVME_PRP_SIZE; + __le64 *prp_entry, *prp1_entry, *prp2_entry, *prp_page; + dma_addr_t prp_entry_dma, prp_page_dma, dma_addr; + u32 offset, entry_len, dev_pgsz, page_mask_result, page_mask; + size_t length = 0; + u8 count; + struct mpi3mr_buf_map *dma_buff; + struct mpi3mr_tgt_dev *tgtdev; + u64 sgemod_mask, sgemod_val; + u16 dev_handle; + + dma_buff = dma_buffers; + dev_handle = nvme_encap_request->dev_handle; + + /* + * Not all commands require a data transfer. If no data, just return + * without constructing any PRP. + */ + for (count = 0; count < bufcnt; count++, dma_buff++) { + if ((dma_buff->data_dir == DMA_TO_DEVICE) || + (dma_buff->data_dir == DMA_FROM_DEVICE)) { + dma_addr = dma_buff->kern_buf_dma; + length = dma_buff->kern_buf_len; + break; + } + } + if (!length) + return 0; + + tgtdev = mpi3mr_get_tgtdev_by_handle(mrioc, dev_handle); + if (!tgtdev) { + dbgprint(mrioc, "%s: invalid device handle 0x%04x\n", + __func__, dev_handle); + return -1; + } + if (tgtdev->dev_spec.pcie_inf.pgsz == 0) { + dbgprint(mrioc, + "%s: NVME device page size is zero for handle 0x%04x\n", + __func__, dev_handle); + mpi3mr_tgtdev_put(tgtdev); + return -1; + } + dev_pgsz = 1 << (tgtdev->dev_spec.pcie_inf.pgsz); + mpi3mr_tgtdev_put(tgtdev); + + mrioc->prp_sz = 0; + mrioc->prp_list_virt = dma_alloc_coherent(&mrioc->pdev->dev, + dev_pgsz, + &mrioc->prp_list_virt_dma, + GFP_KERNEL); + + if (!mrioc->prp_list_virt) + return -1; + + mrioc->prp_sz = dev_pgsz; + /* + * Set pointers to PRP1 and PRP2, which are in the NVMe command. + * PRP1 is located at a 24 byte offset from the start of the NVMe + * command. Then set the current PRP entry pointer to PRP1. + */ + prp1_entry = (__le64 *)((u8 *)(nvme_encap_request->command) + + MPI3MR_NVME_CMD_PRP1_OFFSET); + prp2_entry = (__le64 *)((u8 *)(nvme_encap_request->command) + + MPI3MR_NVME_CMD_PRP2_OFFSET); + prp_entry = prp1_entry; + /* + * For the PRP entries, use the specially allocated buffer of + * contiguous memory. + */ + prp_page = (__le64 *)mrioc->prp_list_virt; + prp_page_dma = mrioc->prp_list_virt_dma; + + /* + * Check if we are within 1 entry of a page boundary we don't + * want our first entry to be a PRP List entry. + */ + page_mask = dev_pgsz - 1; + page_mask_result = (uintptr_t)((u8 *)prp_page + prp_size) & page_mask; + if (!page_mask_result) { + ioc_err(mrioc, "%s: PRP page is not page aligned\n", __func__); + goto err_out; + } + + /* + * Set PRP physical pointer, which initially points to the current PRP + * DMA memory page. + */ + prp_entry_dma = prp_page_dma; + sgemod_mask = ((u64)((mrioc->facts.sge_mod_mask) << + mrioc->facts.sge_mod_shift) << 32); + sgemod_val = ((u64)(mrioc->facts.sge_mod_value) << + mrioc->facts.sge_mod_shift) << 32; + + /* Loop while the length is not zero. */ + while (length) { + page_mask_result = (prp_entry_dma + prp_size) & page_mask; + if (!page_mask_result && (length > dev_pgsz)) { + dbgprint(mrioc, + "%s: single PRP page is not sufficient\n", + __func__); + goto err_out; + } + + /* Need to handle if entry will be part of a page. */ + offset = dma_addr & page_mask; + entry_len = dev_pgsz - offset; + + if (prp_entry == prp1_entry) { + /* + * Must fill in the first PRP pointer (PRP1) before + * moving on. + */ + *prp1_entry = cpu_to_le64(dma_addr); + if (*prp1_entry & sgemod_mask) { + dbgprint(mrioc, + "%s: PRP1 address collides with SGE modifier\n", + __func__); + goto err_out; + } + *prp1_entry &= ~sgemod_mask; + *prp1_entry |= sgemod_val; + + /* + * Now point to the second PRP entry within the + * command (PRP2). + */ + prp_entry = prp2_entry; + } else if (prp_entry == prp2_entry) { + /* + * Should the PRP2 entry be a PRP List pointer or just + * a regular PRP pointer? If there is more than one + * more page of data, must use a PRP List pointer. + */ + if (length > dev_pgsz) { + /* + * PRP2 will contain a PRP List pointer because + * more PRP's are needed with this command. The + * list will start at the beginning of the + * contiguous buffer. + */ + *prp2_entry = cpu_to_le64(prp_entry_dma); + if (*prp2_entry & sgemod_mask) { + dbgprint(mrioc, + "%s: PRP list address collides with SGE modifier\n", + __func__); + goto err_out; + } + *prp2_entry &= ~sgemod_mask; + *prp2_entry |= sgemod_val; + + /* + * The next PRP Entry will be the start of the + * first PRP List. + */ + prp_entry = prp_page; + continue; + } else { + /* + * After this, the PRP Entries are complete. + * This command uses 2 PRP's and no PRP list. + */ + *prp2_entry = cpu_to_le64(dma_addr); + if (*prp2_entry & sgemod_mask) { + dbgprint(mrioc, + "%s: PRP2 collides with SGE modifier\n", + __func__); + goto err_out; + } + *prp2_entry &= ~sgemod_mask; + *prp2_entry |= sgemod_val; + } + } else { + /* + * Put entry in list and bump the addresses. + * + * After PRP1 and PRP2 are filled in, this will fill in + * all remaining PRP entries in a PRP List, one per + * each time through the loop. + */ + *prp_entry = cpu_to_le64(dma_addr); + if (*prp1_entry & sgemod_mask) { + dbgprint(mrioc, + "%s: PRP address collides with SGE modifier\n", + __func__); + goto err_out; + } + *prp_entry &= ~sgemod_mask; + *prp_entry |= sgemod_val; + prp_entry++; + prp_entry_dma++; + } + + /* + * Bump the phys address of the command's data buffer by the + * entry_len. + */ + dma_addr += entry_len; + + /* decrement length accounting for last partial page. */ + if (entry_len > length) + length = 0; + else + length -= entry_len; + } + return 0; +err_out: + if (mrioc->prp_list_virt) { + dma_free_coherent(&mrioc->pdev->dev, mrioc->prp_sz, + mrioc->prp_list_virt, mrioc->prp_list_virt_dma); + mrioc->prp_list_virt = NULL; + } + return -1; +} + + /** * mpi3mr_ioctl_process_mpt_cmds - MPI Pass through IOCTL handler * @mrioc: Adapter instance reference @@ -622,7 +931,7 @@ static long mpi3mr_ioctl_process_mpt_cmds(struct file *file, struct mpi3_status_reply_descriptor *status_desc; struct mpi3mr_ioctl_reply_buf *ioctl_reply_buf = NULL; u8 *mpi_req = NULL, *sense_buff_k = NULL; - u8 count, bufcnt, din_cnt = 0, dout_cnt = 0; + u8 count, bufcnt, din_cnt = 0, dout_cnt = 0, nvme_fmt; u8 erb_offset = 0xFF, reply_offset = 0xFF, sg_entries = 0; bool invalid_be = false, is_rmcb = false, is_rmrb = false; u32 tmplen; @@ -809,6 +1118,35 @@ static long mpi3mr_ioctl_process_mpt_cmds(struct file *file, goto out; } + if (mpi_header->function == MPI3_FUNCTION_NVME_ENCAPSULATED) { + nvme_fmt = mpi3mr_get_nvme_data_fmt( + (struct mpi3_nvme_encapsulated_request *)mpi_req); + if (nvme_fmt == MPI3MR_NVME_DATA_FORMAT_PRP) { + if (mpi3mr_build_nvme_prp(mrioc, + (struct mpi3_nvme_encapsulated_request *)mpi_req, + dma_buffers, bufcnt)) { + rval = -ENOMEM; + mutex_unlock(&mrioc->ioctl_cmds.mutex); + goto out; + } + } else if (nvme_fmt == MPI3MR_NVME_DATA_FORMAT_SGL1 || + nvme_fmt == MPI3MR_NVME_DATA_FORMAT_SGL2) { + if (mpi3mr_build_nvme_sgl(mrioc, + (struct mpi3_nvme_encapsulated_request *)mpi_req, + dma_buffers, bufcnt)) { + rval = -EINVAL; + mutex_unlock(&mrioc->ioctl_cmds.mutex); + goto out; + } + } else { + dbgprint(mrioc, + "%s:invalid NVMe command format\n", __func__); + rval = -EINVAL; + mutex_unlock(&mrioc->ioctl_cmds.mutex); + goto out; + } + } + mrioc->ioctl_cmds.state = MPI3MR_CMD_PENDING; mrioc->ioctl_cmds.is_waiting = 1; mrioc->ioctl_cmds.callback = NULL; @@ -834,6 +1172,12 @@ static long mpi3mr_ioctl_process_mpt_cmds(struct file *file, goto out_unlock; } + if (mrioc->prp_list_virt) { + dma_free_coherent(&mrioc->pdev->dev, mrioc->prp_sz, + mrioc->prp_list_virt, mrioc->prp_list_virt_dma); + mrioc->prp_list_virt = NULL; + } + if ((mrioc->ioctl_cmds.ioc_status & MPI3_IOCSTATUS_STATUS_MASK) != MPI3_IOCSTATUS_SUCCESS) { dbgprint(mrioc, diff --git a/drivers/scsi/mpi3mr/mpi3mr_app.h b/drivers/scsi/mpi3mr/mpi3mr_app.h index ec714d210b9e..65ad2f9f3fbe 100644 --- a/drivers/scsi/mpi3mr/mpi3mr_app.h +++ b/drivers/scsi/mpi3mr/mpi3mr_app.h @@ -108,6 +108,33 @@ struct mpi3mr_adp_info { struct mpi3_driver_info_layout driver_info; }; +/* Encapsulated NVMe command definitions */ +#define MPI3MR_NVME_PRP_SIZE 8 /* PRP size */ +#define MPI3MR_NVME_CMD_PRP1_OFFSET 24 /* PRP1 offset in NVMe cmd */ +#define MPI3MR_NVME_CMD_PRP2_OFFSET 32 /* PRP2 offset in NVMe cmd */ +#define MPI3MR_NVME_CMD_SGL_OFFSET 24 /* SGL offset in NVMe cmd */ +#define MPI3MR_NVME_DATA_FORMAT_PRP 0 +#define MPI3MR_NVME_DATA_FORMAT_SGL1 1 +#define MPI3MR_NVME_DATA_FORMAT_SGL2 2 + +/** + * struct mpi3mr_nvme_pt_sge - Structure to store SGEs for NVMe + * Encapsulated commands. + * + * @base_addr: Physical address + * @length: SGE length + * @rsvd: Reserved + * @rsvd1: Reserved + * @sgl_type: sgl type + */ +struct mpi3mr_nvme_pt_sge { + u64 base_addr; + u32 length; + u16 rsvd; + u8 rsvd1; + u8 sgl_type; +}; + /** * struct mpi3mr_buf_map - local structure to * track kernel and user buffers associated with an IOCTL From patchwork Tue Sep 21 18:46:00 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Kashyap Desai X-Patchwork-Id: 12508641 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-20.1 required=3.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_CR_TRAILER,INCLUDES_PATCH,MAILING_LIST_MULTI,MIME_HEADER_CTYPE_ONLY, SPF_HELO_NONE,SPF_PASS,T_TVD_MIME_NO_HEADERS,URIBL_BLOCKED,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 23ECCC433F5 for ; Tue, 21 Sep 2021 18:47:18 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 0EE9261211 for ; Tue, 21 Sep 2021 18:47:18 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231474AbhIUSsg (ORCPT ); Tue, 21 Sep 2021 14:48:36 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:40266 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S233885AbhIUSr4 (ORCPT ); Tue, 21 Sep 2021 14:47:56 -0400 Received: from mail-pj1-x102c.google.com (mail-pj1-x102c.google.com [IPv6:2607:f8b0:4864:20::102c]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 6D065C061574 for ; Tue, 21 Sep 2021 11:46:27 -0700 (PDT) Received: by mail-pj1-x102c.google.com with SMTP id me1so243600pjb.4 for ; Tue, 21 Sep 2021 11:46:27 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=broadcom.com; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=NJ+nWZCFIY/UOj9FMrU5Kq1nXYZWQms7K1BB/RcYtYs=; b=NQlI8ywFm2lKKwW1lXcBAzlXaR2nKntnR2hTGVI/NiEeM7g5x4EO3yvclT3GaCxO44 n+1IaIw36pw84Hx/9OBRGTVfPUbpRF9f/wv/pEdcSL8L3Wv1OnFmkM3rMOb0hn5cW55C hPEEnOJJR8C+9tM2Wffef8csmqO0ZIHuR3EHA= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=NJ+nWZCFIY/UOj9FMrU5Kq1nXYZWQms7K1BB/RcYtYs=; b=CwFdSlf007VoJdJTjzW0n0wO7zYaZHDZKsfVwE+HeCVQIigXQW6z5rtghSg7rqhG7+ YCYSrQ04Dt/0vavg+J7xo+q80QuBQuELi5wXVKhKthyEreCmiUnBF0in7YSetCTSxxLy 3A2JrGlEVpqRCWNYQElpac8sqrU7aRdyyEQlqY97MSFg+Fi32Hkr1GDT8xsFlKBpSSnK suA/TImJ+a/7NOqSK9/qzfhjRsDDkBhnRopM4PnbJUuTw+w4CsE6+4xngWTZ+Dt9Aa0R l7rLuJKgGuUUh4u1TD/UbkuSxFlcsE1uco8CGGfDJRlqnI1ULZvTldLieMcYUYD1uacL /+5A== X-Gm-Message-State: AOAM530rmLyc99qlT+BtkVDJquGdXbKKDIDidlGXpY0bCGY+tdvE0URW PP5i/kF3FbW5Xc8Qv4PrE34Pfr5Fstiw7PUe9ORd/eiEgxei2kcoANEBlJVEcpfU2VNyl85WgWZ W2PJgYb3+rHpbiwZqz7n4yM4FILzIY18e8EawP+SX26ucQmvBIVSUIex29RoOu4QuhPnDlCeviw GhbG7MP53j X-Google-Smtp-Source: ABdhPJylyVbzOZf+r4xNlA46vkA+XFLxN2H/YR8klN9gAexxgxtnl0zQws0DvVp2f/JrOtte+S5GTg== X-Received: by 2002:a17:90a:ba0e:: with SMTP id s14mr6996811pjr.213.1632249986510; Tue, 21 Sep 2021 11:46:26 -0700 (PDT) Received: from drv-bst-rhel8.dhcp.broadcom.net ([192.19.234.250]) by smtp.gmail.com with ESMTPSA id f144sm18258897pfa.24.2021.09.21.11.46.24 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 21 Sep 2021 11:46:26 -0700 (PDT) From: Kashyap Desai To: linux-scsi@vger.kernel.org Cc: jejb@linux.ibm.com, martin.petersen@oracle.com, steve.hagan@broadcom.com, mpi3mr-linuxdrv.pdl@broadcom.com, Kashyap Desai , sathya.prakash@broadcom.com Subject: [PATCH 7/7] mpi3mr: task management for pass through command Date: Wed, 22 Sep 2021 00:16:00 +0530 Message-Id: <20210921184600.64427-8-kashyap.desai@broadcom.com> X-Mailer: git-send-email 2.18.1 In-Reply-To: <20210921184600.64427-1-kashyap.desai@broadcom.com> References: <20210921184600.64427-1-kashyap.desai@broadcom.com> Precedence: bulk List-ID: X-Mailing-List: linux-scsi@vger.kernel.org Signed-off-by: Kashyap Desai Cc: sathya.prakash@broadcom.com --- drivers/scsi/mpi3mr/mpi3mr.h | 4 ++++ drivers/scsi/mpi3mr/mpi3mr_app.c | 23 +++++++++++++++++++---- drivers/scsi/mpi3mr/mpi3mr_os.c | 2 +- 3 files changed, 24 insertions(+), 5 deletions(-) diff --git a/drivers/scsi/mpi3mr/mpi3mr.h b/drivers/scsi/mpi3mr/mpi3mr.h index 289aaaec7ee2..db3de78a979c 100644 --- a/drivers/scsi/mpi3mr/mpi3mr.h +++ b/drivers/scsi/mpi3mr/mpi3mr.h @@ -953,6 +953,10 @@ void mpi3mr_stop_watchdog(struct mpi3mr_ioc *mrioc); int mpi3mr_soft_reset_handler(struct mpi3mr_ioc *mrioc, u32 reset_reason, u8 snapdump); +int mpi3mr_issue_tm(struct mpi3mr_ioc *mrioc, u8 tm_type, + u16 handle, uint lun, u16 htag, ulong timeout, + struct mpi3mr_drv_cmd *drv_cmd, + u8 *resp_code, struct scmd_priv *cmd_priv); int mpi3mr_diagfault_reset_handler(struct mpi3mr_ioc *mrioc, u32 reset_reason); void mpi3mr_ioc_disable_intr(struct mpi3mr_ioc *mrioc); diff --git a/drivers/scsi/mpi3mr/mpi3mr_app.c b/drivers/scsi/mpi3mr/mpi3mr_app.c index 0ecdf02c10c5..c45d722a7f2a 100644 --- a/drivers/scsi/mpi3mr/mpi3mr_app.c +++ b/drivers/scsi/mpi3mr/mpi3mr_app.c @@ -931,7 +931,7 @@ static long mpi3mr_ioctl_process_mpt_cmds(struct file *file, struct mpi3_status_reply_descriptor *status_desc; struct mpi3mr_ioctl_reply_buf *ioctl_reply_buf = NULL; u8 *mpi_req = NULL, *sense_buff_k = NULL; - u8 count, bufcnt, din_cnt = 0, dout_cnt = 0, nvme_fmt; + u8 count, bufcnt, din_cnt = 0, dout_cnt = 0, nvme_fmt, resp_code; u8 erb_offset = 0xFF, reply_offset = 0xFF, sg_entries = 0; bool invalid_be = false, is_rmcb = false, is_rmrb = false; u32 tmplen; @@ -1165,10 +1165,25 @@ static long mpi3mr_ioctl_process_mpt_cmds(struct file *file, (karg.timeout * HZ)); if (!(mrioc->ioctl_cmds.state & MPI3MR_CMD_COMPLETE)) { mrioc->ioctl_cmds.is_waiting = 0; - dbgprint(mrioc, "%s command timed out\n", __func__); + if (mrioc->ioctl_cmds.state & MPI3MR_CMD_RESET) { + rval = -EAGAIN; + goto out_unlock; + } rval = -EFAULT; - mpi3mr_soft_reset_handler(mrioc, - MPI3MR_RESET_FROM_IOCTL_TIMEOUT, 1); + dbgprint(mrioc, + "%s: ioctl request timedout after %d seconds\n", + __func__, karg.timeout); + if ((mpi_header->function == MPI3_FUNCTION_NVME_ENCAPSULATED) || + (mpi_header->function == MPI3_FUNCTION_SCSI_IO)) + mpi3mr_issue_tm(mrioc, + MPI3_SCSITASKMGMT_TASKTYPE_TARGET_RESET, + mpi_header->function_dependent, 0, + MPI3MR_HOSTTAG_BLK_TMS, MPI3MR_RESETTM_TIMEOUT, + &mrioc->host_tm_cmds, &resp_code, NULL); + if (!(mrioc->ioctl_cmds.state & MPI3MR_CMD_COMPLETE) && + !(mrioc->ioctl_cmds.state & MPI3MR_CMD_RESET)) + mpi3mr_soft_reset_handler(mrioc, + MPI3MR_RESET_FROM_IOCTL_TIMEOUT, 1); goto out_unlock; } diff --git a/drivers/scsi/mpi3mr/mpi3mr_os.c b/drivers/scsi/mpi3mr/mpi3mr_os.c index 149ba3fdfceb..c82cb3c2fe4b 100644 --- a/drivers/scsi/mpi3mr/mpi3mr_os.c +++ b/drivers/scsi/mpi3mr/mpi3mr_os.c @@ -2606,7 +2606,7 @@ static void mpi3mr_print_response_code(struct mpi3mr_ioc *mrioc, u8 resp_code) * * Return: 0 on success, non-zero on errors */ -static int mpi3mr_issue_tm(struct mpi3mr_ioc *mrioc, u8 tm_type, +int mpi3mr_issue_tm(struct mpi3mr_ioc *mrioc, u8 tm_type, u16 handle, uint lun, u16 htag, ulong timeout, struct mpi3mr_drv_cmd *drv_cmd, u8 *resp_code, struct scmd_priv *cmd_priv)