diff options
| author | Martin K. Petersen <martin.petersen@oracle.com> | 2026-01-23 22:17:34 -0500 |
|---|---|---|
| committer | Martin K. Petersen <martin.petersen@oracle.com> | 2026-01-23 22:17:34 -0500 |
| commit | d24e091dff06d49c1873bbd5818b204202cc118f (patch) | |
| tree | f5c7f43da0d569af40667d9966b902e3327f67cb /drivers | |
| parent | 15df721f6297224a14bafde390146413be0d6942 (diff) | |
| parent | 943e9049e84a8ff379534ed8945a929cec722a5a (diff) | |
Merge patch series "mpi3mr: Enhancements for mpi3mr"
Ranjan Kumar <ranjan.kumar@broadcom.com> says:
Enhancements for mpi3mr driver
Link: https://patch.msgid.link/20260116060719.32937-1-ranjan.kumar@broadcom.com
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
Diffstat (limited to 'drivers')
| -rw-r--r-- | drivers/scsi/mpi3mr/mpi/mpi30_cnfg.h | 92 | ||||
| -rw-r--r-- | drivers/scsi/mpi3mr/mpi/mpi30_image.h | 102 | ||||
| -rw-r--r-- | drivers/scsi/mpi3mr/mpi/mpi30_init.h | 2 | ||||
| -rw-r--r-- | drivers/scsi/mpi3mr/mpi/mpi30_ioc.h | 1 | ||||
| -rw-r--r-- | drivers/scsi/mpi3mr/mpi/mpi30_pci.h | 2 | ||||
| -rw-r--r-- | drivers/scsi/mpi3mr/mpi/mpi30_sas.h | 2 | ||||
| -rw-r--r-- | drivers/scsi/mpi3mr/mpi/mpi30_tool.h | 6 | ||||
| -rw-r--r-- | drivers/scsi/mpi3mr/mpi/mpi30_transport.h | 4 | ||||
| -rw-r--r-- | drivers/scsi/mpi3mr/mpi3mr.h | 16 | ||||
| -rw-r--r-- | drivers/scsi/mpi3mr/mpi3mr_app.c | 28 | ||||
| -rw-r--r-- | drivers/scsi/mpi3mr/mpi3mr_fw.c | 131 | ||||
| -rw-r--r-- | drivers/scsi/mpi3mr/mpi3mr_os.c | 102 | ||||
| -rw-r--r-- | drivers/scsi/mpi3mr/mpi3mr_transport.c | 30 |
13 files changed, 478 insertions, 40 deletions
diff --git a/drivers/scsi/mpi3mr/mpi/mpi30_cnfg.h b/drivers/scsi/mpi3mr/mpi/mpi30_cnfg.h index 8c8bfbbdd34e..33dd303c97bb 100644 --- a/drivers/scsi/mpi3mr/mpi/mpi30_cnfg.h +++ b/drivers/scsi/mpi3mr/mpi/mpi30_cnfg.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-or-later */ /* - * Copyright 2017-2023 Broadcom Inc. All rights reserved. + * Copyright 2017-2026 Broadcom Inc. All rights reserved. */ #ifndef MPI30_CNFG_H #define MPI30_CNFG_H 1 @@ -1037,6 +1037,7 @@ struct mpi3_io_unit_page5 { #define MPI3_IOUNIT5_DEVICE_SHUTDOWN_SATA_SSD_SHIFT (2) #define MPI3_IOUNIT5_DEVICE_SHUTDOWN_SAS_SSD_MASK (0x0003) #define MPI3_IOUNIT5_DEVICE_SHUTDOWN_SAS_SSD_SHIFT (0) +#define MPI3_IOUNIT5_DEVICE_SHUTDOWN_HDD_SPINDOWN_ENABLE (0x8000) #define MPI3_IOUNIT5_FLAGS_SATAPUIS_MASK (0x0c) #define MPI3_IOUNIT5_FLAGS_SATAPUIS_NOT_SUPPORTED (0x00) #define MPI3_IOUNIT5_FLAGS_SATAPUIS_OS_CONTROLLED (0x04) @@ -1074,7 +1075,8 @@ struct mpi3_io_unit_page8 { u8 current_key_encryption_algo; u8 key_digest_hash_algo; union mpi3_version_union current_svn; - __le32 reserved14; + __le16 pending_svn_time; + __le16 reserved16; __le32 current_key[128]; union mpi3_iounit8_digest digest[MPI3_IOUNIT8_DIGEST_MAX]; }; @@ -1406,6 +1408,7 @@ struct mpi3_driver_page1 { }; #define MPI3_DRIVER1_PAGEVERSION (0x00) +#define MPI3_DRIVER1_FLAGS_DEVICE_SHUTDOWN_ON_UNLOAD_DISABLE (0x0001) #ifndef MPI3_DRIVER2_TRIGGER_MAX #define MPI3_DRIVER2_TRIGGER_MAX (1) #endif @@ -1561,7 +1564,9 @@ struct mpi3_security1_key_record { u8 consumer; __le16 key_data_size; __le32 additional_key_data; - __le32 reserved08[2]; + u8 library_version; + u8 reserved09[3]; + __le32 reserved0c; union mpi3_security1_key_data key_data; }; @@ -1614,6 +1619,85 @@ struct mpi3_security_page2 { u8 reserved9d[3]; struct mpi3_security2_trusted_root trusted_root[MPI3_SECURITY2_TRUSTED_ROOT_MAX]; }; + +struct mpi3_security_page3 { + struct mpi3_config_page_header header; + __le16 key_data_length; + __le16 reserved0a; + u8 key_number; + u8 reserved0d[3]; + union mpi3_security_mac mac; + union mpi3_security_nonce nonce; + __le32 reserved90[12]; + u8 flags; + u8 consumer; + __le16 key_data_size; + __le32 additional_key_data; + u8 library_version; + u8 reserved_c9[3]; + __le32 reserved_cc; + u8 key_data[]; +}; + +#define MPI3_SECURITY3_PAGEVERSION (0x00) +#define MPI3_SECURITY3_FLAGS_TYPE_MASK (0x0f) +#define MPI3_SECURITY3_FLAGS_TYPE_SHIFT (0) +#define MPI3_SECURITY3_FLAGS_TYPE_NOT_VALID (0) +#define MPI3_SECURITY3_FLAGS_TYPE_MLDSA_PRIVATE (1) +#define MPI3_SECURITY3_FLAGS_TYPE_MLDSA_PUBLIC (2) +struct mpi3_security_page10 { + struct mpi3_config_page_header header; + __le32 reserved08[2]; + union mpi3_security_mac mac; + union mpi3_security_nonce nonce; + __le64 current_token_nonce; + __le64 previous_token_nonce; + __le32 reserved_a0[8]; + u8 diagnostic_auth_id[64]; +}; +#define MPI3_SECURITY10_PAGEVERSION (0x00) + +struct mpi3_security_page11 { + struct mpi3_config_page_header header; + u8 flags; + u8 reserved09[3]; + __le32 reserved0c; + __le32 diagnostic_token_length; + __le32 reserved14[3]; + u8 diagnostic_token[]; +}; +#define MPI3_SECURITY11_PAGEVERSION (0x00) +#define MPI3_SECURITY11_FLAGS_TOKEN_ENABLED (0x01) + +struct mpi3_security12_diag_feature { + __le32 feature_identifier; + u8 feature_size; + u8 feature_type; + __le16 reserved06; + u8 status; + u8 section; + __le16 reserved0a; + __le32 reserved0c; + u8 feature_data[64]; +}; +#define MPI3_SECURITY12_DIAG_FEATURE_STATUS_MASK (0x03) +#define MPI3_SECURITY12_DIAG_FEATURE_STATUS_SHIFT (0) +#define MPI3_SECURITY12_DIAG_FEATURE_STATUS_UNKNOWN (0x00) +#define MPI3_SECURITY12_DIAG_FEATURE_STATUS_DISABLED (0x01) +#define MPI3_SECURITY12_DIAG_FEATURE_STATUS_ENABLED (0x02) +#define MPI3_SECURITY12_DIAG_FEATURE_SECTION_PROTECTED (0x00) +#define MPI3_SECURITY12_DIAG_FEATURE_SECTION_UNPROTECTED (0x01) +#define MPI3_SECURITY12_DIAG_FEATURE_SECTION_PAYLOAD (0x02) +#define MPI3_SECURITY12_DIAG_FEATURE_SECTION_SIGNATURE (0x03) +struct mpi3_security_page12 { + struct mpi3_config_page_header header; + __le32 reserved08[2]; + u8 num_diag_features; + u8 reserved11[3]; + __le32 reserved14[3]; + struct mpi3_security12_diag_feature diag_feature[]; +}; + #define MPI3_SECURITY2_PAGEVERSION (0x00) struct mpi3_sas_io_unit0_phy_data { u8 io_unit_port; @@ -2314,6 +2398,8 @@ struct mpi3_device0_sas_sata_format { u8 attached_phy_identifier; u8 max_port_connections; u8 zone_group; + u8 reserved10[3]; + u8 negotiated_link_rate; }; #define MPI3_DEVICE0_SASSATA_FLAGS_WRITE_SAME_UNMAP_NCQ (0x0400) diff --git a/drivers/scsi/mpi3mr/mpi/mpi30_image.h b/drivers/scsi/mpi3mr/mpi/mpi30_image.h index 8d824107a678..62ddf094d46c 100644 --- a/drivers/scsi/mpi3mr/mpi/mpi30_image.h +++ b/drivers/scsi/mpi3mr/mpi/mpi30_image.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-or-later */ /* - * Copyright 2018-2023 Broadcom Inc. All rights reserved. + * Copyright 2018-2026 Broadcom Inc. All rights reserved. */ #ifndef MPI30_IMAGE_H #define MPI30_IMAGE_H 1 @@ -135,7 +135,7 @@ struct mpi3_ci_manifest_mpi { __le32 package_version_string_offset; __le32 package_build_date_string_offset; __le32 package_build_time_string_offset; - __le32 reserved4c; + __le32 diag_authorization_key_offset; __le32 diag_authorization_identifier[16]; struct mpi3_ci_manifest_mpi_comp_image_ref component_image_ref[MPI3_CI_MANIFEST_MPI_MAX]; }; @@ -148,16 +148,112 @@ struct mpi3_ci_manifest_mpi { #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_FLAGS_DIAG_AUTH_ANCHOR_MASK (0x06) +#define MPI3_CI_MANIFEST_MPI_FLAGS_DIAG_AUTH_ANCHOR_SHIFT (1) +#define MPI3_CI_MANIFEST_MPI_FLAGS_DIAG_AUTH_ANCHOR_IDENTIFIER (0x00) +#define MPI3_CI_MANIFEST_MPI_FLAGS_DIAG_AUTH_ANCHOR_KEY_OFFSET (0x02) #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) + +struct mpi3_sb_manifest_ci_digest { + __le32 signature1; + __le32 reserved04[2]; + u8 hash_algorithm; + u8 reserved09[3]; + struct mpi3_comp_image_version component_image_version; + __le32 component_image_version_string_offset; + __le32 digest[16]; +}; + +struct mpi3_sb_manifest_ci_ref_element { + u8 num_ci_digests; + u8 reserved01[3]; + struct mpi3_sb_manifest_ci_digest ci_digest[]; +}; + +struct mpi3_sb_manifest_embedded_key_element { + __le32 reserved00[3]; + u8 key_algorithm; + u8 flags; + __le16 public_key_size; + __le32 start_tag; + __le32 public_key[]; +}; + +#define MPI3_SB_MANIFEST_EMBEDDED_KEY_FLAGS_KEYINDEX_MASK (0x03) +#define MPI3_SB_MANIFEST_EMBEDDED_KEY_FLAGS_KEYINDEX_STRT (0x00) +#define MPI3_SB_MANIFEST_EMBEDDED_KEY_FLAGS_KEYINDEX_K2GO (0x01) +#define MPI3_SB_MANIFEST_EMBEDDED_KEY_STARTTAG_STRT (0x54525453) +#define MPI3_SB_MANIFEST_EMBEDDED_KEY_STARTTAG_K2GO (0x4f47324b) +#define MPI3_SB_MANIFEST_EMBEDDED_KEY_ENDTAG_STOP (0x504f5453) +#define MPI3_SB_MANIFEST_EMBEDDED_KEY_ENDTAG_K2ST (0x5453324b) + +struct mpi3_sb_manifest_diag_key_element { + __le32 reserved00[3]; + u8 key_algorithm; + u8 flags; + __le16 public_key_size; + __le32 public_key[]; +}; + +#define MPI3_SB_MANIFEST_DIAG_KEY_FLAGS_KEYINDEX_MASK (0x03) +#define MPI3_SB_MANIFEST_DIAG_KEY_FLAGS_KEYSELECT_FW_KEY (0x04) +union mpi3_sb_manifest_element_data { + struct mpi3_sb_manifest_ci_ref_element ci_ref; + struct mpi3_sb_manifest_embedded_key_element embed_key; + struct mpi3_sb_manifest_diag_key_element diag_key; + __le32 dword; +}; +struct mpi3_sb_manifest_element { + u8 manifest_element_form; + u8 reserved01[3]; + union mpi3_sb_manifest_element_data form_specific[]; +}; +#define MPI3_SB_MANIFEST_ELEMENT_FORM_CI_REFS (0x01) +#define MPI3_SB_MANIFEST_ELEMENT_FORM_EMBED_KEY (0x02) +#define MPI3_SB_MANIFEST_ELEMENT_FORM_DIAG_KEY (0x03) +struct mpi3_sb_manifest_mpi { + u8 manifest_type; + u8 reserved01[3]; + __le32 reserved04[3]; + u8 reserved10; + 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 component_image_references_offset; + __le32 embedded_key0offset; + __le32 embedded_key1offset; + __le32 diag_authorization_key_offset; + __le32 reserved5c[9]; + struct mpi3_sb_manifest_element manifest_elements[]; +}; + union mpi3_ci_manifest { struct mpi3_ci_manifest_mpi mpi; + struct mpi3_sb_manifest_mpi sb_mpi; __le32 dword[1]; }; -#define MPI3_CI_MANIFEST_TYPE_MPI (0x00) +#define MPI3_SB_MANIFEST_APU_IMMEDIATE_DEFER_APU_ENABLE (0x01) + +#define MPI3_CI_MANIFEST_TYPE_MPI (0x00) +#define MPI3_CI_MANIFEST_TYPE_SB (0x01) + struct mpi3_extended_image_header { u8 image_type; u8 reserved01[3]; diff --git a/drivers/scsi/mpi3mr/mpi/mpi30_init.h b/drivers/scsi/mpi3mr/mpi/mpi30_init.h index bbef5bac92ed..745e1101ebf4 100644 --- a/drivers/scsi/mpi3mr/mpi/mpi30_init.h +++ b/drivers/scsi/mpi3mr/mpi/mpi30_init.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-or-later */ /* - * Copyright 2016-2023 Broadcom Inc. All rights reserved. + * Copyright 2016-2026 Broadcom Inc. All rights reserved. */ #ifndef MPI30_INIT_H #define MPI30_INIT_H 1 diff --git a/drivers/scsi/mpi3mr/mpi/mpi30_ioc.h b/drivers/scsi/mpi3mr/mpi/mpi30_ioc.h index b42933fcd423..76dc18684be1 100644 --- a/drivers/scsi/mpi3mr/mpi/mpi30_ioc.h +++ b/drivers/scsi/mpi3mr/mpi/mpi30_ioc.h @@ -661,6 +661,7 @@ struct mpi3_event_data_diag_buffer_status_change { #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_EVENT_DIAG_BUFFER_STATUS_CHANGE_RC_CLEARED (0x04) #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) diff --git a/drivers/scsi/mpi3mr/mpi/mpi30_pci.h b/drivers/scsi/mpi3mr/mpi/mpi30_pci.h index 4eeb11c3c73e..3092dfe6d952 100644 --- a/drivers/scsi/mpi3mr/mpi/mpi30_pci.h +++ b/drivers/scsi/mpi3mr/mpi/mpi30_pci.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-or-later */ /* - * Copyright 2016-2023 Broadcom Inc. All rights reserved. + * Copyright 2016-2026 Broadcom Inc. All rights reserved. * */ #ifndef MPI30_PCI_H diff --git a/drivers/scsi/mpi3mr/mpi/mpi30_sas.h b/drivers/scsi/mpi3mr/mpi/mpi30_sas.h index 190b06508b00..f86da445df1e 100644 --- a/drivers/scsi/mpi3mr/mpi/mpi30_sas.h +++ b/drivers/scsi/mpi3mr/mpi/mpi30_sas.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-or-later */ /* - * Copyright 2016-2023 Broadcom Inc. All rights reserved. + * Copyright 2016-2026 Broadcom Inc. All rights reserved. */ #ifndef MPI30_SAS_H #define MPI30_SAS_H 1 diff --git a/drivers/scsi/mpi3mr/mpi/mpi30_tool.h b/drivers/scsi/mpi3mr/mpi/mpi30_tool.h index 50a65b16a818..72d3e6bc52ec 100644 --- a/drivers/scsi/mpi3mr/mpi/mpi30_tool.h +++ b/drivers/scsi/mpi3mr/mpi/mpi30_tool.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-or-later */ /* - * Copyright 2016-2024 Broadcom Inc. All rights reserved. + * Copyright 2016-2026 Broadcom Inc. All rights reserved. */ #ifndef MPI30_TOOL_H #define MPI30_TOOL_H 1 @@ -8,6 +8,10 @@ #define MPI3_DIAG_BUFFER_TYPE_TRACE (0x01) #define MPI3_DIAG_BUFFER_TYPE_FW (0x02) #define MPI3_DIAG_BUFFER_ACTION_RELEASE (0x01) +#define MPI3_DIAG_BUFFER_ACTION_PAUSE (0x02) +#define MPI3_DIAG_BUFFER_ACTION_RESUME (0x03) +#define MPI3_DIAG_BUFFER_ACTION_CLEAR (0x04) + #define MPI3_DIAG_BUFFER_POST_MSGFLAGS_SEGMENTED (0x01) struct mpi3_diag_buffer_post_request { diff --git a/drivers/scsi/mpi3mr/mpi/mpi30_transport.h b/drivers/scsi/mpi3mr/mpi/mpi30_transport.h index 28ab2efb3baa..290a1f5c2924 100644 --- a/drivers/scsi/mpi3mr/mpi/mpi30_transport.h +++ b/drivers/scsi/mpi3mr/mpi/mpi30_transport.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-or-later */ /* - * Copyright 2016-2023 Broadcom Inc. All rights reserved. + * Copyright 2016-2026 Broadcom Inc. All rights reserved. */ #ifndef MPI30_TRANSPORT_H #define MPI30_TRANSPORT_H 1 @@ -18,7 +18,7 @@ union mpi3_version_union { #define MPI3_VERSION_MAJOR (3) #define MPI3_VERSION_MINOR (0) -#define MPI3_VERSION_UNIT (37) +#define MPI3_VERSION_UNIT (39) #define MPI3_VERSION_DEV (0) #define MPI3_DEVHANDLE_INVALID (0xffff) struct mpi3_sysif_oper_queue_indexes { diff --git a/drivers/scsi/mpi3mr/mpi3mr.h b/drivers/scsi/mpi3mr/mpi3mr.h index 82f4ae87d6bc..6e962092577d 100644 --- a/drivers/scsi/mpi3mr/mpi3mr.h +++ b/drivers/scsi/mpi3mr/mpi3mr.h @@ -56,8 +56,8 @@ extern struct list_head mrioc_list; extern int prot_mask; extern atomic64_t event_counter; -#define MPI3MR_DRIVER_VERSION "8.15.0.5.51" -#define MPI3MR_DRIVER_RELDATE "18-November-2025" +#define MPI3MR_DRIVER_VERSION "8.17.0.3.50" +#define MPI3MR_DRIVER_RELDATE "09-January-2026" #define MPI3MR_DRIVER_NAME "mpi3mr" #define MPI3MR_DRIVER_LICENSE "GPL" @@ -643,6 +643,7 @@ struct mpi3mr_enclosure_node { * @dev_info: Device information bits * @phy_id: Phy identifier provided in device page 0 * @attached_phy_id: Attached phy identifier provided in device page 0 + * @negotiated_link_rate: Negotiated link rate from device page 0 * @sas_transport_attached: Is this device exposed to transport * @pend_sas_rphy_add: Flag to check device is in process of add * @hba_port: HBA port entry @@ -654,6 +655,7 @@ struct tgt_dev_sas_sata { u16 dev_info; u8 phy_id; u8 attached_phy_id; + u8 negotiated_link_rate; u8 sas_transport_attached; u8 pend_sas_rphy_add; struct mpi3mr_hba_port *hba_port; @@ -1134,6 +1136,10 @@ struct scmd_priv { * @default_qcount: Total Default queues * @active_poll_qcount: Currently active poll queue count * @requested_poll_qcount: User requested poll queue count + * @fault_during_init: Indicates a firmware fault occurred during initialization + * @saved_fault_code: Firmware fault code captured at the time of failure + * @saved_fault_info: Additional firmware-provided fault information + * @fwfault_counter: Count of firmware faults detected by the driver * @bsg_dev: BSG device structure * @bsg_queue: Request queue for BSG device * @stop_bsgs: Stop BSG request flag @@ -1336,6 +1342,10 @@ struct mpi3mr_ioc { u16 default_qcount; u16 active_poll_qcount; u16 requested_poll_qcount; + u8 fault_during_init; + u32 saved_fault_code; + u32 saved_fault_info[3]; + u64 fwfault_counter; struct device bsg_dev; struct request_queue *bsg_queue; @@ -1506,7 +1516,7 @@ void mpi3mr_pel_get_seqnum_complete(struct mpi3mr_ioc *mrioc, struct mpi3mr_drv_cmd *drv_cmd); int mpi3mr_pel_get_seqnum_post(struct mpi3mr_ioc *mrioc, struct mpi3mr_drv_cmd *drv_cmd); -void mpi3mr_app_save_logdata(struct mpi3mr_ioc *mrioc, char *event_data, +void mpi3mr_app_save_logdata_th(struct mpi3mr_ioc *mrioc, char *event_data, u16 event_data_size); struct mpi3mr_enclosure_node *mpi3mr_enclosure_find_by_handle( struct mpi3mr_ioc *mrioc, u16 handle); diff --git a/drivers/scsi/mpi3mr/mpi3mr_app.c b/drivers/scsi/mpi3mr/mpi3mr_app.c index 0e5478d62580..1353a8ff9c85 100644 --- a/drivers/scsi/mpi3mr/mpi3mr_app.c +++ b/drivers/scsi/mpi3mr/mpi3mr_app.c @@ -2920,7 +2920,7 @@ out: } /** - * mpi3mr_app_save_logdata - Save Log Data events + * mpi3mr_app_save_logdata_th - 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 @@ -2932,7 +2932,7 @@ out: * * Return:Nothing */ -void mpi3mr_app_save_logdata(struct mpi3mr_ioc *mrioc, char *event_data, +void mpi3mr_app_save_logdata_th(struct mpi3mr_ioc *mrioc, char *event_data, u16 event_data_size) { u32 index = mrioc->logdata_buf_idx, sz; @@ -3255,6 +3255,29 @@ adp_state_show(struct device *dev, struct device_attribute *attr, static DEVICE_ATTR_RO(adp_state); +/** + * fwfault_count_show() - SysFS callback to show firmware fault count + * @dev: class device + * @attr: Device attribute + * @buf: Buffer to copy data into + * + * Displays the total number of firmware faults detected by the driver + * since the controller was initialized. + * + * Return: Number of bytes written to @buf + */ + +static ssize_t +fwfault_count_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ + struct Scsi_Host *shost = class_to_shost(dev); + struct mpi3mr_ioc *mrioc = shost_priv(shost); + + return snprintf(buf, PAGE_SIZE, "%llu\n", mrioc->fwfault_counter); +} +static DEVICE_ATTR_RO(fwfault_count); + static struct attribute *mpi3mr_host_attrs[] = { &dev_attr_version_fw.attr, &dev_attr_fw_queue_depth.attr, @@ -3263,6 +3286,7 @@ static struct attribute *mpi3mr_host_attrs[] = { &dev_attr_reply_qfull_count.attr, &dev_attr_logging_level.attr, &dev_attr_adp_state.attr, + &dev_attr_fwfault_count.attr, NULL, }; diff --git a/drivers/scsi/mpi3mr/mpi3mr_fw.c b/drivers/scsi/mpi3mr/mpi3mr_fw.c index b564fe5980a6..1cfbdb773353 100644 --- a/drivers/scsi/mpi3mr/mpi3mr_fw.c +++ b/drivers/scsi/mpi3mr/mpi3mr_fw.c @@ -21,6 +21,10 @@ static int mpi3mr_check_op_admin_proc(struct mpi3mr_ioc *mrioc); static int poll_queues; module_param(poll_queues, int, 0444); MODULE_PARM_DESC(poll_queues, "Number of queues for io_uring poll mode. (Range 1 - 126)"); +static bool threaded_isr_poll = true; +module_param(threaded_isr_poll, bool, 0444); +MODULE_PARM_DESC(threaded_isr_poll, + "Enablement of IRQ polling thread (default=true)"); #if defined(writeq) && defined(CONFIG_64BIT) static inline void mpi3mr_writeq(__u64 b, void __iomem *addr, @@ -595,7 +599,8 @@ int mpi3mr_process_op_reply_q(struct mpi3mr_ioc *mrioc, * Exit completion loop to avoid CPU lockup * Ensure remaining completion happens from threaded ISR. */ - if (num_op_reply > mrioc->max_host_ios) { + if ((num_op_reply > mrioc->max_host_ios) && + (threaded_isr_poll == true)) { op_reply_q->enable_irq_poll = true; break; } @@ -692,7 +697,7 @@ static irqreturn_t mpi3mr_isr(int irq, void *privdata) * If more IOs are expected, schedule IRQ polling thread. * Otherwise exit from ISR. */ - if (!intr_info->op_reply_q) + if ((threaded_isr_poll == false) || !intr_info->op_reply_q) return ret; if (!intr_info->op_reply_q->enable_irq_poll || @@ -771,8 +776,8 @@ static inline int mpi3mr_request_irq(struct mpi3mr_ioc *mrioc, u16 index) intr_info->msix_index = index; intr_info->op_reply_q = NULL; - snprintf(intr_info->name, MPI3MR_NAME_LENGTH, "%s%d-msix%d", - mrioc->driver_name, mrioc->id, index); + scnprintf(intr_info->name, MPI3MR_NAME_LENGTH, + "%.32s%d-msix%u", mrioc->driver_name, mrioc->id, index); #ifndef CONFIG_PREEMPT_RT retval = request_threaded_irq(pci_irq_vector(pdev, index), mpi3mr_isr, @@ -1104,6 +1109,31 @@ void mpi3mr_print_fault_info(struct mpi3mr_ioc *mrioc) } /** + * mpi3mr_save_fault_info - Save fault information + * @mrioc: Adapter instance reference + * + * Save the controller fault information if there is a + * controller fault. + * + * Return: Nothing. + */ +static void mpi3mr_save_fault_info(struct mpi3mr_ioc *mrioc) +{ + u32 ioc_status, i; + + ioc_status = readl(&mrioc->sysif_regs->ioc_status); + + if (ioc_status & MPI3_SYSIF_IOC_STATUS_FAULT) { + mrioc->saved_fault_code = readl(&mrioc->sysif_regs->fault) & + MPI3_SYSIF_FAULT_CODE_MASK; + for (i = 0; i < 3; i++) { + mrioc->saved_fault_info[i] = + readl(&mrioc->sysif_regs->fault_info[i]); + } + } +} + +/** * mpi3mr_get_iocstate - Get IOC State * @mrioc: Adapter instance reference * @@ -1245,6 +1275,60 @@ out_failed: } /** + * mpi3mr_fault_uevent_emit - Emit uevent for any controller + * fault + * @mrioc: Pointer to the mpi3mr_ioc structure for the controller instance + * + * This function is invoked when the controller undergoes any + * type of fault. + */ + +static void mpi3mr_fault_uevent_emit(struct mpi3mr_ioc *mrioc) +{ + struct kobj_uevent_env *env; + int ret; + + env = kzalloc(sizeof(*env), GFP_KERNEL); + if (!env) + return; + + ret = add_uevent_var(env, "DRIVER=%s", mrioc->driver_name); + if (ret) + goto out_free; + + ret = add_uevent_var(env, "IOC_ID=%u", mrioc->id); + if (ret) + goto out_free; + + ret = add_uevent_var(env, "FAULT_CODE=0x%08x", + mrioc->saved_fault_code); + if (ret) + goto out_free; + + ret = add_uevent_var(env, "FAULT_INFO0=0x%08x", + mrioc->saved_fault_info[0]); + if (ret) + goto out_free; + + ret = add_uevent_var(env, "FAULT_INFO1=0x%08x", + mrioc->saved_fault_info[1]); + if (ret) + goto out_free; + + ret = add_uevent_var(env, "FAULT_INFO2=0x%08x", + mrioc->saved_fault_info[2]); + if (ret) + goto out_free; + + kobject_uevent_env(&mrioc->shost->shost_gendev.kobj, + KOBJ_CHANGE, env->envp); + +out_free: + kfree(env); + +} + +/** * mpi3mr_clear_reset_history - clear reset history * @mrioc: Adapter instance reference * @@ -1475,6 +1559,10 @@ retry_bring_ioc_ready: if (ioc_state == MRIOC_STATE_FAULT) { timeout = MPI3_SYSIF_DIAG_SAVE_TIMEOUT * 10; mpi3mr_print_fault_info(mrioc); + mpi3mr_save_fault_info(mrioc); + mrioc->fault_during_init = 1; + mrioc->fwfault_counter++; + do { host_diagnostic = readl(&mrioc->sysif_regs->host_diagnostic); @@ -1701,7 +1789,9 @@ static int mpi3mr_issue_reset(struct mpi3mr_ioc *mrioc, u16 reset_type, scratch_pad0 = ((MPI3MR_RESET_REASON_OSTYPE_LINUX << MPI3MR_RESET_REASON_OSTYPE_SHIFT) | (mrioc->facts.ioc_num << MPI3MR_RESET_REASON_IOCNUM_SHIFT) | reset_reason); - writel(reset_reason, &mrioc->sysif_regs->scratchpad[0]); + writel(scratch_pad0, &mrioc->sysif_regs->scratchpad[0]); + if (reset_type == MPI3_SYSIF_HOST_DIAG_RESET_ACTION_DIAG_FAULT) + mpi3mr_set_diagsave(mrioc); writel(host_diagnostic | reset_type, &mrioc->sysif_regs->host_diagnostic); switch (reset_type) { @@ -2570,6 +2660,9 @@ void mpi3mr_check_rh_fault_ioc(struct mpi3mr_ioc *mrioc, u32 reason_code) mpi3mr_set_trigger_data_in_all_hdb(mrioc, MPI3MR_HDB_TRIGGER_TYPE_FAULT, &trigger_data, 0); mpi3mr_print_fault_info(mrioc); + mpi3mr_save_fault_info(mrioc); + mrioc->fault_during_init = 1; + mrioc->fwfault_counter++; return; } @@ -2587,6 +2680,10 @@ void mpi3mr_check_rh_fault_ioc(struct mpi3mr_ioc *mrioc, u32 reason_code) break; msleep(100); } while (--timeout); + + mpi3mr_save_fault_info(mrioc); + mrioc->fault_during_init = 1; + mrioc->fwfault_counter++; } /** @@ -2763,6 +2860,11 @@ static void mpi3mr_watchdog_work(struct work_struct *work) union mpi3mr_trigger_data trigger_data; u16 reset_reason = MPI3MR_RESET_FROM_FAULT_WATCH; + if (mrioc->fault_during_init) { + mpi3mr_fault_uevent_emit(mrioc); + mrioc->fault_during_init = 0; + } + if (mrioc->reset_in_progress || mrioc->pci_err_recovery) return; @@ -2835,6 +2937,10 @@ static void mpi3mr_watchdog_work(struct work_struct *work) goto schedule_work; } + mpi3mr_save_fault_info(mrioc); + mpi3mr_fault_uevent_emit(mrioc); + mrioc->fwfault_counter++; + switch (trigger_data.fault) { case MPI3_SYSIF_FAULT_CODE_COMPLETE_RESET_NEEDED: case MPI3_SYSIF_FAULT_CODE_POWER_CYCLE_REQUIRED: @@ -5396,6 +5502,7 @@ int mpi3mr_soft_reset_handler(struct mpi3mr_ioc *mrioc, { int retval = 0, i; unsigned long flags; + enum mpi3mr_iocstate ioc_state; u32 host_diagnostic, timeout = MPI3_SYSIF_DIAG_SAVE_TIMEOUT * 10; union mpi3mr_trigger_data trigger_data; @@ -5454,7 +5561,6 @@ int mpi3mr_soft_reset_handler(struct mpi3mr_ioc *mrioc, mrioc->io_admin_reset_sync = 1; if (snapdump) { - mpi3mr_set_diagsave(mrioc); retval = mpi3mr_issue_reset(mrioc, MPI3_SYSIF_HOST_DIAG_RESET_ACTION_DIAG_FAULT, reset_reason); if (!retval) { @@ -5468,6 +5574,10 @@ int mpi3mr_soft_reset_handler(struct mpi3mr_ioc *mrioc, break; msleep(100); } while (--timeout); + + mpi3mr_save_fault_info(mrioc); + mpi3mr_fault_uevent_emit(mrioc); + mrioc->fwfault_counter++; mpi3mr_set_trigger_data_in_all_hdb(mrioc, MPI3MR_HDB_TRIGGER_TYPE_FAULT, &trigger_data, 0); } @@ -5556,8 +5666,13 @@ out: if (mrioc->pel_enabled) atomic64_inc(&event_counter); } else { - mpi3mr_issue_reset(mrioc, - MPI3_SYSIF_HOST_DIAG_RESET_ACTION_DIAG_FAULT, reset_reason); + dprint_reset(mrioc, + "soft_reset_handler failed, marking controller as unrecoverable\n"); + ioc_state = mpi3mr_get_iocstate(mrioc); + + if (ioc_state != MRIOC_STATE_FAULT) + mpi3mr_issue_reset(mrioc, + MPI3_SYSIF_HOST_DIAG_RESET_ACTION_DIAG_FAULT, reset_reason); mrioc->device_refresh_on = 0; mrioc->unrecoverable = 1; mrioc->reset_in_progress = 0; diff --git a/drivers/scsi/mpi3mr/mpi3mr_os.c b/drivers/scsi/mpi3mr/mpi3mr_os.c index 7212459d5c4a..e697ae6b7871 100644 --- a/drivers/scsi/mpi3mr/mpi3mr_os.c +++ b/drivers/scsi/mpi3mr/mpi3mr_os.c @@ -1139,6 +1139,89 @@ static void mpi3mr_refresh_tgtdevs(struct mpi3mr_ioc *mrioc) } /** + * mpi3mr_debug_dump_devpg0 - Dump device page0 + * @mrioc: Adapter instance reference + * @dev_pg0: Device page 0. + * + * Prints pertinent details of the device page 0. + * + * Return: Nothing. + */ +static void +mpi3mr_debug_dump_devpg0(struct mpi3mr_ioc *mrioc, struct mpi3_device_page0 *dev_pg0) +{ + ioc_info(mrioc, + "device_pg0: handle(0x%04x), perst_id(%d), wwid(0x%016llx), encl_handle(0x%04x), slot(%d)\n", + le16_to_cpu(dev_pg0->dev_handle), + le16_to_cpu(dev_pg0->persistent_id), + le64_to_cpu(dev_pg0->wwid), le16_to_cpu(dev_pg0->enclosure_handle), + le16_to_cpu(dev_pg0->slot)); + ioc_info(mrioc, "device_pg0: access_status(0x%02x), flags(0x%04x), device_form(0x%02x), queue_depth(%d)\n", + dev_pg0->access_status, le16_to_cpu(dev_pg0->flags), + dev_pg0->device_form, le16_to_cpu(dev_pg0->queue_depth)); + ioc_info(mrioc, "device_pg0: parent_handle(0x%04x), iounit_port(%d)\n", + le16_to_cpu(dev_pg0->parent_dev_handle), dev_pg0->io_unit_port); + + switch (dev_pg0->device_form) { + case MPI3_DEVICE_DEVFORM_SAS_SATA: + { + + struct mpi3_device0_sas_sata_format *sasinf = + &dev_pg0->device_specific.sas_sata_format; + ioc_info(mrioc, + "device_pg0: sas_sata: sas_address(0x%016llx),flags(0x%04x),\n" + "device_info(0x%04x), phy_num(%d), attached_phy_id(%d),negotiated_link_rate(0x%02x)\n", + le64_to_cpu(sasinf->sas_address), + le16_to_cpu(sasinf->flags), + le16_to_cpu(sasinf->device_info), sasinf->phy_num, + sasinf->attached_phy_identifier, sasinf->negotiated_link_rate); + break; + } + case MPI3_DEVICE_DEVFORM_PCIE: + { + + struct mpi3_device0_pcie_format *pcieinf = + &dev_pg0->device_specific.pcie_format; + ioc_info(mrioc, + "device_pg0: pcie: port_num(%d), device_info(0x%04x), mdts(%d), page_sz(0x%02x)\n", + pcieinf->port_num, le16_to_cpu(pcieinf->device_info), + le32_to_cpu(pcieinf->maximum_data_transfer_size), + pcieinf->page_size); + ioc_info(mrioc, + "device_pg0: pcie: abort_timeout(%d), reset_timeout(%d) capabilities (0x%08x)\n", + pcieinf->nvme_abort_to, pcieinf->controller_reset_to, + le32_to_cpu(pcieinf->capabilities)); + break; + } + case MPI3_DEVICE_DEVFORM_VD: + { + + struct mpi3_device0_vd_format *vdinf = + &dev_pg0->device_specific.vd_format; + + ioc_info(mrioc, + "device_pg0: vd: state(0x%02x), raid_level(%d), flags(0x%04x),\n" + "device_info(0x%04x) abort_timeout(%d), reset_timeout(%d)\n", + vdinf->vd_state, vdinf->raid_level, + le16_to_cpu(vdinf->flags), + le16_to_cpu(vdinf->device_info), + vdinf->vd_abort_to, vdinf->vd_reset_to); + ioc_info(mrioc, + "device_pg0: vd: tg_id(%d), high(%dMiB), low(%dMiB), qd_reduction_factor(%d)\n", + vdinf->io_throttle_group, + le16_to_cpu(vdinf->io_throttle_group_high), + le16_to_cpu(vdinf->io_throttle_group_low), + ((le16_to_cpu(vdinf->flags) & + MPI3_DEVICE0_VD_FLAGS_IO_THROTTLE_GROUP_QD_MASK) >> 12)); + break; + + } + default: + break; + } +} + +/** * mpi3mr_update_tgtdev - DevStatusChange evt bottomhalf * @mrioc: Adapter instance reference * @tgtdev: Target device internal structure @@ -1159,6 +1242,10 @@ static void mpi3mr_update_tgtdev(struct mpi3mr_ioc *mrioc, struct mpi3mr_enclosure_node *enclosure_dev = NULL; u8 prot_mask = 0; + if (mrioc->logging_level & + (MPI3_DEBUG_EVENT | MPI3_DEBUG_EVENT_WORK_TASK)) + mpi3mr_debug_dump_devpg0(mrioc, dev_pg0); + tgtdev->perst_id = le16_to_cpu(dev_pg0->persistent_id); tgtdev->dev_handle = le16_to_cpu(dev_pg0->dev_handle); tgtdev->dev_type = dev_pg0->device_form; @@ -1237,6 +1324,8 @@ static void mpi3mr_update_tgtdev(struct mpi3mr_ioc *mrioc, tgtdev->dev_spec.sas_sata_inf.phy_id = sasinf->phy_num; tgtdev->dev_spec.sas_sata_inf.attached_phy_id = sasinf->attached_phy_identifier; + tgtdev->dev_spec.sas_sata_inf.negotiated_link_rate = + sasinf->negotiated_link_rate; if ((dev_info & MPI3_SAS_DEVICE_INFO_DEVICE_TYPE_MASK) != MPI3_SAS_DEVICE_INFO_DEVICE_TYPE_END_DEVICE) tgtdev->is_hidden = 1; @@ -1962,7 +2051,7 @@ static void mpi3mr_pcietopochg_evt_bh(struct mpi3mr_ioc *mrioc, static void mpi3mr_logdata_evt_bh(struct mpi3mr_ioc *mrioc, struct mpi3mr_fwevt *fwevt) { - mpi3mr_app_save_logdata(mrioc, fwevt->event_data, + mpi3mr_app_save_logdata_th(mrioc, fwevt->event_data, fwevt->event_data_size); } @@ -3058,6 +3147,11 @@ void mpi3mr_os_handle_events(struct mpi3mr_ioc *mrioc, } case MPI3_EVENT_DEVICE_INFO_CHANGED: case MPI3_EVENT_LOG_DATA: + + sz = event_reply->event_data_length * 4; + mpi3mr_app_save_logdata_th(mrioc, + (char *)event_reply->event_data, sz); + break; case MPI3_EVENT_ENCL_DEVICE_STATUS_CHANGE: case MPI3_EVENT_ENCL_DEVICE_ADDED: { @@ -5381,8 +5475,10 @@ mpi3mr_probe(struct pci_dev *pdev, const struct pci_device_id *id) if (retval < 0) goto id_alloc_failed; mrioc->id = (u8)retval; - sprintf(mrioc->driver_name, "%s", MPI3MR_DRIVER_NAME); - sprintf(mrioc->name, "%s%d", mrioc->driver_name, mrioc->id); + strscpy(mrioc->driver_name, MPI3MR_DRIVER_NAME, + sizeof(mrioc->driver_name)); + scnprintf(mrioc->name, sizeof(mrioc->name), + "%s%u", mrioc->driver_name, mrioc->id); INIT_LIST_HEAD(&mrioc->list); spin_lock(&mrioc_list_lock); list_add_tail(&mrioc->list, &mrioc_list); diff --git a/drivers/scsi/mpi3mr/mpi3mr_transport.c b/drivers/scsi/mpi3mr/mpi3mr_transport.c index d70f002d6487..101161554ef1 100644 --- a/drivers/scsi/mpi3mr/mpi3mr_transport.c +++ b/drivers/scsi/mpi3mr/mpi3mr_transport.c @@ -2284,11 +2284,11 @@ void mpi3mr_expander_remove(struct mpi3mr_ioc *mrioc, u64 sas_address, * @mrioc: Adapter instance reference * @tgtdev: Target device * - * This function identifies whether the target device is - * attached directly or through expander and issues sas phy - * page0 or expander phy page1 and gets the link rate, if there - * is any failure in reading the pages then this returns link - * rate of 1.5. + * This function first tries to use the link rate from DevicePage0 + * (populated by firmware during device discovery). If the cached + * value is not available or invalid, it falls back to reading from + * sas phy page0 or expander phy page1. + * * * Return: logical link rate. */ @@ -2301,6 +2301,14 @@ static u8 mpi3mr_get_sas_negotiated_logical_linkrate(struct mpi3mr_ioc *mrioc, u32 phynum_handle; u16 ioc_status; + /* First, try to use link rate from DevicePage0 (populated by firmware) */ + if (tgtdev->dev_spec.sas_sata_inf.negotiated_link_rate >= + MPI3_SAS_NEG_LINK_RATE_1_5) { + link_rate = tgtdev->dev_spec.sas_sata_inf.negotiated_link_rate; + goto out; + } + + /* Fallback to reading from phy pages if DevicePage0 value not available */ phy_number = tgtdev->dev_spec.sas_sata_inf.phy_id; if (!(tgtdev->devpg0_flag & MPI3_DEVICE0_FLAGS_ATT_METHOD_DIR_ATTACHED)) { phynum_handle = ((phy_number<<MPI3_SAS_EXPAND_PGAD_PHYNUM_SHIFT) @@ -2318,9 +2326,7 @@ static u8 mpi3mr_get_sas_negotiated_logical_linkrate(struct mpi3mr_ioc *mrioc, __FILE__, __LINE__, __func__); goto out; } - link_rate = (expander_pg1.negotiated_link_rate & - MPI3_SAS_NEG_LINK_RATE_LOGICAL_MASK) >> - MPI3_SAS_NEG_LINK_RATE_LOGICAL_SHIFT; + link_rate = expander_pg1.negotiated_link_rate; goto out; } if (mpi3mr_cfg_get_sas_phy_pg0(mrioc, &ioc_status, &phy_pg0, @@ -2335,11 +2341,11 @@ static u8 mpi3mr_get_sas_negotiated_logical_linkrate(struct mpi3mr_ioc *mrioc, __FILE__, __LINE__, __func__); goto out; } - link_rate = (phy_pg0.negotiated_link_rate & - MPI3_SAS_NEG_LINK_RATE_LOGICAL_MASK) >> - MPI3_SAS_NEG_LINK_RATE_LOGICAL_SHIFT; + link_rate = phy_pg0.negotiated_link_rate; + out: - return link_rate; + return ((link_rate & MPI3_SAS_NEG_LINK_RATE_LOGICAL_MASK) >> + MPI3_SAS_NEG_LINK_RATE_LOGICAL_SHIFT); } /** |
