mirror of
https://github.com/torvalds/linux.git
synced 2026-11-07 06:17:02 +01:00
Merge patch series "mpi3mr: Few Enhancements and minor fixes"
Ranjan Kumar <ranjan.kumar@broadcom.com> says: Few Enhancements and minor fixes of mpi3mr driver. Link: https://patch.msgid.link/20260916082705.44712-1-ranjan.kumar@broadcom.com Signed-off-by: Martin K. Petersen (Oracle) <mkp@kernel.org>
This commit is contained in:
commit
c3cff7fac0
|
|
@ -72,6 +72,12 @@
|
|||
#define MPI3_SECURITY_PGAD_SLOT_GROUP_SHIFT (8)
|
||||
#define MPI3_SECURITY_PGAD_SLOT_MASK (0x000000ff)
|
||||
#define MPI3_INSTANCE_PGAD_INSTANCE_MASK (0x0000ffff)
|
||||
#define MPI3_INSTANCE_PGAD_INSTANCE_SHIFT (0)
|
||||
#define MPI3_INTERFACE_PGAD_INTERFACE_MASK (0x0000000f)
|
||||
#define MPI3_INTERFACE_PGAD_INTERFACE_SHIFT (0)
|
||||
#define MPI3_INTERFACE_PGAD_INTERFACE_MPI (0)
|
||||
#define MPI3_INTERFACE_PGAD_INTERFACE_NVME_VD (1)
|
||||
#define MPI3_INTERFACE_PGAD_INTERFACE_NVME_PD (2)
|
||||
struct mpi3_config_request {
|
||||
__le16 host_tag;
|
||||
u8 ioc_use_only02;
|
||||
|
|
@ -492,10 +498,31 @@ struct mpi3_man10_istwi_ctrlr_entry {
|
|||
};
|
||||
|
||||
#define MPI3_MAN10_ISTWI_CTRLR_FLAGS_BUS_SPEED_MASK (0x000c)
|
||||
#define MPI3_MAN10_ISTWI_CTRLR_FLAGS_BUS_SPEED_100K (0x0000)
|
||||
#define MPI3_MAN10_ISTWI_CTRLR_FLAGS_BUS_SPEED_400K (0x0004)
|
||||
#define MPI3_MAN10_ISTWI_CTRLR_FLAGS_BUS_SPEED_100_KHZ (0x0000)
|
||||
#define MPI3_MAN10_ISTWI_CTRLR_FLAGS_BUS_SPEED_400_KHZ (0x0004)
|
||||
#define MPI3_MAN10_ISTWI_CTRLR_FLAGS_TARGET_ENABLED (0x0002)
|
||||
#define MPI3_MAN10_ISTWI_CTRLR_FLAGS_INITIATOR_ENABLED (0x0001)
|
||||
#define MPI3_MAN10_ISTWI_CTRLR_FLAGS_I2C_GLITCH_FLTR_MASK (0xc000)
|
||||
#define MPI3_MAN10_ISTWI_CTRLR_FLAGS_I2C_GLITCH_FLTR_SHIFT (14)
|
||||
#define MPI3_MAN10_ISTWI_CTRLR_FLAGS_I2C_GLITCH_FLTR_50_NS (0x0000)
|
||||
#define MPI3_MAN10_ISTWI_CTRLR_FLAGS_I2C_GLITCH_FLTR_10_NS (0x4000)
|
||||
#define MPI3_MAN10_ISTWI_CTRLR_FLAGS_I2C_GLITCH_FLTR_5_NS (0x8000)
|
||||
#define MPI3_MAN10_ISTWI_CTRLR_FLAGS_I2C_GLITCH_FLTR_0_NS (0xc000)
|
||||
#define MPI3_MAN10_ISTWI_CTRLR_FLAGS_BUS_TYPE_MASK (0x3000)
|
||||
#define MPI3_MAN10_ISTWI_CTRLR_FLAGS_BUS_TYPE_SHIFT (12)
|
||||
#define MPI3_MAN10_ISTWI_CTRLR_FLAGS_BUS_TYPE_I2C (0x0000)
|
||||
#define MPI3_MAN10_ISTWI_CTRLR_FLAGS_BUS_TYPE_I3C (0x1000)
|
||||
#define MPI3_MAN10_ISTWI_CTRLR_FLAGS_BUS_TYPE_AUTO (0x2000)
|
||||
#define MPI3_MAN10_ISTWI_CTRLR_FLAGS_I3C_MAX_DATA_RATE_MASK (0x0e00)
|
||||
#define MPI3_MAN10_ISTWI_CTRLR_FLAGS_I3C_MAX_DATA_RATE_SHIFT (9)
|
||||
#define MPI3_MAN10_ISTWI_CTRLR_FLAGS_I3C_MAX_DATA_RATE_12_5_MHZ (0x0000)
|
||||
#define MPI3_MAN10_ISTWI_CTRLR_FLAGS_I3C_MAX_DATA_RATE_8_MHZ (0x0200)
|
||||
#define MPI3_MAN10_ISTWI_CTRLR_FLAGS_I3C_MAX_DATA_RATE_6_MHZ (0x0400)
|
||||
#define MPI3_MAN10_ISTWI_CTRLR_FLAGS_I3C_MAX_DATA_RATE_4_MHZ (0x0600)
|
||||
#define MPI3_MAN10_ISTWI_CTRLR_FLAGS_I3C_MAX_DATA_RATE_2_MHZ (0x0800)
|
||||
#define MPI3_MAN10_ISTWI_CTRLR_FLAGS_BUS_SPEED_MASK (0x000c)
|
||||
#define MPI3_MAN10_ISTWI_CTRLR_FLAGS_BUS_SPEED_SHIFT (0)
|
||||
|
||||
#ifndef MPI3_MAN10_ISTWI_CTRLR_MAX
|
||||
#define MPI3_MAN10_ISTWI_CTRLR_MAX (1)
|
||||
#endif
|
||||
|
|
@ -1027,6 +1054,16 @@ struct mpi3_io_unit_page5 {
|
|||
#define MPI3_IOUNIT5_DEVICE_SHUTDOWN_SWITCH_ATTACHED (0x02)
|
||||
#define MPI3_IOUNIT5_DEVICE_SHUTDOWN_DIRECT_AND_EXPANDER (0x03)
|
||||
#define MPI3_IOUNIT5_DEVICE_SHUTDOWN_DIRECT_AND_SWITCH (0x03)
|
||||
#define MPI3_IOUNIT5_DEVICE_SHUTDOWN_HDD_SPINDOWN_MASK (0xc000)
|
||||
#define MPI3_IOUNIT5_DEVICE_SHUTDOWN_HDD_SPINDOWN_NONE (0x0000)
|
||||
#define MPI3_IOUNIT5_DEVICE_SHUTDOWN_HDD_SPINDOWN_ALL (0x4000)
|
||||
#define MPI3_IOUNIT5_DEVICE_SHUTDOWN_HDD_SPINDOWN_FILTERED (0x8000)
|
||||
#define MPI3_IOUNIT5_DEVICE_SHUTDOWN_HDD_SPINDOWN_RESERVED (0xc000)
|
||||
#define MPI3_IOUNIT5_DEVICE_SHUTDOWN_SYNC_CACHE_MASK (0x3000)
|
||||
#define MPI3_IOUNIT5_DEVICE_SHUTDOWN_SYNC_CACHE_ALL (0x0000)
|
||||
#define MPI3_IOUNIT5_DEVICE_SHUTDOWN_SYNC_CACHE_FILTERED (0x1000)
|
||||
#define MPI3_IOUNIT5_DEVICE_SHUTDOWN_SYNC_CACHE_NONE (0x2000)
|
||||
#define MPI3_IOUNIT5_DEVICE_SHUTDOWN_SYNC_CACHE_RESERVED (0x3000)
|
||||
#define MPI3_IOUNIT5_DEVICE_SHUTDOWN_SATA_HDD_MASK (0x0300)
|
||||
#define MPI3_IOUNIT5_DEVICE_SHUTDOWN_SATA_HDD_SHIFT (8)
|
||||
#define MPI3_IOUNIT5_DEVICE_SHUTDOWN_SAS_HDD_MASK (0x00c0)
|
||||
|
|
@ -1069,7 +1106,8 @@ struct mpi3_io_unit_page8 {
|
|||
struct mpi3_config_page_header header;
|
||||
u8 sb_mode;
|
||||
u8 sb_state;
|
||||
__le16 reserved0a;
|
||||
u8 flags;
|
||||
u8 reserved0b;
|
||||
u8 num_slots;
|
||||
u8 slots_available;
|
||||
u8 current_key_encryption_algo;
|
||||
|
|
@ -1088,6 +1126,8 @@ struct mpi3_io_unit_page8 {
|
|||
#define MPI3_IOUNIT8_SBSTATE_SVN_UPDATE_PENDING (0x04)
|
||||
#define MPI3_IOUNIT8_SBSTATE_KEY_UPDATE_PENDING (0x02)
|
||||
#define MPI3_IOUNIT8_SBSTATE_SECURE_BOOT_ENABLED (0x01)
|
||||
#define MPI3_IOUNIT8_FLAGS_FWQR_CAPABLE (0x80)
|
||||
#define MPI3_IOUNIT8_FLAGS_FWQR_SECURED (0x40)
|
||||
#define MPI3_IOUNIT8_SBMODE_CURRENT_KEY_IOUNIT17 (0x10)
|
||||
#define MPI3_IOUNIT8_SBMODE_HARD_SECURE_RECERTIFIED (0x08)
|
||||
struct mpi3_io_unit_page9 {
|
||||
|
|
@ -1174,10 +1214,16 @@ struct mpi3_io_unit_page12 {
|
|||
#define MPI3_IOUNIT12_FLAGS_NUMPASSES_32 (0x00000200)
|
||||
#define MPI3_IOUNIT12_FLAGS_NUMPASSES_64 (0x00000300)
|
||||
#define MPI3_IOUNIT12_FLAGS_PASSPERIOD_MASK (0x00000003)
|
||||
#define MPI3_IOUNIT12_FLAGS_PASSPERIOD_SHIFT (0)
|
||||
#define MPI3_IOUNIT12_FLAGS_PASSPERIOD_DISABLED (0x00000000)
|
||||
#define MPI3_IOUNIT12_FLAGS_PASSPERIOD_500US (0x00000001)
|
||||
#define MPI3_IOUNIT12_FLAGS_PASSPERIOD_1MS (0x00000002)
|
||||
#define MPI3_IOUNIT12_FLAGS_PASSPERIOD_2MS (0x00000003)
|
||||
#define MPI3_IOUNIT12_FLAGS_INTERFACE_MASK (0x0000000c)
|
||||
#define MPI3_IOUNIT12_FLAGS_INTERFACE_SHIFT (2)
|
||||
#define MPI3_IOUNIT12_FLAGS_INTERFACE_MPI (0x00000000)
|
||||
#define MPI3_IOUNIT12_FLAGS_INTERFACE_NVME_VD (0x00000004)
|
||||
#define MPI3_IOUNIT12_FLAGS_INTERFACE_NVME_PD (0x00000008)
|
||||
#ifndef MPI3_IOUNIT13_FUNC_MAX
|
||||
#define MPI3_IOUNIT13_FUNC_MAX (1)
|
||||
#endif
|
||||
|
|
@ -1238,6 +1284,7 @@ struct mpi3_io_unit_page15 {
|
|||
#define MPI3_IOUNIT15_PAGEVERSION (0x00)
|
||||
#define MPI3_IOUNIT15_FLAGS_EPRINIT_INITREQUIRED (0x04)
|
||||
#define MPI3_IOUNIT15_FLAGS_EPRSUPPORT_MASK (0x03)
|
||||
#define MPI3_IOUNIT15_FLAGS_EPRSUPPORT_SHIFT (0)
|
||||
#define MPI3_IOUNIT15_FLAGS_EPRSUPPORT_NOT_SUPPORTED (0x00)
|
||||
#define MPI3_IOUNIT15_FLAGS_EPRSUPPORT_WITHOUT_POWER_BRAKE_GPIO (0x01)
|
||||
#define MPI3_IOUNIT15_FLAGS_EPRSUPPORT_WITH_POWER_BRAKE_GPIO (0x02)
|
||||
|
|
@ -1255,6 +1302,9 @@ struct mpi3_io_unit_page17 {
|
|||
__le32 current_key[];
|
||||
};
|
||||
#define MPI3_IOUNIT17_PAGEVERSION (0x00)
|
||||
#define MPI3_IOUNIT17_FLAGS_KEYROOT_MASK (0x01)
|
||||
#define MPI3_IOUNIT17_FLAGS_KEYROOT_HW (0x00)
|
||||
#define MPI3_IOUNIT17_FLAGS_KEYROOT_FW (0x01)
|
||||
struct mpi3_io_unit_page18 {
|
||||
struct mpi3_config_page_header header;
|
||||
u8 flags;
|
||||
|
|
@ -1640,11 +1690,28 @@ struct mpi3_security_page3 {
|
|||
};
|
||||
|
||||
#define MPI3_SECURITY3_PAGEVERSION (0x00)
|
||||
#define MPI3_SECURITY3_FLAGS_TYPE_MASK (0x0f)
|
||||
#define MPI3_SECURITY3_FLAGS_TYPE_MASK (0x1f)
|
||||
#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)
|
||||
union mpi3_security_digest {
|
||||
__le32 dword[16];
|
||||
__le16 word[32];
|
||||
u8 byte[64];
|
||||
};
|
||||
struct mpi3_security_page4 {
|
||||
struct mpi3_config_page_header header;
|
||||
__le32 reserved08[2];
|
||||
union mpi3_security_mac mac;
|
||||
union mpi3_security_nonce nonce;
|
||||
u8 num_digests;
|
||||
u8 hash_algorithm;
|
||||
__le16 reserved92;
|
||||
__le32 reserved94[3];
|
||||
union mpi3_security_digest digest[];
|
||||
};
|
||||
#define MPI3_SECURITY4_PAGEVERSION (0x00)
|
||||
struct mpi3_security_page10 {
|
||||
struct mpi3_config_page_header header;
|
||||
__le32 reserved08[2];
|
||||
|
|
@ -2074,7 +2141,7 @@ struct mpi3_sas_phy3_phy_event_config {
|
|||
#define MPI3_SASPHY3_EVENT_CODE_LCCONN_TIME (0xd5)
|
||||
#define MPI3_SASPHY3_EVENT_CODE_SSP_TX_START_TRANSMIT (0xd6)
|
||||
#define MPI3_SASPHY3_EVENT_CODE_SATA_TX_START (0xd7)
|
||||
#define MPI3_SASPHY3_EVENT_CODE_SMP_TX_START_TRANSMT (0xd8)
|
||||
#define MPI3_SASPHY3_EVENT_CODE_SMP_TX_START_TRANSMIT (0xd8)
|
||||
#define MPI3_SASPHY3_EVENT_CODE_TX_SMP_BREAK_CONN (0xd9)
|
||||
#define MPI3_SASPHY3_EVENT_CODE_SSP_RX_START_RECEIVE (0xda)
|
||||
#define MPI3_SASPHY3_EVENT_CODE_SATA_RX_START_RECEIVE (0xdb)
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ struct mpi3_hash_exclusion_format {
|
|||
__le32 size;
|
||||
};
|
||||
|
||||
#define MPI3_IMAGE_HASH_EXCUSION_NUM (4)
|
||||
#define MPI3_IMAGE_HASH_EXCLUSION_NUM (4)
|
||||
struct mpi3_component_image_header {
|
||||
__le32 signature0;
|
||||
__le32 load_address;
|
||||
|
|
@ -42,7 +42,7 @@ struct mpi3_component_image_header {
|
|||
union mpi3_version_union rmc_interface_version;
|
||||
union mpi3_version_union etp_interface_version;
|
||||
struct mpi3_comp_image_version component_image_version;
|
||||
struct mpi3_hash_exclusion_format hash_exclusion[MPI3_IMAGE_HASH_EXCUSION_NUM];
|
||||
struct mpi3_hash_exclusion_format hash_exclusion[MPI3_IMAGE_HASH_EXCLUSION_NUM];
|
||||
__le32 next_image_header_offset;
|
||||
union mpi3_version_union security_version;
|
||||
__le32 reserved84[31];
|
||||
|
|
@ -347,7 +347,8 @@ struct mpi3_encrypted_hash_entry {
|
|||
struct mpi3_encrypted_hash_data {
|
||||
u8 image_version;
|
||||
u8 num_hash;
|
||||
__le16 reserved02;
|
||||
u8 fw_num_hash;
|
||||
u8 reserved03;
|
||||
__le32 reserved04;
|
||||
struct mpi3_encrypted_hash_entry encrypted_hash_entry[MPI3_ENCRYPTED_HASH_ENTRY_MAX];
|
||||
};
|
||||
|
|
|
|||
|
|
@ -428,10 +428,10 @@ struct mpi3_event_data_sas_discovery {
|
|||
#define MPI3_EVENT_SAS_DISC_FLAGS_IN_PROGRESS (0x01)
|
||||
#define MPI3_EVENT_SAS_DISC_RC_STARTED (0x01)
|
||||
#define MPI3_EVENT_SAS_DISC_RC_COMPLETED (0x02)
|
||||
#define MPI3_SAS_DISC_STATUS_MAX_ENCLOSURES_EXCEED (0x80000000)
|
||||
#define MPI3_SAS_DISC_STATUS_MAX_EXPANDERS_EXCEED (0x40000000)
|
||||
#define MPI3_SAS_DISC_STATUS_MAX_DEVICES_EXCEED (0x20000000)
|
||||
#define MPI3_SAS_DISC_STATUS_MAX_TOPO_PHYS_EXCEED (0x10000000)
|
||||
#define MPI3_SAS_DISC_STATUS_MAX_ENCLOSURES_EXCEEDED (0x80000000)
|
||||
#define MPI3_SAS_DISC_STATUS_MAX_EXPANDERS_EXCEEDED (0x40000000)
|
||||
#define MPI3_SAS_DISC_STATUS_MAX_DEVICES_EXCEEDED (0x20000000)
|
||||
#define MPI3_SAS_DISC_STATUS_MAX_TOPO_PHYS_EXCEEDED (0x10000000)
|
||||
#define MPI3_SAS_DISC_STATUS_INVALID_CEI (0x00010000)
|
||||
#define MPI3_SAS_DISC_STATUS_FECEI_MISMATCH (0x00008000)
|
||||
#define MPI3_SAS_DISC_STATUS_MULTIPLE_DEVICES_IN_SLOT (0x00004000)
|
||||
|
|
@ -965,7 +965,7 @@ struct mpi3_ci_download_reply {
|
|||
u8 flags;
|
||||
u8 cache_dirty;
|
||||
u8 pending_count;
|
||||
u8 reserved13;
|
||||
u8 additional_flags;
|
||||
};
|
||||
|
||||
#define MPI3_CI_DOWNLOAD_FLAGS_DOWNLOAD_IN_PROGRESS (0x80)
|
||||
|
|
@ -979,6 +979,11 @@ struct mpi3_ci_download_reply {
|
|||
#define MPI3_CI_DOWNLOAD_FLAGS_ACTIVATION_STATUS_ONLINE_PENDING (0x04)
|
||||
#define MPI3_CI_DOWNLOAD_FLAGS_ACTIVATION_STATUS_OFFLINE_PENDING (0x06)
|
||||
#define MPI3_CI_DOWNLOAD_FLAGS_COMPATIBLE (0x01)
|
||||
#define MPI3_CI_DOWNLOAD_ADDITIONALFLAGS_REDUNDANCYRESTORATION_MASK (0x03)
|
||||
#define MPI3_CI_DOWNLOAD_ADDITIONALFLAGS_REDUNDANCYRESTORATION_SHIFT (0)
|
||||
#define MPI3_CI_DOWNLOAD_ADDITIONALFLAGS_REDUNDANCYRESTORATION_NONE (0x00)
|
||||
#define MPI3_CI_DOWNLOAD_ADDITIONALFLAGS_REDUNDANCYRESTORATION_PRIMARY (0x01)
|
||||
#define MPI3_CI_DOWNLOAD_ADDITIONALFLAGS_REDUNDANCYRESTORATION_SECONDARY (0x02)
|
||||
struct mpi3_ci_upload_request {
|
||||
__le16 host_tag;
|
||||
u8 ioc_use_only02;
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ union mpi3_version_union {
|
|||
|
||||
#define MPI3_VERSION_MAJOR (3)
|
||||
#define MPI3_VERSION_MINOR (0)
|
||||
#define MPI3_VERSION_UNIT (39)
|
||||
#define MPI3_VERSION_UNIT (41)
|
||||
#define MPI3_VERSION_DEV (0)
|
||||
#define MPI3_DEVHANDLE_INVALID (0xffff)
|
||||
struct mpi3_sysif_oper_queue_indexes {
|
||||
|
|
|
|||
|
|
@ -56,8 +56,8 @@ extern struct list_head mrioc_list;
|
|||
extern int prot_mask;
|
||||
extern atomic64_t event_counter;
|
||||
|
||||
#define MPI3MR_DRIVER_VERSION "8.17.0.3.50"
|
||||
#define MPI3MR_DRIVER_RELDATE "09-January-2026"
|
||||
#define MPI3MR_DRIVER_VERSION "8.18.0.8.50"
|
||||
#define MPI3MR_DRIVER_RELDATE "26-June-2026"
|
||||
|
||||
#define MPI3MR_DRIVER_NAME "mpi3mr"
|
||||
#define MPI3MR_DRIVER_LICENSE "GPL"
|
||||
|
|
@ -125,6 +125,7 @@ extern atomic64_t event_counter;
|
|||
#define MPI3MR_RESETTM_TIMEOUT 60
|
||||
#define MPI3MR_RESET_HOST_IOWAIT_TIMEOUT 5
|
||||
#define MPI3MR_TSUPDATE_INTERVAL 900
|
||||
#define MPI3MR_EARLY_TSUPDATE_SECONDS 60
|
||||
#define MPI3MR_DEFAULT_SHUTDOWN_TIME 120
|
||||
#define MPI3MR_RAID_ERRREC_RESET_TIMEOUT 180
|
||||
#define MPI3MR_PREPARE_FOR_RESET_TIMEOUT 180
|
||||
|
|
@ -168,6 +169,7 @@ extern atomic64_t event_counter;
|
|||
|
||||
#define MPI3MR_DEFAULT_MDTS (128 * 1024)
|
||||
#define MPI3MR_DEFAULT_PGSZEXP (12)
|
||||
#define MPI3MR_MAX_PGSZEXP (27)
|
||||
|
||||
/* Command retry count definitions */
|
||||
#define MPI3MR_DEV_RMHS_RETRY_COUNT 3
|
||||
|
|
@ -177,7 +179,7 @@ extern atomic64_t event_counter;
|
|||
#define MPI3MR_DEFAULT_SDEV_QD 32
|
||||
|
||||
/* Definitions for Threaded IRQ poll*/
|
||||
#define MPI3MR_IRQ_POLL_SLEEP 20
|
||||
#define MPI3MR_IRQ_POLL_SLEEP 2
|
||||
#define MPI3MR_IRQ_POLL_TRIGGER_IOCOUNT 8
|
||||
|
||||
/* Definitions for the controller security status*/
|
||||
|
|
@ -1118,6 +1120,7 @@ struct scmd_priv {
|
|||
* @evtack_cmds_bitmap: Event Ack bitmap
|
||||
* @delayed_evtack_cmds_list: Delayed event acknowledgment list
|
||||
* @ts_update_counter: Timestamp update counter
|
||||
* @early_ts_sync_done: Early (1 min) timestamp sync completed after load
|
||||
* @ts_update_interval: Timestamp update interval
|
||||
* @reset_in_progress: Reset in progress flag
|
||||
* @unrecoverable: Controller unrecoverable flag
|
||||
|
|
@ -1318,6 +1321,7 @@ struct mpi3mr_ioc {
|
|||
struct list_head delayed_evtack_cmds_list;
|
||||
|
||||
u16 ts_update_counter;
|
||||
u8 early_ts_sync_done;
|
||||
u16 ts_update_interval;
|
||||
u8 reset_in_progress;
|
||||
u8 unrecoverable;
|
||||
|
|
@ -1410,6 +1414,9 @@ struct mpi3mr_ioc {
|
|||
struct dma_pool *trace_buf_pool;
|
||||
struct segments *trace_buf;
|
||||
u8 invalid_io_comp;
|
||||
bool is_unload;
|
||||
bool skip_dev_shutdown_on_unload;
|
||||
|
||||
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -141,25 +141,27 @@ void mpi3mr_alloc_diag_bufs(struct mpi3mr_ioc *mrioc)
|
|||
trace_min_size = fw_min_size = MPI3MR_DEFAULT_HDB_MIN_SZ;
|
||||
|
||||
} else {
|
||||
trace_size = driver_pg1.host_diag_trace_max_size * 1024;
|
||||
trace_dec_size = driver_pg1.host_diag_trace_decrement_size
|
||||
trace_size = le16_to_cpu(driver_pg1.host_diag_trace_max_size) * 1024;
|
||||
trace_dec_size = le16_to_cpu(driver_pg1.host_diag_trace_decrement_size)
|
||||
* 1024;
|
||||
trace_min_size = driver_pg1.host_diag_trace_min_size * 1024;
|
||||
fw_size = driver_pg1.host_diag_fw_max_size * 1024;
|
||||
fw_dec_size = driver_pg1.host_diag_fw_decrement_size * 1024;
|
||||
fw_min_size = driver_pg1.host_diag_fw_min_size * 1024;
|
||||
trace_min_size = le16_to_cpu(driver_pg1.host_diag_trace_min_size) * 1024;
|
||||
fw_size = le16_to_cpu(driver_pg1.host_diag_fw_max_size) * 1024;
|
||||
fw_dec_size = le16_to_cpu(driver_pg1.host_diag_fw_decrement_size) * 1024;
|
||||
fw_min_size = le16_to_cpu(driver_pg1.host_diag_fw_min_size) * 1024;
|
||||
dprint_init(mrioc,
|
||||
"%s:trace diag buffer sizes read from driver\n"
|
||||
"page1: maximum size = %dKB, decrement size = %dKB\n"
|
||||
", minimum size = %dKB\n", __func__, driver_pg1.host_diag_trace_max_size,
|
||||
driver_pg1.host_diag_trace_decrement_size,
|
||||
driver_pg1.host_diag_trace_min_size);
|
||||
", minimum size = %dKB\n", __func__,
|
||||
le16_to_cpu(driver_pg1.host_diag_trace_max_size),
|
||||
le16_to_cpu(driver_pg1.host_diag_trace_decrement_size),
|
||||
le16_to_cpu(driver_pg1.host_diag_trace_min_size));
|
||||
dprint_init(mrioc,
|
||||
"%s:firmware diag buffer sizes read from driver\n"
|
||||
"page1: maximum size = %dKB, decrement size = %dKB\n"
|
||||
", minimum size = %dKB\n", __func__, driver_pg1.host_diag_fw_max_size,
|
||||
driver_pg1.host_diag_fw_decrement_size,
|
||||
driver_pg1.host_diag_fw_min_size);
|
||||
", minimum size = %dKB\n", __func__,
|
||||
le16_to_cpu(driver_pg1.host_diag_fw_max_size),
|
||||
le16_to_cpu(driver_pg1.host_diag_fw_decrement_size),
|
||||
le16_to_cpu(driver_pg1.host_diag_fw_min_size));
|
||||
if ((trace_size == 0) && (fw_size == 0))
|
||||
return;
|
||||
}
|
||||
|
|
@ -179,6 +181,12 @@ void mpi3mr_alloc_diag_bufs(struct mpi3mr_ioc *mrioc)
|
|||
mpi3mr_alloc_trace_buffer(mrioc, trace_size)) {
|
||||
|
||||
retry = true;
|
||||
|
||||
if (!trace_dec_size || trace_dec_size > trace_size) {
|
||||
retry = false;
|
||||
goto retry_fw;
|
||||
}
|
||||
|
||||
trace_size -= trace_dec_size;
|
||||
dprint_init(mrioc, "trace diag buffer allocation failed\n"
|
||||
"retrying smaller size %dKB\n", trace_size / 1024);
|
||||
|
|
@ -211,11 +219,13 @@ void mpi3mr_alloc_diag_bufs(struct mpi3mr_ioc *mrioc)
|
|||
diag_buffer->size = fw_size;
|
||||
} else {
|
||||
retry = true;
|
||||
fw_size -= fw_dec_size;
|
||||
dprint_init(mrioc, "%s:trace diag buffer allocation failed,\n"
|
||||
"retrying smaller size %dKB\n",
|
||||
__func__, fw_size / 1024);
|
||||
goto retry_fw;
|
||||
if (fw_dec_size && fw_dec_size <= fw_size) {
|
||||
fw_size -= fw_dec_size;
|
||||
dprint_init(mrioc, "%s:trace diag buffer allocation failed,\n"
|
||||
"retrying smaller size %dKB\n",
|
||||
__func__, fw_size / 1024);
|
||||
goto retry_fw;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -490,6 +490,12 @@ int mpi3mr_process_admin_reply_q(struct mpi3mr_ioc *mrioc)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Ensure that the descriptor payload is read only after
|
||||
* the phase bit check is complete.
|
||||
*/
|
||||
dma_rmb();
|
||||
|
||||
do {
|
||||
if (mrioc->unrecoverable || mrioc->io_admin_reset_sync)
|
||||
break;
|
||||
|
|
@ -510,6 +516,13 @@ int mpi3mr_process_admin_reply_q(struct mpi3mr_ioc *mrioc)
|
|||
if ((le16_to_cpu(reply_desc->reply_flags) &
|
||||
MPI3_REPLY_DESCRIPT_FLAGS_PHASE_MASK) != exp_phase)
|
||||
break;
|
||||
|
||||
/*
|
||||
* Ensure that the descriptor payload is read only after
|
||||
* the phase bit check is complete.
|
||||
*/
|
||||
dma_rmb();
|
||||
|
||||
if (threshold_comps == MPI3MR_THRESHOLD_REPLY_COUNT) {
|
||||
writel(admin_reply_ci,
|
||||
&mrioc->sysif_regs->admin_reply_queue_ci);
|
||||
|
|
@ -570,6 +583,9 @@ int mpi3mr_process_op_reply_q(struct mpi3mr_ioc *mrioc,
|
|||
struct mpi3_default_reply_descriptor *reply_desc;
|
||||
u16 req_q_idx = 0, reply_qidx, threshold_comps = 0;
|
||||
|
||||
if (!op_reply_q)
|
||||
return 0;
|
||||
|
||||
reply_qidx = op_reply_q->qid - 1;
|
||||
|
||||
if (!atomic_add_unless(&op_reply_q->in_use, 1, 1))
|
||||
|
|
@ -581,15 +597,33 @@ int mpi3mr_process_op_reply_q(struct mpi3mr_ioc *mrioc,
|
|||
reply_desc = mpi3mr_get_reply_desc(op_reply_q, reply_ci);
|
||||
if ((le16_to_cpu(reply_desc->reply_flags) &
|
||||
MPI3_REPLY_DESCRIPT_FLAGS_PHASE_MASK) != exp_phase) {
|
||||
/* Recheck under in_use before releasing, to avoid a reclaim race */
|
||||
dma_rmb();
|
||||
if ((le16_to_cpu(reply_desc->reply_flags) &
|
||||
MPI3_REPLY_DESCRIPT_FLAGS_PHASE_MASK) == exp_phase)
|
||||
goto process_desc;
|
||||
atomic_dec(&op_reply_q->in_use);
|
||||
return 0;
|
||||
}
|
||||
process_desc:
|
||||
/*
|
||||
* Ensure that the descriptor payload is read only after
|
||||
* the phase bit check is complete.
|
||||
*/
|
||||
dma_rmb();
|
||||
|
||||
do {
|
||||
if (mrioc->unrecoverable || mrioc->io_admin_reset_sync)
|
||||
break;
|
||||
|
||||
req_q_idx = le16_to_cpu(reply_desc->request_queue_id) - 1;
|
||||
|
||||
if (unlikely(req_q_idx >= mrioc->num_op_req_q)) {
|
||||
ioc_err(mrioc, "Invalid request queue id %d, skipping reply\n",
|
||||
req_q_idx + 1);
|
||||
goto next_reply;
|
||||
}
|
||||
|
||||
op_req_q = &mrioc->req_qinfo[req_q_idx];
|
||||
|
||||
WRITE_ONCE(op_req_q->ci, le16_to_cpu(reply_desc->request_queue_ci));
|
||||
|
|
@ -598,8 +632,9 @@ int mpi3mr_process_op_reply_q(struct mpi3mr_ioc *mrioc,
|
|||
|
||||
if (reply_dma)
|
||||
mpi3mr_repost_reply_buf(mrioc, reply_dma);
|
||||
num_op_reply++;
|
||||
threshold_comps++;
|
||||
next_reply:
|
||||
num_op_reply++;
|
||||
|
||||
if (++reply_ci == op_reply_q->num_replies) {
|
||||
reply_ci = 0;
|
||||
|
|
@ -609,8 +644,19 @@ int mpi3mr_process_op_reply_q(struct mpi3mr_ioc *mrioc,
|
|||
reply_desc = mpi3mr_get_reply_desc(op_reply_q, reply_ci);
|
||||
|
||||
if ((le16_to_cpu(reply_desc->reply_flags) &
|
||||
MPI3_REPLY_DESCRIPT_FLAGS_PHASE_MASK) != exp_phase)
|
||||
MPI3_REPLY_DESCRIPT_FLAGS_PHASE_MASK) != exp_phase) {
|
||||
dma_rmb();
|
||||
if ((le16_to_cpu(reply_desc->reply_flags) &
|
||||
MPI3_REPLY_DESCRIPT_FLAGS_PHASE_MASK) == exp_phase)
|
||||
goto reply_ready;
|
||||
break;
|
||||
}
|
||||
reply_ready:
|
||||
/*
|
||||
* Ensure that the descriptor payload is read only after
|
||||
* the phase bit check is complete.
|
||||
*/
|
||||
dma_rmb();
|
||||
#ifndef CONFIG_PREEMPT_RT
|
||||
/*
|
||||
* Exit completion loop to avoid CPU lockup
|
||||
|
|
@ -672,6 +718,7 @@ static irqreturn_t mpi3mr_isr_primary(int irq, void *privdata)
|
|||
{
|
||||
struct mpi3mr_intr_info *intr_info = privdata;
|
||||
struct mpi3mr_ioc *mrioc;
|
||||
struct op_reply_qinfo *op_reply_q;
|
||||
u16 midx;
|
||||
u32 num_admin_replies = 0, num_op_reply = 0;
|
||||
|
||||
|
|
@ -687,9 +734,9 @@ static irqreturn_t mpi3mr_isr_primary(int irq, void *privdata)
|
|||
|
||||
if (!midx)
|
||||
num_admin_replies = mpi3mr_process_admin_reply_q(mrioc);
|
||||
if (intr_info->op_reply_q)
|
||||
num_op_reply = mpi3mr_process_op_reply_q(mrioc,
|
||||
intr_info->op_reply_q);
|
||||
op_reply_q = READ_ONCE(intr_info->op_reply_q);
|
||||
if (op_reply_q)
|
||||
num_op_reply = mpi3mr_process_op_reply_q(mrioc, op_reply_q);
|
||||
|
||||
if (num_admin_replies || num_op_reply)
|
||||
return IRQ_HANDLED;
|
||||
|
|
@ -702,6 +749,7 @@ static irqreturn_t mpi3mr_isr_primary(int irq, void *privdata)
|
|||
static irqreturn_t mpi3mr_isr(int irq, void *privdata)
|
||||
{
|
||||
struct mpi3mr_intr_info *intr_info = privdata;
|
||||
struct op_reply_qinfo *op_reply_q;
|
||||
int ret;
|
||||
|
||||
if (!intr_info)
|
||||
|
|
@ -714,11 +762,12 @@ static irqreturn_t mpi3mr_isr(int irq, void *privdata)
|
|||
* If more IOs are expected, schedule IRQ polling thread.
|
||||
* Otherwise exit from ISR.
|
||||
*/
|
||||
if ((threaded_isr_poll == false) || !intr_info->op_reply_q)
|
||||
op_reply_q = READ_ONCE(intr_info->op_reply_q);
|
||||
if ((threaded_isr_poll == false) || !op_reply_q)
|
||||
return ret;
|
||||
|
||||
if (!intr_info->op_reply_q->enable_irq_poll ||
|
||||
!atomic_read(&intr_info->op_reply_q->pend_ios))
|
||||
if (!op_reply_q->enable_irq_poll ||
|
||||
!atomic_read(&op_reply_q->pend_ios))
|
||||
return ret;
|
||||
|
||||
disable_irq_nosync(intr_info->os_irq);
|
||||
|
|
@ -740,12 +789,19 @@ static irqreturn_t mpi3mr_isr_poll(int irq, void *privdata)
|
|||
{
|
||||
struct mpi3mr_intr_info *intr_info = privdata;
|
||||
struct mpi3mr_ioc *mrioc;
|
||||
struct op_reply_qinfo *op_reply_q;
|
||||
u16 midx;
|
||||
u32 num_op_reply = 0;
|
||||
|
||||
if (!intr_info || !intr_info->op_reply_q)
|
||||
if (!intr_info)
|
||||
return IRQ_NONE;
|
||||
|
||||
op_reply_q = READ_ONCE(intr_info->op_reply_q);
|
||||
if (!op_reply_q) {
|
||||
enable_irq(intr_info->os_irq);
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
mrioc = intr_info->mrioc;
|
||||
midx = intr_info->msix_index;
|
||||
|
||||
|
|
@ -754,19 +810,23 @@ static irqreturn_t mpi3mr_isr_poll(int irq, void *privdata)
|
|||
if (!mrioc->intr_enabled || mrioc->unrecoverable)
|
||||
break;
|
||||
|
||||
op_reply_q = READ_ONCE(intr_info->op_reply_q);
|
||||
if (!op_reply_q)
|
||||
break;
|
||||
|
||||
if (!midx)
|
||||
mpi3mr_process_admin_reply_q(mrioc);
|
||||
if (intr_info->op_reply_q)
|
||||
num_op_reply +=
|
||||
mpi3mr_process_op_reply_q(mrioc,
|
||||
intr_info->op_reply_q);
|
||||
num_op_reply +=
|
||||
mpi3mr_process_op_reply_q(mrioc, op_reply_q);
|
||||
if (!atomic_read(&op_reply_q->pend_ios))
|
||||
break;
|
||||
|
||||
usleep_range(MPI3MR_IRQ_POLL_SLEEP, MPI3MR_IRQ_POLL_SLEEP + 1);
|
||||
usleep_range(MPI3MR_IRQ_POLL_SLEEP, 10 * MPI3MR_IRQ_POLL_SLEEP);
|
||||
|
||||
} while (atomic_read(&intr_info->op_reply_q->pend_ios) &&
|
||||
(num_op_reply < mrioc->max_host_ios));
|
||||
} while (num_op_reply < mrioc->max_host_ios);
|
||||
|
||||
intr_info->op_reply_q->enable_irq_poll = false;
|
||||
if (op_reply_q)
|
||||
op_reply_q->enable_irq_poll = false;
|
||||
enable_irq(intr_info->os_irq);
|
||||
|
||||
return IRQ_HANDLED;
|
||||
|
|
@ -1950,10 +2010,6 @@ static void mpi3mr_free_op_req_q_segments(struct mpi3mr_ioc *mrioc, u16 q_idx)
|
|||
int size;
|
||||
struct segments *segments;
|
||||
|
||||
segments = mrioc->req_qinfo[q_idx].q_segments;
|
||||
if (!segments)
|
||||
return;
|
||||
|
||||
if (mrioc->enable_segqueue) {
|
||||
size = MPI3MR_OP_REQ_Q_SEG_SIZE;
|
||||
if (mrioc->req_qinfo[q_idx].q_segment_list) {
|
||||
|
|
@ -1967,6 +2023,10 @@ static void mpi3mr_free_op_req_q_segments(struct mpi3mr_ioc *mrioc, u16 q_idx)
|
|||
size = mrioc->req_qinfo[q_idx].segment_qd *
|
||||
mrioc->facts.op_req_sz;
|
||||
|
||||
segments = mrioc->req_qinfo[q_idx].q_segments;
|
||||
if (!segments)
|
||||
return;
|
||||
|
||||
for (j = 0; j < mrioc->req_qinfo[q_idx].num_segments; j++) {
|
||||
if (!segments[j].segment)
|
||||
continue;
|
||||
|
|
@ -1993,10 +2053,17 @@ static void mpi3mr_free_op_reply_q_segments(struct mpi3mr_ioc *mrioc, u16 q_idx)
|
|||
u16 j;
|
||||
int size;
|
||||
struct segments *segments;
|
||||
u16 midx = REPLY_QUEUE_IDX_TO_MSIX_IDX(q_idx, mrioc->op_reply_q_offset);
|
||||
|
||||
segments = mrioc->op_reply_qinfo[q_idx].q_segments;
|
||||
if (!segments)
|
||||
return;
|
||||
/*
|
||||
* Stop the ISR/poll thread from picking up this queue before its
|
||||
* segments are freed below, and wait for any in-flight handler
|
||||
* that already has the old pointer to finish using it.
|
||||
*/
|
||||
if (midx < mrioc->intr_info_count) {
|
||||
WRITE_ONCE(mrioc->intr_info[midx].op_reply_q, NULL);
|
||||
synchronize_irq(pci_irq_vector(mrioc->pdev, midx));
|
||||
}
|
||||
|
||||
if (mrioc->enable_segqueue) {
|
||||
size = MPI3MR_OP_REP_Q_SEG_SIZE;
|
||||
|
|
@ -2011,6 +2078,10 @@ static void mpi3mr_free_op_reply_q_segments(struct mpi3mr_ioc *mrioc, u16 q_idx)
|
|||
size = mrioc->op_reply_qinfo[q_idx].segment_qd *
|
||||
mrioc->op_reply_desc_sz;
|
||||
|
||||
segments = mrioc->op_reply_qinfo[q_idx].q_segments;
|
||||
if (!segments)
|
||||
return;
|
||||
|
||||
for (j = 0; j < mrioc->op_reply_qinfo[q_idx].num_segments; j++) {
|
||||
if (!segments[j].segment)
|
||||
continue;
|
||||
|
|
@ -2477,7 +2548,7 @@ static int mpi3mr_create_op_req_q(struct mpi3mr_ioc *mrioc, u16 idx,
|
|||
static int mpi3mr_create_op_queues(struct mpi3mr_ioc *mrioc)
|
||||
{
|
||||
int retval = 0;
|
||||
u16 num_queues = 0, i = 0, msix_count_op_q = 1;
|
||||
u16 num_queues = 0, i = 0, j = 0, msix_count_op_q = 1;
|
||||
u32 ioc_status;
|
||||
enum mpi3mr_iocstate ioc_state;
|
||||
|
||||
|
|
@ -2529,6 +2600,13 @@ static int mpi3mr_create_op_queues(struct mpi3mr_ioc *mrioc)
|
|||
}
|
||||
}
|
||||
|
||||
if (i < num_queues) {
|
||||
for (j = i; j < num_queues; j++) {
|
||||
mpi3mr_free_op_req_q_segments(mrioc, j);
|
||||
mpi3mr_free_op_reply_q_segments(mrioc, j);
|
||||
}
|
||||
}
|
||||
|
||||
if (i == 0) {
|
||||
/* Not even one queue is created successfully*/
|
||||
retval = -1;
|
||||
|
|
@ -2550,11 +2628,19 @@ static int mpi3mr_create_op_queues(struct mpi3mr_ioc *mrioc)
|
|||
|
||||
return retval;
|
||||
out_failed:
|
||||
kfree(mrioc->req_qinfo);
|
||||
mrioc->req_qinfo = NULL;
|
||||
if (mrioc->req_qinfo) {
|
||||
for (j = 0; j < i; j++) {
|
||||
mpi3mr_free_op_req_q_segments(mrioc, j);
|
||||
mpi3mr_free_op_reply_q_segments(mrioc, j);
|
||||
}
|
||||
kfree(mrioc->req_qinfo);
|
||||
mrioc->req_qinfo = NULL;
|
||||
}
|
||||
mrioc->num_op_req_q = 0;
|
||||
|
||||
kfree(mrioc->op_reply_qinfo);
|
||||
mrioc->op_reply_qinfo = NULL;
|
||||
mrioc->num_op_reply_q = 0;
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
|
@ -2598,7 +2684,8 @@ int mpi3mr_op_request_post(struct mpi3mr_ioc *mrioc,
|
|||
if (mpi3mr_check_req_qfull(op_req_q)) {
|
||||
midx = REPLY_QUEUE_IDX_TO_MSIX_IDX(
|
||||
reply_qidx, mrioc->op_reply_q_offset);
|
||||
mpi3mr_process_op_reply_q(mrioc, mrioc->intr_info[midx].op_reply_q);
|
||||
mpi3mr_process_op_reply_q(mrioc,
|
||||
READ_ONCE(mrioc->intr_info[midx].op_reply_q));
|
||||
|
||||
if (mpi3mr_check_req_qfull(op_req_q)) {
|
||||
|
||||
|
|
@ -2891,8 +2978,9 @@ static int mpi3mr_print_pkg_ver(struct mpi3mr_ioc *mrioc)
|
|||
* @work: work struct
|
||||
*
|
||||
* Watch dog work periodically executed (1 second interval) to
|
||||
* monitor firmware fault and to issue periodic timer sync to
|
||||
* the firmware.
|
||||
* monitor firmware fault and perform timestamp synchronization
|
||||
* to firmware, with an early sync 1 minute after load followed
|
||||
* by periodic updates at ts_update_interval seconds (default 15 minutes).
|
||||
*
|
||||
* Return: Nothing.
|
||||
*/
|
||||
|
|
@ -2938,11 +3026,23 @@ static void mpi3mr_watchdog_work(struct work_struct *work)
|
|||
}
|
||||
|
||||
if (!(mrioc->facts.ioc_capabilities &
|
||||
MPI3_IOCFACTS_CAPABILITY_NON_SUPERVISOR_IOC) &&
|
||||
(mrioc->ts_update_counter++ >= mrioc->ts_update_interval)) {
|
||||
MPI3_IOCFACTS_CAPABILITY_NON_SUPERVISOR_IOC)) {
|
||||
if (!mrioc->early_ts_sync_done) {
|
||||
/*
|
||||
* Send time sync 1 min after load
|
||||
*/
|
||||
if (mrioc->ts_update_counter++ >=
|
||||
MPI3MR_EARLY_TSUPDATE_SECONDS) {
|
||||
mrioc->early_ts_sync_done = 1;
|
||||
mrioc->ts_update_counter = 0;
|
||||
mpi3mr_sync_timestamp(mrioc);
|
||||
}
|
||||
} else if (mrioc->ts_update_counter++ >=
|
||||
mrioc->ts_update_interval) {
|
||||
mrioc->ts_update_counter = 0;
|
||||
mpi3mr_sync_timestamp(mrioc);
|
||||
}
|
||||
|
||||
mrioc->ts_update_counter = 0;
|
||||
mpi3mr_sync_timestamp(mrioc);
|
||||
}
|
||||
|
||||
if ((mrioc->prepare_for_reset) &&
|
||||
|
|
@ -4128,26 +4228,35 @@ static int mpi3mr_repost_diag_bufs(struct mpi3mr_ioc *mrioc)
|
|||
}
|
||||
|
||||
/**
|
||||
* mpi3mr_read_tsu_interval - Update time stamp interval
|
||||
* mpi3mr_read_driver_page1 - Read Driver Page 1 parameters
|
||||
* @mrioc: Adapter instance reference
|
||||
*
|
||||
* Update time stamp interval if its defined in driver page 1,
|
||||
* otherwise use default value.
|
||||
* Reads and caches Driver Page 1 parameters such as
|
||||
* timestamp update interval and driver behavior flags.
|
||||
*
|
||||
* Return: Nothing
|
||||
*/
|
||||
static void
|
||||
mpi3mr_read_tsu_interval(struct mpi3mr_ioc *mrioc)
|
||||
mpi3mr_read_driver_page1(struct mpi3mr_ioc *mrioc)
|
||||
{
|
||||
struct mpi3_driver_page1 driver_pg1;
|
||||
u16 pg_sz = sizeof(driver_pg1);
|
||||
int retval = 0;
|
||||
|
||||
mrioc->ts_update_interval = MPI3MR_TSUPDATE_INTERVAL;
|
||||
mrioc->skip_dev_shutdown_on_unload = 0;
|
||||
|
||||
retval = mpi3mr_cfg_get_driver_pg1(mrioc, &driver_pg1, pg_sz);
|
||||
if (!retval && driver_pg1.time_stamp_update)
|
||||
|
||||
if (retval)
|
||||
return;
|
||||
|
||||
if (driver_pg1.time_stamp_update)
|
||||
mrioc->ts_update_interval = (driver_pg1.time_stamp_update * 60);
|
||||
|
||||
mrioc->skip_dev_shutdown_on_unload =
|
||||
(le32_to_cpu(driver_pg1.flags) &
|
||||
MPI3_DRIVER1_FLAGS_DEVICE_SHUTDOWN_ON_UNLOAD_DISABLE) ? 1 : 0;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -4453,7 +4562,7 @@ int mpi3mr_init_ioc(struct mpi3mr_ioc *mrioc)
|
|||
goto out_failed_noretry;
|
||||
}
|
||||
|
||||
mpi3mr_read_tsu_interval(mrioc);
|
||||
mpi3mr_read_driver_page1(mrioc);
|
||||
mpi3mr_print_ioc_info(mrioc);
|
||||
|
||||
dprint_init(mrioc, "allocating host diag buffers\n");
|
||||
|
|
@ -4625,7 +4734,7 @@ int mpi3mr_reinit_ioc(struct mpi3mr_ioc *mrioc, u8 is_resume)
|
|||
goto out_failed_noretry;
|
||||
}
|
||||
|
||||
mpi3mr_read_tsu_interval(mrioc);
|
||||
mpi3mr_read_driver_page1(mrioc);
|
||||
mpi3mr_print_ioc_info(mrioc);
|
||||
|
||||
if (is_resume) {
|
||||
|
|
@ -5110,8 +5219,16 @@ static void mpi3mr_issue_ioc_shutdown(struct mpi3mr_ioc *mrioc)
|
|||
return;
|
||||
}
|
||||
|
||||
shutdown_action = MPI3_SYSIF_IOC_CONFIG_SHUTDOWN_NORMAL |
|
||||
MPI3_SYSIF_IOC_CONFIG_DEVICE_SHUTDOWN_SEND_REQ;
|
||||
shutdown_action = MPI3_SYSIF_IOC_CONFIG_SHUTDOWN_NORMAL;
|
||||
|
||||
if (!(mrioc->is_unload && mrioc->skip_dev_shutdown_on_unload))
|
||||
shutdown_action |=
|
||||
MPI3_SYSIF_IOC_CONFIG_DEVICE_SHUTDOWN_SEND_REQ;
|
||||
else
|
||||
ioc_info(mrioc,
|
||||
"The shutdown request is issued without the device shutdown bit set\n"
|
||||
"as indicated by the controller configuration\n");
|
||||
|
||||
ioc_config = readl(&mrioc->sysif_regs->ioc_configuration);
|
||||
ioc_config |= shutdown_action;
|
||||
|
||||
|
|
|
|||
|
|
@ -283,32 +283,6 @@ void mpi3mr_hdb_trigger_data_event(struct mpi3mr_ioc *mrioc,
|
|||
mpi3mr_fwevt_add_to_list(mrioc, fwevt);
|
||||
}
|
||||
|
||||
/**
|
||||
* mpi3mr_fwevt_del_from_list - Delete firmware event from list
|
||||
* @mrioc: Adapter instance reference
|
||||
* @fwevt: Firmware event reference
|
||||
*
|
||||
* Delete the given firmware event from the firmware event list.
|
||||
*
|
||||
* Return: Nothing.
|
||||
*/
|
||||
static void mpi3mr_fwevt_del_from_list(struct mpi3mr_ioc *mrioc,
|
||||
struct mpi3mr_fwevt *fwevt)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&mrioc->fwevt_lock, flags);
|
||||
if (!list_empty(&fwevt->list)) {
|
||||
list_del_init(&fwevt->list);
|
||||
/*
|
||||
* Put fwevt reference count after
|
||||
* removing it from fwevt_list
|
||||
*/
|
||||
mpi3mr_fwevt_put(fwevt);
|
||||
}
|
||||
spin_unlock_irqrestore(&mrioc->fwevt_lock, flags);
|
||||
}
|
||||
|
||||
/**
|
||||
* mpi3mr_dequeue_fwevt - Dequeue firmware event from the list
|
||||
* @mrioc: Adapter instance reference
|
||||
|
|
@ -328,11 +302,7 @@ static struct mpi3mr_fwevt *mpi3mr_dequeue_fwevt(
|
|||
fwevt = list_first_entry(&mrioc->fwevt_list,
|
||||
struct mpi3mr_fwevt, list);
|
||||
list_del_init(&fwevt->list);
|
||||
/*
|
||||
* Put fwevt reference count after
|
||||
* removing it from fwevt_list
|
||||
*/
|
||||
mpi3mr_fwevt_put(fwevt);
|
||||
|
||||
}
|
||||
spin_unlock_irqrestore(&mrioc->fwevt_lock, flags);
|
||||
|
||||
|
|
@ -366,6 +336,11 @@ static void mpi3mr_cancel_work(struct mpi3mr_fwevt *fwevt)
|
|||
*/
|
||||
mpi3mr_fwevt_put(fwevt);
|
||||
}
|
||||
|
||||
/*
|
||||
* Drop the reference count that was acquired by the caller.
|
||||
*/
|
||||
mpi3mr_fwevt_put(fwevt);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -380,17 +355,44 @@ static void mpi3mr_cancel_work(struct mpi3mr_fwevt *fwevt)
|
|||
void mpi3mr_cleanup_fwevt_list(struct mpi3mr_ioc *mrioc)
|
||||
{
|
||||
struct mpi3mr_fwevt *fwevt = NULL;
|
||||
unsigned long flags;
|
||||
|
||||
/*
|
||||
* Safely read current_event under lock to prevent TOCTOU race
|
||||
* with the firmware event worker thread.
|
||||
*/
|
||||
spin_lock_irqsave(&mrioc->fwevt_lock, flags);
|
||||
if ((list_empty(&mrioc->fwevt_list) && !mrioc->current_event) ||
|
||||
!mrioc->fwevt_worker_thread)
|
||||
!mrioc->fwevt_worker_thread) {
|
||||
spin_unlock_irqrestore(&mrioc->fwevt_lock, flags);
|
||||
return;
|
||||
}
|
||||
spin_unlock_irqrestore(&mrioc->fwevt_lock, flags);
|
||||
|
||||
while ((fwevt = mpi3mr_dequeue_fwevt(mrioc)))
|
||||
mpi3mr_cancel_work(fwevt);
|
||||
|
||||
if (mrioc->current_event) {
|
||||
fwevt = mrioc->current_event;
|
||||
/*
|
||||
* Safely read current_event under lock to prevent TOCTOU race
|
||||
* with the firmware event worker thread.
|
||||
*/
|
||||
spin_lock_irqsave(&mrioc->fwevt_lock, flags);
|
||||
fwevt = mrioc->current_event;
|
||||
if (fwevt) {
|
||||
/*
|
||||
* Take a reference to ensure the event is not freed by the
|
||||
* worker thread while we are evaluating or cancelling it.
|
||||
*/
|
||||
mpi3mr_fwevt_get(fwevt);
|
||||
}
|
||||
spin_unlock_irqrestore(&mrioc->fwevt_lock, flags);
|
||||
|
||||
if (fwevt) {
|
||||
bool pending_at_sml;
|
||||
|
||||
/*
|
||||
* Read pending_at_sml under lock to avoid a stale value.
|
||||
*
|
||||
* Don't call cancel_work_sync() API for the
|
||||
* fwevt work if the controller reset is
|
||||
* get called as part of processing the
|
||||
|
|
@ -398,8 +400,13 @@ void mpi3mr_cleanup_fwevt_list(struct mpi3mr_ioc *mrioc)
|
|||
* waiting for device add/remove APIs to complete.
|
||||
* Otherwise we will see deadlock.
|
||||
*/
|
||||
if (current_work() == &fwevt->work || fwevt->pending_at_sml) {
|
||||
spin_lock_irqsave(&mrioc->fwevt_lock, flags);
|
||||
pending_at_sml = fwevt->pending_at_sml;
|
||||
spin_unlock_irqrestore(&mrioc->fwevt_lock, flags);
|
||||
|
||||
if (current_work() == &fwevt->work || pending_at_sml) {
|
||||
fwevt->discard = 1;
|
||||
mpi3mr_fwevt_put(fwevt);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -913,6 +920,8 @@ void mpi3mr_remove_tgtdev_from_host(struct mpi3mr_ioc *mrioc,
|
|||
struct mpi3mr_tgt_dev *tgtdev)
|
||||
{
|
||||
struct mpi3mr_stgt_priv_data *tgt_priv;
|
||||
unsigned long flags;
|
||||
bool discard = false;
|
||||
|
||||
ioc_info(mrioc, "%s :Removing handle(0x%04x), wwid(0x%016llx)\n",
|
||||
__func__, tgtdev->dev_handle, (unsigned long long)tgtdev->wwid);
|
||||
|
|
@ -925,17 +934,27 @@ void mpi3mr_remove_tgtdev_from_host(struct mpi3mr_ioc *mrioc,
|
|||
if (!mrioc->sas_transport_enabled || (tgtdev->dev_type !=
|
||||
MPI3_DEVICE_DEVFORM_SAS_SATA) || tgtdev->non_stl) {
|
||||
if (tgtdev->starget) {
|
||||
spin_lock_irqsave(&mrioc->fwevt_lock, flags);
|
||||
if (mrioc->stop_drv_processing ||
|
||||
mrioc->reset_in_progress) {
|
||||
spin_unlock_irqrestore(&mrioc->fwevt_lock, flags);
|
||||
return;
|
||||
}
|
||||
if (mrioc->current_event)
|
||||
mrioc->current_event->pending_at_sml = 1;
|
||||
spin_unlock_irqrestore(&mrioc->fwevt_lock, flags);
|
||||
scsi_remove_target(&tgtdev->starget->dev);
|
||||
tgtdev->host_exposed = 0;
|
||||
spin_lock_irqsave(&mrioc->fwevt_lock, flags);
|
||||
if (mrioc->current_event) {
|
||||
mrioc->current_event->pending_at_sml = 0;
|
||||
if (mrioc->current_event->discard) {
|
||||
mpi3mr_print_device_event_notice(mrioc,
|
||||
false);
|
||||
return;
|
||||
}
|
||||
discard = mrioc->current_event->discard;
|
||||
}
|
||||
spin_unlock_irqrestore(&mrioc->fwevt_lock, flags);
|
||||
if (discard) {
|
||||
mpi3mr_print_device_event_notice(mrioc,
|
||||
false);
|
||||
return;
|
||||
}
|
||||
}
|
||||
} else
|
||||
|
|
@ -963,6 +982,8 @@ static int mpi3mr_report_tgtdev_to_host(struct mpi3mr_ioc *mrioc,
|
|||
{
|
||||
int retval = 0;
|
||||
struct mpi3mr_tgt_dev *tgtdev;
|
||||
unsigned long flags;
|
||||
bool discard = false;
|
||||
|
||||
if (mrioc->reset_in_progress || mrioc->pci_err_recovery)
|
||||
return -1;
|
||||
|
|
@ -979,19 +1000,29 @@ static int mpi3mr_report_tgtdev_to_host(struct mpi3mr_ioc *mrioc,
|
|||
if (!mrioc->sas_transport_enabled || (tgtdev->dev_type !=
|
||||
MPI3_DEVICE_DEVFORM_SAS_SATA) || tgtdev->non_stl){
|
||||
tgtdev->host_exposed = 1;
|
||||
spin_lock_irqsave(&mrioc->fwevt_lock, flags);
|
||||
if (mrioc->stop_drv_processing || mrioc->reset_in_progress) {
|
||||
spin_unlock_irqrestore(&mrioc->fwevt_lock, flags);
|
||||
tgtdev->host_exposed = 0;
|
||||
goto out;
|
||||
}
|
||||
if (mrioc->current_event)
|
||||
mrioc->current_event->pending_at_sml = 1;
|
||||
spin_unlock_irqrestore(&mrioc->fwevt_lock, flags);
|
||||
scsi_scan_target(&mrioc->shost->shost_gendev,
|
||||
mrioc->scsi_device_channel, tgtdev->perst_id,
|
||||
SCAN_WILD_CARD, SCSI_SCAN_INITIAL);
|
||||
if (!tgtdev->starget)
|
||||
tgtdev->host_exposed = 0;
|
||||
spin_lock_irqsave(&mrioc->fwevt_lock, flags);
|
||||
if (mrioc->current_event) {
|
||||
mrioc->current_event->pending_at_sml = 0;
|
||||
if (mrioc->current_event->discard) {
|
||||
mpi3mr_print_device_event_notice(mrioc, true);
|
||||
goto out;
|
||||
}
|
||||
discard = mrioc->current_event->discard;
|
||||
}
|
||||
spin_unlock_irqrestore(&mrioc->fwevt_lock, flags);
|
||||
if (discard) {
|
||||
mpi3mr_print_device_event_notice(mrioc, true);
|
||||
goto out;
|
||||
}
|
||||
dprint_event_bh(mrioc,
|
||||
"exposed target device with handle(0x%04x), perst_id(%d)\n",
|
||||
|
|
@ -1350,24 +1381,32 @@ static void mpi3mr_update_tgtdev(struct mpi3mr_ioc *mrioc,
|
|||
struct mpi3_device0_pcie_format *pcieinf =
|
||||
&dev_pg0->device_specific.pcie_format;
|
||||
u16 dev_info = le16_to_cpu(pcieinf->device_info);
|
||||
u8 pgsz = MPI3MR_DEFAULT_PGSZEXP;
|
||||
u8 reset_to = MPI3MR_INTADMCMD_TIMEOUT;
|
||||
u8 abort_to = MPI3MR_INTADMCMD_TIMEOUT;
|
||||
u8 fw_pgsz = READ_ONCE(pcieinf->page_size);
|
||||
|
||||
tgtdev->dev_spec.pcie_inf.dev_info = dev_info;
|
||||
tgtdev->dev_spec.pcie_inf.capb =
|
||||
le32_to_cpu(pcieinf->capabilities);
|
||||
tgtdev->dev_spec.pcie_inf.mdts = MPI3MR_DEFAULT_MDTS;
|
||||
/* 2^12 = 4096 */
|
||||
tgtdev->dev_spec.pcie_inf.pgsz = 12;
|
||||
/* Validate firmware page size to prevent undefined shift behavior */
|
||||
if (fw_pgsz >= MPI3MR_DEFAULT_PGSZEXP && fw_pgsz <= MPI3MR_MAX_PGSZEXP)
|
||||
pgsz = fw_pgsz;
|
||||
|
||||
if (dev_pg0->access_status == MPI3_DEVICE0_ASTATUS_NO_ERRORS) {
|
||||
tgtdev->dev_spec.pcie_inf.mdts =
|
||||
le32_to_cpu(pcieinf->maximum_data_transfer_size);
|
||||
tgtdev->dev_spec.pcie_inf.pgsz = pcieinf->page_size;
|
||||
tgtdev->dev_spec.pcie_inf.reset_to =
|
||||
max_t(u8, pcieinf->controller_reset_to,
|
||||
MPI3MR_INTADMCMD_TIMEOUT);
|
||||
tgtdev->dev_spec.pcie_inf.abort_to =
|
||||
max_t(u8, pcieinf->nvme_abort_to,
|
||||
reset_to = max_t(u8, pcieinf->controller_reset_to,
|
||||
MPI3MR_INTADMCMD_TIMEOUT);
|
||||
abort_to = max_t(u8, pcieinf->nvme_abort_to,
|
||||
MPI3MR_INTADMCMD_TIMEOUT);
|
||||
}
|
||||
|
||||
tgtdev->dev_spec.pcie_inf.pgsz = pgsz;
|
||||
tgtdev->dev_spec.pcie_inf.reset_to = reset_to;
|
||||
tgtdev->dev_spec.pcie_inf.abort_to = abort_to;
|
||||
|
||||
if (tgtdev->dev_spec.pcie_inf.mdts > (1024 * 1024))
|
||||
tgtdev->dev_spec.pcie_inf.mdts = (1024 * 1024);
|
||||
if (((dev_info & MPI3_DEVICE0_PCIE_DEVICE_INFO_TYPE_MASK) !=
|
||||
|
|
@ -2126,9 +2165,19 @@ static void mpi3mr_fwevt_bh(struct mpi3mr_ioc *mrioc,
|
|||
u16 perst_id, handle, dev_info;
|
||||
struct mpi3_device0_sas_sata_format *sasinf = NULL;
|
||||
unsigned int timeout;
|
||||
unsigned long flags;
|
||||
|
||||
mpi3mr_fwevt_del_from_list(mrioc, fwevt);
|
||||
spin_lock_irqsave(&mrioc->fwevt_lock, flags);
|
||||
if (!list_empty(&fwevt->list)) {
|
||||
list_del_init(&fwevt->list);
|
||||
/*
|
||||
* Put fwevt reference count after
|
||||
* removing it from fwevt_list
|
||||
*/
|
||||
mpi3mr_fwevt_put(fwevt);
|
||||
}
|
||||
mrioc->current_event = fwevt;
|
||||
spin_unlock_irqrestore(&mrioc->fwevt_lock, flags);
|
||||
|
||||
if (mrioc->stop_drv_processing || mrioc->pci_err_recovery) {
|
||||
dprint_event_bh(mrioc,
|
||||
|
|
@ -2263,9 +2312,12 @@ static void mpi3mr_fwevt_bh(struct mpi3mr_ioc *mrioc,
|
|||
mpi3mr_process_event_ack(mrioc, fwevt->event_id,
|
||||
fwevt->evt_ctx);
|
||||
out:
|
||||
spin_lock_irqsave(&mrioc->fwevt_lock, flags);
|
||||
mrioc->current_event = NULL;
|
||||
spin_unlock_irqrestore(&mrioc->fwevt_lock, flags);
|
||||
|
||||
/* Put fwevt reference count to neutralize kref_init increment */
|
||||
mpi3mr_fwevt_put(fwevt);
|
||||
mrioc->current_event = NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -3484,8 +3536,12 @@ void mpi3mr_process_op_reply_desc(struct mpi3mr_ioc *mrioc,
|
|||
scsi_reply = mpi3mr_get_reply_virt_addr(mrioc,
|
||||
*reply_dma);
|
||||
if (!scsi_reply) {
|
||||
panic("%s: scsi_reply is NULL, this shouldn't happen\n",
|
||||
mrioc->name);
|
||||
ioc_err(mrioc, "scsi_reply is NULL, invalid reply_frame_address\n");
|
||||
/*
|
||||
* Do not let the caller repost an address that
|
||||
* failed virt-addr lookup back to the hardware.
|
||||
*/
|
||||
*reply_dma = 0;
|
||||
goto out;
|
||||
}
|
||||
host_tag = le16_to_cpu(scsi_reply->host_tag);
|
||||
|
|
@ -3982,7 +4038,7 @@ inline void mpi3mr_poll_pend_io_completions(struct mpi3mr_ioc *mrioc)
|
|||
|
||||
for (i = mrioc->op_reply_q_offset; i < num_of_reply_queues; i++)
|
||||
mpi3mr_process_op_reply_q(mrioc,
|
||||
mrioc->intr_info[i].op_reply_q);
|
||||
READ_ONCE(mrioc->intr_info[i].op_reply_q));
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -5730,6 +5786,8 @@ static void mpi3mr_remove(struct pci_dev *pdev)
|
|||
return;
|
||||
|
||||
mrioc = shost_priv(shost);
|
||||
mrioc->is_unload = true;
|
||||
|
||||
while (mrioc->reset_in_progress || mrioc->is_driver_loading)
|
||||
ssleep(1);
|
||||
|
||||
|
|
@ -5862,6 +5920,9 @@ mpi3mr_suspend(struct device *dev)
|
|||
ssleep(1);
|
||||
mrioc->stop_drv_processing = 1;
|
||||
mpi3mr_cleanup_fwevt_list(mrioc);
|
||||
/* Flush any pending discarded event before unmapping PCI resources below. */
|
||||
if (mrioc->fwevt_worker_thread)
|
||||
flush_workqueue(mrioc->fwevt_worker_thread);
|
||||
scsi_block_requests(shost);
|
||||
mpi3mr_stop_watchdog(mrioc);
|
||||
mpi3mr_cleanup_ioc(mrioc);
|
||||
|
|
|
|||
|
|
@ -1223,13 +1223,14 @@ void mpi3mr_sas_host_add(struct mpi3mr_ioc *mrioc)
|
|||
}
|
||||
num_phys = sas_io_unit_pg0->num_phys;
|
||||
kfree(sas_io_unit_pg0);
|
||||
sas_io_unit_pg0 = NULL;
|
||||
|
||||
mrioc->sas_hba.host_node = 1;
|
||||
INIT_LIST_HEAD(&mrioc->sas_hba.sas_port_list);
|
||||
mrioc->sas_hba.parent_dev = &mrioc->shost->shost_gendev;
|
||||
mrioc->sas_hba.phy = kzalloc_objs(struct mpi3mr_sas_phy, num_phys);
|
||||
if (!mrioc->sas_hba.phy)
|
||||
return;
|
||||
goto out;
|
||||
|
||||
mrioc->sas_hba.num_phys = num_phys;
|
||||
|
||||
|
|
@ -1237,12 +1238,12 @@ void mpi3mr_sas_host_add(struct mpi3mr_ioc *mrioc)
|
|||
(num_phys * sizeof(struct mpi3_sas_io_unit0_phy_data));
|
||||
sas_io_unit_pg0 = kzalloc(sz, GFP_KERNEL);
|
||||
if (!sas_io_unit_pg0)
|
||||
return;
|
||||
goto out_free_phy;
|
||||
|
||||
if (mpi3mr_cfg_get_sas_io_unit_pg0(mrioc, sas_io_unit_pg0, sz)) {
|
||||
ioc_err(mrioc, "failure at %s:%d/%s()!\n",
|
||||
__FILE__, __LINE__, __func__);
|
||||
goto out;
|
||||
goto out_free_phy;
|
||||
}
|
||||
|
||||
mrioc->sas_hba.handle = 0;
|
||||
|
|
@ -1256,12 +1257,12 @@ void mpi3mr_sas_host_add(struct mpi3mr_ioc *mrioc)
|
|||
MPI3_SAS_PHY_PGAD_FORM_PHY_NUMBER, i)) {
|
||||
ioc_err(mrioc, "failure at %s:%d/%s()!\n",
|
||||
__FILE__, __LINE__, __func__);
|
||||
goto out;
|
||||
goto out_free_phy;
|
||||
}
|
||||
if (ioc_status != MPI3_IOCSTATUS_SUCCESS) {
|
||||
ioc_err(mrioc, "failure at %s:%d/%s()!\n",
|
||||
__FILE__, __LINE__, __func__);
|
||||
goto out;
|
||||
goto out_free_phy;
|
||||
}
|
||||
|
||||
if (!mrioc->sas_hba.handle)
|
||||
|
|
@ -1271,26 +1272,27 @@ void mpi3mr_sas_host_add(struct mpi3mr_ioc *mrioc)
|
|||
|
||||
if (!(mpi3mr_get_hba_port_by_id(mrioc, port_id)))
|
||||
if (!mpi3mr_alloc_hba_port(mrioc, port_id))
|
||||
goto out;
|
||||
goto out_free_phy;
|
||||
|
||||
mrioc->sas_hba.phy[i].handle = mrioc->sas_hba.handle;
|
||||
mrioc->sas_hba.phy[i].phy_id = i;
|
||||
mrioc->sas_hba.phy[i].hba_port =
|
||||
mpi3mr_get_hba_port_by_id(mrioc, port_id);
|
||||
mpi3mr_add_host_phy(mrioc, &mrioc->sas_hba.phy[i],
|
||||
phy_pg0, mrioc->sas_hba.parent_dev);
|
||||
if (mpi3mr_add_host_phy(mrioc, &mrioc->sas_hba.phy[i],
|
||||
phy_pg0, mrioc->sas_hba.parent_dev))
|
||||
goto out_free_phy;
|
||||
}
|
||||
if ((mpi3mr_cfg_get_dev_pg0(mrioc, &ioc_status, &dev_pg0,
|
||||
sizeof(dev_pg0), MPI3_DEVICE_PGAD_FORM_HANDLE,
|
||||
mrioc->sas_hba.handle))) {
|
||||
ioc_err(mrioc, "%s: device page0 read failed\n", __func__);
|
||||
goto out;
|
||||
goto out_free_phy;
|
||||
}
|
||||
if (ioc_status != MPI3_IOCSTATUS_SUCCESS) {
|
||||
ioc_err(mrioc, "device page read failed for handle(0x%04x), with ioc_status(0x%04x) failure at %s:%d/%s()!\n",
|
||||
mrioc->sas_hba.handle, ioc_status, __FILE__, __LINE__,
|
||||
__func__);
|
||||
goto out;
|
||||
goto out_free_phy;
|
||||
}
|
||||
mrioc->sas_hba.enclosure_handle =
|
||||
le16_to_cpu(dev_pg0.enclosure_handle);
|
||||
|
|
@ -1313,6 +1315,17 @@ void mpi3mr_sas_host_add(struct mpi3mr_ioc *mrioc)
|
|||
le64_to_cpu(encl_pg0.enclosure_logical_id);
|
||||
}
|
||||
|
||||
goto out;
|
||||
|
||||
out_free_phy:
|
||||
for (i = 0; i < mrioc->sas_hba.num_phys; i++) {
|
||||
if (mrioc->sas_hba.phy[i].phy)
|
||||
sas_phy_delete(mrioc->sas_hba.phy[i].phy);
|
||||
}
|
||||
kfree(mrioc->sas_hba.phy);
|
||||
mrioc->sas_hba.phy = NULL;
|
||||
mrioc->sas_hba.num_phys = 0;
|
||||
|
||||
out:
|
||||
kfree(sas_io_unit_pg0);
|
||||
}
|
||||
|
|
@ -1337,6 +1350,7 @@ static struct mpi3mr_sas_port *mpi3mr_sas_port_add(struct mpi3mr_ioc *mrioc,
|
|||
struct mpi3mr_sas_phy *mr_sas_phy, *next;
|
||||
struct mpi3mr_sas_port *mr_sas_port;
|
||||
unsigned long flags;
|
||||
bool discard = false;
|
||||
struct mpi3mr_sas_node *mr_sas_node;
|
||||
struct sas_rphy *rphy;
|
||||
struct mpi3mr_tgt_dev *tgtdev = NULL;
|
||||
|
|
@ -1435,9 +1449,15 @@ static struct mpi3mr_sas_port *mpi3mr_sas_port_add(struct mpi3mr_ioc *mrioc,
|
|||
}
|
||||
|
||||
port = sas_port_alloc_num(mr_sas_node->parent_dev);
|
||||
if (!port) {
|
||||
ioc_err(mrioc, "failure at %s:%d/%s() (sas_port_alloc)!\n",
|
||||
__FILE__, __LINE__, __func__);
|
||||
goto out_fail;
|
||||
}
|
||||
if ((sas_port_add(port))) {
|
||||
ioc_err(mrioc, "failure at %s:%d/%s()!\n",
|
||||
__FILE__, __LINE__, __func__);
|
||||
sas_port_free(port);
|
||||
goto out_fail;
|
||||
}
|
||||
|
||||
|
|
@ -1457,19 +1477,51 @@ static struct mpi3mr_sas_port *mpi3mr_sas_port_add(struct mpi3mr_ioc *mrioc,
|
|||
mr_sas_port->port = port;
|
||||
if (mr_sas_port->remote_identify.device_type == SAS_END_DEVICE) {
|
||||
rphy = sas_end_device_alloc(port);
|
||||
if (!rphy) {
|
||||
ioc_err(mrioc, "failure at %s:%d/%s() (sas_end_device_alloc)!\n",
|
||||
__FILE__, __LINE__, __func__);
|
||||
sas_port_delete(port);
|
||||
goto out_fail;
|
||||
}
|
||||
tgtdev->dev_spec.sas_sata_inf.rphy = rphy;
|
||||
} else {
|
||||
rphy = sas_expander_alloc(port,
|
||||
mr_sas_port->remote_identify.device_type);
|
||||
if (!rphy) {
|
||||
ioc_err(mrioc, "failure at %s:%d/%s() (sas_expander_alloc)!\n",
|
||||
__FILE__, __LINE__, __func__);
|
||||
sas_port_delete(port);
|
||||
goto out_fail;
|
||||
}
|
||||
}
|
||||
rphy->identify = mr_sas_port->remote_identify;
|
||||
|
||||
spin_lock_irqsave(&mrioc->fwevt_lock, flags);
|
||||
if (mrioc->stop_drv_processing || mrioc->reset_in_progress) {
|
||||
spin_unlock_irqrestore(&mrioc->fwevt_lock, flags);
|
||||
sas_rphy_free(rphy);
|
||||
sas_port_delete(port);
|
||||
goto out_fail;
|
||||
}
|
||||
if (mrioc->current_event)
|
||||
mrioc->current_event->pending_at_sml = 1;
|
||||
spin_unlock_irqrestore(&mrioc->fwevt_lock, flags);
|
||||
|
||||
if ((sas_rphy_add(rphy))) {
|
||||
ioc_err(mrioc, "failure at %s:%d/%s()!\n",
|
||||
__FILE__, __LINE__, __func__);
|
||||
spin_lock_irqsave(&mrioc->fwevt_lock, flags);
|
||||
if (mrioc->current_event) {
|
||||
mrioc->current_event->pending_at_sml = 0;
|
||||
discard = mrioc->current_event->discard;
|
||||
}
|
||||
spin_unlock_irqrestore(&mrioc->fwevt_lock, flags);
|
||||
if (discard)
|
||||
mpi3mr_print_device_event_notice(mrioc, true);
|
||||
sas_rphy_unlink(rphy);
|
||||
sas_rphy_free(rphy);
|
||||
sas_port_delete(port);
|
||||
goto out_fail;
|
||||
}
|
||||
if (mr_sas_port->remote_identify.device_type == SAS_END_DEVICE) {
|
||||
tgtdev->dev_spec.sas_sata_inf.pend_sas_rphy_add = 0;
|
||||
|
|
@ -1487,11 +1539,14 @@ static struct mpi3mr_sas_port *mpi3mr_sas_port_add(struct mpi3mr_ioc *mrioc,
|
|||
list_add_tail(&mr_sas_port->port_list, &mr_sas_node->sas_port_list);
|
||||
spin_unlock_irqrestore(&mrioc->sas_node_lock, flags);
|
||||
|
||||
spin_lock_irqsave(&mrioc->fwevt_lock, flags);
|
||||
if (mrioc->current_event) {
|
||||
mrioc->current_event->pending_at_sml = 0;
|
||||
if (mrioc->current_event->discard)
|
||||
mpi3mr_print_device_event_notice(mrioc, true);
|
||||
discard = mrioc->current_event->discard;
|
||||
}
|
||||
spin_unlock_irqrestore(&mrioc->fwevt_lock, flags);
|
||||
if (discard)
|
||||
mpi3mr_print_device_event_notice(mrioc, true);
|
||||
|
||||
/* fill in report manufacture */
|
||||
if (mr_sas_port->remote_identify.device_type ==
|
||||
|
|
@ -1505,9 +1560,17 @@ static struct mpi3mr_sas_port *mpi3mr_sas_port_add(struct mpi3mr_ioc *mrioc,
|
|||
return mr_sas_port;
|
||||
|
||||
out_fail:
|
||||
if (tgtdev) {
|
||||
tgtdev->dev_spec.sas_sata_inf.pend_sas_rphy_add = 0;
|
||||
tgtdev->dev_spec.sas_sata_inf.rphy = NULL;
|
||||
mpi3mr_tgtdev_put(tgtdev);
|
||||
}
|
||||
|
||||
list_for_each_entry_safe(mr_sas_phy, next, &mr_sas_port->phy_list,
|
||||
port_siblings)
|
||||
port_siblings) {
|
||||
mr_sas_phy->phy_belongs_to_port = 0;
|
||||
list_del(&mr_sas_phy->port_siblings);
|
||||
}
|
||||
kfree(mr_sas_port);
|
||||
return NULL;
|
||||
}
|
||||
|
|
@ -1529,6 +1592,7 @@ static void mpi3mr_sas_port_remove(struct mpi3mr_ioc *mrioc, u64 sas_address,
|
|||
{
|
||||
int i;
|
||||
unsigned long flags;
|
||||
bool discard = false;
|
||||
struct mpi3mr_sas_port *mr_sas_port, *next;
|
||||
struct mpi3mr_sas_node *mr_sas_node;
|
||||
u8 found = 0;
|
||||
|
|
@ -1585,8 +1649,10 @@ static void mpi3mr_sas_port_remove(struct mpi3mr_ioc *mrioc, u64 sas_address,
|
|||
|
||||
spin_unlock_irqrestore(&mrioc->sas_node_lock, flags);
|
||||
|
||||
spin_lock_irqsave(&mrioc->fwevt_lock, flags);
|
||||
if (mrioc->current_event)
|
||||
mrioc->current_event->pending_at_sml = 1;
|
||||
spin_unlock_irqrestore(&mrioc->fwevt_lock, flags);
|
||||
|
||||
list_for_each_entry_safe(mr_sas_phy, next_phy,
|
||||
&mr_sas_port->phy_list, port_siblings) {
|
||||
|
|
@ -1608,11 +1674,14 @@ static void mpi3mr_sas_port_remove(struct mpi3mr_ioc *mrioc, u64 sas_address,
|
|||
ioc_info(mrioc, "%s: removed sas_address(0x%016llx)\n",
|
||||
__func__, (unsigned long long)sas_address);
|
||||
|
||||
spin_lock_irqsave(&mrioc->fwevt_lock, flags);
|
||||
if (mrioc->current_event) {
|
||||
mrioc->current_event->pending_at_sml = 0;
|
||||
if (mrioc->current_event->discard)
|
||||
mpi3mr_print_device_event_notice(mrioc, false);
|
||||
discard = mrioc->current_event->discard;
|
||||
}
|
||||
spin_unlock_irqrestore(&mrioc->fwevt_lock, flags);
|
||||
if (discard)
|
||||
mpi3mr_print_device_event_notice(mrioc, false);
|
||||
|
||||
kfree(mr_sas_port);
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user