| /* 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__ */ |