summaryrefslogtreecommitdiff
path: root/drivers/scsi/elx/efct/efct_lio.h
blob: 569a0d4b1894cd4b9c345d998dc729c13e223364 (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
/* SPDX-License-Identifier: GPL-2.0 */
/*
 * Copyright (C) 2021 Broadcom. All Rights Reserved. The term
 * “Broadcom” refers to Broadcom Inc. and/or its subsidiaries.
 */

#ifndef __EFCT_LIO_H__
#define __EFCT_LIO_H__

#include "efct_scsi.h"
#include <target/target_core_base.h>

#define efct_lio_io_printf(io, fmt, ...)			\
	efc_log_debug(io->efct,					\
		"[%s] [%04x][i:%04x t:%04x h:%04x]" fmt,\
		io->node->display_name, io->instance_index,	\
		io->init_task_tag, io->tgt_task_tag, io->hw_tag,\
		##__VA_ARGS__)

#define efct_lio_tmfio_printf(io, fmt, ...)			\
	efc_log_debug(io->efct,					\
		"[%s] [%04x][i:%04x t:%04x h:%04x][f:%02x]" fmt,\
		io->node->display_name, io->instance_index,	\
		io->init_task_tag, io->tgt_task_tag, io->hw_tag,\
		io->tgt_io.tmf,  ##__VA_ARGS__)

#define efct_set_lio_io_state(io, value) (io->tgt_io.state |= value)

struct efct_lio_wq_data {
	struct efct		*efct;
	void			*ptr;
	struct work_struct	work;
};

/* Target private efct structure */
struct efct_scsi_tgt {
	u32			max_sge;
	u32			max_sgl;

	/*
	 * Variables used to send task set full. We are using a high watermark
	 * method to send task set full. We will reserve a fixed number of IOs
	 * per initiator plus a fudge factor. Once we reach this number,
	 * then the target will start sending task set full/busy responses.
	 */
	atomic_t		initiator_count;
	atomic_t		ios_in_use;
	atomic_t		io_high_watermark;

	atomic_t		watermark_hit;
	int			watermark_min;
	int			watermark_max;

	struct efct_lio_nport	*lio_nport;
	struct efct_lio_tpg	*tpg;

	struct list_head	vport_list;
	/* Protects vport list*/
	spinlock_t		efct_lio_lock;

	u64			wwnn;
};

struct efct_scsi_tgt_nport {
	struct efct_lio_nport	*lio_nport;
};

struct efct_node {
	struct list_head	list_entry;
	struct kref		ref;
	void			(*release)(struct kref *arg);
	struct efct		*efct;
	struct efc_node		*node;
	struct se_session	*session;
	spinlock_t		active_ios_lock;
	struct list_head	active_ios;
	char			display_name[EFC_NAME_LENGTH];
	u32			port_fc_id;
	u32			node_fc_id;
	u32			vpi;
	u32			rpi;
	u32			abort_cnt;
};

#define EFCT_LIO_STATE_SCSI_RECV_CMD		(1 << 0)
#define EFCT_LIO_STATE_TGT_SUBMIT_CMD		(1 << 1)
#define EFCT_LIO_STATE_TFO_QUEUE_DATA_IN	(1 << 2)
#define EFCT_LIO_STATE_TFO_WRITE_PENDING	(1 << 3)
#define EFCT_LIO_STATE_TGT_EXECUTE_CMD		(1 << 4)
#define EFCT_LIO_STATE_SCSI_SEND_RD_DATA	(1 << 5)
#define EFCT_LIO_STATE_TFO_CHK_STOP_FREE	(1 << 6)
#define EFCT_LIO_STATE_SCSI_DATA_DONE		(1 << 7)
#define EFCT_LIO_STATE_TFO_QUEUE_STATUS		(1 << 8)
#define EFCT_LIO_STATE_SCSI_SEND_RSP		(1 << 9)
#define EFCT_LIO_STATE_SCSI_RSP_DONE		(1 << 10)
#define EFCT_LIO_STATE_TGT_GENERIC_FREE		(1 << 11)
#define EFCT_LIO_STATE_SCSI_RECV_TMF		(1 << 12)
#define EFCT_LIO_STATE_TGT_SUBMIT_TMR		(1 << 13)
#define EFCT_LIO_STATE_TFO_WRITE_PEND_STATUS	(1 << 14)
#define EFCT_LIO_STATE_TGT_GENERIC_REQ_FAILURE  (1 << 15)

#define EFCT_LIO_STATE_TFO_ABORTED_TASK		(1 << 29)
#define EFCT_LIO_STATE_TFO_RELEASE_CMD		(1 << 30)
#define EFCT_LIO_STATE_SCSI_CMPL_CMD		(1u << 31)

struct efct_scsi_tgt_io {
	struct se_cmd		cmd;
	unsigned char		sense_buffer[TRANSPORT_SENSE_BUFFER];
	enum dma_data_direction	ddir;
	int			task_attr;
	u64			lun;

	u32			state;
	u8			tmf;
	struct efct_io		*io_to_abort;
	u32			seg_map_cnt;
	u32			seg_cnt;
	u32			cur_seg;
	enum efct_scsi_io_status err;
	bool			aborting;
	bool			rsp_sent;
	u32			transferred_len;
};

/* Handler return codes */
enum {
	SCSI_HANDLER_DATAPHASE_STARTED = 1,
	SCSI_HANDLER_RESP_STARTED,
	SCSI_HANDLER_VALIDATED_DATAPHASE_STARTED,
	SCSI_CMD_NOT_SUPPORTED,
};

#define WWN_NAME_LEN		32
struct efct_lio_vport {
	u64			wwpn;
	u64			npiv_wwpn;
	u64			npiv_wwnn;
	unsigned char		wwpn_str[WWN_NAME_LEN];
	struct se_wwn		vport_wwn;
	struct efct_lio_tpg	*tpg;
	struct efct		*efct;
	struct Scsi_Host	*shost;
	struct fc_vport		*fc_vport;
	atomic_t		enable;
};

struct efct_lio_nport {
	u64			wwpn;
	unsigned char		wwpn_str[WWN_NAME_LEN];
	struct se_wwn		nport_wwn;
	struct efct_lio_tpg	*tpg;
	struct efct		*efct;
	atomic_t		enable;
};

struct efct_lio_tpg_attrib {
	u32			generate_node_acls;
	u32			cache_dynamic_acls;
	u32			demo_mode_write_protect;
	u32			prod_mode_write_protect;
	u32			demo_mode_login_only;
	bool			session_deletion_wait;
};

struct efct_lio_tpg {
	struct se_portal_group	tpg;
	struct efct_lio_nport	*nport;
	struct efct_lio_vport	*vport;
	struct efct_lio_tpg_attrib tpg_attrib;
	unsigned short		tpgt;
	bool			enabled;
};

struct efct_lio_nacl {
	u64			nport_wwnn;
	char			nport_name[WWN_NAME_LEN];
	struct se_session	*session;
	struct se_node_acl	se_node_acl;
};

struct efct_lio_vport_list_t {
	struct list_head	list_entry;
	struct efct_lio_vport	*lio_vport;
};

int efct_scsi_tgt_driver_init(void);
int efct_scsi_tgt_driver_exit(void);

#endif /*__EFCT_LIO_H__ */