162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0-or-later */ 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * iSCSI lib definitions 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * Copyright (C) 2006 Red Hat, Inc. All rights reserved. 662306a36Sopenharmony_ci * Copyright (C) 2004 - 2006 Mike Christie 762306a36Sopenharmony_ci * Copyright (C) 2004 - 2005 Dmitry Yusupov 862306a36Sopenharmony_ci * Copyright (C) 2004 - 2005 Alex Aizman 962306a36Sopenharmony_ci */ 1062306a36Sopenharmony_ci#ifndef LIBISCSI_H 1162306a36Sopenharmony_ci#define LIBISCSI_H 1262306a36Sopenharmony_ci 1362306a36Sopenharmony_ci#include <linux/types.h> 1462306a36Sopenharmony_ci#include <linux/wait.h> 1562306a36Sopenharmony_ci#include <linux/mutex.h> 1662306a36Sopenharmony_ci#include <linux/timer.h> 1762306a36Sopenharmony_ci#include <linux/workqueue.h> 1862306a36Sopenharmony_ci#include <linux/kfifo.h> 1962306a36Sopenharmony_ci#include <linux/refcount.h> 2062306a36Sopenharmony_ci#include <scsi/iscsi_proto.h> 2162306a36Sopenharmony_ci#include <scsi/iscsi_if.h> 2262306a36Sopenharmony_ci#include <scsi/scsi_cmnd.h> 2362306a36Sopenharmony_ci#include <scsi/scsi_transport_iscsi.h> 2462306a36Sopenharmony_ci 2562306a36Sopenharmony_cistruct scsi_transport_template; 2662306a36Sopenharmony_cistruct scsi_host_template; 2762306a36Sopenharmony_cistruct scsi_device; 2862306a36Sopenharmony_cistruct Scsi_Host; 2962306a36Sopenharmony_cistruct scsi_target; 3062306a36Sopenharmony_cistruct scsi_cmnd; 3162306a36Sopenharmony_cistruct socket; 3262306a36Sopenharmony_cistruct iscsi_transport; 3362306a36Sopenharmony_cistruct iscsi_cls_session; 3462306a36Sopenharmony_cistruct iscsi_cls_conn; 3562306a36Sopenharmony_cistruct iscsi_session; 3662306a36Sopenharmony_cistruct iscsi_nopin; 3762306a36Sopenharmony_cistruct device; 3862306a36Sopenharmony_ci 3962306a36Sopenharmony_ci#define ISCSI_DEF_XMIT_CMDS_MAX 128 /* must be power of 2 */ 4062306a36Sopenharmony_ci#define ISCSI_MGMT_CMDS_MAX 15 4162306a36Sopenharmony_ci 4262306a36Sopenharmony_ci#define ISCSI_DEF_CMD_PER_LUN 32 4362306a36Sopenharmony_ci 4462306a36Sopenharmony_ci/* Task Mgmt states */ 4562306a36Sopenharmony_cienum { 4662306a36Sopenharmony_ci TMF_INITIAL, 4762306a36Sopenharmony_ci TMF_QUEUED, 4862306a36Sopenharmony_ci TMF_SUCCESS, 4962306a36Sopenharmony_ci TMF_FAILED, 5062306a36Sopenharmony_ci TMF_TIMEDOUT, 5162306a36Sopenharmony_ci TMF_NOT_FOUND, 5262306a36Sopenharmony_ci}; 5362306a36Sopenharmony_ci 5462306a36Sopenharmony_ci#define ISID_SIZE 6 5562306a36Sopenharmony_ci 5662306a36Sopenharmony_ci/* Connection flags */ 5762306a36Sopenharmony_ci#define ISCSI_CONN_FLAG_SUSPEND_TX 0 5862306a36Sopenharmony_ci#define ISCSI_CONN_FLAG_SUSPEND_RX 1 5962306a36Sopenharmony_ci#define ISCSI_CONN_FLAG_BOUND 2 6062306a36Sopenharmony_ci 6162306a36Sopenharmony_ci#define ISCSI_ITT_MASK 0x1fff 6262306a36Sopenharmony_ci#define ISCSI_TOTAL_CMDS_MAX 4096 6362306a36Sopenharmony_ci/* this must be a power of two greater than ISCSI_MGMT_CMDS_MAX */ 6462306a36Sopenharmony_ci#define ISCSI_TOTAL_CMDS_MIN 16 6562306a36Sopenharmony_ci#define ISCSI_AGE_SHIFT 28 6662306a36Sopenharmony_ci#define ISCSI_AGE_MASK 0xf 6762306a36Sopenharmony_ci 6862306a36Sopenharmony_ci#define ISCSI_ADDRESS_BUF_LEN 64 6962306a36Sopenharmony_ci 7062306a36Sopenharmony_cienum { 7162306a36Sopenharmony_ci /* this is the maximum possible storage for AHSs */ 7262306a36Sopenharmony_ci ISCSI_MAX_AHS_SIZE = sizeof(struct iscsi_ecdb_ahdr) + 7362306a36Sopenharmony_ci sizeof(struct iscsi_rlength_ahdr), 7462306a36Sopenharmony_ci ISCSI_DIGEST_SIZE = sizeof(__u32), 7562306a36Sopenharmony_ci}; 7662306a36Sopenharmony_ci 7762306a36Sopenharmony_ci 7862306a36Sopenharmony_cienum { 7962306a36Sopenharmony_ci ISCSI_TASK_FREE, 8062306a36Sopenharmony_ci ISCSI_TASK_COMPLETED, 8162306a36Sopenharmony_ci ISCSI_TASK_PENDING, 8262306a36Sopenharmony_ci ISCSI_TASK_RUNNING, 8362306a36Sopenharmony_ci ISCSI_TASK_ABRT_TMF, /* aborted due to TMF */ 8462306a36Sopenharmony_ci ISCSI_TASK_ABRT_SESS_RECOV, /* aborted due to session recovery */ 8562306a36Sopenharmony_ci ISCSI_TASK_REQUEUE_SCSIQ, /* qcmd requeueing to scsi-ml */ 8662306a36Sopenharmony_ci}; 8762306a36Sopenharmony_ci 8862306a36Sopenharmony_cistruct iscsi_r2t_info { 8962306a36Sopenharmony_ci __be32 ttt; /* copied from R2T */ 9062306a36Sopenharmony_ci __be32 exp_statsn; /* copied from R2T */ 9162306a36Sopenharmony_ci uint32_t data_length; /* copied from R2T */ 9262306a36Sopenharmony_ci uint32_t data_offset; /* copied from R2T */ 9362306a36Sopenharmony_ci int data_count; /* DATA-Out payload progress */ 9462306a36Sopenharmony_ci int datasn; 9562306a36Sopenharmony_ci /* LLDs should set/update these values */ 9662306a36Sopenharmony_ci int sent; /* R2T sequence progress */ 9762306a36Sopenharmony_ci}; 9862306a36Sopenharmony_ci 9962306a36Sopenharmony_cistruct iscsi_task { 10062306a36Sopenharmony_ci /* 10162306a36Sopenharmony_ci * Because LLDs allocate their hdr differently, this is a pointer 10262306a36Sopenharmony_ci * and length to that storage. It must be setup at session 10362306a36Sopenharmony_ci * creation time. 10462306a36Sopenharmony_ci */ 10562306a36Sopenharmony_ci struct iscsi_hdr *hdr; 10662306a36Sopenharmony_ci unsigned short hdr_max; 10762306a36Sopenharmony_ci unsigned short hdr_len; /* accumulated size of hdr used */ 10862306a36Sopenharmony_ci /* copied values in case we need to send tmfs */ 10962306a36Sopenharmony_ci itt_t hdr_itt; 11062306a36Sopenharmony_ci __be32 cmdsn; 11162306a36Sopenharmony_ci struct scsi_lun lun; 11262306a36Sopenharmony_ci 11362306a36Sopenharmony_ci int itt; /* this ITT */ 11462306a36Sopenharmony_ci 11562306a36Sopenharmony_ci unsigned imm_count; /* imm-data (bytes) */ 11662306a36Sopenharmony_ci /* offset in unsolicited stream (bytes); */ 11762306a36Sopenharmony_ci struct iscsi_r2t_info unsol_r2t; 11862306a36Sopenharmony_ci char *data; /* mgmt payload */ 11962306a36Sopenharmony_ci unsigned data_count; 12062306a36Sopenharmony_ci struct scsi_cmnd *sc; /* associated SCSI cmd*/ 12162306a36Sopenharmony_ci struct iscsi_conn *conn; /* used connection */ 12262306a36Sopenharmony_ci 12362306a36Sopenharmony_ci /* data processing tracking */ 12462306a36Sopenharmony_ci unsigned long last_xfer; 12562306a36Sopenharmony_ci unsigned long last_timeout; 12662306a36Sopenharmony_ci bool have_checked_conn; 12762306a36Sopenharmony_ci 12862306a36Sopenharmony_ci /* T10 protection information */ 12962306a36Sopenharmony_ci bool protected; 13062306a36Sopenharmony_ci 13162306a36Sopenharmony_ci /* state set/tested under session->lock */ 13262306a36Sopenharmony_ci int state; 13362306a36Sopenharmony_ci refcount_t refcount; 13462306a36Sopenharmony_ci struct list_head running; /* running cmd list */ 13562306a36Sopenharmony_ci void *dd_data; /* driver/transport data */ 13662306a36Sopenharmony_ci}; 13762306a36Sopenharmony_ci 13862306a36Sopenharmony_cistatic inline int iscsi_task_has_unsol_data(struct iscsi_task *task) 13962306a36Sopenharmony_ci{ 14062306a36Sopenharmony_ci return task->unsol_r2t.data_length > task->unsol_r2t.sent; 14162306a36Sopenharmony_ci} 14262306a36Sopenharmony_ci 14362306a36Sopenharmony_cistatic inline void* iscsi_next_hdr(struct iscsi_task *task) 14462306a36Sopenharmony_ci{ 14562306a36Sopenharmony_ci return (void*)task->hdr + task->hdr_len; 14662306a36Sopenharmony_ci} 14762306a36Sopenharmony_ci 14862306a36Sopenharmony_cistatic inline bool iscsi_task_is_completed(struct iscsi_task *task) 14962306a36Sopenharmony_ci{ 15062306a36Sopenharmony_ci return task->state == ISCSI_TASK_COMPLETED || 15162306a36Sopenharmony_ci task->state == ISCSI_TASK_ABRT_TMF || 15262306a36Sopenharmony_ci task->state == ISCSI_TASK_ABRT_SESS_RECOV; 15362306a36Sopenharmony_ci} 15462306a36Sopenharmony_ci 15562306a36Sopenharmony_ci/* Private data associated with struct scsi_cmnd. */ 15662306a36Sopenharmony_cistruct iscsi_cmd { 15762306a36Sopenharmony_ci struct iscsi_task *task; 15862306a36Sopenharmony_ci int age; 15962306a36Sopenharmony_ci}; 16062306a36Sopenharmony_ci 16162306a36Sopenharmony_cistatic inline struct iscsi_cmd *iscsi_cmd(struct scsi_cmnd *cmd) 16262306a36Sopenharmony_ci{ 16362306a36Sopenharmony_ci return scsi_cmd_priv(cmd); 16462306a36Sopenharmony_ci} 16562306a36Sopenharmony_ci 16662306a36Sopenharmony_ci/* Connection's states */ 16762306a36Sopenharmony_cienum { 16862306a36Sopenharmony_ci ISCSI_CONN_INITIAL_STAGE, 16962306a36Sopenharmony_ci ISCSI_CONN_STARTED, 17062306a36Sopenharmony_ci ISCSI_CONN_STOPPED, 17162306a36Sopenharmony_ci ISCSI_CONN_CLEANUP_WAIT, 17262306a36Sopenharmony_ci}; 17362306a36Sopenharmony_ci 17462306a36Sopenharmony_cistruct iscsi_conn { 17562306a36Sopenharmony_ci struct iscsi_cls_conn *cls_conn; /* ptr to class connection */ 17662306a36Sopenharmony_ci void *dd_data; /* iscsi_transport data */ 17762306a36Sopenharmony_ci struct iscsi_session *session; /* parent session */ 17862306a36Sopenharmony_ci /* 17962306a36Sopenharmony_ci * conn_stop() flag: stop to recover, stop to terminate 18062306a36Sopenharmony_ci */ 18162306a36Sopenharmony_ci int stop_stage; 18262306a36Sopenharmony_ci struct timer_list transport_timer; 18362306a36Sopenharmony_ci unsigned long last_recv; 18462306a36Sopenharmony_ci unsigned long last_ping; 18562306a36Sopenharmony_ci int ping_timeout; 18662306a36Sopenharmony_ci int recv_timeout; 18762306a36Sopenharmony_ci struct iscsi_task *ping_task; 18862306a36Sopenharmony_ci 18962306a36Sopenharmony_ci /* iSCSI connection-wide sequencing */ 19062306a36Sopenharmony_ci uint32_t exp_statsn; 19162306a36Sopenharmony_ci uint32_t statsn; 19262306a36Sopenharmony_ci 19362306a36Sopenharmony_ci /* control data */ 19462306a36Sopenharmony_ci int id; /* CID */ 19562306a36Sopenharmony_ci int c_stage; /* connection state */ 19662306a36Sopenharmony_ci /* 19762306a36Sopenharmony_ci * Preallocated buffer for pdus that have data but do not 19862306a36Sopenharmony_ci * originate from scsi-ml. We never have two pdus using the 19962306a36Sopenharmony_ci * buffer at the same time. It is only allocated to 20062306a36Sopenharmony_ci * the default max recv size because the pdus we support 20162306a36Sopenharmony_ci * should always fit in this buffer 20262306a36Sopenharmony_ci */ 20362306a36Sopenharmony_ci char *data; 20462306a36Sopenharmony_ci struct iscsi_task *login_task; /* mtask used for login/text */ 20562306a36Sopenharmony_ci struct iscsi_task *task; /* xmit task in progress */ 20662306a36Sopenharmony_ci 20762306a36Sopenharmony_ci /* xmit */ 20862306a36Sopenharmony_ci /* items must be added/deleted under frwd lock */ 20962306a36Sopenharmony_ci struct list_head mgmtqueue; /* mgmt (control) xmit queue */ 21062306a36Sopenharmony_ci struct list_head cmdqueue; /* data-path cmd queue */ 21162306a36Sopenharmony_ci struct list_head requeue; /* tasks needing another run */ 21262306a36Sopenharmony_ci struct work_struct xmitwork; /* per-conn. xmit workqueue */ 21362306a36Sopenharmony_ci /* recv */ 21462306a36Sopenharmony_ci struct work_struct recvwork; 21562306a36Sopenharmony_ci unsigned long flags; /* ISCSI_CONN_FLAGs */ 21662306a36Sopenharmony_ci 21762306a36Sopenharmony_ci /* negotiated params */ 21862306a36Sopenharmony_ci unsigned max_recv_dlength; /* initiator_max_recv_dsl*/ 21962306a36Sopenharmony_ci unsigned max_xmit_dlength; /* target_max_recv_dsl */ 22062306a36Sopenharmony_ci int hdrdgst_en; 22162306a36Sopenharmony_ci int datadgst_en; 22262306a36Sopenharmony_ci int ifmarker_en; 22362306a36Sopenharmony_ci int ofmarker_en; 22462306a36Sopenharmony_ci /* values userspace uses to id a conn */ 22562306a36Sopenharmony_ci int persistent_port; 22662306a36Sopenharmony_ci char *persistent_address; 22762306a36Sopenharmony_ci 22862306a36Sopenharmony_ci unsigned max_segment_size; 22962306a36Sopenharmony_ci unsigned tcp_xmit_wsf; 23062306a36Sopenharmony_ci unsigned tcp_recv_wsf; 23162306a36Sopenharmony_ci uint16_t keepalive_tmo; 23262306a36Sopenharmony_ci uint16_t local_port; 23362306a36Sopenharmony_ci uint8_t tcp_timestamp_stat; 23462306a36Sopenharmony_ci uint8_t tcp_nagle_disable; 23562306a36Sopenharmony_ci uint8_t tcp_wsf_disable; 23662306a36Sopenharmony_ci uint8_t tcp_timer_scale; 23762306a36Sopenharmony_ci uint8_t tcp_timestamp_en; 23862306a36Sopenharmony_ci uint8_t fragment_disable; 23962306a36Sopenharmony_ci uint8_t ipv4_tos; 24062306a36Sopenharmony_ci uint8_t ipv6_traffic_class; 24162306a36Sopenharmony_ci uint8_t ipv6_flow_label; 24262306a36Sopenharmony_ci uint8_t is_fw_assigned_ipv6; 24362306a36Sopenharmony_ci char *local_ipaddr; 24462306a36Sopenharmony_ci 24562306a36Sopenharmony_ci /* MIB-statistics */ 24662306a36Sopenharmony_ci uint64_t txdata_octets; 24762306a36Sopenharmony_ci uint64_t rxdata_octets; 24862306a36Sopenharmony_ci uint32_t scsicmd_pdus_cnt; 24962306a36Sopenharmony_ci uint32_t dataout_pdus_cnt; 25062306a36Sopenharmony_ci uint32_t scsirsp_pdus_cnt; 25162306a36Sopenharmony_ci uint32_t datain_pdus_cnt; 25262306a36Sopenharmony_ci uint32_t r2t_pdus_cnt; 25362306a36Sopenharmony_ci uint32_t tmfcmd_pdus_cnt; 25462306a36Sopenharmony_ci int32_t tmfrsp_pdus_cnt; 25562306a36Sopenharmony_ci 25662306a36Sopenharmony_ci /* custom statistics */ 25762306a36Sopenharmony_ci uint32_t eh_abort_cnt; 25862306a36Sopenharmony_ci uint32_t fmr_unalign_cnt; 25962306a36Sopenharmony_ci}; 26062306a36Sopenharmony_ci 26162306a36Sopenharmony_cistruct iscsi_pool { 26262306a36Sopenharmony_ci struct kfifo queue; /* FIFO Queue */ 26362306a36Sopenharmony_ci void **pool; /* Pool of elements */ 26462306a36Sopenharmony_ci int max; /* Max number of elements */ 26562306a36Sopenharmony_ci}; 26662306a36Sopenharmony_ci 26762306a36Sopenharmony_ci/* Session's states */ 26862306a36Sopenharmony_cienum { 26962306a36Sopenharmony_ci ISCSI_STATE_FREE = 1, 27062306a36Sopenharmony_ci ISCSI_STATE_LOGGED_IN, 27162306a36Sopenharmony_ci ISCSI_STATE_FAILED, 27262306a36Sopenharmony_ci ISCSI_STATE_TERMINATE, 27362306a36Sopenharmony_ci ISCSI_STATE_IN_RECOVERY, 27462306a36Sopenharmony_ci ISCSI_STATE_RECOVERY_FAILED, 27562306a36Sopenharmony_ci ISCSI_STATE_LOGGING_OUT, 27662306a36Sopenharmony_ci}; 27762306a36Sopenharmony_ci 27862306a36Sopenharmony_cistruct iscsi_session { 27962306a36Sopenharmony_ci struct iscsi_cls_session *cls_session; 28062306a36Sopenharmony_ci /* 28162306a36Sopenharmony_ci * Syncs up the scsi eh thread with the iscsi eh thread when sending 28262306a36Sopenharmony_ci * task management functions. This must be taken before the session 28362306a36Sopenharmony_ci * and recv lock. 28462306a36Sopenharmony_ci */ 28562306a36Sopenharmony_ci struct mutex eh_mutex; 28662306a36Sopenharmony_ci /* abort */ 28762306a36Sopenharmony_ci wait_queue_head_t ehwait; /* used in eh_abort() */ 28862306a36Sopenharmony_ci struct iscsi_tm tmhdr; 28962306a36Sopenharmony_ci struct timer_list tmf_timer; 29062306a36Sopenharmony_ci int tmf_state; /* see TMF_INITIAL, etc.*/ 29162306a36Sopenharmony_ci struct iscsi_task *running_aborted_task; 29262306a36Sopenharmony_ci 29362306a36Sopenharmony_ci /* iSCSI session-wide sequencing */ 29462306a36Sopenharmony_ci uint32_t cmdsn; 29562306a36Sopenharmony_ci uint32_t exp_cmdsn; 29662306a36Sopenharmony_ci uint32_t max_cmdsn; 29762306a36Sopenharmony_ci 29862306a36Sopenharmony_ci /* This tracks the reqs queued into the initiator */ 29962306a36Sopenharmony_ci uint32_t queued_cmdsn; 30062306a36Sopenharmony_ci 30162306a36Sopenharmony_ci /* configuration */ 30262306a36Sopenharmony_ci int abort_timeout; 30362306a36Sopenharmony_ci int lu_reset_timeout; 30462306a36Sopenharmony_ci int tgt_reset_timeout; 30562306a36Sopenharmony_ci int initial_r2t_en; 30662306a36Sopenharmony_ci unsigned short max_r2t; 30762306a36Sopenharmony_ci int imm_data_en; 30862306a36Sopenharmony_ci unsigned first_burst; 30962306a36Sopenharmony_ci unsigned max_burst; 31062306a36Sopenharmony_ci int time2wait; 31162306a36Sopenharmony_ci int time2retain; 31262306a36Sopenharmony_ci int pdu_inorder_en; 31362306a36Sopenharmony_ci int dataseq_inorder_en; 31462306a36Sopenharmony_ci int erl; 31562306a36Sopenharmony_ci int fast_abort; 31662306a36Sopenharmony_ci int tpgt; 31762306a36Sopenharmony_ci char *username; 31862306a36Sopenharmony_ci char *username_in; 31962306a36Sopenharmony_ci char *password; 32062306a36Sopenharmony_ci char *password_in; 32162306a36Sopenharmony_ci char *targetname; 32262306a36Sopenharmony_ci char *targetalias; 32362306a36Sopenharmony_ci char *ifacename; 32462306a36Sopenharmony_ci char *initiatorname; 32562306a36Sopenharmony_ci char *boot_root; 32662306a36Sopenharmony_ci char *boot_nic; 32762306a36Sopenharmony_ci char *boot_target; 32862306a36Sopenharmony_ci char *portal_type; 32962306a36Sopenharmony_ci char *discovery_parent_type; 33062306a36Sopenharmony_ci uint16_t discovery_parent_idx; 33162306a36Sopenharmony_ci uint16_t def_taskmgmt_tmo; 33262306a36Sopenharmony_ci uint16_t tsid; 33362306a36Sopenharmony_ci uint8_t auto_snd_tgt_disable; 33462306a36Sopenharmony_ci uint8_t discovery_sess; 33562306a36Sopenharmony_ci uint8_t chap_auth_en; 33662306a36Sopenharmony_ci uint8_t discovery_logout_en; 33762306a36Sopenharmony_ci uint8_t bidi_chap_en; 33862306a36Sopenharmony_ci uint8_t discovery_auth_optional; 33962306a36Sopenharmony_ci uint8_t isid[ISID_SIZE]; 34062306a36Sopenharmony_ci 34162306a36Sopenharmony_ci /* control data */ 34262306a36Sopenharmony_ci struct iscsi_transport *tt; 34362306a36Sopenharmony_ci struct Scsi_Host *host; 34462306a36Sopenharmony_ci struct iscsi_conn *leadconn; /* leading connection */ 34562306a36Sopenharmony_ci /* Between the forward and the backward locks exists a strict locking 34662306a36Sopenharmony_ci * hierarchy. The mutual exclusion zone protected by the forward lock 34762306a36Sopenharmony_ci * can enclose the mutual exclusion zone protected by the backward lock 34862306a36Sopenharmony_ci * but not vice versa. 34962306a36Sopenharmony_ci */ 35062306a36Sopenharmony_ci spinlock_t frwd_lock; /* protects session state, * 35162306a36Sopenharmony_ci * cmdsn, queued_cmdsn * 35262306a36Sopenharmony_ci * session resources: * 35362306a36Sopenharmony_ci * - cmdpool kfifo_out , * 35462306a36Sopenharmony_ci * - mgmtpool, queues */ 35562306a36Sopenharmony_ci spinlock_t back_lock; /* protects cmdsn_exp * 35662306a36Sopenharmony_ci * cmdsn_max, * 35762306a36Sopenharmony_ci * cmdpool kfifo_in */ 35862306a36Sopenharmony_ci int state; /* session state */ 35962306a36Sopenharmony_ci int age; /* counts session re-opens */ 36062306a36Sopenharmony_ci 36162306a36Sopenharmony_ci int scsi_cmds_max; /* max scsi commands */ 36262306a36Sopenharmony_ci int cmds_max; /* size of cmds array */ 36362306a36Sopenharmony_ci struct iscsi_task **cmds; /* Original Cmds arr */ 36462306a36Sopenharmony_ci struct iscsi_pool cmdpool; /* PDU's pool */ 36562306a36Sopenharmony_ci void *dd_data; /* LLD private data */ 36662306a36Sopenharmony_ci}; 36762306a36Sopenharmony_ci 36862306a36Sopenharmony_cienum { 36962306a36Sopenharmony_ci ISCSI_HOST_SETUP, 37062306a36Sopenharmony_ci ISCSI_HOST_REMOVED, 37162306a36Sopenharmony_ci}; 37262306a36Sopenharmony_ci 37362306a36Sopenharmony_cistruct iscsi_host { 37462306a36Sopenharmony_ci char *initiatorname; 37562306a36Sopenharmony_ci /* hw address or netdev iscsi connection is bound to */ 37662306a36Sopenharmony_ci char *hwaddress; 37762306a36Sopenharmony_ci char *netdev; 37862306a36Sopenharmony_ci 37962306a36Sopenharmony_ci wait_queue_head_t session_removal_wq; 38062306a36Sopenharmony_ci /* protects sessions and state */ 38162306a36Sopenharmony_ci spinlock_t lock; 38262306a36Sopenharmony_ci int num_sessions; 38362306a36Sopenharmony_ci int state; 38462306a36Sopenharmony_ci 38562306a36Sopenharmony_ci struct workqueue_struct *workq; 38662306a36Sopenharmony_ci}; 38762306a36Sopenharmony_ci 38862306a36Sopenharmony_ci/* 38962306a36Sopenharmony_ci * scsi host template 39062306a36Sopenharmony_ci */ 39162306a36Sopenharmony_ciextern int iscsi_eh_abort(struct scsi_cmnd *sc); 39262306a36Sopenharmony_ciextern int iscsi_eh_recover_target(struct scsi_cmnd *sc); 39362306a36Sopenharmony_ciextern int iscsi_eh_session_reset(struct scsi_cmnd *sc); 39462306a36Sopenharmony_ciextern int iscsi_eh_device_reset(struct scsi_cmnd *sc); 39562306a36Sopenharmony_ciextern int iscsi_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *sc); 39662306a36Sopenharmony_ciextern enum scsi_timeout_action iscsi_eh_cmd_timed_out(struct scsi_cmnd *sc); 39762306a36Sopenharmony_ci 39862306a36Sopenharmony_ci/* 39962306a36Sopenharmony_ci * iSCSI host helpers. 40062306a36Sopenharmony_ci */ 40162306a36Sopenharmony_ci#define iscsi_host_priv(_shost) \ 40262306a36Sopenharmony_ci (shost_priv(_shost) + sizeof(struct iscsi_host)) 40362306a36Sopenharmony_ci 40462306a36Sopenharmony_ciextern int iscsi_host_set_param(struct Scsi_Host *shost, 40562306a36Sopenharmony_ci enum iscsi_host_param param, char *buf, 40662306a36Sopenharmony_ci int buflen); 40762306a36Sopenharmony_ciextern int iscsi_host_get_param(struct Scsi_Host *shost, 40862306a36Sopenharmony_ci enum iscsi_host_param param, char *buf); 40962306a36Sopenharmony_ciextern int iscsi_host_add(struct Scsi_Host *shost, struct device *pdev); 41062306a36Sopenharmony_ciextern struct Scsi_Host *iscsi_host_alloc(const struct scsi_host_template *sht, 41162306a36Sopenharmony_ci int dd_data_size, 41262306a36Sopenharmony_ci bool xmit_can_sleep); 41362306a36Sopenharmony_ciextern void iscsi_host_remove(struct Scsi_Host *shost, bool is_shutdown); 41462306a36Sopenharmony_ciextern void iscsi_host_free(struct Scsi_Host *shost); 41562306a36Sopenharmony_ciextern int iscsi_target_alloc(struct scsi_target *starget); 41662306a36Sopenharmony_ciextern int iscsi_host_get_max_scsi_cmds(struct Scsi_Host *shost, 41762306a36Sopenharmony_ci uint16_t requested_cmds_max); 41862306a36Sopenharmony_ci 41962306a36Sopenharmony_ci/* 42062306a36Sopenharmony_ci * session management 42162306a36Sopenharmony_ci */ 42262306a36Sopenharmony_ciextern struct iscsi_cls_session * 42362306a36Sopenharmony_ciiscsi_session_setup(struct iscsi_transport *, struct Scsi_Host *shost, 42462306a36Sopenharmony_ci uint16_t, int, int, uint32_t, unsigned int); 42562306a36Sopenharmony_civoid iscsi_session_remove(struct iscsi_cls_session *cls_session); 42662306a36Sopenharmony_civoid iscsi_session_free(struct iscsi_cls_session *cls_session); 42762306a36Sopenharmony_ciextern void iscsi_session_teardown(struct iscsi_cls_session *); 42862306a36Sopenharmony_ciextern void iscsi_session_recovery_timedout(struct iscsi_cls_session *); 42962306a36Sopenharmony_ciextern int iscsi_set_param(struct iscsi_cls_conn *cls_conn, 43062306a36Sopenharmony_ci enum iscsi_param param, char *buf, int buflen); 43162306a36Sopenharmony_ciextern int iscsi_session_get_param(struct iscsi_cls_session *cls_session, 43262306a36Sopenharmony_ci enum iscsi_param param, char *buf); 43362306a36Sopenharmony_ci 43462306a36Sopenharmony_ci#define iscsi_session_printk(prefix, _sess, fmt, a...) \ 43562306a36Sopenharmony_ci iscsi_cls_session_printk(prefix, _sess->cls_session, fmt, ##a) 43662306a36Sopenharmony_ci 43762306a36Sopenharmony_ci/* 43862306a36Sopenharmony_ci * connection management 43962306a36Sopenharmony_ci */ 44062306a36Sopenharmony_ciextern struct iscsi_cls_conn *iscsi_conn_setup(struct iscsi_cls_session *, 44162306a36Sopenharmony_ci int, uint32_t); 44262306a36Sopenharmony_ciextern void iscsi_conn_teardown(struct iscsi_cls_conn *); 44362306a36Sopenharmony_ciextern int iscsi_conn_start(struct iscsi_cls_conn *); 44462306a36Sopenharmony_ciextern void iscsi_conn_stop(struct iscsi_cls_conn *, int); 44562306a36Sopenharmony_ciextern int iscsi_conn_bind(struct iscsi_cls_session *, struct iscsi_cls_conn *, 44662306a36Sopenharmony_ci int); 44762306a36Sopenharmony_ciextern void iscsi_conn_unbind(struct iscsi_cls_conn *cls_conn, bool is_active); 44862306a36Sopenharmony_ciextern void iscsi_conn_failure(struct iscsi_conn *conn, enum iscsi_err err); 44962306a36Sopenharmony_ciextern void iscsi_session_failure(struct iscsi_session *session, 45062306a36Sopenharmony_ci enum iscsi_err err); 45162306a36Sopenharmony_ciextern int iscsi_conn_get_param(struct iscsi_cls_conn *cls_conn, 45262306a36Sopenharmony_ci enum iscsi_param param, char *buf); 45362306a36Sopenharmony_ciextern int iscsi_conn_get_addr_param(struct sockaddr_storage *addr, 45462306a36Sopenharmony_ci enum iscsi_param param, char *buf); 45562306a36Sopenharmony_ciextern void iscsi_suspend_tx(struct iscsi_conn *conn); 45662306a36Sopenharmony_ciextern void iscsi_suspend_rx(struct iscsi_conn *conn); 45762306a36Sopenharmony_ciextern void iscsi_suspend_queue(struct iscsi_conn *conn); 45862306a36Sopenharmony_ciextern void iscsi_conn_queue_xmit(struct iscsi_conn *conn); 45962306a36Sopenharmony_ciextern void iscsi_conn_queue_recv(struct iscsi_conn *conn); 46062306a36Sopenharmony_ci 46162306a36Sopenharmony_ci#define iscsi_conn_printk(prefix, _c, fmt, a...) \ 46262306a36Sopenharmony_ci iscsi_cls_conn_printk(prefix, ((struct iscsi_conn *)_c)->cls_conn, \ 46362306a36Sopenharmony_ci fmt, ##a) 46462306a36Sopenharmony_ci 46562306a36Sopenharmony_ci/* 46662306a36Sopenharmony_ci * pdu and task processing 46762306a36Sopenharmony_ci */ 46862306a36Sopenharmony_ciextern void iscsi_update_cmdsn(struct iscsi_session *, struct iscsi_nopin *); 46962306a36Sopenharmony_ciextern void iscsi_prep_data_out_pdu(struct iscsi_task *task, 47062306a36Sopenharmony_ci struct iscsi_r2t_info *r2t, 47162306a36Sopenharmony_ci struct iscsi_data *hdr); 47262306a36Sopenharmony_ciextern int iscsi_conn_send_pdu(struct iscsi_cls_conn *, struct iscsi_hdr *, 47362306a36Sopenharmony_ci char *, uint32_t); 47462306a36Sopenharmony_ciextern int iscsi_complete_pdu(struct iscsi_conn *, struct iscsi_hdr *, 47562306a36Sopenharmony_ci char *, int); 47662306a36Sopenharmony_ciextern int __iscsi_complete_pdu(struct iscsi_conn *, struct iscsi_hdr *, 47762306a36Sopenharmony_ci char *, int); 47862306a36Sopenharmony_ciextern int iscsi_verify_itt(struct iscsi_conn *, itt_t); 47962306a36Sopenharmony_ciextern struct iscsi_task *iscsi_itt_to_ctask(struct iscsi_conn *, itt_t); 48062306a36Sopenharmony_ciextern struct iscsi_task *iscsi_itt_to_task(struct iscsi_conn *, itt_t); 48162306a36Sopenharmony_ciextern void iscsi_requeue_task(struct iscsi_task *task); 48262306a36Sopenharmony_ciextern void iscsi_put_task(struct iscsi_task *task); 48362306a36Sopenharmony_ciextern void __iscsi_put_task(struct iscsi_task *task); 48462306a36Sopenharmony_ciextern bool iscsi_get_task(struct iscsi_task *task); 48562306a36Sopenharmony_ciextern void iscsi_complete_scsi_task(struct iscsi_task *task, 48662306a36Sopenharmony_ci uint32_t exp_cmdsn, uint32_t max_cmdsn); 48762306a36Sopenharmony_ci 48862306a36Sopenharmony_ci/* 48962306a36Sopenharmony_ci * generic helpers 49062306a36Sopenharmony_ci */ 49162306a36Sopenharmony_ciextern void iscsi_pool_free(struct iscsi_pool *); 49262306a36Sopenharmony_ciextern int iscsi_pool_init(struct iscsi_pool *, int, void ***, int); 49362306a36Sopenharmony_ciextern int iscsi_switch_str_param(char **, char *); 49462306a36Sopenharmony_ci 49562306a36Sopenharmony_ci/* 49662306a36Sopenharmony_ci * inline functions to deal with padding. 49762306a36Sopenharmony_ci */ 49862306a36Sopenharmony_cistatic inline unsigned int 49962306a36Sopenharmony_ciiscsi_padded(unsigned int len) 50062306a36Sopenharmony_ci{ 50162306a36Sopenharmony_ci return (len + ISCSI_PAD_LEN - 1) & ~(ISCSI_PAD_LEN - 1); 50262306a36Sopenharmony_ci} 50362306a36Sopenharmony_ci 50462306a36Sopenharmony_cistatic inline unsigned int 50562306a36Sopenharmony_ciiscsi_padding(unsigned int len) 50662306a36Sopenharmony_ci{ 50762306a36Sopenharmony_ci len &= (ISCSI_PAD_LEN - 1); 50862306a36Sopenharmony_ci if (len) 50962306a36Sopenharmony_ci len = ISCSI_PAD_LEN - len; 51062306a36Sopenharmony_ci return len; 51162306a36Sopenharmony_ci} 51262306a36Sopenharmony_ci 51362306a36Sopenharmony_ci#endif 514