summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
authorMartin K. Petersen <martin.petersen@oracle.com>2026-01-23 22:17:34 -0500
committerMartin K. Petersen <martin.petersen@oracle.com>2026-01-23 22:17:34 -0500
commitd24e091dff06d49c1873bbd5818b204202cc118f (patch)
treef5c7f43da0d569af40667d9966b902e3327f67cb /drivers
parent15df721f6297224a14bafde390146413be0d6942 (diff)
parent943e9049e84a8ff379534ed8945a929cec722a5a (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.h92
-rw-r--r--drivers/scsi/mpi3mr/mpi/mpi30_image.h102
-rw-r--r--drivers/scsi/mpi3mr/mpi/mpi30_init.h2
-rw-r--r--drivers/scsi/mpi3mr/mpi/mpi30_ioc.h1
-rw-r--r--drivers/scsi/mpi3mr/mpi/mpi30_pci.h2
-rw-r--r--drivers/scsi/mpi3mr/mpi/mpi30_sas.h2
-rw-r--r--drivers/scsi/mpi3mr/mpi/mpi30_tool.h6
-rw-r--r--drivers/scsi/mpi3mr/mpi/mpi30_transport.h4
-rw-r--r--drivers/scsi/mpi3mr/mpi3mr.h16
-rw-r--r--drivers/scsi/mpi3mr/mpi3mr_app.c28
-rw-r--r--drivers/scsi/mpi3mr/mpi3mr_fw.c131
-rw-r--r--drivers/scsi/mpi3mr/mpi3mr_os.c102
-rw-r--r--drivers/scsi/mpi3mr/mpi3mr_transport.c30
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);
}
/**