diff options
Diffstat (limited to 'drivers/scsi/mpi3mr')
-rw-r--r-- | drivers/scsi/mpi3mr/mpi/mpi30_cnfg.h | 4 | ||||
-rw-r--r-- | drivers/scsi/mpi3mr/mpi/mpi30_image.h | 8 | ||||
-rw-r--r-- | drivers/scsi/mpi3mr/mpi/mpi30_init.h | 11 | ||||
-rw-r--r-- | drivers/scsi/mpi3mr/mpi/mpi30_ioc.h | 21 | ||||
-rw-r--r-- | drivers/scsi/mpi3mr/mpi/mpi30_tool.h | 1 | ||||
-rw-r--r-- | drivers/scsi/mpi3mr/mpi/mpi30_transport.h | 20 | ||||
-rw-r--r-- | drivers/scsi/mpi3mr/mpi3mr.h | 34 | ||||
-rw-r--r-- | drivers/scsi/mpi3mr/mpi3mr_app.c | 129 | ||||
-rw-r--r-- | drivers/scsi/mpi3mr/mpi3mr_fw.c | 159 | ||||
-rw-r--r-- | drivers/scsi/mpi3mr/mpi3mr_os.c | 101 |
10 files changed, 460 insertions, 28 deletions
diff --git a/drivers/scsi/mpi3mr/mpi/mpi30_cnfg.h b/drivers/scsi/mpi3mr/mpi/mpi30_cnfg.h index 00cd18edfad6..96401eb7e231 100644 --- a/drivers/scsi/mpi3mr/mpi/mpi30_cnfg.h +++ b/drivers/scsi/mpi3mr/mpi/mpi30_cnfg.h @@ -19,6 +19,7 @@ #define MPI3_CONFIG_PAGETYPE_PCIE_SWITCH (0x31) #define MPI3_CONFIG_PAGETYPE_PCIE_LINK (0x33) #define MPI3_CONFIG_PAGEATTR_MASK (0xf0) +#define MPI3_CONFIG_PAGEATTR_SHIFT (4) #define MPI3_CONFIG_PAGEATTR_READ_ONLY (0x00) #define MPI3_CONFIG_PAGEATTR_CHANGEABLE (0x10) #define MPI3_CONFIG_PAGEATTR_PERSISTENT (0x20) @@ -29,10 +30,13 @@ #define MPI3_CONFIG_ACTION_READ_PERSISTENT (0x04) #define MPI3_CONFIG_ACTION_WRITE_PERSISTENT (0x05) #define MPI3_DEVICE_PGAD_FORM_MASK (0xf0000000) +#define MPI3_DEVICE_PGAD_FORM_SHIFT (28) #define MPI3_DEVICE_PGAD_FORM_GET_NEXT_HANDLE (0x00000000) #define MPI3_DEVICE_PGAD_FORM_HANDLE (0x20000000) #define MPI3_DEVICE_PGAD_HANDLE_MASK (0x0000ffff) +#define MPI3_DEVICE_PGAD_HANDLE_SHIFT (0) #define MPI3_SAS_EXPAND_PGAD_FORM_MASK (0xf0000000) +#define MPI3_SAS_EXPAND_PGAD_FORM_SHIFT (28) #define MPI3_SAS_EXPAND_PGAD_FORM_GET_NEXT_HANDLE (0x00000000) #define MPI3_SAS_EXPAND_PGAD_FORM_HANDLE_PHY_NUM (0x10000000) #define MPI3_SAS_EXPAND_PGAD_FORM_HANDLE (0x20000000) diff --git a/drivers/scsi/mpi3mr/mpi/mpi30_image.h b/drivers/scsi/mpi3mr/mpi/mpi30_image.h index 2c6e548cbd0f..8d824107a678 100644 --- a/drivers/scsi/mpi3mr/mpi/mpi30_image.h +++ b/drivers/scsi/mpi3mr/mpi/mpi30_image.h @@ -66,7 +66,12 @@ struct mpi3_component_image_header { #define MPI3_IMAGE_HEADER_SIGNATURE1_SMM (0x204d4d53) #define MPI3_IMAGE_HEADER_SIGNATURE1_PSW (0x20575350) #define MPI3_IMAGE_HEADER_SIGNATURE2_VALUE (0x50584546) +#define MPI3_IMAGE_HEADER_FLAGS_SIGNED_UEFI_MASK (0x00000300) +#define MPI3_IMAGE_HEADER_FLAGS_SIGNED_UEFI_SHIFT (8) +#define MPI3_IMAGE_HEADER_FLAGS_CERT_CHAIN_FORMAT_MASK (0x000000c0) +#define MPI3_IMAGE_HEADER_FLAGS_CERT_CHAIN_FORMAT_SHIFT (6) #define MPI3_IMAGE_HEADER_FLAGS_DEVICE_KEY_BASIS_MASK (0x00000030) +#define MPI3_IMAGE_HEADER_FLAGS_DEVICE_KEY_BASIS_SHIFT (4) #define MPI3_IMAGE_HEADER_FLAGS_DEVICE_KEY_BASIS_CDI (0x00000000) #define MPI3_IMAGE_HEADER_FLAGS_DEVICE_KEY_BASIS_DI (0x00000010) #define MPI3_IMAGE_HEADER_FLAGS_SIGNED_NVDATA (0x00000008) @@ -214,11 +219,13 @@ struct mpi3_encrypted_hash_entry { #define MPI3_HASH_IMAGE_TYPE_KEY_WITH_HASH_1_OF_2 (0x04) #define MPI3_HASH_IMAGE_TYPE_KEY_WITH_HASH_2_OF_2 (0x05) #define MPI3_HASH_ALGORITHM_VERSION_MASK (0xe0) +#define MPI3_HASH_ALGORITHM_VERSION_SHIFT (5) #define MPI3_HASH_ALGORITHM_VERSION_NONE (0x00) #define MPI3_HASH_ALGORITHM_VERSION_SHA1 (0x20) #define MPI3_HASH_ALGORITHM_VERSION_SHA2 (0x40) #define MPI3_HASH_ALGORITHM_VERSION_SHA3 (0x60) #define MPI3_HASH_ALGORITHM_SIZE_MASK (0x1f) +#define MPI3_HASH_ALGORITHM_SIZE_SHIFT (0) #define MPI3_HASH_ALGORITHM_SIZE_UNUSED (0x00) #define MPI3_HASH_ALGORITHM_SIZE_SHA256 (0x01) #define MPI3_HASH_ALGORITHM_SIZE_SHA512 (0x02) @@ -236,6 +243,7 @@ struct mpi3_encrypted_hash_entry { #define MPI3_ENCRYPTION_ALGORITHM_ML_DSA_65 (0x0c) #define MPI3_ENCRYPTION_ALGORITHM_ML_DSA_44 (0x0d) #define MPI3_ENCRYPTED_HASH_ENTRY_FLAGS_PAIRED_KEY_MASK (0x0f) +#define MPI3_ENCRYPTED_HASH_ENTRY_FLAGS_PAIRED_KEY_SHIFT (0) #ifndef MPI3_ENCRYPTED_HASH_ENTRY_MAX #define MPI3_ENCRYPTED_HASH_ENTRY_MAX (1) diff --git a/drivers/scsi/mpi3mr/mpi/mpi30_init.h b/drivers/scsi/mpi3mr/mpi/mpi30_init.h index af86d12c8e49..bbef5bac92ed 100644 --- a/drivers/scsi/mpi3mr/mpi/mpi30_init.h +++ b/drivers/scsi/mpi3mr/mpi/mpi30_init.h @@ -38,23 +38,31 @@ struct mpi3_scsi_io_request { #define MPI3_SCSIIO_MSGFLAGS_METASGL_VALID (0x80) #define MPI3_SCSIIO_MSGFLAGS_DIVERT_TO_FIRMWARE (0x40) #define MPI3_SCSIIO_FLAGS_LARGE_CDB (0x60000000) +#define MPI3_SCSIIO_FLAGS_LARGE_CDB_MASK (0x60000000) +#define MPI3_SCSIIO_FLAGS_LARGE_CDB_SHIFT (29) +#define MPI3_SCSIIO_FLAGS_IOC_USE_ONLY_27_MASK (0x18000000) +#define MPI3_SCSIIO_FLAGS_IOC_USE_ONLY_27_SHIFT (27) #define MPI3_SCSIIO_FLAGS_CDB_16_OR_LESS (0x00000000) #define MPI3_SCSIIO_FLAGS_CDB_GREATER_THAN_16 (0x20000000) #define MPI3_SCSIIO_FLAGS_CDB_IN_SEPARATE_BUFFER (0x40000000) #define MPI3_SCSIIO_FLAGS_TASKATTRIBUTE_MASK (0x07000000) +#define MPI3_SCSIIO_FLAGS_TASKATTRIBUTE_SHIFT (24) +#define MPI3_SCSIIO_FLAGS_DATADIRECTION_MASK (0x000c0000) +#define MPI3_SCSIIO_FLAGS_DATADIRECTION_SHIFT (18) #define MPI3_SCSIIO_FLAGS_TASKATTRIBUTE_SIMPLEQ (0x00000000) #define MPI3_SCSIIO_FLAGS_TASKATTRIBUTE_HEADOFQ (0x01000000) #define MPI3_SCSIIO_FLAGS_TASKATTRIBUTE_ORDEREDQ (0x02000000) #define MPI3_SCSIIO_FLAGS_TASKATTRIBUTE_ACAQ (0x04000000) #define MPI3_SCSIIO_FLAGS_CMDPRI_MASK (0x00f00000) #define MPI3_SCSIIO_FLAGS_CMDPRI_SHIFT (20) -#define MPI3_SCSIIO_FLAGS_DATADIRECTION_MASK (0x000c0000) #define MPI3_SCSIIO_FLAGS_DATADIRECTION_NO_DATA_TRANSFER (0x00000000) #define MPI3_SCSIIO_FLAGS_DATADIRECTION_WRITE (0x00040000) #define MPI3_SCSIIO_FLAGS_DATADIRECTION_READ (0x00080000) #define MPI3_SCSIIO_FLAGS_DMAOPERATION_MASK (0x00030000) +#define MPI3_SCSIIO_FLAGS_DMAOPERATION_SHIFT (16) #define MPI3_SCSIIO_FLAGS_DMAOPERATION_HOST_PI (0x00010000) #define MPI3_SCSIIO_FLAGS_DIVERT_REASON_MASK (0x000000f0) +#define MPI3_SCSIIO_FLAGS_DIVERT_REASON_SHIFT (4) #define MPI3_SCSIIO_FLAGS_DIVERT_REASON_IO_THROTTLING (0x00000010) #define MPI3_SCSIIO_FLAGS_DIVERT_REASON_WRITE_SAME_TOO_LARGE (0x00000020) #define MPI3_SCSIIO_FLAGS_DIVERT_REASON_PROD_SPECIFIC (0x00000080) @@ -99,6 +107,7 @@ struct mpi3_scsi_io_reply { #define MPI3_SCSI_STATUS_ACA_ACTIVE (0x30) #define MPI3_SCSI_STATUS_TASK_ABORTED (0x40) #define MPI3_SCSI_STATE_SENSE_MASK (0x03) +#define MPI3_SCSI_STATE_SENSE_SHIFT (0) #define MPI3_SCSI_STATE_SENSE_VALID (0x00) #define MPI3_SCSI_STATE_SENSE_FAILED (0x01) #define MPI3_SCSI_STATE_SENSE_BUFF_Q_EMPTY (0x02) diff --git a/drivers/scsi/mpi3mr/mpi/mpi30_ioc.h b/drivers/scsi/mpi3mr/mpi/mpi30_ioc.h index c374867f9ba0..b42933fcd423 100644 --- a/drivers/scsi/mpi3mr/mpi/mpi30_ioc.h +++ b/drivers/scsi/mpi3mr/mpi/mpi30_ioc.h @@ -30,6 +30,7 @@ struct mpi3_ioc_init_request { #define MPI3_IOCINIT_MSGFLAGS_WRITESAMEDIVERT_SUPPORTED (0x08) #define MPI3_IOCINIT_MSGFLAGS_SCSIIOSTATUSREPLY_SUPPORTED (0x04) #define MPI3_IOCINIT_MSGFLAGS_HOSTMETADATA_MASK (0x03) +#define MPI3_IOCINIT_MSGFLAGS_HOSTMETADATA_SHIFT (0) #define MPI3_IOCINIT_MSGFLAGS_HOSTMETADATA_NOT_USED (0x00) #define MPI3_IOCINIT_MSGFLAGS_HOSTMETADATA_SEPARATED (0x01) #define MPI3_IOCINIT_MSGFLAGS_HOSTMETADATA_INLINE (0x02) @@ -40,6 +41,7 @@ struct mpi3_ioc_init_request { #define MPI3_WHOINIT_MANUFACTURER (0x04) #define MPI3_IOCINIT_DRIVERCAP_OSEXPOSURE_MASK (0x00000003) +#define MPI3_IOCINIT_DRIVERCAP_OSEXPOSURE_SHIFT (0) #define MPI3_IOCINIT_DRIVERCAP_OSEXPOSURE_NO_GUIDANCE (0x00000000) #define MPI3_IOCINIT_DRIVERCAP_OSEXPOSURE_NO_SPECIAL (0x00000001) #define MPI3_IOCINIT_DRIVERCAP_OSEXPOSURE_REPORT_AS_HDD (0x00000002) @@ -111,9 +113,11 @@ struct mpi3_ioc_facts_data { __le32 diag_tty_size; }; #define MPI3_IOCFACTS_CAPABILITY_NON_SUPERVISOR_MASK (0x80000000) +#define MPI3_IOCFACTS_CAPABILITY_NON_SUPERVISOR_SHIFT (31) #define MPI3_IOCFACTS_CAPABILITY_SUPERVISOR_IOC (0x00000000) #define MPI3_IOCFACTS_CAPABILITY_NON_SUPERVISOR_IOC (0x80000000) #define MPI3_IOCFACTS_CAPABILITY_INT_COALESCE_MASK (0x00000600) +#define MPI3_IOCFACTS_CAPABILITY_INT_COALESCE_SHIFT (9) #define MPI3_IOCFACTS_CAPABILITY_INT_COALESCE_FIXED_THRESHOLD (0x00000000) #define MPI3_IOCFACTS_CAPABILITY_INT_COALESCE_OUTSTANDING_IO (0x00000200) #define MPI3_IOCFACTS_CAPABILITY_COMPLETE_RESET_SUPPORTED (0x00000100) @@ -134,6 +138,7 @@ struct mpi3_ioc_facts_data { #define MPI3_IOCFACTS_EXCEPT_SAS_DISABLED (0x1000) #define MPI3_IOCFACTS_EXCEPT_SAFE_MODE (0x0800) #define MPI3_IOCFACTS_EXCEPT_SECURITY_KEY_MASK (0x0700) +#define MPI3_IOCFACTS_EXCEPT_SECURITY_KEY_SHIFT (8) #define MPI3_IOCFACTS_EXCEPT_SECURITY_KEY_NONE (0x0000) #define MPI3_IOCFACTS_EXCEPT_SECURITY_KEY_LOCAL_VIA_MGMT (0x0100) #define MPI3_IOCFACTS_EXCEPT_SECURITY_KEY_EXT_VIA_MGMT (0x0200) @@ -149,6 +154,7 @@ struct mpi3_ioc_facts_data { #define MPI3_IOCFACTS_EXCEPT_BLOCKING_BOOT_EVENT (0x0004) #define MPI3_IOCFACTS_EXCEPT_SECURITY_SELFTEST_FAILURE (0x0002) #define MPI3_IOCFACTS_EXCEPT_BOOTSTAT_MASK (0x0001) +#define MPI3_IOCFACTS_EXCEPT_BOOTSTAT_SHIFT (0) #define MPI3_IOCFACTS_EXCEPT_BOOTSTAT_PRIMARY (0x0000) #define MPI3_IOCFACTS_EXCEPT_BOOTSTAT_SECONDARY (0x0001) #define MPI3_IOCFACTS_PROTOCOL_SAS (0x0010) @@ -161,10 +167,12 @@ struct mpi3_ioc_facts_data { #define MPI3_IOCFACTS_FLAGS_DMA_ADDRESS_WIDTH_MASK (0x0000ff00) #define MPI3_IOCFACTS_FLAGS_DMA_ADDRESS_WIDTH_SHIFT (8) #define MPI3_IOCFACTS_FLAGS_INITIAL_PORT_ENABLE_MASK (0x00000030) +#define MPI3_IOCFACTS_FLAGS_INITIAL_PORT_ENABLE_SHIFT (4) #define MPI3_IOCFACTS_FLAGS_INITIAL_PORT_ENABLE_NOT_STARTED (0x00000000) #define MPI3_IOCFACTS_FLAGS_INITIAL_PORT_ENABLE_IN_PROGRESS (0x00000010) #define MPI3_IOCFACTS_FLAGS_INITIAL_PORT_ENABLE_COMPLETE (0x00000020) #define MPI3_IOCFACTS_FLAGS_PERSONALITY_MASK (0x0000000f) +#define MPI3_IOCFACTS_FLAGS_PERSONALITY_SHIFT (0) #define MPI3_IOCFACTS_FLAGS_PERSONALITY_EHBA (0x00000000) #define MPI3_IOCFACTS_FLAGS_PERSONALITY_RAID_DDR (0x00000002) #define MPI3_IOCFACTS_IO_THROTTLE_DATA_LENGTH_NOT_REQUIRED (0x0000) @@ -204,6 +212,7 @@ struct mpi3_create_request_queue_request { }; #define MPI3_CREATE_REQUEST_QUEUE_FLAGS_SEGMENTED_MASK (0x80) +#define MPI3_CREATE_REQUEST_QUEUE_FLAGS_SEGMENTED_SHIFT (7) #define MPI3_CREATE_REQUEST_QUEUE_FLAGS_SEGMENTED_SEGMENTED (0x80) #define MPI3_CREATE_REQUEST_QUEUE_FLAGS_SEGMENTED_CONTIGUOUS (0x00) #define MPI3_CREATE_REQUEST_QUEUE_SIZE_MINIMUM (2) @@ -237,10 +246,12 @@ struct mpi3_create_reply_queue_request { }; #define MPI3_CREATE_REPLY_QUEUE_FLAGS_SEGMENTED_MASK (0x80) +#define MPI3_CREATE_REPLY_QUEUE_FLAGS_SEGMENTED_SHIFT (7) #define MPI3_CREATE_REPLY_QUEUE_FLAGS_SEGMENTED_SEGMENTED (0x80) #define MPI3_CREATE_REPLY_QUEUE_FLAGS_SEGMENTED_CONTIGUOUS (0x00) #define MPI3_CREATE_REPLY_QUEUE_FLAGS_COALESCE_DISABLE (0x02) #define MPI3_CREATE_REPLY_QUEUE_FLAGS_INT_ENABLE_MASK (0x01) +#define MPI3_CREATE_REPLY_QUEUE_FLAGS_INT_ENABLE_SHIFT (0) #define MPI3_CREATE_REPLY_QUEUE_FLAGS_INT_ENABLE_DISABLE (0x00) #define MPI3_CREATE_REPLY_QUEUE_FLAGS_INT_ENABLE_ENABLE (0x01) #define MPI3_CREATE_REPLY_QUEUE_SIZE_MINIMUM (2) @@ -326,9 +337,11 @@ struct mpi3_event_notification_reply { }; #define MPI3_EVENT_NOTIFY_MSGFLAGS_ACK_MASK (0x01) +#define MPI3_EVENT_NOTIFY_MSGFLAGS_ACK_SHIFT (0) #define MPI3_EVENT_NOTIFY_MSGFLAGS_ACK_REQUIRED (0x01) #define MPI3_EVENT_NOTIFY_MSGFLAGS_ACK_NOT_REQUIRED (0x00) #define MPI3_EVENT_NOTIFY_MSGFLAGS_EVENT_ORIGINALITY_MASK (0x02) +#define MPI3_EVENT_NOTIFY_MSGFLAGS_EVENT_ORIGINALITY_SHIFT (1) #define MPI3_EVENT_NOTIFY_MSGFLAGS_EVENT_ORIGINALITY_ORIGINAL (0x00) #define MPI3_EVENT_NOTIFY_MSGFLAGS_EVENT_ORIGINALITY_REPLAY (0x02) struct mpi3_event_data_gpio_interrupt { @@ -487,6 +500,7 @@ struct mpi3_event_sas_topo_phy_entry { #define MPI3_EVENT_SAS_TOPO_PHY_STATUS_NO_EXIST (0x40) #define MPI3_EVENT_SAS_TOPO_PHY_STATUS_VACANT (0x80) #define MPI3_EVENT_SAS_TOPO_PHY_RC_MASK (0x0f) +#define MPI3_EVENT_SAS_TOPO_PHY_RC_SHIFT (0) #define MPI3_EVENT_SAS_TOPO_PHY_RC_TARG_NOT_RESPONDING (0x02) #define MPI3_EVENT_SAS_TOPO_PHY_RC_PHY_CHANGED (0x03) #define MPI3_EVENT_SAS_TOPO_PHY_RC_NO_CHANGE (0x04) @@ -566,6 +580,7 @@ struct mpi3_event_pcie_topo_port_entry { #define MPI3_EVENT_PCIE_TOPO_PS_DELAY_NOT_RESPONDING (0x05) #define MPI3_EVENT_PCIE_TOPO_PS_RESPONDING (0x06) #define MPI3_EVENT_PCIE_TOPO_PI_LANES_MASK (0xf0) +#define MPI3_EVENT_PCIE_TOPO_PI_LANES_SHIFT (4) #define MPI3_EVENT_PCIE_TOPO_PI_LANES_UNKNOWN (0x00) #define MPI3_EVENT_PCIE_TOPO_PI_LANES_1 (0x10) #define MPI3_EVENT_PCIE_TOPO_PI_LANES_2 (0x20) @@ -573,6 +588,7 @@ struct mpi3_event_pcie_topo_port_entry { #define MPI3_EVENT_PCIE_TOPO_PI_LANES_8 (0x40) #define MPI3_EVENT_PCIE_TOPO_PI_LANES_16 (0x50) #define MPI3_EVENT_PCIE_TOPO_PI_RATE_MASK (0x0f) +#define MPI3_EVENT_PCIE_TOPO_PI_RATE_SHIFT (0) #define MPI3_EVENT_PCIE_TOPO_PI_RATE_UNKNOWN (0x00) #define MPI3_EVENT_PCIE_TOPO_PI_RATE_DISABLED (0x01) #define MPI3_EVENT_PCIE_TOPO_PI_RATE_2_5 (0x02) @@ -881,6 +897,7 @@ struct mpi3_pel_req_action_acknowledge { }; #define MPI3_PELACKNOWLEDGE_MSGFLAGS_SAFE_MODE_EXIT_MASK (0x03) +#define MPI3_PELACKNOWLEDGE_MSGFLAGS_SAFE_MODE_EXIT_SHIFT (0) #define MPI3_PELACKNOWLEDGE_MSGFLAGS_SAFE_MODE_EXIT_NO_GUIDANCE (0x00) #define MPI3_PELACKNOWLEDGE_MSGFLAGS_SAFE_MODE_EXIT_CONTINUE_OP (0x01) #define MPI3_PELACKNOWLEDGE_MSGFLAGS_SAFE_MODE_EXIT_TRANSITION_TO_FAULT (0x02) @@ -924,6 +941,7 @@ struct mpi3_ci_download_request { #define MPI3_CI_DOWNLOAD_MSGFLAGS_FORCE_FMC_ENABLE (0x40) #define MPI3_CI_DOWNLOAD_MSGFLAGS_SIGNED_NVDATA (0x20) #define MPI3_CI_DOWNLOAD_MSGFLAGS_WRITE_CACHE_FLUSH_MASK (0x03) +#define MPI3_CI_DOWNLOAD_MSGFLAGS_WRITE_CACHE_FLUSH_SHIFT (0) #define MPI3_CI_DOWNLOAD_MSGFLAGS_WRITE_CACHE_FLUSH_FAST (0x00) #define MPI3_CI_DOWNLOAD_MSGFLAGS_WRITE_CACHE_FLUSH_MEDIUM (0x01) #define MPI3_CI_DOWNLOAD_MSGFLAGS_WRITE_CACHE_FLUSH_SLOW (0x02) @@ -953,6 +971,7 @@ struct mpi3_ci_download_reply { #define MPI3_CI_DOWNLOAD_FLAGS_OFFLINE_ACTIVATION_REQUIRED (0x20) #define MPI3_CI_DOWNLOAD_FLAGS_KEY_UPDATE_PENDING (0x10) #define MPI3_CI_DOWNLOAD_FLAGS_ACTIVATION_STATUS_MASK (0x0e) +#define MPI3_CI_DOWNLOAD_FLAGS_ACTIVATION_STATUS_SHIFT (1) #define MPI3_CI_DOWNLOAD_FLAGS_ACTIVATION_STATUS_NOT_NEEDED (0x00) #define MPI3_CI_DOWNLOAD_FLAGS_ACTIVATION_STATUS_AWAITING (0x02) #define MPI3_CI_DOWNLOAD_FLAGS_ACTIVATION_STATUS_ONLINE_PENDING (0x04) @@ -976,9 +995,11 @@ struct mpi3_ci_upload_request { }; #define MPI3_CI_UPLOAD_MSGFLAGS_LOCATION_MASK (0x01) +#define MPI3_CI_UPLOAD_MSGFLAGS_LOCATION_SHIFT (0) #define MPI3_CI_UPLOAD_MSGFLAGS_LOCATION_PRIMARY (0x00) #define MPI3_CI_UPLOAD_MSGFLAGS_LOCATION_SECONDARY (0x01) #define MPI3_CI_UPLOAD_MSGFLAGS_FORMAT_MASK (0x02) +#define MPI3_CI_UPLOAD_MSGFLAGS_FORMAT_SHIFT (1) #define MPI3_CI_UPLOAD_MSGFLAGS_FORMAT_FLASH (0x00) #define MPI3_CI_UPLOAD_MSGFLAGS_FORMAT_EXECUTABLE (0x02) #define MPI3_CTRL_OP_FORCE_FULL_DISCOVERY (0x01) diff --git a/drivers/scsi/mpi3mr/mpi/mpi30_tool.h b/drivers/scsi/mpi3mr/mpi/mpi30_tool.h index 3b960893870f..50a65b16a818 100644 --- a/drivers/scsi/mpi3mr/mpi/mpi30_tool.h +++ b/drivers/scsi/mpi3mr/mpi/mpi30_tool.h @@ -9,6 +9,7 @@ #define MPI3_DIAG_BUFFER_TYPE_FW (0x02) #define MPI3_DIAG_BUFFER_ACTION_RELEASE (0x01) +#define MPI3_DIAG_BUFFER_POST_MSGFLAGS_SEGMENTED (0x01) struct mpi3_diag_buffer_post_request { __le16 host_tag; u8 ioc_use_only02; diff --git a/drivers/scsi/mpi3mr/mpi/mpi30_transport.h b/drivers/scsi/mpi3mr/mpi/mpi30_transport.h index b2ab25a1cfeb..5c522e2531c3 100644 --- a/drivers/scsi/mpi3mr/mpi/mpi30_transport.h +++ b/drivers/scsi/mpi3mr/mpi/mpi30_transport.h @@ -18,7 +18,7 @@ union mpi3_version_union { #define MPI3_VERSION_MAJOR (3) #define MPI3_VERSION_MINOR (0) -#define MPI3_VERSION_UNIT (34) +#define MPI3_VERSION_UNIT (35) #define MPI3_VERSION_DEV (0) #define MPI3_DEVHANDLE_INVALID (0xffff) struct mpi3_sysif_oper_queue_indexes { @@ -80,6 +80,7 @@ struct mpi3_sysif_registers { #define MPI3_SYSIF_IOC_CONFIG_OPER_RPY_ENT_SZ_SHIFT (20) #define MPI3_SYSIF_IOC_CONFIG_OPER_REQ_ENT_SZ (0x000f0000) #define MPI3_SYSIF_IOC_CONFIG_OPER_REQ_ENT_SZ_SHIFT (16) +#define MPI3_SYSIF_IOC_CONFIG_SHUTDOWN_SHIFT (14) #define MPI3_SYSIF_IOC_CONFIG_SHUTDOWN_MASK (0x0000c000) #define MPI3_SYSIF_IOC_CONFIG_SHUTDOWN_NO (0x00000000) #define MPI3_SYSIF_IOC_CONFIG_SHUTDOWN_NORMAL (0x00004000) @@ -97,6 +98,7 @@ struct mpi3_sysif_registers { #define MPI3_SYSIF_IOC_STATUS_READY (0x00000001) #define MPI3_SYSIF_ADMIN_Q_NUM_ENTRIES_OFFSET (0x00000024) #define MPI3_SYSIF_ADMIN_Q_NUM_ENTRIES_REQ_MASK (0x0fff) +#define MPI3_SYSIF_ADMIN_Q_NUM_ENTRIES_REQ_SHIFT (0) #define MPI3_SYSIF_ADMIN_Q_NUM_ENTRIES_REPLY_OFFSET (0x00000026) #define MPI3_SYSIF_ADMIN_Q_NUM_ENTRIES_REPLY_MASK (0x0fff0000) #define MPI3_SYSIF_ADMIN_Q_NUM_ENTRIES_REPLY_SHIFT (16) @@ -106,6 +108,7 @@ struct mpi3_sysif_registers { #define MPI3_SYSIF_ADMIN_REPLY_Q_ADDR_HIGH_OFFSET (0x00000034) #define MPI3_SYSIF_COALESCE_CONTROL_OFFSET (0x00000040) #define MPI3_SYSIF_COALESCE_CONTROL_ENABLE_MASK (0xc0000000) +#define MPI3_SYSIF_COALESCE_CONTROL_ENABLE_SHIFT (30) #define MPI3_SYSIF_COALESCE_CONTROL_ENABLE_NO_CHANGE (0x00000000) #define MPI3_SYSIF_COALESCE_CONTROL_ENABLE_DISABLE (0x40000000) #define MPI3_SYSIF_COALESCE_CONTROL_ENABLE_ENABLE (0xc0000000) @@ -124,6 +127,7 @@ struct mpi3_sysif_registers { #define MPI3_SYSIF_OPER_REPLY_Q_N_CI_OFFSET(N) (MPI3_SYSIF_OPER_REPLY_Q_CI_OFFSET + (((N) - 1) * 8)) #define MPI3_SYSIF_WRITE_SEQUENCE_OFFSET (0x00001c04) #define MPI3_SYSIF_WRITE_SEQUENCE_KEY_VALUE_MASK (0x0000000f) +#define MPI3_SYSIF_WRITE_SEQUENCE_KEY_VALUE_SHIFT (0) #define MPI3_SYSIF_WRITE_SEQUENCE_KEY_VALUE_FLUSH (0x0) #define MPI3_SYSIF_WRITE_SEQUENCE_KEY_VALUE_1ST (0xf) #define MPI3_SYSIF_WRITE_SEQUENCE_KEY_VALUE_2ND (0x4) @@ -133,6 +137,7 @@ struct mpi3_sysif_registers { #define MPI3_SYSIF_WRITE_SEQUENCE_KEY_VALUE_6TH (0xd) #define MPI3_SYSIF_HOST_DIAG_OFFSET (0x00001c08) #define MPI3_SYSIF_HOST_DIAG_RESET_ACTION_MASK (0x00000700) +#define MPI3_SYSIF_HOST_DIAG_RESET_ACTION_SHIFT (8) #define MPI3_SYSIF_HOST_DIAG_RESET_ACTION_NO_RESET (0x00000000) #define MPI3_SYSIF_HOST_DIAG_RESET_ACTION_SOFT_RESET (0x00000100) #define MPI3_SYSIF_HOST_DIAG_RESET_ACTION_HOST_CONTROL_BOOT_RESET (0x00000200) @@ -151,6 +156,7 @@ struct mpi3_sysif_registers { #define MPI3_SYSIF_FAULT_FUNC_AREA_SHIFT (24) #define MPI3_SYSIF_FAULT_FUNC_AREA_MPI_DEFINED (0x00000000) #define MPI3_SYSIF_FAULT_CODE_MASK (0x0000ffff) +#define MPI3_SYSIF_FAULT_CODE_SHIFT (0) #define MPI3_SYSIF_FAULT_CODE_DIAG_FAULT_RESET (0x0000f000) #define MPI3_SYSIF_FAULT_CODE_CI_ACTIVATION_RESET (0x0000f001) #define MPI3_SYSIF_FAULT_CODE_SOFT_RESET_IN_PROGRESS (0x0000f002) @@ -176,17 +182,20 @@ struct mpi3_sysif_registers { #define MPI3_SYSIF_DIAG_RW_ADDRESS_HIGH_OFFSET (0x00001c5c) #define MPI3_SYSIF_DIAG_RW_CONTROL_OFFSET (0x00001c60) #define MPI3_SYSIF_DIAG_RW_CONTROL_LEN_MASK (0x00000030) +#define MPI3_SYSIF_DIAG_RW_CONTROL_LEN_SHIFT (4) #define MPI3_SYSIF_DIAG_RW_CONTROL_LEN_1BYTE (0x00000000) #define MPI3_SYSIF_DIAG_RW_CONTROL_LEN_2BYTES (0x00000010) #define MPI3_SYSIF_DIAG_RW_CONTROL_LEN_4BYTES (0x00000020) #define MPI3_SYSIF_DIAG_RW_CONTROL_LEN_8BYTES (0x00000030) #define MPI3_SYSIF_DIAG_RW_CONTROL_RESET (0x00000004) #define MPI3_SYSIF_DIAG_RW_CONTROL_DIR_MASK (0x00000002) +#define MPI3_SYSIF_DIAG_RW_CONTROL_DIR_SHIFT (1) #define MPI3_SYSIF_DIAG_RW_CONTROL_DIR_READ (0x00000000) #define MPI3_SYSIF_DIAG_RW_CONTROL_DIR_WRITE (0x00000002) #define MPI3_SYSIF_DIAG_RW_CONTROL_START (0x00000001) #define MPI3_SYSIF_DIAG_RW_STATUS_OFFSET (0x00001c62) #define MPI3_SYSIF_DIAG_RW_STATUS_STATUS_MASK (0x0000000e) +#define MPI3_SYSIF_DIAG_RW_STATUS_STATUS_SHIFT (1) #define MPI3_SYSIF_DIAG_RW_STATUS_STATUS_SUCCESS (0x00000000) #define MPI3_SYSIF_DIAG_RW_STATUS_STATUS_INV_ADDR (0x00000002) #define MPI3_SYSIF_DIAG_RW_STATUS_STATUS_ACC_ERR (0x00000004) @@ -207,7 +216,9 @@ struct mpi3_default_reply_descriptor { }; #define MPI3_REPLY_DESCRIPT_FLAGS_PHASE_MASK (0x0001) +#define MPI3_REPLY_DESCRIPT_FLAGS_PHASE_SHIFT (0) #define MPI3_REPLY_DESCRIPT_FLAGS_TYPE_MASK (0xf000) +#define MPI3_REPLY_DESCRIPT_FLAGS_TYPE_SHIFT (12) #define MPI3_REPLY_DESCRIPT_FLAGS_TYPE_ADDRESS_REPLY (0x0000) #define MPI3_REPLY_DESCRIPT_FLAGS_TYPE_SUCCESS (0x1000) #define MPI3_REPLY_DESCRIPT_FLAGS_TYPE_TARGET_COMMAND_BUFFER (0x2000) @@ -301,6 +312,7 @@ union mpi3_sge_union { }; #define MPI3_SGE_FLAGS_ELEMENT_TYPE_MASK (0xf0) +#define MPI3_SGE_FLAGS_ELEMENT_TYPE_SHIFT (4) #define MPI3_SGE_FLAGS_ELEMENT_TYPE_SIMPLE (0x00) #define MPI3_SGE_FLAGS_ELEMENT_TYPE_BIT_BUCKET (0x10) #define MPI3_SGE_FLAGS_ELEMENT_TYPE_CHAIN (0x20) @@ -309,6 +321,7 @@ union mpi3_sge_union { #define MPI3_SGE_FLAGS_END_OF_LIST (0x08) #define MPI3_SGE_FLAGS_END_OF_BUFFER (0x04) #define MPI3_SGE_FLAGS_DLAS_MASK (0x03) +#define MPI3_SGE_FLAGS_DLAS_SHIFT (0) #define MPI3_SGE_FLAGS_DLAS_SYSTEM (0x00) #define MPI3_SGE_FLAGS_DLAS_IOC_UDP (0x01) #define MPI3_SGE_FLAGS_DLAS_IOC_CTL (0x02) @@ -322,15 +335,18 @@ union mpi3_sge_union { #define MPI3_EEDPFLAGS_CHK_APP_TAG (0x0200) #define MPI3_EEDPFLAGS_CHK_GUARD (0x0100) #define MPI3_EEDPFLAGS_ESC_MODE_MASK (0x00c0) +#define MPI3_EEDPFLAGS_ESC_MODE_SHIFT (6) #define MPI3_EEDPFLAGS_ESC_MODE_DO_NOT_DISABLE (0x0040) #define MPI3_EEDPFLAGS_ESC_MODE_APPTAG_DISABLE (0x0080) #define MPI3_EEDPFLAGS_ESC_MODE_APPTAG_REFTAG_DISABLE (0x00c0) #define MPI3_EEDPFLAGS_HOST_GUARD_MASK (0x0030) +#define MPI3_EEDPFLAGS_HOST_GUARD_SHIFT (4) #define MPI3_EEDPFLAGS_HOST_GUARD_T10_CRC (0x0000) #define MPI3_EEDPFLAGS_HOST_GUARD_IP_CHKSUM (0x0010) #define MPI3_EEDPFLAGS_HOST_GUARD_OEM_SPECIFIC (0x0020) #define MPI3_EEDPFLAGS_PT_REF_TAG (0x0008) #define MPI3_EEDPFLAGS_EEDP_OP_MASK (0x0007) +#define MPI3_EEDPFLAGS_EEDP_OP_SHIFT (0) #define MPI3_EEDPFLAGS_EEDP_OP_CHECK (0x0001) #define MPI3_EEDPFLAGS_EEDP_OP_STRIP (0x0002) #define MPI3_EEDPFLAGS_EEDP_OP_CHECK_REMOVE (0x0003) @@ -403,6 +419,7 @@ struct mpi3_default_reply { #define MPI3_IOCSTATUS_LOG_INFO_AVAIL_MASK (0x8000) #define MPI3_IOCSTATUS_LOG_INFO_AVAILABLE (0x8000) #define MPI3_IOCSTATUS_STATUS_MASK (0x7fff) +#define MPI3_IOCSTATUS_STATUS_SHIFT (0) #define MPI3_IOCSTATUS_SUCCESS (0x0000) #define MPI3_IOCSTATUS_INVALID_FUNCTION (0x0001) #define MPI3_IOCSTATUS_BUSY (0x0002) @@ -469,4 +486,5 @@ struct mpi3_default_reply { #define MPI3_IOCLOGINFO_TYPE_NONE (0x0) #define MPI3_IOCLOGINFO_TYPE_SAS (0x3) #define MPI3_IOCLOGINFO_LOG_DATA_MASK (0x0fffffff) +#define MPI3_IOCLOGINFO_LOG_DATA_SHIFT (0) #endif diff --git a/drivers/scsi/mpi3mr/mpi3mr.h b/drivers/scsi/mpi3mr/mpi3mr.h index 0d72b5f1b69d..9bbc7cb98ca3 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.12.0.3.50" -#define MPI3MR_DRIVER_RELDATE "11-November-2024" +#define MPI3MR_DRIVER_VERSION "8.13.0.5.50" +#define MPI3MR_DRIVER_RELDATE "20-February-2025" #define MPI3MR_DRIVER_NAME "mpi3mr" #define MPI3MR_DRIVER_LICENSE "GPL" @@ -80,13 +80,14 @@ extern atomic64_t event_counter; /* Admin queue management definitions */ #define MPI3MR_ADMIN_REQ_Q_SIZE (2 * MPI3MR_PAGE_SIZE_4K) -#define MPI3MR_ADMIN_REPLY_Q_SIZE (4 * MPI3MR_PAGE_SIZE_4K) +#define MPI3MR_ADMIN_REPLY_Q_SIZE (8 * MPI3MR_PAGE_SIZE_4K) #define MPI3MR_ADMIN_REQ_FRAME_SZ 128 #define MPI3MR_ADMIN_REPLY_FRAME_SZ 16 /* Operational queue management definitions */ #define MPI3MR_OP_REQ_Q_QD 512 #define MPI3MR_OP_REP_Q_QD 1024 +#define MPI3MR_OP_REP_Q_QD2K 2048 #define MPI3MR_OP_REP_Q_QD4K 4096 #define MPI3MR_OP_REQ_Q_SEG_SIZE 4096 #define MPI3MR_OP_REP_Q_SEG_SIZE 4096 @@ -328,6 +329,7 @@ enum mpi3mr_reset_reason { #define MPI3MR_RESET_REASON_OSTYPE_SHIFT 28 #define MPI3MR_RESET_REASON_IOCNUM_SHIFT 20 + /* Queue type definitions */ enum queue_type { MPI3MR_DEFAULT_QUEUE = 0, @@ -387,6 +389,7 @@ struct mpi3mr_ioc_facts { u16 max_msix_vectors; u8 personality; u8 dma_mask; + bool max_req_limit; u8 protocol_flags; u8 sge_mod_mask; u8 sge_mod_value; @@ -456,6 +459,8 @@ struct op_req_qinfo { * @enable_irq_poll: Flag to indicate polling is enabled * @in_use: Queue is handled by poll/ISR * @qtype: Type of queue (types defined in enum queue_type) + * @qfull_watermark: Watermark defined in reply queue to avoid + * reply queue full */ struct op_reply_qinfo { u16 ci; @@ -471,6 +476,7 @@ struct op_reply_qinfo { bool enable_irq_poll; atomic_t in_use; enum queue_type qtype; + u16 qfull_watermark; }; /** @@ -928,6 +934,8 @@ struct trigger_event_data { * @size: Buffer size * @addr: Virtual address * @dma_addr: Buffer DMA address + * @is_segmented: The buffer is segmented or not + * @disabled_after_reset: The buffer is disabled after reset */ struct diag_buffer_desc { u8 type; @@ -937,6 +945,8 @@ struct diag_buffer_desc { u32 size; void *addr; dma_addr_t dma_addr; + bool is_segmented; + bool disabled_after_reset; }; /** @@ -1022,6 +1032,8 @@ struct scmd_priv { * @admin_reply_base: Admin reply queue base virtual address * @admin_reply_dma: Admin reply queue base dma address * @admin_reply_q_in_use: Queue is handled by poll/ISR + * @admin_pend_isr: Count of unprocessed admin ISR/poll calls + * due to another thread processing replies * @ready_timeout: Controller ready timeout * @intr_info: Interrupt cookie pointer * @intr_info_count: Number of interrupt cookies @@ -1090,6 +1102,7 @@ struct scmd_priv { * @ts_update_interval: Timestamp update interval * @reset_in_progress: Reset in progress flag * @unrecoverable: Controller unrecoverable flag + * @io_admin_reset_sync: Manage state of I/O ops during an admin reset process * @prev_reset_result: Result of previous reset * @reset_mutex: Controller reset mutex * @reset_waitq: Controller reset wait queue @@ -1153,6 +1166,12 @@ struct scmd_priv { * @snapdump_trigger_active: Snapdump trigger active flag * @pci_err_recovery: PCI error recovery in progress * @block_on_pci_err: Block IO during PCI error recovery + * @reply_qfull_count: Occurences of reply queue full avoidance kicking-in + * @prevent_reply_qfull: Enable reply queue prevention + * @seg_tb_support: Segmented trace buffer support + * @num_tb_segs: Number of Segments in Trace buffer + * @trace_buf_pool: DMA pool for Segmented trace buffer segments + * @trace_buf: Trace buffer segments memory descriptor */ struct mpi3mr_ioc { struct list_head list; @@ -1189,6 +1208,7 @@ struct mpi3mr_ioc { void *admin_reply_base; dma_addr_t admin_reply_dma; atomic_t admin_reply_q_in_use; + atomic_t admin_pend_isr; u32 ready_timeout; @@ -1276,6 +1296,7 @@ struct mpi3mr_ioc { u16 ts_update_interval; u8 reset_in_progress; u8 unrecoverable; + u8 io_admin_reset_sync; int prev_reset_result; struct mutex reset_mutex; wait_queue_head_t reset_waitq; @@ -1351,6 +1372,13 @@ struct mpi3mr_ioc { bool fw_release_trigger_active; bool pci_err_recovery; bool block_on_pci_err; + atomic_t reply_qfull_count; + bool prevent_reply_qfull; + bool seg_tb_support; + u32 num_tb_segs; + struct dma_pool *trace_buf_pool; + struct segments *trace_buf; + }; /** diff --git a/drivers/scsi/mpi3mr/mpi3mr_app.c b/drivers/scsi/mpi3mr/mpi3mr_app.c index 7589f48aebc8..f36663613950 100644 --- a/drivers/scsi/mpi3mr/mpi3mr_app.c +++ b/drivers/scsi/mpi3mr/mpi3mr_app.c @@ -12,23 +12,98 @@ #include <uapi/scsi/scsi_bsg_mpi3mr.h> /** - * mpi3mr_alloc_trace_buffer: Allocate trace buffer + * mpi3mr_alloc_trace_buffer: Allocate segmented trace buffer * @mrioc: Adapter instance reference * @trace_size: Trace buffer size * - * Allocate trace buffer + * Allocate either segmented memory pools or contiguous buffer + * based on the controller capability for the host trace + * buffer. + * * Return: 0 on success, non-zero on failure. */ static int mpi3mr_alloc_trace_buffer(struct mpi3mr_ioc *mrioc, u32 trace_size) { struct diag_buffer_desc *diag_buffer = &mrioc->diag_buffers[0]; + int i, sz; + u64 *diag_buffer_list = NULL; + dma_addr_t diag_buffer_list_dma; + u32 seg_count; + + if (mrioc->seg_tb_support) { + seg_count = (trace_size) / MPI3MR_PAGE_SIZE_4K; + trace_size = seg_count * MPI3MR_PAGE_SIZE_4K; + + diag_buffer_list = dma_alloc_coherent(&mrioc->pdev->dev, + sizeof(u64) * seg_count, + &diag_buffer_list_dma, GFP_KERNEL); + if (!diag_buffer_list) + return -1; + + mrioc->num_tb_segs = seg_count; + + sz = sizeof(struct segments) * seg_count; + mrioc->trace_buf = kzalloc(sz, GFP_KERNEL); + if (!mrioc->trace_buf) + goto trace_buf_failed; + + mrioc->trace_buf_pool = dma_pool_create("trace_buf pool", + &mrioc->pdev->dev, MPI3MR_PAGE_SIZE_4K, MPI3MR_PAGE_SIZE_4K, + 0); + if (!mrioc->trace_buf_pool) { + ioc_err(mrioc, "trace buf pool: dma_pool_create failed\n"); + goto trace_buf_pool_failed; + } - diag_buffer->addr = dma_alloc_coherent(&mrioc->pdev->dev, - trace_size, &diag_buffer->dma_addr, GFP_KERNEL); - if (diag_buffer->addr) { - dprint_init(mrioc, "trace diag buffer is allocated successfully\n"); + for (i = 0; i < seg_count; i++) { + mrioc->trace_buf[i].segment = + dma_pool_zalloc(mrioc->trace_buf_pool, GFP_KERNEL, + &mrioc->trace_buf[i].segment_dma); + diag_buffer_list[i] = + (u64) mrioc->trace_buf[i].segment_dma; + if (!diag_buffer_list[i]) + goto tb_seg_alloc_failed; + } + + diag_buffer->addr = diag_buffer_list; + diag_buffer->dma_addr = diag_buffer_list_dma; + diag_buffer->is_segmented = true; + + dprint_init(mrioc, "segmented trace diag buffer\n" + "is allocated successfully seg_count:%d\n", seg_count); return 0; + } else { + diag_buffer->addr = dma_alloc_coherent(&mrioc->pdev->dev, + trace_size, &diag_buffer->dma_addr, GFP_KERNEL); + if (diag_buffer->addr) { + dprint_init(mrioc, "trace diag buffer is allocated successfully\n"); + return 0; + } + return -1; } + +tb_seg_alloc_failed: + if (mrioc->trace_buf_pool) { + for (i = 0; i < mrioc->num_tb_segs; i++) { + if (mrioc->trace_buf[i].segment) { + dma_pool_free(mrioc->trace_buf_pool, + mrioc->trace_buf[i].segment, + mrioc->trace_buf[i].segment_dma); + mrioc->trace_buf[i].segment = NULL; + } + mrioc->trace_buf[i].segment = NULL; + } + dma_pool_destroy(mrioc->trace_buf_pool); + mrioc->trace_buf_pool = NULL; + } +trace_buf_pool_failed: + kfree(mrioc->trace_buf); + mrioc->trace_buf = NULL; +trace_buf_failed: + if (diag_buffer_list) + dma_free_coherent(&mrioc->pdev->dev, + sizeof(u64) * mrioc->num_tb_segs, + diag_buffer_list, diag_buffer_list_dma); return -1; } @@ -100,8 +175,9 @@ retry_trace: dprint_init(mrioc, "trying to allocate trace diag buffer of size = %dKB\n", trace_size / 1024); - if (get_order(trace_size) > MAX_PAGE_ORDER || + if ((!mrioc->seg_tb_support && (get_order(trace_size) > MAX_PAGE_ORDER)) || mpi3mr_alloc_trace_buffer(mrioc, trace_size)) { + retry = true; trace_size -= trace_dec_size; dprint_init(mrioc, "trace diag buffer allocation failed\n" @@ -161,6 +237,12 @@ int mpi3mr_issue_diag_buf_post(struct mpi3mr_ioc *mrioc, u8 prev_status; int retval = 0; + if (diag_buffer->disabled_after_reset) { + dprint_bsg_err(mrioc, "%s: skipping diag buffer posting\n" + "as it is disabled after reset\n", __func__); + return -1; + } + memset(&diag_buf_post_req, 0, sizeof(diag_buf_post_req)); mutex_lock(&mrioc->init_cmds.mutex); if (mrioc->init_cmds.state & MPI3MR_CMD_PENDING) { @@ -177,8 +259,12 @@ int mpi3mr_issue_diag_buf_post(struct mpi3mr_ioc *mrioc, diag_buf_post_req.address = le64_to_cpu(diag_buffer->dma_addr); diag_buf_post_req.length = le32_to_cpu(diag_buffer->size); - dprint_bsg_info(mrioc, "%s: posting diag buffer type %d\n", __func__, - diag_buffer->type); + if (diag_buffer->is_segmented) + diag_buf_post_req.msg_flags |= MPI3_DIAG_BUFFER_POST_MSGFLAGS_SEGMENTED; + + dprint_bsg_info(mrioc, "%s: posting diag buffer type %d segmented:%d\n", __func__, + diag_buffer->type, diag_buffer->is_segmented); + prev_status = diag_buffer->status; diag_buffer->status = MPI3MR_HDB_BUFSTATUS_POSTED_UNPAUSED; init_completion(&mrioc->init_cmds.done); @@ -2339,6 +2425,7 @@ static long mpi3mr_bsg_process_mpt_cmds(struct bsg_job *job) } if (!mrioc->ioctl_sges_allocated) { + mutex_unlock(&mrioc->bsg_cmds.mutex); dprint_bsg_err(mrioc, "%s: DMA memory was not allocated\n", __func__); return -ENOMEM; @@ -3061,6 +3148,29 @@ reply_queue_count_show(struct device *dev, struct device_attribute *attr, static DEVICE_ATTR_RO(reply_queue_count); /** + * reply_qfull_count_show - Show reply qfull count + * @dev: class device + * @attr: Device attributes + * @buf: Buffer to copy + * + * Retrieves the current value of the reply_qfull_count from the mrioc structure and + * formats it as a string for display. + * + * Return: sysfs_emit() return + */ +static ssize_t +reply_qfull_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 sysfs_emit(buf, "%u\n", atomic_read(&mrioc->reply_qfull_count)); +} + +static DEVICE_ATTR_RO(reply_qfull_count); + +/** * logging_level_show - Show controller debug level * @dev: class device * @attr: Device attributes @@ -3152,6 +3262,7 @@ static struct attribute *mpi3mr_host_attrs[] = { &dev_attr_fw_queue_depth.attr, &dev_attr_op_req_q_count.attr, &dev_attr_reply_queue_count.attr, + &dev_attr_reply_qfull_count.attr, &dev_attr_logging_level.attr, &dev_attr_adp_state.attr, NULL, diff --git a/drivers/scsi/mpi3mr/mpi3mr_fw.c b/drivers/scsi/mpi3mr/mpi3mr_fw.c index 5ed31fe57474..3fcb1ad3b070 100644 --- a/drivers/scsi/mpi3mr/mpi3mr_fw.c +++ b/drivers/scsi/mpi3mr/mpi3mr_fw.c @@ -17,7 +17,7 @@ static void mpi3mr_process_factsdata(struct mpi3mr_ioc *mrioc, struct mpi3_ioc_facts_data *facts_data); static void mpi3mr_pel_wait_complete(struct mpi3mr_ioc *mrioc, struct mpi3mr_drv_cmd *drv_cmd); - +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)"); @@ -446,8 +446,10 @@ int mpi3mr_process_admin_reply_q(struct mpi3mr_ioc *mrioc) u16 threshold_comps = 0; struct mpi3_default_reply_descriptor *reply_desc; - if (!atomic_add_unless(&mrioc->admin_reply_q_in_use, 1, 1)) + if (!atomic_add_unless(&mrioc->admin_reply_q_in_use, 1, 1)) { + atomic_inc(&mrioc->admin_pend_isr); return 0; + } reply_desc = (struct mpi3_default_reply_descriptor *)mrioc->admin_reply_base + admin_reply_ci; @@ -459,7 +461,7 @@ int mpi3mr_process_admin_reply_q(struct mpi3mr_ioc *mrioc) } do { - if (mrioc->unrecoverable) + if (mrioc->unrecoverable || mrioc->io_admin_reset_sync) break; mrioc->admin_req_ci = le16_to_cpu(reply_desc->request_queue_ci); @@ -554,7 +556,7 @@ int mpi3mr_process_op_reply_q(struct mpi3mr_ioc *mrioc, } do { - if (mrioc->unrecoverable) + if (mrioc->unrecoverable || mrioc->io_admin_reset_sync) break; req_q_idx = le16_to_cpu(reply_desc->request_queue_id) - 1; @@ -1302,7 +1304,7 @@ static int mpi3mr_issue_and_process_mur(struct mpi3mr_ioc *mrioc, (ioc_config & MPI3_SYSIF_IOC_CONFIG_ENABLE_IOC))) retval = 0; - ioc_info(mrioc, "Base IOC Sts/Config after %s MUR is (0x%x)/(0x%x)\n", + ioc_info(mrioc, "Base IOC Sts/Config after %s MUR is (0x%08x)/(0x%08x)\n", (!retval) ? "successful" : "failed", ioc_status, ioc_config); return retval; } @@ -1355,6 +1357,19 @@ mpi3mr_revalidate_factsdata(struct mpi3mr_ioc *mrioc) "\tcontroller while sas transport support is enabled at the\n" "\tdriver, please reboot the system or reload the driver\n"); + if (mrioc->seg_tb_support) { + if (!(mrioc->facts.ioc_capabilities & + MPI3_IOCFACTS_CAPABILITY_SEG_DIAG_TRACE_SUPPORTED)) { + ioc_err(mrioc, + "critical error: previously enabled segmented trace\n" + " buffer capability is disabled after reset. Please\n" + " update the firmware or reboot the system or\n" + " reload the driver to enable trace diag buffer\n"); + mrioc->diag_buffers[0].disabled_after_reset = true; + } else + mrioc->diag_buffers[0].disabled_after_reset = false; + } + if (mrioc->facts.max_devhandle > mrioc->dev_handle_bitmap_bits) { removepend_bitmap = bitmap_zalloc(mrioc->facts.max_devhandle, GFP_KERNEL); @@ -1717,7 +1732,7 @@ static int mpi3mr_issue_reset(struct mpi3mr_ioc *mrioc, u16 reset_type, ioc_config = readl(&mrioc->sysif_regs->ioc_configuration); ioc_status = readl(&mrioc->sysif_regs->ioc_status); ioc_info(mrioc, - "ioc_status/ioc_onfig after %s reset is (0x%x)/(0x%x)\n", + "ioc_status/ioc_config after %s reset is (0x%08x)/(0x%08x)\n", (!retval)?"successful":"failed", ioc_status, ioc_config); if (retval) @@ -2104,15 +2119,22 @@ static int mpi3mr_create_op_reply_q(struct mpi3mr_ioc *mrioc, u16 qidx) } reply_qid = qidx + 1; - op_reply_q->num_replies = MPI3MR_OP_REP_Q_QD; - if ((mrioc->pdev->device == MPI3_MFGPAGE_DEVID_SAS4116) && - !mrioc->pdev->revision) - op_reply_q->num_replies = MPI3MR_OP_REP_Q_QD4K; + + if (mrioc->pdev->device == MPI3_MFGPAGE_DEVID_SAS4116) { + if (mrioc->pdev->revision) + op_reply_q->num_replies = MPI3MR_OP_REP_Q_QD; + else + op_reply_q->num_replies = MPI3MR_OP_REP_Q_QD4K; + } else + op_reply_q->num_replies = MPI3MR_OP_REP_Q_QD2K; + op_reply_q->ci = 0; op_reply_q->ephase = 1; atomic_set(&op_reply_q->pend_ios, 0); atomic_set(&op_reply_q->in_use, 0); op_reply_q->enable_irq_poll = false; + op_reply_q->qfull_watermark = + op_reply_q->num_replies - (MPI3MR_THRESHOLD_REPLY_COUNT * 2); if (!op_reply_q->q_segments) { retval = mpi3mr_alloc_op_reply_q_segments(mrioc, qidx); @@ -2416,8 +2438,10 @@ int mpi3mr_op_request_post(struct mpi3mr_ioc *mrioc, void *segment_base_addr; u16 req_sz = mrioc->facts.op_req_sz; struct segments *segments = op_req_q->q_segments; + struct op_reply_qinfo *op_reply_q = NULL; reply_qidx = op_req_q->reply_qid - 1; + op_reply_q = mrioc->op_reply_qinfo + reply_qidx; if (mrioc->unrecoverable) return -EFAULT; @@ -2448,6 +2472,15 @@ int mpi3mr_op_request_post(struct mpi3mr_ioc *mrioc, goto out; } + /* Reply queue is nearing to get full, push back IOs to SML */ + if ((mrioc->prevent_reply_qfull == true) && + (atomic_read(&op_reply_q->pend_ios) > + (op_reply_q->qfull_watermark))) { + atomic_inc(&mrioc->reply_qfull_count); + retval = -EAGAIN; + goto out; + } + segment_base_addr = segments[pi / op_req_q->segment_qd].segment; req_entry = (u8 *)segment_base_addr + ((pi % op_req_q->segment_qd) * req_sz); @@ -2726,7 +2759,16 @@ static void mpi3mr_watchdog_work(struct work_struct *work) return; } - if (mrioc->ts_update_counter++ >= mrioc->ts_update_interval) { + if (atomic_read(&mrioc->admin_pend_isr)) { + ioc_err(mrioc, "Unprocessed admin ISR instance found\n" + "flush admin replies\n"); + mpi3mr_process_admin_reply_q(mrioc); + } + + if (!(mrioc->facts.ioc_capabilities & + MPI3_IOCFACTS_CAPABILITY_NON_SUPERVISOR_IOC) && + (mrioc->ts_update_counter++ >= mrioc->ts_update_interval)) { + mrioc->ts_update_counter = 0; mpi3mr_sync_timestamp(mrioc); } @@ -3091,6 +3133,9 @@ static void mpi3mr_process_factsdata(struct mpi3mr_ioc *mrioc, mrioc->facts.dma_mask = (facts_flags & MPI3_IOCFACTS_FLAGS_DMA_ADDRESS_WIDTH_MASK) >> MPI3_IOCFACTS_FLAGS_DMA_ADDRESS_WIDTH_SHIFT; + mrioc->facts.dma_mask = (facts_flags & + MPI3_IOCFACTS_FLAGS_DMA_ADDRESS_WIDTH_MASK) >> + MPI3_IOCFACTS_FLAGS_DMA_ADDRESS_WIDTH_SHIFT; mrioc->facts.protocol_flags = facts_data->protocol_flags; mrioc->facts.mpi_version = le32_to_cpu(facts_data->mpi_version.word); mrioc->facts.max_reqs = le16_to_cpu(facts_data->max_outstanding_requests); @@ -4214,6 +4259,13 @@ retry_init: mrioc->shost->transportt = mpi3mr_transport_template; } + if (mrioc->facts.max_req_limit) + mrioc->prevent_reply_qfull = true; + + if (mrioc->facts.ioc_capabilities & + MPI3_IOCFACTS_CAPABILITY_SEG_DIAG_TRACE_SUPPORTED) + mrioc->seg_tb_support = true; + mrioc->reply_sz = mrioc->facts.reply_sz; retval = mpi3mr_check_reset_dma_mask(mrioc); @@ -4370,6 +4422,7 @@ retry_init: goto out_failed_noretry; } + mrioc->io_admin_reset_sync = 0; if (is_resume || mrioc->block_on_pci_err) { dprint_reset(mrioc, "setting up single ISR\n"); retval = mpi3mr_setup_isr(mrioc, 1); @@ -4671,7 +4724,7 @@ void mpi3mr_memset_buffers(struct mpi3mr_ioc *mrioc) */ void mpi3mr_free_mem(struct mpi3mr_ioc *mrioc) { - u16 i; + u16 i, j; struct mpi3mr_intr_info *intr_info; struct diag_buffer_desc *diag_buffer; @@ -4806,6 +4859,26 @@ void mpi3mr_free_mem(struct mpi3mr_ioc *mrioc) for (i = 0; i < MPI3MR_MAX_NUM_HDB; i++) { diag_buffer = &mrioc->diag_buffers[i]; + if ((i == 0) && mrioc->seg_tb_support) { + if (mrioc->trace_buf_pool) { + for (j = 0; j < mrioc->num_tb_segs; j++) { + if (mrioc->trace_buf[j].segment) { + dma_pool_free(mrioc->trace_buf_pool, + mrioc->trace_buf[j].segment, + mrioc->trace_buf[j].segment_dma); + mrioc->trace_buf[j].segment = NULL; + } + + mrioc->trace_buf[j].segment = NULL; + } + dma_pool_destroy(mrioc->trace_buf_pool); + mrioc->trace_buf_pool = NULL; + } + + kfree(mrioc->trace_buf); + mrioc->trace_buf = NULL; + diag_buffer->size = sizeof(u64) * mrioc->num_tb_segs; + } if (diag_buffer->addr) { dma_free_coherent(&mrioc->pdev->dev, diag_buffer->size, diag_buffer->addr, @@ -4883,7 +4956,7 @@ static void mpi3mr_issue_ioc_shutdown(struct mpi3mr_ioc *mrioc) } ioc_info(mrioc, - "Base IOC Sts/Config after %s shutdown is (0x%x)/(0x%x)\n", + "Base IOC Sts/Config after %s shutdown is (0x%08x)/(0x%08x)\n", (!retval) ? "successful" : "failed", ioc_status, ioc_config); } @@ -5229,6 +5302,55 @@ cleanup_drv_cmd: } /** + * mpi3mr_check_op_admin_proc - + * @mrioc: Adapter instance reference + * + * Check if any of the operation reply queues + * or the admin reply queue are currently in use. + * If any queue is in use, this function waits for + * a maximum of 10 seconds for them to become available. + * + * Return: 0 on success, non-zero on failure. + */ +static int mpi3mr_check_op_admin_proc(struct mpi3mr_ioc *mrioc) +{ + + u16 timeout = 10 * 10; + u16 elapsed_time = 0; + bool op_admin_in_use = false; + + do { + op_admin_in_use = false; + + /* Check admin_reply queue first to exit early */ + if (atomic_read(&mrioc->admin_reply_q_in_use) == 1) + op_admin_in_use = true; + else { + /* Check op_reply queues */ + int i; + + for (i = 0; i < mrioc->num_queues; i++) { + if (atomic_read(&mrioc->op_reply_qinfo[i].in_use) == 1) { + op_admin_in_use = true; + break; + } + } + } + + if (!op_admin_in_use) + break; + + msleep(100); + + } while (++elapsed_time < timeout); + + if (op_admin_in_use) + return 1; + + return 0; +} + +/** * mpi3mr_soft_reset_handler - Reset the controller * @mrioc: Adapter instance reference * @reset_reason: Reset reason code @@ -5308,6 +5430,7 @@ int mpi3mr_soft_reset_handler(struct mpi3mr_ioc *mrioc, mpi3mr_wait_for_host_io(mrioc, MPI3MR_RESET_HOST_IOWAIT_TIMEOUT); mpi3mr_ioc_disable_intr(mrioc); + mrioc->io_admin_reset_sync = 1; if (snapdump) { mpi3mr_set_diagsave(mrioc); @@ -5335,6 +5458,16 @@ int mpi3mr_soft_reset_handler(struct mpi3mr_ioc *mrioc, ioc_err(mrioc, "Failed to issue soft reset to the ioc\n"); goto out; } + + retval = mpi3mr_check_op_admin_proc(mrioc); + if (retval) { + ioc_err(mrioc, "Soft reset failed due to an Admin or I/O queue polling\n" + "thread still processing replies even after a 10 second\n" + "timeout. Marking the controller as unrecoverable!\n"); + + goto out; + } + if (mrioc->num_io_throttle_group != mrioc->facts.max_io_throttle_group) { ioc_err(mrioc, diff --git a/drivers/scsi/mpi3mr/mpi3mr_os.c b/drivers/scsi/mpi3mr/mpi3mr_os.c index b9a51d3f2024..c186b892150f 100644 --- a/drivers/scsi/mpi3mr/mpi3mr_os.c +++ b/drivers/scsi/mpi3mr/mpi3mr_os.c @@ -3839,6 +3839,18 @@ int mpi3mr_issue_tm(struct mpi3mr_ioc *mrioc, u8 tm_type, tgtdev = mpi3mr_get_tgtdev_by_handle(mrioc, handle); if (scmd) { + if (tm_type == MPI3_SCSITASKMGMT_TASKTYPE_ABORT_TASK) { + cmd_priv = scsi_cmd_priv(scmd); + if (!cmd_priv) + goto out_unlock; + + struct op_req_qinfo *op_req_q; + + op_req_q = &mrioc->req_qinfo[cmd_priv->req_q_idx]; + tm_req.task_host_tag = cpu_to_le16(cmd_priv->host_tag); + tm_req.task_request_queue_id = + cpu_to_le16(op_req_q->qid); + } sdev = scmd->device; sdev_priv_data = sdev->hostdata; scsi_tgt_priv_data = ((sdev_priv_data) ? @@ -4388,6 +4400,92 @@ out: } /** + * mpi3mr_eh_abort - Callback function for abort error handling + * @scmd: SCSI command reference + * + * Issues Abort Task Management if the command is in LLD scope + * and verifies if it is aborted successfully, and return status + * accordingly. + * + * Return: SUCCESS if the abort was successful, otherwise FAILED + */ +static int mpi3mr_eh_abort(struct scsi_cmnd *scmd) +{ + struct mpi3mr_ioc *mrioc = shost_priv(scmd->device->host); + struct mpi3mr_stgt_priv_data *stgt_priv_data; + struct mpi3mr_sdev_priv_data *sdev_priv_data; + struct scmd_priv *cmd_priv; + u16 dev_handle, timeout = MPI3MR_ABORTTM_TIMEOUT; + u8 resp_code = 0; + int retval = FAILED, ret = 0; + struct request *rq = scsi_cmd_to_rq(scmd); + unsigned long scmd_age_ms = jiffies_to_msecs(jiffies - scmd->jiffies_at_alloc); + unsigned long scmd_age_sec = scmd_age_ms / HZ; + + sdev_printk(KERN_INFO, scmd->device, + "%s: attempting abort task for scmd(%p)\n", mrioc->name, scmd); + + sdev_printk(KERN_INFO, scmd->device, + "%s: scmd(0x%p) is outstanding for %lus %lums, timeout %us, retries %d, allowed %d\n", + mrioc->name, scmd, scmd_age_sec, scmd_age_ms % HZ, rq->timeout / HZ, + scmd->retries, scmd->allowed); + + scsi_print_command(scmd); + + sdev_priv_data = scmd->device->hostdata; + if (!sdev_priv_data || !sdev_priv_data->tgt_priv_data) { + sdev_printk(KERN_INFO, scmd->device, + "%s: Device not available, Skip issuing abort task\n", + mrioc->name); + retval = SUCCESS; + goto out; + } + + stgt_priv_data = sdev_priv_data->tgt_priv_data; + dev_handle = stgt_priv_data->dev_handle; + + cmd_priv = scsi_cmd_priv(scmd); + if (!cmd_priv->in_lld_scope || + cmd_priv->host_tag == MPI3MR_HOSTTAG_INVALID) { + sdev_printk(KERN_INFO, scmd->device, + "%s: scmd (0x%p) not in LLD scope, Skip issuing Abort Task\n", + mrioc->name, scmd); + retval = SUCCESS; + goto out; + } + + if (stgt_priv_data->dev_removed) { + sdev_printk(KERN_INFO, scmd->device, + "%s: Device (handle = 0x%04x) removed, Skip issuing Abort Task\n", + mrioc->name, dev_handle); + retval = FAILED; + goto out; + } + + ret = mpi3mr_issue_tm(mrioc, MPI3_SCSITASKMGMT_TASKTYPE_ABORT_TASK, + dev_handle, sdev_priv_data->lun_id, MPI3MR_HOSTTAG_BLK_TMS, + timeout, &mrioc->host_tm_cmds, &resp_code, scmd); + + if (ret) + goto out; + + if (cmd_priv->in_lld_scope) { + sdev_printk(KERN_INFO, scmd->device, + "%s: Abort task failed. scmd (0x%p) was not terminated\n", + mrioc->name, scmd); + goto out; + } + + retval = SUCCESS; +out: + sdev_printk(KERN_INFO, scmd->device, + "%s: Abort Task %s for scmd (0x%p)\n", mrioc->name, + ((retval == SUCCESS) ? "SUCCEEDED" : "FAILED"), scmd); + + return retval; +} + +/** * mpi3mr_scan_start - Scan start callback handler * @shost: SCSI host reference * @@ -5069,6 +5167,7 @@ static const struct scsi_host_template mpi3mr_driver_template = { .scan_finished = mpi3mr_scan_finished, .scan_start = mpi3mr_scan_start, .change_queue_depth = mpi3mr_change_queue_depth, + .eh_abort_handler = mpi3mr_eh_abort, .eh_device_reset_handler = mpi3mr_eh_dev_reset, .eh_target_reset_handler = mpi3mr_eh_target_reset, .eh_bus_reset_handler = mpi3mr_eh_bus_reset, @@ -5803,7 +5902,7 @@ static const struct pci_device_id mpi3mr_pci_id_table[] = { }; MODULE_DEVICE_TABLE(pci, mpi3mr_pci_id_table); -static struct pci_error_handlers mpi3mr_err_handler = { +static const struct pci_error_handlers mpi3mr_err_handler = { .error_detected = mpi3mr_pcierr_error_detected, .mmio_enabled = mpi3mr_pcierr_mmio_enabled, .slot_reset = mpi3mr_pcierr_slot_reset, |