X-Git-Url: https://err.no/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=include%2Fscsi%2Flibiscsi.h;h=21cfb1d5483f0a23eb282936737c3bcb1c300462;hb=88dfd340b9dece8fcaa1a2d4c782338926c017f7;hp=b4b31132618bbeae62699d998beb78bb99b98b23;hpb=b981d8b3f5e008ff10d993be633ad00564fc22cd;p=linux-2.6 diff --git a/include/scsi/libiscsi.h b/include/scsi/libiscsi.h index b4b3113261..21cfb1d548 100644 --- a/include/scsi/libiscsi.h +++ b/include/scsi/libiscsi.h @@ -24,6 +24,7 @@ #define LIBISCSI_H #include +#include #include #include #include @@ -31,6 +32,7 @@ #include struct scsi_transport_template; +struct scsi_host_template; struct scsi_device; struct Scsi_Host; struct scsi_cmnd; @@ -40,6 +42,7 @@ struct iscsi_cls_session; struct iscsi_cls_conn; struct iscsi_session; struct iscsi_nopin; +struct device; /* #define DEBUG_SCSI */ #ifdef DEBUG_SCSI @@ -57,49 +60,47 @@ struct iscsi_nopin; #define ISCSI_MAX_CMD_PER_LUN 128 /* Task Mgmt states */ -#define TMABORT_INITIAL 0x0 -#define TMABORT_SUCCESS 0x1 -#define TMABORT_FAILED 0x2 -#define TMABORT_TIMEDOUT 0x3 -#define TMABORT_NOT_FOUND 0x4 +enum { + TMF_INITIAL, + TMF_QUEUED, + TMF_SUCCESS, + TMF_FAILED, + TMF_TIMEDOUT, + TMF_NOT_FOUND, +}; /* Connection suspend "bit" */ #define ISCSI_SUSPEND_BIT 1 #define ISCSI_ITT_MASK (0xfff) -#define ISCSI_CID_SHIFT 12 -#define ISCSI_CID_MASK (0xffff << ISCSI_CID_SHIFT) #define ISCSI_AGE_SHIFT 28 #define ISCSI_AGE_MASK (0xf << ISCSI_AGE_SHIFT) #define ISCSI_ADDRESS_BUF_LEN 64 -struct iscsi_mgmt_task { - /* - * Becuae LLDs allocate their hdr differently, this is a pointer to - * that storage. It must be setup at session creation time. - */ - struct iscsi_hdr *hdr; - char *data; /* mgmt payload */ - unsigned data_count; /* counts data to be sent */ - uint32_t itt; /* this ITT */ - void *dd_data; /* driver/transport data */ - struct list_head running; +enum { + /* this is the maximum possible storage for AHSs */ + ISCSI_MAX_AHS_SIZE = sizeof(struct iscsi_ecdb_ahdr) + + sizeof(struct iscsi_rlength_ahdr), + ISCSI_DIGEST_SIZE = sizeof(__u32), }; + enum { ISCSI_TASK_COMPLETED, ISCSI_TASK_PENDING, ISCSI_TASK_RUNNING, - ISCSI_TASK_ABORTING, }; -struct iscsi_cmd_task { +struct iscsi_task { /* - * Becuae LLDs allocate their hdr differently, this is a pointer to - * that storage. It must be setup at session creation time. + * Because LLDs allocate their hdr differently, this is a pointer + * and length to that storage. It must be setup at session + * creation time. */ struct iscsi_cmd *hdr; + unsigned short hdr_max; + unsigned short hdr_len; /* accumulated size of hdr used */ int itt; /* this ITT */ uint32_t unsol_datasn; @@ -108,9 +109,9 @@ struct iscsi_cmd_task { /* offset in unsolicited stream (bytes); */ unsigned unsol_offset; unsigned data_count; /* remaining Data-Out */ + char *data; /* mgmt payload */ struct scsi_cmnd *sc; /* associated SCSI cmd*/ struct iscsi_conn *conn; /* used connection */ - struct iscsi_mgmt_task *mtask; /* tmf mtask in progr */ /* state set/tested under session->lock */ int state; @@ -119,6 +120,19 @@ struct iscsi_cmd_task { void *dd_data; /* driver/transport data */ }; +static inline void* iscsi_next_hdr(struct iscsi_task *task) +{ + return (void*)task->hdr + task->hdr_len; +} + +/* Connection's states */ +enum { + ISCSI_CONN_INITIAL_STAGE, + ISCSI_CONN_STARTED, + ISCSI_CONN_STOPPED, + ISCSI_CONN_CLEANUP_WAIT, +}; + struct iscsi_conn { struct iscsi_cls_conn *cls_conn; /* ptr to class connection */ void *dd_data; /* iscsi_transport data */ @@ -132,6 +146,12 @@ struct iscsi_conn { * conn_stop() flag: stop to recover, stop to terminate */ int stop_stage; + struct timer_list transport_timer; + unsigned long last_recv; + unsigned long last_ping; + int ping_timeout; + int recv_timeout; + struct iscsi_task *ping_task; /* iSCSI connection-wide sequencing */ uint32_t exp_statsn; @@ -147,15 +167,15 @@ struct iscsi_conn { * should always fit in this buffer */ char *data; - struct iscsi_mgmt_task *login_mtask; /* mtask used for login/text */ - struct iscsi_mgmt_task *mtask; /* xmit mtask in progress */ - struct iscsi_cmd_task *ctask; /* xmit ctask in progress */ + struct iscsi_task *login_task; /* mtask used for login/text */ + struct iscsi_task *task; /* xmit task in progress */ /* xmit */ - struct kfifo *mgmtqueue; /* mgmt (control) xmit queue */ + struct list_head mgmtqueue; /* mgmt (control) xmit queue */ struct list_head mgmt_run_list; /* list of control tasks */ struct list_head xmitqueue; /* data-path cmd queue */ struct list_head run_list; /* list of cmds in progress */ + struct list_head requeue; /* tasks needing another run */ struct work_struct xmitwork; /* per-conn. xmit workqueue */ unsigned long suspend_tx; /* suspend Tx */ unsigned long suspend_rx; /* suspend Rx */ @@ -163,8 +183,8 @@ struct iscsi_conn { /* abort */ wait_queue_head_t ehwait; /* used in eh_abort() */ struct iscsi_tm tmhdr; - struct timer_list tmabort_timer; - int tmabort_state; /* see TMABORT_INITIAL, etc.*/ + struct timer_list tmf_timer; + int tmf_state; /* see TMF_INITIAL, etc.*/ /* negotiated params */ unsigned max_recv_dlength; /* initiator_max_recv_dsl*/ @@ -179,9 +199,6 @@ struct iscsi_conn { /* remote portal currently connected to */ int portal_port; char portal_address[ISCSI_ADDRESS_BUF_LEN]; - /* local address */ - int local_port; - char local_address[ISCSI_ADDRESS_BUF_LEN]; /* MIB-statistics */ uint64_t txdata_octets; @@ -196,15 +213,28 @@ struct iscsi_conn { /* custom statistics */ uint32_t eh_abort_cnt; + uint32_t fmr_unalign_cnt; }; -struct iscsi_queue { +struct iscsi_pool { struct kfifo *queue; /* FIFO Queue */ void **pool; /* Pool of elements */ int max; /* Max number of elements */ }; +/* Session's states */ +enum { + ISCSI_STATE_FREE = 1, + ISCSI_STATE_LOGGED_IN, + ISCSI_STATE_FAILED, + ISCSI_STATE_TERMINATE, + ISCSI_STATE_IN_RECOVERY, + ISCSI_STATE_RECOVERY_FAILED, + ISCSI_STATE_LOGGING_OUT, +}; + struct iscsi_session { + struct iscsi_cls_session *cls_session; /* * Syncs up the scsi eh thread with the iscsi eh thread when sending * task management functions. This must be taken before the session @@ -221,6 +251,8 @@ struct iscsi_session { uint32_t queued_cmdsn; /* configuration */ + int abort_timeout; + int lu_reset_timeout; int initial_r2t_en; unsigned max_r2t; int imm_data_en; @@ -231,16 +263,15 @@ struct iscsi_session { int pdu_inorder_en; int dataseq_inorder_en; int erl; + int fast_abort; int tpgt; char *username; char *username_in; char *password; char *password_in; char *targetname; + char *ifacename; char *initiatorname; - /* hw address or netdev iscsi connection is bound to */ - char *hwaddress; - char *netdev; /* control data */ struct iscsi_transport *tt; struct Scsi_Host *host; @@ -254,12 +285,20 @@ struct iscsi_session { int state; /* session state */ int age; /* counts session re-opens */ + int scsi_cmds_max; /* max scsi commands */ int cmds_max; /* size of cmds array */ - struct iscsi_cmd_task **cmds; /* Original Cmds arr */ - struct iscsi_queue cmdpool; /* PDU's pool */ - int mgmtpool_max; /* size of mgmt array */ - struct iscsi_mgmt_task **mgmt_cmds; /* Original mgmt arr */ - struct iscsi_queue mgmtpool; /* Mgmt PDU's pool */ + struct iscsi_task **cmds; /* Original Cmds arr */ + struct iscsi_pool cmdpool; /* PDU's pool */ +}; + +struct iscsi_host { + char *initiatorname; + /* hw address or netdev iscsi connection is bound to */ + char *hwaddress; + char *netdev; + /* local address */ + int local_port; + char local_address[ISCSI_ADDRESS_BUF_LEN]; }; /* @@ -268,41 +307,48 @@ struct iscsi_session { extern int iscsi_change_queue_depth(struct scsi_device *sdev, int depth); extern int iscsi_eh_abort(struct scsi_cmnd *sc); extern int iscsi_eh_host_reset(struct scsi_cmnd *sc); +extern int iscsi_eh_device_reset(struct scsi_cmnd *sc); extern int iscsi_queuecommand(struct scsi_cmnd *sc, void (*done)(struct scsi_cmnd *)); - /* * iSCSI host helpers. */ +#define iscsi_host_priv(_shost) \ + (shost_priv(_shost) + sizeof(struct iscsi_host)) + extern int iscsi_host_set_param(struct Scsi_Host *shost, enum iscsi_host_param param, char *buf, int buflen); extern int iscsi_host_get_param(struct Scsi_Host *shost, enum iscsi_host_param param, char *buf); +extern int iscsi_host_add(struct Scsi_Host *shost, struct device *pdev); +extern struct Scsi_Host *iscsi_host_alloc(struct scsi_host_template *sht, + int dd_data_size, uint16_t qdepth); +extern void iscsi_host_remove(struct Scsi_Host *shost); +extern void iscsi_host_free(struct Scsi_Host *shost); /* * session management */ extern struct iscsi_cls_session * -iscsi_session_setup(struct iscsi_transport *, struct scsi_transport_template *, - uint16_t, uint16_t, int, int, uint32_t, uint32_t *); +iscsi_session_setup(struct iscsi_transport *, struct Scsi_Host *shost, + uint16_t, int, uint32_t, unsigned int); extern void iscsi_session_teardown(struct iscsi_cls_session *); -extern struct iscsi_session *class_to_transport_session(struct iscsi_cls_session *); extern void iscsi_session_recovery_timedout(struct iscsi_cls_session *); extern int iscsi_set_param(struct iscsi_cls_conn *cls_conn, enum iscsi_param param, char *buf, int buflen); extern int iscsi_session_get_param(struct iscsi_cls_session *cls_session, enum iscsi_param param, char *buf); -#define session_to_cls(_sess) \ - hostdata_session(_sess->host->hostdata) +#define iscsi_session_printk(prefix, _sess, fmt, a...) \ + iscsi_cls_session_printk(prefix, _sess->cls_session, fmt, ##a) /* * connection management */ extern struct iscsi_cls_conn *iscsi_conn_setup(struct iscsi_cls_session *, - uint32_t); + int, uint32_t); extern void iscsi_conn_teardown(struct iscsi_cls_conn *); extern int iscsi_conn_start(struct iscsi_cls_conn *); extern void iscsi_conn_stop(struct iscsi_cls_conn *, int); @@ -311,26 +357,49 @@ extern int iscsi_conn_bind(struct iscsi_cls_session *, struct iscsi_cls_conn *, extern void iscsi_conn_failure(struct iscsi_conn *conn, enum iscsi_err err); extern int iscsi_conn_get_param(struct iscsi_cls_conn *cls_conn, enum iscsi_param param, char *buf); +extern void iscsi_suspend_tx(struct iscsi_conn *conn); + +#define iscsi_conn_printk(prefix, _c, fmt, a...) \ + iscsi_cls_conn_printk(prefix, ((struct iscsi_conn *)_c)->cls_conn, \ + fmt, ##a) /* * pdu and task processing */ extern void iscsi_update_cmdsn(struct iscsi_session *, struct iscsi_nopin *); -extern void iscsi_prep_unsolicit_data_pdu(struct iscsi_cmd_task *, +extern void iscsi_prep_unsolicit_data_pdu(struct iscsi_task *, struct iscsi_data *hdr); extern int iscsi_conn_send_pdu(struct iscsi_cls_conn *, struct iscsi_hdr *, char *, uint32_t); extern int iscsi_complete_pdu(struct iscsi_conn *, struct iscsi_hdr *, char *, int); -extern int __iscsi_complete_pdu(struct iscsi_conn *, struct iscsi_hdr *, - char *, int); -extern int iscsi_verify_itt(struct iscsi_conn *, struct iscsi_hdr *, - uint32_t *); +extern int iscsi_verify_itt(struct iscsi_conn *, itt_t); +extern struct iscsi_task *iscsi_itt_to_ctask(struct iscsi_conn *, itt_t); +extern void iscsi_requeue_task(struct iscsi_task *task); +extern void iscsi_put_task(struct iscsi_task *task); /* * generic helpers */ -extern void iscsi_pool_free(struct iscsi_queue *, void **); -extern int iscsi_pool_init(struct iscsi_queue *, int, void ***, int); +extern void iscsi_pool_free(struct iscsi_pool *); +extern int iscsi_pool_init(struct iscsi_pool *, int, void ***, int); + +/* + * inline functions to deal with padding. + */ +static inline unsigned int +iscsi_padded(unsigned int len) +{ + return (len + ISCSI_PAD_LEN - 1) & ~(ISCSI_PAD_LEN - 1); +} + +static inline unsigned int +iscsi_padding(unsigned int len) +{ + len &= (ISCSI_PAD_LEN - 1); + if (len) + len = ISCSI_PAD_LEN - len; + return len; +} #endif