diff options
Diffstat (limited to 'include')
-rw-r--r-- | include/linux/crc-t10dif.h | 8 | ||||
-rw-r--r-- | include/scsi/iscsi_if.h | 93 | ||||
-rw-r--r-- | include/scsi/iscsi_proto.h | 3 | ||||
-rw-r--r-- | include/scsi/libiscsi.h | 107 | ||||
-rw-r--r-- | include/scsi/scsi.h | 18 | ||||
-rw-r--r-- | include/scsi/scsi_cmnd.h | 1 | ||||
-rw-r--r-- | include/scsi/scsi_device.h | 22 | ||||
-rw-r--r-- | include/scsi/scsi_dh.h | 69 | ||||
-rw-r--r-- | include/scsi/scsi_transport_iscsi.h | 91 | ||||
-rw-r--r-- | include/scsi/sd.h | 57 | ||||
-rw-r--r-- | include/scsi/sg.h | 1 |
11 files changed, 269 insertions, 201 deletions
diff --git a/include/linux/crc-t10dif.h b/include/linux/crc-t10dif.h new file mode 100644 index 00000000000..a9c96d865ee --- /dev/null +++ b/include/linux/crc-t10dif.h @@ -0,0 +1,8 @@ +#ifndef _LINUX_CRC_T10DIF_H +#define _LINUX_CRC_T10DIF_H + +#include <linux/types.h> + +__u16 crc_t10dif(unsigned char const *, size_t); + +#endif diff --git a/include/scsi/iscsi_if.h b/include/scsi/iscsi_if.h index e19e5842316..16be12f1cbe 100644 --- a/include/scsi/iscsi_if.h +++ b/include/scsi/iscsi_if.h @@ -50,6 +50,7 @@ enum iscsi_uevent_e { ISCSI_UEVENT_TGT_DSCVR = UEVENT_BASE + 15, ISCSI_UEVENT_SET_HOST_PARAM = UEVENT_BASE + 16, ISCSI_UEVENT_UNBIND_SESSION = UEVENT_BASE + 17, + ISCSI_UEVENT_CREATE_BOUND_SESSION = UEVENT_BASE + 18, /* up events */ ISCSI_KEVENT_RECV_PDU = KEVENT_BASE + 1, @@ -78,6 +79,12 @@ struct iscsi_uevent { uint16_t cmds_max; uint16_t queue_depth; } c_session; + struct msg_create_bound_session { + uint64_t ep_handle; + uint32_t initial_cmdsn; + uint16_t cmds_max; + uint16_t queue_depth; + } c_bound_session; struct msg_destroy_session { uint32_t sid; } d_session; @@ -250,42 +257,49 @@ enum iscsi_param { ISCSI_PARAM_PING_TMO, ISCSI_PARAM_RECV_TMO, + + ISCSI_PARAM_IFACE_NAME, + ISCSI_PARAM_ISID, + ISCSI_PARAM_INITIATOR_NAME, /* must always be last */ ISCSI_PARAM_MAX, }; -#define ISCSI_MAX_RECV_DLENGTH (1 << ISCSI_PARAM_MAX_RECV_DLENGTH) -#define ISCSI_MAX_XMIT_DLENGTH (1 << ISCSI_PARAM_MAX_XMIT_DLENGTH) -#define ISCSI_HDRDGST_EN (1 << ISCSI_PARAM_HDRDGST_EN) -#define ISCSI_DATADGST_EN (1 << ISCSI_PARAM_DATADGST_EN) -#define ISCSI_INITIAL_R2T_EN (1 << ISCSI_PARAM_INITIAL_R2T_EN) -#define ISCSI_MAX_R2T (1 << ISCSI_PARAM_MAX_R2T) -#define ISCSI_IMM_DATA_EN (1 << ISCSI_PARAM_IMM_DATA_EN) -#define ISCSI_FIRST_BURST (1 << ISCSI_PARAM_FIRST_BURST) -#define ISCSI_MAX_BURST (1 << ISCSI_PARAM_MAX_BURST) -#define ISCSI_PDU_INORDER_EN (1 << ISCSI_PARAM_PDU_INORDER_EN) -#define ISCSI_DATASEQ_INORDER_EN (1 << ISCSI_PARAM_DATASEQ_INORDER_EN) -#define ISCSI_ERL (1 << ISCSI_PARAM_ERL) -#define ISCSI_IFMARKER_EN (1 << ISCSI_PARAM_IFMARKER_EN) -#define ISCSI_OFMARKER_EN (1 << ISCSI_PARAM_OFMARKER_EN) -#define ISCSI_EXP_STATSN (1 << ISCSI_PARAM_EXP_STATSN) -#define ISCSI_TARGET_NAME (1 << ISCSI_PARAM_TARGET_NAME) -#define ISCSI_TPGT (1 << ISCSI_PARAM_TPGT) -#define ISCSI_PERSISTENT_ADDRESS (1 << ISCSI_PARAM_PERSISTENT_ADDRESS) -#define ISCSI_PERSISTENT_PORT (1 << ISCSI_PARAM_PERSISTENT_PORT) -#define ISCSI_SESS_RECOVERY_TMO (1 << ISCSI_PARAM_SESS_RECOVERY_TMO) -#define ISCSI_CONN_PORT (1 << ISCSI_PARAM_CONN_PORT) -#define ISCSI_CONN_ADDRESS (1 << ISCSI_PARAM_CONN_ADDRESS) -#define ISCSI_USERNAME (1 << ISCSI_PARAM_USERNAME) -#define ISCSI_USERNAME_IN (1 << ISCSI_PARAM_USERNAME_IN) -#define ISCSI_PASSWORD (1 << ISCSI_PARAM_PASSWORD) -#define ISCSI_PASSWORD_IN (1 << ISCSI_PARAM_PASSWORD_IN) -#define ISCSI_FAST_ABORT (1 << ISCSI_PARAM_FAST_ABORT) -#define ISCSI_ABORT_TMO (1 << ISCSI_PARAM_ABORT_TMO) -#define ISCSI_LU_RESET_TMO (1 << ISCSI_PARAM_LU_RESET_TMO) -#define ISCSI_HOST_RESET_TMO (1 << ISCSI_PARAM_HOST_RESET_TMO) -#define ISCSI_PING_TMO (1 << ISCSI_PARAM_PING_TMO) -#define ISCSI_RECV_TMO (1 << ISCSI_PARAM_RECV_TMO) +#define ISCSI_MAX_RECV_DLENGTH (1ULL << ISCSI_PARAM_MAX_RECV_DLENGTH) +#define ISCSI_MAX_XMIT_DLENGTH (1ULL << ISCSI_PARAM_MAX_XMIT_DLENGTH) +#define ISCSI_HDRDGST_EN (1ULL << ISCSI_PARAM_HDRDGST_EN) +#define ISCSI_DATADGST_EN (1ULL << ISCSI_PARAM_DATADGST_EN) +#define ISCSI_INITIAL_R2T_EN (1ULL << ISCSI_PARAM_INITIAL_R2T_EN) +#define ISCSI_MAX_R2T (1ULL << ISCSI_PARAM_MAX_R2T) +#define ISCSI_IMM_DATA_EN (1ULL << ISCSI_PARAM_IMM_DATA_EN) +#define ISCSI_FIRST_BURST (1ULL << ISCSI_PARAM_FIRST_BURST) +#define ISCSI_MAX_BURST (1ULL << ISCSI_PARAM_MAX_BURST) +#define ISCSI_PDU_INORDER_EN (1ULL << ISCSI_PARAM_PDU_INORDER_EN) +#define ISCSI_DATASEQ_INORDER_EN (1ULL << ISCSI_PARAM_DATASEQ_INORDER_EN) +#define ISCSI_ERL (1ULL << ISCSI_PARAM_ERL) +#define ISCSI_IFMARKER_EN (1ULL << ISCSI_PARAM_IFMARKER_EN) +#define ISCSI_OFMARKER_EN (1ULL << ISCSI_PARAM_OFMARKER_EN) +#define ISCSI_EXP_STATSN (1ULL << ISCSI_PARAM_EXP_STATSN) +#define ISCSI_TARGET_NAME (1ULL << ISCSI_PARAM_TARGET_NAME) +#define ISCSI_TPGT (1ULL << ISCSI_PARAM_TPGT) +#define ISCSI_PERSISTENT_ADDRESS (1ULL << ISCSI_PARAM_PERSISTENT_ADDRESS) +#define ISCSI_PERSISTENT_PORT (1ULL << ISCSI_PARAM_PERSISTENT_PORT) +#define ISCSI_SESS_RECOVERY_TMO (1ULL << ISCSI_PARAM_SESS_RECOVERY_TMO) +#define ISCSI_CONN_PORT (1ULL << ISCSI_PARAM_CONN_PORT) +#define ISCSI_CONN_ADDRESS (1ULL << ISCSI_PARAM_CONN_ADDRESS) +#define ISCSI_USERNAME (1ULL << ISCSI_PARAM_USERNAME) +#define ISCSI_USERNAME_IN (1ULL << ISCSI_PARAM_USERNAME_IN) +#define ISCSI_PASSWORD (1ULL << ISCSI_PARAM_PASSWORD) +#define ISCSI_PASSWORD_IN (1ULL << ISCSI_PARAM_PASSWORD_IN) +#define ISCSI_FAST_ABORT (1ULL << ISCSI_PARAM_FAST_ABORT) +#define ISCSI_ABORT_TMO (1ULL << ISCSI_PARAM_ABORT_TMO) +#define ISCSI_LU_RESET_TMO (1ULL << ISCSI_PARAM_LU_RESET_TMO) +#define ISCSI_HOST_RESET_TMO (1ULL << ISCSI_PARAM_HOST_RESET_TMO) +#define ISCSI_PING_TMO (1ULL << ISCSI_PARAM_PING_TMO) +#define ISCSI_RECV_TMO (1ULL << ISCSI_PARAM_RECV_TMO) +#define ISCSI_IFACE_NAME (1ULL << ISCSI_PARAM_IFACE_NAME) +#define ISCSI_ISID (1ULL << ISCSI_PARAM_ISID) +#define ISCSI_INITIATOR_NAME (1ULL << ISCSI_PARAM_INITIATOR_NAME) /* iSCSI HBA params */ enum iscsi_host_param { @@ -296,20 +310,13 @@ enum iscsi_host_param { ISCSI_HOST_PARAM_MAX, }; -#define ISCSI_HOST_HWADDRESS (1 << ISCSI_HOST_PARAM_HWADDRESS) -#define ISCSI_HOST_INITIATOR_NAME (1 << ISCSI_HOST_PARAM_INITIATOR_NAME) -#define ISCSI_HOST_NETDEV_NAME (1 << ISCSI_HOST_PARAM_NETDEV_NAME) -#define ISCSI_HOST_IPADDRESS (1 << ISCSI_HOST_PARAM_IPADDRESS) +#define ISCSI_HOST_HWADDRESS (1ULL << ISCSI_HOST_PARAM_HWADDRESS) +#define ISCSI_HOST_INITIATOR_NAME (1ULL << ISCSI_HOST_PARAM_INITIATOR_NAME) +#define ISCSI_HOST_NETDEV_NAME (1ULL << ISCSI_HOST_PARAM_NETDEV_NAME) +#define ISCSI_HOST_IPADDRESS (1ULL << ISCSI_HOST_PARAM_IPADDRESS) #define iscsi_ptr(_handle) ((void*)(unsigned long)_handle) #define iscsi_handle(_ptr) ((uint64_t)(unsigned long)_ptr) -#define hostdata_session(_hostdata) (iscsi_ptr(*(unsigned long *)_hostdata)) - -/** - * iscsi_hostdata - get LLD hostdata from scsi_host - * @_hostdata: pointer to scsi host's hostdata - **/ -#define iscsi_hostdata(_hostdata) ((void*)_hostdata + sizeof(unsigned long)) /* * These flags presents iSCSI Data-Path capabilities. diff --git a/include/scsi/iscsi_proto.h b/include/scsi/iscsi_proto.h index e0593bfae62..f2a2c116948 100644 --- a/include/scsi/iscsi_proto.h +++ b/include/scsi/iscsi_proto.h @@ -22,6 +22,7 @@ #define ISCSI_PROTO_H #include <linux/types.h> +#include <scsi/scsi.h> #define ISCSI_DRAFT20_VERSION 0x00 @@ -156,7 +157,7 @@ struct iscsi_ecdb_ahdr { uint8_t ahstype; uint8_t reserved; /* 4-byte aligned extended CDB spillover */ - uint8_t ecdb[260 - ISCSI_CDB_SIZE]; + uint8_t ecdb[SCSI_MAX_VARLEN_CDB_SIZE - ISCSI_CDB_SIZE]; }; /* SCSI Response Header */ diff --git a/include/scsi/libiscsi.h b/include/scsi/libiscsi.h index cd3ca63d4fb..5e75bb7f311 100644 --- a/include/scsi/libiscsi.h +++ b/include/scsi/libiscsi.h @@ -24,6 +24,7 @@ #define LIBISCSI_H #include <linux/types.h> +#include <linux/wait.h> #include <linux/mutex.h> #include <linux/timer.h> #include <linux/workqueue.h> @@ -31,6 +32,7 @@ #include <scsi/iscsi_if.h> 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 @@ -49,9 +52,7 @@ struct iscsi_nopin; #endif #define ISCSI_DEF_XMIT_CMDS_MAX 128 /* must be power of 2 */ -#define ISCSI_MGMT_CMDS_MAX 16 /* must be power of 2 */ - -#define ISCSI_MGMT_ITT_OFFSET 0xa00 +#define ISCSI_MGMT_CMDS_MAX 15 #define ISCSI_DEF_CMD_PER_LUN 32 #define ISCSI_MAX_CMD_PER_LUN 128 @@ -69,7 +70,10 @@ enum { /* Connection suspend "bit" */ #define ISCSI_SUSPEND_BIT 1 -#define ISCSI_ITT_MASK (0xfff) +#define ISCSI_ITT_MASK (0x1fff) +#define ISCSI_TOTAL_CMDS_MAX 4096 +/* this must be a power of two greater than ISCSI_MGMT_CMDS_MAX */ +#define ISCSI_TOTAL_CMDS_MIN 16 #define ISCSI_AGE_SHIFT 28 #define ISCSI_AGE_MASK (0xf << ISCSI_AGE_SHIFT) @@ -82,18 +86,6 @@ enum { ISCSI_DIGEST_SIZE = sizeof(__u32), }; -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 { ISCSI_TASK_COMPLETED, @@ -101,7 +93,7 @@ enum { ISCSI_TASK_RUNNING, }; -struct iscsi_cmd_task { +struct iscsi_task { /* * Because LLDs allocate their hdr differently, this is a pointer * and length to that storage. It must be setup at session @@ -118,6 +110,7 @@ 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 */ @@ -128,9 +121,9 @@ struct iscsi_cmd_task { void *dd_data; /* driver/transport data */ }; -static inline void* iscsi_next_hdr(struct iscsi_cmd_task *ctask) +static inline void* iscsi_next_hdr(struct iscsi_task *task) { - return (void*)ctask->hdr + ctask->hdr_len; + return (void*)task->hdr + task->hdr_len; } /* Connection's states */ @@ -146,11 +139,6 @@ struct iscsi_conn { void *dd_data; /* iscsi_transport data */ struct iscsi_session *session; /* parent session */ /* - * LLDs should set this lock. It protects the transport recv - * code - */ - rwlock_t *recv_lock; - /* * conn_stop() flag: stop to recover, stop to terminate */ int stop_stage; @@ -159,7 +147,7 @@ struct iscsi_conn { unsigned long last_ping; int ping_timeout; int recv_timeout; - struct iscsi_mgmt_task *ping_mtask; + struct iscsi_task *ping_task; /* iSCSI connection-wide sequencing */ uint32_t exp_statsn; @@ -175,9 +163,8 @@ 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 list_head mgmtqueue; /* mgmt (control) xmit queue */ @@ -208,9 +195,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; @@ -246,6 +230,7 @@ enum { }; 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 @@ -281,10 +266,8 @@ struct iscsi_session { 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; @@ -298,12 +281,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_task **cmds; /* Original Cmds arr */ struct iscsi_pool cmdpool; /* PDU's pool */ - int mgmtpool_max; /* size of mgmt array */ - struct iscsi_mgmt_task **mgmt_cmds; /* Original mgmt arr */ - struct iscsi_pool mgmtpool; /* Mgmt 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]; }; /* @@ -316,42 +307,44 @@ 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, \ - (struct iscsi_cls_session *)session_to_cls(_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); @@ -360,25 +353,29 @@ 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, _c->cls_conn, 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_verify_itt(struct iscsi_conn *, struct iscsi_hdr *, - uint32_t *); -extern void iscsi_requeue_ctask(struct iscsi_cmd_task *ctask); -extern void iscsi_free_mgmt_task(struct iscsi_conn *conn, - struct iscsi_mgmt_task *mtask); +extern int __iscsi_complete_pdu(struct iscsi_conn *, struct iscsi_hdr *, + char *, int); +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); +extern void __iscsi_get_task(struct iscsi_task *task); /* * generic helpers diff --git a/include/scsi/scsi.h b/include/scsi/scsi.h index 32742c4563d..00137a7769e 100644 --- a/include/scsi/scsi.h +++ b/include/scsi/scsi.h @@ -9,6 +9,7 @@ #define _SCSI_SCSI_H #include <linux/types.h> +#include <scsi/scsi_cmnd.h> /* * The maximum number of SG segments that we will put inside a @@ -400,6 +401,7 @@ struct scsi_lun { #define SOFT_ERROR 0x2005 #define ADD_TO_MLQUEUE 0x2006 #define TIMEOUT_ERROR 0x2007 +#define SCSI_RETURN_NOT_HANDLED 0x2008 /* * Midlevel queue return values. @@ -424,6 +426,22 @@ struct scsi_lun { #define driver_byte(result) (((result) >> 24) & 0xff) #define suggestion(result) (driver_byte(result) & SUGGEST_MASK) +static inline void set_msg_byte(struct scsi_cmnd *cmd, char status) +{ + cmd->result |= status << 8; +} + +static inline void set_host_byte(struct scsi_cmnd *cmd, char status) +{ + cmd->result |= status << 16; +} + +static inline void set_driver_byte(struct scsi_cmnd *cmd, char status) +{ + cmd->result |= status << 24; +} + + #define sense_class(sense) (((sense) >> 4) & 0x7) #define sense_error(sense) ((sense) & 0xf) #define sense_valid(sense) ((sense) & 0x80); diff --git a/include/scsi/scsi_cmnd.h b/include/scsi/scsi_cmnd.h index 3e46dfae819..66c944849d6 100644 --- a/include/scsi/scsi_cmnd.h +++ b/include/scsi/scsi_cmnd.h @@ -7,7 +7,6 @@ #include <linux/types.h> #include <linux/timer.h> #include <linux/scatterlist.h> -#include <linux/blkdev.h> struct Scsi_Host; struct scsi_device; diff --git a/include/scsi/scsi_device.h b/include/scsi/scsi_device.h index 00b78763a1b..6467f78b191 100644 --- a/include/scsi/scsi_device.h +++ b/include/scsi/scsi_device.h @@ -162,9 +162,29 @@ struct scsi_device { struct execute_work ew; /* used to get process context on put */ + struct scsi_dh_data *scsi_dh_data; enum scsi_device_state sdev_state; unsigned long sdev_data[0]; } __attribute__((aligned(sizeof(unsigned long)))); + +struct scsi_device_handler { + /* Used by the infrastructure */ + struct list_head list; /* list of scsi_device_handlers */ + struct notifier_block nb; + + /* Filled by the hardware handler */ + struct module *module; + const char *name; + int (*check_sense)(struct scsi_device *, struct scsi_sense_hdr *); + int (*activate)(struct scsi_device *); + int (*prep_fn)(struct scsi_device *, struct request *); +}; + +struct scsi_dh_data { + struct scsi_device_handler *scsi_dh; + char buf[0]; +}; + #define to_scsi_device(d) \ container_of(d, struct scsi_device, sdev_gendev) #define class_to_sdev(d) \ @@ -231,7 +251,9 @@ extern struct scsi_device *__scsi_add_device(struct Scsi_Host *, uint, uint, uint, void *hostdata); extern int scsi_add_device(struct Scsi_Host *host, uint channel, uint target, uint lun); +extern int scsi_register_device_handler(struct scsi_device_handler *scsi_dh); extern void scsi_remove_device(struct scsi_device *); +extern int scsi_unregister_device_handler(struct scsi_device_handler *scsi_dh); extern int scsi_device_get(struct scsi_device *); extern void scsi_device_put(struct scsi_device *); diff --git a/include/scsi/scsi_dh.h b/include/scsi/scsi_dh.h new file mode 100644 index 00000000000..3ad2303d1a1 --- /dev/null +++ b/include/scsi/scsi_dh.h @@ -0,0 +1,69 @@ +/* + * Header file for SCSI device handler infrastruture. + * + * Modified version of patches posted by Mike Christie <michaelc@cs.wisc.edu> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * Copyright IBM Corporation, 2007 + * Authors: + * Chandra Seetharaman <sekharan@us.ibm.com> + * Mike Anderson <andmike@linux.vnet.ibm.com> + */ + +#include <scsi/scsi_device.h> + +enum { + SCSI_DH_OK = 0, + /* + * device errors + */ + SCSI_DH_DEV_FAILED, /* generic device error */ + SCSI_DH_DEV_TEMP_BUSY, + SCSI_DH_DEVICE_MAX, /* max device blkerr definition */ + + /* + * transport errors + */ + SCSI_DH_NOTCONN = SCSI_DH_DEVICE_MAX + 1, + SCSI_DH_CONN_FAILURE, + SCSI_DH_TRANSPORT_MAX, /* max transport blkerr definition */ + + /* + * driver and generic errors + */ + SCSI_DH_IO = SCSI_DH_TRANSPORT_MAX + 1, /* generic error */ + SCSI_DH_INVALID_IO, + SCSI_DH_RETRY, /* retry the req, but not immediately */ + SCSI_DH_IMM_RETRY, /* immediately retry the req */ + SCSI_DH_TIMED_OUT, + SCSI_DH_RES_TEMP_UNAVAIL, + SCSI_DH_DEV_OFFLINED, + SCSI_DH_NOSYS, + SCSI_DH_DRIVER_MAX, +}; +#if defined(CONFIG_SCSI_DH) || defined(CONFIG_SCSI_DH_MODULE) +extern int scsi_dh_activate(struct request_queue *); +extern int scsi_dh_handler_exist(const char *); +#else +static inline int scsi_dh_activate(struct request_queue *req) +{ + return 0; +} +static inline int scsi_dh_handler_exist(const char *name) +{ + return 0; +} +#endif diff --git a/include/scsi/scsi_transport_iscsi.h b/include/scsi/scsi_transport_iscsi.h index aab1eae2ec4..f5444e033cc 100644 --- a/include/scsi/scsi_transport_iscsi.h +++ b/include/scsi/scsi_transport_iscsi.h @@ -30,11 +30,11 @@ struct scsi_transport_template; struct iscsi_transport; +struct iscsi_endpoint; struct Scsi_Host; struct iscsi_cls_conn; struct iscsi_conn; -struct iscsi_cmd_task; -struct iscsi_mgmt_task; +struct iscsi_task; struct sockaddr; /** @@ -58,19 +58,22 @@ struct sockaddr; * @stop_conn: suspend/recover/terminate connection * @send_pdu: send iSCSI PDU, Login, Logout, NOP-Out, Reject, Text. * @session_recovery_timedout: notify LLD a block during recovery timed out - * @init_cmd_task: Initialize a iscsi_cmd_task and any internal structs. - * Called from queuecommand with session lock held. - * @init_mgmt_task: Initialize a iscsi_mgmt_task and any internal structs. - * Called from iscsi_conn_send_generic with xmitmutex. - * @xmit_cmd_task: Requests LLD to transfer cmd task. Returns 0 or the + * @init_task: Initialize a iscsi_task and any internal structs. + * When offloading the data path, this is called from + * queuecommand with the session lock, or from the + * iscsi_conn_send_pdu context with the session lock. + * When not offloading the data path, this is called + * from the scsi work queue without the session lock. + * @xmit_task Requests LLD to transfer cmd task. Returns 0 or the * the number of bytes transferred on success, and -Exyz - * value on error. - * @xmit_mgmt_task: Requests LLD to transfer mgmt task. Returns 0 or the - * the number of bytes transferred on success, and -Exyz - * value on error. - * @cleanup_cmd_task: requests LLD to fail cmd task. Called with xmitmutex - * and session->lock after the connection has been - * suspended and terminated during recovery. If called + * value on error. When offloading the data path, this + * is called from queuecommand with the session lock, or + * from the iscsi_conn_send_pdu context with the session + * lock. When not offloading the data path, this is called + * from the scsi work queue without the session lock. + * @cleanup_task: requests LLD to fail task. Called with session lock + * and after the connection has been suspended and + * terminated during recovery. If called * from abort task then connection is not suspended * or terminated but sk_callback_lock is held * @@ -83,17 +86,9 @@ struct iscsi_transport { /* LLD sets this to indicate what values it can export to sysfs */ uint64_t param_mask; uint64_t host_param_mask; - struct scsi_host_template *host_template; - /* LLD connection data size */ - int conndata_size; - /* LLD session data size */ - int sessiondata_size; - int max_lun; - unsigned int max_conn; - unsigned int max_cmd_len; - struct iscsi_cls_session *(*create_session) (struct iscsi_transport *it, - struct scsi_transport_template *t, uint16_t, uint16_t, - uint32_t sn, uint32_t *hn); + struct iscsi_cls_session *(*create_session) (struct iscsi_endpoint *ep, + uint16_t cmds_max, uint16_t qdepth, + uint32_t sn, uint32_t *hn); void (*destroy_session) (struct iscsi_cls_session *session); struct iscsi_cls_conn *(*create_conn) (struct iscsi_cls_session *sess, uint32_t cid); @@ -118,20 +113,15 @@ struct iscsi_transport { char *data, uint32_t data_size); void (*get_stats) (struct iscsi_cls_conn *conn, struct iscsi_stats *stats); - int (*init_cmd_task) (struct iscsi_cmd_task *ctask); - void (*init_mgmt_task) (struct iscsi_conn *conn, - struct iscsi_mgmt_task *mtask); - int (*xmit_cmd_task) (struct iscsi_conn *conn, - struct iscsi_cmd_task *ctask); - void (*cleanup_cmd_task) (struct iscsi_conn *conn, - struct iscsi_cmd_task *ctask); - int (*xmit_mgmt_task) (struct iscsi_conn *conn, - struct iscsi_mgmt_task *mtask); + int (*init_task) (struct iscsi_task *task); + int (*xmit_task) (struct iscsi_task *task); + void (*cleanup_task) (struct iscsi_conn *conn, + struct iscsi_task *task); void (*session_recovery_timedout) (struct iscsi_cls_session *session); - int (*ep_connect) (struct sockaddr *dst_addr, int non_blocking, - uint64_t *ep_handle); - int (*ep_poll) (uint64_t ep_handle, int timeout_ms); - void (*ep_disconnect) (uint64_t ep_handle); + struct iscsi_endpoint *(*ep_connect) (struct sockaddr *dst_addr, + int non_blocking); + int (*ep_poll) (struct iscsi_endpoint *ep, int timeout_ms); + void (*ep_disconnect) (struct iscsi_endpoint *ep); int (*tgt_dscvr) (struct Scsi_Host *shost, enum iscsi_tgt_dscvr type, uint32_t enable, struct sockaddr *dst_addr); }; @@ -172,9 +162,10 @@ enum { ISCSI_SESSION_FREE, }; +#define ISCSI_MAX_TARGET -1 + struct iscsi_cls_session { struct list_head sess_list; /* item in session_list */ - struct list_head host_list; struct iscsi_transport *transport; spinlock_t lock; struct work_struct block_work; @@ -186,7 +177,7 @@ struct iscsi_cls_session { int recovery_tmo; struct delayed_work recovery_work; - int target_id; + unsigned int target_id; int state; int sid; /* session id */ @@ -203,14 +194,22 @@ struct iscsi_cls_session { #define starget_to_session(_stgt) \ iscsi_dev_to_session(_stgt->dev.parent) -struct iscsi_host { - struct list_head sessions; +struct iscsi_cls_host { atomic_t nr_scans; struct mutex mutex; struct workqueue_struct *scan_workq; char scan_workq_name[KOBJ_NAME_LEN]; }; +extern void iscsi_host_for_each_session(struct Scsi_Host *shost, + void (*fn)(struct iscsi_cls_session *)); + +struct iscsi_endpoint { + void *dd_data; /* LLD private data */ + struct device dev; + unsigned int id; +}; + /* * session and connection functions that can be used by HW iSCSI LLDs */ @@ -222,22 +221,26 @@ struct iscsi_host { extern int iscsi_session_chkready(struct iscsi_cls_session *session); extern struct iscsi_cls_session *iscsi_alloc_session(struct Scsi_Host *shost, - struct iscsi_transport *transport); + struct iscsi_transport *transport, int dd_size); extern int iscsi_add_session(struct iscsi_cls_session *session, unsigned int target_id); extern int iscsi_session_event(struct iscsi_cls_session *session, enum iscsi_uevent_e event); extern struct iscsi_cls_session *iscsi_create_session(struct Scsi_Host *shost, struct iscsi_transport *t, + int dd_size, unsigned int target_id); extern void iscsi_remove_session(struct iscsi_cls_session *session); extern void iscsi_free_session(struct iscsi_cls_session *session); extern int iscsi_destroy_session(struct iscsi_cls_session *session); extern struct iscsi_cls_conn *iscsi_create_conn(struct iscsi_cls_session *sess, - uint32_t cid); + int dd_size, uint32_t cid); extern int iscsi_destroy_conn(struct iscsi_cls_conn *conn); extern void iscsi_unblock_session(struct iscsi_cls_session *session); extern void iscsi_block_session(struct iscsi_cls_session *session); extern int iscsi_scan_finished(struct Scsi_Host *shost, unsigned long time); +extern struct iscsi_endpoint *iscsi_create_endpoint(int dd_size); +extern void iscsi_destroy_endpoint(struct iscsi_endpoint *ep); +extern struct iscsi_endpoint *iscsi_lookup_endpoint(u64 handle); #endif diff --git a/include/scsi/sd.h b/include/scsi/sd.h deleted file mode 100644 index 4f032d48cb6..00000000000 --- a/include/scsi/sd.h +++ /dev/null @@ -1,57 +0,0 @@ -#ifndef _SCSI_DISK_H -#define _SCSI_DISK_H - -/* - * More than enough for everybody ;) The huge number of majors - * is a leftover from 16bit dev_t days, we don't really need that - * much numberspace. - */ -#define SD_MAJORS 16 - -/* - * This is limited by the naming scheme enforced in sd_probe, - * add another character to it if you really need more disks. - */ -#define SD_MAX_DISKS (((26 * 26) + 26 + 1) * 26) - -/* - * Time out in seconds for disks and Magneto-opticals (which are slower). - */ -#define SD_TIMEOUT (30 * HZ) -#define SD_MOD_TIMEOUT (75 * HZ) - -/* - * Number of allowed retries - */ -#define SD_MAX_RETRIES 5 -#define SD_PASSTHROUGH_RETRIES 1 - -/* - * Size of the initial data buffer for mode and read capacity data - */ -#define SD_BUF_SIZE 512 - -struct scsi_disk { - struct scsi_driver *driver; /* always &sd_template */ - struct scsi_device *device; - struct device dev; - struct gendisk *disk; - unsigned int openers; /* protected by BKL for now, yuck */ - sector_t capacity; /* size in 512-byte sectors */ - u32 index; - u8 media_present; - u8 write_prot; - unsigned previous_state : 1; - unsigned WCE : 1; /* state of disk WCE bit */ - unsigned RCD : 1; /* state of disk RCD bit, unused */ - unsigned DPOFUA : 1; /* state of disk DPOFUA bit */ -}; -#define to_scsi_disk(obj) container_of(obj,struct scsi_disk,dev) - -#define sd_printk(prefix, sdsk, fmt, a...) \ - (sdsk)->disk ? \ - sdev_printk(prefix, (sdsk)->device, "[%s] " fmt, \ - (sdsk)->disk->disk_name, ##a) : \ - sdev_printk(prefix, (sdsk)->device, fmt, ##a) - -#endif /* _SCSI_DISK_H */ diff --git a/include/scsi/sg.h b/include/scsi/sg.h index 519c49a0fc1..934ae389671 100644 --- a/include/scsi/sg.h +++ b/include/scsi/sg.h @@ -206,6 +206,7 @@ typedef struct sg_req_info { /* used by SG_GET_REQUEST_TABLE ioctl() */ #define SG_SCSI_RESET_DEVICE 1 #define SG_SCSI_RESET_BUS 2 #define SG_SCSI_RESET_HOST 3 +#define SG_SCSI_RESET_TARGET 4 /* synchronous SCSI command ioctl, (only in version 3 interface) */ #define SG_IO 0x2285 /* similar effect as write() followed by read() */ |