提交 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 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
此差异已折叠。
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册