From: Dongdong Hao <doubled@leap-io-kernel.com> LeapIO inclusion category: feature bugzilla: https://atomgit.com/openeuler/kernel/issues/9234 ------------------------------------------ leapraid driver changes from v2.0.0.6 to v2.0.1.2. This update includes: - overheat handling rework - reset flow stabilization - improved timeout diagnostics - sysfs enhancement - topology and transport error-path fixes - memory leak/UAF/reference leak fixes - mmap/ioctl validation fixes - improved queue depth handling - improved interrupt and resource cleanup logic The update also fixes several race conditions and improves overall driver robustness under reset, topology change, and controller abnormal scenarios. Signed-off-by: Dongdong Hao <doubled@leap-io-kernel.com> --- drivers/scsi/leapraid/Kconfig | 2 +- drivers/scsi/leapraid/leapraid.h | 1335 +++--- drivers/scsi/leapraid/leapraid_app.c | 529 +-- drivers/scsi/leapraid/leapraid_func.c | 4237 ++++++++++++-------- drivers/scsi/leapraid/leapraid_func.h | 1086 ++--- drivers/scsi/leapraid/leapraid_os.c | 889 ++-- drivers/scsi/leapraid/leapraid_transport.c | 485 ++- 7 files changed, 4859 insertions(+), 3704 deletions(-) diff --git a/drivers/scsi/leapraid/Kconfig b/drivers/scsi/leapraid/Kconfig index b539183b24a7..f4ece78f80d3 100644 --- a/drivers/scsi/leapraid/Kconfig +++ b/drivers/scsi/leapraid/Kconfig @@ -5,7 +5,7 @@ config SCSI_LEAPRAID depends on PCI && SCSI select SCSI_SAS_ATTRS help - This driver supports LeapIO PCIe-based Storage + This driver supports LeapIO PCIe-based storage and RAID controllers. <http://www.leap-io.com> diff --git a/drivers/scsi/leapraid/leapraid.h b/drivers/scsi/leapraid/leapraid.h index 77bb93b79254..2a99417143ad 100644 --- a/drivers/scsi/leapraid/leapraid.h +++ b/drivers/scsi/leapraid/leapraid.h @@ -1,13 +1,13 @@ /* SPDX-License-Identifier: GPL-2.0 */ /* - * Copyright (C) 2025 LeapIO Tech Inc. + * Copyright (C) 2026 LeapIO Tech Inc. * - * LeapRAID Storage and RAID Controller driver. + * LeapRAID storage and RAID controller driver. */ #ifndef LEAPRAID_H #define LEAPRAID_H -/* doorbell register definitions */ +/* Doorbell register definitions. */ #define LEAPRAID_DB_RESET 0x00000000 #define LEAPRAID_DB_READY 0x10000000 #define LEAPRAID_DB_OPERATIONAL 0x20000000 @@ -22,55 +22,60 @@ #define LEAPRAID_DB_FUNC_SHIFT 24 #define LEAPRAID_DB_ADD_DWORDS_SHIFT 16 -/* maximum number of retries waiting for doorbell to become ready */ +/* Maximum number of retries waiting for doorbell to become ready. */ #define LEAPRAID_DB_RETRY_COUNT_MAX 10 -/* maximum number of retries waiting for doorbell to become operational */ -#define LEAPRAID_DB_WAIT_OPERATIONAL 10 -/* sleep interval (in seconds) between doorbell polls */ +/* Maximum number of retries waiting for doorbell to become operational. */ +#define LEAPRAID_DB_WAIT_OP_SHORT 10 +#define LEAPRAID_DB_WAIT_OP_LONG 200 +/* Sleep interval (in seconds) between doorbell polls. */ #define LEAPRAID_DB_POLL_INTERVAL_S 1 -/* maximum number of retries waiting for host to end recovery */ -#define LEAPRAID_WAIT_SHOST_RECOVERY 30 +/* Maximum number of retries waiting for host to end recovery. */ +#define LEAPRAID_WAIT_SHOST_RECOVERY 400 -/* diagnostic register definitions */ +/* Diagnostic register definitions. */ #define LEAPRAID_DIAG_WRITE_ENABLE 0x00000080 #define LEAPRAID_DIAG_RESET 0x00000004 -#define LEAPRAID_DIAG_HOLD_ADAPTER_RESET 0x00000002 -/* interrupt status register definitions */ +/* Interrupt status register definitions. */ #define LEAPRAID_HOST2ADAPTER_DB_STATUS 0x80000000 #define LEAPRAID_ADAPTER2HOST_DB_STATUS 0x00000001 -/* the number of debug register */ +/* The number of debug register. */ #define LEAPRAID_DEBUGLOG_SZ_MAX 16 +#define LEAPRAID_DEBUGLOG_DWORDS_PER_LINE 4 -/* reply post host register defines */ +/* Reply post host register definitions. */ #define REP_POST_HOST_IDX_REG_CNT 16 #define LEAPRAID_RPHI_MSIX_IDX_SHIFT 24 -/* vphy flags */ +/* Virtual PHY flags. */ #define LEAPRAID_SAS_PHYINFO_VPHY 0x00001000 -/* linux driver init fw */ +/* Linux driver init firmware. */ #define LEAPRAID_WHOINIT_LINUX_DRIVER 0x04 -/* rdpq array mode */ +/* Reply descriptor post queue array mode. */ #define LEAPRAID_ADAPTER_INIT_MSGFLG_RDPQ_ARRAY_MODE 0x01 -/* request description flags */ +/* Request description flags. */ #define LEAPRAID_REQ_DESC_FLG_SCSI_IO 0x00 #define LEAPRAID_REQ_DESC_FLG_HPR 0x06 #define LEAPRAID_REQ_DESC_FLG_DFLT_TYPE 0x08 -/* reply description flags */ +/* Reply description flags. */ #define LEAPRAID_RPY_DESC_FLG_TYPE_MASK 0x0F #define LEAPRAID_RPY_DESC_FLG_SCSI_IO_SUCCESS 0x00 #define LEAPRAID_RPY_DESC_FLG_ADDRESS_REPLY 0x01 #define LEAPRAID_RPY_DESC_FLG_FP_SCSI_IO_SUCCESS 0x06 #define LEAPRAID_RPY_DESC_FLG_UNUSED 0x0F -/* MPI functions */ -#define LEAPRAID_FUNC_SCSIIO_REQ 0x00 +/* Request and reply messages share the same set of function codes. + * + * Note: SCSIIO (SCSI I/O) represents SCSI I/O operations and is used + * consistently throughout the driver for all SCSI command handling. + */ +#define LEAPRAID_FUNC_SCSIIO 0x00 #define LEAPRAID_FUNC_SCSI_TMF 0x01 #define LEAPRAID_FUNC_ADAPTER_INIT 0x02 #define LEAPRAID_FUNC_GET_ADAPTER_FEATURES 0x03 @@ -79,17 +84,16 @@ #define LEAPRAID_FUNC_EVENT_NOTIFY 0x07 #define LEAPRAID_FUNC_FW_DOWNLOAD 0x09 #define LEAPRAID_FUNC_FW_UPLOAD 0x12 -#define LEAPRAID_FUNC_RAID_ACTION 0x15 -#define LEAPRAID_FUNC_RAID_SCSIIO_PASSTHROUGH 0x16 +#define LEAPRAID_FUNC_SCSIIO_RAID_PASSTHROUGH 0x16 #define LEAPRAID_FUNC_SCSI_ENC_PROCESSOR 0x18 #define LEAPRAID_FUNC_SMP_PASSTHROUGH 0x1A #define LEAPRAID_FUNC_SAS_IO_UNIT_CTRL 0x1B -#define LEAPRAID_FUNC_SATA_PASSTHROUGH 0x1C +#define LEAPRAID_FUNC_SCSIIO_SATA_PASSTHROUGH 0x1C #define LEAPRAID_FUNC_ADAPTER_UNIT_RESET 0x40 #define LEAPRAID_FUNC_HANDSHAKE 0x42 #define LEAPRAID_FUNC_LOGBUF_INIT 0x57 -/* adapter status values */ +/* Adapter status values. */ #define LEAPRAID_ADAPTER_STATUS_MASK 0x7FFF #define LEAPRAID_ADAPTER_STATUS_SUCCESS 0x0000 #define LEAPRAID_ADAPTER_STATUS_BUSY 0x0002 @@ -113,7 +117,7 @@ #define LEAPRAID_ADAPTER_STATUS_SCSI_ADAPTER_TERMINATED 0x004B #define LEAPRAID_ADAPTER_STATUS_SCSI_EXT_TERMINATED 0x004C -/* sge flags */ +/* SGE flags. */ #define LEAPRAID_SGE_FLG_LAST_ONE 0x80 #define LEAPRAID_SGE_FLG_EOB 0x40 #define LEAPRAID_SGE_FLG_EOL 0x01 @@ -129,15 +133,19 @@ #define LEAPRAID_IEEE_SGE_FLG_CHAIN_ONE 0x80 #define LEAPRAID_IEEE_SGE_FLG_SYSTEM_ADDR 0x00 -#define LEAPRAID_SGE_OFFSET_SIZE 4 +#define LEAPRAID_SGE_NO_DATA_ADDR -1 +#define LEAPRAID_SGE_OFFSET_SIZE 4 -/* page and ext page type */ +/* The type of page. */ #define LEAPRAID_CFG_PT_IO_UNIT 0x00 #define LEAPRAID_CFG_PT_ADAPTER 0x01 #define LEAPRAID_CFG_PT_BIOS 0x02 #define LEAPRAID_CFG_PT_RAID_VOLUME 0x08 +#define LEAPRAID_CFG_PT_MANUFACTURING 0x09 #define LEAPRAID_CFG_PT_RAID_PHYSDISK 0x0A #define LEAPRAID_CFG_PT_EXTENDED 0x0F + +/* The type of extended page. */ #define LEAPRAID_CFG_EXTPT_SAS_IO_UNIT 0x10 #define LEAPRAID_CFG_EXTPT_SAS_EXP 0x11 #define LEAPRAID_CFG_EXTPT_SAS_DEV 0x12 @@ -145,7 +153,7 @@ #define LEAPRAID_CFG_EXTPT_ENC 0x15 #define LEAPRAID_CFG_EXTPT_RAID_CONFIG 0x16 -/* config page address */ +/* Config page address. */ #define LEAPRAID_SAS_CFG_PGAD_GET_NEXT_LOOP 0x00000000 #define LEAPRAID_SAS_ENC_CFG_PGAD_HDL 0x10000000 #define LEAPRAID_SAS_DEV_CFG_PGAD_HDL 0x20000000 @@ -156,51 +164,55 @@ #define LEAPRAID_SAS_PHY_CFG_PGAD_PHY_NUMBER 0x00000000 #define LEAPRAID_PHYSDISK_CFG_PGAD_PHYSDISKNUM 0x10000000 -/* config page operations */ +/* Config page operations. */ #define LEAPRAID_CFG_ACT_PAGE_HEADER 0x00 #define LEAPRAID_CFG_ACT_PAGE_READ_CUR 0x01 #define LEAPRAID_CFG_ACT_PAGE_WRITE_CUR 0x02 -/* bios pages */ +/* BIOS page number. */ #define LEAPRAID_CFG_PAGE_NUM_BIOS2 0x2 #define LEAPRAID_CFG_PAGE_NUM_BIOS3 0x3 -/* sas device pages */ +/* Manufacturing page number. */ +#define LEAPRAID_CFG_PAGE_NUM_MANU0 0x0 + +/* SAS device page number. */ #define LEAPRAID_CFG_PAGE_NUM_DEV0 0x0 -/* sas device page 0 flags */ +/* SAS device page 0 flags. */ #define LEAPRAID_SAS_DEV_P0_FLG_FP_CAP 0x2000 #define LEAPRAID_SAS_DEV_P0_FLG_SATA_SMART 0x0040 #define LEAPRAID_SAS_DEV_P0_FLG_ENC_LEVEL_VALID 0x0002 #define LEAPRAID_SAS_DEV_P0_FLG_DEV_PRESENT 0x0001 +#define LEAPRAID_SAS_DEV_P0_CON_NAME_LEN 4 -/* sas IO unit pages */ +/* SAS I/O unit page number. */ #define LEAPRAID_CFG_PAGE_NUM_IOUNIT0 0x0 #define LEAPRAID_CFG_PAGE_NUM_IOUNIT1 0x1 -/* sas expander pages */ +/* SAS expander page number. */ #define LEAPRAID_CFG_PAGE_NUM_EXP0 0x0 #define LEAPRAID_CFG_PAGE_NUM_EXP1 0x1 -/* sas enclosure page */ +/* SAS enclosure page number. */ #define LEAPRAID_CFG_PAGE_NUM_ENC0 0x0 -/* sas phy page */ +/* SAS PHY page number. */ #define LEAPRAID_CFG_PAGE_NUM_PHY0 0x0 -/* raid volume pages */ +/* RAID volume page number. */ #define LEAPRAID_CFG_PAGE_NUM_VOL0 0x0 #define LEAPRAID_CFG_PAGE_NUM_VOL1 0x1 -/* physical disk page */ +/* Physical disk page number. */ #define LEAPRAID_CFG_PAGE_NUM_PD0 0x0 -/* adapter page */ +/* Adapter page number. */ #define LEAPRAID_CFG_PAGE_NUM_ADAPTER1 0x1 #define LEAPRAID_CFG_UNIT_SIZE 4 -/* raid volume type and state */ +/* Raid volume type and state. */ #define LEAPRAID_VOL_STATE_MISSING 0x00 #define LEAPRAID_VOL_STATE_FAILED 0x01 #define LEAPRAID_VOL_STATE_INITIALIZING 0x02 @@ -213,17 +225,17 @@ #define LEAPRAID_VOL_TYPE_RAID10 0x05 #define LEAPRAID_VOL_TYPE_UNKNOWN 0xFF -/* raid volume element flags */ +/* Raid volume element flags. */ #define LEAPRAID_RAIDCFG_P0_EFLG_MASK_ELEMENT_TYPE 0x000F #define LEAPRAID_RAIDCFG_P0_EFLG_VOL_PHYS_DISK_ELEMENT 0x0001 #define LEAPRAID_RAIDCFG_P0_EFLG_HOT_SPARE_ELEMENT 0x0002 #define LEAPRAID_RAIDCFG_P0_EFLG_OCE_ELEMENT 0x0003 -/* raid action */ +/* Raid action. */ #define LEAPRAID_RAID_ACT_SYSTEM_SHUTDOWN_INITIATED 0x20 #define LEAPRAID_RAID_ACT_PHYSDISK_HIDDEN 0x24 -/* sas negotiated link rates */ +/* SAS negotiated link rates. */ #define LEAPRAID_SAS_NEG_LINK_RATE_MASK_PHYSICAL 0x0F #define LEAPRAID_SAS_NEG_LINK_RATE_UNKNOWN_LINK_RATE 0x00 #define LEAPRAID_SAS_NEG_LINK_RATE_PHY_DISABLED 0x01 @@ -231,6 +243,7 @@ #define LEAPRAID_SAS_NEG_LINK_RATE_SATA_OOB_COMPLETE 0x03 #define LEAPRAID_SAS_NEG_LINK_RATE_PORT_SELECTOR 0x04 #define LEAPRAID_SAS_NEG_LINK_RATE_SMP_RESETTING 0x05 +#define LEAPRAID_SAS_NEG_LINK_RATE_SHIFT 4 #define LEAPRAID_SAS_NEG_LINK_RATE_1_5 0x08 #define LEAPRAID_SAS_NEG_LINK_RATE_3_0 0x09 @@ -240,8 +253,11 @@ #define LEAPRAID_SAS_PRATE_MIN_RATE_MASK 0x0F #define LEAPRAID_SAS_HWRATE_MIN_RATE_MASK 0x0F -/* scsi IO control bits */ -#define LEAPRAID_SCSIIO_CTRL_ADDCDBLEN_SHIFT 26 +/* + * Control flags for a SCSI I/O Request. + */ +#define LEAPRAID_SCSIIO_CTRL_CDB_32BYTE 4 +#define LEAPRAID_SCSIIO_CTRL_CDB_LEN_SHIFT 26 #define LEAPRAID_SCSIIO_CTRL_NODATATRANSFER 0x00000000 #define LEAPRAID_SCSIIO_CTRL_WRITE 0x01000000 #define LEAPRAID_SCSIIO_CTRL_READ 0x02000000 @@ -250,7 +266,7 @@ #define LEAPRAID_SCSIIO_CTRL_ORDEREDQ 0x00000200 #define LEAPRAID_SCSIIO_CTRL_CMDPRI 0x00000800 -/* scsi state and status */ +/* SCSI state and status. */ #define LEAPRAID_SCSI_STATUS_BUSY 0x08 #define LEAPRAID_SCSI_STATUS_RESERVATION_CONFLICT 0x18 #define LEAPRAID_SCSI_STATUS_TASK_SET_FULL 0x28 @@ -261,7 +277,7 @@ #define LEAPRAID_SCSI_STATE_AUTOSENSE_FAILED 0x02 #define LEAPRAID_SCSI_STATE_AUTOSENSE_VALID 0x01 -/* scsi task management defines */ +/* SCSI task management defines. */ #define LEAPRAID_TM_TASKTYPE_ABORT_TASK 0x01 #define LEAPRAID_TM_TASKTYPE_ABRT_TASK_SET 0x02 #define LEAPRAID_TM_TASKTYPE_TARGET_RESET 0x03 @@ -277,21 +293,20 @@ #define LEAPRAID_TM_RSP_TM_SUCCEEDED 0x08 #define LEAPRAID_TM_RSP_IO_QUEUED_ON_ADAPTER 0x80 -/* scsi sep request defines */ +/* SCSI enclosure processor request defines. */ #define LEAPRAID_SEP_REQ_ACT_WRITE_STATUS 0x00 #define LEAPRAID_SEP_REQ_FLG_DEVHDL_ADDRESS 0x00 #define LEAPRAID_SEP_REQ_FLG_ENCLOSURE_SLOT_ADDRESS 0x01 #define LEAPRAID_SEP_REQ_SLOTSTATUS_PREDICTED_FAULT 0x00000040 -/* the capabilities of the adapter */ +/* The capabilities of the adapter. */ #define LEAPRAID_ADAPTER_FEATURES_CAP_ATOMIC_REQ 0x00080000 #define LEAPRAID_ADAPTER_FEATURES_CAP_RDPQ_ARRAY_CAPABLE 0x00040000 #define LEAPRAID_ADAPTER_FEATURES_CAP_EVENT_REPLAY 0x00002000 #define LEAPRAID_ADAPTER_FEATURES_CAP_INTEGRATED_RAID 0x00001000 -/* event code definitions for the firmware */ +/* Event code definitions for the firmware. */ #define LEAPRAID_EVT_SAS_DEV_STATUS_CHANGE 0x000F -#define LEAPRAID_EVT_SAS_DISCOVERY 0x0016 #define LEAPRAID_EVT_SAS_TOPO_CHANGE_LIST 0x001C #define LEAPRAID_EVT_SAS_ENCL_DEV_STATUS_CHANGE 0x001D #define LEAPRAID_EVT_IR_CHANGE 0x0020 @@ -303,7 +318,7 @@ #define LEAPRAID_EVT_SAS_DEV_STAT_RC_INTERNAL_DEV_RESET 0x08 #define LEAPRAID_EVT_SAS_DEV_STAT_RC_CMP_INTERNAL_DEV_RESET 0x0E -/* raid configuration change event */ +/* RAID configuration change event. */ #define LEAPRAID_EVT_IR_RC_VOLUME_ADD 0x01 #define LEAPRAID_EVT_IR_RC_VOLUME_DELETE 0x02 #define LEAPRAID_EVT_IR_RC_PD_HIDDEN_TO_ADD 0x03 @@ -313,27 +328,25 @@ #define LEAPRAID_EVT_IR_RC_VOLUME_HIDE 0x0A #define LEAPRAID_EVT_IR_RC_VOLUME_UNHIDE 0x0B -/* sas topology change event */ +/* SAS topology change event. */ #define LEAPRAID_EVT_SAS_TOPO_ES_NO_EXPANDER 0x00 #define LEAPRAID_EVT_SAS_TOPO_ES_ADDED 0x01 #define LEAPRAID_EVT_SAS_TOPO_ES_NOT_RESPONDING 0x02 #define LEAPRAID_EVT_SAS_TOPO_ES_RESPONDING 0x03 #define LEAPRAID_EVT_SAS_TOPO_RC_MASK 0x0F -#define LEAPRAID_EVT_SAS_TOPO_RC_CLEAR_MASK 0xF0 #define LEAPRAID_EVT_SAS_TOPO_RC_TARG_ADDED 0x01 #define LEAPRAID_EVT_SAS_TOPO_RC_TARG_NOT_RESPONDING 0x02 -#define LEAPRAID_EVT_SAS_TOPO_RC_PHY_CHANGED 0x03 -/* sas discovery event defines */ +/* SAS discovery event defines. */ #define LEAPRAID_EVT_SAS_DISC_RC_STARTED 0x01 #define LEAPRAID_EVT_SAS_DISC_RC_COMPLETED 0x02 -/* enclosure device status change event */ +/* Enclosure device status change event. */ #define LEAPRAID_EVT_SAS_ENCL_RC_ADDED 0x01 #define LEAPRAID_EVT_SAS_ENCL_RC_NOT_RESPONDING 0x02 -/* device type and identifiers */ +/* Device type and identifiers. */ #define LEAPRAID_DEVTYP_SEP 0x00004000 #define LEAPRAID_DEVTYP_SSP_TGT 0x00000400 #define LEAPRAID_DEVTYP_STP_TGT 0x00000200 @@ -350,12 +363,12 @@ #define LEAPRAID_DEVTYP_EDGE_EXPANDER 0x00000002 #define LEAPRAID_DEVTYP_FANOUT_EXPANDER 0x00000003 -/* sas control operation */ +/* SAS control operation. */ #define LEAPRAID_SAS_OP_PHY_LINK_RESET 0x06 #define LEAPRAID_SAS_OP_PHY_HARD_RESET 0x07 #define LEAPRAID_SAS_OP_SET_PARAMETER 0x0F -/* boot device defines */ +/* Boot device defines */ #define LEAPRAID_BOOTDEV_FORM_MASK 0x0F #define LEAPRAID_BOOTDEV_FORM_NONE 0x00 #define LEAPRAID_BOOTDEV_FORM_SAS_WWID 0x05 @@ -365,21 +378,21 @@ /** * struct leapraid_reg_base - Register layout of the LeapRAID controller * - * @db: Doorbell register used to signal commands or status to firmware - * @ws: Write sequence register for synchronizing doorbell operations - * @host_diag: Diagnostic register used for status or debug reporting - * @r1: Reserved - * @host_int_status: Interrupt status register reporting active interrupts - * @host_int_mask: Interrupt mask register enabling or disabling sources - * @r2: Reserved - * @rep_msg_host_idx: Reply message index for the next available reply slot - * @r3: Reserved - * @debug_log: DebugLog registers for firmware debug and diagnostic output - * @r4: Reserved - * @atomic_req_desc_post: Atomic register for single descriptor posting - * @adapter_log_buf_pos: Adapter log buffer write position - * @host_log_buf_pos: Host log buffer write position - * @r5: Reserved + * @db: Doorbell register used to signal commands or status to firmware. + * @ws: Write sequence register for synchronizing doorbell operations. + * @host_diag: Diagnostic register used for status or debug reporting. + * @r1: Reserved. + * @host_int_status: Interrupt status register reporting active interrupts. + * @host_int_mask: Interrupt mask register enabling or disabling sources. + * @r2: Reserved. + * @rep_msg_host_idx: Reply message index for the next available reply slot. + * @r3: Reserved. + * @debug_log: DebugLog registers for firmware debug and diagnostic output. + * @r4: Reserved. + * @atomic_req_desc_post: Atomic register for single descriptor posting. + * @adapter_log_buf_pos: Adapter log buffer write position. + * @host_log_buf_pos: Host log buffer write position. + * @r5: Reserved. * @rep_post_reg_idx: Array of reply post index registers, one per queue. * The number of entries is defined by * REP_POST_HOST_IDX_REG_CNT. @@ -411,9 +424,9 @@ struct leapraid_reg_base { /** * struct leapraid_atomic_req_desc - Atomic request descriptor * - * @flg: Descriptor flag indicating the type of request (e.g. SCSI I/O) - * @msix_idx: MSI-X vector index used for interrupt routing - * @taskid: Unique task identifier associated with this request + * @flg: Descriptor flag indicating the type of request (e.g. SCSI I/O). + * @msix_idx: MSI-X vector index used for interrupt routing. + * @taskid: Unique task identifier associated with this request. */ struct leapraid_atomic_req_desc { u8 flg; @@ -424,23 +437,23 @@ struct leapraid_atomic_req_desc { /** * union leapraid_rep_desc_union - Unified reply descriptor format * - * @dflt_rep: Default reply descriptor containing basic completion info - * @dflt_rep.rep_flg: Reply flag indicating reply type or status - * @dflt_rep.msix_idx: MSI-X index for interrupt routing - * @dflt_rep.taskid: Task identifier matching the submitted request - * @r1: Reserved + * @dflt_rep: Default reply descriptor containing basic completion info. + * @dflt_rep.rep_flg: Reply flag indicating reply type or status. + * @dflt_rep.msix_idx: MSI-X index for interrupt routing. + * @dflt_rep.taskid: Task identifier matching the submitted request. + * @r1: Reserved. * * @addr_rep: Address reply descriptor used when firmware returns a - * memory address associated with the reply - * @addr_rep.rep_flg: Reply flag indicating reply type or status - * @addr_rep.msix_idx: MSI-X index for interrupt routing - * @addr_rep.taskid: Task identifier matching the submitted request - * @addr_rep.rep_frame_addr: Physical address of the reply frame + * memory address associated with the reply. + * @addr_rep.rep_flg: Reply flag indicating reply type or status. + * @addr_rep.msix_idx: MSI-X index for interrupt routing. + * @addr_rep.taskid: Task identifier matching the submitted request. + * @addr_rep.rep_frame_addr: Physical address of the reply frame. * - * @words: Raw 64-bit representation of the reply descriptor - * @u: Alternative access using 32-bit low/high words - * @u.low: Lower 32 bits of the descriptor - * @u.high: Upper 32 bits of the descriptor + * @words: Raw 64-bit representation of the reply descriptor. + * @u: Alternative access using 32-bit low/high words. + * @u.low: Lower 32 bits of the descriptor. + * @u.high: Upper 32 bits of the descriptor. */ union leapraid_rep_desc_union { struct leapraid_rep_desc { @@ -465,10 +478,10 @@ union leapraid_rep_desc_union { /** * struct leapraid_req - Generic request header * - * @func_dep1: Function-dependent parameter (low 16 bits) - * @r1: Reserved - * @func: Function code identifying the command type - * @r2: Reserved + * @func_dep1: Function-dependent parameter (low 16 bits). + * @r1: Reserved. + * @func: Function code identifying the command type. + * @r2: Reserved. */ struct leapraid_req { __le16 func_dep1; @@ -480,12 +493,12 @@ struct leapraid_req { /** * struct leapraid_rep - Generic reply header * - * @r1: Reserved - * @msg_len: Length of the reply message in bytes - * @function: Function code corresponding to the request - * @r2: Reserved - * @adapter_status: Status code reported by the adapter - * @r3: Reserved + * @r1: Reserved. + * @msg_len: Length of the reply message in bytes. + * @function: Function code corresponding to the request. + * @r2: Reserved. + * @adapter_status: Status code reported by the adapter. + * @r3: Reserved. */ struct leapraid_rep { u8 r1[2]; @@ -499,8 +512,8 @@ struct leapraid_rep { /** * struct leapraid_sge_simple32 - 32-bit simple scatter-gather entry * - * @flg_and_len: Combined field for flags and segment length - * @addr: 32-bit physical address of the data buffer + * @flg_and_len: Combined field for flags and segment length. + * @addr: 32-bit physical address of the data buffer. */ struct leapraid_sge_simple32 { __le32 flg_and_len; @@ -510,8 +523,8 @@ struct leapraid_sge_simple32 { /** * struct leapraid_sge_simple64 - 64-bit simple scatter-gather entry * - * @flg_and_len: Combined field for flags and segment length - * @addr: 64-bit physical address of the data buffer + * @flg_and_len: Combined field for flags and segment length. + * @addr: 64-bit physical address of the data buffer. */ struct leapraid_sge_simple64 { __le32 flg_and_len; @@ -521,9 +534,9 @@ struct leapraid_sge_simple64 { /** * struct leapraid_sge_simple_union - Unified 32/64-bit SGE representation * - * @flg_and_len: Combined field for flags and segment length - * @u.addr32: 32-bit address field - * @u.addr64: 64-bit address field + * @flg_and_len: Combined field for flags and segment length. + * @u.addr32: 32-bit address field. + * @u.addr64: 64-bit address field. */ struct leapraid_sge_simple_union { __le32 flg_and_len; @@ -536,11 +549,11 @@ struct leapraid_sge_simple_union { /** * struct leapraid_sge_chain_union - Chained scatter-gather entry * - * @len: Length of the chain descriptor - * @next_chain_offset: Offset to the next SGE chain - * @flg: Flags indicating chain or termination properties - * @u.addr32: 32-bit physical address - * @u.addr64: 64-bit physical address + * @len: Length of the chain descriptor. + * @next_chain_offset: Offset to the next SGE chain. + * @flg: Flags indicating chain or termination properties. + * @u.addr32: 32-bit physical address. + * @u.addr64: 64-bit physical address. */ struct leapraid_sge_chain_union { __le16 len; @@ -555,8 +568,8 @@ struct leapraid_sge_chain_union { /** * struct leapraid_ieee_sge_simple32 - IEEE 32-bit simple SGE format * - * @addr: 32-bit physical address of the data buffer - * @flg_and_len: Combined field for flags and data length + * @addr: 32-bit physical address of the data buffer. + * @flg_and_len: Combined field for flags and data length. */ struct leapraid_ieee_sge_simple32 { __le32 addr; @@ -566,10 +579,10 @@ struct leapraid_ieee_sge_simple32 { /** * struct leapraid_ieee_sge_simple64 - IEEE 64-bit simple SGE format * - * @addr: 64-bit physical address of the data buffer - * @len: Length of the data segment - * @r1: Reserved - * @flg: Flags indicating transfer properties + * @addr: 64-bit physical address of the data buffer. + * @len: Length of the data segment. + * @r1: Reserved. + * @flg: Flags indicating transfer properties. */ struct leapraid_ieee_sge_simple64 { __le64 addr; @@ -581,8 +594,8 @@ struct leapraid_ieee_sge_simple64 { /** * union leapraid_ieee_sge_simple_union - Unified IEEE SGE format * - * @simple32: IEEE 32-bit simple SGE entry - * @simple64: IEEE 64-bit simple SGE entry + * @simple32: IEEE 32-bit simple SGE entry. + * @simple64: IEEE 64-bit simple SGE entry. */ union leapraid_ieee_sge_simple_union { struct leapraid_ieee_sge_simple32 simple32; @@ -592,8 +605,8 @@ union leapraid_ieee_sge_simple_union { /** * union leapraid_ieee_sge_chain_union - Unified IEEE SGE chain format * - * @chain32: IEEE 32-bit chain SGE entry - * @chain64: IEEE 64-bit chain SGE entry + * @chain32: IEEE 32-bit chain SGE entry. + * @chain64: IEEE 64-bit chain SGE entry. */ union leapraid_ieee_sge_chain_union { struct leapraid_ieee_sge_simple32 chain32; @@ -603,11 +616,11 @@ union leapraid_ieee_sge_chain_union { /** * struct leapraid_chain64_ieee_sg - 64-bit IEEE chain SGE descriptor * - * @addr: Physical address of the next chain segment - * @len: Length of the current SGE - * @r1: Reserved - * @next_chain_offset: Offset to the next chain element - * @flg: Flags that describe SGE attributes + * @addr: Physical address of the next chain segment. + * @len: Length of the current SGE. + * @r1: Reserved. + * @next_chain_offset: Offset to the next chain element. + * @flg: Flags that describe SGE attributes. */ struct leapraid_chain64_ieee_sg { __le64 addr; @@ -620,8 +633,8 @@ struct leapraid_chain64_ieee_sg { /** * union leapraid_ieee_sge_io_union - IEEE-style SGE union for I/O * - * @ieee_simple: Simple IEEE SGE descriptor - * @ieee_chain: IEEE chain SGE descriptor + * @ieee_simple: Simple IEEE SGE descriptor. + * @ieee_chain: IEEE chain SGE descriptor. */ union leapraid_ieee_sge_io_union { struct leapraid_ieee_sge_simple64 ieee_simple; @@ -631,25 +644,25 @@ union leapraid_ieee_sge_io_union { /** * union leapraid_simple_sge_union - Union of simple SGE descriptors * - * @leapio_simple: LeapIO-style simple SGE - * @ieee_simple: IEEE-style simple SGE + * @leapraid_simple: LeapRAID simple SGE. + * @ieee_simple: IEEE-style simple SGE. */ union leapraid_simple_sge_union { - struct leapraid_sge_simple_union leapio_simple; + struct leapraid_sge_simple_union leapraid_simple; union leapraid_ieee_sge_simple_union ieee_simple; }; /** * union leapraid_sge_io_union - Combined SGE union for all I/O types * - * @leapio_simple: LeapIO simple SGE format - * @leapio_chain: LeapIO chain SGE format - * @ieee_simple: IEEE simple SGE format - * @ieee_chain: IEEE chain SGE format + * @leapraid_simple: LeapRAID simple SGE format. + * @leapraid_chain: LeapRAID chain SGE format. + * @ieee_simple: IEEE simple SGE format. + * @ieee_chain: IEEE chain SGE format. */ union leapraid_sge_io_union { - struct leapraid_sge_simple_union leapio_simple; - struct leapraid_sge_chain_union leapio_chain; + struct leapraid_sge_simple_union leapraid_simple; + struct leapraid_sge_chain_union leapraid_chain; union leapraid_ieee_sge_simple_union ieee_simple; union leapraid_ieee_sge_chain_union ieee_chain; }; @@ -657,10 +670,10 @@ union leapraid_sge_io_union { /** * struct leapraid_cfg_pg_header - Standard configuration page header * - * @r1: Reserved - * @page_len: Length of the page in 4-byte units - * @page_num: Page number - * @page_type: Page type + * @r1: Reserved. + * @page_len: Length of the page in 4-byte units. + * @page_num: Page number. + * @page_type: Page type. */ struct leapraid_cfg_pg_header { u8 r1; @@ -672,13 +685,13 @@ struct leapraid_cfg_pg_header { /** * struct leapraid_cfg_ext_pg_header - Extended configuration page header * - * @r1: Reserved - * @r2: Reserved - * @page_num: Page number - * @page_type: Page type - * @ext_page_len: Extended page length - * @ext_page_type: Extended page type - * @r3: Reserved + * @r1: Reserved. + * @r2: Reserved. + * @page_num: Page number. + * @page_type: Page type. + * @ext_page_len: Extended page length. + * @ext_page_type: Extended page type. + * @r3: Reserved. */ struct leapraid_cfg_ext_pg_header { u8 r1; @@ -693,17 +706,17 @@ struct leapraid_cfg_ext_pg_header { /** * struct leapraid_cfg_req - Configuration request message * - * @action: Requested action type - * @sgl_flag: SGL flag field - * @chain_offset: Offset to next chain SGE - * @func: Function code - * @ext_page_len: Extended page length - * @ext_page_type: Extended page type - * @msg_flag: Message flags - * @r1: Reserved - * @header: Configuration page header - * @page_addr: Address of the page buffer - * @page_buf_sge: SGE describing the page buffer + * @action: Requested action type. + * @sgl_flag: SGL flag field. + * @chain_offset: Offset to next chain SGE. + * @func: Function code. + * @ext_page_len: Extended page length. + * @ext_page_type: Extended page type. + * @msg_flag: Message flags. + * @r1: Reserved. + * @header: Configuration page header. + * @page_addr: Address of the page buffer. + * @page_buf_sge: SGE describing the page buffer. */ struct leapraid_cfg_req { u8 action; @@ -722,17 +735,17 @@ struct leapraid_cfg_req { /** * struct leapraid_cfg_rep - Configuration reply message * - * @action: Action type from the request - * @r1: Reserved - * @msg_len: Message length in bytes - * @func: Function code - * @ext_page_len: Extended page length - * @ext_page_type: Extended page type - * @msg_flag: Message flags - * @r2: Reserved - * @adapter_status: Adapter status code - * @r3: Reserved - * @header: Configuration page header + * @action: Action type from the request. + * @r1: Reserved. + * @msg_len: Message length in bytes. + * @func: Function code. + * @ext_page_len: Extended page length. + * @ext_page_type: Extended page type. + * @msg_flag: Message flags. + * @r2: Reserved. + * @adapter_status: Adapter status code. + * @r3: Reserved. + * @header: Configuration page header. */ struct leapraid_cfg_rep { u8 action; @@ -751,9 +764,9 @@ struct leapraid_cfg_rep { /** * struct leapraid_boot_dev_format_sas_wwid - Boot device identified by wwid * - * @sas_addr: SAS address of the device - * @lun: Logical unit number - * @r1: Reserved + * @sas_addr: SAS address of the device. + * @lun: Logical unit number. + * @r1: Reserved. */ struct leapraid_boot_dev_format_sas_wwid { __le64 sas_addr; @@ -764,10 +777,10 @@ struct leapraid_boot_dev_format_sas_wwid { /** * struct leapraid_boot_dev_format_enc_slot - identified by enclosure * - * @enc_lid: Enclosure logical ID - * @r1: Reserved - * @slot_num: Slot number in the enclosure - * @r2: Reserved + * @enc_lid: Enclosure logical ID. + * @r1: Reserved. + * @slot_num: Slot number in the enclosure. + * @r2: Reserved. */ struct leapraid_boot_dev_format_enc_slot { __le64 enc_lid; @@ -779,9 +792,9 @@ struct leapraid_boot_dev_format_enc_slot { /** * struct leapraid_boot_dev_format_dev_name - Boot device by device name * - * @dev_name: Device name identifier - * @lun: Logical unit number - * @r1: Reserved + * @dev_name: Device name identifier. + * @lun: Logical unit number. + * @r1: Reserved. */ struct leapraid_boot_dev_format_dev_name { __le64 dev_name; @@ -792,9 +805,9 @@ struct leapraid_boot_dev_format_dev_name { /** * union leapraid_boot_dev_format - Boot device format union * - * @sas_wwid: Format using SAS WWID and LUN - * @enc_slot: Format using enclosure slot and ID - * @dev_name: Format using device name and LUN + * @sas_wwid: Format using SAS WWID and LUN. + * @enc_slot: Format using enclosure slot and ID. + * @dev_name: Format using device name and LUN. */ union leapraid_boot_dev_format { struct leapraid_boot_dev_format_sas_wwid sas_wwid; @@ -802,20 +815,39 @@ union leapraid_boot_dev_format { struct leapraid_boot_dev_format_dev_name dev_name; }; +/** + * struct leapraid_manufacturing_p0 - Manufacturing configuration page 0 + * + * @header: Configuration page header. + * @chip_name: Chip name as a 16-byte ASCII string. + * @chip_revision: Chip revision as an 8-byte ASCII string. + * @board_name: Board name as a 16-byte ASCII string. + * @board_assembly: Board assembly as a 16-byte ASCII string. + * @board_tracer_number: Board tracer number as a 16-byte ASCII string. + */ +struct leapraid_manufacturing_p0 { + struct leapraid_cfg_pg_header header; + u8 chip_name[16]; + u8 chip_revision[8]; + u8 board_name[16]; + u8 board_assembly[16]; + u8 board_tracer_number[16]; +}; + /** * struct leapraid_bios_page2 - BIOS configuration page 2 * - * @header: Configuration page header - * @r1: Reserved - * @requested_boot_dev_form: Format type of the requested boot device - * @r2: Reserved - * @requested_boot_dev: Boot device requested by BIOS or user - * @requested_alt_boot_dev_form: Format of the alternate boot device - * @r3: Reserved - * @requested_alt_boot_dev: Alternate boot device requested - * @current_boot_dev_form: Format type of the active boot device - * @r4: Reserved - * @current_boot_dev: Currently active boot device in use + * @header: Configuration page header. + * @r1: Reserved. + * @requested_boot_dev_form: Format type of the requested boot device. + * @r2: Reserved. + * @requested_boot_dev: Boot device requested by BIOS or user. + * @requested_alt_boot_dev_form: Format of the alternate boot device. + * @r3: Reserved. + * @requested_alt_boot_dev: Alternate boot device requested. + * @current_boot_dev_form: Format type of the active boot device. + * @r4: Reserved. + * @current_boot_dev: Currently active boot device in use. */ struct leapraid_bios_page2 { struct leapraid_cfg_pg_header header; @@ -834,10 +866,10 @@ struct leapraid_bios_page2 { /** * struct leapraid_bios_page3 - BIOS configuration page 3 * - * @header: Configuration page header - * @r1: Reserved - * @bios_version: BIOS firmware version number - * @r2: Reserved + * @header: Configuration page header. + * @r1: Reserved. + * @bios_version: BIOS firmware version number. + * @r2: Reserved. */ struct leapraid_bios_page3 { struct leapraid_cfg_pg_header header; @@ -849,9 +881,9 @@ struct leapraid_bios_page3 { /** * struct leapraid_raidvol0_phys_disk - Physical disk in RAID volume * - * @r1: Reserved - * @phys_disk_num: Physical disk number within the RAID volume - * @r2: Reserved + * @r1: Reserved. + * @phys_disk_num: Physical disk number within the RAID volume. + * @r2: Reserved. */ struct leapraid_raidvol0_phys_disk { u8 r1[2]; @@ -862,14 +894,14 @@ struct leapraid_raidvol0_phys_disk { /** * struct leapraid_raidvol_p0 - RAID volume configuration page 0 * - * @header: Configuration page header - * @dev_hdl: Device handle for the RAID volume - * @volume_state: State of the RAID volume - * @volume_type: RAID type - * @r1: Reserved - * @num_phys_disks: Number of physical disks in the volume - * @r2: Reserved - * @phys_disk: Array of physical disks in this volume + * @header: Configuration page header. + * @dev_hdl: Device handle for the RAID volume. + * @volume_state: State of the RAID volume. + * @volume_type: RAID type. + * @r1: Reserved. + * @num_phys_disks: Number of physical disks in the volume. + * @r2: Reserved. + * @phys_disk: Array of physical disks in this volume. */ struct leapraid_raidvol_p0 { struct leapraid_cfg_pg_header header; @@ -885,11 +917,11 @@ struct leapraid_raidvol_p0 { /** * struct leapraid_raidvol_p1 - RAID volume configuration page 1 * - * @header: Configuration page header - * @dev_hdl: Device handle of the RAID volume - * @r1: Reserved - * @wwid: World-wide identifier for the volume - * @r2: Reserved + * @header: Configuration page header. + * @dev_hdl: Device handle of the RAID volume. + * @r1: Reserved. + * @wwid: World-wide identifier for the volume. + * @r2: Reserved. */ struct leapraid_raidvol_p1 { struct leapraid_cfg_pg_header header; @@ -902,11 +934,11 @@ struct leapraid_raidvol_p1 { /** * struct leapraid_raidpd_p0 - Physical disk configuration page 0 * - * @header: Configuration page header - * @dev_hdl: Device handle of the physical disk - * @r1: Reserved - * @phys_disk_num: Physical disk number - * @r2: Reserved + * @header: Configuration page header. + * @dev_hdl: Device handle of the physical disk. + * @r1: Reserved. + * @phys_disk_num: Physical disk number. + * @r2: Reserved. */ struct leapraid_raidpd_p0 { struct leapraid_cfg_pg_header header; @@ -919,14 +951,14 @@ struct leapraid_raidpd_p0 { /** * struct leapraid_sas_io_unit0_phy_info - PHY info for SAS I/O unit * - * @port: Port number the PHY belongs to - * @port_flg: Flags describing port status - * @phy_flg: Flags describing PHY status - * @neg_link_rate: Negotiated link rate of the PHY - * @controller_phy_dev_info: Controller PHY device info - * @attached_dev_hdl: Handle of attached device - * @controller_dev_hdl: Handle of the controller device - * @r1: Reserved + * @port: Port number the PHY belongs to. + * @port_flg: Flags describing port status. + * @phy_flg: Flags describing PHY status. + * @neg_link_rate: Negotiated link rate of the PHY. + * @controller_phy_dev_info: Controller PHY device info. + * @attached_dev_hdl: Handle of attached device. + * @controller_dev_hdl: Handle of the controller device. + * @r1: Reserved. */ struct leapraid_sas_io_unit0_phy_info { u8 port; @@ -942,11 +974,11 @@ struct leapraid_sas_io_unit0_phy_info { /** * struct leapraid_sas_io_unit_p0 - SAS I/O unit configuration page 0 * - * @header: Extended configuration page header - * @r1: Reserved - * @phy_num: Number of PHYs in this unit - * @r2: Reserved - * @phy_info: Array of PHY information + * @header: Extended configuration page header. + * @r1: Reserved. + * @phy_num: Number of PHYs in this unit. + * @r2: Reserved. + * @phy_info: Array of PHY information. */ struct leapraid_sas_io_unit_p0 { struct leapraid_cfg_ext_pg_header header; @@ -956,54 +988,20 @@ struct leapraid_sas_io_unit_p0 { struct leapraid_sas_io_unit0_phy_info phy_info[]; }; -/** - * struct leapraid_sas_io_unit1_phy_info - Placeholder for SAS unit page 1 PHY - * - * @r1: Reserved - */ -struct leapraid_sas_io_unit1_phy_info { - u8 r1[12]; -}; - -/** - * struct leapraid_sas_io_unit_page1 - SAS I/O unit configuration page 1 - * - * @header: Extended configuration page header - * @r1: Reserved - * @narrowport_max_queue_depth: Maximum queue depth for narrow ports - * @r2: Reserved - * @wideport_max_queue_depth: Maximum queue depth for wide ports - * @r3: Reserved - * @sata_max_queue_depth: Maximum SATA queue depth - * @r4: Reserved - * @phy_info: Array of PHY info structures - */ -struct leapraid_sas_io_unit_page1 { - struct leapraid_cfg_ext_pg_header header; - u8 r1[2]; - __le16 narrowport_max_queue_depth; - u8 r2[2]; - __le16 wideport_max_queue_depth; - u8 r3; - u8 sata_max_queue_depth; - u8 r4[2]; - struct leapraid_sas_io_unit1_phy_info phy_info[]; -}; - /** * struct leapraid_exp_p0 - SAS expander page 0 * - * @header: Extended page header - * @physical_port: Physical port number - * @r1: Reserved - * @enc_hdl: Enclosure handle - * @sas_address: SAS address of the expander - * @r2: Reserved - * @dev_hdl: Device handle of this expander - * @parent_dev_hdl: Device handle of parent expander - * @r3: Reserved - * @phy_num: Number of PHYs - * @r4: Reserved + * @header: Extended page header. + * @physical_port: Physical port number. + * @r1: Reserved. + * @enc_hdl: Enclosure handle. + * @sas_address: SAS address of the expander. + * @r2: Reserved. + * @dev_hdl: Device handle of this expander. + * @parent_dev_hdl: Device handle of parent expander. + * @r3: Reserved. + * @phy_num: Number of PHYs. + * @r4: Reserved. */ struct leapraid_exp_p0 { struct leapraid_cfg_ext_pg_header header; @@ -1022,14 +1020,14 @@ struct leapraid_exp_p0 { /** * struct leapraid_exp_p1 - SAS expander page 1 * - * @header: Extended page header - * @r1: Reserved - * @p_link_rate: PHY link rate - * @hw_link_rate: Hardware supported link rate - * @attached_dev_hdl: Attached device handle - * @r2: Reserved - * @neg_link_rate: Negotiated link rate - * @r3: Reserved + * @header: Extended page header. + * @r1: Reserved. + * @p_link_rate: PHY link rate. + * @hw_link_rate: Hardware supported link rate. + * @attached_dev_hdl: Attached device handle. + * @r2: Reserved. + * @neg_link_rate: Negotiated link rate. + * @r3: Reserved. */ struct leapraid_exp_p1 { struct leapraid_cfg_ext_pg_header header; @@ -1045,25 +1043,25 @@ struct leapraid_exp_p1 { /** * struct leapraid_sas_dev_p0 - SAS device page 0 * - * @header: Extended configuration page header - * @slot: Slot number - * @enc_hdl: Enclosure handle - * @sas_address: SAS address - * @parent_dev_hdl: Parent device handle - * @phy_num: Number of PHYs - * @r1: Reserved - * @dev_hdl: Device handle - * @r2: Reserved - * @dev_info: Device information - * @flg: Flags - * @physical_port: Physical port number - * @max_port_connections: Maximum port connections - * @dev_name: Device name - * @port_groups: Number of port groups - * @r3: Reserved - * @enc_level: Enclosure level - * @connector_name: Connector identifier - * @r4: Reserved + * @header: Extended configuration page header. + * @slot: Slot number. + * @enc_hdl: Enclosure handle. + * @sas_address: SAS address. + * @parent_dev_hdl: Parent device handle. + * @phy_num: Number of PHYs. + * @r1: Reserved. + * @dev_hdl: Device handle. + * @r2: Reserved. + * @dev_info: Device information. + * @flg: Flags. + * @physical_port: Physical port number. + * @max_port_connections: Maximum port connections. + * @dev_name: Device name. + * @port_groups: Number of port groups. + * @r3: Reserved. + * @enc_level: Enclosure level. + * @connector_name: Connector identifier. + * @r4: Reserved. */ struct leapraid_sas_dev_p0 { struct leapraid_cfg_ext_pg_header header; @@ -1083,23 +1081,23 @@ struct leapraid_sas_dev_p0 { u8 port_groups; u8 r3[2]; u8 enc_level; - u8 connector_name[4]; + u8 connector_name[LEAPRAID_SAS_DEV_P0_CON_NAME_LEN]; u8 r4[4]; } __packed __aligned(4); /** * struct leapraid_sas_phy_p0 - SAS PHY configuration page 0 * - * @header: Extended configuration page header - * @r1: Reserved - * @attached_dev_hdl: Handle of attached device - * @r2: Reserved - * @p_link_rate: PHY link rate - * @hw_link_rate: Hardware supported link rate - * @r3: Reserved - * @phy_info: PHY information - * @neg_link_rate: Negotiated link rate - * @r4: Reserved + * @header: Extended configuration page header. + * @r1: Reserved. + * @attached_dev_hdl: Handle of attached device. + * @r2: Reserved. + * @p_link_rate: PHY link rate. + * @hw_link_rate: Hardware supported link rate. + * @r3: Reserved. + * @phy_info: PHY information. + * @neg_link_rate: Negotiated link rate. + * @r4: Reserved. */ struct leapraid_sas_phy_p0 { struct leapraid_cfg_ext_pg_header header; @@ -1117,12 +1115,12 @@ struct leapraid_sas_phy_p0 { /** * struct leapraid_enc_p0 - SAS enclosure page 0 * - * @header: Extended configuration page header - * @r1: Reserved - * @enc_lid: Enclosure logical ID - * @r2: Reserved - * @enc_hdl: Enclosure handle - * @r3: Reserved + * @header: Extended configuration page header. + * @r1: Reserved. + * @enc_lid: Enclosure logical ID. + * @r2: Reserved. + * @enc_hdl: Enclosure handle. + * @r3: Reserved. */ struct leapraid_enc_p0 { struct leapraid_cfg_ext_pg_header header; @@ -1136,10 +1134,10 @@ struct leapraid_enc_p0 { /** * struct leapraid_raid_cfg_p0_element - RAID configuration element * - * @element_flg: Element flags - * @vol_dev_hdl: Volume device handle - * @r1: Reserved - * @phys_disk_dev_hdl: Physical disk device handle + * @element_flg: Element flags. + * @vol_dev_hdl: Volume device handle. + * @r1: Reserved. + * @phys_disk_dev_hdl: Physical disk device handle. */ struct leapraid_raid_cfg_p0_element { __le16 element_flg; @@ -1151,13 +1149,13 @@ struct leapraid_raid_cfg_p0_element { /** * struct leapraid_raid_cfg_p0 - RAID configuration page 0 * - * @header: Extended configuration page header - * @r1: Reserved - * @cfg_num: Configuration number - * @r2: Reserved - * @elements_num: Number of RAID elements - * @r3: Reserved - * @cfg_element: Array of RAID elements + * @header: Extended configuration page header. + * @r1: Reserved. + * @cfg_num: Configuration number. + * @r2: Reserved. + * @elements_num: Number of RAID elements. + * @r3: Reserved. + * @cfg_element: Array of RAID elements. */ struct leapraid_raid_cfg_p0 { struct leapraid_cfg_ext_pg_header header; @@ -1172,8 +1170,8 @@ struct leapraid_raid_cfg_p0 { /** * union leapraid_mpi_scsi_io_cdb_union - SCSI I/O CDB or simple SGE * - * @cdb32: 32-byte SCSI command descriptor block - * @sge: Simple SGE format + * @cdb32: 32-byte SCSI command descriptor block. + * @sge: Simple SGE format. */ union leapraid_mpi_scsi_io_cdb_union { u8 cdb32[32]; @@ -1183,32 +1181,32 @@ union leapraid_mpi_scsi_io_cdb_union { /** * struct leapraid_mpi_scsiio_req - MPI SCSI I/O request * - * @dev_hdl: Device handle for the target - * @chain_offset: Offset for chained SGE - * @func: Function code - * @r1: Reserved - * @msg_flg: Message flags - * @r2: Reserved - * @sense_buffer_low_add: Lower 32-bit address of sense buffer - * @dma_flag: DMA flags - * @r3: Reserved - * @sense_buffer_len: Sense buffer length - * @r4: Reserved - * @sgl_offset0..3: SGL offsets - * @skip_count: Bytes to skip before transfer - * @data_len: Length of data transfer - * @bi_dir_data_len: Bi-directional transfer length - * @io_flg: I/O flags - * @eedp_flag: EEDP flags - * @eedp_block_size: EEDP block size - * @r5: Reserved - * @secondary_ref_tag: Secondary reference tag - * @secondary_app_tag: Secondary application tag - * @app_tag_trans_mask: Application tag mask - * @lun: Logical Unit Number - * @ctrl: Control flags - * @cdb: SCSI Command Descriptor Block or simple SGE - * @sgl: Scatter-gather list + * @dev_hdl: Device handle for the target. + * @chain_offset: Offset for chained SGE. + * @func: Function code. + * @r1: Reserved. + * @msg_flg: Message flags. + * @r2: Reserved. + * @sense_buffer_low_add: Lower 32-bit address of sense buffer. + * @dma_flag: DMA flags. + * @r3: Reserved. + * @sense_buffer_len: Sense buffer length. + * @r4: Reserved. + * @sgl_offset0..3: SGL offsets. + * @skip_count: Bytes to skip before transfer. + * @data_len: Length of data transfer. + * @bi_dir_data_len: Bi-directional transfer length. + * @io_flg: I/O flags. + * @eedp_flag: End-to-end data protection flags. + * @eedp_block_size: End-to-end data protection block size. + * @r5: Reserved. + * @secondary_ref_tag: Secondary reference tag. + * @secondary_app_tag: Secondary application tag. + * @app_tag_trans_mask: Application tag mask. + * @lun: Logical Unit Number. + * @ctrl: Control flags. + * @cdb: SCSI Command Descriptor Block or simple SGE. + * @sgl: Scatter-gather list. */ struct leapraid_mpi_scsiio_req { __le16 dev_hdl; @@ -1245,8 +1243,8 @@ struct leapraid_mpi_scsiio_req { /** * union leapraid_scsi_io_cdb_union - SCSI I/O CDB or IEEE simple SGE * - * @cdb32: 32-byte SCSI CDB - * @sge: IEEE simple 64-bit SGE + * @cdb32: 32-byte SCSI CDB. + * @sge: IEEE simple 64-bit SGE. */ union leapraid_scsi_io_cdb_union { u8 cdb32[32]; @@ -1256,32 +1254,32 @@ union leapraid_scsi_io_cdb_union { /** * struct leapraid_scsiio_req - SCSI I/O request * - * @dev_hdl: Device handle - * @chain_offset: Offset for chained SGE - * @func: Function code - * @r1: Reserved - * @msg_flg: Message flags - * @r2: Reserved - * @sense_buffer_low_add: Lower 32-bit address of sense buffer - * @dma_flag: DMA flag - * @r3: Reserved - * @sense_buffer_len: Sense buffer length - * @r4: Reserved - * @sgl_offset0-3: SGL offsets - * @skip_count: Bytes to skip before transfer - * @data_len: Length of data transfer - * @bi_dir_data_len: Bi-directional transfer length - * @io_flg: I/O flags - * @eedp_flag: EEDP flags - * @eedp_block_size: EEDP block size - * @r5: Reserved - * @secondary_ref_tag: Secondary reference tag - * @secondary_app_tag: Secondary application tag - * @app_tag_trans_mask: Application tag mask - * @lun: Logical Unit Number - * @ctrl: Control flags - * @cdb: SCSI Command Descriptor Block or simple SGE - * @sgl: Scatter-gather list + * @dev_hdl: Device handle. + * @chain_offset: Offset for chained SGE. + * @func: Function code. + * @r1: Reserved. + * @msg_flg: Message flags. + * @r2: Reserved. + * @sense_buffer_low_add: Lower 32-bit address of sense buffer. + * @dma_flag: DMA flag. + * @r3: Reserved. + * @sense_buffer_len: Sense buffer length. + * @r4: Reserved. + * @sgl_offset0-3: SGL offsets. + * @skip_count: Bytes to skip before transfer. + * @data_len: Length of data transfer. + * @bi_dir_data_len: Bi-directional transfer length. + * @io_flg: I/O flags. + * @eedp_flag: End-to-end data protection flags. + * @eedp_block_size: End-to-end data protection block size. + * @r5: Reserved. + * @secondary_ref_tag: Secondary reference tag. + * @secondary_app_tag: Secondary application tag. + * @app_tag_trans_mask: Application tag mask. + * @lun: Logical Unit Number. + * @ctrl: Control flags. + * @cdb: SCSI Command Descriptor Block or simple SGE. + * @sgl: Scatter-gather list. */ struct leapraid_scsiio_req { __le16 dev_hdl; @@ -1318,23 +1316,23 @@ struct leapraid_scsiio_req { /** * struct leapraid_scsiio_rep - SCSI I/O response * - * @dev_hdl: Device handle - * @msg_len: Length of response message - * @func: Function code - * @r1: Reserved - * @msg_flg: Message flags - * @r2: Reserved - * @scsi_status: SCSI status - * @scsi_state: SCSI state - * @adapter_status: Adapter status - * @r3: Reserved - * @transfer_count: Number of bytes transferred - * @sense_count: Number of sense bytes - * @resp_info: Additional response info - * @task_tag: Task identifier - * @scsi_status_qualifier: SCSI status qualifier - * @bi_dir_trans_count: Bi-directional transfer count - * @r4: Reserved + * @dev_hdl: Device handle. + * @msg_len: Length of response message. + * @func: Function code. + * @r1: Reserved. + * @msg_flg: Message flags. + * @r2: Reserved. + * @scsi_status: SCSI status. + * @scsi_state: SCSI state. + * @adapter_status: Adapter status. + * @r3: Reserved. + * @transfer_count: Number of bytes transferred. + * @sense_count: Number of sense bytes. + * @resp_info: Additional response info. + * @task_tag: Task identifier. + * @scsi_status_qualifier: SCSI status qualifier. + * @bi_dir_trans_count: Bi-directional transfer count. + * @r4: Reserved. */ struct leapraid_scsiio_rep { __le16 dev_hdl; @@ -1359,18 +1357,18 @@ struct leapraid_scsiio_rep { /** * struct leapraid_scsi_tm_req - SCSI Task Management request * - * @dev_hdl: Device handle - * @chain_offset: Offset for chained SGE - * @func: Function code - * @r1: Reserved - * @task_type: Task management function type - * @r2: Reserved - * @msg_flg: Message flags - * @r3: Reserved - * @lun: Logical Unit Number - * @r4: Reserved - * @task_mid: Task identifier - * @r5: Reserved + * @dev_hdl: Device handle. + * @chain_offset: Offset for chained SGE. + * @func: Function code. + * @r1: Reserved. + * @task_type: Task management function type. + * @r2: Reserved. + * @msg_flg: Message flags. + * @r3: Reserved. + * @lun: Logical Unit Number. + * @r4: Reserved. + * @task_mid: Task identifier. + * @r5: Reserved. */ struct leapraid_scsi_tm_req { __le16 dev_hdl; @@ -1390,18 +1388,18 @@ struct leapraid_scsi_tm_req { /** * struct leapraid_scsi_tm_rep - SCSI Task Management response * - * @dev_hdl: Device handle - * @msg_len: Length of response message - * @func: Function code - * @resp_code: Response code - * @task_type: Task management type - * @r1: Reserved - * @msg_flag: Message flags - * @r2: Reserved - * @adapter_status: Adapter status - * @r3: Reserved - * @termination_count: Count of terminated tasks - * @response_info: Additional response info + * @dev_hdl: Device handle. + * @msg_len: Length of response message. + * @func: Function code. + * @resp_code: Response code. + * @task_type: Task management type. + * @r1: Reserved. + * @msg_flag: Message flags. + * @r2: Reserved. + * @adapter_status: Adapter status. + * @r3: Reserved. + * @termination_count: Count of terminated tasks. + * @response_info: Additional response info. */ struct leapraid_scsi_tm_rep { __le16 dev_hdl; @@ -1421,18 +1419,18 @@ struct leapraid_scsi_tm_rep { /** * struct leapraid_sep_req - SEP (SCSI Enclosure Processor) request * - * @dev_hdl: Device handle - * @chain_offset: Offset for chained SGE - * @func: Function code - * @act: Action to perform - * @flg: Flags - * @r1: Reserved - * @msg_flag: Message flags - * @r2: Reserved - * @slot_status: Slot status - * @r3: Reserved - * @slot: Slot number - * @enc_hdl: Enclosure handle + * @dev_hdl: Device handle. + * @chain_offset: Offset for chained SGE. + * @func: Function code. + * @act: Action to perform. + * @flg: Flags. + * @r1: Reserved. + * @msg_flag: Message flags. + * @r2: Reserved. + * @slot_status: Slot status. + * @r3: Reserved. + * @slot: Slot number. + * @enc_hdl: Enclosure handle. */ struct leapraid_sep_req { __le16 dev_hdl; @@ -1452,19 +1450,19 @@ struct leapraid_sep_req { /** * struct leapraid_sep_rep - SEP response * - * @dev_hdl: Device handle - * @msg_len: Message length - * @func: Function code - * @act: Action performed - * @flg: Flags - * @msg_flag: Message flags - * @r1: Reserved - * @adapter_status: Adapter status - * @r2: Reserved - * @slot_status: Slot status - * @r3: Reserved - * @slot: Slot number - * @enc_hdl: Enclosure handle + * @dev_hdl: Device handle. + * @msg_len: Message length. + * @func: Function code. + * @act: Action performed. + * @flg: Flags. + * @msg_flag: Message flags. + * @r1: Reserved. + * @adapter_status: Adapter status. + * @r2: Reserved. + * @slot_status: Slot status. + * @r3: Reserved. + * @slot: Slot number. + * @enc_hdl: Enclosure handle. */ struct leapraid_sep_rep { __le16 dev_hdl; @@ -1486,29 +1484,29 @@ struct leapraid_sep_rep { /** * struct leapraid_adapter_init_req - Adapter initialization request * - * @who_init: Initiator of the initialization - * @r1: Reserved - * @chain_offset: Chain offset - * @func: Function code - * @r2: Reserved - * @msg_flg: Message flags - * @r3: Reserved - * @msg_ver: Message version - * @header_ver: Header version - * @host_buf_addr: Host buffer address (non adapter-ref) - * @r4: Reserved - * @host_buf_size: Host buffer size (non adapter-ref) - * @host_msix_vectors: Number of host MSI-X vectors - * @r6: Reserved - * @req_frame_size: Request frame size - * @rep_desc_qd: Reply descriptor queue depth - * @rep_msg_qd: Reply message queue depth - * @sense_buffer_add_high: High 32-bit of sense buffer address - * @rep_msg_dma_high: High 32-bit of reply message DMA address - * @task_desc_base_addr: Base address of task descriptors - * @rep_desc_q_arr_addr: Address of reply descriptor queue array - * @rep_msg_addr_dma: Reply message DMA address - * @time_stamp: Timestamp + * @who_init: Initiator of the initialization. + * @r1: Reserved. + * @chain_offset: Chain offset. + * @func: Function code. + * @r2: Reserved. + * @msg_flg: Message flags. + * @r3: Reserved. + * @msg_ver: Message version. + * @header_ver: Header version. + * @host_buf_addr: Host buffer address (non adapter-ref). + * @r4: Reserved. + * @host_buf_size: Host buffer size (non adapter-ref). + * @host_msix_vectors: Number of host MSI-X vectors. + * @r6: Reserved. + * @req_frame_size: Request frame size. + * @rep_desc_qd: Reply descriptor queue depth. + * @rep_msg_qd: Reply message queue depth. + * @sense_buffer_add_high: High 32-bit of sense buffer address. + * @rep_msg_dma_high: High 32-bit of reply message DMA address. + * @task_desc_base_addr: Base address of task descriptors. + * @rep_desc_q_arr_addr: Address of reply descriptor queue array. + * @rep_msg_addr_dma: Reply message DMA address. + * @time_stamp: Timestamp. */ struct leapraid_adapter_init_req { u8 who_init; @@ -1539,8 +1537,8 @@ struct leapraid_adapter_init_req { /** * struct leapraid_rep_desc_q_arr - Reply descriptor queue array * - * @rep_desc_base_addr: Base address of the reply descriptors - * @r1: Reserved + * @rep_desc_base_addr: Base address of the reply descriptors. + * @r1: Reserved. */ struct leapraid_rep_desc_q_arr { __le64 rep_desc_base_addr; @@ -1550,15 +1548,15 @@ struct leapraid_rep_desc_q_arr { /** * struct leapraid_adapter_init_rep - Adapter initialization reply * - * @who_init: Initiator of the initialization - * @r1: Reserved - * @msg_len: Length of reply message - * @func: Function code - * @r2: Reserved - * @msg_flag: Message flags - * @r3: Reserved - * @adapter_status: Adapter status - * @r4: Reserved + * @who_init: Initiator of the initialization. + * @r1: Reserved. + * @msg_len: Length of reply message. + * @func: Function code. + * @r2: Reserved. + * @msg_flag: Message flags. + * @r3: Reserved. + * @adapter_status: Adapter status. + * @r4: Reserved. */ struct leapraid_adapter_init_rep { u8 who_init; @@ -1575,15 +1573,15 @@ struct leapraid_adapter_init_rep { /** * struct leapraid_adapter_log_req - Adapter log request * - * @action: Action code - * @type: Log type - * @chain_offset: Offset for chained SGE - * @func: Function code - * r1: Reserved - * @msg_flag: Message flags - * r2: Reserved - * @mbox: Mailbox for command-specific parameters - * @sge: Scatter-gather entry for data buffer + * @action: Action code. + * @type: Log type. + * @chain_offset: Offset for chained SGE. + * @func: Function code. + * r1: Reserved. + * @msg_flag: Message flags. + * r2: Reserved. + * @mbox: Mailbox for command-specific parameters. + * @sge: Scatter-gather entry for data buffer. */ struct leapraid_adapter_log_req { u8 action; @@ -1604,14 +1602,14 @@ struct leapraid_adapter_log_req { /** * struct leapraid_adapter_log_rep - Adapter log reply * - * @action: Action code echoed - * @type: Log type echoed - * @msg_len: Length of message - * @func: Function code - * @r1: Reserved - * @msg_flag: Message flags - * @r2: Reserved - * @adapter_status: Status returned by adapter + * @action: Action code echoed. + * @type: Log type echoed. + * @msg_len: Length of message. + * @func: Function code. + * @r1: Reserved. + * @msg_flag: Message flags. + * @r2: Reserved. + * @adapter_status: Status returned by adapter. */ struct leapraid_adapter_log_rep { u8 action; @@ -1627,12 +1625,12 @@ struct leapraid_adapter_log_rep { /** * struct leapraid_adapter_features_req - Request adapter features * - * @r1: Reserved - * @chain_offset: Offset for chained SGE - * @func: Function code - * @r2: Reserved - * @msg_flag: Message flags - * @r3: Reserved + * @r1: Reserved. + * @chain_offset: Offset for chained SGE. + * @func: Function code. + * @r2: Reserved. + * @msg_flag: Message flags. + * @r3: Reserved. */ struct leapraid_adapter_features_req { u8 r1[2]; @@ -1646,32 +1644,32 @@ struct leapraid_adapter_features_req { /** * struct leapraid_adapter_features_rep - Adapter features reply * - * @msg_ver: Message version - * @msg_len: Length of reply message - * @func: Function code - * @header_ver: Header version - * @r1: Reserved - * @msg_flag: Message flags - * @r2: Reserved - * @adapter_status: Adapter status - * @r3: Reserved - * @who_init: Who initialized the adapter - * @r4: Reserved - * @max_msix_vectors: Max MSI-X vectors supported - * @req_slot: Number of request slots - * @r5: Reserved - * @adapter_caps: Adapter capabilities - * @fw_version: Firmware version - * @sas_wide_max_qdepth: Max wide SAS queue depth - * @sas_narrow_max_qdepth: Max narrow SAS queue depth - * @r6: Reserved - * @hp_slot: Number of high-priority slots - * @r7: Reserved - * @max_volumes: Maximum supported volumes - * @max_dev_hdl: Maximum device handle - * @r8: Reserved - * @min_dev_hdl: Minimum device handle - * @r9: Reserved + * @msg_ver: Message version. + * @msg_len: Length of reply message. + * @func: Function code. + * @header_ver: Header version. + * @r1: Reserved. + * @msg_flag: Message flags. + * @r2: Reserved. + * @adapter_status: Adapter status. + * @r3: Reserved. + * @who_init: Who initialized the adapter. + * @r4: Reserved. + * @max_msix_vectors: Max MSI-X vectors supported. + * @req_slot: Number of request slots. + * @r5: Reserved. + * @adapter_caps: Adapter capabilities. + * @fw_version: Firmware version. + * @sas_wide_max_qdepth: Max wide SAS queue depth. + * @sas_narrow_max_qdepth: Max narrow SAS queue depth. + * @r6: Reserved. + * @hp_slot: Number of high-priority slots. + * @r7: Reserved. + * @max_volumes: Maximum supported volumes. + * @max_dev_hdl: Maximum device handle. + * @r8: Reserved. + * @min_dev_hdl: Minimum device handle. + * @r9: Reserved. */ struct leapraid_adapter_features_rep { u16 msg_ver; @@ -1706,12 +1704,12 @@ struct leapraid_adapter_features_rep { /** * struct leapraid_scan_dev_req - Request to scan devices * - * @r1: Reserved - * @chain_offset: Offset for chained SGE - * @func: Function code - * @r2: Reserved - * @msg_flag: Message flags - * @r3: Reserved + * @r1: Reserved. + * @chain_offset: Offset for chained SGE. + * @func: Function code. + * @r2: Reserved. + * @msg_flag: Message flags. + * @r3: Reserved. */ struct leapraid_scan_dev_req { u8 r1[2]; @@ -1725,14 +1723,14 @@ struct leapraid_scan_dev_req { /** * struct leapraid_scan_dev_rep - Scan devices reply * - * @r1: Reserved - * @msg_len: Length of message - * @func: Function code - * @r2: Reserved - * @msg_flag: Message flags - * @r3: Reserved - * @adapter_status: Adapter status - * @r4: Reserved + * @r1: Reserved. + * @msg_len: Length of message. + * @func: Function code. + * @r2: Reserved. + * @msg_flag: Message flags. + * @r3: Reserved. + * @adapter_status: Adapter status. + * @r4: Reserved. */ struct leapraid_scan_dev_rep { u8 r1[2]; @@ -1748,14 +1746,14 @@ struct leapraid_scan_dev_rep { /** * struct leapraid_evt_notify_req - Event notification request * - * @r1: Reserved - * @chain_offset: Offset for chained SGE - * @func: Function code - * @r2: Reserved - * @msg_flag: Message flags - * @r3: Reserved - * @evt_masks: Event masks to enable notifications - * @r4: Reserved + * @r1: Reserved. + * @chain_offset: Offset for chained SGE. + * @func: Function code. + * @r2: Reserved. + * @msg_flag: Message flags. + * @r3: Reserved. + * @evt_masks: Event masks to enable notifications. + * @r4: Reserved. */ struct leapraid_evt_notify_req { u8 r1[2]; @@ -1771,18 +1769,18 @@ struct leapraid_evt_notify_req { /** * struct leapraid_evt_notify_rep - Event notification reply * - * @evt_data_len: Length of event data - * @msg_len: Length of message - * @func: Function code - * @r1: Reserved - * @r2: Reserved - * @msg_flag: Message flags - * @r3: Reserved - * @adapter_status: Adapter status - * @r4: Reserved - * @evt: Event code - * @r5: Reserved - * @evt_data: Event data array + * @evt_data_len: Length of event data. + * @msg_len: Length of message. + * @func: Function code. + * @r1: Reserved. + * @r2: Reserved. + * @msg_flag: Message flags. + * @r3: Reserved. + * @adapter_status: Adapter status. + * @r4: Reserved. + * @evt: Event code. + * @r5: Reserved. + * @evt_data: Event data array. */ struct leapraid_evt_notify_rep { __le16 evt_data_len; @@ -1802,14 +1800,14 @@ struct leapraid_evt_notify_rep { /** * struct leapraid_evt_data_sas_dev_status_change - SAS device status change * - * @task_tag: Task identifier - * @reason_code: Reason for status change - * @physical_port: Physical port number - * @r1: Reserved - * @dev_hdl: Device handle - * @r2: Reserved - * @sas_address: SAS address of device - * @lun: Logical Unit Number + * @task_tag: Task identifier. + * @reason_code: Reason for status change. + * @physical_port: Physical port number. + * @r1: Reserved. + * @dev_hdl: Device handle. + * @r2: Reserved. + * @sas_address: SAS address of device. + * @lun: Logical unit Number. */ struct leapraid_evt_data_sas_dev_status_change { __le16 task_tag; @@ -1824,11 +1822,11 @@ struct leapraid_evt_data_sas_dev_status_change { /** * struct leapraid_evt_data_ir_change - IR (Integrated RAID) change event data * - * @r1: Reserved - * @reason_code: Reason for IR change - * @r2: Reserved - * @vol_dev_hdl: Volume device handle - * @phys_disk_dev_hdl: Physical disk device handle + * @r1: Reserved. + * @reason_code: Reason for IR change. + * @r2: Reserved. + * @vol_dev_hdl: Volume device handle. + * @phys_disk_dev_hdl: Physical disk device handle. */ struct leapraid_evt_data_ir_change { u8 r1; @@ -1841,10 +1839,10 @@ struct leapraid_evt_data_ir_change { /** * struct leapraid_evt_data_sas_disc - SAS discovery event data * - * @r1: Reserved - * @reason_code: Reason for discovery event - * @physical_port: Physical port number where event occurred - * @r2: Reserved + * @r1: Reserved. + * @reason_code: Reason for discovery event. + * @physical_port: Physical port number where event occurred. + * @r2: Reserved. */ struct leapraid_evt_data_sas_disc { u8 r1; @@ -1856,9 +1854,9 @@ struct leapraid_evt_data_sas_disc { /** * struct leapraid_evt_sas_topo_phy_entry - SAS topology PHY entry * - * @attached_dev_hdl: Device handle attached to PHY - * @link_rate: Current link rate - * @phy_status: PHY status flags + * @attached_dev_hdl: Device handle attached to PHY. + * @link_rate: Current link rate. + * @phy_status: PHY status flags. */ struct leapraid_evt_sas_topo_phy_entry { __le16 attached_dev_hdl; @@ -1869,15 +1867,15 @@ struct leapraid_evt_sas_topo_phy_entry { /** * struct leapraid_evt_data_sas_topo_change_list - SAS topology change list * - * @encl_hdl: Enclosure handle - * @exp_dev_hdl: Expander device handle - * @num_phys: Number of PHYs in this entry - * @r1: Reserved - * @entry_num: Entry index - * @start_phy_num: Start PHY number - * @exp_status: Expander status - * @physical_port: Physical port number - * @phy: Array of SAS PHY entries + * @encl_hdl: Enclosure handle. + * @exp_dev_hdl: Expander device handle. + * @num_phys: Number of PHYs in this entry. + * @r1: Reserved. + * @entry_num: Entry index. + * @start_phy_num: Start PHY number. + * @exp_status: Expander status. + * @physical_port: Physical port number. + * @phy: Array of SAS PHY entries. */ struct leapraid_evt_data_sas_topo_change_list { __le16 encl_hdl; @@ -1892,15 +1890,16 @@ struct leapraid_evt_data_sas_topo_change_list { }; /** - * struct leapraid_evt_data_sas_enc_dev_status_change - SAS enclosure device status + * struct leapraid_evt_data_sas_enc_dev_status_change - + * SAS enclosure device status * - * @enc_hdl: Enclosure handle - * @reason_code: Reason code for status change - * @physical_port: Physical port number - * @encl_logical_id: Enclosure logical ID - * @num_slots: Number of slots in enclosure - * @start_slot: First affected slot - * @phy_bits: Bitmap of affected PHYs + * @enc_hdl: Enclosure handle. + * @reason_code: Reason code for status change. + * @physical_port: Physical port number. + * @encl_logical_id: Enclosure logical ID. + * @num_slots: Number of slots in enclosure. + * @start_slot: First affected slot. + * @phy_bits: Bitmap of affected PHYs. */ struct leapraid_evt_data_sas_enc_dev_status_change { __le16 enc_hdl; @@ -1913,21 +1912,21 @@ struct leapraid_evt_data_sas_enc_dev_status_change { }; /** - * struct leapraid_io_unit_ctrl_req - IO unit control request + * struct leapraid_io_unit_ctrl_req - I/O unit control request * - * @op: Operation code - * @r1: Reserved - * @chain_offset: SGE chain offset - * @func: Function code - * @dev_hdl: Device handle - * @adapter_para: Adapter parameter selector - * @msg_flag: Message flags - * @r2: Reserved - * @phy_num: PHY number - * @r3: Reserved - * @adapter_para_value: Value for adapter parameter - * @adapter_para_value2: Optional second parameter value - * @r4: Reserved + * @op: Operation code. + * @r1: Reserved. + * @chain_offset: SGE chain offset. + * @func: Function code. + * @dev_hdl: Device handle. + * @adapter_para: Adapter parameter selector. + * @msg_flag: Message flags. + * @r2: Reserved. + * @phy_num: PHY number. + * @r3: Reserved. + * @adapter_para_value: Value for adapter parameter. + * @adapter_para_value2: Optional second parameter value. + * @r4: Reserved. */ struct leapraid_io_unit_ctrl_req { u8 op; @@ -1946,13 +1945,13 @@ struct leapraid_io_unit_ctrl_req { }; /** - * struct leapraid_io_unit_ctrl_rep - IO unit control reply + * struct leapraid_io_unit_ctrl_rep - I/O unit control reply * - * @op: Operation code echoed - * @r1: Reserved - * @func: Function code - * @dev_hdl: Device handle - * @r2: Reserved + * @op: Operation code echoed. + * @r1: Reserved. + * @func: Function code. + * @dev_hdl: Device handle. + * @r2: Reserved. */ struct leapraid_io_unit_ctrl_rep { u8 op; @@ -1965,13 +1964,13 @@ struct leapraid_io_unit_ctrl_rep { /** * struct leapraid_raid_act_req - RAID action request * - * @act: RAID action code - * @r1: Reserved - * @func: Function code - * @r2: Reserved - * @phys_disk_num: Number of physical disks involved - * @r3: Reserved - * @action_data_sge: SGE describing action-specific data + * @act: RAID action code. + * @r1: Reserved. + * @func: Function code. + * @r2: Reserved. + * @phys_disk_num: Number of physical disks involved. + * @r3: Reserved. + * @action_data_sge: SGE describing action-specific data. */ struct leapraid_raid_act_req { u8 act; @@ -1986,13 +1985,13 @@ struct leapraid_raid_act_req { /** * struct leapraid_raid_act_rep - RAID action reply * - * @act: RAID action code echoed - * @r1: Reserved - * @func: Function code - * @vol_dev_hdl: Volume device handle + * @act: RAID action code echoed. + * @r1: Reserved. + * @func: Function code. + * @vol_dev_hdl: Volume device handle. * @r2: Reserved - * @adapter_status: Status returned by adapter - * @r3: Reserved + * @adapter_status: Status returned by adapter. + * @r3: Reserved. */ struct leapraid_raid_act_rep { u8 act; @@ -2007,15 +2006,15 @@ struct leapraid_raid_act_rep { /** * struct leapraid_smp_passthrough_req - SMP passthrough request * - * @passthrough_flg: Passthrough flags - * @physical_port: Target PHY port - * @r1: Reserved - * @func: Function code - * @req_data_len: Request data length - * @r2: Reserved - * @sas_address: SAS address of target device - * @r3: Reserved - * @sgl: Scatter-gather list describing request buffer + * @passthrough_flg: Passthrough flags. + * @physical_port: Target PHY port. + * @r1: Reserved. + * @func: Function code. + * @req_data_len: Request data length. + * @r2: Reserved. + * @sas_address: SAS address of target device. + * @r3: Reserved. + * @sgl: Scatter-gather list describing request buffer. */ struct leapraid_smp_passthrough_req { u8 passthrough_flg; @@ -2032,14 +2031,14 @@ struct leapraid_smp_passthrough_req { /** * struct leapraid_smp_passthrough_rep - SMP passthrough reply * - * @passthrough_flg: Passthrough flags echoed - * @physical_port: Target PHY port - * @r1: Reserved - * @func: Function code - * @resp_data_len: Length of response data - * @r2: Reserved - * @adapter_status: Adapter status - * @r3: Reserved + * @passthrough_flg: Passthrough flags echoed. + * @physical_port: Target PHY port. + * @r1: Reserved. + * @func: Function code. + * @resp_data_len: Length of response data. + * @r2: Reserved. + * @adapter_status: Adapter status. + * @r3: Reserved. */ struct leapraid_smp_passthrough_rep { u8 passthrough_flg; @@ -2053,13 +2052,13 @@ struct leapraid_smp_passthrough_rep { }; /** - * struct leapraid_sas_io_unit_ctrl_req - SAS IO unit control request + * struct leapraid_sas_io_unit_ctrl_req - SAS I/O unit control request * - * @op: Operation code - * @r1: Reserved - * @func: Function code - * @dev_hdl: Device handle - * @r2: Reserved + * @op: Operation code. + * @r1: Reserved. + * @func: Function code. + * @dev_hdl: Device handle. + * @r2: Reserved. */ struct leapraid_sas_io_unit_ctrl_req { u8 op; diff --git a/drivers/scsi/leapraid/leapraid_app.c b/drivers/scsi/leapraid/leapraid_app.c index f838bd5aa20e..25ec57c2ce4b 100644 --- a/drivers/scsi/leapraid/leapraid_app.c +++ b/drivers/scsi/leapraid/leapraid_app.c @@ -1,23 +1,22 @@ // SPDX-License-Identifier: GPL-2.0 /* - * Copyright (C) 2025 LeapIO Tech Inc. + * Copyright (C) 2026 LeapIO Tech Inc. * - * LeapRAID Storage and RAID Controller driver. + * LeapRAID storage and RAID controller driver. */ - #include <linux/compat.h> #include <linux/module.h> #include <linux/miscdevice.h> #include "leapraid_func.h" -/* ioctl device file */ +/* IOCTL device file name. */ #define LEAPRAID_DEV_NAME "leapraid_ctl" -/* ioctl version */ +/* IOCTL version. */ #define LEAPRAID_IOCTL_VERSION 0x07 -/* ioctl command */ +/* IOCTL commands. */ #define LEAPRAID_ADAPTER_INFO 17 #define LEAPRAID_COMMAND 20 #define LEAPRAID_EVENTQUERY 21 @@ -25,9 +24,10 @@ /** * struct leapraid_ioctl_header - IOCTL command header - * @adapter_id : Adapter identifier - * @port_number: Port identifier - * @max_data_size: Maximum data size for transfer + * + * @adapter_id : Adapter identifier. + * @port_number: Port identifier. + * @max_data_size: Maximum data size for transfer. */ struct leapraid_ioctl_header { u32 adapter_id; @@ -37,7 +37,8 @@ struct leapraid_ioctl_header { /** * struct leapraid_ioctl_diag_reset - Diagnostic reset request - * @hdr: Common IOCTL header + * + * @hdr: Common IOCTL header. */ struct leapraid_ioctl_diag_reset { struct leapraid_ioctl_header hdr; @@ -45,12 +46,13 @@ struct leapraid_ioctl_diag_reset { /** * struct leapraid_ioctl_pci_info - PCI device information - * @u: Union holding PCI bus/device/function information - * @u.bits.dev: PCI device number - * @u.bits.func: PCI function number - * @u.bits.bus: PCI bus number - * @u.word: Combined representation of PCI BDF - * @seg_id: PCI segment identifier + * + * @u: Union holding PCI bus/device/function information. + * @u.bits.dev: PCI device number. + * @u.bits.func: PCI function number. + * @u.bits.bus: PCI bus number. + * @u.word: Combined representation of PCI BDF. + * @seg_id: PCI segment identifier. */ struct leapraid_ioctl_pci_info { union { @@ -66,21 +68,22 @@ struct leapraid_ioctl_pci_info { /** * struct leapraid_ioctl_adapter_info - Adapter information for IOCTL - * @hdr: IOCTL header - * @adapter_type: Adapter type identifier - * @port_number: Port number - * @pci_id: PCI device ID - * @revision: Revision number - * @sub_dev: Subsystem device ID - * @sub_vendor: Subsystem vendor ID - * @r0: Reserved - * @fw_ver: Firmware version - * @bios_ver: BIOS version - * @driver_ver: Driver version - * @r1: Reserved - * @scsi_id: SCSI ID - * @r2: Reserved - * @pci_info: PCI information structure + * + * @hdr: IOCTL header. + * @adapter_type: Adapter type identifier. + * @port_number: Port number. + * @pci_id: PCI device ID. + * @revision: Revision number. + * @sub_dev: Subsystem device ID. + * @sub_vendor: Subsystem vendor ID. + * @r0: Reserved. + * @fw_ver: Firmware version. + * @bios_ver: BIOS version. + * @driver_ver: Driver version. + * @r1: Reserved. + * @scsi_id: SCSI ID. + * @r2: Reserved. + * @pci_info: PCI information structure. */ struct leapraid_ioctl_adapter_info { struct leapraid_ioctl_header hdr; @@ -102,18 +105,19 @@ struct leapraid_ioctl_adapter_info { /** * struct leapraid_ioctl_command - IOCTL command structure - * @hdr: IOCTL header - * @timeout: Command timeout - * @rep_msg_buf_ptr: User pointer to reply message buffer - * @c2h_buf_ptr: User pointer to card-to-host data buffer - * @h2c_buf_ptr: User pointer to host-to-card data buffer - * @sense_data_ptr: User pointer to sense data buffer - * @max_rep_bytes: Maximum reply bytes - * @c2h_size: Card-to-host data size - * @h2c_size: Host-to-card data size - * @max_sense_bytes: Maximum sense data bytes - * @data_sge_offset: Data SGE offset - * @mf: Message frame data (flexible array) + * + * @hdr: IOCTL header. + * @timeout: Command timeout. + * @rep_msg_buf_ptr: User pointer to reply message buffer. + * @c2h_buf_ptr: User pointer to card-to-host data buffer. + * @h2c_buf_ptr: User pointer to host-to-card data buffer. + * @sense_data_ptr: User pointer to sense data buffer. + * @max_rep_bytes: Maximum reply bytes. + * @c2h_size: Card-to-host data size. + * @h2c_size: Host-to-card data size. + * @max_sense_bytes: Maximum sense data bytes. + * @data_sge_offset: Data SGE offset. + * @mf: Message frame data (flexible array). */ struct leapraid_ioctl_command { struct leapraid_ioctl_header hdr; @@ -146,39 +150,38 @@ static struct leapraid_adapter *leapraid_ctl_lookup_adapter(int adapter_id) return NULL; } -static void leapraid_cli_scsiio_cmd(struct leapraid_adapter *adapter, - struct leapraid_req *ctl_sp_mpi_req, u16 taskid, +static void leapraid_ctl_scsiio_cmd(struct leapraid_adapter *adapter, + void *ctl_sp_mpi_req, + u16 taskid, dma_addr_t h2c_dma_addr, size_t h2c_size, dma_addr_t c2h_dma_addr, size_t c2h_size, u16 dev_hdl, void *psge) { - struct leapraid_mpi_scsiio_req *scsiio_request = - (struct leapraid_mpi_scsiio_req *)ctl_sp_mpi_req; + struct leapraid_mpi_scsiio_req *scsiio_request = ctl_sp_mpi_req; scsiio_request->sense_buffer_len = SCSI_SENSE_BUFFERSIZE; scsiio_request->sense_buffer_low_add = - leapraid_get_sense_buffer_dma(adapter, taskid); - memset((void *)(&adapter->driver_cmds.ctl_cmd.sense), + leapraid_get_sense_buffer_dma(adapter, taskid); + memset(&adapter->driver_cmds.ctl_cmd.sense, 0, SCSI_SENSE_BUFFERSIZE); leapraid_build_ieee_sg(adapter, psge, h2c_dma_addr, h2c_size, c2h_dma_addr, c2h_size); - if (scsiio_request->func == LEAPRAID_FUNC_SCSIIO_REQ) + if (scsiio_request->func == LEAPRAID_FUNC_SCSIIO) leapraid_fire_scsi_io(adapter, taskid, dev_hdl); else leapraid_fire_task(adapter, taskid); } -static void leapraid_ctl_smp_passthrough_cmd(struct leapraid_adapter *adapter, - struct leapraid_req *ctl_sp_mpi_req, - u16 taskid, - dma_addr_t h2c_dma_addr, - size_t h2c_size, - dma_addr_t c2h_dma_addr, - size_t c2h_size, - void *psge, void *h2c) +static int leapraid_ctl_smp_passthrough_cmd(struct leapraid_adapter *adapter, + void *ctl_sp_req, + u16 taskid, + dma_addr_t h2c_dma_addr, + size_t h2c_size, + dma_addr_t c2h_dma_addr, + size_t c2h_size, + void *psge, void *h2c) { - struct leapraid_smp_passthrough_req *smp_pt_req = - (struct leapraid_smp_passthrough_req *)ctl_sp_mpi_req; + struct leapraid_smp_passthrough_req *smp_pt_req = ctl_sp_req; u8 *data; if (!adapter->adapter_attr.enable_mp) @@ -188,83 +191,49 @@ static void leapraid_ctl_smp_passthrough_cmd(struct leapraid_adapter *adapter, else data = h2c; - if (data[1] == LEAPRAID_SMP_FN_REPORT_PHY_ERR_LOG && - (data[10] == 1 || data[10] == 2)) - adapter->reset_desc.adapter_link_resetting = true; + if (!(smp_pt_req->passthrough_flg & LEAPRAID_SMP_PT_FLAG_SGL_PTR) && + h2c_size <= 10) { + dev_err(&adapter->pdev->dev, + "%s: Invalid request size=%zu\n", + __func__, h2c_size); + return -EINVAL; + } + + if (data[1] == SMP_PHY_CONTROL && + (data[10] == SMP_PHY_CONTROL_LINK_RESET || + data[10] == SMP_PHY_CONTROL_HARD_RESET)) + adapter->reset_desc.adapter_link_resetting = 1; + leapraid_build_ieee_sg(adapter, psge, h2c_dma_addr, h2c_size, c2h_dma_addr, c2h_size); leapraid_fire_task(adapter, taskid); + return 0; } -static void leapraid_ctl_fire_ieee_cmd(struct leapraid_adapter *adapter, - dma_addr_t h2c_dma_addr, - size_t h2c_size, - dma_addr_t c2h_dma_addr, - size_t c2h_size, - void *psge, u16 taskid) -{ - leapraid_build_ieee_sg(adapter, psge, h2c_dma_addr, h2c_size, - c2h_dma_addr, c2h_size); - leapraid_fire_task(adapter, taskid); -} - -static void leapraid_ctl_sata_passthrough_cmd(struct leapraid_adapter *adapter, +static void leapraid_ctl_sas_io_unit_ctrl_cmd(struct leapraid_adapter *adapter, + void *ctl_sp_req, dma_addr_t h2c_dma_addr, size_t h2c_size, dma_addr_t c2h_dma_addr, size_t c2h_size, void *psge, u16 taskid) { - leapraid_ctl_fire_ieee_cmd(adapter, h2c_dma_addr, - h2c_size, c2h_dma_addr, - c2h_size, psge, taskid); -} - -static void leapraid_ctl_load_fw_cmd(struct leapraid_adapter *adapter, - dma_addr_t h2c_dma_addr, size_t h2c_size, - dma_addr_t c2h_dma_addr, size_t c2h_size, - void *psge, u16 taskid) -{ - leapraid_ctl_fire_ieee_cmd(adapter, h2c_dma_addr, - h2c_size, c2h_dma_addr, - c2h_size, psge, taskid); -} + struct leapraid_sas_io_unit_ctrl_req *sas_io_unit_ctl_req = ctl_sp_req; -static void leapraid_ctl_fire_mpi_cmd(struct leapraid_adapter *adapter, - dma_addr_t h2c_dma_addr, size_t h2c_size, - dma_addr_t c2h_dma_addr, size_t c2h_size, - void *psge, u16 taskid) -{ + if (sas_io_unit_ctl_req->op == LEAPRAID_SAS_OP_PHY_HARD_RESET || + sas_io_unit_ctl_req->op == LEAPRAID_SAS_OP_PHY_LINK_RESET) + adapter->reset_desc.adapter_link_resetting = 1; leapraid_build_mpi_sg(adapter, psge, h2c_dma_addr, h2c_size, c2h_dma_addr, c2h_size); leapraid_fire_task(adapter, taskid); } -static void leapraid_ctl_sas_io_unit_ctrl_cmd(struct leapraid_adapter *adapter, - struct leapraid_req *ctl_sp_mpi_req, - dma_addr_t h2c_dma_addr, - size_t h2c_size, - dma_addr_t c2h_dma_addr, - size_t c2h_size, - void *psge, u16 taskid) +static int leapraid_ctl_do_command(struct leapraid_adapter *adapter, + struct leapraid_ioctl_command *karg, + void __user *mf) { - struct leapraid_sas_io_unit_ctrl_req *sas_io_unit_ctrl_req = - (struct leapraid_sas_io_unit_ctrl_req *)ctl_sp_mpi_req; - - if (sas_io_unit_ctrl_req->op == LEAPRAID_SAS_OP_PHY_HARD_RESET || - sas_io_unit_ctrl_req->op == LEAPRAID_SAS_OP_PHY_LINK_RESET) - adapter->reset_desc.adapter_link_resetting = true; - leapraid_ctl_fire_mpi_cmd(adapter, h2c_dma_addr, - h2c_size, c2h_dma_addr, - c2h_size, psge, taskid); -} - -static long leapraid_ctl_do_command(struct leapraid_adapter *adapter, - struct leapraid_ioctl_command *karg, - void __user *mf) -{ - struct leapraid_req *leap_mpi_req = NULL; - struct leapraid_req *ctl_sp_mpi_req = NULL; + struct leapraid_req *leap_mpi_req; + struct leapraid_req *ctl_sp_mpi_req; u16 taskid; void *h2c = NULL; size_t h2c_size = 0; @@ -277,74 +246,88 @@ static long leapraid_ctl_do_command(struct leapraid_adapter *adapter, u16 dev_hdl = LEAPRAID_INVALID_DEV_HANDLE; bool issue_reset = false; u32 sz; - long rc = 0; + int rc; - rc = leapraid_check_adapter_is_op(adapter); + rc = leapraid_check_adapter_is_op(adapter, LEAPRAID_DB_WAIT_OP_SHORT, + __func__); if (rc) - goto out; + return rc; leap_mpi_req = kzalloc(LEAPRAID_REQUEST_SIZE, GFP_KERNEL); - if (!leap_mpi_req) { - rc = -ENOMEM; - goto out; - } + if (!leap_mpi_req) + return -ENOMEM; - if (karg->data_sge_offset * LEAPRAID_SGE_OFFSET_SIZE > LEAPRAID_REQUEST_SIZE || - karg->data_sge_offset > ((UINT_MAX) / LEAPRAID_SGE_OFFSET_SIZE)) { + if (karg->data_sge_offset > (UINT_MAX / LEAPRAID_SGE_OFFSET_SIZE) || + karg->data_sge_offset * LEAPRAID_SGE_OFFSET_SIZE > + LEAPRAID_REQUEST_SIZE) { + dev_err(&adapter->pdev->dev, + "%s: Invalid data_sge_offset=%u\n", + __func__, karg->data_sge_offset); rc = -EINVAL; - goto out; + goto out_cleanup; } if (copy_from_user(leap_mpi_req, mf, karg->data_sge_offset * LEAPRAID_SGE_OFFSET_SIZE)) { + dev_err(&adapter->pdev->dev, + "%s: Failed to copy request message from user\n", + __func__); rc = -EFAULT; - goto out; + goto out_cleanup; } taskid = adapter->driver_cmds.ctl_cmd.taskid; adapter->driver_cmds.ctl_cmd.status = LEAPRAID_CMD_PENDING; - memset((void *)(&adapter->driver_cmds.ctl_cmd.reply), 0, - LEAPRAID_REPLY_SIEZ); + memset(&adapter->driver_cmds.ctl_cmd.reply, 0, + LEAPRAID_REPLY_SIZE); ctl_sp_mpi_req = leapraid_get_task_desc(adapter, taskid); memset(ctl_sp_mpi_req, 0, LEAPRAID_REQUEST_SIZE); memcpy(ctl_sp_mpi_req, leap_mpi_req, karg->data_sge_offset * LEAPRAID_SGE_OFFSET_SIZE); - if (ctl_sp_mpi_req->func == LEAPRAID_FUNC_SCSIIO_REQ || - ctl_sp_mpi_req->func == LEAPRAID_FUNC_RAID_SCSIIO_PASSTHROUGH || - ctl_sp_mpi_req->func == LEAPRAID_FUNC_SATA_PASSTHROUGH) { + if (ctl_sp_mpi_req->func == LEAPRAID_FUNC_SCSIIO || + ctl_sp_mpi_req->func == LEAPRAID_FUNC_SCSIIO_RAID_PASSTHROUGH || + ctl_sp_mpi_req->func == LEAPRAID_FUNC_SCSIIO_SATA_PASSTHROUGH) { dev_hdl = le16_to_cpu(ctl_sp_mpi_req->func_dep1); - if (!dev_hdl || dev_hdl > adapter->adapter_attr.features.max_dev_handle) { + if (!dev_hdl || + dev_hdl > adapter->adapter_attr.features.max_dev_handle) { + dev_err(&adapter->pdev->dev, + "%s: Invalid device handle\n", __func__); rc = -EINVAL; - goto out; + goto out_cleanup; } } - if (WARN_ON(ctl_sp_mpi_req->func == LEAPRAID_FUNC_SCSI_TMF)) - return -EINVAL; + if (WARN_ON(ctl_sp_mpi_req->func == LEAPRAID_FUNC_SCSI_TMF)) { + rc = -EINVAL; + goto out_cleanup; + } h2c_size = karg->h2c_size; c2h_size = karg->c2h_size; if (h2c_size) { h2c = dma_alloc_coherent(&adapter->pdev->dev, h2c_size, - &h2c_dma_addr, GFP_ATOMIC); + &h2c_dma_addr, GFP_KERNEL); if (!h2c) { rc = -ENOMEM; - goto out; + goto out_cleanup; } if (copy_from_user(h2c, karg->h2c_buf_ptr, h2c_size)) { + dev_err(&adapter->pdev->dev, + "%s: Failed to copy h2c from user\n", + __func__); rc = -EFAULT; - goto out; + goto out_cleanup; } } if (c2h_size) { - c2h = dma_alloc_coherent(&adapter->pdev->dev, - c2h_size, &c2h_dma_addr, GFP_ATOMIC); + c2h = dma_alloc_coherent(&adapter->pdev->dev, c2h_size, + &c2h_dma_addr, GFP_KERNEL); if (!c2h) { rc = -ENOMEM; - goto out; + goto out_cleanup; } } @@ -353,13 +336,9 @@ static long leapraid_ctl_do_command(struct leapraid_adapter *adapter, init_completion(&adapter->driver_cmds.ctl_cmd.done); switch (ctl_sp_mpi_req->func) { - case LEAPRAID_FUNC_SCSIIO_REQ: - case LEAPRAID_FUNC_RAID_SCSIIO_PASSTHROUGH: - if (test_bit(dev_hdl, (unsigned long *)adapter->dev_topo.dev_removing)) { - rc = -EINVAL; - goto out; - } - leapraid_cli_scsiio_cmd(adapter, ctl_sp_mpi_req, taskid, + case LEAPRAID_FUNC_SCSIIO: + case LEAPRAID_FUNC_SCSIIO_RAID_PASSTHROUGH: + leapraid_ctl_scsiio_cmd(adapter, ctl_sp_mpi_req, taskid, h2c_dma_addr, h2c_size, c2h_dma_addr, c2h_size, dev_hdl, psge); @@ -367,28 +346,26 @@ static long leapraid_ctl_do_command(struct leapraid_adapter *adapter, case LEAPRAID_FUNC_SMP_PASSTHROUGH: if (!h2c) { rc = -EINVAL; - goto out; + goto out_cleanup; } - leapraid_ctl_smp_passthrough_cmd(adapter, - ctl_sp_mpi_req, taskid, - h2c_dma_addr, h2c_size, - c2h_dma_addr, c2h_size, - psge, h2c); + rc = leapraid_ctl_smp_passthrough_cmd(adapter, + ctl_sp_mpi_req, taskid, + h2c_dma_addr, h2c_size, + c2h_dma_addr, c2h_size, + psge, h2c); + if (rc) + goto out_cleanup; break; - case LEAPRAID_FUNC_SATA_PASSTHROUGH: - if (test_bit(dev_hdl, (unsigned long *)adapter->dev_topo.dev_removing)) { - rc = -EINVAL; - goto out; - } - leapraid_ctl_sata_passthrough_cmd(adapter, h2c_dma_addr, - h2c_size, c2h_dma_addr, - c2h_size, psge, taskid); + case LEAPRAID_FUNC_SCSIIO_SATA_PASSTHROUGH: + leapraid_build_ieee_sg(adapter, psge, h2c_dma_addr, h2c_size, + c2h_dma_addr, c2h_size); + leapraid_fire_task(adapter, taskid); break; case LEAPRAID_FUNC_FW_DOWNLOAD: case LEAPRAID_FUNC_FW_UPLOAD: - leapraid_ctl_load_fw_cmd(adapter, h2c_dma_addr, - h2c_size, c2h_dma_addr, - c2h_size, psge, taskid); + leapraid_build_ieee_sg(adapter, psge, h2c_dma_addr, h2c_size, + c2h_dma_addr, c2h_size); + leapraid_fire_task(adapter, taskid); break; case LEAPRAID_FUNC_SAS_IO_UNIT_CTRL: leapraid_ctl_sas_io_unit_ctrl_cmd(adapter, ctl_sp_mpi_req, @@ -397,23 +374,27 @@ static long leapraid_ctl_do_command(struct leapraid_adapter *adapter, psge, taskid); break; default: - leapraid_ctl_fire_mpi_cmd(adapter, h2c_dma_addr, - h2c_size, c2h_dma_addr, - c2h_size, psge, taskid); + leapraid_build_mpi_sg(adapter, psge, h2c_dma_addr, + h2c_size, c2h_dma_addr, c2h_size); + leapraid_fire_task(adapter, taskid); break; } timeout = karg->timeout; if (timeout < LEAPRAID_CTL_CMD_TIMEOUT) timeout = LEAPRAID_CTL_CMD_TIMEOUT; - wait_for_completion_timeout(&adapter->driver_cmds.ctl_cmd.done, - timeout * HZ); + if (!wait_for_completion_timeout(&adapter->driver_cmds.ctl_cmd.done, + timeout * HZ)) { + dev_err(&adapter->pdev->dev, + "%s: ctl_cmd timeout, status=0x%x\n", + __func__, adapter->driver_cmds.ctl_cmd.status); + } if ((leap_mpi_req->func == LEAPRAID_FUNC_SMP_PASSTHROUGH || leap_mpi_req->func == LEAPRAID_FUNC_SAS_IO_UNIT_CTRL) && - adapter->reset_desc.adapter_link_resetting) { - adapter->reset_desc.adapter_link_resetting = false; - } + adapter->reset_desc.adapter_link_resetting) + adapter->reset_desc.adapter_link_resetting = 0; + if (!(adapter->driver_cmds.ctl_cmd.status & LEAPRAID_CMD_DONE)) { issue_reset = leapraid_check_reset( @@ -421,57 +402,66 @@ static long leapraid_ctl_do_command(struct leapraid_adapter *adapter, goto reset; } - if (c2h_size) { - if (copy_to_user(karg->c2h_buf_ptr, c2h, c2h_size)) { - rc = -ENODATA; - goto out; - } + if (c2h_size && copy_to_user(karg->c2h_buf_ptr, c2h, c2h_size)) { + dev_err(&adapter->pdev->dev, + "%s: Failed to copy c2h to user\n", __func__); + rc = -ENODATA; + goto out_cleanup; } if (karg->max_rep_bytes) { - sz = min_t(u32, karg->max_rep_bytes, LEAPRAID_REPLY_SIEZ); + sz = min_t(u32, karg->max_rep_bytes, LEAPRAID_REPLY_SIZE); if (copy_to_user(karg->rep_msg_buf_ptr, - (void *)&adapter->driver_cmds.ctl_cmd.reply, + &adapter->driver_cmds.ctl_cmd.reply, sz)) { + dev_err(&adapter->pdev->dev, + "%s: Failed to copy reply to user\n", + __func__); rc = -ENODATA; - goto out; + goto out_cleanup; } } if (karg->max_sense_bytes && - (leap_mpi_req->func == LEAPRAID_FUNC_SCSIIO_REQ || - leap_mpi_req->func == LEAPRAID_FUNC_RAID_SCSIIO_PASSTHROUGH)) { + (leap_mpi_req->func == LEAPRAID_FUNC_SCSIIO || + leap_mpi_req->func == LEAPRAID_FUNC_SCSIIO_RAID_PASSTHROUGH)) { if (!karg->sense_data_ptr) - goto out; + goto out_cleanup; sz = min_t(u32, karg->max_sense_bytes, SCSI_SENSE_BUFFERSIZE); if (copy_to_user(karg->sense_data_ptr, - (void *)&adapter->driver_cmds.ctl_cmd.sense, + &adapter->driver_cmds.ctl_cmd.sense, sz)) { + dev_err(&adapter->pdev->dev, + "%s: Failed to copy sense data to user\n", + __func__); rc = -ENODATA; - goto out; + goto out_cleanup; } } reset: if (issue_reset) { rc = -ENODATA; - if (leap_mpi_req->func == LEAPRAID_FUNC_SCSIIO_REQ || - leap_mpi_req->func == LEAPRAID_FUNC_RAID_SCSIIO_PASSTHROUGH || - leap_mpi_req->func == LEAPRAID_FUNC_SATA_PASSTHROUGH) { + if (leap_mpi_req->func == LEAPRAID_FUNC_SCSIIO || + leap_mpi_req->func == + LEAPRAID_FUNC_SCSIIO_RAID_PASSTHROUGH || + leap_mpi_req->func == + LEAPRAID_FUNC_SCSIIO_SATA_PASSTHROUGH) { dev_err(&adapter->pdev->dev, - "fire tgt reset: hdl=0x%04x\n", + "Fire tgt reset, hdl=0x%04x\n", le16_to_cpu(leap_mpi_req->func_dep1)); - leapraid_issue_locked_tm(adapter, + leapraid_issue_locked_tm( + adapter, le16_to_cpu(leap_mpi_req->func_dep1), 0, 0, 0, LEAPRAID_TM_TASKTYPE_TARGET_RESET, taskid, LEAPRAID_TM_MSGFLAGS_LINK_RESET); } else { dev_info(&adapter->pdev->dev, - "%s:%d call hard_reset\n", + "%s:%d: call hard_reset\n", __func__, __LINE__); leapraid_hard_reset_handler(adapter, FULL_RESET); } } -out: +out_cleanup: if (c2h) dma_free_coherent(&adapter->pdev->dev, c2h_size, c2h, c2h_dma_addr); @@ -483,12 +473,12 @@ static long leapraid_ctl_do_command(struct leapraid_adapter *adapter, return rc; } -static long leapraid_ctl_get_adapter_info(struct leapraid_adapter *adapter, - void __user *arg) +static int leapraid_ctl_get_adapter_info(struct leapraid_adapter *adapter, + void __user *arg) { struct leapraid_ioctl_adapter_info *karg; - ssize_t __maybe_unused ret; u8 revision; + int rc = 0; karg = kzalloc(sizeof(*karg), GFP_KERNEL); if (!karg) @@ -504,80 +494,98 @@ static long leapraid_ctl_get_adapter_info(struct leapraid_adapter *adapter, karg->pci_info.u.bits.func = PCI_FUNC(adapter->pdev->devfn); karg->pci_info.seg_id = pci_domain_nr(adapter->pdev->bus); karg->fw_ver = adapter->adapter_attr.features.fw_version; - ret = strscpy(karg->driver_ver, LEAPRAID_DRIVER_NAME, - sizeof(karg->driver_ver)); - strcat(karg->driver_ver, "-"); - strcat(karg->driver_ver, LEAPRAID_DRIVER_VERSION); + + snprintf(karg->driver_ver, sizeof(karg->driver_ver), "%s-%s", + LEAPRAID_DRIVER_NAME, LEAPRAID_DRIVER_VERSION); + karg->adapter_type = LEAPRAID_IOCTL_VERSION; karg->bios_ver = adapter->adapter_attr.bios_version; if (copy_to_user(arg, karg, sizeof(struct leapraid_ioctl_adapter_info))) { - kfree(karg); - return -EFAULT; + dev_err(&adapter->pdev->dev, + "%s: Failed to copy info to user\n", __func__); + rc = -EFAULT; + goto free_buf; } +free_buf: kfree(karg); - return 0; + return rc; } -static long leapraid_ctl_ioctl_main(struct file *file, unsigned int cmd, - void __user *arg, u8 compat) +static int leapraid_ctl_ioctl_main(struct file *file, unsigned int cmd, + void __user *arg) { struct leapraid_ioctl_header ioctl_header; struct leapraid_adapter *adapter; - long rc = -ENOIOCTLCMD; - int count; - - if (copy_from_user(&ioctl_header, (char __user *)arg, - sizeof(struct leapraid_ioctl_header))) + struct leapraid_ioctl_command __user *uarg; + struct leapraid_ioctl_command karg; + int rc = -ENOIOCTLCMD; + + if (copy_from_user(&ioctl_header, arg, + sizeof(struct leapraid_ioctl_header))) { + pr_err("%s:%s: Failed to copy header from user\n", + LEAPRAID_DRIVER_NAME, __func__); return -EFAULT; + } adapter = leapraid_ctl_lookup_adapter(ioctl_header.adapter_id); if (!adapter) return -EFAULT; + if (atomic_read(&adapter->overheat_desc.thermal_alert)) { + dev_warn(&adapter->pdev->dev, + "%s: Failed, thermal_alert=%d\n", + __func__, + atomic_read(&adapter->overheat_desc.thermal_alert)); + return -EFAULT; + } + mutex_lock(&adapter->access_ctrl.pci_access_lock); - rc = leapraid_check_adapter_is_op(adapter); + rc = leapraid_check_adapter_is_op(adapter, LEAPRAID_DB_WAIT_OP_LONG, + __func__); if (rc) - goto out; + goto unlock; - count = LEAPRAID_WAIT_SHOST_RECOVERY; - while (count--) { - if (!adapter->access_ctrl.shost_recovering) - break; - ssleep(1); + if (!wait_event_timeout(adapter->access_ctrl.shost_recover_wq, + !adapter->access_ctrl.shost_recover_async, + LEAPRAID_WAIT_SHOST_RECOVERY * HZ)) { + dev_warn(&adapter->pdev->dev, + "Timeout waiting for shost recovery async\n"); + rc = -EAGAIN; + goto unlock; } - if (adapter->access_ctrl.shost_recovering || - adapter->access_ctrl.pcie_recovering || + if (adapter->access_ctrl.pcie_recovering || adapter->scan_dev_desc.driver_loading || adapter->access_ctrl.host_removing) { rc = -EAGAIN; - goto out; + goto unlock; } if (file->f_flags & O_NONBLOCK) { if (!mutex_trylock(&adapter->driver_cmds.ctl_cmd.mutex)) { rc = -EAGAIN; - goto out; + goto unlock; } - } else if (mutex_lock_interruptible(&adapter->driver_cmds.ctl_cmd.mutex)) { + } else if (mutex_lock_interruptible(&adapter->driver_cmds + .ctl_cmd.mutex)) { rc = -ERESTARTSYS; - goto out; + goto unlock; } switch (_IOC_NR(cmd)) { case LEAPRAID_ADAPTER_INFO: - if (_IOC_SIZE(cmd) == sizeof(struct leapraid_ioctl_adapter_info)) + if (_IOC_SIZE(cmd) == + sizeof(struct leapraid_ioctl_adapter_info)) rc = leapraid_ctl_get_adapter_info(adapter, arg); break; case LEAPRAID_COMMAND: - { - struct leapraid_ioctl_command __user *uarg; - struct leapraid_ioctl_command karg; - if (copy_from_user(&karg, arg, sizeof(karg))) { + dev_err(&adapter->pdev->dev, + "%s: Failed to copy data from user\n", + __func__); rc = -EFAULT; break; } @@ -591,61 +599,77 @@ static long leapraid_ctl_ioctl_main(struct file *file, unsigned int cmd, uarg = arg; rc = leapraid_ctl_do_command(adapter, &karg, &uarg->mf); + if (rc) + dev_warn(&adapter->pdev->dev, + "%s: IOCTL cmd failed rc=%d\n", + __func__, rc); } break; - } case LEAPRAID_EVENTQUERY: case LEAPRAID_EVENTREPORT: rc = 0; break; default: - pr_err("unknown ioctl opcode=0x%08x\n", cmd); + dev_err(&adapter->pdev->dev, + "Unknown IOCTL opcode=0x%08x\n", cmd); break; } mutex_unlock(&adapter->driver_cmds.ctl_cmd.mutex); -out: +unlock: mutex_unlock(&adapter->access_ctrl.pci_access_lock); return rc; } +static long bad_ioctl(struct file *file, unsigned int cmd, unsigned long arg) +{ + return -ENOTTY; +} + static long leapraid_ctl_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { - return leapraid_ctl_ioctl_main(file, cmd, - (void __user *)arg, 0); + return leapraid_ctl_ioctl_main(file, cmd, (void __user *)arg); } static int leapraid_fw_mmap(struct file *filp, struct vm_area_struct *vma) { struct leapraid_adapter *adapter; + /* Userspace passes the adapter ID via vma->vm_pgoff. */ + u32 adapter_id = vma->vm_pgoff; unsigned long length; - unsigned long pfn; + int rc; length = vma->vm_end - vma->vm_start; - adapter = list_first_entry(&leapraid_adapter_list, - struct leapraid_adapter, list); + adapter = leapraid_ctl_lookup_adapter(adapter_id); + if (!adapter) { + pr_err("%s: No adapter found!\n", __func__); + return -EINVAL; + } if (length > (LEAPRAID_SYS_LOG_BUF_SIZE + LEAPRAID_SYS_LOG_BUF_RESERVE)) { dev_err(&adapter->pdev->dev, - "requested mapping size is too large!\n"); + "Requested mapping size is too large!\n"); return -EINVAL; } if (!adapter->fw_log_desc.fw_log_buffer) { - dev_err(&adapter->pdev->dev, "no log buffer!\n"); + dev_err(&adapter->pdev->dev, "No log buffer!\n"); return -EINVAL; } - pfn = virt_to_phys(adapter->fw_log_desc.fw_log_buffer) >> PAGE_SHIFT; + vma->vm_pgoff = 0; - if (remap_pfn_range(vma, vma->vm_start, pfn, length, - vma->vm_page_prot)) { + rc = dma_mmap_coherent(&adapter->pdev->dev, vma, + adapter->fw_log_desc.fw_log_buffer, + adapter->fw_log_desc.fw_log_buffer_dma, + length); + if (rc) { dev_err(&adapter->pdev->dev, - "failed to map memory to user space!\n"); - return -EAGAIN; + "Failed to map memory to user space!\n"); + return rc; } return 0; @@ -655,6 +679,7 @@ static const struct file_operations leapraid_ctl_fops = { .owner = THIS_MODULE, .unlocked_ioctl = leapraid_ctl_ioctl, .mmap = leapraid_fw_mmap, + .compat_ioctl = bad_ioctl, }; static struct miscdevice leapraid_ctl_dev = { @@ -663,10 +688,14 @@ static struct miscdevice leapraid_ctl_dev = { .fops = &leapraid_ctl_fops, }; -void leapraid_ctl_init(void) +int leapraid_ctl_init(void) { - if (misc_register(&leapraid_ctl_dev) < 0) - pr_err("%s can't register misc device\n", LEAPRAID_DRIVER_NAME); + if (misc_register(&leapraid_ctl_dev) < 0) { + pr_err("%s Can't register misc device\n", + LEAPRAID_DRIVER_NAME); + return -ENODEV; + } + return 0; } void leapraid_ctl_exit(void) diff --git a/drivers/scsi/leapraid/leapraid_func.c b/drivers/scsi/leapraid/leapraid_func.c index 5dfe95a8dd84..01096664d122 100644 --- a/drivers/scsi/leapraid/leapraid_func.c +++ b/drivers/scsi/leapraid/leapraid_func.c @@ -1,10 +1,9 @@ // SPDX-License-Identifier: GPL-2.0 /* - * Copyright (C) 2025 LeapIO Tech Inc. + * Copyright (C) 2026 LeapIO Tech Inc. * - * LeapRAID Storage and RAID Controller driver. + * LeapRAID storage and RAID controller driver. */ - #include <linux/module.h> #include "leapraid_func.h" @@ -22,11 +21,12 @@ MODULE_PARM_DESC(smart_poll, static int interrupt_mode; module_param(interrupt_mode, int, 0444); MODULE_PARM_DESC(interrupt_mode, - "intr mode: 0 for MSI-X, 1 for MSI, 2 for legacy. (default=0)"); + "intr mode: 0 is MSI-X, 1 is MSI, 2 is legacy. (default=0)"); + -static int max_msix_vectors = -1; +static int max_msix_vectors = LEAPRAID_INVALID_MSIX_VECTORS; module_param(max_msix_vectors, int, 0444); -MODULE_PARM_DESC(max_msix_vectors, " max msix vectors"); +MODULE_PARM_DESC(max_msix_vectors, "max msix vectors"); static void leapraid_remove_device(struct leapraid_adapter *adapter, struct leapraid_sas_dev *sas_dev); @@ -35,11 +35,48 @@ static void leapraid_set_led(struct leapraid_adapter *adapter, static void leapraid_ublk_io_dev(struct leapraid_adapter *adapter, u64 sas_address, struct leapraid_card_port *port); +static void leapraid_clear_cached_boot_dev(struct leapraid_adapter *adapter, + void *dev, u32 chnl); static int leapraid_make_adapter_available(struct leapraid_adapter *adapter); static int leapraid_fw_log_init(struct leapraid_adapter *adapter); +static bool leapraid_should_skip_poll_work(struct leapraid_adapter *adapter); static int leapraid_make_adapter_ready(struct leapraid_adapter *adapter, enum reset_type type); +static void leapraid_debug_log_info(struct leapraid_adapter *adapter) +{ + struct leapraid_reg_base __iomem *iomem_base = adapter->iomem_base; + u32 debug_log[LEAPRAID_DEBUGLOG_SZ_MAX]; + bool changed = false; + int i; + + if (leapraid_should_skip_poll_work(adapter)) + return; + + for (i = 0; i < LEAPRAID_DEBUGLOG_SZ_MAX; i++) { + debug_log[i] = leapraid_readl(&iomem_base->debug_log[i]); + if (debug_log[i] != adapter->fw_log_desc.pre_debug_log[i]) + changed = true; + } + + if (!changed) + return; + + memcpy(adapter->fw_log_desc.pre_debug_log, + debug_log, + sizeof(debug_log)); + + for (i = 0; i < LEAPRAID_DEBUGLOG_SZ_MAX; + i += LEAPRAID_DEBUGLOG_DWORDS_PER_LINE) + dev_warn(&adapter->pdev->dev, + "debug_log[%d-%d]: 0x%08x 0x%08x 0x%08x 0x%08x\n", + i, + i + LEAPRAID_DEBUGLOG_DWORDS_PER_LINE - 1, + debug_log[i], + debug_log[i + 1], + debug_log[i + 2], + debug_log[i + 3]); +} static inline bool leapraid_is_end_dev(u32 dev_type) { return (dev_type & LEAPRAID_DEVTYP_END_DEV) && @@ -53,12 +90,14 @@ bool leapraid_pci_removed(struct leapraid_adapter *adapter) struct pci_dev *pdev = adapter->pdev; u32 vendor_id; - if (pci_bus_read_config_dword(pdev->bus, pdev->devfn, PCI_VENDOR_ID, + if (pci_bus_read_config_dword(pdev->bus, + pdev->devfn, + PCI_VENDOR_ID, &vendor_id)) return true; - return ((vendor_id & LEAPRAID_PCI_VENDOR_ID_MASK) != - LEAPRAID_VENDOR_ID); + return (vendor_id & LEAPRAID_PCI_VENDOR_ID_MASK) != + LEAPRAID_VENDOR_ID; } static bool leapraid_pci_active(struct leapraid_adapter *adapter) @@ -78,14 +117,14 @@ void *leapraid_get_reply_vaddr(struct leapraid_adapter *adapter, u32 rep_paddr) void *leapraid_get_task_desc(struct leapraid_adapter *adapter, u16 taskid) { - return (void *)(adapter->mem_desc.task_desc + - (taskid * LEAPRAID_REQUEST_SIZE)); + return adapter->mem_desc.task_desc + + taskid * LEAPRAID_REQUEST_SIZE; } void *leapraid_get_sense_buffer(struct leapraid_adapter *adapter, u16 taskid) { - return (void *)(adapter->mem_desc.sense_data + - ((taskid - 1) * SCSI_SENSE_BUFFERSIZE)); + return adapter->mem_desc.sense_data + + (taskid - 1) * SCSI_SENSE_BUFFERSIZE; } __le32 leapraid_get_sense_buffer_dma(struct leapraid_adapter *adapter, @@ -99,7 +138,7 @@ void leapraid_mask_int(struct leapraid_adapter *adapter) { u32 reg; - adapter->mask_int = true; + adapter->mask_int = 1; reg = leapraid_readl(&adapter->iomem_base->host_int_mask); reg |= LEAPRAID_TO_SYS_DB_MASK + LEAPRAID_REPLY_INT_MASK + LEAPRAID_RESET_IRQ_MASK; @@ -114,35 +153,59 @@ void leapraid_unmask_int(struct leapraid_adapter *adapter) reg = leapraid_readl(&adapter->iomem_base->host_int_mask); reg &= ~LEAPRAID_REPLY_INT_MASK; writel(reg, &adapter->iomem_base->host_int_mask); - adapter->mask_int = false; + adapter->mask_int = 0; } -static void leapraid_flush_io_and_panic(struct leapraid_adapter *adapter) +static void leapraid_overheat_suspend(struct leapraid_adapter *adapter) { - adapter->access_ctrl.adapter_thermal_alert = true; - leapraid_smart_polling_stop(adapter); - leapraid_fw_log_stop(adapter); - leapraid_mq_polling_pause(adapter); - leapraid_clean_active_scsi_cmds(adapter); + struct workqueue_struct *wq; + struct Scsi_Host *shost; + struct pci_dev *pdev; + + if (!adapter) + return; + + pdev = adapter->pdev; + shost = pci_get_drvdata(pdev); + + if (!shost) { + dev_warn(&pdev->dev, + "Overheat suspend failed, invalid host or adapter\n"); + return; + } + + wq = adapter->overheat_desc.fault_overheat_wq; + if (!wq) + return; + + if (atomic_cmpxchg(&adapter->overheat_desc.thermal_alert, 0, 1)) + return; + + queue_work(wq, &adapter->overheat_desc.fault_overheat_work); } -static void leapraid_check_panic_needed(struct leapraid_adapter *adapter, - u32 db, u32 adapter_state) +static void leapraid_stop_adapter_on_fault(struct leapraid_adapter *adapter, + u32 db) { - bool fault_1 = adapter_state == LEAPRAID_DB_MASK; - bool fault_2 = (adapter_state == LEAPRAID_DB_FAULT) && - ((db & LEAPRAID_DB_DATA_MASK) == LEAPRAID_DB_OVER_TEMPERATURE); + u32 adapter_state = db & LEAPRAID_DB_MASK; + bool fault_1 = false; + bool fault_2 = false; + + fault_1 = adapter_state == LEAPRAID_DB_MASK; + fault_2 = adapter_state == LEAPRAID_DB_FAULT && + (db & LEAPRAID_DB_DATA_MASK) == LEAPRAID_DB_OVER_TEMPERATURE; if (!fault_1 && !fault_2) return; if (fault_1) - pr_err("%s, doorbell status 0xFFFF!\n", __func__); + dev_err(&adapter->pdev->dev, + "%s: Doorbell status 0xFFFF!\n", __func__); else - pr_err("%s, adapter overheating detected!\n", __func__); + dev_err(&adapter->pdev->dev, + "%s: Adapter overheating detected!\n", __func__); - leapraid_flush_io_and_panic(adapter); - panic("%s overheating detected, panic now!!!\n", __func__); + leapraid_overheat_suspend(adapter); } u32 leapraid_get_adapter_state(struct leapraid_adapter *adapter) @@ -152,38 +215,40 @@ u32 leapraid_get_adapter_state(struct leapraid_adapter *adapter) db = leapraid_readl(&adapter->iomem_base->db); adapter_state = db & LEAPRAID_DB_MASK; - leapraid_check_panic_needed(adapter, db, adapter_state); + leapraid_stop_adapter_on_fault(adapter, db); return adapter_state; } static bool leapraid_wait_adapter_ready(struct leapraid_adapter *adapter) { u32 cur_state; - u32 cnt = LEAPRAID_ADAPTER_READY_MAX_RETRY; + u32 cnt; - do { + for (cnt = LEAPRAID_ADAPTER_READY_MAX_RETRY; cnt > 0; cnt--) { cur_state = leapraid_get_adapter_state(adapter); + if (cur_state == LEAPRAID_DB_READY) return true; if (cur_state == LEAPRAID_DB_FAULT) break; usleep_range(LEAPRAID_ADAPTER_READY_SLEEP_MIN_US, LEAPRAID_ADAPTER_READY_SLEEP_MAX_US); - } while (--cnt); + } return false; } static int leapraid_db_wait_int_host(struct leapraid_adapter *adapter) { - u32 cnt = LEAPRAID_DB_WAIT_MAX_RETRY; + u32 cnt; - do { + for (cnt = LEAPRAID_DB_WAIT_MAX_RETRY; cnt > 0; cnt--) { if (leapraid_readl(&adapter->iomem_base->host_int_status) & LEAPRAID_ADAPTER2HOST_DB_STATUS) return 0; + udelay(LEAPRAID_DB_WAIT_DELAY_US); - } while (--cnt); + } return -EFAULT; } @@ -194,25 +259,26 @@ static int leapraid_db_wait_ack_and_clear_int(struct leapraid_adapter *adapter) u32 int_status; u32 cnt; - cnt = LEAPRAID_ADAPTER_READY_MAX_RETRY; - do { + for (cnt = LEAPRAID_ADAPTER_READY_MAX_RETRY; cnt > 0; cnt--) { int_status = leapraid_readl(&adapter->iomem_base->host_int_status); - if (!(int_status & LEAPRAID_HOST2ADAPTER_DB_STATUS)) { + + if (int_status == 0xFFFFFFFF) + return -EFAULT; + + if (!(int_status & LEAPRAID_HOST2ADAPTER_DB_STATUS)) return 0; - } else if (int_status & LEAPRAID_ADAPTER2HOST_DB_STATUS) { + + if (int_status & LEAPRAID_ADAPTER2HOST_DB_STATUS) { adapter_state = leapraid_get_adapter_state(adapter); if (adapter_state == LEAPRAID_DB_FAULT) return -EFAULT; - } else if (int_status == 0xFFFFFFFF) { - goto out; } usleep_range(LEAPRAID_ADAPTER_READY_SLEEP_MIN_US, LEAPRAID_ADAPTER_READY_SLEEP_MAX_US); - } while (--cnt); + } -out: return -EFAULT; } @@ -222,8 +288,7 @@ static int leapraid_handshake_func(struct leapraid_adapter *adapter, { int failed, i; - if ((leapraid_readl(&adapter->iomem_base->db) & - LEAPRAID_DB_USED)) { + if (leapraid_readl(&adapter->iomem_base->db) & LEAPRAID_DB_USED) { dev_err(&adapter->pdev->dev, "doorbell used\n"); return -EFAULT; } @@ -238,7 +303,7 @@ static int leapraid_handshake_func(struct leapraid_adapter *adapter, &adapter->iomem_base->db); if (leapraid_db_wait_int_host(adapter)) { - dev_err(&adapter->pdev->dev, "%d:wait db interrupt timeout\n", + dev_err(&adapter->pdev->dev, "%d: Wait db interrupt timeout\n", __LINE__); return -EFAULT; } @@ -246,7 +311,7 @@ static int leapraid_handshake_func(struct leapraid_adapter *adapter, writel(0, &adapter->iomem_base->host_int_status); if (leapraid_db_wait_ack_and_clear_int(adapter)) { - dev_err(&adapter->pdev->dev, "%d:wait ack failure\n", + dev_err(&adapter->pdev->dev, "%d: Wait ack failure\n", __LINE__); return -EFAULT; } @@ -254,12 +319,12 @@ static int leapraid_handshake_func(struct leapraid_adapter *adapter, for (i = 0, failed = 0; i < req_bytes / LEAPRAID_DWORDS_BYTE_SIZE && !failed; i++) { - writel((u32)(req[i]), &adapter->iomem_base->db); + writel((u32)req[i], &adapter->iomem_base->db); if (leapraid_db_wait_ack_and_clear_int(adapter)) failed = 1; } if (failed) { - dev_err(&adapter->pdev->dev, "%d:wait ack failure\n", + dev_err(&adapter->pdev->dev, "%d: Wait ack failure\n", __LINE__); return -EFAULT; } @@ -267,7 +332,7 @@ static int leapraid_handshake_func(struct leapraid_adapter *adapter, for (i = 0; i < rep_bytes / LEAPRAID_WORD_BYTE_SIZE; i++) { if (leapraid_db_wait_int_host(adapter)) { dev_err(&adapter->pdev->dev, - "%d:wait db interrupt timeout\n", __LINE__); + "%d: Wait db interrupt timeout\n", __LINE__); return -EFAULT; } rep[i] = (u16)(leapraid_readl(&adapter->iomem_base->db) @@ -276,7 +341,7 @@ static int leapraid_handshake_func(struct leapraid_adapter *adapter, } if (leapraid_db_wait_int_host(adapter)) { - dev_err(&adapter->pdev->dev, "%d:wait db interrupt timeout\n", + dev_err(&adapter->pdev->dev, "%d: Wait db interrupt timeout\n", __LINE__); return -EFAULT; } @@ -286,28 +351,32 @@ static int leapraid_handshake_func(struct leapraid_adapter *adapter, return 0; } -int leapraid_check_adapter_is_op(struct leapraid_adapter *adapter) +int leapraid_check_adapter_is_op(struct leapraid_adapter *adapter, int wait, + const char *caller) { - int wait_count = LEAPRAID_DB_WAIT_OPERATIONAL; + int wait_count; - do { - if (leapraid_pci_removed(adapter)) + for (wait_count = wait; wait_count > 0; wait_count--) { + if (leapraid_pci_removed(adapter)) { + dev_warn(&adapter->pdev->dev, + "%s: PCI device removed\n", __func__); return -EFAULT; + } if (leapraid_get_adapter_state(adapter) == LEAPRAID_DB_OPERATIONAL) return 0; - dev_info(&adapter->pdev->dev, - "waiting for adapter to become op status(cnt=%d)\n", - LEAPRAID_DB_WAIT_OPERATIONAL - wait_count); + dev_dbg(&adapter->pdev->dev, + "%s: Wait for adapter to become op status(cnt=%d)\n", + caller, wait - wait_count); ssleep(1); - } while (--wait_count); + } dev_err(&adapter->pdev->dev, - "adapter failed to become op state, last state=%d\n", - leapraid_get_adapter_state(adapter)); + "%s: Adapter failed to become op state, last state=%d\n", + caller, leapraid_get_adapter_state(adapter)); return -EFAULT; } @@ -325,7 +394,7 @@ struct leapraid_io_req_tracker *leapraid_get_io_tracker_from_taskid( scmd = leapraid_get_scmd_from_taskid(adapter, taskid); if (scmd) - return leapraid_get_scmd_priv(scmd); + return (struct leapraid_io_req_tracker *)scmd->host_scribble; return NULL; } @@ -350,7 +419,8 @@ static u8 leapraid_get_cb_idx(struct leapraid_adapter *adapter, u16 taskid) } struct scsi_cmnd *leapraid_get_scmd_from_taskid( - struct leapraid_adapter *adapter, u16 taskid) + struct leapraid_adapter *adapter, + u16 taskid) { struct leapraid_scsiio_req *leap_mpi_req; struct leapraid_io_req_tracker *st; @@ -367,7 +437,7 @@ struct scsi_cmnd *leapraid_get_scmd_from_taskid( scmd = scsi_host_find_tag(adapter->shost, uniq_tag); if (scmd) { - st = leapraid_get_scmd_priv(scmd); + st = (struct leapraid_io_req_tracker *)scmd->host_scribble; if (st && st->taskid == taskid) return scmd; } @@ -383,8 +453,8 @@ u16 leapraid_alloc_scsiio_taskid(struct leapraid_adapter *adapter, u32 tag = scmd->request->tag; scmd->host_scribble = - (unsigned char *)(&adapter->mem_desc.io_tracker[tag]); - request = leapraid_get_scmd_priv(scmd); + (unsigned char *)&adapter->mem_desc.io_tracker[tag]; + request = (struct leapraid_io_req_tracker *)scmd->host_scribble; taskid = tag + 1; request->taskid = taskid; request->scmd = scmd; @@ -401,8 +471,9 @@ static void leapraid_check_pending_io(struct leapraid_adapter *adapter) } } -static void leapraid_clear_io_tracker(struct leapraid_adapter *adapter, - struct leapraid_io_req_tracker *io_tracker) +static void leapraid_clear_io_tracker( + struct leapraid_adapter *adapter, + struct leapraid_io_req_tracker *io_tracker) { if (!io_tracker) return; @@ -416,17 +487,18 @@ static void leapraid_clear_io_tracker(struct leapraid_adapter *adapter, static bool leapraid_is_fixed_taskid(struct leapraid_adapter *adapter, u16 taskid) { - return (taskid == adapter->driver_cmds.ctl_cmd.taskid || - taskid == adapter->driver_cmds.driver_scsiio_cmd.taskid || - taskid == adapter->driver_cmds.tm_cmd.hp_taskid || - taskid == adapter->driver_cmds.ctl_cmd.hp_taskid || - taskid == adapter->driver_cmds.scan_dev_cmd.inter_taskid || - taskid == adapter->driver_cmds.timestamp_sync_cmd.inter_taskid || - taskid == adapter->driver_cmds.raid_action_cmd.inter_taskid || - taskid == adapter->driver_cmds.transport_cmd.inter_taskid || - taskid == adapter->driver_cmds.cfg_op_cmd.inter_taskid || - taskid == adapter->driver_cmds.enc_cmd.inter_taskid || - taskid == adapter->driver_cmds.notify_event_cmd.inter_taskid); + struct leapraid_driver_cmds *driver_cmds = &adapter->driver_cmds; + + return (taskid == driver_cmds->ctl_cmd.taskid || + taskid == driver_cmds->driver_scsiio_cmd.taskid || + taskid == driver_cmds->tm_cmd.hp_taskid || + taskid == driver_cmds->ctl_cmd.hp_taskid || + taskid == driver_cmds->scan_dev_cmd.inter_taskid || + taskid == driver_cmds->timestamp_sync_cmd.inter_taskid || + taskid == driver_cmds->transport_cmd.inter_taskid || + taskid == driver_cmds->cfg_op_cmd.inter_taskid || + taskid == driver_cmds->enc_cmd.inter_taskid || + taskid == driver_cmds->notify_event_cmd.inter_taskid); } void leapraid_free_taskid(struct leapraid_adapter *adapter, u16 taskid) @@ -516,6 +588,7 @@ void leapraid_clean_active_scsi_cmds(struct leapraid_adapter *adapter) { struct leapraid_io_req_tracker *io_tracker; struct scsi_cmnd *scmd; + void *task_desc; u16 taskid; for (taskid = 1; taskid <= adapter->shost->can_queue; taskid++) { @@ -523,15 +596,17 @@ void leapraid_clean_active_scsi_cmds(struct leapraid_adapter *adapter) if (!scmd) continue; - io_tracker = leapraid_get_scmd_priv(scmd); + io_tracker = (struct leapraid_io_req_tracker *)scmd->host_scribble; if (io_tracker && io_tracker->taskid == 0) continue; scsi_dma_unmap(scmd); + task_desc = leapraid_get_task_desc(adapter, taskid); + memset(task_desc, 0, LEAPRAID_REQUEST_SIZE); leapraid_clear_io_tracker(adapter, io_tracker); if (!leapraid_pci_active(adapter) || adapter->reset_desc.adapter_reset_results != 0 || - adapter->access_ctrl.adapter_thermal_alert || + atomic_read(&adapter->overheat_desc.thermal_alert) || adapter->access_ctrl.host_removing) scmd->result = DID_NO_CONNECT << 16; else @@ -540,36 +615,37 @@ void leapraid_clean_active_scsi_cmds(struct leapraid_adapter *adapter) } } -static void leapraid_clean_active_driver_cmd( - struct leapraid_driver_cmd *driver_cmd) +static void leapraid_clean_active_driver_cmd(struct leapraid_driver_cmd *cmd) { - if (driver_cmd->status & LEAPRAID_CMD_PENDING) { - driver_cmd->status |= LEAPRAID_CMD_RESET; - complete(&driver_cmd->done); + if (cmd->status & LEAPRAID_CMD_PENDING) { + cmd->status |= LEAPRAID_CMD_RESET; + complete(&cmd->done); } } static void leapraid_clean_active_driver_cmds(struct leapraid_adapter *adapter) { - leapraid_clean_active_driver_cmd(&adapter->driver_cmds.timestamp_sync_cmd); - leapraid_clean_active_driver_cmd(&adapter->driver_cmds.raid_action_cmd); - leapraid_clean_active_driver_cmd(&adapter->driver_cmds.driver_scsiio_cmd); - leapraid_clean_active_driver_cmd(&adapter->driver_cmds.tm_cmd); - leapraid_clean_active_driver_cmd(&adapter->driver_cmds.transport_cmd); - leapraid_clean_active_driver_cmd(&adapter->driver_cmds.enc_cmd); - leapraid_clean_active_driver_cmd(&adapter->driver_cmds.notify_event_cmd); - leapraid_clean_active_driver_cmd(&adapter->driver_cmds.cfg_op_cmd); - leapraid_clean_active_driver_cmd(&adapter->driver_cmds.ctl_cmd); - - if (adapter->driver_cmds.scan_dev_cmd.status & LEAPRAID_CMD_PENDING) { - adapter->scan_dev_desc.scan_dev_failed = true; - adapter->driver_cmds.scan_dev_cmd.status |= LEAPRAID_CMD_RESET; + struct leapraid_driver_cmds *driver_cmds; + + driver_cmds = &adapter->driver_cmds; + leapraid_clean_active_driver_cmd(&driver_cmds->timestamp_sync_cmd); + leapraid_clean_active_driver_cmd(&driver_cmds->driver_scsiio_cmd); + leapraid_clean_active_driver_cmd(&driver_cmds->tm_cmd); + leapraid_clean_active_driver_cmd(&driver_cmds->transport_cmd); + leapraid_clean_active_driver_cmd(&driver_cmds->enc_cmd); + leapraid_clean_active_driver_cmd(&driver_cmds->notify_event_cmd); + leapraid_clean_active_driver_cmd(&driver_cmds->cfg_op_cmd); + leapraid_clean_active_driver_cmd(&driver_cmds->ctl_cmd); + + if (driver_cmds->scan_dev_cmd.status & LEAPRAID_CMD_PENDING) { + adapter->scan_dev_desc.scan_dev_failed = 1; + driver_cmds->scan_dev_cmd.status |= LEAPRAID_CMD_RESET; if (adapter->scan_dev_desc.driver_loading) { adapter->scan_dev_desc.scan_start_failed = LEAPRAID_ADAPTER_STATUS_INTERNAL_ERROR; - adapter->scan_dev_desc.scan_start = false; + adapter->scan_dev_desc.scan_start = 0; } else { - complete(&adapter->driver_cmds.scan_dev_cmd.done); + complete(&driver_cmds->scan_dev_cmd.done); } } } @@ -577,10 +653,6 @@ static void leapraid_clean_active_driver_cmds(struct leapraid_adapter *adapter) static void leapraid_clean_active_cmds(struct leapraid_adapter *adapter) { leapraid_clean_active_driver_cmds(adapter); - memset(adapter->dev_topo.pending_dev_add, 0, - adapter->dev_topo.pending_dev_add_sz); - memset(adapter->dev_topo.dev_removing, 0, - adapter->dev_topo.dev_removing_sz); leapraid_clean_active_fw_evt(adapter); leapraid_clean_active_scsi_cmds(adapter); } @@ -589,9 +661,9 @@ static void leapraid_tgt_not_responding(struct leapraid_adapter *adapter, u16 hdl) { struct leapraid_starget_priv *starget_priv = NULL; - struct leapraid_sas_dev *sas_dev = NULL; + struct leapraid_sas_dev *sas_dev; unsigned long flags = 0; - u32 adapter_state = 0; + u32 adapter_state; if (adapter->access_ctrl.pcie_recovering) return; @@ -600,15 +672,15 @@ static void leapraid_tgt_not_responding(struct leapraid_adapter *adapter, if (adapter_state != LEAPRAID_DB_OPERATIONAL) return; - if (test_bit(hdl, (unsigned long *)adapter->dev_topo.pd_hdls)) + if (!hdl || hdl > adapter->adapter_attr.features.max_dev_handle || + test_bit(hdl, adapter->dev_topo.pd_hdls)) return; - clear_bit(hdl, (unsigned long *)adapter->dev_topo.pending_dev_add); spin_lock_irqsave(&adapter->dev_topo.sas_dev_lock, flags); sas_dev = leapraid_hold_lock_get_sas_dev_by_hdl(adapter, hdl); if (sas_dev && sas_dev->starget && sas_dev->starget->hostdata) { starget_priv = sas_dev->starget->hostdata; - starget_priv->deleted = true; + starget_priv->deleted = 1; } spin_unlock_irqrestore(&adapter->dev_topo.sas_dev_lock, flags); @@ -622,9 +694,9 @@ static void leapraid_tgt_not_responding(struct leapraid_adapter *adapter, static void leapraid_tgt_rst_send(struct leapraid_adapter *adapter, u16 hdl) { struct leapraid_starget_priv *starget_priv = NULL; - struct leapraid_sas_dev *sas_dev = NULL; - struct leapraid_card_port *port = NULL; - u64 sas_address = 0; + struct leapraid_sas_dev *sas_dev; + struct leapraid_card_port *port; + u64 sas_address; unsigned long flags; u32 adapter_state; @@ -635,15 +707,15 @@ static void leapraid_tgt_rst_send(struct leapraid_adapter *adapter, u16 hdl) if (adapter_state != LEAPRAID_DB_OPERATIONAL) return; - if (test_bit(hdl, (unsigned long *)adapter->dev_topo.pd_hdls)) + if (!hdl || hdl > adapter->adapter_attr.features.max_dev_handle || + test_bit(hdl, adapter->dev_topo.pd_hdls)) return; - clear_bit(hdl, (unsigned long *)adapter->dev_topo.pending_dev_add); spin_lock_irqsave(&adapter->dev_topo.sas_dev_lock, flags); sas_dev = leapraid_hold_lock_get_sas_dev_by_hdl(adapter, hdl); if (sas_dev && sas_dev->starget && sas_dev->starget->hostdata) { starget_priv = sas_dev->starget->hostdata; - starget_priv->deleted = true; + starget_priv->deleted = 1; sas_address = sas_dev->sas_addr; port = sas_dev->card_port; } @@ -657,26 +729,30 @@ static void leapraid_tgt_rst_send(struct leapraid_adapter *adapter, u16 hdl) leapraid_sdev_put(sas_dev); } -static inline void leapraid_single_mpi_sg_append(struct leapraid_adapter *adapter, - void *sge, u32 flag_and_len, - dma_addr_t dma_addr) +static inline void leapraid_single_mpi_sg_append( + struct leapraid_adapter *adapter, + void *sge, + u32 flag_and_len, + dma_addr_t dma_addr) { if (adapter->adapter_attr.use_32_dma_mask) { - ((struct leapraid_sge_simple32 *)sge)->flg_and_len = + struct leapraid_sge_simple32 *sge32 = sge; + + sge32->flg_and_len = cpu_to_le32(flag_and_len | (LEAPRAID_SGE_FLG_32 | LEAPRAID_SGE_FLG_SYSTEM_ADDR) << LEAPRAID_SGE_FLG_SHIFT); - ((struct leapraid_sge_simple32 *)sge)->addr = - cpu_to_le32(dma_addr); + sge32->addr = cpu_to_le32(dma_addr); } else { - ((struct leapraid_sge_simple64 *)sge)->flg_and_len = + struct leapraid_sge_simple64 *sge64 = sge; + + sge64->flg_and_len = cpu_to_le32(flag_and_len | (LEAPRAID_SGE_FLG_64 | LEAPRAID_SGE_FLG_SYSTEM_ADDR) << LEAPRAID_SGE_FLG_SHIFT); - ((struct leapraid_sge_simple64 *)sge)->addr = - cpu_to_le64(dma_addr); + sge64->addr = cpu_to_le64(dma_addr); } } @@ -685,11 +761,12 @@ static inline void leapraid_single_ieee_sg_append(void *sge, u8 flag, u32 len, dma_addr_t dma_addr) { - ((struct leapraid_chain64_ieee_sg *)sge)->flg = flag; - ((struct leapraid_chain64_ieee_sg *)sge)->next_chain_offset = - next_chain_offset; - ((struct leapraid_chain64_ieee_sg *)sge)->len = cpu_to_le32(len); - ((struct leapraid_chain64_ieee_sg *)sge)->addr = cpu_to_le64(dma_addr); + struct leapraid_chain64_ieee_sg *ieee_sg = sge; + + ieee_sg->flg = flag; + ieee_sg->next_chain_offset = next_chain_offset; + ieee_sg->len = cpu_to_le32(len); + ieee_sg->addr = cpu_to_le64(dma_addr); } static void leapraid_build_nodata_mpi_sg(struct leapraid_adapter *adapter, @@ -697,12 +774,12 @@ static void leapraid_build_nodata_mpi_sg(struct leapraid_adapter *adapter, { leapraid_single_mpi_sg_append(adapter, sge, - (u32)((LEAPRAID_SGE_FLG_LAST_ONE | - LEAPRAID_SGE_FLG_EOB | - LEAPRAID_SGE_FLG_EOL | - LEAPRAID_SGE_FLG_SIMPLE_ONE) << - LEAPRAID_SGE_FLG_SHIFT), - -1); + (LEAPRAID_SGE_FLG_LAST_ONE | + LEAPRAID_SGE_FLG_EOB | + LEAPRAID_SGE_FLG_EOL | + LEAPRAID_SGE_FLG_SIMPLE_ONE) << + LEAPRAID_SGE_FLG_SHIFT, + LEAPRAID_SGE_NO_DATA_ADDR); } void leapraid_build_mpi_sg(struct leapraid_adapter *adapter, void *sge, @@ -753,7 +830,7 @@ void leapraid_build_mpi_sg(struct leapraid_adapter *adapter, void *sge, c2h_size, c2h_dma_addr); } else { - return leapraid_build_nodata_mpi_sg(adapter, sge); + leapraid_build_nodata_mpi_sg(adapter, sge); } } @@ -763,7 +840,9 @@ void leapraid_build_ieee_nodata_sg(struct leapraid_adapter *adapter, void *sge) (LEAPRAID_IEEE_SGE_FLG_SIMPLE_ONE | LEAPRAID_IEEE_SGE_FLG_SYSTEM_ADDR | LEAPRAID_IEEE_SGE_FLG_EOL), - 0, 0, -1); + 0, + 0, + LEAPRAID_SGE_NO_DATA_ADDR); } int leapraid_build_scmd_ieee_sg(struct leapraid_adapter *adapter, @@ -781,7 +860,7 @@ int leapraid_build_scmd_ieee_sg(struct leapraid_adapter *adapter, u32 chain_offset_in_cur_seg; u32 chain_len_in_cur_seg; - io_tracker = leapraid_get_scmd_priv(scmd); + io_tracker = (struct leapraid_io_req_tracker *)scmd->host_scribble; scsiio_req = leapraid_get_task_desc(adapter, taskid); scmd_sg_cur = scsi_sglist(scmd); sg_entries_left = scsi_dma_map(scmd); @@ -819,7 +898,8 @@ int leapraid_build_scmd_ieee_sg(struct leapraid_adapter *adapter, if (chain_offset_in_cur_seg) chain_len_in_cur_seg += LEAPRAID_IEEE_SGE64_ENTRY_SIZE; - leapraid_single_ieee_sg_append(sg_entry_cur, + leapraid_single_ieee_sg_append( + sg_entry_cur, LEAPRAID_IEEE_SGE_FLG_CHAIN_ONE | LEAPRAID_IEEE_SGE_FLG_SYSTEM_ADDR, chain_offset_in_cur_seg, chain_len_in_cur_seg, @@ -829,7 +909,8 @@ int leapraid_build_scmd_ieee_sg(struct leapraid_adapter *adapter, goto fill_last_seg; while (sg_entries_in_cur_seg) { - leapraid_single_ieee_sg_append(sg_entry_cur, + leapraid_single_ieee_sg_append( + sg_entry_cur, LEAPRAID_IEEE_SGE_FLG_SIMPLE_ONE | LEAPRAID_IEEE_SGE_FLG_SYSTEM_ADDR, 0, sg_dma_len(scmd_sg_cur), @@ -866,39 +947,44 @@ void leapraid_build_ieee_sg(struct leapraid_adapter *adapter, void *sge, dma_addr_t h2c_dma_addr, size_t h2c_size, dma_addr_t c2h_dma_addr, size_t c2h_size) { + u32 base_flag; + u32 flag; + + base_flag = LEAPRAID_IEEE_SGE_FLG_SIMPLE_ONE | + LEAPRAID_IEEE_SGE_FLG_SYSTEM_ADDR; + if (h2c_size && !c2h_size) { + flag = base_flag | LEAPRAID_IEEE_SGE_FLG_EOL; + leapraid_single_ieee_sg_append(sge, - LEAPRAID_IEEE_SGE_FLG_SIMPLE_ONE | - LEAPRAID_IEEE_SGE_FLG_EOL | - LEAPRAID_IEEE_SGE_FLG_SYSTEM_ADDR, + flag, 0, h2c_size, h2c_dma_addr); } else if (!h2c_size && c2h_size) { + flag = base_flag | LEAPRAID_IEEE_SGE_FLG_EOL; + leapraid_single_ieee_sg_append(sge, - LEAPRAID_IEEE_SGE_FLG_SIMPLE_ONE | - LEAPRAID_IEEE_SGE_FLG_EOL | - LEAPRAID_IEEE_SGE_FLG_SYSTEM_ADDR, + flag, 0, c2h_size, c2h_dma_addr); } else if (h2c_size && c2h_size) { leapraid_single_ieee_sg_append(sge, - LEAPRAID_IEEE_SGE_FLG_SIMPLE_ONE | - LEAPRAID_IEEE_SGE_FLG_SYSTEM_ADDR, + base_flag, 0, h2c_size, h2c_dma_addr); sge += LEAPRAID_IEEE_SGE64_ENTRY_SIZE; + + flag = base_flag | LEAPRAID_IEEE_SGE_FLG_EOL; leapraid_single_ieee_sg_append(sge, - LEAPRAID_IEEE_SGE_FLG_SIMPLE_ONE | - LEAPRAID_IEEE_SGE_FLG_SYSTEM_ADDR | - LEAPRAID_IEEE_SGE_FLG_EOL, + flag, 0, c2h_size, c2h_dma_addr); } else { - return leapraid_build_ieee_nodata_sg(adapter, sge); + leapraid_build_ieee_nodata_sg(adapter, sge); } } @@ -952,8 +1038,11 @@ static struct leapraid_card_port *leapraid_get_port_by_id( if (unlikely(!adapter->adapter_attr.enable_mp)) { port = kzalloc(sizeof(*port), GFP_ATOMIC); - if (!port) + if (!port) { + dev_warn(&adapter->pdev->dev, + "%s: Failed to alloc port\n", __func__); return NULL; + } port->port_id = LEAPRAID_DISABLE_MP_PORT_ID; list_add_tail(&port->list, &adapter->dev_topo.card_port_list); @@ -980,7 +1069,8 @@ struct leapraid_vphy *leapraid_get_vphy_by_phy(struct leapraid_card_port *port, } struct leapraid_sas_dev *leapraid_hold_lock_get_sas_dev_by_addr_and_rphy( - struct leapraid_adapter *adapter, u64 sas_address, + struct leapraid_adapter *adapter, + u64 sas_address, struct sas_rphy *rphy) { struct leapraid_sas_dev *sas_dev; @@ -1010,8 +1100,10 @@ struct leapraid_sas_dev *leapraid_hold_lock_get_sas_dev_by_addr( { struct leapraid_sas_dev *sas_dev; - if (!port) + if (!port) { + dev_warn(&adapter->pdev->dev, "%s: Invalid port\n", __func__); return NULL; + } assert_spin_locked(&adapter->dev_topo.sas_dev_lock); list_for_each_entry(sas_dev, &adapter->dev_topo.sas_dev_list, list) @@ -1039,8 +1131,10 @@ struct leapraid_sas_dev *leapraid_get_sas_dev_by_addr( struct leapraid_sas_dev *sas_dev; unsigned long flags; - if (!port) + if (!port) { + dev_warn(&adapter->pdev->dev, "%s: Invalid port\n", __func__); return NULL; + } spin_lock_irqsave(&adapter->dev_topo.sas_dev_lock, flags); sas_dev = leapraid_hold_lock_get_sas_dev_by_addr(adapter, sas_address, @@ -1089,8 +1183,11 @@ void leapraid_sas_dev_remove(struct leapraid_adapter *adapter, unsigned long flags; bool del_from_list; - if (!sas_dev) + if (!sas_dev) { + dev_warn(&adapter->pdev->dev, + "%s: Invalid SAS device\n", __func__); return; + } del_from_list = false; spin_lock_irqsave(&adapter->dev_topo.sas_dev_lock, flags); @@ -1100,8 +1197,10 @@ void leapraid_sas_dev_remove(struct leapraid_adapter *adapter, } spin_unlock_irqrestore(&adapter->dev_topo.sas_dev_lock, flags); - if (del_from_list) + if (del_from_list) { + leapraid_clear_cached_boot_dev(adapter, sas_dev, 0); leapraid_sdev_put(sas_dev); + } } static void leapraid_sas_dev_remove_by_hdl(struct leapraid_adapter *adapter, @@ -1117,12 +1216,10 @@ static void leapraid_sas_dev_remove_by_hdl(struct leapraid_adapter *adapter, del_from_list = false; spin_lock_irqsave(&adapter->dev_topo.sas_dev_lock, flags); sas_dev = leapraid_hold_lock_get_sas_dev_by_hdl(adapter, hdl); - if (sas_dev) { - if (!list_empty(&sas_dev->list)) { - list_del_init(&sas_dev->list); - del_from_list = true; - leapraid_sdev_put(sas_dev); - } + if (sas_dev && (!list_empty(&sas_dev->list))) { + list_del_init(&sas_dev->list); + del_from_list = true; + leapraid_sdev_put(sas_dev); } spin_unlock_irqrestore(&adapter->dev_topo.sas_dev_lock, flags); @@ -1147,12 +1244,10 @@ void leapraid_sas_dev_remove_by_sas_address(struct leapraid_adapter *adapter, spin_lock_irqsave(&adapter->dev_topo.sas_dev_lock, flags); sas_dev = leapraid_hold_lock_get_sas_dev_by_addr(adapter, sas_address, port); - if (sas_dev) { - if (!list_empty(&sas_dev->list)) { - list_del_init(&sas_dev->list); - del_from_list = true; - leapraid_sdev_put(sas_dev); - } + if (sas_dev && (!list_empty(&sas_dev->list))) { + list_del_init(&sas_dev->list); + del_from_list = true; + leapraid_sdev_put(sas_dev); } spin_unlock_irqrestore(&adapter->dev_topo.sas_dev_lock, flags); @@ -1166,14 +1261,19 @@ struct leapraid_raid_volume *leapraid_raid_volume_find_by_id( struct leapraid_adapter *adapter, uint id, uint channel) { struct leapraid_raid_volume *raid_volume; + unsigned long flags; + spin_lock_irqsave(&adapter->dev_topo.raid_volume_lock, flags); list_for_each_entry(raid_volume, &adapter->dev_topo.raid_volume_list, list) { - if (raid_volume->id == id && - raid_volume->channel == channel) { + if (raid_volume->id == id && raid_volume->channel == channel) { + leapraid_raid_volume_get(raid_volume); + spin_unlock_irqrestore( + &adapter->dev_topo.raid_volume_lock, flags); return raid_volume; } } + spin_unlock_irqrestore(&adapter->dev_topo.raid_volume_lock, flags); return NULL; } @@ -1182,12 +1282,19 @@ struct leapraid_raid_volume *leapraid_raid_volume_find_by_hdl( struct leapraid_adapter *adapter, u16 hdl) { struct leapraid_raid_volume *raid_volume; + unsigned long flags; + spin_lock_irqsave(&adapter->dev_topo.raid_volume_lock, flags); list_for_each_entry(raid_volume, &adapter->dev_topo.raid_volume_list, list) { - if (raid_volume->hdl == hdl) + if (raid_volume->hdl == hdl) { + leapraid_raid_volume_get(raid_volume); + spin_unlock_irqrestore( + &adapter->dev_topo.raid_volume_lock, flags); return raid_volume; + } } + spin_unlock_irqrestore(&adapter->dev_topo.raid_volume_lock, flags); return NULL; } @@ -1196,12 +1303,19 @@ static struct leapraid_raid_volume *leapraid_raid_volume_find_by_wwid( struct leapraid_adapter *adapter, u64 wwid) { struct leapraid_raid_volume *raid_volume; + unsigned long flags; + spin_lock_irqsave(&adapter->dev_topo.raid_volume_lock, flags); list_for_each_entry(raid_volume, &adapter->dev_topo.raid_volume_list, list) { - if (raid_volume->wwid == wwid) + if (raid_volume->wwid == wwid) { + leapraid_raid_volume_get(raid_volume); + spin_unlock_irqrestore( + &adapter->dev_topo.raid_volume_lock, flags); return raid_volume; + } } + spin_unlock_irqrestore(&adapter->dev_topo.raid_volume_lock, flags); return NULL; } @@ -1212,6 +1326,7 @@ static void leapraid_raid_volume_add(struct leapraid_adapter *adapter, unsigned long flags; spin_lock_irqsave(&adapter->dev_topo.raid_volume_lock, flags); + leapraid_raid_volume_get(raid_volume); list_add_tail(&raid_volume->list, &adapter->dev_topo.raid_volume_list); spin_unlock_irqrestore(&adapter->dev_topo.raid_volume_lock, flags); } @@ -1220,11 +1335,24 @@ void leapraid_raid_volume_remove(struct leapraid_adapter *adapter, struct leapraid_raid_volume *raid_volume) { unsigned long flags; + bool del_from_list = false; + + if (!raid_volume) { + dev_warn(&adapter->pdev->dev, + "%s: Invalid RAID volume\n", __func__); + return; + } spin_lock_irqsave(&adapter->dev_topo.raid_volume_lock, flags); - list_del(&raid_volume->list); - kfree(raid_volume); + if (!list_empty(&raid_volume->list)) { + list_del_init(&raid_volume->list); + del_from_list = true; + } spin_unlock_irqrestore(&adapter->dev_topo.raid_volume_lock, flags); + + leapraid_clear_cached_boot_dev(adapter, raid_volume, RAID_CHANNEL); + if (del_from_list) + leapraid_raid_volume_put(raid_volume); } static struct leapraid_enc_node *leapraid_enc_find_by_hdl( @@ -1232,10 +1360,9 @@ static struct leapraid_enc_node *leapraid_enc_find_by_hdl( { struct leapraid_enc_node *enc_dev; - list_for_each_entry(enc_dev, &adapter->dev_topo.enc_list, list) { + list_for_each_entry(enc_dev, &adapter->dev_topo.enc_list, list) if (le16_to_cpu(enc_dev->pg0.enc_hdl) == hdl) return enc_dev; - } return NULL; } @@ -1246,15 +1373,19 @@ struct leapraid_topo_node *leapraid_exp_find_by_sas_address( { struct leapraid_topo_node *sas_exp; - if (!port) + if (!port) { + dev_warn(&adapter->pdev->dev, "%s: Invalid port\n", __func__); return NULL; + } - list_for_each_entry(sas_exp, &adapter->dev_topo.exp_list, list) { + list_for_each_entry(sas_exp, &adapter->dev_topo.exp_list, list) if (sas_exp->sas_address == sas_address && sas_exp->card_port == port) return sas_exp; - } + dev_warn(&adapter->pdev->dev, + "%s: No expander found for SAS addr=0x%016llx port=%p\n", + __func__, (unsigned long long)sas_address, port); return NULL; } @@ -1301,10 +1432,9 @@ static struct leapraid_topo_node *leapraid_exp_find_by_hdl( { struct leapraid_topo_node *sas_exp; - list_for_each_entry(sas_exp, &adapter->dev_topo.exp_list, list) { + list_for_each_entry(sas_exp, &adapter->dev_topo.exp_list, list) if (sas_exp->hdl == hdl) return sas_exp; - } return NULL; } @@ -1332,7 +1462,7 @@ static enum leapraid_card_port_checking_flg leapraid_get_card_port_feature( return CARD_PORT_FURTHER_CHECKING_NEEDED; } -static int leapraid_process_card_port_feature( +static bool leapraid_process_card_port_feature( struct leapraid_card_port_feature *feature) { struct leapraid_card_port *old_card_port; @@ -1341,8 +1471,10 @@ static int leapraid_process_card_port_feature( if (feature->exact_phy) { feature->checking_state = SAME_PORT_WITH_NOTHING_CHANGED; feature->expected_old_port = old_card_port; - return 1; - } else if (feature->phy_overlap) { + return true; + } + + if (feature->phy_overlap) { if (feature->same_port) { feature->checking_state = SAME_PORT_WITH_PARTIALLY_CHANGED_PHYS; @@ -1353,21 +1485,20 @@ static int leapraid_process_card_port_feature( SAME_ADDR_WITH_PARTIALLY_CHANGED_PHYS; feature->expected_old_port = old_card_port; } - } else { - if (feature->checking_state != - SAME_PORT_WITH_PARTIALLY_CHANGED_PHYS && - feature->checking_state != - SAME_ADDR_WITH_PARTIALLY_CHANGED_PHYS) { - feature->checking_state = SAME_ADDR_ONLY; - feature->expected_old_port = old_card_port; - feature->same_addr_port_count++; - } + } else if (feature->checking_state != + SAME_PORT_WITH_PARTIALLY_CHANGED_PHYS && + feature->checking_state != + SAME_ADDR_WITH_PARTIALLY_CHANGED_PHYS) { + feature->checking_state = SAME_ADDR_ONLY; + feature->expected_old_port = old_card_port; + feature->same_addr_port_count++; } - return 0; + return false; } -static int leapraid_check_card_port(struct leapraid_adapter *adapter, +static int leapraid_check_card_port( + struct leapraid_adapter *adapter, struct leapraid_card_port *card_port, struct leapraid_card_port **expected_card_port, int *count) @@ -1413,7 +1544,8 @@ static void leapraid_del_phy_part_of_anther_port( continue; if (card_port_table[i].phy_mask & BIT(offset)) { - leapraid_transport_detach_phy_to_port(adapter, + leapraid_transport_detach_phy_to_port( + adapter, card_topo_node, &card_topo_node->card_phy[offset]); found = true; @@ -1433,7 +1565,7 @@ static void leapraid_add_or_del_phys_from_existing_port( { struct leapraid_topo_node *card_topo_node; u32 phy_mask_diff; - u32 offset = 0; + u32 offset; card_topo_node = &adapter->dev_topo.card; phy_mask_diff = card_port->phy_mask ^ @@ -1451,12 +1583,15 @@ static void leapraid_add_or_del_phys_from_existing_port( } if (card_topo_node->card_phy[offset].phy_is_assigned) - leapraid_transport_detach_phy_to_port(adapter, + leapraid_transport_detach_phy_to_port( + adapter, card_topo_node, &card_topo_node->card_phy[offset]); - leapraid_transport_attach_phy_to_port(adapter, - card_topo_node, &card_topo_node->card_phy[offset], + leapraid_transport_attach_phy_to_port( + adapter, + card_topo_node, + &card_topo_node->card_phy[offset], card_port->sas_address, card_port); } @@ -1471,7 +1606,8 @@ struct leapraid_sas_dev *leapraid_get_next_sas_dev_from_init_list( spin_lock_irqsave(&adapter->dev_topo.sas_dev_lock, flags); if (!list_empty(&adapter->dev_topo.sas_dev_init_list)) { sas_dev = list_first_entry(&adapter->dev_topo.sas_dev_init_list, - struct leapraid_sas_dev, list); + struct leapraid_sas_dev, + list); leapraid_sdev_get(sas_dev); } spin_unlock_irqrestore(&adapter->dev_topo.sas_dev_lock, flags); @@ -1483,37 +1619,66 @@ static bool leapraid_check_boot_dev_internal(u64 sas_address, u64 dev_name, struct leapraid_boot_dev *boot_dev, u8 form) { + struct leapraid_boot_dev_format_sas_wwid *wwid; + struct leapraid_boot_dev_format_enc_slot *es; + struct leapraid_boot_dev_format_dev_name *dn; + void *pg_dev; + if (!boot_dev) return false; + pg_dev = boot_dev->pg_dev; switch (form & LEAPRAID_BOOTDEV_FORM_MASK) { case LEAPRAID_BOOTDEV_FORM_SAS_WWID: + wwid = pg_dev; + if (!sas_address) return false; - return sas_address == - le64_to_cpu(((struct leapraid_boot_dev_format_sas_wwid *)( - boot_dev->pg_dev))->sas_addr); + return sas_address == le64_to_cpu(wwid->sas_addr); case LEAPRAID_BOOTDEV_FORM_ENC_SLOT: + es = pg_dev; + if (!enc_lid) return false; - return (enc_lid == le64_to_cpu(((struct leapraid_boot_dev_format_enc_slot *)( - boot_dev->pg_dev))->enc_lid) && - slot == le16_to_cpu(((struct leapraid_boot_dev_format_enc_slot *)( - boot_dev->pg_dev))->slot_num)); + return (enc_lid == le64_to_cpu(es->enc_lid) && + slot == le16_to_cpu(es->slot_num)); case LEAPRAID_BOOTDEV_FORM_DEV_NAME: + dn = pg_dev; + if (!dev_name) return false; - return dev_name == le64_to_cpu(((struct leapraid_boot_dev_format_dev_name *)( - boot_dev->pg_dev))->dev_name); + return dev_name == le64_to_cpu(dn->dev_name); case LEAPRAID_BOOTDEV_FORM_NONE: default: return false; } } +void leapraid_boot_dev_get(void *dev, u32 chnl) +{ + if (!dev) + return; + + if (chnl == RAID_CHANNEL) + leapraid_raid_volume_get((struct leapraid_raid_volume *)dev); + else + leapraid_sdev_get((struct leapraid_sas_dev *)dev); +} + +void leapraid_boot_dev_put(void *dev, u32 chnl) +{ + if (!dev) + return; + + if (chnl == RAID_CHANNEL) + leapraid_raid_volume_put((struct leapraid_raid_volume *)dev); + else + leapraid_sdev_put((struct leapraid_sas_dev *)dev); +} + static void leapraid_try_set_boot_dev(struct leapraid_boot_dev *boot_dev, u64 sas_addr, u64 dev_name, u64 enc_lid, u16 slot, @@ -1528,15 +1693,56 @@ static void leapraid_try_set_boot_dev(struct leapraid_boot_dev *boot_dev, slot, boot_dev, boot_dev->form); if (matched) { + leapraid_boot_dev_get(dev, chnl); boot_dev->dev = dev; boot_dev->chnl = chnl; } } +static void leapraid_clear_boot_dev(struct leapraid_adapter *adapter, + struct leapraid_boot_dev *boot_dev, + void *dev, u32 chnl) +{ + void *cached_dev; + u32 cached_chnl; + unsigned long flags; + + spin_lock_irqsave(&adapter->boot_devs.lock, flags); + if (boot_dev->dev != dev || boot_dev->chnl != chnl) + goto out_unlock; + + cached_dev = boot_dev->dev; + cached_chnl = boot_dev->chnl; + boot_dev->dev = NULL; + boot_dev->chnl = 0; + spin_unlock_irqrestore(&adapter->boot_devs.lock, flags); + leapraid_boot_dev_put(cached_dev, cached_chnl); + return; + +out_unlock: + spin_unlock_irqrestore(&adapter->boot_devs.lock, flags); +} + +static void leapraid_clear_cached_boot_dev(struct leapraid_adapter *adapter, + void *dev, u32 chnl) +{ + leapraid_clear_boot_dev(adapter, + &adapter->boot_devs.requested_boot_dev, + dev, chnl); + leapraid_clear_boot_dev(adapter, + &adapter->boot_devs.requested_alt_boot_dev, + dev, chnl); + leapraid_clear_boot_dev(adapter, + &adapter->boot_devs.current_boot_dev, + dev, chnl); +} + static void leapraid_check_boot_dev(struct leapraid_adapter *adapter, void *dev, u32 chnl) { - u64 sas_addr = 0; + struct leapraid_raid_volume *raid_volume; + struct leapraid_sas_dev *sas_dev; + u64 sas_addr; u64 dev_name = 0; u64 enc_lid = 0; u16 slot = 0; @@ -1546,24 +1752,17 @@ static void leapraid_check_boot_dev(struct leapraid_adapter *adapter, switch (chnl) { case RAID_CHANNEL: - { - struct leapraid_raid_volume *raid_volume = - (struct leapraid_raid_volume *)dev; - + raid_volume = dev; sas_addr = raid_volume->wwid; break; - } default: - { - struct leapraid_sas_dev *sas_dev = - (struct leapraid_sas_dev *)dev; + sas_dev = dev; sas_addr = sas_dev->sas_addr; dev_name = sas_dev->dev_name; enc_lid = sas_dev->enc_lid; slot = sas_dev->slot; break; } - } leapraid_try_set_boot_dev(&adapter->boot_devs.requested_boot_dev, sas_addr, dev_name, enc_lid, @@ -1576,17 +1775,272 @@ static void leapraid_check_boot_dev(struct leapraid_adapter *adapter, slot, dev, chnl); } -static void leapraid_build_and_fire_cfg_req(struct leapraid_adapter *adapter, +static const char *leapraid_func_name(u8 func) +{ + switch (func) { + case LEAPRAID_FUNC_SCSIIO: + return "SCSIIO"; + case LEAPRAID_FUNC_SCSI_TMF: + return "SCSI_TMF"; + case LEAPRAID_FUNC_ADAPTER_INIT: + return "ADAPTER_INIT"; + case LEAPRAID_FUNC_GET_ADAPTER_FEATURES: + return "GET_ADAPTER_FEATURES"; + case LEAPRAID_FUNC_CONFIG_OP: + return "CONFIG_OP"; + case LEAPRAID_FUNC_SCAN_DEV: + return "SCAN_DEV"; + case LEAPRAID_FUNC_EVENT_NOTIFY: + return "EVENT_NOTIFY"; + case LEAPRAID_FUNC_FW_DOWNLOAD: + return "FW_DOWNLOAD"; + case LEAPRAID_FUNC_FW_UPLOAD: + return "FW_UPLOAD"; + case LEAPRAID_FUNC_SCSIIO_RAID_PASSTHROUGH: + return "SCSIIO_RAID_PASSTHROUGH"; + case LEAPRAID_FUNC_SCSI_ENC_PROCESSOR: + return "SCSI_ENC_PROCESSOR"; + case LEAPRAID_FUNC_SMP_PASSTHROUGH: + return "SMP_PASSTHROUGH"; + case LEAPRAID_FUNC_SAS_IO_UNIT_CTRL: + return "SAS_IO_UNIT_CTRL"; + case LEAPRAID_FUNC_SCSIIO_SATA_PASSTHROUGH: + return "SCSIIO_SATA_PASSTHROUGH"; + case LEAPRAID_FUNC_ADAPTER_UNIT_RESET: + return "ADAPTER_UNIT_RESET"; + case LEAPRAID_FUNC_HANDSHAKE: + return "HANDSHAKE"; + case LEAPRAID_FUNC_LOGBUF_INIT: + return "LOGBUF_INIT"; + default: + return "UNKNOWN"; + } +} + +static const char *leapraid_cfg_action_name(u8 action) +{ + switch (action) { + case LEAPRAID_CFG_ACT_PAGE_HEADER: + return "PAGE_HEADER"; + case LEAPRAID_CFG_ACT_PAGE_READ_CUR: + return "PAGE_READ_CUR"; + case LEAPRAID_CFG_ACT_PAGE_WRITE_CUR: + return "PAGE_WRITE_CUR"; + default: + return "UNKNOWN"; + } +} + +static const char *leapraid_cfg_page_type_name(u8 page_type) +{ + switch (page_type) { + case LEAPRAID_CFG_PT_IO_UNIT: + return "IO_UNIT"; + case LEAPRAID_CFG_PT_ADAPTER: + return "ADAPTER"; + case LEAPRAID_CFG_PT_BIOS: + return "BIOS"; + case LEAPRAID_CFG_PT_RAID_VOLUME: + return "RAID_VOLUME"; + case LEAPRAID_CFG_PT_MANUFACTURING: + return "MANUFACTURING"; + case LEAPRAID_CFG_PT_RAID_PHYSDISK: + return "RAID_PHYSDISK"; + case LEAPRAID_CFG_PT_EXTENDED: + return "EXTENDED"; + default: + return "UNKNOWN"; + } +} + +static const char *leapraid_cfg_ext_page_type_name(u8 ext_page_type) +{ + switch (ext_page_type) { + case LEAPRAID_CFG_EXTPT_SAS_IO_UNIT: + return "SAS_IO_UNIT"; + case LEAPRAID_CFG_EXTPT_SAS_EXP: + return "SAS_EXPANDER"; + case LEAPRAID_CFG_EXTPT_SAS_DEV: + return "SAS_DEVICE"; + case LEAPRAID_CFG_EXTPT_SAS_PHY: + return "SAS_PHY"; + case LEAPRAID_CFG_EXTPT_ENC: + return "ENCLOSURE"; + case LEAPRAID_CFG_EXTPT_RAID_CONFIG: + return "RAID_CONFIG"; + default: + return "UNKNOWN"; + } +} + +static const char *leapraid_sep_action_name(u8 action) +{ + switch (action) { + case LEAPRAID_SEP_REQ_ACT_WRITE_STATUS: + return "WRITE_STATUS"; + default: + return "UNKNOWN"; + } +} + +static const char *leapraid_sas_op_name(u8 op) +{ + switch (op) { + case LEAPRAID_SAS_OP_PHY_LINK_RESET: + return "PHY_LINK_RESET"; + case LEAPRAID_SAS_OP_PHY_HARD_RESET: + return "PHY_HARD_RESET"; + case LEAPRAID_SAS_OP_SET_PARAMETER: + return "SET_PARAMETER"; + default: + return "UNKNOWN"; + } +} + +static const char *leapraid_io_param_name(u8 adapter_param) +{ + switch (adapter_param) { + case LEAPRAID_SET_PARAMETER_SYNC_TIMESTAMP: + return "SYNC_TIMESTAMP"; + default: + return "UNKNOWN"; + } +} + +static const char *leapraid_tm_type_name(u8 task_type) +{ + switch (task_type) { + case LEAPRAID_TM_TASKTYPE_ABORT_TASK: + return "ABORT_TASK"; + case LEAPRAID_TM_TASKTYPE_ABRT_TASK_SET: + return "ABORT_TASK_SET"; + case LEAPRAID_TM_TASKTYPE_TARGET_RESET: + return "TARGET_RESET"; + case LEAPRAID_TM_TASKTYPE_LOGICAL_UNIT_RESET: + return "LOGICAL_UNIT_RESET"; + case LEAPRAID_TM_TASKTYPE_CLEAR_TASK_SET: + return "CLEAR_TASK_SET"; + case LEAPRAID_TM_TASKTYPE_QUERY_TASK: + return "QUERY_TASK"; + case LEAPRAID_TM_TASKTYPE_CLEAR_ACA: + return "CLEAR_ACA"; + case LEAPRAID_TM_TASKTYPE_QUERY_TASK_SET: + return "QUERY_TASK_SET"; + case LEAPRAID_TM_TASKTYPE_QUERY_ASYNC_EVENT: + return "QUERY_ASYNC_EVENT"; + default: + return "UNKNOWN"; + } +} + +void leapraid_log_req_context(struct leapraid_adapter *adapter, + const void *req_data) +{ + const struct leapraid_req *req = req_data; + + if (!adapter || !adapter->pdev || !req_data) + return; + + switch (req->func) { + case LEAPRAID_FUNC_CONFIG_OP: { + const struct leapraid_cfg_req *cfg_req = req_data; + + dev_err(&adapter->pdev->dev, + "cfg-req: func=0x%02x(%s) act=0x%02x(%s)\n", + req->func, leapraid_func_name(req->func), + cfg_req->action, + leapraid_cfg_action_name(cfg_req->action)); + dev_err(&adapter->pdev->dev, + "cfg-req: page_type=0x%02x(%s) page_num=%u\n", + cfg_req->header.page_type, + leapraid_cfg_page_type_name(cfg_req->header.page_type), + cfg_req->header.page_num); + if (cfg_req->header.page_type == LEAPRAID_CFG_PT_EXTENDED) + dev_err(&adapter->pdev->dev, + "cfg-req: ext_page_type=0x%02x(%s)\n", + cfg_req->ext_page_type, + leapraid_cfg_ext_page_type_name( + cfg_req->ext_page_type)); + dev_err(&adapter->pdev->dev, "cfg-req: page_addr=0x%08x\n", + le32_to_cpu(cfg_req->page_addr)); + break; + } + case LEAPRAID_FUNC_SCSI_TMF: { + const struct leapraid_scsi_tm_req *tm_req = req_data; + + dev_err(&adapter->pdev->dev, + "scsi_tm: func=0x%02x(%s) task=0x%02x(%s)\n", + req->func, leapraid_func_name(req->func), + tm_req->task_type, + leapraid_tm_type_name(tm_req->task_type)); + dev_err(&adapter->pdev->dev, + "scsi_tm: dev_hdl=0x%04x task_mid=%u\n", + le16_to_cpu(tm_req->dev_hdl), + le16_to_cpu(tm_req->task_mid)); + break; + } + case LEAPRAID_FUNC_SCSI_ENC_PROCESSOR: { + const struct leapraid_sep_req *sep_req = req_data; + + dev_err(&adapter->pdev->dev, + "sep: func=0x%02x(%s) act=0x%02x(%s)\n", + req->func, leapraid_func_name(req->func), + sep_req->act, + leapraid_sep_action_name(sep_req->act)); + dev_err(&adapter->pdev->dev, + "sep: dev_hdl=0x%04x slot=%u enc_hdl=0x%04x\n", + le16_to_cpu(sep_req->dev_hdl), + le16_to_cpu(sep_req->slot), + le16_to_cpu(sep_req->enc_hdl)); + break; + } + case LEAPRAID_FUNC_SAS_IO_UNIT_CTRL: { + const struct leapraid_io_unit_ctrl_req *io_req = req_data; + + dev_err(&adapter->pdev->dev, + "timestamp sync: func=0x%02x(%s) op=0x%02x(%s)\n", + req->func, leapraid_func_name(req->func), + io_req->op, leapraid_sas_op_name(io_req->op)); + dev_err(&adapter->pdev->dev, + "timestamp sync: dev_hdl=0x%04x param=0x%02x(%s)\n", + le16_to_cpu(io_req->dev_hdl), + io_req->adapter_para, + leapraid_io_param_name(io_req->adapter_para)); + break; + } + case LEAPRAID_FUNC_SMP_PASSTHROUGH: { + const struct leapraid_smp_passthrough_req *smp_req = req_data; + + dev_err(&adapter->pdev->dev, + "transport: func=0x%02x(%s) port=%u req_len=%u\n", + req->func, leapraid_func_name(req->func), + smp_req->physical_port, + le16_to_cpu(smp_req->req_data_len)); + dev_err(&adapter->pdev->dev, "transport: sas_addr=0x%016llx\n", + (unsigned long long)le64_to_cpu(smp_req->sas_address)); + break; + } + default: + dev_err(&adapter->pdev->dev, + "%s: func=0x%02x(%s)\n", + __func__, req->func, leapraid_func_name(req->func)); + break; + } +} + +static void leapraid_build_and_fire_cfg_req( + struct leapraid_adapter *adapter, struct leapraid_cfg_req *leap_mpi_cfgp_req, struct leapraid_cfg_rep *leap_mpi_cfgp_rep) { struct leapraid_cfg_req *local_leap_cfg_req; memset(leap_mpi_cfgp_rep, 0, sizeof(struct leapraid_cfg_rep)); - memset((void *)(&adapter->driver_cmds.cfg_op_cmd.reply), 0, + memset(&adapter->driver_cmds.cfg_op_cmd.reply, 0, sizeof(struct leapraid_cfg_rep)); adapter->driver_cmds.cfg_op_cmd.status = LEAPRAID_CMD_PENDING; - local_leap_cfg_req = leapraid_get_task_desc(adapter, + local_leap_cfg_req = leapraid_get_task_desc( + adapter, adapter->driver_cmds.cfg_op_cmd.inter_taskid); memcpy(local_leap_cfg_req, leap_mpi_cfgp_req, sizeof(struct leapraid_cfg_req)); @@ -1614,17 +2068,18 @@ static int leapraid_req_cfg_func(struct leapraid_adapter *adapter, if (retry_cnt) { if (retry_cnt > LEAPRAID_CFG_REQ_RETRY_TIMES) { rc = -EFAULT; - goto out; + goto out_cleanup; } dev_warn(&adapter->pdev->dev, - "cfg-req: retry request, cnt=%u\n", retry_cnt); + "cfg-req: Retry request, cnt=%u\n", retry_cnt); } - rc = leapraid_check_adapter_is_op(adapter); + rc = leapraid_check_adapter_is_op(adapter, LEAPRAID_DB_WAIT_OP_SHORT, + __func__); if (rc) { dev_err(&adapter->pdev->dev, - "cfg-req: adapter not operational\n"); - goto out; + "cfg-req: Adapter not operational\n"); + goto out_cleanup; } leapraid_build_and_fire_cfg_req(adapter, leap_mpi_cfgp_req, @@ -1634,44 +2089,47 @@ static int leapraid_req_cfg_func(struct leapraid_adapter *adapter, if (adapter->driver_cmds.cfg_op_cmd.status & LEAPRAID_CMD_RESET) { dev_warn(&adapter->pdev->dev, - "cfg-req: cmd gg due to hard reset\n"); + "cfg-req: CMD fail due to hard reset\n"); goto retry; } if (adapter->access_ctrl.shost_recovering || adapter->access_ctrl.pcie_recovering) { dev_err(&adapter->pdev->dev, - "cfg-req: cmd not done during %s, skip reset\n", + "cfg-req: pending in %s, status=0x%x\n", adapter->access_ctrl.shost_recovering ? - "shost recovery" : "pcie recovery"); + "shost recovery" : "pcie recovery", + adapter->driver_cmds.cfg_op_cmd.status); + leapraid_log_req_context(adapter, leap_mpi_cfgp_req); issue_reset = false; rc = -EFAULT; } else { dev_err(&adapter->pdev->dev, - "cfg-req: cmd timeout, issuing hard reset\n"); + "cfg-req: timeout, status=0x%x, reset\n", + adapter->driver_cmds.cfg_op_cmd.status); + leapraid_log_req_context(adapter, leap_mpi_cfgp_req); issue_reset = true; } - goto out; + goto out_cleanup; } if (adapter->driver_cmds.cfg_op_cmd.status & LEAPRAID_CMD_REPLY_VALID) { memcpy(leap_mpi_cfgp_rep, - (void *)(&adapter->driver_cmds.cfg_op_cmd.reply), + &adapter->driver_cmds.cfg_op_cmd.reply, sizeof(struct leapraid_cfg_rep)); adapter_status = le16_to_cpu( leap_mpi_cfgp_rep->adapter_status) & LEAPRAID_ADAPTER_STATUS_MASK; - if (adapter_status == LEAPRAID_ADAPTER_STATUS_SUCCESS) { - if (target_cfg_pg && real_cfg_pg_addr && - target_real_cfg_pg_sz) - if (leap_mpi_cfgp_req->action == - LEAPRAID_CFG_ACT_PAGE_READ_CUR) - memcpy(target_cfg_pg, - real_cfg_pg_addr, - target_real_cfg_pg_sz); - } else { + if (adapter_status == LEAPRAID_ADAPTER_STATUS_SUCCESS && + target_cfg_pg && real_cfg_pg_addr && + target_real_cfg_pg_sz && + leap_mpi_cfgp_req->action == + LEAPRAID_CFG_ACT_PAGE_READ_CUR) + memcpy(target_cfg_pg, real_cfg_pg_addr, + target_real_cfg_pg_sz); + if (adapter_status != LEAPRAID_ADAPTER_STATUS_SUCCESS) { if (adapter_status != LEAPRAID_ADAPTER_STATUS_CONFIG_INVALID_PAGE) dev_err(&adapter->pdev->dev, @@ -1680,30 +2138,30 @@ static int leapraid_req_cfg_func(struct leapraid_adapter *adapter, rc = -EFAULT; } } else { - dev_err(&adapter->pdev->dev, "cfg-rep: reply invalid\n"); + dev_err(&adapter->pdev->dev, "cfg-rep: Reply invalid\n"); rc = -EFAULT; } -out: +out_cleanup: adapter->driver_cmds.cfg_op_cmd.status = LEAPRAID_CMD_NOT_USED; mutex_unlock(&adapter->driver_cmds.cfg_op_cmd.mutex); if (issue_reset) { if (adapter->scan_dev_desc.first_scan_dev_fired) { dev_info(&adapter->pdev->dev, - "%s:%d cfg-req: failure, issuing reset\n", + "%s:%d cfg-req: Failure, issuing reset\n", __func__, __LINE__); leapraid_hard_reset_handler(adapter, FULL_RESET); - rc = -EFAULT; } else { dev_warn(&adapter->pdev->dev, - "cfg-req: cmd gg during init, skip reset\n"); - rc = -EFAULT; + "cfg-req: CMD fail in init, skip reset\n"); } + rc = -EFAULT; } return rc; } -static int leapraid_request_cfg_pg_header(struct leapraid_adapter *adapter, +static int leapraid_request_cfg_pg_header( + struct leapraid_adapter *adapter, struct leapraid_cfg_req *leap_mpi_cfgp_req, struct leapraid_cfg_rep *leap_mpi_cfgp_rep) { @@ -1729,8 +2187,8 @@ int leapraid_op_config_page(struct leapraid_adapter *adapter, { struct leapraid_cfg_req leap_mpi_cfgp_req; struct leapraid_cfg_rep leap_mpi_cfgp_rep; - u16 real_cfg_pg_sz = 0; - void *real_cfg_pg_addr = NULL; + u16 real_cfg_pg_sz; + void *real_cfg_pg_addr; dma_addr_t real_cfg_pg_dma = 0; u32 __page_size; int rc; @@ -1752,6 +2210,13 @@ int leapraid_op_config_page(struct leapraid_adapter *adapter, LEAPRAID_CFG_PAGE_NUM_BIOS2; __page_size = sizeof(struct leapraid_bios_page2); break; + case GET_MANUFACTURING_PG0: + leap_mpi_cfgp_req.header.page_type = + LEAPRAID_CFG_PT_MANUFACTURING; + leap_mpi_cfgp_req.header.page_num = + LEAPRAID_CFG_PAGE_NUM_MANU0; + __page_size = sizeof(struct leapraid_manufacturing_p0); + break; case GET_SAS_DEVICE_PG0: leap_mpi_cfgp_req.header.page_type = LEAPRAID_CFG_PT_EXTENDED; leap_mpi_cfgp_req.ext_page_type = LEAPRAID_CFG_EXTPT_SAS_DEV; @@ -1818,9 +2283,8 @@ int leapraid_op_config_page(struct leapraid_adapter *adapter, break; default: dev_err(&adapter->pdev->dev, - "unsupported config page action=%d!\n", cfg_op); - rc = -EINVAL; - goto out; + "Unsupported config page action=%d!\n", cfg_op); + return -EINVAL; } leapraid_build_nodata_mpi_sg(adapter, @@ -1830,8 +2294,8 @@ int leapraid_op_config_page(struct leapraid_adapter *adapter, &leap_mpi_cfgp_rep); if (rc) { dev_err(&adapter->pdev->dev, - "cfg-req: header failed rc=%dn", rc); - goto out; + "cfg-req: Header failed rc=%dn", rc); + return rc; } if (cfg_op == GET_SAS_DEVICE_PG0 || @@ -1867,17 +2331,14 @@ int leapraid_op_config_page(struct leapraid_adapter *adapter, leap_mpi_cfgp_req.ext_page_type = leap_mpi_cfgp_rep.ext_page_type; real_cfg_pg_sz = (leap_mpi_cfgp_req.header.page_len) ? - leap_mpi_cfgp_req.header.page_len * 4 : - le16_to_cpu(leap_mpi_cfgp_rep.ext_page_len) * 4; + leap_mpi_cfgp_req.header.page_len * sizeof(u32) : + le16_to_cpu(leap_mpi_cfgp_rep.ext_page_len) * sizeof(u32); real_cfg_pg_addr = dma_alloc_coherent(&adapter->pdev->dev, real_cfg_pg_sz, &real_cfg_pg_dma, GFP_KERNEL); - if (!real_cfg_pg_addr) { - dev_err(&adapter->pdev->dev, "cfg-req: dma alloc failed\n"); - rc = -ENOMEM; - goto out; - } + if (!real_cfg_pg_addr) + return -ENOMEM; if (leap_mpi_cfgp_req.action == LEAPRAID_CFG_ACT_PAGE_WRITE_CUR) { leapraid_single_mpi_sg_append(adapter, @@ -1914,12 +2375,11 @@ int leapraid_op_config_page(struct leapraid_adapter *adapter, real_cfg_pg_addr, min_t(u16, real_cfg_pg_sz, __page_size)); if (rc) { - u32 adapter_status; + u32 status; - adapter_status = le16_to_cpu(leap_mpi_cfgp_rep.adapter_status) & - LEAPRAID_ADAPTER_STATUS_MASK; - if (adapter_status != - LEAPRAID_ADAPTER_STATUS_CONFIG_INVALID_PAGE) + status = le16_to_cpu(leap_mpi_cfgp_rep.adapter_status) & + LEAPRAID_ADAPTER_STATUS_MASK; + if (status != LEAPRAID_ADAPTER_STATUS_CONFIG_INVALID_PAGE) dev_err(&adapter->pdev->dev, "cfg-req: rc=%d, pg_info: 0x%x, 0x%x, %d\n", rc, leap_mpi_cfgp_req.header.page_type, @@ -1932,10 +2392,52 @@ int leapraid_op_config_page(struct leapraid_adapter *adapter, real_cfg_pg_sz, real_cfg_pg_addr, real_cfg_pg_dma); -out: + return rc; } +static int leapraid_cfg_find_vol_in_page( + struct leapraid_raid_cfg_p0 *raid_cfg_p0, + u16 pd_hdl, u16 *vol_hdl) +{ + u16 elements = raid_cfg_p0->elements_num; + int i; + + for (i = 0; i < elements; i++) { + struct leapraid_raid_cfg_p0_element *elem; + u16 type; + + elem = &raid_cfg_p0->cfg_element[i]; + + type = le16_to_cpu(elem->element_flg) & + LEAPRAID_RAIDCFG_P0_EFLG_MASK_ELEMENT_TYPE; + + switch (type) { + case LEAPRAID_RAIDCFG_P0_EFLG_VOL_PHYS_DISK_ELEMENT: + case LEAPRAID_RAIDCFG_P0_EFLG_OCE_ELEMENT: { + u16 phys_hdl; + + phys_hdl = le16_to_cpu(elem->phys_disk_dev_hdl); + + if (phys_hdl == pd_hdl) { + *vol_hdl = le16_to_cpu(elem->vol_dev_hdl); + return 0; + } + break; + } + + case LEAPRAID_RAIDCFG_P0_EFLG_HOT_SPARE_ELEMENT: + *vol_hdl = 0; + return 0; + + default: + break; + } + } + + return -ENOENT; +} + static int leapraid_cfg_get_volume_hdl_dispatch( struct leapraid_adapter *adapter, struct leapraid_cfg_req *cfg_req, @@ -1946,13 +2448,11 @@ static int leapraid_cfg_get_volume_hdl_dispatch( u16 raid_cfg_p0_sz, u16 pd_hdl, u16 *vol_hdl) { - u16 phys_disk_dev_hdl; u16 adapter_status; - u16 element_type; int config_num; - int rc, i; + int rc; - config_num = 0xff; + config_num = 0xFF; while (true) { cfg_req->page_addr = cpu_to_le32(config_num + @@ -1973,35 +2473,14 @@ static int leapraid_cfg_get_volume_hdl_dispatch( } if (adapter_status != LEAPRAID_ADAPTER_STATUS_SUCCESS) - return -1; - - for (i = 0; i < raid_cfg_p0->elements_num; i++) { - element_type = - le16_to_cpu(raid_cfg_p0->cfg_element[i].element_flg) & - LEAPRAID_RAIDCFG_P0_EFLG_MASK_ELEMENT_TYPE; - - switch (element_type) { - case LEAPRAID_RAIDCFG_P0_EFLG_VOL_PHYS_DISK_ELEMENT: - case LEAPRAID_RAIDCFG_P0_EFLG_OCE_ELEMENT: - phys_disk_dev_hdl = - le16_to_cpu(raid_cfg_p0->cfg_element[i] - .phys_disk_dev_hdl); - if (phys_disk_dev_hdl == pd_hdl) { - *vol_hdl = - le16_to_cpu - (raid_cfg_p0->cfg_element[i] - .vol_dev_hdl); - return 0; - } - break; + return LEAPRAID_OPERATION_FAILED; + + rc = leapraid_cfg_find_vol_in_page(raid_cfg_p0, + pd_hdl, + vol_hdl); + if (rc != -ENOENT) + return rc; - case LEAPRAID_RAIDCFG_P0_EFLG_HOT_SPARE_ELEMENT: - *vol_hdl = 0; - return 0; - default: - break; - } - } config_num = raid_cfg_p0->cfg_num; } return 0; @@ -2010,12 +2489,12 @@ static int leapraid_cfg_get_volume_hdl_dispatch( int leapraid_cfg_get_volume_hdl(struct leapraid_adapter *adapter, u16 pd_hdl, u16 *vol_hdl) { - struct leapraid_raid_cfg_p0 *raid_cfg_p0 = NULL; + struct leapraid_raid_cfg_p0 *raid_cfg_p0; struct leapraid_cfg_req cfg_req; struct leapraid_cfg_rep cfg_rep; dma_addr_t real_cfg_pg_dma = 0; - void *real_cfg_pg_addr = NULL; - u16 real_cfg_pg_sz = 0; + void *real_cfg_pg_addr; + u16 real_cfg_pg_sz; int rc, raid_cfg_p0_sz; *vol_hdl = 0; @@ -2029,16 +2508,14 @@ int leapraid_cfg_get_volume_hdl(struct leapraid_adapter *adapter, leapraid_build_nodata_mpi_sg(adapter, &cfg_req.page_buf_sge); rc = leapraid_request_cfg_pg_header(adapter, &cfg_req, &cfg_rep); if (rc) - goto out; + return rc; cfg_req.action = LEAPRAID_CFG_ACT_PAGE_READ_CUR; raid_cfg_p0_sz = le16_to_cpu(cfg_rep.ext_page_len) * LEAPRAID_CFG_UNIT_SIZE; raid_cfg_p0 = kmalloc(raid_cfg_p0_sz, GFP_KERNEL); - if (!raid_cfg_p0) { - rc = -1; - goto out; - } + if (!raid_cfg_p0) + return -ENOMEM; real_cfg_pg_sz = (cfg_req.header.page_len) ? cfg_req.header.page_len * LEAPRAID_CFG_UNIT_SIZE : @@ -2049,7 +2526,7 @@ int leapraid_cfg_get_volume_hdl(struct leapraid_adapter *adapter, GFP_KERNEL); if (!real_cfg_pg_addr) { rc = -ENOMEM; - goto out; + goto out_free; } memset(raid_cfg_p0, 0, raid_cfg_p0_sz); @@ -2073,7 +2550,7 @@ int leapraid_cfg_get_volume_hdl(struct leapraid_adapter *adapter, raid_cfg_p0_sz, pd_hdl, vol_hdl); -out: +out_free: if (real_cfg_pg_addr) dma_free_coherent(&adapter->pdev->dev, real_cfg_pg_sz, real_cfg_pg_addr, @@ -2088,7 +2565,7 @@ static int leapraid_get_adapter_phys(struct leapraid_adapter *adapter, struct leapraid_sas_io_unit_p0 sas_io_unit_page0; union cfg_param_1 cfgp1 = {0}; union cfg_param_2 cfgp2 = {0}; - int rc = 0; + int rc; *nr_phys = 0; cfgp1.size = sizeof(struct leapraid_sas_io_unit_p0); @@ -2141,7 +2618,8 @@ int leapraid_cfg_get_volume_wwid(struct leapraid_adapter *adapter, return rc; } -static int leapraid_get_sas_io_unit_page0(struct leapraid_adapter *adapter, +static int leapraid_get_sas_io_unit_page0( + struct leapraid_adapter *adapter, struct leapraid_sas_io_unit_p0 *sas_io_unit_p0, u16 sas_iou_pg0_sz) { @@ -2163,8 +2641,8 @@ static int leapraid_get_sas_address(struct leapraid_adapter *adapter, *sas_address = 0; cfgp1.form = LEAPRAID_SAS_DEV_CFG_PGAD_HDL; cfgp2.handle = hdl; - if ((leapraid_op_config_page(adapter, &sas_dev_p0, cfgp1, - cfgp2, GET_SAS_DEVICE_PG0))) + if (leapraid_op_config_page(adapter, &sas_dev_p0, cfgp1, + cfgp2, GET_SAS_DEVICE_PG0)) return -ENXIO; if (hdl <= adapter->dev_topo.card.phys_num && @@ -2186,9 +2664,10 @@ int leapraid_get_volume_cap(struct leapraid_adapter *adapter, struct leapraid_raidpd_p0 raidpd_p0; u8 num_pds; u16 sz; + int rc = 0; - if ((leapraid_cfg_get_number_pds(adapter, raid_volume->hdl, - &num_pds)) || !num_pds) + if (leapraid_cfg_get_number_pds(adapter, raid_volume->hdl, + &num_pds) || !num_pds) return -EFAULT; raid_volume->pd_num = num_pds; @@ -2196,14 +2675,14 @@ int leapraid_get_volume_cap(struct leapraid_adapter *adapter, (num_pds * sizeof(struct leapraid_raidvol0_phys_disk)); raidvol_p0 = kzalloc(sz, GFP_KERNEL); if (!raidvol_p0) - return -EFAULT; + return -ENOMEM; cfgp1.size = sz; cfgp2.handle = raid_volume->hdl; - if ((leapraid_op_config_page(adapter, raidvol_p0, cfgp1, cfgp2, - GET_RAID_VOLUME_PG0))) { - kfree(raidvol_p0); - return -EFAULT; + if (leapraid_op_config_page(adapter, raidvol_p0, cfgp1, cfgp2, + GET_RAID_VOLUME_PG0)) { + rc = -EFAULT; + goto out_cleanup; } raid_volume->vol_type = raidvol_p0->volume_type; @@ -2214,14 +2693,28 @@ int leapraid_get_volume_cap(struct leapraid_adapter *adapter, cfgp1.form = LEAPRAID_SAS_DEV_CFG_PGAD_HDL; cfgp2.handle = le16_to_cpu(raidpd_p0.dev_hdl); if (!(leapraid_op_config_page(adapter, &sas_dev_p0, cfgp1, - cfgp2, GET_SAS_DEVICE_PG0))) { + cfgp2, GET_SAS_DEVICE_PG0))) raid_volume->dev_info = le32_to_cpu(sas_dev_p0.dev_info); - } } +out_cleanup: kfree(raidvol_p0); - return 0; + return rc; +} + +static bool leapraid_should_skip_poll_work(struct leapraid_adapter *adapter) +{ + unsigned long flags; + bool skip; + + spin_lock_irqsave(&adapter->reset_desc.adapter_reset_lock, flags); + skip = adapter->access_ctrl.shost_recovering || + adapter->access_ctrl.pcie_recovering || + adapter->access_ctrl.host_removing; + spin_unlock_irqrestore(&adapter->reset_desc.adapter_reset_lock, flags); + + return skip; } static void leapraid_fw_log_work(struct work_struct *work) @@ -2229,26 +2722,34 @@ static void leapraid_fw_log_work(struct work_struct *work) struct leapraid_adapter *adapter = container_of(work, struct leapraid_adapter, fw_log_desc.fw_log_work.work); struct leapraid_fw_log_info *infom; + struct leapraid_reg_base __iomem *iomem_base; unsigned long flags; - infom = (struct leapraid_fw_log_info *)(adapter->fw_log_desc.fw_log_buffer + - LEAPRAID_SYS_LOG_BUF_SIZE); + if (leapraid_should_skip_poll_work(adapter)) + goto scheduled_timer; + + infom = (struct leapraid_fw_log_info *) + (adapter->fw_log_desc.fw_log_buffer + + LEAPRAID_SYS_LOG_BUF_SIZE); + iomem_base = adapter->iomem_base; if (adapter->fw_log_desc.fw_log_init_flag == 0) { infom->user_position = - leapraid_readl(&adapter->iomem_base->host_log_buf_pos); + leapraid_readl(&iomem_base->host_log_buf_pos); infom->adapter_position = - leapraid_readl(&adapter->iomem_base->adapter_log_buf_pos); + leapraid_readl(&iomem_base->adapter_log_buf_pos); adapter->fw_log_desc.fw_log_init_flag++; } - writel(infom->user_position, &adapter->iomem_base->host_log_buf_pos); + writel(infom->user_position, &iomem_base->host_log_buf_pos); infom->adapter_position = - leapraid_readl(&adapter->iomem_base->adapter_log_buf_pos); + leapraid_readl(&iomem_base->adapter_log_buf_pos); +scheduled_timer: spin_lock_irqsave(&adapter->reset_desc.adapter_reset_lock, flags); if (adapter->fw_log_desc.fw_log_wq) - queue_delayed_work(adapter->fw_log_desc.fw_log_wq, + queue_delayed_work( + adapter->fw_log_desc.fw_log_wq, &adapter->fw_log_desc.fw_log_work, msecs_to_jiffies(LEAPRAID_PCIE_LOG_POLLING_INTERVAL)); spin_unlock_irqrestore(&adapter->reset_desc.adapter_reset_lock, flags); @@ -2267,7 +2768,8 @@ void leapraid_fw_log_stop(struct leapraid_adapter *adapter) adapter->fw_log_desc.fw_log_wq = NULL; spin_unlock_irqrestore(&adapter->reset_desc.adapter_reset_lock, flags); if (wq) { - if (!cancel_delayed_work_sync(&adapter->fw_log_desc.fw_log_work)) + if (!cancel_delayed_work_sync(&adapter->fw_log_desc + .fw_log_work)) flush_workqueue(wq); destroy_workqueue(wq); } @@ -2297,7 +2799,8 @@ void leapraid_fw_log_start(struct leapraid_adapter *adapter) spin_lock_irqsave(&adapter->reset_desc.adapter_reset_lock, flags); if (adapter->fw_log_desc.fw_log_wq) - queue_delayed_work(adapter->fw_log_desc.fw_log_wq, + queue_delayed_work( + adapter->fw_log_desc.fw_log_wq, &adapter->fw_log_desc.fw_log_work, msecs_to_jiffies(LEAPRAID_PCIE_LOG_POLLING_INTERVAL)); spin_unlock_irqrestore(&adapter->reset_desc.adapter_reset_lock, flags); @@ -2308,12 +2811,13 @@ static void leapraid_timestamp_sync(struct leapraid_adapter *adapter) struct leapraid_io_unit_ctrl_req *io_unit_ctrl_req; ktime_t current_time; bool issue_reset = false; - u64 time_stamp = 0; + u64 time_stamp; mutex_lock(&adapter->driver_cmds.timestamp_sync_cmd.mutex); adapter->driver_cmds.timestamp_sync_cmd.status = LEAPRAID_CMD_PENDING; io_unit_ctrl_req = - leapraid_get_task_desc(adapter, + leapraid_get_task_desc( + adapter, adapter->driver_cmds.timestamp_sync_cmd.inter_taskid); memset(io_unit_ctrl_req, 0, sizeof(struct leapraid_io_unit_ctrl_req)); io_unit_ctrl_req->func = LEAPRAID_FUNC_SAS_IO_UNIT_CTRL; @@ -2328,18 +2832,27 @@ static void leapraid_timestamp_sync(struct leapraid_adapter *adapter) io_unit_ctrl_req->adapter_para_value2 = cpu_to_le32(time_stamp >> 32); init_completion(&adapter->driver_cmds.timestamp_sync_cmd.done); - leapraid_fire_task(adapter, - adapter->driver_cmds.timestamp_sync_cmd.inter_taskid); - wait_for_completion_timeout(&adapter->driver_cmds.timestamp_sync_cmd.done, + leapraid_fire_task( + adapter, + adapter->driver_cmds.timestamp_sync_cmd.inter_taskid); + leapraid_debug_log_info(adapter); + wait_for_completion_timeout(&adapter->driver_cmds + .timestamp_sync_cmd.done, LEAPRAID_TIMESTAMP_SYNC_CMD_TIMEOUT * HZ); if (!(adapter->driver_cmds.timestamp_sync_cmd.status & - LEAPRAID_CMD_DONE)) + LEAPRAID_CMD_DONE)) { + dev_err(&adapter->pdev->dev, + "%s: timestamp sync timeout, status=0x%x\n", + __func__, + adapter->driver_cmds.timestamp_sync_cmd.status); + leapraid_log_req_context(adapter, io_unit_ctrl_req); issue_reset = leapraid_check_reset( adapter->driver_cmds.timestamp_sync_cmd.status); + } if (issue_reset) { - dev_info(&adapter->pdev->dev, "%s:%d call hard_reset\n", + dev_info(&adapter->pdev->dev, "%s:%d: call hard_reset\n", __func__, __LINE__); leapraid_hard_reset_handler(adapter, FULL_RESET); } @@ -2348,20 +2861,6 @@ static void leapraid_timestamp_sync(struct leapraid_adapter *adapter) mutex_unlock(&adapter->driver_cmds.timestamp_sync_cmd.mutex); } -static bool leapraid_should_skip_fault_check(struct leapraid_adapter *adapter) -{ - unsigned long flags; - bool skip; - - spin_lock_irqsave(&adapter->reset_desc.adapter_reset_lock, flags); - skip = adapter->access_ctrl.shost_recovering || - adapter->access_ctrl.pcie_recovering || - adapter->access_ctrl.host_removing; - spin_unlock_irqrestore(&adapter->reset_desc.adapter_reset_lock, flags); - - return skip; -} - static void leapraid_check_scheduled_fault_work(struct work_struct *work) { struct leapraid_adapter *adapter; @@ -2372,16 +2871,16 @@ static void leapraid_check_scheduled_fault_work(struct work_struct *work) adapter = container_of(work, struct leapraid_adapter, reset_desc.fault_reset_work.work); - if (leapraid_should_skip_fault_check(adapter)) + if (leapraid_should_skip_poll_work(adapter)) goto scheduled_timer; adapter_state = leapraid_get_adapter_state(adapter); if (adapter_state != LEAPRAID_DB_OPERATIONAL) { - dev_info(&adapter->pdev->dev, "%s:%d call hard_reset\n", + dev_info(&adapter->pdev->dev, "%s:%d: call hard_reset\n", __func__, __LINE__); rc = leapraid_hard_reset_handler(adapter, FULL_RESET); - dev_warn(&adapter->pdev->dev, "%s: hard reset: %s\n", - __func__, (rc == 0) ? "success" : "failed"); + dev_warn(&adapter->pdev->dev, "%s: Hard reset %s\n", + __func__, rc == 0 ? "success" : "failed"); adapter_state = leapraid_get_adapter_state(adapter); if (rc && adapter_state != LEAPRAID_DB_OPERATIONAL) @@ -2397,7 +2896,8 @@ static void leapraid_check_scheduled_fault_work(struct work_struct *work) scheduled_timer: spin_lock_irqsave(&adapter->reset_desc.adapter_reset_lock, flags); if (adapter->reset_desc.fault_reset_wq) - queue_delayed_work(adapter->reset_desc.fault_reset_wq, + queue_delayed_work( + adapter->reset_desc.fault_reset_wq, &adapter->reset_desc.fault_reset_work, msecs_to_jiffies(LEAPRAID_FAULT_POLLING_INTERVAL)); spin_unlock_irqrestore(&adapter->reset_desc.adapter_reset_lock, flags); @@ -2422,14 +2922,15 @@ void leapraid_check_scheduled_fault_start(struct leapraid_adapter *adapter) adapter->reset_desc.fault_reset_wq_name); if (!adapter->reset_desc.fault_reset_wq) { dev_err(&adapter->pdev->dev, - "create single thread workqueue failed!\n"); + "Create single thread workqueue failed!\n"); return; } spin_lock_irqsave(&adapter->reset_desc.adapter_reset_lock, flags); if (adapter->reset_desc.fault_reset_wq) - queue_delayed_work(adapter->reset_desc.fault_reset_wq, - &adapter->reset_desc.fault_reset_work, + queue_delayed_work( + adapter->reset_desc.fault_reset_wq, + &adapter->reset_desc.fault_reset_work, msecs_to_jiffies(LEAPRAID_FAULT_POLLING_INTERVAL)); spin_unlock_irqrestore(&adapter->reset_desc.adapter_reset_lock, flags); } @@ -2456,17 +2957,24 @@ static bool leapraid_ready_for_scsi_io(struct leapraid_adapter *adapter, u16 hdl) { if (adapter->access_ctrl.pcie_recovering || - adapter->access_ctrl.shost_recovering) - return false; - - if (leapraid_check_adapter_is_op(adapter)) + adapter->access_ctrl.shost_recovering) { + dev_err(&adapter->pdev->dev, + "%s: Failed, pcie_recovering=%d shost_recovering=%d\n", + __func__, + adapter->access_ctrl.pcie_recovering, + adapter->access_ctrl.shost_recovering); return false; + } - if (hdl == LEAPRAID_INVALID_DEV_HANDLE) + if (leapraid_check_adapter_is_op(adapter, LEAPRAID_DB_WAIT_OP_SHORT, + __func__)) return false; - if (test_bit(hdl, (unsigned long *)adapter->dev_topo.dev_removing)) + if (hdl == LEAPRAID_INVALID_DEV_HANDLE) { + dev_err(&adapter->pdev->dev, + "%s: Device handle is invalid\n", __func__); return false; + } return true; } @@ -2475,13 +2983,13 @@ static int leapraid_dispatch_scsi_io(struct leapraid_adapter *adapter, struct leapraid_scsi_cmd_desc *cmd_desc) { struct scsi_device *sdev; + struct scsi_device *target_sdev = NULL; struct leapraid_sdev_priv *sdev_priv; struct scsi_cmnd *scmd; void *dma_buffer = NULL; - dma_addr_t dma_addr = 0; - u8 sdev_flg = 0; + dma_addr_t dma_addr; bool issue_reset = false; - int rc = 0; + int rc; if (WARN_ON(!adapter->driver_cmds.internal_scmd)) return -EINVAL; @@ -2492,23 +3000,28 @@ static int leapraid_dispatch_scsi_io(struct leapraid_adapter *adapter, mutex_lock(&adapter->driver_cmds.driver_scsiio_cmd.mutex); if (adapter->driver_cmds.driver_scsiio_cmd.status != LEAPRAID_CMD_NOT_USED) { + dev_err(&adapter->pdev->dev, + "%s: scsiio cmd busy\n", __func__); rc = -EAGAIN; - goto out; + goto out_cleanup; } adapter->driver_cmds.driver_scsiio_cmd.status = LEAPRAID_CMD_PENDING; - __shost_for_each_device(sdev, adapter->shost) { + shost_for_each_device(sdev, adapter->shost) { sdev_priv = sdev->hostdata; + if (sdev_priv->starget_priv->hdl == cmd_desc->hdl && sdev_priv->lun == cmd_desc->lun) { - sdev_flg = 1; + target_sdev = sdev; break; } } - if (!sdev_flg) { + if (!target_sdev) { + dev_warn(&adapter->pdev->dev, + "%s: Device not found\n", __func__); rc = -ENXIO; - goto out; + goto out_cleanup; } if (cmd_desc->data_length) { @@ -2517,7 +3030,7 @@ static int leapraid_dispatch_scsi_io(struct leapraid_adapter *adapter, &dma_addr, GFP_ATOMIC); if (!dma_buffer) { rc = -ENOMEM; - goto out; + goto out_cleanup; } if (cmd_desc->dir == DMA_TO_DEVICE) memcpy(dma_buffer, cmd_desc->data_buffer, @@ -2525,7 +3038,7 @@ static int leapraid_dispatch_scsi_io(struct leapraid_adapter *adapter, } scmd = adapter->driver_cmds.internal_scmd; - scmd->device = sdev; + scmd->device = target_sdev; scmd->cmd_len = cmd_desc->cdb_length; memcpy(scmd->cmnd, cmd_desc->cdb, cmd_desc->cdb_length); scmd->sc_data_direction = cmd_desc->dir; @@ -2538,11 +3051,14 @@ static int leapraid_dispatch_scsi_io(struct leapraid_adapter *adapter, adapter->driver_cmds.driver_scsiio_cmd.status &= ~LEAPRAID_CMD_PENDING; complete(&adapter->driver_cmds.driver_scsiio_cmd.done); + dev_err(&adapter->pdev->dev, + "%s: queuecommand failed\n", __func__); rc = -EINVAL; - goto out; + goto out_cleanup; } - wait_for_completion_timeout(&adapter->driver_cmds.driver_scsiio_cmd.done, + wait_for_completion_timeout(&adapter->driver_cmds + .driver_scsiio_cmd.done, cmd_desc->time_out * HZ); if (!(adapter->driver_cmds.driver_scsiio_cmd.status & @@ -2564,15 +3080,22 @@ static int leapraid_dispatch_scsi_io(struct leapraid_adapter *adapter, rc = -ENODATA; dev_err(&adapter->pdev->dev, "fire tgt reset: hdl=0x%04x\n", cmd_desc->hdl); - leapraid_issue_locked_tm(adapter, cmd_desc->hdl, 0, 0, 0, + leapraid_issue_locked_tm( + adapter, cmd_desc->hdl, 0, 0, 0, LEAPRAID_TM_TASKTYPE_TARGET_RESET, adapter->driver_cmds.driver_scsiio_cmd.taskid, LEAPRAID_TM_MSGFLAGS_LINK_RESET); } -out: +out_cleanup: + if (target_sdev) + scsi_device_put(target_sdev); + if (dma_buffer) dma_free_coherent(&adapter->pdev->dev, - cmd_desc->data_length, dma_buffer, dma_addr); + cmd_desc->data_length, + dma_buffer, + dma_addr); + adapter->driver_cmds.driver_scsiio_cmd.status = LEAPRAID_CMD_NOT_USED; mutex_unlock(&adapter->driver_cmds.driver_scsiio_cmd.mutex); return rc; @@ -2582,7 +3105,8 @@ static int leapraid_dispatch_logsense(struct leapraid_adapter *adapter, u16 hdl, u32 lun) { struct leapraid_scsi_cmd_desc *desc; - int rc = 0; + char *buf; + int rc; desc = kzalloc(sizeof(*desc), GFP_KERNEL); if (!desc) @@ -2596,7 +3120,7 @@ static int leapraid_dispatch_logsense(struct leapraid_adapter *adapter, desc->cdb[0] = LOG_SENSE; desc->cdb[2] = LEAPRAID_LOGSENSE_CDB_CODE; desc->cdb[8] = desc->data_length; - desc->raid_member = false; + desc->raid_member = 0; desc->time_out = LEAPRAID_LOGSENSE_TIMEOUT; desc->data_buffer = kzalloc(desc->data_length, GFP_KERNEL); @@ -2606,11 +3130,10 @@ static int leapraid_dispatch_logsense(struct leapraid_adapter *adapter, } rc = leapraid_dispatch_scsi_io(adapter, desc); - if (!rc) { - if (((char *)desc->data_buffer)[8] == - LEAPRAID_LOGSENSE_SMART_CODE) - leapraid_smart_fault_detect(adapter, hdl); - } + buf = desc->data_buffer; + + if (!rc && buf[8] == LEAPRAID_LOGSENSE_SMART_CODE) + leapraid_smart_fault_detect(adapter, hdl); kfree(desc->data_buffer); kfree(desc); @@ -2622,31 +3145,32 @@ static bool leapraid_smart_poll_check(struct leapraid_adapter *adapter, struct leapraid_sdev_priv *sdev_priv, u32 reset_flg) { - struct leapraid_sas_dev *sas_dev = NULL; + struct leapraid_sas_dev *sas_dev; if (!sdev_priv || !sdev_priv->starget_priv->card_port) - goto out; + return false; - sas_dev = leapraid_get_sas_dev_by_addr(adapter, - sdev_priv->starget_priv->sas_address, - sdev_priv->starget_priv->card_port); + sas_dev = leapraid_get_sas_dev_by_addr( + adapter, + sdev_priv->starget_priv->sas_address, + sdev_priv->starget_priv->card_port); if (!sas_dev || !sas_dev->support_smart) - goto out; + goto out_fail; if (reset_flg) - sas_dev->led_on = false; + sas_dev->led_on = 0; else if (sas_dev->led_on) - goto out; + goto out_fail; - if ((sdev_priv->starget_priv->flg & LEAPRAID_TGT_FLG_RAID_MEMBER) || - (sdev_priv->starget_priv->flg & LEAPRAID_TGT_FLG_VOLUME) || + if (sdev_priv->starget_priv->flg & LEAPRAID_TGT_FLG_RAID_MEMBER || + sdev_priv->starget_priv->flg & LEAPRAID_TGT_FLG_VOLUME || sdev_priv->block) - goto out; + goto out_fail; leapraid_sdev_put(sas_dev); return true; -out: +out_fail: if (sas_dev) leapraid_sdev_put(sas_dev); return false; @@ -2659,16 +3183,21 @@ static void leapraid_sata_smart_poll_work(struct work_struct *work) smart_poll_desc.smart_poll_work.work); struct scsi_device *sdev; struct leapraid_sdev_priv *sdev_priv; - static u32 reset_cnt; bool reset_flg = false; - if (leapraid_check_adapter_is_op(adapter)) - goto out; + if (leapraid_should_skip_poll_work(adapter)) + goto scheduled_timer; + + if (leapraid_check_adapter_is_op(adapter, LEAPRAID_DB_WAIT_OP_SHORT, + __func__)) + goto scheduled_timer; + + if (adapter->reset_desc.last_reset_cnt < adapter->reset_desc.reset_cnt) + reset_flg = true; - reset_flg = (reset_cnt < adapter->reset_desc.reset_cnt); - reset_cnt = adapter->reset_desc.reset_cnt; + adapter->reset_desc.last_reset_cnt = adapter->reset_desc.reset_cnt; - __shost_for_each_device(sdev, adapter->shost) { + shost_for_each_device(sdev, adapter->shost) { sdev_priv = sdev->hostdata; if (leapraid_smart_poll_check(adapter, sdev_priv, reset_flg)) leapraid_dispatch_logsense(adapter, @@ -2676,11 +3205,12 @@ static void leapraid_sata_smart_poll_work(struct work_struct *work) sdev_priv->lun); } -out: +scheduled_timer: if (adapter->smart_poll_desc.smart_poll_wq) - queue_delayed_work(adapter->smart_poll_desc.smart_poll_wq, - &adapter->smart_poll_desc.smart_poll_work, - msecs_to_jiffies(LEAPRAID_SMART_POLLING_INTERVAL)); + queue_delayed_work( + adapter->smart_poll_desc.smart_poll_wq, + &adapter->smart_poll_desc.smart_poll_work, + msecs_to_jiffies(LEAPRAID_SMART_POLLING_INTERVAL)); } void leapraid_smart_polling_start(struct leapraid_adapter *adapter) @@ -2709,20 +3239,118 @@ void leapraid_smart_polling_start(struct leapraid_adapter *adapter) void leapraid_smart_polling_stop(struct leapraid_adapter *adapter) { struct workqueue_struct *wq; + struct leapraid_smart_poll_desc *desc; - if (!adapter->smart_poll_desc.smart_poll_wq) + desc = &adapter->smart_poll_desc; + if (!desc->smart_poll_wq) return; - wq = adapter->smart_poll_desc.smart_poll_wq; - adapter->smart_poll_desc.smart_poll_wq = NULL; + wq = desc->smart_poll_wq; + desc->smart_poll_wq = NULL; if (wq) { - if (!cancel_delayed_work_sync(&adapter->smart_poll_desc.smart_poll_work)) + if (!cancel_delayed_work_sync(&desc->smart_poll_work)) flush_workqueue(wq); destroy_workqueue(wq); } } +static void leapraid_overheat_work(struct work_struct *work) +{ + struct leapraid_overheat_desc *desc; + struct leapraid_adapter *adapter; + struct workqueue_struct *wq; + struct Scsi_Host *shost; + struct pci_dev *pdev; + unsigned long flags; + + desc = container_of(work, struct leapraid_overheat_desc, + fault_overheat_work); + adapter = container_of(desc, struct leapraid_adapter, overheat_desc); + pdev = adapter->pdev; + shost = pci_get_drvdata(pdev); + + if (!shost) { + dev_err(&pdev->dev, + "Overheat processing failed: invalid host/adapter\n"); + atomic_set(&adapter->overheat_desc.thermal_alert, 0); + wake_up(&adapter->scan_dev_desc.wait_driver_loading); + return; + } + + if (adapter->access_ctrl.host_removing) { + atomic_set(&adapter->overheat_desc.thermal_alert, 0); + wake_up(&adapter->scan_dev_desc.wait_driver_loading); + return; + } + + adapter->access_ctrl.host_removing = 1; + adapter->access_ctrl.shost_recover_async = 0; + adapter->scan_dev_desc.scan_start = 0; + adapter->scan_dev_desc.wait_scan_dev_done = 0; + adapter->scan_dev_desc.driver_loading = 0; + wake_up(&adapter->access_ctrl.recovery_waitq); + wake_up(&adapter->access_ctrl.shost_recover_wq); + wake_up(&adapter->scan_dev_desc.wait_driver_loading); + + leapraid_mask_int(adapter); + + leapraid_smart_polling_stop(adapter); + leapraid_check_scheduled_fault_stop(adapter); + leapraid_fw_log_stop(adapter); + leapraid_mq_polling_pause(adapter); + + leapraid_clean_active_cmds(adapter); + spin_lock_irqsave(&adapter->fw_evt_s.fw_evt_lock, flags); + wq = adapter->fw_evt_s.fw_evt_thread; + adapter->fw_evt_s.fw_evt_thread = NULL; + spin_unlock_irqrestore(&adapter->fw_evt_s.fw_evt_lock, flags); + if (wq) + destroy_workqueue(wq); + + sas_remove_host(shost); + leapraid_cleanup_lists(adapter); + atomic_set(&adapter->overheat_desc.thermal_alert, 0); + wake_up(&adapter->scan_dev_desc.wait_driver_loading); + dev_err(&pdev->dev, "%s: Suspend adapter due to overheat\n", __func__); +} + +static void leapraid_overheat_init(struct leapraid_adapter *adapter) +{ + if (adapter->overheat_desc.fault_overheat_wq) + return; + + atomic_set(&adapter->overheat_desc.thermal_alert, 0); + snprintf(adapter->overheat_desc.fault_overheat_wq_name, + sizeof(adapter->overheat_desc.fault_overheat_wq_name), + "driver_%s%u_overheat", + LEAPRAID_DRIVER_NAME, + adapter->adapter_attr.id); + adapter->overheat_desc.fault_overheat_wq = + create_singlethread_workqueue( + adapter->overheat_desc.fault_overheat_wq_name); + if (!adapter->overheat_desc.fault_overheat_wq) { + dev_err(&adapter->pdev->dev, + "Failed to create overheat workqueue\n"); + return; + } + + INIT_WORK(&adapter->overheat_desc.fault_overheat_work, + leapraid_overheat_work); +} + +void leapraid_overheat_cleanup(struct leapraid_adapter *adapter) +{ + struct workqueue_struct *wq; + + wq = xchg(&adapter->overheat_desc.fault_overheat_wq, NULL); + if (!wq) + return; + + cancel_work_sync(&adapter->overheat_desc.fault_overheat_work); + destroy_workqueue(wq); +} + static void leapraid_fw_work(struct leapraid_adapter *adapter, struct leapraid_fw_evt_work *fw_evt); @@ -2807,7 +3435,6 @@ static struct leapraid_fw_evt_work *leapraid_next_fw_evt( fw_evt = list_first_entry(&adapter->fw_evt_s.fw_evt_list, struct leapraid_fw_evt_work, list); list_del_init(&fw_evt->list); - leapraid_fw_evt_put(fw_evt); } spin_unlock_irqrestore(&adapter->fw_evt_s.fw_evt_lock, flags); return fw_evt; @@ -2816,56 +3443,65 @@ static struct leapraid_fw_evt_work *leapraid_next_fw_evt( void leapraid_clean_active_fw_evt(struct leapraid_adapter *adapter) { struct leapraid_fw_evt_work *fw_evt; - bool rc = false; + unsigned long flags; + bool in_fw_evt_context; + bool rc; if ((list_empty(&adapter->fw_evt_s.fw_evt_list) && !adapter->fw_evt_s.cur_evt) || !adapter->fw_evt_s.fw_evt_thread) return; adapter->fw_evt_s.fw_evt_cleanup = 1; + wake_up(&adapter->access_ctrl.recovery_waitq); if (adapter->access_ctrl.shost_recovering && adapter->fw_evt_s.cur_evt) adapter->fw_evt_s.cur_evt->ignore = 1; - while ((fw_evt = leapraid_next_fw_evt(adapter)) || - (fw_evt = adapter->fw_evt_s.cur_evt)) { - if (fw_evt == adapter->fw_evt_s.cur_evt && - adapter->fw_evt_s.cur_evt->evt_type != - LEAPRAID_EVT_REMOVE_DEAD_DEV) { - adapter->fw_evt_s.cur_evt = NULL; - continue; - } - + while ((fw_evt = leapraid_next_fw_evt(adapter))) { rc = cancel_work_sync(&fw_evt->work); - if (rc) leapraid_fw_evt_put(fw_evt); + leapraid_fw_evt_put(fw_evt); } + + spin_lock_irqsave(&adapter->fw_evt_s.fw_evt_lock, flags); + fw_evt = adapter->fw_evt_s.cur_evt; + if (fw_evt) { + in_fw_evt_context = adapter->fw_evt_s.cur_evt_task == current; + leapraid_fw_evt_get(fw_evt); + } + spin_unlock_irqrestore(&adapter->fw_evt_s.fw_evt_lock, flags); + if (fw_evt) { + if (!in_fw_evt_context) + cancel_work_sync(&fw_evt->work); + leapraid_fw_evt_put(fw_evt); + } + adapter->fw_evt_s.fw_evt_cleanup = 0; } static void leapraid_internal_dev_ublk(struct scsi_device *sdev, struct leapraid_sdev_priv *sdev_priv) { - int rc = 0; + int rc; sdev_printk(KERN_WARNING, sdev, - "hdl 0x%04x: now internal unblkg dev\n", + "hdl 0x%04x: Now internal unblkg dev\n", sdev_priv->starget_priv->hdl); - sdev_priv->block = false; + sdev_priv->block = 0; rc = scsi_internal_device_unblock_nowait(sdev, SDEV_RUNNING); if (rc == -EINVAL) { sdev_printk(KERN_WARNING, sdev, "hdl 0x%04x: unblkg failed, rc=%d\n", sdev_priv->starget_priv->hdl, rc); - sdev_priv->block = true; + sdev_priv->block = 1; rc = scsi_internal_device_block_nowait(sdev); if (rc) sdev_printk(KERN_WARNING, sdev, - "hdl 0x%04x: blkg failed: earlier unblkg err, rc=%d\n", + "hdl 0x%04x: Earlier ublkg err, rc=%d\n", sdev_priv->starget_priv->hdl, rc); - sdev_priv->block = false; + sdev_priv->block = 0; rc = scsi_internal_device_unblock_nowait(sdev, SDEV_RUNNING); if (rc) sdev_printk(KERN_WARNING, sdev, @@ -2874,38 +3510,6 @@ static void leapraid_internal_dev_ublk(struct scsi_device *sdev, } } -static void leapraid_internal_ublk_io_dev_to_running(struct scsi_device *sdev) -{ - struct leapraid_sdev_priv *sdev_priv; - - sdev_priv = sdev->hostdata; - sdev_priv->block = false; - scsi_internal_device_unblock_nowait(sdev, SDEV_RUNNING); - sdev_printk(KERN_WARNING, sdev, "%s: ublk hdl 0x%04x\n", - __func__, sdev_priv->starget_priv->hdl); -} - -static void leapraid_ublk_io_dev_to_running( - struct leapraid_adapter *adapter, u64 sas_addr, - struct leapraid_card_port *card_port) -{ - struct leapraid_sdev_priv *sdev_priv; - struct scsi_device *sdev; - - shost_for_each_device(sdev, adapter->shost) { - sdev_priv = sdev->hostdata; - if (!sdev_priv) - continue; - - if (sdev_priv->starget_priv->sas_address != sas_addr || - sdev_priv->starget_priv->card_port != card_port) - continue; - - if (sdev_priv->block) - leapraid_internal_ublk_io_dev_to_running(sdev); - } -} - static void leapraid_ublk_io_dev(struct leapraid_adapter *adapter, u64 sas_addr, struct leapraid_card_port *card_port) @@ -2957,15 +3561,15 @@ static void leapraid_ublk_io_all_dev(struct leapraid_adapter *adapter) } } -static void __maybe_unused leapraid_internal_dev_blk( +static void leapraid_internal_dev_blk( struct scsi_device *sdev, struct leapraid_sdev_priv *sdev_priv) { - int rc = 0; + int rc; - sdev_printk(KERN_INFO, sdev, "internal blkg hdl 0x%04x\n", + sdev_printk(KERN_INFO, sdev, "Internal blkg hdl 0x%04x\n", sdev_priv->starget_priv->hdl); - sdev_priv->block = true; + sdev_priv->block = 1; rc = scsi_internal_device_block_nowait(sdev); if (rc == -EINVAL) sdev_printk(KERN_WARNING, sdev, @@ -2973,42 +3577,6 @@ static void __maybe_unused leapraid_internal_dev_blk( rc, sdev_priv->starget_priv->hdl); } -static void __maybe_unused leapraid_blkio_dev(struct leapraid_adapter *adapter, - u16 hdl) -{ - struct leapraid_sdev_priv *sdev_priv; - struct leapraid_sas_dev *sas_dev; - struct scsi_device *sdev; - - sas_dev = leapraid_get_sas_dev_by_hdl(adapter, hdl); - shost_for_each_device(sdev, adapter->shost) { - sdev_priv = sdev->hostdata; - if (!sdev_priv) - continue; - - if (sdev_priv->starget_priv->hdl != hdl) - continue; - - if (sdev_priv->block) - continue; - - if (sas_dev && sas_dev->pend_sas_rphy_add) - continue; - - if (sdev_priv->sep) { - sdev_printk(KERN_INFO, sdev, - "sep hdl 0x%04x skip blkg\n", - sdev_priv->starget_priv->hdl); - continue; - } - - leapraid_internal_dev_blk(sdev, sdev_priv); - } - - if (sas_dev) - leapraid_sdev_put(sas_dev); -} - static void leapraid_imm_blkio_to_end_dev(struct leapraid_adapter *adapter, struct leapraid_sas_port *sas_port) { @@ -3040,8 +3608,7 @@ static void leapraid_imm_blkio_to_end_dev(struct leapraid_adapter *adapter, if (sdev_priv->sep) { sdev_printk(KERN_INFO, sdev, - "%s skip dev blk for sep hdl 0x%04x\n", - __func__, + "skip dev blk: sep hdl 0x%04x\n", sdev_priv->starget_priv->hdl); continue; } @@ -3062,10 +3629,8 @@ static void leapraid_imm_blkio_set_end_dev_blk_hdls( list_for_each_entry(sas_port, &topo_node_exp->sas_port_list, port_list) { - if (sas_port->remote_identify.device_type == - SAS_END_DEVICE) { + if (sas_port->remote_identify.device_type == SAS_END_DEVICE) leapraid_imm_blkio_to_end_dev(adapter, sas_port); - } } } @@ -3087,7 +3652,7 @@ static void leapraid_imm_blkio_to_sib_exp( sas_port->remote_identify.device_type == SAS_FANOUT_EXPANDER_DEVICE) { topo_node_exp_sib = - leapraid_exp_find_by_sas_address( + leapraid_exp_find_by_sas_address( adapter, sas_port->remote_identify.sas_address, sas_port->card_port); @@ -3126,17 +3691,15 @@ static void leapraid_report_sdev_directly(struct leapraid_adapter *adapter, if (!sas_dev->starget) { if (!adapter->scan_dev_desc.driver_loading) { - leapraid_transport_port_remove(adapter, - sas_dev->sas_addr, - sas_dev->parent_sas_addr, - sas_dev->card_port); + leapraid_transport_port_remove( + adapter, + sas_dev->sas_addr, + sas_dev->parent_sas_addr, + sas_dev->card_port); leapraid_sas_dev_remove(adapter, sas_dev); } return; } - - clear_bit(sas_dev->hdl, - (unsigned long *)adapter->dev_topo.pending_dev_add); } static struct leapraid_sas_dev *leapraid_init_sas_dev( @@ -3147,6 +3710,7 @@ static struct leapraid_sas_dev *leapraid_init_sas_dev( { struct leapraid_sas_dev *sas_dev; struct leapraid_enc_node *enc_dev; + unsigned long flags; sas_dev = kzalloc(sizeof(*sas_dev), GFP_KERNEL); if (!sas_dev) @@ -3161,28 +3725,32 @@ static struct leapraid_sas_dev *leapraid_init_sas_dev( sas_dev->phy = sas_dev_pg0->phy_num; sas_dev->enc_hdl = le16_to_cpu(sas_dev_pg0->enc_hdl); sas_dev->dev_name = le64_to_cpu(sas_dev_pg0->dev_name); - sas_dev->port_type = sas_dev_pg0->max_port_connections; + sas_dev->port_connection = sas_dev_pg0->max_port_connections; sas_dev->slot = sas_dev->enc_hdl ? le16_to_cpu(sas_dev_pg0->slot) : 0; sas_dev->support_smart = (le16_to_cpu(sas_dev_pg0->flg) & LEAPRAID_SAS_DEV_P0_FLG_SATA_SMART); if (le16_to_cpu(sas_dev_pg0->flg) & LEAPRAID_SAS_DEV_P0_FLG_ENC_LEVEL_VALID) { sas_dev->enc_level = sas_dev_pg0->enc_level; - memcpy(sas_dev->connector_name, sas_dev_pg0->connector_name, 4); - sas_dev->connector_name[4] = '\0'; + memcpy(sas_dev->connector_name, + sas_dev_pg0->connector_name, + LEAPRAID_SAS_DEV_P0_CON_NAME_LEN); + sas_dev->connector_name[LEAPRAID_SAS_DEV_P0_CON_NAME_LEN] = + '\0'; } else { sas_dev->enc_level = 0; sas_dev->connector_name[0] = '\0'; } - if (le16_to_cpu(sas_dev_pg0->enc_hdl)) { - enc_dev = leapraid_enc_find_by_hdl(adapter, - le16_to_cpu(sas_dev_pg0->enc_hdl)); - sas_dev->enc_lid = enc_dev ? - le64_to_cpu(enc_dev->pg0.enc_lid) : 0; + if (sas_dev->enc_hdl) { + spin_lock_irqsave(&adapter->dev_topo.enc_lock, flags); + enc_dev = leapraid_enc_find_by_hdl(adapter, sas_dev->enc_hdl); + if (enc_dev) + sas_dev->enc_lid = le64_to_cpu(enc_dev->pg0.enc_lid); + spin_unlock_irqrestore(&adapter->dev_topo.enc_lock, flags); } dev_info(&adapter->pdev->dev, - "add dev: hdl=0x%0x, sas addr=0x%016llx, port_type=0x%0x\n", - hdl, sas_dev->sas_addr, sas_dev->port_type); + "add dev: hdl=0x%x, SAS addr=0x%016llx, port connect=0x%x\n", + hdl, sas_dev->sas_addr, sas_dev->port_connection); return sas_dev; } @@ -3202,15 +3770,14 @@ static void leapraid_add_dev(struct leapraid_adapter *adapter, u16 hdl) cfgp1.form = LEAPRAID_SAS_DEV_CFG_PGAD_HDL; cfgp2.handle = hdl; - if ((leapraid_op_config_page(adapter, &sas_dev_pg0, - cfgp1, cfgp2, GET_SAS_DEVICE_PG0))) + if (leapraid_op_config_page(adapter, &sas_dev_pg0, + cfgp1, cfgp2, GET_SAS_DEVICE_PG0)) return; dev_info = le32_to_cpu(sas_dev_pg0.dev_info); if (!(leapraid_is_end_dev(dev_info))) return; - set_bit(hdl, (unsigned long *)adapter->dev_topo.pending_dev_add); sas_addr = le64_to_cpu(sas_dev_pg0.sas_address); if (!(le16_to_cpu(sas_dev_pg0.flg) & LEAPRAID_SAS_DEV_P0_FLG_DEV_PRESENT)) @@ -3223,8 +3790,6 @@ static void leapraid_add_dev(struct leapraid_adapter *adapter, u16 hdl) sas_dev = leapraid_get_sas_dev_by_addr(adapter, sas_addr, card_port); if (sas_dev) { - clear_bit(hdl, - (unsigned long *)adapter->dev_topo.pending_dev_add); leapraid_sdev_put(sas_dev); return; } @@ -3239,6 +3804,7 @@ static void leapraid_add_dev(struct leapraid_adapter *adapter, u16 hdl) dev_info); if (!sas_dev) return; + if (adapter->scan_dev_desc.wait_scan_dev_done) { spin_lock_irqsave(&adapter->dev_topo.sas_dev_lock, flags); leapraid_sdev_get(sas_dev); @@ -3253,6 +3819,7 @@ static void leapraid_add_dev(struct leapraid_adapter *adapter, u16 hdl) spin_unlock_irqrestore(&adapter->dev_topo.sas_dev_lock, flags); leapraid_report_sdev_directly(adapter, sas_dev); } + leapraid_sdev_put(sas_dev); } static void leapraid_remove_device(struct leapraid_adapter *adapter, @@ -3260,14 +3827,15 @@ static void leapraid_remove_device(struct leapraid_adapter *adapter, { struct leapraid_starget_priv *starget_priv; + leapraid_clear_cached_boot_dev(adapter, sas_dev, 0); if (sas_dev->led_on) { leapraid_set_led(adapter, sas_dev, false); - sas_dev->led_on = false; + sas_dev->led_on = 0; } if (sas_dev->starget && sas_dev->starget->hostdata) { starget_priv = sas_dev->starget->hostdata; - starget_priv->deleted = true; + starget_priv->deleted = 1; leapraid_ublk_io_dev(adapter, sas_dev->sas_addr, sas_dev->card_port); starget_priv->hdl = LEAPRAID_INVALID_DEV_HANDLE; @@ -3279,12 +3847,13 @@ static void leapraid_remove_device(struct leapraid_adapter *adapter, sas_dev->card_port); dev_info(&adapter->pdev->dev, - "remove dev: hdl=0x%04x, sas addr=0x%016llx\n", + "remove dev: hdl=0x%04x, SAS addr=0x%016llx\n", sas_dev->hdl, (unsigned long long)sas_dev->sas_addr); } -static struct leapraid_vphy *leapraid_alloc_vphy(struct leapraid_adapter *adapter, - u8 port_id, u8 phy_num) +static struct leapraid_vphy *leapraid_alloc_vphy( + struct leapraid_adapter *adapter, + u8 port_id, u8 phy_num) { struct leapraid_card_port *port; struct leapraid_vphy *vphy; @@ -3296,7 +3865,6 @@ static struct leapraid_vphy *leapraid_alloc_vphy(struct leapraid_adapter *adapte vphy = leapraid_get_vphy_by_phy(port, phy_num); if (vphy) return vphy; - vphy = kzalloc(sizeof(*vphy), GFP_KERNEL); if (!vphy) return NULL; @@ -3310,46 +3878,157 @@ static struct leapraid_vphy *leapraid_alloc_vphy(struct leapraid_adapter *adapte return vphy; } -static int leapraid_add_port_to_card_port_list(struct leapraid_adapter *adapter, - u8 port_id, bool refresh) +static int leapraid_add_port_to_card_port_list( + struct leapraid_adapter *adapter, + u8 port_id, bool refresh) { struct leapraid_card_port *card_port; card_port = leapraid_get_port_by_id(adapter, port_id, false); if (card_port) return 0; - card_port = kzalloc(sizeof(*card_port), GFP_KERNEL); if (!card_port) return -ENOMEM; card_port->port_id = port_id; - dev_info(&adapter->pdev->dev, - "port: %d is added to card_port list\n", - card_port->port_id); + dev_dbg(&adapter->pdev->dev, + "port: %d is added to card_port list\n", + card_port->port_id); - if (refresh) - if (adapter->access_ctrl.shost_recovering) - card_port->flg = LEAPRAID_CARD_PORT_FLG_NEW; + if (refresh && adapter->access_ctrl.shost_recovering) + card_port->flg = LEAPRAID_CARD_PORT_FLG_NEW; list_add_tail(&card_port->list, &adapter->dev_topo.card_port_list); return 0; } +static int leapraid_add_card_phy(struct leapraid_adapter *adapter, + struct leapraid_sas_io_unit_p0 *iou, + int i) +{ + struct leapraid_sas_phy_p0 phy_pg0; + union cfg_param_1 cfgp1 = {0}; + union cfg_param_2 cfgp2 = {0}; + struct leapraid_topo_node *card = &adapter->dev_topo.card; + u8 port_id; + + cfgp1.phy_number = i; + + if (leapraid_op_config_page(adapter, &phy_pg0, + cfgp1, cfgp2, GET_PHY_PG0)) + return -EINVAL; + + port_id = iou->phy_info[i].port; + + if (leapraid_add_port_to_card_port_list(adapter, port_id, false)) + return -EINVAL; + + if ((le32_to_cpu(phy_pg0.phy_info) & + LEAPRAID_SAS_PHYINFO_VPHY) && + ((phy_pg0.neg_link_rate >> + LEAPRAID_SAS_NEG_LINK_RATE_SHIFT) >= + LEAPRAID_SAS_NEG_LINK_RATE_1_5)) { + if (!leapraid_alloc_vphy(adapter, port_id, i)) + return -ENOMEM; + + card->card_phy[i].vphy = 1; + } + + card->card_phy[i].hdl = card->hdl; + card->card_phy[i].phy_id = i; + card->card_phy[i].card_port = + leapraid_get_port_by_id(adapter, port_id, false); + + leapraid_transport_add_card_phy(adapter, + &card->card_phy[i], + &phy_pg0, + card->parent_dev); + + return 0; +} + +static int leapraid_refresh_card_phy(struct leapraid_adapter *adapter, + struct leapraid_sas_io_unit_p0 *iou, + int i) +{ + struct leapraid_topo_node *card = &adapter->dev_topo.card; + struct leapraid_sas_phy_p0 phy_pg0; + union cfg_param_1 cfgp1 = {0}; + union cfg_param_2 cfgp2 = {0}; + u16 attached_hdl; + u32 dev_info; + u8 link_rate; + u8 port_id; + + link_rate = iou->phy_info[i].neg_link_rate >> + LEAPRAID_SAS_NEG_LINK_RATE_SHIFT; + port_id = iou->phy_info[i].port; + if (leapraid_add_port_to_card_port_list(adapter, port_id, true)) + return -EINVAL; + + dev_info = le32_to_cpu(iou->phy_info[i].controller_phy_dev_info); + if (dev_info & LEAPRAID_DEVTYP_SEP && + link_rate >= LEAPRAID_SAS_NEG_LINK_RATE_1_5) { + cfgp1.phy_number = i; + + if (leapraid_op_config_page(adapter, &phy_pg0, + cfgp1, cfgp2, GET_PHY_PG0)) + return 0; + + if (le32_to_cpu(phy_pg0.phy_info) & + LEAPRAID_SAS_PHYINFO_VPHY && + !leapraid_alloc_vphy(adapter, port_id, i)) + return -EINVAL; + + card->card_phy[i].vphy = 1; + } + + card->card_phy[i].hdl = card->hdl; + + attached_hdl = le16_to_cpu(iou->phy_info[i].attached_dev_hdl); + if (attached_hdl && link_rate < LEAPRAID_SAS_NEG_LINK_RATE_1_5) + link_rate = LEAPRAID_SAS_NEG_LINK_RATE_1_5; + + card->card_phy[i].card_port = + leapraid_get_port_by_id(adapter, port_id, false); + + if (!card->card_phy[i].phy) { + cfgp1.phy_number = i; + if (leapraid_op_config_page(adapter, &phy_pg0, + cfgp1, cfgp2, GET_PHY_PG0)) + return 0; + + card->card_phy[i].phy_id = i; + + leapraid_transport_add_card_phy(adapter, + &card->card_phy[i], + &phy_pg0, + card->parent_dev); + return 0; + } + + leapraid_transport_update_links(adapter, + card->sas_address, + attached_hdl, + i, + link_rate, + card->card_phy[i].card_port); + + return 0; +} + static void leapraid_sas_host_add(struct leapraid_adapter *adapter, bool refresh) { union cfg_param_1 cfgp1 = {0}; union cfg_param_2 cfgp2 = {0}; - struct leapraid_sas_phy_p0 phy_pg0; struct leapraid_sas_dev_p0 sas_dev_pg0; struct leapraid_enc_p0 enc_pg0; struct leapraid_sas_io_unit_p0 *sas_iou_pg0; u16 sas_iou_pg0_sz; - u16 attached_hdl; u8 phys_num; - u8 port_id; - u8 link_rate; int i; + int rc; if (!refresh) { if (leapraid_get_adapter_phys(adapter, &phys_num) || !phys_num) @@ -3364,128 +4043,46 @@ static void leapraid_sas_host_add(struct leapraid_adapter *adapter, adapter->dev_topo.card.phys_num = phys_num; } - sas_iou_pg0_sz = offsetof(struct leapraid_sas_io_unit_p0, phy_info) + - (adapter->dev_topo.card.phys_num * - sizeof(struct leapraid_sas_io_unit0_phy_info)); + sas_iou_pg0_sz = + offsetof(struct leapraid_sas_io_unit_p0, phy_info) + + (adapter->dev_topo.card.phys_num * + sizeof(struct leapraid_sas_io_unit0_phy_info)); sas_iou_pg0 = kzalloc(sas_iou_pg0_sz, GFP_KERNEL); if (!sas_iou_pg0) - goto out; + return; if (leapraid_get_sas_io_unit_page0(adapter, sas_iou_pg0, sas_iou_pg0_sz)) - goto out; + goto out_free; adapter->dev_topo.card.parent_dev = &adapter->shost->shost_gendev; adapter->dev_topo.card.hdl = le16_to_cpu(sas_iou_pg0->phy_info[0].controller_dev_hdl); for (i = 0; i < adapter->dev_topo.card.phys_num; i++) { - if (!refresh) { /* add */ - cfgp1.phy_number = i; - if (leapraid_op_config_page(adapter, &phy_pg0, cfgp1, - cfgp2, GET_PHY_PG0)) - goto out; - - port_id = sas_iou_pg0->phy_info[i].port; - if (leapraid_add_port_to_card_port_list(adapter, - port_id, - false)) - goto out; - - if ((le32_to_cpu(phy_pg0.phy_info) & - LEAPRAID_SAS_PHYINFO_VPHY) && - (phy_pg0.neg_link_rate >> 4) >= - LEAPRAID_SAS_NEG_LINK_RATE_1_5) { - if (!leapraid_alloc_vphy(adapter, port_id, i)) - goto out; - adapter->dev_topo.card.card_phy[i].vphy = true; - } - - adapter->dev_topo.card.card_phy[i].hdl = - adapter->dev_topo.card.hdl; - adapter->dev_topo.card.card_phy[i].phy_id = i; - adapter->dev_topo.card.card_phy[i].card_port = - leapraid_get_port_by_id(adapter, - port_id, - false); - leapraid_transport_add_card_phy( - adapter, - &adapter->dev_topo.card.card_phy[i], - &phy_pg0, adapter->dev_topo.card.parent_dev); - } else { /* refresh */ - link_rate = sas_iou_pg0->phy_info[i].neg_link_rate >> 4; - port_id = sas_iou_pg0->phy_info[i].port; - if (leapraid_add_port_to_card_port_list(adapter, - port_id, - true)) - goto out; - - if (le32_to_cpu(sas_iou_pg0->phy_info[i] - .controller_phy_dev_info) & - LEAPRAID_DEVTYP_SEP && - link_rate >= LEAPRAID_SAS_NEG_LINK_RATE_1_5) { - cfgp1.phy_number = i; - if ((leapraid_op_config_page(adapter, &phy_pg0, - cfgp1, cfgp2, - GET_PHY_PG0))) - continue; - - if ((le32_to_cpu(phy_pg0.phy_info) & - LEAPRAID_SAS_PHYINFO_VPHY)) { - if (!leapraid_alloc_vphy(adapter, - port_id, - i)) - goto out; - adapter->dev_topo.card.card_phy[i].vphy = true; - } - } - - adapter->dev_topo.card.card_phy[i].hdl = - adapter->dev_topo.card.hdl; - attached_hdl = - le16_to_cpu(sas_iou_pg0->phy_info[i].attached_dev_hdl); - if (attached_hdl && link_rate < LEAPRAID_SAS_NEG_LINK_RATE_1_5) - link_rate = LEAPRAID_SAS_NEG_LINK_RATE_1_5; - - adapter->dev_topo.card.card_phy[i].card_port = - leapraid_get_port_by_id(adapter, - port_id, - false); - if (!adapter->dev_topo.card.card_phy[i].phy) { - cfgp1.phy_number = i; - if ((leapraid_op_config_page(adapter, &phy_pg0, - cfgp1, cfgp2, - GET_PHY_PG0))) - continue; - - adapter->dev_topo.card.card_phy[i].phy_id = i; - leapraid_transport_add_card_phy(adapter, - &adapter->dev_topo.card.card_phy[i], - &phy_pg0, - adapter->dev_topo.card.parent_dev); - continue; - } - - leapraid_transport_update_links(adapter, - adapter->dev_topo.card.sas_address, - attached_hdl, i, link_rate, - adapter->dev_topo.card.card_phy[i].card_port); - } + if (!refresh) /* add */ + rc = leapraid_add_card_phy(adapter, sas_iou_pg0, i); + else /* refresh */ + rc = leapraid_refresh_card_phy(adapter, + sas_iou_pg0, + i); + if (rc) + goto out_free; } if (!refresh) { cfgp1.form = LEAPRAID_SAS_DEV_CFG_PGAD_HDL; cfgp2.handle = adapter->dev_topo.card.hdl; - if ((leapraid_op_config_page(adapter, &sas_dev_pg0, cfgp1, - cfgp2, GET_SAS_DEVICE_PG0))) - goto out; + if (leapraid_op_config_page(adapter, &sas_dev_pg0, cfgp1, + cfgp2, GET_SAS_DEVICE_PG0)) + goto out_free; adapter->dev_topo.card.enc_hdl = le16_to_cpu(sas_dev_pg0.enc_hdl); adapter->dev_topo.card.sas_address = le64_to_cpu(sas_dev_pg0.sas_address); dev_info(&adapter->pdev->dev, - "add host: devhdl=0x%04x, sas addr=0x%016llx, phynums=%d\n", + "add host: hdl=0x%04x, SAS addr=0x%016llx, phy=%d\n", adapter->dev_topo.card.hdl, (unsigned long long)adapter->dev_topo.card.sas_address, adapter->dev_topo.card.phys_num); @@ -3500,7 +4097,7 @@ static void leapraid_sas_host_add(struct leapraid_adapter *adapter, le64_to_cpu(enc_pg0.enc_lid); } } -out: +out_free: kfree(sas_iou_pg0); } @@ -3514,22 +4111,24 @@ static int leapraid_internal_exp_add(struct leapraid_adapter *adapter, struct leapraid_sas_port *sas_port = NULL; struct leapraid_enc_node *enc_dev; struct leapraid_exp_p1 exp_pg1; - int rc = 0; + int ret; + int rc; unsigned long flags; u8 port_id; u16 parent_handle; - u64 sas_addr_parent = 0; + u64 sas_addr_parent; int i; port_id = exp_pg0->physical_port; parent_handle = le16_to_cpu(exp_pg0->parent_dev_hdl); - if (leapraid_get_sas_address(adapter, parent_handle, &sas_addr_parent)) - return -1; - + rc = leapraid_get_sas_address(adapter, + parent_handle, &sas_addr_parent); + if (rc) + return rc; topo_node_exp = kzalloc(sizeof(*topo_node_exp), GFP_KERNEL); if (!topo_node_exp) - return -1; + return -ENOMEM; topo_node_exp->hdl = hdl; topo_node_exp->phys_num = exp_pg0->phy_num; @@ -3538,17 +4137,19 @@ static int leapraid_internal_exp_add(struct leapraid_adapter *adapter, topo_node_exp->card_port = leapraid_get_port_by_id(adapter, port_id, false); if (!topo_node_exp->card_port) { - rc = -1; + rc = -EPERM; goto out_fail; } dev_info(&adapter->pdev->dev, - "add exp: sas addr=0x%016llx, hdl=0x%04x, phdl=0x%04x, phys=%d\n", + "add exp: saddr=0x%016llx, hdl=0x%04x, phdl=0x%04x, phy=%d\n", (unsigned long long)topo_node_exp->sas_address, hdl, parent_handle, topo_node_exp->phys_num); if (!topo_node_exp->phys_num) { - rc = -1; + dev_err(&adapter->pdev->dev, + "%s: Invalid PHY num from exp_pg0\n", __func__); + rc = -EPERM; goto out_fail; } @@ -3556,7 +4157,10 @@ static int leapraid_internal_exp_add(struct leapraid_adapter *adapter, kcalloc(topo_node_exp->phys_num, sizeof(struct leapraid_card_phy), GFP_KERNEL); if (!topo_node_exp->card_phy) { - rc = -1; + dev_err(&adapter->pdev->dev, + "%s: Failed to alloc expander phy array, count=%u\n", + __func__, topo_node_exp->phys_num); + rc = -EPERM; goto out_fail; } @@ -3564,7 +4168,7 @@ static int leapraid_internal_exp_add(struct leapraid_adapter *adapter, sas_port = leapraid_transport_port_add(adapter, hdl, sas_addr_parent, topo_node_exp->card_port); if (!sas_port) { - rc = -1; + rc = -EPERM; goto out_fail; } @@ -3573,31 +4177,38 @@ static int leapraid_internal_exp_add(struct leapraid_adapter *adapter, for (i = 0; i < topo_node_exp->phys_num; i++) { cfgp1->phy_number = i; cfgp2->handle = hdl; - if ((leapraid_op_config_page(adapter, &exp_pg1, *cfgp1, *cfgp2, - GET_SAS_EXPANDER_PG1))) { - rc = -1; + if (leapraid_op_config_page(adapter, &exp_pg1, *cfgp1, *cfgp2, + GET_SAS_EXPANDER_PG1)) { + dev_err(&adapter->pdev->dev, + "%s: Failed to get exp_pg1, phy=%d\n", + __func__, i); + rc = -EPERM; goto out_fail; } topo_node_exp->card_phy[i].hdl = hdl; topo_node_exp->card_phy[i].phy_id = i; topo_node_exp->card_phy[i].card_port = - leapraid_get_port_by_id(adapter, port_id, false); - if ((leapraid_transport_add_exp_phy(adapter, - &topo_node_exp->card_phy[i], - &exp_pg1, - topo_node_exp->parent_dev))) { - rc = -1; + leapraid_get_port_by_id(adapter, port_id, false); + ret = leapraid_transport_add_exp_phy( + adapter, + &topo_node_exp->card_phy[i], + &exp_pg1, + topo_node_exp->parent_dev); + if (ret) { + rc = -EPERM; goto out_fail; } } if (topo_node_exp->enc_hdl) { + spin_lock_irqsave(&adapter->dev_topo.enc_lock, flags); enc_dev = leapraid_enc_find_by_hdl(adapter, topo_node_exp->enc_hdl); if (enc_dev) topo_node_exp->enc_lid = le64_to_cpu(enc_dev->pg0.enc_lid); + spin_unlock_irqrestore(&adapter->dev_topo.enc_lock, flags); } spin_lock_irqsave(&adapter->dev_topo.topo_node_lock, flags); @@ -3611,6 +4222,7 @@ static int leapraid_internal_exp_add(struct leapraid_adapter *adapter, topo_node_exp->sas_address, sas_addr_parent, topo_node_exp->card_port); + kfree(topo_node_exp->card_phy); kfree(topo_node_exp); return rc; } @@ -3622,22 +4234,29 @@ static int leapraid_exp_add(struct leapraid_adapter *adapter, u16 hdl) struct leapraid_topo_node *topo_node_exp; struct leapraid_exp_p0 exp_pg0; u16 parent_handle; - u64 sas_addr, sas_addr_parent = 0; + u64 sas_addr, sas_addr_parent; unsigned long flags; u8 port_id; - int rc = 0; + int rc; - if (!hdl) + if (!hdl) { + dev_warn(&adapter->pdev->dev, "%s: Invalid hdl\n", __func__); return -EPERM; + } if (adapter->access_ctrl.shost_recovering || - adapter->access_ctrl.pcie_recovering) + adapter->access_ctrl.pcie_recovering) { + dev_warn(&adapter->pdev->dev, + "%s: Failed, shost_recovering=%d pcie_recovering=%d\n", + __func__, adapter->access_ctrl.shost_recovering, + adapter->access_ctrl.pcie_recovering); return -EPERM; + } cfgp1.form = LEAPRAID_SAS_EXP_CFD_PGAD_HDL; cfgp2.handle = hdl; - if ((leapraid_op_config_page(adapter, &exp_pg0, cfgp1, cfgp2, - GET_SAS_EXPANDER_PG0))) + if (leapraid_op_config_page(adapter, &exp_pg0, cfgp1, cfgp2, + GET_SAS_EXPANDER_PG0)) return -EPERM; parent_handle = le16_to_cpu(exp_pg0.parent_dev_hdl); @@ -3648,10 +4267,14 @@ static int leapraid_exp_add(struct leapraid_adapter *adapter, u16 hdl) if (sas_addr_parent != adapter->dev_topo.card.sas_address) { spin_lock_irqsave(&adapter->dev_topo.topo_node_lock, flags); topo_node_exp = - leapraid_exp_find_by_sas_address(adapter, + leapraid_exp_find_by_sas_address( + adapter, sas_addr_parent, - leapraid_get_port_by_id(adapter, port_id, false)); - spin_unlock_irqrestore(&adapter->dev_topo.topo_node_lock, flags); + leapraid_get_port_by_id(adapter, + port_id, + false)); + spin_unlock_irqrestore(&adapter->dev_topo.topo_node_lock, + flags); if (!topo_node_exp) { rc = leapraid_exp_add(adapter, parent_handle); if (rc != 0) @@ -3662,7 +4285,9 @@ static int leapraid_exp_add(struct leapraid_adapter *adapter, u16 hdl) spin_lock_irqsave(&adapter->dev_topo.topo_node_lock, flags); sas_addr = le64_to_cpu(exp_pg0.sas_address); topo_node_exp = - leapraid_exp_find_by_sas_address(adapter, sas_addr, + leapraid_exp_find_by_sas_address( + adapter, + sas_addr, leapraid_get_port_by_id(adapter, port_id, false)); spin_unlock_irqrestore(&adapter->dev_topo.topo_node_lock, flags); @@ -3710,7 +4335,7 @@ static void leapraid_exp_node_rm(struct leapraid_adapter *adapter, topo_node_exp->sas_address_parent, topo_node_exp->card_port); dev_info(&adapter->pdev->dev, - "removing exp: port=%d, sas addr=0x%016llx, hdl=0x%04x\n", + "removing exp: port=%d, SAS addr=0x%016llx, hdl=0x%04x\n", port_id, (unsigned long long)topo_node_exp->sas_address, topo_node_exp->hdl); spin_lock_irqsave(&adapter->dev_topo.topo_node_lock, flags); @@ -3742,92 +4367,6 @@ void leapraid_exp_rm(struct leapraid_adapter *adapter, u64 sas_addr, leapraid_exp_node_rm(adapter, topo_node_exp); } -static void leapraid_check_device(struct leapraid_adapter *adapter, - u64 parent_sas_address, u16 handle, - u8 phy_number, u8 link_rate) -{ - struct leapraid_sas_dev_p0 sas_device_pg0; - struct leapraid_sas_dev *sas_dev = NULL; - struct leapraid_enc_node *enclosure_dev = NULL; - union cfg_param_1 cfgp1 = {0}; - union cfg_param_2 cfgp2 = {0}; - unsigned long flags; - u64 sas_address; - struct scsi_target *starget; - struct leapraid_starget_priv *sas_target_priv_data; - u32 device_info; - struct leapraid_card_port *port; - - cfgp1.form = LEAPRAID_SAS_DEV_CFG_PGAD_HDL; - cfgp2.handle = handle; - if ((leapraid_op_config_page(adapter, &sas_device_pg0, cfgp1, cfgp2, - GET_SAS_DEVICE_PG0))) - return; - - if (phy_number != sas_device_pg0.phy_num) - return; - - device_info = le32_to_cpu(sas_device_pg0.dev_info); - if (!(leapraid_is_end_dev(device_info))) - return; - - spin_lock_irqsave(&adapter->dev_topo.sas_dev_lock, flags); - sas_address = le64_to_cpu(sas_device_pg0.sas_address); - port = leapraid_get_port_by_id(adapter, sas_device_pg0.physical_port, - false); - if (!port) - goto out_unlock; - - sas_dev = leapraid_hold_lock_get_sas_dev_by_addr(adapter, sas_address, - port); - if (!sas_dev) - goto out_unlock; - - if (unlikely(sas_dev->hdl != handle)) { - starget = sas_dev->starget; - sas_target_priv_data = starget->hostdata; - starget_printk(KERN_INFO, starget, - "hdl changed from 0x%04x to 0x%04x!\n", - sas_dev->hdl, handle); - sas_target_priv_data->hdl = handle; - sas_dev->hdl = handle; - if (le16_to_cpu(sas_device_pg0.flg) & - LEAPRAID_SAS_DEV_P0_FLG_ENC_LEVEL_VALID) { - sas_dev->enc_level = - sas_device_pg0.enc_level; - memcpy(sas_dev->connector_name, - sas_device_pg0.connector_name, 4); - sas_dev->connector_name[4] = '\0'; - } else { - sas_dev->enc_level = 0; - sas_dev->connector_name[0] = '\0'; - } - sas_dev->enc_hdl = - le16_to_cpu(sas_device_pg0.enc_hdl); - enclosure_dev = - leapraid_enc_find_by_hdl(adapter, sas_dev->enc_hdl); - if (enclosure_dev) { - sas_dev->enc_lid = - le64_to_cpu(enclosure_dev->pg0.enc_lid); - } - } - - if (!(le16_to_cpu(sas_device_pg0.flg) & - LEAPRAID_SAS_DEV_P0_FLG_DEV_PRESENT)) - goto out_unlock; - - spin_unlock_irqrestore(&adapter->dev_topo.sas_dev_lock, flags); - - leapraid_ublk_io_dev_to_running(adapter, sas_address, port); - goto out; - -out_unlock: - spin_unlock_irqrestore(&adapter->dev_topo.sas_dev_lock, flags); -out: - if (sas_dev) - leapraid_sdev_put(sas_dev); -} - static int leapraid_internal_sas_topo_chg_evt( struct leapraid_adapter *adapter, struct leapraid_card_port *card_port, @@ -3836,10 +4375,8 @@ static int leapraid_internal_sas_topo_chg_evt( u64 sas_addr, u8 max_phys) { struct leapraid_evt_data_sas_topo_change_list *evt_data; - struct leapraid_sas_dev *sas_dev; - unsigned long flags; u8 phy_number; - u8 link_rate, prev_link_rate; + u8 link_rate; u16 reason_code; u16 hdl; int i; @@ -3861,47 +4398,15 @@ static int leapraid_internal_sas_topo_chg_evt( LEAPRAID_EVT_SAS_TOPO_RC_MASK; hdl = le16_to_cpu(evt_data->phy[i].attached_dev_hdl); - if (!hdl) + if (!hdl || + hdl > adapter->adapter_attr.features.max_dev_handle) { + dev_warn(&adapter->pdev->dev, + "%s: Invalid device handle\n", __func__); continue; - - link_rate = evt_data->phy[i].link_rate >> 4; - prev_link_rate = evt_data->phy[i].link_rate & 0xF; + } + link_rate = evt_data->phy[i].link_rate >> + LEAPRAID_SAS_NEG_LINK_RATE_SHIFT; switch (reason_code) { - case LEAPRAID_EVT_SAS_TOPO_RC_PHY_CHANGED: - if (adapter->access_ctrl.shost_recovering) - break; - - if (link_rate == prev_link_rate) - break; - - leapraid_transport_update_links(adapter, sas_addr, - hdl, phy_number, - link_rate, card_port); - if (link_rate < LEAPRAID_SAS_NEG_LINK_RATE_1_5) - break; - - leapraid_check_device(adapter, sas_addr, hdl, - phy_number, link_rate); - spin_lock_irqsave(&adapter->dev_topo.sas_dev_lock, - flags); - sas_dev = - leapraid_hold_lock_get_sas_dev_by_hdl( - adapter, hdl); - spin_unlock_irqrestore(&adapter->dev_topo.sas_dev_lock, - flags); - if (sas_dev) { - leapraid_sdev_put(sas_dev); - break; - } - if (!test_bit(hdl, (unsigned long *)adapter->dev_topo.pending_dev_add)) - break; - - evt_data->phy[i].phy_status &= - LEAPRAID_EVT_SAS_TOPO_RC_CLEAR_MASK; - evt_data->phy[i].phy_status |= - LEAPRAID_EVT_SAS_TOPO_RC_TARG_ADDED; - fallthrough; - case LEAPRAID_EVT_SAS_TOPO_RC_TARG_ADDED: if (adapter->access_ctrl.shost_recovering) break; @@ -3942,7 +4447,7 @@ static int leapraid_sas_topo_chg_evt(struct leapraid_adapter *adapter, return 0; evt_data = fw_evt->evt_data; - leapraid_sas_host_add(adapter, adapter->dev_topo.card.phys_num); + leapraid_sas_host_add(adapter, adapter->dev_topo.card.phys_num > 0); if (fw_evt->ignore) return 0; @@ -3951,9 +4456,9 @@ static int leapraid_sas_topo_chg_evt(struct leapraid_adapter *adapter, card_port = leapraid_get_port_by_id(adapter, evt_data->physical_port, false); - if (evt_data->exp_status == LEAPRAID_EVT_SAS_TOPO_ES_ADDED) - if (leapraid_exp_add(adapter, phdl) != 0) - return 0; + if (evt_data->exp_status == LEAPRAID_EVT_SAS_TOPO_ES_ADDED && + leapraid_exp_add(adapter, phdl) != 0) + return 0; spin_lock_irqsave(&adapter->dev_topo.topo_node_lock, flags); topo_node_exp = leapraid_exp_find_by_hdl(adapter, phdl); @@ -3980,12 +4485,13 @@ static void leapraid_reprobe_lun(struct scsi_device *sdev, void *no_uld_attach) { sdev->no_uld_attach = no_uld_attach ? 1 : 0; sdev_printk(KERN_INFO, sdev, - "%s raid component to upper layer\n", + "%s RAID component to upper layer\n", sdev->no_uld_attach ? "hide" : "expose"); WARN_ON(scsi_device_reprobe(sdev)); } -static void leapraid_sas_pd_add(struct leapraid_adapter *adapter, +static void leapraid_sas_pd_add( + struct leapraid_adapter *adapter, struct leapraid_evt_data_ir_change *evt_data) { union cfg_param_1 cfgp1 = {0}; @@ -3997,20 +4503,26 @@ static void leapraid_sas_pd_add(struct leapraid_adapter *adapter, u16 hdl; hdl = le16_to_cpu(evt_data->phys_disk_dev_hdl); - set_bit(hdl, (unsigned long *)adapter->dev_topo.pd_hdls); + if (!hdl || hdl > adapter->adapter_attr.features.max_dev_handle) { + dev_warn(&adapter->pdev->dev, + "%s: Invalid device handle\n", __func__); + return; + } + + set_bit(hdl, adapter->dev_topo.pd_hdls); sas_dev = leapraid_get_sas_dev_by_hdl(adapter, hdl); if (sas_dev) { leapraid_sdev_put(sas_dev); dev_warn(&adapter->pdev->dev, - "dev handle 0x%x already exists\n", hdl); + "Dev handle 0x%x already exists\n", hdl); return; } cfgp1.form = LEAPRAID_SAS_DEV_CFG_PGAD_HDL; cfgp2.handle = hdl; - if ((leapraid_op_config_page(adapter, &sas_dev_p0, cfgp1, cfgp2, - GET_SAS_DEVICE_PG0))) { - dev_warn(&adapter->pdev->dev, "failed to read dev page0\n"); + if (leapraid_op_config_page(adapter, &sas_dev_p0, cfgp1, cfgp2, + GET_SAS_DEVICE_PG0)) { + dev_warn(&adapter->pdev->dev, "Failed to read dev page0\n"); return; } @@ -4025,7 +4537,8 @@ static void leapraid_sas_pd_add(struct leapraid_adapter *adapter, leapraid_add_dev(adapter, hdl); } -static void leapraid_sas_pd_delete(struct leapraid_adapter *adapter, +static void leapraid_sas_pd_delete( + struct leapraid_adapter *adapter, struct leapraid_evt_data_ir_change *evt_data) { u16 hdl; @@ -4034,7 +4547,8 @@ static void leapraid_sas_pd_delete(struct leapraid_adapter *adapter, leapraid_sas_dev_remove_by_hdl(adapter, hdl); } -static void leapraid_sas_pd_hide(struct leapraid_adapter *adapter, +static void leapraid_sas_pd_hide( + struct leapraid_adapter *adapter, struct leapraid_evt_data_ir_change *evt_data) { struct leapraid_starget_priv *starget_priv; @@ -4042,10 +4556,15 @@ static void leapraid_sas_pd_hide(struct leapraid_adapter *adapter, struct leapraid_sas_dev *sas_dev; unsigned long flags; u64 volume_wwid = 0; - u16 volume_hdl = 0; + u16 volume_hdl; u16 hdl; hdl = le16_to_cpu(evt_data->phys_disk_dev_hdl); + if (!hdl || hdl > adapter->adapter_attr.features.max_dev_handle) { + dev_warn(&adapter->pdev->dev, + "%s: Invalid device handle\n", __func__); + return; + } leapraid_cfg_get_volume_hdl(adapter, hdl, &volume_hdl); if (volume_hdl) leapraid_cfg_get_volume_wwid(adapter, @@ -4059,21 +4578,23 @@ static void leapraid_sas_pd_hide(struct leapraid_adapter *adapter, return; } - set_bit(hdl, (unsigned long *)adapter->dev_topo.pd_hdls); + set_bit(hdl, adapter->dev_topo.pd_hdls); if (sas_dev->starget && sas_dev->starget->hostdata) { starget = sas_dev->starget; starget_priv = starget->hostdata; starget_priv->flg |= LEAPRAID_TGT_FLG_RAID_MEMBER; sas_dev->volume_hdl = volume_hdl; sas_dev->volume_wwid = volume_wwid; - leapraid_sdev_put(sas_dev); } spin_unlock_irqrestore(&adapter->dev_topo.sas_dev_lock, flags); if (starget) { dev_info(&adapter->pdev->dev, "hide sas_dev, hdl=0x%x\n", hdl); starget_for_each_device(starget, - (void *)1, leapraid_reprobe_lun); + (void *)LEAPRAID_NO_ULD_ATTACH_FLAG, + leapraid_reprobe_lun); } + + leapraid_sdev_put(sas_dev); } static void leapraid_sas_pd_expose( @@ -4088,11 +4609,17 @@ static void leapraid_sas_pd_expose( hdl = le16_to_cpu(evt_data->phys_disk_dev_hdl); + if (!hdl || hdl > adapter->adapter_attr.features.max_dev_handle) { + dev_warn(&adapter->pdev->dev, + "%s: Invalid device handle\n", __func__); + return; + } + spin_lock_irqsave(&adapter->dev_topo.sas_dev_lock, flags); sas_dev = leapraid_hold_lock_get_sas_dev_by_hdl(adapter, hdl); if (!sas_dev) { dev_warn(&adapter->pdev->dev, - "%s:%d: sas_dev not found, hdl=0x%x\n", + "%s:%d: sas_dev not found, hdl=0x%x\n", __func__, __LINE__, hdl); spin_unlock_irqrestore(&adapter->dev_topo.sas_dev_lock, flags); return; @@ -4100,84 +4627,100 @@ static void leapraid_sas_pd_expose( sas_dev->volume_hdl = 0; sas_dev->volume_wwid = 0; - clear_bit(hdl, (unsigned long *)adapter->dev_topo.pd_hdls); + clear_bit(hdl, adapter->dev_topo.pd_hdls); if (sas_dev->starget && sas_dev->starget->hostdata) { starget = sas_dev->starget; starget_priv = starget->hostdata; starget_priv->flg &= ~LEAPRAID_TGT_FLG_RAID_MEMBER; - sas_dev->led_on = false; - leapraid_sdev_put(sas_dev); + sas_dev->led_on = 0; } spin_unlock_irqrestore(&adapter->dev_topo.sas_dev_lock, flags); if (starget) { dev_info(&adapter->pdev->dev, "expose sas_dev, hdl=0x%x\n", hdl); - starget_for_each_device(starget, NULL, leapraid_reprobe_lun); + starget_for_each_device(starget, + LEAPRAID_ULD_ATTACH_FLAG, + leapraid_reprobe_lun); } + + leapraid_sdev_put(sas_dev); } -static void leapraid_sas_vol_visibility(struct leapraid_adapter *adapter, +static void leapraid_sas_vol_visibility( + struct leapraid_adapter *adapter, struct leapraid_evt_data_ir_change *evt_data) { - struct leapraid_raid_volume *raid_volume = NULL; - struct scsi_device *sdev = NULL; - u16 hdl = 0; + struct leapraid_raid_volume *raid_volume; + struct scsi_device *sdev; + bool reprobe_flg = false; + bool sdev_held = false; unsigned long flags; - u8 rc = 0; - u8 reprobe_flg = 0; + u16 hdl; + u8 rc; hdl = le16_to_cpu(evt_data->vol_dev_hdl); rc = evt_data->reason_code; - spin_lock_irqsave(&adapter->dev_topo.raid_volume_lock, flags); raid_volume = leapraid_raid_volume_find_by_hdl(adapter, hdl); if (!raid_volume) { + dev_warn(&adapter->pdev->dev, + "%s:%d: Volume handle 0x%x not found\n", + __func__, __LINE__, hdl); + return; + } + + spin_lock_irqsave(&adapter->dev_topo.raid_volume_lock, flags); + sdev = raid_volume->sdev; + if (!sdev) { spin_unlock_irqrestore(&adapter->dev_topo.raid_volume_lock, flags); + leapraid_raid_volume_put(raid_volume); dev_warn(&adapter->pdev->dev, - "%s:%d: volume handle 0x%x not found\n", + "%s:%d: Volume handle 0x%x has no sdev\n", __func__, __LINE__, hdl); return; } - reprobe_flg = 0; - sdev = raid_volume->sdev; - if (sdev) { - if (sdev->no_uld_attach) { - if (rc == LEAPRAID_EVT_IR_RC_VOLUME_UNHIDE) { - sdev->no_uld_attach = 0; - reprobe_flg = 1; - } - } else { - if (rc == LEAPRAID_EVT_IR_RC_VOLUME_HIDE) { - sdev->no_uld_attach = 1; - reprobe_flg = 1; - } - } + if (sdev->no_uld_attach && + rc == LEAPRAID_EVT_IR_RC_VOLUME_UNHIDE) { + sdev->no_uld_attach = 0; + reprobe_flg = true; + } else if (!sdev->no_uld_attach && + rc == LEAPRAID_EVT_IR_RC_VOLUME_HIDE) { + sdev->no_uld_attach = 1; + reprobe_flg = true; + } - if (reprobe_flg) { - if (sdev->no_uld_attach) - sdev_printk(KERN_INFO, sdev, "hide vol\n"); - else - sdev_printk(KERN_INFO, sdev, "unhide vol\n"); + if (reprobe_flg && !scsi_device_get(sdev)) + sdev_held = true; + spin_unlock_irqrestore(&adapter->dev_topo.raid_volume_lock, flags); + leapraid_raid_volume_put(raid_volume); - WARN_ON(scsi_device_reprobe(sdev)); - } else { - dev_warn(&adapter->pdev->dev, - "%s:rc(0x%x):request matches, skipping.\n", - __func__, rc); - } + if (!reprobe_flg) { + dev_warn(&adapter->pdev->dev, + "%s:rc(0x%x): Request matches, skipping\n", + __func__, rc); + return; + } - } else { + if (!sdev_held) { dev_warn(&adapter->pdev->dev, - "%s:%d: volume handle 0x%x has no sdev\n", - __func__, __LINE__, hdl); + "%s: Failed to hold sdev for reprobe, hdl=0x%x\n", + __func__, hdl); + return; } - spin_unlock_irqrestore(&adapter->dev_topo.raid_volume_lock, flags); + if (sdev->no_uld_attach) + sdev_printk(KERN_INFO, sdev, "hide vol\n"); + else + sdev_printk(KERN_INFO, sdev, "unhide vol\n"); + + WARN_ON(scsi_device_reprobe(sdev)); + scsi_device_put(sdev); } -static void leapraid_sas_volume_add(struct leapraid_adapter *adapter, +static void leapraid_sas_volume_add( + struct leapraid_adapter *adapter, struct leapraid_evt_data_ir_change *evt_data) { struct leapraid_raid_volume *raid_volume; @@ -4188,23 +4731,21 @@ static void leapraid_sas_volume_add(struct leapraid_adapter *adapter, hdl = le16_to_cpu(evt_data->vol_dev_hdl); if (leapraid_cfg_get_volume_wwid(adapter, hdl, &wwid)) { - dev_warn(&adapter->pdev->dev, "failed to read volume page1\n"); + dev_warn(&adapter->pdev->dev, "Failed to read volume page1\n"); return; } if (!wwid) { - dev_warn(&adapter->pdev->dev, "invalid WWID(handle=0x%x)\n", + dev_warn(&adapter->pdev->dev, "Invalid WWID(handle=0x%x)\n", hdl); return; } - spin_lock_irqsave(&adapter->dev_topo.raid_volume_lock, flags); raid_volume = leapraid_raid_volume_find_by_wwid(adapter, wwid); - spin_unlock_irqrestore(&adapter->dev_topo.raid_volume_lock, flags); - if (raid_volume) { dev_warn(&adapter->pdev->dev, - "volume handle 0x%x already exists\n", hdl); + "Volume handle 0x%x already exists\n", hdl); + leapraid_raid_volume_put(raid_volume); return; } @@ -4212,6 +4753,8 @@ static void leapraid_sas_volume_add(struct leapraid_adapter *adapter, if (!raid_volume) return; + INIT_LIST_HEAD(&raid_volume->list); + kref_init(&raid_volume->refcnt); raid_volume->id = adapter->dev_topo.sas_id++; raid_volume->channel = RAID_CHANNEL; raid_volume->hdl = hdl; @@ -4222,50 +4765,65 @@ static void leapraid_sas_volume_add(struct leapraid_adapter *adapter, raid_volume->id, 0)) leapraid_raid_volume_remove(adapter, raid_volume); dev_info(&adapter->pdev->dev, - "add raid volume: hdl=0x%x, wwid=0x%llx\n", hdl, wwid); + "add RAID volume: hdl=0x%x, wwid=0x%llx\n", hdl, wwid); } else { spin_lock_irqsave(&adapter->dev_topo.raid_volume_lock, flags); leapraid_check_boot_dev(adapter, raid_volume, RAID_CHANNEL); spin_unlock_irqrestore(&adapter->dev_topo.raid_volume_lock, flags); } + leapraid_raid_volume_put(raid_volume); +} + +static void leapraid_sas_volume_delete_by_ptr( + struct leapraid_adapter *adapter, + struct leapraid_raid_volume *raid_volume) +{ + struct leapraid_starget_priv *starget_priv; + struct scsi_target *starget = NULL; + unsigned long flags; + bool in_list; + + if (!raid_volume) + return; + + spin_lock_irqsave(&adapter->dev_topo.raid_volume_lock, flags); + in_list = !list_empty(&raid_volume->list); + if (in_list && raid_volume->starget) { + starget = raid_volume->starget; + starget_priv = starget->hostdata; + if (starget_priv) + starget_priv->deleted = 1; + } + spin_unlock_irqrestore(&adapter->dev_topo.raid_volume_lock, flags); + + if (!in_list) + return; + + dev_info(&adapter->pdev->dev, + "delete RAID volume: hdl=0x%x, wwid=0x%llx\n", + raid_volume->hdl, raid_volume->wwid); + leapraid_raid_volume_remove(adapter, raid_volume); + + if (starget) + scsi_remove_target(&starget->dev); } static void leapraid_sas_volume_delete(struct leapraid_adapter *adapter, u16 hdl) { - struct leapraid_starget_priv *starget_priv; struct leapraid_raid_volume *raid_volume; - struct scsi_target *starget = NULL; - unsigned long flags; - spin_lock_irqsave(&adapter->dev_topo.raid_volume_lock, flags); raid_volume = leapraid_raid_volume_find_by_hdl(adapter, hdl); if (!raid_volume) { - spin_unlock_irqrestore(&adapter->dev_topo.raid_volume_lock, - flags); dev_warn(&adapter->pdev->dev, - "%s:%d: volume handle 0x%x not found\n", + "%s:%d: Volume handle 0x%x not found\n", __func__, __LINE__, hdl); return; } - if (raid_volume->starget) { - starget = raid_volume->starget; - starget_priv = starget->hostdata; - starget_priv->deleted = true; - } - - dev_info(&adapter->pdev->dev, - "delete raid volume: hdl=0x%x, wwid=0x%llx\n", - raid_volume->hdl, raid_volume->wwid); - list_del(&raid_volume->list); - kfree(raid_volume); - - spin_unlock_irqrestore(&adapter->dev_topo.raid_volume_lock, flags); - - if (starget) - scsi_remove_target(&starget->dev); + leapraid_sas_volume_delete_by_ptr(adapter, raid_volume); + leapraid_raid_volume_put(raid_volume); } static void leapraid_sas_ir_chg_evt(struct leapraid_adapter *adapter, @@ -4309,7 +4867,9 @@ static void leapraid_sas_enc_dev_stat_add_node( { union cfg_param_1 cfgp1 = {0}; union cfg_param_2 cfgp2 = {0}; - struct leapraid_enc_node *enc_node = NULL; + struct leapraid_enc_node *enc_node; + struct leapraid_enc_node *enc_exist; + unsigned long flags; int rc; enc_node = kzalloc(sizeof(*enc_node), GFP_KERNEL); @@ -4324,16 +4884,33 @@ static void leapraid_sas_enc_dev_stat_add_node( kfree(enc_node); return; } + + spin_lock_irqsave(&adapter->dev_topo.enc_lock, flags); + enc_exist = leapraid_enc_find_by_hdl(adapter, hdl); + if (enc_exist) { + spin_unlock_irqrestore(&adapter->dev_topo.enc_lock, flags); + kfree(enc_node); + return; + } list_add_tail(&enc_node->list, &adapter->dev_topo.enc_list); + spin_unlock_irqrestore(&adapter->dev_topo.enc_lock, flags); } static void leapraid_sas_enc_dev_stat_del_node( - struct leapraid_enc_node *enc_node) + struct leapraid_adapter *adapter, u16 hdl) { - if (!enc_node) + struct leapraid_enc_node *enc_node; + unsigned long flags; + + if (!hdl) return; - list_del(&enc_node->list); + spin_lock_irqsave(&adapter->dev_topo.enc_lock, flags); + enc_node = leapraid_enc_find_by_hdl(adapter, hdl); + if (enc_node) + list_del(&enc_node->list); + spin_unlock_irqrestore(&adapter->dev_topo.enc_lock, flags); + kfree(enc_node); } @@ -4341,7 +4918,6 @@ static void leapraid_sas_enc_dev_stat_chg_evt( struct leapraid_adapter *adapter, struct leapraid_fw_evt_work *fw_evt) { - struct leapraid_enc_node *enc_node = NULL; struct leapraid_evt_data_sas_enc_dev_status_change *evt_data; u16 enc_hdl; @@ -4350,15 +4926,13 @@ static void leapraid_sas_enc_dev_stat_chg_evt( evt_data = fw_evt->evt_data; enc_hdl = le16_to_cpu(evt_data->enc_hdl); - if (enc_hdl) - enc_node = leapraid_enc_find_by_hdl(adapter, enc_hdl); switch (evt_data->reason_code) { case LEAPRAID_EVT_SAS_ENCL_RC_ADDED: - if (!enc_node) + if (enc_hdl) leapraid_sas_enc_dev_stat_add_node(adapter, enc_hdl); break; case LEAPRAID_EVT_SAS_ENCL_RC_NOT_RESPONDING: - leapraid_sas_enc_dev_stat_del_node(enc_node); + leapraid_sas_enc_dev_stat_del_node(adapter, enc_hdl); break; default: break; @@ -4375,7 +4949,11 @@ static void leapraid_remove_unresp_sas_end_dev( spin_lock_irqsave(&adapter->dev_topo.sas_dev_lock, flags); list_for_each_entry_safe(sas_dev, sas_dev_next, &adapter->dev_topo.sas_dev_init_list, list) { + if (sas_dev->rphy || sas_dev->pend_sas_rphy_add) + continue; + list_del_init(&sas_dev->list); + leapraid_clear_cached_boot_dev(adapter, sas_dev, 0); leapraid_sdev_put(sas_dev); } list_for_each_entry_safe(sas_dev, sas_dev_next, @@ -4383,7 +4961,7 @@ static void leapraid_remove_unresp_sas_end_dev( if (!sas_dev->resp) list_move_tail(&sas_dev->list, &head); else - sas_dev->resp = false; + sas_dev->resp = 0; } spin_unlock_irqrestore(&adapter->dev_topo.sas_dev_lock, flags); @@ -4394,23 +4972,32 @@ static void leapraid_remove_unresp_sas_end_dev( } dev_info(&adapter->pdev->dev, - "unresponding sas end devices removed\n"); + "Unresponsive SAS end devices removed\n"); } static void leapraid_remove_unresp_raid_volumes( struct leapraid_adapter *adapter) { + unsigned long flags; struct leapraid_raid_volume *raid_volume, *raid_volume_next; + LIST_HEAD(head); + spin_lock_irqsave(&adapter->dev_topo.raid_volume_lock, flags); list_for_each_entry_safe(raid_volume, raid_volume_next, &adapter->dev_topo.raid_volume_list, list) { if (!raid_volume->resp) - leapraid_sas_volume_delete(adapter, raid_volume->hdl); + list_move_tail(&raid_volume->list, &head); else - raid_volume->resp = false; + raid_volume->resp = 0; + } + spin_unlock_irqrestore(&adapter->dev_topo.raid_volume_lock, flags); + + list_for_each_entry_safe(raid_volume, raid_volume_next, &head, list) { + leapraid_sas_volume_delete_by_ptr(adapter, raid_volume); } + dev_info(&adapter->pdev->dev, - "unresponding raid volumes removed\n"); + "Unresponsive RAID volumes removed\n"); } static void leapraid_remove_unresp_sas_exp(struct leapraid_adapter *adapter) @@ -4425,7 +5012,7 @@ static void leapraid_remove_unresp_sas_exp(struct leapraid_adapter *adapter) if (!topo_node_exp->resp) list_move_tail(&topo_node_exp->list, &head); else - topo_node_exp->resp = false; + topo_node_exp->resp = 0; } spin_unlock_irqrestore(&adapter->dev_topo.topo_node_lock, flags); @@ -4434,7 +5021,7 @@ static void leapraid_remove_unresp_sas_exp(struct leapraid_adapter *adapter) leapraid_exp_node_rm(adapter, topo_node_exp); dev_info(&adapter->pdev->dev, - "unresponding sas expanders removed\n"); + "Unresponsive SAS expanders removed\n"); } static void leapraid_remove_unresp_dev(struct leapraid_adapter *adapter) @@ -4490,25 +5077,27 @@ static void leapraid_update_dev_qdepth(struct leapraid_adapter *adapter) { struct leapraid_sdev_priv *sdev_priv; struct leapraid_sas_dev *sas_dev; + struct leapraid_adapter_attr *attr; struct scsi_device *sdev; u16 qdepth; + attr = &adapter->adapter_attr; shost_for_each_device(sdev, adapter->shost) { sdev_priv = sdev->hostdata; if (!sdev_priv || !sdev_priv->starget_priv) continue; sas_dev = sdev_priv->starget_priv->sas_dev; if (sas_dev && sas_dev->dev_info & LEAPRAID_DEVTYP_SSP_TGT) - qdepth = (sas_dev->port_type > 1) ? - adapter->adapter_attr.wideport_max_queue_depth : - adapter->adapter_attr.narrowport_max_queue_depth; + qdepth = (sas_dev->port_connection > 1) ? + attr->wideport_max_queue_depth : + attr->narrowport_max_queue_depth; else if (sas_dev && sas_dev->dev_info & LEAPRAID_DEVTYP_SATA_DEV) - qdepth = adapter->adapter_attr.sata_max_queue_depth; + qdepth = attr->sata_max_queue_depth; else continue; - leapraid_adjust_sdev_queue_depth(sdev, qdepth); + leapraid_change_queue_depth(sdev, qdepth); } } @@ -4524,15 +5113,17 @@ static void leapraid_update_exp_links(struct leapraid_adapter *adapter, cfgp2.handle = hdl; for (i = 0; i < topo_node_exp->phys_num; i++) { cfgp1.phy_number = i; - if ((leapraid_op_config_page(adapter, &exp_p1, cfgp1, cfgp2, - GET_SAS_EXPANDER_PG1))) + if (leapraid_op_config_page(adapter, &exp_p1, cfgp1, cfgp2, + GET_SAS_EXPANDER_PG1)) return; - leapraid_transport_update_links(adapter, + leapraid_transport_update_links( + adapter, topo_node_exp->sas_address, le16_to_cpu(exp_p1.attached_dev_hdl), i, - exp_p1.neg_link_rate >> 4, + exp_p1.neg_link_rate >> + LEAPRAID_SAS_NEG_LINK_RATE_SHIFT, topo_node_exp->card_port); } } @@ -4547,7 +5138,7 @@ static void leapraid_scan_exp_after_reset(struct leapraid_adapter *adapter) u16 hdl; u8 port_id; - dev_info(&adapter->pdev->dev, "begin scanning expanders\n"); + dev_info(&adapter->pdev->dev, "Begin scanning expanders\n"); cfgp1.form = LEAPRAID_SAS_CFG_PGAD_GET_NEXT_LOOP; for (hdl = 0xFFFF, cfgp2.handle = hdl; @@ -4558,7 +5149,8 @@ static void leapraid_scan_exp_after_reset(struct leapraid_adapter *adapter) port_id = exp_p0.physical_port; spin_lock_irqsave(&adapter->dev_topo.topo_node_lock, flags); topo_node_exp = - leapraid_exp_find_by_sas_address(adapter, + leapraid_exp_find_by_sas_address( + adapter, le64_to_cpu(exp_p0.sas_address), leapraid_get_port_by_id(adapter, port_id, @@ -4572,14 +5164,14 @@ static void leapraid_scan_exp_after_reset(struct leapraid_adapter *adapter) leapraid_exp_add(adapter, hdl); dev_info(&adapter->pdev->dev, - "add exp: hdl=0x%04x, sas addr=0x%016llx\n", + "add exp: hdl=0x%04x, SAS addr=0x%016llx\n", hdl, (unsigned long long)le64_to_cpu( exp_p0.sas_address)); } } - dev_info(&adapter->pdev->dev, "expanders scan complete\n"); + dev_info(&adapter->pdev->dev, "Expanders scan complete\n"); } static void leapraid_scan_phy_disks_after_reset( @@ -4596,7 +5188,7 @@ static void leapraid_scan_phy_disks_after_reset( u16 hdl, parent_hdl; u64 sas_addr; - dev_info(&adapter->pdev->dev, "begin scanning phys disk\n"); + dev_info(&adapter->pdev->dev, "Begin scanning phys disk\n"); cfgp1.form = LEAPRAID_SAS_CFG_PGAD_GET_NEXT_LOOP; for (phys_disk_num = 0xFF, cfgp2.form_specific = phys_disk_num; @@ -4629,20 +5221,25 @@ static void leapraid_scan_phy_disks_after_reset( LEAPRAID_SAS_NEG_LINK_RATE_1_5, leapraid_get_port_by_id( adapter, port_id, false)); - set_bit(hdl, - (unsigned long *)adapter->dev_topo.pd_hdls); - - leapraid_add_dev(adapter, hdl); - - dev_info(&adapter->pdev->dev, - "add phys disk: hdl=0x%04x, sas addr=0x%016llx\n", - hdl, - (unsigned long long)le64_to_cpu( - sas_dev_p0.sas_address)); + if (!hdl || hdl > + adapter->adapter_attr.features.max_dev_handle) { + dev_warn(&adapter->pdev->dev, + "%s: Invalid device handle\n", + __func__); + } else { + set_bit(hdl, adapter->dev_topo.pd_hdls); + leapraid_add_dev(adapter, hdl); + + dev_info(&adapter->pdev->dev, + "add pd hdl=0x%04x saddr=0x%016llx\n", + hdl, + (unsigned long long)le64_to_cpu( + sas_dev_p0.sas_address)); + } } } - dev_info(&adapter->pdev->dev, "phys disk scan complete\n"); + dev_info(&adapter->pdev->dev, "PHYs disk scan complete\n"); } static void leapraid_scan_vol_after_reset(struct leapraid_adapter *adapter) @@ -4652,10 +5249,9 @@ static void leapraid_scan_vol_after_reset(struct leapraid_adapter *adapter) union cfg_param_1 cfgp1_extra = {0}; union cfg_param_2 cfgp2_extra = {0}; struct leapraid_evt_data_ir_change evt_data; - static struct leapraid_raid_volume *raid_volume; + struct leapraid_raid_volume *raid_volume; struct leapraid_raidvol_p1 *vol_p1; struct leapraid_raidvol_p0 *vol_p0; - unsigned long flags; u16 hdl; vol_p0 = kzalloc(sizeof(*vol_p0), GFP_KERNEL); @@ -4668,21 +5264,20 @@ static void leapraid_scan_vol_after_reset(struct leapraid_adapter *adapter) return; } - dev_info(&adapter->pdev->dev, "begin scanning volumes\n"); + dev_info(&adapter->pdev->dev, "Begin scanning volumes\n"); cfgp1.form = LEAPRAID_SAS_CFG_PGAD_GET_NEXT_LOOP; for (hdl = 0xFFFF, cfgp2.handle = hdl; !leapraid_op_config_page(adapter, vol_p1, cfgp1, cfgp2, GET_RAID_VOLUME_PG1); cfgp2.handle = hdl) { hdl = le16_to_cpu(vol_p1->dev_hdl); - spin_lock_irqsave(&adapter->dev_topo.raid_volume_lock, flags); raid_volume = leapraid_raid_volume_find_by_wwid( adapter, le64_to_cpu(vol_p1->wwid)); - spin_unlock_irqrestore(&adapter->dev_topo.raid_volume_lock, - flags); - if (raid_volume) + if (raid_volume) { + leapraid_raid_volume_put(raid_volume); continue; + } cfgp1_extra.size = sizeof(struct leapraid_raidvol_p0); cfgp2_extra.handle = hdl; @@ -4707,7 +5302,7 @@ static void leapraid_scan_vol_after_reset(struct leapraid_adapter *adapter) kfree(vol_p0); kfree(vol_p1); - dev_info(&adapter->pdev->dev, "volumes scan complete\n"); + dev_info(&adapter->pdev->dev, "Volumes scan complete\n"); } static void leapraid_scan_sas_dev_after_reset(struct leapraid_adapter *adapter) @@ -4721,7 +5316,7 @@ static void leapraid_scan_sas_dev_after_reset(struct leapraid_adapter *adapter) u8 port_id; dev_info(&adapter->pdev->dev, - "begin scanning sas end devices\n"); + "Begin scanning SAS end devices\n"); cfgp1.form = LEAPRAID_SAS_CFG_PGAD_GET_NEXT_LOOP; for (hdl = 0xFFFF, cfgp2.handle = hdl; @@ -4729,6 +5324,13 @@ static void leapraid_scan_sas_dev_after_reset(struct leapraid_adapter *adapter) GET_SAS_DEVICE_PG0); cfgp2.handle = hdl) { hdl = le16_to_cpu(sas_dev_p0.dev_hdl); + if (!hdl || + hdl > adapter->adapter_attr.features.max_dev_handle) { + dev_warn(&adapter->pdev->dev, + "%s: Invalid device handle\n", __func__); + continue; + } + if (!(leapraid_is_end_dev(le32_to_cpu(sas_dev_p0.dev_info)))) continue; @@ -4759,21 +5361,21 @@ static void leapraid_scan_sas_dev_after_reset(struct leapraid_adapter *adapter) false)); leapraid_add_dev(adapter, hdl); dev_info(&adapter->pdev->dev, - "add sas dev: hdl=0x%04x, sas addr=0x%016llx\n", + "Add SAS dev: hdl=0x%04x, saddr=0x%016llx\n", hdl, (unsigned long long)le64_to_cpu( sas_dev_p0.sas_address)); } } - dev_info(&adapter->pdev->dev, "sas end devices scan complete\n"); + dev_info(&adapter->pdev->dev, "SAS end devices scan complete\n"); } static void leapraid_scan_all_dev_after_reset(struct leapraid_adapter *adapter) { - dev_info(&adapter->pdev->dev, "begin scanning devices\n"); + dev_info(&adapter->pdev->dev, "Begin scanning devices\n"); - leapraid_sas_host_add(adapter, adapter->dev_topo.card.phys_num); + leapraid_sas_host_add(adapter, adapter->dev_topo.card.phys_num > 0); leapraid_scan_exp_after_reset(adapter); if (adapter->adapter_attr.raid_support) { leapraid_scan_phy_disks_after_reset(adapter); @@ -4781,11 +5383,13 @@ static void leapraid_scan_all_dev_after_reset(struct leapraid_adapter *adapter) } leapraid_scan_sas_dev_after_reset(adapter); - dev_info(&adapter->pdev->dev, "devices scan complete\n"); + dev_info(&adapter->pdev->dev, "Devices scan complete\n"); } static void leapraid_hardreset_async_logic(struct leapraid_adapter *adapter) { + unsigned long flags; + leapraid_remove_unresp_dev(adapter); leapraid_del_dirty_vphy(adapter); leapraid_del_dirty_card_port(adapter); @@ -4794,6 +5398,10 @@ static void leapraid_hardreset_async_logic(struct leapraid_adapter *adapter) if (adapter->scan_dev_desc.driver_loading) leapraid_scan_dev_done(adapter); + spin_lock_irqsave(&adapter->reset_desc.adapter_reset_lock, flags); + adapter->access_ctrl.shost_recover_async = 0; + spin_unlock_irqrestore(&adapter->reset_desc.adapter_reset_lock, flags); + wake_up(&adapter->access_ctrl.shost_recover_wq); } static int leapraid_send_enc_cmd(struct leapraid_adapter *adapter, @@ -4802,15 +5410,17 @@ static int leapraid_send_enc_cmd(struct leapraid_adapter *adapter, { void *req; bool reset_flg = false; - int rc = 0; + int rc; mutex_lock(&adapter->driver_cmds.enc_cmd.mutex); - rc = leapraid_check_adapter_is_op(adapter); + rc = leapraid_check_adapter_is_op(adapter, LEAPRAID_DB_WAIT_OP_SHORT, + __func__); if (rc) - goto out; + goto unlock; adapter->driver_cmds.enc_cmd.status = LEAPRAID_CMD_PENDING; - req = leapraid_get_task_desc(adapter, + req = leapraid_get_task_desc( + adapter, adapter->driver_cmds.enc_cmd.inter_taskid); memset(req, 0, LEAPRAID_REQUEST_SIZE); memcpy(req, sep_req, sizeof(struct leapraid_sep_req)); @@ -4820,6 +5430,10 @@ static int leapraid_send_enc_cmd(struct leapraid_adapter *adapter, wait_for_completion_timeout(&adapter->driver_cmds.enc_cmd.done, LEAPRAID_ENC_CMD_TIMEOUT * HZ); if (!(adapter->driver_cmds.enc_cmd.status & LEAPRAID_CMD_DONE)) { + dev_err(&adapter->pdev->dev, + "%s: SEP command timeout, status=0x%x\n", + __func__, adapter->driver_cmds.enc_cmd.status); + leapraid_log_req_context(adapter, sep_req); reset_flg = leapraid_check_reset( adapter->driver_cmds.enc_cmd.status); @@ -4828,17 +5442,17 @@ static int leapraid_send_enc_cmd(struct leapraid_adapter *adapter, } if (adapter->driver_cmds.enc_cmd.status & LEAPRAID_CMD_REPLY_VALID) - memcpy(sep_rep, (void *)(&adapter->driver_cmds.enc_cmd.reply), + memcpy(sep_rep, &adapter->driver_cmds.enc_cmd.reply, sizeof(struct leapraid_sep_rep)); do_hard_reset: if (reset_flg) { - dev_info(&adapter->pdev->dev, "%s:%d call hard_reset\n", + dev_info(&adapter->pdev->dev, "%s:%d: call hard_reset\n", __func__, __LINE__); leapraid_hard_reset_handler(adapter, FULL_RESET); } adapter->driver_cmds.enc_cmd.status = LEAPRAID_CMD_NOT_USED; -out: +unlock: mutex_unlock(&adapter->driver_cmds.enc_cmd.mutex); return rc; } @@ -4857,8 +5471,9 @@ static void leapraid_set_led(struct leapraid_adapter *adapter, sep_req.func = LEAPRAID_FUNC_SCSI_ENC_PROCESSOR; sep_req.act = LEAPRAID_SEP_REQ_ACT_WRITE_STATUS; if (on) { - sep_req.slot_status = - cpu_to_le32(LEAPRAID_SEP_REQ_SLOTSTATUS_PREDICTED_FAULT); + u32 status = LEAPRAID_SEP_REQ_SLOTSTATUS_PREDICTED_FAULT; + + sep_req.slot_status = cpu_to_le32(status); sep_req.dev_hdl = cpu_to_le16(sas_dev->hdl); sep_req.flg = LEAPRAID_SEP_REQ_FLG_DEVHDL_ADDRESS; if (leapraid_send_enc_cmd(adapter, &sep_rep, &sep_req)) { @@ -4866,52 +5481,75 @@ static void leapraid_set_led(struct leapraid_adapter *adapter, return; } - sas_dev->led_on = true; - if (sep_rep.adapter_status) - leapraid_sdev_put(sas_dev); + sas_dev->led_on = 1; + leapraid_sdev_put(sas_dev); } else { sep_req.slot_status = 0; sep_req.slot = cpu_to_le16(sas_dev->slot); sep_req.dev_hdl = 0; sep_req.enc_hdl = cpu_to_le16(sas_dev->enc_hdl); sep_req.flg = LEAPRAID_SEP_REQ_FLG_ENCLOSURE_SLOT_ADDRESS; - if ((leapraid_send_enc_cmd(adapter, &sep_rep, &sep_req))) { - leapraid_sdev_put(sas_dev); - return; - } + leapraid_send_enc_cmd(adapter, &sep_rep, &sep_req); + } +} - if (sep_rep.adapter_status) { - leapraid_sdev_put(sas_dev); - return; +static int leapraid_wait_adapter_recovery(struct leapraid_adapter *adapter) +{ + unsigned long flags; + + while (scsi_host_in_recovery(adapter->shost) || + adapter->access_ctrl.shost_recovering) { + if (adapter->access_ctrl.host_removing || + adapter->fw_evt_s.fw_evt_cleanup) { + spin_lock_irqsave( + &adapter->reset_desc.adapter_reset_lock, + flags); + adapter->access_ctrl.shost_recover_async = 0; + spin_unlock_irqrestore( + &adapter->reset_desc.adapter_reset_lock, + flags); + + wake_up(&adapter->access_ctrl.shost_recover_wq); + + dev_warn(&adapter->pdev->dev, + "%s: Failed, shost %d, host %d\n", + __func__, + adapter->access_ctrl.shost_recovering, + adapter->access_ctrl.host_removing); + + return -EFAULT; } + + wait_event_timeout(adapter->access_ctrl.recovery_waitq, + !adapter->access_ctrl.shost_recovering || + adapter->access_ctrl.host_removing || + adapter->fw_evt_s.fw_evt_cleanup, + msecs_to_jiffies(1000)); } + return 0; } static void leapraid_fw_work(struct leapraid_adapter *adapter, struct leapraid_fw_evt_work *fw_evt) { struct leapraid_sas_dev *sas_dev; + unsigned long flags; + spin_lock_irqsave(&adapter->fw_evt_s.fw_evt_lock, flags); adapter->fw_evt_s.cur_evt = fw_evt; + adapter->fw_evt_s.cur_evt_task = current; + spin_unlock_irqrestore(&adapter->fw_evt_s.fw_evt_lock, flags); leapraid_del_fw_evt_from_list(adapter, fw_evt); if (adapter->access_ctrl.host_removing || adapter->access_ctrl.pcie_recovering) { + spin_lock_irqsave(&adapter->fw_evt_s.fw_evt_lock, flags); leapraid_fw_evt_put(fw_evt); adapter->fw_evt_s.cur_evt = NULL; + adapter->fw_evt_s.cur_evt_task = NULL; + spin_unlock_irqrestore(&adapter->fw_evt_s.fw_evt_lock, flags); return; } switch (fw_evt->evt_type) { - case LEAPRAID_EVT_SAS_DISCOVERY: - { - struct leapraid_evt_data_sas_disc *evt_data; - - evt_data = fw_evt->evt_data; - if (evt_data->reason_code == - LEAPRAID_EVT_SAS_DISC_RC_STARTED && - !adapter->dev_topo.card.phys_num) - leapraid_sas_host_add(adapter, 0); - break; - } case LEAPRAID_EVT_SAS_TOPO_CHANGE_LIST: leapraid_sas_topo_chg_evt(adapter, fw_evt); break; @@ -4922,14 +5560,9 @@ static void leapraid_fw_work(struct leapraid_adapter *adapter, leapraid_sas_enc_dev_stat_chg_evt(adapter, fw_evt); break; case LEAPRAID_EVT_REMOVE_DEAD_DEV: - while (scsi_host_in_recovery(adapter->shost) || - adapter->access_ctrl.shost_recovering) { - if (adapter->access_ctrl.host_removing || - adapter->fw_evt_s.fw_evt_cleanup) - goto out; + if (leapraid_wait_adapter_recovery(adapter)) + goto out_cleanup; - ssleep(1); - } leapraid_hardreset_async_logic(adapter); break; case LEAPRAID_EVT_TURN_ON_PFA_LED: @@ -4938,14 +5571,17 @@ static void leapraid_fw_work(struct leapraid_adapter *adapter, leapraid_set_led(adapter, sas_dev, true); break; case LEAPRAID_EVT_SCAN_DEV_DONE: - adapter->scan_dev_desc.scan_start = false; + adapter->scan_dev_desc.scan_start = 0; break; default: break; } -out: +out_cleanup: + spin_lock_irqsave(&adapter->fw_evt_s.fw_evt_lock, flags); leapraid_fw_evt_put(fw_evt); adapter->fw_evt_s.cur_evt = NULL; + adapter->fw_evt_s.cur_evt_task = NULL; + spin_unlock_irqrestore(&adapter->fw_evt_s.fw_evt_lock, flags); } static void leapraid_sas_dev_stat_chg_evt( @@ -4953,7 +5589,7 @@ static void leapraid_sas_dev_stat_chg_evt( struct leapraid_evt_data_sas_dev_status_change *event_data) { struct leapraid_starget_priv *starget_priv; - struct leapraid_sas_dev *sas_dev = NULL; + struct leapraid_sas_dev *sas_dev; u64 sas_address; unsigned long flags; @@ -4968,26 +5604,29 @@ static void leapraid_sas_dev_stat_chg_evt( spin_lock_irqsave(&adapter->dev_topo.sas_dev_lock, flags); sas_address = le64_to_cpu(event_data->sas_address); - sas_dev = leapraid_hold_lock_get_sas_dev_by_addr(adapter, + sas_dev = leapraid_hold_lock_get_sas_dev_by_addr( + adapter, sas_address, leapraid_get_port_by_id(adapter, event_data->physical_port, false)); - if (sas_dev && sas_dev->starget) { - starget_priv = sas_dev->starget->hostdata; - if (starget_priv) { - switch (event_data->reason_code) { - case LEAPRAID_EVT_SAS_DEV_STAT_RC_INTERNAL_DEV_RESET: - starget_priv->tm_busy = true; - break; - case LEAPRAID_EVT_SAS_DEV_STAT_RC_CMP_INTERNAL_DEV_RESET: - starget_priv->tm_busy = false; - break; - } + if (!sas_dev || !sas_dev->starget) + goto out_unlock; + + starget_priv = sas_dev->starget->hostdata; + if (starget_priv) { + switch (event_data->reason_code) { + case LEAPRAID_EVT_SAS_DEV_STAT_RC_INTERNAL_DEV_RESET: + starget_priv->tm_busy = 1; + break; + case LEAPRAID_EVT_SAS_DEV_STAT_RC_CMP_INTERNAL_DEV_RESET: + starget_priv->tm_busy = 0; + break; } } +out_unlock: if (sas_dev) leapraid_sdev_put(sas_dev); spin_unlock_irqrestore(&adapter->dev_topo.sas_dev_lock, flags); @@ -5000,32 +5639,45 @@ static void leapraid_set_volume_delete_flag(struct leapraid_adapter *adapter, struct leapraid_starget_priv *sas_target_priv_data; unsigned long flags; - spin_lock_irqsave(&adapter->dev_topo.raid_volume_lock, flags); raid_volume = leapraid_raid_volume_find_by_hdl(adapter, handle); - if (raid_volume && raid_volume->starget && - raid_volume->starget->hostdata) { - sas_target_priv_data = raid_volume->starget->hostdata; - sas_target_priv_data->deleted = true; + if (raid_volume) { + spin_lock_irqsave(&adapter->dev_topo.raid_volume_lock, flags); + if (raid_volume->starget && + raid_volume->starget->hostdata) { + sas_target_priv_data = raid_volume->starget->hostdata; + sas_target_priv_data->deleted = 1; + } + spin_unlock_irqrestore(&adapter->dev_topo.raid_volume_lock, + flags); + leapraid_raid_volume_put(raid_volume); } - spin_unlock_irqrestore(&adapter->dev_topo.raid_volume_lock, flags); } -static void leapraid_check_ir_change_evt(struct leapraid_adapter *adapter, +static void leapraid_check_ir_change_evt( + struct leapraid_adapter *adapter, struct leapraid_evt_data_ir_change *evt_data) { u16 phys_disk_dev_hdl; switch (evt_data->reason_code) { case LEAPRAID_EVT_IR_RC_VOLUME_DELETE: - leapraid_set_volume_delete_flag(adapter, - le16_to_cpu(evt_data->vol_dev_hdl)); + leapraid_set_volume_delete_flag( + adapter, + le16_to_cpu(evt_data->vol_dev_hdl)); break; case LEAPRAID_EVT_IR_RC_PD_UNHIDDEN_TO_DELETE: phys_disk_dev_hdl = le16_to_cpu(evt_data->phys_disk_dev_hdl); - clear_bit(phys_disk_dev_hdl, - (unsigned long *)adapter->dev_topo.pd_hdls); - leapraid_tgt_rst_send(adapter, phys_disk_dev_hdl); + if (!phys_disk_dev_hdl || + phys_disk_dev_hdl > + adapter->adapter_attr.features.max_dev_handle) { + dev_warn(&adapter->pdev->dev, + "%s: Invalid device handle\n", __func__); + } else { + clear_bit(phys_disk_dev_hdl, + adapter->dev_topo.pd_hdls); + leapraid_tgt_rst_send(adapter, phys_disk_dev_hdl); + } break; } } @@ -5035,7 +5687,7 @@ static void leapraid_topo_del_evts_process_exp_status( struct leapraid_evt_data_sas_topo_change_list *evt_data) { struct leapraid_fw_evt_work *fw_evt = NULL; - struct leapraid_evt_data_sas_topo_change_list *loc_evt_data = NULL; + struct leapraid_evt_data_sas_topo_change_list *loc_evt_data; unsigned long flags; u16 exp_hdl; @@ -5066,7 +5718,8 @@ static void leapraid_topo_del_evts_process_exp_status( } } -static void leapraid_check_topo_del_evts(struct leapraid_adapter *adapter, +static void leapraid_check_topo_del_evts( + struct leapraid_adapter *adapter, struct leapraid_evt_data_sas_topo_change_list *evt_data) { int reason_code; @@ -5096,17 +5749,20 @@ static bool leapraid_async_process_evt( switch (evt) { case LEAPRAID_EVT_SAS_DEV_STATUS_CHANGE: - leapraid_sas_dev_stat_chg_evt(adapter, + leapraid_sas_dev_stat_chg_evt( + adapter, (struct leapraid_evt_data_sas_dev_status_change *)event_notify_rep->evt_data); break; case LEAPRAID_EVT_IR_CHANGE: - leapraid_check_ir_change_evt(adapter, + leapraid_check_ir_change_evt( + adapter, (struct leapraid_evt_data_ir_change *)event_notify_rep->evt_data); break; case LEAPRAID_EVT_SAS_TOPO_CHANGE_LIST: - leapraid_check_topo_del_evts(adapter, + leapraid_check_topo_del_evts( + adapter, (struct leapraid_evt_data_sas_topo_change_list *)event_notify_rep->evt_data); if (adapter->access_ctrl.shost_recovering) { @@ -5114,7 +5770,6 @@ static bool leapraid_async_process_evt( return exit_flag; } break; - case LEAPRAID_EVT_SAS_DISCOVERY: case LEAPRAID_EVT_SAS_ENCL_DEV_STATUS_CHANGE: break; default: @@ -5136,7 +5791,7 @@ static void leapraid_async_evt_cb_enqueue( if (!fw_evt) return; - evt_sz = le16_to_cpu(evt_notify_rep->evt_data_len) * 4; + evt_sz = le16_to_cpu(evt_notify_rep->evt_data_len) * sizeof(u32); fw_evt->evt_data = kmemdup(evt_notify_rep->evt_data, evt_sz, GFP_ATOMIC); if (!fw_evt->evt_data) { @@ -5225,13 +5880,63 @@ static void leapraid_scan_dev_complete(struct leapraid_adapter *adapter) leapraid_fw_evt_put(fw_evt); } -static u8 leapraid_driver_cmds_done(struct leapraid_adapter *adapter, - u16 taskid, u8 msix_index, - u32 rep_paddr, u8 cb_idx) +static u8 leapraid_handle_scan_cb(struct leapraid_adapter *adapter, + struct leapraid_driver_cmd *cmd, + struct leapraid_rep *rep) +{ + u16 status; + + cmd->status &= ~LEAPRAID_CMD_PENDING; + + status = le16_to_cpu(rep->adapter_status) & + LEAPRAID_ADAPTER_STATUS_MASK; + + if (status != LEAPRAID_ADAPTER_STATUS_SUCCESS) + adapter->scan_dev_desc.scan_dev_failed = 1; + + if (!cmd->async_scan_dev) { + complete(&cmd->done); + return 1; + } + + if (status == LEAPRAID_ADAPTER_STATUS_SUCCESS) + leapraid_scan_dev_complete(adapter); + else + adapter->scan_dev_desc.scan_start_failed = status; + + return 1; +} + +static void leapraid_handle_ctl_cb(struct leapraid_adapter *adapter, + struct leapraid_rep *rep, + u16 taskid) +{ + struct leapraid_scsiio_rep *scsiio_reply; + + if (rep->function != LEAPRAID_FUNC_SCSIIO && + rep->function != LEAPRAID_FUNC_SCSIIO_RAID_PASSTHROUGH) + return; + + scsiio_reply = (struct leapraid_scsiio_rep *)rep; + + if (!(scsiio_reply->scsi_state & + LEAPRAID_SCSI_STATE_AUTOSENSE_VALID)) + return; + + memcpy(&adapter->driver_cmds.ctl_cmd.sense, + leapraid_get_sense_buffer(adapter, taskid), + min_t(u32, SCSI_SENSE_BUFFERSIZE, + le32_to_cpu(scsiio_reply->sense_count))); +} + +static bool leapraid_driver_cmds_done(struct leapraid_adapter *adapter, + u16 taskid, u8 msix_index, + u32 rep_paddr, u8 cb_idx) { struct leapraid_rep *leap_mpi_rep = leapraid_get_reply_vaddr(adapter, rep_paddr); struct leapraid_driver_cmd *sp_cmd, *_sp_cmd = NULL; + u8 reply_len; list_for_each_entry(sp_cmd, &adapter->driver_cmds.special_cmd_list, list) @@ -5241,74 +5946,55 @@ static u8 leapraid_driver_cmds_done(struct leapraid_adapter *adapter, } if (WARN_ON(!_sp_cmd)) - return 1; + return true; if (WARN_ON(_sp_cmd->status == LEAPRAID_CMD_NOT_USED)) - return 1; + return true; if (WARN_ON(taskid != _sp_cmd->hp_taskid && taskid != _sp_cmd->taskid && taskid != _sp_cmd->inter_taskid)) - return 1; - + return true; _sp_cmd->status |= LEAPRAID_CMD_DONE; if (leap_mpi_rep) { - memcpy((void *)(&_sp_cmd->reply), leap_mpi_rep, - leap_mpi_rep->msg_len * 4); + reply_len = leap_mpi_rep->msg_len * sizeof(u32); + if (reply_len > LEAPRAID_REPLY_SIZE) + reply_len = LEAPRAID_REPLY_SIZE; + memcpy(&_sp_cmd->reply, leap_mpi_rep, reply_len); _sp_cmd->status |= LEAPRAID_CMD_REPLY_VALID; - if (_sp_cmd->cb_idx == LEAPRAID_SCAN_DEV_CB_IDX) { - u16 adapter_status; - - _sp_cmd->status &= ~LEAPRAID_CMD_PENDING; - adapter_status = - le16_to_cpu(leap_mpi_rep->adapter_status) & - LEAPRAID_ADAPTER_STATUS_MASK; - if (adapter_status != LEAPRAID_ADAPTER_STATUS_SUCCESS) - adapter->scan_dev_desc.scan_dev_failed = true; - - if (_sp_cmd->async_scan_dev) { - if (adapter_status == - LEAPRAID_ADAPTER_STATUS_SUCCESS) { - leapraid_scan_dev_complete(adapter); - } else { - adapter->scan_dev_desc.scan_start_failed = - adapter_status; - } - return 1; - } - - complete(&_sp_cmd->done); - return 1; - } + if (_sp_cmd->cb_idx == LEAPRAID_SCAN_DEV_CB_IDX) + return leapraid_handle_scan_cb(adapter, + _sp_cmd, + leap_mpi_rep); - if (_sp_cmd->cb_idx == LEAPRAID_CTL_CB_IDX) { - struct leapraid_scsiio_rep *scsiio_reply; - - if (leap_mpi_rep->function == - LEAPRAID_FUNC_SCSIIO_REQ || - leap_mpi_rep->function == - LEAPRAID_FUNC_RAID_SCSIIO_PASSTHROUGH) { - scsiio_reply = - (struct leapraid_scsiio_rep *)leap_mpi_rep; - if (scsiio_reply->scsi_state & - LEAPRAID_SCSI_STATE_AUTOSENSE_VALID) - memcpy((void *)(&adapter->driver_cmds.ctl_cmd.sense), - leapraid_get_sense_buffer(adapter, taskid), - min_t(u32, - SCSI_SENSE_BUFFERSIZE, - le32_to_cpu(scsiio_reply->sense_count))); - } - } + if (_sp_cmd->cb_idx == LEAPRAID_CTL_CB_IDX) + leapraid_handle_ctl_cb(adapter, leap_mpi_rep, taskid); } _sp_cmd->status &= ~LEAPRAID_CMD_PENDING; complete(&_sp_cmd->done); - return 1; + return true; } -static void leapraid_request_descript_handler(struct leapraid_adapter *adapter, - union leapraid_rep_desc_union *rpf, - u8 req_desc_type, u8 msix_idx) +static void leapraid_complete_task(struct leapraid_adapter *adapter, + u16 taskid, u8 msix_idx, u32 rep) +{ + if (taskid <= adapter->shost->can_queue || + taskid == adapter->driver_cmds.driver_scsiio_cmd.taskid) { + if (leapraid_scsiio_done(adapter, taskid, msix_idx, rep)) + leapraid_free_taskid(adapter, taskid); + return; + } + + if (leapraid_driver_cmds_done(adapter, taskid, msix_idx, rep, + leapraid_get_cb_idx(adapter, taskid))) + leapraid_free_taskid(adapter, taskid); +} + +static void leapraid_request_descript_handler( + struct leapraid_adapter *adapter, + union leapraid_rep_desc_union *rpf, + u8 req_desc_type, u8 msix_idx) { u32 rep; u16 taskid; @@ -5318,50 +6004,34 @@ static void leapraid_request_descript_handler(struct leapraid_adapter *adapter, switch (req_desc_type) { case LEAPRAID_RPY_DESC_FLG_FP_SCSI_IO_SUCCESS: case LEAPRAID_RPY_DESC_FLG_SCSI_IO_SUCCESS: - if (taskid <= adapter->shost->can_queue || - taskid == adapter->driver_cmds.driver_scsiio_cmd.taskid) { - leapraid_scsiio_done(adapter, taskid, msix_idx, 0); - } else { - if (leapraid_driver_cmds_done(adapter, taskid, - msix_idx, 0, - leapraid_get_cb_idx(adapter, - taskid))) - leapraid_free_taskid(adapter, taskid); - } + leapraid_complete_task(adapter, taskid, msix_idx, 0); break; case LEAPRAID_RPY_DESC_FLG_ADDRESS_REPLY: rep = le32_to_cpu(rpf->addr_rep.rep_frame_addr); - if (rep > ((u32)adapter->mem_desc.rep_msg_dma + - adapter->adapter_attr.rep_msg_qd * LEAPRAID_REPLY_SIEZ) || - rep < ((u32)adapter->mem_desc.rep_msg_dma)) + if (rep > (u32)adapter->mem_desc.rep_msg_dma + + adapter->adapter_attr.rep_msg_qd * + LEAPRAID_REPLY_SIZE || + rep < (u32)adapter->mem_desc.rep_msg_dma) rep = 0; - if (taskid) { - if (taskid <= adapter->shost->can_queue || - taskid == adapter->driver_cmds.driver_scsiio_cmd.taskid) { - leapraid_scsiio_done(adapter, taskid, - msix_idx, rep); - } else { - if (leapraid_driver_cmds_done(adapter, taskid, - msix_idx, rep, - leapraid_get_cb_idx(adapter, - taskid))) - leapraid_free_taskid(adapter, taskid); - } - } else { + + if (taskid) + leapraid_complete_task(adapter, taskid, msix_idx, rep); + else leapraid_handle_async_event(adapter, msix_idx, rep); - } - if (rep) { - adapter->rep_msg_host_idx = - (adapter->rep_msg_host_idx == - (adapter->adapter_attr.rep_msg_qd - 1)) ? - 0 : adapter->rep_msg_host_idx + 1; - adapter->mem_desc.rep_msg_addr[adapter->rep_msg_host_idx] = - cpu_to_le32(rep); - wmb(); /* Make sure that all write ops are in order */ - writel(adapter->rep_msg_host_idx, - &adapter->iomem_base->rep_msg_host_idx); - } + if (!rep) + return; + + adapter->rep_msg_host_idx = + (adapter->rep_msg_host_idx == + (adapter->adapter_attr.rep_msg_qd - 1)) ? + 0 : adapter->rep_msg_host_idx + 1; + adapter->mem_desc.rep_msg_addr[adapter->rep_msg_host_idx] = + cpu_to_le32(rep); + wmb(); /* Make sure that all write ops are in order */ + writel(adapter->rep_msg_host_idx, + &adapter->iomem_base->rep_msg_host_idx); + break; default: break; @@ -5423,8 +6093,8 @@ int leapraid_rep_queue_handler(struct leapraid_rq *rq) wmb(); /* Make sure that all write ops are in order */ writel(rq->rep_post_host_idx | ((msix_idx & LEAPRAID_MSIX_GROUP_MASK) << LEAPRAID_RPHI_MSIX_IDX_SHIFT), - &adapter->iomem_base->rep_post_reg_idx[msix_idx / - LEAPRAID_MSIX_GROUP_SIZE].idx); + &adapter->iomem_base->rep_post_reg_idx[ + msix_idx / LEAPRAID_MSIX_GROUP_SIZE].idx); atomic_dec(&rq->busy); return finish_cmds; } @@ -5441,7 +6111,7 @@ static irqreturn_t leapraid_irq_handler(int irq, void *bus_id) if (adapter->mask_int) return IRQ_NONE; - return ((leapraid_rep_queue_handler(rq) > 0) ? + return (leapraid_rep_queue_handler(rq) > 0 ? IRQ_HANDLED : IRQ_NONE); } @@ -5469,7 +6139,8 @@ void leapraid_sync_irqs(struct leapraid_adapter *adapter, bool poll) if (int_rq->rq.msix_idx == 0) continue; - synchronize_irq(pci_irq_vector(adapter->pdev, int_rq->rq.msix_idx)); + synchronize_irq(pci_irq_vector(adapter->pdev, + int_rq->rq.msix_idx)); if (poll) leapraid_rep_queue_handler(&int_rq->rq); } @@ -5491,16 +6162,18 @@ void leapraid_sync_irqs(struct leapraid_adapter *adapter, bool poll) void leapraid_mq_polling_pause(struct leapraid_adapter *adapter) { - int iopoll_q_count = - adapter->adapter_attr.rq_cnt - - adapter->notification_desc.iopoll_qdex; + struct leapraid_notification_desc *desc; + int iopoll_q_count; int qid; + desc = &adapter->notification_desc; + iopoll_q_count = adapter->adapter_attr.rq_cnt - desc->iopoll_qdex; + for (qid = 0; qid < iopoll_q_count; qid++) - atomic_set(&adapter->notification_desc.blk_mq_poll_rqs[qid].pause, 1); + atomic_set(&desc->blk_mq_poll_rqs[qid].pause, 1); for (qid = 0; qid < iopoll_q_count; qid++) { - while (atomic_read(&adapter->notification_desc.blk_mq_poll_rqs[qid].busy)) { + while (atomic_read(&desc->blk_mq_poll_rqs[qid].busy)) { cpu_relax(); udelay(LEAPRAID_IO_POLL_DELAY_US); } @@ -5509,19 +6182,30 @@ void leapraid_mq_polling_pause(struct leapraid_adapter *adapter) void leapraid_mq_polling_resume(struct leapraid_adapter *adapter) { - int iopoll_q_count = - adapter->adapter_attr.rq_cnt - - adapter->notification_desc.iopoll_qdex; + struct leapraid_notification_desc *desc; + int iopoll_q_count; int qid; + desc = &adapter->notification_desc; + iopoll_q_count = adapter->adapter_attr.rq_cnt - desc->iopoll_qdex; + for (qid = 0; qid < iopoll_q_count; qid++) - atomic_set(&adapter->notification_desc.blk_mq_poll_rqs[qid].pause, 0); + atomic_set(&desc->blk_mq_poll_rqs[qid].pause, 0); } static int leapraid_unlock_host_diag(struct leapraid_adapter *adapter, u32 *host_diag) { - const u32 unlock_seq[] = { 0x0, 0xF, 0x4, 0xB, 0x2, 0x7, 0xD }; + const u32 unlock_seq[] = { + LEAPRAID_WRSEQ_FLUSH_KEY_VALUE, + LEAPRAID_WRSEQ_1ST_KEY_VALUE, + LEAPRAID_WRSEQ_2ND_KEY_VALUE, + LEAPRAID_WRSEQ_3RD_KEY_VALUE, + LEAPRAID_WRSEQ_4TH_KEY_VALUE, + LEAPRAID_WRSEQ_5TH_KEY_VALUE, + LEAPRAID_WRSEQ_6TH_KEY_VALUE + }; + const int max_retries = LEAPRAID_UNLOCK_RETRY_LIMIT; int retry = 0; unsigned int i; @@ -5538,51 +6222,46 @@ static int leapraid_unlock_host_diag(struct leapraid_adapter *adapter, return 0; } - dev_err(&adapter->pdev->dev, "try host reset timeout!\n"); + dev_err(&adapter->pdev->dev, "Try host reset timeout!\n"); return -EFAULT; } static int leapraid_host_diag_reset(struct leapraid_adapter *adapter) { u32 host_diag; - u32 cnt; - dev_info(&adapter->pdev->dev, "entering host diag reset!\n"); + dev_info(&adapter->pdev->dev, "Entering host diag reset!\n"); pci_cfg_access_lock(adapter->pdev); mutex_lock(&adapter->reset_desc.host_diag_mutex); if (leapraid_unlock_host_diag(adapter, &host_diag)) - goto out; + goto out_cleanup; writel(host_diag | LEAPRAID_DIAG_RESET, &adapter->iomem_base->host_diag); + msleep(LEAPRAID_MSLEEP_EXTRA_LONG_MS); msleep(LEAPRAID_MSLEEP_NORMAL_MS); - for (cnt = 0; cnt < LEAPRAID_RESET_LOOP_COUNT_DEFAULT; cnt++) { - host_diag = leapraid_readl(&adapter->iomem_base->host_diag); - if (host_diag == LEAPRAID_INVALID_HOST_DIAG_VAL) - goto out; - - if (!(host_diag & LEAPRAID_DIAG_RESET)) - break; - msleep(LEAPRAID_RESET_POLL_INTERVAL_MS); - } + host_diag = leapraid_readl(&adapter->iomem_base->host_diag); + if (host_diag == LEAPRAID_INVALID_HOST_DIAG_VAL || + host_diag & LEAPRAID_DIAG_RESET) + goto out_cleanup; - writel(host_diag & ~LEAPRAID_DIAG_HOLD_ADAPTER_RESET, - &adapter->iomem_base->host_diag); writel(0x0, &adapter->iomem_base->ws); mutex_unlock(&adapter->reset_desc.host_diag_mutex); if (!leapraid_wait_adapter_ready(adapter)) - goto out; + goto out_failed; pci_cfg_access_unlock(adapter->pdev); - dev_info(&adapter->pdev->dev, "host diag success!\n"); + dev_info(&adapter->pdev->dev, "Host diag success!\n"); return 0; -out: - pci_cfg_access_unlock(adapter->pdev); - dev_info(&adapter->pdev->dev, "host diag failed!\n"); + +out_cleanup: mutex_unlock(&adapter->reset_desc.host_diag_mutex); +out_failed: + pci_cfg_access_unlock(adapter->pdev); + dev_info(&adapter->pdev->dev, "Host diag failed!\n"); return -EFAULT; } @@ -5592,12 +6271,12 @@ static int leapraid_find_matching_port( { int i; - for (i = 0; i < count; i++) { + for (i = 0; i < count; i++) if (card_port_table[i].port_id == port_id && card_port_table[i].sas_address == sas_addr) return i; - } - return -1; + + return LEAPRAID_INVALID_INDEX; } static u8 leapraid_fill_card_port_table( @@ -5611,12 +6290,13 @@ static u8 leapraid_fill_card_port_table( int i, idx; for (i = 0; i < adapter->dev_topo.card.phys_num; i++) { - if ((sas_iounit_p0->phy_info[i].neg_link_rate >> 4) - < LEAPRAID_SAS_NEG_LINK_RATE_1_5) + if (sas_iounit_p0->phy_info[i].neg_link_rate >> + LEAPRAID_SAS_NEG_LINK_RATE_SHIFT < + LEAPRAID_SAS_NEG_LINK_RATE_1_5) continue; - attached_hdl = - le16_to_cpu(sas_iounit_p0->phy_info[i].attached_dev_hdl); + attached_hdl = le16_to_cpu(sas_iounit_p0->phy_info[i] + .attached_dev_hdl); if (leapraid_get_sas_address(adapter, attached_hdl, &attached_sas_addr) != 0) @@ -5648,7 +6328,7 @@ static u8 leapraid_set_new_card_port_table_after_reset( { union cfg_param_1 cfgp1 = {0}; union cfg_param_2 cfgp2 = {0}; - struct leapraid_sas_io_unit_p0 *sas_iounit_p0 = NULL; + struct leapraid_sas_io_unit_p0 *sas_iounit_p0; u8 port_entry_num = 0; u16 sz; @@ -5660,14 +6340,14 @@ static u8 leapraid_set_new_card_port_table_after_reset( return port_entry_num; cfgp1.size = sz; - if ((leapraid_op_config_page(adapter, sas_iounit_p0, cfgp1, cfgp2, - GET_SAS_IOUNIT_PG0)) != 0) - goto out; + if (leapraid_op_config_page(adapter, sas_iounit_p0, cfgp1, cfgp2, + GET_SAS_IOUNIT_PG0) != 0) + goto out_free; port_entry_num = leapraid_fill_card_port_table(adapter, sas_iounit_p0, new_card_port_table); -out: +out_free: kfree(sas_iounit_p0); return port_entry_num; } @@ -5676,9 +6356,9 @@ static void leapraid_update_existing_port(struct leapraid_adapter *adapter, struct leapraid_card_port *new_table, int entry_idx, int port_entry_num) { - struct leapraid_card_port *matched_card_port = NULL; + struct leapraid_card_port *matched_card_port; int matched_code; - int count = 0, lcount = 0; + int count, lcount = 0; u64 sas_addr; int i; @@ -5699,10 +6379,10 @@ static void leapraid_update_existing_port(struct leapraid_adapter *adapter, port_entry_num); } else if (matched_code == SAME_ADDR_ONLY) { sas_addr = new_table[entry_idx].sas_address; - for (i = 0; i < port_entry_num; i++) { + for (i = 0; i < port_entry_num; i++) if (new_table[i].sas_address == sas_addr) lcount++; - } + if (count > 1 || lcount > 1) return; @@ -5724,15 +6404,24 @@ static void leapraid_update_card_port_after_reset( struct leapraid_adapter *adapter) { struct leapraid_card_port *new_card_port_table; - struct leapraid_card_port *matched_card_port = NULL; - u8 port_entry_num = 0; + struct leapraid_card_port *matched_card_port; + u8 port_entry_num; u8 nr_phys; int i; if (leapraid_get_adapter_phys(adapter, &nr_phys) || !nr_phys) return; + if (!adapter->dev_topo.card.card_phy) { + adapter->dev_topo.card.card_phy = + kcalloc(nr_phys, sizeof(struct leapraid_card_phy), + GFP_KERNEL); + if (!adapter->dev_topo.card.card_phy) + return; + } + adapter->dev_topo.card.phys_num = nr_phys; + new_card_port_table = kcalloc(adapter->dev_topo.card.phys_num, sizeof(struct leapraid_card_port), GFP_KERNEL); @@ -5740,21 +6429,23 @@ static void leapraid_update_card_port_after_reset( return; port_entry_num = - leapraid_set_new_card_port_table_after_reset(adapter, - new_card_port_table); + leapraid_set_new_card_port_table_after_reset( + adapter, + new_card_port_table); if (!port_entry_num) - return; + goto out_free_port_table; list_for_each_entry(matched_card_port, - &adapter->dev_topo.card_port_list, list) { + &adapter->dev_topo.card_port_list, list) matched_card_port->flg |= LEAPRAID_CARD_PORT_FLG_DIRTY; - } matched_card_port = NULL; for (i = 0; i < port_entry_num; i++) leapraid_update_existing_port(adapter, new_card_port_table, i, port_entry_num); +out_free_port_table: + kfree(new_card_port_table); } static bool leapraid_is_valid_vphy( @@ -5765,13 +6456,16 @@ static bool leapraid_is_valid_vphy( union cfg_param_1 cfgp1 = {0}; union cfg_param_2 cfgp2 = {0}; struct leapraid_sas_phy_p0 phy_p0; + u32 dev_info; - if ((sas_io_unit_p0->phy_info[phy_index].neg_link_rate >> 4) < + if (sas_io_unit_p0->phy_info[phy_index].neg_link_rate >> + LEAPRAID_SAS_NEG_LINK_RATE_SHIFT < LEAPRAID_SAS_NEG_LINK_RATE_1_5) return false; - if (!(le32_to_cpu(sas_io_unit_p0->phy_info[phy_index].controller_phy_dev_info) & - LEAPRAID_DEVTYP_SEP)) + dev_info = le32_to_cpu(sas_io_unit_p0->phy_info[phy_index] + .controller_phy_dev_info); + if (!(dev_info & LEAPRAID_DEVTYP_SEP)) return false; cfgp1.phy_number = phy_index; @@ -5804,7 +6498,7 @@ static void leapraid_update_vphy_binding(struct leapraid_adapter *adapter, return; may_new_card_port->port_id = may_new_port_id; dev_err(&adapter->pdev->dev, - "%s: new card port %p added, port=%d\n", + "%s: New card port %p added, port=%d\n", __func__, may_new_card_port, may_new_port_id); list_add_tail(&may_new_card_port->list, &adapter->dev_topo.card_port_list); @@ -5820,8 +6514,10 @@ static void leapraid_update_vphy_binding(struct leapraid_adapter *adapter, sas_dev = leapraid_get_sas_dev_by_addr(adapter, attached_sas_addr, card_port); - if (sas_dev) + if (sas_dev) { sas_dev->card_port = may_new_card_port; + leapraid_sdev_put(sas_dev); + } } if (may_new_card_port->flg & LEAPRAID_CARD_PORT_FLG_DIRTY) { @@ -5836,7 +6532,7 @@ static void leapraid_update_vphys_after_reset(struct leapraid_adapter *adapter) { union cfg_param_1 cfgp1 = {0}; union cfg_param_2 cfgp2 = {0}; - struct leapraid_sas_io_unit_p0 *sas_iounit_p0 = NULL; + struct leapraid_sas_io_unit_p0 *sas_iounit_p0; struct leapraid_card_port *card_port, *card_port_next; struct leapraid_vphy *vphy, *vphy_next; u64 attached_sas_addr; @@ -5852,9 +6548,8 @@ static void leapraid_update_vphys_after_reset(struct leapraid_adapter *adapter) continue; list_for_each_entry_safe(vphy, vphy_next, - &card_port->vphys_list, list) { + &card_port->vphys_list, list) vphy->flg |= LEAPRAID_VPHY_FLG_DIRTY; - } } sz = offsetof(struct leapraid_sas_io_unit_p0, phy_info) + @@ -5865,16 +6560,17 @@ static void leapraid_update_vphys_after_reset(struct leapraid_adapter *adapter) return; cfgp1.size = sz; - if ((leapraid_op_config_page(adapter, sas_iounit_p0, cfgp1, cfgp2, - GET_SAS_IOUNIT_PG0)) != 0) - goto out; + if (leapraid_op_config_page(adapter, sas_iounit_p0, cfgp1, cfgp2, + GET_SAS_IOUNIT_PG0) != 0) + goto out_free; for (i = 0; i < adapter->dev_topo.card.phys_num; i++) { if (!leapraid_is_valid_vphy(adapter, sas_iounit_p0, i)) continue; attached_hdl = - le16_to_cpu(sas_iounit_p0->phy_info[i].attached_dev_hdl); + le16_to_cpu(sas_iounit_p0->phy_info[i] + .attached_dev_hdl); if (leapraid_get_sas_address(adapter, attached_hdl, &attached_sas_addr) != 0) continue; @@ -5916,7 +6612,7 @@ static void leapraid_update_vphys_after_reset(struct leapraid_adapter *adapter) break; } } -out: +out_free: kfree(sas_iounit_p0); } @@ -5928,17 +6624,21 @@ static void leapraid_mark_all_dev_deleted(struct leapraid_adapter *adapter) shost_for_each_device(sdev, adapter->shost) { sdev_priv = sdev->hostdata; if (sdev_priv && sdev_priv->starget_priv) - sdev_priv->starget_priv->deleted = true; + sdev_priv->starget_priv->deleted = 1; } } static void leapraid_free_enc_list(struct leapraid_adapter *adapter) { struct leapraid_enc_node *enc_dev, *enc_dev_next; + LIST_HEAD(free_list); + unsigned long flags; + + spin_lock_irqsave(&adapter->dev_topo.enc_lock, flags); + list_splice_init(&adapter->dev_topo.enc_list, &free_list); + spin_unlock_irqrestore(&adapter->dev_topo.enc_lock, flags); - list_for_each_entry_safe(enc_dev, enc_dev_next, - &adapter->dev_topo.enc_list, - list) { + list_for_each_entry_safe(enc_dev, enc_dev_next, &free_list, list) { list_del(&enc_dev->list); kfree(enc_dev); } @@ -5951,14 +6651,14 @@ static void leapraid_rebuild_enc_list_after_reset( union cfg_param_2 cfgp2 = {0}; struct leapraid_enc_node *enc_node; u16 enc_hdl; + unsigned long flags; int rc; leapraid_free_enc_list(adapter); cfgp1.form = LEAPRAID_SAS_CFG_PGAD_GET_NEXT_LOOP; for (enc_hdl = 0xFFFF; ; enc_hdl = le16_to_cpu(enc_node->pg0.enc_hdl)) { - enc_node = kzalloc(sizeof(*enc_node), - GFP_KERNEL); + enc_node = kzalloc(sizeof(*enc_node), GFP_KERNEL); if (!enc_node) return; @@ -5970,91 +6670,102 @@ static void leapraid_rebuild_enc_list_after_reset( return; } + spin_lock_irqsave(&adapter->dev_topo.enc_lock, flags); list_add_tail(&enc_node->list, &adapter->dev_topo.enc_list); + spin_unlock_irqrestore(&adapter->dev_topo.enc_lock, flags); } } static void leapraid_mark_resp_sas_dev(struct leapraid_adapter *adapter, struct leapraid_sas_dev_p0 *sas_dev_p0) { - struct leapraid_starget_priv *starget_priv = NULL; + struct leapraid_starget_priv *starget_priv; struct leapraid_enc_node *enc_node = NULL; struct leapraid_card_port *card_port; struct leapraid_sas_dev *sas_dev; struct scsi_target *starget; unsigned long flags; + unsigned long enc_flags = 0; + u16 enc_hdl; + u64 enc_lid = 0; card_port = leapraid_get_port_by_id(adapter, sas_dev_p0->physical_port, false); - if (sas_dev_p0->enc_hdl) { - enc_node = leapraid_enc_find_by_hdl(adapter, - le16_to_cpu( - sas_dev_p0->enc_hdl)); + enc_hdl = le16_to_cpu(sas_dev_p0->enc_hdl); + if (enc_hdl) { + spin_lock_irqsave(&adapter->dev_topo.enc_lock, enc_flags); + enc_node = leapraid_enc_find_by_hdl(adapter, enc_hdl); + if (enc_node) + enc_lid = le64_to_cpu(enc_node->pg0.enc_lid); + spin_unlock_irqrestore(&adapter->dev_topo.enc_lock, enc_flags); if (!enc_node) dev_info(&adapter->pdev->dev, "enc hdl 0x%04x has no matched enc dev\n", - le16_to_cpu(sas_dev_p0->enc_hdl)); + enc_hdl); } spin_lock_irqsave(&adapter->dev_topo.sas_dev_lock, flags); list_for_each_entry(sas_dev, &adapter->dev_topo.sas_dev_list, list) { - if (sas_dev->sas_addr == le64_to_cpu(sas_dev_p0->sas_address) && - sas_dev->slot == le16_to_cpu(sas_dev_p0->slot) && - sas_dev->card_port == card_port) { - sas_dev->resp = true; - starget = sas_dev->starget; - if (starget && starget->hostdata) { - starget_priv = starget->hostdata; - starget_priv->tm_busy = false; - starget_priv->deleted = false; - } else { - starget_priv = NULL; - } + if (sas_dev->sas_addr != le64_to_cpu(sas_dev_p0->sas_address) || + sas_dev->slot != le16_to_cpu(sas_dev_p0->slot) || + sas_dev->card_port != card_port) + continue; - if (starget) { - starget_printk(KERN_INFO, starget, - "dev: hdl=0x%04x, sas addr=0x%016llx, port_id=%d\n", - sas_dev->hdl, - (unsigned long long)sas_dev->sas_addr, - sas_dev->card_port->port_id); - if (sas_dev->enc_hdl != 0) - starget_printk(KERN_INFO, starget, - "enc info: enc_lid=0x%016llx, slot=%d\n", - (unsigned long long)sas_dev->enc_lid, - sas_dev->slot); - } + sas_dev->resp = 1; + starget = sas_dev->starget; + if (starget && starget->hostdata) { + starget_priv = starget->hostdata; + starget_priv->tm_busy = 0; + starget_priv->deleted = 0; + } else { + starget_priv = NULL; + } - if (le16_to_cpu(sas_dev_p0->flg) & - LEAPRAID_SAS_DEV_P0_FLG_ENC_LEVEL_VALID) { - sas_dev->enc_level = sas_dev_p0->enc_level; - memcpy(sas_dev->connector_name, - sas_dev_p0->connector_name, 4); - sas_dev->connector_name[4] = '\0'; - } else { - sas_dev->enc_level = 0; - sas_dev->connector_name[0] = '\0'; - } + if (starget) { + starget_printk( + KERN_INFO, starget, + "dev: hdl=0x%04x saddr=0x%016llx port_id=%d\n", + sas_dev->hdl, + (unsigned long long)sas_dev->sas_addr, + sas_dev->card_port->port_id); + if (sas_dev->enc_hdl != 0) + starget_printk( + KERN_INFO, + starget, + "enc info: enc_lid=0x%016llx slot=%d\n", + (unsigned long long)sas_dev->enc_lid, + sas_dev->slot); + } + + if (le16_to_cpu(sas_dev_p0->flg) & + LEAPRAID_SAS_DEV_P0_FLG_ENC_LEVEL_VALID) { + sas_dev->enc_level = sas_dev_p0->enc_level; + memcpy(sas_dev->connector_name, + sas_dev_p0->connector_name, + LEAPRAID_SAS_DEV_P0_CON_NAME_LEN); + sas_dev->connector_name[ + LEAPRAID_SAS_DEV_P0_CON_NAME_LEN] = '\0'; + } else { + sas_dev->enc_level = 0; + sas_dev->connector_name[0] = '\0'; + } + + sas_dev->enc_hdl = enc_hdl; + sas_dev->enc_lid = enc_lid; - sas_dev->enc_hdl = - le16_to_cpu(sas_dev_p0->enc_hdl); - if (enc_node) { - sas_dev->enc_lid = - le64_to_cpu(enc_node->pg0.enc_lid); - } - if (sas_dev->hdl == le16_to_cpu(sas_dev_p0->dev_hdl)) - goto out; + if (sas_dev->hdl == le16_to_cpu(sas_dev_p0->dev_hdl)) + goto unlock; - dev_info(&adapter->pdev->dev, - "hdl changed: 0x%04x -> 0x%04x\n", - sas_dev->hdl, sas_dev_p0->dev_hdl); - sas_dev->hdl = le16_to_cpu(sas_dev_p0->dev_hdl); - if (starget_priv) - starget_priv->hdl = - le16_to_cpu(sas_dev_p0->dev_hdl); - goto out; - } + dev_info(&adapter->pdev->dev, + "hdl changed: 0x%04x -> 0x%04x\n", + sas_dev->hdl, sas_dev_p0->dev_hdl); + sas_dev->hdl = le16_to_cpu(sas_dev_p0->dev_hdl); + if (starget_priv) + starget_priv->hdl = le16_to_cpu(sas_dev_p0->dev_hdl); + + goto unlock; } -out: +unlock: spin_unlock_irqrestore(&adapter->dev_topo.sas_dev_lock, flags); } @@ -6066,10 +6777,10 @@ static void leapraid_search_resp_sas_dev(struct leapraid_adapter *adapter) u32 device_info; dev_info(&adapter->pdev->dev, - "begin searching for sas end devices\n"); + "Begin searching for SAS end devices\n"); if (list_empty(&adapter->dev_topo.sas_dev_list)) - goto out; + goto exit_search; cfgp1.form = LEAPRAID_SAS_CFG_PGAD_GET_NEXT_LOOP; for (cfgp2.handle = 0xFFFF; @@ -6082,63 +6793,58 @@ static void leapraid_search_resp_sas_dev(struct leapraid_adapter *adapter) leapraid_mark_resp_sas_dev(adapter, &sas_dev_p0); } -out: +exit_search: dev_info(&adapter->pdev->dev, - "sas end devices searching complete\n"); + "SAS end devices searching complete\n"); } static void leapraid_mark_resp_raid_volume(struct leapraid_adapter *adapter, u64 wwid, u16 hdl) { - struct leapraid_starget_priv *starget_priv; struct leapraid_raid_volume *raid_volume; + struct leapraid_starget_priv *starget_priv = NULL; struct scsi_target *starget; unsigned long flags; + u64 volume_wwid; + u16 old_hdl; - spin_lock_irqsave(&adapter->dev_topo.raid_volume_lock, flags); - list_for_each_entry(raid_volume, - &adapter->dev_topo.raid_volume_list, list) { - if (raid_volume->wwid == wwid && raid_volume->starget) { - starget = raid_volume->starget; - if (starget && starget->hostdata) { - starget_priv = starget->hostdata; - starget_priv->deleted = false; - } else { - starget_priv = NULL; - } - - raid_volume->resp = true; - spin_unlock_irqrestore( - &adapter->dev_topo.raid_volume_lock, - flags); + raid_volume = leapraid_raid_volume_find_by_wwid(adapter, wwid); + if (!raid_volume) + return; - starget_printk( - KERN_INFO, raid_volume->starget, - "raid volume: hdl=0x%04x, wwid=0x%016llx\n", - hdl, (unsigned long long)raid_volume->wwid); - spin_lock_irqsave(&adapter->dev_topo.raid_volume_lock, - flags); - if (raid_volume->hdl == hdl) { - spin_unlock_irqrestore( - &adapter->dev_topo.raid_volume_lock, - flags); - return; - } + spin_lock_irqsave(&adapter->dev_topo.raid_volume_lock, flags); + if (!raid_volume->starget) { + spin_unlock_irqrestore(&adapter->dev_topo.raid_volume_lock, + flags); + leapraid_raid_volume_put(raid_volume); + return; + } - dev_info(&adapter->pdev->dev, - "hdl changed: 0x%04x -> 0x%04x\n", - raid_volume->hdl, hdl); + starget = raid_volume->starget; + if (starget->hostdata) { + starget_priv = starget->hostdata; + starget_priv->deleted = 0; + } - raid_volume->hdl = hdl; - if (starget_priv) - starget_priv->hdl = hdl; - spin_unlock_irqrestore( - &adapter->dev_topo.raid_volume_lock, - flags); - return; - } + raid_volume->resp = 1; + volume_wwid = raid_volume->wwid; + old_hdl = raid_volume->hdl; + if (old_hdl != hdl) { + raid_volume->hdl = hdl; + if (starget_priv) + starget_priv->hdl = hdl; } spin_unlock_irqrestore(&adapter->dev_topo.raid_volume_lock, flags); + + starget_printk(KERN_INFO, starget, + "raid volume: hdl=0x%04x, wwid=0x%016llx\n", + hdl, (unsigned long long)volume_wwid); + if (old_hdl != hdl) + dev_info(&adapter->pdev->dev, + "hdl changed: 0x%04x -> 0x%04x\n", + old_hdl, hdl); + + leapraid_raid_volume_put(raid_volume); } static void leapraid_search_resp_raid_volume(struct leapraid_adapter *adapter) @@ -6150,17 +6856,22 @@ static void leapraid_search_resp_raid_volume(struct leapraid_adapter *adapter) struct leapraid_raidvol_p1 raidvol_p1; struct leapraid_raidvol_p0 raidvol_p0; struct leapraid_raidpd_p0 raidpd_p0; + unsigned long flags; u16 hdl; u8 phys_disk_num; + bool is_empty; if (!adapter->adapter_attr.raid_support) return; dev_info(&adapter->pdev->dev, - "begin searching for raid volumes\n"); + "Begin searching for RAID volumes\n"); - if (list_empty(&adapter->dev_topo.raid_volume_list)) - goto out; + spin_lock_irqsave(&adapter->dev_topo.raid_volume_lock, flags); + is_empty = list_empty(&adapter->dev_topo.raid_volume_list); + spin_unlock_irqrestore(&adapter->dev_topo.raid_volume_lock, flags); + if (is_empty) + goto exit_search; cfgp1.form = LEAPRAID_SAS_CFG_PGAD_GET_NEXT_LOOP; for (hdl = 0xFFFF, cfgp2.handle = hdl; @@ -6191,11 +6902,16 @@ static void leapraid_search_resp_raid_volume(struct leapraid_adapter *adapter) cfgp2.form_specific = phys_disk_num) { phys_disk_num = raidpd_p0.phys_disk_num; hdl = le16_to_cpu(raidpd_p0.dev_hdl); - set_bit(hdl, (unsigned long *)adapter->dev_topo.pd_hdls); + if (!hdl || + hdl > adapter->adapter_attr.features.max_dev_handle) + dev_warn(&adapter->pdev->dev, + "%s: Invalid device handle\n", __func__); + else + set_bit(hdl, adapter->dev_topo.pd_hdls); } -out: +exit_search: dev_info(&adapter->pdev->dev, - "raid volumes searching complete\n"); + "RAID volumes searching complete\n"); } static void leapraid_mark_resp_exp(struct leapraid_adapter *adapter, @@ -6211,10 +6927,17 @@ static void leapraid_mark_resp_exp(struct leapraid_adapter *adapter, port_id, false); unsigned long flags; + unsigned long enc_flags = 0; + u64 enc_lid = 0; int i; - if (enc_hdl) + if (enc_hdl) { + spin_lock_irqsave(&adapter->dev_topo.enc_lock, enc_flags); enc_node = leapraid_enc_find_by_hdl(adapter, enc_hdl); + if (enc_node) + enc_lid = le64_to_cpu(enc_node->pg0.enc_lid); + spin_unlock_irqrestore(&adapter->dev_topo.enc_lock, enc_flags); + } spin_lock_irqsave(&adapter->dev_topo.topo_node_lock, flags); list_for_each_entry(topo_node_exp, &adapter->dev_topo.exp_list, list) { @@ -6222,14 +6945,11 @@ static void leapraid_mark_resp_exp(struct leapraid_adapter *adapter, topo_node_exp->card_port != card_port) continue; - topo_node_exp->resp = true; - if (enc_node) { - topo_node_exp->enc_lid = - le64_to_cpu(enc_node->pg0.enc_lid); - topo_node_exp->enc_hdl = le16_to_cpu(exp_pg0->enc_hdl); - } + topo_node_exp->resp = 1; + topo_node_exp->enc_hdl = enc_hdl; + topo_node_exp->enc_lid = enc_lid; if (topo_node_exp->hdl == hdl) - goto out; + goto unlock; dev_info(&adapter->pdev->dev, "hdl changed: 0x%04x -> 0x%04x\n", @@ -6237,9 +6957,9 @@ static void leapraid_mark_resp_exp(struct leapraid_adapter *adapter, topo_node_exp->hdl = hdl; for (i = 0; i < topo_node_exp->phys_num; i++) topo_node_exp->card_phy[i].hdl = hdl; - goto out; + goto unlock; } -out: +unlock: spin_unlock_irqrestore(&adapter->dev_topo.topo_node_lock, flags); } @@ -6252,10 +6972,10 @@ static void leapraid_search_resp_exp(struct leapraid_adapter *adapter) u16 hdl; u8 port; - dev_info(&adapter->pdev->dev, - "begin searching for expanders\n"); + dev_dbg(&adapter->pdev->dev, + "Begin searching for expanders\n"); if (list_empty(&adapter->dev_topo.exp_list)) - goto out; + goto exit_search; cfgp1.form = LEAPRAID_SAS_CFG_PGAD_GET_NEXT_LOOP; for (hdl = 0xFFFF, cfgp2.handle = hdl; @@ -6266,16 +6986,16 @@ static void leapraid_search_resp_exp(struct leapraid_adapter *adapter) sas_address = le64_to_cpu(exp_p0.sas_address); port = exp_p0.physical_port; - dev_info(&adapter->pdev->dev, - "exp detected: hdl=0x%04x, sas=0x%016llx, port=%u", - hdl, (unsigned long long)sas_address, - ((adapter->adapter_attr.enable_mp) ? (port) : - (LEAPRAID_DISABLE_MP_PORT_ID))); + dev_dbg(&adapter->pdev->dev, + "exp detected: hdl=0x%04x, sas=0x%016llx, port=%u", + hdl, (unsigned long long)sas_address, + adapter->adapter_attr.enable_mp ? port : + LEAPRAID_DISABLE_MP_PORT_ID); leapraid_mark_resp_exp(adapter, &exp_p0); } -out: - dev_info(&adapter->pdev->dev, - "expander searching complete\n"); +exit_search: + dev_dbg(&adapter->pdev->dev, + "Expander searching complete\n"); } void leapraid_wait_cmds_done(struct leapraid_adapter *adapter) @@ -6287,7 +7007,7 @@ void leapraid_wait_cmds_done(struct leapraid_adapter *adapter) adapter->reset_desc.pending_io_cnt = 0; if (!leapraid_pci_active(adapter)) { dev_err(&adapter->pdev->dev, - "%s %s: pci error, device reset or unplugged!\n", + "%s %s: PCI error, device reset or unplugged!\n", adapter->adapter_attr.name, __func__); return; } @@ -6299,9 +7019,9 @@ void leapraid_wait_cmds_done(struct leapraid_adapter *adapter) for (i = 1; i <= adapter->shost->can_queue; i++) { io_req_tracker = leapraid_get_io_tracker_from_taskid(adapter, i); - if (io_req_tracker && io_req_tracker->taskid != 0) - if (io_req_tracker->scmd) - adapter->reset_desc.pending_io_cnt++; + if (io_req_tracker && io_req_tracker->taskid != 0 && + io_req_tracker->scmd) + adapter->reset_desc.pending_io_cnt++; } spin_unlock_irqrestore(&adapter->dynamic_task_desc.task_lock, flags); @@ -6309,38 +7029,37 @@ void leapraid_wait_cmds_done(struct leapraid_adapter *adapter) return; wait_event_timeout(adapter->reset_desc.reset_wait_queue, - adapter->reset_desc.pending_io_cnt == 0, 10 * HZ); + adapter->reset_desc.pending_io_cnt == 0, + LEAPRAID_IO_CMD_TIMEOUT * HZ); } int leapraid_hard_reset_handler(struct leapraid_adapter *adapter, enum reset_type type) { unsigned long flags; + bool wake = false; int rc; - if (!mutex_trylock(&adapter->reset_desc.adapter_reset_mutex)) { - do { - ssleep(1); - } while (adapter->access_ctrl.shost_recovering); - return adapter->reset_desc.adapter_reset_results; - } + mutex_lock(&adapter->reset_desc.adapter_reset_mutex); if (!leapraid_pci_active(adapter)) { if (leapraid_pci_removed(adapter)) { dev_info(&adapter->pdev->dev, - "pci_dev removed, pausing polling and cleaning cmds\n"); + "pci_dev removed, pause poll, clean cmds\n"); leapraid_mq_polling_pause(adapter); leapraid_clean_active_scsi_cmds(adapter); leapraid_mq_polling_resume(adapter); } - rc = 0; - goto exit_pci_unavailable; + dev_err(&adapter->pdev->dev, "PCIe unavailable!\n"); + mutex_unlock(&adapter->reset_desc.adapter_reset_mutex); + return -ENXIO; } - dev_info(&adapter->pdev->dev, "starting hard reset\n"); + dev_info(&adapter->pdev->dev, "Starting hard reset\n"); spin_lock_irqsave(&adapter->reset_desc.adapter_reset_lock, flags); - adapter->access_ctrl.shost_recovering = true; + adapter->access_ctrl.shost_recovering = 1; + adapter->access_ctrl.shost_recover_async = 1; spin_unlock_irqrestore(&adapter->reset_desc.adapter_reset_lock, flags); leapraid_wait_cmds_done(adapter); @@ -6349,14 +7068,14 @@ int leapraid_hard_reset_handler(struct leapraid_adapter *adapter, rc = leapraid_make_adapter_ready(adapter, type); if (rc) { dev_err(&adapter->pdev->dev, - "failed to make adapter ready, rc=%d\n", rc); - goto out; + "Failed to make adapter ready, rc=%d\n", rc); + goto out_cleanup; } rc = leapraid_fw_log_init(adapter); if (rc) { - dev_err(&adapter->pdev->dev, "firmware log init failed\n"); - goto out; + dev_err(&adapter->pdev->dev, "Firmware log init failed\n"); + goto out_cleanup; } leapraid_clean_active_cmds(adapter); @@ -6364,15 +7083,16 @@ int leapraid_hard_reset_handler(struct leapraid_adapter *adapter, adapter->scan_dev_desc.scan_dev_failed) { dev_err(&adapter->pdev->dev, "Previous device scan failed or driver loading\n"); - adapter->access_ctrl.host_removing = true; + adapter->access_ctrl.host_removing = 1; + wake_up(&adapter->access_ctrl.recovery_waitq); rc = -EFAULT; - goto out; + goto out_cleanup; } rc = leapraid_make_adapter_available(adapter); if (!rc) { dev_info(&adapter->pdev->dev, - "adapter is now available, rebuilding topology\n"); + "Adapter is now available, rebuilding topology\n"); if (adapter->adapter_attr.enable_mp) { leapraid_update_card_port_after_reset(adapter); leapraid_update_vphys_after_reset(adapter); @@ -6384,14 +7104,22 @@ int leapraid_hard_reset_handler(struct leapraid_adapter *adapter, leapraid_search_resp_exp(adapter); leapraid_hardreset_barrier(adapter); } -out: - dev_info(&adapter->pdev->dev, "hard reset %s\n", - ((rc == 0) ? "SUCCESS" : "FAILED")); +out_cleanup: + dev_info(&adapter->pdev->dev, "Hard reset %s\n", + rc == 0 ? "SUCCESS" : "FAILED"); spin_lock_irqsave(&adapter->reset_desc.adapter_reset_lock, flags); adapter->reset_desc.adapter_reset_results = rc; - adapter->access_ctrl.shost_recovering = false; + adapter->access_ctrl.shost_recovering = 0; + wake_up(&adapter->access_ctrl.recovery_waitq); + if (rc) { + adapter->access_ctrl.shost_recover_async = 0; + wake = true; + } spin_unlock_irqrestore(&adapter->reset_desc.adapter_reset_lock, flags); + if (wake) + wake_up(&adapter->access_ctrl.shost_recover_wq); + adapter->reset_desc.reset_cnt++; mutex_unlock(&adapter->reset_desc.adapter_reset_mutex); @@ -6399,8 +7127,6 @@ int leapraid_hard_reset_handler(struct leapraid_adapter *adapter, leapraid_clean_active_scsi_cmds(adapter); leapraid_mq_polling_resume(adapter); -exit_pci_unavailable: - dev_info(&adapter->pdev->dev, "pcie unavailable!\n"); return rc; } @@ -6409,31 +7135,40 @@ static int leapraid_get_adapter_features(struct leapraid_adapter *adapter) struct leapraid_adapter_features_req leap_mpi_req; struct leapraid_adapter_features_rep leap_mpi_rep; u8 fw_major, fw_minor, fw_build, fw_release; + u32 req_sz; + u32 rep_sz; u32 db; int r; db = leapraid_readl(&adapter->iomem_base->db); if (db & LEAPRAID_DB_USED || - (db & LEAPRAID_DB_MASK) == LEAPRAID_DB_FAULT) + (db & LEAPRAID_DB_MASK) == LEAPRAID_DB_FAULT) { + dev_err(&adapter->pdev->dev, + "%s: Doorbell used or fault\n", __func__); return -EFAULT; + } - if (((db & LEAPRAID_DB_MASK) != LEAPRAID_DB_READY) && - ((db & LEAPRAID_DB_MASK) != LEAPRAID_DB_OPERATIONAL)) { - if (!leapraid_wait_adapter_ready(adapter)) - return -EFAULT; + if ((db & LEAPRAID_DB_MASK) != LEAPRAID_DB_READY && + (db & LEAPRAID_DB_MASK) != LEAPRAID_DB_OPERATIONAL && + !leapraid_wait_adapter_ready(adapter)) { + dev_err(&adapter->pdev->dev, + "%s: adapter not ready\n", __func__); + return -EFAULT; } - memset(&leap_mpi_req, 0, sizeof(struct leapraid_adapter_features_req)); - memset(&leap_mpi_rep, 0, sizeof(struct leapraid_adapter_features_rep)); + req_sz = sizeof(struct leapraid_adapter_features_req); + rep_sz = sizeof(struct leapraid_adapter_features_rep); + memset(&leap_mpi_req, 0, req_sz); + memset(&leap_mpi_rep, 0, rep_sz); leap_mpi_req.func = LEAPRAID_FUNC_GET_ADAPTER_FEATURES; r = leapraid_handshake_func(adapter, - sizeof(struct leapraid_adapter_features_req), + req_sz, (u32 *)&leap_mpi_req, - sizeof(struct leapraid_adapter_features_rep), + rep_sz, (u16 *)&leap_mpi_rep); if (r) { dev_err(&adapter->pdev->dev, - "%s %s: handshake failed, r=%d\n", + "%s %s: Handshake failed, r=%d\n", adapter->adapter_attr.name, __func__, r); return r; } @@ -6460,19 +7195,43 @@ static int leapraid_get_adapter_features(struct leapraid_adapter *adapter) LEAPRAID_MAX_DEV_HANDLE_DEFAULT; adapter->adapter_attr.features.min_dev_handle = le16_to_cpu(leap_mpi_rep.min_dev_hdl); - if ((adapter->adapter_attr.features.adapter_caps & - LEAPRAID_ADAPTER_FEATURES_CAP_INTEGRATED_RAID)) - adapter->adapter_attr.raid_support = true; + if (adapter->adapter_attr.features.adapter_caps & + LEAPRAID_ADAPTER_FEATURES_CAP_INTEGRATED_RAID) + adapter->adapter_attr.raid_support = 1; + adapter->adapter_attr.wideport_max_queue_depth = + le16_to_cpu(leap_mpi_rep.sas_wide_max_qdepth) ? + le16_to_cpu(leap_mpi_rep.sas_wide_max_qdepth) : + LEAPRAID_SAS_QUEUE_DEPTH; + adapter->adapter_attr.narrowport_max_queue_depth = + le16_to_cpu(leap_mpi_rep.sas_narrow_max_qdepth) ? + le16_to_cpu(leap_mpi_rep.sas_narrow_max_qdepth) : + LEAPRAID_SAS_QUEUE_DEPTH; + adapter->adapter_attr.sata_max_queue_depth = + leap_mpi_rep.sata_max_qdepth ? + leap_mpi_rep.sata_max_qdepth : + LEAPRAID_SATA_QUEUE_DEPTH; + adapter->adapter_attr.raid_volume_max_queue_depth = + LEAPRAID_RAID_QUEUE_DEPTH; + dev_info(&adapter->pdev->dev, + "max: wp qd=%d, np qd=%d, SATA qd=%d, raid qd=%d\n", + adapter->adapter_attr.wideport_max_queue_depth, + adapter->adapter_attr.narrowport_max_queue_depth, + adapter->adapter_attr.sata_max_queue_depth, + adapter->adapter_attr.raid_volume_max_queue_depth); if (WARN_ON(!(adapter->adapter_attr.features.adapter_caps & LEAPRAID_ADAPTER_FEATURES_CAP_ATOMIC_REQ))) return -EFAULT; adapter->adapter_attr.features.fw_version = le32_to_cpu(leap_mpi_rep.fw_version); - fw_major = (adapter->adapter_attr.features.fw_version >> 24) & 0xFF; - fw_minor = (adapter->adapter_attr.features.fw_version >> 16) & 0xFF; - fw_build = (adapter->adapter_attr.features.fw_version >> 8) & 0xFF; - fw_release = adapter->adapter_attr.features.fw_version & 0xFF; + fw_major = (adapter->adapter_attr.features.fw_version >> + LEAPRAID_VER_MAJOR_SHIFT) & LEAPRAID_VER_MASK; + fw_minor = (adapter->adapter_attr.features.fw_version >> + LEAPRAID_VER_MINOR_SHIFT) & LEAPRAID_VER_MASK; + fw_build = (adapter->adapter_attr.features.fw_version >> + LEAPRAID_VER_BUILD_SHIFT) & LEAPRAID_VER_MASK; + fw_release = + adapter->adapter_attr.features.fw_version & LEAPRAID_VER_MASK; dev_info(&adapter->pdev->dev, "Firmware version: %u.%u.%u.%u (0x%08x)\n", @@ -6484,7 +7243,7 @@ static int leapraid_get_adapter_features(struct leapraid_adapter *adapter) "Unsupported firmware major version, requires >= 2\n"); return -EFAULT; } - adapter->shost->max_id = -1; + adapter->shost->max_id = LEAPRAID_INVALID_INITIAL_VALUE; return 0; } @@ -6511,54 +7270,50 @@ static int leapraid_enable_pcie(struct leapraid_adapter *adapter) rc = pci_enable_device(adapter->pdev); if (rc) { - dev_err(&adapter->pdev->dev, "failed to enable PCI device\n"); + dev_err(&adapter->pdev->dev, "Failed to enable PCI device\n"); return rc; } rc = pci_request_regions(adapter->pdev, LEAPRAID_DRIVER_NAME); if (rc) { dev_err(&adapter->pdev->dev, - "failed to obtain PCI resources\n"); - goto disable_pcie; + "Failed to obtain PCI resources\n"); + return rc; } if (sizeof(dma_addr_t) > 4) { - dma_mask = DMA_BIT_MASK(64); - adapter->adapter_attr.use_32_dma_mask = false; + dma_mask = DMA_BIT_MASK(DMA_64_BITS); + adapter->adapter_attr.use_32_dma_mask = 0; } else { - dma_mask = DMA_BIT_MASK(32); - adapter->adapter_attr.use_32_dma_mask = true; + dma_mask = DMA_BIT_MASK(DMA_32_BITS); + adapter->adapter_attr.use_32_dma_mask = 1; } rc = dma_set_mask_and_coherent(&adapter->pdev->dev, dma_mask); if (rc) { dev_err(&adapter->pdev->dev, - "failed to set %lld DMA mask\n", dma_mask); - goto disable_pcie; + "Failed to set %lld DMA mask\n", dma_mask); + return rc; } adapter->iomem_base = ioremap(pci_resource_start(adapter->pdev, 0), sizeof(struct leapraid_reg_base)); if (!adapter->iomem_base) { dev_err(&adapter->pdev->dev, - "failed to map memory for controller registers\n"); - rc = -ENOMEM; - goto disable_pcie; + "Failed to map memory for controller registers\n"); + return -ENOMEM; } pci_enable_pcie_error_reporting(adapter->pdev); pci_set_master(adapter->pdev); return 0; - -disable_pcie: - return rc; } static void leapraid_cpus_on_irq(struct leapraid_adapter *adapter) { struct leapraid_int_rq *int_rq; unsigned int i, base_group, this_group; - unsigned int cpu, nr_cpus, total_msix, index = 0; + unsigned int cpu, nr_cpus, total_msix, index; total_msix = adapter->notification_desc.iopoll_qdex; nr_cpus = num_online_cpus(); @@ -6600,8 +7355,12 @@ static void leapraid_map_msix_to_cpu(struct leapraid_adapter *adapter) int_rq = &adapter->notification_desc.int_rqs[i]; affinity_mask = pci_irq_get_affinity(adapter->pdev, int_rq->rq.msix_idx); - if (!affinity_mask) - goto out; + if (!affinity_mask) { + dev_warn(&adapter->pdev->dev, + "%s: IRQ affinity NULL, msix_idx=%d\n", + __func__, int_rq->rq.msix_idx); + goto out_apply_irq_affinity; + } for_each_cpu_and(cpu, affinity_mask, cpu_online_mask) { if (cpu >= adapter->notification_desc.msix_cpu_map_sz) @@ -6611,7 +7370,7 @@ static void leapraid_map_msix_to_cpu(struct leapraid_adapter *adapter) int_rq->rq.msix_idx; } } -out: +out_apply_irq_affinity: leapraid_cpus_on_irq(adapter); } @@ -6628,27 +7387,26 @@ static void leapraid_free_irq(struct leapraid_adapter *adapter) { struct leapraid_int_rq *int_rq; unsigned int i; + int irq; - if (!adapter->notification_desc.int_rqs) - return; - - for (i = 0; i < adapter->notification_desc.int_rqs_allocated; i++) { + for (i = 0; adapter->notification_desc.int_rqs && + i < adapter->notification_desc.int_rqs_allocated; i++) { int_rq = &adapter->notification_desc.int_rqs[i]; if (!int_rq) continue; - irq_set_affinity_hint(pci_irq_vector(adapter->pdev, - int_rq->rq.msix_idx), NULL); - free_irq(pci_irq_vector(adapter->pdev, int_rq->rq.msix_idx), - &int_rq->rq); + irq = pci_irq_vector(adapter->pdev, int_rq->rq.msix_idx); + irq_set_affinity_hint(irq, NULL); + free_irq(irq, &int_rq->rq); } adapter->notification_desc.int_rqs_allocated = 0; - if (!adapter->notification_desc.msix_enable) - return; + if (adapter->notification_desc.irq_vectors_allocated) { + pci_free_irq_vectors(adapter->pdev); + adapter->notification_desc.irq_vectors_allocated = 0; + } - pci_free_irq_vectors(adapter->pdev); - adapter->notification_desc.msix_enable = false; + adapter->notification_desc.msix_enable = 0; kfree(adapter->notification_desc.blk_mq_poll_rqs); adapter->notification_desc.blk_mq_poll_rqs = NULL; @@ -6658,16 +7416,9 @@ static void leapraid_free_irq(struct leapraid_adapter *adapter) kfree(adapter->notification_desc.msix_cpu_map); adapter->notification_desc.msix_cpu_map = NULL; -} - -static inline int leapraid_msix_cnt(struct pci_dev *pdev) -{ - return pci_msix_vec_count(pdev); -} - -static inline int leapraid_msi_cnt(struct pci_dev *pdev) -{ - return pci_msi_vec_count(pdev); + adapter->notification_desc.msix_cpu_map_sz = 0; + adapter->notification_desc.iopoll_qdex = 0; + adapter->notification_desc.iopoll_qcnt = 0; } static int leapraid_setup_irqs(struct leapraid_adapter *adapter) @@ -6675,7 +7426,7 @@ static int leapraid_setup_irqs(struct leapraid_adapter *adapter) unsigned int i; int rc = 0; - if (interrupt_mode == 0) { + if (interrupt_mode == LEAPRAID_INTERRUPT_MODE_MSIX) { rc = pci_alloc_irq_vectors_affinity( adapter->pdev, adapter->notification_desc.iopoll_qdex, @@ -6684,22 +7435,26 @@ static int leapraid_setup_irqs(struct leapraid_adapter *adapter) if (rc < 0) { dev_err(&adapter->pdev->dev, - "%d msi/msix vectors alloacted failed!\n", + "%d MSI/MSIX vectors allocated failed!\n", adapter->notification_desc.iopoll_qdex); return rc; } + + adapter->notification_desc.irq_vectors_allocated = 1; + adapter->notification_desc.irq_mode = + LEAPRAID_INTERRUPT_MODE_MSIX; } for (i = 0; i < adapter->notification_desc.iopoll_qdex; i++) { adapter->notification_desc.int_rqs[i].rq.adapter = adapter; adapter->notification_desc.int_rqs[i].rq.msix_idx = i; atomic_set(&adapter->notification_desc.int_rqs[i].rq.busy, 0); - if (interrupt_mode == 0) + if (interrupt_mode == LEAPRAID_INTERRUPT_MODE_MSIX) snprintf(adapter->notification_desc.int_rqs[i].rq.name, LEAPRAID_NAME_LENGTH, "%s%u-MSIx%u", LEAPRAID_DRIVER_NAME, adapter->adapter_attr.id, i); - else if (interrupt_mode == 1) + else if (interrupt_mode == LEAPRAID_INTERRUPT_MODE_MSI) snprintf(adapter->notification_desc.int_rqs[i].rq.name, LEAPRAID_NAME_LENGTH, "%s%u-MSI%u", LEAPRAID_DRIVER_NAME, @@ -6710,6 +7465,7 @@ static int leapraid_setup_irqs(struct leapraid_adapter *adapter) IRQF_SHARED, adapter->notification_desc.int_rqs[i].rq.name, &adapter->notification_desc.int_rqs[i].rq); + if (rc) { dev_err(&adapter->pdev->dev, "MSI/MSIx: request_irq %s failed!\n", @@ -6741,10 +7497,12 @@ static int leapraid_setup_legacy_int(struct leapraid_adapter *adapter) NULL); if (rc < 0) { dev_err(&adapter->pdev->dev, - "legacy irq alloacted failed!\n"); + "Legacy irq allocated failed!\n"); return rc; } + adapter->notification_desc.irq_vectors_allocated = 1; + adapter->notification_desc.irq_mode = LEAPRAID_INTERRUPT_MODE_LEGACY; rc = request_irq(pci_irq_vector(adapter->pdev, 0), leapraid_irq_handler, IRQF_SHARED, @@ -6753,8 +7511,9 @@ static int leapraid_setup_legacy_int(struct leapraid_adapter *adapter) if (rc) { irq_set_affinity_hint(pci_irq_vector(adapter->pdev, 0), NULL); pci_free_irq_vectors(adapter->pdev); + adapter->notification_desc.irq_vectors_allocated = 0; dev_err(&adapter->pdev->dev, - "Legact Int: request_irq %s failed!\n", + "Legacy Int: request_irq %s failed!\n", adapter->notification_desc.int_rqs[0].rq.name); return -EBUSY; } @@ -6768,8 +7527,8 @@ static int leapraid_set_legacy_int(struct leapraid_adapter *adapter) adapter->notification_desc.msix_cpu_map_sz = num_online_cpus(); adapter->notification_desc.msix_cpu_map = - kzalloc(adapter->notification_desc.msix_cpu_map_sz, - GFP_KERNEL); + kzalloc(adapter->notification_desc.msix_cpu_map_sz, + GFP_KERNEL); if (!adapter->notification_desc.msix_cpu_map) return -ENOMEM; @@ -6778,19 +7537,15 @@ static int leapraid_set_legacy_int(struct leapraid_adapter *adapter) adapter->adapter_attr.rq_cnt; adapter->notification_desc.iopoll_qcnt = 0; dev_info(&adapter->pdev->dev, - "Legacy Intr: req queue cnt=%d, intr=%d/poll=%d rep queues!\n", + "Legacy Intr: req queue cnt=%d intr=%d/poll=%d rep queues!\n", adapter->adapter_attr.rq_cnt, adapter->notification_desc.iopoll_qdex, adapter->notification_desc.iopoll_qcnt); adapter->notification_desc.int_rqs = kcalloc(adapter->notification_desc.iopoll_qdex, sizeof(struct leapraid_int_rq), GFP_KERNEL); - if (!adapter->notification_desc.int_rqs) { - dev_err(&adapter->pdev->dev, - "Legacy Intr: allocate %d intr rep queues failed!\n", - adapter->notification_desc.iopoll_qdex); + if (!adapter->notification_desc.int_rqs) return -ENOMEM; - } rc = leapraid_setup_legacy_int(adapter); @@ -6804,13 +7559,13 @@ static int leapraid_set_msix(struct leapraid_adapter *adapter) int rc, msix_cnt; if (msix_disable == 1) - goto legacy_int; + goto apply_legacy_int; - msix_cnt = leapraid_msix_cnt(adapter->pdev); + msix_cnt = pci_msix_vec_count(adapter->pdev); if (msix_cnt <= 0 || adapter->adapter_attr.features.max_msix_vectors == 0) { - dev_info(&adapter->pdev->dev, "msix unsupported!\n"); - goto legacy_int; + dev_info(&adapter->pdev->dev, "MSIX unsupported!\n"); + goto apply_legacy_int; } msix_cnt = min_t(int, msix_cnt, @@ -6852,25 +7607,25 @@ static int leapraid_set_msix(struct leapraid_adapter *adapter) adapter->notification_desc.int_rqs = kcalloc(adapter->notification_desc.iopoll_qdex, sizeof(struct leapraid_int_rq), GFP_KERNEL); - if (!adapter->notification_desc.int_rqs) { - dev_err(&adapter->pdev->dev, - "MSIx: allocate %d interrupt reply queues failed!\n", - adapter->notification_desc.iopoll_qdex); + if (!adapter->notification_desc.int_rqs) return -ENOMEM; - } for (i = 0; i < adapter->notification_desc.iopoll_qcnt; i++) { adapter->notification_desc.blk_mq_poll_rqs[i].rq.adapter = adapter; adapter->notification_desc.blk_mq_poll_rqs[i].rq.msix_idx = i + adapter->notification_desc.iopoll_qdex; - atomic_set(&adapter->notification_desc.blk_mq_poll_rqs[i].rq.busy, 0); + atomic_set( + &adapter->notification_desc.blk_mq_poll_rqs[i].rq.busy, + 0); snprintf(adapter->notification_desc.blk_mq_poll_rqs[i].rq.name, LEAPRAID_NAME_LENGTH, "%s%u-MQ-Poll%u", LEAPRAID_DRIVER_NAME, adapter->adapter_attr.id, i); - atomic_set(&adapter->notification_desc.blk_mq_poll_rqs[i].busy, 0); - atomic_set(&adapter->notification_desc.blk_mq_poll_rqs[i].pause, 0); + atomic_set(&adapter->notification_desc.blk_mq_poll_rqs[i].busy, + 0); + atomic_set(&adapter->notification_desc.blk_mq_poll_rqs[i].pause, + 0); } adapter->notification_desc.msix_cpu_map_sz = @@ -6880,20 +7635,21 @@ static int leapraid_set_msix(struct leapraid_adapter *adapter) GFP_KERNEL); if (!adapter->notification_desc.msix_cpu_map) return -ENOMEM; + memset(adapter->notification_desc.msix_cpu_map, 0, adapter->notification_desc.msix_cpu_map_sz); - adapter->notification_desc.msix_enable = true; + adapter->notification_desc.msix_enable = 1; rc = leapraid_setup_irqs(adapter); if (rc) { leapraid_free_irq(adapter); - adapter->notification_desc.msix_enable = false; - goto legacy_int; + adapter->notification_desc.msix_enable = 0; + goto apply_legacy_int; } return 0; -legacy_int: +apply_legacy_int: rc = leapraid_set_legacy_int(adapter); return rc; @@ -6906,13 +7662,13 @@ static int leapraid_set_msi(struct leapraid_adapter *adapter) int rc, msi_cnt; if (msix_disable == 1) - goto legacy_int1; + goto apply_legacy_int; - msi_cnt = leapraid_msi_cnt(adapter->pdev); + msi_cnt = pci_msi_vec_count(adapter->pdev); if (msi_cnt <= 0 || adapter->adapter_attr.features.max_msix_vectors == 0) { - dev_info(&adapter->pdev->dev, "msi unsupported!\n"); - goto legacy_int1; + dev_info(&adapter->pdev->dev, "MSI unsupported!\n"); + goto apply_legacy_int; } msi_cnt = min_t(int, msi_cnt, @@ -6952,10 +7708,13 @@ static int leapraid_set_msi(struct leapraid_adapter *adapter) PCI_IRQ_MSI | PCI_IRQ_AFFINITY, NULL); if (rc < 0) { dev_err(&adapter->pdev->dev, - "%d msi vectors alloacted failed!\n", + "%d MSI vectors allocated failed!\n", adapter->notification_desc.iopoll_qdex); - goto legacy_int1; + leapraid_free_irq(adapter); + goto apply_legacy_int; } + adapter->notification_desc.irq_vectors_allocated = 1; + adapter->notification_desc.irq_mode = LEAPRAID_INTERRUPT_MODE_MSI; if (rc != adapter->notification_desc.iopoll_qdex) { adapter->notification_desc.iopoll_qdex = rc; adapter->adapter_attr.rq_cnt = @@ -6972,12 +7731,8 @@ static int leapraid_set_msi(struct leapraid_adapter *adapter) kcalloc(adapter->notification_desc.iopoll_qdex, sizeof(struct leapraid_int_rq), GFP_KERNEL); - if (!adapter->notification_desc.int_rqs) { - dev_err(&adapter->pdev->dev, - "MSI: allocate %d interrupt reply queues failed!\n", - adapter->notification_desc.iopoll_qdex); + if (!adapter->notification_desc.int_rqs) return -ENOMEM; - } for (i = 0; i < adapter->notification_desc.iopoll_qcnt; i++) { adapter->notification_desc.blk_mq_poll_rqs[i].rq.adapter = @@ -7001,24 +7756,24 @@ static int leapraid_set_msi(struct leapraid_adapter *adapter) adapter->notification_desc.msix_cpu_map_sz = num_online_cpus(); adapter->notification_desc.msix_cpu_map = - kzalloc(adapter->notification_desc.msix_cpu_map_sz, - GFP_KERNEL); + kzalloc(adapter->notification_desc.msix_cpu_map_sz, + GFP_KERNEL); if (!adapter->notification_desc.msix_cpu_map) return -ENOMEM; memset(adapter->notification_desc.msix_cpu_map, 0, adapter->notification_desc.msix_cpu_map_sz); - adapter->notification_desc.msix_enable = true; + adapter->notification_desc.msix_enable = 1; rc = leapraid_setup_irqs(adapter); if (rc) { leapraid_free_irq(adapter); - adapter->notification_desc.msix_enable = false; - goto legacy_int1; + adapter->notification_desc.msix_enable = 0; + goto apply_legacy_int; } return 0; -legacy_int1: +apply_legacy_int: rc = leapraid_set_legacy_int(adapter); return rc; @@ -7028,30 +7783,26 @@ static int leapraid_set_notification(struct leapraid_adapter *adapter) { int rc = 0; - if (interrupt_mode == 0) { + if (interrupt_mode == LEAPRAID_INTERRUPT_MODE_MSIX) { rc = leapraid_set_msix(adapter); if (rc) - pr_err("%s enable MSI-X irq failed!\n", __func__); - } else if (interrupt_mode == 1) { + dev_err(&adapter->pdev->dev, + "%s: Enable MSI-X irq failed!\n", __func__); + } else if (interrupt_mode == LEAPRAID_INTERRUPT_MODE_MSI) { rc = leapraid_set_msi(adapter); if (rc) - pr_err("%s enable MSI irq failed!\n", __func__); - } else if (interrupt_mode == 2) { + dev_err(&adapter->pdev->dev, + "%s: Enable MSI irq failed!\n", __func__); + } else if (interrupt_mode == LEAPRAID_INTERRUPT_MODE_LEGACY) { rc = leapraid_set_legacy_int(adapter); if (rc) - pr_err("%s enable legacy irq failed!\n", __func__); + dev_err(&adapter->pdev->dev, + "%s: Enable legacy irq failed!\n", __func__); } return rc; } -static void leapraid_disable_pcie_and_notification( - struct leapraid_adapter *adapter) -{ - leapraid_free_irq(adapter); - leapraid_disable_pcie(adapter); -} - int leapraid_set_pcie_and_notification(struct leapraid_adapter *adapter) { int rc; @@ -7064,13 +7815,13 @@ int leapraid_set_pcie_and_notification(struct leapraid_adapter *adapter) rc = leapraid_make_adapter_ready(adapter, PART_RESET); if (rc) { - dev_err(&adapter->pdev->dev, "make adapter ready failure\n"); + dev_err(&adapter->pdev->dev, "Make adapter ready failure\n"); goto out_fail; } rc = leapraid_get_adapter_features(adapter); if (rc) { - dev_err(&adapter->pdev->dev, "get adapter feature failure\n"); + dev_err(&adapter->pdev->dev, "Get adapter feature failure\n"); goto out_fail; } @@ -7083,7 +7834,8 @@ int leapraid_set_pcie_and_notification(struct leapraid_adapter *adapter) return 0; out_fail: - leapraid_disable_pcie_and_notification(adapter); + leapraid_free_irq(adapter); + leapraid_disable_pcie(adapter); return rc; } @@ -7094,11 +7846,13 @@ void leapraid_disable_controller(struct leapraid_adapter *adapter) leapraid_mask_int(adapter); - adapter->access_ctrl.shost_recovering = true; + adapter->access_ctrl.shost_recovering = 1; leapraid_make_adapter_ready(adapter, PART_RESET); - adapter->access_ctrl.shost_recovering = false; + adapter->access_ctrl.shost_recovering = 0; + wake_up(&adapter->access_ctrl.recovery_waitq); - leapraid_disable_pcie_and_notification(adapter); + leapraid_free_irq(adapter); + leapraid_disable_pcie(adapter); } static int leapraid_adapter_unit_reset(struct leapraid_adapter *adapter) @@ -7112,12 +7866,11 @@ static int leapraid_adapter_unit_reset(struct leapraid_adapter *adapter) rc = -EFAULT; if (!leapraid_wait_adapter_ready(adapter)) { - rc = -EFAULT; - goto out; + dev_info(&adapter->pdev->dev, "unit reset: FAILED\n"); + return -EFAULT; } -out: - dev_info(&adapter->pdev->dev, "unit reset: %s\n", - ((rc == 0) ? "SUCCESS" : "FAILED")); + + dev_info(&adapter->pdev->dev, "unit reset: SUCCESS\n"); return rc; } @@ -7137,13 +7890,13 @@ static int leapraid_make_adapter_ready(struct leapraid_adapter *adapter, while ((db & LEAPRAID_DB_MASK) != LEAPRAID_DB_READY) { if (count++ == LEAPRAID_DB_RETRY_COUNT_MAX) { dev_err(&adapter->pdev->dev, - "wait adapter ready timeout\n"); + "Wait adapter ready timeout\n"); return -EFAULT; } ssleep(1); db = leapraid_readl(&adapter->iomem_base->db); dev_info(&adapter->pdev->dev, - "wait adapter ready, count=%d, db=0x%x\n", + "Wait adapter ready, count=%d, db=0x%x\n", count, db); } } @@ -7159,9 +7912,9 @@ static int leapraid_make_adapter_ready(struct leapraid_adapter *adapter, if (type == FULL_RESET) goto full_reset; - if ((db & LEAPRAID_DB_MASK) == LEAPRAID_DB_OPERATIONAL) - if (!(leapraid_adapter_unit_reset(adapter))) - return 0; + if ((db & LEAPRAID_DB_MASK) == LEAPRAID_DB_OPERATIONAL && + !leapraid_adapter_unit_reset(adapter)) + return 0; full_reset: rc = leapraid_host_diag_reset(adapter); @@ -7202,12 +7955,8 @@ static int leapraid_fw_log_init(struct leapraid_adapter *adapter) LEAPRAID_SYS_LOG_BUF_RESERVE), &adapter->fw_log_desc.fw_log_buffer_dma, GFP_KERNEL); - if (!adapter->fw_log_desc.fw_log_buffer) { - dev_err(&adapter->pdev->dev, - "%s: log buf alloc failed.\n", - __func__); + if (!adapter->fw_log_desc.fw_log_buffer) return -ENOMEM; - } } memset(&adapter_log_req, 0, sizeof(struct leapraid_adapter_log_req)); @@ -7226,7 +7975,7 @@ static int leapraid_fw_log_init(struct leapraid_adapter *adapter) sizeof(struct leapraid_adapter_log_rep), (u16 *)&adapter_log_rep); if (rc != 0) { - dev_err(&adapter->pdev->dev, "%s: handshake failed, rc=%d\n", + dev_err(&adapter->pdev->dev, "%s: Handshake failed, rc=%d\n", __func__, rc); return rc; } @@ -7265,7 +8014,7 @@ static void leapraid_free_host_memory(struct leapraid_adapter *adapter) if (adapter->mem_desc.rep_msg) { dma_free_coherent( &adapter->pdev->dev, - adapter->adapter_attr.rep_msg_qd * LEAPRAID_REPLY_SIEZ, + adapter->adapter_attr.rep_msg_qd * LEAPRAID_REPLY_SIZE, adapter->mem_desc.rep_msg, adapter->mem_desc.rep_msg_dma); adapter->mem_desc.rep_msg = NULL; @@ -7283,15 +8032,19 @@ static void leapraid_free_host_memory(struct leapraid_adapter *adapter) if (adapter->mem_desc.rep_desc_seg_maint) { for (i = 0; i < adapter->adapter_attr.rep_desc_q_seg_cnt; i++) { - if (adapter->mem_desc.rep_desc_seg_maint[i].rep_desc_seg) { + if (adapter->mem_desc.rep_desc_seg_maint[i] + .rep_desc_seg) { dma_free_coherent( &adapter->pdev->dev, (adapter->adapter_attr.rep_desc_qd * LEAPRAID_REP_DESC_ENTRY_SIZE) * LEAPRAID_REP_DESC_CHUNK_SIZE, - adapter->mem_desc.rep_desc_seg_maint[i].rep_desc_seg, - adapter->mem_desc.rep_desc_seg_maint[i].rep_desc_seg_dma); - adapter->mem_desc.rep_desc_seg_maint[i].rep_desc_seg = NULL; + adapter->mem_desc.rep_desc_seg_maint[i] + .rep_desc_seg, + adapter->mem_desc.rep_desc_seg_maint[i] + .rep_desc_seg_dma); + adapter->mem_desc.rep_desc_seg_maint[i] + .rep_desc_seg = NULL; } } @@ -7306,7 +8059,8 @@ static void leapraid_free_host_memory(struct leapraid_adapter *adapter) } for (i = 0; i < adapter->adapter_attr.rep_desc_q_seg_cnt; i++) - kfree(adapter->mem_desc.rep_desc_seg_maint[i].rep_desc_maint); + kfree(adapter->mem_desc.rep_desc_seg_maint[i] + .rep_desc_maint); kfree(adapter->mem_desc.rep_desc_seg_maint); } @@ -7324,16 +8078,16 @@ static void leapraid_free_host_memory(struct leapraid_adapter *adapter) static inline bool leapraid_is_in_same_4g_seg(dma_addr_t start, u32 size) { - return (upper_32_bits(start) == upper_32_bits(start + size - 1)); + return upper_32_bits(start) == upper_32_bits(start + size - 1); } int leapraid_internal_init_cmd_priv(struct leapraid_adapter *adapter, struct leapraid_io_req_tracker *io_tracker) { io_tracker->chain = - dma_pool_alloc(adapter->mem_desc.sg_chain_pool, - GFP_KERNEL, - &io_tracker->chain_dma); + dma_pool_alloc(adapter->mem_desc.sg_chain_pool, + GFP_KERNEL, + &io_tracker->chain_dma); if (!io_tracker->chain) return -ENOMEM; @@ -7360,17 +8114,16 @@ static int leapraid_request_host_memory(struct leapraid_adapter *adapter) unsigned int i, j; int rc; - /* sg table size */ + /* Scatter-gather table size. */ adapter->shost->sg_tablesize = LEAPRAID_SG_DEPTH; if (reset_devices) adapter->shost->sg_tablesize = LEAPRAID_KDUMP_MIN_PHYS_SEGMENTS; - /* high priority cmds queue depth */ - adapter->dynamic_task_desc.hp_cmd_qd = facts->hp_slot; + /* High-priority commands queue depth. */ adapter->dynamic_task_desc.hp_cmd_qd = LEAPRAID_FIXED_HP_CMDS; - /* internal cmds queue depth */ + /* Internal commands queue depth. */ adapter->dynamic_task_desc.inter_cmd_qd = LEAPRAID_FIXED_INTER_CMDS; - /* adapter cmds total queue depth */ + /* Adapter commands total queue depth. */ if (reset_devices) adapter->adapter_attr.adapter_total_qd = LEAPRAID_DEFAULT_CMD_QD_OFFSET + @@ -7379,22 +8132,22 @@ static int leapraid_request_host_memory(struct leapraid_adapter *adapter) else adapter->adapter_attr.adapter_total_qd = facts->req_slot + adapter->dynamic_task_desc.hp_cmd_qd; - /* reply message queue depth */ + /* Reply message queue depth. */ adapter->adapter_attr.rep_msg_qd = adapter->adapter_attr.adapter_total_qd + LEAPRAID_DEFAULT_CMD_QD_OFFSET; - /* reply descriptor queue depth */ + /* Reply descriptor queue depth. */ adapter->adapter_attr.rep_desc_qd = round_up(adapter->adapter_attr.adapter_total_qd + adapter->adapter_attr.rep_msg_qd + LEAPRAID_TASKID_OFFSET_CTRL_CMD, LEAPRAID_REPLY_QD_ALIGNMENT); - /* scsi cmd io depth */ + /* SCSI command I/O depth. */ adapter->adapter_attr.io_qd = adapter->adapter_attr.adapter_total_qd - adapter->dynamic_task_desc.hp_cmd_qd - adapter->dynamic_task_desc.inter_cmd_qd; - /* scsi host can queue */ + /* SCSI host can queue. */ adapter->shost->can_queue = adapter->adapter_attr.io_qd - LEAPRAID_TASKID_OFFSET_SCSIIO_CMD; adapter->driver_cmds.ctl_cmd.taskid = adapter->shost->can_queue + @@ -7403,7 +8156,7 @@ static int leapraid_request_host_memory(struct leapraid_adapter *adapter) adapter->shost->can_queue + LEAPRAID_TASKID_OFFSET_SCSIIO_CMD; - /* allocate task descriptor */ + /* Allocate task descriptor. */ try_again: adapter->adapter_attr.task_desc_dma_size = (adapter->adapter_attr.adapter_total_qd + @@ -7414,49 +8167,41 @@ static int leapraid_request_host_memory(struct leapraid_adapter *adapter) adapter->adapter_attr.task_desc_dma_size, &adapter->mem_desc.task_desc_dma, GFP_KERNEL); - if (!adapter->mem_desc.task_desc) { - dev_err(&adapter->pdev->dev, - "failed to allocate task descriptor DMA!\n"); - rc = -ENOMEM; - goto out; - } - /* allocate chain message pool */ + if (!adapter->mem_desc.task_desc) + return -ENOMEM; + + /* Allocate chain message pool. */ adapter->mem_desc.sg_chain_pool_size = LEAPRAID_DEFAULT_CHAINS_PER_IO * LEAPRAID_CHAIN_SEG_SIZE; adapter->mem_desc.sg_chain_pool = dma_pool_create("leapraid chain pool", &adapter->pdev->dev, - adapter->mem_desc.sg_chain_pool_size, 16, 0); - if (!adapter->mem_desc.sg_chain_pool) { - dev_err(&adapter->pdev->dev, - "failed to allocate chain message DMA!\n"); - rc = -ENOMEM; - goto out; - } + adapter->mem_desc.sg_chain_pool_size, + LEAPRAID_DMA_ALIGN, 0); + if (!adapter->mem_desc.sg_chain_pool) + return -ENOMEM; - /* allocate io tracker to ref scsi io */ + /* Allocate I/O tracker to SCSI I/O. */ adapter->mem_desc.io_tracker = kcalloc(adapter->shost->can_queue, sizeof(struct leapraid_io_req_tracker), GFP_KERNEL); - if (!adapter->mem_desc.io_tracker) { - rc = -ENOMEM; - goto out; - } + if (!adapter->mem_desc.io_tracker) + return -ENOMEM; for (i = 0; (int)i < adapter->shost->can_queue; i++) { rc = leapraid_internal_init_cmd_priv( adapter, adapter->mem_desc.io_tracker + i); if (rc) - goto out; + goto out_fail; } adapter->dynamic_task_desc.hp_taskid = adapter->adapter_attr.io_qd + LEAPRAID_HP_TASKID_OFFSET_CTL_CMD; - /* allocate static hp taskid */ + /* Allocate static high-priority task ID. */ adapter->driver_cmds.ctl_cmd.hp_taskid = adapter->dynamic_task_desc.hp_taskid; adapter->driver_cmds.tm_cmd.hp_taskid = @@ -7477,9 +8222,6 @@ static int leapraid_request_host_memory(struct leapraid_adapter *adapter) adapter->driver_cmds.timestamp_sync_cmd.inter_taskid = adapter->dynamic_task_desc.inter_taskid + LEAPRAID_TASKID_OFFSET_TIMESTAMP_SYNC_CMD; - adapter->driver_cmds.raid_action_cmd.inter_taskid = - adapter->dynamic_task_desc.inter_taskid + - LEAPRAID_TASKID_OFFSET_RAID_ACTION_CMD; adapter->driver_cmds.enc_cmd.inter_taskid = adapter->dynamic_task_desc.inter_taskid + LEAPRAID_TASKID_OFFSET_ENC_CMD; @@ -7507,64 +8249,58 @@ static int leapraid_request_host_memory(struct leapraid_adapter *adapter) adapter->dynamic_task_desc.inter_taskid); /* - * allocate sense dma, driver maintain - * need in same 4GB segment + * Allocate sense data DMA buffer. + * Constraint: Must reside within the same 4GB segment + * (driver-maintained). */ adapter->mem_desc.sense_data = - dma_alloc_coherent( + dma_alloc_coherent( &adapter->pdev->dev, adapter->adapter_attr.io_qd * SCSI_SENSE_BUFFERSIZE, - &adapter->mem_desc.sense_data_dma, GFP_KERNEL); - if (!adapter->mem_desc.sense_data) { - dev_err(&adapter->pdev->dev, - "failed to allocate sense data DMA!\n"); - rc = -ENOMEM; - goto out; - } + &adapter->mem_desc.sense_data_dma, + GFP_KERNEL); + if (!adapter->mem_desc.sense_data) + return -ENOMEM; + if (!leapraid_is_in_same_4g_seg(adapter->mem_desc.sense_data_dma, adapter->adapter_attr.io_qd * SCSI_SENSE_BUFFERSIZE)) { dev_warn(&adapter->pdev->dev, - "try 32 bit dma due to sense data is not in same 4g!\n"); + "Try 32bit DMA: Sense not in same 4G\n"); rc = -EAGAIN; - goto out; + goto out_fail; } - /* reply frame, need in same 4GB segment */ + /* + * Allocate reply frame buffer. + * Constraint: Must reside in the same 4GB segment as the sense DMA. + */ adapter->mem_desc.rep_msg = - dma_alloc_coherent(&adapter->pdev->dev, - adapter->adapter_attr.rep_msg_qd * - LEAPRAID_REPLY_SIEZ, - &adapter->mem_desc.rep_msg_dma, - GFP_KERNEL); - if (!adapter->mem_desc.rep_msg) { - dev_err(&adapter->pdev->dev, - "failed to allocate reply message DMA!\n"); - rc = -ENOMEM; - goto out; - } + dma_alloc_coherent(&adapter->pdev->dev, + adapter->adapter_attr.rep_msg_qd * + LEAPRAID_REPLY_SIZE, + &adapter->mem_desc.rep_msg_dma, + GFP_KERNEL); + if (!adapter->mem_desc.rep_msg) + return -ENOMEM; if (!leapraid_is_in_same_4g_seg(adapter->mem_desc.rep_msg_dma, adapter->adapter_attr.rep_msg_qd * - LEAPRAID_REPLY_SIEZ)) { + LEAPRAID_REPLY_SIZE)) { dev_warn(&adapter->pdev->dev, - "use 32 bit dma due to rep msg is not in same 4g!\n"); + "Use 32 bit DMA due to rep msg is not in same 4g!\n"); rc = -EAGAIN; - goto out; + goto out_fail; } - /* address of reply frame */ + /* Address of reply frame. */ adapter->mem_desc.rep_msg_addr = - dma_alloc_coherent(&adapter->pdev->dev, - adapter->adapter_attr.rep_msg_qd * - LEAPRAID_REP_MSG_ADDR_SIZE, - &adapter->mem_desc.rep_msg_addr_dma, - GFP_KERNEL); - if (!adapter->mem_desc.rep_msg_addr) { - dev_err(&adapter->pdev->dev, - "failed to allocate reply message address DMA!\n"); - rc = -ENOMEM; - goto out; - } + dma_alloc_coherent(&adapter->pdev->dev, + adapter->adapter_attr.rep_msg_qd * + LEAPRAID_REP_MSG_ADDR_SIZE, + &adapter->mem_desc.rep_msg_addr_dma, + GFP_KERNEL); + if (!adapter->mem_desc.rep_msg_addr) + return -ENOMEM; adapter->adapter_attr.rep_desc_q_seg_cnt = DIV_ROUND_UP(adapter->adapter_attr.rq_cnt, LEAPRAID_REP_DESC_CHUNK_SIZE); @@ -7572,10 +8308,8 @@ static int leapraid_request_host_memory(struct leapraid_adapter *adapter) kcalloc(adapter->adapter_attr.rep_desc_q_seg_cnt, sizeof(struct leapraid_rep_desc_seg_maint), GFP_KERNEL); - if (!adapter->mem_desc.rep_desc_seg_maint) { - rc = -ENOMEM; - goto out; - } + if (!adapter->mem_desc.rep_desc_seg_maint) + return -ENOMEM; rep_desc_q_cnt_allocated = 0; for (i = 0; i < adapter->adapter_attr.rep_desc_q_seg_cnt; i++) { @@ -7583,25 +8317,20 @@ static int leapraid_request_host_memory(struct leapraid_adapter *adapter) kcalloc(LEAPRAID_REP_DESC_CHUNK_SIZE, sizeof(struct leapraid_rep_desc_maint), GFP_KERNEL); - if (!adapter->mem_desc.rep_desc_seg_maint[i].rep_desc_maint) { - rc = -ENOMEM; - goto out; - } + if (!adapter->mem_desc.rep_desc_seg_maint[i].rep_desc_maint) + return -ENOMEM; adapter->mem_desc.rep_desc_seg_maint[i].rep_desc_seg = - dma_alloc_coherent( + dma_alloc_coherent( &adapter->pdev->dev, (adapter->adapter_attr.rep_desc_qd * - LEAPRAID_REP_DESC_ENTRY_SIZE) * + LEAPRAID_REP_DESC_ENTRY_SIZE) * LEAPRAID_REP_DESC_CHUNK_SIZE, - &adapter->mem_desc.rep_desc_seg_maint[i].rep_desc_seg_dma, + &adapter->mem_desc.rep_desc_seg_maint[i] + .rep_desc_seg_dma, GFP_KERNEL); - if (!adapter->mem_desc.rep_desc_seg_maint[i].rep_desc_seg) { - dev_err(&adapter->pdev->dev, - "failed to allocate reply descriptor segment DMA!\n"); - rc = -ENOMEM; - goto out; - } + if (!adapter->mem_desc.rep_desc_seg_maint[i].rep_desc_seg) + return -ENOMEM; for (j = 0; j < LEAPRAID_REP_DESC_CHUNK_SIZE; j++) { if (rep_desc_q_cnt_allocated >= @@ -7634,30 +8363,26 @@ static int leapraid_request_host_memory(struct leapraid_adapter *adapter) if (!reset_devices) { adapter->mem_desc.rep_desc_q_arr = - dma_alloc_coherent( + dma_alloc_coherent( &adapter->pdev->dev, adapter->adapter_attr.rq_cnt * LEAPRAID_REP_RQ_CNT_SIZE, &adapter->mem_desc.rep_desc_q_arr_dma, GFP_KERNEL); - if (!adapter->mem_desc.rep_desc_q_arr) { - dev_err(&adapter->pdev->dev, - "failed to allocate reply descriptor queue array DMA!\n"); - rc = -ENOMEM; - goto out; - } + if (!adapter->mem_desc.rep_desc_q_arr) + return -ENOMEM; } return 0; -out: +out_fail: if (rc == -EAGAIN) { leapraid_free_host_memory(adapter); - adapter->adapter_attr.use_32_dma_mask = true; + adapter->adapter_attr.use_32_dma_mask = 1; rc = dma_set_mask_and_coherent(&adapter->pdev->dev, - DMA_BIT_MASK(32)); + DMA_BIT_MASK(DMA_32_BITS)); if (rc) { dev_err(&adapter->pdev->dev, - "failed to set 32 DMA mask\n"); + "Failed to set 32 DMA mask\n"); return rc; } goto try_again; @@ -7667,12 +8392,13 @@ static int leapraid_request_host_memory(struct leapraid_adapter *adapter) static int leapraid_alloc_dev_topo_bitmaps(struct leapraid_adapter *adapter) { - adapter->dev_topo.pd_hdls_sz = - adapter->adapter_attr.features.max_dev_handle / - LEAPRAID_BITS_PER_BYTE; - if (adapter->adapter_attr.features.max_dev_handle % - LEAPRAID_BITS_PER_BYTE) - adapter->dev_topo.pd_hdls_sz++; + u16 pd_hdls_sz; + + pd_hdls_sz = adapter->adapter_attr.features.max_dev_handle / + LEAPRAID_BITS_PER_BYTE; + pd_hdls_sz++; + + adapter->dev_topo.pd_hdls_sz = pd_hdls_sz; adapter->dev_topo.pd_hdls = kzalloc(adapter->dev_topo.pd_hdls_sz, GFP_KERNEL); if (!adapter->dev_topo.pd_hdls) @@ -7683,24 +8409,6 @@ static int leapraid_alloc_dev_topo_bitmaps(struct leapraid_adapter *adapter) if (!adapter->dev_topo.blocking_hdls) return -ENOMEM; - adapter->dev_topo.pending_dev_add_sz = - adapter->adapter_attr.features.max_dev_handle / - LEAPRAID_BITS_PER_BYTE; - if (adapter->adapter_attr.features.max_dev_handle % - LEAPRAID_BITS_PER_BYTE) - adapter->dev_topo.pending_dev_add_sz++; - adapter->dev_topo.pending_dev_add = - kzalloc(adapter->dev_topo.pending_dev_add_sz, GFP_KERNEL); - if (!adapter->dev_topo.pending_dev_add) - return -ENOMEM; - - adapter->dev_topo.dev_removing_sz = - adapter->dev_topo.pending_dev_add_sz; - adapter->dev_topo.dev_removing = - kzalloc(adapter->dev_topo.dev_removing_sz, GFP_KERNEL); - if (!adapter->dev_topo.dev_removing) - return -ENOMEM; - return 0; } @@ -7708,13 +8416,11 @@ static void leapraid_free_dev_topo_bitmaps(struct leapraid_adapter *adapter) { kfree(adapter->dev_topo.pd_hdls); kfree(adapter->dev_topo.blocking_hdls); - kfree(adapter->dev_topo.pending_dev_add); - kfree(adapter->dev_topo.dev_removing); } static int leapraid_init_driver_cmds(struct leapraid_adapter *adapter) { - u32 buffer_size = 0; + u32 buffer_size; void *buffer; INIT_LIST_HEAD(&adapter->driver_cmds.special_cmd_list); @@ -7767,15 +8473,14 @@ static int leapraid_init_driver_cmds(struct leapraid_adapter *adapter) return -ENOMEM; adapter->driver_cmds.internal_scmd = buffer; - buffer = (void *)((u8 *)buffer + - sizeof(struct scsi_cmnd) + - sizeof(struct leapraid_io_req_tracker)); + buffer = (u8 *)buffer + sizeof(struct scsi_cmnd) + + sizeof(struct leapraid_io_req_tracker); adapter->driver_cmds.internal_scmd->sense_buffer = - (unsigned char *)buffer; - buffer = (void *)((u8 *)buffer + SCSI_SENSE_BUFFERSIZE); + (unsigned char *)buffer; + buffer = (u8 *)buffer + SCSI_SENSE_BUFFERSIZE; adapter->driver_cmds.internal_scmd->sdb.table.sgl = - (struct scatterlist *)buffer; - buffer = (void *)((u8 *)buffer + sizeof(struct scatterlist)); + (struct scatterlist *)buffer; + buffer = (u8 *)buffer + sizeof(struct scatterlist); adapter->driver_cmds.internal_scmd->cmnd = buffer; adapter->driver_cmds.internal_scmd->host_scribble = (unsigned char *)(adapter->driver_cmds.internal_scmd + 1); @@ -7821,32 +8526,34 @@ static void leapraid_init_event_mask(struct leapraid_adapter *adapter) int i; for (i = 0; i < LEAPRAID_EVT_MASK_COUNT; i++) - adapter->fw_evt_s.leapraid_evt_masks[i] = -1; - leapraid_unmask_evts(adapter, LEAPRAID_EVT_SAS_DISCOVERY); + adapter->fw_evt_s.leapraid_evt_masks[i] = + LEAPRAID_INVALID_INITIAL_VALUE; + leapraid_unmask_evts(adapter, LEAPRAID_EVT_SAS_TOPO_CHANGE_LIST); leapraid_unmask_evts(adapter, LEAPRAID_EVT_SAS_ENCL_DEV_STATUS_CHANGE); leapraid_unmask_evts(adapter, LEAPRAID_EVT_SAS_DEV_STATUS_CHANGE); leapraid_unmask_evts(adapter, LEAPRAID_EVT_IR_CHANGE); } -static void leapraid_prepare_adp_init_req( +static void leapraid_prepare_adapter_init_req( struct leapraid_adapter *adapter, struct leapraid_adapter_init_req *init_req) { ktime_t cur_time; - int i; + int i, chunk; u32 reply_post_free_ary_sz; memset(init_req, 0, sizeof(struct leapraid_adapter_init_req)); init_req->func = LEAPRAID_FUNC_ADAPTER_INIT; init_req->who_init = LEAPRAID_WHOINIT_LINUX_DRIVER; - init_req->msg_ver = cpu_to_le16(0x0100); - init_req->header_ver = cpu_to_le16(0x0000); - - init_req->driver_ver = cpu_to_le32((LEAPRAID_MAJOR_VERSION << 24) | - (LEAPRAID_MINOR_VERSION << 16) | - (LEAPRAID_BUILD_VERSION << 8) | - LEAPRAID_RELEASE_VERSION); + init_req->msg_ver = cpu_to_le16(LEAPRAID_MSG_VERSION); + init_req->header_ver = cpu_to_le16(LEAPRAID_HEADER_VERSION); + init_req->driver_ver = + cpu_to_le32((LEAPRAID_MAJOR_VERSION << + LEAPRAID_VER_MAJOR_SHIFT) | + (LEAPRAID_MINOR_VERSION << LEAPRAID_VER_MINOR_SHIFT) | + (LEAPRAID_BUILD_VERSION << LEAPRAID_VER_BUILD_SHIFT) | + LEAPRAID_RELEASE_VERSION); if (adapter->notification_desc.msix_enable) init_req->host_msix_vectors = adapter->adapter_attr.rq_cnt; @@ -7870,18 +8577,13 @@ static void leapraid_prepare_adp_init_req( memset(adapter->mem_desc.rep_desc_q_arr, 0, reply_post_free_ary_sz); - for (i = 0; i < adapter->adapter_attr.rq_cnt; i++) { - adapter->mem_desc - .rep_desc_q_arr[i] - .rep_desc_base_addr = - cpu_to_le64 ( - (u64)adapter->mem_desc - .rep_desc_seg_maint[i / - LEAPRAID_REP_DESC_CHUNK_SIZE] - .rep_desc_maint[i % - LEAPRAID_REP_DESC_CHUNK_SIZE] - .rep_desc_dma); - } + chunk = LEAPRAID_REP_DESC_CHUNK_SIZE; + for (i = 0; i < adapter->adapter_attr.rq_cnt; i++) + adapter->mem_desc.rep_desc_q_arr[i].rep_desc_base_addr = + cpu_to_le64 ((u64)adapter->mem_desc + .rep_desc_seg_maint[i / chunk] + .rep_desc_maint[i % chunk] + .rep_desc_dma); init_req->msg_flg = LEAPRAID_ADAPTER_INIT_MSGFLG_RDPQ_ARRAY_MODE; @@ -7903,9 +8605,9 @@ static int leapraid_send_adapter_init(struct leapraid_adapter *adapter) struct leapraid_adapter_init_req init_req; struct leapraid_adapter_init_rep init_rep; u16 adapter_status; - int rc = 0; + int rc; - leapraid_prepare_adp_init_req(adapter, &init_req); + leapraid_prepare_adapter_init_req(adapter, &init_req); rc = leapraid_handshake_func(adapter, sizeof(struct leapraid_adapter_init_req), @@ -7913,7 +8615,7 @@ static int leapraid_send_adapter_init(struct leapraid_adapter *adapter) sizeof(struct leapraid_adapter_init_rep), (u16 *)&init_rep); if (rc != 0) { - dev_err(&adapter->pdev->dev, "%s: handshake failed, rc=%d\n", + dev_err(&adapter->pdev->dev, "%s: Handshake failed, rc=%d\n", __func__, rc); return rc; } @@ -7934,11 +8636,10 @@ static int leapraid_cfg_pages(struct leapraid_adapter *adapter) { union cfg_param_1 cfgp1 = {0}; union cfg_param_2 cfgp2 = {0}; - struct leapraid_sas_io_unit_page1 *sas_io_unit_page1 = NULL; + struct leapraid_manufacturing_p0 manufacturing_page0; struct leapraid_bios_page3 bios_page3; struct leapraid_bios_page2 bios_page2; - int rc = 0; - int sz; + int rc; rc = leapraid_op_config_page(adapter, &bios_page3, cfgp1, cfgp2, GET_BIOS_PG3); @@ -7950,79 +8651,49 @@ static int leapraid_cfg_pages(struct leapraid_adapter *adapter) if (rc) return rc; + rc = leapraid_op_config_page(adapter, &manufacturing_page0, cfgp1, + cfgp2, GET_MANUFACTURING_PG0); + if (rc) + return rc; + adapter->adapter_attr.bios_version = le32_to_cpu(bios_page3.bios_version); - adapter->adapter_attr.wideport_max_queue_depth = - LEAPRAID_SAS_QUEUE_DEPTH; - adapter->adapter_attr.narrowport_max_queue_depth = - LEAPRAID_SAS_QUEUE_DEPTH; - adapter->adapter_attr.sata_max_queue_depth = - LEAPRAID_SATA_QUEUE_DEPTH; - + snprintf(adapter->adapter_attr.board_name, + sizeof(adapter->adapter_attr.board_name), + "%.*s", + (int)sizeof(manufacturing_page0.board_name), + manufacturing_page0.board_name); adapter->boot_devs.requested_boot_dev.form = bios_page2.requested_boot_dev_form; - memcpy((void *)adapter->boot_devs.requested_boot_dev.pg_dev, - (void *)&bios_page2.requested_boot_dev, + memcpy(adapter->boot_devs.requested_boot_dev.pg_dev, + &bios_page2.requested_boot_dev, LEAPRAID_BOOT_DEV_SIZE); adapter->boot_devs.requested_alt_boot_dev.form = bios_page2.requested_alt_boot_dev_form; - memcpy((void *)adapter->boot_devs.requested_alt_boot_dev.pg_dev, - (void *)&bios_page2.requested_alt_boot_dev, + memcpy(adapter->boot_devs.requested_alt_boot_dev.pg_dev, + &bios_page2.requested_alt_boot_dev, LEAPRAID_BOOT_DEV_SIZE); adapter->boot_devs.current_boot_dev.form = bios_page2.current_boot_dev_form; - memcpy((void *)adapter->boot_devs.current_boot_dev.pg_dev, - (void *)&bios_page2.current_boot_dev, + memcpy(adapter->boot_devs.current_boot_dev.pg_dev, + &bios_page2.current_boot_dev, LEAPRAID_BOOT_DEV_SIZE); - - sz = offsetof(struct leapraid_sas_io_unit_page1, phy_info); - sas_io_unit_page1 = kzalloc(sz, GFP_KERNEL); - if (!sas_io_unit_page1) { - rc = -ENOMEM; - return rc; - } - - cfgp1.size = sz; - - rc = leapraid_op_config_page(adapter, sas_io_unit_page1, cfgp1, - cfgp2, GET_SAS_IOUNIT_PG1); - if (rc) - goto out; - - if (le16_to_cpu(sas_io_unit_page1->wideport_max_queue_depth)) - adapter->adapter_attr.wideport_max_queue_depth = - le16_to_cpu( - sas_io_unit_page1->wideport_max_queue_depth); - - if (le16_to_cpu(sas_io_unit_page1->narrowport_max_queue_depth)) - adapter->adapter_attr.narrowport_max_queue_depth = - le16_to_cpu( - sas_io_unit_page1->narrowport_max_queue_depth); - - if (sas_io_unit_page1->sata_max_queue_depth) - adapter->adapter_attr.sata_max_queue_depth = - sas_io_unit_page1->sata_max_queue_depth; - -out: - kfree(sas_io_unit_page1); - dev_info(&adapter->pdev->dev, - "max wp qd=%d, max np qd=%d, max sata qd=%d\n", - adapter->adapter_attr.wideport_max_queue_depth, - adapter->adapter_attr.narrowport_max_queue_depth, - adapter->adapter_attr.sata_max_queue_depth); return rc; } static int leapraid_evt_notify(struct leapraid_adapter *adapter) { struct leapraid_evt_notify_req *evt_notify_req; + struct leapraid_evt_notify_rep *evt_notify_rep; + u16 adapter_status; int rc = 0; int i; mutex_lock(&adapter->driver_cmds.notify_event_cmd.mutex); adapter->driver_cmds.notify_event_cmd.status = LEAPRAID_CMD_PENDING; evt_notify_req = - leapraid_get_task_desc(adapter, + leapraid_get_task_desc( + adapter, adapter->driver_cmds.notify_event_cmd.inter_taskid); memset(evt_notify_req, 0, sizeof(struct leapraid_evt_notify_req)); evt_notify_req->func = LEAPRAID_FUNC_EVENT_NOTIFY; @@ -8031,15 +8702,30 @@ static int leapraid_evt_notify(struct leapraid_adapter *adapter) cpu_to_le32(adapter->fw_evt_s.leapraid_evt_masks[i]); init_completion(&adapter->driver_cmds.notify_event_cmd.done); leapraid_fire_task(adapter, - adapter->driver_cmds.notify_event_cmd.inter_taskid); + adapter->driver_cmds.notify_event_cmd.inter_taskid); wait_for_completion_timeout( &adapter->driver_cmds.notify_event_cmd.done, LEAPRAID_NOTIFY_EVENT_CMD_TIMEOUT * HZ); + if (!(adapter->driver_cmds.notify_event_cmd.status & - LEAPRAID_CMD_DONE)) - if (adapter->driver_cmds.notify_event_cmd.status & - LEAPRAID_CMD_RESET) - rc = -EFAULT; + LEAPRAID_CMD_DONE)) { + rc = -EFAULT; + goto out_cleanup; + } + + if (!(adapter->driver_cmds.notify_event_cmd.status & + LEAPRAID_CMD_REPLY_VALID)) { + rc = -EFAULT; + goto out_cleanup; + } + + evt_notify_rep = (void *)&adapter->driver_cmds.notify_event_cmd.reply; + adapter_status = le16_to_cpu(evt_notify_rep->adapter_status) & + LEAPRAID_ADAPTER_STATUS_MASK; + if (adapter_status != LEAPRAID_ADAPTER_STATUS_SUCCESS) + rc = -EFAULT; + +out_cleanup: adapter->driver_cmds.notify_event_cmd.status = LEAPRAID_CMD_NOT_USED; mutex_unlock(&adapter->driver_cmds.notify_event_cmd.mutex); @@ -8054,51 +8740,54 @@ int leapraid_scan_dev(struct leapraid_adapter *adapter, bool async_scan_dev) int rc = 0; dev_info(&adapter->pdev->dev, - "send device scan, async_scan_dev=%d!\n", async_scan_dev); + "Send device scan, async_scan_dev=%d!\n", async_scan_dev); adapter->driver_cmds.scan_dev_cmd.status = LEAPRAID_CMD_PENDING; adapter->driver_cmds.scan_dev_cmd.async_scan_dev = async_scan_dev; - scan_dev_req = leapraid_get_task_desc(adapter, - adapter->driver_cmds.scan_dev_cmd.inter_taskid); + scan_dev_req = + leapraid_get_task_desc( + adapter, + adapter->driver_cmds.scan_dev_cmd.inter_taskid); memset(scan_dev_req, 0, sizeof(struct leapraid_scan_dev_req)); scan_dev_req->func = LEAPRAID_FUNC_SCAN_DEV; if (async_scan_dev) { - adapter->scan_dev_desc.first_scan_dev_fired = true; - leapraid_fire_task(adapter, + adapter->scan_dev_desc.first_scan_dev_fired = 1; + leapraid_fire_task( + adapter, adapter->driver_cmds.scan_dev_cmd.inter_taskid); return 0; } init_completion(&adapter->driver_cmds.scan_dev_cmd.done); leapraid_fire_task(adapter, - adapter->driver_cmds.scan_dev_cmd.inter_taskid); + adapter->driver_cmds.scan_dev_cmd.inter_taskid); wait_for_completion_timeout(&adapter->driver_cmds.scan_dev_cmd.done, LEAPRAID_SCAN_DEV_CMD_TIMEOUT * HZ); if (!(adapter->driver_cmds.scan_dev_cmd.status & LEAPRAID_CMD_DONE)) { - dev_err(&adapter->pdev->dev, "device scan timeout!\n"); + dev_err(&adapter->pdev->dev, "Device scan timeout!\n"); if (adapter->driver_cmds.scan_dev_cmd.status & LEAPRAID_CMD_RESET) rc = -EFAULT; else rc = -ETIME; - goto out; + goto out_cleanup; } - scan_dev_rep = (void *)(&adapter->driver_cmds.scan_dev_cmd.reply); + scan_dev_rep = (void *)&adapter->driver_cmds.scan_dev_cmd.reply; adapter_status = le16_to_cpu(scan_dev_rep->adapter_status) & LEAPRAID_ADAPTER_STATUS_MASK; if (adapter_status != LEAPRAID_ADAPTER_STATUS_SUCCESS) { - dev_err(&adapter->pdev->dev, "device scan failure!\n"); + dev_err(&adapter->pdev->dev, "Device scan failure!\n"); rc = -EFAULT; - goto out; + goto out_cleanup; } -out: +out_cleanup: adapter->driver_cmds.scan_dev_cmd.status = LEAPRAID_CMD_NOT_USED; dev_info(&adapter->pdev->dev, - "device scan %s\n", ((rc == 0) ? "SUCCESS" : "FAILED")); + "Device scan %s\n", rc == 0 ? "SUCCESS" : "FAILED"); return rc; } @@ -8125,13 +8814,14 @@ static void leapraid_init_rep_msg_addr(struct leapraid_adapter *adapter) for (i = 0, reply_address = (u32)adapter->mem_desc.rep_msg_dma; i < adapter->adapter_attr.rep_msg_qd; - i++, reply_address += LEAPRAID_REPLY_SIEZ) { + i++, reply_address += LEAPRAID_REPLY_SIZE) adapter->mem_desc.rep_msg_addr[i] = cpu_to_le32(reply_address); - } } -static void init_rep_desc(struct leapraid_rq *rq, int index, - union leapraid_rep_desc_union *reply_post_free_contig) +static void init_rep_desc( + struct leapraid_rq *rq, + int index, + union leapraid_rep_desc_union *reply_post_free_contig) { struct leapraid_adapter *adapter = rq->adapter; unsigned int i; @@ -8218,7 +8908,7 @@ static void leapraid_init_bar_idx_regs(struct leapraid_adapter *adapter) static int leapraid_make_adapter_available(struct leapraid_adapter *adapter) { - int rc = 0; + int rc; leapraid_init_task_tracker(adapter); leapraid_init_rep_msg_addr(adapter); @@ -8242,7 +8932,7 @@ static int leapraid_make_adapter_available(struct leapraid_adapter *adapter) return rc; if (!adapter->access_ctrl.shost_recovering) { - adapter->scan_dev_desc.wait_scan_dev_done = true; + adapter->scan_dev_desc.wait_scan_dev_done = 1; return 0; } @@ -8256,45 +8946,45 @@ static int leapraid_make_adapter_available(struct leapraid_adapter *adapter) int leapraid_ctrl_init(struct leapraid_adapter *adapter) { u32 cap; - int rc = 0; + int rc; rc = leapraid_set_pcie_and_notification(adapter); if (rc) - goto out_free_resources; + goto out_free; pci_set_drvdata(adapter->pdev, adapter->shost); pcie_capability_read_dword(adapter->pdev, PCI_EXP_DEVCAP, &cap); - if (cap & PCI_EXP_DEVCAP_EXT_TAG) { + if (cap & PCI_EXP_DEVCAP_EXT_TAG) pcie_capability_set_word(adapter->pdev, PCI_EXP_DEVCTL, PCI_EXP_DEVCTL_EXT_TAG); - } rc = leapraid_fw_log_init(adapter); if (rc) { - dev_err(&adapter->pdev->dev, "fw log init failure\n"); - goto out_free_resources; + dev_err(&adapter->pdev->dev, "FW log init failure\n"); + goto out_free; } rc = leapraid_request_host_memory(adapter); if (rc) { - dev_err(&adapter->pdev->dev, "request host memory failure\n"); - goto out_free_resources; + dev_err(&adapter->pdev->dev, "Request host memory failure\n"); + goto out_free; } init_waitqueue_head(&adapter->reset_desc.reset_wait_queue); + init_waitqueue_head(&adapter->access_ctrl.shost_recover_wq); rc = leapraid_alloc_dev_topo_bitmaps(adapter); if (rc) { - dev_err(&adapter->pdev->dev, "alloc topo bitmaps failure\n"); - goto out_free_resources; + dev_err(&adapter->pdev->dev, "Alloc topo bitmaps failure\n"); + goto out_free; } rc = leapraid_init_driver_cmds(adapter); if (rc) { - dev_err(&adapter->pdev->dev, "init driver cmds failure\n"); - goto out_free_resources; + dev_err(&adapter->pdev->dev, "Init driver cmds failure\n"); + goto out_free; } leapraid_init_event_mask(adapter); @@ -8302,14 +8992,23 @@ int leapraid_ctrl_init(struct leapraid_adapter *adapter) rc = leapraid_make_adapter_available(adapter); if (rc) { dev_err(&adapter->pdev->dev, - "make adapter available failure\n"); - goto out_free_resources; + "Make adapter available failure\n"); + goto out_free; } + + leapraid_overheat_init(adapter); + if (!adapter->overheat_desc.fault_overheat_wq) { + rc = -ENOMEM; + goto out_free; + } + return 0; -out_free_resources: - adapter->access_ctrl.host_removing = true; +out_free: + adapter->access_ctrl.host_removing = 1; + wake_up(&adapter->access_ctrl.recovery_waitq); leapraid_fw_log_exit(adapter); + leapraid_free_internal_scsi_cmd(adapter); leapraid_disable_controller(adapter); leapraid_free_host_memory(adapter); leapraid_free_dev_topo_bitmaps(adapter); @@ -8319,9 +9018,11 @@ int leapraid_ctrl_init(struct leapraid_adapter *adapter) void leapraid_remove_ctrl(struct leapraid_adapter *adapter) { + leapraid_overheat_cleanup(adapter); leapraid_check_scheduled_fault_stop(adapter); leapraid_fw_log_stop(adapter); leapraid_fw_log_exit(adapter); + leapraid_free_internal_scsi_cmd(adapter); leapraid_disable_controller(adapter); leapraid_free_host_memory(adapter); leapraid_free_dev_topo_bitmaps(adapter); diff --git a/drivers/scsi/leapraid/leapraid_func.h b/drivers/scsi/leapraid/leapraid_func.h index 15293922aefa..359802578586 100644 --- a/drivers/scsi/leapraid/leapraid_func.h +++ b/drivers/scsi/leapraid/leapraid_func.h @@ -1,16 +1,16 @@ /* SPDX-License-Identifier: GPL-2.0 */ /* - * Copyright (C) 2025 LeapIO Tech Inc. + * Copyright (C) 2026 LeapIO Tech Inc. * - * LeapRAID Storage and RAID Controller driver. + * LeapRAID storage and RAID controller driver. */ - #ifndef LEAPRAID_FUNC_H_INCLUDED #define LEAPRAID_FUNC_H_INCLUDED #include <linux/pci.h> #include <linux/aer.h> #include <linux/poll.h> +#include <linux/atomic.h> #include <linux/errno.h> #include <linux/ktime.h> #include <linux/delay.h> @@ -27,9 +27,9 @@ #include "leapraid.h" -/* some requset and reply buffer size */ +/* Request and reply buffer size. */ #define LEAPRAID_REQUEST_SIZE 128 -#define LEAPRAID_REPLY_SIEZ 128 +#define LEAPRAID_REPLY_SIZE 128 #define LEAPRAID_CHAIN_SEG_SIZE 128 #define LEAPRAID_MAX_SGES_IN_CHAIN 7 #define LEAPRAID_DEFAULT_CHAINS_PER_IO 19 @@ -44,61 +44,68 @@ #define LEAPRAID_SYS_LOG_BUF_SIZE 0x200000 #define LEAPRAID_SYS_LOG_BUF_RESERVE 0x1000 -/* Driver version and name */ +/* Driver version and name. */ #define LEAPRAID_DRIVER_NAME "LeapRAID" #define LEAPRAID_NAME_LENGTH 48 +#define LEAPRAID_BOARD_NAME_LENGTH 17 #define LEAPRAID_AUTHOR "LeapIO Inc." #define LEAPRAID_DESCRIPTION "LeapRAID Driver" -#define LEAPRAID_DRIVER_VERSION "2.00.00.06" +#define LEAPRAID_DRIVER_VERSION "2.00.01.02" #define LEAPRAID_MAJOR_VERSION 2 #define LEAPRAID_MINOR_VERSION 00 -#define LEAPRAID_BUILD_VERSION 00 -#define LEAPRAID_RELEASE_VERSION 06 +#define LEAPRAID_BUILD_VERSION 01 +#define LEAPRAID_RELEASE_VERSION 02 +#define LEAPRAID_MSG_VERSION 0x1021 +#define LEAPRAID_HEADER_VERSION 0x0000 -/* Device ID */ +/* Device ID. */ #define LEAPRAID_VENDOR_ID 0xD405 #define LEAPRAID_DEVID_HBA 0x8200 -#define LEAPRAID_DEVID_RAID 0x8201 +#define LEAPRAID_SUBVENDOR_ID 0xD405 +#define LEAPRAID_SUBDEVID_HBA 0x8200 #define LEAPRAID_PCI_VENDOR_ID_MASK 0xFFFF - /* RAID virtual channel ID */ + /* RAID virtual channel ID. */ #define RAID_CHANNEL 1 -/* Scatter/Gather (SG) segment limits */ +/* Scatter-gather (SG) segment limits. */ #define LEAPRAID_MAX_PHYS_SEGMENTS SG_CHUNK_SIZE #define LEAPRAID_KDUMP_MIN_PHYS_SEGMENTS 32 #define LEAPRAID_SG_DEPTH LEAPRAID_MAX_PHYS_SEGMENTS -/* firmware / config page operations */ +/* Firmware and config page operations. */ #define LEAPRAID_SET_PARAMETER_SYNC_TIMESTAMP 0x81 #define LEAPRAID_CFG_REQ_RETRY_TIMES 2 -/* Hardware access helpers*/ +/* Hardware access helpers. */ #define leapraid_readl(addr) readl(addr) #define leapraid_check_reset(status) \ (!((status) & LEAPRAID_CMD_RESET)) -/* Polling intervals */ +/* Polling intervals. */ #define LEAPRAID_PCIE_LOG_POLLING_INTERVAL 1 #define LEAPRAID_FAULT_POLLING_INTERVAL 1000 #define LEAPRAID_TIMESTAMP_SYNC_INTERVAL 900 #define LEAPRAID_SMART_POLLING_INTERVAL (300 * 1000) -/* init mask */ +/* Init mask. */ #define LEAPRAID_RESET_IRQ_MASK 0x40000000 #define LEAPRAID_REPLY_INT_MASK 0x00000008 #define LEAPRAID_TO_SYS_DB_MASK 0x00000001 -/* queue depth */ +/* Queue depth. */ #define LEAPRAID_SATA_QUEUE_DEPTH 32 -#define LEAPRAID_SAS_QUEUE_DEPTH 254 -#define LEAPRAID_RAID_QUEUE_DEPTH 128 +#define LEAPRAID_SAS_QUEUE_DEPTH 64 +#define LEAPRAID_RAID_QUEUE_DEPTH 64 + +/* Target probe flag. */ +#define LEAPRAID_NO_ULD_ATTACH_FLAG 1 +#define LEAPRAID_ULD_ATTACH_FLAG 0 -/* SCSI device and queue limits */ -#define LEAPRAID_MAX_SECTORS 8192 -#define LEAPRAID_DEF_MAX_SECTORS 32767 +/* SCSI device and queue limits. */ +#define LEAPRAID_MAX_SECTORS 2048 #define LEAPRAID_MAX_CDB_LEN 32 #define LEAPRAID_MAX_LUNS 16384 #define LEAPRAID_CAN_QUEUE_MIN 1 @@ -106,136 +113,166 @@ #define LEAPRAID_CMD_PER_LUN 128 #define LEAPRAID_MAX_SEGMENT_SIZE 0xffffffff -/* SCSI sense and ASC/ASCQ and disk geometry configuration */ +/* SCSI sense and ASC/ASCQ and disk geometry configuration. */ #define DESC_FORMAT_THRESHOLD 0x72 #define SENSE_KEY_MASK 0x0F #define SCSI_SENSE_RESPONSE_CODE_MASK 0x7F #define ASC_FAILURE_PREDICTION_THRESHOLD_EXCEEDED 0x5D -#define LEAPRAID_LARGE_DISK_THRESHOLD 0x200000UL /* in sectors, 1GB */ +#define LEAPRAID_LARGE_DISK_THRESHOLD 0x200000UL #define LEAPRAID_LARGE_DISK_HEADS 255 #define LEAPRAID_LARGE_DISK_SECTORS 63 #define LEAPRAID_SMALL_DISK_HEADS 64 #define LEAPRAID_SMALL_DISK_SECTORS 32 -/* SMP (Serial Management Protocol) */ +/* SMP (Serial Management Protocol). */ #define LEAPRAID_SMP_PT_FLAG_SGL_PTR 0x80 #define LEAPRAID_SMP_FN_REPORT_PHY_ERR_LOG 0x91 #define LEAPRAID_SMP_FRAME_HEADER_SIZE 4 #define LEAPRAID_SCSI_HOST_SHIFT 16 #define LEAPRAID_SCSI_DRIVER_SHIFT 24 -/* SCSI ASC/ASCQ definitions */ +/* SCSI ASC/ASCQ definitions. */ #define LEAPRAID_SCSI_ASCQ_DEFAULT 0x00 #define LEAPRAID_SCSI_ASC_POWER_ON_RESET 0x29 #define LEAPRAID_SCSI_ASC_INVALID_CMD_CODE 0x20 #define LEAPRAID_SCSI_ASCQ_POWER_ON_RESET 0x07 -/* ---- VPD Page 0x89 (ATA Information) ---- */ +/* VPD Page 0x89 (ATA Information). */ #define LEAPRAID_VPD_PAGE_ATA_INFO 0x89 #define LEAPRAID_VPD_PG89_MAX_LEN 255 #define LEAPRAID_VPD_PG89_MIN_LEN 214 -/* Byte index for NCQ support flag in VPD Page 0x89 */ +/* Byte index for NCQ support flag in VPD page 0x89. */ #define LEAPRAID_VPD_PG89_NCQ_BYTE_IDX 213 #define LEAPRAID_VPD_PG89_NCQ_BIT_SHIFT 4 #define LEAPRAID_VPD_PG89_NCQ_BIT_MASK 0x1 -/* readiness polling: max retries, sleep µs between */ +/* Readiness polling: max retries, sleep µs between. */ #define LEAPRAID_ADAPTER_READY_MAX_RETRY 15000 #define LEAPRAID_ADAPTER_READY_SLEEP_MIN_US 1000 #define LEAPRAID_ADAPTER_READY_SLEEP_MAX_US 1100 -/* Doorbell wait parameters */ +/* Doorbell wait parameters. */ #define LEAPRAID_DB_WAIT_MAX_RETRY 20000 #define LEAPRAID_DB_WAIT_DELAY_US 500 -/* Basic data size definitions */ +/* Basic data size definitions. */ #define LEAPRAID_DWORDS_BYTE_SIZE 4 #define LEAPRAID_WORD_BYTE_SIZE 2 -/* SGL threshold and chain offset*/ +/* SGL threshold and chain offset. */ #define LEAPRAID_SGL_INLINE_THRESHOLD 2 #define LEAPRAID_CHAIN_OFFSET_DWORDS 7 -/* MSI-X group size and mask */ +/* MSI-X group size and mask. */ #define LEAPRAID_MSIX_GROUP_SIZE 8 #define LEAPRAID_MSIX_GROUP_MASK 7 -/* basic constants and limits */ +/* Basic constants and limits. */ #define LEAPRAID_BUSY_LIMIT 1 #define LEAPRAID_INDEX_FIRST 0 #define LEAPRAID_BITS_PER_BYTE 8 #define LEAPRAID_INVALID_HOST_DIAG_VAL 0xFFFFFFFF -/* retry / sleep configuration */ +/* Retry/Sleep configuration. */ +#define LEAPRAID_WRITE_SEQUENCE_OFFSET 0x4 +#define LEAPRAID_WRSEQ_KEY_VALUE_MASK 0xF +#define LEAPRAID_WRSEQ_FLUSH_KEY_VALUE 0x0 +#define LEAPRAID_WRSEQ_1ST_KEY_VALUE 0xF +#define LEAPRAID_WRSEQ_2ND_KEY_VALUE 0x4 +#define LEAPRAID_WRSEQ_3RD_KEY_VALUE 0xB +#define LEAPRAID_WRSEQ_4TH_KEY_VALUE 0x2 +#define LEAPRAID_WRSEQ_5TH_KEY_VALUE 0x7 +#define LEAPRAID_WRSEQ_6TH_KEY_VALUE 0xD #define LEAPRAID_UNLOCK_RETRY_LIMIT 20 #define LEAPRAID_UNLOCK_SLEEP_MS 100 #define LEAPRAID_MSLEEP_SHORT_MS 50 #define LEAPRAID_MSLEEP_NORMAL_MS 100 -#define LEAPRAID_MSLEEP_LONG_MS 256 #define LEAPRAID_MSLEEP_EXTRA_LONG_MS 500 #define LEAPRAID_IO_POLL_DELAY_US 500 -/* controller reset loop parameters */ -#define LEAPRAID_RESET_LOOP_COUNT_REF (300000 / 256) -#define LEAPRAID_RESET_LOOP_COUNT_DEFAULT 10000 -#define LEAPRAID_RESET_POLL_INTERVAL_MS 500 - -/* Device / Volume configuration */ +/* Device/Volume configuration. */ #define LEAPRAID_MAX_VOLUMES_DEFAULT 32 #define LEAPRAID_MAX_DEV_HANDLE_DEFAULT 2048 #define LEAPRAID_INVALID_DEV_HANDLE 0xFFFF -/* cmd queue depth */ +/* Commands queue depth. */ #define LEAPRAID_COALESCING_DEPTH_MAX 256 #define LEAPRAID_DEFAULT_CMD_QD_OFFSET 64 #define LEAPRAID_REPLY_QD_ALIGNMENT 16 -/* task id offset */ +/* Task ID offset. */ #define LEAPRAID_TASKID_OFFSET_CTRL_CMD 1 #define LEAPRAID_TASKID_OFFSET_SCSIIO_CMD 2 -#define LEAPRAID_TASKID_OFFSET_CFG_OP_CMD 1 +#define LEAPRAID_TASKID_OFFSET_CFG_OP_CMD 1 #define LEAPRAID_TASKID_OFFSET_TRANSPORT_CMD 2 #define LEAPRAID_TASKID_OFFSET_TIMESTAMP_SYNC_CMD 3 -#define LEAPRAID_TASKID_OFFSET_RAID_ACTION_CMD 4 -#define LEAPRAID_TASKID_OFFSET_ENC_CMD 5 -#define LEAPRAID_TASKID_OFFSET_NOTIFY_EVENT_CMD 6 +#define LEAPRAID_TASKID_OFFSET_ENC_CMD 4 +#define LEAPRAID_TASKID_OFFSET_NOTIFY_EVENT_CMD 5 -/* task id offset for high-priority */ +/* Task ID offset for high-priority. */ #define LEAPRAID_HP_TASKID_OFFSET_CTL_CMD 0 #define LEAPRAID_HP_TASKID_OFFSET_TM_CMD 1 -/* Event / Boot configuration */ +/* Event/Boot configuration. */ #define LEAPRAID_EVT_MASK_COUNT 4 #define LEAPRAID_BOOT_DEV_SIZE 24 -/* logsense command definitions */ +/* Commands timeout. */ +#define LEAPRAID_UNIFIED_TIMEOUT 30 +#define LEAPRAID_CFG_OP_TIMEOUT LEAPRAID_UNIFIED_TIMEOUT +#define LEAPRAID_CTL_CMD_TIMEOUT LEAPRAID_UNIFIED_TIMEOUT +#define LEAPRAID_SCAN_DEV_CMD_TIMEOUT 300 +#define LEAPRAID_TIMESTAMP_SYNC_CMD_TIMEOUT LEAPRAID_UNIFIED_TIMEOUT +#define LEAPRAID_RAID_ACTION_CMD_TIMEOUT LEAPRAID_UNIFIED_TIMEOUT +#define LEAPRAID_ENC_CMD_TIMEOUT LEAPRAID_UNIFIED_TIMEOUT +#define LEAPRAID_IO_CMD_TIMEOUT LEAPRAID_UNIFIED_TIMEOUT +#define LEAPRAID_NOTIFY_EVENT_CMD_TIMEOUT LEAPRAID_UNIFIED_TIMEOUT +#define LEAPRAID_TM_CMD_TIMEOUT LEAPRAID_UNIFIED_TIMEOUT +#define LEAPRAID_TRANSPORT_CMD_TIMEOUT LEAPRAID_UNIFIED_TIMEOUT + +/* Logsense command definitions. */ #define LEAPRAID_LOGSENSE_DATA_LENGTH 16 #define LEAPRAID_LOGSENSE_CDB_LENGTH 10 #define LEAPRAID_LOGSENSE_CDB_CODE 0x6F -#define LEAPRAID_LOGSENSE_TIMEOUT 5 +#define LEAPRAID_LOGSENSE_TIMEOUT LEAPRAID_UNIFIED_TIMEOUT #define LEAPRAID_LOGSENSE_SMART_CODE 0x5D -/* cmd timeout */ -#define LEAPRAID_DRIVER_SCSIIO_CMD_TIMEOUT LEAPRAID_LOGSENSE_TIMEOUT -#define LEAPRAID_CFG_OP_TIMEOUT 15 -#define LEAPRAID_CTL_CMD_TIMEOUT 10 -#define LEAPRAID_SCAN_DEV_CMD_TIMEOUT 300 -#define LEAPRAID_TIMESTAMP_SYNC_CMD_TIMEOUT 10 -#define LEAPRAID_RAID_ACTION_CMD_TIMEOUT 10 -#define LEAPRAID_ENC_CMD_TIMEOUT 10 -#define LEAPRAID_NOTIFY_EVENT_CMD_TIMEOUT 30 -#define LEAPRAID_TM_CMD_TIMEOUT 30 -#define LEAPRAID_TRANSPORT_CMD_TIMEOUT 10 +/* Host DMA cap. */ +#define DMA_32_BITS 32 +#define DMA_64_BITS 64 +#define LEAPRAID_DMA_ALIGN 16 + +/* Values used to represent an invalid. */ +#define LEAPRAID_INVALID_INDEX -1 +#define LEAPRAID_INVALID_MSIX_VECTORS -1 +#define LEAPRAID_INVALID_INITIAL_VALUE -1 +#define LEAPRAID_OPERATION_FAILED -1 + +/* Version shift and mask. */ +#define LEAPRAID_VER_MAJOR_SHIFT 24 +#define LEAPRAID_VER_MINOR_SHIFT 16 +#define LEAPRAID_VER_BUILD_SHIFT 8 +#define LEAPRAID_VER_MASK 0xFF + +/* Interrupt type. */ +#define LEAPRAID_INTERRUPT_MODE_MSIX 0 +#define LEAPRAID_INTERRUPT_MODE_MSI 1 +#define LEAPRAID_INTERRUPT_MODE_LEGACY 2 + +/* SMP link reset. */ +#define SMP_PHY_CONTROL_LINK_RESET 0x01 +#define SMP_PHY_CONTROL_HARD_RESET 0x02 +#define SMP_PHY_CONTROL_DISABLE 0x03 /** - * struct leapraid_adapter_features - Features and - * capabilities of a LeapRAID adapter + * struct leapraid_adapter_features - Adapter features/capabilities. * - * @req_slot: Number of request slots supported by the adapter - * @hp_slot: Number of high-priority slots supported by the adapter - * @adapter_caps: Adapter capabilities - * @fw_version: Firmware version of the adapter - * @max_dev_handle: Maximum device supported by the adapter + * @req_slot: Number of request slots supported by the adapter. + * @hp_slot: Number of high-priority slots supported by the adapter. + * @adapter_caps: Adapter capabilities. + * @fw_version: Firmware version of the adapter. + * @max_dev_handle: Maximum device handle supported by the adapter. + * @min_dev_handle: Minimum device handle supported by the adapter. */ struct leapraid_adapter_features { u16 req_slot; @@ -251,32 +288,35 @@ struct leapraid_adapter_features { /** * struct leapraid_adapter_attr - Adapter attributes and capabilities * - * @id: Adapter identifier - * @raid_support: Indicates if RAID is supported - * @bios_version: Version of the adapter BIOS - * @enable_mp: Indicates if multipath (MP) support is enabled - * @wideport_max_queue_depth: Maximum queue depth for wide ports - * @narrowport_max_queue_depth: Maximum queue depth for narrow ports - * @sata_max_queue_depth: Maximum queue depth for SATA - * @features: Detailed features of the adapter - * @adapter_total_qd: Total queue depth available on the adapter - * @io_qd: Queue depth allocated for I/O operations - * @rep_msg_qd: Queue depth for reply messages - * @rep_desc_qd: Queue depth for reply descriptors - * @rep_desc_q_seg_cnt: Number of segments in a reply descriptor queue - * @rq_cnt: Number of request queues - * @task_desc_dma_size: Size of task descriptor DMA memory - * @use_32_dma_mask: Indicates if 32-bit DMA mask is used - * @name: Adapter name string + * @id: Adapter identifier. + * @raid_support: Indicates if RAID is supported. + * @bios_version: Version of the adapter BIOS. + * @enable_mp: Indicates if multipath (MP) support is enabled. + * @wideport_max_queue_depth: Maximum queue depth for wide ports. + * @narrowport_max_queue_depth: Maximum queue depth for narrow ports. + * @sata_max_queue_depth: Maximum queue depth for SATA. + * @raid_volume_max_queue_depth: Maximum queue depth for RAID volumes. + * @features: Detailed features of the adapter. + * @adapter_total_qd: Total queue depth available on the adapter. + * @io_qd: Queue depth allocated for I/O operations. + * @rep_msg_qd: Queue depth for reply messages. + * @rep_desc_qd: Queue depth for reply descriptors. + * @rep_desc_q_seg_cnt: Number of segments in a reply descriptor queue. + * @rq_cnt: Number of request queues. + * @task_desc_dma_size: Size of task descriptor DMA memory. + * @use_32_dma_mask: Indicates if 32-bit DMA mask is used. + * @name: Adapter name string. + * @board_name: Board name retrieved from manufacturing page 0. */ struct leapraid_adapter_attr { u8 id; - bool raid_support; + u8 raid_support; u32 bios_version; - bool enable_mp; + u8 enable_mp; u32 wideport_max_queue_depth; u32 narrowport_max_queue_depth; u32 sata_max_queue_depth; + u32 raid_volume_max_queue_depth; struct leapraid_adapter_features features; u32 adapter_total_qd; u32 io_qd; @@ -285,20 +325,20 @@ struct leapraid_adapter_attr { u32 rep_desc_q_seg_cnt; u16 rq_cnt; u32 task_desc_dma_size; - bool use_32_dma_mask; + u8 use_32_dma_mask; char name[LEAPRAID_NAME_LENGTH]; + char board_name[LEAPRAID_BOARD_NAME_LENGTH]; }; /** - * struct leapraid_io_req_tracker - Track a SCSI I/O request - * for the adapter + * struct leapraid_io_req_tracker - Track a SCSI I/O request for the adapter * - * @taskid: Unique task ID for this I/O request - * @scmd: Pointer to the associated SCSI command - * @chain_list: List of chain frames associated with this request - * @msix_io: MSI-X vector assigned to this I/O request - * @chain: Pointer to the chain memory for this request - * @chain_dma: DMA address of the chain memory + * @taskid: Unique task ID for this I/O request. + * @scmd: Pointer to the associated SCSI command. + * @chain_list: List of chain frames associated with this request. + * @msix_io: MSI-X vector assigned to this I/O request. + * @chain: Pointer to the chain memory for this request. + * @chain_dma: DMA address of the chain memory. */ struct leapraid_io_req_tracker { u16 taskid; @@ -312,9 +352,9 @@ struct leapraid_io_req_tracker { /** * struct leapraid_task_tracker - Tracks a task in the adapter * - * @taskid: Unique task ID for this tracker - * @cb_idx: Callback index associated with this task - * @tracker_list: Linked list node to chain this tracker in lists + * @taskid: Unique task ID for this tracker. + * @cb_idx: Callback index associated with this task. + * @tracker_list: Linked list node to chain this tracker in lists. */ struct leapraid_task_tracker { u16 taskid; @@ -323,11 +363,10 @@ struct leapraid_task_tracker { }; /** - * struct leapraid_rep_desc_maint - Maintains reply descriptor - * memory + * struct leapraid_rep_desc_maint - Maintains reply descriptor memory * - * @rep_desc: Pointer to the reply descriptor - * @rep_desc_dma: DMA address of the reply descriptor + * @rep_desc: Pointer to the reply descriptor. + * @rep_desc_dma: DMA address of the reply descriptor. */ struct leapraid_rep_desc_maint { union leapraid_rep_desc_union *rep_desc; @@ -335,12 +374,12 @@ struct leapraid_rep_desc_maint { }; /** - * struct leapraid_rep_desc_seg_maint - Maintains reply descriptor - * segment memory + * struct leapraid_rep_desc_seg_maint - + * Maintains reply descriptor segment memory * - * @rep_desc_seg: Pointer to the reply descriptor segment - * @rep_desc_seg_dma: DMA address of the reply descriptor segment - * @rep_desc_maint: Pointer to the main reply descriptor structure + * @rep_desc_seg: Pointer to the reply descriptor segment. + * @rep_desc_seg_dma: DMA address of the reply descriptor segment. + * @rep_desc_maint: Pointer to the main reply descriptor structure. */ struct leapraid_rep_desc_seg_maint { void *rep_desc_seg; @@ -351,20 +390,20 @@ struct leapraid_rep_desc_seg_maint { /** * struct leapraid_mem_desc - Memory descriptor for LeapRAID adapter * - * @task_desc: Pointer to task descriptor - * @task_desc_dma: DMA address of task descriptor - * @sg_chain_pool: DMA pool for SGL chain allocations - * @sg_chain_pool_size: Size of the sg_chain_pool - * @io_tracker: IO request tracker array - * @sense_data: Buffer for SCSI sense data - * @sense_data_dma: DMA address of sense_data buffer - * @rep_msg: Buffer for reply message - * @rep_msg_dma: DMA address of reply message buffer - * @rep_msg_addr: Pointer to reply message address - * @rep_msg_addr_dma: DMA address of reply message address - * @rep_desc_seg_maint: Pointer to reply descriptor segment - * @rep_desc_q_arr: Pointer to reply descriptor queue array - * @rep_desc_q_arr_dma: DMA address of reply descriptor queue array + * @task_desc: Pointer to task descriptor. + * @task_desc_dma: DMA address of task descriptor. + * @sg_chain_pool: DMA pool for SGL chain allocations. + * @sg_chain_pool_size: Size of the sg_chain_pool. + * @io_tracker: I/O request tracker array. + * @sense_data: Buffer for SCSI sense data. + * @sense_data_dma: DMA address of sense_data buffer. + * @rep_msg: Buffer for reply message. + * @rep_msg_dma: DMA address of reply message buffer. + * @rep_msg_addr: Pointer to reply message address. + * @rep_msg_addr_dma: DMA address of reply message address. + * @rep_desc_seg_maint: Pointer to reply descriptor segment. + * @rep_desc_q_arr: Pointer to reply descriptor queue array. + * @rep_desc_q_arr_dma: DMA address of reply descriptor queue array. */ struct leapraid_mem_desc { void *task_desc; @@ -383,31 +422,30 @@ struct leapraid_mem_desc { dma_addr_t rep_desc_q_arr_dma; }; -#define LEAPRAID_FIXED_INTER_CMDS 7 -#define LEAPRAID_FIXED_HP_CMDS 2 -#define LEAPRAID_INTER_HP_CMDS_DIF \ - (LEAPRAID_FIXED_INTER_CMDS - LEAPRAID_FIXED_HP_CMDS) +/* internal cmd description */ +#define LEAPRAID_FIXED_INTER_CMDS 6 +#define LEAPRAID_FIXED_HP_CMDS 2 -#define LEAPRAID_CMD_NOT_USED 0x8000 -#define LEAPRAID_CMD_DONE 0x0001 -#define LEAPRAID_CMD_PENDING 0x0002 -#define LEAPRAID_CMD_REPLY_VALID 0x0004 -#define LEAPRAID_CMD_RESET 0x0008 +#define LEAPRAID_CMD_NOT_USED 0x8000 +#define LEAPRAID_CMD_DONE 0x0001 +#define LEAPRAID_CMD_PENDING 0x0002 +#define LEAPRAID_CMD_REPLY_VALID 0x0004 +#define LEAPRAID_CMD_RESET 0x0008 /** * enum LEAPRAID_CB_INDEX - Callback index for LeapRAID driver * - * @LEAPRAID_SCAN_DEV_CB_IDX: Scan device callback index - * @LEAPRAID_CONFIG_CB_IDX: Configuration callback index - * @LEAPRAID_TRANSPORT_CB_IDX: Transport callback index - * @LEAPRAID_TIMESTAMP_SYNC_CB_IDX: Timestamp sync callback index - * @LEAPRAID_RAID_ACTION_CB_IDX: RAID action callback index - * @LEAPRAID_DRIVER_SCSIIO_CB_IDX: Driver SCSI I/O callback index - * @LEAPRAID_SAS_CTRL_CB_IDX: SAS controller callback index - * @LEAPRAID_ENC_CB_IDX: Encryption callback index - * @LEAPRAID_NOTIFY_EVENT_CB_IDX: Notify event callback index - * @LEAPRAID_CTL_CB_IDX: Control callback index - * @LEAPRAID_TM_CB_IDX: Task management callback index + * @LEAPRAID_SCAN_DEV_CB_IDX: Scan device callback index. + * @LEAPRAID_CONFIG_CB_IDX: Configuration callback index. + * @LEAPRAID_TRANSPORT_CB_IDX: Transport callback index. + * @LEAPRAID_TIMESTAMP_SYNC_CB_IDX: Timestamp sync callback index. + * @LEAPRAID_RAID_ACTION_CB_IDX: RAID action callback index. + * @LEAPRAID_DRIVER_SCSIIO_CB_IDX: Driver SCSI I/O callback index. + * @LEAPRAID_SAS_CTRL_CB_IDX: SAS controller callback index. + * @LEAPRAID_ENC_CB_IDX: Encryption callback index. + * @LEAPRAID_NOTIFY_EVENT_CB_IDX: Notify event callback index. + * @LEAPRAID_CTL_CB_IDX: Control callback index. + * @LEAPRAID_TM_CB_IDX: Task management callback index. */ enum LEAPRAID_CB_INDEX { LEAPRAID_SCAN_DEV_CB_IDX = 0x1, @@ -424,10 +462,25 @@ enum LEAPRAID_CB_INDEX { LEAPRAID_NUM_CB_IDXS }; +/** + * struct leapraid_default_reply - Default reply frame buffer + * @pad: Raw reply data buffer returned by firmware. + * + * This structure represents a generic reply frame used by the firmware + * when no specific reply format is required. The buffer size is defined + * by LEAPRAID_REPLY_SIZE and stores the raw reply data. + */ struct leapraid_default_reply { - u8 pad[LEAPRAID_REPLY_SIEZ]; + u8 pad[LEAPRAID_REPLY_SIZE]; }; +/** + * struct leapraid_sense_buffer - SCSI sense data buffer + * @pad: Buffer used to store sense data returned by a SCSI command. + * + * This buffer holds the sense data provided by a device.The size is + * defined by SCSI_SENSE_BUFFERSIZE. + */ struct leapraid_sense_buffer { u8 pad[SCSI_SENSE_BUFFERSIZE]; }; @@ -435,17 +488,17 @@ struct leapraid_sense_buffer { /** * struct leapraid_driver_cmd - Driver command tracking structure * - * @reply: Default reply structure returned by the adapter - * @done: Completion object used to signal command completion - * @status: Status code returned by the firmware - * @taskid: Unique task identifier for this command - * @hp_taskid: Task identifier for high-priority commands - * @inter_taskid: Task identifier for internal commands - * @cb_idx: Callback index used to identify completion context - * @async_scan_dev: True if this command is for asynchronous device scan - * @sense: Sense buffer holding error information from device - * @mutex: Mutex to protect access to this command structure - * @list: List node for linking driver commands into lists + * @reply: Default reply structure returned by the adapter. + * @done: Completion object used to signal command completion. + * @status: Status code returned by the firmware. + * @taskid: Unique task identifier for this command. + * @hp_taskid: Task identifier for high-priority commands. + * @inter_taskid: Task identifier for internal commands. + * @cb_idx: Callback index used to identify completion context. + * @async_scan_dev: True if this command is for asynchronous device scan. + * @sense: Sense buffer holding error information from device. + * @mutex: Mutex to protect access to this command structure. + * @list: List node for linking driver commands into lists. */ struct leapraid_driver_cmd { struct leapraid_default_reply reply; @@ -455,27 +508,27 @@ struct leapraid_driver_cmd { u16 hp_taskid; u16 inter_taskid; u8 cb_idx; - bool async_scan_dev; + u8 async_scan_dev; struct leapraid_sense_buffer sense; - struct mutex mutex; + struct mutex mutex; /* Mutex for driver cmd */ struct list_head list; }; /** * struct leapraid_driver_cmds - Collection of driver command objects * - * @special_cmd_list: List head for tracking special driver commands - * @scan_dev_cmd: Command used for asynchronous device scan operations - * @cfg_op_cmd: Command for configuration operations - * @transport_cmd: Command for transport-level operations - * @timestamp_sync_cmd: Command for synchronizing timestamp with firmware - * @raid_action_cmd: Command for RAID-related management or action requests - * @driver_scsiio_cmd: Command used for internal SCSI I/O processing - * @enc_cmd: Command for enclosure management operations - * @notify_event_cmd: Command for asynchronous event notification handling - * @ctl_cmd: Command for generic control or maintenance operations - * @tm_cmd: Task management command - * @internal_scmd: Pointer to internal SCSI command used by the driver + * @special_cmd_list: List head for tracking special driver commands. + * @scan_dev_cmd: Command used for asynchronous device scan operations. + * @cfg_op_cmd: Command for configuration operations. + * @transport_cmd: Command for transport-level operations. + * @timestamp_sync_cmd: Command for synchronizing timestamp with firmware. + * @raid_action_cmd: Command for RAID-related management or action requests. + * @driver_scsiio_cmd: Command used for internal SCSI I/O processing. + * @enc_cmd: Command for enclosure management operations. + * @notify_event_cmd: Command for asynchronous event notification handling. + * @ctl_cmd: Command for generic control or maintenance operations. + * @tm_cmd: Task management command. + * @internal_scmd: Pointer to internal SCSI command used by the driver. */ struct leapraid_driver_cmds { struct list_head special_cmd_list; @@ -495,14 +548,14 @@ struct leapraid_driver_cmds { /** * struct leapraid_dynamic_task_desc - Dynamic task descriptor * - * @task_lock: Spinlock to protect concurrent access - * @hp_taskid: Current high-priority task ID - * @hp_cmd_qd: Fixed command queue depth for high-priority tasks - * @inter_taskid: Current internal task ID - * @inter_cmd_qd: Fixed command queue depth for internal tasks + * @task_lock: Spinlock to protect concurrent access. + * @hp_taskid: Current high-priority task ID. + * @hp_cmd_qd: Fixed command queue depth for high-priority tasks. + * @inter_taskid: Current internal task ID. + * @inter_cmd_qd: Fixed command queue depth for internal tasks. */ struct leapraid_dynamic_task_desc { - spinlock_t task_lock; + spinlock_t task_lock; /* protects dynamic task */ u16 hp_taskid; u16 hp_cmd_qd; u16 inter_taskid; @@ -512,14 +565,14 @@ struct leapraid_dynamic_task_desc { /** * struct leapraid_fw_evt_work - Firmware event work structure * - * @list: Linked list node for queuing the work - * @adapter: Pointer to the associated LeapRAID adapter - * @work: Work structure used by the kernel workqueue - * @refcnt: Reference counter for managing the lifetime of this work - * @evt_data: Pointer to firmware event data - * @dev_handle: Device handle associated with the event - * @evt_type: Type of firmware event - * @ignore: Flag indicating whether the event should be ignored + * @list: Linked list node for queuing the work. + * @adapter: Pointer to the associated LeapRAID adapter. + * @work: Work structure used by the kernel workqueue. + * @refcnt: Reference counter for managing the lifetime of this work. + * @evt_data: Pointer to firmware event data. + * @dev_handle: Device handle associated with the event. + * @evt_type: Type of firmware event. + * @ignore: Flag indicating whether the event should be ignored. */ struct leapraid_fw_evt_work { struct list_head list; @@ -535,33 +588,35 @@ struct leapraid_fw_evt_work { /** * struct leapraid_fw_evt_struct - Firmware event handling structure * - * @fw_evt_name: Name of the firmware event - * @fw_evt_thread: Workqueue used for processing firmware events - * @fw_evt_lock: Spinlock protecting access to the firmware event list - * @fw_evt_list: Linked list of pending firmware events - * @cur_evt: Pointer to the currently processing firmware event - * @fw_evt_cleanup: Flag indicating whether cleanup of events is in progress - * @leapraid_evt_masks: Array of event masks for filtering firmware events + * @fw_evt_name: Name of the firmware event. + * @fw_evt_thread: Workqueue used for processing firmware events. + * @fw_evt_lock: Spinlock protecting access to the firmware event list. + * @fw_evt_list: Linked list of pending firmware events. + * @cur_evt: Pointer to the currently processing firmware event. + * @cur_evt_task: Task currently executing @cur_evt work. + * @fw_evt_cleanup: Flag indicating whether cleanup of events is in progress. + * @leapraid_evt_masks: Array of event masks for filtering firmware events. */ struct leapraid_fw_evt_struct { char fw_evt_name[48]; struct workqueue_struct *fw_evt_thread; - spinlock_t fw_evt_lock; + spinlock_t fw_evt_lock; /* protects firmware event */ struct list_head fw_evt_list; struct leapraid_fw_evt_work *cur_evt; - int fw_evt_cleanup; + struct task_struct *cur_evt_task; + u8 fw_evt_cleanup; u32 leapraid_evt_masks[4]; }; /** * struct leapraid_rq - Represents a LeapRAID request queue * - * @adapter: Pointer to the associated LeapRAID adapter - * @msix_idx: MSI-X vector index used by this queue - * @rep_post_host_idx: Index of the last processed reply descriptor - * @rep_desc: Pointer to the reply descriptor associated with this queue - * @name: Name of the request queue - * @busy: Atomic counter indicating if the queue is busy + * @adapter: Pointer to the associated LeapRAID adapter. + * @msix_idx: MSI-X vector index used by this queue. + * @rep_post_host_idx: Index of the last processed reply descriptor. + * @rep_desc: Pointer to the reply descriptor associated with this queue. + * @name: Name of the request queue. + * @busy: Atomic counter indicating if the queue is busy. */ struct leapraid_rq { struct leapraid_adapter *adapter; @@ -575,8 +630,8 @@ struct leapraid_rq { /** * struct leapraid_int_rq - Internal request queue for a CPU * - * @affinity_hint: CPU affinity mask for the queue - * @rq: Underlying LeapRAID request queue structure + * @affinity_hint: CPU affinity mask for the queue. + * @rq: Underlying LeapRAID request queue structure. */ struct leapraid_int_rq { cpumask_var_t affinity_hint; @@ -586,9 +641,9 @@ struct leapraid_int_rq { /** * struct leapraid_blk_mq_poll_rq - Polling request for LeapRAID blk-mq * - * @busy: Atomic flag indicating request is being processed - * @pause: Atomic flag to temporarily suspend polling - * @rq: The underlying LeapRAID request structure + * @busy: Atomic flag indicating request is being processed. + * @pause: Atomic flag to temporarily suspend polling. + * @rq: The underlying LeapRAID request structure. */ struct leapraid_blk_mq_poll_rq { atomic_t busy; @@ -597,22 +652,25 @@ struct leapraid_blk_mq_poll_rq { }; /** - * struct leapraid_notification_desc - Notification - * descriptor for LeapRAID + * struct leapraid_notification_desc - Notification descriptor for LeapRAID * - * @iopoll_qdex: Index of the I/O polling queue - * @iopoll_qcnt: Count of I/O polling queues - * @msix_enable: Flag indicating MSI-X is enabled - * @msix_cpu_map: CPU map for MSI-X interrupts - * @msix_cpu_map_sz: Size of the MSI-X CPU map - * @int_rqs: Array of interrupt request queues - * @int_rqs_allocated: Count of allocated interrupt request queues - * @blk_mq_poll_rqs: Array of blk-mq polling requests + * @iopoll_qdex: Index of the I/O polling queue. + * @iopoll_qcnt: Count of I/O polling queues. + * @msix_enable: Flag indicating MSI-X is enabled. + * @irq_vectors_allocated: Flag indicating PCI IRQ vectors are allocated. + * @irq_mode: Actual interrupt mode used for allocated PCI IRQ vectors. + * @msix_cpu_map: CPU map for MSI-X interrupts. + * @msix_cpu_map_sz: Size of the MSI-X CPU map. + * @int_rqs: Array of interrupt request queues. + * @int_rqs_allocated: Count of allocated interrupt request queues. + * @blk_mq_poll_rqs: Array of blk-mq polling requests. */ struct leapraid_notification_desc { u32 iopoll_qdex; u32 iopoll_qcnt; - bool msix_enable; + u8 msix_enable; + u8 irq_vectors_allocated; + u8 irq_mode; u8 *msix_cpu_map; u32 msix_cpu_map_sz; struct leapraid_int_rq *int_rqs; @@ -620,82 +678,104 @@ struct leapraid_notification_desc { struct leapraid_blk_mq_poll_rq *blk_mq_poll_rqs; }; +/** + * struct leapraid_overheat_desc - Overheat descriptor for LeapRAID + * + * @fault_overheat_wq: Workqueue for adapter thermal overheat operations. + * @fault_overheat_work: Work structure for thermal overheat. + * @thermal_alert: Flag indicating if adapter thermal alert is active. + * @fault_overheat_wq_name: Name of the fault overheat workqueue. + */ +struct leapraid_overheat_desc { + struct workqueue_struct *fault_overheat_wq; + struct work_struct fault_overheat_work; + atomic_t thermal_alert; + char fault_overheat_wq_name[48]; +}; + /** * struct leapraid_reset_desc - Reset descriptor for LeapRAID * - * @fault_reset_wq: Workqueue for fault reset operations - * @fault_reset_work: Delayed work structure for fault reset - * @fault_reset_wq_name: Name of the fault reset workqueue - * @host_diag_mutex: Mutex for host diagnostic operations - * @adapter_reset_lock: Spinlock for adapter reset operations - * @adapter_reset_mutex: Mutex for adapter reset operations - * @adapter_link_resetting: Flag indicating if adapter link is resetting - * @adapter_reset_results: Results of the adapter reset operation - * @pending_io_cnt: Count of pending I/O operations - * @reset_wait_queue: Wait queue for reset operations - * @reset_cnt: Counter for reset operations + * @fault_reset_wq: Workqueue for fault reset operations. + * @fault_reset_work: Delayed work structure for fault reset. + * @fault_reset_wq_name: Name of the fault reset workqueue. + * @host_diag_mutex: Mutex for host diagnostic operations. + * @adapter_reset_lock: Spinlock for adapter reset operations. + * @adapter_reset_mutex: Mutex for adapter reset operations. + * @adapter_link_resetting: Flag indicating if adapter link is resetting. + * @adapter_reset_results: Results of the adapter reset operation. + * @pending_io_cnt: Count of pending I/O operations. + * @reset_wait_queue: Wait queue for reset operations. + * @reset_cnt: Counter for reset operations. + * @last_reset_cnt: Last observed adapter reset counter. */ struct leapraid_reset_desc { struct workqueue_struct *fault_reset_wq; struct delayed_work fault_reset_work; char fault_reset_wq_name[48]; - struct mutex host_diag_mutex; - spinlock_t adapter_reset_lock; - struct mutex adapter_reset_mutex; - bool adapter_link_resetting; + struct mutex host_diag_mutex; /* Mutex for operations. */ + spinlock_t adapter_reset_lock; /* Protects adapter reset state. */ + struct mutex adapter_reset_mutex; /* Serializes adapter reset. */ + u8 adapter_link_resetting; int adapter_reset_results; int pending_io_cnt; wait_queue_head_t reset_wait_queue; u32 reset_cnt; + u32 last_reset_cnt; }; /** - * struct leapraid_scan_dev_desc - Scan device descriptor - * for LeapRAID + * struct leapraid_scan_dev_desc - Scan device descriptor for LeapRAID * - * @wait_scan_dev_done: Flag indicating if scan device operation is done - * @driver_loading: Flag indicating if driver is loading - * @first_scan_dev_fired: Flag indicating if first scan device operation fired - * @scan_dev_failed: Flag indicating if scan device operation failed - * @scan_start: Flag indicating if scan operation started - * @scan_start_failed: Count of failed scan start operations + * @wait_scan_dev_done: Flag indicating if scan device operation is done. + * @driver_loading: Flag indicating if driver is loading. + * @first_scan_dev_fired: Flag indicating if first scan device operation fired. + * @scan_dev_failed: Flag indicating if scan device operation failed. + * @scan_start: Flag indicating if scan operation started. + * @scan_start_failed: Count of failed scan start operations. */ struct leapraid_scan_dev_desc { - bool wait_scan_dev_done; - bool driver_loading; - bool first_scan_dev_fired; - bool scan_dev_failed; - bool scan_start; + u8 wait_scan_dev_done; + u8 driver_loading; + wait_queue_head_t wait_driver_loading; + u8 first_scan_dev_fired; + u8 scan_dev_failed; + u8 scan_start; u16 scan_start_failed; }; /** * struct leapraid_access_ctrl - Access control structure for LeapRAID * - * @pci_access_lock: Mutex for PCI access control - * @adapter_thermal_alert: Flag indicating if adapter thermal alert is active - * @shost_recovering: Flag indicating if host is recovering - * @host_removing: Flag indicating if host is being removed - * @pcie_recovering: Flag indicating if PCIe is recovering + * @pci_access_lock: Mutex for PCI access control. + * @shost_recovering: Flag indicating if host is recovering. + * @shost_recover_async: Flag indicating if host is recovering + * and the 0xFFFF event. + * @shost_recover_wq: Wait queue for threads waiting on shost_recover_async. + * @host_removing: Flag indicating if host is being removed. + * @pcie_recovering: Flag indicating if PCIe is recovering. */ struct leapraid_access_ctrl { - struct mutex pci_access_lock; - bool adapter_thermal_alert; - bool shost_recovering; - bool host_removing; - bool pcie_recovering; + struct mutex pci_access_lock; /* serializes PCI register access. */ + u8 shost_recovering; + wait_queue_head_t recovery_waitq; + u8 shost_recover_async; + wait_queue_head_t shost_recover_wq; + u8 host_removing; + u8 pcie_recovering; }; /** * struct leapraid_fw_log_desc - Firmware log descriptor for LeapRAID * - * @fw_log_buffer: Buffer for firmware log data - * @fw_log_buffer_dma: DMA address of the firmware log buffer - * @fw_log_wq_name: Name of the firmware log workqueue - * @fw_log_wq: Workqueue for firmware log operations - * @fw_log_work: Delayed work structure for firmware log - * @open_pcie_trace: Flag indicating if PCIe tracing is open - * @fw_log_init_flag: Flag indicating if firmware log is initialized + * @fw_log_buffer: Buffer for firmware log data. + * @fw_log_buffer_dma: DMA address of the firmware log buffer. + * @fw_log_wq_name: Name of the firmware log workqueue. + * @fw_log_wq: Workqueue for firmware log operations. + * @fw_log_work: Delayed work structure for firmware log. + * @open_pcie_trace: Flag indicating if PCIe tracing is open. + * @fw_log_init_flag: Flag indicating if firmware log is initialized. + * @pre_debug_log: Last DebugLog register snapshot for change detection. */ struct leapraid_fw_log_desc { u8 *fw_log_buffer; @@ -705,6 +785,7 @@ struct leapraid_fw_log_desc { struct delayed_work fw_log_work; int open_pcie_trace; int fw_log_init_flag; + u32 pre_debug_log[LEAPRAID_DEBUGLOG_SZ_MAX]; }; #define LEAPRAID_CARD_PORT_FLG_DIRTY 0x01 @@ -713,13 +794,13 @@ struct leapraid_fw_log_desc { /** * struct leapraid_card_port - Card port structure for LeapRAID * - * @list: List head for card port - * @vphys_list: List head for virtual phy list - * @port_id: Port ID - * @sas_address: SAS address - * @phy_mask: Mask of phy - * @vphys_mask: Mask of virtual phy - * @flg: Flags for the port + * @list: List head for card port. + * @vphys_list: List head for virtual PHY list. + * @port_id: Port ID. + * @sas_address: SAS address. + * @phy_mask: Mask of PHY. + * @vphys_mask: Mask of virtual PHY. + * @flg: Flags for the port. */ struct leapraid_card_port { struct list_head list; @@ -732,18 +813,18 @@ struct leapraid_card_port { }; /** - * struct leapraid_card_phy - Card phy structure for LeapRAID + * struct leapraid_card_phy - Card PHY structure for LeapRAID * - * @port_siblings: List head for port siblings - * @card_port: Pointer to the card port - * @identify: SAS identify structure - * @remote_identify: Remote SAS identify structure - * @phy: SAS phy structure - * @phy_id: Phy ID - * @hdl: Handle for the port - * @attached_hdl: Handle for the attached port - * @phy_is_assigned: Flag indicating if phy is assigned - * @vphy: Flag indicating if virtual phy + * @port_siblings: List head for port siblings. + * @card_port: Pointer to the card port. + * @identify: SAS identify structure. + * @remote_identify: Remote SAS identify structure. + * @phy: SAS PHY structure. + * @phy_id: PHY ID. + * @hdl: Handle for the port. + * @attached_hdl: Handle for the attached port. + * @phy_is_assigned: Flag indicating if PHY is assigned. + * @vphy: Flag indicating if virtual PHY. */ struct leapraid_card_phy { struct list_head port_siblings; @@ -754,26 +835,26 @@ struct leapraid_card_phy { u8 phy_id; u16 hdl; u16 attached_hdl; - bool phy_is_assigned; - bool vphy; + u8 phy_is_assigned; + u8 vphy; }; /** * struct leapraid_topo_node - SAS topology node for LeapRAID * - * @list: List head for linking nodes - * @sas_port_list: List of SAS ports - * @card_port: Associated card port - * @card_phy: Associated card PHY - * @rphy: SAS remote PHY device - * @parent_dev: Parent device pointer - * @sas_address: SAS address of this node - * @sas_address_parent: Parent node's SAS address - * @phys_num: Number of physical links - * @hdl: Handle identifier - * @enc_hdl: Enclosure handle - * @enc_lid: Enclosure logical identifier - * @resp: Response status flag + * @list: List head for linking nodes. + * @sas_port_list: List of SAS ports. + * @card_port: Associated card port. + * @card_phy: Associated card PHY. + * @rphy: SAS remote PHY device. + * @parent_dev: Parent device pointer. + * @sas_address: SAS address of this node. + * @sas_address_parent: Parent node's SAS address. + * @phys_num: Number of physical links. + * @hdl: Handle identifier. + * @enc_hdl: Enclosure handle. + * @enc_lid: Enclosure logical identifier. + * @resp: Response status flag. */ struct leapraid_topo_node { struct list_head list; @@ -788,32 +869,32 @@ struct leapraid_topo_node { u16 hdl; u16 enc_hdl; u64 enc_lid; - bool resp; + u8 resp; }; /** * struct leapraid_dev_topo - LeapRAID device topology management structure * - * @topo_node_lock: Spinlock for protecting topology node operations - * @sas_dev_lock: Spinlock for SAS device list access - * @raid_volume_lock: Spinlock for RAID volume list access - * @sas_id: SAS domain identifier - * @card: Main card topology node - * @exp_list: List of expander devices - * @enc_list: List of enclosure devices - * @sas_dev_list: List of SAS devices - * @sas_dev_init_list: List of SAS devices being initialized - * @raid_volume_list: List of RAID volumes - * @card_port_list: List of card ports - * @pd_hdls: Array of physical disk handles - * @dev_removing: Array tracking devices being removed - * @pending_dev_add: Array tracking devices pending addition - * @blocking_hdls: Array of blocking handles + * @topo_node_lock: Spinlock for protecting topology node operations. + * @sas_dev_lock: Spinlock for SAS device list access. + * @raid_volume_lock: Spinlock for RAID volume list access. + * @enc_lock: Spinlock for enclosure device list access. + * @sas_id: SAS domain identifier. + * @card: Main card topology node. + * @exp_list: List of expander devices. + * @enc_list: List of enclosure devices. + * @sas_dev_list: List of SAS devices. + * @sas_dev_init_list: List of SAS devices being initialized. + * @raid_volume_list: List of RAID volumes. + * @card_port_list: List of card ports. + * @pd_hdls: Array of physical disk handles. + * @blocking_hdls: Array of blocking handles. */ struct leapraid_dev_topo { - spinlock_t topo_node_lock; - spinlock_t sas_dev_lock; - spinlock_t raid_volume_lock; + spinlock_t topo_node_lock; /* Protects topology node. */ + spinlock_t sas_dev_lock; /* Protects SAS device list access. */ + spinlock_t raid_volume_lock; /* Protects RAID volume list access. */ + spinlock_t enc_lock; /* Protects enclosure device list access. */ int sas_id; struct leapraid_topo_node card; struct list_head exp_list; @@ -823,21 +904,17 @@ struct leapraid_dev_topo { struct list_head raid_volume_list; struct list_head card_port_list; u16 pd_hdls_sz; - void *pd_hdls; - void *blocking_hdls; - u16 pending_dev_add_sz; - void *pending_dev_add; - u16 dev_removing_sz; - void *dev_removing; + unsigned long *pd_hdls; + unsigned long *blocking_hdls; }; /** * struct leapraid_boot_dev - Boot device structure for LeapRAID * - * @dev: Device pointer - * @chnl: Channel number - * @form: Form factor - * @pg_dev: Config page device content + * @dev: Device pointer. + * @chnl: Channel number. + * @form: Form factor. + * @pg_dev: Config page device content. */ struct leapraid_boot_dev { void *dev; @@ -848,11 +925,14 @@ struct leapraid_boot_dev { /** * struct leapraid_boot_devs - Boot device management structure - * @requested_boot_dev: Requested primary boot device - * @requested_alt_boot_dev: Requested alternate boot device - * @current_boot_dev: Currently active boot device + * + * @lock: Spinlock protecting boot device cache access. + * @requested_boot_dev: Requested primary boot device. + * @requested_alt_boot_dev: Requested alternate boot device. + * @current_boot_dev: Currently active boot device. */ struct leapraid_boot_devs { + spinlock_t lock; /* protects boot dev */ struct leapraid_boot_dev requested_boot_dev; struct leapraid_boot_dev requested_alt_boot_dev; struct leapraid_boot_dev current_boot_dev; @@ -860,9 +940,10 @@ struct leapraid_boot_devs { /** * struct leapraid_smart_poll_desc - SMART polling descriptor - * @smart_poll_wq: Workqueue for SMART polling tasks - * @smart_poll_work: Delayed work for SMART polling operations - * @smart_poll_wq_name: Workqueue name string + * + * @smart_poll_wq: Workqueue for SMART polling tasks. + * @smart_poll_work: Delayed work for SMART polling operations. + * @smart_poll_wq_name: Workqueue name string. */ struct leapraid_smart_poll_desc { struct workqueue_struct *smart_poll_wq; @@ -872,26 +953,28 @@ struct leapraid_smart_poll_desc { /** * struct leapraid_adapter - Main LeapRAID adapter structure - * @list: List head for adapter management - * @shost: SCSI host structure - * @pdev: PCI device structure - * @iomem_base: I/O memory mapped base address - * @rep_msg_host_idx: Host index for reply messages - * @mask_int: Interrupt masking flag - * @timestamp_sync_cnt: Timestamp synchronization counter - * @adapter_attr: Adapter attributes - * @mem_desc: Memory descriptor - * @driver_cmds: Driver commands - * @dynamic_task_desc: Dynamic task descriptor - * @fw_evt_s: Firmware event structure - * @notification_desc: Notification descriptor - * @reset_desc: Reset descriptor - * @scan_dev_desc: Device scan descriptor - * @access_ctrl: Access control - * @fw_log_desc: Firmware log descriptor - * @dev_topo: Device topology - * @boot_devs: Boot devices - * @smart_poll_desc: SMART polling descriptor + * + * @list: List head for adapter management. + * @shost: SCSI host structure. + * @pdev: PCI device structure. + * @iomem_base: I/O memory mapped base address. + * @rep_msg_host_idx: Host index for reply messages. + * @mask_int: Interrupt masking flag. + * @timestamp_sync_cnt: Timestamp synchronization counter. + * @adapter_attr: Adapter attributes. + * @mem_desc: Memory descriptor. + * @driver_cmds: Driver commands. + * @dynamic_task_desc: Dynamic task descriptor. + * @fw_evt_s: Firmware event structure. + * @notification_desc: Notification descriptor. + * @reset_desc: Reset descriptor. + * @scan_dev_desc: Device scan descriptor. + * @access_ctrl: Access control. + * @fw_log_desc: Firmware log descriptor. + * @dev_topo: Device topology. + * @boot_devs: Boot devices. + * @smart_poll_desc: SMART polling descriptor. + * @overheat_desc: Overheat processing descriptor. */ struct leapraid_adapter { struct list_head list; @@ -899,7 +982,7 @@ struct leapraid_adapter { struct pci_dev *pdev; struct leapraid_reg_base __iomem *iomem_base; u32 rep_msg_host_idx; - bool mask_int; + u8 mask_int; u32 timestamp_sync_cnt; struct leapraid_adapter_attr adapter_attr; @@ -915,6 +998,7 @@ struct leapraid_adapter { struct leapraid_dev_topo dev_topo; struct leapraid_boot_devs boot_devs; struct leapraid_smart_poll_desc smart_poll_desc; + struct leapraid_overheat_desc overheat_desc; }; union cfg_param_1 { @@ -931,6 +1015,7 @@ union cfg_param_2 { enum config_page_action { GET_BIOS_PG2, GET_BIOS_PG3, + GET_MANUFACTURING_PG0, GET_SAS_DEVICE_PG0, GET_SAS_IOUNIT_PG0, GET_SAS_IOUNIT_PG1, @@ -945,8 +1030,9 @@ enum config_page_action { /** * struct leapraid_enc_node - Enclosure node structure - * @list: List head for enclosure management - * @pg0: Enclosure page 0 data + * + * @list: List head for enclosure management. + * @pg0: Enclosure page 0 data. */ struct leapraid_enc_node { struct list_head list; @@ -955,20 +1041,23 @@ struct leapraid_enc_node { /** * struct leapraid_raid_volume - RAID volume structure - * @list: List head for volume management - * @starget: SCSI target structure - * @sdev: SCSI device structure - * @id: Volume ID - * @channel: SCSI channel - * @wwid: World Wide Identifier - * @hdl: Volume handle - * @vol_type: Volume type - * @pd_num: Number of physical disks - * @resp: Response status - * @dev_info: Device information + * + * @list: List head for volume management. + * @refcnt: Reference count. + * @starget: SCSI target structure. + * @sdev: SCSI device structure. + * @id: Volume ID. + * @channel: SCSI channel. + * @wwid: World wide Identifier. + * @hdl: Volume handle. + * @vol_type: Volume type. + * @pd_num: Number of physical disks. + * @resp: Response status. + * @dev_info: Device information. */ struct leapraid_raid_volume { struct list_head list; + struct kref refcnt; struct scsi_target *starget; struct scsi_device *sdev; unsigned int id; @@ -981,20 +1070,31 @@ struct leapraid_raid_volume { u32 dev_info; }; +static inline void leapraid_raid_volume_free(struct kref *ref) +{ + kfree(container_of(ref, struct leapraid_raid_volume, refcnt)); +} + +#define leapraid_raid_volume_get(volume) \ + kref_get(&(volume)->refcnt) +#define leapraid_raid_volume_put(volume) \ + kref_put(&(volume)->refcnt, leapraid_raid_volume_free) + #define LEAPRAID_TGT_FLG_RAID_MEMBER 0x01 #define LEAPRAID_TGT_FLG_VOLUME 0x02 #define LEAPRAID_NO_ULD_ATTACH 1 /** * struct leapraid_starget_priv - SCSI target private data - * @starget: SCSI target structure - * @sas_address: SAS address - * @hdl: Device handle - * @num_luns: Number of LUNs - * @flg: Flags - * @deleted: Deletion flag - * @tm_busy: Task management busy flag - * @card_port: Associated card port - * @sas_dev: SAS device structure + * + * @starget: SCSI target structure. + * @sas_address: SAS address. + * @hdl: Device handle. + * @num_luns: Number of LUNs. + * @flg: Flags. + * @deleted: Deletion flag. + * @tm_busy: Task management busy flag. + * @card_port: Associated card port. + * @sas_dev: SAS device structure. */ struct leapraid_starget_priv { struct scsi_target *starget; @@ -1002,8 +1102,8 @@ struct leapraid_starget_priv { u16 hdl; int num_luns; u32 flg; - bool deleted; - bool tm_busy; + u8 deleted; + u8 tm_busy; struct leapraid_card_port *card_port; struct leapraid_sas_dev *sas_dev; }; @@ -1011,50 +1111,52 @@ struct leapraid_starget_priv { #define LEAPRAID_DEVICE_FLG_INIT 0x01 /** * struct leapraid_sdev_priv - SCSI device private data - * @starget_priv: Associated target private data - * @lun: Logical Unit Number - * @flg: Flags - * @block: Block flag - * @deleted: Deletion flag - * @sep: SEP flag + * + * @starget_priv: Associated target private data. + * @lun: Logical Unit Number. + * @flg: Flags. + * @block: Block flag. + * @deleted: Deletion flag. + * @sep: SEP flag. */ struct leapraid_sdev_priv { struct leapraid_starget_priv *starget_priv; unsigned int lun; u32 flg; - bool ncq; - bool block; - bool deleted; - bool sep; + u8 ncq; + u8 block; + u8 deleted; + u8 sep; }; /** * struct leapraid_sas_dev - SAS device structure - * @list: List head for device management - * @starget: SCSI target structure - * @card_port: Associated card port - * @rphy: SAS remote PHY - * @refcnt: Reference count - * @id: Device ID - * @channel: SCSI channel - * @slot: Slot number - * @phy: PHY identifier - * @resp: Response status - * @led_on: LED state - * @sas_addr: SAS address - * @dev_name: Device name - * @hdl: Device handle - * @parent_sas_addr: Parent SAS address - * @enc_hdl: Enclosure handle - * @enc_lid: Enclosure logical ID - * @volume_hdl: Volume handle - * @volume_wwid: Volume WWID - * @dev_info: Device information - * @pend_sas_rphy_add: Pending SAS rphy addition flag - * @enc_level: Enclosure level - * @port_type: Port type - * @connector_name: Connector name - * @support_smart: SMART support flag + * + * @list: List head for device management. + * @starget: SCSI target structure. + * @card_port: Associated card port. + * @rphy: SAS remote PHY. + * @refcnt: Reference count. + * @id: Device ID. + * @channel: SCSI channel. + * @slot: Slot number. + * @phy: PHY identifier. + * @resp: Response status. + * @led_on: LED state. + * @sas_addr: SAS address. + * @dev_name: Device name. + * @hdl: Device handle. + * @parent_sas_addr: Parent SAS address. + * @enc_hdl: Enclosure handle. + * @enc_lid: Enclosure logical ID. + * @volume_hdl: Volume handle. + * @volume_wwid: Volume WWID. + * @dev_info: Device information. + * @pend_sas_rphy_add: Pending SAS remote PHY addition flag. + * @enc_level: Enclosure level. + * @port_connection: Port connection. + * @connector_name: Connector name. + * @support_smart: SMART support flag. */ struct leapraid_sas_dev { struct list_head list; @@ -1066,8 +1168,8 @@ struct leapraid_sas_dev { unsigned int channel; u16 slot; u8 phy; - bool resp; - bool led_on; + u8 resp; + u8 led_on; u64 sas_addr; u64 dev_name; u16 hdl; @@ -1079,9 +1181,9 @@ struct leapraid_sas_dev { u32 dev_info; u8 pend_sas_rphy_add; u8 enc_level; - u8 port_type; - u8 connector_name[5]; - bool support_smart; + u8 port_connection; + u8 connector_name[LEAPRAID_SAS_DEV_P0_CON_NAME_LEN + 1]; + u8 support_smart; }; static inline void leapraid_sdev_free(struct kref *ref) @@ -1092,15 +1194,19 @@ static inline void leapraid_sdev_free(struct kref *ref) #define leapraid_sdev_get(sdev) kref_get(&(sdev)->refcnt) #define leapraid_sdev_put(sdev) kref_put(&(sdev)->refcnt, leapraid_sdev_free) +void leapraid_boot_dev_get(void *dev, u32 chnl); +void leapraid_boot_dev_put(void *dev, u32 chnl); + /** * struct leapraid_sas_port - SAS port structure - * @port_list: List head for port management - * @phy_list: List of PHYs in this port - * @port: SAS port structure - * @card_port: Associated card port - * @remote_identify: Remote device identification - * @rphy: SAS remote PHY - * @phys_num: Number of PHYs in this port + * + * @port_list: List head for port management. + * @phy_list: List of PHYs in this port. + * @port: SAS port structure. + * @card_port: Associated card port. + * @remote_identify: Remote device identification. + * @rphy: SAS remote PHY. + * @phys_num: Number of PHYs in this port. */ struct leapraid_sas_port { struct list_head port_list; @@ -1115,10 +1221,11 @@ struct leapraid_sas_port { #define LEAPRAID_VPHY_FLG_DIRTY 0x01 /** * struct leapraid_vphy - Virtual PHY structure - * @list: List head for PHY management - * @sas_address: SAS address - * @phy_mask: PHY mask - * @flg: Flags + * + * @list: List head for PHY management. + * @sas_address: SAS address. + * @phy_mask: PHY mask. + * @flg: Flags. */ struct leapraid_vphy { struct list_head list; @@ -1127,23 +1234,44 @@ struct leapraid_vphy { u8 flg; }; +/** + * struct leapraid_tgt_rst_list - Target reset tracking entry + * @list: List node used to link reset entries. + * @handle: Device handle of the target being reset. + * @state: Current state of the target reset operation. + * + * Each entry represents a target device that is undergoing or has + * undergone a target reset operation. + */ struct leapraid_tgt_rst_list { struct list_head list; u16 handle; u16 state; }; -struct leapraid_sc_list { - struct list_head list; - u16 handle; -}; - +/** + * struct sense_info - Parsed SCSI sense information + * @sense_key: Sense key extracted from sense data. + * @asc: Additional Sense Code (ASC). + * @ascq: Additional Sense Code Qualifier (ASCQ). + * + * This structure stores key fields parsed from SCSI sense data to + * simplify error handling and reporting. + */ struct sense_info { u8 sense_key; u8 asc; u8 ascq; }; +/** + * struct leapraid_fw_log_info - Firmware log position information + * @user_position: Current log read position used by the driver. + * @adapter_position: Current log write position maintained by firmware. + * + * This structure tracks firmware log buffer positions used for retrieving + * log entries from the adapter. + */ struct leapraid_fw_log_info { u32 user_position; u32 adapter_position; @@ -1151,8 +1279,9 @@ struct leapraid_fw_log_info { /** * enum reset_type - Reset type enumeration - * @FULL_RESET: Full hardware reset - * @PART_RESET: Partial reset + * + * @FULL_RESET: Full hardware reset. + * @PART_RESET: Partial reset. */ enum reset_type { FULL_RESET, @@ -1174,22 +1303,23 @@ enum leapraid_port_checking_state { /** * struct leapraid_card_port_feature - Card port feature - * @dirty_flg: Dirty flag indicator - * @same_addr: Same address flag - * @exact_phy: Exact PHY match flag - * @phy_overlap: PHY overlap bitmap - * @same_port: Same port flag - * @cur_chking_old_port: Current checking old port - * @expected_old_port: Expected old port - * @same_addr_port_count: Same address port count - * @checking_state: Port checking state + * + * @dirty_flg: Dirty flag indicator. + * @same_addr: Same address flag. + * @exact_phy: Exact PHY match flag. + * @phy_overlap: PHY overlap bitmap. + * @same_port: Same port flag. + * @cur_chking_old_port: Current checking old port. + * @expected_old_port: Expected old port. + * @same_addr_port_count: Same address port count. + * @checking_state: Port checking state. */ struct leapraid_card_port_feature { u8 dirty_flg; - bool same_addr; - bool exact_phy; + u8 same_addr; + u8 exact_phy; u32 phy_overlap; - bool same_port; + u8 same_port; struct leapraid_card_port *cur_chking_old_port; struct leapraid_card_port *expected_old_port; int same_addr_port_count; @@ -1224,7 +1354,7 @@ struct leapraid_rep_manu_reply { u8 vendor_identification[SAS_EXPANDER_VENDOR_ID_LEN]; u8 product_identification[SAS_EXPANDER_PRODUCT_ID_LEN]; u8 product_revision_level[SAS_EXPANDER_PRODUCT_REV_LEN]; - u8 component_vendor_identification[SAS_EXPANDER_COMPONENT_VENDOR_ID_LEN]; + u8 comp_vendor_identification[SAS_EXPANDER_COMPONENT_VENDOR_ID_LEN]; u16 component_id; u8 component_revision_level; u8 r3; @@ -1233,20 +1363,21 @@ struct leapraid_rep_manu_reply { /** * struct leapraid_scsi_cmd_desc - SCSI command descriptor - * @hdl: Device handle - * @lun: Logical Unit Number - * @raid_member: RAID member flag - * @dir: DMA data direction - * @data_length: Data transfer length - * @data_buffer: Data buffer pointer - * @cdb_length: CDB length - * @cdb: Command Descriptor Block - * @time_out: Timeout + * + * @hdl: Device handle. + * @lun: Logical Unit Number. + * @raid_member: RAID member flag. + * @dir: DMA data direction. + * @data_length: Data transfer length. + * @data_buffer: Data buffer pointer. + * @cdb_length: CDB length. + * @cdb: Command Descriptor Block. + * @time_out: Timeout. */ struct leapraid_scsi_cmd_desc { u16 hdl; u32 lun; - bool raid_member; + u8 raid_member; enum dma_data_direction dir; u32 data_length; void *data_buffer; @@ -1273,7 +1404,8 @@ void leapraid_mask_int(struct leapraid_adapter *adapter); void leapraid_unmask_int(struct leapraid_adapter *adapter); u32 leapraid_get_adapter_state(struct leapraid_adapter *adapter); bool leapraid_pci_removed(struct leapraid_adapter *adapter); -int leapraid_check_adapter_is_op(struct leapraid_adapter *adapter); +int leapraid_check_adapter_is_op(struct leapraid_adapter *adapter, int wait, + const char *caller); void *leapraid_get_task_desc(struct leapraid_adapter *adapter, u16 taskid); void *leapraid_get_sense_buffer(struct leapraid_adapter *adapter, u16 taskid); __le32 leapraid_get_sense_buffer_dma(struct leapraid_adapter *adapter, @@ -1285,11 +1417,11 @@ u16 leapraid_alloc_scsiio_taskid(struct leapraid_adapter *adapter, void leapraid_free_taskid(struct leapraid_adapter *adapter, u16 taskid); struct leapraid_io_req_tracker *leapraid_get_io_tracker_from_taskid( struct leapraid_adapter *adapter, u16 taskid); -struct leapraid_io_req_tracker *leapraid_get_scmd_priv(struct scsi_cmnd *scmd); struct scsi_cmnd *leapraid_get_scmd_from_taskid( struct leapraid_adapter *adapter, u16 taskid); int leapraid_scan_dev(struct leapraid_adapter *adapter, bool async_scan_dev); void leapraid_scan_dev_done(struct leapraid_adapter *adapter); +void leapraid_cleanup_lists(struct leapraid_adapter *adapter); void leapraid_wait_cmds_done(struct leapraid_adapter *adapter); void leapraid_clean_active_scsi_cmds(struct leapraid_adapter *adapter); void leapraid_sync_irqs(struct leapraid_adapter *adapter, bool poll); @@ -1305,14 +1437,16 @@ int leapraid_issue_locked_tm(struct leapraid_adapter *adapter, u16 handle, int leapraid_issue_tm(struct leapraid_adapter *adapter, u16 handle, uint channel, uint id, uint lun, u8 type, u16 taskid_task, u8 tr_method); -u8 leapraid_scsiio_done(struct leapraid_adapter *adapter, u16 taskid, - u8 msix_index, u32 rep); +bool leapraid_scsiio_done(struct leapraid_adapter *adapter, u16 taskid, + u8 msix_index, u32 rep); int leapraid_get_volume_cap(struct leapraid_adapter *adapter, struct leapraid_raid_volume *raid_volume); -int leapraid_internal_init_cmd_priv(struct leapraid_adapter *adapter, - struct leapraid_io_req_tracker *io_tracker); -int leapraid_internal_exit_cmd_priv(struct leapraid_adapter *adapter, - struct leapraid_io_req_tracker *io_tracker); +int leapraid_internal_init_cmd_priv( + struct leapraid_adapter *adapter, + struct leapraid_io_req_tracker *io_tracker); +int leapraid_internal_exit_cmd_priv( + struct leapraid_adapter *adapter, + struct leapraid_io_req_tracker *io_tracker); void leapraid_clean_active_fw_evt(struct leapraid_adapter *adapter); bool leapraid_scmd_find_by_lun(struct leapraid_adapter *adapter, uint id, unsigned int lun, uint channel); @@ -1381,10 +1515,13 @@ int leapraid_op_config_page(struct leapraid_adapter *adapter, void *cfgp, union cfg_param_1 cfgp1, union cfg_param_2 cfgp2, enum config_page_action cfg_op); -void leapraid_adjust_sdev_queue_depth(struct scsi_device *sdev, int qdepth); +void leapraid_log_req_context(struct leapraid_adapter *adapter, + const void *req_data); + +int leapraid_change_queue_depth(struct scsi_device *sdev, int qdepth); int leapraid_ctl_release(struct inode *inode, struct file *filep); -void leapraid_ctl_init(void); +int leapraid_ctl_init(void); void leapraid_ctl_exit(void); extern struct sas_function_template leapraid_transport_functions; @@ -1407,17 +1544,20 @@ void leapraid_transport_update_links(struct leapraid_adapter *adapter, u64 sas_address, u16 handle, u8 phy_number, u8 link_rate, struct leapraid_card_port *card_port); -void leapraid_transport_detach_phy_to_port(struct leapraid_adapter *adapter, - struct leapraid_topo_node *topo_node, - struct leapraid_card_phy *card_phy); -void leapraid_transport_attach_phy_to_port(struct leapraid_adapter *adapter, - struct leapraid_topo_node *sas_node, - struct leapraid_card_phy *card_phy, - u64 sas_address, - struct leapraid_card_port *card_port); +void leapraid_transport_detach_phy_to_port( + struct leapraid_adapter *adapter, + struct leapraid_topo_node *topo_node, + struct leapraid_card_phy *card_phy); +void leapraid_transport_attach_phy_to_port( + struct leapraid_adapter *adapter, + struct leapraid_topo_node *sas_node, + struct leapraid_card_phy *card_phy, + u64 sas_address, + struct leapraid_card_port *card_port); int leapraid_queuecommand(struct Scsi_Host *shost, struct scsi_cmnd *scmd); void leapraid_smart_polling_start(struct leapraid_adapter *adapter); void leapraid_smart_polling_stop(struct leapraid_adapter *adapter); +void leapraid_overheat_cleanup(struct leapraid_adapter *adapter); void leapraid_smart_fault_detect(struct leapraid_adapter *adapter, u16 hdl); void leapraid_free_internal_scsi_cmd(struct leapraid_adapter *adapter); diff --git a/drivers/scsi/leapraid/leapraid_os.c b/drivers/scsi/leapraid/leapraid_os.c index 6635e74fd8ff..5a6cda0b5ea8 100644 --- a/drivers/scsi/leapraid/leapraid_os.c +++ b/drivers/scsi/leapraid/leapraid_os.c @@ -1,10 +1,9 @@ // SPDX-License-Identifier: GPL-2.0 /* - * Copyright (C) 2025 LeapIO Tech Inc. + * Copyright (C) 2026 LeapIO Tech Inc. * - * LeapRAID Storage and RAID Controller driver. + * LeapRAID storage and RAID controller driver. */ - #include <linux/module.h> #include "leapraid_func.h" @@ -18,16 +17,16 @@ MODULE_DESCRIPTION(LEAPRAID_DESCRIPTION); MODULE_LICENSE("GPL"); MODULE_VERSION(LEAPRAID_DRIVER_VERSION); -static int leapraid_ids; +static atomic_t leapraid_ids = ATOMIC_INIT(0); static int open_pcie_trace = 1; module_param(open_pcie_trace, int, 0644); -MODULE_PARM_DESC(open_pcie_trace, "open_pcie_trace: default=1(open)/0(close)"); +MODULE_PARM_DESC(open_pcie_trace, "Default=1(open)/0(close)"); static int enable_mp = 1; module_param(enable_mp, int, 0444); MODULE_PARM_DESC(enable_mp, - "enable multipath on target device. default=1(enable)"); + "Enable multipath on target device. default=1(enable)"); static inline void leapraid_get_sense_data(char *sense, struct sense_info *data) @@ -46,14 +45,9 @@ static inline void leapraid_get_sense_data(char *sense, } } -static struct Scsi_Host *pdev_to_shost(struct pci_dev *pdev) -{ - return pci_get_drvdata(pdev); -} - static struct leapraid_adapter *pdev_to_adapter(struct pci_dev *pdev) { - struct Scsi_Host *shost = pdev_to_shost(pdev); + struct Scsi_Host *shost = pci_get_drvdata(pdev); if (!shost) return NULL; @@ -61,18 +55,13 @@ static struct leapraid_adapter *pdev_to_adapter(struct pci_dev *pdev) return shost_priv(shost); } -struct leapraid_io_req_tracker *leapraid_get_scmd_priv(struct scsi_cmnd *scmd) -{ - return (struct leapraid_io_req_tracker *)scmd->host_scribble; -} - void leapraid_set_tm_flg(struct leapraid_adapter *adapter, u16 hdl) { struct leapraid_sdev_priv *sdev_priv; struct scsi_device *sdev; bool skip = false; - /* don't break out of the loop */ + /* Iterate over all devices. */ shost_for_each_device(sdev, adapter->shost) { if (skip) continue; @@ -82,7 +71,7 @@ void leapraid_set_tm_flg(struct leapraid_adapter *adapter, u16 hdl) continue; if (sdev_priv->starget_priv->hdl == hdl) { - sdev_priv->starget_priv->tm_busy = true; + sdev_priv->starget_priv->tm_busy = 1; skip = true; } } @@ -94,7 +83,7 @@ void leapraid_clear_tm_flg(struct leapraid_adapter *adapter, u16 hdl) struct scsi_device *sdev; bool skip = false; - /* don't break out of the loop */ + /* Iterate over all devices. */ shost_for_each_device(sdev, adapter->shost) { if (skip) continue; @@ -104,7 +93,7 @@ void leapraid_clear_tm_flg(struct leapraid_adapter *adapter, u16 hdl) continue; if (sdev_priv->starget_priv->hdl == hdl) { - sdev_priv->starget_priv->tm_busy = false; + sdev_priv->starget_priv->tm_busy = 0; skip = true; } } @@ -136,21 +125,19 @@ static int leapraid_tm_cmd_map_status(struct leapraid_adapter *adapter, } } - if (taskid_task == adapter->driver_cmds.driver_scsiio_cmd.taskid) { - if ((adapter->driver_cmds.driver_scsiio_cmd.status & - LEAPRAID_CMD_DONE) || - (adapter->driver_cmds.driver_scsiio_cmd.status & - LEAPRAID_CMD_NOT_USED)) - rc = SUCCESS; - } + if (taskid_task == adapter->driver_cmds.driver_scsiio_cmd.taskid && + (adapter->driver_cmds.driver_scsiio_cmd.status & + LEAPRAID_CMD_DONE || + adapter->driver_cmds.driver_scsiio_cmd.status & + LEAPRAID_CMD_NOT_USED)) + rc = SUCCESS; - if (taskid_task == adapter->driver_cmds.ctl_cmd.hp_taskid) { - if ((adapter->driver_cmds.ctl_cmd.status & - LEAPRAID_CMD_DONE) || - (adapter->driver_cmds.ctl_cmd.status & - LEAPRAID_CMD_NOT_USED)) - rc = SUCCESS; - } + if (taskid_task == adapter->driver_cmds.ctl_cmd.hp_taskid && + (adapter->driver_cmds.ctl_cmd.status & + LEAPRAID_CMD_DONE || + adapter->driver_cmds.ctl_cmd.status & + LEAPRAID_CMD_NOT_USED)) + rc = SUCCESS; return rc; } @@ -197,7 +184,7 @@ int leapraid_issue_tm(struct leapraid_adapter *adapter, u16 hdl, uint channel, struct leapraid_scsi_tm_req *scsi_tm_req; struct leapraid_scsiio_req *scsiio_req; struct leapraid_io_req_tracker *io_req_tracker = NULL; - u16 msix_task = 0; + u16 msix_task; bool issue_reset = false; u32 db; int rc; @@ -208,7 +195,7 @@ int leapraid_issue_tm(struct leapraid_adapter *adapter, u16 hdl, uint channel, adapter->access_ctrl.host_removing || adapter->access_ctrl.pcie_recovering) { dev_info(&adapter->pdev->dev, - "%s %s: host is recovering, skip tm command!\n", + "%s %s: Host is recovering, skip tm command!\n", __func__, adapter->adapter_attr.name); return FAILED; } @@ -216,24 +203,25 @@ int leapraid_issue_tm(struct leapraid_adapter *adapter, u16 hdl, uint channel, db = leapraid_readl(&adapter->iomem_base->db); if (db & LEAPRAID_DB_USED) { dev_info(&adapter->pdev->dev, - "%s unexpected db status, issuing hard reset!\n", + "%s Unexpected db status, issuing hard reset!\n", adapter->adapter_attr.name); - dev_info(&adapter->pdev->dev, "%s:%d call hard_reset\n", + dev_info(&adapter->pdev->dev, "%s:%d: call hard_reset\n", __func__, __LINE__); rc = leapraid_hard_reset_handler(adapter, FULL_RESET); - return (!rc) ? SUCCESS : FAILED; + return !rc ? SUCCESS : FAILED; } if ((db & LEAPRAID_DB_MASK) == LEAPRAID_DB_FAULT) { - dev_info(&adapter->pdev->dev, "%s:%d call hard_reset\n", + dev_info(&adapter->pdev->dev, "%s:%d: call hard_reset\n", __func__, __LINE__); rc = leapraid_hard_reset_handler(adapter, FULL_RESET); - return (!rc) ? SUCCESS : FAILED; + return !rc ? SUCCESS : FAILED; } if (type == LEAPRAID_TM_TASKTYPE_ABORT_TASK) - io_req_tracker = leapraid_get_io_tracker_from_taskid(adapter, - target_taskid); + io_req_tracker = + leapraid_get_io_tracker_from_taskid(adapter, + target_taskid); adapter->driver_cmds.tm_cmd.status = LEAPRAID_CMD_PENDING; scsi_tm_req = @@ -241,7 +229,7 @@ int leapraid_issue_tm(struct leapraid_adapter *adapter, u16 hdl, uint channel, adapter->driver_cmds.tm_cmd.hp_taskid); leapraid_build_tm_req(scsi_tm_req, hdl, lun, type, tr_method, target_taskid); - memset((void *)(&adapter->driver_cmds.tm_cmd.reply), 0, + memset(&adapter->driver_cmds.tm_cmd.reply, 0, sizeof(struct leapraid_scsi_tm_rep)); leapraid_set_tm_flg(adapter, hdl); init_completion(&adapter->driver_cmds.tm_cmd.done); @@ -257,16 +245,20 @@ int leapraid_issue_tm(struct leapraid_adapter *adapter, u16 hdl, uint channel, wait_for_completion_timeout(&adapter->driver_cmds.tm_cmd.done, LEAPRAID_TM_CMD_TIMEOUT * HZ); if (!(adapter->driver_cmds.tm_cmd.status & LEAPRAID_CMD_DONE)) { + dev_err(&adapter->pdev->dev, + "%s: TM cmd timeout, status=0x%x\n", + __func__, adapter->driver_cmds.tm_cmd.status); + leapraid_log_req_context(adapter, scsi_tm_req); issue_reset = leapraid_check_reset( adapter->driver_cmds.tm_cmd.status); if (issue_reset) { dev_info(&adapter->pdev->dev, - "%s:%d call hard_reset\n", + "%s:%d: call hard_reset\n", __func__, __LINE__); rc = leapraid_hard_reset_handler(adapter, FULL_RESET); - rc = (!rc) ? SUCCESS : FAILED; - goto out; + rc = !rc ? SUCCESS : FAILED; + goto out_cleanup; } } @@ -276,15 +268,15 @@ int leapraid_issue_tm(struct leapraid_adapter *adapter, u16 hdl, uint channel, case LEAPRAID_TM_TASKTYPE_TARGET_RESET: case LEAPRAID_TM_TASKTYPE_ABRT_TASK_SET: case LEAPRAID_TM_TASKTYPE_LOGICAL_UNIT_RESET: - rc = leapraid_tm_post_processing(adapter, hdl, channel, id, lun, - type, target_taskid); + rc = leapraid_tm_post_processing(adapter, hdl, channel, id, + lun, type, target_taskid); break; case LEAPRAID_TM_TASKTYPE_ABORT_TASK: rc = SUCCESS; scsiio_req = leapraid_get_task_desc(adapter, target_taskid); if (le16_to_cpu(scsiio_req->dev_hdl) != hdl) break; - dev_err(&adapter->pdev->dev, "%s abort failed, hdl=0x%04x\n", + dev_err(&adapter->pdev->dev, "%s: Abort failed, hdl=0x%04x\n", adapter->adapter_attr.name, hdl); rc = FAILED; break; @@ -296,7 +288,7 @@ int leapraid_issue_tm(struct leapraid_adapter *adapter, u16 hdl, uint channel, break; } -out: +out_cleanup: leapraid_clear_tm_flg(adapter, hdl); adapter->driver_cmds.tm_cmd.status = LEAPRAID_CMD_NOT_USED; return rc; @@ -327,20 +319,25 @@ void leapraid_smart_fault_detect(struct leapraid_adapter *adapter, u16 hdl) sas_dev = leapraid_hold_lock_get_sas_dev_by_hdl(adapter, hdl); if (!sas_dev) { spin_unlock_irqrestore(&adapter->dev_topo.sas_dev_lock, flags); - goto out; + return; } starget = sas_dev->starget; - starget_priv = starget->hostdata; - if ((starget_priv->flg & LEAPRAID_TGT_FLG_RAID_MEMBER) || - (starget_priv->flg & LEAPRAID_TGT_FLG_VOLUME)) { + starget_priv = starget ? starget->hostdata : NULL; + if (!starget_priv) { spin_unlock_irqrestore(&adapter->dev_topo.sas_dev_lock, flags); - goto out; + goto release_sdev; + } + + if (starget_priv->flg & LEAPRAID_TGT_FLG_RAID_MEMBER || + starget_priv->flg & LEAPRAID_TGT_FLG_VOLUME) { + spin_unlock_irqrestore(&adapter->dev_topo.sas_dev_lock, flags); + goto release_sdev; } spin_unlock_irqrestore(&adapter->dev_topo.sas_dev_lock, flags); leapraid_async_turn_on_led(adapter, hdl); -out: +release_sdev: if (sas_dev) leapraid_sdev_put(sas_dev); } @@ -420,7 +417,8 @@ static void leapraid_handle_success_status( scmd->result = DID_RESET << LEAPRAID_SCSI_HOST_SHIFT; } -static void leapraid_scsiio_done_dispatch(struct leapraid_adapter *adapter, +static void leapraid_scsiio_done_dispatch( + struct leapraid_adapter *adapter, struct leapraid_scsiio_rep *scsiio_rep, struct leapraid_sdev_priv *sdev_priv, struct scsi_cmnd *scmd, @@ -442,9 +440,8 @@ static void leapraid_scsiio_done_dispatch(struct leapraid_adapter *adapter, xfer_cnt == 0 && (scsi_status == LEAPRAID_SCSI_STATUS_BUSY || scsi_status == LEAPRAID_SCSI_STATUS_RESERVATION_CONFLICT || - scsi_status == LEAPRAID_SCSI_STATUS_TASK_SET_FULL)) { + scsi_status == LEAPRAID_SCSI_STATUS_TASK_SET_FULL)) adapter_status = LEAPRAID_ADAPTER_STATUS_SUCCESS; - } switch (adapter_status) { case LEAPRAID_ADAPTER_STATUS_SCSI_DEVICE_NOT_THERE: @@ -516,7 +513,7 @@ static void leapraid_scsiio_done_dispatch(struct leapraid_adapter *adapter, scsi_print_command(scmd); dev_warn(&adapter->pdev->dev, - "scsiio warn: hdl=0x%x, status are: 0x%x, 0x%x, 0x%x\n", + "SCSI I/O: hdl=0x%x, status: 0x%x, 0x%x, 0x%x\n", le16_to_cpu(scsiio_rep->dev_hdl), adapter_status, scsi_status, scsi_state); @@ -526,24 +523,23 @@ static void leapraid_scsiio_done_dispatch(struct leapraid_adapter *adapter, sz = min_t(u32, SCSI_SENSE_BUFFERSIZE, le32_to_cpu(scsiio_rep->sense_count)); if (scsi_normalize_sense(scmd->sense_buffer, sz, - &sshdr)) { + &sshdr)) dev_warn(&adapter->pdev->dev, - "sense: key=0x%x asc=0x%x ascq=0x%x\n", + "Sense: key=0x%x asc=0x%x ascq=0x%x\n", sshdr.sense_key, sshdr.asc, sshdr.ascq); - } else { + else dev_warn(&adapter->pdev->dev, - "sense: invalid sense data\n"); - } + "Sense: Invalid sense data\n"); } } -u8 leapraid_scsiio_done(struct leapraid_adapter *adapter, u16 taskid, - u8 msix_index, u32 rep) +bool leapraid_scsiio_done(struct leapraid_adapter *adapter, u16 taskid, + u8 msix_index, u32 rep) { - struct leapraid_scsiio_rep *scsiio_rep = NULL; - struct leapraid_sdev_priv *sdev_priv = NULL; - struct scsi_cmnd *scmd = NULL; + struct leapraid_scsiio_rep *scsiio_rep; + struct leapraid_sdev_priv *sdev_priv; + struct scsi_cmnd *scmd; u32 response_code = 0; if (likely(taskid != adapter->driver_cmds.driver_scsiio_cmd.taskid)) @@ -551,12 +547,12 @@ u8 leapraid_scsiio_done(struct leapraid_adapter *adapter, u16 taskid, else scmd = adapter->driver_cmds.internal_scmd; if (!scmd) - return 1; + return true; scsiio_rep = leapraid_get_reply_vaddr(adapter, rep); if (!scsiio_rep) { scmd->result = DID_OK << LEAPRAID_SCSI_HOST_SHIFT; - goto out; + goto out_scsiio_done; } sdev_priv = scmd->device->hostdata; @@ -564,7 +560,7 @@ u8 leapraid_scsiio_done(struct leapraid_adapter *adapter, u16 taskid, !sdev_priv->starget_priv || sdev_priv->starget_priv->deleted) { scmd->result = DID_NO_CONNECT << LEAPRAID_SCSI_HOST_SHIFT; - goto out; + goto out_scsiio_done; } if (scsiio_rep->scsi_state & LEAPRAID_SCSI_STATE_RESPONSE_INFO_VALID) @@ -574,33 +570,51 @@ u8 leapraid_scsiio_done(struct leapraid_adapter *adapter, u16 taskid, leapraid_scsiio_done_dispatch(adapter, scsiio_rep, sdev_priv, scmd, taskid, response_code); -out: +out_scsiio_done: scsi_dma_unmap(scmd); - if (unlikely(taskid == adapter->driver_cmds.driver_scsiio_cmd.taskid)) { + if (unlikely(taskid == + adapter->driver_cmds.driver_scsiio_cmd.taskid)) { adapter->driver_cmds.driver_scsiio_cmd.status = LEAPRAID_CMD_DONE; complete(&adapter->driver_cmds.driver_scsiio_cmd.done); - return 0; + return false; } leapraid_free_taskid(adapter, taskid); scmd->scsi_done(scmd); - return 0; + return false; } static void leapraid_probe_raid(struct leapraid_adapter *adapter) { - struct leapraid_raid_volume *raid_volume, *raid_volume_next; + struct leapraid_raid_volume *raid_volume, *next_raid_volume; + unsigned long flags; + LIST_HEAD(head); int rc; - list_for_each_entry_safe(raid_volume, raid_volume_next, - &adapter->dev_topo.raid_volume_list, list) { - if (raid_volume->starget) + spin_lock_irqsave(&adapter->dev_topo.raid_volume_lock, flags); + list_splice_init(&adapter->dev_topo.raid_volume_list, &head); + spin_unlock_irqrestore(&adapter->dev_topo.raid_volume_lock, flags); + + list_for_each_entry_safe(raid_volume, next_raid_volume, &head, list) { + spin_lock_irqsave(&adapter->dev_topo.raid_volume_lock, flags); + list_move_tail(&raid_volume->list, + &adapter->dev_topo.raid_volume_list); + if (raid_volume->starget) { + spin_unlock_irqrestore( + &adapter->dev_topo.raid_volume_lock, flags); continue; + } + + leapraid_raid_volume_get(raid_volume); + spin_unlock_irqrestore( + &adapter->dev_topo.raid_volume_lock, flags); rc = scsi_add_device(adapter->shost, RAID_CHANNEL, raid_volume->id, 0); if (rc) leapraid_raid_volume_remove(adapter, raid_volume); + + leapraid_raid_volume_put(raid_volume); } } @@ -629,7 +643,6 @@ static void leapraid_probe_sas(struct leapraid_adapter *adapter) sas_dev = leapraid_get_next_sas_dev_from_init_list(adapter); if (!sas_dev) break; - added = leapraid_transport_port_add(adapter, sas_dev->hdl, sas_dev->parent_sas_addr, @@ -657,32 +670,52 @@ static void leapraid_probe_sas(struct leapraid_adapter *adapter) } } -static bool leapraid_get_boot_dev(struct leapraid_boot_dev *boot_dev, +static bool leapraid_get_boot_dev(struct leapraid_adapter *adapter, + struct leapraid_boot_dev *boot_dev, void **pdev, u32 *pchnl) { - if (boot_dev->dev) { - *pdev = boot_dev->dev; - *pchnl = boot_dev->chnl; - return true; + unsigned long flags; + void *dev; + u32 chnl; + + spin_lock_irqsave(&adapter->boot_devs.lock, flags); + if (!boot_dev->dev) { + spin_unlock_irqrestore(&adapter->boot_devs.lock, flags); + return false; } - return false; + + dev = boot_dev->dev; + chnl = boot_dev->chnl; + leapraid_boot_dev_get(dev, chnl); + spin_unlock_irqrestore(&adapter->boot_devs.lock, flags); + + *pdev = dev; + *pchnl = chnl; + return true; } static void leapraid_probe_boot_dev(struct leapraid_adapter *adapter) { + struct leapraid_raid_volume *raid_volume; + struct leapraid_sas_dev *sas_dev; + struct leapraid_sas_port *sport; + unsigned long flags; void *dev = NULL; u32 chnl; - if (leapraid_get_boot_dev(&adapter->boot_devs.requested_boot_dev, &dev, - &chnl)) + if (leapraid_get_boot_dev(adapter, + &adapter->boot_devs.requested_boot_dev, + &dev, &chnl)) goto boot_dev_found; - if (leapraid_get_boot_dev(&adapter->boot_devs.requested_alt_boot_dev, + if (leapraid_get_boot_dev(adapter, + &adapter->boot_devs.requested_alt_boot_dev, &dev, &chnl)) goto boot_dev_found; - if (leapraid_get_boot_dev(&adapter->boot_devs.current_boot_dev, &dev, - &chnl)) + if (leapraid_get_boot_dev(adapter, + &adapter->boot_devs.current_boot_dev, + &dev, &chnl)) goto boot_dev_found; return; @@ -690,12 +723,10 @@ static void leapraid_probe_boot_dev(struct leapraid_adapter *adapter) boot_dev_found: switch (chnl) { case RAID_CHANNEL: - { - struct leapraid_raid_volume *raid_volume = - (struct leapraid_raid_volume *)dev; + raid_volume = dev; if (raid_volume->starget) - return; + break; /* TODO eedp */ @@ -703,16 +734,11 @@ static void leapraid_probe_boot_dev(struct leapraid_adapter *adapter) raid_volume->id, 0)) leapraid_raid_volume_remove(adapter, raid_volume); break; - } default: - { - struct leapraid_sas_dev *sas_dev = - (struct leapraid_sas_dev *)dev; - struct leapraid_sas_port *sas_port; - unsigned long flags; + sas_dev = dev; if (sas_dev->starget) - return; + break; spin_lock_irqsave(&adapter->dev_topo.sas_dev_lock, flags); list_move_tail(&sas_dev->list, @@ -720,16 +746,17 @@ static void leapraid_probe_boot_dev(struct leapraid_adapter *adapter) spin_unlock_irqrestore(&adapter->dev_topo.sas_dev_lock, flags); if (!sas_dev->card_port) - return; + break; - sas_port = leapraid_transport_port_add(adapter, sas_dev->hdl, - sas_dev->parent_sas_addr, - sas_dev->card_port); - if (!sas_port) + sport = leapraid_transport_port_add(adapter, sas_dev->hdl, + sas_dev->parent_sas_addr, + sas_dev->card_port); + if (!sport) leapraid_sas_dev_remove(adapter, sas_dev); break; } - } + + leapraid_boot_dev_put(dev, chnl); } static void leapraid_probe_devices(struct leapraid_adapter *adapter) @@ -747,69 +774,23 @@ static void leapraid_probe_devices(struct leapraid_adapter *adapter) void leapraid_scan_dev_done(struct leapraid_adapter *adapter) { if (adapter->scan_dev_desc.wait_scan_dev_done) { - adapter->scan_dev_desc.wait_scan_dev_done = false; + adapter->scan_dev_desc.wait_scan_dev_done = 0; leapraid_probe_devices(adapter); } + adapter->scan_dev_desc.scan_start = 0; + leapraid_check_scheduled_fault_start(adapter); leapraid_fw_log_start(adapter); - adapter->scan_dev_desc.driver_loading = false; + adapter->scan_dev_desc.driver_loading = 0; + wake_up(&adapter->scan_dev_desc.wait_driver_loading); leapraid_smart_polling_start(adapter); } -static void leapraid_ir_shutdown(struct leapraid_adapter *adapter) -{ - struct leapraid_raid_act_req *raid_act_req; - struct leapraid_raid_act_rep *raid_act_rep; - struct leapraid_driver_cmd *raid_action_cmd; - - if (!adapter || !adapter->adapter_attr.raid_support) - return; - - if (list_empty(&adapter->dev_topo.raid_volume_list)) - return; - - if (leapraid_pci_removed(adapter)) - return; - - raid_action_cmd = &adapter->driver_cmds.raid_action_cmd; - - mutex_lock(&raid_action_cmd->mutex); - raid_action_cmd->status = LEAPRAID_CMD_PENDING; - - raid_act_req = leapraid_get_task_desc(adapter, - raid_action_cmd->inter_taskid); - memset(raid_act_req, 0, sizeof(struct leapraid_raid_act_req)); - raid_act_req->func = LEAPRAID_FUNC_RAID_ACTION; - raid_act_req->act = LEAPRAID_RAID_ACT_SYSTEM_SHUTDOWN_INITIATED; - - dev_info(&adapter->pdev->dev, "ir shutdown start\n"); - init_completion(&raid_action_cmd->done); - leapraid_fire_task(adapter, raid_action_cmd->inter_taskid); - wait_for_completion_timeout(&raid_action_cmd->done, - LEAPRAID_RAID_ACTION_CMD_TIMEOUT * HZ); - - if (!(raid_action_cmd->status & LEAPRAID_CMD_DONE)) { - dev_err(&adapter->pdev->dev, - "%s: timeout waiting for ir shutdown\n", __func__); - goto out; - } - - if (raid_action_cmd->status & LEAPRAID_CMD_REPLY_VALID) { - raid_act_rep = (void *)(&raid_action_cmd->reply); - dev_info(&adapter->pdev->dev, - "ir shutdown done, adapter status=0x%04x\n", - le16_to_cpu(raid_act_rep->adapter_status)); - } - -out: - raid_action_cmd->status = LEAPRAID_CMD_NOT_USED; - mutex_unlock(&raid_action_cmd->mutex); -} - static const struct pci_device_id leapraid_pci_table[] = { - { PCI_DEVICE(LEAPRAID_VENDOR_ID, LEAPRAID_DEVID_HBA) }, - { PCI_DEVICE(LEAPRAID_VENDOR_ID, LEAPRAID_DEVID_RAID) }, + { PCI_DEVICE_SUB(LEAPRAID_VENDOR_ID, LEAPRAID_DEVID_HBA, + LEAPRAID_SUBVENDOR_ID, + LEAPRAID_SUBDEVID_HBA) }, { 0, } }; @@ -819,7 +800,7 @@ static inline bool leapraid_is_scmd_permitted(struct leapraid_adapter *adapter, u8 opcode; if (adapter->access_ctrl.pcie_recovering || - adapter->access_ctrl.adapter_thermal_alert) + atomic_read(&adapter->overheat_desc.thermal_alert)) return false; if (adapter->access_ctrl.host_removing) { @@ -829,8 +810,8 @@ static inline bool leapraid_is_scmd_permitted(struct leapraid_adapter *adapter, opcode = scmd->cmnd[0]; if (opcode == SYNCHRONIZE_CACHE || opcode == START_STOP) return true; - else - return false; + + return false; } return true; } @@ -860,28 +841,33 @@ static bool leapraid_should_queuecommand(struct leapraid_adapter *adapter, scmd->result = (DRIVER_SENSE << LEAPRAID_SCSI_DRIVER_SHIFT) | (DID_OK << LEAPRAID_SCSI_HOST_SHIFT) | SAM_STAT_CHECK_CONDITION; - goto done_out; + goto scsiio_done; } if (adapter->access_ctrl.shost_recovering || adapter->reset_desc.adapter_link_resetting) { *rc = SCSI_MLQUEUE_HOST_BUSY; - goto out; - } else if (starget_priv->deleted || sdev_priv->deleted) { + return false; + } + + if (starget_priv->deleted || sdev_priv->deleted) goto no_connect; - } else if (starget_priv->tm_busy || sdev_priv->block) { + + if (starget_priv->tm_busy || sdev_priv->block) { *rc = SCSI_MLQUEUE_DEVICE_BUSY; - goto out; + return false; } return true; no_connect: scmd->result = DID_NO_CONNECT << LEAPRAID_SCSI_HOST_SHIFT; -done_out: +scsiio_done: if (likely(scmd != adapter->driver_cmds.internal_scmd)) scmd->scsi_done(scmd); -out: + else + *rc = LEAPRAID_OPERATION_FAILED; + return false; } @@ -909,12 +895,14 @@ static u32 build_scsiio_req_control(struct scsi_cmnd *scmd, IOPRIO_CLASS_RT)) control |= LEAPRAID_SCSIIO_CTRL_CMDPRI; if (scmd->cmd_len == 32) - control |= 4 << LEAPRAID_SCSIIO_CTRL_ADDCDBLEN_SHIFT; + control |= LEAPRAID_SCSIIO_CTRL_CDB_32BYTE << + LEAPRAID_SCSIIO_CTRL_CDB_LEN_SHIFT; return control; } -int leapraid_queuecommand(struct Scsi_Host *shost, struct scsi_cmnd *scmd) +int leapraid_queuecommand(struct Scsi_Host *shost, + struct scsi_cmnd *scmd) { struct leapraid_adapter *adapter = shost_priv(scmd->device->host); struct leapraid_sdev_priv *sdev_priv = scmd->device->hostdata; @@ -926,7 +914,7 @@ int leapraid_queuecommand(struct Scsi_Host *shost, struct scsi_cmnd *scmd) int rc = 0; if (!leapraid_should_queuecommand(adapter, sdev_priv, scmd, &rc)) - goto out; + return rc; starget_priv = sdev_priv->starget_priv; hdl = starget_priv->hdl; @@ -938,11 +926,11 @@ int leapraid_queuecommand(struct Scsi_Host *shost, struct scsi_cmnd *scmd) taskid = leapraid_alloc_scsiio_taskid(adapter, scmd); scsiio_req = leapraid_get_task_desc(adapter, taskid); - scsiio_req->func = LEAPRAID_FUNC_SCSIIO_REQ; + scsiio_req->func = LEAPRAID_FUNC_SCSIIO; if (sdev_priv->starget_priv->flg & LEAPRAID_TGT_FLG_RAID_MEMBER) - scsiio_req->func = LEAPRAID_FUNC_RAID_SCSIIO_PASSTHROUGH; + scsiio_req->func = LEAPRAID_FUNC_SCSIIO_RAID_PASSTHROUGH; else - scsiio_req->func = LEAPRAID_FUNC_SCSIIO_REQ; + scsiio_req->func = LEAPRAID_FUNC_SCSIIO; scsiio_req->dev_hdl = cpu_to_le16(hdl); scsiio_req->data_len = cpu_to_le32(scsi_bufflen(scmd)); @@ -960,23 +948,21 @@ int leapraid_queuecommand(struct Scsi_Host *shost, struct scsi_cmnd *scmd) if (scsiio_req->data_len) { if (leapraid_build_scmd_ieee_sg(adapter, scmd, taskid)) { leapraid_free_taskid(adapter, taskid); - rc = SCSI_MLQUEUE_HOST_BUSY; - goto out; + return SCSI_MLQUEUE_HOST_BUSY; } } else { leapraid_build_ieee_nodata_sg(adapter, &scsiio_req->sgl); } - if (likely(scsiio_req->func == LEAPRAID_FUNC_SCSIIO_REQ)) { + if (likely(scsiio_req->func == LEAPRAID_FUNC_SCSIIO)) leapraid_fire_scsi_io(adapter, taskid, - le16_to_cpu(scsiio_req->dev_hdl)); - } else { + le16_to_cpu(scsiio_req->dev_hdl)); + else leapraid_fire_task(adapter, taskid); - } + dev_dbg(&adapter->pdev->dev, "LEAPRAID_SCSIIO: Send Descriptor taskid %d, req type 0x%x\n", taskid, scsiio_req->func); -out: return rc; } @@ -999,9 +985,9 @@ static int leapraid_error_handler(struct scsi_cmnd *scmd, scsi_print_command(scmd); if (type == LEAPRAID_TM_TASKTYPE_ABORT_TASK) { - io_req_tracker = leapraid_get_scmd_priv(scmd); + io_req_tracker = (struct leapraid_io_req_tracker *)scmd->host_scribble; dev_info(&adapter->pdev->dev, - "EH ABORT: scmd=0x%p, pending=%u ms, tout=%u ms, req tag=%d\n", + "EH ABORT: scmd=0x%p, pend=%ums, tout=%ums, tag=%d\n", scmd, jiffies_to_msecs(jiffies - scmd->jiffies_at_alloc), (scmd->request->timeout / HZ) * 1000, @@ -1014,48 +1000,47 @@ static int leapraid_error_handler(struct scsi_cmnd *scmd, "EH %s failed: %s scmd=0x%p\n", str, (adapter->access_ctrl.host_removing ? "shost removing!" : "pci_dev removed!"), scmd); - if (type == LEAPRAID_TM_TASKTYPE_ABORT_TASK) - if (io_req_tracker && io_req_tracker->taskid) - leapraid_free_taskid(adapter, - io_req_tracker->taskid); + if (type == LEAPRAID_TM_TASKTYPE_ABORT_TASK && + io_req_tracker && io_req_tracker->taskid) + leapraid_free_taskid(adapter, io_req_tracker->taskid); scmd->result = DID_NO_CONNECT << LEAPRAID_SCSI_HOST_SHIFT; #ifdef FAST_IO_FAIL rc = FAST_IO_FAIL; #else rc = FAILED; #endif - goto out; + goto out_eh_done; } sdev_priv = scmd->device->hostdata; if (!sdev_priv || !sdev_priv->starget_priv) { dev_warn(&adapter->pdev->dev, - "EH %s: sdev or starget gone, scmd=0x%p\n", + "EH %s: SAS dev or starget gone, scmd=0x%p\n", str, scmd); scmd->result = DID_NO_CONNECT << LEAPRAID_SCSI_HOST_SHIFT; scmd->scsi_done(scmd); rc = SUCCESS; - goto out; + goto out_eh_done; } if (type == LEAPRAID_TM_TASKTYPE_ABORT_TASK) { if (!io_req_tracker) { dev_warn(&adapter->pdev->dev, - "EH ABORT: no io tracker, scmd 0x%p\n", scmd); + "EH ABORT: No I/O tracker, scmd 0x%p\n", scmd); scmd->result = DID_RESET << LEAPRAID_SCSI_HOST_SHIFT; rc = SUCCESS; - goto out; + goto out_eh_done; } if (sdev_priv->starget_priv->flg & LEAPRAID_TGT_FLG_RAID_MEMBER || sdev_priv->starget_priv->flg & LEAPRAID_TGT_FLG_VOLUME) { dev_err(&adapter->pdev->dev, - "EH ABORT: skip RAID/VOLUME target, scmd=0x%p\n", + "EH ABORT: Skip RAID/VOLUME, scmd=0x%p\n", scmd); scmd->result = DID_RESET << LEAPRAID_SCSI_HOST_SHIFT; rc = FAILED; - goto out; + goto out_eh_done; } hdl = sdev_priv->starget_priv->hdl; @@ -1073,11 +1058,11 @@ static int leapraid_error_handler(struct scsi_cmnd *scmd, if (!hdl) { dev_err(&adapter->pdev->dev, - "EH %s failed: target handle is 0, scmd=0x%p\n", + "EH %s failed: Target handle 0, scmd=0x%p\n", str, scmd); scmd->result = DID_RESET << LEAPRAID_SCSI_HOST_SHIFT; rc = FAILED; - goto out; + goto out_eh_done; } } @@ -1085,24 +1070,27 @@ static int leapraid_error_handler(struct scsi_cmnd *scmd, "EH issue TM: type=%s, scmd=0x%p, hdl=0x%x\n", str, scmd, hdl); - rc = leapraid_issue_locked_tm(adapter, hdl, scmd->device->channel, - scmd->device->id, - (type == LEAPRAID_TM_TASKTYPE_TARGET_RESET ? - 0 : scmd->device->lun), - type, - (type == LEAPRAID_TM_TASKTYPE_ABORT_TASK ? - io_req_tracker->taskid : 0), - LEAPRAID_TM_MSGFLAGS_LINK_RESET); - -out: + rc = leapraid_issue_locked_tm( + adapter, + hdl, + scmd->device->channel, + scmd->device->id, + (type == LEAPRAID_TM_TASKTYPE_TARGET_RESET ? + 0 : scmd->device->lun), + type, + (type == LEAPRAID_TM_TASKTYPE_ABORT_TASK ? + io_req_tracker->taskid : 0), + LEAPRAID_TM_MSGFLAGS_LINK_RESET); + +out_eh_done: if (type == LEAPRAID_TM_TASKTYPE_ABORT_TASK) { dev_info(&adapter->pdev->dev, "EH ABORT result: %s, scmd=0x%p\n", - ((rc == SUCCESS) ? "success" : "failed"), scmd); + rc == SUCCESS ? "success" : "failed", scmd); } else { dev_info(&adapter->pdev->dev, "EH %s result: %s, scmd=0x%p\n", - str, ((rc == SUCCESS) ? "success" : "failed"), scmd); + str, rc == SUCCESS ? "success" : "failed", scmd); if (sas_dev) leapraid_sdev_put(sas_dev); } @@ -1145,19 +1133,19 @@ static int leapraid_eh_host_reset_handler(struct scsi_cmnd *scmd) (adapter->access_ctrl.host_removing ? "shost removing!" : "driver loading!"), scmd); rc = FAILED; - goto out; + goto out_host_reset_done; } - dev_info(&adapter->pdev->dev, "%s:%d issuing hard reset\n", + dev_info(&adapter->pdev->dev, "%s:%d: Issuing hard reset\n", __func__, __LINE__); if (leapraid_hard_reset_handler(adapter, FULL_RESET) < 0) rc = FAILED; else rc = SUCCESS; -out: +out_host_reset_done: dev_info(&adapter->pdev->dev, "EH HOST RESET result: %s, scmd=0x%p\n", - ((rc == SUCCESS) ? "success" : "failed"), scmd); + rc == SUCCESS ? "success" : "failed", scmd); return rc; } @@ -1183,30 +1171,35 @@ static int leapraid_slave_alloc(struct scsi_device *sdev) stgt_priv->num_luns++; sdev_priv->starget_priv = stgt_priv; sdev->hostdata = sdev_priv; - if ((stgt_priv->flg & LEAPRAID_TGT_FLG_RAID_MEMBER)) + if (stgt_priv->flg & LEAPRAID_TGT_FLG_RAID_MEMBER) sdev->no_uld_attach = LEAPRAID_NO_ULD_ATTACH; shost = dev_to_shost(&tgt->dev); adapter = shost_priv(shost); if (tgt->channel == RAID_CHANNEL) { - spin_lock_irqsave(&adapter->dev_topo.raid_volume_lock, flags); raid_volume = leapraid_raid_volume_find_by_id(adapter, tgt->id, tgt->channel); - if (raid_volume) + if (raid_volume) { + spin_lock_irqsave(&adapter->dev_topo.raid_volume_lock, + flags); raid_volume->sdev = sdev; - spin_unlock_irqrestore(&adapter->dev_topo.raid_volume_lock, - flags); + spin_unlock_irqrestore( + &adapter->dev_topo.raid_volume_lock, flags); + leapraid_raid_volume_put(raid_volume); + } } if (!(stgt_priv->flg & LEAPRAID_TGT_FLG_VOLUME)) { spin_lock_irqsave(&adapter->dev_topo.sas_dev_lock, flags); - sas_dev = leapraid_hold_lock_get_sas_dev_by_addr(adapter, - stgt_priv->sas_address, - stgt_priv->card_port); + sas_dev = leapraid_hold_lock_get_sas_dev_by_addr( + adapter, + stgt_priv->sas_address, + stgt_priv->card_port); if (sas_dev && !sas_dev->starget) { sdev_printk(KERN_INFO, sdev, - "%s: assign starget to sas_dev\n", __func__); + "%s: Assign starget to sas_dev\n", + __func__); sas_dev->starget = tgt; } @@ -1224,7 +1217,6 @@ static int leapraid_slave_cfg_volume(struct scsi_device *sdev) struct leapraid_raid_volume *raid_volume; struct leapraid_starget_priv *starget_priv; struct leapraid_sdev_priv *sdev_priv; - unsigned long flags; int qd; u16 hdl; @@ -1232,37 +1224,38 @@ static int leapraid_slave_cfg_volume(struct scsi_device *sdev) starget_priv = sdev_priv->starget_priv; hdl = starget_priv->hdl; - spin_lock_irqsave(&adapter->dev_topo.raid_volume_lock, flags); raid_volume = leapraid_raid_volume_find_by_hdl(adapter, hdl); - spin_unlock_irqrestore(&adapter->dev_topo.raid_volume_lock, flags); if (!raid_volume) { sdev_printk(KERN_WARNING, sdev, - "%s: raid_volume not found, hdl=0x%x\n", + "%s: RAID volume not found, hdl=0x%x\n", __func__, hdl); return 1; } if (leapraid_get_volume_cap(adapter, raid_volume)) { sdev_printk(KERN_ERR, sdev, - "%s: failed to get volume cap, hdl=0x%x\n", + "%s: Failed to get volume cap, hdl=0x%x\n", __func__, hdl); + leapraid_raid_volume_put(raid_volume); return 1; } qd = (raid_volume->dev_info & LEAPRAID_DEVTYP_SSP_TGT) ? - LEAPRAID_SAS_QUEUE_DEPTH : LEAPRAID_SATA_QUEUE_DEPTH; + adapter->adapter_attr.narrowport_max_queue_depth : + adapter->adapter_attr.sata_max_queue_depth; if (raid_volume->vol_type != LEAPRAID_VOL_TYPE_RAID0) - qd = LEAPRAID_RAID_QUEUE_DEPTH; + qd = adapter->adapter_attr.raid_volume_max_queue_depth; sdev_printk(KERN_INFO, sdev, - "raid volume: hdl=0x%04x, wwid=0x%016llx\n", + "RAID volume: hdl=0x%04x, wwid=0x%016llx\n", raid_volume->hdl, (unsigned long long)raid_volume->wwid); if (shost->max_sectors > LEAPRAID_MAX_SECTORS) blk_queue_max_hw_sectors(sdev->request_queue, LEAPRAID_MAX_SECTORS); - leapraid_adjust_sdev_queue_depth(sdev, qd); + leapraid_change_queue_depth(sdev, qd); + leapraid_raid_volume_put(raid_volume); return 0; } @@ -1280,13 +1273,14 @@ static int leapraid_slave_configure_extra(struct scsi_device *sdev, sdev_priv = sdev->hostdata; spin_lock_irqsave(&adapter->dev_topo.sas_dev_lock, flags); *is_target_ssp = false; - sas_dev = leapraid_hold_lock_get_sas_dev_by_addr(adapter, - sdev_priv->starget_priv->sas_address, - sdev_priv->starget_priv->card_port); + sas_dev = leapraid_hold_lock_get_sas_dev_by_addr( + adapter, + sdev_priv->starget_priv->sas_address, + sdev_priv->starget_priv->card_port); if (!sas_dev) { spin_unlock_irqrestore(&adapter->dev_topo.sas_dev_lock, flags); sdev_printk(KERN_WARNING, sdev, - "%s: sas_dev not found, sas=0x%llx\n", + "%s: SAS dev not found, sas=0x%llx\n", __func__, sdev_priv->starget_priv->sas_address); return 1; } @@ -1295,18 +1289,18 @@ static int leapraid_slave_configure_extra(struct scsi_device *sdev, sas_dev->volume_hdl = vol_hdl; sas_dev->volume_wwid = volume_wwid; if (sas_dev->dev_info & LEAPRAID_DEVTYP_SSP_TGT) { - *qd = (sas_dev->port_type > 1) ? + *qd = (sas_dev->port_connection > 1) ? adapter->adapter_attr.wideport_max_queue_depth : adapter->adapter_attr.narrowport_max_queue_depth; *is_target_ssp = true; if (sas_dev->dev_info & LEAPRAID_DEVTYP_SEP) - sdev_priv->sep = true; + sdev_priv->sep = 1; } else { *qd = adapter->adapter_attr.sata_max_queue_depth; } sdev_printk(KERN_INFO, sdev, - "sdev: dev name=0x%016llx, sas addr=0x%016llx\n", + "device name=0x%016llx, SAS addr=0x%016llx\n", (unsigned long long)sas_dev->dev_name, (unsigned long long)sas_dev->sas_addr); leapraid_sdev_put(sas_dev); @@ -1337,7 +1331,7 @@ static int leapraid_slave_configure(struct scsi_device *sdev) if (starget_priv->flg & LEAPRAID_TGT_FLG_RAID_MEMBER) { if (leapraid_cfg_get_volume_hdl(adapter, hdl, &vol_hdl)) { sdev_printk(KERN_WARNING, sdev, - "%s: get volume hdl failed, hdl=0x%x\n", + "%s: Get volume hdl failed, hdl=0x%x\n", __func__, hdl); return 1; } @@ -1345,7 +1339,7 @@ static int leapraid_slave_configure(struct scsi_device *sdev) if (vol_hdl && leapraid_cfg_get_volume_wwid(adapter, vol_hdl, &volume_wwid)) { sdev_printk(KERN_WARNING, sdev, - "%s: get wwid failed, volume_hdl=0x%x\n", + "%s: Get wwid failed, volume_hdl=0x%x\n", __func__, vol_hdl); return 1; } @@ -1358,7 +1352,7 @@ static int leapraid_slave_configure(struct scsi_device *sdev) return 1; } - leapraid_adjust_sdev_queue_depth(sdev, qd); + leapraid_change_queue_depth(sdev, qd); if (is_target_ssp) sas_read_port_mode_page(sdev); @@ -1405,17 +1399,19 @@ static int leapraid_target_alloc_raid(struct scsi_target *tgt) struct leapraid_adapter *adapter = shost_priv(shost); unsigned long flags; - starget_priv = (struct leapraid_starget_priv *)tgt->hostdata; - spin_lock_irqsave(&adapter->dev_topo.raid_volume_lock, flags); + starget_priv = tgt->hostdata; raid_volume = leapraid_raid_volume_find_by_id(adapter, tgt->id, tgt->channel); if (raid_volume) { + spin_lock_irqsave(&adapter->dev_topo.raid_volume_lock, flags); starget_priv->hdl = raid_volume->hdl; starget_priv->sas_address = raid_volume->wwid; starget_priv->flg |= LEAPRAID_TGT_FLG_VOLUME; raid_volume->starget = tgt; + spin_unlock_irqrestore(&adapter->dev_topo.raid_volume_lock, + flags); + leapraid_raid_volume_put(raid_volume); } - spin_unlock_irqrestore(&adapter->dev_topo.raid_volume_lock, flags); return 0; } @@ -1430,12 +1426,13 @@ static int leapraid_target_alloc_sas(struct scsi_target *tgt) shost = dev_to_shost(&tgt->dev); adapter = shost_priv(shost); - starget_priv = (struct leapraid_starget_priv *)tgt->hostdata; + starget_priv = tgt->hostdata; spin_lock_irqsave(&adapter->dev_topo.sas_dev_lock, flags); rphy = dev_to_rphy(tgt->dev.parent); - sas_dev = leapraid_hold_lock_get_sas_dev_by_addr_and_rphy(adapter, - rphy->identify.sas_address, - rphy); + sas_dev = leapraid_hold_lock_get_sas_dev_by_addr_and_rphy( + adapter, + rphy->identify.sas_address, + rphy); if (sas_dev) { starget_priv->sas_dev = sas_dev; starget_priv->card_port = sas_dev->card_port; @@ -1444,8 +1441,10 @@ static int leapraid_target_alloc_sas(struct scsi_target *tgt) sas_dev->channel = tgt->channel; sas_dev->id = tgt->id; sas_dev->starget = tgt; - if (test_bit(sas_dev->hdl, - (unsigned long *)adapter->dev_topo.pd_hdls)) + if (sas_dev->hdl && + sas_dev->hdl <= + adapter->adapter_attr.features.max_dev_handle && + test_bit(sas_dev->hdl, adapter->dev_topo.pd_hdls)) starget_priv->flg |= LEAPRAID_TGT_FLG_RAID_MEMBER; } spin_unlock_irqrestore(&adapter->dev_topo.sas_dev_lock, flags); @@ -1477,14 +1476,16 @@ static void leapraid_target_destroy_raid(struct scsi_target *tgt) struct leapraid_adapter *adapter = shost_priv(shost); unsigned long flags; - spin_lock_irqsave(&adapter->dev_topo.raid_volume_lock, flags); raid_volume = leapraid_raid_volume_find_by_id(adapter, tgt->id, tgt->channel); if (raid_volume) { + spin_lock_irqsave(&adapter->dev_topo.raid_volume_lock, flags); raid_volume->starget = NULL; raid_volume->sdev = NULL; + spin_unlock_irqrestore(&adapter->dev_topo.raid_volume_lock, + flags); + leapraid_raid_volume_put(raid_volume); } - spin_unlock_irqrestore(&adapter->dev_topo.raid_volume_lock, flags); } static void leapraid_target_destroy_sas(struct scsi_target *tgt) @@ -1526,12 +1527,12 @@ static void leapraid_target_destroy(struct scsi_target *tgt) if (tgt->channel == RAID_CHANNEL) { leapraid_target_destroy_raid(tgt); - goto out; + goto out_free; } leapraid_target_destroy_sas(tgt); -out: +out_free: kfree(starget_priv); tgt->hostdata = NULL; } @@ -1552,24 +1553,27 @@ static bool leapraid_scan_check_status(struct leapraid_adapter *adapter, if (adapter->driver_cmds.scan_dev_cmd.status & LEAPRAID_CMD_RESET) { dev_err(&adapter->pdev->dev, - "device scan: aborted due to reset\n"); + "Device scan: Aborted due to reset\n"); adapter->driver_cmds.scan_dev_cmd.status = LEAPRAID_CMD_NOT_USED; - adapter->scan_dev_desc.driver_loading = false; + adapter->scan_dev_desc.driver_loading = 0; + wake_up(&adapter->scan_dev_desc.wait_driver_loading); return true; } if (adapter->scan_dev_desc.scan_start_failed) { dev_err(&adapter->pdev->dev, - "device scan: failed with adapter_status=0x%08x\n", + "Device scan: Failed with adapter_status=0x%08x\n", adapter->scan_dev_desc.scan_start_failed); - adapter->scan_dev_desc.driver_loading = false; - adapter->scan_dev_desc.wait_scan_dev_done = false; - adapter->access_ctrl.host_removing = true; + adapter->scan_dev_desc.driver_loading = 0; + wake_up(&adapter->scan_dev_desc.wait_driver_loading); + adapter->scan_dev_desc.wait_scan_dev_done = 0; + adapter->access_ctrl.host_removing = 1; + wake_up(&adapter->access_ctrl.recovery_waitq); return true; } - dev_info(&adapter->pdev->dev, "device scan: SUCCESS\n"); + dev_info(&adapter->pdev->dev, "Device scan: SUCCESS\n"); adapter->driver_cmds.scan_dev_cmd.status = LEAPRAID_CMD_NOT_USED; leapraid_scan_dev_done(adapter); return true; @@ -1584,8 +1588,9 @@ static int leapraid_scan_finished(struct Scsi_Host *shost, unsigned long time) adapter->driver_cmds.scan_dev_cmd.status = LEAPRAID_CMD_NOT_USED; dev_err(&adapter->pdev->dev, - "device scan: failed with timeout 300s\n"); - adapter->scan_dev_desc.driver_loading = false; + "Device scan: Failed with timeout 300s\n"); + adapter->scan_dev_desc.driver_loading = 0; + wake_up(&adapter->scan_dev_desc.wait_driver_loading); return 1; } @@ -1595,10 +1600,12 @@ static int leapraid_scan_finished(struct Scsi_Host *shost, unsigned long time) if (need_hard_reset) { adapter->driver_cmds.scan_dev_cmd.status = LEAPRAID_CMD_NOT_USED; - dev_info(&adapter->pdev->dev, "%s:%d call hard_reset\n", + dev_info(&adapter->pdev->dev, "%s:%d: call hard_reset\n", __func__, __LINE__); - if (leapraid_hard_reset_handler(adapter, PART_RESET)) - adapter->scan_dev_desc.driver_loading = false; + if (leapraid_hard_reset_handler(adapter, PART_RESET)) { + adapter->scan_dev_desc.driver_loading = 0; + wake_up(&adapter->scan_dev_desc.wait_driver_loading); + } } return 1; @@ -1608,18 +1615,88 @@ static void leapraid_scan_start(struct Scsi_Host *shost) { struct leapraid_adapter *adapter = shost_priv(shost); - adapter->scan_dev_desc.scan_start = true; + adapter->scan_dev_desc.scan_start = 1; leapraid_scan_dev(adapter, true); } +static u32 leapraid_get_raid_qd(struct leapraid_adapter *adapter, + const struct leapraid_raid_volume *raid_volume, + bool default_qd) +{ + const struct leapraid_adapter_attr *attr = &adapter->adapter_attr; + + if (raid_volume->vol_type != LEAPRAID_VOL_TYPE_RAID0) + return default_qd ? LEAPRAID_RAID_QUEUE_DEPTH : + attr->raid_volume_max_queue_depth; + + if (raid_volume->dev_info & LEAPRAID_DEVTYP_SSP_TGT) + return default_qd ? LEAPRAID_SAS_QUEUE_DEPTH : + attr->narrowport_max_queue_depth; + + return default_qd ? LEAPRAID_SATA_QUEUE_DEPTH : + attr->sata_max_queue_depth; +} + static int leapraid_calc_max_queue_depth(struct scsi_device *sdev, int qdepth) { struct Scsi_Host *shost; + struct leapraid_adapter *adapter; + struct leapraid_starget_priv *starget_priv; + struct leapraid_sdev_priv *sdev_priv; + struct leapraid_raid_volume *raid_volume; + struct leapraid_sas_dev *sas_dev; int max_depth; + u32 default_qdepth = 0; + u32 fw_qdepth = 0; shost = sdev->host; + adapter = shost_priv(shost); max_depth = shost->can_queue; + sdev_priv = sdev->hostdata; + if (!sdev_priv) + goto out_tag_check; + + starget_priv = sdev_priv->starget_priv; + if (!starget_priv) + goto out_tag_check; + + if (starget_priv->flg & LEAPRAID_TGT_FLG_VOLUME) { + raid_volume = leapraid_raid_volume_find_by_hdl( + adapter, starget_priv->hdl); + if (raid_volume) { + default_qdepth = leapraid_get_raid_qd( + adapter, raid_volume, true); + fw_qdepth = leapraid_get_raid_qd( + adapter, raid_volume, false); + leapraid_raid_volume_put(raid_volume); + } + goto out_limit_check; + } + + sas_dev = leapraid_get_sas_dev_from_tgt(adapter, starget_priv); + if (sas_dev) { + if (sas_dev->dev_info & LEAPRAID_DEVTYP_SSP_TGT) { + default_qdepth = LEAPRAID_SAS_QUEUE_DEPTH; + fw_qdepth = (sas_dev->port_connection > 1) ? + adapter->adapter_attr.wideport_max_queue_depth : + adapter->adapter_attr.narrowport_max_queue_depth; + } + if (sas_dev->dev_info & LEAPRAID_DEVTYP_SATA_DEV) { + default_qdepth = LEAPRAID_SATA_QUEUE_DEPTH; + fw_qdepth = adapter->adapter_attr.sata_max_queue_depth; + } + leapraid_sdev_put(sas_dev); + } + +out_limit_check: + if (fw_qdepth > shost->can_queue && default_qdepth) + fw_qdepth = default_qdepth; + + if (fw_qdepth) + max_depth = min_t(int, max_depth, fw_qdepth); + +out_tag_check: if (!sdev->tagged_supported) max_depth = 1; @@ -1629,26 +1706,21 @@ static int leapraid_calc_max_queue_depth(struct scsi_device *sdev, int qdepth) return qdepth; } -static int leapraid_change_queue_depth(struct scsi_device *sdev, int qdepth) +int leapraid_change_queue_depth(struct scsi_device *sdev, int qdepth) { qdepth = leapraid_calc_max_queue_depth(sdev, qdepth); scsi_change_queue_depth(sdev, qdepth); return sdev->queue_depth; } -void leapraid_adjust_sdev_queue_depth(struct scsi_device *sdev, int qdepth) -{ - leapraid_change_queue_depth(sdev, qdepth); -} - static int leapraid_bios_param(struct scsi_device *sdev, struct block_device *bdev, sector_t capacity, int geom[]) { - int heads = 0; - int sectors = 0; + int heads; + int sectors; sector_t cylinders; if (scsi_partsize(bdev, capacity, geom)) @@ -1692,12 +1764,24 @@ static ssize_t host_sas_address_show(struct device *cdev, (unsigned long long)adapter->dev_topo.card.sas_address); } +static ssize_t board_name_show(struct device *cdev, + struct device_attribute *attr, char *buf) +{ + struct Scsi_Host *shost = class_to_shost(cdev); + struct leapraid_adapter *adapter = shost_priv(shost); + + return scnprintf(buf, PAGE_SIZE, "%s\n", + adapter->adapter_attr.board_name); +} + static DEVICE_ATTR_RO(fw_queue_depth); static DEVICE_ATTR_RO(host_sas_address); +static DEVICE_ATTR_RO(board_name); static struct device_attribute *leapraid_shost_attrs[] = { &dev_attr_fw_queue_depth, &dev_attr_host_sas_address, + &dev_attr_board_name, NULL, }; @@ -1706,9 +1790,18 @@ static ssize_t sas_address_show(struct device *dev, { struct scsi_device *sdev = to_scsi_device(dev); struct leapraid_sdev_priv *sas_device_priv_data = sdev->hostdata; + u64 sas_address; + + if (!sas_device_priv_data || !sas_device_priv_data->starget_priv) { + dev_err(&sdev->sdev_gendev, + "%s: Invalid sdev_priv or starget_priv\n", __func__); + return -EINVAL; + } + + sas_address = sas_device_priv_data->starget_priv->sas_address; return scnprintf(buf, PAGE_SIZE, "0x%016llx\n", - (unsigned long long)sas_device_priv_data->starget_priv->sas_address); + (unsigned long long)sas_address); } static ssize_t sas_device_handle_show(struct device *dev, @@ -1717,6 +1810,12 @@ static ssize_t sas_device_handle_show(struct device *dev, struct scsi_device *sdev = to_scsi_device(dev); struct leapraid_sdev_priv *sas_device_priv_data = sdev->hostdata; + if (!sas_device_priv_data || !sas_device_priv_data->starget_priv) { + dev_err(&sdev->sdev_gendev, + "%s: Invalid sdev_priv or starget_priv\n", __func__); + return -EINVAL; + } + return scnprintf(buf, PAGE_SIZE, "0x%04x\n", sas_device_priv_data->starget_priv->hdl); } @@ -1727,6 +1826,12 @@ static ssize_t sas_ncq_show(struct device *dev, struct device_attribute *attr, struct scsi_device *sdev = to_scsi_device(dev); struct leapraid_sdev_priv *sas_device_priv_data = sdev->hostdata; + if (!sas_device_priv_data) { + dev_err(&sdev->sdev_gendev, + "%s: Invalid sdev_priv\n", __func__); + return -EINVAL; + } + return scnprintf(buf, PAGE_SIZE, "%d\n", sas_device_priv_data->ncq); } @@ -1737,21 +1842,34 @@ static ssize_t sas_ncq_store(struct device *dev, struct scsi_device *sdev = to_scsi_device(dev); struct leapraid_sdev_priv *sas_device_priv_data = sdev->hostdata; unsigned char *vpd_pg89; - int ncq_op = 0; - bool ncq_supported = false; + int ncq_op; + bool ncq_supported; + + if (!sas_device_priv_data) { + dev_err(&sdev->sdev_gendev, + "%s: Invalid sdev_priv\n", __func__); + return -EINVAL; + } if (kstrtoint(buf, 0, &ncq_op)) - goto out; + return -EINVAL; + + if (ncq_op != 0 && ncq_op != 1) { + dev_err(&sdev->sdev_gendev, + "%s: Invalid NCQ value %d (only 0/1 allowed)\n", + __func__, ncq_op); + return -EINVAL; + } vpd_pg89 = kmalloc(LEAPRAID_VPD_PG89_MAX_LEN, GFP_KERNEL); if (!vpd_pg89) - goto out; + return -ENOMEM; if (!scsi_device_supports_vpd(sdev) || scsi_get_vpd_page(sdev, LEAPRAID_VPD_PAGE_ATA_INFO, vpd_pg89, LEAPRAID_VPD_PG89_MAX_LEN)) { kfree(vpd_pg89); - goto out; + return -EINVAL; } ncq_supported = (vpd_pg89[LEAPRAID_VPD_PG89_NCQ_BYTE_IDX] >> @@ -1760,9 +1878,7 @@ static ssize_t sas_ncq_store(struct device *dev, kfree(vpd_pg89); if (ncq_supported) sas_device_priv_data->ncq = ncq_op; - return strlen(buf); -out: - return -EINVAL; + return count; } static DEVICE_ATTR_RO(sas_address); @@ -1798,7 +1914,7 @@ static struct scsi_host_template leapraid_driver_template = { .can_queue = LEAPRAID_CAN_QUEUE_MIN, .this_id = LEAPRAID_THIS_ID_NONE, .sg_tablesize = LEAPRAID_SG_DEPTH, - .max_sectors = LEAPRAID_DEF_MAX_SECTORS, + .max_sectors = LEAPRAID_MAX_SECTORS, .max_segment_size = LEAPRAID_MAX_SEGMENT_SIZE, .cmd_per_lun = LEAPRAID_CMD_PER_LUN, .shost_attrs = leapraid_shost_attrs, @@ -1818,6 +1934,8 @@ static void leapraid_lock_init(struct leapraid_adapter *adapter) spin_lock_init(&adapter->dev_topo.topo_node_lock); spin_lock_init(&adapter->fw_evt_s.fw_evt_lock); spin_lock_init(&adapter->dev_topo.raid_volume_lock); + spin_lock_init(&adapter->dev_topo.enc_lock); + spin_lock_init(&adapter->boot_devs.lock); } static void leapraid_list_init(struct leapraid_adapter *adapter) @@ -1834,18 +1952,23 @@ static void leapraid_list_init(struct leapraid_adapter *adapter) static int leapraid_probe(struct pci_dev *pdev, const struct pci_device_id *id) { - struct leapraid_adapter *adapter = NULL; - struct Scsi_Host *shost = NULL; + struct leapraid_adapter *adapter; + struct Scsi_Host *shost; int rc; shost = scsi_host_alloc(&leapraid_driver_template, sizeof(struct leapraid_adapter)); - if (!shost) + if (!shost) { + dev_err(&pdev->dev, + "%s: SCSI host alloc failed\n", __func__); return -ENODEV; + } adapter = shost_priv(shost); memset(adapter, 0, sizeof(struct leapraid_adapter)); - adapter->adapter_attr.id = leapraid_ids++; + + init_waitqueue_head(&adapter->access_ctrl.recovery_waitq); + adapter->adapter_attr.id = atomic_inc_return(&leapraid_ids) - 1; adapter->adapter_attr.enable_mp = enable_mp; @@ -1860,8 +1983,8 @@ static int leapraid_probe(struct pci_dev *pdev, const struct pci_device_id *id) adapter->fw_log_desc.open_pcie_trace = open_pcie_trace; leapraid_lock_init(adapter); leapraid_list_init(adapter); - sprintf(adapter->adapter_attr.name, "%s%d", - LEAPRAID_DRIVER_NAME, adapter->adapter_attr.id); + snprintf(adapter->adapter_attr.name, LEAPRAID_NAME_LENGTH, "%s%d", + LEAPRAID_DRIVER_NAME, adapter->adapter_attr.id); shost->max_cmd_len = LEAPRAID_MAX_CDB_LEN; shost->max_lun = LEAPRAID_MAX_LUNS; @@ -1875,12 +1998,17 @@ static int leapraid_probe(struct pci_dev *pdev, const struct pci_device_id *id) adapter->fw_evt_s.fw_evt_thread = alloc_ordered_workqueue(adapter->fw_evt_s.fw_evt_name, 0); if (!adapter->fw_evt_s.fw_evt_thread) { + dev_err(&adapter->pdev->dev, + "%s: Failed to create fw event workqueue\n", __func__); rc = -ENODEV; goto evt_wq_fail; } - adapter->scan_dev_desc.driver_loading = true; - if ((leapraid_ctrl_init(adapter))) { + init_waitqueue_head(&adapter->scan_dev_desc.wait_driver_loading); + adapter->scan_dev_desc.driver_loading = 1; + if (leapraid_ctrl_init(adapter)) { + dev_err(&adapter->pdev->dev, + "%s: Adapter init failed\n", __func__); rc = -ENODEV; goto ctrl_init_fail; } @@ -1888,9 +2016,8 @@ static int leapraid_probe(struct pci_dev *pdev, const struct pci_device_id *id) rc = scsi_add_host(shost, &pdev->dev); if (rc) { - spin_lock(&leapraid_adapter_lock); - list_del(&adapter->list); - spin_unlock(&leapraid_adapter_lock); + dev_err(&pdev->dev, + "%s: SCSI host add failed\n", __func__); goto scsi_add_shost_fail; } @@ -1900,6 +2027,7 @@ static int leapraid_probe(struct pci_dev *pdev, const struct pci_device_id *id) scsi_add_shost_fail: leapraid_remove_ctrl(adapter); ctrl_init_fail: + leapraid_overheat_cleanup(adapter); destroy_workqueue(adapter->fw_evt_s.fw_evt_thread); evt_wq_fail: spin_lock(&leapraid_adapter_lock); @@ -1909,7 +2037,7 @@ static int leapraid_probe(struct pci_dev *pdev, const struct pci_device_id *id) return rc; } -static void leapraid_cleanup_lists(struct leapraid_adapter *adapter) +void leapraid_cleanup_lists(struct leapraid_adapter *adapter) { struct leapraid_raid_volume *raid_volume, *next_raid_volume; struct leapraid_starget_priv *starget_priv_data; @@ -1921,12 +2049,14 @@ static void leapraid_cleanup_lists(struct leapraid_adapter *adapter) &adapter->dev_topo.raid_volume_list, list) { if (raid_volume->starget) { starget_priv_data = raid_volume->starget->hostdata; - starget_priv_data->deleted = true; + if (starget_priv_data) + starget_priv_data->deleted = 1; scsi_remove_target(&raid_volume->starget->dev); } - pr_info("removing hdl=0x%04x, wwid=0x%016llx\n", - raid_volume->hdl, - (unsigned long long)raid_volume->wwid); + dev_info(&adapter->pdev->dev, + "removing hdl=0x%04x, wwid=0x%016llx\n", + raid_volume->hdl, + (unsigned long long)raid_volume->wwid); leapraid_raid_volume_remove(adapter, raid_volume); } @@ -1935,16 +2065,18 @@ static void leapraid_cleanup_lists(struct leapraid_adapter *adapter) port_list) { if (leapraid_port->remote_identify.device_type == SAS_END_DEVICE) - leapraid_sas_dev_remove_by_sas_address(adapter, + leapraid_sas_dev_remove_by_sas_address( + adapter, leapraid_port->remote_identify.sas_address, leapraid_port->card_port); else if (leapraid_port->remote_identify.device_type == SAS_EDGE_EXPANDER_DEVICE || leapraid_port->remote_identify.device_type == SAS_FANOUT_EXPANDER_DEVICE) - leapraid_exp_rm(adapter, - leapraid_port->remote_identify.sas_address, - leapraid_port->card_port); + leapraid_exp_rm( + adapter, + leapraid_port->remote_identify.sas_address, + leapraid_port->card_port); } list_for_each_entry_safe(port, port_next, @@ -1969,27 +2101,26 @@ static void leapraid_cleanup_lists(struct leapraid_adapter *adapter) static void leapraid_remove(struct pci_dev *pdev) { struct leapraid_adapter *adapter = pdev_to_adapter(pdev); - struct Scsi_Host *shost = pdev_to_shost(pdev); + struct Scsi_Host *shost = pci_get_drvdata(pdev); struct workqueue_struct *wq; unsigned long flags; if (!shost || !adapter) { - dev_err(&pdev->dev, "unable to remove!\n"); + dev_err(&pdev->dev, "Unable to remove!\n"); return; } - while (adapter->scan_dev_desc.driver_loading) - ssleep(1); + wait_event(adapter->scan_dev_desc.wait_driver_loading, + !adapter->scan_dev_desc.driver_loading); + wait_event(adapter->scan_dev_desc.wait_driver_loading, + !atomic_read(&adapter->overheat_desc.thermal_alert)); - while (adapter->access_ctrl.shost_recovering) - ssleep(1); - - adapter->access_ctrl.host_removing = true; + adapter->access_ctrl.host_removing = 1; + wake_up(&adapter->access_ctrl.recovery_waitq); leapraid_wait_cmds_done(adapter); leapraid_smart_polling_stop(adapter); - leapraid_free_internal_scsi_cmd(adapter); if (leapraid_pci_removed(adapter)) { leapraid_mq_polling_pause(adapter); @@ -2004,7 +2135,6 @@ static void leapraid_remove(struct pci_dev *pdev) if (wq) destroy_workqueue(wq); - leapraid_ir_shutdown(adapter); sas_remove_host(shost); leapraid_cleanup_lists(adapter); leapraid_remove_ctrl(adapter); @@ -2017,18 +2147,20 @@ static void leapraid_remove(struct pci_dev *pdev) static void leapraid_shutdown(struct pci_dev *pdev) { struct leapraid_adapter *adapter = pdev_to_adapter(pdev); - struct Scsi_Host *shost = pdev_to_shost(pdev); + struct Scsi_Host *shost = pci_get_drvdata(pdev); struct workqueue_struct *wq; unsigned long flags; if (!shost || !adapter) { - dev_err(&pdev->dev, "unable to shutdown!\n"); + dev_err(&pdev->dev, "Unable to shutdown!\n"); return; } - adapter->access_ctrl.host_removing = true; + adapter->access_ctrl.host_removing = 1; + wake_up(&adapter->access_ctrl.recovery_waitq); leapraid_wait_cmds_done(adapter); leapraid_clean_active_fw_evt(adapter); + leapraid_overheat_cleanup(adapter); leapraid_fw_log_stop(adapter); spin_lock_irqsave(&adapter->fw_evt_s.fw_evt_lock, flags); wq = adapter->fw_evt_s.fw_evt_thread; @@ -2037,7 +2169,6 @@ static void leapraid_shutdown(struct pci_dev *pdev) if (wq) destroy_workqueue(wq); - leapraid_ir_shutdown(adapter); leapraid_disable_controller(adapter); } @@ -2045,29 +2176,31 @@ static pci_ers_result_t leapraid_pci_error_detected(struct pci_dev *pdev, pci_channel_state_t state) { struct leapraid_adapter *adapter = pdev_to_adapter(pdev); - struct Scsi_Host *shost = pdev_to_shost(pdev); + struct Scsi_Host *shost = pci_get_drvdata(pdev); if (!shost || !adapter) { - dev_err(&pdev->dev, "failed to error detected for device\n"); + dev_err(&pdev->dev, "Failed to error detected for device\n"); return PCI_ERS_RESULT_DISCONNECT; } - pr_err("%s: pci error detected, state=%d\n", - adapter->adapter_attr.name, state); + dev_err(&pdev->dev, "%s: PCI error detected, state=%d\n", + adapter->adapter_attr.name, state); switch (state) { case pci_channel_io_normal: return PCI_ERS_RESULT_CAN_RECOVER; case pci_channel_io_frozen: - adapter->access_ctrl.pcie_recovering = true; + adapter->access_ctrl.pcie_recovering = 1; scsi_block_requests(adapter->shost); + leapraid_overheat_cleanup(adapter); leapraid_smart_polling_stop(adapter); leapraid_check_scheduled_fault_stop(adapter); leapraid_fw_log_stop(adapter); leapraid_disable_controller(adapter); return PCI_ERS_RESULT_NEED_RESET; case pci_channel_io_perm_failure: - adapter->access_ctrl.pcie_recovering = true; + adapter->access_ctrl.pcie_recovering = 1; + leapraid_overheat_cleanup(adapter); leapraid_smart_polling_stop(adapter); leapraid_check_scheduled_fault_stop(adapter); leapraid_fw_log_stop(adapter); @@ -2082,15 +2215,15 @@ static pci_ers_result_t leapraid_pci_error_detected(struct pci_dev *pdev, static pci_ers_result_t leapraid_pci_mmio_enabled(struct pci_dev *pdev) { struct leapraid_adapter *adapter = pdev_to_adapter(pdev); - struct Scsi_Host *shost = pdev_to_shost(pdev); + struct Scsi_Host *shost = pci_get_drvdata(pdev); if (!shost || !adapter) { dev_err(&pdev->dev, - "failed to enable mmio for device\n"); + "Failed to enable mmio for device\n"); return PCI_ERS_RESULT_DISCONNECT; } - dev_info(&pdev->dev, "%s: pci error mmio enabled\n", + dev_info(&pdev->dev, "%s: PCI error mmio enabled\n", adapter->adapter_attr.name); return PCI_ERS_RESULT_RECOVERED; @@ -2099,43 +2232,47 @@ static pci_ers_result_t leapraid_pci_mmio_enabled(struct pci_dev *pdev) static pci_ers_result_t leapraid_pci_slot_reset(struct pci_dev *pdev) { struct leapraid_adapter *adapter = pdev_to_adapter(pdev); - struct Scsi_Host *shost = pdev_to_shost(pdev); + struct Scsi_Host *shost = pci_get_drvdata(pdev); int rc; if (!shost || !adapter) { dev_err(&pdev->dev, - "failed to slot reset for device\n"); + "Failed to slot reset for device\n"); return PCI_ERS_RESULT_DISCONNECT; } - dev_err(&pdev->dev, "%s pci error slot reset\n", + dev_err(&pdev->dev, "%s PCI error slot reset\n", adapter->adapter_attr.name); - adapter->access_ctrl.pcie_recovering = false; + adapter->access_ctrl.pcie_recovering = 0; adapter->pdev = pdev; pci_restore_state(pdev); - if (leapraid_set_pcie_and_notification(adapter)) + if (leapraid_set_pcie_and_notification(adapter)) { + dev_err(&pdev->dev, + "%s: Failed to set PCIe state and notification\n", + __func__); return PCI_ERS_RESULT_DISCONNECT; + } - dev_info(&pdev->dev, "%s: hard reset triggered by pci slot reset\n", + dev_info(&pdev->dev, "%s: Hard reset triggered by PCI slot reset\n", adapter->adapter_attr.name); - dev_info(&adapter->pdev->dev, "%s:%d call hard_reset\n", + dev_info(&adapter->pdev->dev, "%s: %d: call hard_reset\n", __func__, __LINE__); rc = leapraid_hard_reset_handler(adapter, FULL_RESET); dev_info(&pdev->dev, "%s hard reset: %s\n", - adapter->adapter_attr.name, (rc == 0) ? "success" : "failed"); + adapter->adapter_attr.name, rc == 0 ? "success" : "failed"); - return (rc == 0) ? PCI_ERS_RESULT_RECOVERED : + return rc == 0 ? PCI_ERS_RESULT_RECOVERED : PCI_ERS_RESULT_DISCONNECT; } static void leapraid_pci_resume(struct pci_dev *pdev) { - struct Scsi_Host *shost = pdev_to_shost(pdev); + struct Scsi_Host *shost = pci_get_drvdata(pdev); struct leapraid_adapter *adapter = pdev_to_adapter(pdev); if (!shost || !adapter) { - dev_err(&pdev->dev, "failed to resume\n"); + dev_err(&pdev->dev, "Failed to resume\n"); return; } @@ -2159,24 +2296,24 @@ static struct pci_error_handlers leapraid_err_handler = { static int leapraid_suspend(struct pci_dev *pdev, pm_message_t state) { struct leapraid_adapter *adapter = pdev_to_adapter(pdev); - struct Scsi_Host *shost = pdev_to_shost(pdev); + struct Scsi_Host *shost = pci_get_drvdata(pdev); pci_power_t device_state; if (!shost || !adapter) { dev_err(&pdev->dev, - "suspend failed, invalid host or adapter\n"); + "Suspend failed, invalid host or adapter\n"); return -ENXIO; } + leapraid_overheat_cleanup(adapter); leapraid_smart_polling_stop(adapter); leapraid_check_scheduled_fault_stop(adapter); leapraid_fw_log_stop(adapter); flush_scheduled_work(); scsi_block_requests(shost); device_state = pci_choose_state(pdev, state); - leapraid_ir_shutdown(adapter); - dev_info(&pdev->dev, "entering PCI power state D%d, (slot=%s)\n", + dev_info(&pdev->dev, "Entering PCI power state D%d, (slot=%s)\n", device_state, pci_name(pdev)); pci_save_state(pdev); @@ -2188,18 +2325,18 @@ static int leapraid_suspend(struct pci_dev *pdev, pm_message_t state) static int leapraid_resume(struct pci_dev *pdev) { struct leapraid_adapter *adapter = pdev_to_adapter(pdev); - struct Scsi_Host *shost = pdev_to_shost(pdev); + struct Scsi_Host *shost = pci_get_drvdata(pdev); pci_power_t device_state = pdev->current_state; int rc; if (!shost || !adapter) { dev_err(&pdev->dev, - "resume failed, invalid host or adapter\n"); + "Resume failed, invalid host or adapter\n"); return -ENXIO; } dev_info(&pdev->dev, - "resuming device %s, previous state D%d\n", + "Resuming device %s, previous state D%d\n", pci_name(pdev), device_state); pci_set_power_state(pdev, PCI_D0); @@ -2207,12 +2344,22 @@ static int leapraid_resume(struct pci_dev *pdev) pci_restore_state(pdev); adapter->pdev = pdev; rc = leapraid_set_pcie_and_notification(adapter); - if (rc) + if (rc) { + dev_err(&pdev->dev, + "%s: Failed to set PCIe state and notification\n", + __func__); return rc; + } - dev_info(&adapter->pdev->dev, "%s:%d call hard_reset\n", + dev_info(&adapter->pdev->dev, "%s:%d: call hard_reset\n", __func__, __LINE__); - leapraid_hard_reset_handler(adapter, PART_RESET); + rc = leapraid_hard_reset_handler(adapter, PART_RESET); + if (rc) { + dev_err(&adapter->pdev->dev, + "%s: Hard reset failed during resume, rc=%d\n", + __func__, rc); + return rc; + } scsi_unblock_requests(shost); leapraid_check_scheduled_fault_start(adapter); leapraid_fw_log_start(adapter); @@ -2238,29 +2385,37 @@ static int __init leapraid_init(void) { int error; - pr_info("%s version %s loaded\n", LEAPRAID_DRIVER_NAME, - LEAPRAID_DRIVER_VERSION); + pr_info("%s initializing\n", LEAPRAID_DRIVER_NAME); leapraid_transport_template = sas_attach_transport(&leapraid_transport_functions); - if (!leapraid_transport_template) + if (!leapraid_transport_template) { + pr_err("%s: Failed to attach SAS transport\n", + LEAPRAID_DRIVER_NAME); return -ENODEV; - - leapraid_ids = 0; - - leapraid_ctl_init(); + } error = pci_register_driver(&leapraid_driver); - if (error) + if (error) { + pr_err("%s: PCI driver registration failed: %d\n", + LEAPRAID_DRIVER_NAME, error); + sas_release_transport(leapraid_transport_template); + return error; + } + + error = leapraid_ctl_init(); + if (error) { + pci_unregister_driver(&leapraid_driver); sas_release_transport(leapraid_transport_template); + return error; + } - return error; + return 0; } static void __exit leapraid_exit(void) { - pr_info("leapraid version %s unloading\n", - LEAPRAID_DRIVER_VERSION); + pr_info("%s exiting\n", LEAPRAID_DRIVER_NAME); leapraid_ctl_exit(); pci_unregister_driver(&leapraid_driver); diff --git a/drivers/scsi/leapraid/leapraid_transport.c b/drivers/scsi/leapraid/leapraid_transport.c index d224449732a3..738bc55df416 100644 --- a/drivers/scsi/leapraid/leapraid_transport.c +++ b/drivers/scsi/leapraid/leapraid_transport.c @@ -1,10 +1,9 @@ // SPDX-License-Identifier: GPL-2.0 /* - * Copyright (C) 2025 LeapIO Tech Inc. + * Copyright (C) 2026 LeapIO Tech Inc. * - * LeapRAID Storage and RAID Controller driver. + * LeapRAID storage and RAID controller driver. */ - #include <scsi/scsi_host.h> #include "leapraid_func.h" @@ -16,10 +15,8 @@ static struct leapraid_topo_node *leapraid_transport_topo_node_by_sas_addr( { if (adapter->dev_topo.card.sas_address == sas_addr) return &adapter->dev_topo.card; - else - return leapraid_exp_find_by_sas_address(adapter, - sas_addr, - card_port); + + return leapraid_exp_find_by_sas_address(adapter, sas_addr, card_port); } static u8 leapraid_get_port_id_by_expander(struct leapraid_adapter *adapter, @@ -49,7 +46,8 @@ static u8 leapraid_get_port_id_by_end_dev(struct leapraid_adapter *adapter, u8 port_id = 0xFF; spin_lock_irqsave(&adapter->dev_topo.sas_dev_lock, flags); - sas_dev = leapraid_hold_lock_get_sas_dev_by_addr_and_rphy(adapter, + sas_dev = leapraid_hold_lock_get_sas_dev_by_addr_and_rphy( + adapter, rphy->identify.sas_address, rphy); if (sas_dev) { @@ -131,10 +129,9 @@ static enum sas_linkrate leapraid_transport_convert_phy_link_rate(u8 link_rate) }, }; - for (i = 0; i < ARRAY_SIZE(linkrate_table); i++) { + for (i = 0; i < ARRAY_SIZE(linkrate_table); i++) if (linkrate_table[i].in == link_rate) return linkrate_table[i].out; - } return SAS_LINK_RATE_UNKNOWN; } @@ -192,7 +189,7 @@ static void leapraid_set_identify_protocol_flags(u32 dev_info, }; for (i = 0; i < ARRAY_SIZE(mappings); i++) - if ((dev_info & mappings[i].mask) && mappings[i].target) + if (dev_info & mappings[i].mask && mappings[i].target) *mappings[i].target |= mappings[i].protocol; } @@ -207,13 +204,19 @@ static int leapraid_transport_set_identify(struct leapraid_adapter *adapter, if ((adapter->access_ctrl.shost_recovering && !adapter->scan_dev_desc.driver_loading) || - adapter->access_ctrl.pcie_recovering) + adapter->access_ctrl.pcie_recovering) { + dev_warn(&adapter->pdev->dev, + "%s: Failed, shost_recovering=%d pcie_recovering=%d\n", + __func__, + adapter->access_ctrl.shost_recovering, + adapter->access_ctrl.pcie_recovering); return -EFAULT; + } cfgp1.form = LEAPRAID_SAS_DEV_CFG_PGAD_HDL; cfgp2.handle = hdl; - if ((leapraid_op_config_page(adapter, &sas_dev_pg0, cfgp1, - cfgp2, GET_SAS_DEVICE_PG0))) + if (leapraid_op_config_page(adapter, &sas_dev_pg0, cfgp1, + cfgp2, GET_SAS_DEVICE_PG0)) return -ENXIO; memset(identify, 0, sizeof(struct sas_identify)); @@ -248,27 +251,34 @@ static void leapraid_transport_exp_set_edev(struct leapraid_adapter *adapter, struct leapraid_smp_passthrough_rep *smp_passthrough_rep; struct leapraid_rep_manu_reply *rep_manu_reply; u8 *component_id; - ssize_t __maybe_unused ret; smp_passthrough_rep = - (void *)(&adapter->driver_cmds.transport_cmd.reply); + (void *)&adapter->driver_cmds.transport_cmd.reply; if (le16_to_cpu(smp_passthrough_rep->resp_data_len) != sizeof(struct leapraid_rep_manu_reply)) return; rep_manu_reply = data_out + sizeof(struct leapraid_rep_manu_request); - ret = strscpy(edev->vendor_id, rep_manu_reply->vendor_identification, - SAS_EXPANDER_VENDOR_ID_LEN); - ret = strscpy(edev->product_id, rep_manu_reply->product_identification, - SAS_EXPANDER_PRODUCT_ID_LEN); - ret = strscpy(edev->product_rev, - rep_manu_reply->product_revision_level, - SAS_EXPANDER_PRODUCT_REV_LEN); + + memcpy(edev->vendor_id, rep_manu_reply->vendor_identification, + SAS_EXPANDER_VENDOR_ID_LEN); + edev->vendor_id[SAS_EXPANDER_VENDOR_ID_LEN] = '\0'; + + memcpy(edev->product_id, rep_manu_reply->product_identification, + SAS_EXPANDER_PRODUCT_ID_LEN); + edev->product_id[SAS_EXPANDER_PRODUCT_ID_LEN] = '\0'; + + memcpy(edev->product_rev, rep_manu_reply->product_revision_level, + SAS_EXPANDER_PRODUCT_REV_LEN); + edev->product_rev[SAS_EXPANDER_PRODUCT_REV_LEN] = '\0'; + edev->level = rep_manu_reply->sas_format & 1; if (edev->level) { - ret = strscpy(edev->component_vendor_id, - rep_manu_reply->component_vendor_identification, - SAS_EXPANDER_COMPONENT_VENDOR_ID_LEN); + memcpy(edev->component_vendor_id, + rep_manu_reply->comp_vendor_identification, + SAS_EXPANDER_COMPONENT_VENDOR_ID_LEN); + edev->component_vendor_id[ + SAS_EXPANDER_COMPONENT_VENDOR_ID_LEN] = '\0'; component_id = (u8 *)&rep_manu_reply->component_id; edev->component_id = component_id[0] << 8 | component_id[1]; @@ -291,18 +301,24 @@ static int leapraid_transport_exp_report_manu(struct leapraid_adapter *adapter, size_t c2h_size; size_t h2c_size; void *psge; - int rc = 0; + int rc; if (adapter->access_ctrl.shost_recovering || adapter->access_ctrl.pcie_recovering) { + dev_warn(&adapter->pdev->dev, + "%s: Failed, shost_recovering=%d pcie_recovering=%d\n", + __func__, + adapter->access_ctrl.shost_recovering, + adapter->access_ctrl.pcie_recovering); return -EFAULT; } mutex_lock(&adapter->driver_cmds.transport_cmd.mutex); adapter->driver_cmds.transport_cmd.status = LEAPRAID_CMD_PENDING; - rc = leapraid_check_adapter_is_op(adapter); + rc = leapraid_check_adapter_is_op(adapter, LEAPRAID_DB_WAIT_OP_SHORT, + __func__); if (rc) - goto out; + goto out_cleanup; h2c_size = sizeof(struct leapraid_rep_manu_request); c2h_size = sizeof(struct leapraid_rep_manu_reply); @@ -312,7 +328,7 @@ static int leapraid_transport_exp_report_manu(struct leapraid_adapter *adapter, GFP_ATOMIC); if (!data_out) { rc = -ENOMEM; - goto out; + goto out_cleanup; } rep_manu_request = data_out; @@ -323,8 +339,9 @@ static int leapraid_transport_exp_report_manu(struct leapraid_adapter *adapter, rep_manu_request->request_length = 0; smp_passthrough_req = - leapraid_get_task_desc(adapter, - adapter->driver_cmds.transport_cmd.inter_taskid); + leapraid_get_task_desc( + adapter, + adapter->driver_cmds.transport_cmd.inter_taskid); memset(smp_passthrough_req, 0, sizeof(struct leapraid_smp_passthrough_req)); smp_passthrough_req->func = LEAPRAID_FUNC_SMP_PASSTHROUGH; @@ -342,11 +359,13 @@ static int leapraid_transport_exp_report_manu(struct leapraid_adapter *adapter, wait_for_completion_timeout(&adapter->driver_cmds.transport_cmd.done, LEAPRAID_TRANSPORT_CMD_TIMEOUT * HZ); if (!(adapter->driver_cmds.transport_cmd.status & LEAPRAID_CMD_DONE)) { + rc = -ETIMEDOUT; dev_err(&adapter->pdev->dev, - "%s: smp passthrough to exp timeout\n", - __func__); + "%s: SMP passthrough timeout, st=0x%x\n", + __func__, adapter->driver_cmds.transport_cmd.status); + leapraid_log_req_context(adapter, smp_passthrough_req); if (!(adapter->driver_cmds.transport_cmd.status & - LEAPRAID_CMD_RESET)) + LEAPRAID_CMD_RESET)) issue_reset = true; goto hard_reset; @@ -358,11 +377,11 @@ static int leapraid_transport_exp_report_manu(struct leapraid_adapter *adapter, hard_reset: if (issue_reset) { - dev_info(&adapter->pdev->dev, "%s:%d call hard_reset\n", + dev_info(&adapter->pdev->dev, "%s:%d: call hard_reset\n", __func__, __LINE__); - leapraid_hard_reset_handler(adapter, FULL_RESET); + rc = leapraid_hard_reset_handler(adapter, FULL_RESET); } -out: +out_cleanup: adapter->driver_cmds.transport_cmd.status = LEAPRAID_CMD_NOT_USED; if (data_out) dma_free_coherent(&adapter->pdev->dev, h2c_size + c2h_size, @@ -376,13 +395,14 @@ static void leapraid_transport_del_port(struct leapraid_adapter *adapter, struct leapraid_sas_port *sas_port) { dev_info(&sas_port->port->dev, - "remove port: sas addr=0x%016llx\n", + "Remove port: SAS addr=0x%016llx\n", (unsigned long long)sas_port->remote_identify.sas_address); switch (sas_port->remote_identify.device_type) { case SAS_END_DEVICE: - leapraid_sas_dev_remove_by_sas_address(adapter, - sas_port->remote_identify.sas_address, - sas_port->card_port); + leapraid_sas_dev_remove_by_sas_address( + adapter, + sas_port->remote_identify.sas_address, + sas_port->card_port); break; case SAS_EDGE_EXPANDER_DEVICE: case SAS_FANOUT_EXPANDER_DEVICE: @@ -399,13 +419,13 @@ static void leapraid_transport_del_phy(struct leapraid_adapter *adapter, struct leapraid_card_phy *card_phy) { dev_info(&card_phy->phy->dev, - "remove phy: sas addr=0x%016llx, phy=%d\n", + "Remove PHY: SAS addr=0x%016llx, phy=%d\n", (unsigned long long)sas_port->remote_identify.sas_address, card_phy->phy_id); list_del(&card_phy->port_siblings); sas_port->phys_num--; sas_port_delete_phy(sas_port->port, card_phy->phy); - card_phy->phy_is_assigned = false; + card_phy->phy_is_assigned = 0; } static void leapraid_transport_add_phy(struct leapraid_adapter *adapter, @@ -413,16 +433,17 @@ static void leapraid_transport_add_phy(struct leapraid_adapter *adapter, struct leapraid_card_phy *card_phy) { dev_info(&card_phy->phy->dev, - "add phy: sas addr=0x%016llx, phy=%d\n", + "Add PHY: SAS addr=0x%016llx, phy=%d\n", (unsigned long long)sas_port->remote_identify.sas_address, card_phy->phy_id); list_add_tail(&card_phy->port_siblings, &sas_port->phy_list); sas_port->phys_num++; sas_port_add_phy(sas_port->port, card_phy->phy); - card_phy->phy_is_assigned = true; + card_phy->phy_is_assigned = 1; } -void leapraid_transport_attach_phy_to_port(struct leapraid_adapter *adapter, +void leapraid_transport_attach_phy_to_port( + struct leapraid_adapter *adapter, struct leapraid_topo_node *topo_node, struct leapraid_card_phy *card_phy, u64 sas_address, @@ -454,7 +475,8 @@ void leapraid_transport_attach_phy_to_port(struct leapraid_adapter *adapter, } } -void leapraid_transport_detach_phy_to_port(struct leapraid_adapter *adapter, +void leapraid_transport_detach_phy_to_port( + struct leapraid_adapter *adapter, struct leapraid_topo_node *topo_node, struct leapraid_card_phy *target_card_phy) { @@ -482,7 +504,8 @@ void leapraid_transport_detach_phy_to_port(struct leapraid_adapter *adapter, } } -static void leapraid_detach_phy_from_old_port(struct leapraid_adapter *adapter, +static void leapraid_detach_phy_from_old_port( + struct leapraid_adapter *adapter, struct leapraid_topo_node *topo_node, u64 sas_address, struct leapraid_card_port *card_port) @@ -495,9 +518,10 @@ static void leapraid_detach_phy_from_old_port(struct leapraid_adapter *adapter, topo_node->card_phy[i].card_port != card_port) continue; if (topo_node->card_phy[i].phy_is_assigned) - leapraid_transport_detach_phy_to_port(adapter, - topo_node, - &topo_node->card_phy[i]); + leapraid_transport_detach_phy_to_port( + adapter, + topo_node, + &topo_node->card_phy[i]); } } @@ -512,8 +536,11 @@ static struct leapraid_sas_port *leapraid_prepare_sas_port( unsigned long flags; sas_port = kzalloc(sizeof(*sas_port), GFP_KERNEL); - if (!sas_port) + if (!sas_port) { + dev_warn(&adapter->pdev->dev, + "%s: Failed alloc sas_port\n", __func__); return NULL; + } INIT_LIST_HEAD(&sas_port->port_list); INIT_LIST_HEAD(&sas_port->phy_list); @@ -526,27 +553,30 @@ static struct leapraid_sas_port *leapraid_prepare_sas_port( if (!topo_node) { dev_err(&adapter->pdev->dev, - "%s: failed to find parent node for sas addr 0x%016llx!\n", + "%s: Failed to locate parent for SAS 0x%016llx!\n", __func__, sas_address); - kfree(sas_port); - return NULL; + goto out_cleanup; } if (leapraid_transport_set_identify(adapter, handle, - &sas_port->remote_identify)) { - kfree(sas_port); - return NULL; - } + &sas_port->remote_identify)) + goto out_cleanup; if (sas_port->remote_identify.device_type == SAS_PHY_UNUSED) { - kfree(sas_port); - return NULL; + dev_warn(&adapter->pdev->dev, + "%s: Failed, device type is SAS_PHY_UNUSED\n", + __func__); + goto out_cleanup; } sas_port->card_port = card_port; *out_topo_node = topo_node; return sas_port; + +out_cleanup: + kfree(sas_port); + return NULL; } static int leapraid_bind_phys_and_vphy(struct leapraid_adapter *adapter, @@ -576,12 +606,12 @@ static int leapraid_bind_phys_and_vphy(struct leapraid_adapter *adapter, vphy = leapraid_get_vphy_by_phy(card_port, i); if (!vphy) - return -1; + return LEAPRAID_OPERATION_FAILED; } } *out_vphy = vphy; - return sas_port->phys_num ? 0 : -1; + return sas_port->phys_num ? 0 : LEAPRAID_OPERATION_FAILED; } static struct sas_rphy *leapraid_create_and_register_rphy( @@ -596,26 +626,42 @@ static struct sas_rphy *leapraid_create_and_register_rphy( struct sas_port *port; struct sas_rphy *rphy; - if (!topo_node->parent_dev) - return NULL; + if (sas_port->remote_identify.device_type == SAS_END_DEVICE) { + sas_dev = leapraid_get_sas_dev_by_addr( + adapter, + sas_port->remote_identify.sas_address, + card_port); + if (!sas_dev) + return NULL; + sas_dev->pend_sas_rphy_add = 1; + } + + if (!topo_node->parent_dev) { + dev_warn(&adapter->pdev->dev, + "%s: topo_node parent device is NULL\n", __func__); + goto cleanup_sas_dev; + } port = sas_port_alloc_num(topo_node->parent_dev); - if (sas_port_add(port)) - return NULL; + if (!port) { + dev_err(&adapter->pdev->dev, + "%s: Failed to allocate SAS port\n", __func__); + goto cleanup_sas_dev; + } + + if (sas_port_add(port)) { + dev_err(&adapter->pdev->dev, + "%s: Failed to add SAS port\n", __func__); + goto out_delete_port; + } list_for_each_entry(card_phy, &sas_port->phy_list, port_siblings) { sas_port_add_phy(port, card_phy->phy); - card_phy->phy_is_assigned = true; + card_phy->phy_is_assigned = 1; card_phy->card_port = card_port; } - if (sas_port->remote_identify.device_type == SAS_END_DEVICE) { - sas_dev = leapraid_get_sas_dev_by_addr(adapter, - sas_port->remote_identify.sas_address, - card_port); - if (!sas_dev) - return NULL; - sas_dev->pend_sas_rphy_add = 1; + if (sas_dev) { rphy = sas_end_device_alloc(port); sas_dev->rphy = rphy; @@ -625,28 +671,63 @@ static struct sas_rphy *leapraid_create_and_register_rphy( else vphy->sas_address = sas_dev->sas_addr; } - } else { - rphy = sas_expander_alloc(port, - sas_port->remote_identify.device_type); + rphy = sas_expander_alloc( + port, + sas_port->remote_identify.device_type); if (topo_node->hdl <= adapter->dev_topo.card.phys_num) card_port->sas_address = sas_port->remote_identify.sas_address; } + if (!rphy) { + dev_err(&adapter->pdev->dev, + "%s: Failed to allocate RPHY\n", __func__); + goto cleanup_card_phy; + } + rphy->identify = sas_port->remote_identify; - if (sas_rphy_add(rphy)) + if (sas_rphy_add(rphy)) { dev_err(&adapter->pdev->dev, - "%s: failed to add rphy\n", __func__); + "%s: Failed to add RPHY\n", __func__); + if (sas_dev) + sas_dev->rphy = NULL; + + sas_rphy_free(rphy); + goto cleanup_card_phy; + } + sas_port->port = port; if (sas_dev) { sas_dev->pend_sas_rphy_add = 0; leapraid_sdev_put(sas_dev); } - sas_port->port = port; return rphy; + +cleanup_card_phy: + if (topo_node->hdl <= adapter->dev_topo.card.phys_num) { + if (!vphy) + card_port->sas_address = 0; + else + vphy->sas_address = 0; + } + + list_for_each_entry(card_phy, &sas_port->phy_list, port_siblings) { + card_phy->phy_is_assigned = 0; + card_phy->card_port = NULL; + } + +out_delete_port: + sas_port_delete(port); + +cleanup_sas_dev: + if (sas_dev) { + sas_dev->pend_sas_rphy_add = 0; + leapraid_sdev_put(sas_dev); + } + return NULL; } struct leapraid_sas_port *leapraid_transport_port_add( @@ -656,35 +737,45 @@ struct leapraid_sas_port *leapraid_transport_port_add( { struct leapraid_card_phy *card_phy, *card_phy_next; struct leapraid_topo_node *topo_node = NULL; - struct leapraid_sas_port *sas_port = NULL; + struct leapraid_sas_port *sas_port; struct leapraid_vphy *vphy = NULL; - struct sas_rphy *rphy = NULL; + struct sas_rphy *rphy; unsigned long flags; - if (!card_port) + if (!card_port) { + dev_warn(&adapter->pdev->dev, + "%s: Invalid card_port\n", __func__); return NULL; + } sas_port = leapraid_prepare_sas_port(adapter, hdl, sas_address, card_port, &topo_node); if (!sas_port) return NULL; - leapraid_detach_phy_from_old_port(adapter, - topo_node, - sas_port->remote_identify.sas_address, - card_port); + leapraid_detach_phy_from_old_port( + adapter, + topo_node, + sas_port->remote_identify.sas_address, + card_port); if (leapraid_bind_phys_and_vphy(adapter, sas_port, topo_node, - card_port, &vphy)) + card_port, &vphy)) { + dev_err(&adapter->pdev->dev, + "%s: Failed to bind phy to vphy\n", __func__); goto out_fail; + } rphy = leapraid_create_and_register_rphy(adapter, sas_port, topo_node, card_port, vphy); - if (!rphy) + if (!rphy) { + dev_err(&adapter->pdev->dev, + "%s: Failed to create rphy\n", __func__); goto out_fail; + } dev_info(&rphy->dev, - "%s: added dev: hdl=0x%04x, sas addr=0x%016llx\n", + "%s: Added dev: hdl=0x%04x, SAS addr=0x%016llx\n", __func__, hdl, (unsigned long long)sas_port->remote_identify.sas_address); @@ -695,20 +786,27 @@ struct leapraid_sas_port *leapraid_transport_port_add( spin_unlock_irqrestore(&adapter->dev_topo.topo_node_lock, flags); if (sas_port->remote_identify.device_type == - LEAPRAID_DEVTYP_EDGE_EXPANDER || + SAS_EDGE_EXPANDER_DEVICE || sas_port->remote_identify.device_type == - LEAPRAID_DEVTYP_FANOUT_EXPANDER) - leapraid_transport_exp_report_manu(adapter, - sas_port->remote_identify.sas_address, - rphy_to_expander_device(rphy), - card_port->port_id); + SAS_FANOUT_EXPANDER_DEVICE) + leapraid_transport_exp_report_manu( + adapter, + sas_port->remote_identify.sas_address, + rphy_to_expander_device(rphy), + card_port->port_id); return sas_port; out_fail: list_for_each_entry_safe(card_phy, card_phy_next, - &sas_port->phy_list, port_siblings) - list_del(&card_phy->port_siblings); + &sas_port->phy_list, port_siblings) { + if (topo_node->hdl <= adapter->dev_topo.card.phys_num && + !card_phy->vphy) + card_port->phy_mask &= ~BIT(card_phy->phy_id); + + list_del_init(&card_phy->port_siblings); + } + kfree(sas_port); return NULL; } @@ -750,10 +848,10 @@ static void leapraid_cleanup_card_port_and_vphys( if (vphy->sas_address != sas_address) continue; - dev_info(&adapter->pdev->dev, - "%s: remove vphy: %p from port: %p, port_id=%d\n", - __func__, vphy, remove_card_port, - remove_card_port->port_id); + dev_dbg(&adapter->pdev->dev, + "%s: Remove vphy=%p from port=%p port_id=%d\n", + __func__, vphy, remove_card_port, + remove_card_port->port_id); remove_card_port->vphys_mask &= ~vphy->phy_mask; list_del(&vphy->list); @@ -762,11 +860,11 @@ static void leapraid_cleanup_card_port_and_vphys( if (!remove_card_port->vphys_mask && !remove_card_port->sas_address) { - dev_info(&adapter->pdev->dev, - "%s: remove empty hba_port: %p, port_id=%d\n", - __func__, - remove_card_port, - remove_card_port->port_id); + dev_dbg(&adapter->pdev->dev, + "%s: Remove empty hba_port: %p, port_id=%d\n", + __func__, + remove_card_port, + remove_card_port->port_id); list_del(&remove_card_port->list); kfree(remove_card_port); remove_card_port = NULL; @@ -782,15 +880,15 @@ static void leapraid_cleanup_card_port_and_vphys( continue; if (!remove_card_port->vphys_mask) { - dev_info(&adapter->pdev->dev, - "%s: remove hba_port: %p, port_id=%d\n", - __func__, card_port, card_port->port_id); + dev_dbg(&adapter->pdev->dev, + "%s: Remove hba_port: %p, port_id=%d\n", + __func__, card_port, card_port->port_id); list_del(&card_port->list); kfree(card_port); } else { - dev_info(&adapter->pdev->dev, - "%s: clear sas_address of hba_port: %p, port_id=%d\n", - __func__, card_port, card_port->port_id); + dev_dbg(&adapter->pdev->dev, + "Clear sas_address of port=%p, port_id=%d\n", + card_port, card_port->port_id); remove_card_port->sas_address = 0; } break; @@ -802,22 +900,23 @@ static void leapraid_clear_topo_node_phys(struct leapraid_topo_node *topo_node, { int i; - for (i = 0; i < topo_node->phys_num; i++) { + for (i = 0; i < topo_node->phys_num; i++) if (topo_node->card_phy[i].remote_identify.sas_address == sas_address) { memset(&topo_node->card_phy[i].remote_identify, 0, sizeof(struct sas_identify)); - topo_node->card_phy[i].vphy = false; + topo_node->card_phy[i].vphy = 0; } - } } -void leapraid_transport_port_remove(struct leapraid_adapter *adapter, - u64 sas_address, u64 sas_address_parent, +void leapraid_transport_port_remove( + struct leapraid_adapter *adapter, + u64 sas_address, + u64 sas_address_parent, struct leapraid_card_port *remove_card_port) { struct leapraid_card_phy *card_phy, *card_phy_next; - struct leapraid_sas_port *sas_port = NULL; + struct leapraid_sas_port *sas_port; struct leapraid_topo_node *topo_node; unsigned long flags; bool found = false; @@ -855,7 +954,7 @@ void leapraid_transport_port_remove(struct leapraid_adapter *adapter, list_for_each_entry_safe(card_phy, card_phy_next, &sas_port->phy_list, port_siblings) { - card_phy->phy_is_assigned = false; + card_phy->phy_is_assigned = 0; if (!adapter->access_ctrl.host_removing) sas_port_delete_phy(sas_port->port, card_phy->phy); @@ -865,9 +964,9 @@ void leapraid_transport_port_remove(struct leapraid_adapter *adapter, if (!adapter->access_ctrl.host_removing) sas_port_delete(sas_port->port); - dev_info(&adapter->pdev->dev, - "%s: removed sas_port for sas addr=0x%016llx\n", - __func__, (unsigned long long)sas_address); + dev_dbg(&adapter->pdev->dev, + "%s: Removed sas_port for SAS addr=0x%016llx\n", + __func__, (unsigned long long)sas_address); kfree(sas_port); } @@ -902,9 +1001,11 @@ static void leapraid_init_sas_or_exp_phy(struct leapraid_adapter *adapter, LEAPRAID_SAS_HWRATE_MIN_RATE_MASK); phy->maximum_linkrate_hw = phy_pg0 ? leapraid_transport_convert_phy_link_rate( - phy_pg0->hw_link_rate >> 4) : + phy_pg0->hw_link_rate >> + LEAPRAID_SAS_NEG_LINK_RATE_SHIFT) : leapraid_transport_convert_phy_link_rate( - exp_pg1->hw_link_rate >> 4); + exp_pg1->hw_link_rate >> + LEAPRAID_SAS_NEG_LINK_RATE_SHIFT); phy->minimum_linkrate = phy_pg0 ? leapraid_transport_convert_phy_link_rate( phy_pg0->p_link_rate & @@ -914,9 +1015,11 @@ static void leapraid_init_sas_or_exp_phy(struct leapraid_adapter *adapter, LEAPRAID_SAS_PRATE_MIN_RATE_MASK); phy->maximum_linkrate = phy_pg0 ? leapraid_transport_convert_phy_link_rate( - phy_pg0->p_link_rate >> 4) : + phy_pg0->p_link_rate >> + LEAPRAID_SAS_NEG_LINK_RATE_SHIFT) : leapraid_transport_convert_phy_link_rate( - exp_pg1->p_link_rate >> 4); + exp_pg1->p_link_rate >> + LEAPRAID_SAS_NEG_LINK_RATE_SHIFT); phy->hostdata = card_phy->card_port; } @@ -926,30 +1029,33 @@ void leapraid_transport_add_card_phy(struct leapraid_adapter *adapter, struct device *parent_dev) { struct sas_phy *phy; + int ret; INIT_LIST_HEAD(&card_phy->port_siblings); phy = sas_phy_alloc(parent_dev, card_phy->phy_id); if (!phy) { dev_err(&adapter->pdev->dev, - "%s sas_phy_alloc failed!\n", __func__); + "%s: sas_phy_alloc failed!\n", __func__); return; } - if ((leapraid_transport_set_identify(adapter, card_phy->hdl, - &card_phy->identify))) { + if (leapraid_transport_set_identify(adapter, card_phy->hdl, + &card_phy->identify)) { dev_err(&adapter->pdev->dev, - "%s set phy handle identify failed!\n", __func__); + "%s: Set PHY handle identify failed!\n", __func__); sas_phy_free(phy); return; } card_phy->attached_hdl = le16_to_cpu(phy_pg0->attached_dev_hdl); if (card_phy->attached_hdl) { - if (leapraid_transport_set_identify(adapter, - card_phy->attached_hdl, - &card_phy->remote_identify)) { + ret = leapraid_transport_set_identify( + adapter, + card_phy->attached_hdl, + &card_phy->remote_identify); + if (ret) { dev_err(&adapter->pdev->dev, - "%s set phy attached handle identify failed!\n", + "%s: Set PHY attached hdl identify failed!\n", __func__); sas_phy_free(phy); return; @@ -958,7 +1064,9 @@ void leapraid_transport_add_card_phy(struct leapraid_adapter *adapter, leapraid_init_sas_or_exp_phy(adapter, card_phy, phy, phy_pg0, NULL); - if ((sas_phy_add(phy))) { + if (sas_phy_add(phy)) { + dev_err(&adapter->pdev->dev, + "%s: SAS PHY add failed!\n", __func__); sas_phy_free(phy); return; } @@ -972,38 +1080,41 @@ int leapraid_transport_add_exp_phy(struct leapraid_adapter *adapter, struct device *parent_dev) { struct sas_phy *phy; + int ret; INIT_LIST_HEAD(&card_phy->port_siblings); phy = sas_phy_alloc(parent_dev, card_phy->phy_id); if (!phy) { dev_err(&adapter->pdev->dev, - "%s sas_phy_alloc failed!\n", __func__); + "%s: sas_phy_alloc failed!\n", __func__); return -EFAULT; } - if ((leapraid_transport_set_identify(adapter, card_phy->hdl, - &card_phy->identify))) { + if (leapraid_transport_set_identify(adapter, card_phy->hdl, + &card_phy->identify)) { dev_err(&adapter->pdev->dev, - "%s set phy hdl identify failed!\n", __func__); + "%s: Set PHY hdl identify failed!\n", __func__); sas_phy_free(phy); return -EFAULT; } card_phy->attached_hdl = le16_to_cpu(exp_pg1->attached_dev_hdl); if (card_phy->attached_hdl) { - if (leapraid_transport_set_identify(adapter, - card_phy->attached_hdl, - &card_phy->remote_identify)) { - dev_err(&adapter->pdev->dev, - "%s set phy attached hdl identify failed!\n", - __func__); - sas_phy_free(phy); - } + ret = leapraid_transport_set_identify( + adapter, + card_phy->attached_hdl, + &card_phy->remote_identify); + if (ret) + dev_warn(&adapter->pdev->dev, + "%s: Set PHY attached hdl identify failed!\n", + __func__); } leapraid_init_sas_or_exp_phy(adapter, card_phy, phy, NULL, exp_pg1); - if ((sas_phy_add(phy))) { + if (sas_phy_add(phy)) { + dev_err(&adapter->pdev->dev, + "%s: SAS PHY add failed!\n", __func__); sas_phy_free(phy); return -EFAULT; } @@ -1012,13 +1123,14 @@ int leapraid_transport_add_exp_phy(struct leapraid_adapter *adapter, return 0; } -void leapraid_transport_update_links(struct leapraid_adapter *adapter, +void leapraid_transport_update_links( + struct leapraid_adapter *adapter, u64 sas_address, u16 hdl, u8 phy_index, u8 link_rate, struct leapraid_card_port *target_card_port) { struct leapraid_topo_node *topo_node; struct leapraid_card_phy *card_phy; - struct leapraid_card_port *card_port = NULL; + struct leapraid_card_port *card_port; unsigned long flags; if (adapter->access_ctrl.shost_recovering || @@ -1053,10 +1165,12 @@ void leapraid_transport_update_links(struct leapraid_adapter *adapter, BIT(card_phy->phy_id); } } - leapraid_transport_attach_phy_to_port(adapter, topo_node, - card_phy, - card_phy->remote_identify.sas_address, - target_card_port); + leapraid_transport_attach_phy_to_port( + adapter, + topo_node, + card_phy, + card_phy->remote_identify.sas_address, + target_card_port); } else { memset(&card_phy->remote_identify, 0, sizeof(struct sas_identify)); @@ -1079,8 +1193,12 @@ static int leapraid_dma_map_buffer(struct device *dev, struct bsg_buffer *buf, *dma_len = buf->payload_len; } else { - if (!dma_map_sg(dev, buf->sg_list, 1, DMA_BIDIRECTIONAL)) + if (!dma_map_sg(dev, buf->sg_list, 1, DMA_BIDIRECTIONAL)) { + dev_err(dev, + "%s: Failed to map sg buffer for dma\n", + __func__); return -ENOMEM; + } *dma_addr = sg_dma_address(buf->sg_list); *dma_len = sg_dma_len(buf->sg_list); @@ -1106,11 +1224,11 @@ static void leapraid_build_smp_task(struct leapraid_adapter *adapter, dma_addr_t c2h_dma_addr, size_t c2h_size) { struct leapraid_smp_passthrough_req *smp_passthrough_req; + u16 inter_taskid; void *psge; - smp_passthrough_req = - leapraid_get_task_desc(adapter, - adapter->driver_cmds.transport_cmd.inter_taskid); + inter_taskid = adapter->driver_cmds.transport_cmd.inter_taskid; + smp_passthrough_req = leapraid_get_task_desc(adapter, inter_taskid); memset(smp_passthrough_req, 0, sizeof(*smp_passthrough_req)); smp_passthrough_req->func = LEAPRAID_FUNC_SMP_PASSTHROUGH; @@ -1130,30 +1248,36 @@ static void leapraid_build_smp_task(struct leapraid_adapter *adapter, static int leapraid_send_smp_req(struct leapraid_adapter *adapter) { - dev_info(&adapter->pdev->dev, - "%s: sending smp request\n", __func__); + const struct leapraid_smp_passthrough_req *smp_passthrough_req; + + dev_dbg(&adapter->pdev->dev, + "%s: Sending smp request\n", __func__); + smp_passthrough_req = leapraid_get_task_desc( + adapter, adapter->driver_cmds.transport_cmd.inter_taskid); init_completion(&adapter->driver_cmds.transport_cmd.done); leapraid_fire_task(adapter, adapter->driver_cmds.transport_cmd.inter_taskid); wait_for_completion_timeout(&adapter->driver_cmds.transport_cmd.done, LEAPRAID_TRANSPORT_CMD_TIMEOUT * HZ); if (!(adapter->driver_cmds.transport_cmd.status & LEAPRAID_CMD_DONE)) { - dev_err(&adapter->pdev->dev, "%s: timeout\n", __func__); + dev_err(&adapter->pdev->dev, "%s: timeout, st=0x%x\n", + __func__, adapter->driver_cmds.transport_cmd.status); + leapraid_log_req_context(adapter, smp_passthrough_req); if (!(adapter->driver_cmds.transport_cmd.status & LEAPRAID_CMD_RESET)) { - dev_info(&adapter->pdev->dev, - "%s:%d call hard_reset\n", - __func__, __LINE__); + dev_dbg(&adapter->pdev->dev, + "%s:%d: call hard_reset\n", + __func__, __LINE__); leapraid_hard_reset_handler(adapter, FULL_RESET); return -ETIMEDOUT; } } - dev_info(&adapter->pdev->dev, "%s: smp request complete\n", __func__); + dev_dbg(&adapter->pdev->dev, "%s: SMP request complete\n", __func__); if (!(adapter->driver_cmds.transport_cmd.status & LEAPRAID_CMD_REPLY_VALID)) { dev_err(&adapter->pdev->dev, - "%s: smp request no reply\n", __func__); + "%s: SMP request no reply\n", __func__); return -ENXIO; } @@ -1167,10 +1291,10 @@ static void leapraid_handle_smp_rep(struct leapraid_adapter *adapter, struct leapraid_smp_passthrough_rep *smp_passthrough_rep; smp_passthrough_rep = - (void *)(&adapter->driver_cmds.transport_cmd.reply); + (void *)&adapter->driver_cmds.transport_cmd.reply; - dev_info(&adapter->pdev->dev, "%s: response data len=%d\n", - __func__, le16_to_cpu(smp_passthrough_rep->resp_data_len)); + dev_dbg(&adapter->pdev->dev, "%s: Response data len=%d\n", + __func__, le16_to_cpu(smp_passthrough_rep->resp_data_len)); memcpy(job->reply, smp_passthrough_rep, sizeof(*smp_passthrough_rep)); job->reply_len = sizeof(*smp_passthrough_rep); @@ -1198,13 +1322,19 @@ static void leapraid_transport_smp_handler(struct bsg_job *job, if (adapter->access_ctrl.shost_recovering || adapter->access_ctrl.pcie_recovering) { + dev_err(&adapter->pdev->dev, + "%s: Failed, shost_recovering=%d pcie_recovering=%d\n", + __func__, + adapter->access_ctrl.shost_recovering, + adapter->access_ctrl.pcie_recovering); rc = -EFAULT; - goto done; + goto exit_bsg_job; } - rc = mutex_lock_interruptible(&adapter->driver_cmds.transport_cmd.mutex); + rc = mutex_lock_interruptible(&adapter->driver_cmds + .transport_cmd.mutex); if (rc) - goto done; + goto exit_bsg_job; adapter->driver_cmds.transport_cmd.status = LEAPRAID_CMD_PENDING; rc = leapraid_dma_map_buffer(&adapter->pdev->dev, @@ -1223,7 +1353,8 @@ static void leapraid_transport_smp_handler(struct bsg_job *job, if (rc) goto free_req_buf; - rc = leapraid_check_adapter_is_op(adapter); + rc = leapraid_check_adapter_is_op(adapter, LEAPRAID_DB_WAIT_OP_SHORT, + __func__); if (rc) goto free_rep_buf; @@ -1245,7 +1376,7 @@ static void leapraid_transport_smp_handler(struct bsg_job *job, release_lock: adapter->driver_cmds.transport_cmd.status = LEAPRAID_CMD_NOT_USED; mutex_unlock(&adapter->driver_cmds.transport_cmd.mutex); -done: +exit_bsg_job: bsg_job_done(job, rc, reslen); } -- 2.25.1