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>
This commit is contained in:
Martin K. Petersen 2026-01-23 22:17:34 -05:00
commit d24e091dff
13 changed files with 478 additions and 40 deletions

View file

@ -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)

View file

@ -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];

View file

@ -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

View file

@ -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)

View file

@ -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

View file

@ -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

View file

@ -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 {

View file

@ -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 {

View file

@ -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);

View file

@ -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,
};

View file

@ -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,
@ -1103,6 +1108,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
@ -1244,6 +1274,60 @@ out_failed:
mpi3mr_free_ioctl_dma_memory(mrioc);
}
/**
* 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;

View file

@ -1138,6 +1138,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
@ -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);

View file

@ -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);
}
/**