285 lines
10 KiB
C
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
|