2026-01-21 18:59:54 +08:00

285 lines
10 KiB
C

/* SPDX-License-Identifier: GPL-2.0 */
/* Huawei Hifc PCI Express Linux driver
* Copyright(c) 2017 Huawei Technologies Co., Ltd
*
*/
#ifndef __UNF_RPORT_H
#define __UNF_RPORT_H
#define UNF_MAX_SCSI_ID 2048
#define UNF_LOSE_TMO 30
#define UNF_RPORT_INVALID_INDEX 0xffff
/* RSCN compare DISC list with local RPort macro */
#define UNF_RPORT_NEED_PROCESS 0x1
#define UNF_RPORT_ONLY_IN_DISC_PROCESS 0x2
#define UNF_RPORT_ONLY_IN_LOCAL_PROCESS 0x3
#define UNF_RPORT_IN_DISC_AND_LOCAL_PROCESS 0x4
#define UNF_RPORT_NOT_NEED_PROCESS 0x5
#define UNF_ECHO_SEND_MAX_TIMES 1
extern struct unf_rport_feature_pool_s *port_fea_pool;
enum unf_rport_login_state_e {
UNF_RPORT_ST_INIT = 0x1000, /* initialized */
UNF_RPORT_ST_PLOGI_WAIT, /* waiting for PLOGI completion */
UNF_RPORT_ST_PRLI_WAIT, /* waiting for PRLI completion */
UNF_RPORT_ST_READY, /* ready for use */
UNF_RPORT_ST_LOGO, /* port logout sent */
UNF_RPORT_ST_CLOSING, /* being closed */
UNF_RPORT_ST_DELETE, /* port being deleted */
UNF_RPORT_ST_BUTT
};
enum unf_rport_event_e {
UNF_EVENT_RPORT_NORMAL_ENTER = 0x9000,
UNF_EVENT_RPORT_ENTER_PLOGI = 0x9001,
UNF_EVENT_RPORT_ENTER_PRLI = 0x9002,
UNF_EVENT_RPORT_READY = 0x9003,
UNF_EVENT_RPORT_LOGO = 0x9004,
UNF_EVENT_RPORT_CLS_TIMEOUT = 0x9005,
UNF_EVENT_RPORT_RECOVERY = 0x9006,
UNF_EVENT_RPORT_RELOGIN = 0x9007,
UNF_EVENT_RPORT_LINK_DOWN = 0x9008,
UNF_EVENT_RPORT_BUTT
};
/* RPort local link state */
enum unf_port_state_e {
UNF_PORT_STATE_LINKUP = 0x1001,
UNF_PORT_STATE_LINKDOWN = 0x1002
};
enum unf_rport_reuse_flag_e {
UNF_RPORT_REUSE_ONLY = 0x1001,
UNF_RPORT_REUSE_INIT = 0x1002,
UNF_RPORT_REUSE_RECOVER = 0x1003
};
struct unf_disc_rport_s {
/* RPort entry */
struct list_head entry_rport;
unsigned int nport_id; /* Remote port NPortID */
unsigned int disc_done; /* 1:Disc done */
};
struct unf_rport_feature_pool_s {
struct list_head list_busy_head;
struct list_head list_free_head;
void *p_port_feature_pool_addr;
spinlock_t port_fea_pool_lock;
};
struct unf_rport_feature_recard_s {
struct list_head entry_feature;
unsigned long long wwpn;
unsigned int port_feature;
unsigned int reserved;
};
struct unf_os_thread_private_data_s {
struct list_head list;
spinlock_t spin_lock;
struct task_struct *thread;
unsigned int in_process;
unsigned int cpu_id;
atomic_t user_count;
};
/* Remote Port struct */
struct unf_rport_s {
unsigned int max_frame_size;
unsigned int supported_classes;
/* Dynamic Attributes */
/* Remote Port loss timeout in seconds. */
unsigned int dev_loss_tmo;
unsigned long long node_name;
unsigned long long port_name;
unsigned int nport_id; /* Remote port NPortID */
unsigned int local_nport_id;
unsigned int roles;
/* Remote port local INI state */
enum unf_port_state_e lport_ini_state;
enum unf_port_state_e last_lport_ini_state;
/* Remote port local TGT state */
enum unf_port_state_e lport_tgt_state;
enum unf_port_state_e last_lport_tgt_state;
/* Port Type:fc */
unsigned int port_type;
/* RPort reference counter */
atomic_t rport_ref_cnt;
/* Pending IO count */
atomic_t pending_io_cnt;
/* RPort entry */
struct list_head entry_rport;
/* Port State,delay reclaim when uiRpState == complete. */
enum unf_rport_login_state_e rp_state;
unsigned int disc_done; /* 1:Disc done */
struct unf_lport_s *lport;
void *rport;
spinlock_t rport_state_lock;
/* Port attribution */
unsigned int ed_tov;
unsigned int ra_tov;
unsigned int options; /* ini or tgt */
unsigned int last_report_linkup_options;
unsigned int fcp_conf_needed; /* INI Rport send FCP CONF flag */
unsigned int tape_support_needed; /* INI tape support flag */
unsigned int retries; /* special req retry times */
unsigned int logo_retries; /* logo error recovery retry times */
unsigned int mas_retries; /* special req retry times */
/* Rport alloc jiffies */
unsigned long long rport_alloc_jifs;
void *session;
/* binding with SCSI */
unsigned int scsi_id;
/* disc list compare flag */
unsigned int rscn_position;
unsigned int rport_index;
/* RPort timer,closing status */
struct work_struct closing_work;
/* RPort timer,rport linkup */
struct work_struct start_work;
/* RPort timer,recovery */
struct delayed_work recovery_work;
/* RPort timer,TGT mode,PRLI waiting */
struct delayed_work open_work;
struct semaphore task_sema;
/* Callback after rport Ready/delete.[with state:ok/fail].
* Creat/free TGT session here
* input : L_Port,R_Port,state:ready
* --creat session/delete--free session
*/
void (*pfn_unf_rport_call_back)(void *, void *, unsigned int);
struct unf_os_thread_private_data_s *data_thread;
};
#define UNF_IO_RESULT_CNT(v_scsi_table, v_scsi_id, v_io_result) \
do { \
if (likely(((v_io_result) < UNF_MAX_IO_RETURN_VALUE) && \
((v_scsi_id) < UNF_MAX_SCSI_ID) && \
((v_scsi_table)->wwn_rport_info_table) && \
(v_scsi_table->wwn_rport_info_table[v_scsi_id].dfx_counter))) { \
atomic64_inc(&v_scsi_table->wwn_rport_info_table[v_scsi_id].dfx_counter->io_done_cnt[v_io_result]); \
} else { \
UNF_TRACE(UNF_EVTLOG_DRIVER_ERR, \
UNF_LOG_EQUIP_ATT, UNF_ERR, \
"[err] io return value(0x%x) or scsi_id(0x%x) is invalid", \
v_io_result, v_scsi_id); \
} \
} while (0)
#define UNF_SCSI_CMD_CNT(v_scsi_table, v_scsi_id, v_io_type) \
do { \
if (likely(((v_io_type) < UNF_MAX_SCSI_CMD) && \
((v_scsi_id) < UNF_MAX_SCSI_ID) && \
((v_scsi_table)->wwn_rport_info_table) && \
(v_scsi_table->wwn_rport_info_table[v_scsi_id].dfx_counter))) { \
atomic64_inc(&((v_scsi_table->wwn_rport_info_table[v_scsi_id]).dfx_counter->scsi_cmd_cnt[v_io_type])); \
} else { \
UNF_TRACE(UNF_EVTLOG_DRIVER_ERR, \
UNF_LOG_EQUIP_ATT, UNF_ERR, \
"[err] scsi_cmd(0x%x) or scsi_id(0x%x) is invalid", \
v_io_type, v_scsi_id); \
} \
} while (0)
#define UNF_SCSI_ERROR_HANDLE_CNT(v_scsi_table, v_scsi_id, v_io_type) \
do { \
if (likely(((v_io_type) < UNF_SCSI_ERROR_HANDLE_BUTT) && \
((v_scsi_id) < UNF_MAX_SCSI_ID) && \
((v_scsi_table)->wwn_rport_info_table) && \
(v_scsi_table->wwn_rport_info_table[v_scsi_id].dfx_counter))) { \
atomic_inc(&v_scsi_table->wwn_rport_info_table[v_scsi_id].dfx_counter->error_handle[v_io_type]); \
} else { \
UNF_TRACE(UNF_EVTLOG_DRIVER_ERR, \
UNF_LOG_EQUIP_ATT, UNF_ERR, \
"[err] scsi_cmd(0x%x) or scsi_id(0x%x) is invalid", \
v_io_type, v_scsi_id); \
} \
} while (0)
#define UNF_SCSI_ERROR_HANDLE_RESULT_CNT(v_scsi_table, v_scsi_id, v_io_type) \
do { \
if (likely(((v_io_type) < UNF_SCSI_ERROR_HANDLE_BUTT) && \
((v_scsi_id) < UNF_MAX_SCSI_ID) && \
((v_scsi_table)->wwn_rport_info_table) && \
(v_scsi_table->wwn_rport_info_table[v_scsi_id].dfx_counter))) { \
atomic_inc(&v_scsi_table->wwn_rport_info_table[v_scsi_id].dfx_counter->error_handle_result[v_io_type]); \
} else { \
UNF_TRACE(UNF_EVTLOG_DRIVER_ERR, \
UNF_LOG_EQUIP_ATT, UNF_ERR, \
"[err] scsi_cmd(0x%x) or scsi_id(0x%x) is invalid", \
v_io_type, v_scsi_id); \
} \
} while (0)
void unf_rport_state_ma(struct unf_rport_s *v_rport,
enum unf_rport_event_e v_event);
void unf_update_lport_state_by_linkup_event(struct unf_lport_s *v_lport,
struct unf_rport_s *v_rport,
unsigned int rport_att);
void unf_rport_enter_closing(struct unf_rport_s *v_rport);
void unf_clean_linkdown_rport(struct unf_lport_s *v_lport);
void unf_rport_error_recovery(struct unf_rport_s *v_rport);
struct unf_rport_s *unf_get_rport_by_nport_id(struct unf_lport_s *v_lport,
unsigned int nport_id);
void unf_rport_enter_logo(struct unf_lport_s *v_lport,
struct unf_rport_s *v_rport);
unsigned int unf_rport_ref_inc(struct unf_rport_s *v_rport);
void unf_rport_ref_dec(struct unf_rport_s *v_rport);
struct unf_rport_s *unf_rport_set_qualifier_key_reuse(
struct unf_lport_s *v_lport,
struct unf_rport_s *v_rport_by_nport_id,
struct unf_rport_s *v_rport_by_wwpn,
unsigned long long v_wwpn,
unsigned int v_sid);
void unf_rport_delay_login(struct unf_rport_s *v_rport);
struct unf_rport_s *unf_find_valid_rport(struct unf_lport_s *v_lport,
unsigned long long v_wwpn,
unsigned int v_sid);
void unf_rport_linkdown(struct unf_lport_s *v_lport,
struct unf_rport_s *v_rport);
struct unf_rport_s *unf_get_safe_rport(struct unf_lport_s *v_lport,
struct unf_rport_s *v_rport,
enum unf_rport_reuse_flag_e v_reuse_flag,
unsigned int v_nport_id);
void *unf_rport_get_free_and_init(void *v_lport,
unsigned int v_port_type,
unsigned int v_nport_id);
unsigned int unf_free_scsi_id(struct unf_lport_s *v_lport,
unsigned int v_scsi_id);
void unf_schedule_closing_work(struct unf_lport_s *v_lport,
struct unf_rport_s *v_rport);
void unf_sesion_loss_timeout(struct work_struct *v_work);
unsigned int unf_get_port_feature(unsigned long long v_wwpn);
void unf_update_port_feature(unsigned long long v_wwpn,
unsigned int v_port_feature);
#endif