18c2ecf20Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0-or-later */
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci * iSCSI lib definitions
48c2ecf20Sopenharmony_ci *
58c2ecf20Sopenharmony_ci * Copyright (C) 2006 Red Hat, Inc.  All rights reserved.
68c2ecf20Sopenharmony_ci * Copyright (C) 2004 - 2006 Mike Christie
78c2ecf20Sopenharmony_ci * Copyright (C) 2004 - 2005 Dmitry Yusupov
88c2ecf20Sopenharmony_ci * Copyright (C) 2004 - 2005 Alex Aizman
98c2ecf20Sopenharmony_ci */
108c2ecf20Sopenharmony_ci#ifndef LIBISCSI_H
118c2ecf20Sopenharmony_ci#define LIBISCSI_H
128c2ecf20Sopenharmony_ci
138c2ecf20Sopenharmony_ci#include <linux/types.h>
148c2ecf20Sopenharmony_ci#include <linux/wait.h>
158c2ecf20Sopenharmony_ci#include <linux/mutex.h>
168c2ecf20Sopenharmony_ci#include <linux/timer.h>
178c2ecf20Sopenharmony_ci#include <linux/workqueue.h>
188c2ecf20Sopenharmony_ci#include <linux/kfifo.h>
198c2ecf20Sopenharmony_ci#include <linux/refcount.h>
208c2ecf20Sopenharmony_ci#include <scsi/iscsi_proto.h>
218c2ecf20Sopenharmony_ci#include <scsi/iscsi_if.h>
228c2ecf20Sopenharmony_ci#include <scsi/scsi_transport_iscsi.h>
238c2ecf20Sopenharmony_ci
248c2ecf20Sopenharmony_cistruct scsi_transport_template;
258c2ecf20Sopenharmony_cistruct scsi_host_template;
268c2ecf20Sopenharmony_cistruct scsi_device;
278c2ecf20Sopenharmony_cistruct Scsi_Host;
288c2ecf20Sopenharmony_cistruct scsi_target;
298c2ecf20Sopenharmony_cistruct scsi_cmnd;
308c2ecf20Sopenharmony_cistruct socket;
318c2ecf20Sopenharmony_cistruct iscsi_transport;
328c2ecf20Sopenharmony_cistruct iscsi_cls_session;
338c2ecf20Sopenharmony_cistruct iscsi_cls_conn;
348c2ecf20Sopenharmony_cistruct iscsi_session;
358c2ecf20Sopenharmony_cistruct iscsi_nopin;
368c2ecf20Sopenharmony_cistruct device;
378c2ecf20Sopenharmony_ci
388c2ecf20Sopenharmony_ci#define ISCSI_DEF_XMIT_CMDS_MAX	128	/* must be power of 2 */
398c2ecf20Sopenharmony_ci#define ISCSI_MGMT_CMDS_MAX	15
408c2ecf20Sopenharmony_ci
418c2ecf20Sopenharmony_ci#define ISCSI_DEF_CMD_PER_LUN	32
428c2ecf20Sopenharmony_ci
438c2ecf20Sopenharmony_ci/* Task Mgmt states */
448c2ecf20Sopenharmony_cienum {
458c2ecf20Sopenharmony_ci	TMF_INITIAL,
468c2ecf20Sopenharmony_ci	TMF_QUEUED,
478c2ecf20Sopenharmony_ci	TMF_SUCCESS,
488c2ecf20Sopenharmony_ci	TMF_FAILED,
498c2ecf20Sopenharmony_ci	TMF_TIMEDOUT,
508c2ecf20Sopenharmony_ci	TMF_NOT_FOUND,
518c2ecf20Sopenharmony_ci};
528c2ecf20Sopenharmony_ci
538c2ecf20Sopenharmony_ci#define ISID_SIZE			6
548c2ecf20Sopenharmony_ci
558c2ecf20Sopenharmony_ci/* Connection suspend "bit" */
568c2ecf20Sopenharmony_ci#define ISCSI_SUSPEND_BIT		1
578c2ecf20Sopenharmony_ci
588c2ecf20Sopenharmony_ci#define ISCSI_ITT_MASK			0x1fff
598c2ecf20Sopenharmony_ci#define ISCSI_TOTAL_CMDS_MAX		4096
608c2ecf20Sopenharmony_ci/* this must be a power of two greater than ISCSI_MGMT_CMDS_MAX */
618c2ecf20Sopenharmony_ci#define ISCSI_TOTAL_CMDS_MIN		16
628c2ecf20Sopenharmony_ci#define ISCSI_AGE_SHIFT			28
638c2ecf20Sopenharmony_ci#define ISCSI_AGE_MASK			0xf
648c2ecf20Sopenharmony_ci
658c2ecf20Sopenharmony_ci#define ISCSI_ADDRESS_BUF_LEN		64
668c2ecf20Sopenharmony_ci
678c2ecf20Sopenharmony_cienum {
688c2ecf20Sopenharmony_ci	/* this is the maximum possible storage for AHSs */
698c2ecf20Sopenharmony_ci	ISCSI_MAX_AHS_SIZE = sizeof(struct iscsi_ecdb_ahdr) +
708c2ecf20Sopenharmony_ci				sizeof(struct iscsi_rlength_ahdr),
718c2ecf20Sopenharmony_ci	ISCSI_DIGEST_SIZE = sizeof(__u32),
728c2ecf20Sopenharmony_ci};
738c2ecf20Sopenharmony_ci
748c2ecf20Sopenharmony_ci
758c2ecf20Sopenharmony_cienum {
768c2ecf20Sopenharmony_ci	ISCSI_TASK_FREE,
778c2ecf20Sopenharmony_ci	ISCSI_TASK_COMPLETED,
788c2ecf20Sopenharmony_ci	ISCSI_TASK_PENDING,
798c2ecf20Sopenharmony_ci	ISCSI_TASK_RUNNING,
808c2ecf20Sopenharmony_ci	ISCSI_TASK_ABRT_TMF,		/* aborted due to TMF */
818c2ecf20Sopenharmony_ci	ISCSI_TASK_ABRT_SESS_RECOV,	/* aborted due to session recovery */
828c2ecf20Sopenharmony_ci	ISCSI_TASK_REQUEUE_SCSIQ,	/* qcmd requeueing to scsi-ml */
838c2ecf20Sopenharmony_ci};
848c2ecf20Sopenharmony_ci
858c2ecf20Sopenharmony_cistruct iscsi_r2t_info {
868c2ecf20Sopenharmony_ci	__be32			ttt;		/* copied from R2T */
878c2ecf20Sopenharmony_ci	__be32			exp_statsn;	/* copied from R2T */
888c2ecf20Sopenharmony_ci	uint32_t		data_length;	/* copied from R2T */
898c2ecf20Sopenharmony_ci	uint32_t		data_offset;	/* copied from R2T */
908c2ecf20Sopenharmony_ci	int			data_count;	/* DATA-Out payload progress */
918c2ecf20Sopenharmony_ci	int			datasn;
928c2ecf20Sopenharmony_ci	/* LLDs should set/update these values */
938c2ecf20Sopenharmony_ci	int			sent;		/* R2T sequence progress */
948c2ecf20Sopenharmony_ci};
958c2ecf20Sopenharmony_ci
968c2ecf20Sopenharmony_cistruct iscsi_task {
978c2ecf20Sopenharmony_ci	/*
988c2ecf20Sopenharmony_ci	 * Because LLDs allocate their hdr differently, this is a pointer
998c2ecf20Sopenharmony_ci	 * and length to that storage. It must be setup at session
1008c2ecf20Sopenharmony_ci	 * creation time.
1018c2ecf20Sopenharmony_ci	 */
1028c2ecf20Sopenharmony_ci	struct iscsi_hdr	*hdr;
1038c2ecf20Sopenharmony_ci	unsigned short		hdr_max;
1048c2ecf20Sopenharmony_ci	unsigned short		hdr_len;	/* accumulated size of hdr used */
1058c2ecf20Sopenharmony_ci	/* copied values in case we need to send tmfs */
1068c2ecf20Sopenharmony_ci	itt_t			hdr_itt;
1078c2ecf20Sopenharmony_ci	__be32			cmdsn;
1088c2ecf20Sopenharmony_ci	struct scsi_lun		lun;
1098c2ecf20Sopenharmony_ci
1108c2ecf20Sopenharmony_ci	int			itt;		/* this ITT */
1118c2ecf20Sopenharmony_ci
1128c2ecf20Sopenharmony_ci	unsigned		imm_count;	/* imm-data (bytes)   */
1138c2ecf20Sopenharmony_ci	/* offset in unsolicited stream (bytes); */
1148c2ecf20Sopenharmony_ci	struct iscsi_r2t_info	unsol_r2t;
1158c2ecf20Sopenharmony_ci	char			*data;		/* mgmt payload */
1168c2ecf20Sopenharmony_ci	unsigned		data_count;
1178c2ecf20Sopenharmony_ci	struct scsi_cmnd	*sc;		/* associated SCSI cmd*/
1188c2ecf20Sopenharmony_ci	struct iscsi_conn	*conn;		/* used connection    */
1198c2ecf20Sopenharmony_ci
1208c2ecf20Sopenharmony_ci	/* data processing tracking */
1218c2ecf20Sopenharmony_ci	unsigned long		last_xfer;
1228c2ecf20Sopenharmony_ci	unsigned long		last_timeout;
1238c2ecf20Sopenharmony_ci	bool			have_checked_conn;
1248c2ecf20Sopenharmony_ci
1258c2ecf20Sopenharmony_ci	/* T10 protection information */
1268c2ecf20Sopenharmony_ci	bool			protected;
1278c2ecf20Sopenharmony_ci
1288c2ecf20Sopenharmony_ci	/* state set/tested under session->lock */
1298c2ecf20Sopenharmony_ci	int			state;
1308c2ecf20Sopenharmony_ci	refcount_t		refcount;
1318c2ecf20Sopenharmony_ci	struct list_head	running;	/* running cmd list */
1328c2ecf20Sopenharmony_ci	void			*dd_data;	/* driver/transport data */
1338c2ecf20Sopenharmony_ci};
1348c2ecf20Sopenharmony_ci
1358c2ecf20Sopenharmony_ci/* invalid scsi_task pointer */
1368c2ecf20Sopenharmony_ci#define	INVALID_SCSI_TASK	(struct iscsi_task *)-1l
1378c2ecf20Sopenharmony_ci
1388c2ecf20Sopenharmony_cistatic inline int iscsi_task_has_unsol_data(struct iscsi_task *task)
1398c2ecf20Sopenharmony_ci{
1408c2ecf20Sopenharmony_ci	return task->unsol_r2t.data_length > task->unsol_r2t.sent;
1418c2ecf20Sopenharmony_ci}
1428c2ecf20Sopenharmony_ci
1438c2ecf20Sopenharmony_cistatic inline void* iscsi_next_hdr(struct iscsi_task *task)
1448c2ecf20Sopenharmony_ci{
1458c2ecf20Sopenharmony_ci	return (void*)task->hdr + task->hdr_len;
1468c2ecf20Sopenharmony_ci}
1478c2ecf20Sopenharmony_ci
1488c2ecf20Sopenharmony_ci/* Connection's states */
1498c2ecf20Sopenharmony_cienum {
1508c2ecf20Sopenharmony_ci	ISCSI_CONN_INITIAL_STAGE,
1518c2ecf20Sopenharmony_ci	ISCSI_CONN_STARTED,
1528c2ecf20Sopenharmony_ci	ISCSI_CONN_STOPPED,
1538c2ecf20Sopenharmony_ci	ISCSI_CONN_CLEANUP_WAIT,
1548c2ecf20Sopenharmony_ci};
1558c2ecf20Sopenharmony_ci
1568c2ecf20Sopenharmony_cistruct iscsi_conn {
1578c2ecf20Sopenharmony_ci	struct iscsi_cls_conn	*cls_conn;	/* ptr to class connection */
1588c2ecf20Sopenharmony_ci	void			*dd_data;	/* iscsi_transport data */
1598c2ecf20Sopenharmony_ci	struct iscsi_session	*session;	/* parent session */
1608c2ecf20Sopenharmony_ci	/*
1618c2ecf20Sopenharmony_ci	 * conn_stop() flag: stop to recover, stop to terminate
1628c2ecf20Sopenharmony_ci	 */
1638c2ecf20Sopenharmony_ci        int			stop_stage;
1648c2ecf20Sopenharmony_ci	struct timer_list	transport_timer;
1658c2ecf20Sopenharmony_ci	unsigned long		last_recv;
1668c2ecf20Sopenharmony_ci	unsigned long		last_ping;
1678c2ecf20Sopenharmony_ci	int			ping_timeout;
1688c2ecf20Sopenharmony_ci	int			recv_timeout;
1698c2ecf20Sopenharmony_ci	struct iscsi_task 	*ping_task;
1708c2ecf20Sopenharmony_ci
1718c2ecf20Sopenharmony_ci	/* iSCSI connection-wide sequencing */
1728c2ecf20Sopenharmony_ci	uint32_t		exp_statsn;
1738c2ecf20Sopenharmony_ci	uint32_t		statsn;
1748c2ecf20Sopenharmony_ci
1758c2ecf20Sopenharmony_ci	/* control data */
1768c2ecf20Sopenharmony_ci	int			id;		/* CID */
1778c2ecf20Sopenharmony_ci	int			c_stage;	/* connection state */
1788c2ecf20Sopenharmony_ci	/*
1798c2ecf20Sopenharmony_ci	 * Preallocated buffer for pdus that have data but do not
1808c2ecf20Sopenharmony_ci	 * originate from scsi-ml. We never have two pdus using the
1818c2ecf20Sopenharmony_ci	 * buffer at the same time. It is only allocated to
1828c2ecf20Sopenharmony_ci	 * the default max recv size because the pdus we support
1838c2ecf20Sopenharmony_ci	 * should always fit in this buffer
1848c2ecf20Sopenharmony_ci	 */
1858c2ecf20Sopenharmony_ci	char			*data;
1868c2ecf20Sopenharmony_ci	struct iscsi_task 	*login_task;	/* mtask used for login/text */
1878c2ecf20Sopenharmony_ci	struct iscsi_task	*task;		/* xmit task in progress */
1888c2ecf20Sopenharmony_ci
1898c2ecf20Sopenharmony_ci	/* xmit */
1908c2ecf20Sopenharmony_ci	/* items must be added/deleted under frwd lock */
1918c2ecf20Sopenharmony_ci	struct list_head	mgmtqueue;	/* mgmt (control) xmit queue */
1928c2ecf20Sopenharmony_ci	struct list_head	cmdqueue;	/* data-path cmd queue */
1938c2ecf20Sopenharmony_ci	struct list_head	requeue;	/* tasks needing another run */
1948c2ecf20Sopenharmony_ci	struct work_struct	xmitwork;	/* per-conn. xmit workqueue */
1958c2ecf20Sopenharmony_ci	unsigned long		suspend_tx;	/* suspend Tx */
1968c2ecf20Sopenharmony_ci	unsigned long		suspend_rx;	/* suspend Rx */
1978c2ecf20Sopenharmony_ci
1988c2ecf20Sopenharmony_ci	/* negotiated params */
1998c2ecf20Sopenharmony_ci	unsigned		max_recv_dlength; /* initiator_max_recv_dsl*/
2008c2ecf20Sopenharmony_ci	unsigned		max_xmit_dlength; /* target_max_recv_dsl */
2018c2ecf20Sopenharmony_ci	int			hdrdgst_en;
2028c2ecf20Sopenharmony_ci	int			datadgst_en;
2038c2ecf20Sopenharmony_ci	int			ifmarker_en;
2048c2ecf20Sopenharmony_ci	int			ofmarker_en;
2058c2ecf20Sopenharmony_ci	/* values userspace uses to id a conn */
2068c2ecf20Sopenharmony_ci	int			persistent_port;
2078c2ecf20Sopenharmony_ci	char			*persistent_address;
2088c2ecf20Sopenharmony_ci
2098c2ecf20Sopenharmony_ci	unsigned		max_segment_size;
2108c2ecf20Sopenharmony_ci	unsigned		tcp_xmit_wsf;
2118c2ecf20Sopenharmony_ci	unsigned		tcp_recv_wsf;
2128c2ecf20Sopenharmony_ci	uint16_t		keepalive_tmo;
2138c2ecf20Sopenharmony_ci	uint16_t		local_port;
2148c2ecf20Sopenharmony_ci	uint8_t			tcp_timestamp_stat;
2158c2ecf20Sopenharmony_ci	uint8_t			tcp_nagle_disable;
2168c2ecf20Sopenharmony_ci	uint8_t			tcp_wsf_disable;
2178c2ecf20Sopenharmony_ci	uint8_t			tcp_timer_scale;
2188c2ecf20Sopenharmony_ci	uint8_t			tcp_timestamp_en;
2198c2ecf20Sopenharmony_ci	uint8_t			fragment_disable;
2208c2ecf20Sopenharmony_ci	uint8_t			ipv4_tos;
2218c2ecf20Sopenharmony_ci	uint8_t			ipv6_traffic_class;
2228c2ecf20Sopenharmony_ci	uint8_t			ipv6_flow_label;
2238c2ecf20Sopenharmony_ci	uint8_t			is_fw_assigned_ipv6;
2248c2ecf20Sopenharmony_ci	char			*local_ipaddr;
2258c2ecf20Sopenharmony_ci
2268c2ecf20Sopenharmony_ci	/* MIB-statistics */
2278c2ecf20Sopenharmony_ci	uint64_t		txdata_octets;
2288c2ecf20Sopenharmony_ci	uint64_t		rxdata_octets;
2298c2ecf20Sopenharmony_ci	uint32_t		scsicmd_pdus_cnt;
2308c2ecf20Sopenharmony_ci	uint32_t		dataout_pdus_cnt;
2318c2ecf20Sopenharmony_ci	uint32_t		scsirsp_pdus_cnt;
2328c2ecf20Sopenharmony_ci	uint32_t		datain_pdus_cnt;
2338c2ecf20Sopenharmony_ci	uint32_t		r2t_pdus_cnt;
2348c2ecf20Sopenharmony_ci	uint32_t		tmfcmd_pdus_cnt;
2358c2ecf20Sopenharmony_ci	int32_t			tmfrsp_pdus_cnt;
2368c2ecf20Sopenharmony_ci
2378c2ecf20Sopenharmony_ci	/* custom statistics */
2388c2ecf20Sopenharmony_ci	uint32_t		eh_abort_cnt;
2398c2ecf20Sopenharmony_ci	uint32_t		fmr_unalign_cnt;
2408c2ecf20Sopenharmony_ci};
2418c2ecf20Sopenharmony_ci
2428c2ecf20Sopenharmony_cistruct iscsi_pool {
2438c2ecf20Sopenharmony_ci	struct kfifo		queue;		/* FIFO Queue */
2448c2ecf20Sopenharmony_ci	void			**pool;		/* Pool of elements */
2458c2ecf20Sopenharmony_ci	int			max;		/* Max number of elements */
2468c2ecf20Sopenharmony_ci};
2478c2ecf20Sopenharmony_ci
2488c2ecf20Sopenharmony_ci/* Session's states */
2498c2ecf20Sopenharmony_cienum {
2508c2ecf20Sopenharmony_ci	ISCSI_STATE_FREE = 1,
2518c2ecf20Sopenharmony_ci	ISCSI_STATE_LOGGED_IN,
2528c2ecf20Sopenharmony_ci	ISCSI_STATE_FAILED,
2538c2ecf20Sopenharmony_ci	ISCSI_STATE_TERMINATE,
2548c2ecf20Sopenharmony_ci	ISCSI_STATE_IN_RECOVERY,
2558c2ecf20Sopenharmony_ci	ISCSI_STATE_RECOVERY_FAILED,
2568c2ecf20Sopenharmony_ci	ISCSI_STATE_LOGGING_OUT,
2578c2ecf20Sopenharmony_ci};
2588c2ecf20Sopenharmony_ci
2598c2ecf20Sopenharmony_cistruct iscsi_session {
2608c2ecf20Sopenharmony_ci	struct iscsi_cls_session *cls_session;
2618c2ecf20Sopenharmony_ci	/*
2628c2ecf20Sopenharmony_ci	 * Syncs up the scsi eh thread with the iscsi eh thread when sending
2638c2ecf20Sopenharmony_ci	 * task management functions. This must be taken before the session
2648c2ecf20Sopenharmony_ci	 * and recv lock.
2658c2ecf20Sopenharmony_ci	 */
2668c2ecf20Sopenharmony_ci	struct mutex		eh_mutex;
2678c2ecf20Sopenharmony_ci	/* abort */
2688c2ecf20Sopenharmony_ci	wait_queue_head_t	ehwait;		/* used in eh_abort() */
2698c2ecf20Sopenharmony_ci	struct iscsi_tm		tmhdr;
2708c2ecf20Sopenharmony_ci	struct timer_list	tmf_timer;
2718c2ecf20Sopenharmony_ci	int			tmf_state;	/* see TMF_INITIAL, etc.*/
2728c2ecf20Sopenharmony_ci
2738c2ecf20Sopenharmony_ci	/* iSCSI session-wide sequencing */
2748c2ecf20Sopenharmony_ci	uint32_t		cmdsn;
2758c2ecf20Sopenharmony_ci	uint32_t		exp_cmdsn;
2768c2ecf20Sopenharmony_ci	uint32_t		max_cmdsn;
2778c2ecf20Sopenharmony_ci
2788c2ecf20Sopenharmony_ci	/* This tracks the reqs queued into the initiator */
2798c2ecf20Sopenharmony_ci	uint32_t		queued_cmdsn;
2808c2ecf20Sopenharmony_ci
2818c2ecf20Sopenharmony_ci	/* configuration */
2828c2ecf20Sopenharmony_ci	int			abort_timeout;
2838c2ecf20Sopenharmony_ci	int			lu_reset_timeout;
2848c2ecf20Sopenharmony_ci	int			tgt_reset_timeout;
2858c2ecf20Sopenharmony_ci	int			initial_r2t_en;
2868c2ecf20Sopenharmony_ci	unsigned short		max_r2t;
2878c2ecf20Sopenharmony_ci	int			imm_data_en;
2888c2ecf20Sopenharmony_ci	unsigned		first_burst;
2898c2ecf20Sopenharmony_ci	unsigned		max_burst;
2908c2ecf20Sopenharmony_ci	int			time2wait;
2918c2ecf20Sopenharmony_ci	int			time2retain;
2928c2ecf20Sopenharmony_ci	int			pdu_inorder_en;
2938c2ecf20Sopenharmony_ci	int			dataseq_inorder_en;
2948c2ecf20Sopenharmony_ci	int			erl;
2958c2ecf20Sopenharmony_ci	int			fast_abort;
2968c2ecf20Sopenharmony_ci	int			tpgt;
2978c2ecf20Sopenharmony_ci	char			*username;
2988c2ecf20Sopenharmony_ci	char			*username_in;
2998c2ecf20Sopenharmony_ci	char			*password;
3008c2ecf20Sopenharmony_ci	char			*password_in;
3018c2ecf20Sopenharmony_ci	char			*targetname;
3028c2ecf20Sopenharmony_ci	char			*targetalias;
3038c2ecf20Sopenharmony_ci	char			*ifacename;
3048c2ecf20Sopenharmony_ci	char			*initiatorname;
3058c2ecf20Sopenharmony_ci	char			*boot_root;
3068c2ecf20Sopenharmony_ci	char			*boot_nic;
3078c2ecf20Sopenharmony_ci	char			*boot_target;
3088c2ecf20Sopenharmony_ci	char			*portal_type;
3098c2ecf20Sopenharmony_ci	char			*discovery_parent_type;
3108c2ecf20Sopenharmony_ci	uint16_t		discovery_parent_idx;
3118c2ecf20Sopenharmony_ci	uint16_t		def_taskmgmt_tmo;
3128c2ecf20Sopenharmony_ci	uint16_t		tsid;
3138c2ecf20Sopenharmony_ci	uint8_t			auto_snd_tgt_disable;
3148c2ecf20Sopenharmony_ci	uint8_t			discovery_sess;
3158c2ecf20Sopenharmony_ci	uint8_t			chap_auth_en;
3168c2ecf20Sopenharmony_ci	uint8_t			discovery_logout_en;
3178c2ecf20Sopenharmony_ci	uint8_t			bidi_chap_en;
3188c2ecf20Sopenharmony_ci	uint8_t			discovery_auth_optional;
3198c2ecf20Sopenharmony_ci	uint8_t			isid[ISID_SIZE];
3208c2ecf20Sopenharmony_ci
3218c2ecf20Sopenharmony_ci	/* control data */
3228c2ecf20Sopenharmony_ci	struct iscsi_transport	*tt;
3238c2ecf20Sopenharmony_ci	struct Scsi_Host	*host;
3248c2ecf20Sopenharmony_ci	struct iscsi_conn	*leadconn;	/* leading connection */
3258c2ecf20Sopenharmony_ci	/* Between the forward and the backward locks exists a strict locking
3268c2ecf20Sopenharmony_ci	 * hierarchy. The mutual exclusion zone protected by the forward lock
3278c2ecf20Sopenharmony_ci	 * can enclose the mutual exclusion zone protected by the backward lock
3288c2ecf20Sopenharmony_ci	 * but not vice versa.
3298c2ecf20Sopenharmony_ci	 */
3308c2ecf20Sopenharmony_ci	spinlock_t		frwd_lock;	/* protects session state, *
3318c2ecf20Sopenharmony_ci						 * cmdsn, queued_cmdsn     *
3328c2ecf20Sopenharmony_ci						 * session resources:      *
3338c2ecf20Sopenharmony_ci						 * - cmdpool kfifo_out ,   *
3348c2ecf20Sopenharmony_ci						 * - mgmtpool, queues	   */
3358c2ecf20Sopenharmony_ci	spinlock_t		back_lock;	/* protects cmdsn_exp      *
3368c2ecf20Sopenharmony_ci						 * cmdsn_max,              *
3378c2ecf20Sopenharmony_ci						 * cmdpool kfifo_in        */
3388c2ecf20Sopenharmony_ci	int			state;		/* session state           */
3398c2ecf20Sopenharmony_ci	int			age;		/* counts session re-opens */
3408c2ecf20Sopenharmony_ci
3418c2ecf20Sopenharmony_ci	int			scsi_cmds_max; 	/* max scsi commands */
3428c2ecf20Sopenharmony_ci	int			cmds_max;	/* size of cmds array */
3438c2ecf20Sopenharmony_ci	struct iscsi_task	**cmds;		/* Original Cmds arr */
3448c2ecf20Sopenharmony_ci	struct iscsi_pool	cmdpool;	/* PDU's pool */
3458c2ecf20Sopenharmony_ci	void			*dd_data;	/* LLD private data */
3468c2ecf20Sopenharmony_ci};
3478c2ecf20Sopenharmony_ci
3488c2ecf20Sopenharmony_cienum {
3498c2ecf20Sopenharmony_ci	ISCSI_HOST_SETUP,
3508c2ecf20Sopenharmony_ci	ISCSI_HOST_REMOVED,
3518c2ecf20Sopenharmony_ci};
3528c2ecf20Sopenharmony_ci
3538c2ecf20Sopenharmony_cistruct iscsi_host {
3548c2ecf20Sopenharmony_ci	char			*initiatorname;
3558c2ecf20Sopenharmony_ci	/* hw address or netdev iscsi connection is bound to */
3568c2ecf20Sopenharmony_ci	char			*hwaddress;
3578c2ecf20Sopenharmony_ci	char			*netdev;
3588c2ecf20Sopenharmony_ci
3598c2ecf20Sopenharmony_ci	wait_queue_head_t	session_removal_wq;
3608c2ecf20Sopenharmony_ci	/* protects sessions and state */
3618c2ecf20Sopenharmony_ci	spinlock_t		lock;
3628c2ecf20Sopenharmony_ci	int			num_sessions;
3638c2ecf20Sopenharmony_ci	int			state;
3648c2ecf20Sopenharmony_ci
3658c2ecf20Sopenharmony_ci	struct workqueue_struct	*workq;
3668c2ecf20Sopenharmony_ci	char			workq_name[20];
3678c2ecf20Sopenharmony_ci};
3688c2ecf20Sopenharmony_ci
3698c2ecf20Sopenharmony_ci/*
3708c2ecf20Sopenharmony_ci * scsi host template
3718c2ecf20Sopenharmony_ci */
3728c2ecf20Sopenharmony_ciextern int iscsi_eh_abort(struct scsi_cmnd *sc);
3738c2ecf20Sopenharmony_ciextern int iscsi_eh_recover_target(struct scsi_cmnd *sc);
3748c2ecf20Sopenharmony_ciextern int iscsi_eh_session_reset(struct scsi_cmnd *sc);
3758c2ecf20Sopenharmony_ciextern int iscsi_eh_device_reset(struct scsi_cmnd *sc);
3768c2ecf20Sopenharmony_ciextern int iscsi_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *sc);
3778c2ecf20Sopenharmony_ciextern enum blk_eh_timer_return iscsi_eh_cmd_timed_out(struct scsi_cmnd *sc);
3788c2ecf20Sopenharmony_ci
3798c2ecf20Sopenharmony_ci/*
3808c2ecf20Sopenharmony_ci * iSCSI host helpers.
3818c2ecf20Sopenharmony_ci */
3828c2ecf20Sopenharmony_ci#define iscsi_host_priv(_shost) \
3838c2ecf20Sopenharmony_ci	(shost_priv(_shost) + sizeof(struct iscsi_host))
3848c2ecf20Sopenharmony_ci
3858c2ecf20Sopenharmony_ciextern int iscsi_host_set_param(struct Scsi_Host *shost,
3868c2ecf20Sopenharmony_ci				enum iscsi_host_param param, char *buf,
3878c2ecf20Sopenharmony_ci				int buflen);
3888c2ecf20Sopenharmony_ciextern int iscsi_host_get_param(struct Scsi_Host *shost,
3898c2ecf20Sopenharmony_ci				enum iscsi_host_param param, char *buf);
3908c2ecf20Sopenharmony_ciextern int iscsi_host_add(struct Scsi_Host *shost, struct device *pdev);
3918c2ecf20Sopenharmony_ciextern struct Scsi_Host *iscsi_host_alloc(struct scsi_host_template *sht,
3928c2ecf20Sopenharmony_ci					  int dd_data_size,
3938c2ecf20Sopenharmony_ci					  bool xmit_can_sleep);
3948c2ecf20Sopenharmony_ciextern void iscsi_host_remove(struct Scsi_Host *shost);
3958c2ecf20Sopenharmony_ciextern void iscsi_host_free(struct Scsi_Host *shost);
3968c2ecf20Sopenharmony_ciextern int iscsi_target_alloc(struct scsi_target *starget);
3978c2ecf20Sopenharmony_ciextern int iscsi_host_get_max_scsi_cmds(struct Scsi_Host *shost,
3988c2ecf20Sopenharmony_ci					uint16_t requested_cmds_max);
3998c2ecf20Sopenharmony_ci
4008c2ecf20Sopenharmony_ci/*
4018c2ecf20Sopenharmony_ci * session management
4028c2ecf20Sopenharmony_ci */
4038c2ecf20Sopenharmony_ciextern struct iscsi_cls_session *
4048c2ecf20Sopenharmony_ciiscsi_session_setup(struct iscsi_transport *, struct Scsi_Host *shost,
4058c2ecf20Sopenharmony_ci		    uint16_t, int, int, uint32_t, unsigned int);
4068c2ecf20Sopenharmony_ciextern void iscsi_session_teardown(struct iscsi_cls_session *);
4078c2ecf20Sopenharmony_ciextern void iscsi_session_recovery_timedout(struct iscsi_cls_session *);
4088c2ecf20Sopenharmony_ciextern int iscsi_set_param(struct iscsi_cls_conn *cls_conn,
4098c2ecf20Sopenharmony_ci			   enum iscsi_param param, char *buf, int buflen);
4108c2ecf20Sopenharmony_ciextern int iscsi_session_get_param(struct iscsi_cls_session *cls_session,
4118c2ecf20Sopenharmony_ci				   enum iscsi_param param, char *buf);
4128c2ecf20Sopenharmony_ci
4138c2ecf20Sopenharmony_ci#define iscsi_session_printk(prefix, _sess, fmt, a...)	\
4148c2ecf20Sopenharmony_ci	iscsi_cls_session_printk(prefix, _sess->cls_session, fmt, ##a)
4158c2ecf20Sopenharmony_ci
4168c2ecf20Sopenharmony_ci/*
4178c2ecf20Sopenharmony_ci * connection management
4188c2ecf20Sopenharmony_ci */
4198c2ecf20Sopenharmony_ciextern struct iscsi_cls_conn *iscsi_conn_setup(struct iscsi_cls_session *,
4208c2ecf20Sopenharmony_ci					       int, uint32_t);
4218c2ecf20Sopenharmony_ciextern void iscsi_conn_teardown(struct iscsi_cls_conn *);
4228c2ecf20Sopenharmony_ciextern int iscsi_conn_start(struct iscsi_cls_conn *);
4238c2ecf20Sopenharmony_ciextern void iscsi_conn_stop(struct iscsi_cls_conn *, int);
4248c2ecf20Sopenharmony_ciextern int iscsi_conn_bind(struct iscsi_cls_session *, struct iscsi_cls_conn *,
4258c2ecf20Sopenharmony_ci			   int);
4268c2ecf20Sopenharmony_ciextern void iscsi_conn_unbind(struct iscsi_cls_conn *cls_conn, bool is_active);
4278c2ecf20Sopenharmony_ciextern void iscsi_conn_failure(struct iscsi_conn *conn, enum iscsi_err err);
4288c2ecf20Sopenharmony_ciextern void iscsi_session_failure(struct iscsi_session *session,
4298c2ecf20Sopenharmony_ci				  enum iscsi_err err);
4308c2ecf20Sopenharmony_ciextern int iscsi_conn_get_param(struct iscsi_cls_conn *cls_conn,
4318c2ecf20Sopenharmony_ci				enum iscsi_param param, char *buf);
4328c2ecf20Sopenharmony_ciextern int iscsi_conn_get_addr_param(struct sockaddr_storage *addr,
4338c2ecf20Sopenharmony_ci				     enum iscsi_param param, char *buf);
4348c2ecf20Sopenharmony_ciextern void iscsi_suspend_tx(struct iscsi_conn *conn);
4358c2ecf20Sopenharmony_ciextern void iscsi_suspend_queue(struct iscsi_conn *conn);
4368c2ecf20Sopenharmony_ciextern void iscsi_conn_queue_work(struct iscsi_conn *conn);
4378c2ecf20Sopenharmony_ci
4388c2ecf20Sopenharmony_ci#define iscsi_conn_printk(prefix, _c, fmt, a...) \
4398c2ecf20Sopenharmony_ci	iscsi_cls_conn_printk(prefix, ((struct iscsi_conn *)_c)->cls_conn, \
4408c2ecf20Sopenharmony_ci			      fmt, ##a)
4418c2ecf20Sopenharmony_ci
4428c2ecf20Sopenharmony_ci/*
4438c2ecf20Sopenharmony_ci * pdu and task processing
4448c2ecf20Sopenharmony_ci */
4458c2ecf20Sopenharmony_ciextern void iscsi_update_cmdsn(struct iscsi_session *, struct iscsi_nopin *);
4468c2ecf20Sopenharmony_ciextern void iscsi_prep_data_out_pdu(struct iscsi_task *task,
4478c2ecf20Sopenharmony_ci				    struct iscsi_r2t_info *r2t,
4488c2ecf20Sopenharmony_ci				    struct iscsi_data *hdr);
4498c2ecf20Sopenharmony_ciextern int iscsi_conn_send_pdu(struct iscsi_cls_conn *, struct iscsi_hdr *,
4508c2ecf20Sopenharmony_ci				char *, uint32_t);
4518c2ecf20Sopenharmony_ciextern int iscsi_complete_pdu(struct iscsi_conn *, struct iscsi_hdr *,
4528c2ecf20Sopenharmony_ci			      char *, int);
4538c2ecf20Sopenharmony_ciextern int __iscsi_complete_pdu(struct iscsi_conn *, struct iscsi_hdr *,
4548c2ecf20Sopenharmony_ci				char *, int);
4558c2ecf20Sopenharmony_ciextern int iscsi_verify_itt(struct iscsi_conn *, itt_t);
4568c2ecf20Sopenharmony_ciextern struct iscsi_task *iscsi_itt_to_ctask(struct iscsi_conn *, itt_t);
4578c2ecf20Sopenharmony_ciextern struct iscsi_task *iscsi_itt_to_task(struct iscsi_conn *, itt_t);
4588c2ecf20Sopenharmony_ciextern void iscsi_requeue_task(struct iscsi_task *task);
4598c2ecf20Sopenharmony_ciextern void iscsi_put_task(struct iscsi_task *task);
4608c2ecf20Sopenharmony_ciextern void __iscsi_put_task(struct iscsi_task *task);
4618c2ecf20Sopenharmony_ciextern void __iscsi_get_task(struct iscsi_task *task);
4628c2ecf20Sopenharmony_ciextern void iscsi_complete_scsi_task(struct iscsi_task *task,
4638c2ecf20Sopenharmony_ci				     uint32_t exp_cmdsn, uint32_t max_cmdsn);
4648c2ecf20Sopenharmony_ci
4658c2ecf20Sopenharmony_ci/*
4668c2ecf20Sopenharmony_ci * generic helpers
4678c2ecf20Sopenharmony_ci */
4688c2ecf20Sopenharmony_ciextern void iscsi_pool_free(struct iscsi_pool *);
4698c2ecf20Sopenharmony_ciextern int iscsi_pool_init(struct iscsi_pool *, int, void ***, int);
4708c2ecf20Sopenharmony_ciextern int iscsi_switch_str_param(char **, char *);
4718c2ecf20Sopenharmony_ci
4728c2ecf20Sopenharmony_ci/*
4738c2ecf20Sopenharmony_ci * inline functions to deal with padding.
4748c2ecf20Sopenharmony_ci */
4758c2ecf20Sopenharmony_cistatic inline unsigned int
4768c2ecf20Sopenharmony_ciiscsi_padded(unsigned int len)
4778c2ecf20Sopenharmony_ci{
4788c2ecf20Sopenharmony_ci	return (len + ISCSI_PAD_LEN - 1) & ~(ISCSI_PAD_LEN - 1);
4798c2ecf20Sopenharmony_ci}
4808c2ecf20Sopenharmony_ci
4818c2ecf20Sopenharmony_cistatic inline unsigned int
4828c2ecf20Sopenharmony_ciiscsi_padding(unsigned int len)
4838c2ecf20Sopenharmony_ci{
4848c2ecf20Sopenharmony_ci	len &= (ISCSI_PAD_LEN - 1);
4858c2ecf20Sopenharmony_ci	if (len)
4868c2ecf20Sopenharmony_ci		len = ISCSI_PAD_LEN - len;
4878c2ecf20Sopenharmony_ci	return len;
4888c2ecf20Sopenharmony_ci}
4898c2ecf20Sopenharmony_ci
4908c2ecf20Sopenharmony_ci#endif
491