0
     ˆÇÆ„O²À¾Ä :S    /* SPDX-License-Identifier: GPL-2.0-or-later */
/*
 * iSCSI lib definitions
 *
 * Copyright (C) 2006 Red Hat, Inc.  All rights reserved.
 * Copyright (C) 2004 - 2006 Mike Christie
 * Copyright (C) 2004 - 2005 Dmitry Yusupov
 * Copyright (C) 2004 - 2005 Alex Aizman
 */
#ifndef LIBISCSI_H
#define LIBISCSI_H

#include <linux/types.h>
#include <linux/wait.h>
#include <linux/mutex.h>
#include <linux/timer.h>
#include <linux/workqueue.h>
#include <linux/kfifo.h>
#include <linux/refcount.h>
#include <scsi/iscsi_proto.h>
#include <scsi/iscsi_if.h>
#include <scsi/scsi_cmnd.h>
#include <scsi/scsi_transport_iscsi.h>

struct scsi_transport_template;
struct scsi_host_template;
struct scsi_device;
struct Scsi_Host;
struct scsi_target;
struct scsi_cmnd;
struct socket;
struct iscsi_transport;
struct iscsi_cls_session;
struct iscsi_cls_conn;
struct iscsi_session;
struct iscsi_nopin;
struct device;

#define ISCSI_DEF_XMIT_CMDS_MAX	128	/* must be power of 2 */
#define ISCSI_MGMT_CMDS_MAX	15

#define ISCSI_DEF_CMD_PER_LUN	32

/* Task Mgmt states */
enum {
	TMF_INITIAL,
	TMF_QUEUED,
	TMF_SUCCESS,
	TMF_FAILED,
	TMF_TIMEDOUT,
	TMF_NOT_FOUND,
};

#define ISID_SIZE			6

/* Connection flags */
#define ISCSI_CONN_FLAG_SUSPEND_TX	0
#define ISCSI_CONN_FLAG_SUSPEND_RX	1
#define ISCSI_CONN_FLAG_BOUND		2

#define ISCSI_ITT_MASK			0x1fff
#define ISCSI_TOTAL_CMDS_MAX		4096
/* this must be a power of two greater than ISCSI_MGMT_CMDS_MAX */
#define ISCSI_TOTAL_CMDS_MIN		16
#define ISCSI_AGE_SHIFT			28
#define ISCSI_AGE_MASK			0xf

#define ISCSI_ADDRESS_BUF_LEN		64

enum {
	/* this is the maximum possible storage for AHSs */
	ISCSI_MAX_AHS_SIZE = sizeof(struct iscsi_ecdb_ahdr) +
				sizeof(struct iscsi_rlength_ahdr),
	ISCSI_DIGEST_SIZE = sizeof(__u32),
};


enum {
	ISCSI_TASK_FREE,
	ISCSI_TASK_COMPLETED,
	ISCSI_TASK_PENDING,
	ISCSI_TASK_RUNNING,
	ISCSI_TASK_ABRT_TMF,		/* aborted due to TMF */
	ISCSI_TASK_ABRT_SESS_RECOV,	/* aborted due to session recovery */
	ISCSI_TASK_REQUEUE_SCSIQ,	/* qcmd requeueing to scsi-ml */
};

struct iscsi_r2t_info {
	__be32			ttt;		/* copied from R2T */
	__be32			exp_statsn;	/* copied from R2T */
	uint32_t		data_length;	/* copied from R2T */
	uint32_t		data_offset;	/* copied from R2T */
	int			data_count;	/* DATA-Out payload progress */
	int			datasn;
	/* LLDs should set/update these values */
	int			sent;		/* R2T sequence progress */
};

struct iscsi_task {
	/*
	 * Because LLDs allocate their hdr differently, this is a pointer
	 * and length to that storage. It must be setup at session
	 * creation time.
	 */
	struct iscsi_hdr	*hdr;
	unsigned short		hdr_max;
	unsigned short		hdr_len;	/* accumulated size of hdr used */
	/* copied values in case we need to send tmfs */
	itt_t			hdr_itt;
	__be32			cmdsn;
	struct scsi_lun		lun;

	int			itt;		/* this ITT */

	unsigned		imm_count;	/* imm-data (bytes)   */
	/* offset in unsolicited stream (bytes); */
	struct iscsi_r2t_info	unsol_r2t;
	char			*data;		/* mgmt payload */
	unsigned		data_count;
	struct scsi_cmnd	*sc;		/* associated SCSI cmd*/
	struct iscsi_conn	*conn;		/* used connection    */

	/* data processing tracking */
	unsigned long		last_xfer;
	unsigned long		last_timeout;
	bool			have_checked_conn;

	/* T10 protection information */
	bool			protected;

	/* state set/tested under session->lock */
	int			state;
	refcount_t		refcount;
	struct list_head	running;	/* running cmd list */
	void			*dd_data;	/* driver/transport data */
};

static inline int iscsi_task_has_unsol_data(struct iscsi_task *task)
{
	return task->unsol_r2t.data_length > task->unsol_r2t.sent;
}

static inline void* iscsi_next_hdr(struct iscsi_task *task)
{
	return (void*)task->hdr + task->hdr_len;
}

static inline bool iscsi_task_is_completed(struct iscsi_task *task)
{
	return task->state == ISCSI_TASK_COMPLETED ||
	       task->state == ISCSI_TASK_ABRT_TMF ||
	       task->state == ISCSI_TASK_ABRT_SESS_RECOV;
}

/* Private data associated with struct scsi_cmnd. */
struct iscsi_cmd {
	struct iscsi_task	*task;
	int			age;
};

static inline struct iscsi_cmd *iscsi_cmd(struct scsi_cm