162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * Copyright (C) 2021 Broadcom. All Rights Reserved. The term
462306a36Sopenharmony_ci * “Broadcom” refers to Broadcom Inc. and/or its subsidiaries.
562306a36Sopenharmony_ci */
662306a36Sopenharmony_ci
762306a36Sopenharmony_ci#if !defined(__EFCT_SCSI_H__)
862306a36Sopenharmony_ci#define __EFCT_SCSI_H__
962306a36Sopenharmony_ci#include <scsi/scsi_host.h>
1062306a36Sopenharmony_ci#include <scsi/scsi_transport_fc.h>
1162306a36Sopenharmony_ci
1262306a36Sopenharmony_ci/* efct_scsi_rcv_cmd() efct_scsi_rcv_tmf() flags */
1362306a36Sopenharmony_ci#define EFCT_SCSI_CMD_DIR_IN		(1 << 0)
1462306a36Sopenharmony_ci#define EFCT_SCSI_CMD_DIR_OUT		(1 << 1)
1562306a36Sopenharmony_ci#define EFCT_SCSI_CMD_SIMPLE		(1 << 2)
1662306a36Sopenharmony_ci#define EFCT_SCSI_CMD_HEAD_OF_QUEUE	(1 << 3)
1762306a36Sopenharmony_ci#define EFCT_SCSI_CMD_ORDERED		(1 << 4)
1862306a36Sopenharmony_ci#define EFCT_SCSI_CMD_UNTAGGED		(1 << 5)
1962306a36Sopenharmony_ci#define EFCT_SCSI_CMD_ACA		(1 << 6)
2062306a36Sopenharmony_ci#define EFCT_SCSI_FIRST_BURST_ERR	(1 << 7)
2162306a36Sopenharmony_ci#define EFCT_SCSI_FIRST_BURST_ABORTED	(1 << 8)
2262306a36Sopenharmony_ci
2362306a36Sopenharmony_ci/* efct_scsi_send_rd_data/recv_wr_data/send_resp flags */
2462306a36Sopenharmony_ci#define EFCT_SCSI_LAST_DATAPHASE	(1 << 0)
2562306a36Sopenharmony_ci#define EFCT_SCSI_NO_AUTO_RESPONSE	(1 << 1)
2662306a36Sopenharmony_ci#define EFCT_SCSI_LOW_LATENCY		(1 << 2)
2762306a36Sopenharmony_ci
2862306a36Sopenharmony_ci#define EFCT_SCSI_SNS_BUF_VALID(sense)	((sense) && \
2962306a36Sopenharmony_ci			(0x70 == (((const u8 *)(sense))[0] & 0x70)))
3062306a36Sopenharmony_ci
3162306a36Sopenharmony_ci#define EFCT_SCSI_WQ_STEERING_SHIFT	16
3262306a36Sopenharmony_ci#define EFCT_SCSI_WQ_STEERING_MASK	(0xf << EFCT_SCSI_WQ_STEERING_SHIFT)
3362306a36Sopenharmony_ci#define EFCT_SCSI_WQ_STEERING_CLASS	(0 << EFCT_SCSI_WQ_STEERING_SHIFT)
3462306a36Sopenharmony_ci#define EFCT_SCSI_WQ_STEERING_REQUEST	(1 << EFCT_SCSI_WQ_STEERING_SHIFT)
3562306a36Sopenharmony_ci#define EFCT_SCSI_WQ_STEERING_CPU	(2 << EFCT_SCSI_WQ_STEERING_SHIFT)
3662306a36Sopenharmony_ci
3762306a36Sopenharmony_ci#define EFCT_SCSI_WQ_CLASS_SHIFT		(20)
3862306a36Sopenharmony_ci#define EFCT_SCSI_WQ_CLASS_MASK		(0xf << EFCT_SCSI_WQ_CLASS_SHIFT)
3962306a36Sopenharmony_ci#define EFCT_SCSI_WQ_CLASS(x)		((x & EFCT_SCSI_WQ_CLASS_MASK) << \
4062306a36Sopenharmony_ci						EFCT_SCSI_WQ_CLASS_SHIFT)
4162306a36Sopenharmony_ci
4262306a36Sopenharmony_ci#define EFCT_SCSI_WQ_CLASS_LOW_LATENCY	1
4362306a36Sopenharmony_ci
4462306a36Sopenharmony_cistruct efct_scsi_cmd_resp {
4562306a36Sopenharmony_ci	u8 scsi_status;
4662306a36Sopenharmony_ci	u16 scsi_status_qualifier;
4762306a36Sopenharmony_ci	u8 *response_data;
4862306a36Sopenharmony_ci	u32 response_data_length;
4962306a36Sopenharmony_ci	u8 *sense_data;
5062306a36Sopenharmony_ci	u32 sense_data_length;
5162306a36Sopenharmony_ci	int residual;
5262306a36Sopenharmony_ci	u32 response_wire_length;
5362306a36Sopenharmony_ci};
5462306a36Sopenharmony_ci
5562306a36Sopenharmony_cistruct efct_vport {
5662306a36Sopenharmony_ci	struct efct		*efct;
5762306a36Sopenharmony_ci	bool			is_vport;
5862306a36Sopenharmony_ci	struct fc_host_statistics fc_host_stats;
5962306a36Sopenharmony_ci	struct Scsi_Host	*shost;
6062306a36Sopenharmony_ci	struct fc_vport		*fc_vport;
6162306a36Sopenharmony_ci	u64			npiv_wwpn;
6262306a36Sopenharmony_ci	u64			npiv_wwnn;
6362306a36Sopenharmony_ci};
6462306a36Sopenharmony_ci
6562306a36Sopenharmony_ci/* Status values returned by IO callbacks */
6662306a36Sopenharmony_cienum efct_scsi_io_status {
6762306a36Sopenharmony_ci	EFCT_SCSI_STATUS_GOOD = 0,
6862306a36Sopenharmony_ci	EFCT_SCSI_STATUS_ABORTED,
6962306a36Sopenharmony_ci	EFCT_SCSI_STATUS_ERROR,
7062306a36Sopenharmony_ci	EFCT_SCSI_STATUS_DIF_GUARD_ERR,
7162306a36Sopenharmony_ci	EFCT_SCSI_STATUS_DIF_REF_TAG_ERROR,
7262306a36Sopenharmony_ci	EFCT_SCSI_STATUS_DIF_APP_TAG_ERROR,
7362306a36Sopenharmony_ci	EFCT_SCSI_STATUS_DIF_UNKNOWN_ERROR,
7462306a36Sopenharmony_ci	EFCT_SCSI_STATUS_PROTOCOL_CRC_ERROR,
7562306a36Sopenharmony_ci	EFCT_SCSI_STATUS_NO_IO,
7662306a36Sopenharmony_ci	EFCT_SCSI_STATUS_ABORT_IN_PROGRESS,
7762306a36Sopenharmony_ci	EFCT_SCSI_STATUS_CHECK_RESPONSE,
7862306a36Sopenharmony_ci	EFCT_SCSI_STATUS_COMMAND_TIMEOUT,
7962306a36Sopenharmony_ci	EFCT_SCSI_STATUS_TIMEDOUT_AND_ABORTED,
8062306a36Sopenharmony_ci	EFCT_SCSI_STATUS_SHUTDOWN,
8162306a36Sopenharmony_ci	EFCT_SCSI_STATUS_NEXUS_LOST,
8262306a36Sopenharmony_ci};
8362306a36Sopenharmony_ci
8462306a36Sopenharmony_cistruct efct_node;
8562306a36Sopenharmony_cistruct efct_io;
8662306a36Sopenharmony_cistruct efc_node;
8762306a36Sopenharmony_cistruct efc_nport;
8862306a36Sopenharmony_ci
8962306a36Sopenharmony_ci/* Callback used by send_rd_data(), recv_wr_data(), send_resp() */
9062306a36Sopenharmony_citypedef int (*efct_scsi_io_cb_t)(struct efct_io *io,
9162306a36Sopenharmony_ci				    enum efct_scsi_io_status status,
9262306a36Sopenharmony_ci				    u32 flags, void *arg);
9362306a36Sopenharmony_ci
9462306a36Sopenharmony_ci/* Callback used by send_rd_io(), send_wr_io() */
9562306a36Sopenharmony_citypedef int (*efct_scsi_rsp_io_cb_t)(struct efct_io *io,
9662306a36Sopenharmony_ci			enum efct_scsi_io_status status,
9762306a36Sopenharmony_ci			struct efct_scsi_cmd_resp *rsp,
9862306a36Sopenharmony_ci			u32 flags, void *arg);
9962306a36Sopenharmony_ci
10062306a36Sopenharmony_ci/* efct_scsi_cb_t flags */
10162306a36Sopenharmony_ci#define EFCT_SCSI_IO_CMPL		(1 << 0)
10262306a36Sopenharmony_ci/* IO completed, response sent */
10362306a36Sopenharmony_ci#define EFCT_SCSI_IO_CMPL_RSP_SENT	(1 << 1)
10462306a36Sopenharmony_ci#define EFCT_SCSI_IO_ABORTED		(1 << 2)
10562306a36Sopenharmony_ci
10662306a36Sopenharmony_ci/* efct_scsi_recv_tmf() request values */
10762306a36Sopenharmony_cienum efct_scsi_tmf_cmd {
10862306a36Sopenharmony_ci	EFCT_SCSI_TMF_ABORT_TASK = 1,
10962306a36Sopenharmony_ci	EFCT_SCSI_TMF_QUERY_TASK_SET,
11062306a36Sopenharmony_ci	EFCT_SCSI_TMF_ABORT_TASK_SET,
11162306a36Sopenharmony_ci	EFCT_SCSI_TMF_CLEAR_TASK_SET,
11262306a36Sopenharmony_ci	EFCT_SCSI_TMF_QUERY_ASYNCHRONOUS_EVENT,
11362306a36Sopenharmony_ci	EFCT_SCSI_TMF_LOGICAL_UNIT_RESET,
11462306a36Sopenharmony_ci	EFCT_SCSI_TMF_CLEAR_ACA,
11562306a36Sopenharmony_ci	EFCT_SCSI_TMF_TARGET_RESET,
11662306a36Sopenharmony_ci};
11762306a36Sopenharmony_ci
11862306a36Sopenharmony_ci/* efct_scsi_send_tmf_resp() response values */
11962306a36Sopenharmony_cienum efct_scsi_tmf_resp {
12062306a36Sopenharmony_ci	EFCT_SCSI_TMF_FUNCTION_COMPLETE = 1,
12162306a36Sopenharmony_ci	EFCT_SCSI_TMF_FUNCTION_SUCCEEDED,
12262306a36Sopenharmony_ci	EFCT_SCSI_TMF_FUNCTION_IO_NOT_FOUND,
12362306a36Sopenharmony_ci	EFCT_SCSI_TMF_FUNCTION_REJECTED,
12462306a36Sopenharmony_ci	EFCT_SCSI_TMF_INCORRECT_LOGICAL_UNIT_NUMBER,
12562306a36Sopenharmony_ci	EFCT_SCSI_TMF_SERVICE_DELIVERY,
12662306a36Sopenharmony_ci};
12762306a36Sopenharmony_ci
12862306a36Sopenharmony_cistruct efct_scsi_sgl {
12962306a36Sopenharmony_ci	uintptr_t	addr;
13062306a36Sopenharmony_ci	uintptr_t	dif_addr;
13162306a36Sopenharmony_ci	size_t		len;
13262306a36Sopenharmony_ci};
13362306a36Sopenharmony_ci
13462306a36Sopenharmony_cienum efct_scsi_io_role {
13562306a36Sopenharmony_ci	EFCT_SCSI_IO_ROLE_ORIGINATOR,
13662306a36Sopenharmony_ci	EFCT_SCSI_IO_ROLE_RESPONDER,
13762306a36Sopenharmony_ci};
13862306a36Sopenharmony_ci
13962306a36Sopenharmony_cistruct efct_io *
14062306a36Sopenharmony_ciefct_scsi_io_alloc(struct efct_node *node);
14162306a36Sopenharmony_civoid efct_scsi_io_free(struct efct_io *io);
14262306a36Sopenharmony_cistruct efct_io *efct_io_get_instance(struct efct *efct, u32 index);
14362306a36Sopenharmony_ci
14462306a36Sopenharmony_ciint efct_scsi_tgt_driver_init(void);
14562306a36Sopenharmony_ciint efct_scsi_tgt_driver_exit(void);
14662306a36Sopenharmony_ciint efct_scsi_tgt_new_device(struct efct *efct);
14762306a36Sopenharmony_ciint efct_scsi_tgt_del_device(struct efct *efct);
14862306a36Sopenharmony_ciint
14962306a36Sopenharmony_ciefct_scsi_tgt_new_nport(struct efc *efc, struct efc_nport *nport);
15062306a36Sopenharmony_civoid
15162306a36Sopenharmony_ciefct_scsi_tgt_del_nport(struct efc *efc, struct efc_nport *nport);
15262306a36Sopenharmony_ci
15362306a36Sopenharmony_ciint
15462306a36Sopenharmony_ciefct_scsi_new_initiator(struct efc *efc, struct efc_node *node);
15562306a36Sopenharmony_ci
15662306a36Sopenharmony_cienum efct_scsi_del_initiator_reason {
15762306a36Sopenharmony_ci	EFCT_SCSI_INITIATOR_DELETED,
15862306a36Sopenharmony_ci	EFCT_SCSI_INITIATOR_MISSING,
15962306a36Sopenharmony_ci};
16062306a36Sopenharmony_ci
16162306a36Sopenharmony_ciint
16262306a36Sopenharmony_ciefct_scsi_del_initiator(struct efc *efc, struct efc_node *node,	int reason);
16362306a36Sopenharmony_civoid
16462306a36Sopenharmony_ciefct_scsi_recv_cmd(struct efct_io *io, uint64_t lun, u8 *cdb, u32 cdb_len,
16562306a36Sopenharmony_ci		   u32 flags);
16662306a36Sopenharmony_ciint
16762306a36Sopenharmony_ciefct_scsi_recv_tmf(struct efct_io *tmfio, u32 lun, enum efct_scsi_tmf_cmd cmd,
16862306a36Sopenharmony_ci		   struct efct_io *abortio, u32 flags);
16962306a36Sopenharmony_ciint
17062306a36Sopenharmony_ciefct_scsi_send_rd_data(struct efct_io *io, u32 flags, struct efct_scsi_sgl *sgl,
17162306a36Sopenharmony_ci		u32 sgl_count, u64 wire_len, efct_scsi_io_cb_t cb, void *arg);
17262306a36Sopenharmony_ciint
17362306a36Sopenharmony_ciefct_scsi_recv_wr_data(struct efct_io *io, u32 flags, struct efct_scsi_sgl *sgl,
17462306a36Sopenharmony_ci		u32 sgl_count, u64 wire_len, efct_scsi_io_cb_t cb, void *arg);
17562306a36Sopenharmony_ciint
17662306a36Sopenharmony_ciefct_scsi_send_resp(struct efct_io *io, u32 flags,
17762306a36Sopenharmony_ci		struct efct_scsi_cmd_resp *rsp, efct_scsi_io_cb_t cb, void *arg);
17862306a36Sopenharmony_ciint
17962306a36Sopenharmony_ciefct_scsi_send_tmf_resp(struct efct_io *io, enum efct_scsi_tmf_resp rspcode,
18062306a36Sopenharmony_ci			u8 addl_rsp_info[3], efct_scsi_io_cb_t cb, void *arg);
18162306a36Sopenharmony_ciint
18262306a36Sopenharmony_ciefct_scsi_tgt_abort_io(struct efct_io *io, efct_scsi_io_cb_t cb, void *arg);
18362306a36Sopenharmony_ci
18462306a36Sopenharmony_civoid efct_scsi_io_complete(struct efct_io *io);
18562306a36Sopenharmony_ci
18662306a36Sopenharmony_ciint efct_scsi_reg_fc_transport(void);
18762306a36Sopenharmony_civoid efct_scsi_release_fc_transport(void);
18862306a36Sopenharmony_ciint efct_scsi_new_device(struct efct *efct);
18962306a36Sopenharmony_civoid efct_scsi_del_device(struct efct *efct);
19062306a36Sopenharmony_civoid _efct_scsi_io_free(struct kref *arg);
19162306a36Sopenharmony_ci
19262306a36Sopenharmony_ciint
19362306a36Sopenharmony_ciefct_scsi_del_vport(struct efct *efct, struct Scsi_Host *shost);
19462306a36Sopenharmony_cistruct efct_vport *
19562306a36Sopenharmony_ciefct_scsi_new_vport(struct efct *efct, struct device *dev);
19662306a36Sopenharmony_ci
19762306a36Sopenharmony_ciint efct_scsi_io_dispatch(struct efct_io *io, void *cb);
19862306a36Sopenharmony_ciint efct_scsi_io_dispatch_abort(struct efct_io *io, void *cb);
19962306a36Sopenharmony_civoid efct_scsi_check_pending(struct efct *efct);
20062306a36Sopenharmony_cistruct efct_io *
20162306a36Sopenharmony_ciefct_bls_send_rjt(struct efct_io *io, struct fc_frame_header *hdr);
20262306a36Sopenharmony_ci
20362306a36Sopenharmony_ci#endif /* __EFCT_SCSI_H__ */
204