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

#if !defined(__EFCT_SCSI_H__)
#define __EFCT_SCSI_H__
#include <scsi/scsi_host.h>
#include <scsi/scsi_transport_fc.h>

/* efct_scsi_rcv_cmd() efct_scsi_rcv_tmf() flags */
#define EFCT_SCSI_CMD_DIR_IN		(1 << 0)
#define EFCT_SCSI_CMD_DIR_OUT		(1 << 1)
#define EFCT_SCSI_CMD_SIMPLE		(1 << 2)
#define EFCT_SCSI_CMD_HEAD_OF_QUEUE	(1 << 3)
#define EFCT_SCSI_CMD_ORDERED		(1 << 4)
#define EFCT_SCSI_CMD_UNTAGGED		(1 << 5)
#define EFCT_SCSI_CMD_ACA		(1 << 6)
#define EFCT_SCSI_FIRST_BURST_ERR	(1 << 7)
#define EFCT_SCSI_FIRST_BURST_ABORTED	(1 << 8)

/* efct_scsi_send_rd_data/recv_wr_data/send_resp flags */
#define EFCT_SCSI_LAST_DATAPHASE	(1 << 0)
#define EFCT_SCSI_NO_AUTO_RESPONSE	(1 << 1)
#define EFCT_SCSI_LOW_LATENCY		(1 << 2)

#define EFCT_SCSI_SNS_BUF_VALID(sense)	((sense) && \
			(0x70 == (((const u8 *)(sense))[0] & 0x70)))

#define EFCT_SCSI_WQ_STEERING_SHIFT	16
#define EFCT_SCSI_WQ_STEERING_MASK	(0xf << EFCT_SCSI_WQ_STEERING_SHIFT)
#define EFCT_SCSI_WQ_STEERING_CLASS	(0 << EFCT_SCSI_WQ_STEERING_SHIFT)
#define EFCT_SCSI_WQ_STEERING_REQUEST	(1 << EFCT_SCSI_WQ_STEERING_SHIFT)
#define EFCT_SCSI_WQ_STEERING_CPU	(2 << EFCT_SCSI_WQ_STEERING_SHIFT)

#define EFCT_SCSI_WQ_CLASS_SHIFT		(20)
#define EFCT_SCSI_WQ_CLASS_MASK		(0xf << EFCT_SCSI_WQ_CLASS_SHIFT)
#define EFCT_SCSI_WQ_CLASS(x)		((x & EFCT_SCSI_WQ_CLASS_MASK) << \
						EFCT_SCSI_WQ_CLASS_SHIFT)

#define EFCT_SCSI_WQ_CLASS_LOW_LATENCY	1

struct efct_scsi_cmd_resp {
	u8 scsi_status;
	u16 scsi_status_qualifier;
	u8 *response_data;
	u32 response_data_length;
	u8 *sense_data;
	u32 sense_data_length;
	int residual;
	u32 response_wire_length;
};

struct efct_vport {
	struct efct		*efct;
	bool			is_vport;
	struct fc_host_statistics fc_host_stats;
	struct Scsi_Host	*shost;
	struct fc_vport		*fc_vport;
	u64			npiv_wwpn;
	u64			npiv_wwnn;
};

/* Status values returned by IO callbacks */
enum efct_scsi_io_status {
	EFCT_SCSI_STATUS_GOOD = 0,
	EFCT_SCSI_STATUS_ABORTED,
	EFCT_SCSI_STATUS_ERROR,
	EFCT_SCSI_STATUS_DIF_GUARD_ERR,
	EFCT_SCSI_STATUS_DIF_REF_TAG_ERROR,
	EFCT_SCSI_STATUS_DIF_APP_TAG_ERROR,
	EFCT_SCSI_STATUS_DIF_UNKNOWN_ERROR,
	EFCT_SCSI_STATUS_PROTOCOL_CRC_ERROR,
	EFCT_SCSI_STATUS_NO_IO,
	EFCT_SCSI_STATUS_ABORT_IN_PROGRESS,
	EFCT_SCSI_STATUS_CHECK_RESPONSE,
	EFCT_SCSI_STATUS_COMMAND_TIMEOUT,
	EFCT_SCSI_STATUS_TIMEDOUT_AND_ABORTED,
	EFCT_SCSI_STATUS_SHUTDOWN,
	EFCT_SCSI_STATUS_NEXUS_LOST,
};

struct efct_node;
struct efct_io;
struct efc_node;
struct efc_nport;

/* Callback used by send_rd_data(), recv_wr_data(), send_resp() */
typedef int (*efct_scsi_io_cb_t)(struct efct_io *io,
				    enum efct_scsi_io_status status,
				    u32 flags, void *arg);

/* Callback used by send_rd_io(), send_wr_io() */
typedef int (*efct_scsi_rsp_io_cb_t)(struct efct_io *io,
			enum efct_scsi_io_status status,
			struct efct_scsi_cmd_resp *rsp,
			u32 flags, void *arg);

