From: John Garry <john.garry@huawei.com>
To: Yanling Song <songyl@ramaxel.com>, <martin.petersen@oracle.com>
Cc: <linux-scsi@vger.kernel.org>, <bvanassche@acm.org>
Subject: Re: [PATCH v5] scsi:spraid: initial commit of Ramaxel spraid driver
Date: Tue, 15 Mar 2022 14:43:35 +0000 [thread overview]
Message-ID: <ecf79a5c-49f4-cf0e-edf4-9363c8b60bb5@huawei.com> (raw)
In-Reply-To: <20220314025315.96674-1-songyl@ramaxel.com>
On 14/03/2022 02:53, Yanling Song wrote:
Some initial comments from me.
> This initial commit contains Ramaxel's spraid module.
It would be useful to give brief overview of the HW and driver.
>
> Signed-off-by: Yanling Song <songyl@ramaxel.com>
>
I think that you require a '---' here
> Changes from V4:
> Rebased and retested on top of the latest for-next tree
>
> Changes from V3:
> 1. Use macro to repalce scmd_tmout_nonpt module parameter.
>
> Changes from V2:
> 1. Change "depends BLK_DEV_BSGLIB" to "select BLK_DEV_BSGLIB".
> 2. Add more descriptions in help.
> 3. Use pr_debug() instead of introducing dev_log_dbg().
> 4. Use get_unaligned_be*() in spraid_setup_rw_cmd();
> 5. Remove some unncessarry module parameters:
> scmd_tmout_pt, wait_abl_tmout, use_sgl_force
> 6. Some module parameters will be changed in the next version:
> admin_tmout, scmd_tmout_nonpt
>
> Changes from V1:
> 1. Use BSG module to replace with ioctrl
> 2. Use author's email as MODULE_AUTHOR
> 3. Remove "default=m" in drivers/scsi/spraid/Kconfig
> 4. To be changed in the next version:
> a. Use get_unaligned_be*() in spraid_setup_rw_cmd();
> b. Use pr_debug() instead of introducing dev_log_dbg().
>
> Signed-off-by: Yanling Song <songyl@ramaxel.com>
2x Signed off - why?
> ---
> Documentation/scsi/spraid.rst | 16 +
> MAINTAINERS | 7 +
> drivers/scsi/Kconfig | 1 +
> drivers/scsi/Makefile | 1 +
> drivers/scsi/spraid/Kconfig | 13 +
> drivers/scsi/spraid/Makefile | 7 +
> drivers/scsi/spraid/spraid.h | 695 ++++++
> drivers/scsi/spraid/spraid_main.c | 3266 +++++++++++++++++++++++++++++
> 8 files changed, 4006 insertions(+)
> create mode 100644 Documentation/scsi/spraid.rst
> create mode 100644 drivers/scsi/spraid/Kconfig
> create mode 100644 drivers/scsi/spraid/Makefile
> create mode 100644 drivers/scsi/spraid/spraid.h
> create mode 100644 drivers/scsi/spraid/spraid_main.c
I'm not sure why this driver cannot be located in drivers/scsi/spraid.c
since it could be contained in a single C file
>
> diff --git a/Documentation/scsi/spraid.rst b/Documentation/scsi/spraid.rst
> new file mode 100644
> index 000000000000..f87b02a6907b
> --- /dev/null
> +++ b/Documentation/scsi/spraid.rst
> @@ -0,0 +1,16 @@
> +.. SPDX-License-Identifier: GPL-2.0
> +
> +==============================================
> +SPRAID - Ramaxel SCSI Raid Controller driver
> +==============================================
> +
> +This file describes the spraid SCSI driver for Ramaxel
> +raid controllers. The spraid driver is the first generation raid driver for
capitalize acronyms, like RAID
> +Ramaxel Corp.
> +
> +For Ramaxel spraid controller support, enable the spraid driver
> +when configuring the kernel.
> +
> +Supported devices
> +=================
> +<Controller names to be added as they become publicly available.>
there's not really much in this file...so I doubt its use
> diff --git a/MAINTAINERS b/MAINTAINERS
> index ea3e6c914384..cf3bb776b615 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -18221,6 +18221,13 @@ F: include/dt-bindings/spmi/spmi.h
> F: include/linux/spmi.h
> F: include/trace/events/spmi.h
>
> +SPRAID SCSI/Raid DRIVERS
> +M: Yanling Song <yanling.song@ramaxel.com>
> +L: linux-scsi@vger.kernel.org
> +S: Maintained
> +F: Documentation/scsi/spraid.rst
> +F: drivers/scsi/spraid/
> +
> SPU FILE SYSTEM
> M: Jeremy Kerr <jk@ozlabs.org>
> L: linuxppc-dev@lists.ozlabs.org
> diff --git a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig
> index 6e3a04107bb6..3da5d26e1e11 100644
> --- a/drivers/scsi/Kconfig
> +++ b/drivers/scsi/Kconfig
> @@ -501,6 +501,7 @@ source "drivers/scsi/mpt3sas/Kconfig"
> source "drivers/scsi/mpi3mr/Kconfig"
> source "drivers/scsi/smartpqi/Kconfig"
> source "drivers/scsi/ufs/Kconfig"
> +source "drivers/scsi/spraid/Kconfig"
alphabetic ordering
>
> config SCSI_HPTIOP
> tristate "HighPoint RocketRAID 3xxx/4xxx Controller support"
> diff --git a/drivers/scsi/Makefile b/drivers/scsi/Makefile
> index 19814c26c908..192f8fb10a19 100644
> --- a/drivers/scsi/Makefile
> +++ b/drivers/scsi/Makefile
> @@ -96,6 +96,7 @@ obj-$(CONFIG_SCSI_ZALON) += zalon7xx.o
> obj-$(CONFIG_SCSI_DC395x) += dc395x.o
> obj-$(CONFIG_SCSI_AM53C974) += esp_scsi.o am53c974.o
> obj-$(CONFIG_CXLFLASH) += cxlflash/
> +obj-$(CONFIG_RAMAXEL_SPRAID) += spraid/
> obj-$(CONFIG_MEGARAID_LEGACY) += megaraid.o
> obj-$(CONFIG_MEGARAID_NEWGEN) += megaraid/
> obj-$(CONFIG_MEGARAID_SAS) += megaraid/
> diff --git a/drivers/scsi/spraid/Kconfig b/drivers/scsi/spraid/Kconfig
> new file mode 100644
> index 000000000000..bfbba3db8db0
> --- /dev/null
> +++ b/drivers/scsi/spraid/Kconfig
> @@ -0,0 +1,13 @@
> +#
> +# Ramaxel driver configuration
> +#
> +
> +config RAMAXEL_SPRAID
many SCSI-related configs are in form CONFIG_SCSI_XXX
> + tristate "Ramaxel spraid Adapter"
> + depends on PCI && SCSI
> + select BLK_DEV_BSGLIB
> + depends on ARM64 || X86_64
why only 2x architectures?
and what about COMPILE_TEST?
> + help
> + This driver supports Ramaxel SPRxxx serial
> + raid controller, which has PCIE Gen4 interface
> + with host and supports SAS/SATA Hdd/ssd.
> diff --git a/drivers/scsi/spraid/Makefile b/drivers/scsi/spraid/Makefile
> new file mode 100644
> index 000000000000..ad2c2a84ddaf
> --- /dev/null
> +++ b/drivers/scsi/spraid/Makefile
> @@ -0,0 +1,7 @@
> +#
> +# Makefile for the Ramaxel device drivers.
> +#
> +
> +obj-$(CONFIG_RAMAXEL_SPRAID) += spraid.o
> +
> +spraid-objs := spraid_main.o
> diff --git a/drivers/scsi/spraid/spraid.h b/drivers/scsi/spraid/spraid.h
why do you need a separate header file? why not put all this in the only
C file?
> new file mode 100644
> index 000000000000..617f5c2cdb82
> --- /dev/null
> +++ b/drivers/scsi/spraid/spraid.h
> @@ -0,0 +1,695 @@
> +/* SPDX-License-Identifier: GPL-2.0 */
> +/* Copyright(c) 2021 Ramaxel Memory Technology, Ltd */
> +
> +#ifndef __SPRAID_H_
> +#define __SPRAID_H_
> +
> +#define SPRAID_CAP_MQES(cap) ((cap) & 0xffff)
> +#define SPRAID_CAP_STRIDE(cap) (((cap) >> 32) & 0xf)
> +#define SPRAID_CAP_MPSMIN(cap) (((cap) >> 48) & 0xf)
> +#define SPRAID_CAP_MPSMAX(cap) (((cap) >> 52) & 0xf)
> +#define SPRAID_CAP_TIMEOUT(cap) (((cap) >> 24) & 0xff)
> +#define SPRAID_CAP_DMAMASK(cap) (((cap) >> 37) & 0xff)
> +
> +#define SPRAID_DEFAULT_MAX_CHANNEL 4
> +#define SPRAID_DEFAULT_MAX_ID 240
> +#define SPRAID_DEFAULT_MAX_LUN_PER_HOST 8
> +#define MAX_SECTORS 2048
> +
> +#define IO_SQE_SIZE sizeof(struct spraid_ioq_command)
> +#define ADMIN_SQE_SIZE sizeof(struct spraid_admin_command)
> +#define SQE_SIZE(qid) (((qid) > 0) ? IO_SQE_SIZE : ADMIN_SQE_SIZE)
> +#define CQ_SIZE(depth) ((depth) * sizeof(struct spraid_completion))
> +#define SQ_SIZE(qid, depth) ((depth) * SQE_SIZE(qid))
> +
> +#define SENSE_SIZE(depth) ((depth) * SCSI_SENSE_BUFFERSIZE)
> +
> +#define SPRAID_AQ_DEPTH 128
> +#define SPRAID_NR_AEN_COMMANDS 16
> +#define SPRAID_AQ_BLK_MQ_DEPTH (SPRAID_AQ_DEPTH - SPRAID_NR_AEN_COMMANDS)
> +#define SPRAID_AQ_MQ_TAG_DEPTH (SPRAID_AQ_BLK_MQ_DEPTH - 1)
> +
> +#define SPRAID_ADMIN_QUEUE_NUM 1
> +#define SPRAID_PTCMDS_PERQ 1
> +#define SPRAID_IO_BLK_MQ_DEPTH (hdev->shost->can_queue)
> +#define SPRAID_NR_IOQ_PTCMDS (SPRAID_PTCMDS_PERQ * hdev->shost->nr_hw_queues)
> +
> +#define FUA_MASK 0x08
> +#define SPRAID_MINORS BIT(MINORBITS)
> +
> +#define COMMAND_IS_WRITE(cmd) ((cmd)->common.opcode & 1)
This is not used. Anything that is not used may be dropped.
> +
> +#define SPRAID_IO_IOSQES 7
> +#define SPRAID_IO_IOCQES 4
> +#define PRP_ENTRY_SIZE 8
> +
> +#define SMALL_POOL_SIZE 256
> +#define MAX_SMALL_POOL_NUM 16
> +#define MAX_CMD_PER_DEV 64
> +#define MAX_CDB_LEN 32
> +
> +#define SPRAID_UP_TO_MULTY4(x) (((x) + 4) & (~0x03))
> +
> +#define CQE_STATUS_SUCCESS (0x0)
> +
> +#define PCI_VENDOR_ID_RAMAXEL_LOGIC 0x1E81
> +
> +#define SPRAID_SERVER_DEVICE_HBA_DID 0x2100
> +#define SPRAID_SERVER_DEVICE_RAID_DID 0x2200
> +
> +#define IO_6_DEFAULT_TX_LEN 256
> +
> +#define SPRAID_INT_PAGES 2
> +#define SPRAID_INT_BYTES(hdev) (SPRAID_INT_PAGES * (hdev)->page_size)
> +
> +enum {
> + SPRAID_REQ_CANCELLED = (1 << 0),
> + SPRAID_REQ_USERCMD = (1 << 1),
> +};
> +
> +enum {
> + SPRAID_SC_SUCCESS = 0x0,
> + SPRAID_SC_INVALID_OPCODE = 0x1,
> + SPRAID_SC_INVALID_FIELD = 0x2,
> +
> + SPRAID_SC_ABORT_LIMIT = 0x103,
> + SPRAID_SC_ABORT_MISSING = 0x104,
> + SPRAID_SC_ASYNC_LIMIT = 0x105,
> +
> + SPRAID_SC_DNR = 0x4000,
> +};
> +
> +enum {
> + SPRAID_REG_CAP = 0x0000,
> + SPRAID_REG_CC = 0x0014,
> + SPRAID_REG_CSTS = 0x001c,
> + SPRAID_REG_AQA = 0x0024,
> + SPRAID_REG_ASQ = 0x0028,
> + SPRAID_REG_ACQ = 0x0030,
> + SPRAID_REG_DBS = 0x1000,
> +};
> +
> +enum {
> + SPRAID_CC_ENABLE = 1 << 0,
> + SPRAID_CC_CSS_NVM = 0 << 4,
> + SPRAID_CC_MPS_SHIFT = 7,
> + SPRAID_CC_AMS_SHIFT = 11,
> + SPRAID_CC_SHN_SHIFT = 14,
> + SPRAID_CC_IOSQES_SHIFT = 16,
> + SPRAID_CC_IOCQES_SHIFT = 20,
> + SPRAID_CC_AMS_RR = 0 << SPRAID_CC_AMS_SHIFT,
> + SPRAID_CC_SHN_NONE = 0 << SPRAID_CC_SHN_SHIFT,
> + SPRAID_CC_IOSQES = SPRAID_IO_IOSQES << SPRAID_CC_IOSQES_SHIFT,
> + SPRAID_CC_IOCQES = SPRAID_IO_IOCQES << SPRAID_CC_IOCQES_SHIFT,
> + SPRAID_CC_SHN_NORMAL = 1 << SPRAID_CC_SHN_SHIFT,
> + SPRAID_CC_SHN_MASK = 3 << SPRAID_CC_SHN_SHIFT,
> + SPRAID_CSTS_CFS_SHIFT = 1,
> + SPRAID_CSTS_SHST_SHIFT = 2,
> + SPRAID_CSTS_PP_SHIFT = 5,
> + SPRAID_CSTS_RDY = 1 << 0,
> + SPRAID_CSTS_SHST_CMPLT = 2 << 2,
> + SPRAID_CSTS_SHST_MASK = 3 << 2,
> + SPRAID_CSTS_CFS_MASK = 1 << SPRAID_CSTS_CFS_SHIFT,
> + SPRAID_CSTS_PP_MASK = 1 << SPRAID_CSTS_PP_SHIFT,
> +};
> +
> +enum {
> + SPRAID_ADMIN_DELETE_SQ = 0x00,
> + SPRAID_ADMIN_CREATE_SQ = 0x01,
> + SPRAID_ADMIN_DELETE_CQ = 0x04,
> + SPRAID_ADMIN_CREATE_CQ = 0x05,
> + SPRAID_ADMIN_ABORT_CMD = 0x08,
> + SPRAID_ADMIN_SET_FEATURES = 0x09,
> + SPRAID_ADMIN_ASYNC_EVENT = 0x0c,
> + SPRAID_ADMIN_GET_INFO = 0xc6,
> + SPRAID_ADMIN_RESET = 0xc8,
> +};
> +
> +enum {
> + SPRAID_GET_INFO_CTRL = 0,
> + SPRAID_GET_INFO_DEV_LIST = 1,
> +};
> +
> +enum {
> + SPRAID_RESET_TARGET = 0,
> + SPRAID_RESET_BUS = 1,
> +};
> +
> +enum {
> + SPRAID_AEN_ERROR = 0,
> + SPRAID_AEN_NOTICE = 2,
> + SPRAID_AEN_VS = 7,
> +};
> +
> +enum {
> + SPRAID_AEN_DEV_CHANGED = 0x00,
> + SPRAID_AEN_HOST_PROBING = 0x10,
> +};
> +
> +enum {
> + SPRAID_AEN_TIMESYN = 0x07
> +};
> +
> +enum {
> + SPRAID_CMD_WRITE = 0x01,
> + SPRAID_CMD_READ = 0x02,
> +
> + SPRAID_CMD_NONIO_NONE = 0x80,
> + SPRAID_CMD_NONIO_TODEV = 0x81,
> + SPRAID_CMD_NONIO_FROMDEV = 0x82,
> +};
> +
> +enum {
> + SPRAID_QUEUE_PHYS_CONTIG = (1 << 0),
> + SPRAID_CQ_IRQ_ENABLED = (1 << 1),
> +
> + SPRAID_FEAT_NUM_QUEUES = 0x07,
> + SPRAID_FEAT_ASYNC_EVENT = 0x0b,
> + SPRAID_FEAT_TIMESTAMP = 0x0e,
> +};
> +
> +enum spraid_state {
> + SPRAID_NEW,
> + SPRAID_LIVE,
> + SPRAID_RESETTING,
> + SPRAID_DELETING,
> + SPRAID_DEAD,
> +};
> +
> +enum {
> + SPRAID_CARD_HBA,
> + SPRAID_CARD_RAID,
> +};
> +
> +enum spraid_cmd_type {
> + SPRAID_CMD_ADM,
> + SPRAID_CMD_IOPT,
> +};
> +
> +struct spraid_completion {
> + __le32 result;
I think that __le32 is used for userspace common defines, while we use
le32 for internal to kernel
> + union {
> + struct {
> + __u8 sense_len;
> + __u8 resv[3];
> + };
> + __le32 result1;
> + };
> + __le16 sq_head;
> + __le16 sq_id;
> + __u16 cmd_id;
> + __le16 status;
> +};
> +
> +struct spraid_ctrl_info {
> + __le32 nd;
> + __le16 max_cmds;
> + __le16 max_channel;
> + __le32 max_tgt_id;
> + __le16 max_lun;
> + __le16 max_num_sge;
> + __le16 lun_num_in_boot;
> + __u8 mdts;
> + __u8 acl;
> + __u8 aerl;
> + __u8 card_type;
> + __u16 rsvd;
> + __u32 rtd3e;
> + __u8 sn[32];
> + __u8 fr[16];
> + __u8 rsvd1[4020];
> +};
> +
> +struct spraid_dev {
> + struct pci_dev *pdev;
> + struct device *dev;
do you really need both, as one can be derived from the other?
> + struct Scsi_Host *shost;
> + struct spraid_queue *queues;
> + struct dma_pool *prp_page_pool;
> + struct dma_pool *prp_small_pool[MAX_SMALL_POOL_NUM];
> + mempool_t *iod_mempool;
> + void __iomem *bar;
> + u32 max_qid;
> + u32 num_vecs;
> + u32 queue_count;
> + u32 ioq_depth;
> + int db_stride;
> + u32 __iomem *dbs;
> + struct rw_semaphore devices_rwsem;
> + int numa_node;
> + u32 page_size;
> + u32 ctrl_config;
> + u32 online_queues;
> + u64 cap;
> + int instance;
> + struct spraid_ctrl_info *ctrl_info;
> + struct spraid_dev_info *devices;
> +
> + struct spraid_cmd *adm_cmds;
> + struct list_head adm_cmd_list;
> + spinlock_t adm_cmd_lock;
> +
> + struct spraid_cmd *ioq_ptcmds;
> + struct list_head ioq_pt_list;
> + spinlock_t ioq_pt_lock;
> +
> + struct work_struct scan_work;
> + struct work_struct timesyn_work;
> + struct work_struct reset_work;
> +
> + enum spraid_state state;
> + spinlock_t state_lock;
> + struct request_queue *bsg_queue;
> +};
> +
> +struct spraid_sgl_desc {
> + __le64 addr;
> + __le32 length;
> + __u8 rsvd[3];
> + __u8 type;
> +};
> +
> +union spraid_data_ptr {
> + struct {
> + __le64 prp1;
> + __le64 prp2;
> + };
> + struct spraid_sgl_desc sgl;
> +};
> +
> +struct spraid_admin_common_command {
> + __u8 opcode;
> + __u8 flags;
> + __u16 command_id;
> + __le32 hdid;
> + __le32 cdw2[4];
> + union spraid_data_ptr dptr;
> + __le32 cdw10;
> + __le32 cdw11;
> + __le32 cdw12;
> + __le32 cdw13;
> + __le32 cdw14;
> + __le32 cdw15;
> +};
> +
> +struct spraid_features {
> + __u8 opcode;
> + __u8 flags;
> + __u16 command_id;
> + __le32 hdid;
> + __u64 rsvd2[2];
> + union spraid_data_ptr dptr;
> + __le32 fid;
> + __le32 dword11;
> + __le32 dword12;
> + __le32 dword13;
> + __le32 dword14;
> + __le32 dword15;
> +};
> +
> +struct spraid_create_cq {
> + __u8 opcode;
> + __u8 flags;
> + __u16 command_id;
> + __u32 rsvd1[5];
> + __le64 prp1;
> + __u64 rsvd8;
> + __le16 cqid;
> + __le16 qsize;
> + __le16 cq_flags;
> + __le16 irq_vector;
> + __u32 rsvd12[4];
> +};
> +
> +struct spraid_create_sq {
> + __u8 opcode;
> + __u8 flags;
> + __u16 command_id;
> + __u32 rsvd1[5];
> + __le64 prp1;
> + __u64 rsvd8;
> + __le16 sqid;
> + __le16 qsize;
> + __le16 sq_flags;
> + __le16 cqid;
> + __u32 rsvd12[4];
> +};
> +
> +struct spraid_delete_queue {
> + __u8 opcode;
> + __u8 flags;
> + __u16 command_id;
> + __u32 rsvd1[9];
> + __le16 qid;
> + __u16 rsvd10;
> + __u32 rsvd11[5];
> +};
> +
> +struct spraid_get_info {
> + __u8 opcode;
> + __u8 flags;
> + __u16 command_id;
> + __le32 hdid;
> + __u32 rsvd2[4];
> + union spraid_data_ptr dptr;
> + __u8 type;
> + __u8 rsvd10[3];
> + __le32 cdw11;
> + __u32 rsvd12[4];
> +};
> +
> +struct spraid_usr_cmd {
> + __u8 opcode;
> + __u8 flags;
> + __u16 command_id;
> + __le32 hdid;
> + union {
> + struct {
> + __le16 subopcode;
> + __le16 rsvd1;
> + } info_0;
> + __le32 cdw2;
> + };
> + union {
> + struct {
> + __le16 data_len;
> + __le16 param_len;
> + } info_1;
> + __le32 cdw3;
> + };
> + __u64 metadata;
> + union spraid_data_ptr dptr;
> + __le32 cdw10;
> + __le32 cdw11;
> + __le32 cdw12;
> + __le32 cdw13;
> + __le32 cdw14;
> + __le32 cdw15;
> +};
> +
> +enum {
> + SPRAID_CMD_FLAG_SGL_METABUF = (1 << 6),
> + SPRAID_CMD_FLAG_SGL_METASEG = (1 << 7),
> + SPRAID_CMD_FLAG_SGL_ALL = SPRAID_CMD_FLAG_SGL_METABUF | SPRAID_CMD_FLAG_SGL_METASEG,
about SPRAID_CMD_FLAG_SGL_ALL, this is the second item I checked for
being referenced and second item which I find is not referenced - please
don't add stuff which is not referenced
> +};
> +
> +enum spraid_cmd_state {
> + SPRAID_CMD_IDLE = 0,
> + SPRAID_CMD_IN_FLIGHT = 1,
> + SPRAID_CMD_COMPLETE = 2,
> + SPRAID_CMD_TIMEOUT = 3,
> + SPRAID_CMD_TMO_COMPLETE = 4,
> +};
> +
> +struct spraid_abort_cmd {
> + __u8 opcode;
> + __u8 flags;
> + __u16 command_id;
> + __le32 hdid;
> + __u64 rsvd2[4];
> + __le16 sqid;
> + __le16 cid;
> + __u32 rsvd11[5];
> +};
> +
> +struct spraid_reset_cmd {
> + __u8 opcode;
> + __u8 flags;
> + __u16 command_id;
> + __le32 hdid;
> + __u64 rsvd2[4];
> + __u8 type;
> + __u8 rsvd10[3];
> + __u32 rsvd11[5];
> +};
> +
> +struct spraid_admin_command {
> + union {
> + struct spraid_admin_common_command common;
> + struct spraid_features features;
> + struct spraid_create_cq create_cq;
> + struct spraid_create_sq create_sq;
> + struct spraid_delete_queue delete_queue;
> + struct spraid_get_info get_info;
> + struct spraid_abort_cmd abort;
> + struct spraid_reset_cmd reset;
> + struct spraid_usr_cmd usr_cmd;
> + };
> +};
> +
> +struct spraid_ioq_common_command {
> + __u8 opcode;
> + __u8 flags;
> + __u16 command_id;
> + __le32 hdid;
> + __le16 sense_len;
> + __u8 cdb_len;
> + __u8 rsvd2;
> + __le32 cdw3[3];
> + union spraid_data_ptr dptr;
> + __le32 cdw10[6];
> + __u8 cdb[32];
> + __le64 sense_addr;
> + __le32 cdw26[6];
> +};
> +
> +struct spraid_rw_command {
> + __u8 opcode;
> + __u8 flags;
> + __u16 command_id;
> + __le32 hdid;
> + __le16 sense_len;
> + __u8 cdb_len;
> + __u8 rsvd2;
> + __u32 rsvd3[3];
> + union spraid_data_ptr dptr;
> + __le64 slba;
> + __le16 nlb;
> + __le16 control;
> + __u32 rsvd13[3];
> + __u8 cdb[32];
> + __le64 sense_addr;
> + __u32 rsvd26[6];
> +};
> +
> +struct spraid_scsi_nonio {
> + __u8 opcode;
> + __u8 flags;
> + __u16 command_id;
> + __le32 hdid;
> + __le16 sense_len;
> + __u8 cdb_length;
> + __u8 rsvd2;
> + __u32 rsvd3[3];
> + union spraid_data_ptr dptr;
> + __u32 rsvd10[5];
> + __le32 buffer_len;
> + __u8 cdb[32];
> + __le64 sense_addr;
> + __u32 rsvd26[6];
> +};
> +
> +struct spraid_ioq_command {
> + union {
> + struct spraid_ioq_common_command common;
> + struct spraid_rw_command rw;
> + struct spraid_scsi_nonio scsi_nonio;
> + };
> +};
> +
> +struct spraid_passthru_common_cmd {
> + __u8 opcode;
> + __u8 flags;
> + __u16 rsvd0;
> + __u32 nsid;
> + union {
> + struct {
> + __u16 subopcode;
> + __u16 rsvd1;
> + } info_0;
> + __u32 cdw2;
> + };
> + union {
> + struct {
> + __u16 data_len;
> + __u16 param_len;
> + } info_1;
> + __u32 cdw3;
> + };
> + __u64 metadata;
> +
> + __u64 addr;
> + __u64 prp2;
> +
> + __u32 cdw10;
> + __u32 cdw11;
> + __u32 cdw12;
> + __u32 cdw13;
> + __u32 cdw14;
> + __u32 cdw15;
> + __u32 timeout_ms;
> + __u32 result0;
> + __u32 result1;
> +};
> +
> +struct spraid_ioq_passthru_cmd {
> + __u8 opcode;
> + __u8 flags;
> + __u16 rsvd0;
> + __u32 nsid;
> + union {
> + struct {
> + __u16 res_sense_len;
> + __u8 cdb_len;
> + __u8 rsvd0;
> + } info_0;
> + __u32 cdw2;
> + };
> + union {
> + struct {
> + __u16 subopcode;
> + __u16 rsvd1;
> + } info_1;
> + __u32 cdw3;
> + };
> + union {
> + struct {
> + __u16 rsvd;
> + __u16 param_len;
> + } info_2;
> + __u32 cdw4;
> + };
> + __u32 cdw5;
> + __u64 addr;
> + __u64 prp2;
> + union {
> + struct {
> + __u16 eid;
> + __u16 sid;
> + } info_3;
> + __u32 cdw10;
> + };
> + union {
> + struct {
> + __u16 did;
> + __u8 did_flag;
> + __u8 rsvd2;
> + } info_4;
> + __u32 cdw11;
> + };
> + __u32 cdw12;
> + __u32 cdw13;
> + __u32 cdw14;
> + __u32 data_len;
> + __u32 cdw16;
> + __u32 cdw17;
> + __u32 cdw18;
> + __u32 cdw19;
> + __u32 cdw20;
> + __u32 cdw21;
> + __u32 cdw22;
> + __u32 cdw23;
> + __u64 sense_addr;
> + __u32 cdw26[4];
> + __u32 timeout_ms;
> + __u32 result0;
> + __u32 result1;
> +};
> +
> +struct spraid_bsg_request {
> + u32 msgcode;
> + u32 control;
> + union {
> + struct spraid_passthru_common_cmd admcmd;
> + struct spraid_ioq_passthru_cmd ioqcmd;
> + };
> +};
> +
> +enum {
> + SPRAID_BSG_ADM,
> + SPRAID_BSG_IOQ,
> +};
> +
> +struct spraid_cmd {
> + int qid;
> + int cid;
> + u32 result0;
> + u32 result1;
> + u16 status;
> + void *priv;
> + enum spraid_cmd_state state;
> + struct completion cmd_done;
> + struct list_head list;
> +};
> +
> +struct spraid_queue {
> + struct spraid_dev *hdev;
> + spinlock_t sq_lock; /* spinlock for lock handling */
such comments are of little use
> +
> + spinlock_t cq_lock ____cacheline_aligned_in_smp; /* spinlock for lock handling */
> +
> + void *sq_cmds;
> +
> + struct spraid_completion *cqes;
> +
> + dma_addr_t sq_dma_addr;
> + dma_addr_t cq_dma_addr;
> + u32 __iomem *q_db;
> + u8 cq_phase;
> + u8 sqes;
> + u16 qid;
> + u16 sq_tail;
> + u16 cq_head;
> + u16 last_cq_head;
> + u16 q_depth;
> + s16 cq_vector;
> + void *sense;
> + dma_addr_t sense_dma_addr;
> + struct dma_pool *prp_small_pool;
> +};
> +
> +struct spraid_iod {
> + struct spraid_queue *spraidq;
> + enum spraid_cmd_state state;
> + int npages;
> + u32 nsge;
> + u32 length;
> + bool use_sgl;
> + bool sg_drv_mgmt;
> + dma_addr_t first_dma;
> + void *sense;
> + dma_addr_t sense_dma;
> + struct scatterlist *sg;
> + struct scatterlist inline_sg[0];
> +};
> +
> +#define SPRAID_DEV_INFO_ATTR_BOOT(attr) ((attr) & 0x01)
> +#define SPRAID_DEV_INFO_ATTR_VD(attr) (((attr) & 0x02) == 0x0)
> +#define SPRAID_DEV_INFO_ATTR_PT(attr) (((attr) & 0x22) == 0x02)
> +#define SPRAID_DEV_INFO_ATTR_RAWDISK(attr) ((attr) & 0x20)
> +
> +#define SPRAID_DEV_INFO_FLAG_VALID(flag) ((flag) & 0x01)
> +#define SPRAID_DEV_INFO_FLAG_CHANGE(flag) ((flag) & 0x02)
> +
> +struct spraid_dev_info {
> + __le32 hdid;
> + __le16 target;
> + __u8 channel;
> + __u8 lun;
> + __u8 attr;
> + __u8 flag;
> + __le16 max_io_kb;
> +};
> +
> +#define MAX_DEV_ENTRY_PER_PAGE_4K 340
> +struct spraid_dev_list {
> + __le32 dev_num;
> + __u32 rsvd0[3];
> + struct spraid_dev_info devices[MAX_DEV_ENTRY_PER_PAGE_4K];
> +};
> +
> +struct spraid_sdev_hostdata {
> + u32 hdid;
> +};
> +
> +#endif
> diff --git a/drivers/scsi/spraid/spraid_main.c b/drivers/scsi/spraid/spraid_main.c
> new file mode 100644
> index 000000000000..7edce06b62a4
> --- /dev/null
> +++ b/drivers/scsi/spraid/spraid_main.c
> @@ -0,0 +1,3266 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/* Copyright(c) 2021 Ramaxel Memory Technology, Ltd */
> +
> +/* Ramaxel Raid SPXXX Series Linux Driver */
> +
> +#define pr_fmt(fmt) "spraid: " fmt
> +
> +#include <linux/sched/signal.h>
> +#include <linux/pci.h>
> +#include <linux/aer.h>
> +#include <linux/module.h>
> +#include <linux/ioport.h>
> +#include <linux/device.h>
> +#include <linux/delay.h>
> +#include <linux/interrupt.h>
> +#include <linux/cdev.h>
> +#include <linux/sysfs.h>
> +#include <linux/gfp.h>
> +#include <linux/types.h>
> +#include <linux/ratelimit.h>
> +#include <linux/once.h>
> +#include <linux/debugfs.h>
> +#include <linux/io-64-nonatomic-lo-hi.h>
> +#include <linux/blkdev.h>
> +#include <linux/bsg-lib.h>
> +#include <asm/unaligned.h>
alphabetic ordering preferred
> +
> +#include <scsi/scsi.h>
> +#include <scsi/scsi_cmnd.h>
> +#include <scsi/scsi_device.h>
> +#include <scsi/scsi_host.h>
> +#include <scsi/scsi_transport.h>
> +#include <scsi/scsi_dbg.h>
> +#include <scsi/sg.h>
> +
> +
> +#include "spraid.h"
> +
> +#define SCMD_TMOUT_RAWDISK 180
> +
> +#define SCMD_TMOUT_VD 180
> +
> +static int ioq_depth_set(const char *val, const struct kernel_param *kp);
> +static const struct kernel_param_ops ioq_depth_ops = {
> + .set = ioq_depth_set,
> + .get = param_get_uint,
> +};
> +
> +static u32 io_queue_depth = 1024;
> +module_param_cb(io_queue_depth, &ioq_depth_ops, &io_queue_depth, 0644);
> +MODULE_PARM_DESC(io_queue_depth, "set io queue depth, should >= 2");
why do we need a commandline param for this?
> +
> +static int small_pool_num_set(const char *val, const struct kernel_param *kp)
> +{
> + u8 n = 0;
> + int ret;
> +
> + ret = kstrtou8(val, 10, &n);
> + if (ret != 0)
> + return -EINVAL;
> + if (n > MAX_SMALL_POOL_NUM)
> + n = MAX_SMALL_POOL_NUM;
> + if (n < 1)
> + n = 1;
> + *((u8 *)kp->arg) = n;
> +
> + return 0;
> +}
> +
> +static const struct kernel_param_ops small_pool_num_ops = {
> + .set = small_pool_num_set,
> + .get = param_get_byte,
> +};
> +
> +/* It was found that the spindlock of a single pool conflicts
spinlock
> + * a lot with multiple CPUs.So multiple pools are introduced
> + * to reduce the conflictions.
so what are these small pools used for?
> + */
> +static unsigned char small_pool_num = 4;
> +module_param_cb(small_pool_num, &small_pool_num_ops, &small_pool_num, 0644);
> +MODULE_PARM_DESC(small_pool_num, "set prp small pool num, default 4, MAX 16");
> +
> +static void spraid_free_queue(struct spraid_queue *spraidq);
> +static void spraid_handle_aen_notice(struct spraid_dev *hdev, u32 result);
> +static void spraid_handle_aen_vs(struct spraid_dev *hdev, u32 result, u32 result1);
> +
> +static DEFINE_IDA(spraid_instance_ida);
> +
> +static struct class *spraid_class;
> +
> +#define SPRAID_CAP_TIMEOUT_UNIT_MS (HZ / 2)
> +
> +static struct workqueue_struct *spraid_wq;
> +
> +#define SPRAID_DRV_VERSION "1.0.0.0"
I don't see much value in driver versioning. As I see, the kernel
version is the driver version.
> +
> +#define ADMIN_TIMEOUT (60 * HZ)
> +#define ADMIN_ERR_TIMEOUT 32757
> +
> +#define SPRAID_WAIT_ABNL_CMD_TIMEOUT (3 * 2)
6?
> +
> +#define SPRAID_DMA_MSK_BIT_MAX 64
> +
> +enum FW_STAT_CODE {
> + FW_STAT_OK = 0,
> + FW_STAT_NEED_CHECK,
> + FW_STAT_ERROR,
> + FW_STAT_EP_PCIE_ERROR,
> + FW_STAT_NAC_DMA_ERROR,
> + FW_STAT_ABORTED,
> + FW_STAT_NEED_RETRY
> +};
> +
> +static int ioq_depth_set(const char *val, const struct kernel_param *kp)
> +{
> + int n = 0;
> + int ret;
> +
> + ret = kstrtoint(val, 10, &n);
> + if (ret != 0 || n < 2)
> + return -EINVAL;
> +
> + return param_set_int(val, kp);
> +}
> +
> +static int spraid_remap_bar(struct spraid_dev *hdev, u32 size)
> +{
> + struct pci_dev *pdev = hdev->pdev;
> +
> + if (size > pci_resource_len(pdev, 0)) {
> + dev_err(hdev->dev, "Input size[%u] exceed bar0 length[%llu]\n",
> + size, pci_resource_len(pdev, 0));
> + return -ENOMEM;
> + }
> +
> + if (hdev->bar)
> + iounmap(hdev->bar);
> +
> + hdev->bar = ioremap(pci_resource_start(pdev, 0), size);
is there a device-managed version of this? pcim_ioremap() maybe?
> + if (!hdev->bar) {
> + dev_err(hdev->dev, "ioremap for bar0 failed\n");
> + return -ENOMEM;
> + }
> + hdev->dbs = hdev->bar + SPRAID_REG_DBS;
> +
> + return 0;
> +}
> +
> +static int spraid_dev_map(struct spraid_dev *hdev)
> +{
> + struct pci_dev *pdev = hdev->pdev;
> + int ret;
> +
> + ret = pci_request_mem_regions(pdev, "spraid");
> + if (ret) {
> + dev_err(hdev->dev, "fail to request memory regions\n");
> + return ret;
> + }
> +
> + ret = spraid_remap_bar(hdev, SPRAID_REG_DBS + 4096);
> + if (ret) {
> + pci_release_mem_regions(pdev);
> + return ret;
> + }
> +
> + return 0;
> +}
> +
> +static void spraid_dev_unmap(struct spraid_dev *hdev)
> +{
> + struct pci_dev *pdev = hdev->pdev;
> +
> + if (hdev->bar) {
> + iounmap(hdev->bar);
> + hdev->bar = NULL;
> + }
> + pci_release_mem_regions(pdev);
again, please check for devm/pcim version of the alloc/request/enable
functions, so that you don't need to do this manually
> +}
> +
> +static int spraid_pci_enable(struct spraid_dev *hdev)
> +{
> + struct pci_dev *pdev = hdev->pdev;
> + int ret = -ENOMEM;
> + u64 maskbit = SPRAID_DMA_MSK_BIT_MAX;
> +
> + if (pci_enable_device_mem(pdev)) {
> + dev_err(hdev->dev, "Enable pci device memory resources failed\n");
> + return ret;
> + }
> + pci_set_master(pdev);
> +
> + if (readl(hdev->bar + SPRAID_REG_CSTS) == U32_MAX) {
> + ret = -ENODEV;
> + dev_err(hdev->dev, "Read csts register failed\n");
> + goto disable;
> + }
> +
> + ret = pci_alloc_irq_vectors(pdev, 1, 1, PCI_IRQ_ALL_TYPES);
> + if (ret < 0) {
> + dev_err(hdev->dev, "Allocate one IRQ for setup admin channel failed\n");
> + goto disable;
> + }
> +
> + hdev->cap = lo_hi_readq(hdev->bar + SPRAID_REG_CAP);
> + hdev->ioq_depth = min_t(u32, SPRAID_CAP_MQES(hdev->cap) + 1, io_queue_depth);
> + hdev->db_stride = 1 << SPRAID_CAP_STRIDE(hdev->cap);
hdev is your host control structure. What is the point of storing values
in it which can easily be derived from other values in the host control
structure?
> +
> + maskbit = SPRAID_CAP_DMAMASK(hdev->cap);
> + if (maskbit < 32 || maskbit > SPRAID_DMA_MSK_BIT_MAX) {
> + dev_err(hdev->dev, "err, dma mask invalid[%llu], set to default\n", maskbit);
> + maskbit = SPRAID_DMA_MSK_BIT_MAX;
> + }
> + if (dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(maskbit))) {
> + dev_err(hdev->dev, "set dma mask and coherent failed\n");
> + goto disable;
> + }
> +
> + dev_info(hdev->dev, "set dma mask[%llu] success\n", maskbit);
> +
> + pci_enable_pcie_error_reporting(pdev);
> + pci_save_state(pdev);
> +
> + return 0;
> +
> +disable:
> + pci_disable_device(pdev);
> + return ret;
> +}
> +
> +static int spraid_npages_prp(u32 size, struct spraid_dev *hdev)
> +{
> + u32 nprps = DIV_ROUND_UP(size + hdev->page_size, hdev->page_size);
> +
> + return DIV_ROUND_UP(PRP_ENTRY_SIZE * nprps, PAGE_SIZE - PRP_ENTRY_SIZE);
> +}
> +
> +static int spraid_npages_sgl(u32 nseg)
> +{
> + return DIV_ROUND_UP(nseg * sizeof(struct spraid_sgl_desc), PAGE_SIZE);
> +}
> +
> +static void **spraid_iod_list(struct spraid_iod *iod)
> +{
> + return (void **)(iod->inline_sg + (iod->sg_drv_mgmt ? iod->nsge : 0));
> +}
> +
> +static u32 spraid_iod_ext_size(struct spraid_dev *hdev, u32 size, u32 nsge,
> + bool sg_drv_mgmt, bool use_sgl)
> +{
> + size_t alloc_size, sg_size;
> +
> + if (use_sgl)
> + alloc_size = sizeof(__le64 *) * spraid_npages_sgl(nsge);
> + else
> + alloc_size = sizeof(__le64 *) * spraid_npages_prp(size, hdev);
> +
> + sg_size = sg_drv_mgmt ? (sizeof(struct scatterlist) * nsge) : 0;
> + return sg_size + alloc_size;
> +}
> +
> +static u32 spraid_cmd_size(struct spraid_dev *hdev, bool sg_drv_mgmt, bool use_sgl)
> +{
> + u32 alloc_size = spraid_iod_ext_size(hdev, SPRAID_INT_BYTES(hdev),
> + SPRAID_INT_PAGES, sg_drv_mgmt, use_sgl);
> +
> + dev_info(hdev->dev, "sg_drv_mgmt: %s, use_sgl: %s, iod size: %lu, alloc_size: %u\n",
> + sg_drv_mgmt ? "true" : "false", use_sgl ? "true" : "false",
> + sizeof(struct spraid_iod), alloc_size);
strange to have a print like this in such a function
> +
> + return sizeof(struct spraid_iod) + alloc_size;
> +}
> +
> +static int spraid_setup_prps(struct spraid_dev *hdev, struct spraid_iod *iod)
> +{
> + struct scatterlist *sg = iod->sg;
> + u64 dma_addr = sg_dma_address(sg);
this should be dma_addr_t
> + int dma_len = sg_dma_len(sg);
this should be unsigned int
> + __le64 *prp_list, *old_prp_list;
> + u32 page_size = hdev->page_size;
> + int offset = dma_addr & (page_size - 1);
> + void **list = spraid_iod_list(iod);
> + int length = iod->length;
> + struct dma_pool *pool;
> + dma_addr_t prp_dma;
> + int nprps, i;
> +
next prev parent reply other threads:[~2022-03-15 14:43 UTC|newest]
Thread overview: 7+ messages / expand[flat|nested] mbox.gz Atom feed top
2022-03-14 2:53 [PATCH v5] scsi:spraid: initial commit of Ramaxel spraid driver Yanling Song
2022-03-15 14:43 ` John Garry [this message]
2022-03-16 23:03 ` Bart Van Assche
2022-03-17 8:46 ` John Garry
2022-03-18 12:52 ` Yanling Song
2022-03-24 16:34 ` John Garry
2022-03-30 2:54 ` Yanling Song
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=ecf79a5c-49f4-cf0e-edf4-9363c8b60bb5@huawei.com \
--to=john.garry@huawei.com \
--cc=bvanassche@acm.org \
--cc=linux-scsi@vger.kernel.org \
--cc=martin.petersen@oracle.com \
--cc=songyl@ramaxel.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox