anolis: scsi: support linkdata HBA/RAID controllers

ANBZ: #20901

This commit is to support Linkdata HBA/RAID controllers.

Signed-off-by: liujie_answer <liujie5@linkdatatechnology.com>
Reviewed-by: Guixin Liu <kanie@linux.alibaba.com>
Link: https://gitee.com/anolis/cloud-kernel/pulls/5216
This commit is contained in:
liujie_answer 2025-05-08 14:03:20 +08:00 committed by 小龙
parent 72ad9fd00b
commit 4e26f60571
113 changed files with 65251 additions and 0 deletions

View File

@ -0,0 +1 @@
CONFIG_SCSI_PS3STOR=m

View File

@ -482,6 +482,7 @@ config SCSI_ARCMSR
source "drivers/scsi/esas2r/Kconfig"
source "drivers/scsi/megaraid/Kconfig.megaraid"
source "drivers/scsi/mpt3sas/Kconfig"
source "drivers/scsi/linkdata/Kconfig"
source "drivers/scsi/sssraid/Kconfig"
source "drivers/scsi/smartpqi/Kconfig"
source "drivers/scsi/ufs/Kconfig"

View File

@ -101,6 +101,7 @@ obj-$(CONFIG_MEGARAID_LEGACY) += megaraid.o
obj-$(CONFIG_MEGARAID_NEWGEN) += megaraid/
obj-$(CONFIG_MEGARAID_SAS) += megaraid/
obj-$(CONFIG_SCSI_MPT3SAS) += mpt3sas/
obj-$(CONFIG_SCSI_PS3STOR) += linkdata/
obj-$(CONFIG_SCSI_UFSHCD) += ufs/
obj-$(CONFIG_SCSI_ACARD) += atp870u.o
obj-$(CONFIG_SCSI_SUNESP) += esp_scsi.o sun_esp.o

View File

@ -0,0 +1 @@
source "drivers/scsi/linkdata/ps3stor/Kconfig"

View File

@ -0,0 +1,3 @@
# SPDX-License-Identifier: GPL-2.0
obj-$(CONFIG_SCSI_PS3STOR) += ps3stor/

View File

@ -0,0 +1,9 @@
config SCSI_PS3STOR
tristate "Linkdata ps3stor Storage Controller Device Driver"
depends on PCI && SCSI
select SCSI_SAS_ATTRS
select RAID_ATTRS
select IRQ_POLL
default m
help
This driver supports Linkdata HBA & RAID controllers.

View File

@ -0,0 +1,56 @@
# SPDX-License-Identifier: GPL-2.0
obj-$(CONFIG_SCSI_PS3STOR) += ps3stor.o
ps3stor-objs := \
ps3_cmd_channel.o \
ps3_device_update.o \
ps3_ioc_manager.o \
ps3_mgr_channel.o \
ps3_platform_utils.o \
ps3_scsi_cmd_err.o \
ps3_cmd_complete.o \
ps3_ioc_state.o \
ps3_mgr_cmd.o \
ps3_qos.o \
ps3_scsih.o \
ps3_cmd_statistics.o \
ps3_event.o \
ps3_ioctl.o \
ps3_mgr_cmd_err.o \
ps3_r1x_write_lock.o \
ps3_scsih_cmd_parse.o \
ps3_debug.o \
ps3_io_trace.o \
ps3_module_para.o \
ps3_rb_tree.o \
ps3_scsih_raid_engine.o \
ps3_device_manager.o \
ps3_instance_manager.o \
ps3_irq.o \
ps3_nvme_resp_to_scsi.o \
ps3_recovery.o \
ps3_trace_id_alloc.o \
ps3_device_manager_sas.o \
ps3_ioc_adp.o \
ps3_load.o \
ps3_pci.o \
ps3_sas_transport.o \
ps3_watchdog.o \
./linux/ps3_base.o \
./linux/ps3_cli.o \
./linux/ps3_cli_debug.o \
./linux/ps3_driver_log.o \
./linux/ps3_dump.o \
./linux/ps3_pcie_err_handle.o
ccflags-y += -DPS3_CFG_RELEASE
ccflags-y += -DPS3_HARDWARE_ASIC
ccflags-y += -DPS3_MODEL_V200
ccflags-y += -Werror
ccflags-y += $(call cc-option, -Wmaybe-uninitialized)
ccflags-y += \
-I$(srctree)/drivers/scsi/linkdata/ps3stor \
-I$(srctree)/drivers/scsi/linkdata/ps3stor/linux \
-I$(srctree)/drivers/scsi/linkdata/ps3stor/include \
-I$(srctree)/drivers/scsi/linkdata/ps3stor/include/htp_v200

View File

@ -0,0 +1,278 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef _PS3_HTP_H_
#define _PS3_HTP_H_
#include "ps3_htp_def.h"
#include "ps3_htp_dev.h"
#include "ps3_htp_req_frame_hw.h"
#define PS3_DUMP_CTRL_COPY_FINISH 0x1
#define PS3_DUMP_CTRL_DUMP_ABORT 0x2
#define PS3_DUMP_CTRL_DUMP_FW_LOG 0x3
#define PS3_DUMP_CTRL_DUMP_BAR_DATA 0x4
#define PS3_DUMP_CTRL_DUMP_CORE_FILE 0x5
#define PS3_DUMP_CTRL_DUMP_END 0x6
#define PS3_DUMP_CTRL_DUMP_INT_READY 0x7
#define PS3_DUMP_DMA_DONE (0x1)
#define PS3_DUMP_DMA_ABORT (0x1 << 6)
#define PS3_DUMP_DATA_UNIT_SIZE (0x400)
#define PS3_DREICT_SENSE_DATA_BUF_SIZE 72
#define PS3_ATU_FLAG_LOW_BITS_MASK (0x0000FFFF)
#define PS3_ATU_FLAG_HIGH_BITS_MASK (0xFFFFFFFFFFFF0000)
#define PS3_ATU_FLAG_DRIVER_SET (0xC0DE)
#define PS3_IOCTL_VERSION (0x2000000)
enum {
HIL_MODEL_SW = 0,
HIL_MODEL_HW,
HIL_MODEL_HW_ENHANCED,
HIL_MODEL_SW_ASSIST,
};
enum Ps3DumpType {
PS3_DUMP_TYPE_UNKNOWN = 0,
PS3_DUMP_TYPE_CRASH = 1,
PS3_DUMP_TYPE_FW_LOG = 2,
PS3_DUMP_TYPE_BAR_DATA = 3,
};
enum Ps3DumpState {
PS3_DUMP_STATE_INVALID = 0,
PS3_DUMP_STATE_PRE_ABORT,
PS3_DUMP_STATE_ABORTED,
PS3_DUMP_STATE_START,
PS3_DUMP_STATE_COPYING,
PS3_DUMP_STATE_COPY_DONE,
PS3_DUMP_STATE_READY = 7,
};
enum Ps3CtrlSecurityState {
PS3_CTRL_SECURITY_STATE_DECRYPT = 0,
PS3_CTRL_SECURITY_STATE_ENCRYPT,
};
struct Ps3DumpNotifyInfo {
int dumpType;
};
struct PS3LinkErrInfo {
unsigned int invalidDwordCount;
unsigned int runningDisparityErrCount;
unsigned int lossOfDwordSyncCount;
unsigned int phyResetProblemCount;
};
enum PhyCtrl {
PS3_SAS_CTRL_UNKNOWN = 0,
PS3_SAS_CTRL_RESET = 1,
PS3_SAS_CTRL_RESET_HARD = 2,
PS3_SAS_CTRL_DISABLE = 3
};
enum {
PS3_UNLOAD_SUB_TYPE_RESERVED = 0,
PS3_UNLOAD_SUB_TYPE_REMOVE = 1,
PS3_UNLOAD_SUB_TYPE_SHUTDOWN = 2,
PS3_UNLOAD_SUB_TYPE_SUSPEND = 3,
};
enum {
PS3_SUSPEND_TYPE_NONE = 0,
PS3_SUSPEND_TYPE_SLEEP = 1,
PS3_SUSPEND_TYPE_HIBERNATE = 2,
};
static inline const char *namePhyCtrl(enum PhyCtrl e)
{
static const char * const myNames[] = {
[PS3_SAS_CTRL_UNKNOWN] = "PS3_SAS_CTRL_UNKNOWN",
[PS3_SAS_CTRL_RESET] = "PS3_SAS_CTRL_RESET",
[PS3_SAS_CTRL_RESET_HARD] = "PS3_SAS_CTRL_RESET_HARD",
[PS3_SAS_CTRL_DISABLE] = "PS3_SAS_CTRL_DISABLE"
};
return myNames[e];
}
struct PS3InitCmdWord {
union {
struct {
unsigned int type : 2;
unsigned int reserved1 : 1;
unsigned int direct : 2;
unsigned int reserved2 : 27;
};
unsigned int lowAddr;
};
unsigned int highAddr;
};
struct PS3CmdWord {
unsigned short type : 2;
unsigned short reserved1 : 2;
unsigned short direct : 2;
unsigned short isrSN : 8;
unsigned short reserved2 : 2;
unsigned short cmdFrameID : 13;
unsigned short reserved3 : 3;
unsigned short phyDiskID : 12;
unsigned short reserved4 : 4;
unsigned short virtDiskID : 8;
unsigned short reserved5 : 4;
unsigned short qMask : 4;
};
struct PS3CmdWordSw {
unsigned int type : 2;
unsigned int noReplyWord : 1;
unsigned int cmdFrameID : 13;
unsigned int isrSN : 8;
unsigned int cmdIndex : 8;
};
union PS3CmdWordU32 {
struct PS3CmdWordSw cmdWord;
unsigned int val;
};
union PS3DefaultCmdWord {
struct PS3CmdWord cmdWord;
union {
struct {
unsigned int low;
unsigned int high;
} u;
unsigned long long words;
};
};
enum {
PS3_ISR_ACC_MODE_LATENCY = 0,
PS3_ISR_ACC_MODE_SSD_IOPS,
PS3_ISR_ACC_MODE_HDD_IOPS,
PS3_ISR_ACC_MODE_IOPS_VER0 = 2,
PS3_ISR_ACC_MODE_DEV_IOPS,
PS3_ISR_ACC_MODE_MAX,
};
struct PS3ReplyFifoDesc {
unsigned long long ReplyFifoBaseAddr;
unsigned int irqNo;
unsigned short depthReplyFifo;
unsigned char isrAccMode;
unsigned char reserved;
};
struct PS3ReplyWord {
unsigned short type : 2;
unsigned short diskType : 1;
unsigned short reserved1 : 1;
unsigned short mode : 2;
unsigned short reserved2 : 10;
unsigned short cmdFrameID : 13;
unsigned short reserved3 : 2;
unsigned short reserved4 : 1;
unsigned short retStatus : 15;
unsigned short retType : 1;
unsigned short reserved5 : 12;
unsigned short qMask : 4;
};
struct PS3MgrTaskRespInfo {
unsigned char iocStatus;
unsigned char reserved1;
unsigned short iocLogInfo;
unsigned int terminationCnt;
unsigned int respInfo;
unsigned int reserved2;
};
struct PS3MgrCmdReplyRespInfo {
unsigned char cmdReplyStatus;
unsigned char reserved[15];
};
union PS3RespDetails {
unsigned int xfer_cnt;
unsigned int respData[4];
struct PS3MgrTaskRespInfo taskMgrRespInfo;
struct PS3MgrCmdReplyRespInfo replyCmdRespInfo;
};
struct PS3SasDirectRespStatus {
unsigned int status : 8;
unsigned int dataPres : 2;
unsigned int reserved : 22;
};
struct Ps3SasDirectRespFrameIU {
union {
unsigned char reserved0[8];
unsigned long long mediumErrorLba;
};
unsigned char reserved1[2];
unsigned char dataPres;
unsigned char status;
union {
unsigned int reserved2;
unsigned int xfer_cnt;
};
unsigned int senseDataLen;
unsigned int respDataLen;
unsigned char data[PS3_SENSE_BUFFER_SIZE];
unsigned char reserved3[8];
};
struct PS3NormalRespFrame {
union PS3RespDetails respDetail;
unsigned char reserved1[8];
unsigned char sense[PS3_SENSE_BUFFER_SIZE];
unsigned char type;
unsigned char reserved2[3];
unsigned char respStatus;
unsigned char dataPre;
unsigned char reserved3[2];
};
union PS3RespFrame {
struct Ps3SasDirectRespFrameIU sasRespFrame;
struct PS3NormalRespFrame normalRespFrame;
};
struct Ps3DebugMemEntry {
unsigned long long debugMemAddr;
unsigned int debugMemSize;
unsigned int reserved;
};
struct PS3NvmeCmdStatus {
union {
struct {
unsigned short sc : 8;
unsigned short sct : 3;
unsigned short crd : 2;
unsigned short m : 1;
unsigned short dnr : 1;
unsigned short p : 1;
};
unsigned short cmdStatus;
};
};
#endif

View File

@ -0,0 +1,561 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef _PS3_HTP_DEF_H_
#define _PS3_HTP_DEF_H_
#define PCIE_DMA_HOST_ADDR_BIT_POS (44)
#define PCIE_DMA_HOST_ADDR_BIT_POS_SET(addr) \
(((1ULL) << (PCIE_DMA_HOST_ADDR_BIT_POS)) | (addr))
#define PCIE_DMA_HOST_ADDR_BIT_POS_CLEAR(addr) \
((~((1ULL) << (PCIE_DMA_HOST_ADDR_BIT_POS))) & (addr))
#define PCIE_DMA_HOST_ADDR_BIT_POS_F0 (54)
#define PCIE_DMA_HOST_ADDR_BIT_POS_F1 (53)
#define PCIE_DMA_HOST_ADDR_BIT_POS_VALID (52)
#define PCIE_DMA_HOST_ADDR_BIT_POS_SET_NEW(bit_pos, addr) \
((addr) + ((1ULL) << (bit_pos)))
#define PCIE_DMA_HOST_ADDR_BIT_POS_CLEAR_NEW(bit_pos, addr) \
((addr) - ((1ULL) << (bit_pos)))
enum PS3FWDiagKey {
PS3_FW_DIAG_FLUSH = 0X00,
PS3_FW_DIAG_1ST_KEY = 0x52,
PS3_FW_DIAG_2ND_KEY = 0x5F,
PS3_FW_DIAG_3RD_KEY = 0x55,
PS3_FW_DIAG_4TH_KEY = 0x5F,
PS3_FW_DIAG_5TH_KEY = 0x52,
PS3_FW_DIAG_6TH_KEY = 0x45,
PS3_FW_DIAG_7TH_KEY = 0x41,
PS3_FW_DIAG_8TH_KEY = 0x44,
PS3_FW_DIAG_9TH_KEY = 0x59,
};
enum PS3FWStateAct {
PS3_FW_STATE_ACT_INIT_READY = 0X00000001,
};
enum PS3RegDoorBellType {
PS3_REG_DOORBELL_STATE_TO_READY = 1,
PS3_REG_DOORBELL_STATE_TO_FAULT = 2,
PS3_REG_DOORBELL_STATE_TO_HALT = 3,
};
enum PS3FWSoftResetAct {
PS3_FW_STATE_ACT_SHALLOW_SOFT_RESET = 0X00000001,
PS3_FW_STATE_ACT_DEEP_SOFT_RESET = 0X00000002,
};
enum PS3PerfModeType {
PS3_PERF_MODE_BALANCE = 0,
PS3_PERF_MODE_IOPS = 1,
PS3_PERF_MODE_LATENCY = 2,
};
enum PS3BitPos {
PS3_BIT_POS_DEFAULT = 0,
PS3_BIT_POS_44 = 1,
PS3_BIT_POS_45 = 2,
PS3_BIT_POS_46 = 3,
PS3_BIT_POS_47 = 4,
PS3_BIT_POS_48 = 5,
PS3_BIT_POS_49 = 6,
PS3_BIT_POS_50 = 7,
PS3_BIT_POS_51 = 8,
PS3_BIT_POS_52 = 9,
PS3_BIT_POS_53 = 10,
PS3_BIT_POS_54 = 11,
};
enum PS3CmdType {
PS3_CMD_INIT_IOC = 0x0,
PS3_CMD_VD_SCSI_IO_RW = 0x1,
PS3_CMD_VD_SCSI_IO_NORW = 0x2,
PS3_CMD_PD_SCSI_IO_RW = 0x3,
PS3_CMD_PD_SCSI_IO_NORW = 0x4,
PS3_CMD_MANAGEMENT = 0x5,
PS3_CMD_SCSI_TASK_MANAGEMENT = 0x6,
PS3_CMD_IOCTL = 0x7,
PS3_CMD_SAS_MANAGEMENT = 0x8,
PS3_CMD_COUNT = 0x9,
PS3_CMD_INVALID = 0xff,
};
enum {
PS3_SGL = 0x0,
PS3_PRP = 0x1,
};
enum {
PS3_CMD_OPERATOR_TYPE_HOST = 0x0,
PS3_CMD_OPERATOR_TYPE_UEFI = 0x1,
PS3_CMD_OPERATOR_TYPE_IOC = 0x2,
};
enum {
PS3_PCI_IRQ_LEGACY = 0,
PS3_PCI_IRQ_MSI = 1,
PS3_PCI_IRQ_MSIX = 2,
};
#define PS3_DRV_SYSTEM_ID_MAX_LEN 64
#define PS3_SENSE_BUFFER_SIZE (96)
#define PS3_RESP_FRAME_BUFFER_SIZE (128)
#define PS3_REQUEST_CONTROL_DIR_NONE 0x00
#define PS3_REQUEST_CONTROL_DIR_READ 0x01
#define PS3_REQUEST_CONTROL_DIR_WRITE 0x02
#define PS3_REQUEST_CONTROL_DIR_BOTH 0x03
#define PS3_MAX_PD_COUNT_IN_SPAN 32
#define PS3_MAX_SPAN_IN_VD 8
#define PS3_IOC_INIT_STATE_MASK 0xFFFF
#define PS3_IOC_RECOVERY_COUNT_MASK 0xFFFFFFFF
#define PS3_START_STATE_SPACE 0x0100
#define PS3_DRV_MGR_FLUSH_RETRY_MAX_COUNT 1
#define MAX_MGR_CMD_TOTAL_COUNT (16)
#define PS3_HOT_RESET_OFFSET \
(HIL_REG1_PS3_REGISTER_F_PS3_DEBUG10_ADDR - \
HIL_REG1_PS3_REGISTER_F_BASEADDR)
union HilRegPs3RegisterHotReset {
unsigned long long val;
struct {
unsigned char isHotReset : 1;
unsigned char reserved0 : 7;
unsigned char reserved1[7];
} reg;
};
#define PS3_ATU_SUPPORT_OFFSET \
(HIL_REG1_PS3_REGISTER_F_PS3_DEBUG8_ADDR - \
HIL_REG1_PS3_REGISTER_F_BASEADDR)
union HilRegPs3RegisterFPs3AtuSupport {
unsigned long long val;
struct {
unsigned char bitPos;
unsigned char reserved[7];
} reg;
};
#define PS3_CAN_HARD_RESET_OFFSET \
(HIL_REG1_PS3_REGISTER_F_PS3_DEBUG9_ADDR - \
HIL_REG1_PS3_REGISTER_F_BASEADDR)
union HilRegPs3RegisterFPs3CanHardReset {
unsigned long long val;
struct {
unsigned char canHardReset : 1;
unsigned char reserved0 : 7;
unsigned char reserved1[7];
} reg;
};
enum PS3FWRunState {
PS3_FW_STATE_UNDEFINED = 0x00,
PS3_FW_STATE_START = 0x01,
PS3_FW_STATE_READY = 0x02,
PS3_FW_STATE_WAIT = 0x03,
PS3_FW_STATE_RUNNING = 0x04,
PS3_FW_STATE_FLUSHING = 0x05,
PS3_FW_STATE_RESET = 0x06,
PS3_FW_STATE_CRITICAL = 0x09,
PS3_FW_STATE_FAULT = 0xE0,
PS3_FW_STATE_HALT = 0xF0,
PS3_FW_STATE_END,
PS3_FW_STATE_MASK = 0xFF,
PS3_FW_STATE_WDT_MASK = 0xFF0000FF,
};
enum PS3FWStartState {
PS3_START_STATE_UNDEFINED = 0x0000,
PS3_START_STATE_INIT_BASE = 0x0100,
PS3_START_STATE_INIT_HARDWARE = 0x0200,
PS3_START_STATE_INIT_SOFTWARE = 0x0300,
PS3_START_STATE_INIT_DATAPATH = 0x0400,
PS3_START_STATE_INIT_THREAD = 0x0500,
PS3_START_STATE_SCAN_DEVICE = 0x0600,
PS3_START_STATE_FLUSH_CACHE = 0x0700,
PS3_START_STATE_INIT_RESET = 0x0800,
PS3_START_STATE_FINISHED = 0x0900,
PS3_START_STATE_MASK = 0xFF00,
PS3_START_STATE_WDT_MASK = 0xFF00FF00,
};
#define PS3_FW_RESET_FLAG (0X00000001)
#define PS3_FW_DIAG_ENABLE (0X00000001)
#define PS3_FW_HARD_RESET_ACT (0X00000001)
#define PS3_FW_MAX_CMD_MASK (0X0000FFFF)
#define PS3_FW_MAX_MSIX_VECTORS_MASK (0X0000FFFF)
#define PS3_FW_MAX_CHAIN_SIZE_MASK (0XFFFFFFFF)
#define PS3_FW_MAX_RAID_MAP_SIZE_MASK (0XFFFFFFFF)
#define PS3_FW_MAX_NVME_PAGE_SIZE_MASK (0xFFFFFFFF)
#define PS3_FW_INTERRUPT_STATUS_MASK (0X00000001)
#define PS3_FW_INTERRUPT_CMD_INTR_CAP_MASK (0X00000004)
#define PS3_FW_INTERRUPT_CMD_MSI_CAP_MASK (0X00000002)
#define PS3_FW_INTERRUPT_CMD_MSIX_CAP_MASK (0X00000001)
#define PS3_FW_INTERRUPT_CLEAR_MASK (0X00000001)
enum PS3FWFeatureSupportMask {
PS3_FW_FEATURE_SUPPORT_SYNC_CACHE = 0X00000001,
PS3_FW_FEATURE_SUPPORT_DMA64 = 0X00000002,
};
enum PS3FWCtrlMask {
PS3_FW_CTRL_CMD_TRIGGER_SNAPSHOT = 0X00000001,
PS3_FW_CTRL_CMD_CRASHDUMP_COLLECTION_DONE = 0X00000002,
PS3_FW_CTRL_CMD_CRASHDUMP_DMA_CLEAR = 0X00000004,
};
enum PS3FWCtrlStatusMask {
PS3_FW_CTRL_STATUS_CRASHDUMP_DONE = 0X00000001,
PS3_FW_CTRL_STATUS_RSVR = 0X00000002,
PS3_FW_CTRL_STATUS_CRASHDUMP_MAP = 0X00000004,
};
enum PS3CmdTrigger {
PS3_CMD_TRIGGER_UNLOAD = 0X0001,
PS3_CMD_TRIGGER_UNLOAD_SUSPEND = 0X0002,
};
enum PS3RegCmdState {
PS3_DOORBELL_DONE = 0X0001,
};
enum PS3Debug12Mask {
PS3_DEBUG12__HOT_RESET = 0X00000001,
};
enum PS3MgrControlFlag {
PS3_REQUEST_CONTROL_SKIP_REFIRE = 0x0,
PS3_REQUEST_CONTROL_SENSE32 = 0x1,
PS3_REQUEST_CONTROL_SENSE64 = 0x2,
};
enum PS3TaskCmdSubType {
PS3_TASK_CMD_SCSI_TASK_ABORT,
PS3_TASK_CMD_SCSI_TASK_RESET,
PS3_TASK_CMD_COUNT,
PS3_TASK_CMD_INVALID = 0xffff,
};
enum PS3MgrCmdSubType {
PS3_MGR_CMD_GET_CTRL_INFO = 0x0,
PS3_MGR_CMD_UNLOAD,
PS3_MGR_CMD_SUBSCRIBE_EVENT,
PS3_MGR_CMD_GET_VD_LIST,
PS3_MGR_CMD_GET_PD_LIST,
PS3_MGR_CMD_GET_VD_INFO,
PS3_MGR_CMD_GET_PD_INFO,
PS3_MGR_CMD_GET_BOOTDRIVE_INFO,
PS3_MGR_CMD_GET_BIOS_INFO,
PS3_MGR_CMD_GET_SNAPSHOT_ATTR,
PS3_MGR_CMD_SET_CRASH_DUMP,
PS3_MGR_CMD_CANCEL,
PS3_MGR_CMD_ABORT,
PS3_MGR_CMD_DEV_ADD_ACK,
PS3_MGR_CMD_DEV_DEL_DONE,
PS3_SAS_SMP_REQUEST,
PS3_SAS_GET_LINK_ERR,
PS3_SAS_PHY_CTRL,
PS3_SAS_GET_EXPANDERS,
PS3_SAS_GET_PHY_INFO,
PS3_SAS_GET_EXPANDER_INFO,
PS3_MGR_CMD_AUTODUMP_NOTIFY,
PS3_MGR_CMD_SECURITY_RANDOM_GET,
PS3_MGR_CMD_SECURITY_PASSWORD,
PS3_MGR_CMD_WEBSUBSCRIBE_EVENT,
PS3_MGR_CMD_PRESERVED_INFO_GET,
PS3_MGR_CMD_GET_PD_SN_LIST,
PS3_MGR_CMD_PD_REF_CLEAR,
PS3_MGR_CMD_COUNT,
PS3_MGR_CMD_INVALID = 0xff
};
static inline const char *namePS3MgrCmdSubType(enum PS3MgrCmdSubType type)
{
static const char * const myNames[] = {
[PS3_MGR_CMD_GET_CTRL_INFO] = "PS3_MGR_CMD_GET_CTRL_INFO",
[PS3_MGR_CMD_UNLOAD] = "PS3_MGR_CMD_UNLOAD",
[PS3_MGR_CMD_SUBSCRIBE_EVENT] = "PS3_MGR_CMD_SUBSCRIBE_EVENT",
[PS3_MGR_CMD_GET_VD_LIST] = "PS3_MGR_CMD_GET_VD_LIST",
[PS3_MGR_CMD_GET_PD_LIST] = "PS3_MGR_CMD_GET_PD_LIST",
[PS3_MGR_CMD_GET_VD_INFO] = "PS3_MGR_CMD_GET_VD_INFO",
[PS3_MGR_CMD_GET_PD_INFO] = "PS3_MGR_CMD_GET_PD_INFO",
[PS3_MGR_CMD_GET_BOOTDRIVE_INFO] =
"PS3_MGR_CMD_GET_BOOTDRIVE_INFO",
[PS3_MGR_CMD_GET_BIOS_INFO] = "PS3_MGR_CMD_GET_BIOS_INFO",
[PS3_MGR_CMD_GET_SNAPSHOT_ATTR] =
"PS3_MGR_CMD_GET_SNAPSHOT_ATTR",
[PS3_MGR_CMD_SET_CRASH_DUMP] = "PS3_MGR_CMD_SET_CRASH_DUMP",
[PS3_MGR_CMD_CANCEL] = "PS3_MGR_CMD_CANCEL",
[PS3_MGR_CMD_ABORT] = "PS3_MGR_CMD_ABORT",
[PS3_MGR_CMD_DEV_ADD_ACK] = "PS3_MGR_CMD_DEV_ADD_ACK",
[PS3_MGR_CMD_DEV_DEL_DONE] = "PS3_MGR_CMD_DEV_DEL_DONE",
[PS3_SAS_SMP_REQUEST] = "PS3_SAS_SMP_REQUEST",
[PS3_SAS_GET_LINK_ERR] = "PS3_SAS_GET_LINK_ERR",
[PS3_SAS_PHY_CTRL] = "PS3_SAS_PHY_CTRL",
[PS3_SAS_GET_EXPANDERS] = "PS3_SAS_GET_EXPANDERS",
[PS3_SAS_GET_PHY_INFO] = "PS3_SAS_GET_PHY_INFO",
[PS3_SAS_GET_EXPANDER_INFO] = "PS3_SAS_GET_EXPANDER_INFO",
[PS3_MGR_CMD_AUTODUMP_NOTIFY] = "PS3_MGR_CMD_AUTODUMP_NOTIFY",
[PS3_MGR_CMD_SECURITY_RANDOM_GET] =
"PS3_MGR_CMD_SECURITY_RANDOM_GET",
[PS3_MGR_CMD_SECURITY_PASSWORD] =
"PS3_MGR_CMD_SECURITY_PASSWORD",
[PS3_MGR_CMD_WEBSUBSCRIBE_EVENT] =
"PS3_MGR_CMD_WEBSUBSCRIBE_EVENT",
[PS3_MGR_CMD_PRESERVED_INFO_GET] =
"PS3_MGR_CMD_PRESERVED_INFO_GET",
[PS3_MGR_CMD_GET_PD_SN_LIST] = "PS3_MGR_CMD_GET_PD_SN_LIST",
[PS3_MGR_CMD_PD_REF_CLEAR] = "PS3_MGR_CMD_PD_REF_CLEAR",
[PS3_MGR_CMD_COUNT] = "PS3_MGR_CMD_INVALID",
};
if (type < PS3_MGR_CMD_COUNT && type < ARRAY_SIZE(myNames))
return myNames[type];
return "PS3_MGR_CMD_INVALID";
}
enum PS3CmdIocErrCode {
PS3_IOC_ERR_CODE_OK = 0x00,
PS3_IOC_ERR_CODE_ERR = 0x01,
PS3_IOC_STATE_INVALID_STATUS = 0xFFFF,
};
enum PS3CmdStatusCode {
SCSI_STATUS_GOOD = 0x00,
SCSI_STATUS_CHECK_CONDITION = 0x02,
SCSI_STATUS_CONDITION_MET = 0x04,
SCSI_STATUS_BUSY = 0x08,
SCSI_STATUS_RESERVATION_CONFLICT = 0x18,
SCSI_STATUS_TASK_SET_FULL = 0x28,
SCSI_STATUS_ACA_ACTIVE = 0x30,
SCSI_STATUS_TASK_ABORTED = 0x40,
PS3_STATUS_DEVICE_NOT_FOUND = 0x80,
PS3_STATUS_IO_ABORTED = 0x81,
PS3_STATUS_REQ_ILLEGAL = 0x82,
PS3_STATUS_RESET_FAIL = 0x83,
PS3_STATUS_VD_OFFLINE = 0x84,
PS3_STATUS_ACCESS_BLOCK = 0x85,
PS3_STATUS_INTERNAL_SOFT_ERR = 0x86,
PS3_STATUS_INTERNAL_ERR = 0x87,
PS3_STATUS_HOST_NOT_FOUND = 0x88,
PS3_STATUS_HOST_RESET = 0x89,
PS3_STATUS_PCI_RECOVERY = 0x8A,
PS3_STATUS_VD_MEMBER_OFFLINE = 0x8B,
PS3_STATUS_UNDERRUN = 0x8C,
PS3_STATUS_OVERRUN = 0x8D,
PS3_STATUS_DIF_GRD_ERROR = 0x8E,
PS3_STATUS_DIF_REF_ERROR = 0x8F,
PS3_STATUS_DIF_APP_ERROR = 0x90,
PS3_STATUS_ACCESS_RO = 0x91,
};
enum PS3CmdWordType {
PS3_CMDWORD_TYPE_INIT = 0x00,
PS3_CMDWORD_TYPE_ABORT = 0x00,
PS3_CMDWORD_TYPE_MGR = 0x01,
PS3_CMDWORD_TYPE_READ = 0x02,
PS3_CMDWORD_TYPE_WRITE = 0x03,
};
#define PS3_CMD_TYPE_IS_RW(type) \
((type) == PS3_CMDWORD_TYPE_READ || (type) == PS3_CMDWORD_TYPE_WRITE)
enum PS3ReqFrameCtrl {
PS3_DATA_BUF_SGL = 0x00,
PS3_DATA_BUF_PRP = 0x02,
};
enum PS3CmdWordDirect {
PS3_CMDWORD_DIRECT_NORMAL = 0x00,
PS3_CMDWORD_DIRECT_RESERVE = 0x01,
PS3_CMDWORD_DIRECT_OK = 0x02,
PS3_CMDWORD_DIRECT_ADVICE = 0x03,
};
enum PS3CmdWordPort {
PS3_CMDWORD_PORT_SAS0 = 0x00,
PS3_CMDWORD_PORT_SAS1 = 0x01,
PS3_CMDWORD_PORT_NVME = 0x02,
PS3_CMDWORD_PORT_RESERVE = 0x03,
};
enum PS3CmdWordFormat {
PS3_CMDWORD_FORMAT_FRONTEND = 0x00,
PS3_CMDWORD_FORMAT_HARDWARE = 0x01,
};
enum PS3ReplyWordFlag {
PS3_REPLY_WORD_FLAG_SUCCESS = 0x00,
PS3_REPLY_WORD_FLAG_FAIL = 0X01,
PS3_REPLY_WORD_FLAG_REPEAT_REPLY = 0x0F,
PS3_REPLY_WORD_FLAG_INVALID = 0X7FFF,
};
enum PS3ReplyWordMask {
PS3_REPLY_WORD_MASK_FLAG = 0X7FFF,
};
enum PS3ReplyWordMode {
PS3_REPLY_WORD_MODE_NORMAL = 0x00,
PS3_REPLY_WORD_MODE_DIRECT_ADVICE_TO_NORMAL = 0X01,
PS3_REPLY_WORD_MODE_DIRECT_OK = 0X02,
PS3_REPLY_WORD_MODE_DIRECT_ADVICE_TO_DIRECT = 0X03,
};
enum PS3RetType {
PS3_NOT_HARD_RET = 0x00,
PS3_HARD_RET = 0X01,
};
enum PS3CmdWordVer {
PS3_CMDWORD_VER_0 = 0x0,
PS3_CMDWORD_VER_1 = 0x1,
PS3_CMDWORD_VER_UPDATING = 0x2,
PS3_CMDWORD_VER_INVALID = 0x3,
};
enum PS3CmdWordNoReplyWord {
PS3_CMD_WORD_NEED_REPLY_WORD = 0,
PS3_CMD_WORD_NO_REPLY_WORD = 1,
};
enum PS3ChannelType {
PS3_CHAN_TYPE_UNKNOWN = 0,
PS3_CHAN_TYPE_VD = 1,
PS3_CHAN_TYPE_PD = 2,
};
enum PS3DiskType {
PS3_DISK_TYPE_UNKNOWN = 0,
PS3_DISK_TYPE_VD = 1,
PS3_DISK_TYPE_PD = 2,
};
#define PS3_CONTROL_PAGE_TYPE_BIT_OFFSET (0x1)
#define PS3_CONTROL_PAGE_TYPE_BIT_NUM (0x1)
#define PS3_CONTROL_PAGE_TYPE_MASK (0x1)
enum PS3PageType {
PS3_CONTROL_PAGE_TYPE_OF_SGE = 0,
PS3_CONTROL_PAGE_TYPE_OF_PRP = 1,
PS3_CONTROL_PAGE_TYPE_MAX = 2,
};
static inline const char *namePS3DiskType(enum PS3DiskType e)
{
static const char * const myNames[] = {
[PS3_DISK_TYPE_UNKNOWN] = "PS3_DISK_TYPE_UNKNOWN",
[PS3_DISK_TYPE_VD] = "PS3_DISK_TYPE_VD",
[PS3_DISK_TYPE_PD] = "PS3_DISK_TYPE_PD"
};
return myNames[e];
}
static inline const char *namePS3ChannelType(enum PS3ChannelType e)
{
static const char * const myNames[] = {
[PS3_CHAN_TYPE_UNKNOWN] = "PS3_CHAN_TYPE_UNKNOWN",
[PS3_CHAN_TYPE_VD] = "PS3_CHAN_TYPE_VD",
[PS3_CHAN_TYPE_PD] = "PS3_CHAN_TYPE_PD"
};
return myNames[e];
}
enum PS3DrvMgrErrorCode {
PS3_DRV_MGR_TIMEOUT = 1,
PS3_DRV_MGR_UNRUNING,
PS3_DRV_MGR_INVAL_CMD,
PS3_DRV_MGR_NORESOURCE,
PS3_DRV_MGR_INVAL_PARAM,
PS3_DRV_MGR_DEV_NOEXIST,
PS3_DRV_MGR_DEV_DATA_ERR,
PS3_DRV_MGR_BUSY,
PS3_DRV_MGR_EVT_REPEAT,
PS3_DRV_MGR_EVT_CANCEL_ERR,
PS3_DRV_MGR_FLUSH_FAILED,
PS3_DRV_MGR_SMP_BACKEND_ERR,
PS3_DRV_MGR_LINK_GET_BACKEND_ERR,
PS3_DRV_MGR_PHY_CTL_BACKEND_ERR,
PS3_DRV_MGR_RESTART_COMMAND_RSP,
PS3_DRV_MGR_TM_FAILED,
};
enum PS3IoctlRetCode {
PS3_IOCTL_STATUS_OK = 0,
PS3_IOCTL_STATUS_INVALID_REQ = 1,
PS3_IOCTL_STATUS_NO_HBA = 2,
PS3_IOCTL_STATUS_BUSY = 3,
PS3_IOCTL_STATUS_NOT_READY = 4,
PS3_IOCTL_STATUS_INVALIED_PARAM = 5,
PS3_IOCTL_STATUS_REQ_ERR = 6,
PS3_IOCTL_STATUS_NEED_RETRY = 7,
};
enum PS3HwVdMaxIOSize {
PS3_ENUM_HW_VD_MAX_IO_SIZE_1M = 0,
PS3_ENUM_HW_VD_MAX_IO_SIZE_OTHER,
};
#endif

View File

@ -0,0 +1,328 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef _PS3_HTP_DEV_H_
#define _PS3_HTP_DEV_H_
#include "ps3_htp_def.h"
#define PS3_MAX_CHANNEL_NUM 15
#define PS3_MAX_RANDOM_NUM 32
#define PS3_MAX_IV_NUM 16
#define PS3_SECURITY_CIPHER_NUM_MAX 2
#define PS3_STABLE_WRITES_MASK (0x1)
struct PS3IocCtrlProp {
unsigned int enableSnapshot : 1;
unsigned int enableSoftReset : 1;
unsigned int reserved1 : 30;
unsigned int reserved2;
};
struct PS3IocCtrlCapable {
unsigned int supportUnevenSpans : 1;
unsigned int supportJbodSecure : 1;
unsigned int supportNvmePassthru : 1;
unsigned int supportDirectCmd : 1;
unsigned int supportAcceleration : 1;
unsigned int supportSataDirectCmd : 1;
unsigned int supportSataNcq : 1;
unsigned int reserved1 : 25;
unsigned int reserved2[3];
};
#define PS3_IOC_CLUSTER_SERIAL_NO_SIZE 16
struct PS3ChannelAttr {
unsigned short channelType : 4;
unsigned short maxDevNum : 12;
};
struct PS3ChannelInfo {
unsigned char channelNum;
unsigned char reserved;
struct PS3ChannelAttr channels[PS3_MAX_CHANNEL_NUM];
};
struct PS3QosInfo {
unsigned short tfifoDepth;
unsigned short sataHddQuota;
unsigned short sataSsdQuota;
unsigned short sasHddQuota;
unsigned short sasSsdQuota;
unsigned short nvmeVdQuota;
unsigned short nvmeDirectQuota;
unsigned short nvmeNormalQuota;
};
struct PS3IocCtrlInfo {
unsigned short maxVdCount;
unsigned short maxPdCount;
unsigned int maxSectors;
struct PS3IocCtrlProp properties;
struct PS3IocCtrlCapable capabilities;
unsigned char scsiTaskAbortTimeout;
unsigned char scsiTaskResetTimeout;
unsigned short offsetOfVDID;
unsigned char reserved1[2];
unsigned short cancelTimeOut;
unsigned int vdIOThreshold;
unsigned char iocPerfMode;
unsigned char vdQueueNum;
unsigned char ioTimeOut;
unsigned char hwVdMaxIOSize : 4;
unsigned char reserved2 : 4;
struct PS3ChannelInfo channelInfo;
struct PS3QosInfo qosInfo;
unsigned short isotoneTimeOut;
unsigned char reserved3[2];
unsigned char reserved4[32];
};
struct PS3Dev {
union {
unsigned short phyDiskID;
unsigned short virtDiskID;
};
unsigned short softChan : 4;
unsigned short devID : 12;
};
union PS3DiskDev {
unsigned int diskID;
struct PS3Dev ps3Dev;
};
struct PS3DiskDevPos {
union {
struct {
unsigned char checkSum;
unsigned char enclId;
unsigned char phyId;
};
unsigned int diskMagicNum;
};
union PS3DiskDev diskDev;
};
struct PS3PhyDevice {
struct PS3DiskDevPos diskPos;
unsigned char diskState;
unsigned char configFlag;
unsigned char driverType : 4;
unsigned char mediumType : 4;
unsigned char reserved;
unsigned char reserved1[4];
};
struct PS3VirtDevice {
struct PS3DiskDevPos diskPos;
unsigned char accessPolicy;
unsigned char isHidden;
unsigned char diskState;
unsigned char reserved;
unsigned char reserved1[4];
};
union PS3Device {
struct PS3PhyDevice pd;
struct PS3VirtDevice vd;
};
struct PS3DevList {
unsigned short count;
unsigned char reserved[6];
union PS3Device devs[0];
};
struct PS3PDInfo {
struct PS3DiskDevPos diskPos;
unsigned char diskState;
unsigned char configFlag;
unsigned char driverType : 4;
unsigned char mediumType : 4;
unsigned char scsiInterfaceType;
unsigned char taskAbortTimeout;
unsigned char taskResetTimeout;
union {
struct {
unsigned char supportNCQ : 1;
unsigned char protect : 1;
unsigned char isDirectDisable : 1;
unsigned char reserved : 5;
};
unsigned char pdFlags;
};
unsigned char reserved1;
unsigned short sectorSize;
unsigned char reserved2[2];
unsigned char enclId;
unsigned char phyId;
unsigned char dmaAddrAlignShift;
unsigned char dmaLenAlignShift;
unsigned char reserved3[4];
unsigned int maxIOSize;
unsigned int devQueDepth;
unsigned short normalQuota;
unsigned short directQuota;
unsigned char reserved4[20];
};
struct PS3Extent {
union PS3DiskDev phyDiskID;
unsigned char state;
unsigned char reserved[3];
};
struct PS3Span {
unsigned int spanStripeDataSize;
unsigned char spanState;
unsigned char spanPdNum;
unsigned char reserved[2];
struct PS3Extent extent[PS3_MAX_PD_COUNT_IN_SPAN];
};
struct PS3VDEntry {
struct PS3DiskDevPos diskPos;
unsigned short sectorSize;
unsigned short stripSize;
unsigned int stripeDataSize;
unsigned short physDrvCnt;
unsigned short diskGrpId;
unsigned char accessPolicy;
unsigned char reserved1;
unsigned char dmaAddrAlignShift;
unsigned char dmaLenAlignShift;
unsigned char isDirectEnable : 1;
unsigned char isHidden : 1;
unsigned char isNvme : 1;
unsigned char isSsd : 1;
unsigned char bdev_bdi_cap : 2;
unsigned char isWriteDirectEnable : 1;
unsigned char reserved2 : 1;
unsigned char raidLevel;
unsigned char spanCount;
unsigned char diskState;
unsigned short umapBlkDescCnt : 3;
unsigned short umapNumblk : 13;
unsigned short dev_busy_scale;
unsigned long long startLBA;
unsigned long long extentSize;
unsigned long long mapBlock;
unsigned long long capacity;
unsigned char isTaskMgmtEnable;
unsigned char taskAbortTimeout;
unsigned char taskResetTimeout;
unsigned char mapBlockVer;
unsigned int maxIOSize;
unsigned int devQueDepth;
unsigned short virtDiskSeq;
unsigned short normalQuota;
unsigned short directQuota;
unsigned short reserved4[21];
struct PS3Span span[PS3_MAX_SPAN_IN_VD];
};
struct PS3VDInfo {
unsigned short count;
unsigned char reserved[6];
struct PS3VDEntry vds[0];
};
struct PS3DrvSysInfo {
unsigned char version;
unsigned char systemIDLen;
unsigned char reserved[6];
unsigned char systemID[PS3_DRV_SYSTEM_ID_MAX_LEN];
};
struct PS3PhyInfo {
unsigned long long sasAddr;
unsigned long long attachedSasAddr;
unsigned char phyId;
unsigned char negLinkRate;
unsigned char slotId;
unsigned char attachDevType;
unsigned char initiatorPortProtocol : 4;
unsigned char targetPortProtocols : 4;
unsigned char attachInitiatorPortProtocol : 4;
unsigned char attachTargetPortProtocols : 4;
unsigned char minLinkRateHw : 4;
unsigned char maxLinkRateHw : 4;
unsigned char minLinkRate : 4;
unsigned char maxLinkRate : 4;
unsigned char enable : 1;
unsigned char reserve : 7;
unsigned char reserved[7];
};
struct PS3ExpanderInfo {
unsigned long long sasAddr;
unsigned long long parentSasAddr;
unsigned char parentId;
unsigned char enclID;
unsigned char devType;
unsigned char phyCount;
unsigned char reserved[4];
};
struct PS3Expanders {
unsigned char count;
unsigned char reserved[7];
unsigned long long hbaSasAddr[3];
struct PS3ExpanderInfo expanders[0];
};
struct PS3BiosInfo {
unsigned char biosState;
unsigned char biosMode;
unsigned char biosAbs;
unsigned char devMaxNum;
};
struct PS3BootDriveInfo {
unsigned char hasBootDrive : 1;
unsigned char isPD : 1;
unsigned char reserved_9 : 6;
unsigned char enclID;
unsigned short slotID;
unsigned short vdID;
unsigned char pad[2];
};
struct PS3RandomInfo {
unsigned char randomNum[PS3_MAX_RANDOM_NUM];
unsigned char iv[PS3_MAX_IV_NUM];
};
struct PS3SecurityPwHead {
unsigned char cipherNum;
unsigned int cipherLegth[PS3_SECURITY_CIPHER_NUM_MAX];
unsigned int cipherOffset[PS3_SECURITY_CIPHER_NUM_MAX];
unsigned char iv[PS3_MAX_IV_NUM];
};
#endif

View File

@ -0,0 +1,37 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef _PS3_HTP_EVENT_H_
#define _PS3_HTP_EVENT_H_
#include "ps3_htp_def.h"
#include "ps3_htp_dev.h"
#include "ps3_htp_mgr_evt.h"
#include "ps3_evtcode_trans.h"
#define PS3_EVENT_DETAIL_BUF_MAX (20)
enum PS3EventLevel {
PS3_EVENT_LEVEL_INFO,
PS3_EVENT_LEVEL_WARN,
PS3_EVENT_LEVEL_CRITICAL,
};
struct PS3EventDetail {
unsigned int eventCode;
unsigned int timestamp;
enum MgrEvtType eventType;
union {
struct PS3DiskDevPos devicePos;
unsigned char EnclId;
};
};
struct PS3EventInfo {
unsigned int eventTypeMap;
unsigned int eventCount;
struct PS3EventDetail eventDetail[PS3_EVENT_DETAIL_BUF_MAX];
unsigned char reserved[8];
};
#endif

View File

@ -0,0 +1,112 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef _PS3_HTP_IOCTL_H_
#define _PS3_HTP_IOCTL_H_
#include "ps3_htp.h"
#include "ps3_htp_reqframe.h"
#define PS3_MAX_IOCTL_SGE_NUM 16
#define PS3_IOCTL_SENSE_SIZE 96
#define PS3_IOCTL_MAX_FRAME_SIZE 128
#ifndef PS3_SCSI_HOST_PROC_NAME
#define PS3_SCSI_HOST_PROC_NAME "ps3stor"
#endif
#define PS3_PRODUCT_MODEL "ps3stor"
#ifndef PS3_SCSI_HOST_PROC_NAME_V100
#define PS3_SCSI_HOST_PROC_NAME_V100 "ps3"
#endif
#define PS3_PRODUCT_MODEL_V100 "ps3"
#define PS3_PSW_PRODUCT_MODEL "psw"
struct PS3CmdIoctlHeader {
unsigned char cmdType;
unsigned char version;
unsigned short deviceId;
unsigned short cmdSubType;
unsigned char cmdResult;
unsigned char sglOffset;
unsigned short index;
unsigned short control;
unsigned int sgeCount;
unsigned short timeout;
unsigned char sglChainOffset;
unsigned char syncFlag;
unsigned int abortCmdFrameId;
};
union PS3IoctlFrame {
unsigned char value[PS3_IOCTL_MAX_FRAME_SIZE];
struct PS3CmdIoctlHeader header;
};
#ifdef _WINDOWS
#define PS3_IOCTL_SIG "ps3stor"
#define PS3_IOCTL_FUNCTION 0x801
#define PS3_DEBUG_CLI_FUNCTION 0x802
#define PS3_CTL_CODE \
CTL_CODE(FILE_DEVICE_MASS_STORAGE, PS3_IOCTL_FUNCTION, \
METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
#define PS3_DBG_CLI_CODE \
CTL_CODE(FILE_DEVICE_MASS_STORAGE, PS3_DEBUG_CLI_FUNCTION, \
METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
struct PS3IoctlSyncCmd {
unsigned short hostId;
unsigned short sglOffset;
unsigned short sgeCount;
unsigned short reserved;
unsigned long long traceId;
struct PS3Sge Sgl[PS3_MAX_IOCTL_SGE_NUM];
unsigned char data[0];
};
struct _PS3_IO_CONTROL {
SRB_IO_CONTROL SrbHeader;
unsigned long reserved;
struct PS3IoctlSyncCmd ps3Ioctl;
};
#else
#define PS3_CMD_IOCTL_SYNC_CMD _IOWR('M', 1, struct PS3IoctlSyncCmd)
#ifndef __WIN32__
#define PS3_EVENT_NOTICE_SIG (SIGRTMIN + 7)
enum {
PS3_IOCTL_CMD_NORMAL = 0,
PS3_IOCTL_CMD_WEB_SUBSCRIBE,
};
struct PS3IoctlSyncCmd {
unsigned short hostId;
unsigned short sglOffset;
unsigned short sgeCount;
unsigned short reserved1;
unsigned int resultCode;
unsigned char reserved2[4];
unsigned char sense[PS3_IOCTL_SENSE_SIZE];
unsigned long long traceId;
unsigned char reserved3[120];
union PS3IoctlFrame msg;
struct PS3Sge sgl[PS3_MAX_IOCTL_SGE_NUM];
};
#endif
struct PS3IoctlAsynCmd {
unsigned short hostId;
unsigned short reserved1;
unsigned int seqNum;
unsigned short eventLevel;
unsigned short eventType;
unsigned char reserved2[4];
};
#endif
#endif

View File

@ -0,0 +1,53 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef _PS3_HTP_PCI_H_
#define _PS3_HTP_PCI_H_
#define PCI_DEVICE_ID 0x02
enum {
PCI_VENDOR_ID_STARS = 0x1eb6,
PCI_VENDOR_ID_PS3_FPGA = 0x1eb6,
PCI_VENDOR_ID_PS3_SWITCH_FPGA = 0x1eb6,
PCI_VENDOR_ID_PS3_ASIC = 0x1666,
PCI_VENDOR_ID_PS3 = 0x1ff2,
PCI_DEVICE_ID_PS3_RAID = 0x0001,
PCI_DEVICE_ID_PS3_HBA = 0x0002,
PCI_DEVICE_ID_PS3_SWITCH = 0x0003,
PCI_DEVICE_ID_PS3_SWITCH_FPGA = 0x6004,
PCI_DEVICE_ID_PS3_RAID_FPGA = 0xabcd,
PCI_DEVICE_ID_STARS_HBA_2120_16i = 0x20a1,
PCI_DEVICE_ID_STARS_IOC_2020_18i = 0x20a2,
PCI_DEVICE_ID_STARS_IOC_2213_16i = 0x20a3,
PCI_DEVICE_ID_STARS_ROC_2020_10i = 0x30a2,
PCI_SUBVERDOR_PS3_SWITCH_FPGA = 0x1eb6,
PCI_SUBSYSTEM_PS3_SWITCH_FPGA = 0x6004,
PCI_CLASS_CODE_PS3_SWITCH_FPGA = 0x058000,
};
static inline const char *namePciDevType(unsigned short e)
{
switch (e) {
case PCI_DEVICE_ID_PS3_RAID:
return "PCI_DEVICE_ID_PS3_RAID";
case PCI_DEVICE_ID_PS3_RAID_FPGA:
return "PCI_DEVICE_ID_PS3_RAID_FPGA";
case PCI_DEVICE_ID_PS3_HBA:
return "PCI_DEVICE_ID_PS3_HBA";
case PCI_DEVICE_ID_PS3_SWITCH:
return "PCI_DEVICE_ID_PS3_SWITCH";
case PCI_DEVICE_ID_PS3_SWITCH_FPGA:
return "PCI_DEVICE_ID_PS3_SWITCH_FPGA";
case PCI_DEVICE_ID_STARS_HBA_2120_16i:
return "PCI_DEVICE_ID_STARS_HBA_2120_16i";
case PCI_DEVICE_ID_STARS_IOC_2020_18i:
return "PCI_DEVICE_ID_STARS_IOC_2020_18i";
case PCI_DEVICE_ID_STARS_ROC_2020_10i:
return "PCI_DEVICE_ID_STARS_ROC_2020_10i";
case PCI_DEVICE_ID_STARS_IOC_2213_16i:
return "PCI_DEVICE_ID_STARS_IOC_2213_16i";
default:
return "PCI_DEVICE_ID_INVALID";
}
}
#endif

View File

@ -0,0 +1,98 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef _PS3_HTP_REQ_FRAME_HW_H_
#define _PS3_HTP_REQ_FRAME_HW_H_
#include "ps3_htp_def.h"
#define ENCODE_CCS_XFERLEN(x) (((unsigned int)(x) >> 2))
#define DECODE_CCS_XFERLEN(x) (((unsigned int)(x) << 2))
#ifdef _WINDOWS
#define __attribute__(x)
#pragma pack(push, 1)
#endif
struct PS3NvmeSglDesc {
unsigned long long addr;
union {
struct {
unsigned char reserved[7];
unsigned char subtype : 4;
unsigned char type : 4;
} generic;
struct {
unsigned int length;
unsigned char reserved[3];
unsigned char subtype : 4;
unsigned char type : 4;
} unkeyed;
struct {
unsigned long long length : 24;
unsigned long long key : 32;
unsigned long long subtype : 4;
unsigned long long type : 4;
} keyed;
};
};
struct PS3NvmeCmdDw0_9 {
unsigned short opcode : 8;
unsigned short fuse : 2;
unsigned short reserved1 : 4;
unsigned short psdt : 2;
unsigned short cID;
unsigned int nsID;
unsigned int reserved2;
unsigned int reserved3;
unsigned long long mPtr;
union {
struct {
unsigned long long prp1;
unsigned long long prp2;
} prp;
struct PS3NvmeSglDesc sgl1;
} dPtr;
};
struct PS3NvmeCommonCmd {
struct PS3NvmeCmdDw0_9 cDW0_9;
unsigned int cDW10;
unsigned int cDW11;
unsigned int cDW12;
unsigned int cDW13;
unsigned int cDW14;
unsigned int cDW15;
};
struct PS3NvmeRWCmd {
struct PS3NvmeCmdDw0_9 cDW0_9;
unsigned int sLbaLo;
unsigned int sLbaHi;
unsigned int numLba;
unsigned int cDW13;
unsigned int cDW14;
unsigned int cDW15;
};
union PS3NvmeReqFrame {
struct PS3NvmeCommonCmd commonReqFrame;
struct PS3NvmeRWCmd rwReqFrame;
};
#ifdef _WINDOWS
#pragma pack(pop)
#endif
#endif

View File

@ -0,0 +1,295 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef _PS3_HTP_REQFRAME_H_
#define _PS3_HTP_REQFRAME_H_
#include "ps3_htp_def.h"
#include "ps3_htp_dev.h"
#include "ps3_htp_sas.h"
#include "ps3_htp_req_frame_hw.h"
enum {
PS3_FRAME_SGE_BUFSIZE = 4096,
PS3_FRAME_SGE_SHIFT = 12,
PS3_FRAME_REQ_SGE_NUM_FE = 8,
PS3_FRAME_REQ_PRP_NUM_FE = 2,
PS3_FRAME_REQ_SGE_NUM_HW = 8,
PS3_FRAME_REQ_PRP_NUM_HW = 2,
PS3_FRAME_REQ_SGE_NUM_MGR = 11,
PS3_FRAME_REQ_EXT_SGE_MIN = 2,
PS3_FRAME_CDB_BUFLEN = 32,
PS3_FRAME_LUN_BUFLEN = 8,
PS3_DEBUG_MEM_ARRAY_MAX_NUM = 16,
PS3_MAX_DMA_MEM_SIZE = 4096,
PS3_MAX_DEBUG_MEM_SIZE_PARA = 65536,
PS3_DRV_NAME_MAX_LEN = 32,
PS3_DRV_VERSION_MAX_LEN = 24,
};
enum {
PS3_DATA_DIRECTION_WRITE = 0,
PS3_DATA_DIRECTION_READ = 1,
};
enum {
PS3_REQFRAME_FORMAT_FRONTEND = 0,
PS3_REQFRAME_FORMAT_SAS = 1,
PS3_REQFRAME_FORMAT_SATA = 2,
PS3_REQFRAME_FORMAT_NVME = 3,
};
enum {
PS3_LINUX_FRAME = 0,
PS3_WINDOWS_FRAME = 1,
};
enum {
PS3_COMPAT_VER_DEFAULT = 0,
PS3_COMPAT_VER_1 = 1,
PS3_COMPAT_VER_MAX = 0xffff,
};
struct PS3Sge {
unsigned long long addr;
unsigned int length;
unsigned int reserved1 : 30;
unsigned int lastSge : 1;
unsigned int ext : 1;
};
struct PS3Prp {
unsigned long long prp1;
unsigned long long prp2;
};
struct PS3SoftwareZone {
unsigned long long virtDiskLba;
unsigned int numBlocks;
unsigned char opcode;
unsigned char sglOffset;
unsigned char sglFormat : 2;
unsigned char isResendCmd : 1;
unsigned char reserved1 : 5;
unsigned char reserved2;
unsigned short subOpcode;
unsigned short sgeCount : 9;
unsigned short reserved3 : 7;
unsigned char reserved4[4];
};
struct PS3ReqFrameHead {
unsigned char cmdType;
unsigned char cmdSubType;
unsigned short cmdFrameID;
union {
struct {
unsigned int noReplyWord : 1;
unsigned int dataFormat : 1;
unsigned int reqFrameFormat : 2;
unsigned int mapBlockVer : 2;
unsigned int isWrite : 1;
unsigned int isStream1 : 1;
unsigned int reserved : 24;
};
unsigned int control;
};
union PS3DiskDev devID;
unsigned short timeout;
unsigned short virtDiskSeq;
unsigned short reserved1[4];
unsigned long long traceID;
};
struct PS3HwReqFrame {
struct PS3ReqFrameHead reqHead;
struct PS3SoftwareZone softwareZone;
unsigned char reserved[8];
union {
struct IODT_V1 sasReqFrame;
union PS3NvmeReqFrame nvmeReqFrame;
};
struct PS3Sge sgl[PS3_FRAME_REQ_SGE_NUM_FE];
};
struct PS3VDAccAttr {
unsigned long long firstPdStartLba;
unsigned char firstSpanNo;
unsigned char fisrtSeqInSpan;
unsigned char secondSeqInSapn;
unsigned char thirdSeqInSapn;
unsigned char clineCount;
unsigned char isAccActive : 1;
unsigned char isStream : 1;
unsigned char reserved1 : 6;
unsigned short ioOutStandingCnt;
unsigned char reserved2[16];
};
struct PS3FrontEndReqFrame {
struct PS3ReqFrameHead reqHead;
unsigned char cdb[PS3_FRAME_CDB_BUFLEN];
struct PS3VDAccAttr vdAccAttr;
unsigned int dataXferLen;
unsigned char reserved[25];
unsigned char sgeOffset;
unsigned short sgeCount;
union {
struct PS3Sge sgl[PS3_FRAME_REQ_SGE_NUM_FE];
struct PS3Prp prp;
};
};
struct PS3MgrDev {
struct PS3DiskDevPos devID;
unsigned short num;
unsigned char devType;
unsigned char reserved[17];
};
struct PS3MgrEvent {
unsigned int eventTypeMap;
unsigned int eventTypeMapProcResult;
unsigned int eventLevel;
unsigned char reserved[20];
};
struct PS3SasMgr {
unsigned long long sasAddr;
unsigned char enclID;
unsigned char startPhyID;
unsigned char phyCount;
unsigned char reserved1;
unsigned short reqLen;
unsigned char reserved2[2];
};
struct PS3SasPhySet {
unsigned long long sasAddr;
unsigned char phyID;
unsigned char minLinkRate;
unsigned char maxLinkRate;
unsigned char phyCtrl;
unsigned char reserved[3];
};
union PS3MgrReqDiffValue {
unsigned char word[32];
unsigned short originalCmdFrameID;
unsigned char eventStart;
struct PS3MgrDev dev;
struct PS3MgrEvent event;
struct PS3SasMgr sasMgr;
struct PS3SasPhySet phySet;
unsigned char unLoadType;
int isRetry;
};
struct PS3MgrReqFrame {
struct PS3ReqFrameHead reqHead;
unsigned short sgeCount;
unsigned char sgeOffset;
unsigned char syncFlag;
unsigned short timeout;
unsigned char abortFlag;
unsigned char pendingFlag;
union PS3MgrReqDiffValue value;
unsigned char osType;
unsigned char suspend_type;
unsigned char reserved[6];
struct PS3Sge sgl[PS3_FRAME_REQ_SGE_NUM_MGR];
};
struct PS3MgrTaskReqFrame {
struct PS3ReqFrameHead reqHead;
unsigned short taskID;
unsigned char lun[PS3_FRAME_LUN_BUFLEN];
unsigned char abortedCmdType;
unsigned char reserved[5];
};
union PS3ReqFrame {
struct PS3MgrTaskReqFrame taskReq;
struct PS3MgrReqFrame mgrReq;
struct PS3FrontEndReqFrame frontendReq;
struct PS3HwReqFrame hwReq;
unsigned char word[256];
};
struct PS3DrvInfo {
char drvName[PS3_DRV_NAME_MAX_LEN];
char drvVersion[PS3_DRV_VERSION_MAX_LEN];
unsigned long long bus;
unsigned char dev : 5;
unsigned char func : 3;
unsigned char domain_support : 1;
unsigned char reserved : 7;
unsigned short compatVer;
unsigned int domain;
unsigned char reserved1[56];
};
enum {
PS3_MEM_TYPE_UNKNOWN = 0,
PS3_MEM_TYPE_SO = 1,
PS3_MEM_TYPE_RO = 2,
};
struct PS3HostMemInfo {
unsigned long long startAddr;
unsigned long long endAddr;
unsigned char type;
unsigned char reserved[7];
};
struct PS3InitReqFrame {
struct PS3ReqFrameHead reqHead;
unsigned char ver;
unsigned char reserved0;
unsigned short length;
unsigned char operater;
unsigned char pageSize;
unsigned char pciIrqType;
unsigned char osType;
unsigned char reserved1[6];
unsigned short msixVector;
unsigned long long timeStamp;
unsigned long long reqFrameBufBaseAddr;
unsigned long long hostMemInfoBaseAddr;
unsigned int hostMemInfoNum;
unsigned char reserved2[20];
unsigned long long replyFifoDescBaseAddr;
unsigned long long respFrameBaseAddr;
unsigned int eventTypeMap;
unsigned short reqFrameMaxNum;
unsigned short respFrameMaxNum;
unsigned long long filterTableAddr;
unsigned int filterTableLen;
unsigned short bufSizePerRespFrame;
unsigned char hilMode;
unsigned char reserved3[33];
unsigned long long systemInfoBufAddr;
unsigned long long debugMemArrayAddr;
unsigned int debugMemArrayNum;
unsigned int dumpDmaBufLen;
unsigned long long dumpDmaBufAddr;
unsigned int dumpIsrSN;
unsigned short drvInfoBufLen;
unsigned char reserverd4[2];
unsigned long long drvInfoBufAddr;
unsigned char reserved5[36];
unsigned int respStatus;
};
#endif

View File

@ -0,0 +1,324 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef _PS3_IODT_H_
#define _PS3_IODT_H_
#include "ps3_htp_def.h"
enum IodtProtocolType {
PROTOCOL_SMP = 0b000,
PROTOCOL_SSP = 0b001,
PROTOCOL_STP = 0b010,
PROTOCOL_DIRT = 0b111,
};
enum IodtFrameType {
FRAMETYPE_SSP_CMD = 0b001,
FRAMETYPE_SSP_SMP = 0b001,
FRAMETYPE_SATA_NONDATA = 0b001,
FRAMETYPE_SSP_TASK = 0b010,
FRAMETYPE_SATA_PIO = 0b010,
FRAMETYPE_SATA_DMA = 0b011,
FRAMETYPE_SATA_FPDMA = 0b100,
FRAMETYPE_SATA_ATAPI = 0b101,
FRAMETYPE_DIRECT = 0b111,
};
enum IodtIuSrc {
IU_SRC_MEM = 0b00,
IU_SRC_IODT = 0b01,
IU_SRC_TUPLE = 0b10,
IU_SRC_SATA = 0b11,
};
enum IodtSgeMode {
IODT_SGEMODE_DIRECT = 0x0,
IODT_SGEMODE_SGL = 0x1,
};
enum IodtEedpMode {
EEDP_MODE_CHECK = 0x0,
EEDP_MODE_INSERT = 0x1,
EEDP_MODE_REPLACE = 0x2,
EEDP_MODE_RMV = 0x3,
};
enum AbortCtrl {
ABT_SASSATA_TASK = 0b00,
ABT_SAS_TASKSET = 0b01,
ABT_LOCAL_BY_DISK = 0b10,
ABT_LOCAL_BY_PORT = 0b11,
ABT_MGT_IO = 0b00,
ABT_SOFTRESET = 0b01,
ABT_READ_NCQ_ERR_LOG = 0b10,
ABT_SMP = 0b11,
};
enum DirectFlag {
DIRECT_FLAG_NORMAL = 0b00,
DIRECT_FLAG_DIRECT = 0b10,
};
enum CmdWordType {
CMD_WORD_TYPE_ABORT = 0b00,
CMD_WORD_TYPE_MGT = 0b01,
CMD_WORD_TYPE_READ = 0b10,
CMD_WORD_TYPE_WRITE = 0b11,
};
enum SmpFrameType {
SMP_REQ = 0x40,
SMP_RESP = 0x41,
};
enum eedpMode {
EEDP_NONE = 0b0000,
EEDP_CHK = 0b0001,
EEDP_INST = 0b0010,
EEDP_REPL = 0b0100,
EEDP_RMV = 0b1000,
};
union IoDmaCfg {
struct {
unsigned char eedpEn : 1;
unsigned char eedpSgMod : 1;
unsigned char twoSglMod : 1;
unsigned char sgMode : 1;
unsigned char eedpMode : 4;
};
unsigned char byte;
};
struct __packed SspTaskFrameIu {
unsigned long long LUN;
unsigned short reserved0;
unsigned char function;
unsigned char reserved1;
unsigned short manageTag;
unsigned char reserved2[14];
};
union __packed SmpFrameIu {
struct {
unsigned char frameType;
unsigned char reqestBytes[31];
};
unsigned char smpIURaw[32];
};
struct __packed DfifoWordCommon {
union {
struct {
unsigned short type : 2;
unsigned short rsv1 : 2;
unsigned short direct : 2;
unsigned short rFifoID : 4;
unsigned short rsv2 : 6;
};
unsigned short WD0;
};
union {
struct {
union {
struct {
unsigned short darID : 13;
unsigned short rsv3 : 2;
unsigned short function : 1;
};
struct {
unsigned short manageIptt : 13;
};
};
};
struct {
union {
struct {
unsigned short reqFrameID : 13;
};
struct {
unsigned short manageReqFrameID : 13;
};
};
};
unsigned short WD1;
};
union {
struct {
unsigned short phyDiskID : 12;
unsigned short rsv4 : 2;
unsigned short abortCtrl : 2;
};
unsigned short WD2;
};
};
struct __packed IODT_V1 {
union {
struct __packed {
union {
struct {
union {
struct {
unsigned char
protocolType : 3;
unsigned char
frameType : 3;
unsigned char iuSrc : 2;
};
unsigned char byte0;
};
union IoDmaCfg dmaCfg;
};
unsigned short config;
};
unsigned short cmdLen : 9;
unsigned short rsv0 : 7;
union {
struct {
unsigned int taskDarID : 13;
unsigned int resv0 : 19;
};
struct {
unsigned int dataBufLenDWAlign : 24;
unsigned int rsvd0 : 1;
unsigned int cmdDir : 1;
unsigned int refTagEn : 1;
unsigned int appTagEn : 1;
unsigned int guardTagEn : 1;
unsigned int refTagInc : 1;
unsigned int rsv1 : 1;
unsigned int aborted : 1;
};
};
};
unsigned long long QW0;
};
union {
struct __packed {
struct DfifoWordCommon commonWord;
unsigned short rsv2 : 1;
unsigned short sataCtl : 1;
unsigned short rsv3 : 2;
unsigned short sasCtl : 1;
unsigned short sataByteBlock0 : 1;
unsigned short sataByteBlock1 : 1;
unsigned short rsv4 : 9;
};
unsigned long long QW1;
};
union {
unsigned long long dataBaseAddr;
unsigned long long QW2;
};
union {
unsigned long long eedpBaseAddr;
unsigned long long QW3;
};
union {
struct {
unsigned long long cmdIUAddr;
unsigned long long rsv9;
unsigned long long refTag : 32;
unsigned long long appTag : 16;
unsigned long long rsv10 : 16;
unsigned long long rsv11;
} A;
union {
unsigned char cdb[32];
struct SspTaskFrameIu taskIU;
union SmpFrameIu smpIU;
} B;
struct {
unsigned long long opCode : 8;
unsigned long long rsv12 : 56;
unsigned long long lba : 48;
unsigned long long rsv13 : 16;
unsigned long long refTag : 32;
unsigned long long appTag : 16;
unsigned long long rsv14 : 16;
unsigned long long rsv15;
} C;
struct {
unsigned int ataCmd : 8;
unsigned int ataDev : 8;
unsigned int ataCtl : 8;
unsigned int ataIcc : 8;
unsigned int ataSecCnt : 16;
unsigned int ataFeature : 16;
union {
struct {
unsigned long long ataLba : 48;
unsigned long long rsv16 : 16;
};
struct {
unsigned char lba0;
unsigned char lba1;
unsigned char lba2;
unsigned char lba3;
unsigned char lba4;
unsigned char lba5;
};
unsigned char lba[6];
};
unsigned int ataAuxiliary;
unsigned int rsv17;
unsigned long long rsv18;
} D;
};
};
enum {
CMD_LEN_THR = 32,
CMD_LEN_S = 7,
CMD_LEN_L = 11,
};
#endif

View File

@ -0,0 +1,9 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef __S1861_GLOBAL_BASEADDR_REG_H__
#define __S1861_GLOBAL_BASEADDR_REG_H__
#define HIL_REG0_PS3_REGISTER_F_BASEADDR 0x24000000UL
#define HIL_REG0_PS3_REGISTER_F_SIZE 0x10000UL
#define HIL_REG0_PS3_REQUEST_QUEUE_BASEADDR 0x24010000UL
#define HIL_REG0_PS3_REQUEST_QUEUE_SIZE 0x200UL
#define HIL_REG0_PS3_REGISTER_S_SIZE 0x1FE00UL
#endif

View File

@ -0,0 +1,39 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef __S1861_HIL_REG0_PS3_REGISTER_S_REG_H__
#define __S1861_HIL_REG0_PS3_REGISTER_S_REG_H__
#include "s1861_global_baseaddr.h"
#ifndef __S1861_HIL_REG0_PS3_REGISTER_S_REG_MACRO__
#define HIL_REG0_PS3_REGISTER_S_PS3_FUNCTION_LOCK_ADDR \
(HIL_REG0_PS3_REGISTER_S_BASEADDR + 0x0)
#define HIL_REG0_PS3_REGISTER_S_PS3_FUNCTION_LOCK_RST (0x0000000000000000)
#define HIL_REG0_PS3_REGISTER_S_PS3_FUNCTION_LOCK_OWNER_ADDR \
(HIL_REG0_PS3_REGISTER_S_BASEADDR + 0x8)
#define HIL_REG0_PS3_REGISTER_S_PS3_FUNCTION_LOCK_OWNER_RST (0x0000000000000003)
#endif
#ifndef __S1861_HIL_REG0_PS3_REGISTER_S_REG_STRUCT__
union HilReg0Ps3RegisterSPs3FucntionLock {
unsigned long long val;
struct {
unsigned long long lock : 1;
unsigned long long reserved1 : 63;
} reg;
};
union HilReg0Ps3RegisterSPs3FunctionLockOwner {
unsigned long long val;
struct {
unsigned long long display : 2;
unsigned long long reserved1 : 62;
} reg;
};
struct HilReg0Ps3RegisterS {
union HilReg0Ps3RegisterSPs3FucntionLock ps3FucntionLock;
union HilReg0Ps3RegisterSPs3FunctionLockOwner ps3FunctionLockOwner;
};
#endif
#endif

View File

@ -0,0 +1,424 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef __S1861_HIL_REG0_PS3_REQUEST_QUEUE_REG_H__
#define __S1861_HIL_REG0_PS3_REQUEST_QUEUE_REG_H__
#include "s1861_global_baseaddr.h"
#ifndef __S1861_HIL_REG0_PS3_REQUEST_QUEUE_REG_MACRO__
#define HIL_REG0_PS3_REQUEST_QUEUE_PS3_REQUEST_QUEUE_ADDR \
(HIL_REG0_PS3_REQUEST_QUEUE_BASEADDR + 0x0)
#define HIL_REG0_PS3_REQUEST_QUEUE_PS3_REQUEST_QUEUE_RST (0xFFFFFFFFFFFFFFFF)
#define HIL_REG0_PS3_REQUEST_QUEUE_FIFOERRCNT_ADDR \
(HIL_REG0_PS3_REQUEST_QUEUE_BASEADDR + 0x8)
#define HIL_REG0_PS3_REQUEST_QUEUE_FIFOERRCNT_RST (0x0000000000000000)
#define HIL_REG0_PS3_REQUEST_QUEUE_FIFOSTATUS_ADDR \
(HIL_REG0_PS3_REQUEST_QUEUE_BASEADDR + 0x10)
#define HIL_REG0_PS3_REQUEST_QUEUE_FIFOSTATUS_RST (0x0000000C1FFF0000)
#define HIL_REG0_PS3_REQUEST_QUEUE_FIFOLEVELCONFIG_ADDR \
(HIL_REG0_PS3_REQUEST_QUEUE_BASEADDR + 0x18)
#define HIL_REG0_PS3_REQUEST_QUEUE_FIFOLEVELCONFIG_RST (0x0000000300000000)
#define HIL_REG0_PS3_REQUEST_QUEUE_FIFORST_ADDR \
(HIL_REG0_PS3_REQUEST_QUEUE_BASEADDR + 0x20)
#define HIL_REG0_PS3_REQUEST_QUEUE_FIFORST_RST (0x0000000000000000)
#define HIL_REG0_PS3_REQUEST_QUEUE_FIFOIOCNT_ADDR \
(HIL_REG0_PS3_REQUEST_QUEUE_BASEADDR + 0x28)
#define HIL_REG0_PS3_REQUEST_QUEUE_FIFOIOCNT_RST (0x0000000000000000)
#define HIL_REG0_PS3_REQUEST_QUEUE_FIFOFLOWCNT_ADDR \
(HIL_REG0_PS3_REQUEST_QUEUE_BASEADDR + 0x30)
#define HIL_REG0_PS3_REQUEST_QUEUE_FIFOFLOWCNT_RST (0x0000000000000000)
#define HIL_REG0_PS3_REQUEST_QUEUE_FIFO_INT_STATUS_ADDR \
(HIL_REG0_PS3_REQUEST_QUEUE_BASEADDR + 0x38)
#define HIL_REG0_PS3_REQUEST_QUEUE_FIFO_INT_STATUS_RST (0x0000000000000000)
#define HIL_REG0_PS3_REQUEST_QUEUE_FIFO_INT_SET_ADDR \
(HIL_REG0_PS3_REQUEST_QUEUE_BASEADDR + 0x40)
#define HIL_REG0_PS3_REQUEST_QUEUE_FIFO_INT_SET_RST (0x0000000000000000)
#define HIL_REG0_PS3_REQUEST_QUEUE_FIFO_INT_CLR_ADDR \
(HIL_REG0_PS3_REQUEST_QUEUE_BASEADDR + 0x48)
#define HIL_REG0_PS3_REQUEST_QUEUE_FIFO_INT_CLR_RST (0x0000000000000000)
#define HIL_REG0_PS3_REQUEST_QUEUE_FIFO_INT_MASK_ADDR \
(HIL_REG0_PS3_REQUEST_QUEUE_BASEADDR + 0x50)
#define HIL_REG0_PS3_REQUEST_QUEUE_FIFO_INT_MASK_RST (0x0000000000000000)
#define HIL_REG0_PS3_REQUEST_QUEUE_FIFO_CNT_CLR_ADDR \
(HIL_REG0_PS3_REQUEST_QUEUE_BASEADDR + 0x58)
#define HIL_REG0_PS3_REQUEST_QUEUE_FIFO_CNT_CLR_RST (0x0000000000000000)
#define HIL_REG0_PS3_REQUEST_QUEUE_FIFOORDERERROR_ADDR \
(HIL_REG0_PS3_REQUEST_QUEUE_BASEADDR + 0x60)
#define HIL_REG0_PS3_REQUEST_QUEUE_FIFOORDERERROR_RST (0x0000000000000000)
#define HIL_REG0_PS3_REQUEST_QUEUE_FIFODINSHIFT_ADDR(_n) \
(HIL_REG0_PS3_REQUEST_QUEUE_BASEADDR + 0x68 + (_n) * 0x8)
#define HIL_REG0_PS3_REQUEST_QUEUE_FIFODINSHIFT_RST (0x0000000000000000)
#define HIL_REG0_PS3_REQUEST_QUEUE_FIFODOUTSHIFT_ADDR(_n) \
(HIL_REG0_PS3_REQUEST_QUEUE_BASEADDR + 0x88 + (_n) * 0x8)
#define HIL_REG0_PS3_REQUEST_QUEUE_FIFODOUTSHIFT_RST (0x0000000000000000)
#define HIL_REG0_PS3_REQUEST_QUEUE_FIFOSTATUS_MAXLEVEL_ADDR \
(HIL_REG0_PS3_REQUEST_QUEUE_BASEADDR + 0xa8)
#define HIL_REG0_PS3_REQUEST_QUEUE_FIFOSTATUS_MAXLEVEL_RST (0x0000000000000000)
#define HIL_REG0_PS3_REQUEST_QUEUE_FIFOINIT_ADDR \
(HIL_REG0_PS3_REQUEST_QUEUE_BASEADDR + 0xb0)
#define HIL_REG0_PS3_REQUEST_QUEUE_FIFOINIT_RST (0x0000000000000002)
#define HIL_REG0_PS3_REQUEST_QUEUE_FIFOINIT_EN_ADDR \
(HIL_REG0_PS3_REQUEST_QUEUE_BASEADDR + 0xb8)
#define HIL_REG0_PS3_REQUEST_QUEUE_FIFOINIT_EN_RST (0x0000000000000000)
#define HIL_REG0_PS3_REQUEST_QUEUE_FIFOINIT_MAX_ADDR \
(HIL_REG0_PS3_REQUEST_QUEUE_BASEADDR + 0xc0)
#define HIL_REG0_PS3_REQUEST_QUEUE_FIFOINIT_MAX_RST (0x0000000000000000)
#define HIL_REG0_PS3_REQUEST_QUEUE_FIFOSTATUS_ECC_CNT_ADDR \
(HIL_REG0_PS3_REQUEST_QUEUE_BASEADDR + 0xc8)
#define HIL_REG0_PS3_REQUEST_QUEUE_FIFOSTATUS_ECC_CNT_RST (0x0000000000000000)
#define HIL_REG0_PS3_REQUEST_QUEUE_FIFOSTATUS_ECC_ADDR_ADDR \
(HIL_REG0_PS3_REQUEST_QUEUE_BASEADDR + 0xd0)
#define HIL_REG0_PS3_REQUEST_QUEUE_FIFOSTATUS_ECC_ADDR_RST (0x0000000000000000)
#define HIL_REG0_PS3_REQUEST_QUEUE_FIFO_DECODER_OVERFLOW_ADDR \
(HIL_REG0_PS3_REQUEST_QUEUE_BASEADDR + 0xd8)
#define HIL_REG0_PS3_REQUEST_QUEUE_FIFO_DECODER_OVERFLOW_RST \
(0x000000000000003F)
#define HIL_REG0_PS3_REQUEST_QUEUE_FIFO_ECC_BAD_PROJECT_ADDR \
(HIL_REG0_PS3_REQUEST_QUEUE_BASEADDR + 0xe0)
#define HIL_REG0_PS3_REQUEST_QUEUE_FIFO_ECC_BAD_PROJECT_RST (0x0000000000000001)
#define HIL_REG0_PS3_REQUEST_QUEUE_FIFOOVERFLOW_WORD_ADDR \
(HIL_REG0_PS3_REQUEST_QUEUE_BASEADDR + 0xe8)
#define HIL_REG0_PS3_REQUEST_QUEUE_FIFOOVERFLOW_WORD_RST (0x0000000000000000)
#define HIL_REG0_PS3_REQUEST_QUEUE_FIFOLEVELMONITORCTL_ADDR \
(HIL_REG0_PS3_REQUEST_QUEUE_BASEADDR + 0xf0)
#define HIL_REG0_PS3_REQUEST_QUEUE_FIFOLEVELMONITORCTL_RST (0x0000000000000000)
#define HIL_REG0_PS3_REQUEST_QUEUE_FIFOLEVELMONITORCNTCLR_ADDR \
(HIL_REG0_PS3_REQUEST_QUEUE_BASEADDR + 0xf8)
#define HIL_REG0_PS3_REQUEST_QUEUE_FIFOLEVELMONITORCNTCLR_RST \
(0x0000000000000000)
#define HIL_REG0_PS3_REQUEST_QUEUE_FIFOLEVELMONITORLOW_ADDR \
(HIL_REG0_PS3_REQUEST_QUEUE_BASEADDR + 0x100)
#define HIL_REG0_PS3_REQUEST_QUEUE_FIFOLEVELMONITORLOW_RST (0x0000000000000000)
#define HIL_REG0_PS3_REQUEST_QUEUE_FIFOLEVELMONITORMID_ADDR \
(HIL_REG0_PS3_REQUEST_QUEUE_BASEADDR + 0x108)
#define HIL_REG0_PS3_REQUEST_QUEUE_FIFOLEVELMONITORMID_RST (0x0000000000000000)
#define HIL_REG0_PS3_REQUEST_QUEUE_FIFOLEVELMONITORHIGH_ADDR \
(HIL_REG0_PS3_REQUEST_QUEUE_BASEADDR + 0x110)
#define HIL_REG0_PS3_REQUEST_QUEUE_FIFOLEVELMONITORHIGH_RST (0x0000000000000000)
#endif
#ifndef __S1861_HIL_REG0_PS3_REQUEST_QUEUE_REG_STRUCT__
union HilReg0Ps3RequestQueuePs3RequestQueue {
unsigned long long val;
struct {
unsigned long long port : 64;
} reg;
};
union HilReg0Ps3RequestQueueFifoErrCnt {
unsigned long long val;
struct {
unsigned long long waddrerr : 32;
unsigned long long reserved1 : 32;
} reg;
};
union HilReg0Ps3RequestQueueFifoStatus {
unsigned long long val;
struct {
unsigned long long filled : 16;
unsigned long long fifoDepth : 16;
unsigned long long almostfull : 1;
unsigned long long full : 1;
unsigned long long almostempty : 1;
unsigned long long empty : 1;
unsigned long long reserved6 : 28;
} reg;
};
union HilReg0Ps3RequestQueueFifoLevelConfig {
unsigned long long val;
struct {
unsigned long long cfgAempty : 16;
unsigned long long cfgAfull : 16;
unsigned long long emptyProtect : 1;
unsigned long long fullProtect : 1;
unsigned long long reserved4 : 30;
} reg;
};
union HilReg0Ps3RequestQueueFifoRst {
unsigned long long val;
struct {
unsigned long long resetPls : 1;
unsigned long long reserved1 : 63;
} reg;
};
union HilReg0Ps3RequestQueueFifoIOCnt {
unsigned long long val;
struct {
unsigned long long wr : 32;
unsigned long long rd : 32;
} reg;
};
union HilReg0Ps3RequestQueueFifoFlowCnt {
unsigned long long val;
struct {
unsigned long long overflow : 32;
unsigned long long underflow : 32;
} reg;
};
union HilReg0Ps3RequestQueueFifoIntStatus {
unsigned long long val;
struct {
unsigned long long overflowStatus : 1;
unsigned long long underflowStatus : 1;
unsigned long long nemptyStatus : 1;
unsigned long long eccBadStatus : 1;
unsigned long long reserved4 : 60;
} reg;
};
union HilReg0Ps3RequestQueueFifoIntSet {
unsigned long long val;
struct {
unsigned long long overflowSet : 1;
unsigned long long underflowSet : 1;
unsigned long long nemptySet : 1;
unsigned long long eccBadSet : 1;
unsigned long long reserved4 : 60;
} reg;
};
union HilReg0Ps3RequestQueueFifoIntClr {
unsigned long long val;
struct {
unsigned long long overflowClr : 1;
unsigned long long underflowClr : 1;
unsigned long long nemptyClr : 1;
unsigned long long eccBadClr : 1;
unsigned long long reserved4 : 60;
} reg;
};
union HilReg0Ps3RequestQueueFifoIntMask {
unsigned long long val;
struct {
unsigned long long overflowMask : 1;
unsigned long long underflowMask : 1;
unsigned long long nemptyMask : 1;
unsigned long long eccBadMask : 1;
unsigned long long reserved4 : 60;
} reg;
};
union HilReg0Ps3RequestQueueFifoCntClr {
unsigned long long val;
struct {
unsigned long long fifowrcntClr : 1;
unsigned long long fifordcntClr : 1;
unsigned long long fifoerrcntClr : 1;
unsigned long long fifoordererrwrcntClr : 1;
unsigned long long fifoordererrrdcntClr : 1;
unsigned long long fifobit1errcntClr : 1;
unsigned long long fifobit2errcntClr : 1;
unsigned long long reserved7 : 57;
} reg;
};
union HilReg0Ps3RequestQueueFifoOrderError {
unsigned long long val;
struct {
unsigned long long wrcnt : 32;
unsigned long long rdcnt : 32;
} reg;
};
union HilReg0Ps3RequestQueueFifoDinShift {
unsigned long long val;
struct {
unsigned long long val : 64;
} reg;
};
union HilReg0Ps3RequestQueueFifoDoutShift {
unsigned long long val;
struct {
unsigned long long val : 64;
} reg;
};
union HilReg0Ps3RequestQueueFifostatusMaxlevel {
unsigned long long val;
struct {
unsigned long long val : 16;
unsigned long long reserved1 : 48;
} reg;
};
union HilReg0Ps3RequestQueueFifoInit {
unsigned long long val;
struct {
unsigned long long stat : 2;
unsigned long long reserved1 : 62;
} reg;
};
union HilReg0Ps3RequestQueueFifoinitEn {
unsigned long long val;
struct {
unsigned long long start : 1;
unsigned long long reserved1 : 63;
} reg;
};
union HilReg0Ps3RequestQueueFifoinitMax {
unsigned long long val;
struct {
unsigned long long num : 16;
unsigned long long reserved1 : 48;
} reg;
};
union HilReg0Ps3RequestQueueFifostatusEccCnt {
unsigned long long val;
struct {
unsigned long long bit1Err : 32;
unsigned long long bit2Err : 32;
} reg;
};
union HilReg0Ps3RequestQueueFifostatusEccAddr {
unsigned long long val;
struct {
unsigned long long errPoint : 64;
} reg;
};
union HilReg0Ps3RequestQueueFifoDecoderOverflow {
unsigned long long val;
struct {
unsigned long long rCmdwordEmpty : 1;
unsigned long long rPortindexEmpty : 1;
unsigned long long rCmdbackEmpty : 1;
unsigned long long wCmdwordEmpty : 1;
unsigned long long wPortindexEmpty : 1;
unsigned long long wCmdbackEmpty : 1;
unsigned long long rCmdwordFull : 1;
unsigned long long rPortindexFull : 1;
unsigned long long rCmdbackFull : 1;
unsigned long long wCmdwordFull : 1;
unsigned long long wPortindexFull : 1;
unsigned long long wCmdbackFull : 1;
unsigned long long reserved12 : 52;
} reg;
};
union HilReg0Ps3RequestQueueFifoEccBadProject {
unsigned long long val;
struct {
unsigned long long en : 1;
unsigned long long reserved1 : 63;
} reg;
};
union HilReg0Ps3RequestQueueFifooverflowWord {
unsigned long long val;
struct {
unsigned long long record : 64;
} reg;
};
union HilReg0Ps3RequestQueueFifoLevelMonitorCtl {
unsigned long long val;
struct {
unsigned long long low : 16;
unsigned long long high : 16;
unsigned long long en : 1;
unsigned long long reserved3 : 31;
} reg;
};
union HilReg0Ps3RequestQueueFifoLevelMonitorCntClr {
unsigned long long val;
struct {
unsigned long long en : 1;
unsigned long long reserved1 : 63;
} reg;
};
union HilReg0Ps3RequestQueueFifoLevelMonitorLow {
unsigned long long val;
struct {
unsigned long long cnt : 64;
} reg;
};
union HilReg0Ps3RequestQueueFifoLevelMonitorMid {
unsigned long long val;
struct {
unsigned long long cnt : 64;
} reg;
};
union HilReg0Ps3RequestQueueFifoLevelMonitorHigh {
unsigned long long val;
struct {
unsigned long long cnt : 64;
} reg;
};
struct HilReg0Ps3RequestQueue {
union HilReg0Ps3RequestQueuePs3RequestQueue ps3RequestQueue;
union HilReg0Ps3RequestQueueFifoErrCnt fifoErrCnt;
union HilReg0Ps3RequestQueueFifoStatus fifoStatus;
union HilReg0Ps3RequestQueueFifoLevelConfig fifoLevelConfig;
union HilReg0Ps3RequestQueueFifoRst fifoRst;
union HilReg0Ps3RequestQueueFifoIOCnt fifoIOCnt;
union HilReg0Ps3RequestQueueFifoFlowCnt fifoFlowCnt;
union HilReg0Ps3RequestQueueFifoIntStatus fifoIntStatus;
union HilReg0Ps3RequestQueueFifoIntSet fifoIntSet;
union HilReg0Ps3RequestQueueFifoIntClr fifoIntClr;
union HilReg0Ps3RequestQueueFifoIntMask fifoIntMask;
union HilReg0Ps3RequestQueueFifoCntClr fifoCntClr;
union HilReg0Ps3RequestQueueFifoOrderError fifoOrderError;
union HilReg0Ps3RequestQueueFifoDinShift fifoDinShift[4];
union HilReg0Ps3RequestQueueFifoDoutShift fifoDoutShift[4];
union HilReg0Ps3RequestQueueFifostatusMaxlevel fifoStatusMaxLevel;
union HilReg0Ps3RequestQueueFifoInit fifoInit;
union HilReg0Ps3RequestQueueFifoinitEn fifoinitEn;
union HilReg0Ps3RequestQueueFifoinitMax fifoinitMax;
union HilReg0Ps3RequestQueueFifostatusEccCnt fifoStatusEccCnt;
union HilReg0Ps3RequestQueueFifostatusEccAddr fifoStatusEccAddr;
union HilReg0Ps3RequestQueueFifoDecoderOverflow fifoDecoderOverflow;
union HilReg0Ps3RequestQueueFifoEccBadProject fifoEccBadProject;
union HilReg0Ps3RequestQueueFifooverflowWord fifoOverFlowWord;
union HilReg0Ps3RequestQueueFifoLevelMonitorCtl fifoLevelMonitorCtl;
union HilReg0Ps3RequestQueueFifoLevelMonitorCntClr
fifoLevelMonitorCntClr;
union HilReg0Ps3RequestQueueFifoLevelMonitorLow fifoLevelMonitorLow;
union HilReg0Ps3RequestQueueFifoLevelMonitorMid fifoLevelMonitorMid;
union HilReg0Ps3RequestQueueFifoLevelMonitorHigh fifoLevelMonitorHigh;
};
#endif
#endif

View File

@ -0,0 +1,507 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef __PS3_EVTCODE_TRANS_H__
#define __PS3_EVTCODE_TRANS_H__
#if !(defined(PS3_PRODUCT_EXPANDER) || defined(PS3_PRODUCT_SWITCH))
#include "ps3_htp_mgr_evt_raidhba.h"
#define PS3_EVT_EXT_NR (PS3_EVT_MAX_TYPE_LOCAL - MGR_EVT_EXTEND_TYPE_START)
static inline char const *mgrEvtCodeTrans(unsigned int opCode)
{
unsigned int typeIndex = 0;
unsigned int codeIndex = 0;
const char *pEvtTransStr = NULL;
static const char *pEvtCodeInfo[MGR_EVT_EXTEND_TYPE_START][MGR_EVT_TYPE_OFFSET] = {
{
"MGR_EVT_SAS_START",
"MGR_EVT_SAS_EXPANDER_IN",
"MGR_EVT_SAS_EXPANDER_OUT",
"MGR_EVT_SAS_EXPANDER_UPDATE",
"MGR_EVT_SAS_EXPANDER_CHANGE",
"MGR_EVT_ENCL_TEMP_NORMAL",
"MGR_EVT_ENCL_TEMP_WARNING",
"MGR_EVT_ENCL_TEMP_CRITICAL",
"MGR_EVT_TOPO_LOOP",
"MGR_EVT_LOOP_RESOLUTION",
"MGR_EVT_CASCADED_SCAN_SMP_FAIL",
"MGR_EVT_ENCL_EXCEED",
"MGR_EVT_TRI_MODE_SWITCH",
"MGR_EVT_CHANGE_PHY_BY_USER",
"MGR_EVT_REV_HIBERNATE_CMD",
"MGR_EVT_PHY_CHANGE",
"MGR_EVT_INQUIRY_INFO",
"MGR_EVT_SAS_SATA_LINK_SPEED_NOMATCH",
"MGR_EVT_SAS_SATA_LN_EXCEPTION",
"MGR_EVT_SAS_SATA_DRIVER_INFO",
},
{
"MGR_EVT_PD_COUNT_START",
"MGR_EVT_DEVM_DISK_IN",
"MGR_EVT_DEVM_DISK_OUT",
"MGR_EVT_MULITPILE_PD_IN",
"MGR_EVT_MULITPILE_PD_OUT",
"MGR_EVT_DEVM_JBOD",
"MGR_EVT_DEVM_READY",
"MGR_EVT_MULITPILE_JBOD",
"MGR_EVT_MULITPILE_READY",
"MGR_EVT_BACKPLANE_ON",
"MGR_EVT_BACKPLANE_OFF",
"MGR_EVT_MULITPILE_PD_STATE_CHANGE",
"MGR_EVT_DEVM_DISK_CHANGE",
"MGR_EVT_DEFAULT_UNUSED",
"MGR_EVT_PD_PRE_READY",
},
{
"MGR_EVT_VD_COUNT_START",
"MGR_EVT_VD_OPTIMAL",
"MGR_EVT_VD_PARTIAL_DEGRADE",
"MGR_EVT_VD_DEGRADE",
"MGR_EVT_VD_CREATED",
"MGR_EVT_VD_DELETED",
"MGR_EVT_VD_HIDDEN_CHANGE",
"MGR_EVT_MULITPILE_VD_IN",
"MGR_EVT_MULITPILE_VD_OUT",
"MGR_EVT_VD_UNLOCK",
"MGR_EVT_VD_OFFLINE",
},
{
"MGR_EVT_CTRL_INFO_START",
"MGR_EVT_CTRL_REBOOT",
"MGR_EVT_CTRL_SHUTDOWN",
"MGR_EVT_CTRL_TIME_CHANGE",
"MGR_EVT_CTRL_EVENT_LOG_CLEARED",
"MGR_EVT_CTRL_RBLD_RATE_CHANGED",
"MGR_EVT_CTRL_ENABLEMOVEBACK_CHANGED",
"MGR_EVT_CTRL_ENABLENCQ_CHANGED",
"MGR_EVT_CTRL_AUTO_REBUILD_CHANGED",
"MGR_EVT_CTRL_EGHS_READY_CHANGED",
"MGR_EVT_CTRL_EGHS_SPARE_CHANGED",
"MGR_EVT_CTRL_BGI_RATE_CHANGED",
"MGR_EVT_CTRL_MIGRATE_RATE_CHANGED",
"MGR_EVT_CTRL_CC_RATE_CHANGED",
"MGR_EVT_CTRL_DIRECT_CHANGE",
"MGR_EVT_CTRL_PR_START",
"MGR_EVT_CTRL_PR_PAUSE",
"MGR_EVT_CTRL_PR_REMINDER_PAUSE",
"MGR_EVT_CTRL_PR_RESUME",
"MGR_EVT_CTRL_PR_DONE",
"MGR_EVT_CTRL_PR_RATE_CHANGED",
"MGR_EVT_CTRL_PR_CANT_START",
"MGR_EVT_CTRL_PR_PROP_CHANGED",
"MGR_EVT_CTRL_PARAM_CHANGE",
"MGR_EVT_CTRL_AUTO_CC_PARAM_CHANGE",
"MGR_EVT_CTRL_RECOVERY_FACTORY",
"MGR_EVT_CTRL_PROFILEID_CHANGED",
"MGR_EVT_CTRL_SANPSHOT_CREATE",
"MGR_EVT_CTRL_SANPSHOT_DELETE",
"MGR_EVT_CTRL_ENABLEPDM_CHANGED",
"MGR_EVT_CTRL_PDMSUPPORTREADYPD",
"MGR_EVT_CTRL_PDMTIMERINTERVAL",
"MGR_EVT_CTRL_SECURITY_KEY_CHANGE",
"MGR_EVT_CTRL_SECURITY_KEY_CREATE",
"MGR_EVT_CTRL_SECURITY_KEY_DESTROY",
"MGR_EVT_CTRL_SECURITY_KEY_ESCROW",
"MGR_EVT_CTRL_SECURITY_KEY_FAILED",
"MGR_EVT_CTRL_SECURITY_KEY_INVALID",
"MGR_EVT_AUTOCONFIG",
"MGR_EVT_CTRL_FOREIGN_IMPORTED_ALL",
"MGR_EVT_CTRL_FOREIGN_CLEAR",
"MGR_EVT_CTRL_FOREIGN_IMPORT_FAIL",
"MGR_EVT_CTRL_FOREIGN_IMPORT_PART_FAIL",
"MGR_EVT_CTRL_FOREIGN_IMPORT_FAIL_PDS",
"MGR_EVT_CTRL_FOREIGN_PD_DETECTED",
"MGR_EVT_PD_INSERT_TO_DG",
"MGR_EVT_PD_IMPORT_TO_DG",
"MGR_EVT_HARD_RESET",
"MGR_EVT_DPF_CFG_MODIFY",
"MGR_EVT_SPOR",
"MGR_EVT_ONF_ABNORMAL",
"MGR_EVT_CTRL_LOADED",
"MGR_EVT_CACHE_PROTECTION_CMPT_READY",
"MGR_EVT_CACHE_PROTECTION_CMPT_NOT_READY",
"MGR_EVT_CACHE_PROTECTION_CMPT_INSTABLE",
"MGR_EVT_MAIN_MEDIUM_NOT_AVAILABLE",
"MGR_EVT_BACKUP_MEDIUM_NOT_AVAILABLE",
"MGR_EVT_MEDIUM_DATA_RECOVER",
"MGR_EVT_INIT_FAIL",
"MGR_EVT_CTRL_POWER_MODE_CHANGED",
},
{
"MGR_EVT_PD_ATTR_START",
"MGR_EVT_PD_INFO_CHANGE",
"MGR_EVT_PD_STATE_CHANGE",
"MGR_EVT_PD_MARKED_JBOD",
"MGR_EVT_PD_MARKED_READY",
"MGR_EVT_PD_MARKED_ONLINE",
"MGR_EVT_PD_MARKED_OFFLINE",
"MGR_EVT_PD_MARKED_FAILED",
"MGR_EVT_PD_MARKED_MISSING",
"MGR_EVT_PD_MARKED_REBUILD",
"MGR_EVT_PD_MARKED_REPLACE",
"MGR_EVT_PD_MARKED_UNCONFIGUREDBAD",
"MGR_EVT_PD_MARKED_FOREIGN",
"MGR_EVT_PD_NR_GLOBAL_SPARE_ADDED",
"MGR_EVT_PD_NR_GLOBAL_SPARE_DELETED",
"MGR_EVT_PD_NR_DEDICATED_SPARE_ADDED",
"MGR_EVT_PD_NR_DEDICATED_SPARE_DELETED",
"MGR_EVT_PD_R_GLOBAL_SPARE_ADDED",
"MGR_EVT_PD_R_GLOBAL_SPARE_DELETED",
"MGR_EVT_PD_R_DEDICATED_SPARE_ADDED",
"MGR_EVT_PD_R_DEDICATED_SPARE_DELETED",
"MGR_EVT_PD_RBLD_ABORT_BY_USER",
"MGR_EVT_PD_RBLD_DONE_PD",
"MGR_EVT_PD_RBLD_FAILED_BAD_SOURCE",
"MGR_EVT_PD_RBLD_FAILED_BAD_TARGET",
"MGR_EVT_PD_RBLD_PROGRESS",
"MGR_EVT_PD_RBLD_SUSPENDED_REMINDER",
"MGR_EVT_PD_RBLD_SUSPENDED",
"MGR_EVT_PD_RBLD_RESUME",
"MGR_EVT_PD_RBLD_START",
"MGR_EVT_PD_RBLD_START_AUTO",
"MGR_EVT_PD_RBLD_MEDIUM_ERROR",
"MGR_EVT_PD_EMERGENCY_SPARE",
"MGR_EVT_PD_RECOVER_MEDIUM_ERROR",
"MGR_EVT_PD_MOVEBACK_START",
"MGR_EVT_PD_MOVEBACK_ABORT",
"MGR_EVT_PD_MOVEBACK_ABORT_FOR_REBUILD",
"MGR_EVT_PD_MOVEBACK_DONE",
"MGR_EVT_PD_MOVEBACK_PROGRESS",
"MGR_EVT_PD_MOVEBACK_SUSPENDED",
"MGR_EVT_PD_MOVEBACK_SUSPENDED_REMINDER",
"MGR_EVT_PD_MOVEBACK_RESUME",
"MGR_EVT_PD_MOVEBACK_START_AUTO",
"MGR_EVT_PD_MOVEBACK_FAILED_BAD_SOURCE",
"MGR_EVT_PD_MOVEBACK_FAILED_BAD_TARGET",
"MGR_EVT_PD_MOVEBACK_ABORT_BY_USER",
"MGR_EVT_PD_MOVEBACK_MEDIUM_ERROR",
"MGR_EVT_PD_FGI_START",
"MGR_EVT_PD_FGI_COMPLETE",
"MGR_EVT_PD_FGI_FAILED",
"MGR_EVT_PD_FGI_PROGRESS",
"MGR_EVT_PD_FGI_ABORT",
"MGR_EVT_PD_PR_ABORTED",
"MGR_EVT_PD_PR_CORRECTED",
"MGR_EVT_PD_PR_UNCORRECTABLE",
"MGR_EVT_PD_PR_FOUND_MEDIUM_ERROR",
"MGR_EVT_PD_PR_PROGRESS",
"MGR_EVT_PD_SET_BOOT_DRIVE",
"MGR_EVT_PD_RESET_BOOT_DRIVE",
"MGR_EVT_PD_RESET_BOOT_DRIVE_WITH_DISK_OUT",
"MGR_EVT_PD_SET_BOOT_DRIVE_WITH_DISK_IN",
"MGR_EVT_PD_POWERSAVE_TO_ON",
"MGR_EVT_PD_POWERSAVE_TO_TRANSITION",
"MGR_EVT_PD_TRANSITION_TO_ON",
"MGR_EVT_PD_TRANSITION_TO_POWERSAVE",
"MGR_EVT_PD_ON_TO_POWERSAVE",
"MGR_EVT_PD_START_LOCATE",
"MGR_EVT_PD_STOP_LOCATE",
"MGR_EVT_PD_PFA_ERROR",
"MGR_EVT_PD_NOT_PRESENT",
"MGR_EVT_DEVM_DISK_FAULT",
"MGR_EVT_PHY_FLASHOFFLINE",
"MGR_EVT_PHY_FLASHONLINE",
"MGR_EVT_NFR_DONE",
"MGR_EVT_NFR_REPAIRED",
"MGR_EVT_NFR_REPORT",
"MGR_EVT_NFR_STOP",
"MGR_EVT_PD_DOWNLOAD_DONE",
"MGR_EVT_PD_DOWNLOAD_START",
"MGR_EVT_NVME_PHY_BAD",
},
{
"MGR_EVT_VD_ATTR_START",
"MGR_EVT_MULITPILE_VD_STATE_CHANGE",
"MGR_EVT_VD_OFFLINE_OLD",
"MGR_EVT_VD_LOCK",
"MGR_EVT_VD_PASSWD_CHANGED",
"MGR_EVT_VD_SETTINGS_CHANGE",
"MGR_EVT_VD_PD_CHANGE",
"MGR_EVT_VD_STATE_CHANGE",
"MGR_EVT_PD_RBLD_DONE_LD",
"MGR_EVT_VD_FGI_START",
"MGR_EVT_VD_FGI_COMPLETE",
"MGR_EVT_VD_FGI_FAILED",
"MGR_EVT_VD_FGI_PROGRESS",
"MGR_EVT_VD_FGI_ABORT",
"MGR_EVT_VD_BGI_START",
"MGR_EVT_VD_BGI_COMPLETE",
"MGR_EVT_VD_BGI_FAILED",
"MGR_EVT_VD_BGI_PROGRESS",
"MGR_EVT_VD_BGI_ABORT",
"MGR_EVT_VD_BGI_PAUSE",
"MGR_EVT_VD_BGI_REMINDER_PAUSE",
"MGR_EVT_VD_BGI_RESUME",
"MGR_EVT_VD_BGI_CORRECTABLE_ERROR",
"MGR_EVT_VD_BGI_UNCORRECTABLE_ERROR",
"MGR_EVT_VD_ALTER_ATTR_BY_MIGRATION",
"MGR_EVT_VD_BBM_CLEARED",
"MGR_EVT_VD_BBM_PERCENT_FULL",
"MGR_EVT_VD_BBM_100_FULL",
"MGR_EVT_VD_BBM_LOG_FULL",
"MGR_EVT_VD_BBM_LOG_RCT",
"MGR_EVT_VD_BBM_LOG_WCT",
"MGR_EVT_VD_BBM_DEL_RCT",
"MGR_EVT_VD_CC_ABORTED",
"MGR_EVT_VD_CC_CORRECTED_MEDIUM_ERROR",
"MGR_EVT_VD_CC_DOUBLE_MEDIUM_ERRORS",
"MGR_EVT_VD_CC_DONE",
"MGR_EVT_VD_CC_DONE_INCON",
"MGR_EVT_VD_CC_FAILED",
"MGR_EVT_VD_CC_FAILED_UNCOR",
"MGR_EVT_VD_CC_INCONSISTENT_PARITY",
"MGR_EVT_VD_CC_INCONSISTENT_PARITY_LOGGING_DISABLED",
"MGR_EVT_VD_CC_PROGRESS",
"MGR_EVT_VD_CC_START",
"MGR_EVT_VD_CC_PAUSE",
"MGR_EVT_VD_CC_REMINDER_PAUSE",
"MGR_EVT_VD_CC_RESUME",
"MGR_EVT_VD_RW_RAID1X_WRITE_CARDBUSY",
"MGR_EVT_VD_SET_BOOT_DRIVE",
"MGR_EVT_VD_RESET_BOOT_DRIVE",
"MGR_EVT_VD_RESET_BOOT_DRIVE_WITH_DISK_OUT",
"MGR_EVT_VD_SET_BOOT_DRIVE_WITH_DISK_IN",
"MGR_EVT_ALL_CONFIGS_MISSING",
"MGR_EVT_PDS_MISSING",
"MGR_EVT_NVSRAM_RECOVER_FAIL",
"MGR_EVT_NVSRAM_UPDATE_FAIL",
"MGR_EVT_VD_ERASE_ABORT",
"MGR_EVT_VD_ERASE_COMPLETE",
"MGR_EVT_VD_ERASE_DISK_FAILED",
"MGR_EVT_VD_ERASE_FAILED",
"MGR_EVT_VD_ERASE_PROGRESS",
"MGR_EVT_VD_ERASE_START",
"MGR_EVT_VD_EXPAND_FINISH",
"MGR_EVT_VD_EXPAND_START",
"MGR_EVT_VD_FLUSH_CLEAR_FAILED",
"MGR_EVT_VD_FLUSH_RECORD_FAILED",
"MGR_EVT_VD_FLUSH_SET_INCONSIST",
"MGR_EVT_VDS_MISSING",
"MGR_EVT_VD_BBM_UNCORRECTABLE_LOGGED",
"MGR_EVT_VD_FLUSH_CACHE_PINNED",
"MGR_EVT_VD_FLUSH_OCR_CACHE_PINNED",
"MGR_EVT_VD_FLUSH_CACHE_DISCARDED",
"MGR_EVT_VD_FLUSH_CACHE_DISCARDED_DEL",
"MGR_EVT_VD_FLUSH_CACHE_DESTAGED",
"MGR_EVT_VD_CM_RECOVERY_CRC_FAIL",
"MGR_EVT_VD_BGI_COMPLETE_UNCOR",
},
{
"MGR_EVT_DG_INFO_START",
"MGR_EVT_DG_CREATED",
"MGR_EVT_DG_DELETED",
"MGR_EVT_DG_SETTING_CHANGE",
"MGR_EVT_DG_MIGRATION_START",
"MGR_EVT_DG_MIGRATION_RECOVER",
"MGR_EVT_DG_MIGRATION_SUCCESS",
"MGR_EVT_DG_MIGRATION_ALLOC_RESOURCE_FAILED",
"MGR_EVT_DG_MIGRATION_FAILED",
"MGR_EVT_DG_MIGRATION_RECOVER_FAILED",
"MGR_EVT_DG_MIGRATION_PROGRESS",
"MGR_EVT_DG_MIGRATION_INTERNAL_WARNING",
"MGR_EVT_DG_PRSWITCH_CHANGE",
"MGR_EVT_DG_PR_ABORTED_WM_FAILED",
"MGR_EVT_DG_PR_ABORTED_SPINUP_FAILED",
},
{
"MGR_EVT_BBU_START",
"MGR_EVT_BBU_PRESENT",
"MGR_EVT_BBU_NOT_PRESENT",
"MGR_EVT_BBU_GOOD",
"MGR_EVT_BBU_BAD",
"MGR_EVT_BBU_CAP_BELOW_THRESHOLD",
"MGR_EVT_BBU_CAP_ABOVE_THRESHOLD",
"MGR_EVT_BBU_CHARGE_STATUS",
"MGR_EVT_BBU_CHARGE_COMPLETE",
"MGR_EVT_BBU_INSERT",
"MGR_EVT_BBU_ABSENT",
"MGR_EVT_BBU_TEMPERATURE_NORMAL",
"MGR_EVT_BBU_TEMPERATURE_HIGH",
"MGR_EVT_BBU_VOLTAGE_NORMAL",
"MGR_EVT_BBU_VOLTAGE_HIGH",
"MGR_EVT_BBU_CURRENT_NORMAL",
"MGR_EVT_BBU_CURRENT_HIGH",
"MGR_EVT_BBU_LOAD_NORMAL",
"MGR_EVT_BBU_VOLTAGE_LOW",
"MGR_EVT_BBU_BATTERY_CAP_ABOVE_SOH_THRESHOLD",
"MGR_EVT_BBU_BATTERY_CAP_BELOW_SOH_THRESHOLD",
"MGR_EVT_BBU_LEARN_STAGE",
"MGR_EVT_BBU_LEARN_REQUESTED",
"MGR_EVT_BBU_LEARN_POSTPONED",
"MGR_EVT_BBU_LEARN_TIMEOUT",
"MGR_EVT_BBU_LEARN_MANUAL",
"MGR_EVT_BBU_LEARN_RESCHEDULED",
"MGR_EVT_BBU_PROPERTIES_CHANGED",
},
{
"MGR_EVT_CONFIG_START",
"MGR_EVT_CONFIG_INFO",
"MGR_EVT_CONFIG_FLASH_READ_FAIL",
"MGR_EVT_CONFIG_FLASH_WRITE_FAIL",
"MGR_EVT_CONFIG_NVSRAM_READ_FAIL",
"MGR_EVT_CONFIG_NVSRAM_WRITE_FAIL",
"MGR_EVT_CONFIG_VERSION_MISMATCH",
"MGR_EVT_CONFIG_MEDIA_VALUE_CHECK_FAIL",
"MGR_EVT_CONFIG_ERASE_NVSRAM",
"MGR_EVT_PHY_LINKSPEED_CFG_CHANGE",
},
{
"MGR_EVT_IO_START",
"MGR_EVT_IO_TEST",
"MGR_EVT_IO_SENSE_DATA",
"MGR_EVT_DEVICE_RESET",
"MGR_EVT_NVME_DEVICE_RESET",
"MGR_EVT_DEVICE_ABNORMAL",
"MGR_EVT_IO_SENSE",
},
{
"MGR_EVT_UKEY_START",
"MGR_EVT_UKEY_INSERT",
"MGR_EVT_UKEY_DEGRADE",
"MGR_EVT_RAID_KEY_OVERCURRENT",
"MGR_EVT_RAID_KEY_OVERCURRENT_RECOVER",
},
{
"MGR_EVT_HWR_START",
"MGR_EVT_HWR_HAC_RESET_BEGIN",
"MGR_EVT_HWR_HAC_RESET_END",
"MGR_EVT_REPORT_HAC_ECC",
},
{
"MGR_EVT_ALARM_START",
"MGR_EVT_ALARM_ENABLED",
"MGR_EVT_ALARM_DISABLED",
},
{
"MGR_EVT_ECC_START",
"MGR_EVT_ECC_CNT_EXCEED",
"MGR_EVT_ECC_ERR_INTR",
"MGR_EVT_ECC_CNT_CLEAR",
"MGR_EVT_ECC_CLI_CHANGE",
"MGR_EVT_ECC_FACTORY_CHANGE",
},
{
"MGR_EVT_UPGRADE_START",
"MGR_EVT_IMAGE_DOWNLOAD_ERROR",
"MGR_EVT_IMAGE_AUTHENTICATION_FAIL",
"MGR_EVT_IMAGE_VERSION_CHECK_FAIL",
"MGR_EVT_IMAGE_CHECKSUM_CHECK_FAIL",
"MGR_EVT_IMAGE_FROM_BACKUP",
"MGR_EVT_DEV_OPEN_ERROR",
"MGR_EVT_DEV_FLASH_ERROR",
"MGR_EVT_DEV_ERASE_ERROR",
"MGR_EVT_DEV_CLOSE_ERROR",
"MGR_EVT_FLASH_GENERAL_ERROR",
"MGR_EVT_FLASH_TIMEOUT",
"MGR_EVT_UPGRADE_SUCCESS",
"MGR_EVT_UPGRADE_SYNC_START",
"MGR_EVT_UPGRADE_SYNC_FAILED",
"MGR_EVT_UPGRADE_SYNC_SUCCESS",
},
{
"MGR_EVT_TEMP_START",
"MGR_EVT_TEMP_WITHIN_OPTIMAL_RANGE",
"MGR_EVT_TEMP_ABOVE_OPTIMAL_RANGE",
"MGR_EVT_TEMP_WARNING",
"MGR_EVT_TEMP_CRITICAL",
},
};
static const char *pEvtCodeExtInfo[PS3_EVT_EXT_NR][MGR_EVT_TYPE_EXTEND_OFFSET] = {
{
"MGR_EVT_PD_ATTR_EXTEND_START_START",
"MGR_EVT_PD_ERASE_ABORT",
"MGR_EVT_PD_ERASE_COMPLETE",
"MGR_EVT_PD_ERASE_FAILED",
"MGR_EVT_PD_ERASE_PROGRESS",
"MGR_EVT_PD_ERASE_START",
"MGR_EVT_PD_PDM_ABORT_BY_USER",
"MGR_EVT_PD_PDM_ABORT_FOR_REBUILD",
"MGR_EVT_PD_PDM_ABORT",
"MGR_EVT_PD_PDM_DONE",
"MGR_EVT_PD_PDM_FAILED_BAD_SOURCE",
"MGR_EVT_PD_PDM_FAILED_BAD_TARGET",
"MGR_EVT_PD_PDM_MEDIUM_ERROR",
"MGR_EVT_PD_PDM_PROGRESS",
"MGR_EVT_PD_PDM_REPLACED_SOURCE",
"MGR_EVT_PD_PDM_RESUME",
"MGR_EVT_PD_PDM_START_AUTO",
"MGR_EVT_PD_PDM_START",
"MGR_EVT_PD_PDM_SUSPENDED_REMINDER",
"MGR_EVT_PD_PDM_SUSPENDED",
"MGR_EVT_PD_PFA_ERROR_CLEAR",
"MGR_EVT_PD_SANITIZE_START",
"MGR_EVT_PD_FORMAT_START",
"MGR_EVT_PD_SANITIZE_PROGRESS",
"MGR_EVT_PD_SANITIZE_DONE",
"MGR_EVT_PD_FORMAT_DONE",
"MGR_EVT_PD_DPF_ERROR",
"MGR_EVT_PD_MARKED_SHIELD",
"MGR_EVT_PD_BBM_CORRECTED",
"MGR_EVT_PD_BBM_UNRECOVERABLE",
"MGR_EVT_PD_BBM_PUNCTURING",
"MGR_EVT_PD_BBM_REASSIGN_WR_ERROR",
"MGR_EVT_PD_UNABLE_ACCESS",
"MGR_EVT_MULITPILE_PD_UNABLE_ACCESS",
"MGR_EVT_PD_INSERT_FAIL",
"MGR_EVT_PHY_SATA_D2H_FAIL",
"MGR_EVT_PD_NOT_INSERTED",
"MGR_EVT_PD_NOT_SUPPORT",
"MGR_EVT_MULITPILE_PD_NOT_SUPPORT",
"MGR_EVT_NVDATA_INVALID",
"MGR_EVT_PD_RBLD_NON_UNMAP_PD",
"MGR_EVT_PD_MOVEBACK_NON_UNMAP_PD",
"MGR_EVT_PD_PDM_NON_UNMAP_PD",
"MGR_EVT_PD_RBLD_FAILED",
"MGR_EVT_PD_SANITIZE_FAILED",
"MGR_EVT_PD_SPIN_FAIL",
"MGR_EVT_PD_RBLD_MEDIA_MIX_NOT_SUPPORT",
"MGR_EVT_PD_RBLD_DRIVE_MIX_NOT_SUPPORT",
"MGR_EVT_PD_PDM_MEDIA_MIX_NOT_SUPPORT",
"MGR_EVT_PD_PDM_DRIVE_MIX_NOT_SUPPORT",
"MGR_EVT_PD_MOVEBACK_MEDIA_MIX_NOT_SUPPORT",
"MGR_EVT_PD_MOVEBACK_DRIVE_MIX_NOT_SUPPORT",
"MGR_EVT_NFR_FAILED",
"MGR_EVT_PD_RBLD_SMALL_SIZE",
"MGR_EVT_PD_MOVEBACK_SMALL_SIZE",
"MGR_EVT_NEGO_LOWER_LINK_SPEED",
"MGR_EVT_PD_NVME_CMD_ERR",
"MGR_EVT_PD_NVME_CMD_TO",
"MGR_EVT_PD_NVME_INSERT_FAIL",
"MGR_EVT_PCIE_LINK_NEGO_ABNORMAL",
"MGR_EVT_PD_ISOLATION",
"MGR_EVT_PD_REPAIR_FAILED",
"MGR_EVT_PD_PCIE_LINK_UP_WITHOUT_I2C",
"MGR_EVT_PD_PCIE_ENUMERATE_FAILED",
"MGR_EVT_PD_MISS_LIGHTING",
},
};
if (opCode >= ((MGR_EVT_EXTEND_TYPE_START - 1) * MGR_EVT_TYPE_OFFSET) +
(PS3_EVT_MAX_TYPE_LOCAL - MGR_EVT_EXTEND_TYPE_START)
* MGR_EVT_TYPE_EXTEND_OFFSET) {
goto end;
};
if (opCode < ((MGR_EVT_EXTEND_TYPE_START - 1) * MGR_EVT_TYPE_OFFSET)) {
typeIndex = opCode / MGR_EVT_TYPE_OFFSET;
codeIndex = opCode % MGR_EVT_TYPE_OFFSET;
pEvtTransStr = pEvtCodeInfo[typeIndex][codeIndex];
} else {
typeIndex = (opCode - ((MGR_EVT_EXTEND_TYPE_START - 1) * MGR_EVT_TYPE_OFFSET))
/ MGR_EVT_TYPE_EXTEND_OFFSET;
codeIndex = (opCode - ((MGR_EVT_EXTEND_TYPE_START - 1) * MGR_EVT_TYPE_OFFSET))
% MGR_EVT_TYPE_EXTEND_OFFSET;
pEvtTransStr = pEvtCodeExtInfo[typeIndex][codeIndex];
};
end:
return pEvtTransStr;
}
#else
static inline char const *mgrEvtCodeTrans(unsigned int opCode)
{
const char * const pEvtTransStr = NULL;
return pEvtTransStr;
}
#endif
#endif

View File

@ -0,0 +1,87 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef __PS3_HTP_DEV_INFO_H__
#define __PS3_HTP_DEV_INFO_H__
enum DriverType {
DRIVER_TYPE_UNKNOWN = 0,
DRIVER_TYPE_SAS,
DRIVER_TYPE_SATA,
DRIVER_TYPE_SES,
DRIVER_TYPE_NVME,
DRIVER_TYPE_EXP_SAS,
DRIVER_TYPE_VEP,
DRIVER_TYPE_CHASSIS,
DRIVER_TYPE_BACKPLANE,
DRIVER_TYPE_MAX,
};
static inline const char *getDriverTypeName(enum DriverType driverType)
{
static const char * const driverTypeName[] = {
[DRIVER_TYPE_UNKNOWN] = "DRIVER_TYPE_UNKNOWN",
[DRIVER_TYPE_SAS] = "DRIVER_TYPE_SAS",
[DRIVER_TYPE_SATA] = "DRIVER_TYPE_SATA",
[DRIVER_TYPE_SES] = "DRIVER_TYPE_SES",
[DRIVER_TYPE_NVME] = "DRIVER_TYPE_NVME",
[DRIVER_TYPE_EXP_SAS] = "DRIVER_TYPE_EXP_SAS",
[DRIVER_TYPE_VEP] = "DRIVER_TYPE_VEP",
[DRIVER_TYPE_CHASSIS] = "DRIVER_TYPE_CHASSIS",
[DRIVER_TYPE_BACKPLANE] = "DRIVER_TYPE_BACKPLANE",
[DRIVER_TYPE_MAX] = "DRIVER_TYPE_MAX",
};
return driverTypeName[driverType];
}
enum MediumType {
DEVICE_TYPE_UNKNOWN = 0,
DEVICE_TYPE_HDD,
DEVICE_TYPE_SSD,
DEVICE_TYPE_ENCLOSURE,
DEVICE_TYPE_MAX,
};
static inline const char *getMediumTypeName(enum MediumType mediumType)
{
static const char * const mediumTypeName[] = {
[DEVICE_TYPE_UNKNOWN] = "DEVICE_TYPE_UNKNOWN",
[DEVICE_TYPE_HDD] = "DEVICE_TYPE_HDD",
[DEVICE_TYPE_SSD] = "DEVICE_TYPE_SSD",
[DEVICE_TYPE_ENCLOSURE] = "DEVICE_TYPE_ENCLOSURE",
[DEVICE_TYPE_MAX] = "DEVICE_TYPE_MAX",
};
return mediumTypeName[mediumType];
}
enum DeviceState {
DEVICE_STATE_FREE = 0x0,
DEVICE_STATE_INSERTING,
DEVICE_STATE_ONLINE,
DEVICE_STATE_WAIT,
DEVICE_STATE_RECOVER,
DEVICE_STATE_PREONLINE,
DEVICE_STATE_OUTING,
DEVICE_STATE_MAX,
};
static inline const char *getDeviceStateName(enum DeviceState pdState)
{
static const char * const pdStateName[] = {
[DEVICE_STATE_FREE] = "DEVICE_STATE_FREE",
[DEVICE_STATE_INSERTING] = "DEVICE_STATE_INSERTING",
[DEVICE_STATE_ONLINE] = "DEVICE_STATE_ONLINE",
[DEVICE_STATE_WAIT] = "DEVICE_STATE_WAIT",
[DEVICE_STATE_RECOVER] = "DEVICE_STATE_RECOVER",
[DEVICE_STATE_PREONLINE] = "DEVICE_STATE_PREONLINE",
[DEVICE_STATE_OUTING] = "DEVICE_STATE_OUTING",
[DEVICE_STATE_MAX] = "DEVICE_STATE_MAX",
};
return pdStateName[pdState];
}
#endif

View File

@ -0,0 +1,126 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef __PS3_HTP_META_H__
#define __PS3_HTP_META_H__
enum MicPdState {
MIC_PD_STATE_UNKNOWN = 0,
MIC_PD_STATE_READY = 1,
MIC_PD_STATE_UBAD = 2,
MIC_PD_STATE_DSPARE = 3,
MIC_PD_STATE_GSPARE = 4,
MIC_PD_STATE_OFFLINE = 5,
MIC_PD_STATE_ONLINE = 6,
MIC_PD_STATE_MISSING = 7,
MIC_PD_STATE_FAILED = 8,
MIC_PD_STATE_REBUILD = 9,
MIC_PD_STATE_REPLACE = 10,
MIC_PD_STATE_FOREIGN = 11,
MIC_PD_STATE_JBOD = 12,
MIC_PD_STATE_UNSUPPORT = 13,
MIC_PD_STATE_PDM = 14,
MIC_PD_STATE_CFSHLD = 15,
MIC_PD_STATE_HSPSHLD = 16,
MIC_PD_STATE_RUNSP = 17,
MIC_PD_STATE_UBUNSP = 18,
MIC_PD_STATE_MAX
};
static inline const char *getPdStateName(enum MicPdState pdSate,
unsigned char isRaid)
{
static const char * const raidPdName[] = {
[MIC_PD_STATE_UNKNOWN] = "UNKNOWN",
[MIC_PD_STATE_READY] = "UGOOD",
[MIC_PD_STATE_UBAD] = "UBAD",
[MIC_PD_STATE_DSPARE] = "DSPARE",
[MIC_PD_STATE_GSPARE] = "GSPARE",
[MIC_PD_STATE_OFFLINE] = "OFFLINE",
[MIC_PD_STATE_ONLINE] = "ONLINE",
[MIC_PD_STATE_MISSING] = "MISSING",
[MIC_PD_STATE_FAILED] = "FAILED",
[MIC_PD_STATE_REBUILD] = "REBUILD",
[MIC_PD_STATE_REPLACE] = "REPLACE",
[MIC_PD_STATE_FOREIGN] = "FOREIGN",
[MIC_PD_STATE_JBOD] = "JBOD",
[MIC_PD_STATE_UNSUPPORT] = "UNSUPPORT",
[MIC_PD_STATE_PDM] = "PDM",
[MIC_PD_STATE_CFSHLD] = "CFSHLD",
[MIC_PD_STATE_HSPSHLD] = "HSPSHLD",
[MIC_PD_STATE_RUNSP] = "UGUNSP",
[MIC_PD_STATE_UBUNSP] = "UBUNSP",
};
static const char * const hbaPdName[] = {
[MIC_PD_STATE_UNKNOWN] = "UNKNOWN",
[MIC_PD_STATE_READY] = "READY",
[MIC_PD_STATE_UBAD] = "UBAD",
[MIC_PD_STATE_DSPARE] = "DSPARE",
[MIC_PD_STATE_GSPARE] = "GSPARE",
[MIC_PD_STATE_OFFLINE] = "OFFLINE",
[MIC_PD_STATE_ONLINE] = "ONLINE",
[MIC_PD_STATE_MISSING] = "MISSING",
[MIC_PD_STATE_FAILED] = "FAILED",
[MIC_PD_STATE_REBUILD] = "REBUILD",
[MIC_PD_STATE_REPLACE] = "REPLACE",
[MIC_PD_STATE_FOREIGN] = "FOREIGN",
[MIC_PD_STATE_JBOD] = "JBOD",
[MIC_PD_STATE_UNSUPPORT] = "UNSUPPORT",
[MIC_PD_STATE_PDM] = "PDM",
[MIC_PD_STATE_CFSHLD] = "CFSHLD",
[MIC_PD_STATE_HSPSHLD] = "HSPSHLD",
[MIC_PD_STATE_RUNSP] = "RUNSP",
[MIC_PD_STATE_UBUNSP] = "UBUNSP",
};
if (isRaid)
return raidPdName[pdSate];
else
return hbaPdName[pdSate];
}
enum MicVdState {
MIC_VD_STATE_UNKNOWN = 0,
MIC_VD_STATE_OFFLINE,
MIC_VD_STATE_OPTIMAL,
MIC_VD_STATE_PARTIAL_DEGRADE,
MIC_VD_STATE_DEGRADE
};
static inline const char *getVdStateName(enum MicVdState vdSate)
{
static const char * const vdStateName[] = { [MIC_VD_STATE_UNKNOWN] = "UNKNOWN",
[MIC_VD_STATE_OFFLINE] = "OFFLINE",
[MIC_VD_STATE_OPTIMAL] = "OPTIMAL",
[MIC_VD_STATE_PARTIAL_DEGRADE] =
"PARTIALLY DEGRADED",
[MIC_VD_STATE_DEGRADE] =
"DEGRADED" };
return vdStateName[vdSate];
}
enum RaidLevel {
RAID0 = 0x00,
RAID1 = 0x01,
RAID5 = 0x05,
RAID6 = 0x06,
JBOD = 0x0A,
RAID10 = 0x10,
RAID1E = 0x11,
RAID00 = 0x20,
RAID50 = 0x50,
RAID60 = 0x60,
RAID_UNKNOWN = 0xFF
};
enum VDAccessPolicy {
VD_ACCESS_POLICY_READ_WRITE = 0,
VD_ACCESS_POLICY_READ_ONLY,
VD_ACCESS_POLICY_BLOCK,
VD_ACCESS_POLICY_REMOVE_ACCESS
};
#endif

View File

@ -0,0 +1,15 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef __PS3_HTP_MGR_EVT_H__
#define __PS3_HTP_MGR_EVT_H__
#include "ps3_htp_mgr_evt_raidhba.h"
struct PS3EventFilter {
unsigned char eventType;
unsigned char eventCodeCnt;
unsigned char reserved[6];
unsigned short eventCodeTable[0];
};
#endif

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,189 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef __PS3_HTP_NVME_SPEC_H__
#define __PS3_HTP_NVME_SPEC_H__
enum NvmeGenCmdSC {
NVME_SC_SUCCESS = 0x00,
NVME_SC_INVALID_OPCODE = 0x01,
NVME_SC_INVALID_FIELD = 0x02,
NVME_SC_COMMAND_ID_CONFLICT = 0x03,
NVME_SC_DATA_TRANSFER_ERROR = 0x04,
NVME_SC_ABORTED_POWER_LOSS = 0x05,
NVME_SC_INTERNAL_DEVICE_ERROR = 0x06,
NVME_SC_ABORTED_BY_REQUEST = 0x07,
NVME_SC_ABORTED_SQ_DELETION = 0x08,
NVME_SC_ABORTED_FAILED_FUSED = 0x09,
NVME_SC_ABORTED_MISSING_FUSED = 0x0a,
NVME_SC_INVALID_NAMESPACE_OR_FORMAT = 0x0b,
NVME_SC_COMMAND_SEQUENCE_ERROR = 0x0c,
NVME_SC_INVALID_SGL_SEG_DESCRIPTOR = 0x0d,
NVME_SC_INVALID_NUM_SGL_DESCIRPTORS = 0x0e,
NVME_SC_DATA_SGL_LENGTH_INVALID = 0x0f,
NVME_SC_METADATA_SGL_LENGTH_INVALID = 0x10,
NVME_SC_SGL_DESCRIPTOR_TYPE_INVALID = 0x11,
NVME_SC_INVALID_CONTROLLER_MEM_BUF = 0x12,
NVME_SC_INVALID_PRP_OFFSET = 0x13,
NVME_SC_ATOMIC_WRITE_UNIT_EXCEEDED = 0x14,
NVME_SC_OPERATION_DENIED = 0x15,
NVME_SC_INVALID_SGL_OFFSET = 0x16,
NVME_SC_HOSTID_INCONSISTENT_FORMAT = 0x18,
NVME_SC_KEEP_ALIVE_EXPIRED = 0x19,
NVME_SC_KEEP_ALIVE_INVALID = 0x1a,
NVME_SC_ABORTED_PREEMPT = 0x1b,
NVME_SC_SANITIZE_FAILED = 0x1c,
NVME_SC_SANITIZE_IN_PROGRESS = 0x1d,
NVME_SC_SGL_DATA_BLOCK_GRANULARITY_INVALID = 0x1e,
NVME_SC_COMMAND_INVALID_IN_CMB = 0x1f,
NVME_SC_NAMESPACE_IS_WRITE_PROTECTED = 0x20,
NVME_SC_COMMAND_INTERRUPTED = 0x21,
NVME_SC_TRANSIENT_TRANSPORT_ERROR = 0x22,
NVME_SC_LBA_OUT_OF_RANGE = 0x80,
NVME_SC_CAPACITY_EXCEEDED = 0x81,
NVME_SC_NAMESPACE_NOT_READY = 0x82,
NVME_SC_RESERVATION_CONFLICT = 0x83,
NVME_SC_FORMAT_IN_PROGRESS = 0x84,
};
enum NvmeCmdSpecSC {
NVME_CSC_COMPLETION_QUEUE_INVALID = 0x00,
NVME_CSC_INVALID_QUEUE_IDENTIFIER = 0x01,
NVME_CSC_MAXIMUM_QUEUE_SIZE_EXCEEDED = 0x02,
NVME_CSC_ABORT_COMMAND_LIMIT_EXCEEDED = 0x03,
NVME_CSC_ASYNC_EVENT_REQUEST_LIMIT_EXCEEDED = 0x05,
NVME_CSC_INVALID_FIRMWARE_SLOT = 0x06,
NVME_CSC_INVALID_FIRMWARE_IMAGE = 0x07,
NVME_CSC_INVALID_INTERRUPT_VECTOR = 0x08,
NVME_CSC_INVALID_LOG_PAGE = 0x09,
NVME_CSC_INVALID_FORMAT = 0x0a,
NVME_CSC_FIRMWARE_REQ_CONVENTIONAL_RESET = 0x0b,
NVME_CSC_INVALID_QUEUE_DELETION = 0x0c,
NVME_CSC_FEATURE_ID_NOT_SAVEABLE = 0x0d,
NVME_CSC_FEATURE_NOT_CHANGEABLE = 0x0e,
NVME_CSC_FEATURE_NOT_NAMESPACE_SPECIFIC = 0x0f,
NVME_CSC_FIRMWARE_REQ_NVM_RESET = 0x10,
NVME_CSC_FIRMWARE_REQ_RESET = 0x11,
NVME_CSC_FIRMWARE_REQ_MAX_TIME_VIOLATION = 0x12,
NVME_CSC_FIRMWARE_ACTIVATION_PROHIBITED = 0x13,
NVME_CSC_OVERLAPPING_RANGE = 0x14,
NVME_CSC_NAMESPACE_INSUFFICIENT_CAPACITY = 0x15,
NVME_CSC_NAMESPACE_ID_UNAVAILABLE = 0x16,
NVME_CSC_NAMESPACE_ALREADY_ATTACHED = 0x18,
NVME_CSC_NAMESPACE_IS_PRIVATE = 0x19,
NVME_CSC_NAMESPACE_NOT_ATTACHED = 0x1a,
NVME_CSC_THINPROVISIONING_NOT_SUPPORTED = 0x1b,
NVME_CSC_CONTROLLER_LIST_INVALID = 0x1c,
NVME_CSC_DEVICE_SELF_TEST_IN_PROGRESS = 0x1d,
NVME_CSC_BOOT_PARTITION_WRITE_PROHIBITED = 0x1e,
NVME_CSC_INVALID_CTRLR_ID = 0x1f,
NVME_CSC_INVALID_SECONDARY_CTRLR_STATE = 0x20,
NVME_CSC_INVALID_NUM_CTRLR_RESOURCES = 0x21,
NVME_CSC_INVALID_RESOURCE_ID = 0x22,
NVME_CSC_CONFLICTING_ATTRIBUTES = 0x80,
NVME_CSC_INVALID_PROTECTION_INFO = 0x81,
NVME_CSC_ATTEMPTED_WRITE_TO_RO_RANGE = 0x82,
};
enum NvmeMediaErrSC {
NVME_MSC_WRITE_FAULTS = 0x80,
NVME_MSC_UNRECOVERED_READ_ERROR = 0x81,
NVME_MSC_GUARD_CHECK_ERROR = 0x82,
NVME_MSC_APPLICATION_TAG_CHECK_ERROR = 0x83,
NVME_MSC_REFERENCE_TAG_CHECK_ERROR = 0x84,
NVME_MSC_COMPARE_FAILURE = 0x85,
NVME_MSC_ACCESS_DENIED = 0x86,
NVME_MSC_DEALLOCATED_OR_UNWRITTEN_BLOCK = 0x87,
};
enum NvmeStatusCodes {
NVME_SUCCESS = 0x0000,
NVME_INVALID_OPCODE = 0x0001,
NVME_INVALID_FIELD = 0x0002,
NVME_CID_CONFLICT = 0x0003,
NVME_DATA_TRAS_ERROR = 0x0004,
NVME_POWER_LOSS_ABORT = 0x0005,
NVME_INTERNAL_DEV_ERROR = 0x0006,
NVME_CMD_ABORT_REQ = 0x0007,
NVME_CMD_ABORT_SQ_DEL = 0x0008,
NVME_CMD_ABORT_FAILED_FUSE = 0x0009,
NVME_CMD_ABORT_MISSING_FUSE = 0x000a,
NVME_INVALID_NSID = 0x000b,
NVME_CMD_SEQ_ERROR = 0x000c,
NVME_INVALID_SGL_SEG_DESCR = 0x000d,
NVME_INVALID_NUM_SGL_DESCRS = 0x000e,
NVME_DATA_SGL_LEN_INVALID = 0x000f,
NVME_MD_SGL_LEN_INVALID = 0x0010,
NVME_SGL_DESCR_TYPE_INVALID = 0x0011,
NVME_INVALID_USE_OF_CMB = 0x0012,
NVME_INVALID_PRP_OFFSET = 0x0013,
NVME_CMD_SET_CMB_REJECTED = 0x002b,
NVME_INVALID_CMD_SET = 0x002c,
NVME_LBA_RANGE = 0x0080,
NVME_CAP_EXCEEDED = 0x0081,
NVME_NS_NOT_READY = 0x0082,
NVME_NS_RESV_CONFLICT = 0x0083,
NVME_FORMAT_IN_PROGRESS = 0x0084,
NVME_INVALID_CQID = 0x0100,
NVME_INVALID_QID = 0x0101,
NVME_MAX_QSIZE_EXCEEDED = 0x0102,
NVME_ACL_EXCEEDED = 0x0103,
NVME_RESERVED = 0x0104,
NVME_AER_LIMIT_EXCEEDED = 0x0105,
NVME_INVALID_FW_SLOT = 0x0106,
NVME_INVALID_FW_IMAGE = 0x0107,
NVME_INVALID_IRQ_VECTOR = 0x0108,
NVME_INVALID_LOG_ID = 0x0109,
NVME_INVALID_FORMAT = 0x010a,
NVME_FW_REQ_RESET = 0x010b,
NVME_INVALID_QUEUE_DEL = 0x010c,
NVME_FID_NOT_SAVEABLE = 0x010d,
NVME_FEAT_NOT_CHANGEABLE = 0x010e,
NVME_FEAT_NOT_NS_SPEC = 0x010f,
NVME_FW_REQ_SUSYSTEM_RESET = 0x0110,
NVME_NS_ALREADY_ATTACHED = 0x0118,
NVME_NS_PRIVATE = 0x0119,
NVME_NS_NOT_ATTACHED = 0x011A,
NVME_NS_CTRL_LIST_INVALID = 0x011C,
NVME_CONFLICTING_ATTRS = 0x0180,
NVME_INVALID_PROT_INFO = 0x0181,
NVME_WRITE_TO_RO = 0x0182,
NVME_CMD_SIZE_LIMIT = 0x0183,
NVME_ZONE_BOUNDARY_ERROR = 0x01b8,
NVME_ZONE_FULL = 0x01b9,
NVME_ZONE_READ_ONLY = 0x01ba,
NVME_ZONE_OFFLINE = 0x01bb,
NVME_ZONE_INVALID_WRITE = 0x01bc,
NVME_ZONE_TOO_MANY_ACTIVE = 0x01bd,
NVME_ZONE_TOO_MANY_OPEN = 0x01be,
NVME_ZONE_INVAL_TRANSITION = 0x01bf,
NVME_WRITE_FAULT = 0x0280,
NVME_UNRECOVERED_READ = 0x0281,
NVME_E2E_GUARD_ERROR = 0x0282,
NVME_E2E_APP_ERROR = 0x0283,
NVME_E2E_REF_ERROR = 0x0284,
NVME_CMP_FAILURE = 0x0285,
NVME_ACCESS_DENIED = 0x0286,
NVME_DULB = 0x0287,
NVME_MORE = 0x2000,
NVME_DNR = 0x4000,
NVME_NO_COMPLETE = 0xffff,
};
enum NvmeStatusCodeType {
NVME_SCT_GENERIC = 0x0,
NVME_SCT_COMMAND_SPECIFIC = 0x1,
NVME_SCT_MEDIA_ERROR = 0x2,
NVME_SCT_PATH = 0x3,
NVME_SCT_VENDOR_SPECIFIC = 0x7,
};
#endif

View File

@ -0,0 +1,40 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef __PS3_HTP_REGISTER_FIFO_H__
#define __PS3_HTP_REGISTER_FIFO_H__
#include "hwapi/include_v200/s1861_regs/s1861_global_baseaddr.h"
#include "hwapi/include_v200/s1861_regs/s1861_hil_reg0_ps3_request_queue_reg.h"
#include "hwapi/include_v200/s1861_regs/s1861_hil_reg0_ps3_register_f_reg.h"
#include "hwapi/include_v200/s1861_regs/s1861_hil_reg0_ps3_register_s_reg.h"
#ifdef __cplusplus
extern "C" {
#endif
union ps3RequestFifo {
unsigned char reserved0[HIL_REG0_PS3_REQUEST_QUEUE_SIZE];
struct HilReg0Ps3RequestQueue request_fifo;
};
union ps3RegShare {
unsigned char reserved0[HIL_REG0_PS3_REGISTER_S_SIZE];
struct HilReg0Ps3RegisterS share_reg;
};
union ps3RegExclusive {
unsigned char reserved0[HIL_REG0_PS3_REGISTER_F_SIZE];
struct HilReg0Ps3RegisterF Excl_reg;
};
struct Ps3Fifo {
union ps3RegExclusive reg_f;
union ps3RequestFifo cmd_fifo;
union ps3RegShare reg_s;
};
#ifdef __cplusplus
}
#endif
#endif

View File

@ -0,0 +1,20 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef __PS3_HTP_TRACE_ID_H__
#define __PS3_HTP_TRACE_ID_H__
#define TRACE_ID_CHIP_OUT_COUNT_MASK 0x000FFFFFFFFFFFFFLLU
#define TRACE_ID_CHIP_OUT_CPUID_SHIFT 52
#define TRACE_ID_CHIP_OUT_CPUID_MASK 0x7FFLLU
static inline void traceIdCpuIdSet(unsigned long long *traceId,
unsigned short cpuId)
{
*traceId &= ~(TRACE_ID_CHIP_OUT_CPUID_MASK
<< TRACE_ID_CHIP_OUT_CPUID_SHIFT);
*traceId |= ((unsigned long long)cpuId & TRACE_ID_CHIP_OUT_CPUID_MASK)
<< TRACE_ID_CHIP_OUT_CPUID_SHIFT;
}
#endif

View File

@ -0,0 +1,85 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef __PS3_MGR_EVT_COMMON_H__
#define __PS3_MGR_EVT_COMMON_H__
#define MGR_EVT_TYPE_OFFSET (80)
#define MGR_EVT_LOG_INFO_MAX_SIZE (116)
#if !(defined(PS3_PRODUCT_EXPANDER) || defined(PS3_PRODUCT_SWITCH))
#define MGR_EVT_TYPE_EXTEND_OFFSET (200)
#define MGR_EVT_EXTEND_TYPE_START (17)
#define MGR_EVT_TYPE_BASE_LOCAL(sn) (sn < MGR_EVT_EXTEND_TYPE_START ? \
(sn - 1) * MGR_EVT_TYPE_OFFSET : \
MGR_EVT_TYPE_OFFSET * (MGR_EVT_EXTEND_TYPE_START - 1) \
+ MGR_EVT_TYPE_EXTEND_OFFSET * (sn - MGR_EVT_EXTEND_TYPE_START))
#define MGR_EVENT_CODE_2_TYPE(code) \
(code <= MGR_EVT_TYPE_OFFSET * (MGR_EVT_EXTEND_TYPE_START - 1) ? \
((code) / MGR_EVT_TYPE_OFFSET + 1) : \
(code - MGR_EVT_TYPE_OFFSET * (MGR_EVT_EXTEND_TYPE_START - 1)) / \
MGR_EVT_TYPE_EXTEND_OFFSET + MGR_EVT_EXTEND_TYPE_START)
#else
#define MGR_EVT_TYPE_BASE_LOCAL(sn) ((sn - 1) * MGR_EVT_TYPE_OFFSET)
#define MGR_EVENT_CODE_2_TYPE(code) ((code) / MGR_EVT_TYPE_OFFSET + 1)
#endif
#define PS3_EVT_TYPE_OFFSET (30)
#define PS3_EVT_EXPOSE_OFFSET (28)
#define PS3_EVT_BATCH_OFFSET (27)
#define PS3_EVT_ATTR_OFFSET (16)
#define PS3_EVT_LEVEL_OFFSET (12)
#define PS3_EVT_CODE_OFFSET (0)
#define PS3_MAKE_EVT_CODE(type, expose, batch, attr, level, code) \
((((type)&0b11) << PS3_EVT_TYPE_OFFSET) | \
(((expose)&0b11) << PS3_EVT_EXPOSE_OFFSET) | \
(((batch)&0b1) << PS3_EVT_BATCH_OFFSET) | \
(((attr)&0x3F) << PS3_EVT_ATTR_OFFSET) | \
(((level)&0xF) << PS3_EVT_LEVEL_OFFSET) | \
((code)&0xFFF) << PS3_EVT_CODE_OFFSET)
#define PS3_MK_EVT(type, expose, batch, attr, level, code) \
(PS3_MAKE_EVT_CODE(type, expose, batch, attr, level, code))
#define PS3_EVT_TYPE(evtcode) ((evtcode >> PS3_EVT_TYPE_OFFSET) & 0b11)
#define PS3_EVT_EXPOSE(evtcode) ((evtcode >> PS3_EVT_EXPOSE_OFFSET) & 0b11)
#define PS3_EVT_IS_BATCH(evtcode) ((evtcode >> PS3_EVT_BATCH_OFFSET) & 0b1)
#define PS3_EVT_ATTR_EXTEND(evtcode) ((U8)((evtcode >> PS3_EVT_ATTR_OFFSET) & 0x3F))
#define PS3_EVT_LEVEL(evtcode) ((evtcode >> PS3_EVT_LEVEL_OFFSET) & 0xF)
#define PS3_EVT_CODE(evtcode) (((unsigned int)evtcode >> PS3_EVT_CODE_OFFSET) & 0xFFF)
enum Ps3EventType {
PS3_EVT_TYPE_UNKNOWN = 0b0000,
PS3_EVT_TYPE_RAIDHBA = 0b0001,
PS3_EVT_TYPE_EXPANDER = 0b0010,
PS3_EVT_TYPE_PCIESWITCH = 0b0011
};
enum Ps3EventExpose {
PS3_EVT_EXP_UNKNOWN = 0b0000,
PS3_EVT_EXP_EXTERNAL = 0b0001,
PS3_EVT_EXP_INTERNAL = 0b0010,
PS3_EVT_EXP_MAX = 0b0011
};
enum MgrEventLevel {
PS3_EVT_CLASS_UNKNOWN = 0b0000,
PS3_EVT_CLASS_DEBUG = 0b0011,
PS3_EVT_CLASS_PROCESS = 0b0101,
PS3_EVT_CLASS_INFO = 0b0001,
PS3_EVT_CLASS_WARNING = 0b0010,
PS3_EVT_CLASS_CRITICAL = 0b0100,
PS3_EVT_CLASS_FATAL = 0b1000,
PS3_EVT_CLASS_MAX
};
enum MgrEventIsBatch {
PS3_EVT_IS_BATCH_FALSE = 0b0,
PS3_EVT_IS_BATCH_TRUE = 0b1,
};
#endif

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,334 @@
// SPDX-License-Identifier: GPL-2.0
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/errno.h>
#include <linux/miscdevice.h>
#include <linux/types.h>
#include <linux/uaccess.h>
#include <linux/list.h>
#include <linux/mutex.h>
#include <linux/slab.h>
#include <linux/string.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/version.h>
#include "ps3_cli.h"
#include "ps3_instance_manager.h"
#include "ps3_kernel_version.h"
#include "ps3_util.h"
#define PS3_CLI_STATIC_MINOR 26
#define PS3_CLI_DYNAMIC_MINOR MISC_DYNAMIC_MINOR
#define PS3_CLI_HASH_LEN 256
struct ps3_cli_cmd_s {
struct ps3_cli_cmd_s *next;
char cmd[PS3_CLI_CMD_MAXLEN];
char help[PS3_CLI_HELP_LEN];
void (*func)(int argc, char *argv[]);
};
static int misc_registered;
static atomic_t dev_opened;
static int cmd_ready;
static char ps3_cli_input[PS3_CLI_INPUT_LEN];
static char ps3_cli_output[PS3_CLI_OUTLINE_LEN];
static char __user *read_buf;
static int read_buf_len;
static int read_buf_ptr;
static struct ps3_cli_cmd_s *ps3_cli_cmd_head[PS3_CLI_HASH_LEN];
static struct mutex ps3_cli_mutex;
#define __pl()
static inline int ps3_cli_minor_get(void)
{
if (strstr(ps3_host_release_get(), "5.10.134-16.2.an8"))
return PS3_CLI_DYNAMIC_MINOR;
#if defined(PS3_STATIC_MINOR)
return PS3_CLI_STATIC_MINOR;
#else
return PS3_CLI_DYNAMIC_MINOR;
#endif
}
static ssize_t ps3_cli_write(struct file *fp, const char __user *buffer,
size_t nbytes, loff_t *ppos)
{
__pl();
(void)fp;
(void)ppos;
if (nbytes > PS3_CLI_INPUT_LEN - 1)
return -EINVAL;
if (copy_from_user(ps3_cli_input, buffer, nbytes))
return -EFAULT;
ps3_cli_input[nbytes] = '\0';
cmd_ready = 1;
__pl();
return (ssize_t)nbytes;
}
static u32 str_hash(const char *name)
{
u32 hash, hash0 = 0x12a3fe2d, hash1 = 0x37abe8f9;
const signed char *scp = (const signed char *)name;
while (*scp) {
hash = hash1 + (hash0 ^ (((int)*scp++) * 7152373));
if (hash & 0x80000000)
hash -= 0x7fffffff;
hash1 = hash0;
hash0 = hash;
}
return hash0 << 1;
}
static struct ps3_cli_cmd_s *ps3_cli_find_cmd(const char *cmd)
{
u32 idx = str_hash(cmd) & (PS3_CLI_HASH_LEN - 1);
struct ps3_cli_cmd_s *p;
for (p = ps3_cli_cmd_head[idx]; p; p = p->next)
if (!strcmp(p->cmd, cmd))
return p;
return NULL;
}
int ps3stor_cli_printf(const char *fmt, ...)
{
va_list args;
int len, n, ret;
__pl();
va_start(args, fmt);
len = vsnprintf(ps3_cli_output, PS3_CLI_OUTLINE_LEN, fmt, args);
va_end(args);
if (read_buf_ptr >= read_buf_len)
return read_buf_ptr;
n = read_buf_len - read_buf_ptr;
if (n > len)
n = len;
ret = copy_to_user(read_buf + read_buf_ptr, ps3_cli_output, n);
if (ret < 0) {
pr_err("copy_to_user err=%d\n", ret);
return -1;
}
read_buf_ptr += n;
__pl();
return len;
}
EXPORT_SYMBOL(ps3stor_cli_printf);
int ps3stor_cli_register(void (*func)(int argc, char *argv[]), const char *cmd_str,
const char *help)
{
u32 idx = str_hash(cmd_str) & (PS3_CLI_HASH_LEN - 1);
struct ps3_cli_cmd_s *cmd;
int ret;
__pl();
ret = mutex_lock_killable(&ps3_cli_mutex);
if (ret != 0) {
pr_err("%s(): mutex_lock_killable return err = %d\n",
__func__, ret);
return ret;
}
cmd = ps3_cli_find_cmd(cmd_str);
if (cmd) {
pr_err("cmd=['%s'] has already been registered\n", cmd_str);
mutex_unlock(&ps3_cli_mutex);
return -EEXIST;
}
cmd = kmalloc(sizeof(struct ps3_cli_cmd_s), GFP_KERNEL);
if (cmd == NULL) {
mutex_unlock(&ps3_cli_mutex);
return -ENOMEM;
}
memset(cmd, 0, sizeof(struct ps3_cli_cmd_s));
PS3_STRCPY(cmd->cmd, cmd_str, PS3_CLI_CMD_MAXLEN - 1);
PS3_STRCPY(cmd->help, help, PS3_CLI_HELP_LEN - 1);
cmd->func = func;
cmd->next = ps3_cli_cmd_head[idx];
ps3_cli_cmd_head[idx] = cmd;
mutex_unlock(&ps3_cli_mutex);
__pl();
return 0;
}
EXPORT_SYMBOL(ps3stor_cli_register);
static void ps3_parse_cmd(char *cmdline, int *argc, char *argv[])
{
char *p = cmdline;
int i = 0, spc = 1;
while (*p) {
if (spc) {
if (*p != ' ') {
spc = 0;
argv[i] = p;
i++;
} else {
*p = '\0';
}
} else {
if (*p == ' ') {
spc = 1;
*p = '\0';
} else {
}
}
p++;
}
*argc = i;
}
static ssize_t ps3_cli_read(struct file *fp, char __user *buf, size_t nbytes,
loff_t *ppos)
{
struct ps3_cli_cmd_s *cmd;
int argc;
char *argv[PS3_MAX_ARGV];
int ret;
(void)fp;
(void)ppos;
__pl();
if (!cmd_ready) {
pr_err("ps3_cli_write() must be called before ps_cli_read()\n");
return -EINVAL;
}
read_buf = buf;
read_buf_len = (int)nbytes;
read_buf_ptr = 0;
ps3_parse_cmd(ps3_cli_input, &argc, argv);
ret = mutex_lock_killable(&ps3_cli_mutex);
if (ret != 0) {
pr_err("ps3stor_cli_register(): mutex_lock_killable return err = %d\n",
ret);
return ret;
}
cmd = ps3_cli_find_cmd((const char *)argv[0]);
if (cmd != NULL)
cmd->func(argc, argv);
mutex_unlock(&ps3_cli_mutex);
__pl();
return read_buf_ptr;
}
static int ps3_cli_open(struct inode *ip, struct file *fp)
{
(void)ip;
(void)fp;
if (atomic_cmpxchg(&dev_opened, 0, 1) == 1) {
pr_err("/dev/ps3stor_cli has already been opened\n");
return -EBUSY;
}
cmd_ready = 0;
return 0;
}
static int ps3_cli_release(struct inode *ip, struct file *fp)
{
(void)ip;
(void)fp;
ps3_atomic_set(&dev_opened, 0);
return 0;
}
static const struct file_operations ps3_cli_fops = { .owner = NULL,
.unlocked_ioctl = NULL,
.open = ps3_cli_open,
.release = ps3_cli_release,
.llseek = NULL,
.read = ps3_cli_read,
.write = ps3_cli_write,
.fasync = NULL };
static struct miscdevice ps3_cli_device = {
.minor = PS3_CLI_STATIC_MINOR,
.name = "ps3stor_cli",
.fops = &ps3_cli_fops,
};
static void ps3_cli_help(int argc, char *argv[])
{
int i;
struct ps3_cli_cmd_s *cmd;
(void)argc;
(void)argv;
__pl();
for (i = 0; i < PS3_CLI_HASH_LEN; i++) {
for (cmd = ps3_cli_cmd_head[i]; cmd != NULL; cmd = cmd->next) {
ps3stor_cli_printf("%20s -- %s\n", cmd->cmd,
(const char *)cmd->help);
}
}
__pl();
}
static void ps3_free_cmds(void)
{
int i;
struct ps3_cli_cmd_s *cmd;
for (i = 0; i < PS3_CLI_HASH_LEN; i++) {
while (ps3_cli_cmd_head[i]) {
cmd = ps3_cli_cmd_head[i];
ps3_cli_cmd_head[i] = cmd->next;
kfree(cmd);
}
}
}
int ps3cmd_init(void)
{
int err;
if (misc_registered != 0)
return -EBUSY;
ps3_atomic_set(&dev_opened, 0);
mutex_init(&ps3_cli_mutex);
ps3_cli_device.minor = ps3_cli_minor_get();
err = misc_register(&ps3_cli_device);
if (err) {
pr_warn("Couldn't initialize miscdevice /dev/ps3stor_cli.\n");
return err;
}
misc_registered = 1;
ps3stor_cli_register(ps3_cli_help, "help",
"show this help information");
return 0;
}
void ps3cmd_exit(void)
{
if (!misc_registered)
return;
misc_deregister(&ps3_cli_device);
ps3_free_cmds();
misc_registered = 0;
mutex_destroy(&ps3_cli_mutex);
}

View File

@ -0,0 +1,22 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef _PS3_CLI_H_
#define _PS3_CLI_H_
#define PS3_CLI_INPUT_LEN 2048
#define PS3_CLI_OUTPUT_MAX (16 * 1024 * 1024)
#define PS3_CLI_OUTLINE_LEN 4096
#define PS3_CLI_HELP_LEN 256
#define PS3_CLI_CMD_MAXLEN 32
#define PS3_MAX_ARGV 64
int ps3stor_cli_register(void (*func)(int argc, char *argv[]), const char *cmd_str,
const char *help);
int ps3stor_cli_printf(const char *fmt, ...);
int ps3cmd_init(void);
void ps3cmd_exit(void);
#endif

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,13 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef _PS3_CLI_DEBUG_H_
#define _PS3_CLI_DEBUG_H_
#include "ps3_instance_manager.h"
ssize_t ps3_ioc_reg_dump(struct ps3_instance *instance, char *buf);
void ps3_cli_debug_init(void);
void ps3_io_statis_dump_cli_cb_test(unsigned char detail);
unsigned char ps3_get_wait_cli_flag(void);
#endif

View File

@ -0,0 +1,960 @@
// SPDX-License-Identifier: GPL-2.0
#include <linux/types.h>
#include <linux/version.h>
#include <linux/spinlock.h>
#include <linux/moduleparam.h>
#include <linux/mutex.h>
#include <linux/kthread.h>
#include <linux/string.h>
#include <linux/pagemap.h>
#include <linux/uaccess.h>
#include <linux/fsnotify.h>
#include <linux/rtc.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/compiler.h>
#include <linux/vmalloc.h>
#include <linux/mm.h>
#ifdef __KERNEL__
#include <linux/init.h>
#endif
#include "ps3_driver_log.h"
#include "ps3_module_para.h"
#include "ps3_kernel_version.h"
#include "ps3_util.h"
#if defined DRIVER_DEBUG && defined __KERNEL__
#define FILE_NAME_SIZE 128
#define PS3_KLOG_OUT_WAIT (5 * HZ)
#define DRIVER_SWITCH_FILE
#define LOG_PATH_LEN 100
#define DRV_LOG_FILE_SIZE_MIN_MB 10
#define DRV_LOG_FILE_SIZE_MAX_MB 200
struct ps3_debug g_ps3_debug;
char g_log_path_str[LOG_PATH_LEN] = { 0 };
char g_log_path_bin[LOG_PATH_LEN] = { 0 };
static inline int time_for_log(char *buff, int buf_len)
{
#if defined(PS3_DUMP_TIME_32)
struct timeval tv;
struct tm td;
do_gettimeofday(&tv);
time_to_tm(tv.tv_sec, -sys_tz.tz_minuteswest * 60, &td);
return snprintf(buff, buf_len, "[%04ld-%02d-%02d;%02d:%02d:%02d.%ld]",
td.tm_year + 1900, td.tm_mon + 1, td.tm_mday,
td.tm_hour, td.tm_min, td.tm_sec, tv.tv_usec);
#else
struct timespec64 tv;
struct tm td;
ktime_get_real_ts64(&tv);
time64_to_tm(tv.tv_sec, -sys_tz.tz_minuteswest * 60, &td);
return snprintf(buff, buf_len, "[%04ld-%02d-%02d;%02d:%02d:%02d.%ld]",
td.tm_year + 1900, td.tm_mon + 1, td.tm_mday,
td.tm_hour, td.tm_min, td.tm_sec, tv.tv_nsec * 1000);
#endif
}
static inline int time_for_file_name(char *buff, int buf_len)
{
#if defined(PS3_DUMP_TIME_32)
struct timeval tv;
struct tm td;
do_gettimeofday(&tv);
time_to_tm(tv.tv_sec, -sys_tz.tz_minuteswest * 60, &td);
#else
struct timespec64 tv;
struct tm td;
ktime_get_real_ts64(&tv);
time64_to_tm(tv.tv_sec, -sys_tz.tz_minuteswest * 60, &td);
#endif
return snprintf(buff, buf_len, "%04ld-%02d-%02d_%02d:%02d:%02d",
td.tm_year + 1900, td.tm_mon + 1, td.tm_mday,
td.tm_hour, td.tm_min, td.tm_sec);
}
static inline char *ps3_stack_top(void)
{
#if defined(PS3_THREAD_INFO)
unsigned long *ptr = (unsigned long *)(current->thread_info + 1);
#else
unsigned long *ptr = (unsigned long *)(task_thread_info(current) + 1);
#endif
return (char *)(ptr + 1);
}
static inline struct ps3_thread_local *ps3_thread_local_get(struct ps3_thread_key *key)
{
return (struct ps3_thread_local *)(ps3_stack_top() + key->offset);
}
void ps3_thread_key_create(int size, struct ps3_thread_key *key)
{
key->offset = g_ps3_debug.key_offset;
g_ps3_debug.key_offset += sizeof(struct ps3_thread_local) + size;
}
void *ps3_thread_get_specific(struct ps3_thread_key *key)
{
struct ps3_thread_local *local = ps3_thread_local_get(key);
if (local->magic != DEBUG_TRACE_MAGIC)
return NULL;
return (void *)local->data;
}
void ps3_thread_clear_specific(struct ps3_thread_key *key)
{
struct ps3_thread_local *local = ps3_thread_local_get(key);
local->magic = 0;
}
int ps3_filter_file_add(char *name)
{
struct debug_file *file = NULL;
file = kmalloc(sizeof(struct debug_file), GFP_ATOMIC);
if (!file) {
ps3_print(PRINT_ERR, "kmalloc size %lu failed\n", PAGE_SIZE);
return -ENOMEM;
}
PS3_STRCPY(file->name, name, sizeof(file->name));
INIT_LIST_HEAD(&file->list);
list_add_rcu(&file->list, &g_ps3_debug.filter_file);
return 0;
}
void ps3_filter_file_del(char *filename)
{
struct debug_file *file = NULL;
list_for_each_entry_rcu(file, &g_ps3_debug.filter_file, list) {
if (!strcmp(file->name, filename)) {
list_del_rcu(&file->list);
synchronize_rcu();
kfree(file);
return;
}
}
}
#ifndef PS3_CFG_RELEASE
static inline int ps3_filter_file_print(const char *filename)
{
struct debug_file *file;
rcu_read_lock();
list_for_each_entry_rcu(file, &g_ps3_debug.filter_file, list) {
if (!strcmp(file->name, filename)) {
rcu_read_unlock();
return 1;
}
}
rcu_read_unlock();
return 0;
}
#endif
void ps3_filter_file_clear(void)
{
struct debug_file *file = NULL;
do {
file = list_first_or_null_rcu(&g_ps3_debug.filter_file,
struct debug_file, list);
if (file) {
list_del_rcu(&file->list);
synchronize_rcu();
kfree(file);
}
} while (file);
}
int ps3_filter_func_add(char *name)
{
struct debug_func *func = NULL;
func = kmalloc(sizeof(struct debug_func), GFP_ATOMIC);
if (!func) {
ps3_print(PRINT_ERR, "kmalloc size %lu failed\n", PAGE_SIZE);
return -ENOMEM;
}
PS3_STRCPY(func->name, name, sizeof(func->name));
INIT_LIST_HEAD(&func->list);
list_add_rcu(&func->list, &g_ps3_debug.filter_func);
return 0;
}
void ps3_filter_func_del(char *name)
{
struct debug_func *func = NULL;
list_for_each_entry_rcu(func, &g_ps3_debug.filter_func, list) {
if (!strcmp(func->name, name)) {
list_del_rcu(&func->list);
synchronize_rcu();
kfree(func);
return;
}
}
}
void ps3_filter_func_clear(void)
{
struct debug_func *func = NULL;
do {
func = list_first_or_null_rcu(&g_ps3_debug.filter_func,
struct debug_func, list);
if (func) {
list_del_rcu(&func->list);
synchronize_rcu();
kfree(func);
}
} while (func);
}
void ps3_level_set(int level)
{
g_ps3_debug.level = level;
}
int ps3_level_get(void)
{
return (int)g_ps3_debug.level;
}
#if defined(PS3_SUPPORT_DEBUG) || \
(defined(PS3_CFG_RELEASE) && defined(PS3_CFG_OCM_DBGBUG)) || \
(defined(PS3_CFG_RELEASE) && defined(PS3_CFG_OCM_RELEASE))
static void ps3_file_close(struct file **file)
{
filp_close(*file, NULL);
*file = NULL;
}
static int ps3_file_open(struct ps3_log *log, struct file **pp_file)
{
struct file *file;
int flags_new = O_CREAT | O_RDWR | O_APPEND | O_LARGEFILE;
int flags_rewrite = O_CREAT | O_RDWR | O_LARGEFILE | O_TRUNC;
int err = 0;
int len = 0;
char filename[FILE_NAME_SIZE];
static unsigned long j;
#ifdef DRIVER_SWITCH_FILE
memset(filename, 0, FILE_NAME_SIZE);
len += snprintf(filename, FILE_NAME_SIZE, "%s", log->file_path);
if (log->file_num == 0) {
time_for_file_name(filename + len, FILE_NAME_SIZE - len);
} else {
snprintf(filename + len, FILE_NAME_SIZE - len, "%04d",
log->index++);
log->index = log->index % log->file_num;
}
if (log->file_num == 1 && log->file != NULL) {
ps3_file_close(&log->file);
log->file_pos = 0;
}
#else
memset(filename, 0, FILE_NAME_SIZE);
PS3_STRCPY(filename, path, FILE_NAME_SIZE);
#endif
if (log->file_num == 0) {
file = filp_open(filename, flags_new, 0666);
} else {
file = filp_open(filename, flags_rewrite, 0666);
if (IS_ERR(file)) {
err = (int)PTR_ERR(file);
if (err == -ENOENT)
file = filp_open(filename, flags_new, 0666);
}
}
if (IS_ERR(file)) {
err = (int)PTR_ERR(file);
if (printk_timed_ratelimit(&j, PS3_LOG_LIMIT_INTERVAL_MSEC)) {
ps3_print(PRINT_INFO, "open file:%s failed[errno:%d]\n",
filename, err);
}
goto l_out;
}
if (!ps3_fs_requires_dev(file)) {
#if defined(PS3_SUPPORT_DEBUG) || \
(defined(PS3_CFG_RELEASE) && defined(PS3_CFG_OCM_DBGBUG)) || \
(defined(PS3_CFG_RELEASE) && defined(PS3_CFG_OCM_RELEASE))
if (printk_timed_ratelimit(&j, PS3_LOG_LIMIT_INTERVAL_MSEC)) {
ps3_print(
PRINT_INFO,
"unexpected filesystem, superblock flags: 0x%x\n",
file->f_inode->i_sb->s_type->fs_flags);
}
#endif
ps3_file_close(&file);
err = -EINVAL;
goto l_out;
}
mapping_set_gfp_mask(file->f_path.dentry->d_inode->i_mapping, GFP_NOFS);
ps3_print(PRINT_INFO, "redirect file %s\n", filename);
*pp_file = file;
l_out:
return err;
}
static void ps3_file_sync(struct file *file)
{
struct address_space *mapping;
void *journal;
int ret = 0;
int err;
(void)ret;
(void)err;
if (!file || !file->f_op || !file->f_op->fsync)
goto l_end;
journal = current->journal_info;
current->journal_info = NULL;
mapping = file->f_mapping;
ret = filemap_fdatawrite(mapping);
#if defined(PS3_FILEMAP_WAIT)
mutex_lock(&mapping->host->i_mutex);
err = file->f_op->fsync(file, file->f_path.dentry, 1);
if (!ret)
ret = err;
mutex_unlock(&mapping->host->i_mutex);
err = filemap_fdatawait(mapping);
if (!ret)
ret = err;
#else
err = file->f_op->fsync(file, 0, file->f_mapping->host->i_size, 1);
#endif
current->journal_info = journal;
l_end:
return;
}
static int ps3_file_write(struct file *file, char *buf, int len)
{
int ret = 0;
void *journal;
#if defined(PS3_SUPPORT_FS)
mm_segment_t old_fs;
#endif
#if defined(PS3_KERNEL_WRITE_GET_DS)
old_fs = get_fs();
set_fs(get_ds());
#elif defined(PS3_KERNEL_WRITE)
old_fs = get_fs();
set_fs(KERNEL_DS);
#elif defined(PS3_VFS_WRITE)
#else
old_fs = force_uaccess_begin();
#endif
journal = current->journal_info;
current->journal_info = NULL;
if (!file) {
return 0;
}
do {
#if defined(PS3_KERNEL_WRITE_FILE_OP)
ret = file->f_op->write(file, buf, len, &file->f_pos);
#elif defined(PS3_KERNEL_WRITE_FILE_VFS)
ret = vfs_write(file, buf, len, &file->f_pos);
#else
ret = kernel_write(file, buf, len, &file->f_pos);
#endif
} while (ret == -EINTR);
if (ret >= 0) {
#if defined(PS3_FSNOTIFY_FILE)
fsnotify_modify(file);
#elif defined(PS3_FSNOTIFY_FILE_PATH)
if (file->f_path.dentry)
fsnotify_modify(file->f_path.dentry);
#endif
}
current->journal_info = journal;
#if defined(PS3_SET_FS)
set_fs(old_fs);
#elif defined(PS3_FORCE_UACCESS)
#else
force_uaccess_end(old_fs);
#endif
return ret;
}
static void ps3_klog_in(struct ps3_log *log, char *buf, const int len)
{
int begin = 0;
int end = 0;
int free_size;
unsigned long flags;
static unsigned long j;
spin_lock_irqsave(&log->lock, flags);
if (log->head > log->tail) {
if (printk_timed_ratelimit(&j, PS3_LOG_LIMIT_INTERVAL_MSEC)) {
ps3_print(PRINT_INFO,
"FAILURE: log head exceeds log tail\n");
PS3_BUG_NO_SYNC();
}
}
free_size = log->buf_size - (log->tail - log->head);
if (free_size <= len) {
log->is_drop = 1;
spin_unlock_irqrestore(&log->lock, flags);
return;
}
begin = log->tail % log->buf_size;
end = (log->tail + len) % log->buf_size;
if (begin < end) {
memcpy(log->buf + begin, buf, len);
} else {
memcpy(log->buf + begin, buf, log->buf_size - begin);
memcpy(log->buf, buf + log->buf_size - begin, end);
}
log->tail = log->tail + len;
spin_unlock_irqrestore(&log->lock, flags);
}
static void ps3_klog_out(struct ps3_log *log)
{
int len = 0;
int rc = 0;
long long tail;
int begin;
int end;
int schedule_count_th = 0;
const int max_loop = 4096;
static unsigned long j;
#ifdef DRIVER_SWITCH_FILE
struct file *file = NULL;
#endif
if (log->file == NULL) {
rc = ps3_file_open(log, &log->file);
if (log->file != NULL)
log->file_pos = 0;
else
return;
}
do {
tail = log->tail;
begin = log->head % log->buf_size;
end = tail % log->buf_size;
len = 0;
rc = 0;
schedule_count_th++;
if (schedule_count_th >= max_loop) {
schedule_count_th = 0;
schedule_timeout_interruptible(PS3_KLOG_OUT_WAIT);
}
if (log->is_drop) {
rc = ps3_file_write(log->file, DEBUG_DROP_LOG_STRING,
strlen(DEBUG_DROP_LOG_STRING));
if (rc < 0)
break;
log->is_drop = 0;
}
if (begin < end) {
rc = ps3_file_write(log->file, log->buf + begin,
end - begin);
if (rc > 0)
len += rc;
} else if (begin > end) {
rc = ps3_file_write(log->file, log->buf + begin,
log->buf_size - begin);
if (rc > 0) {
len += rc;
rc = ps3_file_write(log->file, log->buf, end);
if (rc > 0)
len += rc;
}
}
log->head += len;
log->file_pos += len;
LOG_BUG_ON(log->head > log->tail,
"FAILURE: log head exceeds log tail\n");
} while (log->head != log->tail && rc > 0);
if (rc < 0) {
if (printk_timed_ratelimit(&j, PS3_LOG_LIMIT_INTERVAL_MSEC)) {
ps3_print(PRINT_INFO, "write file %s error %d\n",
log->file_path, rc);
}
return;
}
#ifdef DRIVER_SWITCH_FILE
if (log->file_pos >= log->file_size) {
rc = ps3_file_open(log, &file);
if (rc >= 0 && log->file != NULL && log->file_num != 1) {
ps3_file_close(&log->file);
log->file = file;
log->file_pos = 0;
}
}
#endif
}
static int ps3_klog_flush(void *arg)
{
int i;
while (!kthread_should_stop()) {
schedule_timeout_interruptible(PS3_KLOG_OUT_WAIT);
for (i = 0; i < ARRAY_SIZE(g_ps3_debug.log); i++)
ps3_klog_out(&g_ps3_debug.log[i]);
}
return 0;
}
static int ps3_klog_init(struct ps3_log *log, long long buf_size, char *file_path,
long long file_size, unsigned int file_num)
{
int rc = 0;
memset(log, 0, sizeof(*log));
spin_lock_init(&log->lock);
log->buf = vmalloc(buf_size + PAGE_SIZE);
if (!log->buf) {
rc = -ENOMEM;
goto l_end;
}
log->file = NULL;
log->head = 0;
log->tail = 0;
log->buf_size = buf_size;
log->file_path = file_path;
log->file_pos = 0;
log->file_size = file_size;
log->file_num = file_num;
log->index = 0;
l_end:
return rc;
}
static void ps3_klog_exit(struct ps3_log *log)
{
if (log->buf)
vfree(log->buf);
if (log->file)
ps3_file_close(&log->file);
}
static inline char *ps3_file_name_locale(char *file)
{
char *p_slash = strrchr(file, '/');
return (p_slash == NULL) ? file : (p_slash + 1);
}
void ps3_log_string(enum debug_level level, const char *file, int line,
const char *fmt, ...)
{
struct ps3_ctxt *ctxt = NULL;
char *buf = NULL;
int len = 0;
unsigned long flags = 0;
va_list args;
if (level > g_ps3_debug.level) {
#ifndef PS3_CFG_RELEASE
if (!ps3_filter_file_print(file))
return;
#else
return;
#endif
}
if (!in_interrupt())
local_irq_save(flags);
ctxt = per_cpu_ptr(g_ps3_debug.ctxt, get_cpu());
put_cpu();
buf = ctxt->buff;
len = snprintf(buf, PAGE_SIZE, "%s", ps3_debug_level_name(level));
len += time_for_log(buf + len, PAGE_SIZE - len);
len += snprintf(buf + len, PAGE_SIZE - len,
"[%d][%d]%s:%4d:", raw_smp_processor_id(), current->pid,
ps3_file_name_locale((char *)file), line);
va_start(args, fmt);
len += vsnprintf(buf + len, PAGE_SIZE - len, fmt, args);
va_end(args);
if (!in_interrupt())
local_irq_restore(flags);
if (ps3_log_tty_query()) {
if (buf[0] == 'I' || buf[0] == 'W') {
pr_warn_ratelimited("%s",
buf + LOG_INFO_PREFIX_LEN);
} else if (buf[0] == 'E') {
pr_warn_ratelimited("%s",
buf + LOG_ERROR_PREFIX_LEN);
}
}
ps3_klog_in(&g_ps3_debug.log[DEBUG_TYPE_STRING], buf, len);
wake_up_process(g_ps3_debug.task);
}
void ps3_log_binary(const char *file, int line, char *ptr, int size, char *str)
{
#define LINE_TOTAL 16
struct ps3_ctxt *ctxt = NULL;
char *buf = NULL;
int len = 0;
int i;
unsigned long flags = 0;
if (!in_interrupt())
local_irq_save(flags);
ctxt = per_cpu_ptr(g_ps3_debug.ctxt, get_cpu());
put_cpu();
buf = ctxt->buff;
len += time_for_log(buf + len, PAGE_SIZE - len);
len += snprintf(buf + len, PAGE_SIZE - len, "[%d]%s:%d, size:%d, ",
current->pid, ps3_file_name_locale((char *)file), line,
size);
len += snprintf(buf + len, PAGE_SIZE - len, "%s", str);
for (i = 0; i < size; i++) {
if (i % LINE_TOTAL == 0)
len += snprintf(buf + len, PAGE_SIZE - len, "%08x ", i);
len += snprintf(buf + len, PAGE_SIZE - len, "%02hhx", ptr[i]);
if ((i % LINE_TOTAL) == (LINE_TOTAL - 1) || i == (size - 1))
len += snprintf(buf + len, PAGE_SIZE - len, "\n");
else if ((i % LINE_TOTAL) == (LINE_TOTAL / 2 - 1))
len += snprintf(buf + len, PAGE_SIZE - len, " ");
else
len += snprintf(buf + len, PAGE_SIZE - len, " ");
}
if (!in_interrupt())
local_irq_restore(flags);
ps3_klog_in(&g_ps3_debug.log[DEBUG_TYPE_BINARY], buf, len);
wake_up_process(g_ps3_debug.task);
}
void ps3_log_sync(void)
{
ps3_file_sync(g_ps3_debug.log[DEBUG_TYPE_STRING].file);
ps3_file_sync(g_ps3_debug.log[DEBUG_TYPE_BINARY].file);
}
int ps3_debug_init(void)
{
struct task_struct *task = NULL;
struct ps3_ctxt *ctxt = NULL;
int rc = 0;
int i;
int nid;
unsigned int file_num = 0;
unsigned int log_path_len = 0;
unsigned int input_log_space = ps3_log_space_size_query();
unsigned int input_log_file_size = ps3_log_file_size_query();
unsigned int log_file_size = 0;
char *log_path_p = NULL;
struct ps3_log *log_bin = &g_ps3_debug.log[DEBUG_TYPE_BINARY];
struct ps3_log *log_str = &g_ps3_debug.log[DEBUG_TYPE_STRING];
INIT_LIST_HEAD(&g_ps3_debug.filter_file);
INIT_LIST_HEAD(&g_ps3_debug.filter_func);
g_ps3_debug.level = ps3_log_level_query();
g_ps3_debug.ctxt = alloc_percpu(struct ps3_ctxt);
if (!g_ps3_debug.ctxt) {
rc = -ENOMEM;
ps3_print(PRINT_ERR, "alloc percpu failed\n");
goto l_end;
}
for_each_possible_cpu(i) {
ctxt = per_cpu_ptr(g_ps3_debug.ctxt, i);
memset(ctxt, 0, sizeof(*ctxt));
}
for_each_possible_cpu(i) {
ctxt = per_cpu_ptr(g_ps3_debug.ctxt, i);
nid = cpu_to_node(i);
ctxt->page = alloc_pages_node(nid, GFP_ATOMIC, 0);
if (!ctxt->page) {
rc = -ENOMEM;
ps3_print(PRINT_ERR, "kmalloc size %lu failed\n",
PAGE_SIZE);
goto l_free_cpu_buff;
}
ctxt->buff = PS3_KMAP(ctxt->page);
}
log_path_p = ps3_log_path_query();
log_path_len = strlen(log_path_p);
if (log_path_p != NULL && log_path_p[0] == '/') {
if (log_path_p[log_path_len - 1] == '/') {
snprintf(g_log_path_str, LOG_PATH_LEN, "%s%s.",
log_path_p, LOG_FILE_PREFIX);
snprintf(g_log_path_bin, LOG_PATH_LEN, "%s%s.",
log_path_p, BINARY_FILE_PREFIX);
} else {
snprintf(g_log_path_str, LOG_PATH_LEN, "%s/%s.",
log_path_p, LOG_FILE_PREFIX);
snprintf(g_log_path_bin, LOG_PATH_LEN, "%s/%s.",
log_path_p, BINARY_FILE_PREFIX);
}
} else {
snprintf(g_log_path_str, LOG_PATH_LEN, "%s.", LOG_FILE_PATH);
snprintf(g_log_path_bin, LOG_PATH_LEN, "%s.", BINARY_FILE_PATH);
}
if (input_log_file_size < DRV_LOG_FILE_SIZE_MIN_MB ||
input_log_file_size > DRV_LOG_FILE_SIZE_MAX_MB) {
ps3_log_file_size_modify(LOG_FILE_SIZE >> MEGABYTE);
input_log_file_size = LOG_FILE_SIZE >> MEGABYTE;
}
if (input_log_space && input_log_space < input_log_file_size) {
ps3_log_file_size_modify(input_log_space);
input_log_file_size = input_log_space;
}
log_file_size = input_log_file_size << MEGABYTE;
if (input_log_space) {
file_num = input_log_space / input_log_file_size;
if (file_num == 0) {
ps3_print(PRINT_ERR, "filenum shouldnot be 0\n");
PS3_BUG();
}
} else {
file_num = 0;
}
rc = ps3_klog_init(log_str, LOG_BUF_SIZE, g_log_path_str, log_file_size,
file_num);
if (rc < 0)
goto l_free_cpu_buff;
rc = ps3_klog_init(log_bin, BIN_BUF_SIZE, g_log_path_bin,
BINARY_FILE_SIZE, 0);
if (rc < 0)
goto l_free_string;
task = kthread_create(ps3_klog_flush, NULL, "ps3_klog_flush");
if (IS_ERR(task)) {
rc = (int)PTR_ERR(task);
ps3_print(PRINT_ERR, "Create kernel thread, err: %d\n", rc);
goto l_free_binary;
}
wake_up_process(task);
g_ps3_debug.task = task;
rc = 0;
ps3_print(PRINT_INFO,
"PS3 debug init logpath[%s] strlogsize[%dM] filenum[%d]\n",
g_log_path_str, (log_file_size >> MEGABYTE),
log_str->file_num);
l_end:
return rc;
l_free_binary:
ps3_klog_exit(&g_ps3_debug.log[DEBUG_TYPE_BINARY]);
l_free_string:
ps3_klog_exit(&g_ps3_debug.log[DEBUG_TYPE_STRING]);
l_free_cpu_buff:
for_each_possible_cpu(i) {
ctxt = per_cpu_ptr(g_ps3_debug.ctxt, i);
if (ctxt && ctxt->page) {
PS3_KUNMAP(ctxt->page, ctxt->buff);
__free_page(ctxt->page);
}
}
free_percpu(g_ps3_debug.ctxt);
goto l_end;
}
void ps3_debug_exit(void)
{
int i = 0;
struct ps3_ctxt *ctxt;
if (g_ps3_debug.task == NULL)
return;
kthread_stop(g_ps3_debug.task);
for (i = 0; i < ARRAY_SIZE(g_ps3_debug.log); i++)
ps3_klog_exit(&g_ps3_debug.log[i]);
if (g_ps3_debug.ctxt) {
for_each_possible_cpu(i) {
ctxt = per_cpu_ptr(g_ps3_debug.ctxt, i);
if (ctxt && ctxt->page) {
PS3_KUNMAP(ctxt->page, ctxt->buff);
__free_page(ctxt->page);
}
}
free_percpu(g_ps3_debug.ctxt);
g_ps3_debug.ctxt = NULL;
}
}
#else
void ps3_log_sync(void)
{
}
int ps3_debug_init(void)
{
g_ps3_debug.level = LEVEL_WARN;
return 0;
};
void ps3_debug_exit(void)
{
}
#endif
#else
int g_ps3_log_level = LEVEL_INFO;
void ps3_thread_key_create(int size, struct ps3_thread_key *key)
{
(void)size;
(void)key;
}
void *ps3_thread_get_specific(struct ps3_thread_key *key)
{
return key;
}
void ps3_thread_clear_specific(struct ps3_thread_key *key)
{
(void)key;
}
int ps3_filter_file_add(char *name)
{
(void)name;
return 0;
}
void ps3_filter_file_del(char *name)
{
(void)name;
}
void ps3_filter_file_clear(void)
{
}
int ps3_filter_func_add(char *name)
{
(void)name;
return 0;
}
void ps3_filter_func_del(char *name)
{
(void)name;
}
void ps3_filter_func_clear(void)
{
}
void ps3_level_set(int level)
{
g_ps3_log_level = level;
}
int ps3_level_get(void)
{
return g_ps3_log_level;
}
void ps3_log_sync(void)
{
}
int ps3_debug_init(void)
{
g_ps3_log_level = LEVEL_WARN;
return 0;
};
void ps3_debug_exit(void)
{
}
#endif
static int g_ramfs_test_enable;
int ps3_ramfs_test_query(void)
{
return g_ramfs_test_enable;
}
void ps3_ramfs_test_store(int val)
{
g_ramfs_test_enable = val;
}

View File

@ -0,0 +1,655 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef _PS3_DRIVER_LOG_H_
#define _PS3_DRIVER_LOG_H_
#include <linux/kernel.h>
#include <linux/spinlock.h>
#include <linux/fs.h>
#include <linux/sched.h>
#include "ps3_htp_def.h"
#include "ps3_platform_utils.h"
#ifdef __cplusplus
extern "C" {
#endif
#define PS3_HOST(ins) ((ins)->host->host_no)
#define DRIVER_DEBUG
#define LOG_INFO_PREFIX_LEN 32
#define LOG_ERROR_PREFIX_LEN 33
#define MEGABYTE 20
enum debug_level {
LEVEL_ERROR,
LEVEL_WARN,
LEVEL_INFO,
LEVEL_DEBUG,
};
static inline const char *ps3_debug_level_name(enum debug_level lv)
{
static const char * const level[] = {
[LEVEL_ERROR] = "ERROR",
[LEVEL_WARN] = "WARN",
[LEVEL_INFO] = "INFO",
[LEVEL_DEBUG] = "DBG",
};
return level[lv];
}
int ps3_level_get(void);
#define PS3_LOG_LIMIT_INTERVAL_MSEC (24 * 60 * 60 * 1000)
#ifdef __KERNEL__
#define PRINT_DEBUG LEVEL_DEBUG
#define PRINT_INFO LEVEL_INFO
#define PRINT_WARN LEVEL_WARN
#define PRINT_ERR LEVEL_ERROR
#define ps3_print(level, fmt, ...) \
do { \
if (level == LEVEL_DEBUG) { \
pr_debug("[PS3STOR]%s():%d;" fmt, \
__func__, __LINE__, ##__VA_ARGS__); \
} else if (level == LEVEL_INFO) { \
pr_info("[PS3STOR]%s():%d;" fmt, \
__func__, __LINE__, ##__VA_ARGS__); \
} else if (level == LEVEL_WARN) { \
pr_warn("[PS3STOR]%s():%d;" fmt, \
__func__, __LINE__, ##__VA_ARGS__); \
} else if (level == LEVEL_ERROR) { \
pr_err("[PS3STOR]%s():%d;" fmt, \
__func__, __LINE__, ##__VA_ARGS__); \
} \
} while (0)
#define ps3_printk(level, fmt, ...) \
do { \
if (level <= ps3_level_get()) { \
if (level == LEVEL_DEBUG) { \
pr_debug("[PS3STOR][%u]%d;" fmt, \
current->pid, __LINE__, ##__VA_ARGS__); \
} else if (level == LEVEL_INFO) { \
pr_info("[PS3STOR][%u]%d;" fmt, \
current->pid, __LINE__, ##__VA_ARGS__); \
} else if (level == LEVEL_WARN) { \
pr_warn("[PS3STOR][%u]%d;" fmt, \
current->pid, __LINE__, ##__VA_ARGS__); \
} else if (level == LEVEL_ERROR) { \
pr_err("[PS3STOR][%u]%d;" fmt, \
current->pid, __LINE__, ##__VA_ARGS__); \
} \
} \
} while (0)
#define ps3_printk_ratelimited(level, fmt, ...) \
do { \
if (level <= ps3_level_get()) { \
if (level == LEVEL_INFO) { \
pr_info_ratelimited( \
"[PS3STOR][%u]%d;" fmt, \
current->pid, __LINE__, \
##__VA_ARGS__); \
} else if (level == LEVEL_WARN) { \
pr_warn_ratelimited( \
"[PS3STOR][%u]%d;" fmt, \
current->pid, __LINE__, \
##__VA_ARGS__); \
} else if (level == LEVEL_ERROR) { \
pr_err_ratelimited( \
"[PS3STOR][%u]%d;" fmt, \
current->pid, __LINE__, \
##__VA_ARGS__); \
} \
} \
} while (0)
#else
#define PRINT_DEBUG LEVEL_DEBUG
#define PRINT_INFO LEVEL_INFO
#define PRINT_WARN LEVEL_WARN
#define PRINT_ERR LEVEL_ERROR
#include <assert.h>
#include <sys/time.h>
#include <linux/mutex.h>
#define __percpu
static inline unsigned long long get_now_ms(void)
{
struct timeval tv;
unsigned long long timestamp = 0;
gettimeofday(&tv, NULL);
timestamp = tv.tv_sec * 1000 + tv.tv_usec / 1000;
return timestamp;
}
#define filename_printf(x) (strrchr((x), '/') ? strrchr((x), '/') + 1 : (x))
#define ps3_print(lock_chk, level, fmt, ...) \
do { \
if (level != LEVEL_DEBUG && lock_chk) { \
EXPECT_EQ(ps3_get_irq_spin_lock_count(), 0); \
} \
if (level <= ps3_level_get()) { \
if (level == LEVEL_DEBUG) { \
printf("DEBUG:%llu:%s:%s():%d:[%lu];" fmt, \
get_now_ms(), \
filename_printf(__FILE__), \
__func__, __LINE__, pthread_self(), \
##__VA_ARGS__); \
} else if (level == LEVEL_INFO) { \
printf("INFO:%llu:%s:%s():%d:[%lu];" fmt, \
get_now_ms(), \
filename_printf(__FILE__), \
__func__, __LINE__, pthread_self(), \
##__VA_ARGS__); \
} else if (level == LEVEL_WARN) { \
printf("WARN:%llu:%s:%s():%d:[%lu];" fmt, \
get_now_ms(), \
filename_printf(__FILE__), \
__func__, __LINE__, pthread_self(), \
##__VA_ARGS__); \
} else if (level == LEVEL_ERROR) { \
printf("ERROR:%llu:%s:%s():%d:[%lu];" fmt, \
get_now_ms(), \
filename_printf(__FILE__), \
__func__, __LINE__, pthread_self(), \
##__VA_ARGS__); \
} \
} \
} while (0)
#endif
#define LOG_BUG_ON(cond, fmt, ...) \
do { \
if ((cond)) { \
LOG_ERROR(fmt, ##__VA_ARGS__); \
LOG_SYNC(); \
BUG(); \
} \
} while (0)
#define DEBUG_TRACE_MAGIC 0x456789
#define LOG_BUF_SIZE (1024LL << 11)
#define BIN_BUF_SIZE (1024LL << 10)
#define LOG_FILE_SIZE (200LL << 20)
#define LOG_FILE_PATH "/var/log/ps3sas_drv.log"
#define LOG_FILE_PREFIX "ps3sas_drv.log"
#define BINARY_FILE_PREFIX "ps3sas_drv.bin"
#define BINARY_FILE_SIZE (200LL << 20)
#define BINARY_FILE_PATH "/var/log/ps3sas_drv.bin"
#define DEBUG_DROP_LOG_STRING "\nwarnning:drop some logs\n\n"
enum {
DEBUG_TYPE_STRING,
DEBUG_TYPE_BINARY,
DEBUG_TYPE_NR,
};
struct debug_func {
struct list_head list;
char name[64];
};
struct debug_file {
struct list_head list;
char name[64];
};
struct ps3_log {
struct {
char *buf;
int buf_size;
long long head;
long long tail;
spinlock_t lock;
unsigned char is_drop;
};
struct {
char *file_path;
struct file *file;
long long file_pos;
long long file_size;
unsigned int file_num;
unsigned int index;
};
};
struct ps3_thread_local {
int magic;
char data[0];
};
struct ps3_ctxt {
struct page *page;
void *buff;
};
struct ps3_thread_key {
int offset;
};
struct ps3_debug {
enum debug_level level;
unsigned short key_offset;
struct ps3_ctxt __percpu *ctxt;
struct list_head filter_func;
struct list_head filter_file;
struct task_struct *task;
struct ps3_log log[DEBUG_TYPE_NR];
};
void ps3_thread_key_create(int size, struct ps3_thread_key *key);
void *ps3_thread_get_specific(struct ps3_thread_key *key);
void ps3_thread_clear_specific(struct ps3_thread_key *key);
int ps3_filter_file_add(char *name);
void ps3_filter_file_del(char *name);
void ps3_filter_file_clear(void);
int ps3_filter_func_add(char *name);
void ps3_filter_func_del(char *name);
void ps3_filter_func_clear(void);
void ps3_level_set(int level);
int ps3_level_get(void);
int ps3_debug_init(void);
void ps3_debug_exit(void);
void ps3_log_string(enum debug_level level, const char *file, int line,
const char *fmt, ...);
void ps3_log_binary(const char *file, int line, char *ptr, int size, char *str);
void ps3_log_sync(void);
int ps3_ramfs_test_query(void);
void ps3_ramfs_test_store(int val);
#if defined DRIVER_DEBUG && defined __KERNEL__
#if defined(PS3_SUPPORT_DEBUG) || \
(defined(PS3_CFG_RELEASE) && defined(PS3_CFG_OCM_DBGBUG)) || \
(defined(PS3_CFG_RELEASE) && defined(PS3_CFG_OCM_RELEASE))
#define WRITE_LOG(level, fmt, ...) \
ps3_log_string(level, __FILE__, __LINE__, fmt, ##__VA_ARGS__)
#define LOG_DEBUG(fmt, ...) WRITE_LOG(LEVEL_DEBUG, fmt, ##__VA_ARGS__)
#define LOG_INFO(fmt, ...) WRITE_LOG(LEVEL_INFO, fmt, ##__VA_ARGS__)
#define LOG_WARN(fmt, ...) WRITE_LOG(LEVEL_WARN, fmt, ##__VA_ARGS__)
#define LOG_ERROR(fmt, ...) WRITE_LOG(LEVEL_ERROR, fmt, ##__VA_ARGS__)
#define LOG2_DEBUG(fmt, ...) \
do { \
WRITE_LOG(LEVEL_DEBUG, fmt, ##__VA_ARGS__); \
ps3_print(PRINT_DEBUG, fmt, ##__VA_ARGS__); \
} while (0)
#define LOG2_INFO(fmt, ...) \
do { \
WRITE_LOG(LEVEL_INFO, fmt, ##__VA_ARGS__); \
ps3_print(PRINT_INFO, fmt, ##__VA_ARGS__); \
} while (0)
#define LOG2_WARN(fmt, ...) \
do { \
WRITE_LOG(LEVEL_WARN, fmt, ##__VA_ARGS__); \
ps3_print(PRINT_WARN, fmt, ##__VA_ARGS__); \
} while (0)
#define LOG2_ERROR(fmt, ...) \
do { \
WRITE_LOG(LEVEL_ERROR, fmt, ##__VA_ARGS__); \
ps3_print(PRINT_ERR, fmt, ##__VA_ARGS__); \
} while (0)
#define LOG_LEVEL(log_lvl, fmt, ...) WRITE_LOG(log_lvl, fmt, ##__VA_ARGS__)
#define LOG_INFO_LIM(fmt, ...) WRITE_LOG(LEVEL_INFO, fmt, ##__VA_ARGS__)
#define LOG_WARN_LIM(fmt, ...) WRITE_LOG(LEVEL_WARN, fmt, ##__VA_ARGS__)
#define LOG_ERROR_LIM(fmt, ...) WRITE_LOG(LEVEL_ERROR, fmt, ##__VA_ARGS__)
#define LOG_INFO_TIME_LIM(caller_jiffies, time, fmt, ...) \
do { \
(void)caller_jiffies; \
(void)time; \
WRITE_LOG(LEVEL_INFO, fmt, ##__VA_ARGS__); \
} while (0)
#define LOG_WARN_TIME_LIM(caller_jiffies, time, fmt, ...) \
do { \
(void)caller_jiffies; \
(void)time; \
WRITE_LOG(LEVEL_WARN, fmt, ##__VA_ARGS__); \
} while (0)
#define LOG_ERROR_TIME_LIM(caller_jiffies, time, fmt, ...) \
do { \
(void)caller_jiffies; \
(void)time; \
WRITE_LOG(LEVEL_ERROR, fmt, ##__VA_ARGS__); \
} while (0)
#define LOG2_INFO_LIM(fmt, ...) WRITE_LOG(LEVEL_INFO, fmt, ##__VA_ARGS__)
#define LOG2_WARN_LIM(fmt, ...) WRITE_LOG(LEVEL_WARN, fmt, ##__VA_ARGS__)
#define LOG2_ERROR_LIM(fmt, ...) WRITE_LOG(LEVEL_ERROR, fmt, ##__VA_ARGS__)
#define LOG_FILE_INFO(fmt, ...) WRITE_LOG(LEVEL_INFO, fmt, ##__VA_ARGS__)
#define LOG_FILE_WARN(fmt, ...) WRITE_LOG(LEVEL_WARN, fmt, ##__VA_ARGS__)
#define LOG_FILE_ERROR(fmt, ...) WRITE_LOG(LEVEL_ERROR, fmt, ##__VA_ARGS__)
#define LOG_SPC_ERROR(fmt, ...) WRITE_LOG(LEVEL_ERROR, fmt, ##__VA_ARGS__)
#define LOG_INFO_IN_IRQ(ins, fmt, ...) WRITE_LOG(LEVEL_INFO, fmt, ##__VA_ARGS__)
#define LOG_WARN_IN_IRQ(ins, fmt, ...) WRITE_LOG(LEVEL_WARN, fmt, ##__VA_ARGS__)
#define LOG_ERROR_IN_IRQ(ins, fmt, ...) \
WRITE_LOG(LEVEL_ERROR, fmt, ##__VA_ARGS__)
#define LOG_INFO_LIM_WITH_CHECK(ins, need_prk_err, fmt, ...) \
WRITE_LOG(LEVEL_INFO, fmt, ##__VA_ARGS__)
#define LOG_WARN_LIM_WITH_CHECK(ins, need_prk_err, fmt, ...) \
WRITE_LOG(LEVEL_WARN, fmt, ##__VA_ARGS__)
#define LOG_ERROR_LIM_WITH_CHECK(ins, need_prk_err, fmt, ...) \
WRITE_LOG(LEVEL_ERROR, fmt, ##__VA_ARGS__)
#define LOG_SYNC() ps3_log_sync()
#define DATA_DUMP(ptr, size, str) \
ps3_log_binary(__FILE__, __LINE__, (char *)ptr, size, str)
#else
#define LOG_DEBUG(fmt, ...) ps3_printk(LEVEL_DEBUG, fmt, ##__VA_ARGS__)
#define LOG_INFO(fmt, ...) ps3_printk(LEVEL_INFO, fmt, ##__VA_ARGS__)
#define LOG_WARN(fmt, ...) ps3_printk(LEVEL_WARN, fmt, ##__VA_ARGS__)
#define LOG_ERROR(fmt, ...) ps3_printk(LEVEL_ERROR, fmt, ##__VA_ARGS__)
#define LOG2_DEBUG(fmt, ...) ps3_print(PRINT_DEBUG, fmt, ##__VA_ARGS__)
#define LOG2_INFO(fmt, ...) ps3_print(PRINT_INFO, fmt, ##__VA_ARGS__)
#define LOG2_WARN(fmt, ...) ps3_print(PRINT_WARN, fmt, ##__VA_ARGS__)
#define LOG2_ERROR(fmt, ...) ps3_print(PRINT_ERR, fmt, ##__VA_ARGS__)
#define LOG_INFO_LIM(fmt, ...) \
ps3_printk_ratelimited(LEVEL_INFO, fmt, ##__VA_ARGS__)
#define LOG_WARN_LIM(fmt, ...) \
ps3_printk_ratelimited(LEVEL_WARN, fmt, ##__VA_ARGS__)
#define LOG_ERROR_LIM(fmt, ...) \
ps3_printk_ratelimited(LEVEL_ERROR, fmt, ##__VA_ARGS__)
#define LOG_INFO_TIME_LIM(caller_jiffies, time, fmt, ...) \
do { \
if (printk_timed_ratelimit(caller_jiffies, time)) { \
ps3_printk(LEVEL_INFO, fmt, ##__VA_ARGS__); \
} \
} while (0)
#define LOG_WARN_TIME_LIM(caller_jiffies, time, fmt, ...) \
do { \
if (printk_timed_ratelimit(caller_jiffies, time)) { \
ps3_printk(LEVEL_WARN, fmt, ##__VA_ARGS__); \
} \
} while (0)
#define LOG_ERROR_TIME_LIM(caller_jiffies, time, fmt, ...) \
do { \
if (printk_timed_ratelimit(caller_jiffies, time)) { \
ps3_printk(LEVEL_ERROR, fmt, ##__VA_ARGS__); \
} \
} while (0)
#define LOG2_INFO_LIM(fmt, ...) LOG_INFO_LIM(fmt, ##__VA_ARGS__)
#define LOG2_WARN_LIM(fmt, ...) LOG_WARN_LIM(fmt, ##__VA_ARGS__)
#define LOG2_ERROR_LIM(fmt, ...) LOG_ERROR_LIM(fmt, ##__VA_ARGS__)
#define LOG_SPC_ERROR(fmt, ...) LOG_INFO(fmt, ##__VA_ARGS__)
#define LOG_FILE_INFO(fmt, ...)
#define LOG_FILE_WARN(fmt, ...)
#define LOG_FILE_ERROR(fmt, ...)
#define LOG_LEVEL(log_lvl, fmt, ...) ps3_printk(log_lvl, fmt, ##__VA_ARGS__)
#define LOG_INFO_IN_IRQ(ins, fmt, ...) \
do { \
if ((ins)->is_irq_prk_support) { \
ps3_printk(LEVEL_INFO, fmt, ##__VA_ARGS__); \
} \
} while (0)
#define LOG_WARN_IN_IRQ(ins, fmt, ...) \
do { \
if ((ins)->is_irq_prk_support) { \
ps3_printk(LEVEL_WARN, fmt, ##__VA_ARGS__); \
} \
} while (0)
#define LOG_ERROR_IN_IRQ(ins, fmt, ...) \
do { \
if ((ins)->is_irq_prk_support) { \
ps3_printk(LEVEL_ERROR, fmt, ##__VA_ARGS__); \
} \
} while (0)
#define LOG_INFO_LIM_WITH_CHECK(ins, need_prk_err, fmt, ...) \
do { \
if (need_prk_err) { \
LOG_INFO_LIM(fmt, ##__VA_ARGS__); \
} else { \
LOG_INFO_IN_IRQ((ins), fmt, ##__VA_ARGS__); \
} \
} while (0)
#define LOG_WARN_LIM_WITH_CHECK(ins, need_prk_err, fmt, ...) \
do { \
if (need_prk_err) { \
LOG_WARN_LIM(fmt, ##__VA_ARGS__); \
} else { \
LOG_WARN_IN_IRQ((ins), fmt, ##__VA_ARGS__); \
} \
} while (0)
#define LOG_ERROR_LIM_WITH_CHECK(ins, need_prk_err, fmt, ...) \
do { \
if (need_prk_err) { \
LOG_ERROR_LIM(fmt, ##__VA_ARGS__); \
} else { \
LOG_ERROR_IN_IRQ((ins), fmt, ##__VA_ARGS__); \
} \
} while (0)
#define LOG_SYNC()
#define DATA_DUMP(ptr, size, str)
#endif
static inline unsigned char ps3_fs_requires_dev(struct file *fp)
{
if (ps3_ramfs_test_query())
return PS3_FALSE;
return (fp->f_inode->i_sb->s_type->fs_flags & FS_REQUIRES_DEV);
}
#else
#define LOG_DEBUG(fmt, ...) ps3_print(PS3_TRUE, PRINT_DEBUG, fmt, ##__VA_ARGS__)
#define LOG_INFO(fmt, ...) ps3_print(PS3_TRUE, PRINT_INFO, fmt, ##__VA_ARGS__)
#define LOG_WARN(fmt, ...) ps3_print(PS3_TRUE, PRINT_WARN, fmt, ##__VA_ARGS__)
#define LOG_ERROR(fmt, ...) ps3_print(PS3_TRUE, PRINT_ERR, fmt, ##__VA_ARGS__)
#define LOG2_DEBUG(fmt, ...) \
ps3_print(PS3_TRUE, PRINT_DEBUG, fmt, ##__VA_ARGS__)
#define LOG2_INFO(fmt, ...) ps3_print(PS3_TRUE, PRINT_INFO, fmt, ##__VA_ARGS__)
#define LOG2_WARN(fmt, ...) ps3_print(PS3_TRUE, PRINT_WARN, fmt, ##__VA_ARGS__)
#define LOG2_ERROR(fmt, ...) ps3_print(PS3_TRUE, PRINT_ERR, fmt, ##__VA_ARGS__)
#define LOG_LEVEL(log_lvl, fmt, ...) \
ps3_print(PS3_TRUE, log_lvl, fmt, ##__VA_ARGS__)
#define LOG_INFO_LIM(fmt, ...) \
ps3_print(PS3_TRUE, LEVEL_INFO, fmt, ##__VA_ARGS__)
#define LOG_WARN_LIM(fmt, ...) \
ps3_print(PS3_TRUE, LEVEL_WARN, fmt, ##__VA_ARGS__)
#define LOG_ERROR_LIM(fmt, ...) \
ps3_print(PS3_TRUE, LEVEL_ERROR, fmt, ##__VA_ARGS__)
#define LOG_INFO_TIME_LIM(caller_jiffies, time, fmt, ...) \
do { \
(void)caller_jiffies; \
(void)time; \
ps3_print(PS3_TRUE, LEVEL_INFO, fmt, ##__VA_ARGS__); \
} while (0)
#define LOG_WARN_TIME_LIM(caller_jiffies, time, fmt, ...) \
do { \
(void)caller_jiffies; \
(void)time; \
ps3_print(PS3_TRUE, LEVEL_WARN, fmt, ##__VA_ARGS__); \
} while (0)
#define LOG_ERROR_TIME_LIM(caller_jiffies, time, fmt, ...) \
do { \
(void)caller_jiffies; \
(void)time; \
ps3_print(PS3_TRUE, LEVEL_ERROR, fmt, ##__VA_ARGS__); \
} while (0)
#define LOG2_INFO_LIM(fmt, ...) LOG_INFO_LIM(fmt, ##__VA_ARGS__)
#define LOG2_WARN_LIM(fmt, ...) LOG_WARN_LIM(fmt, ##__VA_ARGS__)
#define LOG2_ERROR_LIM(fmt, ...) LOG_ERROR_LIM(fmt, ##__VA_ARGS__)
#define LOG_FILE_INFO(fmt, ...)
#define LOG_FILE_WARN(fmt, ...)
#define LOG_FILE_ERROR(fmt, ...)
#define LOG_SPC_ERROR(fmt, ...) LOG_INFO(fmt, ##__VA_ARGS__)
#define LOG_INFO_IN_IRQ(ins, fmt, ...) \
do { \
(void)ins; \
ps3_print(PS3_FALSE, LEVEL_INFO, fmt, ##__VA_ARGS__); \
} while (0)
#define LOG_WARN_IN_IRQ(ins, fmt, ...) \
do { \
(void)ins; \
ps3_print(PS3_FALSE, LEVEL_WARN, fmt, ##__VA_ARGS__); \
} while (0)
#define LOG_ERROR_IN_IRQ(ins, fmt, ...) \
do { \
(void)ins; \
ps3_print(PS3_FALSE, LEVEL_ERROR, fmt, ##__VA_ARGS__); \
} while (0)
#define LOG_INFO_LIM_WITH_CHECK(ins, need_prk_err, fmt, ...) \
do { \
(void)ins; \
ps3_print((need_prk_err), LEVEL_INFO, fmt, ##__VA_ARGS__); \
} while (0)
#define LOG_WARN_LIM_WITH_CHECK(ins, need_prk_err, fmt, ...) \
do { \
(void)ins; \
ps3_print((need_prk_err), LEVEL_WARN, fmt, ##__VA_ARGS__); \
} while (0)
#define LOG_ERROR_LIM_WITH_CHECK(ins, need_prk_err, fmt, ...) \
do { \
(void)ins; \
ps3_print((need_prk_err), LEVEL_ERROR, fmt, ##__VA_ARGS__); \
} while (0)
#define LOG_SYNC()
#define DATA_DUMP(ptr, size, str)
static inline unsigned char ps3_fs_requires_dev(struct file *fp)
{
(void)fp;
return PS3_TRUE;
}
#endif
#ifdef PS3_CFG_RELEASE
#define PS3_BUG()
#define PS3_BUG_NO_SYNC()
#if defined(PS3_CFG_OCM_DBGBUG) || defined(PS3_CFG_OCM_RELEASE)
#define PS3_BUG_ON(cond) \
do { \
if ((cond)) { \
pr_err("BUG_ON's condition(%s) has been triggered\n", \
#cond); \
LOG_ERROR( \
"BUG_ON's condition(%s) has been triggered\n", \
#cond); \
} \
} while (0)
#define PS3_BUG_ON_NO_SYNC(cond) \
do { \
if ((cond)) { \
pr_err("BUG_ON's condition(%s) has been triggered\n", \
#cond); \
LOG_ERROR( \
"BUG_ON's condition(%s) has been triggered\n", \
#cond); \
} \
} while (0)
#else
#define PS3_BUG_ON(cond) \
do { \
if ((cond)) { \
pr_err("BUG_ON's condition(%s) has been triggered\n", \
#cond); \
} \
} while (0)
#define PS3_BUG_ON_NO_SYNC(cond) \
do { \
if ((cond)) { \
pr_err("BUG_ON's condition(%s) has been triggered\n", \
#cond); \
} \
} while (0)
#endif
#else
#define PS3_BUG_ON(cond) \
do { \
if ((cond)) { \
pr_err("BUG_ON's condition(%s) has been triggered\n", \
#cond); \
LOG_ERROR( \
"BUG_ON's condition(%s) has been triggered\n", \
#cond); \
LOG_SYNC(); \
} \
BUG_ON(cond); \
} while (0)
#define PS3_BUG(void) \
do { \
LOG_SYNC(); \
BUG(void); \
} while (0)
#define PS3_BUG_ON_NO_SYNC(cond) \
do { \
if ((cond)) { \
pr_err( \
"BUG_ON's condition(%s) has been triggered\n", \
#cond); \
LOG_ERROR( \
"BUG_ON's condition(%s) has been triggered\n", \
#cond); \
} \
BUG_ON(cond); \
} while (0)
#define PS3_BUG_NO_SYNC(void) BUG(void)
#endif
#define PS3_WARN_ON(cond) WARN_ON(cond)
#ifdef __cplusplus
}
#endif
#endif

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,244 @@
// SPDX-License-Identifier: GPL-2.0
#include <scsi/scsi_host.h>
#include "ps3_pcie_err_handle.h"
#include "ps3_driver_log.h"
#include "ps3_recovery.h"
#include "ps3_ioc_state.h"
#include "ps3_module_para.h"
#include "ps3_kernel_version.h"
static pci_ers_result_t ps3_pci_err_detected(struct pci_dev *pdev,
pci_channel_state_t state);
static pci_ers_result_t ps3_pci_mmio_enabled(struct pci_dev *pdev);
static pci_ers_result_t ps3_pci_slot_reset(struct pci_dev *pdev);
static void ps3_pci_resume(struct pci_dev *pdev);
extern int ps3_pci_init(struct pci_dev *pdev, struct ps3_instance *instance);
extern int ps3_pci_init_complete(struct ps3_instance *instance);
extern void ps3_pci_init_complete_exit(struct ps3_instance *instance);
static struct pci_error_handlers ps3_err_handlers = {
.error_detected = ps3_pci_err_detected,
.mmio_enabled = ps3_pci_mmio_enabled,
.slot_reset = ps3_pci_slot_reset,
.resume = ps3_pci_resume
};
void ps3_pci_err_handler_init(struct pci_driver *drv)
{
drv->err_handler = &ps3_err_handlers;
}
int ps3_base_init_resources(struct ps3_instance *instance)
{
int ret = PS3_SUCCESS;
struct pci_dev *pdev = instance->pdev;
ret = ps3_pci_init(pdev, instance);
if (ret) {
LOG_ERROR("hno:%u pci init failed, ret: %d\n",
PS3_HOST(instance), ret);
goto l_out;
}
instance->is_pci_reset = PS3_FALSE;
ret = ps3_pci_init_complete(instance);
if (ret) {
LOG_ERROR("hno:%u pci init complete failed, ret: %d\n",
PS3_HOST(instance), ret);
goto l_out;
}
pci_save_state(pdev);
l_out:
return ret;
}
void ps3_base_free_resources(struct ps3_instance *instance)
{
instance->ioc_adpter->irq_disable(instance);
ps3_irqs_sync(instance);
ps3_irqpolls_enable(instance);
ps3_dump_work_stop(instance);
ps3_pci_init_complete_exit(instance);
}
static pci_ers_result_t ps3_pci_err_detected(struct pci_dev *pdev,
pci_channel_state_t state)
{
pci_ers_result_t ret = PCI_ERS_RESULT_NEED_RESET;
struct ps3_instance *instance =
(struct ps3_instance *)pci_get_drvdata(pdev);
if (instance == NULL) {
LOG_INFO("get instance failed\n");
dev_info(&pdev->dev, "[PS3]%s():%d; get instance failed\n",
__func__, __LINE__);
ret = PCI_ERS_RESULT_DISCONNECT;
goto l_out;
}
LOG_INFO("[%04x:%02x:%02x:%x]:PCIe err detected state:%u\n",
ps3_get_pci_domain(pdev), ps3_get_pci_bus(pdev),
ps3_get_pci_slot(pdev), ps3_get_pci_function(pdev), state);
dev_info(&pdev->dev, "[PS3]%s():%d;PCIe err detected state:%u\n",
__func__, __LINE__, state);
instance->is_pcie_err_detected = PS3_TRUE;
switch (state) {
case pci_channel_io_normal:
ret = PCI_ERS_RESULT_CAN_RECOVER;
break;
case pci_channel_io_frozen:
ps3_pci_err_recovery_set(instance, PS3_TRUE);
scsi_block_requests(instance->host);
ps3_watchdog_stop(instance);
if (ps3_recovery_cancel_work_sync(instance) != PS3_SUCCESS) {
LOG_ERROR("hno:%u work sync failed, state: %u\n",
PS3_HOST(instance), state);
}
instance->pci_err_handle_state = PS3_DEVICE_ERR_STATE_CLEAN;
ps3_base_free_resources(instance);
ret = PCI_ERS_RESULT_NEED_RESET;
break;
case pci_channel_io_perm_failure:
ps3_pci_err_recovery_set(instance, PS3_TRUE);
ps3_watchdog_stop(instance);
if (ps3_recovery_cancel_work_sync(instance) != PS3_SUCCESS) {
LOG_ERROR("hno:%u work sync failed, state: %u\n",
PS3_HOST(instance), state);
}
ps3_cmd_force_stop(instance);
ps3_pci_err_recovery_set(instance, PS3_FALSE);
ps3_instance_state_transfer_to_dead(instance);
ret = PCI_ERS_RESULT_DISCONNECT;
break;
default:
ret = PCI_ERS_RESULT_RECOVERED;
break;
}
instance->is_pcie_err_detected = PS3_FALSE;
l_out:
LOG_INFO("[%04x:%02x:%02x:%x]:PCIe err detect state:%u ret:%u\n",
ps3_get_pci_domain(pdev), ps3_get_pci_bus(pdev),
ps3_get_pci_slot(pdev), ps3_get_pci_function(pdev), state,
ret);
dev_info(&pdev->dev, "[PS3]%s():%d;PCIe err detect state:%u ret:%u\n",
__func__, __LINE__, state, ret);
return ret;
}
static pci_ers_result_t ps3_pci_mmio_enabled(struct pci_dev *pdev)
{
pci_ers_result_t ret = PCI_ERS_RESULT_RECOVERED;
LOG_INFO("[%04x:%02x:%02x:%x]: PCIe err mmio enabled\n",
ps3_get_pci_domain(pdev), ps3_get_pci_bus(pdev),
ps3_get_pci_slot(pdev), ps3_get_pci_function(pdev));
dev_info(&pdev->dev, "[PS3]%s():%d; PCIe err mmio enabled\n",
__func__, __LINE__);
return ret;
}
static pci_ers_result_t ps3_pci_slot_reset(struct pci_dev *pdev)
{
int ret;
struct ps3_instance *instance =
(struct ps3_instance *)pci_get_drvdata(pdev);
LOG_INFO("hno:%u PCIe err slot reset begin.\n", PS3_HOST(instance));
dev_info(&pdev->dev, "[PS3]%s():%d;hno:%u PCIe err slot reset begin.\n",
__func__, __LINE__, PS3_HOST(instance));
instance->pdev = pdev;
pci_restore_state(pdev);
ps3_irq_context_exit(instance);
ret = ps3_base_init_resources(instance);
if (ret) {
LOG_ERROR("hno:%u base init resources failed, ret: %d\n",
PS3_HOST(instance), ret);
dev_info(&pdev->dev,
"[PS3]hno:%u init resources failed, ret: %d\n",
PS3_HOST(instance), ret);
goto l_out;
}
LOG_INFO("hno:%u PCIe err slot reset succeed.\n", PS3_HOST(instance));
dev_info(&pdev->dev,
"[PS3]%s():%d;hno:%u PCIe err slot reset succeed.\n",
__func__, __LINE__, PS3_HOST(instance));
ps3_pci_err_recovery_set(instance, PS3_FALSE);
instance->pci_err_handle_state = PS3_DEVICE_ERR_STATE_INIT;
return PCI_ERS_RESULT_RECOVERED;
l_out:
if (instance)
ps3_instance_state_transfer_to_dead(instance);
ps3_pci_err_recovery_set(instance, PS3_FALSE);
instance->pci_err_handle_state = PS3_DEVICE_ERR_STATE_INIT;
return PCI_ERS_RESULT_DISCONNECT;
}
static void ps3_pci_resume(struct pci_dev *pdev)
{
int ret = PS3_SUCCESS;
unsigned int fw_cur_state = PS3_FW_STATE_UNDEFINED;
struct ps3_instance *instance =
(struct ps3_instance *)pci_get_drvdata(pdev);
LOG_INFO("hno:%u PCIe err resume\n", PS3_HOST(instance));
dev_info(&pdev->dev, "[PS3]%s():%d;hno:%u PCIe err resume\n",
__func__, __LINE__, PS3_HOST(instance));
fw_cur_state = instance->ioc_adpter->ioc_state_get(instance);
if (fw_cur_state == PS3_FW_STATE_RUNNING) {
LOG_INFO("hno:%u not need repeat recovery\n",
PS3_HOST(instance));
dev_info(&pdev->dev, "[PS3]hno:%u not need repeat recovery\n",
PS3_HOST(instance));
goto l_norecovery;
}
ret = ps3_hard_recovery_request_with_retry(instance);
if (ret != PS3_SUCCESS) {
LOG_ERROR("hno:%u hard reset NOK, ret: %d\n",
PS3_HOST(instance), ret);
dev_info(&pdev->dev, "[PS3]hno:%u hard reset NOK, ret: %d\n",
PS3_HOST(instance), ret);
goto l_failed;
}
ret = ps3_instance_wait_for_operational(instance, PS3_TRUE);
if (ret != PS3_SUCCESS) {
LOG_ERROR("hno:%u wait for opt NOK.\n", PS3_HOST(instance));
dev_info(&pdev->dev, "[PS3]hno:%u wait for opt NOK.\n",
PS3_HOST(instance));
goto l_failed;
}
l_norecovery:
#if defined(PS3_AER_CLEAR_STATUS)
pci_aer_clear_nonfatal_status(pdev);
#elif defined(PS3_AER_CLEAR_STATUS_LOW_KERNER)
pci_cleanup_aer_uncorrect_error_status(pdev);
#endif
ps3_watchdog_start(instance);
scsi_unblock_requests(instance->host);
instance->pci_err_handle_state = PS3_DEVICE_ERR_STATE_NORMAL;
return;
l_failed:
#if defined(PS3_AER_CLEAR_STATUS)
pci_aer_clear_nonfatal_status(pdev);
#elif defined(PS3_AER_CLEAR_STATUS_LOW_KERNER)
pci_cleanup_aer_uncorrect_error_status(pdev);
#endif
if (instance)
ps3_instance_state_transfer_to_dead(instance);
instance->pci_err_handle_state = PS3_DEVICE_ERR_STATE_NORMAL;
}

View File

@ -0,0 +1,23 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef _PS3_PCIE_ERR_HANDLE_H_
#define _PS3_PCIE_ERR_HANDLE_H_
#include <linux/pci.h>
#include <linux/aer.h>
#include "ps3_instance_manager.h"
#ifdef __cplusplus
extern "C" {
#endif
void ps3_pci_err_handler_init(struct pci_driver *drv);
int ps3_base_init_resources(struct ps3_instance *instance);
void ps3_base_free_resources(struct ps3_instance *instance);
#ifdef __cplusplus
}
#endif
#endif

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,353 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef _PS3_CMD_CHANNEL_H_
#define _PS3_CMD_CHANNEL_H_
#include "ps3_htp.h"
#include "ps3_htp_reqframe.h"
#ifdef _WINDOWS
#include "ps3_def.h"
#include "ps3_cmd_adp.h"
#endif
#include "ps3_platform_utils.h"
#include "ps3_inner_data.h"
#include "ps3_driver_log.h"
#include "ps3_htp_ioctl.h"
#define PS3_DEFAULT_REQ_FRAME_SIZE (256)
#define PS3_WAIT_SCSI_CMD_DONE_COUNT (1200)
enum {
DMA_ALIGN_BYTES_4K = 4096,
DMA_ALIGN_BYTES_2K = 2048,
DMA_ALIGN_BYTES_1K = 1024,
DMA_ALIGN_BYTES_512 = 512,
DMA_ALIGN_BYTES_256 = 256,
DMA_ALIGN_BYTES_128 = 128,
DMA_ALIGN_BYTES_64 = 64,
DMA_ALIGN_BYTES_16 = 16,
DMA_ALIGN_BYTES_4 = 4,
};
enum {
PS3_CMD_STATE_INIT = 0,
PS3_CMD_STATE_PROCESS = 1,
PS3_CMD_STATE_COMPLETE = 2,
PS3_CMD_STATE_DEAD = 3,
};
enum {
PS3_CMD_FLAG_SOFTRESET = 1,
PS3_CMD_FLAG_HARDRESET = 2,
};
enum {
PS3_R1X_MODE_NORMAL = 0,
PS3_R1X_MODE_PERF = 1,
};
#define PS3_CMD_EXT_BUF_DEFAULT_SIZE (4096)
#define PS3_CMD_EXT_BUF_SIZE_MGR (4096)
#define PS3_MIN_SCSI_CMD_COUNT (4096)
static inline const char *namePS3CmdState(unsigned int s)
{
static const char * const myNames[] = {
[PS3_CMD_STATE_INIT] = "PS3_CMD_STATE_INIT",
[PS3_CMD_STATE_PROCESS] = "PS3_CMD_STATE_PROCESS",
[PS3_CMD_STATE_COMPLETE] = "PS3_CMD_STATE_COMPLETE",
[PS3_CMD_STATE_DEAD] = "PS3_CMD_STATE_DEAD"
};
if (s > PS3_CMD_STATE_DEAD)
return "PS3_CMD_STATE_INVALID";
return myNames[s];
}
struct ps3_cmd_state_t {
unsigned char state;
unsigned char reset_flag;
unsigned char reserived[6];
spinlock_t lock;
};
union ps3_scsi_cdb_option {
struct {
unsigned char non_ncq : 1;
unsigned char reserved0 : 1;
unsigned char reserved1 : 1;
unsigned char fua : 1;
unsigned char dpo : 1;
unsigned char protect : 3;
};
unsigned char option;
};
struct ps3_scsi_io_attr {
unsigned char is_retry_cmd;
unsigned char direct_flag;
unsigned char seq_flag;
unsigned char dev_type;
union {
struct {
unsigned char rw_flag : 7;
unsigned char is_confilct_check : 1;
};
unsigned char rw_type;
};
unsigned int num_blocks;
unsigned int lba_lo;
unsigned int lba_hi;
const struct ps3_pd_entry *pd_entry;
const struct ps3_pd_entry *peer_pd_entry;
const struct PS3VDEntry *vd_entry;
unsigned long long plba;
unsigned long long plba_back;
unsigned char span_idx;
unsigned char span_pd_idx;
unsigned short disk_id;
unsigned char is_use_frontend_prp;
unsigned char span_pd_idx_p;
unsigned char span_pd_idx_q;
unsigned char is_force_normal : 1;
unsigned char reserved : 7;
union ps3_scsi_cdb_option cdb_opts;
unsigned char cdb[PS3_FRAME_CDB_BUFLEN];
unsigned int sgl_buf_len;
unsigned int reserved1;
};
struct ps3_ioctl_transient {
unsigned short sge_num;
unsigned char reserved[6];
void *transient_buff[PS3_MAX_IOCTL_SGE_NUM];
};
#define PS3_QOS_MAX_PD_IN_VD (17)
struct ps3_qos_member_pd_info {
unsigned short flat_disk_id;
unsigned short strip_count;
unsigned char get_quota;
};
#define PS3_QOS_MAX_CMDQ_ONE_CMD 2
struct ps3_qos_cmdq_info {
unsigned char que_id;
unsigned char get_rc;
};
struct ps3_cmd {
union PS3ReqFrame *req_frame;
unsigned long long req_frame_phys;
void *ext_buf;
unsigned long long ext_buf_phys;
union PS3RespFrame *resp_frame;
unsigned long long resp_frame_phys;
struct ps3_instance *instance;
union {
struct PS3CmdWord cmd_word;
struct PS3InitCmdWord init_cmd_word;
unsigned long long cmd_word_value;
};
struct scsi_cmnd *scmd;
#ifndef _WINDOWS
struct list_head cmd_list;
#else
SCSI_REQUEST_BLOCK * srb;
struct list_head cmd_list;
#endif
unsigned long long trace_id;
unsigned short index;
unsigned char no_reply_word;
unsigned char is_force_polling;
unsigned char is_got_r1x;
unsigned char is_inserted_c_q;
unsigned char is_r1x_aborting;
unsigned char is_r1x_scsi_complete;
unsigned short r1x_read_pd;
struct ps3_cmd *r1x_peer_cmd;
unsigned char is_aborting;
unsigned char r1x_reply_flag;
unsigned char qos_processing;
unsigned int os_sge_map_count;
struct ps3_cmd_state_t cmd_state;
unsigned short time_out;
unsigned char is_interrupt;
unsigned char szblock_cnt;
unsigned int retry_cnt;
void *node_buff;
#ifdef _WINDOWS
KEVENT sync_done;
#else
struct completion sync_done;
#endif
int (*cmd_send_cb)(struct ps3_instance *, struct ps3_cmd *,
unsigned short);
int (*cmd_receive_cb)(struct ps3_cmd *cmd, unsigned short reply_flags);
struct ps3_ioctl_transient *transient;
struct ps3_scsi_io_attr io_attr;
#ifdef _WINDOWS
struct scsi_cmnd scmd_imp;
#endif
struct PS3ReplyWord reply_word;
struct list_head qos_list;
struct ps3_qos_member_pd_info target_pd[PS3_QOS_MAX_PD_IN_VD];
struct ps3_qos_cmdq_info cmdq_info[PS3_QOS_MAX_CMDQ_ONE_CMD];
unsigned short target_pd_count;
unsigned short first_over_quota_pd_idx;
unsigned char qos_waitq_flag;
unsigned char cmdq_count;
unsigned char flighting;
};
struct ps3_cmd_context {
unsigned int max_cmd_count;
unsigned int max_scsi_cmd_count;
unsigned int max_mgr_cmd_count;
unsigned int max_prp_count;
struct ps3_cmd **cmd_buf;
dma_addr_t init_frame_buf_phys;
unsigned char *init_frame_buf;
dma_addr_t init_filter_table_phy_addr;
unsigned char *init_filter_table_buff;
#ifndef _WINDOWS
struct dma_pool *req_frame_dma_pool;
#endif
unsigned int req_frame_buf_size;
dma_addr_t req_frame_buf_phys;
unsigned char *req_frame_buf;
#ifndef _WINDOWS
struct dma_pool *response_frame_dma_pool;
#endif
unsigned int response_frame_buf_size;
dma_addr_t response_frame_buf_phys;
unsigned char *response_frame_buf;
#ifndef _WINDOWS
struct dma_pool *ext_buf_dma_pool;
#endif
unsigned int ext_buf_size;
unsigned int ext_sge_frame_count;
#ifndef _WINDOWS
struct dma_pool *mgr_ext_buf_dma_pool;
#endif
unsigned int mgr_ext_buf_size;
dma_addr_t init_frame_sys_info_phys;
unsigned char *init_frame_sys_info_buf;
unsigned char sgl_mode_support;
unsigned char reserved0[1];
unsigned short max_host_sge_count;
#ifndef _WINDOWS
struct list_head mgr_cmd_pool;
struct list_head task_cmd_pool;
struct list_head r1x_scsi_cmd_pool;
spinlock_t mgr_pool_lock;
spinlock_t task_pool_lock;
spinlock_t r1x_scsi_pool_lock;
#else
struct list_head mgr_cmd_pool;
struct list_head task_cmd_pool;
struct list_head scsi_cmd_pool;
spinlock_t mgr_pool_lock;
spinlock_t task_pool_lock;
spinlock_t scsi_pool_lock;
atomic64_t trace_id;
#endif
unsigned short max_r1x_cmd_count;
unsigned char reserved1[6];
};
int ps3_cmd_context_init(struct ps3_instance *instance);
void ps3_cmd_context_exit(struct ps3_instance *instance);
#ifndef _WINDOWS
struct ps3_cmd *ps3_scsi_cmd_alloc(struct ps3_instance *instance,
unsigned int tag);
#else
struct ps3_cmd *ps3_scsi_cmd_alloc(struct ps3_instance *instance);
#endif
int ps3_scsi_cmd_free(struct ps3_cmd *cmd);
struct ps3_cmd *ps3_mgr_cmd_alloc(struct ps3_instance *instance);
int ps3_mgr_cmd_free_nolock(struct ps3_instance *instance, struct ps3_cmd *cmd);
int ps3_mgr_cmd_free(struct ps3_instance *instance, struct ps3_cmd *cmd);
struct ps3_cmd *ps3_task_cmd_alloc(struct ps3_instance *instance);
int ps3_task_cmd_free(struct ps3_instance *instance, struct ps3_cmd *cmd);
int ps3_reply_cmd_dispatcher(struct ps3_instance *instance,
unsigned short cmd_frame_id);
int ps3_async_cmd_send(struct ps3_instance *instance, struct ps3_cmd *cmd);
#ifndef _WINDOWS
int ps3_scsi_cmd_send(struct ps3_instance *instance, struct ps3_cmd *cmd,
unsigned char need_prk_err);
#endif
struct ps3_cmd *ps3_cmd_find(struct ps3_instance *instance,
unsigned short cmd_frame_id);
int ps3_cmd_dispatch(struct ps3_instance *instance, unsigned short cmd_frame_id,
struct PS3ReplyWord *reply_word);
struct ps3_cmd *ps3_r1x_peer_cmd_alloc(struct ps3_instance *instance,
unsigned int index);
unsigned char ps3_r1x_peer_cmd_free_nolock(struct ps3_cmd *cmd);
static inline unsigned short ps3_cmd_frame_id(struct ps3_cmd *cmd)
{
return cmd->index;
}
static inline unsigned long long ps3_cmd_trace_id(struct ps3_cmd *cmd)
{
return cmd->trace_id;
}
static inline void ps3_cmd_trace_id_replace(struct ps3_cmd *cmd,
unsigned long long trace_id)
{
cmd->trace_id = trace_id;
}
unsigned char
ps3_is_instance_state_allow_cmd_execute(struct ps3_instance *instance);
int ps3_cmd_send_pre_check(struct ps3_instance *instance);
void ps3_wait_scsi_cmd_done(struct ps3_instance *instance,
unsigned char time_out);
void ps3_scsi_cmd_deliver_get(struct ps3_instance *instance);
void ps3_scsi_cmd_deliver_put(struct ps3_instance *instance);
void ps3_dma_addr_bit_pos_update(struct ps3_instance *instance,
unsigned char bit_pos);
unsigned char ps3_bit_pos_update(struct ps3_instance *instance);
void ps3_wait_mgr_cmd_done(struct ps3_instance *instance,
unsigned char time_out);
int ps3_mgr_cmd_send_pre_check(struct ps3_instance *instance,
unsigned char no_check);
int ps3_mgr_cmd_send_check(struct ps3_instance *instance, struct ps3_cmd *cmd);
#endif

View File

@ -0,0 +1,363 @@
// SPDX-License-Identifier: GPL-2.0
#ifdef _WINDOWS
#else
#include <linux/irqreturn.h>
#include <linux/types.h>
#include <linux/jiffies.h>
#include <linux/spinlock.h>
#include <linux/limits.h>
#include <linux/delay.h>
#include <linux/compiler.h>
#endif
#include "ps3_cmd_complete.h"
#include "ps3_cmd_channel.h"
#include "ps3_driver_log.h"
#include "ps3_err_def.h"
#include "ps3_ioc_state.h"
#include "ps3_ioc_manager.h"
#include "ps3_scsi_cmd_err.h"
static inline unsigned char ps3_reply_word_is_valid(unsigned long long val);
static inline void ps3_reply_word_next(struct ps3_irq *irq,
struct PS3ReplyWord **reply_word);
static int ps3_reply_fifo_traverse(struct ps3_irq *irq,
struct ps3_instance *instance,
struct PS3ReplyWord *reply_word,
int *completed_count);
static inline struct PS3ReplyWord *ps3_reply_word_query(struct ps3_irq *irq,
unsigned short idx);
int ps3_cmd_complete(struct ps3_irq *irq)
{
int ret = PS3_SUCCESS;
int completed_count = 0;
struct PS3ReplyWord *reply_word = NULL;
struct ps3_instance *instance = irq->instance;
int cur_state = PS3_INSTANCE_STATE_INIT;
#ifndef _WINDOWS
LOG_DEBUG(
"hno:%u start isr_os:%d, name:%s sn:%d, en:%d, poll:%d, last_reply_idx:%d, is_busy:%d\n",
PS3_HOST(irq->instance), irq->irqNo, irq->name, irq->isrSN,
irq->is_enable_irq, irq->is_sched_irq_poll,
irq->last_reply_idx, atomic_read(&irq->is_busy));
#else
LOG_DEBUG("hno:%u start isr_os:%d, name:%s isr_sn:%d, last_reply_idx:%d, is_busy:%d\n",
PS3_HOST(irq->instance), irq->irqNo, irq->name, irq->isrSN,
irq->last_reply_idx, ps3_atomic_read(&irq->is_busy));
#endif
cur_state = ps3_atomic_read(&instance->state_machine.state);
if (unlikely(cur_state == PS3_INSTANCE_STATE_QUIT)) {
LOG_WARN_IN_IRQ(instance, "hno:%u instance state is quit\n",
PS3_HOST(instance));
ret = -PS3_FAILED;
goto l_out;
}
if (!ps3_irq_busy_add(irq)) {
LOG_INFO_IN_IRQ(instance, "hno:%u irq is_busy:%d\n",
PS3_HOST(instance),
ps3_atomic_read(&irq->is_busy));
goto l_out;
}
reply_word = ps3_reply_word_query(irq, irq->last_reply_idx);
if (!ps3_reply_word_is_valid(*(unsigned long long *)reply_word)) {
ps3_irq_busy_dec(irq);
LOG_DEBUG("hno:%u reply_w:0x%llx last_reply_idx:%d\n",
PS3_HOST(instance), *(unsigned long long *)reply_word,
irq->last_reply_idx);
goto l_out;
}
ret = ps3_reply_fifo_traverse(irq, instance, reply_word,
&completed_count);
if (ret == -PS3_IN_IRQ_POLLING) {
ps3_irq_busy_dec(irq);
LOG_DEBUG("hno:%u reply in irq polling:%d\n",
PS3_HOST(instance), ret);
goto l_out;
}
if (completed_count != 0) {
wmb(); /* in order to force CPU ordering */
#ifndef _WINDOWS
ps3_can_queue_depth_update(instance);
#endif
}
ps3_irq_busy_dec(irq);
#ifndef _WINDOWS
LOG_DEBUG(
"hno:%u end isr_os:%d, name:%s sn:%d, en:%d, poll:%d, lastidx:%d, count:%d, is_busy:%d\n",
PS3_HOST(instance), irq->irqNo, irq->name, irq->isrSN,
irq->is_enable_irq, irq->is_sched_irq_poll, irq->last_reply_idx,
completed_count, atomic_read(&irq->is_busy));
#else
LOG_DEBUG(
"hno:%u end isr_os:%d, name:%s sn:%d, irq_enable:%d, complete_count:%d, is_busy:%d\n",
PS3_HOST(instance), irq->irqNo, irq->name, irq->isrSN,
irq->last_reply_idx, completed_count,
ps3_atomic_read(&irq->is_busy));
#endif
l_out:
return completed_count;
}
static inline struct PS3ReplyWord *ps3_reply_word_query(struct ps3_irq *irq,
unsigned short idx)
{
return irq->reply_fifo_virt_base_addr + idx;
}
static inline unsigned char ps3_reply_word_is_valid(unsigned long long val)
{
unsigned long long type = val & U64_MAX;
return (type != U64_MAX);
}
static inline void ps3_reply_word_next(struct ps3_irq *irq,
struct PS3ReplyWord **reply_word)
{
if (!irq->last_reply_idx)
*reply_word = ps3_reply_word_query(irq, irq->last_reply_idx);
else
++(*reply_word);
}
#ifndef _WINDOWS
void ps3_trigger_irq_poll(struct ps3_irq *irq)
{
LOG_DEBUG("host_no:%u trigger irq_poll isrSN:%d\n",
PS3_HOST(irq->instance), irq->isrSN);
if (irq->is_sched_irq_poll) {
LOG_DEBUG("host_no:%u irq_poll_is_processing is PS3_TRUE\n",
PS3_HOST(irq->instance));
goto l_out;
}
irq->is_sched_irq_poll = PS3_TRUE;
irq->is_enable_irq = PS3_TRUE;
ps3_irq_poll_sched(&irq->irqpoll);
l_out:
return;
}
void ps3_can_queue_depth_update(struct ps3_instance *instance)
{
unsigned long flag = 0;
unsigned long time_threahold = 5;
int old_host_can_que = 0;
if (instance->fault_context.ioc_busy &&
time_after(jiffies, instance->fault_context.last_time +
time_threahold * HZ) &&
(atomic_read(&instance->cmd_statistics.io_outstanding) <
(instance->cmd_attr.throttle_que_depth + 1))) {
instance->fault_context.ioc_busy = PS3_FALSE;
spin_lock_irqsave(instance->host->host_lock, flag);
old_host_can_que = instance->host->can_queue;
instance->host->can_queue = instance->cmd_attr.cur_can_que;
spin_unlock_irqrestore(instance->host->host_lock, flag);
LOG_INFO(
"hno:%u old_can_queue:%d, cur_can_que:%d, ioc_busy:%d.\n",
PS3_HOST(instance), old_host_can_que,
instance->cmd_attr.cur_can_que,
instance->fault_context.ioc_busy);
}
}
#endif
static int ps3_reply_fifo_traverse(struct ps3_irq *irq,
struct ps3_instance *instance,
struct PS3ReplyWord *reply_word,
int *completed_count)
{
int ret = PS3_SUCCESS;
unsigned int reply_threshold_count = 0;
unsigned long long *r_word = NULL;
static unsigned short reply_word_size = sizeof(struct PS3ReplyWord);
while (ps3_reply_word_is_valid(*(unsigned long long *)reply_word)) {
r_word = (unsigned long long *)reply_word;
LOG_DEBUG(
"hno:%u CFID:%d reply_word:0x%llx reply_f:%d reply_mode:%d rettype:%d\n",
PS3_HOST(instance), le16_to_cpu(reply_word->cmdFrameID),
*r_word, reply_word->retStatus, reply_word->mode,
reply_word->retType);
ret = ps3_cmd_dispatch(instance,
le16_to_cpu(reply_word->cmdFrameID),
reply_word);
if (unlikely(ret != PS3_SUCCESS)) {
LOG_ERROR_IN_IRQ(
instance,
"host_no:%u CFID:%d dispatch cmd fail\n",
PS3_HOST(instance),
le16_to_cpu(reply_word->cmdFrameID));
}
memset(reply_word, 0xff, reply_word_size);
++(irq->last_reply_idx);
if (irq->last_reply_idx >=
instance->irq_context.reply_fifo_depth) {
LOG_DEBUG("last_reply_idx = %d, depth=%d\n",
irq->last_reply_idx,
instance->irq_context.reply_fifo_depth);
irq->last_reply_idx = 0;
}
if (((++(*completed_count)) & (PS3_QOS_NOTIFY_CMD_COUNT - 1)) ==
0) {
ps3_qos_waitq_notify(instance);
}
++reply_threshold_count;
ps3_reply_word_next(irq, &reply_word);
if (!ps3_reply_word_is_valid(*(unsigned long long *)reply_word))
break;
#ifndef _WINDOWS
#ifdef CONFIG_IRQ_POLL
if (reply_threshold_count >= irq->irq_poll_sched_threshold) {
reply_threshold_count = 0;
wmb(); /* in order to force CPU ordering */
ps3_trigger_irq_poll(irq);
ret = -PS3_IN_IRQ_POLLING;
break;
}
#endif
#endif
}
if (((*completed_count) & (PS3_QOS_NOTIFY_CMD_COUNT - 1)) > 0)
ps3_qos_waitq_notify(instance);
return ret;
}
int ps3_resp_status_convert(unsigned int resp_status)
{
int ret = PS3_SUCCESS;
switch (resp_status) {
case U8_MAX:
ret = -PS3_TIMEOUT;
break;
case SCSI_STATUS_GOOD:
ret = PS3_SUCCESS;
break;
default:
ret = -PS3_RESP_ERR;
break;
}
return ret;
}
int ps3_cmd_reply_polling(struct ps3_instance *instance, struct ps3_cmd *cmd,
unsigned long timeout, unsigned char ignore)
{
const unsigned int seconds_to_msecs_unit = 1000;
const unsigned int step_size = 20;
const unsigned int read_fw_satus_period = 5000;
unsigned int local_resp_status = U8_MAX;
unsigned int msecs = U32_MAX;
unsigned int i = 0;
unsigned long flags = 0;
unsigned int time_out;
int cur_state = PS3_INSTANCE_STATE_INIT;
time_out = max_t(unsigned long, cmd->time_out, timeout);
if (time_out != 0)
msecs = time_out * seconds_to_msecs_unit;
for (i = 0;
(i < msecs) && (cmd->resp_frame->normalRespFrame.respStatus ==
PS3_SCSI_STATUS_MASK);
i += step_size) {
rmb(); /* in order to force CPU ordering */
ps3_msleep(step_size);
if (i % read_fw_satus_period)
continue;
if (ignore) {
cur_state =
ps3_atomic_read(&instance->state_machine.state);
if (cur_state == PS3_INSTANCE_STATE_DEAD)
break;
} else {
if (!ps3_is_instance_state_allow_cmd_execute(
instance)) {
break;
}
}
}
local_resp_status =
le32_to_cpu(cmd->resp_frame->normalRespFrame.respStatus);
LOG_DEBUG("host_no:%u CFID:%d, respStatus:0x%x\n", PS3_HOST(instance),
cmd->index, local_resp_status);
if (local_resp_status != U8_MAX) {
ps3_spin_lock_irqsave(&cmd->cmd_state.lock, &flags);
cmd->cmd_state.state = PS3_CMD_STATE_COMPLETE;
ps3_spin_unlock_irqrestore(&cmd->cmd_state.lock, flags);
}
return ps3_resp_status_convert(local_resp_status);
}
int ps3_cmd_reply_polling_when_recovery(struct ps3_instance *instance,
struct ps3_cmd *cmd,
unsigned long timeout)
{
const unsigned int seconds_to_msecs_unit = 1000;
const unsigned int step_size = 20;
const unsigned int read_fw_satus_period = 5000;
unsigned int local_resp_status = U8_MAX;
unsigned int msecs = U32_MAX;
unsigned int i = 0;
unsigned long flags = 0;
unsigned int time_out;
time_out = max_t(unsigned long, cmd->time_out, timeout);
if (time_out != 0)
msecs = time_out * seconds_to_msecs_unit;
for (i = 0;
(i < msecs) && (cmd->resp_frame->normalRespFrame.respStatus ==
PS3_SCSI_STATUS_MASK);
i += step_size) {
rmb(); /* in order to force CPU ordering */
ps3_msleep(step_size);
if (i % read_fw_satus_period)
continue;
}
local_resp_status =
le32_to_cpu(cmd->resp_frame->normalRespFrame.respStatus);
LOG_DEBUG("host_no:%u CFID:%d, respStatus:0x%x\n", PS3_HOST(instance),
cmd->index, local_resp_status);
if (local_resp_status != U8_MAX) {
ps3_spin_lock_irqsave(&cmd->cmd_state.lock, &flags);
cmd->cmd_state.state = PS3_CMD_STATE_COMPLETE;
ps3_spin_unlock_irqrestore(&cmd->cmd_state.lock, flags);
}
return ps3_resp_status_convert(local_resp_status);
}
void ps3_all_reply_fifo_complete(struct ps3_instance *instance)
{
unsigned int i = 0;
if (instance->irq_context.irqs == NULL)
return;
for (; i < instance->irq_context.valid_msix_vector_count; ++i)
(void)ps3_cmd_complete(instance->irq_context.irqs + i);
}

View File

@ -0,0 +1,23 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef _PS3_CMD_COMPLETE_H_
#define _PS3_CMD_COMPLETE_H_
#include "ps3_htp_def.h"
#include "ps3_irq.h"
#include "ps3_instance_manager.h"
#include "ps3_inner_data.h"
int ps3_cmd_complete(struct ps3_irq *irq);
int ps3_cmd_reply_polling(struct ps3_instance *instance, struct ps3_cmd *cmd,
unsigned long timeout, unsigned char ignore);
int ps3_cmd_reply_polling_when_recovery(struct ps3_instance *instance,
struct ps3_cmd *cmd,
unsigned long timeout);
void ps3_all_reply_fifo_complete(struct ps3_instance *instance);
void ps3_can_queue_depth_update(struct ps3_instance *instance);
#endif

View File

@ -0,0 +1,189 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef _PS3_CMD_STAT_DEF_H_
#define _PS3_CMD_STAT_DEF_H_
#ifndef _WINDOWS
#include <linux/workqueue.h>
#include <linux/mutex.h>
#else
#include "ps3_worker.h"
#endif
#include "ps3_htp_def.h"
#ifdef __cplusplus
extern "C" {
#endif
struct ps3_instance;
enum {
PS3_STAT_LOG_COUNT = 0,
PS3_STAT_LOG_MAX_COUNT = 10,
PS3_STAT_START = 0,
PS3_STAT_BACK = 1,
PS3_STAT_WROKQ_NAME_MAX_LEN = 16,
PS3_STAT_WORKQ_INTERVAL_DEFAULT = 5000,
};
enum ps3_cmd_stat_item {
PS3_SCSI_DRV_READ,
PS3_SCSI_DRV_WRITE,
PS3_SCSI_DRV_NORW,
PS3_SCSI_DRV_ALL,
PS3_DRV_IOC_READ,
PS3_DRV_IOC_WRITE,
PS3_DRV_IOC_NORW,
PS3_DRV_IOC_ALL,
PS3_DRV_IOC_VD_READ,
PS3_DRV_IOC_VD_WRITE,
PS3_DRV_IOC_VD_NORW,
PS3_DRV_IOC_PD_READ,
PS3_DRV_IOC_PD_WRITE,
PS3_DRV_IOC_PD_NORW,
PS3_DRV_IOC_VD_D_READ,
PS3_DRV_IOC_VD_D_WRITE,
PS3_DRV_IOC_PD_D_READ,
PS3_DRV_IOC_PD_D_WRITE,
PS3_DRV_IOC_MGR,
PS3_SCSI_ABORT,
PS3_SCSI_DEVICE_RESET,
PS3_SCSI_RETRY_CMD,
PS3_QOS_PD_PRO,
PS3_QOS_VD_PRO,
PS3_QOS_TAG_PRO,
PS3_QOS_MGR_PRO,
PS3_QOS_CMD_PRO,
PS3_QOS_PD_QUEUE,
PS3_QOS_VD_QUEUE,
PS3_QOS_TAG_QUEUE,
PS3_QOS_MGR_QUEUE,
PS3_QOS_CMD_QUEUE,
PS3_CMD_STAT_COUNT,
};
static inline const char *
ps3_cmd_stat_item_tostring(enum ps3_cmd_stat_item type)
{
static const char * const itme_string[] = {
[PS3_SCSI_DRV_READ] = "scsi_drv_read",
[PS3_SCSI_DRV_WRITE] = "scsi_drv_write",
[PS3_SCSI_DRV_NORW] = "scsi_drv_norw",
[PS3_SCSI_DRV_ALL] = "scsi_drv_all",
[PS3_DRV_IOC_READ] = "scsi_drv_ioc_read",
[PS3_DRV_IOC_WRITE] = "scsi_drv_ioc_write",
[PS3_DRV_IOC_NORW] = "scsi_drv_ioc_norw",
[PS3_DRV_IOC_ALL] = "scsi_drv_ioc_all",
[PS3_DRV_IOC_VD_READ] = "scsi_drv_ioc_vd_read",
[PS3_DRV_IOC_VD_WRITE] = "scsi_drv_ioc_vd_write",
[PS3_DRV_IOC_VD_NORW] = "scsi_drv_ioc_vd_norw",
[PS3_DRV_IOC_PD_READ] = "scsi_drv_ioc_pd_read",
[PS3_DRV_IOC_PD_WRITE] = "scsi_drv_ioc_pd_write",
[PS3_DRV_IOC_PD_NORW] = "scsi_drv_ioc_pd_norw",
[PS3_DRV_IOC_VD_D_READ] = "scsi_drv_ioc_vd_d_read",
[PS3_DRV_IOC_VD_D_WRITE] = "scsi_drv_ioc_vd_d_write",
[PS3_DRV_IOC_PD_D_READ] = "scsi_drv_ioc_pd_d_read",
[PS3_DRV_IOC_PD_D_WRITE] = "scsi_drv_ioc_pd_d_write",
[PS3_DRV_IOC_MGR] = "mgr_drv_ioc_cmd",
[PS3_SCSI_ABORT] = "task_abort",
[PS3_SCSI_DEVICE_RESET] = "task_reset",
[PS3_SCSI_RETRY_CMD] = "scsi_retry_cmd",
[PS3_QOS_PD_PRO] = "qos_pd_pro",
[PS3_QOS_VD_PRO] = "qos_vd_pro",
[PS3_QOS_TAG_PRO] = "qos_tag_pro",
[PS3_QOS_MGR_PRO] = "qos_mgr_pro",
[PS3_QOS_CMD_PRO] = "qos_cmd_pro",
[PS3_QOS_PD_QUEUE] = "qos_pd_queue",
[PS3_QOS_VD_QUEUE] = "qos_vd_queue",
[PS3_QOS_TAG_QUEUE] = "qos_tag_queue",
[PS3_QOS_MGR_QUEUE] = "qos_mgr_queue",
[PS3_QOS_CMD_QUEUE] = "qos_cmd_queue",
[PS3_CMD_STAT_COUNT] = "type_unknown",
};
return (type >= PS3_CMD_STAT_COUNT) ? "type_unknown" :
itme_string[type];
}
struct ps3_lagency_info {
unsigned long long start_time;
unsigned long long back_time;
unsigned long long avg;
unsigned long long max_lagency;
unsigned long long min_lagency;
unsigned long long all;
};
struct ps3_cmd_stat_entry {
unsigned long long start;
unsigned long long back_good;
unsigned long long back_err;
unsigned long long not_back;
struct ps3_lagency_info lagency;
};
struct ps3_total_cmd_stat {
struct ps3_cmd_stat_entry stat[PS3_CMD_STAT_COUNT];
};
enum ps3_cmd_stat_back_flag {
PS3_STAT_BACK_OK,
PS3_STAT_BACK_FAIL,
PS3_STAT_BACK_NO = 0xFF,
};
struct ps3_single_cmd_stat {
struct ps3_cmd_stat_entry stat[PS3_CMD_STAT_COUNT];
};
enum ps3_cmd_stat_switch_flag {
PS3_STAT_ALL_SWITCH_CLOSE = 0x00,
PS3_STAT_OUTSTAND_SWITCH_OPEN = 0x01,
PS3_STAT_INC_SWITCH_OPEN = 0x02,
PS3_STAT_LOG_SWITCH_OPEN = 0x04,
PS3_STAT_DEV_SWITCH_OPEN = 0x08,
PS3_STAT_QOS_SWITCH_OPEN = 0x10,
PS3_STAT_ALL_SWITCH_OPEN =
(PS3_STAT_OUTSTAND_SWITCH_OPEN | PS3_STAT_INC_SWITCH_OPEN |
PS3_STAT_LOG_SWITCH_OPEN | PS3_STAT_DEV_SWITCH_OPEN |
PS3_STAT_QOS_SWITCH_OPEN),
};
struct ps3_cmd_stat_wrokq_context {
#ifndef _WINDOWS
struct delayed_work stat_work;
struct workqueue_struct *stat_queue;
struct ps3_instance *instance;
#else
struct ps3_delay_worker statis_work;
#endif
unsigned char is_stop;
};
struct ps3_cmd_statistics_context {
atomic_t cmd_outstanding;
atomic_t io_outstanding;
atomic_t vd_io_outstanding;
atomic_t cmd_delivering;
atomic_t scsi_cmd_delivering;
atomic64_t cmd_word_send_count;
struct ps3_total_cmd_stat total_stat;
struct ps3_total_cmd_stat inc_stat;
struct ps3_single_cmd_stat **cmd_stat_backup_buf;
struct ps3_single_cmd_stat **last_stat_buf;
struct ps3_single_cmd_stat **cmd_stat_buf;
unsigned int stat_entry_max_count;
unsigned int stat_interval;
struct ps3_cmd_stat_wrokq_context stat_workq;
unsigned char cmd_stat_switch;
unsigned char log_record_count;
atomic_t cli_cnt;
atomic_t cmd_qos_processing;
atomic64_t cmd_qos_total;
unsigned char reserved2[2];
};
#ifdef __cplusplus
}
#endif
#endif

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,412 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef _PS3_CMD_STATICTIS_H_
#define _PS3_CMD_STATICTIS_H_
#ifndef _WINDOWS
#include <linux/mutex.h>
#include <linux/limits.h>
#include <scsi/scsi_cmnd.h>
#endif
#include "ps3_htp_def.h"
#include "ps3_scsih_cmd_parse.h"
#include "ps3_instance_manager.h"
#include "ps3_cmd_channel.h"
#include "ps3_platform_utils.h"
#include "ps3_scsih.h"
#ifdef __cplusplus
extern "C" {
#endif
#define PS3_CMD_STAT_INIT_VALUE (0)
#define PS3_CMD_WORD_INDEX_SHIFT (0x000000FF)
void ps3_dev_io_statis_init(struct ps3_dev_io_statis *statis);
void ps3_io_statis_inc(struct scsi_device *sdev,
enum ps3_dev_io_stat_type type);
void ps3_io_statis_dec(struct scsi_device *sdev,
enum ps3_dev_io_stat_type type);
void ps3_io_statis_clear(struct scsi_device *sdev);
int ps3_cmd_statistics_init(struct ps3_instance *instance);
void ps3_cmd_statistics_exit(struct ps3_instance *instance);
void ps3_dev_io_start_inc(struct ps3_instance *instance,
const struct ps3_cmd *cmd);
void ps3_dev_io_start_err_inc(struct ps3_instance *instance,
const struct ps3_cmd *cmd);
void ps3_dev_io_start_ok_inc(struct ps3_instance *instance,
const struct ps3_cmd *cmd);
void ps3_dev_io_back_inc(struct ps3_instance *instance,
const struct ps3_cmd *cmd, unsigned char status);
static inline void ps3_dev_scsi_err_stat_inc(struct ps3_cmd *cmd)
{
if (ps3_scsih_is_read_cmd(cmd->io_attr.rw_flag)) {
ps3_io_statis_inc(cmd->scmd->device,
PS3_DEV_IO_STAT_TYPE_R_RECV_ERR);
} else if (ps3_scsih_is_write_cmd(cmd->io_attr.rw_flag)) {
ps3_io_statis_inc(cmd->scmd->device,
PS3_DEV_IO_STAT_TYPE_W_RECV_ERR);
}
}
static inline unsigned char ps3_is_vd_rw_cmd(const struct scsi_cmnd *s_cmd)
{
return (PS3_SDEV_PRI_DATA(s_cmd->device)->dev_type ==
PS3_DEV_TYPE_VD) &&
ps3_scsih_cdb_is_rw_cmd(s_cmd->cmnd);
}
static inline unsigned char ps3_is_read_cmd(const struct scsi_cmnd *s_cmd)
{
return ps3_scsih_cdb_is_read_cmd(s_cmd->cmnd);
}
static inline unsigned char ps3_is_write_cmd(const struct scsi_cmnd *s_cmd)
{
return ps3_scsih_cdb_is_write_cmd(s_cmd->cmnd);
}
void ps3_io_outstand_inc(struct ps3_instance *instance,
const struct ps3_cmd *cmd);
void ps3_io_outstand_dec(struct ps3_instance *instance,
const struct scsi_cmnd *s_cmd);
void ps3_vd_outstand_dec(struct ps3_instance *instance,
const struct scsi_cmnd *s_cmd);
void ps3_vd_outstand_inc(struct ps3_instance *instance,
const struct scsi_cmnd *s_cmd);
void ps3_dev_io_outstand_dec(const struct ps3_cmd *cmd);
void ps3_dev_io_qos_inc(struct ps3_scsi_priv_data *priv_data);
void ps3_dev_io_qos_dec(struct ps3_scsi_priv_data *priv_data);
void ps3_dev_io_outstand_inc(const struct ps3_cmd *cmd);
void ps3_qos_cmd_inc(struct ps3_instance *instance);
void ps3_qos_stat_inc(struct ps3_instance *instance, struct ps3_cmd *cmd,
unsigned short stat, unsigned short type);
static inline unsigned char
ps3_cmd_word_index_get(struct ps3_instance *instance)
{
unsigned long long cmd_count =
(unsigned long long)ps3_atomic64_inc_return(
&instance->cmd_statistics.cmd_word_send_count);
return (unsigned char)(cmd_count & PS3_CMD_WORD_INDEX_SHIFT);
}
static inline void ps3_cmd_word_stat_inc(struct ps3_instance *instance,
struct PS3CmdWord *cmd_word)
{
(void)cmd_word;
(void)ps3_cmd_word_index_get(instance);
}
#ifndef _WINDOWS
void ps3_scmd_inc(struct ps3_instance *instance, struct scsi_cmnd *s_cmd,
unsigned char type, unsigned char status);
#else
void ps3_scmd_inc(struct ps3_instance *instance, const struct scsi_cmnd *s_cmd,
unsigned int tag, unsigned char type, unsigned char status);
#endif
void ps3_scmd_drv2ioc_start_inc(struct ps3_instance *instance,
const struct ps3_cmd *cmd);
void ps3_scmd_drv2ioc_back_inc(struct ps3_instance *instance,
const struct ps3_cmd *cmd, unsigned char status);
static inline unsigned char
ps3_resp_stauts_to_stat_status(unsigned char reply_flags)
{
return (reply_flags == PS3_REPLY_WORD_FLAG_SUCCESS) ?
(unsigned char)PS3_STAT_BACK_OK :
(unsigned char)PS3_STAT_BACK_FAIL;
}
void ps3_mgr_start_inc(struct ps3_instance *instance,
const struct ps3_cmd *cmd);
void ps3_mgr_back_inc(struct ps3_instance *instance, const struct ps3_cmd *cmd,
unsigned char status);
void ps3_stat_all_clear(struct ps3_instance *instance);
static inline unsigned char
ps3_stat_inc_switch_is_open(const struct ps3_instance *instance)
{
return (instance->cmd_statistics.cmd_stat_switch &
PS3_STAT_INC_SWITCH_OPEN);
}
static inline unsigned char
ps3_stat_log_switch_is_open(const struct ps3_instance *instance)
{
return (instance->cmd_statistics.cmd_stat_switch &
PS3_STAT_LOG_SWITCH_OPEN);
}
static inline unsigned char
ps3_stat_outstand_switch_is_open(const struct ps3_instance *instance)
{
return (instance->cmd_statistics.cmd_stat_switch &
PS3_STAT_OUTSTAND_SWITCH_OPEN);
}
static inline unsigned char
ps3_stat_dev_switch_is_open(const struct ps3_instance *instance)
{
return (instance->cmd_statistics.cmd_stat_switch &
PS3_STAT_DEV_SWITCH_OPEN);
}
#ifndef _WINDOWS
static inline void ps3_sdev_busy_inc(struct scsi_cmnd *scmd)
{
#if defined DRIVER_SUPPORT_PRIV_BUSY
struct ps3_scsi_priv_data *device_priv_data =
(struct ps3_scsi_priv_data *)scmd->device->hostdata;
if (device_priv_data == NULL)
return;
atomic_inc(&device_priv_data->sdev_priv_busy);
#else
#ifdef PS3_UT
atomic_inc(&scmd->device->device_busy);
#else
(void)scmd;
#endif
#endif
}
static inline void ps3_sdev_busy_dec(struct scsi_cmnd *scmd)
{
#if defined DRIVER_SUPPORT_PRIV_BUSY
struct ps3_scsi_priv_data *device_priv_data =
(struct ps3_scsi_priv_data *)scmd->device->hostdata;
if (device_priv_data == NULL)
return;
atomic_dec(&device_priv_data->sdev_priv_busy);
#else
#ifdef PS3_UT
atomic_dec(&scmd->device->device_busy);
#else
(void)scmd;
#endif
#endif
}
#define PS3_DEV_BUSY_DEC(cmd) ps3_sdev_busy_dec((cmd))
#define PS3_DEV_BUSY_INC(cmd) ps3_sdev_busy_inc((cmd))
#else
#define PS3_DEV_BUSY_DEC(cmd)
#define PS3_DEV_BUSY_INC(cmd)
#endif
static inline unsigned char
ps3_stat_qos_switch_is_open(const struct ps3_instance *instance)
{
return (instance->cmd_statistics.cmd_stat_switch &
PS3_STAT_QOS_SWITCH_OPEN);
}
#define PS3_CMD_WORD_STAT_INC(instance, cmd_word) \
do { \
if (ps3_stat_inc_switch_is_open((instance))) { \
ps3_cmd_word_stat_inc((instance), (cmd_word)); \
} \
} while (0)
#define PS3_DEV_IO_START_OK_INC(instance, cmd) \
do { \
if (ps3_stat_dev_switch_is_open((instance))) { \
ps3_dev_io_start_ok_inc((instance), (cmd)); \
} \
} while (0)
#define PS3_DEV_IO_BACK_INC(instance, cmd, status) \
do { \
if (ps3_stat_dev_switch_is_open((instance))) { \
ps3_dev_io_back_inc((instance), (cmd), (status)); \
} \
} while (0)
#define PS3_DEV_IO_START_ERR_INC(instance, cmd) \
do { \
if (ps3_stat_dev_switch_is_open((instance))) { \
ps3_dev_io_start_err_inc((instance), (cmd)); \
} \
} while (0)
#define PS3_DEV_IO_START_INC(instance, cmd) \
do { \
if (ps3_stat_dev_switch_is_open((instance))) { \
ps3_dev_io_start_inc((instance), (cmd)); \
} \
} while (0)
#ifndef _WINDOWS
#define PS3_IO_BACK_INC(instance, s_cmd, status) \
do { \
if (ps3_stat_inc_switch_is_open((instance))) { \
ps3_scmd_inc( \
(instance), (s_cmd), PS3_STAT_BACK, \
ps3_resp_stauts_to_stat_status((status))); \
} \
} while (0)
#else
#define PS3_IO_BACK_INC(instance, s_cmd, tag, status) \
do { \
if (ps3_stat_inc_switch_is_open((instance))) { \
ps3_scmd_inc( \
(instance), (s_cmd), (tag), PS3_STAT_BACK, \
ps3_resp_stauts_to_stat_status((status))); \
} \
} while (0)
#endif
#define PS3_IO_OUTSTANDING_INC(instance, cmd) ps3_io_outstand_inc(instance, cmd)
#define PS3_DEV_IO_ERR_STAT_INC(instance, cmd) \
do { \
if (ps3_stat_dev_switch_is_open((instance))) { \
ps3_dev_scsi_err_stat_inc((cmd)); \
} \
} while (0)
#ifndef _WINDOWS
#define PS3_IO_START_INC(instance, s_cmd) \
do { \
if (ps3_stat_inc_switch_is_open((instance))) { \
ps3_scmd_inc((instance), (s_cmd), PS3_STAT_START, \
PS3_STAT_BACK_OK); \
} \
} while (0)
#define PS3_IO_BACK_ERR_INC(instance, s_cmd) \
do { \
if (ps3_stat_inc_switch_is_open((instance))) { \
ps3_scmd_inc((instance), (s_cmd), PS3_STAT_BACK, \
PS3_STAT_BACK_FAIL); \
} \
} while (0)
#else
#define PS3_IO_START_INC(instance, s_cmd, tag) \
do { \
if (ps3_stat_inc_switch_is_open((instance))) { \
ps3_scmd_inc((instance), (s_cmd), (tag), \
PS3_STAT_START, PS3_STAT_BACK_OK); \
} \
} while (0)
#define PS3_IO_BACK_ERR_INC(instance, s_cmd, tag) \
do { \
if (ps3_stat_inc_switch_is_open((instance))) { \
ps3_scmd_inc((instance), (s_cmd), (tag), \
PS3_STAT_BACK, PS3_STAT_BACK_FAIL); \
} \
} while (0)
#endif
#define PS3_IO_DRV2IOC_START_INC(instance, cmd) \
do { \
if (ps3_stat_inc_switch_is_open((instance))) { \
ps3_scmd_drv2ioc_start_inc((instance), (cmd)); \
} \
} while (0)
#define PS3_IOC_DRV2IOC_BACK_INC(instance, cmd, status) \
do { \
if (ps3_stat_inc_switch_is_open((instance))) { \
ps3_scmd_drv2ioc_back_inc( \
(instance), (cmd), \
ps3_resp_stauts_to_stat_status((status))); \
} \
} while (0)
#define PS3_MGR_CMD_STAT_INC(instance, cmd) \
do { \
if (ps3_stat_inc_switch_is_open((instance))) { \
ps3_mgr_start_inc((instance), (cmd)); \
} \
} while (0)
#define PS3_MGR_CMD_BACK_INC(instance, cmd, status) \
do { \
if (ps3_stat_inc_switch_is_open((instance))) { \
ps3_mgr_back_inc( \
(instance), (cmd), \
ps3_resp_stauts_to_stat_status((status))); \
} \
} while (0)
#define PS3_IO_OUTSTAND_DEC(instance, s_cmd) \
do { \
if (ps3_stat_outstand_switch_is_open((instance))) { \
ps3_io_outstand_dec((instance), (s_cmd)); \
} \
} while (0)
#define PS3_VD_OUTSTAND_DEC(instance, s_cmd) \
ps3_vd_outstand_dec(instance, s_cmd) \
#define PS3_VD_OUTSTAND_INC(instance, s_cmd) ps3_vd_outstand_inc(instance, s_cmd)
#define PS3_DEV_IO_OUTSTAND_DEC(instance, cmd) \
do { \
if (ps3_stat_dev_switch_is_open((instance))) { \
ps3_dev_io_outstand_dec((cmd)); \
} \
} while (0)
#define PS3_DEV_IO_OUTSTAND_INC(instance, cmd) \
do { \
if (ps3_stat_dev_switch_is_open((instance))) { \
ps3_dev_io_outstand_inc((cmd)); \
} \
} while (0)
#define PS3_QOS_CMD_INC(instance) \
do { \
if (ps3_stat_qos_switch_is_open((instance))) { \
ps3_qos_cmd_inc((instance)); \
} \
} while (0)
#define PS3_QOS_STAT_START(instance, cmd, type) \
do { \
if (ps3_stat_inc_switch_is_open((instance))) { \
ps3_qos_stat_inc((instance), (cmd), (type), \
PS3_STAT_START); \
} \
} while (0)
#define PS3_QOS_STAT_END(instance, cmd, type) \
do { \
if (ps3_stat_inc_switch_is_open((instance))) { \
ps3_qos_stat_inc((instance), (cmd), (type), \
PS3_STAT_BACK); \
} \
} while (0)
int ps3_stat_workq_start(struct ps3_instance *instance);
void ps3_stat_workq_stop(struct ps3_instance *instance);
#ifdef __cplusplus
}
#endif
#endif

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,152 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef _PS3_DEBUG_H_
#define _PS3_DEBUG_H_
#ifndef _WINDOWS
#include <linux/kernel.h>
#include <linux/pci.h>
#include <linux/device.h>
struct ps3_reg_dump_attr {
unsigned long long read_dump_timestamp;
unsigned long long write_dump_timestamp;
unsigned long long read_dump_interval_ms;
unsigned long long write_dump_interval_ms;
unsigned long long lastest_value;
char name[32];
};
struct ps3_debug_context {
unsigned char io_trace_switch;
unsigned char reserved[7];
struct ps3_reg_dump_attr
reg_dump[PS3_REGISTER_SET_SIZE / sizeof(unsigned long long)];
struct Ps3DebugMemEntry debug_mem_vaddr[PS3_DEBUG_MEM_ARRAY_MAX_NUM];
struct Ps3DebugMemEntry *debug_mem_buf;
dma_addr_t debug_mem_buf_phy;
unsigned int debug_mem_array_num;
unsigned char reserved1[4];
};
void ps3_debug_context_init(struct ps3_instance *instance);
void ps3_reg_dump(struct ps3_instance *instance, void __iomem *reg,
unsigned long long value, unsigned char is_read);
ssize_t ps3_vd_io_outstanding_show(struct device *cdev,
struct device_attribute *attr, char *buf);
ssize_t ps3_io_outstanding_show(struct device *cdev,
struct device_attribute *attr, char *buf);
ssize_t ps3_is_load_show(struct device *cdev, struct device_attribute *attr,
char *buf);
ssize_t ps3_dump_ioc_regs_show(struct device *cdev,
struct device_attribute *attr, char *buf);
ssize_t ps3_max_scsi_cmds_show(struct device *cdev,
struct device_attribute *attr, char *buf);
ssize_t ps3_event_subscribe_info_show(struct device *cdev,
struct device_attribute *attr, char *buf);
ssize_t ps3_ioc_state_show(struct device *cdev, struct device_attribute *attr,
char *buf);
ssize_t ps3_log_level_store(struct device *cdev, struct device_attribute *attr,
const char *buf, size_t count);
ssize_t ps3_log_level_show(struct device *cdev, struct device_attribute *attr,
char *buf);
ssize_t ps3_io_trace_switch_store(struct device *cdev,
struct device_attribute *attr,
const char *buf, size_t count);
ssize_t ps3_io_trace_switch_show(struct device *cdev,
struct device_attribute *attr, char *buf);
ssize_t ps3_halt_support_cli_show(struct device *cdev,
struct device_attribute *attr, char *buf);
ssize_t ps3_halt_support_cli_store(struct device *cdev,
struct device_attribute *attr,
const char *buf, size_t count);
#if defined(PS3_SUPPORT_DEBUG) || \
(defined(PS3_CFG_RELEASE) && defined(PS3_CFG_OCM_DBGBUG)) || \
(defined(PS3_CFG_RELEASE) && defined(PS3_CFG_OCM_RELEASE))
#else
ssize_t ps3_irq_prk_support_store(struct device *cdev,
struct device_attribute *attr,
const char *buf, size_t count);
ssize_t ps3_irq_prk_support_show(struct device *cdev,
struct device_attribute *attr, char *buf);
#endif
ssize_t ps3_product_model_show(struct device *cdev,
struct device_attribute *attr, char *buf);
ssize_t ps3_qos_switch_show(struct device *cdev, struct device_attribute *attr,
char *buf);
ssize_t ps3_qos_switch_store(struct device *cdev, struct device_attribute *attr,
const char *buf, size_t count);
#endif
ssize_t ps3_event_subscribe_info_get(struct ps3_instance *instance, char *buf,
ssize_t total_len);
#ifndef _WINDOWS
int ps3_debug_mem_alloc(struct ps3_instance *ins);
int ps3_debug_mem_free(struct ps3_instance *ins);
ssize_t ps3_dump_state_show(struct device *cdev, struct device_attribute *attr,
char *buf);
ssize_t ps3_dump_state_store(struct device *cdev, struct device_attribute *attr,
const char *buf, size_t count);
ssize_t ps3_dump_type_show(struct device *cdev, struct device_attribute *attr,
char *buf);
ssize_t ps3_dump_type_store(struct device *cdev, struct device_attribute *attr,
const char *buf, size_t count);
ssize_t ps3_dump_dir_show(struct device *cdev, struct device_attribute *attr,
char *buf);
void ps3_dma_dump_mapping(struct pci_dev *pdev);
ssize_t ps3_soc_dead_reset_store(struct device *cdev,
struct device_attribute *attr, const char *buf,
size_t count);
#else
struct ps3_reg_dump_attr {
unsigned long long read_dump_timestamp;
unsigned long long write_dump_timestamp;
unsigned long long read_dump_interval_ms;
unsigned long long write_dump_interval_ms;
unsigned long long lastest_value;
char name[32];
};
struct ps3_debug_context {
unsigned char io_trace_switch;
unsigned char reserved[7];
struct ps3_reg_dump_attr
reg_dump[PS3_REGISTER_SET_SIZE / sizeof(unsigned long long)];
struct Ps3DebugMemEntry debug_mem_vaddr[PS3_DEBUG_MEM_ARRAY_MAX_NUM];
struct Ps3DebugMemEntry *debug_mem_buf;
dma_addr_t debug_mem_buf_phy;
unsigned int debug_mem_array_num;
unsigned char reserved1[4];
};
void ps3_debug_context_init(struct ps3_instance *instance);
void ps3_reg_dump(struct ps3_instance *instance, void __iomem *reg,
unsigned long long value, unsigned char is_read);
#endif
#endif

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,563 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef _PS3_DEVICE_MANAGER_H_
#define _PS3_DEVICE_MANAGER_H_
#include "ps3_platform_utils.h"
#ifdef _WINDOWS
#include "ps3_dev_adp.h"
#else
#include <linux/version.h>
#include <linux/workqueue.h>
#include <scsi/scsi_device.h>
#include <linux/completion.h>
#endif
#include "ps3_htp_meta.h"
#include "ps3_htp_dev_info.h"
#include "ps3_htp.h"
#include "ps3_err_def.h"
#include "ps3_kernel_version.h"
#define PS3_QUEUE_DEPTH_DEFAULT (256)
#define PS3_QUEUE_DEPTH_SATA (32)
#define PS3_QUEUE_DEPTH_SAS (64)
#define PS3_QUEUE_DEPTH_NVME (32)
#define PS3_INVALID_VALUE (0)
#define PS3_INVALID_DEV_ID (0)
#define PS3_INVALID_LIST_ID (0)
#define PS3_DMA_ALIGN_SHIFT_MAX (15)
#define PS3_VD_TABLE_NUM (2)
#define PS3_SCSI_4B_ALINNMENT_MASK (4)
#define PS3_SCSI_ALINNMENT_MASK (0x3)
#define PS3_SCSI_32B_ALINNMENT_MASK (0x1f)
#define PS3_SCSI_512B_ALINNMENT_MASK (0x000001FF)
#define PS3_SCSI_4K_ALINNMENT_MASK (0xFFF)
#define PS3_512B_SHIFT (9)
#define PS3_SECTORSIZE_512B (512)
#define PS3_MAX_VD_COUNT(instance) ((instance)->ctrl_info.maxVdCount)
#define PS3_MAX_PD_COUNT(instance) ((instance)->ctrl_info.maxPdCount)
#define PS3_CHANNEL(pos) ((unsigned char)((pos)->diskDev.ps3Dev.softChan))
#define PS3_TARGET(pos) ((unsigned short)((pos)->diskDev.ps3Dev.devID))
#define PS3_DISKID(pos) ((pos)->diskDev.diskID)
#define PS3_PDID(pos) ((pos)->diskDev.ps3Dev.phyDiskID)
#define PS3_VDID(pos) ((pos)->diskDev.ps3Dev.virtDiskID)
#define PS3_DEV(pos) ((struct PS3Dev *)(&(pos)->diskDev.ps3Dev))
#define PS3_VDID_OFFSET(instance) ((instance)->ctrl_info.offsetOfVDID)
#define PS3_DEV_INVALID(pos) ((pos).diskDev.diskID == PS3_INVALID_DEV_ID)
#define PS3_PDID_INVALID(pos) (PS3_PDID(pos) == PS3_INVALID_DEV_ID)
#define PS3_VDID_INVALID(pos) (PS3_VDID(pos) == PS3_INVALID_DEV_ID)
#define PS3_IS_VD_CHANNEL(ins, chan) \
((ins->dev_context.vd_table[0].vd_idxs[chan] != NULL) ? PS3_DRV_TRUE : \
PS3_DRV_FALSE)
#define PS3_IS_PD_CHANNEL(ins, chan) \
((ins->dev_context.pd_table.pd_idxs[chan] != NULL) ? PS3_DRV_TRUE : \
PS3_DRV_FALSE)
#define PS3_MAX_PD_NUM_ONE_VD (PS3_MAX_PD_COUNT_IN_SPAN * PS3_MAX_SPAN_IN_VD)
struct ps3_instance;
#define MR_STREM_BITMAP (0xfedcba9876543210)
#define PS3_IO_MAX_STREAMS_TRACKED (16)
#define BITS_PER_INDEX_STREAM (4)
#define BITS_PER_INDEX_STREAM_SHIFT (2)
#define STREAM_MASK ((1ULL << BITS_PER_INDEX_STREAM) - 1)
#define ZERO_LAST_STREAM (0x0FFFFFFFFFFFFFFF)
#define MAX_QUE_DEPTH (16)
#define TEST_IO_BLOCK_SIZE (8)
#define IO_STREAM_DETECT_RANGE (MAX_QUE_DEPTH * TEST_IO_BLOCK_SIZE)
#define PS3_IS_HAC_LIMIT_TYPE(type) \
((type) == PS3_DEV_TYPE_SAS_HDD || (type) == PS3_DEV_TYPE_SATA_HDD || \
(type) == PS3_DEV_TYPE_SATA_SSD || (type) == PS3_DEV_TYPE_SAS_SSD || \
(type) == PS3_DEV_TYPE_SES)
struct ps3_stream_detect {
unsigned long long next_seq_lba;
unsigned char rw_type;
unsigned char reserved[7];
};
struct ps3_vd_stream_detect {
spinlock_t ps3_sequence_stream_lock;
unsigned long long mru_bit_map;
struct ps3_stream_detect stream_track[PS3_IO_MAX_STREAMS_TRACKED];
};
enum PS3DevType {
PS3_DEV_TYPE_UNKNOWN = 0,
PS3_DEV_TYPE_VD = 1,
PS3_DEV_TYPE_SAS_HDD = 2,
PS3_DEV_TYPE_SATA_HDD = 3,
PS3_DEV_TYPE_SATA_SSD = 4,
PS3_DEV_TYPE_SAS_SSD = 5,
PS3_DEV_TYPE_NVME_SSD = 6,
PS3_DEV_TYPE_SES = 7,
PS3_DEV_TYPE_VEP = 8,
PS3_DEV_TYPE_COUNT,
};
enum PS3DevTypeV1 {
PS3_DEV_TYPE_SAS_SATA = 0,
PS3_DEV_TYPE_NVME = 1,
};
static inline const char *namePS3DevType(enum PS3DevType e)
{
static const char * const myNames[] = {
[PS3_DEV_TYPE_UNKNOWN] = "DEV_T_UNKNOWN",
[PS3_DEV_TYPE_VD] = "DEV_T_VD",
[PS3_DEV_TYPE_SAS_HDD] = "DEV_T_SAS_HDD",
[PS3_DEV_TYPE_SATA_HDD] = "DEV_T_SATA_HDD",
[PS3_DEV_TYPE_SATA_SSD] = "DEV_T_SATA_SSD",
[PS3_DEV_TYPE_SAS_SSD] = "DEV_T_SAS_SSD",
[PS3_DEV_TYPE_NVME_SSD] = "DEV_T_NVME_SSD",
[PS3_DEV_TYPE_SES] = "DEV_T_SES",
[PS3_DEV_TYPE_VEP] = "DEV_T_VEP"
};
return myNames[e];
}
enum ps3_dev_io_stat_type {
PS3_DEV_IO_STAT_TYPE_R_SEND = 1,
PS3_DEV_IO_STAT_TYPE_R_SEND_OK,
PS3_DEV_IO_STAT_TYPE_R_SEND_WAIT,
PS3_DEV_IO_STAT_TYPE_R_SEND_ERR,
PS3_DEV_IO_STAT_TYPE_R_RECV,
PS3_DEV_IO_STAT_TYPE_R_RECV_OK,
PS3_DEV_IO_STAT_TYPE_R_RECV_ERR,
PS3_DEV_IO_STAT_TYPE_R_OK_BYTES,
PS3_DEV_IO_STAT_TYPE_W_SEND,
PS3_DEV_IO_STAT_TYPE_W_SEND_OK,
PS3_DEV_IO_STAT_TYPE_W_SEND_WAIT,
PS3_DEV_IO_STAT_TYPE_W_SEND_ERR,
PS3_DEV_IO_STAT_TYPE_W_RECV,
PS3_DEV_IO_STAT_TYPE_W_RECV_OK,
PS3_DEV_IO_STAT_TYPE_W_RECV_ERR,
PS3_DEV_IO_STAT_TYPE_W_OK_BYTES,
PS3_DEV_IO_STAT_TYPE_MAX,
};
struct ps3_dev_io_statis {
atomic64_t read_send_cnt;
atomic64_t read_send_ok_cnt;
atomic64_t read_send_wait_cnt;
atomic64_t read_send_err_cnt;
atomic64_t read_recv_cnt;
atomic64_t read_recv_ok_cnt;
atomic64_t read_recv_err_cnt;
atomic64_t read_ok_bytes;
atomic64_t write_send_cnt;
atomic64_t write_send_ok_cnt;
atomic64_t write_send_err_cnt;
atomic64_t write_send_wait_cnt;
atomic64_t write_recv_cnt;
atomic64_t write_recv_ok_cnt;
atomic64_t write_recv_err_cnt;
atomic64_t write_ok_bytes;
atomic64_t qos_processing_cnt;
};
static inline unsigned char ps3_disk_type(enum PS3DevType e)
{
unsigned char disk_type = PS3_DISK_TYPE_UNKNOWN;
switch (e) {
case PS3_DEV_TYPE_VD:
disk_type = PS3_DISK_TYPE_VD;
break;
case PS3_DEV_TYPE_SAS_HDD:
case PS3_DEV_TYPE_SATA_HDD:
case PS3_DEV_TYPE_SATA_SSD:
case PS3_DEV_TYPE_SAS_SSD:
case PS3_DEV_TYPE_NVME_SSD:
case PS3_DEV_TYPE_SES:
case PS3_DEV_TYPE_VEP:
disk_type = PS3_DISK_TYPE_PD;
break;
default:
disk_type = PS3_DISK_TYPE_UNKNOWN;
break;
}
return disk_type;
}
static inline unsigned char ps3_is_fake_pd(unsigned char dev_type)
{
return (dev_type == PS3_DEV_TYPE_SES || dev_type == PS3_DEV_TYPE_VEP);
}
struct ps3_r1x_read_balance_info {
atomic_t scsi_outstanding_cmds[PS3_MAX_PD_NUM_ONE_VD + 1];
unsigned long long last_accessed_block[PS3_MAX_PD_NUM_ONE_VD + 1];
};
struct ps3_r1x_lock_mgr {
int (*try_lock)(struct ps3_r1x_lock_mgr *mgr, void *cmd);
int (*resend_try_lock)(struct ps3_r1x_lock_mgr *mgr, void *cmd);
void (*unlock)(struct ps3_r1x_lock_mgr *mgr, void *cmd);
spinlock_t mgr_lock;
void *hash_mgr;
struct list_head conflict_cmd_list;
struct task_struct *conflict_send_th;
void *hash_mgr_conflict;
int force_ret_code;
unsigned int cmd_count_in_q;
unsigned char dev_deling;
unsigned char thread_stop;
#ifdef _WINDOWS
KEVENT thread_sync;
#else
struct completion thread_sync;
#endif
};
struct ps3_scsi_priv_data {
struct PS3DiskDevPos disk_pos;
struct ps3_dev_io_statis statis;
struct ps3_vd_stream_detect vd_sd[2];
struct ps3_r1x_lock_mgr lock_mgr;
struct ps3_r1x_read_balance_info *r1x_rb_info;
unsigned char is_taskmgmt_enable;
unsigned char task_manager_busy;
unsigned char dev_type;
unsigned char task_abort_timeout;
unsigned char task_reset_timeout;
unsigned char encl_id;
unsigned char phy_id;
unsigned char reserved;
atomic_t rd_io_outstand;
atomic_t wr_io_outstand;
atomic_t r1x_read_cmd_swap_total_cnt;
atomic_t r1x_read_cmd_swap_res_cnt;
#if defined DRIVER_SUPPORT_PRIV_BUSY
atomic_t sdev_priv_busy;
#else
unsigned char reserved1[4];
#endif
unsigned long ata_cmd_busy;
unsigned char dev_deling;
unsigned char swap_flag;
unsigned short qmask_count;
unsigned char reserved2[6];
};
#ifdef _WINDOWS
struct scsi_device_real {
struct scsi_device sdev;
struct ps3_scsi_priv_data hostdata;
};
#define PS3_SDEV_PRI_DATA(sdev) \
((struct ps3_scsi_priv_data *)&( \
((struct scsi_device_real *)(sdev))->hostdata))
#define PS3_SDEV_POS(sdev) (&(PS3_SDEV_PRI_DATA(sdev)->disk_pos))
#define PS3_SDEV_CHANNEL(sdev) (PS3_CHANNEL(PS3_SDEV_POS(sdev)))
#define PS3_SDEV_TARGET(sdev) (PS3_TARGET(PS3_SDEV_POS(sdev)))
#define PS3_SDEV_PDID(sdev) (PS3_PDID(PS3_SDEV_POS(sdev)))
#define PS3_SDEV_MAGIC(sdev) (PS3_SDEV_POS(sdev)->diskMagicNum)
#else
#define PS3_SDEV_CHANNEL(sdev) ((sdev)->channel)
#define PS3_SDEV_TARGET(sdev) ((sdev)->id)
#define PS3_SDEV_PRI_DATA(sdev) \
((struct ps3_scsi_priv_data *)((sdev)->hostdata))
#endif
struct ps3_channel {
unsigned char channel;
unsigned char reserved0;
unsigned short max_dev_num;
unsigned short channel_start_num;
unsigned char reserved1[2];
};
struct ps3_dev_pool {
union PS3Device *devs_buffer;
union PS3Device *devs[PS3_MAX_CHANNEL_NUM];
};
struct ps3_pd_entry {
struct PS3DiskDevPos disk_pos;
unsigned char state;
unsigned char config_flag;
unsigned char RWCT;
unsigned char scsi_interface_type;
unsigned char task_abort_timeout;
unsigned char task_reset_timeout;
unsigned char dev_type;
union {
struct {
unsigned char support_ncq : 1;
unsigned char protect : 1;
unsigned char is_direct_disable : 1;
unsigned char reserved : 5;
};
unsigned char pd_flags;
};
unsigned int max_io_size;
unsigned int dev_queue_depth;
unsigned char encl_id;
unsigned char phy_id;
unsigned short sector_size;
unsigned short dma_addr_alignment;
unsigned short dma_len_alignment;
struct sas_rphy *sas_rphy;
unsigned short normal_quota;
unsigned short direct_quota;
};
struct ps3_pd_table {
unsigned short *pd_idxs_array;
unsigned short *pd_idxs[PS3_MAX_CHANNEL_NUM];
};
struct ps3_vd_table {
unsigned short *vd_idxs_array;
unsigned short *vd_idxs[PS3_MAX_CHANNEL_NUM];
};
struct ps3_pri_data_table {
struct ps3_scsi_priv_data **vd_pri_data_idxs_array;
struct ps3_scsi_priv_data **vd_pri_data_idxs[PS3_MAX_CHANNEL_NUM];
};
struct ps3_dev_context {
struct ps3_vd_table vd_table[PS3_VD_TABLE_NUM];
struct ps3_pd_table pd_table;
struct PS3VDEntry *vd_entries_array[PS3_VD_TABLE_NUM];
struct ps3_pd_entry *pd_entries_array;
struct ps3_channel channel_pd[PS3_MAX_CHANNEL_NUM];
struct ps3_channel channel_vd[PS3_MAX_CHANNEL_NUM];
struct ps3_pri_data_table vd_pri_data_table;
unsigned short max_dev_in_channel[PS3_MAX_CHANNEL_NUM];
atomic_t subwork;
unsigned char reserved[3];
struct ps3_dev_pool vd_pool;
struct ps3_dev_pool pd_pool;
dma_addr_t pd_list_buf_phys;
struct PS3DevList *pd_list_buf;
dma_addr_t vd_list_buf_phys;
struct PS3DevList *vd_list_buf;
dma_addr_t pd_info_buf_phys;
struct PS3PDInfo *pd_info_buf;
dma_addr_t vd_info_buf_phys_sync;
struct PS3VDInfo *vd_info_buf_sync;
dma_addr_t vd_info_buf_phys_async;
struct PS3VDInfo *vd_info_buf_async;
struct ps3_cmd *vd_pending_cmd;
struct ps3_cmd *vdpending_abort_cmd;
atomic_t abort_vdpending_cmd;
atomic_t is_vdpending_abort;
unsigned short total_vd_count;
unsigned short total_pd_count;
unsigned short max_dev_per_channel;
unsigned char vd_table_idx;
unsigned char pd_channel_count;
unsigned char vd_channel_count;
struct mutex dev_priv_lock;
#ifdef _WINDOWS
unsigned char channel_map_rang_num;
unsigned char total_os_channel;
struct ps3_windows_private_table windows_table;
unsigned char reserved2[3];
KEVENT disk_sync;
spinlock_t dev_lock;
#else
unsigned char reserved2[7];
#endif
struct mutex dev_scan_lock;
};
int ps3_dev_mgr_cli_register(void);
int ps3_device_mgr_init(struct ps3_instance *instance);
void ps3_device_mgr_exit(struct ps3_instance *instance);
int ps3_device_mgr_data_init(struct ps3_instance *instance);
int ps3_device_mgr_data_exit(struct ps3_instance *instance);
int ps3_dev_mgr_vd_info_subscribe(struct ps3_instance *instance);
int ps3_dev_mgr_vd_info_unsubscribe(struct ps3_instance *instance);
int ps3_dev_mgr_vd_info_resubscribe(struct ps3_instance *instance);
void ps3_dev_mgr_vd_info_clear(struct ps3_instance *instance);
int ps3_dev_mgr_pd_info_get(struct ps3_instance *instance,
unsigned short channel, unsigned short target_id,
unsigned short pd_id);
struct ps3_pd_entry *
ps3_dev_mgr_pd_info_find_by_id(struct ps3_instance *instance,
unsigned short disk_id);
int ps3_dev_mgr_pd_list_get(struct ps3_instance *instance);
int ps3_dev_mgr_vd_list_get(struct ps3_instance *instance);
int ps3_vd_info_get_all(struct ps3_instance *instance);
static inline unsigned short get_offset_of_vdid(unsigned short offsetOfVDID,
unsigned short virtDiskID)
{
unsigned short virtDiskIdx = PS3_INVALID_DEV_ID;
if (virtDiskID >= offsetOfVDID)
virtDiskIdx = virtDiskID - offsetOfVDID;
return virtDiskIdx;
}
unsigned char ps3_dev_id_valid_check(struct ps3_instance *instance,
unsigned char channel,
unsigned short target_id,
unsigned char dev_type);
unsigned char ps3_get_vd_raid_level(struct ps3_instance *instance,
unsigned char channel,
unsigned short target_id);
struct ps3_scsi_priv_data *
ps3_dev_mgr_lookup_vd_pri_data(struct ps3_instance *instance,
unsigned char channel, unsigned short target_id);
struct PS3VDEntry *ps3_dev_mgr_lookup_vd_info(struct ps3_instance *instance,
unsigned char channel,
unsigned short target_id);
struct ps3_pd_entry *ps3_dev_mgr_lookup_pd_info(struct ps3_instance *instance,
unsigned char channel,
unsigned short target_id);
struct PS3VDEntry *
ps3_dev_mgr_lookup_vd_info_by_id(struct ps3_instance *instance,
unsigned short disk_id);
struct ps3_pd_entry *
ps3_dev_mgr_lookup_pd_info_by_id(struct ps3_instance *instance,
unsigned short disk_id);
union PS3Device *ps3_dev_mgr_lookup_vd_list(struct ps3_instance *instance,
unsigned char channel,
unsigned short target_id);
union PS3Device *ps3_dev_mgr_lookup_pd_list(struct ps3_instance *instance,
unsigned char channel,
unsigned short target_id);
#ifndef _WINDOWS
#if defined(PS3_CHANGE_QUEUE_DEPTH)
int ps3_change_queue_depth(struct scsi_device *sdev, int queue_depth,
int reason);
#else
int ps3_change_queue_depth(struct scsi_device *sdev, int queue_depth);
#endif
int ps3_scsi_slave_alloc(struct scsi_device *sdev);
void ps3_scsi_slave_destroy(struct scsi_device *sdev);
int ps3_scsi_slave_configure(struct scsi_device *sdev);
#endif
static inline unsigned char ps3_check_pd_is_vd_member(unsigned char config_flag)
{
return (config_flag != MIC_PD_STATE_JBOD &&
config_flag != MIC_PD_STATE_READY &&
config_flag != MIC_PD_STATE_UNKNOWN);
}
static inline unsigned char ps3_get_converted_dev_type(unsigned char driverType,
unsigned char mediumType)
{
unsigned char dev_type = PS3_DEV_TYPE_UNKNOWN;
switch (driverType) {
case DRIVER_TYPE_SAS:
if (mediumType == DEVICE_TYPE_HDD)
dev_type = PS3_DEV_TYPE_SAS_HDD;
else if (mediumType == DEVICE_TYPE_SSD)
dev_type = PS3_DEV_TYPE_SAS_SSD;
break;
case DRIVER_TYPE_SATA:
if (mediumType == DEVICE_TYPE_HDD)
dev_type = PS3_DEV_TYPE_SATA_HDD;
else if (mediumType == DEVICE_TYPE_SSD)
dev_type = PS3_DEV_TYPE_SATA_SSD;
break;
case DRIVER_TYPE_SES:
if (mediumType == DEVICE_TYPE_ENCLOSURE)
dev_type = PS3_DEV_TYPE_SES;
break;
case DRIVER_TYPE_VEP:
if (mediumType == DEVICE_TYPE_ENCLOSURE)
dev_type = PS3_DEV_TYPE_VEP;
break;
case DRIVER_TYPE_NVME:
if (mediumType == DEVICE_TYPE_SSD)
dev_type = PS3_DEV_TYPE_NVME_SSD;
break;
default:
break;
}
return dev_type;
};
void ps3_change_sdev_max_sector(struct ps3_instance *instance,
struct PS3VDEntry *vd_entry);
void ps3_vd_info_show(const struct ps3_instance *instance,
const struct PS3VDEntry *vd_entry);
int ps3_adjust_queue_depth(struct ps3_instance *instance,
unsigned char dev_type, unsigned int queue_depth);
static inline const char *
ps3_get_vd_access_plolicy_str(enum VDAccessPolicy policy)
{
static const char *const vdAccessPolicyName[] = {
[VD_ACCESS_POLICY_READ_WRITE] = "RW",
[VD_ACCESS_POLICY_READ_ONLY] = "RO",
[VD_ACCESS_POLICY_BLOCK] = "BLOCK",
[VD_ACCESS_POLICY_REMOVE_ACCESS] = "REMOVE_ACCESS",
};
return (policy < ARRAY_SIZE(vdAccessPolicyName)) ?
vdAccessPolicyName[policy] :
"Unknown";
}
static inline unsigned char ps3_is_hdd_pd(unsigned char dev_type)
{
return (dev_type == PS3_DEV_TYPE_SAS_HDD ||
dev_type == PS3_DEV_TYPE_SATA_HDD);
}
void ps3_vd_busy_scale_get(struct PS3VDEntry *vd_entry);
void ps3_sdev_bdi_stable_writes_set(struct ps3_instance *instance,
struct scsi_device *sdev);
void ps3_sdev_bdi_stable_writes_clear(struct ps3_instance *instance,
struct scsi_device *sdev);
int ps3_sdev_bdi_stable_writes_get(struct scsi_device *sdev);
#endif

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,131 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef _WINDOWS
#ifndef _PS3_DEVICE_MANAGER_SAS_H_
#define _PS3_DEVICE_MANAGER_SAS_H_
#include <linux/version.h>
#include <scsi/scsi_device.h>
#include <scsi/scsi_transport_sas.h>
#include "ps3_htp_def.h"
#include "ps3_htp_dev.h"
#include "ps3_htp_event.h"
#include "ps3_device_manager.h"
#include "ps3_kernel_version.h"
#define PS3_SAS_HBA_MAX_SAS_NUM 3
#define PS3_SAS_MAX_PHY_NUM (128)
#define PS3_SAS_INVALID_ID (0xFF)
#define PS3_SAS_INVALID_SAS_ADDR (0x0)
#define PS3_SAS_REQ_BUFF_LEN (4096)
struct ps3_instance;
struct ps3_sas_node {
struct list_head list;
struct device *dev;
struct ps3_sas_phy *phys;
struct list_head sas_port_list;
unsigned long long sas_address;
unsigned long long parent_sas_address;
unsigned char phy_count;
unsigned char encl_id;
unsigned char parent_encl_id;
unsigned char dev_type;
unsigned char reserved[4];
};
struct ps3_sas_phy {
struct list_head port_siblings;
struct sas_identify identify;
struct sas_identify remote_identify;
struct sas_phy *phy;
struct ps3_sas_port *attach_port;
unsigned char phy_id;
unsigned char encl_id;
unsigned char slot_id;
unsigned char reserved[5];
};
struct ps3_sas_port {
struct list_head list;
struct sas_identify remote_identify;
struct sas_rphy *rphy;
struct sas_port *port;
struct list_head phy_list;
unsigned short pd_flat_id;
unsigned char phy_count;
unsigned char reserved[5];
};
struct ps3_sas_dev_context {
struct list_head ps3_sas_node_list;
spinlock_t ps3_sas_node_lock;
struct ps3_sas_node ps3_hba_sas;
unsigned long long ps3_hba_sas_addr[PS3_SAS_HBA_MAX_SAS_NUM];
struct semaphore ps3_sas_smp_semaphore;
dma_addr_t ps3_sas_buff_dma_addr;
dma_addr_t ps3_sas_phy_buff_dma_addr;
void *ps3_sas_buff;
struct PS3PhyInfo *ps3_sas_phy_buff;
unsigned char is_support_smp;
unsigned char reserved[7];
};
unsigned char ps3_sas_is_support_smp(struct ps3_instance *instance);
int ps3_sas_device_mgr_init(struct ps3_instance *instance);
int ps3_sas_device_mgr_exit(struct ps3_instance *instance);
int ps3_sas_device_data_init(struct ps3_instance *instance);
int ps3_sas_device_data_exit(struct ps3_instance *instance);
int ps3_sas_rphy_slot_get(struct ps3_instance *instance,
unsigned long long sas_addr, unsigned int *slot_id);
unsigned long long
ps3_sas_rphy_parent_sas_addr_get(struct ps3_instance *instance,
unsigned long long sas_addr);
unsigned char ps3_sas_encl_id_get(struct ps3_instance *instance,
unsigned long long sas_addr);
int ps3_sas_expander_event_refresh(struct ps3_instance *instance);
int ps3_sas_update_detail_proc(struct ps3_instance *instance,
struct PS3EventDetail *event_detail,
unsigned int event_cnt);
int ps3_sas_add_device(struct ps3_instance *instance,
struct ps3_pd_entry *pd_entry);
int ps3_sas_remove_device(struct ps3_instance *instance,
struct PS3DiskDevPos *diskPos, unsigned char encl_id,
unsigned char phy_id);
void ps3_sas_expander_node_del(struct ps3_instance *instance,
struct ps3_sas_node *exp_node);
struct ps3_sas_node *
ps3_sas_find_node_by_sas_addr(struct ps3_instance *instance,
unsigned long long sas_addr);
void ps3_sas_node_phy_update(struct ps3_instance *instance,
struct ps3_sas_phy *ps3_phy,
struct PS3PhyInfo *phy_info);
#if defined(PS3_SAS_LONG_LUN)
int ps3_sas_user_scan(struct Scsi_Host *host, unsigned int channel,
unsigned int id, unsigned int lun);
#else
int ps3_sas_user_scan(struct Scsi_Host *host, unsigned int channel,
unsigned int id, unsigned long long lun);
#endif
#endif
#endif

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,41 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef _PS3_DEVICE_UPDATE_H_
#define _PS3_DEVICE_UPDATE_H_
#ifndef _WINDOWS
#include <linux/workqueue.h>
#endif
#include "ps3_htp_event.h"
#include "ps3_instance_manager.h"
unsigned char ps3_pd_scsi_visible_check(struct ps3_instance *instance,
struct PS3DiskDevPos *disk_pos,
unsigned char dev_type,
unsigned char config_flag,
unsigned char pd_state);
int ps3_dev_update_detail_proc(struct ps3_instance *instance,
struct PS3EventDetail *event_detail,
unsigned int event_cnt);
int ps3_dev_update_full_proc(struct ps3_instance *instance,
enum MgrEvtType event_type);
int ps3_dev_vd_pending_proc(struct ps3_cmd *cmd, unsigned short reply_flags);
#ifdef _WINDOWS
int ps3_device_check_and_ack(struct ps3_instance *instance,
unsigned char channel_type, unsigned char channel,
unsigned short target_id);
#endif
unsigned int ps3_scsi_dev_magic(struct ps3_instance *instance,
struct scsi_device *sdev);
void ps3_scsi_scan_host(struct ps3_instance *instance);
void ps3_check_vd_member_change(struct ps3_instance *instance,
struct ps3_pd_entry *local_entry);
#endif

View File

@ -0,0 +1,16 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef _PS3_DRV_VER_H_
#define _PS3_DRV_VER_H_
#define PS3_PRIVATE_VERSION "00.000.00.01"
#define PS3_DRV_VERSION "2.5.0.34"
#define PS3_DRV_COMMIT_ID "98da299 ce2f094"
#define PS3_DRV_BUILD_TIME "Mar 04 2025 11:12:45"
#define PS3_DRV_TOOLCHAIN_ID ""
#define PS3_DRV_PRODUCT_SUPPORT "RAID/HBA"
#define PS3_DRV_LICENSE "GPL"
#define PS3_DRV_AUTHOR "ps3stor"
#define PS3_DRV_DESCRIPTION "ps3stor driver"
#endif

View File

@ -0,0 +1,183 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef _PS3_CRASH_DUMP_H_
#define _PS3_CRASH_DUMP_H_
#ifndef _WINDOWS
#include <linux/kernel.h>
#include <linux/types.h>
#include <linux/delay.h>
#include <linux/slab.h>
#include <linux/sysfs.h>
#include <linux/mutex.h>
#include <linux/atomic.h>
#include <linux/workqueue.h>
#include <linux/pci.h>
#include <linux/irqreturn.h>
#else
#include "ps3_worker.h"
#endif
#include "ps3_platform_utils.h"
#include "ps3_htp.h"
#include "ps3_htp_def.h"
#define PS3_DUMP_DATA_MAX_NUM 512
#define WAIT_DUMP_COLLECT (1000)
#define WAIT_DUMP_TIMES_DEFAULT (300)
#define WAIT_DUMP_TIMES_MIN (10)
#define WAIT_DUMP_TIMES_MAX (3600)
#define WAIT_DUMP_DMA_DONE (200)
#ifndef _WINDOWS
#ifdef __KERNEL__
#define PS3_DUMP_FILE_DIR "/var/log"
#else
#define PS3_DUMP_FILE_DIR "/tmp"
#endif
#else
#define PS3_DUMP_FILE_DIR "c:"
#endif
#define PS3_DUMP_FILE_CORE_PREFIX "core-"
#define PS3_DUMP_FILE_FWLOG_PREFIX "fwlog-"
#define PS3_DUMP_FILE_BAR_PREFIX "bar-"
#define PS3_DUMP_STATUS_REG_DMA_FINISH_MASK (0x1 << 0)
#define PS3_DUMP_STATUS_REG_CRASH_DUMP_MASK (0x1 << 1)
#define PS3_DUMP_STATUS_REG_FW_DUMP_MASK (0x1 << 2)
#define PS3_DUMP_STATUS_REG_BAR_DUMP_MASK (0x1 << 3)
#define PS3_DUMP_STATUS_REG_CRASH_DUMP_TRIGGER_MASK (0x1 << 4)
#define PS3_DUMP_STATUS_REG_FW_DUMP_TRIGGER_MASK (0x2 << 4)
#define PS3_DUMP_STATUS_REG_BAR_DUMP_TRIGGER_MASK (0x3 << 4)
#define PS3_DUMP_STATUS_REG_ABORT_MASK (0x1 << 6)
#define PS3_DUMP_STATUS_REG_MASK (0x0F)
#define PS3_DUMP_STATUS_REG_INVALID_BITS_MASK (0x7F)
#define PS3_REG_TEST(val, mask) (((val) & (mask)) ? PS3_TRUE : PS3_FALSE)
#define PS3_REG_SET(val, mask) (((val) |= (mask)))
#define PS3_REG_CLR(val, mask) ((val) &= (~(mask)))
#define PS3_IOC_DUMP_SUPPORT(ins) (ins->dump_context.is_dump_support)
enum ps3_dump_work_status {
PS3_DUMP_WORK_UNKNOWN,
PS3_DUMP_WORK_RUNNING,
PS3_DUMP_WORK_STOP,
PS3_DUMP_WORK_DONE,
PS3_DUMP_WORK_CANCEL,
};
enum ps3_dump_irq_handler_work_status {
PS3_DUMP_IRQ_HANDLER_WORK_UNKNOWN,
PS3_DUMP_IRQ_HANDLER_WORK_RUNNING,
PS3_DUMP_IRQ_HANDLER_WORK_STOP,
PS3_DUMP_IRQ_HANDLER_WORK_DONE,
PS3_DUMP_IRQ_HANDLER_WORK_CANCEL,
};
enum ps3_dump_env {
PS3_DUMP_ENV_UNKNOWN,
PS3_DUMP_ENV_CLI,
PS3_DUMP_ENV_NOTIFY,
PS3_DUMP_ENV_COUNT,
};
enum ps3_dump_file_status {
PS3_DUMP_FILE_UNKNOWN,
PS3_DUMP_FILE_OPEN,
PS3_DUMP_FILE_CLOSE,
PS3_DUMP_FILE_MAX,
};
#define PS3_DUMP_FILE_DIR_LEN (128)
#define PS3_DUMP_FILE_NAME_LEN (256)
struct ps3_dump_file_info {
unsigned char filename[PS3_DUMP_FILE_NAME_LEN];
#ifdef _WINDOWS
HANDLE fp;
#else
struct file *fp;
#endif
unsigned long long file_size;
unsigned int file_w_cnt;
unsigned int file_status;
unsigned int type;
unsigned char reserved[4];
};
struct ps3_dump_context {
unsigned char dump_dir[PS3_DUMP_FILE_DIR_LEN];
unsigned long long dump_data_size;
char dump_type;
int dump_state;
unsigned int dump_env;
unsigned int dump_work_status;
unsigned int dump_irq_handler_work_status;
unsigned long long copyed_data_size;
unsigned char *dump_dma_buf;
dma_addr_t dump_dma_addr;
unsigned int dump_dma_wait_times;
#ifdef _WINDOWS
struct ps3_delay_worker dump_work;
struct mutex dump_mutex;
#else
struct workqueue_struct *dump_work_queue;
struct delayed_work dump_work;
struct workqueue_struct *dump_irq_handler_work_queue;
struct work_struct dump_irq_handler_work;
spinlock_t dump_irq_handler_lock;
unsigned int dump_enabled;
#endif
struct mutex dump_lock;
struct ps3_instance *instance;
struct ps3_dump_file_info dump_out_file;
struct ps3_cmd *dump_pending_cmd;
unsigned int dump_pending_send_times;
unsigned int dump_type_times;
unsigned int dump_state_times;
unsigned char is_dump_support;
unsigned char is_hard_recovered;
unsigned char reserved[2];
};
static inline const char *ps3_dump_type_to_name(int dump_type)
{
static const char * const name[] = { [PS3_DUMP_TYPE_UNKNOWN] = "NULL",
[PS3_DUMP_TYPE_CRASH] = "dump_crash",
[PS3_DUMP_TYPE_FW_LOG] = "fw_log",
[PS3_DUMP_TYPE_BAR_DATA] = "bar_data" };
return name[dump_type];
}
extern int ps3_dump_init(struct ps3_instance *instance);
extern void ps3_dump_exit(struct ps3_instance *instance);
extern int ps3_dump_type_set(struct ps3_dump_context *ctxt, int type,
unsigned int env);
extern int ps3_dump_state_set(struct ps3_dump_context *ctxt, int state);
#ifndef _WINDOWS
extern struct ps3_dump_context *dev_to_dump_context(struct device *cdev);
void ps3_dump_work_stop(struct ps3_instance *instance);
#endif
int ps3_dump_dma_buf_alloc(struct ps3_instance *instance);
void ps3_dump_dma_buf_free(struct ps3_instance *instance);
void ps3_dump_detect(struct ps3_instance *instance);
#ifndef _WINDOWS
irqreturn_t ps3_dump_irq_handler(int virq, void *dev_id);
#endif
void ps3_dump_ctrl_set_int_ready(struct ps3_instance *instance);
unsigned char ps3_dump_is_trigger_log(struct ps3_instance *instance);
#endif

View File

@ -0,0 +1,47 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef _PS3_ERR_DEF_H_
#define _PS3_ERR_DEF_H_
#include "ps3_htp_def.h"
enum {
PS3_SUCCESS = 0x00,
PS3_FAILED = 0x01,
PS3_TIMEOUT = 0x02,
PS3_IN_IRQ_POLLING = 0x03,
PS3_DEV_UNKNOWN = 0x04,
PS3_RETRY = 0x05,
PS3_EBUSY = 0x06,
PS3_EINVAL = 0x07,
PS3_ENOMEM = 0x08,
PS3_ENODEV = 0x09,
PS3_ERESTARTSYS = 0x0a,
PS3_ENOTTY = 0x0b,
PS3_RESP_ERR = 0x0c,
PS3_RESP_INT = 0x0d,
PS3_ACTIVE_ERR = 0x0e,
PS3_CMD_NO_RESP = 0x0f,
PS3_IO_BLOCK = 0x10,
PS3_IO_REQUEUE = 0x11,
PS3_IO_CONFLICT_IN_Q = 0x12,
PS3_IO_CONFLICT = 0x13,
PS3_MGR_REC_FORCE = 0x14,
PS3_RECOVERED = 0x15,
PS3_IN_UNLOAD = 0x16,
PS3_NO_RECOVERED = 0x17,
PS3_IN_QOS_Q = 0x18,
PS3_IN_PCIE_ERR = 0x19,
};
#define PS3_DRV_TRUE (1)
#define PS3_DRV_FALSE (0)
struct ps3_fault_context {
unsigned char ioc_busy;
unsigned char reserved[2];
unsigned long last_time;
};
#endif

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,37 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef _PS3_EVENT_H_
#define _PS3_EVENT_H_
#include "ps3_instance_manager.h"
#define PS3_EVENT_WORKER_POOL_SIZE (3)
#define PS3_WEB_FLAG_INIT_VALUE (0)
int ps3_event_context_init(struct ps3_instance *instance);
void ps3_event_context_exit(struct ps3_instance *instance);
const char *ps3_event_print(enum MgrEvtType event_type);
int ps3_event_subscribe(struct ps3_instance *instance);
int ps3_event_unsubscribe(struct ps3_instance *instance);
int ps3_soft_reset_event_resubscribe(struct ps3_instance *instance);
void ps3_event_handle(struct ps3_event_delay_work *ps3_delay_work);
int ps3_event_service(struct ps3_cmd *cmd, unsigned short reply_flags);
int ps3_event_delay_set(struct ps3_instance *instance, unsigned int delay);
void ps3_event_filter_table_get_raid(unsigned char *data);
void ps3_event_filter_table_get_hba(unsigned char *data);
void ps3_event_filter_table_get_switch(unsigned char *data);
void ps3_vd_pending_filter_table_build(unsigned char *data);
int ps3_fasync(int fd, struct file *filp, int mode);
int ps3_webSubscribe_context_init(struct ps3_instance *instance);
void ps3_webSubscribe_context_exit(struct ps3_instance *instance);
int ps3_webSubscribe_service(struct ps3_cmd *cmd, unsigned short reply_flags);
int ps3_web_subscribe(struct ps3_instance *instance);
int ps3_web_unsubscribe(struct ps3_instance *instance);
int ps3_soft_reset_web_resubscribe(struct ps3_instance *instance);
void ps3_web_cmd_clear(struct ps3_instance *instance);
#endif

View File

@ -0,0 +1,362 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef _PS3_INNER_DATA_H_
#define _PS3_INNER_DATA_H_
#ifndef _WINDOWS
#include <linux/types.h>
#include <linux/workqueue.h>
#include <linux/irq_poll.h>
#include <linux/atomic.h>
#include <linux/completion.h>
#include <linux/mutex.h>
#else
#include "ps3_worker.h"
#endif
#include "ps3_htp_event.h"
#include "ps3_htp_dev.h"
#include "ps3_htp_pci.h"
#include "hwapi/include_v200/s1861_regs/s1861_global_baseaddr.h"
#include "hwapi/include_v200/s1861_regs/s1861_hil_reg0_ps3_request_queue_reg.h"
#include "hwapi/include_v200/s1861_regs/s1861_hil_reg0_ps3_register_f_reg.h"
#include "hwapi/include_v200/s1861_regs/s1861_hil_reg0_ps3_register_s_reg.h"
#include "ps3_device_manager.h"
#include "ps3_htp_register_fifo.h"
#include "ps3_err_def.h"
#include "ps3_kernel_version.h"
#define PS3_DEFAULT_PAGE_SIZE_SHIFT (12)
#define PS3_CMD_SGE_FRAME_BUFFER_SIZE (4096)
#define PS3_DUMP_DMA_BUF_SIZE (0x100000)
#define PS3_DEFAULT_TASK_MGR_TIMEOUT (50)
#define PS3_DEFAULT_MGR_CMD_TIMEOUT (180)
#define PS3_CANCEL_MGR_CMD_TIMEOUT (30)
#define PS3_UNLOAD_MGR_CMD_TIMEOUT (60)
#define PS3_RAID_UNLOAD_MGR_CMD_TIMEOUT (360)
#define PS3_SOFT_RESET_WAIT_TIMEOUT (30)
#define PS3_SLEEP_TOLERATE_TIMEOUT (10)
#define PS3_RESET_WAIT_IO_REPLY_MAX_TIME (5)
#define PS3_REGISTER_SET_SIZE (147456)
#define PS3_MAX_DEBUG_REG_CNT (8)
#define PS3_HARD_RESET_MAX_RETRY (2)
#define PS3_MAX_REPLY_QUE_COUNT (128)
#define PS3_RAIDHBA_NUM_ADJUST_VALUE (1)
#define PS3_DEVICE_IO_BUSY_THRESHOLD (8)
#if defined(PS3_MAP_QUEUES)
#define MAP_QUEUES_RET_TYPE void
#define MAP_QUEUES_RET_VAL(x)
#else
#define MAP_QUEUES_RET_TYPE int
#define MAP_QUEUES_RET_VAL(x) (x)
#endif
#define PS3_BLOCK_NUM_OF_32K (1 << 6)
#define PS3_VD_IO_16_OUTSTANDING (16)
#define PS3_VD_IO_1_OUTSTANDING (1)
enum {
PS3_SCSI_CMD_TIMEOUT_MIN = 10,
PS3_SCSI_CMD_TIMEOUT_DEFAULT = 90,
PS3_SCSI_CMD_TIMEOUT_MAX = 255,
};
enum {
PS3_DEVICE_QDEPTH_DEFAULT_VALUE = 16,
};
enum PS3FuncID {
PS3_FUNC_ID_0 = 0,
PS3_FUNC_ID_1 = 1,
PS3_FUNC_UNLIMITED = 2,
};
enum {
PS3_SHIFT_BYTE = 8,
PS3_SHIFT_WORD = 16,
PS3_SHIFT_3BYTE = 24,
PS3_SHIFT_DWORD = 32,
};
enum {
PS3_SGL_MODE_SGE_COUNT_NO_DATA = 0,
PS3_SGL_MODE_SGE_COUNT_DIRECT = 1,
};
struct ps3_event_delay_work {
#ifdef _WINDOWS
struct ps3_worker event_work;
#else
struct delayed_work event_work;
#endif
struct ps3_cmd *cmd;
unsigned int event_delay;
};
struct ps3_event_context {
struct PS3EventInfo *event_info;
struct ps3_cmd *event_cmd;
struct ps3_cmd *event_abort_cmd;
atomic_t abort_eventcmd;
#ifdef _WINDOWS
struct ps3_event_delay_work delay_work;
#else
struct ps3_event_delay_work *delay_work;
struct ps3_event_delay_work *delay_work_pool;
#endif
unsigned long long event_phy_addr;
atomic_t subwork;
unsigned char flag;
};
struct ps3_webSubscribe_context {
struct ps3_cmd *webSubscribe_cmd;
struct ps3_cmd *web_abort_cmd;
atomic_t is_subscribe;
atomic_t is_abort;
atomic_t subscribe_count;
atomic_t abort_webcmd;
};
#ifndef _WINDOWS
struct ps3_refire_delay_work {
struct delayed_work refire_cmd_work;
struct ps3_cmd *refire_cmd;
};
#endif
struct ps3_cmd_attr_context {
int throttle_que_depth;
int cur_can_que;
unsigned int vd_io_threshold;
unsigned int nvme_page_size;
unsigned char is_support_direct_cmd;
unsigned char reserved[7];
};
enum {
PS3_REG_OFFSET_REQUEST_QUE =
(HIL_REG0_PS3_REQUEST_QUEUE_PS3_REQUEST_QUEUE_ADDR -
HIL_REG0_PS3_REGISTER_F_BASEADDR),
PS3_REG_OFFSET_DOORBELL = (HIL_REG0_PS3_REGISTER_F_PS3_DOORBELL_ADDR -
HIL_REG0_PS3_REGISTER_F_BASEADDR),
PS3_REG_OFFSET_DOORBELL_IRQ_CLEAR =
(HIL_REG0_PS3_REGISTER_F_PS3_DOORBELL_IRQ_CLEAR_ADDR -
HIL_REG0_PS3_REGISTER_F_BASEADDR),
PS3_REG_OFFSET_DOORBELL_IRQ_MASK =
(HIL_REG0_PS3_REGISTER_F_PS3_DOORBELL_IRQ_MASK_ADDR -
HIL_REG0_PS3_REGISTER_F_BASEADDR),
PS3_REG_OFFSET_IRQ_CONTROL =
(HIL_REG0_PS3_REGISTER_F_PS3_IRQ_CONTROL_ADDR -
HIL_REG0_PS3_REGISTER_F_BASEADDR),
PS3_REG_OFFSET_SOFTRESET_KEY =
(HIL_REG0_PS3_REGISTER_F_PS3_SOFTRESET_KEY_ADDR -
HIL_REG0_PS3_REGISTER_F_BASEADDR),
PS3_REG_OFFSET_SOFTRESET_STATE =
(HIL_REG0_PS3_REGISTER_F_PS3_SOFTRESET_STATE_ADDR -
HIL_REG0_PS3_REGISTER_F_BASEADDR),
PS3_REG_OFFSET_SOFTRESET = (HIL_REG0_PS3_REGISTER_F_PS3_SOFTRESET_ADDR -
HIL_REG0_PS3_REGISTER_F_BASEADDR),
PS3_REG_OFFSET_SOFTRESET_IRQ_CLEAR =
(HIL_REG0_PS3_REGISTER_F_PS3_SOFTRESET_IRQ_CLEAR_ADDR -
HIL_REG0_PS3_REGISTER_F_BASEADDR),
PS3_REG_OFFSET_SOFTRESET_IRQ_MASK =
(HIL_REG0_PS3_REGISTER_F_PS3_SOFTRESET_IRQ_MASK_ADDR -
HIL_REG0_PS3_REGISTER_F_BASEADDR),
PS3_REG_OFFSET_SOFTRESET_KEY_SHIFT_REG_LOW =
(HIL_REG0_PS3_REGISTER_F_PS3_SOFTRESET_KEY_SHIFT_REG_LOW_ADDR -
HIL_REG0_PS3_REGISTER_F_BASEADDR),
PS3_REG_OFFSET_SOFTRESET_KEY_SHIFT_REG_HIGH =
(HIL_REG0_PS3_REGISTER_F_PS3_SOFTRESET_KEY_SHIFT_REG_HIGH_ADDR -
HIL_REG0_PS3_REGISTER_F_BASEADDR),
PS3_REG_OFFSET_SOFTRESET_TIME_CNT =
(HIL_REG0_PS3_REGISTER_F_PS3_SOFTRESET_TIME_CNT_ADDR -
HIL_REG0_PS3_REGISTER_F_BASEADDR),
PS3_REG_OFFSET_SOFTRESET_TIME_OUT_CNT =
(HIL_REG0_PS3_REGISTER_F_PS3_SOFTRESET_TIME_OUT_EN_ADDR -
HIL_REG0_PS3_REGISTER_F_BASEADDR),
PS3_REG_OFFSET_HARDRESET_KEY =
(HIL_REG0_PS3_REGISTER_F_PS3_HARDRESET_KEY_ADDR -
HIL_REG0_PS3_REGISTER_F_BASEADDR),
PS3_REG_OFFSET_HARDRESET_STATE =
(HIL_REG0_PS3_REGISTER_F_PS3_HARDRESET_STATE_ADDR -
HIL_REG0_PS3_REGISTER_F_BASEADDR),
PS3_REG_OFFSET_HARDRESET = (HIL_REG0_PS3_REGISTER_F_PS3_HARDRESET_ADDR -
HIL_REG0_PS3_REGISTER_F_BASEADDR),
PS3_REG_OFFSET_HARDRESET_KEY_SHIFT_REG_LOW =
(HIL_REG0_PS3_REGISTER_F_PS3_HARDRESET_KEY_SHIFT_REG_LOW_ADDR -
HIL_REG0_PS3_REGISTER_F_BASEADDR),
PS3_REG_OFFSET_HARDRESET_KEY_SHIFT_REG_HIGH =
(HIL_REG0_PS3_REGISTER_F_PS3_HARDRESET_KEY_SHIFT_REG_HIGH_ADDR -
HIL_REG0_PS3_REGISTER_F_BASEADDR),
PS3_REG_OFFSET_HARDRESET_TIME_CNT =
(HIL_REG0_PS3_REGISTER_F_PS3_HARDRESET_TIME_CNT_ADDR -
HIL_REG0_PS3_REGISTER_F_BASEADDR),
PS3_REG_OFFSET_HARDRESET_TIME_OUT_CNT =
(HIL_REG0_PS3_REGISTER_F_PS3_HARDRESET_TIME_OUT_EN_ADDR -
HIL_REG0_PS3_REGISTER_F_BASEADDR),
PS3_REG_OFFSET_KEY_GAP_CFG =
(HIL_REG0_PS3_REGISTER_F_PS3_KEY_GAP_CFG_ADDR -
HIL_REG0_PS3_REGISTER_F_BASEADDR),
PS3_REG_OFFSET_HARDRESET_IRQ_CLEAR =
(HIL_REG0_PS3_REGISTER_F_PS3_HARDRESET_IRQ_CLEAR_ADDR -
HIL_REG0_PS3_REGISTER_F_BASEADDR),
PS3_REG_OFFSET_HARDRESET_IRQ_MASK =
(HIL_REG0_PS3_REGISTER_F_PS3_HARDRESET_IRQ_MASK_ADDR -
HIL_REG0_PS3_REGISTER_F_BASEADDR),
PS3_REG_OFFSET_SOC_FW_STATE =
(HIL_REG0_PS3_REGISTER_F_PS3_SOC_FW_STATE_ADDR -
HIL_REG0_PS3_REGISTER_F_BASEADDR),
PS3_REG_OFFSET_MAX_FW_CMD =
(HIL_REG0_PS3_REGISTER_F_PS3_MAX_FW_CMD_ADDR -
HIL_REG0_PS3_REGISTER_F_BASEADDR),
PS3_REG_OFFSET_MAX_CHAIN_SIZE =
(HIL_REG0_PS3_REGISTER_F_PS3_MAX_CHAIN_SIZE_ADDR -
HIL_REG0_PS3_REGISTER_F_BASEADDR),
PS3_REG_OFFSET_MAX_VD_INFO_SIZE =
(HIL_REG0_PS3_REGISTER_F_PS3_MAX_VD_INFO_SIZE_ADDR -
HIL_REG0_PS3_REGISTER_F_BASEADDR),
PS3_REG_OFFSET_MAX_NVME_PAGE_SIZE =
(HIL_REG0_PS3_REGISTER_F_PS3_MAX_NVME_PAGE_SIZE_ADDR -
HIL_REG0_PS3_REGISTER_F_BASEADDR),
PS3_REG_OFFSET_FEATURE_SUPPORT =
(HIL_REG0_PS3_REGISTER_F_PS3_FEATURE_SUPPORT_ADDR -
HIL_REG0_PS3_REGISTER_F_BASEADDR),
PS3_REG_OFFSET_FIRMWARE_VERSION =
(HIL_REG0_PS3_REGISTER_F_PS3_FIRMWARE_VERSION_ADDR -
HIL_REG0_PS3_REGISTER_F_BASEADDR),
PS3_REG_OFFSET_REPLY_QUE =
(HIL_REG0_PS3_REGISTER_F_PS3_MAX_REPLYQUE_ADDR -
HIL_REG0_PS3_REGISTER_F_BASEADDR),
PS3_REG_OFFSET_HARDWARE_VERSION =
(HIL_REG0_PS3_REGISTER_F_PS3_HARDWARE_VERSION_ADDR -
HIL_REG0_PS3_REGISTER_F_BASEADDR),
PS3_REG_OFFSET_MGR_QUEUE_DEPTH =
(HIL_REG0_PS3_REGISTER_F_PS3_MGR_QUEUE_DEPTH_ADDR -
HIL_REG0_PS3_REGISTER_F_BASEADDR),
PS3_REG_OFFSET_CMD_QUEUE_DEPTH =
(HIL_REG0_PS3_REGISTER_F_PS3_CMD_QUEUE_DEPTH_ADDR -
HIL_REG0_PS3_REGISTER_F_BASEADDR),
PS3_REG_OFFSET_TFIFO_DEPTH =
(HIL_REG0_PS3_REGISTER_F_PS3_TFIFO_DEPTH_ADDR -
HIL_REG0_PS3_REGISTER_F_BASEADDR),
PS3_REG_OFFSET_MAX_SEC_R1X_CMDS =
(HIL_REG0_PS3_REGISTER_F_PS3_MAX_SEC_R1X_CMDS_ADDR -
HIL_REG0_PS3_REGISTER_F_BASEADDR),
PS3_REG_OFFSET_HIL_ADVICE2DIRECT_CNT0 =
(HIL_REG0_PS3_REGISTER_F_PS3_HIL_ADVICE2DIRECT_CNT0_ADDR -
HIL_REG0_PS3_REGISTER_F_BASEADDR),
PS3_REG_OFFSET_HIL_ADVICE2DIRECT_CNT1 =
(HIL_REG0_PS3_REGISTER_F_PS3_HIL_ADVICE2DIRECT_CNT1_ADDR -
HIL_REG0_PS3_REGISTER_F_BASEADDR),
PS3_REG_OFFSET_HIL_ADVICE2DIRECT_CNT2 =
(HIL_REG0_PS3_REGISTER_F_PS3_HIL_ADVICE2DIRECT_CNT2_ADDR -
HIL_REG0_PS3_REGISTER_F_BASEADDR),
PS3_REG_OFFSET_HIL_ADVICE2DIRECT_CNT3 =
(HIL_REG0_PS3_REGISTER_F_PS3_HIL_ADVICE2DIRECT_CNT3_ADDR -
HIL_REG0_PS3_REGISTER_F_BASEADDR),
PS3_REG_OFFSET_HIL_ADVICE2DIRECT_CNT_ALL =
(HIL_REG0_PS3_REGISTER_F_PS3_HIL_ADVICE2DIRECT_CNT_ALL_ADDR -
HIL_REG0_PS3_REGISTER_F_BASEADDR),
PS3_REG_OFFSET_IRQ_STATUS_RPT =
(HIL_REG0_PS3_REGISTER_F_PS3_IRQ_STATUS_RPT_ADDR -
HIL_REG0_PS3_REGISTER_F_BASEADDR),
PS3_REG_OFFSET_DUMP_CTRL = (HIL_REG0_PS3_REGISTER_F_PS3_DUMP_CTRL_ADDR -
HIL_REG0_PS3_REGISTER_F_BASEADDR),
PS3_REG_OFFSET_DUMP_CTRl_IRQ_CLEAR =
(HIL_REG0_PS3_REGISTER_F_PS3_DUMP_CTRL_IRQ_CLEAR_ADDR -
HIL_REG0_PS3_REGISTER_F_BASEADDR),
PS3_REG_OFFSET_DUMP_CTRl_IRQ_MASK =
(HIL_REG0_PS3_REGISTER_F_PS3_DUMP_CTRL_IRQ_MASK_ADDR -
HIL_REG0_PS3_REGISTER_F_BASEADDR),
PS3_REG_OFFSET_DUMP_STATUS =
(HIL_REG0_PS3_REGISTER_F_PS3_DUMP_STATUS_ADDR -
HIL_REG0_PS3_REGISTER_F_BASEADDR),
PS3_REG_OFFSET_DUMP_DATA_SIZE =
(HIL_REG0_PS3_REGISTER_F_PS3_DUMP_DATA_SIZE_ADDR -
HIL_REG0_PS3_REGISTER_F_BASEADDR),
PS3_REG_OFFSET_CMD_TRIGGER =
(HIL_REG0_PS3_REGISTER_F_PS3_CMD_TRIGGER_ADDR -
HIL_REG0_PS3_REGISTER_F_BASEADDR),
PS3_REG_OFFSET_CMD_TRIGGER_IRQ_CLEAR =
(HIL_REG0_PS3_REGISTER_F_PS3_CMD_TRIGGER_IRQ_CLEAR_ADDR -
HIL_REG0_PS3_REGISTER_F_BASEADDR),
PS3_REG_OFFSET_CMD_TRIGGER_IRQ_MASK =
(HIL_REG0_PS3_REGISTER_F_PS3_CMD_TRIGGER_IRQ_MASK_ADDR -
HIL_REG0_PS3_REGISTER_F_BASEADDR),
PS3_REG_OFFSET_REG_CMD_STATE =
(HIL_REG0_PS3_REGISTER_F_PS3_REG_CMD_STATE_ADDR -
HIL_REG0_PS3_REGISTER_F_BASEADDR),
PS3_REG_OFFSET_SOFTRESET_COUNTER =
(HIL_REG0_PS3_REGISTER_F_PS3_SOFTRESET_COUNTER_ADDR -
HIL_REG0_PS3_REGISTER_F_BASEADDR),
PS3_REG_OFFSET_DEBUG0 = (HIL_REG0_PS3_REGISTER_F_PS3_DEBUG0_ADDR -
HIL_REG0_PS3_REGISTER_F_BASEADDR),
PS3_REG_OFFSET_DEBUG0_IRQ_CLEAR =
(HIL_REG0_PS3_REGISTER_F_PS3_DEBUG0_IRQ_CLEAR_ADDR -
HIL_REG0_PS3_REGISTER_F_BASEADDR),
PS3_REG_OFFSET_DEBUG0_IRQ_MASK =
(HIL_REG0_PS3_REGISTER_F_PS3_DEBUG0_IRQ_MASK_ADDR -
HIL_REG0_PS3_REGISTER_F_BASEADDR),
PS3_REG_OFFSET_DEBUG1 = (HIL_REG0_PS3_REGISTER_F_PS3_DEBUG1_ADDR -
HIL_REG0_PS3_REGISTER_F_BASEADDR),
PS3_REG_OFFSET_DEBUG1_IRQ_CLEAR =
(HIL_REG0_PS3_REGISTER_F_PS3_DEBUG1_IRQ_CLEAR_ADDR -
HIL_REG0_PS3_REGISTER_F_BASEADDR),
PS3_REG_OFFSET_DEBUG1_IRQ_MASK =
(HIL_REG0_PS3_REGISTER_F_PS3_DEBUG1_IRQ_MASK_ADDR -
HIL_REG0_PS3_REGISTER_F_BASEADDR),
PS3_REG_OFFSET_DEBUG2 = (HIL_REG0_PS3_REGISTER_F_PS3_DEBUG2_ADDR -
HIL_REG0_PS3_REGISTER_F_BASEADDR),
PS3_REG_OFFSET_DEBUG2_IRQ_CLEAR =
(HIL_REG0_PS3_REGISTER_F_PS3_DEBUG2_IRQ_CLEAR_ADDR -
HIL_REG0_PS3_REGISTER_F_BASEADDR),
PS3_REG_OFFSET_DEBUG2_IRQ_MASK =
(HIL_REG0_PS3_REGISTER_F_PS3_DEBUG2_IRQ_MASK_ADDR -
HIL_REG0_PS3_REGISTER_F_BASEADDR),
PS3_REG_OFFSET_DEBUG3 = (HIL_REG0_PS3_REGISTER_F_PS3_DEBUG3_ADDR -
HIL_REG0_PS3_REGISTER_F_BASEADDR),
PS3_REG_OFFSET_DEBUG3_IRQ_CLEAR =
(HIL_REG0_PS3_REGISTER_F_PS3_DEBUG3_IRQ_CLEAR_ADDR -
HIL_REG0_PS3_REGISTER_F_BASEADDR),
PS3_REG_OFFSET_DEBUG3_IRQ_MASK =
(HIL_REG0_PS3_REGISTER_F_PS3_DEBUG3_IRQ_MASK_ADDR -
HIL_REG0_PS3_REGISTER_F_BASEADDR),
PS3_REG_OFFSET_DEBUG4 = (HIL_REG0_PS3_REGISTER_F_PS3_DEBUG4_ADDR -
HIL_REG0_PS3_REGISTER_F_BASEADDR),
PS3_REG_OFFSET_DEBUG4_IRQ_CLEAR =
(HIL_REG0_PS3_REGISTER_F_PS3_DEBUG4_IRQ_CLEAR_ADDR -
HIL_REG0_PS3_REGISTER_F_BASEADDR),
PS3_REG_OFFSET_DEBUG4_IRQ_MASK =
(HIL_REG0_PS3_REGISTER_F_PS3_DEBUG4_IRQ_MASK_ADDR -
HIL_REG0_PS3_REGISTER_F_BASEADDR),
PS3_REG_OFFSET_DEBUG5 = (HIL_REG0_PS3_REGISTER_F_PS3_DEBUG5_ADDR -
HIL_REG0_PS3_REGISTER_F_BASEADDR),
PS3_REG_OFFSET_DEBUG6 = (HIL_REG0_PS3_REGISTER_F_PS3_DEBUG6_ADDR -
HIL_REG0_PS3_REGISTER_F_BASEADDR),
PS3_REG_OFFSET_DEBUG7 = (HIL_REG0_PS3_REGISTER_F_PS3_DEBUG7_ADDR -
HIL_REG0_PS3_REGISTER_F_BASEADDR),
PS3_REG_OFFSET_DEBUG8 = (HIL_REG0_PS3_REGISTER_F_PS3_DEBUG8_ADDR -
HIL_REG0_PS3_REGISTER_F_BASEADDR),
PS3_REG_OFFSET_DEBUG9 = (HIL_REG0_PS3_REGISTER_F_PS3_DEBUG9_ADDR -
HIL_REG0_PS3_REGISTER_F_BASEADDR),
PS3_REG_OFFSET_DEBUG10 = (HIL_REG0_PS3_REGISTER_F_PS3_DEBUG10_ADDR -
HIL_REG0_PS3_REGISTER_F_BASEADDR),
PS3_REG_OFFSET_DEBUG11 = (HIL_REG0_PS3_REGISTER_F_PS3_DEBUG11_ADDR -
HIL_REG0_PS3_REGISTER_F_BASEADDR),
PS3_REG_OFFSET_DEBUG12 = (HIL_REG0_PS3_REGISTER_F_PS3_DEBUG12_ADDR -
HIL_REG0_PS3_REGISTER_F_BASEADDR),
PS3_REG_SESSION_ADDR =
(HIL_REG0_PS3_REGISTER_F_PS3_SESSIONCMD_ADDR_ADDR -
HIL_REG0_PS3_REGISTER_F_BASEADDR),
PS3_REG_SESSION_ADDR_IRQ_CLEAR =
(HIL_REG0_PS3_REGISTER_F_PS3_SESSIONCMD_ADDR_IRQ_CLEAR_ADDR -
HIL_REG0_PS3_REGISTER_F_BASEADDR),
PS3_REG_SESSION_ADDR_IRQ_MASK =
(HIL_REG0_PS3_REGISTER_F_PS3_SESSIONCMD_ADDR_IRQ_MASK_ADDR -
HIL_REG0_PS3_REGISTER_F_BASEADDR),
};
#endif

View File

@ -0,0 +1,692 @@
// SPDX-License-Identifier: GPL-2.0
#include "ps3_instance_manager.h"
#include "ps3_driver_log.h"
#include "ps3_ioc_manager.h"
#ifndef _WINDOWS
#include "ps3_debug.h"
#include <linux/cpu.h>
#include <linux/utsname.h>
#endif
#include "ps3_cli_debug.h"
#ifdef PS3_HARDWARE_HAPS_V200
#define PS3_INSTANCE_WAIT_TO_OPERATIONAL_MAX_SECS (180)
#define PS3_INSTANCE_WAIT_TO_NORMAL_MAX_SECS (3600)
#define PS3_INSTANCE_STATE_CHECK_INTERVAL_MS (1000)
#define PS3_INSTANCE_STATE_CHECK_NORMAL_INTERVAL_MS (3000)
#else
#define PS3_INSTANCE_WAIT_TO_OPERATIONAL_MAX_SECS (180)
#define PS3_INSTANCE_WAIT_TO_NORMAL_MAX_SECS (420)
#define PS3_INSTANCE_STATE_CHECK_INTERVAL_MS (1000)
#endif
struct ps3_host_info g_ps3_host_info;
#ifndef _WINDOWS
struct ps3_mgmt_info *ps3_mgmt_info_get(void)
{
static struct ps3_mgmt_info g_mgmt_info;
return &g_mgmt_info;
}
struct ps3_instance *ps3_instance_lookup(unsigned short host_no)
{
struct ps3_instance *instance = NULL;
struct list_head *pitem = NULL;
list_for_each(pitem, &ps3_mgmt_info_get()->instance_list_head) {
instance = list_entry(pitem, struct ps3_instance, list_item);
if (instance->host->host_no == host_no)
return instance;
}
return NULL;
}
int ps3_instance_add(struct ps3_instance *instance)
{
int ret = -PS3_FAILED;
struct list_head *pitem = NULL;
struct ps3_instance *peer_instance = NULL;
if (instance == NULL)
return ret;
ps3_mutex_lock(&ps3_mgmt_info_get()->ps3_mgmt_lock);
list_for_each(pitem, &ps3_mgmt_info_get()->instance_list_head) {
if (pitem == &instance->list_item) {
pitem = NULL;
goto l_repeat_add;
}
}
list_for_each_entry(peer_instance,
&ps3_mgmt_info_get()->instance_list_head,
list_item) {
if (peer_instance != NULL &&
ps3_get_pci_domain(peer_instance->pdev) ==
ps3_get_pci_domain(instance->pdev) &&
peer_instance->pdev->bus->number ==
instance->pdev->bus->number &&
PCI_SLOT(peer_instance->pdev->devfn) ==
PCI_SLOT(instance->pdev->devfn)) {
peer_instance->recovery_context->instance_change = 1;
mb(); /* in order to force CPU ordering */
ps3_recovery_cancel_work_sync(peer_instance);
instance->peer_instance = peer_instance;
peer_instance->peer_instance = instance;
mb(); /* in order to force CPU ordering */
peer_instance->recovery_context->instance_change = 0;
}
}
list_add(&instance->list_item,
&ps3_mgmt_info_get()->instance_list_head);
mutex_init(&instance->state_machine.lock);
ps3_mutex_init(&instance->task_mgr_reset_lock);
ps3_mutex_init(&instance->task_abort_lock);
atomic_set(&instance->state_machine.state, PS3_INSTANCE_STATE_INIT);
instance->state_machine.is_load = PS3_FALSE;
instance->state_machine.is_pci_err_recovery = PS3_FALSE;
ret = PS3_SUCCESS;
l_repeat_add:
ps3_mutex_unlock(&ps3_mgmt_info_get()->ps3_mgmt_lock);
if (pitem == NULL)
LOG_WARN("hno:%u repeat add instance!\n", PS3_HOST(instance));
return ret;
}
int ps3_instance_remove(struct ps3_instance *instance)
{
struct ps3_instance *peer_instance = NULL;
if (instance == NULL)
return -PS3_FAILED;
ps3_mutex_lock(&ps3_mgmt_info_get()->ps3_mgmt_lock);
list_del(&instance->list_item);
instance->peer_instance = NULL;
list_for_each_entry(peer_instance,
&ps3_mgmt_info_get()->instance_list_head,
list_item) {
if (peer_instance != NULL &&
ps3_get_pci_domain(peer_instance->pdev) ==
ps3_get_pci_domain(instance->pdev) &&
peer_instance->pdev->bus->number ==
instance->pdev->bus->number &&
PCI_SLOT(peer_instance->pdev->devfn) ==
PCI_SLOT(instance->pdev->devfn)) {
peer_instance->recovery_context->instance_change = 1;
mb(); /* in order to force CPU ordering */
ps3_recovery_cancel_work_sync(peer_instance);
peer_instance->peer_instance = NULL;
mb(); /* in order to force CPU ordering */
peer_instance->recovery_context->instance_change = 0;
}
}
mutex_destroy(&instance->state_machine.lock);
ps3_mutex_destroy(&instance->task_mgr_reset_lock);
ps3_mutex_destroy(&instance->task_abort_lock);
ps3_mutex_unlock(&ps3_mgmt_info_get()->ps3_mgmt_lock);
return PS3_SUCCESS;
}
void ps3_mgmt_info_init(void)
{
ps3_mutex_init(&ps3_mgmt_info_get()->ps3_mgmt_lock);
INIT_LIST_HEAD(&ps3_mgmt_info_get()->instance_list_head);
ps3_cli_debug_init();
}
void ps3_mgmt_exit(void)
{
ps3_mutex_destroy(&ps3_mgmt_info_get()->ps3_mgmt_lock);
}
#endif
void ps3_instance_init(struct ps3_instance *instance)
{
memset(instance, 0, sizeof(struct ps3_instance));
ps3_mutex_init(&instance->state_machine.lock);
ps3_atomic_set(&instance->state_machine.state, PS3_INSTANCE_STATE_INIT);
instance->state_machine.is_load = PS3_FALSE;
instance->state_machine.is_poweroff = PS3_FALSE;
instance->state_machine.is_pci_err_recovery = PS3_FALSE;
}
int ps3_instance_state_transfer(struct ps3_instance *instance,
unsigned int exp_cur_state,
unsigned int dest_state)
{
unsigned int cur_state = 0;
ps3_mutex_lock(&instance->state_machine.lock);
cur_state = ps3_atomic_read(&instance->state_machine.state);
if (cur_state != exp_cur_state)
goto l_fail;
switch (cur_state) {
case PS3_INSTANCE_STATE_INIT:
if ((dest_state == PS3_INSTANCE_STATE_READY) ||
(dest_state == PS3_INSTANCE_STATE_RECOVERY)) {
goto l_success;
} else {
goto l_fail;
}
break;
case PS3_INSTANCE_STATE_READY:
if ((dest_state == PS3_INSTANCE_STATE_PRE_OPERATIONAL) ||
(dest_state == PS3_INSTANCE_STATE_RECOVERY) ||
(dest_state == PS3_INSTANCE_STATE_PCIE_RECOVERY)) {
goto l_success;
} else {
goto l_fail;
}
break;
case PS3_INSTANCE_STATE_PRE_OPERATIONAL:
if ((dest_state == PS3_INSTANCE_STATE_OPERATIONAL) ||
(dest_state == PS3_INSTANCE_STATE_RECOVERY) ||
(dest_state == PS3_INSTANCE_STATE_SOFT_RECOVERY)) {
goto l_success;
} else {
goto l_fail;
}
break;
case PS3_INSTANCE_STATE_OPERATIONAL:
if ((dest_state == PS3_INSTANCE_STATE_SOFT_RECOVERY) ||
(dest_state == PS3_INSTANCE_STATE_RECOVERY) ||
(dest_state == PS3_INSTANCE_STATE_SUSPEND) ||
(dest_state == PS3_INSTANCE_STATE_QUIT)) {
goto l_success;
} else {
goto l_fail;
}
break;
case PS3_INSTANCE_STATE_SOFT_RECOVERY:
if ((dest_state == PS3_INSTANCE_STATE_PRE_OPERATIONAL) ||
(dest_state == PS3_INSTANCE_STATE_RECOVERY)) {
goto l_success;
} else {
goto l_fail;
}
break;
case PS3_INSTANCE_STATE_RECOVERY:
if ((dest_state == PS3_INSTANCE_STATE_READY) ||
(dest_state == PS3_INSTANCE_STATE_DEAD)) {
goto l_success;
} else {
goto l_fail;
}
break;
case PS3_INSTANCE_STATE_SUSPEND:
if (dest_state == PS3_INSTANCE_STATE_READY)
goto l_success;
else
goto l_fail;
break;
case PS3_INSTANCE_STATE_DEAD:
if (dest_state == PS3_INSTANCE_STATE_QUIT)
goto l_success;
else
goto l_fail;
break;
case PS3_INSTANCE_STATE_QUIT:
goto l_fail;
case PS3_INSTANCE_STATE_PCIE_RECOVERY:
if (dest_state == PS3_INSTANCE_STATE_RECOVERY)
goto l_success;
else
goto l_fail;
default:
goto l_fail;
}
l_fail:
ps3_mutex_unlock(&instance->state_machine.lock);
LOG_ERROR("hno:%u state transfer NOK! [exp_cur_state:%s][cur_state:%s][dest_state:%s]\n",
PS3_HOST(instance), namePS3InstanceState(exp_cur_state),
namePS3InstanceState(cur_state),
namePS3InstanceState(dest_state));
return -PS3_FAILED;
l_success:
ps3_atomic_set(&instance->state_machine.state, dest_state);
ps3_mutex_unlock(&instance->state_machine.lock);
LOG_INFO("hno:%u state transfer from %s to %s!\n", PS3_HOST(instance),
namePS3InstanceState(cur_state),
namePS3InstanceState(dest_state));
return PS3_SUCCESS;
}
int ps3_instance_no_lock_state_transfer(struct ps3_instance *instance,
unsigned int dest_state)
{
unsigned int cur_state = 0;
cur_state = ps3_atomic_read(&instance->state_machine.state);
if (cur_state == dest_state)
goto l_success;
switch (cur_state) {
case PS3_INSTANCE_STATE_INIT:
if ((dest_state == PS3_INSTANCE_STATE_READY) ||
(dest_state == PS3_INSTANCE_STATE_RECOVERY)) {
goto l_success;
} else {
goto l_fail;
}
break;
case PS3_INSTANCE_STATE_READY:
if ((dest_state == PS3_INSTANCE_STATE_PRE_OPERATIONAL) ||
(dest_state == PS3_INSTANCE_STATE_RECOVERY)) {
goto l_success;
} else {
goto l_fail;
}
break;
case PS3_INSTANCE_STATE_PRE_OPERATIONAL:
if ((dest_state == PS3_INSTANCE_STATE_OPERATIONAL) ||
(dest_state == PS3_INSTANCE_STATE_RECOVERY) ||
(dest_state == PS3_INSTANCE_STATE_SOFT_RECOVERY)) {
goto l_success;
} else {
goto l_fail;
}
break;
case PS3_INSTANCE_STATE_OPERATIONAL:
if ((dest_state == PS3_INSTANCE_STATE_SOFT_RECOVERY) ||
(dest_state == PS3_INSTANCE_STATE_RECOVERY) ||
(dest_state == PS3_INSTANCE_STATE_SUSPEND) ||
(dest_state == PS3_INSTANCE_STATE_QUIT)) {
goto l_success;
} else {
goto l_fail;
}
break;
case PS3_INSTANCE_STATE_SOFT_RECOVERY:
if ((dest_state == PS3_INSTANCE_STATE_PRE_OPERATIONAL) ||
(dest_state == PS3_INSTANCE_STATE_RECOVERY)) {
goto l_success;
} else {
goto l_fail;
}
break;
case PS3_INSTANCE_STATE_RECOVERY:
if ((dest_state == PS3_INSTANCE_STATE_READY) ||
(dest_state == PS3_INSTANCE_STATE_DEAD)) {
goto l_success;
} else {
goto l_fail;
}
break;
case PS3_INSTANCE_STATE_SUSPEND:
if (dest_state == PS3_INSTANCE_STATE_READY)
goto l_success;
else
goto l_fail;
break;
case PS3_INSTANCE_STATE_DEAD:
if (dest_state == PS3_INSTANCE_STATE_QUIT)
goto l_success;
else
goto l_fail;
break;
case PS3_INSTANCE_STATE_QUIT:
goto l_fail;
case PS3_INSTANCE_STATE_PCIE_RECOVERY:
if (dest_state == PS3_INSTANCE_STATE_RECOVERY)
goto l_success;
else
goto l_fail;
default:
goto l_fail;
}
l_fail:
LOG_ERROR("hno:%u state transfer NOK! [cur_state:%s][dest_state:%s]\n",
PS3_HOST(instance), namePS3InstanceState(cur_state),
namePS3InstanceState(dest_state));
return -PS3_FAILED;
l_success:
ps3_atomic_set(&instance->state_machine.state, dest_state);
LOG_INFO("hno:%u state transfer from %s to %s!\n", PS3_HOST(instance),
namePS3InstanceState(cur_state),
namePS3InstanceState(dest_state));
return PS3_SUCCESS;
}
void ps3_instance_state_transfer_to_dead_nolock(struct ps3_instance *instance)
{
ps3_atomic_set(&instance->state_machine.state, PS3_INSTANCE_STATE_DEAD);
}
void ps3_instance_state_transfer_to_dead(struct ps3_instance *instance)
{
ps3_mutex_lock(&instance->state_machine.lock);
if (ps3_atomic_read(&instance->state_machine.state) !=
PS3_INSTANCE_STATE_DEAD) {
ps3_atomic_set(&instance->state_machine.state,
PS3_INSTANCE_STATE_DEAD);
}
ps3_mutex_unlock(&instance->state_machine.lock);
}
void ps3_instance_state_transfer_to_pcie_recovery(struct ps3_instance *instance)
{
ps3_mutex_lock(&instance->state_machine.lock);
if (ps3_atomic_read(&instance->state_machine.state) !=
PS3_INSTANCE_STATE_PCIE_RECOVERY) {
ps3_atomic_set(&instance->state_machine.state,
PS3_INSTANCE_STATE_PCIE_RECOVERY);
}
ps3_mutex_unlock(&instance->state_machine.lock);
}
void ps3_instance_state_transfer_to_quit(struct ps3_instance *instance)
{
ps3_atomic_set(&instance->state_machine.state, PS3_INSTANCE_STATE_QUIT);
}
void ps3_instance_state_transfer_to_suspend(struct ps3_instance *instance)
{
ps3_atomic_set(&instance->state_machine.state,
PS3_INSTANCE_STATE_SUSPEND);
}
void ps3_instance_state_transition_to_recovery(struct ps3_instance *instance)
{
ps3_atomic_set(&instance->state_machine.state,
PS3_INSTANCE_STATE_RECOVERY);
}
int ps3_instance_wait_for_hard_reset_flag_done(struct ps3_instance *instance)
{
unsigned int wait_cnt = PS3_INSTANCE_WAIT_TO_OPERATIONAL_MAX_SECS * 2;
int cur_state = PS3_INSTANCE_STATE_INIT;
unsigned int idx = 0;
int ret = PS3_SUCCESS;
for (idx = 0; idx < wait_cnt; idx++) {
cur_state = ps3_atomic_read(&instance->state_machine.state);
if ((cur_state == PS3_INSTANCE_STATE_DEAD) ||
(cur_state == PS3_INSTANCE_STATE_QUIT)) {
ret = -PS3_FAILED;
goto l_out;
}
ps3_mutex_lock(&instance->state_machine.lock);
if (instance->recovery_context->host_reset_state ==
PS3_HOST_RESET_HARD_RESET_DONE &&
ps3_atomic_read(&instance->state_machine.state) ==
PS3_INSTANCE_STATE_OPERATIONAL) {
if (atomic_read(
&instance->cmd_statistics.io_outstanding) !=
0) {
ret = -PS3_RETRY;
}
ps3_mutex_unlock(&instance->state_machine.lock);
goto l_out;
}
ps3_mutex_unlock(&instance->state_machine.lock);
ps3_msleep(PS3_INSTANCE_STATE_CHECK_INTERVAL_MS);
}
if (idx >= wait_cnt) {
LOG_WARN("hno:%u wait pre_operational timeout!\n",
PS3_HOST(instance));
}
ps3_mutex_lock(&instance->state_machine.lock);
if (instance->recovery_context->host_reset_state !=
PS3_HOST_RESET_HARD_RESET_DONE) {
LOG_WARN("hno:%u wait host reset hard reset done NOK!\n",
PS3_HOST(instance));
ret = -PS3_RETRY;
}
ps3_mutex_unlock(&instance->state_machine.lock);
l_out:
LOG_INFO("hno:%u wait hard reset flag %d!\n", PS3_HOST(instance), ret);
return ret;
}
int ps3_instance_wait_for_dead_or_pre_operational(struct ps3_instance *instance)
{
unsigned int wait_cnt = PS3_INSTANCE_WAIT_TO_OPERATIONAL_MAX_SECS * 3;
int cur_state = PS3_INSTANCE_STATE_INIT;
unsigned int idx = 0;
LOG_INFO("hno:%u wait dead or pre_operational begin\n",
PS3_HOST(instance));
for (idx = 0; idx < wait_cnt; idx++) {
cur_state = ps3_atomic_read(&instance->state_machine.state);
if ((cur_state == PS3_INSTANCE_STATE_PRE_OPERATIONAL) ||
(cur_state == PS3_INSTANCE_STATE_OPERATIONAL) ||
(cur_state == PS3_INSTANCE_STATE_DEAD) ||
(cur_state == PS3_INSTANCE_STATE_QUIT)) {
break;
}
ps3_msleep(PS3_INSTANCE_STATE_CHECK_INTERVAL_MS);
}
if (idx >= wait_cnt) {
LOG_WARN("hno:%u wait dead or pre_operational timeout!\n",
PS3_HOST(instance));
}
if ((cur_state != PS3_INSTANCE_STATE_PRE_OPERATIONAL) &&
(cur_state != PS3_INSTANCE_STATE_OPERATIONAL) &&
(cur_state != PS3_INSTANCE_STATE_DEAD)) {
LOG_WARN("hno:%u wait dead or pre_operational NOK!\n",
PS3_HOST(instance));
return -PS3_FAILED;
}
LOG_INFO("hno:%u wait dead or pre_operational success!\n",
PS3_HOST(instance));
return PS3_SUCCESS;
}
int ps3_instance_wait_for_operational(struct ps3_instance *instance,
unsigned char is_hardreset)
{
unsigned int wait_cnt = PS3_INSTANCE_WAIT_TO_OPERATIONAL_MAX_SECS * 3;
int cur_state = PS3_INSTANCE_STATE_INIT;
unsigned int idx = 0;
int recovery_state = PS3_RESET_LOG_INTERVAL;
for (idx = 0; idx < wait_cnt; idx++) {
if (!instance->state_machine.is_load) {
LOG_INFO("hno:%u instance state not is_load\n",
PS3_HOST(instance));
break;
}
ps3_mutex_lock(&instance->state_machine.lock);
cur_state = ps3_atomic_read(&instance->state_machine.state);
recovery_state = instance->recovery_context->recovery_state;
if (((cur_state == PS3_INSTANCE_STATE_OPERATIONAL) ||
(cur_state == PS3_INSTANCE_STATE_DEAD) ||
(cur_state == PS3_INSTANCE_STATE_QUIT)) &&
(is_hardreset ?
(recovery_state == PS3_HARD_RECOVERY_FINISH) :
PS3_TRUE)) {
LOG_INFO(
"hno:%u wait break, cur_state: %s, recovery_state: %d, is_hardreset: %d\n",
PS3_HOST(instance),
namePS3InstanceState(cur_state), recovery_state,
is_hardreset);
ps3_mutex_unlock(&instance->state_machine.lock);
break;
}
ps3_mutex_unlock(&instance->state_machine.lock);
ps3_msleep(PS3_INSTANCE_STATE_CHECK_INTERVAL_MS);
}
if (idx >= wait_cnt) {
LOG_WARN("hno:%u wait operational timeout!\n",
PS3_HOST(instance));
}
if (cur_state != PS3_INSTANCE_STATE_OPERATIONAL) {
LOG_WARN(
"hno:%u wait operational NOK, cur_state: %s, recovery_state: %d\n",
PS3_HOST(instance), namePS3InstanceState(cur_state),
recovery_state);
return -PS3_FAILED;
}
LOG_INFO("hno:%u wait operational success!\n", PS3_HOST(instance));
return PS3_SUCCESS;
}
int ps3_instance_wait_for_normal(struct ps3_instance *instance)
{
int ret = PS3_SUCCESS;
unsigned int wait_cnt = PS3_INSTANCE_WAIT_TO_NORMAL_MAX_SECS;
int cur_state = PS3_INSTANCE_STATE_INIT;
unsigned int idx = 0;
unsigned char is_pci_err_recovery = PS3_FALSE;
for (idx = 0; idx < wait_cnt; idx++) {
is_pci_err_recovery = ps3_pci_err_recovery_get(instance);
cur_state = ps3_atomic_read(&instance->state_machine.state);
if (cur_state == PS3_INSTANCE_STATE_DEAD &&
PS3_IOC_STATE_HALT_SUPPORT(instance) &&
PS3_HALT_CLI_SUPPORT(instance)) {
goto l_out;
}
if (ps3_state_is_normal(cur_state) ||
cur_state == PS3_INSTANCE_STATE_QUIT ||
cur_state == PS3_INSTANCE_STATE_DEAD ||
is_pci_err_recovery) {
LOG_DEBUG(
"hno:%u cur state: %d, pci err recovery: %d\n",
PS3_HOST(instance), cur_state,
is_pci_err_recovery);
break;
}
if (!(idx % PS3_RESET_LOG_INTERVAL)) {
LOG_DEBUG(
"hno:%u state[%s] waiting for reset to finish\n",
PS3_HOST(instance),
namePS3InstanceState(cur_state));
}
#ifdef PS3_HARDWARE_HAPS_V200
ps3_msleep(PS3_INSTANCE_STATE_CHECK_NORMAL_INTERVAL_MS);
if (ps3_get_wait_cli_flag()) {
LOG_DEBUG("hno:%u not wait cmd\n", PS3_HOST(instance));
break;
}
#else
ps3_msleep(PS3_INSTANCE_STATE_CHECK_INTERVAL_MS);
#endif
}
if (!ps3_state_is_normal(cur_state) || is_pci_err_recovery) {
LOG_WARN(
"hno:%u cannot handle cmd, driver state: %s, pci recovery: %d\n",
PS3_HOST(instance), namePS3InstanceState(cur_state),
is_pci_err_recovery);
ret = -PS3_FAILED;
goto l_out;
}
l_out:
return ret;
}
int ps3_recovery_state_wait_for_normal(struct ps3_instance *instance)
{
int ret = PS3_SUCCESS;
unsigned int wait_cnt = PS3_INSTANCE_WAIT_TO_NORMAL_MAX_SECS;
int recovery_state = PS3_RESET_LOG_INTERVAL;
unsigned int idx = 0;
unsigned char is_pci_err_recovery = PS3_FALSE;
for (idx = 0; idx < wait_cnt; idx++) {
recovery_state = instance->recovery_context->recovery_state;
is_pci_err_recovery = ps3_pci_err_recovery_get(instance);
if (recovery_state == PS3_HARD_RECOVERY_FINISH ||
recovery_state == PS3_SOFT_RECOVERY_PROBE_PROCESS ||
is_pci_err_recovery) {
LOG_DEBUG(
"hno:%u recovery state: %d, pci err recovery: %d\n",
PS3_HOST(instance), recovery_state,
is_pci_err_recovery);
goto l_out;
}
#ifdef PS3_HARDWARE_HAPS_V200
ps3_msleep(PS3_INSTANCE_STATE_CHECK_NORMAL_INTERVAL_MS);
if (ps3_get_wait_cli_flag()) {
LOG_DEBUG("hno:%u not wait cmd\n", PS3_HOST(instance));
break;
}
#else
ps3_msleep(PS3_INSTANCE_STATE_CHECK_INTERVAL_MS);
#endif
}
ret = -PS3_FAILED;
LOG_WARN("hno:%u wait recovery time out, recovery_state: %d\n",
PS3_HOST(instance), recovery_state);
l_out:
if (is_pci_err_recovery) {
LOG_WARN("hno:%u cannot handle cmd, pci recovery: %d\n",
PS3_HOST(instance), is_pci_err_recovery);
ret = -PS3_FAILED;
}
return ret;
}
void ps3_host_info_get(void)
{
#if defined(CONFIG_X86) || defined(CONFIG_X86_64)
struct cpuinfo_x86 *cpu = NULL;
memset(&g_ps3_host_info, 0, sizeof(struct ps3_host_info));
cpu = &cpu_data(0);
g_ps3_host_info.machine = PS3_HOST_MACHINE_X86;
if (strstr(cpu->x86_vendor_id, "Intel"))
g_ps3_host_info.vendor = PS3_HOST_VENDOR_INTEL;
else if (strstr(cpu->x86_vendor_id, "Hygon"))
g_ps3_host_info.vendor = PS3_HOST_VENDOR_HYGON;
else if (strstr(cpu->x86_vendor_id, "AMD"))
g_ps3_host_info.vendor = PS3_HOST_VENDOR_AMD;
g_ps3_host_info.processor_cnt = num_online_cpus();
#else
memset(&g_ps3_host_info, 0, sizeof(struct ps3_host_info));
#endif
memset(g_ps3_host_info.release, 0, SYS_INFO_LEN + 1);
snprintf(g_ps3_host_info.release, SYS_INFO_LEN, "%s",
utsname()->release);
LOG_DEBUG(
"host info: machine=%u,vendor=%u,processor_cnt=%u release=%s\n",
g_ps3_host_info.machine, g_ps3_host_info.vendor,
g_ps3_host_info.processor_cnt, g_ps3_host_info.release);
}
unsigned short ps3_host_vendor_get(void)
{
return g_ps3_host_info.vendor;
}
char *ps3_host_release_get(void)
{
return g_ps3_host_info.release;
}
unsigned char ps3_is_last_func(struct ps3_instance *instance)
{
return (!ps3_ioc_multi_func_support(instance) ||
(ps3_get_pci_function(instance->pdev) == PS3_FUNC_ID_1));
}

View File

@ -0,0 +1,536 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef _PS3_INSTANCE_MANAGER_H_
#define _PS3_INSTANCE_MANAGER_H_
#ifndef _WINDOWS
#include <linux/pci.h>
#include <linux/types.h>
#include <linux/mutex.h>
#include <linux/irqreturn.h>
#include <scsi/scsi_host.h>
#include <scsi/scsi_cmnd.h>
#include <scsi/scsi_device.h>
#include "ps3_sas_transport.h"
#include "ps3_device_manager_sas.h"
#else
#include "ps3_pci.h"
#endif
#include "ps3_inner_data.h"
#include "ps3_irq.h"
#include "ps3_cmd_channel.h"
#include "ps3_platform_utils.h"
#include "ps3_cmd_channel.h"
#include "ps3_inner_data.h"
#include "ps3_debug.h"
#include "ps3_irq.h"
#include "ps3_recovery.h"
#include "ps3_dump.h"
#include "ps3_cmd_stat_def.h"
#include "ps3_watchdog.h"
#include "ps3_qos.h"
enum PS3_INSTANCE_STATE_TYPE {
PS3_INSTANCE_STATE_INIT = 0,
PS3_INSTANCE_STATE_READY = 1,
PS3_INSTANCE_STATE_PRE_OPERATIONAL = 2,
PS3_INSTANCE_STATE_OPERATIONAL = 3,
PS3_INSTANCE_STATE_SOFT_RECOVERY = 4,
PS3_INSTANCE_STATE_RECOVERY = 5,
PS3_INSTANCE_STATE_SUSPEND = 6,
PS3_INSTANCE_STATE_DEAD = 7,
PS3_INSTANCE_STATE_QUIT = 8,
PS3_INSTANCE_STATE_PCIE_RECOVERY = 9,
PS3_INSTANCE_STATE_COUNT = 10
};
enum PS3_DEVICE_ERR_HANDLE_STATE_TYPE {
PS3_DEVICE_ERR_STATE_NORMAL = 0,
PS3_DEVICE_ERR_STATE_CLEAN = 1,
PS3_DEVICE_ERR_STATE_INIT = 2,
};
struct ps3_instance_state_machine {
struct mutex lock;
atomic_t state;
unsigned char is_load;
unsigned char is_suspend;
unsigned char is_poweroff;
unsigned char is_pci_err_recovery;
unsigned char can_hostreset;
};
static inline const char *namePS3InstanceState(int s)
{
static const char * const myNames[] = {
[PS3_INSTANCE_STATE_INIT] = "PS3_INSTANCE_STATE_INIT",
[PS3_INSTANCE_STATE_READY] = "PS3_INSTANCE_STATE_READY",
[PS3_INSTANCE_STATE_PRE_OPERATIONAL] =
"PS3_INSTANCE_STATE_PRE_OPERATIONAL",
[PS3_INSTANCE_STATE_OPERATIONAL] =
"PS3_INSTANCE_STATE_OPERATIONAL",
[PS3_INSTANCE_STATE_SOFT_RECOVERY] =
"PS3_INSTANCE_STATE_SOFT_RECOVERY",
[PS3_INSTANCE_STATE_RECOVERY] = "PS3_INSTANCE_STATE_RECOVERY",
[PS3_INSTANCE_STATE_SUSPEND] = "PS3_INSTANCE_STATE_SUSPEND",
[PS3_INSTANCE_STATE_DEAD] = "PS3_INSTANCE_STATE_DEAD",
[PS3_INSTANCE_STATE_QUIT] = "PS3_INSTANCE_STATE_QUIT",
[PS3_INSTANCE_STATE_PCIE_RECOVERY] =
"PS3_INSTANCE_STATE_PCIE_RECOVERY"
};
if (s >= PS3_INSTANCE_STATE_COUNT)
return "PS3_INSTANCE_STATE_INVALID";
return myNames[s];
}
struct ps3_recovery_function {
int (*recovery_handle_cb)(struct ps3_instance *instance,
unsigned char reason);
int (*hardreset_handle_pre_cb)(struct ps3_instance *instance);
int (*hardreset_handle_wait_ready_cb)(struct ps3_instance *instance);
int (*hardreset_handle_init_running_cb)(struct ps3_instance *instance);
int (*hardreset_handle_post_cb)(struct ps3_instance *instance);
int (*hardreset_handle_finish_cb)(struct ps3_instance *instance);
int (*hardreset_handle_offline_cb)(struct ps3_instance *instance);
int (*softreset_handle_pre_cb)(struct ps3_instance *instance);
int (*softreset_handle_post_cb)(struct ps3_instance *instance);
int (*halt_handle_cb)(struct ps3_instance *instance);
};
struct ps3_instance {
struct list_head list_item;
struct ps3_instance *peer_instance;
#ifndef _WINDOWS
struct pci_dev *pdev;
struct Scsi_Host *host;
#else
unsigned long bus_number;
struct ps3_pci_context pci_dev_context;
#endif
struct Ps3Fifo __iomem *reg_set;
atomic_t watchdog_reg_read_fail_count;
struct ps3_cmd_context cmd_context;
struct ps3_irq_context irq_context;
struct ps3_dev_context dev_context;
#ifndef _WINDOWS
struct ps3_sas_dev_context sas_dev_context;
#endif
struct ps3_event_context event_context;
struct ps3_webSubscribe_context webSubscribe_context;
struct ps3_fault_context fault_context;
struct ps3_watchdog_context watchdog_context;
struct ps3_dump_context dump_context;
struct ps3_debug_context debug_context;
struct ps3_cmd_statistics_context cmd_statistics;
struct PS3IocCtrlInfo ctrl_info;
struct PS3IocCtrlInfo *ctrl_info_buf;
#ifdef _WINDOWS
atomic_t ioctl_count;
#else
struct semaphore ioctl_sem;
#endif
struct ps3_ioc_adp_template *ioc_adpter;
struct ps3_cmd_attr_context cmd_attr;
struct PS3MgrEvent event_req_info;
spinlock_t req_queue_lock;
dma_addr_t ctrl_info_buf_h;
dma_addr_t drv_info_buf_phys;
unsigned char *drv_info_buf;
dma_addr_t host_mem_info_buf_phys;
unsigned char *host_mem_info_buf;
unsigned int max_mgr_cmd_total_count;
unsigned int max_mgr_cmd_count;
unsigned int max_task_cmd_count;
unsigned int min_intr_count;
unsigned char reserve[4];
unsigned int reply_fifo_depth_addition;
unsigned long reg_bar;
unsigned char is_support_sync_cache;
unsigned char is_use_frontend_prp;
unsigned char dma_mask;
unsigned char is_support_jbod;
unsigned char use_clusting;
unsigned char is_adjust_register_count;
unsigned char is_scan_host_finish;
unsigned char is_probe_finish;
unsigned char is_probe_failed;
unsigned char is_suspend;
unsigned char is_resume;
unsigned char is_hard_reset;
unsigned char is_pci_reset;
unsigned char is_ioc_halt_support;
unsigned char is_shallow_soft_recovery_support;
unsigned char is_deep_soft_recovery_support;
unsigned char is_hard_recovery_support;
unsigned char is_halt_support_cli;
unsigned char is_half_hard_reset;
unsigned char is_host_added;
unsigned char is_need_event;
unsigned char is_raid1_direct_skip_mapblock_check;
unsigned char is_single_disk_raid0_direct_skip_strip_check;
unsigned char is_support_dump_ctrl;
unsigned char is_support_io_limit;
unsigned char task_manager_host_busy;
unsigned char hilMode;
unsigned char is_irq_prk_support;
unsigned char is_support_irq;
unsigned char is_raid;
unsigned char smp_affinity_enable;
unsigned char msix_combined;
unsigned char reserved[2];
unsigned short unload_timeout;
unsigned short wait_ready_timeout;
unsigned short dev_id;
unsigned char dma_addr_bit_pos;
unsigned char pci_err_handle_state;
const char *product_model;
long long __percpu *scsi_cmd_deliver;
unsigned long long ioc_fw_version;
struct mutex task_mgr_reset_lock;
#ifdef _WINDOWS
STOR_DPC device_reset_dpc;
#endif
unsigned char page_mode_change;
unsigned long long page_mode_addr_mask;
atomic_t is_err_scsi_processing;
atomic_t reg_op_count;
atomic_t host_reset_processing;
atomic_t watchdog_ref;
struct ps3_instance_state_machine state_machine;
struct ps3_recovery_context *recovery_context;
struct ps3_recovery_function recovery_function;
#ifndef _WINDOWS
struct work_struct recovery_irq_work;
struct workqueue_struct *recovery_irq_queue;
unsigned char recovery_irq_enable;
unsigned char is_print_special_log;
unsigned char reserved2[2];
unsigned int hard_dog_mask;
#endif
atomic_t hardreset_event;
struct ps3_qos_context qos_context;
struct mutex task_abort_lock;
unsigned char r1x_mode;
unsigned long long start_pfn;
unsigned long long end_pfn;
unsigned long long so_start_addr;
unsigned long long so_end_addr;
int device_busy_threshold;
unsigned char is_pcie_err_detected;
unsigned char reserved3;
};
#ifndef _WINDOWS
struct ps3_mgmt_info {
struct mutex ps3_mgmt_lock;
struct list_head instance_list_head;
};
enum {
PS3_HOST_MACHINE_DEFAULT,
PS3_HOST_MACHINE_X86 = 0,
PS3_HOST_MACHINE_ARM,
PS3_HOST_MACHINE_MIPS,
PS3_HOST_MACHINE_COUNT,
};
enum {
PS3_HOST_VENDOR_DEFAULT,
PS3_HOST_VENDOR_INTEL = 0,
PS3_HOST_VENDOR_HYGON,
PS3_HOST_VENDOR_AMD,
PS3_HOST_VENDOR_COUNT,
};
#define SYS_INFO_LEN (64)
struct ps3_host_info {
unsigned char machine;
unsigned char vendor;
unsigned short cpu_cnt;
unsigned short core_cnt;
unsigned short processor_cnt;
char release[SYS_INFO_LEN + 1];
};
struct ps3_mgmt_info *ps3_mgmt_info_get(void);
struct ps3_instance *ps3_instance_lookup(unsigned short host_no);
int ps3_instance_add(struct ps3_instance *instance);
int ps3_instance_remove(struct ps3_instance *instance);
void ps3_mgmt_info_init(void);
void ps3_mgmt_exit(void);
#endif
void ps3_instance_init(struct ps3_instance *instance);
int ps3_instance_state_transfer(struct ps3_instance *instance,
unsigned int exp_cur_state,
unsigned int dest_state);
int ps3_instance_no_lock_state_transfer(struct ps3_instance *instance,
unsigned int dest_state);
void ps3_instance_state_transfer_to_dead_nolock(struct ps3_instance *instance);
void ps3_instance_state_transfer_to_dead(struct ps3_instance *instance);
void ps3_instance_state_transfer_to_pcie_recovery(struct ps3_instance *instance);
void ps3_instance_state_transfer_to_quit(struct ps3_instance *instance);
void ps3_instance_state_transfer_to_suspend(struct ps3_instance *instance);
void ps3_instance_state_transition_to_recovery(struct ps3_instance *instance);
int ps3_instance_wait_for_operational(struct ps3_instance *instance,
unsigned char is_hardreset);
int ps3_instance_wait_for_hard_reset_flag_done(struct ps3_instance *instance);
int ps3_instance_wait_for_dead_or_pre_operational(struct ps3_instance *instance);
static inline unsigned char
ps3_is_instance_state_normal(struct ps3_instance *instance,
unsigned char need_prk_err)
{
int cur_state = ps3_atomic_read(&instance->state_machine.state);
if (cur_state != PS3_INSTANCE_STATE_OPERATIONAL &&
cur_state != PS3_INSTANCE_STATE_PRE_OPERATIONAL &&
cur_state != PS3_INSTANCE_STATE_SOFT_RECOVERY) {
LOG_WARN_LIM_WITH_CHECK(instance, need_prk_err,
"hno:%u instance exception state %s\n",
PS3_HOST(instance),
namePS3InstanceState(cur_state));
return PS3_FALSE;
}
return PS3_TRUE;
}
static inline void ps3_pci_err_recovery_set(struct ps3_instance *instance,
unsigned char state)
{
instance->state_machine.is_pci_err_recovery = state;
}
static inline unsigned char
ps3_pci_err_recovery_get(struct ps3_instance *instance)
{
return instance->state_machine.is_pci_err_recovery;
}
static inline unsigned char
ps3_need_block_hard_reset_request(struct ps3_instance *instance)
{
int ret = PS3_SUCCESS;
if (ps3_pci_err_recovery_get(instance)) {
LOG_WARN_LIM(
"hno[%u], host in pci recovery during reset request\n",
PS3_HOST(instance));
ret = -PS3_FAILED;
goto end;
}
ps3_mutex_lock(&instance->state_machine.lock);
if (instance->recovery_context->host_reset_state !=
PS3_HOST_RESET_INIT) {
ps3_mutex_unlock(&instance->state_machine.lock);
LOG_WARN_LIM(
"hno[%u], host in host reset during reset request\n",
PS3_HOST(instance));
ret = -PS3_FAILED;
goto end;
}
ps3_mutex_unlock(&instance->state_machine.lock);
end:
return ((ret == PS3_SUCCESS) ? PS3_FALSE : PS3_TRUE);
}
static inline void
ps3_need_wait_hard_reset_request(struct ps3_instance *instance)
{
do {
if (ps3_pci_err_recovery_get(instance)) {
LOG_WARN_LIM(
"hno[%u], host in pci recovery during reset request\n",
PS3_HOST(instance));
ps3_msleep(100);
continue;
}
ps3_mutex_lock(&instance->state_machine.lock);
if (instance->recovery_context->host_reset_state !=
PS3_HOST_RESET_INIT) {
ps3_mutex_unlock(&instance->state_machine.lock);
LOG_WARN_LIM(
"hno[%u], host in host reset during reset request\n",
PS3_HOST(instance));
ps3_msleep(100);
continue;
}
ps3_mutex_unlock(&instance->state_machine.lock);
break;
} while (1);
}
static inline unsigned char ps3_state_is_normal(int cur_state)
{
return (cur_state != PS3_INSTANCE_STATE_OPERATIONAL &&
cur_state != PS3_INSTANCE_STATE_PRE_OPERATIONAL) ?
PS3_FALSE :
PS3_TRUE;
}
int ps3_instance_wait_for_normal(struct ps3_instance *instance);
int ps3_recovery_state_wait_for_normal(struct ps3_instance *instance);
struct ps3_ioc_adp_template {
int (*io_cmd_build)(struct ps3_cmd *cmd);
int (*mgr_cmd_build)(struct ps3_instance *instance,
struct ps3_cmd *cmd);
void (*init_cmd_send)(struct ps3_instance *instance,
struct PS3CmdWord *cmd_word);
void (*cmd_send)(struct ps3_instance *instance,
struct PS3CmdWord *cmd_word);
unsigned int (*ioc_state_get)(struct ps3_instance *instance);
int (*ioc_init_state_to_ready)(struct ps3_instance *instance);
int (*ioc_init_proc)(struct ps3_instance *instance);
void (*ioc_resource_prepare)(struct ps3_instance *instance);
int (*ioc_hard_reset)(struct ps3_instance *instance);
int (*ioc_shallow_soft_reset)(struct ps3_instance *instance);
int (*ioc_deep_soft_reset)(struct ps3_instance *instance);
int (*ioc_force_to_fault)(struct ps3_instance *instance);
int (*ioc_force_to_halt)(struct ps3_instance *instance);
int (*irq_init)(struct ps3_instance *instance);
void (*irq_enable)(struct ps3_instance *instance);
void (*irq_disable)(struct ps3_instance *instance);
#ifndef _WINDOWS
irqreturn_t (*isr)(int irq_no, void *data);
struct scsi_transport_template *(*sas_transport_get)(void);
#else
unsigned char (*isr)(void *instance, unsigned long irq_no);
#endif
void (*event_filter_table_get)(unsigned char *data);
void (*reg_write)(struct ps3_instance *instance, unsigned long long val,
void __iomem *reg);
unsigned long long (*reg_read)(struct ps3_instance *instance,
void __iomem *reg);
unsigned char (*is_need_direct_to_normal)(const struct ps3_cmd *cmd);
unsigned char (*max_replyq_count_get)(struct ps3_instance *instance,
unsigned int *max_replyq_count);
void (*check_vd_member_change)(struct ps3_instance *instance,
struct ps3_pd_entry *local_entry);
unsigned char (*scsih_stream_is_detect)(struct ps3_cmd *cmd);
unsigned char (*scsih_stream_is_direct)(const struct ps3_cmd *cmd);
unsigned int (*ioc_heartbeat_detect)(struct ps3_instance *instance);
void __iomem *(*reg_set)(struct pci_dev *pdev, unsigned long reg_bar);
unsigned char (*ioc_security_check)(struct ps3_instance *instance);
void (*io_cmd_rebuild)(struct ps3_cmd *cmd);
unsigned char (*rw_cmd_is_need_split)(struct ps3_cmd *cmd);
unsigned char (*write_direct_enable)(struct ps3_cmd *cmd);
unsigned char (*ssd_vd_qmask_calculate)(struct ps3_cmd *cmd);
};
#define PS3_DEVICE_IS_SWITCH(id) \
((id == PCI_DEVICE_ID_PS3_SWITCH || \
id == PCI_DEVICE_ID_PS3_SWITCH_FPGA))
#ifndef _WINDOWS
void ps3_ioc_adp_init(struct ps3_instance *instance,
const struct pci_device_id *id);
void ps3_remove(struct pci_dev *pdev);
#else
void ps3_ioc_adp_init(struct ps3_instance *instance);
#endif
static inline int ps3_get_pci_function(struct pci_dev *pci)
{
return PCI_FUNC(pci->devfn);
}
static inline int ps3_get_pci_slot(struct pci_dev *pci)
{
return PCI_SLOT(pci->devfn);
}
static inline int ps3_get_pci_bus(struct pci_dev *pci)
{
return pci->bus->number;
}
static inline int ps3_get_pci_domain(struct pci_dev *pci)
{
return pci_domain_nr(pci->bus);
}
static inline bool ps3_is_latest_func(struct ps3_instance *instance)
{
bool ret = PS3_TRUE;
struct ps3_instance *peer_instance = NULL;
list_for_each_entry(peer_instance,
&ps3_mgmt_info_get()->instance_list_head,
list_item) {
if ((peer_instance != NULL) &&
(ps3_get_pci_domain(peer_instance->pdev) ==
ps3_get_pci_domain(instance->pdev)) &&
(PCI_BUS_NUM(peer_instance->pdev->devfn) ==
PCI_BUS_NUM(instance->pdev->devfn)) &&
(PCI_SLOT(peer_instance->pdev->devfn) ==
PCI_SLOT(instance->pdev->devfn)) &&
(PCI_FUNC(peer_instance->pdev->devfn) !=
PCI_FUNC(instance->pdev->devfn))) {
ret = PS3_FALSE;
}
}
return ret;
}
static inline void ps3_get_so_addr_ranger(struct ps3_instance *instance,
unsigned long long addr,
unsigned int offset)
{
unsigned long long so_end_addr = (addr + offset) - 1;
if (instance->so_start_addr == 0 && instance->so_end_addr == 0) {
instance->so_start_addr = addr;
instance->so_end_addr = so_end_addr;
goto l_out;
}
instance->so_start_addr =
((addr < instance->so_start_addr) ? addr :
instance->so_start_addr);
instance->so_end_addr =
((so_end_addr > instance->so_end_addr) ? so_end_addr :
instance->so_end_addr);
l_out:
return;
}
void ps3_host_info_get(void);
unsigned short ps3_host_vendor_get(void);
char *ps3_host_release_get(void);
unsigned char ps3_is_last_func(struct ps3_instance *instance);
#endif

View File

@ -0,0 +1,127 @@
// SPDX-License-Identifier: GPL-2.0
#ifndef _WINDOWS
#include <linux/kernel.h>
#include <linux/compiler.h>
#include <linux/crc32.h>
#endif
#include "ps3_instance_manager.h"
#include "ps3_scsih_cmd_parse.h"
#include "ps3_io_trace.h"
#include "ps3_kernel_version.h"
static inline const char *ps3_io_trace_direct_name(enum ps3_io_trace_dtype type)
{
static const char *const direct_name[] = { "cmd send", "cmd recv",
"unknown" };
if (type >= PS3_IO_TRACE_DIRECT_COUNT)
return direct_name[PS3_IO_TRACE_DIRECT_COUNT];
return direct_name[type];
}
#ifndef _WINDOWS
static inline unsigned char ps3_is_scsi_read_cmd(struct scsi_cmnd *s_cmnd)
{
return (s_cmnd != NULL &&
s_cmnd->sc_data_direction == DMA_FROM_DEVICE &&
(s_cmnd->cmnd[0] == READ_6 || s_cmnd->cmnd[0] == READ_10 ||
s_cmnd->cmnd[0] == READ_12 || s_cmnd->cmnd[0] == READ_16));
}
static inline unsigned char ps3_is_scsi_write_cmd(struct scsi_cmnd *s_cmnd)
{
return (s_cmnd != NULL && s_cmnd->sc_data_direction == DMA_TO_DEVICE &&
(s_cmnd->cmnd[0] == WRITE_6 || s_cmnd->cmnd[0] == WRITE_10 ||
s_cmnd->cmnd[0] == WRITE_12 || s_cmnd->cmnd[0] == WRITE_16));
}
static void ps3_scsi_sgl_crc(const struct ps3_cmd *cmd)
{
unsigned int sge_count = 0;
unsigned int i = 0;
unsigned int crc = 0;
unsigned int seed = 0x1234;
char *pdata = NULL;
unsigned int buf_len = 0;
char buf[PS3_IO_TRACE_BUF_LEN] = { 0 };
struct scatterlist *os_sgl = NULL;
struct ps3_instance *instance = cmd->instance;
struct scsi_cmnd *s_cmnd = cmd->scmd;
if (instance->debug_context.io_trace_switch == PS3_FALSE)
goto l_out;
sge_count = cmd->os_sge_map_count;
scsi_for_each_sg(s_cmnd, os_sgl, sge_count, i) {
pdata = (char *)sg_virt(os_sgl);
crc = crc32(seed, pdata, sg_dma_len(os_sgl));
memset(buf, '\0', sizeof(buf));
buf_len = snprintf(
buf, PS3_IO_TRACE_BUF_LEN,
"hno:%u channel[%u], target[%u], trace_id[0x%llx], [%u of %u]sge\n"
"\tsge data addr[0x%llx] length[%u], D[%llx:%llx] CRC[0x%x]\n",
PS3_HOST(instance), s_cmnd->device->channel,
s_cmnd->device->id, cmd->trace_id, i + 1, sge_count,
(unsigned long long)sg_dma_address(os_sgl),
sg_dma_len(os_sgl), *(unsigned long long *)pdata,
*((unsigned long long *)(pdata + 8)), crc);
if (buf_len >= PS3_IO_TRACE_BUF_LEN) {
LOG_ERROR("buf_len > PS3_IO_TRACE_BUF_LEN\n");
goto l_out;
}
DATA_DUMP(NULL, 0, buf);
}
l_out:
return;
}
#endif
void ps3_scsih_io_trace(const struct ps3_cmd *cmd, enum ps3_io_trace_dtype type)
{
int buf_len = 0;
char buf[PS3_IO_TRACE_BUF_LEN] = { 0 };
unsigned long long lba = 0;
if (cmd == NULL || cmd->scmd == NULL) {
LOG_WARN("cmd or scmd is null\n");
goto l_out;
}
if (scsi_sg_count(cmd->scmd) == 0)
goto l_out;
#if defined(PS3_CMD_CDB_CHECK)
if (cmd->scmd->cmnd == NULL || cmd->instance->host == NULL) {
LOG_WARN("cdb null\n");
goto l_out;
}
#else
if (cmd->instance->host == NULL) {
LOG_WARN("cdb null\n");
goto l_out;
}
#endif
if ((type == PS3_IO_TRACE_DIRECT_SEND &&
ps3_is_scsi_write_cmd(cmd->scmd)) ||
(type == PS3_IO_TRACE_DIRECT_RECV &&
ps3_is_scsi_read_cmd(cmd->scmd))) {
ps3_scsi_sgl_crc(cmd);
}
ps3_scsih_lba_parse(cmd->scmd->cmnd, &lba);
memset(buf, '\0', sizeof(buf));
buf_len = snprintf(buf, PS3_IO_TRACE_BUF_LEN,
"%s, trace_id[0x%llx], hno:%u lba[0x%llx]\n",
ps3_io_trace_direct_name(type), cmd->trace_id,
PS3_HOST(cmd->instance), lba);
if (buf_len >= PS3_IO_TRACE_BUF_LEN) {
LOG_ERROR("buf_len > PS3_IO_TRACE_BUF_LEN\n");
goto l_out;
}
DATA_DUMP(sg_virt(cmd->scmd->sdb.table.sgl),
min_t(unsigned int, cmd->scmd->sdb.table.sgl[0].length,
PS3_IO_TRACE_PRINT_COUNT),
buf);
l_out:
return;
}

View File

@ -0,0 +1,27 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef _PS3_IO_TRACE_H_
#define _PS3_IO_TRACE_H_
#include "ps3_cmd_channel.h"
#define PS3_IO_TRACE_PRINT_COUNT (32)
#define PS3_IO_TRACE_BUF_LEN (256)
enum ps3_io_trace_dtype {
PS3_IO_TRACE_DIRECT_SEND,
PS3_IO_TRACE_DIRECT_RECV,
PS3_IO_TRACE_DIRECT_COUNT,
};
void ps3_scsih_io_trace(const struct ps3_cmd *cmd,
enum ps3_io_trace_dtype type);
#define PS3_IO_TRACE(cmd, type) \
do { \
if ((cmd)->instance->debug_context.io_trace_switch == \
PS3_FALSE) { \
break; \
} \
ps3_scsih_io_trace((cmd), (type)); \
} while (0)
#endif

View File

@ -0,0 +1,459 @@
// SPDX-License-Identifier: GPL-2.0
#ifdef _WINDOWS
#include "ps3_def.h"
#endif
#include "ps3_instance_manager.h"
#include "ps3_ioc_state.h"
#include "ps3_irq.h"
#include "ps3_ioc_manager.h"
#include "ps3_scsih_cmd_parse.h"
#include "ps3_scsih.h"
#include "ps3_inner_data.h"
#include "ps3_event.h"
#include "ps3_device_update.h"
#include "ps3_pci.h"
#include "ps3_module_para.h"
#include "ps3_scsih.h"
#define MAX_MGR_CMD_COUNT (8)
#define MAX_TASK_CMD_COUNT (8)
#define MIN_MSIX_INT_COUNT (1)
#define PS3_HARD_DOG_MASK (0xF000000UL)
#define SWITCH_MAX_MGR_CMD_COUNT (12)
#define SWITCH_MAX_TASK_CMD_COUNT (2)
#define SWITCH_MAX_MGR_CMD_TOTAL_COUNT (14)
#define SWITCH_MIN_MSI_INT_COUNT (1)
#define SWITCH_REPLY_FIFO_DEP_ADDITION (1)
#define PS3_HARD_DOG_MASK_SWITCH (0x1000000UL)
struct ps3_ioc_adp_temp_entry {
unsigned short device_id;
struct ps3_ioc_adp_template *adp_template;
};
void ps3_ioc_resource_prepare_switch(struct ps3_instance *instance)
{
struct PS3MgrEvent *event_req_info = &instance->event_req_info;
memset(event_req_info, 0, sizeof(struct PS3MgrEvent));
event_req_info->eventTypeMap = PS3_EVT_PD_COUNT;
event_req_info->eventLevel = PS3_EVENT_LEVEL_INFO;
event_req_info->eventTypeMapProcResult = PS3_EVT_ILLEGAL_TYPE;
instance->max_mgr_cmd_total_count = SWITCH_MAX_MGR_CMD_TOTAL_COUNT;
instance->max_mgr_cmd_count = SWITCH_MAX_MGR_CMD_COUNT;
instance->max_task_cmd_count = SWITCH_MAX_TASK_CMD_COUNT;
instance->min_intr_count = SWITCH_MIN_MSI_INT_COUNT;
instance->reply_fifo_depth_addition = SWITCH_REPLY_FIFO_DEP_ADDITION;
instance->is_support_jbod = PS3_TRUE;
instance->use_clusting = PS3_TRUE;
instance->is_use_frontend_prp = PS3_FALSE;
instance->is_adjust_register_count = PS3_FALSE;
instance->is_probe_finish = PS3_FALSE;
instance->is_probe_failed = PS3_FALSE;
instance->is_suspend = PS3_FALSE;
instance->is_resume = PS3_FALSE;
instance->is_hard_reset = PS3_FALSE;
instance->is_pci_reset = PS3_FALSE;
instance->ioc_fw_version = 0;
instance->hilMode = HIL_MODEL_SW;
instance->unload_timeout = PS3_DEFAULT_MGR_CMD_TIMEOUT;
instance->wait_ready_timeout =
PS3_FW_STATE_TO_READY_TMO_LOOP_COUNT_SWITCH;
instance->is_half_hard_reset = PS3_FALSE;
instance->is_need_event = PS3_FALSE;
instance->is_raid1_direct_skip_mapblock_check = PS3_FALSE;
instance->is_single_disk_raid0_direct_skip_strip_check = PS3_FALSE;
instance->is_support_dump_ctrl = PS3_FALSE;
instance->is_support_io_limit = PS3_FALSE;
instance->is_irq_prk_support = PS3_FALSE;
instance->is_support_irq = PS3_FALSE;
instance->is_raid = PS3_FALSE;
instance->hard_dog_mask = PS3_HARD_DOG_MASK_SWITCH;
instance->task_manager_host_busy = PS3_FALSE;
instance->is_print_special_log = PS3_FALSE;
instance->r1x_mode = PS3_R1X_MODE_NORMAL;
instance->smp_affinity_enable = ps3_smp_affinity_query();
instance->page_mode_change =
ps3_host_vendor_get() == PS3_HOST_VENDOR_INTEL ? PS3_FALSE :
PS3_TRUE;
instance->page_mode_addr_mask = PS3_PAGE_MODE_ABOVE_3_ADDR_MASK;
ps3_mutex_init(&instance->task_mgr_reset_lock);
ps3_mutex_init(&instance->task_abort_lock);
}
void ps3_ioc_resource_prepare_raid(struct ps3_instance *instance)
{
struct PS3MgrEvent *event_req_info = &instance->event_req_info;
memset(event_req_info, 0, sizeof(struct PS3MgrEvent));
event_req_info->eventTypeMap = PS3_EVT_PD_COUNT | PS3_EVT_VD_COUNT |
PS3_EVT_CTRL_INFO | PS3_EVT_PD_ATTR;
event_req_info->eventLevel = PS3_EVENT_LEVEL_INFO;
event_req_info->eventTypeMapProcResult = PS3_EVT_ILLEGAL_TYPE;
instance->max_mgr_cmd_total_count = MAX_MGR_CMD_TOTAL_COUNT;
instance->max_mgr_cmd_count = MAX_MGR_CMD_COUNT;
instance->max_task_cmd_count = MAX_TASK_CMD_COUNT;
instance->min_intr_count = MIN_MSIX_INT_COUNT;
instance->is_support_jbod = PS3_TRUE;
instance->use_clusting = (ps3_use_clustering_query() == PS3_TRUE);
instance->is_use_frontend_prp = PS3_FALSE;
instance->is_adjust_register_count = PS3_TRUE;
instance->is_probe_finish = PS3_FALSE;
instance->is_probe_failed = PS3_FALSE;
instance->is_suspend = PS3_FALSE;
instance->is_resume = PS3_FALSE;
instance->is_hard_reset = PS3_FALSE;
instance->is_pci_reset = PS3_FALSE;
instance->ioc_fw_version = 0;
instance->hilMode = HIL_MODEL_HW_ENHANCED;
instance->unload_timeout = PS3_RAID_UNLOAD_MGR_CMD_TIMEOUT;
#ifdef PS3_HARDWARE_HAPS_V200
instance->wait_ready_timeout =
PS3_FW_STATE_TO_READY_TMO_LOOP_COUNT_RAID_HAPS;
#else
instance->wait_ready_timeout =
PS3_FW_STATE_TO_READY_TMO_LOOP_COUNT_RAID;
#endif
instance->is_half_hard_reset = PS3_FALSE;
instance->is_need_event = PS3_TRUE;
instance->is_raid1_direct_skip_mapblock_check = PS3_FALSE;
instance->is_single_disk_raid0_direct_skip_strip_check = PS3_FALSE;
instance->is_support_dump_ctrl = PS3_TRUE;
instance->is_support_io_limit = PS3_TRUE;
instance->is_irq_prk_support = PS3_FALSE;
instance->is_support_irq = PS3_FALSE;
instance->is_raid = PS3_TRUE;
instance->hard_dog_mask = PS3_HARD_DOG_MASK;
instance->is_print_special_log = PS3_FALSE;
instance->r1x_mode = PS3_R1X_MODE_NORMAL;
instance->task_manager_host_busy = PS3_FALSE;
instance->smp_affinity_enable = ps3_smp_affinity_query();
instance->page_mode_change =
ps3_host_vendor_get() == PS3_HOST_VENDOR_INTEL ? PS3_FALSE :
PS3_TRUE;
instance->page_mode_addr_mask = PS3_PAGE_MODE_ABOVE_3_ADDR_MASK;
ps3_mutex_init(&instance->task_mgr_reset_lock);
ps3_mutex_init(&instance->task_abort_lock);
ps3_raid_qos_prepare(instance);
}
void ps3_ioc_resource_prepare_hba(struct ps3_instance *instance)
{
struct PS3MgrEvent *event_req_info = &instance->event_req_info;
memset(event_req_info, 0, sizeof(struct PS3MgrEvent));
event_req_info->eventTypeMap = PS3_EVT_PD_COUNT | PS3_EVT_VD_COUNT |
PS3_EVT_CTRL_INFO | PS3_EVT_SAS_INFO |
PS3_EVT_PD_ATTR;
event_req_info->eventLevel = PS3_EVENT_LEVEL_INFO;
event_req_info->eventTypeMapProcResult = PS3_EVT_ILLEGAL_TYPE;
instance->max_mgr_cmd_total_count = MAX_MGR_CMD_TOTAL_COUNT;
instance->max_mgr_cmd_count = MAX_MGR_CMD_COUNT;
instance->max_task_cmd_count = MAX_TASK_CMD_COUNT;
instance->min_intr_count = MIN_MSIX_INT_COUNT;
instance->is_support_jbod = PS3_FALSE;
instance->use_clusting = (ps3_use_clustering_query() == PS3_TRUE);
instance->is_use_frontend_prp = PS3_TRUE;
instance->is_adjust_register_count = PS3_TRUE;
instance->is_probe_finish = PS3_FALSE;
instance->is_probe_failed = PS3_FALSE;
instance->is_suspend = PS3_FALSE;
instance->is_resume = PS3_FALSE;
instance->is_scan_host_finish = PS3_FALSE;
instance->is_hard_reset = PS3_FALSE;
instance->is_pci_reset = PS3_FALSE;
instance->is_halt_support_cli = PS3_FALSE;
ps3_atomic_set(&instance->reg_op_count, 0);
instance->ioc_fw_version = 0;
instance->hilMode = HIL_MODEL_HW_ENHANCED;
instance->unload_timeout = PS3_UNLOAD_MGR_CMD_TIMEOUT;
instance->wait_ready_timeout = PS3_FW_STATE_TO_READY_TMO_LOOP_COUNT_HBA;
instance->is_half_hard_reset = PS3_FALSE;
instance->is_need_event = PS3_TRUE;
instance->is_raid1_direct_skip_mapblock_check = PS3_TRUE;
instance->is_single_disk_raid0_direct_skip_strip_check = PS3_TRUE;
instance->is_support_dump_ctrl = PS3_TRUE;
instance->is_support_io_limit = PS3_FALSE;
instance->is_irq_prk_support = PS3_FALSE;
instance->is_support_irq = PS3_FALSE;
instance->is_raid = PS3_FALSE;
instance->hard_dog_mask = PS3_HARD_DOG_MASK;
instance->is_print_special_log = PS3_FALSE;
instance->smp_affinity_enable = ps3_smp_affinity_query();
ps3_atomic_set(&instance->host_reset_processing, 0);
instance->task_manager_host_busy = PS3_FALSE;
instance->r1x_mode = PS3_R1X_MODE_NORMAL;
instance->page_mode_change =
ps3_host_vendor_get() == PS3_HOST_VENDOR_INTEL ? PS3_FALSE :
PS3_TRUE;
instance->page_mode_addr_mask = PS3_PAGE_MODE_ABOVE_3_ADDR_MASK;
ps3_mutex_init(&instance->task_mgr_reset_lock);
ps3_mutex_init(&instance->task_abort_lock);
ps3_hba_qos_prepare(instance);
}
static unsigned char
ps3_replyq_count_raidhba_get(struct ps3_instance *instance,
unsigned int *max_replyq_count)
{
unsigned char ret = PS3_TRUE;
if (!ps3_max_replyq_count_get(instance, max_replyq_count)) {
LOG_ERROR("hno:%u ps3_max_replyq_count_get NOK!\n",
PS3_HOST(instance));
ret = PS3_FALSE;
goto l_out;
}
*max_replyq_count += PS3_RAIDHBA_NUM_ADJUST_VALUE;
*max_replyq_count = *max_replyq_count > PS3_MAX_REPLY_QUE_COUNT ?
PS3_MAX_REPLY_QUE_COUNT :
*max_replyq_count;
l_out:
return ret;
}
static unsigned char ps3_is_need_direct_to_normal_hba(const struct ps3_cmd *cmd)
{
unsigned char ret = PS3_TRUE;
if (ps3_direct_to_normal_query()) {
ret = PS3_TRUE;
goto l_out;
}
if (cmd->io_attr.dev_type == PS3_DEV_TYPE_NVME_SSD) {
ret = PS3_TRUE;
goto l_out;
}
if (cmd->io_attr.dev_type != PS3_DEV_TYPE_VD) {
ret = PS3_FALSE;
goto l_out;
}
if (unlikely(cmd->io_attr.vd_entry == NULL)) {
ret = PS3_FALSE;
goto l_out;
}
if (cmd->io_attr.vd_entry->isNvme) {
ret = PS3_TRUE;
goto l_out;
}
l_out:
return ret;
}
static unsigned char
ps3_is_need_direct_to_normal_raid(const struct ps3_cmd *cmd)
{
(void)cmd;
return PS3_TRUE;
}
static unsigned char
ps3_is_need_direct_to_normal_switch(const struct ps3_cmd *cmd)
{
(void)cmd;
return PS3_FALSE;
}
struct ps3_ioc_adp_template g_ps3_template_switch = {
.io_cmd_build = ps3_scsih_cmd_build,
.mgr_cmd_build = NULL,
.init_cmd_send = ps3_switch_init_cmd_send,
.cmd_send = ps3_switch_normal_cmd_send,
.ioc_state_get = ps3_ioc_state_get,
.ioc_init_state_to_ready = ps3_ioc_init_to_ready,
.ioc_init_proc = ps3_ioc_init_proc,
.ioc_resource_prepare = ps3_ioc_resource_prepare_switch,
.ioc_hard_reset = ps3_ioc_state_hard_reset,
.ioc_shallow_soft_reset = ps3_ioc_state_shallow_soft_reset,
.ioc_deep_soft_reset = ps3_ioc_state_deep_soft_reset,
.ioc_force_to_fault = ps3_ioc_state_force_to_fault,
.ioc_force_to_halt = ps3_ioc_state_force_to_halt,
.irq_init = ps3_irqs_init_switch,
.irq_enable = ps3_irqs_enable,
.irq_disable = ps3_irqs_disable,
.isr = ps3_irqs_service,
#ifndef _WINDOWS
.sas_transport_get = NULL,
#endif
.event_filter_table_get = ps3_event_filter_table_get_switch,
.reg_write = ps3_reg_write_u64,
#ifdef _WINDOWS
.reg_read = ps3_reg_read_u64,
#else
.reg_read = ps3_switch_ioc_reg_read,
#endif
.is_need_direct_to_normal = ps3_is_need_direct_to_normal_switch,
.max_replyq_count_get = ps3_max_replyq_count_get,
.check_vd_member_change = NULL,
.scsih_stream_is_detect = NULL,
.scsih_stream_is_direct = NULL,
#ifdef PS3_HARDWARE_ASIC
.ioc_heartbeat_detect = ps3_ioc_heartbeat_detect,
#else
.ioc_heartbeat_detect = NULL,
#endif
.reg_set = NULL,
.ioc_security_check = NULL,
.io_cmd_rebuild = ps3_scsih_direct_to_normal_req_frame_rebuild,
.rw_cmd_is_need_split = NULL,
.write_direct_enable = NULL,
.ssd_vd_qmask_calculate = NULL,
};
struct ps3_ioc_adp_template g_ps3_template_hba = {
.io_cmd_build = ps3_scsih_cmd_build,
.mgr_cmd_build = NULL,
.init_cmd_send = ps3_switch_init_cmd_send,
.cmd_send = ps3_ioc_cmd_send,
.ioc_state_get = ps3_ioc_state_get,
.ioc_init_state_to_ready = ps3_ioc_init_to_ready,
.ioc_init_proc = ps3_ioc_init_proc,
.ioc_resource_prepare = ps3_ioc_resource_prepare_hba,
.ioc_hard_reset = ps3_ioc_state_hard_reset,
.ioc_shallow_soft_reset = ps3_ioc_state_shallow_soft_reset,
.ioc_deep_soft_reset = ps3_ioc_state_deep_soft_reset,
.ioc_force_to_fault = ps3_ioc_state_force_to_fault,
.ioc_force_to_halt = ps3_ioc_state_force_to_halt,
.irq_init = ps3_irqs_init,
.irq_enable = ps3_irqs_enable,
.irq_disable = ps3_irqs_disable,
.isr = ps3_irqs_service,
#ifndef _WINDOWS
.sas_transport_get = ps3_sas_transport_get,
#endif
.event_filter_table_get = ps3_event_filter_table_get_hba,
.reg_write = ps3_reg_write_u64,
.reg_read = ps3_reg_read_u64,
.is_need_direct_to_normal = ps3_is_need_direct_to_normal_hba,
.max_replyq_count_get = ps3_replyq_count_raidhba_get,
.check_vd_member_change = ps3_check_vd_member_change,
.scsih_stream_is_detect = ps3_scsih_stream_is_detect,
.scsih_stream_is_direct = ps3_hba_scsih_stream_is_direct,
#ifdef PS3_HARDWARE_ASIC
.ioc_heartbeat_detect = ps3_ioc_heartbeat_detect,
#else
.ioc_heartbeat_detect = NULL,
#endif
.reg_set = ps3_reg_set_ioremap,
.ioc_security_check = NULL,
.io_cmd_rebuild = ps3_scsih_direct_to_normal_req_frame_rebuild,
.rw_cmd_is_need_split = ps3_scsih_rw_cmd_is_need_split_hba,
.write_direct_enable = NULL,
.ssd_vd_qmask_calculate = ps3_ssd_vd_qmask_calculate_hba,
};
struct ps3_ioc_adp_template g_ps3_template_raid = {
.io_cmd_build = ps3_scsih_cmd_build,
.mgr_cmd_build = NULL,
.init_cmd_send = ps3_switch_init_cmd_send,
.cmd_send = ps3_ioc_cmd_send,
.ioc_state_get = ps3_ioc_state_get,
.ioc_init_state_to_ready = ps3_ioc_init_to_ready,
.ioc_init_proc = ps3_ioc_init_proc,
.ioc_resource_prepare = ps3_ioc_resource_prepare_raid,
.ioc_hard_reset = ps3_ioc_state_hard_reset,
.ioc_shallow_soft_reset = ps3_ioc_state_shallow_soft_reset,
.ioc_deep_soft_reset = ps3_ioc_state_deep_soft_reset,
.ioc_force_to_fault = ps3_ioc_state_force_to_fault,
.ioc_force_to_halt = ps3_ioc_state_force_to_halt,
.irq_init = ps3_irqs_init,
.irq_enable = ps3_irqs_enable,
.irq_disable = ps3_irqs_disable,
.isr = ps3_irqs_service,
#ifndef _WINDOWS
.sas_transport_get = NULL,
#endif
.event_filter_table_get = ps3_event_filter_table_get_raid,
.reg_write = ps3_reg_write_u64,
.reg_read = ps3_reg_read_u64,
.is_need_direct_to_normal = ps3_is_need_direct_to_normal_raid,
.max_replyq_count_get = ps3_replyq_count_raidhba_get,
.check_vd_member_change = NULL,
.scsih_stream_is_detect = ps3_scsih_stream_is_detect,
.scsih_stream_is_direct = ps3_raid_scsih_stream_is_direct,
#ifdef PS3_HARDWARE_ASIC
.ioc_heartbeat_detect = ps3_ioc_heartbeat_detect,
#else
.ioc_heartbeat_detect = NULL,
#endif
.reg_set = ps3_reg_set_ioremap,
.ioc_security_check = ps3_ioc_security_state_check,
.io_cmd_rebuild = ps3_scsih_direct_to_normal_req_frame_rebuild,
.rw_cmd_is_need_split = ps3_scsih_rw_cmd_is_need_split_raid,
.write_direct_enable = ps3_write_direct_enable,
.ssd_vd_qmask_calculate = NULL,
};
static struct ps3_ioc_adp_temp_entry ps3_ioc_adp_template_map[] = {
{ PCI_DEVICE_ID_PS3_RAID, &g_ps3_template_raid },
{ PCI_DEVICE_ID_PS3_HBA, &g_ps3_template_hba },
{ PCI_DEVICE_ID_PS3_SWITCH, &g_ps3_template_switch },
{ PCI_DEVICE_ID_PS3_SWITCH_FPGA, &g_ps3_template_switch },
{ PCI_DEVICE_ID_STARS_IOC_2020_18i, &g_ps3_template_hba },
{ PCI_DEVICE_ID_STARS_ROC_2020_10i, &g_ps3_template_raid },
{ PCI_DEVICE_ID_PS3_RAID_FPGA, &g_ps3_template_raid },
{ PCI_DEVICE_ID_STARS_IOC_2213_16i, &g_ps3_template_hba },
};
#ifndef _WINDOWS
void ps3_ioc_adp_init(struct ps3_instance *instance,
const struct pci_device_id *id)
{
unsigned short i = 0;
unsigned short adp_num = sizeof(ps3_ioc_adp_template_map) /
sizeof(struct ps3_ioc_adp_temp_entry);
for (i = 0; i < adp_num; i++) {
if (id->device == ps3_ioc_adp_template_map[i].device_id) {
instance->ioc_adpter =
ps3_ioc_adp_template_map[i].adp_template;
}
}
instance->ioc_adpter->ioc_resource_prepare(instance);
}
#else
void ps3_ioc_adp_init(struct ps3_instance *instance)
{
unsigned short i = 0;
unsigned short adp_num = sizeof(ps3_ioc_adp_template_map) /
sizeof(struct ps3_ioc_adp_temp_entry);
for (i = 0; i < adp_num; i++) {
if (instance->pci_dev_context.device_id ==
ps3_ioc_adp_template_map[i].device_id) {
instance->ioc_adpter =
ps3_ioc_adp_template_map[i].adp_template;
LOG_WARN(
"hno:%u pci dev type is [%s]\n",
PS3_HOST(instance),
namePciDevType(
ps3_ioc_adp_template_map[i].device_id));
#ifdef _WINDOWS
instance->ioc_adpter->event_filter_table_get =
ps3_event_filter_table_get_raid;
#endif
}
}
instance->ioc_adpter->ioc_resource_prepare(instance);
}
#endif

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,925 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef _PS3_IOC_MANAGER_H_
#define _PS3_IOC_MANAGER_H_
#include "ps3_instance_manager.h"
#include "ps3_inner_data.h"
#include "ps3_module_para.h"
#include "ps3_ioc_state.h"
#define PS3_REG_SESSION_ADDR_WRITE(instance, val, reg) \
do { \
ps3_reg_dump(instance, reg, val, PS3_FALSE); \
ps3_ioc_reg_write(instance, val, reg); \
} while (0)
#define PS3_MAX_CMD_COUNT_DURING_RESET_DEVICES (100)
#define PS3_REG_READ_INTERVAL_MS (10)
#if (defined PS3_HARDWARE_FPGA && defined PS3_MODEL_V200)
#define PS3_REG_WRITE_RETRY_NUM (60)
#else
#define PS3_REG_WRITE_RETRY_NUM (10)
#endif
#define PS3_REG_WRITE_INTERVAL_MS (10)
#define PS3_REG_READ_RETRY_NUM (5000)
#define PS3_ATU_SUPPORT_READ_RETRY_NUM (3)
#define PS3_REG_READ_SAFE_RETRY_NUM (3)
#define PS3_HOST_MEM_INFO_NUM (1)
#define PS3_IOC_STATE_HALT_SUPPORT(ins) (ins->is_ioc_halt_support)
#define PS3_IOC_SHALLOW_SOFT_RECOVERY_SUPPORT(ins) \
(ins->is_shallow_soft_recovery_support)
#define PS3_IOC_DEEP_SOFT_RECOVERY_SUPPORT(ins) \
((ins->is_deep_soft_recovery_support) && \
ps3_deep_soft_reset_enable_query())
#define PS3_IOC_HARD_RECOVERY_SUPPORT(ins) \
(PS3_INSTANCE_ABNORMAL_FORCE_HARD_RECOVERY(ins) || \
ins->is_hard_recovery_support)
#define PS3_HALT_CLI_SUPPORT(ins) (ins->is_halt_support_cli)
#define PS3_IOC_REG_READ_WITH_CHECK(instance, reg_type, reg_name, read_value) \
do { \
ps3_atomic_inc(&(instance)->reg_op_count); \
mb(); /* in order to force CPU ordering */ \
if ((instance)->is_hard_reset == PS3_FALSE && \
(instance)->is_pci_reset == PS3_FALSE) { \
read_value = ps3_ioc_reg_read_with_check( \
instance, \
&(instance)->reg_set->reg_type.reg_name); \
} else { \
LOG_FILE_ERROR( \
"hno:%u register %p,read blocked by hardreset(%d)\n" \
"\tor pci err(%d)\n", \
PS3_HOST(instance), \
&(instance)->reg_set->reg_type.reg_name, \
(instance)->is_hard_reset, \
(instance)->is_pci_reset); \
read_value = U64_MAX; \
} \
ps3_atomic_dec(&(instance)->reg_op_count); \
} while (0)
#define PS3_IOC_REG_READ_SAFE_WITH_RETRY(instance, reg_type, reg_name, \
read_value) \
do { \
ps3_atomic_inc(&(instance)->reg_op_count); \
mb(); /* in order to force CPU ordering */ \
if ((instance)->is_hard_reset == PS3_FALSE && \
(instance)->is_pci_reset == PS3_FALSE) { \
read_value = ps3_ioc_reg_retry_safe_read( \
instance, \
&(instance)->reg_set->reg_type.reg_name); \
} else { \
LOG_FILE_ERROR( \
"hno:%u register %p,read blocked by hardreset(%d)\n" \
"\tor pci err(%d)\n", \
PS3_HOST(instance), \
&(instance)->reg_set->reg_type.reg_name, \
(instance)->is_hard_reset, \
(instance)->is_pci_reset); \
read_value = U64_MAX; \
} \
ps3_atomic_dec(&(instance)->reg_op_count); \
} while (0)
#define PS3_IOC_REG_READ_OFFSET(instance, offset, read_value) \
do { \
ps3_atomic_inc(&(instance)->reg_op_count); \
mb(); /* in order to force CPU ordering */ \
if ((instance)->is_hard_reset == PS3_FALSE && \
(instance)->is_pci_reset == PS3_FALSE) { \
read_value = ps3_ioc_reg_read( \
instance, \
(unsigned char *)(instance)->reg_set + \
(offset)); \
} else { \
LOG_FILE_ERROR( \
"hno:%u register %p, read blocked by hardreset(%d)\n" \
"\tor pci err(%d)\n", \
PS3_HOST(instance), \
(unsigned char *)(instance)->reg_set + \
(offset), \
(instance)->is_hard_reset, \
instance->is_pci_reset); \
read_value = U64_MAX; \
} \
ps3_atomic_dec(&(instance)->reg_op_count); \
} while (0)
#define PS3_IOC_REG_READ_OFFSET_WITCH_CHECK(instance, offset, read_value) \
do { \
ps3_atomic_inc(&(instance)->reg_op_count); \
mb(); /* in order to force CPU ordering */ \
if ((instance)->is_hard_reset == PS3_FALSE && \
(instance)->is_pci_reset == PS3_FALSE) { \
read_value = ps3_ioc_reg_read_with_check( \
instance, \
(unsigned char *)(instance)->reg_set + \
(offset)); \
} else { \
LOG_WARN( \
"hno:%u register %p, read blocked by hardreset(%d)\n" \
"\tor pci recovery(%d)\n", \
PS3_HOST(instance), \
(unsigned char *)(instance)->reg_set + \
(offset), \
(instance)->is_hard_reset, \
instance->is_pci_reset); \
read_value = U64_MAX; \
} \
ps3_atomic_dec(&(instance)->reg_op_count); \
} while (0)
#define PS3_IOC_REG_WRITE(instance, reg_type, reg_name, value) \
do { \
ps3_atomic_inc(&(instance)->reg_op_count); \
mb(); /* in order to force CPU ordering */ \
if ((instance)->is_hard_reset == PS3_FALSE && \
(instance)->is_pci_reset == PS3_FALSE) { \
ps3_ioc_reg_write( \
instance, value, \
&(instance)->reg_set->reg_type.reg_name); \
} else { \
LOG_FILE_ERROR( \
"hno:%u register %p,write blocked by hardreset(%d)\n" \
"\tor pci err(%d)\n", \
PS3_HOST(instance), \
&(instance)->reg_set->reg_type.reg_name, \
(instance)->is_hard_reset, \
instance->is_pci_reset); \
} \
ps3_atomic_dec(&(instance)->reg_op_count); \
} while (0)
#define PS3_IOC_REG_WRITE_OFFSET(instance, offset, value) \
do { \
ps3_atomic_inc(&(instance)->reg_op_count); \
mb(); /* in order to force CPU ordering */ \
if ((instance)->is_hard_reset == PS3_FALSE && \
(instance)->is_pci_reset == PS3_FALSE) { \
ps3_ioc_reg_write( \
instance, value, \
(unsigned char *)(instance)->reg_set + \
(offset)); \
} else { \
LOG_FILE_ERROR( \
"hno:%u register %p,write blocked by hardreset(%d)\n" \
"\tor pci err(%d)\n", \
PS3_HOST(instance), \
(unsigned char *)(instance)->reg_set + \
(offset), \
(instance)->is_hard_reset, \
instance->is_pci_reset); \
} \
ps3_atomic_dec(&(instance)->reg_op_count); \
} while (0)
#define PS3_IOC_REG_WRITE_WITH_CHECK(instance, reg_type, reg_name, value) \
do { \
ps3_atomic_inc(&(instance)->reg_op_count); \
mb(); /* in order to force CPU ordering */ \
if ((instance)->is_hard_reset == PS3_FALSE && \
(instance)->is_pci_reset == PS3_FALSE) { \
ps3_ioc_reg_write_with_check( \
instance, value, \
&(instance)->reg_set->reg_type.reg_name); \
} else { \
LOG_WARN( \
"hno:%u register %p,write blocked by hardreset(%d)\n" \
"\tor pci recovery(%d)\n", \
PS3_HOST(instance), \
&(instance)->reg_set->reg_type.reg_name, \
(instance)->is_hard_reset, \
instance->is_pci_reset); \
} \
ps3_atomic_dec(&(instance)->reg_op_count); \
} while (0)
#define PS3_IOC_REG_WRITE_OFFSET_WITH_CHECK(instance, offset, value) \
do { \
ps3_atomic_inc(&(instance)->reg_op_count); \
mb(); /* in order to force CPU ordering */ \
if ((instance)->is_hard_reset == PS3_FALSE && \
(instance)->is_pci_reset == PS3_FALSE) { \
ps3_ioc_reg_write_with_check( \
instance, value, \
(unsigned char *)(instance)->reg_set + \
(offset)); \
} else { \
LOG_WARN( \
"hno:%u register %p,write blocked by hardreset(%d)\n" \
"\tor pci recovery(%d)\n", \
PS3_HOST(instance), \
(unsigned char *)(instance)->reg_set + \
(offset), \
(instance)->is_hard_reset, \
instance->is_pci_reset); \
} \
ps3_atomic_dec(&(instance)->reg_op_count); \
} while (0)
int ps3_ioc_init_cmd_context_init(struct ps3_instance *instance);
void ps3_ioc_init_cmd_context_exit(struct ps3_instance *instance);
void ps3_ioc_cmd_send(struct ps3_instance *instance,
struct PS3CmdWord *cmd_word);
void ps3_switch_init_cmd_send(struct ps3_instance *instance,
struct PS3CmdWord *cmd_word);
void ps3_switch_normal_cmd_send(struct ps3_instance *instance,
struct PS3CmdWord *cmd_word);
void ps3_ioc_legacy_irqs_enable(struct ps3_instance *instance);
void ps3_ioc_legacy_irqs_disable(struct ps3_instance *instance);
void ps3_ioc_msi_enable(struct ps3_instance *instance);
void ps3_ioc_msi_disable(struct ps3_instance *instance);
void ps3_ioc_msix_enable(struct ps3_instance *instance);
void ps3_ioc_msix_disable(struct ps3_instance *instance);
unsigned char ps3_ioc_is_legacy_irq_existed(struct ps3_instance *instance);
int ps3_drv_info_buf_alloc(struct ps3_instance *instance);
void ps3_drv_info_buf_free(struct ps3_instance *instance);
int ps3_host_mem_info_buf_alloc(struct ps3_instance *instance);
void ps3_host_mem_info_buf_free(struct ps3_instance *instance);
int ps3_ioc_init_to_ready(struct ps3_instance *instance);
int ps3_ioc_hard_reset_to_ready(struct ps3_instance *instance);
int ps3_ioc_init_proc(struct ps3_instance *instance);
void ps3_ioc_reg_write(struct ps3_instance *instance, unsigned long long val,
void __iomem *reg);
void ps3_ioc_hardreset_reg_write(struct ps3_instance *instance,
unsigned long long val, void __iomem *reg,
unsigned char is_warn_prk);
unsigned long long ps3_ioc_hardreset_reg_read(struct ps3_instance *instance,
void __iomem *reg);
unsigned long long ps3_ioc_reg_read(struct ps3_instance *instance,
void __iomem *reg);
unsigned long long ps3_ioc_reg_read_with_check(struct ps3_instance *instance,
void __iomem *reg);
static inline unsigned char ps3_ioc_state_valid_check(unsigned int fw_cur_state)
{
return ((fw_cur_state > PS3_FW_STATE_START) &&
(fw_cur_state != PS3_FW_STATE_MASK));
}
unsigned long long ps3_ioc_reg_retry_safe_read(struct ps3_instance *instance,
void __iomem *reg);
static inline void ps3_ioc_reg_write_with_check(struct ps3_instance *instance,
unsigned long long val,
void __iomem *reg)
{
unsigned char try_count = 0;
ps3_reg_dump(instance, reg, val, PS3_FALSE);
if (instance->ioc_adpter->reg_write) {
while (try_count != PS3_REG_WRITE_RETRY_NUM) {
instance->ioc_adpter->reg_write(instance, val, reg);
if (instance->ioc_adpter->reg_read(instance, reg) ==
val) {
break;
}
try_count++;
ps3_msleep(PS3_REG_WRITE_INTERVAL_MS);
}
} else {
LOG_ERROR("hno:%u no register write\n", PS3_HOST(instance));
}
if (try_count == PS3_REG_WRITE_RETRY_NUM)
ps3_instance_state_transfer_to_dead(instance);
}
unsigned long long ps3_switch_ioc_reg_read(struct ps3_instance *instance,
void __iomem *reg);
static inline void
ps3_ioc_mgr_req_queue_lock_init(struct ps3_instance *instance)
{
ps3_spin_lock_init(&instance->req_queue_lock);
}
static inline unsigned char
ps3_ioc_mgr_max_fw_cmd_get(struct ps3_instance *instance,
unsigned int *max_cmd_count)
{
unsigned char ret = PS3_TRUE;
union HilReg0Ps3RegisterFPs3MaxFwCmd *reg_max_fw_cmd = NULL;
unsigned long long value = 0;
PS3_IOC_REG_READ_SAFE_WITH_RETRY(instance, reg_f.Excl_reg, ps3MaxFwCmd,
value);
if (value == U64_MAX) {
LOG_ERROR("hno:%u read reg ps3MaxFwCmd NOK!\n",
PS3_HOST(instance));
*max_cmd_count = 0;
ret = PS3_FALSE;
goto l_out;
}
reg_max_fw_cmd = (union HilReg0Ps3RegisterFPs3MaxFwCmd *)&value;
*max_cmd_count = (unsigned int)reg_max_fw_cmd->reg.ps3MaxFwCmd;
if (instance->is_adjust_register_count)
*max_cmd_count += 1;
if (reset_devices &&
*max_cmd_count > PS3_MAX_CMD_COUNT_DURING_RESET_DEVICES) {
*max_cmd_count = PS3_MAX_CMD_COUNT_DURING_RESET_DEVICES;
}
l_out:
return ret;
}
static inline unsigned int
ps3_ioc_mgr_max_msix_vectors_get(struct ps3_instance *instance)
{
unsigned long long reg_max_msix_vectors = PS3_MAX_REPLY_QUE_COUNT;
(void)instance;
return (unsigned int)(reg_max_msix_vectors &
PS3_FW_MAX_MSIX_VECTORS_MASK);
}
static inline unsigned char
ps3_ioc_mgr_max_chain_size_get(struct ps3_instance *instance,
unsigned int *max_chain_size)
{
unsigned char ret = PS3_TRUE;
union HilReg0Ps3RegisterFPs3MaxChainSize *max_chain_size_u = NULL;
unsigned long long value = 0;
PS3_IOC_REG_READ_SAFE_WITH_RETRY(instance, reg_f.Excl_reg,
ps3MaxChainSize, value);
if (value == U64_MAX) {
LOG_ERROR("hno:%u read reg ps3MaxChainSize NOK!\n",
PS3_HOST(instance));
*max_chain_size = 0;
ret = PS3_FALSE;
goto l_out;
}
max_chain_size_u = (union HilReg0Ps3RegisterFPs3MaxChainSize *)&value;
*max_chain_size = (unsigned int)max_chain_size_u->reg.ps3MaxChainSize;
l_out:
return ret;
}
static inline unsigned char
ps3_ioc_mgr_max_vd_info_size_get(struct ps3_instance *instance,
unsigned int *vd_info_size)
{
unsigned char ret = PS3_TRUE;
union HilReg0Ps3RegisterFPs3MaxVdInfoSize *vd_info_size_u = NULL;
unsigned long long value = 0;
PS3_IOC_REG_READ_WITH_CHECK(instance, reg_f.Excl_reg, ps3MaxVdInfoSize,
value);
if (value == U64_MAX) {
LOG_ERROR("hno:%u read reg ps3MaxVdInfoSize NOK!\n",
PS3_HOST(instance));
*vd_info_size = 0;
ret = PS3_FALSE;
goto l_out;
}
vd_info_size_u = (union HilReg0Ps3RegisterFPs3MaxVdInfoSize *)&value;
*vd_info_size = (unsigned int)vd_info_size_u->reg.ps3MaxVdInfoSize;
l_out:
return ret;
}
static inline unsigned char
ps3_ioc_mgr_max_nvme_page_size_get(struct ps3_instance *instance,
unsigned int *max_nvme_page_size)
{
unsigned char ret = PS3_TRUE;
union HilReg0Ps3RegisterFPs3MaxNvmePageSize *max_nvme_page_size_u =
NULL;
unsigned long long value = 0;
PS3_IOC_REG_READ_SAFE_WITH_RETRY(instance, reg_f.Excl_reg,
ps3MaxNvmePageSize, value);
if (value == U64_MAX) {
LOG_ERROR("hno:%u read reg ps3MaxNvmePageSize NOK!\n",
PS3_HOST(instance));
*max_nvme_page_size = 0;
ret = PS3_FALSE;
goto l_out;
}
max_nvme_page_size_u =
(union HilReg0Ps3RegisterFPs3MaxNvmePageSize *)&value;
*max_nvme_page_size =
(unsigned int)max_nvme_page_size_u->reg.ps3MaxNvmePageSize;
l_out:
return ret;
}
static inline unsigned char
ps3_ioc_mgr_is_dma64_support(struct ps3_instance *instance,
unsigned char *is_dma64_support)
{
unsigned char ret = PS3_TRUE;
union HilReg0Ps3RegisterFPs3FeatureSupport *ps3_feature_support = NULL;
unsigned long long value = 0;
PS3_IOC_REG_READ_SAFE_WITH_RETRY(instance, reg_f.Excl_reg,
ps3FeatureSupport, value);
if (value == U64_MAX) {
LOG_ERROR("hno:%u read reg ps3FeatureSupport NOK!\n",
PS3_HOST(instance));
*is_dma64_support = PS3_FALSE;
ret = PS3_FALSE;
goto l_out;
}
ps3_feature_support =
(union HilReg0Ps3RegisterFPs3FeatureSupport *)&value;
*is_dma64_support = (ps3_feature_support->reg.dmaBit64Support != 0);
l_out:
return ret;
}
static inline unsigned char
ps3_max_replyq_count_get(struct ps3_instance *instance,
unsigned int *max_replyq_count)
{
unsigned char ret = PS3_TRUE;
unsigned long long value = 0;
PS3_IOC_REG_READ_SAFE_WITH_RETRY(instance, reg_f.Excl_reg,
ps3MaxReplyque, value);
if (value == U64_MAX) {
LOG_ERROR("hno:%u read reg ps3MaxReplyque NOK!\n",
PS3_HOST(instance));
*max_replyq_count = 0;
ret = PS3_FALSE;
goto l_out;
}
*max_replyq_count = value & 0xffff;
l_out:
return ret;
}
static inline unsigned char
ps3_ioc_fw_version_get(struct ps3_instance *instance)
{
unsigned char ret = PS3_TRUE;
union HilReg0Ps3RegisterFPs3FirmwareVersion *pver = NULL;
unsigned long long fw_version_last = instance->ioc_fw_version;
unsigned long long ver = 0;
PS3_IOC_REG_READ_SAFE_WITH_RETRY(instance, reg_f.Excl_reg,
ps3FirmwareVersion, ver);
if (ver == U64_MAX) {
LOG_ERROR("hno:%u read reg ps3FirmwareVersion NOK!\n",
PS3_HOST(instance));
instance->ioc_fw_version = fw_version_last;
ret = PS3_FALSE;
goto l_out;
}
pver = (union HilReg0Ps3RegisterFPs3FirmwareVersion *)&ver;
instance->ioc_fw_version = (unsigned long long)pver->reg.ps3FmVer;
l_out:
return ret;
}
static inline unsigned char
ps3_ioc_sgl_mode_support(struct ps3_instance *instance,
unsigned char *is_sgl_mode_support)
{
unsigned char ret = PS3_TRUE;
union HilReg0Ps3RegisterFPs3FeatureSupport *ps3_feature_support = NULL;
unsigned long long value = 0;
PS3_IOC_REG_READ_SAFE_WITH_RETRY(instance, reg_f.Excl_reg,
ps3FeatureSupport, value);
if (value == U64_MAX) {
LOG_ERROR("hno:%u read reg ps3FeatureSupport NOK!\n",
PS3_HOST(instance));
*is_sgl_mode_support = PS3_FALSE;
ret = PS3_FALSE;
goto l_out;
}
ps3_feature_support =
(union HilReg0Ps3RegisterFPs3FeatureSupport *)&value;
*is_sgl_mode_support = (ps3_feature_support->reg.sglModeSupport == 1);
l_out:
return ret;
}
static inline unsigned char
ps3_ioc_dump_support_get(struct ps3_instance *instance)
{
unsigned char ret = PS3_TRUE;
unsigned char last_dump_support =
instance->dump_context.is_dump_support;
union HilReg0Ps3RegisterFPs3FeatureSupport *ps3_feature_support = NULL;
unsigned long long value = 0;
PS3_IOC_REG_READ_WITH_CHECK(instance, reg_f.Excl_reg, ps3FeatureSupport,
value);
if (value == U64_MAX) {
LOG_ERROR("hno:%u read reg ps3FeatureSupport NOK!\n",
PS3_HOST(instance));
instance->dump_context.is_dump_support = last_dump_support;
ret = PS3_FALSE;
goto l_out;
}
ps3_feature_support =
(union HilReg0Ps3RegisterFPs3FeatureSupport *)&value;
instance->dump_context.is_dump_support =
(ps3_feature_support->reg.dumpCrashSupport == 1);
l_out:
return ret;
}
static inline unsigned char
ps3_ioc_state_halt_support_get(struct ps3_instance *instance)
{
unsigned char ret = PS3_TRUE;
unsigned char last_halt_support = instance->is_ioc_halt_support;
union HilReg0Ps3RegisterFPs3FeatureSupport *ps3_feature_support = NULL;
unsigned long long value = 0;
PS3_IOC_REG_READ_WITH_CHECK(instance, reg_f.Excl_reg, ps3FeatureSupport,
value);
if (value == U64_MAX) {
LOG_ERROR("hno:%u read reg ps3FeatureSupport NOK!\n",
PS3_HOST(instance));
instance->is_ioc_halt_support = last_halt_support;
ret = PS3_FALSE;
goto l_out;
}
ps3_feature_support =
(union HilReg0Ps3RegisterFPs3FeatureSupport *)&value;
instance->is_ioc_halt_support =
(ps3_feature_support->reg.fwHaltSupport == 1);
l_out:
return ret;
}
static inline unsigned char
ps3_ioc_recovery_count_get(struct ps3_instance *instance,
unsigned int *recovery_count)
{
(void)instance;
*recovery_count = 0;
return PS3_TRUE;
}
static inline unsigned int ps3_ioc_state_get(struct ps3_instance *instance)
{
unsigned long long ioc_state = 0;
PS3_IOC_REG_READ_WITH_CHECK(instance, reg_f.Excl_reg, ps3SocFwState,
ioc_state);
return (unsigned int)(ioc_state & PS3_FW_STATE_MASK);
}
static inline unsigned char
ps3_ioc_state_get_with_check(struct ps3_instance *instance,
unsigned int *ioc_state)
{
unsigned char ret = PS3_TRUE;
unsigned long long value = 0;
PS3_IOC_REG_READ_WITH_CHECK(instance, reg_f.Excl_reg, ps3SocFwState,
value);
if (value == U64_MAX) {
LOG_ERROR("hno:%u read reg ps3SocFwState NOK!\n",
PS3_HOST(instance));
*ioc_state = 0;
ret = PS3_FALSE;
goto l_out;
}
*ioc_state = (unsigned int)value & PS3_FW_STATE_MASK;
l_out:
return ret;
}
static inline unsigned char
ps3_get_doorbell_done_with_check(struct ps3_instance *instance,
unsigned char *is_doorbell_done)
{
unsigned char ret = PS3_TRUE;
unsigned long long value = 0;
PS3_IOC_REG_READ_WITH_CHECK(instance, reg_f.Excl_reg, ps3RegCmdState,
value);
if (value == U64_MAX) {
LOG_ERROR("hno:%u read reg ps3RegCmdState NOK!\n",
PS3_HOST(instance));
*is_doorbell_done = PS3_FALSE;
ret = PS3_FALSE;
goto l_out;
}
*is_doorbell_done = value & PS3_DOORBELL_DONE;
if (*is_doorbell_done) {
value &= ~PS3_DOORBELL_DONE;
if (instance->peer_instance != NULL &&
instance->peer_instance->reg_set != NULL) {
PS3_IOC_REG_WRITE_WITH_CHECK(instance, reg_f.Excl_reg,
ps3RegCmdState, value);
PS3_IOC_REG_WRITE_WITH_CHECK(instance->peer_instance,
reg_f.Excl_reg,
ps3RegCmdState, value);
} else {
PS3_IOC_REG_WRITE_WITH_CHECK(instance, reg_f.Excl_reg,
ps3RegCmdState, value);
}
}
l_out:
return ret;
}
static inline unsigned char
ps3_get_max_r1x_cmds_with_check(struct ps3_instance *instance,
unsigned short *max_r1x_cmds)
{
unsigned char ret = PS3_TRUE;
union HilReg0Ps3RegisterFPs3MaxSecR1xCmds *ps3_max_sec_r1x_cmds = NULL;
unsigned long long value = 0;
PS3_IOC_REG_READ_SAFE_WITH_RETRY(instance, reg_f.Excl_reg,
ps3MaxSecR1xCmds, value);
if (value == U64_MAX) {
LOG_ERROR("hno:%u read reg ps3Debug6 NOK!\n",
PS3_HOST(instance));
*max_r1x_cmds = 0;
ret = PS3_FALSE;
goto l_out;
}
ps3_max_sec_r1x_cmds =
(union HilReg0Ps3RegisterFPs3MaxSecR1xCmds *)&value;
*max_r1x_cmds = ps3_max_sec_r1x_cmds->reg.ps3MaxSecR1xCmds;
l_out:
return ret;
}
static inline unsigned char
ps3_check_debug0_valid_with_check(struct ps3_instance *instance,
unsigned char *is_doorbell_valid,
unsigned int check_mask)
{
unsigned char ret = PS3_TRUE;
unsigned long long value = 0;
PS3_IOC_REG_READ_WITH_CHECK(instance, reg_f.Excl_reg, ps3CmdTrigger,
value);
if (value == U64_MAX) {
LOG_ERROR("hno:%u read reg ps3CmdTrigger NOK!\n",
PS3_HOST(instance));
*is_doorbell_valid = PS3_FALSE;
ret = PS3_FALSE;
goto l_out;
}
*is_doorbell_valid = (value & check_mask);
l_out:
return ret;
}
static inline unsigned char
ps3_ioc_heartbeat_get(struct ps3_instance *instance,
unsigned long long *heartbeat_value)
{
unsigned char ret = PS3_TRUE;
static unsigned char last_fault_state = PS3_TRUE;
*heartbeat_value = ps3_ioc_reg_read_with_check(
instance, &instance->reg_set->reg_f.Excl_reg.ps3SocFwState);
if (*heartbeat_value == U64_MAX) {
if (last_fault_state) {
LOG_ERROR("hno:%u read reg ps3SocFwState NOK!\n",
PS3_HOST(instance));
last_fault_state = PS3_FALSE;
}
*heartbeat_value = 0;
ret = PS3_FALSE;
goto l_out;
} else {
last_fault_state = PS3_TRUE;
LOG_DEBUG(
"hno:%u read reg ps3SocFwState success value[%llu]!\n",
PS3_HOST(instance), *heartbeat_value);
}
l_out:
return ret;
}
static inline unsigned char
ps3_ioc_recovery_support_get(struct ps3_instance *instance)
{
unsigned char ret = PS3_TRUE;
unsigned char last_shallow_soft_recovery_support =
instance->is_shallow_soft_recovery_support;
unsigned char last_deep_soft_recovery_support =
instance->is_deep_soft_recovery_support;
unsigned char last_hard_recovery_support =
instance->is_hard_recovery_support;
union HilReg0Ps3RegisterFPs3FeatureSupport *ps3_feature_support = NULL;
unsigned long long value = 0;
PS3_IOC_REG_READ_WITH_CHECK(instance, reg_f.Excl_reg, ps3FeatureSupport,
value);
if (value == U64_MAX) {
LOG_ERROR("hno:%u read reg ps3FeatureSupport NOK!\n",
PS3_HOST(instance));
instance->is_shallow_soft_recovery_support =
last_shallow_soft_recovery_support;
instance->is_deep_soft_recovery_support =
last_deep_soft_recovery_support;
instance->is_hard_recovery_support = last_hard_recovery_support;
ret = PS3_FALSE;
goto l_out;
}
ps3_feature_support =
(union HilReg0Ps3RegisterFPs3FeatureSupport *)&value;
instance->is_shallow_soft_recovery_support =
(ps3_feature_support->reg.shallowSoftRecoverySupport == 1);
instance->is_deep_soft_recovery_support =
(ps3_feature_support->reg.deepSoftRecoverySupport == 1);
instance->is_hard_recovery_support =
(ps3_feature_support->reg.hardRecoverySupport == 1);
l_out:
return ret;
}
static inline unsigned char
ps3_ioc_multi_func_support(struct ps3_instance *instance)
{
unsigned char ret = PS3_TRUE;
union HilReg0Ps3RegisterFPs3FeatureSupport *ps3_feature_support = NULL;
unsigned long long value = 0;
PS3_IOC_REG_READ_SAFE_WITH_RETRY(instance, reg_f.Excl_reg,
ps3FeatureSupport, value);
if (value == U64_MAX) {
LOG_ERROR("hno:%u read reg ps3FeatureSupport failed!\n",
PS3_HOST(instance));
ret = PS3_FALSE;
goto l_out;
}
ps3_feature_support =
(union HilReg0Ps3RegisterFPs3FeatureSupport *)&value;
ret = (ps3_feature_support->reg.multiDevfnSupport == 1);
l_out:
return ret;
}
static inline unsigned char
ps3_ioc_security_state_check(struct ps3_instance *instance)
{
unsigned long long value = 0;
unsigned char ret = PS3_FALSE;
PS3_IOC_REG_READ_SAFE_WITH_RETRY(instance, reg_f.Excl_reg, ps3Debug7,
value);
if (value == U64_MAX || (value & 0x1)) {
ret = PS3_TRUE;
LOG_ERROR(
"hno:%u read register NOK or ioc is security [%llu]\n",
PS3_HOST(instance), value);
}
#ifdef PS3_HARDWARE_SIM
ret = PS3_FALSE;
#endif
return ret;
}
static inline unsigned char
ps3_ioc_atu_support_get(struct ps3_instance *instance, unsigned char *bit_pos)
{
unsigned char ret = PS3_TRUE;
union HilRegPs3RegisterFPs3AtuSupport *ps3_atu_support = NULL;
unsigned long long value = PS3_BIT_POS_DEFAULT;
PS3_IOC_REG_READ_WITH_CHECK(instance, reg_f.Excl_reg, ps3Debug8, value);
if (value == U64_MAX) {
LOG_ERROR("hno:%u read reg ps3AtuSupport NOK!\n",
PS3_HOST(instance));
*bit_pos = PS3_BIT_POS_DEFAULT;
ret = PS3_FALSE;
goto l_out;
}
ps3_atu_support = (union HilRegPs3RegisterFPs3AtuSupport *)&value;
*bit_pos = ps3_atu_support->reg.bitPos;
l_out:
return ret;
}
static inline unsigned char
ps3_ioc_atu_support_safe_get(struct ps3_instance *instance,
unsigned char *bit_pos)
{
unsigned char ret = PS3_FALSE;
unsigned int fw_cur_state = PS3_FW_STATE_UNDEFINED;
unsigned int count = 0;
unsigned int retry_cnt = 0;
unsigned char tmp_bit_pos = 0;
unsigned char is_first = PS3_TRUE;
for (; retry_cnt < PS3_ATU_SUPPORT_READ_RETRY_NUM; retry_cnt++) {
if (!ps3_ioc_atu_support_get(instance, &tmp_bit_pos))
goto l_out;
fw_cur_state = instance->ioc_adpter->ioc_state_get(instance);
if (!ps3_ioc_state_valid_check(fw_cur_state)) {
for (; count < PS3_REG_READ_RETRY_NUM; count++) {
fw_cur_state =
instance->ioc_adpter->ioc_state_get(
instance);
if (ps3_ioc_state_valid_check(fw_cur_state)) {
if (!ps3_ioc_atu_support_get(
instance, &tmp_bit_pos)) {
goto l_out;
}
*bit_pos = tmp_bit_pos;
ret = PS3_TRUE;
goto l_out;
}
ps3_msleep(PS3_LOOP_TIME_INTERVAL_20MS);
}
goto l_out;
}
if (is_first) {
*bit_pos = tmp_bit_pos;
is_first = PS3_FALSE;
continue;
}
if (*bit_pos != tmp_bit_pos)
goto l_out;
ps3_msleep(PS3_LOOP_TIME_INTERVAL_50MS);
}
ret = PS3_TRUE;
l_out:
return ret;
}
static inline unsigned char
ps3_ioc_atu_support_retry_read(struct ps3_instance *instance,
unsigned char *bit_pos)
{
unsigned int retry_cnt = PS3_ATU_SUPPORT_READ_RETRY_NUM;
unsigned char ret = PS3_FALSE;
while (retry_cnt--) {
if (ps3_ioc_atu_support_safe_get(instance, bit_pos)) {
ret = PS3_TRUE;
break;
}
ps3_msleep(PS3_LOOP_TIME_INTERVAL_20MS);
}
return ret;
}
static inline void ps3_ioc_can_hardreset_set(struct ps3_instance *instance,
unsigned char enable)
{
unsigned long long can_hardreset = 0;
union HilRegPs3RegisterFPs3CanHardReset *ps3_can_hardreset = NULL;
ps3_can_hardreset =
(union HilRegPs3RegisterFPs3CanHardReset *)&can_hardreset;
ps3_can_hardreset->reg.canHardReset = enable;
PS3_IOC_REG_WRITE(instance, reg_f.Excl_reg, ps3Debug9,
ps3_can_hardreset->val);
}
unsigned char ps3_feature_support_reg_get(struct ps3_instance *instance);
void ps3_ioc_scsi_cmd_send(struct ps3_instance *instance,
struct PS3CmdWord *cmd_word);
struct pglist_data *ps3_first_online_pgdat(void);
struct pglist_data *ps3_next_online_pgdat(struct pglist_data *pgdat);
#define for_each_ps3_online_pgdat(pgdat) \
for (pgdat = ps3_first_online_pgdat(); pgdat; \
pgdat = ps3_next_online_pgdat(pgdat))
#endif

View File

@ -0,0 +1,855 @@
// SPDX-License-Identifier: GPL-2.0
#ifndef _WINDOWS
#include <linux/kernel.h>
#include <linux/pci.h>
#include <linux/delay.h>
#endif
#include "ps3_ioc_state.h"
#include "ps3_driver_log.h"
#include "ps3_ioc_manager.h"
#include "ps3_module_para.h"
#define PS3_SOFTRESET_MASK (0xFF)
#define PS3_HARDRESET_MASK (0xFF)
enum ps3_reset_type {
PS3_FW_HARD_RESET = 0,
PS3_FW_SHALLOW_SOFT_RESET = 1,
PS3_FW_DEEP_SOFT_RESET = 2,
};
static inline const char *namePS3ResetType(int s)
{
static const char * const myNames[] = {
[PS3_FW_HARD_RESET] = "PS3_FW_HARD_RESET",
[PS3_FW_SHALLOW_SOFT_RESET] = "PS3_FW_SHALLOW_SOFT_RESET",
[PS3_FW_DEEP_SOFT_RESET] = "PS3_FW_DEEP_SOFT_RESET"
};
if (s > PS3_FW_DEEP_SOFT_RESET)
return "PS3_RESET_TYPE_INVALID";
return myNames[s];
}
struct ps3_reset_key_map {
unsigned int reset_key_offset;
unsigned int reset_state_offset;
unsigned int reset_offset;
unsigned int reset_type;
unsigned int reset_status_offset;
unsigned int reset_status_mask;
};
struct ps3_state_desc_map {
unsigned int state;
const char *state_desc;
};
static struct ps3_reset_key_map g_reset_key_table[] = {
[PS3_FW_HARD_RESET] = { offsetof(struct HilReg0Ps3RegisterF,
ps3HardresetKey),
offsetof(struct HilReg0Ps3RegisterF,
ps3HardresetState),
offsetof(struct HilReg0Ps3RegisterF,
ps3Hardreset),
PS3_FW_HARD_RESET_ACT,
offsetof(struct HilReg0Ps3RegisterF,
ps3Hardreset),
PS3_HARDRESET_MASK },
[PS3_FW_SHALLOW_SOFT_RESET] = { offsetof(struct HilReg0Ps3RegisterF,
ps3SoftresetKey),
offsetof(struct HilReg0Ps3RegisterF,
ps3SoftresetState),
offsetof(struct HilReg0Ps3RegisterF,
ps3Softreset),
PS3_FW_STATE_ACT_SHALLOW_SOFT_RESET,
offsetof(struct HilReg0Ps3RegisterF,
ps3Softreset),
PS3_SOFTRESET_MASK },
[PS3_FW_DEEP_SOFT_RESET] = { offsetof(struct HilReg0Ps3RegisterF,
ps3SoftresetKey),
offsetof(struct HilReg0Ps3RegisterF,
ps3SoftresetState),
offsetof(struct HilReg0Ps3RegisterF,
ps3Softreset),
PS3_FW_STATE_ACT_DEEP_SOFT_RESET,
offsetof(struct HilReg0Ps3RegisterF,
ps3Softreset),
PS3_SOFTRESET_MASK },
};
static struct ps3_state_desc_map g_state_desc[] = {
{ PS3_FW_STATE_UNDEFINED, "PS3_FW_STATE_UNDEFINED" },
{ PS3_FW_STATE_START, "PS3_FW_STATE_START" },
{ PS3_FW_STATE_READY, "PS3_FW_STATE_READY" },
{ PS3_FW_STATE_WAIT, "PS3_FW_STATE_WAIT" },
{ PS3_FW_STATE_RUNNING, "PS3_FW_STATE_RUNNING" },
{ PS3_FW_STATE_FLUSHING, "PS3_FW_STATE_FLUSHING" },
{ PS3_FW_STATE_RESET, "PS3_FW_STATE_RESET" },
{ PS3_FW_STATE_FAULT, "PS3_FW_STATE_FAULT" },
{ PS3_FW_STATE_CRITICAL, "PS3_FW_STATE_CRITICAL" },
{ PS3_FW_STATE_HALT, "PS3_FW_STATE_HALT" }
};
static void ps3_reset_key_write(struct ps3_instance *instance,
unsigned int offset)
{
static unsigned int reset_key_array[] = {
PS3_FW_DIAG_1ST_KEY, PS3_FW_DIAG_2ND_KEY, PS3_FW_DIAG_3RD_KEY,
PS3_FW_DIAG_4TH_KEY, PS3_FW_DIAG_5TH_KEY, PS3_FW_DIAG_6TH_KEY,
PS3_FW_DIAG_7TH_KEY, PS3_FW_DIAG_8TH_KEY, PS3_FW_DIAG_9TH_KEY
};
unsigned int idx = 0;
for (idx = 0; idx < ARRAY_SIZE(reset_key_array); idx++) {
PS3_IOC_REG_WRITE_OFFSET(
instance, offset,
(unsigned long long)reset_key_array[idx]);
}
}
static void ps3_hardreset_key_write(struct ps3_instance *instance,
unsigned char *reset_key_vir_addr,
unsigned long long *timeval)
{
static unsigned int reset_key_array[] = {
PS3_FW_DIAG_1ST_KEY, PS3_FW_DIAG_2ND_KEY, PS3_FW_DIAG_3RD_KEY,
PS3_FW_DIAG_4TH_KEY, PS3_FW_DIAG_5TH_KEY, PS3_FW_DIAG_6TH_KEY,
PS3_FW_DIAG_7TH_KEY, PS3_FW_DIAG_8TH_KEY, PS3_FW_DIAG_9TH_KEY
};
unsigned int idx = 0;
timeval[PS3_START_WRITE_KEY_REG] = ps3_1970_now_ms_get();
for (idx = 0; idx < ARRAY_SIZE(reset_key_array); idx++) {
ps3_ioc_hardreset_reg_write(
instance, (unsigned long long)reset_key_array[idx],
reset_key_vir_addr, 0);
}
timeval[PS3_END_WRITE_KEY_REG] = ps3_1970_now_ms_get();
}
static int ps3_reset_key_state_check(struct ps3_instance *instance,
unsigned int offset)
{
unsigned int reset_key_state = 0;
unsigned int read_count = 0;
const unsigned int retry_max = 50;
int ret = PS3_SUCCESS;
unsigned long long value = 0;
do {
if (read_count >= retry_max) {
LOG_ERROR("hno:%u PS3 reset key state is still disabled after 5 sec\n",
PS3_HOST(instance));
ret = -PS3_FAILED;
break;
}
if (read_count != 0)
ps3_msleep(PS3_LOOP_TIME_INTERVAL_100MS);
PS3_IOC_REG_READ_OFFSET(instance, offset, value);
reset_key_state = (unsigned int)value;
read_count++;
} while (!(reset_key_state & PS3_FW_DIAG_ENABLE) ||
(reset_key_state == U32_MAX));
if (ret == PS3_SUCCESS) {
LOG_INFO(
"hno:%u PS3 reset key state is enabled after %d msecs\n",
PS3_HOST(instance),
(read_count - 1) * PS3_LOOP_TIME_INTERVAL_100MS);
}
return ret;
}
static int
ps3_hardreset_key_state_check(struct ps3_instance *instance,
unsigned char *reset_key_state_vir_addr,
unsigned long long *timeval)
{
unsigned int reset_key_state = 0;
unsigned int read_count = 0;
const unsigned int retry_max = 900;
int ret = PS3_SUCCESS;
timeval[PS3_START_WAIT_KEY_READY_REG] = ps3_1970_now_ms_get();
do {
if (read_count >= retry_max) {
ret = -PS3_FAILED;
break;
}
if (read_count != 0)
ps3_mdelay(PS3_LOOP_TIME_INTERVAL_1MS);
reset_key_state = (unsigned int)ps3_ioc_hardreset_reg_read(
instance, reset_key_state_vir_addr);
read_count++;
} while (!(reset_key_state & PS3_FW_DIAG_ENABLE) ||
((U32_MAX & reset_key_state) == U32_MAX));
timeval[PS3_END_WAIT_KEY_READY_REG] = ps3_1970_now_ms_get();
return ret;
}
static int ps3_after_reset_request_check(struct ps3_instance *instance,
enum ps3_reset_type reset_type)
{
unsigned int fw_state = instance->ioc_adpter->ioc_state_get(instance);
unsigned int read_count = 0;
#ifdef PS3_HARDWARE_HAPS_V200
const unsigned int retry_max = 3600;
#else
const unsigned int retry_max = 1800;
#endif
int ret = -PS3_FAILED;
while (read_count < retry_max) {
if ((fw_state == PS3_FW_STATE_START) ||
(fw_state == PS3_FW_STATE_READY)) {
ret = PS3_SUCCESS;
break;
}
if ((reset_type == PS3_FW_SHALLOW_SOFT_RESET) ||
(reset_type == PS3_FW_DEEP_SOFT_RESET)) {
if (fw_state == PS3_FW_STATE_RUNNING) {
ret = PS3_SUCCESS;
break;
}
}
if (ps3_pci_err_recovery_get(instance)) {
LOG_WARN("hno:%u pci recovery resetting\n",
PS3_HOST(instance));
ret = -PS3_IN_PCIE_ERR;
break;
}
#ifdef PS3_HARDWARE_HAPS_V200
ps3_msleep(PS3_LOOP_TIME_INTERVAL_3000MS);
#else
ps3_msleep(PS3_LOOP_TIME_INTERVAL_100MS);
#endif
fw_state = instance->ioc_adpter->ioc_state_get(instance);
read_count++;
}
if (ret != PS3_SUCCESS) {
LOG_ERROR(
"hno:%u PS3 IOC state is not valid 180 secs after IOC reset, fw state is %s\n",
PS3_HOST(instance), ps3_ioc_state_print(fw_state));
}
LOG_INFO("hno:%u fw state is %s\n", PS3_HOST(instance),
ps3_ioc_state_print(fw_state));
return ret;
}
static int ps3_reset_request_completion_check(struct ps3_instance *instance,
unsigned int offset,
unsigned int completion_mask)
{
unsigned int read_count = 0;
const unsigned int retry_max = 1000;
int ret = PS3_SUCCESS;
unsigned long long value = 0;
unsigned int completion = 0;
PS3_IOC_REG_READ_OFFSET(instance, offset, value);
completion = (unsigned int)value;
while (completion & completion_mask || completion == U32_MAX) {
if (read_count > retry_max) {
LOG_ERROR(
"hno:%u PS3 reset flag is not clear 100 secs after reset request\n",
PS3_HOST(instance));
ret = -PS3_FAILED;
break;
}
if (ps3_pci_err_recovery_get(instance)) {
LOG_WARN("hno:%u pci recovery resetting\n",
PS3_HOST(instance));
ret = -PS3_FAILED;
break;
}
ps3_msleep(PS3_LOOP_TIME_INTERVAL_100MS);
PS3_IOC_REG_READ_OFFSET(instance, offset, value);
completion = (unsigned int)value;
read_count++;
}
if (ret == PS3_SUCCESS) {
LOG_INFO(
"hno:%u PS3 reset complete %d msecs after reset complete\n",
PS3_HOST(instance),
read_count * PS3_LOOP_TIME_INTERVAL_100MS);
}
return ret;
}
const char *ps3_ioc_state_print(unsigned int state)
{
unsigned int idx = 0;
unsigned int fw_state = state & PS3_FW_STATE_MASK;
const char *ps3_state_name = "invalid state";
for (idx = 0; idx < ARRAY_SIZE(g_state_desc); idx++) {
if (g_state_desc[idx].state == fw_state) {
ps3_state_name = g_state_desc[idx].state_desc;
break;
}
}
return ps3_state_name;
}
static inline void
ps3_ioc_state_trigger_transition(struct ps3_instance *instance,
unsigned int action)
{
PS3_IOC_REG_WRITE(instance, reg_f.Excl_reg, ps3Doorbell,
(unsigned long long)action);
}
static inline void ps3_ioc_debug0_trigger(struct ps3_instance *instance,
unsigned int mask_value)
{
PS3_IOC_REG_WRITE(instance, reg_f.Excl_reg, ps3CmdTrigger,
(unsigned long long)mask_value);
}
int ps3_ioc_state_fault_wait(struct ps3_instance *instance)
{
unsigned int fw_cur_state = PS3_FW_STATE_UNDEFINED;
int ret = PS3_SUCCESS;
unsigned int count = 0;
fw_cur_state = instance->ioc_adpter->ioc_state_get(instance);
while (count < PS3_FW_STATE_TO_FAULT_TMO_LOOP_COUNT) {
if (fw_cur_state == PS3_FW_STATE_FAULT ||
fw_cur_state == PS3_FW_STATE_CRITICAL) {
LOG_INFO("hno:%u within 180s fw transfer to %s\n",
PS3_HOST(instance),
ps3_ioc_state_print(fw_cur_state));
break;
}
ps3_msleep(PS3_LOOP_TIME_INTERVAL_20MS);
fw_cur_state = instance->ioc_adpter->ioc_state_get(instance);
count++;
}
if (fw_cur_state != PS3_FW_STATE_FAULT) {
LOG_ERROR("hno:%u fw state[%s] is not fault\n",
PS3_HOST(instance),
ps3_ioc_state_print(fw_cur_state));
ret = -PS3_FAILED;
} else {
LOG_INFO("hno:%u fw state transition to %s\n",
PS3_HOST(instance), ps3_ioc_state_print(fw_cur_state));
}
return ret;
}
int ps3_ioc_state_ready_wait(struct ps3_instance *instance)
{
unsigned int fw_cur_state = PS3_FW_STATE_UNDEFINED;
int ret = PS3_SUCCESS;
unsigned int count = 0;
unsigned char is_unload_valid = PS3_FALSE;
ps3_check_debug0_valid_with_check(instance, &is_unload_valid,
PS3_CMD_TRIGGER_UNLOAD);
fw_cur_state = instance->ioc_adpter->ioc_state_get(instance);
while (count < instance->wait_ready_timeout) {
if (ps3_pci_err_recovery_get(instance)) {
LOG_WARN("hno:%u pci recovery resetting\n",
PS3_HOST(instance));
ret = -PS3_IN_PCIE_ERR;
goto l_out;
}
if (fw_cur_state == PS3_FW_STATE_READY && !is_unload_valid) {
LOG_INFO("hno:%u within 180s fw transfer to %s\n",
PS3_HOST(instance),
ps3_ioc_state_print(fw_cur_state));
break;
}
#ifdef PS3_HARDWARE_HAPS_V200
ps3_msleep(PS3_LOOP_TIME_INTERVAL_3000MS);
#else
ps3_msleep(PS3_LOOP_TIME_INTERVAL_20MS);
#endif
ps3_check_debug0_valid_with_check(instance, &is_unload_valid,
PS3_CMD_TRIGGER_UNLOAD);
fw_cur_state = instance->ioc_adpter->ioc_state_get(instance);
count++;
}
if (fw_cur_state != PS3_FW_STATE_READY || is_unload_valid) {
LOG_ERROR(
"hno:%u fw state[%s] is not ready, or unload[%d] not done\n",
PS3_HOST(instance), ps3_ioc_state_print(fw_cur_state),
is_unload_valid);
ret = -PS3_FAILED;
} else {
LOG_INFO("hno:%u fw state transition to %s\n",
PS3_HOST(instance), ps3_ioc_state_print(fw_cur_state));
}
l_out:
return ret;
}
int ps3_ioc_state_transfer_to_ready(struct ps3_instance *instance)
{
unsigned int fw_cur_state = PS3_FW_STATE_UNDEFINED;
int ret = PS3_SUCCESS;
if (!ps3_ioc_state_get_with_check(instance, &fw_cur_state)) {
ret = -PS3_FAILED;
goto l_out;
}
LOG_INFO("hno:%u fw state is %s(0x%x)\n", PS3_HOST(instance),
ps3_ioc_state_print(fw_cur_state), fw_cur_state);
switch (fw_cur_state) {
case PS3_FW_STATE_UNDEFINED:
case PS3_FW_STATE_RESET:
case PS3_FW_STATE_START:
case PS3_FW_STATE_FLUSHING:
ret = ps3_ioc_state_ready_wait(instance);
if (ret != PS3_SUCCESS) {
if (ret != -PS3_IN_PCIE_ERR)
ret = -PS3_NO_RECOVERED;
LOG_ERROR("hno:%u fw state to ready NOK\n",
PS3_HOST(instance));
}
break;
case PS3_FW_STATE_READY:
break;
case PS3_FW_STATE_WAIT:
case PS3_FW_STATE_RUNNING:
LOG_WARN("hno:%u fw state is wait/running\n",
PS3_HOST(instance));
ret = -PS3_FAILED;
break;
case PS3_FW_STATE_FAULT:
case PS3_FW_STATE_CRITICAL:
case PS3_FW_STATE_HALT:
LOG_ERROR("hno:%u fw state is fault/halt, to ready NOK\n",
PS3_HOST(instance));
ret = -PS3_FAILED;
break;
default:
ret = ps3_ioc_state_ready_wait(instance);
break;
}
l_out:
return ret;
}
int ps3_ioc_state_transfer_wait_to_running(struct ps3_instance *instance)
{
unsigned int fw_cur_state = PS3_FW_STATE_UNDEFINED;
int ret = PS3_SUCCESS;
unsigned int count = 0;
fw_cur_state = instance->ioc_adpter->ioc_state_get(instance);
LOG_INFO("hno:%u fw state is %s(0x%x)\n", PS3_HOST(instance),
ps3_ioc_state_print(fw_cur_state), fw_cur_state);
while (count < PS3_FW_STATE_TO_RUNNING_TMO_LOOP_COUNT) {
if ((fw_cur_state == PS3_FW_STATE_RUNNING) ||
(fw_cur_state == PS3_FW_STATE_FAULT) ||
(fw_cur_state == PS3_FW_STATE_HALT) ||
(fw_cur_state == PS3_FW_STATE_CRITICAL)) {
break;
}
if (ps3_pci_err_recovery_get(instance)) {
LOG_WARN("hno:%u pci recovery resetting\n",
PS3_HOST(instance));
ret = -PS3_IN_PCIE_ERR;
goto l_out;
}
ps3_mutex_lock(&instance->state_machine.lock);
if (PS3_IS_INTERRUPT_SOFT_RECOVERY(instance)) {
LOG_WARN("hno:%u soft reset proc is interrupt!\n",
PS3_HOST(instance));
ret = -PS3_FAILED;
ps3_mutex_unlock(&instance->state_machine.lock);
break;
}
ps3_mutex_unlock(&instance->state_machine.lock);
ps3_msleep(PS3_LOOP_TIME_INTERVAL_20MS);
fw_cur_state = instance->ioc_adpter->ioc_state_get(instance);
count++;
}
if (fw_cur_state != PS3_FW_STATE_RUNNING) {
LOG_ERROR("hno:%u fw state transition NOK, state is %s\n",
PS3_HOST(instance),
ps3_ioc_state_print(fw_cur_state));
if (ps3_pci_err_recovery_get(instance)) {
LOG_WARN("hno:%u pci recovery resetting\n",
PS3_HOST(instance));
ret = -PS3_IN_PCIE_ERR;
} else {
ret = -PS3_FAILED;
}
}
LOG_INFO("hno:%u fw state transit to %s\n", PS3_HOST(instance),
ps3_ioc_state_print(fw_cur_state));
l_out:
return ret;
}
static int ps3_ioc_state_reset_request(struct ps3_instance *instance,
enum ps3_reset_type reset_type)
{
int ret = -PS3_FAILED;
unsigned int ioc_reset_type = 0;
unsigned int reset_status_mask = 0;
unsigned int cur_state = 0;
ioc_reset_type = g_reset_key_table[reset_type].reset_type;
reset_status_mask = g_reset_key_table[reset_type].reset_status_mask;
cur_state = ps3_atomic_read(&instance->state_machine.state);
LOG_INFO(
"hno:%u %s, key_offset: 0x%x, state_offset: 0x%x\n"
"\treset_offset: 0x%x, status_offset: 0x%x, IOC reset_type: 0x%8x\n"
"\tstatus mask: 0x%8x cur_state[%d]\n",
PS3_HOST(instance), namePS3ResetType(reset_type),
g_reset_key_table[reset_type].reset_key_offset,
g_reset_key_table[reset_type].reset_state_offset,
g_reset_key_table[reset_type].reset_offset,
g_reset_key_table[reset_type].reset_status_offset,
g_reset_key_table[reset_type].reset_type,
g_reset_key_table[reset_type].reset_status_mask, cur_state);
preempt_disable();
ps3_reset_key_write(instance,
g_reset_key_table[reset_type].reset_key_offset);
preempt_enable();
ps3_reset_key_state_check(
instance, g_reset_key_table[reset_type].reset_state_offset);
PS3_IOC_REG_WRITE_OFFSET(instance,
g_reset_key_table[reset_type].reset_offset,
(unsigned long long)ioc_reset_type);
if (ps3_hard_reset_waiting_query())
ps3_msleep(ps3_hard_reset_waiting_query());
if (ps3_reset_request_completion_check(
instance, g_reset_key_table[reset_type].reset_status_offset,
reset_status_mask) != PS3_SUCCESS) {
goto l_out;
}
if (ps3_after_reset_request_check(instance, reset_type) !=
PS3_SUCCESS) {
goto l_out;
}
ret = PS3_SUCCESS;
l_out:
LOG_INFO("hno:%u PS3 %s complete, ret:%d\n", PS3_HOST(instance),
namePS3ResetType(reset_type), ret);
return ret;
}
static int ps3_ioc_state_hardreset_request(struct ps3_instance *instance,
enum ps3_reset_type reset_type)
{
int ret = -PS3_FAILED;
unsigned char *reset_key_addr = NULL;
unsigned char *reset_state_addr = NULL;
unsigned char *reset_addr = NULL;
unsigned int ioc_reset_type = 0;
unsigned int cur_state = 0;
unsigned char *reg_start = (unsigned char *)instance->reg_set;
unsigned int read_count = 0;
const unsigned int retry_max = 180;
unsigned long flags = 0;
unsigned long long timeval[PS3_RESET_MAX_COUNT] = { 0 };
reset_key_addr =
reg_start + g_reset_key_table[reset_type].reset_key_offset;
reset_state_addr =
reg_start + g_reset_key_table[reset_type].reset_state_offset;
reset_addr = reg_start + g_reset_key_table[reset_type].reset_offset;
ioc_reset_type = g_reset_key_table[reset_type].reset_type;
cur_state = ps3_atomic_read(&instance->state_machine.state);
LOG_INFO(
"hno:%u %s, key_offset: 0x%x, state_offset: 0x%x\n"
"\treset_offset: 0x%x, status_offset: 0x%x, IOC reset_type: 0x%8x\n"
"\tstatus mask: 0x%8x cur_state[%d]\n",
PS3_HOST(instance), namePS3ResetType(reset_type),
g_reset_key_table[reset_type].reset_key_offset,
g_reset_key_table[reset_type].reset_state_offset,
g_reset_key_table[reset_type].reset_offset,
g_reset_key_table[reset_type].reset_status_offset,
g_reset_key_table[reset_type].reset_type,
g_reset_key_table[reset_type].reset_status_mask, cur_state);
instance->is_hard_reset = PS3_TRUE;
mb(); /* in order to force CPU ordering */
while (ps3_atomic_read(&instance->reg_op_count) != 0) {
ps3_msleep(PS3_LOOP_TIME_INTERVAL_100MS);
if (read_count++ > retry_max) {
LOG_INFO("hno:%u %s, wait reg op over:%d ms,failed\n",
PS3_HOST(instance),
namePS3ResetType(reset_type),
read_count * PS3_LOOP_TIME_INTERVAL_100MS);
ret = -PS3_FAILED;
goto l_out;
}
}
ps3_wait_scsi_cmd_done(instance, PS3_TRUE);
ps3_wait_mgr_cmd_done(instance, PS3_TRUE);
if (instance->peer_instance != NULL) {
ps3_wait_scsi_cmd_done(instance->peer_instance, PS3_TRUE);
ps3_wait_mgr_cmd_done(instance->peer_instance, PS3_TRUE);
}
if (ps3_pci_err_recovery_get(instance)) {
LOG_INFO("hno:%u pcie recovery proceess\n", PS3_HOST(instance));
ret = -PS3_IN_PCIE_ERR;
goto l_out;
}
spin_lock_irqsave(&instance->recovery_context->ps3_hardreset_lock,
flags);
ps3_hardreset_key_write(instance, reset_key_addr, timeval);
ret = ps3_hardreset_key_state_check(instance, reset_state_addr,
timeval);
if (ret != PS3_SUCCESS) {
spin_unlock_irqrestore(
&instance->recovery_context->ps3_hardreset_lock, flags);
LOG_INFO("hno:%u %s, key check failed, ret:%d\n",
PS3_HOST(instance), namePS3ResetType(reset_type), ret);
goto l_out;
}
if (ps3_pci_err_recovery_get(instance)) {
spin_unlock_irqrestore(
&instance->recovery_context->ps3_hardreset_lock, flags);
LOG_WARN("hno:%u pcie recovery proceess\n", PS3_HOST(instance));
ret = -PS3_IN_PCIE_ERR;
goto l_out;
}
timeval[PS3_START_WRITE_HARDRESET_REG] = ps3_1970_now_ms_get();
ps3_ioc_hardreset_reg_write(instance,
(unsigned long long)ioc_reset_type,
reset_addr, PS3_TRUE);
timeval[PS3_END_WRITE_HARDRESET_REG] = ps3_1970_now_ms_get();
spin_unlock_irqrestore(&instance->recovery_context->ps3_hardreset_lock,
flags);
LOG_INFO("hno:%u %s, key_offset: key state success\n"
"\tthen write hardreset ioc_reset_type:%u, reset_addr:%p\n",
PS3_HOST(instance), namePS3ResetType(reset_type),
ioc_reset_type, reset_addr);
LOG_INFO("hno:%u time:%lld-%lld-%lld-%lld-%lld-%lld\n",
PS3_HOST(instance), timeval[PS3_START_WRITE_KEY_REG],
timeval[PS3_END_WRITE_KEY_REG],
timeval[PS3_START_WAIT_KEY_READY_REG],
timeval[PS3_END_WAIT_KEY_READY_REG],
timeval[PS3_START_WRITE_HARDRESET_REG],
timeval[PS3_END_WRITE_HARDRESET_REG]);
instance->recovery_context->hardreset_count++;
if (ps3_hard_reset_waiting_query())
ps3_msleep(ps3_hard_reset_waiting_query());
LOG_INFO("hno:%u %s, after sleep:%d ms\n", PS3_HOST(instance),
namePS3ResetType(reset_type), ps3_hard_reset_waiting_query());
instance->is_hard_reset = PS3_FALSE;
ret = ps3_after_reset_request_check(instance, reset_type);
if (ret != PS3_SUCCESS)
goto l_out;
ret = PS3_SUCCESS;
l_out:
instance->is_hard_reset = PS3_FALSE;
LOG_INFO("hno:%u PS3 %s complete, ret:%d\n", PS3_HOST(instance),
namePS3ResetType(reset_type), ret);
return ret;
}
int ps3_ioc_state_hard_reset(struct ps3_instance *instance)
{
if (ps3_use_hard_reset_reg_query()) {
return ps3_ioc_state_hardreset_request(instance,
PS3_FW_HARD_RESET);
} else {
return ps3_ioc_state_reset_request(instance,
PS3_FW_SHALLOW_SOFT_RESET);
}
}
int ps3_ioc_state_shallow_soft_reset(struct ps3_instance *instance)
{
return ps3_ioc_state_reset_request(instance, PS3_FW_SHALLOW_SOFT_RESET);
}
int ps3_ioc_state_deep_soft_reset(struct ps3_instance *instance)
{
return ps3_ioc_state_reset_request(instance, PS3_FW_DEEP_SOFT_RESET);
}
static int ps3_trigger_ioc_state_change_by_doorbell(
struct ps3_instance *instance, unsigned int expect_fw_state,
unsigned int doorbell_trigger, u32 time_out)
{
unsigned int fw_cur_state = PS3_FW_STATE_UNDEFINED;
unsigned char is_doorbell_done = PS3_TRUE;
int ret = PS3_SUCCESS;
unsigned int count = 0;
LOG2_WARN("hno:%u expect fw state:%s, doorbell_trigger is %d\n",
PS3_HOST(instance), ps3_ioc_state_print(expect_fw_state),
doorbell_trigger);
fw_cur_state = instance->ioc_adpter->ioc_state_get(instance);
if (fw_cur_state == expect_fw_state)
goto l_out;
if (ps3_pci_err_recovery_get(instance)) {
LOG_WARN("hno:%u pci recovery resetting\n", PS3_HOST(instance));
ret = -PS3_IN_PCIE_ERR;
goto l_out;
}
ps3_ioc_state_trigger_transition(instance, doorbell_trigger);
fw_cur_state = instance->ioc_adpter->ioc_state_get(instance);
if (doorbell_trigger == PS3_REG_DOORBELL_STATE_TO_FAULT)
ps3_get_doorbell_done_with_check(instance, &is_doorbell_done);
while (count < time_out) {
if (fw_cur_state == expect_fw_state && is_doorbell_done)
break;
ps3_msleep(PS3_LOOP_TIME_INTERVAL_20MS);
fw_cur_state = instance->ioc_adpter->ioc_state_get(instance);
if (fw_cur_state == PS3_FW_STATE_MASK) {
LOG_ERROR(
"hno:%u break because get fw_cur_state NOK.\n",
PS3_HOST(instance));
break;
}
if (doorbell_trigger == PS3_REG_DOORBELL_STATE_TO_FAULT &&
!is_doorbell_done) {
if (ps3_get_doorbell_done_with_check(
instance, &is_doorbell_done) == PS3_FALSE) {
LOG_ERROR(
"hno:%u break because get doorbell_done NOK.\n",
PS3_HOST(instance));
break;
}
}
count++;
}
if (fw_cur_state != expect_fw_state) {
LOG_ERROR(
"hno:%u fw state transition NOK, is_doorbell_done %d state is %s\n",
PS3_HOST(instance), is_doorbell_done,
ps3_ioc_state_print(fw_cur_state));
ret = -PS3_FAILED;
}
l_out:
return ret;
}
int ps3_ioc_notify_unload(struct ps3_instance *instance)
{
unsigned char is_unload_valid = PS3_FALSE;
int ret = PS3_SUCCESS;
unsigned int count = 0;
unsigned char unload_type = PS3_CMD_TRIGGER_UNLOAD;
LOG_WARN("hno:%u trigger ioc unload reg!!\n", PS3_HOST(instance));
if (instance->state_machine.is_suspend)
unload_type = PS3_CMD_TRIGGER_UNLOAD_SUSPEND;
ps3_ioc_debug0_trigger(instance, unload_type);
ps3_check_debug0_valid_with_check(instance, &is_unload_valid,
unload_type);
while (count < PS3_FW_STATE_TO_UNLOAD_TMO_LOOP_COUNT) {
if (!is_unload_valid)
break;
ps3_msleep(PS3_LOOP_TIME_INTERVAL_20MS);
ps3_check_debug0_valid_with_check(instance, &is_unload_valid,
unload_type);
count++;
}
if (is_unload_valid) {
LOG_ERROR("hno:%u do not wait unload done\n",
PS3_HOST(instance));
ret = -PS3_FAILED;
}
return ret;
}
int ps3_ioc_state_force_to_fault(struct ps3_instance *instance)
{
return ps3_trigger_ioc_state_change_by_doorbell(
instance, PS3_FW_STATE_FAULT, PS3_REG_DOORBELL_STATE_TO_FAULT,
PS3_FW_STATE_TO_FAULT_TMO_LOOP_COUNT);
}
int ps3_ioc_state_force_to_halt(struct ps3_instance *instance)
{
return ps3_trigger_ioc_state_change_by_doorbell(
instance, PS3_FW_STATE_HALT, PS3_REG_DOORBELL_STATE_TO_HALT,
PS3_FW_STATE_TO_HALT_TMO_LOOP_COUNT);
}
#ifdef PS3_HARDWARE_ASIC
unsigned int ps3_ioc_heartbeat_detect(struct ps3_instance *instance)
{
unsigned int ret = PS3_FALSE;
unsigned long long heartbeat_value = 0;
(void)instance;
if (!ps3_enable_heartbeat_query())
return ret;
if (!ps3_ioc_heartbeat_get(instance, &heartbeat_value)) {
LOG_DEBUG("hno:%u probably Linkdown\n", PS3_HOST(instance));
return ret;
}
if (heartbeat_value & instance->hard_dog_mask) {
LOG_DEBUG("hno:%u heartbeat detect success\n",
PS3_HOST(instance));
ret = PS3_TRUE;
}
return ret;
}
#endif

View File

@ -0,0 +1,85 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef _PS3_IOC_STATE_H_
#define _PS3_IOC_STATE_H_
#include "ps3_instance_manager.h"
enum {
PS3_FW_STATE_TO_READY_TMO_LOOP_COUNT_RAID = 18000,
PS3_FW_STATE_TO_READY_TMO_LOOP_COUNT_HBA = 18000,
PS3_WAIT_FOR_OUTSTANDING_IO_COMPLETE = 9000,
PS3_FW_STATE_TO_READY_TMO_LOOP_COUNT_SWITCH = 15000,
PS3_FW_STATE_TO_READY_TMO_LOOP_COUNT_RAID_HAPS = 3600,
PS3_FW_STATE_TO_RUNNING_TMO_LOOP_COUNT = 9000,
PS3_FW_STATE_TO_FAULT_TMO_LOOP_COUNT = 1500,
PS3_FW_STATE_TO_HALT_TMO_LOOP_COUNT = 9000,
PS3_FW_STATE_TO_UNLOAD_TMO_LOOP_COUNT = 500,
PS3_WAIT_EVENT_CMD_LOOP_COUNT = 100,
PS3_LOOP_TIME_INTERVAL_1MS = 1,
PS3_LOOP_TIME_INTERVAL_20MS = 20,
PS3_LOOP_TIME_INTERVAL_50MS = 50,
PS3_LOOP_TIME_INTERVAL_100MS = 100,
PS3_LOOP_TIME_INTERVAL_3000MS = 3000,
PS3_WRITE_HARD_RESET_WAIT_TIME_500MS = 500,
PS3_RECOVERY_WAIT_PROBE_FINISH_LOOP_COUNT = 9000,
PS3_RECOVERY_WAIT_LOOP_TIME_INTERVAL_20MS = 20,
PS3_PS3_LOOP_TIME_INTERVAL_1000MS = 1000,
PS3_TRANS_DEAD_IOC_FAILED_MAX_COUNT = 10,
};
enum ps3_reset_time_type {
PS3_START_WRITE_KEY_REG = 0,
PS3_END_WRITE_KEY_REG = 1,
PS3_START_WAIT_KEY_READY_REG = 2,
PS3_END_WAIT_KEY_READY_REG = 3,
PS3_START_WRITE_HARDRESET_REG = 4,
PS3_END_WRITE_HARDRESET_REG = 5,
PS3_RESET_MAX_COUNT = 6,
};
#define PS3_HARD_RESET_FORCE_STOP_MAX_TIME_FIXED \
(PS3_RECOVERY_WAIT_PROBE_FINISH_LOOP_COUNT * \
PS3_RECOVERY_WAIT_LOOP_TIME_INTERVAL_20MS / HZ + \
PS3_FW_STATE_TO_FAULT_TMO_LOOP_COUNT * PS3_LOOP_TIME_INTERVAL_20MS / \
HZ + \
PS3_LOOP_TIME_INTERVAL_100MS * PS3_LOOP_TIME_INTERVAL_100MS / HZ + \
PS3_WRITE_HARD_RESET_WAIT_TIME_500MS / HZ + \
PS3_SLEEP_TOLERATE_TIMEOUT)
#ifdef PS3_HARDWARE_HAPS_V200
#define PS3_HARD_RESET_FORCE_STOP_MAX_TIME(ins) \
(PS3_HARD_RESET_FORCE_STOP_MAX_TIME_FIXED + \
(ins)->wait_ready_timeout * PS3_LOOP_TIME_INTERVAL_3000MS / HZ)
#else
#define PS3_HARD_RESET_FORCE_STOP_MAX_TIME(ins) \
(PS3_HARD_RESET_FORCE_STOP_MAX_TIME_FIXED + \
(ins)->wait_ready_timeout * PS3_LOOP_TIME_INTERVAL_20MS / HZ)
#endif
int ps3_ioc_state_transfer_to_ready(struct ps3_instance *instance);
int ps3_ioc_state_transfer_wait_to_running(struct ps3_instance *instance);
int ps3_ioc_state_hard_reset(struct ps3_instance *instance);
int ps3_ioc_state_shallow_soft_reset(struct ps3_instance *instance);
int ps3_ioc_state_deep_soft_reset(struct ps3_instance *instance);
int ps3_ioc_state_force_to_fault(struct ps3_instance *instance);
int ps3_ioc_state_force_to_halt(struct ps3_instance *instance);
int ps3_ioc_notify_unload(struct ps3_instance *instance);
#ifdef PS3_HARDWARE_ASIC
unsigned int ps3_ioc_heartbeat_detect(struct ps3_instance *instance);
#endif
int ps3_ioc_state_ready_wait(struct ps3_instance *instance);
int ps3_ioc_state_fault_wait(struct ps3_instance *instance);
const char *ps3_ioc_state_print(unsigned int state);
#endif

View File

@ -0,0 +1,825 @@
// SPDX-License-Identifier: GPL-2.0
#include "ps3_ioctl.h"
#ifdef _WINDOWS
#include <storport.h>
#define PS3_FUNC_FROM_CTL_CODE(ctrlCode) \
(((unsigned long)(ctrlCode & 0x3FFC)) >> 2)
#define PS3_ACC_FROM_CTL_CODE(ctrlCode) \
(((unsigned long)(ctrlCode & 0xC000)) >> 14)
#else
#include <linux/kernel.h>
#include <linux/pci.h>
#include <linux/moduleparam.h>
#include <linux/module.h>
#include <linux/mutex.h>
#include <linux/uio.h>
#include <linux/irq_poll.h>
#include <linux/workqueue.h>
#include <linux/mutex.h>
#include <linux/uaccess.h>
#include <scsi/scsi_host.h>
#endif
#include "ps3_cmd_statistics.h"
#include "ps3_htp.h"
#include "ps3_htp_def.h"
#include "ps3_mgr_cmd.h"
#include "ps3_driver_log.h"
#include "ps3_mgr_channel.h"
#include "ps3_mgr_cmd_err.h"
#include "ps3_util.h"
#include "ps3_event.h"
int ps3_ioctl_init(struct ps3_instance *instance, int cmd_num)
{
#ifdef _WINDOWS
(void)cmd_num;
ps3_atomic_set(&instance->ioctl_count, 0);
#else
sema_init(&instance->ioctl_sem, cmd_num);
#endif
ps3_atomic_set(&instance->cmd_statistics.cli_cnt,
PS3_CMD_STAT_INIT_VALUE);
return PS3_SUCCESS;
}
static int ps3_ioctl_capbility_pre_check(struct ps3_instance *instance,
struct PS3IoctlSyncCmd *ioc)
{
int ret = PS3_SUCCESS;
if (ioc->sgeCount > PS3_MAX_IOCTL_SGE_NUM || ioc->sgeCount == 0) {
LOG_WARN(
"hno:%u ioctl req, SGE count [%d] > max limit [%d], or SGE count = 0\n",
PS3_HOST(instance), ioc->sgeCount,
PS3_MAX_IOCTL_SGE_NUM);
ret = -PS3_EINVAL;
goto l_out;
}
(void)instance;
l_out:
return ret;
}
void ps3_ioctl_buff_bit_pos_update(struct ps3_cmd *cmd)
{
unsigned char i = 0;
struct PS3Sge *pSge = (struct PS3Sge *)cmd->req_frame->mgrReq.sgl;
struct ps3_instance *instance = cmd->instance;
unsigned char bit_pos = 0;
if (cmd->transient == NULL)
goto l_out;
if (cmd->transient->sge_num == 0)
goto l_out;
for (i = 0; i < cmd->transient->sge_num; i++) {
if (cmd->transient->transient_buff[i] != NULL) {
if (pSge->ext == 1)
pSge = (struct PS3Sge *)cmd->ext_buf;
bit_pos = ps3_dma_addr_bit_pos_check(
(dma_addr_t)le64_to_cpu(pSge->addr));
if (bit_pos != instance->dma_addr_bit_pos) {
pSge->addr = cpu_to_le64(
PCIE_DMA_HOST_ADDR_BIT_POS_CLEAR_NEW(
bit_pos,
le64_to_cpu(pSge->addr)));
pSge->addr = cpu_to_le64(
PCIE_DMA_HOST_ADDR_BIT_POS_SET_NEW(
instance->dma_addr_bit_pos,
le64_to_cpu(pSge->addr)));
}
}
pSge++;
}
l_out:
return;
}
void ps3_ioctl_buff_release(struct ps3_cmd *cmd)
{
unsigned char i = 0;
struct PS3Sge *pSge = (struct PS3Sge *)cmd->req_frame->mgrReq.sgl;
struct ps3_instance *instance = cmd->instance;
if (cmd->transient == NULL)
return;
if (cmd->transient->sge_num == 0)
return;
for (i = 0; i < cmd->transient->sge_num; i++) {
if (cmd->transient->transient_buff[i] != NULL) {
if (pSge->ext == 1)
pSge = (struct PS3Sge *)cmd->ext_buf;
ps3_dma_free_coherent(
instance, cpu_to_le32(pSge->length),
cmd->transient->transient_buff[i],
(dma_addr_t)cpu_to_le64(pSge->addr));
cmd->transient->transient_buff[i] = NULL;
memset(pSge, 0, sizeof(struct PS3Sge));
}
pSge++;
}
memset((void *)cmd->req_frame, 0, sizeof(union PS3ReqFrame));
cmd->transient->sge_num = 0;
}
static int ps3_ioctl_sge_fill(struct ps3_instance *instance,
unsigned char *base_addr, struct PS3Sge *psrc_sge,
struct PS3Sge *pdst_sge, void **transient_buff)
{
int ret = PS3_SUCCESS;
dma_addr_t transient_addr = 0;
*transient_buff =
ps3_dma_alloc_coherent(instance, psrc_sge->length,
(unsigned long long *)&transient_addr);
if (*transient_buff == NULL) {
LOG_ERROR(
"hno:%u Failed to alloc kernel SGL buffer for IOCTL\n",
PS3_HOST(instance));
ret = -PS3_ENOMEM;
goto l_out;
}
pdst_sge->length = cpu_to_le32(psrc_sge->length);
pdst_sge->ext = 0;
pdst_sge->lastSge = 0;
pdst_sge->addr = (unsigned long long)cpu_to_le64(transient_addr);
#ifdef _WINDOWS
LOG_DEBUG(
"===base_addr[%p],psrc_sge->addr[%d], psrc_sge->length[%d]\n",
base_addr, psrc_sge->addr, psrc_sge->length);
memcpy(*transient_buff, (void *)(base_addr + psrc_sge->addr),
psrc_sge->length);
#else
(void)base_addr;
if (copy_from_user(*transient_buff,
(void __user *)(uintptr_t)psrc_sge->addr,
psrc_sge->length)) {
LOG_ERROR("hno:%u, copy from user err\n", PS3_HOST(instance));
ret = -PS3_FAILED;
goto l_out;
}
#endif
l_out:
return ret;
}
static int ps3_ioctl_sgl_fill(struct ps3_instance *instance,
struct ps3_cmd *cmd, struct PS3IoctlSyncCmd *ioc)
{
unsigned char i = 0;
int ret = PS3_SUCCESS;
struct PS3Sge *pdst_sge = NULL;
struct PS3Sge *psrc_sge =
(struct PS3Sge *)((unsigned int *)ioc + ioc->sglOffset);
unsigned char pre_sge_count =
(unsigned char)((ioc->sgeCount > PS3_FRAME_REQ_SGE_NUM_MGR) ?
(PS3_FRAME_REQ_SGE_NUM_MGR - 1) :
ioc->sgeCount);
if (cmd->transient->sge_num != 0) {
LOG_ERROR("trace_id[0x%llx], hno:%u got cmd NOK: %d\n",
cmd->trace_id, PS3_HOST(instance), cmd->index);
PS3_BUG();
ret = -PS3_FAILED;
goto l_out;
}
cmd->transient->sge_num = ioc->sgeCount;
cmd->req_frame->mgrReq.sgeOffset =
offsetof(struct PS3MgrReqFrame, sgl) >>
PS3_MGR_CMD_SGL_OFFSET_DWORD_SHIFT;
cmd->req_frame->mgrReq.sgeCount = ioc->sgeCount;
pdst_sge = cmd->req_frame->mgrReq.sgl;
for (i = 0; i < pre_sge_count; i++) {
LOG_DEBUG("trace_id[0x%llx], hno:%u sge[%u] size : %d\n",
cmd->trace_id, PS3_HOST(instance), i,
psrc_sge->length);
pdst_sge->length = 0;
if (psrc_sge->length > 0) {
ret = ps3_ioctl_sge_fill(
instance, (unsigned char *)ioc, psrc_sge,
pdst_sge, &cmd->transient->transient_buff[i]);
if (ret != PS3_SUCCESS) {
LOG_ERROR(
"trace_id[0x%llx], hno:%u sge[%u] fill data error(%d)\n",
cmd->trace_id, PS3_HOST(instance), i, ret);
goto l_out;
}
}
pdst_sge++;
psrc_sge++;
}
if (ioc->sgeCount > PS3_FRAME_REQ_SGE_NUM_MGR) {
LOG_FILE_INFO(
"hno:%u ioctl req num %d is bigger than req frame num %d\n",
PS3_HOST(instance), ioc->sgeCount,
PS3_FRAME_REQ_SGE_NUM_MGR);
pdst_sge->addr =
(unsigned long long)cpu_to_le64(cmd->ext_buf_phys);
pdst_sge->length = 0;
pdst_sge->ext = 1;
pdst_sge = (struct PS3Sge *)cmd->ext_buf;
cmd->req_frame->mgrReq.sgeCount++;
for (i = PS3_FRAME_REQ_SGE_NUM_MGR - 1; i < ioc->sgeCount;
i++) {
LOG_DEBUG(
"trace_id[0x%llx], hno:%u sge[%u] size : %d\n",
cmd->trace_id, PS3_HOST(instance), i,
psrc_sge->length);
pdst_sge->length = 0;
if (psrc_sge->length > 0) {
ret = ps3_ioctl_sge_fill(
instance, (unsigned char *)ioc,
psrc_sge, pdst_sge,
&cmd->transient->transient_buff[i]);
if (ret != PS3_SUCCESS) {
LOG_ERROR(
"trace_id[0x%llx], hno:%u sge[%u] fill data error(%d)\n",
cmd->trace_id,
PS3_HOST(instance), i, ret);
goto l_out;
}
}
pdst_sge++;
psrc_sge++;
}
}
pdst_sge--;
pdst_sge->lastSge = 1;
l_out:
return ret;
}
static int ps3_ioctl_complete(struct ps3_instance *instance,
struct ps3_cmd *cmd, struct PS3IoctlSyncCmd *ioc)
{
int ret = PS3_SUCCESS;
unsigned int i = 0;
struct PS3Sge *psrc_sge =
(struct PS3Sge *)((unsigned int *)ioc + ioc->sglOffset);
for (i = 0; i < ioc->sgeCount; i++) {
LOG_DEBUG(
"trace_id[0x%llx], hno:%u CFID [%d], transient_buff[%u] address: %p, data size: %d\n",
cmd->trace_id, PS3_HOST(instance), cmd->index, i,
cmd->transient->transient_buff[i], psrc_sge->length);
if (psrc_sge->length > 0) {
#ifdef _WINDOWS
memcpy((void *)((unsigned char *)ioc + psrc_sge->addr),
cmd->transient->transient_buff[i],
psrc_sge->length);
#else
if (copy_to_user(
(void __user *)(uintptr_t)psrc_sge->addr,
cmd->transient->transient_buff[i],
psrc_sge->length)) {
LOG_ERROR("hno:%u copy to user err\n",
PS3_HOST(instance));
ret = -PS3_FAILED;
goto l_out;
}
#endif
}
psrc_sge++;
}
#ifndef _WINDOWS
l_out:
#endif
LOG_FILE_INFO(
"trace_id[0x%llx], ioctl complete hno:%u CFID [%u], ret[%d]\n",
cmd->trace_id, PS3_HOST(instance), cmd->index, ret);
return ret;
}
static int ps3_ioctl_mgr_handle(struct ps3_instance *instance,
struct PS3IoctlSyncCmd *ioc)
{
int ret = PS3_SUCCESS;
struct ps3_cmd *cmd = NULL;
int send_result = PS3_SUCCESS;
unsigned char retry_count = 0;
while (retry_count < PS3_ERR_MGR_CMD_FAULT_RETRY_MAX) {
ps3_atomic_inc(&instance->cmd_statistics.cmd_delivering);
ret = ps3_mgr_cmd_send_pre_check(instance, PS3_FALSE);
if (ret != PS3_SUCCESS) {
ps3_atomic_dec(
&instance->cmd_statistics.cmd_delivering);
if (ret == -PS3_RECOVERED) {
if (++retry_count <
PS3_ERR_MGR_CMD_FAULT_RETRY_MAX) {
ret = ps3_instance_wait_for_normal(
instance);
}
}
if (ret != PS3_SUCCESS) {
LOG_WARN_LIM(
"tid[0x%llx], hno:%u ioctl cmd pre check NOK ret:%d!\n",
ioc->traceId, PS3_HOST(instance), ret);
goto l_no_free_cmd;
}
continue;
}
break;
}
cmd = ps3_mgr_cmd_alloc(instance);
if (cmd == NULL) {
LOG_WARN("hno:%u ioctl req, not get a cmd packet\n",
PS3_HOST(instance));
ret = -PS3_FAILED;
ps3_atomic_dec(&instance->cmd_statistics.cmd_delivering);
goto l_no_free_cmd;
}
LOG_DEBUG("trace_id[0x%llx], hno:%u CFID [%u], get mgr cmd succeed\n",
cmd->trace_id, PS3_HOST(instance), cmd->index);
cmd->time_out = 0;
cmd->is_interrupt = PS3_DRV_TRUE;
if (ioc->traceId != 0) {
ps3_cmd_trace_id_replace(cmd, ioc->traceId);
LOG_DEBUG(
"trace_id[0x%llx], hno:%u CFID [%u], change trace id from cli\n",
cmd->trace_id, PS3_HOST(instance), cmd->index);
}
memset(&cmd->req_frame->mgrReq, 0, sizeof(struct PS3MgrReqFrame));
memset(cmd->transient->transient_buff, 0,
sizeof(void *) * PS3_MAX_IOCTL_SGE_NUM);
ret = ps3_ioctl_sgl_fill(instance, cmd, ioc);
if (ret != PS3_SUCCESS) {
ps3_atomic_dec(&instance->cmd_statistics.cmd_delivering);
goto l_out;
}
ps3_ioctl_req_frame_build(cmd);
ps3_mgr_cmd_word_build(cmd);
send_result = ps3_cmd_send_sync(instance, cmd);
ps3_atomic_dec(&instance->cmd_statistics.cmd_delivering);
if (send_result == PS3_SUCCESS)
send_result = ps3_cmd_wait_sync(instance, cmd);
ret = ps3_mgr_complete_proc(instance, cmd, send_result);
if (ret == -PS3_CMD_NO_RESP) {
LOG_ERROR(
"trace_id[0x%llx], hno:%u ioctl request no response!\n",
cmd->trace_id, PS3_HOST(instance));
goto l_no_free_cmd;
}
if (ret != PS3_SUCCESS) {
LOG_ERROR(
"trace_id[0x%llx], hno:%u ioctl send request NOK!%d\n",
cmd->trace_id, PS3_HOST(instance), ret);
goto l_out;
}
ret = ps3_ioctl_complete(instance, cmd, ioc);
LOG_INFO(
"trace_id[0x%llx], hno:%u CFID [%u], ioctl cmd_type[%d], sub_type[%d] end\n",
cmd->trace_id, PS3_HOST(instance), cmd->index,
ioc->msg.header.cmdType, ioc->msg.header.cmdSubType);
l_out:
ps3_ioctl_buff_release(cmd);
ps3_mgr_cmd_free(instance, cmd);
l_no_free_cmd:
return ret;
}
#ifdef _WINDOWS
static unsigned char ps3_ioctl_windows_pre_check(struct ps3_instance *instance,
struct _PS3_IO_CONTROL ioctl)
{
unsigned char ret = PS3_TRUE;
unsigned char i = 0;
unsigned char *base_addr = (unsigned char *)&ioctl->ps3Ioctl;
unsigned char *last_addr = base_addr + ioctl->SrbHeader.Length;
if (ioctl->ps3Ioctl.data == NULL || ioctl->SrbHeader.Length == 0) {
LOG_WARN(
"hno:%u ioctl req, data is [%p], or data len is [%llu]\n",
PS3_HOST(instance), ioctl->ps3Ioctl.data,
ioctl->SrbHeader.Length);
ret = PS3_FALSE;
goto l_out;
}
if (ps3_ioctl_capbility_pre_check(instance, &ioctl->ps3Ioctl) !=
PS3_SUCCESS) {
ret = PS3_FALSE;
goto l_out;
}
LOG_INFO("hno:%u base_addr[%p], Length[%d], last_addr[%p]\n",
PS3_HOST(instance), base_addr, ioctl->SrbHeader.Length,
last_addr);
for (i = 0; i < ioctl->ps3Ioctl.sgeCount; i++) {
if (base_addr + ioctl->ps3Ioctl.Sgl[i].addr +
ioctl->ps3Ioctl.Sgl[i].length >
last_addr) {
LOG_ERROR(
"hno:%u ioctl req, sge[%d] len[%d] > total len[%d], sge offset[%p], base addr[%p]\n",
PS3_HOST(instance), i,
ioctl->ps3Ioctl.Sgl[i].length,
ioctl->SrbHeader.Length,
ioctl->ps3Ioctl.Sgl[i].addr, &ioctl->ps3Ioctl);
ret = PS3_FALSE;
goto l_out;
}
}
(void)instance;
l_out:
return ret;
}
int ps3_ioctl_callback_proc(struct ps3_cmd *cmd, unsigned char reply_flags)
{
unsigned long flags = 0;
int ret = PS3_SUCCESS;
struct ps3_instance *instance = cmd->instance;
int send_result = -PS3_RESP_ERR;
SCSI_REQUEST_BLOCK *srb = cmd->srb;
struct _PS3_IO_CONTROL ps3_ioctl = NULL;
LOG_DEBUG(
"hno:%u trace_id[0x%llx], got a ioctl response, reply_flags[0x%x]\n",
PS3_HOST(instance), cmd->trace_id, reply_flags);
PS3_MGR_CMD_BACK_INC(instance, cmd, reply_flags);
if (unlikely(reply_flags != PS3_REPLY_WORD_FLAG_SUCCESS) &&
cmd->retry_cnt < PS3_ERR_MGR_CMD_FAULT_RETRY_MAX) {
LOG_ERROR("trace_id[0x%llx], hno:%u ioctl cmd return failed\n",
cmd->trace_id, PS3_HOST(instance));
ret = ps3_err_mgr_cmd_proc(instance, send_result, cmd);
if (ret == -PS3_CMD_NO_RESP)
ret = ps3_mgr_cmd_no_resp_proc(instance, cmd);
if (ret != -PS3_RETRY) {
LOG_WARN("hno:%u CFID:%d retry, retries:%d, ret:%d\n",
PS3_HOST(instance), cmd->index, cmd->retry_cnt,
ret);
goto l_out;
}
ps3_spin_lock_irqsave(&cmd->cmd_state.lock, &flags);
cmd->cmd_state.state = PS3_CMD_STATE_PROCESS;
ps3_spin_unlock_irqrestore(&cmd->cmd_state.lock, flags);
cmd->retry_cnt++;
if (cmd->retry_cnt >= PS3_ERR_MGR_CMD_FAULT_RETRY_MAX) {
LOG_ERROR("hno:%u retry time full.\n",
PS3_HOST(instance));
ret = -PS3_FAILED;
goto l_out;
}
LOG_INFO("hno:%u mgr CFID[%d] retry:%u\n", PS3_HOST(instance),
cmd->index, cmd->retry_cnt);
ret = ps3_srb_send(instance, srb);
if (ret != PS3_SUCCESS) {
LOG_ERROR(
"trace_id[0x%llx], hno:%u ioctl send request failed!%d\n",
cmd->trace_id, PS3_HOST(instance), ret);
goto l_out;
}
goto l_retry;
}
l_out:
SrbSetSrbStatus(srb, SRB_STATUS_ERROR);
if ((cmd->resp_frame->normalRespFrame.respStatus ==
PS3_DRV_MGR_RESTART_COMMAND_RSP) &&
(reply_flags == PS3_REPLY_WORD_FLAG_FAIL)) {
reply_flags = PS3_REPLY_WORD_FLAG_SUCCESS;
}
if (likely(reply_flags == PS3_REPLY_WORD_FLAG_SUCCESS)) {
ps3_ioctl = (struct _PS3_IO_CONTROL)SrbGetDataBuffer(srb);
ps3_ioctl_complete(instance, cmd, &ps3_ioctl->ps3Ioctl);
SrbSetSrbStatus(srb, SRB_STATUS_SUCCESS);
}
ps3_ioctl_buff_release(cmd);
ps3_mgr_cmd_free(instance, cmd);
StorPortNotification(RequestComplete, instance, srb);
ps3_atomic_dec(&instance->ioctl_count);
l_retry:
LOG_DEBUG(
"hno:%u trace_id[0x%llx], end proc a ioctl response, ret[%d]\n",
PS3_HOST(instance), cmd->trace_id, ret);
return ret;
}
unsigned char ps3_ioctl_build_io(_In_ struct ps3_instance *instance,
_In_ PSCSI_REQUEST_BLOCK Srb)
{
unsigned char ret = PS3_FALSE;
struct _PS3_IO_CONTROL ps3_ioctl =
(struct _PS3_IO_CONTROL)SrbGetDataBuffer(Srb);
LOG_INFO(
"ioctl parase: Type[0x%x], Method[0x%x], Function[0x%x], Access[0x%x]\n",
DEVICE_TYPE_FROM_CTL_CODE(ps3_ioctl->SrbHeader.ControlCode),
METHOD_FROM_CTL_CODE(ps3_ioctl->SrbHeader.ControlCode),
PS3_FUNC_FROM_CTL_CODE(ps3_ioctl->SrbHeader.ControlCode),
PS3_ACC_FROM_CTL_CODE(ps3_ioctl->SrbHeader.ControlCode));
if (memcmp(ps3_ioctl->SrbHeader.Signature, PS3_IOCTL_SIG,
sizeof(PS3_IOCTL_SIG)) != 0) {
LOG_ERROR("hno:%u ioctl signature error\n", PS3_HOST(instance));
SrbSetSrbStatus(Srb, SRB_STATUS_INVALID_REQUEST);
goto l_out;
}
if (!instance->state_machine.is_load) {
LOG_WARN(
"trace_id[0x%llx], hno:%u instance state not is_load\n",
ps3_ioctl->ps3Ioctl.traceId, PS3_HOST(instance));
SrbSetSrbStatus(Srb, SRB_STATUS_NO_HBA);
goto l_out;
}
if (!ps3_atomic_add_unless(&instance->ioctl_count, 1,
PS3_MAX_IOCTL_CMDS)) {
LOG_WARN("hno:%u ioctl concurrency full\n", PS3_HOST(instance));
SrbSetSrbStatus(Srb, SRB_STATUS_BUSY);
goto l_out;
}
if (!ps3_is_instance_state_allow_cmd_execute(instance)) {
SrbSetSrbStatus(Srb, SRB_STATUS_NO_DEVICE);
goto l_out;
}
ret = ps3_ioctl_windows_pre_check(instance, ps3_ioctl);
if (!ret) {
LOG_WARN("hno:%u ioctl capblity not support\n",
PS3_HOST(instance));
SrbSetSrbStatus(Srb, SRB_STATUS_INVALID_REQUEST);
ps3_atomic_dec(&instance->ioctl_count);
goto l_out;
}
if (ps3_ioctl_mgr_handle(instance, &ps3_ioctl->ps3Ioctl, Srb) !=
PS3_SUCCESS) {
LOG_ERROR("hno:%u ioctl handle err\n", PS3_HOST(instance));
SrbSetSrbStatus(Srb, SRB_STATUS_ERROR);
ps3_atomic_dec(&instance->ioctl_count);
goto l_out;
}
ret = PS3_TRUE;
SrbSetSrbStatus(Srb, SRB_STATUS_SUCCESS);
l_out:
if (!ret)
StorPortNotification(RequestComplete, instance, Srb);
return ret;
}
unsigned char ps3_ioctl_start_io(_In_ struct ps3_instance *instance,
_In_ PSCSI_REQUEST_BLOCK Srb)
{
struct ps3_cmd *cmd = ps3_cmd_from_srb_extension_get(Srb);
unsigned char ret = PS3_FALSE;
int ret_tmp = PS3_SUCCESS;
SrbSetSrbStatus(Srb, SRB_STATUS_ERROR);
ret_tmp = ps3_srb_send(instance, Srb);
if (ret_tmp != PS3_SUCCESS) {
LOG_ERROR(
"trace_id[0x%llx], hno:%u ioctl send request failed!%d\n",
cmd->trace_id, PS3_HOST(instance), ret_tmp);
goto l_out;
}
ret = PS3_TRUE;
SrbSetSrbStatus(Srb, SRB_STATUS_SUCCESS);
l_out:
if (!ret) {
ps3_ioctl_buff_release(cmd);
ps3_mgr_cmd_free(instance, cmd);
StorPortNotification(RequestComplete, instance, Srb);
ps3_atomic_dec(&instance->ioctl_count);
}
return ret;
}
#else
static int ps3_ioctl_mgr_sync(unsigned long arg)
{
int ret = PS3_SUCCESS;
struct PS3IoctlSyncCmd *ioc = NULL;
struct ps3_instance *instance = NULL;
struct PS3IoctlSyncCmd __user *user_ioc =
(struct PS3IoctlSyncCmd __user *)arg;
ioc = (struct PS3IoctlSyncCmd *)memdup_user(
(const void __user *)user_ioc, sizeof(*ioc));
if (IS_ERR(ioc)) {
LOG_ERROR("ioctl memdup_user err\n");
return PTR_ERR(ioc);
}
LOG_INFO("ioctl ps3_ioctl_sync_cmd: trace_id[0x%llx], hno:%u\n"
"\tcmd_type[%d], sgl_offset[%d], sge_count[%d], result[%d]\n",
ioc->traceId, ioc->hostId, ioc->msg.header.cmdType,
ioc->sglOffset, ioc->sgeCount, ioc->resultCode);
ps3_mutex_lock(&ps3_mgmt_info_get()->ps3_mgmt_lock);
instance = ps3_instance_lookup(ioc->hostId);
if (instance == NULL) {
ps3_mutex_unlock(&ps3_mgmt_info_get()->ps3_mgmt_lock);
LOG_WARN("can found instance, host no is %d\n", ioc->hostId);
ret = -ENODEV;
goto l_out_free_ioc;
}
if (!instance->state_machine.is_load) {
ps3_mutex_unlock(&ps3_mgmt_info_get()->ps3_mgmt_lock);
LOG_WARN("trace_id[0x%llx], hno:%u instance state [%d]\n",
ioc->traceId, PS3_HOST(instance),
instance->state_machine.is_load);
ret = -ENODEV;
goto l_out_free_ioc;
}
if (!instance->is_scan_host_finish) {
ps3_mutex_unlock(&ps3_mgmt_info_get()->ps3_mgmt_lock);
LOG_WARN(
"trace_id[0x%llx], hno:%u instance scan host not finish\n",
ioc->traceId, PS3_HOST(instance));
ret = -EAGAIN;
goto l_out_free_ioc;
}
ps3_atomic_inc(&instance->cmd_statistics.cli_cnt);
ps3_mutex_unlock(&ps3_mgmt_info_get()->ps3_mgmt_lock);
LOG_FILE_INFO("hno:%u ioctl ready get sem\n", PS3_HOST(instance));
if (down_interruptible(&instance->ioctl_sem)) {
LOG_WARN("hno:%u ioctl concurrency full\n", PS3_HOST(instance));
ret = -ERESTARTSYS;
goto l_out_dec_cnt;
}
ret = ps3_instance_wait_for_normal(instance);
if (ret != PS3_SUCCESS) {
LOG_WARN(
"trace_id[0x%llx], hno:%u instance state not allowed ioctl req\n",
ioc->traceId, PS3_HOST(instance));
ret = -ENODEV;
goto l_out_up;
}
LOG_INFO("hno:%u ioctl got sem\n", PS3_HOST(instance));
if (ioc->msg.header.cmdType == PS3_IOCTL_CMD_WEB_SUBSCRIBE) {
if (ps3_atomic_read(
&instance->webSubscribe_context.is_subscribe) !=
1) {
if (ps3_atomic_add_unless(&instance->webSubscribe_context
.subscribe_count,
1, 1) != 0) {
ret = ps3_web_subscribe(instance);
if (ret != PS3_SUCCESS) {
ps3_atomic_set(
&instance->webSubscribe_context
.subscribe_count,
0);
ret = -EBUSY;
goto l_out_up;
}
ps3_atomic_set(&instance->webSubscribe_context
.is_subscribe,
1);
goto l_out_dec_cnt;
} else {
ret = -EAGAIN;
goto l_out_up;
}
} else {
ret = PS3_SUCCESS;
goto l_out_up;
}
} else {
ret = ps3_ioctl_capbility_pre_check(instance, ioc);
if (ret != PS3_SUCCESS) {
LOG_WARN("hno:%u ioctl capblity not support\n",
PS3_HOST(instance));
ret = -EINVAL;
goto l_out_up;
}
ret = ps3_ioctl_mgr_handle(instance, ioc);
if (ret != PS3_SUCCESS) {
LOG_ERROR("hno:%u ioctl handle NOK\n",
PS3_HOST(instance));
ret = -EBUSY;
}
}
l_out_up:
up(&instance->ioctl_sem);
l_out_dec_cnt:
ps3_atomic_dec(&instance->cmd_statistics.cli_cnt);
l_out_free_ioc:
kfree(ioc);
return ret;
}
long ps3_ioctl_fops(struct file *file, unsigned int cmd, unsigned long arg)
{
int ret = -ENOTTY;
if (file == NULL || arg == 0)
goto l_out;
switch (cmd) {
case PS3_CMD_IOCTL_SYNC_CMD:
ret = ps3_ioctl_mgr_sync(arg);
break;
default:
break;
}
l_out:
return ret;
}
void ps3_clean_mgr_cmd(struct ps3_instance *instance)
{
struct ps3_cmd_context *context = &instance->cmd_context;
unsigned int mgr_cmd_idx = 0;
unsigned int mgr_start_idx = context->max_scsi_cmd_count;
unsigned int mgr_end_idx =
context->max_scsi_cmd_count + instance->max_mgr_cmd_count;
struct ps3_cmd *cmd = NULL;
for (mgr_cmd_idx = mgr_start_idx; mgr_cmd_idx < mgr_end_idx;
mgr_cmd_idx++) {
cmd = context->cmd_buf[mgr_cmd_idx];
if (cmd->cmd_word.type == PS3_CMDWORD_TYPE_MGR) {
LOG_WARN("hno:%u mgr cmd[%d] complete force!\n",
PS3_HOST(instance), cmd->index);
cmd->resp_frame->normalRespFrame.respStatus =
PS3_MGR_REC_FORCE;
cmd->cmd_state.state = PS3_CMD_STATE_COMPLETE;
complete(&cmd->sync_done);
}
}
}
void ps3_ioctl_clean(struct ps3_instance *instance)
{
if (ps3_atomic_read(&instance->state_machine.state) !=
PS3_INSTANCE_STATE_QUIT) {
goto l_out;
}
while (ps3_atomic_read(&instance->cmd_statistics.cli_cnt) != 0) {
LOG_INFO("hno:%u ioctls not finish\n", PS3_HOST(instance));
ps3_clean_mgr_cmd(instance);
ps3_msleep(1000);
}
l_out:
return;
}
#endif

View File

@ -0,0 +1,64 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef _PS3_IOCTL_H_
#define _PS3_IOCTL_H_
#ifdef _WINDOWS
#include "ps3_def.h"
#endif
#include "ps3_instance_manager.h"
#include "ps3_cmd_channel.h"
#include "ps3_htp_ioctl.h"
#define PS3_MAX_IOCTL_CMDS 3
#ifdef _WINDOWS
unsigned char ps3_ioctl_start_io(_In_ struct ps3_instance *instance,
_In_ PSCSI_REQUEST_BLOCK Srb);
unsigned char ps3_ioctl_build_io(_In_ struct ps3_instance *instance,
_In_ PSCSI_REQUEST_BLOCK Srb);
#else
long ps3_ioctl_fops(struct file *file, unsigned int cmd, unsigned long arg);
#endif
int ps3_ioctl_init(struct ps3_instance *instance, int cmd_num);
void ps3_ioctl_buff_release(struct ps3_cmd *cmd);
static inline void ps3_ioctl_req_frame_build(struct ps3_cmd *cmd)
{
struct PS3MgrReqFrame *mgr_req = &cmd->req_frame->mgrReq;
mgr_req->reqHead.traceID = cmd->trace_id;
mgr_req->reqHead.cmdType = PS3_CMD_IOCTL;
mgr_req->reqHead.cmdSubType = 0;
mgr_req->reqHead.cmdFrameID = cmd->index;
mgr_req->reqHead.timeout = 0;
mgr_req->timeout = 0;
mgr_req->syncFlag = 1;
}
static inline void ps3_ioctl_cmd_word_build(struct ps3_instance *instance,
struct ps3_cmd *cmd,
unsigned short cmd_frame_id)
{
struct PS3CmdWord *cmd_word = &cmd->cmd_word;
memset(cmd_word, 0, sizeof(*cmd_word));
(void)instance;
cmd_word->type = PS3_CMDWORD_TYPE_MGR;
cmd_word->direct = PS3_CMDWORD_DIRECT_NORMAL;
cmd_word->cmdFrameID = cmd_frame_id;
#ifndef _WINDOWS
cmd_word->isrSN = ps3_msix_index_get(cmd, 1);
#endif
}
int ps3_ioctl_callback_proc(struct ps3_cmd *cmd, unsigned char reply_flags);
void ps3_ioctl_clean(struct ps3_instance *instance);
void ps3_ioctl_buff_bit_pos_update(struct ps3_cmd *cmd);
#endif

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,198 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef _PS3_IRQ_H_
#define _PS3_IRQ_H_
#ifndef _WINDOWS
#include <linux/list.h>
#include <linux/irq_poll.h>
#include <scsi/scsi_host.h>
#include <linux/irqreturn.h>
#endif
#include "ps3_htp_def.h"
#include "ps3_err_def.h"
#include "ps3_cmd_channel.h"
#include "ps3_inner_data.h"
#include "ps3_kernel_version.h"
#define PS3_IRQ_NAME_LENGTH (32)
#define PS3_SWITCH_IRQ_INDEX (0)
struct ps3_instance;
enum {
PS3_PCI_IRQ_MODE_NONE_SPE = 0,
PS3_PCI_IRQ_MODE_LEGACY = 1,
PS3_PCI_IRQ_MODE_MSI = 2,
PS3_PCI_IRQ_MODE_MSIX = 3,
};
struct ps3_irq {
char name[PS3_IRQ_NAME_LENGTH];
struct PS3ReplyWord *reply_fifo_virt_base_addr;
struct ps3_instance *instance;
unsigned int irqNo;
unsigned int isrSN;
unsigned short last_reply_idx;
unsigned char reserved0[6];
#ifdef _WINDOWS
STOR_DPC dpc;
#else
struct irq_poll irqpoll;
unsigned char is_irq_poll_disabled;
unsigned int irq_poll_sched_threshold;
unsigned char is_sched_irq_poll;
unsigned char is_enable_irq;
unsigned char reserved1[2];
#endif
atomic_t is_busy;
};
struct ps3_irq_recovery {
unsigned int irqNo;
unsigned int isrSN;
unsigned char reserved0[8];
struct ps3_instance *instance;
};
struct ps3_irq_context {
struct ps3_instance *instance;
unsigned int reply_fifo_depth;
unsigned int valid_msix_vector_count;
unsigned int high_iops_msix_vectors;
unsigned int dump_isrSN;
unsigned int reply_fifo_desc_buf_size;
#ifndef _WINDOWS
struct dma_pool *reply_fifo_desc_buf_pool;
#endif
unsigned int reply_fifo_size;
dma_addr_t reply_fifo_desc_buf_phys;
struct PS3ReplyFifoDesc *reply_fifo_desc_buf;
#ifndef _WINDOWS
struct dma_pool *reply_fifo_pool;
#endif
struct PS3ReplyWord
*reply_fifo_virt_base_addr_buf[PS3_MAX_REPLY_QUE_COUNT];
dma_addr_t reply_fifo_phys_base_addr_buf[PS3_MAX_REPLY_QUE_COUNT];
struct ps3_irq *irqs;
#ifndef _WINDOWS
unsigned int *cpu_msix_table;
atomic_t high_iops_io_count;
int cpu_msix_table_sz;
#endif
unsigned char is_enable_interrupts;
unsigned char is_support_balance;
unsigned char is_balance_current_perf_mode;
unsigned char pci_irq_type;
#ifdef _WINDOWS
PGROUP_AFFINITY group_affinity;
#endif
struct ps3_irq_recovery *irq_recovery;
};
int ps3_irq_context_init(struct ps3_instance *instance);
int ps3_irq_context_exit(struct ps3_instance *instance);
int ps3_irqs_dpc_init(struct ps3_instance *instance);
int ps3_irqs_init(struct ps3_instance *instance);
int ps3_irqs_init_switch(struct ps3_instance *instance);
void ps3_irqs_exit(struct ps3_instance *instance);
#ifndef _WINDOWS
unsigned int ps3_msix_index_get(struct ps3_cmd *cmd, unsigned short pd_count);
void ps3_perf_update(struct ps3_instance *instance, unsigned char iocPerfMode);
#endif
void ps3_irqs_enable(struct ps3_instance *instance);
void ps3_irqs_disable(struct ps3_instance *instance);
#ifndef _WINDOWS
void ps3_irqpolls_enable(struct ps3_instance *instance);
void ps3_irqs_sync(struct ps3_instance *instance);
#endif
#ifndef _WINDOWS
irqreturn_t ps3_irqs_service(int irq_so, void *priv);
#else
unsigned char ps3_irqs_service(void *priv, unsigned long irq_no);
#endif
#ifndef _WINDOWS
int ps3_irqpoll_service(struct irq_poll *irqpoll, int budget);
#endif
static inline unsigned char ps3_irq_busy_add(struct ps3_irq *irq)
{
return ps3_atomic_add_unless(&irq->is_busy, 1, 1);
}
static inline void ps3_irq_busy_dec(struct ps3_irq *irq)
{
ps3_atomic_dec(&irq->is_busy);
}
static inline unsigned char
ps3_irq_is_enable(const struct ps3_irq_context *irq_ctx)
{
return (irq_ctx->is_enable_interrupts == PS3_DRV_TRUE);
}
void ps3_all_reply_fifo_init(struct ps3_instance *instance);
#ifndef _WINDOWS
static inline void ps3_irq_poll_sched(struct irq_poll *iop)
{
#ifdef CONFIG_IRQ_POLL
irq_poll_sched(iop);
#else
(void)iop;
#endif
}
static inline void ps3_irq_poll_init(struct irq_poll *iop, int weight,
irq_poll_fn *func)
{
#ifdef CONFIG_IRQ_POLL
irq_poll_init(iop, weight, func);
#else
(void)iop;
(void)weight;
(void)func;
#endif
}
static inline void ps3_irq_poll_complete(struct irq_poll *iop)
{
#ifdef CONFIG_IRQ_POLL
irq_poll_complete(iop);
#else
(void)iop;
#endif
}
static inline void ps3_irq_poll_enable(struct irq_poll *iop)
{
#ifdef CONFIG_IRQ_POLL
irq_poll_enable(iop);
#else
(void)iop;
#endif
}
static inline void ps3_irq_poll_disable(struct irq_poll *iop)
{
#ifdef CONFIG_IRQ_POLL
irq_poll_disable(iop);
#else
(void)iop;
#endif
}
#endif
#endif

View File

@ -0,0 +1,30 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef _PS3_KERNEL_VERSION_H_
#define _PS3_KERNEL_VERSION_H_
#define DRIVER_SUPPORT_PRIV_BUSY
#define PS3_TRACK_QUEUE_DEPTH
#define PS3_SUPPORT_PCIE_REPORT
#define PS3_SUPPORT_CMD_SCP
#define PS3_SUPPORT_DRIVER_SENSE
#define PS3_SUPPORT_FS
#define PS3_DID_NEXUS_FAILURE
#define PS3_FALLTHROUGH
#define PS3_SYPPORT_BIO_ITER
#define PS3_AER_CLEAR_STATUS
#define PS3_LINUX_SIGNAL
#define DRIVER_SUPPORT_KERNEL_IRQ_AFFINITY
#define PS3_OS_MANAGED_IRQ_SUPPORT
#define PS3_CMD_CDB_CHECK
#include <linux/blk-mq-pci.h>
#ifndef PS3_TAGSET_SUPPORT
#define PS3_TAGSET_SUPPORT
#endif
#define PS3_FSNOTIFY_FILE
#define PS3_KERNEL_WRITE_FILE
#define PS3_BLK_QUEUE_FLAG_CLEAR
#define PS3_STATIC_MINOR
#define PS3_SUPPORT_FLUSH_SCHEDULED
#define PS3_MAP_QUEUES_RET
#endif

View File

@ -0,0 +1,259 @@
// SPDX-License-Identifier: GPL-2.0
#include "ps3_load.h"
#include "ps3_instance_manager.h"
#include "ps3_ioc_manager.h"
#include "ps3_mgr_cmd_err.h"
#include "ps3_mgr_cmd.h"
#include "ps3_cmd_channel.h"
#include "ps3_event.h"
#include "ps3_cmd_statistics.h"
#include "ps3_ioctl.h"
#ifdef _WINDOWS
static int ps3_init_ioc_prepare(struct ps3_instance *instance);
static void ps3_init_ioc_prepare_exit(struct ps3_instance *instance);
static int ps3_init_ioc_complete(struct ps3_instance *instance);
static void ps3_init_ioc_complete_exit(struct ps3_instance *instance);
static int ps3_pci_init_complete(struct ps3_instance *instance);
static void ps3_pci_init_complete_exit(struct ps3_instance *instance);
int ps3_firmware_init(struct ps3_instance *instance)
{
ps3_ioc_adp_init(instance);
if (instance->ioc_adpter->ioc_init_state_to_ready(instance) !=
PS3_SUCCESS) {
goto l_failed;
}
ps3_atomic_set(&instance->state_machine.state,
PS3_INSTANCE_STATE_READY);
if (ps3_pci_init_complete(instance) != PS3_SUCCESS)
goto l_failed;
if (ps3_init_ioc_prepare(instance) != PS3_SUCCESS)
goto l_failed;
if (instance->ioc_adpter->ioc_init_proc(instance) != PS3_SUCCESS)
goto l_failed;
ps3_atomic_set(&instance->state_machine.state,
PS3_INSTANCE_STATE_PRE_OPERATIONAL);
if (ps3_ctrl_info_get(instance) != PS3_SUCCESS)
goto l_failed;
if (ps3_init_ioc_complete(instance) != PS3_SUCCESS)
goto l_failed;
ps3_ioctl_init(instance, PS3_MAX_IOCTL_CMDS);
return PS3_SUCCESS;
l_failed:
DbgPrint("fireware init failed\n");
ps3_firmware_exit(instance);
return -PS3_FAILED;
}
void ps3_firmware_exit(struct ps3_instance *instance)
{
ps3_pci_init_complete_exit(instance);
ps3_init_ioc_complete_exit(instance);
ps3_init_ioc_prepare_exit(instance);
}
void ps3_remove(struct ps3_instance *instance)
{
unsigned long flags = 0;
LOG_INFO("hno:%u %s\n", PS3_HOST(instance), __func__);
instance->state_machine.is_load = PS3_FALSE;
instance->ioc_adpter->irq_disable(instance);
ps3_watchdog_stop(instance);
ps3_recovery_context_exit(instance);
ps3_event_unsubscribe(instance);
ps3_spin_lock_irqsave(&instance->recov ery_context->recovery_lock,
&flags);
ps3_atomic_set(&instance->event_context.abort_eventcmd, 0);
ps3_atomic_set(&instance->dev_context.abort_vdpending_cmd, 0);
ps3_spin_unlock_irqrestore(&instance->recovery_context->recovery_lock,
flags);
ps3_dev_mgr_vd_info_unsubscribe(instance);
#ifndef _WINDOWS
ps3_sas_device_data_exit(instance);
#endif
ps3_device_mgr_data_exit(instance);
#ifndef _WINDOWS
if (ps3_sas_is_support_smp(instance))
sas_remove_host(instance->host);
else
scsi_remove_host(instance->host);
#else
ps3_device_unload_done(instance);
#endif
if (ps3_soc_unload(instance, PS3_FALSE, PS3_UNLOAD_SUB_TYPE_REMOVE,
PS3_SUSPEND_TYPE_NONE) != PS3_SUCCESS) {
LOG_ERROR("hno:%u unload failed.\n", PS3_HOST(instance));
if (ps3_ioc_hard_reset_to_ready(instance) != PS3_SUCCESS) {
LOG_ERROR("hno:%u hard reset failed.\n",
PS3_HOST(instance));
}
}
#ifndef _WINDOWS
ps3_irqs_sync(instance);
ps3_irqpolls_enable(instance);
#endif
ps3_instance_state_transfer_to_quit(instance);
ps3_firmware_exit(instance);
ps3_pci_exit(instance);
#ifndef _WINDOWS
pci_set_drvdata(instance->pdev, NULL);
ps3_instance_put(instance);
scsi_host_put(instance->host);
ps3_dma_dump_mapping(pdev);
#endif
}
static void ps3_cmd_attr_context_init(struct ps3_instance *instance)
{
unsigned int cmd_qdepth = 0;
instance->cmd_attr.cur_can_que =
instance->cmd_context.max_scsi_cmd_count -
instance->cmd_context.max_r1x_cmd_count;
#ifndef _WINDOWS
cmd_qdepth = ps3_throttle_qdepth_query();
if ((cmd_qdepth != 0) && cmd_qdepth <= instance->cmd_attr.cur_can_que) {
instance->cmd_attr.throttle_que_depth = cmd_qdepth;
} else {
instance->cmd_attr.throttle_que_depth =
PS3_DEVICE_QDEPTH_DEFAULT_VALUE;
}
#else
instance->cmd_attr.throttle_que_depth = PS3_DEVICE_QDEPTH_DEFAULT_VALUE;
#endif
instance->cmd_attr.vd_io_threshold = 0;
instance->cmd_attr.is_support_direct_cmd = PS3_FALSE;
}
static int ps3_init_ioc_prepare(struct ps3_instance *instance)
{
ps3_ioc_mgr_req_queue_lock_init(instance);
ps3_err_fault_context_init(instance);
if (!ps3_ioc_fw_version_get(instance))
goto l_fail;
if (!ps3_ioc_state_halt_support_get(instance))
goto l_fail;
if (!ps3_ioc_recovery_support_get(instance))
goto l_fail;
if (ps3_recovery_context_init(instance) != PS3_SUCCESS)
goto l_fail;
if (ps3_ioc_init_cmd_context_init(instance) != PS3_SUCCESS)
goto l_fail;
if (ps3_ctrl_info_buf_alloc(instance) != PS3_SUCCESS)
goto l_fail;
if (ps3_cmd_context_init(instance) != PS3_SUCCESS)
goto l_fail;
ps3_cmd_attr_context_init(instance);
if (ps3_event_context_init(instance) != PS3_SUCCESS)
goto l_fail;
if (ps3_cmd_statistics_init(instance) != PS3_SUCCESS)
goto l_fail;
if (ps3_dump_init(instance) != PS3_SUCCESS)
goto l_fail;
return PS3_SUCCESS;
l_fail:
ps3_init_ioc_prepare_exit(instance);
return -PS3_FAILED;
}
static void ps3_init_ioc_prepare_exit(struct ps3_instance *instance)
{
ps3_ioc_init_cmd_context_exit(instance);
ps3_err_fault_context_exit(instance);
ps3_ctrl_info_buf_free(instance);
ps3_cmd_statistics_exit(instance);
ps3_event_context_exit(instance);
ps3_recovery_context_exit(instance);
ps3_cmd_context_exit(instance);
ps3_dump_dma_buf_free(instance);
ps3_dump_exit(instance);
#ifndef _WINDOWS
(void)ps3_debug_mem_free(instance);
#endif
}
static int ps3_init_ioc_complete(struct ps3_instance *instance)
{
if (ps3_mgr_cmd_init(instance) != PS3_SUCCESS)
goto l_failed;
if (ps3_device_mgr_init(instance) != PS3_SUCCESS)
goto l_failed;
#ifndef _WINDOWS
if (ps3_sas_device_mgr_init(instance) != PS3_SUCCESS)
goto l_failed;
#endif
return PS3_SUCCESS;
l_failed:
ps3_init_ioc_complete_exit(instance);
return -PS3_FAILED;
}
static void ps3_init_ioc_complete_exit(struct ps3_instance *instance)
{
#ifndef _WINDOWS
ps3_sas_device_mgr_exit(instance);
#endif
ps3_device_mgr_exit(instance);
ps3_mgr_cmd_exit(instance);
}
static int ps3_pci_init_complete(struct ps3_instance *instance)
{
if (ps3_irq_context_init(instance) != PS3_SUCCESS)
goto l_failed;
if (instance->ioc_adpter->irq_init) {
if (instance->ioc_adpter->irq_init(instance) != PS3_SUCCESS)
goto l_failed;
} else {
if (ps3_irqs_init(instance) != PS3_SUCCESS)
goto l_failed;
}
return PS3_SUCCESS;
l_failed:
ps3_pci_init_complete_exit(instance);
return -PS3_FAILED;
}
static void ps3_pci_init_complete_exit(struct ps3_instance *instance)
{
ps3_irqs_exit(instance);
ps3_irq_context_exit(instance);
}
#endif

View File

@ -0,0 +1,18 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef _PS3_LOAD_H_
#define _PS3_LOAD_H_
#ifdef _WINDOWS
#include "ps3_def.h"
struct ps3_instance;
int ps3_firmware_init(struct ps3_instance *instance);
void ps3_firmware_exit(struct ps3_instance *instance);
void ps3_remove(struct ps3_instance *instance);
#endif
#endif

View File

@ -0,0 +1,439 @@
// SPDX-License-Identifier: GPL-2.0
#ifdef _WINDOWS
#include "ps3_def.h"
#else
#define WINDOWS_DELAY
#include <linux/types.h>
#include <linux/slab.h>
#include <linux/list.h>
#include <linux/spinlock.h>
#include <linux/delay.h>
#include <linux/kernel.h>
#include "ps3_scsih.h"
#include "ps3_scsih_cmd_parse.h"
#endif
#include "ps3_htp.h"
#include "ps3_mgr_channel.h"
#include "ps3_cmd_complete.h"
#include "ps3_platform_utils.h"
#include "ps3_util.h"
#include "ps3_mgr_cmd_err.h"
#include "ps3_mgr_cmd.h"
#include "ps3_cmd_complete.h"
#include "ps3_ioc_manager.h"
#include "ps3_driver_log.h"
#include "ps3_instance_manager.h"
#include "ps3_cmd_statistics.h"
#include "ps3_kernel_version.h"
#ifndef _WINDOWS
#if defined(PS3_LINUX_SIGNAL)
#include <linux/sched/signal.h>
#else
#include <linux/signal.h>
#endif
#endif
#define CMD_MAX_RETRY_COUNT (10)
#define SEND_IOCTL_CMD_CHECK(instance, cmd) \
((PS3_MGR_CMD_TYPE(cmd) == PS3_CMD_IOCTL) && (instance)->is_support_irq)
static inline unsigned char is_interrupt_signal(struct task_struct *p)
{
if (sigismember(&p->pending.signal, SIGINT) ||
sigismember(&p->pending.signal, SIGKILL) ||
sigismember(&p->pending.signal, SIGQUIT)) {
return PS3_TRUE;
}
return PS3_FALSE;
}
void ps3_wait_cmd_for_completion_interrupt(struct ps3_instance *instance,
struct ps3_cmd *cmd)
{
int ret = PS3_SUCCESS;
unsigned long flags = 0;
unsigned char is_send_cancel = PS3_FALSE;
int cur_state = PS3_INSTANCE_STATE_INIT;
int retry_count = 0;
while (1) {
ret = wait_for_completion_interruptible(&cmd->sync_done);
if (ret == PS3_SUCCESS) {
LOG_DEBUG(
"host_no:%u wait_for_completion_interrupted success\n",
PS3_HOST(instance));
if ((cmd->resp_frame->normalRespFrame.respStatus ==
PS3_DRV_MGR_BUSY) &&
is_send_cancel) {
cmd->resp_frame->normalRespFrame.respStatus =
PS3_MGR_REC_FORCE;
}
break;
}
ps3_spin_lock_irqsave(&cmd->cmd_state.lock, &flags);
ret = signal_pending(current);
if (!ret) {
ps3_spin_unlock_irqrestore(&cmd->cmd_state.lock, flags);
ps3_msleep(100);
continue;
}
ret = is_interrupt_signal(current);
if (ret) {
cur_state =
ps3_atomic_read(&instance->state_machine.state);
if (cur_state == PS3_INSTANCE_STATE_QUIT ||
cur_state == PS3_INSTANCE_STATE_DEAD) {
LOG_INFO_IN_IRQ(
instance, "host_no:%u cur_state:%s\n",
PS3_HOST(instance),
namePS3InstanceState(cur_state));
ps3_spin_unlock_irqrestore(&cmd->cmd_state.lock,
flags);
break;
}
ps3_spin_unlock_irqrestore(&cmd->cmd_state.lock, flags);
LOG_INFO_LIM(
"host_no:%u wait_for_completion_interrupted by SIG INT OR KILL, QUIT\n",
PS3_HOST(instance));
if (is_send_cancel) {
ps3_msleep(100);
continue;
}
is_send_cancel = PS3_TRUE;
cancel:
ret = ps3_mgr_cmd_cancel(instance, cmd->index);
if (ret != PS3_SUCCESS) {
if (ret == -PS3_RECOVERED) {
LOG_INFO_LIM(
"host_no:%u cancel cmd %u send failed, wait\n",
PS3_HOST(instance), cmd->index);
ps3_msleep(100);
continue;
} else if (ret == -PS3_EBUSY) {
ps3_msleep(100);
if (retry_count++ <
CMD_MAX_RETRY_COUNT) {
goto cancel;
}
continue;
}
LOG_INFO(
"host_no:%u cancel cmd %u failed, QUIT, ret:%d\n",
PS3_HOST(instance), cmd->index, ret);
} else {
ps3_spin_lock_irqsave(&cmd->cmd_state.lock,
&flags);
cmd->cmd_state.state = PS3_CMD_STATE_COMPLETE;
ps3_spin_unlock_irqrestore(&cmd->cmd_state.lock,
flags);
}
break;
}
ps3_spin_unlock_irqrestore(&cmd->cmd_state.lock, flags);
ps3_msleep(100);
}
}
static int ps3_mgr_cmd_send(struct ps3_instance *instance, struct ps3_cmd *cmd)
{
int ret = PS3_SUCCESS;
int cur_state = PS3_INSTANCE_STATE_INIT;
if (!instance->state_machine.is_load) {
if (PS3_MGR_CMD_TYPE(cmd) != PS3_CMD_MANAGEMENT) {
LOG_WARN(
"host_no:%u instance state is unloading or suspend\n",
PS3_HOST(instance));
ret = -PS3_FAILED;
goto l_out;
}
}
if (!ps3_is_instance_state_allow_cmd_execute(instance)) {
LOG_WARN("host_no:%u cannot send block cmd\n",
PS3_HOST(instance));
ret = -PS3_RECOVERED;
if (PS3_MGR_CMD_TYPE(cmd) == PS3_CMD_IOCTL) {
cur_state =
ps3_atomic_read(&instance->state_machine.state);
if (cur_state == PS3_INSTANCE_STATE_QUIT ||
cur_state == PS3_INSTANCE_STATE_DEAD) {
LOG_WARN("host_no:%u cur_state:%s\n",
PS3_HOST(instance),
namePS3InstanceState(cur_state));
goto l_out;
}
cmd->resp_frame->normalRespFrame.respStatus =
PS3_DRV_MGR_BUSY;
LOG_WARN(
"host_no:%u ioctl cannot send block cmd:%u,resp:%d, will retry\n",
PS3_HOST(instance), cmd->index,
cmd->resp_frame->normalRespFrame.respStatus);
ret = -PS3_RESP_ERR;
}
goto l_out;
}
if (ps3_pci_err_recovery_get(instance)) {
LOG_WARN(
"host_no:%u cannot send block cmd due to pci recovery\n",
PS3_HOST(instance));
ret = -PS3_FAILED;
goto l_out;
}
PS3_MGR_CMD_STAT_INC(instance, cmd);
LOG_FILE_INFO("host_no:%u CFID:%d trace_id:0x%llx ready send\n",
PS3_HOST(instance), cmd->cmd_word.cmdFrameID,
cmd->trace_id);
LOG_DEBUG("host_no:%u req cmd info:\n"
"\t reqFrameBufBase = 0x%llx, function = %d\n",
PS3_HOST(instance),
cpu_to_le64(instance->cmd_context.req_frame_buf_phys),
ps3_get_pci_function(instance->pdev));
instance->ioc_adpter->cmd_send(instance, &cmd->cmd_word);
l_out:
return ret;
}
static int ps3_blocked_unload_cmd_send(struct ps3_instance *instance,
struct ps3_cmd *cmd)
{
int ret = PS3_SUCCESS;
PS3_MGR_CMD_STAT_INC(instance, cmd);
instance->ioc_adpter->cmd_send(instance, &cmd->cmd_word);
ret = ps3_block_cmd_wait(instance, cmd, 0);
LOG_INFO("host_no:%u CFID:%d trace_id:0x%llx ret:%d\n",
PS3_HOST(instance), cmd->cmd_word.cmdFrameID, cmd->trace_id,
ret);
return ret;
}
static int ps3_blocked_cmd_wake(struct ps3_cmd *cmd)
{
unsigned long flags = 0;
ps3_spin_lock_irqsave(&cmd->cmd_state.lock, &flags);
if (cmd->cmd_state.state == PS3_CMD_STATE_DEAD) {
LOG_WARN_IN_IRQ(
cmd->instance,
"host_no:%u CFID:%d trace_id:0x%llx dead free\n",
PS3_HOST(cmd->instance), cmd->index, cmd->trace_id);
PS3_MGR_CMD_BACK_INC(cmd->instance, cmd, 0);
ps3_mgr_cmd_free_nolock(cmd->instance, cmd);
goto l_out;
}
if (cmd->cmd_state.state == PS3_CMD_STATE_PROCESS) {
cmd->cmd_state.state = PS3_CMD_STATE_COMPLETE;
complete(&cmd->sync_done);
PS3_MGR_CMD_BACK_INC(cmd->instance, cmd, 0);
} else {
LOG_ERROR_IN_IRQ(
cmd->instance,
"host_no:%u CFID:%d trace_id:0x%llx repeat reply\n",
PS3_HOST(cmd->instance), cmd->index, cmd->trace_id);
}
l_out:
ps3_spin_unlock_irqrestore(&cmd->cmd_state.lock, flags);
return PS3_SUCCESS;
}
static int ps3_polled_cmd_send(struct ps3_instance *instance,
struct ps3_cmd *cmd)
{
int ret = PS3_SUCCESS;
if (!instance->state_machine.is_load) {
if (PS3_MGR_CMD_TYPE(cmd) != PS3_CMD_MANAGEMENT) {
LOG_WARN(
"host_no:%u instance state is unloading or suspend\n",
PS3_HOST(instance));
ret = -PS3_FAILED;
goto l_out;
}
}
if (!ps3_is_instance_state_allow_cmd_execute(instance)) {
ret = -PS3_RECOVERED;
goto l_out;
}
if (ps3_pci_err_recovery_get(instance)) {
LOG_WARN(
"host_no:%u cannot send block cmd due to pci recovery\n",
PS3_HOST(instance));
ret = -PS3_FAILED;
goto l_out;
}
PS3_MGR_CMD_STAT_INC(instance, cmd);
instance->ioc_adpter->cmd_send(instance, &cmd->cmd_word);
l_out:
return ret;
}
static int ps3_polled_unload_cmd_send(struct ps3_instance *instance,
struct ps3_cmd *cmd)
{
int ret = -PS3_FAILED;
PS3_MGR_CMD_STAT_INC(instance, cmd);
instance->ioc_adpter->cmd_send(instance, &cmd->cmd_word);
ret = ps3_cmd_reply_polling(instance, cmd, 0, PS3_TRUE);
if (ret != -PS3_TIMEOUT) {
PS3_MGR_CMD_BACK_INC(instance, cmd,
(ret == PS3_SUCCESS) ?
PS3_REPLY_WORD_FLAG_SUCCESS :
PS3_REPLY_WORD_FLAG_FAIL);
}
return ret;
}
static int ps3_blocked_cmd_cb(struct ps3_cmd *cmd, unsigned short reply_flags)
{
if ((cmd->req_frame->mgrReq.reqHead.noReplyWord ==
PS3_CMD_WORD_NEED_REPLY_WORD) &&
(reply_flags == PS3_REPLY_WORD_FLAG_SUCCESS)) {
cmd->resp_frame->normalRespFrame.respStatus = SCSI_STATUS_GOOD;
}
return ps3_blocked_cmd_wake(cmd);
}
int ps3_cmd_send_sync(struct ps3_instance *instance, struct ps3_cmd *cmd)
{
if ((cmd->is_force_polling == 0 &&
ps3_irq_is_enable(&cmd->instance->irq_context)) ||
SEND_IOCTL_CMD_CHECK(instance, cmd)) {
cmd->cmd_receive_cb = ps3_blocked_cmd_cb;
cmd->req_frame->mgrReq.reqHead.noReplyWord =
PS3_CMD_WORD_NEED_REPLY_WORD;
return ps3_mgr_cmd_send(instance, cmd);
}
cmd->cmd_receive_cb = NULL;
cmd->req_frame->mgrReq.reqHead.noReplyWord =
PS3_CMD_WORD_NO_REPLY_WORD;
return ps3_polled_cmd_send(instance, cmd);
}
int ps3_cmd_wait_sync(struct ps3_instance *instance, struct ps3_cmd *cmd)
{
int ret = PS3_SUCCESS;
if (cmd->req_frame->mgrReq.reqHead.noReplyWord ==
PS3_CMD_WORD_NEED_REPLY_WORD) {
ret = ps3_block_cmd_wait(instance, cmd, 0);
} else {
ret = ps3_cmd_reply_polling(instance, cmd, 0, PS3_FALSE);
if (ret != -PS3_TIMEOUT) {
PS3_MGR_CMD_BACK_INC(
instance, cmd,
(ret == PS3_SUCCESS) ?
PS3_REPLY_WORD_FLAG_SUCCESS :
PS3_REPLY_WORD_FLAG_FAIL);
}
}
LOG_FILE_INFO("host_no:%u CFID:%d trace_id:0x%llx recv ret:%d\n",
PS3_HOST(instance), cmd->cmd_word.cmdFrameID,
cmd->trace_id, ret);
return ret;
}
int ps3_unload_cmd_send_sync(struct ps3_instance *instance, struct ps3_cmd *cmd)
{
if (cmd->is_force_polling == 0 &&
ps3_irq_is_enable(&cmd->instance->irq_context)) {
cmd->cmd_receive_cb = ps3_blocked_cmd_cb;
cmd->req_frame->mgrReq.reqHead.noReplyWord =
PS3_CMD_WORD_NEED_REPLY_WORD;
return ps3_blocked_unload_cmd_send(instance, cmd);
}
cmd->cmd_receive_cb = NULL;
cmd->req_frame->mgrReq.reqHead.noReplyWord = PS3_CMD_WORD_NO_REPLY_WORD;
return ps3_polled_unload_cmd_send(instance, cmd);
}
int ps3_cmd_no_block_send(struct ps3_instance *instance, struct ps3_cmd *cmd)
{
int ret = PS3_SUCCESS;
cmd->cmd_receive_cb = ps3_blocked_cmd_cb;
cmd->req_frame->mgrReq.reqHead.noReplyWord =
PS3_CMD_WORD_NEED_REPLY_WORD;
if (!ps3_is_instance_state_allow_cmd_execute(instance)) {
ret = -PS3_FAILED;
goto l_out;
}
PS3_MGR_CMD_STAT_INC(instance, cmd);
instance->ioc_adpter->cmd_send(instance, &cmd->cmd_word);
l_out:
return ret;
}
int ps3_block_cmd_wait(struct ps3_instance *instance, struct ps3_cmd *cmd,
unsigned long timeout)
{
int ret = PS3_SUCCESS;
if (cmd->is_interrupt) {
#ifdef WINDOWS_DELAY
ps3_wait_cmd_for_completion_interrupt(instance, cmd);
#endif
} else {
ret = ps3_wait_cmd_for_completion_timeout(instance, cmd,
timeout);
if (ret == -PS3_TIMEOUT) {
LOG_ERROR(
"host_no:%u CFID:%d trace_id:0x%llx time out\n",
PS3_HOST(instance), cmd->cmd_word.cmdFrameID,
cmd->trace_id);
goto l_out;
}
}
if (cmd->cmd_state.state != PS3_CMD_STATE_COMPLETE) {
LOG_INFO(
"host_no:%u CFID:%d trace_id:0x%llx not complete,state:%u\n",
PS3_HOST(instance), cmd->cmd_word.cmdFrameID,
cmd->trace_id, cmd->cmd_state.state);
ret = -PS3_TIMEOUT;
goto l_out;
}
if (ps3_cmd_resp_status(cmd) != SCSI_STATUS_GOOD) {
ret = -PS3_RESP_ERR;
LOG_INFO("host_no:%u CFID:%d trace_id:0x%llx resp err:0x%x\n",
PS3_HOST(instance), cmd->cmd_word.cmdFrameID,
cmd->trace_id, ps3_cmd_resp_status(cmd));
}
l_out:
return ret;
}
int ps3_cmd_send_async(struct ps3_instance *instance, struct ps3_cmd *cmd,
int (*cmd_receive_cb)(struct ps3_cmd *, unsigned short))
{
cmd->cmd_receive_cb = cmd_receive_cb;
PS3_MGR_CMD_STAT_INC(instance, cmd);
return ps3_async_cmd_send(instance, cmd);
}

View File

@ -0,0 +1,33 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef _PS3_MGR_CHANNEL_H_
#define _PS3_MGR_CHANNEL_H_
#include "ps3_cmd_channel.h"
int ps3_cmd_send_sync(struct ps3_instance *instance, struct ps3_cmd *cmd);
int ps3_unload_cmd_send_sync(struct ps3_instance *instance,
struct ps3_cmd *cmd);
int ps3_block_cmd_wait(struct ps3_instance *instance, struct ps3_cmd *cmd,
unsigned long timeout);
int ps3_cmd_send_async(struct ps3_instance *instance, struct ps3_cmd *cmd,
int (*cmd_receive_cb)(struct ps3_cmd *, unsigned short));
int ps3_cmd_wait_sync(struct ps3_instance *instance, struct ps3_cmd *cmd);
int ps3_cmd_no_block_send(struct ps3_instance *instance, struct ps3_cmd *cmd);
#ifndef _WINDOWS
void ps3_wait_cmd_for_completion_interrupt(struct ps3_instance *instance,
struct ps3_cmd *cmd);
#endif
static inline union PS3RespFrame *ps3_cmd_resp_frame_get(struct ps3_cmd *cmd)
{
return cmd->resp_frame;
}
static inline unsigned int ps3_cmd_resp_status(struct ps3_cmd *cmd)
{
return le32_to_cpu(cmd->resp_frame->normalRespFrame.respStatus);
};
#endif

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,95 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef _PS3_MANAGEMENT_CMD_H_
#define _PS3_MANAGEMENT_CMD_H_
#include "ps3_instance_manager.h"
#include "ps3_device_manager.h"
#define PS3_MGR_BASE_DATA_SIZE (64)
#define PS3_MGR_CMD_SGL_OFFSET_DWORD_SHIFT (2)
#define PS3_MGR_CMD_TYPE(cmd) ((cmd)->req_frame->mgrReq.reqHead.cmdType)
#define PS3_MGR_CMD_SUBTYPE(cmd) ((cmd)->req_frame->mgrReq.reqHead.cmdSubType)
enum {
PS3_CANCEL_EVENT_CMD = 1,
PS3_CANCEL_VDPENDING_CMD,
PS3_CANCEL_WEB_CMD,
};
int ps3_ctrl_info_buf_alloc(struct ps3_instance *instance);
void ps3_ctrl_info_buf_free(struct ps3_instance *instance);
int ps3_mgr_cmd_init(struct ps3_instance *instance);
void ps3_mgr_cmd_exit(struct ps3_instance *instance);
int ps3_pd_list_get(struct ps3_instance *instance);
int ps3_vd_list_get(struct ps3_instance *instance);
int ps3_pd_info_get(struct ps3_instance *instance, unsigned short channel,
unsigned short target_id, unsigned short pd_disk_id);
int ps3_vd_info_sync_get(struct ps3_instance *instance, unsigned int disk_id,
unsigned short vd_num);
int ps3_vd_info_async_get(struct ps3_instance *instance);
int ps3_ctrl_info_get(struct ps3_instance *instance);
int ps3_soc_unload(struct ps3_instance *instance, unsigned char is_polling,
unsigned char type, unsigned char suspend_type);
int ps3_scsi_remove_device_done(struct ps3_instance *instance,
struct PS3DiskDevPos *disk_pos,
unsigned char dev_type);
int ps3_scsi_add_device_ack(struct ps3_instance *instance,
struct PS3DiskDevPos *disk_pos,
unsigned char dev_type);
int ps3_mgr_cmd_cancel(struct ps3_instance *instance,
unsigned short cancel_cmd_frame_id);
int ps3_event_register(struct ps3_instance *instance,
struct PS3MgrEvent *event);
int ps3_web_register(struct ps3_instance *instance);
int ps3_scsi_task_mgr_abort(struct ps3_instance *instance,
struct ps3_scsi_priv_data *priv_data,
unsigned short aborted_cmd_frame_id,
struct scsi_cmnd *scmd);
void ps3_mgr_cmd_word_build(struct ps3_cmd *cmd);
int ps3_sas_expander_all_get(struct ps3_instance *instance);
int ps3_sas_phy_get(struct ps3_instance *instance, struct PS3SasMgr *sas_req);
int ps3_sas_expander_get(struct ps3_instance *instance,
struct PS3SasMgr *sas_req);
int ps3_mgr_complete_proc(struct ps3_instance *instance, struct ps3_cmd *cmd,
int send_result);
struct ps3_cmd *ps3_dump_notify_cmd_build(struct ps3_instance *instance);
struct ps3_cmd *
ps3_scsi_task_mgr_reset_build(struct ps3_instance *instance,
struct ps3_scsi_priv_data *priv_data);
int ps3_mgr_cmd_no_resp_proc(struct ps3_instance *instance,
struct ps3_cmd *cmd);
unsigned char
ps3_check_ioc_state_is_normal_in_unload(struct ps3_instance *instance);
int ps3_mgr_cmd_cancel_send(struct ps3_instance *instance,
unsigned short cancel_cmd_frame_id,
unsigned char type);
int ps3_mgr_cmd_cancel_wait(struct ps3_instance *instance, unsigned char type);
#endif

View File

@ -0,0 +1,268 @@
// SPDX-License-Identifier: GPL-2.0
#include "ps3_mgr_cmd_err.h"
#ifndef _WINDOWS
#include <linux/kernel.h>
#include <linux/pci.h>
#include <linux/spinlock.h>
#include <linux/mutex.h>
#include <linux/delay.h>
#include <scsi/scsi.h>
#endif
#include "ps3_htp.h"
#include "ps3_mgr_channel.h"
#include "ps3_mgr_cmd.h"
#include "ps3_driver_log.h"
#include "ps3_recovery.h"
enum ps3_fault_action {
PS3_FAULT_STRATEGY_NONE = 0,
PS3_FAULT_STRATEGY_RETRY,
};
enum ps3_reset_type {
PS3_RESET_TYPE_SOFT,
PS3_RESET_TYPE_HARD,
};
struct ps3_fault_strategy {
unsigned int resp_status;
enum ps3_fault_action fault_action;
};
static struct ps3_fault_strategy ps3_fault_strategy_desc[] = {
{ PS3_DRV_MGR_UNRUNING, PS3_FAULT_STRATEGY_NONE },
{ PS3_DRV_MGR_INVAL_CMD, PS3_FAULT_STRATEGY_NONE },
{ PS3_DRV_MGR_NORESOURCE, PS3_FAULT_STRATEGY_RETRY },
{ PS3_DRV_MGR_INVAL_PARAM, PS3_FAULT_STRATEGY_NONE },
{ PS3_DRV_MGR_DEV_NOEXIST, PS3_FAULT_STRATEGY_NONE },
{ PS3_DRV_MGR_DEV_DATA_ERR, PS3_FAULT_STRATEGY_NONE },
{ PS3_DRV_MGR_EVT_REPEAT, PS3_FAULT_STRATEGY_NONE },
{ PS3_DRV_MGR_EVT_CANCEL_ERR, PS3_FAULT_STRATEGY_NONE },
{ PS3_DRV_MGR_FLUSH_FAILED, PS3_FAULT_STRATEGY_RETRY },
{ PS3_DRV_MGR_BUSY, PS3_FAULT_STRATEGY_RETRY },
{ PS3_DRV_MGR_TIMEOUT, PS3_FAULT_STRATEGY_RETRY },
{ PS3_DRV_MGR_SMP_BACKEND_ERR, PS3_FAULT_STRATEGY_NONE },
{ PS3_DRV_MGR_LINK_GET_BACKEND_ERR, PS3_FAULT_STRATEGY_NONE },
{ PS3_DRV_MGR_PHY_CTL_BACKEND_ERR, PS3_FAULT_STRATEGY_NONE },
{ PS3_DRV_MGR_RESTART_COMMAND_RSP, PS3_FAULT_STRATEGY_NONE },
{ PS3_DRV_MGR_TM_FAILED, PS3_FAULT_STRATEGY_NONE },
{ U32_MAX, PS3_FAULT_STRATEGY_NONE }
};
static inline const char *ps3_err_action_print(enum ps3_fault_action action)
{
static const char * const action_string[] = {
[PS3_FAULT_STRATEGY_NONE] = "PS3_FAULT_STRATEGY_NONE",
[PS3_FAULT_STRATEGY_RETRY] = "PS3_FAULT_STRATEGY_RETRY"
};
return action_string[action];
}
const char *ps3_err_mgr_fault_proc_result_print(int result)
{
const char *proc_result_string = NULL;
switch (result) {
case PS3_SUCCESS:
proc_result_string = "SUCCESS";
break;
case -PS3_RETRY:
proc_result_string = "NEED RETRY";
break;
case -PS3_FAILED:
proc_result_string = "FAILED";
break;
case -PS3_TIMEOUT:
proc_result_string = "TIMEOUT";
break;
case -PS3_RESP_ERR:
proc_result_string = "RESPONSE ERROR";
break;
case -PS3_RESP_INT:
proc_result_string = "RESPONSE INTERRUPTED";
break;
case -PS3_CMD_NO_RESP:
proc_result_string = "PS3_CMD_NO_RESP";
break;
default:
proc_result_string = "INVALID RESULT";
break;
}
return proc_result_string;
}
static enum ps3_fault_action
ps3_err_fault_strategy_lookup(struct ps3_instance *instance,
unsigned int resp_status, unsigned int retry_cnt)
{
unsigned int idx = 0;
enum ps3_fault_action fault_action = PS3_FAULT_STRATEGY_RETRY;
for (idx = 0; idx < ARRAY_SIZE(ps3_fault_strategy_desc); idx++) {
if (ps3_fault_strategy_desc[idx].resp_status == resp_status) {
fault_action =
ps3_fault_strategy_desc[idx].fault_action;
break;
}
}
if ((fault_action == PS3_FAULT_STRATEGY_RETRY) && (retry_cnt > 0))
fault_action = PS3_FAULT_STRATEGY_NONE;
LOG_INFO("host_no:%u error_no:%d fault_action is %s!\n",
PS3_HOST(instance), resp_status,
ps3_err_action_print(fault_action));
return fault_action;
}
static int ps3_err_fault_strategy_exec(struct ps3_instance *instance,
enum ps3_fault_action fault_action)
{
int proc_result = -PS3_FAILED;
switch (fault_action) {
case PS3_FAULT_STRATEGY_RETRY:
ps3_msleep(PS3_ERR_MGR_CMD_DELAY_TIME_BEFORE_RERTY);
proc_result = -PS3_RETRY;
break;
default:
break;
}
LOG_INFO("host_no:%u proc result for mgr cmd fault is %s!\n",
PS3_HOST(instance),
ps3_err_mgr_fault_proc_result_print(proc_result));
return proc_result;
}
int ps3_err_mgr_cmd_failed_check(struct ps3_instance *instance,
struct ps3_cmd *cmd)
{
int ret = PS3_SUCCESS;
enum ps3_fault_action fault_action = PS3_FAULT_STRATEGY_NONE;
unsigned int resp_status = cmd->resp_frame->normalRespFrame.respStatus;
if (!ps3_is_instance_state_allow_cmd_execute(instance)) {
ret = -PS3_FAILED;
goto l_out;
}
fault_action = ps3_err_fault_strategy_lookup(instance, resp_status,
cmd->retry_cnt);
ret = ps3_err_fault_strategy_exec(instance, fault_action);
l_out:
return ret;
}
void ps3_err_fault_context_init(struct ps3_instance *instance)
{
struct ps3_fault_context *fault_context = &instance->fault_context;
memset(fault_context, 0, sizeof(*fault_context));
ps3_atomic_set(&instance->is_err_scsi_processing, 0);
}
void ps3_err_fault_context_exit(struct ps3_instance *instance)
{
struct ps3_fault_context *fault_context = &instance->fault_context;
memset(fault_context, 0, sizeof(*fault_context));
}
int ps3_err_mgr_cmd_proc(struct ps3_instance *instance, int fault_type,
struct ps3_cmd *cmd)
{
int proc_result = PS3_SUCCESS;
int cur_state = PS3_INSTANCE_STATE_INIT;
LOG_INFO("host_no:%u fault_type: %s, retries:%d!\n", PS3_HOST(instance),
ps3_err_mgr_fault_proc_result_print(fault_type),
cmd->retry_cnt);
switch (fault_type) {
case PS3_SUCCESS:
break;
case -PS3_RESP_ERR:
if (PS3_MGR_CMD_TYPE(cmd) == PS3_CMD_IOCTL) {
LOG_INFO(
"host_no:%u CFID:%d trace_id:0x%llx cli return err:%u\n",
PS3_HOST(instance), cmd->cmd_word.cmdFrameID,
cmd->trace_id, ps3_cmd_resp_status(cmd));
if (instance->is_probe_finish) {
if (ps3_cmd_resp_status(cmd) ==
PS3_DRV_MGR_BUSY) {
LOG_INFO(
"host_no:%u CFID:%d trace_id:0x%llx cli return busy\n",
PS3_HOST(instance),
cmd->cmd_word.cmdFrameID,
cmd->trace_id);
if (ps3_instance_wait_for_normal(
instance) == PS3_SUCCESS) {
cmd->req_frame->mgrReq.value
.isRetry = PS3_TRUE;
proc_result = -PS3_RETRY;
} else {
proc_result = -PS3_FAILED;
}
} else if (ps3_cmd_resp_status(cmd) ==
PS3_DRV_MGR_RESTART_COMMAND_RSP) {
LOG_WARN(
"host_no:%u CFID:%d trace_id:0x%llx cli cx restart return success\n",
PS3_HOST(instance),
cmd->cmd_word.cmdFrameID,
cmd->trace_id);
ps3_need_wait_hard_reset_request(
instance);
if (ps3_recovery_state_wait_for_normal(
instance) != PS3_SUCCESS) {
proc_result = -PS3_FAILED;
} else if (ps3_hard_recovery_request_with_retry(instance)
!= PS3_SUCCESS) {
LOG_WARN(
"host_no:%u hard recovery request NOK\n",
PS3_HOST(instance));
}
} else {
cur_state = ps3_atomic_read(
&instance->state_machine.state);
if (cur_state ==
PS3_INSTANCE_STATE_QUIT ||
cur_state ==
PS3_INSTANCE_STATE_DEAD) {
proc_result = -PS3_ENODEV;
} else {
proc_result = -PS3_FAILED;
}
}
} else {
proc_result = -PS3_FAILED;
}
} else {
proc_result =
ps3_err_mgr_cmd_failed_check(instance, cmd);
}
break;
case -PS3_TIMEOUT:
proc_result = -PS3_CMD_NO_RESP;
break;
default:
proc_result = -PS3_FAILED;
break;
}
if (proc_result != -PS3_CMD_NO_RESP)
cmd->cmd_state.reset_flag = 0;
LOG_INFO("host_no:%u proc_result: %s, retries:%d!\n",
PS3_HOST(instance),
ps3_err_mgr_fault_proc_result_print(proc_result),
cmd->retry_cnt);
return proc_result;
}

View File

@ -0,0 +1,28 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef _PS3_MGR_CMD_ERR_H_
#define _PS3_MGR_CMD_ERR_H_
#ifndef _WINDOWS
#include <linux/mutex.h>
#include <linux/atomic.h>
#include "linux/kernel.h"
#endif
#include "ps3_htp_def.h"
#include "ps3_instance_manager.h"
#define PS3_ERR_MGR_CMD_FAULT_RETRY_MAX (3)
#define PS3_ERR_MGR_CMD_DELAY_TIME_BEFORE_RERTY (500)
void ps3_err_fault_context_init(struct ps3_instance *instance);
void ps3_err_fault_context_exit(struct ps3_instance *instance);
int ps3_err_mgr_cmd_proc(struct ps3_instance *instance, int fault_type,
struct ps3_cmd *cmd);
int ps3_err_mgr_cmd_failed_check(struct ps3_instance *instance,
struct ps3_cmd *cmd);
const char *ps3_err_mgr_fault_proc_result_print(int result);
#endif

View File

@ -0,0 +1,629 @@
// SPDX-License-Identifier: GPL-2.0
#ifndef _WINDOWS
#include "linux/moduleparam.h"
#endif
#include "ps3_inner_data.h"
#include "ps3_module_para.h"
#include "ps3_driver_log.h"
#include "ps3_drv_ver.h"
#include "ps3_ioc_state.h"
#include "ps3_kernel_version.h"
#ifndef _WINDOWS
static unsigned int cli_ver = PS3_IOCTL_VERSION;
module_param(cli_ver, uint, 0444);
MODULE_PARM_DESC(cli_ver,
"The version for communication between driver and CLI");
#endif
static unsigned int g_throttle_que_depth = PS3_DEVICE_QDEPTH_DEFAULT_VALUE;
#ifndef _WINDOWS
module_param(g_throttle_que_depth, uint, 0644);
MODULE_PARM_DESC(
g_throttle_que_depth,
"IOC queue depth when throttled due to SCSI cmd timeout. Default: 16");
#endif
static unsigned int g_debug_mem_size;
#ifndef _WINDOWS
#if defined(PS3_SUPPORT_DEBUG) || \
(defined(PS3_CFG_RELEASE) && defined(PS3_CFG_OCM_DBGBUG)) || \
(defined(PS3_CFG_RELEASE) && defined(PS3_CFG_OCM_RELEASE))
module_param(g_debug_mem_size, uint, 0644);
MODULE_PARM_DESC(
g_debug_mem_size,
"Allocate DMA memory for IOC debugging little than 65535KB. Default: 0KB");
#endif
#endif
static unsigned int g_use_clustering = 1;
#ifndef _WINDOWS
module_param(g_use_clustering, uint, 0644);
MODULE_PARM_DESC(
g_use_clustering,
"SCSI mid-layer bio merge feature enable/disable. Default: enable(1)");
#endif
static unsigned int g_scsi_cmd_timeout;
#ifndef _WINDOWS
module_param(g_scsi_cmd_timeout, uint, 0644);
MODULE_PARM_DESC(
g_scsi_cmd_timeout,
"SCSI cmd timeout (10-255s). Default: 0(No specify default 90s)");
#endif
extern unsigned int g_ps3_r1x_lock_flag;
extern unsigned int g_ps3_r1x_lock_enable;
#ifndef _WINDOWS
module_param(g_ps3_r1x_lock_enable, uint, 0644);
MODULE_PARM_DESC(
g_ps3_r1x_lock_enable,
"R1x write conflict check feature enable/disable. Default: enable(1)");
#endif
#if defined(PS3_SUPPORT_DEBUG) || \
(defined(PS3_CFG_RELEASE) && defined(PS3_CFG_OCM_DBGBUG)) || \
(defined(PS3_CFG_RELEASE) && defined(PS3_CFG_OCM_RELEASE))
extern unsigned int g_ps3_qos_hdd_pd_quota;
extern unsigned int g_ps3_qos_nvme_pd_quota;
#ifndef _WINDOWS
module_param(g_ps3_qos_hdd_pd_quota, uint, 0644);
MODULE_PARM_DESC(g_ps3_qos_hdd_pd_quota, "Qos pd quota. Default: 40");
module_param(g_ps3_qos_nvme_pd_quota, uint, 0644);
MODULE_PARM_DESC(g_ps3_qos_nvme_pd_quota, "Qos nvme pd quota. Default: 127");
#endif
extern unsigned int g_ps3_r1x_rb_diff_cmds;
#ifndef _WINDOWS
module_param(g_ps3_r1x_rb_diff_cmds, uint, 0644);
MODULE_PARM_DESC(g_ps3_r1x_rb_diff_cmds,
"R1x read balancing outstanding threshold. Default: 4");
#endif
#endif
static unsigned int g_direct_to_normal_enable = 1;
#ifndef _WINDOWS
module_param(g_direct_to_normal_enable, uint, 0644);
MODULE_PARM_DESC(g_direct_to_normal_enable,
"Direct to normal feature enable/disable. Default: enable(1)");
#endif
static unsigned int g_hba_check_time = 10;
#ifndef _WINDOWS
#if defined(PS3_SUPPORT_DEBUG) || \
(defined(PS3_CFG_RELEASE) && defined(PS3_CFG_OCM_DBGBUG)) || \
(defined(PS3_CFG_RELEASE) && defined(PS3_CFG_OCM_RELEASE))
module_param(g_hba_check_time, uint, 0644);
MODULE_PARM_DESC(g_hba_check_time,
"HBA device id check time out. Default: 10s");
#endif
#endif
static unsigned int g_task_reset_delay_time = 50;
#ifndef _WINDOWS
#if defined(PS3_SUPPORT_DEBUG) || \
(defined(PS3_CFG_RELEASE) && defined(PS3_CFG_OCM_DBGBUG)) || \
(defined(PS3_CFG_RELEASE) && defined(PS3_CFG_OCM_RELEASE))
module_param(g_task_reset_delay_time, uint, 0644);
MODULE_PARM_DESC(g_task_reset_delay_time,
"Task reset delay time (0-1000ms). Default: 50ms");
#endif
#endif
static unsigned int g_r1x_ring_size = 16;
#ifndef _WINDOWS
#if defined(PS3_SUPPORT_DEBUG) || \
(defined(PS3_CFG_RELEASE) && defined(PS3_CFG_OCM_DBGBUG)) || \
(defined(PS3_CFG_RELEASE) && defined(PS3_CFG_OCM_RELEASE))
module_param(g_r1x_ring_size, uint, 0644);
MODULE_PARM_DESC(
g_r1x_ring_size,
"If R1X direct read more than g_r1x_ring_size, read from spare. Default: 16MB");
#endif
#endif
static unsigned int g_direct_check_stream_enable = PS3_TRUE;
#ifndef _WINDOWS
module_param(g_direct_check_stream_enable, uint, 0644);
MODULE_PARM_DESC(
g_direct_check_stream_enable,
"Direct detect stream or not feature enable/disable. Default: enable(1)");
#endif
static int g_device_busy_threshold = PS3_DEVICE_IO_BUSY_THRESHOLD;
#ifndef _WINDOWS
module_param(g_device_busy_threshold, int, 0644);
MODULE_PARM_DESC(g_device_busy_threshold,
"Device busy threshold value. Default: 8");
#endif
#ifndef __cplusplus
static char g_log_path[80] = { 0 };
#ifndef _WINDOWS
module_param_string(g_log_path, g_log_path, 80, 0644);
MODULE_PARM_DESC(
g_log_path,
"The log path of host driver will be saved little than 80 chars. Default: /var/log");
#endif
#endif
static unsigned int g_log_file_size = 200;
#ifdef PS3_CFG_RELEASE
static unsigned int g_log_level = LEVEL_INFO;
#else
static unsigned int g_log_level = LEVEL_DEBUG;
#endif
#if defined(PS3_SUPPORT_DEBUG) || \
(defined(PS3_CFG_RELEASE) && defined(PS3_CFG_OCM_DBGBUG)) || \
(defined(PS3_CFG_RELEASE) && defined(PS3_CFG_OCM_RELEASE))
#ifndef _WINDOWS
module_param(g_log_file_size, uint, 0644);
MODULE_PARM_DESC(g_log_file_size,
"Single driver log file size (10-200MB). Default: 200MB");
module_param(g_log_level, uint, 0644);
MODULE_PARM_DESC(g_log_level,
"Specify driver log level."
#ifdef PS3_CFG_RELEASE
"0 - error, 1 - warn, 2 - info, 3 - debug. Default: 2");
#else
"0 - error, 1 - warn, 2 - info, 3 - debug. Default: 3");
#endif
#endif
#endif
static unsigned int g_r1x_time_out = 3000;
#ifndef _WINDOWS
#if defined(PS3_SUPPORT_DEBUG) || \
(defined(PS3_CFG_RELEASE) && defined(PS3_CFG_OCM_DBGBUG)) || \
(defined(PS3_CFG_RELEASE) && defined(PS3_CFG_OCM_RELEASE))
module_param(g_r1x_time_out, uint, 0644);
MODULE_PARM_DESC(g_r1x_time_out,
"R1X conflict in queue after time. Default: 3000ms");
#endif
#endif
static unsigned int g_r1x_conflict_queue_enable = PS3_TRUE;
#ifndef _WINDOWS
#if defined(PS3_SUPPORT_DEBUG) || \
(defined(PS3_CFG_RELEASE) && defined(PS3_CFG_OCM_DBGBUG)) || \
(defined(PS3_CFG_RELEASE) && defined(PS3_CFG_OCM_RELEASE))
module_param(g_r1x_conflict_queue_enable, uint, 0644);
MODULE_PARM_DESC(
g_r1x_conflict_queue_enable,
"R1X conflict queue function feature enable/disable. Default: enable(1)");
#endif
#endif
#ifndef _WINDOWS
#endif
static unsigned int g_log_space_size;
static unsigned int g_log_tty;
#ifndef _WINDOWS
#if defined(PS3_SUPPORT_DEBUG) || \
(defined(PS3_CFG_RELEASE) && defined(PS3_CFG_OCM_DBGBUG)) || \
(defined(PS3_CFG_RELEASE) && defined(PS3_CFG_OCM_RELEASE))
module_param(g_log_tty, uint, 0644);
MODULE_PARM_DESC(
g_log_tty,
"Allow driver log output to tty console feature enable/disable. Default: disable(0)");
#endif
#endif
#if defined PS3_HARDWARE_ASIC
static unsigned int g_hard_reset_enable = 1;
static unsigned int g_deep_soft_reset_enable;
#elif (((defined PS3_HARDWARE_FPGA || defined PS3_HARDWARE_ASIC) && \
defined PS3_MODEL_V200) || \
defined(PS3_HARDWARE_HAPS_V200))
static unsigned int g_hard_reset_enable = 1;
static unsigned int g_deep_soft_reset_enable;
#else
static unsigned int g_hard_reset_enable;
static unsigned int g_deep_soft_reset_enable;
#endif
#ifndef _WINDOWS
#if defined(PS3_SUPPORT_DEBUG) || \
(defined(PS3_CFG_RELEASE) && defined(PS3_CFG_OCM_DBGBUG)) || \
(defined(PS3_CFG_RELEASE) && defined(PS3_CFG_OCM_RELEASE))
module_param(g_hard_reset_enable, uint, 0644);
MODULE_PARM_DESC(g_hard_reset_enable,
"Hard reset feature enable/disable. Default: enable(1)");
module_param(g_deep_soft_reset_enable, uint, 0644);
MODULE_PARM_DESC(g_deep_soft_reset_enable,
"Deep soft reset feature enable/disable. Default: disable(0)");
#endif
#endif
static unsigned int g_aer_handle_support = 1;
#ifndef _WINDOWS
module_param(g_aer_handle_support, uint, 0644);
MODULE_PARM_DESC(
g_aer_handle_support,
"Driver aer handle support feature enable/disable. Default: enable(1)");
#endif
#ifndef __cplusplus
static char g_version_verbose[512] = { 0 };
#ifndef _WINDOWS
module_param_string(g_version_verbose, g_version_verbose, 511, 0444);
MODULE_PARM_DESC(g_version_verbose,
"Display detailed version information about ps3stor driver");
#endif
#endif
static unsigned int g_hard_reset_waiting;
static unsigned int g_use_hard_reset_reg = 1;
static unsigned int g_use_hard_reset_max_retry = PS3_HARD_RESET_MAX_RETRY;
#ifndef _WINDOWS
#if defined(PS3_SUPPORT_DEBUG) || \
(defined(PS3_CFG_RELEASE) && defined(PS3_CFG_OCM_DBGBUG)) || \
(defined(PS3_CFG_RELEASE) && defined(PS3_CFG_OCM_RELEASE))
module_param(g_hard_reset_waiting, uint, 0644);
MODULE_PARM_DESC(g_hard_reset_waiting,
"Allow to access PCIe Config/BAR after xxx ms. Default: 0");
module_param(g_use_hard_reset_reg, uint, 0644);
MODULE_PARM_DESC(
g_use_hard_reset_reg,
"Write hard reset reg triggered feature enable/disable. Default: enable(1)");
module_param(g_use_hard_reset_max_retry, uint, 0644);
MODULE_PARM_DESC(g_use_hard_reset_max_retry,
"Hard reset retry max count. Default: 2");
#endif
#endif
#if ((defined PS3_HARDWARE_FPGA && defined PS3_MODEL_V200) || \
defined(PS3_HARDWARE_HAPS_V200) || defined(PS3_HARDWARE_ASIC))
static unsigned int g_enable_heartbeat = 1;
module_param(g_enable_heartbeat, uint, 0644);
MODULE_PARM_DESC(g_enable_heartbeat,
"Heartbeat query feature enable/disable. Default: enable(1)");
#else
static unsigned int g_enable_heartbeat;
module_param(g_enable_heartbeat, uint, 0644);
MODULE_PARM_DESC(g_enable_heartbeat,
"Heartbeat query feature enable/disable. Default: disable(0)");
#endif
static unsigned int g_hil_mode = 0xFFFF;
#ifndef _WINDOWS
#if defined(PS3_SUPPORT_DEBUG) || \
(defined(PS3_CFG_RELEASE) && defined(PS3_CFG_OCM_DBGBUG)) || \
(defined(PS3_CFG_RELEASE) && defined(PS3_CFG_OCM_RELEASE))
module_param(g_hil_mode, uint, 0644);
MODULE_PARM_DESC(
g_hil_mode,
"Set HIL operational mode.\n"
"\t0 - SW mode, 1 - HW mode, 2 - Enhanced HW mode, 3 - SW assist mode. Default: 65535(0xFFFF)");
#endif
#endif
static unsigned int g_available_func_id = 0xFF;
#ifndef _WINDOWS
#if defined(PS3_SUPPORT_DEBUG) || \
(defined(PS3_CFG_RELEASE) && defined(PS3_CFG_OCM_DBGBUG)) || \
(defined(PS3_CFG_RELEASE) && defined(PS3_CFG_OCM_RELEASE))
module_param(g_available_func_id, uint, 0644);
MODULE_PARM_DESC(g_available_func_id,
"Set function id.\n"
"\t0 - Func0, 1 - Func1, 2 - Unlimited. Default: 255(0xFF)");
#endif
#endif
static unsigned int g_pci_irq_mode = PS3_PCI_IRQ_MODE_NONE_SPE;
#ifndef _WINDOWS
#if defined(PS3_SUPPORT_DEBUG) || \
(defined(PS3_CFG_RELEASE) && defined(PS3_CFG_OCM_DBGBUG)) || \
(defined(PS3_CFG_RELEASE) && defined(PS3_CFG_OCM_RELEASE))
module_param(g_pci_irq_mode, uint, 0644);
MODULE_PARM_DESC(g_pci_irq_mode,
"Specify pci irq mode.\n"
"\t0 - none specify, 1 - legacy, 2 - msi, 3 - msix. Default: 0");
#endif
#endif
#if defined(PS3_TAGSET_SUPPORT)
#if defined(PS3_SUPPORT_TAGSET)
static int g_ps3_tagset_enable = 1;
module_param(g_ps3_tagset_enable, int, 0444);
MODULE_PARM_DESC(g_ps3_tagset_enable,
"Shared host tagset enable/disable. Default: enable(1)");
#else
static int g_ps3_tagset_enable;
module_param(g_ps3_tagset_enable, int, 0444);
MODULE_PARM_DESC(g_ps3_tagset_enable,
"Shared host tagset enable/disable. Default: disable(0)");
#endif
#endif
static unsigned int g_smp_affinity_enable = 1;
module_param(g_smp_affinity_enable, int, 0444);
MODULE_PARM_DESC(g_smp_affinity_enable,
"SMP affinity feature enable/disable. Default: enable(1)");
void ps3_version_verbose_fill(void)
{
#ifndef __cplusplus
int len = 0;
int total_len = sizeof(g_version_verbose) - 1;
memset(g_version_verbose, 0, sizeof(g_version_verbose));
len += snprintf(g_version_verbose + len, total_len - len, "%-20s:%s\n",
"version", PS3_DRV_VERSION);
len += snprintf(g_version_verbose + len, total_len - len, "%-20s:%s\n",
"commit_id", PS3_DRV_COMMIT_ID);
len += snprintf(g_version_verbose + len, total_len - len, "%-20s:%s\n",
"toolchain_id", PS3_DRV_TOOLCHAIN_ID);
len += snprintf(g_version_verbose + len, total_len - len, "%-20s:%s\n",
"build_time", PS3_DRV_BUILD_TIME);
len += snprintf(g_version_verbose + len, total_len - len, "%-20s:%s\n",
"product_support", PS3_DRV_PRODUCT_SUPPORT);
#endif
}
unsigned int ps3_throttle_qdepth_query(void)
{
return g_throttle_que_depth;
}
void ps3_debug_mem_size_modify(unsigned int size)
{
g_debug_mem_size = size;
}
unsigned int ps3_debug_mem_size_query(void)
{
return g_debug_mem_size;
}
unsigned short ps3_use_clustering_query(void)
{
return (unsigned short)g_use_clustering;
}
void ps3_scsi_cmd_timeout_modify(unsigned int val)
{
g_scsi_cmd_timeout = val;
}
void ps3_scsi_cmd_timeout_adjust(void)
{
if (g_scsi_cmd_timeout != 0 &&
(g_scsi_cmd_timeout < PS3_SCSI_CMD_TIMEOUT_MIN ||
g_scsi_cmd_timeout > PS3_SCSI_CMD_TIMEOUT_MAX)) {
g_scsi_cmd_timeout = PS3_SCSI_CMD_TIMEOUT_DEFAULT;
}
}
unsigned int ps3_scsi_cmd_timeout_query(void)
{
return g_scsi_cmd_timeout;
}
unsigned int ps3_r1x_lock_flag_quiry(void)
{
return g_ps3_r1x_lock_flag;
}
void ps3_r1x_lock_flag_modify(unsigned int val)
{
g_ps3_r1x_lock_flag = val;
}
unsigned int ps3_direct_to_normal_query(void)
{
return g_direct_to_normal_enable;
}
void ps3_direct_to_normal_modify(unsigned int val)
{
g_direct_to_normal_enable = val;
}
unsigned int ps3_hba_check_time_query(void)
{
return g_hba_check_time;
}
unsigned int ps3_task_reset_delay_time_query(void)
{
return g_task_reset_delay_time;
}
unsigned long long ps3_r1x_ring_size_query(void)
{
unsigned long long ring_size_byte = (unsigned long long)g_r1x_ring_size;
ring_size_byte = MB_TO_BYTE(ring_size_byte);
return ring_size_byte;
}
void ps3_r1x_ring_size_modify(unsigned int size)
{
g_r1x_ring_size = size;
}
unsigned int ps3_direct_check_stream_query(void)
{
return g_direct_check_stream_enable;
}
void ps3_direct_check_stream_modify(unsigned int val)
{
g_direct_check_stream_enable = val;
}
int ps3_device_busy_threshold_query(void)
{
return g_device_busy_threshold;
}
void ps3_device_busy_threshold_modify(int busy)
{
g_device_busy_threshold = busy;
}
void ps3_log_level_modify(unsigned int level)
{
ps3_level_set(level);
}
char *ps3_log_path_query(void)
{
#ifndef __cplusplus
return g_log_path;
#else
return NULL;
#endif
}
unsigned int ps3_log_space_size_query(void)
{
return g_log_space_size;
}
unsigned int ps3_log_file_size_query(void)
{
return g_log_file_size;
}
unsigned int ps3_log_level_query(void)
{
return g_log_level;
}
void ps3_log_file_size_modify(unsigned int size)
{
g_log_file_size = size;
}
unsigned int ps3_log_tty_query(void)
{
return g_log_tty;
}
void ps3_log_tty_modify(unsigned int enable)
{
g_log_tty = enable;
}
void ps3_hard_reset_enable_modify(unsigned int val)
{
g_hard_reset_enable = val;
}
unsigned int ps3_hard_reset_enable_query(void)
{
return g_hard_reset_enable;
}
unsigned int ps3_deep_soft_reset_enable_query(void)
{
return g_deep_soft_reset_enable;
}
void ps3_deep_soft_reset_enable_modify(unsigned int val)
{
g_deep_soft_reset_enable = val;
}
unsigned int ps3_aer_handle_support_query(void)
{
return g_aer_handle_support;
}
void ps3_aer_handle_support_set(unsigned int aer_handle_support)
{
g_aer_handle_support = aer_handle_support;
}
unsigned int ps3_hard_reset_waiting_query(void)
{
return g_hard_reset_waiting;
}
unsigned int ps3_use_hard_reset_reg_query(void)
{
return g_use_hard_reset_reg;
}
unsigned int ps3_use_hard_reset_max_retry(void)
{
return g_use_hard_reset_max_retry;
}
unsigned int ps3_enable_heartbeat_query(void)
{
return g_enable_heartbeat;
}
unsigned int ps3_enable_heartbeat_set(unsigned int val)
{
return g_enable_heartbeat = val;
}
unsigned int ps3_hil_mode_query(void)
{
return g_hil_mode;
}
void ps3_hil_mode_modify(unsigned int val)
{
g_hil_mode = val;
}
unsigned int ps3_available_func_id_query(void)
{
return g_available_func_id;
}
void ps3_available_func_id_modify(unsigned int val)
{
g_available_func_id = val;
}
unsigned int ps3_r1x_tmo_query(void)
{
if (unlikely(g_r1x_time_out > 360000))
g_r1x_time_out = 360000;
return g_r1x_time_out * HZ / 1000;
}
unsigned int ps3_r1x_conflict_queue_support_query(void)
{
return g_r1x_conflict_queue_enable;
}
unsigned int ps3_pci_irq_mode_query(void)
{
return g_pci_irq_mode;
}
unsigned int ps3_cli_ver_query(void)
{
return cli_ver;
}
#if defined(PS3_TAGSET_SUPPORT)
void ps3_tagset_enable_modify(unsigned char enable)
{
g_ps3_tagset_enable = enable;
}
unsigned char ps3_tagset_enable_query(void)
{
return (g_ps3_tagset_enable == 1) ? PS3_TRUE : PS3_FALSE;
}
#endif
unsigned char ps3_smp_affinity_query(void)
{
return (g_smp_affinity_enable == 1) ? PS3_TRUE : PS3_FALSE;
}

View File

@ -0,0 +1,102 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef _PS3_MODULE_PARA_H_
#define _PS3_MODULE_PARA_H_
#define MB_TO_BYTE(MB) ((MB) << 20)
#define PS3_MAX_FUNC_ID (2)
unsigned int ps3_throttle_qdepth_query(void);
void ps3_debug_mem_size_modify(unsigned int size);
unsigned int ps3_debug_mem_size_query(void);
unsigned int ps3_sata_direct_query(void);
void ps3_sata_direct_modify(unsigned int val);
unsigned short ps3_use_clustering_query(void);
void ps3_scsi_cmd_timeout_modify(unsigned int val);
unsigned int ps3_scsi_cmd_timeout_query(void);
void ps3_scsi_cmd_timeout_adjust(void);
unsigned int ps3_r1x_lock_flag_quiry(void);
void ps3_r1x_lock_flag_modify(unsigned int val);
unsigned int ps3_direct_to_normal_query(void);
void ps3_direct_to_normal_modify(unsigned int val);
unsigned int ps3_hba_check_time_query(void);
unsigned int ps3_task_reset_delay_time_query(void);
unsigned long long ps3_r1x_ring_size_query(void);
void ps3_r1x_ring_size_modify(unsigned int size);
unsigned int ps3_direct_check_stream_query(void);
int ps3_device_busy_threshold_query(void);
void ps3_device_busy_threshold_modify(int busy);
void ps3_log_level_modify(unsigned int level);
char *ps3_log_path_query(void);
unsigned int ps3_log_space_size_query(void);
unsigned int ps3_log_file_size_query(void);
void ps3_log_file_size_modify(unsigned int size);
unsigned int ps3_log_level_query(void);
unsigned int ps3_log_tty_query(void);
void ps3_log_tty_modify(unsigned int enable);
void ps3_hard_reset_enable_modify(unsigned int val);
void ps3_deep_soft_reset_enable_modify(unsigned int val);
unsigned int ps3_hard_reset_enable_query(void);
unsigned int ps3_deep_soft_reset_enable_query(void);
unsigned int ps3_log_level_query(void);
unsigned int ps3_aer_handle_support_query(void);
void ps3_aer_handle_support_set(unsigned int aer_handle_support);
void ps3_version_verbose_fill(void);
unsigned int ps3_hard_reset_waiting_query(void);
unsigned int ps3_use_hard_reset_reg_query(void);
unsigned int ps3_use_hard_reset_max_retry(void);
unsigned int ps3_enable_heartbeat_query(void);
unsigned int ps3_enable_heartbeat_set(unsigned int val);
unsigned int ps3_hil_mode_query(void);
void ps3_hil_mode_modify(unsigned int val);
unsigned int ps3_available_func_id_query(void);
void ps3_available_func_id_modify(unsigned int val);
void ps3_direct_check_stream_modify(unsigned int val);
unsigned int ps3_r1x_tmo_query(void);
unsigned int ps3_r1x_conflict_queue_support_query(void);
unsigned int ps3_pci_irq_mode_query(void);
#if defined(PS3_TAGSET_SUPPORT)
void ps3_tagset_enable_modify(unsigned char enable);
unsigned char ps3_tagset_enable_query(void);
#endif
unsigned char ps3_smp_affinity_query(void);
#ifndef _WINDOWS
#endif
#endif

View File

@ -0,0 +1,397 @@
// SPDX-License-Identifier: GPL-2.0
#include <scsi/scsi_eh.h>
#include "ps3_htp_nvme_spec.h"
#include "ps3_nvme_resp_to_scsi.h"
#include "ps3_instance_manager.h"
#include "ps3_htp_def.h"
#include "ps3_htp.h"
enum {
SENSE_KEY_NO_SENSE = 0x00,
SENSE_KEY_RECOVERED_ERROR = 0x01,
SENSE_KEY_NOT_READY = 0x02,
SENSE_KEY_MEDIUM_ERROR = 0x03,
SENSE_KEY_HARDWARE_ERROR = 0x04,
SENSE_KEY_ILLEGAL_REQUEST = 0x05,
SENSE_KEY_UNIT_ATTENTION = 0x06,
SENSE_KEY_DATA_PROTECT = 0x07,
SENSE_KEY_BLANK_CHECK = 0x08,
SENSE_KEY_VENDOR_SPECIFIC = 0x09,
SENSE_KEY_COPY_ABORTED = 0x0a,
SENSE_KEY_ABORTED_COMMAND = 0x0b,
SENSE_KEY_VOLUME_OVERFLOW = 0x0d,
SENSE_KEY_MISCOMPARE = 0x0e,
};
enum {
SCSI_ASC_NO_ADDITIONAL_SENSE = 0x00,
SCSI_ASC_PERIPHERAL_DEVICE_WRITE_FAULT = 0x03,
SCSI_ASC_LOGICAL_UNIT_NOT_READY = 0x04,
SCSI_ASC_WARNING = 0x0b,
SCSI_ASC_LOGICAL_BLOCK_GUARD_CHECK_FAILED = 0x10,
SCSI_ASC_LOGICAL_BLOCK_APPTAG_CHECK_FAILED = 0x10,
SCSI_ASC_LOGICAL_BLOCK_REFTAG_CHECK_FAILED = 0x10,
SCSI_ASC_UNRECOVERED_READ_ERROR = 0x11,
SCSI_ASC_MISCOMPARE_DURING_VERIFY_OPERATION = 0x1d,
SCSI_ASC_INVALID_COMMAND_OPERATION_CODE = 0x20,
SCSI_ASC_ACCESS_DENIED = 0x20,
SCSI_ASC_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE = 0x21,
SCSI_ASC_INVALID_FIELD_IN_CDB = 0x24,
SCSI_ASC_LOGICAL_UNIT_NOT_SUPPORTED = 0x25,
SCSI_ASC_WRITE_PROTECTED = 0x27,
SCSI_ASC_FORMAT_COMMAND_FAILED = 0x31,
SCSI_ASC_SAVING_PARAMETERS_NOT_SUPPORTED = 0x39,
SCSI_ASC_INTERNAL_TARGET_FAILURE = 0x44,
SCSI_ASC_DATA_PHASE_ERROR = 0x4b,
};
enum ScsiAscq {
SCSI_ASCQ_CAUSE_NOT_REPORTABLE = 0x00,
SCSI_ASCQ_BECOMING_READY = 0x01,
SCSI_ASCQ_FORMAT_COMMAND_FAILED = 0x01,
SCSI_ASCQ_LOGICAL_BLOCK_GUARD_CHECK_FAILED = 0x01,
SCSI_ASCQ_LOGICAL_BLOCK_APPTAG_CHECK_FAILED = 0x02,
SCSI_ASCQ_NO_ACCESS_RIGHTS = 0x02,
SCSI_ASCQ_LOGICAL_BLOCK_REFTAG_CHECK_FAILED = 0x03,
SCSI_ASCQ_SANITIZE_COMMAND_FAILED = 0x03,
SCSI_ASCQ_LOGICAL_UNIT_NOT_READY_FORMAT_IN_PROGRESS = 0x04,
SCSI_ASCQ_DATA_OFFSET_ERROR = 0x05,
SCSI_ASCQ_POWER_LOSS_EXPECTED = 0x08,
SCSI_ASCQ_INVALID_LU_IDENTIFIER = 0x09,
SCSI_ASCQ_SDBP_INCOMING_BUFFER_OVERFLOW = 0x0C,
SCSI_ASCQ_WARNING_MICROCODE_DIGITAL_SIGNATURE_VALIDATION_FAILURE = 0x13,
SCSI_ASCQ_ERASE_OPEARTION_IN_PROGRESS = 0x18,
SCSI_ASCQ_LOGICAL_UNIT_NOT_READY_SANITIZE_IN_PROGRESS = 0x1b,
};
#define PS3_MEDIUM_ERROR_LEN (4)
static void
ps3_nvme_generic_error_to_scsi_status(unsigned char nvmeSc,
struct ps3_nvme_scsi_status *cpl)
{
switch (nvmeSc) {
case NVME_SC_SUCCESS:
cpl->status = SCSI_STATUS_GOOD;
cpl->senseKey = SENSE_KEY_NO_SENSE;
cpl->asc = SCSI_ASC_NO_ADDITIONAL_SENSE;
cpl->ascq = SCSI_ASCQ_CAUSE_NOT_REPORTABLE;
break;
case NVME_SC_INVALID_OPCODE:
cpl->status = SCSI_STATUS_CHECK_CONDITION;
cpl->senseKey = SENSE_KEY_ILLEGAL_REQUEST;
cpl->asc = SCSI_ASC_INVALID_COMMAND_OPERATION_CODE;
cpl->ascq = SCSI_ASCQ_CAUSE_NOT_REPORTABLE;
break;
case NVME_SC_INVALID_FIELD:
cpl->status = SCSI_STATUS_CHECK_CONDITION;
cpl->senseKey = SENSE_KEY_ILLEGAL_REQUEST;
cpl->asc = SCSI_ASC_INVALID_FIELD_IN_CDB;
cpl->ascq = SCSI_ASCQ_CAUSE_NOT_REPORTABLE;
break;
case NVME_SC_DATA_TRANSFER_ERROR:
case NVME_SC_CAPACITY_EXCEEDED:
cpl->status = SCSI_STATUS_CHECK_CONDITION;
cpl->senseKey = SENSE_KEY_MEDIUM_ERROR;
cpl->asc = SCSI_ASC_NO_ADDITIONAL_SENSE;
cpl->ascq = SCSI_ASCQ_CAUSE_NOT_REPORTABLE;
break;
case NVME_SC_ABORTED_POWER_LOSS:
cpl->status = SCSI_STATUS_CHECK_CONDITION;
cpl->senseKey = SENSE_KEY_ABORTED_COMMAND;
cpl->asc = SCSI_ASC_WARNING;
cpl->ascq = SCSI_ASCQ_POWER_LOSS_EXPECTED;
break;
case NVME_SC_INTERNAL_DEVICE_ERROR:
cpl->status = SCSI_STATUS_CHECK_CONDITION;
cpl->senseKey = SENSE_KEY_HARDWARE_ERROR;
cpl->asc = SCSI_ASC_INTERNAL_TARGET_FAILURE;
cpl->ascq = SCSI_ASCQ_CAUSE_NOT_REPORTABLE;
break;
case NVME_SC_ABORTED_BY_REQUEST:
case NVME_SC_ABORTED_SQ_DELETION:
case NVME_SC_ABORTED_FAILED_FUSED:
case NVME_SC_ABORTED_MISSING_FUSED:
cpl->status = SCSI_STATUS_CHECK_CONDITION;
cpl->senseKey = SENSE_KEY_ABORTED_COMMAND;
cpl->asc = SCSI_ASC_NO_ADDITIONAL_SENSE;
cpl->ascq = SCSI_ASCQ_CAUSE_NOT_REPORTABLE;
break;
case NVME_SC_INVALID_NAMESPACE_OR_FORMAT:
cpl->status = SCSI_STATUS_CHECK_CONDITION;
cpl->senseKey = SENSE_KEY_ILLEGAL_REQUEST;
cpl->asc = SCSI_ASC_ACCESS_DENIED;
cpl->ascq = SCSI_ASCQ_INVALID_LU_IDENTIFIER;
break;
case NVME_SC_LBA_OUT_OF_RANGE:
cpl->status = SCSI_STATUS_CHECK_CONDITION;
cpl->senseKey = SENSE_KEY_ILLEGAL_REQUEST;
cpl->asc = SCSI_ASC_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE;
cpl->ascq = SCSI_ASCQ_CAUSE_NOT_REPORTABLE;
break;
case NVME_SC_NAMESPACE_NOT_READY:
cpl->status = SCSI_STATUS_CHECK_CONDITION;
cpl->senseKey = SENSE_KEY_NOT_READY;
cpl->asc = SCSI_ASC_LOGICAL_UNIT_NOT_READY;
cpl->ascq = SCSI_ASCQ_CAUSE_NOT_REPORTABLE;
break;
case NVME_SC_RESERVATION_CONFLICT:
cpl->status = SCSI_STATUS_RESERVATION_CONFLICT;
cpl->senseKey = SENSE_KEY_NO_SENSE;
cpl->asc = SCSI_ASC_NO_ADDITIONAL_SENSE;
cpl->ascq = SCSI_ASCQ_CAUSE_NOT_REPORTABLE;
break;
case NVME_SC_COMMAND_ID_CONFLICT:
case NVME_SC_COMMAND_SEQUENCE_ERROR:
case NVME_SC_INVALID_SGL_SEG_DESCRIPTOR:
case NVME_SC_INVALID_NUM_SGL_DESCIRPTORS:
case NVME_SC_DATA_SGL_LENGTH_INVALID:
case NVME_SC_METADATA_SGL_LENGTH_INVALID:
case NVME_SC_SGL_DESCRIPTOR_TYPE_INVALID:
case NVME_SC_INVALID_CONTROLLER_MEM_BUF:
case NVME_SC_INVALID_PRP_OFFSET:
cpl->status = SCSI_STATUS_CHECK_CONDITION;
cpl->senseKey = SENSE_KEY_ILLEGAL_REQUEST;
cpl->asc = SCSI_ASC_DATA_PHASE_ERROR;
cpl->ascq = SCSI_ASCQ_DATA_OFFSET_ERROR;
break;
case NVME_SC_ATOMIC_WRITE_UNIT_EXCEEDED:
case NVME_SC_INVALID_SGL_OFFSET:
case NVME_SC_HOSTID_INCONSISTENT_FORMAT:
case NVME_SC_KEEP_ALIVE_EXPIRED:
case NVME_SC_KEEP_ALIVE_INVALID:
case NVME_SC_FORMAT_IN_PROGRESS:
cpl->status = SCSI_STATUS_CHECK_CONDITION;
cpl->senseKey = SENSE_KEY_NOT_READY;
cpl->asc = SCSI_ASC_LOGICAL_UNIT_NOT_READY;
cpl->ascq = SCSI_ASCQ_LOGICAL_UNIT_NOT_READY_FORMAT_IN_PROGRESS;
break;
case NVME_SC_SANITIZE_FAILED:
cpl->status = SCSI_STATUS_CHECK_CONDITION;
cpl->senseKey = SENSE_KEY_MEDIUM_ERROR;
cpl->asc = SCSI_ASC_FORMAT_COMMAND_FAILED;
cpl->ascq = SCSI_ASCQ_SANITIZE_COMMAND_FAILED;
break;
case NVME_SC_SANITIZE_IN_PROGRESS:
cpl->status = SCSI_STATUS_CHECK_CONDITION;
cpl->senseKey = SENSE_KEY_NOT_READY;
cpl->asc = SCSI_ASC_LOGICAL_UNIT_NOT_READY;
cpl->ascq =
SCSI_ASCQ_LOGICAL_UNIT_NOT_READY_SANITIZE_IN_PROGRESS;
break;
case NVME_SC_NAMESPACE_IS_WRITE_PROTECTED:
cpl->status = SCSI_STATUS_CHECK_CONDITION;
cpl->senseKey = SENSE_KEY_DATA_PROTECT;
cpl->asc = SCSI_ASC_WRITE_PROTECTED;
cpl->ascq = SCSI_ASCQ_CAUSE_NOT_REPORTABLE;
break;
case NVME_SC_COMMAND_INTERRUPTED:
case NVME_SC_TRANSIENT_TRANSPORT_ERROR:
cpl->status = SCSI_STATUS_CHECK_CONDITION;
cpl->senseKey = SENSE_KEY_ABORTED_COMMAND;
cpl->asc = SCSI_ASC_NO_ADDITIONAL_SENSE;
cpl->ascq = SCSI_ASCQ_CAUSE_NOT_REPORTABLE;
break;
default:
cpl->status = SCSI_STATUS_CHECK_CONDITION;
cpl->senseKey = SENSE_KEY_ILLEGAL_REQUEST;
cpl->asc = SCSI_ASC_NO_ADDITIONAL_SENSE;
cpl->ascq = SCSI_ASCQ_CAUSE_NOT_REPORTABLE;
break;
}
}
static void ps3_nvme_spec_error_to_scsi_status(unsigned char nvmeSc,
struct ps3_nvme_scsi_status *cpl)
{
switch (nvmeSc) {
case NVME_CSC_COMPLETION_QUEUE_INVALID:
case NVME_CSC_ABORT_COMMAND_LIMIT_EXCEEDED:
cpl->status = SCSI_STATUS_CHECK_CONDITION;
cpl->senseKey = SENSE_KEY_ILLEGAL_REQUEST;
cpl->asc = SCSI_ASC_NO_ADDITIONAL_SENSE;
cpl->ascq = SCSI_ASCQ_CAUSE_NOT_REPORTABLE;
break;
case NVME_CSC_INVALID_FORMAT:
cpl->status = SCSI_STATUS_CHECK_CONDITION;
cpl->senseKey = SENSE_KEY_ILLEGAL_REQUEST;
cpl->asc = SCSI_ASC_FORMAT_COMMAND_FAILED;
cpl->ascq = SCSI_ASCQ_FORMAT_COMMAND_FAILED;
break;
case NVME_CSC_CONFLICTING_ATTRIBUTES:
cpl->status = SCSI_STATUS_CHECK_CONDITION;
cpl->senseKey = SENSE_KEY_ILLEGAL_REQUEST;
cpl->asc = SCSI_ASC_INVALID_FIELD_IN_CDB;
cpl->ascq = SCSI_ASCQ_CAUSE_NOT_REPORTABLE;
break;
case NVME_CSC_ATTEMPTED_WRITE_TO_RO_RANGE:
cpl->status = SCSI_STATUS_CHECK_CONDITION;
cpl->senseKey = SENSE_KEY_DATA_PROTECT;
cpl->asc = SCSI_ASC_WRITE_PROTECTED;
cpl->ascq = SCSI_ASCQ_CAUSE_NOT_REPORTABLE;
break;
case NVME_CSC_INVALID_QUEUE_IDENTIFIER:
case NVME_CSC_MAXIMUM_QUEUE_SIZE_EXCEEDED:
case NVME_CSC_ASYNC_EVENT_REQUEST_LIMIT_EXCEEDED:
case NVME_CSC_FIRMWARE_REQ_NVM_RESET:
case NVME_CSC_INVALID_PROTECTION_INFO:
case NVME_CSC_FIRMWARE_REQ_MAX_TIME_VIOLATION:
case NVME_CSC_FIRMWARE_ACTIVATION_PROHIBITED:
case NVME_CSC_BOOT_PARTITION_WRITE_PROHIBITED:
case NVME_CSC_INVALID_FIRMWARE_SLOT:
cpl->status = SCSI_STATUS_CHECK_CONDITION;
cpl->senseKey = SENSE_KEY_ABORTED_COMMAND;
cpl->asc = SCSI_ASC_NO_ADDITIONAL_SENSE;
cpl->ascq = SCSI_ASCQ_CAUSE_NOT_REPORTABLE;
break;
case NVME_CSC_INVALID_FIRMWARE_IMAGE:
cpl->status = SCSI_STATUS_CHECK_CONDITION;
cpl->senseKey = SENSE_KEY_ABORTED_COMMAND;
cpl->asc = SCSI_ASC_WARNING;
cpl->ascq =
SCSI_ASCQ_WARNING_MICROCODE_DIGITAL_SIGNATURE_VALIDATION_FAILURE;
break;
case NVME_CSC_INVALID_INTERRUPT_VECTOR:
case NVME_CSC_INVALID_LOG_PAGE:
case NVME_CSC_FIRMWARE_REQ_CONVENTIONAL_RESET:
case NVME_CSC_INVALID_QUEUE_DELETION:
case NVME_CSC_FEATURE_ID_NOT_SAVEABLE:
case NVME_CSC_FEATURE_NOT_CHANGEABLE:
case NVME_CSC_FEATURE_NOT_NAMESPACE_SPECIFIC:
case NVME_CSC_FIRMWARE_REQ_RESET:
case NVME_CSC_OVERLAPPING_RANGE:
cpl->status = SCSI_STATUS_CHECK_CONDITION;
cpl->senseKey = SENSE_KEY_ILLEGAL_REQUEST;
cpl->asc = SCSI_ASC_INVALID_FIELD_IN_CDB;
cpl->ascq = SCSI_ASCQ_CAUSE_NOT_REPORTABLE;
break;
case NVME_CSC_NAMESPACE_INSUFFICIENT_CAPACITY:
case NVME_CSC_NAMESPACE_ID_UNAVAILABLE:
case NVME_CSC_NAMESPACE_ALREADY_ATTACHED:
case NVME_CSC_NAMESPACE_IS_PRIVATE:
case NVME_CSC_NAMESPACE_NOT_ATTACHED:
case NVME_CSC_THINPROVISIONING_NOT_SUPPORTED:
case NVME_CSC_CONTROLLER_LIST_INVALID:
default:
cpl->status = SCSI_STATUS_CHECK_CONDITION;
cpl->senseKey = SENSE_KEY_ILLEGAL_REQUEST;
cpl->asc = SCSI_ASC_NO_ADDITIONAL_SENSE;
cpl->ascq = SCSI_ASCQ_CAUSE_NOT_REPORTABLE;
break;
}
}
static void
ps3_nvme_media_error_to_scsi_status(unsigned char nvmeSc,
struct ps3_nvme_scsi_status *cpl)
{
switch (nvmeSc) {
case NVME_MSC_WRITE_FAULTS:
cpl->status = SCSI_STATUS_CHECK_CONDITION;
cpl->senseKey = SENSE_KEY_MEDIUM_ERROR;
cpl->asc = SCSI_ASC_PERIPHERAL_DEVICE_WRITE_FAULT;
cpl->ascq = SCSI_ASCQ_CAUSE_NOT_REPORTABLE;
break;
case NVME_MSC_UNRECOVERED_READ_ERROR:
cpl->status = SCSI_STATUS_CHECK_CONDITION;
cpl->senseKey = SENSE_KEY_MEDIUM_ERROR;
cpl->asc = SCSI_ASC_UNRECOVERED_READ_ERROR;
cpl->ascq = SCSI_ASCQ_CAUSE_NOT_REPORTABLE;
break;
case NVME_MSC_GUARD_CHECK_ERROR:
cpl->status = SCSI_STATUS_CHECK_CONDITION;
cpl->senseKey = SENSE_KEY_ABORTED_COMMAND;
cpl->asc = SCSI_ASC_LOGICAL_BLOCK_GUARD_CHECK_FAILED;
cpl->ascq = SCSI_ASCQ_LOGICAL_BLOCK_GUARD_CHECK_FAILED;
break;
case NVME_MSC_APPLICATION_TAG_CHECK_ERROR:
cpl->status = SCSI_STATUS_CHECK_CONDITION;
cpl->senseKey = SENSE_KEY_ABORTED_COMMAND;
cpl->asc = SCSI_ASC_LOGICAL_BLOCK_APPTAG_CHECK_FAILED;
cpl->ascq = SCSI_ASCQ_LOGICAL_BLOCK_APPTAG_CHECK_FAILED;
break;
case NVME_MSC_REFERENCE_TAG_CHECK_ERROR:
cpl->status = SCSI_STATUS_CHECK_CONDITION;
cpl->senseKey = SENSE_KEY_ABORTED_COMMAND;
cpl->asc = SCSI_ASC_LOGICAL_BLOCK_REFTAG_CHECK_FAILED;
cpl->ascq = SCSI_ASCQ_LOGICAL_BLOCK_REFTAG_CHECK_FAILED;
break;
case NVME_MSC_COMPARE_FAILURE:
cpl->status = SCSI_STATUS_CHECK_CONDITION;
cpl->senseKey = SENSE_KEY_MISCOMPARE;
cpl->asc = SCSI_ASC_MISCOMPARE_DURING_VERIFY_OPERATION;
cpl->ascq = SCSI_ASCQ_CAUSE_NOT_REPORTABLE;
break;
case NVME_MSC_ACCESS_DENIED:
cpl->status = SCSI_STATUS_CHECK_CONDITION;
cpl->senseKey = SENSE_KEY_DATA_PROTECT;
cpl->asc = SCSI_ASC_ACCESS_DENIED;
cpl->ascq = SCSI_ASCQ_NO_ACCESS_RIGHTS;
break;
case NVME_MSC_DEALLOCATED_OR_UNWRITTEN_BLOCK:
cpl->status = SCSI_STATUS_CHECK_CONDITION;
cpl->senseKey = SENSE_KEY_MEDIUM_ERROR;
cpl->asc = SCSI_ASC_UNRECOVERED_READ_ERROR;
cpl->ascq = SCSI_ASCQ_SDBP_INCOMING_BUFFER_OVERFLOW;
break;
default:
cpl->status = SCSI_STATUS_CHECK_CONDITION;
cpl->senseKey = SENSE_KEY_ILLEGAL_REQUEST;
cpl->asc = SCSI_ASC_NO_ADDITIONAL_SENSE;
cpl->ascq = SCSI_ASCQ_CAUSE_NOT_REPORTABLE;
break;
}
}
void ps3_nvme_error_to_scsi_status(struct PS3NvmeCmdStatus status,
struct ps3_nvme_scsi_status *cpl)
{
unsigned char sct = status.sct;
unsigned char sc = status.sc;
switch (sct) {
case NVME_SCT_GENERIC:
ps3_nvme_generic_error_to_scsi_status(sc, cpl);
break;
case NVME_SCT_COMMAND_SPECIFIC:
ps3_nvme_spec_error_to_scsi_status(sc, cpl);
break;
case NVME_SCT_MEDIA_ERROR:
ps3_nvme_media_error_to_scsi_status(sc, cpl);
break;
case NVME_SCT_VENDOR_SPECIFIC:
default:
cpl->status = SCSI_STATUS_CHECK_CONDITION;
cpl->senseKey = SENSE_KEY_ILLEGAL_REQUEST;
cpl->asc = SCSI_ASC_NO_ADDITIONAL_SENSE;
cpl->ascq = SCSI_ASCQ_CAUSE_NOT_REPORTABLE;
break;
}
}
void ps3_nvme_resp_to_scsi_status(struct ps3_cmd *cmd)
{
struct PS3NvmeCmdStatus status;
struct ps3_nvme_scsi_status cpl;
status.cmdStatus = cmd->reply_word.retStatus;
LOG_FILE_ERROR("trace_id:0x%llx host_no:%d tag:%d nvme status:\n"
"\tsc:%d sct:%d crd:%d more:%d dnr:%d p:%d\n",
cmd->trace_id, PS3_HOST(cmd->instance), cmd->index,
status.sc, status.sct, status.crd, status.m, status.dnr,
status.p);
memset(&cpl, 0, sizeof(struct ps3_nvme_scsi_status));
ps3_nvme_error_to_scsi_status(status, &cpl);
memset(cmd->resp_frame->sasRespFrame.data, 0, PS3_SENSE_BUFFER_SIZE);
scsi_build_sense_buffer(0, cmd->resp_frame->sasRespFrame.data,
cpl.senseKey, cpl.asc, cpl.ascq);
if (cmd->reply_word.mode == PS3_REPLY_WORD_MODE_DIRECT_OK &&
cpl.senseKey == SENSE_KEY_MEDIUM_ERROR) {
memset(&cmd->resp_frame->sasRespFrame.data[3], 0xff,
PS3_MEDIUM_ERROR_LEN);
}
cmd->resp_frame->sasRespFrame.status = cpl.status;
}

View File

@ -0,0 +1,13 @@
/* SPDX-License-Identifier: GPL-2.0 */
#include "ps3_cmd_channel.h"
struct ps3_nvme_scsi_status {
unsigned char status;
unsigned char senseKey;
unsigned char asc;
unsigned char ascq;
};
void ps3_nvme_error_to_scsi_status(struct PS3NvmeCmdStatus status,
struct ps3_nvme_scsi_status *cpl);
void ps3_nvme_resp_to_scsi_status(struct ps3_cmd *cmd);

View File

@ -0,0 +1,475 @@
// SPDX-License-Identifier: GPL-2.0
#include "ps3_instance_manager.h"
#include "ps3_pci.h"
#define PS3_VALID_MEMORY_BAR_INDEX 2
#ifdef _WINDOWS
#define PS3_CHECK_BAR_64BIT(bar) ((bar) & 0x4)
#define PS3_CHECK_BAR_MEMORYSPACE(bar) (!((bar) & 0x1))
#define PS3_BAR_BASE_ADDR_MARSK (0xFFFFFFF0)
#define PS3_GET_BAR_BASE_ADDR(addr) \
((unsigned long long)((addr) & PS3_BAR_BASE_ADDR_MARSK))
static int ps3_pci_map_reg(struct ps3_instance *instance,
PPORT_CONFIGURATION_INFORMATION config);
static int ps3_pci_info_get(struct ps3_instance *instance,
PPORT_CONFIGURATION_INFORMATION config);
static void ps3_pci_unmap_reg(struct ps3_instance *instance);
static void ps3_pci_irq_type_get(struct ps3_instance *instance,
PPCI_COMMON_CONFIG pci_config);
static unsigned short ps3_pci_msix_vec_count(struct ps3_instance *instance,
PPCI_COMMON_CONFIG pci_config);
static unsigned short ps3_pci_msi_vec_count(struct ps3_instance *instance,
PPCI_COMMON_CONFIG pci_config);
int ps3_pci_init(struct ps3_instance *instance, void *config)
{
int ret = PS3_SUCCESS;
PPORT_CONFIGURATION_INFORMATION config_info =
(PPORT_CONFIGURATION_INFORMATION)config;
ret = ps3_pci_info_get(instance, config_info);
if (ret != PS3_SUCCESS)
goto l_out;
ret = ps3_pci_map_reg(instance, config_info);
if (ret != PS3_SUCCESS)
goto l_out;
l_out:
return ret;
}
void ps3_pci_exit(struct ps3_instance *instance)
{
ps3_pci_unmap_reg(instance);
}
static int ps3_pci_info_get(struct ps3_instance *instance,
PPORT_CONFIGURATION_INFORMATION config)
{
PCI_COMMON_CONFIG pci_config = { 0 };
unsigned long len = 0;
unsigned long base_addr = 0;
#ifdef PS3_HARDWARE_ASIC
unsigned int check_count = ps3_hba_check_time_query() * 10;
#endif
if (config->AdapterInterfaceType != PCIBus) {
LOG_ERROR("there is not pcibus, type:%d\n",
config->AdapterInterfaceType);
return -PS3_FAILED;
}
len = StorPortGetBusData(instance, PCIConfiguration,
config->SystemIoBusNumber,
(unsigned long)config->SlotNumber,
(void *)&pci_config, sizeof(pci_config));
if (len == 0 || len == 2) {
LOG_ERROR("get bus data failed,cfg length:%d\n", len);
return -PS3_FAILED;
}
#ifdef PS3_HARDWARE_ASIC
while (pci_config.DeviceID == PCI_DEVICE_ID_PS3_RAID_FPGA &&
check_count > 0) {
check_count--;
ps3_msleep(100);
len = StorPortGetBusData(instance, PCIConfiguration,
config->SystemIoBusNumber,
(unsigned long)config->SlotNumber,
(void *)&pci_config,
sizeof(pci_config));
if (len == 0 || len == 2) {
LOG_ERROR("get bus data failed,cfg length:%d\n", len);
return -PS3_FAILED;
}
LOG_INFO("get real device id is[0x%x]\n", pci_config.DeviceID);
};
#endif
instance->pci_dev_context.slot_number =
(unsigned long long)config->SlotNumber;
instance->pci_dev_context.device_id = pci_config.DeviceID;
instance->pci_dev_context.vendor_id = pci_config.VendorID;
instance->pci_dev_context.sub_vendor_id =
pci_config.u.type0.SubVendorID;
instance->pci_dev_context.sub_device_id =
pci_config.u.type0.SubSystemID;
base_addr =
pci_config.u.type0.BaseAddresses[PS3_VALID_MEMORY_BAR_INDEX];
if (!PS3_CHECK_BAR_MEMORYSPACE(base_addr)) {
LOG_ERROR("Bar%d is not memory space\n",
PS3_VALID_MEMORY_BAR_INDEX);
return -PS3_FAILED;
}
if (PS3_CHECK_BAR_64BIT(base_addr)) {
instance->pci_dev_context.bar_base_addr =
PS3_GET_BAR_BASE_ADDR(base_addr);
base_addr =
pci_config.u.type0
.BaseAddresses[PS3_VALID_MEMORY_BAR_INDEX + 1];
instance->pci_dev_context.bar_base_addr |=
((unsigned long long)base_addr) << 32;
} else {
instance->pci_dev_context.bar_base_addr =
PS3_GET_BAR_BASE_ADDR(base_addr);
}
ps3_pci_irq_type_get(instance, &pci_config);
if (instance->pci_dev_context.pci_irq_type == PS3_PCI_IRQ_MSIX) {
instance->pci_dev_context.irq_vec_count =
ps3_pci_msix_vec_count(instance, &pci_config);
} else if (instance->pci_dev_context.pci_irq_type == PS3_PCI_IRQ_MSI) {
instance->pci_dev_context.irq_vec_count =
ps3_pci_msi_vec_count(instance, &pci_config);
} else {
instance->pci_dev_context.irq_vec_count = 1;
}
LOG_INFO(
"vid:%x, devid:%x, sub_vid:%x, sub_devid:%x, bar_base:0x%llx, irq_type:%d, vec_count:%d\n",
instance->pci_dev_context.vendor_id,
instance->pci_dev_context.device_id,
instance->pci_dev_context.sub_vendor_id,
instance->pci_dev_context.sub_device_id,
instance->pci_dev_context.bar_base_addr,
instance->pci_dev_context.pci_irq_type,
instance->pci_dev_context.irq_vec_count);
return PS3_SUCCESS;
};
static int ps3_pci_map_reg(struct ps3_instance *instance,
PPORT_CONFIGURATION_INFORMATION config)
{
int ret = -PS3_FAILED;
unsigned long i = 0;
if (config->NumberOfAccessRanges <= 0) {
LOG_ERROR("valid access range is 0\n");
goto l_out;
}
if (config->AdapterInterfaceType != PCIBus) {
LOG_ERROR("adapter interface type is not PCIBus\n");
goto l_out;
}
for (i = 0; i < config->NumberOfAccessRanges; i++) {
LOG_DEBUG("Bar%llu:0x%llx, memory:%d, len:0x%x, ex:0x%llx\n", i,
(*(config->AccessRanges))[i].RangeStart.QuadPart,
(*(config->AccessRanges))[i].RangeInMemory,
(*(config->AccessRanges))[i].RangeLength,
instance->pci_dev_context.bar_base_addr);
if ((unsigned long long)(*(config->AccessRanges))[i]
.RangeStart.QuadPart !=
instance->pci_dev_context.bar_base_addr) {
continue;
}
if (!(*(config->AccessRanges))[i].RangeInMemory) {
LOG_INFO(
"access range number continue:%d, is not memery\n",
i);
continue;
}
instance->reg_set = (struct Ps3Fifo *)StorPortGetDeviceBase(
instance, config->AdapterInterfaceType,
config->SystemIoBusNumber,
(*(config->AccessRanges))[i].RangeStart,
(*(config->AccessRanges))[i].RangeLength, 0);
if (instance->reg_set != NULL)
ret = PS3_SUCCESS;
break;
}
l_out:
LOG_INFO("map reg:%d,reg:%p\n", ret, instance->reg_set);
return ret;
}
static void ps3_pci_unmap_reg(struct ps3_instance *instance)
{
if (instance->reg_set != NULL) {
StorPortFreeDeviceBase(instance, instance->reg_set);
instance->reg_set = NULL;
}
}
static int __ps3_pci_find_capability(PPCI_COMMON_CONFIG pci_config, int cap_id)
{
int pos = 0;
unsigned char *config_base_addr = (unsigned char *)pci_config;
unsigned char cap_offset = 0;
PPCI_CAPABILITIES_HEADER cap_header = NULL;
if (PCI_CONFIGURATION_TYPE(pci_config)) {
LOG_ERROR("there is not agent device\n");
goto l_out;
}
if ((pci_config->Status & PCI_STATUS_CAPABILITIES_LIST) == 0) {
LOG_ERROR("capability pointer invalid\n");
goto l_out;
}
cap_offset = pci_config->u.type0.CapabilitiesPtr;
while (cap_offset != 0) {
cap_header = (PPCI_CAPABILITIES_HEADER)(config_base_addr +
cap_offset);
if (cap_header->CapabilityID == 0) {
cap_offset = cap_header->Next;
continue;
}
if (cap_header->CapabilityID == (unsigned char)cap_id) {
pos = cap_offset;
break;
}
cap_offset = cap_header->Next;
};
l_out:
return pos;
}
static void ps3_pci_irq_type_get(struct ps3_instance *instance,
PPCI_COMMON_CONFIG pci_config)
{
unsigned char *config_base_addr = (unsigned char *)pci_config;
unsigned short data_u16 = 0;
int pos = 0;
instance->pci_dev_context.pci_irq_type = PS3_PCI_IRQ_LEGACY;
pos = __ps3_pci_find_capability(pci_config, PCI_CAP_ID_MSIX);
if (pos != 0) {
data_u16 = *((unsigned short *)(config_base_addr + pos +
PCI_MSIX_FLAGS));
for (size_t i = 0; i < 4; i++) {
unsigned char tmp = *(
(unsigned char *)(config_base_addr + pos + i));
LOG_DEBUG("%d:%d:%x\n", pos, i, tmp);
}
if ((data_u16 & PCI_MSIX_FLAGS_ENABLE) ==
PCI_MSIX_FLAGS_ENABLE) {
instance->pci_dev_context.pci_irq_type =
PS3_PCI_IRQ_MSIX;
goto l_out;
}
}
pos = __ps3_pci_find_capability(pci_config, PCI_CAP_ID_MSI);
if (pos != 0) {
data_u16 = *((unsigned short *)(config_base_addr + pos +
PCI_MSI_FLAGS));
if ((data_u16 & PCI_MSI_FLAGS_ENABLE) == PCI_MSI_FLAGS_ENABLE) {
instance->pci_dev_context.pci_irq_type =
PS3_PCI_IRQ_MSI;
goto l_out;
}
}
l_out:
return;
}
void ps3_pci_intx(struct ps3_instance *instance, unsigned char enable)
{
unsigned short pci_command = 0;
unsigned short pci_command_new = 0;
if (ps3_pci_read_config_word(instance, PCI_COMMAND, &pci_command) !=
PS3_SUCCESS) {
goto l_out;
}
if (enable)
pci_command_new = pci_command & ~PCI_COMMAND_INTX_DISABLE;
else
pci_command_new = pci_command | PCI_COMMAND_INTX_DISABLE;
if (pci_command_new != pci_command) {
ps3_pci_write_config_word(instance, PCI_COMMAND,
pci_command_new);
}
l_out:
return;
}
static unsigned short ps3_pci_msix_vec_count(struct ps3_instance *instance,
PPCI_COMMON_CONFIG pci_config)
{
unsigned char *config_base_addr = (unsigned char *)pci_config;
int pos = 0;
unsigned short msix_vec_count = 0;
unsigned short data_u16 = 0;
(void)instance;
pos = __ps3_pci_find_capability(pci_config, PCI_CAP_ID_MSIX);
if (pos != 0)
data_u16 = *((unsigned short *)(config_base_addr + pos +
PCI_MSIX_FLAGS));
msix_vec_count = ((data_u16 & PCI_MSIX_FLAGS_QSIZE) + 1);
return msix_vec_count;
}
static unsigned short ps3_pci_msi_vec_count(struct ps3_instance *instance,
PPCI_COMMON_CONFIG pci_config)
{
unsigned char *config_base_addr = (unsigned char *)pci_config;
int pos = 0;
unsigned short msi_vec_count = 0;
unsigned short data_u16 = 0;
(void)instance;
pos = __ps3_pci_find_capability(pci_config, PCI_CAP_ID_MSI);
if (pos != 0)
data_u16 = *((unsigned short *)(config_base_addr + pos +
PCI_MSI_FLAGS));
msi_vec_count = 1 << ((data_u16 & PCI_MSI_FLAGS_QMASK) >> 1);
return data_u16;
}
#endif
int ps3_pci_find_capability(struct ps3_instance *instance, int cap_id)
{
int pos = 0;
#ifdef _WINDOWS
PCI_COMMON_CONFIG pci_config = { 0 };
unsigned int len = 0;
len = (unsigned int)StorPortGetBusData(
instance, PCIConfiguration, (unsigned long)instance->bus_number,
(unsigned long)instance->pci_dev_context.slot_number,
(void *)&pci_config, (unsigned long)sizeof(pci_config));
if (len == 0 || len == 2) {
LOG_ERROR("get bus data failed,cfg length:%d\n", len);
goto l_out;
}
pos = __ps3_pci_find_capability(&pci_config, cap_id);
l_out:
#else
pos = pci_find_capability(instance->pdev, cap_id);
#endif
return pos;
}
int ps3_pci_read_config_word(struct ps3_instance *instance, unsigned int offset,
unsigned short *val)
{
int ret = -PS3_FAILED;
#ifdef _WINDOWS
PCI_COMMON_CONFIG pci_config = { 0 };
unsigned int len = 0;
unsigned char *config_base_addr = (unsigned char *)&pci_config;
len = (unsigned int)StorPortGetBusData(
instance, PCIConfiguration, (unsigned long)instance->bus_number,
(unsigned long)instance->pci_dev_context.slot_number,
(void *)&pci_config, (unsigned long)sizeof(pci_config));
if (len == 0 || len == 2) {
LOG_ERROR("get bus data failed,cfg length:%d\n", len);
goto l_out;
}
*val = *((unsigned short *)(config_base_addr + offset));
ret = PS3_SUCCESS;
l_out:
#else
ret = pci_read_config_word(instance->pdev, offset, val);
#endif
LOG_INFO("read config word :%d\n", ret);
return ret;
}
int ps3_pci_write_config_word(struct ps3_instance *instance,
unsigned int offset, unsigned short val)
{
int ret = -PS3_FAILED;
#ifdef _WINDOWS
unsigned int len = 0;
len = (unsigned int)StorPortSetBusDataByOffset(
instance, PCIConfiguration, (unsigned long)instance->bus_number,
(unsigned long)instance->pci_dev_context.slot_number,
(void *)&val, (unsigned long)offset,
(unsigned long)sizeof(unsigned short));
if (len == sizeof(unsigned short))
ret = PS3_SUCCESS;
#else
ret = pci_write_config_word(instance->pdev, offset, val);
#endif
LOG_INFO("write config word :%d\n", ret);
return ret;
}
void ps3_reg_write_u64(struct ps3_instance *instance, unsigned long long val,
void *reg)
{
#ifndef _WINDOWS
#if defined(writeq) && defined(CONFIG_64BIT)
(void)instance;
writeq(val, reg);
#else
unsigned long flags;
ps3_spin_lock_irqsave(&instance->req_queue_lock, &flags);
writel((unsigned int)(val & 0xffffffff), reg);
writel((unsigned int)(val >> 32), reg + 0x4UL);
ps3_spin_unlock_irqrestore(&instance->req_queue_lock, flags);
#endif
#else
StorPortWriteRegisterUlong64(instance, reg, val);
#endif
}
unsigned long long ps3_reg_read_u64(struct ps3_instance *instance, void *reg)
{
unsigned long long value = 0;
(void)instance;
#ifndef _WINDOWS
#if defined(readq) && defined(CONFIG_64BIT)
value = readq(reg);
#else
value = (((unsigned long long)readl(reg + 0x4UL) << 32) |
(unsigned long long)readl(reg));
#endif
#else
value = StorPortReadRegisterUlong64(instance, reg);
#endif
return value;
}
void __iomem *ps3_reg_set_ioremap(struct pci_dev *pdev, unsigned long reg_bar)
{
resource_size_t base_addr = 0;
base_addr = pci_resource_start(pdev, reg_bar);
return ioremap(base_addr, PS3_REGISTER_SET_SIZE);
}

View File

@ -0,0 +1,66 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef _PS3_PCI_H_
#define _PS3_PCI_H_
#ifdef _WINDOWS
#include "ps3_def.h"
#define PCI_CAP_ID_MSIX PCI_CAPABILITY_ID_MSIX
#define PCI_CAP_ID_MSI PCI_CAPABILITY_ID_MSI
#define PCI_MSIX_FLAGS_ENABLE 0x8000
#define PCI_MSIX_FLAGS 2
#define PCI_MSI_FLAGS 2
#define PCI_MSI_FLAGS_ENABLE 0x0001
#define PCI_COMMAND_INTX_DISABLE 0x400
#define PCI_COMMAND 0x04
#define PCI_STATUS 0x06
#define PCI_STATUS_INTERRUPT 0x08
#define PCI_MSIX_FLAGS_QSIZE 0x07FF
#define PCI_MSI_FLAGS_QMASK 0x000e
#endif
#ifndef _WINDOWS
#if defined PS3_HARDWARE_ASIC
#include "ps3_ioc_manager.h"
#endif
#endif
struct ps3_instance;
#ifdef _WINDOWS
struct ps3_pci_context {
unsigned long long slot_number;
unsigned short vendor_id;
unsigned short device_id;
unsigned short sub_vendor_id;
unsigned short sub_device_id;
unsigned long long bar_base_addr;
unsigned short irq_vec_count;
unsigned short valid_irq_count;
unsigned char pci_irq_type;
};
int ps3_pci_init(struct ps3_instance *instance, void *config);
void ps3_pci_exit(struct ps3_instance *instance);
void ps3_pci_intx(struct ps3_instance *instance, unsigned char enable);
#endif
int ps3_pci_find_capability(struct ps3_instance *instance, int cap_id);
int ps3_pci_read_config_word(struct ps3_instance *instance, unsigned int offset,
unsigned short *val);
int ps3_pci_write_config_word(struct ps3_instance *instance,
unsigned int offset, unsigned short val);
void ps3_reg_write_u64(struct ps3_instance *instance, unsigned long long val,
void *reg);
unsigned long long ps3_reg_read_u64(struct ps3_instance *instance, void *reg);
void __iomem *ps3_reg_set_ioremap(struct pci_dev *pdev, unsigned long reg_bar);
#endif

View File

@ -0,0 +1,407 @@
// SPDX-License-Identifier: GPL-2.0
#include "ps3_platform_utils.h"
#include "ps3_instance_manager.h"
#include "ps3_mgr_channel.h"
#include "ps3_driver_log.h"
#ifndef _WINDOWS
#include <linux/vmalloc.h>
#endif
#include "ps3_kernel_version.h"
#ifdef _WINDOWS
int ps3_dma_free(struct ps3_instance *instance, size_t length, void *buffer)
{
int ret = PS3_SUCCESS;
unsigned long status;
if (buffer == NULL || length == 0) {
ret = -PS3_FAILED;
goto l_out;
}
status = StorPortFreeContiguousMemorySpecifyCache(instance, buffer,
length, MmCached);
if (status != STOR_STATUS_SUCCESS)
ret = -PS3_FAILED;
l_out:
return ret;
}
int ps3_dma_alloc(struct ps3_instance *instance, size_t length, void **buffer,
unsigned long long *phy_addr)
{
int ret = PS3_SUCCESS;
unsigned long len;
unsigned long status;
PHYSICAL_ADDRESS minPhysicalAddress;
PHYSICAL_ADDRESS maxPhysicalAddress;
PHYSICAL_ADDRESS boundaryPhysicalAddress;
STOR_PHYSICAL_ADDRESS PhysicalAddress;
minPhysicalAddress.QuadPart = 0;
maxPhysicalAddress.QuadPart = 0xFFFFFFFFFFFF;
boundaryPhysicalAddress.QuadPart = 0;
status = StorPortAllocateContiguousMemorySpecifyCacheNode(
instance, length, minPhysicalAddress, maxPhysicalAddress,
boundaryPhysicalAddress, MmCached, MM_ANY_NODE_OK, buffer);
if (status != STOR_STATUS_SUCCESS) {
LOG_ERROR("alloc dma buffer failed, length:%d, status:0x%x\n",
length, status);
ret = -PS3_FAILED;
goto l_out;
}
PhysicalAddress =
StorPortGetPhysicalAddress(instance, NULL, *buffer, &len);
*phy_addr = (unsigned long long)PhysicalAddress.QuadPart;
if (PhysicalAddress.QuadPart == 0) {
LOG_ERROR("dma buffer remap fail\n");
ps3_dma_free(instance, length, *buffer);
*buffer = NULL;
ret = -PS3_FAILED;
}
l_out:
return ret;
}
#endif
void *ps3_kcalloc(struct ps3_instance *instance, unsigned int blocks,
unsigned int block_size)
{
void *ret = NULL;
#ifndef _WINDOWS
(void)instance;
ret = kcalloc(blocks, block_size, GFP_KERNEL);
#else
unsigned long status = StorPortAllocatePool(
instance, blocks * block_size, 'd3sp', &ret);
if (status != STOR_STATUS_SUCCESS) {
LOG_ERROR("host_no:%d, memory alloc failed, status0x%x\n",
PS3_HOST(instance), status);
ret = NULL;
} else {
memset(ret, 0, blocks * block_size);
}
#endif
if (ret == NULL) {
LOG_ERROR("host_no:%u, memory:%u %u alloc failed\n",
PS3_HOST(instance), blocks, block_size);
}
return ret;
}
void ps3_kfree(struct ps3_instance *instance, void *buffer)
{
#ifndef _WINDOWS
(void)instance;
if (buffer != NULL)
kfree(buffer);
#else
unsigned long status = StorPortFreePool(instance, buffer);
if (status != STOR_STATUS_SUCCESS) {
LOG_ERROR("host_no:%u, memory free failed, status0x%x\n",
PS3_HOST(instance), status);
}
#endif
}
void *ps3_kzalloc(struct ps3_instance *instance, unsigned int size)
{
return ps3_kcalloc(instance, 1, size);
}
void ps3_vfree(struct ps3_instance *instance, void *buffer)
{
#ifndef _WINDOWS
(void)instance;
vfree(buffer);
#else
unsigned long status = StorPortFreePool(instance, buffer);
if (status != STOR_STATUS_SUCCESS) {
LOG_ERROR("host_no:%u, memory free failed, status0x%x\n",
PS3_HOST(instance), status);
}
#endif
}
void *ps3_vzalloc(struct ps3_instance *instance, unsigned int size)
{
void *ret = NULL;
#ifndef _WINDOWS
(void)instance;
ret = vzalloc(size);
#else
unsigned long status =
StorPortAllocatePool(instance, size, 'd3sp', &ret);
if (status != STOR_STATUS_SUCCESS) {
LOG_ERROR("host_no:%d, memory alloc failed, status0x%x\n",
PS3_HOST(instance), status);
ret = NULL;
} else {
memset(ret, 0, size);
}
#endif
if (ret == NULL) {
LOG_ERROR("host_no:%u, memory:%u alloc failed\n",
PS3_HOST(instance), size);
}
return ret;
}
int ps3_wait_for_completion_timeout(void *sync_done, unsigned long time_out)
{
int ret = PS3_SUCCESS;
#ifdef _WINDOWS
NTSTATUS wait_ret = STATUS_SUCCESS;
LARGE_INTEGER win_timeout = { 0 };
if (time_out > 0) {
win_timeout.QuadPart = (long long)(time_out * (-10000000LL));
wait_ret = KeWaitForSingleObject(
sync_done, Executive, KernelMode, FALSE, &win_timeout);
} else {
wait_ret = KeWaitForSingleObject(sync_done, Executive,
KernelMode, FALSE, NULL);
}
if (wait_ret == STATUS_TIMEOUT)
ret = -PS3_TIMEOUT;
#else
unsigned short timeout = 0;
if (time_out > 0) {
timeout = wait_for_completion_timeout(
(struct completion *)sync_done, time_out * HZ);
if (timeout == 0)
ret = -PS3_TIMEOUT;
} else {
wait_for_completion((struct completion *)sync_done);
}
#endif
return ret;
}
int ps3_wait_cmd_for_completion_timeout(struct ps3_instance *instance,
struct ps3_cmd *cmd,
unsigned long timeout)
{
int ret = PS3_SUCCESS;
unsigned long time_out;
#ifdef _WINDOWS
(void)instance;
time_out = max_t(unsigned long, cmd->time_out, timeout);
ret = ps3_wait_for_completion_timeout(&cmd->sync_done, time_out);
#else
if (cmd->time_out == 0 && cmd->is_interrupt) {
ps3_wait_cmd_for_completion_interrupt(instance, cmd);
} else {
time_out = max_t(unsigned long, cmd->time_out, timeout);
ret = ps3_wait_for_completion_timeout(&cmd->sync_done,
time_out);
}
#endif
return ret;
}
int ps3_scsi_device_get(struct ps3_instance *instance, struct scsi_device *sdev)
{
#ifdef _WINDOWS
return ps3_scsi_device_get_win(instance, sdev);
#else
(void)instance;
return scsi_device_get(sdev);
#endif
}
void ps3_scsi_device_put(struct ps3_instance *instance,
struct scsi_device *sdev)
{
#ifdef _WINDOWS
ps3_scsi_device_put_win(instance, sdev);
#else
(void)instance;
scsi_device_put(sdev);
#endif
}
#ifndef _WINDOWS
#if defined(PS3_SCSI_DEVICE_LOOKUP)
struct scsi_device *__ps3_scsi_device_lookup_check(struct Scsi_Host *shost,
unsigned int channel,
unsigned int id,
unsigned int lun)
{
struct scsi_device *sdev = NULL;
list_for_each_entry(sdev, &shost->__devices, siblings) {
if (sdev->sdev_state == SDEV_DEL)
continue;
if (sdev->channel == channel && sdev->id == id &&
sdev->lun == lun)
return sdev;
}
return NULL;
}
struct scsi_device *ps3_scsi_device_lookup_check(struct Scsi_Host *shost,
unsigned int channel,
unsigned int id,
unsigned int lun)
{
struct scsi_device *sdev = NULL;
unsigned long flags = 0;
spin_lock_irqsave(shost->host_lock, flags);
sdev = __ps3_scsi_device_lookup_check(shost, channel, id, lun);
if (sdev && scsi_device_get(sdev))
sdev = NULL;
spin_unlock_irqrestore(shost->host_lock, flags);
return sdev;
}
#endif
#endif
struct scsi_device *ps3_scsi_device_lookup(struct ps3_instance *instance,
unsigned char channel,
unsigned short target_id,
unsigned char lun)
{
#ifdef _WINDOWS
(void)lun;
struct scsi_device *sdev = ps3_scsi_device_lookup_win(
instance, channel, (unsigned char)target_id);
if (sdev != NULL && sdev->unit_start == 1)
return sdev;
return NULL;
#else
#if defined(PS3_SCSI_DEVICE_LOOKUP)
return ps3_scsi_device_lookup_check(instance->host, channel, target_id,
lun);
#else
return scsi_device_lookup(instance->host, channel, target_id, lun);
#endif
#endif
}
void ps3_scsi_remove_device(struct ps3_instance *instance,
struct scsi_device *sdev)
{
#ifdef _WINDOWS
ps3_scsi_remove_device_win(instance, sdev);
#else
(void)instance;
scsi_remove_device(sdev);
#endif
}
int ps3_scsi_add_device(struct ps3_instance *instance, unsigned char channel,
unsigned short target_id, unsigned char lun)
{
#ifdef _WINDOWS
(void)lun;
return ps3_scsi_add_device_win(instance, channel,
(unsigned char)target_id);
#else
return scsi_add_device(instance->host, channel, target_id, lun);
#endif
}
unsigned long long ps3_now_ms_get(void)
{
#ifdef _WINDOWS
LARGE_INTEGER timestamp;
KeQuerySystemTime(&timestamp);
return timestamp.QuadPart / 10000;
#else
return ktime_to_ms(ktime_get_real());
#endif
}
unsigned long long ps3_1970_now_ms_get(void)
{
#ifdef _WINDOWS
unsigned long long timestamp;
LARGE_INTEGER timestamp1970;
TIME_FIELDS timefiled;
timefiled.Year = 1970;
timefiled.Month = 1;
timefiled.Day = 1;
timefiled.Hour = 0;
timefiled.Minute = 0;
timefiled.Second = 0;
timefiled.Milliseconds = 0;
RtlTimeFieldsToTime(&timefiled, &timestamp1970);
timestamp = ps3_now_ms_get();
return timestamp - (timestamp1970.QuadPart / 10000);
#else
return ps3_now_ms_get();
#endif
}
#ifdef _WINDOWS
int ps3_now_format_get(char *buff, int buf_len)
{
#ifdef _WINDOWS
LARGE_INTEGER timestamp;
KeQuerySystemTime(&timestamp);
LARGE_INTEGER localtime;
TIME_FIELDS timefiled;
ExSystemTimeToLocalTime(&timestamp, &localtime);
RtlTimeToTimeFields(&localtime, &timefiled);
return snprintf(buff, buf_len, "%04ld-%02d-%02d_%02d:%02d:%02d.%03d",
timefiled.Year, timefiled.Month, timefiled.Day,
timefiled.Hour, timefiled.Minute, timefiled.Second,
timefiled.Milliseconds);
#else
struct timeval tv;
struct tm td;
do_gettimeofday(&tv);
time_to_tm(tv.tv_sec, -sys_tz.tz_minuteswest * 60, &td);
return snprintf(buff, buf_len, "%04ld-%02d-%02d_%02d:%02d:%02d",
td.tm_year + 1900, td.tm_mon + 1, td.tm_mday,
td.tm_hour, td.tm_min, td.tm_sec);
#endif
}
#endif
unsigned long long ps3_tick_count_get(void)
{
#ifdef _WINDOWS
LARGE_INTEGER tick_count;
LARGE_INTEGER tick_frequency;
tick_count = KeQueryPerformanceCounter(&tick_frequency);
return (unsigned long long)(tick_count.QuadPart * 1000000 /
tick_frequency.QuadPart);
#else
return (unsigned long long)ktime_to_us(ktime_get_real());
#endif
}

View File

@ -0,0 +1,525 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef _PS3_PLATFORM_UTILS_H_
#define _PS3_PLATFORM_UTILS_H_
#ifdef _WINDOWS
#include "ps3_def.h"
#else
#include <linux/mutex.h>
#include <linux/atomic.h>
#include <linux/spinlock.h>
#include <linux/delay.h>
#include "linux/kernel.h"
#endif
#include "ps3_err_def.h"
struct ps3_instance;
struct scsi_device;
struct ps3_cmd;
#define scsi_cmnd_cdb(scmnd) ((scmnd)->cmnd)
#define scsi_device_private_data(scmnd) (PS3_SDEV_PRI_DATA((scmnd)->device))
#ifdef _WINDOWS
#define scsi_host_data(scmnd) ((struct ps3_instance *)((scmnd)->instance))
#else
#define scsi_host_data(scmnd) \
((struct ps3_instance *)((scmnd)->device->host->hostdata))
#endif
#ifdef _WINDOWS
#define ps3_container_of(ptr, type, member) \
((type *)((char *)ptr - offsetof(type, member)))
#else
#define ps3_container_of container_of
#endif
#define MAX_MDELAY (1)
#ifndef PS3_FALSE
#define PS3_FALSE (0)
#endif
#ifndef PS3_TRUE
#define PS3_TRUE (1)
#endif
#ifndef PS3_MAX
#define PS3_MAX(a, b) (((a) > (b)) ? (a) : (b))
#endif
#ifndef PS3_MIN
#define PS3_MIN(a, b) (((a) < (b)) ? (a) : (b))
#endif
#ifndef PS3_DESC
#define PS3_DESC(a) 1
#endif
static inline void ps3_mutex_init(struct mutex *mutex_lock)
{
#ifdef _WINDOWS
ExInitializeFastMutex(&mutex_lock->mutex);
#else
mutex_init(mutex_lock);
#endif
}
static inline void ps3_mutex_destroy(struct mutex *mutex_lock)
{
#ifdef _WINDOWS
(void)mutex_lock;
#else
mutex_destroy(mutex_lock);
#endif
}
static inline int ps3_mutex_lock(struct mutex *mtx_lock)
{
#ifdef _WINDOWS
if (KeGetCurrentIrql() <= APC_LEVEL) {
ExAcquireFastMutex(&mtx_lock->mutex);
return PS3_SUCCESS;
}
return -PS3_FAILED;
#else
mutex_lock(mtx_lock);
return PS3_SUCCESS;
#endif
}
static inline int ps3_mutex_trylock(struct mutex *mutex_lock)
{
int ret = PS3_SUCCESS;
#ifdef _WINDOWS
if (KeGetCurrentIrql() > APC_LEVEL) {
ret = -PS3_FAILED;
goto l_out;
}
if (!ExTryToAcquireFastMutex(&mutex_lock->mutex)) {
ret = -PS3_FAILED;
goto l_out;
}
l_out:
#else
ret = mutex_trylock(mutex_lock);
#endif
return ret;
}
static inline int ps3_mutex_unlock(struct mutex *mutex_lock)
{
#ifdef _WINDOWS
if (KeGetCurrentIrql() <= APC_LEVEL) {
ExReleaseFastMutex(&mutex_lock->mutex);
return PS3_SUCCESS;
}
return -PS3_FAILED;
#else
mutex_unlock(mutex_lock);
return PS3_SUCCESS;
#endif
}
static inline int ps3_atomic_read(atomic_t *value)
{
#ifdef _WINDOWS
return value->value;
#else
return atomic_read(value);
#endif
}
static inline int ps3_atomic_dec(atomic_t *value)
{
#ifdef _WINDOWS
return (int)InterlockedDecrement((LONG *)(&value->value));
#else
atomic_dec(value);
return PS3_SUCCESS;
#endif
}
static inline int ps3_atomic_add(int i, atomic_t *value)
{
#ifdef _WINDOWS
return (int)_InlineInterlockedAdd((LONG *)&value->value, (LONG)i);
#else
atomic_add(i, value);
return PS3_SUCCESS;
#endif
}
static inline int ps3_atomic_sub(int i, atomic_t *value)
{
#ifdef _WINDOWS
return (int)_InlineInterlockedAdd((LONG *)&value->value, (LONG)-i);
#else
atomic_sub(i, value);
return PS3_SUCCESS;
#endif
}
static inline int ps3_atomic_cmpxchg(atomic_t *value, int old, int cur)
{
#ifdef _WINDOWS
return (int)InterlockedCompareExchange((LONG *)&value->value, (LONG)cur,
(LONG)old);
#else
return atomic_cmpxchg(value, cur, old);
#endif
}
static inline unsigned char ps3_atomic_add_unless(atomic_t *value, int a, int u)
{
#ifdef _WINDOWS
int c = 0;
int old = 0;
c = value->value;
while (c != u && (old = ps3_atomic_cmpxchg(value, c, c + a)) != c)
c = old;
return c != u;
#else
return atomic_add_unless(value, a, u);
#endif
}
static inline int ps3_atomic_inc(atomic_t *value)
{
#ifdef _WINDOWS
return (int)InterlockedIncrement((LONG *)(&value->value));
#else
atomic_inc(value);
return PS3_SUCCESS;
#endif
}
static inline int ps3_atomic_inc_return(atomic_t *value)
{
#ifdef _WINDOWS
return (int)InterlockedIncrement((LONG *)(&value->value));
#else
return atomic_inc_return(value);
#endif
}
static inline int ps3_atomic_dec_return(atomic_t *value)
{
#ifdef _WINDOWS
return (int)InterlockedDecrement((LONG *)(&value->value));
#else
return atomic_dec_return(value);
#endif
}
static inline long long ps3_atomic64_inc(atomic64_t *value)
{
#ifdef _WINDOWS
return (long long)InterlockedIncrement64((LONG64 *)(&value->value));
#else
atomic64_inc(value);
return PS3_SUCCESS;
#endif
}
static inline long long ps3_atomic64_inc_return(atomic64_t *value)
{
#ifdef _WINDOWS
return (long long)InterlockedIncrement64((LONG64 *)(&value->value));
#else
return atomic64_inc_return(value);
#endif
}
static inline long long ps3_atomic64_read(atomic64_t *value)
{
#ifdef _WINDOWS
return value->value;
#else
return atomic64_read(value);
#endif
}
static inline void ps3_atomic64_set(atomic64_t *value, long long i)
{
#ifdef _WINDOWS
value->value = i;
#else
atomic64_set(value, i);
#endif
}
static inline void ps3_atomic_set(atomic_t *value, int i)
{
#ifdef _WINDOWS
value->value = i;
#else
atomic_set(value, i);
#endif
}
static inline long long ps3_atomic64_add(long long i, atomic64_t *value)
{
#ifdef _WINDOWS
return (long long)_InlineInterlockedAdd64((LONG64 *)&value->value,
(LONG64)i);
#else
atomic64_add(i, value);
return PS3_SUCCESS;
#endif
}
static inline long long ps3_atomic64_dec(atomic64_t *value)
{
#ifdef _WINDOWS
return (long long)InterlockedDecrement64((LONG64 *)&value->value);
#else
atomic64_dec(value);
return PS3_SUCCESS;
#endif
}
static inline void ps3_spin_lock_init(spinlock_t *lock)
{
#ifdef _WINDOWS
KeInitializeSpinLock(&lock->lock);
#else
spin_lock_init(lock);
#endif
}
static inline void ps3_spin_lock(spinlock_t *lock, unsigned long *flag)
{
#ifdef _WINDOWS
KeAcquireSpinLock(&lock->lock, (PKIRQL)flag);
#else
(void)flag;
spin_lock(lock);
#endif
}
static inline void ps3_spin_lock_irqsave(spinlock_t *lock, unsigned long *flag)
{
#ifdef _WINDOWS
KeAcquireSpinLock(&lock->lock, (PKIRQL)flag);
#else
spin_lock_irqsave(lock, *flag);
#endif
}
static inline void ps3_spin_unlock(spinlock_t *lock, unsigned long flag)
{
#ifdef _WINDOWS
KeReleaseSpinLock(&lock->lock, (KIRQL)flag);
#else
(void)flag;
spin_unlock(lock);
#endif
}
static inline void ps3_spin_unlock_irqrestore(spinlock_t *lock,
unsigned long flag)
{
#ifdef _WINDOWS
KeReleaseSpinLock(&lock->lock, (KIRQL)flag);
#else
spin_unlock_irqrestore(lock, flag);
#endif
}
int ps3_wait_for_completion_timeout(void *sync_done, unsigned long Timeout);
int ps3_wait_cmd_for_completion_timeout(struct ps3_instance *instance,
struct ps3_cmd *cmd,
unsigned long timeout);
#ifdef _WINDOWS
#define complete(x) KeSetEvent(x, IO_NO_INCREMENT, FALSE)
#define init_completion(x) KeInitializeEvent(x, SynchronizationEvent, FALSE)
static inline int list_empty(const struct list_head *head)
{
return head->Blink == head;
}
#define list_entry(ptr, type, member) CONTAINING_RECORD(ptr, type, member)
#define list_for_each(pos, head) \
for (pos = (head)->Blink; pos != (head); pos = pos->Blink)
#define list_first_entry(ptr, type, member) \
list_entry((ptr)->Blink, type, member)
#define list_next_entry(pos, type, member) \
list_entry((pos)->member.Blink, type, member)
#define list_for_each_entry(pos, type, head, member) \
for (pos = list_first_entry(head, type, member); \
&pos->member != (head); pos = list_next_entry(pos, type, member))
#define list_for_each_entry_safe(pos, type, tmp, head, member) \
for (pos = list_first_entry(head, type, member), \
tmp = list_next_entry(pos, type, member); \
&pos->member != (head); \
pos = tmp, tmp = list_next_entry(tmp, type, member))
static inline void INIT_LIST_HEAD(struct list_head *list)
{
InitializeListHead((PLIST_ENTRY)list);
}
static inline void list_del(struct list_head *entry)
{
RemoveEntryList((PLIST_ENTRY)entry);
}
static inline void list_del_init(struct list_head *entry)
{
list_del(entry);
INIT_LIST_HEAD(entry);
}
static inline void list_add_tail(struct list_head *entry,
struct list_head *head)
{
InsertTailList((PLIST_ENTRY)head, (PLIST_ENTRY)entry);
}
static inline struct list_head *list_remove_head(struct list_head *head)
{
return (struct list_head *)RemoveHeadList((PLIST_ENTRY)head);
}
inline int kstrtou16(const char *s, unsigned int base, unsigned short *res)
{
unsigned long tmp = 0;
int ret = RtlCharToInteger(s, base, &tmp);
if (ret != STATUS_SUCCESS)
goto l_out;
if (tmp != (unsigned long long)(unsigned short)tmp) {
ret = -34;
goto l_out;
}
*res = (unsigned short)tmp;
l_out:
return ret;
}
inline int kstrtoint(const char *s, unsigned int base, int *res)
{
unsigned long tmp = 0;
int ret = RtlCharToInteger(s, base, &tmp);
if (ret != STATUS_SUCCESS)
goto l_out;
if (tmp != (unsigned long long)(int)tmp) {
ret = -34;
goto l_out;
}
*res = (int)tmp;
l_out:
return ret;
}
inline int kstrtouint(const char *s, unsigned int base, unsigned int *res)
{
unsigned long tmp = 0;
int ret = RtlCharToInteger(s, base, &tmp);
if (ret != STATUS_SUCCESS)
goto l_out;
if (tmp != (unsigned long long)(unsigned int)tmp) {
ret = -34;
goto l_out;
}
*res = (unsigned int)tmp;
l_out:
return ret;
}
inline int kstrtou64(const char *s, unsigned long long base,
unsigned long long *res)
{
unsigned long tmp = 0;
int ret = RtlCharToInteger(s, base, &tmp);
if (ret != STATUS_SUCCESS)
goto l_out;
if (tmp != (unsigned long long)tmp) {
ret = -34;
goto l_out;
}
*res = (unsigned long)tmp;
l_out:
return ret;
}
int ps3_dma_free(struct ps3_instance *instance, size_t length, void *buffer);
int ps3_dma_alloc(struct ps3_instance *instance, size_t length, void **buffer,
unsigned long long *phy_addr);
#endif
static inline void ps3_msleep(unsigned int ms)
{
#ifdef _WINDOWS
StorPortStallExecution((unsigned long)ms * 1000);
#else
msleep(ms);
#endif
}
static inline void ps3_mdelay(unsigned int ms)
{
#ifndef _WINDOWS
unsigned int count = (ms / MAX_MDELAY);
unsigned int remain = (ms % MAX_MDELAY);
do {
udelay(1000 * MAX_MDELAY);
count--;
} while (count);
if (remain != 0)
udelay(remain * 1000);
#else
StorPortStallExecution((unsigned long)ms * 1000);
#endif
}
void *ps3_kcalloc(struct ps3_instance *instance, unsigned int blocks,
unsigned int block_size);
void ps3_kfree(struct ps3_instance *instance, void *buffer);
void *ps3_kzalloc(struct ps3_instance *instance, unsigned int size);
void ps3_vfree(struct ps3_instance *instance, void *buffer);
void *ps3_vzalloc(struct ps3_instance *instance, unsigned int size);
int ps3_scsi_device_get(struct ps3_instance *instance,
struct scsi_device *sdev);
void ps3_scsi_device_put(struct ps3_instance *instance,
struct scsi_device *sdev);
struct scsi_device *ps3_scsi_device_lookup(struct ps3_instance *instance,
unsigned char channel,
unsigned short target_id,
unsigned char lun);
void ps3_scsi_remove_device(struct ps3_instance *instance,
struct scsi_device *sdev);
int ps3_scsi_add_device(struct ps3_instance *instance, unsigned char channel,
unsigned short target_id, unsigned char lun);
unsigned long long ps3_now_ms_get(void);
#ifdef _WINDOWS
int ps3_now_format_get(char *buff, int buf_len);
#endif
unsigned long long ps3_1970_now_ms_get(void);
unsigned long long ps3_tick_count_get(void);
#endif

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,303 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef _PS3_QOS_H_
#define _PS3_QOS_H_
#include "ps3_platform_utils.h"
#include "ps3_htp.h"
#include "ps3_cmd_channel.h"
#include "ps3_kernel_version.h"
#define QOS_HIGH_PRI_EXCLUSIVE_CMD_COUNT 32
#define QOS_MGR_EXCLUSIVE_CMD_COUNT 64
#define PS3_QOS_DEFAULT_PD_QUOTA 40
#define PS3_QOS_SAS_PD_QUOTA 125
#define PS3_QOS_NVME_MEMBER_QUOTA 127
#define PS3_QOS_NVME_DIRECT_QUOTA 127
#define PS3_QOS_HBA_NVME_NORMAL_QUOTA 126
#define PS3_QOS_RAID_NVME_NORMAL_QUOTA 252
#define PS3_QOS_FUNC1_JBOD_VD_QUOTA 768
#define PS3_QOS_VD_EXCLUSIVE_CMD_COUNT 40
#define PS3_QOS_JBOD_EXCLUSIVE_CMD_COUNT 128
#define PS3_QOS_POLL_INTERVAL 2
#define PS3_QOS_WAITQ_TIMEOUT 5
#define PS3_QOS_HBA_MAX_CMD 944
#define PS3_QOS_CS_FUNC0_SHARE_CMD 80
#define PS3_QOS_CS_FUNC0_JBOD_VD_QUOTA 80
#define PS3_QOS_NOTIFY_CMD_COUNT 32
#define PS3_QOS_FUNC0_PD_WORKQ_COUNT 1
#define PS3_QOS_FUNC1_PD_WORKQ_COUNT 4
#define PS3_QOS_POLL_CMD_COUNT 16
#define PS3_CMD_NEED_QOS(cmd) \
((cmd)->cmd_word.direct == PS3_CMDWORD_DIRECT_NORMAL || \
(cmd)->cmd_word.direct == PS3_CMDWORD_DIRECT_ADVICE)
#define PS3_QOS_INITED(instance) ((instance)->qos_context.inited)
enum ps3_qos_fifo_type {
PS3_QOS_CMDQ_0,
PS3_QOS_CMDQ_1,
PS3_QOS_CMDQ_2,
PS3_QOS_CMDQ_3,
PS3_QOS_MGRQ,
PS3_QOS_TFIFO,
PS3_QOS_FIFO_TYPE_MAX
};
enum ps3_qos_cmd_flag {
PS3_QOS_CMD_INIT = 0,
PS3_QOS_CMD_IN_PD,
PS3_QOS_CMD_IN_VD,
PS3_QOS_CMD_IN_FRAME,
PS3_QOS_CMD_IN_MGR,
PS3_QOS_CMD_IN_CMDQ0,
PS3_QOS_CMD_IN_CMDQ1,
PS3_QOS_CMD_IN_CMDQ2,
PS3_QOS_CMD_IN_CMDQ3
};
enum ps3_qos_quota_adjust_flag {
PS3_QOS_QUOTA_ADJUST_DEFULAT = 0,
PS3_QOS_QUOTA_ADJUST_QFULL,
PS3_QOS_QUOTA_ADJUST_UP,
PS3_QOS_QUOTA_ADJUST_INVALID
};
enum ps3_qos_vd_change_type {
PS3_QOS_VD_TYPE_CHANGE_TO_HDD,
PS3_QOS_VD_TYPE_CHANGE_TO_SSD,
PS3_QOS_VD_TYPE_CHANGE_INVALID
};
struct qos_wait_queue {
struct list_head wait_list;
unsigned int count;
unsigned short id;
spinlock_t *rsc_lock;
int *free_rsc;
atomic_t *used_rsc;
unsigned int *total_waited_cnt;
unsigned short can_resend;
unsigned short has_resend;
unsigned long last_sched_jiffies;
};
struct ps3_qos_vd_mgr {
unsigned char valid;
unsigned short id;
unsigned char workq_id;
atomic_t vd_quota;
spinlock_t rsc_lock;
struct qos_wait_queue vd_quota_wait_q;
atomic_t exclusive_cmd_cnt;
atomic_t share_cmd_used;
struct PS3VDEntry *vd_entry;
struct ps3_instance *instance;
struct work_struct resend_work;
unsigned long long last_sched_jiffies;
};
struct ps3_qos_pd_mgr {
atomic_t valid;
unsigned char workq_id;
unsigned char dev_type;
unsigned char clearing;
unsigned short disk_id;
unsigned short vd_id;
int pd_quota;
atomic_t pd_used_quota;
struct ps3_instance *instance;
struct work_struct resend_work;
unsigned long long last_sched_jiffies;
struct qos_wait_queue *waitqs;
unsigned short waitq_cnt;
unsigned int total_wait_cmd_cnt;
spinlock_t rc_lock;
unsigned short poll_que_id;
unsigned short poll_start_que_id;
unsigned short poll_cmd_cnt;
spinlock_t direct_rsc_lock;
int direct_quota;
atomic_t direct_used_quota;
unsigned int total_waited_direct_cmd;
atomic_t processing_cnt;
spinlock_t adjust_quota_lock;
int adjust_max_quota;
int adjust_min_quota;
int pd_init_quota;
};
struct ps3_qos_pd_context {
struct ps3_qos_pd_mgr *qos_pd_mgrs;
struct workqueue_struct **work_queues;
unsigned short sas_sata_hdd_quota;
unsigned short sas_sata_ssd_quota;
unsigned short nvme_normal_quota;
unsigned short nvme_direct_quota;
atomic_t workq_id_cnt;
unsigned char workq_count;
};
struct ps3_qos_vd_context {
struct ps3_qos_vd_mgr *qos_vd_mgrs;
struct workqueue_struct **work_queues;
unsigned short jbod_exclusive_cnt;
unsigned short vd_exclusive_cnt;
unsigned char workq_count;
unsigned char inited;
};
struct ps3_qos_tg_context {
unsigned int share;
unsigned int mgr_exclusive_cnt;
unsigned short high_pri_exclusive_cnt;
atomic_t mgr_free_cnt;
atomic_t mgr_share_used;
atomic_t share_free_cnt;
struct qos_wait_queue mgr_cmd_wait_q;
struct qos_wait_queue *vd_cmd_waitqs;
unsigned int total_wait_cmd_cnt;
unsigned char poll_vd_id;
spinlock_t lock;
struct ps3_instance *instance;
struct workqueue_struct *work_queue;
struct work_struct resend_work;
unsigned long long last_sched_jiffies;
};
struct ps3_qos_ops {
int (*qos_init)(struct ps3_instance *instance);
void (*qos_exit)(struct ps3_instance *instance);
void (*qos_vd_init)(struct ps3_instance *instance,
struct PS3VDEntry *vd_entry);
void (*qos_vd_reset)(struct ps3_instance *instance,
unsigned short disk_id);
unsigned char (*qos_decision)(struct ps3_cmd *cmd);
void (*qos_cmd_update)(struct ps3_cmd *cmd);
void (*qos_waitq_notify)(struct ps3_instance *instance);
unsigned char (*qos_pd_resend_check)(struct ps3_cmd *cmd);
unsigned char (*qos_waitq_abort)(struct ps3_cmd *cmd);
void (*qos_vd_clean)(struct ps3_instance *instance,
struct ps3_scsi_priv_data *pri_data, int ret_code);
void (*qos_pd_clean)(struct ps3_instance *instance,
struct ps3_scsi_priv_data *priv_data,
int ret_code);
void (*qos_waitq_clear)(struct ps3_instance *instance, int ret_code);
void (*qos_waitq_poll)(struct ps3_instance *instance);
void (*qos_reset)(struct ps3_instance *instance);
};
int ps3_hba_qos_init(struct ps3_instance *instance);
void ps3_hba_qos_exit(struct ps3_instance *instance);
void ps3_qos_vd_init(struct ps3_instance *instance,
struct PS3VDEntry *vd_entry);
void ps3_qos_vd_reset(struct ps3_instance *instance, unsigned short disk_id);
struct ps3_qos_pd_mgr *ps3_qos_pd_mgr_init(struct ps3_instance *instance,
struct ps3_pd_entry *pd_entry);
void ps3_qos_pd_mgr_reset(struct ps3_instance *instance, unsigned short pd_id);
void ps3_qos_vd_member_change(struct ps3_instance *instance,
struct ps3_pd_entry *pd_entry,
struct scsi_device *sdev,
unsigned char is_vd_member);
int ps3_qos_decision(struct ps3_cmd *cmd);
void ps3_qos_cmd_update(struct ps3_instance *instance, struct ps3_cmd *cmd);
void ps3_qos_waitq_notify(struct ps3_instance *instance);
unsigned char ps3_qos_waitq_abort(struct ps3_cmd *aborted_cmd);
void ps3_qos_device_clean(struct ps3_instance *instance,
struct ps3_scsi_priv_data *pri_data, int ret_code);
void ps3_qos_disk_del(struct ps3_instance *instance,
struct ps3_scsi_priv_data *priv_data);
void ps3_qos_vd_member_del(struct ps3_instance *instance,
struct PS3DiskDevPos *dev_pos);
void ps3_qos_hard_reset(struct ps3_instance *instance);
void ps3_qos_waitq_clear_all(struct ps3_instance *instance, int resp_status);
void ps3_qos_waitq_poll(struct ps3_instance *instance);
void ps3_qos_close(struct ps3_instance *instance);
void ps3_qos_open(struct ps3_instance *instance);
void ps3_hba_qos_prepare(struct ps3_instance *instance);
void ps3_raid_qos_prepare(struct ps3_instance *instance);
#define PS3_QOS_CMDQ_COUNT 4
#define PS3_QOS_CMDQ_DEPTH 4096
#define PS3_QOS_MGRQ_DEPTH 1024
#define PS3_QOS_HIGH_PRI_MGR_CMD_COUNT 32
struct ps3_qos_softq_mgr {
unsigned short id;
struct ps3_instance *instance;
spinlock_t rc_lock;
atomic_t free_cnt;
struct qos_wait_queue *waitqs;
unsigned short waitq_cnt;
unsigned int total_wait_cmd_cnt;
struct workqueue_struct *work_queue;
struct work_struct resend_work;
unsigned long long last_sched_jiffies;
unsigned short poll_cmd_cnt;
unsigned short poll_que_id;
};
struct ps3_qos_cq_context {
struct ps3_qos_softq_mgr mgrq;
struct ps3_qos_softq_mgr *cmdqs;
unsigned char cmdq_cnt;
unsigned int mgrq_depth;
unsigned int cmdq_depth;
};
struct ps3_qos_context {
struct ps3_qos_ops opts;
struct ps3_qos_pd_context pd_ctx;
struct ps3_qos_vd_context vd_ctx;
struct ps3_qos_tg_context tg_ctx;
struct ps3_qos_cq_context cq_ctx;
unsigned short max_vd_count;
unsigned short max_pd_count;
unsigned char poll_count;
unsigned char qos_switch;
unsigned char inited;
};
int ps3_raid_qos_init(struct ps3_instance *instance);
void ps3_raid_qos_exit(struct ps3_instance *instance);
int ps3_qos_init(struct ps3_instance *instance);
void ps3_qos_exit(struct ps3_instance *instance);
void ps3_qos_adjust_pd_rsc(struct scsi_device *sdev,
struct ps3_instance *instance, int reason);
void ps3_qos_vd_attr_change(struct ps3_instance *instance,
struct PS3VDEntry *vd_entry_old,
struct PS3VDEntry *vd_entry);
void ps3_qos_pd_rsc_init(struct ps3_qos_pd_mgr *qos_pd_mgr,
struct ps3_pd_entry *pd_entry);
#if defined(PS3_SUPPORT_LINX80)
void ps3_linx80_vd_member_change(struct ps3_instance *instance,
struct ps3_pd_entry *pd_entry);
#endif
#endif

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,62 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef __PS3_R1X_WRITE_LOCK_H__
#define __PS3_R1X_WRITE_LOCK_H__
#include "ps3_cmd_channel.h"
enum {
PS3_R1X_HASHBIT_LOCK = 0,
PS3_R1X_HASHRANGE_LOCK = 1,
};
extern unsigned int g_ps3_r1x_lock_flag;
extern unsigned int g_ps3_r1x_lock_enable;
unsigned int ps3_r1x_get_node_Buff_size(void);
static inline int ps3_r1x_write_lock(struct ps3_r1x_lock_mgr *mgr,
struct ps3_cmd *cmd)
{
if (mgr->hash_mgr == NULL)
return PS3_SUCCESS;
if (g_ps3_r1x_lock_enable == 0)
return PS3_SUCCESS;
if (!cmd->io_attr.is_confilct_check)
return PS3_SUCCESS;
if (cmd->is_inserted_c_q == 0)
return mgr->try_lock(mgr, cmd);
else
return mgr->resend_try_lock(mgr, cmd);
}
static inline void ps3_r1x_write_unlock(struct ps3_r1x_lock_mgr *mgr,
struct ps3_cmd *cmd)
{
if (cmd->szblock_cnt == 0)
return;
mgr->unlock(mgr, cmd);
cmd->szblock_cnt = 0;
}
int ps3_r1x_lock_prepare_for_vd(struct ps3_instance *instance,
struct scsi_device *sdev,
unsigned char raid_level);
void ps3_r1x_lock_destroy_for_vd(struct ps3_instance *instance,
struct ps3_r1x_lock_mgr *mgr);
void ps3_r1x_conflict_queue_clean(struct ps3_scsi_priv_data *pri_data,
int ret_code);
unsigned char ps3_r1x_conflict_queue_abort(struct ps3_cmd *cmd,
struct scsi_cmnd *scmd);
void ps3_r1x_conflict_queue_target_reset(struct ps3_instance *instance,
unsigned short target_id);
void ps3_r1x_conflict_queue_clean_all(struct ps3_instance *instance,
int ret_code, unsigned char is_remove);
#endif

View File

@ -0,0 +1,588 @@
// SPDX-License-Identifier: GPL-2.0
#include "ps3_rb_tree.h"
static void rbtNodeSetParent(struct Ps3RbNode *pNode, struct Ps3RbNode *pParent)
{
pNode->pParentColor =
((pNode->pParentColor & 3ULL) | ((uintptr_t)(void *)pParent));
}
static void rbtNodeSetColor(struct Ps3RbNode *pNode, unsigned int color)
{
pNode->pParentColor = ((pNode->pParentColor & ~1ULL) | color);
}
static void rbtRotateLeft(struct Ps3RbRoot *pRoot, struct Ps3RbNode *pNode)
{
struct Ps3RbNode *pRight = pNode->pRight;
struct Ps3RbNode *pParent = RBT_PARENT(pNode);
pNode->pRight = pRight->pLeft;
if (pNode->pRight != NULL)
rbtNodeSetParent(pRight->pLeft, pNode);
pRight->pLeft = pNode;
rbtNodeSetParent(pRight, pParent);
if (pParent != NULL) {
if (pNode == pParent->pLeft)
pParent->pLeft = pRight;
else
pParent->pRight = pRight;
} else {
pRoot->pRoot = pRight;
}
rbtNodeSetParent(pNode, pRight);
}
static void rbtRotateRight(struct Ps3RbRoot *pRoot, struct Ps3RbNode *pNode)
{
struct Ps3RbNode *pLeft = pNode->pLeft;
struct Ps3RbNode *pParent = RBT_PARENT(pNode);
pNode->pLeft = pLeft->pRight;
if (pNode->pLeft != NULL)
rbtNodeSetParent(pLeft->pRight, pNode);
pLeft->pRight = pNode;
rbtNodeSetParent(pLeft, pParent);
if (pParent != NULL) {
if (pNode == pParent->pRight)
pParent->pRight = pLeft;
else
pParent->pLeft = pLeft;
} else {
pRoot->pRoot = pLeft;
}
rbtNodeSetParent(pNode, pLeft);
}
static void rbtColorAfterDel(struct Ps3RbRoot *pRoot, struct Ps3RbNode *pNode,
struct Ps3RbNode *pParent)
{
struct Ps3RbNode *pOther = NULL;
struct Ps3RbNode *pOLeft = NULL;
struct Ps3RbNode *pORight = NULL;
while (((pNode == NULL) || RBT_IS_BLACK(pNode)) &&
(pNode != pRoot->pRoot)) {
if (pParent->pLeft == pNode) {
pOther = pParent->pRight;
if (RBT_IS_RED(pOther)) {
RBT_SET_BLACK(pOther);
RBT_SET_RED(pParent);
rbtRotateLeft(pRoot, pParent);
pOther = pParent->pRight;
}
if (((pOther->pLeft == NULL) ||
RBT_IS_BLACK(pOther->pLeft)) &&
((pOther->pRight == NULL) ||
RBT_IS_BLACK(pOther->pRight))) {
RBT_SET_RED(pOther);
pNode = pParent;
pParent = RBT_PARENT(pNode);
continue;
}
if ((pOther->pRight == NULL) ||
RBT_IS_BLACK(pOther->pRight)) {
pOLeft = pOther->pLeft;
if (pOLeft != NULL)
RBT_SET_BLACK(pOLeft);
RBT_SET_RED(pOther);
rbtRotateRight(pRoot, pOther);
pOther = pParent->pRight;
}
rbtNodeSetColor(pOther, RBT_COLOR(pParent));
RBT_SET_BLACK(pParent);
if (pOther->pRight != NULL)
RBT_SET_BLACK(pOther->pRight);
rbtRotateLeft(pRoot, pParent);
pNode = pRoot->pRoot;
break;
}
pOther = pParent->pLeft;
if (RBT_IS_RED(pOther)) {
RBT_SET_BLACK(pOther);
RBT_SET_RED(pParent);
rbtRotateRight(pRoot, pParent);
pOther = pParent->pLeft;
}
if (((pOther->pLeft == NULL) || RBT_IS_BLACK(pOther->pLeft)) &&
((pOther->pRight == NULL) ||
RBT_IS_BLACK(pOther->pRight))) {
RBT_SET_RED(pOther);
pNode = pParent;
pParent = RBT_PARENT(pNode);
continue;
}
if ((pOther->pLeft == NULL) || RBT_IS_BLACK(pOther->pLeft)) {
pORight = pOther->pRight;
if (pORight != NULL)
RBT_SET_BLACK(pORight);
RBT_SET_RED(pOther);
rbtRotateLeft(pRoot, pOther);
pOther = pParent->pLeft;
}
rbtNodeSetColor(pOther, RBT_COLOR(pParent));
RBT_SET_BLACK(pParent);
if (pOther->pLeft != NULL)
RBT_SET_BLACK(pOther->pLeft);
rbtRotateRight(pRoot, pParent);
pNode = pRoot->pRoot;
break;
}
if (pNode != NULL)
RBT_SET_BLACK(pNode);
}
void rbtDelNodeDo(struct Ps3RbRoot *pRoot, struct Ps3RbNode *pNode)
{
struct Ps3RbNode *pParent = NULL;
struct Ps3RbNode *pChild = NULL;
struct Ps3RbNode *pOld = NULL;
unsigned int color = 0;
if (pNode->pLeft == NULL) {
pChild = pNode->pRight;
} else if (pNode->pRight == NULL) {
pChild = pNode->pLeft;
} else {
pOld = pNode;
pNode = pNode->pRight;
while (pNode->pLeft != NULL)
pNode = pNode->pLeft;
pChild = pNode->pRight;
pParent = RBT_PARENT(pNode);
color = RBT_COLOR(pNode);
if (pChild != NULL)
rbtNodeSetParent(pChild, pParent);
if (pParent == pOld) {
pParent->pRight = pChild;
pParent = pNode;
} else {
pParent->pLeft = pChild;
}
pNode->pParentColor = pOld->pParentColor;
pNode->pRight = pOld->pRight;
pNode->pLeft = pOld->pLeft;
if (RBT_PARENT(pOld) != NULL) {
if (RBT_PARENT(pOld)->pLeft == pOld)
RBT_PARENT(pOld)->pLeft = pNode;
else
RBT_PARENT(pOld)->pRight = pNode;
} else {
pRoot->pRoot = pNode;
}
rbtNodeSetParent(pOld->pLeft, pNode);
if (pOld->pRight != NULL)
rbtNodeSetParent(pOld->pRight, pNode);
goto l_color;
}
pParent = RBT_PARENT(pNode);
color = RBT_COLOR(pNode);
if (pChild != NULL)
rbtNodeSetParent(pChild, pParent);
if (pParent != NULL) {
if (pParent->pLeft == pNode)
pParent->pLeft = pChild;
else
pParent->pRight = pChild;
} else {
pRoot->pRoot = pChild;
}
l_color:
if (color == RBT_BLACK)
rbtColorAfterDel(pRoot, pChild, pParent);
}
static struct Ps3RbNode *rbtFindNodeDo(struct Ps3RbRoot *pRoot, void *pKey,
struct Ps3RbTreeOps *pOps,
unsigned char intent_addnode,
struct Ps3RbNode **ppParent,
struct Ps3RbNode ***pppLinker)
{
struct Ps3RbNode *pNode = NULL;
struct Ps3RbNode *pParent = NULL;
struct Ps3RbNode **ppLinker = NULL;
void *pKeyCur = NULL;
enum Ps3Cmp cmprc = PS3_EQ;
BUG_ON(pOps->cmpkey == NULL);
BUG_ON((pOps->getkey == NULL) &&
(!testBitNonAtomic(RBTBF_KEYOFFSET_ENABLE,
(unsigned long *)&pOps->flags)));
ppLinker = &pRoot->pRoot;
while (NULL != (*ppLinker)) {
pParent = (*ppLinker);
pKeyCur = ps3RbNodeGetKey(pParent, pOps);
cmprc = pOps->cmpkey(pKey, pKeyCur);
if (cmprc == PS3_LT) {
ppLinker = &pParent->pLeft;
} else if (cmprc == PS3_GT) {
ppLinker = &pParent->pRight;
} else if ((intent_addnode == PS3_TRUE) &&
testBitNonAtomic(
RBTBF_CONFLICT_ENABLE,
(unsigned long *)&pOps->flags)) {
ppLinker = &pParent->pLeft;
} else {
pNode = pParent;
break;
}
}
if (pppLinker != NULL)
(*pppLinker) = ppLinker;
if (ppParent != NULL) {
if (pNode != NULL)
(*ppParent) = RBT_PARENT(pNode);
else
(*ppParent) = pParent;
}
return pNode;
}
void ps3RbtColorAfterAdd(struct Ps3RbRoot *pRoot, struct Ps3RbNode *pNode)
{
struct Ps3RbNode *pGparent = NULL;
struct Ps3RbNode *pParent = NULL;
struct Ps3RbNode *pUncle = NULL;
struct Ps3RbNode *pTmp = NULL;
while (1) {
pParent = RBT_PARENT(pNode);
if ((pParent == NULL) || RBT_IS_BLACK(pParent))
break;
pGparent = RBT_PARENT(pParent);
if (pParent == pGparent->pLeft) {
pUncle = pGparent->pRight;
if ((pUncle != NULL) && RBT_IS_RED(pUncle)) {
RBT_SET_BLACK(pUncle);
RBT_SET_BLACK(pParent);
RBT_SET_RED(pGparent);
pNode = pGparent;
continue;
}
if (pParent->pRight == pNode) {
rbtRotateLeft(pRoot, pParent);
pTmp = pParent;
pParent = pNode;
pNode = pTmp;
}
RBT_SET_BLACK(pParent);
RBT_SET_RED(pGparent);
rbtRotateRight(pRoot, pGparent);
} else {
pUncle = pGparent->pLeft;
if ((pUncle != NULL) && RBT_IS_RED(pUncle)) {
RBT_SET_BLACK(pUncle);
RBT_SET_BLACK(pParent);
RBT_SET_RED(pGparent);
pNode = pGparent;
continue;
}
if (pParent->pLeft == pNode) {
rbtRotateRight(pRoot, pParent);
pTmp = pParent;
pParent = pNode;
pNode = pTmp;
}
RBT_SET_BLACK(pParent);
RBT_SET_RED(pGparent);
rbtRotateLeft(pRoot, pGparent);
}
}
RBT_SET_BLACK(pRoot->pRoot);
}
struct Ps3RbNode *ps3RbtHeadNode(struct Ps3RbRoot *pRoot)
{
struct Ps3RbNode *pNode = NULL;
pNode = pRoot->pRoot;
if (pNode == NULL)
goto end;
while (pNode->pLeft != NULL)
pNode = pNode->pLeft;
end:
return pNode;
}
struct Ps3RbNode *ps3RbtTailNode(struct Ps3RbRoot *pRoot)
{
struct Ps3RbNode *pNode = NULL;
pNode = pRoot->pRoot;
if (pNode == NULL)
goto end;
while (pNode->pRight != NULL)
pNode = pNode->pRight;
end:
return pNode;
}
struct Ps3RbNode *ps3RbtPrevNode(struct Ps3RbNode *pNode)
{
struct Ps3RbNode *pParent = NULL;
if (pNode == NULL)
goto end;
if (pNode->pLeft != NULL) {
pNode = pNode->pLeft;
while (pNode->pRight != NULL)
pNode = pNode->pRight;
return pNode;
}
while (1) {
pParent = RBT_PARENT(pNode);
if ((pParent == NULL) || (pNode != pParent->pLeft))
goto end;
pNode = pParent;
}
end:
return pParent;
}
struct Ps3RbNode *ps3RbtNextNode(struct Ps3RbNode *pNode)
{
struct Ps3RbNode *pParent = NULL;
if (pNode == NULL)
goto end;
if (pNode->pRight != NULL) {
pNode = pNode->pRight;
while (pNode->pLeft != NULL)
pNode = pNode->pLeft;
return pNode;
}
while (1) {
pParent = RBT_PARENT(pNode);
if ((pParent == NULL) || (pNode != pParent->pRight))
goto end;
pNode = pParent;
}
end:
return pParent;
}
void ps3RbtReplaceNode(struct Ps3RbRoot *pRoot, struct Ps3RbNode *pNew,
struct Ps3RbNode *pVictim)
{
struct Ps3RbNode *pParent = RBT_PARENT(pVictim);
if (pParent != NULL) {
if (pVictim == pParent->pLeft)
pParent->pLeft = pNew;
else
pParent->pRight = pNew;
} else {
pRoot->pRoot = pNew;
}
if (pVictim->pLeft != NULL)
rbtNodeSetParent(pVictim->pLeft, pNew);
if (pVictim->pRight != NULL)
rbtNodeSetParent(pVictim->pRight, pNew);
(*pNew) = (*pVictim);
}
int ps3RbtDelNode(struct Ps3RbRoot *pRoot, struct Ps3RbNode *pNode)
{
int rc = 0;
if (RBT_NODE_IS_EMPTY(pNode)) {
rc = -PS3_FAILED;
goto end;
}
rbtDelNodeDo(pRoot, pNode);
ps3RbNodeInit(pNode);
end:
return rc;
}
int ps3RbtAddNode(struct Ps3RbRoot *pRoot, struct Ps3RbNode *pNode,
struct Ps3RbTreeOps *pOps)
{
struct Ps3RbNode *pParent = NULL;
struct Ps3RbNode **ppLinker = NULL;
void *pKey = NULL;
int rc = 0;
BUG_ON((pOps->getkey == NULL) &&
(!testBitNonAtomic(RBTBF_KEYOFFSET_ENABLE,
(unsigned long *)&pOps->flags)));
if (!RBT_NODE_IS_EMPTY(pNode)) {
rc = -PS3_FAILED;
goto end;
}
pKey = ps3RbNodeGetKey(pNode, pOps);
if (NULL !=
rbtFindNodeDo(pRoot, pKey, pOps, PS3_TRUE, &pParent, &ppLinker)) {
rc = -PS3_FAILED;
goto end;
}
ps3RbNodeLink(pNode, pParent, ppLinker);
ps3RbtColorAfterAdd(pRoot, pNode);
end:
return rc;
}
struct Ps3RbNode *ps3RbtFindNode(struct Ps3RbRoot *pRoot, void *pKey,
struct Ps3RbTreeOps *pOps)
{
struct Ps3RbNode *pNode = NULL;
if (pKey == NULL) {
pNode = ps3RbtHeadNode(pRoot);
goto end;
}
pNode = rbtFindNodeDo(pRoot, pKey, pOps, PS3_FALSE, NULL, NULL);
end:
return pNode;
}
struct Ps3RbNode *ps3RbtFindNextNode(struct Ps3RbRoot *pRoot, void *pKey,
struct Ps3RbTreeOps *pOps)
{
struct Ps3RbNode *pNode = NULL;
struct Ps3RbNode *pParent = NULL;
struct Ps3RbNode **ppLinker = NULL;
void *pKeyCur = NULL;
if (pKey == NULL) {
pNode = ps3RbtHeadNode(pRoot);
goto end;
}
pNode = rbtFindNodeDo(pRoot, pKey, pOps, PS3_FALSE, &pParent,
&ppLinker);
if (pNode != NULL) {
pNode = ps3RbtNextNode(pNode);
if (!testBitNonAtomic(RBTBF_CONFLICT_ENABLE,
(unsigned long *)&pOps->flags)) {
goto end;
}
while (pNode != NULL) {
pKeyCur = ps3RbNodeGetKey(pNode, pOps);
if (pOps->cmpkey(pKey, pKeyCur) != PS3_EQ)
break;
pNode = ps3RbtNextNode(pNode);
}
goto end;
}
if (pParent == NULL)
goto end;
if (ppLinker == &pParent->pLeft) {
pNode = pParent;
goto end;
}
pNode = ps3RbtNextNode(pParent);
end:
return pNode;
}
void ps3RbtClean(struct Ps3RbRoot *pRoot)
{
struct Ps3RbNode *pNode = NULL;
pNode = ps3RbtHeadNode(pRoot);
while (pNode != NULL) {
(void)ps3RbtDelNode(pRoot, pNode);
pNode = ps3RbtHeadNode(pRoot);
}
}
int ps3RbtTraverse(struct Ps3RbRoot *pRoot,
int (*visit)(struct Ps3RbNode *pNode, void *pCtxt),
void *p_ctxt)
{
struct Ps3RbNode *pNode = NULL;
struct Ps3RbNode *pNext = NULL;
int rc = 0;
BUG_ON(visit == NULL);
RBT_FOR_EACH_SAFE(pNode, pNext, pRoot)
{
rc = visit(pNode, p_ctxt);
if (rc < 0)
goto end;
}
end:
return rc;
}

View File

@ -0,0 +1,325 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef __PS3_RBTREE_H__
#define __PS3_RBTREE_H__
#ifndef _WINDOWS
#include <linux/kernel.h>
#include <linux/version.h>
#include <linux/bitmap.h>
#endif
#include "ps3_driver_log.h"
#include "ps3_err_def.h"
static inline void setBitNonAtomic(unsigned int nr,
unsigned long *addr)
{
set_bit(nr, addr);
}
static inline void clearBitNonAtomic(unsigned int nr,
unsigned long *addr)
{
clear_bit(nr, addr);
}
static inline int testBitNonAtomic(unsigned int nr,
const unsigned long *addr)
{
return test_bit(nr, addr);
}
struct Ps3RbNode {
__aligned(8) unsigned long long pParentColor;
struct {
struct Ps3RbNode *pLeft;
struct Ps3RbNode *pRight;
};
};
struct Ps3RbRoot {
struct Ps3RbNode *pRoot;
};
#define PS3_RBROOT_INITNIL \
{ \
NULL \
}
enum Ps3Cmp {
PS3_EQ = 0,
PS3_GT = 1,
PS3_LT = 2,
PS3_CMPNR = 3,
};
enum Ps3RbtreebFlag {
RBTBF_KEYOFFSET_ENABLE = 0,
RBTBF_CONFLICT_ENABLE,
};
struct Ps3RbTreeOps {
enum Ps3Cmp (*cmpkey)(void *pKey1, void *pKey2);
union {
void *(*getkey)(struct Ps3RbNode *pNode, void *pCtxt);
unsigned long long keyoffset;
};
unsigned int flags;
void *pCtxt;
};
struct Ps3RbTree {
struct Ps3RbRoot root;
unsigned int nodenr;
struct Ps3RbTreeOps ops;
};
static inline void ps3RbNodeInit(struct Ps3RbNode *pNode)
{
pNode->pParentColor = ((uintptr_t)(void *)pNode);
}
static inline void ps3RbNodeLink(struct Ps3RbNode *pNode,
struct Ps3RbNode *pParent,
struct Ps3RbNode **ppLinker)
{
pNode->pParentColor = ((uintptr_t)(void *)pParent);
pNode->pLeft = NULL;
pNode->pRight = NULL;
(*ppLinker) = pNode;
}
static inline void *ps3RbNodeGetKey(struct Ps3RbNode *pNode,
struct Ps3RbTreeOps *pOps)
{
if (testBitNonAtomic(RBTBF_KEYOFFSET_ENABLE,
(unsigned long *)&pOps->flags)) {
return (void *)((unsigned char *)pNode + pOps->keyoffset);
}
return pOps->getkey(pNode, pOps->pCtxt);
}
static inline void ps3RbRootInit(struct Ps3RbRoot *pRoot)
{
pRoot->pRoot = NULL;
}
static inline void ps3RbRootFini(struct Ps3RbRoot *pRoot)
{
BUG_ON(pRoot->pRoot != NULL);
}
void ps3RbtColorAfterAdd(struct Ps3RbRoot *pRoot, struct Ps3RbNode *pNode);
struct Ps3RbNode *ps3RbtHeadNode(struct Ps3RbRoot *pRoot);
struct Ps3RbNode *ps3RbtTailNode(struct Ps3RbRoot *pRoot);
struct Ps3RbNode *ps3RbtPrevNode(struct Ps3RbNode *pNode);
struct Ps3RbNode *ps3RbtNextNode(struct Ps3RbNode *pNode);
void ps3RbtReplaceNode(struct Ps3RbRoot *pRoot, struct Ps3RbNode *pNew,
struct Ps3RbNode *pVictim);
int ps3RbtDelNode(struct Ps3RbRoot *pRoot, struct Ps3RbNode *pNode);
int ps3RbtAddNode(struct Ps3RbRoot *pRoot, struct Ps3RbNode *pNode,
struct Ps3RbTreeOps *pOps);
struct Ps3RbNode *ps3RbtFindNode(struct Ps3RbRoot *pRoot, void *pKey,
struct Ps3RbTreeOps *pOps);
struct Ps3RbNode *ps3RbtFindNextNode(struct Ps3RbRoot *pRoot, void *pKey,
struct Ps3RbTreeOps *pOps);
void ps3RbtClean(struct Ps3RbRoot *pRoot);
int ps3RbtTraverse(struct Ps3RbRoot *pRoot,
int (*visit)(struct Ps3RbNode *pNode, void *pCtxt),
void *pCtxt);
static inline unsigned char ps3RbtIsEmpty(struct Ps3RbRoot *pRoot)
{
return (unsigned char)(pRoot->pRoot == NULL);
}
static inline int ps3RbTreeInit(struct Ps3RbTree *pTree,
struct Ps3RbTreeOps *pOps)
{
int rc = 0;
ps3RbRootInit(&pTree->root);
pTree->nodenr = 0;
memset(&pTree->ops, 0, sizeof(struct Ps3RbTreeOps));
if (pOps != NULL)
pTree->ops = (*pOps);
return rc;
}
static inline int
ps3RbTreeInitGetKey(struct Ps3RbTree *pTree,
enum Ps3Cmp (*cmpkey)(void *pKey1, void *pKey2),
void *(*getkey)(struct Ps3RbNode *pNode, void *pCtxt),
void *pCtxt)
{
struct Ps3RbTreeOps ops;
memset(&ops, 0, sizeof(struct Ps3RbTreeOps));
ops.cmpkey = cmpkey;
ops.getkey = getkey;
ops.pCtxt = pCtxt;
return ps3RbTreeInit(pTree, &ops);
}
static inline int
ps3RbTreeInitKeyOffset(struct Ps3RbTree *pTree,
enum Ps3Cmp (*cmpkey)(void *pKey1, void *pKey2),
unsigned long long keyoffset, void *pCtxt)
{
struct Ps3RbTreeOps ops;
memset(&ops, 0, sizeof(struct Ps3RbTreeOps));
ops.cmpkey = cmpkey;
ops.keyoffset = keyoffset;
ops.pCtxt = pCtxt;
setBitNonAtomic(RBTBF_KEYOFFSET_ENABLE,
(unsigned long *)&ops.flags);
return ps3RbTreeInit(pTree, &ops);
}
static inline void ps3RbTreeFini(struct Ps3RbTree *pTree)
{
BUG_ON(pTree->nodenr != 0);
ps3RbRootFini(&pTree->root);
}
static inline struct Ps3RbNode *ps3RbTreeHeadNode(struct Ps3RbTree *pTree)
{
return ps3RbtHeadNode(&pTree->root);
}
static inline struct Ps3RbNode *ps3RbTreeTailNode(struct Ps3RbTree *pTree)
{
return ps3RbtTailNode(&pTree->root);
}
static inline struct Ps3RbNode *ps3RbTreePrevNode(struct Ps3RbNode *pNode)
{
return ps3RbtPrevNode(pNode);
}
static inline struct Ps3RbNode *ps3RbTreeNextNode(struct Ps3RbNode *pNode)
{
return ps3RbtNextNode(pNode);
}
static inline void ps3RbTreeReplaceNode(struct Ps3RbTree *pTree,
struct Ps3RbNode *pNew,
struct Ps3RbNode *pVictim)
{
ps3RbtReplaceNode(&pTree->root, pNew, pVictim);
}
static inline int ps3RbTreeDelNode(struct Ps3RbTree *pTree,
struct Ps3RbNode *pNode)
{
int rc = 0;
rc = ps3RbtDelNode(&pTree->root, pNode);
if (rc >= 0)
pTree->nodenr--;
return rc;
}
static inline int ps3RbTreeAddNode(struct Ps3RbTree *pTree,
struct Ps3RbNode *pNode)
{
int rc = 0;
rc = ps3RbtAddNode(&pTree->root, pNode, &pTree->ops);
if (rc >= 0)
pTree->nodenr++;
return rc;
}
static inline struct Ps3RbNode *ps3RbTreeFindNode(struct Ps3RbTree *pTree,
void *pKey)
{
return ps3RbtFindNode(&pTree->root, pKey, &pTree->ops);
}
static inline struct Ps3RbNode *ps3RbTreeFindNextNode(struct Ps3RbTree *pTree,
void *pKey)
{
return ps3RbtFindNextNode(&pTree->root, pKey, &pTree->ops);
}
static inline void ps3RbTreeClean(struct Ps3RbTree *pTree)
{
ps3RbtClean(&pTree->root);
pTree->nodenr = 0;
}
static inline int ps3RbTreeTraverse(struct Ps3RbTree *pTree,
int (*visit)(struct Ps3RbNode *pNode,
void *pCtxt),
void *pCtxt)
{
return ps3RbtTraverse(&pTree->root, visit, pCtxt);
}
static inline unsigned char ps3RbTreeIsEmpty(struct Ps3RbTree *pTree)
{
return (unsigned char)(pTree->root.pRoot == NULL);
}
static inline unsigned int ps3RbTreeNodeNr(struct Ps3RbTree *pTree)
{
return pTree->nodenr;
}
#define RBT_RED (0)
#define RBT_BLACK (1)
#define RBT_PARENT(_n) \
((struct Ps3RbNode *)(uintptr_t)((_n)->pParentColor & ~3ULL))
#define RBT_COLOR(_n) ((_n)->pParentColor & 1ULL)
#define RBT_IS_RED(_n) (!RBT_COLOR(_n))
#define RBT_IS_BLACK(_n) RBT_COLOR(_n)
#define RBT_SET_RED(_n) ((_n)->pParentColor &= ~1ULL)
#define RBT_SET_BLACK(_n) ((_n)->pParentColor |= 1ULL)
#define RBT_ROOT_IS_EMPTY(_r) ((_r)->pRoot == NULL)
#define RBT_TREE_IS_EMPTY(_t) RBT_ROOT_IS_EMPTY(&(_t)->root)
#define RBT_NODE_IS_EMPTY(_n) (RBT_PARENT(_n) == (_n))
#define RBT_NODE_CLEAR(_n) (ps3RbNodeInit(_n))
#define RBT_FOR_EACH(_p_node, _p_root) \
for (_p_node = ps3RbtHeadNode(_p_root); _p_node != NULL; \
_p_node = ps3RbtNextNode(_p_node))
#define RBT_FOR_EACH_SAFE(_p_node, _p_next, _p_root) \
for (_p_node = ps3RbtHeadNode(_p_root), \
_p_next = ps3RbtNextNode(_p_node); \
_p_node != NULL; \
_p_node = _p_next, _p_next = ps3RbtNextNode(_p_node))
#define RBTREE_FOR_EACH(_p_node, _p_tree) \
RBT_FOR_EACH((_p_node), &(_p_tree)->root)
#define RBTREE_FOR_EACH_SAFE(_p_node, _p_next, _p_tree) \
RBT_FOR_EACH_SAFE((_p_node), (_p_next), &(_p_tree)->root)
#endif

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,165 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef _PS3_RECOVERY_H_
#define _PS3_RECOVERY_H_
#ifndef _WINDOWS
#include <linux/mutex.h>
#include <linux/atomic.h>
#include <linux/workqueue.h>
#include <linux/irqreturn.h>
#else
#include "ps3_worker.h"
#endif
#include "ps3_platform_utils.h"
#include "ps3_inner_data.h"
#include "ps3_driver_log.h"
enum {
PS3_SOFT_RECOVERY_PROBE_PROCESS = 0,
PS3_SOFT_RECOVERY_SHALLOW = 1,
PS3_SOFT_RECOVERY_DEEP = 2,
PS3_SOFT_RECOVERY_IOC_RECOVERY = 3,
PS3_SOFT_RECOVERY_FINISH = 4,
PS3_HARD_RECOVERY_DECIDE = 5,
PS3_HARD_RECOVERY_SHALLOW = 6,
PS3_HARD_RECOVERY_FINISH = 7,
PS3_RESET_LOG_INTERVAL = 8,
};
enum {
PS3_HOST_RESET_INIT = 0,
PS3_HOST_RESET_START = 1,
PS3_HOST_RESET_HARD_RESET_DONE = 2,
};
enum {
PS3_PARALLEL_HARDRESET_STATE_INIT = 0,
PS3_PARALLEL_HARDRESET_STATE_PENDING,
PS3_PARALLEL_HARDRESET_STATE_CONTINUE,
};
#define PS3_PARALLEL_HARDRESET_STATE_WAIT_INIT_INTERVAL (5)
#define PS3_RECOVERY_CONTEXT_MAX_NUM (8)
#define PS3_RECOVERY_IRQ_NAME_MAX_LENGTH (48)
#define PS3_RECOVERY_WHILE_PRINT_REACH_TIME (10 * 1000)
enum {
PS3_HEARTBEAT_NULL = 0,
PS3_HEARTBEAT_HARDRESET_DECIDE = 1,
PS3_HEARTBEAT_HARDRESET_RECOVERY = 2,
PS3_HEARTBEAT_HARDRESET_RETRY = 3,
};
enum {
PS3_IOC_CANNOT_HARDRESET = 0,
PS3_IOC_CAN_HARDRESET = 1,
};
struct ps3_recovery_context {
struct mutex free_cmd_lock;
spinlock_t recovery_lock;
spinlock_t ps3_hardreset_lock;
unsigned int ioc_recovery_count;
unsigned char recovery_state;
unsigned char reserved1;
unsigned char host_reset_state;
unsigned char heartbeat_recovery;
#ifndef _WINDOWS
struct workqueue_struct *recovery_wq;
char recovery_wq_name[20];
struct work_struct recovery_work;
#else
struct ps3_worker recovery_work;
#endif
struct ps3_instance *instance[2];
struct ps3_instance *work_instance;
int recovery_result;
unsigned int hardreset_count;
unsigned char parall_hardreset_state;
unsigned char instance_change;
unsigned char reserved[6];
atomic_t hardreset_ref;
struct mutex ps3_watchdog_recovery_mutex;
};
#define PS3_IS_INTERRUPT_SOFT_RECOVERY(instance) \
(instance->recovery_context->recovery_state == PS3_HARD_RECOVERY_DECIDE)
#define PS3_IS_INSTANCE_NOT_LOAD_NORMAL(instance) \
(PS3_IS_INSTANCE_PROBE(instance) || \
PS3_IS_INSTANCE_REMOVE(instance) || \
PS3_IS_INSTANCE_SUSPEND_OR_RESUME(instance))
#define PS3_IS_INSTANCE_PROBE(instance) \
(!(instance)->state_machine.is_suspend && \
!((instance)->is_probe_finish || (instance)->is_probe_failed))
#define PS3_IS_INSTANCE_REMOVE(instance) \
(!(instance)->state_machine.is_suspend && \
((instance)->is_probe_finish || (instance)->is_probe_failed) && \
!(instance)->state_machine.is_load)
#define PS3_INSTANCE_ABNORMAL_FORCE_HARD_RECOVERY(instance) \
(PS3_IS_INSTANCE_NOT_LOAD_NORMAL(instance) || \
((instance)->peer_instance != NULL && \
PS3_IS_INSTANCE_NOT_LOAD_NORMAL((instance)->peer_instance)))
#define PS3_IS_INSTANCE_PROBE_INIT(instance) \
(!((instance)->is_probe_finish || (instance)->is_probe_failed) && \
!(instance)->state_machine.is_load)
#define PS3_IS_INSTANCE_SUSPEND_OR_RESUME(instance) \
(PS3_IS_INSTANCE_SUSPEND(instance) || PS3_IS_INSTANCE_RESUME(instance))
#define PS3_IS_INSTANCE_SUSPEND(instance) \
((instance)->state_machine.is_suspend && (instance)->is_suspend)
#define PS3_IS_INSTANCE_RESUME(instance) \
((instance)->state_machine.is_suspend && (instance)->is_resume)
int ps3_recovery_context_init(struct ps3_instance *instance);
void ps3_recovery_function_init(struct ps3_instance *instance);
void ps3_recovery_context_exit(struct ps3_instance *instance);
void ps3_recovery_clean(struct ps3_instance *instance);
void ps3_recovery_destroy(struct ps3_instance *instance);
int ps3_recovery_request(struct ps3_instance *instance);
int ps3_hard_recovery_request(struct ps3_instance *instance);
void ps3_scsi_cmd_force_stop(struct ps3_instance *instance);
void ps3_mgr_cmd_force_stop(struct ps3_instance *instance);
int ps3_recovery_cancel_work_sync(struct ps3_instance *instance);
#ifndef _WINDOWS
int ps3_hard_reset_to_ready_with_doorbell(struct ps3_instance *instance);
int ps3_init_fail_hard_reset_with_doorbell(struct ps3_instance *instance);
unsigned char ps3_is_need_hard_reset(struct ps3_instance *instance);
void ps3_recovery_work_queue_destroy(struct ps3_instance *instance);
#endif
int ps3_hardreset_handle_pre(struct ps3_instance *instance);
int ps3_hardreset_handle_wait_ready(struct ps3_instance *instance);
int ps3_hardreset_handle_init_running(struct ps3_instance *instance);
int ps3_hardreset_handle_post(struct ps3_instance *instance);
int ps3_hardreset_handle_finish(struct ps3_instance *instance);
int ps3_hardreset_handle_offline(struct ps3_instance *instance);
int ps3_softreset_handle_pre(struct ps3_instance *instance);
int ps3_softreset_handle_post(struct ps3_instance *instance);
int ps3_hard_recovery_request_with_retry(struct ps3_instance *instance);
int ps3_recovery_request_with_retry(struct ps3_instance *instance);
irqreturn_t ps3_recovery_irq_handler(int virq, void *dev_id);
int ps3_recovery_irq_start(struct ps3_instance *instance);
void ps3_cmd_force_stop(struct ps3_instance *instance);
#endif

View File

@ -0,0 +1,935 @@
// SPDX-License-Identifier: GPL-2.0
#ifndef _WINDOWS
#include <linux/compiler.h>
#include "ps3_sas_transport.h"
#include "ps3_mgr_channel.h"
#include "ps3_irq.h"
#include "ps3_mgr_cmd_err.h"
#include "ps3_mgr_cmd.h"
#include "ps3_driver_log.h"
#include "ps3_device_manager_sas.h"
static struct scsi_transport_template *ps3_sas_transport_template;
extern struct ps3_sas_node *
ps3_sas_find_node_by_sas_addr(struct ps3_instance *instance,
unsigned long long sas_addr);
struct scsi_transport_template *ps3_sas_transport_get(void)
{
return ps3_sas_transport_template;
}
static inline struct ps3_instance *phy_to_ps3_instance(struct sas_phy *phy)
{
struct Scsi_Host *s_host = dev_to_shost(phy->dev.parent);
return (struct ps3_instance *)s_host->hostdata;
}
static inline struct ps3_instance *rphy_to_ps3_instance(struct sas_rphy *rphy)
{
struct Scsi_Host *s_host = dev_to_shost(rphy->dev.parent);
return (struct ps3_instance *)s_host->hostdata;
}
static inline int ps3_sas_request_pre_check(struct ps3_instance *instance)
{
int ret = PS3_SUCCESS;
if (!instance->state_machine.is_load) {
LOG_WARN("hno:%u instance state not is_load\n",
PS3_HOST(instance));
ret = -EFAULT;
goto l_out;
}
if (!ps3_is_instance_state_normal(instance, PS3_TRUE)) {
ret = -EFAULT;
goto l_out;
}
if (ps3_pci_err_recovery_get(instance)) {
LOG_WARN("hno[%u] host in pci recovery\n", PS3_HOST(instance));
ret = -EFAULT;
goto l_out;
}
l_out:
return ret;
}
static inline int ps3_sas_smp_pre_check(struct ps3_instance *instance)
{
int ret = PS3_SUCCESS;
ret = ps3_sas_request_pre_check(instance);
if (ret != PS3_SUCCESS)
goto l_out;
LOG_INFO("hno:%u ready get semaphore\n", PS3_HOST(instance));
if (down_interruptible(
&instance->sas_dev_context.ps3_sas_smp_semaphore)) {
LOG_WARN("hno:%u smp concurrency full\n", PS3_HOST(instance));
ret = -EFAULT;
}
LOG_INFO("hno:%u got semaphore\n", PS3_HOST(instance));
l_out:
return ret;
}
static inline void ps3_sas_linkerror_reqframe_build(struct ps3_cmd *cmd,
struct sas_phy *phy,
unsigned char encl_id)
{
struct PS3MgrReqFrame *mgrReq = &cmd->req_frame->mgrReq;
mgrReq->reqHead.timeout = cmd->time_out;
mgrReq->reqHead.traceID = cmd->trace_id;
mgrReq->reqHead.cmdType = PS3_CMD_SAS_MANAGEMENT;
mgrReq->reqHead.cmdSubType = PS3_SAS_GET_LINK_ERR;
mgrReq->reqHead.cmdFrameID = cmd->index;
mgrReq->reqHead.control = 0;
mgrReq->syncFlag = 1;
mgrReq->timeout = 0;
mgrReq->sgeOffset = offsetof(struct PS3MgrReqFrame, sgl) >>
PS3_MGR_CMD_SGL_OFFSET_DWORD_SHIFT;
mgrReq->sgeCount = 1;
mgrReq->sgl[0].length = cpu_to_le32(sizeof(struct PS3LinkErrInfo));
mgrReq->sgl[0].addr = cpu_to_le64(cmd->ext_buf_phys);
mgrReq->sgl[0].lastSge = 1;
mgrReq->sgl[0].ext = 0;
mgrReq->value.sasMgr.sasAddr = cpu_to_le64(phy->identify.sas_address);
mgrReq->value.sasMgr.enclID = encl_id;
mgrReq->value.sasMgr.phyCount = 1;
mgrReq->value.sasMgr.startPhyID = phy->identify.phy_identifier;
}
int ps3_sas_linkerrors_get(struct sas_phy *phy)
{
int ret = 0;
int send_result = PS3_SUCCESS;
unsigned char encl_id = PS3_SAS_INVALID_ID;
struct ps3_cmd *cmd = NULL;
struct PS3LinkErrInfo *erroInfo = NULL;
struct ps3_instance *instance = phy_to_ps3_instance(phy);
ret = ps3_sas_smp_pre_check(instance);
if (ret != PS3_SUCCESS) {
ret = -ENXIO;
goto l_out;
}
encl_id = ps3_sas_encl_id_get(instance, phy->identify.sas_address);
if (encl_id == PS3_SAS_INVALID_ID) {
LOG_ERROR("hno:%u cannot foud PS3 node by sas_addr[%016llx]\n",
PS3_HOST(instance), phy->identify.sas_address);
ret = -EINVAL;
goto l_no_free_cmd;
}
ps3_atomic_inc(&instance->cmd_statistics.cmd_delivering);
if (ps3_sas_request_pre_check(instance) != PS3_SUCCESS) {
LOG_WARN_LIM(
"sas_addr[%016llx], hno:%u smp linkerror pre check NOK\n",
phy->identify.sas_address, PS3_HOST(instance));
ps3_atomic_dec(&instance->cmd_statistics.cmd_delivering);
ret = -ENXIO;
goto l_no_free_cmd;
}
cmd = ps3_mgr_cmd_alloc(instance);
if (cmd == NULL) {
LOG_WARN("hno:%u not get a cmd packet\n", PS3_HOST(instance));
ps3_atomic_dec(&instance->cmd_statistics.cmd_delivering);
ret = -ENOMEM;
goto l_no_free_cmd;
}
cmd->time_out = PS3_SAS_TIMEOUT_SEC;
cmd->is_interrupt = PS3_DRV_FALSE;
LOG_DEBUG(
"hno:%u trace_id[0x%llx] CFID [%u], sas_addr[%016llx] get mgr cmd succeed\n",
PS3_HOST(instance), cmd->trace_id, cmd->index,
phy->identify.sas_address);
ps3_sas_linkerror_reqframe_build(cmd, phy, encl_id);
ps3_mgr_cmd_word_build(cmd);
send_result = ps3_cmd_send_sync(instance, cmd);
ps3_atomic_dec(&instance->cmd_statistics.cmd_delivering);
if (send_result == PS3_SUCCESS)
send_result = ps3_cmd_wait_sync(instance, cmd);
ret = ps3_mgr_complete_proc(instance, cmd, send_result);
if (ret == -PS3_CMD_NO_RESP) {
LOG_ERROR("hno:%u %d respStatus NOK CFID[%d] respStatus[%d]\n",
PS3_HOST(cmd->instance), ret,
cmd->cmd_word.cmdFrameID, ps3_cmd_resp_status(cmd));
ret = -ETIMEDOUT;
goto l_no_free_cmd;
}
if (ret != PS3_SUCCESS) {
LOG_ERROR("hno:%u %d respStatus NOK CFID[%d] respStatus[%d]\n",
PS3_HOST(cmd->instance), ret,
cmd->cmd_word.cmdFrameID, ps3_cmd_resp_status(cmd));
ret = -EFAULT;
} else {
erroInfo = (struct PS3LinkErrInfo *)cmd->ext_buf;
phy->invalid_dword_count =
le32_to_cpu(erroInfo->invalidDwordCount);
phy->running_disparity_error_count =
le32_to_cpu(erroInfo->runningDisparityErrCount);
phy->loss_of_dword_sync_count =
le32_to_cpu(erroInfo->lossOfDwordSyncCount);
phy->phy_reset_problem_count =
le32_to_cpu(erroInfo->phyResetProblemCount);
ret = 0;
}
LOG_DEBUG("hno:%u trace_id[0x%llx] CFID [%u], end, ret[%d]\n",
PS3_HOST(instance), cmd->trace_id, cmd->index, ret);
ps3_mgr_cmd_free(instance, cmd);
l_no_free_cmd:
up(&instance->sas_dev_context.ps3_sas_smp_semaphore);
l_out:
return ret;
}
int ps3_sas_enclosure_identifier_get(struct sas_rphy *rphy, u64 *identifier)
{
int ret = 0;
struct ps3_instance *instance = rphy_to_ps3_instance(rphy);
*identifier = 0;
LOG_DEBUG(
"hno:%u ----1---ready get encl identifier sas_addr[%016llx]\n",
PS3_HOST(instance), rphy->identify.sas_address);
ret = ps3_sas_smp_pre_check(instance);
if (ret != PS3_SUCCESS) {
ret = -ENXIO;
goto l_out;
}
LOG_DEBUG("hno:%u ready get encl identifier sas_addr[%016llx]\n",
PS3_HOST(instance), rphy->identify.sas_address);
*identifier = ps3_sas_rphy_parent_sas_addr_get(
instance, rphy->identify.sas_address);
if (*identifier == PS3_SAS_INVALID_SAS_ADDR) {
ret = -ENXIO;
*identifier = 0;
}
up(&instance->sas_dev_context.ps3_sas_smp_semaphore);
l_out:
LOG_DEBUG(
"hno:%u end get encl identifier sas_addr[%016llx], identifier[%llu]\n",
PS3_HOST(instance), rphy->identify.sas_address, *identifier);
return ret;
}
int ps3_sas_bay_identifier_get(struct sas_rphy *rphy)
{
unsigned int solt_id = 0;
struct ps3_instance *instance = rphy_to_ps3_instance(rphy);
LOG_DEBUG("hno:%u ----1---ready get bay identifier sas_addr[%016llx]\n",
PS3_HOST(instance), rphy->identify.sas_address);
if (ps3_sas_smp_pre_check(instance) != PS3_SUCCESS) {
solt_id = -ENXIO;
goto l_out;
}
LOG_DEBUG("hno:%u ready get bay identifier sas_addr[%016llx]\n",
PS3_HOST(instance), rphy->identify.sas_address);
if (ps3_sas_rphy_slot_get(instance, rphy->identify.sas_address,
&solt_id) != PS3_SUCCESS) {
solt_id = -ENXIO;
}
up(&instance->sas_dev_context.ps3_sas_smp_semaphore);
l_out:
LOG_DEBUG(
"hno:%u end get bay identifier sas_addr[%016llx], slot_id[%d]\n",
PS3_HOST(instance), rphy->identify.sas_address, solt_id);
return solt_id;
}
static inline void ps3_sas_ctrl_reqframe_build(struct ps3_cmd *cmd,
struct sas_phy *phy,
enum PhyCtrl ctrl_code)
{
struct PS3MgrReqFrame *mgrReq = &cmd->req_frame->mgrReq;
mgrReq->reqHead.timeout = cmd->time_out;
mgrReq->reqHead.traceID = cmd->trace_id;
mgrReq->reqHead.cmdType = PS3_CMD_SAS_MANAGEMENT;
mgrReq->reqHead.cmdSubType = PS3_SAS_PHY_CTRL;
mgrReq->reqHead.cmdFrameID = cmd->index;
mgrReq->reqHead.control = 0;
mgrReq->syncFlag = 1;
mgrReq->timeout = 0;
mgrReq->sgeCount = 0;
mgrReq->value.phySet.sasAddr = cpu_to_le64(phy->identify.sas_address);
mgrReq->value.phySet.phyCtrl = ctrl_code;
mgrReq->value.phySet.phyID = phy->identify.phy_identifier;
mgrReq->value.phySet.maxLinkRate = phy->maximum_linkrate;
mgrReq->value.phySet.minLinkRate = phy->minimum_linkrate;
}
static inline int __ps3_sas_phy_ctrl(struct sas_phy *phy,
enum PhyCtrl ctrl_code)
{
int ret = PS3_SUCCESS;
int send_result = PS3_SUCCESS;
struct ps3_cmd *cmd = NULL;
struct ps3_instance *instance = phy_to_ps3_instance(phy);
ret = ps3_sas_smp_pre_check(instance);
if (ret != PS3_SUCCESS) {
ret = -ENXIO;
goto l_out;
}
ps3_atomic_inc(&instance->cmd_statistics.cmd_delivering);
if (ps3_sas_request_pre_check(instance) != PS3_SUCCESS) {
LOG_WARN_LIM(
"sas_addr[%016llx], hno:%u smp phyctrl pre check NOK\n",
phy->identify.sas_address, PS3_HOST(instance));
ps3_atomic_dec(&instance->cmd_statistics.cmd_delivering);
ret = -ENXIO;
goto l_no_free_cmd;
}
cmd = ps3_mgr_cmd_alloc(instance);
if (cmd == NULL) {
LOG_WARN("hno:%u not get a cmd packet\n", PS3_HOST(instance));
ps3_atomic_dec(&instance->cmd_statistics.cmd_delivering);
ret = -ENOMEM;
goto l_no_free_cmd;
}
cmd->time_out = PS3_SAS_TIMEOUT_SEC;
cmd->is_interrupt = PS3_DRV_FALSE;
LOG_DEBUG(
"hno:%u trace_id[0x%llx] CFID [%u], sas_addr[%016llx] ctrl_code[%s] get mgr cmd succeed\n",
PS3_HOST(instance), cmd->trace_id, cmd->index,
phy->identify.sas_address,
namePhyCtrl((enum PhyCtrl)ctrl_code));
ps3_sas_ctrl_reqframe_build(cmd, phy, ctrl_code);
ps3_mgr_cmd_word_build(cmd);
send_result = ps3_cmd_send_sync(instance, cmd);
ps3_atomic_dec(&instance->cmd_statistics.cmd_delivering);
if (send_result == PS3_SUCCESS)
send_result = ps3_cmd_wait_sync(instance, cmd);
ret = ps3_mgr_complete_proc(instance, cmd, send_result);
if (ret == -PS3_CMD_NO_RESP) {
LOG_ERROR("hno:%u %d respStatus NOK CFID[%d] respStatus[%d]\n",
PS3_HOST(cmd->instance), ret,
cmd->cmd_word.cmdFrameID, ps3_cmd_resp_status(cmd));
ret = -ETIMEDOUT;
goto l_no_free_cmd;
}
if (ret != PS3_SUCCESS) {
LOG_ERROR("hno:%u %d respStatus NOK CFID[%d] respStatus[%d]\n",
PS3_HOST(cmd->instance), ret,
cmd->cmd_word.cmdFrameID, ps3_cmd_resp_status(cmd));
ret = -EFAULT;
}
LOG_DEBUG("hno:%u trace_id[0x%llx] CFID [%u], end, ret[%d]\n",
PS3_HOST(instance), cmd->trace_id, cmd->index, ret);
ps3_mgr_cmd_free(instance, cmd);
l_no_free_cmd:
up(&instance->sas_dev_context.ps3_sas_smp_semaphore);
l_out:
return ret;
}
int ps3_sas_phy_reset(struct sas_phy *phy, int hard_reset)
{
int ret = PS3_SUCCESS;
enum PhyCtrl ctrl_code =
hard_reset ? PS3_SAS_CTRL_RESET_HARD : PS3_SAS_CTRL_RESET;
struct sas_phy *tmp_phy = kcalloc(1, sizeof(struct sas_phy), GFP_KERNEL);
if (tmp_phy == NULL) {
LOG_ERROR("kcalloc sas_phy fail!\n");
ret = -ENOMEM;
goto l_out;
}
memcpy(tmp_phy, phy, sizeof(struct sas_phy));
tmp_phy->maximum_linkrate = 0;
tmp_phy->minimum_linkrate = 0;
LOG_INFO("enter phy reset, phy sas_addr[%016llx], is_hard[%d]\n",
phy->identify.sas_address, hard_reset);
ret = __ps3_sas_phy_ctrl(tmp_phy, ctrl_code);
kfree(tmp_phy);
tmp_phy = NULL;
l_out:
return ret;
}
int ps3_sas_phy_enable(struct sas_phy *phy, int enable)
{
int ret = PS3_SUCCESS;
enum PhyCtrl ctrl_code =
enable ? PS3_SAS_CTRL_RESET : PS3_SAS_CTRL_DISABLE;
struct sas_phy *tmp_phy = kcalloc(1, sizeof(struct sas_phy), GFP_KERNEL);
if (tmp_phy == NULL) {
LOG_ERROR("kcalloc sas_phy fail!\n");
ret = -ENOMEM;
goto l_out;
}
memcpy(tmp_phy, phy, sizeof(struct sas_phy));
tmp_phy->maximum_linkrate = 0;
tmp_phy->minimum_linkrate = 0;
LOG_INFO("enter phy enable, phy sas_addr[%016llx], is_enable[%d]\n",
phy->identify.sas_address, enable);
ret = __ps3_sas_phy_ctrl(tmp_phy, ctrl_code);
kfree(tmp_phy);
tmp_phy = NULL;
l_out:
return ret;
}
int ps3_sas_update_phy_info(struct sas_phy *phy)
{
int ret = -PS3_FAILED;
struct PS3SasMgr sas_req_param;
struct ps3_instance *instance = phy_to_ps3_instance(phy);
struct PS3PhyInfo *phy_info =
instance->sas_dev_context.ps3_sas_phy_buff;
unsigned long flags = 0;
struct ps3_sas_node *sas_node = ps3_sas_find_node_by_sas_addr(
instance, phy->identify.sas_address);
memset(&sas_req_param, 0, sizeof(sas_req_param));
sas_req_param.enclID = sas_node->encl_id;
sas_req_param.sasAddr = cpu_to_le64(sas_node->sas_address);
sas_req_param.startPhyID = phy->identify.phy_identifier;
sas_req_param.phyCount = 1;
LOG_DEBUG("hno:%u ready get phys[%d] of encl_id[%d] !\n",
PS3_HOST(instance), phy->identify.phy_identifier,
sas_req_param.enclID);
memset(phy_info, 0, PS3_SAS_REQ_BUFF_LEN);
ret = ps3_sas_phy_get(instance, &sas_req_param);
if (ret != PS3_SUCCESS) {
LOG_ERROR("hno:%u get phy info NOK\n", PS3_HOST(instance));
goto l_out;
}
spin_lock_irqsave(&instance->sas_dev_context.ps3_sas_node_lock, flags);
LOG_INFO_IN_IRQ(instance,
"hno:%u ready update phy %d of encl_id[%d]!\n",
PS3_HOST(instance), phy->identify.phy_identifier,
sas_req_param.enclID);
ps3_sas_node_phy_update(instance,
&sas_node->phys[phy->identify.phy_identifier],
&phy_info[0]);
spin_unlock_irqrestore(&instance->sas_dev_context.ps3_sas_node_lock,
flags);
l_out:
return ret;
}
int ps3_sas_linkrates_set(struct sas_phy *phy, struct sas_phy_linkrates *rates)
{
int ret = PS3_SUCCESS;
unsigned char tmp_min = 0;
unsigned char tmp_max = 0;
LOG_INFO("enter link rate set, phy sas_addr[%016llx],\n"
"\tminimum_linkrate[%d], maximum_linkrate[%d]\n",
phy->identify.sas_address, rates->minimum_linkrate,
rates->maximum_linkrate);
if (!rates->minimum_linkrate)
rates->minimum_linkrate = phy->minimum_linkrate;
else if (rates->minimum_linkrate < phy->minimum_linkrate_hw)
rates->minimum_linkrate = phy->minimum_linkrate_hw;
if (!rates->maximum_linkrate)
rates->maximum_linkrate = phy->maximum_linkrate;
else if (rates->maximum_linkrate > phy->maximum_linkrate_hw)
rates->maximum_linkrate = phy->maximum_linkrate_hw;
if (rates->maximum_linkrate < phy->minimum_linkrate ||
rates->minimum_linkrate > phy->maximum_linkrate) {
LOG_ERROR(
"linkrate set param NOK, %d phy sas_addr[%016llx],\n"
"\trate minimum_linkrate[%d] > cur maximum_linkrate[%d] or\n"
"\trate maximum_linkrate[%d] < cur minimum_linkrate[%d]\n",
phy->identify.phy_identifier, phy->identify.sas_address,
rates->minimum_linkrate, phy->maximum_linkrate,
rates->maximum_linkrate, phy->minimum_linkrate);
ret = -EINVAL;
goto l_out;
}
tmp_min = phy->minimum_linkrate;
tmp_max = phy->maximum_linkrate;
phy->minimum_linkrate = rates->minimum_linkrate;
phy->maximum_linkrate = rates->maximum_linkrate;
ret = __ps3_sas_phy_ctrl(phy, PS3_SAS_CTRL_RESET);
if (ret != PS3_SUCCESS) {
LOG_ERROR("linkrate NOK, phy sas_addr[%016llx],\n"
"\tminimum_linkrate[%d], maximum_linkrate[%d]\n",
phy->identify.sas_address, rates->minimum_linkrate,
rates->maximum_linkrate);
phy->minimum_linkrate = tmp_min;
phy->maximum_linkrate = tmp_max;
goto l_out;
}
ps3_sas_update_phy_info(phy);
l_out:
return ret;
}
static inline void ps3_sas_smp_reqframe_build(struct ps3_cmd *cmd,
unsigned long long sas_addr,
unsigned int req_data_len)
{
struct PS3MgrReqFrame *mgrReq = &cmd->req_frame->mgrReq;
mgrReq->reqHead.timeout = cmd->time_out;
mgrReq->reqHead.traceID = cmd->trace_id;
mgrReq->reqHead.cmdType = PS3_CMD_SAS_MANAGEMENT;
mgrReq->reqHead.cmdSubType = PS3_SAS_SMP_REQUEST;
mgrReq->reqHead.cmdFrameID = cmd->index;
mgrReq->reqHead.control = 0;
mgrReq->syncFlag = 1;
mgrReq->timeout = 0;
mgrReq->sgeOffset = offsetof(struct PS3MgrReqFrame, sgl) >>
PS3_MGR_CMD_SGL_OFFSET_DWORD_SHIFT;
mgrReq->sgeCount = 1;
mgrReq->sgl[0].length =
cpu_to_le32(cmd->instance->cmd_context.ext_buf_size);
mgrReq->sgl[0].addr = cpu_to_le64(cmd->ext_buf_phys);
mgrReq->sgl[0].lastSge = 1;
mgrReq->sgl[0].ext = 0;
mgrReq->value.sasMgr.sasAddr = cpu_to_le64(sas_addr);
mgrReq->value.sasMgr.reqLen =
cpu_to_le16(req_data_len - PS3_SMP_CRC_LEN);
}
static inline void show_smp(unsigned char *data, unsigned short len)
{
unsigned short i = 0;
char tmp_buf[256] = { 0 };
char *p_tmp = tmp_buf;
LOG_DEBUG("smp frame data start\n");
while (len != 0) {
memset(tmp_buf, 0, sizeof(char) * 256);
for (i = 0; i < 32 && len != 0; i++, len--) {
snprintf(p_tmp, 4, " %02x", *data++);
p_tmp += 3;
}
LOG_DEBUG("smp frame data is ==[%s]==\n", tmp_buf);
p_tmp = tmp_buf;
}
LOG_DEBUG("smp frame data end\n");
}
#if defined(PS3_SAS_SMP_RETURN)
static inline unsigned int ps3_sas_req_to_ext_buf(struct ps3_instance *instance,
struct request *req,
void *ext_buf)
{
#if defined(PS3_SYPPORT_BIO_ITER)
struct bio_vec bvec;
struct bvec_iter iter;
#else
struct bio_vec *bvec = NULL;
unsigned int i = 0;
#endif
unsigned int req_len = 0;
if (unlikely(blk_rq_bytes(req) > instance->cmd_context.ext_buf_size)) {
LOG_ERROR(
"hno:%u request is too big!(req_len:%d > ext_buf_len:%d\n",
PS3_HOST(instance), blk_rq_bytes(req),
instance->cmd_context.ext_buf_size);
goto l_out;
}
#if defined(PS3_SYPPORT_BIO_ITER)
bio_for_each_segment(bvec, req->bio, iter) {
memcpy((unsigned char *)ext_buf + req_len,
page_address(bvec.bv_page) + bvec.bv_offset,
bvec.bv_len);
req_len += bvec.bv_len;
}
#else
bio_for_each_segment(bvec, req->bio, i) {
memcpy((unsigned char *)ext_buf + req_len,
page_address(bvec->bv_page) + bvec->bv_offset,
bvec->bv_len);
req_len += bvec->bv_len;
}
#endif
l_out:
return req_len;
}
static inline int ps3_sas_ext_buf_to_rsp(struct ps3_instance *instance,
struct request *req, void *ext_buf)
{
int ret = PS3_SUCCESS;
struct request *rsp = req->next_rq;
#if defined(PS3_SYPPORT_BIO_ITER)
struct bio_vec bvec;
struct bvec_iter iter;
#else
struct bio_vec *bvec = NULL;
unsigned int i = 0;
#endif
unsigned int offset = 0;
unsigned short rsq_data_len = 0;
unsigned short smp_len = 0;
if (rsp == NULL) {
ret = -PS3_FAILED;
LOG_ERROR("hno:%u rsp == NULL\n", PS3_HOST(instance));
goto l_out;
}
rsq_data_len =
min(blk_rq_bytes(rsp), instance->cmd_context.ext_buf_size);
smp_len = ((unsigned char *)ext_buf)[3] * 4 + 4;
rsp->resid_len -= smp_len;
LOG_DEBUG("hno:%u smp frame len[%d], rsq_data_len[%d]\n",
PS3_HOST(instance), smp_len, rsq_data_len);
rsq_data_len = min(smp_len, rsq_data_len);
show_smp((unsigned char *)ext_buf, rsq_data_len);
#if defined(PS3_SYPPORT_BIO_ITER)
bio_for_each_segment(bvec, rsp->bio, iter) {
if (rsq_data_len <= bvec.bv_len) {
memcpy(page_address(bvec.bv_page) + bvec.bv_offset,
(unsigned char *)ext_buf + offset, rsq_data_len);
break;
}
memcpy(page_address(bvec.bv_page) + bvec.bv_offset,
(unsigned char *)ext_buf + offset, bvec.bv_len);
rsq_data_len -= bvec.bv_len;
offset += bvec.bv_len;
}
#else
bio_for_each_segment(bvec, rsp->bio, i) {
if (rsq_data_len <= bvec->bv_len) {
memcpy(page_address(bvec->bv_page) + bvec->bv_offset,
(unsigned char *)ext_buf + offset, rsq_data_len);
break;
}
memcpy(page_address(bvec->bv_page) + bvec->bv_offset,
(unsigned char *)ext_buf + offset, bvec->bv_len);
rsq_data_len -= bvec->bv_len;
offset += bvec->bv_len;
}
#endif
l_out:
return ret;
}
int ps3_sas_smp_handler(struct Scsi_Host *shost, struct sas_rphy *rphy,
struct request *req)
{
int ret = -PS3_FAILED;
int send_result = PS3_SUCCESS;
struct ps3_instance *instance = (struct ps3_instance *)shost->hostdata;
struct ps3_cmd *cmd = NULL;
unsigned int req_data_len = 0;
unsigned long long sas_addr = 0;
struct ps3_sas_node *ps3_sas_node = NULL;
ret = ps3_sas_smp_pre_check(instance);
if (ret != PS3_SUCCESS) {
ret = -EFAULT;
goto l_out;
}
sas_addr = (rphy) ? (rphy->identify.sas_address) :
(instance->sas_dev_context.ps3_hba_sas.sas_address);
ps3_sas_node = ps3_sas_find_node_by_sas_addr(instance, sas_addr);
if (ps3_sas_node == NULL) {
LOG_ERROR("hno:%u cannot find node[%llx] !\n",
PS3_HOST(instance), sas_addr);
up(&instance->sas_dev_context.ps3_sas_smp_semaphore);
ret = -EFAULT;
goto l_out;
}
ps3_atomic_inc(&instance->cmd_statistics.cmd_delivering);
if (ps3_sas_request_pre_check(instance) != PS3_SUCCESS) {
LOG_WARN_LIM("sas_addr[%016llx], hno:%u smp pre check NOK\n",
sas_addr, PS3_HOST(instance));
ps3_atomic_dec(&instance->cmd_statistics.cmd_delivering);
ret = -EFAULT;
goto l_no_free_cmd;
}
cmd = ps3_mgr_cmd_alloc(instance);
if (cmd == NULL) {
LOG_WARN("hno:%u not get a cmd packet\n", PS3_HOST(instance));
ps3_atomic_dec(&instance->cmd_statistics.cmd_delivering);
ret = -ENOMEM;
goto l_no_free_cmd;
}
cmd->time_out = PS3_SAS_TIMEOUT_SEC;
cmd->is_interrupt = PS3_DRV_FALSE;
req_data_len = ps3_sas_req_to_ext_buf(instance, req, cmd->ext_buf);
if (req_data_len == 0) {
ret = -ENOMEM;
ps3_atomic_dec(&instance->cmd_statistics.cmd_delivering);
goto l_out_failed;
}
LOG_DEBUG(
"hno:%u trace_id[0x%llx] CFID [%u], sas_addr[%016llx], len[%u] send smp req\n",
PS3_HOST(instance), cmd->trace_id, cmd->index, sas_addr,
req_data_len);
ps3_sas_smp_reqframe_build(cmd, sas_addr, req_data_len);
ps3_mgr_cmd_word_build(cmd);
send_result = ps3_cmd_send_sync(instance, cmd);
ps3_atomic_dec(&instance->cmd_statistics.cmd_delivering);
if (send_result == PS3_SUCCESS)
send_result = ps3_cmd_wait_sync(instance, cmd);
ret = ps3_mgr_complete_proc(instance, cmd, send_result);
if (ret == -PS3_CMD_NO_RESP) {
LOG_ERROR("hno:%u %d respStatus NOK CFID[%d] respStatus[%d]\n",
PS3_HOST(cmd->instance), ret,
cmd->cmd_word.cmdFrameID, ps3_cmd_resp_status(cmd));
ret = -ETIMEDOUT;
goto l_no_free_cmd;
}
if (ret != PS3_SUCCESS) {
LOG_ERROR("hno:%u %d respStatus NOK CFID[%d] respStatus[%d]\n",
PS3_HOST(cmd->instance), ret,
cmd->cmd_word.cmdFrameID, ps3_cmd_resp_status(cmd));
ret = -ENXIO;
if (ret == -PS3_TIMEOUT)
ret = -ETIMEDOUT;
goto l_out_failed;
}
ret = ps3_sas_ext_buf_to_rsp(instance, req, cmd->ext_buf);
if (ret != PS3_SUCCESS) {
LOG_ERROR("hno:%u %d smp response NOK CFID[%d]\n",
PS3_HOST(cmd->instance), ret,
cmd->cmd_word.cmdFrameID);
ret = -EINVAL;
goto l_out_failed;
}
LOG_DEBUG("hno:%u trace_id[0x%llx] CFID [%u], end, ret[%d]\n",
PS3_HOST(instance), cmd->trace_id, cmd->index, ret);
l_out_failed:
ps3_mgr_cmd_free(instance, cmd);
l_no_free_cmd:
up(&instance->sas_dev_context.ps3_sas_smp_semaphore);
l_out:
return ret;
}
#else
static inline unsigned int ps3_sas_req_to_ext_buf(struct ps3_instance *instance,
struct bsg_buffer *req_buf,
void *ext_buf)
{
unsigned int req_len = 0;
if (unlikely(req_buf->payload_len >
instance->cmd_context.ext_buf_size)) {
LOG_ERROR(
"hno:%u request is too big!(req_len:%d > ext_buf_len:%d\n",
PS3_HOST(instance), req_buf->payload_len,
instance->cmd_context.ext_buf_size);
goto l_out;
}
req_len = sg_copy_to_buffer(req_buf->sg_list, req_buf->sg_cnt, ext_buf,
req_buf->payload_len);
l_out:
return req_len;
}
static inline unsigned int ps3_sas_ext_buf_to_rsp(struct ps3_instance *instance,
struct bsg_buffer *rsp_buf,
void *ext_buf)
{
unsigned short rsq_data_len = 0;
unsigned short smp_len = 0;
rsq_data_len =
min(rsp_buf->payload_len, instance->cmd_context.ext_buf_size);
smp_len = ((unsigned char *)ext_buf)[3] * 4 + 4;
LOG_DEBUG("hno:%u smp frame len[%d], rsq_data_len[%d]\n",
PS3_HOST(instance), smp_len, rsq_data_len);
rsq_data_len = min(smp_len, rsq_data_len);
show_smp((unsigned char *)ext_buf, rsq_data_len);
sg_copy_from_buffer(rsp_buf->sg_list, rsp_buf->sg_cnt, ext_buf,
rsp_buf->payload_len);
return rsq_data_len;
}
void ps3_sas_smp_handler(struct bsg_job *job, struct Scsi_Host *shost,
struct sas_rphy *rphy)
{
int ret = PS3_SUCCESS;
int send_result = PS3_SUCCESS;
struct ps3_instance *instance = (struct ps3_instance *)shost->hostdata;
struct ps3_cmd *cmd = NULL;
unsigned int req_data_len = 0;
unsigned int resp_len = 0;
unsigned long long sas_addr = 0;
struct ps3_sas_node *ps3_sas_node = NULL;
ret = ps3_sas_smp_pre_check(instance);
if (ret != PS3_SUCCESS) {
ret = -EFAULT;
goto l_out;
}
sas_addr = (rphy) ? (rphy->identify.sas_address) :
(instance->sas_dev_context.ps3_hba_sas.sas_address);
ps3_sas_node = ps3_sas_find_node_by_sas_addr(instance, sas_addr);
if (ps3_sas_node == NULL) {
LOG_ERROR("hno:%u cannot find node[%llx] !\n",
PS3_HOST(instance), sas_addr);
up(&instance->sas_dev_context.ps3_sas_smp_semaphore);
ret = -EFAULT;
goto l_out;
}
ps3_atomic_inc(&instance->cmd_statistics.cmd_delivering);
if (ps3_sas_request_pre_check(instance) != PS3_SUCCESS) {
LOG_WARN_LIM("sas_addr[%016llx], hno:%u smp pre check NOK\n",
sas_addr, PS3_HOST(instance));
ps3_atomic_dec(&instance->cmd_statistics.cmd_delivering);
ret = -EFAULT;
goto l_no_free_cmd;
}
cmd = ps3_mgr_cmd_alloc(instance);
if (cmd == NULL) {
LOG_WARN("hno:%u Failed to get a cmd packet\n",
PS3_HOST(instance));
ps3_atomic_dec(&instance->cmd_statistics.cmd_delivering);
ret = -ENOMEM;
goto l_no_free_cmd;
}
cmd->time_out = PS3_SAS_TIMEOUT_SEC;
cmd->is_interrupt = PS3_DRV_FALSE;
req_data_len = ps3_sas_req_to_ext_buf(instance, &job->request_payload,
cmd->ext_buf);
if (req_data_len == 0) {
ret = -ENOMEM;
ps3_atomic_dec(&instance->cmd_statistics.cmd_delivering);
goto l_out_failed;
}
LOG_DEBUG(
"hno:%u trace_id[0x%llx] CFID [%u], sas_addr[%016llx], len[%u] send smp req\n",
PS3_HOST(instance), cmd->trace_id, cmd->index, sas_addr,
req_data_len);
ps3_sas_smp_reqframe_build(cmd, sas_addr, req_data_len);
ps3_mgr_cmd_word_build(cmd);
send_result = ps3_cmd_send_sync(instance, cmd);
ps3_atomic_dec(&instance->cmd_statistics.cmd_delivering);
if (send_result == PS3_SUCCESS)
send_result = ps3_cmd_wait_sync(instance, cmd);
ret = ps3_mgr_complete_proc(instance, cmd, send_result);
if (ret == -PS3_CMD_NO_RESP) {
LOG_ERROR("hno:%u %d respStatus NOK CFID[%d] respStatus[%d]\n",
PS3_HOST(cmd->instance), ret,
cmd->cmd_word.cmdFrameID, ps3_cmd_resp_status(cmd));
ret = -ETIMEDOUT;
goto l_no_free_cmd;
}
if (ret != PS3_SUCCESS) {
LOG_ERROR("hno:%u %d respStatus NOK CFID[%d] respStatus[%d]\n",
PS3_HOST(cmd->instance), ret,
cmd->cmd_word.cmdFrameID, ps3_cmd_resp_status(cmd));
ret = -ENXIO;
goto l_out_failed;
}
resp_len = ps3_sas_ext_buf_to_rsp(instance, &job->reply_payload,
cmd->ext_buf);
LOG_DEBUG("hno:%u trace_id[0x%llx] CFID [%u], end, ret[%d]\n",
PS3_HOST(instance), cmd->trace_id, cmd->index, ret);
l_out_failed:
ps3_mgr_cmd_free(instance, cmd);
l_no_free_cmd:
up(&instance->sas_dev_context.ps3_sas_smp_semaphore);
l_out:
bsg_job_done(job, ret, resp_len);
}
#endif
int ps3_sas_attach_transport(void)
{
int ret = PS3_SUCCESS;
static struct sas_function_template ps3_sas_transport_functions = {
.get_linkerrors = ps3_sas_linkerrors_get,
.get_enclosure_identifier = ps3_sas_enclosure_identifier_get,
.get_bay_identifier = ps3_sas_bay_identifier_get,
.phy_reset = ps3_sas_phy_reset,
.phy_enable = ps3_sas_phy_enable,
.set_phy_speed = ps3_sas_linkrates_set,
.smp_handler = ps3_sas_smp_handler,
};
ps3_sas_transport_template =
sas_attach_transport(&ps3_sas_transport_functions);
if (!ps3_sas_transport_template)
ret = -PS3_FAILED;
return ret;
}
void ps3_sas_release_transport(void)
{
if (ps3_sas_transport_template != NULL) {
sas_release_transport(ps3_sas_transport_template);
ps3_sas_transport_template = NULL;
}
}
#endif

View File

@ -0,0 +1,44 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef _WINDOWS
#ifndef _PS3_SAS_TRANSPORT_H_
#define _PS3_SAS_TRANSPORT_H_
#include "ps3_instance_manager.h"
#include <scsi/scsi_transport_sas.h>
#include <linux/version.h>
#include "ps3_htp.h"
#include "ps3_kernel_version.h"
#define PS3_SAS_TIMEOUT_SEC (40)
#define PS3_SMP_CRC_LEN (4)
struct scsi_transport_template *ps3_sas_transport_get(void);
int ps3_sas_attach_transport(void);
void ps3_sas_release_transport(void);
int ps3_sas_linkerrors_get(struct sas_phy *phy);
int ps3_sas_enclosure_identifier_get(struct sas_rphy *rphy, u64 *identifier);
int ps3_sas_bay_identifier_get(struct sas_rphy *rphy);
int ps3_sas_phy_reset(struct sas_phy *phy, int hard_reset);
int ps3_sas_phy_enable(struct sas_phy *phy, int enable);
int ps3_sas_linkrates_set(struct sas_phy *phy, struct sas_phy_linkrates *rates);
#if defined(PS3_SAS_SMP_RETURN)
int ps3_sas_smp_handler(struct Scsi_Host *shost, struct sas_rphy *rphy,
struct request *req);
#else
void ps3_sas_smp_handler(struct bsg_job *job, struct Scsi_Host *shost,
struct sas_rphy *rphy);
#endif
#endif
#endif

Some files were not shown because too many files have changed in this diff Show More