提交 418ca332 编写于 作者: C Chenguangli 提交者: Yang Yingliang

scsi/hifc: add hifc driver scsi module

driver inclusion
category: feature
bugzilla: NA

-----------------------------------------------------------------------

This module is used to register the hifc driver FC capability to the
SCSI layer.
Signed-off-by: NChenguangli <chenguangli2@huawei.com>
Reviewed-by: NZengweiliang <zengweiliang.zengweiliang@huawei.com>
Acked-by: NHanjun Guo <guohanjun@huawei.com>
Signed-off-by: NYang Yingliang <yangyingliang@huawei.com>
上级 b1f94ebe
/* SPDX-License-Identifier: GPL-2.0 */
/* Huawei Hifc PCI Express Linux driver
* Copyright(c) 2017 Huawei Technologies Co., Ltd
*
*/
#ifndef HIFC_KNL_ADP_H_
#define HIFC_KNL_ADP_H_
#include <linux/types.h>
#include <linux/compiler.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/pci.h>
#include <linux/interrupt.h>
#include <linux/jiffies.h>
#include <linux/cpufreq.h>
#include <linux/semaphore.h>
#include <linux/sched.h>
#include <linux/kthread.h>
#include <linux/vmalloc.h>
#include <linux/version.h>
#include <linux/list.h>
#include <linux/spinlock.h>
#include <linux/delay.h>
#include <linux/workqueue.h>
#include <linux/scatterlist.h>
#include <scsi/scsi.h>
#include <scsi/scsi_host.h>
#include <scsi/scsi_device.h>
#include <scsi/scsi_cmnd.h>
#include <scsi/scsi_tcq.h>
#include <scsi/scsi_transport_fc.h>
#include <linux/sched/signal.h>
#define __TIME_STR__ "[compiled with the kernel]"
#define sdk_err(dev, format, ...) \
dev_err(dev, "[COMM]"format, ##__VA_ARGS__)
#define sdk_warn(dev, format, ...) \
dev_warn(dev, "[COMM]"format, ##__VA_ARGS__)
#define sdk_notice(dev, format, ...) \
dev_notice(dev, "[COMM]"format, ##__VA_ARGS__)
#define sdk_info(dev, format, ...) \
dev_info(dev, "[COMM]"format, ##__VA_ARGS__)
#endif
// SPDX-License-Identifier: GPL-2.0
/* Huawei Hifc PCI Express Linux driver
* Copyright(c) 2017 Huawei Technologies Co., Ltd
*
*/
#include "hifc_module.h"
struct unf_cm_handle_op_s hifc_cm_handle = { 0 };
unsigned int dif_sgl_mode;
unsigned int max_speed = HIFC_SPEED_32G;
unsigned int accum_db_num = 1;
unsigned int dif_type = 0x1;
unsigned int wqe_page_size = 4096;
unsigned int wqe_pre_load = 6;
unsigned int combo_length_kb = 8;
unsigned int cos_bit_map = 0x1f;
unsigned int hifc_dif_type;
unsigned int hifc_dif_enable;
unsigned char hifc_guard;
/* dfx counter */
atomic64_t rx_tx_stat[HIFC_MAX_PORT_NUM][HIFC_TASK_TYPE_STAT_NUM];
atomic64_t rx_tx_err[HIFC_MAX_PORT_NUM][HIFC_TASK_TYPE_STAT_NUM];
atomic64_t scq_err_stat[HIFC_MAX_PORT_NUM][HIFC_TASK_TYPE_STAT_NUM];
atomic64_t aeq_err_stat[HIFC_MAX_PORT_NUM][HIFC_TASK_TYPE_STAT_NUM];
atomic64_t dif_err_stat[HIFC_MAX_PORT_NUM][HIFC_TASK_TYPE_STAT_NUM];
atomic64_t mail_box_stat[HIFC_MAX_PORT_NUM][HIFC_TASK_TYPE_STAT_NUM];
atomic64_t up_err_event_stat[HIFC_MAX_PORT_NUM][HIFC_TASK_TYPE_STAT_NUM];
unsigned long long link_event_stat[HIFC_MAX_PORT_NUM][HIFC_MAX_LINK_EVENT_CNT];
unsigned long long link_reason_stat[HIFC_MAX_PORT_NUM][HIFC_MAX_LINK_REASON_CNT];
unsigned long long hba_stat[HIFC_MAX_PORT_NUM][HIFC_HBA_STAT_BUTT];
atomic64_t com_up_event_err_stat[HIFC_MAX_PORT_NUM][HIFC_TASK_TYPE_STAT_NUM];
static void hifc_realease_cmo_op_handle(void)
{
memset(&hifc_cm_handle, 0, sizeof(struct unf_cm_handle_op_s));
}
static void hifc_check_module_para(void)
{
if (dif_sgl_mode != 0)
dif_sgl_mode = 1;
}
int hifc_init_module(void)
{
int ret = RETURN_OK;
ret = unf_common_init();
if (ret != RETURN_OK) {
UNF_TRACE(UNF_EVTLOG_DRIVER_ERR, UNF_LOG_REG_ATT, UNF_ERR,
"[err]unf_common_init failed");
return RETURN_ERROR_S32;
}
memset(rx_tx_stat, 0, sizeof(rx_tx_stat));
memset(rx_tx_err, 0, sizeof(rx_tx_err));
memset(scq_err_stat, 0, sizeof(scq_err_stat));
memset(aeq_err_stat, 0, sizeof(aeq_err_stat));
memset(dif_err_stat, 0, sizeof(dif_err_stat));
memset(link_event_stat, 0, sizeof(link_event_stat));
memset(link_reason_stat, 0, sizeof(link_reason_stat));
memset(hba_stat, 0, sizeof(hba_stat));
memset(&hifc_cm_handle, 0, sizeof(struct unf_cm_handle_op_s));
memset(up_err_event_stat, 0, sizeof(up_err_event_stat));
memset(mail_box_stat, 0, sizeof(mail_box_stat));
memset(hifc_hba, 0, sizeof(hifc_hba));
spin_lock_init(&probe_spin_lock);
/* 2. Module parameters check */
hifc_check_module_para();
/* 4. Get COM Handlers used for low_level */
if (unf_get_cm_handle_op(&hifc_cm_handle) != RETURN_OK) {
hifc_realease_cmo_op_handle();
return RETURN_ERROR_S32;
}
HIFC_TRACE(UNF_EVTLOG_DRIVER_INFO, UNF_LOG_REG_ATT, UNF_KEVENT,
"[event]Init HIFC module succeed");
return ret;
}
void hifc_exit_module(void)
{
HIFC_TRACE(UNF_EVTLOG_DRIVER_INFO, UNF_LOG_REG_ATT, UNF_MAJOR,
"[event]HIFC module removing...");
hifc_realease_cmo_op_handle();
/* 2. Unregister FC COM module(level) */
unf_common_exit();
}
module_param(dif_sgl_mode, uint, 0444);
module_param(max_speed, uint, 0444);
module_param(wqe_page_size, uint, 0444);
module_param(combo_length_kb, uint, 0444);
module_param(cos_bit_map, uint, 0444);
/* SPDX-License-Identifier: GPL-2.0 */
/* Huawei Hifc PCI Express Linux driver
* Copyright(c) 2017 Huawei Technologies Co., Ltd
*
*/
#ifndef __HIFC_MODULE_H__
#define __HIFC_MODULE_H__
#include "unf_log.h"
#include "unf_common.h"
#include "hifc_utils.h"
#include "hifc_hba.h"
#define HIFC_SPEED_16G 0x10
#define HIFC_SPEED_32G 0x20
#define HIFC_MAX_PORT_NUM HIFC_MAX_PROBE_PORT_NUM
#define HIFC_TASK_TYPE_STAT_NUM 128
#define HIFC_MAX_LINK_EVENT_CNT 4
#define HIFC_MAX_LINK_REASON_CNT 256
/* Declare the global function. */
extern struct unf_cm_handle_op_s hifc_cm_handle;
extern unsigned int max_speed;
extern unsigned int accum_db_num;
extern unsigned int wqe_page_size;
extern unsigned int dif_type;
extern unsigned int wqe_pre_load;
extern unsigned int combo_length_kb;
extern unsigned int cos_bit_map;
extern atomic64_t rx_tx_stat[HIFC_MAX_PORT_NUM][HIFC_TASK_TYPE_STAT_NUM];
extern atomic64_t rx_tx_err[HIFC_MAX_PORT_NUM][HIFC_TASK_TYPE_STAT_NUM];
extern atomic64_t scq_err_stat[HIFC_MAX_PORT_NUM][HIFC_TASK_TYPE_STAT_NUM];
extern atomic64_t aeq_err_stat[HIFC_MAX_PORT_NUM][HIFC_TASK_TYPE_STAT_NUM];
extern atomic64_t dif_err_stat[HIFC_MAX_PORT_NUM][HIFC_TASK_TYPE_STAT_NUM];
extern atomic64_t mail_box_stat[HIFC_MAX_PORT_NUM][HIFC_TASK_TYPE_STAT_NUM];
extern atomic64_t com_up_event_err_stat[HIFC_MAX_PORT_NUM][HIFC_TASK_TYPE_STAT_NUM];
extern unsigned long long link_event_stat[HIFC_MAX_PORT_NUM][HIFC_MAX_LINK_EVENT_CNT];
extern unsigned long long link_reason_stat[HIFC_MAX_PORT_NUM][HIFC_MAX_LINK_REASON_CNT];
extern atomic64_t up_err_event_stat[HIFC_MAX_PORT_NUM][HIFC_TASK_TYPE_STAT_NUM];
extern unsigned long long hba_stat[HIFC_MAX_PORT_NUM][HIFC_HBA_STAT_BUTT];
#define HIFC_LINK_EVENT_STAT(v_hba, link_ent) \
(link_event_stat[(v_hba)->probe_index][link_ent]++)
#define HIFC_LINK_REASON_STAT(v_hba, link_rsn) \
(link_reason_stat[(v_hba)->probe_index][link_rsn]++)
#define HIFC_HBA_STAT(v_hba, hba_stat_type) \
(hba_stat[(v_hba)->probe_index][hba_stat_type]++)
#define HIFC_UP_ERR_EVENT_STAT(v_hba, err_type) \
(atomic64_inc(&up_err_event_stat[(v_hba)->probe_index][err_type]))
#define HIFC_UP_ERR_EVENT_STAT_READ(probe_index, io_type) \
(atomic64_read(&up_err_event_stat[probe_index][io_type]))
#define HIFC_DIF_ERR_STAT(v_hba, dif_err) \
(atomic64_inc(&dif_err_stat[(v_hba)->probe_index][dif_err]))
#define HIFC_DIF_ERR_STAT_READ(probe_index, dif_err) \
(atomic64_read(&dif_err_stat[probe_index][dif_err]))
#define HIFC_IO_STAT(v_hba, io_type) \
(atomic64_inc(&rx_tx_stat[(v_hba)->probe_index][io_type]))
#define HIFC_IO_STAT_READ(probe_index, io_type) \
(atomic64_read(&rx_tx_stat[probe_index][io_type]))
#define HIFC_ERR_IO_STAT(v_hba, io_type) \
(atomic64_inc(&rx_tx_err[(v_hba)->probe_index][io_type]))
#define HIFC_ERR_IO_STAT_READ(probe_index, io_type) \
(atomic64_read(&rx_tx_err[probe_index][io_type]))
#define HIFC_SCQ_ERR_TYPE_STAT(v_hba, err_type) \
(atomic64_inc(&scq_err_stat[(v_hba)->probe_index][err_type]))
#define HIFC_SCQ_ERR_TYPE_STAT_READ(probe_index, io_type) \
(atomic64_read(&scq_err_stat[probe_index][io_type]))
#define HIFC_AEQ_ERR_TYPE_STAT(v_hba, err_type) \
(atomic64_inc(&aeq_err_stat[(v_hba)->probe_index][err_type]))
#define HIFC_AEQ_ERR_TYPE_STAT_READ(probe_index, io_type) \
(atomic64_read(&aeq_err_stat[probe_index][io_type]))
#define HIFC_MAILBOX_STAT(v_hba, io_type) \
(atomic64_inc(&mail_box_stat[(v_hba)->probe_index][io_type]))
#define HIFC_COM_UP_ERR_EVENT_STAT(v_hba, err_type) \
(atomic64_inc(&com_up_event_err_stat[(v_hba)->probe_index][err_type]))
#define HIFC_COM_UP_ERR_EVENT_STAT_READ(probe_index, err_type) \
(atomic64_read(&com_up_event_err_stat[probe_index][err_type]))
/*
*----------------------------------------------*
* Define function *
*----------------------------------------------
*/
#define UNF_LOWLEVEL_ALLOC_LPORT(v_lport, fc_port, stLowLevel)\
do {\
if (hifc_cm_handle.pfn_unf_alloc_local_port) { \
v_lport = \
hifc_cm_handle.pfn_unf_alloc_local_port((fc_port), \
(stLowLevel));\
} else { \
v_lport = NULL; \
} \
} while (0)
#define UNF_LOWLEVEL_RECEIVE_ELS_PKG(v_ret, fc_port, pkg) \
do { \
if (hifc_cm_handle.pfn_unf_receive_els_pkg) {\
v_ret =\
hifc_cm_handle.pfn_unf_receive_els_pkg(\
(fc_port), (pkg));\
} else { \
v_ret = UNF_RETURN_ERROR; \
} \
} while (0)
#define UNF_LOWLEVEL_SEND_ELS_DONE(v_ret, fc_port, pkg) \
do { \
if (hifc_cm_handle.pfn_unf_send_els_done) {\
v_ret = hifc_cm_handle.pfn_unf_send_els_done((fc_port),\
(pkg)); \
} else { \
v_ret = UNF_RETURN_ERROR; \
} \
} while (0)
#define UNF_LOWLEVEL_RECEIVE_GS_PKG(v_ret, fc_port, pkg)\
do { \
if (hifc_cm_handle.pfn_unf_receive_gs_pkg) {\
v_ret = hifc_cm_handle.pfn_unf_receive_gs_pkg(\
(fc_port),\
(pkg)); \
} else { \
v_ret = UNF_RETURN_ERROR; \
} \
} while (0)
#define UNF_LOWLEVEL_GET_CFG_PARMS(v_ret, \
v_section_name, \
v_cfg_parm, \
v_cfg_value, \
v_item_num) \
do { \
if (hifc_cm_handle.pfn_unf_get_cfg_parms) { \
v_ret = (unsigned int)\
hifc_cm_handle.pfn_unf_get_cfg_parms(\
(v_section_name), \
(v_cfg_parm), \
(v_cfg_value), \
(v_item_num)); \
} else { \
HIFC_TRACE(UNF_EVTLOG_DRIVER_WARN, UNF_LOG_REG_ATT,\
UNF_WARN,\
"Get config parameter function is NULL.");\
v_ret = UNF_RETURN_ERROR; \
} \
} while (0)
#define UNF_LOWLEVEL_RELEASE_LOCAL_PORT(v_ret, lport) \
do { \
if (unlikely(!hifc_cm_handle.pfn_unf_release_local_port)) {\
v_ret = UNF_RETURN_ERROR; \
} else { \
v_ret =\
hifc_cm_handle.pfn_unf_release_local_port(\
(lport));\
} \
} while (0)
#define UNF_LOWLEVEL_TO_CM_HINICADM(v_ret, lport, pkg) \
do { \
if (unlikely(!hifc_cm_handle.pfn_unf_ioctl_to_com_handler)) {\
v_ret = UNF_RETURN_ERROR; \
} else { \
v_ret = hifc_cm_handle.pfn_unf_ioctl_to_com_handler(\
lport, pkg); \
} \
} while (0)
#define UNF_CM_GET_SGL_ENTRY(v_ret, pkg, v_buf, v_buf_len) \
do { \
if (unlikely(!hifc_cm_handle.pfn_unf_cm_get_sgl_entry)) {\
v_ret = UNF_RETURN_ERROR; \
} else { \
v_ret = hifc_cm_handle.pfn_unf_cm_get_sgl_entry(\
pkg, v_buf, v_buf_len);\
} \
} while (0)
#define UNF_CM_GET_DIF_SGL_ENTRY(v_ret, pkg, v_buf, v_buf_len)\
do { \
if (unlikely(!hifc_cm_handle.pfn_unf_cm_get_dif_sgl_entry)) {\
v_ret = UNF_RETURN_ERROR; \
} else { \
v_ret = hifc_cm_handle.pfn_unf_cm_get_dif_sgl_entry(\
pkg,\
v_buf,\
v_buf_len);\
} \
} while (0)
#define UNF_GET_SGL_ENTRY(v_ret, pkg, v_buf, v_buf_len, v_dif_flag) \
do { \
if (v_dif_flag) { \
UNF_CM_GET_DIF_SGL_ENTRY(v_ret, pkg, v_buf, v_buf_len);\
} else { \
UNF_CM_GET_SGL_ENTRY(v_ret, pkg, v_buf, v_buf_len);\
} \
} while (0)
#define UNF_GET_FREE_ESGL_PAGE(v_ret, lport, pkg) \
do { \
if (unlikely(!hifc_cm_handle.pfn_unf_get_one_free_esgl_page)) {\
v_ret = NULL; \
} else { \
v_ret = hifc_cm_handle.pfn_unf_get_one_free_esgl_page(\
lport, pkg); \
} \
} while (0)
#define UNF_LOWLEVEL_SCSI_COMPLETED(v_ret, lport, pkg) \
do { \
if (unlikely(!hifc_cm_handle.pfn_unf_receive_ini_rsponse)) {\
v_ret = UNF_RETURN_ERROR; \
} else { \
v_ret = hifc_cm_handle.pfn_unf_receive_ini_rsponse(\
lport, pkg);\
} \
} while (0)
#define UNF_LOWLEVEL_PORT_EVENT(v_ret, lport, v_events, v_input)\
do { \
if (unlikely(!hifc_cm_handle.pfn_unf_fc_port_link_event)) {\
v_ret = UNF_RETURN_ERROR; \
} else { \
v_ret = hifc_cm_handle.pfn_unf_fc_port_link_event(\
lport, v_events, v_input);\
} \
} while (0)
#define UNF_LOWLEVEL_RECEIVE_FC4LS_PKG(v_ret, fc_port, pkg)\
do { \
if (hifc_cm_handle.pfn_unf_receive_fc4_pkg) {\
v_ret = hifc_cm_handle.pfn_unf_receive_fc4_pkg(\
(fc_port), (pkg));\
} else { \
v_ret = UNF_RETURN_ERROR; \
} \
} while (0)
#define UNF_LOWLEVEL_SEND_FC4LS_DONE(v_ret, lport, pkg) \
do { \
if (hifc_cm_handle.pfn_unf_send_fc4_done) {\
v_ret = hifc_cm_handle.pfn_unf_send_fc4_done(\
(lport), (pkg));\
} else { \
v_ret = UNF_RETURN_ERROR; \
} \
} while (0)
#define UNF_LOWLEVEL_RECEIVE_BLS_PKG(v_ret, lport, pkg) \
do { \
if (hifc_cm_handle.pfn_unf_receive_bls_pkg) {\
v_ret = hifc_cm_handle.pfn_unf_receive_bls_pkg(\
(lport), (pkg)); \
} else { \
v_ret = UNF_RETURN_ERROR; \
} \
} while (0)
#define UNF_LOWLEVEL_RECEIVE_MARKER_STS(v_ret, lport, pkg)\
do { \
if (hifc_cm_handle.pfn_unf_receive_marker_status) {\
v_ret = hifc_cm_handle.pfn_unf_receive_marker_status(\
(lport), (pkg));\
} else { \
v_ret = UNF_RETURN_ERROR; \
} \
} while (0)
#define UNF_LOWLEVEL_RECEIVE_ABTS_MARKER_STS(v_ret, lport, pkg) \
do { \
if (hifc_cm_handle.pfn_unf_receive_abts_marker_status) {\
v_ret =\
hifc_cm_handle.pfn_unf_receive_abts_marker_status(\
(lport), (pkg));\
} else { \
v_ret = UNF_RETURN_ERROR; \
} \
} while (0)
#endif
// SPDX-License-Identifier: GPL-2.0
/* Huawei Hifc PCI Express Linux driver
* Copyright(c) 2017 Huawei Technologies Co., Ltd
*
*/
#include "hifc_utils.h"
#include "unf_log.h"
#include "unf_common.h"
void hifc_cpu_to_big64(void *v_addr, unsigned int size)
{
unsigned int index = 0;
unsigned int cnt = 0;
unsigned long long *temp = NULL;
UNF_CHECK_VALID(INVALID_VALUE32, UNF_TRUE,
v_addr, dump_stack(); return);
UNF_CHECK_VALID(INVALID_VALUE32, UNF_TRUE,
(size % HIFC_QWORD_BYTE) == 0, dump_stack(); return);
temp = (unsigned long long *)v_addr;
cnt = HIFC_SHIFT_TO_U64(size);
for (index = 0; index < cnt; index++) {
*temp = cpu_to_be64(*temp);
temp++;
}
}
void hifc_big_to_cpu64(void *v_addr, unsigned int size)
{
unsigned int index = 0;
unsigned int cnt = 0;
unsigned long long *tmp = NULL;
UNF_CHECK_VALID(INVALID_VALUE32, UNF_TRUE,
v_addr, dump_stack(); return);
UNF_CHECK_VALID(INVALID_VALUE32, UNF_TRUE,
(size % HIFC_QWORD_BYTE) == 0, dump_stack(); return);
tmp = (unsigned long long *)v_addr;
cnt = HIFC_SHIFT_TO_U64(size);
for (index = 0; index < cnt; index++) {
*tmp = be64_to_cpu(*tmp);
tmp++;
}
}
void hifc_cpu_to_big32(void *v_addr, unsigned int size)
{
unf_cpu_to_big_end(v_addr, size);
}
void hifc_big_to_cpu32(void *v_addr, unsigned int size)
{
if (size % UNF_BYTES_OF_DWORD)
dump_stack();
unf_big_end_to_cpu(v_addr, size);
}
unsigned int hifc_log2n(unsigned int val)
{
unsigned int result = 0;
unsigned int logn = (val >> 1);
while (logn) {
logn >>= 1;
result++;
}
return result;
}
/* SPDX-License-Identifier: GPL-2.0 */
/* Huawei Hifc PCI Express Linux driver
* Copyright(c) 2017 Huawei Technologies Co., Ltd
*
*/
#ifndef __HIFC_UTILS_H__
#define __HIFC_UTILS_H__
#define UNF_ZERO 0
#define HIFC_BIT(n) (0x1UL << (n))
#define HIFC_BIT_0 HIFC_BIT(0)
#define HIFC_BIT_1 HIFC_BIT(1)
#define HIFC_BIT_2 HIFC_BIT(2)
#define HIFC_BIT_3 HIFC_BIT(3)
#define HIFC_BIT_4 HIFC_BIT(4)
#define HIFC_BIT_5 HIFC_BIT(5)
#define HIFC_BIT_6 HIFC_BIT(6)
#define HIFC_BIT_7 HIFC_BIT(7)
#define HIFC_BIT_8 HIFC_BIT(8)
#define HIFC_BIT_9 HIFC_BIT(9)
#define HIFC_BIT_10 HIFC_BIT(10)
#define HIFC_BIT_11 HIFC_BIT(11)
#define HIFC_BIT_12 HIFC_BIT(12)
#define HIFC_BIT_13 HIFC_BIT(13)
#define HIFC_BIT_14 HIFC_BIT(14)
#define HIFC_BIT_15 HIFC_BIT(15)
#define HIFC_BIT_16 HIFC_BIT(16)
#define HIFC_BIT_17 HIFC_BIT(17)
#define HIFC_BIT_18 HIFC_BIT(18)
#define HIFC_BIT_19 HIFC_BIT(19)
#define HIFC_BIT_20 HIFC_BIT(20)
#define HIFC_BIT_21 HIFC_BIT(21)
#define HIFC_BIT_22 HIFC_BIT(22)
#define HIFC_BIT_23 HIFC_BIT(23)
#define HIFC_BIT_24 HIFC_BIT(24)
#define HIFC_BIT_25 HIFC_BIT(25)
#define HIFC_BIT_26 HIFC_BIT(26)
#define HIFC_BIT_27 HIFC_BIT(27)
#define HIFC_BIT_28 HIFC_BIT(28)
#define HIFC_BIT_29 HIFC_BIT(29)
#define HIFC_BIT_30 HIFC_BIT(30)
#define HIFC_BIT_31 HIFC_BIT(31)
#define HIFC_GET_BITS(data, mask) ((data) & (mask)) /* Obtains the bit */
#define HIFC_SET_BITS(data, mask) ((data) |= (mask)) /* set the bit */
#define HIFC_CLR_BITS(data, mask) ((data) &= ~(mask)) /* clear the bit */
/* Byte alignment */
#define HIFC_ALIGN_N(n) __attribute__((__packed, __aligned(n)))
#define HIFC_ALIGN_1 HIFC_ALIGN_N(1)
#define HIFC_ALIGN_2 HIFC_ALIGN_N(2)
#define HIFC_ALIGN_4 HIFC_ALIGN_N(4)
#define HIFC_ALIGN_8 HIFC_ALIGN_N(8)
#define HIFC_ADJUST_ALIGN_4(n) ((n) - (n) % 4)
#define HIFC_LSB(x) ((unsigned char)(x))
#define HIFC_MSB(x) ((unsigned char)((unsigned short)(x) >> 8))
#define HIFC_LSW(x) ((unsigned short)(x))
#define HIFC_MSW(x) ((unsigned short)((unsigned int)(x) >> 16))
#define HIFC_LSD(x) ((unsigned int)((unsigned long long)(x)))
#define HIFC_MSD(x) ((unsigned int)((((unsigned long long)(x)) >> 16) >> 16))
#define HIFC_BYTES_TO_QW_NUM(x) ((x) >> 3)
#define HIFC_BYTES_TO_DW_NUM(x) ((x) >> 2)
#define UNF_GET_SHIFTMASK(__src, __shift, __mask) \
(((__src) & (__mask)) >> (__shift))
#define UNF_FC_SET_SHIFTMASK(__des, __val, __shift, __mask)\
((__des) = \
(((__des) & ~(__mask)) | (((__val) << (__shift)) & (__mask))))
/* D_ID */
#define UNF_FC_HEADER_DID_MASK 0x00FFFFFF
#define UNF_FC_HEADER_DID_SHIFT 0
#define UNF_FC_HEADER_DID_DWORD 0
#define UNF_GET_FC_HEADER_DID(__pfcheader)\
UNF_GET_SHIFTMASK(\
((unsigned int *)(void *)__pfcheader)[UNF_FC_HEADER_DID_DWORD],\
UNF_FC_HEADER_DID_SHIFT, UNF_FC_HEADER_DID_MASK)
#define UNF_SET_FC_HEADER_DID(__pfcheader, __val)\
UNF_FC_SET_SHIFTMASK(\
((unsigned int *)(void *)__pfcheader)[UNF_FC_HEADER_DID_DWORD],\
__val, UNF_FC_HEADER_DID_SHIFT, UNF_FC_HEADER_DID_MASK)
/* R_CTL */
#define UNF_FC_HEADER_RCTL_MASK 0xFF000000
#define UNF_FC_HEADER_RCTL_SHIFT 24
#define UNF_FC_HEADER_RCTL_DWORD 0
#define UNF_GET_FC_HEADER_RCTL(__pfcheader)\
UNF_GET_SHIFTMASK(\
((unsigned int *)(void *)__pfcheader)[UNF_FC_HEADER_RCTL_DWORD],\
UNF_FC_HEADER_RCTL_SHIFT, UNF_FC_HEADER_RCTL_MASK)
#define UNF_SET_FC_HEADER_RCTL(__pfcheader, __val)\
UNF_FC_SET_SHIFTMASK(\
((unsigned int *)(void *)__pfcheader)[UNF_FC_HEADER_RCTL_DWORD],\
__val, UNF_FC_HEADER_RCTL_SHIFT, UNF_FC_HEADER_RCTL_MASK)
/* S_ID */
#define UNF_FC_HEADER_SID_MASK 0x00FFFFFF
#define UNF_FC_HEADER_SID_SHIFT 0
#define UNF_FC_HEADER_SID_DWORD 1
#define UNF_GET_FC_HEADER_SID(__pfcheader)\
UNF_GET_SHIFTMASK(\
((unsigned int *)(void *)__pfcheader)[UNF_FC_HEADER_SID_DWORD],\
UNF_FC_HEADER_SID_SHIFT, UNF_FC_HEADER_SID_MASK)
#define UNF_SET_FC_HEADER_SID(__pfcheader, __val)\
UNF_FC_SET_SHIFTMASK(\
((unsigned int *)(void *)__pfcheader)[UNF_FC_HEADER_SID_DWORD],\
__val, UNF_FC_HEADER_SID_SHIFT, UNF_FC_HEADER_SID_MASK)
/* CS_CTL */
#define UNF_FC_HEADER_CS_CTL_MASK 0xFF000000
#define UNF_FC_HEADER_CS_CTL_SHIFT 24
#define UNF_FC_HEADER_CS_CTL_DWORD 1
#define UNF_GET_FC_HEADER_CS_CTL(__pfcheader)\
UNF_GET_SHIFTMASK(\
((unsigned int *)(void *)__pfcheader)[UNF_FC_HEADER_CS_CTL_DWORD],\
UNF_FC_HEADER_CS_CTL_SHIFT, UNF_FC_HEADER_CS_CTL_MASK)
#define UNF_SET_FC_HEADER_CS_CTL(__pfcheader, __val)\
UNF_FC_SET_SHIFTMASK(\
((unsigned int *)(void *)__pfcheader)[UNF_FC_HEADER_CS_CTL_DWORD],\
__val, UNF_FC_HEADER_CS_CTL_SHIFT, UNF_FC_HEADER_CS_CTL_MASK)
/* F_CTL */
#define UNF_FC_HEADER_FCTL_MASK 0x00FFFFFF
#define UNF_FC_HEADER_FCTL_SHIFT 0
#define UNF_FC_HEADER_FCTL_DWORD 2
#define UNF_GET_FC_HEADER_FCTL(__pfcheader)\
UNF_GET_SHIFTMASK(\
((unsigned int *)(void *)__pfcheader)[UNF_FC_HEADER_FCTL_DWORD],\
UNF_FC_HEADER_FCTL_SHIFT, UNF_FC_HEADER_FCTL_MASK)
#define UNF_SET_FC_HEADER_FCTL(__pfcheader, __val)\
UNF_FC_SET_SHIFTMASK(\
((unsigned int *)(void *)__pfcheader)[UNF_FC_HEADER_FCTL_DWORD],\
__val, UNF_FC_HEADER_FCTL_SHIFT, UNF_FC_HEADER_FCTL_MASK)
/* TYPE */
#define UNF_FC_HEADER_TYPE_MASK 0xFF000000
#define UNF_FC_HEADER_TYPE_SHIFT 24
#define UNF_FC_HEADER_TYPE_DWORD 2
#define UNF_GET_FC_HEADER_TYPE(__pfcheader)\
UNF_GET_SHIFTMASK(\
((unsigned int *)(void *)__pfcheader)[UNF_FC_HEADER_TYPE_DWORD],\
UNF_FC_HEADER_TYPE_SHIFT, UNF_FC_HEADER_TYPE_MASK)
#define UNF_SET_FC_HEADER_TYPE(__pfcheader, __val)\
UNF_FC_SET_SHIFTMASK(\
((unsigned int *)(void *)__pfcheader)[UNF_FC_HEADER_TYPE_DWORD],\
__val, UNF_FC_HEADER_TYPE_SHIFT, UNF_FC_HEADER_TYPE_MASK)
/* SEQ_CNT */
#define UNF_FC_HEADER_SEQ_CNT_MASK 0x0000FFFF
#define UNF_FC_HEADER_SEQ_CNT_SHIFT 0
#define UNF_FC_HEADER_SEQ_CNT_DWORD 3
#define UNF_GET_FC_HEADER_SEQ_CNT(__pfcheader)\
UNF_GET_SHIFTMASK(\
((unsigned int *)(void *)__pfcheader)[UNF_FC_HEADER_SEQ_CNT_DWORD],\
UNF_FC_HEADER_SEQ_CNT_SHIFT, UNF_FC_HEADER_SEQ_CNT_MASK)
#define UNF_SET_FC_HEADER_SEQ_CNT(__pfcheader, __val)\
UNF_FC_SET_SHIFTMASK(\
((unsigned int *)(void *)__pfcheader)[UNF_FC_HEADER_SEQ_CNT_DWORD],\
__val, UNF_FC_HEADER_SEQ_CNT_SHIFT, UNF_FC_HEADER_SEQ_CNT_MASK)
/* DF_CTL */
#define UNF_FC_HEADER_DF_CTL_MASK 0x00FF0000
#define UNF_FC_HEADER_DF_CTL_SHIFT 16
#define UNF_FC_HEADER_DF_CTL_DWORD 3
#define UNF_GET_FC_HEADER_DF_CTL(__pfcheader)\
UNF_GET_SHIFTMASK(\
((unsigned int *)(void *)__pfcheader)[UNF_FC_HEADER_DF_CTL_DWORD],\
UNF_FC_HEADER_DF_CTL_SHIFT, UNF_FC_HEADER_DF_CTL_MASK)
#define UNF_SET_FC_HEADER_DF_CTL(__pfcheader, __val)\
UNF_FC_SET_SHIFTMASK(\
((unsigned int *)(void *)__pfcheader)[UNF_FC_HEADER_DF_CTL_DWORD],\
__val, UNF_FC_HEADER_DF_CTL_SHIFT, UNF_FC_HEADER_DF_CTL_MASK)
/* SEQ_ID */
#define UNF_FC_HEADER_SEQ_ID_MASK 0xFF000000
#define UNF_FC_HEADER_SEQ_ID_SHIFT 24
#define UNF_FC_HEADER_SEQ_ID_DWORD 3
#define UNF_GET_FC_HEADER_SEQ_ID(__pfcheader)\
UNF_GET_SHIFTMASK(\
((unsigned int *)(void *)__pfcheader)[UNF_FC_HEADER_SEQ_ID_DWORD],\
UNF_FC_HEADER_SEQ_ID_SHIFT, UNF_FC_HEADER_SEQ_ID_MASK)
#define UNF_SET_FC_HEADER_SEQ_ID(__pfcheader, __val)\
UNF_FC_SET_SHIFTMASK(\
((unsigned int *)(void *)__pfcheader)[UNF_FC_HEADER_SEQ_ID_DWORD],\
__val, UNF_FC_HEADER_SEQ_ID_SHIFT, UNF_FC_HEADER_SEQ_ID_MASK)
/* RX_ID */
#define UNF_FC_HEADER_RXID_MASK 0x0000FFFF
#define UNF_FC_HEADER_RXID_SHIFT 0
#define UNF_FC_HEADER_RXID_DWORD 4
#define UNF_GET_FC_HEADER_RXID(__pfcheader)\
UNF_GET_SHIFTMASK(\
((unsigned int *)(void *)__pfcheader)[UNF_FC_HEADER_RXID_DWORD],\
UNF_FC_HEADER_RXID_SHIFT, UNF_FC_HEADER_RXID_MASK)
#define UNF_SET_FC_HEADER_RXID(__pfcheader, __val)\
UNF_FC_SET_SHIFTMASK(\
((unsigned int *)(void *)__pfcheader)[UNF_FC_HEADER_RXID_DWORD],\
__val, UNF_FC_HEADER_RXID_SHIFT, UNF_FC_HEADER_RXID_MASK)
/* OX_ID */
#define UNF_FC_HEADER_OXID_MASK 0xFFFF0000
#define UNF_FC_HEADER_OXID_SHIFT 16
#define UNF_FC_HEADER_OXID_DWORD 4
#define UNF_GET_FC_HEADER_OXID(__pfcheader)\
((unsigned short)UNF_GET_SHIFTMASK(\
((unsigned int *)(void *)__pfcheader)[UNF_FC_HEADER_OXID_DWORD],\
UNF_FC_HEADER_OXID_SHIFT\
, UNF_FC_HEADER_OXID_MASK))
#define UNF_SET_FC_HEADER_OXID(__pfcheader, __val)\
(UNF_FC_SET_SHIFTMASK(\
((unsigned int *)(void *)__pfcheader)[UNF_FC_HEADER_OXID_DWORD],\
__val, UNF_FC_HEADER_OXID_SHIFT, UNF_FC_HEADER_OXID_MASK))
/* PRLI PARAM 3 */
#define HIFC_PRLI_PARAM_WXFER_ENABLE_MASK 0x00000001
#define HIFC_PRLI_PARAM_WXFER_ENABLE_SHIFT 0
#define HIFC_PRLI_PARAM_WXFER_DWORD 3
#define HIFC_GET_PRLI_PARAM_WXFER(__pfcheader)\
UNF_GET_SHIFTMASK(\
((unsigned int *)(void *)(__pfcheader))[HIFC_PRLI_PARAM_WXFER_DWORD],\
HIFC_PRLI_PARAM_WXFER_ENABLE_SHIFT, HIFC_PRLI_PARAM_WXFER_ENABLE_MASK)
#define HIFC_PRLI_PARAM_CONF_ENABLE_MASK 0x00000080
#define HIFC_PRLI_PARAM_CONF_ENABLE_SHIFT 7
#define HIFC_PRLI_PARAM_CONF_DWORD 3
#define HIFC_GET_PRLI_PARAM_CONF(__pfcheader)\
UNF_GET_SHIFTMASK(\
((unsigned int *)(void *)(__pfcheader))[HIFC_PRLI_PARAM_CONF_DWORD],\
HIFC_PRLI_PARAM_CONF_ENABLE_SHIFT, HIFC_PRLI_PARAM_CONF_ENABLE_MASK)
#define HIFC_PRLI_PARAM_REC_ENABLE_MASK 0x00000400
#define HIFC_PRLI_PARAM_REC_ENABLE_SHIFT 10
#define HIFC_PRLI_PARAM_CONF_REC 3
#define HIFC_GET_PRLI_PARAM_REC(__pfcheader)\
UNF_GET_SHIFTMASK(\
((unsigned int *)(void *)(__pfcheader))[HIFC_PRLI_PARAM_CONF_REC],\
HIFC_PRLI_PARAM_REC_ENABLE_SHIFT, HIFC_PRLI_PARAM_REC_ENABLE_MASK)
#define HIFC_WQE_TYPE_MASK 0x000000FF
#define HIFC_WQE_TYPE_SHIFT 0
#define HIFC_WQE_TYPE_DWORD 0
#define HIFC_GET_WQE_TYPE_BE(__pfcheader)\
UNF_GET_SHIFTMASK(\
((unsigned int *)(void *)__pfcheader)[HIFC_WQE_TYPE_DWORD],\
HIFC_WQE_TYPE_SHIFT, HIFC_WQE_TYPE_MASK)
#define HIFC_MAKE_64BIT_ADDR(__high32, __low32) \
(unsigned long long)(((unsigned long long)(__high32) << 32) |\
(unsigned long long)(__low32))
#define HIFC_TRACE(log_id, log_att, log_level, fmt, ...) \
UNF_TRACE(log_id, log_att, log_level, fmt, ##__VA_ARGS__)
/* Valid check */
#define HIFC_CHECK(log_id, condition, fail_do) \
do { \
if (unlikely(!(condition))) { \
HIFC_TRACE((log_id), UNF_LOG_IO_ATT, UNF_ERR, \
"[err]Function:%s parameter check[%s] invalid",\
__func__, #condition); \
fail_do; \
} \
} while (0)
#define PRINT_IN_MBOX(dbg_level, data, count) \
do { \
unsigned int index = 0; \
if ((dbg_level) <= unf_dbg_level) { \
printk("HIFC send inbound mailbox: "); \
for (index = 0; index < (count) / 4; index++) { \
printk("%08x ", \
(((unsigned int *)(data))[index]));\
} \
printk("\n"); \
} \
} while (0)
#define PRINT_OUT_MBOX(dbg_level, data, count) \
do { \
unsigned int index = 0; \
if ((dbg_level) <= unf_dbg_level) { \
printk("HIFC receive outbound mailbox: "); \
for (index = 0; index < (count) / 4; index++) { \
printk("%08x ",\
(((unsigned int *)(data))[index]));\
} \
printk("\n"); \
} \
} while (0)
#define PRINT_INBOUND_IOB(dbg_level, data, count) \
do { \
unsigned int index = 0; \
if ((dbg_level) <= unf_dbg_level) { \
printk("HIFC send inbound iob: "); \
for (index = 0; index < (count) / 4; index++) { \
printk("%08x ",\
(((unsigned int *)(data))[index]));\
} \
printk("\n"); \
} \
} while (0)
#define PRINT_OUTBOUND_IOB(dbg_level, data, count) \
do { \
unsigned int index = 0; \
if ((dbg_level) <= unf_dbg_level) { \
printk("HIFC receive outbound iob: "); \
for (index = 0; index < (count) / 4; index++) { \
printk("%08x ",\
(((unsigned int *)(data))[index]));\
} \
printk("\n"); \
} \
} while (0)
#define HIFC_REFERNCE_VAR(ref, cmp, ret)
#define RETURN_ERROR_S32 (-1)
#define UNF_RETURN_ERROR_S32 (-1)
enum HIFC_HBA_ERR_STAT_E {
HIFC_STAT_CTXT_FLUSH_DONE = 0,
HIFC_STAT_SQ_WAIT_EMPTY,
HIFC_STAT_LAST_GS_SCQE,
HIFC_STAT_SQ_POOL_EMPTY,
HIFC_STAT_PARENT_IO_FLUSHED,
HIFC_STAT_ROOT_IO_FLUSHED, /* 5 */
HIFC_STAT_ROOT_SQ_FULL,
HIFC_STAT_ELS_RSP_EXCH_REUSE,
HIFC_STAT_GS_RSP_EXCH_REUSE,
HIFC_STAT_SQ_IO_BUFFER_CLEARED,
HIFC_STAT_PARENT_SQ_NOT_OFFLOADED, /* 10 */
HIFC_STAT_PARENT_SQ_QUEUE_DELAYED_WORK,
HIFC_STAT_PARENT_SQ_INVALID_CACHED_ID,
HIFC_HBA_STAT_BUTT
};
#define HIFC_DWORD_BYTE 4
#define HIFC_QWORD_BYTE 8
#define HIFC_SHIFT_TO_U64(x) ((x) >> 3)
#define HIFC_SHIFT_TO_U32(x) ((x) >> 2)
void hifc_cpu_to_big64(void *v_addr, unsigned int size);
void hifc_big_to_cpu64(void *v_addr, unsigned int size);
void hifc_cpu_to_big32(void *v_addr, unsigned int size);
void hifc_big_to_cpu32(void *v_addr, unsigned int size);
unsigned int hifc_log2n(unsigned int val);
#endif /* __HIFC_UTILS_H__ */
/* SPDX-License-Identifier: GPL-2.0 */
/* Huawei Hifc PCI Express Linux driver
* Copyright(c) 2017 Huawei Technologies Co., Ltd
*
*/
#ifndef __UNF_COMMON_H
#define __UNF_COMMON_H
#include "unf_scsi_common.h"
/* V/C version number */
#define UNF_MAJOR_VERSION "3"
/* B version, B0XX Corresponding x.x */
#define UNF_B_VERSION "5.0"
/* Indicates the minor version number of the driver */
#define UNF_DRIVER_VERSION "8"
/* version num */
#define UNF_FC_VERSION UNF_MAJOR_VERSION "." UNF_B_VERSION "." UNF_DRIVER_VERSION
extern unsigned int unf_dbg_level;
extern unsigned int hifc_dif_type;
extern unsigned int hifc_dif_enable;
extern unsigned char hifc_guard;
#define RETURN_ERROR_S32 (-1)
#define UNF_RETURN_ERROR_S32 (-1)
#define UNF_IO_SUCCESS 0x00000000
/* the host system aborted the command */
#define UNF_IO_ABORTED 0x00000001
#define UNF_IO_FAILED 0x00000002
#define UNF_IO_ABORT_ABTS 0x00000003
#define UNF_IO_ABORT_LOGIN 0x00000004 /* abort login */
/* reset event aborted the transport */
#define UNF_IO_ABORT_REET 0x00000005
#define UNF_IO_ABORT_FAILED 0x00000006 /* abort failed */
/* data out of order ,data reassembly error */
#define UNF_IO_OUTOF_ORDER 0x00000007
#define UNF_IO_FTO 0x00000008 /* frame time out */
#define UNF_IO_LINK_FAILURE 0x00000009
#define UNF_IO_OVER_FLOW 0x0000000a /* data over run */
#define UNF_IO_RSP_OVER 0x0000000b
#define UNF_IO_LOST_FRAME 0x0000000c
#define UNF_IO_UNDER_FLOW 0x0000000d /* data under run */
#define UNF_IO_HOST_PROG_ERROR 0x0000000e
#define UNF_IO_SEST_PROG_ERROR 0x0000000f
#define UNF_IO_INVALID_ENTRY 0x00000010
#define UNF_IO_ABORT_SEQ_NOT 0x00000011
#define UNF_IO_REJECT 0x00000012
#define UNF_IO_RS_INFO 0x00000013
#define UNF_IO_EDC_IN_ERROR 0x00000014
#define UNF_IO_EDC_OUT_ERROR 0x00000015
#define UNF_IO_UNINIT_KEK_ERR 0x00000016
#define UNF_IO_DEK_OUTOF_RANGE 0x00000017
#define UNF_IO_KEY_UNWRAP_ERR 0x00000018
#define UNF_IO_KEY_TAG_ERR 0x00000019
#define UNF_IO_KEY_ECC_ERR 0x0000001a
#define UNF_IO_BLOCK_SIZE_ERROR 0x0000001b
#define UNF_IO_ILLEGAL_CIPHER_MODE 0x0000001c
#define UNF_IO_CLEAN_UP 0x0000001d
#define UNF_SRR_RECEIVE 0x0000001e /* receive srr */
/* The target device sent an ABTS to abort the I/O. */
#define UNF_IO_ABORTED_BY_TARGET 0x0000001f
#define UNF_IO_TRANSPORT_ERROR 0x00000020
#define UNF_IO_LINK_FLASH 0x00000021
#define UNF_IO_TIMEOUT 0x00000022
#define UNF_IO_PORT_UNAVAILABLE 0x00000023
#define UNF_IO_PORT_LOGOUT 0x00000024
#define UNF_IO_PORT_CFG_CHG 0x00000025
#define UNF_IO_FIRMWARE_RES_UNAVAILABLE 0x00000026
#define UNF_IO_TASK_MGT_OVERRUN 0x00000027
#define UNF_IO_DMA_ERROR 0x00000028
#define UNF_IO_DIF_ERROR 0x00000029
#define UNF_IO_NO_LPORT 0x0000002a
#define UNF_IO_NO_XCHG 0x0000002b
#define UNF_IO_SOFT_ERR 0x0000002c
#define UNF_IO_XCHG_ADD_ERROR 0x0000002d
#define UNF_IO_NO_LOGIN 0x0000002e
#define UNF_IO_NO_BUFFER 0x0000002f
#define UNF_IO_DID_ERROR 0x00000030
#define UNF_IO_UNSUPPORT 0x00000031
#define UNF_IO_NOREADY 0x00000032
#define UNF_IO_NPORTID_REUSED 0x00000033
#define UNF_IO_NPORT_HANDLE_REUSED 0x00000034
#define UNF_IO_NO_NPORT_HANDLE 0x00000035
#define UNF_IO_ABORT_BY_FW 0x00000036
#define UNF_IO_ABORT_PORT_REMOVING 0x00000037
#define UNF_IO_INCOMPLETE 0x00000038
#define UNF_IO_DIF_REF_ERROR 0x00000039
#define UNF_IO_DIF_GEN_ERROR 0x0000003a
#define UNF_IO_ERREND 0xFFFFFFFF
/* define bits */
#define UNF_BIT(n) (0x1UL << (n))
#define UNF_BIT_0 UNF_BIT(0)
#define UNF_BIT_1 UNF_BIT(1)
#define UNF_BIT_2 UNF_BIT(2)
#define UNF_BIT_3 UNF_BIT(3)
#define UNF_BIT_4 UNF_BIT(4)
#define UNF_BIT_5 UNF_BIT(5)
struct buff_list_s {
u8 *vaddr;
dma_addr_t paddr;
};
struct buf_describe_s {
struct buff_list_s *buflist;
u32 buf_size;
u32 buf_num;
};
#define BUF_LIST_PAGE_SIZE (PAGE_SIZE << 8)
/* Echo macro define */
#define ECHO_MG_VERSION_LOCAL 1
#define ECHO_MG_VERSION_REMOTE 2
/* save hba info macro define */
#define SAVE_PORT_INFO_LEN 1016
#define UNF_GET_NAME_HIGH_WORD(v_name) \
(((v_name) >> 32) & 0xffffffff)
#define UNF_GET_NAME_LOW_WORD(v_name) \
((v_name) & 0xffffffff)
#define UNF_FIRST_LPORT_ID_MASK 0xffffff00
#define HIFC_MAX_COUNTER_TYPE 128
#define UNF_EVENT_ASYN 0
#define UNF_EVENT_SYN 1
#define UNF_GLOBAL_EVENT_ASYN 2
#define UNF_GLOBAL_EVENT_SYN 3
/* define sfp err */
#define UNF_SFP_PRESENT_FAIL 0x1
#define UNF_SFP_POWER_FAIL 0x2
#define UNF_9545_FAIL 0x3
/* obtain the values of board type and ID */
#define UNF_GET_BOARD_TYPE_AND_SLOT_ID_BY_PORTID(port_id) \
(((port_id) & 0x00FF00) >> 8)
#define UNF_FC_SERVER_BOARD_8_G 13 /* 8G mode */
#define UNF_FC_SERVER_BOARD_16_G 7 /* 16G mode */
#define UNF_FC_SERVER_BOARD_32_G 6 /* 32G mode */
#define UNF_PORT_TYPE_FC_QSFP 1
#define UNF_PORT_TYPE_FC_SFP 0
#define UNF_PORT_UNGRADE_FW_RESET_ACTIVE 0
#define UNF_PORT_UNGRADE_FW_RESET_INACTIVE 1
#ifndef __BIG_ENDIAN__
#define __BIG_ENDIAN__ 0x4321
#endif
#ifndef __LITTLE_ENDIAN__
#define __LITTLE_ENDIAN__ 0x1234
#endif
#ifdef __BYTE_ORDER__
#undef __BYTE_ORDER__
#endif
#define __BYTE_ORDER__ __LITTLE_ENDIAN__
#ifndef INVALID_VALUE64
#define INVALID_VALUE64 0xFFFFFFFFFFFFFFFFULL
#endif /* INVALID_VALUE64 */
#ifndef INVALID_VALUE32
#define INVALID_VALUE32 0xFFFFFFFF
#endif /* INVALID_VALUE32 */
#ifndef INVALID_VALUE16
#define INVALID_VALUE16 0xFFFF
#endif /* INVALID_VALUE16 */
#ifndef INVALID_VALUE8
#define INVALID_VALUE8 0xFF
#endif /* INVALID_VALUE8 */
#ifndef RETURN_OK
#define RETURN_OK 0
#endif
#ifndef RETURN_ERROR
#define RETURN_ERROR (~0)
#endif
#define UNF_RETURN_ERROR (~0)
#ifndef UNF_RETURN_NOT_SUPPORT
#define UNF_RETURN_NOT_SUPPORT (2)
#endif
enum int_e {
UNF_FALSE = 0,
UNF_TRUE = 1
};
#define DRV_DIF_CRC_ERR 0x1001
#define DRV_DIF_LBA_ERR 0x1002
#define DRV_DIF_APP_ERR 0x1003
#define UNF_SCSI_SENSE_DATA_LEN SCSI_SENSE_DATA_LEN
/* RPort Management information related to Rport,
* only used at the boundary between common and lowlevel
*/
struct unf_rport_info_s {
unsigned int local_nport_id;
unsigned int nport_id;
unsigned int rport_index;
unsigned long long port_name;
unsigned char rsvd0[3];
};
struct unf_cfg_item_s {
char *name;
unsigned int min_value;
unsigned int default_value;
unsigned int max_value;
};
struct unf_port_params_s {
unsigned int ra_tov;
unsigned int ed_tov;
};
/* get wwpn adn wwnn */
struct unf_get_chip_info_argout {
unsigned char board_type;
unsigned long long wwpn;
unsigned long long wwnn;
unsigned long long sys_mac;
};
/* get sfp info: present and speed */
struct unf_get_port_info_argout {
unsigned char sfp_speed;
unsigned char present;
unsigned char rsvd[2];
};
/* SFF-8436(QSFP+) Rev 4.7 */
struct sfp_plus_field_a0_s {
unsigned char identifier;
/* offset 1~2 */
struct {
unsigned char reserved;
unsigned char status;
} status_indicator;
/* offset 3~21 */
struct {
unsigned char rx_tx_los;
unsigned char tx_fault;
unsigned char all_resv;
unsigned char ini_complete : 1;
unsigned char bit_resv : 3;
unsigned char temp_low_warn : 1;
unsigned char temp_high_warn : 1;
unsigned char temp_low_alarm : 1;
unsigned char temp_high_alarm : 1;
unsigned char resv : 4;
unsigned char vcc_low_warn : 1;
unsigned char vcc_high_warn : 1;
unsigned char vcc_low_alarm : 1;
unsigned char vcc_high_alarm : 1;
unsigned char resv8;
unsigned char rx_pow[2];
unsigned char tx_bias[2];
unsigned char reserved[6];
unsigned char vendor_specifics[3];
} interrupt_flag;
/* offset 22~33 */
struct {
unsigned char temp[2];
unsigned char reserved[2];
unsigned char supply_vol[2];
unsigned char reserveds[2];
unsigned char vendor_specific[4];
} module_monitors;
/* offset 34~81 */
struct {
unsigned char rx_pow[8];
unsigned char tx_bias[8];
unsigned char reserved[16];
unsigned char vendor_specific[16];
} channel_monitor_val;
/* offset 82~85 */
unsigned char reserved[4];
/* offset 86~97 */
struct {
/* 86~88 */
unsigned char tx_disable;
unsigned char rx_rate_select;
unsigned char tx_rate_select;
/* 89~92 */
unsigned char rx_4_app_select;
unsigned char rx_3_app_select;
unsigned char rx_2_app_select;
unsigned char rx_1_app_select;
/* 93 */
unsigned char power_override : 1;
unsigned char power_set : 1;
unsigned char reserved : 6;
/* 94~97 */
unsigned char tx_4_app_select;
unsigned char tx_3_app_select;
unsigned char tx_2_app_select;
unsigned char tx_1_app_select;
/* 98~99 */
unsigned char auc_reserved[2];
} control;
/* 100~106 */
struct {
/* 100 */
unsigned char mrx_1_os : 1;
unsigned char mrx_2_los : 1;
unsigned char mrx_3_los : 1;
unsigned char mrx_4_los : 1;
unsigned char mtx_1_los : 1;
unsigned char mtx_2_los : 1;
unsigned char mtx_3_los : 1;
unsigned char mtx_4_los : 1;
/* 101 */
unsigned char mtx_1_fault : 1;
unsigned char mtx_2_fault : 1;
unsigned char mtx_3_fault : 1;
unsigned char mtx_4_fault : 1;
unsigned char reserved : 4;
/* 102 */
unsigned char uc_reserved;
/* 103 */
unsigned char mini_cmp_flag : 1;
unsigned char rsv : 3;
unsigned char mtemp_low_warn : 1;
unsigned char mtemp_high_warn : 1;
unsigned char mtemp_low_alarm : 1;
unsigned char mtemp_high_alarm : 1;
/* 104 */
unsigned char rsv1 : 4;
unsigned char mvcc_low_warn : 1;
unsigned char mvcc_high_warn : 1;
unsigned char mvcc_low_alarm : 1;
unsigned char mvcc_high_alarm : 1;
/* 105~106 */
unsigned char vendor_specific[2];
} module_channel_mask_bit;
/* 107~118 */
unsigned char auc_resv[12];
/* 119~126 */
unsigned char auc_reserved[8];
/* 127 */
unsigned char page_select;
};
/* page 00 */
struct sfp_plus_field_00_s {
/* 128~191 */
struct {
unsigned char id;
unsigned char id_ext;
unsigned char connector;
unsigned char speci_com[6];
unsigned char mode;
unsigned char speed;
unsigned char encoding;
unsigned char br_nominal;
unsigned char ext_rate_select_com;
unsigned char length_smf;
unsigned char length_om3;
unsigned char length_om2;
unsigned char length_om1;
unsigned char length_copper;
unsigned char device_tech;
unsigned char vendor_name[16];
unsigned char ex_module;
unsigned char vendor_oui[3];
unsigned char vendor_pn[16];
unsigned char vendor_rev[2];
/* Wave length or Copper cable Attenuation */
unsigned char wave_or_copper_attenuation[2];
unsigned char wave_length_toler[2]; /* Wavelength tolerance */
unsigned char max_temp;
unsigned char cc_base;
} base_id_fields;
/* 192~223 */
struct {
unsigned char options[4];
unsigned char vendor_sn[16];
unsigned char date_code[8];
unsigned char diagn_monit_type;
unsigned char enhance_opt;
unsigned char uc_reserved;
unsigned char ccext;
} ext_id_fields;
/* 224~255 */
unsigned char vendor_spec_eeprom[32];
};
/* page 01 */
struct sfp_field_01_s {
unsigned char optiona_l01[128];
};
/* page 02 */
struct sfp_field_02_s {
unsigned char optiona_l02[128];
};
/* page 03 */
struct sfp_field_03_s {
unsigned char temp_high_alarm[2];
unsigned char temp_low_alarm[2];
unsigned char temp_high_warn[2];
unsigned char temp_low_warn[2];
unsigned char reserved1[8];
unsigned char vcc_high_alarm[2];
unsigned char vcc_low_alarm[2];
unsigned char vcc_high_warn[2];
unsigned char vcc_low_warn[2];
unsigned char reserved2[8];
unsigned char vendor_specific1[16];
unsigned char pow_high_alarm[2];
unsigned char pow_low_alarm[2];
unsigned char pow_high_warn[2];
unsigned char pow_low_warn[2];
unsigned char bias_high_alarm[2];
unsigned char bias_low_alarm[2];
unsigned char bias_high_warn[2];
unsigned char bias_low_warn[2];
unsigned char tx_power_high_alarm[2];
unsigned char tx_power_low_alarm[2];
unsigned char reserved3[4];
unsigned char reserved4[8];
unsigned char vendor_specific2[16];
unsigned char reserved5[2];
unsigned char vendor_specific3[12];
unsigned char rx_ampl[2];
unsigned char rx_tx_sq_disable;
unsigned char rx_output_disable;
unsigned char chan_monit_mask[12];
unsigned char reserved6[2];
};
struct sfp_plus_info_s {
struct sfp_plus_field_a0_s sfp_plus_info_a0;
struct sfp_plus_field_00_s sfp_plus_info_00;
struct sfp_field_01_s sfp_plus_info_01;
struct sfp_field_02_s sfp_plus_info_02;
struct sfp_field_03_s sfp_plus_info_03;
};
/* SFF-8472 Rev 10.4 */
struct unf_sfp_data_field_a0_s {
/* Offset 0~63 */
struct {
unsigned char id;
unsigned char id_ext;
unsigned char connector;
unsigned char atransceiver[8];
unsigned char encoding;
/* Nominal signalling rate, units of 100MBd. */
unsigned char br_nominal;
/* Type of rate select functionality */
unsigned char rate_identifier;
/* Link length supported for single mode fiber, units of km */
unsigned char length_smf_km;
/* Link length supported for single mode fiber,
* units of 100 m
*/
unsigned char length_smf;
/* Link length supported for 50 um OM2 fiber, units of 10 m */
unsigned char length_smf_om2;
/* Link length supported for 62.5 um OM1 fiber, units of 10 m */
unsigned char length_smf_om1;
/* Link length supported for copper or direct attach cable,
* units of m
*/
unsigned char length_cable;
/* Link length supported for 50 um OM3 fiber, units of 10 m */
unsigned char length_om3;
unsigned char vendor_name[16]; /* ASCII */
/* Code for electronic or optical compatibility */
unsigned char transceiver;
unsigned char vendor_oui[3]; /* SFP vendor IEEE company ID */
/* Part number provided by SFP vendor (ASCII) */
unsigned char vendor_pn[16];
/* Revision level for part number provided by vendor (ASCII) */
unsigned char vendor_rev[4];
/* Laser wavelength (Passive/Active Cable
* Specification Compliance)
*/
unsigned char wave_length[2];
unsigned char unallocated;
/* Check code for Base ID Fields (addresses 0 to 62) */
unsigned char cc_base;
} base_id_fields;
/* Offset 64~95 */
struct {
unsigned char options[2];
unsigned char br_max;
unsigned char br_min;
unsigned char vendor_sn[16];
unsigned char date_code[8];
unsigned char diag_monitoring_type;
unsigned char enhanced_options;
unsigned char sff8472_compliance;
unsigned char cc_ext;
} ext_id_fields;
/* Offset 96~255 */
struct {
unsigned char vendor_spec_eeprom[32];
unsigned char rsvd[128];
} vendor_spec_id_fields;
};
struct unf_sfp_data_field_a2_s {
/* Offset 0~119 */
struct {
/* 0~39 */
struct {
unsigned char temp_alarm_high[2];
unsigned char temp_alarm_low[2];
unsigned char temp_warning_high[2];
unsigned char temp_warning_low[2];
unsigned char vcc_alarm_high[2];
unsigned char vcc_alarm_low[2];
unsigned char vcc_warning_high[2];
unsigned char vcc_warning_low[2];
unsigned char bias_alarm_high[2];
unsigned char bias_alarm_low[2];
unsigned char bias_warning_high[2];
unsigned char bias_warning_low[2];
unsigned char tx_alarm_high[2];
unsigned char tx_alarm_low[2];
unsigned char tx_warning_high[2];
unsigned char tx_warning_low[2];
unsigned char rx_alarm_high[2];
unsigned char rx_alarm_low[2];
unsigned char rx_warning_high[2];
unsigned char rx_warning_low[2];
} alarm_warn_th;
unsigned char unallocated0[16];
unsigned char ext_cal_constants[36];
unsigned char unallocated1[3];
unsigned char cc_dmi;
/* 96~105 */
struct {
unsigned char temp[2];
unsigned char vcc[2];
unsigned char tx_bias[2];
unsigned char tx_power[2];
unsigned char rx_power[2];
} diag;
unsigned char unallocated2[4];
struct {
unsigned char data_rdy_bar_state : 1;
unsigned char rx_los : 1;
unsigned char tx_fault_state : 1;
unsigned char soft_rate_select_state : 1;
unsigned char rate_select_state : 1;
unsigned char rs_state : 1;
unsigned char soft_tx_disable_select : 1;
unsigned char tx_disable_state : 1;
} status_ctrl;
unsigned char rsvd;
/* 112~113 */
struct {
/* 112 */
unsigned char tx_alarm_low : 1;
unsigned char tx_alarm_high : 1;
unsigned char tx_bias_alarm_low : 1;
unsigned char tx_bias_alarm_high : 1;
unsigned char vcc_alarm_low : 1;
unsigned char vcc_alarm_high : 1;
unsigned char temp_alarm_low : 1;
unsigned char temp_alarm_high : 1;
/* 113 */
unsigned char rsvd : 6;
unsigned char rx_alarm_low : 1;
unsigned char rx_alarm_high : 1;
} alarm;
unsigned char unallocated3[2];
/* 116~117 */
struct {
/* 116 */
unsigned char tx_warn_lo : 1;
unsigned char tx_warn_hi : 1;
unsigned char bias_warn_lo : 1;
unsigned char bias_warn_hi : 1;
unsigned char vcc_warn_lo : 1;
unsigned char vcc_warn_hi : 1;
unsigned char temp_warn_lo : 1;
unsigned char temp_warn_hi : 1;
/* 117 */
unsigned char rsvd : 6;
unsigned char rx_warn_lo : 1;
unsigned char rx_warn_hi : 1;
} warning;
unsigned char ext_status_and_ctrl[2];
} diag;
/* Offset 120~255 */
struct {
unsigned char vendor_spec[8];
unsigned char user_eeprom[120];
unsigned char vendor_ctrl[8];
} general_use_fields;
};
struct unf_sfp_info_s {
struct unf_sfp_data_field_a0_s sfp_info_a0;
struct unf_sfp_data_field_a2_s sfp_info_a2;
};
union unf_sfp_eeprome_info {
struct unf_sfp_info_s sfp_info;
struct sfp_plus_info_s sfp_plus_info;
};
/* sfp info end */
struct unf_lport_sfp_info {
unsigned int status;
union unf_sfp_eeprome_info sfp_eeprom_info;
};
struct unf_err_code_s {
unsigned int loss_of_signal_count;
unsigned int bad_rx_char_count;
unsigned int loss_of_sync_count;
unsigned int link_fail_count;
unsigned int rx_eo_fa_count;
unsigned int dis_frame_count;
unsigned int bad_crc_count;
unsigned int proto_error_count;
};
/* config file */
enum unf_scsi_mode_e {
UNF_PORT_MODE_UNKNOWN = 0x00,
UNF_PORT_MODE_TGT = 0x10,
UNF_PORT_MODE_INI = 0x20,
UNF_PORT_MODE_BOTH = 0x30
};
enum unf_port_upgrade_e {
UNF_PORT_UNSUPPORT_UPGRADE_REPORT = 0x00,
UNF_PORT_SUPPORT_UPGRADE_REPORT = 0x01,
UNF_PORT_UPGRADE_BUTT
};
#define UNF_BYTES_OF_DWORD 0x4
static inline void __attribute__((unused)) unf_big_end_to_cpu(
unsigned char *v_buffer, unsigned int v_size)
{
unsigned int *buffer = NULL;
unsigned int word_sum = 0;
unsigned int i = 0;
if (!v_buffer)
return;
buffer = (unsigned int *)v_buffer;
/* byte to word */
if (v_size % UNF_BYTES_OF_DWORD == 0)
word_sum = v_size / UNF_BYTES_OF_DWORD;
else
return;
/* word to byte */
while (i < word_sum) {
*buffer = be32_to_cpu(*buffer);
buffer++;
i++;
}
}
static inline void __attribute__((unused)) unf_cpu_to_big_end(
void *v_buffer, unsigned int v_size)
{
#define DWORD_BIT 32
#define BYTE_BIT 8
unsigned int *buffer = NULL;
unsigned int word_sum = 0;
unsigned int i = 0;
unsigned int tmp = 0;
if (!v_buffer)
return;
buffer = (unsigned int *)v_buffer;
/* byte to dword */
word_sum = v_size / 4;
/* dword to byte */
while (i < word_sum) {
*buffer = cpu_to_be32(*buffer);
buffer++;
i++;
}
if (v_size % 4) {
tmp = cpu_to_be32(*buffer);
tmp = tmp >> (DWORD_BIT - (v_size % 4) * BYTE_BIT);
memcpy(buffer, &tmp, (v_size % 4));
}
}
#define UNF_FUNCTION_RETURN_CHECK(ret, dstlen) \
do { \
if (((ret) <= 0) || ((ret) >= (dstlen))) { \
UNF_TRACE(UNF_EVTLOG_DRIVER_ERR, \
UNF_LOG_REG_ATT, UNF_ERR, \
"function return (%d) check invalid, dst len(%d).", \
(ret), (dstlen)); \
} \
} while (0)
#define UNF_TOP_AUTO_MASK 0x0f
#define UNF_NORMAL_MODE 0
#define UNF_SET_NOMAL_MODE(mode) (mode = UNF_NORMAL_MODE)
/*
* SCSI status
*/
#define SCSI_CHECK_CONDITION 0x02
enum unf_act_topo_e {
UNF_ACT_TOP_PUBLIC_LOOP = 0x1,
UNF_ACT_TOP_PRIVATE_LOOP = 0x2,
UNF_ACT_TOP_P2P_DIRECT = 0x4,
UNF_ACT_TOP_P2P_FABRIC = 0x8,
UNF_TOP_LOOP_MASK = 0x03,
UNF_TOP_P2P_MASK = 0x0c,
UNF_TOP_FCOE_MASK = 0x30,
UNF_ACT_TOP_UNKNOWN
};
#define UNF_FL_PORT_LOOP_ADDR 0x00
#define UNF_FC_PROTOCOL_TYPE 0x100
#define UNF_LOOP_ROLE_MASTER_OR_SLAVE 0x0
#define UNF_TOU16_CHECK(dest, src, over_action) \
do { \
if (unlikely((src) > 0xFFFF)) { \
UNF_TRACE(UNF_EVTLOG_DRIVER_ERR, UNF_LOG_REG_ATT, \
UNF_ERR, "ToU16 error, src 0x%x ", (src)); \
over_action; \
} \
((dest) = (unsigned short)(src)); \
} while (0)
#define UNF_PORT_SPEED_AUTO 0
#define UNF_PORT_SPEED_2_G 2
#define UNF_PORT_SPEED_4_G 4
#define UNF_PORT_SPEED_8_G 8
#define UNF_PORT_SPEED_10_G 10
#define UNF_PORT_SPEED_16_G 16
#define UNF_PORT_SPEED_32_G 32
#define UNF_PORT_SPEED_UNKNOWN (~0)
#define UNF_PORT_SFP_SPEED_ERR 0xFF
#define UNF_FW_VERSION_LEN 32
#define UNF_HW_VERSION_LEN 32
/* max frame size */
#define UNF_MAX_FRAME_SIZE 2112
/* default */
#define UNF_DEFAULT_FRAME_SIZE 2048
#define UNF_DEFAULT_EDTOV 2000
#define UNF_DEFAULT_RATOV 10000
#define UNF_DEFAULT_FABRIC_RATOV 10000
#define UNF_MAX_RETRY_COUNT 3
#define UNF_DEFAULT_RRTOV (10000 + 500) /* FCP-4 10.4.10 */
#define UNF_RRQ_MIN_TIMEOUT_INTERVAL 30000
#define UNF_LOGO_TIMEOUT_INTERVAL 3000
#define UNF_WRITE_RRQ_SENDERR_INTERVAL 3000
#define UNF_REC_TOV 3000
#define UNF_WAIT_SEM_TIMEOUT (5000UL)
#define UNF_WAIT_ABTS_RSP_TIMEOUT (20000UL)
#define UNF_INI_RRQ_REDUNDANT_TIME 500
#define UNF_INI_ELS_REDUNDANT_TIME 2000
/* ELS command values */
#define UNF_ELS_CMND_HIGH_MASK 0xff000000
#define UNF_ELS_CMND_RJT 0x01000000
#define UNF_ELS_CMND_ACC 0x02000000
#define UNF_ELS_CMND_PLOGI 0x03000000
#define UNF_ELS_CMND_FLOGI 0x04000000
#define UNF_ELS_CMND_LOGO 0x05000000
#define UNF_ELS_CMND_RLS 0x0F000000
#define UNF_ELS_CMND_ECHO 0x10000000
#define UNF_ELS_CMND_REC 0x13000000
#define UNF_ELS_CMND_RRQ 0x12000000
#define UNF_ELS_CMND_PRLI 0x20000000
#define UNF_ELS_CMND_PRLO 0x21000000
#define UNF_ELS_CMND_PDISC 0x50000000
#define UNF_ELS_CMND_FDISC 0x51000000
#define UNF_ELS_CMND_ADISC 0x52000000
#define UNF_ELS_CMND_FAN 0x60000000
#define UNF_ELS_CMND_RSCN 0x61000000
#define UNF_FCP_CMND_SRR 0x14000000
#define UNF_GS_CMND_SCR 0x62000000
#define UNF_PLOGI_VERSION_UPPER 0x20
#define UNF_PLOGI_VERSION_LOWER 0x20
#define UNF_PLOGI_CONCURRENT_SEQ 0x00FF
#define UNF_PLOGI_RO_CATEGORY 0x00FE
#define UNF_PLOGI_SEQ_PER_XCHG 0x0001
/* CT_IU pream defines */
#define UNF_REV_NPORTID_INIT 0x01000000
#define UNF_FSTYPE_OPT_INIT 0xfc020000
#define UNF_FSTYPE_RFT_ID 0x02170000
#define UNF_FSTYPE_GID_PT 0x01A10000
#define UNF_FSTYPE_GID_FT 0x01710000
#define UNF_FSTYPE_RFF_ID 0x021F0000
#define UNF_FSTYPE_GFF_ID 0x011F0000
#define UNF_FSTYPE_GNN_ID 0x01130000
#define UNF_FSTYPE_GPN_ID 0x01120000
#define UNF_CT_IU_RSP_MASK 0xffff0000
#define UNF_CT_IU_REASON_MASK 0x00ff0000
#define UNF_CT_IU_EXPLAN_MASK 0x0000ff00
#define UNF_CT_IU_REJECT 0x80010000
#define UNF_CT_IU_ACCEPT 0x80020000
#define UNF_FABRIC_FULL_REG 0x00000003
#define UNF_FC4_SCSI_BIT8 0x00000100
#define UNF_FC4_FCP_TYPE 0x00000008
#define UNF_FRAG_REASON_VENDOR 0
/* GID_PT, GID_FT */
#define UNF_GID_PT_TYPE 0x7F000000
#define UNF_GID_FT_TYPE 0x00000008
/*
* FC4 defines
*/
#define UNF_FC4_FRAME_PAGE_SIZE 0x10
#define UNF_FC4_FRAME_PAGE_SIZE_SHIFT 16
#define UNF_FC4_FRAME_PARM_0_FCP 0x08000000
#define UNF_FC4_FRAME_PARM_0_I_PAIR 0x00002000
#define UNF_FC4_FRAME_PARM_0_GOOD_RSP_CODE 0x00000100
#define UNF_FC4_FRAME_PARM_3_INI 0x00000020
#define UNF_FC4_FRAME_PARM_3_TGT 0x00000010
#define UNF_FC4_FRAME_PARM_3_R_XFER_DIS 0x00000002
#define UNF_FC4_FRAME_PARM_3_CONF_ALLOW 0x00000080 /* bit 7 */
#define UNF_FC4_FRAME_PARM_3_REC_SUPPORT 0x00000400 /* bit 10 */
#define UNF_FC4_FRAME_PARM_3_TASK_RETRY_ID_SUPPORT 0x00000200 /* bit 9 */
#define UNF_FC4_FRAME_PARM_3_RETRY_SUPPORT 0x00000100 /* bit 8 */
#define UNF_FC4_FRAME_PARM_3_CONF_ALLOW 0x00000080 /* bit 7 */
#define UNF_GFF_ACC_MASK 0xFF000000
/* Reject CT_IU Reason Codes */
#define UNF_CTIU_RJT_MASK 0xffff0000
#define UNF_CTIU_RJT_INVALID_COMMAND 0x00010000
#define UNF_CTIU_RJT_INVALID_VERSION 0x00020000
#define UNF_CTIU_RJT_LOGIC_ERR 0x00030000
#define UNF_CTIU_RJT_INVALID_SIZE 0x00040000
#define UNF_CTIU_RJT_LOGIC_BUSY 0x00050000
#define UNF_CTIU_RJT_PROTOCOL_ERR 0x00070000
#define UNF_CTIU_RJT_UNABLE_PERFORM 0x00090000
#define UNF_CTIU_RJT_NOT_SUPPORTED 0x000B0000
/* FS_RJT Reason code explanations, FC-GS-2 6.5 */
#define UNF_CTIU_RJT_EXP_MASK 0x0000FF00
#define UNF_CTIU_RJT_EXP_NO_ADDTION 0x00000000
#define UNF_CTIU_RJT_EXP_PORTID_NO_REG 0x00000100
#define UNF_CTIU_RJT_EXP_PORTNAME_NO_REG 0x00000200
#define UNF_CTIU_RJT_EXP_NODENAME_NO_REG 0x00000300
#define UNF_CTIU_RJT_EXP_FC4TYPE_NO_REG 0x00000700
#define UNF_CTIU_RJT_EXP_PORTTYPE_NO_REG 0x00000A00
/*
* LS_RJT defines
*/
#define UNF_FC_LS_RJT_REASON_MASK 0x00ff0000
/*
* LS_RJT reason code defines
*/
#define UNF_LS_OK 0x00000000
#define UNF_LS_RJT_INVALID_COMMAND 0x00010000
#define UNF_LS_RJT_LOGICAL_ERROR 0x00030000
#define UNF_LS_RJT_BUSY 0x00050000
#define UNF_LS_RJT_PROTOCOL_ERROR 0x00070000
#define UNF_LS_RJT_REQUEST_DENIED 0x00090000
#define UNF_LS_RJT_NOT_SUPPORTED 0x000b0000
#define UNF_LS_RJT_CLASS_ERROR 0x000c0000
/*
* LS_RJT code explanation
*/
#define UNF_LS_RJT_NO_ADDITIONAL_INFO 0x00000000
#define UNF_LS_RJT_INV_DATA_FIELD_SIZE 0x00000700
#define UNF_LS_RJT_INV_COMMON_SERV_PARAM 0x00000F00
#define UNF_LS_RJT_INVALID_OXID_RXID 0x00001700
#define UNF_LS_RJT_COMMAND_IN_PROGRESS 0x00001900
#define UNF_LS_RJT_INSUFFICIENT_RESOURCES 0x00002900
#define UNF_LS_RJT_COMMAND_NOT_SUPPORTED 0x00002C00
#define UNF_LS_RJT_UNABLE_TO_SUPLY_REQ_DATA 0x00002A00
#define UNF_LS_RJT_INVALID_PAYLOAD_LENGTH 0x00002D00
#define UNF_P2P_LOCAL_NPORT_ID 0x000000EF
#define UNF_P2P_REMOTE_NPORT_ID 0x000000D6
#define UNF_BBCREDIT_MANAGE_NFPORT 0
#define UNF_BBCREDIT_MANAGE_LPORT 1
#define UNF_BBCREDIT_LPORT 0
#define UNF_CONTIN_INCREASE_SUPPORT 1
#define UNF_CLASS_VALID 1
#define UNF_CLASS_INVALID 0
#define UNF_NOT_MEANINGFUL 0
#define UNF_NO_SERVICE_PARAMS 0
#define UNF_CLEAN_ADDRESS_DEFAULT 0
#define UNF_PRIORITY_ENABLE 1
#define UNF_PRIORITY_DISABLE 0
#define UNF_SEQUEN_DELIVERY_REQ 1 /* Sequential delivery requested */
/* RSCN */
#define UNF_RSCN_PORT_ADDR 0x0
#define UNF_RSCN_AREA_ADDR_GROUP 0x1
#define UNF_RSCN_DOMAIN_ADDR_GROUP 0x2
#define UNF_RSCN_FABRIC_ADDR_GROUP 0x3
#define UNF_GET_RSCN_PLD_LEN(v_cmnd) ((v_cmnd)&0x0000ffff)
#define UNF_RSCN_PAGE_LEN 0x4
#define UNF_PORT_LINK_UP 0x0000
#define UNF_PORT_LINK_DOWN 0x0001
#define UNF_PORT_RESET_START 0x0002
#define UNF_PORT_RESET_END 0x0003
#define UNF_PORT_LINK_UNKNOWN 0x0004
#define UNF_PORT_NOP 0x0005
#define UNF_PORT_CORE_FATAL_ERROR 0x0006
#define UNF_PORT_CORE_UNRECOVERABLE_ERROR 0x0007
#define UNF_PORT_CORE_RECOVERABLE_ERROR 0x0008
#define UNF_PORT_UPDATE_PROCESS 0x000b
#define UNF_PORT_DEBUG_DUMP 0x000c
#define UNF_PORT_GET_FWLOG 0x000d
#define UNF_PORT_CLEAN_DONE 0x000e
#define UNF_PORT_BEGIN_REMOVE 0x000f
#define UNF_PORT_RELEASE_RPORT_INDEX 0x0010
#define UNF_PORT_ABNORMAL_RESET 0x0012
#define UNF_READ 0
#define UNF_WRITE 1
#define UNF_READ_64 2
#define UNF_WRITE_64 3
/*
*SCSI begin
*/
#define SCSIOPC_TEST_UNIT_READY 0x00
#define SCSIOPC_INQUIRY 0x12
#define SCSIOPC_MODE_SENSE_6 0x1A
#define SCSIOPC_MODE_SENSE_10 0x5A
#define SCSIOPC_MODE_SELECT_6 0x15
#define SCSIOPC_RESERVE 0x16
#define SCSIOPC_RELEASE 0x17
#define SCSIOPC_START_STOP_UNIT 0x1B
#define SCSIOPC_READ_CAPACITY_10 0x25
#define SCSIOPC_READ_CAPACITY_16 0x9E
#define SCSIOPC_READ_6 0x08
#define SCSIOPC_READ_10 0x28
#define SCSIOPC_READ_12 0xA8
#define SCSIOPC_READ_16 0x88
#define SCSIOPC_WRITE_6 0x0A
#define SCSIOPC_WRITE_10 0x2A
#define SCSIOPC_WRITE_12 0xAA
#define SCSIOPC_WRITE_16 0x8A
#define SCSIOPC_WRITE_VERIFY 0x2E
#define SCSIOPC_VERIFY_10 0x2F
#define SCSIOPC_VERIFY_12 0xAF
#define SCSIOPC_VERIFY_16 0x8F
#define SCSIOPC_REQUEST_SENSE 0x03
#define SCSIOPC_REPORT_LUN 0xA0
#define SCSIOPC_FORMAT_UNIT 0x04
#define SCSIOPC_SEND_DIAGNOSTIC 0x1D
#define SCSIOPC_WRITE_SAME_10 0x41
#define SCSIOPC_WRITE_SAME_16 0x93
#define SCSIOPC_READ_BUFFER 0x3C
#define SCSIOPC_WRITE_BUFFER 0x3B
#define SCSIOPC_LOG_SENSE 0x4D
#define SCSIOPC_MODE_SELECT_10 0x55
#define SCSIOPC_SYNCHRONIZE_CACHE_10 0x35
#define SCSIOPC_SYNCHRONIZE_CACHE_16 0x91
#define SCSIOPC_WRITE_AND_VERIFY_10 0x2E
#define SCSIOPC_WRITE_AND_VERIFY_12 0xAE
#define SCSIOPC_WRITE_AND_VERIFY_16 0x8E
#define SCSIOPC_READ_MEDIA_SERIAL_NUMBER 0xAB
#define SCSIOPC_REASSIGN_BLOCKS 0x07
#define SCSIOPC_ATA_PASSTHROUGH_16 0x85
#define SCSIOPC_ATA_PASSTHROUGH_12 0xa1
/*
* SCSI end
*/
#define IS_READ_COMMAND(opcode) ((opcode) == SCSIOPC_READ_6 || \
(opcode) == SCSIOPC_READ_10 || \
(opcode) == SCSIOPC_READ_12 || \
(opcode) == SCSIOPC_READ_16)
#define IS_WRITE_COMMAND(opcode) ((opcode) == SCSIOPC_WRITE_6 || \
(opcode) == SCSIOPC_WRITE_10 || \
(opcode) == SCSIOPC_WRITE_12 || \
(opcode) == SCSIOPC_WRITE_16)
#define FCP_RSP_LEN_VALID_MASK 0x1
#define FCP_SNS_LEN_VALID_MASK 0x2
#define FCP_RESID_OVER_MASK 0x4
#define FCP_RESID_UNDER_MASK 0x8
#define FCP_CONF_REQ_MASK 0x10
#define FCP_SCSI_STATUS_GOOD 0x0
#define UNF_DELAYED_WORK_SYNC(v_ret, v_pord_id, v_work, v_work_symb) \
do { \
if (!cancel_delayed_work_sync(v_work)) { \
UNF_TRACE(UNF_EVTLOG_DRIVER_INFO, UNF_LOG_REG_ATT, \
UNF_INFO, \
"[info]LPort or RPort(0x%x) %s worker can't destroy, or no worker", \
v_pord_id, v_work_symb); \
v_ret = UNF_RETURN_ERROR; \
} else { \
v_ret = RETURN_OK; \
} \
} while (0)
#define UNF_DELAYED_WORK(v_ret, v_pord_id, v_work, v_work_symb) \
do { \
if (!cancel_delayed_work(v_work)) { \
UNF_TRACE(UNF_EVTLOG_DRIVER_INFO, UNF_LOG_REG_ATT, \
UNF_MAJOR, \
"LPort or RPort(0x%x) %s worker can't destroy, or no worker.", \
v_pord_id, v_work_symb); \
v_ret = UNF_RETURN_ERROR; \
} else { \
v_ret = RETURN_OK; \
} \
} while (0)
#define UNF_DELAYED_WORK_CONFUSED(v_ret, v_pord_id, v_work, v_work_symb) \
do { \
if (in_interrupt()) { \
UNF_DELAYED_WORK(v_ret, v_pord_id, v_work, \
v_work_symb) \
} else { \
UNF_DELAYED_WORK_SYNC(v_ret, v_pord_id, v_work, \
v_work_symb) \
} \
} while (0)
#define UNF_GET_IO_XCHG_TAG(v_pkg) \
((unsigned short)((v_pkg)->private[PKG_PRIVATE_XCHG_HOT_POOL_INDEX]))
#define UNF_GET_SFS_ENTRY(v_pkg) ((union unf_sfs_u *)(void *) \
(((struct unf_frame_pkg_s *)v_pkg)->unf_cmnd_pload_bl.buffer_ptr))
/* FLOGI */
#define UNF_GET_FLOGI_PAYLOAD(v_pkg) (&(((union unf_sfs_u *) \
(UNF_GET_SFS_ENTRY(v_pkg)))->flogi.flogi_payload))
#define UNF_FLOGI_PAYLOAD_LEN sizeof(struct unf_flogi_payload_s)
/* FLOGI ACC */
#define UNF_GET_FLOGI_ACC_PAYLOAD(v_pkg) (&(((union unf_sfs_u *) \
(UNF_GET_SFS_ENTRY(v_pkg)))->flogi_acc.flogi_payload))
#define UNF_FLOGI_ACC_PAYLOAD_LEN sizeof(struct unf_flogi_payload_s)
/* FDISC */
#define UNF_FDISC_PAYLOAD_LEN UNF_FLOGI_PAYLOAD_LEN
#define UNF_FDISC_ACC_PAYLOAD_LEN UNF_FLOGI_ACC_PAYLOAD_LEN
/* PLOGI */
#define UNF_GET_PLOGI_PAYLOAD(v_pkg) \
(&(((union unf_sfs_u *)(UNF_GET_SFS_ENTRY(v_pkg)))->plogi.payload))
#define UNF_PLOGI_PAYLOAD_LEN sizeof(struct unf_plogi_payload_s)
/* PLOGI ACC */
#define UNF_GET_PLOGI_ACC_PAYLOAD(v_pkg) \
(&(((union unf_sfs_u *)(UNF_GET_SFS_ENTRY(v_pkg)))->plogi_acc.payload))
#define UNF_PLOGI_ACC_PAYLOAD_LEN sizeof(struct unf_plogi_payload_s)
/* LOGO */
#define UNF_LOGO_PAYLOAD_LEN sizeof(struct unf_logo_payload_s)
/* ECHO */
#define UNF_GET_ECHO_PAYLOAD(v_pkg) \
(((union unf_sfs_u *)(UNF_GET_SFS_ENTRY(v_pkg)))->echo.echo_pld)
/* ECHO PHYADDR */
#define UNF_GET_ECHO_PAYLOAD_PHYADDR(v_pkg) \
(((union unf_sfs_u *)(UNF_GET_SFS_ENTRY(v_pkg)))->echo.phy_echo_addr)
#define UNF_ECHO_PAYLOAD_LEN sizeof(struct unf_echo_payload_s)
/* RLS */
#define UNF_RLS_PAYLOAD_LEN sizeof(struct unf_rls_payload_s)
/* ECHO ACC */
#define UNF_ECHO_ACC_PAYLOAD_LEN sizeof(struct unf_echo_payload_s)
/* REC */
#define UNF_REC_PAYLOAD_LEN sizeof(struct unf_rec_pld_s)
/* REC ACC */
#define UNF_GET_REC_ACC_PAYLOAD(v_pkg) \
(&(((union unf_sfs_u *)(UNF_GET_SFS_ENTRY(v_pkg)))->els_acc.cmnd))
#define UNF_REC_ACC_PAYLOAD_LEN (sizeof(struct unf_els_acc_s) - \
sizeof(struct unf_fchead_s))
/* RRQ */
#define UNF_RRQ_PAYLOAD_LEN (sizeof(struct unf_rrq_s) - \
sizeof(struct unf_fchead_s))
/* PRLI */
#define UNF_PRLI_PAYLOAD_LEN sizeof(struct unf_pril_payload_s)
/* PRLI ACC */
#define UNF_PRLI_ACC_PAYLOAD_LEN sizeof(struct unf_pril_payload_s)
/* PRLO */
#define UNF_PRLO_PAYLOAD_LEN sizeof(struct unf_pril_payload_s)
#define UNF_PRLO_ACC_PAYLOAD_LEN sizeof(struct unf_pril_payload_s)
/* PDISC */
#define UNF_PDISC_PAYLOAD_LEN sizeof(struct unf_plogi_payload_s)
/* PDISC ACC */
#define UNF_PDISC_ACC_PAYLOAD_LEN sizeof(struct unf_plogi_payload_s)
/* ADISC */
#define UNF_ADISC_PAYLOAD_LEN sizeof(struct unf_adisc_payload_s)
/* ADISC ACC */
#define UNF_ADISC_ACC_PAYLOAD_LEN sizeof(struct unf_adisc_payload_s)
/* RSCN ACC */
#define UNF_GET_RSCN_ACC_PAYLOAD(v_pkg) \
(&(((union unf_sfs_u *)(UNF_GET_SFS_ENTRY(v_pkg)))->els_acc.cmnd))
#define UNF_RSCN_ACC_PAYLOAD_LEN (sizeof(struct unf_els_acc_s) - \
sizeof(struct unf_fchead_s))
/* LOGO ACC */
#define UNF_LOGO_ACC_PAYLOAD_LEN (sizeof(struct unf_els_acc_s) - \
sizeof(struct unf_fchead_s))
/* RRQ ACC */
#define UNF_RRQ_ACC_PAYLOAD_LEN (sizeof(struct unf_els_acc_s) - \
sizeof(struct unf_fchead_s))
/* RLS ACC */
#define UNF_RLS_ACC_PAYLOAD_LEN (sizeof(struct unf_rls_acc_s) - \
sizeof(struct unf_fchead_s))
/* GPN_ID */
#define UNF_GPNID_PAYLOAD_LEN (sizeof(struct unf_gpnid_s) - \
sizeof(struct unf_fchead_s))
#define UNF_GPNID_RSP_PAYLOAD_LEN (sizeof(struct unf_gpnid_rsp_s) - \
sizeof(struct unf_fchead_s))
/* GNN_ID */
#define UNF_GNNID_PAYLOAD_LEN (sizeof(struct unf_gnnid_s) - \
sizeof(struct unf_fchead_s))
#define UNF_GNNID_RSP_PAYLOAD_LEN (sizeof(struct unf_gnnid_rsp_s) - \
sizeof(struct unf_fchead_s))
/* GFF_ID */
#define UNF_GFFID_PAYLOAD_LEN (sizeof(struct unf_gffid_s) - \
sizeof(struct unf_fchead_s))
#define UNF_GFFID_RSP_PAYLOAD_LEN (sizeof(struct unf_gffid_rsp_s) - \
sizeof(struct unf_fchead_s))
/* GID_FT/GID_PT */
#define UNF_GET_GID_PAYLOAD(v_pkg) (&(((union unf_sfs_u *) \
UNF_GET_SFS_ENTRY(v_pkg))->get_id.gid_req.ctiu_pream))
#define UNF_GID_PAYLOAD_LEN (sizeof(struct unf_ctiu_prem_s) + \
sizeof(unsigned int))
#define UNF_GID_ACC_PAYLOAD_LEN sizeof(struct unf_gif_acc_pld_s)
/* RFT_ID */
#define UNF_RFTID_PAYLOAD_LEN (sizeof(struct unf_rftid_s) - \
sizeof(struct unf_fchead_s))
#define UNF_RFTID_RSP_PAYLOAD_LEN sizeof(struct unf_ctiu_prem_s)
/* RFF_ID */
#define UNF_RFFID_PAYLOAD_LEN (sizeof(struct unf_rffid_s) - \
sizeof(struct unf_fchead_s))
#define UNF_RFFID_RSP_PAYLOAD_LEN sizeof(struct unf_ctiu_prem_s)
/* SRR */
#define UNF_SRR_PAYLOAD_LEN \
sizeof(struct unf_srr_payload_s)
/* ACC&RJT */
#define UNF_ELS_ACC_RJT_LEN (sizeof(struct unf_els_rjt_s) - \
sizeof(struct unf_fchead_s))
/* SCR */
#define UNF_SCR_PAYLOAD_LEN (sizeof(struct unf_scr_s) - \
sizeof(struct unf_fchead_s))
#define UNF_SCR_RSP_PAYLOAD_LEN (sizeof(struct unf_els_acc_s) - \
sizeof(struct unf_fchead_s))
/**********************************************************/
#define UNF_GET_XCHG_TAG(v_pkg) (((struct unf_frame_pkg_s *) \
v_pkg)->private[PKG_PRIVATE_XCHG_HOT_POOL_INDEX])
#define UNF_GET_SID(v_pkg) (((struct unf_frame_pkg_s *) \
v_pkg)->frame_head.csctl_sid & UNF_NPORTID_MASK)
#define UNF_GET_DID(v_pkg) (((struct unf_frame_pkg_s *) \
v_pkg)->frame_head.rctl_did & UNF_NPORTID_MASK)
#define UNF_GET_OXID(v_pkg) (((struct unf_frame_pkg_s *) \
v_pkg)->frame_head.oxid_rxid >> 16)
#define UNF_GET_RXID(v_pkg) ((unsigned short)((struct unf_frame_pkg_s *) \
v_pkg)->frame_head.oxid_rxid)
#define UNF_GET_XFER_LEN(v_pkg) (((struct unf_frame_pkg_s *)v_pkg)->transfer_len)
/* ioc abort */
#define UNF_GETXCHGALLOCTIME(v_pkg) \
(((struct unf_frame_pkg_s *)v_pkg)->private[PKG_PRIVATE_XCHG_ALLOC_TIME])
#define UNF_SET_XCHG_ALLOC_TIME(pkg, xchg) \
(((struct unf_frame_pkg_s *)(pkg))->private[PKG_PRIVATE_XCHG_ALLOC_TIME] = \
(((struct unf_xchg_s *)(xchg))->private[PKG_PRIVATE_XCHG_ALLOC_TIME]))
#define UNF_SET_ABORT_INFO_IOTYPE(pkg, xchg) \
(((struct unf_frame_pkg_s *)(pkg))->private[PKG_PRIVATE_XCHG_ABORT_INFO] |= \
(((unsigned char)(((struct unf_xchg_s *)(xchg))->data_direction & 0x7))\
<< 2))
#define UNF_CHECK_NPORT_FPORT_BIT(els_payload) \
(((struct unf_flogi_payload_s *)els_payload)->fabric_parms.co_parms.n_port)
#define UNF_N_PORT 0
#define UNF_F_PORT 1
#define UNF_GET_RA_TOV_FROM_PARAMS(params) \
(((struct unf_fabric_parms_s *)params)->co_parms.r_a_tov)
#define UNF_GET_RT_TOV_FROM_PARAMS(params) \
(((struct unf_fabric_parms_s *)params)->co_parms.r_t_tov)
#define UNF_GET_E_D_TOV_FROM_PARAMS(params) \
(((struct unf_fabric_parms_s *)params)->co_parms.e_d_tov)
#define UNF_GET_E_D_TOV_RESOLUTION_FROM_PARAMS(params) \
(((struct unf_fabric_parms_s *)params)->co_parms.e_d_tov_resolution)
#define UNF_GET_BB_SC_N_FROM_PARAMS(params) \
(((struct unf_fabric_parms_s *)params)->co_parms.bb_scn)
#define UNF_GET_BB_CREDIT_FROM_PARAMS(params) \
(((struct unf_fabric_parms_s *)params)->co_parms.bb_credit)
enum unf_pcie_error_code_e {
UNF_PCIE_ERROR_NONE = 0,
UNF_PCIE_DATAPARITYDETECTED = 1,
UNF_PCIE_SIGNALTARGETABORT,
UNF_PCIE_RECEIVEDTARGETABORT,
UNF_PCIE_RECEIVEDMASTERABORT,
UNF_PCIE_SIGNALEDSYSTEMERROR,
UNF_PCIE_DETECTEDPARITYERROR,
UNF_PCIE_CORRECTABLEERRORDETECTED,
UNF_PCIE_NONFATALERRORDETECTED,
UNF_PCIE_FATALERRORDETECTED,
UNF_PCIE_UNSUPPORTEDREQUESTDETECTED,
UNF_PCIE_AUXILIARYPOWERDETECTED,
UNF_PCIE_TRANSACTIONSPENDING,
UNF_PCIE_UNCORRECTINTERERRSTATUS,
UNF_PCIE_UNSUPPORTREQERRSTATUS,
UNF_PCIE_ECRCERRORSTATUS,
UNF_PCIE_MALFORMEDTLPSTATUS,
UNF_PCIE_RECEIVEROVERFLOWSTATUS,
UNF_PCIE_UNEXPECTCOMPLETESTATUS,
UNF_PCIE_COMPLETERABORTSTATUS,
UNF_PCIE_COMPLETIONTIMEOUTSTATUS,
UNF_PCIE_FLOWCTRLPROTOCOLERRSTATUS,
UNF_PCIE_POISONEDTLPSTATUS,
UNF_PCIE_SURPRISEDOWNERRORSTATUS,
UNF_PCIE_DATALINKPROTOCOLERRSTATUS,
UNF_PCIE_ADVISORYNONFATALERRSTATUS,
UNF_PCIE_REPLAYTIMERTIMEOUTSTATUS,
UNF_PCIE_REPLAYNUMROLLOVERSTATUS,
UNF_PCIE_BADDLLPSTATUS,
UNF_PCIE_BADTLPSTATUS,
UNF_PCIE_RECEIVERERRORSTATUS,
UNF_PCIE_BUTT
};
#define UNF_DMA_HI32(a) (((a) >> 32) & 0xffffffff)
#define UNF_DMA_LO32(a) ((a) & 0xffffffff)
#define UNF_WWN_LEN 8
#define UNF_MAC_LEN 6
/* send BLS/ELS/BLS REPLY/ELS REPLY/GS/ */
/* rcvd BLS/ELS/REQ DONE/REPLY DONE */
#define UNF_PKG_BLS_REQ 0x0100
#define UNF_PKG_BLS_REQ_DONE 0x0101
#define UNF_PKG_ELS_REQ 0x0200
#define UNF_PKG_ELS_REQ_DONE 0x0201
#define UNF_PKG_ELS_REPLY 0x0202
#define UNF_PKG_ELS_REPLY_DONE 0x0203
#define UNF_PKG_GS_REQ 0x0300
#define UNF_PKG_GS_REQ_DONE 0x0301
#define UNF_PKG_INI_IO 0x0500
#define UNF_PKG_INI_RCV_TGT_RSP 0x0507
/* external sgl struct start */
struct unf_esgl_page_s {
unsigned long long page_address;
dma_addr_t esgl_phyaddr;
unsigned int page_size;
};
struct unf_esgl_s {
struct list_head entry_esgl;
struct unf_esgl_page_s page;
};
/* external sgl struct end */
struct unf_frame_payld_s {
unsigned char *buffer_ptr;
dma_addr_t buf_dma_addr;
unsigned int length;
};
enum pkg_private_index_e {
PKG_PRIVATE_LOWLEVEL_XCHG_ADD = 0,
PKG_PRIVATE_XCHG_HOT_POOL_INDEX = 1, /* Hot Pool Index */
PKG_PRIVATE_XCHG_RPORT_INDEX = 2, /* RPort index */
PKG_PRIVATE_XCHG_VP_INDEX = 3, /* VPort index */
PKG_PRIVATE_RPORT_RX_SIZE,
PKG_PRIVATE_XCHG_TIMEER,
PKG_PRIVATE_XCHG_ALLOC_TIME,
PKG_PRIVATE_XCHG_ABORT_INFO,
PKG_PRIVATE_ECHO_CMD_SND_TIME, /* local send echo cmd time stamp */
PKG_PRIVATE_ECHO_ACC_RCV_TIME, /* local receive echo acc time stamp */
PKG_PRIVATE_ECHO_CMD_RCV_TIME, /* remote receive echo cmd time stamp */
PKG_PRIVATE_ECHO_RSP_SND_TIME, /* remote send echo rsp time stamp */
PKG_MAX_PRIVATE_DATA_SIZE
};
extern unsigned int dix_flag;
extern unsigned int dif_sgl_mode;
extern unsigned int dif_app_esc_check;
extern unsigned int dif_ref_esc_check;
#define UNF_DIF_ACTION_NONE 0
enum unf_adm_dif_mode_e {
UNF_SWITCH_DIF_DIX = 0,
UNF_APP_REF_ESCAPE,
ALL_DIF_MODE = 20,
};
#define UNF_VERIFY_CRC_MASK (1 << 1)
#define UNF_VERIFY_APP_MASK (1 << 2)
#define UNF_VERIFY_LBA_MASK (1 << 3)
#define UNF_REPLACE_CRC_MASK (1 << 8)
#define UNF_REPLACE_APP_MASK (1 << 9)
#define UNF_REPLACE_LBA_MASK (1 << 10)
#define UNF_DIF_ACTION_MASK (0xff << 16)
#define UNF_DIF_ACTION_INSERT (0x1 << 16)
#define UNF_DIF_ACTION_VERIFY_AND_DELETE (0x2 << 16)
#define UNF_DIF_ACTION_VERIFY_AND_FORWARD (0x3 << 16)
#define UNF_DIF_ACTION_VERIFY_AND_REPLACE (0x4 << 16)
#define UNF_DIF_ACTION_NO_INCREASE_REFTAG (0x1 << 24)
#define UNF_DEFAULT_CRC_GUARD_SEED (0)
#define UNF_CAL_BLOCK_CNT(data_len, sector_size) ((data_len) / (sector_size))
#define UNF_DIF_DOUBLE_SGL (1 << 1)
#define UNF_DIF_SECTSIZE_4KB (1 << 2)
#define UNF_DIF_LBA_NONE_INCREASE (1 << 3)
#define UNF_DIF_TYPE3 (1 << 4)
#define HIFC_DIF_APP_REF_ESC_NOT_CHECK 1
#define HIFC_DIF_APP_REF_ESC_CHECK 0
enum unf_io_state_e {
UNF_INI_IO = 0,
UNF_TGT_XFER = 1,
UNF_TGT_RSP = 2
};
#define UNF_PKG_LAST_RESPONSE 0
#define UNF_PKG_NOT_LAST_RESPONSE 1
#define UNF_PKG_LAST_REQUEST 1
#define UNF_PKG_NOT_LAST_REQUEST 0
struct unf_frame_pkg_s {
/* pkt type:BLS/ELS/FC4LS/CMND/XFER/RSP */
unsigned int type;
unsigned int last_pkg_flag;
#define UNF_FCP_RESPONSE_VALID 0x01
#define UNF_FCP_SENSE_VALID 0x02
/* resp and sense vailed flag */
unsigned int response_and_sense_valid_flag;
unsigned int cmnd;
struct unf_fchead_s frame_head;
unsigned int entry_count;
void *xchg_contex;
unsigned int transfer_len;
unsigned int residus_len;
unsigned int status;
unsigned int status_sub_code;
enum unf_io_state_e io_state;
unsigned int qos_level;
unsigned int private[PKG_MAX_PRIVATE_DATA_SIZE];
unsigned char byte_orders;
struct unf_fcp_cmnd_s *fcp_cmnd;
struct unf_dif_control_info_s dif_control;
struct unf_frame_payld_s unf_cmnd_pload_bl;
struct unf_frame_payld_s unf_rsp_pload_bl;
struct unf_frame_payld_s unf_sense_pload_bl;
void *upper_cmd;
unsigned int abts_maker_status;
};
#define UNF_MAX_SFS_XCHG 2048
#define UNF_RESERVE_SFS_XCHG 128 /* times on exchange mgr num */
struct unf_lport_cfg_item_s {
unsigned int port_id;
unsigned int port_mode; /* INI(0x20) TGT(0x10) BOTH(0x30) */
unsigned int port_topology; /* 0x3:loop , 0xc:p2p ,0xf:auto */
unsigned int max_queue_depth;
unsigned int max_io; /* Recommended Value 512-4096 */
unsigned int max_login;
unsigned int max_sfs_xchg;
/* 0:auto 1:1Gbps 2:2Gbps 4:4Gbps 8:8Gbps 16:16Gbps */
unsigned int port_speed;
unsigned int tape_support; /* tape support */
unsigned int fcp_conf; /* fcp confirm support */
unsigned int bb_scn;
unsigned int sum_resource;
enum int_e res_mgmt_enabled;
};
struct unf_port_dynamic_info_s {
unsigned int sfp_posion;
unsigned int sfp_valid;
unsigned int phy_link;
unsigned int firmware_state;
unsigned int cur_speed;
unsigned int mailbox_timeout_cnt;
};
struct unf_hinicam_pkg {
unsigned int msg_format;
void *buff_in;
void *buff_out;
unsigned int in_size;
unsigned int *out_size;
};
struct unf_version_str_s {
char *buf;
unsigned int buf_len;
};
struct unf_buf_s {
unsigned char *cbuf;
unsigned int buf_len;
};
struct unf_rw_reg_param_s {
unsigned int rw_type;
unsigned int offset;
unsigned long long value;
};
/* get ucode & up ver */
#define HIFC_VER_LEN (16)
#define HIFC_COMPILE_TIME_LEN (20)
struct unf_fw_version_s {
unsigned int message_type;
unsigned char fw_version[HIFC_VER_LEN];
};
enum unf_port_config_set_op_e {
UNF_PORT_CFG_SET_SPEED,
UNF_PORT_CFG_SET_TOPO,
UNF_PORT_CFG_SET_BBSCN,
UNF_PORT_CFG_SET_MODE,
UNF_PORT_CFG_SET_SFP_SWITCH,
UNF_PORT_CFG_SET_PORT_SWITCH,
UNF_PORT_CFG_SET_POWER_STATE,
UNF_PORT_CFG_SET_PORT_STATE,
UNF_PORT_CFG_SET_INTR_COALSEC,
UNF_PORT_CFG_UPDATE_PORT,
UNF_PORT_CFG_UPDATE_WWN,
UNF_PORT_CFG_TEST_FLASH,
UNF_PORT_CFG_SET_FCP_CONF,
UNF_PORT_CFG_SET_LOOP_ROLE,
UNF_PORT_CFG_SET_INIT_REQ,
UNF_PORT_CFG_SET_MAX_SUPPORT_SPEED,
UNF_PORT_CFG_SET_MAC_ADDR,
UNF_PORT_CFG_SET_SFP_USEDTIME,
UNF_PORT_CFG_SET_PORT_TRANSFER_PARAMETER,
UNF_PORT_CFG_SET_SFP_REG_WRITE,
UNF_PORT_CFG_UPDATE_SFP,
UNF_PORT_CFG_UPDATE_FABRIC_PARAM,
UNF_PORT_CFG_UPDATE_PLOGI_PARAM,
UNF_PORT_CFG_UPDATE_FDISC_PARAM,
UNF_PORT_CFG_SAVE_HBA_INFO,
UNF_PORT_CFG_SET_HBA_BASE_INFO,
UNF_PORT_CFG_SET_FLASH_DATA_INFO,
UNF_PORT_CFG_SET_BUTT
};
enum unf_port_config_get_op_e {
UNF_PORT_CFG_GET_SPEED_CFG,
UNF_PORT_CFG_GET_SPEED_ACT,
UNF_PORT_CFG_GET_TOPO_CFG,
UNF_PORT_CFG_GET_TOPO_ACT,
UNF_PORT_CFG_GET_MODE,
UNF_PORT_CFG_GET_LOOP_MAP,
UNF_PORT_CFG_GET_TOV,
UNF_PORT_CFG_GET_SFP_PRESENT,
UNF_PORT_CFG_GET_SFP_INFO,
UNF_PORT_CFG_GET_FW_VER,
UNF_PORT_CFG_GET_HW_VER,
UNF_PORT_CFG_GET_LESB_THEN_CLR, /* Link Error Status Block, LESB */
UNF_PORT_CFG_GET_DYNAMIC_INFO,
UNF_PORT_CFG_GET_VITAL_REGS,
UNF_PORT_CFG_CLR_LESB,
UNF_PORT_CFG_GET_WORKBALE_BBCREDIT,
UNF_PORT_CFG_GET_WORKBALE_BBSCN,
UNF_PORT_CFG_GET_FC_SERDES,
UNF_PORT_CFG_GET_LOOP_ALPA,
UNF_PORT_CFG_GET_SFP_DYNAMIC_INFO,
UNF_PORT_CFG_GET_MAC_ADDR,
UNF_PORT_CFG_GET_SFP_USEDTIME,
UNF_PORT_CFG_GET_PORT_INFO,
UNF_PORT_CFG_DDT_TEST,
UNF_PORT_CFG_GET_LED_STATE,
UNF_PORT_CFG_GET_VLAN,
UNF_PORT_CFG_GET_SFP_REG_READ,
UNF_PORT_CFG_GET_SFP_VER,
UNF_PORT_CFG_GET_SFP_SUPPORT_UPDATE,
UNF_PORT_CFG_GET_SFP_LOG,
UNF_PORT_CFG_GET_FEC,
UNF_PORT_CFG_GET_PCIE_LINK_STATE,
UNF_PORT_CFG_GET_FLASH_DATA_INFO,
UNF_PORT_CFG_GET_BUTT
};
enum unf_port_diag_op_e {
UNF_PORT_DIAG_PORT_DETAIL,
UNF_PORT_DIAG_RD_WR_REG,
UNF_PORT_DIAG_BUTT
};
enum unf_port_config_state_e {
UNF_PORT_CONFIG_STATE_START,
UNF_PORT_CONFIG_STATE_STOP,
UNF_PORT_CONFIG_STATE_RESET,
UNF_PORT_CONFIG_STATE_STOP_INTR,
UNF_PORT_CONFIG_STATE_BUTT
};
struct unf_port_login_parms_s {
enum unf_act_topo_e en_act_topo;
unsigned int rport_index;
unsigned int seq_cnt : 1;
unsigned int ed_tov : 1;
unsigned int reserved : 14;
unsigned int tx_mfs : 16;
unsigned int ed_tov_timer_val;
unsigned char remote_rttov_tag;
unsigned char remote_edtov_tag;
unsigned short remote_bbcredit;
unsigned short compared_bbscn;
unsigned int compared_edtov_val;
unsigned int compared_ratov_val;
unsigned int els_cmnd_code;
};
#define HIFC_FLASH_MAX_LEN 1024 // bytes
struct unf_mbox_head_info_s {
/* mbox header */
unsigned char cmnd_type;
unsigned char length;
unsigned char port_id;
unsigned char pad0;
/* operation */
unsigned int op_code : 4;
unsigned int pad1 : 28;
};
#define HIFC_FLASH_MBOX_HEAD_MAX_LEN 8 // bytes
struct unf_mbox_head_sts_s {
/* mbox header */
unsigned char cmnd_type;
unsigned char length;
unsigned char port_id;
unsigned char pad0;
/* operation */
unsigned short pad1;
unsigned char pad2;
unsigned char status;
};
#define HIFC_FLASH_UEFI_MAX_LEN 16 // bytes
struct unf_flash_uefi_switch_s {
unsigned char writeflag;
unsigned char sanbooten;
unsigned char reserved[14];
};
#define HIFC_MGMT_UEFI_MAGIC_NUM 0xAF
#define HIFC_MGMT_TMO_MAGIC_NUM 0xAE
#define HIFC_FLASH_LINK_TMO_MAX_LEN 16 // bytes
struct unf_flash_link_tmo_s {
unsigned char writeflag;
unsigned char link_tmo0;
unsigned char link_tmo1;
unsigned char link_tmo2;
unsigned char link_tmo3;
unsigned char reserved[11];
};
#define HIFC_FLASH_DATA_MAX_LEN (HIFC_FLASH_MAX_LEN - \
HIFC_FLASH_MBOX_HEAD_MAX_LEN) // bytes
struct unf_flash_data_s {
struct unf_flash_uefi_switch_s uefi_switch; // 16 bytes
struct unf_flash_link_tmo_s link_tmo; // 16 bytes
/* once the related struct change, the reserved size needs modify */
unsigned char reserved[HIFC_FLASH_DATA_MAX_LEN - 32];
};
/* size of hifc_flash_data_mgmt not more than 1024 bytes */
struct unf_mbox_flash_data_mgmt_s {
struct unf_mbox_head_info_s mbox_head; // 8 bytes
struct unf_flash_data_s flash_data;
};
struct unf_flash_data_mgmt_sts_s {
struct unf_mbox_head_sts_s mbox_head; // 8 bytes
struct unf_flash_data_s flash_data;
};
struct unf_low_level_service_op_s {
unsigned int (*pfn_unf_els_send)(void *, struct unf_frame_pkg_s *);
unsigned int (*pfn_unf_bls_send)(void *, struct unf_frame_pkg_s *);
unsigned int (*pfn_unf_gs_send)(void *, struct unf_frame_pkg_s *);
unsigned int (*pfn_unf_fc_4_ls_send)(void *, struct unf_frame_pkg_s *);
unsigned int (*pfn_unf_cmnd_send)(void *, struct unf_frame_pkg_s *);
unsigned int (*pfn_ll_relese_xchg_res)(void *,
struct unf_frame_pkg_s *);
unsigned int (*pfn_unf_release_rport_res)(void *, struct
unf_rport_info_s *);
unsigned int (*pfn_unf_get_consumed_res)(void *,
struct unf_frame_pkg_s *);
unsigned int (*pfn_unf_flush_ini_resp_que)(void *);
unsigned int (*pfn_unf_alloc_rport_res)(void *,
struct unf_rport_info_s *);
unsigned int (*pfn_unf_rport_session_rst)(void *,
struct unf_rport_info_s *);
};
struct unf_low_level_port_mgr_op_s {
/* fcport/opcode/input parameter */
unsigned int (*pfn_ll_port_config_set)
(void *v_fc_port,
enum unf_port_config_set_op_e v_op_code,
void *v_para_in);
/* fcport/opcode/output parameter */
unsigned int (*pfn_ll_port_config_get)
(void *v_fc_port,
enum unf_port_config_get_op_e v_op_code,
void *v_para_out);
/* fcport/opcode/input parameter/output parameter */
unsigned int (*pfn_ll_port_diagnose)
(void *v_fc_port,
enum unf_port_diag_op_e v_op_code,
void *v_para);
};
struct unf_chip_info_s {
unsigned char chip_type;
unsigned char chip_work_mode;
unsigned char disable_err_flag;
};
struct unf_low_level_function_op_s {
struct unf_chip_info_s chip_info;
/* low level type */
unsigned int low_level_type;
/* low level name, fc etc. */
const char *name;
struct pci_dev *dev;
unsigned long long sys_node_name;
unsigned long long sys_port_name;
struct unf_lport_cfg_item_s lport_cfg_items;
/* low level Xchg mgr type,
* active --alloc oxid and rxid
* passtive -- not alloc oxid and rxid
*/
#define UNF_LOW_LEVEL_MGR_TYPE_ACTIVE 0
#define UNF_LOW_LEVEL_MGR_TYPE_PASSTIVE 1
const unsigned int xchg_mgr_type;
#define UNF_NO_EXTRA_ABTS_XCHG 0x0
#define UNF_LL_IOC_ABTS_XCHG 0x1
const unsigned int abts_xchg;
#define UNF_CM_RPORT_SET_QUALIFIER 0x0
#define UNF_CM_RPORT_SET_QUALIFIER_REUSE 0x1
#define UNF_CM_RPORT_SET_QUALIFIER_HIFC 0x2
/* low level pass-through flag. */
#define UNF_LOW_LEVEL_PASS_THROUGH_FIP 0x0
#define UNF_LOW_LEVEL_PASS_THROUGH_FABRIC_LOGIN 0x1
#define UNF_LOW_LEVEL_PASS_THROUGH_PORT_LOGIN 0x2
unsigned int pass_through_flag;
/* low level parameter */
unsigned int support_max_npiv_num;
unsigned int support_max_speed;
unsigned int fc_ser_max_speed;
unsigned int support_max_rport;
unsigned int support_max_xid_range;
unsigned int sfp_type;
unsigned int update_fw_reset_active;
unsigned int support_upgrade_report;
unsigned int multi_conf_support;
unsigned int port_type;
#define UNF_LOW_LEVEL_RELEASE_RPORT_SYNC 0x0
#define UNF_LOW_LEVEL_RELEASE_RPORT_ASYNC 0x1
unsigned char rport_release_type;
#define UNF_LOW_LEVEL_SIRT_PAGE_MODE_FIXED 0x0
#define UNF_LOW_LEVEL_SIRT_PAGE_MODE_XCHG 0x1
unsigned char sirt_page_mode;
unsigned char sfp_speed;
/* IO reference */
struct unf_low_level_service_op_s service_op;
/* Port Mgr reference */
struct unf_low_level_port_mgr_op_s port_mgr_op;
unsigned char chip_id;
};
struct unf_cm_handle_op_s {
/* return:L_Port */
void *(*pfn_unf_alloc_local_port)(void *,
struct unf_low_level_function_op_s *);
/* input para:L_Port */
unsigned int (*pfn_unf_release_local_port)(void *);
/* input para:lport vn2vnid,output para:ok/err */
unsigned int (*pfn_unf_set_vn2vn_id)(void *, unsigned int);
unsigned char (*pfn_unf_get_loop_id)(unsigned int v_port_id);
/* input para:L_Port, FRAME_PKG_S */
unsigned int (*pfn_unf_receive_els_pkg)(void *v_lport,
struct unf_frame_pkg_s *v_pkg);
/* input para:L_Port, FRAME_PKG_S */
unsigned int (*pfn_unf_receive_gs_pkg)(void *v_lport,
struct unf_frame_pkg_s *v_pkg);
/* input para:L_Port, FRAME_PKG_S */
unsigned int (*pfn_unf_receive_bls_pkg)(void *v_lport,
struct unf_frame_pkg_s *v_pkg);
/* input para:L_Port, FRAME_PKG_S */
unsigned int (*pfn_unf_receive_fc4_ls_pkg)(
void *v_lport,
struct unf_frame_pkg_s *v_pkg);
/* input para:L_Port, FRAME_PKG_S */
unsigned int (*pfn_unf_send_els_done)(void *v_lport,
struct unf_frame_pkg_s *v_pkg);
unsigned int (*pfn_unf_send_fc4_ls_done)(void *v_lport,
struct unf_frame_pkg_s *v_pkg);
/* input para:L_Port, FRAME_PKG_S */
unsigned int (*pfn_unf_receive_marker_status)(
void *v_lport, struct unf_frame_pkg_s *v_pkg);
unsigned int (*pfn_unf_receive_abts_marker_status)(
void *v_lport, struct unf_frame_pkg_s *v_pkg);
/* input para:L_Port, FRAME_PKG_S */
unsigned int (*pfn_unf_receive_ini_rsponse)(
void *v_lport, struct unf_frame_pkg_s *v_pkg);
int (*pfn_unf_get_cfg_parms)(char *v_section_name,
struct unf_cfg_item_s *v_cfg_parm,
unsigned int *v_cfg_value,
unsigned int v_item_num);
unsigned int (*pfn_unf_cm_get_sgl_entry)(void *v_pkg,
char **v_buf,
unsigned int *v_buf_len);
unsigned int (*pfn_unf_cm_get_dif_sgl_entry)(void *v_pkg,
char **v_buf,
unsigned int *v_buf_len);
struct unf_esgl_page_s *(*pfn_unf_get_one_free_esgl_page)(
void *v_lport, struct unf_frame_pkg_s *v_pkg);
/* input para:L_Port, EVENT */
unsigned int (*pfn_unf_fc_port_link_event)(void *v_lport,
unsigned int v_events,
void *v_input);
unsigned int (*pfn_unf_fcoe_update_fcf_name)(void *v_lport,
void *v_input);
int (*pfn_unf_ioctl_to_com_handler)(void *v_lport,
struct unf_hinicam_pkg *v_pkg);
};
unsigned int unf_get_cm_handle_op(struct unf_cm_handle_op_s *v_cm_handle);
int unf_common_init(void);
void unf_common_exit(void);
struct unf_port_info_entry_s {
unsigned int bb_scn;
unsigned int speed;
unsigned int topo;
unsigned int fec;
};
enum drv_cable_connector_type_e {
DRV_CABLE_CONNECTOR_NONE,
DRV_CABLE_CONNECTOR_OPTICAL,
DRV_CABLE_CONNECTOR_COPPER,
DRV_CABLE_CONNECTOR_INVALID,
DRV_CABLE_CONNECTOR_BUTT
};
#endif
// SPDX-License-Identifier: GPL-2.0
/* Huawei Fabric Channel Linux driver
* Copyright(c) 2018 Huawei Technologies Co., Ltd
*
*/
#include "unf_log.h"
#include "unf_event.h"
#include "unf_exchg.h"
#include "unf_portman.h"
#include "unf_rport.h"
#include "unf_service.h"
#include "unf_io.h"
#define RPORT_FEATURE_POOL_SIZE 4096
static struct unf_esgl_page_s *unf_cm_get_one_free_esgl_page(
void *v_lport,
struct unf_frame_pkg_s *v_fra_pkg);
static unsigned int unf_recv_tmf_marker_status(
void *v_lport,
struct unf_frame_pkg_s *v_fra_pkg);
static unsigned int unf_recv_abts_mrker_status(
void *v_lport,
struct unf_frame_pkg_s *v_fra_pkg);
static int unf_get_cfg_parms(char *v_section_name,
struct unf_cfg_item_s *v_cfg_parm,
unsigned int *v_cfg_value,
unsigned int v_item_num);
/* global variables */
unsigned int event_thread_exit;
struct task_struct *event_thread;
struct completion *fc_event_handle_thd_comp;
struct workqueue_struct *unf_work_queue;
struct unf_global_card_thread_s card_thread_mgr;
unsigned int unf_dbg_level = UNF_MAJOR;
unsigned int log_print_level = UNF_INFO;
unsigned int log_limted_times = UNF_LOGIN_ATT_PRINT_TIMES;
struct unf_cm_handle_op_s cm_low_levle_handle = {
.pfn_unf_alloc_local_port = unf_lport_create_and_init,
.pfn_unf_release_local_port = unf_release_local_port,
.pfn_unf_receive_els_pkg = unf_receive_els_pkg,
.pfn_unf_receive_gs_pkg = unf_receive_gs_pkg,
.pfn_unf_receive_bls_pkg = unf_receive_bls_pkg,
.pfn_unf_send_els_done = unf_send_els_done,
.pfn_unf_receive_ini_rsponse = unf_ini_scsi_completed,
.pfn_unf_get_cfg_parms = unf_get_cfg_parms,
.pfn_unf_receive_marker_status = unf_recv_tmf_marker_status,
.pfn_unf_receive_abts_marker_status = unf_recv_abts_mrker_status,
.pfn_unf_cm_get_sgl_entry = unf_ini_get_sgl_entry,
.pfn_unf_cm_get_dif_sgl_entry = unf_ini_get_dif_sgl_entry,
.pfn_unf_get_one_free_esgl_page = unf_cm_get_one_free_esgl_page,
.pfn_unf_fc_port_link_event = unf_fc_port_link_event,
.pfn_unf_ioctl_to_com_handler = unf_cmd_adm_handler,
};
static struct unf_esgl_page_s *unf_cm_get_one_free_esgl_page(
void *v_lport,
struct unf_frame_pkg_s *v_fra_pkg)
{
struct unf_lport_s *lport = NULL;
struct unf_xchg_s *xchg = NULL;
UNF_CHECK_VALID(0x1700, 1, v_lport, return NULL);
UNF_CHECK_VALID(0x1701, 1, v_fra_pkg, return NULL);
lport = (struct unf_lport_s *)v_lport;
xchg = (struct unf_xchg_s *)v_fra_pkg->xchg_contex;
return unf_get_one_free_esgl_page(lport, xchg); /* from esgl pool */
}
static int unf_get_cfg_parms(char *v_section_name,
struct unf_cfg_item_s *v_cfg_parm,
unsigned int *v_cfg_value,
unsigned int v_item_num)
{
/* Maximum length of a configuration item value,
* including the end character
*/
#define UNF_MAX_ITEM_VALUE_LEN (256)
unsigned int *value = NULL;
struct unf_cfg_item_s *cfg_parm = NULL;
unsigned int i = 0;
cfg_parm = v_cfg_parm;
value = v_cfg_value;
for (i = 0; i < v_item_num; i++) {
if (!cfg_parm || !value) {
UNF_TRACE(UNF_EVTLOG_DRIVER_ERR,
UNF_LOG_REG_ATT, UNF_ERR,
"[err]Config name or value is NULL");
return UNF_RETURN_ERROR;
}
if (strcmp("End", cfg_parm->name) == 0)
break;
if (strcmp("fw_path", cfg_parm->name) == 0) {
cfg_parm++;
value += UNF_MAX_ITEM_VALUE_LEN / sizeof(unsigned int);
continue;
}
*value = cfg_parm->default_value;
cfg_parm++;
value++;
}
return RETURN_OK;
}
static unsigned int unf_recv_tmf_marker_status(
void *v_lport,
struct unf_frame_pkg_s *v_fra_pkg)
{
struct unf_lport_s *lport = NULL;
struct unf_xchg_s *xchg = NULL;
unsigned short hot_pool_tag = 0;
UNF_CHECK_VALID(0x3543, UNF_TRUE, v_lport, return UNF_RETURN_ERROR);
UNF_CHECK_VALID(0x3544, UNF_TRUE, v_fra_pkg, return UNF_RETURN_ERROR);
lport = (struct unf_lport_s *)v_lport;
/* Find exchange which point to marker sts */
if (!lport->xchg_mgr_temp.pfn_unf_look_up_xchg_by_tag) {
UNF_TRACE(UNF_EVTLOG_DRIVER_ERR, UNF_LOG_LOGIN_ATT, UNF_ERR,
"[err]Port(0x%x) tag function is NULL",
lport->port_id);
return UNF_RETURN_ERROR;
}
hot_pool_tag = (unsigned short)
(v_fra_pkg->private[PKG_PRIVATE_XCHG_HOT_POOL_INDEX]);
xchg = (struct unf_xchg_s *)
(lport->xchg_mgr_temp.pfn_unf_look_up_xchg_by_tag((void *)lport,
hot_pool_tag));
if (!xchg) {
UNF_TRACE(UNF_EVTLOG_DRIVER_WARN, UNF_LOG_LOGIN_ATT, UNF_WARN,
"[warn]Port(0x%x_0x%x) find exchange by tag(0x%x) failed",
lport->port_id, lport->nport_id, hot_pool_tag);
return UNF_RETURN_ERROR;
}
/*
* NOTE: set exchange TMF state with MARKER_STS_RECEIVED
*
* About TMF state
* 1. STS received
* 2. Response received
* 3. Do check if necessary
*/
xchg->tmf_state |= MARKER_STS_RECEIVED;
UNF_TRACE(UNF_EVTLOG_DRIVER_INFO, UNF_LOG_IO_ATT, UNF_MAJOR,
"[info]Marker STS: D_ID(0x%x) S_ID(0x%x) OX_ID(0x%x) RX_ID(0x%x), EXCH: D_ID(0x%x) S_ID(0x%x) OX_ID(0x%x) RX_ID(0x%x)",
v_fra_pkg->frame_head.rctl_did & UNF_NPORTID_MASK,
v_fra_pkg->frame_head.csctl_sid & UNF_NPORTID_MASK,
(unsigned short)(v_fra_pkg->frame_head.oxid_rxid >> 16),
(unsigned short)(v_fra_pkg->frame_head.oxid_rxid),
xchg->did,
xchg->sid,
xchg->ox_id,
xchg->rx_id);
return RETURN_OK;
}
static unsigned int unf_recv_abts_mrker_status(
void *v_lport,
struct unf_frame_pkg_s *v_fra_pkg)
{
struct unf_lport_s *lport = NULL;
struct unf_xchg_s *xchg = NULL;
unsigned short hot_pool_tag = 0;
unsigned long flags = 0;
UNF_CHECK_VALID(0x3543, UNF_TRUE, v_lport, return UNF_RETURN_ERROR);
UNF_CHECK_VALID(0x3544, UNF_TRUE, v_fra_pkg, return UNF_RETURN_ERROR);
lport = (struct unf_lport_s *)v_lport;
/* Find exchange by tag */
if (!lport->xchg_mgr_temp.pfn_unf_look_up_xchg_by_tag) {
UNF_TRACE(UNF_EVTLOG_DRIVER_ERR, UNF_LOG_LOGIN_ATT, UNF_ERR,
"[err]Port(0x%x) tag function is NULL",
lport->port_id);
return UNF_RETURN_ERROR;
}
hot_pool_tag = (unsigned short)
(v_fra_pkg->private[PKG_PRIVATE_XCHG_HOT_POOL_INDEX]);
xchg = (struct unf_xchg_s *)
(lport->xchg_mgr_temp.pfn_unf_look_up_xchg_by_tag((void *)lport,
hot_pool_tag));
if (!xchg) {
UNF_TRACE(UNF_EVTLOG_DRIVER_WARN, UNF_LOG_LOGIN_ATT, UNF_WARN,
"[warn]Port(0x%x_0x%x) find exchange by tag(0x%x) failed",
lport->port_id, lport->nport_id, hot_pool_tag);
return UNF_RETURN_ERROR;
}
/*
* NOTE: set exchange ABTS state with MARKER_STS_RECEIVED
*
* About exchange ABTS state
* 1. STS received
* 2. Response received
* 3. Do check if necessary
*
* About Exchange status get from low level
* 1. Set: when RCVD ABTS Marker
* 2. Set: when RCVD ABTS Req Done
* 3. value: set value with pkg->status
*/
spin_lock_irqsave(&xchg->xchg_state_lock, flags);
xchg->ucode_abts_state = v_fra_pkg->status;
xchg->abts_state |= MARKER_STS_RECEIVED;
UNF_TRACE(UNF_EVTLOG_DRIVER_INFO, UNF_LOG_LOGIN_ATT, UNF_KEVENT,
"[info]Port(0x%x) wake up SEMA for Abts marker exchange(0x%p) oxid(0x%x 0x%x) status(0x%x)",
lport->port_id, xchg, xchg->ox_id, xchg->hot_pool_tag,
v_fra_pkg->abts_maker_status);
/*
* NOTE: Second time for ABTS marker received, or
* ABTS response have been received, no need to wake up sema
*/
if ((xchg->io_state & INI_IO_STATE_ABORT_TIMEOUT) ||
(xchg->abts_state & ABTS_RESPONSE_RECEIVED)) {
spin_unlock_irqrestore(&xchg->xchg_state_lock, flags);
UNF_TRACE(UNF_EVTLOG_DRIVER_INFO, UNF_LOG_LOGIN_ATT,
UNF_KEVENT,
"[info]Port(0x%x) no need to wake up SEMA for Abts marker ABTS_STATE(0x%x) IO_STATE(0x%x)",
lport->port_id, xchg->abts_state,
xchg->io_state);
return RETURN_OK;
}
if (xchg->io_state & INI_IO_STATE_TMF_ABORT) {
spin_unlock_irqrestore(&xchg->xchg_state_lock, flags);
UNF_TRACE(UNF_EVTLOG_DRIVER_INFO, UNF_LOG_LOGIN_ATT,
UNF_KEVENT,
"[info]Port(0x%x) receive Abts marker, exchange(%p) state(0x%x) free it",
lport->port_id, xchg, xchg->io_state);
unf_cm_free_xchg(lport, xchg);
} else {
spin_unlock_irqrestore(&xchg->xchg_state_lock, flags);
up(&xchg->task_sema);
}
return RETURN_OK;
}
unsigned int unf_get_cm_handle_op(struct unf_cm_handle_op_s *v_cm_handle)
{
UNF_CHECK_VALID(0x1708, UNF_TRUE, v_cm_handle,
return UNF_RETURN_ERROR);
memcpy(v_cm_handle, &cm_low_levle_handle,
sizeof(struct unf_cm_handle_op_s));
return RETURN_OK;
}
static void unf_uninit_cm_low_level_handle(void)
{
memset(&cm_low_levle_handle, 0, sizeof(struct unf_cm_handle_op_s));
}
int unf_event_process(void *v_arg)
{
struct list_head *node = NULL;
struct unf_cm_event_report *event_node = NULL;
unsigned long flags = 0;
UNF_REFERNCE_VAR(v_arg);
set_user_nice(current, 4);
recalc_sigpending();
UNF_TRACE(UNF_EVTLOG_DRIVER_INFO, UNF_LOG_REG_ATT, UNF_INFO,
"[event]Enter event thread");
complete(fc_event_handle_thd_comp);
do {
spin_lock_irqsave(&fc_event_list.fc_eventlist_lock, flags);
if (list_empty(&fc_event_list.list_head) == UNF_TRUE) {
spin_unlock_irqrestore(&fc_event_list.fc_eventlist_lock,
flags);
set_current_state(TASK_INTERRUPTIBLE);
schedule_timeout((long)msecs_to_jiffies(1000));
} else {
node = (&fc_event_list.list_head)->next;
list_del_init(node);
fc_event_list.list_num--;
event_node = list_entry(node,
struct unf_cm_event_report,
list_entry);
spin_unlock_irqrestore(&fc_event_list.fc_eventlist_lock,
flags);
/* Process event node */
unf_handle_event(event_node);
}
} while (!event_thread_exit);
complete_and_exit(fc_event_handle_thd_comp, 0);
UNF_TRACE(UNF_EVTLOG_DRIVER_INFO, UNF_LOG_EVENT, UNF_MAJOR,
"[event]Event thread exit");
return RETURN_OK;
}
static unsigned int unf_creat_event_center(void)
{
struct completion fc_event_completion =
COMPLETION_INITIALIZER(fc_event_completion);
struct completion *p_fc_event_completion = &fc_event_completion;
INIT_LIST_HEAD(&fc_event_list.list_head);
fc_event_list.list_num = 0;
spin_lock_init(&fc_event_list.fc_eventlist_lock);
fc_event_handle_thd_comp = p_fc_event_completion;
event_thread = kthread_run(unf_event_process, NULL, "hifc_event");
if (IS_ERR(event_thread)) {
complete_and_exit(fc_event_handle_thd_comp, 0);
fc_event_handle_thd_comp = NULL;
UNF_TRACE(UNF_EVTLOG_DRIVER_ERR, UNF_LOG_REG_ATT, UNF_ERR,
"[err]Create event thread failed(0x%p)",
event_thread);
return UNF_RETURN_ERROR;
}
wait_for_completion(fc_event_handle_thd_comp);
return RETURN_OK;
}
static void unf_cm_event_thread_exit(void)
{
struct completion fc_event_completion =
COMPLETION_INITIALIZER(fc_event_completion);
struct completion *p_fc_event_completion = &fc_event_completion;
fc_event_handle_thd_comp = p_fc_event_completion;
event_thread_exit = 1;
wake_up_process(event_thread);
wait_for_completion(fc_event_handle_thd_comp);
fc_event_handle_thd_comp = NULL;
}
static void unf_cm_cread_card_mgr_list(void)
{
/* So far, do not care */
INIT_LIST_HEAD(&card_thread_mgr.list_card_list_head);
spin_lock_init(&card_thread_mgr.global_card_list_lock);
card_thread_mgr.card_sum = 0;
}
static int unf_port_feature_pool_init(void)
{
unsigned int i = 0;
unsigned int rport_fea_pool_size = 0;
struct unf_rport_feature_recard_s *rport_fea_recard = NULL;
unsigned long flags = 0;
rport_fea_pool_size = sizeof(struct unf_rport_feature_pool_s);
port_fea_pool = vmalloc(rport_fea_pool_size);
if (!port_fea_pool) {
UNF_TRACE(UNF_EVTLOG_DRIVER_ERR, UNF_LOG_REG_ATT, UNF_ERR,
"[err]cannot allocate rport feature pool");
return UNF_RETURN_ERROR;
}
memset(port_fea_pool, 0, rport_fea_pool_size);
spin_lock_init(&port_fea_pool->port_fea_pool_lock);
INIT_LIST_HEAD(&port_fea_pool->list_busy_head);
INIT_LIST_HEAD(&port_fea_pool->list_free_head);
port_fea_pool->p_port_feature_pool_addr =
vmalloc((size_t)(RPORT_FEATURE_POOL_SIZE *
sizeof(struct unf_rport_feature_recard_s)));
if (!port_fea_pool->p_port_feature_pool_addr) {
UNF_TRACE(UNF_EVTLOG_DRIVER_ERR, UNF_LOG_REG_ATT, UNF_ERR,
"[err]cannot allocate rport feature pool address");
vfree(port_fea_pool);
port_fea_pool = NULL;
return UNF_RETURN_ERROR;
}
memset(port_fea_pool->p_port_feature_pool_addr, 0,
sizeof(struct unf_rport_feature_recard_s) *
RPORT_FEATURE_POOL_SIZE);
rport_fea_recard =
(struct unf_rport_feature_recard_s *)
port_fea_pool->p_port_feature_pool_addr;
spin_lock_irqsave(&port_fea_pool->port_fea_pool_lock, flags);
for (i = 0; i < RPORT_FEATURE_POOL_SIZE; i++) {
list_add_tail(&rport_fea_recard->entry_feature,
&port_fea_pool->list_free_head);
rport_fea_recard++;
}
spin_unlock_irqrestore(&port_fea_pool->port_fea_pool_lock, flags);
return RETURN_OK;
}
void unf_free_port_feature_pool(void)
{
if (port_fea_pool->p_port_feature_pool_addr) {
vfree(port_fea_pool->p_port_feature_pool_addr);
port_fea_pool->p_port_feature_pool_addr = NULL;
}
vfree(port_fea_pool);
port_fea_pool = NULL;
}
int unf_common_init(void)
{
int ret = RETURN_OK;
unf_dbg_level = UNF_MAJOR;
log_print_level = UNF_KEVENT;
UNF_TRACE(UNF_EVTLOG_DRIVER_INFO, UNF_LOG_REG_ATT, UNF_KEVENT,
"UNF Driver Version:%s.", UNF_FC_VERSION);
UNF_TRACE(UNF_EVTLOG_DRIVER_INFO, UNF_LOG_REG_ATT, UNF_KEVENT,
"UNF Compile Time: %s", __TIME_STR__);
ret = unf_port_feature_pool_init();
if (ret != RETURN_OK) {
UNF_TRACE(UNF_EVTLOG_DRIVER_ERR, UNF_LOG_REG_ATT, UNF_ERR,
"[err]Port Feature Pool init failed");
return ret;
}
/* 1. Init Transport */
ret = (int)unf_register_ini_transport();
if (ret != RETURN_OK) {
UNF_TRACE(UNF_EVTLOG_DRIVER_ERR, UNF_LOG_REG_ATT, UNF_ERR,
"[err]INI interface init failed");
unf_free_port_feature_pool();
return ret;
}
/* 2. Init L_Port MG: Y */
unf_port_mgmt_init();
/* 3. Init card MG list: N */
unf_cm_cread_card_mgr_list();
/* 4. Init global event resource: N */
ret = (int)unf_init_global_event_msg();
if (ret != RETURN_OK) {
unf_unregister_ini_transport();
unf_free_port_feature_pool();
UNF_TRACE(UNF_EVTLOG_DRIVER_ERR, UNF_LOG_REG_ATT, UNF_ERR,
"[err]Create global event center failed");
return ret;
}
/* 5. Create event center(one thread per pf): Y */
ret = (int)unf_creat_event_center();
if (ret != RETURN_OK) {
unf_destroy_global_event_msg();
unf_unregister_ini_transport();
unf_free_port_feature_pool();
fc_event_handle_thd_comp = NULL;
UNF_TRACE(UNF_EVTLOG_DRIVER_ERR, UNF_LOG_REG_ATT, UNF_ERR,
"[err]Create event center (thread) failed");
return ret;
}
/* 6. Create work queue: Y */
unf_work_queue = create_workqueue("unf_wq");
if (!unf_work_queue) {
/* event thread exist */
unf_cm_event_thread_exit();
unf_destroy_global_event_msg();
fc_event_handle_thd_comp = NULL;
unf_unregister_ini_transport();
unf_free_port_feature_pool();
UNF_TRACE(UNF_EVTLOG_DRIVER_ERR, UNF_LOG_REG_ATT, UNF_ERR,
"[err]Create work queue failed");
return UNF_RETURN_ERROR;
}
UNF_TRACE(UNF_EVTLOG_DRIVER_INFO, UNF_LOG_REG_ATT, UNF_MAJOR,
"[info]Init common layer succeed");
return ret;
}
static void unf_destroy_dirty_port(void)
{
unsigned int v_ditry_port_num = 0;
unf_show_dirty_port(UNF_FALSE, &v_ditry_port_num);
UNF_TRACE(UNF_EVTLOG_DRIVER_INFO, UNF_LOG_REG_ATT, UNF_MAJOR,
"[info]Sys has %d dirty L_Port(s)", v_ditry_port_num);
}
void unf_common_exit(void)
{
unf_free_port_feature_pool();
unf_destroy_dirty_port();
flush_workqueue(unf_work_queue);
destroy_workqueue(unf_work_queue);
unf_work_queue = NULL;
unf_cm_event_thread_exit();
unf_destroy_global_event_msg();
unf_uninit_cm_low_level_handle();
unf_port_mgmt_deinit();
unf_unregister_ini_transport();
UNF_TRACE(UNF_EVTLOG_DRIVER_INFO, UNF_LOG_REG_ATT, UNF_KEVENT,
"[info]HIFC module remove succeed");
}
/* SPDX-License-Identifier: GPL-2.0 */
/* Huawei Hifc PCI Express Linux driver
* Copyright(c) 2017 Huawei Technologies Co., Ltd
*
*/
#ifndef __UNF_LOG_H__
#define __UNF_LOG_H__
#define UNF_CRITICAL 1
#define UNF_ERR 2
#define UNF_WARN 3
#define UNF_KEVENT 4
#define UNF_MAJOR 5
#define UNF_MINOR 6
#define UNF_INFO 7
#define UNF_DATA 7
#define UNF_ALL 7
enum unf_debug_type_e {
UNF_DEBUG_TYPE_MML = 0,
UNF_DEBUG_TYPE_DIAGNOSE = 1,
UNF_DEBUG_TYPE_MESSAGE = 2,
UNF_DEBUG_TYPE_BUTT
};
enum unf_log_attr_e {
UNF_LOG_LOGIN_ATT = 0x1,
UNF_LOG_IO_ATT = 0x2,
UNF_LOG_EQUIP_ATT = 0x4,
UNF_LOG_REG_ATT = 0x8,
UNF_LOG_REG_MML_TEST = 0x10,
UNF_LOG_EVENT = 0x20,
UNF_LOG_NORMAL = 0x40,
UNF_LOG_ABNORMAL = 0X80,
UNF_LOG_BUTT
};
enum event_log_e {
UNF_EVTLOG_DRIVER_SUC = 0,
UNF_EVTLOG_DRIVER_INFO,
UNF_EVTLOG_DRIVER_WARN,
UNF_EVTLOG_DRIVER_ERR,
UNF_EVTLOG_LINK_SUC,
UNF_EVTLOG_LINK_INFO,
UNF_EVTLOG_LINK_WARN,
UNF_EVTLOG_LINK_ERR,
UNF_EVTLOG_IO_SUC,
UNF_EVTLOG_IO_INFO,
UNF_EVTLOG_IO_WARN,
UNF_EVTLOG_IO_ERR,
UNF_EVTLOG_TOOL_SUC,
UNF_EVTLOG_TOOL_INFO,
UNF_EVTLOG_TOOL_WARN,
UNF_EVTLOG_TOOL_ERR,
UNF_EVTLOG_BUT
};
#define UNF_IO_ATT_PRINT_TIMES 2
#define UNF_LOGIN_ATT_PRINT_TIMES 100
#define UNF_IO_ATT_PRINT_LIMIT msecs_to_jiffies(2 * 1000)
extern unsigned int unf_dbg_level;
extern unsigned int log_print_level;
extern unsigned int log_limted_times;
#define DRV_LOG_LIMIT(module_id, log_level, log_id, log_att, format, ...) \
do { \
static unsigned long pre; \
static int should_print = UNF_LOGIN_ATT_PRINT_TIMES; \
if (time_after_eq(jiffies, pre + (UNF_IO_ATT_PRINT_LIMIT))) { \
if (log_att == UNF_LOG_ABNORMAL) { \
should_print = UNF_IO_ATT_PRINT_TIMES; \
} else { \
should_print = log_limted_times; \
} \
} \
if (should_print < 0) { \
if (log_att != UNF_LOG_ABNORMAL) { \
pre = jiffies; \
} \
break; \
} \
if (should_print-- > 0) { \
printk(log_level \
"[%d][FC_UNF]" format "[%s][%-5d]\n", \
smp_processor_id(), ##__VA_ARGS__, \
__func__, __LINE__); \
} \
if (should_print == 0) { \
printk(log_level \
"[FC_UNF]log is limited[%s][%-5d]\n", \
__func__, __LINE__); \
} \
pre = jiffies; \
} while (0)
#define UNF_CHECK_VALID(logid, need_check, condition, fail_do) \
do { \
if (unlikely(!(condition))) { \
UNF_TRACE((logid), UNF_LOG_REG_ATT, UNF_ERR, \
"Para check(%s) invalid", #condition); \
fail_do; \
} \
} while (0)
#define HIUNF_TRACE(log_id, log_att, log_level, format, ...) \
do { \
if (unlikely((log_level) <= log_print_level)) { \
if (log_level == UNF_CRITICAL) { \
DRV_LOG_LIMIT(UNF_PID, KERN_CRIT, log_id, \
log_att, format, ##__VA_ARGS__); \
} else if (log_level == UNF_WARN) { \
DRV_LOG_LIMIT(UNF_PID, KERN_WARNING, log_id, \
log_att, format, ##__VA_ARGS__); \
} else if (log_level == UNF_ERR) { \
DRV_LOG_LIMIT(UNF_PID, KERN_ERR, log_id, \
log_att, format, ##__VA_ARGS__); \
} else if (log_level == UNF_MAJOR || \
log_level == UNF_MINOR || \
log_level == UNF_KEVENT) { \
DRV_LOG_LIMIT(UNF_PID, KERN_NOTICE, log_id, \
log_att, format, ##__VA_ARGS__); \
} else if (log_level == UNF_INFO || \
log_level == UNF_DATA) { \
DRV_LOG_LIMIT(UNF_PID, KERN_INFO, log_id, \
log_att, format, ##__VA_ARGS__); \
} \
} \
} while (0)
#define UNF_TRACE(log_id, log_att, log_level, fmt, ...) \
do { \
HIUNF_TRACE(log_id, log_att, log_level, fmt, ##__VA_ARGS__); \
} while (0)
#define UNF_INIT_PRIVATE_ST(private_st) \
do { \
memset(&(private_st), 0, sizeof(private_st)); \
} while (0)
#define UNF_PRINT_SFS(dbg_level, portid, v_data, v_size) \
do { \
if ((dbg_level) <= log_print_level) { \
unsigned int cnt = 0; \
printk(KERN_INFO "[INFO]Port(0x%x) sfs:0x", \
(portid)); \
for (cnt = 0; cnt < (v_size) / 4; cnt++) { \
printk(KERN_INFO "%08x ", \
((unsigned int *)v_data)[cnt]); \
} \
printk(KERN_INFO "[FC_UNF][%s]\n", __FUNCTION__); \
} \
} while (0)
#define UNF_PRINT_SFS_LIMIT(dbg_level, portid, v_data, v_size) \
do { \
if ((dbg_level) <= log_print_level) { \
static unsigned long pre; \
static int should_print = UNF_LOGIN_ATT_PRINT_TIMES; \
if (time_after_eq(jiffies, pre + \
UNF_IO_ATT_PRINT_LIMIT)) { \
should_print = log_limted_times; \
} \
if (should_print < 0) { \
pre = jiffies; \
break; \
} \
if (should_print-- > 0) { \
UNF_PRINT_SFS(dbg_level, portid, \
v_data, v_size); \
} \
if (should_print == 0) { \
printk(KERN_INFO "[FC_UNF]sfs log is limited[%s][%-5d]\n", \
__func__, __LINE__); \
} \
pre = jiffies; \
} \
} while (0)
#define UNF_REFERNCE_VAR(var)
#endif
// SPDX-License-Identifier: GPL-2.0
/* Huawei Hifc PCI Express Linux driver
* Copyright(c) 2017 Huawei Technologies Co., Ltd
*
*/
#include "unf_log.h"
#include "unf_scsi_common.h"
#include "unf_lport.h"
#include "unf_rport.h"
#include "unf_portman.h"
#include "unf_npiv.h"
#include "unf_exchg.h"
#include "unf_io.h"
static int unf_scsi_queue_cmd(struct Scsi_Host *shost,
struct scsi_cmnd *v_cmnd);
static int unf_scsi_abort_scsi_cmnd(struct scsi_cmnd *v_cmnd);
static int unf_scsi_device_reset_handler(struct scsi_cmnd *v_cmnd);
static int unf_scsi_bus_reset_handler(struct scsi_cmnd *v_cmnd);
static int unf_scsi_target_reset_handler(struct scsi_cmnd *v_cmnd);
static int unf_scsi_slave_alloc(struct scsi_device *sdev);
static void unf_scsi_destroy_slave(struct scsi_device *sdev);
static int unf_scsi_slave_configure(struct scsi_device *sdev);
static int unf_scsi_scan_finished(struct Scsi_Host *shost, unsigned long time);
static void unf_scsi_scan_start(struct Scsi_Host *shost);
static struct scsi_transport_template *scsi_transport_template;
static struct scsi_transport_template *scsi_transport_template_v;
struct unf_ini_error_code_s ini_error_code_table1[] = {
{ UNF_IO_SUCCESS, UNF_SCSI_HOST(DID_OK) },
{ UNF_IO_ABORTED, UNF_SCSI_HOST(DID_ABORT) },
{ UNF_IO_FAILED, UNF_SCSI_HOST(DID_ERROR) },
{ UNF_IO_ABORT_ABTS, UNF_SCSI_HOST(DID_ERROR) },
{ UNF_IO_ABORT_LOGIN, UNF_SCSI_HOST(DID_NO_CONNECT) },
{ UNF_IO_ABORT_REET, UNF_SCSI_HOST(DID_RESET) },
{ UNF_IO_ABORT_FAILED, UNF_SCSI_HOST(DID_ERROR) },
{ UNF_IO_OUTOF_ORDER, UNF_SCSI_HOST(DID_ERROR) },
{ UNF_IO_FTO, UNF_SCSI_HOST(DID_TIME_OUT) },
{ UNF_IO_LINK_FAILURE, UNF_SCSI_HOST(DID_ERROR) },
{ UNF_IO_OVER_FLOW, UNF_SCSI_HOST(DID_ERROR) },
{ UNF_IO_RSP_OVER, UNF_SCSI_HOST(DID_ERROR) },
{ UNF_IO_LOST_FRAME, UNF_SCSI_HOST(DID_ERROR) },
{ UNF_IO_UNDER_FLOW, UNF_SCSI_HOST(DID_OK) },
{ UNF_IO_HOST_PROG_ERROR, UNF_SCSI_HOST(DID_ERROR) },
{ UNF_IO_SEST_PROG_ERROR, UNF_SCSI_HOST(DID_ERROR) },
{ UNF_IO_INVALID_ENTRY, UNF_SCSI_HOST(DID_ERROR) },
{ UNF_IO_ABORT_SEQ_NOT, UNF_SCSI_HOST(DID_ERROR) },
{ UNF_IO_REJECT, UNF_SCSI_HOST(DID_ERROR) },
{ UNF_IO_EDC_IN_ERROR, UNF_SCSI_HOST(DID_ERROR) },
{ UNF_IO_EDC_OUT_ERROR, UNF_SCSI_HOST(DID_ERROR) },
{ UNF_IO_UNINIT_KEK_ERR, UNF_SCSI_HOST(DID_ERROR) },
{ UNF_IO_DEK_OUTOF_RANGE, UNF_SCSI_HOST(DID_ERROR) },
{ UNF_IO_KEY_UNWRAP_ERR, UNF_SCSI_HOST(DID_ERROR) },
{ UNF_IO_KEY_TAG_ERR, UNF_SCSI_HOST(DID_ERROR) },
{ UNF_IO_KEY_ECC_ERR, UNF_SCSI_HOST(DID_ERROR) },
{ UNF_IO_BLOCK_SIZE_ERROR, UNF_SCSI_HOST(DID_ERROR) },
{ UNF_IO_ILLEGAL_CIPHER_MODE, UNF_SCSI_HOST(DID_ERROR) },
{ UNF_IO_CLEAN_UP, UNF_SCSI_HOST(DID_ERROR) },
{ UNF_IO_ABORTED_BY_TARGET, UNF_SCSI_HOST(DID_ERROR) },
{ UNF_IO_TRANSPORT_ERROR, UNF_SCSI_HOST(DID_ERROR) },
{ UNF_IO_LINK_FLASH, UNF_SCSI_HOST(DID_NO_CONNECT) },
{ UNF_IO_TIMEOUT, UNF_SCSI_HOST(DID_TIME_OUT) },
{ UNF_IO_DMA_ERROR, UNF_SCSI_HOST(DID_ERROR) },
{ UNF_IO_NO_LPORT, UNF_SCSI_HOST(DID_NO_CONNECT) },
{ UNF_IO_NO_XCHG, UNF_SCSI_HOST(DID_SOFT_ERROR) },
{ UNF_IO_SOFT_ERR, UNF_SCSI_HOST(DID_SOFT_ERROR) },
{ UNF_IO_PORT_LOGOUT, UNF_SCSI_HOST(DID_NO_CONNECT) },
{ UNF_IO_ERREND, UNF_SCSI_HOST(DID_ERROR) },
{ UNF_IO_DIF_ERROR, (UNF_SCSI_HOST(DID_OK) | UNF_SCSI_STATUS(SCSI_CHECK_CONDITION)) },
{ UNF_IO_INCOMPLETE, UNF_SCSI_HOST(DID_IMM_RETRY) },
{ UNF_IO_DIF_REF_ERROR, (UNF_SCSI_HOST(DID_OK) | UNF_SCSI_STATUS(SCSI_CHECK_CONDITION)) },
{ UNF_IO_DIF_GEN_ERROR, (UNF_SCSI_HOST(DID_OK) | UNF_SCSI_STATUS(SCSI_CHECK_CONDITION)) }
};
unsigned int ini_err_code_table_cnt1 =
sizeof(ini_error_code_table1) / sizeof(struct unf_ini_error_code_s);
static void unf_set_rport_loss_tmo(struct fc_rport *rport,
unsigned int timeout)
{
if (timeout)
rport->dev_loss_tmo = timeout;
else
rport->dev_loss_tmo = 1;
}
static void unf_get_host_port_id(struct Scsi_Host *shost)
{
struct unf_lport_s *lport = NULL;
lport = (struct unf_lport_s *)shost->hostdata[0];
if (unlikely(!lport)) {
UNF_TRACE(0x3808, UNF_LOG_LOGIN_ATT, UNF_ERR,
"[err]Port is null");
return;
}
fc_host_port_id(shost) = lport->port_id;
}
static void unf_get_host_speed(struct Scsi_Host *shost)
{
struct unf_lport_s *lport = NULL;
unsigned int speed = FC_PORTSPEED_UNKNOWN;
lport = (struct unf_lport_s *)shost->hostdata[0];
if (unlikely(!lport)) {
UNF_TRACE(0x3808, UNF_LOG_LOGIN_ATT, UNF_ERR,
"[err]Port is null");
return;
}
switch (lport->speed) {
case UNF_PORT_SPEED_2_G:
speed = FC_PORTSPEED_2GBIT;
break;
case UNF_PORT_SPEED_4_G:
speed = FC_PORTSPEED_4GBIT;
break;
case UNF_PORT_SPEED_8_G:
speed = FC_PORTSPEED_8GBIT;
break;
case UNF_PORT_SPEED_16_G:
speed = FC_PORTSPEED_16GBIT;
break;
case UNF_PORT_SPEED_32_G:
speed = FC_PORTSPEED_32GBIT;
break;
default:
UNF_TRACE(0x3808, UNF_LOG_LOGIN_ATT, UNF_MAJOR,
"[info]Port(0x%x) with unknown speed(0x%x) for FC mode",
lport->port_id, lport->speed);
break;
}
fc_host_speed(shost) = speed;
}
static void unf_get_host_port_type(struct Scsi_Host *shost)
{
struct unf_lport_s *lport = NULL;
unsigned int port_type = FC_PORTTYPE_UNKNOWN;
lport = (struct unf_lport_s *)shost->hostdata[0];
if (unlikely(!lport)) {
UNF_TRACE(0x3808, UNF_LOG_LOGIN_ATT, UNF_ERR,
"[err]Port is null");
return;
}
switch (lport->en_act_topo) {
case UNF_ACT_TOP_PRIVATE_LOOP:
port_type = FC_PORTTYPE_LPORT;
break;
case UNF_ACT_TOP_PUBLIC_LOOP:
port_type = FC_PORTTYPE_NLPORT;
break;
case UNF_ACT_TOP_P2P_DIRECT:
port_type = FC_PORTTYPE_PTP;
break;
case UNF_ACT_TOP_P2P_FABRIC:
port_type = FC_PORTTYPE_NPORT;
break;
default:
UNF_TRACE(0x3808, UNF_LOG_LOGIN_ATT, UNF_MAJOR,
"[info]Port(0x%x) with unknown topo type(0x%x) for FC mode",
lport->port_id, lport->en_act_topo);
break;
}
fc_host_port_type(shost) = port_type;
}
static void unf_get_symbolic_name(struct Scsi_Host *shost)
{
unsigned char *name = NULL;
struct unf_lport_s *lport = NULL;
lport = (struct unf_lport_s *)shost->hostdata[0];
if (unlikely(!lport)) {
UNF_TRACE(0x3808, UNF_LOG_LOGIN_ATT, UNF_ERR,
"[err]Check l_port failed");
return;
}
name = fc_host_symbolic_name(shost);
if (name) {
snprintf(name, FC_SYMBOLIC_NAME_SIZE,
"HIFC_FW_RELEASE:%s HIFC_DRV_RELEASE:%s",
lport->fw_version, UNF_FC_VERSION);
}
}
static void unf_get_host_fabric_name(struct Scsi_Host *shost)
{
struct unf_lport_s *lport = NULL;
lport = (struct unf_lport_s *)shost->hostdata[0];
if (unlikely(!lport)) {
UNF_TRACE(0x3808, UNF_LOG_LOGIN_ATT, UNF_ERR,
"[err]Port is null");
return;
}
fc_host_fabric_name(shost) = lport->fabric_node_name;
}
static void unf_get_host_port_state(struct Scsi_Host *shost)
{
struct unf_lport_s *lport = NULL;
enum fc_port_state port_state;
lport = (struct unf_lport_s *)shost->hostdata[0];
if (unlikely(!lport)) {
UNF_TRACE(0x3808, UNF_LOG_LOGIN_ATT, UNF_ERR,
"[err]Port is null");
return;
}
switch (lport->link_up) {
case UNF_PORT_LINK_DOWN:
port_state = FC_PORTSTATE_OFFLINE;
break;
case UNF_PORT_LINK_UP:
port_state = FC_PORTSTATE_ONLINE;
break;
default:
port_state = FC_PORTSTATE_UNKNOWN;
break;
}
fc_host_port_state(shost) = port_state;
}
static void unf_dev_loss_timeout_callbk(struct fc_rport *rport)
{
/*
* NOTE: about rport->dd_data
* --->>> local SCSI_ID
* 1. Assignment during scsi rport link up
* 2. Released when scsi rport link down & timeout(30s)
* 3. Used during scsi do callback with slave_alloc function
*/
struct Scsi_Host *host = NULL;
struct unf_lport_s *lport = NULL;
unsigned int scsi_id = 0;
if (unlikely(!rport)) {
UNF_TRACE(0x3808, UNF_LOG_LOGIN_ATT, UNF_ERR,
"[err]SCSI rport is null");
return;
}
host = rport_to_shost(rport);
if (unlikely(!host)) {
UNF_TRACE(0x3808, UNF_LOG_LOGIN_ATT, UNF_ERR,
"[err]Host is null");
return;
}
/* according to Local SCSI_ID */
scsi_id = *(unsigned int *)(rport->dd_data);
if (unlikely(scsi_id >= UNF_MAX_SCSI_ID)) {
UNF_TRACE(0x3808, UNF_LOG_LOGIN_ATT, UNF_ERR,
"[err]scsi_id(0x%x) is max than(0x%x)",
scsi_id, UNF_MAX_SCSI_ID);
return;
}
lport = (struct unf_lport_s *)host->hostdata[0];
if (unf_is_lport_valid(lport) == RETURN_OK) {
UNF_TRACE(0x3097, UNF_LOG_LOGIN_ATT, UNF_INFO,
"[event]Port(0x%x_0x%x) RPort scsi_id(0x%x) target_id(0x%x) loss timeout",
lport->port_id, lport->nport_id,
scsi_id, rport->scsi_target_id);
atomic_inc(&lport->session_loss_tmo);
/* Free SCSI ID & set table state with DEAD */
(void)unf_free_scsi_id(lport, scsi_id);
} else {
UNF_TRACE(0x3097, UNF_LOG_LOGIN_ATT, UNF_ERR,
"[err]Port(%p) is invalid", lport);
}
/* reset scsi rport dd_data(local SCSI_ID) */
*((unsigned int *)rport->dd_data) = INVALID_VALUE32;
}
int unf_scsi_create_vport(struct fc_vport *fc_port, bool disabled)
{
struct unf_lport_s *vport = NULL;
struct unf_lport_s *lport = NULL;
struct Scsi_Host *shost = NULL;
struct vport_config_s vport_config = { 0 };
shost = vport_to_shost(fc_port);
lport = (struct unf_lport_s *)shost->hostdata[0];
if (unf_is_lport_valid(lport) != RETURN_OK) {
UNF_TRACE(0x3097, UNF_LOG_LOGIN_ATT, UNF_ERR,
"[err]Port(%p) is invalid", lport);
return RETURN_ERROR;
}
vport_config.port_name = fc_port->port_name;
vport_config.port_mode = fc_port->roles;
vport = unf_create_vport(lport, &vport_config);
if (!vport) {
UNF_TRACE(0x3097, UNF_LOG_LOGIN_ATT, UNF_ERR,
"[err]Port(0x%x) Create Vport failed on lldrive",
lport->port_id);
return RETURN_ERROR;
}
fc_port->dd_data = vport;
vport->vport = fc_port;
return RETURN_OK;
}
int unf_scsi_delete_vport(struct fc_vport *fc_port)
{
int ret = RETURN_ERROR;
struct unf_lport_s *vport = NULL;
vport = (struct unf_lport_s *)fc_port->dd_data;
if (unf_is_lport_valid(vport) != RETURN_OK) {
UNF_TRACE(0x3097, UNF_LOG_LOGIN_ATT, UNF_WARN,
"[warn]VPort(%p) is invalid or is removing",
vport);
fc_port->dd_data = NULL;
return ret;
}
ret = (int)unf_destroy_one_vport(vport);
if (ret != RETURN_OK) {
UNF_TRACE(0x3097, UNF_LOG_LOGIN_ATT, UNF_ERR,
"[err]VPort(0x%x) destroy failed on drive",
vport->port_id);
return ret;
}
fc_port->dd_data = NULL;
return ret;
}
struct fc_function_template function_template = {
.show_host_node_name = 1,
.show_host_port_name = 1,
.show_host_supported_classes = 1,
.show_host_supported_speeds = 1,
.get_host_port_id = unf_get_host_port_id,
.show_host_port_id = 1,
.get_host_speed = unf_get_host_speed,
.show_host_speed = 1,
.get_host_port_type = unf_get_host_port_type,
.show_host_port_type = 1,
.get_host_symbolic_name = unf_get_symbolic_name,
.show_host_symbolic_name = 1,
.set_host_system_hostname = NULL,
.show_host_system_hostname = 1,
.get_host_fabric_name = unf_get_host_fabric_name,
.show_host_fabric_name = 1,
.get_host_port_state = unf_get_host_port_state,
.show_host_port_state = 1,
.dd_fcrport_size = sizeof(void *),
.show_rport_supported_classes = 1,
.get_starget_node_name = NULL,
.show_starget_node_name = 1,
.get_starget_port_name = NULL,
.show_starget_port_name = 1,
.get_starget_port_id = NULL,
.show_starget_port_id = 1,
.set_rport_dev_loss_tmo = unf_set_rport_loss_tmo,
.show_rport_dev_loss_tmo = 0,
.issue_fc_host_lip = NULL,
.dev_loss_tmo_callbk = unf_dev_loss_timeout_callbk,
.terminate_rport_io = NULL,
.get_fc_host_stats = NULL,
.vport_create = unf_scsi_create_vport,
.vport_disable = NULL,
.vport_delete = unf_scsi_delete_vport,
.bsg_request = NULL,
.bsg_timeout = NULL,
};
struct fc_function_template function_template_v = {
.show_host_node_name = 1,
.show_host_port_name = 1,
.show_host_supported_classes = 1,
.show_host_supported_speeds = 1,
.get_host_port_id = unf_get_host_port_id,
.show_host_port_id = 1,
.get_host_speed = unf_get_host_speed,
.show_host_speed = 1,
.get_host_port_type = unf_get_host_port_type,
.show_host_port_type = 1,
.get_host_symbolic_name = unf_get_symbolic_name,
.show_host_symbolic_name = 1,
.set_host_system_hostname = NULL,
.show_host_system_hostname = 1,
.get_host_fabric_name = unf_get_host_fabric_name,
.show_host_fabric_name = 1,
.get_host_port_state = unf_get_host_port_state,
.show_host_port_state = 1,
.dd_fcrport_size = sizeof(void *),
.show_rport_supported_classes = 1,
.get_starget_node_name = NULL,
.show_starget_node_name = 1,
.get_starget_port_name = NULL,
.show_starget_port_name = 1,
.get_starget_port_id = NULL,
.show_starget_port_id = 1,
.set_rport_dev_loss_tmo = unf_set_rport_loss_tmo,
.show_rport_dev_loss_tmo = 1,
.issue_fc_host_lip = NULL,
.dev_loss_tmo_callbk = unf_dev_loss_timeout_callbk,
.terminate_rport_io = NULL,
.get_fc_host_stats = NULL,
.vport_create = NULL,
.vport_disable = NULL,
.vport_delete = NULL,
.bsg_request = NULL,
.bsg_timeout = NULL,
};
struct scsi_host_template scsi_host_template = {
.module = THIS_MODULE,
.name = "HIFC",
.queuecommand = unf_scsi_queue_cmd,
.eh_abort_handler = unf_scsi_abort_scsi_cmnd,
.eh_device_reset_handler = unf_scsi_device_reset_handler,
.eh_target_reset_handler = unf_scsi_target_reset_handler,
.eh_bus_reset_handler = unf_scsi_bus_reset_handler,
.eh_host_reset_handler = NULL,
.slave_configure = unf_scsi_slave_configure,
.slave_alloc = unf_scsi_slave_alloc,
.slave_destroy = unf_scsi_destroy_slave,
.scan_finished = unf_scsi_scan_finished,
.scan_start = unf_scsi_scan_start,
.this_id = -1,
.cmd_per_lun = 3,
.use_clustering = ENABLE_CLUSTERING,
.shost_attrs = NULL,
.sg_tablesize = SG_ALL,
.max_sectors = 0xFFFF,
.supported_mode = MODE_INITIATOR,
};
static void unf_unmap_prot_sgl(struct scsi_cmnd *v_cmnd)
{
struct device *dev;
if ((scsi_get_prot_op(v_cmnd) != SCSI_PROT_NORMAL) &&
hifc_dif_enable && (scsi_prot_sg_count(v_cmnd))) {
dev = v_cmnd->device->host->dma_dev;
dma_unmap_sg(dev, scsi_prot_sglist(v_cmnd),
(int)scsi_prot_sg_count(v_cmnd),
v_cmnd->sc_data_direction);
UNF_TRACE(UNF_EVTLOG_DRIVER_INFO, UNF_LOG_REG_ATT, UNF_INFO,
"scsi done cmd:%p op:%d,difsglcount:%d",
v_cmnd, scsi_get_prot_op(v_cmnd),
scsi_prot_sg_count(v_cmnd));
}
}
void unf_scsi_done(struct unf_scsi_cmd_s *v_scsi_cmnd)
{
struct scsi_cmnd *cmnd = NULL;
UNF_CHECK_VALID(0x509, UNF_TRUE, v_scsi_cmnd, return);
cmnd = (struct scsi_cmnd *)v_scsi_cmnd->upper_cmnd;
UNF_CHECK_VALID(0x510, UNF_TRUE, cmnd, return);
UNF_CHECK_VALID(0x511, UNF_TRUE, cmnd->scsi_done, return);
scsi_set_resid(cmnd, (int)v_scsi_cmnd->resid);
cmnd->result = v_scsi_cmnd->result;
scsi_dma_unmap(cmnd);
unf_unmap_prot_sgl(cmnd);
return cmnd->scsi_done(cmnd);
}
void unf_host_init_attr_setting(unf_scsi_host_s *scsi_host)
{
struct unf_lport_s *lport = NULL;
unsigned int speed = FC_PORTSPEED_UNKNOWN;
lport = (struct unf_lport_s *)scsi_host->hostdata[0];
fc_host_supported_classes(scsi_host) = FC_COS_CLASS3; /* class_3 */
fc_host_dev_loss_tmo(scsi_host) =
(unsigned int)unf_get_link_lose_tmo(lport); /* 30s */
fc_host_node_name(scsi_host) = lport->node_name;
fc_host_port_name(scsi_host) = lport->port_name;
fc_host_max_npiv_vports(scsi_host) =
(unsigned short)((lport == lport->root_lport) ?
lport->low_level_func.support_max_npiv_num : 0);
fc_host_npiv_vports_inuse(scsi_host) = 0;
fc_host_next_vport_number(scsi_host) = 0;
/* About speed mode */
if ((lport->low_level_func.fc_ser_max_speed == UNF_PORT_SPEED_32_G) &&
(lport->card_type == UNF_FC_SERVER_BOARD_32_G)) {
speed = FC_PORTSPEED_32GBIT | FC_PORTSPEED_16GBIT |
FC_PORTSPEED_8GBIT;
} else if ((lport->low_level_func.fc_ser_max_speed ==
UNF_PORT_SPEED_16_G) &&
(lport->card_type == UNF_FC_SERVER_BOARD_16_G)) {
speed = FC_PORTSPEED_16GBIT | FC_PORTSPEED_8GBIT |
FC_PORTSPEED_4GBIT;
} else if ((lport->low_level_func.fc_ser_max_speed ==
UNF_PORT_SPEED_8_G) &&
(lport->card_type == UNF_FC_SERVER_BOARD_8_G)) {
speed = FC_PORTSPEED_8GBIT | FC_PORTSPEED_4GBIT |
FC_PORTSPEED_2GBIT;
}
fc_host_supported_speeds(scsi_host) = speed;
}
int unf_alloc_scsi_host(unf_scsi_host_s **v_scsi_host,
struct unf_host_param_s *v_host_param)
{
int ret = RETURN_ERROR;
struct Scsi_Host *scsi_host = NULL;
struct unf_lport_s *lport = NULL;
UNF_CHECK_VALID(0x512, UNF_TRUE, v_scsi_host, return RETURN_ERROR);
UNF_CHECK_VALID(0x513, UNF_TRUE, v_host_param, return RETURN_ERROR);
UNF_TRACE(0x3808, UNF_LOG_LOGIN_ATT, UNF_MAJOR,
"[event]Alloc scsi host...");
/* Check L_Port validity */
lport = (struct unf_lport_s *)(v_host_param->lport);
if (unlikely(!lport)) {
UNF_TRACE(0x3808, UNF_LOG_LOGIN_ATT, UNF_ERR,
"[err]Port is NULL and return directly");
return RETURN_ERROR;
}
scsi_host_template.can_queue = v_host_param->can_queue;
scsi_host_template.cmd_per_lun = v_host_param->cmnd_per_lun;
scsi_host_template.sg_tablesize = v_host_param->sg_table_size;
scsi_host_template.max_sectors = v_host_param->max_sectors;
/* Alloc scsi host */
scsi_host = scsi_host_alloc(&scsi_host_template,
sizeof(unsigned long long));
if (unlikely(!scsi_host)) {
UNF_TRACE(0x3808, UNF_LOG_LOGIN_ATT, UNF_ERR,
"[err]Register scsi host failed");
return RETURN_ERROR;
}
scsi_host->max_channel = v_host_param->max_channel;
scsi_host->max_lun = v_host_param->max_lun;
scsi_host->max_cmd_len = v_host_param->max_cmnd_len;
scsi_host->unchecked_isa_dma = 0;
scsi_host->hostdata[0] = (unsigned long)lport; /* save L_Port to scsi */
scsi_host->unique_id = scsi_host->host_no;
scsi_host->max_id = v_host_param->max_id;
scsi_host->transportt = (lport == lport->root_lport) ?
scsi_transport_template : scsi_transport_template_v;
/* register DIF/DIX protection */
if (hifc_dif_enable) {
/* Enable DIF and DIX function */
scsi_host_set_prot(scsi_host, hifc_dif_type);
hifc_guard = SHOST_DIX_GUARD_CRC;
/* Enable IP checksum algorithm in DIX */
if (dix_flag)
hifc_guard |= SHOST_DIX_GUARD_IP;
scsi_host_set_guard(scsi_host, hifc_guard);
}
/* Add scsi host */
ret = scsi_add_host(scsi_host, v_host_param->pdev);
if (unlikely(ret)) {
UNF_TRACE(0x3808, UNF_LOG_LOGIN_ATT, UNF_ERR,
"[err]Add scsi host failed with return value %d",
ret);
scsi_host_put(scsi_host);
return RETURN_ERROR;
}
/* Set scsi host attribute */
unf_host_init_attr_setting(scsi_host);
*v_scsi_host = scsi_host;
UNF_TRACE(0x3808, UNF_LOG_LOGIN_ATT, UNF_MAJOR,
"[event]Alloc and add scsi host(0x%llx) succeed",
(unsigned long long)scsi_host);
return RETURN_OK;
}
void unf_free_scsi_host(unf_scsi_host_s *v_scsi_host)
{
struct Scsi_Host *scsi_host = NULL;
scsi_host = v_scsi_host;
fc_remove_host(scsi_host);
scsi_remove_host(scsi_host);
UNF_TRACE(0x3808, UNF_LOG_LOGIN_ATT, UNF_MAJOR,
"[event]Remove scsi host(%d) succeed", scsi_host->host_no);
scsi_host_put(scsi_host);
}
static int unf_get_protect_mode(struct unf_lport_s *lport,
struct scsi_cmnd *v_cmnd,
struct unf_scsi_cmd_s *v_scsi_cmnd)
{
struct scsi_cmnd *cmd = NULL;
int difsegcnt = 0;
struct unf_dif_control_info_s *dif_control_info = NULL;
cmd = v_cmnd;
dif_control_info = &v_scsi_cmnd->dif_control;
switch (scsi_get_prot_op(cmd)) {
/* OS-HBA: Unprotected, HBA-Target: Protected */
case SCSI_PROT_READ_STRIP:
dif_control_info->protect_opcode |=
UNF_DIF_ACTION_VERIFY_AND_DELETE;
break;
case SCSI_PROT_WRITE_INSERT:
dif_control_info->protect_opcode |=
UNF_DIF_ACTION_INSERT;
break;
/* OS-HBA: Protected, HBA-Target: Unprotected */
case SCSI_PROT_READ_INSERT:
dif_control_info->protect_opcode |=
UNF_DIF_ACTION_INSERT;
break;
case SCSI_PROT_WRITE_STRIP:
dif_control_info->protect_opcode |=
UNF_DIF_ACTION_VERIFY_AND_DELETE;
break;
/* OS-HBA: Protected, HBA-Target: Protected */
case SCSI_PROT_READ_PASS:
case SCSI_PROT_WRITE_PASS:
dif_control_info->protect_opcode |=
UNF_DIF_ACTION_VERIFY_AND_FORWARD;
break;
default:
dif_control_info->protect_opcode |=
UNF_DIF_ACTION_VERIFY_AND_FORWARD;
break;
}
if (dif_sgl_mode)
dif_control_info->flags |= UNF_DIF_DOUBLE_SGL;
dif_control_info->protect_opcode |=
UNF_VERIFY_CRC_MASK | UNF_VERIFY_LBA_MASK;
dif_control_info->dif_sge_count = scsi_prot_sg_count(cmd);
dif_control_info->dif_sgl = scsi_prot_sglist(cmd);
dif_control_info->start_lba =
cpu_to_le32(((uint32_t)(0xffffffff & scsi_get_lba(cmd))));
if (scsi_prot_sg_count(cmd)) {
difsegcnt = dma_map_sg(&lport->low_level_func.dev->dev,
scsi_prot_sglist(cmd),
(int)scsi_prot_sg_count(cmd),
cmd->sc_data_direction);
if (unlikely(!difsegcnt)) {
UNF_TRACE(0x3808, UNF_LOG_LOGIN_ATT, UNF_WARN,
"[warn]Port(0x%x) cmd:%p map dif sgl err",
lport->port_id, cmd);
return UNF_RETURN_ERROR;
}
}
UNF_TRACE(UNF_EVTLOG_DRIVER_INFO, UNF_LOG_REG_ATT, UNF_INFO,
"build scsi cmd:%p op:%d,difsglcount:%d,difsegcnt:%d",
cmd, scsi_get_prot_op(cmd), scsi_prot_sg_count(cmd),
difsegcnt);
return RETURN_OK;
}
unsigned int unf_get_frame_entry_buf(void *v_up_cmnd,
void *v_driver_sgl,
void **v_upper_sgl,
unsigned int *v_port_id,
unsigned int *v_index,
char **v_buf,
unsigned int *v_buf_len)
{
#define HIFC_1822_MAX_DMA_LENGTH (0x20000 - 1)
struct scatterlist *scsi_sgl = *v_upper_sgl;
UNF_REFERNCE_VAR(v_up_cmnd);
UNF_REFERNCE_VAR(v_driver_sgl);
UNF_REFERNCE_VAR(v_port_id);
if (unlikely(!scsi_sgl)) {
UNF_TRACE(UNF_EVTLOG_IO_ERR, UNF_LOG_IO_ATT, UNF_ERR,
"[err]Command(0x%p) can not get SGL.", v_up_cmnd);
return RETURN_ERROR;
}
*v_buf = (char *)sg_dma_address(scsi_sgl);
*v_buf_len = sg_dma_len(scsi_sgl);
*v_upper_sgl = (void *)sg_next(scsi_sgl);
if (unlikely((*v_buf_len > HIFC_1822_MAX_DMA_LENGTH) ||
(*v_buf_len == 0))) {
UNF_TRACE(UNF_EVTLOG_IO_ERR, UNF_LOG_IO_ATT, UNF_ERR,
"[err]Command(0x%p) dmalen:0x%x is not support.",
v_up_cmnd, *v_buf_len);
return RETURN_ERROR;
}
return RETURN_OK;
}
static int unf_scsi_queue_cmd(struct Scsi_Host *shost,
struct scsi_cmnd *v_cmnd)
{
struct Scsi_Host *host = NULL;
struct scsi_cmnd *cmd = NULL;
struct unf_scsi_cmd_s scsi_cmnd = { 0 };
unsigned int scsi_id = 0;
unsigned int en_scsi_state = 0;
int ret = SCSI_MLQUEUE_HOST_BUSY;
// unsigned int uiError = 0;
struct unf_lport_s *lport = NULL;
struct fc_rport *p_rport = NULL;
struct unf_rport_scsi_id_image_s *scsi_image_table = NULL;
unsigned int ret_value = 0;
struct unf_rport_s *rport = NULL;
unsigned int cmnd_result = 0;
unsigned int rport_state_err = 0;
unsigned int scan_device_cmd = 0;
unsigned long long raw_lun_id = 0;
int data_seg_cnt = 0;
static atomic64_t ull_count;
host = shost;
cmd = v_cmnd;
UNF_CHECK_VALID(0x515, UNF_TRUE, host, return RETURN_ERROR);
UNF_CHECK_VALID(0x514, UNF_TRUE, cmd, return RETURN_ERROR);
/* Get L_Port from scsi_cmnd */
lport = (struct unf_lport_s *)host->hostdata[0];
if (unlikely(!lport)) {
UNF_TRACE(0x3808, UNF_LOG_LOGIN_ATT, UNF_ERR,
"[err]Check l_port failed, cmd(%p)", cmd);
/* scsi_done & return 0 & I/O error */
cmd->result = DID_NO_CONNECT << 16;
cmd->scsi_done(cmd);
return 0;
}
/* Check device/session local state by device_id */
/* local SCSI_ID from device */
scsi_id = (unsigned int)((unsigned long long)cmd->device->hostdata);
if (unlikely(scsi_id >= UNF_MAX_SCSI_ID)) {
UNF_TRACE(0x3808, UNF_LOG_LOGIN_ATT, UNF_ERR,
"[err]Port(0x%x) scsi_id(0x%x) is max than %d",
lport->port_id, scsi_id, UNF_MAX_SCSI_ID);
/* scsi_done & return 0 & I/O error */
cmd->result = DID_NO_CONNECT << 16;
cmd->scsi_done(cmd);
return 0;
}
scsi_image_table = &lport->rport_scsi_table;
UNF_SCSI_CMD_CNT(scsi_image_table, scsi_id, cmd->cmnd[0]);
/* Get scsi r_port */
/*lint -e666 -esym(666,*)*/
p_rport = starget_to_rport(scsi_target(cmd->device));
if (unlikely(!p_rport)) {
UNF_TRACE(0x3808, UNF_LOG_LOGIN_ATT, UNF_ERR,
"[err]Port(0x%x) cmd(%p) to get scsi rport failed",
lport->port_id, cmd);
/* scsi_done & return 0 & I/O error */
cmd->result = DID_NO_CONNECT << 16;
cmd->scsi_done(cmd);
ret_value = DID_NO_CONNECT;
UNF_IO_RESULT_CNT(scsi_image_table, scsi_id, ret_value);
return 0;
}
en_scsi_state = atomic_read(&scsi_image_table->wwn_rport_info_table[scsi_id].en_scsi_state);
if (unlikely(en_scsi_state != UNF_SCSI_ST_ONLINE)) {
if (en_scsi_state == UNF_SCSI_ST_OFFLINE) {
UNF_TRACE(0x3808, UNF_LOG_LOGIN_ATT, UNF_WARN,
"[warn]Port(0x%x) scsi_state(0x%x) scsi_id(0x%x) rport(0x%p) target_id(0x%x) cmd(0x%p), target is busy",
lport->port_id, en_scsi_state, scsi_id,
p_rport, p_rport->scsi_target_id, cmd);
scan_device_cmd = (cmd->cmnd[0] == INQUIRY) ||
(cmd->cmnd[0] == REPORT_LUNS);
/* report lun or inquiry cmd, if send failed,
* do not retry, prevent the scan_mutex in
* scsi host locked up by eachother
*/
if (scan_device_cmd) {
UNF_TRACE(0x3808, UNF_LOG_LOGIN_ATT, UNF_WARN,
"[warn]Port(0x%x) host(0x%x) scsi_id(0x%x) lun(0x%llx) cmd(0x%x) DID_NO_CONNECT",
lport->port_id, host->host_no,
scsi_id,
(unsigned long long)cmd->device->lun,
cmd->cmnd[0]);
cmd->result = DID_NO_CONNECT << 16;
cmd->scsi_done(cmd);
ret_value = DID_NO_CONNECT;
UNF_IO_RESULT_CNT(scsi_image_table, scsi_id,
ret_value);
return 0;
}
if (likely(scsi_image_table->wwn_rport_info_table)) {
if (likely(scsi_image_table->wwn_rport_info_table[scsi_id].dfx_counter))
atomic64_inc(&scsi_image_table->wwn_rport_info_table[scsi_id].dfx_counter->target_busy);
}
/* Target busy: need scsi retry */
return SCSI_MLQUEUE_TARGET_BUSY;
}
/* timeout(DEAD): scsi_done & return 0 & I/O error */
UNF_TRACE(0x3808, UNF_LOG_LOGIN_ATT, UNF_WARN,
"[warn]Port(0x%x) scsi_id(0x%x) rport(0x%p) target_id(0x%x) cmd(0x%p), target is loss timeout",
lport->port_id, scsi_id, p_rport,
p_rport->scsi_target_id, cmd);
cmd->result = DID_NO_CONNECT << 16;
cmd->scsi_done(cmd);
ret_value = DID_NO_CONNECT;
UNF_IO_RESULT_CNT(scsi_image_table, scsi_id, ret_value);
return 0;
}
raw_lun_id = ((unsigned long long)cmd->device->lun << 16) &
0x00000000ffff0000;
if (scsi_sg_count(cmd)) {
data_seg_cnt = dma_map_sg(&lport->low_level_func.dev->dev,
scsi_sglist(cmd),
(int)scsi_sg_count(cmd),
cmd->sc_data_direction);
if (unlikely(!data_seg_cnt)) {
UNF_TRACE(0x3808, UNF_LOG_LOGIN_ATT, UNF_WARN,
"[warn]Port(0x%x) scsi_id(0x%x) rport(0x%p) target_id(0x%x) cmd(0x%p), dma map sg err",
lport->port_id, scsi_id,
p_rport, p_rport->scsi_target_id, cmd);
cmd->result = DID_BUS_BUSY << 16;
cmd->scsi_done(cmd);
ret_value = DID_BUS_BUSY;
UNF_IO_RESULT_CNT(scsi_image_table, scsi_id, ret_value);
return SCSI_MLQUEUE_HOST_BUSY;
}
}
/* Construct local SCSI CMND info */
/* save host_no to scsi_cmnd->scsi_host_id */
scsi_cmnd.scsi_host_id = host->host_no;
scsi_cmnd.scsi_id = scsi_id;
scsi_cmnd.lun_id = raw_lun_id;
scsi_cmnd.data_direction = cmd->sc_data_direction;
scsi_cmnd.underflow = cmd->underflow;
scsi_cmnd.cmnd_len = cmd->cmd_len;
scsi_cmnd.pcmnd = cmd->cmnd;
scsi_cmnd.transfer_len = cpu_to_le32((uint32_t)scsi_bufflen(cmd));
scsi_cmnd.sense_buf_len = SCSI_SENSE_DATA_LEN;
scsi_cmnd.sense_buf = cmd->sense_buffer;
scsi_cmnd.time_out = 0;
scsi_cmnd.upper_cmnd = cmd;
scsi_cmnd.drv_private =
(void *)(*(unsigned long long *)shost_priv(host));
scsi_cmnd.entry_count = data_seg_cnt;
scsi_cmnd.sgl = scsi_sglist(cmd);
scsi_cmnd.pfn_unf_ini_get_sgl_entry = unf_get_frame_entry_buf;
scsi_cmnd.pfn_done = unf_scsi_done;
scsi_cmnd.pc_lun_id = (unsigned char *)&scsi_cmnd.lun_id;
scsi_cmnd.err_code_table_cout = ini_err_code_table_cnt1;
scsi_cmnd.err_code_table = ini_error_code_table1;
scsi_cmnd.world_id = 0xfffffffc;
scsi_cmnd.cmnd_sn = atomic64_inc_return(&ull_count);
if (unlikely(scsi_cmnd.cmnd_sn == 0))
scsi_cmnd.cmnd_sn = atomic64_inc_return(&ull_count);
if ((scsi_get_prot_op(cmd) != SCSI_PROT_NORMAL) &&
hifc_dif_enable) {
ret = unf_get_protect_mode(lport, cmd, &scsi_cmnd);
if (ret != RETURN_OK) {
cmd->result = DID_BUS_BUSY << 16;
cmd->scsi_done(cmd);
ret_value = DID_BUS_BUSY;
UNF_IO_RESULT_CNT(scsi_image_table, scsi_id,
ret_value);
scsi_dma_unmap(cmd);
return SCSI_MLQUEUE_HOST_BUSY;
}
}
UNF_TRACE(0x3808, UNF_LOG_LOGIN_ATT, UNF_INFO,
"[info]Port(0x%x) host(0x%x) scsi_id(0x%x) lun(0x%llx) transfer length(0x%x) cmd_len(0x%x) direction(0x%x) cmd(0x%x) under_flow(0x%x)",
lport->port_id, host->host_no, scsi_id,
(unsigned long long)cmd->device->lun,
scsi_cmnd.transfer_len,
scsi_cmnd.cmnd_len, cmd->sc_data_direction,
scsi_cmnd.pcmnd[0], scsi_cmnd.underflow);
/* Bind the Exchange address corresponding to scsi_cmnd to
* scsi_cmnd->host_scribble
*/
cmd->host_scribble = (unsigned char *)scsi_cmnd.cmnd_sn;
ret = unf_cm_queue_command(&scsi_cmnd);
if (ret != RETURN_OK) {
rport = unf_find_rport_by_scsi_id(lport,
ini_error_code_table1,
ini_err_code_table_cnt1,
scsi_id,
&cmnd_result);
rport_state_err = (!rport) ||
(rport->lport_ini_state !=
UNF_PORT_STATE_LINKUP) ||
(rport->rp_state == UNF_RPORT_ST_CLOSING);
scan_device_cmd = (cmd->cmnd[0] == INQUIRY) ||
(cmd->cmnd[0] == REPORT_LUNS);
/* report lun or inquiry cmd if send failed, do not retry,
* prevent the scan_mutex in scsi host locked up by eachother
*/
if (rport_state_err && scan_device_cmd) {
UNF_TRACE(0x3808, UNF_LOG_LOGIN_ATT, UNF_WARN,
"[warn]Port(0x%x) host(0x%x) scsi_id(0x%x) lun(0x%llx) cmd(0x%x) cmResult(0x%x) DID_NO_CONNECT",
lport->port_id, host->host_no, scsi_id,
(unsigned long long)cmd->device->lun,
cmd->cmnd[0], cmnd_result);
cmd->result = DID_NO_CONNECT << 16;
cmd->scsi_done(cmd);
ret_value = DID_NO_CONNECT;
UNF_IO_RESULT_CNT(scsi_image_table, scsi_id, ret_value);
scsi_dma_unmap(cmd);
unf_unmap_prot_sgl(cmd);
return 0;
}
/* Host busy: scsi need to retry */
ret = SCSI_MLQUEUE_HOST_BUSY;
if (likely(scsi_image_table->wwn_rport_info_table)) {
if (likely(scsi_image_table->wwn_rport_info_table[scsi_id].dfx_counter))
atomic64_inc(&scsi_image_table->wwn_rport_info_table[scsi_id].dfx_counter->host_busy);
}
scsi_dma_unmap(cmd);
unf_unmap_prot_sgl(cmd);
UNF_TRACE(0x3808, UNF_LOG_LOGIN_ATT, UNF_WARN,
"[warn]Port(0x%x) return(0x%x) to process INI IO falid",
lport->port_id, ret);
}
return ret;
}
static int unf_scsi_abort_scsi_cmnd(struct scsi_cmnd *v_cmnd)
{
/* SCSI ABORT Command --->>> FC ABTS */
struct unf_scsi_cmd_s scsi_cmnd = { 0 };
struct Scsi_Host *scsi_host = NULL;
int ret = FAILED;
struct unf_rport_scsi_id_image_s *scsi_image_table = NULL;
struct unf_lport_s *lport = NULL;
unsigned int scsi_id = 0;
unsigned int err_handle = 0;
UNF_CHECK_VALID(0x516, UNF_TRUE, v_cmnd, return FAILED);
lport = (struct unf_lport_s *)v_cmnd->device->host->hostdata[0];
scsi_id = (unsigned int)((unsigned long long)v_cmnd->device->hostdata);
if (unf_is_lport_valid(lport) == RETURN_OK) {
scsi_image_table = &lport->rport_scsi_table;
err_handle = UNF_SCSI_ABORT_IO_TYPE;
UNF_SCSI_ERROR_HANDLE_CNT(scsi_image_table,
scsi_id, err_handle);
UNF_TRACE(0x3808, UNF_LOG_LOGIN_ATT, UNF_MAJOR,
"[abort]Port(0x%x) scsi_id(0x%x) lun_id(0x%x) cmnd_type(0x%x)",
lport->port_id, scsi_id,
(unsigned int)v_cmnd->device->lun,
v_cmnd->cmnd[0]);
} else {
UNF_TRACE(0x3808, UNF_LOG_LOGIN_ATT, UNF_ERR,
"[err]Lport(%p) is moving or null", lport);
return UNF_SCSI_ABORT_FAIL;
}
/* Check local SCSI_ID validity */
if (unlikely(scsi_id >= UNF_MAX_SCSI_ID)) {
UNF_TRACE(0x3808, UNF_LOG_LOGIN_ATT, UNF_ERR,
"[err]scsi_id(0x%x) is max than(0x%x)",
scsi_id, UNF_MAX_SCSI_ID);
return UNF_SCSI_ABORT_FAIL;
}
/* Block scsi (check rport state -> whether offline or not) */
ret = fc_block_scsi_eh(v_cmnd);
if (unlikely(ret != 0)) {
UNF_TRACE(0x3808, UNF_LOG_LOGIN_ATT, UNF_WARN,
"[warn]Block scsi eh failed(0x%x)", ret);
return ret;
}
scsi_host = v_cmnd->device->host;
scsi_cmnd.scsi_host_id = scsi_host->host_no; // L_Port ID
scsi_cmnd.scsi_id = scsi_id; // R_Port ID (Target ID)
scsi_cmnd.lun_id = (unsigned long long)v_cmnd->device->lun; // LUN ID
scsi_cmnd.upper_cmnd = v_cmnd; // scsi_cmnd
// L_Port
scsi_cmnd.drv_private =
(void *)(*(unsigned long long *)shost_priv(scsi_host));
scsi_cmnd.cmnd_sn = (unsigned long long)(v_cmnd->host_scribble);
scsi_cmnd.pc_lun_id = (unsigned char *)&scsi_cmnd.lun_id;
scsi_cmnd.pfn_done = unf_scsi_done;
scsi_cmnd.world_id = 0xfffffffc;
/* Process scsi Abort cmnd */
ret = unf_cm_eh_abort_handler(&scsi_cmnd);
if (ret == UNF_SCSI_ABORT_SUCCESS) {
if (unf_is_lport_valid(lport) == RETURN_OK) {
scsi_image_table = &lport->rport_scsi_table;
err_handle = UNF_SCSI_ABORT_IO_TYPE;
UNF_SCSI_ERROR_HANDLE_RESULT_CNT(scsi_image_table,
scsi_id, err_handle);
}
}
return ret;
}
static int unf_scsi_device_reset_handler(struct scsi_cmnd *v_cmnd)
{
/* LUN reset */
struct unf_scsi_cmd_s scsi_cmnd = { 0 };
struct Scsi_Host *scsi_host = NULL;
struct unf_rport_scsi_id_image_s *scsi_image_table = NULL;
int ret = FAILED;
struct unf_lport_s *lport = NULL;
unsigned int scsi_id = 0;
unsigned int err_handle = 0;
UNF_CHECK_VALID(0x517, UNF_TRUE, v_cmnd, return FAILED);
lport = (struct unf_lport_s *)v_cmnd->device->host->hostdata[0];
if (unf_is_lport_valid(lport) == RETURN_OK) {
scsi_image_table = &lport->rport_scsi_table;
err_handle = UNF_SCSI_DEVICE_RESET_TYPE;
UNF_SCSI_ERROR_HANDLE_CNT(scsi_image_table,
scsi_id, err_handle);
UNF_TRACE(0x3808, UNF_LOG_LOGIN_ATT, UNF_KEVENT,
"[device_reset]Port(0x%x) scsi_id(0x%x) lun_id(0x%x) cmnd_type(0x%x)",
lport->port_id, scsi_id,
(unsigned int)v_cmnd->device->lun,
v_cmnd->cmnd[0]);
} else {
UNF_TRACE(0x3808, UNF_LOG_LOGIN_ATT, UNF_ERR,
"[err]Port is invalid");
return FAILED;
}
/* Check local SCSI_ID validity */
scsi_id = (unsigned int)((unsigned long long)v_cmnd->device->hostdata);
if (unlikely(scsi_id >= UNF_MAX_SCSI_ID)) {
UNF_TRACE(0x3808, UNF_LOG_LOGIN_ATT, UNF_ERR,
"[err]scsi_id(0x%x) is max than(0x%x)",
scsi_id, UNF_MAX_SCSI_ID);
return FAILED;
}
/* Block scsi (check rport state -> whether offline or not) */
ret = fc_block_scsi_eh(v_cmnd);
if (unlikely(ret != 0)) {
UNF_TRACE(0x3808, UNF_LOG_LOGIN_ATT, UNF_WARN,
"[warn]Block scsi eh failed(0x%x)", ret);
return ret;
}
scsi_host = v_cmnd->device->host;
scsi_cmnd.scsi_host_id = scsi_host->host_no; /* l_port id */
scsi_cmnd.scsi_id = scsi_id; /* r_port id */
scsi_cmnd.lun_id = (unsigned long long)v_cmnd->device->lun; /* lun id */
scsi_cmnd.upper_cmnd = v_cmnd; /* scsi_cmnd */
/* l_port */
scsi_cmnd.drv_private =
(void *)(*(unsigned long long *)shost_priv(scsi_host));
scsi_cmnd.pc_lun_id = (unsigned char *)&scsi_cmnd.lun_id; /* lun id */
/* Process scsi device/LUN reset cmnd */
ret = unf_cm_eh_device_reset_handler(&scsi_cmnd);
if (ret == UNF_SCSI_ABORT_SUCCESS) {
if (unf_is_lport_valid(lport) == RETURN_OK) {
scsi_image_table = &lport->rport_scsi_table;
err_handle = UNF_SCSI_DEVICE_RESET_TYPE;
UNF_SCSI_ERROR_HANDLE_RESULT_CNT(scsi_image_table,
scsi_id,
err_handle);
}
}
return ret;
}
static int unf_scsi_bus_reset_handler(struct scsi_cmnd *v_cmnd)
{
/* BUS Reset */
struct unf_scsi_cmd_s scsi_cmnd = { 0 };
struct unf_lport_s *lport = NULL;
struct Scsi_Host *scsi_host = NULL;
struct unf_rport_scsi_id_image_s *scsi_image_table = NULL;
int ret = FAILED;
unsigned int scsi_id = 0;
unsigned int err_handle = 0;
UNF_CHECK_VALID(0x517, UNF_TRUE, v_cmnd, return FAILED);
lport = (struct unf_lport_s *)v_cmnd->device->host->hostdata[0];
if (unlikely(!lport)) {
UNF_TRACE(0x3808, UNF_LOG_LOGIN_ATT, UNF_ERR,
"[err]Port is null");
return FAILED;
}
/* Check local SCSI_ID validity */
scsi_id = (unsigned int)((unsigned long long)v_cmnd->device->hostdata);
if (unlikely(scsi_id >= UNF_MAX_SCSI_ID)) {
UNF_TRACE(0x3808, UNF_LOG_LOGIN_ATT, UNF_ERR,
"[err]scsi_id(0x%x) is max than(0x%x)",
scsi_id, UNF_MAX_SCSI_ID);
return FAILED;
}
if (unf_is_lport_valid(lport) == RETURN_OK) {
scsi_image_table = &lport->rport_scsi_table;
err_handle = UNF_SCSI_BUS_RESET_TYPE;
UNF_SCSI_ERROR_HANDLE_CNT(scsi_image_table,
scsi_id, err_handle);
UNF_TRACE(0x3808, UNF_LOG_LOGIN_ATT, UNF_MAJOR,
"[info][bus_reset]Port(0x%x) scsi_id(0x%x) lun_id(0x%x) cmnd_type(0x%x)",
lport->port_id, scsi_id,
(unsigned int)v_cmnd->device->lun,
v_cmnd->cmnd[0]);
}
/* Block scsi (check rport state -> whether offline or not) */
ret = fc_block_scsi_eh(v_cmnd);
if (unlikely(ret != 0)) {
UNF_TRACE(0x3808, UNF_LOG_LOGIN_ATT, UNF_WARN,
"[warn]Block scsi eh failed(0x%x)", ret);
return ret;
}
scsi_host = v_cmnd->device->host;
scsi_cmnd.scsi_host_id = scsi_host->host_no; /* l_port id */
scsi_cmnd.scsi_id = scsi_id; /* r_port id */
scsi_cmnd.lun_id = (unsigned long long)v_cmnd->device->lun; /* lun id */
scsi_cmnd.upper_cmnd = v_cmnd; /* scsi_cmnd */
/* l_port */
scsi_cmnd.drv_private =
(void *)(*(unsigned long long *)shost_priv(scsi_host));
scsi_cmnd.pc_lun_id = (unsigned char *)&scsi_cmnd.lun_id; /* lun id */
/* Process scsi BUS Reset cmnd */
ret = unf_cm_bus_reset_handler(&scsi_cmnd);
if (ret == UNF_SCSI_ABORT_SUCCESS) {
if (unf_is_lport_valid(lport) == RETURN_OK) {
scsi_image_table = &lport->rport_scsi_table;
err_handle = UNF_SCSI_BUS_RESET_TYPE;
UNF_SCSI_ERROR_HANDLE_RESULT_CNT(scsi_image_table,
scsi_id,
err_handle);
}
}
return ret;
}
static int unf_scsi_target_reset_handler(struct scsi_cmnd *v_cmnd)
{
/* Session reset/delete */
struct unf_scsi_cmd_s scsi_cmnd = { 0 };
struct Scsi_Host *scsi_host = NULL;
struct unf_rport_scsi_id_image_s *scsi_image_table = NULL;
int ret = FAILED;
struct unf_lport_s *lport = NULL;
unsigned int scsi_id = 0;
unsigned int err_handle = 0;
UNF_CHECK_VALID(0x517, UNF_TRUE, v_cmnd, return RETURN_ERROR);
lport = (struct unf_lport_s *)v_cmnd->device->host->hostdata[0];
if (unlikely(!lport)) {
UNF_TRACE(0x3808, UNF_LOG_LOGIN_ATT, UNF_ERR,
"[err]Port is null");
return FAILED;
}
/* Check local SCSI_ID validity */
scsi_id = (unsigned int)((unsigned long long)v_cmnd->device->hostdata);
if (unlikely(scsi_id >= UNF_MAX_SCSI_ID)) {
UNF_TRACE(0x3808, UNF_LOG_LOGIN_ATT, UNF_ERR,
"[err]scsi_id(0x%x) is max than(0x%x)",
scsi_id, UNF_MAX_SCSI_ID);
return FAILED;
}
if (unf_is_lport_valid(lport) == RETURN_OK) {
scsi_image_table = &lport->rport_scsi_table;
err_handle = UNF_SCSI_TARGET_RESET_TYPE;
UNF_SCSI_ERROR_HANDLE_CNT(scsi_image_table, scsi_id,
err_handle);
UNF_TRACE(0x3808, UNF_LOG_LOGIN_ATT, UNF_KEVENT,
"[target_reset]Port(0x%x) scsi_id(0x%x) lun_id(0x%x) cmnd_type(0x%x)",
lport->port_id, scsi_id,
(unsigned int)v_cmnd->device->lun,
v_cmnd->cmnd[0]);
}
/* Block scsi (check rport state -> whether offline or not) */
ret = fc_block_scsi_eh(v_cmnd);
if (unlikely(ret != 0)) {
UNF_TRACE(0x3808, UNF_LOG_LOGIN_ATT, UNF_WARN,
"[warn]Block scsi eh failed(0x%x)", ret);
return ret;
}
scsi_host = v_cmnd->device->host;
scsi_cmnd.scsi_host_id = scsi_host->host_no; /* l_port id */
scsi_cmnd.scsi_id = scsi_id; /* r_port id */
scsi_cmnd.lun_id = (unsigned long long)v_cmnd->device->lun; /* lun id */
scsi_cmnd.upper_cmnd = v_cmnd; /* scsi_cmnd */
/* l_port */
scsi_cmnd.drv_private =
(void *)(*(unsigned long long *)shost_priv(scsi_host));
scsi_cmnd.pc_lun_id = (unsigned char *)&scsi_cmnd.lun_id; /* lun id */
/* Process scsi Target/Session reset/delete cmnd */
ret = unf_cm_target_reset_handler(&scsi_cmnd);
if (ret == UNF_SCSI_ABORT_SUCCESS) {
if (unf_is_lport_valid(lport) == RETURN_OK) {
scsi_image_table = &lport->rport_scsi_table;
err_handle = UNF_SCSI_TARGET_RESET_TYPE;
UNF_SCSI_ERROR_HANDLE_RESULT_CNT(scsi_image_table,
scsi_id, err_handle);
}
}
return ret;
}
static int unf_scsi_slave_alloc(struct scsi_device *sdev)
{
/*lint -e666 -esym(666,*)*/
struct fc_rport *rport = NULL;
unsigned int scsi_id = 0;
struct unf_lport_s *lport = NULL;
struct Scsi_Host *host = NULL;
struct unf_rport_scsi_id_image_s *scsi_image_table = NULL;
/* About device */
if (unlikely(!sdev)) {
UNF_TRACE(0x4101, UNF_LOG_LOGIN_ATT, UNF_ERR,
"[err]SDev is null");
return -ENXIO;
}
/* About scsi rport */
rport = starget_to_rport(scsi_target(sdev));
if (unlikely(!rport || fc_remote_port_chkready(rport))) {
UNF_TRACE(0x4101, UNF_LOG_LOGIN_ATT, UNF_ERR,
"[err]SCSI rport is null");
if (rport) {
UNF_TRACE(0x4101, UNF_LOG_LOGIN_ATT, UNF_ERR,
"[err]SCSI rport is not ready(0x%x)",
fc_remote_port_chkready(rport));
}
return -ENXIO;
}
/* About host */
host = rport_to_shost(rport);
if (unlikely(!host)) {
UNF_TRACE(0x3808, UNF_LOG_LOGIN_ATT, UNF_ERR,
"[err]Host is null");
return -ENXIO;
}
/* About Local Port */
lport = (struct unf_lport_s *)host->hostdata[0];
if (unf_is_lport_valid(lport) != RETURN_OK) {
UNF_TRACE(0x3808, UNF_LOG_LOGIN_ATT, UNF_ERR,
"[err]Port is invalid");
return -ENXIO;
}
/* About Local SCSI_ID */
/* use local SCSI_ID to alloc slave device */
scsi_id = *(unsigned int *)rport->dd_data;
if (unlikely(scsi_id >= UNF_MAX_SCSI_ID)) {
UNF_TRACE(0x3808, UNF_LOG_LOGIN_ATT, UNF_ERR,
"[err]scsi_id(0x%x) is max than(0x%x)",
scsi_id, UNF_MAX_SCSI_ID);
return -ENXIO;
}
scsi_image_table = &lport->rport_scsi_table;
if (scsi_image_table->wwn_rport_info_table[scsi_id].dfx_counter)
atomic_inc(&scsi_image_table->wwn_rport_info_table[scsi_id].dfx_counter->device_alloc);
atomic_inc(&lport->device_alloc);
/* save local SCSI_ID */
sdev->hostdata = (void *)(unsigned long long)scsi_id;
UNF_TRACE(0x4101, UNF_LOG_LOGIN_ATT, UNF_KEVENT,
"[event]Port(0x%x) use scsi_id(%d) to alloc device[%u:%u:%u:%u]",
lport->port_id, scsi_id, host->host_no,
sdev->channel, sdev->id, (unsigned int)sdev->lun);
return 0;
}
static void unf_scsi_destroy_slave(struct scsi_device *sdev)
{
/*
* NOTE: about sdev->hostdata
* --->>> pointing to local SCSI_ID
* 1. Assignment during slave allocation
* 2. Released when callback for slave destroy
* 3. Used during: Queue_CMND, Abort CMND, Device Reset,
* Target Reset & Bus Reset
*/
/*lint -e666 -esym(666,*)*/
struct fc_rport *rport = NULL;
unsigned int scsi_id = 0;
struct unf_lport_s *lport = NULL;
struct Scsi_Host *host = NULL;
struct unf_rport_scsi_id_image_s *scsi_image_table = NULL;
/* About scsi device */
if (unlikely(!sdev)) {
UNF_TRACE(0x4101, UNF_LOG_LOGIN_ATT, UNF_ERR,
"[err]SDev is null");
return;
}
/* About scsi rport */
rport = starget_to_rport(scsi_target(sdev));
if (unlikely(!rport)) {
UNF_TRACE(0x4101, UNF_LOG_LOGIN_ATT, UNF_ERR,
"[err]SCSI rport is null or remote port is not ready");
return;
}
/* About host */
host = rport_to_shost(rport);
if (unlikely(!host)) {
UNF_TRACE(0x3808, UNF_LOG_LOGIN_ATT, UNF_ERR,
"[err]Host is null");
return;
}
/* About L_Port */
lport = (struct unf_lport_s *)host->hostdata[0];
if (unf_is_lport_valid(lport) == RETURN_OK) {
scsi_image_table = &lport->rport_scsi_table;
atomic_inc(&lport->device_destroy);
scsi_id = (unsigned int)((unsigned long long)sdev->hostdata);
if ((scsi_id < UNF_MAX_SCSI_ID) &&
(scsi_image_table->wwn_rport_info_table)) {
if (scsi_image_table->wwn_rport_info_table[scsi_id].dfx_counter)
atomic_inc(&scsi_image_table->wwn_rport_info_table[scsi_id].dfx_counter->device_destroy);
UNF_TRACE(0x4101, UNF_LOG_LOGIN_ATT, UNF_KEVENT,
"[event]Port(0x%x) with scsi_id(%d) to destroy slave device[%u:%u:%u:%u]",
lport->port_id, scsi_id, host->host_no,
sdev->channel, sdev->id,
(unsigned int)sdev->lun);
} else {
UNF_TRACE(0x4101, UNF_LOG_LOGIN_ATT, UNF_WARN,
"[err]Port(0x%x) scsi_id(%d) is invalid and destroy device[%u:%u:%u:%u]",
lport->port_id, scsi_id, host->host_no,
sdev->channel, sdev->id,
(unsigned int)sdev->lun);
}
} else {
UNF_TRACE(0x3097, UNF_LOG_LOGIN_ATT, UNF_ERR,
"[err]Port(%p) is invalid", lport);
}
sdev->hostdata = NULL; /* reset local SCSI_ID */
}
static int unf_scsi_slave_configure(struct scsi_device *sdev)
{
#define UNF_SCSI_DEV_DEPTH 32
blk_queue_update_dma_alignment(sdev->request_queue, 0x7);
scsi_change_queue_depth(sdev, UNF_SCSI_DEV_DEPTH);
UNF_TRACE(0x4101, UNF_LOG_LOGIN_ATT, UNF_INFO,
"[event]Enter slave configure, set depth is %d, sdev->tagged_supported is (%d)",
UNF_SCSI_DEV_DEPTH, sdev->tagged_supported);
return 0;
}
static int unf_scsi_scan_finished(struct Scsi_Host *shost, unsigned long time)
{
UNF_TRACE(0x4101, UNF_LOG_LOGIN_ATT, UNF_MAJOR,
"[event]Scan finished");
return 1;
}
static void unf_scsi_scan_start(struct Scsi_Host *shost)
{
UNF_TRACE(0x4101, UNF_LOG_LOGIN_ATT, UNF_MAJOR,
"[event]Start scsi scan...");
}
unsigned int unf_register_ini_transport(void)
{
/* Register INI Transport */
scsi_transport_template = fc_attach_transport(&function_template);
if (!scsi_transport_template) {
UNF_TRACE(0x4101, UNF_LOG_LOGIN_ATT, UNF_ERR,
"[err]Register FC transport to scsi failed");
return RETURN_ERROR;
}
scsi_transport_template_v = fc_attach_transport(&function_template_v);
if (!scsi_transport_template_v) {
UNF_TRACE(0x4101, UNF_LOG_LOGIN_ATT, UNF_ERR,
"[err]Register FC vport transport to scsi failed");
fc_release_transport(scsi_transport_template);
return RETURN_ERROR;
}
UNF_TRACE(0x4101, UNF_LOG_LOGIN_ATT, UNF_MAJOR,
"[event]Register FC transport to scsi succeed");
return RETURN_OK;
}
void unf_unregister_ini_transport(void)
{
fc_release_transport(scsi_transport_template);
fc_release_transport(scsi_transport_template_v);
UNF_TRACE(0x4101, UNF_LOG_LOGIN_ATT, UNF_MAJOR,
"[event]Unregister FC transport succeed");
}
void unf_report_io_dm_event(void *v_lport, unsigned int type,
unsigned int value)
{
}
void unf_save_sense_data(void *scsicmd, const char *sense, int senslen)
{
struct scsi_cmnd *cmd;
UNF_CHECK_VALID(INVALID_VALUE32, UNF_TRUE, scsicmd, return);
UNF_CHECK_VALID(INVALID_VALUE32, UNF_TRUE, sense, return);
cmd = (struct scsi_cmnd *)scsicmd;
memcpy(cmd->sense_buffer, sense, senslen);
}
/* SPDX-License-Identifier: GPL-2.0 */
/* Huawei Hifc PCI Express Linux driver
* Copyright(c) 2017 Huawei Technologies Co., Ltd
*
*/
#ifndef __UNF_SCSI_COMMON__
#define __UNF_SCSI_COMMON__
#include "unf_log.h"
#include "hifc_knl_adp.h"
#define DRV_ISCSI_NAME 223
#define SCSI_SENSE_DATA_LEN 96
#define DRV_SCSI_CDB_LEN 16
#define DRV_SCSI_LUN_LEN 8
#define DRV_PORTID_NUM 32
#ifndef SUCCESS
#define SUCCESS 0x2002
#endif
#ifndef FAILED
#define FAILED 0x2003
#endif
#ifndef FC_PORTSPEED_32GBIT
#define FC_PORTSPEED_32GBIT 0x40
#endif
/*
* FCTL defines (FrameHdr.Type_Fctl)
*/
#define FC_EXCHANGE_RESPONDER 0x00800000
#define FC_LAST_SEQUENCE 0x00100000
#define FC_END_SEQUENCE 0x00080000
#define FC_SEQUENCE_INITIATIVE 0x00010000
/*
* FCTL common use defines
*/
#define FC_FCTL_RSP (FC_EXCHANGE_RESPONDER | FC_LAST_SEQUENCE | \
FC_END_SEQUENCE)
#define UNF_GID_PORT_CNT 2048
#define UNF_RSCN_PAGE_SUM 255
#define UNF_CPU_ENDIAN
#define UNF_NPORTID_MASK 0x00FFFFFF
#define UNF_DOMAIN_MASK 0x00FF0000
#define UNF_AREA_MASK 0x0000FF00
#define UNF_ALPA_MASK 0x000000FF
#define UNF_NPORTID_WELLKNOWN_MASK 0x00fffff0
#define UNF_SCSI_ABORT_SUCCESS SUCCESS
#define UNF_SCSI_ABORT_FAIL FAILED
#define UNF_SCSI_STATUS(byte) (byte)
#define UNF_SCSI_MSG(byte) ((byte) << 8)
#define UNF_SCSI_HOST(byte) ((byte) << 16)
#define UNF_SCSI_DRIVER(byte) ((byte) << 24)
#define UNF_GET_SCSI_HOST_ID(scsi_host) ((scsi_host)->host_no)
struct unf_fchead_s {
/* Routing control and Destination address of the seq */
unsigned int rctl_did;
/* Class control and Source address of the sequence */
unsigned int csctl_sid;
/* Data type and Initial frame control value of the seq */
unsigned int type_fctl;
/* Seq ID, Data Field and Initial seq count */
unsigned int seq_id_dfctl_seq_cnt;
/* Originator & Responder exchange IDs for the sequence */
unsigned int oxid_rxid;
/* Relative offset of the first frame of the sequence */
unsigned int parameter;
};
#define UNF_FCPRSP_CTL_LEN (24)
#define UNF_MAX_RSP_INFO_LEN (8)
#define UNF_RSP_LEN_VLD (1 << 0)
#define UNF_SENSE_LEN_VLD (1 << 1)
#define UNF_RESID_OVERRUN (1 << 2)
#define UNF_RESID_UNDERRUN (1 << 3)
/* T10: FCP2r.07 9.4.1 Overview and format of FCP_RSP IU */
struct unf_fcprsp_iu_s {
unsigned int ui_reserved[2];
unsigned char uc_reserved[2];
unsigned char control;
unsigned char fcp_status;
unsigned int fcp_residual;
unsigned int fcp_sense_len; /* Length of sense info field */
/* Length of response info field in bytes 0,4 or 8 */
unsigned int fcp_response_len;
/* Buffer for response info */
unsigned char fcp_rsp_info[UNF_MAX_RSP_INFO_LEN];
/* Buffer for sense info */
unsigned char fcp_sense_info[SCSI_SENSE_DATA_LEN];
} __attribute__((packed));
#define UNF_CMD_REF_MASK 0xFF000000
#define UNF_TASK_ATTR_MASK 0x00070000
#define UNF_TASK_MGMT_MASK 0x0000FF00
#define UNF_FCP_WR_DATA 0x00000001
#define UNF_FCP_RD_DATA 0x00000002
#define UNF_CDB_LEN_MASK 0x0000007C
#define UNF_FCP_CDB_LEN_16 (16)
#define UNF_FCP_CDB_LEN_32 (32)
#define UNF_FCP_LUNID_LEN_8 (8)
/* FCP-4 :Table 27 - RSP_CODE field */
#define UNF_FCP_TM_RSP_COMPLETE (0)
#define UNF_FCP_TM_INVALID_CMND (0x2)
#define UNF_FCP_TM_RSP_REJECT (0x4)
#define UNF_FCP_TM_RSP_FAIL (0x5)
#define UNF_FCP_TM_RSP_SUCCEED (0x8)
#define UNF_FCP_TM_RSP_INCRECT_LUN (0x9)
#define UNF_SET_TASK_MGMT_FLAGS(v_fcp_tm_code) ((v_fcp_tm_code) << 8)
#define UNF_GET_TASK_MGMT_FLAGS(v_control) \
(((v_control) & UNF_TASK_MGMT_MASK) >> 8)
enum unf_task_mgmt_cmnd_e {
UNF_FCP_TM_QUERY_TASK_SET = (1 << 0),
UNF_FCP_TM_ABORT_TASK_SET = (1 << 1),
UNF_FCP_TM_CLEAR_TASK_SET = (1 << 2),
UNF_FCP_TM_QUERY_UNIT_ATTENTION = (1 << 3),
UNF_FCP_TM_LOGICAL_UNIT_RESET = (1 << 4),
UNF_FCP_TM_TARGET_RESET = (1 << 5),
UNF_FCP_TM_CLEAR_ACA = (1 << 6),
UNF_FCP_TM_TERMINATE_TASK = (1 << 7) /* obsolete */
};
struct unf_fcp_cmnd_s {
unsigned char lun[UNF_FCP_LUNID_LEN_8]; /* Logical unit number */
unsigned int control; /* Control field :
* uint8_t cmnd_ref;
* uint8_t task_attr:3;
* uint8_t reserved:5;
* uint8_t task_mgmt_flags;
* uint8_t wrdata:1;
* uint8_t rddata:1;
* uint8_t add_cdb_len:6;
*/
/* Payload data containing cdb info */
unsigned char cdb[UNF_FCP_CDB_LEN_16];
/* Number of bytes expected to be transferred */
unsigned int data_length;
} __attribute__((packed));
struct unf_fcp_cmd_hdr_s {
struct unf_fchead_s frame_hdr; /* FCHS structure */
struct unf_fcp_cmnd_s fcp_cmnd; /* Fcp Cmnd struct */
};
/*
* parameter struct
*/
/* Common Services Parameter used for returning Fabric
* parameters. See FC-FS Rev. 1.90, FC-PH-3 Rev. 9.4 and see FC-DA 3.1.
* This is the structure that is used to enquire Fabric parameters
* after a Fabric login is successful. The fileds in this structure
* are relevant for FLOGI ACC.
*/
/* FC-LS-2 Table 140 Common Service Parameter applicability */
struct unf_fabric_coparms_s {
#if defined(UNF_CPU_ENDIAN)
unsigned int bb_credit : 16; /* 0 [0-15] */
unsigned int lowest_version : 8; /* 0 [16-23] */
unsigned int highest_version : 8; /* 0 [24-31] */
#else
unsigned int highest_version : 8; /* 0 [24-31] */
unsigned int lowest_version : 8; /* 0 [16-23] */
unsigned int bb_credit : 16; /* 0 [0-15] */
#endif
/* Word1 Common Features */
#if defined(UNF_CPU_ENDIAN)
unsigned int bb_receive_data_field_size : 12; /* 1 [0-11] */
unsigned int bb_scn : 4; /* 1 [12-15] */
unsigned int payload_length : 1; /* 1 [16] */
unsigned int seq_cnt : 1; /* 1 [17] */
unsigned int dynamic_half_duplex : 1; /* 1 [18] */
unsigned int r_t_tov : 1; /* 1 [19] */
unsigned int reserved_co2 : 6; /* 1 [20-25] */
unsigned int e_d_tov_resolution : 1; /* 1 [26] */
unsigned int alternate_bb_credit_mgmt : 1; /* 1 [27] */
unsigned int n_port : 1; /* 1 [28] */
unsigned int mnid_assignment : 1; /* 1 [29] */
unsigned int random_relative_offset : 1; /* 1 [30] */
unsigned int clean_address : 1; /* 1 [31] */
#else
unsigned int reserved_co22 : 2; /* 1 [24-25] */
unsigned int e_d_tov_resolution : 1; /* 1 [26] */
unsigned int alternate_bb_credit_mgmt : 1; /* 1 [27] */
unsigned int n_port : 1; /* 1 [28] */
unsigned int mnid_assignment : 1; /* 1 [29] */
unsigned int random_relative_offset : 1; /* 1 [30] */
unsigned int clean_address : 1; /* 1 [31] */
unsigned int payload_length : 1; /* 1 [16] */
unsigned int seq_cnt : 1; /* 1 [17] */
unsigned int dynamic_half_duplex : 1; /* 1 [18] */
unsigned int r_t_tov : 1; /* 1 [19] */
unsigned int reserved_co25 : 4; /* 1 [20-23] */
unsigned int bb_receive_data_field_size : 12; /* 1 [0-11] */
unsigned int bb_scn : 4; /* 1 [12-15] */
#endif
unsigned int r_a_tov; /* 2 [0-31] */
unsigned int e_d_tov; /* 3 [0-31] */
};
/*
* Common Services Parameter 16 byte structure.
* See FC-PH 4.3 Section 23.6.3, FC-PLDA Section 5.2 and
* TachLite Users Manual 3.24.1
* the structure does not need to be packed.
*/
/* FC-LS-2 Table 140 Common Service Parameter applicability */
/* Table 142 Common Service Parameters - PLOGI and PLOGI LS_ACC */
struct unf_lgn_port_coparms_s {
#if defined(UNF_CPU_ENDIAN)
unsigned int bb_credit : 16; /* 0 [0-15] */
unsigned int lowest_version : 8; /* 0 [16-23] */
unsigned int highest_version : 8; /* 0 [24-31] */
#else
unsigned int highest_version : 8; /* 0 [24-31] */
unsigned int lowest_version : 8; /* 0 [16-23] */
unsigned int bb_credit : 16; /* 0 [0-15] */
#endif
#if defined(UNF_CPU_ENDIAN)
unsigned int bb_receive_data_field_size : 12; /* 1 [0-11] */
unsigned int bb_scn : 4; /* 1 [12-15] */
unsigned int payload_length : 1; /* 1 [16] */
unsigned int seq_cnt : 1; /* 1 [17] */
unsigned int dynamic_half_duplex : 1; /* 1 [18] */
unsigned int reserved_co2 : 7; /* 1 [19-25] */
unsigned int e_d_tov_resolution : 1; /* 1 [26] */
unsigned int alternate_bb_credit_mgmt : 1; /* 1 [27] */
unsigned int n_port : 1; /* 1 [28] */
unsigned int vendor_version_level : 1; /* 1 [29] */
unsigned int random_relative_offset : 1; /* 1 [30] */
unsigned int continuously_increasing : 1; /* 1 [31] */
#else
unsigned int reserved_co22 : 2; /* 1 [24-25] */
unsigned int e_d_tov_resolution : 1; /* 1 [26] */
unsigned int alternate_bb_credit_mgmt : 1; /* 1 [27] */
unsigned int n_port : 1; /* 1 [28] */
unsigned int vendor_version_level : 1; /* 1 [29] */
unsigned int random_relative_offset : 1; /* 1 [30] */
unsigned int continuously_increasing : 1; /* 1 [31] */
unsigned int payload_length : 1; /* 1 [16] */
unsigned int seq_cnt : 1; /* 1 [17] */
unsigned int dynamic_half_duplex : 1; /* 1 [18] */
unsigned int reserved_co25 : 5; /* 1 [19-23] */
unsigned int bb_receive_data_field_size : 12; /* 1 [0-11] */
unsigned int reserved_co1 : 4; /* 1 [12-15] */
#endif
#if defined(UNF_CPU_ENDIAN)
unsigned int relative_offset : 16; /* 2 [0-15] */
unsigned int nport_total_concurrent_sequences : 16; /* 2 [16-31] */
#else
unsigned int nport_total_concurrent_sequences : 16; /* 2 [16-31] */
unsigned int relative_offset : 16; /* 2 [0-15] */
#endif
unsigned int e_d_tov;
};
/*
* Class services 16 byte structure. See FC-PH 4.3 Section 23.6.8 and
* FC-PLDA Section 5.3
* the structure does not need to be packed
*/
/* FC-LS-2 Table 145 Class Service Parameters Applicability */
struct unf_lgn_port_clparms_s {
#if defined(UNF_CPU_ENDIAN)
unsigned int reserved_cl1 : 6; /* 0 [0-5] */
unsigned int ic_data_compression_history_buffer_size : 2; /* 0 [6-7] */
unsigned int ic_data_compression_capable : 1; /* 0 [8] */
unsigned int ic_ack_generation_assistance : 1; /* 0 [9] */
unsigned int ic_ack_n_capable : 1; /* 0 [10] */
unsigned int ic_ack_o_capable : 1; /* 0 [11] */
/* 0 [12-13] */
unsigned int ic_initial_responder_processes_accociator : 2;
unsigned int ic_x_id_reassignment : 2; /* 0 [14-15] */
unsigned int reserved_cl2 : 7; /* 0 [16-22] */
unsigned int priority : 1; /* 0 [23] */
unsigned int buffered_class : 1; /* 0 [24] */
unsigned int camp_on : 1; /* 0 [25] */
unsigned int dedicated_simplex : 1; /* 0 [26] */
unsigned int sequential_delivery : 1; /* 0 [27] */
unsigned int stacked_connect_request : 2; /* 0 [28-29] */
unsigned int intermix_mode : 1; /* 0 [30] */
unsigned int valid : 1; /* 0 [31] */
#else
unsigned int buffered_class : 1; /* 0 [24] */
unsigned int camp_on : 1; /* 0 [25] */
unsigned int dedicated_simplex : 1; /* 0 [26] */
unsigned int sequential_delivery : 1; /* 0 [27] */
unsigned int stacked_connect_request : 2; /* 0 [28-29] */
unsigned int intermix_mode : 1; /* 0 [30] */
unsigned int valid : 1; /* 0 [31] */
unsigned int reserved_cl2 : 7; /* 0 [16-22] */
unsigned int priority : 1; /* 0 [23] */
unsigned int ic_data_compression_capable : 1; /* 0 [8] */
unsigned int ic_ack_generation_assistance : 1; /* 0 [9] */
unsigned int ic_ack_n_capable : 1; /* 0 [10] */
unsigned int ic_ack_o_capable : 1; /* 0 [11] */
/* 0 [12-13] */
unsigned int ic_initial_responder_processes_accociator : 2;
unsigned int ic_x_id_reassignment : 2; /* 0 [14-15] */
unsigned int reserved_cl1 : 6; /* 0 [0-5] */
/* 0 [6-7] */
unsigned int ic_data_compression_history_buffer_size : 2;
#endif
#if defined(UNF_CPU_ENDIAN)
unsigned int received_data_field_size : 16; /* 1 [0-15] */
unsigned int reserved_cl3 : 5; /* 1 [16-20] */
/* 1 [21-22] */
unsigned int rc_data_compression_history_buffer_size : 2;
unsigned int rc_data_compression_capable : 1; /* 1 [23] */
unsigned int rc_categories_per_sequence : 2; /* 1 [24-25] */
unsigned int reserved_cl4 : 1; /* 1 [26] */
unsigned int rc_error_policy_supported : 2; /* 1 [27-28] */
unsigned int rc_x_id_interlock : 1; /* 1 [29] */
unsigned int rc_ack_n_capable : 1; /* 1 [30] */
unsigned int rc_ack_o_capable : 1; /* 1 [31] */
#else
unsigned int rc_categories_per_sequence : 2; /* 1 [24-25] */
unsigned int reserved_cl4 : 1; /* 1 [26] */
unsigned int rc_error_policy_supported : 2; /* 1 [27-28] */
unsigned int rc_x_id_interlock : 1; /* 1 [29] */
unsigned int rc_ack_n_capable : 1; /* 1 [30] */
unsigned int rc_ack_o_capable : 1; /* 1 [31] */
unsigned int reserved_cl3 : 5; /* 1 [16-20] */
/* 1 [21-22] */
unsigned int rc_data_compression_history_buffer_size : 2;
unsigned int rc_data_compression_capable : 1; /* 1 [23] */
unsigned int received_data_field_size : 16; /* 1 [0-15] */
#endif
#if defined(UNF_CPU_ENDIAN)
unsigned int n_port_end_to_end_credit : 15; /* 2 [0-14] */
unsigned int reserved_cl5 : 1; /* 2 [15] */
unsigned int concurrent_sequences : 16; /* 2 [16-31] */
#else
unsigned int concurrent_sequences : 16; /* 2 [16-31] */
unsigned int n_port_end_to_end_credit : 15; /* 2 [0-14] */
unsigned int reserved_cl5 : 1; /* 2 [15] */
#endif
#if defined(UNF_CPU_ENDIAN)
unsigned int reserved_cl6 : 16; /* 3 [0-15] */
unsigned int open_sequences_per_exchange : 16; /* 3 [16-31] */
#else
unsigned int open_sequences_per_exchange : 16; /* 3 [16-31] */
unsigned int reserved_cl6 : 16; /* 3 [0-15] */
#endif
};
struct unf_fabric_parms_s {
struct unf_fabric_coparms_s co_parms;
unsigned int high_port_name;
unsigned int low_port_name;
unsigned int high_node_name;
unsigned int low_node_name;
struct unf_lgn_port_clparms_s cl_parms[3];
unsigned int reserved_1[4];
unsigned int vendor_version_level[4];
};
struct unf_lgn_parms_s {
struct unf_lgn_port_coparms_s co_parms;
unsigned int high_port_name;
unsigned int low_port_name;
unsigned int high_node_name;
unsigned int low_node_name;
struct unf_lgn_port_clparms_s cl_parms[3];
unsigned int reserved_1[4];
unsigned int vendor_version_level[4];
};
#define ELS_RJT 0x1
#define ELS_ACC 0x2
#define ELS_PLOGI 0x3
#define ELS_FLOGI 0x4
#define ELS_LOGO 0x5
#define ELS_RLS 0xf
#define ELS_ECHO 0x10
#define ELS_RRQ 0x12
#define ELS_REC 0x13
#define ELS_PRLI 0x20
#define ELS_PRLO 0x21
#define ELS_TPRLO 0x24
#define ELS_PDISC 0x50
#define ELS_FDISC 0x51
#define ELS_ADISC 0x52
#define ELS_RSCN 0x61 /* registered state change notification */
#define ELS_SCR 0x62 /* state change registration */
#define NS_GIEL 0X0101
#define NS_GA_NXT 0X0100
#define NS_GPN_ID 0x0112 /* get port name by ID */
#define NS_GNN_ID 0x0113 /* get node name by ID */
#define NS_GFF_ID 0x011f /* get FC-4 features by ID */
#define NS_GID_PN 0x0121 /* get ID for port name */
#define NS_GID_NN 0x0131 /* get IDs for node name */
#define NS_GID_FT 0x0171 /* get IDs by FC4 type */
#define NS_GPN_FT 0x0172 /* get port names by FC4 type */
#define NS_GID_PT 0x01a1 /* get IDs by port type */
#define NS_RFT_ID 0x0217 /* reg FC4 type for ID */
#define NS_RPN_ID 0x0212 /* reg port name for ID */
#define NS_RNN_ID 0x0213 /* reg node name for ID */
#define NS_RSNPN 0x0218 /* reg symbolic port name */
#define NS_RFF_ID 0x021f /* reg FC4 Features for ID */
#define NS_RSNN 0x0239 /* reg symbolic node name */
#define ST_NULL 0xffff /* reg symbolic node name */
#define BLS_ABTS 0xA001 /* ABTS */
#define FCP_SRR 0x14 /* Sequence Retransmission Request */
#define UNF_FC_FID_DOM_MGR 0xfffc00 /* domain manager base */
enum unf_fc_well_known_fabric_id {
UNF_FC_FID_NONE = 0x000000, /* No destination */
UNF_FC_FID_DOM_CTRL = 0xfffc01, /* domain controller */
UNF_FC_FID_BCAST = 0xffffff, /* broadcast */
UNF_FC_FID_FLOGI = 0xfffffe, /* fabric login */
UNF_FC_FID_FCTRL = 0xfffffd, /* fabric controller */
UNF_FC_FID_DIR_SERV = 0xfffffc, /* directory server */
UNF_FC_FID_TIME_SERV = 0xfffffb, /* time server */
UNF_FC_FID_MGMT_SERV = 0xfffffa, /* management server */
UNF_FC_FID_QOS = 0xfffff9, /* QoS Facilitator */
UNF_FC_FID_ALIASES = 0xfffff8, /* alias server (FC-PH2) */
UNF_FC_FID_SEC_KEY = 0xfffff7, /* Security key dist. server */
UNF_FC_FID_CLOCK = 0xfffff6, /* clock synch server */
UNF_FC_FID_MCAST_SERV = 0xfffff5 /* multicast server */
};
#define DRV_ENTRY_PER_SGL 64 /* Size of an entry array in a hash table */
#define DRV_DATA_PROTECTION_LEN 8
struct dif_result_info_s {
unsigned char actual_dif[DRV_DATA_PROTECTION_LEN];
unsigned char expected_dif[DRV_DATA_PROTECTION_LEN];
};
struct drv_sge {
char *buf;
void *page_ctrl;
unsigned int length;
unsigned int offset;
};
/*
* @enum drv_io_direction
* SCSI data direction
*/
enum drv_io_direction {
DRV_IO_BIDIRECTIONAL = 0,
DRV_IO_DIRECTION_WRITE = 1,
DRV_IO_DIRECTION_READ = 2,
DRV_IO_DIRECTION_NONE = 3,
};
/*
* Hash table data structure
*/
struct drv_sgl {
struct drv_sgl *next_sgl; /* poin to SGL,SGL list */
unsigned short num_sges_in_chain;
unsigned short num_sges_in_sgl;
unsigned int flag;
unsigned long long serial_num;
struct drv_sge sge[DRV_ENTRY_PER_SGL];
struct list_head node;
unsigned int cpu_id;
};
struct dif_info_s {
/* Indicates the result returned when the data
* protection information is inconsistent,add by pangea
*/
struct dif_result_info_s dif_result;
/* Data protection information operation code
* bit[31-24] other operation code
* bit[23-16] Data Protection Information Operation
* bit[15-8] Data protection information verification
* bit[7-0] Data protection information replace
*/
unsigned int protect_opcode;
unsigned short app_tag;
unsigned long long start_lba; /* IO start LBA */
struct drv_sgl *protection_sgl;
};
typedef struct Scsi_Host unf_scsi_host_s;
struct unf_ini_error_code_s {
unsigned int drv_err_code; /* driver error code */
unsigned int ap_err_code; /* up level error code */
};
typedef unsigned int (*ini_get_sgl_entry_buf)(void *v_upper_cmnd,
void *v_driver_sgl,
void **v_upper_sgl,
unsigned int *v_req_index,
unsigned int *v_index,
char **v_buf,
unsigned int *v_buf_len);
struct unf_host_param_s {
int can_queue;
unsigned short sg_table_size;
short cmnd_per_lun;
unsigned int max_id;
unsigned int max_lun;
unsigned int max_channel;
unsigned short max_cmnd_len;
unsigned short max_sectors;
unsigned long long dma_boundary;
unsigned int port_id;
void *lport;
struct device *pdev;
};
#define UNF_DIF_AREA_SIZE 8
struct unf_dif_control_info_s {
unsigned short app_tag;
unsigned short flags;
unsigned int protect_opcode;
unsigned int fcp_dl;
unsigned int start_lba;
unsigned char actual_dif[UNF_DIF_AREA_SIZE];
unsigned char expected_dif[UNF_DIF_AREA_SIZE];
unsigned int dif_sge_count;
void *dif_sgl;
};
struct unf_scsi_cmd_s {
unsigned int scsi_host_id;
unsigned int scsi_id; /* cmd->dev->id */
unsigned long long lun_id;
unsigned long long port_id;
unsigned int underflow; /* Underflow */
unsigned int transfer_len; /* Transfer Length */
unsigned int resid; /* Resid */
unsigned int sense_buf_len;
int result;
unsigned int entry_count; /* IO Buffer counter */
unsigned int abort;
unsigned int err_code_table_cout; /* error code size */
unsigned long long cmnd_sn;
unsigned long time_out; /* EPL driver add timer */
unsigned short cmnd_len; /* Cdb length */
unsigned char data_direction; /* data direction */
unsigned char *pcmnd; /* SCSI CDB */
unsigned char *sense_buf;
void *drv_private; /* driver host pionter */
void *driver_scribble; /* Xchg pionter */
void *upper_cmnd; /* UpperCmnd pointer by driver */
unsigned char *pc_lun_id; /* new lunid */
unsigned int world_id;
struct unf_dif_control_info_s dif_control; /* DIF control */
struct unf_ini_error_code_s *err_code_table; /* error code table */
void *sgl; /* Sgl pointer */
ini_get_sgl_entry_buf pfn_unf_ini_get_sgl_entry;
void (*pfn_done)(struct unf_scsi_cmd_s *);
struct dif_info_s dif_info;
};
/*
* R_CTL Basic Link Data defines
*/
#define FC_RCTL_BLS 0x80000000
#define FC_RCTL_BLS_ACC (FC_RCTL_BLS | 0x04000000)
#define FC_RCTL_BLS_RJT (FC_RCTL_BLS | 0x05000000)
/*
* BA_RJT reason code defines
*/
#define FCXLS_BA_OK 0x00000000
#define FCXLS_BA_RJT_INVALID_COMMAND 0x00010000
#define FCXLS_BA_RJT_LOGICAL_ERROR 0x00030000
/*
* BA_RJT code explanation
*/
#define FCXLS_BA_RJT_INV_OXID_RXID 0x00000300
#define FCXLS_LS_RJT_INVALID_OXID_RXID 0x00001700
/*
* Types (word)
*/
#define FC_TYPE_WORD_BLS 0x00000000
/*
* SFS structures
*/
struct unf_ba_rjt_s {
unsigned int reason_code; /* BLS reason code and Reason Explanation */
};
#define FC_ABTS_ACC_SEQ_CNT 0x0000ffff
struct unf_ba_acc_s {
unsigned int seq_id;
unsigned int oxid_rxid;
unsigned int seq_cnt;
};
union unf_ba_pld_u {
struct unf_ba_rjt_s ba_rjt;
struct unf_ba_acc_s ba_acc;
};
struct unf_abts_rsps_s {
struct unf_fchead_s frame_hdr;
union unf_ba_pld_u ba_pld;
};
/*
* BLS RJT structure header and payload
*/
struct unf_bls_rjt_s {
struct unf_fchead_s frame_hdr;
/* BLS reason code and Reason Explanation */
unsigned int reason_code;
};
/*
* ELS ACC
*/
struct unf_els_acc_s {
struct unf_fchead_s frame_hdr;
unsigned int cmnd;
};
/*
* ELS RJT
*/
struct unf_els_rjt_s {
struct unf_fchead_s frame_hdr;
unsigned int cmnd;
unsigned int reason_code;
};
/*
* FLOGI payload,
* FC-LS-2 Table 139 FLOGI, PLOGI, FDISC or LS_ACC Payload
*/
struct unf_flogi_payload_s {
unsigned int cmnd;
struct unf_fabric_parms_s fabric_parms;
};
/*
* Flogi and Flogi accept frames. They are the same structure
*/
struct unf_flogi_fdisc_acc_s {
struct unf_fchead_s frame_hdr;
struct unf_flogi_payload_s flogi_payload;
};
/*
* Fdisc and Fdisc accept frames. They are the same structure
*/
struct unf_fdisc_acc_s {
struct unf_fchead_s frame_hdr;
struct unf_flogi_payload_s fdisc_payload;
};
/*
* PLOGI payload
*/
struct unf_plogi_payload_s {
unsigned int cmnd;
struct unf_lgn_parms_s parms;
};
/*
* Plogi, Plogi accept, Pdisc and Pdisc accept frames.
* They are all the same structure.
*/
struct unf_plogi_pdisc_s {
struct unf_fchead_s frame_hdr;
struct unf_plogi_payload_s payload;
};
/*
* LOGO logout link service requests invalidation of service parameters and
* port name.
* see FC-PH 4.3 Section 21.4.8
*/
/* FC-LS-2 Table 12 LOGO Payload */
struct unf_logo_payload_s {
unsigned int cmnd;
unsigned int nport_id;
unsigned int high_port_name;
unsigned int low_port_name;
};
/*
* payload to hold LOGO command
*/
struct unf_logo_s {
struct unf_fchead_s frame_hdr;
struct unf_logo_payload_s payload;
};
/*
* payload for ECHO command, refer to FC-LS-2 4.2.4
*/
struct unf_echo_payload_s {
unsigned int cmnd;
#define UNF_FC_ECHO_PAYLOAD_LENGTH 255 /* Length in words */
unsigned int data[UNF_FC_ECHO_PAYLOAD_LENGTH];
};
struct unf_echo_s {
struct unf_fchead_s frame_hdr;
struct unf_echo_payload_s *echo_pld;
dma_addr_t phy_echo_addr;
};
#define UNF_PRLI_SIRT_EXTRA_SIZE 12
/*
* payload for PRLI and PRLO
*/
struct unf_pril_payload_s {
unsigned int cmnd;
#define UNF_FC_PRLI_PAYLOAD_LENGTH 7 /* Length in words */
unsigned int parms[UNF_FC_PRLI_PAYLOAD_LENGTH];
};
/*
* FCHS structure with payload
*/
struct unf_prli_prlo_s {
struct unf_fchead_s frame_hdr;
struct unf_pril_payload_s payload;
};
/*
* ADISC payload
*/
/* FC-LS-2 Table 75 ADISC Request payload */
struct unf_adisc_payload_s {
unsigned int cmnd;
unsigned int hard_address;
unsigned int high_port_name;
unsigned int low_port_name;
unsigned int high_node_name;
unsigned int low_node_name;
unsigned int nport_id;
};
/*
* FCHS structure with payload
*/
struct unf_adisc_s {
/* FCHS structure */
struct unf_fchead_s frame_hdr;
/* Payload data containing ADISC info */
struct unf_adisc_payload_s adisc_payl;
};
/*
* RLS payload
*/
struct unf_rls_payload_s {
unsigned int cmnd;
unsigned int nport_id; /* in litle endian format */
};
/*
* RLS
*/
struct unf_rls_s {
struct unf_fchead_s frame_hdr; /* FCHS structure */
/* payload data containing the RLS info */
struct unf_rls_payload_s rls;
};
/*
* RLS accept payload
*/
struct unf_rls_acc_payload_s {
unsigned int cmnd;
unsigned int link_failure_count;
unsigned int loss_of_sync_count;
unsigned int loss_of_signal_count;
unsigned int primitive_seq_count;
unsigned int invalid_trans_word_count;
unsigned int invalid_crc_count;
};
/*
* RLS accept
*/
struct unf_rls_acc_s {
struct unf_fchead_s frame_hdr; /* FCHS structure */
/* payload data containing the RLS ACC info */
struct unf_rls_acc_payload_s rls;
};
/*
* FCHS structure with payload
*/
struct unf_rrq_s {
struct unf_fchead_s frame_hdr;
unsigned int cmnd;
unsigned int sid;
unsigned int oxid_rxid;
};
/*
* ABTA accept
*/
struct unf_abts_acc_s {
struct unf_fchead_s frame_hdr;
unsigned int seq_id;
unsigned int oxid_rxid;
unsigned int seq_cnt;
};
struct unf_scr_s {
struct unf_fchead_s frame_hdr;
unsigned int payload[2];
};
struct unf_ctiu_prem_s {
unsigned int rev_inid;
unsigned int gstype_gssub_options;
unsigned int cmnd_rsp_size;
unsigned int frag_reason_exp_vend;
};
struct unf_rftid_s {
struct unf_fchead_s frame_hdr;
struct unf_ctiu_prem_s ctiu_pream;
unsigned int nport_id;
unsigned int fc_4_types[8];
};
struct unf_rffid_s {
struct unf_fchead_s frame_hdr;
struct unf_ctiu_prem_s ctiu_pream;
unsigned int nport_id;
unsigned int fc_4_feature;
};
struct unf_rffid_rsp_s {
struct unf_fchead_s frame_hdr;
struct unf_ctiu_prem_s ctiu_pream;
};
struct unf_gffid_s {
struct unf_fchead_s frame_hdr;
struct unf_ctiu_prem_s ctiu_pream;
unsigned int nport_id;
};
struct unf_gffid_rsp_s {
struct unf_fchead_s frame_hdr;
struct unf_ctiu_prem_s ctiu_pream;
unsigned int fc_4_feature[32];
};
struct unf_gnnid_s {
struct unf_fchead_s frame_hdr;
struct unf_ctiu_prem_s ctiu_pream;
unsigned int nport_id;
};
struct unf_gnnid_rsp_s {
struct unf_fchead_s frame_hdr;
struct unf_ctiu_prem_s ctiu_pream;
unsigned int node_name[2];
};
struct unf_gpnid_s {
struct unf_fchead_s frame_hdr;
struct unf_ctiu_prem_s ctiu_pream;
unsigned int nport_id;
};
struct unf_gpnid_rsp_s {
struct unf_fchead_s frame_hdr;
struct unf_ctiu_prem_s ctiu_pream;
unsigned int port_name[2];
};
struct unf_rft_rsp_s {
struct unf_fchead_s frame_hdr;
struct unf_ctiu_prem_s ctiu_pream;
};
struct unf_srr_payload_s {
unsigned int srr_op;
unsigned short rx_id;
unsigned short ox_id;
unsigned int rel_offset;
unsigned char reserved[3];
unsigned char rctl_for_iu;
};
struct unf_srr_s {
struct unf_fchead_s frame_hdr;
struct unf_srr_payload_s pld;
};
struct unf_srr_acc_pld_s {
unsigned int srr_op; /* 02000000h */
};
struct unf_srr_acc_s {
struct unf_fchead_s frame_hdr;
struct unf_srr_acc_pld_s pld;
};
struct unf_ls_rjt_pld_s {
unsigned int srr_op; /* 01000000h */
unsigned char vandor;
unsigned char reason_exp;
unsigned char reason;
unsigned char reserved;
};
struct unf_ls_rjt_s {
struct unf_fchead_s frame_hdr;
struct unf_ls_rjt_pld_s pld;
};
struct unf_rec_pld_s {
unsigned int rec_cmnd;
unsigned int xchg_org_sid; /* bit0-bit23 */
unsigned short rx_id;
unsigned short ox_id;
};
struct unf_rec_s {
struct unf_fchead_s frame_hdr;
struct unf_rec_pld_s rec_pld;
};
struct unf_rec_acc_pld_s {
unsigned int cmnd;
unsigned short rx_id;
unsigned short ox_id;
unsigned int org_addr_id; /* bit0-bit23 */
unsigned int rsp_addr_id; /* bit0-bit23 */
};
struct unf_rec_acc_s {
struct unf_fchead_s frame_hdr;
struct unf_rec_acc_pld_s payload;
};
struct unf_gid_s {
struct unf_ctiu_prem_s ctiu_pream;
unsigned int scope_type;
};
struct unf_gid_acc_s {
struct unf_fchead_s frame_hdr;
struct unf_ctiu_prem_s ctiu_pream;
};
#define UNF_LOOPMAP_COUNT 128
struct unf_loop_init_s {
struct unf_fchead_s frame_hdr;
unsigned int cmnd;
#define UNF_FC_ALPA_BIT_MAP_SIZE 4
unsigned int alpa_bit_map[UNF_FC_ALPA_BIT_MAP_SIZE];
};
struct unf_loop_map_s {
struct unf_fchead_s frame_hdr;
unsigned int cmnd;
unsigned int loop_map[32];
};
struct unf_ctiu_rjt_s {
struct unf_fchead_s frame_hdr;
struct unf_ctiu_prem_s ctiu_pream;
};
struct unf_gif_acc_pld_s {
struct unf_ctiu_prem_s ctiu_pream;
unsigned int gid_port_id[UNF_GID_PORT_CNT];
};
struct unf_gid_rsp_s {
struct unf_gif_acc_pld_s *gid_acc_pld;
};
struct unf_gid_req_rsp_s {
struct unf_fchead_s frame_hdr;
struct unf_gid_s gid_req;
struct unf_gid_rsp_s gid_rsp;
};
/* Added by fangtao FC-LS-2 Table 31 RSCN Payload */
struct unf_rscn_port_id_page_s {
unsigned char port_id_port;
unsigned char port_id_area;
unsigned char port_id_domain;
unsigned char addr_format : 2;
unsigned char event_qualifier : 4;
unsigned char reserved : 2;
};
struct unf_rscn_pld_s {
unsigned int cmnd;
struct unf_rscn_port_id_page_s port_id_page[UNF_RSCN_PAGE_SUM];
};
struct unf_rscn_s {
struct unf_fchead_s frame_hdr;
struct unf_rscn_pld_s *rscn_pld;
};
union unf_sfs_u {
struct {
struct unf_fchead_s frame_head;
unsigned char data[0];
} sfs_common;
struct unf_abts_rsps_s abts_rsps;
struct unf_els_acc_s els_acc;
struct unf_els_rjt_s els_rjt;
struct unf_plogi_pdisc_s plogi;
struct unf_logo_s logo;
struct unf_echo_s echo;
struct unf_echo_s echo_acc;
struct unf_prli_prlo_s prli;
struct unf_prli_prlo_s prlo;
struct unf_rls_s rls;
struct unf_rls_acc_s rls_acc;
struct unf_plogi_pdisc_s pdisc;
struct unf_adisc_s adisc;
struct unf_rrq_s rrq;
struct unf_flogi_fdisc_acc_s flogi;
struct unf_fdisc_acc_s fdisc;
struct unf_scr_s scr;
struct unf_rec_s rec;
struct unf_rec_acc_s rec_acc;
struct unf_srr_s srr;
struct unf_srr_acc_s srr_acc;
struct unf_ls_rjt_s ls_rjt;
struct unf_rscn_s rscn;
struct unf_gid_req_rsp_s get_id;
struct unf_rftid_s rft_id;
struct unf_rft_rsp_s rft_id_rsp;
struct unf_rffid_s rff_id;
struct unf_rffid_rsp_s rff_id_rsp;
struct unf_gffid_s gff_id;
struct unf_gffid_rsp_s gff_id_rsp;
struct unf_gnnid_s gnn_id;
struct unf_gnnid_rsp_s gnn_id_rsp;
struct unf_gpnid_s gpn_id;
struct unf_gpnid_rsp_s gpn_id_rsp;
struct unf_plogi_pdisc_s plogi_acc;
struct unf_plogi_pdisc_s pdisc_acc;
struct unf_adisc_s adisc_acc;
struct unf_prli_prlo_s prli_acc;
struct unf_prli_prlo_s prlo_acc;
struct unf_flogi_fdisc_acc_s flogi_acc;
struct unf_fdisc_acc_s fdisc_acc;
struct unf_loop_init_s lpi;
struct unf_loop_map_s loopmap;
struct unf_ctiu_rjt_s ctiu_rjt;
};
struct unf_sfs_entry_s {
/* Virtual addr of SFS buffer */
union unf_sfs_u *fc_sfs_entry_ptr;
/* Physical addr of SFS buffer */
unsigned long long sfs_buff_phy_addr;
/* Length of bytes in SFS buffer */
unsigned int sfs_buff_len;
unsigned int cur_offset;
};
struct unf_fcp_rsp_iu_entry_s {
struct unf_fcprsp_iu_s *fcp_rsp_iu;
dma_addr_t fcp_rsp_iu_phy_addr;
};
struct unf_rjt_info_s {
unsigned int els_cmnd_code;
unsigned int reason_code;
unsigned int reason_explanation;
};
int unf_alloc_scsi_host(unf_scsi_host_s **v_scsi_host,
struct unf_host_param_s *v_host_param);
void unf_free_scsi_host(unf_scsi_host_s *v_scsi_host);
unsigned int unf_register_ini_transport(void);
void unf_unregister_ini_transport(void);
void unf_report_io_dm_event(void *v_lport, unsigned int type,
unsigned int value);
void unf_save_sense_data(void *scsicmd, const char *sense, int senslen);
#endif
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册