/* efct_scsi_cb_t flags */
#define EFCT_SCSI_IO_CMPL		(1 << 0)
/* IO completed, response sent */
#define EFCT_SCSI_IO_CMPL_RSP_SENT	(1 << 1)
#define EFCT_SCSI_IO_ABORTED		(1 << 2)

/* efct_scsi_recv_tmf() request values */
enum efct_scsi_tmf_cmd {
	EFCT_SCSI_TMF_ABORT_TASK = 1,
	EFCT_SCSI_TMF_QUERY_TASK_SET,
	EFCT_SCSI_TMF_ABORT_TASK_SET,
	EFCT_SCSI_TMF_CLEAR_TASK_SET,
	EFCT_SCSI_TMF_QUERY_ASYNCHRONOUS_EVENT,
	EFCT_SCSI_TMF_LOGICAL_UNIT_RESET,
	EFCT_SCSI_TMF_CLEAR_ACA,
	EFCT_SCSI_TMF_TARGET_RESET,
};

/* efct_scsi_send_tmf_resp() response values */
enum efct_scsi_tmf_resp {
	EFCT_SCSI_TMF_FUNCTION_COMPLETE = 1,
	EFCT_SCSI_TMF_FUNCTION_SUCCEEDED,
	EFCT_SCSI_TMF_FUNCTION_IO_NOT_FOUND,
	EFCT_SCSI_TMF_FUNCTION_REJECTED,
	EFCT_SCSI_TMF_INCORRECT_LOGICAL_UNIT_NUMBER,
	EFCT_SCSI_TMF_SERVICE_DELIVERY,
};

struct efct_scsi_sgl {
	uintptr_t	addr;
	uintptr_t	dif_addr;
	size_t		len;
};

enum efct_scsi_io_role {
	EFCT_SCSI_IO_ROLE_ORIGINATOR,
	EFCT_SCSI_IO_ROLE_RESPONDER,
};

struct efct_io *
efct_scsi_io_alloc(struct efct_node *node);
void efct_scsi_io_free(struct efct_io *io);
struct efct_io *efct_io_get_instance(struct efct *efct, u32 index);

int efct_scsi_tgt_driver_init(void);
int efct_scsi_tgt_driver_exit(void);
int efct_scsi_tgt_new_device(struct efct *efct);
int efct_scsi_tgt_del_device(struct efct *efct);
int
efct_scsi_tgt_new_nport(struct efc *efc, struct efc_nport *nport);
void
efct_scsi_tgt_del_nport(struct efc *efc, struct efc_nport *nport);

int
efct_scsi_new_initiator(struct efc *efc, struct efc_node *node);

enum efct_scsi_del_initiator_reason {
	EFCT_SCSI_INITIATOR_DELETED,
	EFCT_SCSI_INITIATOR_MISSING,
};

int
efct_scsi_del_initiator(struct efc *efc, struct efc_node *node,	int reason);
void
efct_scsi_recv_cmd(struct efct_io *io, uint64_t lun, u8 *cdb, u32 cdb_len,
		   u32 flags);
int
efct_scsi_recv_tmf(struct efct_io *tmfio, u32 lun, enum efct_scsi_tmf_cmd cmd,
		   struct efct_io *abortio, u32 flags);
int
efct_scsi_send_rd_data(struct efct_io *io, u32 flags, struct efct_scsi_sgl *sgl,
		u32 sgl_count, u64 wire_len, efct_scsi_io_cb_t cb, void *arg);
int
efct_scsi_recv_wr_data(struct efct_io *io, u32 flags, struct efct_scsi_sgl *sgl,
		u32 sgl_count, u64 wire_len, efct_scsi_io_cb_t cb, void *arg);
int
efct_scsi_send_resp(struct efct_io *io, u32 flags,
		struct efct_scsi_cmd_resp *rsp, efct_scsi_io_cb_t cb, void *arg);
int
efct_scsi_send_tmf_resp(struct efct_io *io, enum efct_scsi_tmf_resp rspcode,
			u8 addl_rsp_info[3], efct_scsi_io_cb_t cb, void *arg);
int
efct_scsi_tgt_abort_io(struct efct_io *io, efct_scsi_io_cb_t cb, void *arg);

void efct_scsi_io_complete(struct efct_io *io);

int efct_scsi_reg_fc_transport(void);
void efct_scsi_release_fc_transport(void);
int efct_scsi_new_device(struct efct *efct);
void efct_scsi_del_device(struct efct *efct);
void _efct_scsi_io_free(struct kref *arg);

int
efct_scsi_del_vport(struct efct *efct, struct Scsi_Host *shost);
struct efct_vport *
efct_scsi_new_vport(struct efct *efct, struct device *dev);

int efct_scsi_io_dispatch(struct efct_io *io, void *cb);
int efct_scsi_io_dispatch_abort(struct efct_io *io, void *cb);
void efct_scsi_check_pending(struct efct *efct);
struct efct_io *
efct_bls_send_rjt(struct efct_io *io, struct fc_frame_header *hdr);

#endif /* __EFCT_SCSI_H__ */