summaryrefslogtreecommitdiff
path: root/drivers/target/tcm_fc/tcm_fc.h
blob: 7b82f1b7fef814b595f8cc266f182baa3f031642 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
/*
 * Copyright (c) 2010 Cisco Systems, Inc.
 *
 * This program is free software; you can redistribute it and/or modify it
 * under the terms and conditions of the GNU General Public License,
 * version 2, as published by the Free Software Foundation.
 *
 * This program is distributed in the hope 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.,
 * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
 */
#ifndef __TCM_FC_H__
#define __TCM_FC_H__

#define FT_VERSION "0.3"

#define FT_NAMELEN 32		/* length of ASCII WWPNs including pad */
#define FT_TPG_NAMELEN 32	/* max length of TPG name */
#define FT_LUN_NAMELEN 32	/* max length of LUN name */

/*
 * Debug options.
 */
#define FT_DEBUG_CONF	0x01	/* configuration messages */
#define	FT_DEBUG_SESS	0x02	/* session messages */
#define	FT_DEBUG_TM	0x04	/* TM operations */
#define	FT_DEBUG_IO	0x08	/* I/O commands */
#define	FT_DEBUG_DATA	0x10	/* Data transfer */

extern unsigned int ft_debug_logging;	/* debug options */

#define FT_DEBUG(mask, fmt, args...)					\
	do {								\
		if (ft_debug_logging & (mask))				\
			printk(KERN_INFO "tcm_fc: %s: " fmt,		\
				__func__, ##args);			\
	} while (0)

#define	FT_CONF_DBG(fmt, args...)	FT_DEBUG(FT_DEBUG_CONF, fmt, ##args)
#define	FT_SESS_DBG(fmt, args...)	FT_DEBUG(FT_DEBUG_SESS, fmt, ##args)
#define	FT_TM_DBG(fmt, args...)		FT_DEBUG(FT_DEBUG_TM, fmt, ##args)
#define	FT_IO_DBG(fmt, args...)		FT_DEBUG(FT_DEBUG_IO, fmt, ##args)
#define	FT_DATA_DBG(fmt, args...)	FT_DEBUG(FT_DEBUG_DATA, fmt, ##args)

struct ft_transport_id {
	__u8	format;
	__u8	__resvd1[7];
	__u8	wwpn[8];
	__u8	__resvd2[8];
} __attribute__((__packed__));

/*
 * Session (remote port).
 */
struct ft_sess {
	u32 port_id;			/* for hash lookup use only */
	u32 params;
	u16 max_frame;			/* maximum frame size */
	u64 port_name;			/* port name for transport ID */
	struct ft_tport *tport;
	struct se_session *se_sess;
	struct hlist_node hash;		/* linkage in ft_sess_hash table */
	struct rcu_head rcu;
	struct kref kref;		/* ref for hash and outstanding I/Os */
};

/*
 * Hash table of sessions per local port.
 * Hash lookup by remote port FC_ID.
 */
#define	FT_SESS_HASH_BITS	6
#define	FT_SESS_HASH_SIZE	(1 << FT_SESS_HASH_BITS)

/*
 * Per local port data.
 * This is created only after a TPG exists that allows target function
 * for the local port.  If the TPG exists, this is allocated when
 * we're notified that the local port has been created, or when
 * the first PRLI provider callback is received.
 */
struct ft_tport {
	struct fc_lport *lport;
	struct ft_tpg *tpg;		/* NULL if TPG deleted before tport */
	u32	sess_count;		/* number of sessions in hash */
	struct rcu_head rcu;
	struct hlist_head hash[FT_SESS_HASH_SIZE];	/* list of sessions */
};

/*
 * Node ID and authentication.
 */
struct ft_node_auth {
	u64	port_name;
	u64	node_name;
};

/*
 * Node ACL for FC remote port session.
 */
struct ft_node_acl {
	struct ft_node_auth node_auth;
	struct se_node_acl se_node_acl;
};

struct ft_lun {
	u32 index;
	char name[FT_LUN_NAMELEN];
};

/*
 * Target portal group (local port).
 */
struct ft_tpg {
	u32 index;
	struct ft_lport_acl *lport_acl;
	struct ft_tport *tport;		/* active tport or NULL */
	struct list_head list;		/* linkage in ft_lport_acl tpg_list */
	struct list_head lun_list;	/* head of LUNs */
	struct se_portal_group se_tpg;
	struct task_struct *thread;	/* processing thread */
	struct se_queue_obj qobj;	/* queue for processing thread */
};

struct ft_lport_acl {
	u64 wwpn;
	char name[FT_NAMELEN];
	struct list_head list;
	struct list_head tpg_list;
	struct se_wwn fc_lport_wwn;
};

enum ft_cmd_state {
	FC_CMD_ST_NEW = 0,
	FC_CMD_ST_REJ
};

/*
 * Commands
 */
struct ft_cmd {
	enum ft_cmd_state state;
	u32 lun;                        /* LUN from request */
	struct ft_sess *sess;		/* session held for cmd */
	struct fc_seq *seq;		/* sequence in exchange mgr */
	struct se_cmd se_cmd;		/* Local TCM I/O descriptor */
	struct fc_frame *req_frame;
	unsigned char *cdb;		/* pointer to CDB inside frame */
	u32 write_data_len;		/* data received on writes */
	struct se_queue_req se_req;
	/* Local sense buffer */
	unsigned char ft_sense_buffer[TRANSPORT_SENSE_BUFFER];
	u32 was_ddp_setup:1;		/* Set only if ddp is setup */
	struct scatterlist *sg;		/* Set only if DDP is setup */
	u32 sg_cnt;			/* No. of item in scatterlist */
};

extern struct list_head ft_lport_list;
extern struct mutex ft_lport_lock;
extern struct fc4_prov ft_prov;
extern struct target_fabric_configfs *ft_configfs;

/*
 * Fabric methods.
 */

/*
 * Session ops.
 */
void ft_sess_put(struct ft_sess *);
int ft_sess_shutdown(struct se_session *);
void ft_sess_close(struct se_session *);
void ft_sess_stop(struct se_session *, int, int);
int ft_sess_logged_in(struct se_session *);
u32 ft_sess_get_index(struct se_session *);
u32 ft_sess_get_port_name(struct se_session *, unsigned char *, u32);
void ft_sess_set_erl0(struct se_session *);

void ft_lport_add(struct fc_lport *, void *);
void ft_lport_del(struct fc_lport *, void *);
int ft_lport_notify(struct notifier_block *, unsigned long, void *);

/*
 * IO methods.
 */
void ft_check_stop_free(struct se_cmd *);
void ft_release_cmd(struct se_cmd *);
int ft_queue_status(struct se_cmd *);
int ft_queue_data_in(struct se_cmd *);
int ft_write_pending(struct se_cmd *);
int ft_write_pending_status(struct se_cmd *);
u32 ft_get_task_tag(struct se_cmd *);
int ft_get_cmd_state(struct se_cmd *);
void ft_new_cmd_failure(struct se_cmd *);
int ft_queue_tm_resp(struct se_cmd *);
int ft_is_state_remove(struct se_cmd *);

/*
 * other internal functions.
 */
int ft_thread(void *);
void ft_recv_req(struct ft_sess *, struct fc_frame *);
struct ft_tpg *ft_lport_find_tpg(struct fc_lport *);
struct ft_node_acl *ft_acl_get(struct ft_tpg *, struct fc_rport_priv *);

void ft_recv_write_data(struct ft_cmd *, struct fc_frame *);
void ft_dump_cmd(struct ft_cmd *, const char *caller);

ssize_t ft_format_wwn(char *, size_t, u64);

#endif /* __TCM_FC_H__ */