162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */
262306a36Sopenharmony_ci#include <linux/socket.h>
362306a36Sopenharmony_ci#include <linux/in.h>
462306a36Sopenharmony_ci#include <linux/in6.h>
562306a36Sopenharmony_ci#include <rdma/ib_verbs.h>
662306a36Sopenharmony_ci#include <rdma/rdma_cm.h>
762306a36Sopenharmony_ci#include <rdma/rw.h>
862306a36Sopenharmony_ci#include <scsi/iser.h>
962306a36Sopenharmony_ci
1062306a36Sopenharmony_ci
1162306a36Sopenharmony_ci#define DRV_NAME	"isert"
1262306a36Sopenharmony_ci#define PFX		DRV_NAME ": "
1362306a36Sopenharmony_ci
1462306a36Sopenharmony_ci#define isert_dbg(fmt, arg...)				 \
1562306a36Sopenharmony_ci	do {						 \
1662306a36Sopenharmony_ci		if (unlikely(isert_debug_level > 2))	 \
1762306a36Sopenharmony_ci			printk(KERN_DEBUG PFX "%s: " fmt,\
1862306a36Sopenharmony_ci				__func__ , ## arg);	 \
1962306a36Sopenharmony_ci	} while (0)
2062306a36Sopenharmony_ci
2162306a36Sopenharmony_ci#define isert_warn(fmt, arg...)				\
2262306a36Sopenharmony_ci	do {						\
2362306a36Sopenharmony_ci		if (unlikely(isert_debug_level > 0))	\
2462306a36Sopenharmony_ci			pr_warn(PFX "%s: " fmt,         \
2562306a36Sopenharmony_ci				__func__ , ## arg);	\
2662306a36Sopenharmony_ci	} while (0)
2762306a36Sopenharmony_ci
2862306a36Sopenharmony_ci#define isert_info(fmt, arg...)				\
2962306a36Sopenharmony_ci	do {						\
3062306a36Sopenharmony_ci		if (unlikely(isert_debug_level > 1))	\
3162306a36Sopenharmony_ci			pr_info(PFX "%s: " fmt,         \
3262306a36Sopenharmony_ci				__func__ , ## arg);	\
3362306a36Sopenharmony_ci	} while (0)
3462306a36Sopenharmony_ci
3562306a36Sopenharmony_ci#define isert_err(fmt, arg...) \
3662306a36Sopenharmony_ci	pr_err(PFX "%s: " fmt, __func__ , ## arg)
3762306a36Sopenharmony_ci
3862306a36Sopenharmony_ci/* Constant PDU lengths calculations */
3962306a36Sopenharmony_ci#define ISER_HEADERS_LEN	(sizeof(struct iser_ctrl) + \
4062306a36Sopenharmony_ci				 sizeof(struct iscsi_hdr))
4162306a36Sopenharmony_ci#define ISER_RX_PAYLOAD_SIZE	(ISER_HEADERS_LEN + ISCSI_DEF_MAX_RECV_SEG_LEN)
4262306a36Sopenharmony_ci
4362306a36Sopenharmony_ci/* QP settings */
4462306a36Sopenharmony_ci/* Maximal bounds on received asynchronous PDUs */
4562306a36Sopenharmony_ci#define ISERT_MAX_TX_MISC_PDUS	4 /* NOOP_IN(2) , ASYNC_EVENT(2)   */
4662306a36Sopenharmony_ci
4762306a36Sopenharmony_ci#define ISERT_MAX_RX_MISC_PDUS	6 /*
4862306a36Sopenharmony_ci				   * NOOP_OUT(2), TEXT(1),
4962306a36Sopenharmony_ci				   * SCSI_TMFUNC(2), LOGOUT(1)
5062306a36Sopenharmony_ci				   */
5162306a36Sopenharmony_ci
5262306a36Sopenharmony_ci#define ISCSI_DEF_XMIT_CMDS_MAX 128 /* from libiscsi.h, must be power of 2 */
5362306a36Sopenharmony_ci
5462306a36Sopenharmony_ci#define ISERT_QP_MAX_RECV_DTOS	(ISCSI_DEF_XMIT_CMDS_MAX)
5562306a36Sopenharmony_ci
5662306a36Sopenharmony_ci#define ISERT_MIN_POSTED_RX	(ISCSI_DEF_XMIT_CMDS_MAX >> 2)
5762306a36Sopenharmony_ci
5862306a36Sopenharmony_ci#define ISERT_QP_MAX_REQ_DTOS	(ISCSI_DEF_XMIT_CMDS_MAX +    \
5962306a36Sopenharmony_ci				ISERT_MAX_TX_MISC_PDUS	+ \
6062306a36Sopenharmony_ci				ISERT_MAX_RX_MISC_PDUS)
6162306a36Sopenharmony_ci
6262306a36Sopenharmony_ci/*
6362306a36Sopenharmony_ci * RX size is default of 8k plus headers, but data needs to align to
6462306a36Sopenharmony_ci * 512 boundary, so use 1024 to have the extra space for alignment.
6562306a36Sopenharmony_ci */
6662306a36Sopenharmony_ci#define ISER_RX_SIZE		(ISCSI_DEF_MAX_RECV_SEG_LEN + 1024)
6762306a36Sopenharmony_ci
6862306a36Sopenharmony_ci/* Minimum I/O size is 512KB */
6962306a36Sopenharmony_ci#define ISCSI_ISER_MIN_SG_TABLESIZE 128
7062306a36Sopenharmony_ci
7162306a36Sopenharmony_ci/* Maximum support is 16MB I/O size */
7262306a36Sopenharmony_ci#define ISCSI_ISER_MAX_SG_TABLESIZE	4096
7362306a36Sopenharmony_ci
7462306a36Sopenharmony_cienum isert_desc_type {
7562306a36Sopenharmony_ci	ISCSI_TX_CONTROL,
7662306a36Sopenharmony_ci	ISCSI_TX_DATAIN
7762306a36Sopenharmony_ci};
7862306a36Sopenharmony_ci
7962306a36Sopenharmony_cienum iser_conn_state {
8062306a36Sopenharmony_ci	ISER_CONN_INIT,
8162306a36Sopenharmony_ci	ISER_CONN_UP,
8262306a36Sopenharmony_ci	ISER_CONN_BOUND,
8362306a36Sopenharmony_ci	ISER_CONN_FULL_FEATURE,
8462306a36Sopenharmony_ci	ISER_CONN_TERMINATING,
8562306a36Sopenharmony_ci	ISER_CONN_DOWN,
8662306a36Sopenharmony_ci};
8762306a36Sopenharmony_ci
8862306a36Sopenharmony_cistruct iser_rx_desc {
8962306a36Sopenharmony_ci	char		buf[ISER_RX_SIZE];
9062306a36Sopenharmony_ci	u64		dma_addr;
9162306a36Sopenharmony_ci	struct ib_sge	rx_sg;
9262306a36Sopenharmony_ci	struct ib_cqe	rx_cqe;
9362306a36Sopenharmony_ci	bool		in_use;
9462306a36Sopenharmony_ci};
9562306a36Sopenharmony_ci
9662306a36Sopenharmony_cistatic inline struct iser_rx_desc *cqe_to_rx_desc(struct ib_cqe *cqe)
9762306a36Sopenharmony_ci{
9862306a36Sopenharmony_ci	return container_of(cqe, struct iser_rx_desc, rx_cqe);
9962306a36Sopenharmony_ci}
10062306a36Sopenharmony_ci
10162306a36Sopenharmony_cistatic void *isert_get_iser_hdr(struct iser_rx_desc *desc)
10262306a36Sopenharmony_ci{
10362306a36Sopenharmony_ci	return PTR_ALIGN(desc->buf + ISER_HEADERS_LEN, 512) - ISER_HEADERS_LEN;
10462306a36Sopenharmony_ci}
10562306a36Sopenharmony_ci
10662306a36Sopenharmony_cistatic size_t isert_get_hdr_offset(struct iser_rx_desc *desc)
10762306a36Sopenharmony_ci{
10862306a36Sopenharmony_ci	return isert_get_iser_hdr(desc) - (void *)desc->buf;
10962306a36Sopenharmony_ci}
11062306a36Sopenharmony_ci
11162306a36Sopenharmony_cistatic void *isert_get_iscsi_hdr(struct iser_rx_desc *desc)
11262306a36Sopenharmony_ci{
11362306a36Sopenharmony_ci	return isert_get_iser_hdr(desc) + sizeof(struct iser_ctrl);
11462306a36Sopenharmony_ci}
11562306a36Sopenharmony_ci
11662306a36Sopenharmony_cistatic void *isert_get_data(struct iser_rx_desc *desc)
11762306a36Sopenharmony_ci{
11862306a36Sopenharmony_ci	void *data = isert_get_iser_hdr(desc) + ISER_HEADERS_LEN;
11962306a36Sopenharmony_ci
12062306a36Sopenharmony_ci	WARN_ON((uintptr_t)data & 511);
12162306a36Sopenharmony_ci	return data;
12262306a36Sopenharmony_ci}
12362306a36Sopenharmony_ci
12462306a36Sopenharmony_cistruct iser_tx_desc {
12562306a36Sopenharmony_ci	struct iser_ctrl iser_header;
12662306a36Sopenharmony_ci	struct iscsi_hdr iscsi_header;
12762306a36Sopenharmony_ci	enum isert_desc_type type;
12862306a36Sopenharmony_ci	u64		dma_addr;
12962306a36Sopenharmony_ci	struct ib_sge	tx_sg[2];
13062306a36Sopenharmony_ci	struct ib_cqe	tx_cqe;
13162306a36Sopenharmony_ci	int		num_sge;
13262306a36Sopenharmony_ci	struct ib_send_wr send_wr;
13362306a36Sopenharmony_ci} __packed;
13462306a36Sopenharmony_ci
13562306a36Sopenharmony_cistatic inline struct iser_tx_desc *cqe_to_tx_desc(struct ib_cqe *cqe)
13662306a36Sopenharmony_ci{
13762306a36Sopenharmony_ci	return container_of(cqe, struct iser_tx_desc, tx_cqe);
13862306a36Sopenharmony_ci}
13962306a36Sopenharmony_ci
14062306a36Sopenharmony_cistruct isert_cmd {
14162306a36Sopenharmony_ci	uint32_t		read_stag;
14262306a36Sopenharmony_ci	uint32_t		write_stag;
14362306a36Sopenharmony_ci	uint64_t		read_va;
14462306a36Sopenharmony_ci	uint64_t		write_va;
14562306a36Sopenharmony_ci	uint32_t		inv_rkey;
14662306a36Sopenharmony_ci	u64			pdu_buf_dma;
14762306a36Sopenharmony_ci	u32			pdu_buf_len;
14862306a36Sopenharmony_ci	struct isert_conn	*conn;
14962306a36Sopenharmony_ci	struct iscsit_cmd	*iscsit_cmd;
15062306a36Sopenharmony_ci	struct iser_tx_desc	tx_desc;
15162306a36Sopenharmony_ci	struct iser_rx_desc	*rx_desc;
15262306a36Sopenharmony_ci	struct rdma_rw_ctx	rw;
15362306a36Sopenharmony_ci	struct work_struct	comp_work;
15462306a36Sopenharmony_ci	struct scatterlist	sg;
15562306a36Sopenharmony_ci	bool			ctx_init_done;
15662306a36Sopenharmony_ci};
15762306a36Sopenharmony_ci
15862306a36Sopenharmony_cistatic inline struct isert_cmd *tx_desc_to_cmd(struct iser_tx_desc *desc)
15962306a36Sopenharmony_ci{
16062306a36Sopenharmony_ci	return container_of(desc, struct isert_cmd, tx_desc);
16162306a36Sopenharmony_ci}
16262306a36Sopenharmony_ci
16362306a36Sopenharmony_cistruct isert_device;
16462306a36Sopenharmony_ci
16562306a36Sopenharmony_cistruct isert_conn {
16662306a36Sopenharmony_ci	enum iser_conn_state	state;
16762306a36Sopenharmony_ci	u32			responder_resources;
16862306a36Sopenharmony_ci	u32			initiator_depth;
16962306a36Sopenharmony_ci	bool			pi_support;
17062306a36Sopenharmony_ci	struct iser_rx_desc	*login_desc;
17162306a36Sopenharmony_ci	char			*login_rsp_buf;
17262306a36Sopenharmony_ci	int			login_req_len;
17362306a36Sopenharmony_ci	u64			login_rsp_dma;
17462306a36Sopenharmony_ci	struct iser_rx_desc	*rx_descs;
17562306a36Sopenharmony_ci	struct ib_recv_wr	rx_wr[ISERT_QP_MAX_RECV_DTOS];
17662306a36Sopenharmony_ci	struct iscsit_conn	*conn;
17762306a36Sopenharmony_ci	struct list_head	node;
17862306a36Sopenharmony_ci	struct completion	login_comp;
17962306a36Sopenharmony_ci	struct completion	login_req_comp;
18062306a36Sopenharmony_ci	struct iser_tx_desc	login_tx_desc;
18162306a36Sopenharmony_ci	struct rdma_cm_id	*cm_id;
18262306a36Sopenharmony_ci	struct ib_qp		*qp;
18362306a36Sopenharmony_ci	struct ib_cq		*cq;
18462306a36Sopenharmony_ci	u32			cq_size;
18562306a36Sopenharmony_ci	struct isert_device	*device;
18662306a36Sopenharmony_ci	struct mutex		mutex;
18762306a36Sopenharmony_ci	struct kref		kref;
18862306a36Sopenharmony_ci	struct work_struct	release_work;
18962306a36Sopenharmony_ci	bool                    logout_posted;
19062306a36Sopenharmony_ci	bool                    snd_w_inv;
19162306a36Sopenharmony_ci	wait_queue_head_t	rem_wait;
19262306a36Sopenharmony_ci	bool			dev_removed;
19362306a36Sopenharmony_ci};
19462306a36Sopenharmony_ci
19562306a36Sopenharmony_cistruct isert_device {
19662306a36Sopenharmony_ci	bool			pi_capable;
19762306a36Sopenharmony_ci	int			refcount;
19862306a36Sopenharmony_ci	struct ib_device	*ib_device;
19962306a36Sopenharmony_ci	struct ib_pd		*pd;
20062306a36Sopenharmony_ci	struct isert_comp	*comps;
20162306a36Sopenharmony_ci	int                     comps_used;
20262306a36Sopenharmony_ci	struct list_head	dev_node;
20362306a36Sopenharmony_ci};
20462306a36Sopenharmony_ci
20562306a36Sopenharmony_cistruct isert_np {
20662306a36Sopenharmony_ci	struct iscsi_np         *np;
20762306a36Sopenharmony_ci	struct semaphore	sem;
20862306a36Sopenharmony_ci	struct rdma_cm_id	*cm_id;
20962306a36Sopenharmony_ci	struct mutex		mutex;
21062306a36Sopenharmony_ci	struct list_head	accepted;
21162306a36Sopenharmony_ci	struct list_head	pending;
21262306a36Sopenharmony_ci};
213